From 056fc916b20459b2954fff78f3f99b2df7f11950 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Tue, 27 Jan 2009 02:08:48 +0400 Subject: Use Diseqc 3/3 mode to send data From: Sigmund Augdal Signed-off-by: Sigmund Augdal Signed-off-by: Manu Abraham --- linux/drivers/media/dvb/frontends/stb0899_drv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/frontends/stb0899_drv.c b/linux/drivers/media/dvb/frontends/stb0899_drv.c index 1e38abee5..32841ade0 100644 --- a/linux/drivers/media/dvb/frontends/stb0899_drv.c +++ b/linux/drivers/media/dvb/frontends/stb0899_drv.c @@ -794,7 +794,7 @@ static int stb0899_send_diseqc_burst(struct dvb_frontend *fe, fe_sec_mini_cmd_t reg = stb0899_read_reg(state, STB0899_DISCNTRL1); old_state = reg; /* set to burst mode */ - STB0899_SETFIELD_VAL(DISEQCMODE, reg, 0x02); + STB0899_SETFIELD_VAL(DISEQCMODE, reg, 0x03); STB0899_SETFIELD_VAL(DISPRECHARGE, reg, 0x01); stb0899_write_reg(state, STB0899_DISCNTRL1, reg); switch (burst) { -- cgit v1.2.3 From a4d14c1b200f333fb3b27517bd31d7f31445dbf8 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Tue, 27 Jan 2009 18:03:16 +0400 Subject: Bug: Use signed types, Offsets and range can be negative Code simplification: use in kernel macros From: Manu Abraham Signed-off-by: Manu Abraham --- linux/drivers/media/dvb/frontends/stb0899_algo.c | 14 +++++++------- linux/drivers/media/dvb/frontends/stb0899_priv.h | 12 ++++-------- 2 files changed, 11 insertions(+), 15 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/frontends/stb0899_algo.c b/linux/drivers/media/dvb/frontends/stb0899_algo.c index 3d13968a7..72012ce11 100644 --- a/linux/drivers/media/dvb/frontends/stb0899_algo.c +++ b/linux/drivers/media/dvb/frontends/stb0899_algo.c @@ -156,7 +156,7 @@ static void stb0899_first_subrange(struct stb0899_state *state) } if (range > 0) - internal->sub_range = MIN(internal->srch_range, range); + internal->sub_range = min(internal->srch_range, range); else internal->sub_range = 0; @@ -185,7 +185,7 @@ static enum stb0899_status stb0899_check_tmg(struct stb0899_state *state) timing = stb0899_read_reg(state, STB0899_RTF); if (lock >= 42) { - if ((lock > 48) && (ABS(timing) >= 110)) { + if ((lock > 48) && (abs(timing) >= 110)) { internal->status = ANALOGCARRIER; dprintk(state->verbose, FE_DEBUG, 1, "-->ANALOG Carrier !"); } else { @@ -222,7 +222,7 @@ static enum stb0899_status stb0899_search_tmg(struct stb0899_state *state) index++; derot_freq += index * internal->direction * derot_step; /* next derot zig zag position */ - if (ABS(derot_freq) > derot_limit) + if (abs(derot_freq) > derot_limit) next_loop--; if (next_loop) { @@ -298,7 +298,7 @@ static enum stb0899_status stb0899_search_carrier(struct stb0899_state *state) last_derot_freq = derot_freq; derot_freq += index * internal->direction * internal->derot_step; /* next zig zag derotator position */ - if(ABS(derot_freq) > derot_limit) + if(abs(derot_freq) > derot_limit) next_loop--; if (next_loop) { @@ -400,7 +400,7 @@ static enum stb0899_status stb0899_search_data(struct stb0899_state *state) if ((internal->status != CARRIEROK) || (stb0899_check_data(state) != DATAOK)) { derot_freq += index * internal->direction * derot_step; /* next zig zag derotator position */ - if (ABS(derot_freq) > derot_limit) + if (abs(derot_freq) > derot_limit) next_loop--; if (next_loop) { @@ -467,7 +467,7 @@ static void next_sub_range(struct stb0899_state *state) if (internal->sub_dir > 0) { old_sub_range = internal->sub_range; - internal->sub_range = MIN((internal->srch_range / 2) - + internal->sub_range = min((internal->srch_range / 2) - (internal->tuner_offst + internal->sub_range / 2), internal->sub_range); @@ -771,7 +771,7 @@ static long Log2Int(int number) int i; i = 0; - while ((1 << i) <= ABS(number)) + while ((1 << i) <= abs(number)) i++; if (number == 0) diff --git a/linux/drivers/media/dvb/frontends/stb0899_priv.h b/linux/drivers/media/dvb/frontends/stb0899_priv.h index e57ff227b..d2a69d0a3 100644 --- a/linux/drivers/media/dvb/frontends/stb0899_priv.h +++ b/linux/drivers/media/dvb/frontends/stb0899_priv.h @@ -59,10 +59,6 @@ #define MAKEWORD32(a, b, c, d) (((a) << 24) | ((b) << 16) | ((c) << 8) | (d)) #define MAKEWORD16(a, b) (((a) << 8) | (b)) -#define MIN(x, y) ((x) <= (y) ? (x) : (y)) -#define MAX(x, y) ((x) >= (y) ? (x) : (y)) -#define ABS(x) ((x) >= 0 ? (x) : -(x)) - #define LSB(x) ((x & 0xff)) #define MSB(y) ((y >> 8) & 0xff) @@ -168,10 +164,10 @@ struct stb0899_internal { u32 freq; /* Demod internal Frequency */ u32 srate; /* Demod internal Symbol rate */ enum stb0899_fec fecrate; /* Demod internal FEC rate */ - u32 srch_range; /* Demod internal Search Range */ - u32 sub_range; /* Demod current sub range (Hz) */ - u32 tuner_step; /* Tuner step (Hz) */ - u32 tuner_offst; /* Relative offset to carrier (Hz) */ + s32 srch_range; /* Demod internal Search Range */ + s32 sub_range; /* Demod current sub range (Hz) */ + s32 tuner_step; /* Tuner step (Hz) */ + s32 tuner_offst; /* Relative offset to carrier (Hz) */ u32 tuner_bw; /* Current bandwidth of the tuner (Hz) */ s32 mclk; /* Masterclock Divider factor (binary) */ -- cgit v1.2.3 From b7deb66fda3accee36c079e200d1773c5e0fcc67 Mon Sep 17 00:00:00 2001 From: "Igor M. Liplianin" Date: Sun, 9 Nov 2008 16:35:13 +0200 Subject: Bug fix: For legacy applications stv0899 performs search only first time after insmod. From: Igor M. Liplianin For legacy applications stv0899 performs search only first time after insmod due to not set DVBFE_ALGO_SEARCH_AGAIN bit Signed-off-by: Igor M. Liplianin Signed-off-by: Manu Abraham --- linux/drivers/media/dvb/dvb-core/dvb_frontend.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (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 01a9ceb37..60a9c80a1 100644 --- a/linux/drivers/media/dvb/dvb-core/dvb_frontend.c +++ b/linux/drivers/media/dvb/dvb-core/dvb_frontend.c @@ -1396,9 +1396,6 @@ static int dtv_property_process_set(struct dvb_frontend *fe, dprintk("%s() Finalised property cache\n", __func__); dtv_property_cache_submit(fe); - /* Request the search algorithm to search */ - fepriv->algo_status |= DVBFE_ALGO_SEARCH_AGAIN; - r |= dvb_frontend_ioctl_legacy(inode, file, FE_SET_FRONTEND, &fepriv->parameters); break; @@ -1832,6 +1829,10 @@ static int dvb_frontend_ioctl_legacy(struct inode *inode, struct file *file, fepriv->min_delay = (dvb_override_tune_delay * HZ) / 1000; fepriv->state = FESTATE_RETUNE; + + /* Request the search algorithm to search */ + fepriv->algo_status |= DVBFE_ALGO_SEARCH_AGAIN; + dvb_frontend_wakeup(fe); dvb_frontend_add_event(fe, 0); fepriv->status = 0; -- cgit v1.2.3 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 497b92000f676ccf6af25a05c9efdade20379135 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Thu, 26 Mar 2009 10:03:28 +0100 Subject: gspca - vc032x: Remove the JPEG tables of mi1320_soc. From: Jean-Francois Moine Priority: normal Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/vc032x.c | 32 ++++++++++++++++++++------------ 1 file changed, 20 insertions(+), 12 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/vc032x.c b/linux/drivers/media/video/gspca/vc032x.c index 772d18e70..b5026a2d1 100644 --- a/linux/drivers/media/video/gspca/vc032x.c +++ b/linux/drivers/media/video/gspca/vc032x.c @@ -159,37 +159,37 @@ static const struct v4l2_pix_format vc0323_mode[] = { .priv = 2}, }; static const struct v4l2_pix_format bi_mode[] = { -/*fixme: jeg does not work +#if 0 /* JPEG vc0323 */ {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, .bytesperline = 320, .sizeimage = 320 * 240 * 3 / 8 + 590, .colorspace = V4L2_COLORSPACE_JPEG, .priv = 5}, -*/ +#endif {320, 240, V4L2_PIX_FMT_YVYU, V4L2_FIELD_NONE, .bytesperline = 320, .sizeimage = 320 * 240 * 2, .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 4}, -/* + .priv = 2}, +#if 0 /* JPEG vc0323 */ {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, .bytesperline = 640, .sizeimage = 640 * 480 * 3 / 8 + 590, .colorspace = V4L2_COLORSPACE_JPEG, - .priv = 3}, -*/ + .priv = 4}, +#endif {640, 480, V4L2_PIX_FMT_YVYU, V4L2_FIELD_NONE, .bytesperline = 640, .sizeimage = 640 * 480 * 2, .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 2}, -/* + .priv = 1}, +#if 0 /* JPEG vc0323 */ {1280, 1024, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, .bytesperline = 1280, .sizeimage = 1280 * 1024 * 1 / 4 + 590, .colorspace = V4L2_COLORSPACE_JPEG, - .priv = 1}, -*/ + .priv = 3}, +#endif {1280, 1024, V4L2_PIX_FMT_YVYU, V4L2_FIELD_NONE, .bytesperline = 1280, .sizeimage = 1280 * 1024 * 2, @@ -1034,6 +1034,7 @@ static const u8 mi1320_soc_InitVGA[][4] = { {0xb3, 0x5c, 0x01, 0xcc}, {} }; +#if 0 /* JPEG vc0323 */ static const u8 mi1320_soc_InitVGA_JPG[][4] = { {0xb3, 0x01, 0x01, 0xcc}, {0xb0, 0x03, 0x19, 0xcc}, @@ -1149,6 +1150,7 @@ static const u8 mi1320_soc_InitVGA_JPG[][4] = { {0xb3, 0x5c, 0x01, 0xcc}, {} }; +#endif static const u8 mi1320_soc_InitQVGA[][4] = { {0xb3, 0x01, 0x01, 0xcc}, {0xb0, 0x03, 0x19, 0xcc}, @@ -1262,6 +1264,7 @@ static const u8 mi1320_soc_InitQVGA[][4] = { {0xb3, 0x5c, 0x01, 0xcc}, {} }; +#if 0 /* JPEG vc0323 */ static const u8 mi1320_soc_InitQVGA_JPG[][4] = { {0xb3, 0x01, 0x01, 0xcc}, {0xb0, 0x03, 0x19, 0xcc}, @@ -1387,6 +1390,8 @@ static const u8 mi1320_soc_InitQVGA_JPG[][4] = { {0xb3, 0x5c, 0x01, 0xcc}, {} }; +#endif +#if 0 /* JPEG vc0323 */ static const u8 mi1320_soc_InitSXGA_JPG[][4] = { {0xb3, 0x01, 0x01, 0xcc}, {0xb0, 0x03, 0x19, 0xcc}, @@ -1524,6 +1529,7 @@ static const u8 mi1320_soc_InitSXGA_JPG[][4] = { {0x2f, 0x90, 0x00, 0xbb}, {} }; +#endif static const u8 mi1320_soc_InitSXGA[][4] = { {0xb3, 0x01, 0x01, 0xcc}, {0xb0, 0x03, 0x19, 0xcc}, @@ -3066,11 +3072,13 @@ static int sd_start(struct gspca_dev *gspca_dev) int mode; static const u8 (*mi1320_soc_init[])[4] = { mi1320_soc_InitSXGA, - mi1320_soc_InitSXGA_JPG, mi1320_soc_InitVGA, - mi1320_soc_InitVGA_JPG, mi1320_soc_InitQVGA, +#if 0 /* JPEG vc0323 */ + mi1320_soc_InitSXGA_JPG, + mi1320_soc_InitVGA_JPG, mi1320_soc_InitQVGA_JPG +#endif }; /* Assume start use the good resolution from gspca_dev->mode */ -- cgit v1.2.3 From f4ad67ca7e19beab57c395b8317f232399534ee0 Mon Sep 17 00:00:00 2001 From: Erik Andr?n Date: Fri, 26 Dec 2008 15:56:43 +0100 Subject: gspca - m5602-s5k4aa: No more "default" mode From: Erik Andr?n Priority: normal Signed-off-by: Erik Andr?n --- linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.h b/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.h index 1f88b0d04..2f3af9503 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.h @@ -143,13 +143,13 @@ static struct m5602_sensor s5k4aa = { .nmodes = 1, .modes = { { - M5602_DEFAULT_FRAME_WIDTH, - M5602_DEFAULT_FRAME_HEIGHT, + 640, + 480, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, .sizeimage = - M5602_DEFAULT_FRAME_WIDTH * M5602_DEFAULT_FRAME_HEIGHT, - .bytesperline = M5602_DEFAULT_FRAME_WIDTH, + 640 * 480, + .bytesperline = 640, .colorspace = V4L2_COLORSPACE_SRGB, .priv = 1 } -- cgit v1.2.3 From cc99e0915696cc281889cbff60b3693074c0a105 Mon Sep 17 00:00:00 2001 From: Erik Andr?n Date: Fri, 26 Dec 2008 16:57:42 +0100 Subject: gspca - m5602-s5k4aa: Add start function and VGA resolution init. From: Erik Andr?n Priority: normal Signed-off-by: Erik Andr?n --- .../drivers/media/video/gspca/m5602/m5602_s5k4aa.c | 43 +++++++++++++++ .../drivers/media/video/gspca/m5602/m5602_s5k4aa.h | 61 ++++++++++++++++++++++ 2 files changed, 104 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c b/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c index 7e79f7eca..8e5f2cb05 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c @@ -125,6 +125,49 @@ sensor_found: return 0; } +int s5k4aa_start(struct sd *sd) +{ + int i, err = 0; + u8 data[2]; + struct cam *cam = &sd->gspca_dev.cam; + + switch (cam->cam_mode[sd->gspca_dev.curr_mode].width) + { + case 640: + PDEBUG(D_V4L2, "Configuring camera for VGA mode"); + + for (i = 0; i < ARRAY_SIZE(VGA_s5k4aa); i++) { + switch (VGA_s5k4aa[i][0]) { + case BRIDGE: + err = m5602_write_bridge(sd, + VGA_s5k4aa[i][1], + VGA_s5k4aa[i][2]); + break; + + case SENSOR: + data[0] = VGA_s5k4aa[i][2]; + err = m5602_write_sensor(sd, + VGA_s5k4aa[i][1], + data, 1); + break; + + case SENSOR_LONG: + data[0] = VGA_s5k4aa[i][2]; + data[1] = VGA_s5k4aa[i][3]; + err = m5602_write_sensor(sd, + VGA_s5k4aa[i][1], + data, 2); + break; + + default: + err("Invalid stream command, exiting init"); + return -EINVAL; + } + } + } + return err; +} + int s5k4aa_init(struct sd *sd) { int i, err = 0; diff --git a/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.h b/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.h index 2f3af9503..0c08ccffc 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.h @@ -65,6 +65,7 @@ extern int dump_sensor; int s5k4aa_probe(struct sd *sd); int s5k4aa_init(struct sd *sd); +int s5k4aa_start(struct sd *sd); int s5k4aa_power_down(struct sd *sd); int s5k4aa_get_exposure(struct gspca_dev *gspca_dev, __s32 *val); @@ -80,6 +81,7 @@ static struct m5602_sensor s5k4aa = { .name = "S5K4AA", .probe = s5k4aa_probe, .init = s5k4aa_init, + .start = s5k4aa_start, .power_down = s5k4aa_power_down, .i2c_slave_id = 0x5a, .i2c_regW = 2, @@ -329,4 +331,63 @@ static const unsigned char init_s5k4aa[][4] = {SENSOR, S5K4AA_GAIN_2, 0xa0, 0x00} }; +static const unsigned char VGA_s5k4aa[][4] = +{ + {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06, 0x00}, + {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, + {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00}, + {BRIDGE, M5602_XB_SENSOR_TYPE, 0x08, 0x00}, + {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81, 0x00}, + {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82, 0x00}, + {BRIDGE, M5602_XB_SIG_INI, 0x01, 0x00}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, + /* VSYNC_PARA, VSYNC_PARA : img height 480 = 0x01e0 */ + {BRIDGE, M5602_XB_VSYNC_PARA, 0x01, 0x00}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0xe0, 0x00}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, + {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00}, + {BRIDGE, M5602_XB_SIG_INI, 0x02, 0x00}, + {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00}, + {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00}, + /* HSYNC_PARA, HSYNC_PARA : img width 640 = 0x0280 */ + {BRIDGE, M5602_XB_HSYNC_PARA, 0x02, 0x00}, + {BRIDGE, M5602_XB_HSYNC_PARA, 0x80, 0x00}, + {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00}, + {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, + {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xa0, 0x00}, /* 48 MHz */ + + {SENSOR, S5K4AA_PAGE_MAP, 0x02, 0x00}, + {SENSOR, S5K4AA_READ_MODE, S5K4AA_RM_H_FLIP | S5K4AA_RM_ROW_SKIP_2X + | S5K4AA_RM_COL_SKIP_2X, 0x00}, + /* 0x37 : Fix image stability when light is too bright and improves + * image quality in 640x480, but worsens it in 1280x1024 */ + {SENSOR, 0x37, 0x01, 0x00}, + /* ROWSTART_HI, ROWSTART_LO : 10 + (1024-960)/2 = 42 = 0x002a */ + {SENSOR, S5K4AA_ROWSTART_HI, 0x00, 0x00}, + {SENSOR, S5K4AA_ROWSTART_LO, 0x2a, 0x00}, + {SENSOR, S5K4AA_COLSTART_HI, 0x00, 0x00}, + {SENSOR, S5K4AA_COLSTART_LO, 0x0c, 0x00}, + /* window_height_hi, window_height_lo : 960 = 0x03c0 */ + {SENSOR, S5K4AA_WINDOW_HEIGHT_HI, 0x03, 0x00}, + {SENSOR, S5K4AA_WINDOW_HEIGHT_LO, 0xc0, 0x00}, + /* window_width_hi, window_width_lo : 1280 = 0x0500 */ + {SENSOR, S5K4AA_WINDOW_WIDTH_HI, 0x05, 0x00}, + {SENSOR, S5K4AA_WINDOW_WIDTH_LO, 0x00, 0x00}, + {SENSOR, S5K4AA_H_BLANK_HI__, 0x00, 0x00}, + {SENSOR, S5K4AA_H_BLANK_LO__, 0xa8, 0x00}, /* helps to sync... */ + {SENSOR, S5K4AA_EXPOSURE_HI, 0x01, 0x00}, + {SENSOR, S5K4AA_EXPOSURE_LO, 0x00, 0x00}, + {SENSOR, 0x11, 0x04, 0x00}, + {SENSOR, 0x12, 0xc3, 0x00}, + {SENSOR, S5K4AA_PAGE_MAP, 0x02, 0x00}, + {SENSOR, 0x02, 0x0e, 0x00}, + {SENSOR_LONG, S5K4AA_GLOBAL_GAIN__, 0x0f, 0x00}, + {SENSOR, S5K4AA_GAIN_1, 0x0b, 0x00}, + {SENSOR, S5K4AA_GAIN_2, 0xa0, 0x00} +}; + #endif -- cgit v1.2.3 From 9bb669dba4b0c284e2aefe88babb1649a7b12c84 Mon Sep 17 00:00:00 2001 From: Erik Andr?n Date: Sat, 27 Dec 2008 16:28:00 +0100 Subject: gspca - m5602: Simplify error handling From: Erik Andr?n Simplfy error handling by replacing goto statements with return equivalents. Priority: normal Signed-off-by: Erik Andr?n --- linux/drivers/media/video/gspca/m5602/m5602_core.c | 13 +++--- .../media/video/gspca/m5602/m5602_mt9m111.c | 14 +++--- .../drivers/media/video/gspca/m5602/m5602_ov9650.c | 38 ++++++++-------- .../drivers/media/video/gspca/m5602/m5602_po1030.c | 13 +++--- .../drivers/media/video/gspca/m5602/m5602_s5k4aa.c | 51 ++++++++++------------ .../drivers/media/video/gspca/m5602/m5602_s5k83a.c | 35 ++++++--------- 6 files changed, 73 insertions(+), 91 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/m5602/m5602_core.c b/linux/drivers/media/video/gspca/m5602/m5602_core.c index b35e4838a..9f833b4ec 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_core.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_core.c @@ -92,29 +92,29 @@ int m5602_read_sensor(struct sd *sd, const u8 address, err = m5602_read_bridge(sd, M5602_XB_I2C_STATUS, i2c_data); } while ((*i2c_data & I2C_BUSY) && !err); if (err < 0) - goto out; + return err; err = m5602_write_bridge(sd, M5602_XB_I2C_DEV_ADDR, sd->sensor->i2c_slave_id); if (err < 0) - goto out; + return err; err = m5602_write_bridge(sd, M5602_XB_I2C_REG_ADDR, address); if (err < 0) - goto out; + return err; if (sd->sensor->i2c_regW == 1) { err = m5602_write_bridge(sd, M5602_XB_I2C_CTRL, len); if (err < 0) - goto out; + return err; err = m5602_write_bridge(sd, M5602_XB_I2C_CTRL, 0x08); if (err < 0) - goto out; + return err; } else { err = m5602_write_bridge(sd, M5602_XB_I2C_CTRL, 0x18 + len); if (err < 0) - goto out; + return err; } for (i = 0; (i < len) && !err; i++) { @@ -123,7 +123,6 @@ int m5602_read_sensor(struct sd *sd, const u8 address, PDEBUG(D_CONF, "Reading sensor register " "0x%x containing 0x%x ", address, *i2c_data); } -out: return err; } diff --git a/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.c b/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.c index c0e71c331..f3e9d8f0e 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.c @@ -125,16 +125,15 @@ int mt9m111_set_vflip(struct gspca_dev *gspca_dev, __s32 val) /* Set the correct page map */ err = m5602_write_sensor(sd, MT9M111_PAGE_MAP, data, 2); if (err < 0) - goto out; + return err; err = m5602_read_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B, data, 2); if (err < 0) - goto out; + return err; data[0] = (data[0] & 0xfe) | val; err = m5602_write_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B, data, 2); -out: return err; } @@ -163,16 +162,15 @@ int mt9m111_set_hflip(struct gspca_dev *gspca_dev, __s32 val) /* Set the correct page map */ err = m5602_write_sensor(sd, MT9M111_PAGE_MAP, data, 2); if (err < 0) - goto out; + return err; err = m5602_read_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B, data, 2); if (err < 0) - goto out; + return err; data[0] = (data[0] & 0xfd) | ((val << 1) & 0x02); err = m5602_write_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B, data, 2); -out: return err; } @@ -204,7 +202,7 @@ int mt9m111_set_gain(struct gspca_dev *gspca_dev, __s32 val) /* Set the correct page map */ err = m5602_write_sensor(sd, MT9M111_PAGE_MAP, data, 2); if (err < 0) - goto out; + return err; if (val >= INITIAL_MAX_GAIN * 2 * 2 * 2) return -EINVAL; @@ -229,7 +227,7 @@ int mt9m111_set_gain(struct gspca_dev *gspca_dev, __s32 val) err = m5602_write_sensor(sd, MT9M111_SC_GLOBAL_GAIN, data, 2); -out: + return err; } diff --git a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c index dde5075ed..42b46a844 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c @@ -224,21 +224,21 @@ int ov9650_get_exposure(struct gspca_dev *gspca_dev, __s32 *val) err = m5602_read_sensor(sd, OV9650_COM1, &i2c_data, 1); if (err < 0) - goto out; + return err; *val = i2c_data & 0x03; err = m5602_read_sensor(sd, OV9650_AECH, &i2c_data, 1); if (err < 0) - goto out; + return err; *val |= (i2c_data << 2); err = m5602_read_sensor(sd, OV9650_AECHM, &i2c_data, 1); if (err < 0) - goto out; + return err; *val |= (i2c_data & 0x3f) << 10; PDEBUG(D_V4L2, "Read exposure %d", *val); -out: + return err; } @@ -256,20 +256,19 @@ int ov9650_set_exposure(struct gspca_dev *gspca_dev, __s32 val) err = m5602_write_sensor(sd, OV9650_AECHM, &i2c_data, 1); if (err < 0) - goto out; + return err; /* The 8 middle bits */ i2c_data = (val >> 2) & 0xff; err = m5602_write_sensor(sd, OV9650_AECH, &i2c_data, 1); if (err < 0) - goto out; + return err; /* The 2 LSBs */ i2c_data = val & 0x03; err = m5602_write_sensor(sd, OV9650_COM1, &i2c_data, 1); -out: return err; } @@ -392,7 +391,7 @@ int ov9650_set_hflip(struct gspca_dev *gspca_dev, __s32 val) PDEBUG(D_V4L2, "Set horizontal flip to %d", val); err = m5602_read_sensor(sd, OV9650_MVFP, &i2c_data, 1); if (err < 0) - goto out; + return err; if (dmi_check_system(ov9650_flip_dmi_table)) i2c_data = ((i2c_data & 0xdf) | @@ -402,7 +401,7 @@ int ov9650_set_hflip(struct gspca_dev *gspca_dev, __s32 val) ((val & 0x01) << 5)); err = m5602_write_sensor(sd, OV9650_MVFP, &i2c_data, 1); -out: + return err; } @@ -431,7 +430,7 @@ int ov9650_set_vflip(struct gspca_dev *gspca_dev, __s32 val) PDEBUG(D_V4L2, "Set vertical flip to %d", val); err = m5602_read_sensor(sd, OV9650_MVFP, &i2c_data, 1); if (err < 0) - goto out; + return err; if (dmi_check_system(ov9650_flip_dmi_table)) i2c_data = ((i2c_data & 0xef) | @@ -441,7 +440,7 @@ int ov9650_set_vflip(struct gspca_dev *gspca_dev, __s32 val) ((val & 0x01) << 4)); err = m5602_write_sensor(sd, OV9650_MVFP, &i2c_data, 1); -out: + return err; } @@ -453,13 +452,13 @@ int ov9650_get_brightness(struct gspca_dev *gspca_dev, __s32 *val) err = m5602_read_sensor(sd, OV9650_VREF, &i2c_data, 1); if (err < 0) - goto out; + return err; *val = (i2c_data & 0x03) << 8; err = m5602_read_sensor(sd, OV9650_GAIN, &i2c_data, 1); *val |= i2c_data; PDEBUG(D_V4L2, "Read gain %d", *val); -out: + return err; } @@ -475,19 +474,18 @@ int ov9650_set_brightness(struct gspca_dev *gspca_dev, __s32 val) corrupting the VREF high and low bits */ err = m5602_read_sensor(sd, OV9650_VREF, &i2c_data, 1); if (err < 0) - goto out; + return err; /* Mask away all uninteresting bits */ i2c_data = ((val & 0x0300) >> 2) | (i2c_data & 0x3F); err = m5602_write_sensor(sd, OV9650_VREF, &i2c_data, 1); if (err < 0) - goto out; + return err; /* The 8 LSBs */ i2c_data = val & 0xff; err = m5602_write_sensor(sd, OV9650_GAIN, &i2c_data, 1); -out: return err; } @@ -513,11 +511,11 @@ int ov9650_set_auto_white_balance(struct gspca_dev *gspca_dev, __s32 val) PDEBUG(D_V4L2, "Set auto white balance to %d", val); err = m5602_read_sensor(sd, OV9650_COM8, &i2c_data, 1); if (err < 0) - goto out; + return err; i2c_data = ((i2c_data & 0xfd) | ((val & 0x01) << 1)); err = m5602_write_sensor(sd, OV9650_COM8, &i2c_data, 1); -out: + return err; } @@ -543,11 +541,11 @@ int ov9650_set_auto_gain(struct gspca_dev *gspca_dev, __s32 val) PDEBUG(D_V4L2, "Set auto gain control to %d", val); err = m5602_read_sensor(sd, OV9650_COM8, &i2c_data, 1); if (err < 0) - goto out; + return err; i2c_data = ((i2c_data & 0xfb) | ((val & 0x01) << 2)); err = m5602_write_sensor(sd, OV9650_COM8, &i2c_data, 1); -out: + return err; } diff --git a/linux/drivers/media/video/gspca/m5602/m5602_po1030.c b/linux/drivers/media/video/gspca/m5602/m5602_po1030.c index 2e7fb9167..d509330f5 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_po1030.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_po1030.c @@ -108,7 +108,7 @@ int po1030_get_exposure(struct gspca_dev *gspca_dev, __s32 *val) err = m5602_read_sensor(sd, PO1030_REG_INTEGLINES_H, &i2c_data, 1); if (err < 0) - goto out; + return err; *val = (i2c_data << 8); err = m5602_read_sensor(sd, PO1030_REG_INTEGLINES_M, @@ -116,7 +116,7 @@ int po1030_get_exposure(struct gspca_dev *gspca_dev, __s32 *val) *val |= i2c_data; PDEBUG(D_V4L2, "Exposure read as %d", *val); -out: + return err; } @@ -135,7 +135,7 @@ int po1030_set_exposure(struct gspca_dev *gspca_dev, __s32 val) err = m5602_write_sensor(sd, PO1030_REG_INTEGLINES_H, &i2c_data, 1); if (err < 0) - goto out; + return err; i2c_data = (val & 0xff); PDEBUG(D_V4L2, "Set exposure to low byte to 0x%x", @@ -143,7 +143,6 @@ int po1030_set_exposure(struct gspca_dev *gspca_dev, __s32 val) err = m5602_write_sensor(sd, PO1030_REG_INTEGLINES_M, &i2c_data, 1); -out: return err; } @@ -186,14 +185,13 @@ int po1030_set_hflip(struct gspca_dev *gspca_dev, __s32 val) PDEBUG(D_V4L2, "Set hflip %d", val); err = m5602_read_sensor(sd, PO1030_REG_CONTROL2, &i2c_data, 1); if (err < 0) - goto out; + return err; i2c_data = (0x7f & i2c_data) | ((val & 0x01) << 7); err = m5602_write_sensor(sd, PO1030_REG_CONTROL2, &i2c_data, 1); -out: return err; } @@ -222,14 +220,13 @@ int po1030_set_vflip(struct gspca_dev *gspca_dev, __s32 val) PDEBUG(D_V4L2, "Set vflip %d", val); err = m5602_read_sensor(sd, PO1030_REG_CONTROL2, &i2c_data, 1); if (err < 0) - goto out; + return err; i2c_data = (i2c_data & 0xbf) | ((val & 0x01) << 6); err = m5602_write_sensor(sd, PO1030_REG_CONTROL2, &i2c_data, 1); -out: return err; } diff --git a/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c b/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c index 8e5f2cb05..e7c4c5ef1 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c @@ -239,17 +239,17 @@ int s5k4aa_get_exposure(struct gspca_dev *gspca_dev, __s32 *val) err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1); if (err < 0) - goto out; + return err; err = m5602_read_sensor(sd, S5K4AA_EXPOSURE_HI, &data, 1); if (err < 0) - goto out; + return err; *val = data << 8; err = m5602_read_sensor(sd, S5K4AA_EXPOSURE_LO, &data, 1); *val |= data; PDEBUG(D_V4L2, "Read exposure %d", *val); -out: + return err; } @@ -262,14 +262,14 @@ int s5k4aa_set_exposure(struct gspca_dev *gspca_dev, __s32 val) PDEBUG(D_V4L2, "Set exposure to %d", val); err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1); if (err < 0) - goto out; + return err; data = (val >> 8) & 0xff; err = m5602_write_sensor(sd, S5K4AA_EXPOSURE_HI, &data, 1); if (err < 0) - goto out; + return err; data = val & 0xff; err = m5602_write_sensor(sd, S5K4AA_EXPOSURE_LO, &data, 1); -out: + return err; } @@ -281,13 +281,12 @@ int s5k4aa_get_vflip(struct gspca_dev *gspca_dev, __s32 *val) err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1); if (err < 0) - goto out; + return err; err = m5602_read_sensor(sd, S5K4AA_PAGE_MAP, &data, 1); *val = (data & S5K4AA_RM_V_FLIP) >> 7; PDEBUG(D_V4L2, "Read vertical flip %d", *val); -out: return err; } @@ -300,32 +299,32 @@ int s5k4aa_set_vflip(struct gspca_dev *gspca_dev, __s32 val) PDEBUG(D_V4L2, "Set vertical flip to %d", val); err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1); if (err < 0) - goto out; + return err; err = m5602_write_sensor(sd, S5K4AA_READ_MODE, &data, 1); if (err < 0) - goto out; + return err; data = ((data & ~S5K4AA_RM_V_FLIP) | ((val & 0x01) << 7)); err = m5602_write_sensor(sd, S5K4AA_READ_MODE, &data, 1); if (err < 0) - goto out; + return err; if (val) { err = m5602_read_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1); if (err < 0) - goto out; + return err; data++; err = m5602_write_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1); } else { err = m5602_read_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1); if (err < 0) - goto out; + return err; data--; err = m5602_write_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1); } -out: + return err; } @@ -337,12 +336,12 @@ int s5k4aa_get_hflip(struct gspca_dev *gspca_dev, __s32 *val) err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1); if (err < 0) - goto out; + return err; err = m5602_read_sensor(sd, S5K4AA_PAGE_MAP, &data, 1); *val = (data & S5K4AA_RM_H_FLIP) >> 6; PDEBUG(D_V4L2, "Read horizontal flip %d", *val); -out: + return err; } @@ -356,32 +355,32 @@ int s5k4aa_set_hflip(struct gspca_dev *gspca_dev, __s32 val) val); err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1); if (err < 0) - goto out; + return err; err = m5602_write_sensor(sd, S5K4AA_READ_MODE, &data, 1); if (err < 0) - goto out; + return err; data = ((data & ~S5K4AA_RM_H_FLIP) | ((val & 0x01) << 6)); err = m5602_write_sensor(sd, S5K4AA_READ_MODE, &data, 1); if (err < 0) - goto out; + return err; if (val) { err = m5602_read_sensor(sd, S5K4AA_COLSTART_LO, &data, 1); if (err < 0) - goto out; + return err; data++; err = m5602_write_sensor(sd, S5K4AA_COLSTART_LO, &data, 1); if (err < 0) - goto out; + return err; } else { err = m5602_read_sensor(sd, S5K4AA_COLSTART_LO, &data, 1); if (err < 0) - goto out; + return err; data--; err = m5602_write_sensor(sd, S5K4AA_COLSTART_LO, &data, 1); } -out: + return err; } @@ -393,13 +392,12 @@ int s5k4aa_get_gain(struct gspca_dev *gspca_dev, __s32 *val) err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1); if (err < 0) - goto out; + return err; err = m5602_read_sensor(sd, S5K4AA_GAIN_2, &data, 1); *val = data; PDEBUG(D_V4L2, "Read gain %d", *val); -out: return err; } @@ -412,12 +410,11 @@ int s5k4aa_set_gain(struct gspca_dev *gspca_dev, __s32 val) PDEBUG(D_V4L2, "Set gain to %d", val); err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1); if (err < 0) - goto out; + return err; data = val & 0xff; err = m5602_write_sensor(sd, S5K4AA_GAIN_2, &data, 1); -out: return err; } diff --git a/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.c b/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.c index ccea4a758..9bea347b9 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.c @@ -163,12 +163,11 @@ int s5k83a_get_brightness(struct gspca_dev *gspca_dev, __s32 *val) err = m5602_read_sensor(sd, S5K83A_BRIGHTNESS, data, 2); if (err < 0) - goto out; + return err; data[1] = data[1] << 1; *val = data[1]; -out: return err; } @@ -182,13 +181,13 @@ int s5k83a_set_brightness(struct gspca_dev *gspca_dev, __s32 val) data[1] = 0x20; err = m5602_write_sensor(sd, 0x14, data, 2); if (err < 0) - goto out; + return err; data[0] = 0x01; data[1] = 0x00; err = m5602_write_sensor(sd, 0x0d, data, 2); if (err < 0) - goto out; + return err; /* FIXME: This is not sane, we need to figure out the composition of these registers */ @@ -196,7 +195,6 @@ int s5k83a_set_brightness(struct gspca_dev *gspca_dev, __s32 val) data[1] = val >> 1; /* brightness, high 7 bits */ err = m5602_write_sensor(sd, S5K83A_BRIGHTNESS, data, 2); -out: return err; } @@ -208,11 +206,10 @@ int s5k83a_get_whiteness(struct gspca_dev *gspca_dev, __s32 *val) err = m5602_read_sensor(sd, S5K83A_WHITENESS, &data, 1); if (err < 0) - goto out; + return err; *val = data; -out: return err; } @@ -236,7 +233,7 @@ int s5k83a_get_gain(struct gspca_dev *gspca_dev, __s32 *val) err = m5602_read_sensor(sd, S5K83A_GAIN, data, 2); if (err < 0) - goto out; + return err; data[1] = data[1] & 0x3f; if (data[1] > S5K83A_MAXIMUM_GAIN) @@ -244,7 +241,6 @@ int s5k83a_get_gain(struct gspca_dev *gspca_dev, __s32 *val) *val = data[1]; -out: return err; } @@ -269,12 +265,11 @@ int s5k83a_get_vflip(struct gspca_dev *gspca_dev, __s32 *val) data[0] = 0x05; err = m5602_write_sensor(sd, S5K83A_PAGE_MAP, data, 1); if (err < 0) - goto out; + return err; err = m5602_read_sensor(sd, S5K83A_FLIP, data, 1); *val = (data[0] | 0x40) ? 1 : 0; -out: return err; } @@ -287,23 +282,22 @@ int s5k83a_set_vflip(struct gspca_dev *gspca_dev, __s32 val) data[0] = 0x05; err = m5602_write_sensor(sd, S5K83A_PAGE_MAP, data, 1); if (err < 0) - goto out; + return err; err = m5602_read_sensor(sd, S5K83A_FLIP, data, 1); if (err < 0) - goto out; + return err; /* set or zero six bit, seven is hflip */ data[0] = (val) ? (data[0] & 0x80) | 0x40 | S5K83A_FLIP_MASK : (data[0] & 0x80) | S5K83A_FLIP_MASK; err = m5602_write_sensor(sd, S5K83A_FLIP, data, 1); if (err < 0) - goto out; + return err; data[0] = (val) ? 0x0b : 0x0a; err = m5602_write_sensor(sd, S5K83A_VFLIP_TUNE, data, 1); -out: return err; } @@ -316,12 +310,11 @@ int s5k83a_get_hflip(struct gspca_dev *gspca_dev, __s32 *val) data[0] = 0x05; err = m5602_write_sensor(sd, S5K83A_PAGE_MAP, data, 1); if (err < 0) - goto out; + return err; err = m5602_read_sensor(sd, S5K83A_FLIP, data, 1); *val = (data[0] | 0x80) ? 1 : 0; -out: return err; } @@ -334,21 +327,21 @@ int s5k83a_set_hflip(struct gspca_dev *gspca_dev, __s32 val) data[0] = 0x05; err = m5602_write_sensor(sd, S5K83A_PAGE_MAP, data, 1); if (err < 0) - goto out; + return err; err = m5602_read_sensor(sd, S5K83A_FLIP, data, 1); if (err < 0) - goto out; + return err; /* set or zero seven bit, six is vflip */ data[0] = (val) ? (data[0] & 0x40) | 0x80 | S5K83A_FLIP_MASK : (data[0] & 0x40) | S5K83A_FLIP_MASK; err = m5602_write_sensor(sd, S5K83A_FLIP, data, 1); if (err < 0) - goto out; + return err; data[0] = (val) ? 0x0a : 0x0b; err = m5602_write_sensor(sd, S5K83A_HFLIP_TUNE, data, 1); -out: + return err; } -- cgit v1.2.3 From 6b8e289572105660293c15e0a23daf249aadbf06 Mon Sep 17 00:00:00 2001 From: Erik Andr?n Date: Sat, 27 Dec 2008 17:30:10 +0100 Subject: gspca - m5602-ov9650: Add QCIF resolution support From: Erik Andr?n Adds QCIF support for the ov9650 sensor Priority: normal Signed-off-by: Erik Andr?n --- .../drivers/media/video/gspca/m5602/m5602_ov9650.c | 14 +++++++++ .../drivers/media/video/gspca/m5602/m5602_ov9650.h | 33 +++++++++++++++++++++- 2 files changed, 46 insertions(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c index 42b46a844..61c5e6b5e 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c @@ -196,6 +196,20 @@ int ov9650_start(struct sd *sd) err = m5602_write_bridge(sd, QVGA_ov9650[i][1], data); } break; + + case 176: + PDEBUG(D_V4L2, "Configuring camera for QCIF mode"); + + for (i = 0; i < ARRAY_SIZE(QCIF_ov9650) && !err; i++) { + u8 data = QCIF_ov9650[i][2]; + if (QCIF_ov9650[i][0] == SENSOR) + err = m5602_write_sensor(sd, + QCIF_ov9650[i][1], &data, 1); + else + err = m5602_write_bridge(sd, QCIF_ov9650[i][1], data); + } + break; + } return err; } diff --git a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.h b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.h index f4b33b8e8..92536da9d 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.h @@ -96,6 +96,7 @@ #define OV9650_VGA_SELECT (1 << 6) #define OV9650_CIF_SELECT (1 << 5) #define OV9650_QVGA_SELECT (1 << 4) +#define OV9650_QCIF_SELECT (1 << 3) #define OV9650_RGB_SELECT (1 << 2) #define OV9650_RAW_RGB_SELECT (1 << 0) @@ -262,9 +263,19 @@ static struct m5602_sensor ov9650 = { } }, - .nmodes = 3, + .nmodes = 4, .modes = { { + 176, + 144, + V4L2_PIX_FMT_SBGGR8, + V4L2_FIELD_NONE, + .sizeimage = + 176 * 144, + .bytesperline = 176, + .colorspace = V4L2_COLORSPACE_SRGB, + .priv = 0 + }, { 320, 240, V4L2_PIX_FMT_SBGGR8, @@ -530,4 +541,24 @@ static const unsigned char QVGA_ov9650[][3] = OV9650_RAW_RGB_SELECT}, }; +static const unsigned char QCIF_ov9650[][3] = +{ + /* Moves the view window in a vertical orientation */ + {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x09}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x90}, /* 144 */ + {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, + {BRIDGE, M5602_XB_HSYNC_PARA, 0x00}, + {BRIDGE, M5602_XB_HSYNC_PARA, 0x31}, /* 48 */ + {BRIDGE, M5602_XB_HSYNC_PARA, 0x00}, /* 176 + 49 */ + {BRIDGE, M5602_XB_HSYNC_PARA, 0xe1}, + + {SENSOR, OV9650_COM7, OV9650_QCIF_SELECT | + OV9650_RGB_SELECT | + OV9650_RAW_RGB_SELECT}, +}; + #endif -- cgit v1.2.3 From 45a8275182889ae4860fd2e7b5f8fe07efcf7567 Mon Sep 17 00:00:00 2001 From: Erik Andr?n Date: Sat, 27 Dec 2008 18:06:06 +0100 Subject: gspca - m5602-ov9650: Clean up ov9650_start() function. From: Erik Andr?n Cleans some unnecessary temporary variable usage in the ov9650 start function. Priority: normal Signed-off-by: Erik Andr?n --- .../drivers/media/video/gspca/m5602/m5602_ov9650.c | 45 ++++++++++++---------- 1 file changed, 25 insertions(+), 20 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c index 61c5e6b5e..d0668e595 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c @@ -149,10 +149,8 @@ int ov9650_start(struct sd *sd) int i, err = 0; struct cam *cam = &sd->gspca_dev.cam; - for (i = 0; i < ARRAY_SIZE(res_init_ov9650) && !err; i++) { - u8 data = res_init_ov9650[i][1]; - err = m5602_write_bridge(sd, res_init_ov9650[i][0], data); - } + for (i = 0; i < ARRAY_SIZE(res_init_ov9650) && !err; i++) + err = m5602_write_bridge(sd, res_init_ov9650[i][0], res_init_ov9650[i][1]); if (err < 0) return err; @@ -162,12 +160,14 @@ int ov9650_start(struct sd *sd) PDEBUG(D_V4L2, "Configuring camera for VGA mode"); for (i = 0; i < ARRAY_SIZE(VGA_ov9650) && !err; i++) { - u8 data = VGA_ov9650[i][2]; - if (VGA_ov9650[i][0] == SENSOR) + if (VGA_ov9650[i][0] == SENSOR) { + u8 data = VGA_ov9650[i][2]; + err = m5602_write_sensor(sd, VGA_ov9650[i][1], &data, 1); - else - err = m5602_write_bridge(sd, VGA_ov9650[i][1], data); + } else { + err = m5602_write_bridge(sd, VGA_ov9650[i][1], VGA_ov9650[i][2]); + } } break; @@ -175,12 +175,14 @@ int ov9650_start(struct sd *sd) PDEBUG(D_V4L2, "Configuring camera for CIF mode"); for (i = 0; i < ARRAY_SIZE(CIF_ov9650) && !err; i++) { - u8 data = CIF_ov9650[i][2]; - if (CIF_ov9650[i][0] == SENSOR) + if (CIF_ov9650[i][0] == SENSOR) { + u8 data = CIF_ov9650[i][2]; + err = m5602_write_sensor(sd, CIF_ov9650[i][1], &data, 1); - else - err = m5602_write_bridge(sd, CIF_ov9650[i][1], data); + } else { + err = m5602_write_bridge(sd, CIF_ov9650[i][1], CIF_ov9650[i][2]); + } } break; @@ -188,12 +190,14 @@ int ov9650_start(struct sd *sd) PDEBUG(D_V4L2, "Configuring camera for QVGA mode"); for (i = 0; i < ARRAY_SIZE(QVGA_ov9650) && !err; i++) { - u8 data = QVGA_ov9650[i][2]; - if (QVGA_ov9650[i][0] == SENSOR) + if (QVGA_ov9650[i][0] == SENSOR) { + u8 data = QVGA_ov9650[i][2]; + err = m5602_write_sensor(sd, QVGA_ov9650[i][1], &data, 1); - else - err = m5602_write_bridge(sd, QVGA_ov9650[i][1], data); + } else { + err = m5602_write_bridge(sd, QVGA_ov9650[i][1], QVGA_ov9650[i][2]); + } } break; @@ -201,12 +205,13 @@ int ov9650_start(struct sd *sd) PDEBUG(D_V4L2, "Configuring camera for QCIF mode"); for (i = 0; i < ARRAY_SIZE(QCIF_ov9650) && !err; i++) { - u8 data = QCIF_ov9650[i][2]; - if (QCIF_ov9650[i][0] == SENSOR) + if (QCIF_ov9650[i][0] == SENSOR) { + u8 data = QCIF_ov9650[i][2]; err = m5602_write_sensor(sd, QCIF_ov9650[i][1], &data, 1); - else - err = m5602_write_bridge(sd, QCIF_ov9650[i][1], data); + } else { + err = m5602_write_bridge(sd, QCIF_ov9650[i][1], QCIF_ov9650[i][2]); + } } break; -- cgit v1.2.3 From 8f763cc5d1872ca6139a91bb7d32dd04c1a70a5c Mon Sep 17 00:00:00 2001 From: Erik Andr?n Date: Sun, 28 Dec 2008 18:09:21 +0100 Subject: gspca - m5602-s5k83a: Add led support to the s5k83a sensor. From: Lukas Karas This patch toggles the led seen on many laptops having a m5602 connected to a Samsung s5k83a sensor. Priority: normal Signed-off-by: Lukas Karas Signed-off-by: Erik Andr?n --- linux/drivers/media/video/gspca/m5602/m5602_core.c | 6 ++++- .../drivers/media/video/gspca/m5602/m5602_s5k83a.c | 29 ++++++++++++++++++++++ .../drivers/media/video/gspca/m5602/m5602_s5k83a.h | 10 ++++++-- .../drivers/media/video/gspca/m5602/m5602_sensor.h | 3 +++ 4 files changed, 45 insertions(+), 3 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/m5602/m5602_core.c b/linux/drivers/media/video/gspca/m5602/m5602_core.c index 9f833b4ec..bae7aa6f0 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_core.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_core.c @@ -309,7 +309,11 @@ static void m5602_urb_complete(struct gspca_dev *gspca_dev, static void m5602_stop_transfer(struct gspca_dev *gspca_dev) { - /* Is there are a command to stop a data transfer? */ + struct sd *sd = (struct sd *) gspca_dev; + + /* Run the sensor specific end transfer sequence */ + if (sd->sensor->stop) + sd->sensor->stop(sd); } /* sub-driver description, the ctrl and nctrl is filled at probe time */ diff --git a/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.c b/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.c index 9bea347b9..5ce69d74d 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.c @@ -108,6 +108,16 @@ int s5k83a_init(struct sd *sd) return (err < 0) ? err : 0; } +int s5k83a_start(struct sd *sd) +{ + return s5k83a_set_led_indication(sd, 1); +} + +int s5k83a_stop(struct sd *sd) +{ + return s5k83a_set_led_indication(sd, 0); +} + int s5k83a_power_down(struct sd *sd) { return 0; @@ -345,3 +355,22 @@ int s5k83a_set_hflip(struct gspca_dev *gspca_dev, __s32 val) return err; } + +int s5k83a_set_led_indication(struct sd *sd, u8 val) +{ + int err = 0; + u8 data[1]; + + err = m5602_read_bridge(sd, M5602_XB_GPIO_DAT, data); + if (err < 0) + return err; + + if (val) + data[0] = data[0] | S5K83A_GPIO_LED_MASK; + else + data[0] = data[0] & ~S5K83A_GPIO_LED_MASK; + + err = m5602_write_bridge(sd, M5602_XB_GPIO_DAT, data[0]); + + return (err < 0) ? err : 0; +} diff --git a/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.h b/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.h index 05ccb5b57..40ed14165 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.h @@ -34,7 +34,7 @@ #define S5K83A_DEFAULT_GAIN 0x00 #define S5K83A_MAXIMUM_GAIN 0x3c #define S5K83A_FLIP_MASK 0x10 - +#define S5K83A_GPIO_LED_MASK 0x10 /*****************************************************************************/ @@ -44,8 +44,12 @@ extern int dump_sensor; int s5k83a_probe(struct sd *sd); int s5k83a_init(struct sd *sd); +int s5k83a_start(struct sd *sd); +int s5k83a_stop(struct sd *sd); int s5k83a_power_down(struct sd *sd); +int s5k83a_set_led_indication(struct sd *sd, u8 val); + int s5k83a_set_brightness(struct gspca_dev *gspca_dev, __s32 val); int s5k83a_get_brightness(struct gspca_dev *gspca_dev, __s32 *val); int s5k83a_set_whiteness(struct gspca_dev *gspca_dev, __s32 val); @@ -61,6 +65,8 @@ static struct m5602_sensor s5k83a = { .name = "S5K83A", .probe = s5k83a_probe, .init = s5k83a_init, + .start = s5k83a_start, + .stop = s5k83a_stop, .power_down = s5k83a_power_down, .i2c_slave_id = 0x5a, .i2c_regW = 2, @@ -381,7 +387,7 @@ static const unsigned char init_s5k83a[][4] = {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xf0, 0x00}, {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00}, - {BRIDGE, M5602_XB_GPIO_DAT, 0x1c, 0x00}, + {BRIDGE, M5602_XB_GPIO_DAT, 0x08, 0x00}, {BRIDGE, M5602_XB_GPIO_EN_H, 0x06, 0x00}, {BRIDGE, M5602_XB_GPIO_DIR_H, 0x06, 0x00}, {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00, 0x00}, diff --git a/linux/drivers/media/video/gspca/m5602/m5602_sensor.h b/linux/drivers/media/video/gspca/m5602/m5602_sensor.h index 261623f0d..8eed4cc0b 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_sensor.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_sensor.h @@ -61,6 +61,9 @@ struct m5602_sensor { /* Executed when the camera starts to send data */ int (*start)(struct sd *sd); + /* Executed when the camera ends to send data */ + int (*stop)(struct sd *sd); + /* Performs a power down sequence */ int (*power_down)(struct sd *sd); -- cgit v1.2.3 From c38361e834fd13184e9104b6a477081d032391b1 Mon Sep 17 00:00:00 2001 From: Erik Andr?n Date: Mon, 29 Dec 2008 16:49:25 +0100 Subject: gspca - m5602-ov9650: Set the ov9650 sensor in soft sleep when inactive. From: Erik Andr?n In order to save energy, put the sensor in soft sleep mode when not active Priority: normal Signed-off-by: Erik Andr?n --- .../drivers/media/video/gspca/m5602/m5602_ov9650.c | 16 +++++++++++++-- .../drivers/media/video/gspca/m5602/m5602_ov9650.h | 23 ++++++++++++++++------ 2 files changed, 31 insertions(+), 8 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c index d0668e595..ce4a1f0df 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c @@ -149,8 +149,14 @@ int ov9650_start(struct sd *sd) int i, err = 0; struct cam *cam = &sd->gspca_dev.cam; - for (i = 0; i < ARRAY_SIZE(res_init_ov9650) && !err; i++) - err = m5602_write_bridge(sd, res_init_ov9650[i][0], res_init_ov9650[i][1]); + for (i = 0; i < ARRAY_SIZE(res_init_ov9650) && !err; i++) { + if (res_init_ov9650[i][0] == BRIDGE) + err = m5602_write_bridge(sd, res_init_ov9650[i][1], res_init_ov9650[i][2]); + else if (res_init_ov9650[i][0] == SENSOR) { + u8 data = res_init_ov9650[i][2]; + err = m5602_write_sensor(sd, res_init_ov9650[i][1], &data, 1); + } + } if (err < 0) return err; @@ -219,6 +225,12 @@ int ov9650_start(struct sd *sd) return err; } +int ov9650_stop(struct sd *sd) +{ + u8 data = OV9650_SOFT_SLEEP | OV9650_OUTPUT_DRIVE_2X; + return m5602_write_sensor(sd, OV9650_COM2, &data, 1); +} + int ov9650_power_down(struct sd *sd) { int i, err = 0; diff --git a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.h b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.h index 92536da9d..fe69ddfcb 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.h @@ -32,6 +32,7 @@ #define OV9650_BAVE 0x05 #define OV9650_GEAVE 0x06 #define OV9650_RSVD7 0x07 +#define OV9650_COM2 0x09 #define OV9650_PID 0x0a #define OV9650_VER 0x0b #define OV9650_COM3 0x0c @@ -116,6 +117,9 @@ #define OV9650_VFLIP (1 << 4) #define OV9650_HFLIP (1 << 5) +#define OV9650_SOFT_SLEEP (1 << 4) +#define OV9650_OUTPUT_DRIVE_2X (1 << 0) + #define GAIN_DEFAULT 0x14 #define RED_GAIN_DEFAULT 0x70 #define BLUE_GAIN_DEFAULT 0x20 @@ -130,6 +134,7 @@ extern int dump_sensor; int ov9650_probe(struct sd *sd); int ov9650_init(struct sd *sd); int ov9650_start(struct sd *sd); +int ov9650_stop(struct sd *sd); int ov9650_power_down(struct sd *sd); int ov9650_set_exposure(struct gspca_dev *gspca_dev, __s32 val); @@ -158,6 +163,7 @@ static struct m5602_sensor ov9650 = { .probe = ov9650_probe, .init = ov9650_init, .start = ov9650_start, + .stop = ov9650_stop, .power_down = ov9650_power_down, .nctrls = 8, @@ -450,6 +456,9 @@ static const unsigned char init_ov9650[][3] = {SENSOR, OV9650_GAIN, GAIN_DEFAULT}, {SENSOR, OV9650_BLUE, BLUE_GAIN_DEFAULT}, {SENSOR, OV9650_RED, RED_GAIN_DEFAULT}, + + /* Put the sensor in soft sleep mode */ + {SENSOR, OV9650_COM2, OV9650_SOFT_SLEEP | OV9650_OUTPUT_DRIVE_2X}, }; static const unsigned char power_down_ov9650[][3] = @@ -472,13 +481,15 @@ static const unsigned char power_down_ov9650[][3] = {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0}, }; -static const unsigned char res_init_ov9650[][2] = +static const unsigned char res_init_ov9650[][3] = { - {M5602_XB_LINE_OF_FRAME_H, 0x82}, - {M5602_XB_LINE_OF_FRAME_L, 0x00}, - {M5602_XB_PIX_OF_LINE_H, 0x82}, - {M5602_XB_PIX_OF_LINE_L, 0x00}, - {M5602_XB_SIG_INI, 0x01} + {SENSOR, OV9650_COM2, (1 << 0)}, + + {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x82}, + {BRIDGE, M5602_XB_LINE_OF_FRAME_L, 0x00}, + {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82}, + {BRIDGE, M5602_XB_PIX_OF_LINE_L, 0x00}, + {BRIDGE, M5602_XB_SIG_INI, 0x01} }; static const unsigned char VGA_ov9650[][3] = -- cgit v1.2.3 From aaec9d2ce358856c524d13dc51b02d4cc01fba8a Mon Sep 17 00:00:00 2001 From: Erik Andr?n Date: Tue, 30 Dec 2008 11:47:11 +0100 Subject: gspca - m5602-ov9650: Always init the ov9650 before starting a stream From: Erik Andr?n This is a hack preventing a suspend-to-ram/disk regression. Priority: normal Signed-off-by: Erik Andr?n --- linux/drivers/media/video/gspca/m5602/m5602_ov9650.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c index ce4a1f0df..90f64e443 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c @@ -141,6 +141,7 @@ int ov9650_init(struct sd *sd) data = 0x30; err = m5602_write_sensor(sd, OV9650_MVFP, &data, 1); } + return err; } @@ -149,6 +150,10 @@ int ov9650_start(struct sd *sd) int i, err = 0; struct cam *cam = &sd->gspca_dev.cam; + err = ov9650_init(sd); + if (err < 0) + return err; + for (i = 0; i < ARRAY_SIZE(res_init_ov9650) && !err; i++) { if (res_init_ov9650[i][0] == BRIDGE) err = m5602_write_bridge(sd, res_init_ov9650[i][1], res_init_ov9650[i][2]); -- cgit v1.2.3 From f432c786231aa49d870920164745f6398096dc60 Mon Sep 17 00:00:00 2001 From: Erik Andr?n Date: Tue, 30 Dec 2008 19:27:17 +0100 Subject: gspca - m5602: Rework v4l ctrl handling in all sensors From: Erik Andr?n Previously, all sensors allocated a part of a large ctrl vector. Define this vector separately for each sensor instead. Priority: normal Signed-off-by: Erik Andr?n --- linux/drivers/media/video/gspca/m5602/Makefile | 3 +- .../drivers/media/video/gspca/m5602/m5602_bridge.h | 2 +- .../media/video/gspca/m5602/m5602_mt9m111.c | 2 +- .../media/video/gspca/m5602/m5602_mt9m111.h | 25 ++++++++-------- .../drivers/media/video/gspca/m5602/m5602_ov9650.c | 2 +- .../drivers/media/video/gspca/m5602/m5602_ov9650.h | 35 ++++++++-------------- .../drivers/media/video/gspca/m5602/m5602_po1030.c | 2 +- .../drivers/media/video/gspca/m5602/m5602_po1030.h | 27 +++++++++-------- .../drivers/media/video/gspca/m5602/m5602_s5k4aa.c | 3 +- .../drivers/media/video/gspca/m5602/m5602_s5k4aa.h | 23 +++++++------- .../drivers/media/video/gspca/m5602/m5602_s5k83a.c | 2 +- .../drivers/media/video/gspca/m5602/m5602_s5k83a.h | 29 ++++++++++-------- .../drivers/media/video/gspca/m5602/m5602_sensor.h | 5 +--- 13 files changed, 75 insertions(+), 85 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/m5602/Makefile b/linux/drivers/media/video/gspca/m5602/Makefile index 226ab4fc9..9fa3644f4 100644 --- a/linux/drivers/media/video/gspca/m5602/Makefile +++ b/linux/drivers/media/video/gspca/m5602/Makefile @@ -7,5 +7,4 @@ gspca_m5602-objs := m5602_core.o \ m5602_s5k83a.o \ m5602_s5k4aa.o -EXTRA_CFLAGS += -Idrivers/media/video/gspca - +EXTRA_CFLAGS += -Idrivers/media/video/gspca \ No newline at end of file diff --git a/linux/drivers/media/video/gspca/m5602/m5602_bridge.h b/linux/drivers/media/video/gspca/m5602/m5602_bridge.h index a3f3b7a0c..9ff410066 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_bridge.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_bridge.h @@ -116,7 +116,7 @@ struct sd { char *name; /* A pointer to the currently connected sensor */ - struct m5602_sensor *sensor; + const struct m5602_sensor *sensor; struct sd_desc *desc; diff --git a/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.c b/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.c index f3e9d8f0e..69f8f6ce5 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.c @@ -65,7 +65,7 @@ sensor_found: sd->gspca_dev.cam.cam_mode = mt9m111.modes; sd->gspca_dev.cam.nmodes = mt9m111.nmodes; sd->desc->ctrls = mt9m111.ctrls; - sd->desc->nctrls = mt9m111.nctrls; + sd->desc->nctrls = ARRAY_SIZE(mt9m111_ctrls); return 0; } diff --git a/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h b/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h index e795ab7a3..23b8e4f57 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h @@ -94,18 +94,7 @@ int mt9m111_set_hflip(struct gspca_dev *gspca_dev, __s32 val); int mt9m111_get_gain(struct gspca_dev *gspca_dev, __s32 *val); int mt9m111_set_gain(struct gspca_dev *gspca_dev, __s32 val); -static struct m5602_sensor mt9m111 = { - .name = "MT9M111", - - .i2c_slave_id = 0xba, - .i2c_regW = 2, - - .probe = mt9m111_probe, - .init = mt9m111_init, - .power_down = mt9m111_power_down, - - .nctrls = 3, - .ctrls = { +const static struct ctrl mt9m111_ctrls[] = { { { .id = V4L2_CID_VFLIP, @@ -144,7 +133,17 @@ static struct m5602_sensor mt9m111 = { .set = mt9m111_set_gain, .get = mt9m111_get_gain } - }, +}; + +static struct m5602_sensor mt9m111 = { + .name = "MT9M111", + + .i2c_slave_id = 0xba, + .i2c_regW = 2, + + .probe = mt9m111_probe, + .init = mt9m111_init, + .power_down = mt9m111_power_down, .nmodes = 1, .modes = { diff --git a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c index 90f64e443..ce0d8c7da 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c @@ -115,7 +115,7 @@ sensor_found: sd->gspca_dev.cam.cam_mode = ov9650.modes; sd->gspca_dev.cam.nmodes = ov9650.nmodes; sd->desc->ctrls = ov9650.ctrls; - sd->desc->nctrls = ov9650.nctrls; + sd->desc->nctrls = ARRAY_SIZE(ov9650_ctrls); return 0; } diff --git a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.h b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.h index fe69ddfcb..ebf729133 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.h @@ -156,18 +156,7 @@ int ov9650_set_auto_white_balance(struct gspca_dev *gspca_dev, __s32 val); int ov9650_get_auto_gain(struct gspca_dev *gspca_dev, __s32 *val); int ov9650_set_auto_gain(struct gspca_dev *gspca_dev, __s32 val); -static struct m5602_sensor ov9650 = { - .name = "OV9650", - .i2c_slave_id = 0x60, - .i2c_regW = 1, - .probe = ov9650_probe, - .init = ov9650_init, - .start = ov9650_start, - .stop = ov9650_stop, - .power_down = ov9650_power_down, - - .nctrls = 8, - .ctrls = { +static struct ctrl ov9650_ctrls[] = { { { .id = V4L2_CID_EXPOSURE, @@ -267,7 +256,18 @@ static struct m5602_sensor ov9650 = { .set = ov9650_set_auto_gain, .get = ov9650_get_auto_gain } - }, +}; + +static struct m5602_sensor ov9650 = { + .name = "OV9650", + .i2c_slave_id = 0x60, + .i2c_regW = 1, + .probe = ov9650_probe, + .init = ov9650_init, + .start = ov9650_start, + .stop = ov9650_stop, + .power_down = ov9650_power_down, + .ctrls = ov9650_ctrls, .nmodes = 4, .modes = { @@ -444,19 +444,10 @@ static const unsigned char init_ov9650[][3] = /* Enable denoise, and white-pixel erase */ {SENSOR, OV9650_COM22, 0x23}, - /* Set the high bits of the exposure value */ - {SENSOR, OV9650_AECH, ((EXPOSURE_DEFAULT & 0xff00) >> 8)}, - /* Enable VARIOPIXEL */ {SENSOR, OV9650_COM3, OV9650_VARIOPIXEL}, {SENSOR, OV9650_COM4, OV9650_QVGA_VARIOPIXEL}, - /* Set the low bits of the exposure value */ - {SENSOR, OV9650_COM1, (EXPOSURE_DEFAULT & 0xff)}, - {SENSOR, OV9650_GAIN, GAIN_DEFAULT}, - {SENSOR, OV9650_BLUE, BLUE_GAIN_DEFAULT}, - {SENSOR, OV9650_RED, RED_GAIN_DEFAULT}, - /* Put the sensor in soft sleep mode */ {SENSOR, OV9650_COM2, OV9650_SOFT_SLEEP | OV9650_OUTPUT_DRIVE_2X}, }; diff --git a/linux/drivers/media/video/gspca/m5602/m5602_po1030.c b/linux/drivers/media/video/gspca/m5602/m5602_po1030.c index d509330f5..7914dcc6e 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_po1030.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_po1030.c @@ -62,7 +62,7 @@ sensor_found: sd->gspca_dev.cam.cam_mode = po1030.modes; sd->gspca_dev.cam.nmodes = po1030.nmodes; sd->desc->ctrls = po1030.ctrls; - sd->desc->nctrls = po1030.nctrls; + sd->desc->nctrls = ARRAY_SIZE(po1030_ctrls); return 0; } diff --git a/linux/drivers/media/video/gspca/m5602/m5602_po1030.h b/linux/drivers/media/video/gspca/m5602/m5602_po1030.h index def39d5bc..afd776a07 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_po1030.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_po1030.h @@ -141,18 +141,7 @@ int po1030_set_hflip(struct gspca_dev *gspca_dev, __s32 val); int po1030_get_vflip(struct gspca_dev *gspca_dev, __s32 *val); int po1030_set_vflip(struct gspca_dev *gspca_dev, __s32 val); -static struct m5602_sensor po1030 = { - .name = "PO1030", - - .i2c_slave_id = 0xdc, - .i2c_regW = 1, - - .probe = po1030_probe, - .init = po1030_init, - .power_down = po1030_power_down, - - .nctrls = 6, - .ctrls = { +static struct ctrl po1030_ctrls[] = { { { .id = V4L2_CID_GAIN, @@ -230,7 +219,19 @@ static struct m5602_sensor po1030 = { .set = po1030_set_vflip, .get = po1030_get_vflip } - }, +}; + +static struct m5602_sensor po1030 = { + .name = "PO1030", + + .i2c_slave_id = 0xdc, + .i2c_regW = 1, + + .probe = po1030_probe, + .init = po1030_init, + .power_down = po1030_power_down, + + .ctrls = po1030_ctrls, .nmodes = 1, .modes = { diff --git a/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c b/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c index e7c4c5ef1..e4dc4d5ba 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c @@ -120,8 +120,7 @@ sensor_found: sd->gspca_dev.cam.cam_mode = s5k4aa.modes; sd->gspca_dev.cam.nmodes = s5k4aa.nmodes; sd->desc->ctrls = s5k4aa.ctrls; - sd->desc->nctrls = s5k4aa.nctrls; - + sd->desc->nctrls = ARRAY_SIZE(s5k4aa_ctrls); return 0; } diff --git a/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.h b/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.h index 0c08ccffc..33ba1621b 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.h @@ -77,16 +77,7 @@ int s5k4aa_set_hflip(struct gspca_dev *gspca_dev, __s32 val); int s5k4aa_get_gain(struct gspca_dev *gspca_dev, __s32 *val); int s5k4aa_set_gain(struct gspca_dev *gspca_dev, __s32 val); -static struct m5602_sensor s5k4aa = { - .name = "S5K4AA", - .probe = s5k4aa_probe, - .init = s5k4aa_init, - .start = s5k4aa_start, - .power_down = s5k4aa_power_down, - .i2c_slave_id = 0x5a, - .i2c_regW = 2, - .nctrls = 4, - .ctrls = { +static struct ctrl s5k4aa_ctrls[] = { { { .id = V4L2_CID_VFLIP, @@ -140,7 +131,17 @@ static struct m5602_sensor s5k4aa = { .set = s5k4aa_set_exposure, .get = s5k4aa_get_exposure } - }, +}; + +static struct m5602_sensor s5k4aa = { + .name = "S5K4AA", + .probe = s5k4aa_probe, + .init = s5k4aa_init, + .start = s5k4aa_start, + .power_down = s5k4aa_power_down, + .i2c_slave_id = 0x5a, + .i2c_regW = 2, + .ctrls = s5k4aa_ctrls, .nmodes = 1, .modes = { diff --git a/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.c b/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.c index 5ce69d74d..6880b3157 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.c @@ -66,7 +66,7 @@ sensor_found: sd->gspca_dev.cam.cam_mode = s5k83a.modes; sd->gspca_dev.cam.nmodes = s5k83a.nmodes; sd->desc->ctrls = s5k83a.ctrls; - sd->desc->nctrls = s5k83a.nctrls; + sd->desc->nctrls = ARRAY_SIZE(s5k83a_ctrls); return 0; } diff --git a/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.h b/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.h index 40ed14165..ed74d9734 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.h @@ -61,17 +61,7 @@ int s5k83a_set_vflip(struct gspca_dev *gspca_dev, __s32 val); int s5k83a_get_hflip(struct gspca_dev *gspca_dev, __s32 *val); int s5k83a_set_hflip(struct gspca_dev *gspca_dev, __s32 val); -static struct m5602_sensor s5k83a = { - .name = "S5K83A", - .probe = s5k83a_probe, - .init = s5k83a_init, - .start = s5k83a_start, - .stop = s5k83a_stop, - .power_down = s5k83a_power_down, - .i2c_slave_id = 0x5a, - .i2c_regW = 2, - .nctrls = 5, - .ctrls = { +static struct ctrl s5k83a_ctrls[] = { { { .id = V4L2_CID_BRIGHTNESS, @@ -136,8 +126,21 @@ static struct m5602_sensor s5k83a = { }, .set = s5k83a_set_vflip, .get = s5k83a_get_vflip - } - }, + } +}; + + +static struct m5602_sensor s5k83a = { + .name = "S5K83A", + .probe = s5k83a_probe, + .init = s5k83a_init, + .start = s5k83a_start, + .stop = s5k83a_stop, + .power_down = s5k83a_power_down, + .i2c_slave_id = 0x5a, + .i2c_regW = 2, + .ctrls = s5k83a_ctrls, + .nmodes = 1, .modes = { { diff --git a/linux/drivers/media/video/gspca/m5602/m5602_sensor.h b/linux/drivers/media/video/gspca/m5602/m5602_sensor.h index 8eed4cc0b..5867ee258 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_sensor.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_sensor.h @@ -24,8 +24,6 @@ #define M5602_DEFAULT_FRAME_WIDTH 640 #define M5602_DEFAULT_FRAME_HEIGHT 480 -#define M5602_MAX_CTRLS (V4L2_CID_LASTP1 - V4L2_CID_BASE + 10) - /* Enumerates all supported sensors */ enum sensors { OV9650_SENSOR = 1, @@ -67,8 +65,7 @@ struct m5602_sensor { /* Performs a power down sequence */ int (*power_down)(struct sd *sd); - int nctrls; - struct ctrl ctrls[M5602_MAX_CTRLS]; + const struct ctrl *ctrls; char nmodes; struct v4l2_pix_format modes[]; -- cgit v1.2.3 From 5d2a8429aa0bc4f056fbf716fc5cb094c68ef979 Mon Sep 17 00:00:00 2001 From: Erik Andr?n Date: Tue, 30 Dec 2008 19:29:48 +0100 Subject: gspca - m5602-ov9650: Checkpatch fixes From: Erik Andr?n Priority: normal Signed-off-by: Erik Andr?n --- .../drivers/media/video/gspca/m5602/m5602_ov9650.c | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c index ce0d8c7da..0593adc64 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c @@ -156,17 +156,18 @@ int ov9650_start(struct sd *sd) for (i = 0; i < ARRAY_SIZE(res_init_ov9650) && !err; i++) { if (res_init_ov9650[i][0] == BRIDGE) - err = m5602_write_bridge(sd, res_init_ov9650[i][1], res_init_ov9650[i][2]); + err = m5602_write_bridge(sd, res_init_ov9650[i][1], + res_init_ov9650[i][2]); else if (res_init_ov9650[i][0] == SENSOR) { u8 data = res_init_ov9650[i][2]; - err = m5602_write_sensor(sd, res_init_ov9650[i][1], &data, 1); + err = m5602_write_sensor(sd, + res_init_ov9650[i][1], &data, 1); } } if (err < 0) return err; - switch (cam->cam_mode[sd->gspca_dev.curr_mode].width) - { + switch (cam->cam_mode[sd->gspca_dev.curr_mode].width) { case 640: PDEBUG(D_V4L2, "Configuring camera for VGA mode"); @@ -177,7 +178,8 @@ int ov9650_start(struct sd *sd) err = m5602_write_sensor(sd, VGA_ov9650[i][1], &data, 1); } else { - err = m5602_write_bridge(sd, VGA_ov9650[i][1], VGA_ov9650[i][2]); + err = m5602_write_bridge(sd, VGA_ov9650[i][1], + VGA_ov9650[i][2]); } } break; @@ -192,7 +194,8 @@ int ov9650_start(struct sd *sd) err = m5602_write_sensor(sd, CIF_ov9650[i][1], &data, 1); } else { - err = m5602_write_bridge(sd, CIF_ov9650[i][1], CIF_ov9650[i][2]); + err = m5602_write_bridge(sd, CIF_ov9650[i][1], + CIF_ov9650[i][2]); } } break; @@ -207,7 +210,8 @@ int ov9650_start(struct sd *sd) err = m5602_write_sensor(sd, QVGA_ov9650[i][1], &data, 1); } else { - err = m5602_write_bridge(sd, QVGA_ov9650[i][1], QVGA_ov9650[i][2]); + err = m5602_write_bridge(sd, QVGA_ov9650[i][1], + QVGA_ov9650[i][2]); } } break; @@ -221,7 +225,8 @@ int ov9650_start(struct sd *sd) err = m5602_write_sensor(sd, QCIF_ov9650[i][1], &data, 1); } else { - err = m5602_write_bridge(sd, QCIF_ov9650[i][1], QCIF_ov9650[i][2]); + err = m5602_write_bridge(sd, QCIF_ov9650[i][1], + QCIF_ov9650[i][2]); } } break; -- cgit v1.2.3 From 63e01b8a8e4578a822d040b6acb59fabd531b9b6 Mon Sep 17 00:00:00 2001 From: Erik Andr?n Date: Tue, 30 Dec 2008 20:48:42 +0100 Subject: gspca - m5602-mt9m111: Separate mode vectors per sensor. From: Erik Andr?n By separating the supported for each sensor into a separate vector we can eliminate the nmodes variable and instead calculate it at runtime. Priority: normal Signed-off-by: Erik Andr?n --- .../media/video/gspca/m5602/m5602_mt9m111.c | 17 +++++++- .../media/video/gspca/m5602/m5602_mt9m111.h | 17 +------- .../drivers/media/video/gspca/m5602/m5602_ov9650.c | 51 +++++++++++++++++++++- .../drivers/media/video/gspca/m5602/m5602_ov9650.h | 47 +------------------- .../drivers/media/video/gspca/m5602/m5602_po1030.c | 17 +++++++- .../drivers/media/video/gspca/m5602/m5602_po1030.h | 15 ------- .../drivers/media/video/gspca/m5602/m5602_s5k4aa.c | 18 +++++++- .../drivers/media/video/gspca/m5602/m5602_s5k4aa.h | 15 ------- .../drivers/media/video/gspca/m5602/m5602_s5k83a.c | 18 +++++++- .../drivers/media/video/gspca/m5602/m5602_s5k83a.h | 16 ------- .../drivers/media/video/gspca/m5602/m5602_sensor.h | 3 -- 11 files changed, 113 insertions(+), 121 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.c b/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.c index 69f8f6ce5..5b57fb1eb 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.c @@ -18,6 +18,19 @@ #include "m5602_mt9m111.h" +static struct v4l2_pix_format mt9m111_modes[] = { + { + 640, + 480, + V4L2_PIX_FMT_SBGGR8, + V4L2_FIELD_NONE, + .sizeimage = 640 * 480, + .bytesperline = 640, + .colorspace = V4L2_COLORSPACE_SRGB, + .priv = 0 + } +}; + static void mt9m111_dump_registers(struct sd *sd); int mt9m111_probe(struct sd *sd) @@ -62,8 +75,8 @@ int mt9m111_probe(struct sd *sd) return -ENODEV; sensor_found: - sd->gspca_dev.cam.cam_mode = mt9m111.modes; - sd->gspca_dev.cam.nmodes = mt9m111.nmodes; + sd->gspca_dev.cam.cam_mode = mt9m111_modes; + sd->gspca_dev.cam.nmodes = ARRAY_SIZE(mt9m111_modes); sd->desc->ctrls = mt9m111.ctrls; sd->desc->nctrls = ARRAY_SIZE(mt9m111_ctrls); return 0; diff --git a/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h b/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h index 23b8e4f57..ff3809f28 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h @@ -143,22 +143,7 @@ static struct m5602_sensor mt9m111 = { .probe = mt9m111_probe, .init = mt9m111_init, - .power_down = mt9m111_power_down, - - .nmodes = 1, - .modes = { - { - M5602_DEFAULT_FRAME_WIDTH, - M5602_DEFAULT_FRAME_HEIGHT, - V4L2_PIX_FMT_SBGGR8, - V4L2_FIELD_NONE, - .sizeimage = - M5602_DEFAULT_FRAME_WIDTH * M5602_DEFAULT_FRAME_HEIGHT, - .bytesperline = M5602_DEFAULT_FRAME_WIDTH, - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 1 - } - } + .power_down = mt9m111_power_down }; static const unsigned char preinit_mt9m111[][4] = diff --git a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c index 0593adc64..4f59f13c9 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c @@ -70,6 +70,50 @@ static { } }; +static struct v4l2_pix_format ov9650_modes[] = { + { + 176, + 144, + V4L2_PIX_FMT_SBGGR8, + V4L2_FIELD_NONE, + .sizeimage = + 176 * 144, + .bytesperline = 176, + .colorspace = V4L2_COLORSPACE_SRGB, + .priv = 0 + }, { + 320, + 240, + V4L2_PIX_FMT_SBGGR8, + V4L2_FIELD_NONE, + .sizeimage = + 320 * 240, + .bytesperline = 320, + .colorspace = V4L2_COLORSPACE_SRGB, + .priv = 0 + }, { + 352, + 288, + V4L2_PIX_FMT_SBGGR8, + V4L2_FIELD_NONE, + .sizeimage = + 352 * 288, + .bytesperline = 352, + .colorspace = V4L2_COLORSPACE_SRGB, + .priv = 0 + }, { + 640, + 480, + V4L2_PIX_FMT_SBGGR8, + V4L2_FIELD_NONE, + .sizeimage = + 640 * 480, + .bytesperline = 640, + .colorspace = V4L2_COLORSPACE_SRGB, + .priv = 0 + } +}; + static void ov9650_dump_registers(struct sd *sd); int ov9650_probe(struct sd *sd) @@ -112,8 +156,11 @@ int ov9650_probe(struct sd *sd) return -ENODEV; sensor_found: - sd->gspca_dev.cam.cam_mode = ov9650.modes; - sd->gspca_dev.cam.nmodes = ov9650.nmodes; +// sd->gspca_dev.cam.cam_mode = ov9650.modes; +// sd->gspca_dev.cam.nmodes = ov9650.nmodes; + sd->gspca_dev.cam.cam_mode = ov9650_modes; + sd->gspca_dev.cam.nmodes = ARRAY_SIZE(ov9650_modes); + sd->desc->ctrls = ov9650.ctrls; sd->desc->nctrls = ARRAY_SIZE(ov9650_ctrls); return 0; diff --git a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.h b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.h index ebf729133..fb8fe56c4 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.h @@ -267,52 +267,7 @@ static struct m5602_sensor ov9650 = { .start = ov9650_start, .stop = ov9650_stop, .power_down = ov9650_power_down, - .ctrls = ov9650_ctrls, - - .nmodes = 4, - .modes = { - { - 176, - 144, - V4L2_PIX_FMT_SBGGR8, - V4L2_FIELD_NONE, - .sizeimage = - 176 * 144, - .bytesperline = 176, - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 0 - }, { - 320, - 240, - V4L2_PIX_FMT_SBGGR8, - V4L2_FIELD_NONE, - .sizeimage = - 320 * 240, - .bytesperline = 320, - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 0 - }, { - 352, - 288, - V4L2_PIX_FMT_SBGGR8, - V4L2_FIELD_NONE, - .sizeimage = - 352 * 288, - .bytesperline = 352, - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 0 - }, { - 640, - 480, - V4L2_PIX_FMT_SBGGR8, - V4L2_FIELD_NONE, - .sizeimage = - 640 * 480, - .bytesperline = 640, - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 0 - } - } + .ctrls = ov9650_ctrls }; static const unsigned char preinit_ov9650[][3] = diff --git a/linux/drivers/media/video/gspca/m5602/m5602_po1030.c b/linux/drivers/media/video/gspca/m5602/m5602_po1030.c index 7914dcc6e..716b359e7 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_po1030.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_po1030.c @@ -18,6 +18,19 @@ #include "m5602_po1030.h" +static struct v4l2_pix_format po1030_modes[] = { + { + 640, + 480, + V4L2_PIX_FMT_SBGGR8, + V4L2_FIELD_NONE, + .sizeimage = 640 * 480, + .bytesperline = 640, + .colorspace = V4L2_COLORSPACE_SRGB, + .priv = 0 + } +}; + static void po1030_dump_registers(struct sd *sd); int po1030_probe(struct sd *sd) @@ -59,8 +72,8 @@ int po1030_probe(struct sd *sd) return -ENODEV; sensor_found: - sd->gspca_dev.cam.cam_mode = po1030.modes; - sd->gspca_dev.cam.nmodes = po1030.nmodes; + sd->gspca_dev.cam.cam_mode = po1030_modes; + sd->gspca_dev.cam.nmodes = ARRAY_SIZE(po1030_modes); sd->desc->ctrls = po1030.ctrls; sd->desc->nctrls = ARRAY_SIZE(po1030_ctrls); return 0; diff --git a/linux/drivers/media/video/gspca/m5602/m5602_po1030.h b/linux/drivers/media/video/gspca/m5602/m5602_po1030.h index afd776a07..b28ab2e85 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_po1030.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_po1030.h @@ -232,21 +232,6 @@ static struct m5602_sensor po1030 = { .power_down = po1030_power_down, .ctrls = po1030_ctrls, - - .nmodes = 1, - .modes = { - { - M5602_DEFAULT_FRAME_WIDTH, - M5602_DEFAULT_FRAME_HEIGHT, - V4L2_PIX_FMT_SBGGR8, - V4L2_FIELD_NONE, - .sizeimage = - M5602_DEFAULT_FRAME_WIDTH * M5602_DEFAULT_FRAME_HEIGHT, - .bytesperline = M5602_DEFAULT_FRAME_WIDTH, - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 1 - } - } }; static const unsigned char preinit_po1030[][3] = diff --git a/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c b/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c index e4dc4d5ba..77f341d97 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c @@ -52,6 +52,20 @@ static { } }; +static struct v4l2_pix_format s5k4aa_modes[] = { + { + 640, + 480, + V4L2_PIX_FMT_SBGGR8, + V4L2_FIELD_NONE, + .sizeimage = + 640 * 480, + .bytesperline = 640, + .colorspace = V4L2_COLORSPACE_SRGB, + .priv = 0 + } +}; + static void s5k4aa_dump_registers(struct sd *sd); int s5k4aa_probe(struct sd *sd) @@ -117,8 +131,8 @@ int s5k4aa_probe(struct sd *sd) info("Detected a s5k4aa sensor"); sensor_found: - sd->gspca_dev.cam.cam_mode = s5k4aa.modes; - sd->gspca_dev.cam.nmodes = s5k4aa.nmodes; + sd->gspca_dev.cam.cam_mode = s5k4aa_modes; + sd->gspca_dev.cam.nmodes = ARRAY_SIZE(s5k4aa_modes); sd->desc->ctrls = s5k4aa.ctrls; sd->desc->nctrls = ARRAY_SIZE(s5k4aa_ctrls); return 0; diff --git a/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.h b/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.h index 33ba1621b..0f0c6dff1 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.h @@ -142,21 +142,6 @@ static struct m5602_sensor s5k4aa = { .i2c_slave_id = 0x5a, .i2c_regW = 2, .ctrls = s5k4aa_ctrls, - - .nmodes = 1, - .modes = { - { - 640, - 480, - V4L2_PIX_FMT_SBGGR8, - V4L2_FIELD_NONE, - .sizeimage = - 640 * 480, - .bytesperline = 640, - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 1 - } - } }; static const unsigned char preinit_s5k4aa[][4] = diff --git a/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.c b/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.c index 6880b3157..fcc8c3752 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.c @@ -18,6 +18,20 @@ #include "m5602_s5k83a.h" +static struct v4l2_pix_format s5k83a_modes[] = { + { + 640, + 480, + V4L2_PIX_FMT_SBGGR8, + V4L2_FIELD_NONE, + .sizeimage = + 640 * 480, + .bytesperline = 640, + .colorspace = V4L2_COLORSPACE_SRGB, + .priv = 0 + } +}; + static void s5k83a_dump_registers(struct sd *sd); int s5k83a_probe(struct sd *sd) @@ -63,8 +77,8 @@ int s5k83a_probe(struct sd *sd) info("Detected a s5k83a sensor"); sensor_found: - sd->gspca_dev.cam.cam_mode = s5k83a.modes; - sd->gspca_dev.cam.nmodes = s5k83a.nmodes; + sd->gspca_dev.cam.cam_mode = s5k83a_modes; + sd->gspca_dev.cam.nmodes = ARRAY_SIZE(s5k83a_modes); sd->desc->ctrls = s5k83a.ctrls; sd->desc->nctrls = ARRAY_SIZE(s5k83a_ctrls); return 0; diff --git a/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.h b/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.h index ed74d9734..d56eb4c5e 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.h @@ -129,7 +129,6 @@ static struct ctrl s5k83a_ctrls[] = { } }; - static struct m5602_sensor s5k83a = { .name = "S5K83A", .probe = s5k83a_probe, @@ -140,21 +139,6 @@ static struct m5602_sensor s5k83a = { .i2c_slave_id = 0x5a, .i2c_regW = 2, .ctrls = s5k83a_ctrls, - - .nmodes = 1, - .modes = { - { - M5602_DEFAULT_FRAME_WIDTH, - M5602_DEFAULT_FRAME_HEIGHT, - V4L2_PIX_FMT_SBGGR8, - V4L2_FIELD_NONE, - .sizeimage = - M5602_DEFAULT_FRAME_WIDTH * M5602_DEFAULT_FRAME_HEIGHT, - .bytesperline = M5602_DEFAULT_FRAME_WIDTH, - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 1 - } - } }; static const unsigned char preinit_s5k83a[][4] = diff --git a/linux/drivers/media/video/gspca/m5602/m5602_sensor.h b/linux/drivers/media/video/gspca/m5602/m5602_sensor.h index 5867ee258..3fd92d370 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_sensor.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_sensor.h @@ -66,9 +66,6 @@ struct m5602_sensor { int (*power_down)(struct sd *sd); const struct ctrl *ctrls; - - char nmodes; - struct v4l2_pix_format modes[]; }; #endif -- cgit v1.2.3 From 5ad53f606d69a980600f067aac469e09dec84f70 Mon Sep 17 00:00:00 2001 From: Erik Andr?n Date: Tue, 30 Dec 2008 21:06:55 +0100 Subject: gspca - m5602-mt9m111: Move v4l2 controls to main sensor file. From: Erik Andr?n Move over the v4l2 controls to the sensor specific source file. Remove the now redundant sensor struct member. Priority: normal Signed-off-by: Erik Andr?n --- .../media/video/gspca/m5602/m5602_mt9m111.c | 44 ++++++++- .../media/video/gspca/m5602/m5602_mt9m111.h | 41 -------- .../drivers/media/video/gspca/m5602/m5602_ov9650.c | 107 ++++++++++++++++++++- .../drivers/media/video/gspca/m5602/m5602_ov9650.h | 103 -------------------- .../drivers/media/video/gspca/m5602/m5602_po1030.c | 82 +++++++++++++++- .../drivers/media/video/gspca/m5602/m5602_po1030.h | 82 ---------------- .../drivers/media/video/gspca/m5602/m5602_s5k4aa.c | 58 ++++++++++- .../drivers/media/video/gspca/m5602/m5602_s5k4aa.h | 56 ----------- .../drivers/media/video/gspca/m5602/m5602_s5k83a.c | 70 +++++++++++++- .../drivers/media/video/gspca/m5602/m5602_s5k83a.h | 69 ------------- .../drivers/media/video/gspca/m5602/m5602_sensor.h | 2 - 11 files changed, 353 insertions(+), 361 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.c b/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.c index 5b57fb1eb..7d3f9e348 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.c @@ -31,6 +31,48 @@ static struct v4l2_pix_format mt9m111_modes[] = { } }; +const static struct ctrl mt9m111_ctrls[] = { + { + { + .id = V4L2_CID_VFLIP, + .type = V4L2_CTRL_TYPE_BOOLEAN, + .name = "vertical flip", + .minimum = 0, + .maximum = 1, + .step = 1, + .default_value = 0 + }, + .set = mt9m111_set_vflip, + .get = mt9m111_get_vflip + }, { + { + .id = V4L2_CID_HFLIP, + .type = V4L2_CTRL_TYPE_BOOLEAN, + .name = "horizontal flip", + .minimum = 0, + .maximum = 1, + .step = 1, + .default_value = 0 + }, + .set = mt9m111_set_hflip, + .get = mt9m111_get_hflip + }, { + { + .id = V4L2_CID_GAIN, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "gain", + .minimum = 0, + .maximum = (INITIAL_MAX_GAIN - 1) * 2 * 2 * 2, + .step = 1, + .default_value = DEFAULT_GAIN, + .flags = V4L2_CTRL_FLAG_SLIDER + }, + .set = mt9m111_set_gain, + .get = mt9m111_get_gain + } +}; + + static void mt9m111_dump_registers(struct sd *sd); int mt9m111_probe(struct sd *sd) @@ -77,7 +119,7 @@ int mt9m111_probe(struct sd *sd) sensor_found: sd->gspca_dev.cam.cam_mode = mt9m111_modes; sd->gspca_dev.cam.nmodes = ARRAY_SIZE(mt9m111_modes); - sd->desc->ctrls = mt9m111.ctrls; + sd->desc->ctrls = mt9m111_ctrls; sd->desc->nctrls = ARRAY_SIZE(mt9m111_ctrls); return 0; } diff --git a/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h b/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h index ff3809f28..cb04d8fef 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h @@ -94,47 +94,6 @@ int mt9m111_set_hflip(struct gspca_dev *gspca_dev, __s32 val); int mt9m111_get_gain(struct gspca_dev *gspca_dev, __s32 *val); int mt9m111_set_gain(struct gspca_dev *gspca_dev, __s32 val); -const static struct ctrl mt9m111_ctrls[] = { - { - { - .id = V4L2_CID_VFLIP, - .type = V4L2_CTRL_TYPE_BOOLEAN, - .name = "vertical flip", - .minimum = 0, - .maximum = 1, - .step = 1, - .default_value = 0 - }, - .set = mt9m111_set_vflip, - .get = mt9m111_get_vflip - }, { - { - .id = V4L2_CID_HFLIP, - .type = V4L2_CTRL_TYPE_BOOLEAN, - .name = "horizontal flip", - .minimum = 0, - .maximum = 1, - .step = 1, - .default_value = 0 - }, - .set = mt9m111_set_hflip, - .get = mt9m111_get_hflip - }, { - { - .id = V4L2_CID_GAIN, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "gain", - .minimum = 0, - .maximum = (INITIAL_MAX_GAIN - 1) * 2 * 2 * 2, - .step = 1, - .default_value = DEFAULT_GAIN, - .flags = V4L2_CTRL_FLAG_SLIDER - }, - .set = mt9m111_set_gain, - .get = mt9m111_get_gain - } -}; - static struct m5602_sensor mt9m111 = { .name = "MT9M111", diff --git a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c index 4f59f13c9..ca7609e0f 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c @@ -70,6 +70,108 @@ static { } }; +const static struct ctrl ov9650_ctrls[] = { + { + { + .id = V4L2_CID_EXPOSURE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "exposure", + .minimum = 0x00, + .maximum = 0xffff, + .step = 0x1, + .default_value = EXPOSURE_DEFAULT, + .flags = V4L2_CTRL_FLAG_SLIDER + }, + .set = ov9650_set_exposure, + .get = ov9650_get_exposure + }, { + { + .id = V4L2_CID_GAIN, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "gain", + .minimum = 0x00, + .maximum = 0x3ff, + .step = 0x1, + .default_value = GAIN_DEFAULT, + .flags = V4L2_CTRL_FLAG_SLIDER + }, + .set = ov9650_set_gain, + .get = ov9650_get_gain + }, { + { + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "red balance", + .minimum = 0x00, + .maximum = 0xff, + .step = 0x1, + .default_value = RED_GAIN_DEFAULT, + .flags = V4L2_CTRL_FLAG_SLIDER + }, + .set = ov9650_set_red_balance, + .get = ov9650_get_red_balance + }, { + { + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "blue balance", + .minimum = 0x00, + .maximum = 0xff, + .step = 0x1, + .default_value = BLUE_GAIN_DEFAULT, + .flags = V4L2_CTRL_FLAG_SLIDER + }, + .set = ov9650_set_blue_balance, + .get = ov9650_get_blue_balance + }, { + { + .id = V4L2_CID_HFLIP, + .type = V4L2_CTRL_TYPE_BOOLEAN, + .name = "horizontal flip", + .minimum = 0, + .maximum = 1, + .step = 1, + .default_value = 0 + }, + .set = ov9650_set_hflip, + .get = ov9650_get_hflip + }, { + { + .id = V4L2_CID_VFLIP, + .type = V4L2_CTRL_TYPE_BOOLEAN, + .name = "vertical flip", + .minimum = 0, + .maximum = 1, + .step = 1, + .default_value = 0 + }, + .set = ov9650_set_vflip, + .get = ov9650_get_vflip + }, { + { + .id = V4L2_CID_AUTO_WHITE_BALANCE, + .type = V4L2_CTRL_TYPE_BOOLEAN, + .name = "auto white balance", + .minimum = 0, + .maximum = 1, + .step = 1, + .default_value = 0 + }, + .set = ov9650_set_auto_white_balance, + .get = ov9650_get_auto_white_balance + }, { + { + .id = V4L2_CID_AUTOGAIN, + .type = V4L2_CTRL_TYPE_BOOLEAN, + .name = "auto gain control", + .minimum = 0, + .maximum = 1, + .step = 1, + .default_value = 0 + }, + .set = ov9650_set_auto_gain, + .get = ov9650_get_auto_gain + } +}; + static struct v4l2_pix_format ov9650_modes[] = { { 176, @@ -156,12 +258,9 @@ int ov9650_probe(struct sd *sd) return -ENODEV; sensor_found: -// sd->gspca_dev.cam.cam_mode = ov9650.modes; -// sd->gspca_dev.cam.nmodes = ov9650.nmodes; sd->gspca_dev.cam.cam_mode = ov9650_modes; sd->gspca_dev.cam.nmodes = ARRAY_SIZE(ov9650_modes); - - sd->desc->ctrls = ov9650.ctrls; + sd->desc->ctrls = ov9650_ctrls; sd->desc->nctrls = ARRAY_SIZE(ov9650_ctrls); return 0; } diff --git a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.h b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.h index fb8fe56c4..6bfe7a9c8 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.h @@ -156,108 +156,6 @@ int ov9650_set_auto_white_balance(struct gspca_dev *gspca_dev, __s32 val); int ov9650_get_auto_gain(struct gspca_dev *gspca_dev, __s32 *val); int ov9650_set_auto_gain(struct gspca_dev *gspca_dev, __s32 val); -static struct ctrl ov9650_ctrls[] = { - { - { - .id = V4L2_CID_EXPOSURE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "exposure", - .minimum = 0x00, - .maximum = 0xffff, - .step = 0x1, - .default_value = EXPOSURE_DEFAULT, - .flags = V4L2_CTRL_FLAG_SLIDER - }, - .set = ov9650_set_exposure, - .get = ov9650_get_exposure - }, { - { - .id = V4L2_CID_GAIN, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "gain", - .minimum = 0x00, - .maximum = 0x3ff, - .step = 0x1, - .default_value = GAIN_DEFAULT, - .flags = V4L2_CTRL_FLAG_SLIDER - }, - .set = ov9650_set_gain, - .get = ov9650_get_gain - }, { - { - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "red balance", - .minimum = 0x00, - .maximum = 0xff, - .step = 0x1, - .default_value = RED_GAIN_DEFAULT, - .flags = V4L2_CTRL_FLAG_SLIDER - }, - .set = ov9650_set_red_balance, - .get = ov9650_get_red_balance - }, { - { - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "blue balance", - .minimum = 0x00, - .maximum = 0xff, - .step = 0x1, - .default_value = BLUE_GAIN_DEFAULT, - .flags = V4L2_CTRL_FLAG_SLIDER - }, - .set = ov9650_set_blue_balance, - .get = ov9650_get_blue_balance - }, { - { - .id = V4L2_CID_HFLIP, - .type = V4L2_CTRL_TYPE_BOOLEAN, - .name = "horizontal flip", - .minimum = 0, - .maximum = 1, - .step = 1, - .default_value = 0 - }, - .set = ov9650_set_hflip, - .get = ov9650_get_hflip - }, { - { - .id = V4L2_CID_VFLIP, - .type = V4L2_CTRL_TYPE_BOOLEAN, - .name = "vertical flip", - .minimum = 0, - .maximum = 1, - .step = 1, - .default_value = 0 - }, - .set = ov9650_set_vflip, - .get = ov9650_get_vflip - }, { - { - .id = V4L2_CID_AUTO_WHITE_BALANCE, - .type = V4L2_CTRL_TYPE_BOOLEAN, - .name = "auto white balance", - .minimum = 0, - .maximum = 1, - .step = 1, - .default_value = 0 - }, - .set = ov9650_set_auto_white_balance, - .get = ov9650_get_auto_white_balance - }, { - { - .id = V4L2_CID_AUTOGAIN, - .type = V4L2_CTRL_TYPE_BOOLEAN, - .name = "auto gain control", - .minimum = 0, - .maximum = 1, - .step = 1, - .default_value = 0 - }, - .set = ov9650_set_auto_gain, - .get = ov9650_get_auto_gain - } -}; - static struct m5602_sensor ov9650 = { .name = "OV9650", .i2c_slave_id = 0x60, @@ -267,7 +165,6 @@ static struct m5602_sensor ov9650 = { .start = ov9650_start, .stop = ov9650_stop, .power_down = ov9650_power_down, - .ctrls = ov9650_ctrls }; static const unsigned char preinit_ov9650[][3] = diff --git a/linux/drivers/media/video/gspca/m5602/m5602_po1030.c b/linux/drivers/media/video/gspca/m5602/m5602_po1030.c index 716b359e7..eaddf488b 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_po1030.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_po1030.c @@ -31,6 +31,86 @@ static struct v4l2_pix_format po1030_modes[] = { } }; +const static struct ctrl po1030_ctrls[] = { + { + { + .id = V4L2_CID_GAIN, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "gain", + .minimum = 0x00, + .maximum = 0x4f, + .step = 0x1, + .default_value = PO1030_GLOBAL_GAIN_DEFAULT, + .flags = V4L2_CTRL_FLAG_SLIDER + }, + .set = po1030_set_gain, + .get = po1030_get_gain + }, { + { + .id = V4L2_CID_EXPOSURE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "exposure", + .minimum = 0x00, + .maximum = 0x02ff, + .step = 0x1, + .default_value = PO1030_EXPOSURE_DEFAULT, + .flags = V4L2_CTRL_FLAG_SLIDER + }, + .set = po1030_set_exposure, + .get = po1030_get_exposure + }, { + { + .id = V4L2_CID_RED_BALANCE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "red balance", + .minimum = 0x00, + .maximum = 0xff, + .step = 0x1, + .default_value = PO1030_RED_GAIN_DEFAULT, + .flags = V4L2_CTRL_FLAG_SLIDER + }, + .set = po1030_set_red_balance, + .get = po1030_get_red_balance + }, { + { + .id = V4L2_CID_BLUE_BALANCE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "blue balance", + .minimum = 0x00, + .maximum = 0xff, + .step = 0x1, + .default_value = PO1030_BLUE_GAIN_DEFAULT, + .flags = V4L2_CTRL_FLAG_SLIDER + }, + .set = po1030_set_blue_balance, + .get = po1030_get_blue_balance + }, { + { + .id = V4L2_CID_HFLIP, + .type = V4L2_CTRL_TYPE_BOOLEAN, + .name = "horizontal flip", + .minimum = 0, + .maximum = 1, + .step = 1, + .default_value = 0, + }, + .set = po1030_set_hflip, + .get = po1030_get_hflip + }, { + { + .id = V4L2_CID_VFLIP, + .type = V4L2_CTRL_TYPE_BOOLEAN, + .name = "vertical flip", + .minimum = 0, + .maximum = 1, + .step = 1, + .default_value = 0, + }, + .set = po1030_set_vflip, + .get = po1030_get_vflip + } +}; + static void po1030_dump_registers(struct sd *sd); int po1030_probe(struct sd *sd) @@ -74,7 +154,7 @@ int po1030_probe(struct sd *sd) sensor_found: sd->gspca_dev.cam.cam_mode = po1030_modes; sd->gspca_dev.cam.nmodes = ARRAY_SIZE(po1030_modes); - sd->desc->ctrls = po1030.ctrls; + sd->desc->ctrls = po1030_ctrls; sd->desc->nctrls = ARRAY_SIZE(po1030_ctrls); return 0; } diff --git a/linux/drivers/media/video/gspca/m5602/m5602_po1030.h b/linux/drivers/media/video/gspca/m5602/m5602_po1030.h index b28ab2e85..e68ae8896 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_po1030.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_po1030.h @@ -141,86 +141,6 @@ int po1030_set_hflip(struct gspca_dev *gspca_dev, __s32 val); int po1030_get_vflip(struct gspca_dev *gspca_dev, __s32 *val); int po1030_set_vflip(struct gspca_dev *gspca_dev, __s32 val); -static struct ctrl po1030_ctrls[] = { - { - { - .id = V4L2_CID_GAIN, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "gain", - .minimum = 0x00, - .maximum = 0x4f, - .step = 0x1, - .default_value = PO1030_GLOBAL_GAIN_DEFAULT, - .flags = V4L2_CTRL_FLAG_SLIDER - }, - .set = po1030_set_gain, - .get = po1030_get_gain - }, { - { - .id = V4L2_CID_EXPOSURE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "exposure", - .minimum = 0x00, - .maximum = 0x02ff, - .step = 0x1, - .default_value = PO1030_EXPOSURE_DEFAULT, - .flags = V4L2_CTRL_FLAG_SLIDER - }, - .set = po1030_set_exposure, - .get = po1030_get_exposure - }, { - { - .id = V4L2_CID_RED_BALANCE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "red balance", - .minimum = 0x00, - .maximum = 0xff, - .step = 0x1, - .default_value = PO1030_RED_GAIN_DEFAULT, - .flags = V4L2_CTRL_FLAG_SLIDER - }, - .set = po1030_set_red_balance, - .get = po1030_get_red_balance - }, { - { - .id = V4L2_CID_BLUE_BALANCE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "blue balance", - .minimum = 0x00, - .maximum = 0xff, - .step = 0x1, - .default_value = PO1030_BLUE_GAIN_DEFAULT, - .flags = V4L2_CTRL_FLAG_SLIDER - }, - .set = po1030_set_blue_balance, - .get = po1030_get_blue_balance - }, { - { - .id = V4L2_CID_HFLIP, - .type = V4L2_CTRL_TYPE_BOOLEAN, - .name = "horizontal flip", - .minimum = 0, - .maximum = 1, - .step = 1, - .default_value = 0, - }, - .set = po1030_set_hflip, - .get = po1030_get_hflip - }, { - { - .id = V4L2_CID_VFLIP, - .type = V4L2_CTRL_TYPE_BOOLEAN, - .name = "vertical flip", - .minimum = 0, - .maximum = 1, - .step = 1, - .default_value = 0, - }, - .set = po1030_set_vflip, - .get = po1030_get_vflip - } -}; - static struct m5602_sensor po1030 = { .name = "PO1030", @@ -230,8 +150,6 @@ static struct m5602_sensor po1030 = { .probe = po1030_probe, .init = po1030_init, .power_down = po1030_power_down, - - .ctrls = po1030_ctrls, }; static const unsigned char preinit_po1030[][3] = diff --git a/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c b/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c index 77f341d97..79a1d27a4 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c @@ -66,6 +66,62 @@ static struct v4l2_pix_format s5k4aa_modes[] = { } }; +const static struct ctrl s5k4aa_ctrls[] = { + { + { + .id = V4L2_CID_VFLIP, + .type = V4L2_CTRL_TYPE_BOOLEAN, + .name = "vertical flip", + .minimum = 0, + .maximum = 1, + .step = 1, + .default_value = 0 + }, + .set = s5k4aa_set_vflip, + .get = s5k4aa_get_vflip + + }, { + { + .id = V4L2_CID_HFLIP, + .type = V4L2_CTRL_TYPE_BOOLEAN, + .name = "horizontal flip", + .minimum = 0, + .maximum = 1, + .step = 1, + .default_value = 0 + }, + .set = s5k4aa_set_hflip, + .get = s5k4aa_get_hflip + + }, { + { + .id = V4L2_CID_GAIN, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Gain", + .minimum = 0, + .maximum = 127, + .step = 1, + .default_value = 0xa0, + .flags = V4L2_CTRL_FLAG_SLIDER + }, + .set = s5k4aa_set_gain, + .get = s5k4aa_get_gain + }, { + { + .id = V4L2_CID_EXPOSURE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Exposure", + .minimum = 13, + .maximum = 0xfff, + .step = 1, + .default_value = 0x100, + .flags = V4L2_CTRL_FLAG_SLIDER + }, + .set = s5k4aa_set_exposure, + .get = s5k4aa_get_exposure + } +}; + static void s5k4aa_dump_registers(struct sd *sd); int s5k4aa_probe(struct sd *sd) @@ -133,7 +189,7 @@ int s5k4aa_probe(struct sd *sd) sensor_found: sd->gspca_dev.cam.cam_mode = s5k4aa_modes; sd->gspca_dev.cam.nmodes = ARRAY_SIZE(s5k4aa_modes); - sd->desc->ctrls = s5k4aa.ctrls; + sd->desc->ctrls = s5k4aa_ctrls; sd->desc->nctrls = ARRAY_SIZE(s5k4aa_ctrls); return 0; } diff --git a/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.h b/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.h index 0f0c6dff1..ec96c8e05 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.h @@ -77,61 +77,6 @@ int s5k4aa_set_hflip(struct gspca_dev *gspca_dev, __s32 val); int s5k4aa_get_gain(struct gspca_dev *gspca_dev, __s32 *val); int s5k4aa_set_gain(struct gspca_dev *gspca_dev, __s32 val); -static struct ctrl s5k4aa_ctrls[] = { - { - { - .id = V4L2_CID_VFLIP, - .type = V4L2_CTRL_TYPE_BOOLEAN, - .name = "vertical flip", - .minimum = 0, - .maximum = 1, - .step = 1, - .default_value = 0 - }, - .set = s5k4aa_set_vflip, - .get = s5k4aa_get_vflip - - }, { - { - .id = V4L2_CID_HFLIP, - .type = V4L2_CTRL_TYPE_BOOLEAN, - .name = "horizontal flip", - .minimum = 0, - .maximum = 1, - .step = 1, - .default_value = 0 - }, - .set = s5k4aa_set_hflip, - .get = s5k4aa_get_hflip - - }, { - { - .id = V4L2_CID_GAIN, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "Gain", - .minimum = 0, - .maximum = 127, - .step = 1, - .default_value = 0xa0, - .flags = V4L2_CTRL_FLAG_SLIDER - }, - .set = s5k4aa_set_gain, - .get = s5k4aa_get_gain - }, { - { - .id = V4L2_CID_EXPOSURE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "Exposure", - .minimum = 13, - .maximum = 0xfff, - .step = 1, - .default_value = 0x100, - .flags = V4L2_CTRL_FLAG_SLIDER - }, - .set = s5k4aa_set_exposure, - .get = s5k4aa_get_exposure - } -}; static struct m5602_sensor s5k4aa = { .name = "S5K4AA", @@ -141,7 +86,6 @@ static struct m5602_sensor s5k4aa = { .power_down = s5k4aa_power_down, .i2c_slave_id = 0x5a, .i2c_regW = 2, - .ctrls = s5k4aa_ctrls, }; static const unsigned char preinit_s5k4aa[][4] = diff --git a/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.c b/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.c index fcc8c3752..42c86aa4d 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.c @@ -32,6 +32,74 @@ static struct v4l2_pix_format s5k83a_modes[] = { } }; +const static struct ctrl s5k83a_ctrls[] = { + { + { + .id = V4L2_CID_BRIGHTNESS, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "brightness", + .minimum = 0x00, + .maximum = 0xff, + .step = 0x01, + .default_value = S5K83A_DEFAULT_BRIGHTNESS, + .flags = V4L2_CTRL_FLAG_SLIDER + }, + .set = s5k83a_set_brightness, + .get = s5k83a_get_brightness + + }, { + { + .id = V4L2_CID_WHITENESS, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "whiteness", + .minimum = 0x00, + .maximum = 0xff, + .step = 0x01, + .default_value = S5K83A_DEFAULT_WHITENESS, + .flags = V4L2_CTRL_FLAG_SLIDER + }, + .set = s5k83a_set_whiteness, + .get = s5k83a_get_whiteness, + }, { + { + .id = V4L2_CID_GAIN, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "gain", + .minimum = 0x00, + .maximum = S5K83A_MAXIMUM_GAIN, + .step = 0x01, + .default_value = S5K83A_DEFAULT_GAIN, + .flags = V4L2_CTRL_FLAG_SLIDER + }, + .set = s5k83a_set_gain, + .get = s5k83a_get_gain + }, { + { + .id = V4L2_CID_HFLIP, + .type = V4L2_CTRL_TYPE_BOOLEAN, + .name = "horizontal flip", + .minimum = 0, + .maximum = 1, + .step = 1, + .default_value = 0 + }, + .set = s5k83a_set_hflip, + .get = s5k83a_get_hflip + }, { + { + .id = V4L2_CID_VFLIP, + .type = V4L2_CTRL_TYPE_BOOLEAN, + .name = "vertical flip", + .minimum = 0, + .maximum = 1, + .step = 1, + .default_value = 0 + }, + .set = s5k83a_set_vflip, + .get = s5k83a_get_vflip + } +}; + static void s5k83a_dump_registers(struct sd *sd); int s5k83a_probe(struct sd *sd) @@ -79,7 +147,7 @@ int s5k83a_probe(struct sd *sd) sensor_found: sd->gspca_dev.cam.cam_mode = s5k83a_modes; sd->gspca_dev.cam.nmodes = ARRAY_SIZE(s5k83a_modes); - sd->desc->ctrls = s5k83a.ctrls; + sd->desc->ctrls = s5k83a_ctrls; sd->desc->nctrls = ARRAY_SIZE(s5k83a_ctrls); return 0; } diff --git a/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.h b/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.h index d56eb4c5e..9b9450fbd 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.h @@ -61,74 +61,6 @@ int s5k83a_set_vflip(struct gspca_dev *gspca_dev, __s32 val); int s5k83a_get_hflip(struct gspca_dev *gspca_dev, __s32 *val); int s5k83a_set_hflip(struct gspca_dev *gspca_dev, __s32 val); -static struct ctrl s5k83a_ctrls[] = { - { - { - .id = V4L2_CID_BRIGHTNESS, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "brightness", - .minimum = 0x00, - .maximum = 0xff, - .step = 0x01, - .default_value = S5K83A_DEFAULT_BRIGHTNESS, - .flags = V4L2_CTRL_FLAG_SLIDER - }, - .set = s5k83a_set_brightness, - .get = s5k83a_get_brightness - - }, { - { - .id = V4L2_CID_WHITENESS, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "whiteness", - .minimum = 0x00, - .maximum = 0xff, - .step = 0x01, - .default_value = S5K83A_DEFAULT_WHITENESS, - .flags = V4L2_CTRL_FLAG_SLIDER - }, - .set = s5k83a_set_whiteness, - .get = s5k83a_get_whiteness, - }, { - { - .id = V4L2_CID_GAIN, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "gain", - .minimum = 0x00, - .maximum = S5K83A_MAXIMUM_GAIN, - .step = 0x01, - .default_value = S5K83A_DEFAULT_GAIN, - .flags = V4L2_CTRL_FLAG_SLIDER - }, - .set = s5k83a_set_gain, - .get = s5k83a_get_gain - }, { - { - .id = V4L2_CID_HFLIP, - .type = V4L2_CTRL_TYPE_BOOLEAN, - .name = "horizontal flip", - .minimum = 0, - .maximum = 1, - .step = 1, - .default_value = 0 - }, - .set = s5k83a_set_hflip, - .get = s5k83a_get_hflip - }, { - { - .id = V4L2_CID_VFLIP, - .type = V4L2_CTRL_TYPE_BOOLEAN, - .name = "vertical flip", - .minimum = 0, - .maximum = 1, - .step = 1, - .default_value = 0 - }, - .set = s5k83a_set_vflip, - .get = s5k83a_get_vflip - } -}; - static struct m5602_sensor s5k83a = { .name = "S5K83A", .probe = s5k83a_probe, @@ -138,7 +70,6 @@ static struct m5602_sensor s5k83a = { .power_down = s5k83a_power_down, .i2c_slave_id = 0x5a, .i2c_regW = 2, - .ctrls = s5k83a_ctrls, }; static const unsigned char preinit_s5k83a[][4] = diff --git a/linux/drivers/media/video/gspca/m5602/m5602_sensor.h b/linux/drivers/media/video/gspca/m5602/m5602_sensor.h index 3fd92d370..b3e82af65 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_sensor.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_sensor.h @@ -64,8 +64,6 @@ struct m5602_sensor { /* Performs a power down sequence */ int (*power_down)(struct sd *sd); - - const struct ctrl *ctrls; }; #endif -- cgit v1.2.3 From 9cc29332cc27df953ca82fd174a1a6c31dcbe67a Mon Sep 17 00:00:00 2001 From: Erik Andr?n Date: Tue, 30 Dec 2008 21:18:23 +0100 Subject: gspca - m5602: Remove an unused member in the sd struct. From: Erik Andr?n Remove an unused sd struct member. Remove a redundant define while we're at it. Priority: normal Signed-off-by: Erik Andr?n --- linux/drivers/media/video/gspca/m5602/m5602_bridge.h | 3 --- linux/drivers/media/video/gspca/m5602/m5602_sensor.h | 3 --- 2 files changed, 6 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/m5602/m5602_bridge.h b/linux/drivers/media/video/gspca/m5602/m5602_bridge.h index 9ff410066..de76a1613 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_bridge.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_bridge.h @@ -112,9 +112,6 @@ static const unsigned char sensor_urb_skeleton[] = { struct sd { struct gspca_dev gspca_dev; - /* The name of the m5602 camera */ - char *name; - /* A pointer to the currently connected sensor */ const struct m5602_sensor *sensor; diff --git a/linux/drivers/media/video/gspca/m5602/m5602_sensor.h b/linux/drivers/media/video/gspca/m5602/m5602_sensor.h index b3e82af65..5c8fb7aba 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_sensor.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_sensor.h @@ -21,9 +21,6 @@ #include "m5602_bridge.h" -#define M5602_DEFAULT_FRAME_WIDTH 640 -#define M5602_DEFAULT_FRAME_HEIGHT 480 - /* Enumerates all supported sensors */ enum sensors { OV9650_SENSOR = 1, -- cgit v1.2.3 From 62d8b3f1b9dd02697c01630ffd4baee204bc8855 Mon Sep 17 00:00:00 2001 From: Erik Andr?n Date: Tue, 30 Dec 2008 21:35:34 +0100 Subject: gspca - m5602: Constify all sensor structs From: Erik Andr?n Priority: normal Signed-off-by: Erik Andr?n --- linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h | 2 +- linux/drivers/media/video/gspca/m5602/m5602_ov9650.h | 2 +- linux/drivers/media/video/gspca/m5602/m5602_po1030.h | 2 +- linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.h | 3 +-- linux/drivers/media/video/gspca/m5602/m5602_s5k83a.h | 2 +- 5 files changed, 5 insertions(+), 6 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h b/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h index cb04d8fef..00c6db02b 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h @@ -94,7 +94,7 @@ int mt9m111_set_hflip(struct gspca_dev *gspca_dev, __s32 val); int mt9m111_get_gain(struct gspca_dev *gspca_dev, __s32 *val); int mt9m111_set_gain(struct gspca_dev *gspca_dev, __s32 val); -static struct m5602_sensor mt9m111 = { +const static struct m5602_sensor mt9m111 = { .name = "MT9M111", .i2c_slave_id = 0xba, diff --git a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.h b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.h index 6bfe7a9c8..08ae7ea96 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.h @@ -156,7 +156,7 @@ int ov9650_set_auto_white_balance(struct gspca_dev *gspca_dev, __s32 val); int ov9650_get_auto_gain(struct gspca_dev *gspca_dev, __s32 *val); int ov9650_set_auto_gain(struct gspca_dev *gspca_dev, __s32 val); -static struct m5602_sensor ov9650 = { +const static struct m5602_sensor ov9650 = { .name = "OV9650", .i2c_slave_id = 0x60, .i2c_regW = 1, diff --git a/linux/drivers/media/video/gspca/m5602/m5602_po1030.h b/linux/drivers/media/video/gspca/m5602/m5602_po1030.h index e68ae8896..c10b12335 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_po1030.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_po1030.h @@ -141,7 +141,7 @@ int po1030_set_hflip(struct gspca_dev *gspca_dev, __s32 val); int po1030_get_vflip(struct gspca_dev *gspca_dev, __s32 *val); int po1030_set_vflip(struct gspca_dev *gspca_dev, __s32 val); -static struct m5602_sensor po1030 = { +static const struct m5602_sensor po1030 = { .name = "PO1030", .i2c_slave_id = 0xdc, diff --git a/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.h b/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.h index ec96c8e05..ca854d4f9 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.h @@ -77,8 +77,7 @@ int s5k4aa_set_hflip(struct gspca_dev *gspca_dev, __s32 val); int s5k4aa_get_gain(struct gspca_dev *gspca_dev, __s32 *val); int s5k4aa_set_gain(struct gspca_dev *gspca_dev, __s32 val); - -static struct m5602_sensor s5k4aa = { +static const struct m5602_sensor s5k4aa = { .name = "S5K4AA", .probe = s5k4aa_probe, .init = s5k4aa_init, diff --git a/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.h b/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.h index 9b9450fbd..819ab2527 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.h @@ -61,7 +61,7 @@ int s5k83a_set_vflip(struct gspca_dev *gspca_dev, __s32 val); int s5k83a_get_hflip(struct gspca_dev *gspca_dev, __s32 *val); int s5k83a_set_hflip(struct gspca_dev *gspca_dev, __s32 val); -static struct m5602_sensor s5k83a = { +static const struct m5602_sensor s5k83a = { .name = "S5K83A", .probe = s5k83a_probe, .init = s5k83a_init, -- cgit v1.2.3 From 3f2166781628c2697a4f9a1d4ad63d29668690d4 Mon Sep 17 00:00:00 2001 From: Erik Andr?n Date: Wed, 31 Dec 2008 08:49:33 +0100 Subject: gspca - m5602-ov9650: Autogain is on by default From: Erik Andr?n Autogain is on by default, properly set the default value in the v4l2 ctrl. Priority: normal Signed-off-by: Erik Andr?n --- linux/drivers/media/video/gspca/m5602/m5602_ov9650.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c index ca7609e0f..e5e79aa2a 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c @@ -165,7 +165,7 @@ const static struct ctrl ov9650_ctrls[] = { .minimum = 0, .maximum = 1, .step = 1, - .default_value = 0 + .default_value = 1 }, .set = ov9650_set_auto_gain, .get = ov9650_get_auto_gain -- cgit v1.2.3 From eed2ee4f687a72b34352aac05672296f90826b6b Mon Sep 17 00:00:00 2001 From: Erik Andr?n Date: Wed, 31 Dec 2008 10:36:52 +0100 Subject: gspca - m5602-ov9650: Auto white balancing is on by default From: Erik Andr?n Priority: normal Signed-off-by: Erik Andr?n --- linux/drivers/media/video/gspca/m5602/m5602_ov9650.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c index e5e79aa2a..d7e4e080e 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c @@ -153,7 +153,7 @@ const static struct ctrl ov9650_ctrls[] = { .minimum = 0, .maximum = 1, .step = 1, - .default_value = 0 + .default_value = 1 }, .set = ov9650_set_auto_white_balance, .get = ov9650_get_auto_white_balance -- cgit v1.2.3 From bf2b33554b1eb89b8266720f9651a9d52240d1d3 Mon Sep 17 00:00:00 2001 From: Erik Andr?n Date: Wed, 31 Dec 2008 11:25:42 +0100 Subject: gspca - m5602-ov9650: Don't read exposure data from COM1. From: Erik Andr?n ov9650: Reading the COM1 register corrupts the image. Decrease the granularity of the exposure and limit its upper range as setting such high values doesn't have any effect on the image. Priority: normal Signed-off-by: Erik Andr?n --- linux/drivers/media/video/gspca/m5602/m5602_ov9650.c | 9 ++------- linux/drivers/media/video/gspca/m5602/m5602_ov9650.h | 2 +- 2 files changed, 3 insertions(+), 8 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c index d7e4e080e..73a889630 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c @@ -77,8 +77,8 @@ const static struct ctrl ov9650_ctrls[] = { .type = V4L2_CTRL_TYPE_INTEGER, .name = "exposure", .minimum = 0x00, - .maximum = 0xffff, - .step = 0x1, + .maximum = 0x1ff, + .step = 0x4, .default_value = EXPOSURE_DEFAULT, .flags = V4L2_CTRL_FLAG_SLIDER }, @@ -409,11 +409,6 @@ int ov9650_get_exposure(struct gspca_dev *gspca_dev, __s32 *val) u8 i2c_data; int err; - err = m5602_read_sensor(sd, OV9650_COM1, &i2c_data, 1); - if (err < 0) - return err; - *val = i2c_data & 0x03; - err = m5602_read_sensor(sd, OV9650_AECH, &i2c_data, 1); if (err < 0) return err; diff --git a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.h b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.h index 08ae7ea96..ca0e42ee0 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.h @@ -123,7 +123,7 @@ #define GAIN_DEFAULT 0x14 #define RED_GAIN_DEFAULT 0x70 #define BLUE_GAIN_DEFAULT 0x20 -#define EXPOSURE_DEFAULT 0x5003 +#define EXPOSURE_DEFAULT 0x1ff /*****************************************************************************/ -- cgit v1.2.3 From 22e8f2d7acdd2ab4292ad1f8fe055ee78445f8a1 Mon Sep 17 00:00:00 2001 From: Erik Andr?n Date: Fri, 2 Jan 2009 21:58:08 +0100 Subject: gspca - m5602: Improve error handling in the ov9650 driver From: Erik Andr?n Some errors were not propagated properly. Priority: normal Signed-off-by: Erik Andr?n --- .../drivers/media/video/gspca/m5602/m5602_ov9650.c | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c index 73a889630..e882385dd 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c @@ -220,6 +220,7 @@ static void ov9650_dump_registers(struct sd *sd); int ov9650_probe(struct sd *sd) { + int err = 0; u8 prod_id = 0, ver_id = 0, i; if (force_sensor) { @@ -235,15 +236,18 @@ int ov9650_probe(struct sd *sd) info("Probing for an ov9650 sensor"); /* Run the pre-init to actually probe the unit */ - for (i = 0; i < ARRAY_SIZE(preinit_ov9650); i++) { + for (i = 0; i < ARRAY_SIZE(preinit_ov9650) && !err; i++) { u8 data = preinit_ov9650[i][2]; if (preinit_ov9650[i][0] == SENSOR) - m5602_write_sensor(sd, + err = m5602_write_sensor(sd, preinit_ov9650[i][1], &data, 1); else - m5602_write_bridge(sd, preinit_ov9650[i][1], data); + err = m5602_write_bridge(sd, preinit_ov9650[i][1], data); } + if (err < 0) + return err; + if (m5602_read_sensor(sd, OV9650_PID, &prod_id, 1)) return -ENODEV; @@ -460,7 +464,10 @@ int ov9650_get_gain(struct gspca_dev *gspca_dev, __s32 *val) u8 i2c_data; struct sd *sd = (struct sd *) gspca_dev; - m5602_read_sensor(sd, OV9650_VREF, &i2c_data, 1); + err = m5602_read_sensor(sd, OV9650_VREF, &i2c_data, 1); + if (err < 0) + return err; + *val = (i2c_data & 0x03) << 8; err = m5602_read_sensor(sd, OV9650_GAIN, &i2c_data, 1); @@ -478,11 +485,16 @@ int ov9650_set_gain(struct gspca_dev *gspca_dev, __s32 val) /* The 2 MSB */ /* Read the OV9650_VREF register first to avoid corrupting the VREF high and low bits */ - m5602_read_sensor(sd, OV9650_VREF, &i2c_data, 1); + err = m5602_read_sensor(sd, OV9650_VREF, &i2c_data, 1); + if (err < 0) + return err; + /* Mask away all uninteresting bits */ i2c_data = ((val & 0x0300) >> 2) | (i2c_data & 0x3F); err = m5602_write_sensor(sd, OV9650_VREF, &i2c_data, 1); + if (err < 0) + return err; /* The 8 LSBs */ i2c_data = val & 0xff; -- cgit v1.2.3 From 7ffa3278760242e14d9b05effc7219d1c64849ac Mon Sep 17 00:00:00 2001 From: Erik Andr?n Date: Sat, 3 Jan 2009 14:55:52 +0100 Subject: gspca - m5602-ov9650: Synthesize modesetting. From: Erik Andr?n Previously all resolution setting was done with precalculated tables. When the image is vflipped we need to adjust the alignment which would require another table. Now we can adjust the parameters on the fly instead. Priority: normal Signed-off-by: Erik Andr?n --- linux/drivers/media/video/gspca/m5602/m5602_core.c | 4 +- .../drivers/media/video/gspca/m5602/m5602_ov9650.c | 118 +++++++++++++-------- .../drivers/media/video/gspca/m5602/m5602_ov9650.h | 82 +------------- 3 files changed, 76 insertions(+), 128 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/m5602/m5602_core.c b/linux/drivers/media/video/gspca/m5602/m5602_core.c index bae7aa6f0..0d84a12d5 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_core.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_core.c @@ -51,7 +51,7 @@ int m5602_read_bridge(struct sd *sd, u8 address, u8 *i2c_data) address, *i2c_data); /* usb_control_msg(...) returns the number of bytes sent upon success, - mask that and return zero upon success instead*/ + mask that and return zero instead*/ return (err < 0) ? err : 0; } @@ -76,7 +76,7 @@ int m5602_write_bridge(struct sd *sd, u8 address, u8 i2c_data) 4, M5602_URB_MSG_TIMEOUT); /* usb_control_msg(...) returns the number of bytes sent upon success, - mask that and return zero upon success instead */ + mask that and return zero instead */ return (err < 0) ? err : 0; } diff --git a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c index e882385dd..dbcf61ad0 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c @@ -182,7 +182,7 @@ static struct v4l2_pix_format ov9650_modes[] = { 176 * 144, .bytesperline = 176, .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 0 + .priv = 9 }, { 320, 240, @@ -192,7 +192,7 @@ static struct v4l2_pix_format ov9650_modes[] = { 320 * 240, .bytesperline = 320, .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 0 + .priv = 8 }, { 352, 288, @@ -202,7 +202,7 @@ static struct v4l2_pix_format ov9650_modes[] = { 352 * 288, .bytesperline = 352, .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 0 + .priv = 9 }, { 640, 480, @@ -212,7 +212,7 @@ static struct v4l2_pix_format ov9650_modes[] = { 640 * 480, .bytesperline = 640, .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 0 + .priv = 9 } }; @@ -297,13 +297,22 @@ int ov9650_init(struct sd *sd) int ov9650_start(struct sd *sd) { + u8 data; int i, err = 0; struct cam *cam = &sd->gspca_dev.cam; + int width = cam->cam_mode[sd->gspca_dev.curr_mode].width; + int height = cam->cam_mode[sd->gspca_dev.curr_mode].height; + int ver_offs = cam->cam_mode[sd->gspca_dev.curr_mode].priv; + int hor_offs = OV9650_LEFT_OFFSET; + + if (width <= 320) + hor_offs /= 2; err = ov9650_init(sd); if (err < 0) return err; + /* Synthesize the vsync/hsync setup */ for (i = 0; i < ARRAY_SIZE(res_init_ov9650) && !err; i++) { if (res_init_ov9650[i][0] == BRIDGE) err = m5602_write_bridge(sd, res_init_ov9650[i][1], @@ -317,70 +326,87 @@ int ov9650_start(struct sd *sd) if (err < 0) return err; - switch (cam->cam_mode[sd->gspca_dev.curr_mode].width) { + err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, ((ver_offs >> 8) & 0xff)); + if (err < 0) + return err; + + err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, (ver_offs & 0xff)); + if (err < 0) + return err; + + err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, 0); + if (err < 0) + return err; + + err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, (height >> 8) & 0xff); + if (err < 0) + return err; + + err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, (height & 0xff)); + if (err < 0) + return err; + + for (i = 0; i < 2 && !err; i++) { + err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, 0); + } + if (err < 0) + return err; + + err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA, (hor_offs >> 8) & 0xff); + if (err < 0) + return err; + + err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA, hor_offs & 0xff); + if (err < 0) + return err; + + err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA, ((width + hor_offs) >> 8) & 0xff); + if (err < 0) + return err; + + err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA, ((width + hor_offs) & 0xff)); + if (err < 0) + return err; + + switch (width) { case 640: PDEBUG(D_V4L2, "Configuring camera for VGA mode"); - for (i = 0; i < ARRAY_SIZE(VGA_ov9650) && !err; i++) { - if (VGA_ov9650[i][0] == SENSOR) { - u8 data = VGA_ov9650[i][2]; + data = OV9650_VGA_SELECT | OV9650_RGB_SELECT | + OV9650_RAW_RGB_SELECT; + + err = m5602_write_sensor(sd, OV9650_COM7, &data, 1); - err = m5602_write_sensor(sd, - VGA_ov9650[i][1], &data, 1); - } else { - err = m5602_write_bridge(sd, VGA_ov9650[i][1], - VGA_ov9650[i][2]); - } - } break; case 352: PDEBUG(D_V4L2, "Configuring camera for CIF mode"); - for (i = 0; i < ARRAY_SIZE(CIF_ov9650) && !err; i++) { - if (CIF_ov9650[i][0] == SENSOR) { - u8 data = CIF_ov9650[i][2]; + data = OV9650_CIF_SELECT | OV9650_RGB_SELECT | + OV9650_RAW_RGB_SELECT; + + err = m5602_write_sensor(sd, OV9650_COM7, &data, 1); - err = m5602_write_sensor(sd, - CIF_ov9650[i][1], &data, 1); - } else { - err = m5602_write_bridge(sd, CIF_ov9650[i][1], - CIF_ov9650[i][2]); - } - } break; case 320: PDEBUG(D_V4L2, "Configuring camera for QVGA mode"); - for (i = 0; i < ARRAY_SIZE(QVGA_ov9650) && !err; i++) { - if (QVGA_ov9650[i][0] == SENSOR) { - u8 data = QVGA_ov9650[i][2]; + data = OV9650_QVGA_SELECT | OV9650_RGB_SELECT | + OV9650_RAW_RGB_SELECT; + + err = m5602_write_sensor(sd, OV9650_COM7, &data, 1); - err = m5602_write_sensor(sd, - QVGA_ov9650[i][1], &data, 1); - } else { - err = m5602_write_bridge(sd, QVGA_ov9650[i][1], - QVGA_ov9650[i][2]); - } - } break; case 176: PDEBUG(D_V4L2, "Configuring camera for QCIF mode"); - for (i = 0; i < ARRAY_SIZE(QCIF_ov9650) && !err; i++) { - if (QCIF_ov9650[i][0] == SENSOR) { - u8 data = QCIF_ov9650[i][2]; - err = m5602_write_sensor(sd, - QCIF_ov9650[i][1], &data, 1); - } else { - err = m5602_write_bridge(sd, QCIF_ov9650[i][1], - QCIF_ov9650[i][2]); - } - } - break; + data = OV9650_QCIF_SELECT | OV9650_RGB_SELECT | + OV9650_RAW_RGB_SELECT; + err = m5602_write_sensor(sd, OV9650_COM7, &data, 1); + break; } return err; } diff --git a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.h b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.h index ca0e42ee0..cc39d76e5 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.h @@ -120,6 +120,8 @@ #define OV9650_SOFT_SLEEP (1 << 4) #define OV9650_OUTPUT_DRIVE_2X (1 << 0) +#define OV9650_LEFT_OFFSET 0x62 + #define GAIN_DEFAULT 0x14 #define RED_GAIN_DEFAULT 0x70 #define BLUE_GAIN_DEFAULT 0x20 @@ -335,84 +337,4 @@ static const unsigned char res_init_ov9650[][3] = {BRIDGE, M5602_XB_SIG_INI, 0x01} }; -static const unsigned char VGA_ov9650[][3] = -{ - /* Moves the view window in a vertical orientation */ - {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x09}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x01}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0xe0}, /* 480 */ - {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, - {BRIDGE, M5602_XB_HSYNC_PARA, 0x00}, - {BRIDGE, M5602_XB_HSYNC_PARA, 0x62}, /* 98 */ - {BRIDGE, M5602_XB_HSYNC_PARA, 0x02}, /* 640 + 98 */ - {BRIDGE, M5602_XB_HSYNC_PARA, 0xe2}, - - {SENSOR, OV9650_COM7, OV9650_VGA_SELECT | - OV9650_RGB_SELECT | - OV9650_RAW_RGB_SELECT}, -}; - -static const unsigned char CIF_ov9650[][3] = -{ - /* Moves the view window in a vertical orientation */ - {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x09}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x01}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x20}, /* 288 */ - {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, - {BRIDGE, M5602_XB_HSYNC_PARA, 0x00}, - {BRIDGE, M5602_XB_HSYNC_PARA, 0x62}, /* 98 */ - {BRIDGE, M5602_XB_HSYNC_PARA, 0x01}, /* 352 + 98 */ - {BRIDGE, M5602_XB_HSYNC_PARA, 0xc2}, - - {SENSOR, OV9650_COM7, OV9650_CIF_SELECT | - OV9650_RGB_SELECT | - OV9650_RAW_RGB_SELECT}, -}; - -static const unsigned char QVGA_ov9650[][3] = -{ - /* Moves the view window in a vertical orientation */ - {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x08}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0xf0}, /* 240 */ - {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, - {BRIDGE, M5602_XB_HSYNC_PARA, 0x00}, - {BRIDGE, M5602_XB_HSYNC_PARA, 0x31}, /* 50 */ - {BRIDGE, M5602_XB_HSYNC_PARA, 0x01}, /* 320 + 50 */ - {BRIDGE, M5602_XB_HSYNC_PARA, 0x71}, - - {SENSOR, OV9650_COM7, OV9650_QVGA_SELECT | - OV9650_RGB_SELECT | - OV9650_RAW_RGB_SELECT}, -}; - -static const unsigned char QCIF_ov9650[][3] = -{ - /* Moves the view window in a vertical orientation */ - {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x09}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x90}, /* 144 */ - {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, - {BRIDGE, M5602_XB_HSYNC_PARA, 0x00}, - {BRIDGE, M5602_XB_HSYNC_PARA, 0x31}, /* 48 */ - {BRIDGE, M5602_XB_HSYNC_PARA, 0x00}, /* 176 + 49 */ - {BRIDGE, M5602_XB_HSYNC_PARA, 0xe1}, - - {SENSOR, OV9650_COM7, OV9650_QCIF_SELECT | - OV9650_RGB_SELECT | - OV9650_RAW_RGB_SELECT}, -}; - #endif -- cgit v1.2.3 From 434db44e6232d61ea1fc15b8d66e1a30a2ba67b6 Mon Sep 17 00:00:00 2001 From: Erik Andr?n Date: Sat, 3 Jan 2009 14:56:51 +0100 Subject: gspca - m5602-ov9650: Replace a magic constant with a define From: Erik Andr?n Priority: normal Signed-off-by: Erik Andr?n --- linux/drivers/media/video/gspca/m5602/m5602_ov9650.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.h b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.h index cc39d76e5..eafe4216b 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.h @@ -328,7 +328,7 @@ static const unsigned char power_down_ov9650[][3] = static const unsigned char res_init_ov9650[][3] = { - {SENSOR, OV9650_COM2, (1 << 0)}, + {SENSOR, OV9650_COM2, OV9650_OUTPUT_DRIVE_2X}, {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x82}, {BRIDGE, M5602_XB_LINE_OF_FRAME_L, 0x00}, -- cgit v1.2.3 From b91431d4d5b8bc688f4bbf37bfd838fb0a050e93 Mon Sep 17 00:00:00 2001 From: Erik Andr?n Date: Sat, 3 Jan 2009 16:10:11 +0100 Subject: gspca - m5602-ov9650: Add a disconnect hook, setup a ctrl cache ctrl. From: Erik Andr?n Reading and writing to a register doesn't always work reliably. Add a cache and ensure that it is deallocated properly upon module disconnect. Priority: normal Signed-off-by: Erik Andr?n --- .../drivers/media/video/gspca/m5602/m5602_bridge.h | 3 ++ linux/drivers/media/video/gspca/m5602/m5602_core.c | 13 ++++++- .../drivers/media/video/gspca/m5602/m5602_ov9650.c | 42 +++++++++++++++++----- .../drivers/media/video/gspca/m5602/m5602_ov9650.h | 2 ++ .../drivers/media/video/gspca/m5602/m5602_sensor.h | 3 ++ 5 files changed, 54 insertions(+), 9 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/m5602/m5602_bridge.h b/linux/drivers/media/video/gspca/m5602/m5602_bridge.h index de76a1613..8f1cea6fd 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_bridge.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_bridge.h @@ -117,6 +117,9 @@ struct sd { struct sd_desc *desc; + /* Sensor private data */ + void *sensor_priv; + /* The current frame's id, used to detect frame boundaries */ u8 frame_id; diff --git a/linux/drivers/media/video/gspca/m5602/m5602_core.c b/linux/drivers/media/video/gspca/m5602/m5602_core.c index 0d84a12d5..1aac2985f 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_core.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_core.c @@ -362,6 +362,17 @@ static int m5602_probe(struct usb_interface *intf, THIS_MODULE); } +void m5602_disconnect(struct usb_interface *intf) +{ + struct gspca_dev *gspca_dev = usb_get_intfdata(intf); + struct sd *sd = (struct sd *) gspca_dev; + + if (sd->sensor->disconnect) + sd->sensor->disconnect(sd); + + gspca_disconnect(intf); +} + static struct usb_driver sd_driver = { .name = MODULE_NAME, .id_table = m5602_table, @@ -370,7 +381,7 @@ static struct usb_driver sd_driver = { .suspend = gspca_suspend, .resume = gspca_resume, #endif - .disconnect = gspca_disconnect + .disconnect = m5602_disconnect }; /* -- module insert / remove -- */ diff --git a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c index dbcf61ad0..5099f5613 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c @@ -222,6 +222,7 @@ int ov9650_probe(struct sd *sd) { int err = 0; u8 prod_id = 0, ver_id = 0, i; + s32 *sensor_settings; if (force_sensor) { if (force_sensor == OV9650_SENSOR) { @@ -240,9 +241,10 @@ int ov9650_probe(struct sd *sd) u8 data = preinit_ov9650[i][2]; if (preinit_ov9650[i][0] == SENSOR) err = m5602_write_sensor(sd, - preinit_ov9650[i][1], &data, 1); + preinit_ov9650[i][1], &data, 1); else - err = m5602_write_bridge(sd, preinit_ov9650[i][1], data); + err = m5602_write_bridge(sd, + preinit_ov9650[i][1], data); } if (err < 0) @@ -262,10 +264,21 @@ int ov9650_probe(struct sd *sd) return -ENODEV; sensor_found: + + sensor_settings = kmalloc( + ARRAY_SIZE(ov9650_ctrls) * sizeof(s32), GFP_KERNEL); + if (!sensor_settings) + return -ENOMEM; + sd->gspca_dev.cam.cam_mode = ov9650_modes; sd->gspca_dev.cam.nmodes = ARRAY_SIZE(ov9650_modes); sd->desc->ctrls = ov9650_ctrls; sd->desc->nctrls = ARRAY_SIZE(ov9650_ctrls); + + for (i = 0; i < ARRAY_SIZE(ov9650_ctrls); i++) + sensor_settings[i] = ov9650_ctrls[i].qctrl.default_value; + sd->sensor_priv = sensor_settings; + return 0; } @@ -326,7 +339,8 @@ int ov9650_start(struct sd *sd) if (err < 0) return err; - err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, ((ver_offs >> 8) & 0xff)); + err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, + ((ver_offs >> 8) & 0xff)); if (err < 0) return err; @@ -346,13 +360,13 @@ int ov9650_start(struct sd *sd) if (err < 0) return err; - for (i = 0; i < 2 && !err; i++) { + for (i = 0; i < 2 && !err; i++) err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, 0); - } if (err < 0) return err; - err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA, (hor_offs >> 8) & 0xff); + err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA, + (hor_offs >> 8) & 0xff); if (err < 0) return err; @@ -360,11 +374,13 @@ int ov9650_start(struct sd *sd) if (err < 0) return err; - err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA, ((width + hor_offs) >> 8) & 0xff); + err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA, + ((width + hor_offs) >> 8) & 0xff); if (err < 0) return err; - err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA, ((width + hor_offs) & 0xff)); + err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA, + ((width + hor_offs) & 0xff)); if (err < 0) return err; @@ -433,6 +449,16 @@ int ov9650_power_down(struct sd *sd) return err; } +void ov9650_disconnect(struct sd *sd) +{ + ov9650_stop(sd); + ov9650_power_down(sd); + + sd->sensor = NULL; + + kfree(sd->sensor_priv); +} + int ov9650_get_exposure(struct gspca_dev *gspca_dev, __s32 *val) { struct sd *sd = (struct sd *) gspca_dev; diff --git a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.h b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.h index eafe4216b..1f27a857b 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.h @@ -138,6 +138,7 @@ int ov9650_init(struct sd *sd); int ov9650_start(struct sd *sd); int ov9650_stop(struct sd *sd); int ov9650_power_down(struct sd *sd); +void ov9650_disconnect(struct sd *sd); int ov9650_set_exposure(struct gspca_dev *gspca_dev, __s32 val); int ov9650_get_exposure(struct gspca_dev *gspca_dev, __s32 *val); @@ -167,6 +168,7 @@ const static struct m5602_sensor ov9650 = { .start = ov9650_start, .stop = ov9650_stop, .power_down = ov9650_power_down, + .disconnect = ov9650_disconnect, }; static const unsigned char preinit_ov9650[][3] = diff --git a/linux/drivers/media/video/gspca/m5602/m5602_sensor.h b/linux/drivers/media/video/gspca/m5602/m5602_sensor.h index 5c8fb7aba..0d3026936 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_sensor.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_sensor.h @@ -59,6 +59,9 @@ struct m5602_sensor { /* Executed when the camera ends to send data */ int (*stop)(struct sd *sd); + /* Executed when the device is disconnected */ + void (*disconnect)(struct sd *sd); + /* Performs a power down sequence */ int (*power_down)(struct sd *sd); }; -- cgit v1.2.3 From b053c076c20b54aac032c86390a24d45ee738a3c Mon Sep 17 00:00:00 2001 From: Erik Andr?n Date: Sat, 3 Jan 2009 17:58:12 +0100 Subject: gspca - m5602-ov9650: Use the local ctrl cache. Adjust image on vflip. From: Erik Andr?n Priority: normal Signed-off-by: Erik Andr?n --- .../drivers/media/video/gspca/m5602/m5602_ov9650.c | 189 ++++++++++----------- 1 file changed, 93 insertions(+), 96 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c index 5099f5613..e19eee07d 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c @@ -71,6 +71,7 @@ static }; const static struct ctrl ov9650_ctrls[] = { +#define EXPOSURE_IDX 0 { { .id = V4L2_CID_EXPOSURE, @@ -84,7 +85,9 @@ const static struct ctrl ov9650_ctrls[] = { }, .set = ov9650_set_exposure, .get = ov9650_get_exposure - }, { + }, +#define GAIN_IDX 1 + { { .id = V4L2_CID_GAIN, .type = V4L2_CTRL_TYPE_INTEGER, @@ -97,7 +100,9 @@ const static struct ctrl ov9650_ctrls[] = { }, .set = ov9650_set_gain, .get = ov9650_get_gain - }, { + }, +#define RED_BALANCE_IDX 2 + { { .type = V4L2_CTRL_TYPE_INTEGER, .name = "red balance", @@ -109,7 +114,9 @@ const static struct ctrl ov9650_ctrls[] = { }, .set = ov9650_set_red_balance, .get = ov9650_get_red_balance - }, { + }, +#define BLUE_BALANCE_IDX 3 + { { .type = V4L2_CTRL_TYPE_INTEGER, .name = "blue balance", @@ -121,7 +128,9 @@ const static struct ctrl ov9650_ctrls[] = { }, .set = ov9650_set_blue_balance, .get = ov9650_get_blue_balance - }, { + }, +#define HFLIP_IDX 4 + { { .id = V4L2_CID_HFLIP, .type = V4L2_CTRL_TYPE_BOOLEAN, @@ -133,7 +142,9 @@ const static struct ctrl ov9650_ctrls[] = { }, .set = ov9650_set_hflip, .get = ov9650_get_hflip - }, { + }, +#define VFLIP_IDX 5 + { { .id = V4L2_CID_VFLIP, .type = V4L2_CTRL_TYPE_BOOLEAN, @@ -145,7 +156,9 @@ const static struct ctrl ov9650_ctrls[] = { }, .set = ov9650_set_vflip, .get = ov9650_get_vflip - }, { + }, +#define AUTO_WHITE_BALANCE_IDX 6 + { { .id = V4L2_CID_AUTO_WHITE_BALANCE, .type = V4L2_CTRL_TYPE_BOOLEAN, @@ -157,7 +170,9 @@ const static struct ctrl ov9650_ctrls[] = { }, .set = ov9650_set_auto_white_balance, .get = ov9650_get_auto_white_balance - }, { + }, +#define AUTO_GAIN_CTRL_IDX 7 + { { .id = V4L2_CID_AUTOGAIN, .type = V4L2_CTRL_TYPE_BOOLEAN, @@ -313,18 +328,19 @@ int ov9650_start(struct sd *sd) u8 data; int i, err = 0; struct cam *cam = &sd->gspca_dev.cam; + s32 *sensor_settings = sd->sensor_priv; + int width = cam->cam_mode[sd->gspca_dev.curr_mode].width; int height = cam->cam_mode[sd->gspca_dev.curr_mode].height; int ver_offs = cam->cam_mode[sd->gspca_dev.curr_mode].priv; int hor_offs = OV9650_LEFT_OFFSET; + if (sensor_settings[VFLIP_IDX]) + ver_offs--; + if (width <= 320) hor_offs /= 2; - err = ov9650_init(sd); - if (err < 0) - return err; - /* Synthesize the vsync/hsync setup */ for (i = 0; i < ARRAY_SIZE(res_init_ov9650) && !err; i++) { if (res_init_ov9650[i][0] == BRIDGE) @@ -462,32 +478,23 @@ void ov9650_disconnect(struct sd *sd) int ov9650_get_exposure(struct gspca_dev *gspca_dev, __s32 *val) { struct sd *sd = (struct sd *) gspca_dev; - u8 i2c_data; - int err; - - err = m5602_read_sensor(sd, OV9650_AECH, &i2c_data, 1); - if (err < 0) - return err; - *val |= (i2c_data << 2); - - err = m5602_read_sensor(sd, OV9650_AECHM, &i2c_data, 1); - if (err < 0) - return err; - *val |= (i2c_data & 0x3f) << 10; + s32 *sensor_settings = sd->sensor_priv; + *val = sensor_settings[EXPOSURE_IDX]; PDEBUG(D_V4L2, "Read exposure %d", *val); - - return err; + return 0; } int ov9650_set_exposure(struct gspca_dev *gspca_dev, __s32 val) { struct sd *sd = (struct sd *) gspca_dev; + s32 *sensor_settings = sd->sensor_priv; u8 i2c_data; int err; - PDEBUG(D_V4L2, "Set exposure to %d", - val & 0xffff); + PDEBUG(D_V4L2, "Set exposure to %d", val); + + sensor_settings[EXPOSURE_IDX] = val; /* The 6 MSBs */ i2c_data = (val >> 10) & 0x3f; @@ -512,20 +519,12 @@ int ov9650_set_exposure(struct gspca_dev *gspca_dev, __s32 val) int ov9650_get_gain(struct gspca_dev *gspca_dev, __s32 *val) { - int err; - u8 i2c_data; struct sd *sd = (struct sd *) gspca_dev; + s32 *sensor_settings = sd->sensor_priv; - err = m5602_read_sensor(sd, OV9650_VREF, &i2c_data, 1); - if (err < 0) - return err; - - *val = (i2c_data & 0x03) << 8; - - err = m5602_read_sensor(sd, OV9650_GAIN, &i2c_data, 1); - *val |= i2c_data; + *val = sensor_settings[GAIN_IDX]; PDEBUG(D_V4L2, "Read gain %d", *val); - return err; + return 0; } int ov9650_set_gain(struct gspca_dev *gspca_dev, __s32 val) @@ -533,6 +532,11 @@ int ov9650_set_gain(struct gspca_dev *gspca_dev, __s32 val) int err; u8 i2c_data; struct sd *sd = (struct sd *) gspca_dev; + s32 *sensor_settings = sd->sensor_priv; + + PDEBUG(D_V4L2, "Setting gain to %d", val); + + sensor_settings[GAIN_IDX] = val; /* The 2 MSB */ /* Read the OV9650_VREF register first to avoid @@ -556,16 +560,12 @@ int ov9650_set_gain(struct gspca_dev *gspca_dev, __s32 val) int ov9650_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val) { - int err; - u8 i2c_data; struct sd *sd = (struct sd *) gspca_dev; + s32 *sensor_settings = sd->sensor_priv; - err = m5602_read_sensor(sd, OV9650_RED, &i2c_data, 1); - *val = i2c_data; - + *val = sensor_settings[RED_BALANCE_IDX]; PDEBUG(D_V4L2, "Read red gain %d", *val); - - return err; + return 0; } int ov9650_set_red_balance(struct gspca_dev *gspca_dev, __s32 val) @@ -573,9 +573,11 @@ int ov9650_set_red_balance(struct gspca_dev *gspca_dev, __s32 val) int err; u8 i2c_data; struct sd *sd = (struct sd *) gspca_dev; + s32 *sensor_settings = sd->sensor_priv; - PDEBUG(D_V4L2, "Set red gain to %d", - val & 0xff); + PDEBUG(D_V4L2, "Set red gain to %d", val); + + sensor_settings[RED_BALANCE_IDX] = val; i2c_data = val & 0xff; err = m5602_write_sensor(sd, OV9650_RED, &i2c_data, 1); @@ -585,16 +587,13 @@ int ov9650_set_red_balance(struct gspca_dev *gspca_dev, __s32 val) int ov9650_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val) { - int err; - u8 i2c_data; struct sd *sd = (struct sd *) gspca_dev; + s32 *sensor_settings = sd->sensor_priv; - err = m5602_read_sensor(sd, OV9650_BLUE, &i2c_data, 1); - *val = i2c_data; - + *val = sensor_settings[BLUE_BALANCE_IDX]; PDEBUG(D_V4L2, "Read blue gain %d", *val); - return err; + return 0; } int ov9650_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val) @@ -602,9 +601,11 @@ int ov9650_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val) int err; u8 i2c_data; struct sd *sd = (struct sd *) gspca_dev; + s32 *sensor_settings = sd->sensor_priv; + + PDEBUG(D_V4L2, "Set blue gain to %d", val); - PDEBUG(D_V4L2, "Set blue gain to %d", - val & 0xff); + sensor_settings[BLUE_BALANCE_IDX] = val; i2c_data = val & 0xff; err = m5602_write_sensor(sd, OV9650_BLUE, &i2c_data, 1); @@ -614,18 +615,12 @@ int ov9650_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val) int ov9650_get_hflip(struct gspca_dev *gspca_dev, __s32 *val) { - int err; - u8 i2c_data; struct sd *sd = (struct sd *) gspca_dev; - - err = m5602_read_sensor(sd, OV9650_MVFP, &i2c_data, 1); - if (dmi_check_system(ov9650_flip_dmi_table)) - *val = ((i2c_data & OV9650_HFLIP) >> 5) ? 0 : 1; - else - *val = (i2c_data & OV9650_HFLIP) >> 5; + s32 *sensor_settings = sd->sensor_priv; + *val = sensor_settings[HFLIP_IDX]; PDEBUG(D_V4L2, "Read horizontal flip %d", *val); - return err; + return 0; } int ov9650_set_hflip(struct gspca_dev *gspca_dev, __s32 val) @@ -633,8 +628,11 @@ int ov9650_set_hflip(struct gspca_dev *gspca_dev, __s32 val) int err; u8 i2c_data; struct sd *sd = (struct sd *) gspca_dev; + s32 *sensor_settings = sd->sensor_priv; PDEBUG(D_V4L2, "Set horizontal flip to %d", val); + + sensor_settings[HFLIP_IDX] = val; err = m5602_read_sensor(sd, OV9650_MVFP, &i2c_data, 1); if (err < 0) return err; @@ -653,18 +651,13 @@ int ov9650_set_hflip(struct gspca_dev *gspca_dev, __s32 val) int ov9650_get_vflip(struct gspca_dev *gspca_dev, __s32 *val) { - int err; - u8 i2c_data; struct sd *sd = (struct sd *) gspca_dev; + s32 *sensor_settings = sd->sensor_priv; - err = m5602_read_sensor(sd, OV9650_MVFP, &i2c_data, 1); - if (dmi_check_system(ov9650_flip_dmi_table)) - *val = ((i2c_data & 0x10) >> 4) ? 0 : 1; - else - *val = (i2c_data & 0x10) >> 4; + *val = sensor_settings[VFLIP_IDX]; PDEBUG(D_V4L2, "Read vertical flip %d", *val); - return err; + return 0; } int ov9650_set_vflip(struct gspca_dev *gspca_dev, __s32 val) @@ -672,8 +665,11 @@ int ov9650_set_vflip(struct gspca_dev *gspca_dev, __s32 val) int err; u8 i2c_data; struct sd *sd = (struct sd *) gspca_dev; + s32 *sensor_settings = sd->sensor_priv; PDEBUG(D_V4L2, "Set vertical flip to %d", val); + + sensor_settings[VFLIP_IDX] = val; err = m5602_read_sensor(sd, OV9650_MVFP, &i2c_data, 1); if (err < 0) return err; @@ -687,25 +683,24 @@ int ov9650_set_vflip(struct gspca_dev *gspca_dev, __s32 val) err = m5602_write_sensor(sd, OV9650_MVFP, &i2c_data, 1); + if (err < 0) + return err; + + if (gspca_dev->streaming) + err = ov9650_start(sd); + return err; } int ov9650_get_brightness(struct gspca_dev *gspca_dev, __s32 *val) { - int err; - u8 i2c_data; struct sd *sd = (struct sd *) gspca_dev; + s32 *sensor_settings = sd->sensor_priv; - err = m5602_read_sensor(sd, OV9650_VREF, &i2c_data, 1); - if (err < 0) - return err; - *val = (i2c_data & 0x03) << 8; - - err = m5602_read_sensor(sd, OV9650_GAIN, &i2c_data, 1); - *val |= i2c_data; + *val = sensor_settings[GAIN_IDX]; PDEBUG(D_V4L2, "Read gain %d", *val); - return err; + return 0; } int ov9650_set_brightness(struct gspca_dev *gspca_dev, __s32 val) @@ -713,8 +708,11 @@ int ov9650_set_brightness(struct gspca_dev *gspca_dev, __s32 val) int err; u8 i2c_data; struct sd *sd = (struct sd *) gspca_dev; + s32 *sensor_settings = sd->sensor_priv; + + PDEBUG(D_V4L2, "Set gain to %d", val); - PDEBUG(D_V4L2, "Set gain to %d", val & 0x3ff); + sensor_settings[GAIN_IDX] = val; /* Read the OV9650_VREF register first to avoid corrupting the VREF high and low bits */ @@ -737,15 +735,11 @@ int ov9650_set_brightness(struct gspca_dev *gspca_dev, __s32 val) int ov9650_get_auto_white_balance(struct gspca_dev *gspca_dev, __s32 *val) { - int err; - u8 i2c_data; struct sd *sd = (struct sd *) gspca_dev; + s32 *sensor_settings = sd->sensor_priv; - err = m5602_read_sensor(sd, OV9650_COM8, &i2c_data, 1); - *val = (i2c_data & OV9650_AWB_EN) >> 1; - PDEBUG(D_V4L2, "Read auto white balance %d", *val); - - return err; + *val = sensor_settings[AUTO_WHITE_BALANCE_IDX]; + return 0; } int ov9650_set_auto_white_balance(struct gspca_dev *gspca_dev, __s32 val) @@ -753,8 +747,11 @@ int ov9650_set_auto_white_balance(struct gspca_dev *gspca_dev, __s32 val) int err; u8 i2c_data; struct sd *sd = (struct sd *) gspca_dev; + s32 *sensor_settings = sd->sensor_priv; PDEBUG(D_V4L2, "Set auto white balance to %d", val); + + sensor_settings[AUTO_WHITE_BALANCE_IDX] = val; err = m5602_read_sensor(sd, OV9650_COM8, &i2c_data, 1); if (err < 0) return err; @@ -767,15 +764,12 @@ int ov9650_set_auto_white_balance(struct gspca_dev *gspca_dev, __s32 val) int ov9650_get_auto_gain(struct gspca_dev *gspca_dev, __s32 *val) { - int err; - u8 i2c_data; struct sd *sd = (struct sd *) gspca_dev; + s32 *sensor_settings = sd->sensor_priv; - err = m5602_read_sensor(sd, OV9650_COM8, &i2c_data, 1); - *val = (i2c_data & OV9650_AGC_EN) >> 2; + *val = sensor_settings[AUTO_GAIN_CTRL_IDX]; PDEBUG(D_V4L2, "Read auto gain control %d", *val); - - return err; + return 0; } int ov9650_set_auto_gain(struct gspca_dev *gspca_dev, __s32 val) @@ -783,8 +777,11 @@ int ov9650_set_auto_gain(struct gspca_dev *gspca_dev, __s32 val) int err; u8 i2c_data; struct sd *sd = (struct sd *) gspca_dev; + s32 *sensor_settings = sd->sensor_priv; PDEBUG(D_V4L2, "Set auto gain control to %d", val); + + sensor_settings[AUTO_GAIN_CTRL_IDX] = val; err = m5602_read_sensor(sd, OV9650_COM8, &i2c_data, 1); if (err < 0) return err; -- cgit v1.2.3 From 6b39a5bda8153667efed18a8ef5e7d39c421c73a Mon Sep 17 00:00:00 2001 From: Erik Andr?n Date: Sun, 4 Jan 2009 08:52:50 +0100 Subject: gspca - m5602: Move the vflip quirk to probe stage. From: Erik Andr?n The vflip quirk is better checked at probe time as it's only needed once. Also add an extra reset at init time to resolve a suspend to ram regression. Priority: normal Signed-off-by: Erik Andr?n --- .../drivers/media/video/gspca/m5602/m5602_ov9650.c | 63 ++++++++++++++-------- .../drivers/media/video/gspca/m5602/m5602_ov9650.h | 4 ++ 2 files changed, 46 insertions(+), 21 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c index e19eee07d..1e0652bd6 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c @@ -67,7 +67,7 @@ static DMI_MATCH(DMI_PRODUCT_NAME, "Aurora m9700") } }, - { } + {} }; const static struct ctrl ov9650_ctrls[] = { @@ -251,7 +251,7 @@ int ov9650_probe(struct sd *sd) info("Probing for an ov9650 sensor"); - /* Run the pre-init to actually probe the unit */ + /* Run the pre-init before probing the sensor */ for (i = 0; i < ARRAY_SIZE(preinit_ov9650) && !err; i++) { u8 data = preinit_ov9650[i][2]; if (preinit_ov9650[i][0] == SENSOR) @@ -275,11 +275,9 @@ int ov9650_probe(struct sd *sd) info("Detected an ov9650 sensor"); goto sensor_found; } - return -ENODEV; sensor_found: - sensor_settings = kmalloc( ARRAY_SIZE(ov9650_ctrls) * sizeof(s32), GFP_KERNEL); if (!sensor_settings) @@ -294,6 +292,11 @@ sensor_found: sensor_settings[i] = ov9650_ctrls[i].qctrl.default_value; sd->sensor_priv = sensor_settings; + if (dmi_check_system(ov9650_flip_dmi_table) && !err) { + info("vflip quirk active"); + sensor_settings[VFLIP_IDX] = 1; + } + return 0; } @@ -301,6 +304,7 @@ int ov9650_init(struct sd *sd) { int i, err = 0; u8 data; + s32 *sensor_settings = sd->sensor_priv; if (dump_sensor) ov9650_dump_registers(sd); @@ -314,11 +318,35 @@ int ov9650_init(struct sd *sd) err = m5602_write_bridge(sd, init_ov9650[i][1], data); } - if (dmi_check_system(ov9650_flip_dmi_table) && !err) { - info("vflip quirk active"); - data = 0x30; - err = m5602_write_sensor(sd, OV9650_MVFP, &data, 1); - } + err = ov9650_set_exposure(&sd->gspca_dev, sensor_settings[EXPOSURE_IDX]); + if (err < 0) + return err; + + err = ov9650_set_gain(&sd->gspca_dev, sensor_settings[GAIN_IDX]); + if (err < 0) + return err; + + err = ov9650_set_red_balance(&sd->gspca_dev, sensor_settings[RED_BALANCE_IDX]); + if (err < 0) + return err; + + err = ov9650_set_blue_balance(&sd->gspca_dev, sensor_settings[BLUE_BALANCE_IDX]); + if (err < 0) + return err; + + err = ov9650_set_hflip(&sd->gspca_dev, sensor_settings[HFLIP_IDX]); + if (err < 0) + return err; + + err = ov9650_set_vflip(&sd->gspca_dev, sensor_settings[VFLIP_IDX]); + if (err < 0) + return err; + + err = ov9650_set_auto_white_balance(&sd->gspca_dev, sensor_settings[AUTO_WHITE_BALANCE_IDX]); + if (err < 0) + return err; + + err = ov9650_set_auto_gain(&sd->gspca_dev, sensor_settings[AUTO_GAIN_CTRL_IDX]); return err; } @@ -341,6 +369,9 @@ int ov9650_start(struct sd *sd) if (width <= 320) hor_offs /= 2; + if (err < 0) + return err; + /* Synthesize the vsync/hsync setup */ for (i = 0; i < ARRAY_SIZE(res_init_ov9650) && !err; i++) { if (res_init_ov9650[i][0] == BRIDGE) @@ -637,12 +668,7 @@ int ov9650_set_hflip(struct gspca_dev *gspca_dev, __s32 val) if (err < 0) return err; - if (dmi_check_system(ov9650_flip_dmi_table)) - i2c_data = ((i2c_data & 0xdf) | - (((val ? 0 : 1) & 0x01) << 5)); - else - i2c_data = ((i2c_data & 0xdf) | - ((val & 0x01) << 5)); + i2c_data = ((i2c_data & 0xdf) | ((val & 0x01) << 5)); err = m5602_write_sensor(sd, OV9650_MVFP, &i2c_data, 1); @@ -674,12 +700,7 @@ int ov9650_set_vflip(struct gspca_dev *gspca_dev, __s32 val) if (err < 0) return err; - if (dmi_check_system(ov9650_flip_dmi_table)) - i2c_data = ((i2c_data & 0xef) | - (((val ? 0 : 1) & 0x01) << 4)); - else - i2c_data = ((i2c_data & 0xef) | - ((val & 0x01) << 4)); + i2c_data = ((i2c_data & 0xef) | ((val & 0x01) << 4)); err = m5602_write_sensor(sd, OV9650_MVFP, &i2c_data, 1); diff --git a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.h b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.h index 1f27a857b..fcc54e4c0 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.h @@ -218,6 +218,10 @@ static const unsigned char init_ov9650[][3] = /* Reset chip */ {SENSOR, OV9650_COM7, OV9650_REGISTER_RESET}, + /* One extra reset is needed in order to make the sensor behave + properly when resuming from ram */ + {SENSOR, OV9650_COM7, OV9650_REGISTER_RESET}, + /* Enable double clock */ {SENSOR, OV9650_CLKRC, 0x80}, /* Do something out of spec with the power */ -- cgit v1.2.3 From 847500330c44313131e8d7bf3956da4ed569462a Mon Sep 17 00:00:00 2001 From: Erik Andr?n Date: Sun, 4 Jan 2009 11:28:42 +0100 Subject: gspca - m5602: Don't touch hflip/vflip register on Read/Modify/Write From: Erik Andr?n Touching the hflip/vflip register while doing the read/modify/write corrupts the image. Just read from the sensor ctrl cache instead and all is good. Priority: normal Signed-off-by: Erik Andr?n --- linux/drivers/media/video/gspca/m5602/m5602_ov9650.c | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c index 1e0652bd6..583d8a086 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c @@ -664,12 +664,7 @@ int ov9650_set_hflip(struct gspca_dev *gspca_dev, __s32 val) PDEBUG(D_V4L2, "Set horizontal flip to %d", val); sensor_settings[HFLIP_IDX] = val; - err = m5602_read_sensor(sd, OV9650_MVFP, &i2c_data, 1); - if (err < 0) - return err; - - i2c_data = ((i2c_data & 0xdf) | ((val & 0x01) << 5)); - + i2c_data = ((val & 0x01) << 5) | (sensor_settings[VFLIP_IDX] << 4); err = m5602_write_sensor(sd, OV9650_MVFP, &i2c_data, 1); return err; @@ -694,19 +689,14 @@ int ov9650_set_vflip(struct gspca_dev *gspca_dev, __s32 val) s32 *sensor_settings = sd->sensor_priv; PDEBUG(D_V4L2, "Set vertical flip to %d", val); - sensor_settings[VFLIP_IDX] = val; - err = m5602_read_sensor(sd, OV9650_MVFP, &i2c_data, 1); - if (err < 0) - return err; - - i2c_data = ((i2c_data & 0xef) | ((val & 0x01) << 4)); + i2c_data = ((val & 0x01) << 4) | (sensor_settings[VFLIP_IDX] << 5); err = m5602_write_sensor(sd, OV9650_MVFP, &i2c_data, 1); - if (err < 0) return err; + /* When vflip is toggled we need to readjust the bridge hsync/vsync */ if (gspca_dev->streaming) err = ov9650_start(sd); -- cgit v1.2.3 From e5da3241f55625c20de4bcc0e12da75f9ffd68fa Mon Sep 17 00:00:00 2001 From: Erik Andr?n Date: Sun, 4 Jan 2009 11:35:27 +0100 Subject: gspca - m5602: Minor cleanups From: Erik Andr?n Remove an unnecessary error check and reorder some code. Priority: normal Signed-off-by: Erik Andr?n --- linux/drivers/media/video/gspca/m5602/m5602_ov9650.c | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c index 583d8a086..86e4719fb 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c @@ -347,7 +347,6 @@ int ov9650_init(struct sd *sd) return err; err = ov9650_set_auto_gain(&sd->gspca_dev, sensor_settings[AUTO_GAIN_CTRL_IDX]); - return err; } @@ -369,9 +368,6 @@ int ov9650_start(struct sd *sd) if (width <= 320) hor_offs /= 2; - if (err < 0) - return err; - /* Synthesize the vsync/hsync setup */ for (i = 0; i < ARRAY_SIZE(res_init_ov9650) && !err; i++) { if (res_init_ov9650[i][0] == BRIDGE) @@ -437,9 +433,7 @@ int ov9650_start(struct sd *sd) data = OV9650_VGA_SELECT | OV9650_RGB_SELECT | OV9650_RAW_RGB_SELECT; - err = m5602_write_sensor(sd, OV9650_COM7, &data, 1); - break; case 352: @@ -447,9 +441,7 @@ int ov9650_start(struct sd *sd) data = OV9650_CIF_SELECT | OV9650_RGB_SELECT | OV9650_RAW_RGB_SELECT; - err = m5602_write_sensor(sd, OV9650_COM7, &data, 1); - break; case 320: @@ -457,9 +449,7 @@ int ov9650_start(struct sd *sd) data = OV9650_QVGA_SELECT | OV9650_RGB_SELECT | OV9650_RAW_RGB_SELECT; - err = m5602_write_sensor(sd, OV9650_COM7, &data, 1); - break; case 176: @@ -467,7 +457,6 @@ int ov9650_start(struct sd *sd) data = OV9650_QCIF_SELECT | OV9650_RGB_SELECT | OV9650_RAW_RGB_SELECT; - err = m5602_write_sensor(sd, OV9650_COM7, &data, 1); break; } @@ -502,7 +491,6 @@ void ov9650_disconnect(struct sd *sd) ov9650_power_down(sd); sd->sensor = NULL; - kfree(sd->sensor_priv); } @@ -526,7 +514,6 @@ int ov9650_set_exposure(struct gspca_dev *gspca_dev, __s32 val) PDEBUG(D_V4L2, "Set exposure to %d", val); sensor_settings[EXPOSURE_IDX] = val; - /* The 6 MSBs */ i2c_data = (val >> 10) & 0x3f; err = m5602_write_sensor(sd, OV9650_AECHM, @@ -544,7 +531,6 @@ int ov9650_set_exposure(struct gspca_dev *gspca_dev, __s32 val) /* The 2 LSBs */ i2c_data = val & 0x03; err = m5602_write_sensor(sd, OV9650_COM1, &i2c_data, 1); - return err; } @@ -612,7 +598,6 @@ int ov9650_set_red_balance(struct gspca_dev *gspca_dev, __s32 val) i2c_data = val & 0xff; err = m5602_write_sensor(sd, OV9650_RED, &i2c_data, 1); - return err; } @@ -640,7 +625,6 @@ int ov9650_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val) i2c_data = val & 0xff; err = m5602_write_sensor(sd, OV9650_BLUE, &i2c_data, 1); - return err; } @@ -648,9 +632,9 @@ int ov9650_get_hflip(struct gspca_dev *gspca_dev, __s32 *val) { struct sd *sd = (struct sd *) gspca_dev; s32 *sensor_settings = sd->sensor_priv; + *val = sensor_settings[HFLIP_IDX]; PDEBUG(D_V4L2, "Read horizontal flip %d", *val); - return 0; } -- cgit v1.2.3 From 2f9645d66b4695de43b5545590cfc07f7319e56e Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Thu, 12 Mar 2009 08:40:19 +0100 Subject: gspca - t613: Do sensor reset only for sensor om6802. From: Jean-Francois Moine Priority: normal Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/t613.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/t613.c b/linux/drivers/media/video/gspca/t613.c index f6ff3e1ea..1b58b65fb 100644 --- a/linux/drivers/media/video/gspca/t613.c +++ b/linux/drivers/media/video/gspca/t613.c @@ -697,7 +697,7 @@ static int sd_init(struct gspca_dev *gspca_dev) return -EINVAL; } - if (sd->sensor != SENSOR_OTHER) { + if (sd->sensor == SENSOR_OM6802) { reg_w_buf(gspca_dev, n1, sizeof n1); i = 5; while (--i >= 0) { -- cgit v1.2.3 From fc0db02c3b9278afb23eb9a2045e4ed008249f23 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Fri, 27 Mar 2009 19:57:46 +0100 Subject: gspca - mr97310a: Return good error code in mod_init. From: Alexey Klimov Priority: normal Signed-off-by: Alexey Klimov Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/mr97310a.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/mr97310a.c b/linux/drivers/media/video/gspca/mr97310a.c index 2a901a4a6..f9da55b20 100644 --- a/linux/drivers/media/video/gspca/mr97310a.c +++ b/linux/drivers/media/video/gspca/mr97310a.c @@ -347,8 +347,11 @@ static struct usb_driver sd_driver = { /* -- module insert / remove -- */ static int __init sd_mod_init(void) { - if (usb_register(&sd_driver) < 0) - return -1; + int ret; + + ret = usb_register(&sd_driver); + if (ret < 0) + return ret; PDEBUG(D_PROBE, "registered"); return 0; } -- cgit v1.2.3 From 4ef69f4186e06be9b9103dbc069bf0c530f4a338 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Fri, 27 Mar 2009 20:08:20 +0100 Subject: gspca - main: Use usb interface as parent. From: Hans de Goede Priority: normal Signed-off-by: Hans de Goede Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/gspca.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/gspca.c b/linux/drivers/media/video/gspca/gspca.c index cfd27161b..b12974d5e 100644 --- a/linux/drivers/media/video/gspca/gspca.c +++ b/linux/drivers/media/video/gspca/gspca.c @@ -1955,7 +1955,7 @@ int gspca_dev_probe(struct usb_interface *intf, /* init video stuff */ memcpy(&gspca_dev->vdev, &gspca_template, sizeof gspca_template); - gspca_dev->vdev.parent = &dev->dev; + gspca_dev->vdev.parent = &intf->dev; gspca_dev->module = module; gspca_dev->present = 1; ret = video_register_device(&gspca_dev->vdev, -- cgit v1.2.3 From 7bda6bbcb88a568faee38f32c3cf347fa167a44e Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Sun, 5 Apr 2009 09:01:13 +0200 Subject: gspca - zc3xx: Bad probe of many webcams since adcm2700 addition. From: Jean-Francois Moine Priority: normal Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/zc3xx.c | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/zc3xx.c b/linux/drivers/media/video/gspca/zc3xx.c index a90b3b0d4..18a7ca2b6 100644 --- a/linux/drivers/media/video/gspca/zc3xx.c +++ b/linux/drivers/media/video/gspca/zc3xx.c @@ -6897,7 +6897,6 @@ static const struct sensor_by_chipset_revision chipset_revision_sensor[] = { {0x8001, 0x13}, {0x8000, 0x14}, /* CS2102K */ {0x8400, 0x15}, /* TAS5130K */ - {0x4001, 0x16}, /* ADCM2700 */ }; static int vga_3wr_probe(struct gspca_dev *gspca_dev) @@ -6933,12 +6932,15 @@ static int vga_3wr_probe(struct gspca_dev *gspca_dev) retword |= reg_r(gspca_dev, 0x000a); PDEBUG(D_PROBE, "probe 3wr vga 1 0x%04x", retword); reg_r(gspca_dev, 0x0010); - /* this is tested only once anyway */ - for (i = 0; i < ARRAY_SIZE(chipset_revision_sensor); i++) { - if (chipset_revision_sensor[i].revision == retword) { - sd->chip_revision = retword; - send_unknown(dev, SENSOR_PB0330); - return chipset_revision_sensor[i].internal_sensor_id; + /* value 0x4001 is meaningless */ + if (retword != 0x4001) { + for (i = 0; i < ARRAY_SIZE(chipset_revision_sensor); i++) { + if (chipset_revision_sensor[i].revision == retword) { + sd->chip_revision = retword; + send_unknown(dev, SENSOR_PB0330); + return chipset_revision_sensor[i] + .internal_sensor_id; + } } } @@ -7009,12 +7011,12 @@ static int vga_3wr_probe(struct gspca_dev *gspca_dev) reg_w(dev, 0x01, 0x0001); reg_w(dev, 0x03, 0x0012); reg_w(dev, 0x01, 0x0012); - reg_w(dev, 0x05, 0x0001); + reg_w(dev, 0x05, 0x0012); reg_w(dev, 0xd3, 0x008b); retword = i2c_read(gspca_dev, 0x01); if (retword != 0) { PDEBUG(D_PROBE, "probe 3wr vga type 0a ? ret: %04x", retword); - return retword; + return 0x16; /* adcm2700 (6100/6200) */ } return -1; } -- cgit v1.2.3 From 29da71214c388ee2636e73adecb0d781d6f294c8 Mon Sep 17 00:00:00 2001 From: Erik Andr?n Date: Sun, 4 Jan 2009 20:52:48 +0100 Subject: gspca - m5602-mt9m111: Convert the mt9m111 to use a v4l2 ctrl cache From: Erik Andr?n Priority: normal Signed-off-by: Erik Andr?n --- .../media/video/gspca/m5602/m5602_mt9m111.c | 65 +++++++++++++--------- .../media/video/gspca/m5602/m5602_mt9m111.h | 4 +- 2 files changed, 43 insertions(+), 26 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.c b/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.c index 7d3f9e348..43791a6b8 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.c @@ -32,6 +32,7 @@ static struct v4l2_pix_format mt9m111_modes[] = { }; const static struct ctrl mt9m111_ctrls[] = { +#define VFLIP_IDX 0 { { .id = V4L2_CID_VFLIP, @@ -44,7 +45,9 @@ const static struct ctrl mt9m111_ctrls[] = { }, .set = mt9m111_set_vflip, .get = mt9m111_get_vflip - }, { + }, +#define HFLIP_IDX 1 + { { .id = V4L2_CID_HFLIP, .type = V4L2_CTRL_TYPE_BOOLEAN, @@ -56,7 +59,9 @@ const static struct ctrl mt9m111_ctrls[] = { }, .set = mt9m111_set_hflip, .get = mt9m111_get_hflip - }, { + }, +#define GAIN_IDX 2 + { { .id = V4L2_CID_GAIN, .type = V4L2_CTRL_TYPE_INTEGER, @@ -79,6 +84,7 @@ int mt9m111_probe(struct sd *sd) { u8 data[2] = {0x00, 0x00}; int i; + s32 *sensor_settings; if (force_sensor) { if (force_sensor == MT9M111_SENSOR) { @@ -117,10 +123,19 @@ int mt9m111_probe(struct sd *sd) return -ENODEV; sensor_found: + sensor_settings = kmalloc(ARRAY_SIZE(mt9m111_ctrls) * sizeof(s32), GFP_KERNEL); + if (!sensor_settings) + return -ENOMEM; + sd->gspca_dev.cam.cam_mode = mt9m111_modes; sd->gspca_dev.cam.nmodes = ARRAY_SIZE(mt9m111_modes); sd->desc->ctrls = mt9m111_ctrls; sd->desc->nctrls = ARRAY_SIZE(mt9m111_ctrls); + + for (i = 0; i < ARRAY_SIZE(mt9m111_ctrls); i++) + sensor_settings[i] = mt9m111_ctrls[i].qctrl.default_value; + sd->sensor_priv = sensor_settings; + return 0; } @@ -155,18 +170,21 @@ int mt9m111_power_down(struct sd *sd) return 0; } +void mt9m111_disconnect(struct sd *sd) +{ + sd->sensor = NULL; + kfree(sd->sensor_priv); +} + int mt9m111_get_vflip(struct gspca_dev *gspca_dev, __s32 *val) { - int err; - u8 data[2] = {0x00, 0x00}; struct sd *sd = (struct sd *) gspca_dev; + s32 *sensor_settings = sd->sensor_priv; - err = m5602_read_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B, - data, 2); - *val = data[0] & MT9M111_RMB_MIRROR_ROWS; + *val = sensor_settings[VFLIP_IDX]; PDEBUG(D_V4L2, "Read vertical flip %d", *val); - return err; + return 0; } int mt9m111_set_vflip(struct gspca_dev *gspca_dev, __s32 val) @@ -174,9 +192,12 @@ int mt9m111_set_vflip(struct gspca_dev *gspca_dev, __s32 val) int err; u8 data[2] = {0x00, 0x00}; struct sd *sd = (struct sd *) gspca_dev; + s32 *sensor_settings = sd->sensor_priv; PDEBUG(D_V4L2, "Set vertical flip to %d", val); + sensor_settings[VFLIP_IDX] = val; + /* Set the correct page map */ err = m5602_write_sensor(sd, MT9M111_PAGE_MAP, data, 2); if (err < 0) @@ -194,16 +215,13 @@ int mt9m111_set_vflip(struct gspca_dev *gspca_dev, __s32 val) int mt9m111_get_hflip(struct gspca_dev *gspca_dev, __s32 *val) { - int err; - u8 data[2] = {0x00, 0x00}; struct sd *sd = (struct sd *) gspca_dev; + s32 *sensor_settings = sd->sensor_priv; - err = m5602_read_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B, - data, 2); - *val = data[0] & MT9M111_RMB_MIRROR_COLS; + *val = sensor_settings[HFLIP_IDX]; PDEBUG(D_V4L2, "Read horizontal flip %d", *val); - return err; + return 0; } int mt9m111_set_hflip(struct gspca_dev *gspca_dev, __s32 val) @@ -211,9 +229,11 @@ int mt9m111_set_hflip(struct gspca_dev *gspca_dev, __s32 val) int err; u8 data[2] = {0x00, 0x00}; struct sd *sd = (struct sd *) gspca_dev; + s32 *sensor_settings = sd->sensor_priv; PDEBUG(D_V4L2, "Set horizontal flip to %d", val); + sensor_settings[HFLIP_IDX] = val; /* Set the correct page map */ err = m5602_write_sensor(sd, MT9M111_PAGE_MAP, data, 2); if (err < 0) @@ -231,21 +251,13 @@ int mt9m111_set_hflip(struct gspca_dev *gspca_dev, __s32 val) int mt9m111_get_gain(struct gspca_dev *gspca_dev, __s32 *val) { - int err, tmp; - u8 data[2] = {0x00, 0x00}; struct sd *sd = (struct sd *) gspca_dev; + s32 *sensor_settings = sd->sensor_priv; - err = m5602_read_sensor(sd, MT9M111_SC_GLOBAL_GAIN, data, 2); - tmp = ((data[1] << 8) | data[0]); - - *val = ((tmp & (1 << 10)) * 2) | - ((tmp & (1 << 9)) * 2) | - ((tmp & (1 << 8)) * 2) | - (tmp & 0x7f); - + *val = sensor_settings[GAIN_IDX]; PDEBUG(D_V4L2, "Read gain %d", *val); - return err; + return 0; } int mt9m111_set_gain(struct gspca_dev *gspca_dev, __s32 val) @@ -253,6 +265,9 @@ int mt9m111_set_gain(struct gspca_dev *gspca_dev, __s32 val) int err, tmp; u8 data[2] = {0x00, 0x00}; struct sd *sd = (struct sd *) gspca_dev; + s32 *sensor_settings = sd->sensor_priv; + + sensor_settings[GAIN_IDX] = val; /* Set the correct page map */ err = m5602_write_sensor(sd, MT9M111_PAGE_MAP, data, 2); diff --git a/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h b/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h index 00c6db02b..03769fc04 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h @@ -86,6 +86,7 @@ extern int dump_sensor; int mt9m111_probe(struct sd *sd); int mt9m111_init(struct sd *sd); int mt9m111_power_down(struct sd *sd); +void mt9m111_disconnect(struct sd *sd); int mt9m111_set_vflip(struct gspca_dev *gspca_dev, __s32 val); int mt9m111_get_vflip(struct gspca_dev *gspca_dev, __s32 *val); @@ -102,7 +103,8 @@ const static struct m5602_sensor mt9m111 = { .probe = mt9m111_probe, .init = mt9m111_init, - .power_down = mt9m111_power_down + .power_down = mt9m111_power_down, + .disconnect = mt9m111_disconnect, }; static const unsigned char preinit_mt9m111[][4] = -- cgit v1.2.3 From e68cf1f2bb2b26391ee21355254a8491187d5559 Mon Sep 17 00:00:00 2001 From: Erik Andr?n Date: Fri, 3 Apr 2009 07:45:56 +0200 Subject: gspca - m5602-s5k83a: Add rotation, ctrl cache. Rename some ctrls. From: Luk?? Karas s5k83a sensor mounted on many acer laptops have a swiwel allowing it to be rotated. When the camera is in its rotated state, the image needs to be flipped. The only way to check for if the camera has been flipped is to continously poll a register in the m5602. This patch creates a kernel thread which does this. This patch renames some v4l2 ctrls and finally implements a cache in order to prevent unnecessary sensor reads. Priority: normal Signed-off-by: Luk?? Karas Signed-off-by: Erik Andr?n --- linux/drivers/media/video/gspca/m5602/m5602_core.c | 18 +- .../drivers/media/video/gspca/m5602/m5602_s5k83a.c | 389 +++++++++++++-------- .../drivers/media/video/gspca/m5602/m5602_s5k83a.h | 67 ++-- 3 files changed, 294 insertions(+), 180 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/m5602/m5602_core.c b/linux/drivers/media/video/gspca/m5602/m5602_core.c index 1aac2985f..93302f31a 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_core.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_core.c @@ -80,6 +80,16 @@ int m5602_write_bridge(struct sd *sd, u8 address, u8 i2c_data) return (err < 0) ? err : 0; } +int m5602_wait_for_i2c(struct sd *sd) +{ + int err; + u8 data; + do { + err = m5602_read_bridge(sd, M5602_XB_I2C_STATUS, &data); + } while ((data & I2C_BUSY) && !err); + return (err < 0) ? err : 0; +} + int m5602_read_sensor(struct sd *sd, const u8 address, u8 *i2c_data, const u8 len) { @@ -88,9 +98,7 @@ int m5602_read_sensor(struct sd *sd, const u8 address, if (!len || len > sd->sensor->i2c_regW) return -EINVAL; - do { - err = m5602_read_bridge(sd, M5602_XB_I2C_STATUS, i2c_data); - } while ((*i2c_data & I2C_BUSY) && !err); + err = m5602_wait_for_i2c(sd); if (err < 0) return err; @@ -118,6 +126,10 @@ int m5602_read_sensor(struct sd *sd, const u8 address, } for (i = 0; (i < len) && !err; i++) { + err = m5602_wait_for_i2c(sd); + if (err < 0) + return err; + err = m5602_read_bridge(sd, M5602_XB_I2C_DATA, &(i2c_data[i])); PDEBUG(D_CONF, "Reading sensor register " diff --git a/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.c b/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.c index 42c86aa4d..c77afcab1 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.c @@ -16,6 +16,7 @@ * */ +#include #include "m5602_s5k83a.h" static struct v4l2_pix_format s5k83a_modes[] = { @@ -33,47 +34,54 @@ static struct v4l2_pix_format s5k83a_modes[] = { }; const static struct ctrl s5k83a_ctrls[] = { +#define GAIN_IDX 0 { { - .id = V4L2_CID_BRIGHTNESS, + .id = V4L2_CID_GAIN, .type = V4L2_CTRL_TYPE_INTEGER, - .name = "brightness", + .name = "gain", .minimum = 0x00, .maximum = 0xff, .step = 0x01, - .default_value = S5K83A_DEFAULT_BRIGHTNESS, + .default_value = S5K83A_DEFAULT_GAIN, .flags = V4L2_CTRL_FLAG_SLIDER }, - .set = s5k83a_set_brightness, - .get = s5k83a_get_brightness + .set = s5k83a_set_gain, + .get = s5k83a_get_gain - }, { + }, +#define BRIGHTNESS_IDX 1 + { { - .id = V4L2_CID_WHITENESS, + .id = V4L2_CID_BRIGHTNESS, .type = V4L2_CTRL_TYPE_INTEGER, - .name = "whiteness", + .name = "brightness", .minimum = 0x00, .maximum = 0xff, .step = 0x01, - .default_value = S5K83A_DEFAULT_WHITENESS, + .default_value = S5K83A_DEFAULT_BRIGHTNESS, .flags = V4L2_CTRL_FLAG_SLIDER }, - .set = s5k83a_set_whiteness, - .get = s5k83a_get_whiteness, - }, { + .set = s5k83a_set_brightness, + .get = s5k83a_get_brightness, + }, +#define EXPOSURE_IDX 2 + { { - .id = V4L2_CID_GAIN, + .id = V4L2_CID_EXPOSURE, .type = V4L2_CTRL_TYPE_INTEGER, - .name = "gain", + .name = "exposure", .minimum = 0x00, - .maximum = S5K83A_MAXIMUM_GAIN, + .maximum = S5K83A_MAXIMUM_EXPOSURE, .step = 0x01, - .default_value = S5K83A_DEFAULT_GAIN, + .default_value = S5K83A_DEFAULT_EXPOSURE, .flags = V4L2_CTRL_FLAG_SLIDER }, - .set = s5k83a_set_gain, - .get = s5k83a_get_gain - }, { + .set = s5k83a_set_exposure, + .get = s5k83a_get_exposure + }, +#define HFLIP_IDX 3 + { { .id = V4L2_CID_HFLIP, .type = V4L2_CTRL_TYPE_BOOLEAN, @@ -85,7 +93,9 @@ const static struct ctrl s5k83a_ctrls[] = { }, .set = s5k83a_set_hflip, .get = s5k83a_get_hflip - }, { + }, +#define VFLIP_IDX 4 + { { .id = V4L2_CID_VFLIP, .type = V4L2_CTRL_TYPE_BOOLEAN, @@ -101,9 +111,13 @@ const static struct ctrl s5k83a_ctrls[] = { }; static void s5k83a_dump_registers(struct sd *sd); +static int s5k83a_get_rotation(struct sd *sd, u8 *reg_data); +static int s5k83a_set_led_indication(struct sd *sd, u8 val); +int s5k83a_set_flip_real(struct gspca_dev *gspca_dev, __s32 vflip, __s32 hflip); int s5k83a_probe(struct sd *sd) { + struct s5k83a_priv *sens_priv; u8 prod_id = 0, ver_id = 0; int i, err = 0; @@ -145,10 +159,28 @@ int s5k83a_probe(struct sd *sd) info("Detected a s5k83a sensor"); sensor_found: + sens_priv = kmalloc( + sizeof(struct s5k83a_priv), GFP_KERNEL); + if (!sens_priv) + return -ENOMEM; + + sens_priv->settings = + kmalloc(sizeof(s32)*ARRAY_SIZE(s5k83a_ctrls), GFP_KERNEL); + if (!sens_priv->settings) + return -ENOMEM; + sd->gspca_dev.cam.cam_mode = s5k83a_modes; sd->gspca_dev.cam.nmodes = ARRAY_SIZE(s5k83a_modes); sd->desc->ctrls = s5k83a_ctrls; sd->desc->nctrls = ARRAY_SIZE(s5k83a_ctrls); + + /* null the pointer! thread is't running now */ + sens_priv->rotation_thread = NULL; + + for (i = 0; i < ARRAY_SIZE(s5k83a_ctrls); i++) + sens_priv->settings[i] = s5k83a_ctrls[i].qctrl.default_value; + + sd->sensor_priv = sens_priv; return 0; } @@ -190,84 +222,104 @@ int s5k83a_init(struct sd *sd) return (err < 0) ? err : 0; } +static int rotation_thread_function(void *data) +{ + struct sd *sd = (struct sd *) data; + struct s5k83a_priv *sens_priv = sd->sensor_priv; + u8 reg, previous_rotation = 0; + __s32 vflip, hflip; + + set_current_state(TASK_INTERRUPTIBLE); + while (!schedule_timeout(100)) { + if (mutex_lock_interruptible(&sd->gspca_dev.usb_lock)) + break; + + s5k83a_get_rotation(sd, ®); + if (previous_rotation != reg) { + previous_rotation = reg; + info("Camera was flipped"); + + s5k83a_get_vflip((struct gspca_dev *) sd, &vflip); + s5k83a_get_hflip((struct gspca_dev *) sd, &hflip); + + if (reg) { + vflip = !vflip; + hflip = !hflip; + } + s5k83a_set_flip_real((struct gspca_dev *) sd, vflip, hflip); + } + + mutex_unlock(&sd->gspca_dev.usb_lock); + set_current_state(TASK_INTERRUPTIBLE); + } + + /* return to "front" flip */ + if (previous_rotation) { + s5k83a_get_vflip((struct gspca_dev *) sd, &vflip); + s5k83a_get_hflip((struct gspca_dev *) sd, &hflip); + s5k83a_set_flip_real((struct gspca_dev *) sd, vflip, hflip); + } + + sens_priv->rotation_thread = NULL; + return 0; +} + int s5k83a_start(struct sd *sd) { + struct s5k83a_priv *sens_priv = sd->sensor_priv; + + /* Create another thread, polling the GPIO ports of the camera to check + if it got rotated. This is how the windows driver does it so we have + to assume that there is no better way of accomplishing this */ + sens_priv->rotation_thread = kthread_create(rotation_thread_function, sd, "rotation thread"); + wake_up_process(sens_priv->rotation_thread); + return s5k83a_set_led_indication(sd, 1); } int s5k83a_stop(struct sd *sd) { + struct s5k83a_priv *sens_priv = sd->sensor_priv; + + if (sens_priv->rotation_thread) + kthread_stop(sens_priv->rotation_thread); + return s5k83a_set_led_indication(sd, 0); } -int s5k83a_power_down(struct sd *sd) +void s5k83a_disconnect(struct sd *sd) { - return 0; -} + struct s5k83a_priv *sens_priv = sd->sensor_priv; -static void s5k83a_dump_registers(struct sd *sd) -{ - int address; - u8 page, old_page; - m5602_read_sensor(sd, S5K83A_PAGE_MAP, &old_page, 1); + s5k83a_stop(sd); - for (page = 0; page < 16; page++) { - m5602_write_sensor(sd, S5K83A_PAGE_MAP, &page, 1); - info("Dumping the s5k83a register state for page 0x%x", page); - for (address = 0; address <= 0xff; address++) { - u8 val = 0; - m5602_read_sensor(sd, address, &val, 1); - info("register 0x%x contains 0x%x", - address, val); - } - } - info("s5k83a register state dump complete"); - - for (page = 0; page < 16; page++) { - m5602_write_sensor(sd, S5K83A_PAGE_MAP, &page, 1); - info("Probing for which registers that are read/write " - "for page 0x%x", page); - for (address = 0; address <= 0xff; address++) { - u8 old_val, ctrl_val, test_val = 0xff; - - m5602_read_sensor(sd, address, &old_val, 1); - m5602_write_sensor(sd, address, &test_val, 1); - m5602_read_sensor(sd, address, &ctrl_val, 1); - - if (ctrl_val == test_val) - info("register 0x%x is writeable", address); - else - info("register 0x%x is read only", address); + sd->sensor = NULL; + kfree(sens_priv->settings); + kfree(sens_priv); +} - /* Restore original val */ - m5602_write_sensor(sd, address, &old_val, 1); - } - } - info("Read/write register probing complete"); - m5602_write_sensor(sd, S5K83A_PAGE_MAP, &old_page, 1); +int s5k83a_power_down(struct sd *sd) +{ + return 0; } -int s5k83a_get_brightness(struct gspca_dev *gspca_dev, __s32 *val) +int s5k83a_get_gain(struct gspca_dev *gspca_dev, __s32 *val) { - int err; - u8 data[2]; struct sd *sd = (struct sd *) gspca_dev; + struct s5k83a_priv *sens_priv = sd->sensor_priv; - err = m5602_read_sensor(sd, S5K83A_BRIGHTNESS, data, 2); - if (err < 0) - return err; - - data[1] = data[1] << 1; - *val = data[1]; - - return err; + *val = sens_priv->settings[GAIN_IDX]; + return 0; } -int s5k83a_set_brightness(struct gspca_dev *gspca_dev, __s32 val) +int s5k83a_set_gain(struct gspca_dev *gspca_dev, __s32 val) { int err; u8 data[2]; struct sd *sd = (struct sd *) gspca_dev; + struct s5k83a_priv *sens_priv = sd->sensor_priv; + + sens_priv->settings[GAIN_IDX] = val; data[0] = 0x00; data[1] = 0x20; @@ -283,89 +335,68 @@ int s5k83a_set_brightness(struct gspca_dev *gspca_dev, __s32 val) /* FIXME: This is not sane, we need to figure out the composition of these registers */ - data[0] = val >> 3; /* brightness, high 5 bits */ - data[1] = val >> 1; /* brightness, high 7 bits */ - err = m5602_write_sensor(sd, S5K83A_BRIGHTNESS, data, 2); + data[0] = val >> 3; /* gain, high 5 bits */ + data[1] = val >> 1; /* gain, high 7 bits */ + err = m5602_write_sensor(sd, S5K83A_GAIN, data, 2); return err; } -int s5k83a_get_whiteness(struct gspca_dev *gspca_dev, __s32 *val) +int s5k83a_get_brightness(struct gspca_dev *gspca_dev, __s32 *val) { - int err; - u8 data; struct sd *sd = (struct sd *) gspca_dev; + struct s5k83a_priv *sens_priv = sd->sensor_priv; - err = m5602_read_sensor(sd, S5K83A_WHITENESS, &data, 1); - if (err < 0) - return err; - - *val = data; - - return err; + *val = sens_priv->settings[BRIGHTNESS_IDX]; + return 0; } -int s5k83a_set_whiteness(struct gspca_dev *gspca_dev, __s32 val) +int s5k83a_set_brightness(struct gspca_dev *gspca_dev, __s32 val) { int err; u8 data[1]; struct sd *sd = (struct sd *) gspca_dev; + struct s5k83a_priv *sens_priv = sd->sensor_priv; + sens_priv->settings[BRIGHTNESS_IDX] = val; data[0] = val; - err = m5602_write_sensor(sd, S5K83A_WHITENESS, data, 1); - + err = m5602_write_sensor(sd, S5K83A_BRIGHTNESS, data, 1); return err; } -int s5k83a_get_gain(struct gspca_dev *gspca_dev, __s32 *val) +int s5k83a_get_exposure(struct gspca_dev *gspca_dev, __s32 *val) { - int err; - u8 data[2]; struct sd *sd = (struct sd *) gspca_dev; + struct s5k83a_priv *sens_priv = sd->sensor_priv; - err = m5602_read_sensor(sd, S5K83A_GAIN, data, 2); - if (err < 0) - return err; - - data[1] = data[1] & 0x3f; - if (data[1] > S5K83A_MAXIMUM_GAIN) - data[1] = S5K83A_MAXIMUM_GAIN; - - *val = data[1]; - - return err; + *val = sens_priv->settings[EXPOSURE_IDX]; + return 0; } -int s5k83a_set_gain(struct gspca_dev *gspca_dev, __s32 val) +int s5k83a_set_exposure(struct gspca_dev *gspca_dev, __s32 val) { int err; u8 data[2]; struct sd *sd = (struct sd *) gspca_dev; + struct s5k83a_priv *sens_priv = sd->sensor_priv; + sens_priv->settings[EXPOSURE_IDX] = val; data[0] = 0; data[1] = val; - err = m5602_write_sensor(sd, S5K83A_GAIN, data, 2); + err = m5602_write_sensor(sd, S5K83A_EXPOSURE, data, 2); return err; } int s5k83a_get_vflip(struct gspca_dev *gspca_dev, __s32 *val) { - int err; - u8 data[1]; struct sd *sd = (struct sd *) gspca_dev; + struct s5k83a_priv *sens_priv = sd->sensor_priv; - data[0] = 0x05; - err = m5602_write_sensor(sd, S5K83A_PAGE_MAP, data, 1); - if (err < 0) - return err; - - err = m5602_read_sensor(sd, S5K83A_FLIP, data, 1); - *val = (data[0] | 0x40) ? 1 : 0; - - return err; + *val = sens_priv->settings[VFLIP_IDX]; + return 0; } -int s5k83a_set_vflip(struct gspca_dev *gspca_dev, __s32 val) +int s5k83a_set_flip_real(struct gspca_dev *gspca_dev, __s32 vflip, __s32 hflip) { int err; u8 data[1]; @@ -376,69 +407,83 @@ int s5k83a_set_vflip(struct gspca_dev *gspca_dev, __s32 val) if (err < 0) return err; - err = m5602_read_sensor(sd, S5K83A_FLIP, data, 1); - if (err < 0) - return err; + /* six bit is vflip, seven is hflip */ + data[0] = S5K83A_FLIP_MASK; + data[0] = (vflip) ? data[0] | 0x40 : data[0]; + data[0] = (hflip) ? data[0] | 0x80 : data[0]; - /* set or zero six bit, seven is hflip */ - data[0] = (val) ? (data[0] & 0x80) | 0x40 | S5K83A_FLIP_MASK - : (data[0] & 0x80) | S5K83A_FLIP_MASK; err = m5602_write_sensor(sd, S5K83A_FLIP, data, 1); if (err < 0) return err; - data[0] = (val) ? 0x0b : 0x0a; + data[0] = (vflip) ? 0x0b : 0x0a; err = m5602_write_sensor(sd, S5K83A_VFLIP_TUNE, data, 1); + if (err < 0) + return err; + data[0] = (hflip) ? 0x0a : 0x0b; + err = m5602_write_sensor(sd, S5K83A_HFLIP_TUNE, data, 1); return err; } -int s5k83a_get_hflip(struct gspca_dev *gspca_dev, __s32 *val) +int s5k83a_set_vflip(struct gspca_dev *gspca_dev, __s32 val) { int err; - u8 data[1]; + u8 reg; + __s32 hflip; struct sd *sd = (struct sd *) gspca_dev; + struct s5k83a_priv *sens_priv = sd->sensor_priv; - data[0] = 0x05; - err = m5602_write_sensor(sd, S5K83A_PAGE_MAP, data, 1); + sens_priv->settings[VFLIP_IDX] = val; + + s5k83a_get_hflip(gspca_dev, &hflip); + + err = s5k83a_get_rotation(sd, ®); if (err < 0) return err; + if (reg) { + val = !val; + hflip = !hflip; + } - err = m5602_read_sensor(sd, S5K83A_FLIP, data, 1); - *val = (data[0] | 0x80) ? 1 : 0; - + err = s5k83a_set_flip_real(gspca_dev, val, hflip); return err; } +int s5k83a_get_hflip(struct gspca_dev *gspca_dev, __s32 *val) +{ + struct sd *sd = (struct sd *) gspca_dev; + struct s5k83a_priv *sens_priv = sd->sensor_priv; + + *val = sens_priv->settings[HFLIP_IDX]; + return 0; +} + int s5k83a_set_hflip(struct gspca_dev *gspca_dev, __s32 val) { int err; - u8 data[1]; + u8 reg; + __s32 vflip; struct sd *sd = (struct sd *) gspca_dev; + struct s5k83a_priv *sens_priv = sd->sensor_priv; - data[0] = 0x05; - err = m5602_write_sensor(sd, S5K83A_PAGE_MAP, data, 1); - if (err < 0) - return err; + sens_priv->settings[HFLIP_IDX] = val; - err = m5602_read_sensor(sd, S5K83A_FLIP, data, 1); - if (err < 0) - return err; + s5k83a_get_vflip(gspca_dev, &vflip); - /* set or zero seven bit, six is vflip */ - data[0] = (val) ? (data[0] & 0x40) | 0x80 | S5K83A_FLIP_MASK - : (data[0] & 0x40) | S5K83A_FLIP_MASK; - err = m5602_write_sensor(sd, S5K83A_FLIP, data, 1); + err = s5k83a_get_rotation(sd, ®); if (err < 0) return err; + if (reg) { + val = !val; + vflip = !vflip; + } - data[0] = (val) ? 0x0a : 0x0b; - err = m5602_write_sensor(sd, S5K83A_HFLIP_TUNE, data, 1); - + err = s5k83a_set_flip_real(gspca_dev, vflip, val); return err; } -int s5k83a_set_led_indication(struct sd *sd, u8 val) +static int s5k83a_set_led_indication(struct sd *sd, u8 val) { int err = 0; u8 data[1]; @@ -456,3 +501,53 @@ int s5k83a_set_led_indication(struct sd *sd, u8 val) return (err < 0) ? err : 0; } + +/* Get camera rotation on Acer notebooks */ +static int s5k83a_get_rotation(struct sd *sd, u8 *reg_data) +{ + int err = m5602_read_bridge(sd, M5602_XB_GPIO_DAT, reg_data); + *reg_data = (*reg_data & S5K83A_GPIO_ROTATION_MASK) ? 0 : 1; + return err; +} + +static void s5k83a_dump_registers(struct sd *sd) +{ + int address; + u8 page, old_page; + m5602_read_sensor(sd, S5K83A_PAGE_MAP, &old_page, 1); + + for (page = 0; page < 16; page++) { + m5602_write_sensor(sd, S5K83A_PAGE_MAP, &page, 1); + info("Dumping the s5k83a register state for page 0x%x", page); + for (address = 0; address <= 0xff; address++) { + u8 val = 0; + m5602_read_sensor(sd, address, &val, 1); + info("register 0x%x contains 0x%x", + address, val); + } + } + info("s5k83a register state dump complete"); + + for (page = 0; page < 16; page++) { + m5602_write_sensor(sd, S5K83A_PAGE_MAP, &page, 1); + info("Probing for which registers that are read/write " + "for page 0x%x", page); + for (address = 0; address <= 0xff; address++) { + u8 old_val, ctrl_val, test_val = 0xff; + + m5602_read_sensor(sd, address, &old_val, 1); + m5602_write_sensor(sd, address, &test_val, 1); + m5602_read_sensor(sd, address, &ctrl_val, 1); + + if (ctrl_val == test_val) + info("register 0x%x is writeable", address); + else + info("register 0x%x is read only", address); + + /* Restore original val */ + m5602_write_sensor(sd, address, &old_val, 1); + } + } + info("Read/write register probing complete"); + m5602_write_sensor(sd, S5K83A_PAGE_MAP, &old_page, 1); +} diff --git a/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.h b/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.h index 819ab2527..9ca3ca311 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.h @@ -21,20 +21,21 @@ #include "m5602_sensor.h" -#define S5K83A_FLIP 0x01 -#define S5K83A_HFLIP_TUNE 0x03 -#define S5K83A_VFLIP_TUNE 0x05 -#define S5K83A_WHITENESS 0x0a -#define S5K83A_GAIN 0x18 -#define S5K83A_BRIGHTNESS 0x1b -#define S5K83A_PAGE_MAP 0xec - -#define S5K83A_DEFAULT_BRIGHTNESS 0x71 -#define S5K83A_DEFAULT_WHITENESS 0x7e -#define S5K83A_DEFAULT_GAIN 0x00 -#define S5K83A_MAXIMUM_GAIN 0x3c -#define S5K83A_FLIP_MASK 0x10 +#define S5K83A_FLIP 0x01 +#define S5K83A_HFLIP_TUNE 0x03 +#define S5K83A_VFLIP_TUNE 0x05 +#define S5K83A_BRIGHTNESS 0x0a +#define S5K83A_EXPOSURE 0x18 +#define S5K83A_GAIN 0x1b +#define S5K83A_PAGE_MAP 0xec + +#define S5K83A_DEFAULT_GAIN 0x71 +#define S5K83A_DEFAULT_BRIGHTNESS 0x7e +#define S5K83A_DEFAULT_EXPOSURE 0x00 +#define S5K83A_MAXIMUM_EXPOSURE 0x3c +#define S5K83A_FLIP_MASK 0x10 #define S5K83A_GPIO_LED_MASK 0x10 +#define S5K83A_GPIO_ROTATION_MASK 0x40 /*****************************************************************************/ @@ -47,15 +48,14 @@ int s5k83a_init(struct sd *sd); int s5k83a_start(struct sd *sd); int s5k83a_stop(struct sd *sd); int s5k83a_power_down(struct sd *sd); +void s5k83a_disconnect(struct sd *sd); -int s5k83a_set_led_indication(struct sd *sd, u8 val); - -int s5k83a_set_brightness(struct gspca_dev *gspca_dev, __s32 val); -int s5k83a_get_brightness(struct gspca_dev *gspca_dev, __s32 *val); -int s5k83a_set_whiteness(struct gspca_dev *gspca_dev, __s32 val); -int s5k83a_get_whiteness(struct gspca_dev *gspca_dev, __s32 *val); int s5k83a_set_gain(struct gspca_dev *gspca_dev, __s32 val); int s5k83a_get_gain(struct gspca_dev *gspca_dev, __s32 *val); +int s5k83a_set_brightness(struct gspca_dev *gspca_dev, __s32 val); +int s5k83a_get_brightness(struct gspca_dev *gspca_dev, __s32 *val); +int s5k83a_set_exposure(struct gspca_dev *gspca_dev, __s32 val); +int s5k83a_get_exposure(struct gspca_dev *gspca_dev, __s32 *val); int s5k83a_get_vflip(struct gspca_dev *gspca_dev, __s32 *val); int s5k83a_set_vflip(struct gspca_dev *gspca_dev, __s32 val); int s5k83a_get_hflip(struct gspca_dev *gspca_dev, __s32 *val); @@ -68,10 +68,18 @@ static const struct m5602_sensor s5k83a = { .start = s5k83a_start, .stop = s5k83a_stop, .power_down = s5k83a_power_down, + .disconnect = s5k83a_disconnect, .i2c_slave_id = 0x5a, .i2c_regW = 2, }; +struct s5k83a_priv { + /* We use another thread periodically + probing the orientation of the camera */ + struct task_struct *rotation_thread; + s32 *settings; +}; + static const unsigned char preinit_s5k83a[][4] = { {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02, 0x00}, @@ -125,7 +133,7 @@ static const unsigned char init_s5k83a[][4] = {SENSOR, 0x01, 0x50, 0x00}, {SENSOR, 0x12, 0x20, 0x00}, {SENSOR, 0x17, 0x40, 0x00}, - {SENSOR, S5K83A_BRIGHTNESS, 0x0f, 0x00}, + {SENSOR, S5K83A_GAIN, 0x0f, 0x00}, {SENSOR, 0x1c, 0x00, 0x00}, {SENSOR, 0x02, 0x70, 0x00}, {SENSOR, 0x03, 0x0b, 0x00}, @@ -232,7 +240,7 @@ static const unsigned char init_s5k83a[][4] = {SENSOR, 0x01, 0x50, 0x00}, {SENSOR, 0x12, 0x20, 0x00}, {SENSOR, 0x17, 0x40, 0x00}, - {SENSOR, S5K83A_BRIGHTNESS, 0x0f, 0x00}, + {SENSOR, S5K83A_GAIN, 0x0f, 0x00}, {SENSOR, 0x1c, 0x00, 0x00}, {SENSOR, 0x02, 0x70, 0x00}, /* some values like 0x10 give a blue-purple image */ @@ -320,7 +328,7 @@ static const unsigned char init_s5k83a[][4] = {SENSOR, 0x01, 0x50, 0x00}, {SENSOR, 0x12, 0x20, 0x00}, {SENSOR, 0x17, 0x40, 0x00}, - {SENSOR, S5K83A_BRIGHTNESS, 0x0f, 0x00}, + {SENSOR, S5K83A_GAIN, 0x0f, 0x00}, {SENSOR, 0x1c, 0x00, 0x00}, {SENSOR, 0x02, 0x70, 0x00}, {SENSOR, 0x03, 0x0b, 0x00}, @@ -374,24 +382,23 @@ static const unsigned char init_s5k83a[][4] = (this is value after boot, but after tries can be different) */ {SENSOR, 0x00, 0x06, 0x00}, - /* set default brightness */ + /* set default gain */ {SENSOR_LONG, 0x14, 0x00, 0x20}, {SENSOR_LONG, 0x0d, 0x01, 0x00}, - {SENSOR_LONG, 0x1b, S5K83A_DEFAULT_BRIGHTNESS >> 3, - S5K83A_DEFAULT_BRIGHTNESS >> 1}, + {SENSOR_LONG, 0x1b, S5K83A_DEFAULT_GAIN >> 3, + S5K83A_DEFAULT_GAIN >> 1}, - /* set default whiteness */ - {SENSOR, S5K83A_WHITENESS, S5K83A_DEFAULT_WHITENESS, 0x00}, + /* set default brightness */ + {SENSOR, S5K83A_BRIGHTNESS, S5K83A_DEFAULT_BRIGHTNESS, 0x00}, - /* set default gain */ - {SENSOR_LONG, 0x18, 0x00, S5K83A_DEFAULT_GAIN}, + /* set default exposure */ + {SENSOR_LONG, 0x18, 0x00, S5K83A_DEFAULT_EXPOSURE}, /* set default flip */ {SENSOR, S5K83A_PAGE_MAP, 0x05, 0x00}, {SENSOR, S5K83A_FLIP, 0x00 | S5K83A_FLIP_MASK, 0x00}, {SENSOR, S5K83A_HFLIP_TUNE, 0x0b, 0x00}, {SENSOR, S5K83A_VFLIP_TUNE, 0x0a, 0x00} - }; #endif -- cgit v1.2.3 From 72bb295f8641a2feeb71a7ba98d8a29eb2112a30 Mon Sep 17 00:00:00 2001 From: Erik Andr?n Date: Tue, 6 Jan 2009 10:39:11 +0100 Subject: gspca - m5602-po1030: Convert to have a v4l2 ctrl cache From: Erik Andr?n Let the po1030 have a local v4l2 ctrl cache as this minimizes the load on reading the registers and improves performance. Priority: normal Signed-off-by: Erik Andr?n --- .../drivers/media/video/gspca/m5602/m5602_po1030.c | 140 +++++++++++---------- .../drivers/media/video/gspca/m5602/m5602_po1030.h | 2 + 2 files changed, 79 insertions(+), 63 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/m5602/m5602_po1030.c b/linux/drivers/media/video/gspca/m5602/m5602_po1030.c index eaddf488b..27596fd61 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_po1030.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_po1030.c @@ -32,6 +32,7 @@ static struct v4l2_pix_format po1030_modes[] = { }; const static struct ctrl po1030_ctrls[] = { +#define GAIN_IDX 0 { { .id = V4L2_CID_GAIN, @@ -45,7 +46,9 @@ const static struct ctrl po1030_ctrls[] = { }, .set = po1030_set_gain, .get = po1030_get_gain - }, { + }, +#define EXPOSURE_IDX 1 + { { .id = V4L2_CID_EXPOSURE, .type = V4L2_CTRL_TYPE_INTEGER, @@ -58,7 +61,9 @@ const static struct ctrl po1030_ctrls[] = { }, .set = po1030_set_exposure, .get = po1030_get_exposure - }, { + }, +#define RED_BALANCE_IDX 2 + { { .id = V4L2_CID_RED_BALANCE, .type = V4L2_CTRL_TYPE_INTEGER, @@ -71,7 +76,9 @@ const static struct ctrl po1030_ctrls[] = { }, .set = po1030_set_red_balance, .get = po1030_get_red_balance - }, { + }, +#define BLUE_BALANCE_IDX 3 + { { .id = V4L2_CID_BLUE_BALANCE, .type = V4L2_CTRL_TYPE_INTEGER, @@ -84,7 +91,9 @@ const static struct ctrl po1030_ctrls[] = { }, .set = po1030_set_blue_balance, .get = po1030_get_blue_balance - }, { + }, +#define HFLIP_IDX 4 + { { .id = V4L2_CID_HFLIP, .type = V4L2_CTRL_TYPE_BOOLEAN, @@ -96,7 +105,9 @@ const static struct ctrl po1030_ctrls[] = { }, .set = po1030_set_hflip, .get = po1030_get_hflip - }, { + }, +#define VFLIP_IDX 5 + { { .id = V4L2_CID_VFLIP, .type = V4L2_CTRL_TYPE_BOOLEAN, @@ -116,6 +127,7 @@ static void po1030_dump_registers(struct sd *sd); int po1030_probe(struct sd *sd) { u8 prod_id = 0, ver_id = 0, i; + s32 *sensor_settings = sd->sensor_priv; if (force_sensor) { if (force_sensor == PO1030_SENSOR) { @@ -152,10 +164,19 @@ int po1030_probe(struct sd *sd) return -ENODEV; sensor_found: + sensor_settings = kmalloc( + ARRAY_SIZE(po1030_ctrls) * sizeof(s32), GFP_KERNEL); + if (!sensor_settings) + return -ENOMEM; + sd->gspca_dev.cam.cam_mode = po1030_modes; sd->gspca_dev.cam.nmodes = ARRAY_SIZE(po1030_modes); sd->desc->ctrls = po1030_ctrls; sd->desc->nctrls = ARRAY_SIZE(po1030_ctrls); + + for (i = 0; i < ARRAY_SIZE(po1030_ctrls); i++) + sensor_settings[i] = po1030_ctrls[i].qctrl.default_value; + sd->sensor_priv = sensor_settings; return 0; } @@ -195,30 +216,21 @@ int po1030_init(struct sd *sd) int po1030_get_exposure(struct gspca_dev *gspca_dev, __s32 *val) { struct sd *sd = (struct sd *) gspca_dev; - u8 i2c_data; - int err; - - err = m5602_read_sensor(sd, PO1030_REG_INTEGLINES_H, - &i2c_data, 1); - if (err < 0) - return err; - *val = (i2c_data << 8); - - err = m5602_read_sensor(sd, PO1030_REG_INTEGLINES_M, - &i2c_data, 1); - *val |= i2c_data; + s32 *sensor_settings = sd->sensor_priv; + *val = sensor_settings[EXPOSURE_IDX]; PDEBUG(D_V4L2, "Exposure read as %d", *val); - - return err; + return 0; } int po1030_set_exposure(struct gspca_dev *gspca_dev, __s32 val) { struct sd *sd = (struct sd *) gspca_dev; + s32 *sensor_settings = sd->sensor_priv; u8 i2c_data; int err; + sensor_settings[EXPOSURE_IDX] = val; PDEBUG(D_V4L2, "Set exposure to %d", val & 0xffff); i2c_data = ((val & 0xff00) >> 8); @@ -242,39 +254,49 @@ int po1030_set_exposure(struct gspca_dev *gspca_dev, __s32 val) int po1030_get_gain(struct gspca_dev *gspca_dev, __s32 *val) { struct sd *sd = (struct sd *) gspca_dev; - u8 i2c_data; - int err; + s32 *sensor_settings = sd->sensor_priv; - err = m5602_read_sensor(sd, PO1030_REG_GLOBALGAIN, - &i2c_data, 1); - *val = i2c_data; + *val = sensor_settings[GAIN_IDX]; PDEBUG(D_V4L2, "Read global gain %d", *val); - - return err; + return 0; } -int po1030_get_hflip(struct gspca_dev *gspca_dev, __s32 *val) +int po1030_set_gain(struct gspca_dev *gspca_dev, __s32 val) { struct sd *sd = (struct sd *) gspca_dev; + s32 *sensor_settings = sd->sensor_priv; u8 i2c_data; int err; - err = m5602_read_sensor(sd, PO1030_REG_CONTROL2, + sensor_settings[GAIN_IDX] = val; + + i2c_data = val & 0xff; + PDEBUG(D_V4L2, "Set global gain to %d", i2c_data); + err = m5602_write_sensor(sd, PO1030_REG_GLOBALGAIN, &i2c_data, 1); + return err; +} - *val = (i2c_data >> 7) & 0x01 ; +int po1030_get_hflip(struct gspca_dev *gspca_dev, __s32 *val) +{ + struct sd *sd = (struct sd *) gspca_dev; + s32 *sensor_settings = sd->sensor_priv; + *val = sensor_settings[HFLIP_IDX]; PDEBUG(D_V4L2, "Read hflip %d", *val); - return err; + return 0; } int po1030_set_hflip(struct gspca_dev *gspca_dev, __s32 val) { struct sd *sd = (struct sd *) gspca_dev; + s32 *sensor_settings = sd->sensor_priv; u8 i2c_data; int err; + sensor_settings[HFLIP_IDX] = val; + PDEBUG(D_V4L2, "Set hflip %d", val); err = m5602_read_sensor(sd, PO1030_REG_CONTROL2, &i2c_data, 1); if (err < 0) @@ -291,25 +313,23 @@ int po1030_set_hflip(struct gspca_dev *gspca_dev, __s32 val) int po1030_get_vflip(struct gspca_dev *gspca_dev, __s32 *val) { struct sd *sd = (struct sd *) gspca_dev; - u8 i2c_data; - int err; - - err = m5602_read_sensor(sd, PO1030_REG_GLOBALGAIN, - &i2c_data, 1); - - *val = (i2c_data >> 6) & 0x01; + s32 *sensor_settings = sd->sensor_priv; + *val= sensor_settings[VFLIP_IDX]; PDEBUG(D_V4L2, "Read vflip %d", *val); - return err; + return 0; } int po1030_set_vflip(struct gspca_dev *gspca_dev, __s32 val) { struct sd *sd = (struct sd *) gspca_dev; + s32 *sensor_settings = sd->sensor_priv; u8 i2c_data; int err; + sensor_settings[VFLIP_IDX] = val; + PDEBUG(D_V4L2, "Set vflip %d", val); err = m5602_read_sensor(sd, PO1030_REG_CONTROL2, &i2c_data, 1); if (err < 0) @@ -323,38 +343,25 @@ int po1030_set_vflip(struct gspca_dev *gspca_dev, __s32 val) return err; } -int po1030_set_gain(struct gspca_dev *gspca_dev, __s32 val) -{ - struct sd *sd = (struct sd *) gspca_dev; - u8 i2c_data; - int err; - - i2c_data = val & 0xff; - PDEBUG(D_V4L2, "Set global gain to %d", i2c_data); - err = m5602_write_sensor(sd, PO1030_REG_GLOBALGAIN, - &i2c_data, 1); - return err; -} - int po1030_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val) { struct sd *sd = (struct sd *) gspca_dev; - u8 i2c_data; - int err; + s32 *sensor_settings = sd->sensor_priv; - err = m5602_read_sensor(sd, PO1030_REG_RED_GAIN, - &i2c_data, 1); - *val = i2c_data; + *val = sensor_settings[RED_BALANCE_IDX]; PDEBUG(D_V4L2, "Read red gain %d", *val); - return err; + return 0; } int po1030_set_red_balance(struct gspca_dev *gspca_dev, __s32 val) { struct sd *sd = (struct sd *) gspca_dev; + s32 *sensor_settings = sd->sensor_priv; u8 i2c_data; int err; + sensor_settings[RED_BALANCE_IDX] = val; + i2c_data = val & 0xff; PDEBUG(D_V4L2, "Set red gain to %d", i2c_data); err = m5602_write_sensor(sd, PO1030_REG_RED_GAIN, @@ -365,22 +372,23 @@ int po1030_set_red_balance(struct gspca_dev *gspca_dev, __s32 val) int po1030_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val) { struct sd *sd = (struct sd *) gspca_dev; - u8 i2c_data; - int err; + s32 *sensor_settings = sd->sensor_priv; - err = m5602_read_sensor(sd, PO1030_REG_BLUE_GAIN, - &i2c_data, 1); - *val = i2c_data; + *val = sensor_settings[BLUE_BALANCE_IDX]; PDEBUG(D_V4L2, "Read blue gain %d", *val); - return err; + return 0; } int po1030_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val) { struct sd *sd = (struct sd *) gspca_dev; + s32 *sensor_settings = sd->sensor_priv; u8 i2c_data; int err; + + sensor_settings[BLUE_BALANCE_IDX] = val; + i2c_data = val & 0xff; PDEBUG(D_V4L2, "Set blue gain to %d", i2c_data); err = m5602_write_sensor(sd, PO1030_REG_BLUE_GAIN, @@ -394,6 +402,12 @@ int po1030_power_down(struct sd *sd) return 0; } +void po1030_disconnect(struct sd *sd) +{ + sd->sensor = NULL; + kfree(sd->sensor_priv); +} + static void po1030_dump_registers(struct sd *sd) { int address; diff --git a/linux/drivers/media/video/gspca/m5602/m5602_po1030.h b/linux/drivers/media/video/gspca/m5602/m5602_po1030.h index c10b12335..4c04d1b9a 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_po1030.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_po1030.h @@ -127,6 +127,7 @@ extern int dump_sensor; int po1030_probe(struct sd *sd); int po1030_init(struct sd *sd); int po1030_power_down(struct sd *sd); +void po1030_disconnect(struct sd *sd); int po1030_get_exposure(struct gspca_dev *gspca_dev, __s32 *val); int po1030_set_exposure(struct gspca_dev *gspca_dev, __s32 val); @@ -150,6 +151,7 @@ static const struct m5602_sensor po1030 = { .probe = po1030_probe, .init = po1030_init, .power_down = po1030_power_down, + .disconnect = po1030_disconnect, }; static const unsigned char preinit_po1030[][3] = -- cgit v1.2.3 From c68a15e5fab71a90d3dfcd8d802e34bc626930e6 Mon Sep 17 00:00:00 2001 From: Erik Andr?n Date: Tue, 6 Jan 2009 15:37:03 +0100 Subject: gspca - m5602-s5k4aa: Convert to use the v4l2 ctrl cache From: Erik Andr?n Priority: normal Signed-off-by: Erik Andr?n --- .../drivers/media/video/gspca/m5602/m5602_s5k4aa.c | 103 +++++++++++---------- .../drivers/media/video/gspca/m5602/m5602_s5k4aa.h | 7 +- 2 files changed, 59 insertions(+), 51 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c b/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c index 79a1d27a4..ccba8d10b 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c @@ -67,6 +67,7 @@ static struct v4l2_pix_format s5k4aa_modes[] = { }; const static struct ctrl s5k4aa_ctrls[] = { +#define VFLIP_IDX 0 { { .id = V4L2_CID_VFLIP, @@ -79,8 +80,9 @@ const static struct ctrl s5k4aa_ctrls[] = { }, .set = s5k4aa_set_vflip, .get = s5k4aa_get_vflip - - }, { + }, +#define HFLIP_IDX 1 + { { .id = V4L2_CID_HFLIP, .type = V4L2_CTRL_TYPE_BOOLEAN, @@ -92,8 +94,9 @@ const static struct ctrl s5k4aa_ctrls[] = { }, .set = s5k4aa_set_hflip, .get = s5k4aa_get_hflip - - }, { + }, +#define GAIN_IDX 2 + { { .id = V4L2_CID_GAIN, .type = V4L2_CTRL_TYPE_INTEGER, @@ -106,7 +109,9 @@ const static struct ctrl s5k4aa_ctrls[] = { }, .set = s5k4aa_set_gain, .get = s5k4aa_get_gain - }, { + }, +#define EXPOSURE_IDX 3 + { { .id = V4L2_CID_EXPOSURE, .type = V4L2_CTRL_TYPE_INTEGER, @@ -129,6 +134,7 @@ int s5k4aa_probe(struct sd *sd) u8 prod_id[6] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; const u8 expected_prod_id[6] = {0x00, 0x10, 0x00, 0x4b, 0x33, 0x75}; int i, err = 0; + s32 *sensor_settings; if (force_sensor) { if (force_sensor == S5K4AA_SENSOR) { @@ -187,10 +193,19 @@ int s5k4aa_probe(struct sd *sd) info("Detected a s5k4aa sensor"); sensor_found: + sensor_settings = kmalloc( + ARRAY_SIZE(s5k4aa_ctrls) * sizeof(s32), GFP_KERNEL); + if (!sensor_settings) + return -ENOMEM; + sd->gspca_dev.cam.cam_mode = s5k4aa_modes; sd->gspca_dev.cam.nmodes = ARRAY_SIZE(s5k4aa_modes); sd->desc->ctrls = s5k4aa_ctrls; sd->desc->nctrls = ARRAY_SIZE(s5k4aa_ctrls); + + for (i = 0; i < ARRAY_SIZE(s5k4aa_ctrls); i++) + sensor_settings[i] = s5k4aa_ctrls[i].qctrl.default_value; + sd->sensor_priv = sensor_settings; return 0; } @@ -303,31 +318,22 @@ int s5k4aa_power_down(struct sd *sd) int s5k4aa_get_exposure(struct gspca_dev *gspca_dev, __s32 *val) { struct sd *sd = (struct sd *) gspca_dev; - u8 data = S5K4AA_PAGE_MAP_2; - int err; + s32 *sensor_settings = sd->sensor_priv; - err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1); - if (err < 0) - return err; - - err = m5602_read_sensor(sd, S5K4AA_EXPOSURE_HI, &data, 1); - if (err < 0) - return err; - - *val = data << 8; - err = m5602_read_sensor(sd, S5K4AA_EXPOSURE_LO, &data, 1); - *val |= data; + *val = sensor_settings[EXPOSURE_IDX]; PDEBUG(D_V4L2, "Read exposure %d", *val); - return err; + return 0; } int s5k4aa_set_exposure(struct gspca_dev *gspca_dev, __s32 val) { struct sd *sd = (struct sd *) gspca_dev; + s32 *sensor_settings = sd->sensor_priv; u8 data = S5K4AA_PAGE_MAP_2; int err; + sensor_settings[EXPOSURE_IDX] = val; PDEBUG(D_V4L2, "Set exposure to %d", val); err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1); if (err < 0) @@ -345,26 +351,23 @@ int s5k4aa_set_exposure(struct gspca_dev *gspca_dev, __s32 val) int s5k4aa_get_vflip(struct gspca_dev *gspca_dev, __s32 *val) { struct sd *sd = (struct sd *) gspca_dev; - u8 data = S5K4AA_PAGE_MAP_2; - int err; + s32 *sensor_settings = sd->sensor_priv; - err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1); - if (err < 0) - return err; - - err = m5602_read_sensor(sd, S5K4AA_PAGE_MAP, &data, 1); - *val = (data & S5K4AA_RM_V_FLIP) >> 7; + *val = sensor_settings[VFLIP_IDX]; PDEBUG(D_V4L2, "Read vertical flip %d", *val); - return err; + return 0; } int s5k4aa_set_vflip(struct gspca_dev *gspca_dev, __s32 val) { struct sd *sd = (struct sd *) gspca_dev; + s32 *sensor_settings = sd->sensor_priv; u8 data = S5K4AA_PAGE_MAP_2; int err; + sensor_settings[VFLIP_IDX] = val; + PDEBUG(D_V4L2, "Set vertical flip to %d", val); err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1); if (err < 0) @@ -372,6 +375,10 @@ int s5k4aa_set_vflip(struct gspca_dev *gspca_dev, __s32 val) err = m5602_write_sensor(sd, S5K4AA_READ_MODE, &data, 1); if (err < 0) return err; + + if (dmi_check_system(s5k4aa_vflip_dmi_table)) + val = !val; + data = ((data & ~S5K4AA_RM_V_FLIP) | ((val & 0x01) << 7)); err = m5602_write_sensor(sd, S5K4AA_READ_MODE, &data, 1); @@ -400,28 +407,24 @@ int s5k4aa_set_vflip(struct gspca_dev *gspca_dev, __s32 val) int s5k4aa_get_hflip(struct gspca_dev *gspca_dev, __s32 *val) { struct sd *sd = (struct sd *) gspca_dev; - u8 data = S5K4AA_PAGE_MAP_2; - int err; + s32 *sensor_settings = sd->sensor_priv; - err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1); - if (err < 0) - return err; - - err = m5602_read_sensor(sd, S5K4AA_PAGE_MAP, &data, 1); - *val = (data & S5K4AA_RM_H_FLIP) >> 6; + *val = sensor_settings[HFLIP_IDX]; PDEBUG(D_V4L2, "Read horizontal flip %d", *val); - return err; + return 0; } int s5k4aa_set_hflip(struct gspca_dev *gspca_dev, __s32 val) { struct sd *sd = (struct sd *) gspca_dev; + s32 *sensor_settings = sd->sensor_priv; u8 data = S5K4AA_PAGE_MAP_2; int err; - PDEBUG(D_V4L2, "Set horizontal flip to %d", - val); + sensor_settings[HFLIP_IDX] = val; + + PDEBUG(D_V4L2, "Set horizontal flip to %d", val); err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1); if (err < 0) return err; @@ -456,26 +459,22 @@ int s5k4aa_set_hflip(struct gspca_dev *gspca_dev, __s32 val) int s5k4aa_get_gain(struct gspca_dev *gspca_dev, __s32 *val) { struct sd *sd = (struct sd *) gspca_dev; - u8 data = S5K4AA_PAGE_MAP_2; - int err; - - err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1); - if (err < 0) - return err; + s32 *sensor_settings = sd->sensor_priv; - err = m5602_read_sensor(sd, S5K4AA_GAIN_2, &data, 1); - *val = data; + *val = sensor_settings[GAIN_IDX]; PDEBUG(D_V4L2, "Read gain %d", *val); - - return err; + return 0; } int s5k4aa_set_gain(struct gspca_dev *gspca_dev, __s32 val) { struct sd *sd = (struct sd *) gspca_dev; + s32 *sensor_settings = sd->sensor_priv; u8 data = S5K4AA_PAGE_MAP_2; int err; + sensor_settings[GAIN_IDX] = val; + PDEBUG(D_V4L2, "Set gain to %d", val); err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1); if (err < 0) @@ -487,6 +486,12 @@ int s5k4aa_set_gain(struct gspca_dev *gspca_dev, __s32 val) return err; } +void s5k4aa_disconnect(struct sd *sd) +{ + sd->sensor = NULL; + kfree(sd->sensor_priv); +} + static void s5k4aa_dump_registers(struct sd *sd) { int address; diff --git a/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.h b/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.h index ca854d4f9..958fb72d4 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.h @@ -67,6 +67,7 @@ int s5k4aa_probe(struct sd *sd); int s5k4aa_init(struct sd *sd); int s5k4aa_start(struct sd *sd); int s5k4aa_power_down(struct sd *sd); +void s5k4aa_disconnect(struct sd *sd); int s5k4aa_get_exposure(struct gspca_dev *gspca_dev, __s32 *val); int s5k4aa_set_exposure(struct gspca_dev *gspca_dev, __s32 val); @@ -79,12 +80,14 @@ int s5k4aa_set_gain(struct gspca_dev *gspca_dev, __s32 val); static const struct m5602_sensor s5k4aa = { .name = "S5K4AA", + .i2c_slave_id = 0x5a, + .i2c_regW = 2, + .probe = s5k4aa_probe, .init = s5k4aa_init, .start = s5k4aa_start, .power_down = s5k4aa_power_down, - .i2c_slave_id = 0x5a, - .i2c_regW = 2, + .disconnect = s5k4aa_disconnect, }; static const unsigned char preinit_s5k4aa[][4] = -- cgit v1.2.3 From 7c02d8dbb5d410ca9cc0af821a6d24a7f6412d86 Mon Sep 17 00:00:00 2001 From: Erik Andr?n Date: Tue, 6 Jan 2009 15:59:42 +0100 Subject: gspca - m5602-mt9m111: Remove the unused power_down struct member From: Erik Andr?n The power_down sensor struct member is almost has no purpose in the current driver abstraction. Remove it. Priority: normal Signed-off-by: Erik Andr?n --- .../media/video/gspca/m5602/m5602_mt9m111.c | 5 ----- .../media/video/gspca/m5602/m5602_mt9m111.h | 2 -- .../drivers/media/video/gspca/m5602/m5602_ov9650.c | 17 ----------------- .../drivers/media/video/gspca/m5602/m5602_ov9650.h | 22 ---------------------- .../drivers/media/video/gspca/m5602/m5602_po1030.c | 5 ----- .../drivers/media/video/gspca/m5602/m5602_po1030.h | 2 -- .../drivers/media/video/gspca/m5602/m5602_s5k4aa.c | 5 ----- .../drivers/media/video/gspca/m5602/m5602_s5k4aa.h | 2 -- .../drivers/media/video/gspca/m5602/m5602_s5k83a.c | 5 ----- .../drivers/media/video/gspca/m5602/m5602_s5k83a.h | 2 -- .../drivers/media/video/gspca/m5602/m5602_sensor.h | 3 --- 11 files changed, 70 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.c b/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.c index 43791a6b8..519548d07 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.c @@ -165,11 +165,6 @@ int mt9m111_init(struct sd *sd) return (err < 0) ? err : 0; } -int mt9m111_power_down(struct sd *sd) -{ - return 0; -} - void mt9m111_disconnect(struct sd *sd) { sd->sensor = NULL; diff --git a/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h b/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h index 03769fc04..913863247 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h @@ -85,7 +85,6 @@ extern int dump_sensor; int mt9m111_probe(struct sd *sd); int mt9m111_init(struct sd *sd); -int mt9m111_power_down(struct sd *sd); void mt9m111_disconnect(struct sd *sd); int mt9m111_set_vflip(struct gspca_dev *gspca_dev, __s32 val); @@ -103,7 +102,6 @@ const static struct m5602_sensor mt9m111 = { .probe = mt9m111_probe, .init = mt9m111_init, - .power_down = mt9m111_power_down, .disconnect = mt9m111_disconnect, }; diff --git a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c index 86e4719fb..1843ed3da 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c @@ -469,26 +469,9 @@ int ov9650_stop(struct sd *sd) return m5602_write_sensor(sd, OV9650_COM2, &data, 1); } -int ov9650_power_down(struct sd *sd) -{ - int i, err = 0; - for (i = 0; i < ARRAY_SIZE(power_down_ov9650) && !err; i++) { - u8 data = power_down_ov9650[i][2]; - if (power_down_ov9650[i][0] == SENSOR) - err = m5602_write_sensor(sd, - power_down_ov9650[i][1], &data, 1); - else - err = m5602_write_bridge(sd, power_down_ov9650[i][1], - data); - } - - return err; -} - void ov9650_disconnect(struct sd *sd) { ov9650_stop(sd); - ov9650_power_down(sd); sd->sensor = NULL; kfree(sd->sensor_priv); diff --git a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.h b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.h index fcc54e4c0..b81f26505 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.h @@ -137,7 +137,6 @@ int ov9650_probe(struct sd *sd); int ov9650_init(struct sd *sd); int ov9650_start(struct sd *sd); int ov9650_stop(struct sd *sd); -int ov9650_power_down(struct sd *sd); void ov9650_disconnect(struct sd *sd); int ov9650_set_exposure(struct gspca_dev *gspca_dev, __s32 val); @@ -167,7 +166,6 @@ const static struct m5602_sensor ov9650 = { .init = ov9650_init, .start = ov9650_start, .stop = ov9650_stop, - .power_down = ov9650_power_down, .disconnect = ov9650_disconnect, }; @@ -312,26 +310,6 @@ static const unsigned char init_ov9650[][3] = {SENSOR, OV9650_COM2, OV9650_SOFT_SLEEP | OV9650_OUTPUT_DRIVE_2X}, }; -static const unsigned char power_down_ov9650[][3] = -{ - {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x04}, - {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0}, - {SENSOR, OV9650_COM7, 0x80}, - {SENSOR, OV9650_OFON, 0xf4}, - {SENSOR, OV9650_MVFP, 0x80}, - {SENSOR, OV9650_DBLV, 0x3f}, - {SENSOR, OV9650_RSVD36, 0x49}, - {SENSOR, OV9650_COM7, 0x05}, - - {BRIDGE, M5602_XB_GPIO_DIR, 0x05}, - {BRIDGE, M5602_XB_GPIO_DAT, 0x04}, - {BRIDGE, M5602_XB_GPIO_EN_H, 0x06}, - {BRIDGE, M5602_XB_GPIO_EN_L, 0x06}, - {BRIDGE, M5602_XB_GPIO_DAT_H, 0x02}, - {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x04}, - {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0}, -}; - static const unsigned char res_init_ov9650[][3] = { {SENSOR, OV9650_COM2, OV9650_OUTPUT_DRIVE_2X}, diff --git a/linux/drivers/media/video/gspca/m5602/m5602_po1030.c b/linux/drivers/media/video/gspca/m5602/m5602_po1030.c index 27596fd61..1e9a30660 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_po1030.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_po1030.c @@ -397,11 +397,6 @@ int po1030_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val) return err; } -int po1030_power_down(struct sd *sd) -{ - return 0; -} - void po1030_disconnect(struct sd *sd) { sd->sensor = NULL; diff --git a/linux/drivers/media/video/gspca/m5602/m5602_po1030.h b/linux/drivers/media/video/gspca/m5602/m5602_po1030.h index 4c04d1b9a..c55c31a91 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_po1030.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_po1030.h @@ -126,7 +126,6 @@ extern int dump_sensor; int po1030_probe(struct sd *sd); int po1030_init(struct sd *sd); -int po1030_power_down(struct sd *sd); void po1030_disconnect(struct sd *sd); int po1030_get_exposure(struct gspca_dev *gspca_dev, __s32 *val); @@ -150,7 +149,6 @@ static const struct m5602_sensor po1030 = { .probe = po1030_probe, .init = po1030_init, - .power_down = po1030_power_down, .disconnect = po1030_disconnect, }; diff --git a/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c b/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c index ccba8d10b..d4f45d44d 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c @@ -310,11 +310,6 @@ int s5k4aa_init(struct sd *sd) return (err < 0) ? err : 0; } -int s5k4aa_power_down(struct sd *sd) -{ - return 0; -} - int s5k4aa_get_exposure(struct gspca_dev *gspca_dev, __s32 *val) { struct sd *sd = (struct sd *) gspca_dev; diff --git a/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.h b/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.h index 958fb72d4..9ffcb5d1a 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.h @@ -66,7 +66,6 @@ extern int dump_sensor; int s5k4aa_probe(struct sd *sd); int s5k4aa_init(struct sd *sd); int s5k4aa_start(struct sd *sd); -int s5k4aa_power_down(struct sd *sd); void s5k4aa_disconnect(struct sd *sd); int s5k4aa_get_exposure(struct gspca_dev *gspca_dev, __s32 *val); @@ -86,7 +85,6 @@ static const struct m5602_sensor s5k4aa = { .probe = s5k4aa_probe, .init = s5k4aa_init, .start = s5k4aa_start, - .power_down = s5k4aa_power_down, .disconnect = s5k4aa_disconnect, }; diff --git a/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.c b/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.c index c77afcab1..b43a3b04a 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.c @@ -298,11 +298,6 @@ void s5k83a_disconnect(struct sd *sd) kfree(sens_priv); } -int s5k83a_power_down(struct sd *sd) -{ - return 0; -} - int s5k83a_get_gain(struct gspca_dev *gspca_dev, __s32 *val) { struct sd *sd = (struct sd *) gspca_dev; diff --git a/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.h b/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.h index 9ca3ca311..02a5e2559 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.h @@ -47,7 +47,6 @@ int s5k83a_probe(struct sd *sd); int s5k83a_init(struct sd *sd); int s5k83a_start(struct sd *sd); int s5k83a_stop(struct sd *sd); -int s5k83a_power_down(struct sd *sd); void s5k83a_disconnect(struct sd *sd); int s5k83a_set_gain(struct gspca_dev *gspca_dev, __s32 val); @@ -67,7 +66,6 @@ static const struct m5602_sensor s5k83a = { .init = s5k83a_init, .start = s5k83a_start, .stop = s5k83a_stop, - .power_down = s5k83a_power_down, .disconnect = s5k83a_disconnect, .i2c_slave_id = 0x5a, .i2c_regW = 2, diff --git a/linux/drivers/media/video/gspca/m5602/m5602_sensor.h b/linux/drivers/media/video/gspca/m5602/m5602_sensor.h index 0d3026936..987dcb23e 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_sensor.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_sensor.h @@ -61,9 +61,6 @@ struct m5602_sensor { /* Executed when the device is disconnected */ void (*disconnect)(struct sd *sd); - - /* Performs a power down sequence */ - int (*power_down)(struct sd *sd); }; #endif -- cgit v1.2.3 From 297374d5b9ad2910cb03d63aad8576a3faedb3e0 Mon Sep 17 00:00:00 2001 From: Erik Andr?n Date: Tue, 6 Jan 2009 16:58:50 +0100 Subject: gspca - m5602-ov9650: Improve the vflip quirk handling. From: Erik Andr?n Regardless of the actual sensor orientation vflip = 0 is normal, and vflip = 1 is upside down. This patch makes that happen Priority: normal Signed-off-by: Erik Andr?n --- .../drivers/media/video/gspca/m5602/m5602_ov9650.c | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c index 1843ed3da..96fb8c026 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c @@ -291,12 +291,6 @@ sensor_found: for (i = 0; i < ARRAY_SIZE(ov9650_ctrls); i++) sensor_settings[i] = ov9650_ctrls[i].qctrl.default_value; sd->sensor_priv = sensor_settings; - - if (dmi_check_system(ov9650_flip_dmi_table) && !err) { - info("vflip quirk active"); - sensor_settings[VFLIP_IDX] = 1; - } - return 0; } @@ -362,7 +356,10 @@ int ov9650_start(struct sd *sd) int ver_offs = cam->cam_mode[sd->gspca_dev.curr_mode].priv; int hor_offs = OV9650_LEFT_OFFSET; - if (sensor_settings[VFLIP_IDX]) + if ((!dmi_check_system(ov9650_flip_dmi_table) && + sensor_settings[VFLIP_IDX]) || + (dmi_check_system(ov9650_flip_dmi_table) && + !sensor_settings[VFLIP_IDX])) ver_offs--; if (width <= 320) @@ -631,7 +628,12 @@ int ov9650_set_hflip(struct gspca_dev *gspca_dev, __s32 val) PDEBUG(D_V4L2, "Set horizontal flip to %d", val); sensor_settings[HFLIP_IDX] = val; - i2c_data = ((val & 0x01) << 5) | (sensor_settings[VFLIP_IDX] << 4); + + if (!dmi_check_system(ov9650_flip_dmi_table)) + i2c_data = ((val & 0x01) << 5) | (sensor_settings[VFLIP_IDX] << 4); + else + i2c_data = ((val & 0x01) << 5) | (!sensor_settings[VFLIP_IDX] << 4); + err = m5602_write_sensor(sd, OV9650_MVFP, &i2c_data, 1); return err; @@ -658,6 +660,9 @@ int ov9650_set_vflip(struct gspca_dev *gspca_dev, __s32 val) PDEBUG(D_V4L2, "Set vertical flip to %d", val); sensor_settings[VFLIP_IDX] = val; + if (dmi_check_system(ov9650_flip_dmi_table)) + val = !val; + i2c_data = ((val & 0x01) << 4) | (sensor_settings[VFLIP_IDX] << 5); err = m5602_write_sensor(sd, OV9650_MVFP, &i2c_data, 1); if (err < 0) -- cgit v1.2.3 From 7471b9cfdef5de178b613bd1612596bb6315dda6 Mon Sep 17 00:00:00 2001 From: Erik Andr?n Date: Wed, 7 Jan 2009 17:54:13 +0100 Subject: gspca - m5602-po1030: Rename register defines, add missing ones. From: Erik Andr?n The po1030 register defines are unnecessarily complex, simplify them and also add some missing ones. Priority: normal Signed-off-by: Erik Andr?n --- .../drivers/media/video/gspca/m5602/m5602_po1030.c | 18 +- .../drivers/media/video/gspca/m5602/m5602_po1030.h | 261 +++++++++++---------- 2 files changed, 143 insertions(+), 136 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/m5602/m5602_po1030.c b/linux/drivers/media/video/gspca/m5602/m5602_po1030.c index 1e9a30660..413c5b899 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_po1030.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_po1030.c @@ -237,7 +237,7 @@ int po1030_set_exposure(struct gspca_dev *gspca_dev, __s32 val) PDEBUG(D_V4L2, "Set exposure to high byte to 0x%x", i2c_data); - err = m5602_write_sensor(sd, PO1030_REG_INTEGLINES_H, + err = m5602_write_sensor(sd, PO1030_INTEGLINES_H, &i2c_data, 1); if (err < 0) return err; @@ -245,7 +245,7 @@ int po1030_set_exposure(struct gspca_dev *gspca_dev, __s32 val) i2c_data = (val & 0xff); PDEBUG(D_V4L2, "Set exposure to low byte to 0x%x", i2c_data); - err = m5602_write_sensor(sd, PO1030_REG_INTEGLINES_M, + err = m5602_write_sensor(sd, PO1030_INTEGLINES_M, &i2c_data, 1); return err; @@ -272,7 +272,7 @@ int po1030_set_gain(struct gspca_dev *gspca_dev, __s32 val) i2c_data = val & 0xff; PDEBUG(D_V4L2, "Set global gain to %d", i2c_data); - err = m5602_write_sensor(sd, PO1030_REG_GLOBALGAIN, + err = m5602_write_sensor(sd, PO1030_GLOBALGAIN, &i2c_data, 1); return err; } @@ -298,13 +298,13 @@ int po1030_set_hflip(struct gspca_dev *gspca_dev, __s32 val) sensor_settings[HFLIP_IDX] = val; PDEBUG(D_V4L2, "Set hflip %d", val); - err = m5602_read_sensor(sd, PO1030_REG_CONTROL2, &i2c_data, 1); + err = m5602_read_sensor(sd, PO1030_CONTROL2, &i2c_data, 1); if (err < 0) return err; i2c_data = (0x7f & i2c_data) | ((val & 0x01) << 7); - err = m5602_write_sensor(sd, PO1030_REG_CONTROL2, + err = m5602_write_sensor(sd, PO1030_CONTROL2, &i2c_data, 1); return err; @@ -331,13 +331,13 @@ int po1030_set_vflip(struct gspca_dev *gspca_dev, __s32 val) sensor_settings[VFLIP_IDX] = val; PDEBUG(D_V4L2, "Set vflip %d", val); - err = m5602_read_sensor(sd, PO1030_REG_CONTROL2, &i2c_data, 1); + err = m5602_read_sensor(sd, PO1030_CONTROL2, &i2c_data, 1); if (err < 0) return err; i2c_data = (i2c_data & 0xbf) | ((val & 0x01) << 6); - err = m5602_write_sensor(sd, PO1030_REG_CONTROL2, + err = m5602_write_sensor(sd, PO1030_CONTROL2, &i2c_data, 1); return err; @@ -364,7 +364,7 @@ int po1030_set_red_balance(struct gspca_dev *gspca_dev, __s32 val) i2c_data = val & 0xff; PDEBUG(D_V4L2, "Set red gain to %d", i2c_data); - err = m5602_write_sensor(sd, PO1030_REG_RED_GAIN, + err = m5602_write_sensor(sd, PO1030_RED_GAIN, &i2c_data, 1); return err; } @@ -391,7 +391,7 @@ int po1030_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val) i2c_data = val & 0xff; PDEBUG(D_V4L2, "Set blue gain to %d", i2c_data); - err = m5602_write_sensor(sd, PO1030_REG_BLUE_GAIN, + err = m5602_write_sensor(sd, PO1030_BLUE_GAIN, &i2c_data, 1); return err; diff --git a/linux/drivers/media/video/gspca/m5602/m5602_po1030.h b/linux/drivers/media/video/gspca/m5602/m5602_po1030.h index c55c31a91..7402701d5 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_po1030.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_po1030.h @@ -25,88 +25,95 @@ /*****************************************************************************/ -#define PO1030_REG_DEVID_H 0x00 -#define PO1030_REG_DEVID_L 0x01 -#define PO1030_REG_FRAMEWIDTH_H 0x04 -#define PO1030_REG_FRAMEWIDTH_L 0x05 -#define PO1030_REG_FRAMEHEIGHT_H 0x06 -#define PO1030_REG_FRAMEHEIGHT_L 0x07 -#define PO1030_REG_WINDOWX_H 0x08 -#define PO1030_REG_WINDOWX_L 0x09 -#define PO1030_REG_WINDOWY_H 0x0a -#define PO1030_REG_WINDOWY_L 0x0b -#define PO1030_REG_WINDOWWIDTH_H 0x0c -#define PO1030_REG_WINDOWWIDTH_L 0x0d -#define PO1030_REG_WINDOWHEIGHT_H 0x0e -#define PO1030_REG_WINDOWHEIGHT_L 0x0f - -#define PO1030_REG_GLOBALIBIAS 0x12 -#define PO1030_REG_PIXELIBIAS 0x13 - -#define PO1030_REG_GLOBALGAIN 0x15 -#define PO1030_REG_RED_GAIN 0x16 -#define PO1030_REG_GREEN_1_GAIN 0x17 -#define PO1030_REG_BLUE_GAIN 0x18 -#define PO1030_REG_GREEN_2_GAIN 0x19 - -#define PO1030_REG_INTEGLINES_H 0x1a -#define PO1030_REG_INTEGLINES_M 0x1b -#define PO1030_REG_INTEGLINES_L 0x1c - -#define PO1030_REG_CONTROL1 0x1d -#define PO1030_REG_CONTROL2 0x1e -#define PO1030_REG_CONTROL3 0x1f -#define PO1030_REG_CONTROL4 0x20 - -#define PO1030_REG_PERIOD50_H 0x23 -#define PO1030_REG_PERIOD50_L 0x24 -#define PO1030_REG_PERIOD60_H 0x25 -#define PO1030_REG_PERIOD60_L 0x26 -#define PO1030_REG_REGCLK167 0x27 -#define PO1030_REG_DELTA50 0x28 -#define PO1030_REG_DELTA60 0x29 - -#define PO1030_REG_ADCOFFSET 0x2c +#define PO1030_DEVID_H 0x00 +#define PO1030_DEVID_L 0x01 +#define PO1030_FRAMEWIDTH_H 0x04 +#define PO1030_FRAMEWIDTH_L 0x05 +#define PO1030_FRAMEHEIGHT_H 0x06 +#define PO1030_FRAMEHEIGHT_L 0x07 +#define PO1030_WINDOWX_H 0x08 +#define PO1030_WINDOWX_L 0x09 +#define PO1030_WINDOWY_H 0x0a +#define PO1030_WINDOWY_L 0x0b +#define PO1030_WINDOWWIDTH_H 0x0c +#define PO1030_WINDOWWIDTH_L 0x0d +#define PO1030_WINDOWHEIGHT_H 0x0e +#define PO1030_WINDOWHEIGHT_L 0x0f + +#define PO1030_GLOBALIBIAS 0x12 +#define PO1030_PIXELIBIAS 0x13 + +#define PO1030_GLOBALGAIN 0x15 +#define PO1030_RED_GAIN 0x16 +#define PO1030_GREEN_1_GAIN 0x17 +#define PO1030_BLUE_GAIN 0x18 +#define PO1030_GREEN_2_GAIN 0x19 + +#define PO1030_INTEGLINES_H 0x1a +#define PO1030_INTEGLINES_M 0x1b +#define PO1030_INTEGLINES_L 0x1c + +#define PO1030_CONTROL1 0x1d +#define PO1030_CONTROL2 0x1e +#define PO1030_CONTROL3 0x1f +#define PO1030_CONTROL4 0x20 + +#define PO1030_PERIOD50_H 0x23 +#define PO1030_PERIOD50_L 0x24 +#define PO1030_PERIOD60_H 0x25 +#define PO1030_PERIOD60_L 0x26 +#define PO1030_REGCLK167 0x27 +#define PO1030_FLICKER_DELTA50 0x28 +#define PO1030_FLICKERDELTA60 0x29 + +#define PO1030_ADCOFFSET 0x2c /* Gamma Correction Coeffs */ -#define PO1030_REG_GC0 0x2d -#define PO1030_REG_GC1 0x2e -#define PO1030_REG_GC2 0x2f -#define PO1030_REG_GC3 0x30 -#define PO1030_REG_GC4 0x31 -#define PO1030_REG_GC5 0x32 -#define PO1030_REG_GC6 0x33 -#define PO1030_REG_GC7 0x34 +#define PO1030_GC0 0x2d +#define PO1030_GC1 0x2e +#define PO1030_GC2 0x2f +#define PO1030_GC3 0x30 +#define PO1030_GC4 0x31 +#define PO1030_GC5 0x32 +#define PO1030_GC6 0x33 +#define PO1030_GC7 0x34 /* Color Transform Matrix */ -#define PO1030_REG_CT0 0x35 -#define PO1030_REG_CT1 0x36 -#define PO1030_REG_CT2 0x37 -#define PO1030_REG_CT3 0x38 -#define PO1030_REG_CT4 0x39 -#define PO1030_REG_CT5 0x3a -#define PO1030_REG_CT6 0x3b -#define PO1030_REG_CT7 0x3c -#define PO1030_REG_CT8 0x3d - -#define PO1030_REG_AUTOCTRL1 0x3e -#define PO1030_REG_AUTOCTRL2 0x3f - -#define PO1030_REG_YTARGET 0x40 -#define PO1030_REG_GLOBALGAINMIN 0x41 -#define PO1030_REG_GLOBALGAINMAX 0x42 +#define PO1030_CT0 0x35 +#define PO1030_CT1 0x36 +#define PO1030_CT2 0x37 +#define PO1030_CT3 0x38 +#define PO1030_CT4 0x39 +#define PO1030_CT5 0x3a +#define PO1030_CT6 0x3b +#define PO1030_CT7 0x3c +#define PO1030_CT8 0x3d + +#define PO1030_AUTOCTRL1 0x3e +#define PO1030_AUTOCTRL2 0x3f + +#define PO1030_YTARGET 0x40 +#define PO1030_GLOBALGAINMIN 0x41 +#define PO1030_GLOBALGAINMAX 0x42 + +#define PO1030_AWB_RED_TUNING 0x47 +#define PO1030_AWB_BLUE_TUNING 0x48 /* Output format control */ -#define PO1030_REG_OUTFORMCTRL1 0x5a -#define PO1030_REG_OUTFORMCTRL2 0x5b -#define PO1030_REG_OUTFORMCTRL3 0x5c -#define PO1030_REG_OUTFORMCTRL4 0x5d -#define PO1030_REG_OUTFORMCTRL5 0x5e +#define PO1030_OUTFORMCTRL1 0x5a +#define PO1030_OUTFORMCTRL2 0x5b +#define PO1030_OUTFORMCTRL3 0x5c +#define PO1030_OUTFORMCTRL4 0x5d +#define PO1030_OUTFORMCTRL5 0x5e -/* Imaging coefficients */ -#define PO1030_REG_YBRIGHT 0x73 -#define PO1030_REG_YCONTRAST 0x74 -#define PO1030_REG_YSATURATION 0x75 +#define PO1030_EDGE_ENH_OFF 0x5f +#define PO1030_EGA 0x60 + +#define PO1030_Cb_U_GAIN 0x63 +#define PO1030_Cr_V_GAIN 0x64 + +#define PO1030_YCONTRAST 0x74 +#define PO1030_YSATURATION 0x75 #define PO1030_HFLIP (1 << 7) #define PO1030_VFLIP (1 << 6) @@ -164,7 +171,7 @@ static const unsigned char preinit_po1030[][3] = {BRIDGE, M5602_XB_ADC_CTRL, 0xc0}, {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0c}, - {SENSOR, PO1030_REG_AUTOCTRL2, 0x24}, + {SENSOR, PO1030_AUTOCTRL2, 0x24}, {BRIDGE, M5602_XB_GPIO_DIR, 0x05}, {BRIDGE, M5602_XB_GPIO_DAT, 0x04}, @@ -196,7 +203,7 @@ static const unsigned char preinit_po1030[][3] = {BRIDGE, M5602_XB_HSYNC_PARA, 0x87}, {BRIDGE, M5602_XB_SIG_INI, 0x00}, - {SENSOR, PO1030_REG_AUTOCTRL2, 0x24}, + {SENSOR, PO1030_AUTOCTRL2, 0x24}, {BRIDGE, M5602_XB_GPIO_DIR, 0x05}, {BRIDGE, M5602_XB_GPIO_DAT, 0x04}, @@ -229,7 +236,7 @@ static const unsigned char init_po1030[][4] = /*end of sequence 1*/ /*sequence 2 (same as stop sequence)*/ - {SENSOR, PO1030_REG_AUTOCTRL2, 0x24}, + {SENSOR, PO1030_AUTOCTRL2, 0x24}, {BRIDGE, M5602_XB_GPIO_DIR, 0x05}, {BRIDGE, M5602_XB_GPIO_DAT, 0x04}, {BRIDGE, M5602_XB_GPIO_EN_H, 0x06}, @@ -266,7 +273,7 @@ static const unsigned char init_po1030[][4] = /*end of sequence 5*/ /*sequence 2 stop */ - {SENSOR, PO1030_REG_AUTOCTRL2, 0x24}, + {SENSOR, PO1030_AUTOCTRL2, 0x24}, {BRIDGE, M5602_XB_GPIO_DIR, 0x05}, {BRIDGE, M5602_XB_GPIO_DAT, 0x04}, @@ -293,58 +300,58 @@ static const unsigned char init_po1030[][4] = {BRIDGE, M5602_XB_GPIO_EN_H, 0x06}, {BRIDGE, M5602_XB_GPIO_EN_L, 0x00}, - {SENSOR, PO1030_REG_AUTOCTRL2, 0x04}, + {SENSOR, PO1030_AUTOCTRL2, 0x04}, /* Set the width to 751 */ - {SENSOR, PO1030_REG_FRAMEWIDTH_H, 0x02}, - {SENSOR, PO1030_REG_FRAMEWIDTH_L, 0xef}, + {SENSOR, PO1030_FRAMEWIDTH_H, 0x02}, + {SENSOR, PO1030_FRAMEWIDTH_L, 0xef}, /* Set the height to 540 */ - {SENSOR, PO1030_REG_FRAMEHEIGHT_H, 0x02}, - {SENSOR, PO1030_REG_FRAMEHEIGHT_L, 0x1c}, + {SENSOR, PO1030_FRAMEHEIGHT_H, 0x02}, + {SENSOR, PO1030_FRAMEHEIGHT_L, 0x1c}, /* Set the x window to 1 */ - {SENSOR, PO1030_REG_WINDOWX_H, 0x00}, - {SENSOR, PO1030_REG_WINDOWX_L, 0x01}, + {SENSOR, PO1030_WINDOWX_H, 0x00}, + {SENSOR, PO1030_WINDOWX_L, 0x01}, /* Set the y window to 1 */ - {SENSOR, PO1030_REG_WINDOWY_H, 0x00}, - {SENSOR, PO1030_REG_WINDOWY_L, 0x01}, - - {SENSOR, PO1030_REG_WINDOWWIDTH_H, 0x02}, - {SENSOR, PO1030_REG_WINDOWWIDTH_L, 0x87}, - {SENSOR, PO1030_REG_WINDOWHEIGHT_H, 0x01}, - {SENSOR, PO1030_REG_WINDOWHEIGHT_L, 0xe3}, - - {SENSOR, PO1030_REG_OUTFORMCTRL2, 0x04}, - {SENSOR, PO1030_REG_OUTFORMCTRL2, 0x04}, - {SENSOR, PO1030_REG_AUTOCTRL1, 0x08}, - {SENSOR, PO1030_REG_CONTROL2, 0x03}, + {SENSOR, PO1030_WINDOWY_H, 0x00}, + {SENSOR, PO1030_WINDOWY_L, 0x01}, + + {SENSOR, PO1030_WINDOWWIDTH_H, 0x02}, + {SENSOR, PO1030_WINDOWWIDTH_L, 0x87}, + {SENSOR, PO1030_WINDOWHEIGHT_H, 0x01}, + {SENSOR, PO1030_WINDOWHEIGHT_L, 0xe3}, + + {SENSOR, PO1030_OUTFORMCTRL2, 0x04}, + {SENSOR, PO1030_OUTFORMCTRL2, 0x04}, + {SENSOR, PO1030_AUTOCTRL1, 0x08}, + {SENSOR, PO1030_CONTROL2, 0x03}, {SENSOR, 0x21, 0x90}, - {SENSOR, PO1030_REG_YTARGET, 0x60}, + {SENSOR, PO1030_YTARGET, 0x60}, {SENSOR, 0x59, 0x13}, - {SENSOR, PO1030_REG_OUTFORMCTRL1, 0x40}, - {SENSOR, 0x5f, 0x00}, - {SENSOR, 0x60, 0x80}, + {SENSOR, PO1030_OUTFORMCTRL1, 0x40}, + {SENSOR, PO1030_EDGE_ENH_OFF, 0x00}, + {SENSOR, PO1030_EGA, 0x80}, {SENSOR, 0x78, 0x14}, {SENSOR, 0x6f, 0x01}, - {SENSOR, PO1030_REG_CONTROL1, 0x18}, - {SENSOR, PO1030_REG_GLOBALGAINMAX, 0x14}, - {SENSOR, 0x63, 0x38}, - {SENSOR, 0x64, 0x38}, - {SENSOR, PO1030_REG_CONTROL1, 0x58}, - {SENSOR, PO1030_REG_RED_GAIN, 0x30}, - {SENSOR, PO1030_REG_GREEN_1_GAIN, 0x30}, - {SENSOR, PO1030_REG_BLUE_GAIN, 0x30}, - {SENSOR, PO1030_REG_GREEN_2_GAIN, 0x30}, - {SENSOR, PO1030_REG_GC0, 0x10}, - {SENSOR, PO1030_REG_GC1, 0x20}, - {SENSOR, PO1030_REG_GC2, 0x40}, - {SENSOR, PO1030_REG_GC3, 0x60}, - {SENSOR, PO1030_REG_GC4, 0x80}, - {SENSOR, PO1030_REG_GC5, 0xa0}, - {SENSOR, PO1030_REG_GC6, 0xc0}, - {SENSOR, PO1030_REG_GC7, 0xff}, + {SENSOR, PO1030_CONTROL1, 0x18}, + {SENSOR, PO1030_GLOBALGAINMAX, 0x14}, + {SENSOR, PO1030_Cb_U_GAIN, 0x38}, + {SENSOR, PO1030_Cr_V_GAIN, 0x38}, + {SENSOR, PO1030_CONTROL1, 0x58}, + {SENSOR, PO1030_RED_GAIN, 0x30}, + {SENSOR, PO1030_GREEN_1_GAIN, 0x30}, + {SENSOR, PO1030_BLUE_GAIN, 0x30}, + {SENSOR, PO1030_GREEN_2_GAIN, 0x30}, + {SENSOR, PO1030_GC0, 0x10}, + {SENSOR, PO1030_GC1, 0x20}, + {SENSOR, PO1030_GC2, 0x40}, + {SENSOR, PO1030_GC3, 0x60}, + {SENSOR, PO1030_GC4, 0x80}, + {SENSOR, PO1030_GC5, 0xa0}, + {SENSOR, PO1030_GC6, 0xc0}, + {SENSOR, PO1030_GC7, 0xff}, /*end of sequence 4*/ /*sequence 5*/ {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06}, @@ -374,10 +381,10 @@ static const unsigned char init_po1030[][4] = /*sequence 6*/ /* Changing 40 in f0 the image becomes green in bayer mode and red in * rgb mode */ - {SENSOR, PO1030_REG_RED_GAIN, PO1030_RED_GAIN_DEFAULT}, + {SENSOR, PO1030_RED_GAIN, PO1030_RED_GAIN_DEFAULT}, /* in changing 40 in f0 the image becomes green in bayer mode and red in * rgb mode */ - {SENSOR, PO1030_REG_BLUE_GAIN, PO1030_BLUE_GAIN_DEFAULT}, + {SENSOR, PO1030_BLUE_GAIN, PO1030_BLUE_GAIN_DEFAULT}, /* with a very low lighted environment increase the exposure but * decrease the FPS (Frame Per Second) */ @@ -386,20 +393,20 @@ static const unsigned char init_po1030[][4] = /* Controls high exposure more than SENSOR_LOW_EXPOSURE, use only in * low lighted environment (f0 is more than ff ?)*/ - {SENSOR, PO1030_REG_INTEGLINES_H, ((PO1030_EXPOSURE_DEFAULT >> 2) + {SENSOR, PO1030_INTEGLINES_H, ((PO1030_EXPOSURE_DEFAULT >> 2) & 0xff)}, /* Controls middle exposure, use only in high lighted environment */ - {SENSOR, PO1030_REG_INTEGLINES_M, PO1030_EXPOSURE_DEFAULT & 0xff}, + {SENSOR, PO1030_INTEGLINES_M, PO1030_EXPOSURE_DEFAULT & 0xff}, /* Controls clarity (not sure) */ - {SENSOR, PO1030_REG_INTEGLINES_L, 0x00}, + {SENSOR, PO1030_INTEGLINES_L, 0x00}, /* Controls gain (the image is more lighted) */ - {SENSOR, PO1030_REG_GLOBALGAIN, PO1030_GLOBAL_GAIN_DEFAULT}, + {SENSOR, PO1030_GLOBALGAIN, PO1030_GLOBAL_GAIN_DEFAULT}, /* Sets the width */ - {SENSOR, PO1030_REG_FRAMEWIDTH_H, 0x02}, - {SENSOR, PO1030_REG_FRAMEWIDTH_L, 0xef} + {SENSOR, PO1030_FRAMEWIDTH_H, 0x02}, + {SENSOR, PO1030_FRAMEWIDTH_L, 0xef} /*end of sequence 6*/ }; -- cgit v1.2.3 From de15a6450b6928374c8c4c6d6dfdf408093a44ba Mon Sep 17 00:00:00 2001 From: Erik Andr?n Date: Wed, 7 Jan 2009 21:41:47 +0100 Subject: gspca - m5602-po1030: Simplify register defines From: Erik Andr?n This patch renames some register defines in the ov9650 sensor. Priority: normal Signed-off-by: Erik Andr?n --- .../drivers/media/video/gspca/m5602/m5602_po1030.c | 2 +- .../drivers/media/video/gspca/m5602/m5602_po1030.h | 47 +++++++++++++++------- 2 files changed, 33 insertions(+), 16 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/m5602/m5602_po1030.c b/linux/drivers/media/video/gspca/m5602/m5602_po1030.c index 413c5b899..800b5f4cb 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_po1030.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_po1030.c @@ -315,7 +315,7 @@ int po1030_get_vflip(struct gspca_dev *gspca_dev, __s32 *val) struct sd *sd = (struct sd *) gspca_dev; s32 *sensor_settings = sd->sensor_priv; - *val= sensor_settings[VFLIP_IDX]; + *val = sensor_settings[VFLIP_IDX]; PDEBUG(D_V4L2, "Read vflip %d", *val); return 0; diff --git a/linux/drivers/media/video/gspca/m5602/m5602_po1030.h b/linux/drivers/media/video/gspca/m5602/m5602_po1030.h index 7402701d5..3e9648794 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_po1030.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_po1030.h @@ -115,8 +115,23 @@ #define PO1030_YCONTRAST 0x74 #define PO1030_YSATURATION 0x75 -#define PO1030_HFLIP (1 << 7) -#define PO1030_VFLIP (1 << 6) +#define PO1030_HFLIP (1 << 7) +#define PO1030_VFLIP (1 << 6) + +#define PO1030_HREF_ENABLE (1 << 6) + +#define PO1030_RAW_RGB_BAYER 0x4 + +#define PO1030_FRAME_EQUAL (1 << 3) +#define PO1030_AUTO_SUBSAMPLING (1 << 4) + +#define PO1030_WEIGHT_WIN_2X (1 << 3) + +#define PO1030_SHUTTER_MODE (1 << 6) +#define PO1030_AUTO_SUBSAMPLING (1 << 4) +#define PO1030_FRAME_EQUAL (1 << 3) + +#define PO1030_SENSOR_RESET (1 << 5) /*****************************************************************************/ @@ -171,7 +186,7 @@ static const unsigned char preinit_po1030[][3] = {BRIDGE, M5602_XB_ADC_CTRL, 0xc0}, {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0c}, - {SENSOR, PO1030_AUTOCTRL2, 0x24}, + {SENSOR, PO1030_AUTOCTRL2, PO1030_SENSOR_RESET | (1 << 2)}, {BRIDGE, M5602_XB_GPIO_DIR, 0x05}, {BRIDGE, M5602_XB_GPIO_DAT, 0x04}, @@ -203,7 +218,7 @@ static const unsigned char preinit_po1030[][3] = {BRIDGE, M5602_XB_HSYNC_PARA, 0x87}, {BRIDGE, M5602_XB_SIG_INI, 0x00}, - {SENSOR, PO1030_AUTOCTRL2, 0x24}, + {SENSOR, PO1030_AUTOCTRL2, PO1030_SENSOR_RESET | (1 << 2)}, {BRIDGE, M5602_XB_GPIO_DIR, 0x05}, {BRIDGE, M5602_XB_GPIO_DAT, 0x04}, @@ -271,9 +286,8 @@ static const unsigned char init_po1030[][4] = {BRIDGE, M5602_XB_HSYNC_PARA, 0x87}, {BRIDGE, M5602_XB_SIG_INI, 0x00}, /*end of sequence 5*/ - /*sequence 2 stop */ - {SENSOR, PO1030_AUTOCTRL2, 0x24}, + {SENSOR, PO1030_AUTOCTRL2, PO1030_SENSOR_RESET | (1 << 2)}, {BRIDGE, M5602_XB_GPIO_DIR, 0x05}, {BRIDGE, M5602_XB_GPIO_DAT, 0x04}, @@ -318,31 +332,35 @@ static const unsigned char init_po1030[][4] = {SENSOR, PO1030_WINDOWY_H, 0x00}, {SENSOR, PO1030_WINDOWY_L, 0x01}, + /* Set the window width to 647 */ {SENSOR, PO1030_WINDOWWIDTH_H, 0x02}, {SENSOR, PO1030_WINDOWWIDTH_L, 0x87}, + + /* Set the window height to 483 */ {SENSOR, PO1030_WINDOWHEIGHT_H, 0x01}, {SENSOR, PO1030_WINDOWHEIGHT_L, 0xe3}, - {SENSOR, PO1030_OUTFORMCTRL2, 0x04}, - {SENSOR, PO1030_OUTFORMCTRL2, 0x04}, - {SENSOR, PO1030_AUTOCTRL1, 0x08}, + {SENSOR, PO1030_OUTFORMCTRL2, PO1030_RAW_RGB_BAYER}, + {SENSOR, PO1030_AUTOCTRL1, PO1030_WEIGHT_WIN_2X}, + /* This makes no sense, hflip and vflp is located at bit 7, 6 */ {SENSOR, PO1030_CONTROL2, 0x03}, {SENSOR, 0x21, 0x90}, {SENSOR, PO1030_YTARGET, 0x60}, {SENSOR, 0x59, 0x13}, - {SENSOR, PO1030_OUTFORMCTRL1, 0x40}, + {SENSOR, PO1030_OUTFORMCTRL1, PO1030_HREF_ENABLE}, {SENSOR, PO1030_EDGE_ENH_OFF, 0x00}, {SENSOR, PO1030_EGA, 0x80}, {SENSOR, 0x78, 0x14}, {SENSOR, 0x6f, 0x01}, - {SENSOR, PO1030_CONTROL1, 0x18}, + {SENSOR, PO1030_CONTROL1, PO1030_AUTO_SUBSAMPLING | + PO1030_FRAME_EQUAL}, {SENSOR, PO1030_GLOBALGAINMAX, 0x14}, {SENSOR, PO1030_Cb_U_GAIN, 0x38}, {SENSOR, PO1030_Cr_V_GAIN, 0x38}, - {SENSOR, PO1030_CONTROL1, 0x58}, - {SENSOR, PO1030_RED_GAIN, 0x30}, + {SENSOR, PO1030_CONTROL1, PO1030_SHUTTER_MODE | + PO1030_AUTO_SUBSAMPLING | + PO1030_FRAME_EQUAL}, {SENSOR, PO1030_GREEN_1_GAIN, 0x30}, - {SENSOR, PO1030_BLUE_GAIN, 0x30}, {SENSOR, PO1030_GREEN_2_GAIN, 0x30}, {SENSOR, PO1030_GC0, 0x10}, {SENSOR, PO1030_GC1, 0x20}, @@ -377,7 +395,6 @@ static const unsigned char init_po1030[][4] = {BRIDGE, M5602_XB_HSYNC_PARA, 0x7e}, {BRIDGE, M5602_XB_SIG_INI, 0x00}, /*end of sequence 5*/ - /*sequence 6*/ /* Changing 40 in f0 the image becomes green in bayer mode and red in * rgb mode */ -- cgit v1.2.3 From 81addebd5c8a4e038baef9281d335145168c15b1 Mon Sep 17 00:00:00 2001 From: Erik Andr?n Date: Wed, 7 Jan 2009 22:05:08 +0100 Subject: gspca - m5602-po1030: Set all v4l2 controls at sensor init From: Erik Andr?n Previously many of the v4l2 ctrls were set to their initial values at resume from ram/disk. This patch enforces the values stored in the ctrl cache. Priority: normal Signed-off-by: Erik Andr?n --- .../drivers/media/video/gspca/m5602/m5602_po1030.c | 34 ++++++++++++++++++++-- .../drivers/media/video/gspca/m5602/m5602_po1030.h | 20 +------------ 2 files changed, 32 insertions(+), 22 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/m5602/m5602_po1030.c b/linux/drivers/media/video/gspca/m5602/m5602_po1030.c index 800b5f4cb..7ec3fbffc 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_po1030.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_po1030.c @@ -127,7 +127,7 @@ static void po1030_dump_registers(struct sd *sd); int po1030_probe(struct sd *sd) { u8 prod_id = 0, ver_id = 0, i; - s32 *sensor_settings = sd->sensor_priv; + s32 *sensor_settings; if (force_sensor) { if (force_sensor == PO1030_SENSOR) { @@ -177,11 +177,16 @@ sensor_found: for (i = 0; i < ARRAY_SIZE(po1030_ctrls); i++) sensor_settings[i] = po1030_ctrls[i].qctrl.default_value; sd->sensor_priv = sensor_settings; + + if (dump_sensor) + po1030_dump_registers(sd); + return 0; } int po1030_init(struct sd *sd) { + s32 *sensor_settings = sd->sensor_priv; int i, err = 0; /* Init the sensor */ @@ -206,10 +211,33 @@ int po1030_init(struct sd *sd) return -EINVAL; } } + if (err < 0) + return err; - if (dump_sensor) - po1030_dump_registers(sd); + err = po1030_set_exposure(&sd->gspca_dev, + sensor_settings[EXPOSURE_IDX]); + if (err < 0) + return err; + + err = po1030_set_gain(&sd->gspca_dev, sensor_settings[GAIN_IDX]); + if (err < 0) + return err; + + err = po1030_set_hflip(&sd->gspca_dev, sensor_settings[HFLIP_IDX]); + if (err < 0) + return err; + + err = po1030_set_vflip(&sd->gspca_dev, sensor_settings[VFLIP_IDX]); + if (err < 0) + return err; + + err = po1030_set_red_balance(&sd->gspca_dev, + sensor_settings[RED_BALANCE_IDX]); + if (err < 0) + return err; + err = po1030_set_red_balance(&sd->gspca_dev, + sensor_settings[BLUE_BALANCE_IDX]); return err; } diff --git a/linux/drivers/media/video/gspca/m5602/m5602_po1030.h b/linux/drivers/media/video/gspca/m5602/m5602_po1030.h index 3e9648794..013be33d1 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_po1030.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_po1030.h @@ -371,6 +371,7 @@ static const unsigned char init_po1030[][4] = {SENSOR, PO1030_GC6, 0xc0}, {SENSOR, PO1030_GC7, 0xff}, /*end of sequence 4*/ + /*sequence 5*/ {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06}, {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0}, @@ -396,31 +397,12 @@ static const unsigned char init_po1030[][4] = {BRIDGE, M5602_XB_SIG_INI, 0x00}, /*end of sequence 5*/ /*sequence 6*/ - /* Changing 40 in f0 the image becomes green in bayer mode and red in - * rgb mode */ - {SENSOR, PO1030_RED_GAIN, PO1030_RED_GAIN_DEFAULT}, - /* in changing 40 in f0 the image becomes green in bayer mode and red in - * rgb mode */ - {SENSOR, PO1030_BLUE_GAIN, PO1030_BLUE_GAIN_DEFAULT}, /* with a very low lighted environment increase the exposure but * decrease the FPS (Frame Per Second) */ {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00}, {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0}, - /* Controls high exposure more than SENSOR_LOW_EXPOSURE, use only in - * low lighted environment (f0 is more than ff ?)*/ - {SENSOR, PO1030_INTEGLINES_H, ((PO1030_EXPOSURE_DEFAULT >> 2) - & 0xff)}, - - /* Controls middle exposure, use only in high lighted environment */ - {SENSOR, PO1030_INTEGLINES_M, PO1030_EXPOSURE_DEFAULT & 0xff}, - - /* Controls clarity (not sure) */ - {SENSOR, PO1030_INTEGLINES_L, 0x00}, - /* Controls gain (the image is more lighted) */ - {SENSOR, PO1030_GLOBALGAIN, PO1030_GLOBAL_GAIN_DEFAULT}, - /* Sets the width */ {SENSOR, PO1030_FRAMEWIDTH_H, 0x02}, {SENSOR, PO1030_FRAMEWIDTH_L, 0xef} -- cgit v1.2.3 From 02837d3011a2f6ba4e2a02c6aee7f30f77d61693 Mon Sep 17 00:00:00 2001 From: Erik Andr?n Date: Thu, 8 Jan 2009 07:53:50 +0100 Subject: gspca - m5602-po1030: Add auto white balancing control From: Erik Andr?n Add a po1030 auto white balancing control that's disabled by default Priority: normal Signed-off-by: Erik Andr?n --- .../drivers/media/video/gspca/m5602/m5602_po1030.c | 51 ++++++++++++++++++++++ .../drivers/media/video/gspca/m5602/m5602_po1030.h | 2 + 2 files changed, 53 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/m5602/m5602_po1030.c b/linux/drivers/media/video/gspca/m5602/m5602_po1030.c index 7ec3fbffc..7eec6e8ca 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_po1030.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_po1030.c @@ -119,6 +119,20 @@ const static struct ctrl po1030_ctrls[] = { }, .set = po1030_set_vflip, .get = po1030_get_vflip + }, +#define AUTO_WHITE_BALANCE_IDX 6 + { + { + .id = V4L2_CID_AUTO_WHITE_BALANCE, + .type = V4L2_CTRL_TYPE_BOOLEAN, + .name = "auto white balance", + .minimum = 0, + .maximum = 1, + .step = 1, + .default_value = 0, + }, + .set = po1030_set_auto_white_balance, + .get = po1030_get_auto_white_balance } }; @@ -238,6 +252,14 @@ int po1030_init(struct sd *sd) err = po1030_set_red_balance(&sd->gspca_dev, sensor_settings[BLUE_BALANCE_IDX]); + if (err < 0) + return err; + + err = po1030_set_auto_white_balance(&sd->gspca_dev, + sensor_settings[AUTO_WHITE_BALANCE_IDX]); + if (err < 0) + return err; + return err; } @@ -425,6 +447,35 @@ int po1030_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val) return err; } +int po1030_get_auto_white_balance(struct gspca_dev *gspca_dev, __s32 *val) +{ + struct sd *sd = (struct sd *) gspca_dev; + s32 *sensor_settings = sd->sensor_priv; + + *val = sensor_settings[AUTO_WHITE_BALANCE_IDX]; + PDEBUG(D_V4L2, "Auto white balancing is %d", *val); + + return 0; +} + +int po1030_set_auto_white_balance(struct gspca_dev *gspca_dev, __s32 val) +{ + struct sd *sd = (struct sd *) gspca_dev; + s32 *sensor_settings = sd->sensor_priv; + u8 i2c_data; + int err; + + sensor_settings[AUTO_WHITE_BALANCE_IDX] = val; + + err = m5602_read_sensor(sd, PO1030_AUTOCTRL1, &i2c_data, 1); + if (err < 0) + return err; + + i2c_data = (i2c_data & 0xfe) | (val & 0x01); + err = m5602_write_sensor(sd, PO1030_AUTOCTRL1, &i2c_data, 1); + return err; +} + void po1030_disconnect(struct sd *sd) { sd->sensor = NULL; diff --git a/linux/drivers/media/video/gspca/m5602/m5602_po1030.h b/linux/drivers/media/video/gspca/m5602/m5602_po1030.h index 013be33d1..1260cfa6e 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_po1030.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_po1030.h @@ -162,6 +162,8 @@ int po1030_get_hflip(struct gspca_dev *gspca_dev, __s32 *val); int po1030_set_hflip(struct gspca_dev *gspca_dev, __s32 val); int po1030_get_vflip(struct gspca_dev *gspca_dev, __s32 *val); int po1030_set_vflip(struct gspca_dev *gspca_dev, __s32 val); +int po1030_set_auto_white_balance(struct gspca_dev *gspca_dev, __s32 val); +int po1030_get_auto_white_balance(struct gspca_dev *gspca_dev, __s32 *val); static const struct m5602_sensor po1030 = { .name = "PO1030", -- cgit v1.2.3 From 446db4040b9c2beefff8f8d02819d69d66694a9c Mon Sep 17 00:00:00 2001 From: Erik Andr?n Date: Thu, 8 Jan 2009 08:01:23 +0100 Subject: gspca - m5602-po1030: Remove unnecessary error check From: Erik Andr?n Priority: normal Signed-off-by: Erik Andr?n --- linux/drivers/media/video/gspca/m5602/m5602_po1030.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/m5602/m5602_po1030.c b/linux/drivers/media/video/gspca/m5602/m5602_po1030.c index 7eec6e8ca..0547841b2 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_po1030.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_po1030.c @@ -257,9 +257,6 @@ int po1030_init(struct sd *sd) err = po1030_set_auto_white_balance(&sd->gspca_dev, sensor_settings[AUTO_WHITE_BALANCE_IDX]); - if (err < 0) - return err; - return err; } -- cgit v1.2.3 From eb5048481558b0ffb869825cf1b287ab08b63695 Mon Sep 17 00:00:00 2001 From: Erik Andr?n Date: Thu, 8 Jan 2009 08:04:19 +0100 Subject: gspca - m5602-po1030: Probe read only register at probe time From: Erik Andr?n Currently, we're probing r/w registers at probe time. This is potentially dangerous, probe some read only registers instead. Priority: normal Signed-off-by: Erik Andr?n --- linux/drivers/media/video/gspca/m5602/m5602_po1030.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/m5602/m5602_po1030.c b/linux/drivers/media/video/gspca/m5602/m5602_po1030.c index 0547841b2..122c777c7 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_po1030.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_po1030.c @@ -140,7 +140,7 @@ static void po1030_dump_registers(struct sd *sd); int po1030_probe(struct sd *sd) { - u8 prod_id = 0, ver_id = 0, i; + u8 dev_id_h = 0, dev_id_l = 0, i; s32 *sensor_settings; if (force_sensor) { @@ -165,13 +165,13 @@ int po1030_probe(struct sd *sd) m5602_write_bridge(sd, preinit_po1030[i][1], data); } - if (m5602_read_sensor(sd, 0x3, &prod_id, 1)) + if (m5602_read_sensor(sd, PO1030_DEVID_H, &dev_id_h, 1)) return -ENODEV; - if (m5602_read_sensor(sd, 0x4, &ver_id, 1)) + if (m5602_read_sensor(sd, PO1030_DEVID_L, &dev_id_l, 1)) return -ENODEV; - if ((prod_id == 0x02) && (ver_id == 0xef)) { + if ((dev_id_h == 0x10) && (dev_id_l == 0x30)) { info("Detected a po1030 sensor"); goto sensor_found; } -- cgit v1.2.3 From b57d73529a29d046f3d01a40b27613af57ea6f5e Mon Sep 17 00:00:00 2001 From: Erik Andr?n Date: Thu, 8 Jan 2009 18:15:06 +0100 Subject: gspca - m5602-po1030: Split up the init into init and start From: Erik Andr?n Split up the po1030 init into start and init. Add a start function. Priority: normal Signed-off-by: Erik Andr?n --- linux/drivers/media/video/gspca/m5602/m5602_po1030.c | 17 +++++++++++++++++ linux/drivers/media/video/gspca/m5602/m5602_po1030.h | 14 +++++++++----- 2 files changed, 26 insertions(+), 5 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/m5602/m5602_po1030.c b/linux/drivers/media/video/gspca/m5602/m5602_po1030.c index 122c777c7..c2bd12eeb 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_po1030.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_po1030.c @@ -260,6 +260,23 @@ int po1030_init(struct sd *sd) return err; } +int po1030_start(struct sd *sd) +{ + int i, err = 0; + /* Synthesize the vsync/hsync setup */ + for (i = 0; i < ARRAY_SIZE(start_po1030) && !err; i++) { + if (start_po1030[i][0] == BRIDGE) + err = m5602_write_bridge(sd, start_po1030[i][1], + start_po1030[i][2]); + else if (start_po1030[i][0] == SENSOR) { + u8 data = start_po1030[i][2]; + err = m5602_write_sensor(sd, + start_po1030[i][1], &data, 1); + } + } + return err; +} + int po1030_get_exposure(struct gspca_dev *gspca_dev, __s32 *val) { struct sd *sd = (struct sd *) gspca_dev; diff --git a/linux/drivers/media/video/gspca/m5602/m5602_po1030.h b/linux/drivers/media/video/gspca/m5602/m5602_po1030.h index 1260cfa6e..451d20652 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_po1030.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_po1030.h @@ -148,6 +148,7 @@ extern int dump_sensor; int po1030_probe(struct sd *sd); int po1030_init(struct sd *sd); +int po1030_start(struct sd *sd); void po1030_disconnect(struct sd *sd); int po1030_get_exposure(struct gspca_dev *gspca_dev, __s32 *val); @@ -173,6 +174,7 @@ static const struct m5602_sensor po1030 = { .probe = po1030_probe, .init = po1030_init, + .start = po1030_start, .disconnect = po1030_disconnect, }; @@ -237,7 +239,7 @@ static const unsigned char preinit_po1030[][3] = {BRIDGE, M5602_XB_GPIO_DAT, 0x00} }; -static const unsigned char init_po1030[][4] = +static const unsigned char init_po1030[][3] = { {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02}, {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0}, @@ -299,11 +301,13 @@ static const unsigned char init_po1030[][4] = {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x04}, {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0}, /*end of sequence 2 stop */ +}; -/* --------------------------------- - * end of init - begin of start - * --------------------------------- */ - +static const unsigned char start_po1030[][3] = +{ + /* --------------------------------- + * end of init - begin of start + * --------------------------------- */ /*sequence 3*/ {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00}, {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0}, -- cgit v1.2.3 From 617c15eff1b6db4e52c5147c9ab5f1650badd05a Mon Sep 17 00:00:00 2001 From: Erik Andr?n Date: Thu, 8 Jan 2009 18:22:51 +0100 Subject: gspca - m5602-po1030: Remove unneeded init sequences From: Erik Andr?n po1030: There's a lot of redundant writes to the bridge and sensor. Remove them. Priority: normal Signed-off-by: Erik Andr?n --- .../drivers/media/video/gspca/m5602/m5602_po1030.h | 52 ---------------------- 1 file changed, 52 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/m5602/m5602_po1030.h b/linux/drivers/media/video/gspca/m5602/m5602_po1030.h index 451d20652..9ccf89e59 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_po1030.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_po1030.h @@ -254,42 +254,6 @@ static const unsigned char init_po1030[][3] = {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0c}, /*end of sequence 1*/ - /*sequence 2 (same as stop sequence)*/ - {SENSOR, PO1030_AUTOCTRL2, 0x24}, - {BRIDGE, M5602_XB_GPIO_DIR, 0x05}, - {BRIDGE, M5602_XB_GPIO_DAT, 0x04}, - {BRIDGE, M5602_XB_GPIO_EN_H, 0x06}, - {BRIDGE, M5602_XB_GPIO_DIR_H, 0x06}, - {BRIDGE, M5602_XB_GPIO_DAT_H, 0x02}, - - {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x04}, - {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0}, - /*end of sequence 2*/ - - /*sequence 5*/ - {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06}, - {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0}, - {BRIDGE, M5602_XB_ADC_CTRL, 0xc0}, - {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0c}, - {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81}, - {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82}, - {BRIDGE, M5602_XB_SIG_INI, 0x01}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x02}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x01}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0xec}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, - {BRIDGE, M5602_XB_SIG_INI, 0x00}, - {BRIDGE, M5602_XB_SIG_INI, 0x02}, - {BRIDGE, M5602_XB_HSYNC_PARA, 0x00}, - {BRIDGE, M5602_XB_HSYNC_PARA, 0x00}, - {BRIDGE, M5602_XB_HSYNC_PARA, 0x02}, - {BRIDGE, M5602_XB_HSYNC_PARA, 0x87}, - {BRIDGE, M5602_XB_SIG_INI, 0x00}, - /*end of sequence 5*/ /*sequence 2 stop */ {SENSOR, PO1030_AUTOCTRL2, PO1030_SENSOR_RESET | (1 << 2)}, @@ -305,15 +269,6 @@ static const unsigned char init_po1030[][3] = static const unsigned char start_po1030[][3] = { - /* --------------------------------- - * end of init - begin of start - * --------------------------------- */ - /*sequence 3*/ - {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00}, - {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0}, - {BRIDGE, M5602_XB_ADC_CTRL, 0xc0}, - {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0c}, - /*end of sequence 3*/ /*sequence 4*/ {BRIDGE, M5602_XB_GPIO_DIR, 0x05}, {BRIDGE, M5602_XB_GPIO_DAT, 0x00}, @@ -358,8 +313,6 @@ static const unsigned char start_po1030[][3] = {SENSOR, PO1030_EGA, 0x80}, {SENSOR, 0x78, 0x14}, {SENSOR, 0x6f, 0x01}, - {SENSOR, PO1030_CONTROL1, PO1030_AUTO_SUBSAMPLING | - PO1030_FRAME_EQUAL}, {SENSOR, PO1030_GLOBALGAINMAX, 0x14}, {SENSOR, PO1030_Cb_U_GAIN, 0x38}, {SENSOR, PO1030_Cr_V_GAIN, 0x38}, @@ -408,11 +361,6 @@ static const unsigned char start_po1030[][3] = * decrease the FPS (Frame Per Second) */ {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00}, {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0}, - - /* Sets the width */ - {SENSOR, PO1030_FRAMEWIDTH_H, 0x02}, - {SENSOR, PO1030_FRAMEWIDTH_L, 0xef} - /*end of sequence 6*/ }; #endif -- cgit v1.2.3 From 60879db1480a780ca0be9895ed266b5c812397fd Mon Sep 17 00:00:00 2001 From: Erik Andr?n Date: Thu, 8 Jan 2009 22:11:05 +0100 Subject: gspca - m5602-mt9m111: Set the cached v4l2 ctrl values From: Erik Andr?n When we resume the machine we want the previously set values, not the default values. Fix this for the mt9m111 sensor Priority: normal Signed-off-by: Erik Andr?n --- linux/drivers/media/video/gspca/m5602/m5602_mt9m111.c | 17 ++++++++++++++--- linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h | 6 ------ 2 files changed, 14 insertions(+), 9 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.c b/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.c index 519548d07..8700f37de 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.c @@ -136,12 +136,16 @@ sensor_found: sensor_settings[i] = mt9m111_ctrls[i].qctrl.default_value; sd->sensor_priv = sensor_settings; + if (dump_sensor) + mt9m111_dump_registers(sd); + return 0; } int mt9m111_init(struct sd *sd) { int i, err = 0; + s32 *sensor_settings = sd->sensor_priv; /* Init the sensor */ for (i = 0; i < ARRAY_SIZE(init_mt9m111) && !err; i++) { @@ -159,10 +163,17 @@ int mt9m111_init(struct sd *sd) } } - if (dump_sensor) - mt9m111_dump_registers(sd); + err = mt9m111_set_vflip(&sd->gspca_dev, sensor_settings[VFLIP_IDX]); + if (err < 0) + return err; + + err = mt9m111_set_hflip(&sd->gspca_dev, sensor_settings[HFLIP_IDX]); + if (err < 0) + return err; + + err = mt9m111_set_gain(&sd->gspca_dev, sensor_settings[GAIN_IDX]); - return (err < 0) ? err : 0; + return err; } void mt9m111_disconnect(struct sd *sd) diff --git a/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h b/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h index 913863247..c198734c8 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h @@ -290,7 +290,6 @@ static const unsigned char init_mt9m111[][4] = {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xa0, 0x00}, {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, {SENSOR, MT9M111_SC_SHUTTER_WIDTH, 0x01, 0xf4}, - {SENSOR, MT9M111_SC_GLOBAL_GAIN, 0x00, 0xea}, {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06, 0x00}, {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, @@ -452,7 +451,6 @@ static const unsigned char init_mt9m111[][4] = {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xa0, 0x00}, {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, {SENSOR, MT9M111_SC_SHUTTER_WIDTH, 0x01, 0xf4}, - {SENSOR, MT9M111_SC_GLOBAL_GAIN, 0x00, 0xea}, {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, @@ -590,7 +588,6 @@ static const unsigned char init_mt9m111[][4] = {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xa0, 0x00}, {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, {SENSOR, MT9M111_SC_SHUTTER_WIDTH, 0x01, 0xf4}, - {SENSOR, MT9M111_SC_GLOBAL_GAIN, 0x00, 0xea}, {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, @@ -766,7 +763,6 @@ static const unsigned char init_mt9m111[][4] = {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, {SENSOR, MT9M111_SC_SHUTTER_WIDTH, 0x01, 0x90}, - {SENSOR, MT9M111_SC_GLOBAL_GAIN, 0x00, 0xe6}, {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, @@ -945,8 +941,6 @@ static const unsigned char init_mt9m111[][4] = {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, /* Set number of blank rows chosen to 400 */ {SENSOR, MT9M111_SC_SHUTTER_WIDTH, 0x01, 0x90}, - /* Set the global gain to 283 (of 512) */ - {SENSOR, MT9M111_SC_GLOBAL_GAIN, 0x03, 0x63} }; #endif -- cgit v1.2.3 From b3c271af622d8a162ecbffbe23b0e4e12b9a1d89 Mon Sep 17 00:00:00 2001 From: Erik Andr?n Date: Fri, 9 Jan 2009 07:30:54 +0100 Subject: gspca - m5602-s5k4aa: Set all v4l2 ctrls on sensor init. From: Erik Andr?n Reset all v4l2 ctrls on the s5k4aa init. The prevents all ctrls to be reset during resume from ram. Priority: normal Signed-off-by: Erik Andr?n --- .../drivers/media/video/gspca/m5602/m5602_s5k4aa.c | 45 +++++++++++----------- 1 file changed, 22 insertions(+), 23 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c b/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c index d4f45d44d..14d958bd0 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c @@ -206,6 +206,10 @@ sensor_found: for (i = 0; i < ARRAY_SIZE(s5k4aa_ctrls); i++) sensor_settings[i] = s5k4aa_ctrls[i].qctrl.default_value; sd->sensor_priv = sensor_settings; + + if (dump_sensor) + s5k4aa_dump_registers(sd); + return 0; } @@ -215,8 +219,7 @@ int s5k4aa_start(struct sd *sd) u8 data[2]; struct cam *cam = &sd->gspca_dev.cam; - switch (cam->cam_mode[sd->gspca_dev.curr_mode].width) - { + switch (cam->cam_mode[sd->gspca_dev.curr_mode].width) { case 640: PDEBUG(D_V4L2, "Configuring camera for VGA mode"); @@ -255,6 +258,7 @@ int s5k4aa_start(struct sd *sd) int s5k4aa_init(struct sd *sd) { int i, err = 0; + s32 *sensor_settings = sd->sensor_priv; for (i = 0; i < ARRAY_SIZE(init_s5k4aa) && !err; i++) { u8 data[2] = {0x00, 0x00}; @@ -284,30 +288,22 @@ int s5k4aa_init(struct sd *sd) } } - if (dump_sensor) - s5k4aa_dump_registers(sd); + err = s5k4aa_set_exposure(&sd->gspca_dev, + sensor_settings[EXPOSURE_IDX]); + if (err < 0) + return err; - if (!err && dmi_check_system(s5k4aa_vflip_dmi_table)) { - u8 data = 0x02; - info("vertical flip quirk active"); - m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1); - m5602_read_sensor(sd, S5K4AA_READ_MODE, &data, 1); - data |= S5K4AA_RM_V_FLIP; - data &= ~S5K4AA_RM_H_FLIP; - m5602_write_sensor(sd, S5K4AA_READ_MODE, &data, 1); - - /* Decrement COLSTART to preserve color order (BGGR) */ - m5602_read_sensor(sd, S5K4AA_COLSTART_LO, &data, 1); - data--; - m5602_write_sensor(sd, S5K4AA_COLSTART_LO, &data, 1); + err = s5k4aa_set_gain(&sd->gspca_dev, sensor_settings[GAIN_IDX]); + if (err < 0) + return err; - /* Increment ROWSTART to preserve color order (BGGR) */ - m5602_read_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1); - data++; - m5602_write_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1); - } + err = s5k4aa_set_vflip(&sd->gspca_dev, sensor_settings[VFLIP_IDX]); + if (err < 0) + return err; - return (err < 0) ? err : 0; + err = s5k4aa_set_hflip(&sd->gspca_dev, sensor_settings[HFLIP_IDX]); + + return err; } int s5k4aa_get_exposure(struct gspca_dev *gspca_dev, __s32 *val) @@ -380,6 +376,9 @@ int s5k4aa_set_vflip(struct gspca_dev *gspca_dev, __s32 val) if (err < 0) return err; + if (dmi_check_system(s5k4aa_vflip_dmi_table)) + val = !val; + if (val) { err = m5602_read_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1); if (err < 0) -- cgit v1.2.3 From d6a285a1117236b4293bc9a70baf0c967aabc54e Mon Sep 17 00:00:00 2001 From: Erik Andr?n Date: Fri, 3 Apr 2009 07:49:10 +0200 Subject: gspca - m5602: Let all ctrls on all sensors be static From: Erik Andr?n All hail the static keyword Priority: normal Signed-off-by: Erik Andr?n --- .../media/video/gspca/m5602/m5602_mt9m111.c | 22 ++-- .../media/video/gspca/m5602/m5602_mt9m111.h | 7 -- .../drivers/media/video/gspca/m5602/m5602_ov9650.c | 115 +++++++++------------ .../drivers/media/video/gspca/m5602/m5602_ov9650.h | 19 ---- .../drivers/media/video/gspca/m5602/m5602_po1030.c | 47 ++++++--- .../drivers/media/video/gspca/m5602/m5602_po1030.h | 15 --- .../drivers/media/video/gspca/m5602/m5602_s5k4aa.c | 25 +++-- .../drivers/media/video/gspca/m5602/m5602_s5k4aa.h | 9 -- .../drivers/media/video/gspca/m5602/m5602_s5k83a.c | 31 ++++-- .../drivers/media/video/gspca/m5602/m5602_s5k83a.h | 11 -- 10 files changed, 137 insertions(+), 164 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.c b/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.c index 8700f37de..8017782ef 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.c @@ -18,6 +18,13 @@ #include "m5602_mt9m111.h" +static int mt9m111_set_vflip(struct gspca_dev *gspca_dev, __s32 val); +static int mt9m111_get_vflip(struct gspca_dev *gspca_dev, __s32 *val); +static int mt9m111_get_hflip(struct gspca_dev *gspca_dev, __s32 *val); +static int mt9m111_set_hflip(struct gspca_dev *gspca_dev, __s32 val); +static int mt9m111_get_gain(struct gspca_dev *gspca_dev, __s32 *val); +static int mt9m111_set_gain(struct gspca_dev *gspca_dev, __s32 val); + static struct v4l2_pix_format mt9m111_modes[] = { { 640, @@ -123,7 +130,8 @@ int mt9m111_probe(struct sd *sd) return -ENODEV; sensor_found: - sensor_settings = kmalloc(ARRAY_SIZE(mt9m111_ctrls) * sizeof(s32), GFP_KERNEL); + sensor_settings = kmalloc(ARRAY_SIZE(mt9m111_ctrls) * sizeof(s32), + GFP_KERNEL); if (!sensor_settings) return -ENOMEM; @@ -182,7 +190,7 @@ void mt9m111_disconnect(struct sd *sd) kfree(sd->sensor_priv); } -int mt9m111_get_vflip(struct gspca_dev *gspca_dev, __s32 *val) +static int mt9m111_get_vflip(struct gspca_dev *gspca_dev, __s32 *val) { struct sd *sd = (struct sd *) gspca_dev; s32 *sensor_settings = sd->sensor_priv; @@ -193,7 +201,7 @@ int mt9m111_get_vflip(struct gspca_dev *gspca_dev, __s32 *val) return 0; } -int mt9m111_set_vflip(struct gspca_dev *gspca_dev, __s32 val) +static int mt9m111_set_vflip(struct gspca_dev *gspca_dev, __s32 val) { int err; u8 data[2] = {0x00, 0x00}; @@ -219,7 +227,7 @@ int mt9m111_set_vflip(struct gspca_dev *gspca_dev, __s32 val) return err; } -int mt9m111_get_hflip(struct gspca_dev *gspca_dev, __s32 *val) +static int mt9m111_get_hflip(struct gspca_dev *gspca_dev, __s32 *val) { struct sd *sd = (struct sd *) gspca_dev; s32 *sensor_settings = sd->sensor_priv; @@ -230,7 +238,7 @@ int mt9m111_get_hflip(struct gspca_dev *gspca_dev, __s32 *val) return 0; } -int mt9m111_set_hflip(struct gspca_dev *gspca_dev, __s32 val) +static int mt9m111_set_hflip(struct gspca_dev *gspca_dev, __s32 val) { int err; u8 data[2] = {0x00, 0x00}; @@ -255,7 +263,7 @@ int mt9m111_set_hflip(struct gspca_dev *gspca_dev, __s32 val) return err; } -int mt9m111_get_gain(struct gspca_dev *gspca_dev, __s32 *val) +static int mt9m111_get_gain(struct gspca_dev *gspca_dev, __s32 *val) { struct sd *sd = (struct sd *) gspca_dev; s32 *sensor_settings = sd->sensor_priv; @@ -266,7 +274,7 @@ int mt9m111_get_gain(struct gspca_dev *gspca_dev, __s32 *val) return 0; } -int mt9m111_set_gain(struct gspca_dev *gspca_dev, __s32 val) +static int mt9m111_set_gain(struct gspca_dev *gspca_dev, __s32 val) { int err, tmp; u8 data[2] = {0x00, 0x00}; diff --git a/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h b/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h index c198734c8..dbda4a63d 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h @@ -87,13 +87,6 @@ int mt9m111_probe(struct sd *sd); int mt9m111_init(struct sd *sd); void mt9m111_disconnect(struct sd *sd); -int mt9m111_set_vflip(struct gspca_dev *gspca_dev, __s32 val); -int mt9m111_get_vflip(struct gspca_dev *gspca_dev, __s32 *val); -int mt9m111_get_hflip(struct gspca_dev *gspca_dev, __s32 *val); -int mt9m111_set_hflip(struct gspca_dev *gspca_dev, __s32 val); -int mt9m111_get_gain(struct gspca_dev *gspca_dev, __s32 *val); -int mt9m111_set_gain(struct gspca_dev *gspca_dev, __s32 val); - const static struct m5602_sensor mt9m111 = { .name = "MT9M111", diff --git a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c index 96fb8c026..be59fe7af 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c @@ -18,6 +18,25 @@ #include "m5602_ov9650.h" +static int ov9650_set_exposure(struct gspca_dev *gspca_dev, __s32 val); +static int ov9650_get_exposure(struct gspca_dev *gspca_dev, __s32 *val); +static int ov9650_get_gain(struct gspca_dev *gspca_dev, __s32 *val); +static int ov9650_set_gain(struct gspca_dev *gspca_dev, __s32 val); +static int ov9650_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val); +static int ov9650_set_red_balance(struct gspca_dev *gspca_dev, __s32 val); +static int ov9650_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val); +static int ov9650_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val); +static int ov9650_get_hflip(struct gspca_dev *gspca_dev, __s32 *val); +static int ov9650_set_hflip(struct gspca_dev *gspca_dev, __s32 val); +static int ov9650_get_vflip(struct gspca_dev *gspca_dev, __s32 *val); +static int ov9650_set_vflip(struct gspca_dev *gspca_dev, __s32 val); +static int ov9650_get_auto_white_balance(struct gspca_dev *gspca_dev, + __s32 *val); +static int ov9650_set_auto_white_balance(struct gspca_dev *gspca_dev, + __s32 val); +static int ov9650_get_auto_gain(struct gspca_dev *gspca_dev, __s32 *val); +static int ov9650_set_auto_gain(struct gspca_dev *gspca_dev, __s32 val); + /* Vertically and horizontally flips the image if matched, needed for machines where the sensor is mounted upside down */ static @@ -312,7 +331,8 @@ int ov9650_init(struct sd *sd) err = m5602_write_bridge(sd, init_ov9650[i][1], data); } - err = ov9650_set_exposure(&sd->gspca_dev, sensor_settings[EXPOSURE_IDX]); + err = ov9650_set_exposure(&sd->gspca_dev, + sensor_settings[EXPOSURE_IDX]); if (err < 0) return err; @@ -320,11 +340,13 @@ int ov9650_init(struct sd *sd) if (err < 0) return err; - err = ov9650_set_red_balance(&sd->gspca_dev, sensor_settings[RED_BALANCE_IDX]); + err = ov9650_set_red_balance(&sd->gspca_dev, + sensor_settings[RED_BALANCE_IDX]); if (err < 0) return err; - err = ov9650_set_blue_balance(&sd->gspca_dev, sensor_settings[BLUE_BALANCE_IDX]); + err = ov9650_set_blue_balance(&sd->gspca_dev, + sensor_settings[BLUE_BALANCE_IDX]); if (err < 0) return err; @@ -336,11 +358,13 @@ int ov9650_init(struct sd *sd) if (err < 0) return err; - err = ov9650_set_auto_white_balance(&sd->gspca_dev, sensor_settings[AUTO_WHITE_BALANCE_IDX]); + err = ov9650_set_auto_white_balance(&sd->gspca_dev, + sensor_settings[AUTO_WHITE_BALANCE_IDX]); if (err < 0) return err; - err = ov9650_set_auto_gain(&sd->gspca_dev, sensor_settings[AUTO_GAIN_CTRL_IDX]); + err = ov9650_set_auto_gain(&sd->gspca_dev, + sensor_settings[AUTO_GAIN_CTRL_IDX]); return err; } @@ -474,7 +498,7 @@ void ov9650_disconnect(struct sd *sd) kfree(sd->sensor_priv); } -int ov9650_get_exposure(struct gspca_dev *gspca_dev, __s32 *val) +static int ov9650_get_exposure(struct gspca_dev *gspca_dev, __s32 *val) { struct sd *sd = (struct sd *) gspca_dev; s32 *sensor_settings = sd->sensor_priv; @@ -484,7 +508,7 @@ int ov9650_get_exposure(struct gspca_dev *gspca_dev, __s32 *val) return 0; } -int ov9650_set_exposure(struct gspca_dev *gspca_dev, __s32 val) +static int ov9650_set_exposure(struct gspca_dev *gspca_dev, __s32 val) { struct sd *sd = (struct sd *) gspca_dev; s32 *sensor_settings = sd->sensor_priv; @@ -514,7 +538,7 @@ int ov9650_set_exposure(struct gspca_dev *gspca_dev, __s32 val) return err; } -int ov9650_get_gain(struct gspca_dev *gspca_dev, __s32 *val) +static int ov9650_get_gain(struct gspca_dev *gspca_dev, __s32 *val) { struct sd *sd = (struct sd *) gspca_dev; s32 *sensor_settings = sd->sensor_priv; @@ -524,7 +548,7 @@ int ov9650_get_gain(struct gspca_dev *gspca_dev, __s32 *val) return 0; } -int ov9650_set_gain(struct gspca_dev *gspca_dev, __s32 val) +static int ov9650_set_gain(struct gspca_dev *gspca_dev, __s32 val) { int err; u8 i2c_data; @@ -555,7 +579,7 @@ int ov9650_set_gain(struct gspca_dev *gspca_dev, __s32 val) return err; } -int ov9650_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val) +static int ov9650_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val) { struct sd *sd = (struct sd *) gspca_dev; s32 *sensor_settings = sd->sensor_priv; @@ -565,7 +589,7 @@ int ov9650_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val) return 0; } -int ov9650_set_red_balance(struct gspca_dev *gspca_dev, __s32 val) +static int ov9650_set_red_balance(struct gspca_dev *gspca_dev, __s32 val) { int err; u8 i2c_data; @@ -581,7 +605,7 @@ int ov9650_set_red_balance(struct gspca_dev *gspca_dev, __s32 val) return err; } -int ov9650_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val) +static int ov9650_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val) { struct sd *sd = (struct sd *) gspca_dev; s32 *sensor_settings = sd->sensor_priv; @@ -592,7 +616,7 @@ int ov9650_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val) return 0; } -int ov9650_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val) +static int ov9650_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val) { int err; u8 i2c_data; @@ -608,7 +632,7 @@ int ov9650_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val) return err; } -int ov9650_get_hflip(struct gspca_dev *gspca_dev, __s32 *val) +static int ov9650_get_hflip(struct gspca_dev *gspca_dev, __s32 *val) { struct sd *sd = (struct sd *) gspca_dev; s32 *sensor_settings = sd->sensor_priv; @@ -618,7 +642,7 @@ int ov9650_get_hflip(struct gspca_dev *gspca_dev, __s32 *val) return 0; } -int ov9650_set_hflip(struct gspca_dev *gspca_dev, __s32 val) +static int ov9650_set_hflip(struct gspca_dev *gspca_dev, __s32 val) { int err; u8 i2c_data; @@ -630,16 +654,18 @@ int ov9650_set_hflip(struct gspca_dev *gspca_dev, __s32 val) sensor_settings[HFLIP_IDX] = val; if (!dmi_check_system(ov9650_flip_dmi_table)) - i2c_data = ((val & 0x01) << 5) | (sensor_settings[VFLIP_IDX] << 4); + i2c_data = ((val & 0x01) << 5) | + (sensor_settings[VFLIP_IDX] << 4); else - i2c_data = ((val & 0x01) << 5) | (!sensor_settings[VFLIP_IDX] << 4); + i2c_data = ((val & 0x01) << 5) | + (!sensor_settings[VFLIP_IDX] << 4); err = m5602_write_sensor(sd, OV9650_MVFP, &i2c_data, 1); return err; } -int ov9650_get_vflip(struct gspca_dev *gspca_dev, __s32 *val) +static int ov9650_get_vflip(struct gspca_dev *gspca_dev, __s32 *val) { struct sd *sd = (struct sd *) gspca_dev; s32 *sensor_settings = sd->sensor_priv; @@ -650,7 +676,7 @@ int ov9650_get_vflip(struct gspca_dev *gspca_dev, __s32 *val) return 0; } -int ov9650_set_vflip(struct gspca_dev *gspca_dev, __s32 val) +static int ov9650_set_vflip(struct gspca_dev *gspca_dev, __s32 val) { int err; u8 i2c_data; @@ -675,48 +701,8 @@ int ov9650_set_vflip(struct gspca_dev *gspca_dev, __s32 val) return err; } -int ov9650_get_brightness(struct gspca_dev *gspca_dev, __s32 *val) -{ - struct sd *sd = (struct sd *) gspca_dev; - s32 *sensor_settings = sd->sensor_priv; - - *val = sensor_settings[GAIN_IDX]; - PDEBUG(D_V4L2, "Read gain %d", *val); - - return 0; -} - -int ov9650_set_brightness(struct gspca_dev *gspca_dev, __s32 val) -{ - int err; - u8 i2c_data; - struct sd *sd = (struct sd *) gspca_dev; - s32 *sensor_settings = sd->sensor_priv; - - PDEBUG(D_V4L2, "Set gain to %d", val); - - sensor_settings[GAIN_IDX] = val; - - /* Read the OV9650_VREF register first to avoid - corrupting the VREF high and low bits */ - err = m5602_read_sensor(sd, OV9650_VREF, &i2c_data, 1); - if (err < 0) - return err; - - /* Mask away all uninteresting bits */ - i2c_data = ((val & 0x0300) >> 2) | (i2c_data & 0x3F); - err = m5602_write_sensor(sd, OV9650_VREF, &i2c_data, 1); - if (err < 0) - return err; - - /* The 8 LSBs */ - i2c_data = val & 0xff; - err = m5602_write_sensor(sd, OV9650_GAIN, &i2c_data, 1); - - return err; -} - -int ov9650_get_auto_white_balance(struct gspca_dev *gspca_dev, __s32 *val) +static int ov9650_get_auto_white_balance(struct gspca_dev *gspca_dev, + __s32 *val) { struct sd *sd = (struct sd *) gspca_dev; s32 *sensor_settings = sd->sensor_priv; @@ -725,7 +711,8 @@ int ov9650_get_auto_white_balance(struct gspca_dev *gspca_dev, __s32 *val) return 0; } -int ov9650_set_auto_white_balance(struct gspca_dev *gspca_dev, __s32 val) +static int ov9650_set_auto_white_balance(struct gspca_dev *gspca_dev, + __s32 val) { int err; u8 i2c_data; @@ -745,7 +732,7 @@ int ov9650_set_auto_white_balance(struct gspca_dev *gspca_dev, __s32 val) return err; } -int ov9650_get_auto_gain(struct gspca_dev *gspca_dev, __s32 *val) +static int ov9650_get_auto_gain(struct gspca_dev *gspca_dev, __s32 *val) { struct sd *sd = (struct sd *) gspca_dev; s32 *sensor_settings = sd->sensor_priv; @@ -755,7 +742,7 @@ int ov9650_get_auto_gain(struct gspca_dev *gspca_dev, __s32 *val) return 0; } -int ov9650_set_auto_gain(struct gspca_dev *gspca_dev, __s32 val) +static int ov9650_set_auto_gain(struct gspca_dev *gspca_dev, __s32 val) { int err; u8 i2c_data; diff --git a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.h b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.h index b81f26505..e0ba41870 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.h @@ -139,25 +139,6 @@ int ov9650_start(struct sd *sd); int ov9650_stop(struct sd *sd); void ov9650_disconnect(struct sd *sd); -int ov9650_set_exposure(struct gspca_dev *gspca_dev, __s32 val); -int ov9650_get_exposure(struct gspca_dev *gspca_dev, __s32 *val); -int ov9650_get_gain(struct gspca_dev *gspca_dev, __s32 *val); -int ov9650_set_gain(struct gspca_dev *gspca_dev, __s32 val); -int ov9650_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val); -int ov9650_set_red_balance(struct gspca_dev *gspca_dev, __s32 val); -int ov9650_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val); -int ov9650_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val); -int ov9650_get_hflip(struct gspca_dev *gspca_dev, __s32 *val); -int ov9650_set_hflip(struct gspca_dev *gspca_dev, __s32 val); -int ov9650_get_vflip(struct gspca_dev *gspca_dev, __s32 *val); -int ov9650_set_vflip(struct gspca_dev *gspca_dev, __s32 val); -int ov9650_get_brightness(struct gspca_dev *gspca_dev, __s32 *val); -int ov9650_set_brightness(struct gspca_dev *gspca_dev, __s32 val); -int ov9650_get_auto_white_balance(struct gspca_dev *gspca_dev, __s32 *val); -int ov9650_set_auto_white_balance(struct gspca_dev *gspca_dev, __s32 val); -int ov9650_get_auto_gain(struct gspca_dev *gspca_dev, __s32 *val); -int ov9650_set_auto_gain(struct gspca_dev *gspca_dev, __s32 val); - const static struct m5602_sensor ov9650 = { .name = "OV9650", .i2c_slave_id = 0x60, diff --git a/linux/drivers/media/video/gspca/m5602/m5602_po1030.c b/linux/drivers/media/video/gspca/m5602/m5602_po1030.c index c2bd12eeb..79dcf9bfd 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_po1030.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_po1030.c @@ -18,6 +18,23 @@ #include "m5602_po1030.h" +static int po1030_get_exposure(struct gspca_dev *gspca_dev, __s32 *val); +static int po1030_set_exposure(struct gspca_dev *gspca_dev, __s32 val); +static int po1030_get_gain(struct gspca_dev *gspca_dev, __s32 *val); +static int po1030_set_gain(struct gspca_dev *gspca_dev, __s32 val); +static int po1030_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val); +static int po1030_set_red_balance(struct gspca_dev *gspca_dev, __s32 val); +static int po1030_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val); +static int po1030_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val); +static int po1030_get_hflip(struct gspca_dev *gspca_dev, __s32 *val); +static int po1030_set_hflip(struct gspca_dev *gspca_dev, __s32 val); +static int po1030_get_vflip(struct gspca_dev *gspca_dev, __s32 *val); +static int po1030_set_vflip(struct gspca_dev *gspca_dev, __s32 val); +static int po1030_set_auto_white_balance(struct gspca_dev *gspca_dev, + __s32 val); +static int po1030_get_auto_white_balance(struct gspca_dev *gspca_dev, + __s32 *val); + static struct v4l2_pix_format po1030_modes[] = { { 640, @@ -277,7 +294,7 @@ int po1030_start(struct sd *sd) return err; } -int po1030_get_exposure(struct gspca_dev *gspca_dev, __s32 *val) +static int po1030_get_exposure(struct gspca_dev *gspca_dev, __s32 *val) { struct sd *sd = (struct sd *) gspca_dev; s32 *sensor_settings = sd->sensor_priv; @@ -287,7 +304,7 @@ int po1030_get_exposure(struct gspca_dev *gspca_dev, __s32 *val) return 0; } -int po1030_set_exposure(struct gspca_dev *gspca_dev, __s32 val) +static int po1030_set_exposure(struct gspca_dev *gspca_dev, __s32 val) { struct sd *sd = (struct sd *) gspca_dev; s32 *sensor_settings = sd->sensor_priv; @@ -315,7 +332,7 @@ int po1030_set_exposure(struct gspca_dev *gspca_dev, __s32 val) return err; } -int po1030_get_gain(struct gspca_dev *gspca_dev, __s32 *val) +static int po1030_get_gain(struct gspca_dev *gspca_dev, __s32 *val) { struct sd *sd = (struct sd *) gspca_dev; s32 *sensor_settings = sd->sensor_priv; @@ -325,7 +342,7 @@ int po1030_get_gain(struct gspca_dev *gspca_dev, __s32 *val) return 0; } -int po1030_set_gain(struct gspca_dev *gspca_dev, __s32 val) +static int po1030_set_gain(struct gspca_dev *gspca_dev, __s32 val) { struct sd *sd = (struct sd *) gspca_dev; s32 *sensor_settings = sd->sensor_priv; @@ -341,7 +358,7 @@ int po1030_set_gain(struct gspca_dev *gspca_dev, __s32 val) return err; } -int po1030_get_hflip(struct gspca_dev *gspca_dev, __s32 *val) +static int po1030_get_hflip(struct gspca_dev *gspca_dev, __s32 *val) { struct sd *sd = (struct sd *) gspca_dev; s32 *sensor_settings = sd->sensor_priv; @@ -352,7 +369,7 @@ int po1030_get_hflip(struct gspca_dev *gspca_dev, __s32 *val) return 0; } -int po1030_set_hflip(struct gspca_dev *gspca_dev, __s32 val) +static int po1030_set_hflip(struct gspca_dev *gspca_dev, __s32 val) { struct sd *sd = (struct sd *) gspca_dev; s32 *sensor_settings = sd->sensor_priv; @@ -374,7 +391,7 @@ int po1030_set_hflip(struct gspca_dev *gspca_dev, __s32 val) return err; } -int po1030_get_vflip(struct gspca_dev *gspca_dev, __s32 *val) +static int po1030_get_vflip(struct gspca_dev *gspca_dev, __s32 *val) { struct sd *sd = (struct sd *) gspca_dev; s32 *sensor_settings = sd->sensor_priv; @@ -385,7 +402,7 @@ int po1030_get_vflip(struct gspca_dev *gspca_dev, __s32 *val) return 0; } -int po1030_set_vflip(struct gspca_dev *gspca_dev, __s32 val) +static int po1030_set_vflip(struct gspca_dev *gspca_dev, __s32 val) { struct sd *sd = (struct sd *) gspca_dev; s32 *sensor_settings = sd->sensor_priv; @@ -407,7 +424,7 @@ int po1030_set_vflip(struct gspca_dev *gspca_dev, __s32 val) return err; } -int po1030_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val) +static int po1030_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val) { struct sd *sd = (struct sd *) gspca_dev; s32 *sensor_settings = sd->sensor_priv; @@ -417,7 +434,7 @@ int po1030_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val) return 0; } -int po1030_set_red_balance(struct gspca_dev *gspca_dev, __s32 val) +static int po1030_set_red_balance(struct gspca_dev *gspca_dev, __s32 val) { struct sd *sd = (struct sd *) gspca_dev; s32 *sensor_settings = sd->sensor_priv; @@ -433,7 +450,7 @@ int po1030_set_red_balance(struct gspca_dev *gspca_dev, __s32 val) return err; } -int po1030_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val) +static int po1030_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val) { struct sd *sd = (struct sd *) gspca_dev; s32 *sensor_settings = sd->sensor_priv; @@ -444,7 +461,7 @@ int po1030_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val) return 0; } -int po1030_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val) +static int po1030_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val) { struct sd *sd = (struct sd *) gspca_dev; s32 *sensor_settings = sd->sensor_priv; @@ -461,7 +478,8 @@ int po1030_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val) return err; } -int po1030_get_auto_white_balance(struct gspca_dev *gspca_dev, __s32 *val) +static int po1030_get_auto_white_balance(struct gspca_dev *gspca_dev, + __s32 *val) { struct sd *sd = (struct sd *) gspca_dev; s32 *sensor_settings = sd->sensor_priv; @@ -472,7 +490,8 @@ int po1030_get_auto_white_balance(struct gspca_dev *gspca_dev, __s32 *val) return 0; } -int po1030_set_auto_white_balance(struct gspca_dev *gspca_dev, __s32 val) +static int po1030_set_auto_white_balance(struct gspca_dev *gspca_dev, + __s32 val) { struct sd *sd = (struct sd *) gspca_dev; s32 *sensor_settings = sd->sensor_priv; diff --git a/linux/drivers/media/video/gspca/m5602/m5602_po1030.h b/linux/drivers/media/video/gspca/m5602/m5602_po1030.h index 9ccf89e59..5ba3f73b7 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_po1030.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_po1030.h @@ -151,21 +151,6 @@ int po1030_init(struct sd *sd); int po1030_start(struct sd *sd); void po1030_disconnect(struct sd *sd); -int po1030_get_exposure(struct gspca_dev *gspca_dev, __s32 *val); -int po1030_set_exposure(struct gspca_dev *gspca_dev, __s32 val); -int po1030_get_gain(struct gspca_dev *gspca_dev, __s32 *val); -int po1030_set_gain(struct gspca_dev *gspca_dev, __s32 val); -int po1030_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val); -int po1030_set_red_balance(struct gspca_dev *gspca_dev, __s32 val); -int po1030_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val); -int po1030_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val); -int po1030_get_hflip(struct gspca_dev *gspca_dev, __s32 *val); -int po1030_set_hflip(struct gspca_dev *gspca_dev, __s32 val); -int po1030_get_vflip(struct gspca_dev *gspca_dev, __s32 *val); -int po1030_set_vflip(struct gspca_dev *gspca_dev, __s32 val); -int po1030_set_auto_white_balance(struct gspca_dev *gspca_dev, __s32 val); -int po1030_get_auto_white_balance(struct gspca_dev *gspca_dev, __s32 *val); - static const struct m5602_sensor po1030 = { .name = "PO1030", diff --git a/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c b/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c index 14d958bd0..48658a1d9 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c @@ -18,6 +18,15 @@ #include "m5602_s5k4aa.h" +static int s5k4aa_get_exposure(struct gspca_dev *gspca_dev, __s32 *val); +static int s5k4aa_set_exposure(struct gspca_dev *gspca_dev, __s32 val); +static int s5k4aa_get_vflip(struct gspca_dev *gspca_dev, __s32 *val); +static int s5k4aa_set_vflip(struct gspca_dev *gspca_dev, __s32 val); +static int s5k4aa_get_hflip(struct gspca_dev *gspca_dev, __s32 *val); +static int s5k4aa_set_hflip(struct gspca_dev *gspca_dev, __s32 val); +static int s5k4aa_get_gain(struct gspca_dev *gspca_dev, __s32 *val); +static int s5k4aa_set_gain(struct gspca_dev *gspca_dev, __s32 val); + static #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24) const @@ -306,7 +315,7 @@ int s5k4aa_init(struct sd *sd) return err; } -int s5k4aa_get_exposure(struct gspca_dev *gspca_dev, __s32 *val) +static int s5k4aa_get_exposure(struct gspca_dev *gspca_dev, __s32 *val) { struct sd *sd = (struct sd *) gspca_dev; s32 *sensor_settings = sd->sensor_priv; @@ -317,7 +326,7 @@ int s5k4aa_get_exposure(struct gspca_dev *gspca_dev, __s32 *val) return 0; } -int s5k4aa_set_exposure(struct gspca_dev *gspca_dev, __s32 val) +static int s5k4aa_set_exposure(struct gspca_dev *gspca_dev, __s32 val) { struct sd *sd = (struct sd *) gspca_dev; s32 *sensor_settings = sd->sensor_priv; @@ -339,7 +348,7 @@ int s5k4aa_set_exposure(struct gspca_dev *gspca_dev, __s32 val) return err; } -int s5k4aa_get_vflip(struct gspca_dev *gspca_dev, __s32 *val) +static int s5k4aa_get_vflip(struct gspca_dev *gspca_dev, __s32 *val) { struct sd *sd = (struct sd *) gspca_dev; s32 *sensor_settings = sd->sensor_priv; @@ -350,7 +359,7 @@ int s5k4aa_get_vflip(struct gspca_dev *gspca_dev, __s32 *val) return 0; } -int s5k4aa_set_vflip(struct gspca_dev *gspca_dev, __s32 val) +static int s5k4aa_set_vflip(struct gspca_dev *gspca_dev, __s32 val) { struct sd *sd = (struct sd *) gspca_dev; s32 *sensor_settings = sd->sensor_priv; @@ -398,7 +407,7 @@ int s5k4aa_set_vflip(struct gspca_dev *gspca_dev, __s32 val) return err; } -int s5k4aa_get_hflip(struct gspca_dev *gspca_dev, __s32 *val) +static int s5k4aa_get_hflip(struct gspca_dev *gspca_dev, __s32 *val) { struct sd *sd = (struct sd *) gspca_dev; s32 *sensor_settings = sd->sensor_priv; @@ -409,7 +418,7 @@ int s5k4aa_get_hflip(struct gspca_dev *gspca_dev, __s32 *val) return 0; } -int s5k4aa_set_hflip(struct gspca_dev *gspca_dev, __s32 val) +static int s5k4aa_set_hflip(struct gspca_dev *gspca_dev, __s32 val) { struct sd *sd = (struct sd *) gspca_dev; s32 *sensor_settings = sd->sensor_priv; @@ -450,7 +459,7 @@ int s5k4aa_set_hflip(struct gspca_dev *gspca_dev, __s32 val) return err; } -int s5k4aa_get_gain(struct gspca_dev *gspca_dev, __s32 *val) +static int s5k4aa_get_gain(struct gspca_dev *gspca_dev, __s32 *val) { struct sd *sd = (struct sd *) gspca_dev; s32 *sensor_settings = sd->sensor_priv; @@ -460,7 +469,7 @@ int s5k4aa_get_gain(struct gspca_dev *gspca_dev, __s32 *val) return 0; } -int s5k4aa_set_gain(struct gspca_dev *gspca_dev, __s32 val) +static int s5k4aa_set_gain(struct gspca_dev *gspca_dev, __s32 val) { struct sd *sd = (struct sd *) gspca_dev; s32 *sensor_settings = sd->sensor_priv; diff --git a/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.h b/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.h index 9ffcb5d1a..7a8da1dc4 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.h @@ -68,15 +68,6 @@ int s5k4aa_init(struct sd *sd); int s5k4aa_start(struct sd *sd); void s5k4aa_disconnect(struct sd *sd); -int s5k4aa_get_exposure(struct gspca_dev *gspca_dev, __s32 *val); -int s5k4aa_set_exposure(struct gspca_dev *gspca_dev, __s32 val); -int s5k4aa_get_vflip(struct gspca_dev *gspca_dev, __s32 *val); -int s5k4aa_set_vflip(struct gspca_dev *gspca_dev, __s32 val); -int s5k4aa_get_hflip(struct gspca_dev *gspca_dev, __s32 *val); -int s5k4aa_set_hflip(struct gspca_dev *gspca_dev, __s32 val); -int s5k4aa_get_gain(struct gspca_dev *gspca_dev, __s32 *val); -int s5k4aa_set_gain(struct gspca_dev *gspca_dev, __s32 val); - static const struct m5602_sensor s5k4aa = { .name = "S5K4AA", .i2c_slave_id = 0x5a, diff --git a/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.c b/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.c index b43a3b04a..8d5453572 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.c @@ -19,6 +19,17 @@ #include #include "m5602_s5k83a.h" +static int s5k83a_set_gain(struct gspca_dev *gspca_dev, __s32 val); +static int s5k83a_get_gain(struct gspca_dev *gspca_dev, __s32 *val); +static int s5k83a_set_brightness(struct gspca_dev *gspca_dev, __s32 val); +static int s5k83a_get_brightness(struct gspca_dev *gspca_dev, __s32 *val); +static int s5k83a_set_exposure(struct gspca_dev *gspca_dev, __s32 val); +static int s5k83a_get_exposure(struct gspca_dev *gspca_dev, __s32 *val); +static int s5k83a_get_vflip(struct gspca_dev *gspca_dev, __s32 *val); +static int s5k83a_set_vflip(struct gspca_dev *gspca_dev, __s32 val); +static int s5k83a_get_hflip(struct gspca_dev *gspca_dev, __s32 *val); +static int s5k83a_set_hflip(struct gspca_dev *gspca_dev, __s32 val); + static struct v4l2_pix_format s5k83a_modes[] = { { 640, @@ -298,7 +309,7 @@ void s5k83a_disconnect(struct sd *sd) kfree(sens_priv); } -int s5k83a_get_gain(struct gspca_dev *gspca_dev, __s32 *val) +static int s5k83a_get_gain(struct gspca_dev *gspca_dev, __s32 *val) { struct sd *sd = (struct sd *) gspca_dev; struct s5k83a_priv *sens_priv = sd->sensor_priv; @@ -307,7 +318,7 @@ int s5k83a_get_gain(struct gspca_dev *gspca_dev, __s32 *val) return 0; } -int s5k83a_set_gain(struct gspca_dev *gspca_dev, __s32 val) +static int s5k83a_set_gain(struct gspca_dev *gspca_dev, __s32 val) { int err; u8 data[2]; @@ -337,7 +348,7 @@ int s5k83a_set_gain(struct gspca_dev *gspca_dev, __s32 val) return err; } -int s5k83a_get_brightness(struct gspca_dev *gspca_dev, __s32 *val) +static int s5k83a_get_brightness(struct gspca_dev *gspca_dev, __s32 *val) { struct sd *sd = (struct sd *) gspca_dev; struct s5k83a_priv *sens_priv = sd->sensor_priv; @@ -346,7 +357,7 @@ int s5k83a_get_brightness(struct gspca_dev *gspca_dev, __s32 *val) return 0; } -int s5k83a_set_brightness(struct gspca_dev *gspca_dev, __s32 val) +static int s5k83a_set_brightness(struct gspca_dev *gspca_dev, __s32 val) { int err; u8 data[1]; @@ -359,7 +370,7 @@ int s5k83a_set_brightness(struct gspca_dev *gspca_dev, __s32 val) return err; } -int s5k83a_get_exposure(struct gspca_dev *gspca_dev, __s32 *val) +static int s5k83a_get_exposure(struct gspca_dev *gspca_dev, __s32 *val) { struct sd *sd = (struct sd *) gspca_dev; struct s5k83a_priv *sens_priv = sd->sensor_priv; @@ -368,7 +379,7 @@ int s5k83a_get_exposure(struct gspca_dev *gspca_dev, __s32 *val) return 0; } -int s5k83a_set_exposure(struct gspca_dev *gspca_dev, __s32 val) +static int s5k83a_set_exposure(struct gspca_dev *gspca_dev, __s32 val) { int err; u8 data[2]; @@ -382,7 +393,7 @@ int s5k83a_set_exposure(struct gspca_dev *gspca_dev, __s32 val) return err; } -int s5k83a_get_vflip(struct gspca_dev *gspca_dev, __s32 *val) +static int s5k83a_get_vflip(struct gspca_dev *gspca_dev, __s32 *val) { struct sd *sd = (struct sd *) gspca_dev; struct s5k83a_priv *sens_priv = sd->sensor_priv; @@ -421,7 +432,7 @@ int s5k83a_set_flip_real(struct gspca_dev *gspca_dev, __s32 vflip, __s32 hflip) return err; } -int s5k83a_set_vflip(struct gspca_dev *gspca_dev, __s32 val) +static int s5k83a_set_vflip(struct gspca_dev *gspca_dev, __s32 val) { int err; u8 reg; @@ -445,7 +456,7 @@ int s5k83a_set_vflip(struct gspca_dev *gspca_dev, __s32 val) return err; } -int s5k83a_get_hflip(struct gspca_dev *gspca_dev, __s32 *val) +static int s5k83a_get_hflip(struct gspca_dev *gspca_dev, __s32 *val) { struct sd *sd = (struct sd *) gspca_dev; struct s5k83a_priv *sens_priv = sd->sensor_priv; @@ -454,7 +465,7 @@ int s5k83a_get_hflip(struct gspca_dev *gspca_dev, __s32 *val) return 0; } -int s5k83a_set_hflip(struct gspca_dev *gspca_dev, __s32 val) +static int s5k83a_set_hflip(struct gspca_dev *gspca_dev, __s32 val) { int err; u8 reg; diff --git a/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.h b/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.h index 02a5e2559..e93938532 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.h @@ -49,17 +49,6 @@ int s5k83a_start(struct sd *sd); int s5k83a_stop(struct sd *sd); void s5k83a_disconnect(struct sd *sd); -int s5k83a_set_gain(struct gspca_dev *gspca_dev, __s32 val); -int s5k83a_get_gain(struct gspca_dev *gspca_dev, __s32 *val); -int s5k83a_set_brightness(struct gspca_dev *gspca_dev, __s32 val); -int s5k83a_get_brightness(struct gspca_dev *gspca_dev, __s32 *val); -int s5k83a_set_exposure(struct gspca_dev *gspca_dev, __s32 val); -int s5k83a_get_exposure(struct gspca_dev *gspca_dev, __s32 *val); -int s5k83a_get_vflip(struct gspca_dev *gspca_dev, __s32 *val); -int s5k83a_set_vflip(struct gspca_dev *gspca_dev, __s32 val); -int s5k83a_get_hflip(struct gspca_dev *gspca_dev, __s32 *val); -int s5k83a_set_hflip(struct gspca_dev *gspca_dev, __s32 val); - static const struct m5602_sensor s5k83a = { .name = "S5K83A", .probe = s5k83a_probe, -- cgit v1.2.3 From 2c14a41e11fbda8426340a33e84b16aaad6bb892 Mon Sep 17 00:00:00 2001 From: Erik Andr?n Date: Fri, 9 Jan 2009 17:35:00 +0100 Subject: gspca - m5602: Move all dump_sensor to the init function From: Erik Andr?n Priority: normal Signed-off-by: Erik Andr?n --- linux/drivers/media/video/gspca/m5602/m5602_mt9m111.c | 6 +++--- linux/drivers/media/video/gspca/m5602/m5602_po1030.c | 6 +++--- linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c | 6 +++--- 3 files changed, 9 insertions(+), 9 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.c b/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.c index 8017782ef..8036619e7 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.c @@ -144,9 +144,6 @@ sensor_found: sensor_settings[i] = mt9m111_ctrls[i].qctrl.default_value; sd->sensor_priv = sensor_settings; - if (dump_sensor) - mt9m111_dump_registers(sd); - return 0; } @@ -171,6 +168,9 @@ int mt9m111_init(struct sd *sd) } } + if (dump_sensor) + mt9m111_dump_registers(sd); + err = mt9m111_set_vflip(&sd->gspca_dev, sensor_settings[VFLIP_IDX]); if (err < 0) return err; diff --git a/linux/drivers/media/video/gspca/m5602/m5602_po1030.c b/linux/drivers/media/video/gspca/m5602/m5602_po1030.c index 79dcf9bfd..3ecb53c70 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_po1030.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_po1030.c @@ -209,9 +209,6 @@ sensor_found: sensor_settings[i] = po1030_ctrls[i].qctrl.default_value; sd->sensor_priv = sensor_settings; - if (dump_sensor) - po1030_dump_registers(sd); - return 0; } @@ -245,6 +242,9 @@ int po1030_init(struct sd *sd) if (err < 0) return err; + if (dump_sensor) + po1030_dump_registers(sd); + err = po1030_set_exposure(&sd->gspca_dev, sensor_settings[EXPOSURE_IDX]); if (err < 0) diff --git a/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c b/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c index 48658a1d9..7b1d0602e 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c @@ -216,9 +216,6 @@ sensor_found: sensor_settings[i] = s5k4aa_ctrls[i].qctrl.default_value; sd->sensor_priv = sensor_settings; - if (dump_sensor) - s5k4aa_dump_registers(sd); - return 0; } @@ -297,6 +294,9 @@ int s5k4aa_init(struct sd *sd) } } + if (dump_sensor) + s5k4aa_dump_registers(sd); + err = s5k4aa_set_exposure(&sd->gspca_dev, sensor_settings[EXPOSURE_IDX]); if (err < 0) -- cgit v1.2.3 From 6dfad34be5c7a4f5caa9d1a780efcb8114e7c44a Mon Sep 17 00:00:00 2001 From: Erik Andr?n Date: Fri, 9 Jan 2009 17:41:28 +0100 Subject: gspca - m5602-mt9m111: Remove redundant init sequences From: Erik Andr?n Priority: normal Signed-off-by: Erik Andr?n --- .../media/video/gspca/m5602/m5602_mt9m111.h | 122 --------------------- 1 file changed, 122 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h b/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h index dbda4a63d..f7dbce160 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h @@ -257,58 +257,9 @@ static const unsigned char init_mt9m111[][4] = {SENSOR, MT9M111_SC_R_MODE_CONTEXT_A, 0x01, 0x03}, {SENSOR, 0x30, 0x04, 0x00}, - {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06, 0x00}, - {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, - {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00}, - {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00}, - {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81, 0x00}, - {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82, 0x00}, - {BRIDGE, M5602_XB_SIG_INI, 0x01, 0x00}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x04, 0x00}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x04, 0x00}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, - {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00}, - {BRIDGE, M5602_XB_SIG_INI, 0x02, 0x00}, - {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00}, - {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00}, - {BRIDGE, M5602_XB_HSYNC_PARA, 0x05, 0x00}, - {BRIDGE, M5602_XB_HSYNC_PARA, 0x07, 0x00}, - {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00}, - {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, - {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xa0, 0x00}, {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, {SENSOR, MT9M111_SC_SHUTTER_WIDTH, 0x01, 0xf4}, - {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06, 0x00}, - {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, - {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00}, - {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00}, - {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81, 0x00}, - {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82, 0x00}, - {BRIDGE, M5602_XB_SIG_INI, 0x01, 0x00}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x04, 0x00}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x04, 0x00}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, - {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00}, - {BRIDGE, M5602_XB_SIG_INI, 0x02, 0x00}, - {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00}, - {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00}, - {BRIDGE, M5602_XB_HSYNC_PARA, 0x05, 0x00}, - {BRIDGE, M5602_XB_HSYNC_PARA, 0x07, 0x00}, - {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00}, - {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, - {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, - {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, {SENSOR, MT9M111_SC_RESET, 0x00, 0x09}, {SENSOR, MT9M111_SC_RESET, 0x00, 0x29}, @@ -418,32 +369,6 @@ static const unsigned char init_mt9m111[][4] = {SENSOR, MT9M111_SC_R_MODE_CONTEXT_A, 0x01, 0x03}, {SENSOR, 0x30, 0x04, 0x00}, - {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06, 0x00}, - {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, - {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00}, - {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00}, - {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81, 0x00}, - {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82, 0x00}, - {BRIDGE, M5602_XB_SIG_INI, 0x01, 0x00}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x04, 0x00}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x04, 0x00}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, - {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00}, - {BRIDGE, M5602_XB_SIG_INI, 0x02, 0x00}, - {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00}, - {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00}, - {BRIDGE, M5602_XB_HSYNC_PARA, 0x05, 0x00}, - {BRIDGE, M5602_XB_HSYNC_PARA, 0x07, 0x00}, - {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00}, - {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, - {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xa0, 0x00}, - {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, - {SENSOR, MT9M111_SC_SHUTTER_WIDTH, 0x01, 0xf4}, {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, @@ -557,28 +482,6 @@ static const unsigned char init_mt9m111[][4] = {SENSOR, MT9M111_SC_R_MODE_CONTEXT_A, 0x01, 0x03}, {SENSOR, 0x30, 0x04, 0x00}, - {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06, 0x00}, - {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, - {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00}, - {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00}, - {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81, 0x00}, - {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82, 0x00}, - {BRIDGE, M5602_XB_SIG_INI, 0x01, 0x00}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x04, 0x00}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x04, 0x00}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, - {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00}, - {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00}, - {BRIDGE, M5602_XB_HSYNC_PARA, 0x05, 0x00}, - {BRIDGE, M5602_XB_HSYNC_PARA, 0x07, 0x00}, - {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00}, - {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, - {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xa0, 0x00}, {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, {SENSOR, MT9M111_SC_SHUTTER_WIDTH, 0x01, 0xf4}, {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, @@ -729,31 +632,6 @@ static const unsigned char init_mt9m111[][4] = {SENSOR, MT9M111_SC_R_MODE_CONTEXT_A, 0x01, 0x0f}, {SENSOR, 0x30, 0x04, 0x00}, - {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06, 0x00}, - {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, - {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00}, - {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00}, - {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81, 0x00}, - {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82, 0x00}, - {BRIDGE, M5602_XB_SIG_INI, 0x01, 0x00}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x01, 0x00}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0xe3, 0x00}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, - {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00}, - {BRIDGE, M5602_XB_SIG_INI, 0x02, 0x00}, - {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00}, - {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00}, - {BRIDGE, M5602_XB_HSYNC_PARA, 0x02, 0x00}, - {BRIDGE, M5602_XB_HSYNC_PARA, 0x87, 0x00}, - {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00}, - {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, - {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, - {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, {SENSOR, MT9M111_SC_SHUTTER_WIDTH, 0x01, 0x90}, {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, -- cgit v1.2.3 From a694efccfe707bc3696b043791107fd779d38803 Mon Sep 17 00:00:00 2001 From: Erik Andr?n Date: Fri, 9 Jan 2009 17:53:20 +0100 Subject: gspca - m5602-mt9m111: More redundant init cleanup From: Erik Andr?n Priority: normal Signed-off-by: Erik Andr?n --- linux/drivers/media/video/gspca/m5602/m5602_mt9m111.c | 1 - linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h | 11 +++++------ 2 files changed, 5 insertions(+), 7 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.c b/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.c index 8036619e7..a057b8d5d 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.c @@ -84,7 +84,6 @@ const static struct ctrl mt9m111_ctrls[] = { } }; - static void mt9m111_dump_registers(struct sd *sd); int mt9m111_probe(struct sd *sd) diff --git a/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h b/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h index f7dbce160..e7b7347ea 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h @@ -74,6 +74,8 @@ #define MT9M111_COLORPIPE 0x01 #define MT9M111_CAMERA_CONTROL 0x02 +#define MT9M111_COLOR_MATRIX_BYPASS (1 << 4) + #define INITIAL_MAX_GAIN 64 #define DEFAULT_GAIN 283 @@ -186,7 +188,6 @@ static const unsigned char init_mt9m111[][4] = {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, {SENSOR, MT9M111_SC_RESET, 0x00, 0x08}, {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x01}, - {SENSOR, MT9M111_CP_OPERATING_MODE_CTL, 0x00, 0x10}, {SENSOR, MT9M111_CP_LENS_CORRECTION_1, 0x04, 0x2a}, {SENSOR, MT9M111_CP_DEFECT_CORR_CONTEXT_A, 0x00, 0x01}, {SENSOR, MT9M111_CP_DEFECT_CORR_CONTEXT_B, 0x00, 0x01}, @@ -298,7 +299,6 @@ static const unsigned char init_mt9m111[][4] = {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, {SENSOR, MT9M111_SC_RESET, 0x00, 0x08}, {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x01}, - {SENSOR, MT9M111_CP_OPERATING_MODE_CTL, 0x00, 0x10}, {SENSOR, MT9M111_CP_LENS_CORRECTION_1, 0x04, 0x2a}, {SENSOR, MT9M111_CP_DEFECT_CORR_CONTEXT_A, 0x00, 0x01}, {SENSOR, MT9M111_CP_DEFECT_CORR_CONTEXT_B, 0x00, 0x01}, @@ -411,7 +411,6 @@ static const unsigned char init_mt9m111[][4] = {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, {SENSOR, MT9M111_SC_RESET, 0x00, 0x08}, {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x01}, - {SENSOR, MT9M111_CP_OPERATING_MODE_CTL, 0x00, 0x10}, {SENSOR, MT9M111_CP_LENS_CORRECTION_1, 0x04, 0x2a}, {SENSOR, MT9M111_CP_DEFECT_CORR_CONTEXT_A, 0x00, 0x01}, {SENSOR, MT9M111_CP_DEFECT_CORR_CONTEXT_B, 0x00, 0x01}, @@ -550,7 +549,6 @@ static const unsigned char init_mt9m111[][4] = {SENSOR, MT9M111_SC_RESET, 0x00, 0x08}, {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x01}, - {SENSOR, MT9M111_CP_OPERATING_MODE_CTL, 0x00, 0x10}, {SENSOR, MT9M111_CP_LENS_CORRECTION_1, 0x04, 0x2a}, {SENSOR, MT9M111_CP_DEFECT_CORR_CONTEXT_A, 0x00, 0x01}, {SENSOR, MT9M111_CP_DEFECT_CORR_CONTEXT_B, 0x00, 0x01}, @@ -700,7 +698,8 @@ static const unsigned char init_mt9m111[][4] = {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00}, {SENSOR, MT9M111_SC_RESET, 0x00, 0x08}, {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x01}, - {SENSOR, MT9M111_CP_OPERATING_MODE_CTL, 0x00, 0x10}, + {SENSOR, MT9M111_CP_OPERATING_MODE_CTL, 0x00, + MT9M111_CP_OPERATING_MODE_CTL}, {SENSOR, MT9M111_CP_LENS_CORRECTION_1, 0x04, 0x2a}, {SENSOR, MT9M111_CP_DEFECT_CORR_CONTEXT_A, 0x00, 0x01}, {SENSOR, MT9M111_CP_DEFECT_CORR_CONTEXT_B, 0x00, 0x01}, @@ -796,7 +795,7 @@ static const unsigned char init_mt9m111[][4] = {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, {BRIDGE, M5602_XB_VSYNC_PARA, 0x01, 0x00}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0xe0, 0x00}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0xe0, 0x00}, /* 480 */ {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00}, -- cgit v1.2.3 From 4874985087f6574aa443ab801e631ee86f03966f Mon Sep 17 00:00:00 2001 From: Erik Andr?n Date: Fri, 9 Jan 2009 18:03:27 +0100 Subject: gspca - m5602-mt9m111: Implement an auto white balancing control From: Erik Andr?n Priority: normal Signed-off-by: Erik Andr?n --- .../media/video/gspca/m5602/m5602_mt9m111.c | 50 ++++++++++++++++++++++ 1 file changed, 50 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.c b/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.c index a057b8d5d..37a7fc82a 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.c @@ -24,6 +24,11 @@ static int mt9m111_get_hflip(struct gspca_dev *gspca_dev, __s32 *val); static int mt9m111_set_hflip(struct gspca_dev *gspca_dev, __s32 val); static int mt9m111_get_gain(struct gspca_dev *gspca_dev, __s32 *val); static int mt9m111_set_gain(struct gspca_dev *gspca_dev, __s32 val); +static int mt9m111_set_auto_white_balance(struct gspca_dev *gspca_dev, + __s32 val); +static int mt9m111_get_auto_white_balance(struct gspca_dev *gspca_dev, + __s32 *val); + static struct v4l2_pix_format mt9m111_modes[] = { { @@ -81,6 +86,20 @@ const static struct ctrl mt9m111_ctrls[] = { }, .set = mt9m111_set_gain, .get = mt9m111_get_gain + }, +#define AUTO_WHITE_BALANCE_IDX 3 + { + { + .id = V4L2_CID_AUTO_WHITE_BALANCE, + .type = V4L2_CTRL_TYPE_BOOLEAN, + .name = "auto white balance", + .minimum = 0, + .maximum = 1, + .step = 1, + .default_value = 0, + }, + .set = mt9m111_set_auto_white_balance, + .get = mt9m111_get_auto_white_balance } }; @@ -273,6 +292,37 @@ static int mt9m111_get_gain(struct gspca_dev *gspca_dev, __s32 *val) return 0; } +static int mt9m111_set_auto_white_balance(struct gspca_dev *gspca_dev, + __s32 val) +{ + struct sd *sd = (struct sd *) gspca_dev; + s32 *sensor_settings = sd->sensor_priv; + int err; + u8 data[2]; + + err = m5602_read_sensor(sd, MT9M111_CP_OPERATING_MODE_CTL, data, 2); + if (err < 0) + return err; + + sensor_settings[AUTO_WHITE_BALANCE_IDX] = val & 0x01; + data[0] = ((data[0] & 0xfd) | ((val & 0x01) << 1)); + + err = m5602_write_sensor(sd, MT9M111_CP_OPERATING_MODE_CTL, data, 2); + + PDEBUG(D_V4L2, "Set auto white balance %d", val); + return err; +} + +static int mt9m111_get_auto_white_balance(struct gspca_dev *gspca_dev, + __s32 *val) { + struct sd *sd = (struct sd *) gspca_dev; + s32 *sensor_settings = sd->sensor_priv; + + *val = sensor_settings[AUTO_WHITE_BALANCE_IDX]; + PDEBUG(D_V4L2, "Read auto white balance %d", *val); + return 0; +} + static int mt9m111_set_gain(struct gspca_dev *gspca_dev, __s32 val) { int err, tmp; -- cgit v1.2.3 From f7b2f0d505ca09f7d30291018dc1c06144218855 Mon Sep 17 00:00:00 2001 From: Erik Andr?n Date: Fri, 9 Jan 2009 18:10:19 +0100 Subject: gspca - m5602-mt9m111: Remove more redundant init From: Erik Andr?n Priority: normal Signed-off-by: Erik Andr?n --- .../media/video/gspca/m5602/m5602_mt9m111.h | 50 +--------------------- 1 file changed, 1 insertion(+), 49 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h b/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h index e7b7347ea..fe83f4293 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h @@ -181,22 +181,6 @@ static const unsigned char init_mt9m111[][4] = {BRIDGE, M5602_XB_GPIO_EN_L, 0x00, 0x00}, {BRIDGE, M5602_XB_I2C_CLK_DIV, 0x0a, 0x00}, - {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, - {SENSOR, MT9M111_SC_RESET, 0x00, 0x05}, - {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, - {SENSOR, MT9M111_SC_RESET, 0x00, 0x29}, - {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, - {SENSOR, MT9M111_SC_RESET, 0x00, 0x08}, - {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x01}, - {SENSOR, MT9M111_CP_LENS_CORRECTION_1, 0x04, 0x2a}, - {SENSOR, MT9M111_CP_DEFECT_CORR_CONTEXT_A, 0x00, 0x01}, - {SENSOR, MT9M111_CP_DEFECT_CORR_CONTEXT_B, 0x00, 0x01}, - {SENSOR, MT9M111_CP_LUMA_OFFSET, 0x00, 0x00}, - {SENSOR, MT9M111_CP_LUMA_CLIP, 0xff, 0x00}, - {SENSOR, MT9M111_CP_OUTPUT_FORMAT_CTL2_CONTEXT_A, 0x14, 0x00}, - {SENSOR, MT9M111_CP_OUTPUT_FORMAT_CTL2_CONTEXT_B, 0x14, 0x00}, - {BRIDGE, M5602_XB_I2C_REG_ADDR, 0xcd, 0x00}, - {SENSOR, 0xcd, 0x00, 0x0e}, {BRIDGE, M5602_XB_I2C_REG_ADDR, 0xd0, 0x00}, {SENSOR, 0xd0, 0x00, 0x40}, @@ -292,21 +276,6 @@ static const unsigned char init_mt9m111[][4] = {BRIDGE, M5602_XB_GPIO_EN_L, 0x00, 0x00}, {BRIDGE, M5602_XB_I2C_CLK_DIV, 0x0a, 0x00}, - {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, - {SENSOR, MT9M111_SC_RESET, 0x00, 0x05}, - {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, - {SENSOR, MT9M111_SC_RESET, 0x00, 0x29}, - {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, - {SENSOR, MT9M111_SC_RESET, 0x00, 0x08}, - {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x01}, - {SENSOR, MT9M111_CP_LENS_CORRECTION_1, 0x04, 0x2a}, - {SENSOR, MT9M111_CP_DEFECT_CORR_CONTEXT_A, 0x00, 0x01}, - {SENSOR, MT9M111_CP_DEFECT_CORR_CONTEXT_B, 0x00, 0x01}, - {SENSOR, MT9M111_CP_LUMA_OFFSET, 0x00, 0x00}, - {SENSOR, MT9M111_CP_LUMA_CLIP, 0xff, 0x00}, - {SENSOR, MT9M111_CP_OUTPUT_FORMAT_CTL2_CONTEXT_A, 0x14, 0x00}, - {SENSOR, MT9M111_CP_OUTPUT_FORMAT_CTL2_CONTEXT_B, 0x14, 0x00}, - {BRIDGE, M5602_XB_I2C_REG_ADDR, 0xcd, 0x00}, {SENSOR, 0xcd, 0x00, 0x0e}, {BRIDGE, M5602_XB_I2C_REG_ADDR, 0xd0, 0x00}, @@ -410,14 +379,6 @@ static const unsigned char init_mt9m111[][4] = {SENSOR, MT9M111_SC_RESET, 0x00, 0x29}, {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, {SENSOR, MT9M111_SC_RESET, 0x00, 0x08}, - {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x01}, - {SENSOR, MT9M111_CP_LENS_CORRECTION_1, 0x04, 0x2a}, - {SENSOR, MT9M111_CP_DEFECT_CORR_CONTEXT_A, 0x00, 0x01}, - {SENSOR, MT9M111_CP_DEFECT_CORR_CONTEXT_B, 0x00, 0x01}, - {SENSOR, MT9M111_CP_LUMA_OFFSET, 0x00, 0x00}, - {SENSOR, MT9M111_CP_LUMA_CLIP, 0xff, 0x00}, - {SENSOR, MT9M111_CP_OUTPUT_FORMAT_CTL2_CONTEXT_A, 0x14, 0x00}, - {SENSOR, MT9M111_CP_OUTPUT_FORMAT_CTL2_CONTEXT_B, 0x14, 0x00}, {BRIDGE, M5602_XB_I2C_REG_ADDR, 0xcd, 0x00}, {SENSOR, 0xcd, 0x00, 0x0e}, @@ -547,16 +508,6 @@ static const unsigned char init_mt9m111[][4] = {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x0d, 0x00}, {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00}, - {SENSOR, MT9M111_SC_RESET, 0x00, 0x08}, - {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x01}, - {SENSOR, MT9M111_CP_LENS_CORRECTION_1, 0x04, 0x2a}, - {SENSOR, MT9M111_CP_DEFECT_CORR_CONTEXT_A, 0x00, 0x01}, - {SENSOR, MT9M111_CP_DEFECT_CORR_CONTEXT_B, 0x00, 0x01}, - {SENSOR, MT9M111_CP_LUMA_OFFSET, 0x00, 0x00}, - {SENSOR, MT9M111_CP_LUMA_CLIP, 0xff, 0x00}, - {SENSOR, MT9M111_CP_OUTPUT_FORMAT_CTL2_CONTEXT_A, 0x14, 0x00}, - {SENSOR, MT9M111_CP_OUTPUT_FORMAT_CTL2_CONTEXT_B, 0x14, 0x00}, - {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00}, {BRIDGE, M5602_XB_I2C_REG_ADDR, 0xcd, 0x00}, {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00}, @@ -696,6 +647,7 @@ static const unsigned char init_mt9m111[][4] = {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00}, {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x0d, 0x00}, {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00}, + {SENSOR, MT9M111_SC_RESET, 0x00, 0x08}, {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x01}, {SENSOR, MT9M111_CP_OPERATING_MODE_CTL, 0x00, -- cgit v1.2.3 From f89572049ea6dc6a308d03349459d6326ba1eff3 Mon Sep 17 00:00:00 2001 From: Erik Andr?n Date: Sat, 10 Jan 2009 14:55:07 +0100 Subject: gspca - m5602-mt9m111: Remove lots of redundant init code From: Erik Andr?n Priority: normal Signed-off-by: Erik Andr?n --- .../media/video/gspca/m5602/m5602_mt9m111.h | 352 --------------------- 1 file changed, 352 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h b/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h index fe83f4293..0ffa98c0f 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h @@ -159,185 +159,10 @@ static const unsigned char init_mt9m111[][4] = {SENSOR, MT9M111_CP_GLOBAL_CLK_CONTROL, 0xff, 0xff}, - {BRIDGE, M5602_XB_GPIO_DIR, 0x05, 0x00}, - {BRIDGE, M5602_XB_GPIO_DAT, 0x04, 0x00}, - {BRIDGE, M5602_XB_GPIO_EN_H, 0x3e, 0x00}, - {BRIDGE, M5602_XB_GPIO_DIR_H, 0x3e, 0x00}, - {BRIDGE, M5602_XB_GPIO_DAT_H, 0x02, 0x00}, - {BRIDGE, M5602_XB_GPIO_EN_L, 0xff, 0x00}, - {BRIDGE, M5602_XB_GPIO_DIR_L, 0xff, 0x00}, - {BRIDGE, M5602_XB_GPIO_DAT_L, 0x00, 0x00}, - {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x04, 0x00}, - {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, - {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, - {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, - {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00}, - {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00}, - {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, - {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, - {BRIDGE, M5602_XB_GPIO_DIR, 0x07, 0x00}, - {BRIDGE, M5602_XB_GPIO_DAT, 0x0b, 0x00}, {BRIDGE, M5602_XB_GPIO_EN_H, 0x06, 0x00}, {BRIDGE, M5602_XB_GPIO_EN_L, 0x00, 0x00}, {BRIDGE, M5602_XB_I2C_CLK_DIV, 0x0a, 0x00}, - {SENSOR, 0xcd, 0x00, 0x0e}, - {BRIDGE, M5602_XB_I2C_REG_ADDR, 0xd0, 0x00}, - {SENSOR, 0xd0, 0x00, 0x40}, - {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x02}, - {SENSOR, MT9M111_CC_AUTO_EXPOSURE_PARAMETER_18, 0x00, 0x00}, - {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x28, 0x00}, - {SENSOR, MT9M111_CC_AWB_PARAMETER_7, 0xef, 0x07}, - {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x28, 0x00}, - {SENSOR, MT9M111_CC_AWB_PARAMETER_7, 0xef, 0x03}, - {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, - {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x33, 0x00}, - {SENSOR, 0x33, 0x03, 0x49}, - {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x33, 0x00}, - - {SENSOR, 0x33, 0x03, 0x49}, - {SENSOR, 0x34, 0xc0, 0x19}, - {SENSOR, 0x3f, 0x20, 0x20}, - {SENSOR, 0x40, 0x20, 0x20}, - {SENSOR, 0x5a, 0xc0, 0x0a}, - {SENSOR, 0x70, 0x7b, 0x0a}, - {SENSOR, 0x71, 0xff, 0x00}, - {SENSOR, 0x72, 0x19, 0x0e}, - {SENSOR, 0x73, 0x18, 0x0f}, - {SENSOR, 0x74, 0x57, 0x32}, - {SENSOR, 0x75, 0x56, 0x34}, - {SENSOR, 0x76, 0x73, 0x35}, - {SENSOR, 0x77, 0x30, 0x12}, - {SENSOR, 0x78, 0x79, 0x02}, - {SENSOR, 0x79, 0x75, 0x06}, - {SENSOR, 0x7a, 0x77, 0x0a}, - {SENSOR, 0x7b, 0x78, 0x09}, - {SENSOR, 0x7c, 0x7d, 0x06}, - {SENSOR, 0x7d, 0x31, 0x10}, - {SENSOR, 0x7e, 0x00, 0x7e}, - {SENSOR, 0x80, 0x59, 0x04}, - {SENSOR, 0x81, 0x59, 0x04}, - {SENSOR, 0x82, 0x57, 0x0a}, - {SENSOR, 0x83, 0x58, 0x0b}, - {SENSOR, 0x84, 0x47, 0x0c}, - {SENSOR, 0x85, 0x48, 0x0e}, - {SENSOR, 0x86, 0x5b, 0x02}, - {SENSOR, 0x87, 0x00, 0x5c}, - {SENSOR, MT9M111_CONTEXT_CONTROL, 0x00, 0x08}, - {SENSOR, 0x60, 0x00, 0x80}, - {SENSOR, 0x61, 0x00, 0x00}, - {SENSOR, 0x62, 0x00, 0x00}, - {SENSOR, 0x63, 0x00, 0x00}, - {SENSOR, 0x64, 0x00, 0x00}, - - {SENSOR, MT9M111_SC_ROWSTART, 0x00, 0x0d}, - {SENSOR, MT9M111_SC_COLSTART, 0x00, 0x18}, - {SENSOR, MT9M111_SC_WINDOW_HEIGHT, 0x04, 0x04}, - {SENSOR, MT9M111_SC_WINDOW_WIDTH, 0x05, 0x08}, - {SENSOR, MT9M111_SC_HBLANK_CONTEXT_B, 0x01, 0x38}, - {SENSOR, MT9M111_SC_VBLANK_CONTEXT_B, 0x00, 0x11}, - {SENSOR, MT9M111_SC_HBLANK_CONTEXT_A, 0x01, 0x38}, - {SENSOR, MT9M111_SC_VBLANK_CONTEXT_A, 0x00, 0x11}, - {SENSOR, MT9M111_SC_R_MODE_CONTEXT_B, 0x01, 0x03}, - {SENSOR, MT9M111_SC_R_MODE_CONTEXT_A, 0x01, 0x03}, - {SENSOR, 0x30, 0x04, 0x00}, - - {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, - {SENSOR, MT9M111_SC_SHUTTER_WIDTH, 0x01, 0xf4}, - - {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, - {SENSOR, MT9M111_SC_RESET, 0x00, 0x09}, - {SENSOR, MT9M111_SC_RESET, 0x00, 0x29}, - {SENSOR, MT9M111_SC_RESET, 0x00, 0x08}, - {SENSOR, MT9M111_SC_RESET, 0x00, 0x0c}, - {SENSOR, MT9M111_SC_RESET, 0x00, 0x04}, - {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x01}, - {BRIDGE, M5602_XB_I2C_REG_ADDR, 0xb3, 0x00}, - {SENSOR, MT9M111_CP_GLOBAL_CLK_CONTROL, 0x00, 0x03}, - {BRIDGE, M5602_XB_GPIO_DIR, 0x05, 0x00}, - {BRIDGE, M5602_XB_GPIO_DAT, 0x04, 0x00}, - {BRIDGE, M5602_XB_GPIO_EN_H, 0x3e, 0x00}, - {BRIDGE, M5602_XB_GPIO_DIR_H, 0x3e, 0x00}, - {BRIDGE, M5602_XB_GPIO_DAT_H, 0x02, 0x00}, - {BRIDGE, M5602_XB_GPIO_EN_L, 0xff, 0x00}, - {BRIDGE, M5602_XB_GPIO_DIR_L, 0xff, 0x00}, - {BRIDGE, M5602_XB_GPIO_DAT_L, 0x00, 0x00}, - {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x04, 0x00}, - {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, - {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, - {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, - {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00}, - {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00}, - {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, - {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, - {BRIDGE, M5602_XB_GPIO_DIR, 0x07, 0x00}, - {BRIDGE, M5602_XB_GPIO_DAT, 0x0b, 0x00}, - {BRIDGE, M5602_XB_GPIO_EN_H, 0x06, 0x00}, - {BRIDGE, M5602_XB_GPIO_EN_L, 0x00, 0x00}, - {BRIDGE, M5602_XB_I2C_CLK_DIV, 0x0a, 0x00}, - - {BRIDGE, M5602_XB_I2C_REG_ADDR, 0xcd, 0x00}, - {SENSOR, 0xcd, 0x00, 0x0e}, - {BRIDGE, M5602_XB_I2C_REG_ADDR, 0xd0, 0x00}, - {SENSOR, 0xd0, 0x00, 0x40}, - {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x02}, - {SENSOR, MT9M111_CC_AUTO_EXPOSURE_PARAMETER_18, 0x00, 0x00}, - {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x28, 0x00}, - {SENSOR, MT9M111_CC_AWB_PARAMETER_7, 0xef, 0x07}, - {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x28, 0x00}, - {SENSOR, MT9M111_CC_AWB_PARAMETER_7, 0xef, 0x03}, - {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, - {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x33, 0x00}, - {SENSOR, 0x33, 0x03, 0x49}, - {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x33, 0x00}, - - {SENSOR, 0x33, 0x03, 0x49}, - {SENSOR, 0x34, 0xc0, 0x19}, - {SENSOR, 0x3f, 0x20, 0x20}, - {SENSOR, 0x40, 0x20, 0x20}, - {SENSOR, 0x5a, 0xc0, 0x0a}, - {SENSOR, 0x70, 0x7b, 0x0a}, - {SENSOR, 0x71, 0xff, 0x00}, - {SENSOR, 0x72, 0x19, 0x0e}, - {SENSOR, 0x73, 0x18, 0x0f}, - {SENSOR, 0x74, 0x57, 0x32}, - {SENSOR, 0x75, 0x56, 0x34}, - {SENSOR, 0x76, 0x73, 0x35}, - {SENSOR, 0x77, 0x30, 0x12}, - {SENSOR, 0x78, 0x79, 0x02}, - {SENSOR, 0x79, 0x75, 0x06}, - {SENSOR, 0x7a, 0x77, 0x0a}, - {SENSOR, 0x7b, 0x78, 0x09}, - {SENSOR, 0x7c, 0x7d, 0x06}, - {SENSOR, 0x7d, 0x31, 0x10}, - {SENSOR, 0x7e, 0x00, 0x7e}, - {SENSOR, 0x80, 0x59, 0x04}, - {SENSOR, 0x81, 0x59, 0x04}, - {SENSOR, 0x82, 0x57, 0x0a}, - {SENSOR, 0x83, 0x58, 0x0b}, - {SENSOR, 0x84, 0x47, 0x0c}, - {SENSOR, 0x85, 0x48, 0x0e}, - {SENSOR, 0x86, 0x5b, 0x02}, - {SENSOR, 0x87, 0x00, 0x5c}, - {SENSOR, MT9M111_CONTEXT_CONTROL, 0x00, 0x08}, - {SENSOR, 0x60, 0x00, 0x80}, - {SENSOR, 0x61, 0x00, 0x00}, - {SENSOR, 0x62, 0x00, 0x00}, - {SENSOR, 0x63, 0x00, 0x00}, - {SENSOR, 0x64, 0x00, 0x00}, - - {SENSOR, MT9M111_SC_ROWSTART, 0x00, 0x0d}, - {SENSOR, MT9M111_SC_COLSTART, 0x00, 0x18}, - {SENSOR, MT9M111_SC_WINDOW_HEIGHT, 0x04, 0x04}, - {SENSOR, MT9M111_SC_WINDOW_WIDTH, 0x05, 0x08}, - {SENSOR, MT9M111_SC_HBLANK_CONTEXT_B, 0x01, 0x38}, - {SENSOR, MT9M111_SC_VBLANK_CONTEXT_B, 0x00, 0x11}, - {SENSOR, MT9M111_SC_HBLANK_CONTEXT_A, 0x01, 0x38}, - {SENSOR, MT9M111_SC_VBLANK_CONTEXT_A, 0x00, 0x11}, - {SENSOR, MT9M111_SC_R_MODE_CONTEXT_B, 0x01, 0x03}, - {SENSOR, MT9M111_SC_R_MODE_CONTEXT_A, 0x01, 0x03}, - {SENSOR, 0x30, 0x04, 0x00}, - {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, @@ -348,27 +173,8 @@ static const unsigned char init_mt9m111[][4] = {SENSOR, MT9M111_SC_RESET, 0x00, 0x0c}, {SENSOR, MT9M111_SC_RESET, 0x00, 0x04}, {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x01}, - {BRIDGE, M5602_XB_I2C_REG_ADDR, 0xb3, 0x00}, {SENSOR, MT9M111_CP_GLOBAL_CLK_CONTROL, 0x00, 0x03}, - {BRIDGE, M5602_XB_GPIO_DIR, 0x05, 0x00}, - {BRIDGE, M5602_XB_GPIO_DAT, 0x04, 0x00}, - {BRIDGE, M5602_XB_GPIO_EN_H, 0x3e, 0x00}, - {BRIDGE, M5602_XB_GPIO_DIR_H, 0x3e, 0x00}, - {BRIDGE, M5602_XB_GPIO_DAT_H, 0x02, 0x00}, - {BRIDGE, M5602_XB_GPIO_EN_L, 0xff, 0x00}, - {BRIDGE, M5602_XB_GPIO_DIR_L, 0xff, 0x00}, - {BRIDGE, M5602_XB_GPIO_DAT_L, 0x00, 0x00}, - {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x04, 0x00}, - {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, - {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, - {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, - {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00}, - {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00}, - {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, - {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, - {BRIDGE, M5602_XB_GPIO_DIR, 0x07, 0x00}, - {BRIDGE, M5602_XB_GPIO_DAT, 0x0b, 0x00}, {BRIDGE, M5602_XB_GPIO_EN_H, 0x06, 0x00}, {BRIDGE, M5602_XB_GPIO_EN_L, 0x00, 0x00}, {BRIDGE, M5602_XB_I2C_CLK_DIV, 0x0a, 0x00}, @@ -380,70 +186,6 @@ static const unsigned char init_mt9m111[][4] = {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, {SENSOR, MT9M111_SC_RESET, 0x00, 0x08}, - {BRIDGE, M5602_XB_I2C_REG_ADDR, 0xcd, 0x00}, - {SENSOR, 0xcd, 0x00, 0x0e}, - {BRIDGE, M5602_XB_I2C_REG_ADDR, 0xd0, 0x00}, - {SENSOR, 0xd0, 0x00, 0x40}, - {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x02}, - {SENSOR, MT9M111_CC_AUTO_EXPOSURE_PARAMETER_18, 0x00, 0x00}, - {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x28, 0x00}, - {SENSOR, MT9M111_CC_AWB_PARAMETER_7, 0xef, 0x07}, - {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x28, 0x00}, - {SENSOR, MT9M111_CC_AWB_PARAMETER_7, 0xef, 0x03}, - {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, - {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x33, 0x00}, - {SENSOR, 0x33, 0x03, 0x49}, - {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x33, 0x00}, - - {SENSOR, 0x33, 0x03, 0x49}, - {SENSOR, 0x34, 0xc0, 0x19}, - {SENSOR, 0x3f, 0x20, 0x20}, - {SENSOR, 0x40, 0x20, 0x20}, - {SENSOR, 0x5a, 0xc0, 0x0a}, - {SENSOR, 0x70, 0x7b, 0x0a}, - {SENSOR, 0x71, 0xff, 0x00}, - {SENSOR, 0x72, 0x19, 0x0e}, - {SENSOR, 0x73, 0x18, 0x0f}, - {SENSOR, 0x74, 0x57, 0x32}, - {SENSOR, 0x75, 0x56, 0x34}, - {SENSOR, 0x76, 0x73, 0x35}, - {SENSOR, 0x77, 0x30, 0x12}, - {SENSOR, 0x78, 0x79, 0x02}, - {SENSOR, 0x79, 0x75, 0x06}, - {SENSOR, 0x7a, 0x77, 0x0a}, - {SENSOR, 0x7b, 0x78, 0x09}, - {SENSOR, 0x7c, 0x7d, 0x06}, - {SENSOR, 0x7d, 0x31, 0x10}, - {SENSOR, 0x7e, 0x00, 0x7e}, - {SENSOR, 0x80, 0x59, 0x04}, - {SENSOR, 0x81, 0x59, 0x04}, - {SENSOR, 0x82, 0x57, 0x0a}, - {SENSOR, 0x83, 0x58, 0x0b}, - {SENSOR, 0x84, 0x47, 0x0c}, - {SENSOR, 0x85, 0x48, 0x0e}, - {SENSOR, 0x86, 0x5b, 0x02}, - {SENSOR, 0x87, 0x00, 0x5c}, - {SENSOR, MT9M111_CONTEXT_CONTROL, 0x00, 0x08}, - {SENSOR, 0x60, 0x00, 0x80}, - {SENSOR, 0x61, 0x00, 0x00}, - {SENSOR, 0x62, 0x00, 0x00}, - {SENSOR, 0x63, 0x00, 0x00}, - {SENSOR, 0x64, 0x00, 0x00}, - - {SENSOR, MT9M111_SC_ROWSTART, 0x00, 0x0d}, - {SENSOR, MT9M111_SC_COLSTART, 0x00, 0x18}, - {SENSOR, MT9M111_SC_WINDOW_HEIGHT, 0x04, 0x04}, - {SENSOR, MT9M111_SC_WINDOW_WIDTH, 0x05, 0x08}, - {SENSOR, MT9M111_SC_HBLANK_CONTEXT_B, 0x01, 0x38}, - {SENSOR, MT9M111_SC_VBLANK_CONTEXT_B, 0x00, 0x11}, - {SENSOR, MT9M111_SC_HBLANK_CONTEXT_A, 0x01, 0x38}, - {SENSOR, MT9M111_SC_VBLANK_CONTEXT_A, 0x00, 0x11}, - {SENSOR, MT9M111_SC_R_MODE_CONTEXT_B, 0x01, 0x03}, - {SENSOR, MT9M111_SC_R_MODE_CONTEXT_A, 0x01, 0x03}, - {SENSOR, 0x30, 0x04, 0x00}, - - {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, - {SENSOR, MT9M111_SC_SHUTTER_WIDTH, 0x01, 0xf4}, {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, @@ -472,24 +214,6 @@ static const unsigned char init_mt9m111[][4] = {BRIDGE, M5602_XB_I2C_REG_ADDR, 0xb3, 0x00}, {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00}, {SENSOR, MT9M111_CP_GLOBAL_CLK_CONTROL, 0x00, 0x03}, - {BRIDGE, M5602_XB_GPIO_DIR, 0x05, 0x00}, - {BRIDGE, M5602_XB_GPIO_DAT, 0x04, 0x00}, - {BRIDGE, M5602_XB_GPIO_EN_H, 0x3e, 0x00}, - {BRIDGE, M5602_XB_GPIO_DIR_H, 0x3e, 0x00}, - {BRIDGE, M5602_XB_GPIO_DAT_H, 0x02, 0x00}, - {BRIDGE, M5602_XB_GPIO_EN_L, 0xff, 0x00}, - {BRIDGE, M5602_XB_GPIO_DIR_L, 0xff, 0x00}, - {BRIDGE, M5602_XB_GPIO_DAT_L, 0x00, 0x00}, - {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x04, 0x00}, - {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, - {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, - {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, - {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00}, - {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00}, - {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, - {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, - {BRIDGE, M5602_XB_GPIO_DIR, 0x07, 0x00}, - {BRIDGE, M5602_XB_GPIO_DAT, 0x0b, 0x00}, {BRIDGE, M5602_XB_GPIO_EN_H, 0x06, 0x00}, {BRIDGE, M5602_XB_GPIO_EN_L, 0x00, 0x00}, {BRIDGE, M5602_XB_I2C_CLK_DIV, 0x0a, 0x00}, @@ -508,81 +232,10 @@ static const unsigned char init_mt9m111[][4] = {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x0d, 0x00}, {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00}, - {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00}, - {BRIDGE, M5602_XB_I2C_REG_ADDR, 0xcd, 0x00}, - {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00}, - {SENSOR, 0xcd, 0x00, 0x0e}, - {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00}, - {BRIDGE, M5602_XB_I2C_REG_ADDR, 0xd0, 0x00}, - {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00}, - {SENSOR, 0xd0, 0x00, 0x40}, - {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x02}, - {SENSOR, MT9M111_CC_AUTO_EXPOSURE_PARAMETER_18, 0x00, 0x00}, - {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00}, - {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x28, 0x00}, - {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00}, - {SENSOR, MT9M111_CC_AWB_PARAMETER_7, 0xef, 0x07}, - {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00}, - {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x28, 0x00}, - {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00}, - {SENSOR, MT9M111_CC_AWB_PARAMETER_7, 0xef, 0x03}, - {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, - {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00}, - {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x33, 0x00}, - {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00}, - {SENSOR, 0x33, 0x03, 0x49}, {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00}, {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x33, 0x00}, {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00}, - {SENSOR, 0x33, 0x03, 0x49}, - {SENSOR, 0x34, 0xc0, 0x19}, - {SENSOR, 0x3f, 0x20, 0x20}, - {SENSOR, 0x40, 0x20, 0x20}, - {SENSOR, 0x5a, 0xc0, 0x0a}, - {SENSOR, 0x70, 0x7b, 0x0a}, - {SENSOR, 0x71, 0xff, 0x00}, - {SENSOR, 0x72, 0x19, 0x0e}, - {SENSOR, 0x73, 0x18, 0x0f}, - {SENSOR, 0x74, 0x57, 0x32}, - {SENSOR, 0x75, 0x56, 0x34}, - {SENSOR, 0x76, 0x73, 0x35}, - {SENSOR, 0x77, 0x30, 0x12}, - {SENSOR, 0x78, 0x79, 0x02}, - {SENSOR, 0x79, 0x75, 0x06}, - {SENSOR, 0x7a, 0x77, 0x0a}, - {SENSOR, 0x7b, 0x78, 0x09}, - {SENSOR, 0x7c, 0x7d, 0x06}, - {SENSOR, 0x7d, 0x31, 0x10}, - {SENSOR, 0x7e, 0x00, 0x7e}, - {SENSOR, 0x80, 0x59, 0x04}, - {SENSOR, 0x81, 0x59, 0x04}, - {SENSOR, 0x82, 0x57, 0x0a}, - {SENSOR, 0x83, 0x58, 0x0b}, - {SENSOR, 0x84, 0x47, 0x0c}, - {SENSOR, 0x85, 0x48, 0x0e}, - {SENSOR, 0x86, 0x5b, 0x02}, - {SENSOR, 0x87, 0x00, 0x5c}, - {SENSOR, MT9M111_CONTEXT_CONTROL, 0x00, 0x08}, - {SENSOR, 0x60, 0x00, 0x80}, - {SENSOR, 0x61, 0x00, 0x00}, - {SENSOR, 0x62, 0x00, 0x00}, - {SENSOR, 0x63, 0x00, 0x00}, - {SENSOR, 0x64, 0x00, 0x00}, - {SENSOR, MT9M111_SC_ROWSTART, 0x00, 0x0d}, - {SENSOR, MT9M111_SC_COLSTART, 0x00, 0x12}, - {SENSOR, MT9M111_SC_WINDOW_HEIGHT, 0x04, 0x00}, - {SENSOR, MT9M111_SC_WINDOW_WIDTH, 0x05, 0x10}, - {SENSOR, MT9M111_SC_HBLANK_CONTEXT_B, 0x01, 0x60}, - {SENSOR, MT9M111_SC_VBLANK_CONTEXT_B, 0x00, 0x11}, - {SENSOR, MT9M111_SC_HBLANK_CONTEXT_A, 0x01, 0x60}, - {SENSOR, MT9M111_SC_VBLANK_CONTEXT_A, 0x00, 0x11}, - {SENSOR, MT9M111_SC_R_MODE_CONTEXT_B, 0x01, 0x0f}, - {SENSOR, MT9M111_SC_R_MODE_CONTEXT_A, 0x01, 0x0f}, - {SENSOR, 0x30, 0x04, 0x00}, - - {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, - {SENSOR, MT9M111_SC_SHUTTER_WIDTH, 0x01, 0x90}, {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, @@ -611,7 +264,6 @@ static const unsigned char init_mt9m111[][4] = {BRIDGE, M5602_XB_I2C_REG_ADDR, 0xb3, 0x00}, {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00}, {SENSOR, MT9M111_CP_GLOBAL_CLK_CONTROL, 0x00, 0x03}, - {BRIDGE, M5602_XB_GPIO_DIR, 0x05, 0x00}, {BRIDGE, M5602_XB_GPIO_DAT, 0x04, 0x00}, {BRIDGE, M5602_XB_GPIO_EN_H, 0x3e, 0x00}, @@ -680,10 +332,6 @@ static const unsigned char init_mt9m111[][4] = {SENSOR, MT9M111_CC_AWB_PARAMETER_7, 0xef, 0x03}, {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, - {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00}, - {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x33, 0x00}, - {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00}, - {SENSOR, 0x33, 0x03, 0x49}, {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00}, {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x33, 0x00}, {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00}, -- cgit v1.2.3 From 9b3f212120d0ae53a99328117b273db3f6532446 Mon Sep 17 00:00:00 2001 From: Erik Andr?n Date: Sun, 11 Jan 2009 16:46:51 +0100 Subject: gspca - m5602-po1030: Release reset when init is done. From: Erik Andr?n Priority: normal Signed-off-by: Erik Andr?n --- linux/drivers/media/video/gspca/m5602/m5602_po1030.h | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/m5602/m5602_po1030.h b/linux/drivers/media/video/gspca/m5602/m5602_po1030.h index 5ba3f73b7..886503729 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_po1030.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_po1030.h @@ -250,6 +250,14 @@ static const unsigned char init_po1030[][3] = {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x04}, {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0}, /*end of sequence 2 stop */ + + {BRIDGE, M5602_XB_GPIO_DIR, 0x05}, + {BRIDGE, M5602_XB_GPIO_DAT, 0x00}, + {BRIDGE, M5602_XB_GPIO_EN_H, 0x06}, + {BRIDGE, M5602_XB_GPIO_EN_L, 0x00}, + + {SENSOR, PO1030_AUTOCTRL2, 0x04}, + }; static const unsigned char start_po1030[][3] = -- cgit v1.2.3 From 01a75ffc4cede4889f8c8a460e898bc8adb5b15e Mon Sep 17 00:00:00 2001 From: Erik Andr?n Date: Sun, 11 Jan 2009 16:52:10 +0100 Subject: gspca - m5602-po1030: Fix sensor probing. From: Erik Andr?n The po1030 read sensor are currently returning the contents of the address+1 fix the probing of the sensor to cope with this. Obviously this needs to be tracked down and fixed. Priority: normal Signed-off-by: Erik Andr?n --- linux/drivers/media/video/gspca/m5602/m5602_po1030.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/m5602/m5602_po1030.c b/linux/drivers/media/video/gspca/m5602/m5602_po1030.c index 3ecb53c70..a45d55c53 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_po1030.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_po1030.c @@ -157,7 +157,7 @@ static void po1030_dump_registers(struct sd *sd); int po1030_probe(struct sd *sd) { - u8 dev_id_h = 0, dev_id_l = 0, i; + u8 dev_id_h = 0, i; s32 *sensor_settings; if (force_sensor) { @@ -185,10 +185,7 @@ int po1030_probe(struct sd *sd) if (m5602_read_sensor(sd, PO1030_DEVID_H, &dev_id_h, 1)) return -ENODEV; - if (m5602_read_sensor(sd, PO1030_DEVID_L, &dev_id_l, 1)) - return -ENODEV; - - if ((dev_id_h == 0x10) && (dev_id_l == 0x30)) { + if (dev_id_h == 0x30) { info("Detected a po1030 sensor"); goto sensor_found; } -- cgit v1.2.3 From 1f91ae0862f13d5de573fdba70e38fe6b4d671de Mon Sep 17 00:00:00 2001 From: Erik Andr?n Date: Sun, 11 Jan 2009 17:00:15 +0100 Subject: gspca - m5602-po1030: Lower the default blue and gain balance From: Erik Andr?n Priority: normal Signed-off-by: Erik Andr?n --- linux/drivers/media/video/gspca/m5602/m5602_po1030.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/m5602/m5602_po1030.h b/linux/drivers/media/video/gspca/m5602/m5602_po1030.h index 886503729..b70879fdd 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_po1030.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_po1030.h @@ -137,8 +137,8 @@ #define PO1030_GLOBAL_GAIN_DEFAULT 0x12 #define PO1030_EXPOSURE_DEFAULT 0x0085 -#define PO1030_BLUE_GAIN_DEFAULT 0x40 -#define PO1030_RED_GAIN_DEFAULT 0x40 +#define PO1030_BLUE_GAIN_DEFAULT 0x36 +#define PO1030_RED_GAIN_DEFAULT 0x36 /*****************************************************************************/ -- cgit v1.2.3 From 860ec8dfc35552bb9a0686be7747c1ca73327648 Mon Sep 17 00:00:00 2001 From: Erik Andr?n Date: Sun, 11 Jan 2009 17:39:41 +0100 Subject: gspca - m5602: Add some more register defines From: Erik Andr?n Priority: normal Signed-off-by: Erik Andr?n --- .../drivers/media/video/gspca/m5602/m5602_bridge.h | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/m5602/m5602_bridge.h b/linux/drivers/media/video/gspca/m5602/m5602_bridge.h index 8f1cea6fd..34515e54c 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_bridge.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_bridge.h @@ -45,6 +45,15 @@ #define M5602_XB_SEN_CLK_DIV 0x15 #define M5602_XB_AUD_CLK_CTRL 0x16 #define M5602_XB_AUD_CLK_DIV 0x17 +#define M5602_OB_AC_LINK_STATE 0x22 +#define M5602_OB_PCM_SLOT_INDEX 0x24 +#define M5602_OB_GPIO_SLOT_INDEX 0x25 +#define M5602_OB_ACRX_STATUS_ADDRESS_H 0x28 +#define M5602_OB_ACRX_STATUS_DATA_L 0x29 +#define M5602_OB_ACRX_STATUS_DATA_H 0x2a +#define M5602_OB_ACTX_COMMAND_ADDRESS 0x31 +#define M5602_OB_ACRX_COMMAND_DATA_L 0x32 +#define M5602_OB_ACTX_COMMAND_DATA_H 0X33 #define M5602_XB_DEVCTR1 0x41 #define M5602_XB_EPSETR0 0x42 #define M5602_XB_EPAFCTR 0x47 @@ -77,7 +86,18 @@ #define M5602_XB_GPIO_EN_L 0x75 #define M5602_XB_GPIO_DAT 0x76 #define M5602_XB_GPIO_DIR 0x77 -#define M5602_XB_MISC_CTL 0x70 +#define M5602_XB_SEN_CLK_CONTROL 0x80 +#define M5602_XB_SEN_CLK_DIVISION 0x81 +#define M5602_XB_CPR_CLK_CONTROL 0x82 +#define M5602_XB_CPR_CLK_DIVISION 0x83 +#define M5602_XB_MCU_CLK_CONTROL 0x84 +#define M5602_XB_MCU_CLK_DIVISION 0x85 +#define M5602_XB_DCT_CLK_CONTROL 0x86 +#define M5602_XB_DCT_CLK_DIVISION 0x87 +#define M5602_XB_EC_CLK_CONTROL 0x88 +#define M5602_XB_EC_CLK_DIVISION 0x89 +#define M5602_XB_LBUF_CLK_CONTROL 0x8a +#define M5602_XB_LBUF_CLK_DIVISION 0x8b #define I2C_BUSY 0x80 -- cgit v1.2.3 From ab4d9317b5d4b241ffd1fb5aff48e6addf48202c Mon Sep 17 00:00:00 2001 From: Erik Andr?n Date: Sun, 11 Jan 2009 19:23:46 +0100 Subject: gspca - m5602-po1030: Set the blue balance in the init not red balance twice From: Erik Andr?n Priority: normal Signed-off-by: Erik Andr?n --- linux/drivers/media/video/gspca/m5602/m5602_po1030.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/m5602/m5602_po1030.c b/linux/drivers/media/video/gspca/m5602/m5602_po1030.c index a45d55c53..26ac61978 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_po1030.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_po1030.c @@ -264,7 +264,7 @@ int po1030_init(struct sd *sd) if (err < 0) return err; - err = po1030_set_red_balance(&sd->gspca_dev, + err = po1030_set_blue_balance(&sd->gspca_dev, sensor_settings[BLUE_BALANCE_IDX]); if (err < 0) return err; -- cgit v1.2.3 From 803d7c0352021cd1694ec1e01d1d9f07f1e5aa0e Mon Sep 17 00:00:00 2001 From: Erik Andr?n Date: Mon, 12 Jan 2009 17:43:42 +0100 Subject: gspca - m5602-mt9m111: Replace various magic constants with defines From: Erik Andr?n Priority: normal Signed-off-by: Erik Andr?n --- .../media/video/gspca/m5602/m5602_mt9m111.h | 60 ++++++++++++++-------- 1 file changed, 39 insertions(+), 21 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h b/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h index 0ffa98c0f..750a3fd42 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h @@ -37,7 +37,6 @@ #define MT9M111_SC_VBLANK_CONTEXT_A 0x08 #define MT9M111_SC_SHUTTER_WIDTH 0x09 #define MT9M111_SC_ROW_SPEED 0x0a - #define MT9M111_SC_EXTRA_DELAY 0x0b #define MT9M111_SC_SHUTTER_DELAY 0x0c #define MT9M111_SC_RESET 0x0d @@ -50,9 +49,6 @@ #define MT9M111_SC_GREEN_2_GAIN 0x2e #define MT9M111_SC_GLOBAL_GAIN 0x2f -#define MT9M111_RMB_MIRROR_ROWS (1 << 0) -#define MT9M111_RMB_MIRROR_COLS (1 << 1) - #define MT9M111_CONTEXT_CONTROL 0xc8 #define MT9M111_PAGE_MAP 0xf0 #define MT9M111_BYTEWISE_ADDRESS 0xf1 @@ -74,7 +70,24 @@ #define MT9M111_COLORPIPE 0x01 #define MT9M111_CAMERA_CONTROL 0x02 +#define MT9M111_RESET (1 << 0) +#define MT9M111_RESTART (1 << 1) +#define MT9M111_ANALOG_STANDBY (1 << 2) +#define MT9M111_CHIP_ENABLE (1 << 3) +#define MT9M111_CHIP_DISABLE (0 << 3) +#define MT9M111_OUTPUT_DISABLE (1 << 4) +#define MT9M111_SHOW_BAD_FRAMES (1 << 0) +#define MT9M111_RESTART_BAD_FRAMES (1 << 1) +#define MT9M111_SYNCHRONIZE_CHANGES (1 << 7) + +#define MT9M111_RMB_MIRROR_ROWS (1 << 0) +#define MT9M111_RMB_MIRROR_COLS (1 << 1) + #define MT9M111_COLOR_MATRIX_BYPASS (1 << 4) +#define MT9M111_SEL_CONTEXT_B (1 << 3) + +#define MT9M111_TRISTATE_PIN_IN_STANDBY (1 << 1) +#define MT9M111_SOC_SOFT_STANDBY (1 << 0) #define INITIAL_MAX_GAIN 64 #define DEFAULT_GAIN 283 @@ -112,7 +125,14 @@ static const unsigned char preinit_mt9m111[][4] = {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00}, {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, - {SENSOR, MT9M111_SC_RESET, 0xff, 0xf7}, + {SENSOR, MT9M111_SC_RESET, + MT9M111_RESET | + MT9M111_RESTART | + MT9M111_ANALOG_STANDBY | + MT9M111_CHIP_DISABLE, + MT9M111_SHOW_BAD_FRAMES | + MT9M111_RESTART_BAD_FRAMES | + MT9M111_SYNCHRONIZE_CHANGES}, {BRIDGE, M5602_XB_GPIO_DIR, 0x05, 0x00}, {BRIDGE, M5602_XB_GPIO_DAT, 0x04, 0x00}, @@ -149,15 +169,13 @@ static const unsigned char init_mt9m111[][4] = {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, {SENSOR, MT9M111_SC_RESET, 0xff, 0xff}, - {SENSOR, MT9M111_SC_RESET, 0xff, 0xff}, {SENSOR, MT9M111_SC_RESET, 0xff, 0xde}, {SENSOR, MT9M111_SC_RESET, 0xff, 0xff}, {SENSOR, MT9M111_SC_RESET, 0xff, 0xf7}, {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x01}, - - {BRIDGE, M5602_XB_I2C_REG_ADDR, 0xb3, 0x00}, - - {SENSOR, MT9M111_CP_GLOBAL_CLK_CONTROL, 0xff, 0xff}, + {SENSOR, MT9M111_CP_GLOBAL_CLK_CONTROL, 0x00, + MT9M111_TRISTATE_PIN_IN_STANDBY | + MT9M111_SOC_SOFT_STANDBY}, {BRIDGE, M5602_XB_GPIO_EN_H, 0x06, 0x00}, {BRIDGE, M5602_XB_GPIO_EN_L, 0x00, 0x00}, @@ -364,23 +382,23 @@ static const unsigned char init_mt9m111[][4] = {SENSOR, 0x85, 0x48, 0x0e}, {SENSOR, 0x86, 0x5b, 0x02}, {SENSOR, 0x87, 0x00, 0x5c}, - {SENSOR, MT9M111_CONTEXT_CONTROL, 0x00, 0x08}, + {SENSOR, MT9M111_CONTEXT_CONTROL, 0x00, MT9M111_SEL_CONTEXT_B}, {SENSOR, 0x60, 0x00, 0x80}, {SENSOR, 0x61, 0x00, 0x00}, {SENSOR, 0x62, 0x00, 0x00}, {SENSOR, 0x63, 0x00, 0x00}, {SENSOR, 0x64, 0x00, 0x00}, - {SENSOR, MT9M111_SC_ROWSTART, 0x00, 0x0d}, - {SENSOR, MT9M111_SC_COLSTART, 0x00, 0x12}, - {SENSOR, MT9M111_SC_WINDOW_HEIGHT, 0x04, 0x00}, - {SENSOR, MT9M111_SC_WINDOW_WIDTH, 0x05, 0x10}, - {SENSOR, MT9M111_SC_HBLANK_CONTEXT_B, 0x01, 0x60}, - {SENSOR, MT9M111_SC_VBLANK_CONTEXT_B, 0x00, 0x11}, - {SENSOR, MT9M111_SC_HBLANK_CONTEXT_A, 0x01, 0x60}, - {SENSOR, MT9M111_SC_VBLANK_CONTEXT_A, 0x00, 0x11}, - {SENSOR, MT9M111_SC_R_MODE_CONTEXT_B, 0x01, 0x0f}, - {SENSOR, MT9M111_SC_R_MODE_CONTEXT_A, 0x01, 0x0f}, + {SENSOR, MT9M111_SC_ROWSTART, 0x00, 0x0d}, /* 13 */ + {SENSOR, MT9M111_SC_COLSTART, 0x00, 0x12}, /* 18 */ + {SENSOR, MT9M111_SC_WINDOW_HEIGHT, 0x04, 0x00}, /* 1024 */ + {SENSOR, MT9M111_SC_WINDOW_WIDTH, 0x05, 0x10}, /* 1296 */ + {SENSOR, MT9M111_SC_HBLANK_CONTEXT_B, 0x01, 0x60}, /* 352 */ + {SENSOR, MT9M111_SC_VBLANK_CONTEXT_B, 0x00, 0x11}, /* 17 */ + {SENSOR, MT9M111_SC_HBLANK_CONTEXT_A, 0x01, 0x60}, /* 352 */ + {SENSOR, MT9M111_SC_VBLANK_CONTEXT_A, 0x00, 0x11}, /* 17 */ + {SENSOR, MT9M111_SC_R_MODE_CONTEXT_B, 0x01, 0x0f}, /* 271 */ + {SENSOR, MT9M111_SC_R_MODE_CONTEXT_A, 0x01, 0x0f}, /* 271 */ {SENSOR, 0x30, 0x04, 0x00}, {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06, 0x00}, -- cgit v1.2.3 From 9d6f66b3f1c609e3d840c20115e24ebdb0624cf8 Mon Sep 17 00:00:00 2001 From: Erik Andr?n Date: Mon, 12 Jan 2009 17:50:29 +0100 Subject: gspca - m5602-mt9m111: More magic constants replacement From: Erik Andr?n Priority: normal Signed-off-by: Erik Andr?n --- linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h b/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h index 750a3fd42..cac902309 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h @@ -89,6 +89,8 @@ #define MT9M111_TRISTATE_PIN_IN_STANDBY (1 << 1) #define MT9M111_SOC_SOFT_STANDBY (1 << 0) +#define MT9M111_2D_DEFECT_CORRECTION_ENABLE (1 << 0) + #define INITIAL_MAX_GAIN 64 #define DEFAULT_GAIN 283 @@ -323,8 +325,8 @@ static const unsigned char init_mt9m111[][4] = {SENSOR, MT9M111_CP_OPERATING_MODE_CTL, 0x00, MT9M111_CP_OPERATING_MODE_CTL}, {SENSOR, MT9M111_CP_LENS_CORRECTION_1, 0x04, 0x2a}, - {SENSOR, MT9M111_CP_DEFECT_CORR_CONTEXT_A, 0x00, 0x01}, - {SENSOR, MT9M111_CP_DEFECT_CORR_CONTEXT_B, 0x00, 0x01}, + {SENSOR, MT9M111_CP_DEFECT_CORR_CONTEXT_A, 0x00, MT9M111_2D_DEFECT_CORRECTION_ENABLE}, + {SENSOR, MT9M111_CP_DEFECT_CORR_CONTEXT_B, 0x00, MT9M111_2D_DEFECT_CORRECTION_ENABLE}, {SENSOR, MT9M111_CP_LUMA_OFFSET, 0x00, 0x00}, {SENSOR, MT9M111_CP_LUMA_CLIP, 0xff, 0x00}, {SENSOR, MT9M111_CP_OUTPUT_FORMAT_CTL2_CONTEXT_A, 0x14, 0x00}, -- cgit v1.2.3 From 2f6459fc75a592d37d23ac3ef21a1233a3367260 Mon Sep 17 00:00:00 2001 From: Erik Andr?n Date: Mon, 12 Jan 2009 17:56:13 +0100 Subject: gspca - m5602-mt9m111: Remove lots of redundant sensor reads From: Erik Andr?n Priority: normal Signed-off-by: Erik Andr?n --- .../media/video/gspca/m5602/m5602_mt9m111.h | 84 +--------------------- 1 file changed, 2 insertions(+), 82 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h b/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h index cac902309..d1bb9ddd6 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h @@ -193,7 +193,6 @@ static const unsigned char init_mt9m111[][4] = {SENSOR, MT9M111_SC_RESET, 0x00, 0x0c}, {SENSOR, MT9M111_SC_RESET, 0x00, 0x04}, {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x01}, - {BRIDGE, M5602_XB_I2C_REG_ADDR, 0xb3, 0x00}, {SENSOR, MT9M111_CP_GLOBAL_CLK_CONTROL, 0x00, 0x03}, {BRIDGE, M5602_XB_GPIO_EN_H, 0x06, 0x00}, {BRIDGE, M5602_XB_GPIO_EN_L, 0x00, 0x00}, @@ -209,81 +208,30 @@ static const unsigned char init_mt9m111[][4] = {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, - {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00}, - {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x0d, 0x00}, - {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00}, {SENSOR, MT9M111_SC_RESET, 0x00, 0x09}, - {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00}, - {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x0d, 0x00}, - {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00}, {SENSOR, MT9M111_SC_RESET, 0x00, 0x29}, - {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00}, - {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x0d, 0x00}, - {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00}, {SENSOR, MT9M111_SC_RESET, 0x00, 0x08}, - {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00}, - {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x0d, 0x00}, - {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00}, {SENSOR, MT9M111_SC_RESET, 0x00, 0x0c}, - {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00}, - {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x0d, 0x00}, - {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00}, {SENSOR, MT9M111_SC_RESET, 0x00, 0x04}, {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x01}, - {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00}, - {BRIDGE, M5602_XB_I2C_REG_ADDR, 0xb3, 0x00}, - {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00}, {SENSOR, MT9M111_CP_GLOBAL_CLK_CONTROL, 0x00, 0x03}, - {BRIDGE, M5602_XB_GPIO_EN_H, 0x06, 0x00}, - {BRIDGE, M5602_XB_GPIO_EN_L, 0x00, 0x00}, - {BRIDGE, M5602_XB_I2C_CLK_DIV, 0x0a, 0x00}, {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, - {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00}, - {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x0d, 0x00}, - {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00}, {SENSOR, MT9M111_SC_RESET, 0x00, 0x05}, {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, - {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00}, - {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x0d, 0x00}, - {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00}, {SENSOR, MT9M111_SC_RESET, 0x00, 0x29}, {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, - {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00}, - {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x0d, 0x00}, - {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00}, - - {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00}, - {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x33, 0x00}, - {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00}, {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, - {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00}, - {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x0d, 0x00}, - {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00}, {SENSOR, MT9M111_SC_RESET, 0x00, 0x09}, - {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00}, - {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x0d, 0x00}, - {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00}, {SENSOR, MT9M111_SC_RESET, 0x00, 0x29}, - {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00}, - {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x0d, 0x00}, - {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00}, {SENSOR, MT9M111_SC_RESET, 0x00, 0x08}, - {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00}, - {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x0d, 0x00}, - {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00}, {SENSOR, MT9M111_SC_RESET, 0x00, 0x0c}, - {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00}, - {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x0d, 0x00}, - {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00}, {SENSOR, MT9M111_SC_RESET, 0x00, 0x04}, {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x01}, - {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00}, - {BRIDGE, M5602_XB_I2C_REG_ADDR, 0xb3, 0x00}, - {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00}, {SENSOR, MT9M111_CP_GLOBAL_CLK_CONTROL, 0x00, 0x03}, + {BRIDGE, M5602_XB_GPIO_DIR, 0x05, 0x00}, {BRIDGE, M5602_XB_GPIO_DAT, 0x04, 0x00}, {BRIDGE, M5602_XB_GPIO_EN_H, 0x3e, 0x00}, @@ -292,8 +240,6 @@ static const unsigned char init_mt9m111[][4] = {BRIDGE, M5602_XB_GPIO_EN_L, 0xff, 0x00}, {BRIDGE, M5602_XB_GPIO_DIR_L, 0xff, 0x00}, {BRIDGE, M5602_XB_GPIO_DAT_L, 0x00, 0x00}, - {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x04, 0x00}, - {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00}, @@ -305,21 +251,12 @@ static const unsigned char init_mt9m111[][4] = {BRIDGE, M5602_XB_GPIO_EN_H, 0x06, 0x00}, {BRIDGE, M5602_XB_GPIO_EN_L, 0x00, 0x00}, {BRIDGE, M5602_XB_I2C_CLK_DIV, 0x0a, 0x00}, + {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, - {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00}, - {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x0d, 0x00}, - {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00}, {SENSOR, MT9M111_SC_RESET, 0x00, 0x05}, {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, - {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00}, - {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x0d, 0x00}, - {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00}, {SENSOR, MT9M111_SC_RESET, 0x00, 0x29}, {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, - {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00}, - {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x0d, 0x00}, - {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00}, - {SENSOR, MT9M111_SC_RESET, 0x00, 0x08}, {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x01}, {SENSOR, MT9M111_CP_OPERATING_MODE_CTL, 0x00, @@ -332,30 +269,13 @@ static const unsigned char init_mt9m111[][4] = {SENSOR, MT9M111_CP_OUTPUT_FORMAT_CTL2_CONTEXT_A, 0x14, 0x00}, {SENSOR, MT9M111_CP_OUTPUT_FORMAT_CTL2_CONTEXT_B, 0x14, 0x00}, - {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00}, - {BRIDGE, M5602_XB_I2C_REG_ADDR, 0xcd, 0x00}, - {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00}, {SENSOR, 0xcd, 0x00, 0x0e}, - {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00}, - {BRIDGE, M5602_XB_I2C_REG_ADDR, 0xd0, 0x00}, - {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00}, {SENSOR, 0xd0, 0x00, 0x40}, {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x02}, {SENSOR, MT9M111_CC_AUTO_EXPOSURE_PARAMETER_18, 0x00, 0x00}, - {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00}, - {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x28, 0x00}, - {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00}, - {SENSOR, MT9M111_CC_AWB_PARAMETER_7, 0xef, 0x07}, - {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00}, - {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x28, 0x00}, - {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00}, {SENSOR, MT9M111_CC_AWB_PARAMETER_7, 0xef, 0x03}, {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, - {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00}, - {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x33, 0x00}, - {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00}, - {SENSOR, 0x33, 0x03, 0x49}, {SENSOR, 0x34, 0xc0, 0x19}, {SENSOR, 0x3f, 0x20, 0x20}, -- cgit v1.2.3 From 1f07c6370afaa573622a4eea96ff3779fff99656 Mon Sep 17 00:00:00 2001 From: Erik Andr?n Date: Mon, 12 Jan 2009 18:00:51 +0100 Subject: gspca - m5602-mt9m111: More constant replacement From: Erik Andr?n Priority: normal Signed-off-by: Erik Andr?n --- linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h b/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h index d1bb9ddd6..5dd90a66a 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h @@ -193,7 +193,9 @@ static const unsigned char init_mt9m111[][4] = {SENSOR, MT9M111_SC_RESET, 0x00, 0x0c}, {SENSOR, MT9M111_SC_RESET, 0x00, 0x04}, {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x01}, - {SENSOR, MT9M111_CP_GLOBAL_CLK_CONTROL, 0x00, 0x03}, + {SENSOR, MT9M111_CP_GLOBAL_CLK_CONTROL, 0x00, + MT9M111_TRISTATE_PIN_IN_STANDBY | + MT9M111_SOC_SOFT_STANDBY}, {BRIDGE, M5602_XB_GPIO_EN_H, 0x06, 0x00}, {BRIDGE, M5602_XB_GPIO_EN_L, 0x00, 0x00}, {BRIDGE, M5602_XB_I2C_CLK_DIV, 0x0a, 0x00}, @@ -214,7 +216,9 @@ static const unsigned char init_mt9m111[][4] = {SENSOR, MT9M111_SC_RESET, 0x00, 0x0c}, {SENSOR, MT9M111_SC_RESET, 0x00, 0x04}, {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x01}, - {SENSOR, MT9M111_CP_GLOBAL_CLK_CONTROL, 0x00, 0x03}, + {SENSOR, MT9M111_CP_GLOBAL_CLK_CONTROL, 0x00, + MT9M111_TRISTATE_PIN_IN_STANDBY | + MT9M111_SOC_SOFT_STANDBY}, {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, {SENSOR, MT9M111_SC_RESET, 0x00, 0x05}, {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, @@ -230,8 +234,9 @@ static const unsigned char init_mt9m111[][4] = {SENSOR, MT9M111_SC_RESET, 0x00, 0x0c}, {SENSOR, MT9M111_SC_RESET, 0x00, 0x04}, {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x01}, - {SENSOR, MT9M111_CP_GLOBAL_CLK_CONTROL, 0x00, 0x03}, - + {SENSOR, MT9M111_CP_GLOBAL_CLK_CONTROL, 0x00, + MT9M111_TRISTATE_PIN_IN_STANDBY | + MT9M111_SOC_SOFT_STANDBY}, {BRIDGE, M5602_XB_GPIO_DIR, 0x05, 0x00}, {BRIDGE, M5602_XB_GPIO_DAT, 0x04, 0x00}, {BRIDGE, M5602_XB_GPIO_EN_H, 0x3e, 0x00}, @@ -274,8 +279,8 @@ static const unsigned char init_mt9m111[][4] = {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x02}, {SENSOR, MT9M111_CC_AUTO_EXPOSURE_PARAMETER_18, 0x00, 0x00}, {SENSOR, MT9M111_CC_AWB_PARAMETER_7, 0xef, 0x03}, - {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, + {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, {SENSOR, 0x33, 0x03, 0x49}, {SENSOR, 0x34, 0xc0, 0x19}, {SENSOR, 0x3f, 0x20, 0x20}, -- cgit v1.2.3 From 65204d233fc70caf38045e1838fe456bc6fd7572 Mon Sep 17 00:00:00 2001 From: Erik Andr?n Date: Mon, 12 Jan 2009 18:17:05 +0100 Subject: gspca - m5602-mt9m111: Remove lots of redundant init code From: Erik Andr?n Priority: normal Signed-off-by: Erik Andr?n --- .../media/video/gspca/m5602/m5602_mt9m111.h | 95 +--------------------- 1 file changed, 4 insertions(+), 91 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h b/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h index 5dd90a66a..d0fe02cea 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h @@ -162,104 +162,19 @@ static const unsigned char init_mt9m111[][4] = {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00}, - {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0d, 0x00}, - {BRIDGE, M5602_XB_SENSOR_CTRL, 0x00, 0x00}, - {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00}, {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00}, - {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, - {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, - {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, - {SENSOR, MT9M111_SC_RESET, 0xff, 0xff}, - {SENSOR, MT9M111_SC_RESET, 0xff, 0xde}, - {SENSOR, MT9M111_SC_RESET, 0xff, 0xff}, - {SENSOR, MT9M111_SC_RESET, 0xff, 0xf7}, - {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x01}, - {SENSOR, MT9M111_CP_GLOBAL_CLK_CONTROL, 0x00, - MT9M111_TRISTATE_PIN_IN_STANDBY | - MT9M111_SOC_SOFT_STANDBY}, - - {BRIDGE, M5602_XB_GPIO_EN_H, 0x06, 0x00}, - {BRIDGE, M5602_XB_GPIO_EN_L, 0x00, 0x00}, - {BRIDGE, M5602_XB_I2C_CLK_DIV, 0x0a, 0x00}, - - {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, - {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, - - {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, - {SENSOR, MT9M111_SC_RESET, 0x00, 0x09}, - {SENSOR, MT9M111_SC_RESET, 0x00, 0x29}, - {SENSOR, MT9M111_SC_RESET, 0x00, 0x08}, - {SENSOR, MT9M111_SC_RESET, 0x00, 0x0c}, - {SENSOR, MT9M111_SC_RESET, 0x00, 0x04}, - {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x01}, - {SENSOR, MT9M111_CP_GLOBAL_CLK_CONTROL, 0x00, - MT9M111_TRISTATE_PIN_IN_STANDBY | - MT9M111_SOC_SOFT_STANDBY}, {BRIDGE, M5602_XB_GPIO_EN_H, 0x06, 0x00}, {BRIDGE, M5602_XB_GPIO_EN_L, 0x00, 0x00}, - {BRIDGE, M5602_XB_I2C_CLK_DIV, 0x0a, 0x00}, - - {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, - {SENSOR, MT9M111_SC_RESET, 0x00, 0x05}, - {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, - {SENSOR, MT9M111_SC_RESET, 0x00, 0x29}, - {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, - {SENSOR, MT9M111_SC_RESET, 0x00, 0x08}, - - {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, - {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, - {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, - {SENSOR, MT9M111_SC_RESET, 0x00, 0x09}, - {SENSOR, MT9M111_SC_RESET, 0x00, 0x29}, - {SENSOR, MT9M111_SC_RESET, 0x00, 0x08}, - {SENSOR, MT9M111_SC_RESET, 0x00, 0x0c}, - {SENSOR, MT9M111_SC_RESET, 0x00, 0x04}, - {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x01}, - {SENSOR, MT9M111_CP_GLOBAL_CLK_CONTROL, 0x00, - MT9M111_TRISTATE_PIN_IN_STANDBY | - MT9M111_SOC_SOFT_STANDBY}, - {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, - {SENSOR, MT9M111_SC_RESET, 0x00, 0x05}, - {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, - {SENSOR, MT9M111_SC_RESET, 0x00, 0x29}, - {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, - - {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, - {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, - {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, - {SENSOR, MT9M111_SC_RESET, 0x00, 0x09}, - {SENSOR, MT9M111_SC_RESET, 0x00, 0x29}, - {SENSOR, MT9M111_SC_RESET, 0x00, 0x08}, - {SENSOR, MT9M111_SC_RESET, 0x00, 0x0c}, - {SENSOR, MT9M111_SC_RESET, 0x00, 0x04}, - {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x01}, - {SENSOR, MT9M111_CP_GLOBAL_CLK_CONTROL, 0x00, - MT9M111_TRISTATE_PIN_IN_STANDBY | - MT9M111_SOC_SOFT_STANDBY}, - {BRIDGE, M5602_XB_GPIO_DIR, 0x05, 0x00}, {BRIDGE, M5602_XB_GPIO_DAT, 0x04, 0x00}, - {BRIDGE, M5602_XB_GPIO_EN_H, 0x3e, 0x00}, {BRIDGE, M5602_XB_GPIO_DIR_H, 0x3e, 0x00}, - {BRIDGE, M5602_XB_GPIO_DAT_H, 0x02, 0x00}, - {BRIDGE, M5602_XB_GPIO_EN_L, 0xff, 0x00}, {BRIDGE, M5602_XB_GPIO_DIR_L, 0xff, 0x00}, + {BRIDGE, M5602_XB_GPIO_DAT_H, 0x02, 0x00}, {BRIDGE, M5602_XB_GPIO_DAT_L, 0x00, 0x00}, - {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, - {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, - {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00}, - {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00}, - {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, - {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, {BRIDGE, M5602_XB_GPIO_DIR, 0x07, 0x00}, {BRIDGE, M5602_XB_GPIO_DAT, 0x0b, 0x00}, - {BRIDGE, M5602_XB_GPIO_EN_H, 0x06, 0x00}, - {BRIDGE, M5602_XB_GPIO_EN_L, 0x00, 0x00}, {BRIDGE, M5602_XB_I2C_CLK_DIV, 0x0a, 0x00}, - {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, - {SENSOR, MT9M111_SC_RESET, 0x00, 0x05}, - {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, {SENSOR, MT9M111_SC_RESET, 0x00, 0x29}, {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, {SENSOR, MT9M111_SC_RESET, 0x00, 0x08}, @@ -273,9 +188,9 @@ static const unsigned char init_mt9m111[][4] = {SENSOR, MT9M111_CP_LUMA_CLIP, 0xff, 0x00}, {SENSOR, MT9M111_CP_OUTPUT_FORMAT_CTL2_CONTEXT_A, 0x14, 0x00}, {SENSOR, MT9M111_CP_OUTPUT_FORMAT_CTL2_CONTEXT_B, 0x14, 0x00}, - {SENSOR, 0xcd, 0x00, 0x0e}, {SENSOR, 0xd0, 0x00, 0x40}, + {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x02}, {SENSOR, MT9M111_CC_AUTO_EXPOSURE_PARAMETER_18, 0x00, 0x00}, {SENSOR, MT9M111_CC_AWB_PARAMETER_7, 0xef, 0x03}, @@ -327,6 +242,8 @@ static const unsigned char init_mt9m111[][4] = {SENSOR, MT9M111_SC_R_MODE_CONTEXT_B, 0x01, 0x0f}, /* 271 */ {SENSOR, MT9M111_SC_R_MODE_CONTEXT_A, 0x01, 0x0f}, /* 271 */ {SENSOR, 0x30, 0x04, 0x00}, + /* Set number of blank rows chosen to 400 */ + {SENSOR, MT9M111_SC_SHUTTER_WIDTH, 0x01, 0x90}, {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06, 0x00}, {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, @@ -352,10 +269,6 @@ static const unsigned char init_mt9m111[][4] = {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00}, {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, - - {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, - /* Set number of blank rows chosen to 400 */ - {SENSOR, MT9M111_SC_SHUTTER_WIDTH, 0x01, 0x90}, }; #endif -- cgit v1.2.3 From 3c9086a8f3919fe6df4b73f719de45111bedbdc3 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Sun, 5 Apr 2009 20:36:04 +0200 Subject: gspca - mr97310a: Webcam 093a:010f added. From: Theodore Kilgore Priority: normal Signed-off-by: Theodore Kilgore Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/mr97310a.c | 1 + 1 file changed, 1 insertion(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/mr97310a.c b/linux/drivers/media/video/gspca/mr97310a.c index f9da55b20..301325134 100644 --- a/linux/drivers/media/video/gspca/mr97310a.c +++ b/linux/drivers/media/video/gspca/mr97310a.c @@ -321,6 +321,7 @@ static const struct sd_desc sd_desc = { /* -- module initialisation -- */ static const __devinitdata struct usb_device_id device_table[] = { {USB_DEVICE(0x08ca, 0x0111)}, + {USB_DEVICE(0x093a, 0x010f)}, {} }; MODULE_DEVICE_TABLE(usb, device_table); -- cgit v1.2.3 From 9a1e3bf0799562e60be8d8c254a77d931eca4f81 Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Thu, 9 Apr 2009 15:16:12 +0300 Subject: af9015: add new dvb_usb_device_properties entry for upcoming USB IDs From: Antti Palosaari Add 3rd dvb_usb_device_properties entry for upcoming USB IDs because current entries are full. Priority: normal Signed-off-by: Antti Palosaari --- linux/drivers/media/dvb/dvb-usb/af9015.c | 65 ++++++++++++++++++++++++++++++-- 1 file changed, 61 insertions(+), 4 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/dvb-usb/af9015.c b/linux/drivers/media/dvb/dvb-usb/af9015.c index ceea6676b..ba4ab61eb 100644 --- a/linux/drivers/media/dvb/dvb-usb/af9015.c +++ b/linux/drivers/media/dvb/dvb-usb/af9015.c @@ -40,7 +40,7 @@ DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); static DEFINE_MUTEX(af9015_usb_mutex); static struct af9015_config af9015_config; -static struct dvb_usb_device_properties af9015_properties[2]; +static struct dvb_usb_device_properties af9015_properties[3]; static int af9015_properties_count = ARRAY_SIZE(af9015_properties); static struct af9013_config af9015_af9013_config[] = { @@ -1324,7 +1324,7 @@ static struct dvb_usb_device_properties af9015_properties[] = { .i2c_algo = &af9015_i2c_algo, - .num_device_descs = 9, + .num_device_descs = 9, /* max 9 */ .devices = { { .name = "Afatech AF9015 DVB-T USB2.0 stick", @@ -1429,7 +1429,7 @@ static struct dvb_usb_device_properties af9015_properties[] = { .i2c_algo = &af9015_i2c_algo, - .num_device_descs = 9, + .num_device_descs = 9, /* max 9 */ .devices = { { .name = "Xtensions XD-380", @@ -1481,7 +1481,64 @@ static struct dvb_usb_device_properties af9015_properties[] = { .warm_ids = {NULL}, }, } - } + }, { + .caps = DVB_USB_IS_AN_I2C_ADAPTER, + + .usb_ctrl = DEVICE_SPECIFIC, + .download_firmware = af9015_download_firmware, + .firmware = "dvb-usb-af9015.fw", + .no_reconnect = 1, + + .size_of_priv = sizeof(struct af9015_state), \ + + .num_adapters = 2, + .adapter = { + { + .caps = DVB_USB_ADAP_HAS_PID_FILTER | + DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, + + .pid_filter_count = 32, + .pid_filter = af9015_pid_filter, + .pid_filter_ctrl = af9015_pid_filter_ctrl, + + .frontend_attach = + af9015_af9013_frontend_attach, + .tuner_attach = af9015_tuner_attach, + .stream = { + .type = USB_BULK, + .count = 6, + .endpoint = 0x84, + }, + }, + { + .frontend_attach = + af9015_af9013_frontend_attach, + .tuner_attach = af9015_tuner_attach, + .stream = { + .type = USB_BULK, + .count = 6, + .endpoint = 0x85, + .u = { + .bulk = { + .buffersize = + TS_USB20_MAX_PACKET_SIZE, + } + } + }, + } + }, + + .identify_state = af9015_identify_state, + + .rc_query = af9015_rc_query, + .rc_interval = 150, + + .i2c_algo = &af9015_i2c_algo, + + .num_device_descs = 0, /* max 9 */ + .devices = { + } + }, }; static int af9015_usb_probe(struct usb_interface *intf, -- cgit v1.2.3 From 000a3988dda531d977b79f3b335a41582c4f116f Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Thu, 9 Apr 2009 21:14:18 +0300 Subject: af9015: support for AverMedia AVerTV Volar GPS 805 (A805) From: Antti Palosaari Add USB ID (07ca:a805) for AverMedia AVerTV Volar GPS 805 (A805). Thanks to Chris Brown for reporting and testing. Priority: normal Signed-off-by: Antti Palosaari Tested-by: Chris Brown --- linux/drivers/media/dvb/dvb-usb/af9015.c | 10 ++++++++-- linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h | 1 + 2 files changed, 9 insertions(+), 2 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/dvb-usb/af9015.c b/linux/drivers/media/dvb/dvb-usb/af9015.c index ba4ab61eb..11346263c 100644 --- a/linux/drivers/media/dvb/dvb-usb/af9015.c +++ b/linux/drivers/media/dvb/dvb-usb/af9015.c @@ -1264,7 +1264,8 @@ static struct usb_device_id af9015_usb_table[] = { {USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_395U_2)}, {USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_395U_3)}, {USB_DEVICE(USB_VID_AFATECH, USB_PID_TREKSTOR_DVBT)}, - {USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A850)}, +/* 20 */{USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A850)}, + {USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A805)}, {0}, }; MODULE_DEVICE_TABLE(usb, af9015_usb_table); @@ -1535,8 +1536,13 @@ static struct dvb_usb_device_properties af9015_properties[] = { .i2c_algo = &af9015_i2c_algo, - .num_device_descs = 0, /* max 9 */ + .num_device_descs = 1, /* max 9 */ .devices = { + { + .name = "AverMedia AVerTV Volar GPS 805 (A805)", + .cold_ids = {&af9015_usb_table[21], NULL}, + .warm_ids = {NULL}, + }, } }, }; 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 f506c7411..a25b06825 100644 --- a/linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h +++ b/linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h @@ -171,6 +171,7 @@ #define USB_PID_AVERMEDIA_A309 0xa309 #define USB_PID_AVERMEDIA_A310 0xa310 #define USB_PID_AVERMEDIA_A850 0x850a +#define USB_PID_AVERMEDIA_A805 0xa805 #define USB_PID_TECHNOTREND_CONNECT_S2400 0x3006 #define USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY 0x005a #define USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY_2 0x0081 -- cgit v1.2.3 From 074a4772727768fbe6cebc0c11f14e529a33ff9f Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Thu, 9 Apr 2009 23:16:41 +0300 Subject: af9015: support for Conceptronic USB2.0 DVB-T CTVDIGRCU V3.0 From: Marcel Jueling Add USB ID (1b80:e397) for Conceptronic USB2.0 DVB-T CTVDIGRCU V3.0. Priority: normal Signed-off-by: Marcel Jueling Signed-off-by: Antti Palosaari --- linux/drivers/media/dvb/dvb-usb/af9015.c | 9 ++++++++- linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h | 1 + 2 files changed, 9 insertions(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/dvb-usb/af9015.c b/linux/drivers/media/dvb/dvb-usb/af9015.c index 11346263c..57c678892 100644 --- a/linux/drivers/media/dvb/dvb-usb/af9015.c +++ b/linux/drivers/media/dvb/dvb-usb/af9015.c @@ -1266,6 +1266,7 @@ static struct usb_device_id af9015_usb_table[] = { {USB_DEVICE(USB_VID_AFATECH, USB_PID_TREKSTOR_DVBT)}, /* 20 */{USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A850)}, {USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A805)}, + {USB_DEVICE(USB_VID_KWORLD_2, USB_PID_CONCEPTRONIC_CTVDIGRCU)}, {0}, }; MODULE_DEVICE_TABLE(usb, af9015_usb_table); @@ -1536,13 +1537,19 @@ static struct dvb_usb_device_properties af9015_properties[] = { .i2c_algo = &af9015_i2c_algo, - .num_device_descs = 1, /* max 9 */ + .num_device_descs = 2, /* max 9 */ .devices = { { .name = "AverMedia AVerTV Volar GPS 805 (A805)", .cold_ids = {&af9015_usb_table[21], NULL}, .warm_ids = {NULL}, }, + { + .name = "Conceptronic USB2.0 DVB-T CTVDIGRCU " \ + "V3.0", + .cold_ids = {&af9015_usb_table[22], NULL}, + .warm_ids = {NULL}, + }, } }, }; 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 a25b06825..ca0051272 100644 --- a/linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h +++ b/linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h @@ -80,6 +80,7 @@ #define USB_PID_COMPRO_DVBU2000_UNK_WARM 0x010d #define USB_PID_COMPRO_VIDEOMATE_U500 0x1e78 #define USB_PID_COMPRO_VIDEOMATE_U500_PC 0x1e80 +#define USB_PID_CONCEPTRONIC_CTVDIGRCU 0xe397 #define USB_PID_CONEXANT_D680_DMB 0x86d6 #define USB_PID_DIBCOM_HOOK_DEFAULT 0x0064 #define USB_PID_DIBCOM_HOOK_DEFAULT_REENUM 0x0065 -- cgit v1.2.3 From 70d032c96094e351c2572a042320e406c03766f4 Mon Sep 17 00:00:00 2001 From: Douglas Schilling Landgraf Date: Thu, 9 Apr 2009 18:24:34 -0300 Subject: em28xx: Add EmpireTV board support From: Douglas Schilling Landgraf Added EmpireTV entry. Thanks to Xwang to provide data for this board. Priority: normal Signed-off-by: Douglas Schilling Landgraf --- linux/drivers/media/video/em28xx/em28xx-cards.c | 27 +++++++++++++++++++++++++ linux/drivers/media/video/em28xx/em28xx-dvb.c | 1 + linux/drivers/media/video/em28xx/em28xx.h | 1 + 3 files changed, 29 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 5049dc647..fb83e4f6e 100644 --- a/linux/drivers/media/video/em28xx/em28xx-cards.c +++ b/linux/drivers/media/video/em28xx/em28xx-cards.c @@ -1144,6 +1144,31 @@ struct em28xx_board em28xx_boards[] = { .gpio = default_analog, } }, }, + [EM2880_BOARD_EMPIRE_DUAL_TV] = { + .name = "Empire dual TV", + .tuner_type = TUNER_XC2028, + .tuner_gpio = default_tuner_gpio, + .has_dvb = 1, + .dvb_gpio = default_digital, + .mts_firmware = 1, + .decoder = EM28XX_TVP5150, + .input = { { + .type = EM28XX_VMUX_TELEVISION, + .vmux = TVP5150_COMPOSITE0, + .amux = EM28XX_AMUX_VIDEO, + .gpio = default_analog, + }, { + .type = EM28XX_VMUX_COMPOSITE1, + .vmux = TVP5150_COMPOSITE1, + .amux = EM28XX_AMUX_LINE_IN, + .gpio = default_analog, + }, { + .type = EM28XX_VMUX_SVIDEO, + .vmux = TVP5150_SVIDEO, + .amux = EM28XX_AMUX_LINE_IN, + .gpio = default_analog, + } }, + }, [EM2881_BOARD_DNT_DA2_HYBRID] = { .name = "DNT DA2 Hybrid", .valid = EM28XX_BOARD_NOT_VALIDATED, @@ -1506,6 +1531,7 @@ static struct em28xx_hash_table em28xx_eeprom_hash[] = { {0x6ce05a8f, EM2820_BOARD_PROLINK_PLAYTV_USB2, TUNER_YMEC_TVF_5533MF}, {0x72cc5a8b, EM2820_BOARD_PROLINK_PLAYTV_BOX4_USB2, TUNER_YMEC_TVF_5533MF}, {0x966a0441, EM2880_BOARD_KWORLD_DVB_310U, TUNER_XC2028}, + {0x9567eb1a, EM2880_BOARD_EMPIRE_DUAL_TV, TUNER_XC2028}, }; /* I2C devicelist hash table for devices with generic USB IDs */ @@ -1733,6 +1759,7 @@ static void em28xx_setup_xc3028(struct em28xx *dev, struct xc2028_ctrl *ctl) ctl->mts = em28xx_boards[dev->model].mts_firmware; switch (dev->model) { + case EM2880_BOARD_EMPIRE_DUAL_TV: case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900: ctl->demod = XC3028_FE_ZARLINK456; break; diff --git a/linux/drivers/media/video/em28xx/em28xx-dvb.c b/linux/drivers/media/video/em28xx/em28xx-dvb.c index edafe9bde..dd749442d 100644 --- a/linux/drivers/media/video/em28xx/em28xx-dvb.c +++ b/linux/drivers/media/video/em28xx/em28xx-dvb.c @@ -432,6 +432,7 @@ static int dvb_init(struct em28xx *dev) case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900: case EM2880_BOARD_TERRATEC_HYBRID_XS: case EM2880_BOARD_KWORLD_DVB_310U: + case EM2880_BOARD_EMPIRE_DUAL_TV: dvb->frontend = dvb_attach(zl10353_attach, &em28xx_zl10353_with_xc3028, &dev->i2c_adap); diff --git a/linux/drivers/media/video/em28xx/em28xx.h b/linux/drivers/media/video/em28xx/em28xx.h index a9d0a865f..966a3b924 100644 --- a/linux/drivers/media/video/em28xx/em28xx.h +++ b/linux/drivers/media/video/em28xx/em28xx.h @@ -103,6 +103,7 @@ #define EM2860_BOARD_KAIOMY_TVNPC_U2 63 #define EM2860_BOARD_EASYCAP 64 #define EM2820_BOARD_IODATA_GVMVP_SZ 65 +#define EM2880_BOARD_EMPIRE_DUAL_TV 66 /* Limits minimum and default number of buffers */ #define EM28XX_MIN_BUF 4 -- cgit v1.2.3 From 69f3fd5d5c56529eab9b187f7a58db3dabb12ff3 Mon Sep 17 00:00:00 2001 From: Douglas Schilling Landgraf Date: Thu, 9 Apr 2009 18:27:12 -0300 Subject: em28xx: fix typo em28xx_errdev message From: Filipe Rosset Fix typo usbtransfer->usb transfer on em28xx_errdev message. Priority: normal Signed-off-by: Filipe Rosset Signed-off-by: Douglas Schilling Landgraf --- linux/drivers/media/video/em28xx/em28xx-core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (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 c05f52048..401dc4e39 100644 --- a/linux/drivers/media/video/em28xx/em28xx-core.c +++ b/linux/drivers/media/video/em28xx/em28xx-core.c @@ -947,7 +947,7 @@ int em28xx_init_isoc(struct em28xx *dev, int max_packets, dev->isoc_ctl.transfer_buffer = kzalloc(sizeof(void *)*num_bufs, GFP_KERNEL); if (!dev->isoc_ctl.transfer_buffer) { - em28xx_errdev("cannot allocate memory for usbtransfer\n"); + em28xx_errdev("cannot allocate memory for usb transfer\n"); kfree(dev->isoc_ctl.urb); return -ENOMEM; } -- cgit v1.2.3 From 76116fc7aa5a5d2ace0de81eac3e183a5d40bc33 Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Mon, 13 Apr 2009 20:43:31 -0400 Subject: cx18: Send correct input routing value to external audio multiplexers From: Andy Walls A late v4l2_subdev framework change accidentally sent the audio input routing value to the external multiplexer, instead of the muxer input routing value to the external multiplexer. This change corrects that error. Priority: normal Signed-off-by: Andy Walls --- linux/drivers/media/video/cx18/cx18-audio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/cx18/cx18-audio.c b/linux/drivers/media/video/cx18/cx18-audio.c index 1519e91c6..7a8ad5963 100644 --- a/linux/drivers/media/video/cx18/cx18-audio.c +++ b/linux/drivers/media/video/cx18/cx18-audio.c @@ -44,7 +44,7 @@ int cx18_audio_set_io(struct cx18 *cx) /* handle muxer chips */ v4l2_subdev_call(cx->sd_extmux, audio, s_routing, - in->audio_input, 0, 0); + (u32) in->muxer_input, 0, 0); err = cx18_call_hw_err(cx, cx->card->hw_audio_ctrl, audio, s_routing, in->audio_input, 0, 0); -- cgit v1.2.3 From 82952b23500fff65871d254f64dc6b96eb13785c Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 14 Apr 2009 08:50:00 -0300 Subject: backport arch arm/sh changes that affected v4l From: Mauro Carvalho Chehab kernel-sync: Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/pxa_camera.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/pxa_camera.c b/linux/drivers/media/video/pxa_camera.c index 98825d631..cb4491338 100644 --- a/linux/drivers/media/video/pxa_camera.c +++ b/linux/drivers/media/video/pxa_camera.c @@ -40,7 +40,9 @@ #include #endif #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27) +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30) #include +#endif #include #else #include -- cgit v1.2.3 From a548457acf0e54ce1864d1ec7c3f5fc876568cbe Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 14 Apr 2009 10:13:44 -0300 Subject: backport commit 9137f05f7e72517d44b6b0c15b11b419ecb5d201 From: Mauro Carvalho Chehab Author: Jaswinder Singh Date: Mon Apr 6 14:34:12 2009 -0700 firmware: convert av7110 driver to request_firmware() kernel-sync: Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/ttpci/av7110_hw.c | 35 +++++++++++-------------------- linux/drivers/media/dvb/ttpci/av7110_hw.h | 3 ++- 2 files changed, 14 insertions(+), 24 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/ttpci/av7110_hw.c b/linux/drivers/media/dvb/ttpci/av7110_hw.c index afae0266a..276be4056 100644 --- a/linux/drivers/media/dvb/ttpci/av7110_hw.c +++ b/linux/drivers/media/dvb/ttpci/av7110_hw.c @@ -198,29 +198,10 @@ static int load_dram(struct av7110 *av7110, u32 *data, int len) /* we cannot write av7110 DRAM directly, so load a bootloader into * the DPRAM which implements a simple boot protocol */ -static u8 bootcode[] = { - 0xea, 0x00, 0x00, 0x0e, 0xe1, 0xb0, 0xf0, 0x0e, 0xe2, 0x5e, 0xf0, 0x04, - 0xe2, 0x5e, 0xf0, 0x04, 0xe2, 0x5e, 0xf0, 0x08, 0xe2, 0x5e, 0xf0, 0x04, - 0xe2, 0x5e, 0xf0, 0x04, 0xe2, 0x5e, 0xf0, 0x04, 0x2c, 0x00, 0x00, 0x24, - 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x34, - 0x00, 0x00, 0x00, 0x00, 0xa5, 0xa5, 0x5a, 0x5a, 0x00, 0x1f, 0x15, 0x55, - 0x00, 0x00, 0x00, 0x09, 0xe5, 0x9f, 0xd0, 0x7c, 0xe5, 0x9f, 0x40, 0x74, - 0xe3, 0xa0, 0x00, 0x00, 0xe5, 0x84, 0x00, 0x00, 0xe5, 0x84, 0x00, 0x04, - 0xe5, 0x9f, 0x10, 0x70, 0xe5, 0x9f, 0x20, 0x70, 0xe5, 0x9f, 0x30, 0x64, - 0xe8, 0xb1, 0x1f, 0xe0, 0xe8, 0xa3, 0x1f, 0xe0, 0xe1, 0x51, 0x00, 0x02, - 0xda, 0xff, 0xff, 0xfb, 0xe5, 0x9f, 0xf0, 0x50, 0xe1, 0xd4, 0x10, 0xb0, - 0xe3, 0x51, 0x00, 0x00, 0x0a, 0xff, 0xff, 0xfc, 0xe1, 0xa0, 0x10, 0x0d, - 0xe5, 0x94, 0x30, 0x04, 0xe1, 0xd4, 0x20, 0xb2, 0xe2, 0x82, 0x20, 0x3f, - 0xe1, 0xb0, 0x23, 0x22, 0x03, 0xa0, 0x00, 0x02, 0xe1, 0xc4, 0x00, 0xb0, - 0x0a, 0xff, 0xff, 0xf4, 0xe8, 0xb1, 0x1f, 0xe0, 0xe8, 0xa3, 0x1f, 0xe0, - 0xe8, 0xb1, 0x1f, 0xe0, 0xe8, 0xa3, 0x1f, 0xe0, 0xe2, 0x52, 0x20, 0x01, - 0x1a, 0xff, 0xff, 0xf9, 0xe2, 0x2d, 0xdb, 0x05, 0xea, 0xff, 0xff, 0xec, - 0x2c, 0x00, 0x03, 0xf8, 0x2c, 0x00, 0x04, 0x00, 0x9e, 0x00, 0x08, 0x00, - 0x2c, 0x00, 0x00, 0x74, 0x2c, 0x00, 0x00, 0xc0 -}; - int av7110_bootarm(struct av7110 *av7110) { + const struct firmware *fw; + const char *fw_name = "av7110/bootcode.bin"; struct saa7146_dev *dev = av7110->dev; u32 ret; int i; @@ -261,7 +242,15 @@ int av7110_bootarm(struct av7110 *av7110) //saa7146_setgpio(dev, DEBI_DONE_LINE, SAA7146_GPIO_INPUT); //saa7146_setgpio(dev, 3, SAA7146_GPIO_INPUT); - mwdebi(av7110, DEBISWAB, DPRAM_BASE, bootcode, sizeof(bootcode)); + ret = request_firmware(&fw, fw_name, &dev->pci->dev); + if (ret) { + printk(KERN_ERR "dvb-ttpci: Failed to load firmware \"%s\"\n", + fw_name); + return ret; + } + + mwdebi(av7110, DEBISWAB, DPRAM_BASE, fw->data, fw->size); + release_firmware(fw); iwdebi(av7110, DEBINOSWAP, AV7110_BOOT_STATE, BOOTSTATE_BUFFER_FULL, 2); if (saa7146_wait_for_debi_done(av7110->dev, 1)) { @@ -302,7 +291,7 @@ int av7110_bootarm(struct av7110 *av7110) av7110->arm_ready = 1; return 0; } - +MODULE_FIRMWARE("av7110/bootcode.bin"); /**************************************************************************** * DEBI command polling diff --git a/linux/drivers/media/dvb/ttpci/av7110_hw.h b/linux/drivers/media/dvb/ttpci/av7110_hw.h index ca99e5c1f..1634aba5c 100644 --- a/linux/drivers/media/dvb/ttpci/av7110_hw.h +++ b/linux/drivers/media/dvb/ttpci/av7110_hw.h @@ -390,7 +390,8 @@ static inline void iwdebi(struct av7110 *av7110, u32 config, int addr, u32 val, } /* buffer writes */ -static inline void mwdebi(struct av7110 *av7110, u32 config, int addr, u8 *val, int count) +static inline void mwdebi(struct av7110 *av7110, u32 config, int addr, + const u8 *val, int count) { memcpy(av7110->debi_virt, val, count); av7110_debiwrite(av7110, config, addr, 0, count); -- cgit v1.2.3 From 24f0a7073801c6f55ba324d3141a9bdeee2b5034 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 14 Apr 2009 10:16:40 -0300 Subject: backport commit 4f8d182513690b42b20fb81e487be4cd4729e27c From: Mauro Carvalho Chehab Author: Jaswinder Singh Date: Sun Jun 22 18:24:19 2008 +0530 Remove fdump tool for av7110 firmware There's no point in this, since the user can use the BUILTIN_FIRMWARE option to include arbitrary firmware files directly in the kernel image. Thanks to David Woodhouse for help. kernel-sync: Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/ttpci/Kconfig | 23 ++++-------------- linux/drivers/media/dvb/ttpci/Makefile | 9 ------- linux/drivers/media/dvb/ttpci/av7110.c | 16 ------------- linux/drivers/media/dvb/ttpci/fdump.c | 44 ---------------------------------- 4 files changed, 5 insertions(+), 87 deletions(-) delete mode 100644 linux/drivers/media/dvb/ttpci/fdump.c (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/ttpci/Kconfig b/linux/drivers/media/dvb/ttpci/Kconfig index 772990415..68eb4493f 100644 --- a/linux/drivers/media/dvb/ttpci/Kconfig +++ b/linux/drivers/media/dvb/ttpci/Kconfig @@ -28,25 +28,12 @@ config DVB_AV7110 download/extract it, and then copy it to /usr/lib/hotplug/firmware or /lib/firmware (depending on configuration of firmware hotplug). - Say Y if you own such a card and want to use it. - -config DVB_AV7110_FIRMWARE - bool "Compile AV7110 firmware into the driver" - depends on DVB_AV7110 && !STANDALONE - default y if DVB_AV7110=y - help - The AV7110 firmware is normally loaded by the firmware hotplug manager. - If you want to compile the firmware into the driver you need to say - Y here and provide the correct path of the firmware. You need this - option if you want to compile the whole driver statically into the - kernel. + Alternatively, you can download the file and use the kernel's + EXTRA_FIRMWARE configuration option to build it into your + kernel image by adding the filename to the EXTRA_FIRMWARE + configuration option string. - All other people say N. - -config DVB_AV7110_FIRMWARE_FILE - string "Full pathname of av7110 firmware file" - depends on DVB_AV7110_FIRMWARE - default "/usr/lib/hotplug/firmware/dvb-ttpci-01.fw" + Say Y if you own such a card and want to use it. config DVB_AV7110_OSD bool "AV7110 OSD support" diff --git a/linux/drivers/media/dvb/ttpci/Makefile b/linux/drivers/media/dvb/ttpci/Makefile index 714512372..8a4d5bb20 100644 --- a/linux/drivers/media/dvb/ttpci/Makefile +++ b/linux/drivers/media/dvb/ttpci/Makefile @@ -19,12 +19,3 @@ obj-$(CONFIG_DVB_AV7110) += dvb-ttpci.o EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/ EXTRA_CFLAGS += -Idrivers/media/common/tuners - -hostprogs-y := fdump - -ifeq ($(CONFIG_DVB_AV7110_FIRMWARE),y) -$(obj)/av7110.o: $(obj)/av7110_firm.h - -$(obj)/av7110_firm.h: $(obj)/fdump - $(obj)/fdump $(CONFIG_DVB_AV7110_FIRMWARE_FILE) dvb_ttpci_fw $@ -endif diff --git a/linux/drivers/media/dvb/ttpci/av7110.c b/linux/drivers/media/dvb/ttpci/av7110.c index 841590ed5..1b961db62 100644 --- a/linux/drivers/media/dvb/ttpci/av7110.c +++ b/linux/drivers/media/dvb/ttpci/av7110.c @@ -1521,20 +1521,6 @@ static int check_firmware(struct av7110* av7110) return 0; } -#ifdef CONFIG_DVB_AV7110_FIRMWARE_FILE -#include "av7110_firm.h" -static void put_firmware(struct av7110* av7110) -{ - av7110->bin_fw = NULL; -} - -static inline int get_firmware(struct av7110* av7110) -{ - av7110->bin_fw = dvb_ttpci_fw; - av7110->size_fw = sizeof(dvb_ttpci_fw); - return check_firmware(av7110); -} -#else static void put_firmware(struct av7110* av7110) { vfree(av7110->bin_fw); @@ -1583,8 +1569,6 @@ static int get_firmware(struct av7110* av7110) release_firmware(fw); return ret; } -#endif - static int alps_bsrv2_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params) { diff --git a/linux/drivers/media/dvb/ttpci/fdump.c b/linux/drivers/media/dvb/ttpci/fdump.c deleted file mode 100644 index c90001d35..000000000 --- a/linux/drivers/media/dvb/ttpci/fdump.c +++ /dev/null @@ -1,44 +0,0 @@ -#include -#include -#include -#include -#include - -int main(int argc, char **argv) -{ - unsigned char buf[8]; - unsigned int i, count, bytes = 0; - FILE *fd_in, *fd_out; - - if (argc != 4) { - fprintf(stderr, "\n\tusage: %s \n\n", argv[0]); - return -1; - } - - fd_in = fopen(argv[1], "rb"); - if (fd_in == NULL) { - fprintf(stderr, "firmware file '%s' not found\n", argv[1]); - return -1; - } - - fd_out = fopen(argv[3], "w+"); - if (fd_out == NULL) { - fprintf(stderr, "cannot create output file '%s'\n", argv[3]); - return -1; - } - - fprintf(fd_out, "\n#include \n\nu8 %s [] = {", argv[2]); - - while ((count = fread(buf, 1, 8, fd_in)) > 0) { - fprintf(fd_out, "\n\t"); - for (i = 0; i < count; i++, bytes++) - fprintf(fd_out, "0x%02x, ", buf[i]); - } - - fprintf(fd_out, "\n};\n\n"); - - fclose(fd_in); - fclose(fd_out); - - return 0; -} -- cgit v1.2.3 From d5193c5902aab5c738cd11481b408771c9050d8b Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 14 Apr 2009 10:20:36 -0300 Subject: backport a few language cleanups From: Mauro Carvalho Chehab kernel-sync: Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/common/tuners/Kconfig | 2 +- linux/drivers/media/dvb/frontends/Kconfig | 2 +- linux/drivers/media/video/omap24xxcam.c | 8 ++++---- 3 files changed, 6 insertions(+), 6 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/common/tuners/Kconfig b/linux/drivers/media/common/tuners/Kconfig index 52c3f65b1..607d319ce 100644 --- a/linux/drivers/media/common/tuners/Kconfig +++ b/linux/drivers/media/common/tuners/Kconfig @@ -148,7 +148,7 @@ config MEDIA_TUNER_XC5000 default m if MEDIA_TUNER_CUSTOMISE help A driver for the silicon tuner XC5000 from Xceive. - This device is only used inside a SiP called togther with a + This device is only used inside a SiP called together with a demodulator for now. config MEDIA_TUNER_MXL5005S diff --git a/linux/drivers/media/dvb/frontends/Kconfig b/linux/drivers/media/dvb/frontends/Kconfig index 578b834bf..23e4cffeb 100644 --- a/linux/drivers/media/dvb/frontends/Kconfig +++ b/linux/drivers/media/dvb/frontends/Kconfig @@ -479,7 +479,7 @@ config DVB_TUNER_DIB0070 default m if DVB_FE_CUSTOMISE help A driver for the silicon baseband tuner DiB0070 from DiBcom. - This device is only used inside a SiP called togther with a + This device is only used inside a SiP called together with a demodulator for now. comment "SEC control devices for DVB-S" diff --git a/linux/drivers/media/video/omap24xxcam.c b/linux/drivers/media/video/omap24xxcam.c index d828597ba..5fc4ac0d8 100644 --- a/linux/drivers/media/video/omap24xxcam.c +++ b/linux/drivers/media/video/omap24xxcam.c @@ -80,17 +80,17 @@ static int omap24xxcam_clock_get(struct omap24xxcam_device *cam) { int rval = 0; - cam->fck = clk_get(cam->dev, "cam_fck"); + cam->fck = clk_get(cam->dev, "fck"); if (IS_ERR(cam->fck)) { - dev_err(cam->dev, "can't get cam_fck"); + dev_err(cam->dev, "can't get camera fck"); rval = PTR_ERR(cam->fck); omap24xxcam_clock_put(cam); return rval; } - cam->ick = clk_get(cam->dev, "cam_ick"); + cam->ick = clk_get(cam->dev, "ick"); if (IS_ERR(cam->ick)) { - dev_err(cam->dev, "can't get cam_ick"); + dev_err(cam->dev, "can't get camera ick"); rval = PTR_ERR(cam->ick); omap24xxcam_clock_put(cam); } -- cgit v1.2.3 From 2ec15a3bdd5af9a1ba399e60653b25cd322852e0 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 14 Apr 2009 10:25:59 -0300 Subject: backport commit 284901a90a9e0b812ca3f5f852cbbfb60d10249d From: Mauro Carvalho Chehab Author: Yang Hongyang Date: Mon Apr 6 19:01:15 2009 -0700 dma-mapping: replace all DMA_32BIT_MASK macro with DMA_BIT_MASK(32) Replace all DMA_32BIT_MASK macro with DMA_BIT_MASK(32) Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/dm1105/dm1105.c | 2 +- linux/drivers/media/dvb/pluto2/pluto2.c | 2 +- linux/drivers/media/video/bt8xx/bttv-driver.c | 2 +- linux/drivers/media/video/cx88/cx88-alsa.c | 2 +- linux/drivers/media/video/cx88/cx88-mpeg.c | 2 +- linux/drivers/media/video/cx88/cx88-video.c | 2 +- linux/drivers/media/video/meye.c | 2 +- linux/drivers/media/video/saa7134/saa7134-core.c | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/dm1105/dm1105.c b/linux/drivers/media/dvb/dm1105/dm1105.c index 5d8afefca..ca1048fd4 100644 --- a/linux/drivers/media/dvb/dm1105/dm1105.c +++ b/linux/drivers/media/dvb/dm1105/dm1105.c @@ -694,7 +694,7 @@ static int __devinit dm1105_probe(struct pci_dev *pdev, if (ret < 0) goto err_kfree; - ret = pci_set_dma_mask(pdev, DMA_32BIT_MASK); + ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); if (ret < 0) goto err_pci_disable_device; diff --git a/linux/drivers/media/dvb/pluto2/pluto2.c b/linux/drivers/media/dvb/pluto2/pluto2.c index b27073216..647f6290e 100644 --- a/linux/drivers/media/dvb/pluto2/pluto2.c +++ b/linux/drivers/media/dvb/pluto2/pluto2.c @@ -624,7 +624,7 @@ static int __devinit pluto2_probe(struct pci_dev *pdev, /* enable interrupts */ pci_write_config_dword(pdev, 0x6c, 0x8000); - ret = pci_set_dma_mask(pdev, DMA_32BIT_MASK); + ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); if (ret < 0) goto err_pci_disable_device; diff --git a/linux/drivers/media/video/bt8xx/bttv-driver.c b/linux/drivers/media/video/bt8xx/bttv-driver.c index 958bbd428..622807b54 100644 --- a/linux/drivers/media/video/bt8xx/bttv-driver.c +++ b/linux/drivers/media/video/bt8xx/bttv-driver.c @@ -4354,7 +4354,7 @@ static int __devinit bttv_probe(struct pci_dev *dev, btv->c.nr); return -EIO; } - if (pci_set_dma_mask(dev, DMA_32BIT_MASK)) { + if (pci_set_dma_mask(dev, DMA_BIT_MASK(32))) { printk(KERN_WARNING "bttv%d: No suitable DMA available.\n", btv->c.nr); return -EIO; diff --git a/linux/drivers/media/video/cx88/cx88-alsa.c b/linux/drivers/media/video/cx88/cx88-alsa.c index 1e78faba6..ac9de0094 100644 --- a/linux/drivers/media/video/cx88/cx88-alsa.c +++ b/linux/drivers/media/video/cx88/cx88-alsa.c @@ -802,7 +802,7 @@ static int __devinit snd_cx88_create(struct snd_card *card, return err; } - if (!pci_dma_supported(pci,DMA_32BIT_MASK)) { + if (!pci_dma_supported(pci,DMA_BIT_MASK(32))) { dprintk(0, "%s/1: Oops: no 32bit PCI DMA ???\n",core->name); err = -EIO; cx88_core_put(core,pci); diff --git a/linux/drivers/media/video/cx88/cx88-mpeg.c b/linux/drivers/media/video/cx88/cx88-mpeg.c index 32ed09172..ba083d249 100644 --- a/linux/drivers/media/video/cx88/cx88-mpeg.c +++ b/linux/drivers/media/video/cx88/cx88-mpeg.c @@ -487,7 +487,7 @@ static int cx8802_init_common(struct cx8802_dev *dev) if (pci_enable_device(dev->pci)) return -EIO; pci_set_master(dev->pci); - if (!pci_dma_supported(dev->pci,DMA_32BIT_MASK)) { + if (!pci_dma_supported(dev->pci,DMA_BIT_MASK(32))) { printk("%s/2: Oops: no 32bit PCI DMA ???\n",dev->core->name); return -EIO; } diff --git a/linux/drivers/media/video/cx88/cx88-video.c b/linux/drivers/media/video/cx88/cx88-video.c index 76b16038c..88a326f61 100644 --- a/linux/drivers/media/video/cx88/cx88-video.c +++ b/linux/drivers/media/video/cx88/cx88-video.c @@ -2102,7 +2102,7 @@ static int __devinit cx8800_initdev(struct pci_dev *pci_dev, dev->pci_lat,(unsigned long long)pci_resource_start(pci_dev,0)); pci_set_master(pci_dev); - if (!pci_dma_supported(pci_dev,DMA_32BIT_MASK)) { + if (!pci_dma_supported(pci_dev,DMA_BIT_MASK(32))) { printk("%s/0: Oops: no 32bit PCI DMA ???\n",core->name); err = -EIO; goto fail_core; diff --git a/linux/drivers/media/video/meye.c b/linux/drivers/media/video/meye.c index 11f0b5e0d..1fb7024a5 100644 --- a/linux/drivers/media/video/meye.c +++ b/linux/drivers/media/video/meye.c @@ -118,7 +118,7 @@ static int ptable_alloc(void) memset(meye.mchip_ptable, 0, sizeof(meye.mchip_ptable)); /* give only 32 bit DMA addresses */ - if (dma_set_mask(&meye.mchip_dev->dev, DMA_32BIT_MASK)) + if (dma_set_mask(&meye.mchip_dev->dev, DMA_BIT_MASK(32))) return -1; meye.mchip_ptable_toc = dma_alloc_coherent(&meye.mchip_dev->dev, diff --git a/linux/drivers/media/video/saa7134/saa7134-core.c b/linux/drivers/media/video/saa7134/saa7134-core.c index d6ab4c47c..69a214417 100644 --- a/linux/drivers/media/video/saa7134/saa7134-core.c +++ b/linux/drivers/media/video/saa7134/saa7134-core.c @@ -972,7 +972,7 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev, pci_name(pci_dev), dev->pci_rev, pci_dev->irq, dev->pci_lat,(unsigned long long)pci_resource_start(pci_dev,0)); pci_set_master(pci_dev); - if (!pci_dma_supported(pci_dev, DMA_32BIT_MASK)) { + if (!pci_dma_supported(pci_dev, DMA_BIT_MASK(32))) { printk("%s: Oops: no 32bit PCI DMA ???\n",dev->name); err = -EIO; goto fail1; -- cgit v1.2.3 From 82753c8a0c338f489a20e0554eac589a390ac6bb Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 14 Apr 2009 11:02:14 -0300 Subject: backport commit 758021bfa9ea25c58e62d2f68512628b19502ce7 From: Mauro Carvalho Chehab Author: Takashi Iwai Date: Mon Jan 12 15:17:09 2009 +0100 drivers/media: Convert to snd_card_create() Convert from snd_card_new() to the new snd_card_create() function. While here, backport also cx231xx-audio upstream changes for using snd_card_create(). kernel-sync: Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/cx231xx/cx231xx-audio.c | 7 ++++--- linux/drivers/media/video/cx88/cx88-alsa.c | 7 ++++--- linux/drivers/media/video/em28xx/em28xx-audio.c | 7 ++++--- linux/drivers/media/video/saa7134/saa7134-alsa.c | 8 ++++---- 4 files changed, 16 insertions(+), 13 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/cx231xx/cx231xx-audio.c b/linux/drivers/media/video/cx231xx/cx231xx-audio.c index 0f7fb3ca7..3a060a746 100644 --- a/linux/drivers/media/video/cx231xx/cx231xx-audio.c +++ b/linux/drivers/media/video/cx231xx/cx231xx-audio.c @@ -560,9 +560,10 @@ static int cx231xx_audio_init(struct cx231xx *dev) cx231xx_info("cx231xx-audio.c: probing for cx231xx " "non standard usbaudio\n"); - card = snd_card_new(index[devnr], "Cx231xx Audio", THIS_MODULE, 0); - if (card == NULL) - return -ENOMEM; + err = snd_card_create(index[devnr], "Cx231xx Audio", THIS_MODULE, + 0, &card); + if (err < 0) + return err; spin_lock_init(&adev->slock); err = snd_pcm_new(card, "Cx231xx Audio", 0, 0, 1, &pcm); diff --git a/linux/drivers/media/video/cx88/cx88-alsa.c b/linux/drivers/media/video/cx88/cx88-alsa.c index ac9de0094..077c9f0d7 100644 --- a/linux/drivers/media/video/cx88/cx88-alsa.c +++ b/linux/drivers/media/video/cx88/cx88-alsa.c @@ -867,9 +867,10 @@ static int __devinit cx88_audio_initdev(struct pci_dev *pci, return (-ENOENT); } - card = snd_card_new(index[devno], id[devno], THIS_MODULE, sizeof(snd_cx88_card_t)); - if (!card) - return (-ENOMEM); + err = snd_card_create(index[devno], id[devno], THIS_MODULE, + sizeof(snd_cx88_card_t), &card); + if (err < 0) + return err; card->private_free = snd_cx88_dev_free; diff --git a/linux/drivers/media/video/em28xx/em28xx-audio.c b/linux/drivers/media/video/em28xx/em28xx-audio.c index eb49a1364..089764d42 100644 --- a/linux/drivers/media/video/em28xx/em28xx-audio.c +++ b/linux/drivers/media/video/em28xx/em28xx-audio.c @@ -545,9 +545,10 @@ static int em28xx_audio_init(struct em28xx *dev) printk(KERN_INFO "em28xx-audio.c: Copyright (C) 2006 Markus " "Rechberger\n"); - card = snd_card_new(index[devnr], "Em28xx Audio", THIS_MODULE, 0); - if (card == NULL) - return -ENOMEM; + err = snd_card_create(index[devnr], "Em28xx Audio", THIS_MODULE, 0, + &card); + if (err < 0) + return err; spin_lock_init(&adev->slock); err = snd_pcm_new(card, "Em28xx Audio", 0, 0, 1, &pcm); diff --git a/linux/drivers/media/video/saa7134/saa7134-alsa.c b/linux/drivers/media/video/saa7134/saa7134-alsa.c index eaa03fc07..c09ec3e6f 100644 --- a/linux/drivers/media/video/saa7134/saa7134-alsa.c +++ b/linux/drivers/media/video/saa7134/saa7134-alsa.c @@ -995,10 +995,10 @@ static int alsa_card_saa7134_create(struct saa7134_dev *dev, int devnum) if (!enable[devnum]) return -ENODEV; - card = snd_card_new(index[devnum], id[devnum], THIS_MODULE, sizeof(snd_card_saa7134_t)); - - if (card == NULL) - return -ENOMEM; + err = snd_card_create(index[devnum], id[devnum], THIS_MODULE, + sizeof(snd_card_saa7134_t), &card); + if (err < 0) + return err; strcpy(card->driver, "SAA7134"); -- cgit v1.2.3 From c23903beefd9eaf1b4572041fbe56c64881f8750 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 14 Apr 2009 12:05:32 -0300 Subject: backport commit 99b76233803beab302123d243eea9e41149804f3 From: Mauro Carvalho Chehab kernel-sync: Author: Alexey Dobriyan Date: Wed Mar 25 22:48:06 2009 +0300 proc 2/2: remove struct proc_dir_entry::owner Setting ->owner as done currently (pde->owner = THIS_MODULE) is racy as correctly noted at bug #12454. Someone can lookup entry with NULL ->owner, thus not pinning enything, and release it later resulting in module refcount underflow. We can keep ->owner and supply it at registration time like ->proc_fops and ->data. But this leaves ->owner as easy-manipulative field (just one C assignment) and somebody will forget to unpin previous/pin current module when switching ->owner. ->proc_fops is declared as "const" which should give some thoughts. ->read_proc/->write_proc were just fixed to not require ->owner for protection. rmmod'ed directories will be empty and return "." and ".." -- no harm. And directories with tricky enough readdir and lookup shouldn't be modular. We definitely don't want such modular code. Removing ->owner will also make PDE smaller. So, let's nuke it. Kudos to Jeff Layton for reminding about this, let's say, oversight. http://bugzilla.kernel.org/show_bug.cgi?id=12454 Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/cpia.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/cpia.c b/linux/drivers/media/video/cpia.c index 9baa70fc9..826cf4464 100644 --- a/linux/drivers/media/video/cpia.c +++ b/linux/drivers/media/video/cpia.c @@ -1382,9 +1382,7 @@ static void proc_cpia_create(void) { cpia_proc_root = proc_mkdir("cpia", NULL); - if (cpia_proc_root) - cpia_proc_root->owner = THIS_MODULE; - else + if (!cpia_proc_root) LOG("Unable to initialise /proc/cpia\n"); } -- cgit v1.2.3 From 4c6d792a82b4304ed6ccbfccf9f5ed693a3349e2 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 14 Apr 2009 13:27:46 -0300 Subject: backport commit 32a0f488ce5e8a9a148491f15edc508ab5e8265b From: Mauro Carvalho Chehab Author: Beat Michel Liechti Date: Thu Mar 26 22:36:52 2009 +0100 DVB: firedtv: FireDTV S2 problems with tuning solved Tuning was broken on FireDTV S2 (and presumably FloppyDTV S2) because a wrong opcode was sent. The box only gave "not implemented" responses. Changing the opcode to _TUNE_QPSK2 fixes this for good. kernel-sync: Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/firewire/firedtv-avc.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/firewire/firedtv-avc.c b/linux/drivers/media/dvb/firewire/firedtv-avc.c index 79fab477c..e95a6f094 100644 --- a/linux/drivers/media/dvb/firewire/firedtv-avc.c +++ b/linux/drivers/media/dvb/firewire/firedtv-avc.c @@ -135,6 +135,7 @@ static const char *debug_fcp_opcode(unsigned int opcode, case SFE_VENDOR_OPCODE_REGISTER_REMOTE_CONTROL: return "RegisterRC"; case SFE_VENDOR_OPCODE_LNB_CONTROL: return "LNBControl"; case SFE_VENDOR_OPCODE_TUNE_QPSK: return "TuneQPSK"; + case SFE_VENDOR_OPCODE_TUNE_QPSK2: return "TuneQPSK2"; case SFE_VENDOR_OPCODE_HOST2CA: return "Host2CA"; case SFE_VENDOR_OPCODE_CA2HOST: return "CA2Host"; } @@ -271,7 +272,10 @@ static void avc_tuner_tuneqpsk(struct firedtv *fdtv, c->operand[0] = SFE_VENDOR_DE_COMPANYID_0; c->operand[1] = SFE_VENDOR_DE_COMPANYID_1; c->operand[2] = SFE_VENDOR_DE_COMPANYID_2; - c->operand[3] = SFE_VENDOR_OPCODE_TUNE_QPSK; + if (fdtv->type == FIREDTV_DVB_S2) + c->operand[3] = SFE_VENDOR_OPCODE_TUNE_QPSK2; + else + c->operand[3] = SFE_VENDOR_OPCODE_TUNE_QPSK; c->operand[4] = (params->frequency >> 24) & 0xff; c->operand[5] = (params->frequency >> 16) & 0xff; -- cgit v1.2.3 From 015736e16a8af8a8fe96379031c6a637f4f3a1cb Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 14 Apr 2009 13:29:42 -0300 Subject: backport a few minor cleanups From: Mauro Carvalho Chehab kernel-sync: Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/firewire/firedtv-avc.c | 4 ++-- linux/drivers/media/dvb/frontends/drx397xD.c | 2 +- linux/drivers/media/video/au0828/au0828-video.c | 1 - linux/drivers/media/video/cx88/cx88-dsp.c | 4 ++-- 4 files changed, 5 insertions(+), 6 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/firewire/firedtv-avc.c b/linux/drivers/media/dvb/firewire/firedtv-avc.c index e95a6f094..620fa2c65 100644 --- a/linux/drivers/media/dvb/firewire/firedtv-avc.c +++ b/linux/drivers/media/dvb/firewire/firedtv-avc.c @@ -115,7 +115,7 @@ static const char *debug_fcp_ctype(unsigned int ctype) } static const char *debug_fcp_opcode(unsigned int opcode, - const u8 *data, size_t length) + const u8 *data, int length) { switch (opcode) { case AVC_OPCODE_VENDOR: break; @@ -142,7 +142,7 @@ static const char *debug_fcp_opcode(unsigned int opcode, return "Vendor"; } -static void debug_fcp(const u8 *data, size_t length) +static void debug_fcp(const u8 *data, int length) { unsigned int subunit_type, subunit_id, op; const char *prefix = data[0] > 7 ? "FCP <- " : "FCP -> "; diff --git a/linux/drivers/media/dvb/frontends/drx397xD.c b/linux/drivers/media/dvb/frontends/drx397xD.c index 6b3927e8b..0bdb933d0 100644 --- a/linux/drivers/media/dvb/frontends/drx397xD.c +++ b/linux/drivers/media/dvb/frontends/drx397xD.c @@ -75,7 +75,7 @@ static struct { } fw[] = { #define _FW_ENTRY(a, b, c) { \ .name = a, \ - .file = 0, \ + .file = NULL, \ .lock = __RW_LOCK_UNLOCKED(fw[c].lock), \ .refcnt = 0, \ .data = { } } diff --git a/linux/drivers/media/video/au0828/au0828-video.c b/linux/drivers/media/video/au0828/au0828-video.c index a19d7ba10..8bc0f0481 100644 --- a/linux/drivers/media/video/au0828/au0828-video.c +++ b/linux/drivers/media/video/au0828/au0828-video.c @@ -33,7 +33,6 @@ #include #include #include -#include #include #include #include diff --git a/linux/drivers/media/video/cx88/cx88-dsp.c b/linux/drivers/media/video/cx88/cx88-dsp.c index 4699055f2..dfe2cfce4 100644 --- a/linux/drivers/media/video/cx88/cx88-dsp.c +++ b/linux/drivers/media/video/cx88/cx88-dsp.c @@ -111,8 +111,8 @@ static u32 int_goertzel(s16 x[], u32 N, u32 freq) s_prev = s; } - tmp = (s64)s_prev2*s_prev2 + (s64)s_prev*s_prev - - (s64)coeff*s_prev2*s_prev/32768; + tmp = (s64)s_prev2 * s_prev2 + (s64)s_prev * s_prev - + (s64)coeff * s_prev2 * s_prev / 32768; /* XXX: N must be low enough so that N*N fits in s32. * Else we need two divisions. */ -- cgit v1.2.3 From 34ef7f10c4a258874ea1b35c55c4899cf26bc262 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 14 Apr 2009 13:38:38 -0300 Subject: backport commit 74ca11c2056d01d9ebb3615cd781a148450c3c82 From: Mauro Carvalho Chehab kernel-sync: Author: Bastien Nocera Date: Sat Jan 10 23:44:22 2009 -0800 Input: uvc - the button on the camera is KEY_CAMERA Cameras should generate KEY_CAMERA, not BTN_0. Also call input_sync() on the device once the button has been pressed. CC: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/uvc/uvc_status.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/uvc/uvc_status.c b/linux/drivers/media/video/uvc/uvc_status.c index 4f4171fa8..1e1bda413 100644 --- a/linux/drivers/media/video/uvc/uvc_status.c +++ b/linux/drivers/media/video/uvc/uvc_status.c @@ -47,8 +47,8 @@ static int uvc_input_init(struct uvc_device *dev) input->cdev.dev = &dev->intf->dev; #endif - set_bit(EV_KEY, input->evbit); - set_bit(BTN_0, input->keybit); + __set_bit(EV_KEY, input->evbit); + __set_bit(KEY_CAMERA, input->keybit); if ((ret = input_register_device(input)) < 0) goto error; @@ -70,8 +70,10 @@ static void uvc_input_cleanup(struct uvc_device *dev) static void uvc_input_report_key(struct uvc_device *dev, unsigned int code, int value) { - if (dev->input) + if (dev->input) { input_report_key(dev->input, code, value); + input_sync(dev->input); + } } #else @@ -96,7 +98,7 @@ static void uvc_event_streaming(struct uvc_device *dev, __u8 *data, int len) return; uvc_trace(UVC_TRACE_STATUS, "Button (intf %u) %s len %d\n", data[1], data[3] ? "pressed" : "released", len); - uvc_input_report_key(dev, BTN_0, data[3]); + uvc_input_report_key(dev, KEY_CAMERA, data[3]); } else { uvc_trace(UVC_TRACE_STATUS, "Stream %u error event %02x %02x " "len %d.\n", data[1], data[2], data[3], len); -- cgit v1.2.3 From 138c81cd1bac037cd7a973fa84e915e0c3ecc59a Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 14 Apr 2009 15:50:33 -0700 Subject: drivers/media/video/saa5249.c: fix use-after-free and leak From: Dan Carpenter I moved the kfree() down a couple lines. t->vdev is going to be in freed memory so there is no point setting it to NULL. I added a kfree(t) on a different error path. Signed-off-by: Dan Carpenter Signed-off-by: Andrew Morton Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/saa5249.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/saa5249.c b/linux/drivers/media/video/saa5249.c index e5643b2b6..2d9d7d7fd 100644 --- a/linux/drivers/media/video/saa5249.c +++ b/linux/drivers/media/video/saa5249.c @@ -604,6 +604,7 @@ static int saa5249_probe(struct i2c_client *client, /* Now create a video4linux device */ t->vdev = video_device_alloc(); if (t->vdev == NULL) { + kfree(t); kfree(client); return -ENOMEM; } @@ -623,9 +624,8 @@ static int saa5249_probe(struct i2c_client *client, /* Register it */ err = video_register_device(t->vdev, VFL_TYPE_VTX, -1); if (err < 0) { - kfree(t); video_device_release(t->vdev); - t->vdev = NULL; + kfree(t); return err; } return 0; -- cgit v1.2.3 From 57c7a88fdcaf872957f6390c267ad5d1f43d4862 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 14 Apr 2009 15:51:30 -0700 Subject: drivers/media/video/saa5246a.c: fix use-after-free From: Dan Carpenter I lowered the kfree(t) down a couple lines and removed the superflous "t->vdev = NULL;" Signed-off-by: Dan Carpenter Signed-off-by: Andrew Morton Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/saa5246a.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/saa5246a.c b/linux/drivers/media/video/saa5246a.c index a5e9a8c2e..1b19a72cc 100644 --- a/linux/drivers/media/video/saa5246a.c +++ b/linux/drivers/media/video/saa5246a.c @@ -1098,9 +1098,8 @@ static int saa5246a_probe(struct i2c_client *client, /* Register it */ err = video_register_device(t->vdev, VFL_TYPE_VTX, -1); if (err < 0) { - kfree(t); video_device_release(t->vdev); - t->vdev = NULL; + kfree(t); return err; } return 0; -- cgit v1.2.3 From 28801b0a659f3572bb85b14275bd6f42cc7cca24 Mon Sep 17 00:00:00 2001 From: Erik Andr?n Date: Tue, 13 Jan 2009 07:46:24 +0100 Subject: gspca - m5602-po1030: Remove redundant init sequences From: Erik Andr?n Priority: normal Signed-off-by: Erik Andr?n --- .../drivers/media/video/gspca/m5602/m5602_po1030.h | 48 +--------------------- 1 file changed, 2 insertions(+), 46 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/m5602/m5602_po1030.h b/linux/drivers/media/video/gspca/m5602/m5602_po1030.h index b70879fdd..3ecacf0ed 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_po1030.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_po1030.h @@ -170,55 +170,21 @@ static const unsigned char preinit_po1030[][3] = {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00}, {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0}, {BRIDGE, M5602_XB_ADC_CTRL, 0xc0}, - {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0d}, {BRIDGE, M5602_XB_SENSOR_CTRL, 0x00}, - {BRIDGE, M5602_XB_ADC_CTRL, 0xc0}, {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0c}, - - {SENSOR, PO1030_AUTOCTRL2, PO1030_SENSOR_RESET | (1 << 2)}, - + {BRIDGE, M5602_XB_ADC_CTRL, 0xc0}, {BRIDGE, M5602_XB_GPIO_DIR, 0x05}, {BRIDGE, M5602_XB_GPIO_DAT, 0x04}, {BRIDGE, M5602_XB_GPIO_EN_H, 0x06}, {BRIDGE, M5602_XB_GPIO_DIR_H, 0x06}, {BRIDGE, M5602_XB_GPIO_DAT_H, 0x02}, - {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x04}, - {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0}, - {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06}, - {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0}, - {BRIDGE, M5602_XB_ADC_CTRL, 0xc0}, - {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0c}, - {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81}, - {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82}, - {BRIDGE, M5602_XB_SIG_INI, 0x01}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x02}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x01}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0xec}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, - {BRIDGE, M5602_XB_SIG_INI, 0x00}, - {BRIDGE, M5602_XB_SIG_INI, 0x02}, - {BRIDGE, M5602_XB_HSYNC_PARA, 0x00}, - {BRIDGE, M5602_XB_HSYNC_PARA, 0x00}, - {BRIDGE, M5602_XB_HSYNC_PARA, 0x02}, - {BRIDGE, M5602_XB_HSYNC_PARA, 0x87}, - {BRIDGE, M5602_XB_SIG_INI, 0x00}, {SENSOR, PO1030_AUTOCTRL2, PO1030_SENSOR_RESET | (1 << 2)}, - {BRIDGE, M5602_XB_GPIO_DIR, 0x05}, - {BRIDGE, M5602_XB_GPIO_DAT, 0x04}, - {BRIDGE, M5602_XB_GPIO_EN_H, 0x06}, - {BRIDGE, M5602_XB_GPIO_DIR_H, 0x06}, - {BRIDGE, M5602_XB_GPIO_DAT_H, 0x02}, {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x04}, {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0}, {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00}, {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0}, - {BRIDGE, M5602_XB_ADC_CTRL, 0xc0}, {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0c}, {BRIDGE, M5602_XB_GPIO_DIR, 0x05}, {BRIDGE, M5602_XB_GPIO_DAT, 0x00} @@ -228,36 +194,26 @@ static const unsigned char init_po1030[][3] = { {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02}, {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0}, - /*sequence 1*/ {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00}, {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0}, {BRIDGE, M5602_XB_ADC_CTRL, 0xc0}, - {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0d}, - {BRIDGE, M5602_XB_SENSOR_CTRL, 0x00}, - {BRIDGE, M5602_XB_ADC_CTRL, 0xc0}, {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0c}, - /*end of sequence 1*/ - /*sequence 2 stop */ {SENSOR, PO1030_AUTOCTRL2, PO1030_SENSOR_RESET | (1 << 2)}, {BRIDGE, M5602_XB_GPIO_DIR, 0x05}, {BRIDGE, M5602_XB_GPIO_DAT, 0x04}, {BRIDGE, M5602_XB_GPIO_EN_H, 0x06}, + {BRIDGE, M5602_XB_GPIO_EN_L, 0x00}, {BRIDGE, M5602_XB_GPIO_DIR_H, 0x06}, {BRIDGE, M5602_XB_GPIO_DAT_H, 0x02}, {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x04}, {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0}, - /*end of sequence 2 stop */ - {BRIDGE, M5602_XB_GPIO_DIR, 0x05}, {BRIDGE, M5602_XB_GPIO_DAT, 0x00}, - {BRIDGE, M5602_XB_GPIO_EN_H, 0x06}, - {BRIDGE, M5602_XB_GPIO_EN_L, 0x00}, {SENSOR, PO1030_AUTOCTRL2, 0x04}, - }; static const unsigned char start_po1030[][3] = -- cgit v1.2.3 From fee49c6d61fd792a28607edfc4b1a59136b7425c Mon Sep 17 00:00:00 2001 From: Erik Andr?n Date: Tue, 13 Jan 2009 07:57:57 +0100 Subject: gspca - m5602-ov9650: Add auto exposure ctrl From: Erik Andr?n Priority: normal Signed-off-by: Erik Andr?n --- .../drivers/media/video/gspca/m5602/m5602_ov9650.c | 57 ++++++++++++++++++++-- 1 file changed, 54 insertions(+), 3 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c index be59fe7af..d6a666b86 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c @@ -36,6 +36,8 @@ static int ov9650_set_auto_white_balance(struct gspca_dev *gspca_dev, __s32 val); static int ov9650_get_auto_gain(struct gspca_dev *gspca_dev, __s32 *val); static int ov9650_set_auto_gain(struct gspca_dev *gspca_dev, __s32 val); +static int ov9650_get_auto_exposure(struct gspca_dev *gspca_dev, __s32 *val); +static int ov9650_set_auto_exposure(struct gspca_dev *gspca_dev, __s32 val); /* Vertically and horizontally flips the image if matched, needed for machines where the sensor is mounted upside down */ @@ -203,7 +205,22 @@ const static struct ctrl ov9650_ctrls[] = { }, .set = ov9650_set_auto_gain, .get = ov9650_get_auto_gain + }, +#define AUTO_EXPOSURE_IDX 8 + { + { + .id = V4L2_CID_EXPOSURE_AUTO, + .type = V4L2_CTRL_TYPE_BOOLEAN, + .name = "auto exposure", + .minimum = 0, + .maximum = 1, + .step = 1, + .default_value = 1 + }, + .set = ov9650_set_auto_exposure, + .get = ov9650_get_auto_exposure } + }; static struct v4l2_pix_format ov9650_modes[] = { @@ -358,13 +375,18 @@ int ov9650_init(struct sd *sd) if (err < 0) return err; + err = ov9650_set_auto_exposure(&sd->gspca_dev, + sensor_settings[AUTO_EXPOSURE_IDX]); + if (err < 0) + return err; + err = ov9650_set_auto_white_balance(&sd->gspca_dev, sensor_settings[AUTO_WHITE_BALANCE_IDX]); if (err < 0) return err; err = ov9650_set_auto_gain(&sd->gspca_dev, - sensor_settings[AUTO_GAIN_CTRL_IDX]); + sensor_settings[AUTO_GAIN_CTRL_IDX]); return err; } @@ -701,6 +723,36 @@ static int ov9650_set_vflip(struct gspca_dev *gspca_dev, __s32 val) return err; } +static int ov9650_get_auto_exposure(struct gspca_dev *gspca_dev, __s32 *val) +{ + struct sd *sd = (struct sd *) gspca_dev; + s32 *sensor_settings = sd->sensor_priv; + + *val = sensor_settings[AUTO_EXPOSURE_IDX]; + PDEBUG(D_V4L2, "Read auto exposure control %d", *val); + return 0; +} + +static int ov9650_set_auto_exposure(struct gspca_dev *gspca_dev, + __s32 val) +{ + int err; + u8 i2c_data; + struct sd *sd = (struct sd *) gspca_dev; + s32 *sensor_settings = sd->sensor_priv; + + PDEBUG(D_V4L2, "Set auto exposure control to %d", val); + + sensor_settings[AUTO_EXPOSURE_IDX] = val; + err = m5602_read_sensor(sd, OV9650_COM8, &i2c_data, 1); + if (err < 0) + return err; + + i2c_data = ((i2c_data & 0xfe) | ((val & 0x01) << 0)); + + return m5602_write_sensor(sd, OV9650_COM8, &i2c_data, 1); +} + static int ov9650_get_auto_white_balance(struct gspca_dev *gspca_dev, __s32 *val) { @@ -757,9 +809,8 @@ static int ov9650_set_auto_gain(struct gspca_dev *gspca_dev, __s32 val) return err; i2c_data = ((i2c_data & 0xfb) | ((val & 0x01) << 2)); - err = m5602_write_sensor(sd, OV9650_COM8, &i2c_data, 1); - return err; + return m5602_write_sensor(sd, OV9650_COM8, &i2c_data, 1); } static void ov9650_dump_registers(struct sd *sd) -- cgit v1.2.3 From ea1a5784b0f9edacdb25b4ab26dde75d86b6bb1f Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 10 Mar 2009 16:02:07 -0400 Subject: saa7134: fix typo in product name From: Michael Krufky replace occurances of "HVR1150" with "HVR1120" - this was a typo. Priority: normal Signed-off-by: Michael Krufky --- linux/drivers/media/video/saa7134/saa7134-cards.c | 20 ++++++++++---------- linux/drivers/media/video/saa7134/saa7134.h | 2 +- 2 files changed, 11 insertions(+), 11 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/saa7134/saa7134-cards.c b/linux/drivers/media/video/saa7134/saa7134-cards.c index 725c05f9e..09697c0f1 100644 --- a/linux/drivers/media/video/saa7134/saa7134-cards.c +++ b/linux/drivers/media/video/saa7134/saa7134-cards.c @@ -3331,8 +3331,8 @@ struct saa7134_board saa7134_boards[] = { .gpio = 0x0200100, }, }, - [SAA7134_BOARD_HAUPPAUGE_HVR1150] = { - .name = "Hauppauge WinTV-HVR1150", + [SAA7134_BOARD_HAUPPAUGE_HVR1120] = { + .name = "Hauppauge WinTV-HVR1120", .audio_clock = 0x00187de7, .tuner_type = TUNER_PHILIPS_TDA8290, .radio_type = UNSET, @@ -5505,7 +5505,7 @@ struct pci_device_id saa7134_pci_tbl[] = { .device = PCI_DEVICE_ID_PHILIPS_SAA7133, .subvendor = 0x0070, .subdevice = 0x6706, - .driver_data = SAA7134_BOARD_HAUPPAUGE_HVR1150, + .driver_data = SAA7134_BOARD_HAUPPAUGE_HVR1120, },{ .vendor = PCI_VENDOR_ID_PHILIPS, .device = PCI_DEVICE_ID_PHILIPS_SAA7133, @@ -5517,7 +5517,7 @@ struct pci_device_id saa7134_pci_tbl[] = { .device = PCI_DEVICE_ID_PHILIPS_SAA7133, .subvendor = 0x0070, .subdevice = 0x6708, - .driver_data = SAA7134_BOARD_HAUPPAUGE_HVR1150, + .driver_data = SAA7134_BOARD_HAUPPAUGE_HVR1120, },{ .vendor = PCI_VENDOR_ID_PHILIPS, .device = PCI_DEVICE_ID_PHILIPS_SAA7133, @@ -6057,7 +6057,7 @@ static int saa7134_tda8290_18271_callback(struct saa7134_dev *dev, switch (command) { case TDA18271_CALLBACK_CMD_AGC_ENABLE: /* 0 */ switch (dev->board) { - case SAA7134_BOARD_HAUPPAUGE_HVR1150: + case SAA7134_BOARD_HAUPPAUGE_HVR1120: case SAA7134_BOARD_HAUPPAUGE_HVR1110R3: ret = saa7134_tda18271_hvr11x0_toggle_agc(dev, arg); break; @@ -6078,7 +6078,7 @@ static int saa7134_tda8290_callback(struct saa7134_dev *dev, int ret; switch (dev->board) { - case SAA7134_BOARD_HAUPPAUGE_HVR1150: + case SAA7134_BOARD_HAUPPAUGE_HVR1120: case SAA7134_BOARD_HAUPPAUGE_HVR1110R3: /* tda8290 + tda18271 */ ret = saa7134_tda8290_18271_callback(dev, command, arg); @@ -6125,7 +6125,7 @@ static void hauppauge_eeprom(struct saa7134_dev *dev, u8 *eeprom_data) switch (tv.model) { case 67019: /* WinTV-HVR1110 (Retail, IR Blaster, hybrid, FM, SVid/Comp, 3.5mm audio in) */ case 67109: /* WinTV-HVR1000 (Retail, IR Receive, analog, no FM, SVid/Comp, 3.5mm audio in) */ - case 67201: /* WinTV-HVR1150 (Retail, IR Receive, hybrid, FM, SVid/Comp, 3.5mm audio in) */ + case 67201: /* WinTV-HVR1120 (Retail, IR Receive, hybrid, FM, SVid/Comp, 3.5mm audio in) */ case 67301: /* WinTV-HVR1000 (Retail, IR Receive, analog, no FM, SVid/Comp, 3.5mm audio in) */ case 67209: /* WinTV-HVR1110 (Retail, IR Receive, hybrid, FM, SVid/Comp, 3.5mm audio in) */ case 67559: /* WinTV-HVR1110 (OEM, no IR, hybrid, FM, SVid/Comp, RCA aud) */ @@ -6133,7 +6133,7 @@ static void hauppauge_eeprom(struct saa7134_dev *dev, u8 *eeprom_data) case 67579: /* WinTV-HVR1110 (OEM, no IR, hybrid, no FM) */ case 67589: /* WinTV-HVR1110 (OEM, no IR, hybrid, no FM, SVid/Comp, RCA aud) */ case 67599: /* WinTV-HVR1110 (OEM, no IR, hybrid, no FM, SVid/Comp, RCA aud) */ - case 67651: /* WinTV-HVR1150 (OEM, no IR, hybrid, FM, SVid/Comp, RCA aud) */ + case 67651: /* WinTV-HVR1120 (OEM, no IR, hybrid, FM, SVid/Comp, RCA aud) */ case 67659: /* WinTV-HVR1110 (OEM, no IR, hybrid, FM, SVid/Comp, RCA aud) */ break; default: @@ -6315,7 +6315,7 @@ int saa7134_board_init1(struct saa7134_dev *dev) saa_writeb (SAA7134_PRODUCTION_TEST_MODE, 0x00); break; - case SAA7134_BOARD_HAUPPAUGE_HVR1150: + case SAA7134_BOARD_HAUPPAUGE_HVR1120: case SAA7134_BOARD_HAUPPAUGE_HVR1110R3: /* GPIO 26 high for digital, low for analog */ saa7134_set_gpio(dev, 26, 0); @@ -6577,7 +6577,7 @@ int saa7134_board_init2(struct saa7134_dev *dev) dev->name, saa7134_boards[dev->board].name); } break; - case SAA7134_BOARD_HAUPPAUGE_HVR1150: + case SAA7134_BOARD_HAUPPAUGE_HVR1120: case SAA7134_BOARD_HAUPPAUGE_HVR1110R3: hauppauge_eeprom(dev, dev->eedata+0x80); break; diff --git a/linux/drivers/media/video/saa7134/saa7134.h b/linux/drivers/media/video/saa7134/saa7134.h index 0e45c0931..b21679a71 100644 --- a/linux/drivers/media/video/saa7134/saa7134.h +++ b/linux/drivers/media/video/saa7134/saa7134.h @@ -279,7 +279,7 @@ struct saa7134_format { #define SAA7134_BOARD_ASUSTeK_TIGER 152 #define SAA7134_BOARD_KWORLD_PLUS_TV_ANALOG 153 #define SAA7134_BOARD_AVERMEDIA_GO_007_FM_PLUS 154 -#define SAA7134_BOARD_HAUPPAUGE_HVR1150 155 +#define SAA7134_BOARD_HAUPPAUGE_HVR1120 155 #define SAA7134_BOARD_HAUPPAUGE_HVR1110R3 156 #define SAA7134_MAXBOARDS 32 -- cgit v1.2.3 From da20a75e939aeba2dd14cef84e0de195daaff4ac Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 13 Jan 2009 02:03:26 -0500 Subject: saa7134: enable serial transport streaming interface From: Michael Krufky Priority: normal Signed-off-by: Michael Krufky --- linux/drivers/media/video/saa7134/saa7134-ts.c | 15 +++++++++++++-- linux/drivers/media/video/saa7134/saa7134.h | 6 ++++++ 2 files changed, 19 insertions(+), 2 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/saa7134/saa7134-ts.c b/linux/drivers/media/video/saa7134/saa7134-ts.c index ef55a59f0..cc8b923af 100644 --- a/linux/drivers/media/video/saa7134/saa7134-ts.c +++ b/linux/drivers/media/video/saa7134/saa7134-ts.c @@ -79,8 +79,19 @@ static int buffer_activate(struct saa7134_dev *dev, saa_writeb(SAA7134_TS_SERIAL1, 0x00); /* Start TS stream */ - saa_writeb(SAA7134_TS_SERIAL0, 0x40); - saa_writeb(SAA7134_TS_PARALLEL, 0xEC); + switch (saa7134_boards[dev->board].ts_type) { + case SAA7134_MPEG_TS_PARALLEL: + saa_writeb(SAA7134_TS_SERIAL0, 0x40); + saa_writeb(SAA7134_TS_PARALLEL, 0xec); + break; + case SAA7134_MPEG_TS_SERIAL: + saa_writeb(SAA7134_TS_SERIAL0, 0xd8); + saa_writeb(SAA7134_TS_PARALLEL, 0x6c); + saa_writeb(SAA7134_TS_PARALLEL_SERIAL, 0xbc); + saa_writeb(SAA7134_TS_SERIAL1, 0x02); + break; + } + dev->ts_state = SAA7134_TS_STARTED; } diff --git a/linux/drivers/media/video/saa7134/saa7134.h b/linux/drivers/media/video/saa7134/saa7134.h index b21679a71..d2b29ed9e 100644 --- a/linux/drivers/media/video/saa7134/saa7134.h +++ b/linux/drivers/media/video/saa7134/saa7134.h @@ -313,6 +313,11 @@ enum saa7134_mpeg_type { SAA7134_MPEG_DVB, }; +enum saa7134_mpeg_ts_type { + SAA7134_MPEG_TS_PARALLEL = 0, + SAA7134_MPEG_TS_SERIAL, +}; + struct saa7134_board { char *name; unsigned int audio_clock; @@ -335,6 +340,7 @@ struct saa7134_board { /* peripheral I/O */ enum saa7134_video_out video_out; enum saa7134_mpeg_type mpeg; + enum saa7134_mpeg_ts_type ts_type; unsigned int vid_port_opts; }; -- cgit v1.2.3 From 57f11b4d55f26d34f0e66cc7e84e4e63dc8c80bf Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 13 Jan 2009 02:40:36 -0500 Subject: add support for LG Electronics LGDT3305 ATSC/QAM-B Demodulator From: Michael Krufky Priority: normal Signed-off-by: Michael Krufky --- linux/drivers/media/dvb/frontends/Kconfig | 8 + linux/drivers/media/dvb/frontends/Makefile | 1 + linux/drivers/media/dvb/frontends/lgdt3305.c | 1115 ++++++++++++++++++++++++++ linux/drivers/media/dvb/frontends/lgdt3305.h | 85 ++ 4 files changed, 1209 insertions(+) create mode 100644 linux/drivers/media/dvb/frontends/lgdt3305.c create mode 100644 linux/drivers/media/dvb/frontends/lgdt3305.h (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/frontends/Kconfig b/linux/drivers/media/dvb/frontends/Kconfig index 2887d3398..5c78f6329 100644 --- a/linux/drivers/media/dvb/frontends/Kconfig +++ b/linux/drivers/media/dvb/frontends/Kconfig @@ -419,6 +419,14 @@ config DVB_LGDT3304 An ATSC 8VSB and QAM64/256 tuner module. Say Y when you want to support this frontend. +config DVB_LGDT3305 + tristate "LG Electronics LGDT3305 based" + depends on DVB_CORE && I2C + default m if DVB_FE_CUSTOMISE + help + An ATSC 8VSB and QAM64/256 tuner module. Say Y when you want + to support this frontend. + config DVB_S5H1409 tristate "Samsung S5H1409 based" depends on DVB_CORE && I2C diff --git a/linux/drivers/media/dvb/frontends/Makefile b/linux/drivers/media/dvb/frontends/Makefile index 1e3866b2f..2a250399b 100644 --- a/linux/drivers/media/dvb/frontends/Makefile +++ b/linux/drivers/media/dvb/frontends/Makefile @@ -43,6 +43,7 @@ obj-$(CONFIG_DVB_BCM3510) += bcm3510.o obj-$(CONFIG_DVB_S5H1420) += s5h1420.o obj-$(CONFIG_DVB_LGDT330X) += lgdt330x.o obj-$(CONFIG_DVB_LGDT3304) += lgdt3304.o +obj-$(CONFIG_DVB_LGDT3305) += lgdt3305.o obj-$(CONFIG_DVB_CX24123) += cx24123.o obj-$(CONFIG_DVB_LNBP21) += lnbp21.o obj-$(CONFIG_DVB_ISL6405) += isl6405.o diff --git a/linux/drivers/media/dvb/frontends/lgdt3305.c b/linux/drivers/media/dvb/frontends/lgdt3305.c new file mode 100644 index 000000000..aeb34e924 --- /dev/null +++ b/linux/drivers/media/dvb/frontends/lgdt3305.c @@ -0,0 +1,1115 @@ +/* + * Support for LGDT3305 - VSB/QAM + * + * Copyright (C) 2008, 2009 Michael Krufky + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include "compat.h" +#include +#include "dvb_math.h" +#include "lgdt3305.h" + +static int debug; +module_param(debug, int, 0644); +MODULE_PARM_DESC(debug, "set debug level (info=1, reg=2 (or-able))"); + +#define DBG_INFO 1 +#define DBG_REG 2 + +#define lg_printk(kern, fmt, arg...) \ + printk(kern "%s: " fmt, __func__, ##arg) + +#define lg_info(fmt, arg...) printk(KERN_INFO "lgdt3305: " fmt, ##arg) +#define lg_warn(fmt, arg...) lg_printk(KERN_WARNING, fmt, ##arg) +#define lg_err(fmt, arg...) lg_printk(KERN_ERR, fmt, ##arg) +#define lg_dbg(fmt, arg...) if (debug & DBG_INFO) \ + lg_printk(KERN_DEBUG, fmt, ##arg) +#define lg_reg(fmt, arg...) if (debug & DBG_REG) \ + lg_printk(KERN_DEBUG, fmt, ##arg) + +#define lg_fail(ret) \ +({ \ + int __ret; \ + __ret = (ret < 0); \ + if (__ret) \ + lg_err("error %d on line %d\n", ret, __LINE__); \ + __ret; \ +}) + +struct lgdt3305_state { + struct i2c_adapter *i2c_adap; + const struct lgdt3305_config *cfg; + + struct dvb_frontend frontend; + + fe_modulation_t current_modulation; + u32 current_frequency; + u32 snr; +}; + +/* ------------------------------------------------------------------------ */ + +#define LGDT3305_GEN_CTRL_1 0x0000 +#define LGDT3305_GEN_CTRL_2 0x0001 +#define LGDT3305_GEN_CTRL_3 0x0002 +#define LGDT3305_GEN_STATUS 0x0003 +#define LGDT3305_GEN_CONTROL 0x0007 +#define LGDT3305_GEN_CTRL_4 0x000a +#define LGDT3305_DGTL_AGC_REF_1 0x0012 +#define LGDT3305_DGTL_AGC_REF_2 0x0013 +#define LGDT3305_CR_CTR_FREQ_1 0x0106 +#define LGDT3305_CR_CTR_FREQ_2 0x0107 +#define LGDT3305_CR_CTR_FREQ_3 0x0108 +#define LGDT3305_CR_CTR_FREQ_4 0x0109 +#define LGDT3305_CR_MSE_1 0x011b +#define LGDT3305_CR_MSE_2 0x011c +#define LGDT3305_CR_LOCK_STATUS 0x011d +#define LGDT3305_CR_CTRL_7 0x0126 +#define LGDT3305_AGC_POWER_REF_1 0x0300 +#define LGDT3305_AGC_POWER_REF_2 0x0301 +#define LGDT3305_AGC_DELAY_PT_1 0x0302 +#define LGDT3305_AGC_DELAY_PT_2 0x0303 +#define LGDT3305_RFAGC_LOOP_FLTR_BW_1 0x0306 +#define LGDT3305_RFAGC_LOOP_FLTR_BW_2 0x0307 +#define LGDT3305_IFBW_1 0x0308 +#define LGDT3305_IFBW_2 0x0309 +#define LGDT3305_AGC_CTRL_1 0x030c +#define LGDT3305_AGC_CTRL_4 0x0314 +#define LGDT3305_EQ_MSE_1 0x0413 +#define LGDT3305_EQ_MSE_2 0x0414 +#define LGDT3305_EQ_MSE_3 0x0415 +#define LGDT3305_PT_MSE_1 0x0417 +#define LGDT3305_PT_MSE_2 0x0418 +#define LGDT3305_PT_MSE_3 0x0419 +#define LGDT3305_FEC_BLOCK_CTRL 0x0504 +#define LGDT3305_FEC_LOCK_STATUS 0x050a +#define LGDT3305_FEC_PKT_ERR_1 0x050c +#define LGDT3305_FEC_PKT_ERR_2 0x050d +#define LGDT3305_TP_CTRL_1 0x050e +#define LGDT3305_BERT_PERIOD 0x0801 +#define LGDT3305_BERT_ERROR_COUNT_1 0x080a +#define LGDT3305_BERT_ERROR_COUNT_2 0x080b +#define LGDT3305_BERT_ERROR_COUNT_3 0x080c +#define LGDT3305_BERT_ERROR_COUNT_4 0x080d + +static int lgdt3305_write_reg(struct lgdt3305_state *state, u16 reg, u8 val) +{ + int ret; + u8 buf[] = { reg >> 8, reg & 0xff, val }; + struct i2c_msg msg = { + .addr = state->cfg->i2c_addr, .flags = 0, + .buf = buf, .len = 3, + }; + + lg_reg("reg: 0x%04x, val: 0x%02x\n", reg, val); + + ret = i2c_transfer(state->i2c_adap, &msg, 1); + + if (ret != 1) { + lg_err("error (addr %02x %02x <- %02x, err = %i)\n", + msg.buf[0], msg.buf[1], msg.buf[2], ret); + if (ret < 0) + return ret; + else + return -EREMOTEIO; + } + return 0; +} + +static int lgdt3305_read_reg(struct lgdt3305_state *state, u16 reg, u8 *val) +{ + int ret; + u8 reg_buf[] = { reg >> 8, reg & 0xff }; + struct i2c_msg msg[] = { + { .addr = state->cfg->i2c_addr, + .flags = 0, .buf = reg_buf, .len = 2 }, + { .addr = state->cfg->i2c_addr, + .flags = I2C_M_RD, .buf = val, .len = 1 }, + }; + + lg_reg("reg: 0x%04x\n", reg); + + ret = i2c_transfer(state->i2c_adap, msg, 2); + + if (ret != 2) { + lg_err("error (addr %02x reg %04x error (ret == %i)\n", + state->cfg->i2c_addr, reg, ret); + if (ret < 0) + return ret; + else + return -EREMOTEIO; + } + return 0; +} + +#define read_reg(state, reg) \ +({ \ + u8 __val; \ + int ret = lgdt3305_read_reg(state, reg, &__val); \ + if (lg_fail(ret)) \ + __val = 0; \ + __val; \ +}) + +static int lgdt3305_set_reg_bit(struct lgdt3305_state *state, + u16 reg, int bit, int onoff) +{ + u8 val; + int ret; + + lg_reg("reg: 0x%04x, bit: %d, level: %d\n", reg, bit, onoff); + + ret = lgdt3305_read_reg(state, reg, &val); + if (lg_fail(ret)) + goto fail; + + val &= ~(1 << bit); + val |= (onoff & 1) << bit; + + ret = lgdt3305_write_reg(state, reg, val); +fail: + return ret; +} + +struct lgdt3305_reg { + u16 reg; + u8 val; +}; + +static int lgdt3305_write_regs(struct lgdt3305_state *state, + struct lgdt3305_reg *regs, int len) +{ + int i, ret; + + lg_reg("writing %d registers...\n", len); + + for (i = 0; i < len - 1; i++) { + ret = lgdt3305_write_reg(state, regs[i].reg, regs[i].val); + if (lg_fail(ret)) + return ret; + } + return 0; +} + +/* ------------------------------------------------------------------------ */ + +static int lgdt3305_soft_reset(struct lgdt3305_state *state) +{ + int ret; + + lg_dbg("\n"); + + ret = lgdt3305_set_reg_bit(state, LGDT3305_GEN_CTRL_3, 0, 0); + if (lg_fail(ret)) + goto fail; + + msleep(20); + ret = lgdt3305_set_reg_bit(state, LGDT3305_GEN_CTRL_3, 0, 1); +fail: + return ret; +} + +static inline int lgdt3305_mpeg_mode(struct lgdt3305_state *state, + enum lgdt3305_mpeg_mode mode) +{ + lg_dbg("(%d)\n", mode); + return lgdt3305_set_reg_bit(state, LGDT3305_TP_CTRL_1, 5, mode); +} + +static int lgdt3305_mpeg_mode_polarity(struct lgdt3305_state *state, + enum lgdt3305_tp_clock_edge edge, + enum lgdt3305_tp_valid_polarity valid) +{ + u8 val; + int ret; + + lg_dbg("edge = %d, valid = %d\n", edge, valid); + + ret = lgdt3305_read_reg(state, LGDT3305_TP_CTRL_1, &val); + if (lg_fail(ret)) + goto fail; + + val &= ~0x09; + + if (edge) + val |= 0x08; + if (valid) + val |= 0x01; + + ret = lgdt3305_write_reg(state, LGDT3305_TP_CTRL_1, val); + if (lg_fail(ret)) + goto fail; + + ret = lgdt3305_soft_reset(state); +fail: + return ret; +} + +static int lgdt3305_set_modulation(struct lgdt3305_state *state, + struct dvb_frontend_parameters *param) +{ + u8 opermode; + int ret; + + lg_dbg("\n"); + + ret = lgdt3305_read_reg(state, LGDT3305_GEN_CTRL_1, &opermode); + if (lg_fail(ret)) + goto fail; + + opermode &= ~0x03; + + switch (param->u.vsb.modulation) { + case VSB_8: + opermode |= 0x03; + break; + case QAM_64: + opermode |= 0x00; + break; + case QAM_256: + opermode |= 0x01; + break; + default: + return -EINVAL; + } + ret = lgdt3305_write_reg(state, LGDT3305_GEN_CTRL_1, opermode); +fail: + return ret; +} + +static int lgdt3305_set_filter_extension(struct lgdt3305_state *state, + struct dvb_frontend_parameters *param) +{ + int val; + + switch (param->u.vsb.modulation) { + case VSB_8: + val = 0; + break; + case QAM_64: + case QAM_256: + val = 1; + break; + default: + return -EINVAL; + } + lg_dbg("val = %d\n", val); + + return lgdt3305_set_reg_bit(state, 0x043f, 2, val); +} + +/* ------------------------------------------------------------------------ */ + +static int lgdt3305_passband_digital_agc(struct lgdt3305_state *state, + struct dvb_frontend_parameters *param) +{ + u16 agc_ref; + + switch (param->u.vsb.modulation) { + case VSB_8: + agc_ref = 0x32c4; + break; + case QAM_64: + agc_ref = 0x2a00; + break; + case QAM_256: + agc_ref = 0x2a80; + break; + default: + return -EINVAL; + } + + lg_dbg("agc ref: 0x%04x\n", agc_ref); + + lgdt3305_write_reg(state, LGDT3305_DGTL_AGC_REF_1, agc_ref >> 8); + lgdt3305_write_reg(state, LGDT3305_DGTL_AGC_REF_2, agc_ref & 0xff); + + return 0; +} + +static int lgdt3305_rfagc_loop(struct lgdt3305_state *state, + struct dvb_frontend_parameters *param) +{ + u16 ifbw, rfbw, agcdelay; + + switch (param->u.vsb.modulation) { + case VSB_8: + agcdelay = 0x04c0; + rfbw = 0x8000; + ifbw = 0x8000; + break; + case QAM_64: + case QAM_256: + agcdelay = 0x046b; + rfbw = 0x8889; + ifbw = 0x8888; + break; + default: + return -EINVAL; + } + + if (state->cfg->rf_agc_loop) { + lg_dbg("agcdelay: 0x%04x, rfbw: 0x%04x\n", agcdelay, rfbw); + + /* rf agc loop filter bandwidth */ + lgdt3305_write_reg(state, LGDT3305_AGC_DELAY_PT_1, + agcdelay >> 8); + lgdt3305_write_reg(state, LGDT3305_AGC_DELAY_PT_2, + agcdelay & 0xff); + + lgdt3305_write_reg(state, LGDT3305_RFAGC_LOOP_FLTR_BW_1, + rfbw >> 8); + lgdt3305_write_reg(state, LGDT3305_RFAGC_LOOP_FLTR_BW_2, + rfbw & 0xff); + } else { + lg_dbg("ifbw: 0x%04x\n", ifbw); + + /* if agc loop filter bandwidth */ + lgdt3305_write_reg(state, LGDT3305_IFBW_1, ifbw >> 8); + lgdt3305_write_reg(state, LGDT3305_IFBW_2, ifbw & 0xff); + } + + return 0; +} + +static int lgdt3305_agc_setup(struct lgdt3305_state *state, + struct dvb_frontend_parameters *param) +{ + int lockdten, acqen; + + switch (param->u.vsb.modulation) { + case VSB_8: + lockdten = 0; + acqen = 0; + break; + case QAM_64: + case QAM_256: + lockdten = 1; + acqen = 1; + break; + default: + return -EINVAL; + } + + lg_dbg("lockdten = %d, acqen = %d\n", lockdten, acqen); + + /* control agc function */ + lgdt3305_write_reg(state, LGDT3305_AGC_CTRL_4, 0xe1 | lockdten << 1); + lgdt3305_set_reg_bit(state, LGDT3305_AGC_CTRL_1, 2, acqen); + + return lgdt3305_rfagc_loop(state, param); +} + +static int lgdt3305_set_agc_power_ref(struct lgdt3305_state *state, + struct dvb_frontend_parameters *param) +{ + u16 usref = 0; + + switch (param->u.vsb.modulation) { + case VSB_8: + if (state->cfg->usref_8vsb) + usref = state->cfg->usref_8vsb; + break; + case QAM_64: + if (state->cfg->usref_qam64) + usref = state->cfg->usref_qam64; + break; + case QAM_256: + if (state->cfg->usref_qam256) + usref = state->cfg->usref_qam256; + break; + default: + return -EINVAL; + } + + if (usref) { + lg_dbg("set manual mode: 0x%04x\n", usref); + + lgdt3305_set_reg_bit(state, LGDT3305_AGC_CTRL_1, 3, 1); + + lgdt3305_write_reg(state, LGDT3305_AGC_POWER_REF_1, + 0xff & (usref >> 8)); + lgdt3305_write_reg(state, LGDT3305_AGC_POWER_REF_2, + 0xff & (usref >> 0)); + } + return 0; +} + +/* ------------------------------------------------------------------------ */ + +static int lgdt3305_spectral_inversion(struct lgdt3305_state *state, + struct dvb_frontend_parameters *param, + int inversion) +{ + int ret; + + lg_dbg("(%d)\n", inversion); + + switch (param->u.vsb.modulation) { + case VSB_8: + ret = lgdt3305_write_reg(state, LGDT3305_CR_CTRL_7, + inversion ? 0xf9 : 0x79); + break; + case QAM_64: + case QAM_256: + ret = lgdt3305_write_reg(state, LGDT3305_FEC_BLOCK_CTRL, + inversion ? 0xfd : 0xff); + break; + default: + ret = -EINVAL; + } + return ret; +} + +static int lgdt3305_set_if(struct lgdt3305_state *state, + struct dvb_frontend_parameters *param) +{ + u16 if_freq_khz; + u8 nco1, nco2, nco3, nco4; + u64 nco; + + switch (param->u.vsb.modulation) { + case VSB_8: + if_freq_khz = state->cfg->vsb_if_khz; + break; + case QAM_64: + case QAM_256: + if_freq_khz = state->cfg->qam_if_khz; + break; + default: + return -EINVAL; + } + + nco = if_freq_khz / 10; + +#define LGDT3305_64BIT_DIVISION_ENABLED 0 + /* FIXME: 64bit division disabled to avoid linking error: + * WARNING: "__udivdi3" [lgdt3305.ko] undefined! + */ + switch (param->u.vsb.modulation) { + case VSB_8: +#if LGDT3305_64BIT_DIVISION_ENABLED + nco <<= 24; + nco /= 625; +#else + nco *= ((1 << 24) / 625); +#endif + break; + case QAM_64: + case QAM_256: +#if LGDT3305_64BIT_DIVISION_ENABLED + nco <<= 28; + nco /= 625; +#else + nco *= ((1 << 28) / 625); +#endif + break; + default: + return -EINVAL; + } + + nco1 = (nco >> 24) & 0x3f; + nco1 |= 0x40; + nco2 = (nco >> 16) & 0xff; + nco3 = (nco >> 8) & 0xff; + nco4 = nco & 0xff; + + lgdt3305_write_reg(state, LGDT3305_CR_CTR_FREQ_1, nco1); + lgdt3305_write_reg(state, LGDT3305_CR_CTR_FREQ_2, nco2); + lgdt3305_write_reg(state, LGDT3305_CR_CTR_FREQ_3, nco3); + lgdt3305_write_reg(state, LGDT3305_CR_CTR_FREQ_4, nco4); + + lg_dbg("%d KHz -> [%02x%02x%02x%02x]\n", + if_freq_khz, nco1, nco2, nco3, nco4); + + return 0; +} + +/* ------------------------------------------------------------------------ */ + +static int lgdt3305_i2c_gate_ctrl(struct dvb_frontend *fe, int enable) +{ + struct lgdt3305_state *state = fe->demodulator_priv; + + if (state->cfg->deny_i2c_rptr) + return 0; + + lg_dbg("(%d)\n", enable); + + return lgdt3305_set_reg_bit(state, LGDT3305_GEN_CTRL_2, 5, + enable ? 0 : 1); +} + +static int lgdt3305_sleep(struct dvb_frontend *fe) +{ + struct lgdt3305_state *state = fe->demodulator_priv; + u8 gen_ctrl_3, gen_ctrl_4; + + lg_dbg("\n"); + + gen_ctrl_3 = read_reg(state, LGDT3305_GEN_CTRL_3); + gen_ctrl_4 = read_reg(state, LGDT3305_GEN_CTRL_4); + + /* hold in software reset while sleeping */ + gen_ctrl_3 &= ~0x01; + /* tristate the IF-AGC pin */ + gen_ctrl_3 |= 0x02; + /* tristate the RF-AGC pin */ + gen_ctrl_3 |= 0x04; + + /* disable vsb/qam module */ + gen_ctrl_4 &= ~0x01; + /* disable adc module */ + gen_ctrl_4 &= ~0x02; + + lgdt3305_write_reg(state, LGDT3305_GEN_CTRL_3, gen_ctrl_3); + lgdt3305_write_reg(state, LGDT3305_GEN_CTRL_4, gen_ctrl_4); + + return 0; +} + +static int lgdt3305_init(struct dvb_frontend *fe) +{ + struct lgdt3305_state *state = fe->demodulator_priv; + int ret; + + static struct lgdt3305_reg lgdt3305_init_data[] = { + { .reg = LGDT3305_GEN_CTRL_1, + .val = 0x03, }, + { .reg = LGDT3305_GEN_CTRL_2, + .val = 0xb0, }, + { .reg = LGDT3305_GEN_CTRL_3, + .val = 0x01, }, + { .reg = LGDT3305_GEN_CONTROL, + .val = 0x6f, }, + { .reg = LGDT3305_GEN_CTRL_4, + .val = 0x03, }, + { .reg = LGDT3305_DGTL_AGC_REF_1, + .val = 0x32, }, + { .reg = LGDT3305_DGTL_AGC_REF_2, + .val = 0xc4, }, + { .reg = LGDT3305_CR_CTR_FREQ_1, + .val = 0x00, }, + { .reg = LGDT3305_CR_CTR_FREQ_2, + .val = 0x00, }, + { .reg = LGDT3305_CR_CTR_FREQ_3, + .val = 0x00, }, + { .reg = LGDT3305_CR_CTR_FREQ_4, + .val = 0x00, }, + { .reg = LGDT3305_CR_CTRL_7, + .val = 0x79, }, + { .reg = LGDT3305_AGC_POWER_REF_1, + .val = 0x32, }, + { .reg = LGDT3305_AGC_POWER_REF_2, + .val = 0xc4, }, + { .reg = LGDT3305_AGC_DELAY_PT_1, + .val = 0x0d, }, + { .reg = LGDT3305_AGC_DELAY_PT_2, + .val = 0x30, }, + { .reg = LGDT3305_RFAGC_LOOP_FLTR_BW_1, + .val = 0x80, }, + { .reg = LGDT3305_RFAGC_LOOP_FLTR_BW_2, + .val = 0x00, }, + { .reg = LGDT3305_IFBW_1, + .val = 0x80, }, + { .reg = LGDT3305_IFBW_2, + .val = 0x00, }, + { .reg = LGDT3305_AGC_CTRL_1, + .val = 0x30, }, + { .reg = LGDT3305_AGC_CTRL_4, + .val = 0x61, }, + { .reg = LGDT3305_FEC_BLOCK_CTRL, + .val = 0xff, }, + { .reg = LGDT3305_TP_CTRL_1, + .val = 0x1b, }, + }; + + lg_dbg("\n"); + + ret = lgdt3305_write_regs(state, lgdt3305_init_data, + ARRAY_SIZE(lgdt3305_init_data)); + if (lg_fail(ret)) + goto fail; + + ret = lgdt3305_soft_reset(state); +fail: + return ret; +} + +static int lgdt3305_set_parameters(struct dvb_frontend *fe, + struct dvb_frontend_parameters *param) +{ + struct lgdt3305_state *state = fe->demodulator_priv; + int ret; + + lg_dbg("(%d, %d)\n", param->frequency, param->u.vsb.modulation); + + if (fe->ops.tuner_ops.set_params) { + ret = fe->ops.tuner_ops.set_params(fe, param); + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 0); + if (lg_fail(ret)) + goto fail; + state->current_frequency = param->frequency; + } + + ret = lgdt3305_set_modulation(state, param); + if (lg_fail(ret)) + goto fail; + + ret = lgdt3305_passband_digital_agc(state, param); + if (lg_fail(ret)) + goto fail; + ret = lgdt3305_set_agc_power_ref(state, param); + if (lg_fail(ret)) + goto fail; + ret = lgdt3305_agc_setup(state, param); + if (lg_fail(ret)) + goto fail; + + /* low if */ + ret = lgdt3305_write_reg(state, LGDT3305_GEN_CONTROL, 0x2f); + if (lg_fail(ret)) + goto fail; + ret = lgdt3305_set_reg_bit(state, LGDT3305_CR_CTR_FREQ_1, 6, 1); + if (lg_fail(ret)) + goto fail; + + ret = lgdt3305_set_if(state, param); + if (lg_fail(ret)) + goto fail; + ret = lgdt3305_spectral_inversion(state, param, + state->cfg->spectral_inversion + ? 1 : 0); + if (lg_fail(ret)) + goto fail; + + ret = lgdt3305_set_filter_extension(state, param); + if (lg_fail(ret)) + goto fail; + + state->current_modulation = param->u.vsb.modulation; + + ret = lgdt3305_mpeg_mode(state, state->cfg->mpeg_mode); + if (lg_fail(ret)) + goto fail; + + /* lgdt3305_mpeg_mode_polarity calls lgdt3305_soft_reset */ + ret = lgdt3305_mpeg_mode_polarity(state, + state->cfg->tpclk_edge, + state->cfg->tpvalid_polarity); +fail: + return ret; +} + +static int lgdt3305_get_frontend(struct dvb_frontend *fe, + struct dvb_frontend_parameters *param) +{ + struct lgdt3305_state *state = fe->demodulator_priv; + + lg_dbg("\n"); + + param->u.vsb.modulation = state->current_modulation; + param->frequency = state->current_frequency; + return 0; +} + +/* ------------------------------------------------------------------------ */ + +static int lgdt3305_read_cr_lock_status(struct lgdt3305_state *state, + int *locked) +{ + u8 val; + int ret; + char *cr_lock_state = ""; + + *locked = 0; + + ret = lgdt3305_read_reg(state, LGDT3305_CR_LOCK_STATUS, &val); + if (lg_fail(ret)) + goto fail; + + switch (state->current_modulation) { + case QAM_256: + case QAM_64: + if (val & (1 << 1)) + *locked = 1; + + switch (val & 0x07) { + case 0: + cr_lock_state = "QAM UNLOCK"; + break; + case 4: + cr_lock_state = "QAM 1stLock"; + break; + case 6: + cr_lock_state = "QAM 2ndLock"; + break; + case 7: + cr_lock_state = "QAM FinalLock"; + break; + default: + cr_lock_state = "CLOCKQAM-INVALID!"; + break; + } + break; + case VSB_8: + if (val & (1 << 7)) { + *locked = 1; + cr_lock_state = "CLOCKVSB"; + } + break; + default: + ret = -EINVAL; + } + lg_dbg("(%d) %s\n", *locked, cr_lock_state); +fail: + return ret; +} + +static int lgdt3305_read_fec_lock_status(struct lgdt3305_state *state, + int *locked) +{ + u8 val; + int ret, mpeg_lock, fec_lock, viterbi_lock; + + *locked = 0; + + switch (state->current_modulation) { + case QAM_256: + case QAM_64: + ret = lgdt3305_read_reg(state, + LGDT3305_FEC_LOCK_STATUS, &val); + if (lg_fail(ret)) + goto fail; + + mpeg_lock = (val & (1 << 0)) ? 1 : 0; + fec_lock = (val & (1 << 2)) ? 1 : 0; + viterbi_lock = (val & (1 << 3)) ? 1 : 0; + + *locked = mpeg_lock && fec_lock && viterbi_lock; + + lg_dbg("(%d) %s%s%s\n", *locked, + mpeg_lock ? "mpeg lock " : "", + fec_lock ? "fec lock " : "", + viterbi_lock ? "viterbi lock" : ""); + break; + case VSB_8: + default: + ret = -EINVAL; + } +fail: + return ret; +} + +static int lgdt3305_read_status(struct dvb_frontend *fe, fe_status_t *status) +{ + struct lgdt3305_state *state = fe->demodulator_priv; + u8 val; + int ret, signal, inlock, nofecerr, snrgood, + cr_lock, fec_lock, sync_lock; + + *status = 0; + + ret = lgdt3305_read_reg(state, LGDT3305_GEN_STATUS, &val); + if (lg_fail(ret)) + goto fail; + + signal = (val & (1 << 4)) ? 1 : 0; + inlock = (val & (1 << 3)) ? 0 : 1; + sync_lock = (val & (1 << 2)) ? 1 : 0; + nofecerr = (val & (1 << 1)) ? 1 : 0; + snrgood = (val & (1 << 0)) ? 1 : 0; + + lg_dbg("%s%s%s%s%s\n", + signal ? "SIGNALEXIST " : "", + inlock ? "INLOCK " : "", + sync_lock ? "SYNCLOCK " : "", + nofecerr ? "NOFECERR " : "", + snrgood ? "SNRGOOD " : ""); + + ret = lgdt3305_read_cr_lock_status(state, &cr_lock); + if (lg_fail(ret)) + goto fail; + + if (signal) + *status |= FE_HAS_SIGNAL; + if (cr_lock) + *status |= FE_HAS_CARRIER; + if (nofecerr) + *status |= FE_HAS_VITERBI; + if (sync_lock) + *status |= FE_HAS_SYNC; + + switch (state->current_modulation) { + case QAM_256: + case QAM_64: + ret = lgdt3305_read_fec_lock_status(state, &fec_lock); + if (lg_fail(ret)) + goto fail; + + if (fec_lock) + *status |= FE_HAS_LOCK; + break; + case VSB_8: + if (inlock) + *status |= FE_HAS_LOCK; + break; + default: + ret = -EINVAL; + } +fail: + return ret; +} + +/* ------------------------------------------------------------------------ */ + +/* borrowed from lgdt330x.c */ +static u32 calculate_snr(u32 mse, u32 c) +{ + if (mse == 0) /* no signal */ + return 0; + + mse = intlog10(mse); + if (mse > c) { + /* Negative SNR, which is possible, but realisticly the + demod will lose lock before the signal gets this bad. The + API only allows for unsigned values, so just return 0 */ + return 0; + } + return 10*(c - mse); +} + +static int lgdt3305_read_snr(struct dvb_frontend *fe, u16 *snr) +{ + struct lgdt3305_state *state = fe->demodulator_priv; + u32 noise; /* noise value */ + u32 c; /* per-modulation SNR calculation constant */ + + switch (state->current_modulation) { + case VSB_8: +#ifdef USE_PTMSE + /* Use Phase Tracker Mean-Square Error Register */ + /* SNR for ranges from -13.11 to +44.08 */ + noise = ((read_reg(state, LGDT3305_PT_MSE_1) & 0x07) << 16) | + (read_reg(state, LGDT3305_PT_MSE_2) << 8) | + (read_reg(state, LGDT3305_PT_MSE_3) & 0xff); + c = 73957994; /* log10(25*32^2)*2^24 */ +#else + /* Use Equalizer Mean-Square Error Register */ + /* SNR for ranges from -16.12 to +44.08 */ + noise = ((read_reg(state, LGDT3305_EQ_MSE_1) & 0x0f) << 16) | + (read_reg(state, LGDT3305_EQ_MSE_2) << 8) | + (read_reg(state, LGDT3305_EQ_MSE_3) & 0xff); + c = 73957994; /* log10(25*32^2)*2^24 */ +#endif + break; + case QAM_64: + case QAM_256: + noise = (read_reg(state, LGDT3305_CR_MSE_1) << 8) | + (read_reg(state, LGDT3305_CR_MSE_2) & 0xff); + + c = (state->current_modulation == QAM_64) ? + 97939837 : 98026066; + /* log10(688128)*2^24 and log10(696320)*2^24 */ + break; + default: + return -EINVAL; + } + state->snr = calculate_snr(noise, c); +#if 0 + /* convert from 8.24 fixed-point to 8.8 */ + *snr = (state->snr) >> 16; +#else + /*report SNR in dB * 10 */ + *snr = (state->snr / ((1 << 24) / 10)); +#endif + lg_dbg("noise = 0x%08x, snr = %d.%02d dB\n", noise, + state->snr >> 24, (((state->snr >> 8) & 0xffff) * 100) >> 16); + + return 0; +} + +static int lgdt3305_read_signal_strength(struct dvb_frontend *fe, + u16 *strength) +{ + /* borrowed from lgdt330x.c + * + * Calculate strength from SNR up to 35dB + * Even though the SNR can go higher than 35dB, + * there is some comfort factor in having a range of + * strong signals that can show at 100% + */ + struct lgdt3305_state *state = fe->demodulator_priv; + u16 snr; + int ret; + + *strength = 0; + + ret = fe->ops.read_snr(fe, &snr); + if (lg_fail(ret)) + goto fail; + /* Rather than use the 8.8 value snr, use state->snr which is 8.24 */ + /* scale the range 0 - 35*2^24 into 0 - 65535 */ + if (state->snr >= 8960 * 0x10000) + *strength = 0xffff; + else + *strength = state->snr / 8960; +fail: + return ret; +} + +/* ------------------------------------------------------------------------ */ + +static int lgdt3305_read_ber(struct dvb_frontend *fe, u32 *ber) +{ +#if 0 + struct lgdt3305_state *state = fe->demodulator_priv; + u32 period, biterror; + u8 bertperd; + + bertperd = read_reg(state, LGDT3305_BERT_PERIOD) & 0x1f; + if (bertperd < 4) + bertperd = 4; + period = (1 << bertperd); + + biterror = + (read_reg(state, LGDT3305_BERT_ERROR_COUNT_1) << 24) | + (read_reg(state, LGDT3305_BERT_ERROR_COUNT_2) << 16) | + (read_reg(state, LGDT3305_BERT_ERROR_COUNT_3) << 8) | + (read_reg(state, LGDT3305_BERT_ERROR_COUNT_4) & 0xff); + + *ber = (biterror) / period; + + lg_dbg("biterror = %d, period = %d, ber = 0x%x\n", + biterror, period, *ber); +#else + *ber = 0; +#endif + return 0; +} + +static int lgdt3305_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) +{ + struct lgdt3305_state *state = fe->demodulator_priv; + + *ucblocks = + (read_reg(state, LGDT3305_FEC_PKT_ERR_1) << 8) | + (read_reg(state, LGDT3305_FEC_PKT_ERR_2) & 0xff); + + return 0; +} + +static int lgdt3305_get_tune_settings(struct dvb_frontend *fe, + struct dvb_frontend_tune_settings + *fe_tune_settings) +{ + fe_tune_settings->min_delay_ms = 500; + lg_dbg("\n"); + return 0; +} + +static void lgdt3305_release(struct dvb_frontend *fe) +{ + struct lgdt3305_state *state = fe->demodulator_priv; + lg_dbg("\n"); + kfree(state); +} + +static struct dvb_frontend_ops lgdt3305_ops; + +struct dvb_frontend *lgdt3305_attach(const struct lgdt3305_config *config, + struct i2c_adapter *i2c_adap) +{ + struct lgdt3305_state *state = NULL; + int ret; + u8 val; + + lg_dbg("(%d-%04x)\n", + i2c_adap ? i2c_adapter_id(i2c_adap) : 0, + config ? config->i2c_addr : 0); + + state = kzalloc(sizeof(struct lgdt3305_state), GFP_KERNEL); + if (state == NULL) + goto fail; + + state->cfg = config; + state->i2c_adap = i2c_adap; + + memcpy(&state->frontend.ops, &lgdt3305_ops, + sizeof(struct dvb_frontend_ops)); + state->frontend.demodulator_priv = state; + + /* verify that we're talking to a lg dt3305 */ + ret = lgdt3305_read_reg(state, LGDT3305_GEN_CTRL_2, &val); + if ((lg_fail(ret)) | (val == 0)) + goto fail; + ret = lgdt3305_write_reg(state, 0x0808, 0x80); + if (lg_fail(ret)) + goto fail; + ret = lgdt3305_read_reg(state, 0x0808, &val); + if ((lg_fail(ret)) | (val != 0x80)) + goto fail; + ret = lgdt3305_write_reg(state, 0x0808, 0x00); + if (lg_fail(ret)) + goto fail; + + state->current_frequency = -1; + state->current_modulation = -1; + + return &state->frontend; +fail: + lg_warn("unable to detect LGDT3305 hardware\n"); + state->frontend.demodulator_priv = NULL; + kfree(state); + return NULL; +} +EXPORT_SYMBOL(lgdt3305_attach); + +static struct dvb_frontend_ops lgdt3305_ops = { + .info = { + .name = "LG Electronics LGDT3305 VSB/QAM Frontend", + .type = FE_ATSC, + .frequency_min = 54000000, + .frequency_max = 858000000, + .frequency_stepsize = 62500, + .caps = FE_CAN_QAM_64 | FE_CAN_QAM_256 | FE_CAN_8VSB + }, + .i2c_gate_ctrl = lgdt3305_i2c_gate_ctrl, + .init = lgdt3305_init, + .sleep = lgdt3305_sleep, + .set_frontend = lgdt3305_set_parameters, + .get_frontend = lgdt3305_get_frontend, + .get_tune_settings = lgdt3305_get_tune_settings, + .read_status = lgdt3305_read_status, + .read_ber = lgdt3305_read_ber, + .read_signal_strength = lgdt3305_read_signal_strength, + .read_snr = lgdt3305_read_snr, + .read_ucblocks = lgdt3305_read_ucblocks, + .release = lgdt3305_release, +}; + +MODULE_DESCRIPTION("LG Electronics LGDT3305 ATSC/QAM-B Demodulator Driver"); +MODULE_AUTHOR("Michael Krufky"); +MODULE_LICENSE("GPL"); + +/* + * Local variables: + * c-basic-offset: 8 + * End: + */ diff --git a/linux/drivers/media/dvb/frontends/lgdt3305.h b/linux/drivers/media/dvb/frontends/lgdt3305.h new file mode 100644 index 000000000..4fa6e52d1 --- /dev/null +++ b/linux/drivers/media/dvb/frontends/lgdt3305.h @@ -0,0 +1,85 @@ +/* + * Support for LGDT3305 - VSB/QAM + * + * Copyright (C) 2008, 2009 Michael Krufky + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifndef _LGDT3305_H_ +#define _LGDT3305_H_ + +#include +#include "dvb_frontend.h" + + +enum lgdt3305_mpeg_mode { + LGDT3305_MPEG_PARALLEL = 0, + LGDT3305_MPEG_SERIAL = 1, +}; + +enum lgdt3305_tp_clock_edge { + LGDT3305_TPCLK_RISING_EDGE = 0, + LGDT3305_TPCLK_FALLING_EDGE = 1, +}; + +enum lgdt3305_tp_valid_polarity { + LGDT3305_TP_VALID_LOW = 0, + LGDT3305_TP_VALID_HIGH = 1, +}; + +struct lgdt3305_config { + u8 i2c_addr; + + /* user defined IF frequency in KHz */ + u16 qam_if_khz; + u16 vsb_if_khz; + + /* AGC Power reference - defaults are used if left unset */ + u16 usref_8vsb; /* default: 0x32c4 */ + u16 usref_qam64; /* default: 0x5400 */ + u16 usref_qam256; /* default: 0x2a80 */ + + /* disable i2c repeater - 0:repeater enabled 1:repeater disabled */ + int deny_i2c_rptr:1; + + /* spectral inversion - 0:disabled 1:enabled */ + int spectral_inversion:1; + + /* use RF AGC loop - 0:disabled 1:enabled */ + int rf_agc_loop:1; + + enum lgdt3305_mpeg_mode mpeg_mode; + enum lgdt3305_tp_clock_edge tpclk_edge; + enum lgdt3305_tp_valid_polarity tpvalid_polarity; +}; + +#if defined(CONFIG_DVB_LGDT3305) || (defined(CONFIG_DVB_LGDT3305_MODULE) && \ + defined(MODULE)) +extern +struct dvb_frontend *lgdt3305_attach(const struct lgdt3305_config *config, + struct i2c_adapter *i2c_adap); +#else +static inline +struct dvb_frontend *lgdt3305_attach(const struct lgdt3305_config *config, + struct i2c_adapter *i2c_adap) +{ + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); + return NULL; +} +#endif /* CONFIG_DVB_LGDT3305 */ + +#endif /* _LGDT3305_H_ */ -- cgit v1.2.3 From cc8d160235208990c7c07ab9dd038071f087d154 Mon Sep 17 00:00:00 2001 From: Erik Andr?n Date: Tue, 13 Jan 2009 17:43:46 +0100 Subject: gspca - m5602-po1030: Add auto exposure control From: Erik Andr?n Priority: normal Signed-off-by: Erik Andr?n --- .../drivers/media/video/gspca/m5602/m5602_po1030.c | 58 +++++++++++++++++++++- 1 file changed, 56 insertions(+), 2 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/m5602/m5602_po1030.c b/linux/drivers/media/video/gspca/m5602/m5602_po1030.c index 26ac61978..e32d03a2c 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_po1030.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_po1030.c @@ -34,6 +34,10 @@ static int po1030_set_auto_white_balance(struct gspca_dev *gspca_dev, __s32 val); static int po1030_get_auto_white_balance(struct gspca_dev *gspca_dev, __s32 *val); +static int po1030_set_auto_exposure(struct gspca_dev *gspca_dev, + __s32 val); +static int po1030_get_auto_exposure(struct gspca_dev *gspca_dev, + __s32 *val); static struct v4l2_pix_format po1030_modes[] = { { @@ -150,7 +154,22 @@ const static struct ctrl po1030_ctrls[] = { }, .set = po1030_set_auto_white_balance, .get = po1030_get_auto_white_balance - } + }, +#define AUTO_EXPOSURE_IDX 7 + { + { + .id = V4L2_CID_EXPOSURE_AUTO, + .type = V4L2_CTRL_TYPE_BOOLEAN, + .name = "auto exposure", + .minimum = 0, + .maximum = 1, + .step = 1, + .default_value = 0, + }, + .set = po1030_set_auto_exposure, + .get = po1030_get_auto_exposure + }, + }; static void po1030_dump_registers(struct sd *sd); @@ -270,7 +289,12 @@ int po1030_init(struct sd *sd) return err; err = po1030_set_auto_white_balance(&sd->gspca_dev, - sensor_settings[AUTO_WHITE_BALANCE_IDX]); + sensor_settings[AUTO_WHITE_BALANCE_IDX]); + if (err < 0) + return err; + + err = po1030_set_auto_exposure(&sd->gspca_dev, + sensor_settings[AUTO_EXPOSURE_IDX]); return err; } @@ -501,11 +525,41 @@ static int po1030_set_auto_white_balance(struct gspca_dev *gspca_dev, if (err < 0) return err; + PDEBUG(D_V4L2, "Set auto white balance to %d", val); i2c_data = (i2c_data & 0xfe) | (val & 0x01); err = m5602_write_sensor(sd, PO1030_AUTOCTRL1, &i2c_data, 1); return err; } +static int po1030_get_auto_exposure(struct gspca_dev *gspca_dev, + __s32 *val) +{ + struct sd *sd = (struct sd *) gspca_dev; + s32 *sensor_settings = sd->sensor_priv; + + *val = sensor_settings[AUTO_EXPOSURE_IDX]; + PDEBUG(D_V4L2, "Auto exposure is %d", *val); + return 0; +} + +static int po1030_set_auto_exposure(struct gspca_dev *gspca_dev, + __s32 val) +{ + struct sd *sd = (struct sd *) gspca_dev; + s32 *sensor_settings = sd->sensor_priv; + u8 i2c_data; + int err; + + sensor_settings[AUTO_EXPOSURE_IDX] = val; + err = m5602_read_sensor(sd, PO1030_AUTOCTRL1, &i2c_data, 1); + if (err < 0) + return err; + + PDEBUG(D_V4L2, "Set auto exposure to %d", val); + i2c_data = (i2c_data & 0xfd) | ((val & 0x01) << 1); + return m5602_write_sensor(sd, PO1030_AUTOCTRL1, &i2c_data, 1); +} + void po1030_disconnect(struct sd *sd) { sd->sensor = NULL; -- cgit v1.2.3 From 184dc138ba7f6b20c15c20f122015620da869e9e Mon Sep 17 00:00:00 2001 From: Erik Andr?n Date: Tue, 13 Jan 2009 17:55:52 +0100 Subject: gspca - m5602-po1030: Add private green balance control From: Erik Andr?n Priority: normal Signed-off-by: Erik Andr?n --- .../drivers/media/video/gspca/m5602/m5602_po1030.c | 54 +++++++++++++++++++++- .../drivers/media/video/gspca/m5602/m5602_po1030.h | 1 + .../drivers/media/video/gspca/m5602/m5602_sensor.h | 2 + 3 files changed, 56 insertions(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/m5602/m5602_po1030.c b/linux/drivers/media/video/gspca/m5602/m5602_po1030.c index e32d03a2c..ee8e49609 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_po1030.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_po1030.c @@ -26,6 +26,8 @@ static int po1030_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val); static int po1030_set_red_balance(struct gspca_dev *gspca_dev, __s32 val); static int po1030_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val); static int po1030_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val); +static int po1030_get_green_balance(struct gspca_dev *gspca_dev, __s32 *val); +static int po1030_set_green_balance(struct gspca_dev *gspca_dev, __s32 val); static int po1030_get_hflip(struct gspca_dev *gspca_dev, __s32 *val); static int po1030_set_hflip(struct gspca_dev *gspca_dev, __s32 val); static int po1030_get_vflip(struct gspca_dev *gspca_dev, __s32 *val); @@ -169,7 +171,21 @@ const static struct ctrl po1030_ctrls[] = { .set = po1030_set_auto_exposure, .get = po1030_get_auto_exposure }, - +#define GREEN_BALANCE_IDX 8 + { + { + .id = M5602_V4L2_CID_GREEN_BALANCE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "green balance", + .minimum = 0x00, + .maximum = 0xff, + .step = 0x1, + .default_value = PO1030_GREEN_GAIN_DEFAULT, + .flags = V4L2_CTRL_FLAG_SLIDER + }, + .set = po1030_set_green_balance, + .get = po1030_get_green_balance + }, }; static void po1030_dump_registers(struct sd *sd); @@ -288,6 +304,11 @@ int po1030_init(struct sd *sd) if (err < 0) return err; + err = po1030_set_green_balance(&sd->gspca_dev, + sensor_settings[GREEN_BALANCE_IDX]); + if (err < 0) + return err; + err = po1030_set_auto_white_balance(&sd->gspca_dev, sensor_settings[AUTO_WHITE_BALANCE_IDX]); if (err < 0) @@ -499,6 +520,37 @@ static int po1030_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val) return err; } +static int po1030_get_green_balance(struct gspca_dev *gspca_dev, __s32 *val) +{ + struct sd *sd = (struct sd *) gspca_dev; + s32 *sensor_settings = sd->sensor_priv; + + *val = sensor_settings[GREEN_BALANCE_IDX]; + PDEBUG(D_V4L2, "Read green gain %d", *val); + + return 0; +} + +static int po1030_set_green_balance(struct gspca_dev *gspca_dev, __s32 val) +{ + struct sd *sd = (struct sd *) gspca_dev; + s32 *sensor_settings = sd->sensor_priv; + u8 i2c_data; + int err; + + sensor_settings[GREEN_BALANCE_IDX] = val; + i2c_data = val & 0xff; + PDEBUG(D_V4L2, "Set green gain to %d", i2c_data); + + err = m5602_write_sensor(sd, PO1030_GREEN_1_GAIN, + &i2c_data, 1); + if (err < 0) + return err; + + return m5602_write_sensor(sd, PO1030_GREEN_2_GAIN, + &i2c_data, 1); +} + static int po1030_get_auto_white_balance(struct gspca_dev *gspca_dev, __s32 *val) { diff --git a/linux/drivers/media/video/gspca/m5602/m5602_po1030.h b/linux/drivers/media/video/gspca/m5602/m5602_po1030.h index 3ecacf0ed..0b2dab038 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_po1030.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_po1030.h @@ -139,6 +139,7 @@ #define PO1030_EXPOSURE_DEFAULT 0x0085 #define PO1030_BLUE_GAIN_DEFAULT 0x36 #define PO1030_RED_GAIN_DEFAULT 0x36 +#define PO1030_GREEN_GAIN_DEFAULT 0x40 /*****************************************************************************/ diff --git a/linux/drivers/media/video/gspca/m5602/m5602_sensor.h b/linux/drivers/media/video/gspca/m5602/m5602_sensor.h index 987dcb23e..5b76b6b62 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_sensor.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_sensor.h @@ -21,6 +21,8 @@ #include "m5602_bridge.h" +#define M5602_V4L2_CID_GREEN_BALANCE (V4L2_CID_PRIVATE_BASE + 0) + /* Enumerates all supported sensors */ enum sensors { OV9650_SENSOR = 1, -- cgit v1.2.3 From 152aa2c32eb31d5240e047e8d956a1aea7e9e7a0 Mon Sep 17 00:00:00 2001 From: Erik Andr?n Date: Tue, 13 Jan 2009 18:10:44 +0100 Subject: gspca - m5602-mt9m111: Add green balance ctrl From: Erik Andr?n Priority: normal Signed-off-by: Erik Andr?n --- .../media/video/gspca/m5602/m5602_mt9m111.c | 60 ++++++++++++++++++++-- .../media/video/gspca/m5602/m5602_mt9m111.h | 1 + 2 files changed, 57 insertions(+), 4 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.c b/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.c index 37a7fc82a..c1ff4770e 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.c @@ -28,7 +28,8 @@ static int mt9m111_set_auto_white_balance(struct gspca_dev *gspca_dev, __s32 val); static int mt9m111_get_auto_white_balance(struct gspca_dev *gspca_dev, __s32 *val); - +static int mt9m111_get_green_balance(struct gspca_dev *gspca_dev, __s32 *val); +static int mt9m111_set_green_balance(struct gspca_dev *gspca_dev, __s32 val); static struct v4l2_pix_format mt9m111_modes[] = { { @@ -100,7 +101,23 @@ const static struct ctrl mt9m111_ctrls[] = { }, .set = mt9m111_set_auto_white_balance, .get = mt9m111_get_auto_white_balance - } + }, +#define GREEN_BALANCE_IDX 4 + { + { + .id = M5602_V4L2_CID_GREEN_BALANCE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "green balance", + .minimum = 0x00, + .maximum = 0x7ff, + .step = 0x1, + .default_value = MT9M111_GREEN_GAIN_DEFAULT, + .flags = V4L2_CTRL_FLAG_SLIDER + }, + .set = mt9m111_set_green_balance, + .get = mt9m111_get_green_balance + }, + }; static void mt9m111_dump_registers(struct sd *sd); @@ -197,9 +214,12 @@ int mt9m111_init(struct sd *sd) if (err < 0) return err; - err = mt9m111_set_gain(&sd->gspca_dev, sensor_settings[GAIN_IDX]); + err = mt9m111_set_green_balance(&sd->gspca_dev, + sensor_settings[GREEN_BALANCE_IDX]); + if (err < 0) + return err; - return err; + return mt9m111_set_gain(&sd->gspca_dev, sensor_settings[GAIN_IDX]); } void mt9m111_disconnect(struct sd *sd) @@ -364,6 +384,38 @@ static int mt9m111_set_gain(struct gspca_dev *gspca_dev, __s32 val) return err; } +static int mt9m111_set_green_balance(struct gspca_dev *gspca_dev, __s32 val) +{ + int err; + u8 data[2]; + struct sd *sd = (struct sd *) gspca_dev; + s32 *sensor_settings = sd->sensor_priv; + + sensor_settings[GREEN_BALANCE_IDX] = val; + data[0] = (val & 0xff); + data[1] = (val & 0xff00) >> 8; + + PDEBUG(D_V4L2, "Set green balance %d", val); + err = m5602_write_sensor(sd, MT9M111_SC_GREEN_1_GAIN, + data, 2); + if (err < 0) + return err; + + return m5602_write_sensor(sd, MT9M111_SC_GREEN_2_GAIN, + data, 2); +} + +static int mt9m111_get_green_balance(struct gspca_dev *gspca_dev, __s32 *val) +{ + struct sd *sd = (struct sd *) gspca_dev; + s32 *sensor_settings = sd->sensor_priv; + + *val = sensor_settings[GREEN_BALANCE_IDX]; + PDEBUG(D_V4L2, "Read green balance %d", *val); + return 0; +} + + static void mt9m111_dump_registers(struct sd *sd) { u8 address, value[2] = {0x00, 0x00}; diff --git a/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h b/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h index d0fe02cea..2d39e12d6 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h @@ -93,6 +93,7 @@ #define INITIAL_MAX_GAIN 64 #define DEFAULT_GAIN 283 +#define MT9M111_GREEN_GAIN_DEFAULT 0x20 /*****************************************************************************/ -- cgit v1.2.3 From 94dc411d6ba4e2d8e63c52b41f8fd91d570de65a Mon Sep 17 00:00:00 2001 From: Erik Andr?n Date: Tue, 13 Jan 2009 18:16:03 +0100 Subject: gspca - m5602-mt9m111: Add blue balance ctrl From: Erik Andr?n Priority: normal Signed-off-by: Erik Andr?n --- .../media/video/gspca/m5602/m5602_mt9m111.c | 48 +++++++++++++++++++++- .../media/video/gspca/m5602/m5602_mt9m111.h | 7 +++- 2 files changed, 52 insertions(+), 3 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.c b/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.c index c1ff4770e..8bdd29c7d 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.c @@ -30,6 +30,8 @@ static int mt9m111_get_auto_white_balance(struct gspca_dev *gspca_dev, __s32 *val); static int mt9m111_get_green_balance(struct gspca_dev *gspca_dev, __s32 *val); static int mt9m111_set_green_balance(struct gspca_dev *gspca_dev, __s32 val); +static int mt9m111_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val); +static int mt9m111_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val); static struct v4l2_pix_format mt9m111_modes[] = { { @@ -117,7 +119,21 @@ const static struct ctrl mt9m111_ctrls[] = { .set = mt9m111_set_green_balance, .get = mt9m111_get_green_balance }, - +#define BLUE_BALANCE_IDX 5 + { + { + .id = V4L2_CID_BLUE_BALANCE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "blue balance", + .minimum = 0x00, + .maximum = 0x7ff, + .step = 0x1, + .default_value = MT9M111_BLUE_GAIN_DEFAULT, + .flags = V4L2_CTRL_FLAG_SLIDER + }, + .set = mt9m111_set_blue_balance, + .get = mt9m111_get_blue_balance + }, }; static void mt9m111_dump_registers(struct sd *sd); @@ -219,6 +235,11 @@ int mt9m111_init(struct sd *sd) if (err < 0) return err; + err = mt9m111_set_blue_balance(&sd->gspca_dev, + sensor_settings[BLUE_BALANCE_IDX]); + if (err < 0) + return err; + return mt9m111_set_gain(&sd->gspca_dev, sensor_settings[GAIN_IDX]); } @@ -415,6 +436,31 @@ static int mt9m111_get_green_balance(struct gspca_dev *gspca_dev, __s32 *val) return 0; } +static int mt9m111_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val) +{ + u8 data[2]; + struct sd *sd = (struct sd *) gspca_dev; + s32 *sensor_settings = sd->sensor_priv; + + sensor_settings[BLUE_BALANCE_IDX] = val; + data[0] = (val & 0xff); + data[1] = (val & 0xff00) >> 8; + + PDEBUG(D_V4L2, "Set blue balance %d", val); + + return m5602_write_sensor(sd, MT9M111_SC_BLUE_GAIN, + data, 2); +} + +static int mt9m111_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val) +{ + struct sd *sd = (struct sd *) gspca_dev; + s32 *sensor_settings = sd->sensor_priv; + + *val = sensor_settings[BLUE_BALANCE_IDX]; + PDEBUG(D_V4L2, "Read blue balance %d", *val); + return 0; +} static void mt9m111_dump_registers(struct sd *sd) { diff --git a/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h b/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h index 2d39e12d6..57dcb56ef 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h @@ -94,6 +94,7 @@ #define INITIAL_MAX_GAIN 64 #define DEFAULT_GAIN 283 #define MT9M111_GREEN_GAIN_DEFAULT 0x20 +#define MT9M111_BLUE_GAIN_DEFAULT 0x20 /*****************************************************************************/ @@ -183,8 +184,10 @@ static const unsigned char init_mt9m111[][4] = {SENSOR, MT9M111_CP_OPERATING_MODE_CTL, 0x00, MT9M111_CP_OPERATING_MODE_CTL}, {SENSOR, MT9M111_CP_LENS_CORRECTION_1, 0x04, 0x2a}, - {SENSOR, MT9M111_CP_DEFECT_CORR_CONTEXT_A, 0x00, MT9M111_2D_DEFECT_CORRECTION_ENABLE}, - {SENSOR, MT9M111_CP_DEFECT_CORR_CONTEXT_B, 0x00, MT9M111_2D_DEFECT_CORRECTION_ENABLE}, + {SENSOR, MT9M111_CP_DEFECT_CORR_CONTEXT_A, 0x00, + MT9M111_2D_DEFECT_CORRECTION_ENABLE}, + {SENSOR, MT9M111_CP_DEFECT_CORR_CONTEXT_B, 0x00, + MT9M111_2D_DEFECT_CORRECTION_ENABLE}, {SENSOR, MT9M111_CP_LUMA_OFFSET, 0x00, 0x00}, {SENSOR, MT9M111_CP_LUMA_CLIP, 0xff, 0x00}, {SENSOR, MT9M111_CP_OUTPUT_FORMAT_CTL2_CONTEXT_A, 0x14, 0x00}, -- cgit v1.2.3 From 1396fc29fa670cab79c5d2740149fb8c1f447e6b Mon Sep 17 00:00:00 2001 From: Erik Andr?n Date: Tue, 13 Jan 2009 18:18:53 +0100 Subject: gspca - m5602-mt9m111: Add red balance ctrl From: Erik Andr?n Priority: normal Signed-off-by: Erik Andr?n --- .../media/video/gspca/m5602/m5602_mt9m111.c | 48 ++++++++++++++++++++++ .../media/video/gspca/m5602/m5602_mt9m111.h | 1 + 2 files changed, 49 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.c b/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.c index 8bdd29c7d..95b6e95aa 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.c @@ -32,6 +32,8 @@ static int mt9m111_get_green_balance(struct gspca_dev *gspca_dev, __s32 *val); static int mt9m111_set_green_balance(struct gspca_dev *gspca_dev, __s32 val); static int mt9m111_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val); static int mt9m111_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val); +static int mt9m111_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val); +static int mt9m111_set_red_balance(struct gspca_dev *gspca_dev, __s32 val); static struct v4l2_pix_format mt9m111_modes[] = { { @@ -134,6 +136,21 @@ const static struct ctrl mt9m111_ctrls[] = { .set = mt9m111_set_blue_balance, .get = mt9m111_get_blue_balance }, +#define RED_BALANCE_IDX 5 + { + { + .id = V4L2_CID_RED_BALANCE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "red balance", + .minimum = 0x00, + .maximum = 0x7ff, + .step = 0x1, + .default_value = MT9M111_RED_GAIN_DEFAULT, + .flags = V4L2_CTRL_FLAG_SLIDER + }, + .set = mt9m111_set_red_balance, + .get = mt9m111_get_red_balance + }, }; static void mt9m111_dump_registers(struct sd *sd); @@ -240,6 +257,11 @@ int mt9m111_init(struct sd *sd) if (err < 0) return err; + err = mt9m111_set_red_balance(&sd->gspca_dev, + sensor_settings[RED_BALANCE_IDX]); + if (err < 0) + return err; + return mt9m111_set_gain(&sd->gspca_dev, sensor_settings[GAIN_IDX]); } @@ -462,6 +484,32 @@ static int mt9m111_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val) return 0; } +static int mt9m111_set_red_balance(struct gspca_dev *gspca_dev, __s32 val) +{ + u8 data[2]; + struct sd *sd = (struct sd *) gspca_dev; + s32 *sensor_settings = sd->sensor_priv; + + sensor_settings[RED_BALANCE_IDX] = val; + data[0] = (val & 0xff); + data[1] = (val & 0xff00) >> 8; + + PDEBUG(D_V4L2, "Set red balance %d", val); + + return m5602_write_sensor(sd, MT9M111_SC_RED_GAIN, + data, 2); +} + +static int mt9m111_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val) +{ + struct sd *sd = (struct sd *) gspca_dev; + s32 *sensor_settings = sd->sensor_priv; + + *val = sensor_settings[RED_BALANCE_IDX]; + PDEBUG(D_V4L2, "Read red balance %d", *val); + return 0; +} + static void mt9m111_dump_registers(struct sd *sd) { u8 address, value[2] = {0x00, 0x00}; diff --git a/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h b/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h index 57dcb56ef..217728a24 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h @@ -95,6 +95,7 @@ #define DEFAULT_GAIN 283 #define MT9M111_GREEN_GAIN_DEFAULT 0x20 #define MT9M111_BLUE_GAIN_DEFAULT 0x20 +#define MT9M111_RED_GAIN_DEFAULT 0x20 /*****************************************************************************/ -- cgit v1.2.3 From 381435e02c2d0614ac0dcdcb8a5aebb9b47682f7 Mon Sep 17 00:00:00 2001 From: Erik Andr?n Date: Tue, 13 Jan 2009 19:44:03 +0100 Subject: gspca - m5602-s5k4aa: Try to use proper read-modify-write of the vflip/hflip From: Erik Andr?n Priority: normal Signed-off-by: Erik Andr?n --- linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c b/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c index 7b1d0602e..003dc469c 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c @@ -376,6 +376,10 @@ static int s5k4aa_set_vflip(struct gspca_dev *gspca_dev, __s32 val) if (err < 0) return err; + err = m5602_read_sensor(sd, S5K4AA_READ_MODE, &data, 1); + if (err < 0) + return err; + if (dmi_check_system(s5k4aa_vflip_dmi_table)) val = !val; @@ -435,6 +439,10 @@ static int s5k4aa_set_hflip(struct gspca_dev *gspca_dev, __s32 val) if (err < 0) return err; + err = m5602_read_sensor(sd, S5K4AA_READ_MODE, &data, 1); + if (err < 0) + return err; + data = ((data & ~S5K4AA_RM_H_FLIP) | ((val & 0x01) << 6)); err = m5602_write_sensor(sd, S5K4AA_READ_MODE, &data, 1); if (err < 0) -- cgit v1.2.3 From 9785971b5e2e26b15baa8bd98ca7dc16352c275c Mon Sep 17 00:00:00 2001 From: Erik Andr?n Date: Tue, 13 Jan 2009 20:24:19 +0100 Subject: gspca - m5602-s5k4aa: Consolidate the gain settings, adjust row start From: Erik Andr?n Priority: normal Signed-off-by: Erik Andr?n --- linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c | 2 +- linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.h | 14 ++++---------- 2 files changed, 5 insertions(+), 11 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c b/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c index 003dc469c..cd856ef8d 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c @@ -113,7 +113,7 @@ const static struct ctrl s5k4aa_ctrls[] = { .minimum = 0, .maximum = 127, .step = 1, - .default_value = 0xa0, + .default_value = DEFAULT_GAIN_2, .flags = V4L2_CTRL_FLAG_SLIDER }, .set = s5k4aa_set_gain, diff --git a/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.h b/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.h index 7a8da1dc4..fbcb9c1e8 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.h @@ -57,6 +57,8 @@ #define S5K4AA_RM_H_FLIP 0x40 #define S5K4AA_RM_V_FLIP 0x80 +#define DEFAULT_GAIN_2 0x5f + /*****************************************************************************/ /* Kernel module parameters */ @@ -171,9 +173,6 @@ static const unsigned char init_s5k4aa[][4] = {SENSOR, S5K4AA_PAGE_MAP, 0x02, 0x00}, {SENSOR, 0x0c, 0x05, 0x00}, {SENSOR, 0x02, 0x0e, 0x00}, - {SENSOR, S5K4AA_GAIN_1, 0x0f, 0x00}, - {SENSOR, S5K4AA_GAIN_2, 0x00, 0x00}, - {SENSOR, S5K4AA_GLOBAL_GAIN__, 0x01, 0x00}, {SENSOR, 0x11, 0x00, 0x00}, {SENSOR, 0x12, 0x00, 0x00}, {SENSOR, S5K4AA_PAGE_MAP, 0x02, 0x00}, @@ -247,9 +246,6 @@ static const unsigned char init_s5k4aa[][4] = {SENSOR, 0x12, 0xc3, 0x00}, {SENSOR, S5K4AA_PAGE_MAP, 0x02, 0x00}, {SENSOR, 0x02, 0x0e, 0x00}, - {SENSOR_LONG, S5K4AA_GLOBAL_GAIN__, 0x0f, 0x00}, - {SENSOR, S5K4AA_GAIN_1, 0x0b, 0x00}, - {SENSOR, S5K4AA_GAIN_2, 0xa0, 0x00} }; static const unsigned char VGA_s5k4aa[][4] = @@ -289,7 +285,7 @@ static const unsigned char VGA_s5k4aa[][4] = {SENSOR, 0x37, 0x01, 0x00}, /* ROWSTART_HI, ROWSTART_LO : 10 + (1024-960)/2 = 42 = 0x002a */ {SENSOR, S5K4AA_ROWSTART_HI, 0x00, 0x00}, - {SENSOR, S5K4AA_ROWSTART_LO, 0x2a, 0x00}, + {SENSOR, S5K4AA_ROWSTART_LO, 0x29, 0x00}, {SENSOR, S5K4AA_COLSTART_HI, 0x00, 0x00}, {SENSOR, S5K4AA_COLSTART_LO, 0x0c, 0x00}, /* window_height_hi, window_height_lo : 960 = 0x03c0 */ @@ -306,9 +302,7 @@ static const unsigned char VGA_s5k4aa[][4] = {SENSOR, 0x12, 0xc3, 0x00}, {SENSOR, S5K4AA_PAGE_MAP, 0x02, 0x00}, {SENSOR, 0x02, 0x0e, 0x00}, - {SENSOR_LONG, S5K4AA_GLOBAL_GAIN__, 0x0f, 0x00}, - {SENSOR, S5K4AA_GAIN_1, 0x0b, 0x00}, - {SENSOR, S5K4AA_GAIN_2, 0xa0, 0x00} + {SENSOR, S5K4AA_GAIN_1, 0x10, 0x00}, }; #endif -- cgit v1.2.3 From 81dcc91ec72ff9b0b3464d46ab0965f53e4499e7 Mon Sep 17 00:00:00 2001 From: Erik Andr?n Date: Tue, 13 Jan 2009 20:40:28 +0100 Subject: gspca - m5602-s5k4aa: Add noise suppression ctrl From: Erik Andr?n Priority: normal Signed-off-by: Erik Andr?n --- .../drivers/media/video/gspca/m5602/m5602_s5k4aa.c | 54 ++++++++++++++++++++-- .../drivers/media/video/gspca/m5602/m5602_s5k4aa.h | 1 + .../drivers/media/video/gspca/m5602/m5602_sensor.h | 1 + 3 files changed, 52 insertions(+), 4 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c b/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c index cd856ef8d..b21f2e0b4 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c @@ -26,6 +26,8 @@ static int s5k4aa_get_hflip(struct gspca_dev *gspca_dev, __s32 *val); static int s5k4aa_set_hflip(struct gspca_dev *gspca_dev, __s32 val); static int s5k4aa_get_gain(struct gspca_dev *gspca_dev, __s32 *val); static int s5k4aa_set_gain(struct gspca_dev *gspca_dev, __s32 val); +static int s5k4aa_get_noise(struct gspca_dev *gspca_dev, __s32 *val); +static int s5k4aa_set_noise(struct gspca_dev *gspca_dev, __s32 val); static #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24) @@ -133,7 +135,21 @@ const static struct ctrl s5k4aa_ctrls[] = { }, .set = s5k4aa_set_exposure, .get = s5k4aa_get_exposure - } + }, +#define NOISE_SUPP_IDX 4 + { + { + .id = V4L2_CID_PRIVATE_BASE, + .type = V4L2_CTRL_TYPE_BOOLEAN, + .name = "Noise suppression (smoothing)", + .minimum = 0, + .maximum = 1, + .step = 1, + .default_value = 1, + }, + .set = s5k4aa_set_noise, + .get = s5k4aa_get_noise + }, }; static void s5k4aa_dump_registers(struct sd *sd); @@ -306,13 +322,15 @@ int s5k4aa_init(struct sd *sd) if (err < 0) return err; - err = s5k4aa_set_vflip(&sd->gspca_dev, sensor_settings[VFLIP_IDX]); + err = s5k4aa_set_noise(&sd->gspca_dev, sensor_settings[NOISE_SUPP_IDX]); if (err < 0) return err; - err = s5k4aa_set_hflip(&sd->gspca_dev, sensor_settings[HFLIP_IDX]); + err = s5k4aa_set_vflip(&sd->gspca_dev, sensor_settings[VFLIP_IDX]); + if (err < 0) + return err; - return err; + return s5k4aa_set_hflip(&sd->gspca_dev, sensor_settings[HFLIP_IDX]); } static int s5k4aa_get_exposure(struct gspca_dev *gspca_dev, __s32 *val) @@ -497,6 +515,34 @@ static int s5k4aa_set_gain(struct gspca_dev *gspca_dev, __s32 val) return err; } +static int s5k4aa_get_noise(struct gspca_dev *gspca_dev, __s32 *val) +{ + struct sd *sd = (struct sd *) gspca_dev; + s32 *sensor_settings = sd->sensor_priv; + + *val = sensor_settings[NOISE_SUPP_IDX]; + PDEBUG(D_V4L2, "Read noise %d", *val); + return 0; +} + +static int s5k4aa_set_noise(struct gspca_dev *gspca_dev, __s32 val) +{ + struct sd *sd = (struct sd *) gspca_dev; + s32 *sensor_settings = sd->sensor_priv; + u8 data = S5K4AA_PAGE_MAP_2; + int err; + + sensor_settings[NOISE_SUPP_IDX] = val; + + PDEBUG(D_V4L2, "Set noise to %d", val); + err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1); + if (err < 0) + return err; + + data = val & 0x01; + return m5602_write_sensor(sd, S5K4AA_NOISE_SUPP, &data, 1); +} + void s5k4aa_disconnect(struct sd *sd) { sd->sensor = NULL; diff --git a/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.h b/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.h index fbcb9c1e8..8299f216c 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.h @@ -49,6 +49,7 @@ #define S5K4AA_EXPOSURE_LO 0x18 #define S5K4AA_GAIN_1 0x1f /* (digital?) gain : 5 bits */ #define S5K4AA_GAIN_2 0x20 /* (analogue?) gain : 7 bits */ +#define S5K4AA_NOISE_SUPP 0x37 #define S5K4AA_RM_ROW_SKIP_4X 0x08 #define S5K4AA_RM_ROW_SKIP_2X 0x04 diff --git a/linux/drivers/media/video/gspca/m5602/m5602_sensor.h b/linux/drivers/media/video/gspca/m5602/m5602_sensor.h index 5b76b6b62..c3a72117b 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_sensor.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_sensor.h @@ -22,6 +22,7 @@ #include "m5602_bridge.h" #define M5602_V4L2_CID_GREEN_BALANCE (V4L2_CID_PRIVATE_BASE + 0) +#define M5602_V4L2_CID_NOISE_SUPPRESION (V4L2_CID_PRIVATE_BASE + 1) /* Enumerates all supported sensors */ enum sensors { -- cgit v1.2.3 From 5432c866197d81e8af8579d9865ba47d770d44bc Mon Sep 17 00:00:00 2001 From: Erik Andr?n Date: Wed, 14 Jan 2009 07:37:03 +0100 Subject: gspca - m5602-s5k4aa: Add brightness v4l2 ctrl From: Erik Andr?n Priority: normal Signed-off-by: Erik Andr?n --- .../drivers/media/video/gspca/m5602/m5602_s5k4aa.c | 54 +++++++++++++++++++++- .../drivers/media/video/gspca/m5602/m5602_s5k4aa.h | 8 ++-- 2 files changed, 56 insertions(+), 6 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c b/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c index b21f2e0b4..06da4b3ed 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c @@ -28,6 +28,8 @@ static int s5k4aa_get_gain(struct gspca_dev *gspca_dev, __s32 *val); static int s5k4aa_set_gain(struct gspca_dev *gspca_dev, __s32 val); static int s5k4aa_get_noise(struct gspca_dev *gspca_dev, __s32 *val); static int s5k4aa_set_noise(struct gspca_dev *gspca_dev, __s32 val); +static int s5k4aa_get_brightness(struct gspca_dev *gspca_dev, __s32 *val); +static int s5k4aa_set_brightness(struct gspca_dev *gspca_dev, __s32 val); static #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24) @@ -115,7 +117,7 @@ const static struct ctrl s5k4aa_ctrls[] = { .minimum = 0, .maximum = 127, .step = 1, - .default_value = DEFAULT_GAIN_2, + .default_value = S5K4AA_DEFAULT_GAIN, .flags = V4L2_CTRL_FLAG_SLIDER }, .set = s5k4aa_set_gain, @@ -150,6 +152,21 @@ const static struct ctrl s5k4aa_ctrls[] = { .set = s5k4aa_set_noise, .get = s5k4aa_get_noise }, +#define BRIGHTNESS_IDX 5 + { + { + .id = V4L2_CID_BRIGHTNESS, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Brightness", + .minimum = 0, + .maximum = 0x1f, + .step = 1, + .default_value = S5K4AA_DEFAULT_BRIGHTNESS, + }, + .set = s5k4aa_set_brightness, + .get = s5k4aa_get_brightness + }, + }; static void s5k4aa_dump_registers(struct sd *sd); @@ -322,6 +339,11 @@ int s5k4aa_init(struct sd *sd) if (err < 0) return err; + err = s5k4aa_set_brightness(&sd->gspca_dev, + sensor_settings[BRIGHTNESS_IDX]); + if (err < 0) + return err; + err = s5k4aa_set_noise(&sd->gspca_dev, sensor_settings[NOISE_SUPP_IDX]); if (err < 0) return err; @@ -510,11 +532,39 @@ static int s5k4aa_set_gain(struct gspca_dev *gspca_dev, __s32 val) return err; data = val & 0xff; - err = m5602_write_sensor(sd, S5K4AA_GAIN_2, &data, 1); + err = m5602_write_sensor(sd, S5K4AA_GAIN, &data, 1); return err; } +static int s5k4aa_get_brightness(struct gspca_dev *gspca_dev, __s32 *val) +{ + struct sd *sd = (struct sd *) gspca_dev; + s32 *sensor_settings = sd->sensor_priv; + + *val = sensor_settings[BRIGHTNESS_IDX]; + PDEBUG(D_V4L2, "Read brightness %d", *val); + return 0; +} + +static int s5k4aa_set_brightness(struct gspca_dev *gspca_dev, __s32 val) +{ + struct sd *sd = (struct sd *) gspca_dev; + s32 *sensor_settings = sd->sensor_priv; + u8 data = S5K4AA_PAGE_MAP_2; + int err; + + sensor_settings[BRIGHTNESS_IDX] = val; + + PDEBUG(D_V4L2, "Set brightness to %d", val); + err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1); + if (err < 0) + return err; + + data = val & 0xff; + return m5602_write_sensor(sd, S5K4AA_BRIGHTNESS, &data, 1); +} + static int s5k4aa_get_noise(struct gspca_dev *gspca_dev, __s32 *val) { struct sd *sd = (struct sd *) gspca_dev; diff --git a/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.h b/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.h index 8299f216c..2349174ad 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.h @@ -47,8 +47,8 @@ #define S5K4AA_H_BLANK_LO__ 0x1e #define S5K4AA_EXPOSURE_HI 0x17 #define S5K4AA_EXPOSURE_LO 0x18 -#define S5K4AA_GAIN_1 0x1f /* (digital?) gain : 5 bits */ -#define S5K4AA_GAIN_2 0x20 /* (analogue?) gain : 7 bits */ +#define S5K4AA_BRIGHTNESS 0x1f /* (digital?) gain : 5 bits */ +#define S5K4AA_GAIN 0x20 /* (analogue?) gain : 7 bits */ #define S5K4AA_NOISE_SUPP 0x37 #define S5K4AA_RM_ROW_SKIP_4X 0x08 @@ -58,7 +58,8 @@ #define S5K4AA_RM_H_FLIP 0x40 #define S5K4AA_RM_V_FLIP 0x80 -#define DEFAULT_GAIN_2 0x5f +#define S5K4AA_DEFAULT_GAIN 0x5f +#define S5K4AA_DEFAULT_BRIGHTNESS 0x10 /*****************************************************************************/ @@ -303,7 +304,6 @@ static const unsigned char VGA_s5k4aa[][4] = {SENSOR, 0x12, 0xc3, 0x00}, {SENSOR, S5K4AA_PAGE_MAP, 0x02, 0x00}, {SENSOR, 0x02, 0x0e, 0x00}, - {SENSOR, S5K4AA_GAIN_1, 0x10, 0x00}, }; #endif -- cgit v1.2.3 From be1a0962a6ab828e2487dbb2e72c0c492b33e372 Mon Sep 17 00:00:00 2001 From: Erik Andr?n Date: Thu, 15 Jan 2009 07:40:01 +0100 Subject: gspca - m5602-po1030: Clean up some comments From: Erik Andr?n Priority: normal Signed-off-by: Erik Andr?n --- linux/drivers/media/video/gspca/m5602/m5602_po1030.h | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/m5602/m5602_po1030.h b/linux/drivers/media/video/gspca/m5602/m5602_po1030.h index 0b2dab038..98ef9d05e 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_po1030.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_po1030.h @@ -219,7 +219,6 @@ static const unsigned char init_po1030[][3] = static const unsigned char start_po1030[][3] = { - /*sequence 4*/ {BRIDGE, M5602_XB_GPIO_DIR, 0x05}, {BRIDGE, M5602_XB_GPIO_DAT, 0x00}, {BRIDGE, M5602_XB_GPIO_EN_H, 0x06}, @@ -253,7 +252,7 @@ static const unsigned char start_po1030[][3] = {SENSOR, PO1030_OUTFORMCTRL2, PO1030_RAW_RGB_BAYER}, {SENSOR, PO1030_AUTOCTRL1, PO1030_WEIGHT_WIN_2X}, - /* This makes no sense, hflip and vflp is located at bit 7, 6 */ + {SENSOR, PO1030_CONTROL2, 0x03}, {SENSOR, 0x21, 0x90}, {SENSOR, PO1030_YTARGET, 0x60}, @@ -269,8 +268,6 @@ static const unsigned char start_po1030[][3] = {SENSOR, PO1030_CONTROL1, PO1030_SHUTTER_MODE | PO1030_AUTO_SUBSAMPLING | PO1030_FRAME_EQUAL}, - {SENSOR, PO1030_GREEN_1_GAIN, 0x30}, - {SENSOR, PO1030_GREEN_2_GAIN, 0x30}, {SENSOR, PO1030_GC0, 0x10}, {SENSOR, PO1030_GC1, 0x20}, {SENSOR, PO1030_GC2, 0x40}, @@ -279,9 +276,7 @@ static const unsigned char start_po1030[][3] = {SENSOR, PO1030_GC5, 0xa0}, {SENSOR, PO1030_GC6, 0xc0}, {SENSOR, PO1030_GC7, 0xff}, - /*end of sequence 4*/ - /*sequence 5*/ {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06}, {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0}, {BRIDGE, M5602_XB_ADC_CTRL, 0xc0}, @@ -304,8 +299,6 @@ static const unsigned char start_po1030[][3] = {BRIDGE, M5602_XB_HSYNC_PARA, 0x02}, {BRIDGE, M5602_XB_HSYNC_PARA, 0x7e}, {BRIDGE, M5602_XB_SIG_INI, 0x00}, - /*end of sequence 5*/ - /*sequence 6*/ /* with a very low lighted environment increase the exposure but * decrease the FPS (Frame Per Second) */ -- cgit v1.2.3 From 0d279bbfcf3b99473811cd64982fdcaefe5de8e2 Mon Sep 17 00:00:00 2001 From: Erik Andr?n Date: Thu, 15 Jan 2009 07:52:08 +0100 Subject: gspca - m5602-po1030: Move some code from the start vector to the init vector From: Erik Andr?n This is a prepatory patch in order to support multiple resolutions for the po1030 sensor Priority: normal Signed-off-by: Erik Andr?n --- .../drivers/media/video/gspca/m5602/m5602_po1030.h | 76 +++++++++++----------- 1 file changed, 37 insertions(+), 39 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/m5602/m5602_po1030.h b/linux/drivers/media/video/gspca/m5602/m5602_po1030.h index 98ef9d05e..fb0accfa7 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_po1030.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_po1030.h @@ -215,40 +215,6 @@ static const unsigned char init_po1030[][3] = {BRIDGE, M5602_XB_GPIO_DAT, 0x00}, {SENSOR, PO1030_AUTOCTRL2, 0x04}, -}; - -static const unsigned char start_po1030[][3] = -{ - {BRIDGE, M5602_XB_GPIO_DIR, 0x05}, - {BRIDGE, M5602_XB_GPIO_DAT, 0x00}, - {BRIDGE, M5602_XB_GPIO_EN_H, 0x06}, - {BRIDGE, M5602_XB_GPIO_EN_L, 0x00}, - - {SENSOR, PO1030_AUTOCTRL2, 0x04}, - - /* Set the width to 751 */ - {SENSOR, PO1030_FRAMEWIDTH_H, 0x02}, - {SENSOR, PO1030_FRAMEWIDTH_L, 0xef}, - - /* Set the height to 540 */ - {SENSOR, PO1030_FRAMEHEIGHT_H, 0x02}, - {SENSOR, PO1030_FRAMEHEIGHT_L, 0x1c}, - - /* Set the x window to 1 */ - {SENSOR, PO1030_WINDOWX_H, 0x00}, - {SENSOR, PO1030_WINDOWX_L, 0x01}, - - /* Set the y window to 1 */ - {SENSOR, PO1030_WINDOWY_H, 0x00}, - {SENSOR, PO1030_WINDOWY_L, 0x01}, - - /* Set the window width to 647 */ - {SENSOR, PO1030_WINDOWWIDTH_H, 0x02}, - {SENSOR, PO1030_WINDOWWIDTH_L, 0x87}, - - /* Set the window height to 483 */ - {SENSOR, PO1030_WINDOWHEIGHT_H, 0x01}, - {SENSOR, PO1030_WINDOWHEIGHT_L, 0xe3}, {SENSOR, PO1030_OUTFORMCTRL2, PO1030_RAW_RGB_BAYER}, {SENSOR, PO1030_AUTOCTRL1, PO1030_WEIGHT_WIN_2X}, @@ -277,6 +243,43 @@ static const unsigned char start_po1030[][3] = {SENSOR, PO1030_GC6, 0xc0}, {SENSOR, PO1030_GC7, 0xff}, + /* Set the width to 751 */ + {SENSOR, PO1030_FRAMEWIDTH_H, 0x02}, + {SENSOR, PO1030_FRAMEWIDTH_L, 0xef}, + + /* Set the height to 540 */ + {SENSOR, PO1030_FRAMEHEIGHT_H, 0x02}, + {SENSOR, PO1030_FRAMEHEIGHT_L, 0x1c}, + + /* Set the x window to 1 */ + {SENSOR, PO1030_WINDOWX_H, 0x00}, + {SENSOR, PO1030_WINDOWX_L, 0x01}, + + /* Set the y window to 1 */ + {SENSOR, PO1030_WINDOWY_H, 0x00}, + {SENSOR, PO1030_WINDOWY_L, 0x01}, + + /* with a very low lighted environment increase the exposure but + * decrease the FPS (Frame Per Second) */ + {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00}, + {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0}, + + {BRIDGE, M5602_XB_GPIO_DIR, 0x05}, + {BRIDGE, M5602_XB_GPIO_DAT, 0x00}, + {BRIDGE, M5602_XB_GPIO_EN_H, 0x06}, + {BRIDGE, M5602_XB_GPIO_EN_L, 0x00}, +}; + +static const unsigned char start_po1030[][3] = +{ + /* Set the window width to 647 */ + {SENSOR, PO1030_WINDOWWIDTH_H, 0x02}, + {SENSOR, PO1030_WINDOWWIDTH_L, 0x87}, + + /* Set the window height to 483 */ + {SENSOR, PO1030_WINDOWHEIGHT_H, 0x01}, + {SENSOR, PO1030_WINDOWHEIGHT_L, 0xe3}, + {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06}, {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0}, {BRIDGE, M5602_XB_ADC_CTRL, 0xc0}, @@ -299,11 +302,6 @@ static const unsigned char start_po1030[][3] = {BRIDGE, M5602_XB_HSYNC_PARA, 0x02}, {BRIDGE, M5602_XB_HSYNC_PARA, 0x7e}, {BRIDGE, M5602_XB_SIG_INI, 0x00}, - - /* with a very low lighted environment increase the exposure but - * decrease the FPS (Frame Per Second) */ - {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00}, - {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0}, }; #endif -- cgit v1.2.3 From bad672aa254ea85d9bee65a66d738bc3499f29f3 Mon Sep 17 00:00:00 2001 From: Erik Andr?n Date: Thu, 15 Jan 2009 17:39:39 +0100 Subject: gspca - m5602-po1030: Setup window per resolution From: Erik Andr?n This patch for the po1030 sets the drawing window for the VGA resolution Priority: normal Signed-off-by: Erik Andr?n --- .../drivers/media/video/gspca/m5602/m5602_po1030.c | 29 +++++++++++++++++++++- .../drivers/media/video/gspca/m5602/m5602_po1030.h | 11 -------- 2 files changed, 28 insertions(+), 12 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/m5602/m5602_po1030.c b/linux/drivers/media/video/gspca/m5602/m5602_po1030.c index ee8e49609..af0e93745 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_po1030.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_po1030.c @@ -321,7 +321,34 @@ int po1030_init(struct sd *sd) int po1030_start(struct sd *sd) { + struct cam *cam = &sd->gspca_dev.cam; int i, err = 0; + int width = cam->cam_mode[sd->gspca_dev.curr_mode].width; + int height = cam->cam_mode[sd->gspca_dev.curr_mode].height; + u8 data; + + switch (width) { + case 640: + data = ((width + 7) >> 8) & 0xff; + err = m5602_write_sensor(sd, PO1030_WINDOWWIDTH_H, &data, 1); + if (err < 0) + return err; + + data = (width + 7) & 0xff; + err = m5602_write_sensor(sd, PO1030_WINDOWWIDTH_L, &data, 1); + if (err < 0) + return err; + + data = ((height + 3) >> 8) & 0xff; + err = m5602_write_sensor(sd, PO1030_WINDOWHEIGHT_H, &data, 1); + if (err < 0) + return err; + + data = (height + 3) & 0xff; + err = m5602_write_sensor(sd, PO1030_WINDOWHEIGHT_L, &data, 1); + break; + } + /* Synthesize the vsync/hsync setup */ for (i = 0; i < ARRAY_SIZE(start_po1030) && !err; i++) { if (start_po1030[i][0] == BRIDGE) @@ -330,7 +357,7 @@ int po1030_start(struct sd *sd) else if (start_po1030[i][0] == SENSOR) { u8 data = start_po1030[i][2]; err = m5602_write_sensor(sd, - start_po1030[i][1], &data, 1); + start_po1030[i][1], &data, 1); } } return err; diff --git a/linux/drivers/media/video/gspca/m5602/m5602_po1030.h b/linux/drivers/media/video/gspca/m5602/m5602_po1030.h index fb0accfa7..b47f590ef 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_po1030.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_po1030.h @@ -272,17 +272,6 @@ static const unsigned char init_po1030[][3] = static const unsigned char start_po1030[][3] = { - /* Set the window width to 647 */ - {SENSOR, PO1030_WINDOWWIDTH_H, 0x02}, - {SENSOR, PO1030_WINDOWWIDTH_L, 0x87}, - - /* Set the window height to 483 */ - {SENSOR, PO1030_WINDOWHEIGHT_H, 0x01}, - {SENSOR, PO1030_WINDOWHEIGHT_L, 0xe3}, - - {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06}, - {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0}, - {BRIDGE, M5602_XB_ADC_CTRL, 0xc0}, {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0c}, {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81}, {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82}, -- cgit v1.2.3 From a0cab2a84e16e82ddcac20bdf2773ab1c8ab01c1 Mon Sep 17 00:00:00 2001 From: Erik Andr?n Date: Thu, 15 Jan 2009 18:05:35 +0100 Subject: gspca - m5602-po1030: Synthesize the hsync/vsync setup From: Erik Andr?n Priority: normal Signed-off-by: Erik Andr?n --- .../drivers/media/video/gspca/m5602/m5602_po1030.c | 59 +++++++++++++++++----- .../drivers/media/video/gspca/m5602/m5602_po1030.h | 23 --------- 2 files changed, 47 insertions(+), 35 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/m5602/m5602_po1030.c b/linux/drivers/media/video/gspca/m5602/m5602_po1030.c index af0e93745..d75b27221 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_po1030.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_po1030.c @@ -50,7 +50,7 @@ static struct v4l2_pix_format po1030_modes[] = { .sizeimage = 640 * 480, .bytesperline = 640, .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 0 + .priv = 2 } }; @@ -325,6 +325,7 @@ int po1030_start(struct sd *sd) int i, err = 0; int width = cam->cam_mode[sd->gspca_dev.curr_mode].width; int height = cam->cam_mode[sd->gspca_dev.curr_mode].height; + int ver_offs = cam->cam_mode[sd->gspca_dev.curr_mode].priv; u8 data; switch (width) { @@ -346,20 +347,54 @@ int po1030_start(struct sd *sd) data = (height + 3) & 0xff; err = m5602_write_sensor(sd, PO1030_WINDOWHEIGHT_L, &data, 1); + + height += 12; + width -= 2; break; } - /* Synthesize the vsync/hsync setup */ - for (i = 0; i < ARRAY_SIZE(start_po1030) && !err; i++) { - if (start_po1030[i][0] == BRIDGE) - err = m5602_write_bridge(sd, start_po1030[i][1], - start_po1030[i][2]); - else if (start_po1030[i][0] == SENSOR) { - u8 data = start_po1030[i][2]; - err = m5602_write_sensor(sd, - start_po1030[i][1], &data, 1); - } - } + err = m5602_write_bridge(sd, M5602_XB_LINE_OF_FRAME_H, 0x81); + if (err < 0) + return err; + + err = m5602_write_bridge(sd, M5602_XB_PIX_OF_LINE_H, 0x82); + if (err < 0) + return err; + + err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, + ((ver_offs >> 8) & 0xff)); + if (err < 0) + return err; + + err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, (ver_offs & 0xff)); + if (err < 0) + return err; + + err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, 0); + if (err < 0) + return err; + + err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, (height >> 8) & 0xff); + if (err < 0) + return err; + + err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, (height & 0xff)); + if (err < 0) + return err; + + for (i = 0; i < 2 && !err; i++) + err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, 0); + + for (i = 0; i < 2 && !err; i++) + err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA, 0); + if (err < 0) + return err; + + err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA, (width >> 8) & 0xff); + if (err < 0) + return err; + + err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA, (width & 0xff)); return err; } diff --git a/linux/drivers/media/video/gspca/m5602/m5602_po1030.h b/linux/drivers/media/video/gspca/m5602/m5602_po1030.h index b47f590ef..8ded84d20 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_po1030.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_po1030.h @@ -270,27 +270,4 @@ static const unsigned char init_po1030[][3] = {BRIDGE, M5602_XB_GPIO_EN_L, 0x00}, }; -static const unsigned char start_po1030[][3] = -{ - {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0c}, - {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81}, - {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82}, - {BRIDGE, M5602_XB_SIG_INI, 0x01}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x02}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x01}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0xec}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, - {BRIDGE, M5602_XB_SIG_INI, 0x00}, - {BRIDGE, M5602_XB_SIG_INI, 0x00}, - {BRIDGE, M5602_XB_HSYNC_PARA, 0x00}, - {BRIDGE, M5602_XB_HSYNC_PARA, 0x00}, - {BRIDGE, M5602_XB_HSYNC_PARA, 0x02}, - {BRIDGE, M5602_XB_HSYNC_PARA, 0x7e}, - {BRIDGE, M5602_XB_SIG_INI, 0x00}, -}; - #endif -- cgit v1.2.3 From 34b6351b97b8c11c0b43a0e24bf4f547b95eae50 Mon Sep 17 00:00:00 2001 From: Erik Andr?n Date: Thu, 15 Jan 2009 18:18:36 +0100 Subject: gspca - m5602-po1030: Add experimental QVGA support From: Erik Andr?n Adds experimental support for QVGA. This is code is compile tested only. Priority: normal Signed-off-by: Erik Andr?n --- .../drivers/media/video/gspca/m5602/m5602_po1030.c | 42 ++++++++++++++++++++++ .../drivers/media/video/gspca/m5602/m5602_po1030.h | 2 ++ 2 files changed, 44 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/m5602/m5602_po1030.c b/linux/drivers/media/video/gspca/m5602/m5602_po1030.c index d75b27221..9e9eed89e 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_po1030.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_po1030.c @@ -43,6 +43,15 @@ static int po1030_get_auto_exposure(struct gspca_dev *gspca_dev, static struct v4l2_pix_format po1030_modes[] = { { + 320, + 240, + V4L2_PIX_FMT_SBGGR8, + V4L2_FIELD_NONE, + .sizeimage = 320 * 240, + .bytesperline = 320, + .colorspace = V4L2_COLORSPACE_SRGB, + .priv = 2 + }, { 640, 480, V4L2_PIX_FMT_SBGGR8, @@ -329,7 +338,40 @@ int po1030_start(struct sd *sd) u8 data; switch (width) { + case 320: + data = PO1030_SUBSAMPLING; + err = m5602_write_sensor(sd, PO1030_CONTROL3, &data, 1); + if (err < 0) + return err; + + data = ((width + 3) >> 8) & 0xff; + err = m5602_write_sensor(sd, PO1030_WINDOWWIDTH_H, &data, 1); + if (err < 0) + return err; + + data = (width + 3) & 0xff; + err = m5602_write_sensor(sd, PO1030_WINDOWWIDTH_L, &data, 1); + if (err < 0) + return err; + + data = ((height + 1) >> 8) & 0xff; + err = m5602_write_sensor(sd, PO1030_WINDOWHEIGHT_H, &data, 1); + if (err < 0) + return err; + + data = (height + 1) & 0xff; + err = m5602_write_sensor(sd, PO1030_WINDOWHEIGHT_L, &data, 1); + + height += 6; + width -= 1; + break; + case 640: + data = 0; + err = m5602_write_sensor(sd, PO1030_CONTROL3, &data, 1); + if (err < 0) + return err; + data = ((width + 7) >> 8) & 0xff; err = m5602_write_sensor(sd, PO1030_WINDOWWIDTH_H, &data, 1); if (err < 0) diff --git a/linux/drivers/media/video/gspca/m5602/m5602_po1030.h b/linux/drivers/media/video/gspca/m5602/m5602_po1030.h index 8ded84d20..1ea380b2b 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_po1030.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_po1030.h @@ -133,6 +133,8 @@ #define PO1030_SENSOR_RESET (1 << 5) +#define PO1030_SUBSAMPLING (1 << 6) + /*****************************************************************************/ #define PO1030_GLOBAL_GAIN_DEFAULT 0x12 -- cgit v1.2.3 From c4d8c702fced188accdc9581c1eb3f1d11e384be Mon Sep 17 00:00:00 2001 From: Erik Andr?n Date: Fri, 16 Jan 2009 07:48:15 +0100 Subject: gspca - m5602-po1030: Impove the bridge vsync/hsync configuration From: Erik Andr?n Priority: normal Signed-off-by: Erik Andr?n --- .../drivers/media/video/gspca/m5602/m5602_po1030.c | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/m5602/m5602_po1030.c b/linux/drivers/media/video/gspca/m5602/m5602_po1030.c index 9e9eed89e..5b9113325 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_po1030.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_po1030.c @@ -367,11 +367,6 @@ int po1030_start(struct sd *sd) break; case 640: - data = 0; - err = m5602_write_sensor(sd, PO1030_CONTROL3, &data, 1); - if (err < 0) - return err; - data = ((width + 7) >> 8) & 0xff; err = m5602_write_sensor(sd, PO1030_WINDOWWIDTH_H, &data, 1); if (err < 0) @@ -394,6 +389,9 @@ int po1030_start(struct sd *sd) width -= 2; break; } + err = m5602_write_bridge(sd, M5602_XB_SENSOR_TYPE, 0x0c); + if (err < 0) + return err; err = m5602_write_bridge(sd, M5602_XB_LINE_OF_FRAME_H, 0x81); if (err < 0) @@ -403,6 +401,10 @@ int po1030_start(struct sd *sd) if (err < 0) return err; + err = m5602_write_bridge(sd, M5602_XB_SIG_INI, 0x01); + if (err < 0) + return err; + err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, ((ver_offs >> 8) & 0xff)); if (err < 0) @@ -412,7 +414,8 @@ int po1030_start(struct sd *sd) if (err < 0) return err; - err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, 0); + for (i = 0; i < 2 && !err; i++) + err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, 0); if (err < 0) return err; @@ -427,6 +430,9 @@ int po1030_start(struct sd *sd) for (i = 0; i < 2 && !err; i++) err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, 0); + for (i = 0; i < 2 && !err; i++) + err = m5602_write_bridge(sd, M5602_XB_SIG_INI, 0); + for (i = 0; i < 2 && !err; i++) err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA, 0); if (err < 0) @@ -437,6 +443,10 @@ int po1030_start(struct sd *sd) return err; err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA, (width & 0xff)); + if (err < 0) + return err; + + err = m5602_write_bridge(sd, M5602_XB_SIG_INI, 0); return err; } -- cgit v1.2.3 From 6551d52f93852d6c9d0d6f369fc2778b4ddc594b Mon Sep 17 00:00:00 2001 From: Erik Andr?n Date: Sun, 18 Jan 2009 15:13:47 +0100 Subject: gspca - m5602-po1030: Clear subsampling flag when setting VGA mode From: Erik Andr?n Priority: normal Signed-off-by: Erik Andr?n --- linux/drivers/media/video/gspca/m5602/m5602_po1030.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/m5602/m5602_po1030.c b/linux/drivers/media/video/gspca/m5602/m5602_po1030.c index 5b9113325..840a3ca53 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_po1030.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_po1030.c @@ -367,6 +367,11 @@ int po1030_start(struct sd *sd) break; case 640: + data = 0; + err = m5602_write_sensor(sd, PO1030_CONTROL3, &data, 1); + if (err < 0) + return err; + data = ((width + 7) >> 8) & 0xff; err = m5602_write_sensor(sd, PO1030_WINDOWWIDTH_H, &data, 1); if (err < 0) -- cgit v1.2.3 From cf3b00abbf2245ed507d3487203c9be334ef1fcc Mon Sep 17 00:00:00 2001 From: Erik Andr?n Date: Sun, 18 Jan 2009 19:21:07 +0100 Subject: gscpa - m5602-ov9650: Add defines for some magic constants From: Erik Andr?n Replaces some magic constants with the defines. Remove a couple of bits that should be set later in the process depending on the v4l2 ctrl. Priority: normal Signed-off-by: Erik Andr?n --- linux/drivers/media/video/gspca/m5602/m5602_ov9650.h | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.h b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.h index e0ba41870..27fe54204 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.h @@ -120,6 +120,10 @@ #define OV9650_SOFT_SLEEP (1 << 4) #define OV9650_OUTPUT_DRIVE_2X (1 << 0) +#define OV9650_DENOISE_ENABLE (1 << 5) +#define OV9650_WHITE_PIXEL_ENABLE (1 << 1) +#define OV9650_WHITE_PIXEL_OPTION (1 << 0) + #define OV9650_LEFT_OFFSET 0x62 #define GAIN_DEFAULT 0x14 @@ -198,7 +202,7 @@ static const unsigned char init_ov9650[][3] = /* Reset chip */ {SENSOR, OV9650_COM7, OV9650_REGISTER_RESET}, /* One extra reset is needed in order to make the sensor behave - properly when resuming from ram */ + properly when resuming from ram, could be a timing issue */ {SENSOR, OV9650_COM7, OV9650_REGISTER_RESET}, /* Enable double clock */ @@ -208,8 +212,7 @@ static const unsigned char init_ov9650[][3] = /* Set fast AGC/AEC algorithm with unlimited step size */ {SENSOR, OV9650_COM8, OV9650_FAST_AGC_AEC | - OV9650_AEC_UNLIM_STEP_SIZE | - OV9650_AWB_EN | OV9650_AGC_EN}, + OV9650_AEC_UNLIM_STEP_SIZE}, {SENSOR, OV9650_CHLF, 0x10}, {SENSOR, OV9650_ARBLM, 0xbf}, @@ -280,8 +283,11 @@ static const unsigned char init_ov9650[][3] = {SENSOR, OV9650_VREF, 0x10}, {SENSOR, OV9650_ADC, 0x04}, {SENSOR, OV9650_HV, 0x40}, + /* Enable denoise, and white-pixel erase */ - {SENSOR, OV9650_COM22, 0x23}, + {SENSOR, OV9650_COM22, OV9650_DENOISE_ENABLE | + OV9650_WHITE_PIXEL_ENABLE | + OV9650_WHITE_PIXEL_OPTION}, /* Enable VARIOPIXEL */ {SENSOR, OV9650_COM3, OV9650_VARIOPIXEL}, -- cgit v1.2.3 From efa0fa9346bc7dd58e925951e9dae18a0aed1f34 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Sun, 18 Jan 2009 23:10:49 -0500 Subject: saa7134: enable digital tv support for Hauppauge WinTV-HVR1120 From: Michael Krufky Priority: normal Signed-off-by: Michael Krufky --- linux/drivers/media/video/saa7134/Kconfig | 3 ++ linux/drivers/media/video/saa7134/saa7134-cards.c | 4 ++- linux/drivers/media/video/saa7134/saa7134-dvb.c | 44 +++++++++++++++++++++++ 3 files changed, 50 insertions(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/saa7134/Kconfig b/linux/drivers/media/video/saa7134/Kconfig index 51f17c82b..e62b29967 100644 --- a/linux/drivers/media/video/saa7134/Kconfig +++ b/linux/drivers/media/video/saa7134/Kconfig @@ -42,6 +42,9 @@ config VIDEO_SAA7134_DVB select DVB_MT312 if !DVB_FE_CUSTOMISE select DVB_LNBP21 if !DVB_FE_CUSTOMISE select DVB_ZL10353 if !DVB_FE_CUSTOMISE + select DVB_LGDT3305 if !DVB_FE_CUSTOMISE + select MEDIA_TUNER_TDA18271 if !MEDIA_TUNER_CUSTOMIZE + select MEDIA_TUNER_TDA8290 if !MEDIA_TUNER_CUSTOMIZE ---help--- This adds support for DVB cards based on the Philips saa7134 chip. diff --git a/linux/drivers/media/video/saa7134/saa7134-cards.c b/linux/drivers/media/video/saa7134/saa7134-cards.c index 09697c0f1..e8efc883c 100644 --- a/linux/drivers/media/video/saa7134/saa7134-cards.c +++ b/linux/drivers/media/video/saa7134/saa7134-cards.c @@ -3332,13 +3332,15 @@ struct saa7134_board saa7134_boards[] = { }, }, [SAA7134_BOARD_HAUPPAUGE_HVR1120] = { - .name = "Hauppauge WinTV-HVR1120", + .name = "Hauppauge WinTV-HVR1120 ATSC/QAM-Hybrid", .audio_clock = 0x00187de7, .tuner_type = TUNER_PHILIPS_TDA8290, .radio_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .tuner_config = 3, + .mpeg = SAA7134_MPEG_DVB, + .ts_type = SAA7134_MPEG_TS_SERIAL, .gpiomask = 0x0800100, /* GPIO 21 is an INPUT */ .inputs = {{ .name = name_tv, diff --git a/linux/drivers/media/video/saa7134/saa7134-dvb.c b/linux/drivers/media/video/saa7134/saa7134-dvb.c index 7745cad95..085589998 100644 --- a/linux/drivers/media/video/saa7134/saa7134-dvb.c +++ b/linux/drivers/media/video/saa7134/saa7134-dvb.c @@ -48,6 +48,9 @@ #include "isl6405.h" #include "lnbp21.h" #include "tuner-simple.h" +#include "tda18271.h" +#include "lgdt3305.h" +#include "tda8290.h" #include "zl10353.h" @@ -963,6 +966,34 @@ static struct zl10036_config avertv_a700_tuner = { .tuner_address = 0x60, }; +static struct lgdt3305_config hcw_lgdt3305_config = { + .i2c_addr = 0x0e, + .mpeg_mode = LGDT3305_MPEG_SERIAL, + .tpclk_edge = LGDT3305_TPCLK_RISING_EDGE, + .tpvalid_polarity = LGDT3305_TP_VALID_HIGH, + .deny_i2c_rptr = 1, + .spectral_inversion = 1, + .qam_if_khz = 4000, + .vsb_if_khz = 3250, +}; + +static struct tda18271_std_map hauppauge_tda18271_std_map = { + .atsc_6 = { .if_freq = 3250, .agc_mode = 3, .std = 4, + .if_lvl = 1, .rfagc_top = 0x58, }, + .qam_6 = { .if_freq = 4000, .agc_mode = 3, .std = 5, + .if_lvl = 1, .rfagc_top = 0x58, }, +}; + +static struct tda18271_config hcw_tda18271_config = { + .std_map = &hauppauge_tda18271_std_map, + .gate = TDA18271_GATE_ANALOG, + .config = 3, +}; + +static struct tda829x_config tda829x_no_probe = { + .probe_tuner = TDA829X_DONT_PROBE, +}; + /* ================================================================== * Core code */ @@ -1089,6 +1120,19 @@ static int dvb_init(struct saa7134_dev *dev) &tda827x_cfg_1) < 0) goto dettach_frontend; break; + case SAA7134_BOARD_HAUPPAUGE_HVR1120: + fe0->dvb.frontend = dvb_attach(lgdt3305_attach, + &hcw_lgdt3305_config, + &dev->i2c_adap); + if (fe0->dvb.frontend) { + dvb_attach(tda829x_attach, fe0->dvb.frontend, + &dev->i2c_adap, 0x4b, + &tda829x_no_probe); + dvb_attach(tda18271_attach, fe0->dvb.frontend, + 0x60, &dev->i2c_adap, + &hcw_tda18271_config); + } + break; case SAA7134_BOARD_ASUSTeK_P7131_DUAL: if (configure_tda827x_fe(dev, &asus_p7131_dual_config, &tda827x_cfg_0) < 0) -- cgit v1.2.3 From 54b87636a17edc58610c96dbac2b4f7e984c21ec Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Wed, 20 May 2009 15:06:10 -0400 Subject: saa7134: fix quirk in saa7134_i2c_xfer for the saa7131 bridge From: Michael Krufky The i2c quirk in the saa7134_i2c_xfer function does a bogus write to i2c address 0xfd, to work around a bug in the silicon that affects read transactions. Unfortunately, this hack is not working properly, since the bogus write is to 0xfd, an invalid i2c address. Fix this quirk by using an actual valid i2c address, 0xfe, which is still unlikely to be used as an i2c address for any actual i2c client. This is required in order to properly communicate with a TDA10048 DVB-T demod located at i2c address 0x10 on the primary i2c bus. Priority: normal Signed-off-by: Michael Krufky --- linux/drivers/media/video/saa7134/saa7134-i2c.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/saa7134/saa7134-i2c.c b/linux/drivers/media/video/saa7134/saa7134-i2c.c index 3eb60aabe..78f9cac3d 100644 --- a/linux/drivers/media/video/saa7134/saa7134-i2c.c +++ b/linux/drivers/media/video/saa7134/saa7134-i2c.c @@ -264,7 +264,7 @@ static int saa7134_i2c_xfer(struct i2c_adapter *i2c_adap, /* workaround for a saa7134 i2c bug * needed to talk to the mt352 demux * thanks to pinnacle for the hint */ - int quirk = 0xfd; + int quirk = 0xfe; d1printk(" [%02x quirk]",quirk); i2c_send_byte(dev,START,quirk); i2c_recv_byte(dev); -- cgit v1.2.3 From b17aee4b149a0625595ffec502db3a31094bfaec Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Sun, 18 Jan 2009 23:10:49 -0500 Subject: saa7134: enable digital tv support for Hauppauge WinTV-HVR1110r3 From: Michael Krufky Priority: normal Signed-off-by: Michael Krufky --- linux/drivers/media/video/saa7134/Kconfig | 1 + linux/drivers/media/video/saa7134/saa7134-cards.c | 4 +++- linux/drivers/media/video/saa7134/saa7134-dvb.c | 26 +++++++++++++++++++++++ 3 files changed, 30 insertions(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/saa7134/Kconfig b/linux/drivers/media/video/saa7134/Kconfig index 0ba68987b..5bcce092e 100644 --- a/linux/drivers/media/video/saa7134/Kconfig +++ b/linux/drivers/media/video/saa7134/Kconfig @@ -44,6 +44,7 @@ config VIDEO_SAA7134_DVB select DVB_LNBP21 if !DVB_FE_CUSTOMISE select DVB_ZL10353 if !DVB_FE_CUSTOMISE select DVB_LGDT3305 if !DVB_FE_CUSTOMISE + select DVB_TDA10048 if !DVB_FE_CUSTOMISE select MEDIA_TUNER_TDA18271 if !MEDIA_TUNER_CUSTOMISE select MEDIA_TUNER_TDA8290 if !MEDIA_TUNER_CUSTOMISE ---help--- diff --git a/linux/drivers/media/video/saa7134/saa7134-cards.c b/linux/drivers/media/video/saa7134/saa7134-cards.c index a4e3deac2..587209fdd 100644 --- a/linux/drivers/media/video/saa7134/saa7134-cards.c +++ b/linux/drivers/media/video/saa7134/saa7134-cards.c @@ -3403,13 +3403,15 @@ struct saa7134_board saa7134_boards[] = { }, }, [SAA7134_BOARD_HAUPPAUGE_HVR1110R3] = { - .name = "Hauppauge WinTV-HVR1110r3", + .name = "Hauppauge WinTV-HVR1110r3 DVB-T/Hybrid", .audio_clock = 0x00187de7, .tuner_type = TUNER_PHILIPS_TDA8290, .radio_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .tuner_config = 3, + .mpeg = SAA7134_MPEG_DVB, + .ts_type = SAA7134_MPEG_TS_SERIAL, .gpiomask = 0x0800100, /* GPIO 21 is an INPUT */ .inputs = {{ .name = name_tv, diff --git a/linux/drivers/media/video/saa7134/saa7134-dvb.c b/linux/drivers/media/video/saa7134/saa7134-dvb.c index 2e1344ecf..360fbdf19 100644 --- a/linux/drivers/media/video/saa7134/saa7134-dvb.c +++ b/linux/drivers/media/video/saa7134/saa7134-dvb.c @@ -48,6 +48,7 @@ #include "isl6405.h" #include "lnbp21.h" #include "tuner-simple.h" +#include "tda10048.h" #include "tda18271.h" #include "lgdt3305.h" #include "tda8290.h" @@ -978,6 +979,18 @@ static struct lgdt3305_config hcw_lgdt3305_config = { .vsb_if_khz = 3250, }; +static struct tda10048_config hcw_tda10048_config = { + .demod_address = 0x10 >> 1, + .output_mode = TDA10048_SERIAL_OUTPUT, + .fwbulkwritelen = TDA10048_BULKWRITE_200, + .inversion = TDA10048_INVERSION_ON, + .dtv6_if_freq_khz = TDA10048_IF_3300, + .dtv7_if_freq_khz = TDA10048_IF_3500, + .dtv8_if_freq_khz = TDA10048_IF_4000, + .clk_freq_khz = TDA10048_CLK_16000, + .disable_gate_access = 1, +}; + static struct tda18271_std_map hauppauge_tda18271_std_map = { .atsc_6 = { .if_freq = 3250, .agc_mode = 3, .std = 4, .if_lvl = 1, .rfagc_top = 0x58, }, @@ -1106,6 +1119,19 @@ static int dvb_init(struct saa7134_dev *dev) &tda827x_cfg_2) < 0) goto dettach_frontend; break; + case SAA7134_BOARD_HAUPPAUGE_HVR1110R3: + fe0->dvb.frontend = dvb_attach(tda10048_attach, + &hcw_tda10048_config, + &dev->i2c_adap); + if (fe0->dvb.frontend != NULL) { + dvb_attach(tda829x_attach, fe0->dvb.frontend, + &dev->i2c_adap, 0x4b, + &tda829x_no_probe); + dvb_attach(tda18271_attach, fe0->dvb.frontend, + 0x60, &dev->i2c_adap, + &hcw_tda18271_config); + } + break; case SAA7134_BOARD_PHILIPS_TIGER: if (configure_tda827x_fe(dev, &philips_tiger_config, &tda827x_cfg_0) < 0) -- cgit v1.2.3 From ea09aea560cb0eabd0221c64177257a11e3e6d83 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Sun, 18 Jan 2009 23:12:55 -0500 Subject: dib0700: add support for Hauppauge ATSC MiniCard From: Michael Krufky Priority: normal Signed-off-by: Michael Krufky --- linux/drivers/media/dvb/dvb-usb/Kconfig | 2 + linux/drivers/media/dvb/dvb-usb/dib0700_devices.c | 99 +++++++++++++++++++++++ linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h | 2 + 3 files changed, 103 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/dvb-usb/Kconfig b/linux/drivers/media/dvb/dvb-usb/Kconfig index 64fa1d182..b899d509a 100644 --- a/linux/drivers/media/dvb/dvb-usb/Kconfig +++ b/linux/drivers/media/dvb/dvb-usb/Kconfig @@ -73,11 +73,13 @@ config DVB_USB_DIB0700 select DVB_DIB7000M if !DVB_FE_CUSTOMISE select DVB_DIB3000MC if !DVB_FE_CUSTOMISE select DVB_S5H1411 if !DVB_FE_CUSTOMISE + select DVB_LGDT3305 if !DVB_FE_CUSTOMISE select DVB_TUNER_DIB0070 if !DVB_FE_CUSTOMISE select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMIZE select MEDIA_TUNER_MT2266 if !MEDIA_TUNER_CUSTOMIZE select MEDIA_TUNER_XC2028 if !MEDIA_TUNER_CUSTOMIZE select MEDIA_TUNER_XC5000 if !MEDIA_TUNER_CUSTOMIZE + select MEDIA_TUNER_MXL5007T if !MEDIA_TUNER_CUSTOMIZE help Support for USB2.0/1.1 DVB receivers based on the DiB0700 USB bridge. The USB bridge is also present in devices having the DiB7700 DVB-T-USB diff --git a/linux/drivers/media/dvb/dvb-usb/dib0700_devices.c b/linux/drivers/media/dvb/dvb-usb/dib0700_devices.c index 8877215cb..d8901f7a8 100644 --- a/linux/drivers/media/dvb/dvb-usb/dib0700_devices.c +++ b/linux/drivers/media/dvb/dvb-usb/dib0700_devices.c @@ -17,6 +17,8 @@ #include "xc5000.h" #include "s5h1411.h" #include "dib0070.h" +#include "lgdt3305.h" +#include "mxl5007t.h" static int force_lna_activation; module_param(force_lna_activation, int, 0644); @@ -1370,6 +1372,76 @@ static int xc5000_tuner_attach(struct dvb_usb_adapter *adap) == NULL ? -ENODEV : 0; } +static struct lgdt3305_config hcw_lgdt3305_config = { + .i2c_addr = 0x0e, + .mpeg_mode = LGDT3305_MPEG_PARALLEL, + .tpclk_edge = LGDT3305_TPCLK_FALLING_EDGE, + .tpvalid_polarity = LGDT3305_TP_VALID_LOW, + .deny_i2c_rptr = 0, + .spectral_inversion = 1, + .qam_if_khz = 6000, + .vsb_if_khz = 6000, + .usref_8vsb = 0x0500, +}; + +static struct mxl5007t_config hcw_mxl5007t_config = { + .xtal_freq_hz = MxL_XTAL_25_MHZ, + .if_freq_hz = MxL_IF_6_MHZ, + .invert_if = 1, +#if 0 + .loop_thru_enable = 1, + .clk_out_enable = 1, +#endif +}; + +/* TIGER-ATSC map: + GPIO0 - LNA_CTR (H: LNA power enabled, L: LNA power disabled) + GPIO1 - ANT_SEL (H: VPA, L: MCX) + GPIO4 - SCL2 + GPIO6 - EN_TUNER + GPIO7 - SDA2 + GPIO10 - DEM_RST + + MXL is behind LG's i2c repeater. LG is on SCL2/SDA2 gpios on the DIB + */ +static int lgdt3305_frontend_attach(struct dvb_usb_adapter *adap) +{ + struct dib0700_state *st = adap->dev->priv; + + /* Make use of the new i2c functions from FW 1.20 */ + st->fw_use_new_i2c_api = 1; + + st->disable_streaming_master_mode = 1; + + /* fe power enable */ + dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 0); + msleep(30); + dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1); + msleep(30); + + /* demod reset */ + dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1); + msleep(30); + dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 0); + msleep(30); + dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1); + msleep(30); + + adap->fe = dvb_attach(lgdt3305_attach, + &hcw_lgdt3305_config, + &adap->dev->i2c_adap); + + return adap->fe == NULL ? -ENODEV : 0; +} + +static int mxl5007t_tuner_attach(struct dvb_usb_adapter *adap) +{ + return dvb_attach(mxl5007t_attach, adap->fe, + &adap->dev->i2c_adap, 0x60, + &hcw_mxl5007t_config) == NULL ? -ENODEV : 0; +} + + /* DVB-USB and USB stuff follows */ struct usb_device_id dib0700_usb_id_table[] = { /* 0 */ { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_STK7700P) }, @@ -1421,6 +1493,8 @@ struct usb_device_id dib0700_usb_id_table[] = { USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY_2) }, { USB_DEVICE(USB_VID_SONY, USB_PID_SONY_PLAYTV) }, /* 45 */{ USB_DEVICE(USB_VID_YUAN, USB_PID_YUAN_PD378S) }, + { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_TIGER_ATSC) }, + { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_TIGER_ATSC_B210) }, { 0 } /* Terminating entry */ }; MODULE_DEVICE_TABLE(usb, dib0700_usb_id_table); @@ -1796,6 +1870,31 @@ struct dvb_usb_device_properties dib0700_devices[] = { .rc_key_map = dib0700_rc_keys, .rc_key_map_size = ARRAY_SIZE(dib0700_rc_keys), .rc_query = dib0700_rc_query + }, { DIB0700_DEFAULT_DEVICE_PROPERTIES, + .num_adapters = 1, + .adapter = { + { + .frontend_attach = lgdt3305_frontend_attach, + .tuner_attach = mxl5007t_tuner_attach, + + DIB0700_DEFAULT_STREAMING_CONFIG(0x02), + + .size_of_priv = sizeof(struct + dib0700_adapter_state), + }, + }, + + .num_device_descs = 2, + .devices = { + { "Hauppauge ATSC MiniCard (B200)", + { &dib0700_usb_id_table[46], NULL }, + { NULL }, + }, + { "Hauppauge ATSC MiniCard (B210)", + { &dib0700_usb_id_table[47], NULL }, + { NULL }, + }, + }, }, }; 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 6d70576ad..3dfb27174 100644 --- a/linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h +++ b/linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h @@ -151,6 +151,8 @@ #define USB_PID_HAUPPAUGE_MYTV_T 0x7080 #define USB_PID_HAUPPAUGE_NOVA_TD_STICK 0x9580 #define USB_PID_HAUPPAUGE_NOVA_TD_STICK_52009 0x5200 +#define USB_PID_HAUPPAUGE_TIGER_ATSC 0xb200 +#define USB_PID_HAUPPAUGE_TIGER_ATSC_B210 0xb210 #define USB_PID_AVERMEDIA_EXPRESS 0xb568 #define USB_PID_AVERMEDIA_VOLAR 0xa807 #define USB_PID_AVERMEDIA_VOLAR_2 0xb808 -- cgit v1.2.3 From f7e4d336384ca30f8c58afe8286fae922c9a9eac Mon Sep 17 00:00:00 2001 From: Erik Andr?n Date: Mon, 19 Jan 2009 18:02:28 +0100 Subject: gspca - m5602-ov9650: Be more strict during the hsync/vsync synthesis From: Erik Andr?n Priority: normal Signed-off-by: Erik Andr?n --- linux/drivers/media/video/gspca/m5602/m5602_ov9650.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c index d6a666b86..f0e335533 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c @@ -451,6 +451,14 @@ int ov9650_start(struct sd *sd) if (err < 0) return err; + err = m5602_write_bridge(sd, M5602_XB_SIG_INI, 0); + if (err < 0) + return err; + + err = m5602_write_bridge(sd, M5602_XB_SIG_INI, 2); + if (err < 0) + return err; + err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA, (hor_offs >> 8) & 0xff); if (err < 0) @@ -470,6 +478,10 @@ int ov9650_start(struct sd *sd) if (err < 0) return err; + err = m5602_write_bridge(sd, M5602_XB_SIG_INI, 0); + if (err < 0) + return err; + switch (width) { case 640: PDEBUG(D_V4L2, "Configuring camera for VGA mode"); -- cgit v1.2.3 From 312924eff02687357bebf77fb8c9e6d6e8b168a4 Mon Sep 17 00:00:00 2001 From: Erik Andr?n Date: Tue, 20 Jan 2009 07:49:00 +0100 Subject: gspca - m5602-mt9m111: Replace magic constants with defines From: Erik Andr?n Priority: normal Signed-off-by: Erik Andr?n --- linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h b/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h index 217728a24..7bb8ebb86 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h @@ -80,8 +80,12 @@ #define MT9M111_RESTART_BAD_FRAMES (1 << 1) #define MT9M111_SYNCHRONIZE_CHANGES (1 << 7) +#define MT9M111_RMB_OVER_SIZED (1 << 0) #define MT9M111_RMB_MIRROR_ROWS (1 << 0) #define MT9M111_RMB_MIRROR_COLS (1 << 1) +#define MT9M111_RMB_ROW_SKIP_2X (1 << 2) +#define MT9M111_RMB_COLUMN_SKIP_2X (1 << 3) + #define MT9M111_COLOR_MATRIX_BYPASS (1 << 4) #define MT9M111_SEL_CONTEXT_B (1 << 3) @@ -244,7 +248,12 @@ static const unsigned char init_mt9m111[][4] = {SENSOR, MT9M111_SC_VBLANK_CONTEXT_B, 0x00, 0x11}, /* 17 */ {SENSOR, MT9M111_SC_HBLANK_CONTEXT_A, 0x01, 0x60}, /* 352 */ {SENSOR, MT9M111_SC_VBLANK_CONTEXT_A, 0x00, 0x11}, /* 17 */ - {SENSOR, MT9M111_SC_R_MODE_CONTEXT_B, 0x01, 0x0f}, /* 271 */ + {SENSOR, MT9M111_SC_R_MODE_CONTEXT_B, + MT9M111_RMB_OVER_SIZED, + MT9M111_RMB_MIRROR_ROWS | + MT9M111_RMB_MIRROR_COLS | + MT9M111_RMB_ROW_SKIP_2X | + MT9M111_RMB_COLUMN_SKIP_2X}, {SENSOR, MT9M111_SC_R_MODE_CONTEXT_A, 0x01, 0x0f}, /* 271 */ {SENSOR, 0x30, 0x04, 0x00}, /* Set number of blank rows chosen to 400 */ -- cgit v1.2.3 From d92d1df320e850ba703ecb4966b59d3b6bc7a129 Mon Sep 17 00:00:00 2001 From: Erik Andr?n Date: Tue, 20 Jan 2009 07:54:51 +0100 Subject: gspca - m5602-mt9m111: Add a start function From: Erik Andr?n Priority: normal Signed-off-by: Erik Andr?n --- .../drivers/media/video/gspca/m5602/m5602_mt9m111.c | 20 ++++++++++++++++++++ .../drivers/media/video/gspca/m5602/m5602_mt9m111.h | 6 ++++++ 2 files changed, 26 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.c b/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.c index 95b6e95aa..edf502041 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.c @@ -265,6 +265,26 @@ int mt9m111_init(struct sd *sd) return mt9m111_set_gain(&sd->gspca_dev, sensor_settings[GAIN_IDX]); } +int mt9m111_start(struct sd *sd) +{ + int i, err = 0; + u8 data[2]; + + for (i = 0; i < ARRAY_SIZE(start_mt9m111) && !err; i++) { + if (start_mt9m111[i][0] == BRIDGE) { + err = m5602_write_bridge(sd, + start_mt9m111[i][1], + start_mt9m111[i][2]); + } else { + data[0] = start_mt9m111[i][2]; + data[1] = start_mt9m111[i][3]; + err = m5602_write_sensor(sd, + start_mt9m111[i][1], data, 2); + } + } + return err; +} + void mt9m111_disconnect(struct sd *sd) { sd->sensor = NULL; diff --git a/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h b/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h index 7bb8ebb86..6598dd9c4 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h @@ -109,6 +109,7 @@ extern int dump_sensor; int mt9m111_probe(struct sd *sd); int mt9m111_init(struct sd *sd); +int mt9m111_start(struct sd *sd); void mt9m111_disconnect(struct sd *sd); const static struct m5602_sensor mt9m111 = { @@ -120,6 +121,7 @@ const static struct m5602_sensor mt9m111 = { .probe = mt9m111_probe, .init = mt9m111_init, .disconnect = mt9m111_disconnect, + .start = mt9m111_start, }; static const unsigned char preinit_mt9m111[][4] = @@ -258,7 +260,10 @@ static const unsigned char init_mt9m111[][4] = {SENSOR, 0x30, 0x04, 0x00}, /* Set number of blank rows chosen to 400 */ {SENSOR, MT9M111_SC_SHUTTER_WIDTH, 0x01, 0x90}, +}; +static const unsigned char start_mt9m111[][4] = +{ {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06, 0x00}, {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00}, @@ -285,4 +290,5 @@ static const unsigned char init_mt9m111[][4] = {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, }; + #endif -- cgit v1.2.3 From eec79ab73da9af8887bf32700d43e196c74e2ddc Mon Sep 17 00:00:00 2001 From: Erik Andr?n Date: Tue, 20 Jan 2009 08:05:19 +0100 Subject: gspca - m5602-mt9m111: Synthesize the hsync/vsync setup From: Erik Andr?n Priority: normal Signed-off-by: Erik Andr?n --- .../media/video/gspca/m5602/m5602_mt9m111.c | 51 ++++++++++++++++++++++ .../media/video/gspca/m5602/m5602_mt9m111.h | 14 ------ 2 files changed, 51 insertions(+), 14 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.c b/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.c index edf502041..7986ef074 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.c @@ -269,6 +269,10 @@ int mt9m111_start(struct sd *sd) { int i, err = 0; u8 data[2]; + struct cam *cam = &sd->gspca_dev.cam; + + int width = cam->cam_mode[sd->gspca_dev.curr_mode].width; + int height = cam->cam_mode[sd->gspca_dev.curr_mode].height; for (i = 0; i < ARRAY_SIZE(start_mt9m111) && !err; i++) { if (start_mt9m111[i][0] == BRIDGE) { @@ -282,6 +286,53 @@ int mt9m111_start(struct sd *sd) start_mt9m111[i][1], data, 2); } } + if (err < 0) + return err; + + err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, (height >> 8) & 0xff); + if (err < 0) + return err; + + err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, (height & 0xff)); + if (err < 0) + return err; + + for (i = 0; i < 2 && !err; i++) + err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, 0); + if (err < 0) + return err; + + err = m5602_write_bridge(sd, M5602_XB_SIG_INI, 0); + if (err < 0) + return err; + + err = m5602_write_bridge(sd, M5602_XB_SIG_INI, 2); + if (err < 0) + return err; + + for (i = 0; i < 2 && !err; i++) + err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA, 0); + if (err < 0) + return err; + + err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA, + (width >> 8) & 0xff); + if (err < 0) + return err; + + err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA, width & 0xff); + if (err < 0) + return err; + + err = m5602_write_bridge(sd, M5602_XB_SIG_INI, 0); + if (err < 0) + return err; + + switch (width) { + case 640: + PDEBUG(D_V4L2, "Configuring camera for VGA mode"); + break; + } return err; } diff --git a/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h b/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h index 6598dd9c4..7c8c700ba 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h @@ -275,20 +275,6 @@ static const unsigned char start_mt9m111[][4] = {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x01, 0x00}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0xe0, 0x00}, /* 480 */ - {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, - {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00}, - {BRIDGE, M5602_XB_SIG_INI, 0x02, 0x00}, - {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00}, - {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00}, - {BRIDGE, M5602_XB_HSYNC_PARA, 0x02, 0x00}, /* 639*/ - {BRIDGE, M5602_XB_HSYNC_PARA, 0x7f, 0x00}, - {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00}, - {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, - {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, }; - #endif -- cgit v1.2.3 From 9ae69affd3d0f322a1aeb125b84858d358386160 Mon Sep 17 00:00:00 2001 From: Erik Andr?n Date: Tue, 20 Jan 2009 08:13:34 +0100 Subject: gspca - m5602-mt9m111: Setup VGA resolution From: Erik Andr?n Priority: normal Signed-off-by: Erik Andr?n --- linux/drivers/media/video/gspca/m5602/m5602_mt9m111.c | 10 +++++++++- linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h | 7 ------- 2 files changed, 9 insertions(+), 8 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.c b/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.c index 7986ef074..e7399f3d1 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.c @@ -270,8 +270,9 @@ int mt9m111_start(struct sd *sd) int i, err = 0; u8 data[2]; struct cam *cam = &sd->gspca_dev.cam; + s32 *sensor_settings = sd->sensor_priv; - int width = cam->cam_mode[sd->gspca_dev.curr_mode].width; + int width = cam->cam_mode[sd->gspca_dev.curr_mode].width - 1; int height = cam->cam_mode[sd->gspca_dev.curr_mode].height; for (i = 0; i < ARRAY_SIZE(start_mt9m111) && !err; i++) { @@ -331,6 +332,13 @@ int mt9m111_start(struct sd *sd) switch (width) { case 640: PDEBUG(D_V4L2, "Configuring camera for VGA mode"); + data[0] = MT9M111_RMB_OVER_SIZED; + data[1] = MT9M111_RMB_ROW_SKIP_2X | + MT9M111_RMB_COLUMN_SKIP_2X | + (sensor_settings[VFLIP_IDX] << 0) | + (sensor_settings[HFLIP_IDX] << 1); + + err = m5602_write_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B, data, 2); break; } return err; diff --git a/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h b/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h index 7c8c700ba..668422676 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h @@ -86,7 +86,6 @@ #define MT9M111_RMB_ROW_SKIP_2X (1 << 2) #define MT9M111_RMB_COLUMN_SKIP_2X (1 << 3) - #define MT9M111_COLOR_MATRIX_BYPASS (1 << 4) #define MT9M111_SEL_CONTEXT_B (1 << 3) @@ -250,12 +249,6 @@ static const unsigned char init_mt9m111[][4] = {SENSOR, MT9M111_SC_VBLANK_CONTEXT_B, 0x00, 0x11}, /* 17 */ {SENSOR, MT9M111_SC_HBLANK_CONTEXT_A, 0x01, 0x60}, /* 352 */ {SENSOR, MT9M111_SC_VBLANK_CONTEXT_A, 0x00, 0x11}, /* 17 */ - {SENSOR, MT9M111_SC_R_MODE_CONTEXT_B, - MT9M111_RMB_OVER_SIZED, - MT9M111_RMB_MIRROR_ROWS | - MT9M111_RMB_MIRROR_COLS | - MT9M111_RMB_ROW_SKIP_2X | - MT9M111_RMB_COLUMN_SKIP_2X}, {SENSOR, MT9M111_SC_R_MODE_CONTEXT_A, 0x01, 0x0f}, /* 271 */ {SENSOR, 0x30, 0x04, 0x00}, /* Set number of blank rows chosen to 400 */ -- cgit v1.2.3 From 85f3f08688a8e7c02d6646531af94875452cdb76 Mon Sep 17 00:00:00 2001 From: Erik Andr?n Date: Tue, 20 Jan 2009 08:16:28 +0100 Subject: gspca - m5602-mt9m111: Add experimental QVGA support From: Erik Andr?n Priority: normal Signed-off-by: Erik Andr?n --- linux/drivers/media/video/gspca/m5602/m5602_mt9m111.c | 19 +++++++++++++++++++ linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h | 2 ++ 2 files changed, 21 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.c b/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.c index e7399f3d1..54ccc7391 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.c @@ -37,6 +37,15 @@ static int mt9m111_set_red_balance(struct gspca_dev *gspca_dev, __s32 val); static struct v4l2_pix_format mt9m111_modes[] = { { + 320, + 240, + V4L2_PIX_FMT_SBGGR8, + V4L2_FIELD_NONE, + .sizeimage = 320 * 240, + .bytesperline = 320, + .colorspace = V4L2_COLORSPACE_SRGB, + .priv = 0 + }, { 640, 480, V4L2_PIX_FMT_SBGGR8, @@ -340,6 +349,16 @@ int mt9m111_start(struct sd *sd) err = m5602_write_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B, data, 2); break; + + case 320: + PDEBUG(D_V4L2, "Configuring camera for QVGA mode"); + data[0] = MT9M111_RMB_OVER_SIZED; + data[1] = MT9M111_RMB_ROW_SKIP_4X | + MT9M111_RMB_COLUMN_SKIP_4X | + (sensor_settings[VFLIP_IDX] << 0) | + (sensor_settings[HFLIP_IDX] << 1); + err = m5602_write_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B, data, 2); + break; } return err; } diff --git a/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h b/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h index 668422676..716aba523 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h @@ -85,6 +85,8 @@ #define MT9M111_RMB_MIRROR_COLS (1 << 1) #define MT9M111_RMB_ROW_SKIP_2X (1 << 2) #define MT9M111_RMB_COLUMN_SKIP_2X (1 << 3) +#define MT9M111_RMB_ROW_SKIP_4X (1 << 4) +#define MT9M111_RMB_COLUMN_SKIP_4X (1 << 5) #define MT9M111_COLOR_MATRIX_BYPASS (1 << 4) #define MT9M111_SEL_CONTEXT_B (1 << 3) -- cgit v1.2.3 From e071c5d8056af78cd5c0b05077e68d062cf94b49 Mon Sep 17 00:00:00 2001 From: Erik Andr?n Date: Tue, 20 Jan 2009 18:32:51 +0100 Subject: gspca - m5602-mt9m111: Activate vflip/hflip by default From: Erik Andr?n Priority: normal Signed-off-by: Erik Andr?n --- linux/drivers/media/video/gspca/m5602/m5602_mt9m111.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.c b/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.c index 54ccc7391..e7fec46ac 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.c @@ -67,7 +67,7 @@ const static struct ctrl mt9m111_ctrls[] = { .minimum = 0, .maximum = 1, .step = 1, - .default_value = 0 + .default_value = 1 }, .set = mt9m111_set_vflip, .get = mt9m111_get_vflip @@ -81,7 +81,7 @@ const static struct ctrl mt9m111_ctrls[] = { .minimum = 0, .maximum = 1, .step = 1, - .default_value = 0 + .default_value = 1 }, .set = mt9m111_set_hflip, .get = mt9m111_get_hflip -- cgit v1.2.3 From 6bd34012978a852bf0afb9fb10222cb81e192385 Mon Sep 17 00:00:00 2001 From: Erik Andr?n Date: Tue, 20 Jan 2009 18:48:16 +0100 Subject: gspca - m5602-mt9m111: Endianness fixes. From: Erik Andr?n Priority: normal Signed-off-by: Erik Andr?n --- .../media/video/gspca/m5602/m5602_mt9m111.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.c b/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.c index e7fec46ac..241108c78 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.c @@ -400,7 +400,7 @@ static int mt9m111_set_vflip(struct gspca_dev *gspca_dev, __s32 val) if (err < 0) return err; - data[0] = (data[0] & 0xfe) | val; + data[1] = (data[1] & 0xfe) | val; err = m5602_write_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B, data, 2); return err; @@ -436,7 +436,7 @@ static int mt9m111_set_hflip(struct gspca_dev *gspca_dev, __s32 val) if (err < 0) return err; - data[0] = (data[0] & 0xfd) | ((val << 1) & 0x02); + data[1] = (data[1] & 0xfd) | ((val << 1) & 0x02); err = m5602_write_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B, data, 2); return err; @@ -466,7 +466,7 @@ static int mt9m111_set_auto_white_balance(struct gspca_dev *gspca_dev, return err; sensor_settings[AUTO_WHITE_BALANCE_IDX] = val & 0x01; - data[0] = ((data[0] & 0xfd) | ((val & 0x01) << 1)); + data[1] = ((data[1] & 0xfd) | ((val & 0x01) << 1)); err = m5602_write_sensor(sd, MT9M111_CP_OPERATING_MODE_CTL, data, 2); @@ -514,8 +514,8 @@ static int mt9m111_set_gain(struct gspca_dev *gspca_dev, __s32 val) else tmp = val; - data[1] = (tmp & 0xff00) >> 8; - data[0] = (tmp & 0xff); + data[1] = (tmp & 0xff); + data[0] = (tmp & 0xff00) >> 8; PDEBUG(D_V4L2, "tmp=%d, data[1]=%d, data[0]=%d", tmp, data[1], data[0]); @@ -533,8 +533,8 @@ static int mt9m111_set_green_balance(struct gspca_dev *gspca_dev, __s32 val) s32 *sensor_settings = sd->sensor_priv; sensor_settings[GREEN_BALANCE_IDX] = val; - data[0] = (val & 0xff); - data[1] = (val & 0xff00) >> 8; + data[1] = (val & 0xff); + data[0] = (val & 0xff00) >> 8; PDEBUG(D_V4L2, "Set green balance %d", val); err = m5602_write_sensor(sd, MT9M111_SC_GREEN_1_GAIN, @@ -563,8 +563,8 @@ static int mt9m111_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val) s32 *sensor_settings = sd->sensor_priv; sensor_settings[BLUE_BALANCE_IDX] = val; - data[0] = (val & 0xff); - data[1] = (val & 0xff00) >> 8; + data[1] = (val & 0xff); + data[0] = (val & 0xff00) >> 8; PDEBUG(D_V4L2, "Set blue balance %d", val); @@ -589,8 +589,8 @@ static int mt9m111_set_red_balance(struct gspca_dev *gspca_dev, __s32 val) s32 *sensor_settings = sd->sensor_priv; sensor_settings[RED_BALANCE_IDX] = val; - data[0] = (val & 0xff); - data[1] = (val & 0xff00) >> 8; + data[1] = (val & 0xff); + data[0] = (val & 0xff00) >> 8; PDEBUG(D_V4L2, "Set red balance %d", val); -- cgit v1.2.3 From 7e19dbae26e6d5ad76bb919f08f650625dcc040e Mon Sep 17 00:00:00 2001 From: Erik Andr?n Date: Tue, 20 Jan 2009 18:53:21 +0100 Subject: gspca - m5602-s5k83a: Align the v4l2 ctrl definitions From: Erik Andr?n Priority: normal Signed-off-by: Erik Andr?n --- .../drivers/media/video/gspca/m5602/m5602_s5k83a.c | 28 +++++++++++----------- 1 file changed, 14 insertions(+), 14 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.c b/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.c index 8d5453572..e1529afd4 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.c @@ -94,13 +94,13 @@ const static struct ctrl s5k83a_ctrls[] = { #define HFLIP_IDX 3 { { - .id = V4L2_CID_HFLIP, - .type = V4L2_CTRL_TYPE_BOOLEAN, - .name = "horizontal flip", - .minimum = 0, - .maximum = 1, - .step = 1, - .default_value = 0 + .id = V4L2_CID_HFLIP, + .type = V4L2_CTRL_TYPE_BOOLEAN, + .name = "horizontal flip", + .minimum = 0, + .maximum = 1, + .step = 1, + .default_value = 0 }, .set = s5k83a_set_hflip, .get = s5k83a_get_hflip @@ -108,13 +108,13 @@ const static struct ctrl s5k83a_ctrls[] = { #define VFLIP_IDX 4 { { - .id = V4L2_CID_VFLIP, - .type = V4L2_CTRL_TYPE_BOOLEAN, - .name = "vertical flip", - .minimum = 0, - .maximum = 1, - .step = 1, - .default_value = 0 + .id = V4L2_CID_VFLIP, + .type = V4L2_CTRL_TYPE_BOOLEAN, + .name = "vertical flip", + .minimum = 0, + .maximum = 1, + .step = 1, + .default_value = 0 }, .set = s5k83a_set_vflip, .get = s5k83a_get_vflip -- cgit v1.2.3 From 5b3e990d19cd5c2758ec1fa19f644e06261e3311 Mon Sep 17 00:00:00 2001 From: Erik Andr?n Date: Tue, 20 Jan 2009 18:55:53 +0100 Subject: gspca - m5602-s5k83a: No need to initialize some registers in init From: Erik Andr?n s5k83a: All v4l2 ctrls are initialized later, no need to set those registers during init. Priority: normal Signed-off-by: Erik Andr?n --- linux/drivers/media/video/gspca/m5602/m5602_s5k83a.h | 18 ------------------ 1 file changed, 18 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.h b/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.h index e93938532..3bda16996 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.h @@ -368,24 +368,6 @@ static const unsigned char init_s5k83a[][4] = /* normal colors (this is value after boot, but after tries can be different) */ {SENSOR, 0x00, 0x06, 0x00}, - - /* set default gain */ - {SENSOR_LONG, 0x14, 0x00, 0x20}, - {SENSOR_LONG, 0x0d, 0x01, 0x00}, - {SENSOR_LONG, 0x1b, S5K83A_DEFAULT_GAIN >> 3, - S5K83A_DEFAULT_GAIN >> 1}, - - /* set default brightness */ - {SENSOR, S5K83A_BRIGHTNESS, S5K83A_DEFAULT_BRIGHTNESS, 0x00}, - - /* set default exposure */ - {SENSOR_LONG, 0x18, 0x00, S5K83A_DEFAULT_EXPOSURE}, - - /* set default flip */ - {SENSOR, S5K83A_PAGE_MAP, 0x05, 0x00}, - {SENSOR, S5K83A_FLIP, 0x00 | S5K83A_FLIP_MASK, 0x00}, - {SENSOR, S5K83A_HFLIP_TUNE, 0x0b, 0x00}, - {SENSOR, S5K83A_VFLIP_TUNE, 0x0a, 0x00} }; #endif -- cgit v1.2.3 From 5ccebfca1ada22f17b5426aca60407aa7c3acece Mon Sep 17 00:00:00 2001 From: Erik Andr?n Date: Tue, 20 Jan 2009 19:02:27 +0100 Subject: gspca - m5602-s5k83a: Remove lots of useless init From: Erik Andr?n Priority: normal Signed-off-by: Erik Andr?n --- .../drivers/media/video/gspca/m5602/m5602_s5k83a.h | 99 +--------------------- 1 file changed, 2 insertions(+), 97 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.h b/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.h index 3bda16996..0697f8a99 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.h @@ -103,8 +103,6 @@ static const unsigned char preinit_s5k83a[][4] = {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00, 0x00}, {BRIDGE, M5602_XB_GPIO_EN_L, 0x00, 0x00}, {BRIDGE, M5602_XB_I2C_CLK_DIV, 0x20, 0x00}, - - {SENSOR, S5K83A_PAGE_MAP, 0x00, 0x00} }; /* This could probably be considerably shortened. @@ -120,40 +118,12 @@ static const unsigned char init_s5k83a[][4] = {SENSOR, 0x01, 0x50, 0x00}, {SENSOR, 0x12, 0x20, 0x00}, {SENSOR, 0x17, 0x40, 0x00}, - {SENSOR, S5K83A_GAIN, 0x0f, 0x00}, {SENSOR, 0x1c, 0x00, 0x00}, {SENSOR, 0x02, 0x70, 0x00}, {SENSOR, 0x03, 0x0b, 0x00}, {SENSOR, 0x04, 0xf0, 0x00}, {SENSOR, 0x05, 0x0b, 0x00}, - {SENSOR, S5K83A_PAGE_MAP, 0x05, 0x00}, - {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06, 0x00}, - {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, - {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00}, - {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00}, - {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81, 0x00}, - {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82, 0x00}, - {BRIDGE, M5602_XB_SIG_INI, 0x01, 0x00}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x01, 0x00}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0xe4, 0x00}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, - {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00}, - {BRIDGE, M5602_XB_SIG_INI, 0x02, 0x00}, - {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00}, - {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00}, - {BRIDGE, M5602_XB_HSYNC_PARA, 0x02, 0x00}, - {BRIDGE, M5602_XB_HSYNC_PARA, 0x87, 0x00}, - {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00}, - {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, - {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, - - {SENSOR, S5K83A_PAGE_MAP, 0x05, 0x00}, {SENSOR, 0x06, 0x71, 0x00}, {SENSOR, 0x07, 0xe8, 0x00}, {SENSOR, 0x08, 0x02, 0x00}, @@ -164,32 +134,6 @@ static const unsigned char init_s5k83a[][4] = {SENSOR, 0x1a, 0x98, 0x00}, {SENSOR, 0x0f, 0x02, 0x00}, {SENSOR, 0x10, 0xe5, 0x00}, - {SENSOR, S5K83A_PAGE_MAP, 0x05, 0x00}, - {SENSOR_LONG, 0x14, 0x00, 0x20}, - {SENSOR_LONG, 0x0d, 0x00, 0x7d}, - {SENSOR_LONG, 0x1b, 0x0d, 0x05}, - - {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06, 0x00}, - {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, - {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00}, - {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00}, - {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81, 0x00}, - {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82, 0x00}, - {BRIDGE, M5602_XB_SIG_INI, 0x01, 0x00}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x01, 0x00}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0xe4, 0x00}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, - {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00}, - {BRIDGE, M5602_XB_SIG_INI, 0x02, 0x00}, - {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00}, - {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00}, - {BRIDGE, M5602_XB_HSYNC_PARA, 0x02, 0x00}, - {BRIDGE, M5602_XB_HSYNC_PARA, 0x87, 0x00}, {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00}, {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00}, @@ -227,43 +171,13 @@ static const unsigned char init_s5k83a[][4] = {SENSOR, 0x01, 0x50, 0x00}, {SENSOR, 0x12, 0x20, 0x00}, {SENSOR, 0x17, 0x40, 0x00}, - {SENSOR, S5K83A_GAIN, 0x0f, 0x00}, {SENSOR, 0x1c, 0x00, 0x00}, {SENSOR, 0x02, 0x70, 0x00}, /* some values like 0x10 give a blue-purple image */ {SENSOR, 0x03, 0x0b, 0x00}, {SENSOR, 0x04, 0xf0, 0x00}, {SENSOR, 0x05, 0x0b, 0x00}, - {SENSOR, S5K83A_PAGE_MAP, 0x05, 0x00}, - {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06, 0x00}, - /* under 80 don't work, highter depend on value */ - {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, - - {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00}, - {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00}, - {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81, 0x00}, - {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82, 0x00}, - {BRIDGE, M5602_XB_SIG_INI, 0x01, 0x00}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x01, 0x00}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0xe4, 0x00}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, - {BRIDGE, M5602_XB_SIG_INI, 0x02, 0x00}, - {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00}, - {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00}, - {BRIDGE, M5602_XB_HSYNC_PARA, 0x02, 0x00}, - {BRIDGE, M5602_XB_HSYNC_PARA, 0x7f, 0x00}, - - {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00}, - {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, - {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, - - {SENSOR, S5K83A_PAGE_MAP, 0x05, 0x00}, {SENSOR, 0x06, 0x71, 0x00}, {SENSOR, 0x07, 0xe8, 0x00}, {SENSOR, 0x08, 0x02, 0x00}, @@ -274,10 +188,6 @@ static const unsigned char init_s5k83a[][4] = {SENSOR, 0x1a, 0x98, 0x00}, {SENSOR, 0x0f, 0x02, 0x00}, {SENSOR, 0x10, 0xe5, 0x00}, - {SENSOR, S5K83A_PAGE_MAP, 0x05, 0x00}, - {SENSOR_LONG, 0x14, 0x00, 0x20}, - {SENSOR_LONG, 0x0d, 0x00, 0x7d}, - {SENSOR_LONG, 0x1b, 0x0d, 0x05}, /* The following sequence is useless after a clean boot but is necessary after resume from suspend */ @@ -335,7 +245,7 @@ static const unsigned char init_s5k83a[][4] = {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, {BRIDGE, M5602_XB_VSYNC_PARA, 0x01, 0x00}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0xe4, 0x00}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0xe4, 0x00}, /* 484 */ {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00}, @@ -343,12 +253,11 @@ static const unsigned char init_s5k83a[][4] = {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00}, {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00}, {BRIDGE, M5602_XB_HSYNC_PARA, 0x02, 0x00}, - {BRIDGE, M5602_XB_HSYNC_PARA, 0x7f, 0x00}, + {BRIDGE, M5602_XB_HSYNC_PARA, 0x7f, 0x00}, /* 639 */ {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00}, {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, - {SENSOR, S5K83A_PAGE_MAP, 0x05, 0x00}, {SENSOR, 0x06, 0x71, 0x00}, {SENSOR, 0x07, 0xe8, 0x00}, {SENSOR, 0x08, 0x02, 0x00}, @@ -358,12 +267,8 @@ static const unsigned char init_s5k83a[][4] = {SENSOR, 0x19, 0x00, 0x00}, {SENSOR, 0x1a, 0x98, 0x00}, {SENSOR, 0x0f, 0x02, 0x00}, - {SENSOR, 0x10, 0xe5, 0x00}, {SENSOR, S5K83A_PAGE_MAP, 0x05, 0x00}, - {SENSOR_LONG, 0x14, 0x00, 0x20}, - {SENSOR_LONG, 0x0d, 0x00, 0x7d}, - {SENSOR_LONG, 0x1b, 0x0d, 0x05}, /* normal colors (this is value after boot, but after tries can be different) */ -- cgit v1.2.3 From bbdcb9eaa5d8b92bed1a70fb8f71818aae5f5a55 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20Andr=C3=A9n?= Date: Tue, 20 Jan 2009 19:07:54 +0100 Subject: gspca - m5602-s5k83a: Remove more init MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: Erik Andrén Priority: normal Signed-off-by: Erik Andrén --- .../drivers/media/video/gspca/m5602/m5602_s5k83a.h | 79 ---------------------- 1 file changed, 79 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.h b/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.h index 0697f8a99..12ad43a0c 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.h @@ -110,85 +110,6 @@ static const unsigned char preinit_s5k83a[][4] = */ static const unsigned char init_s5k83a[][4] = { - {SENSOR, S5K83A_PAGE_MAP, 0x04, 0x00}, - {SENSOR, 0xaf, 0x01, 0x00}, - {SENSOR, S5K83A_PAGE_MAP, 0x00, 0x00}, - {SENSOR, 0x7b, 0xff, 0x00}, - {SENSOR, S5K83A_PAGE_MAP, 0x05, 0x00}, - {SENSOR, 0x01, 0x50, 0x00}, - {SENSOR, 0x12, 0x20, 0x00}, - {SENSOR, 0x17, 0x40, 0x00}, - {SENSOR, 0x1c, 0x00, 0x00}, - {SENSOR, 0x02, 0x70, 0x00}, - {SENSOR, 0x03, 0x0b, 0x00}, - {SENSOR, 0x04, 0xf0, 0x00}, - {SENSOR, 0x05, 0x0b, 0x00}, - - {SENSOR, 0x06, 0x71, 0x00}, - {SENSOR, 0x07, 0xe8, 0x00}, - {SENSOR, 0x08, 0x02, 0x00}, - {SENSOR, 0x09, 0x88, 0x00}, - {SENSOR, 0x14, 0x00, 0x00}, - {SENSOR, 0x15, 0x20, 0x00}, - {SENSOR, 0x19, 0x00, 0x00}, - {SENSOR, 0x1a, 0x98, 0x00}, - {SENSOR, 0x0f, 0x02, 0x00}, - {SENSOR, 0x10, 0xe5, 0x00}, - - {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00}, - {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00}, - {BRIDGE, M5602_XB_GPIO_DAT, 0x08, 0x00}, - {BRIDGE, M5602_XB_GPIO_EN_H, 0x3f, 0x00}, - {BRIDGE, M5602_XB_GPIO_DIR_H, 0x3f, 0x00}, - {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00, 0x00}, - {BRIDGE, M5602_XB_GPIO_EN_L, 0xff, 0x00}, - {BRIDGE, M5602_XB_GPIO_DIR_L, 0xff, 0x00}, - {BRIDGE, M5602_XB_GPIO_DAT_L, 0x00, 0x00}, - {BRIDGE, M5602_XB_SEN_CLK_DIV, 0xb0, 0x00}, - {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0x80, 0x00}, - {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, - {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, - {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00}, - {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00}, - {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02, 0x00}, - {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0, 0x00}, - {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, - {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xf0, 0x00}, - {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00}, - {BRIDGE, M5602_XB_GPIO_DAT, 0x1c, 0x00}, - {BRIDGE, M5602_XB_GPIO_EN_H, 0x06, 0x00}, - {BRIDGE, M5602_XB_GPIO_DIR_H, 0x06, 0x00}, - {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00, 0x00}, - {BRIDGE, M5602_XB_GPIO_EN_L, 0x00, 0x00}, - {BRIDGE, M5602_XB_I2C_CLK_DIV, 0x20, 0x00}, - - {SENSOR, S5K83A_PAGE_MAP, 0x04, 0x00}, - {SENSOR, 0xaf, 0x01, 0x00}, - {SENSOR, S5K83A_PAGE_MAP, 0x05, 0x00}, - /* ff ( init value )is very dark) || 71 and f0 better */ - {SENSOR, 0x7b, 0xff, 0x00}, - {SENSOR, S5K83A_PAGE_MAP, 0x05, 0x00}, - {SENSOR, 0x01, 0x50, 0x00}, - {SENSOR, 0x12, 0x20, 0x00}, - {SENSOR, 0x17, 0x40, 0x00}, - {SENSOR, 0x1c, 0x00, 0x00}, - {SENSOR, 0x02, 0x70, 0x00}, - /* some values like 0x10 give a blue-purple image */ - {SENSOR, 0x03, 0x0b, 0x00}, - {SENSOR, 0x04, 0xf0, 0x00}, - {SENSOR, 0x05, 0x0b, 0x00}, - - {SENSOR, 0x06, 0x71, 0x00}, - {SENSOR, 0x07, 0xe8, 0x00}, - {SENSOR, 0x08, 0x02, 0x00}, - {SENSOR, 0x09, 0x88, 0x00}, - {SENSOR, 0x14, 0x00, 0x00}, - {SENSOR, 0x15, 0x20, 0x00}, - {SENSOR, 0x19, 0x00, 0x00}, - {SENSOR, 0x1a, 0x98, 0x00}, - {SENSOR, 0x0f, 0x02, 0x00}, - {SENSOR, 0x10, 0xe5, 0x00}, - /* The following sequence is useless after a clean boot but is necessary after resume from suspend */ {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00}, -- cgit v1.2.3 From fdc505ba1da2dd41739cebdc78438aef20e84924 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20Andr=C3=A9n?= Date: Tue, 20 Jan 2009 19:10:17 +0100 Subject: gspca - m5602-s5k83a: Move some init code around MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: Erik Andrén Priority: normal Signed-off-by: Erik Andrén --- .../drivers/media/video/gspca/m5602/m5602_s5k83a.h | 31 +++++++++------------- 1 file changed, 13 insertions(+), 18 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.h b/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.h index 12ad43a0c..9a2566d5e 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.h @@ -146,13 +146,24 @@ static const unsigned char init_s5k83a[][4] = {SENSOR, 0x01, 0x50, 0x00}, {SENSOR, 0x12, 0x20, 0x00}, {SENSOR, 0x17, 0x40, 0x00}, - {SENSOR, S5K83A_GAIN, 0x0f, 0x00}, {SENSOR, 0x1c, 0x00, 0x00}, {SENSOR, 0x02, 0x70, 0x00}, {SENSOR, 0x03, 0x0b, 0x00}, {SENSOR, 0x04, 0xf0, 0x00}, {SENSOR, 0x05, 0x0b, 0x00}, - {SENSOR, S5K83A_PAGE_MAP, 0x05, 0x00}, + {SENSOR, 0x06, 0x71, 0x00}, + {SENSOR, 0x07, 0xe8, 0x00}, + {SENSOR, 0x08, 0x02, 0x00}, + {SENSOR, 0x09, 0x88, 0x00}, + {SENSOR, 0x14, 0x00, 0x00}, + {SENSOR, 0x15, 0x20, 0x00}, + {SENSOR, 0x19, 0x00, 0x00}, + {SENSOR, 0x1a, 0x98, 0x00}, + {SENSOR, 0x0f, 0x02, 0x00}, + {SENSOR, 0x10, 0xe5, 0x00}, + /* normal colors + (this is value after boot, but after tries can be different) */ + {SENSOR, 0x00, 0x06, 0x00}, {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06, 0x00}, {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, @@ -178,22 +189,6 @@ static const unsigned char init_s5k83a[][4] = {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00}, {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, - - {SENSOR, 0x06, 0x71, 0x00}, - {SENSOR, 0x07, 0xe8, 0x00}, - {SENSOR, 0x08, 0x02, 0x00}, - {SENSOR, 0x09, 0x88, 0x00}, - {SENSOR, 0x14, 0x00, 0x00}, - {SENSOR, 0x15, 0x20, 0x00}, - {SENSOR, 0x19, 0x00, 0x00}, - {SENSOR, 0x1a, 0x98, 0x00}, - {SENSOR, 0x0f, 0x02, 0x00}, - {SENSOR, 0x10, 0xe5, 0x00}, - {SENSOR, S5K83A_PAGE_MAP, 0x05, 0x00}, - - /* normal colors - (this is value after boot, but after tries can be different) */ - {SENSOR, 0x00, 0x06, 0x00}, }; #endif -- cgit v1.2.3 From 8c0be3648f4bdd6dd43fc0166abb3f4880d8983d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20Andr=C3=A9n?= Date: Tue, 20 Jan 2009 19:15:25 +0100 Subject: gspca - s5k83a: Add resolution annotations MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: Erik Andrén Priority: normal Signed-off-by: Erik Andrén --- linux/drivers/media/video/gspca/m5602/m5602_s5k83a.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.h b/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.h index 9a2566d5e..47c0bb473 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.h @@ -152,15 +152,15 @@ static const unsigned char init_s5k83a[][4] = {SENSOR, 0x04, 0xf0, 0x00}, {SENSOR, 0x05, 0x0b, 0x00}, {SENSOR, 0x06, 0x71, 0x00}, - {SENSOR, 0x07, 0xe8, 0x00}, + {SENSOR, 0x07, 0xe8, 0x00}, /* 488 */ {SENSOR, 0x08, 0x02, 0x00}, - {SENSOR, 0x09, 0x88, 0x00}, + {SENSOR, 0x09, 0x88, 0x00}, /* 648 */ {SENSOR, 0x14, 0x00, 0x00}, - {SENSOR, 0x15, 0x20, 0x00}, + {SENSOR, 0x15, 0x20, 0x00}, /* 32 */ {SENSOR, 0x19, 0x00, 0x00}, - {SENSOR, 0x1a, 0x98, 0x00}, + {SENSOR, 0x1a, 0x98, 0x00}, /* 152 */ {SENSOR, 0x0f, 0x02, 0x00}, - {SENSOR, 0x10, 0xe5, 0x00}, + {SENSOR, 0x10, 0xe5, 0x00}, /* 741 */ /* normal colors (this is value after boot, but after tries can be different) */ {SENSOR, 0x00, 0x06, 0x00}, -- cgit v1.2.3 From 5b87a2f7c24397e15869398e8c2b7c6f59a4cb40 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20Andr=C3=A9n?= Date: Wed, 21 Jan 2009 07:43:49 +0100 Subject: gspca - m5602: Remove useless error check MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: Erik Andrén Priority: normal Signed-off-by: Erik Andrén --- linux/drivers/media/video/gspca/m5602/m5602_core.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/m5602/m5602_core.c b/linux/drivers/media/video/gspca/m5602/m5602_core.c index 93302f31a..9147e3927 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_core.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_core.c @@ -84,10 +84,11 @@ int m5602_wait_for_i2c(struct sd *sd) { int err; u8 data; + do { err = m5602_read_bridge(sd, M5602_XB_I2C_STATUS, &data); } while ((data & I2C_BUSY) && !err); - return (err < 0) ? err : 0; + return err; } int m5602_read_sensor(struct sd *sd, const u8 address, -- cgit v1.2.3 From 555fdb0a1db828c74aa0c03df6f3469cfba977e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20Andr=C3=A9n?= Date: Mon, 27 Apr 2009 20:38:05 +0200 Subject: gspca - m5602-s5k83a: Reset the v4l2 ctrl cache upon sensor init MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: Erik Andrén Priority: normal Signed-off-by: Erik Andrén --- .../drivers/media/video/gspca/m5602/m5602_s5k83a.c | 34 ++++++++++++++++++---- 1 file changed, 29 insertions(+), 5 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.c b/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.c index e1529afd4..646796d21 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.c @@ -124,7 +124,8 @@ const static struct ctrl s5k83a_ctrls[] = { static void s5k83a_dump_registers(struct sd *sd); static int s5k83a_get_rotation(struct sd *sd, u8 *reg_data); static int s5k83a_set_led_indication(struct sd *sd, u8 val); -int s5k83a_set_flip_real(struct gspca_dev *gspca_dev, __s32 vflip, __s32 hflip); +static int s5k83a_set_flip_real(struct gspca_dev *gspca_dev, + __s32 vflip, __s32 hflip); int s5k83a_probe(struct sd *sd) { @@ -198,6 +199,7 @@ sensor_found: int s5k83a_init(struct sd *sd) { int i, err = 0; + s32 *sensor_settings = sd->sensor_priv; for (i = 0; i < ARRAY_SIZE(init_s5k83a) && !err; i++) { u8 data[2] = {0x00, 0x00}; @@ -230,7 +232,27 @@ int s5k83a_init(struct sd *sd) if (dump_sensor) s5k83a_dump_registers(sd); - return (err < 0) ? err : 0; + err = s5k83a_set_gain(&sd->gspca_dev, sensor_settings[GAIN_IDX]); + if (err < 0) + return err; + + err = s5k83a_set_brightness(&sd->gspca_dev, + sensor_settings[BRIGHTNESS_IDX]); + if (err < 0) + return err; + + err = s5k83a_set_exposure(&sd->gspca_dev, + sensor_settings[EXPOSURE_IDX]); + if (err < 0) + return err; + + err = s5k83a_set_hflip(&sd->gspca_dev, sensor_settings[HFLIP_IDX]); + if (err < 0) + return err; + + err = s5k83a_set_vflip(&sd->gspca_dev, sensor_settings[VFLIP_IDX]); + + return err; } static int rotation_thread_function(void *data) @@ -282,7 +304,8 @@ int s5k83a_start(struct sd *sd) /* Create another thread, polling the GPIO ports of the camera to check if it got rotated. This is how the windows driver does it so we have to assume that there is no better way of accomplishing this */ - sens_priv->rotation_thread = kthread_create(rotation_thread_function, sd, "rotation thread"); + sens_priv->rotation_thread = kthread_create(rotation_thread_function, + sd, "rotation thread"); wake_up_process(sens_priv->rotation_thread); return s5k83a_set_led_indication(sd, 1); @@ -402,7 +425,8 @@ static int s5k83a_get_vflip(struct gspca_dev *gspca_dev, __s32 *val) return 0; } -int s5k83a_set_flip_real(struct gspca_dev *gspca_dev, __s32 vflip, __s32 hflip) +static int s5k83a_set_flip_real(struct gspca_dev *gspca_dev, + __s32 vflip, __s32 hflip) { int err; u8 data[1]; @@ -505,7 +529,7 @@ static int s5k83a_set_led_indication(struct sd *sd, u8 val) err = m5602_write_bridge(sd, M5602_XB_GPIO_DAT, data[0]); - return (err < 0) ? err : 0; + return err; } /* Get camera rotation on Acer notebooks */ -- cgit v1.2.3 From 2a5c5c2419b9efc9525275c4bfb3f426c3e362e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20Andr=C3=A9n?= Date: Wed, 21 Jan 2009 07:33:14 +0100 Subject: gspca - m5602-s5k83a: Move hsync/vsync setup to start function MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: Erik Andrén Priority: normal Signed-off-by: Erik Andrén --- linux/drivers/media/video/gspca/m5602/m5602_s5k83a.c | 16 +++++++++++++++- linux/drivers/media/video/gspca/m5602/m5602_s5k83a.h | 3 +++ 2 files changed, 18 insertions(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.c b/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.c index 646796d21..118ec8f8c 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.c @@ -299,15 +299,29 @@ static int rotation_thread_function(void *data) int s5k83a_start(struct sd *sd) { + int i, err = 0; struct s5k83a_priv *sens_priv = sd->sensor_priv; /* Create another thread, polling the GPIO ports of the camera to check if it got rotated. This is how the windows driver does it so we have to assume that there is no better way of accomplishing this */ sens_priv->rotation_thread = kthread_create(rotation_thread_function, - sd, "rotation thread"); + sd, "rotation thread"); wake_up_process(sens_priv->rotation_thread); + /* Preinit the sensor */ + for (i = 0; i < ARRAY_SIZE(start_s5k83a) && !err; i++) { + u8 data[2] = {start_s5k83a[i][2], start_s5k83a[i][3]}; + if (start_s5k83a[i][0] == SENSOR) + err = m5602_write_sensor(sd, start_s5k83a[i][1], + data, 2); + else + err = m5602_write_bridge(sd, start_s5k83a[i][1], + data[0]); + } + if (err < 0) + return err; + return s5k83a_set_led_indication(sd, 1); } diff --git a/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.h b/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.h index 47c0bb473..7814b078a 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.h @@ -164,7 +164,10 @@ static const unsigned char init_s5k83a[][4] = /* normal colors (this is value after boot, but after tries can be different) */ {SENSOR, 0x00, 0x06, 0x00}, +}; +static const unsigned char start_s5k83a[][4] = +{ {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06, 0x00}, {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00}, -- cgit v1.2.3 From 9da3a585b1a8a8ce9a6ec4bf2ebc810b7cd43b67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20Andr=C3=A9n?= Date: Wed, 21 Jan 2009 17:14:07 +0100 Subject: gspca - m5602-s5k83a: Set the sensor_settings pointer correctly MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: Lukas Karas Priority: normal Signed-off-by: Lukas Karas Signed-off-by: Erik Andrén --- linux/drivers/media/video/gspca/m5602/m5602_s5k83a.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.c b/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.c index 118ec8f8c..942030fd0 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.c @@ -199,7 +199,8 @@ sensor_found: int s5k83a_init(struct sd *sd) { int i, err = 0; - s32 *sensor_settings = sd->sensor_priv; + s32 *sensor_settings = + ((struct s5k83a_priv *) sd->sensor_priv)->settings; for (i = 0; i < ARRAY_SIZE(init_s5k83a) && !err; i++) { u8 data[2] = {0x00, 0x00}; -- cgit v1.2.3 From 908c823daba859c8e51949cdde4456cfbf6ddd7d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20Andr=C3=A9n?= Date: Wed, 21 Jan 2009 17:28:31 +0100 Subject: gspca - m5602-ov7660: Initial checkin of sensor skeleton code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: Erik Andrén Priority: normal Signed-off-by: Erik Andrén --- linux/drivers/media/video/gspca/m5602/Makefile | 3 +- .../drivers/media/video/gspca/m5602/m5602_ov7660.c | 92 ++++++ .../drivers/media/video/gspca/m5602/m5602_ov7660.h | 367 +++++++++++++++++++++ 3 files changed, 461 insertions(+), 1 deletion(-) create mode 100644 linux/drivers/media/video/gspca/m5602/m5602_ov7660.c create mode 100644 linux/drivers/media/video/gspca/m5602/m5602_ov7660.h (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/m5602/Makefile b/linux/drivers/media/video/gspca/m5602/Makefile index 9fa3644f4..bf7a19a1e 100644 --- a/linux/drivers/media/video/gspca/m5602/Makefile +++ b/linux/drivers/media/video/gspca/m5602/Makefile @@ -2,9 +2,10 @@ obj-$(CONFIG_USB_M5602) += gspca_m5602.o gspca_m5602-objs := m5602_core.o \ m5602_ov9650.o \ + m5602_ov7660.o \ m5602_mt9m111.o \ m5602_po1030.o \ m5602_s5k83a.o \ m5602_s5k4aa.o -EXTRA_CFLAGS += -Idrivers/media/video/gspca \ No newline at end of file +EXTRA_CFLAGS += -Idrivers/media/video/gspca diff --git a/linux/drivers/media/video/gspca/m5602/m5602_ov7660.c b/linux/drivers/media/video/gspca/m5602/m5602_ov7660.c new file mode 100644 index 000000000..466de667a --- /dev/null +++ b/linux/drivers/media/video/gspca/m5602/m5602_ov7660.c @@ -0,0 +1,92 @@ +/* + * Driver for the ov7660 sensor + * + * Copyright (C) 2009 Erik Andrén + * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project. + * Copyright (C) 2005 m5603x Linux Driver Project + * + * Portions of code to USB interface and ALi driver software, + * Copyright (c) 2006 Willem Duinker + * v4l2 interface modeled after the V4L2 driver + * for SN9C10x PC Camera Controllers + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, version 2. + * + */ + +#include "m5602_ov7660.h" + +const static struct ctrl ov7660_ctrls[] = {}; + +static struct v4l2_pix_format ov7660_modes[] = { + { + 640, + 480, + V4L2_PIX_FMT_SBGGR8, + V4L2_FIELD_NONE, + .sizeimage = + 640 * 480, + .bytesperline = 640, + .colorspace = V4L2_COLORSPACE_SRGB, + .priv = 0 + } +}; + +static void ov7660_dump_registers(struct sd *sd); + +int ov7660_probe(struct sd *sd) +{ + return -ENODEV; +} + +int ov7660_init(struct sd *sd) +{ + return 0; +} + +int ov7660_start(struct sd *sd) +{ + return 0; +} + +int ov7660_stop(struct sd *sd) +{ + return 0; +} + +void ov7660_disconnect(struct sd *sd) {} + +static void ov7660_dump_registers(struct sd *sd) +{ + int address; + info("Dumping the ov7660 register state"); + for (address = 0; address < 0xa9; address++) { + u8 value; + m5602_read_sensor(sd, address, &value, 1); + info("register 0x%x contains 0x%x", + address, value); + } + + info("ov7660 register state dump complete"); + + info("Probing for which registers that are read/write"); + for (address = 0; address < 0xff; address++) { + u8 old_value, ctrl_value; + u8 test_value[2] = {0xff, 0xff}; + + m5602_read_sensor(sd, address, &old_value, 1); + m5602_write_sensor(sd, address, test_value, 1); + m5602_read_sensor(sd, address, &ctrl_value, 1); + + if (ctrl_value == test_value[0]) + info("register 0x%x is writeable", address); + else + info("register 0x%x is read only", address); + + /* Restore original value */ + m5602_write_sensor(sd, address, &old_value, 1); + } +} + diff --git a/linux/drivers/media/video/gspca/m5602/m5602_ov7660.h b/linux/drivers/media/video/gspca/m5602/m5602_ov7660.h new file mode 100644 index 000000000..67bde9bb2 --- /dev/null +++ b/linux/drivers/media/video/gspca/m5602/m5602_ov7660.h @@ -0,0 +1,367 @@ +/* + * Driver for the ov7660 sensor + * + * Copyright (C) 2009 Erik Andrén + * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project. + * Copyright (C) 2005 m5603x Linux Driver Project + * + * Portions of code to USB interface and ALi driver software, + * Copyright (c) 2006 Willem Duinker + * v4l2 interface modeled after the V4L2 driver + * for SN9C10x PC Camera Controllers + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, version 2. + * + */ + +#ifndef M5602_OV7660_H_ +#define M5602_OV7660_H_ + +#include "m5602_sensor.h" + +#define OV7660_GAIN 0x00 +#define OV7660_BLUE_GAIN 0x01 +#define OV7660_RED_GAIN 0x02 +#define OV7660_VREF 0x03 +#define OV7660_COM1 0x04 +#define OV7660_BAVE 0x05 +#define OV7660_GEAVE 0x06 +#define OV7660_AECHH 0x07 +#define OV7660_RAVE 0x08 +#define OV7660_COM2 0x09 +#define OV7660_PID 0x0a +#define OV7660_VER 0x0b +#define OV7660_COM3 0x0c +#define OV7660_COM4 0x0d +#define OV7660_COM5 0x0e +#define OV7660_COM6 0x0f +#define OV7660_AECH 0x10 +#define OV7660_CLKRC 0x11 +#define OV7660_COM7 0x12 +#define OV7660_COM8 0x13 +#define OV7660_COM9 0x14 +#define OV7660_COM10 0x15 +#define OV7660_RSVD16 0x16 +#define OV7660_HSTART 0x17 +#define OV7660_HSTOP 0x18 +#define OV7660_VSTART 0x19 +#define OV7660_VSTOP 0x1a +#define OV7660_PSHFT 0x1b +#define OV7660_MIDH 0x1c +#define OV7660_MIDL 0x1d +#define OV7660_MVFP 0x1e +#define OV7660_LAEC 0x1f +#define OV7660_BOS 0x20 +#define OV7660_GBOS 0x21 +#define OV7660_GROS 0x22 +#define OV7660_ROS 0x23 +#define OV7660_AEW 0x24 +#define OV7660_AEB 0x25 +#define OV7660_VPT 0x26 +#define OV7660_BBIAS 0x27 +#define OV7660_GbBIAS 0x28 +#define OV7660_RSVD29 0x29 +#define OV7660_RBIAS 0x2c +#define OV7660_HREF 0x32 +#define OV7660_ADC 0x37 +#define OV7660_OFON 0x39 +#define OV7660_TSLB 0x3a +#define OV7660_COM12 0x3c +#define OV7660_COM13 0x3d +#define OV7660_LCC1 0x62 +#define OV7660_LCC2 0x63 +#define OV7660_LCC3 0x64 +#define OV7660_LCC4 0x65 +#define OV7660_LCC5 0x66 +#define OV7660_HV 0x69 +#define OV7660_RSVDA1 0xa1 + +#define DEFAULT_GAIN 0x0e +#define DEFAULT_RED_GAIN 0x80 +#define DEFAULT_BLUE_GAIN 0x80 +#define DEFAULT_SATURATION 0x00 +#define DEFAULT_EXPOSURE 0x20 + +int ov7660_probe(struct sd *sd); +int ov7660_init(struct sd *sd); +int ov7660_start(struct sd *sd); +int ov7660_stop(struct sd *sd); +void ov7660_disconnect(struct sd *sd); + +const static struct m5602_sensor ov7660 = { + .name = "ov7660", + .i2c_slave_id = 0x42, + .i2c_regW = 1, + .probe = ov7660_probe, + .init = ov7660_init, + .start = ov7660_start, + .stop = ov7660_stop, + .disconnect = ov7660_disconnect, +}; + +static const unsigned char preinit_ov7660[][4] = +{ + {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02}, + {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0}, + {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00}, + {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0}, + {BRIDGE, M5602_XB_ADC_CTRL, 0xc0}, + {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0d}, + {BRIDGE, M5602_XB_SENSOR_CTRL, 0x00}, + {BRIDGE, M5602_XB_GPIO_DIR, 0x03}, + {BRIDGE, M5602_XB_GPIO_DIR, 0x03}, + {BRIDGE, M5602_XB_ADC_CTRL, 0xc0}, + {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0c}, + + {SENSOR, OV7660_OFON, 0x0c}, + {SENSOR, OV7660_COM2, 0x11}, + {SENSOR, OV7660_COM7, 0x05}, + + {BRIDGE, M5602_XB_GPIO_DIR, 0x01}, + {BRIDGE, M5602_XB_GPIO_DAT, 0x04}, + {BRIDGE, M5602_XB_GPIO_EN_H, 0x06}, + {BRIDGE, M5602_XB_GPIO_DIR_H, 0x06}, + {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00}, + {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x08}, + {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0}, + {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00}, + {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0}, + {BRIDGE, M5602_XB_ADC_CTRL, 0xc0}, + {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0c}, + {BRIDGE, M5602_XB_GPIO_DIR, 0x05}, + {BRIDGE, M5602_XB_GPIO_DAT, 0x00}, + {BRIDGE, M5602_XB_GPIO_EN_H, 0x06}, + {BRIDGE, M5602_XB_GPIO_EN_L, 0x00} +}; + +static const unsigned char init_ov7660[][4] = +{ + {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02}, + {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0}, + {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00}, + {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0}, + {BRIDGE, M5602_XB_ADC_CTRL, 0xc0}, + {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0d}, + {BRIDGE, M5602_XB_SENSOR_CTRL, 0x00}, + {BRIDGE, M5602_XB_GPIO_DIR, 0x03}, + {BRIDGE, M5602_XB_GPIO_DIR, 0x03}, + {BRIDGE, M5602_XB_ADC_CTRL, 0xc0}, + {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0c}, + + {SENSOR, OV7660_OFON, 0x0c}, + {SENSOR, OV7660_COM2, 0x11}, + {SENSOR, OV7660_COM7, 0x05}, + + {BRIDGE, M5602_XB_GPIO_DIR, 0x01}, + {BRIDGE, M5602_XB_GPIO_DAT, 0x04}, + {BRIDGE, M5602_XB_GPIO_EN_H, 0x06}, + {BRIDGE, M5602_XB_GPIO_DIR_H, 0x06}, + {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00}, + {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x08}, + {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0}, + {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00}, + {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0}, + {BRIDGE, M5602_XB_ADC_CTRL, 0xc0}, + {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0c}, + {BRIDGE, M5602_XB_GPIO_DIR, 0x05}, + {BRIDGE, M5602_XB_GPIO_DAT, 0x00}, + {BRIDGE, M5602_XB_GPIO_EN_H, 0x06}, + {BRIDGE, M5602_XB_GPIO_EN_L, 0x00}, + + {SENSOR, OV7660_COM7, 0x80}, + {SENSOR, OV7660_CLKRC, 0x80}, + {SENSOR, OV7660_BLUE_GAIN, 0x80}, + {SENSOR, OV7660_RED_GAIN, 0x80}, + {SENSOR, OV7660_COM9, 0x4c}, + {SENSOR, OV7660_OFON, 0x43}, + {SENSOR, OV7660_COM12, 0x28}, + {SENSOR, OV7660_COM8, 0x00}, + {SENSOR, OV7660_COM10, 0x40}, + {SENSOR, OV7660_HSTART, 0x0c}, + {SENSOR, OV7660_HSTOP, 0x61}, + {SENSOR, OV7660_HREF, 0xa4}, + {SENSOR, OV7660_PSHFT, 0x0b}, + {SENSOR, OV7660_VSTART, 0x01}, + {SENSOR, OV7660_VSTOP, 0x7a}, + {SENSOR, OV7660_VREF, 0x00}, + {SENSOR, OV7660_COM7, 0x05}, + {SENSOR, OV7660_COM6, 0x4b}, + {SENSOR, OV7660_BBIAS, 0x98}, + {SENSOR, OV7660_GbBIAS, 0x98}, + {SENSOR, OV7660_RSVD29, 0x98}, + {SENSOR, OV7660_RBIAS, 0x98}, + {SENSOR, OV7660_COM1, 0x00}, + {SENSOR, OV7660_AECH, 0x00}, + {SENSOR, OV7660_AECHH, 0x00}, + {SENSOR, OV7660_ADC, 0x04}, + {SENSOR, OV7660_COM13, 0x00}, + {SENSOR, OV7660_RSVDA1, 0x23}, + {SENSOR, OV7660_TSLB, 0x0d}, + {SENSOR, OV7660_HV, 0x80}, + {SENSOR, OV7660_LCC1, 0x00}, + {SENSOR, OV7660_LCC2, 0x00}, + {SENSOR, OV7660_LCC3, 0x10}, + {SENSOR, OV7660_LCC4, 0x40}, + {SENSOR, OV7660_LCC5, 0x01}, + + {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06}, + {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0}, + {BRIDGE, M5602_XB_ADC_CTRL, 0xc0}, + {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0c}, + {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81}, + {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82}, + {BRIDGE, M5602_XB_SIG_INI, 0x01}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x08}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x01}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0xec}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, + {BRIDGE, M5602_XB_SIG_INI, 0x00}, + {BRIDGE, M5602_XB_SIG_INI, 0x02}, + {BRIDGE, M5602_XB_HSYNC_PARA, 0x00}, + {BRIDGE, M5602_XB_HSYNC_PARA, 0x27}, + {BRIDGE, M5602_XB_HSYNC_PARA, 0x02}, + {BRIDGE, M5602_XB_HSYNC_PARA, 0xae}, + {BRIDGE, M5602_XB_SIG_INI, 0x00}, + + {SENSOR, OV7660_BLUE_GAIN, 0x80}, + {SENSOR, OV7660_RED_GAIN, 0x80}, + + {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x02}, + {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0}, + + {SENSOR, OV7660_AECH, DEFAULT_EXPOSURE}, + {SENSOR, OV7660_COM1, 0x00}, + {SENSOR, OV7660_GAIN, DEFAULT_GAIN}, + + {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06}, + {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0}, + {BRIDGE, M5602_XB_ADC_CTRL, 0xc0}, + {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0c}, + {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81}, + {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82}, + {BRIDGE, M5602_XB_SIG_INI, 0x01}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x08}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x01}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0xec}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, + {BRIDGE, M5602_XB_SIG_INI, 0x00}, + {BRIDGE, M5602_XB_SIG_INI, 0x02}, + {BRIDGE, M5602_XB_HSYNC_PARA, 0x00}, + {BRIDGE, M5602_XB_HSYNC_PARA, 0x27}, + {BRIDGE, M5602_XB_HSYNC_PARA, 0x02}, + {BRIDGE, M5602_XB_HSYNC_PARA, 0xae}, + {BRIDGE, M5602_XB_SIG_INI, 0x00}, + + {SENSOR, OV7660_OFON, 0x0c}, + {SENSOR, OV7660_COM2, 0x11}, + {SENSOR, OV7660_COM7, 0x05}, + + {BRIDGE, M5602_XB_GPIO_DIR, 0x01}, + {BRIDGE, M5602_XB_GPIO_DAT, 0x04}, + {BRIDGE, M5602_XB_GPIO_EN_H, 0x06}, + {BRIDGE, M5602_XB_GPIO_DIR_H, 0x06}, + {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00}, + {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x08}, + {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0}, + + {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00}, + {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0}, + {BRIDGE, M5602_XB_ADC_CTRL, 0xc0}, + {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0c}, + {BRIDGE, M5602_XB_GPIO_DIR, 0x05}, + {BRIDGE, M5602_XB_GPIO_DAT, 0x00}, + {BRIDGE, M5602_XB_GPIO_EN_H, 0x06}, + {BRIDGE, M5602_XB_GPIO_EN_L, 0x00}, + + {SENSOR, OV7660_COM7, 0x80}, + {SENSOR, OV7660_CLKRC, 0x80}, + {SENSOR, OV7660_BLUE_GAIN, 0x80}, + {SENSOR, OV7660_RED_GAIN, 0x80}, + {SENSOR, OV7660_COM9, 0x4c}, + {SENSOR, OV7660_OFON, 0x43}, + {SENSOR, OV7660_COM12, 0x28}, + {SENSOR, OV7660_COM8, 0x00}, + {SENSOR, OV7660_COM10, 0x40}, + {SENSOR, OV7660_HSTART, 0x0c}, + {SENSOR, OV7660_HSTOP, 0x61}, + {SENSOR, OV7660_HREF, 0xa4}, + {SENSOR, OV7660_PSHFT, 0x0b}, + {SENSOR, OV7660_VSTART, 0x01}, + {SENSOR, OV7660_VSTOP, 0x7a}, + {SENSOR, OV7660_VREF, 0x00}, + {SENSOR, OV7660_COM7, 0x05}, + {SENSOR, OV7660_COM6, 0x4b}, + {SENSOR, OV7660_BBIAS, 0x98}, + {SENSOR, OV7660_GbBIAS, 0x98}, + {SENSOR, OV7660_RSVD29, 0x98}, + {SENSOR, OV7660_RBIAS, 0x98}, + {SENSOR, OV7660_COM1, 0x00}, + {SENSOR, OV7660_AECH, 0x00}, + {SENSOR, OV7660_AECHH, 0x00}, + {SENSOR, OV7660_ADC, 0x04}, + {SENSOR, OV7660_COM13, 0x00}, + {SENSOR, OV7660_RSVDA1, 0x23}, + {SENSOR, OV7660_TSLB, 0x0d}, + {SENSOR, OV7660_HV, 0x80}, + {SENSOR, OV7660_LCC1, 0x00}, + {SENSOR, OV7660_LCC2, 0x00}, + {SENSOR, OV7660_LCC3, 0x10}, + {SENSOR, OV7660_LCC4, 0x40}, + {SENSOR, OV7660_LCC5, 0x01}, + + {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06}, + {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0}, + {BRIDGE, M5602_XB_ADC_CTRL, 0xc0}, + {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0c}, + {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81}, + {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82}, + {BRIDGE, M5602_XB_SIG_INI, 0x01}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x08}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x01}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0xec}, /* 492 */ + {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, + {BRIDGE, M5602_XB_SIG_INI, 0x00}, + {BRIDGE, M5602_XB_SIG_INI, 0x02}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x27}, /* 39 */ + {BRIDGE, M5602_XB_VSYNC_PARA, 0x02}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0xae}, /* 686 */ + {BRIDGE, M5602_XB_SIG_INI, 0x00}, + + {SENSOR, OV7660_BLUE_GAIN, 0x80}, + {SENSOR, OV7660_RED_GAIN, 0x80}, + + {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00}, + {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0}, + + {SENSOR, OV7660_AECH, 0x20}, + {SENSOR, OV7660_COM1, 0x00}, + {SENSOR, OV7660_GAIN, DEFAULT_GAIN}, + {SENSOR, OV7660_OFON, 0x0c}, + {SENSOR, OV7660_COM2, 0x11}, + {SENSOR, OV7660_COM7, 0x05}, + + {BRIDGE, M5602_XB_GPIO_DIR, 0x01}, + {BRIDGE, M5602_XB_GPIO_DAT, 0x04}, + {BRIDGE, M5602_XB_GPIO_EN_H, 0x06}, + {BRIDGE, M5602_XB_GPIO_DIR_H, 0x06}, + {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00}, + {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x08}, + {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0} +}; + +#endif -- cgit v1.2.3 From 3996f1d906f6c60eda80447cc1d24e13230c2e27 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20Andr=C3=A9n?= Date: Wed, 21 Jan 2009 17:39:17 +0100 Subject: gspca - m5602-ov7660: Design probe function MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: Erik Andrén Priority: normal Signed-off-by: Erik Andrén --- .../drivers/media/video/gspca/m5602/m5602_ov7660.c | 61 ++++++++++++++++++++++ .../drivers/media/video/gspca/m5602/m5602_ov7660.h | 4 ++ .../drivers/media/video/gspca/m5602/m5602_sensor.h | 3 +- 3 files changed, 67 insertions(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/m5602/m5602_ov7660.c b/linux/drivers/media/video/gspca/m5602/m5602_ov7660.c index 466de667a..a5953d828 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_ov7660.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_ov7660.c @@ -38,7 +38,68 @@ static void ov7660_dump_registers(struct sd *sd); int ov7660_probe(struct sd *sd) { + int err = 0, i; + u8 prod_id = 0, ver_id = 0; + + s32 *sensor_settings; + + if (force_sensor) { + if (force_sensor == OV7660_SENSOR) { + info("Forcing an %s sensor", ov7660.name); + goto sensor_found; + } + /* If we want to force another sensor, + don't try to probe this one */ + return -ENODEV; + } + + /* Do the preinit */ + for (i = 0; i < ARRAY_SIZE(preinit_ov7660) && !err; i++) { + u8 data[2]; + + if (preinit_ov7660[i][0] == BRIDGE) { + err = m5602_write_bridge(sd, + preinit_ov7660[i][1], + preinit_ov7660[i][2]); + } else { + data[0] = preinit_ov7660[i][2]; + err = m5602_write_sensor(sd, + preinit_ov7660[i][1], data, 1); + } + } + if (err < 0) + return err; + + if (m5602_read_sensor(sd, OV7660_PID, &prod_id, 1)) + return -ENODEV; + + if (m5602_read_sensor(sd, OV7660_VER, &ver_id, 1)) + return -ENODEV; + + info("Sensor reported 0x%x%x", prod_id, ver_id); + + if ((prod_id == 0x76) && (ver_id == 0x60)) { + info("Detected a ov7660 sensor"); + goto sensor_found; + } return -ENODEV; + +sensor_found: + sensor_settings = kmalloc( + ARRAY_SIZE(ov7660_ctrls) * sizeof(s32), GFP_KERNEL); + if (!sensor_settings) + return -ENOMEM; + + sd->gspca_dev.cam.cam_mode = ov7660_modes; + sd->gspca_dev.cam.nmodes = ARRAY_SIZE(ov7660_modes); + sd->desc->ctrls = ov7660_ctrls; + sd->desc->nctrls = ARRAY_SIZE(ov7660_ctrls); + + for (i = 0; i < ARRAY_SIZE(ov7660_ctrls); i++) + sensor_settings[i] = ov7660_ctrls[i].qctrl.default_value; + sd->sensor_priv = sensor_settings; + + return 0; } int ov7660_init(struct sd *sd) diff --git a/linux/drivers/media/video/gspca/m5602/m5602_ov7660.h b/linux/drivers/media/video/gspca/m5602/m5602_ov7660.h index 67bde9bb2..71103ede8 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_ov7660.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_ov7660.h @@ -84,6 +84,10 @@ #define DEFAULT_SATURATION 0x00 #define DEFAULT_EXPOSURE 0x20 +/* Kernel module parameters */ +extern int force_sensor; +extern int dump_sensor; + int ov7660_probe(struct sd *sd); int ov7660_init(struct sd *sd); int ov7660_start(struct sd *sd); diff --git a/linux/drivers/media/video/gspca/m5602/m5602_sensor.h b/linux/drivers/media/video/gspca/m5602/m5602_sensor.h index c3a72117b..edff4f1f5 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_sensor.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_sensor.h @@ -30,7 +30,8 @@ enum sensors { S5K83A_SENSOR = 2, S5K4AA_SENSOR = 3, MT9M111_SENSOR = 4, - PO1030_SENSOR = 5 + PO1030_SENSOR = 5, + OV7660_SENSOR = 6, }; /* Enumerates all possible instruction types */ -- cgit v1.2.3 From 1e957c3612f0a153e549eca0319450c7b3f85517 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20Andr=C3=A9n?= Date: Wed, 21 Jan 2009 17:43:20 +0100 Subject: gspca - m5602-ov7660: Design init function. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: Erik Andrén Priority: normal Signed-off-by: Erik Andrén --- .../drivers/media/video/gspca/m5602/m5602_ov7660.c | 27 +++++++++++++++++----- 1 file changed, 21 insertions(+), 6 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/m5602/m5602_ov7660.c b/linux/drivers/media/video/gspca/m5602/m5602_ov7660.c index a5953d828..1c20a3bfa 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_ov7660.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_ov7660.c @@ -85,11 +85,6 @@ int ov7660_probe(struct sd *sd) return -ENODEV; sensor_found: - sensor_settings = kmalloc( - ARRAY_SIZE(ov7660_ctrls) * sizeof(s32), GFP_KERNEL); - if (!sensor_settings) - return -ENOMEM; - sd->gspca_dev.cam.cam_mode = ov7660_modes; sd->gspca_dev.cam.nmodes = ARRAY_SIZE(ov7660_modes); sd->desc->ctrls = ov7660_ctrls; @@ -104,7 +99,27 @@ sensor_found: int ov7660_init(struct sd *sd) { - return 0; + int i, err = 0; + + /* Init the sensor */ + for (i = 0; i < ARRAY_SIZE(init_ov7660); i++) { + u8 data[2]; + + if (init_ov7660[i][0] == BRIDGE) { + err = m5602_write_bridge(sd, + init_ov7660[i][1], + init_ov7660[i][2]); + } else { + data[0] = init_ov7660[i][2]; + err = m5602_write_sensor(sd, + init_ov7660[i][1], data, 1); + } + } + + if (dump_sensor) + ov7660_dump_registers(sd); + + return err; } int ov7660_start(struct sd *sd) -- cgit v1.2.3 From 6969cbb6a4bd8988048cd0cc2f089f01f57c1b71 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20Andr=C3=A9n?= Date: Wed, 21 Jan 2009 17:46:58 +0100 Subject: gspca - m5602-ov7660: Make an educated guess on the proper hsync/vsync MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: Erik Andrén Based on how the ov9650 is configured, make an educated guess on the hsync/vsync setup for the ov7660 Priority: normal Signed-off-by: Erik Andrén --- linux/drivers/media/video/gspca/m5602/m5602_ov7660.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/m5602/m5602_ov7660.h b/linux/drivers/media/video/gspca/m5602/m5602_ov7660.h index 71103ede8..34652bcdf 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_ov7660.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_ov7660.h @@ -335,7 +335,7 @@ static const unsigned char init_ov7660[][4] = {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, {BRIDGE, M5602_XB_VSYNC_PARA, 0x01}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0xec}, /* 492 */ + {BRIDGE, M5602_XB_VSYNC_PARA, 0xe0}, /* 480 */ {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, {BRIDGE, M5602_XB_SIG_INI, 0x00}, @@ -343,7 +343,7 @@ static const unsigned char init_ov7660[][4] = {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, {BRIDGE, M5602_XB_VSYNC_PARA, 0x27}, /* 39 */ {BRIDGE, M5602_XB_VSYNC_PARA, 0x02}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0xae}, /* 686 */ + {BRIDGE, M5602_XB_VSYNC_PARA, 0xa7}, /* 679 */ {BRIDGE, M5602_XB_SIG_INI, 0x00}, {SENSOR, OV7660_BLUE_GAIN, 0x80}, -- cgit v1.2.3 From aaef55c44c4f4af3f656b7884de88f4343dc264a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20Andr=C3=A9n?= Date: Thu, 22 Jan 2009 07:32:32 +0100 Subject: gspca - m5602-mt9m111: Correct the hflip/vflip semantics MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: Erik Andrén mt9m111: Hflip and vflip shall always be 0 at start and the image shall be correctly aligned. The mt9m111 is hflipped and vflipped by default. Correct the semantics to make this happen. Priority: normal Signed-off-by: Erik Andrén --- linux/drivers/media/video/gspca/m5602/m5602_mt9m111.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.c b/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.c index 241108c78..ade7264d4 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.c @@ -67,7 +67,7 @@ const static struct ctrl mt9m111_ctrls[] = { .minimum = 0, .maximum = 1, .step = 1, - .default_value = 1 + .default_value = 0 }, .set = mt9m111_set_vflip, .get = mt9m111_get_vflip @@ -81,7 +81,7 @@ const static struct ctrl mt9m111_ctrls[] = { .minimum = 0, .maximum = 1, .step = 1, - .default_value = 1 + .default_value = 0 }, .set = mt9m111_set_hflip, .get = mt9m111_get_hflip @@ -391,6 +391,9 @@ static int mt9m111_set_vflip(struct gspca_dev *gspca_dev, __s32 val) sensor_settings[VFLIP_IDX] = val; + /* The mt9m111 is flipped by default */ + val = !val; + /* Set the correct page map */ err = m5602_write_sensor(sd, MT9M111_PAGE_MAP, data, 2); if (err < 0) @@ -427,6 +430,10 @@ static int mt9m111_set_hflip(struct gspca_dev *gspca_dev, __s32 val) PDEBUG(D_V4L2, "Set horizontal flip to %d", val); sensor_settings[HFLIP_IDX] = val; + + /* The mt9m111 is flipped by default */ + val = !val; + /* Set the correct page map */ err = m5602_write_sensor(sd, MT9M111_PAGE_MAP, data, 2); if (err < 0) -- cgit v1.2.3 From 14ac13100d3cf2c1b83e308815a03b1b50115481 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20Andr=C3=A9n?= Date: Thu, 22 Jan 2009 07:51:40 +0100 Subject: gspca - m5602-s5k4aa: Flip hflip and vflip together MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: Erik Andrén Priority: normal Signed-off-by: Erik Andrén --- .../drivers/media/video/gspca/m5602/m5602_s5k4aa.c | 28 +++++++++++++++------- 1 file changed, 20 insertions(+), 8 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c b/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c index 06da4b3ed..3ec22ebd2 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c @@ -420,18 +420,21 @@ static int s5k4aa_set_vflip(struct gspca_dev *gspca_dev, __s32 val) if (err < 0) return err; - if (dmi_check_system(s5k4aa_vflip_dmi_table)) + if (dmi_check_system(s5k4aa_vflip_dmi_table)) { val = !val; + data = (data & 0x3f) | + (!sensor_settings[HFLIP_IDX] << 6) | + ((val & 0x01) << 7); + } else { + data = (data & 0x3f) | + (sensor_settings[HFLIP_IDX] << 6) | + ((val & 0x01) << 7); + } - data = ((data & ~S5K4AA_RM_V_FLIP) - | ((val & 0x01) << 7)); err = m5602_write_sensor(sd, S5K4AA_READ_MODE, &data, 1); if (err < 0) return err; - if (dmi_check_system(s5k4aa_vflip_dmi_table)) - val = !val; - if (val) { err = m5602_read_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1); if (err < 0) @@ -447,7 +450,6 @@ static int s5k4aa_set_vflip(struct gspca_dev *gspca_dev, __s32 val) data--; err = m5602_write_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1); } - return err; } @@ -483,6 +485,17 @@ static int s5k4aa_set_hflip(struct gspca_dev *gspca_dev, __s32 val) if (err < 0) return err; + if (dmi_check_system(s5k4aa_vflip_dmi_table)) { + val = !val; + data = (data & 0x3f) | + (!sensor_settings[VFLIP_IDX] << 7) | + ((val & 0x01) << 6); + } else { + data = (data & 0x3f) | + (sensor_settings[VFLIP_IDX] << 7) | + ((val & 0x01) << 6); + } + data = ((data & ~S5K4AA_RM_H_FLIP) | ((val & 0x01) << 6)); err = m5602_write_sensor(sd, S5K4AA_READ_MODE, &data, 1); if (err < 0) @@ -503,7 +516,6 @@ static int s5k4aa_set_hflip(struct gspca_dev *gspca_dev, __s32 val) data--; err = m5602_write_sensor(sd, S5K4AA_COLSTART_LO, &data, 1); } - return err; } -- cgit v1.2.3 From c886de8a9efc2290b68b15dab6416f76a1bc19f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20Andr=C3=A9n?= Date: Thu, 22 Jan 2009 07:57:30 +0100 Subject: gspca - m5602-ov7660: Remove useless init data MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: Erik Andrén Priority: normal Signed-off-by: Erik Andrén --- .../drivers/media/video/gspca/m5602/m5602_ov7660.h | 94 +--------------------- 1 file changed, 2 insertions(+), 92 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/m5602/m5602_ov7660.h b/linux/drivers/media/video/gspca/m5602/m5602_ov7660.h index 34652bcdf..15ab706d5 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_ov7660.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_ov7660.h @@ -174,68 +174,6 @@ static const unsigned char init_ov7660[][4] = {BRIDGE, M5602_XB_GPIO_EN_H, 0x06}, {BRIDGE, M5602_XB_GPIO_EN_L, 0x00}, - {SENSOR, OV7660_COM7, 0x80}, - {SENSOR, OV7660_CLKRC, 0x80}, - {SENSOR, OV7660_BLUE_GAIN, 0x80}, - {SENSOR, OV7660_RED_GAIN, 0x80}, - {SENSOR, OV7660_COM9, 0x4c}, - {SENSOR, OV7660_OFON, 0x43}, - {SENSOR, OV7660_COM12, 0x28}, - {SENSOR, OV7660_COM8, 0x00}, - {SENSOR, OV7660_COM10, 0x40}, - {SENSOR, OV7660_HSTART, 0x0c}, - {SENSOR, OV7660_HSTOP, 0x61}, - {SENSOR, OV7660_HREF, 0xa4}, - {SENSOR, OV7660_PSHFT, 0x0b}, - {SENSOR, OV7660_VSTART, 0x01}, - {SENSOR, OV7660_VSTOP, 0x7a}, - {SENSOR, OV7660_VREF, 0x00}, - {SENSOR, OV7660_COM7, 0x05}, - {SENSOR, OV7660_COM6, 0x4b}, - {SENSOR, OV7660_BBIAS, 0x98}, - {SENSOR, OV7660_GbBIAS, 0x98}, - {SENSOR, OV7660_RSVD29, 0x98}, - {SENSOR, OV7660_RBIAS, 0x98}, - {SENSOR, OV7660_COM1, 0x00}, - {SENSOR, OV7660_AECH, 0x00}, - {SENSOR, OV7660_AECHH, 0x00}, - {SENSOR, OV7660_ADC, 0x04}, - {SENSOR, OV7660_COM13, 0x00}, - {SENSOR, OV7660_RSVDA1, 0x23}, - {SENSOR, OV7660_TSLB, 0x0d}, - {SENSOR, OV7660_HV, 0x80}, - {SENSOR, OV7660_LCC1, 0x00}, - {SENSOR, OV7660_LCC2, 0x00}, - {SENSOR, OV7660_LCC3, 0x10}, - {SENSOR, OV7660_LCC4, 0x40}, - {SENSOR, OV7660_LCC5, 0x01}, - - {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06}, - {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0}, - {BRIDGE, M5602_XB_ADC_CTRL, 0xc0}, - {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0c}, - {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81}, - {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82}, - {BRIDGE, M5602_XB_SIG_INI, 0x01}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x08}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x01}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0xec}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, - {BRIDGE, M5602_XB_SIG_INI, 0x00}, - {BRIDGE, M5602_XB_SIG_INI, 0x02}, - {BRIDGE, M5602_XB_HSYNC_PARA, 0x00}, - {BRIDGE, M5602_XB_HSYNC_PARA, 0x27}, - {BRIDGE, M5602_XB_HSYNC_PARA, 0x02}, - {BRIDGE, M5602_XB_HSYNC_PARA, 0xae}, - {BRIDGE, M5602_XB_SIG_INI, 0x00}, - - {SENSOR, OV7660_BLUE_GAIN, 0x80}, - {SENSOR, OV7660_RED_GAIN, 0x80}, - {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x02}, {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0}, @@ -243,33 +181,6 @@ static const unsigned char init_ov7660[][4] = {SENSOR, OV7660_COM1, 0x00}, {SENSOR, OV7660_GAIN, DEFAULT_GAIN}, - {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06}, - {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0}, - {BRIDGE, M5602_XB_ADC_CTRL, 0xc0}, - {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0c}, - {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81}, - {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82}, - {BRIDGE, M5602_XB_SIG_INI, 0x01}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x08}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x01}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0xec}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, - {BRIDGE, M5602_XB_SIG_INI, 0x00}, - {BRIDGE, M5602_XB_SIG_INI, 0x02}, - {BRIDGE, M5602_XB_HSYNC_PARA, 0x00}, - {BRIDGE, M5602_XB_HSYNC_PARA, 0x27}, - {BRIDGE, M5602_XB_HSYNC_PARA, 0x02}, - {BRIDGE, M5602_XB_HSYNC_PARA, 0xae}, - {BRIDGE, M5602_XB_SIG_INI, 0x00}, - - {SENSOR, OV7660_OFON, 0x0c}, - {SENSOR, OV7660_COM2, 0x11}, - {SENSOR, OV7660_COM7, 0x05}, - {BRIDGE, M5602_XB_GPIO_DIR, 0x01}, {BRIDGE, M5602_XB_GPIO_DAT, 0x04}, {BRIDGE, M5602_XB_GPIO_EN_H, 0x06}, @@ -346,9 +257,6 @@ static const unsigned char init_ov7660[][4] = {BRIDGE, M5602_XB_VSYNC_PARA, 0xa7}, /* 679 */ {BRIDGE, M5602_XB_SIG_INI, 0x00}, - {SENSOR, OV7660_BLUE_GAIN, 0x80}, - {SENSOR, OV7660_RED_GAIN, 0x80}, - {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00}, {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0}, @@ -358,6 +266,8 @@ static const unsigned char init_ov7660[][4] = {SENSOR, OV7660_OFON, 0x0c}, {SENSOR, OV7660_COM2, 0x11}, {SENSOR, OV7660_COM7, 0x05}, + {SENSOR, OV7660_BLUE_GAIN, 0x80}, + {SENSOR, OV7660_RED_GAIN, 0x80}, {BRIDGE, M5602_XB_GPIO_DIR, 0x01}, {BRIDGE, M5602_XB_GPIO_DAT, 0x04}, -- cgit v1.2.3 From 16488f14f6eb401dfa03033651cb9e50f7abb699 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20Andr=C3=A9n?= Date: Thu, 22 Jan 2009 08:04:59 +0100 Subject: gspca - m5602-ov7660: Add a gain ctrl MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: Erik Andrén Priority: normal Signed-off-by: Erik Andrén --- .../drivers/media/video/gspca/m5602/m5602_ov7660.c | 65 +++++++++++++++++++++- .../drivers/media/video/gspca/m5602/m5602_ov7660.h | 2 - 2 files changed, 62 insertions(+), 5 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/m5602/m5602_ov7660.c b/linux/drivers/media/video/gspca/m5602/m5602_ov7660.c index 1c20a3bfa..bfa28de6c 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_ov7660.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_ov7660.c @@ -18,7 +18,26 @@ #include "m5602_ov7660.h" -const static struct ctrl ov7660_ctrls[] = {}; +static int ov7660_get_gain(struct gspca_dev *gspca_dev, __s32 *val); +static int ov7660_set_gain(struct gspca_dev *gspca_dev, __s32 val); + +const static struct ctrl ov7660_ctrls[] = { +#define GAIN_IDX 1 + { + { + .id = V4L2_CID_GAIN, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "gain", + .minimum = 0x00, + .maximum = 0xff, + .step = 0x1, + .default_value = DEFAULT_GAIN, + .flags = V4L2_CTRL_FLAG_SLIDER + }, + .set = ov7660_set_gain, + .get = ov7660_get_gain + }, +}; static struct v4l2_pix_format ov7660_modes[] = { { @@ -85,6 +104,11 @@ int ov7660_probe(struct sd *sd) return -ENODEV; sensor_found: + sensor_settings = kmalloc( + ARRAY_SIZE(ov7660_ctrls) * sizeof(s32), GFP_KERNEL); + if (!sensor_settings) + return -ENOMEM; + sd->gspca_dev.cam.cam_mode = ov7660_modes; sd->gspca_dev.cam.nmodes = ARRAY_SIZE(ov7660_modes); sd->desc->ctrls = ov7660_ctrls; @@ -100,6 +124,7 @@ sensor_found: int ov7660_init(struct sd *sd) { int i, err = 0; + s32 *sensor_settings = sd->sensor_priv; /* Init the sensor */ for (i = 0; i < ARRAY_SIZE(init_ov7660); i++) { @@ -119,6 +144,10 @@ int ov7660_init(struct sd *sd) if (dump_sensor) ov7660_dump_registers(sd); + err = ov7660_set_gain(&sd->gspca_dev, sensor_settings[GAIN_IDX]); + if (err < 0) + return err; + return err; } @@ -132,7 +161,38 @@ int ov7660_stop(struct sd *sd) return 0; } -void ov7660_disconnect(struct sd *sd) {} +void ov7660_disconnect(struct sd *sd) +{ + ov7660_stop(sd); + + sd->sensor = NULL; + kfree(sd->sensor_priv); +} + +static int ov7660_get_gain(struct gspca_dev *gspca_dev, __s32 *val) +{ + struct sd *sd = (struct sd *) gspca_dev; + s32 *sensor_settings = sd->sensor_priv; + + *val = sensor_settings[GAIN_IDX]; + PDEBUG(D_V4L2, "Read gain %d", *val); + return 0; +} + +static int ov7660_set_gain(struct gspca_dev *gspca_dev, __s32 val) +{ + int err; + u8 i2c_data; + struct sd *sd = (struct sd *) gspca_dev; + s32 *sensor_settings = sd->sensor_priv; + + PDEBUG(D_V4L2, "Setting gain to %d", val); + + sensor_settings[GAIN_IDX] = val; + + err = m5602_write_sensor(sd, OV7660_GAIN, &i2c_data, 1); + return err; +} static void ov7660_dump_registers(struct sd *sd) { @@ -165,4 +225,3 @@ static void ov7660_dump_registers(struct sd *sd) m5602_write_sensor(sd, address, &old_value, 1); } } - diff --git a/linux/drivers/media/video/gspca/m5602/m5602_ov7660.h b/linux/drivers/media/video/gspca/m5602/m5602_ov7660.h index 15ab706d5..570715fff 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_ov7660.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_ov7660.h @@ -179,7 +179,6 @@ static const unsigned char init_ov7660[][4] = {SENSOR, OV7660_AECH, DEFAULT_EXPOSURE}, {SENSOR, OV7660_COM1, 0x00}, - {SENSOR, OV7660_GAIN, DEFAULT_GAIN}, {BRIDGE, M5602_XB_GPIO_DIR, 0x01}, {BRIDGE, M5602_XB_GPIO_DAT, 0x04}, @@ -262,7 +261,6 @@ static const unsigned char init_ov7660[][4] = {SENSOR, OV7660_AECH, 0x20}, {SENSOR, OV7660_COM1, 0x00}, - {SENSOR, OV7660_GAIN, DEFAULT_GAIN}, {SENSOR, OV7660_OFON, 0x0c}, {SENSOR, OV7660_COM2, 0x11}, {SENSOR, OV7660_COM7, 0x05}, -- cgit v1.2.3 From d43041857e7ee4406c5cc6f3d1783cd07cd2b9be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20Andr=C3=A9n?= Date: Sun, 25 Jan 2009 14:19:26 +0100 Subject: gspca - m5602: Add the ov7660 to the module parameter description. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: Erik Andrén Priority: normal Signed-off-by: Erik Andrén --- linux/drivers/media/video/gspca/m5602/m5602_core.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/m5602/m5602_core.c b/linux/drivers/media/video/gspca/m5602/m5602_core.c index 9147e3927..ca77dab90 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_core.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_core.c @@ -422,8 +422,9 @@ MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); module_param(force_sensor, int, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(force_sensor, - "force detection of sensor, " - "1 = OV9650, 2 = S5K83A, 3 = S5K4AA, 4 = MT9M111, 5 = PO1030"); + "forces detection of a sensor, " + "1 = OV9650, 2 = S5K83A, 3 = S5K4AA, " + "4 = MT9M111, 5 = PO1030, 6 = OV7660"); module_param(dump_bridge, bool, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(dump_bridge, "Dumps all usb bridge registers at startup"); -- cgit v1.2.3 From 0fb0c88f7ca6589aa418b4482651f144b200e965 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20Andr=C3=A9n?= Date: Sun, 25 Jan 2009 15:45:35 +0100 Subject: gspca - m5602-s5k4aa: Remove some unneeded init code. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: Erik Andrén Remove some redundant init from the s5k4aa. All these registers are programmed again later in the init phase Priority: normal Signed-off-by: Erik Andrén --- .../drivers/media/video/gspca/m5602/m5602_s5k4aa.h | 71 ---------------------- 1 file changed, 71 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.h b/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.h index 2349174ad..c8d909a1f 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.h @@ -175,79 +175,8 @@ static const unsigned char init_s5k4aa[][4] = {SENSOR, S5K4AA_PAGE_MAP, 0x02, 0x00}, {SENSOR, 0x0c, 0x05, 0x00}, {SENSOR, 0x02, 0x0e, 0x00}, - {SENSOR, 0x11, 0x00, 0x00}, - {SENSOR, 0x12, 0x00, 0x00}, - {SENSOR, S5K4AA_PAGE_MAP, 0x02, 0x00}, {SENSOR, S5K4AA_READ_MODE, 0xa0, 0x00}, {SENSOR, 0x37, 0x00, 0x00}, - {SENSOR, S5K4AA_ROWSTART_HI, 0x00, 0x00}, - {SENSOR, S5K4AA_ROWSTART_LO, 0x2a, 0x00}, - {SENSOR, S5K4AA_COLSTART_HI, 0x00, 0x00}, - {SENSOR, S5K4AA_COLSTART_LO, 0x0b, 0x00}, - {SENSOR, S5K4AA_WINDOW_HEIGHT_HI, 0x03, 0x00}, - {SENSOR, S5K4AA_WINDOW_HEIGHT_LO, 0xc4, 0x00}, - {SENSOR, S5K4AA_WINDOW_WIDTH_HI, 0x05, 0x00}, - {SENSOR, S5K4AA_WINDOW_WIDTH_LO, 0x08, 0x00}, - {SENSOR, S5K4AA_H_BLANK_HI__, 0x00, 0x00}, - {SENSOR, S5K4AA_H_BLANK_LO__, 0x48, 0x00}, - {SENSOR, S5K4AA_EXPOSURE_HI, 0x00, 0x00}, - {SENSOR, S5K4AA_EXPOSURE_LO, 0x43, 0x00}, - {SENSOR, 0x11, 0x04, 0x00}, - {SENSOR, 0x12, 0xc3, 0x00}, - {SENSOR, S5K4AA_PAGE_MAP, 0x02, 0x00}, - - {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06, 0x00}, - {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, - {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00}, - {BRIDGE, M5602_XB_SENSOR_TYPE, 0x08, 0x00}, - {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81, 0x00}, - {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82, 0x00}, - {BRIDGE, M5602_XB_SIG_INI, 0x01, 0x00}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, - /* VSYNC_PARA, VSYNC_PARA : img height 480 = 0x01e0 */ - {BRIDGE, M5602_XB_VSYNC_PARA, 0x01, 0x00}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0xe0, 0x00}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, - {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00}, - {BRIDGE, M5602_XB_SIG_INI, 0x02, 0x00}, - {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00}, - {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00}, - /* HSYNC_PARA, HSYNC_PARA : img width 640 = 0x0280 */ - {BRIDGE, M5602_XB_HSYNC_PARA, 0x02, 0x00}, - {BRIDGE, M5602_XB_HSYNC_PARA, 0x80, 0x00}, - {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00}, - {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, - {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xa0, 0x00}, /* 48 MHz */ - - {SENSOR, S5K4AA_PAGE_MAP, 0x02, 0x00}, - {SENSOR, S5K4AA_READ_MODE, S5K4AA_RM_H_FLIP | S5K4AA_RM_ROW_SKIP_2X - | S5K4AA_RM_COL_SKIP_2X, 0x00}, - /* 0x37 : Fix image stability when light is too bright and improves - * image quality in 640x480, but worsens it in 1280x1024 */ - {SENSOR, 0x37, 0x01, 0x00}, - /* ROWSTART_HI, ROWSTART_LO : 10 + (1024-960)/2 = 42 = 0x002a */ - {SENSOR, S5K4AA_ROWSTART_HI, 0x00, 0x00}, - {SENSOR, S5K4AA_ROWSTART_LO, 0x2a, 0x00}, - {SENSOR, S5K4AA_COLSTART_HI, 0x00, 0x00}, - {SENSOR, S5K4AA_COLSTART_LO, 0x0c, 0x00}, - /* window_height_hi, window_height_lo : 960 = 0x03c0 */ - {SENSOR, S5K4AA_WINDOW_HEIGHT_HI, 0x03, 0x00}, - {SENSOR, S5K4AA_WINDOW_HEIGHT_LO, 0xc0, 0x00}, - /* window_width_hi, window_width_lo : 1280 = 0x0500 */ - {SENSOR, S5K4AA_WINDOW_WIDTH_HI, 0x05, 0x00}, - {SENSOR, S5K4AA_WINDOW_WIDTH_LO, 0x00, 0x00}, - {SENSOR, S5K4AA_H_BLANK_HI__, 0x00, 0x00}, - {SENSOR, S5K4AA_H_BLANK_LO__, 0xa8, 0x00}, /* helps to sync... */ - {SENSOR, S5K4AA_EXPOSURE_HI, 0x01, 0x00}, - {SENSOR, S5K4AA_EXPOSURE_LO, 0x00, 0x00}, - {SENSOR, 0x11, 0x04, 0x00}, - {SENSOR, 0x12, 0xc3, 0x00}, - {SENSOR, S5K4AA_PAGE_MAP, 0x02, 0x00}, - {SENSOR, 0x02, 0x0e, 0x00}, }; static const unsigned char VGA_s5k4aa[][4] = -- cgit v1.2.3 From 54ffa484e4edcf5daeade5cf0c25557497d08f37 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20Andr=C3=A9n?= Date: Sun, 25 Jan 2009 19:25:44 +0100 Subject: gspca - m5602-ov9650: Add image flip quirk for the ASUS A6VA MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: Johannes Klug Priority: normal Signed-off-by: Johannes Klug Signed-off-by: Erik Andrén --- linux/drivers/media/video/gspca/m5602/m5602_ov9650.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c index f0e335533..fcaf207c4 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c @@ -47,6 +47,14 @@ static #endif struct dmi_system_id ov9650_flip_dmi_table[] = { { + .ident = "ASUS A6VA", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "A6VA") + } + }, + { + .ident = "ASUS A6VC", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."), -- cgit v1.2.3 From 711a3b562c4751c854fd271f44c6e5f432bc09d6 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Tue, 27 Jan 2009 23:09:12 +0400 Subject: STB6100 init fix, the call to stb6100_set_bandwidth needs an argument in Hz not kHz, and a comment incorrectly says MHz instead of Hz. I don't know if this caused real problems anywhere From: Hans Werner Signed-off-by: Manu Abraham --- linux/drivers/media/dvb/frontends/stb6100.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/frontends/stb6100.c b/linux/drivers/media/dvb/frontends/stb6100.c index 29bc07b86..2b1af36b8 100644 --- a/linux/drivers/media/dvb/frontends/stb6100.c +++ b/linux/drivers/media/dvb/frontends/stb6100.c @@ -434,11 +434,11 @@ static int stb6100_init(struct dvb_frontend *fe) status->refclock = 27000000; /* Hz */ status->iqsense = 1; status->bandwidth = 36000; /* kHz */ - state->bandwidth = status->bandwidth * 1000; /* MHz */ + state->bandwidth = status->bandwidth * 1000; /* Hz */ state->reference = status->refclock / 1000; /* kHz */ /* Set default bandwidth. */ - return stb6100_set_bandwidth(fe, status->bandwidth); + return stb6100_set_bandwidth(fe, state->bandwidth); } static int stb6100_get_state(struct dvb_frontend *fe, -- cgit v1.2.3 From 84c19b03d182a3ad1a04fa4be0772ef587225fe6 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Tue, 27 Jan 2009 23:29:44 +0400 Subject: Report tuning algorith correctly From: Matthias Schwarzzot Signed-off-by: Manu Abraham --- linux/drivers/media/dvb/bt8xx/dst.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/bt8xx/dst.c b/linux/drivers/media/dvb/bt8xx/dst.c index 29e8f1546..fec1d77fa 100644 --- a/linux/drivers/media/dvb/bt8xx/dst.c +++ b/linux/drivers/media/dvb/bt8xx/dst.c @@ -1683,7 +1683,7 @@ static int dst_tune_frontend(struct dvb_frontend* fe, static int dst_get_tuning_algo(struct dvb_frontend *fe) { - return dst_algo; + return dst_algo ? DVBFE_ALGO_HW : DVBFE_ALGO_SW; } static int dst_get_frontend(struct dvb_frontend *fe, struct dvb_frontend_parameters *p) -- cgit v1.2.3 From 21d546ba42d5c8712c5e50f13963110b1a17bf28 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20Andr=C3=A9n?= Date: Wed, 28 Jan 2009 07:29:51 +0100 Subject: gspca - m5602-mt9m111: Disable QVGA until it has been verified to work MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: Erik Andrén The QVGA resolution currently hasn't been verified to work. Disable it for now. Priority: normal Signed-off-by: Erik Andrén --- linux/drivers/media/video/gspca/m5602/m5602_mt9m111.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.c b/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.c index ade7264d4..67400ba1b 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.c @@ -36,6 +36,7 @@ static int mt9m111_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val); static int mt9m111_set_red_balance(struct gspca_dev *gspca_dev, __s32 val); static struct v4l2_pix_format mt9m111_modes[] = { +#if 0 { 320, 240, @@ -45,7 +46,9 @@ static struct v4l2_pix_format mt9m111_modes[] = { .bytesperline = 320, .colorspace = V4L2_COLORSPACE_SRGB, .priv = 0 - }, { + }, +#endif + { 640, 480, V4L2_PIX_FMT_SBGGR8, -- cgit v1.2.3 From 9e835434ce6ebb47cb8fcef4fb4aa78071f37788 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20Andr=C3=A9n?= Date: Wed, 28 Jan 2009 07:34:02 +0100 Subject: gspca - m5602-po1030: Disable QVGA for now MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: Erik Andrén Getting QVGA to be supported on the po1030 seems harder than I first thought. I need access to the proper hardware in order to fix it up. Priority: normal Signed-off-by: Erik Andrén --- linux/drivers/media/video/gspca/m5602/m5602_po1030.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/m5602/m5602_po1030.c b/linux/drivers/media/video/gspca/m5602/m5602_po1030.c index 840a3ca53..7706bd29f 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_po1030.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_po1030.c @@ -42,6 +42,7 @@ static int po1030_get_auto_exposure(struct gspca_dev *gspca_dev, __s32 *val); static struct v4l2_pix_format po1030_modes[] = { +#if 0 { 320, 240, @@ -51,7 +52,9 @@ static struct v4l2_pix_format po1030_modes[] = { .bytesperline = 320, .colorspace = V4L2_COLORSPACE_SRGB, .priv = 2 - }, { + }, +#endif + { 640, 480, V4L2_PIX_FMT_SBGGR8, -- cgit v1.2.3 From cd2add238ace8333d560fa90cd3f246a25b91bb0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20Andr=C3=A9n?= Date: Wed, 28 Jan 2009 08:02:49 +0100 Subject: gspca - m5602: Remove some needless error checking and add comments MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: Erik Andrén Priority: normal Signed-off-by: Erik Andrén --- linux/drivers/media/video/gspca/m5602/m5602_core.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/m5602/m5602_core.c b/linux/drivers/media/video/gspca/m5602/m5602_core.c index ca77dab90..8ca5643f2 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_core.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_core.c @@ -112,18 +112,16 @@ int m5602_read_sensor(struct sd *sd, const u8 address, if (err < 0) return err; + /* Sensors with registers that only are one byte width are differently read */ + /* FIXME: This works with the ov9650, but has issues with the po1030 */ if (sd->sensor->i2c_regW == 1) { - err = m5602_write_bridge(sd, M5602_XB_I2C_CTRL, len); + err = m5602_write_bridge(sd, M5602_XB_I2C_CTRL, 1); if (err < 0) return err; err = m5602_write_bridge(sd, M5602_XB_I2C_CTRL, 0x08); - if (err < 0) - return err; } else { err = m5602_write_bridge(sd, M5602_XB_I2C_CTRL, 0x18 + len); - if (err < 0) - return err; } for (i = 0; (i < len) && !err; i++) { -- cgit v1.2.3 From 3d905953a3fb0f7b2c013ea00f18944f5612b8e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20Andr=C3=A9n?= Date: Mon, 27 Apr 2009 20:41:45 +0200 Subject: gspca - m5602: Probe the ov7660 sensor MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: Erik Andrén Priority: normal Signed-off-by: Erik Andrén --- linux/drivers/media/video/gspca/m5602/m5602_core.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/m5602/m5602_core.c b/linux/drivers/media/video/gspca/m5602/m5602_core.c index 8ca5643f2..36bdcda84 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_core.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_core.c @@ -17,6 +17,7 @@ */ #include "m5602_ov9650.h" +#include "m5602_ov7660.h" #include "m5602_mt9m111.h" #include "m5602_po1030.h" #include "m5602_s5k83a.h" @@ -217,6 +218,11 @@ static int m5602_probe_sensor(struct sd *sd) if (!sd->sensor->probe(sd)) return 0; + /* Try the ov7660 */ + sd->sensor = &ov7660; + if (!sd->sensor->probe(sd)) + return 0; + /* Try the s5k83a */ sd->sensor = &s5k83a; if (!sd->sensor->probe(sd)) -- cgit v1.2.3 From 747dc9fdc6b6205f3b51f9e11f1b0de7ce9db90a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20Andr=C3=A9n?= Date: Wed, 28 Jan 2009 17:14:34 +0100 Subject: gspca - m5602: Sort out macro conflict by adding a prefix MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: Erik Andrén Priority: normal Signed-off-by: Erik Andrén --- linux/drivers/media/video/gspca/m5602/m5602_mt9m111.c | 2 +- linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h | 2 +- linux/drivers/media/video/gspca/m5602/m5602_ov7660.c | 2 +- linux/drivers/media/video/gspca/m5602/m5602_ov7660.h | 12 ++++++------ 4 files changed, 9 insertions(+), 9 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.c b/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.c index 67400ba1b..a9780dfc7 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.c @@ -98,7 +98,7 @@ const static struct ctrl mt9m111_ctrls[] = { .minimum = 0, .maximum = (INITIAL_MAX_GAIN - 1) * 2 * 2 * 2, .step = 1, - .default_value = DEFAULT_GAIN, + .default_value = MT9M111_DEFAULT_GAIN, .flags = V4L2_CTRL_FLAG_SLIDER }, .set = mt9m111_set_gain, diff --git a/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h b/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h index 716aba523..e71ddb786 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h @@ -97,7 +97,7 @@ #define MT9M111_2D_DEFECT_CORRECTION_ENABLE (1 << 0) #define INITIAL_MAX_GAIN 64 -#define DEFAULT_GAIN 283 +#define MT9M111_DEFAULT_GAIN 283 #define MT9M111_GREEN_GAIN_DEFAULT 0x20 #define MT9M111_BLUE_GAIN_DEFAULT 0x20 #define MT9M111_RED_GAIN_DEFAULT 0x20 diff --git a/linux/drivers/media/video/gspca/m5602/m5602_ov7660.c b/linux/drivers/media/video/gspca/m5602/m5602_ov7660.c index bfa28de6c..7aafeb7cf 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_ov7660.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_ov7660.c @@ -31,7 +31,7 @@ const static struct ctrl ov7660_ctrls[] = { .minimum = 0x00, .maximum = 0xff, .step = 0x1, - .default_value = DEFAULT_GAIN, + .default_value = OV7660_DEFAULT_GAIN, .flags = V4L2_CTRL_FLAG_SLIDER }, .set = ov7660_set_gain, diff --git a/linux/drivers/media/video/gspca/m5602/m5602_ov7660.h b/linux/drivers/media/video/gspca/m5602/m5602_ov7660.h index 570715fff..3f2c169a9 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_ov7660.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_ov7660.h @@ -78,11 +78,11 @@ #define OV7660_HV 0x69 #define OV7660_RSVDA1 0xa1 -#define DEFAULT_GAIN 0x0e -#define DEFAULT_RED_GAIN 0x80 -#define DEFAULT_BLUE_GAIN 0x80 -#define DEFAULT_SATURATION 0x00 -#define DEFAULT_EXPOSURE 0x20 +#define OV7660_DEFAULT_GAIN 0x0e +#define OV7660_DEFAULT_RED_GAIN 0x80 +#define OV7660_DEFAULT_BLUE_GAIN 0x80 +#define OV7660_DEFAULT_SATURATION 0x00 +#define OV7660_DEFAULT_EXPOSURE 0x20 /* Kernel module parameters */ extern int force_sensor; @@ -177,7 +177,7 @@ static const unsigned char init_ov7660[][4] = {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x02}, {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0}, - {SENSOR, OV7660_AECH, DEFAULT_EXPOSURE}, + {SENSOR, OV7660_AECH, OV7660_DEFAULT_EXPOSURE}, {SENSOR, OV7660_COM1, 0x00}, {BRIDGE, M5602_XB_GPIO_DIR, 0x01}, -- cgit v1.2.3 From 16753aed2c1ac1d898461c6a35fe89c719ad5dd7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20Andr=C3=A9n?= Date: Thu, 29 Jan 2009 17:34:41 +0100 Subject: gspca - m5602-s5k4aa: Add experimental SXGA support. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: Erik Andrén Priority: normal Signed-off-by: Erik Andrén --- .../drivers/media/video/gspca/m5602/m5602_s5k4aa.c | 43 ++++++++++++++++++ .../drivers/media/video/gspca/m5602/m5602_s5k4aa.h | 52 ++++++++++++++++++++++ 2 files changed, 95 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c b/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c index 2c0940bff..b18d3237b 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c @@ -66,6 +66,17 @@ static }; static struct v4l2_pix_format s5k4aa_modes[] = { + { + 1280, + 1024, + V4L2_PIX_FMT_SBGGR8, + V4L2_FIELD_NONE, + .sizeimage = + 1280 * 1024, + .bytesperline = 1280, + .colorspace = V4L2_COLORSPACE_SRGB, + .priv = 0 + }, { 640, 480, @@ -259,6 +270,38 @@ int s5k4aa_start(struct sd *sd) struct cam *cam = &sd->gspca_dev.cam; switch (cam->cam_mode[sd->gspca_dev.curr_mode].width) { + case 1280: + PDEBUG(D_V4L2, "Configuring camera for SXGA mode"); + + for (i = 0; i < ARRAY_SIZE(SXGA_s5k4aa); i++) { + switch (SXGA_s5k4aa[i][0]) { + case BRIDGE: + err = m5602_write_bridge(sd, + SXGA_s5k4aa[i][1], + SXGA_s5k4aa[i][2]); + break; + + case SENSOR: + data[0] = SXGA_s5k4aa[i][2]; + err = m5602_write_sensor(sd, + SXGA_s5k4aa[i][1], + data, 1); + break; + + case SENSOR_LONG: + data[0] = SXGA_s5k4aa[i][2]; + data[1] = SXGA_s5k4aa[i][3]; + err = m5602_write_sensor(sd, + SXGA_s5k4aa[i][1], + data, 2); + break; + + default: + err("Invalid stream command, exiting init"); + return -EINVAL; + } + } + case 640: PDEBUG(D_V4L2, "Configuring camera for VGA mode"); diff --git a/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.h b/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.h index c8d909a1f..e0709a55e 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.h @@ -235,4 +235,56 @@ static const unsigned char VGA_s5k4aa[][4] = {SENSOR, 0x02, 0x0e, 0x00}, }; +static const unsigned char SXGA_s5k4aa[][4] = +{ + {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06, 0x00}, + {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, + {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00}, + {BRIDGE, M5602_XB_SENSOR_TYPE, 0x08, 0x00}, + {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81, 0x00}, + {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82, 0x00}, + {BRIDGE, M5602_XB_SIG_INI, 0x01, 0x00}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, + /* VSYNC_PARA, VSYNC_PARA : img height 1024 = 0x0400 */ + {BRIDGE, M5602_XB_VSYNC_PARA, 0x04, 0x00}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, + {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, + {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00}, + {BRIDGE, M5602_XB_SIG_INI, 0x02, 0x00}, + {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00}, + {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00}, + /* HSYNC_PARA, HSYNC_PARA : img width 1280 = 0x0500 */ + {BRIDGE, M5602_XB_HSYNC_PARA, 0x05, 0x00}, + {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00}, + {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00}, + {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, + {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xa0, 0x00}, /* 48 MHz */ + + {SENSOR, S5K4AA_PAGE_MAP, 0x02, 0x00}, + {SENSOR, S5K4AA_READ_MODE, S5K4AA_RM_H_FLIP | S5K4AA_RM_ROW_SKIP_2X + | S5K4AA_RM_COL_SKIP_2X, 0x00}, + {SENSOR, 0x37, 0x01, 0x00}, + {SENSOR, S5K4AA_ROWSTART_HI, 0x00, 0x00}, + {SENSOR, S5K4AA_ROWSTART_LO, 0x0a, 0x00}, + {SENSOR, S5K4AA_COLSTART_HI, 0x00, 0x00}, + {SENSOR, S5K4AA_COLSTART_LO, 0x0b, 0x00}, + {SENSOR, S5K4AA_WINDOW_HEIGHT_HI, 0x04, 0x00}, + {SENSOR, S5K4AA_WINDOW_HEIGHT_LO, 0x00, 0x00}, + {SENSOR, S5K4AA_WINDOW_WIDTH_HI, 0x05, 0x00}, + {SENSOR, S5K4AA_WINDOW_WIDTH_LO, 0x00, 0x00}, + {SENSOR, S5K4AA_H_BLANK_HI__, 0x00, 0x00}, + {SENSOR, S5K4AA_H_BLANK_LO__, 0xa8, 0x00}, + {SENSOR, S5K4AA_EXPOSURE_HI, 0x01, 0x00}, + {SENSOR, S5K4AA_EXPOSURE_LO, 0x00, 0x00}, + {SENSOR, 0x11, 0x04, 0x00}, + {SENSOR, 0x12, 0xc3, 0x00}, + {SENSOR, S5K4AA_PAGE_MAP, 0x02, 0x00}, + {SENSOR, 0x02, 0x0e, 0x00}, +}; + + #endif -- cgit v1.2.3 From c8d80c3e41a30668f485fad84257711c4061b18c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20Andr=C3=A9n?= Date: Mon, 2 Feb 2009 07:51:20 +0100 Subject: gspca - gspca-m5602: Constify parameters of two functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: Erik Andrén A number of parameters to some functions in the m5602 are constant and should be flagged as such. Priority: normal Signed-off-by: Erik Andrén --- linux/drivers/media/video/gspca/m5602/m5602_bridge.h | 4 ++-- linux/drivers/media/video/gspca/m5602/m5602_core.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/m5602/m5602_bridge.h b/linux/drivers/media/video/gspca/m5602/m5602_bridge.h index 34515e54c..1127a405c 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_bridge.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_bridge.h @@ -148,10 +148,10 @@ struct sd { }; int m5602_read_bridge( - struct sd *sd, u8 address, u8 *i2c_data); + struct sd *sd, const u8 address, u8 *i2c_data); int m5602_write_bridge( - struct sd *sd, u8 address, u8 i2c_data); + struct sd *sd, const u8 address, const u8 i2c_data); int m5602_write_sensor(struct sd *sd, const u8 address, u8 *i2c_data, const u8 len); diff --git a/linux/drivers/media/video/gspca/m5602/m5602_core.c b/linux/drivers/media/video/gspca/m5602/m5602_core.c index 36bdcda84..dd1024325 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_core.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_core.c @@ -36,7 +36,7 @@ static const __devinitdata struct usb_device_id m5602_table[] = { MODULE_DEVICE_TABLE(usb, m5602_table); /* Reads a byte from the m5602 */ -int m5602_read_bridge(struct sd *sd, u8 address, u8 *i2c_data) +int m5602_read_bridge(struct sd *sd, const u8 address, u8 *i2c_data) { int err; struct usb_device *udev = sd->gspca_dev.dev; @@ -57,7 +57,7 @@ int m5602_read_bridge(struct sd *sd, u8 address, u8 *i2c_data) } /* Writes a byte to to the m5602 */ -int m5602_write_bridge(struct sd *sd, u8 address, u8 i2c_data) +int m5602_write_bridge(struct sd *sd, const u8 address, const u8 i2c_data) { int err; struct usb_device *udev = sd->gspca_dev.dev; -- cgit v1.2.3 From 1b9286232ad7149cdc2b744f376894f66f011289 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20Andr=C3=A9n?= Date: Mon, 2 Feb 2009 19:56:39 +0100 Subject: gspca - m5602-s5k4aa: Disable SXGA resolution for now. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: Erik Andrén SXGA resolution needs more testing. Disable it for now Priority: normal Signed-off-by: Erik Andrén --- linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c b/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c index b18d3237b..97c06c5d0 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c @@ -66,6 +66,7 @@ static }; static struct v4l2_pix_format s5k4aa_modes[] = { +#if 0 { 1280, 1024, @@ -77,6 +78,7 @@ static struct v4l2_pix_format s5k4aa_modes[] = { .colorspace = V4L2_COLORSPACE_SRGB, .priv = 0 }, +#endif { 640, 480, -- cgit v1.2.3 From c2d3fb9ba38411d60945585f92142052c98856b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20Andr=C3=A9n?= Date: Mon, 2 Feb 2009 20:08:06 +0100 Subject: gspca - m5602-ov9650: Add missing v4l2 ctrl ids MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: Erik Andrén Red and blue balance missed their id fields Priority: normal Signed-off-by: Erik Andrén --- linux/drivers/media/video/gspca/m5602/m5602_ov9650.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c index 83fdff268..5378b8d40 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c @@ -133,6 +133,7 @@ static const struct ctrl ov9650_ctrls[] = { #define RED_BALANCE_IDX 2 { { + .id = V4L2_CID_RED_BALANCE, .type = V4L2_CTRL_TYPE_INTEGER, .name = "red balance", .minimum = 0x00, @@ -147,6 +148,7 @@ static const struct ctrl ov9650_ctrls[] = { #define BLUE_BALANCE_IDX 3 { { + .id = V4L2_CID_BLUE_BALANCE, .type = V4L2_CTRL_TYPE_INTEGER, .name = "blue balance", .minimum = 0x00, -- cgit v1.2.3 From ff2ca8d6442a3a606f70879d924dd159d06cda89 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 6 Feb 2009 22:59:35 +0100 Subject: v4l2-subdev: add support for TRY_FMT, ENUM_FMT and G/S_PARM. From: Hans Verkuil These ops are used by the ov7670 driver, so these need to be added. Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/v4l2-subdev.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/v4l2-subdev.c b/linux/drivers/media/video/v4l2-subdev.c index 923ec8d01..dc881671d 100644 --- a/linux/drivers/media/video/v4l2-subdev.c +++ b/linux/drivers/media/video/v4l2-subdev.c @@ -98,6 +98,10 @@ int v4l2_subdev_command(struct v4l2_subdev *sd, unsigned cmd, void *arg) return v4l2_subdev_call(sd, video, g_vbi_data, arg); case VIDIOC_G_SLICED_VBI_CAP: return v4l2_subdev_call(sd, video, g_sliced_vbi_cap, arg); + case VIDIOC_ENUM_FMT: + return v4l2_subdev_call(sd, video, enum_fmt, arg); + case VIDIOC_TRY_FMT: + return v4l2_subdev_call(sd, video, try_fmt, arg); case VIDIOC_S_FMT: return v4l2_subdev_call(sd, video, s_fmt, arg); case VIDIOC_G_FMT: @@ -112,6 +116,10 @@ int v4l2_subdev_command(struct v4l2_subdev *sd, unsigned cmd, void *arg) return v4l2_subdev_call(sd, video, s_stream, 1); case VIDIOC_STREAMOFF: return v4l2_subdev_call(sd, video, s_stream, 0); + case VIDIOC_S_PARM: + return v4l2_subdev_call(sd, video, s_parm, arg); + case VIDIOC_G_PARM: + return v4l2_subdev_call(sd, video, g_parm, arg); default: return v4l2_subdev_call(sd, core, ioctl, cmd, arg); -- cgit v1.2.3 From 7ca03eac2d8ff90a5ffc56ee23935a4daf31aabf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20Andr=C3=A9n?= Date: Thu, 12 Feb 2009 07:32:52 +0100 Subject: gspca - m5602-s5k4aa: Fixup SXGA resolution. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: Grégory Lardière The SXGA resolution doesn't work unless you first force the VGA resolution. More investigation is needed in order to fix this the "right" way. Priority: normal Signed-off-by: Grégory Lardière Signed-off-by: Erik Andrén --- .../drivers/media/video/gspca/m5602/m5602_s5k4aa.c | 30 ++++++++++++---------- .../drivers/media/video/gspca/m5602/m5602_s5k4aa.h | 9 +++---- 2 files changed, 20 insertions(+), 19 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c b/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c index 97c06c5d0..48bf519c6 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c @@ -66,27 +66,25 @@ static }; static struct v4l2_pix_format s5k4aa_modes[] = { -#if 0 { - 1280, - 1024, + 640, + 480, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, .sizeimage = - 1280 * 1024, - .bytesperline = 1280, + 640 * 480, + .bytesperline = 640, .colorspace = V4L2_COLORSPACE_SRGB, .priv = 0 }, -#endif { - 640, - 480, + 1280, + 1024, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, .sizeimage = - 640 * 480, - .bytesperline = 640, + 1280 * 1024, + .bytesperline = 1280, .colorspace = V4L2_COLORSPACE_SRGB, .priv = 0 } @@ -303,6 +301,10 @@ int s5k4aa_start(struct sd *sd) return -EINVAL; } } + err = s5k4aa_set_noise(&sd->gspca_dev, 0); + if (err < 0) + return err; + break; case 640: PDEBUG(D_V4L2, "Configuring camera for VGA mode"); @@ -335,6 +337,10 @@ int s5k4aa_start(struct sd *sd) return -EINVAL; } } + err = s5k4aa_set_noise(&sd->gspca_dev, 1); + if (err < 0) + return err; + break; } return err; } @@ -389,10 +395,6 @@ int s5k4aa_init(struct sd *sd) if (err < 0) return err; - err = s5k4aa_set_noise(&sd->gspca_dev, sensor_settings[NOISE_SUPP_IDX]); - if (err < 0) - return err; - err = s5k4aa_set_vflip(&sd->gspca_dev, sensor_settings[VFLIP_IDX]); if (err < 0) return err; diff --git a/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.h b/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.h index e0709a55e..4440da4e7 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.h @@ -265,18 +265,17 @@ static const unsigned char SXGA_s5k4aa[][4] = {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xa0, 0x00}, /* 48 MHz */ {SENSOR, S5K4AA_PAGE_MAP, 0x02, 0x00}, - {SENSOR, S5K4AA_READ_MODE, S5K4AA_RM_H_FLIP | S5K4AA_RM_ROW_SKIP_2X - | S5K4AA_RM_COL_SKIP_2X, 0x00}, + {SENSOR, S5K4AA_READ_MODE, S5K4AA_RM_H_FLIP, 0x00}, {SENSOR, 0x37, 0x01, 0x00}, {SENSOR, S5K4AA_ROWSTART_HI, 0x00, 0x00}, - {SENSOR, S5K4AA_ROWSTART_LO, 0x0a, 0x00}, + {SENSOR, S5K4AA_ROWSTART_LO, 0x09, 0x00}, {SENSOR, S5K4AA_COLSTART_HI, 0x00, 0x00}, - {SENSOR, S5K4AA_COLSTART_LO, 0x0b, 0x00}, + {SENSOR, S5K4AA_COLSTART_LO, 0x0a, 0x00}, {SENSOR, S5K4AA_WINDOW_HEIGHT_HI, 0x04, 0x00}, {SENSOR, S5K4AA_WINDOW_HEIGHT_LO, 0x00, 0x00}, {SENSOR, S5K4AA_WINDOW_WIDTH_HI, 0x05, 0x00}, {SENSOR, S5K4AA_WINDOW_WIDTH_LO, 0x00, 0x00}, - {SENSOR, S5K4AA_H_BLANK_HI__, 0x00, 0x00}, + {SENSOR, S5K4AA_H_BLANK_HI__, 0x01, 0x00}, {SENSOR, S5K4AA_H_BLANK_LO__, 0xa8, 0x00}, {SENSOR, S5K4AA_EXPOSURE_HI, 0x01, 0x00}, {SENSOR, S5K4AA_EXPOSURE_LO, 0x00, 0x00}, -- cgit v1.2.3 From dda6c8332ecb0d0a4fc7b43de4318a01439078f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20Andr=C3=A9n?= Date: Thu, 12 Feb 2009 07:40:29 +0100 Subject: gspca - m5602-s5k4aa: Fixup the vflip/hflip. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: Grégory Lardière Ensure that the hflip and vflip is consistent when the sensor needs to be vflip quirked or not. Priority: normal Signed-off-by: Grégory Lardière Signed-off-by: Erik Andrén --- .../drivers/media/video/gspca/m5602/m5602_s5k4aa.c | 110 ++++++++------------- 1 file changed, 41 insertions(+), 69 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c b/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c index 48bf519c6..60dc77e2a 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c @@ -268,6 +268,7 @@ int s5k4aa_start(struct sd *sd) int i, err = 0; u8 data[2]; struct cam *cam = &sd->gspca_dev.cam; + s32 *sensor_settings = sd->sensor_priv; switch (cam->cam_mode[sd->gspca_dev.curr_mode].width) { case 1280: @@ -342,13 +343,37 @@ int s5k4aa_start(struct sd *sd) return err; break; } - return err; + if (err < 0) + return err; + + err = s5k4aa_set_exposure(&sd->gspca_dev, + sensor_settings[EXPOSURE_IDX]); + if (err < 0) + return err; + + err = s5k4aa_set_gain(&sd->gspca_dev, sensor_settings[GAIN_IDX]); + if (err < 0) + return err; + + err = s5k4aa_set_brightness(&sd->gspca_dev, + sensor_settings[BRIGHTNESS_IDX]); + if (err < 0) + return err; + + err = s5k4aa_set_noise(&sd->gspca_dev, sensor_settings[NOISE_SUPP_IDX]); + if (err < 0) + return err; + + err = s5k4aa_set_vflip(&sd->gspca_dev, sensor_settings[VFLIP_IDX]); + if (err < 0) + return err; + + return s5k4aa_set_hflip(&sd->gspca_dev, sensor_settings[HFLIP_IDX]); } int s5k4aa_init(struct sd *sd) { int i, err = 0; - s32 *sensor_settings = sd->sensor_priv; for (i = 0; i < ARRAY_SIZE(init_s5k4aa) && !err; i++) { u8 data[2] = {0x00, 0x00}; @@ -381,25 +406,7 @@ int s5k4aa_init(struct sd *sd) if (dump_sensor) s5k4aa_dump_registers(sd); - err = s5k4aa_set_exposure(&sd->gspca_dev, - sensor_settings[EXPOSURE_IDX]); - if (err < 0) - return err; - - err = s5k4aa_set_gain(&sd->gspca_dev, sensor_settings[GAIN_IDX]); - if (err < 0) - return err; - - err = s5k4aa_set_brightness(&sd->gspca_dev, - sensor_settings[BRIGHTNESS_IDX]); - if (err < 0) - return err; - - err = s5k4aa_set_vflip(&sd->gspca_dev, sensor_settings[VFLIP_IDX]); - if (err < 0) - return err; - - return s5k4aa_set_hflip(&sd->gspca_dev, sensor_settings[HFLIP_IDX]); + return err; } static int s5k4aa_get_exposure(struct gspca_dev *gspca_dev, __s32 *val) @@ -467,36 +474,19 @@ static int s5k4aa_set_vflip(struct gspca_dev *gspca_dev, __s32 val) if (err < 0) return err; - if (dmi_check_system(s5k4aa_vflip_dmi_table)) { + if (dmi_check_system(s5k4aa_vflip_dmi_table)) val = !val; - data = (data & 0x3f) | - (!sensor_settings[HFLIP_IDX] << 6) | - ((val & 0x01) << 7); - } else { - data = (data & 0x3f) | - (sensor_settings[HFLIP_IDX] << 6) | - ((val & 0x01) << 7); - } + data = ((data & ~S5K4AA_RM_V_FLIP) | ((val & 0x01) << 7)); err = m5602_write_sensor(sd, S5K4AA_READ_MODE, &data, 1); if (err < 0) return err; - if (val) { - err = m5602_read_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1); - if (err < 0) - return err; - - data++; - err = m5602_write_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1); - } else { - err = m5602_read_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1); - if (err < 0) - return err; - - data--; - err = m5602_write_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1); - } + err = m5602_read_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1); + if (err < 0) + return err; + data = (data & 0xfe) | !val; + err = m5602_write_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1); return err; } @@ -532,37 +522,19 @@ static int s5k4aa_set_hflip(struct gspca_dev *gspca_dev, __s32 val) if (err < 0) return err; - if (dmi_check_system(s5k4aa_vflip_dmi_table)) { + if (dmi_check_system(s5k4aa_vflip_dmi_table)) val = !val; - data = (data & 0x3f) | - (!sensor_settings[VFLIP_IDX] << 7) | - ((val & 0x01) << 6); - } else { - data = (data & 0x3f) | - (sensor_settings[VFLIP_IDX] << 7) | - ((val & 0x01) << 6); - } data = ((data & ~S5K4AA_RM_H_FLIP) | ((val & 0x01) << 6)); err = m5602_write_sensor(sd, S5K4AA_READ_MODE, &data, 1); if (err < 0) return err; - if (val) { - err = m5602_read_sensor(sd, S5K4AA_COLSTART_LO, &data, 1); - if (err < 0) - return err; - data++; - err = m5602_write_sensor(sd, S5K4AA_COLSTART_LO, &data, 1); - if (err < 0) - return err; - } else { - err = m5602_read_sensor(sd, S5K4AA_COLSTART_LO, &data, 1); - if (err < 0) - return err; - data--; - err = m5602_write_sensor(sd, S5K4AA_COLSTART_LO, &data, 1); - } + err = m5602_read_sensor(sd, S5K4AA_COLSTART_LO, &data, 1); + if (err < 0) + return err; + data = (data & 0xfe) | !val; + err = m5602_write_sensor(sd, S5K4AA_COLSTART_LO, &data, 1); return err; } -- cgit v1.2.3 From 42abf44d3269d94fac9261246b91a18e636b0632 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20Andr=C3=A9n?= Date: Thu, 12 Feb 2009 20:36:05 +0100 Subject: gspca - m5602-s5k4aa: Add vflip quirk for the MSI L735 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: Erik Andrén Priority: normal Signed-off-by: Erik Andrén --- linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c b/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c index 60dc77e2a..81f24d413 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c @@ -61,6 +61,12 @@ static DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International"), DMI_MATCH(DMI_PRODUCT_NAME, "GX700/GX705/EX700") } + }, { + .ident = "MSI L735", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International"), + DMI_MATCH(DMI_PRODUCT_NAME, "MS-1717X") + } }, { } }; -- cgit v1.2.3 From 6c7ed65e3ea76c36aec18b3c7d7fc97af216bf05 Mon Sep 17 00:00:00 2001 From: Patrick Boettcher Date: Sat, 28 Feb 2009 14:19:30 +0100 Subject: Fix i2c code of flexcop-driver for rare revisions From: Patrick Boettcher This patch adds a workaround in the i2c-code of the flexcop-driver to fix support for SkyStar2 rev 2.7. There are not many devices out there, that's why this bug was not revealed earlier. Priority: high Signed-off-by: Patrick Boettcher --- linux/drivers/media/dvb/b2c2/flexcop-i2c.c | 12 ++++++++++++ linux/drivers/media/dvb/frontends/itd1000_priv.h | 2 +- 2 files changed, 13 insertions(+), 1 deletion(-) (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 01d27613f..1c07eeafc 100644 --- a/linux/drivers/media/dvb/b2c2/flexcop-i2c.c +++ b/linux/drivers/media/dvb/b2c2/flexcop-i2c.c @@ -47,6 +47,18 @@ static int flexcop_i2c_read4(struct flexcop_i2c_adapter *i2c, int len = r100.tw_sm_c_100.total_bytes, /* remember total_bytes is buflen-1 */ ret; + /* work-around to have CableStar2 and SkyStar2 rev 2.7 work + * correctly: + * + * the ITD1000 is behind an i2c-gate which closes automatically + * after an i2c-transaction the STV0297 needs 2 consecutive reads + * one with no_base_addr = 0 and one with 1 + * + * those two work-arounds are conflictin: we check for the card + * type, it is set when probing the ITD1000 */ + if (i2c->fc->dev_type == FC_SKY_REV27) + r100.tw_sm_c_100.no_base_addr_ack_error = i2c->no_base_addr; + ret = flexcop_i2c_operation(i2c->fc, &r100); if (ret != 0) { deb_i2c("Retrying operation\n"); diff --git a/linux/drivers/media/dvb/frontends/itd1000_priv.h b/linux/drivers/media/dvb/frontends/itd1000_priv.h index 8cdc54e57..08ca85122 100644 --- a/linux/drivers/media/dvb/frontends/itd1000_priv.h +++ b/linux/drivers/media/dvb/frontends/itd1000_priv.h @@ -31,7 +31,7 @@ struct itd1000_state { /* ugly workaround for flexcop's incapable i2c-controller * FIXME, if possible */ - u8 shadow[255]; + u8 shadow[256]; }; enum itd1000_register { -- cgit v1.2.3 From 299a56025d357c1156cbe3b69689f37e5ac19eef Mon Sep 17 00:00:00 2001 From: Patrick Boettcher Date: Sat, 28 Feb 2009 14:30:20 +0100 Subject: Remove unecessary udelay From: Patrick Boettcher When resetting the PID-filter block a safety msleep(1) was injected. Now that the function is called from interrupt context, it was replaced with a udelay. It seems that this delay is not necessary at all, let's remove it for now and test a while. Priority: normal Signed-off-by: Patrick Boettcher --- linux/drivers/media/dvb/b2c2/flexcop.c | 1 - 1 file changed, 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/b2c2/flexcop.c b/linux/drivers/media/dvb/b2c2/flexcop.c index 91068952b..e836caece 100644 --- a/linux/drivers/media/dvb/b2c2/flexcop.c +++ b/linux/drivers/media/dvb/b2c2/flexcop.c @@ -212,7 +212,6 @@ void flexcop_reset_block_300(struct flexcop_device *fc) v210.sw_reset_210.Block_reset_enable = 0xb2; fc->write_ibi_reg(fc,sw_reset_210,v210); - udelay(1000); fc->write_ibi_reg(fc,ctrl_208,v208_save); } -- cgit v1.2.3 From de8c0bf3ec12371150c93adbcd7216b97003305b Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 3 Mar 2009 09:33:41 +0100 Subject: gspca - most jpeg subdrivers: Change the JPEG header creation. From: Jean-Francois Moine Priority: normal Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/gspca/conex.c | 21 ++- linux/drivers/media/video/gspca/jpeg.h | 250 +++++------------------------- linux/drivers/media/video/gspca/mars.c | 23 ++- linux/drivers/media/video/gspca/sonixj.c | 94 +++++++---- linux/drivers/media/video/gspca/spca500.c | 22 ++- linux/drivers/media/video/gspca/stk014.c | 25 ++- linux/drivers/media/video/gspca/sunplus.c | 22 ++- linux/drivers/media/video/gspca/zc3xx.c | 18 ++- 8 files changed, 225 insertions(+), 250 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/conex.c b/linux/drivers/media/video/gspca/conex.c index de2e608bf..fd4df402b 100644 --- a/linux/drivers/media/video/gspca/conex.c +++ b/linux/drivers/media/video/gspca/conex.c @@ -23,7 +23,6 @@ #include "gspca.h" #define CONEX_CAM 1 /* special JPEG header */ -#define QUANT_VAL 0 /* quantization table */ #include "jpeg.h" MODULE_AUTHOR("Michel Xhaard "); @@ -37,6 +36,9 @@ struct sd { unsigned char brightness; unsigned char contrast; unsigned char colors; + u8 quality; + + u8 *jpeg_hdr; }; /* V4L2 controls supported by the driver */ @@ -820,6 +822,7 @@ static int sd_config(struct gspca_dev *gspca_dev, sd->brightness = BRIGHTNESS_DEF; sd->contrast = CONTRAST_DEF; sd->colors = COLOR_DEF; + sd->quality = 40; return 0; } @@ -836,6 +839,14 @@ static int sd_init(struct gspca_dev *gspca_dev) static int sd_start(struct gspca_dev *gspca_dev) { + struct sd *sd = (struct sd *) gspca_dev; + + /* create the JPEG header */ + sd->jpeg_hdr = kmalloc(JPEG_HDR_SZ, GFP_KERNEL); + jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width, + 0x22); /* JPEG 411 */ + jpeg_set_qual(sd->jpeg_hdr, sd->quality); + cx11646_initsize(gspca_dev); cx11646_fw(gspca_dev); cx_sensor(gspca_dev); @@ -846,8 +857,11 @@ static int sd_start(struct gspca_dev *gspca_dev) /* called on streamoff with alt 0 and on disconnect */ static void sd_stop0(struct gspca_dev *gspca_dev) { + struct sd *sd = (struct sd *) gspca_dev; int retry = 50; + kfree(sd->jpeg_hdr); + if (!gspca_dev->present) return; reg_w_val(gspca_dev, 0x0000, 0x00); @@ -873,6 +887,8 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, __u8 *data, /* isoc packet */ int len) /* iso packet length */ { + struct sd *sd = (struct sd *) gspca_dev; + if (data[0] == 0xff && data[1] == 0xd8) { /* start of frame */ @@ -880,7 +896,8 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, data, 0); /* put the JPEG header in the new frame */ - jpeg_put_header(gspca_dev, frame, 0x22); + gspca_frame_add(gspca_dev, FIRST_PACKET, frame, + sd->jpeg_hdr, JPEG_HDR_SZ); data += 2; len -= 2; } diff --git a/linux/drivers/media/video/gspca/jpeg.h b/linux/drivers/media/video/gspca/jpeg.h index 7d2df9720..de63c3680 100644 --- a/linux/drivers/media/video/gspca/jpeg.h +++ b/linux/drivers/media/video/gspca/jpeg.h @@ -27,42 +27,16 @@ /* * generation options * CONEX_CAM Conexant if present - * QUANT_VAL quantization table (0..8) */ -/* - * JPEG header: - * - start of jpeg frame - * - quantization table - * - huffman table - * - start of SOF0 - */ +/* JPEG header */ static const u8 jpeg_head[] = { 0xff, 0xd8, /* jpeg */ + +/* quantization table quality 50% */ 0xff, 0xdb, 0x00, 0x84, /* DQT */ -#if QUANT_VAL == 0 -/* index 0 - Q40*/ -0, /* quantization table part 1 */ - 0x14, 0x0e, 0x0f, 0x12, 0x0f, 0x0d, 0x14, 0x12, - 0x10, 0x12, 0x17, 0x15, 0x14, 0x18, 0x1e, 0x32, - 0x21, 0x1e, 0x1c, 0x1c, 0x1e, 0x3d, 0x2c, 0x2e, - 0x24, 0x32, 0x49, 0x40, 0x4c, 0x4b, 0x47, 0x40, - 0x46, 0x45, 0x50, 0x5a, 0x73, 0x62, 0x50, 0x55, - 0x6d, 0x56, 0x45, 0x46, 0x64, 0x88, 0x65, 0x6d, - 0x77, 0x7b, 0x81, 0x82, 0x81, 0x4e, 0x60, 0x8d, - 0x97, 0x8c, 0x7d, 0x96, 0x73, 0x7e, 0x81, 0x7c, -1, /* quantization table part 2 */ - 0x15, 0x17, 0x17, 0x1e, 0x1a, 0x1e, 0x3b, 0x21, - 0x21, 0x3b, 0x7c, 0x53, 0x46, 0x53, 0x7c, 0x0c, - 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, - 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, - 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, - 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, - 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, - 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, -#elif QUANT_VAL == 1 -/* index 1 - Q50 */ 0, +#define JPEG_QT0_OFFSET 7 0x10, 0x0b, 0x0c, 0x0e, 0x0c, 0x0a, 0x10, 0x0e, 0x0d, 0x0e, 0x12, 0x11, 0x10, 0x13, 0x18, 0x28, 0x1a, 0x18, 0x16, 0x16, 0x18, 0x31, 0x23, 0x25, @@ -72,6 +46,7 @@ static const u8 jpeg_head[] = { 0x5f, 0x62, 0x67, 0x68, 0x67, 0x3e, 0x4d, 0x71, 0x79, 0x70, 0x64, 0x78, 0x5c, 0x65, 0x67, 0x63, 1, +#define JPEG_QT1_OFFSET 72 0x11, 0x12, 0x12, 0x18, 0x15, 0x18, 0x2f, 0x1a, 0x1a, 0x2f, 0x63, 0x42, 0x38, 0x42, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, @@ -80,149 +55,6 @@ static const u8 jpeg_head[] = { 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, -#elif QUANT_VAL == 2 -/* index 2 Q60 */ -0, - 0x0d, 0x09, 0x0a, 0x0b, 0x0a, 0x08, 0x0d, 0x0b, - 0x0a, 0x0b, 0x0e, 0x0e, 0x0d, 0x0f, 0x13, 0x20, - 0x15, 0x13, 0x12, 0x12, 0x13, 0x27, 0x1c, 0x1e, - 0x17, 0x20, 0x2e, 0x29, 0x31, 0x30, 0x2e, 0x29, - 0x2d, 0x2c, 0x33, 0x3a, 0x4a, 0x3e, 0x33, 0x36, - 0x46, 0x37, 0x2c, 0x2d, 0x40, 0x57, 0x41, 0x46, - 0x4c, 0x4e, 0x52, 0x53, 0x52, 0x32, 0x3e, 0x5a, - 0x61, 0x5a, 0x50, 0x60, 0x4a, 0x51, 0x52, 0x4f, -1, - 0x0e, 0x0e, 0x0e, 0x13, 0x11, 0x13, 0x26, 0x15, - 0x15, 0x26, 0x4f, 0x35, 0x2d, 0x35, 0x4f, 0x4f, - 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, - 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, - 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, - 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, - 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, - 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, -#elif QUANT_VAL == 3 -/* index 3 - Q70 */ -0, - 0x0a, 0x07, 0x07, 0x08, 0x07, 0x06, 0x0a, 0x08, - 0x08, 0x08, 0x0b, 0x0a, 0x0a, 0x0b, 0x0e, 0x18, - 0x10, 0x0e, 0x0d, 0x0d, 0x0e, 0x1d, 0x15, 0x16, - 0x11, 0x18, 0x23, 0x1f, 0x25, 0x24, 0x22, 0x1f, - 0x22, 0x21, 0x26, 0x2b, 0x37, 0x2f, 0x26, 0x29, - 0x34, 0x29, 0x21, 0x22, 0x30, 0x41, 0x31, 0x34, - 0x39, 0x3b, 0x3e, 0x3e, 0x3e, 0x25, 0x2e, 0x44, - 0x49, 0x43, 0x3c, 0x48, 0x37, 0x3d, 0x3e, 0x3b, -1, - 0x0a, 0x0b, 0x0b, 0x0e, 0x0d, 0x0e, 0x1c, 0x10, - 0x10, 0x1c, 0x3b, 0x28, 0x22, 0x28, 0x3b, 0x3b, - 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, - 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, - 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, - 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, - 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, - 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, -#elif QUANT_VAL == 4 -/* index 4 - Q80 */ -0, - 0x06, 0x04, 0x05, 0x06, 0x05, 0x04, 0x06, 0x06, - 0x05, 0x06, 0x07, 0x07, 0x06, 0x08, 0x0a, 0x10, - 0x0a, 0x0a, 0x09, 0x09, 0x0a, 0x14, 0x0e, 0x0f, - 0x0c, 0x10, 0x17, 0x14, 0x18, 0x18, 0x17, 0x14, - 0x16, 0x16, 0x1a, 0x1d, 0x25, 0x1f, 0x1a, 0x1b, - 0x23, 0x1c, 0x16, 0x16, 0x20, 0x2c, 0x20, 0x23, - 0x26, 0x27, 0x29, 0x2a, 0x29, 0x19, 0x1f, 0x2d, - 0x30, 0x2d, 0x28, 0x30, 0x25, 0x28, 0x29, 0x28, -1, - 0x07, 0x07, 0x07, 0x0a, 0x08, 0x0a, 0x13, 0x0a, - 0x0a, 0x13, 0x28, 0x1a, 0x16, 0x1a, 0x28, 0x28, - 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, - 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, - 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, - 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, - 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, - 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, -#elif QUANT_VAL == 5 -/* index 5 - Q85 */ -0, - 0x05, 0x03, 0x04, 0x04, 0x04, 0x03, 0x05, 0x04, - 0x04, 0x04, 0x05, 0x05, 0x05, 0x06, 0x07, 0x0c, - 0x08, 0x07, 0x07, 0x07, 0x07, 0x0f, 0x0b, 0x0b, - 0x09, 0x0c, 0x11, 0x0f, 0x12, 0x12, 0x11, 0x0f, - 0x11, 0x11, 0x13, 0x16, 0x1c, 0x17, 0x13, 0x14, - 0x1a, 0x15, 0x11, 0x11, 0x18, 0x21, 0x18, 0x1a, - 0x1d, 0x1d, 0x1f, 0x1f, 0x1f, 0x13, 0x17, 0x22, - 0x24, 0x22, 0x1e, 0x24, 0x1c, 0x1e, 0x1f, 0x1e, -1, - 0x05, 0x05, 0x05, 0x07, 0x06, 0x07, 0x0e, 0x08, - 0x08, 0x0e, 0x1e, 0x14, 0x11, 0x14, 0x1e, 0x1e, - 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, - 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, - 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, - 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, - 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, - 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, -#elif QUANT_VAL == 6 -/* index 6 - 86 */ -0, - 0x04, 0x03, 0x03, 0x04, 0x03, 0x03, 0x04, 0x04, - 0x04, 0x04, 0x05, 0x05, 0x04, 0x05, 0x07, 0x0B, - 0x07, 0x07, 0x06, 0x06, 0x07, 0x0e, 0x0a, 0x0a, - 0x08, 0x0B, 0x10, 0x0e, 0x11, 0x11, 0x10, 0x0e, - 0x10, 0x0f, 0x12, 0x14, 0x1a, 0x16, 0x12, 0x13, - 0x18, 0x13, 0x0f, 0x10, 0x16, 0x1f, 0x17, 0x18, - 0x1b, 0x1b, 0x1d, 0x1d, 0x1d, 0x11, 0x16, 0x20, - 0x22, 0x1f, 0x1c, 0x22, 0x1a, 0x1c, 0x1d, 0x1c, -1, - 0x05, 0x05, 0x05, 0x07, 0x06, 0x07, 0x0D, 0x07, - 0x07, 0x0D, 0x1c, 0x12, 0x10, 0x12, 0x1c, 0x1c, - 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, - 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, - 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, - 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, - 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, - 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, -#elif QUANT_VAL == 7 -/* index 7 - 88 */ -0, - 0x04, 0x03, 0x03, 0x03, 0x03, 0x02, 0x04, 0x03, - 0x03, 0x03, 0x04, 0x04, 0x04, 0x05, 0x06, 0x0a, - 0x06, 0x06, 0x05, 0x05, 0x06, 0x0C, 0x08, 0x09, - 0x07, 0x0a, 0x0e, 0x0c, 0x0f, 0x0e, 0x0e, 0x0c, - 0x0d, 0x0d, 0x0f, 0x11, 0x16, 0x13, 0x0f, 0x10, - 0x15, 0x11, 0x0d, 0x0d, 0x13, 0x1a, 0x13, 0x15, - 0x17, 0x18, 0x19, 0x19, 0x19, 0x0f, 0x12, 0x1b, - 0x1d, 0x1b, 0x18, 0x1d, 0x16, 0x18, 0x19, 0x18, -1, - 0x04, 0x04, 0x04, 0x06, 0x05, 0x06, 0x0B, 0x06, - 0x06, 0x0B, 0x18, 0x10, 0x0d, 0x10, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, -#elif QUANT_VAL == 8 -/* index 8 - ?? */ -0, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x03, 0x05, - 0x03, 0x03, 0x03, 0x03, 0x03, 0x06, 0x04, 0x05, - 0x04, 0x05, 0x07, 0x06, 0x08, 0x08, 0x07, 0x06, - 0x07, 0x07, 0x08, 0x09, 0x0c, 0x0a, 0x08, 0x09, - 0x0B, 0x09, 0x07, 0x07, 0x0a, 0x0e, 0x0a, 0x0b, - 0x0c, 0x0c, 0x0d, 0x0d, 0x0d, 0x08, 0x0a, 0x0e, - 0x0f, 0x0e, 0x0d, 0x0f, 0x0c, 0x0d, 0x0d, 0x0c, -1, - 0x02, 0x02, 0x02, 0x03, 0x03, 0x03, 0x06, 0x03, - 0x03, 0x06, 0x0c, 0x08, 0x07, 0x08, 0x0c, 0x0c, - 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, - 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, - 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, - 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, - 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, - 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, -#else -#error "Invalid quantization table" -#endif /* huffman table */ 0xff, 0xc4, 0x01, 0xa2, @@ -280,55 +112,57 @@ static const u8 jpeg_head[] = { 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, #ifdef CONEX_CAM /* the Conexant frames start with SOF0 */ +#define JPEG_HDR_SZ 556 #else 0xff, 0xc0, 0x00, 0x11, /* SOF0 (start of frame 0 */ 0x08, /* data precision */ -#endif -}; - -#ifndef CONEX_CAM -/* variable part: - * 0x01, 0xe0, height - * 0x02, 0x80, width - * 0x03, component number - * 0x01, - * 0x21, samples Y - */ - -/* end of header */ -static u8 eoh[] = { +#define JPEG_HEIGHT_OFFSET 561 + 0x01, 0xe0, /* height */ + 0x02, 0x80, /* width */ + 0x03, /* component number */ + 0x01, + 0x21, /* samples Y */ 0x00, /* quant Y */ 0x02, 0x11, 0x01, /* samples CbCr - quant CbCr */ 0x03, 0x11, 0x01, 0xff, 0xda, 0x00, 0x0c, /* SOS (start of scan) */ 0x03, 0x01, 0x00, 0x02, 0x11, 0x03, 0x11, 0x00, 0x3f, 0x00 -}; +#define JPEG_HDR_SZ 589 #endif +}; -/* -- output the JPEG header -- */ -static void jpeg_put_header(struct gspca_dev *gspca_dev, - struct gspca_frame *frame, - int samplesY) +/* define the JPEG header */ +static void jpeg_define(u8 *jpeg_hdr, + int height, + int width, + int samplesY) { + memcpy(jpeg_hdr, jpeg_head, sizeof jpeg_head); #ifndef CONEX_CAM - u8 tmpbuf[8]; + jpeg_hdr[JPEG_HEIGHT_OFFSET + 0] = height >> 8; + jpeg_hdr[JPEG_HEIGHT_OFFSET + 1] = height & 0xff; + jpeg_hdr[JPEG_HEIGHT_OFFSET + 2] = width >> 8; + jpeg_hdr[JPEG_HEIGHT_OFFSET + 3] = width & 0xff; + jpeg_hdr[JPEG_HEIGHT_OFFSET + 6] = samplesY; #endif +} - gspca_frame_add(gspca_dev, FIRST_PACKET, frame, - jpeg_head, sizeof jpeg_head); -#ifndef CONEX_CAM - tmpbuf[0] = gspca_dev->height >> 8; - tmpbuf[1] = gspca_dev->height & 0xff; - tmpbuf[2] = gspca_dev->width >> 8; - tmpbuf[3] = gspca_dev->width & 0xff; - tmpbuf[4] = 0x03; /* component number */ - tmpbuf[5] = 0x01; /* first component */ - tmpbuf[6] = samplesY; - gspca_frame_add(gspca_dev, INTER_PACKET, frame, - tmpbuf, 7); - gspca_frame_add(gspca_dev, INTER_PACKET, frame, - eoh, sizeof eoh); -#endif +/* set the JPEG quality */ +static void jpeg_set_qual(u8 *jpeg_hdr, + int quality) +{ + int i, sc; + + if (quality < 50) + sc = 5000 / quality; + else + sc = 200 - quality * 2; + for (i = 0; i < 64; i++) { + jpeg_hdr[JPEG_QT0_OFFSET + i] = + (jpeg_head[JPEG_QT0_OFFSET + i] * sc + 50) / 100; + jpeg_hdr[JPEG_QT1_OFFSET + i] = + (jpeg_head[JPEG_QT1_OFFSET + i] * sc + 50) / 100; + } } #endif diff --git a/linux/drivers/media/video/gspca/mars.c b/linux/drivers/media/video/gspca/mars.c index 5d54893eb..39219e2f5 100644 --- a/linux/drivers/media/video/gspca/mars.c +++ b/linux/drivers/media/video/gspca/mars.c @@ -22,7 +22,6 @@ #define MODULE_NAME "mars" #include "gspca.h" -#define QUANT_VAL 1 /* quantization table */ #include "jpeg.h" MODULE_AUTHOR("Michel Xhaard "); @@ -37,6 +36,9 @@ struct sd { u8 colors; u8 gamma; u8 sharpness; + u8 quality; + + u8 *jpeg_hdr; }; /* V4L2 controls supported by the driver */ @@ -176,6 +178,7 @@ static int sd_config(struct gspca_dev *gspca_dev, sd->colors = COLOR_DEF; sd->gamma = GAMMA_DEF; sd->sharpness = SHARPNESS_DEF; + sd->quality = 50; gspca_dev->nbalt = 9; /* use the altsetting 08 */ return 0; } @@ -193,6 +196,12 @@ static int sd_start(struct gspca_dev *gspca_dev) u8 *data; int i; + /* create the JPEG header */ + sd->jpeg_hdr = kmalloc(JPEG_HDR_SZ, GFP_KERNEL); + jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width, + 0x21); /* JPEG 422 */ + jpeg_set_qual(sd->jpeg_hdr, sd->quality); + data = gspca_dev->usb_buf; data[0] = 0x01; /* address */ @@ -341,11 +350,19 @@ static void sd_stopN(struct gspca_dev *gspca_dev) PDEBUG(D_ERR, "Camera Stop failed"); } +static void sd_stop0(struct gspca_dev *gspca_dev) +{ + struct sd *sd = (struct sd *) gspca_dev; + + kfree(sd->jpeg_hdr); +} + static void sd_pkt_scan(struct gspca_dev *gspca_dev, struct gspca_frame *frame, /* target */ __u8 *data, /* isoc packet */ int len) /* iso packet length */ { + struct sd *sd = (struct sd *) gspca_dev; int p; if (len < 6) { @@ -368,7 +385,8 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, frame, data, p); /* put the JPEG header */ - jpeg_put_header(gspca_dev, frame, 0x21); + gspca_frame_add(gspca_dev, FIRST_PACKET, frame, + sd->jpeg_hdr, JPEG_HDR_SZ); data += p + 16; len -= p + 16; break; @@ -474,6 +492,7 @@ static const struct sd_desc sd_desc = { .init = sd_init, .start = sd_start, .stopN = sd_stopN, + .stop0 = sd_stop0, .pkt_scan = sd_pkt_scan, }; diff --git a/linux/drivers/media/video/gspca/sonixj.c b/linux/drivers/media/video/gspca/sonixj.c index 36d6f50be..ec419213a 100644 --- a/linux/drivers/media/video/gspca/sonixj.c +++ b/linux/drivers/media/video/gspca/sonixj.c @@ -22,7 +22,6 @@ #define MODULE_NAME "sonixj" #include "gspca.h" -#define QUANT_VAL 4 /* quantization table */ #include "jpeg.h" #define V4L2_CID_INFRARED (V4L2_CID_PRIVATE_BASE + 0) @@ -47,6 +46,10 @@ struct sd { u8 gamma; u8 vflip; /* ov7630/ov7648 only */ u8 infrared; /* mt9v111 only */ + u8 quality; /* image quality */ + u8 jpegqual; /* webcam quality */ + + u8 reg18; s8 ag_cnt; #define AG_CNT_START 13 @@ -68,6 +71,8 @@ struct sd { #define SENSOR_OV7660 7 #define SENSOR_SP80708 8 u8 i2c_base; + + u8 *jpeg_hdr; }; /* V4L2 controls supported by the driver */ @@ -867,25 +872,6 @@ static const u8 sp80708_sensor_init[][8] = { {} }; -static const u8 qtable4[] = { - 0x06, 0x04, 0x04, 0x06, 0x04, 0x04, 0x06, 0x06, - 0x06, 0x06, 0x08, 0x06, 0x06, 0x08, 0x0a, 0x11, - 0x0a, 0x0a, 0x08, 0x08, 0x0a, 0x15, 0x0f, 0x0f, - 0x0c, 0x11, 0x19, 0x15, 0x19, 0x19, 0x17, 0x15, - 0x17, 0x17, 0x1b, 0x1d, 0x25, 0x21, 0x1b, 0x1d, - 0x23, 0x1d, 0x17, 0x17, 0x21, 0x2e, 0x21, 0x23, - 0x27, 0x29, 0x2c, 0x2c, 0x2c, 0x19, 0x1f, 0x30, - 0x32, 0x2e, 0x29, 0x32, 0x25, 0x29, 0x2c, 0x29, - 0x06, 0x08, 0x08, 0x0a, 0x08, 0x0a, 0x13, 0x0a, - 0x0a, 0x13, 0x29, 0x1b, 0x17, 0x1b, 0x29, 0x29, - 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, - 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, - 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, - 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, - 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, - 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29 -}; - /* read bytes to gspca_dev->usb_buf */ static void reg_r(struct gspca_dev *gspca_dev, u16 value, int len) @@ -1325,6 +1311,8 @@ static int sd_config(struct gspca_dev *gspca_dev, else sd->vflip = 1; sd->infrared = INFRARED_DEF; + sd->quality = 80; + sd->jpegqual = 80; gspca_dev->ctrl_dis = ctrl_dis[sd->sensor]; return 0; @@ -1642,12 +1630,49 @@ static void setinfrared(struct sd *sd) #endif } +static void setjpegqual(struct gspca_dev *gspca_dev) +{ + struct sd *sd = (struct sd *) gspca_dev; + int i, sc; + + if (sd->jpegqual < 50) + sc = 5000 / sd->jpegqual; + else + sc = 200 - sd->jpegqual * 2; +#if USB_BUF_SZ < 64 +#error "No room enough in usb_buf for quantization table" +#endif + for (i = 0; i < 64; i++) + gspca_dev->usb_buf[i] = + (jpeg_head[JPEG_QT0_OFFSET + i] * sc + 50) / 100; + usb_control_msg(gspca_dev->dev, + usb_sndctrlpipe(gspca_dev->dev, 0), + 0x08, + USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, + 0x0100, 0, + gspca_dev->usb_buf, 64, + 500); + for (i = 0; i < 64; i++) + gspca_dev->usb_buf[i] = + (jpeg_head[JPEG_QT1_OFFSET + i] * sc + 50) / 100; + usb_control_msg(gspca_dev->dev, + usb_sndctrlpipe(gspca_dev->dev, 0), + 0x08, + USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, + 0x0140, 0, + gspca_dev->usb_buf, 64, + 500); + + sd->reg18 ^= 0x40; + reg_w1(gspca_dev, 0x18, sd->reg18); +} + /* -- start the camera -- */ static int sd_start(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; int i; - u8 reg1, reg17, reg18; + u8 reg1, reg17; const u8 *sn9c1xx; int mode; static const u8 C0[] = { 0x2d, 0x2d, 0x3a, 0x05, 0x04, 0x3f }; @@ -1656,6 +1681,12 @@ static int sd_start(struct gspca_dev *gspca_dev) static const u8 CE_ov76xx[] = { 0x32, 0xdd, 0x32, 0xdd }; + /* create the JPEG header */ + sd->jpeg_hdr = kmalloc(JPEG_HDR_SZ, GFP_KERNEL); + jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width, + 0x21); /* JPEG 422 */ + jpeg_set_qual(sd->jpeg_hdr, sd->quality); + sn9c1xx = sn_tb[(int) sd->sensor]; configure_gpio(gspca_dev, sn9c1xx); @@ -1816,13 +1847,9 @@ static int sd_start(struct gspca_dev *gspca_dev) } /* here change size mode 0 -> VGA; 1 -> CIF */ - reg18 = sn9c1xx[0x18] | (mode << 4); - reg_w1(gspca_dev, 0x18, reg18 | 0x40); - - reg_w(gspca_dev, 0x0100, qtable4, 0x40); - reg_w(gspca_dev, 0x0140, qtable4 + 0x40, 0x40); - - reg_w1(gspca_dev, 0x18, reg18); + sd->reg18 = sn9c1xx[0x18] | (mode << 4) | 0x40; + reg_w1(gspca_dev, 0x18, sd->reg18); + setjpegqual(gspca_dev); reg_w1(gspca_dev, 0x17, reg17); reg_w1(gspca_dev, 0x01, reg1); @@ -1884,6 +1911,13 @@ static void sd_stopN(struct gspca_dev *gspca_dev) reg_w1(gspca_dev, 0xf1, 0x00); } +static void sd_stop0(struct gspca_dev *gspca_dev) +{ + struct sd *sd = (struct sd *) gspca_dev; + + kfree(sd->jpeg_hdr); +} + static void do_autogain(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; @@ -1967,7 +2001,8 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, if (gspca_dev->last_packet_type == LAST_PACKET) { /* put the JPEG 422 header */ - jpeg_put_header(gspca_dev, frame, 0x21); + gspca_frame_add(gspca_dev, FIRST_PACKET, frame, + sd->jpeg_hdr, JPEG_HDR_SZ); } gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len); } @@ -2143,6 +2178,7 @@ static const struct sd_desc sd_desc = { .init = sd_init, .start = sd_start, .stopN = sd_stopN, + .stop0 = sd_stop0, .pkt_scan = sd_pkt_scan, .dq_callback = do_autogain, }; diff --git a/linux/drivers/media/video/gspca/spca500.c b/linux/drivers/media/video/gspca/spca500.c index 94caba63b..ab0f007e0 100644 --- a/linux/drivers/media/video/gspca/spca500.c +++ b/linux/drivers/media/video/gspca/spca500.c @@ -22,7 +22,6 @@ #define MODULE_NAME "spca500" #include "gspca.h" -#define QUANT_VAL 5 /* quantization table */ #include "jpeg.h" MODULE_AUTHOR("Michel Xhaard "); @@ -39,6 +38,7 @@ struct sd { unsigned char brightness; unsigned char contrast; unsigned char colors; + u8 quality; char subtype; #define AgfaCl20 0 @@ -56,6 +56,8 @@ struct sd { #define Optimedia 12 #define PalmPixDC85 13 #define ToptroIndus 14 + + u8 *jpeg_hdr; }; /* V4L2 controls supported by the driver */ @@ -657,6 +659,7 @@ static int sd_config(struct gspca_dev *gspca_dev, sd->brightness = BRIGHTNESS_DEF; sd->contrast = CONTRAST_DEF; sd->colors = COLOR_DEF; + sd->quality = 85; return 0; } @@ -682,6 +685,12 @@ static int sd_start(struct gspca_dev *gspca_dev) __u8 Data; __u8 xmult, ymult; + /* create the JPEG header */ + sd->jpeg_hdr = kmalloc(JPEG_HDR_SZ, GFP_KERNEL); + jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width, + 0x22); /* JPEG 411 */ + jpeg_set_qual(sd->jpeg_hdr, sd->quality); + if (sd->subtype == LogitechClickSmart310) { xmult = 0x16; ymult = 0x12; @@ -897,6 +906,13 @@ static void sd_stopN(struct gspca_dev *gspca_dev) gspca_dev->usb_buf[0]); } +static void sd_stop0(struct gspca_dev *gspca_dev) +{ + struct sd *sd = (struct sd *) gspca_dev; + + kfree(sd->jpeg_hdr); +} + static void sd_pkt_scan(struct gspca_dev *gspca_dev, struct gspca_frame *frame, /* target */ __u8 *data, /* isoc packet */ @@ -917,7 +933,8 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, ffd9, 2); /* put the JPEG header in the new frame */ - jpeg_put_header(gspca_dev, frame, 0x22); + gspca_frame_add(gspca_dev, FIRST_PACKET, frame, + sd->jpeg_hdr, JPEG_HDR_SZ); data += SPCA500_OFFSET_DATA; len -= SPCA500_OFFSET_DATA; @@ -1030,6 +1047,7 @@ static struct sd_desc sd_desc = { .init = sd_init, .start = sd_start, .stopN = sd_stopN, + .stop0 = sd_stop0, .pkt_scan = sd_pkt_scan, }; diff --git a/linux/drivers/media/video/gspca/stk014.c b/linux/drivers/media/video/gspca/stk014.c index d1d54edd8..dd007cb52 100644 --- a/linux/drivers/media/video/gspca/stk014.c +++ b/linux/drivers/media/video/gspca/stk014.c @@ -21,8 +21,6 @@ #define MODULE_NAME "stk014" #include "gspca.h" -#define QUANT_VAL 7 /* quantization table */ - /* <= 4 KO - 7: good (enough!) */ #include "jpeg.h" MODULE_AUTHOR("Jean-Francois Moine "); @@ -37,6 +35,9 @@ struct sd { unsigned char contrast; unsigned char colors; unsigned char lightfreq; + u8 quality; + + u8 *jpeg_hdr; }; /* V4L2 controls supported by the driver */ @@ -300,6 +301,7 @@ static int sd_config(struct gspca_dev *gspca_dev, sd->contrast = CONTRAST_DEF; sd->colors = COLOR_DEF; sd->lightfreq = FREQ_DEF; + sd->quality = 80; return 0; } @@ -323,8 +325,15 @@ static int sd_init(struct gspca_dev *gspca_dev) /* -- start the camera -- */ static int sd_start(struct gspca_dev *gspca_dev) { + struct sd *sd = (struct sd *) gspca_dev; int ret, value; + /* create the JPEG header */ + sd->jpeg_hdr = kmalloc(JPEG_HDR_SZ, GFP_KERNEL); + jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width, + 0x22); /* JPEG 411 */ + jpeg_set_qual(sd->jpeg_hdr, sd->quality); + /* work on alternate 1 */ usb_set_interface(gspca_dev->dev, gspca_dev->iface, 1); @@ -396,11 +405,19 @@ static void sd_stopN(struct gspca_dev *gspca_dev) PDEBUG(D_STREAM, "camera stopped"); } +static void sd_stop0(struct gspca_dev *gspca_dev) +{ + struct sd *sd = (struct sd *) gspca_dev; + + kfree(sd->jpeg_hdr); +} + static void sd_pkt_scan(struct gspca_dev *gspca_dev, struct gspca_frame *frame, /* target */ __u8 *data, /* isoc packet */ int len) /* iso packet length */ { + struct sd *sd = (struct sd *) gspca_dev; static unsigned char ffd9[] = {0xff, 0xd9}; /* a frame starts with: @@ -417,7 +434,8 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, ffd9, 2); /* put the JPEG 411 header */ - jpeg_put_header(gspca_dev, frame, 0x22); + gspca_frame_add(gspca_dev, FIRST_PACKET, frame, + sd->jpeg_hdr, JPEG_HDR_SZ); /* beginning of the frame */ #define STKHDRSZ 12 @@ -526,6 +544,7 @@ static const struct sd_desc sd_desc = { .init = sd_init, .start = sd_start, .stopN = sd_stopN, + .stop0 = sd_stop0, .pkt_scan = sd_pkt_scan, .querymenu = sd_querymenu, }; diff --git a/linux/drivers/media/video/gspca/sunplus.c b/linux/drivers/media/video/gspca/sunplus.c index fba6f98d1..ef900469c 100644 --- a/linux/drivers/media/video/gspca/sunplus.c +++ b/linux/drivers/media/video/gspca/sunplus.c @@ -22,7 +22,6 @@ #define MODULE_NAME "sunplus" #include "gspca.h" -#define QUANT_VAL 5 /* quantization table */ #include "jpeg.h" MODULE_AUTHOR("Michel Xhaard "); @@ -40,6 +39,7 @@ struct sd { unsigned char contrast; unsigned char colors; unsigned char autogain; + u8 quality; char bridge; #define BRIDGE_SPCA504 0 @@ -52,6 +52,8 @@ struct sd { #define LogitechClickSmart420 2 #define LogitechClickSmart820 3 #define MegapixV4 4 + + u8 *jpeg_hdr; }; /* V4L2 controls supported by the driver */ @@ -883,6 +885,7 @@ static int sd_config(struct gspca_dev *gspca_dev, sd->brightness = sd_ctrls[SD_BRIGHTNESS].qctrl.default_value; sd->contrast = sd_ctrls[SD_CONTRAST].qctrl.default_value; sd->colors = sd_ctrls[SD_COLOR].qctrl.default_value; + sd->quality = 85; return 0; } @@ -999,6 +1002,12 @@ static int sd_start(struct gspca_dev *gspca_dev) __u8 i; __u8 info[6]; + /* create the JPEG header */ + sd->jpeg_hdr = kmalloc(JPEG_HDR_SZ, GFP_KERNEL); + jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width, + 0x22); /* JPEG 411 */ + jpeg_set_qual(sd->jpeg_hdr, sd->quality); + if (sd->bridge == BRIDGE_SPCA504B) spca504B_setQtable(gspca_dev); spca504B_SetSizeType(gspca_dev); @@ -1108,6 +1117,13 @@ static void sd_stopN(struct gspca_dev *gspca_dev) } } +static void sd_stop0(struct gspca_dev *gspca_dev) +{ + struct sd *sd = (struct sd *) gspca_dev; + + kfree(sd->jpeg_hdr); +} + static void sd_pkt_scan(struct gspca_dev *gspca_dev, struct gspca_frame *frame, /* target */ __u8 *data, /* isoc packet */ @@ -1184,7 +1200,8 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, ffd9, 2); /* put the JPEG header in the new frame */ - jpeg_put_header(gspca_dev, frame, 0x22); + gspca_frame_add(gspca_dev, FIRST_PACKET, frame, + sd->jpeg_hdr, JPEG_HDR_SZ); } /* add 0x00 after 0xff */ @@ -1342,6 +1359,7 @@ static const struct sd_desc sd_desc = { .init = sd_init, .start = sd_start, .stopN = sd_stopN, + .stop0 = sd_stop0, .pkt_scan = sd_pkt_scan, }; diff --git a/linux/drivers/media/video/gspca/zc3xx.c b/linux/drivers/media/video/gspca/zc3xx.c index ad385b9a0..ffd53830e 100644 --- a/linux/drivers/media/video/gspca/zc3xx.c +++ b/linux/drivers/media/video/gspca/zc3xx.c @@ -23,6 +23,7 @@ #define MODULE_NAME "zc3xx" #include "gspca.h" +#include "jpeg.h" MODULE_AUTHOR("Michel Xhaard , " "Serge A. Suchkov "); @@ -32,7 +33,6 @@ MODULE_LICENSE("GPL"); static int force_sensor = -1; #define QUANT_VAL 1 /* quantization table */ -#include "jpeg.h" #include "zc3xx-reg.h" /* specific webcam descriptor */ @@ -45,6 +45,7 @@ struct sd { __u8 autogain; __u8 lightfreq; __u8 sharpness; + u8 quality; /* image quality */ signed char sensor; /* Type of image sensor chip */ /* !! values used in different tables */ @@ -69,6 +70,8 @@ struct sd { #define SENSOR_TAS5130C_VF0250 17 #define SENSOR_MAX 18 unsigned short chip_revision; + + u8 *jpeg_hdr; }; /* V4L2 controls supported by the driver */ @@ -7206,6 +7209,7 @@ static int sd_config(struct gspca_dev *gspca_dev, sd->gamma = gamma[(int) sd->sensor]; sd->autogain = sd_ctrls[SD_AUTOGAIN].qctrl.default_value; sd->lightfreq = sd_ctrls[SD_FREQ].qctrl.default_value; + sd->quality = 50; switch (sd->sensor) { case SENSOR_GC0305: @@ -7261,6 +7265,12 @@ static int sd_start(struct gspca_dev *gspca_dev) /* 17 */ }; + /* create the JPEG header */ + sd->jpeg_hdr = kmalloc(JPEG_HDR_SZ, GFP_KERNEL); + jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width, + 0x21); /* JPEG 422 */ + jpeg_set_qual(sd->jpeg_hdr, sd->quality); + mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv; zc3_init = init_tb[(int) sd->sensor][mode]; switch (sd->sensor) { @@ -7398,6 +7408,7 @@ static void sd_stop0(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; + kfree(sd->jpeg_hdr); if (!gspca_dev->present) return; send_unknown(gspca_dev->dev, sd->sensor); @@ -7408,12 +7419,15 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, __u8 *data, int len) { + struct sd *sd = (struct sd *) gspca_dev; if (data[0] == 0xff && data[1] == 0xd8) { /* start of frame */ frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame, data, 0); /* put the JPEG header in the new frame */ - jpeg_put_header(gspca_dev, frame, 0x21); + gspca_frame_add(gspca_dev, FIRST_PACKET, frame, + sd->jpeg_hdr, JPEG_HDR_SZ); + /* remove the webcam's header: * ff d8 ff fe 00 0e 00 00 ss ss 00 01 ww ww hh hh pp pp * - 'ss ss' is the frame sequence number (BE) -- cgit v1.2.3 From 001bc08cc9ccdaf3efc87846858fb8d555e7f9cf Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 2 Mar 2009 10:40:52 +0100 Subject: gspca - most jpeg subdrivers: Have the JPEG quality settable. From: Jean-Francois Moine The JPEG quality of the images (quantization tables) is now settable by the VIDIOC_S_JPEGCOMP ioctl. Priority: normal Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/gspca/conex.c | 35 ++++++++++++++++++++++++++++++- linux/drivers/media/video/gspca/mars.c | 35 ++++++++++++++++++++++++++++++- linux/drivers/media/video/gspca/sonixj.c | 35 ++++++++++++++++++++++++++++++- linux/drivers/media/video/gspca/spca500.c | 35 ++++++++++++++++++++++++++++++- linux/drivers/media/video/gspca/stk014.c | 35 ++++++++++++++++++++++++++++++- linux/drivers/media/video/gspca/sunplus.c | 35 ++++++++++++++++++++++++++++++- linux/drivers/media/video/gspca/zc3xx.c | 35 ++++++++++++++++++++++++++++++- 7 files changed, 238 insertions(+), 7 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/conex.c b/linux/drivers/media/video/gspca/conex.c index fd4df402b..219cfa6fb 100644 --- a/linux/drivers/media/video/gspca/conex.c +++ b/linux/drivers/media/video/gspca/conex.c @@ -37,6 +37,9 @@ struct sd { unsigned char contrast; unsigned char colors; u8 quality; +#define QUALITY_MIN 30 +#define QUALITY_MAX 60 +#define QUALITY_DEF 40 u8 *jpeg_hdr; }; @@ -822,7 +825,7 @@ static int sd_config(struct gspca_dev *gspca_dev, sd->brightness = BRIGHTNESS_DEF; sd->contrast = CONTRAST_DEF; sd->colors = COLOR_DEF; - sd->quality = 40; + sd->quality = QUALITY_DEF; return 0; } @@ -1000,6 +1003,34 @@ static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val) return 0; } +static int sd_set_jcomp(struct gspca_dev *gspca_dev, + struct v4l2_jpegcompression *jcomp) +{ + struct sd *sd = (struct sd *) gspca_dev; + + if (jcomp->quality < QUALITY_MIN) + sd->quality = QUALITY_MIN; + else if (jcomp->quality > QUALITY_MAX) + sd->quality = QUALITY_MAX; + else + sd->quality = jcomp->quality; + if (gspca_dev->streaming) + jpeg_set_qual(sd->jpeg_hdr, sd->quality); + return 0; +} + +static int sd_get_jcomp(struct gspca_dev *gspca_dev, + struct v4l2_jpegcompression *jcomp) +{ + struct sd *sd = (struct sd *) gspca_dev; + + memset(jcomp, 0, sizeof *jcomp); + jcomp->quality = sd->quality; + jcomp->jpeg_markers = V4L2_JPEG_MARKER_DHT + | V4L2_JPEG_MARKER_DQT; + return 0; +} + /* sub-driver description */ static struct sd_desc sd_desc = { .name = MODULE_NAME, @@ -1010,6 +1041,8 @@ static struct sd_desc sd_desc = { .start = sd_start, .stop0 = sd_stop0, .pkt_scan = sd_pkt_scan, + .get_jcomp = sd_get_jcomp, + .set_jcomp = sd_set_jcomp, }; /* -- module initialisation -- */ diff --git a/linux/drivers/media/video/gspca/mars.c b/linux/drivers/media/video/gspca/mars.c index 39219e2f5..789fd178a 100644 --- a/linux/drivers/media/video/gspca/mars.c +++ b/linux/drivers/media/video/gspca/mars.c @@ -37,6 +37,9 @@ struct sd { u8 gamma; u8 sharpness; u8 quality; +#define QUALITY_MIN 40 +#define QUALITY_MAX 70 +#define QUALITY_DEF 50 u8 *jpeg_hdr; }; @@ -178,7 +181,7 @@ static int sd_config(struct gspca_dev *gspca_dev, sd->colors = COLOR_DEF; sd->gamma = GAMMA_DEF; sd->sharpness = SHARPNESS_DEF; - sd->quality = 50; + sd->quality = QUALITY_DEF; gspca_dev->nbalt = 9; /* use the altsetting 08 */ return 0; } @@ -483,6 +486,34 @@ static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val) return 0; } +static int sd_set_jcomp(struct gspca_dev *gspca_dev, + struct v4l2_jpegcompression *jcomp) +{ + struct sd *sd = (struct sd *) gspca_dev; + + if (jcomp->quality < QUALITY_MIN) + sd->quality = QUALITY_MIN; + else if (jcomp->quality > QUALITY_MAX) + sd->quality = QUALITY_MAX; + else + sd->quality = jcomp->quality; + if (gspca_dev->streaming) + jpeg_set_qual(sd->jpeg_hdr, sd->quality); + return 0; +} + +static int sd_get_jcomp(struct gspca_dev *gspca_dev, + struct v4l2_jpegcompression *jcomp) +{ + struct sd *sd = (struct sd *) gspca_dev; + + memset(jcomp, 0, sizeof *jcomp); + jcomp->quality = sd->quality; + jcomp->jpeg_markers = V4L2_JPEG_MARKER_DHT + | V4L2_JPEG_MARKER_DQT; + return 0; +} + /* sub-driver description */ static const struct sd_desc sd_desc = { .name = MODULE_NAME, @@ -494,6 +525,8 @@ static const struct sd_desc sd_desc = { .stopN = sd_stopN, .stop0 = sd_stop0, .pkt_scan = sd_pkt_scan, + .get_jcomp = sd_get_jcomp, + .set_jcomp = sd_set_jcomp, }; /* -- module initialisation -- */ diff --git a/linux/drivers/media/video/gspca/sonixj.c b/linux/drivers/media/video/gspca/sonixj.c index ec419213a..a7fcc169d 100644 --- a/linux/drivers/media/video/gspca/sonixj.c +++ b/linux/drivers/media/video/gspca/sonixj.c @@ -47,6 +47,9 @@ struct sd { u8 vflip; /* ov7630/ov7648 only */ u8 infrared; /* mt9v111 only */ u8 quality; /* image quality */ +#define QUALITY_MIN 60 +#define QUALITY_MAX 95 +#define QUALITY_DEF 80 u8 jpegqual; /* webcam quality */ u8 reg18; @@ -1311,7 +1314,7 @@ static int sd_config(struct gspca_dev *gspca_dev, else sd->vflip = 1; sd->infrared = INFRARED_DEF; - sd->quality = 80; + sd->quality = QUALITY_DEF; sd->jpegqual = 80; gspca_dev->ctrl_dis = ctrl_dis[sd->sensor]; @@ -2169,6 +2172,34 @@ static int sd_getinfrared(struct gspca_dev *gspca_dev, __s32 *val) return 0; } +static int sd_set_jcomp(struct gspca_dev *gspca_dev, + struct v4l2_jpegcompression *jcomp) +{ + struct sd *sd = (struct sd *) gspca_dev; + + if (jcomp->quality < QUALITY_MIN) + sd->quality = QUALITY_MIN; + else if (jcomp->quality > QUALITY_MAX) + sd->quality = QUALITY_MAX; + else + sd->quality = jcomp->quality; + if (gspca_dev->streaming) + jpeg_set_qual(sd->jpeg_hdr, sd->quality); + return 0; +} + +static int sd_get_jcomp(struct gspca_dev *gspca_dev, + struct v4l2_jpegcompression *jcomp) +{ + struct sd *sd = (struct sd *) gspca_dev; + + memset(jcomp, 0, sizeof *jcomp); + jcomp->quality = sd->quality; + jcomp->jpeg_markers = V4L2_JPEG_MARKER_DHT + | V4L2_JPEG_MARKER_DQT; + return 0; +} + /* sub-driver description */ static const struct sd_desc sd_desc = { .name = MODULE_NAME, @@ -2181,6 +2212,8 @@ static const struct sd_desc sd_desc = { .stop0 = sd_stop0, .pkt_scan = sd_pkt_scan, .dq_callback = do_autogain, + .get_jcomp = sd_get_jcomp, + .set_jcomp = sd_set_jcomp, }; /* -- module initialisation -- */ diff --git a/linux/drivers/media/video/gspca/spca500.c b/linux/drivers/media/video/gspca/spca500.c index ab0f007e0..8cfb7cad9 100644 --- a/linux/drivers/media/video/gspca/spca500.c +++ b/linux/drivers/media/video/gspca/spca500.c @@ -39,6 +39,9 @@ struct sd { unsigned char contrast; unsigned char colors; u8 quality; +#define QUALITY_MIN 70 +#define QUALITY_MAX 95 +#define QUALITY_DEF 85 char subtype; #define AgfaCl20 0 @@ -659,7 +662,7 @@ static int sd_config(struct gspca_dev *gspca_dev, sd->brightness = BRIGHTNESS_DEF; sd->contrast = CONTRAST_DEF; sd->colors = COLOR_DEF; - sd->quality = 85; + sd->quality = QUALITY_DEF; return 0; } @@ -1038,6 +1041,34 @@ static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val) return 0; } +static int sd_set_jcomp(struct gspca_dev *gspca_dev, + struct v4l2_jpegcompression *jcomp) +{ + struct sd *sd = (struct sd *) gspca_dev; + + if (jcomp->quality < QUALITY_MIN) + sd->quality = QUALITY_MIN; + else if (jcomp->quality > QUALITY_MAX) + sd->quality = QUALITY_MAX; + else + sd->quality = jcomp->quality; + if (gspca_dev->streaming) + jpeg_set_qual(sd->jpeg_hdr, sd->quality); + return 0; +} + +static int sd_get_jcomp(struct gspca_dev *gspca_dev, + struct v4l2_jpegcompression *jcomp) +{ + struct sd *sd = (struct sd *) gspca_dev; + + memset(jcomp, 0, sizeof *jcomp); + jcomp->quality = sd->quality; + jcomp->jpeg_markers = V4L2_JPEG_MARKER_DHT + | V4L2_JPEG_MARKER_DQT; + return 0; +} + /* sub-driver description */ static struct sd_desc sd_desc = { .name = MODULE_NAME, @@ -1049,6 +1080,8 @@ static struct sd_desc sd_desc = { .stopN = sd_stopN, .stop0 = sd_stop0, .pkt_scan = sd_pkt_scan, + .get_jcomp = sd_get_jcomp, + .set_jcomp = sd_set_jcomp, }; /* -- module initialisation -- */ diff --git a/linux/drivers/media/video/gspca/stk014.c b/linux/drivers/media/video/gspca/stk014.c index dd007cb52..f25be20cf 100644 --- a/linux/drivers/media/video/gspca/stk014.c +++ b/linux/drivers/media/video/gspca/stk014.c @@ -36,6 +36,9 @@ struct sd { unsigned char colors; unsigned char lightfreq; u8 quality; +#define QUALITY_MIN 60 +#define QUALITY_MAX 95 +#define QUALITY_DEF 80 u8 *jpeg_hdr; }; @@ -301,7 +304,7 @@ static int sd_config(struct gspca_dev *gspca_dev, sd->contrast = CONTRAST_DEF; sd->colors = COLOR_DEF; sd->lightfreq = FREQ_DEF; - sd->quality = 80; + sd->quality = QUALITY_DEF; return 0; } @@ -535,6 +538,34 @@ static int sd_querymenu(struct gspca_dev *gspca_dev, return -EINVAL; } +static int sd_set_jcomp(struct gspca_dev *gspca_dev, + struct v4l2_jpegcompression *jcomp) +{ + struct sd *sd = (struct sd *) gspca_dev; + + if (jcomp->quality < QUALITY_MIN) + sd->quality = QUALITY_MIN; + else if (jcomp->quality > QUALITY_MAX) + sd->quality = QUALITY_MAX; + else + sd->quality = jcomp->quality; + if (gspca_dev->streaming) + jpeg_set_qual(sd->jpeg_hdr, sd->quality); + return 0; +} + +static int sd_get_jcomp(struct gspca_dev *gspca_dev, + struct v4l2_jpegcompression *jcomp) +{ + struct sd *sd = (struct sd *) gspca_dev; + + memset(jcomp, 0, sizeof *jcomp); + jcomp->quality = sd->quality; + jcomp->jpeg_markers = V4L2_JPEG_MARKER_DHT + | V4L2_JPEG_MARKER_DQT; + return 0; +} + /* sub-driver description */ static const struct sd_desc sd_desc = { .name = MODULE_NAME, @@ -547,6 +578,8 @@ static const struct sd_desc sd_desc = { .stop0 = sd_stop0, .pkt_scan = sd_pkt_scan, .querymenu = sd_querymenu, + .get_jcomp = sd_get_jcomp, + .set_jcomp = sd_set_jcomp, }; /* -- module initialisation -- */ diff --git a/linux/drivers/media/video/gspca/sunplus.c b/linux/drivers/media/video/gspca/sunplus.c index ef900469c..428b1e2b7 100644 --- a/linux/drivers/media/video/gspca/sunplus.c +++ b/linux/drivers/media/video/gspca/sunplus.c @@ -40,6 +40,9 @@ struct sd { unsigned char colors; unsigned char autogain; u8 quality; +#define QUALITY_MIN 70 +#define QUALITY_MAX 95 +#define QUALITY_DEF 85 char bridge; #define BRIDGE_SPCA504 0 @@ -885,7 +888,7 @@ static int sd_config(struct gspca_dev *gspca_dev, sd->brightness = sd_ctrls[SD_BRIGHTNESS].qctrl.default_value; sd->contrast = sd_ctrls[SD_CONTRAST].qctrl.default_value; sd->colors = sd_ctrls[SD_COLOR].qctrl.default_value; - sd->quality = 85; + sd->quality = QUALITY_DEF; return 0; } @@ -1350,6 +1353,34 @@ static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val) return 0; } +static int sd_set_jcomp(struct gspca_dev *gspca_dev, + struct v4l2_jpegcompression *jcomp) +{ + struct sd *sd = (struct sd *) gspca_dev; + + if (jcomp->quality < QUALITY_MIN) + sd->quality = QUALITY_MIN; + else if (jcomp->quality > QUALITY_MAX) + sd->quality = QUALITY_MAX; + else + sd->quality = jcomp->quality; + if (gspca_dev->streaming) + jpeg_set_qual(sd->jpeg_hdr, sd->quality); + return 0; +} + +static int sd_get_jcomp(struct gspca_dev *gspca_dev, + struct v4l2_jpegcompression *jcomp) +{ + struct sd *sd = (struct sd *) gspca_dev; + + memset(jcomp, 0, sizeof *jcomp); + jcomp->quality = sd->quality; + jcomp->jpeg_markers = V4L2_JPEG_MARKER_DHT + | V4L2_JPEG_MARKER_DQT; + return 0; +} + /* sub-driver description */ static const struct sd_desc sd_desc = { .name = MODULE_NAME, @@ -1361,6 +1392,8 @@ static const struct sd_desc sd_desc = { .stopN = sd_stopN, .stop0 = sd_stop0, .pkt_scan = sd_pkt_scan, + .get_jcomp = sd_get_jcomp, + .set_jcomp = sd_set_jcomp, }; /* -- module initialisation -- */ diff --git a/linux/drivers/media/video/gspca/zc3xx.c b/linux/drivers/media/video/gspca/zc3xx.c index ffd53830e..e2ab9c2eb 100644 --- a/linux/drivers/media/video/gspca/zc3xx.c +++ b/linux/drivers/media/video/gspca/zc3xx.c @@ -46,6 +46,9 @@ struct sd { __u8 lightfreq; __u8 sharpness; u8 quality; /* image quality */ +#define QUALITY_MIN 40 +#define QUALITY_MAX 60 +#define QUALITY_DEF 50 signed char sensor; /* Type of image sensor chip */ /* !! values used in different tables */ @@ -7209,7 +7212,7 @@ static int sd_config(struct gspca_dev *gspca_dev, sd->gamma = gamma[(int) sd->sensor]; sd->autogain = sd_ctrls[SD_AUTOGAIN].qctrl.default_value; sd->lightfreq = sd_ctrls[SD_FREQ].qctrl.default_value; - sd->quality = 50; + sd->quality = QUALITY_DEF; switch (sd->sensor) { case SENSOR_GC0305: @@ -7569,6 +7572,34 @@ static int sd_querymenu(struct gspca_dev *gspca_dev, return -EINVAL; } +static int sd_set_jcomp(struct gspca_dev *gspca_dev, + struct v4l2_jpegcompression *jcomp) +{ + struct sd *sd = (struct sd *) gspca_dev; + + if (jcomp->quality < QUALITY_MIN) + sd->quality = QUALITY_MIN; + else if (jcomp->quality > QUALITY_MAX) + sd->quality = QUALITY_MAX; + else + sd->quality = jcomp->quality; + if (gspca_dev->streaming) + jpeg_set_qual(sd->jpeg_hdr, sd->quality); + return 0; +} + +static int sd_get_jcomp(struct gspca_dev *gspca_dev, + struct v4l2_jpegcompression *jcomp) +{ + struct sd *sd = (struct sd *) gspca_dev; + + memset(jcomp, 0, sizeof *jcomp); + jcomp->quality = sd->quality; + jcomp->jpeg_markers = V4L2_JPEG_MARKER_DHT + | V4L2_JPEG_MARKER_DQT; + return 0; +} + static const struct sd_desc sd_desc = { .name = MODULE_NAME, .ctrls = sd_ctrls, @@ -7579,6 +7610,8 @@ static const struct sd_desc sd_desc = { .stop0 = sd_stop0, .pkt_scan = sd_pkt_scan, .querymenu = sd_querymenu, + .get_jcomp = sd_get_jcomp, + .set_jcomp = sd_set_jcomp, }; static const __devinitdata struct usb_device_id device_table[] = { -- cgit v1.2.3 From 446d4199a156728c0a046418719b2f3a0645ad84 Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Tue, 10 Mar 2009 19:28:16 -0700 Subject: zoran: Unify buffer descriptors From: Trent Piepho The zoran driver had two kinds of buffer descriptors, one for jpg buffers and one for raw buffers. They were mostly the same with only a couple different fields. A file handle had two sets of descriptors even though only one could be in use at once. I've combined the two kinds into a single buffer descriptor that has the different parts in a union. Each file handle (struct zoran_fh) now only has one set of buffers. The device itself (struct zoran) still has two since it can have both raw and jpg buffers in use at the same time. Along the way, I re-wrapped many lines that were ugly. Some code which was duplicated for both raw and jpg buffers is now merged. The code to setup buffers in zoran_open_init_session() can be merged, as can the code to delete the buffers in zoran_close_end_session(). Lots of code in zoran_vm_close() and zoran_mmap() is merged as well. Since there is now only one set of buffer size & count fields, it's important they get set correctly when changing modes. So I created helper functions to change fh->map_mode which also set the buffer size & count to the proper values. jpg_sync() should only be called in jpg mode, it used to be able to tell the difference between jpg mode active and raw mode, but now there is only one active field. In zoran_streamoff() the spin lock is held for the entire sequence of operations to disable streaming. Priority: normal Signed-off-by: Trent Piepho --- linux/drivers/media/video/zoran/zoran.h | 59 +- linux/drivers/media/video/zoran/zoran_device.c | 12 +- linux/drivers/media/video/zoran/zoran_driver.c | 836 +++++++++++-------------- 3 files changed, 393 insertions(+), 514 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/zoran/zoran.h b/linux/drivers/media/video/zoran/zoran.h index 8beada961..afecf32f1 100644 --- a/linux/drivers/media/video/zoran/zoran.h +++ b/linux/drivers/media/video/zoran/zoran.h @@ -172,6 +172,8 @@ Private IOCTL to set up for displaying MJPEG #endif #define V4L_MASK_FRAME (V4L_MAX_FRAME - 1) +#define MAX_FRAME (BUZ_MAX_FRAME > VIDEO_MAX_FRAME ? BUZ_MAX_FRAME : VIDEO_MAX_FRAME) + #include "zr36057.h" enum card_type { @@ -280,21 +282,21 @@ struct zoran_mapping { int count; }; -struct zoran_jpg_buffer { - struct zoran_mapping *map; - __le32 *frag_tab; /* addresses of frag table */ - u32 frag_tab_bus; /* same value cached to save time in ISR */ - enum zoran_buffer_state state; /* non-zero if corresponding buffer is in use in grab queue */ - struct zoran_sync bs; /* DONE: info to return to application */ -}; - -struct zoran_v4l_buffer { +struct zoran_buffer { struct zoran_mapping *map; - char *fbuffer; /* virtual address of frame buffer */ - unsigned long fbuffer_phys; /* physical address of frame buffer */ - unsigned long fbuffer_bus; /* bus address of frame buffer */ - enum zoran_buffer_state state; /* state: unused/pending/done */ - struct zoran_sync bs; /* DONE: info to return to application */ + enum zoran_buffer_state state; /* state: unused/pending/dma/done */ + struct zoran_sync bs; /* DONE: info to return to application */ + union { + struct { + __le32 *frag_tab; /* addresses of frag table */ + u32 frag_tab_bus; /* same value cached to save time in ISR */ + } jpg; + struct { + char *fbuffer; /* virtual address of frame buffer */ + unsigned long fbuffer_phys;/* physical address of frame buffer */ + unsigned long fbuffer_bus;/* bus address of frame buffer */ + } v4l; + }; }; enum zoran_lock_activity { @@ -304,19 +306,13 @@ enum zoran_lock_activity { }; /* buffer collections */ -struct zoran_jpg_struct { +struct zoran_buffer_col { enum zoran_lock_activity active; /* feature currently in use? */ - struct zoran_jpg_buffer buffer[BUZ_MAX_FRAME]; /* buffers */ - int num_buffers, buffer_size; + unsigned int num_buffers, buffer_size; + struct zoran_buffer buffer[MAX_FRAME]; /* buffers */ u8 allocated; /* Flag if buffers are allocated */ u8 need_contiguous; /* Flag if contiguous buffers are needed */ -}; - -struct zoran_v4l_struct { - enum zoran_lock_activity active; /* feature currently in use? */ - struct zoran_v4l_buffer buffer[VIDEO_MAX_FRAME]; /* buffers */ - int num_buffers, buffer_size; - u8 allocated; /* Flag if buffers are allocated */ + /* only applies to jpg buffers, raw buffers are always contiguous */ }; struct zoran; @@ -325,17 +321,16 @@ struct zoran; struct zoran_fh { struct zoran *zr; - enum zoran_map_mode map_mode; /* Flag which bufferset will map by next mmap() */ + enum zoran_map_mode map_mode; /* Flag which bufferset will map by next mmap() */ struct zoran_overlay_settings overlay_settings; - u32 *overlay_mask; /* overlay mask */ - enum zoran_lock_activity overlay_active; /* feature currently in use? */ + u32 *overlay_mask; /* overlay mask */ + enum zoran_lock_activity overlay_active;/* feature currently in use? */ - struct zoran_v4l_settings v4l_settings; /* structure with a lot of things to play with */ - struct zoran_v4l_struct v4l_buffers; /* V4L buffers' info */ + struct zoran_buffer_col buffers; /* buffers' info */ + struct zoran_v4l_settings v4l_settings; /* structure with a lot of things to play with */ struct zoran_jpg_settings jpg_settings; /* structure with a lot of things to play with */ - struct zoran_jpg_struct jpg_buffers; /* MJPEG buffers' info */ }; struct card_info { @@ -434,7 +429,7 @@ struct zoran { unsigned long v4l_pend_tail; unsigned long v4l_sync_tail; int v4l_pend[V4L_MAX_FRAME]; - struct zoran_v4l_struct v4l_buffers; /* V4L buffers' info */ + struct zoran_buffer_col v4l_buffers; /* V4L buffers' info */ /* Buz MJPEG parameters */ enum zoran_codec_mode codec_mode; /* status of codec */ @@ -461,7 +456,7 @@ struct zoran { int jpg_pend[BUZ_MAX_FRAME]; /* array indexed by frame number */ - struct zoran_jpg_struct jpg_buffers; /* MJPEG buffers' info */ + struct zoran_buffer_col jpg_buffers; /* MJPEG buffers' info */ /* Additional stuff for testing */ #ifdef CONFIG_PROC_FS diff --git a/linux/drivers/media/video/zoran/zoran_device.c b/linux/drivers/media/video/zoran/zoran_device.c index c2dfd4b67..06f2c9a34 100644 --- a/linux/drivers/media/video/zoran/zoran_device.c +++ b/linux/drivers/media/video/zoran/zoran_device.c @@ -1126,7 +1126,7 @@ zoran_feed_stat_com (struct zoran *zr) if (!(zr->stat_com[i] & cpu_to_le32(1))) break; zr->stat_com[i] = - cpu_to_le32(zr->jpg_buffers.buffer[frame].frag_tab_bus); + cpu_to_le32(zr->jpg_buffers.buffer[frame].jpg.frag_tab_bus); } else { /* fill 2 stat_com entries */ i = ((zr->jpg_dma_head - @@ -1134,9 +1134,9 @@ zoran_feed_stat_com (struct zoran *zr) if (!(zr->stat_com[i] & cpu_to_le32(1))) break; zr->stat_com[i] = - cpu_to_le32(zr->jpg_buffers.buffer[frame].frag_tab_bus); + cpu_to_le32(zr->jpg_buffers.buffer[frame].jpg.frag_tab_bus); zr->stat_com[i + 1] = - cpu_to_le32(zr->jpg_buffers.buffer[frame].frag_tab_bus); + cpu_to_le32(zr->jpg_buffers.buffer[frame].jpg.frag_tab_bus); } zr->jpg_buffers.buffer[frame].state = BUZ_STATE_DMA; zr->jpg_dma_head++; @@ -1156,7 +1156,7 @@ zoran_reap_stat_com (struct zoran *zr) u32 stat_com; unsigned int seq; unsigned int dif; - struct zoran_jpg_buffer *buffer; + struct zoran_buffer *buffer; int frame; /* In motion decompress we don't have a hardware frame counter, @@ -1299,7 +1299,7 @@ error_handler (struct zoran *zr, printk(KERN_INFO "stat_com frames:"); for (j = 0; j < BUZ_NUM_STAT_COM; j++) { for (i = 0; i < zr->jpg_buffers.num_buffers; i++) { - if (le32_to_cpu(zr->stat_com[j]) == zr->jpg_buffers.buffer[i].frag_tab_bus) + if (le32_to_cpu(zr->stat_com[j]) == zr->jpg_buffers.buffer[i].jpg.frag_tab_bus) printk(KERN_CONT "% d->%d", j, i); } } @@ -1443,7 +1443,7 @@ zoran_irq (int irq, /* Buffer address */ - reg = zr->v4l_buffers.buffer[frame].fbuffer_bus; + reg = zr->v4l_buffers.buffer[frame].v4l.fbuffer_bus; btwrite(reg, ZR36057_VDTR); if (zr->v4l_settings.height > BUZ_MAX_HEIGHT / 2) reg += zr->v4l_settings.bytesperline; diff --git a/linux/drivers/media/video/zoran/zoran_driver.c b/linux/drivers/media/video/zoran/zoran_driver.c index 4afd14308..32873ca52 100644 --- a/linux/drivers/media/video/zoran/zoran_driver.c +++ b/linux/drivers/media/video/zoran/zoran_driver.c @@ -194,6 +194,24 @@ zoran_v4l2_calc_bufsize (struct zoran_jpg_settings *settings) static void v4l_fbuffer_free(struct file *file); static void jpg_fbuffer_free(struct file *file); +/* Set mapping mode */ +static void map_mode_raw(struct zoran_fh *fh) +{ + fh->map_mode = ZORAN_MAP_MODE_RAW; + fh->buffers.buffer_size = v4l_bufsize; + fh->buffers.num_buffers = v4l_nbufs; +} +static void map_mode_jpg(struct zoran_fh *fh, int play) +{ + fh->map_mode = play ? ZORAN_MAP_MODE_JPG_PLAY : ZORAN_MAP_MODE_JPG_REC; + fh->buffers.buffer_size = jpg_bufsize; + fh->buffers.num_buffers = jpg_nbufs; +} +static inline const char *mode_name(enum zoran_map_mode mode) +{ + return mode == ZORAN_MAP_MODE_RAW ? "V4L" : "JPG"; +} + /* * Allocate the V4L grab buffers * @@ -208,15 +226,15 @@ v4l_fbuffer_alloc (struct file *file) int i, off; unsigned char *mem; - for (i = 0; i < fh->v4l_buffers.num_buffers; i++) { - if (fh->v4l_buffers.buffer[i].fbuffer) + for (i = 0; i < fh->buffers.num_buffers; i++) { + if (fh->buffers.buffer[i].v4l.fbuffer) dprintk(2, KERN_WARNING "%s: v4l_fbuffer_alloc() - buffer %d already allocated!?\n", ZR_DEVNAME(zr), i); //udelay(20); - mem = kmalloc(fh->v4l_buffers.buffer_size, GFP_KERNEL); + mem = kmalloc(fh->buffers.buffer_size, GFP_KERNEL); if (!mem) { dprintk(1, KERN_ERR @@ -225,12 +243,10 @@ v4l_fbuffer_alloc (struct file *file) v4l_fbuffer_free(file); return -ENOBUFS; } - fh->v4l_buffers.buffer[i].fbuffer = mem; - fh->v4l_buffers.buffer[i].fbuffer_phys = - virt_to_phys(mem); - fh->v4l_buffers.buffer[i].fbuffer_bus = - virt_to_bus(mem); - for (off = 0; off < fh->v4l_buffers.buffer_size; + fh->buffers.buffer[i].v4l.fbuffer = mem; + fh->buffers.buffer[i].v4l.fbuffer_phys = virt_to_phys(mem); + fh->buffers.buffer[i].v4l.fbuffer_bus = virt_to_bus(mem); + for (off = 0; off < fh->buffers.buffer_size; off += PAGE_SIZE) SetPageReserved(virt_to_page(mem + off)); dprintk(4, @@ -240,7 +256,7 @@ v4l_fbuffer_alloc (struct file *file) virt_to_bus(mem)); } - fh->v4l_buffers.allocated = 1; + fh->buffers.allocated = 1; return 0; } @@ -256,19 +272,19 @@ v4l_fbuffer_free (struct file *file) dprintk(4, KERN_INFO "%s: v4l_fbuffer_free()\n", ZR_DEVNAME(zr)); - for (i = 0; i < fh->v4l_buffers.num_buffers; i++) { - if (!fh->v4l_buffers.buffer[i].fbuffer) + for (i = 0; i < fh->buffers.num_buffers; i++) { + if (!fh->buffers.buffer[i].v4l.fbuffer) continue; - mem = fh->v4l_buffers.buffer[i].fbuffer; - for (off = 0; off < fh->v4l_buffers.buffer_size; + mem = fh->buffers.buffer[i].v4l.fbuffer; + for (off = 0; off < fh->buffers.buffer_size; off += PAGE_SIZE) ClearPageReserved(virt_to_page(mem + off)); - kfree((void *) fh->v4l_buffers.buffer[i].fbuffer); - fh->v4l_buffers.buffer[i].fbuffer = NULL; + kfree(fh->buffers.buffer[i].v4l.fbuffer); + fh->buffers.buffer[i].v4l.fbuffer = NULL; } - fh->v4l_buffers.allocated = 0; + fh->buffers.allocated = 0; } /* @@ -305,10 +321,10 @@ jpg_fbuffer_alloc (struct file *file) struct zoran_fh *fh = file->private_data; struct zoran *zr = fh->zr; int i, j, off; - unsigned long mem; + u8 *mem; - for (i = 0; i < fh->jpg_buffers.num_buffers; i++) { - if (fh->jpg_buffers.buffer[i].frag_tab) + for (i = 0; i < fh->buffers.num_buffers; i++) { + if (fh->buffers.buffer[i].jpg.frag_tab) dprintk(2, KERN_WARNING "%s: jpg_fbuffer_alloc() - buffer %d already allocated!?\n", @@ -316,7 +332,7 @@ jpg_fbuffer_alloc (struct file *file) /* Allocate fragment table for this buffer */ - mem = get_zeroed_page(GFP_KERNEL); + mem = (void *)get_zeroed_page(GFP_KERNEL); if (mem == 0) { dprintk(1, KERN_ERR @@ -325,17 +341,12 @@ jpg_fbuffer_alloc (struct file *file) jpg_fbuffer_free(file); return -ENOBUFS; } - fh->jpg_buffers.buffer[i].frag_tab = (__le32 *) mem; - fh->jpg_buffers.buffer[i].frag_tab_bus = - virt_to_bus((void *) mem); - - //if (alloc_contig) { - if (fh->jpg_buffers.need_contiguous) { - mem = - (unsigned long) kmalloc(fh->jpg_buffers. - buffer_size, - GFP_KERNEL); - if (mem == 0) { + fh->buffers.buffer[i].jpg.frag_tab = (__le32 *)mem; + fh->buffers.buffer[i].jpg.frag_tab_bus = virt_to_bus(mem); + + if (fh->buffers.need_contiguous) { + mem = kmalloc(fh->buffers.buffer_size, GFP_KERNEL); + if (mem == NULL) { dprintk(1, KERN_ERR "%s: jpg_fbuffer_alloc() - kmalloc failed for buffer %d\n", @@ -343,20 +354,17 @@ jpg_fbuffer_alloc (struct file *file) jpg_fbuffer_free(file); return -ENOBUFS; } - fh->jpg_buffers.buffer[i].frag_tab[0] = - cpu_to_le32(virt_to_bus((void *) mem)); - fh->jpg_buffers.buffer[i].frag_tab[1] = - cpu_to_le32(((fh->jpg_buffers.buffer_size / 4) << 1) | 1); - for (off = 0; off < fh->jpg_buffers.buffer_size; - off += PAGE_SIZE) + fh->buffers.buffer[i].jpg.frag_tab[0] = + cpu_to_le32(virt_to_bus(mem)); + fh->buffers.buffer[i].jpg.frag_tab[1] = + cpu_to_le32((fh->buffers.buffer_size >> 1) | 1); + for (off = 0; off < fh->buffers.buffer_size; off += PAGE_SIZE) SetPageReserved(virt_to_page(mem + off)); } else { /* jpg_bufsize is already page aligned */ - for (j = 0; - j < fh->jpg_buffers.buffer_size / PAGE_SIZE; - j++) { - mem = get_zeroed_page(GFP_KERNEL); - if (mem == 0) { + for (j = 0; j < fh->buffers.buffer_size / PAGE_SIZE; j++) { + mem = (void *)get_zeroed_page(GFP_KERNEL); + if (mem == NULL) { dprintk(1, KERN_ERR "%s: jpg_fbuffer_alloc() - get_zeroed_page failed for buffer %d\n", @@ -365,25 +373,23 @@ jpg_fbuffer_alloc (struct file *file) return -ENOBUFS; } - fh->jpg_buffers.buffer[i].frag_tab[2 * j] = - cpu_to_le32(virt_to_bus((void *) mem)); - fh->jpg_buffers.buffer[i].frag_tab[2 * j + - 1] = - cpu_to_le32((PAGE_SIZE / 4) << 1); + fh->buffers.buffer[i].jpg.frag_tab[2 * j] = + cpu_to_le32(virt_to_bus(mem)); + fh->buffers.buffer[i].jpg.frag_tab[2 * j + 1] = + cpu_to_le32((PAGE_SIZE >> 2) << 1); SetPageReserved(virt_to_page(mem)); } - fh->jpg_buffers.buffer[i].frag_tab[2 * j - 1] |= cpu_to_le32(1); + fh->buffers.buffer[i].jpg.frag_tab[2 * j - 1] |= cpu_to_le32(1); } } dprintk(4, KERN_DEBUG "%s: jpg_fbuffer_alloc() - %d KB allocated\n", ZR_DEVNAME(zr), - (fh->jpg_buffers.num_buffers * - fh->jpg_buffers.buffer_size) >> 10); + (fh->buffers.num_buffers * fh->buffers.buffer_size) >> 10); - fh->jpg_buffers.allocated = 1; + fh->buffers.allocated = 1; return 0; } @@ -397,42 +403,44 @@ jpg_fbuffer_free (struct file *file) int i, j, off; unsigned char *mem; __le32 frag_tab; + struct zoran_buffer *buffer; dprintk(4, KERN_DEBUG "%s: jpg_fbuffer_free()\n", ZR_DEVNAME(zr)); - for (i = 0; i < fh->jpg_buffers.num_buffers; i++) { - if (!fh->jpg_buffers.buffer[i].frag_tab) + for (i = 0, buffer = &fh->buffers.buffer[0]; + i < fh->buffers.num_buffers; i++, buffer++) { + if (!buffer->jpg.frag_tab) continue; - if (fh->jpg_buffers.need_contiguous) { - frag_tab = fh->jpg_buffers.buffer[i].frag_tab[0]; + if (fh->buffers.need_contiguous) { + frag_tab = buffer->jpg.frag_tab[0]; if (frag_tab) { - mem = (unsigned char *)bus_to_virt(le32_to_cpu(frag_tab)); - for (off = 0; off < fh->jpg_buffers.buffer_size; off += PAGE_SIZE) + mem = bus_to_virt(le32_to_cpu(frag_tab)); + for (off = 0; off < fh->buffers.buffer_size; off += PAGE_SIZE) ClearPageReserved(virt_to_page(mem + off)); kfree(mem); - fh->jpg_buffers.buffer[i].frag_tab[0] = 0; - fh->jpg_buffers.buffer[i].frag_tab[1] = 0; + buffer->jpg.frag_tab[0] = 0; + buffer->jpg.frag_tab[1] = 0; } } else { - for (j = 0; j < fh->jpg_buffers.buffer_size / PAGE_SIZE; j++) { - frag_tab = fh->jpg_buffers.buffer[i].frag_tab[2 * j]; + for (j = 0; j < fh->buffers.buffer_size / PAGE_SIZE; j++) { + frag_tab = buffer->jpg.frag_tab[2 * j]; if (!frag_tab) break; ClearPageReserved(virt_to_page(bus_to_virt(le32_to_cpu(frag_tab)))); free_page((unsigned long)bus_to_virt(le32_to_cpu(frag_tab))); - fh->jpg_buffers.buffer[i].frag_tab[2 * j] = 0; - fh->jpg_buffers.buffer[i].frag_tab[2 * j + 1] = 0; + buffer->jpg.frag_tab[2 * j] = 0; + buffer->jpg.frag_tab[2 * j + 1] = 0; } } - free_page((unsigned long)fh->jpg_buffers.buffer[i].frag_tab); - fh->jpg_buffers.buffer[i].frag_tab = NULL; + free_page((unsigned long)buffer->jpg.frag_tab); + buffer->jpg.frag_tab = NULL; } - fh->jpg_buffers.allocated = 0; + fh->buffers.allocated = 0; } /* @@ -440,12 +448,11 @@ jpg_fbuffer_free (struct file *file) */ static int -zoran_v4l_set_format (struct file *file, +zoran_v4l_set_format (struct zoran_fh *fh, int width, int height, const struct zoran_format *format) { - struct zoran_fh *fh = file->private_data; struct zoran *zr = fh->zr; int bpp; @@ -463,11 +470,11 @@ zoran_v4l_set_format (struct file *file, bpp = (format->depth + 7) / 8; /* Check against available buffer size */ - if (height * width * bpp > fh->v4l_buffers.buffer_size) { + if (height * width * bpp > fh->buffers.buffer_size) { dprintk(1, KERN_ERR "%s: v4l_set_format() - video buffer size (%d kB) is too small\n", - ZR_DEVNAME(zr), fh->v4l_buffers.buffer_size >> 10); + ZR_DEVNAME(zr), fh->buffers.buffer_size >> 10); return -EINVAL; } @@ -498,7 +505,7 @@ zoran_v4l_queue_frame (struct file *file, unsigned long flags; int res = 0; - if (!fh->v4l_buffers.allocated) { + if (!fh->buffers.allocated) { dprintk(1, KERN_ERR "%s: v4l_queue_frame() - buffers not yet allocated\n", @@ -507,7 +514,7 @@ zoran_v4l_queue_frame (struct file *file, } /* No grabbing outside the buffer range! */ - if (num >= fh->v4l_buffers.num_buffers || num < 0) { + if (num >= fh->buffers.num_buffers || num < 0) { dprintk(1, KERN_ERR "%s: v4l_queue_frame() - buffer %d is out of range\n", @@ -517,10 +524,10 @@ zoran_v4l_queue_frame (struct file *file, spin_lock_irqsave(&zr->spinlock, flags); - if (fh->v4l_buffers.active == ZORAN_FREE) { + if (fh->buffers.active == ZORAN_FREE) { if (zr->v4l_buffers.active == ZORAN_FREE) { - zr->v4l_buffers = fh->v4l_buffers; - fh->v4l_buffers.active = ZORAN_ACTIVE; + zr->v4l_buffers = fh->buffers; + fh->buffers.active = ZORAN_ACTIVE; } else { dprintk(1, KERN_ERR @@ -536,7 +543,7 @@ zoran_v4l_queue_frame (struct file *file, default: case BUZ_STATE_PEND: if (zr->v4l_buffers.active == ZORAN_FREE) { - fh->v4l_buffers.active = ZORAN_FREE; + fh->buffers.active = ZORAN_FREE; zr->v4l_buffers.allocated = 0; } res = -EBUSY; /* what are you doing? */ @@ -549,14 +556,12 @@ zoran_v4l_queue_frame (struct file *file, case BUZ_STATE_USER: /* since there is at least one unused buffer there's room for at least * one more pend[] entry */ - zr->v4l_pend[zr->v4l_pend_head++ & - V4L_MASK_FRAME] = num; + zr->v4l_pend[zr->v4l_pend_head++ & V4L_MASK_FRAME] = num; zr->v4l_buffers.buffer[num].state = BUZ_STATE_PEND; zr->v4l_buffers.buffer[num].bs.length = fh->v4l_settings.bytesperline * zr->v4l_settings.height; - fh->v4l_buffers.buffer[num] = - zr->v4l_buffers.buffer[num]; + fh->buffers.buffer[num] = zr->v4l_buffers.buffer[num]; break; } } @@ -564,7 +569,7 @@ zoran_v4l_queue_frame (struct file *file, spin_unlock_irqrestore(&zr->spinlock, flags); if (!res && zr->v4l_buffers.active == ZORAN_FREE) - zr->v4l_buffers.active = fh->v4l_buffers.active; + zr->v4l_buffers.active = fh->buffers.active; return res; } @@ -581,7 +586,7 @@ v4l_sync (struct file *file, struct zoran *zr = fh->zr; unsigned long flags; - if (fh->v4l_buffers.active == ZORAN_FREE) { + if (fh->buffers.active == ZORAN_FREE) { dprintk(1, KERN_ERR "%s: v4l_sync() - no grab active for this session\n", @@ -590,7 +595,7 @@ v4l_sync (struct file *file, } /* check passed-in frame number */ - if (frame >= fh->v4l_buffers.num_buffers || frame < 0) { + if (frame >= fh->buffers.num_buffers || frame < 0) { dprintk(1, KERN_ERR "%s: v4l_sync() - frame %d is invalid\n", ZR_DEVNAME(zr), frame); @@ -608,8 +613,7 @@ v4l_sync (struct file *file, /* wait on this buffer to get ready */ if (!wait_event_interruptible_timeout(zr->v4l_capq, - (zr->v4l_buffers.buffer[frame].state != BUZ_STATE_PEND), - 10*HZ)) + (zr->v4l_buffers.buffer[frame].state != BUZ_STATE_PEND), 10*HZ)) return -ETIME; if (signal_pending(current)) return -ERESTARTSYS; @@ -621,7 +625,7 @@ v4l_sync (struct file *file, ZR_DEVNAME(zr)); zr->v4l_buffers.buffer[frame].state = BUZ_STATE_USER; - fh->v4l_buffers.buffer[frame] = zr->v4l_buffers.buffer[frame]; + fh->buffers.buffer[frame] = zr->v4l_buffers.buffer[frame]; spin_lock_irqsave(&zr->spinlock, flags); @@ -629,8 +633,7 @@ v4l_sync (struct file *file, if (zr->v4l_pend_tail == zr->v4l_pend_head) { zr36057_set_memgrab(zr, 0); if (zr->v4l_buffers.active == ZORAN_ACTIVE) { - fh->v4l_buffers.active = zr->v4l_buffers.active = - ZORAN_FREE; + fh->buffers.active = zr->v4l_buffers.active = ZORAN_FREE; zr->v4l_buffers.allocated = 0; } } @@ -655,7 +658,7 @@ zoran_jpg_queue_frame (struct file *file, int res = 0; /* Check if buffers are allocated */ - if (!fh->jpg_buffers.allocated) { + if (!fh->buffers.allocated) { dprintk(1, KERN_ERR "%s: jpg_queue_frame() - buffers not yet allocated\n", @@ -664,7 +667,7 @@ zoran_jpg_queue_frame (struct file *file, } /* No grabbing outside the buffer range! */ - if (num >= fh->jpg_buffers.num_buffers || num < 0) { + if (num >= fh->buffers.num_buffers || num < 0) { dprintk(1, KERN_ERR "%s: jpg_queue_frame() - buffer %d out of range\n", @@ -684,10 +687,10 @@ zoran_jpg_queue_frame (struct file *file, return -EINVAL; } - if (fh->jpg_buffers.active == ZORAN_FREE) { + if (fh->buffers.active == ZORAN_FREE) { if (zr->jpg_buffers.active == ZORAN_FREE) { - zr->jpg_buffers = fh->jpg_buffers; - fh->jpg_buffers.active = ZORAN_ACTIVE; + zr->jpg_buffers = fh->buffers; + fh->buffers.active = ZORAN_ACTIVE; } else { dprintk(1, KERN_ERR @@ -714,18 +717,16 @@ zoran_jpg_queue_frame (struct file *file, case BUZ_STATE_USER: /* since there is at least one unused buffer there's room for at *least one more pend[] entry */ - zr->jpg_pend[zr->jpg_que_head++ & BUZ_MASK_FRAME] = - num; + zr->jpg_pend[zr->jpg_que_head++ & BUZ_MASK_FRAME] = num; zr->jpg_buffers.buffer[num].state = BUZ_STATE_PEND; - fh->jpg_buffers.buffer[num] = - zr->jpg_buffers.buffer[num]; + fh->buffers.buffer[num] = zr->jpg_buffers.buffer[num]; zoran_feed_stat_com(zr); break; default: case BUZ_STATE_DMA: case BUZ_STATE_PEND: if (zr->jpg_buffers.active == ZORAN_FREE) { - fh->jpg_buffers.active = ZORAN_FREE; + fh->buffers.active = ZORAN_FREE; zr->jpg_buffers.allocated = 0; } res = -EBUSY; /* what are you doing? */ @@ -735,9 +736,8 @@ zoran_jpg_queue_frame (struct file *file, spin_unlock_irqrestore(&zr->spinlock, flags); - if (!res && zr->jpg_buffers.active == ZORAN_FREE) { - zr->jpg_buffers.active = fh->jpg_buffers.active; - } + if (!res && zr->jpg_buffers.active == ZORAN_FREE) + zr->jpg_buffers.active = fh->buffers.active; return res; } @@ -754,15 +754,14 @@ jpg_qbuf (struct file *file, /* Does the user want to stop streaming? */ if (frame < 0) { if (zr->codec_mode == mode) { - if (fh->jpg_buffers.active == ZORAN_FREE) { + if (fh->buffers.active == ZORAN_FREE) { dprintk(1, KERN_ERR "%s: jpg_qbuf(-1) - session not active\n", ZR_DEVNAME(zr)); return -EINVAL; } - fh->jpg_buffers.active = zr->jpg_buffers.active = - ZORAN_FREE; + fh->buffers.active = zr->jpg_buffers.active = ZORAN_FREE; zr->jpg_buffers.allocated = 0; zr36057_enable_jpg(zr, BUZ_MODE_IDLE); return 0; @@ -798,7 +797,7 @@ jpg_sync (struct file *file, unsigned long flags; int frame; - if (fh->jpg_buffers.active == ZORAN_FREE) { + if (fh->buffers.active == ZORAN_FREE) { dprintk(1, KERN_ERR "%s: jpg_sync() - capture is not currently active\n", @@ -850,7 +849,7 @@ jpg_sync (struct file *file, *bs = zr->jpg_buffers.buffer[frame].bs; bs->frame = frame; zr->jpg_buffers.buffer[frame].state = BUZ_STATE_USER; - fh->jpg_buffers.buffer[frame] = zr->jpg_buffers.buffer[frame]; + fh->buffers.buffer[frame] = zr->jpg_buffers.buffer[frame]; spin_unlock_irqrestore(&zr->spinlock, flags); @@ -865,7 +864,7 @@ zoran_open_init_session (struct file *file) struct zoran *zr = fh->zr; /* Per default, map the V4L Buffers */ - fh->map_mode = ZORAN_MAP_MODE_RAW; + map_mode_raw(fh); /* take over the card's current settings */ fh->overlay_settings = zr->overlay_settings; @@ -875,32 +874,17 @@ zoran_open_init_session (struct file *file) /* v4l settings */ fh->v4l_settings = zr->v4l_settings; - - /* v4l_buffers */ - memset(&fh->v4l_buffers, 0, sizeof(struct zoran_v4l_struct)); - for (i = 0; i < VIDEO_MAX_FRAME; i++) { - fh->v4l_buffers.buffer[i].state = BUZ_STATE_USER; /* nothing going on */ - fh->v4l_buffers.buffer[i].bs.frame = i; - } - fh->v4l_buffers.allocated = 0; - fh->v4l_buffers.active = ZORAN_FREE; - fh->v4l_buffers.buffer_size = v4l_bufsize; - fh->v4l_buffers.num_buffers = v4l_nbufs; - /* jpg settings */ fh->jpg_settings = zr->jpg_settings; - /* jpg_buffers */ - memset(&fh->jpg_buffers, 0, sizeof(struct zoran_jpg_struct)); - for (i = 0; i < BUZ_MAX_FRAME; i++) { - fh->jpg_buffers.buffer[i].state = BUZ_STATE_USER; /* nothing going on */ - fh->jpg_buffers.buffer[i].bs.frame = i; + /* buffers */ + memset(&fh->buffers, 0, sizeof(fh->buffers)); + for (i = 0; i < MAX_FRAME; i++) { + fh->buffers.buffer[i].state = BUZ_STATE_USER; /* nothing going on */ + fh->buffers.buffer[i].bs.frame = i; } - fh->jpg_buffers.need_contiguous = zr->jpg_buffers.need_contiguous; - fh->jpg_buffers.allocated = 0; - fh->jpg_buffers.active = ZORAN_FREE; - fh->jpg_buffers.buffer_size = jpg_bufsize; - fh->jpg_buffers.num_buffers = jpg_nbufs; + fh->buffers.allocated = 0; + fh->buffers.active = ZORAN_FREE; } static void @@ -918,33 +902,33 @@ zoran_close_end_session (struct file *file) zr->overlay_mask = NULL; } - /* v4l capture */ - if (fh->v4l_buffers.active != ZORAN_FREE) { - unsigned long flags; + if (fh->map_mode == ZORAN_MAP_MODE_RAW) { + /* v4l capture */ + if (fh->buffers.active != ZORAN_FREE) { + unsigned long flags; - spin_lock_irqsave(&zr->spinlock, flags); - zr36057_set_memgrab(zr, 0); - zr->v4l_buffers.allocated = 0; - zr->v4l_buffers.active = fh->v4l_buffers.active = - ZORAN_FREE; - spin_unlock_irqrestore(&zr->spinlock, flags); - } + spin_lock_irqsave(&zr->spinlock, flags); + zr36057_set_memgrab(zr, 0); + zr->v4l_buffers.allocated = 0; + zr->v4l_buffers.active = fh->buffers.active = ZORAN_FREE; + spin_unlock_irqrestore(&zr->spinlock, flags); + } - /* v4l buffers */ - if (fh->v4l_buffers.allocated) - v4l_fbuffer_free(file); + /* v4l buffers */ + if (fh->buffers.allocated) + v4l_fbuffer_free(file); + } else { + /* jpg capture */ + if (fh->buffers.active != ZORAN_FREE) { + zr36057_enable_jpg(zr, BUZ_MODE_IDLE); + zr->jpg_buffers.allocated = 0; + zr->jpg_buffers.active = fh->buffers.active = ZORAN_FREE; + } - /* jpg capture */ - if (fh->jpg_buffers.active != ZORAN_FREE) { - zr36057_enable_jpg(zr, BUZ_MODE_IDLE); - zr->jpg_buffers.allocated = 0; - zr->jpg_buffers.active = fh->jpg_buffers.active = - ZORAN_FREE; + /* jpg buffers */ + if (fh->buffers.allocated) + jpg_fbuffer_free(file); } - - /* jpg buffers */ - if (fh->jpg_buffers.allocated) - jpg_fbuffer_free(file); } /* @@ -1383,15 +1367,15 @@ zoran_v4l2_buffer_status (struct zoran_fh *fh, int num) { struct zoran *zr = fh->zr; + unsigned long flags; buf->flags = V4L2_BUF_FLAG_MAPPED; switch (fh->map_mode) { case ZORAN_MAP_MODE_RAW: - /* check range */ - if (num < 0 || num >= fh->v4l_buffers.num_buffers || - !fh->v4l_buffers.allocated) { + if (num < 0 || num >= fh->buffers.num_buffers || + !fh->buffers.allocated) { dprintk(1, KERN_ERR "%s: v4l2_buffer_status() - wrong number or buffers not allocated\n", @@ -1399,17 +1383,33 @@ zoran_v4l2_buffer_status (struct zoran_fh *fh, return -EINVAL; } + spin_lock_irqsave(&zr->spinlock, flags); + dprintk(3, + KERN_DEBUG + "%s: %s() - raw active=%c, buffer %d: state=%c, map=%c\n", + ZR_DEVNAME(zr), __func__, + "FAL"[fh->buffers.active], num, + "UPMD"[zr->v4l_buffers.buffer[num].state], + fh->buffers.buffer[num].map ? 'Y' : 'N'); + spin_unlock_irqrestore(&zr->spinlock, flags); +#if 0 + /* Process is the one capturing? */ + if (fh->v4l_buffers.active != ZORAN_FREE && + /* Buffer ready to DQBUF? */ + zr->v4l_buffers.buffer[frame].state == BUZ_STATE_DONE) + res = POLLIN | POLLRDNORM; +#endif + buf->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - buf->length = fh->v4l_buffers.buffer_size; + buf->length = fh->buffers.buffer_size; /* get buffer */ - buf->bytesused = fh->v4l_buffers.buffer[num].bs.length; - if (fh->v4l_buffers.buffer[num].state == BUZ_STATE_DONE || - fh->v4l_buffers.buffer[num].state == BUZ_STATE_USER) { - buf->sequence = fh->v4l_buffers.buffer[num].bs.seq; + buf->bytesused = fh->buffers.buffer[num].bs.length; + if (fh->buffers.buffer[num].state == BUZ_STATE_DONE || + fh->buffers.buffer[num].state == BUZ_STATE_USER) { + buf->sequence = fh->buffers.buffer[num].bs.seq; buf->flags |= V4L2_BUF_FLAG_DONE; - buf->timestamp = - fh->v4l_buffers.buffer[num].bs.timestamp; + buf->timestamp = fh->buffers.buffer[num].bs.timestamp; } else { buf->flags |= V4L2_BUF_FLAG_QUEUED; } @@ -1425,8 +1425,8 @@ zoran_v4l2_buffer_status (struct zoran_fh *fh, case ZORAN_MAP_MODE_JPG_PLAY: /* check range */ - if (num < 0 || num >= fh->jpg_buffers.num_buffers || - !fh->jpg_buffers.allocated) { + if (num < 0 || num >= fh->buffers.num_buffers || + !fh->buffers.allocated) { dprintk(1, KERN_ERR "%s: v4l2_buffer_status() - wrong number or buffers not allocated\n", @@ -1437,16 +1437,14 @@ zoran_v4l2_buffer_status (struct zoran_fh *fh, buf->type = (fh->map_mode == ZORAN_MAP_MODE_JPG_REC) ? V4L2_BUF_TYPE_VIDEO_CAPTURE : V4L2_BUF_TYPE_VIDEO_OUTPUT; - buf->length = fh->jpg_buffers.buffer_size; + buf->length = fh->buffers.buffer_size; /* these variables are only written after frame has been captured */ - if (fh->jpg_buffers.buffer[num].state == BUZ_STATE_DONE || - fh->jpg_buffers.buffer[num].state == BUZ_STATE_USER) { - buf->sequence = fh->jpg_buffers.buffer[num].bs.seq; - buf->timestamp = - fh->jpg_buffers.buffer[num].bs.timestamp; - buf->bytesused = - fh->jpg_buffers.buffer[num].bs.length; + if (fh->buffers.buffer[num].state == BUZ_STATE_DONE || + fh->buffers.buffer[num].state == BUZ_STATE_USER) { + buf->sequence = fh->buffers.buffer[num].bs.seq; + buf->timestamp = fh->buffers.buffer[num].bs.timestamp; + buf->bytesused = fh->buffers.buffer[num].bs.length; buf->flags |= V4L2_BUF_FLAG_DONE; } else { buf->flags |= V4L2_BUF_FLAG_QUEUED; @@ -1454,14 +1452,11 @@ zoran_v4l2_buffer_status (struct zoran_fh *fh, /* which fields are these? */ if (fh->jpg_settings.TmpDcm != 1) - buf->field = - fh->jpg_settings. - odd_even ? V4L2_FIELD_TOP : V4L2_FIELD_BOTTOM; + buf->field = fh->jpg_settings.odd_even ? + V4L2_FIELD_TOP : V4L2_FIELD_BOTTOM; else - buf->field = - fh->jpg_settings. - odd_even ? V4L2_FIELD_SEQ_TB : - V4L2_FIELD_SEQ_BT; + buf->field = fh->jpg_settings.odd_even ? + V4L2_FIELD_SEQ_TB : V4L2_FIELD_SEQ_BT; break; @@ -1744,7 +1739,7 @@ sparams_unlock_and_return: mutex_lock(&zr->resource_lock); - if (fh->jpg_buffers.allocated || fh->v4l_buffers.allocated) { + if (fh->buffers.allocated) { dprintk(1, KERN_ERR "%s: BUZIOC_REQBUFS - buffers already allocated\n", @@ -1753,17 +1748,17 @@ sparams_unlock_and_return: goto jpgreqbuf_unlock_and_return; } - fh->jpg_buffers.num_buffers = breq->count; - fh->jpg_buffers.buffer_size = breq->size; + /* The next mmap will map the MJPEG buffers - could + * also be *_PLAY, but it doesn't matter here */ + map_mode_jpg(fh, 0); + fh->buffers.num_buffers = breq->count; + fh->buffers.buffer_size = breq->size; if (jpg_fbuffer_alloc(file)) { res = -ENOMEM; goto jpgreqbuf_unlock_and_return; } - /* The next mmap will map the MJPEG buffers - could - * also be *_PLAY, but it doesn't matter here */ - fh->map_mode = ZORAN_MAP_MODE_JPG_REC; jpgreqbuf_unlock_and_return: mutex_unlock(&zr->resource_lock); @@ -1806,7 +1801,15 @@ jpgreqbuf_unlock_and_return: dprintk(3, KERN_DEBUG "%s: BUZIOC_SYNC\n", ZR_DEVNAME(zr)); mutex_lock(&zr->resource_lock); - res = jpg_sync(file, bsync); + + if (fh->map_mode == ZORAN_MAP_MODE_RAW) { + dprintk(2, KERN_WARNING + "%s: %s - not in jpg capture mode\n", + ZR_DEVNAME(zr), __func__); + res = -EINVAL; + } else { + res = jpg_sync(file, bsync); + } mutex_unlock(&zr->resource_lock); return res; @@ -1885,18 +1888,10 @@ static int zoran_vidiocgmbuf(struct file *file, void *__fh, struct video_mbuf *v struct zoran *zr = fh->zr; int i, res = 0; - vmbuf->size = - fh->v4l_buffers.num_buffers * - fh->v4l_buffers.buffer_size; - vmbuf->frames = fh->v4l_buffers.num_buffers; - for (i = 0; i < vmbuf->frames; i++) { - vmbuf->offsets[i] = - i * fh->v4l_buffers.buffer_size; - } mutex_lock(&zr->resource_lock); - if (fh->jpg_buffers.allocated || fh->v4l_buffers.allocated) { + if (fh->buffers.allocated) { dprintk(1, KERN_ERR "%s: VIDIOCGMBUF - buffers already allocated\n", @@ -1905,13 +1900,19 @@ static int zoran_vidiocgmbuf(struct file *file, void *__fh, struct video_mbuf *v goto v4l1reqbuf_unlock_and_return; } + /* The next mmap will map the V4L buffers */ + map_mode_raw(fh); + if (v4l_fbuffer_alloc(file)) { res = -ENOMEM; goto v4l1reqbuf_unlock_and_return; } - /* The next mmap will map the V4L buffers */ - fh->map_mode = ZORAN_MAP_MODE_RAW; + vmbuf->size = fh->buffers.num_buffers * fh->buffers.buffer_size; + vmbuf->frames = fh->buffers.num_buffers; + for (i = 0; i < vmbuf->frames; i++) + vmbuf->offsets[i] = i * fh->buffers.buffer_size; + v4l1reqbuf_unlock_and_return: mutex_unlock(&zr->resource_lock); @@ -2224,15 +2225,15 @@ static int zoran_s_fmt_vid_out(struct file *file, void *__fh, mutex_lock(&zr->resource_lock); - settings = fh->jpg_settings; - - if (fh->v4l_buffers.allocated || fh->jpg_buffers.allocated) { + if (fh->buffers.allocated) { dprintk(1, KERN_ERR "%s: VIDIOC_S_FMT - cannot change capture mode\n", - ZR_DEVNAME(zr)); + ZR_DEVNAME(zr)); res = -EBUSY; goto sfmtjpg_unlock_and_return; } + settings = fh->jpg_settings; + /* we actually need to set 'real' parameters now */ if (fmt->fmt.pix.height * 2 > BUZ_MAX_HEIGHT) settings.TmpDcm = 1; @@ -2270,6 +2271,9 @@ static int zoran_s_fmt_vid_out(struct file *file, void *__fh, /* it's ok, so set them */ fh->jpg_settings = settings; + map_mode_jpg(fh, fmt->type == V4L2_BUF_TYPE_VIDEO_OUTPUT); + fh->buffers.buffer_size = zoran_v4l2_calc_bufsize(&fh->jpg_settings); + /* tell the user what we actually did */ fmt->fmt.pix.width = settings.img_width / settings.HorDcm; fmt->fmt.pix.height = settings.img_height * 2 / @@ -2280,15 +2284,10 @@ static int zoran_s_fmt_vid_out(struct file *file, void *__fh, else fmt->fmt.pix.field = (fh->jpg_settings.odd_even ? V4L2_FIELD_TOP : V4L2_FIELD_BOTTOM); - fh->jpg_buffers.buffer_size = zoran_v4l2_calc_bufsize(&fh->jpg_settings); fmt->fmt.pix.bytesperline = 0; - fmt->fmt.pix.sizeimage = fh->jpg_buffers.buffer_size; + fmt->fmt.pix.sizeimage = fh->buffers.buffer_size; fmt->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; - /* we hereby abuse this variable to show that - * we're gonna do mjpeg capture */ - fh->map_mode = (fmt->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) ? - ZORAN_MAP_MODE_JPG_REC : ZORAN_MAP_MODE_JPG_PLAY; sfmtjpg_unlock_and_return: mutex_unlock(&zr->resource_lock); return res; @@ -2313,9 +2312,11 @@ static int zoran_s_fmt_vid_cap(struct file *file, void *__fh, ZR_DEVNAME(zr), fmt->fmt.pix.pixelformat); return -EINVAL; } + mutex_lock(&zr->resource_lock); - if (fh->jpg_buffers.allocated || - (fh->v4l_buffers.allocated && fh->v4l_buffers.active != ZORAN_FREE)) { + + if ((fh->map_mode != ZORAN_MAP_MODE_RAW && fh->buffers.allocated) || + fh->buffers.active != ZORAN_FREE) { dprintk(1, KERN_ERR "%s: VIDIOC_S_FMT - cannot change capture mode\n", ZR_DEVNAME(zr)); res = -EBUSY; @@ -2326,13 +2327,14 @@ static int zoran_s_fmt_vid_cap(struct file *file, void *__fh, if (fmt->fmt.pix.width > BUZ_MAX_WIDTH) fmt->fmt.pix.width = BUZ_MAX_WIDTH; - res = zoran_v4l_set_format(file, fmt->fmt.pix.width, - fmt->fmt.pix.height, &zoran_formats[i]); + map_mode_raw(fh); + + res = zoran_v4l_set_format(fh, fmt->fmt.pix.width, fmt->fmt.pix.height, + &zoran_formats[i]); if (res) goto sfmtv4l_unlock_and_return; - /* tell the user the - * results/missing stuff */ + /* tell the user the results/missing stuff */ fmt->fmt.pix.bytesperline = fh->v4l_settings.bytesperline; fmt->fmt.pix.sizeimage = fh->v4l_settings.height * fh->v4l_settings.bytesperline; fmt->fmt.pix.colorspace = fh->v4l_settings.format->colorspace; @@ -2341,7 +2343,6 @@ static int zoran_s_fmt_vid_cap(struct file *file, void *__fh, else fmt->fmt.pix.field = V4L2_FIELD_TOP; - fh->map_mode = ZORAN_MAP_MODE_RAW; sfmtv4l_unlock_and_return: mutex_unlock(&zr->resource_lock); return res; @@ -2430,7 +2431,7 @@ static int zoran_reqbufs(struct file *file, void *__fh, struct v4l2_requestbuffe return zoran_streamoff(file, fh, req->type); mutex_lock(&zr->resource_lock); - if (fh->v4l_buffers.allocated || fh->jpg_buffers.allocated) { + if (fh->buffers.allocated) { dprintk(2, KERN_ERR "%s: VIDIOC_REQBUFS - buffers already allocated\n", @@ -2440,46 +2441,38 @@ static int zoran_reqbufs(struct file *file, void *__fh, struct v4l2_requestbuffe } if (fh->map_mode == ZORAN_MAP_MODE_RAW && - req->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { - + req->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { /* control user input */ if (req->count < 2) req->count = 2; if (req->count > v4l_nbufs) req->count = v4l_nbufs; - fh->v4l_buffers.num_buffers = req->count; + + /* The next mmap will map the V4L buffers */ + map_mode_raw(fh); + fh->buffers.num_buffers = req->count; if (v4l_fbuffer_alloc(file)) { res = -ENOMEM; goto v4l2reqbuf_unlock_and_return; } - - /* The next mmap will map the V4L buffers */ - fh->map_mode = ZORAN_MAP_MODE_RAW; - } else if (fh->map_mode == ZORAN_MAP_MODE_JPG_REC || - fh->map_mode == ZORAN_MAP_MODE_JPG_PLAY) { - + fh->map_mode == ZORAN_MAP_MODE_JPG_PLAY) { /* we need to calculate size ourselves now */ if (req->count < 4) req->count = 4; if (req->count > jpg_nbufs) req->count = jpg_nbufs; - fh->jpg_buffers.num_buffers = req->count; - fh->jpg_buffers.buffer_size = - zoran_v4l2_calc_bufsize(&fh->jpg_settings); + + /* The next mmap will map the MJPEG buffers */ + map_mode_jpg(fh, req->type == V4L2_BUF_TYPE_VIDEO_OUTPUT); + fh->buffers.num_buffers = req->count; + fh->buffers.buffer_size = zoran_v4l2_calc_bufsize(&fh->jpg_settings); if (jpg_fbuffer_alloc(file)) { res = -ENOMEM; goto v4l2reqbuf_unlock_and_return; } - - /* The next mmap will map the MJPEG buffers */ - if (req->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) - fh->map_mode = ZORAN_MAP_MODE_JPG_REC; - else - fh->map_mode = ZORAN_MAP_MODE_JPG_PLAY; - } else { dprintk(1, KERN_ERR @@ -2528,8 +2521,7 @@ static int zoran_qbuf(struct file *file, void *__fh, struct v4l2_buffer *buf) res = zoran_v4l_queue_frame(file, buf->index); if (res) goto qbuf_unlock_and_return; - if (!zr->v4l_memgrab_active && - fh->v4l_buffers.active == ZORAN_LOCKED) + if (!zr->v4l_memgrab_active && fh->buffers.active == ZORAN_LOCKED) zr36057_set_memgrab(zr, 1); break; @@ -2556,9 +2548,9 @@ static int zoran_qbuf(struct file *file, void *__fh, struct v4l2_buffer *buf) if (res != 0) goto qbuf_unlock_and_return; if (zr->codec_mode == BUZ_MODE_IDLE && - fh->jpg_buffers.active == ZORAN_LOCKED) { + fh->buffers.active == ZORAN_LOCKED) zr36057_enable_jpg(zr, codec_mode); - } + break; default: @@ -2661,12 +2653,12 @@ static int zoran_streamon(struct file *file, void *__fh, enum v4l2_buf_type type switch (fh->map_mode) { case ZORAN_MAP_MODE_RAW: /* raw capture */ if (zr->v4l_buffers.active != ZORAN_ACTIVE || - fh->v4l_buffers.active != ZORAN_ACTIVE) { + fh->buffers.active != ZORAN_ACTIVE) { res = -EBUSY; goto strmon_unlock_and_return; } - zr->v4l_buffers.active = fh->v4l_buffers.active = ZORAN_LOCKED; + zr->v4l_buffers.active = fh->buffers.active = ZORAN_LOCKED; zr->v4l_settings = fh->v4l_settings; zr->v4l_sync_tail = zr->v4l_pend_tail; @@ -2680,12 +2672,12 @@ static int zoran_streamon(struct file *file, void *__fh, enum v4l2_buf_type type case ZORAN_MAP_MODE_JPG_PLAY: /* what is the codec mode right now? */ if (zr->jpg_buffers.active != ZORAN_ACTIVE || - fh->jpg_buffers.active != ZORAN_ACTIVE) { + fh->buffers.active != ZORAN_ACTIVE) { res = -EBUSY; goto strmon_unlock_and_return; } - zr->jpg_buffers.active = fh->jpg_buffers.active = ZORAN_LOCKED; + zr->jpg_buffers.active = fh->buffers.active = ZORAN_LOCKED; if (zr->jpg_que_head != zr->jpg_que_tail) { /* Start the jpeg codec when the first frame is queued */ @@ -2712,12 +2704,13 @@ static int zoran_streamoff(struct file *file, void *__fh, enum v4l2_buf_type typ struct zoran_fh *fh = __fh; struct zoran *zr = fh->zr; int i, res = 0; + unsigned long flags; mutex_lock(&zr->resource_lock); switch (fh->map_mode) { case ZORAN_MAP_MODE_RAW: /* raw capture */ - if (fh->v4l_buffers.active == ZORAN_FREE && + if (fh->buffers.active == ZORAN_FREE && zr->v4l_buffers.active != ZORAN_FREE) { res = -EPERM; /* stay off other's settings! */ goto strmoff_unlock_and_return; @@ -2725,30 +2718,30 @@ static int zoran_streamoff(struct file *file, void *__fh, enum v4l2_buf_type typ if (zr->v4l_buffers.active == ZORAN_FREE) goto strmoff_unlock_and_return; + spin_lock_irqsave(&zr->spinlock, flags); /* unload capture */ if (zr->v4l_memgrab_active) { - unsigned long flags; - spin_lock_irqsave(&zr->spinlock, flags); zr36057_set_memgrab(zr, 0); - spin_unlock_irqrestore(&zr->spinlock, flags); } - for (i = 0; i < fh->v4l_buffers.num_buffers; i++) + for (i = 0; i < fh->buffers.num_buffers; i++) zr->v4l_buffers.buffer[i].state = BUZ_STATE_USER; - fh->v4l_buffers = zr->v4l_buffers; + fh->buffers = zr->v4l_buffers; - zr->v4l_buffers.active = fh->v4l_buffers.active = ZORAN_FREE; + zr->v4l_buffers.active = fh->buffers.active = ZORAN_FREE; zr->v4l_grab_seq = 0; zr->v4l_pend_head = zr->v4l_pend_tail = 0; zr->v4l_sync_tail = 0; + spin_unlock_irqrestore(&zr->spinlock, flags); + break; case ZORAN_MAP_MODE_JPG_REC: case ZORAN_MAP_MODE_JPG_PLAY: - if (fh->jpg_buffers.active == ZORAN_FREE && + if (fh->buffers.active == ZORAN_FREE && zr->jpg_buffers.active != ZORAN_FREE) { res = -EPERM; /* stay off other's settings! */ goto strmoff_unlock_and_return; @@ -3017,7 +3010,7 @@ static int zoran_s_crop(struct file *file, void *__fh, struct v4l2_crop *crop) mutex_lock(&zr->resource_lock); - if (fh->jpg_buffers.allocated || fh->v4l_buffers.allocated) { + if (fh->buffers.allocated) { dprintk(1, KERN_ERR "%s: VIDIOC_S_CROP - cannot change settings while active\n", ZR_DEVNAME(zr)); @@ -3095,8 +3088,7 @@ static int zoran_s_jpegcomp(struct file *file, void *__fh, mutex_lock(&zr->resource_lock); - if (fh->v4l_buffers.active != ZORAN_FREE || - fh->jpg_buffers.active != ZORAN_FREE) { + if (fh->buffers.active != ZORAN_FREE) { dprintk(1, KERN_WARNING "%s: VIDIOC_S_JPEGCOMP called while in playback/capture mode\n", ZR_DEVNAME(zr)); @@ -3107,9 +3099,9 @@ static int zoran_s_jpegcomp(struct file *file, void *__fh, res = zoran_check_jpg_settings(zr, &settings, 0); if (res) goto sjpegc_unlock_and_return; - if (!fh->jpg_buffers.allocated) - fh->jpg_buffers.buffer_size = - zoran_v4l2_calc_bufsize(&fh->jpg_settings); + if (!fh->buffers.allocated) + fh->buffers.buffer_size = + zoran_v4l2_calc_bufsize(&fh->jpg_settings); fh->jpg_settings.jpg_comp = *params = settings.jpg_comp; sjpegc_unlock_and_return: mutex_unlock(&zr->resource_lock); @@ -3146,11 +3138,11 @@ zoran_poll (struct file *file, KERN_DEBUG "%s: %s() raw - active=%c, sync_tail=%lu/%c, pend_tail=%lu, pend_head=%lu\n", ZR_DEVNAME(zr), __func__, - "FAL"[fh->v4l_buffers.active], zr->v4l_sync_tail, + "FAL"[fh->buffers.active], zr->v4l_sync_tail, "UPMD"[zr->v4l_buffers.buffer[frame].state], zr->v4l_pend_tail, zr->v4l_pend_head); /* Process is the one capturing? */ - if (fh->v4l_buffers.active != ZORAN_FREE && + if (fh->buffers.active != ZORAN_FREE && /* Buffer ready to DQBUF? */ zr->v4l_buffers.buffer[frame].state == BUZ_STATE_DONE) res = POLLIN | POLLRDNORM; @@ -3168,10 +3160,10 @@ zoran_poll (struct file *file, KERN_DEBUG "%s: %s() jpg - active=%c, que_tail=%lu/%c, que_head=%lu, dma=%lu/%lu\n", ZR_DEVNAME(zr), __func__, - "FAL"[fh->jpg_buffers.active], zr->jpg_que_tail, + "FAL"[fh->buffers.active], zr->jpg_que_tail, "UPMD"[zr->jpg_buffers.buffer[frame].state], zr->jpg_que_head, zr->jpg_dma_tail, zr->jpg_dma_head); - if (fh->jpg_buffers.active != ZORAN_FREE && + if (fh->buffers.active != ZORAN_FREE && zr->jpg_buffers.buffer[frame].state == BUZ_STATE_DONE) { if (fh->map_mode == ZORAN_MAP_MODE_JPG_REC) res = POLLIN | POLLRDNORM; @@ -3225,87 +3217,49 @@ zoran_vm_close (struct vm_area_struct *vma) struct zoran *zr = fh->zr; int i; - map->count--; - if (map->count == 0) { - switch (fh->map_mode) { - case ZORAN_MAP_MODE_JPG_REC: - case ZORAN_MAP_MODE_JPG_PLAY: - - dprintk(3, KERN_INFO "%s: munmap(MJPEG)\n", - ZR_DEVNAME(zr)); - - for (i = 0; i < fh->jpg_buffers.num_buffers; i++) { - if (fh->jpg_buffers.buffer[i].map == map) { - fh->jpg_buffers.buffer[i].map = - NULL; - } - } - kfree(map); - - for (i = 0; i < fh->jpg_buffers.num_buffers; i++) - if (fh->jpg_buffers.buffer[i].map) - break; - if (i == fh->jpg_buffers.num_buffers) { - mutex_lock(&zr->resource_lock); - - if (fh->jpg_buffers.active != ZORAN_FREE) { - jpg_qbuf(file, -1, zr->codec_mode); - zr->jpg_buffers.allocated = 0; - zr->jpg_buffers.active = - fh->jpg_buffers.active = - ZORAN_FREE; - } - jpg_fbuffer_free(file); - mutex_unlock(&zr->resource_lock); - } + if (--map->count > 0) + return; - break; - - case ZORAN_MAP_MODE_RAW: + dprintk(3, KERN_INFO "%s: %s - munmap(%s)\n", ZR_DEVNAME(zr), + __func__, mode_name(fh->map_mode)); - dprintk(3, KERN_INFO "%s: munmap(V4L)\n", - ZR_DEVNAME(zr)); + for (i = 0; i < fh->buffers.num_buffers; i++) { + if (fh->buffers.buffer[i].map == map) + fh->buffers.buffer[i].map = NULL; + } + kfree(map); - for (i = 0; i < fh->v4l_buffers.num_buffers; i++) { - if (fh->v4l_buffers.buffer[i].map == map) { - /* unqueue/unmap */ - fh->v4l_buffers.buffer[i].map = - NULL; - } - } - kfree(map); + /* Any buffers still mapped? */ + for (i = 0; i < fh->buffers.num_buffers; i++) + if (fh->buffers.buffer[i].map) + return; - for (i = 0; i < fh->v4l_buffers.num_buffers; i++) - if (fh->v4l_buffers.buffer[i].map) - break; - if (i == fh->v4l_buffers.num_buffers) { - mutex_lock(&zr->resource_lock); - - if (fh->v4l_buffers.active != ZORAN_FREE) { - unsigned long flags; - - spin_lock_irqsave(&zr->spinlock, flags); - zr36057_set_memgrab(zr, 0); - zr->v4l_buffers.allocated = 0; - zr->v4l_buffers.active = - fh->v4l_buffers.active = - ZORAN_FREE; - spin_unlock_irqrestore(&zr->spinlock, flags); - } - v4l_fbuffer_free(file); - mutex_unlock(&zr->resource_lock); - } + dprintk(3, KERN_INFO "%s: %s - free %s buffers\n", ZR_DEVNAME(zr), + __func__, mode_name(fh->map_mode)); - break; + mutex_lock(&zr->resource_lock); - default: - printk(KERN_ERR - "%s: munmap() - internal error - unknown map mode %d\n", - ZR_DEVNAME(zr), fh->map_mode); - break; + if (fh->map_mode == ZORAN_MAP_MODE_RAW) { + if (fh->buffers.active != ZORAN_FREE) { + unsigned long flags; + spin_lock_irqsave(&zr->spinlock, flags); + zr36057_set_memgrab(zr, 0); + zr->v4l_buffers.allocated = 0; + zr->v4l_buffers.active = fh->buffers.active = ZORAN_FREE; + spin_unlock_irqrestore(&zr->spinlock, flags); } + v4l_fbuffer_free(file); + } else { + if (fh->buffers.active != ZORAN_FREE) { + jpg_qbuf(file, -1, zr->codec_mode); + zr->jpg_buffers.allocated = 0; + zr->jpg_buffers.active = fh->buffers.active = ZORAN_FREE; + } + jpg_fbuffer_free(file); } + + mutex_unlock(&zr->resource_lock); } static struct vm_operations_struct zoran_vm_ops = { @@ -3330,8 +3284,7 @@ zoran_mmap (struct file *file, dprintk(3, KERN_INFO "%s: mmap(%s) of 0x%08lx-0x%08lx (size=%lu)\n", ZR_DEVNAME(zr), - fh->map_mode == ZORAN_MAP_MODE_RAW ? "V4L" : "MJPEG", - vma->vm_start, vma->vm_end, size); + mode_name(fh->map_mode), vma->vm_start, vma->vm_end, size); if (!(vma->vm_flags & VM_SHARED) || !(vma->vm_flags & VM_READ) || !(vma->vm_flags & VM_WRITE)) { @@ -3342,76 +3295,93 @@ zoran_mmap (struct file *file, return -EINVAL; } - switch (fh->map_mode) { + mutex_lock(&zr->resource_lock); - case ZORAN_MAP_MODE_JPG_REC: - case ZORAN_MAP_MODE_JPG_PLAY: + if (!fh->buffers.allocated) { + dprintk(1, + KERN_ERR + "%s: zoran_mmap(%s) - buffers not yet allocated\n", + ZR_DEVNAME(zr), mode_name(fh->map_mode)); + res = -ENOMEM; + goto mmap_unlock_and_return; + } - /* lock */ - mutex_lock(&zr->resource_lock); + first = offset / fh->buffers.buffer_size; + last = first - 1 + size / fh->buffers.buffer_size; + if (offset % fh->buffers.buffer_size != 0 || + size % fh->buffers.buffer_size != 0 || first < 0 || + last < 0 || first >= fh->buffers.num_buffers || + last >= fh->buffers.buffer_size) { + dprintk(1, + KERN_ERR + "%s: mmap(%s) - offset=%lu or size=%lu invalid for bufsize=%d and numbufs=%d\n", + ZR_DEVNAME(zr), mode_name(fh->map_mode), offset, size, + fh->buffers.buffer_size, + fh->buffers.num_buffers); + res = -EINVAL; + goto mmap_unlock_and_return; + } - /* Map the MJPEG buffers */ - if (!fh->jpg_buffers.allocated) { + /* Check if any buffers are already mapped */ + for (i = first; i <= last; i++) { + if (fh->buffers.buffer[i].map) { dprintk(1, KERN_ERR - "%s: zoran_mmap(MJPEG) - buffers not yet allocated\n", - ZR_DEVNAME(zr)); - res = -ENOMEM; - goto jpg_mmap_unlock_and_return; + "%s: mmap(%s) - buffer %d already mapped\n", + ZR_DEVNAME(zr), mode_name(fh->map_mode), i); + res = -EBUSY; + goto mmap_unlock_and_return; } + } - first = offset / fh->jpg_buffers.buffer_size; - last = first - 1 + size / fh->jpg_buffers.buffer_size; - if (offset % fh->jpg_buffers.buffer_size != 0 || - size % fh->jpg_buffers.buffer_size != 0 || first < 0 || - last < 0 || first >= fh->jpg_buffers.num_buffers || - last >= fh->jpg_buffers.num_buffers) { - dprintk(1, - KERN_ERR - "%s: mmap(MJPEG) - offset=%lu or size=%lu invalid for bufsize=%d and numbufs=%d\n", - ZR_DEVNAME(zr), offset, size, - fh->jpg_buffers.buffer_size, - fh->jpg_buffers.num_buffers); - res = -EINVAL; - goto jpg_mmap_unlock_and_return; - } + /* map these buffers */ + map = kmalloc(sizeof(struct zoran_mapping), GFP_KERNEL); + if (!map) { + res = -ENOMEM; + goto mmap_unlock_and_return; + } + map->file = file; + map->count = 1; + + vma->vm_ops = &zoran_vm_ops; + vma->vm_flags |= VM_DONTEXPAND; + vma->vm_private_data = map; + + if (fh->map_mode == ZORAN_MAP_MODE_RAW) { for (i = first; i <= last; i++) { - if (fh->jpg_buffers.buffer[i].map) { + todo = size; + if (todo > fh->buffers.buffer_size) + todo = fh->buffers.buffer_size; + page = fh->buffers.buffer[i].v4l.fbuffer_phys; + if (remap_pfn_range(vma, start, page >> PAGE_SHIFT, + todo, PAGE_SHARED)) { dprintk(1, KERN_ERR - "%s: mmap(MJPEG) - buffer %d already mapped\n", - ZR_DEVNAME(zr), i); - res = -EBUSY; - goto jpg_mmap_unlock_and_return; + "%s: zoran_mmap(V4L) - remap_pfn_range failed\n", + ZR_DEVNAME(zr)); + res = -EAGAIN; + goto mmap_unlock_and_return; } + size -= todo; + start += todo; + fh->buffers.buffer[i].map = map; + if (size == 0) + break; } - - /* map these buffers (v4l_buffers[i]) */ - map = kmalloc(sizeof(struct zoran_mapping), GFP_KERNEL); - if (!map) { - res = -ENOMEM; - goto jpg_mmap_unlock_and_return; - } - map->file = file; - map->count = 1; - - vma->vm_ops = &zoran_vm_ops; - vma->vm_flags |= VM_DONTEXPAND; - vma->vm_private_data = map; - + } else { for (i = first; i <= last; i++) { for (j = 0; - j < fh->jpg_buffers.buffer_size / PAGE_SIZE; + j < fh->buffers.buffer_size / PAGE_SIZE; j++) { fraglen = - (le32_to_cpu(fh->jpg_buffers.buffer[i]. + (le32_to_cpu(fh->buffers.buffer[i].jpg. frag_tab[2 * j + 1]) & ~1) << 1; todo = size; if (todo > fraglen) todo = fraglen; pos = - le32_to_cpu(fh->jpg_buffers. - buffer[i].frag_tab[2 * j]); + le32_to_cpu(fh->buffers. + buffer[i].jpg.frag_tab[2 * j]); /* should just be pos on i386 */ page = virt_to_phys(bus_to_virt(pos)) >> PAGE_SHIFT; @@ -3422,112 +3392,26 @@ zoran_mmap (struct file *file, "%s: zoran_mmap(V4L) - remap_pfn_range failed\n", ZR_DEVNAME(zr)); res = -EAGAIN; - goto jpg_mmap_unlock_and_return; + goto mmap_unlock_and_return; } size -= todo; start += todo; if (size == 0) break; - if (le32_to_cpu(fh->jpg_buffers.buffer[i]. + if (le32_to_cpu(fh->buffers.buffer[i].jpg. frag_tab[2 * j + 1]) & 1) break; /* was last fragment */ } - fh->jpg_buffers.buffer[i].map = map; + fh->buffers.buffer[i].map = map; if (size == 0) break; } - jpg_mmap_unlock_and_return: - mutex_unlock(&zr->resource_lock); - - break; - - case ZORAN_MAP_MODE_RAW: - - mutex_lock(&zr->resource_lock); - - /* Map the V4L buffers */ - if (!fh->v4l_buffers.allocated) { - dprintk(1, - KERN_ERR - "%s: zoran_mmap(V4L) - buffers not yet allocated\n", - ZR_DEVNAME(zr)); - res = -ENOMEM; - goto v4l_mmap_unlock_and_return; - } - - first = offset / fh->v4l_buffers.buffer_size; - last = first - 1 + size / fh->v4l_buffers.buffer_size; - if (offset % fh->v4l_buffers.buffer_size != 0 || - size % fh->v4l_buffers.buffer_size != 0 || first < 0 || - last < 0 || first >= fh->v4l_buffers.num_buffers || - last >= fh->v4l_buffers.buffer_size) { - dprintk(1, - KERN_ERR - "%s: mmap(V4L) - offset=%lu or size=%lu invalid for bufsize=%d and numbufs=%d\n", - ZR_DEVNAME(zr), offset, size, - fh->v4l_buffers.buffer_size, - fh->v4l_buffers.num_buffers); - res = -EINVAL; - goto v4l_mmap_unlock_and_return; - } - for (i = first; i <= last; i++) { - if (fh->v4l_buffers.buffer[i].map) { - dprintk(1, - KERN_ERR - "%s: mmap(V4L) - buffer %d already mapped\n", - ZR_DEVNAME(zr), i); - res = -EBUSY; - goto v4l_mmap_unlock_and_return; - } - } - - /* map these buffers (v4l_buffers[i]) */ - map = kmalloc(sizeof(struct zoran_mapping), GFP_KERNEL); - if (!map) { - res = -ENOMEM; - goto v4l_mmap_unlock_and_return; - } - map->file = file; - map->count = 1; - - vma->vm_ops = &zoran_vm_ops; - vma->vm_flags |= VM_DONTEXPAND; - vma->vm_private_data = map; - - for (i = first; i <= last; i++) { - todo = size; - if (todo > fh->v4l_buffers.buffer_size) - todo = fh->v4l_buffers.buffer_size; - page = fh->v4l_buffers.buffer[i].fbuffer_phys; - if (remap_pfn_range(vma, start, page >> PAGE_SHIFT, - todo, PAGE_SHARED)) { - dprintk(1, - KERN_ERR - "%s: zoran_mmap(V4L)i - remap_pfn_range failed\n", - ZR_DEVNAME(zr)); - res = -EAGAIN; - goto v4l_mmap_unlock_and_return; - } - size -= todo; - start += todo; - fh->v4l_buffers.buffer[i].map = map; - if (size == 0) - break; - } - v4l_mmap_unlock_and_return: - mutex_unlock(&zr->resource_lock); - - break; - - default: - dprintk(1, - KERN_ERR - "%s: zoran_mmap() - internal error - unknown map mode %d\n", - ZR_DEVNAME(zr), fh->map_mode); - break; } +mmap_unlock_and_return: + mutex_unlock(&zr->resource_lock); + return 0; } -- cgit v1.2.3 From 402f9ceab8607e246c388e640cc657e9b5be0286 Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Tue, 10 Mar 2009 19:28:17 -0700 Subject: zoran: Drop the lock_norm module parameter From: Jean Delvare The lock_norm module parameter doesn't look terribly useful. If you don't want to change the norm, just don't change it. As a matter of fact, no other v4l driver has such a parameter. Priority: normal Signed-off-by: Jean Delvare Signed-off-by: Trent Piepho Cc: Hans Verkuil --- linux/drivers/media/video/zoran/zoran_driver.c | 20 -------------------- 1 file changed, 20 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/zoran/zoran_driver.c b/linux/drivers/media/video/zoran/zoran_driver.c index 32873ca52..97e1c776b 100644 --- a/linux/drivers/media/video/zoran/zoran_driver.c +++ b/linux/drivers/media/video/zoran/zoran_driver.c @@ -163,10 +163,6 @@ const struct zoran_format zoran_formats[] = { }; #define NUM_FORMATS ARRAY_SIZE(zoran_formats) -static int lock_norm; /* 0 = default 1 = Don't change TV standard (norm) */ -module_param(lock_norm, int, 0644); -MODULE_PARM_DESC(lock_norm, "Prevent norm changes (1 = ignore, >1 = fail)"); - /* small helper function for calculating buffersizes for v4l2 * we calculate the nearest higher power-of-two, which * will be the recommended buffersize */ @@ -1491,22 +1487,6 @@ zoran_set_norm (struct zoran *zr, return -EBUSY; } - if (lock_norm && norm != zr->norm) { - if (lock_norm > 1) { - dprintk(1, - KERN_WARNING - "%s: set_norm() - TV standard is locked, can not switch norm\n", - ZR_DEVNAME(zr)); - return -EPERM; - } else { - dprintk(1, - KERN_WARNING - "%s: set_norm() - TV standard is locked, norm was not changed\n", - ZR_DEVNAME(zr)); - norm = zr->norm; - } - } - if (!(norm & zr->card.norms)) { dprintk(1, KERN_ERR "%s: set_norm() - unsupported norm %llx\n", -- cgit v1.2.3 From 8fb8df7555475d10ef8154ef9aa81835c093c1b6 Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Tue, 10 Mar 2009 19:28:20 -0700 Subject: zoran: Don't frighten users with failed buffer allocation From: Jean Delvare kmalloc() can fail for large video buffers. By default the kernel complains loudly about allocation failures, but we don't want to frighten the user, so ask kmalloc() to keep quiet on such failures. Priority: normal Signed-off-by: Jean Delvare Signed-off-by: Trent Piepho Cc: Hans Verkuil --- linux/drivers/media/video/zoran/zoran_driver.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/zoran/zoran_driver.c b/linux/drivers/media/video/zoran/zoran_driver.c index 97e1c776b..7fcd43160 100644 --- a/linux/drivers/media/video/zoran/zoran_driver.c +++ b/linux/drivers/media/video/zoran/zoran_driver.c @@ -230,7 +230,8 @@ v4l_fbuffer_alloc (struct file *file) ZR_DEVNAME(zr), i); //udelay(20); - mem = kmalloc(fh->buffers.buffer_size, GFP_KERNEL); + mem = kmalloc(fh->buffers.buffer_size, + GFP_KERNEL | __GFP_NOWARN); if (!mem) { dprintk(1, KERN_ERR -- cgit v1.2.3 From f542aede4d7c37a87c603e57f282b647c9550861 Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Tue, 10 Mar 2009 19:28:31 -0700 Subject: zoran: Pass zoran_fh pointers instead of file pointers From: Trent Piepho Many functions had a struct file pointer argument, but all they wants is the struct zoran_fh pointer from the file's private data. Since every caller of those functions already has the zoran_fh, just pass the that instead. This saves a dereference in each function change. While I'm at it, change the code formatting of affected functions to be kernel standard style. Priority: normal Signed-off-by: Trent Piepho --- linux/drivers/media/video/zoran/zoran_device.c | 6 +- linux/drivers/media/video/zoran/zoran_device.h | 2 +- linux/drivers/media/video/zoran/zoran_driver.c | 158 +++++++++---------------- 3 files changed, 56 insertions(+), 110 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/zoran/zoran_device.c b/linux/drivers/media/video/zoran/zoran_device.c index 06f2c9a34..9d93dd8c0 100644 --- a/linux/drivers/media/video/zoran/zoran_device.c +++ b/linux/drivers/media/video/zoran/zoran_device.c @@ -536,12 +536,8 @@ zr36057_overlay (struct zoran *zr, * and the maximum window size is BUZ_MAX_WIDTH * BUZ_MAX_HEIGHT pixels. */ -void -write_overlay_mask (struct file *file, - struct v4l2_clip *vp, - int count) +void write_overlay_mask(struct zoran_fh *fh, struct v4l2_clip *vp, int count) { - struct zoran_fh *fh = file->private_data; struct zoran *zr = fh->zr; unsigned mask_line_size = (BUZ_MAX_WIDTH + 31) / 32; u32 *mask; diff --git a/linux/drivers/media/video/zoran/zoran_device.h b/linux/drivers/media/video/zoran/zoran_device.h index 2eb645904..e0a4f0ff9 100644 --- a/linux/drivers/media/video/zoran/zoran_device.h +++ b/linux/drivers/media/video/zoran/zoran_device.h @@ -54,7 +54,7 @@ extern int jpeg_codec_reset(struct zoran *zr); /* zr360x7 access to raw capture */ extern void zr36057_overlay(struct zoran *zr, int on); -extern void write_overlay_mask(struct file *file, +extern void write_overlay_mask(struct zoran_fh *fh, struct v4l2_clip *vp, int count); extern void zr36057_set_memgrab(struct zoran *zr, diff --git a/linux/drivers/media/video/zoran/zoran_driver.c b/linux/drivers/media/video/zoran/zoran_driver.c index 7fcd43160..9a014ad8c 100644 --- a/linux/drivers/media/video/zoran/zoran_driver.c +++ b/linux/drivers/media/video/zoran/zoran_driver.c @@ -187,8 +187,8 @@ zoran_v4l2_calc_bufsize (struct zoran_jpg_settings *settings) } /* forward references */ -static void v4l_fbuffer_free(struct file *file); -static void jpg_fbuffer_free(struct file *file); +static void v4l_fbuffer_free(struct zoran_fh *fh); +static void jpg_fbuffer_free(struct zoran_fh *fh); /* Set mapping mode */ static void map_mode_raw(struct zoran_fh *fh) @@ -214,10 +214,8 @@ static inline const char *mode_name(enum zoran_map_mode mode) * These have to be pysically contiguous. */ -static int -v4l_fbuffer_alloc (struct file *file) +static int v4l_fbuffer_alloc(struct zoran_fh *fh) { - struct zoran_fh *fh = file->private_data; struct zoran *zr = fh->zr; int i, off; unsigned char *mem; @@ -237,7 +235,7 @@ v4l_fbuffer_alloc (struct file *file) KERN_ERR "%s: v4l_fbuffer_alloc() - kmalloc for V4L buf %d failed\n", ZR_DEVNAME(zr), i); - v4l_fbuffer_free(file); + v4l_fbuffer_free(fh); return -ENOBUFS; } fh->buffers.buffer[i].v4l.fbuffer = mem; @@ -259,10 +257,8 @@ v4l_fbuffer_alloc (struct file *file) } /* free the V4L grab buffers */ -static void -v4l_fbuffer_free (struct file *file) +static void v4l_fbuffer_free(struct zoran_fh *fh) { - struct zoran_fh *fh = file->private_data; struct zoran *zr = fh->zr; int i, off; unsigned char *mem; @@ -312,10 +308,8 @@ v4l_fbuffer_free (struct file *file) * and fragment buffers are not little-endian. */ -static int -jpg_fbuffer_alloc (struct file *file) +static int jpg_fbuffer_alloc(struct zoran_fh *fh) { - struct zoran_fh *fh = file->private_data; struct zoran *zr = fh->zr; int i, j, off; u8 *mem; @@ -335,7 +329,7 @@ jpg_fbuffer_alloc (struct file *file) KERN_ERR "%s: jpg_fbuffer_alloc() - get_zeroed_page (frag_tab) failed for buffer %d\n", ZR_DEVNAME(zr), i); - jpg_fbuffer_free(file); + jpg_fbuffer_free(fh); return -ENOBUFS; } fh->buffers.buffer[i].jpg.frag_tab = (__le32 *)mem; @@ -348,7 +342,7 @@ jpg_fbuffer_alloc (struct file *file) KERN_ERR "%s: jpg_fbuffer_alloc() - kmalloc failed for buffer %d\n", ZR_DEVNAME(zr), i); - jpg_fbuffer_free(file); + jpg_fbuffer_free(fh); return -ENOBUFS; } fh->buffers.buffer[i].jpg.frag_tab[0] = @@ -366,7 +360,7 @@ jpg_fbuffer_alloc (struct file *file) KERN_ERR "%s: jpg_fbuffer_alloc() - get_zeroed_page failed for buffer %d\n", ZR_DEVNAME(zr), i); - jpg_fbuffer_free(file); + jpg_fbuffer_free(fh); return -ENOBUFS; } @@ -392,10 +386,8 @@ jpg_fbuffer_alloc (struct file *file) } /* free the MJPEG grab buffers */ -static void -jpg_fbuffer_free (struct file *file) +static void jpg_fbuffer_free(struct zoran_fh *fh) { - struct zoran_fh *fh = file->private_data; struct zoran *zr = fh->zr; int i, j, off; unsigned char *mem; @@ -493,11 +485,8 @@ zoran_v4l_set_format (struct zoran_fh *fh, return 0; } -static int -zoran_v4l_queue_frame (struct file *file, - int num) +static int zoran_v4l_queue_frame(struct zoran_fh *fh, int num) { - struct zoran_fh *fh = file->private_data; struct zoran *zr = fh->zr; unsigned long flags; int res = 0; @@ -575,11 +564,8 @@ zoran_v4l_queue_frame (struct file *file, * Sync on a V4L buffer */ -static int -v4l_sync (struct file *file, - int frame) +static int v4l_sync(struct zoran_fh *fh, int frame) { - struct zoran_fh *fh = file->private_data; struct zoran *zr = fh->zr; unsigned long flags; @@ -644,12 +630,9 @@ v4l_sync (struct file *file, * Queue a MJPEG buffer for capture/playback */ -static int -zoran_jpg_queue_frame (struct file *file, - int num, - enum zoran_codec_mode mode) +static int zoran_jpg_queue_frame(struct zoran_fh *fh, int num, + enum zoran_codec_mode mode) { - struct zoran_fh *fh = file->private_data; struct zoran *zr = fh->zr; unsigned long flags; int res = 0; @@ -739,12 +722,8 @@ zoran_jpg_queue_frame (struct file *file, return res; } -static int -jpg_qbuf (struct file *file, - int frame, - enum zoran_codec_mode mode) +static int jpg_qbuf(struct zoran_fh *fh, int frame, enum zoran_codec_mode mode) { - struct zoran_fh *fh = file->private_data; struct zoran *zr = fh->zr; int res = 0; @@ -771,7 +750,7 @@ jpg_qbuf (struct file *file, } } - if ((res = zoran_jpg_queue_frame(file, frame, mode))) + if ((res = zoran_jpg_queue_frame(fh, frame, mode))) return res; /* Start the jpeg codec when the first frame is queued */ @@ -785,11 +764,8 @@ jpg_qbuf (struct file *file, * Sync on a MJPEG buffer */ -static int -jpg_sync (struct file *file, - struct zoran_sync *bs) +static int jpg_sync(struct zoran_fh *fh, struct zoran_sync *bs) { - struct zoran_fh *fh = file->private_data; struct zoran *zr = fh->zr; unsigned long flags; int frame; @@ -853,11 +829,9 @@ jpg_sync (struct file *file, return 0; } -static void -zoran_open_init_session (struct file *file) +static void zoran_open_init_session(struct zoran_fh *fh) { int i; - struct zoran_fh *fh = file->private_data; struct zoran *zr = fh->zr; /* Per default, map the V4L Buffers */ @@ -884,10 +858,8 @@ zoran_open_init_session (struct file *file) fh->buffers.active = ZORAN_FREE; } -static void -zoran_close_end_session (struct file *file) +static void zoran_close_end_session(struct zoran_fh *fh) { - struct zoran_fh *fh = file->private_data; struct zoran *zr = fh->zr; /* overlay */ @@ -913,7 +885,7 @@ zoran_close_end_session (struct file *file) /* v4l buffers */ if (fh->buffers.allocated) - v4l_fbuffer_free(file); + v4l_fbuffer_free(fh); } else { /* jpg capture */ if (fh->buffers.active != ZORAN_FREE) { @@ -924,7 +896,7 @@ zoran_close_end_session (struct file *file) /* jpg buffers */ if (fh->buffers.allocated) - jpg_fbuffer_free(file); + jpg_fbuffer_free(fh); } } @@ -990,7 +962,7 @@ static int zoran_open(struct file *file) /* set file_ops stuff */ file->private_data = fh; fh->zr = zr; - zoran_open_init_session(file); + zoran_open_init_session(fh); unlock_kernel(); return 0; @@ -1019,7 +991,7 @@ zoran_close(struct file *file) * (prevents deadlocks) */ /*mutex_lock(&zr->resource_lock);*/ - zoran_close_end_session(file); + zoran_close_end_session(fh); if (zr->user-- == 1) { /* Last process */ /* Clean up JPEG process */ @@ -1086,15 +1058,13 @@ zoran_write (struct file *file, return -EINVAL; } -static int -setup_fbuffer (struct file *file, +static int setup_fbuffer(struct zoran_fh *fh, void *base, const struct zoran_format *fmt, int width, int height, int bytesperline) { - struct zoran_fh *fh = file->private_data; struct zoran *zr = fh->zr; /* (Ronald) v4l/v4l2 guidelines */ @@ -1164,17 +1134,9 @@ setup_fbuffer (struct file *file, } -static int -setup_window (struct file *file, - int x, - int y, - int width, - int height, - struct v4l2_clip __user *clips, - int clipcount, - void __user *bitmap) +static int setup_window(struct zoran_fh *fh, int x, int y, int width, int height, + struct v4l2_clip __user *clips, int clipcount, void __user *bitmap) { - struct zoran_fh *fh = file->private_data; struct zoran *zr = fh->zr; struct v4l2_clip *vcp = NULL; int on, end; @@ -1274,7 +1236,7 @@ setup_window (struct file *file, vfree(vcp); return -EFAULT; } - write_overlay_mask(file, vcp, clipcount); + write_overlay_mask(fh, vcp, clipcount); vfree(vcp); } @@ -1290,11 +1252,8 @@ setup_window (struct file *file, return wait_grab_pending(zr); } -static int -setup_overlay (struct file *file, - int on) +static int setup_overlay(struct zoran_fh *fh, int on) { - struct zoran_fh *fh = file->private_data; struct zoran *zr = fh->zr; /* If there is nothing to do, return immediatly */ @@ -1357,11 +1316,9 @@ setup_overlay (struct file *file, return wait_grab_pending(zr); } - /* get the status of a buffer in the clients buffer queue */ -static int -zoran_v4l2_buffer_status (struct zoran_fh *fh, - struct v4l2_buffer *buf, - int num) +/* get the status of a buffer in the clients buffer queue */ +static int zoran_v4l2_buffer_status(struct zoran_fh *fh, + struct v4l2_buffer *buf, int num) { struct zoran *zr = fh->zr; unsigned long flags; @@ -1735,7 +1692,7 @@ sparams_unlock_and_return: fh->buffers.num_buffers = breq->count; fh->buffers.buffer_size = breq->size; - if (jpg_fbuffer_alloc(file)) { + if (jpg_fbuffer_alloc(fh)) { res = -ENOMEM; goto jpgreqbuf_unlock_and_return; } @@ -1754,7 +1711,7 @@ jpgreqbuf_unlock_and_return: ZR_DEVNAME(zr), *frame); mutex_lock(&zr->resource_lock); - res = jpg_qbuf(file, *frame, BUZ_MODE_MOTION_COMPRESS); + res = jpg_qbuf(fh, *frame, BUZ_MODE_MOTION_COMPRESS); mutex_unlock(&zr->resource_lock); return res; @@ -1768,7 +1725,7 @@ jpgreqbuf_unlock_and_return: ZR_DEVNAME(zr), *frame); mutex_lock(&zr->resource_lock); - res = jpg_qbuf(file, *frame, BUZ_MODE_MOTION_DECOMPRESS); + res = jpg_qbuf(fh, *frame, BUZ_MODE_MOTION_DECOMPRESS); mutex_unlock(&zr->resource_lock); return res; @@ -1789,7 +1746,7 @@ jpgreqbuf_unlock_and_return: ZR_DEVNAME(zr), __func__); res = -EINVAL; } else { - res = jpg_sync(file, bsync); + res = jpg_sync(fh, bsync); } mutex_unlock(&zr->resource_lock); @@ -1884,7 +1841,7 @@ static int zoran_vidiocgmbuf(struct file *file, void *__fh, struct video_mbuf *v /* The next mmap will map the V4L buffers */ map_mode_raw(fh); - if (v4l_fbuffer_alloc(file)) { + if (v4l_fbuffer_alloc(fh)) { res = -ENOMEM; goto v4l1reqbuf_unlock_and_return; } @@ -2176,14 +2133,10 @@ static int zoran_s_fmt_vid_overlay(struct file *file, void *__fh, fmt->fmt.win.clipcount, fmt->fmt.win.bitmap); mutex_lock(&zr->resource_lock); - res = setup_window(file, fmt->fmt.win.w.left, - fmt->fmt.win.w.top, - fmt->fmt.win.w.width, - fmt->fmt.win.w.height, - (struct v4l2_clip __user *) - fmt->fmt.win.clips, - fmt->fmt.win.clipcount, - fmt->fmt.win.bitmap); + res = setup_window(fh, fmt->fmt.win.w.left, fmt->fmt.win.w.top, + fmt->fmt.win.w.width, fmt->fmt.win.w.height, + (struct v4l2_clip __user *)fmt->fmt.win.clips, + fmt->fmt.win.clipcount, fmt->fmt.win.bitmap); mutex_unlock(&zr->resource_lock); return res; } @@ -2371,9 +2324,8 @@ static int zoran_s_fbuf(struct file *file, void *__fh, } mutex_lock(&zr->resource_lock); - res = setup_fbuffer(file, fb->base, &zoran_formats[i], - fb->fmt.width, fb->fmt.height, - fb->fmt.bytesperline); + res = setup_fbuffer(fh, fb->base, &zoran_formats[i], fb->fmt.width, + fb->fmt.height, fb->fmt.bytesperline); mutex_unlock(&zr->resource_lock); return res; @@ -2386,7 +2338,7 @@ static int zoran_overlay(struct file *file, void *__fh, unsigned int on) int res; mutex_lock(&zr->resource_lock); - res = setup_overlay(file, on); + res = setup_overlay(fh, on); mutex_unlock(&zr->resource_lock); return res; @@ -2433,7 +2385,7 @@ static int zoran_reqbufs(struct file *file, void *__fh, struct v4l2_requestbuffe map_mode_raw(fh); fh->buffers.num_buffers = req->count; - if (v4l_fbuffer_alloc(file)) { + if (v4l_fbuffer_alloc(fh)) { res = -ENOMEM; goto v4l2reqbuf_unlock_and_return; } @@ -2450,7 +2402,7 @@ static int zoran_reqbufs(struct file *file, void *__fh, struct v4l2_requestbuffe fh->buffers.num_buffers = req->count; fh->buffers.buffer_size = zoran_v4l2_calc_bufsize(&fh->jpg_settings); - if (jpg_fbuffer_alloc(file)) { + if (jpg_fbuffer_alloc(fh)) { res = -ENOMEM; goto v4l2reqbuf_unlock_and_return; } @@ -2499,7 +2451,7 @@ static int zoran_qbuf(struct file *file, void *__fh, struct v4l2_buffer *buf) goto qbuf_unlock_and_return; } - res = zoran_v4l_queue_frame(file, buf->index); + res = zoran_v4l_queue_frame(fh, buf->index); if (res) goto qbuf_unlock_and_return; if (!zr->v4l_memgrab_active && fh->buffers.active == ZORAN_LOCKED) @@ -2524,8 +2476,7 @@ static int zoran_qbuf(struct file *file, void *__fh, struct v4l2_buffer *buf) goto qbuf_unlock_and_return; } - res = zoran_jpg_queue_frame(file, buf->index, - codec_mode); + res = zoran_jpg_queue_frame(fh, buf->index, codec_mode); if (res != 0) goto qbuf_unlock_and_return; if (zr->codec_mode == BUZ_MODE_IDLE && @@ -2571,7 +2522,7 @@ static int zoran_dqbuf(struct file *file, void *__fh, struct v4l2_buffer *buf) res = -EAGAIN; goto dqbuf_unlock_and_return; } - res = v4l_sync(file, num); + res = v4l_sync(fh, num); if (res) goto dqbuf_unlock_and_return; zr->v4l_sync_tail++; @@ -2603,7 +2554,7 @@ static int zoran_dqbuf(struct file *file, void *__fh, struct v4l2_buffer *buf) res = -EAGAIN; goto dqbuf_unlock_and_return; } - res = jpg_sync(file, &bs); + res = jpg_sync(fh, &bs); if (res) goto dqbuf_unlock_and_return; res = zoran_v4l2_buffer_status(fh, buf, bs.frame); @@ -2730,7 +2681,7 @@ static int zoran_streamoff(struct file *file, void *__fh, enum v4l2_buf_type typ if (zr->jpg_buffers.active == ZORAN_FREE) goto strmoff_unlock_and_return; - res = jpg_qbuf(file, -1, + res = jpg_qbuf(fh, -1, (fh->map_mode == ZORAN_MAP_MODE_JPG_REC) ? BUZ_MODE_MOTION_COMPRESS : BUZ_MODE_MOTION_DECOMPRESS); @@ -3193,8 +3144,7 @@ static void zoran_vm_close (struct vm_area_struct *vma) { struct zoran_mapping *map = vma->vm_private_data; - struct file *file = map->file; - struct zoran_fh *fh = file->private_data; + struct zoran_fh *fh = map->file->private_data; struct zoran *zr = fh->zr; int i; @@ -3230,14 +3180,14 @@ zoran_vm_close (struct vm_area_struct *vma) zr->v4l_buffers.active = fh->buffers.active = ZORAN_FREE; spin_unlock_irqrestore(&zr->spinlock, flags); } - v4l_fbuffer_free(file); + v4l_fbuffer_free(fh); } else { if (fh->buffers.active != ZORAN_FREE) { - jpg_qbuf(file, -1, zr->codec_mode); + jpg_qbuf(fh, -1, zr->codec_mode); zr->jpg_buffers.allocated = 0; zr->jpg_buffers.active = fh->buffers.active = ZORAN_FREE; } - jpg_fbuffer_free(file); + jpg_fbuffer_free(fh); } mutex_unlock(&zr->resource_lock); -- cgit v1.2.3 From f120858809ddd698f0fcf18b339b5c85112ff308 Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Tue, 10 Mar 2009 19:28:33 -0700 Subject: zoran: replace functions names in strings with __func__ From: Trent Piepho It reduces the size of the driver over all, and the function names in strings need to be manually kept up to date while __func__ doesn't. Priority: normal Signed-off-by: Trent Piepho --- linux/drivers/media/video/zoran/zoran_card.c | 115 +++++------ linux/drivers/media/video/zoran/zoran_driver.c | 254 ++++++++++++------------- 2 files changed, 173 insertions(+), 196 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/zoran/zoran_card.c b/linux/drivers/media/video/zoran/zoran_card.c index 57cc62d82..4a76df3f8 100644 --- a/linux/drivers/media/video/zoran/zoran_card.c +++ b/linux/drivers/media/video/zoran/zoran_card.c @@ -255,7 +255,7 @@ zr36016_write (struct videocodec *codec, static void dc10_init (struct zoran *zr) { - dprintk(3, KERN_DEBUG "%s: dc10_init()\n", ZR_DEVNAME(zr)); + dprintk(3, KERN_DEBUG "%s: %s\n", ZR_DEVNAME(zr), __func__); /* Pixel clock selection */ GPIO(zr, 4, 0); @@ -267,13 +267,13 @@ dc10_init (struct zoran *zr) static void dc10plus_init (struct zoran *zr) { - dprintk(3, KERN_DEBUG "%s: dc10plus_init()\n", ZR_DEVNAME(zr)); + dprintk(3, KERN_DEBUG "%s: %s\n", ZR_DEVNAME(zr), __func__); } static void buz_init (struct zoran *zr) { - dprintk(3, KERN_DEBUG "%s: buz_init()\n", ZR_DEVNAME(zr)); + dprintk(3, KERN_DEBUG "%s: %s\n", ZR_DEVNAME(zr), __func__); /* some stuff from Iomega */ pci_write_config_dword(zr->pci_dev, 0xfc, 0x90680f15); @@ -284,7 +284,7 @@ buz_init (struct zoran *zr) static void lml33_init (struct zoran *zr) { - dprintk(3, KERN_DEBUG "%s: lml33_init()\n", ZR_DEVNAME(zr)); + dprintk(3, KERN_DEBUG "%s: %s\n", ZR_DEVNAME(zr), __func__); GPIO(zr, 2, 1); // Set Composite input/output } @@ -759,13 +759,13 @@ zoran_check_jpg_settings (struct zoran *zr, dprintk(4, KERN_DEBUG - "%s: check_jpg_settings() - dec: %d, Hdcm: %d, Vdcm: %d, Tdcm: %d\n", - ZR_DEVNAME(zr), settings->decimation, settings->HorDcm, + "%s: %s - dec: %d, Hdcm: %d, Vdcm: %d, Tdcm: %d\n", + ZR_DEVNAME(zr), __func__, settings->decimation, settings->HorDcm, settings->VerDcm, settings->TmpDcm); dprintk(4, KERN_DEBUG - "%s: check_jpg_settings() - x: %d, y: %d, w: %d, y: %d\n", - ZR_DEVNAME(zr), settings->img_x, settings->img_y, + "%s: %s - x: %d, y: %d, w: %d, y: %d\n", + ZR_DEVNAME(zr), __func__, settings->img_x, settings->img_y, settings->img_width, settings->img_height); /* Check decimation, set default values for decimation = 1, 2, 4 */ switch (settings->decimation) { @@ -797,8 +797,8 @@ zoran_check_jpg_settings (struct zoran *zr, if (zr->card.type == DC10_new) { dprintk(1, KERN_DEBUG - "%s: check_jpg_settings() - HDec by 4 is not supported on the DC10\n", - ZR_DEVNAME(zr)); + "%s: %s - HDec by 4 is not supported on the DC10\n", + ZR_DEVNAME(zr), __func__); err0++; break; } @@ -875,16 +875,16 @@ zoran_check_jpg_settings (struct zoran *zr, if (!try && err0) { dprintk(1, KERN_ERR - "%s: check_jpg_settings() - error in params for decimation = 0\n", - ZR_DEVNAME(zr)); + "%s: %s - error in params for decimation = 0\n", + ZR_DEVNAME(zr), __func__); err++; } break; default: dprintk(1, KERN_ERR - "%s: check_jpg_settings() - decimation = %d, must be 0, 1, 2 or 4\n", - ZR_DEVNAME(zr), settings->decimation); + "%s: %s - decimation = %d, must be 0, 1, 2 or 4\n", + ZR_DEVNAME(zr), __func__, settings->decimation); err++; break; } @@ -964,10 +964,8 @@ zoran_open_init_params (struct zoran *zr) JPEG_MARKER_DHT | JPEG_MARKER_DQT; i = zoran_check_jpg_settings(zr, &zr->jpg_settings, 0); if (i) - dprintk(1, - KERN_ERR - "%s: zoran_open_init_params() internal error\n", - ZR_DEVNAME(zr)); + dprintk(1, KERN_ERR "%s: %s internal error\n", + ZR_DEVNAME(zr), __func__); clear_interrupt_counters(zr); zr->testing = 0; @@ -1006,8 +1004,8 @@ zr36057_init (struct zoran *zr) dprintk(1, KERN_INFO - "%s: zr36057_init() - initializing card[%d], zr=%p\n", - ZR_DEVNAME(zr), zr->id, zr); + "%s: %s - initializing card[%d], zr=%p\n", + ZR_DEVNAME(zr), __func__, zr->id, zr); /* default setup of all parameters which will persist between opens */ zr->user = 0; @@ -1040,8 +1038,8 @@ zr36057_init (struct zoran *zr) if (zr->timing == NULL) { dprintk(1, KERN_WARNING - "%s: zr36057_init() - default TV standard not supported by hardware. PAL will be used.\n", - ZR_DEVNAME(zr)); + "%s: %s - default TV standard not supported by hardware. PAL will be used.\n", + ZR_DEVNAME(zr), __func__); zr->norm = V4L2_STD_PAL; zr->timing = zr->card.tvn[0]; } @@ -1065,8 +1063,8 @@ zr36057_init (struct zoran *zr) if (!zr->stat_com || !zr->video_dev) { dprintk(1, KERN_ERR - "%s: zr36057_init() - kmalloc (STAT_COM) failed\n", - ZR_DEVNAME(zr)); + "%s: %s - kmalloc (STAT_COM) failed\n", + ZR_DEVNAME(zr), __func__); err = -ENOMEM; goto exit_free; } @@ -1160,10 +1158,8 @@ zoran_setup_videocodec (struct zoran *zr, m = kmalloc(sizeof(struct videocodec_master), GFP_KERNEL); if (!m) { - dprintk(1, - KERN_ERR - "%s: zoran_setup_videocodec() - no memory\n", - ZR_DEVNAME(zr)); + dprintk(1, KERN_ERR "%s: %s - no memory\n", + ZR_DEVNAME(zr), __func__); return m; } @@ -1220,19 +1216,15 @@ static int __devinit zoran_probe(struct pci_dev *pdev, nr = zoran_num++; if (nr >= BUZ_MAX) { - dprintk(1, - KERN_ERR - "%s: driver limited to %d card(s) maximum\n", + dprintk(1, KERN_ERR "%s: driver limited to %d card(s) maximum\n", ZORAN_NAME, BUZ_MAX); return -ENOENT; } zr = kzalloc(sizeof(struct zoran), GFP_KERNEL); if (!zr) { - dprintk(1, - KERN_ERR - "%s: find_zr36057() - kzalloc failed\n", - ZORAN_NAME); + dprintk(1, KERN_ERR "%s: %s - kzalloc failed\n", + ZORAN_NAME, __func__); return -ENOMEM; } if (v4l2_device_register(&pdev->dev, &zr->v4l2_dev)) @@ -1307,9 +1299,7 @@ static int __devinit zoran_probe(struct pci_dev *pdev, zr->zr36057_mem = pci_ioremap_bar(zr->pci_dev, 0); if (!zr->zr36057_mem) { - dprintk(1, - KERN_ERR - "%s: %s() - ioremap failed\n", + dprintk(1, KERN_ERR "%s: %s() - ioremap failed\n", ZR_DEVNAME(zr), __func__); goto zr_unreg; } @@ -1320,18 +1310,18 @@ static int __devinit zoran_probe(struct pci_dev *pdev, if (result == -EINVAL) { dprintk(1, KERN_ERR - "%s: find_zr36057() - bad irq number or handler\n", - ZR_DEVNAME(zr)); + "%s: %s - bad irq number or handler\n", + ZR_DEVNAME(zr), __func__); } else if (result == -EBUSY) { dprintk(1, KERN_ERR - "%s: find_zr36057() - IRQ %d busy, change your PnP config in BIOS\n", - ZR_DEVNAME(zr), zr->pci_dev->irq); + "%s: %s - IRQ %d busy, change your PnP config in BIOS\n", + ZR_DEVNAME(zr), __func__, zr->pci_dev->irq); } else { dprintk(1, KERN_ERR - "%s: find_zr36057() - can't assign irq, error code %d\n", - ZR_DEVNAME(zr), result); + "%s: %s - can't assign irq, error code %d\n", + ZR_DEVNAME(zr), __func__, result); } goto zr_unmap; } @@ -1341,9 +1331,7 @@ static int __devinit zoran_probe(struct pci_dev *pdev, &latency); need_latency = zr->revision > 1 ? 32 : 48; if (latency != need_latency) { - dprintk(2, - KERN_INFO - "%s: Changing PCI latency from %d to %d\n", + dprintk(2, KERN_INFO "%s: Changing PCI latency from %d to %d\n", ZR_DEVNAME(zr), latency, need_latency); pci_write_config_byte(zr->pci_dev, PCI_LATENCY_TIMER, need_latency); @@ -1355,10 +1343,8 @@ static int __devinit zoran_probe(struct pci_dev *pdev, ZR_DEVNAME(zr)); if (zoran_register_i2c(zr) < 0) { - dprintk(1, - KERN_ERR - "%s: find_zr36057() - can't initialize i2c bus\n", - ZR_DEVNAME(zr)); + dprintk(1, KERN_ERR "%s: %s - can't initialize i2c bus\n", + ZR_DEVNAME(zr), __func__); goto zr_free_irq; } @@ -1410,17 +1396,13 @@ static int __devinit zoran_probe(struct pci_dev *pdev, goto zr_unreg_i2c; zr->codec = videocodec_attach(master_codec); if (!zr->codec) { - dprintk(1, - KERN_ERR - "%s: find_zr36057() - no codec found\n", - ZR_DEVNAME(zr)); + dprintk(1, KERN_ERR "%s: %s - no codec found\n", + ZR_DEVNAME(zr), __func__); goto zr_free_codec; } if (zr->codec->type != zr->card.video_codec) { - dprintk(1, - KERN_ERR - "%s: find_zr36057() - wrong codec\n", - ZR_DEVNAME(zr)); + dprintk(1, KERN_ERR "%s: %s - wrong codec\n", + ZR_DEVNAME(zr), __func__); goto zr_detach_codec; } } @@ -1430,17 +1412,13 @@ static int __devinit zoran_probe(struct pci_dev *pdev, goto zr_detach_codec; zr->vfe = videocodec_attach(master_vfe); if (!zr->vfe) { - dprintk(1, - KERN_ERR - "%s: find_zr36057() - no VFE found\n", - ZR_DEVNAME(zr)); + dprintk(1, KERN_ERR "%s: %s - no VFE found\n", + ZR_DEVNAME(zr), __func__); goto zr_free_vfe; } if (zr->vfe->type != zr->card.video_vfe) { - dprintk(1, - KERN_ERR - "%s: find_zr36057() = wrong VFE\n", - ZR_DEVNAME(zr)); + dprintk(1, KERN_ERR "%s: %s = wrong VFE\n", + ZR_DEVNAME(zr), __func__); goto zr_detach_vfe; } } @@ -1448,8 +1426,7 @@ static int __devinit zoran_probe(struct pci_dev *pdev, /* take care of Natoma chipset and a revision 1 zr36057 */ if ((pci_pci_problems & PCIPCI_NATOMA) && zr->revision <= 1) { zr->jpg_buffers.need_contiguous = 1; - dprintk(1, - KERN_INFO + dprintk(1, KERN_INFO "%s: ZR36057/Natoma bug, max. buffer size is 128K\n", ZR_DEVNAME(zr)); } diff --git a/linux/drivers/media/video/zoran/zoran_driver.c b/linux/drivers/media/video/zoran/zoran_driver.c index 9a014ad8c..a194bf180 100644 --- a/linux/drivers/media/video/zoran/zoran_driver.c +++ b/linux/drivers/media/video/zoran/zoran_driver.c @@ -224,8 +224,8 @@ static int v4l_fbuffer_alloc(struct zoran_fh *fh) if (fh->buffers.buffer[i].v4l.fbuffer) dprintk(2, KERN_WARNING - "%s: v4l_fbuffer_alloc() - buffer %d already allocated!?\n", - ZR_DEVNAME(zr), i); + "%s: %s - buffer %d already allocated!?\n", + ZR_DEVNAME(zr), __func__, i); //udelay(20); mem = kmalloc(fh->buffers.buffer_size, @@ -233,8 +233,8 @@ static int v4l_fbuffer_alloc(struct zoran_fh *fh) if (!mem) { dprintk(1, KERN_ERR - "%s: v4l_fbuffer_alloc() - kmalloc for V4L buf %d failed\n", - ZR_DEVNAME(zr), i); + "%s: %s - kmalloc for V4L buf %d failed\n", + ZR_DEVNAME(zr), __func__, i); v4l_fbuffer_free(fh); return -ENOBUFS; } @@ -246,8 +246,8 @@ static int v4l_fbuffer_alloc(struct zoran_fh *fh) SetPageReserved(virt_to_page(mem + off)); dprintk(4, KERN_INFO - "%s: v4l_fbuffer_alloc() - V4L frame %d mem 0x%lx (bus: 0x%lx)\n", - ZR_DEVNAME(zr), i, (unsigned long) mem, + "%s: %s - V4L frame %d mem 0x%lx (bus: 0x%lx)\n", + ZR_DEVNAME(zr), __func__, i, (unsigned long) mem, virt_to_bus(mem)); } @@ -263,7 +263,7 @@ static void v4l_fbuffer_free(struct zoran_fh *fh) int i, off; unsigned char *mem; - dprintk(4, KERN_INFO "%s: v4l_fbuffer_free()\n", ZR_DEVNAME(zr)); + dprintk(4, KERN_INFO "%s: %s\n", ZR_DEVNAME(zr), __func__); for (i = 0; i < fh->buffers.num_buffers; i++) { if (!fh->buffers.buffer[i].v4l.fbuffer) @@ -318,8 +318,8 @@ static int jpg_fbuffer_alloc(struct zoran_fh *fh) if (fh->buffers.buffer[i].jpg.frag_tab) dprintk(2, KERN_WARNING - "%s: jpg_fbuffer_alloc() - buffer %d already allocated!?\n", - ZR_DEVNAME(zr), i); + "%s: %s - buffer %d already allocated!?\n", + ZR_DEVNAME(zr), __func__, i); /* Allocate fragment table for this buffer */ @@ -327,8 +327,8 @@ static int jpg_fbuffer_alloc(struct zoran_fh *fh) if (mem == 0) { dprintk(1, KERN_ERR - "%s: jpg_fbuffer_alloc() - get_zeroed_page (frag_tab) failed for buffer %d\n", - ZR_DEVNAME(zr), i); + "%s: %s - get_zeroed_page (frag_tab) failed for buffer %d\n", + ZR_DEVNAME(zr), __func__, i); jpg_fbuffer_free(fh); return -ENOBUFS; } @@ -340,8 +340,8 @@ static int jpg_fbuffer_alloc(struct zoran_fh *fh) if (mem == NULL) { dprintk(1, KERN_ERR - "%s: jpg_fbuffer_alloc() - kmalloc failed for buffer %d\n", - ZR_DEVNAME(zr), i); + "%s: %s - kmalloc failed for buffer %d\n", + ZR_DEVNAME(zr), __func__, i); jpg_fbuffer_free(fh); return -ENOBUFS; } @@ -358,8 +358,8 @@ static int jpg_fbuffer_alloc(struct zoran_fh *fh) if (mem == NULL) { dprintk(1, KERN_ERR - "%s: jpg_fbuffer_alloc() - get_zeroed_page failed for buffer %d\n", - ZR_DEVNAME(zr), i); + "%s: %s - get_zeroed_page failed for buffer %d\n", + ZR_DEVNAME(zr), __func__, i); jpg_fbuffer_free(fh); return -ENOBUFS; } @@ -376,8 +376,8 @@ static int jpg_fbuffer_alloc(struct zoran_fh *fh) } dprintk(4, - KERN_DEBUG "%s: jpg_fbuffer_alloc() - %d KB allocated\n", - ZR_DEVNAME(zr), + KERN_DEBUG "%s: %s - %d KB allocated\n", + ZR_DEVNAME(zr), __func__, (fh->buffers.num_buffers * fh->buffers.buffer_size) >> 10); fh->buffers.allocated = 1; @@ -394,7 +394,7 @@ static void jpg_fbuffer_free(struct zoran_fh *fh) __le32 frag_tab; struct zoran_buffer *buffer; - dprintk(4, KERN_DEBUG "%s: jpg_fbuffer_free()\n", ZR_DEVNAME(zr)); + dprintk(4, KERN_DEBUG "%s: %s\n", ZR_DEVNAME(zr), __func__); for (i = 0, buffer = &fh->buffers.buffer[0]; i < fh->buffers.num_buffers; i++, buffer++) { @@ -451,8 +451,8 @@ zoran_v4l_set_format (struct zoran_fh *fh, height > BUZ_MAX_HEIGHT || width > BUZ_MAX_WIDTH) { dprintk(1, KERN_ERR - "%s: v4l_set_format() - wrong frame size (%dx%d)\n", - ZR_DEVNAME(zr), width, height); + "%s: %s - wrong frame size (%dx%d)\n", + ZR_DEVNAME(zr), __func__, width, height); return -EINVAL; } @@ -462,8 +462,8 @@ zoran_v4l_set_format (struct zoran_fh *fh, if (height * width * bpp > fh->buffers.buffer_size) { dprintk(1, KERN_ERR - "%s: v4l_set_format() - video buffer size (%d kB) is too small\n", - ZR_DEVNAME(zr), fh->buffers.buffer_size >> 10); + "%s: %s - video buffer size (%d kB) is too small\n", + ZR_DEVNAME(zr), __func__, fh->buffers.buffer_size >> 10); return -EINVAL; } @@ -472,8 +472,8 @@ zoran_v4l_set_format (struct zoran_fh *fh, if ((bpp == 2 && (width & 1)) || (bpp == 3 && (width & 3))) { dprintk(1, KERN_ERR - "%s: v4l_set_format() - wrong frame alignment\n", - ZR_DEVNAME(zr)); + "%s: %s - wrong frame alignment\n", + ZR_DEVNAME(zr), __func__); return -EINVAL; } @@ -494,8 +494,8 @@ static int zoran_v4l_queue_frame(struct zoran_fh *fh, int num) if (!fh->buffers.allocated) { dprintk(1, KERN_ERR - "%s: v4l_queue_frame() - buffers not yet allocated\n", - ZR_DEVNAME(zr)); + "%s: %s - buffers not yet allocated\n", + ZR_DEVNAME(zr), __func__); res = -ENOMEM; } @@ -503,8 +503,8 @@ static int zoran_v4l_queue_frame(struct zoran_fh *fh, int num) if (num >= fh->buffers.num_buffers || num < 0) { dprintk(1, KERN_ERR - "%s: v4l_queue_frame() - buffer %d is out of range\n", - ZR_DEVNAME(zr), num); + "%s: %s - buffer %d is out of range\n", + ZR_DEVNAME(zr), __func__, num); res = -EINVAL; } @@ -517,8 +517,8 @@ static int zoran_v4l_queue_frame(struct zoran_fh *fh, int num) } else { dprintk(1, KERN_ERR - "%s: v4l_queue_frame() - another session is already capturing\n", - ZR_DEVNAME(zr)); + "%s: %s - another session is already capturing\n", + ZR_DEVNAME(zr), __func__); res = -EBUSY; } } @@ -537,8 +537,8 @@ static int zoran_v4l_queue_frame(struct zoran_fh *fh, int num) case BUZ_STATE_DONE: dprintk(2, KERN_WARNING - "%s: v4l_queue_frame() - queueing buffer %d in state DONE!?\n", - ZR_DEVNAME(zr), num); + "%s: %s - queueing buffer %d in state DONE!?\n", + ZR_DEVNAME(zr), __func__, num); case BUZ_STATE_USER: /* since there is at least one unused buffer there's room for at least * one more pend[] entry */ @@ -572,16 +572,16 @@ static int v4l_sync(struct zoran_fh *fh, int frame) if (fh->buffers.active == ZORAN_FREE) { dprintk(1, KERN_ERR - "%s: v4l_sync() - no grab active for this session\n", - ZR_DEVNAME(zr)); + "%s: %s - no grab active for this session\n", + ZR_DEVNAME(zr), __func__); return -EINVAL; } /* check passed-in frame number */ if (frame >= fh->buffers.num_buffers || frame < 0) { dprintk(1, - KERN_ERR "%s: v4l_sync() - frame %d is invalid\n", - ZR_DEVNAME(zr), frame); + KERN_ERR "%s: %s - frame %d is invalid\n", + ZR_DEVNAME(zr), __func__, frame); return -EINVAL; } @@ -589,8 +589,8 @@ static int v4l_sync(struct zoran_fh *fh, int frame) if (zr->v4l_buffers.buffer[frame].state == BUZ_STATE_USER) { dprintk(1, KERN_ERR - "%s: v4l_sync() - attempt to sync on a buffer which was not queued?\n", - ZR_DEVNAME(zr)); + "%s: %s - attempt to sync on a buffer which was not queued?\n", + ZR_DEVNAME(zr), __func__); return -EPROTO; } @@ -604,8 +604,8 @@ static int v4l_sync(struct zoran_fh *fh, int frame) /* buffer should now be in BUZ_STATE_DONE */ if (zr->v4l_buffers.buffer[frame].state != BUZ_STATE_DONE) dprintk(2, - KERN_ERR "%s: v4l_sync() - internal state error\n", - ZR_DEVNAME(zr)); + KERN_ERR "%s: %s - internal state error\n", + ZR_DEVNAME(zr), __func__); zr->v4l_buffers.buffer[frame].state = BUZ_STATE_USER; fh->buffers.buffer[frame] = zr->v4l_buffers.buffer[frame]; @@ -641,8 +641,8 @@ static int zoran_jpg_queue_frame(struct zoran_fh *fh, int num, if (!fh->buffers.allocated) { dprintk(1, KERN_ERR - "%s: jpg_queue_frame() - buffers not yet allocated\n", - ZR_DEVNAME(zr)); + "%s: %s - buffers not yet allocated\n", + ZR_DEVNAME(zr), __func__); return -ENOMEM; } @@ -650,8 +650,8 @@ static int zoran_jpg_queue_frame(struct zoran_fh *fh, int num, if (num >= fh->buffers.num_buffers || num < 0) { dprintk(1, KERN_ERR - "%s: jpg_queue_frame() - buffer %d out of range\n", - ZR_DEVNAME(zr), num); + "%s: %s - buffer %d out of range\n", + ZR_DEVNAME(zr), __func__, num); return -EINVAL; } @@ -662,8 +662,8 @@ static int zoran_jpg_queue_frame(struct zoran_fh *fh, int num, /* wrong codec mode active - invalid */ dprintk(1, KERN_ERR - "%s: jpg_queue_frame() - codec in wrong mode\n", - ZR_DEVNAME(zr)); + "%s: %s - codec in wrong mode\n", + ZR_DEVNAME(zr), __func__); return -EINVAL; } @@ -674,8 +674,8 @@ static int zoran_jpg_queue_frame(struct zoran_fh *fh, int num, } else { dprintk(1, KERN_ERR - "%s: jpg_queue_frame() - another session is already capturing\n", - ZR_DEVNAME(zr)); + "%s: %s - another session is already capturing\n", + ZR_DEVNAME(zr), __func__); res = -EBUSY; } } @@ -692,8 +692,8 @@ static int zoran_jpg_queue_frame(struct zoran_fh *fh, int num, case BUZ_STATE_DONE: dprintk(2, KERN_WARNING - "%s: jpg_queue_frame() - queing frame in BUZ_STATE_DONE state!?\n", - ZR_DEVNAME(zr)); + "%s: %s - queing frame in BUZ_STATE_DONE state!?\n", + ZR_DEVNAME(zr), __func__); case BUZ_STATE_USER: /* since there is at least one unused buffer there's room for at *least one more pend[] entry */ @@ -733,8 +733,8 @@ static int jpg_qbuf(struct zoran_fh *fh, int frame, enum zoran_codec_mode mode) if (fh->buffers.active == ZORAN_FREE) { dprintk(1, KERN_ERR - "%s: jpg_qbuf(-1) - session not active\n", - ZR_DEVNAME(zr)); + "%s: %s(-1) - session not active\n", + ZR_DEVNAME(zr), __func__); return -EINVAL; } fh->buffers.active = zr->jpg_buffers.active = ZORAN_FREE; @@ -744,8 +744,8 @@ static int jpg_qbuf(struct zoran_fh *fh, int frame, enum zoran_codec_mode mode) } else { dprintk(1, KERN_ERR - "%s: jpg_qbuf() - stop streaming but not in streaming mode\n", - ZR_DEVNAME(zr)); + "%s: %s - stop streaming but not in streaming mode\n", + ZR_DEVNAME(zr), __func__); return -EINVAL; } } @@ -773,16 +773,16 @@ static int jpg_sync(struct zoran_fh *fh, struct zoran_sync *bs) if (fh->buffers.active == ZORAN_FREE) { dprintk(1, KERN_ERR - "%s: jpg_sync() - capture is not currently active\n", - ZR_DEVNAME(zr)); + "%s: %s - capture is not currently active\n", + ZR_DEVNAME(zr), __func__); return -EINVAL; } if (zr->codec_mode != BUZ_MODE_MOTION_DECOMPRESS && zr->codec_mode != BUZ_MODE_MOTION_COMPRESS) { dprintk(1, KERN_ERR - "%s: jpg_sync() - codec not in streaming mode\n", - ZR_DEVNAME(zr)); + "%s: %s - codec not in streaming mode\n", + ZR_DEVNAME(zr), __func__); return -EINVAL; } if (!wait_event_interruptible_timeout(zr->jpg_capq, @@ -797,8 +797,8 @@ static int jpg_sync(struct zoran_fh *fh, struct zoran_sync *bs) sizeof(isr), &isr); dprintk(1, KERN_ERR - "%s: jpg_sync() - timeout: codec isr=0x%02x\n", - ZR_DEVNAME(zr), isr); + "%s: %s - timeout: codec isr=0x%02x\n", + ZR_DEVNAME(zr), __func__, isr); return -ETIME; @@ -816,8 +816,8 @@ static int jpg_sync(struct zoran_fh *fh, struct zoran_sync *bs) /* buffer should now be in BUZ_STATE_DONE */ if (zr->jpg_buffers.buffer[frame].state != BUZ_STATE_DONE) dprintk(2, - KERN_ERR "%s: jpg_sync() - internal state error\n", - ZR_DEVNAME(zr)); + KERN_ERR "%s: %s - internal state error\n", + ZR_DEVNAME(zr), __func__); *bs = zr->jpg_buffers.buffer[frame].bs; bs->frame = frame; @@ -910,8 +910,8 @@ static int zoran_open(struct file *file) struct zoran_fh *fh; int res, first_open = 0; - dprintk(2, KERN_INFO "%s: zoran_open(%s, pid=[%d]), users(-)=%d\n", - ZR_DEVNAME(zr), current->comm, task_pid_nr(current), zr->user + 1); + dprintk(2, KERN_INFO "%s: %s(%s, pid=[%d]), users(-)=%d\n", + ZR_DEVNAME(zr), __func__, current->comm, task_pid_nr(current), zr->user + 1); lock_kernel(); @@ -927,8 +927,8 @@ static int zoran_open(struct file *file) if (!fh) { dprintk(1, KERN_ERR - "%s: zoran_open() - allocation of zoran_fh failed\n", - ZR_DEVNAME(zr)); + "%s: %s - allocation of zoran_fh failed\n", + ZR_DEVNAME(zr), __func__); res = -ENOMEM; goto fail_unlock; } @@ -939,8 +939,8 @@ static int zoran_open(struct file *file) if (!fh->overlay_mask) { dprintk(1, KERN_ERR - "%s: zoran_open() - allocation of overlay_mask failed\n", - ZR_DEVNAME(zr)); + "%s: %s - allocation of overlay_mask failed\n", + ZR_DEVNAME(zr), __func__); res = -ENOMEM; goto fail_fh; } @@ -984,8 +984,8 @@ zoran_close(struct file *file) struct zoran_fh *fh = file->private_data; struct zoran *zr = fh->zr; - dprintk(2, KERN_INFO "%s: zoran_close(%s, pid=[%d]), users(+)=%d\n", - ZR_DEVNAME(zr), current->comm, task_pid_nr(current), zr->user - 1); + dprintk(2, KERN_INFO "%s: %s(%s, pid=[%d]), users(+)=%d\n", + ZR_DEVNAME(zr), __func__, current->comm, task_pid_nr(current), zr->user - 1); /* kernel locks (fs/device.c), so don't do that ourselves * (prevents deadlocks) */ @@ -1030,7 +1030,7 @@ zoran_close(struct file *file) kfree(fh->overlay_mask); kfree(fh); - dprintk(4, KERN_INFO "%s: zoran_close() done\n", ZR_DEVNAME(zr)); + dprintk(4, KERN_INFO "%s: %s done\n", ZR_DEVNAME(zr), __func__); return 0; } @@ -1092,8 +1092,8 @@ static int setup_fbuffer(struct zoran_fh *fh, * friendly and silently do as if nothing went wrong */ dprintk(3, KERN_ERR - "%s: setup_fbuffer() - forced overlay turnoff because framebuffer changed\n", - ZR_DEVNAME(zr)); + "%s: %s - forced overlay turnoff because framebuffer changed\n", + ZR_DEVNAME(zr), __func__); zr36057_overlay(zr, 0); } #endif @@ -1101,22 +1101,22 @@ static int setup_fbuffer(struct zoran_fh *fh, if (!(fmt->flags & ZORAN_FORMAT_OVERLAY)) { dprintk(1, KERN_ERR - "%s: setup_fbuffer() - no valid overlay format given\n", - ZR_DEVNAME(zr)); + "%s: %s - no valid overlay format given\n", + ZR_DEVNAME(zr), __func__); return -EINVAL; } if (height <= 0 || width <= 0 || bytesperline <= 0) { dprintk(1, KERN_ERR - "%s: setup_fbuffer() - invalid height/width/bpl value (%d|%d|%d)\n", - ZR_DEVNAME(zr), width, height, bytesperline); + "%s: %s - invalid height/width/bpl value (%d|%d|%d)\n", + ZR_DEVNAME(zr), __func__, width, height, bytesperline); return -EINVAL; } if (bytesperline & 3) { dprintk(1, KERN_ERR - "%s: setup_fbuffer() - bytesperline (%d) must be 4-byte aligned\n", - ZR_DEVNAME(zr), bytesperline); + "%s: %s - bytesperline (%d) must be 4-byte aligned\n", + ZR_DEVNAME(zr), __func__, bytesperline); return -EINVAL; } @@ -1145,16 +1145,16 @@ static int setup_window(struct zoran_fh *fh, int x, int y, int width, int height if (!zr->vbuf_base) { dprintk(1, KERN_ERR - "%s: setup_window() - frame buffer has to be set first\n", - ZR_DEVNAME(zr)); + "%s: %s - frame buffer has to be set first\n", + ZR_DEVNAME(zr), __func__); return -EINVAL; } if (!fh->overlay_settings.format) { dprintk(1, KERN_ERR - "%s: setup_window() - no overlay format set\n", - ZR_DEVNAME(zr)); + "%s: %s - no overlay format set\n", + ZR_DEVNAME(zr), __func__); return -EINVAL; } @@ -1184,8 +1184,8 @@ static int setup_window(struct zoran_fh *fh, int x, int y, int width, int height width > BUZ_MAX_WIDTH || height > BUZ_MAX_HEIGHT) { dprintk(1, KERN_ERR - "%s: setup_window() - width = %d or height = %d invalid\n", - ZR_DEVNAME(zr), width, height); + "%s: %s - width = %d or height = %d invalid\n", + ZR_DEVNAME(zr), __func__, width, height); return -EINVAL; } @@ -1227,8 +1227,8 @@ static int setup_window(struct zoran_fh *fh, int x, int y, int width, int height if (vcp == NULL) { dprintk(1, KERN_ERR - "%s: setup_window() - Alloc of clip mask failed\n", - ZR_DEVNAME(zr)); + "%s: %s - Alloc of clip mask failed\n", + ZR_DEVNAME(zr), __func__); return -ENOMEM; } if (copy_from_user @@ -1266,16 +1266,16 @@ static int setup_overlay(struct zoran_fh *fh, int on) fh->overlay_active == ZORAN_FREE) { dprintk(1, KERN_ERR - "%s: setup_overlay() - overlay is already active for another session\n", - ZR_DEVNAME(zr)); + "%s: %s - overlay is already active for another session\n", + ZR_DEVNAME(zr), __func__); return -EBUSY; } if (!on && zr->overlay_active != ZORAN_FREE && fh->overlay_active == ZORAN_FREE) { dprintk(1, KERN_ERR - "%s: setup_overlay() - you cannot cancel someone else's session\n", - ZR_DEVNAME(zr)); + "%s: %s - you cannot cancel someone else's session\n", + ZR_DEVNAME(zr), __func__); return -EPERM; } @@ -1291,15 +1291,15 @@ static int setup_overlay(struct zoran_fh *fh, int on) if (!zr->vbuf_base || !fh->overlay_settings.is_set) { dprintk(1, KERN_ERR - "%s: setup_overlay() - buffer or window not set\n", - ZR_DEVNAME(zr)); + "%s: %s - buffer or window not set\n", + ZR_DEVNAME(zr), __func__); return -EINVAL; } if (!fh->overlay_settings.format) { dprintk(1, KERN_ERR - "%s: setup_overlay() - no overlay format set\n", - ZR_DEVNAME(zr)); + "%s: %s - no overlay format set\n", + ZR_DEVNAME(zr), __func__); return -EINVAL; } zr->overlay_active = fh->overlay_active = ZORAN_LOCKED; @@ -1332,8 +1332,8 @@ static int zoran_v4l2_buffer_status(struct zoran_fh *fh, !fh->buffers.allocated) { dprintk(1, KERN_ERR - "%s: v4l2_buffer_status() - wrong number or buffers not allocated\n", - ZR_DEVNAME(zr)); + "%s: %s - wrong number or buffers not allocated\n", + ZR_DEVNAME(zr), __func__); return -EINVAL; } @@ -1383,8 +1383,8 @@ static int zoran_v4l2_buffer_status(struct zoran_fh *fh, !fh->buffers.allocated) { dprintk(1, KERN_ERR - "%s: v4l2_buffer_status() - wrong number or buffers not allocated\n", - ZR_DEVNAME(zr)); + "%s: %s - wrong number or buffers not allocated\n", + ZR_DEVNAME(zr), __func__); return -EINVAL; } @@ -1418,8 +1418,8 @@ static int zoran_v4l2_buffer_status(struct zoran_fh *fh, dprintk(5, KERN_ERR - "%s: v4l2_buffer_status() - invalid buffer type|map_mode (%d|%d)\n", - ZR_DEVNAME(zr), buf->type, fh->map_mode); + "%s: %s - invalid buffer type|map_mode (%d|%d)\n", + ZR_DEVNAME(zr), __func__, buf->type, fh->map_mode); return -EINVAL; } @@ -1440,15 +1440,15 @@ zoran_set_norm (struct zoran *zr, zr->jpg_buffers.active != ZORAN_FREE) { dprintk(1, KERN_WARNING - "%s: set_norm() called while in playback/capture mode\n", - ZR_DEVNAME(zr)); + "%s: %s called while in playback/capture mode\n", + ZR_DEVNAME(zr), __func__); return -EBUSY; } if (!(norm & zr->card.norms)) { dprintk(1, - KERN_ERR "%s: set_norm() - unsupported norm %llx\n", - ZR_DEVNAME(zr), norm); + KERN_ERR "%s: %s - unsupported norm %llx\n", + ZR_DEVNAME(zr), __func__, norm); return -EINVAL; } @@ -1466,8 +1466,8 @@ zoran_set_norm (struct zoran *zr, if (status & V4L2_IN_ST_NO_SIGNAL) { dprintk(1, KERN_ERR - "%s: set_norm() - no norm detected\n", - ZR_DEVNAME(zr)); + "%s: %s - no norm detected\n", + ZR_DEVNAME(zr), __func__); /* reset norm */ decoder_s_std(zr, zr->norm); return -EIO; @@ -1514,16 +1514,16 @@ zoran_set_input (struct zoran *zr, zr->jpg_buffers.active != ZORAN_FREE) { dprintk(1, KERN_WARNING - "%s: set_input() called while in playback/capture mode\n", - ZR_DEVNAME(zr)); + "%s: %s called while in playback/capture mode\n", + ZR_DEVNAME(zr), __func__); return -EBUSY; } if (input < 0 || input >= zr->card.inputs) { dprintk(1, KERN_ERR - "%s: set_input() - unnsupported input %d\n", - ZR_DEVNAME(zr), input); + "%s: %s - unnsupported input %d\n", + ZR_DEVNAME(zr), __func__, input); return -EINVAL; } @@ -3109,8 +3109,8 @@ zoran_poll (struct file *file, default: dprintk(1, KERN_ERR - "%s: zoran_poll() - internal error, unknown map_mode=%d\n", - ZR_DEVNAME(zr), fh->map_mode); + "%s: %s - internal error, unknown map_mode=%d\n", + ZR_DEVNAME(zr), __func__, fh->map_mode); res = POLLNVAL; } @@ -3213,16 +3213,16 @@ zoran_mmap (struct file *file, int res = 0; dprintk(3, - KERN_INFO "%s: mmap(%s) of 0x%08lx-0x%08lx (size=%lu)\n", - ZR_DEVNAME(zr), + KERN_INFO "%s: %s(%s) of 0x%08lx-0x%08lx (size=%lu)\n", + ZR_DEVNAME(zr), __func__, mode_name(fh->map_mode), vma->vm_start, vma->vm_end, size); if (!(vma->vm_flags & VM_SHARED) || !(vma->vm_flags & VM_READ) || !(vma->vm_flags & VM_WRITE)) { dprintk(1, KERN_ERR - "%s: mmap() - no MAP_SHARED/PROT_{READ,WRITE} given\n", - ZR_DEVNAME(zr)); + "%s: %s - no MAP_SHARED/PROT_{READ,WRITE} given\n", + ZR_DEVNAME(zr), __func__); return -EINVAL; } @@ -3231,8 +3231,8 @@ zoran_mmap (struct file *file, if (!fh->buffers.allocated) { dprintk(1, KERN_ERR - "%s: zoran_mmap(%s) - buffers not yet allocated\n", - ZR_DEVNAME(zr), mode_name(fh->map_mode)); + "%s: %s(%s) - buffers not yet allocated\n", + ZR_DEVNAME(zr), __func__, mode_name(fh->map_mode)); res = -ENOMEM; goto mmap_unlock_and_return; } @@ -3245,8 +3245,8 @@ zoran_mmap (struct file *file, last >= fh->buffers.buffer_size) { dprintk(1, KERN_ERR - "%s: mmap(%s) - offset=%lu or size=%lu invalid for bufsize=%d and numbufs=%d\n", - ZR_DEVNAME(zr), mode_name(fh->map_mode), offset, size, + "%s: %s(%s) - offset=%lu or size=%lu invalid for bufsize=%d and numbufs=%d\n", + ZR_DEVNAME(zr), __func__, mode_name(fh->map_mode), offset, size, fh->buffers.buffer_size, fh->buffers.num_buffers); res = -EINVAL; @@ -3258,8 +3258,8 @@ zoran_mmap (struct file *file, if (fh->buffers.buffer[i].map) { dprintk(1, KERN_ERR - "%s: mmap(%s) - buffer %d already mapped\n", - ZR_DEVNAME(zr), mode_name(fh->map_mode), i); + "%s: %s(%s) - buffer %d already mapped\n", + ZR_DEVNAME(zr), __func__, mode_name(fh->map_mode), i); res = -EBUSY; goto mmap_unlock_and_return; } @@ -3288,8 +3288,8 @@ zoran_mmap (struct file *file, todo, PAGE_SHARED)) { dprintk(1, KERN_ERR - "%s: zoran_mmap(V4L) - remap_pfn_range failed\n", - ZR_DEVNAME(zr)); + "%s: %s(V4L) - remap_pfn_range failed\n", + ZR_DEVNAME(zr), __func__); res = -EAGAIN; goto mmap_unlock_and_return; } @@ -3320,8 +3320,8 @@ zoran_mmap (struct file *file, todo, PAGE_SHARED)) { dprintk(1, KERN_ERR - "%s: zoran_mmap(V4L) - remap_pfn_range failed\n", - ZR_DEVNAME(zr)); + "%s: %s(V4L) - remap_pfn_range failed\n", + ZR_DEVNAME(zr), __func__); res = -EAGAIN; goto mmap_unlock_and_return; } -- cgit v1.2.3 From 974598b3e1d92694dec31bb072cd65be34fa012d Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 5 Mar 2009 09:38:24 +0000 Subject: cx88: Prevent general protection fault on rmmod From: Jean Delvare When unloading the cx8800 driver I sometimes get a general protection fault. Analysis revealed a race in cx88_ir_stop(). It can be solved by using a delayed work instead of a timer for infrared input polling. This fixes kernel.org bug #12802. Signed-off-by: Jean Delvare Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/cx88/cx88-input.c | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/cx88/cx88-input.c b/linux/drivers/media/video/cx88/cx88-input.c index dbb6ee2d9..f247e5f45 100644 --- a/linux/drivers/media/video/cx88/cx88-input.c +++ b/linux/drivers/media/video/cx88/cx88-input.c @@ -49,8 +49,12 @@ struct cx88_IR { /* poll external decoder */ int polling; +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) struct work_struct work; struct timer_list timer; +#else + struct delayed_work work; +#endif u32 gpio_addr; u32 last_gpio; u32 mask_keycode; @@ -144,6 +148,7 @@ static void cx88_ir_handle_key(struct cx88_IR *ir) } } +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) static void ir_timer(unsigned long data) { struct cx88_IR *ir = (struct cx88_IR *)data; @@ -151,7 +156,6 @@ static void ir_timer(unsigned long data) schedule_work(&ir->work); } -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) static void cx88_ir_work(void *data) #else static void cx88_ir_work(struct work_struct *work) @@ -160,23 +164,30 @@ static void cx88_ir_work(struct work_struct *work) #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) struct cx88_IR *ir = data; #else - struct cx88_IR *ir = container_of(work, struct cx88_IR, work); + struct delayed_work *dwork = container_of(work, struct delayed_work, + work); + struct cx88_IR *ir = container_of(dwork, struct cx88_IR, work); #endif cx88_ir_handle_key(ir); +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) mod_timer(&ir->timer, jiffies + msecs_to_jiffies(ir->polling)); +#else + schedule_delayed_work(dwork, msecs_to_jiffies(ir->polling)); +#endif } void cx88_ir_start(struct cx88_core *core, struct cx88_IR *ir) { if (ir->polling) { - setup_timer(&ir->timer, ir_timer, (unsigned long)ir); #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) + setup_timer(&ir->timer, ir_timer, (unsigned long)ir); INIT_WORK(&ir->work, cx88_ir_work, ir); + schedule_work(&ir->work); #else - INIT_WORK(&ir->work, cx88_ir_work); + INIT_DELAYED_WORK(&ir->work, cx88_ir_work); + schedule_delayed_work(&ir->work, msecs_to_jiffies(ir->polling)); #endif - schedule_work(&ir->work); } if (ir->sampling) { core->pci_irqmask |= PCI_INT_IR_SMPINT; @@ -193,8 +204,12 @@ void cx88_ir_stop(struct cx88_core *core, struct cx88_IR *ir) } if (ir->polling) { +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) del_timer_sync(&ir->timer); flush_scheduled_work(); +#else + cancel_delayed_work_sync(&ir->work); +#endif } } -- cgit v1.2.3 From 24ef92f0974bf26cf8ca949b7ae21286cbca3fd3 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 5 Mar 2009 09:39:30 +0000 Subject: Fix race in infrared polling on rmmod From: Jean Delvare The race on rmmod I just fixed in cx88-input affects 3 other drivers. Fix these the same way. Signed-off-by: Jean Delvare Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/em28xx/em28xx-input.c | 25 ++++++++++++++++++++----- linux/drivers/media/video/ir-kbd-i2c.c | 21 ++++++++++++++++----- linux/drivers/media/video/saa6588.c | 25 ++++++++++++++++++++----- 3 files changed, 56 insertions(+), 15 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/em28xx/em28xx-input.c b/linux/drivers/media/video/em28xx/em28xx-input.c index b97a1bc85..b1344499e 100644 --- a/linux/drivers/media/video/em28xx/em28xx-input.c +++ b/linux/drivers/media/video/em28xx/em28xx-input.c @@ -69,8 +69,12 @@ struct em28xx_IR { /* poll external decoder */ int polling; +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20) struct work_struct work; struct timer_list timer; +#else + struct delayed_work work; +#endif unsigned int last_toggle:1; unsigned int last_readcount; unsigned int repeat_interval; @@ -298,6 +302,7 @@ static void em28xx_ir_handle_key(struct em28xx_IR *ir) return; } +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20) static void ir_timer(unsigned long data) { struct em28xx_IR *ir = (struct em28xx_IR *)data; @@ -305,7 +310,6 @@ static void ir_timer(unsigned long data) schedule_work(&ir->work); } -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20) static void em28xx_ir_work(void *data) #else static void em28xx_ir_work(struct work_struct *work) @@ -314,28 +318,39 @@ static void em28xx_ir_work(struct work_struct *work) #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20) struct em28xx_IR *ir = data; #else - struct em28xx_IR *ir = container_of(work, struct em28xx_IR, work); + struct delayed_work *dwork = container_of(work, struct delayed_work, + work); + struct em28xx_IR *ir = container_of(dwork, struct em28xx_IR, work); #endif em28xx_ir_handle_key(ir); +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20) mod_timer(&ir->timer, jiffies + msecs_to_jiffies(ir->polling)); +#else + schedule_delayed_work(dwork, msecs_to_jiffies(ir->polling)); +#endif } static void em28xx_ir_start(struct em28xx_IR *ir) { - setup_timer(&ir->timer, ir_timer, (unsigned long)ir); #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20) + setup_timer(&ir->timer, ir_timer, (unsigned long)ir); INIT_WORK(&ir->work, em28xx_ir_work, ir); + schedule_work(&ir->work); #else - INIT_WORK(&ir->work, em28xx_ir_work); + INIT_DELAYED_WORK(&ir->work, em28xx_ir_work); + schedule_delayed_work(&ir->work, msecs_to_jiffies(ir->polling)); #endif - schedule_work(&ir->work); } static void em28xx_ir_stop(struct em28xx_IR *ir) { +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20) del_timer_sync(&ir->timer); flush_scheduled_work(); +#else + cancel_delayed_work_sync(&ir->work); +#endif } int em28xx_ir_init(struct em28xx *dev) diff --git a/linux/drivers/media/video/ir-kbd-i2c.c b/linux/drivers/media/video/ir-kbd-i2c.c index a99aea49a..fa5480f64 100644 --- a/linux/drivers/media/video/ir-kbd-i2c.c +++ b/linux/drivers/media/video/ir-kbd-i2c.c @@ -280,13 +280,13 @@ static void ir_key_poll(struct IR_i2c *ir) } } +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) static void ir_timer(unsigned long data) { struct IR_i2c *ir = (struct IR_i2c*)data; schedule_work(&ir->work); } -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) static void ir_work(void *data) #else static void ir_work(struct work_struct *work) @@ -295,7 +295,9 @@ static void ir_work(struct work_struct *work) #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) struct IR_i2c *ir = data; #else - struct IR_i2c *ir = container_of(work, struct IR_i2c, work); + struct delayed_work *dwork = container_of(work, struct delayed_work, + work); + struct IR_i2c *ir = container_of(dwork, struct IR_i2c, work); #endif int polling_interval = 100; @@ -305,7 +307,11 @@ static void ir_work(struct work_struct *work) polling_interval = 50; ir_key_poll(ir); +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) mod_timer(&ir->timer, jiffies + msecs_to_jiffies(polling_interval)); +#else + schedule_delayed_work(dwork, msecs_to_jiffies(polling_interval)); +#endif } /* ----------------------------------------------------------------------- */ @@ -463,13 +469,14 @@ static int ir_attach(struct i2c_adapter *adap, int addr, /* start polling via eventd */ #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) INIT_WORK(&ir->work, ir_work, ir); -#else - INIT_WORK(&ir->work, ir_work); -#endif init_timer(&ir->timer); ir->timer.function = ir_timer; ir->timer.data = (unsigned long)ir; schedule_work(&ir->work); +#else + INIT_DELAYED_WORK(&ir->work, ir_work); + schedule_delayed_work(&ir->work, msecs_to_jiffies(100)); +#endif return 0; @@ -486,8 +493,12 @@ static int ir_detach(struct i2c_client *client) struct IR_i2c *ir = i2c_get_clientdata(client); /* kill outstanding polls */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) del_timer_sync(&ir->timer); flush_scheduled_work(); +#else + cancel_delayed_work_sync(&ir->work); +#endif /* unregister devices */ input_unregister_device(ir->input); diff --git a/linux/drivers/media/video/saa6588.c b/linux/drivers/media/video/saa6588.c index ae96de5fd..4b9b51e39 100644 --- a/linux/drivers/media/video/saa6588.c +++ b/linux/drivers/media/video/saa6588.c @@ -77,8 +77,12 @@ MODULE_LICENSE("GPL"); struct saa6588 { struct v4l2_subdev sd; +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20) struct work_struct work; struct timer_list timer; +#else + struct delayed_work work; +#endif spinlock_t lock; unsigned char *buffer; unsigned int buf_size; @@ -323,6 +327,7 @@ static void saa6588_i2c_poll(struct saa6588 *s) wake_up_interruptible(&s->read_queue); } +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20) static void saa6588_timer(unsigned long data) { struct saa6588 *s = (struct saa6588 *)data; @@ -330,7 +335,6 @@ static void saa6588_timer(unsigned long data) schedule_work(&s->work); } -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) static void saa6588_work(void *data) #else static void saa6588_work(struct work_struct *work) @@ -339,11 +343,17 @@ static void saa6588_work(struct work_struct *work) #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) struct saa6588 *s = (struct saa6588 *)data; #else - struct saa6588 *s = container_of(work, struct saa6588, work); + struct delayed_work *dwork = container_of(work, struct delayed_work, + work); + struct saa6588 *s = container_of(dwork, struct saa6588, work); #endif saa6588_i2c_poll(s); +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20) mod_timer(&s->timer, jiffies + msecs_to_jiffies(20)); +#else + schedule_delayed_work(dwork, msecs_to_jiffies(20)); +#endif } static int saa6588_configure(struct saa6588 *s) @@ -501,13 +511,14 @@ static int saa6588_probe(struct i2c_client *client, /* start polling via eventd */ #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20) INIT_WORK(&s->work, saa6588_work, s); -#else - INIT_WORK(&s->work, saa6588_work); -#endif init_timer(&s->timer); s->timer.function = saa6588_timer; s->timer.data = (unsigned long)s; schedule_work(&s->work); +#else + INIT_DELAYED_WORK(&s->work, saa6588_work); + schedule_delayed_work(&s->work, msecs_to_jiffies(20)); +#endif return 0; } @@ -518,8 +529,12 @@ static int saa6588_remove(struct i2c_client *client) v4l2_device_unregister_subdev(sd); +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20) del_timer_sync(&s->timer); flush_scheduled_work(); +#else + cancel_delayed_work_sync(&s->work); +#endif kfree(s->buffer); kfree(s); -- cgit v1.2.3 From d7673f843f104186787be352493d8660570163ab Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 11 Mar 2009 07:51:41 -0300 Subject: Revert the last changeset, since there are a rev 2 of those changes From: Mauro Carvalho Chehab Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/em28xx/em28xx-input.c | 25 +++++-------------------- linux/drivers/media/video/ir-kbd-i2c.c | 21 +++++---------------- linux/drivers/media/video/saa6588.c | 25 +++++-------------------- 3 files changed, 15 insertions(+), 56 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/em28xx/em28xx-input.c b/linux/drivers/media/video/em28xx/em28xx-input.c index b1344499e..b97a1bc85 100644 --- a/linux/drivers/media/video/em28xx/em28xx-input.c +++ b/linux/drivers/media/video/em28xx/em28xx-input.c @@ -69,12 +69,8 @@ struct em28xx_IR { /* poll external decoder */ int polling; -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20) struct work_struct work; struct timer_list timer; -#else - struct delayed_work work; -#endif unsigned int last_toggle:1; unsigned int last_readcount; unsigned int repeat_interval; @@ -302,7 +298,6 @@ static void em28xx_ir_handle_key(struct em28xx_IR *ir) return; } -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20) static void ir_timer(unsigned long data) { struct em28xx_IR *ir = (struct em28xx_IR *)data; @@ -310,6 +305,7 @@ static void ir_timer(unsigned long data) schedule_work(&ir->work); } +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20) static void em28xx_ir_work(void *data) #else static void em28xx_ir_work(struct work_struct *work) @@ -318,39 +314,28 @@ static void em28xx_ir_work(struct work_struct *work) #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20) struct em28xx_IR *ir = data; #else - struct delayed_work *dwork = container_of(work, struct delayed_work, - work); - struct em28xx_IR *ir = container_of(dwork, struct em28xx_IR, work); + struct em28xx_IR *ir = container_of(work, struct em28xx_IR, work); #endif em28xx_ir_handle_key(ir); -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20) mod_timer(&ir->timer, jiffies + msecs_to_jiffies(ir->polling)); -#else - schedule_delayed_work(dwork, msecs_to_jiffies(ir->polling)); -#endif } static void em28xx_ir_start(struct em28xx_IR *ir) { -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20) setup_timer(&ir->timer, ir_timer, (unsigned long)ir); +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20) INIT_WORK(&ir->work, em28xx_ir_work, ir); - schedule_work(&ir->work); #else - INIT_DELAYED_WORK(&ir->work, em28xx_ir_work); - schedule_delayed_work(&ir->work, msecs_to_jiffies(ir->polling)); + INIT_WORK(&ir->work, em28xx_ir_work); #endif + schedule_work(&ir->work); } static void em28xx_ir_stop(struct em28xx_IR *ir) { -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20) del_timer_sync(&ir->timer); flush_scheduled_work(); -#else - cancel_delayed_work_sync(&ir->work); -#endif } int em28xx_ir_init(struct em28xx *dev) diff --git a/linux/drivers/media/video/ir-kbd-i2c.c b/linux/drivers/media/video/ir-kbd-i2c.c index fa5480f64..a99aea49a 100644 --- a/linux/drivers/media/video/ir-kbd-i2c.c +++ b/linux/drivers/media/video/ir-kbd-i2c.c @@ -280,13 +280,13 @@ static void ir_key_poll(struct IR_i2c *ir) } } -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) static void ir_timer(unsigned long data) { struct IR_i2c *ir = (struct IR_i2c*)data; schedule_work(&ir->work); } +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) static void ir_work(void *data) #else static void ir_work(struct work_struct *work) @@ -295,9 +295,7 @@ static void ir_work(struct work_struct *work) #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) struct IR_i2c *ir = data; #else - struct delayed_work *dwork = container_of(work, struct delayed_work, - work); - struct IR_i2c *ir = container_of(dwork, struct IR_i2c, work); + struct IR_i2c *ir = container_of(work, struct IR_i2c, work); #endif int polling_interval = 100; @@ -307,11 +305,7 @@ static void ir_work(struct work_struct *work) polling_interval = 50; ir_key_poll(ir); -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) mod_timer(&ir->timer, jiffies + msecs_to_jiffies(polling_interval)); -#else - schedule_delayed_work(dwork, msecs_to_jiffies(polling_interval)); -#endif } /* ----------------------------------------------------------------------- */ @@ -469,14 +463,13 @@ static int ir_attach(struct i2c_adapter *adap, int addr, /* start polling via eventd */ #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) INIT_WORK(&ir->work, ir_work, ir); +#else + INIT_WORK(&ir->work, ir_work); +#endif init_timer(&ir->timer); ir->timer.function = ir_timer; ir->timer.data = (unsigned long)ir; schedule_work(&ir->work); -#else - INIT_DELAYED_WORK(&ir->work, ir_work); - schedule_delayed_work(&ir->work, msecs_to_jiffies(100)); -#endif return 0; @@ -493,12 +486,8 @@ static int ir_detach(struct i2c_client *client) struct IR_i2c *ir = i2c_get_clientdata(client); /* kill outstanding polls */ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) del_timer_sync(&ir->timer); flush_scheduled_work(); -#else - cancel_delayed_work_sync(&ir->work); -#endif /* unregister devices */ input_unregister_device(ir->input); diff --git a/linux/drivers/media/video/saa6588.c b/linux/drivers/media/video/saa6588.c index 4b9b51e39..ae96de5fd 100644 --- a/linux/drivers/media/video/saa6588.c +++ b/linux/drivers/media/video/saa6588.c @@ -77,12 +77,8 @@ MODULE_LICENSE("GPL"); struct saa6588 { struct v4l2_subdev sd; -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20) struct work_struct work; struct timer_list timer; -#else - struct delayed_work work; -#endif spinlock_t lock; unsigned char *buffer; unsigned int buf_size; @@ -327,7 +323,6 @@ static void saa6588_i2c_poll(struct saa6588 *s) wake_up_interruptible(&s->read_queue); } -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20) static void saa6588_timer(unsigned long data) { struct saa6588 *s = (struct saa6588 *)data; @@ -335,6 +330,7 @@ static void saa6588_timer(unsigned long data) schedule_work(&s->work); } +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) static void saa6588_work(void *data) #else static void saa6588_work(struct work_struct *work) @@ -343,17 +339,11 @@ static void saa6588_work(struct work_struct *work) #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) struct saa6588 *s = (struct saa6588 *)data; #else - struct delayed_work *dwork = container_of(work, struct delayed_work, - work); - struct saa6588 *s = container_of(dwork, struct saa6588, work); + struct saa6588 *s = container_of(work, struct saa6588, work); #endif saa6588_i2c_poll(s); -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20) mod_timer(&s->timer, jiffies + msecs_to_jiffies(20)); -#else - schedule_delayed_work(dwork, msecs_to_jiffies(20)); -#endif } static int saa6588_configure(struct saa6588 *s) @@ -511,14 +501,13 @@ static int saa6588_probe(struct i2c_client *client, /* start polling via eventd */ #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20) INIT_WORK(&s->work, saa6588_work, s); +#else + INIT_WORK(&s->work, saa6588_work); +#endif init_timer(&s->timer); s->timer.function = saa6588_timer; s->timer.data = (unsigned long)s; schedule_work(&s->work); -#else - INIT_DELAYED_WORK(&s->work, saa6588_work); - schedule_delayed_work(&s->work, msecs_to_jiffies(20)); -#endif return 0; } @@ -529,12 +518,8 @@ static int saa6588_remove(struct i2c_client *client) v4l2_device_unregister_subdev(sd); -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20) del_timer_sync(&s->timer); flush_scheduled_work(); -#else - cancel_delayed_work_sync(&s->work); -#endif kfree(s->buffer); kfree(s); -- cgit v1.2.3 From bf6a78d38280357d2cbb3d3e84ec17f52dae1370 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 7 Mar 2009 10:43:01 +0000 Subject: em28xx: Prevent general protection fault on rmmod From: Jean Delvare The removal of the timer which polls the infrared input is racy. Replacing the timer with a delayed work solves the problem. Signed-off-by: Jean Delvare Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/em28xx/em28xx-input.c | 24 +++++++----------------- 1 file changed, 7 insertions(+), 17 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/em28xx/em28xx-input.c b/linux/drivers/media/video/em28xx/em28xx-input.c index b97a1bc85..5382a6064 100644 --- a/linux/drivers/media/video/em28xx/em28xx-input.c +++ b/linux/drivers/media/video/em28xx/em28xx-input.c @@ -69,8 +69,7 @@ struct em28xx_IR { /* poll external decoder */ int polling; - struct work_struct work; - struct timer_list timer; + struct delayed_work work; unsigned int last_toggle:1; unsigned int last_readcount; unsigned int repeat_interval; @@ -298,13 +297,6 @@ static void em28xx_ir_handle_key(struct em28xx_IR *ir) return; } -static void ir_timer(unsigned long data) -{ - struct em28xx_IR *ir = (struct em28xx_IR *)data; - - schedule_work(&ir->work); -} - #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20) static void em28xx_ir_work(void *data) #else @@ -314,28 +306,26 @@ static void em28xx_ir_work(struct work_struct *work) #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20) struct em28xx_IR *ir = data; #else - struct em28xx_IR *ir = container_of(work, struct em28xx_IR, work); + struct em28xx_IR *ir = container_of(work, struct em28xx_IR, work.work); #endif em28xx_ir_handle_key(ir); - mod_timer(&ir->timer, jiffies + msecs_to_jiffies(ir->polling)); + schedule_delayed_work(&ir->work, msecs_to_jiffies(ir->polling)); } static void em28xx_ir_start(struct em28xx_IR *ir) { - setup_timer(&ir->timer, ir_timer, (unsigned long)ir); #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20) - INIT_WORK(&ir->work, em28xx_ir_work, ir); + INIT_DELAYED_WORK(&ir->work, em28xx_ir_work, ir); #else - INIT_WORK(&ir->work, em28xx_ir_work); + INIT_DELAYED_WORK(&ir->work, em28xx_ir_work); #endif - schedule_work(&ir->work); + schedule_delayed_work(&ir->work, 0); } static void em28xx_ir_stop(struct em28xx_IR *ir) { - del_timer_sync(&ir->timer); - flush_scheduled_work(); + cancel_delayed_work_sync(&ir->work); } int em28xx_ir_init(struct em28xx *dev) -- cgit v1.2.3 From c698fbc627c51ba8ad0e434848499cb4412072da Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 7 Mar 2009 10:43:43 +0000 Subject: ir-kbd-i2c: Prevent general protection fault on rmmod From: Jean Delvare The removal of the timer which polls the infrared input is racy. Replacing the timer with a delayed work solves the problem. Signed-off-by: Jean Delvare Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/ir-kbd-i2c.c | 22 ++++++---------------- 1 file changed, 6 insertions(+), 16 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 a99aea49a..a0b78706d 100644 --- a/linux/drivers/media/video/ir-kbd-i2c.c +++ b/linux/drivers/media/video/ir-kbd-i2c.c @@ -280,12 +280,6 @@ static void ir_key_poll(struct IR_i2c *ir) } } -static void ir_timer(unsigned long data) -{ - struct IR_i2c *ir = (struct IR_i2c*)data; - schedule_work(&ir->work); -} - #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) static void ir_work(void *data) #else @@ -295,7 +289,7 @@ static void ir_work(struct work_struct *work) #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) struct IR_i2c *ir = data; #else - struct IR_i2c *ir = container_of(work, struct IR_i2c, work); + struct IR_i2c *ir = container_of(work, struct IR_i2c, work.work); #endif int polling_interval = 100; @@ -305,7 +299,7 @@ static void ir_work(struct work_struct *work) polling_interval = 50; ir_key_poll(ir); - mod_timer(&ir->timer, jiffies + msecs_to_jiffies(polling_interval)); + schedule_delayed_work(&ir->work, msecs_to_jiffies(polling_interval)); } /* ----------------------------------------------------------------------- */ @@ -462,14 +456,11 @@ static int ir_attach(struct i2c_adapter *adap, int addr, /* start polling via eventd */ #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) - INIT_WORK(&ir->work, ir_work, ir); + INIT_DELAYED_WORK(&ir->work, ir_work, ir); #else - INIT_WORK(&ir->work, ir_work); + INIT_DELAYED_WORK(&ir->work, ir_work); #endif - init_timer(&ir->timer); - ir->timer.function = ir_timer; - ir->timer.data = (unsigned long)ir; - schedule_work(&ir->work); + schedule_delayed_work(&ir->work, 0); return 0; @@ -486,8 +477,7 @@ static int ir_detach(struct i2c_client *client) struct IR_i2c *ir = i2c_get_clientdata(client); /* kill outstanding polls */ - del_timer_sync(&ir->timer); - flush_scheduled_work(); + cancel_delayed_work_sync(&ir->work); /* unregister devices */ input_unregister_device(ir->input); -- cgit v1.2.3 From 0bf47672d2ce934563d0287172c9dbf911e8a3b3 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 7 Mar 2009 10:44:12 +0000 Subject: saa6588: Prevent general protection fault on rmmod From: Jean Delvare The removal of the timer which polls the infrared input is racy. Replacing the timer with a delayed work solves the problem. Signed-off-by: Jean Delvare Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/saa6588.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/saa6588.c b/linux/drivers/media/video/saa6588.c index ae96de5fd..d89d70892 100644 --- a/linux/drivers/media/video/saa6588.c +++ b/linux/drivers/media/video/saa6588.c @@ -77,8 +77,7 @@ MODULE_LICENSE("GPL"); struct saa6588 { struct v4l2_subdev sd; - struct work_struct work; - struct timer_list timer; + struct delayed_work work; spinlock_t lock; unsigned char *buffer; unsigned int buf_size; @@ -323,13 +322,6 @@ static void saa6588_i2c_poll(struct saa6588 *s) wake_up_interruptible(&s->read_queue); } -static void saa6588_timer(unsigned long data) -{ - struct saa6588 *s = (struct saa6588 *)data; - - schedule_work(&s->work); -} - #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) static void saa6588_work(void *data) #else @@ -339,11 +331,11 @@ static void saa6588_work(struct work_struct *work) #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) struct saa6588 *s = (struct saa6588 *)data; #else - struct saa6588 *s = container_of(work, struct saa6588, work); + struct saa6588 *s = container_of(work, struct saa6588, work.work); #endif saa6588_i2c_poll(s); - mod_timer(&s->timer, jiffies + msecs_to_jiffies(20)); + schedule_delayed_work(&s->work, msecs_to_jiffies(20)); } static int saa6588_configure(struct saa6588 *s) @@ -500,14 +492,11 @@ static int saa6588_probe(struct i2c_client *client, /* start polling via eventd */ #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20) - INIT_WORK(&s->work, saa6588_work, s); + INIT_DELAYED_WORK(&s->work, saa6588_work, s); #else - INIT_WORK(&s->work, saa6588_work); + INIT_DELAYED_WORK(&s->work, saa6588_work); #endif - init_timer(&s->timer); - s->timer.function = saa6588_timer; - s->timer.data = (unsigned long)s; - schedule_work(&s->work); + schedule_delayed_work(&s->work, 0); return 0; } @@ -518,8 +507,7 @@ static int saa6588_remove(struct i2c_client *client) v4l2_device_unregister_subdev(sd); - del_timer_sync(&s->timer); - flush_scheduled_work(); + cancel_delayed_work_sync(&s->work); kfree(s->buffer); kfree(s); -- cgit v1.2.3 From f1ecc598eb4d5dcf96c771908ff51c48e734dde8 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 11 Mar 2009 07:57:43 -0300 Subject: Backout changeset, in favor of rev2 of the patch From: Mauro Carvalho Chehab Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/cx88/cx88-input.c | 25 +++++-------------------- 1 file changed, 5 insertions(+), 20 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/cx88/cx88-input.c b/linux/drivers/media/video/cx88/cx88-input.c index f247e5f45..dbb6ee2d9 100644 --- a/linux/drivers/media/video/cx88/cx88-input.c +++ b/linux/drivers/media/video/cx88/cx88-input.c @@ -49,12 +49,8 @@ struct cx88_IR { /* poll external decoder */ int polling; -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) struct work_struct work; struct timer_list timer; -#else - struct delayed_work work; -#endif u32 gpio_addr; u32 last_gpio; u32 mask_keycode; @@ -148,7 +144,6 @@ static void cx88_ir_handle_key(struct cx88_IR *ir) } } -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) static void ir_timer(unsigned long data) { struct cx88_IR *ir = (struct cx88_IR *)data; @@ -156,6 +151,7 @@ static void ir_timer(unsigned long data) schedule_work(&ir->work); } +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) static void cx88_ir_work(void *data) #else static void cx88_ir_work(struct work_struct *work) @@ -164,30 +160,23 @@ static void cx88_ir_work(struct work_struct *work) #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) struct cx88_IR *ir = data; #else - struct delayed_work *dwork = container_of(work, struct delayed_work, - work); - struct cx88_IR *ir = container_of(dwork, struct cx88_IR, work); + struct cx88_IR *ir = container_of(work, struct cx88_IR, work); #endif cx88_ir_handle_key(ir); -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) mod_timer(&ir->timer, jiffies + msecs_to_jiffies(ir->polling)); -#else - schedule_delayed_work(dwork, msecs_to_jiffies(ir->polling)); -#endif } void cx88_ir_start(struct cx88_core *core, struct cx88_IR *ir) { if (ir->polling) { -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) setup_timer(&ir->timer, ir_timer, (unsigned long)ir); +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) INIT_WORK(&ir->work, cx88_ir_work, ir); - schedule_work(&ir->work); #else - INIT_DELAYED_WORK(&ir->work, cx88_ir_work); - schedule_delayed_work(&ir->work, msecs_to_jiffies(ir->polling)); + INIT_WORK(&ir->work, cx88_ir_work); #endif + schedule_work(&ir->work); } if (ir->sampling) { core->pci_irqmask |= PCI_INT_IR_SMPINT; @@ -204,12 +193,8 @@ void cx88_ir_stop(struct cx88_core *core, struct cx88_IR *ir) } if (ir->polling) { -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) del_timer_sync(&ir->timer); flush_scheduled_work(); -#else - cancel_delayed_work_sync(&ir->work); -#endif } } -- cgit v1.2.3 From cc038d948545b0b6de0bb031f28afdf7968813b3 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 7 Mar 2009 10:42:12 +0000 Subject: cx88: Prevent general protection fault on rmmod From: Jean Delvare When unloading the cx8800 driver I sometimes get a general protection fault. Analysis revealed a race in cx88_ir_stop(). It can be solved by using a delayed work instead of a timer for infrared input polling. Signed-off-by: Jean Delvare Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/cx88/cx88-input.c | 27 ++++++++------------------- 1 file changed, 8 insertions(+), 19 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/cx88/cx88-input.c b/linux/drivers/media/video/cx88/cx88-input.c index dbb6ee2d9..8a2e631b7 100644 --- a/linux/drivers/media/video/cx88/cx88-input.c +++ b/linux/drivers/media/video/cx88/cx88-input.c @@ -49,8 +49,7 @@ struct cx88_IR { /* poll external decoder */ int polling; - struct work_struct work; - struct timer_list timer; + struct delayed_work work; u32 gpio_addr; u32 last_gpio; u32 mask_keycode; @@ -144,13 +143,6 @@ static void cx88_ir_handle_key(struct cx88_IR *ir) } } -static void ir_timer(unsigned long data) -{ - struct cx88_IR *ir = (struct cx88_IR *)data; - - schedule_work(&ir->work); -} - #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) static void cx88_ir_work(void *data) #else @@ -160,23 +152,22 @@ static void cx88_ir_work(struct work_struct *work) #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) struct cx88_IR *ir = data; #else - struct cx88_IR *ir = container_of(work, struct cx88_IR, work); + struct cx88_IR *ir = container_of(work, struct cx88_IR, work.work); #endif cx88_ir_handle_key(ir); - mod_timer(&ir->timer, jiffies + msecs_to_jiffies(ir->polling)); + schedule_delayed_work(&ir->work, msecs_to_jiffies(ir->polling)); } void cx88_ir_start(struct cx88_core *core, struct cx88_IR *ir) { if (ir->polling) { - setup_timer(&ir->timer, ir_timer, (unsigned long)ir); #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) - INIT_WORK(&ir->work, cx88_ir_work, ir); + INIT_DELAYED_WORK(&ir->work, cx88_ir_work, ir); #else - INIT_WORK(&ir->work, cx88_ir_work); + INIT_DELAYED_WORK(&ir->work, cx88_ir_work); #endif - schedule_work(&ir->work); + schedule_delayed_work(&ir->work, 0); } if (ir->sampling) { core->pci_irqmask |= PCI_INT_IR_SMPINT; @@ -192,10 +183,8 @@ void cx88_ir_stop(struct cx88_core *core, struct cx88_IR *ir) core->pci_irqmask &= ~PCI_INT_IR_SMPINT; } - if (ir->polling) { - del_timer_sync(&ir->timer); - flush_scheduled_work(); - } + if (ir->polling) + cancel_delayed_work_sync(&ir->work); } /* ---------------------------------------------------------------------- */ -- cgit v1.2.3 From cc21a58533c17e0392f27c1ade56ec09d2e037b3 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 11 Mar 2009 08:18:53 -0300 Subject: Conceptronic CTVFMI2 PCI Id From: Robert Millan My BTTV_BOARD_CONCEPTRONIC_CTVFMI2 card wasn't auto-detected, here's a patch that adds its PCI id. lspci -nnv output: 05:06.0 Multimedia video controller [0400]: Brooktree Corporation Bt878 Video Capture [109e:036e] (rev 11) 05:06.1 Multimedia controller [0480]: Brooktree Corporation Bt878 Audio Capture [109e:0878] (rev 11) Press within 3 seconds if this is wrong. Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/bt8xx/bttv-cards.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/bt8xx/bttv-cards.c b/linux/drivers/media/video/bt8xx/bttv-cards.c index 6868de9bd..57448806c 100644 --- a/linux/drivers/media/video/bt8xx/bttv-cards.c +++ b/linux/drivers/media/video/bt8xx/bttv-cards.c @@ -299,6 +299,8 @@ static struct CARD { /* Duplicate PCI ID, reconfigure for this board during the eeprom read. * { 0x13eb0070, BTTV_BOARD_HAUPPAUGE_IMPACTVCB, "Hauppauge ImpactVCB" }, */ + { 0x109e036e, BTTV_BOARD_CONCEPTRONIC_CTVFMI2, "Conceptronic CTVFMi v2"}, + /* DVB cards (using pci function .1 for mpeg data xfer) */ { 0x001c11bd, BTTV_BOARD_PINNACLESAT, "Pinnacle PCTV Sat" }, { 0x01010071, BTTV_BOARD_NEBULA_DIGITV, "Nebula Electronics DigiTV" }, -- cgit v1.2.3 From b787d6928f6fd204f12cdb534178682662ae8fc2 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 9 Mar 2009 23:16:00 +0000 Subject: pwc : fix LED and power setup for first open From: Martin Fuzzey Call pwc_construct before trying to talk to device to obtain vc interface so that LED and power setup works the first time the video device is opened. Signed-off-by: Martin Fuzzey Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/pwc/pwc-if.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/pwc/pwc-if.c b/linux/drivers/media/video/pwc/pwc-if.c index 49a918636..b3765e280 100644 --- a/linux/drivers/media/video/pwc/pwc-if.c +++ b/linux/drivers/media/video/pwc/pwc-if.c @@ -1133,6 +1133,7 @@ static int pwc_video_open(struct file *file) } mutex_lock(&pdev->modlock); + pwc_construct(pdev); /* set min/max sizes correct */ if (!pdev->usb_init) { PWC_DEBUG_OPEN("Doing first time initialization.\n"); pdev->usb_init = 1; @@ -1157,7 +1158,6 @@ static int pwc_video_open(struct file *file) if (pwc_set_leds(pdev, led_on, led_off) < 0) PWC_DEBUG_OPEN("Failed to set LED on/off time.\n"); - pwc_construct(pdev); /* set min/max sizes correct */ /* So far, so good. Allocate memory. */ i = pwc_allocate_buffers(pdev); -- cgit v1.2.3 From fc1ae637b4c1b67d383b2531d6185cf048967ee0 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 10 Mar 2009 08:14:00 +0000 Subject: radio-rtrack2: fix double mutex_unlock From: Alexey Klimov Patch fixes double mutex unlocking. Signed-off-by: Alexey Klimov Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/radio/radio-rtrack2.c | 1 - 1 file changed, 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/radio/radio-rtrack2.c b/linux/drivers/media/radio/radio-rtrack2.c index 93b3da04a..92fae4acd 100644 --- a/linux/drivers/media/radio/radio-rtrack2.c +++ b/linux/drivers/media/radio/radio-rtrack2.c @@ -61,7 +61,6 @@ static void rt_mute(struct rtrack2 *dev) mutex_lock(&dev->lock); outb(1, dev->io); mutex_unlock(&dev->lock); - mutex_unlock(&dev->lock); dev->muted = 1; } -- cgit v1.2.3 From 9f7a080438022fdabe299e8fc012720f048ecc25 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 2 Mar 2009 18:40:57 +0000 Subject: Auto-load videodev module when device opened. From: Scott James Remnant The videodev module is missing the char-major-81-* alias that would cause it to be auto-loaded when a device of that type is opened. This patch adds the alias. Signed-off-by: Scott James Remnant Signed-off-by: Tim Gardner Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/v4l2-dev.c | 1 + 1 file changed, 1 insertion(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/v4l2-dev.c b/linux/drivers/media/video/v4l2-dev.c index 861e3194f..110cde853 100644 --- a/linux/drivers/media/video/v4l2-dev.c +++ b/linux/drivers/media/video/v4l2-dev.c @@ -654,6 +654,7 @@ module_exit(videodev_exit) MODULE_AUTHOR("Alan Cox, Mauro Carvalho Chehab "); MODULE_DESCRIPTION("Device registrar for Video4Linux drivers v2"); MODULE_LICENSE("GPL"); +MODULE_ALIAS_CHARDEV_MAJOR(VIDEO_MAJOR); /* -- cgit v1.2.3 From c0230ad41429c84a819228694765a2f570ddfe38 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 3 Mar 2009 06:07:42 -0300 Subject: xc5000: prepare it to be used by cx231xx module From: Sri Deevi Signed-off-by: Srinivasa Deevi Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/common/tuners/xc5000.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/common/tuners/xc5000.c b/linux/drivers/media/common/tuners/xc5000.c index 36c81febb..dc534982e 100644 --- a/linux/drivers/media/common/tuners/xc5000.c +++ b/linux/drivers/media/common/tuners/xc5000.c @@ -758,7 +758,10 @@ static int xc5000_set_analog_params(struct dvb_frontend *fe, dprintk(1, "%s() frequency=%d (in units of 62.5khz)\n", __func__, params->frequency); - priv->rf_mode = XC_RF_MODE_CABLE; /* Fix me: it could be air. */ + priv->rf_mode = params->mode;// XC_RF_MODE_CABLE; /* Fix me: it could be air. */ + if(params->mode > XC_RF_MODE_CABLE) + priv->rf_mode = XC_RF_MODE_CABLE; + /* params->frequency is in units of 62.5khz */ priv->freq_hz = params->frequency * 62500; -- cgit v1.2.3 From 1d14933fa2543b8265c202adde0261caa6b2aee1 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 3 Mar 2009 14:35:41 -0300 Subject: xc5000: Fix CodingStyle errors introduced by the last patch From: Mauro Carvalho Chehab Signed-off-by: Mauro Carvalho Chehab --- 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 dc534982e..b0e20bc20 100644 --- a/linux/drivers/media/common/tuners/xc5000.c +++ b/linux/drivers/media/common/tuners/xc5000.c @@ -758,10 +758,10 @@ static int xc5000_set_analog_params(struct dvb_frontend *fe, dprintk(1, "%s() frequency=%d (in units of 62.5khz)\n", __func__, params->frequency); - priv->rf_mode = params->mode;// XC_RF_MODE_CABLE; /* Fix me: it could be air. */ - if(params->mode > XC_RF_MODE_CABLE) - priv->rf_mode = XC_RF_MODE_CABLE; - + /* Fix me: it could be air. */ + priv->rf_mode = params->mode; + if (params->mode > XC_RF_MODE_CABLE) + priv->rf_mode = XC_RF_MODE_CABLE; /* params->frequency is in units of 62.5khz */ priv->freq_hz = params->frequency * 62500; -- cgit v1.2.3 From 3db43fdd419efb4c5ab043895dd26b4fb8adf94f Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 3 Mar 2009 06:07:42 -0300 Subject: cx25840: prepare it to be used by cx231xx module From: Sri Deevi Signed-off-by: Srinivasa Deevi Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/cx25840/cx25840-audio.c | 44 ++++++-- linux/drivers/media/video/cx25840/cx25840-core.c | 121 +++++++++++++++++++-- linux/drivers/media/video/cx25840/cx25840-core.h | 1 + .../drivers/media/video/cx25840/cx25840-firmware.c | 11 +- 4 files changed, 156 insertions(+), 21 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/cx25840/cx25840-audio.c b/linux/drivers/media/video/cx25840/cx25840-audio.c index 3ee7d7a7d..b64430720 100644 --- a/linux/drivers/media/video/cx25840/cx25840-audio.c +++ b/linux/drivers/media/video/cx25840/cx25840-audio.c @@ -33,7 +33,7 @@ static int set_audclk_freq(struct i2c_client *client, u32 freq) /* common for all inputs and rates */ /* SA_MCLK_SEL=1, SA_MCLK_DIV=0x10 */ - if (!state->is_cx23885) + if (!state->is_cx23885 && !state->is_cx231xx) cx25840_write(client, 0x127, 0x50); if (state->aud_input != CX25840_AUDIO_SERIAL) { @@ -44,11 +44,15 @@ static int set_audclk_freq(struct i2c_client *client, u32 freq) * so avoid destroying registers. */ break; } - /* VID_PLL and AUX_PLL */ - cx25840_write4(client, 0x108, 0x1006040f); - /* AUX_PLL_FRAC */ - cx25840_write4(client, 0x110, 0x01bb39ee); + if (!state->is_cx231xx) { + + /* VID_PLL and AUX_PLL */ + cx25840_write4(client, 0x108, 0x1006040f); + + /* AUX_PLL_FRAC */ + cx25840_write4(client, 0x110, 0x01bb39ee); + } if (state->is_cx25836) break; @@ -65,11 +69,15 @@ static int set_audclk_freq(struct i2c_client *client, u32 freq) * so avoid destroying registers. */ break; } - /* VID_PLL and AUX_PLL */ - cx25840_write4(client, 0x108, 0x1009040f); - /* AUX_PLL_FRAC */ - cx25840_write4(client, 0x110, 0x00ec6bd6); + if (!state->is_cx231xx) { + + /* VID_PLL and AUX_PLL */ + cx25840_write4(client, 0x108, 0x1009040f); + + /* AUX_PLL_FRAC */ + cx25840_write4(client, 0x110, 0x00ec6bd6); + } if (state->is_cx25836) break; @@ -86,11 +94,15 @@ static int set_audclk_freq(struct i2c_client *client, u32 freq) * so avoid destroying registers. */ break; } + + if (!state->is_cx231xx) { + /* VID_PLL and AUX_PLL */ cx25840_write4(client, 0x108, 0x100a040f); /* AUX_PLL_FRAC */ cx25840_write4(client, 0x110, 0x0098d6e5); + } if (state->is_cx25836) break; @@ -109,11 +121,15 @@ static int set_audclk_freq(struct i2c_client *client, u32 freq) * so avoid destroying registers. */ break; } + + if (!state->is_cx231xx) { + /* VID_PLL and AUX_PLL */ cx25840_write4(client, 0x108, 0x1e08040f); /* AUX_PLL_FRAC */ cx25840_write4(client, 0x110, 0x012a0869); + } if (state->is_cx25836) break; @@ -137,11 +153,15 @@ static int set_audclk_freq(struct i2c_client *client, u32 freq) break; } + + if (!state->is_cx231xx) { + /* VID_PLL and AUX_PLL */ cx25840_write4(client, 0x108, 0x1809040f); /* AUX_PLL_FRAC */ cx25840_write4(client, 0x110, 0x00ec6bd6); + } if (state->is_cx25836) break; @@ -156,7 +176,7 @@ static int set_audclk_freq(struct i2c_client *client, u32 freq) break; case 48000: - if (!state->is_cx23885) { + if (!state->is_cx23885 && !state->is_cx231xx) { /* VID_PLL and AUX_PLL */ cx25840_write4(client, 0x108, 0x180a040f); @@ -167,7 +187,7 @@ static int set_audclk_freq(struct i2c_client *client, u32 freq) if (state->is_cx25836) break; - if (!state->is_cx23885) { + if (!state->is_cx23885 && !state->is_cx231xx) { /* src1_ctl */ cx25840_write4(client, 0x8f8, 0x08018000); @@ -228,7 +248,7 @@ void cx25840_audio_set_path(struct i2c_client *client) /* deassert soft reset */ cx25840_and_or(client, 0x810, ~0x1, 0x00); - if (state->is_cx23885) { + if (state->is_cx23885 || state->is_cx231xx) { /* Ensure the controller is running when we exit */ cx25840_and_or(client, 0x803, ~0x10, 0x10); } diff --git a/linux/drivers/media/video/cx25840/cx25840-core.c b/linux/drivers/media/video/cx25840/cx25840-core.c index 921cc96fc..d7797fa4a 100644 --- a/linux/drivers/media/video/cx25840/cx25840-core.c +++ b/linux/drivers/media/video/cx25840/cx25840-core.c @@ -367,6 +367,89 @@ static void cx23885_initialize(struct i2c_client *client) /* ----------------------------------------------------------------------- */ +static void cx231xx_initialize(struct i2c_client *client) +{ + DEFINE_WAIT(wait); + struct cx25840_state *state = to_state(i2c_get_clientdata(client)); + struct workqueue_struct *q; + + /* Internal Reset */ + cx25840_and_or(client, 0x102, ~0x01, 0x01); + cx25840_and_or(client, 0x102, ~0x01, 0x00); + + /* Stop microcontroller */ + cx25840_and_or(client, 0x803, ~0x10, 0x00); + + /* DIF in reset? */ + cx25840_write(client, 0x398, 0); + + /* Trust the default xtal, no division */ + /* This changes for the cx23888 products */ + cx25840_write(client, 0x2, 0x76); + + /* Bring down the regulator for AUX clk */ + cx25840_write(client, 0x1, 0x40); + + /* Disable DIF bypass */ + cx25840_write4(client, 0x33c, 0x00000001); + + /* DIF Src phase inc */ + cx25840_write4(client, 0x340, 0x0df7df83); + + + /* Luma */ + cx25840_write4(client, 0x414, 0x00107d12); + + /* Chroma */ + cx25840_write4(client, 0x420, 0x3d008282); + + + + /* ADC2 input select */ + cx25840_write(client, 0x102, 0x10); + + /* VIN1 & VIN5 */ + cx25840_write(client, 0x103, 0x11); + + /* Enable format auto detect */ + cx25840_write(client, 0x400, 0); +#if 0 + /* Force to NTSC-M and Disable autoconf regs */ + cx25840_write(client, 0x400, 0x21); +#endif + /* Fast subchroma lock */ + /* White crush, Chroma AGC & Chroma Killer enabled */ + cx25840_write(client, 0x401, 0xe8); + + + /* Do the firmware load in a work handler to prevent. + Otherwise the kernel is blocked waiting for the + bit-banging i2c interface to finish uploading the + firmware. */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 20) + INIT_WORK(&state->fw_work, cx25840_work_handler); +#else + INIT_WORK(&state->fw_work, cx25840_work_handler, state); +#endif + init_waitqueue_head(&state->fw_wait); + q = create_singlethread_workqueue("cx25840_fw"); + prepare_to_wait(&state->fw_wait, &wait, TASK_UNINTERRUPTIBLE); + queue_work(q, &state->fw_work); + schedule(); + finish_wait(&state->fw_wait, &wait); + destroy_workqueue(q); + + cx25840_std_setup(client); + + /* (re)set input */ + set_input(client, state->vid_input, state->aud_input); + + /* start microcontroller */ + cx25840_and_or(client, 0x803, ~0x10, 0x10); +} + +/* ----------------------------------------------------------------------- */ + void cx25840_std_setup(struct i2c_client *client) { struct cx25840_state *state = to_state(i2c_get_clientdata(client)); @@ -436,6 +519,7 @@ void cx25840_std_setup(struct i2c_client *client) } /* DEBUG: Displays configured PLL frequency */ + if (!state->is_cx231xx) { pll_int = cx25840_read(client, 0x108); pll_frac = cx25840_read4(client, 0x10c) & 0x1ffffff; pll_post = cx25840_read(client, 0x109); @@ -470,6 +554,7 @@ void cx25840_std_setup(struct i2c_client *client) hblank, hactive, vblank, vactive, vblank656, src_decimation, burst, luma_lpf, uv_lpf, comb, sc); } + } /* Sets horizontal blanking delay and active lines */ cx25840_write(client, 0x470, hblank); @@ -618,7 +703,7 @@ static int set_input(struct i2c_client *client, enum cx25840_video_input vid_inp * configuration in reg (for the cx23885) so we have no * need to attempt to flip bits for earlier av decoders. */ - if (!state->is_cx23885) { + if (!state->is_cx23885 && !state->is_cx231xx) { switch (aud_input) { case CX25840_AUDIO_SERIAL: /* do nothing, use serial audio input */ @@ -641,7 +726,7 @@ static int set_input(struct i2c_client *client, enum cx25840_video_input vid_inp /* Set INPUT_MODE to Composite (0) or S-Video (1) */ cx25840_and_or(client, 0x401, ~0x6, is_composite ? 0 : 0x02); - if (!state->is_cx23885) { + if (!state->is_cx23885 && !state->is_cx231xx) { /* Set CH_SEL_ADC2 to 1 if input comes from CH3 */ cx25840_and_or(client, 0x102, ~0x2, (reg & 0x80) == 0 ? 2 : 0); /* Set DUAL_MODE_ADC2 to 1 if input comes from both CH2&CH3 */ @@ -675,6 +760,19 @@ static int set_input(struct i2c_client *client, enum cx25840_video_input vid_inp /* I2S_IN_CTL: I2S_IN_SONY_MODE, LEFT SAMPLE on WS=1 */ cx25840_write(client, 0x914, 0xa0); + /* I2S_OUT_CTL: + * I2S_IN_SONY_MODE, LEFT SAMPLE on WS=1 + * I2S_OUT_MASTER_MODE = Master + */ + cx25840_write(client, 0x918, 0xa0); + cx25840_write(client, 0x919, 0x01); + } else if (state->is_cx231xx) { + /* Audio channel 1 src : Parallel 1 */ + cx25840_write(client, 0x124, 0x03); + + /* I2S_IN_CTL: I2S_IN_SONY_MODE, LEFT SAMPLE on WS=1 */ + cx25840_write(client, 0x914, 0xa0); + /* I2S_OUT_CTL: * I2S_IN_SONY_MODE, LEFT SAMPLE on WS=1 * I2S_OUT_MASTER_MODE = Master @@ -741,7 +839,7 @@ static int set_v4lstd(struct i2c_client *client) static int cx25840_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) { - struct cx25840_state *state = to_state(sd); + struct cx25840_state *state = to_state(sd); struct i2c_client *client = v4l2_get_subdevdata(sd); switch (ctrl->id) { @@ -808,7 +906,7 @@ static int cx25840_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) static int cx25840_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) { - struct cx25840_state *state = to_state(sd); + struct cx25840_state *state = to_state(sd); struct i2c_client *client = v4l2_get_subdevdata(sd); switch (ctrl->id) { @@ -1142,6 +1240,8 @@ static int cx25840_init(struct v4l2_subdev *sd, u32 val) cx25836_initialize(client); else if (state->is_cx23885) cx23885_initialize(client); + else if (state->is_cx231xx) + cx231xx_initialize(client); else cx25840_initialize(client); } @@ -1197,7 +1297,7 @@ static int cx25840_s_stream(struct v4l2_subdev *sd, int enable) v4l_dbg(1, cx25840_debug, client, "%s output\n", enable ? "enable" : "disable"); if (enable) { - if (state->is_cx23885) { + if (state->is_cx23885 || state->is_cx231xx) { u8 v = (cx25840_read(client, 0x421) | 0x0b); cx25840_write(client, 0x421, v); } else { @@ -1207,7 +1307,7 @@ static int cx25840_s_stream(struct v4l2_subdev *sd, int enable) state->is_cx25836 ? 0x04 : 0x07); } } else { - if (state->is_cx23885) { + if (state->is_cx23885 || state->is_cx231xx) { u8 v = cx25840_read(client, 0x421) & ~(0x0b); cx25840_write(client, 0x421, v); } else { @@ -1388,6 +1488,8 @@ static int cx25840_reset(struct v4l2_subdev *sd, u32 val) cx25836_initialize(client); else if (state->is_cx23885) cx23885_initialize(client); + else if (state->is_cx231xx) + cx231xx_initialize(client); else cx25840_initialize(client); return 0; @@ -1496,10 +1598,12 @@ static int cx25840_probe(struct i2c_client *client, } else if ((device_id & 0xff00) == 0x8400) { id = V4L2_IDENT_CX25840 + ((device_id >> 4) & 0xf); - } else if (device_id == 0x0000) { + } /* else if (device_id == 0x0000) { id = V4L2_IDENT_CX25836 + ((device_id >> 4) & 0xf) - 6; - } else if (device_id == 0x1313) { + } */ else if (device_id == 0x1313) { id = V4L2_IDENT_CX25836 + ((device_id >> 4) & 0xf) - 6; + } else if ((device_id & 0xfff0) == 0x5A30) { + id = V4L2_IDENT_CX25840 + ((device_id >> 4) & 0xf); } else { v4l_dbg(1, cx25840_debug, client, "cx25840 not found\n"); @@ -1522,6 +1626,7 @@ static int cx25840_probe(struct i2c_client *client, state->c = client; state->is_cx25836 = ((device_id & 0xff00) == 0x8300); state->is_cx23885 = (device_id == 0x0000) || (device_id == 0x1313); + state->is_cx231xx = (device_id == 0x5A3E); state->vid_input = CX25840_COMPOSITE7; state->aud_input = CX25840_AUDIO8; state->audclk_freq = 48000; diff --git a/linux/drivers/media/video/cx25840/cx25840-core.h b/linux/drivers/media/video/cx25840/cx25840-core.h index 0a99c19df..422c63752 100644 --- a/linux/drivers/media/video/cx25840/cx25840-core.h +++ b/linux/drivers/media/video/cx25840/cx25840-core.h @@ -51,6 +51,7 @@ struct cx25840_state { u32 rev; int is_cx25836; int is_cx23885; + int is_cx231xx; int is_initialized; wait_queue_head_t fw_wait; /* wake up when the fw load is finished */ struct work_struct fw_work; /* work entry for fw load */ diff --git a/linux/drivers/media/video/cx25840/cx25840-firmware.c b/linux/drivers/media/video/cx25840/cx25840-firmware.c index 01fbe174e..ff7a56388 100644 --- a/linux/drivers/media/video/cx25840/cx25840-firmware.c +++ b/linux/drivers/media/video/cx25840/cx25840-firmware.c @@ -26,6 +26,7 @@ #define FWFILE "v4l-cx25840.fw" #define FWFILE_CX23885 "v4l-cx23885-avcore-01.fw" +#define FWFILE_CX231XX "v4l-cx231xx-avcore-01.fw" /* * Mike Isely - The FWSEND parameter controls the @@ -97,9 +98,17 @@ int cx25840_loadfw(struct i2c_client *client) u8 buffer[FWSEND]; const u8 *ptr; int size, retval; + int MAX_BUF_SIZE = FWSEND; if (state->is_cx23885) firmware = FWFILE_CX23885; + else if ( state->is_cx231xx) + firmware = FWFILE_CX231XX; + + if( (state->is_cx231xx) && MAX_BUF_SIZE > 16) { + printk(" Firmware download size changed to 16 bytes max length\n"); + MAX_BUF_SIZE = 16; /* cx231xx cannot accept more than 16 bytes at a time */ + } if (request_firmware(&fw, firmware, FWDEV(client)) != 0) { v4l_err(client, "unable to open firmware %s\n", firmware); @@ -114,7 +123,7 @@ int cx25840_loadfw(struct i2c_client *client) size = fw->size; ptr = fw->data; while (size > 0) { - int len = min(FWSEND - 2, size); + int len = min(MAX_BUF_SIZE - 2, size); memcpy(buffer + 2, ptr, len); -- cgit v1.2.3 From 808f4f3fe30f79d2d30241edd25baa06acce836a Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 3 Mar 2009 14:36:55 -0300 Subject: cx25840: Fix CodingStyle errors introduced by the last patch From: Mauro Carvalho Chehab Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/cx25840/cx25840-audio.c | 42 +++++------- linux/drivers/media/video/cx25840/cx25840-core.c | 80 ++++++++++------------ .../drivers/media/video/cx25840/cx25840-firmware.c | 14 ++-- 3 files changed, 63 insertions(+), 73 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/cx25840/cx25840-audio.c b/linux/drivers/media/video/cx25840/cx25840-audio.c index b64430720..9dcdef03e 100644 --- a/linux/drivers/media/video/cx25840/cx25840-audio.c +++ b/linux/drivers/media/video/cx25840/cx25840-audio.c @@ -46,12 +46,11 @@ static int set_audclk_freq(struct i2c_client *client, u32 freq) } if (!state->is_cx231xx) { + /* VID_PLL and AUX_PLL */ + cx25840_write4(client, 0x108, 0x1006040f); - /* VID_PLL and AUX_PLL */ - cx25840_write4(client, 0x108, 0x1006040f); - - /* AUX_PLL_FRAC */ - cx25840_write4(client, 0x110, 0x01bb39ee); + /* AUX_PLL_FRAC */ + cx25840_write4(client, 0x110, 0x01bb39ee); } if (state->is_cx25836) @@ -71,7 +70,6 @@ static int set_audclk_freq(struct i2c_client *client, u32 freq) } if (!state->is_cx231xx) { - /* VID_PLL and AUX_PLL */ cx25840_write4(client, 0x108, 0x1009040f); @@ -96,12 +94,11 @@ static int set_audclk_freq(struct i2c_client *client, u32 freq) } if (!state->is_cx231xx) { + /* VID_PLL and AUX_PLL */ + cx25840_write4(client, 0x108, 0x100a040f); - /* VID_PLL and AUX_PLL */ - cx25840_write4(client, 0x108, 0x100a040f); - - /* AUX_PLL_FRAC */ - cx25840_write4(client, 0x110, 0x0098d6e5); + /* AUX_PLL_FRAC */ + cx25840_write4(client, 0x110, 0x0098d6e5); } if (state->is_cx25836) @@ -123,12 +120,11 @@ static int set_audclk_freq(struct i2c_client *client, u32 freq) } if (!state->is_cx231xx) { + /* VID_PLL and AUX_PLL */ + cx25840_write4(client, 0x108, 0x1e08040f); - /* VID_PLL and AUX_PLL */ - cx25840_write4(client, 0x108, 0x1e08040f); - - /* AUX_PLL_FRAC */ - cx25840_write4(client, 0x110, 0x012a0869); + /* AUX_PLL_FRAC */ + cx25840_write4(client, 0x110, 0x012a0869); } if (state->is_cx25836) @@ -155,12 +151,11 @@ static int set_audclk_freq(struct i2c_client *client, u32 freq) if (!state->is_cx231xx) { + /* VID_PLL and AUX_PLL */ + cx25840_write4(client, 0x108, 0x1809040f); - /* VID_PLL and AUX_PLL */ - cx25840_write4(client, 0x108, 0x1809040f); - - /* AUX_PLL_FRAC */ - cx25840_write4(client, 0x110, 0x00ec6bd6); + /* AUX_PLL_FRAC */ + cx25840_write4(client, 0x110, 0x00ec6bd6); } if (state->is_cx25836) @@ -248,10 +243,9 @@ void cx25840_audio_set_path(struct i2c_client *client) /* deassert soft reset */ cx25840_and_or(client, 0x810, ~0x1, 0x00); - if (state->is_cx23885 || state->is_cx231xx) { - /* Ensure the controller is running when we exit */ + /* Ensure the controller is running when we exit */ + if (state->is_cx23885 || state->is_cx231xx) cx25840_and_or(client, 0x803, ~0x10, 0x10); - } } static int get_volume(struct i2c_client *client) diff --git a/linux/drivers/media/video/cx25840/cx25840-core.c b/linux/drivers/media/video/cx25840/cx25840-core.c index d7797fa4a..b10f2bb8b 100644 --- a/linux/drivers/media/video/cx25840/cx25840-core.c +++ b/linux/drivers/media/video/cx25840/cx25840-core.c @@ -396,15 +396,12 @@ static void cx231xx_initialize(struct i2c_client *client) /* DIF Src phase inc */ cx25840_write4(client, 0x340, 0x0df7df83); - /* Luma */ cx25840_write4(client, 0x414, 0x00107d12); /* Chroma */ cx25840_write4(client, 0x420, 0x3d008282); - - /* ADC2 input select */ cx25840_write(client, 0x102, 0x10); @@ -421,7 +418,6 @@ static void cx231xx_initialize(struct i2c_client *client) /* White crush, Chroma AGC & Chroma Killer enabled */ cx25840_write(client, 0x401, 0xe8); - /* Do the firmware load in a work handler to prevent. Otherwise the kernel is blocked waiting for the bit-banging i2c interface to finish uploading the @@ -519,42 +515,42 @@ void cx25840_std_setup(struct i2c_client *client) } /* DEBUG: Displays configured PLL frequency */ - if (!state->is_cx231xx) { - pll_int = cx25840_read(client, 0x108); - pll_frac = cx25840_read4(client, 0x10c) & 0x1ffffff; - pll_post = cx25840_read(client, 0x109); - v4l_dbg(1, cx25840_debug, client, - "PLL regs = int: %u, frac: %u, post: %u\n", - pll_int, pll_frac, pll_post); - - if (pll_post) { - int fin, fsc; - int pll = (28636363L * ((((u64)pll_int) << 25L) + pll_frac)) >> 25L; - - pll /= pll_post; - v4l_dbg(1, cx25840_debug, client, "PLL = %d.%06d MHz\n", - pll / 1000000, pll % 1000000); - v4l_dbg(1, cx25840_debug, client, "PLL/8 = %d.%06d MHz\n", - pll / 8000000, (pll / 8) % 1000000); - - fin = ((u64)src_decimation * pll) >> 12; - v4l_dbg(1, cx25840_debug, client, - "ADC Sampling freq = %d.%06d MHz\n", - fin / 1000000, fin % 1000000); - - fsc = (((u64)sc) * pll) >> 24L; + if (!state->is_cx231xx) { + pll_int = cx25840_read(client, 0x108); + pll_frac = cx25840_read4(client, 0x10c) & 0x1ffffff; + pll_post = cx25840_read(client, 0x109); v4l_dbg(1, cx25840_debug, client, - "Chroma sub-carrier freq = %d.%06d MHz\n", - fsc / 1000000, fsc % 1000000); - - v4l_dbg(1, cx25840_debug, client, "hblank %i, hactive %i, " - "vblank %i, vactive %i, vblank656 %i, src_dec %i, " - "burst 0x%02x, luma_lpf %i, uv_lpf %i, comb 0x%02x, " - "sc 0x%06x\n", - hblank, hactive, vblank, vactive, vblank656, - src_decimation, burst, luma_lpf, uv_lpf, comb, sc); + "PLL regs = int: %u, frac: %u, post: %u\n", + pll_int, pll_frac, pll_post); + + if (pll_post) { + int fin, fsc; + int pll = (28636363L * ((((u64)pll_int) << 25L) + pll_frac)) >> 25L; + + pll /= pll_post; + v4l_dbg(1, cx25840_debug, client, "PLL = %d.%06d MHz\n", + pll / 1000000, pll % 1000000); + v4l_dbg(1, cx25840_debug, client, "PLL/8 = %d.%06d MHz\n", + pll / 8000000, (pll / 8) % 1000000); + + fin = ((u64)src_decimation * pll) >> 12; + v4l_dbg(1, cx25840_debug, client, + "ADC Sampling freq = %d.%06d MHz\n", + fin / 1000000, fin % 1000000); + + fsc = (((u64)sc) * pll) >> 24L; + v4l_dbg(1, cx25840_debug, client, + "Chroma sub-carrier freq = %d.%06d MHz\n", + fsc / 1000000, fsc % 1000000); + + v4l_dbg(1, cx25840_debug, client, "hblank %i, hactive %i, " + "vblank %i, vactive %i, vblank656 %i, src_dec %i, " + "burst 0x%02x, luma_lpf %i, uv_lpf %i, comb 0x%02x, " + "sc 0x%06x\n", + hblank, hactive, vblank, vactive, vblank656, + src_decimation, burst, luma_lpf, uv_lpf, comb, sc); + } } - } /* Sets horizontal blanking delay and active lines */ cx25840_write(client, 0x470, hblank); @@ -839,7 +835,7 @@ static int set_v4lstd(struct i2c_client *client) static int cx25840_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) { - struct cx25840_state *state = to_state(sd); + struct cx25840_state *state = to_state(sd); struct i2c_client *client = v4l2_get_subdevdata(sd); switch (ctrl->id) { @@ -906,7 +902,7 @@ static int cx25840_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) static int cx25840_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) { - struct cx25840_state *state = to_state(sd); + struct cx25840_state *state = to_state(sd); struct i2c_client *client = v4l2_get_subdevdata(sd); switch (ctrl->id) { @@ -1240,7 +1236,7 @@ static int cx25840_init(struct v4l2_subdev *sd, u32 val) cx25836_initialize(client); else if (state->is_cx23885) cx23885_initialize(client); - else if (state->is_cx231xx) + else if (state->is_cx231xx) cx231xx_initialize(client); else cx25840_initialize(client); @@ -1626,7 +1622,7 @@ static int cx25840_probe(struct i2c_client *client, state->c = client; state->is_cx25836 = ((device_id & 0xff00) == 0x8300); state->is_cx23885 = (device_id == 0x0000) || (device_id == 0x1313); - state->is_cx231xx = (device_id == 0x5A3E); + state->is_cx231xx = (device_id == 0x5a3e); state->vid_input = CX25840_COMPOSITE7; state->aud_input = CX25840_AUDIO8; state->audclk_freq = 48000; diff --git a/linux/drivers/media/video/cx25840/cx25840-firmware.c b/linux/drivers/media/video/cx25840/cx25840-firmware.c index ff7a56388..f01456ec4 100644 --- a/linux/drivers/media/video/cx25840/cx25840-firmware.c +++ b/linux/drivers/media/video/cx25840/cx25840-firmware.c @@ -98,17 +98,17 @@ int cx25840_loadfw(struct i2c_client *client) u8 buffer[FWSEND]; const u8 *ptr; int size, retval; - int MAX_BUF_SIZE = FWSEND; + int MAX_BUF_SIZE = FWSEND; if (state->is_cx23885) firmware = FWFILE_CX23885; - else if ( state->is_cx231xx) - firmware = FWFILE_CX231XX; + else if (state->is_cx231xx) + firmware = FWFILE_CX231XX; - if( (state->is_cx231xx) && MAX_BUF_SIZE > 16) { - printk(" Firmware download size changed to 16 bytes max length\n"); - MAX_BUF_SIZE = 16; /* cx231xx cannot accept more than 16 bytes at a time */ - } + if ((state->is_cx231xx) && MAX_BUF_SIZE > 16) { + v4l_err(client, " Firmware download size changed to 16 bytes max length\n"); + MAX_BUF_SIZE = 16; /* cx231xx cannot accept more than 16 bytes at a time */ + } if (request_firmware(&fw, firmware, FWDEV(client)) != 0) { v4l_err(client, "unable to open firmware %s\n", firmware); -- cgit v1.2.3 From c33556713c14419683e262c03a7280f8d9fb88bd Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 3 Mar 2009 14:37:50 -0300 Subject: Add cx231xx USB driver From: Sri Deevi Signed-off-by: Srinivasa Deevi Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/Kconfig | 2 + linux/drivers/media/video/Makefile | 1 + linux/drivers/media/video/cx231xx/Kconfig | 35 + linux/drivers/media/video/cx231xx/Makefile | 15 + linux/drivers/media/video/cx231xx/cx231xx-audio.c | 664 ++++++ linux/drivers/media/video/cx231xx/cx231xx-avcore.c | 2289 ++++++++++++++++++ linux/drivers/media/video/cx231xx/cx231xx-cards.c | 947 ++++++++ .../drivers/media/video/cx231xx/cx231xx-conf-reg.h | 491 ++++ linux/drivers/media/video/cx231xx/cx231xx-core.c | 1197 ++++++++++ linux/drivers/media/video/cx231xx/cx231xx-dvb.c | 566 +++++ linux/drivers/media/video/cx231xx/cx231xx-i2c.c | 580 +++++ linux/drivers/media/video/cx231xx/cx231xx-input.c | 267 +++ linux/drivers/media/video/cx231xx/cx231xx-reg.h | 1574 +++++++++++++ linux/drivers/media/video/cx231xx/cx231xx-vbi.c | 697 ++++++ linux/drivers/media/video/cx231xx/cx231xx-vbi.h | 61 + linux/drivers/media/video/cx231xx/cx231xx-video.c | 2440 ++++++++++++++++++++ linux/drivers/media/video/cx231xx/cx231xx.h | 771 +++++++ 17 files changed, 12597 insertions(+) create mode 100644 linux/drivers/media/video/cx231xx/Kconfig create mode 100644 linux/drivers/media/video/cx231xx/Makefile create mode 100644 linux/drivers/media/video/cx231xx/cx231xx-audio.c create mode 100644 linux/drivers/media/video/cx231xx/cx231xx-avcore.c create mode 100644 linux/drivers/media/video/cx231xx/cx231xx-cards.c create mode 100644 linux/drivers/media/video/cx231xx/cx231xx-conf-reg.h create mode 100644 linux/drivers/media/video/cx231xx/cx231xx-core.c create mode 100644 linux/drivers/media/video/cx231xx/cx231xx-dvb.c create mode 100644 linux/drivers/media/video/cx231xx/cx231xx-i2c.c create mode 100644 linux/drivers/media/video/cx231xx/cx231xx-input.c create mode 100644 linux/drivers/media/video/cx231xx/cx231xx-reg.h create mode 100644 linux/drivers/media/video/cx231xx/cx231xx-vbi.c create mode 100644 linux/drivers/media/video/cx231xx/cx231xx-vbi.h create mode 100644 linux/drivers/media/video/cx231xx/cx231xx-video.c create mode 100644 linux/drivers/media/video/cx231xx/cx231xx.h (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/Kconfig b/linux/drivers/media/video/Kconfig index 534a022c4..27f639763 100644 --- a/linux/drivers/media/video/Kconfig +++ b/linux/drivers/media/video/Kconfig @@ -805,6 +805,8 @@ source "drivers/media/video/pvrusb2/Kconfig" source "drivers/media/video/em28xx/Kconfig" +source "drivers/media/video/cx231xx/Kconfig" + source "drivers/media/video/usbvision/Kconfig" source "drivers/media/video/usbvideo/Kconfig" diff --git a/linux/drivers/media/video/Makefile b/linux/drivers/media/video/Makefile index 08a0675fe..99b448e6c 100644 --- a/linux/drivers/media/video/Makefile +++ b/linux/drivers/media/video/Makefile @@ -67,6 +67,7 @@ obj-$(CONFIG_VIDEO_MEYE) += meye.o obj-$(CONFIG_VIDEO_SAA7134) += saa7134/ obj-$(CONFIG_VIDEO_CX88) += cx88/ obj-$(CONFIG_VIDEO_EM28XX) += em28xx/ +obj-$(CONFIG_VIDEO_CX231XX) += cx231xx/ obj-$(CONFIG_VIDEO_USBVISION) += usbvision/ obj-$(CONFIG_VIDEO_TVP5150) += tvp5150.o obj-$(CONFIG_VIDEO_TVP514X) += tvp514x.o diff --git a/linux/drivers/media/video/cx231xx/Kconfig b/linux/drivers/media/video/cx231xx/Kconfig new file mode 100644 index 000000000..f39d26924 --- /dev/null +++ b/linux/drivers/media/video/cx231xx/Kconfig @@ -0,0 +1,35 @@ +config VIDEO_CX231XX + tristate "Conexant cx231xx USB video capture support" + depends on VIDEO_DEV && I2C && INPUT + select VIDEO_TUNER + select VIDEO_TVEEPROM + select VIDEO_IR + select VIDEOBUF_VMALLOC + select VIDEO_CX25840 + select VIDEO_CX231XX_ALSA + + ---help--- + This is a video4linux driver for Conexant 231xx USB based TV cards. + + To compile this driver as a module, choose M here: the + module will be called cx231xx + +config VIDEO_CX231XX_ALSA + tristate "Conexant Cx231xx ALSA audio module" + depends on VIDEO_CX231XX && SND + select SND_PCM + + ---help--- + This is an ALSA driver for Cx231xx USB based TV cards. + + To compile this driver as a module, choose M here: the + module will be called cx231xx-alsa + +config VIDEO_CX231XX_DVB + tristate "DVB/ATSC Support for Cx231xx based TV cards" + depends on VIDEO_CX231XX && DVB_CORE + select VIDEOBUF_DVB + select MEDIA_TUNER_XC5000 if !DVB_FE_CUSTOMIZE + ---help--- + This adds support for DVB cards based on the + Conexant cx231xx chips. diff --git a/linux/drivers/media/video/cx231xx/Makefile b/linux/drivers/media/video/cx231xx/Makefile new file mode 100644 index 000000000..2590a09f3 --- /dev/null +++ b/linux/drivers/media/video/cx231xx/Makefile @@ -0,0 +1,15 @@ +cx231xx-objs := cx231xx-video.o cx231xx-i2c.o cx231xx-cards.o cx231xx-core.o \ + cx231xx-avcore.o cx231xx-pcb-config.o cx231xx-vbi.o + +cx231xx-alsa-objs := cx231xx-audio.o + + +obj-$(CONFIG_VIDEO_CX231XX) += cx231xx.o +obj-$(CONFIG_VIDEO_CX231XX_ALSA) += cx231xx-alsa.o +obj-$(CONFIG_VIDEO_CX231XX_DVB) += cx231xx-dvb.o + +EXTRA_CFLAGS += -Idrivers/media/video +EXTRA_CFLAGS += -Idrivers/media/common/tuners +EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core +EXTRA_CFLAGS += -Idrivers/media/dvb/frontends + diff --git a/linux/drivers/media/video/cx231xx/cx231xx-audio.c b/linux/drivers/media/video/cx231xx/cx231xx-audio.c new file mode 100644 index 000000000..add97c701 --- /dev/null +++ b/linux/drivers/media/video/cx231xx/cx231xx-audio.c @@ -0,0 +1,664 @@ +/* + * Conexant Cx231xx audio extension + * + * Copyright (C) 2008 + * Based on em28xx driver + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "compat.h" +#include +#include +#include +#include +#include +#include +#include +#include "cx231xx.h" +#include "cx231xx-pcb-config.h" + +static int debug; +module_param(debug, int, 0644); +MODULE_PARM_DESC(debug, "activates debug info"); + +#define dprintk(fmt, arg...) do { \ + if (debug) \ + printk(KERN_INFO "cx231xx-audio %s: " fmt, \ + __func__, ##arg); \ + } while (0) + +static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; + +static int cx231xx_isoc_audio_deinit(struct cx231xx *dev) +{ + int i; + + dprintk("Stopping isoc\n"); + + + for (i = 0; i < CX231XX_AUDIO_BUFS; i++) { + if(dev->adev.urb[i]) { + if (!irqs_disabled()) + usb_kill_urb(dev->adev.urb[i]); + else + usb_unlink_urb(dev->adev.urb[i]); + + usb_free_urb(dev->adev.urb[i]); + dev->adev.urb[i] = NULL; + + kfree(dev->adev.transfer_buffer[i]); + dev->adev.transfer_buffer[i] = NULL; + + } + } + + return 0; +} + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19) +static void cx231xx_audio_isocirq(struct urb *urb, struct pt_regs *regs) +#else +static void cx231xx_audio_isocirq(struct urb *urb) +#endif +{ + struct cx231xx *dev = urb->context; + int i; + unsigned int oldptr; +#ifdef NO_PCM_LOCK + unsigned long flags; +#endif + int period_elapsed = 0; + int status; + unsigned char *cp; + unsigned int stride; +#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 16) + snd_pcm_substream_t *substream; + snd_pcm_runtime_t *runtime; +#else + struct snd_pcm_substream *substream; + struct snd_pcm_runtime *runtime; +#endif + + switch (urb->status) { + case 0: /* success */ + case -ETIMEDOUT: /* NAK */ + break; + case -ECONNRESET: /* kill */ + case -ENOENT: + case -ESHUTDOWN: + return; + default: /* error */ + dprintk("urb completition error %d.\n", urb->status); + break; + } + + if (dev->adev.capture_pcm_substream) { + substream = dev->adev.capture_pcm_substream; + runtime = substream->runtime; + stride = runtime->frame_bits >> 3; + + for (i = 0; i < urb->number_of_packets; i++) { + int length = + urb->iso_frame_desc[i].actual_length / stride; + cp = (unsigned char *)urb->transfer_buffer + + urb->iso_frame_desc[i].offset; + + if (!length) + continue; + +#ifdef NO_PCM_LOCK + spin_lock_irqsave(&dev->adev.slock, flags); +#endif + oldptr = dev->adev.hwptr_done_capture; + if (oldptr + length >= runtime->buffer_size) { + unsigned int cnt = + runtime->buffer_size - oldptr; + memcpy(runtime->dma_area + oldptr * stride, cp, + cnt * stride); + memcpy(runtime->dma_area, cp + cnt * stride, + length * stride - cnt * stride); + } else { + memcpy(runtime->dma_area + oldptr * stride, cp, + length * stride); + } + +#ifndef NO_PCM_LOCK + snd_pcm_stream_lock(substream); +#endif + + dev->adev.hwptr_done_capture += length; + if (dev->adev.hwptr_done_capture >= + runtime->buffer_size) + dev->adev.hwptr_done_capture -= + runtime->buffer_size; + + dev->adev.capture_transfer_done += length; + if (dev->adev.capture_transfer_done >= + runtime->period_size) { + dev->adev.capture_transfer_done -= + runtime->period_size; + period_elapsed = 1; + } + +#ifdef NO_PCM_LOCK + spin_unlock_irqrestore(&dev->adev.slock, flags); +#else + snd_pcm_stream_unlock(substream); +#endif + } + if (period_elapsed) + snd_pcm_period_elapsed(substream); + } + urb->status = 0; + + status = usb_submit_urb(urb, GFP_ATOMIC); + if (status < 0) { + cx231xx_errdev("resubmit of audio urb failed (error=%i)\n", + status); + } + return; +} + +static int cx231xx_init_audio_isoc(struct cx231xx *dev) +{ + int i, errCode; + int sb_size; + + cx231xx_info("%s: Starting AUDIO transfers\n",__func__); + + sb_size = CX231XX_NUM_AUDIO_PACKETS * dev->adev.max_pkt_size; + + for (i = 0; i < CX231XX_AUDIO_BUFS; i++) { + struct urb *urb; + int j, k; + + dev->adev.transfer_buffer[i] = kmalloc(sb_size, GFP_ATOMIC); + if (!dev->adev.transfer_buffer[i]) + return -ENOMEM; + + memset(dev->adev.transfer_buffer[i], 0x80, sb_size); + urb = usb_alloc_urb(CX231XX_NUM_AUDIO_PACKETS, GFP_ATOMIC); + if (!urb) { + cx231xx_errdev("usb_alloc_urb failed!\n"); + for (j = 0; j < i; j++) { + usb_free_urb(dev->adev.urb[j]); + kfree(dev->adev.transfer_buffer[j]); + } + return -ENOMEM; + } + + urb->dev = dev->udev; + urb->context = dev; + urb->pipe = usb_rcvisocpipe(dev->udev, dev->adev.end_point_addr); + urb->transfer_flags = URB_ISO_ASAP; + urb->transfer_buffer = dev->adev.transfer_buffer[i]; + urb->interval = 1; + urb->complete = cx231xx_audio_isocirq; + urb->number_of_packets = CX231XX_NUM_AUDIO_PACKETS; + urb->transfer_buffer_length = sb_size; + + for (j = k = 0; j < CX231XX_NUM_AUDIO_PACKETS; + j++, k += dev->adev.max_pkt_size) { + urb->iso_frame_desc[j].offset = k; + urb->iso_frame_desc[j].length = + dev->adev.max_pkt_size; + } + dev->adev.urb[i] = urb; + } + + for (i = 0; i < CX231XX_AUDIO_BUFS; i++) { + errCode = usb_submit_urb(dev->adev.urb[i], GFP_ATOMIC); + if (errCode < 0) { + cx231xx_isoc_audio_deinit(dev); + return errCode; + } + } + + return errCode; +} + +static int cx231xx_cmd(struct cx231xx *dev, int cmd, int arg) +{ + dprintk("%s transfer\n", (dev->adev.capture_stream == STREAM_ON)? + "stop" : "start"); + + switch (cmd) { + case CX231XX_CAPTURE_STREAM_EN: + if (dev->adev.capture_stream == STREAM_OFF && arg == 1) { + dev->adev.capture_stream = STREAM_ON; + cx231xx_init_audio_isoc(dev); + } else if (dev->adev.capture_stream == STREAM_ON && arg == 0) { + dev->adev.capture_stream = STREAM_OFF; + cx231xx_isoc_audio_deinit(dev); + } else { + cx231xx_errdev( "An underrun very likely occurred. " + "Ignoring it.\n"); + } + return 0; + default: + return -EINVAL; + } +} + +#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 16) +static int snd_pcm_alloc_vmalloc_buffer(snd_pcm_substream_t *subs, + size_t size) +#else +static int snd_pcm_alloc_vmalloc_buffer(struct snd_pcm_substream *subs, + size_t size) +#endif +{ +#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 16) + snd_pcm_runtime_t *runtime = subs->runtime; +#else + struct snd_pcm_runtime *runtime = subs->runtime; +#endif + + dprintk("Allocating vbuffer\n"); + if (runtime->dma_area) { + if (runtime->dma_bytes > size) + return 0; + + vfree(runtime->dma_area); + } + runtime->dma_area = vmalloc(size); + if (!runtime->dma_area) + return -ENOMEM; + + runtime->dma_bytes = size; + + return 0; +} + +#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 16) +static snd_pcm_hardware_t snd_cx231xx_hw_capture = { +#else +static struct snd_pcm_hardware snd_cx231xx_hw_capture = { +#endif + .info = SNDRV_PCM_INFO_BLOCK_TRANSFER | + SNDRV_PCM_INFO_MMAP | + SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_MMAP_VALID, + + .formats = SNDRV_PCM_FMTBIT_S16_LE, + + .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_KNOT, + + .rate_min = 48000, + .rate_max = 48000, + .channels_min = 2, + .channels_max = 2, + .buffer_bytes_max = 62720 * 8, /* just about the value in usbaudio.c */ + .period_bytes_min = 64, /* 12544/2, */ + .period_bytes_max = 12544, + .periods_min = 2, + .periods_max = 98, /* 12544, */ +}; + +#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 16) +static int snd_cx231xx_capture_open(snd_pcm_substream_t *substream) +#else +static int snd_cx231xx_capture_open(struct snd_pcm_substream *substream) +#endif +{ + struct cx231xx *dev = snd_pcm_substream_chip(substream); +#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 16) + snd_pcm_runtime_t *runtime = substream->runtime; +#else + struct snd_pcm_runtime *runtime = substream->runtime; +#endif + int ret = 0; + + dprintk("opening device and trying to acquire exclusive lock\n"); + + if (!dev) { + cx231xx_errdev("BUG: cx231xx can't find device struct." + " Can't proceed with open\n"); + return -ENODEV; + } + + /* Sets volume, mute, etc */ + dev->mute = 0; + + /* set alternate setting for audio interface */ + ret = cx231xx_set_alt_setting(dev, INDEX_AUDIO, 1); /* 1 - 48000 samples per sec */ + if (ret < 0) { + cx231xx_errdev("failed to set alternate setting !\n"); + + return ret; + } + + /* inform hardware to start streaming */ + ret = cx231xx_capture_start(dev, 1, Audio); + + runtime->hw = snd_cx231xx_hw_capture; + + mutex_lock(&dev->lock); + dev->adev.users++; + mutex_unlock(&dev->lock); + + snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS); + dev->adev.capture_pcm_substream = substream; + runtime->private_data = dev; + + return 0; +} + +#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 16) +static int snd_cx231xx_pcm_close(snd_pcm_substream_t *substream) +#else +static int snd_cx231xx_pcm_close(struct snd_pcm_substream *substream) +#endif +{ + int ret; + struct cx231xx *dev = snd_pcm_substream_chip(substream); + + + dprintk("closing device\n"); + + /* set alternate setting for audio interface */ + ret = cx231xx_set_alt_setting(dev, INDEX_AUDIO, 0); /* 1 - 48000 samples per sec */ + if (ret < 0) { + cx231xx_errdev("failed to set alternate setting !\n"); + + return ret; + } + + /* inform hardware to start streaming */ + ret = cx231xx_capture_start(dev, 0, Audio); + + dev->mute = 1; + mutex_lock(&dev->lock); + dev->adev.users--; + mutex_unlock(&dev->lock); + + if (dev->adev.users == 0 && dev->adev.shutdown == 1) { + dprintk("audio users: %d\n", dev->adev.users); + dprintk("disabling audio stream!\n"); + dev->adev.shutdown = 0; + dprintk("released lock\n"); + cx231xx_cmd(dev, CX231XX_CAPTURE_STREAM_EN, 0); + } + return 0; +} + +#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 16) +static int snd_cx231xx_hw_capture_params(snd_pcm_substream_t *substream, + snd_pcm_hw_params_t *hw_params) +#else +static int snd_cx231xx_hw_capture_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *hw_params) +#endif +{ + unsigned int channels, rate, format; + int ret; + + dprintk("Setting capture parameters\n"); + + ret = snd_pcm_alloc_vmalloc_buffer(substream, + params_buffer_bytes(hw_params)); + format = params_format(hw_params); + rate = params_rate(hw_params); + channels = params_channels(hw_params); + + /* TODO: set up cx231xx audio chip to deliver the correct audio format, + current default is 48000hz multiplexed => 96000hz mono + which shouldn't matter since analogue TV only supports mono */ + return 0; +} + +#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 16) +static int snd_cx231xx_hw_capture_free(snd_pcm_substream_t *substream) +#else +static int snd_cx231xx_hw_capture_free(struct snd_pcm_substream *substream) +#endif +{ + struct cx231xx *dev = snd_pcm_substream_chip(substream); + + dprintk("Stop capture, if needed\n"); + + if (dev->adev.capture_stream == STREAM_ON) + cx231xx_cmd(dev, CX231XX_CAPTURE_STREAM_EN, CX231XX_STOP_AUDIO); + + return 0; +} + +#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 16) +static int snd_cx231xx_prepare(snd_pcm_substream_t *substream) +#else +static int snd_cx231xx_prepare(struct snd_pcm_substream *substream) +#endif +{ + return 0; +} + +#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 16) +static int snd_cx231xx_capture_trigger(snd_pcm_substream_t *substream, int cmd) +#else +static int snd_cx231xx_capture_trigger(struct snd_pcm_substream *substream, + int cmd) +#endif +{ + struct cx231xx *dev = snd_pcm_substream_chip(substream); + int retval; + + + dprintk("Should %s capture\n", (cmd == SNDRV_PCM_TRIGGER_START)? + "start": "stop"); + + spin_lock(&dev->adev.slock); + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + cx231xx_cmd(dev, CX231XX_CAPTURE_STREAM_EN, CX231XX_START_AUDIO); + retval = 0; + break; + case SNDRV_PCM_TRIGGER_STOP: + cx231xx_cmd(dev, CX231XX_CAPTURE_STREAM_EN, CX231XX_STOP_AUDIO); + retval = 0; + break; + default: + retval = -EINVAL; + } + + spin_unlock(&dev->adev.slock); + return retval; +} + +#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 16) +static snd_pcm_uframes_t snd_cx231xx_capture_pointer(snd_pcm_substream_t + *substream) +#else +static snd_pcm_uframes_t snd_cx231xx_capture_pointer(struct snd_pcm_substream + *substream) +#endif +{ + struct cx231xx *dev; + unsigned long flags; + snd_pcm_uframes_t hwptr_done; + + dev = snd_pcm_substream_chip(substream); + + spin_lock_irqsave(&dev->adev.slock, flags); + hwptr_done = dev->adev.hwptr_done_capture; + spin_unlock_irqrestore(&dev->adev.slock, flags); + + return hwptr_done; +} + +#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 16) +static struct page *snd_pcm_get_vmalloc_page(snd_pcm_substream_t *subs, + unsigned long offset) +#else +static struct page *snd_pcm_get_vmalloc_page(struct snd_pcm_substream *subs, + unsigned long offset) +#endif +{ + void *pageptr = subs->runtime->dma_area + offset; + + return vmalloc_to_page(pageptr); +} + +#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 16) +static snd_pcm_ops_t snd_cx231xx_pcm_capture = { +#else +static struct snd_pcm_ops snd_cx231xx_pcm_capture = { +#endif + .open = snd_cx231xx_capture_open, + .close = snd_cx231xx_pcm_close, + .ioctl = snd_pcm_lib_ioctl, + .hw_params = snd_cx231xx_hw_capture_params, + .hw_free = snd_cx231xx_hw_capture_free, + .prepare = snd_cx231xx_prepare, + .trigger = snd_cx231xx_capture_trigger, + .pointer = snd_cx231xx_capture_pointer, + .page = snd_pcm_get_vmalloc_page, +}; + +static int cx231xx_audio_init(struct cx231xx *dev) +{ + struct cx231xx_audio *adev = &dev->adev; +#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 16) + snd_pcm_t *pcm; + snd_card_t *card; +#else + struct snd_pcm *pcm; + struct snd_card *card; +#endif + static int devnr; + int err; + struct usb_interface *uif; + int i, isoc_pipe = 0; + + if (dev->has_alsa_audio != 1) { + /* This device does not support the extension (in this case + the device is expecting the snd-usb-audio module or + doesn't have analog audio support at all) */ + return 0; + } + + cx231xx_info("cx231xx-audio.c: probing for cx231xx " + "non standard usbaudio\n"); + + card = snd_card_new(index[devnr], "Cx231xx Audio", THIS_MODULE, 0); + if (card == NULL) { + return -ENOMEM; + } + + spin_lock_init(&adev->slock); + err = snd_pcm_new(card, "Cx231xx Audio", 0, 0, 1, &pcm); + if (err < 0) { + snd_card_free(card); + return err; + } + + snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_cx231xx_pcm_capture); + pcm->info_flags = 0; + pcm->private_data = dev; + strcpy(pcm->name, "Conexant cx231xx Capture"); + strcpy(card->driver, "Conexant cx231xx Audio"); + strcpy(card->shortname, "Cx231xx Audio"); + strcpy(card->longname, "Conexant cx231xx Audio"); + + err = snd_card_register(card); + if (err < 0) { + snd_card_free(card); + return err; + } + adev->sndcard = card; + adev->udev = dev->udev; + + /* compute alternate max packet sizes for Audio */ + uif = dev->udev->actconfig->interface[dev->current_pcb_config.hs_config_info[0].interface_info.audio_index+1]; + + adev->end_point_addr = le16_to_cpu(uif->altsetting[0].endpoint[isoc_pipe].desc.bEndpointAddress); + + adev->num_alt = uif->num_altsetting; + cx231xx_info(": EndPoint Addr 0x%x, Alternate settings: %i\n", adev->end_point_addr, + adev->num_alt); + adev->alt_max_pkt_size = kmalloc(32 * adev->num_alt, GFP_KERNEL); + + if (adev->alt_max_pkt_size == NULL) { + cx231xx_errdev("out of memory!\n"); + return -ENOMEM; + } + + for (i = 0; i < adev->num_alt ; i++) { + u16 tmp = le16_to_cpu(uif->altsetting[i].endpoint[isoc_pipe].desc. + wMaxPacketSize); + adev->alt_max_pkt_size[i] = + (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1); + cx231xx_info("Alternate setting %i, max size= %i\n", i, + adev->alt_max_pkt_size[i]); + } + + return 0; +} + +static int cx231xx_audio_fini(struct cx231xx *dev) +{ + if (dev == NULL) + return 0; + + if (dev->has_alsa_audio != 1) { + /* This device does not support the extension (in this case + the device is expecting the snd-usb-audio module or + doesn't have analog audio support at all) */ + return 0; + } + + if (dev->adev.sndcard) { + snd_card_free(dev->adev.sndcard); + kfree(dev->adev.alt_max_pkt_size); + dev->adev.sndcard = NULL; + } + + return 0; +} + +static struct cx231xx_ops audio_ops = { + .id = CX231XX_AUDIO, + .name = "Cx231xx Audio Extension", + .init = cx231xx_audio_init, + .fini = cx231xx_audio_fini, +}; + +static int __init cx231xx_alsa_register(void) +{ + return cx231xx_register_extension(&audio_ops); +} + +static void __exit cx231xx_alsa_unregister(void) +{ + cx231xx_unregister_extension(&audio_ops); +} + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Srinivasa Deevi "); +MODULE_DESCRIPTION("Cx231xx Audio driver"); + +module_init(cx231xx_alsa_register); +module_exit(cx231xx_alsa_unregister); diff --git a/linux/drivers/media/video/cx231xx/cx231xx-avcore.c b/linux/drivers/media/video/cx231xx/cx231xx-avcore.c new file mode 100644 index 000000000..833967f46 --- /dev/null +++ b/linux/drivers/media/video/cx231xx/cx231xx-avcore.c @@ -0,0 +1,2289 @@ +/* + cx231xx_avcore.c - driver for Conexant Cx23100/101/102 USB video capture devices + + Copyright (C) 2008 + + This program contains the specific code to control the avdecoder chip and + other related usb control functions for cx231xx based chipset. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "cx231xx.h" + + +/************************************************************************************* + * C O L I B R I - B L O C K C O N T R O L functions * + *************************************************************************************/ +int cx231xx_colibri_init_super_block(struct cx231xx *dev, u32 ref_count) +{ + int status = 0; + u8 temp = 0; + u32 colibri_power_status = 0; + int i = 0; + + /* super block initialize */ + temp = (u8)(ref_count & 0xff); + status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, SUP_BLK_TUNE2, 2, temp, 1); + + status = cx231xx_read_i2c_data(dev, Colibri_DEVICE_ADDRESS, SUP_BLK_TUNE2, 2, &colibri_power_status, 1); + + temp = (u8)((ref_count & 0x300) >> 8); + temp |= 0x40; + status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, SUP_BLK_TUNE1, 2, temp, 1); + status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, SUP_BLK_PLL2, 2, 0x0f, 1); + + /* enable pll */ + while(colibri_power_status != 0x18) + { + status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, SUP_BLK_PWRDN, 2, 0x18, 1); + status = cx231xx_read_i2c_data(dev, Colibri_DEVICE_ADDRESS, SUP_BLK_PWRDN, 2, &colibri_power_status, 1); + colibri_power_status &= 0xff; + if(status < 0) { + cx231xx_info(": Init Super Block failed in sending/receiving cmds\n"); + break; + } + i++; + if( i == 10) { + cx231xx_info(": Init Super Block force break in loop !!!!\n"); + status = -1; + break; + } + } + + if(status < 0 ) + return status; + + /* start tuning filter */ + status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, SUP_BLK_TUNE3, 2, 0x40, 1); + msleep(5); + + /* exit tuning */ + status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, SUP_BLK_TUNE3, 2, 0x00, 1); + + return status; +} + +int cx231xx_colibri_init_channels(struct cx231xx *dev) +{ + int status = 0; + + /* power up all 3 channels, clear pd_buffer */ + status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_PWRDN_CLAMP_CH1, 2, 0x00, 1); + status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_PWRDN_CLAMP_CH2, 2, 0x00, 1); + status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_PWRDN_CLAMP_CH3, 2, 0x00, 1); + + /* Enable quantizer calibration */ + status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_COM_QUANT, 2, 0x02, 1); + + /* channel initialize, force modulator (fb) reset */ + status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_FB_FRCRST_CH1, 2, 0x17, 1); + status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_FB_FRCRST_CH2, 2, 0x17, 1); + status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_FB_FRCRST_CH3, 2, 0x17, 1); + + /* start quantilizer calibration */ + status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_CAL_ATEST_CH1, 2, 0x10, 1); + status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_CAL_ATEST_CH2, 2, 0x10, 1); + status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_CAL_ATEST_CH3, 2, 0x10, 1); + msleep(5); + + /* exit modulator (fb) reset */ + status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_FB_FRCRST_CH1, 2, 0x07, 1); + status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_FB_FRCRST_CH2, 2, 0x07, 1); + status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_FB_FRCRST_CH3, 2, 0x07, 1); + + /* enable the pre_clamp in each channel for single-ended input */ + status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_NTF_PRECLMP_EN_CH1, 2, 0xf0, 1); + status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_NTF_PRECLMP_EN_CH2, 2, 0xf0, 1); + status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_NTF_PRECLMP_EN_CH3, 2, 0xf0, 1); + + /* use diode instead of resistor, so set term_en to 0, res_en to 0 */ + status = cx231xx_reg_mask_write(dev, Colibri_DEVICE_ADDRESS, 8, ADC_QGAIN_RES_TRM_CH1, 3, 7, 0x00); + status = cx231xx_reg_mask_write(dev, Colibri_DEVICE_ADDRESS, 8, ADC_QGAIN_RES_TRM_CH2, 3, 7, 0x00); + status = cx231xx_reg_mask_write(dev, Colibri_DEVICE_ADDRESS, 8, ADC_QGAIN_RES_TRM_CH3, 3, 7, 0x00); + + /* dynamic element matching off */ + status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_DCSERVO_DEM_CH1, 2, 0x03, 1); + status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_DCSERVO_DEM_CH2, 2, 0x03, 1); + status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_DCSERVO_DEM_CH3, 2, 0x03, 1); + + return status; +} + +int cx231xx_colibri_setup_AFE_for_baseband(struct cx231xx *dev) +{ + u32 c_value = 0; + int status = 0; + + status = cx231xx_read_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_PWRDN_CLAMP_CH2, 2, &c_value, 1); + c_value &= (~(0x50)); + status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_PWRDN_CLAMP_CH2, 2, c_value, 1); + + return status; +} + +/* + we have 3 channel + channel 1 ----- pin 1 to pin4(in reg is 1-4) + channel 2 ----- pin 5 to pin8(in reg is 5-8) + channel 3 ----- pin 9 to pin 12(in reg is 9-11) +*/ +int cx231xx_colibri_set_input_mux(struct cx231xx *dev, u32 input_mux) +{ + u8 ch1_setting = (u8)input_mux; + u8 ch2_setting = (u8)(input_mux >> 8); + u8 ch3_setting = (u8)(input_mux >> 16); + int status = 0; + u32 value = 0; + + if(ch1_setting != 0) + { + status = cx231xx_read_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_INPUT_CH1, 2, &value, 1); + value &= (!INPUT_SEL_MASK); + value |= (ch1_setting-1)<<4; + value &= 0xff; + status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_INPUT_CH1, 2, value, 1); + } + + if(ch2_setting != 0) + { + status = cx231xx_read_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_INPUT_CH2, 2, &value, 1); + value &= (!INPUT_SEL_MASK); + value |= (ch2_setting-1)<<4; + value &= 0xff; + status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_INPUT_CH2, 2, value, 1); + } + + /* For ch3_setting, the value to put in the register is 7 less than the input number */ + if(ch3_setting != 0) + { + status = cx231xx_read_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_INPUT_CH3, 2, &value, 1); + value &= (!INPUT_SEL_MASK); + value |= (ch3_setting-1)<<4; + value &= 0xff; + status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_INPUT_CH3, 2, value, 1); + } + + return status; +} + +int cx231xx_colibri_set_mode(struct cx231xx *dev, enum AFE_MODE mode) +{ + int status = 0; + + switch(mode) { + case AFE_MODE_LOW_IF: + /* SetupAFEforLowIF(); */ + break; + case AFE_MODE_BASEBAND: + status = cx231xx_colibri_setup_AFE_for_baseband(dev); + break; + case AFE_MODE_EU_HI_IF: + /* SetupAFEforEuHiIF(); */ + break; + case AFE_MODE_US_HI_IF: + /* SetupAFEforUsHiIF(); */ + break; + case AFE_MODE_JAPAN_HI_IF: + /* SetupAFEforJapanHiIF(); */ + break; + } + + if((mode != dev->colibri_mode) && (dev->video_input == CX231XX_VMUX_TELEVISION)) { + status = cx231xx_colibri_adjust_ref_count(dev, CX231XX_VMUX_TELEVISION); + } + + dev->colibri_mode = mode; + + return status; +} + +/* For power saving in the EVK */ +int cx231xx_colibri_update_power_control(struct cx231xx *dev, AV_MODE avmode) +{ + u32 colibri_power_status = 0; + int status = 0; + + switch (dev->model) { + case CX231XX_BOARD_CNXT_RDE_250: + case CX231XX_BOARD_CNXT_RDU_250: + + if(avmode==POLARIS_AVMODE_ANALOGT_TV) + { + while(colibri_power_status != 0x18) { + status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, + SUP_BLK_PWRDN, 2, 0x18, 1); + status = cx231xx_read_i2c_data(dev, Colibri_DEVICE_ADDRESS, + SUP_BLK_PWRDN, 2, &colibri_power_status, 1); + if(status < 0 ) + break; + } + + status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, + ADC_PWRDN_CLAMP_CH1, 2, 0x00, 1); + status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, + ADC_PWRDN_CLAMP_CH2, 2, 0x00, 1); + status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, + ADC_PWRDN_CLAMP_CH3, 2, 0x00, 1); + } + else if(avmode==POLARIS_AVMODE_DIGITAL) { + status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, + ADC_PWRDN_CLAMP_CH1, 2, 0x70, 1); + status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, + ADC_PWRDN_CLAMP_CH2, 2, 0x70, 1); + status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, + ADC_PWRDN_CLAMP_CH3, 2, 0x70, 1); + + status = cx231xx_read_i2c_data(dev, Colibri_DEVICE_ADDRESS, + SUP_BLK_PWRDN, 2, &colibri_power_status, 1); + colibri_power_status |=0x07; + status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, + SUP_BLK_PWRDN, 2, colibri_power_status, 1); + } + else if(avmode==POLARIS_AVMODE_ENXTERNAL_AV) { + + while(colibri_power_status != 0x18) { + status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, + SUP_BLK_PWRDN, 2, 0x18, 1); + status = cx231xx_read_i2c_data(dev, Colibri_DEVICE_ADDRESS, + SUP_BLK_PWRDN, 2, &colibri_power_status, 1); + if(status < 0 ) + break; + } + + status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, + ADC_PWRDN_CLAMP_CH1, 2, 0x00, 1); + status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, + ADC_PWRDN_CLAMP_CH2, 2, 0x00, 1); + status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, + ADC_PWRDN_CLAMP_CH3, 2, 0x00, 1); + } + else { + cx231xx_info("Invalid AV mode input\n"); + status = -1; + } + break; + default: + if(avmode==POLARIS_AVMODE_ANALOGT_TV) + { + while(colibri_power_status != 0x18) { + status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, + SUP_BLK_PWRDN, 2, 0x18, 1); + status = cx231xx_read_i2c_data(dev, Colibri_DEVICE_ADDRESS, + SUP_BLK_PWRDN, 2, &colibri_power_status, 1); + if(status < 0 ) + break; + } + + status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, + ADC_PWRDN_CLAMP_CH1, 2, 0x40, 1); + status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, + ADC_PWRDN_CLAMP_CH2, 2, 0x40, 1); + status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, + ADC_PWRDN_CLAMP_CH3, 2, 0x00, 1); + } + else if(avmode==POLARIS_AVMODE_DIGITAL) { + status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, + ADC_PWRDN_CLAMP_CH1, 2, 0x70, 1); + status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, + ADC_PWRDN_CLAMP_CH2, 2, 0x70, 1); + status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, + ADC_PWRDN_CLAMP_CH3, 2, 0x70, 1); + + status = cx231xx_read_i2c_data(dev, Colibri_DEVICE_ADDRESS, + SUP_BLK_PWRDN, 2, &colibri_power_status, 1); + colibri_power_status |=0x07; + status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, + SUP_BLK_PWRDN, 2, colibri_power_status, 1); + } + else if(avmode==POLARIS_AVMODE_ENXTERNAL_AV) { + while(colibri_power_status != 0x18) { + status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, + SUP_BLK_PWRDN, 2, 0x18, 1); + status = cx231xx_read_i2c_data(dev, Colibri_DEVICE_ADDRESS, + SUP_BLK_PWRDN, 2, &colibri_power_status, 1); + if(status < 0 ) + break; + } + + status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, + ADC_PWRDN_CLAMP_CH1, 2, 0x00, 1); + status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, + ADC_PWRDN_CLAMP_CH2, 2, 0x00, 1); + status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, + ADC_PWRDN_CLAMP_CH3, 2, 0x40, 1); + } + else { + cx231xx_info("Invalid AV mode input\n"); + status = -1; + } + } /* switch */ + + return status; +} + +int cx231xx_colibri_adjust_ref_count(struct cx231xx *dev, u32 video_input) +{ + u32 input_mode = 0; + u32 ntf_mode = 0; + int status = 0; + + dev->video_input = video_input; + + if(video_input == CX231XX_VMUX_TELEVISION) { + status = cx231xx_read_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_INPUT_CH3, 2, &input_mode, 1); + status = cx231xx_read_i2c_data(dev, Colibri_DEVICE_ADDRESS, + ADC_NTF_PRECLMP_EN_CH3, 2, &ntf_mode, 1); + } + else { + status = cx231xx_read_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_INPUT_CH1, 2, &input_mode, 1); + status = cx231xx_read_i2c_data(dev, Colibri_DEVICE_ADDRESS, + ADC_NTF_PRECLMP_EN_CH1, 2, &ntf_mode, 1); + } + + input_mode = (ntf_mode & 0x3) | ((input_mode & 0x6) << 1); + + switch(input_mode) + { + case SINGLE_ENDED: + dev->colibri_ref_count = 0x23C; + break; + case LOW_IF: + dev->colibri_ref_count = 0x24C; + break; + case EU_IF: + dev->colibri_ref_count = 0x258; + break; + case US_IF: + dev->colibri_ref_count = 0x260; + break; + default: + break; + } + + status = cx231xx_colibri_init_super_block(dev, dev->colibri_ref_count); + + return status; +} + + + +/************************************************************************************* + * V I D E O / A U D I O D E C O D E R C O N T R O L functions * + *************************************************************************************/ +int cx231xx_set_video_input_mux(struct cx231xx *dev, u8 input) +{ + int status = 0; + + switch(INPUT(input)->type) { + case CX231XX_VMUX_COMPOSITE1: + case CX231XX_VMUX_SVIDEO: + if((dev->current_pcb_config.type == USB_BUS_POWER) && + (dev->power_mode != POLARIS_AVMODE_ENXTERNAL_AV)) { + status = cx231xx_set_power_mode(dev, POLARIS_AVMODE_ENXTERNAL_AV); /* External AV */ + if (status < 0) { + cx231xx_errdev("%s: cx231xx_set_power_mode : Failed to set Power - errCode [%d]!\n", + __func__, status); + return status; + } + } + status = cx231xx_set_decoder_video_input(dev, INPUT(input)->type, INPUT(input)->vmux); + break; + case CX231XX_VMUX_TELEVISION: + case CX231XX_VMUX_CABLE: + if((dev->current_pcb_config.type == USB_BUS_POWER) && + (dev->power_mode != POLARIS_AVMODE_ANALOGT_TV)) { + status = cx231xx_set_power_mode(dev, POLARIS_AVMODE_ANALOGT_TV); /* Tuner */ + if (status < 0) { + cx231xx_errdev("%s: cx231xx_set_power_mode : Failed to set Power - errCode [%d]!\n", + __func__, status); + return status; + } + } + status = cx231xx_set_decoder_video_input(dev, CX231XX_VMUX_COMPOSITE1, INPUT(input)->vmux); + break; + default: + cx231xx_errdev("%s: cx231xx_set_power_mode : Unknown Input %d !\n", + __func__, INPUT(input)->type); + break; + } + + /* save the selection */ + dev->video_input = input; + + return status; +} + +int cx231xx_set_decoder_video_input(struct cx231xx *dev, u8 pin_type, u8 input) +{ + int status = 0; + u32 value = 0; + + if(pin_type != dev->video_input) { + status = cx231xx_colibri_adjust_ref_count(dev, pin_type); + if(status < 0 ) { + cx231xx_errdev("%s: cx231xx_colibri_adjust_ref_count :Failed to set Colibri input mux - errCode [%d]!\n", + __func__, status); + return status; + } + } + + /* call colibri block to set video inputs */ + status = cx231xx_colibri_set_input_mux(dev, input); + if(status < 0 ) { + cx231xx_errdev("%s: cx231xx_colibri_set_input_mux :Failed to set Colibri input mux - errCode [%d]!\n", + __func__, status); + return status; + } + + switch(pin_type) { + case CX231XX_VMUX_COMPOSITE1: + { + status = cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, AFE_CTRL, 2, &value, 4); + value |= (0<<13)|(1<<4); + value &= ~(1<<5); + + value &= (~(0x1FF8000)); /* set [24:23] [22:15] to 0 */ + value |= 0x1000000; /* set FUNC_MODE[24:23] = 2 IF_MOD[22:15] = 0 */ + status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, AFE_CTRL, 2, value, 4); + + status = cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, OUT_CTRL1, 2, &value, 4); + value |= (1<<7); + status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, OUT_CTRL1, 2, value, 4); + + /* Set vip 1.1 output mode */ + status = cx231xx_read_modify_write_i2c_dword(dev, HAMMERHEAD_I2C_ADDRESS, + OUT_CTRL1, FLD_OUT_MODE, OUT_MODE_VIP11); + + /* Tell DIF object to go to baseband mode */ + status = cx231xx_dif_set_standard(dev, DIF_USE_BASEBAND); + if (status < 0) { + cx231xx_errdev("%s: cx231xx_dif set to By pass mode - errCode [%d]!\n", + __func__, status); + return status; + } + + /* Read the DFE_CTRL1 register */ + status = cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DFE_CTRL1, 2, &value, 4); + + /* enable the VBI_GATE_EN */ + value |= FLD_VBI_GATE_EN; + + /* Enable the auto-VGA enable */ + value |= FLD_VGA_AUTO_EN; + + /* Write it back */ + status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DFE_CTRL1, 2, value, 4); + + /* Disable auto config of registers */ + status = cx231xx_read_modify_write_i2c_dword(dev, HAMMERHEAD_I2C_ADDRESS, + MODE_CTRL, FLD_ACFG_DIS, cx231xx_set_field(FLD_ACFG_DIS, 1)); + + /* Set CVBS input mode */ + status = cx231xx_read_modify_write_i2c_dword(dev, HAMMERHEAD_I2C_ADDRESS, + MODE_CTRL, FLD_INPUT_MODE, + cx231xx_set_field(FLD_INPUT_MODE, INPUT_MODE_CVBS_0)); + } + break; + case CX231XX_VMUX_SVIDEO: + { + /* Disable the use of DIF */ + + status = cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, AFE_CTRL, 2, &value, 4); + + value &= (~(0x1FF8000)); /* set [24:23] [22:15] to 0 */ + value |= 0x1000010; /* set FUNC_MODE[24:23] = 2 + IF_MOD[22:15] = 0 DCR_BYP_CH2[4:4] = 1; */ + status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, AFE_CTRL, 2, value, 4); + + /* Tell DIF object to go to baseband mode */ + status = cx231xx_dif_set_standard(dev, DIF_USE_BASEBAND); + if (status < 0) { + cx231xx_errdev("%s: cx231xx_dif set to By pass mode - errCode [%d]!\n", + __func__, status); + return status; + } + + /* Read the DFE_CTRL1 register */ + status = cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DFE_CTRL1, 2, &value, 4); + + /* enable the VBI_GATE_EN */ + value |= FLD_VBI_GATE_EN; + + /* Enable the auto-VGA enable */ + value |= FLD_VGA_AUTO_EN; + + /* Write it back */ + status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DFE_CTRL1, 2, value, 4); + + /* Disable auto config of registers */ + status = cx231xx_read_modify_write_i2c_dword(dev, HAMMERHEAD_I2C_ADDRESS, + MODE_CTRL, FLD_ACFG_DIS, cx231xx_set_field(FLD_ACFG_DIS, 1)); + + /* Set YC input mode */ + status = cx231xx_read_modify_write_i2c_dword(dev, HAMMERHEAD_I2C_ADDRESS, + MODE_CTRL, FLD_INPUT_MODE, + cx231xx_set_field(FLD_INPUT_MODE, INPUT_MODE_YC_1)); + + /* Chroma to ADC2 */ + status = cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, AFE_CTRL, 2, &value, 4); + value |= FLD_CHROMA_IN_SEL; /* set the chroma in select */ + + /* Clear VGA_SEL_CH2 and VGA_SEL_CH3 (bits 7 and 8) This sets them to use video + rather than audio. Only one of the two will be in use. */ + value &= ~(FLD_VGA_SEL_CH2 | FLD_VGA_SEL_CH3); + + status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, AFE_CTRL, 2, value, 4); + + status = cx231xx_colibri_set_mode(dev, AFE_MODE_BASEBAND); + } + break; + case CX231XX_VMUX_TELEVISION: + case CX231XX_VMUX_CABLE: + default: + { + switch(dev->model) { + case CX231XX_BOARD_CNXT_RDE_250: + case CX231XX_BOARD_CNXT_RDU_250: + { + /* Disable the use of DIF */ + + status = cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, AFE_CTRL, 2, &value, 4); + value |= (0<<13)|(1<<4); + value &= ~(1<<5); + + value &= (~(0x1FF8000)); /* set [24:23] [22:15] to 0 */ + value |= 0x1000000; /* set FUNC_MODE[24:23] = 2 IF_MOD[22:15] = 0 */ + status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, AFE_CTRL, 2, value, 4); + + status = cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, OUT_CTRL1, 2, &value, 4); + value |= (1<<7); + status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, OUT_CTRL1, 2, value, 4); + + /* Set vip 1.1 output mode */ + status = cx231xx_read_modify_write_i2c_dword(dev, HAMMERHEAD_I2C_ADDRESS, + OUT_CTRL1, FLD_OUT_MODE, OUT_MODE_VIP11); + + /* Tell DIF object to go to baseband mode */ + status = cx231xx_dif_set_standard(dev, DIF_USE_BASEBAND); + if (status < 0) { + cx231xx_errdev("%s: cx231xx_dif set to By pass mode - errCode [%d]!\n", + __func__, status); + return status; + } + + /* Read the DFE_CTRL1 register */ + status = cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DFE_CTRL1, 2, &value, 4); + + /* enable the VBI_GATE_EN */ + value |= FLD_VBI_GATE_EN; + + /* Enable the auto-VGA enable */ + value |= FLD_VGA_AUTO_EN; + + /* Write it back */ + status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DFE_CTRL1, 2, value, 4); + + /* Disable auto config of registers */ + status = cx231xx_read_modify_write_i2c_dword(dev, HAMMERHEAD_I2C_ADDRESS, + MODE_CTRL, FLD_ACFG_DIS, cx231xx_set_field(FLD_ACFG_DIS, 1)); + + /* Set CVBS input mode */ + status = cx231xx_read_modify_write_i2c_dword(dev, HAMMERHEAD_I2C_ADDRESS, + MODE_CTRL, FLD_INPUT_MODE, + cx231xx_set_field(FLD_INPUT_MODE, INPUT_MODE_CVBS_0)); + } + break; + default: + { + /* Enable the DIF for the tuner */ + + /* Reinitialize the DIF */ + status = cx231xx_dif_set_standard(dev, dev->norm); + if (status < 0) { + cx231xx_errdev("%s: cx231xx_dif set to By pass mode - errCode [%d]!\n", + __func__, status); + return status; + } + + /* Make sure bypass is cleared */ + status = cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_MISC_CTRL, 2, &value, 4); + + /* Clear the bypass bit */ + value &= ~FLD_DIF_DIF_BYPASS; + + /* Enable the use of the DIF block */ + status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_MISC_CTRL, 2, value, 4); + + /* Read the DFE_CTRL1 register */ + status = cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DFE_CTRL1, 2, &value, 4); + + /* Disable the VBI_GATE_EN */ + value &= ~FLD_VBI_GATE_EN; + + /* Enable the auto-VGA enable, AGC, and set the skip count to 2 */ + value |= FLD_VGA_AUTO_EN | FLD_AGC_AUTO_EN | 0x00200000; + + /* Write it back */ + status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DFE_CTRL1, 2, value, 4); + + /* Wait 15 ms */ + msleep(1); + + /* Disable the auto-VGA enable AGC */ + value &= ~(FLD_VGA_AUTO_EN); + + /* Write it back */ + status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DFE_CTRL1, 2, value, 4); + + /* Enable Polaris B0 AGC output */ + status = cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, PIN_CTRL, 2, &value, 4); + value |=(FLD_OEF_AGC_RF)|(FLD_OEF_AGC_IFVGA)|(FLD_OEF_AGC_IF); + status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, PIN_CTRL, 2, value, 4); + + /* Set vip 1.1 output mode */ + status = cx231xx_read_modify_write_i2c_dword(dev, HAMMERHEAD_I2C_ADDRESS, + OUT_CTRL1, FLD_OUT_MODE, OUT_MODE_VIP11); + + /* Disable auto config of registers */ + status = cx231xx_read_modify_write_i2c_dword(dev, HAMMERHEAD_I2C_ADDRESS, + MODE_CTRL, FLD_ACFG_DIS, cx231xx_set_field(FLD_ACFG_DIS, 1)); + + /* Set CVBS input mode */ + status = cx231xx_read_modify_write_i2c_dword(dev, HAMMERHEAD_I2C_ADDRESS, + MODE_CTRL, FLD_INPUT_MODE, + cx231xx_set_field(FLD_INPUT_MODE, INPUT_MODE_CVBS_0)); + + /* Set some bits in AFE_CTRL so that channel 2 or 3 is ready to receive audio */ + /* Clear clamp for channels 2 and 3 (bit 16-17) */ + /* Clear droop comp (bit 19-20) */ + /* Set VGA_SEL (for audio control) (bit 7-8) */ + status = cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, AFE_CTRL, 2, &value, 4); + + value |= FLD_VGA_SEL_CH3 | FLD_VGA_SEL_CH2; + + status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, AFE_CTRL, 2, value, 4); + } + break; + + } + } + break; + } + + /* Set raw VBI mode */ + status = cx231xx_read_modify_write_i2c_dword(dev, HAMMERHEAD_I2C_ADDRESS, + OUT_CTRL1, FLD_VBIHACTRAW_EN, + cx231xx_set_field(FLD_VBIHACTRAW_EN, 1)); + + status = cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, OUT_CTRL1, 2, &value, 4); + if(value & 0x02) { + value |=(1<<19); + status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, OUT_CTRL1, 2, value, 4); + } + + return status; +} + +/* + * Handle any video-mode specific overrides that are different on a per video standards + * basis after touching the MODE_CTRL register which resets many values for autodetect + */ +int cx231xx_do_mode_ctrl_overrides(struct cx231xx *dev) +{ + int status = 0; + + cx231xx_info("do_mode_ctrl_overrides : 0x%x\n", (unsigned int)dev->norm); + + /* Change the DFE_CTRL3 bp_percent to fix flagging */ + status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DFE_CTRL3, 2, 0xCD3F0280, 4); + + if( dev->norm & (V4L2_STD_NTSC_M | V4L2_STD_NTSC_M_JP | V4L2_STD_PAL_M) ) { + cx231xx_info("do_mode_ctrl_overrides NTSC\n"); + + /* Move the close caption lines out of active video, adjust the active video start point */ + status = cx231xx_read_modify_write_i2c_dword(dev, HAMMERHEAD_I2C_ADDRESS, + VERT_TIM_CTRL, FLD_VBLANK_CNT,0x18); + status = cx231xx_read_modify_write_i2c_dword(dev, HAMMERHEAD_I2C_ADDRESS, + VERT_TIM_CTRL, FLD_VACTIVE_CNT,0x1E6000); + status = cx231xx_read_modify_write_i2c_dword(dev, HAMMERHEAD_I2C_ADDRESS, + VERT_TIM_CTRL, FLD_V656BLANK_CNT,0x1E000000); + + status = cx231xx_read_modify_write_i2c_dword(dev, HAMMERHEAD_I2C_ADDRESS, + HORIZ_TIM_CTRL, FLD_HBLANK_CNT, + cx231xx_set_field(FLD_HBLANK_CNT, 0x79)); + } else if ( dev->norm & ( V4L2_STD_PAL_B | V4L2_STD_PAL_G | V4L2_STD_PAL_D | + V4L2_STD_PAL_I | V4L2_STD_PAL_N | V4L2_STD_PAL_Nc) ) { + cx231xx_info("do_mode_ctrl_overrides PAL\n"); + status = cx231xx_read_modify_write_i2c_dword(dev, HAMMERHEAD_I2C_ADDRESS, + VERT_TIM_CTRL, FLD_VBLANK_CNT,0x24); + /* Adjust the active video horizontal start point */ + status = cx231xx_read_modify_write_i2c_dword(dev, HAMMERHEAD_I2C_ADDRESS, + HORIZ_TIM_CTRL, FLD_HBLANK_CNT, + cx231xx_set_field(FLD_HBLANK_CNT, 0x85)); + } else if (dev->norm & ( V4L2_STD_SECAM_B | V4L2_STD_SECAM_D | V4L2_STD_SECAM_G | + V4L2_STD_SECAM_K | V4L2_STD_SECAM_K1 | V4L2_STD_SECAM_L | + V4L2_STD_SECAM_LC) ) { + cx231xx_info("do_mode_ctrl_overrides SECAM\n"); + status = cx231xx_read_modify_write_i2c_dword(dev, HAMMERHEAD_I2C_ADDRESS, + VERT_TIM_CTRL, FLD_VBLANK_CNT,0x24); + /* Adjust the active video horizontal start point */ + status = cx231xx_read_modify_write_i2c_dword(dev, HAMMERHEAD_I2C_ADDRESS, + HORIZ_TIM_CTRL, FLD_HBLANK_CNT, + cx231xx_set_field(FLD_HBLANK_CNT, 0x85)); + } + + return status; +} + +int cx231xx_set_audio_input(struct cx231xx *dev, u8 input) +{ + int status = 0; + enum AUDIO_INPUT ainput = AUDIO_INPUT_LINE; + + switch(INPUT(input)->amux) { + case CX231XX_AMUX_VIDEO: + ainput = AUDIO_INPUT_TUNER_TV; + break; + case CX231XX_AMUX_LINE_IN: + status = cx231xx_flatiron_set_audio_input(dev, input); + ainput = AUDIO_INPUT_LINE; + break; + default: + break; + } + + status = cx231xx_set_audio_decoder_input(dev, ainput); + + return status; +} + +int cx231xx_set_audio_decoder_input(struct cx231xx *dev, enum AUDIO_INPUT audio_input) +{ + u32 dwval; + int status; + u32 gen_ctrl; + u32 value = 0; + + /* Put it in soft reset */ + status = cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, GENERAL_CTL, 2, &gen_ctrl, 1); + gen_ctrl |= 1; + status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, GENERAL_CTL, 2, gen_ctrl, 1); + + switch(audio_input) + { + case AUDIO_INPUT_LINE: + + /* setup AUD_IO control from Merlin paralle output */ + value = cx231xx_set_field(FLD_AUD_CHAN1_SRC, AUD_CHAN_SRC_PARALLEL); + status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, AUD_IO_CTRL, 2, value, 4); + + /* setup input to Merlin, SRC2 connect to AC97 + bypass upsample-by-2, slave mode, sony mode, left justify + adr 091c, dat 01000000 */ + status = cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, AC97_CTL, 2, &dwval, 4); + + status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, AC97_CTL, 2, (dwval | FLD_AC97_UP2X_BYPASS), 4); + + /* select the parallel1 and SRC3 */ + status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, BAND_OUT_SEL, 2, + cx231xx_set_field(FLD_SRC3_IN_SEL, 0x0)| + cx231xx_set_field(FLD_SRC3_CLK_SEL, 0x0)| + cx231xx_set_field(FLD_PARALLEL1_SRC_SEL, 0x0), 4); + + /* unmute all, AC97 in, independence mode + adr 08d0, data 0x00063073 */ + status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, PATH1_CTL1, 2, 0x00063073, 4); + + /* set AVC maximum threshold, adr 08d4, dat ffff0024 */ + status = cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, PATH1_VOL_CTL, 2, &dwval, 4); + status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, PATH1_VOL_CTL, 2, + (dwval | FLD_PATH1_AVC_THRESHOLD), 4); + + /* set SC maximum threshold, adr 08ec, dat ffffb3a3 */ + status = cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, PATH1_SC_CTL, 2, &dwval, 4); + status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, PATH1_SC_CTL, 2, + (dwval | FLD_PATH1_SC_THRESHOLD), 4); + break; + + case AUDIO_INPUT_TUNER_TV: + default: + + /* Setup SRC sources and clocks */ + status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, BAND_OUT_SEL, 2, + cx231xx_set_field(FLD_SRC6_IN_SEL, 0x00)| + cx231xx_set_field(FLD_SRC6_CLK_SEL, 0x01)| + cx231xx_set_field(FLD_SRC5_IN_SEL, 0x00)| + cx231xx_set_field(FLD_SRC5_CLK_SEL, 0x02)| + cx231xx_set_field(FLD_SRC4_IN_SEL, 0x02)| + cx231xx_set_field(FLD_SRC4_CLK_SEL, 0x03)| + cx231xx_set_field(FLD_SRC3_IN_SEL, 0x00)| + cx231xx_set_field(FLD_SRC3_CLK_SEL, 0x00)| + cx231xx_set_field(FLD_BASEBAND_BYPASS_CTL, 0x00)| + cx231xx_set_field(FLD_AC97_SRC_SEL, 0x03)| + cx231xx_set_field(FLD_I2S_SRC_SEL, 0x00)| + cx231xx_set_field(FLD_PARALLEL2_SRC_SEL, 0x02)| + cx231xx_set_field(FLD_PARALLEL1_SRC_SEL, 0x01) , 4); + + /* Setup the AUD_IO control */ + status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, AUD_IO_CTRL, 2, + cx231xx_set_field(FLD_I2S_PORT_DIR, 0x00)| + cx231xx_set_field(FLD_I2S_OUT_SRC, 0x00)| + cx231xx_set_field(FLD_AUD_CHAN3_SRC,0x00)| + cx231xx_set_field(FLD_AUD_CHAN2_SRC, 0x00)| + cx231xx_set_field(FLD_AUD_CHAN1_SRC,0x03 ), 4); + + status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, PATH1_CTL1, 2, 0x1F063870, 4); + + /* setAudioStandard(_audio_standard); */ + + status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, PATH1_CTL1, 2, 0x00063870, 4); + switch(dev->model) + { + case CX231XX_BOARD_CNXT_RDE_250: + case CX231XX_BOARD_CNXT_RDU_250: + status = cx231xx_read_modify_write_i2c_dword(dev, HAMMERHEAD_I2C_ADDRESS, + CHIP_CTRL, FLD_SIF_EN, + cx231xx_set_field(FLD_SIF_EN, 1)); + break; + default: + break; + } + break; + + case AUDIO_INPUT_TUNER_FM: + /* use SIF for FM radio + setupFM(); + setAudioStandard(_audio_standard); + */ + break; + + case AUDIO_INPUT_MUTE: + status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, PATH1_CTL1, 2, 0x1F011012, 4); + break; + } + + /* Take it out of soft reset */ + status = cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, GENERAL_CTL, 2, &gen_ctrl, 1); + gen_ctrl &= ~1; + status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, GENERAL_CTL, 2, gen_ctrl, 1); + + return status; +} + + + +/* Set resolution of the video */ +int cx231xx_resolution_set(struct cx231xx *dev) +{ + int width, height; + u32 hscale, vscale; + int status = 0; + + width = dev->width; + height = dev->height; + + get_scale(dev,width, height,&hscale, &vscale); + + /* set horzontal scale */ + status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, HSCALE_CTRL, 2, hscale, 4); + + /* set vertical scale */ + status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, VSCALE_CTRL, 2, vscale, 4); + + return status; +} + +/************************************************************************************* + * C H I P Specific C O N T R O L functions * + *************************************************************************************/ +int cx231xx_init_ctrl_pin_status(struct cx231xx *dev) +{ + u32 value; + int status = 0; + + status = cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, PIN_CTRL, 2, &value, 4); + value |=(~dev->board.ctl_pin_status_mask); + status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, PIN_CTRL, 2, value, 4); + + return status; +} + +int cx231xx_set_agc_analog_digital_mux_select(struct cx231xx *dev, u8 analog_or_digital) +{ + int status = 0; + + /* first set the direction to output */ + status = cx231xx_set_gpio_direction(dev, dev->board.agc_analog_digital_select_gpio, 1); + + /* 0 - demod ; 1 - Analog mode */ + status = cx231xx_set_gpio_value(dev, dev->board.agc_analog_digital_select_gpio, + analog_or_digital); + + return status; +} + +int cx231xx_enable_i2c_for_tuner(struct cx231xx *dev, u8 I2CIndex) +{ + u8 value[4] ={0,0,0,0}; + int status = 0; + + cx231xx_info("Changing the i2c port for tuner to %d\n",I2CIndex); + + status = cx231xx_read_ctrl_reg(dev,VRT_GET_REGISTER, PWR_CTL_EN, value, 4); + if(status < 0) + return status; + + if(I2CIndex==I2C_1) { + if(value[0] & I2C_DEMOD_EN) { + value[0] &= ~I2C_DEMOD_EN; + status = cx231xx_write_ctrl_reg(dev,VRT_SET_REGISTER, PWR_CTL_EN,value,4); + } + } else { + if(!(value[0] & I2C_DEMOD_EN)) { + value[0] |= I2C_DEMOD_EN; + status = cx231xx_write_ctrl_reg(dev,VRT_SET_REGISTER, PWR_CTL_EN,value,4); + } + } + + return status; + +} + + +/************************************************************************************* + * D I F - B L O C K C O N T R O L functions * + *************************************************************************************/ +int cx231xx_dif_configure_C2HH_for_low_IF(struct cx231xx *dev, u32 mode, + u32 function_mode, u32 standard) +{ + int status = 0; + + if(mode == V4L2_TUNER_RADIO) { + /* C2HH */ + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + AFE_CTRL_C2HH_SRC_CTRL, 30, 31, 0x1); /* lo if big signal */ + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + AFE_CTRL_C2HH_SRC_CTRL, 23, 24, function_mode); /* FUNC_MODE = DIF */ + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + AFE_CTRL_C2HH_SRC_CTRL, 15, 22, 0xFF); /* IF_MODE */ + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + AFE_CTRL_C2HH_SRC_CTRL, 9, 9, 0x1); /* no inv */ + } + else { + switch(standard) { + case V4L2_STD_NTSC_M: /* 75 IRE Setup */ + case V4L2_STD_NTSC_M_JP: /* Japan, 0 IRE Setup */ + case V4L2_STD_PAL_M: + case V4L2_STD_PAL_N: + case V4L2_STD_PAL_Nc: + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + AFE_CTRL_C2HH_SRC_CTRL, 30, 31, 0x1); /* lo if big signal */ + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + AFE_CTRL_C2HH_SRC_CTRL, 23, 24, function_mode); /* FUNC_MODE = DIF */ + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + AFE_CTRL_C2HH_SRC_CTRL, 15, 22, 0xb); /* IF_MODE */ + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + AFE_CTRL_C2HH_SRC_CTRL, 9, 9, 0x1); /* no inv */ + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + AUD_IO_CTRL, 0, 31, 0x00000003); /* 0x124, AUD_CHAN1_SRC = 0x3 */ + break; + + case V4L2_STD_PAL_B: + case V4L2_STD_PAL_G: + /* C2HH setup */ + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + AFE_CTRL_C2HH_SRC_CTRL, 30, 31, 0x1); /* lo if big signal */ + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + AFE_CTRL_C2HH_SRC_CTRL, 23, 24, function_mode); /* FUNC_MODE = DIF */ + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + AFE_CTRL_C2HH_SRC_CTRL, 15, 22, 0xE); /* IF_MODE */ + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + AFE_CTRL_C2HH_SRC_CTRL, 9, 9, 0x1); /* no inv */ + break; + + case V4L2_STD_PAL_D: + case V4L2_STD_PAL_I: + case V4L2_STD_SECAM_L: + case V4L2_STD_SECAM_LC: + case V4L2_STD_SECAM_B: + case V4L2_STD_SECAM_D: + case V4L2_STD_SECAM_G: + case V4L2_STD_SECAM_K: + case V4L2_STD_SECAM_K1: + /* C2HH setup */ + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + AFE_CTRL_C2HH_SRC_CTRL, 30, 31, 0x1); /* lo if big signal */ + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + AFE_CTRL_C2HH_SRC_CTRL, 23, 24, function_mode); /* FUNC_MODE = DIF */ + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + AFE_CTRL_C2HH_SRC_CTRL, 15, 22, 0xF); /* IF_MODE */ + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + AFE_CTRL_C2HH_SRC_CTRL, 9, 9, 0x1); /* no inv */ + break; + + case DIF_USE_BASEBAND: + default: + /* do nothing to config C2HH for baseband */ + break; + } + } + + return status; +} + +int cx231xx_dif_set_standard(struct cx231xx *dev, u32 standard) +{ + int status = 0; + u32 dif_misc_ctrl_value = 0; + u32 func_mode = 0; + + cx231xx_info("%s: setStandard to %x\n",__func__,standard); + + status = cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + DIF_MISC_CTRL, 2, &dif_misc_ctrl_value, 4); + if(standard != DIF_USE_BASEBAND ) + dev->norm = standard; + + switch (dev->model) { + case CX231XX_BOARD_CNXT_RDE_250: + case CX231XX_BOARD_CNXT_RDU_250: + func_mode=0x03; + break; + default: + func_mode=0x01; + } + + status = cx231xx_dif_configure_C2HH_for_low_IF(dev, dev->active_mode, func_mode, standard); + + + if(standard == DIF_USE_BASEBAND ) { /* base band */ + + /* There is a different SRC_PHASE_INC value for baseband vs. DIF */ + status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + DIF_SRC_PHASE_INC, 2, 0xDF7DF83, 4); + status = cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + DIF_MISC_CTRL, 2, &dif_misc_ctrl_value, 4); + dif_misc_ctrl_value |= FLD_DIF_DIF_BYPASS; + status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + DIF_MISC_CTRL, 2, dif_misc_ctrl_value, 4); + + } else if ( standard & (V4L2_STD_PAL_B | V4L2_STD_PAL_G) ) { + + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_PLL_CTRL, 0, 31, 0x6503bc0c); + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_PLL_CTRL1, 0, 31, 0xbd038c85); + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_PLL_CTRL2, 0, 31, 0x1db4640a); + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_PLL_CTRL3, 0, 31, 0x00008800); + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_AGC_IF_REF, 0, 31, 0x444C1380); + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_AGC_CTRL_IF, 0, 31, 0xDA302600); + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_AGC_CTRL_INT, 0, 31, 0xDA261700); + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_AGC_CTRL_RF, 0, 31, 0xDA262600); + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_AGC_IF_INT_CURRENT, 0, 31, 0x26001700); + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_AGC_RF_CURRENT, 0, 31, 0x00002660); + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_VIDEO_AGC_CTRL, 0, 31, 0x72500800); + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_VID_AUD_OVERRIDE, 0, 31, 0x27000100); + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_AV_SEP_CTRL, 0, 31, 0x3F3530EC); + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_COMP_FLT_CTRL, 0, 31, 0x00A653A8); + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_SRC_PHASE_INC, 0, 31, 0x1befbf06); + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_SRC_GAIN_CONTROL, 0, 31, 0x000035e8); + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_RPT_VARIANCE, 0, 31, 0x00000000); + /* Save the Spec Inversion value */ + dif_misc_ctrl_value &= FLD_DIF_SPEC_INV; + dif_misc_ctrl_value |=0x3a013F11; + + } else if( standard & V4L2_STD_PAL_D ) { + + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_PLL_CTRL, 0, 31, 0x6503bc0c); + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_PLL_CTRL1, 0, 31, 0xbd038c85); + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_PLL_CTRL2, 0, 31, 0x1db4640a); + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_PLL_CTRL3, 0, 31, 0x00008800); + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_AGC_IF_REF, 0, 31, 0x444C1380); + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_AGC_CTRL_IF, 0, 31, 0xDA302600); + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_AGC_CTRL_INT, 0, 31, 0xDA261700); + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_AGC_CTRL_RF, 0, 31, 0xDA262600); + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_AGC_IF_INT_CURRENT, 0, 31, 0x26001700); + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_AGC_RF_CURRENT, 0, 31, 0x00002660); + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_VIDEO_AGC_CTRL, 0, 31, 0x72500800); + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_VID_AUD_OVERRIDE, 0, 31, 0x27000100); + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_AV_SEP_CTRL, 0, 31, 0x3F3934EA); + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_COMP_FLT_CTRL, 0, 31, 0x00000000); + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_SRC_PHASE_INC, 0, 31, 0x1befbf06); + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_SRC_GAIN_CONTROL, 0, 31, 0x000035e8); + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_RPT_VARIANCE, 0, 31, 0x00000000); + /* Save the Spec Inversion value */ + dif_misc_ctrl_value &= FLD_DIF_SPEC_INV; + dif_misc_ctrl_value |=0x3a023F11; + + } else if( standard & V4L2_STD_PAL_I ) { + + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_PLL_CTRL, 0, 31, 0x6503bc0c); + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_PLL_CTRL1, 0, 31, 0xbd038c85); + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_PLL_CTRL2, 0, 31, 0x1db4640a); + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_PLL_CTRL3, 0, 31, 0x00008800); + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_AGC_IF_REF, 0, 31, 0x444C1380); + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_AGC_CTRL_IF, 0, 31, 0xDA302600); + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_AGC_CTRL_INT, 0, 31, 0xDA261700); + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_AGC_CTRL_RF, 0, 31, 0xDA262600); + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_AGC_IF_INT_CURRENT, 0, 31, 0x26001700); + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_AGC_RF_CURRENT, 0, 31, 0x00002660); + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_VIDEO_AGC_CTRL, 0, 31, 0x72500800); + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_VID_AUD_OVERRIDE, 0, 31, 0x27000100); + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_AV_SEP_CTRL, 0, 31, 0x5F39A934); + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_COMP_FLT_CTRL, 0, 31, 0x00000000); + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_SRC_PHASE_INC, 0, 31, 0x1befbf06); + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_SRC_GAIN_CONTROL, 0, 31, 0x000035e8); + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_RPT_VARIANCE, 0, 31, 0x00000000); + /* Save the Spec Inversion value */ + dif_misc_ctrl_value &= FLD_DIF_SPEC_INV; + dif_misc_ctrl_value |=0x3a033F11; + + } else if( standard & V4L2_STD_PAL_M ) { + + /* improved Low Frequency Phase Noise */ + status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + DIF_PLL_CTRL, 2, 0xFF01FF0C, 4); + status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + DIF_PLL_CTRL1, 2, 0xbd038c85, 4); + status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + DIF_PLL_CTRL2, 2, 0x1db4640a, 4); + status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + DIF_PLL_CTRL3, 2, 0x00008800, 4); + status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + DIF_AGC_IF_REF, 2, 0x444C1380, 4); + status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + DIF_AGC_IF_INT_CURRENT, 2, 0x26001700, 4); + status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + DIF_AGC_RF_CURRENT, 2, 0x00002660, 4); + status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + DIF_VIDEO_AGC_CTRL, 2, 0x72500800, 4); + status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + DIF_VID_AUD_OVERRIDE, 2, 0x27000100, 4); + status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + DIF_AV_SEP_CTRL, 2, 0x012c405d, 4); + status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + DIF_COMP_FLT_CTRL, 2, 0x009f50c1, 4); + status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + DIF_SRC_PHASE_INC, 2, 0x1befbf06, 4); + status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + DIF_SRC_GAIN_CONTROL, 2, 0x000035e8, 4); + status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + DIF_SOFT_RST_CTRL_REVB, 2, 0x00000000, 4); + + /* Save the Spec Inversion value */ + dif_misc_ctrl_value &= FLD_DIF_SPEC_INV; + dif_misc_ctrl_value |= 0x3A0A3F10; + + } else if( standard & (V4L2_STD_PAL_N | V4L2_STD_PAL_Nc) ) { + + /* improved Low Frequency Phase Noise */ + status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_PLL_CTRL, 2, 0xFF01FF0C, 4); + status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_PLL_CTRL1, 2, 0xbd038c85, 4); + status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_PLL_CTRL2, 2, 0x1db4640a, 4); + status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_PLL_CTRL3, 2, 0x00008800, 4); + status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_AGC_IF_REF, 2, 0x444C1380, 4); + status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_AGC_IF_INT_CURRENT, 2, 0x26001700, 4); + status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_AGC_RF_CURRENT, 2, 0x00002660, 4); + status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_VIDEO_AGC_CTRL, 2, 0x72500800, 4); + status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_VID_AUD_OVERRIDE, 2, 0x27000100, 4); + status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_AV_SEP_CTRL, 2, 0x012c405d, 4); + status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_COMP_FLT_CTRL, 2, 0x009f50c1, 4); + status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_SRC_PHASE_INC, 2, 0x1befbf06, 4); + status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_SRC_GAIN_CONTROL, 2, 0x000035e8, 4); + status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_SOFT_RST_CTRL_REVB, 2, 0x00000000, 4); + + /* Save the Spec Inversion value */ + dif_misc_ctrl_value &= FLD_DIF_SPEC_INV; + dif_misc_ctrl_value = 0x3A093F10; + + } else if( standard & ( V4L2_STD_SECAM_B | V4L2_STD_SECAM_D | V4L2_STD_SECAM_G | + V4L2_STD_SECAM_K | V4L2_STD_SECAM_K1) ) { + + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_PLL_CTRL, 0, 31, 0x6503bc0c); + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_PLL_CTRL1, 0, 31, 0xbd038c85); + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_PLL_CTRL2, 0, 31, 0x1db4640a); + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_PLL_CTRL3, 0, 31, 0x00008800); + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_AGC_IF_REF, 0, 31, 0x888C0380); + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_AGC_CTRL_IF, 0, 31, 0xe0262600); + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_AGC_CTRL_INT, 0, 31, 0xc2171700); + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_AGC_CTRL_RF, 0, 31, 0xc2262600); + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_AGC_IF_INT_CURRENT, 0, 31, 0x26001700); + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_AGC_RF_CURRENT, 0, 31, 0x00002660); + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_VID_AUD_OVERRIDE, 0, 31, 0x27000100); + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_AV_SEP_CTRL, 0, 31, 0x3F3530ec); + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_COMP_FLT_CTRL, 0, 31, 0x00000000); + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_SRC_PHASE_INC, 0, 31, 0x1befbf06); + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_SRC_GAIN_CONTROL, 0, 31, 0x000035e8); + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_RPT_VARIANCE, 0, 31, 0x00000000); + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_VIDEO_AGC_CTRL, 0, 31, 0xf4000000); + + /* Save the Spec Inversion value */ + dif_misc_ctrl_value &= FLD_DIF_SPEC_INV; + dif_misc_ctrl_value |=0x3a023F11; + + } else if( standard & (V4L2_STD_SECAM_L | V4L2_STD_SECAM_LC) ) { + + /* Is it SECAM_L1? */ + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_PLL_CTRL, 0, 31, 0x6503bc0c); + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_PLL_CTRL1, 0, 31, 0xbd038c85); + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_PLL_CTRL2, 0, 31, 0x1db4640a); + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_PLL_CTRL3, 0, 31, 0x00008800); + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_AGC_IF_REF, 0, 31, 0x888C0380); + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_AGC_CTRL_IF, 0, 31, 0xe0262600); + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_AGC_CTRL_INT, 0, 31, 0xc2171700); + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_AGC_CTRL_RF, 0, 31, 0xc2262600); + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_AGC_IF_INT_CURRENT, 0, 31, 0x26001700); + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_AGC_RF_CURRENT, 0, 31, 0x00002660); + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_VID_AUD_OVERRIDE, 0, 31, 0x27000100); + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_AV_SEP_CTRL, 0, 31, 0x3F3530ec); + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_COMP_FLT_CTRL, 0, 31, 0x00000000); + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_SRC_PHASE_INC, 0, 31, 0x1befbf06); + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_SRC_GAIN_CONTROL, 0, 31, 0x000035e8); + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_RPT_VARIANCE, 0, 31, 0x00000000); + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_VIDEO_AGC_CTRL, 0, 31, 0xf2560000); + + /* Save the Spec Inversion value */ + dif_misc_ctrl_value &= FLD_DIF_SPEC_INV; + dif_misc_ctrl_value |=0x3a023F11; + + } else { /* V4L2_STD_NTSC_M (75 IRE Setup) Or V4L2_STD_NTSC_M_JP (Japan, 0 IRE Setup) */ + + /* For NTSC the centre frequency of video coming out of sidewinder is + around 7.1MHz or 3.6MHz depending on the spectral inversion. + so for a non spectrally inverted channel the pll freq word is 0x03420c49 + */ + + status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_PLL_CTRL, 2, 0x6503BC0C, 4); + status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_PLL_CTRL1, 2, 0xBD038C85, 4); + status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_PLL_CTRL2, 2, 0x1DB4640A, 4); + status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_PLL_CTRL3, 2, 0x00008800, 4); + status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_AGC_IF_REF, 2, 0x444C0380, 4); + status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_AGC_IF_INT_CURRENT, 2, 0x26001700, 4); + status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_AGC_RF_CURRENT, 2, 0x00002660, 4); + status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_VIDEO_AGC_CTRL, 2, 0x04000800, 4); + status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_VID_AUD_OVERRIDE, 2, 0x27000100, 4); + status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_AV_SEP_CTRL, 2, 0x01296e1f, 4); + + status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_COMP_FLT_CTRL, 2, 0x009f50c1, 4); + status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_SRC_PHASE_INC, 2, 0x1befbf06, 4); + status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_SRC_GAIN_CONTROL, 2, 0x000035e8, 4); + + status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_AGC_CTRL_IF, 2, 0xC2262600, 4); + status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_AGC_CTRL_INT, 2, 0xC2262600, 4); + status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_AGC_CTRL_RF, 2, 0xC2262600, 4); + + /* Save the Spec Inversion value */ + dif_misc_ctrl_value &= FLD_DIF_SPEC_INV; + dif_misc_ctrl_value |= 0x3a003F10; + + } + + /* The AGC values should be the same for all standards, + AUD_SRC_SEL[19] should always be disabled */ + dif_misc_ctrl_value &= ~FLD_DIF_AUD_SRC_SEL; + + /* It is still possible to get Set Standard calls even when we are in FM mode + This is done to override the value for FM. */ + if (dev->active_mode == V4L2_TUNER_RADIO) + dif_misc_ctrl_value = 0x7a080000; + + /* Write the calculated value for misc ontrol register */ + status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_MISC_CTRL, 2, dif_misc_ctrl_value, 4); + + return status; +} + +int cx231xx_tuner_pre_channel_change(struct cx231xx *dev) +{ + int status = 0; + u32 dwval; + + /* Set the RF and IF k_agc values to 3 */ + status = cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + DIF_AGC_IF_REF, 2, &dwval, 4); + dwval &= ~(FLD_DIF_K_AGC_RF | FLD_DIF_K_AGC_IF); + dwval |= 0x33000000; + + status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + DIF_AGC_IF_REF, 2, dwval, 4); + + return status; +} + +int cx231xx_tuner_post_channel_change(struct cx231xx *dev) +{ + int status = 0; + u32 dwval; + + /* Set the RF and IF k_agc values to 4 for PAL/NTSC and 8 for SECAM */ + status = cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + DIF_AGC_IF_REF, 2, &dwval, 4); + dwval &= ~(FLD_DIF_K_AGC_RF | FLD_DIF_K_AGC_IF); + + if(dev->norm & ( V4L2_STD_SECAM_L | V4L2_STD_SECAM_B | V4L2_STD_SECAM_D) ) { + dwval |= 0x88000000; + } else { + dwval |= 0x44000000; + } + + status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + DIF_AGC_IF_REF, 2, dwval, 4); + + return status; +} + + + +/************************************************************************************* + * F L A T I R O N - B L O C K C O N T R O L functions * + *************************************************************************************/ +int cx231xx_flatiron_initialize(struct cx231xx *dev) +{ + int status = 0; + u32 value; + + status = cx231xx_read_i2c_data(dev, Flatrion_DEVICE_ADDRESS, CH_PWR_CTRL1, 1, &value, 1); + /* enables clock to delta-sigma and decimation filter */ + value |= 0x80; + status = cx231xx_write_i2c_data(dev, Flatrion_DEVICE_ADDRESS, + CH_PWR_CTRL1, 1, value, 1); + /* power up all channel */ + status = cx231xx_write_i2c_data(dev, Flatrion_DEVICE_ADDRESS, + CH_PWR_CTRL2, 1, 0x00, 1); + + return status; +} + +int cx231xx_flatiron_update_power_control(struct cx231xx *dev, AV_MODE avmode) +{ + int status = 0; + u32 value=0; + + if(avmode!=POLARIS_AVMODE_ENXTERNAL_AV) { + status = cx231xx_read_i2c_data(dev, Flatrion_DEVICE_ADDRESS, CH_PWR_CTRL2, 1, &value, 1); + value |= 0xfe; + status = cx231xx_write_i2c_data(dev, Flatrion_DEVICE_ADDRESS, + CH_PWR_CTRL2, 1, value, 1); + } + else { + status = cx231xx_write_i2c_data(dev, Flatrion_DEVICE_ADDRESS, + CH_PWR_CTRL2, 1, 0x00, 1); + } + + return status; +} + +/* set flatiron for audio input types */ +int cx231xx_flatiron_set_audio_input(struct cx231xx *dev, u8 audio_input) +{ + int status = 0; + + switch(audio_input) { + case CX231XX_AMUX_LINE_IN: + + status = cx231xx_write_i2c_data(dev, Flatrion_DEVICE_ADDRESS, + CH_PWR_CTRL2, 1, 0x00, 1); + status = cx231xx_write_i2c_data(dev, Flatrion_DEVICE_ADDRESS, + CH_PWR_CTRL1, 1, 0x80, 1); + break; + case CX231XX_AMUX_VIDEO: + default: + break; + } + + dev->ctl_ainput = audio_input; + + return status; +} + +/************************************************************************************* + * P O W E R C O N T R O L functions * + *************************************************************************************/ +int cx231xx_set_power_mode(struct cx231xx *dev, AV_MODE mode) +{ + u8 value[4] ={0,0,0,0}; + u32 tmp = 0; + int status = 0; + + if(dev->power_mode != mode) + dev->power_mode = mode; + else { + cx231xx_info(" setPowerMode::mode = %d, No Change req.\n",mode); + return 0; + } + + cx231xx_info(" setPowerMode::mode = %d\n",mode); + + status = cx231xx_read_ctrl_reg(dev,VRT_GET_REGISTER, PWR_CTL_EN, value, 4); + if(status < 0) + return status; + + tmp = *((u32 *)value); + + switch(mode) { + case POLARIS_AVMODE_ENXTERNAL_AV: + + tmp &= (~PWR_MODE_MASK); + + tmp |= PWR_AV_EN; + value[0]=(u8)tmp; + value[1]=(u8)(tmp>>8); + value[2]=(u8)(tmp>>16); + value[3]=(u8)(tmp>>24); + status = cx231xx_write_ctrl_reg(dev,VRT_SET_REGISTER, PWR_CTL_EN,value,4); + msleep(PWR_SLEEP_INTERVAL); + + tmp |= PWR_ISO_EN; + value[0]=(u8)tmp; + value[1]=(u8)(tmp>>8); + value[2]=(u8)(tmp>>16); + value[3]=(u8)(tmp>>24); + status = cx231xx_write_ctrl_reg(dev,VRT_SET_REGISTER, PWR_CTL_EN,value,4); + msleep(PWR_SLEEP_INTERVAL); + + tmp |=POLARIS_AVMODE_ENXTERNAL_AV; + value[0]=(u8)tmp; + value[1]=(u8)(tmp>>8); + value[2]=(u8)(tmp>>16); + value[3]=(u8)(tmp>>24); + status = cx231xx_write_ctrl_reg(dev,VRT_SET_REGISTER, PWR_CTL_EN,value,4); + + dev->xc_fw_load_done = 0; /* reset state of xceive tuner */ + break; + + case POLARIS_AVMODE_ANALOGT_TV: + + tmp &= (~PWR_DEMOD_EN); + tmp |= (I2C_DEMOD_EN); + value[0]=(u8)tmp; + value[1]=(u8)(tmp>>8); + value[2]=(u8)(tmp>>16); + value[3]=(u8)(tmp>>24); + status = cx231xx_write_ctrl_reg(dev,VRT_SET_REGISTER, PWR_CTL_EN,value,4); + msleep(PWR_SLEEP_INTERVAL); + + if(!(tmp & PWR_TUNER_EN)) { + tmp |= (PWR_TUNER_EN); + value[0]=(u8)tmp; + value[1]=(u8)(tmp>>8); + value[2]=(u8)(tmp>>16); + value[3]=(u8)(tmp>>24); + status = cx231xx_write_ctrl_reg(dev,VRT_SET_REGISTER, PWR_CTL_EN,value,4); + msleep(PWR_SLEEP_INTERVAL); + } + + if(!(tmp & PWR_AV_EN)) { + tmp |= PWR_AV_EN; + value[0]=(u8)tmp; + value[1]=(u8)(tmp>>8); + value[2]=(u8)(tmp>>16); + value[3]=(u8)(tmp>>24); + status = cx231xx_write_ctrl_reg(dev,VRT_SET_REGISTER, PWR_CTL_EN,value,4); + msleep(PWR_SLEEP_INTERVAL); + } + if(!(tmp & PWR_ISO_EN )) { + tmp |= PWR_ISO_EN; + value[0]=(u8)tmp; + value[1]=(u8)(tmp>>8); + value[2]=(u8)(tmp>>16); + value[3]=(u8)(tmp>>24); + status = cx231xx_write_ctrl_reg(dev,VRT_SET_REGISTER, PWR_CTL_EN,value,4); + msleep(PWR_SLEEP_INTERVAL); + } + + if(!(tmp & POLARIS_AVMODE_ANALOGT_TV )) { + tmp |= POLARIS_AVMODE_ANALOGT_TV; + value[0]=(u8)tmp; + value[1]=(u8)(tmp>>8); + value[2]=(u8)(tmp>>16); + value[3]=(u8)(tmp>>24); + status = cx231xx_write_ctrl_reg(dev,VRT_SET_REGISTER, PWR_CTL_EN,value,4); + msleep(PWR_SLEEP_INTERVAL); + } + + if( (dev->model == CX231XX_BOARD_CNXT_RDE_250) || + (dev->model == CX231XX_BOARD_CNXT_RDU_250)) { + + /* tuner path to channel 1 from port 3 */ + cx231xx_enable_i2c_for_tuner(dev, I2C_3); + + if(dev->cx231xx_reset_analog_tuner) + dev->cx231xx_reset_analog_tuner(dev); + } + break; + + case POLARIS_AVMODE_DIGITAL: + + if(!(tmp & PWR_TUNER_EN)) { + tmp |= (PWR_TUNER_EN); + value[0]=(u8)tmp; + value[1]=(u8)(tmp>>8); + value[2]=(u8)(tmp>>16); + value[3]=(u8)(tmp>>24); + status = cx231xx_write_ctrl_reg(dev,VRT_SET_REGISTER, PWR_CTL_EN,value,4); + msleep(PWR_SLEEP_INTERVAL); + } + if(!(tmp & PWR_AV_EN)) { + tmp |= PWR_AV_EN; + value[0]=(u8)tmp; + value[1]=(u8)(tmp>>8); + value[2]=(u8)(tmp>>16); + value[3]=(u8)(tmp>>24); + status = cx231xx_write_ctrl_reg(dev,VRT_SET_REGISTER, PWR_CTL_EN,value,4); + msleep(PWR_SLEEP_INTERVAL); + } + if(!(tmp & PWR_ISO_EN)) { + tmp |= PWR_ISO_EN; + value[0]=(u8)tmp; + value[1]=(u8)(tmp>>8); + value[2]=(u8)(tmp>>16); + value[3]=(u8)(tmp>>24); + status = cx231xx_write_ctrl_reg(dev,VRT_SET_REGISTER, PWR_CTL_EN,value,4); + msleep(PWR_SLEEP_INTERVAL); + } + + tmp |= POLARIS_AVMODE_DIGITAL|I2C_DEMOD_EN; + value[0]=(u8)tmp; + value[1]=(u8)(tmp>>8); + value[2]=(u8)(tmp>>16); + value[3]=(u8)(tmp>>24); + status = cx231xx_write_ctrl_reg(dev,VRT_SET_REGISTER, PWR_CTL_EN,value,4); + msleep(PWR_SLEEP_INTERVAL); + + if(!(tmp & PWR_DEMOD_EN)) { + tmp |= PWR_DEMOD_EN; + value[0]=(u8)tmp; + value[1]=(u8)(tmp>>8); + value[2]=(u8)(tmp>>16); + value[3]=(u8)(tmp>>24); + status = cx231xx_write_ctrl_reg(dev,VRT_SET_REGISTER, PWR_CTL_EN,value,4); + msleep(PWR_SLEEP_INTERVAL); + } + + if( (dev->model == CX231XX_BOARD_CNXT_RDE_250) || + (dev->model == CX231XX_BOARD_CNXT_RDU_250)) { + + /* tuner path to channel 1 from port 3 */ + cx231xx_enable_i2c_for_tuner(dev, I2C_3); + + if(dev->cx231xx_reset_analog_tuner) + dev->cx231xx_reset_analog_tuner(dev); + } + break; + + default: + break; + } + + msleep(PWR_SLEEP_INTERVAL); + + /* For power saving, only enable Pwr_resetout_n when digital TV is selected. */ + if(mode == POLARIS_AVMODE_DIGITAL) { + tmp |= PWR_RESETOUT_EN; + value[0]=(u8)tmp; + value[1]=(u8)(tmp>>8); + value[2]=(u8)(tmp>>16); + value[3]=(u8)(tmp>>24); + status = cx231xx_write_ctrl_reg(dev,VRT_SET_REGISTER, PWR_CTL_EN,value,4); + msleep(PWR_SLEEP_INTERVAL); + } + + /* update power control for colibri */ + status = cx231xx_colibri_update_power_control(dev, mode); + + /* update power control for flatiron */ + status = cx231xx_flatiron_update_power_control(dev, mode); + + status = cx231xx_read_ctrl_reg(dev,VRT_GET_REGISTER, PWR_CTL_EN, value, 4); + cx231xx_info(" The data of PWR_CTL_EN register 0x74=0x%0x,0x%0x,0x%0x,0x%0x\n",value[0],value[1],value[2],value[3]); + + return status; +} + +int cx231xx_power_suspend(struct cx231xx *dev) +{ + u8 value[4] ={0,0,0,0}; + u32 tmp = 0; + int status = 0; + + status = cx231xx_read_ctrl_reg(dev,VRT_GET_REGISTER, PWR_CTL_EN, value, 4); + if(status > 0) + return status; + + tmp = *((u32 *)value); + tmp &= (~PWR_MODE_MASK); + + value[0]=(u8)tmp; + value[1]=(u8)(tmp>>8); + value[2]=(u8)(tmp>>16); + value[3]=(u8)(tmp>>24); + status = cx231xx_write_ctrl_reg(dev,VRT_SET_REGISTER, PWR_CTL_EN,value,4); + + return status; +} + + +/************************************************************************************* + * S T R E A M C O N T R O L functions * + *************************************************************************************/ +int cx231xx_start_stream(struct cx231xx *dev, u32 ep_mask) +{ + u8 value[4] = {0x0, 0x0, 0x0, 0x0}; + u32 tmp =0; + int status = 0; + + cx231xx_info("cx231xx_start_stream():: ep_mask = %x\n", ep_mask); + status = cx231xx_read_ctrl_reg(dev,VRT_GET_REGISTER, EP_MODE_SET,value,4); + if(status < 0) + return status; + + tmp = *((u32 *)value); + tmp |= ep_mask; + value[0]=(u8) tmp; + value[1]=(u8)(tmp>>8); + value[2]=(u8)(tmp>>16); + value[3]=(u8)(tmp>>24); + + status = cx231xx_write_ctrl_reg(dev,VRT_SET_REGISTER, EP_MODE_SET,value,4); + + return status; +} + +int cx231xx_stop_stream(struct cx231xx *dev, u32 ep_mask) +{ + u8 value[4] = {0x0, 0x0, 0x0, 0x0}; + u32 tmp =0; + int status = 0; + + cx231xx_info("cx231xx_stop_stream():: ep_mask = %x\n", ep_mask); + status = cx231xx_read_ctrl_reg(dev,VRT_GET_REGISTER, EP_MODE_SET,value,4); + if(status < 0) + return status; + + tmp = *((u32 *)value); + tmp&= (~ep_mask); + value[0]=(u8) tmp; + value[1]=(u8)(tmp>>8); + value[2]=(u8)(tmp>>16); + value[3]=(u8)(tmp>>24); + + status = cx231xx_write_ctrl_reg(dev,VRT_SET_REGISTER, EP_MODE_SET,value,4); + + return status; +} + +int cx231xx_initialize_stream_xfer(struct cx231xx *dev, u32 media_type) +{ + int status = 0; + + if(dev->udev->speed == USB_SPEED_HIGH) + { + switch(media_type) + { + case 81: /* audio */ + cx231xx_info("%s: Audio enter HANC\n",__func__); + status = cx231xx_mode_register(dev, TS_MODE_REG, 0x9300); + break; + + case 2: /* vbi */ + cx231xx_info("%s: set vanc registers\n",__func__); + status = cx231xx_mode_register(dev, TS_MODE_REG, 0x300); + break; + + case 3: /* sliced cc */ + cx231xx_info("%s: set hanc registers\n",__func__); + status = cx231xx_mode_register(dev, TS_MODE_REG, 0x1300); + break; + + case 0: /* video */ + cx231xx_info("%s: set video registers\n",__func__); + status = cx231xx_mode_register(dev, TS_MODE_REG, 0x100); + break; + + case 4: /* ts1 */ + cx231xx_info("%s: set ts1 registers\n",__func__); + status = cx231xx_mode_register(dev, TS_MODE_REG, 0x101); + status = cx231xx_mode_register(dev, TS1_CFG_REG, 0x400); + break; + case 6: /* ts1 parallel mode */ + cx231xx_info("%s: set ts1 parrallel mode registers\n",__func__); + status = cx231xx_mode_register(dev, TS_MODE_REG, 0x100); + status = cx231xx_mode_register(dev, TS1_CFG_REG, 0x400); + break; + } + } + else + { + status = cx231xx_mode_register(dev, TS_MODE_REG, 0x101); + } + + return status; +} + + + + +int cx231xx_capture_start(struct cx231xx *dev, int start, u8 media_type) +{ + int rc; + u32 ep_mask = -1; + PPCB_CONFIG pcb_config; + + /* get EP for media type */ + pcb_config = &dev->current_pcb_config; + + if(pcb_config->config_num==1) + { + switch (media_type) + { + case 0: /* Video */ + ep_mask =ENABLE_EP4; /* ep4 [00:1000] */ + break; + case 1: /* Audio */ + ep_mask =ENABLE_EP3; /* ep3 [00:0100] */ + break; + case 2: /* Vbi */ + ep_mask = ENABLE_EP5; /* ep5 [01:0000] */ + break; + case 3: /* Sliced_cc */ + ep_mask = ENABLE_EP6; /* ep6 [10:0000] */ + break; + case 4: /* ts1 */ + case 6: /* ts1 parallel mode */ + ep_mask = ENABLE_EP1; /* ep1 [00:0001] */ + break; + case 5: /* ts2 */ + ep_mask = ENABLE_EP2; /* ep2 [00:0010] */ + break; + } + + } + else if(pcb_config->config_num>1) + { + switch (media_type) + { + case 0: /* Video */ + ep_mask = ENABLE_EP4; /* ep4 [00:1000] */ + break; + case 1: /* Audio */ + ep_mask = ENABLE_EP3; /* ep3 [00:0100] */ + break; + case 2: /* Vbi */ + ep_mask = ENABLE_EP5; /* ep5 [01:0000] */ + break; + case 3: /* Sliced_cc */ + ep_mask = ENABLE_EP6; /* ep6 [10:0000] */ + break; + case 4: /* ts1 */ + case 6: /* ts1 parallel mode */ + ep_mask = ENABLE_EP1; /* ep1 [00:0001] */ + break; + case 5: /* ts2 */ + ep_mask = ENABLE_EP2; /* ep2 [00:0010] */ + break; + } + + } + + if(start) { + rc = cx231xx_initialize_stream_xfer(dev, media_type); + + if(rc < 0) { + return rc; + } + + /* enable video capture */ + if(ep_mask > 0 ) + rc = cx231xx_start_stream(dev, ep_mask); + } + else { + /* disable video capture */ + if(ep_mask > 0 ) + rc = cx231xx_stop_stream(dev, ep_mask); + } + + if (dev->mode == CX231XX_ANALOG_MODE){ + /* do any in Analog mode */ + } + else { + /* do any in digital mode */ + } + + return rc; +} +EXPORT_SYMBOL_GPL(cx231xx_capture_start); + + +/************************************************************************************ +* G P I O B I T control functions * +*************************************************************************************/ +int cx231xx_set_gpio_bit(struct cx231xx *dev, u32 gpio_bit, u8* gpio_val) +{ + int status = 0; + + status = cx231xx_send_gpio_cmd(dev, gpio_bit, gpio_val, 4, 0, 0); + + return status; +} + +int cx231xx_get_gpio_bit(struct cx231xx *dev, u32 gpio_bit, u8* gpio_val) +{ + int status = 0; + + status = cx231xx_send_gpio_cmd(dev, gpio_bit, gpio_val, 4, 0, 1); + + return status; +} + +/* +* cx231xx_set_gpio_direction +* Sets the direction of the GPIO pin to input or output +* +* Parameters : +* pin_number : The GPIO Pin number to program the direction for +* from 0 to 31 +* pin_value : The Direction of the GPIO Pin under reference. +* 0 = Input direction +* 1 = Output direction +*/ +int cx231xx_set_gpio_direction(struct cx231xx *dev, + int pin_number, + int pin_value) +{ + int status = 0; + u32 value = 0; + + /* Check for valid pin_number - if 32 , bail out */ + if (pin_number >= 32) { + return -EINVAL; + } + + if (pin_value == 0) { /* input */ + value = dev->gpio_dir &(~(1<gpio_dir | (1<gpio_val); + + /* cache the value for future */ + dev->gpio_dir = value; + + return status; +} + + +/* +* SetGpioPinLogicValue +* Sets the value of the GPIO pin to Logic high or low. The Pin under +* reference should ALREADY BE SET IN OUTPUT MODE !!!!!!!!! +* +* Parameters : +* pin_number : The GPIO Pin number to program the direction for +* pin_value : The value of the GPIO Pin under reference. +* 0 = set it to 0 +* 1 = set it to 1 +*/ +int cx231xx_set_gpio_value(struct cx231xx *dev, + int pin_number, + int pin_value) +{ + int status = 0; + u32 value = 0; + + /* Check for valid pin_number - if 0xFF , bail out */ + if (pin_number >= 32) + return -EINVAL; + + /* first do a sanity check - if the Pin is not output, make it output */ + if ((dev->gpio_dir & (1<gpio_dir | (1<gpio_dir = value; + status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8*) &dev->gpio_val); + value = 0; + } + + if (pin_value == 0) { + value = dev->gpio_val & (~(1<gpio_val | (1<gpio_val=value; + + /* toggle bit0 of GP_IO */ + status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8*) &dev->gpio_val); + + return status; +} + + +/************************************************************************************ +* G P I O I2C related functions * +*************************************************************************************/ +int cx231xx_gpio_i2c_start(struct cx231xx *dev) +{ + int status = 0; + + /* set SCL to output 1 ; set SDA to output 1 */ + dev->gpio_dir |= 1<< dev->board.tuner_scl_gpio; + dev->gpio_dir |= 1<board.tuner_sda_gpio; + dev->gpio_val |= 1<board.tuner_scl_gpio; + dev->gpio_val |= 1<board.tuner_sda_gpio; + + status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8*) &dev->gpio_val); + if(status < 0){ + return -EINVAL; + } + + /* set SCL to output 1; set SDA to output 0 */ + dev->gpio_val |= 1<board.tuner_scl_gpio; + dev->gpio_val &= ~(1<board.tuner_sda_gpio); + + status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8*) &dev->gpio_val); + if(status < 0){ + return -EINVAL; + } + + /* set SCL to output 0; set SDA to output 0 */ + dev->gpio_val &= ~(1<board.tuner_scl_gpio); + dev->gpio_val &= ~(1<board.tuner_sda_gpio); + + status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8*) &dev->gpio_val); + if(status < 0){ + return -EINVAL; + } + + return status; +} + + +int cx231xx_gpio_i2c_end(struct cx231xx *dev) +{ + int status = 0; + + /* set SCL to output 0; set SDA to output 0 */ + dev->gpio_dir |= 1<board.tuner_scl_gpio; + dev->gpio_dir |= 1<board.tuner_sda_gpio; + + dev->gpio_val &= ~(1<board.tuner_scl_gpio); + dev->gpio_val &= ~(1<board.tuner_sda_gpio); + + status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8*) &dev->gpio_val); + if(status < 0){ + return -EINVAL; + } + + /* set SCL to output 1; set SDA to output 0 */ + dev->gpio_val |= 1<board.tuner_scl_gpio; + dev->gpio_val &= ~(1<board.tuner_sda_gpio); + + status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8*) &dev->gpio_val); + if(status < 0){ + return -EINVAL; + } + + /* set SCL to input ,release SCL cable control + set SDA to input ,release SDA cable control */ + dev->gpio_dir &= ~(1<board.tuner_scl_gpio); + dev->gpio_dir &= ~(1<board.tuner_sda_gpio); + + status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8*) &dev->gpio_val); + if(status < 0){ + return -EINVAL; + } + return status; +} + + +int cx231xx_gpio_i2c_write_byte(struct cx231xx *dev, u8 data) +{ + int status = 0; + u8 i; + + /* set SCL to output ; set SDA to output */ + dev->gpio_dir |= 1<board.tuner_scl_gpio; + dev->gpio_dir |= 1<board.tuner_sda_gpio; + + for(i = 0;i<8;i++) { + if(((data<gpio_val &= ~(1<board.tuner_scl_gpio); + dev->gpio_val &= ~(1<board.tuner_sda_gpio); + status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8*) &dev->gpio_val); + + /* set SCL to output 1; set SDA to output 0 */ + dev->gpio_val |= 1<board.tuner_scl_gpio; + status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8*) &dev->gpio_val); + + /* set SCL to output 0; set SDA to output 0 */ + dev->gpio_val &= ~(1<board.tuner_scl_gpio); + status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8*) &dev->gpio_val); + } else { + /* set SCL to output 0; set SDA to output 1 */ + dev->gpio_val &= ~(1<board.tuner_scl_gpio); + dev->gpio_val |= 1<board.tuner_sda_gpio; + status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8*) &dev->gpio_val); + + /* set SCL to output 1; set SDA to output 1 */ + dev->gpio_val |= 1<board.tuner_scl_gpio; + status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8*) &dev->gpio_val); + + /* set SCL to output 0; set SDA to output 1 */ + dev->gpio_val &= ~(1<board.tuner_scl_gpio); + status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8*) &dev->gpio_val); + } + } + return status; +} + +int cx231xx_gpio_i2c_read_byte(struct cx231xx *dev, u8 *buf) +{ + u8 value = 0; + int status = 0; + u32 gpio_logic_value =0; + u8 i; + + /* read byte */ + for(i=0;i<8;i++) { /* send write I2c addr */ + + /* set SCL to output 0; set SDA to input */ + dev->gpio_val &= ~(1<board.tuner_scl_gpio); + status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8*) &dev->gpio_val); + + /* set SCL to output 1; set SDA to input */ + dev->gpio_val |= 1<board.tuner_scl_gpio; + status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8*) &dev->gpio_val); + + /* get SDA data bit */ + gpio_logic_value = dev->gpio_val; + status = cx231xx_get_gpio_bit(dev, dev->gpio_dir, (u8*) &dev->gpio_val); + if((dev->gpio_val & (1<board.tuner_sda_gpio)) != 0) { + value |= (1<<(8-i-1)); + } + + dev->gpio_val = gpio_logic_value; + } + + /* set SCL to output 0,finish the read latest SCL signal. + !!!set SDA to input,never to modify SDA direction at the same times */ + dev->gpio_val &= ~(1<board.tuner_scl_gpio); + status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8*) &dev->gpio_val); + + /* store the value */ + *buf = value & 0xff; + + return status; +} + +int cx231xx_gpio_i2c_read_ack(struct cx231xx *dev) +{ + int status = 0; + u32 gpio_logic_value = 0; + int nCnt=10; + int nInit=nCnt; + + /* clock stretch; set SCL to input; set SDA to input; get SCL value till SCL = 1 */ + dev->gpio_dir &= ~(1<board.tuner_sda_gpio); + dev->gpio_dir &= ~(1<board.tuner_scl_gpio); + + gpio_logic_value = dev->gpio_val; + status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8*) &dev->gpio_val); + + do{ + msleep(2); + status = cx231xx_get_gpio_bit(dev, dev->gpio_dir, (u8*) &dev->gpio_val); + nCnt--; + }while(((dev->gpio_val & (1<board.tuner_scl_gpio)) == 0) && (nCnt>0)); + + if(nCnt==0) { + cx231xx_info("No ACK after %d msec for clock stretch. GPIO I2C operation failed!",nInit*10); + } + + /* readAck + throuth clock stretch ,slave has given a SCL signal,so the SDA data can be directly read. */ + status = cx231xx_get_gpio_bit(dev, dev->gpio_dir, (u8*) &dev->gpio_val); + + if((dev->gpio_val & 1<< dev->board.tuner_sda_gpio) == 0){ + dev->gpio_val = gpio_logic_value; + dev->gpio_val &= ~(1<< dev->board.tuner_sda_gpio); + status = 0; + } else { + dev->gpio_val = gpio_logic_value; + dev->gpio_val |= (1<< dev->board.tuner_sda_gpio); + } + + /* read SDA end, set the SCL to output 0, after this operation, SDA direction can be changed. */ + dev->gpio_val = gpio_logic_value; + dev->gpio_dir |= (1<board.tuner_scl_gpio); + dev->gpio_val &= ~(1<board.tuner_scl_gpio); + status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8*) &dev->gpio_val); + + return status; +} + + +int cx231xx_gpio_i2c_write_ack(struct cx231xx *dev) +{ + int status = 0; + + /* set SDA to ouput */ + dev->gpio_dir |= 1<board.tuner_sda_gpio; + status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8*) &dev->gpio_val); + + /* set SCL = 0 (output); set SDA = 0 (output) */ + dev->gpio_val &= ~(1<board.tuner_sda_gpio); + dev->gpio_val &= ~(1<board.tuner_scl_gpio); + status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8*) &dev->gpio_val); + + /* set SCL = 1 (output); set SDA = 0 (output) */ + dev->gpio_val |= 1<board.tuner_scl_gpio; + status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8*) &dev->gpio_val); + + /* set SCL = 0 (output); set SDA = 0 (output) */ + dev->gpio_val &= ~(1<board.tuner_scl_gpio); + status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8*) &dev->gpio_val); + + /* set SDA to input,and then the slave will read data from SDA. */ + dev->gpio_dir &= ~(1<board.tuner_sda_gpio); + status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8*) &dev->gpio_val); + + return status; +} + +int cx231xx_gpio_i2c_write_nak(struct cx231xx *dev) +{ + int status = 0; + + /* set scl to output ; set sda to input */ + dev->gpio_dir |= 1<board.tuner_scl_gpio; + dev->gpio_dir &= ~(1<board.tuner_sda_gpio); + status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8*) &dev->gpio_val); + + /* set scl to output 0; set sda to input */ + dev->gpio_val &= ~(1<board.tuner_scl_gpio); + status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8*) &dev->gpio_val); + + /* set scl to output 1; set sda to input */ + dev->gpio_val |= 1<board.tuner_scl_gpio; + status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8*) &dev->gpio_val); + + return status; +} + + + +/************************************************************************************ +* G P I O I2C related functions * +*************************************************************************************/ +/* cx231xx_gpio_i2c_read + * Function to read data from gpio based I2C interface + */ +int cx231xx_gpio_i2c_read(struct cx231xx *dev, u8 dev_addr, u8 *buf ,u8 len) +{ + int status = 0; + int i = 0; + + /* get the lock */ + mutex_lock(&dev->gpio_i2c_lock); + + /* start */ + status = cx231xx_gpio_i2c_start(dev); + + /* write dev_addr */ + status = cx231xx_gpio_i2c_write_byte(dev, (dev_addr << 1) +1); + + /* readAck */ + status = cx231xx_gpio_i2c_read_ack(dev); + + /* read data */ + for(i = 0; i < len; i++ ) { + /* read data */ + buf[i] = 0; + status = cx231xx_gpio_i2c_read_byte(dev, & buf[i]); + + if( (i+1) != len) { + /* only do write ack if we more length */ + status = cx231xx_gpio_i2c_write_ack(dev); + } + } + + /* write NAK - inform reads are complete */ + status = cx231xx_gpio_i2c_write_nak(dev); + + /* write end */ + status = cx231xx_gpio_i2c_end(dev); + + /* release the lock */ + mutex_unlock(&dev->gpio_i2c_lock); + + return status; +} + + +/* cx231xx_gpio_i2c_write + * Function to write data to gpio based I2C interface + */ +int cx231xx_gpio_i2c_write(struct cx231xx *dev, u8 dev_addr, u8 *buf ,u8 len) +{ + int status = 0; + int i=0; + + /* get the lock */ + mutex_lock(&dev->gpio_i2c_lock); + + /* start */ + status = cx231xx_gpio_i2c_start(dev); + + /* write dev_addr */ + status = cx231xx_gpio_i2c_write_byte(dev, dev_addr << 1); + + /* read Ack */ + status = cx231xx_gpio_i2c_read_ack(dev); + + for(i = 0; i < len; i++ ) { + /* Write data */ + status = cx231xx_gpio_i2c_write_byte(dev, buf[i]); + + /* read Ack */ + status = cx231xx_gpio_i2c_read_ack(dev); + } + + /* write End */ + status = cx231xx_gpio_i2c_end(dev); + + /* release the lock */ + mutex_unlock(&dev->gpio_i2c_lock); + + return 0; +} + diff --git a/linux/drivers/media/video/cx231xx/cx231xx-cards.c b/linux/drivers/media/video/cx231xx/cx231xx-cards.c new file mode 100644 index 000000000..b204c7be8 --- /dev/null +++ b/linux/drivers/media/video/cx231xx/cx231xx-cards.c @@ -0,0 +1,947 @@ +/* + cx231xx-cards.c - driver for Conexant Cx23100/101/102 USB video capture devices + + Copyright (C) 2008 + Based on em28xx driver + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include "compat.h" +#include +#include +#include +#include + +#include +#include "xc5000.h" + +#include "cx231xx.h" + +static int tuner = -1; +module_param(tuner, int, 0444); +MODULE_PARM_DESC(tuner, "tuner type"); + +static unsigned int disable_ir; +module_param(disable_ir, int, 0444); +MODULE_PARM_DESC(disable_ir, "disable infrared remote support"); + +/* Bitmask marking allocated devices from 0 to CX231XX_MAXBOARDS */ +static unsigned long cx231xx_devused; + +/* + * Reset sequences for analog/digital modes + */ + +static struct cx231xx_reg_seq RDE250_XCV_TUNER[] = { + { 0x03, 0x01, 10 }, + { 0x03, 0x00, 30 }, + { 0x03, 0x01, 10 }, + { -1, -1, -1 }, +}; + + + +/* + * Board definitions + */ +struct cx231xx_board cx231xx_boards[] = { + + [CX231XX_BOARD_UNKNOWN] = { + .name = "Unknown CX231xx video grabber", + .tuner_type = TUNER_ABSENT, + .input = { { + .type = CX231XX_VMUX_TELEVISION, + .vmux = CX231XX_VIN_3_1, + .amux = CX231XX_AMUX_VIDEO, + .gpio = 0, + }, { + .type = CX231XX_VMUX_COMPOSITE1, + .vmux = CX231XX_VIN_2_1, + .amux = CX231XX_AMUX_LINE_IN, + .gpio = 0, + }, { + .type = CX231XX_VMUX_SVIDEO, + .vmux = CX231XX_VIN_1_1 | (CX231XX_VIN_1_2 << 8 ) | + CX25840_SVIDEO_ON, + .amux = CX231XX_AMUX_LINE_IN, + .gpio = 0, + } }, + }, + + [CX231XX_BOARD_CNXT_RDE_250] = { + .name = "Conexant Hybrid TV - RDE250", + .valid = CX231XX_BOARD_VALIDATED, + .tuner_type = TUNER_XC5000, + .tuner_addr = 0x61, + .tuner_gpio = RDE250_XCV_TUNER, + .tuner_sif_gpio = 0x05, + .tuner_scl_gpio = 0x1a, + .tuner_sda_gpio = 0x1b, + .decoder = CX231XX_AVDECODER, + .demod_xfer_mode = 0, + .ctl_pin_status_mask = 0xFFFFFFC4, + .agc_analog_digital_select_gpio = 0x0c, + .gpio_pin_status_mask = 0x4001000, + .tuner_i2c_master = 1, + .demod_i2c_master = 2, + .has_dvb = 1, + .demod_addr = 0x02, + .norm = V4L2_STD_PAL, + + .input = { { + .type = CX231XX_VMUX_TELEVISION, + .vmux = CX231XX_VIN_3_1, + .amux = CX231XX_AMUX_VIDEO, + .gpio = 0, + }, { + .type = CX231XX_VMUX_COMPOSITE1, + .vmux = CX231XX_VIN_2_1, + .amux = CX231XX_AMUX_LINE_IN, + .gpio = 0, + }, { + .type = CX231XX_VMUX_SVIDEO, + .vmux = CX231XX_VIN_1_1 | (CX231XX_VIN_1_2 << 8 ) | + CX25840_SVIDEO_ON, + .amux = CX231XX_AMUX_LINE_IN, + .gpio = 0, + } }, + }, + + [CX231XX_BOARD_CNXT_RDU_250] = { + .name = "Conexant Hybrid TV - RDU250", + .valid = CX231XX_BOARD_VALIDATED, + .tuner_type = TUNER_XC5000, + .tuner_addr = 0x61, + .tuner_gpio = RDE250_XCV_TUNER, + .tuner_sif_gpio = 0x05, + .tuner_scl_gpio = 0x1a, + .tuner_sda_gpio = 0x1b, + .decoder = CX231XX_AVDECODER, + .demod_xfer_mode = 0, + .ctl_pin_status_mask = 0xFFFFFFC4, + .agc_analog_digital_select_gpio = 0x0c, + .gpio_pin_status_mask = 0x4001000, + .tuner_i2c_master = 1, + .demod_i2c_master = 2, + .has_dvb = 1, + .demod_addr = 0x32, + .norm = V4L2_STD_NTSC, + + .input = { { + .type = CX231XX_VMUX_TELEVISION, + .vmux = CX231XX_VIN_3_1, + .amux = CX231XX_AMUX_VIDEO, + .gpio = 0, + }, { + .type = CX231XX_VMUX_COMPOSITE1, + .vmux = CX231XX_VIN_2_1, + .amux = CX231XX_AMUX_LINE_IN, + .gpio = 0, + }, { + .type = CX231XX_VMUX_SVIDEO, + .vmux = CX231XX_VIN_1_1 | (CX231XX_VIN_1_2 << 8 ) | + CX25840_SVIDEO_ON, + .amux = CX231XX_AMUX_LINE_IN, + .gpio = 0, + } }, + }, +}; +const unsigned int cx231xx_bcount = ARRAY_SIZE(cx231xx_boards); + +/* table of devices that work with this driver */ +struct usb_device_id cx231xx_id_table [] = { + { USB_DEVICE(0x0572, 0x58A0), + .driver_info = CX231XX_BOARD_UNKNOWN }, + { USB_DEVICE(0x0572, 0x58A2), + .driver_info = CX231XX_BOARD_CNXT_RDE_250 }, + { USB_DEVICE(0x0572, 0x5A3C), + .driver_info = CX231XX_BOARD_CNXT_RDU_250 }, + { }, +}; +MODULE_DEVICE_TABLE(usb, cx231xx_id_table); + +/* cx231xx_tuner_callback + * will be used to reset XC5000 tuner using GPIO pin + */ + +int cx231xx_tuner_callback(void *ptr, int component, int command, int arg) +{ + int rc = 0; + struct cx231xx *dev = ptr; + + if (dev->tuner_type == TUNER_XC5000) { + if (command == XC5000_TUNER_RESET) { + cx231xx_info("Tuner Call back : RESET : command %d : tuner type %d \n", + command, dev->tuner_type); + + cx231xx_set_gpio_value(dev, dev->board.tuner_gpio->bit,1); + msleep(10); + cx231xx_set_gpio_value(dev, dev->board.tuner_gpio->bit,0); + msleep(330); + cx231xx_set_gpio_value(dev, dev->board.tuner_gpio->bit,1); + msleep(10); + } + } + return rc; +} +EXPORT_SYMBOL_GPL(cx231xx_tuner_callback); + +static void inline cx231xx_set_model(struct cx231xx *dev) +{ + memcpy(&dev->board, &cx231xx_boards[dev->model], sizeof(dev->board)); +} + +/* Since cx231xx_pre_card_setup() requires a proper dev->model, + * this won't work for boards with generic PCI IDs + */ +void cx231xx_pre_card_setup(struct cx231xx *dev) +{ + + cx231xx_set_model(dev); + + cx231xx_info("Identified as %s (card=%d)\n", + dev->board.name, dev->model); + + /* Do card specific if any */ + switch (dev->model) { + case CX231XX_BOARD_CNXT_RDE_250: + /* do card specific GPIO settings if required */ + cx231xx_info("Precard: Board is Conexnat RDE 250\n"); + /* set the direction for GPIO pins */ + cx231xx_set_gpio_direction(dev, dev->board.tuner_gpio->bit,1); + cx231xx_set_gpio_value(dev, dev->board.tuner_gpio->bit,1); + cx231xx_set_gpio_direction(dev, dev->board.tuner_sif_gpio,1); + break; + case CX231XX_BOARD_CNXT_RDU_250: + /* do card specific GPIO settings if required */ + cx231xx_info("Precard: Board is Conexnat RDU 250\n"); + /* set the direction for GPIO pins */ + cx231xx_set_gpio_direction(dev, dev->board.tuner_gpio->bit,1); + cx231xx_set_gpio_value(dev, dev->board.tuner_gpio->bit,1); + cx231xx_set_gpio_direction(dev, dev->board.tuner_sif_gpio,1); + break; + } + + /* request some modules if any required */ + + /* reset the Tuner */ + cx231xx_gpio_set(dev, dev->board.tuner_gpio); + + /* set the mode to Analog mode initially */ + cx231xx_set_mode(dev, CX231XX_ANALOG_MODE); + + /* Unlock device */ + /* cx231xx_set_mode(dev, CX231XX_SUSPEND); */ + +} + +#if 0 /* Keep */ + +static void cx231xx_config_tuner(struct cx231xx *dev) +{ + struct tuner_setup tun_setup; + struct v4l2_frequency f; + + if (dev->tuner_type == TUNER_ABSENT) + return; + + tun_setup.mode_mask = T_ANALOG_TV | T_RADIO; + tun_setup.type = dev->tuner_type; + tun_setup.addr = dev->tuner_addr; + tun_setup.tuner_callback = cx231xx_tuner_callback; + + cx231xx_i2c_call_clients(&dev->i2c_bus[1], TUNER_SET_TYPE_ADDR, &tun_setup); +#if 0 /* Keep */ + if (tun_setup.type == TUNER_XC5000) { + static struct xc2028_ctrl ctrl = { + .fname = XC5000_DEFAULT_FIRMWARE, + .max_len = 64, + .demod = 0; + }; + struct v4l2_priv_tun_config cfg = { + .tuner = dev->tuner_type, + .priv = &ctrl, + }; + cx231xx_i2c_call_clients(&dev->i2c_bus[1], TUNER_SET_CONFIG, &cfg); + } +#endif + + /* configure tuner */ + f.tuner = 0; + f.type = V4L2_TUNER_ANALOG_TV; + f.frequency = 9076; /* just a magic number */ + dev->ctl_freq = f.frequency; + cx231xx_i2c_call_clients(&dev->i2c_bus[1], VIDIOC_S_FREQUENCY, &f); +} + +#endif + +/* ----------------------------------------------------------------------- */ +void cx231xx_set_ir(struct cx231xx *dev, struct IR_i2c *ir) +{ + if (disable_ir) { + ir->get_key = NULL; + return ; + } + + /* detect & configure */ + switch (dev->model) { + + case CX231XX_BOARD_CNXT_RDE_250: + break; + case CX231XX_BOARD_CNXT_RDU_250: + break; + default: + break; + } +} + +void cx231xx_card_setup(struct cx231xx *dev) +{ + cx231xx_set_model(dev); + + dev->tuner_type = cx231xx_boards[dev->model].tuner_type; + if (cx231xx_boards[dev->model].tuner_addr) + dev->tuner_addr = cx231xx_boards[dev->model].tuner_addr; + + cx231xx_info(": tuner type %d, tuner address %d \n", + dev->tuner_type, dev->tuner_addr); + + /* Do card specific if any */ + switch (dev->model) { + case CX231XX_BOARD_CNXT_RDE_250: + /* do card specific GPIO settings if required */ + cx231xx_info("Board is Conexnat RDE 250\n"); + break; + case CX231XX_BOARD_CNXT_RDU_250: + /* do card specific GPIO settings if required */ + cx231xx_info("Board is Conexnat RDU 250\n"); + break; + } + + if (dev->board.valid == CX231XX_BOARD_NOT_VALIDATED) { + cx231xx_errdev("\n\n"); + cx231xx_errdev("The support for this board weren't " + "valid yet.\n"); + cx231xx_errdev("Please send a report of having this working\n"); + cx231xx_errdev("not to V4L mailing list (and/or to other " + "addresses)\n\n"); + } + + + /* request some modules */ + if (dev->board.decoder == CX231XX_AVDECODER) { + cx231xx_info(": Requesting cx25840 module\n"); + request_module("cx25840"); + } +#if 0 /* Keep */ + if (dev->board.tuner_type != TUNER_ABSENT) { + cx231xx_info(": Requesting Tuner module\n"); + request_module("tuner"); + } + + cx231xx_config_tuner(dev); + + /* TBD IR will be added later */ + cx231xx_ir_init(dev); +#endif +} + + + +/* + * cx231xx_config() + * inits registers with sane defaults + */ +int cx231xx_config(struct cx231xx *dev) +{ + /* TBD need to add cx231xx specific code */ + dev->mute = 1; /* maybe not the right place... */ + dev->volume = 0x1f; + + return 0; +} + +/* + * cx231xx_config_i2c() + * configure i2c attached devices + */ +void cx231xx_config_i2c(struct cx231xx *dev) +{ + struct v4l2_routing route; + + route.input = INPUT(dev->video_input)->vmux; + route.output = 0; + + cx231xx_i2c_call_clients(&dev->i2c_bus[0], VIDIOC_STREAMON, NULL); +} + +/* + * cx231xx_realease_resources() + * unregisters the v4l2,i2c and usb devices + * called when the device gets disconected or at module unload +*/ +void cx231xx_release_resources(struct cx231xx *dev) +{ + +#if 0 /* Keep */ /* TBD IR related */ + if (dev->ir) + cx231xx_ir_fini(dev); +#endif + + cx231xx_release_analog_resources(dev); + + cx231xx_remove_from_devlist(dev); + + cx231xx_dev_uninit(dev); + + usb_put_dev(dev->udev); + + /* Mark device as unused */ + cx231xx_devused &= ~(1<devno); +} + + +/* + * cx231xx_init_dev() + * allocates and inits the device structs, registers i2c bus and v4l device + */ +static int cx231xx_init_dev(struct cx231xx **devhandle, struct usb_device *udev, + int minor) +{ + struct cx231xx *dev = *devhandle; + int retval = -ENOMEM; + int errCode; + unsigned int maxh, maxw; + + dev->udev = udev; + mutex_init(&dev->lock); + mutex_init(&dev->ctrl_urb_lock); + mutex_init(&dev->gpio_i2c_lock); + + spin_lock_init(&dev->video_mode.slock); + spin_lock_init(&dev->vbi_mode.slock); + spin_lock_init(&dev->sliced_cc_mode.slock); + + init_waitqueue_head(&dev->open); + init_waitqueue_head(&dev->wait_frame); + init_waitqueue_head(&dev->wait_stream); + + dev->cx231xx_read_ctrl_reg = cx231xx_read_ctrl_reg; + dev->cx231xx_write_ctrl_reg = cx231xx_write_ctrl_reg; + dev->cx231xx_send_usb_command = cx231xx_send_usb_command; + dev->cx231xx_gpio_i2c_read = cx231xx_gpio_i2c_read; + dev->cx231xx_gpio_i2c_write = cx231xx_gpio_i2c_write; + + /* Query cx231xx to find what pcb config it is related to */ + initialize_cx231xx(dev); + + /* Cx231xx pre card setup */ + cx231xx_pre_card_setup(dev); + + errCode = cx231xx_config(dev); + if (errCode) { + cx231xx_errdev("error configuring device\n"); + return -ENOMEM; + } + + /* set default norm */ + dev->norm = dev->board.norm; + + /* register i2c bus */ + errCode = cx231xx_dev_init(dev); + if (errCode < 0) { + cx231xx_errdev("%s: cx231xx_i2c_register - errCode [%d]!\n", + __func__, errCode); + return errCode; + } + + /* Do board specific init */ + cx231xx_card_setup(dev); + + /* configure the device */ + cx231xx_config_i2c(dev); + + maxw = norm_maxw(dev); + maxh = norm_maxh(dev); + + /* set default image size */ + dev->width = maxw; + dev->height = maxh; + dev->interlaced = 0; + dev->hscale = 0; + dev->vscale = 0; + dev->video_input = 0; + + errCode = cx231xx_config(dev); + if (errCode < 0) { + cx231xx_errdev("%s: cx231xx_config - errCode [%d]!\n", + __func__, errCode); + return errCode; + } + + /* init video dma queues */ + INIT_LIST_HEAD(&dev->video_mode.vidq.active); + INIT_LIST_HEAD(&dev->video_mode.vidq.queued); + + /* init vbi dma queues */ + INIT_LIST_HEAD(&dev->vbi_mode.vidq.active); + INIT_LIST_HEAD(&dev->vbi_mode.vidq.queued); + + /* Reset other chips required if they are tied up with GPIO pins */ + + cx231xx_add_into_devlist(dev); + + retval = cx231xx_register_analog_devices(dev); + if (retval < 0) { + cx231xx_release_resources(dev); + goto fail_reg_devices; + } + + cx231xx_init_extension(dev); + + return 0; + +fail_reg_devices: + mutex_unlock(&dev->lock); + return retval; +} + +#if defined(CONFIG_MODULES) && defined(MODULE) +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20) +static void request_module_async(void *ptr) +{ + struct cx231xx *dev = (struct cx231xx *)ptr; +#else +static void request_module_async(struct work_struct *work) +{ + struct cx231xx *dev = container_of(work, + struct cx231xx, request_module_wk); +#endif + + + if (dev->has_alsa_audio) + request_module("cx231xx-alsa"); + + if (dev->board.has_dvb) + request_module("cx231xx-dvb"); + +} + +static void request_modules(struct cx231xx *dev) +{ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20) + INIT_WORK(&dev->request_module_wk, request_module_async, + (void *)dev); +#else + INIT_WORK(&dev->request_module_wk, request_module_async); +#endif + schedule_work(&dev->request_module_wk); +} +#else +#define request_modules(dev) +#endif /* CONFIG_MODULES */ + + + +/* + * cx231xx_usb_probe() + * checks for supported devices + */ +static int cx231xx_usb_probe(struct usb_interface *interface, + const struct usb_device_id *id) +{ + struct usb_device *udev; + struct usb_interface *uif; + struct cx231xx *dev = NULL; + int retval = -ENODEV; + int nr, ifnum; + int i, isoc_pipe = 0; + char *speed; + char descr[255] = ""; + struct usb_interface *lif = NULL; + int skip_interface = 0; + struct usb_interface_assoc_descriptor *assoc_desc; + + udev = usb_get_dev(interface_to_usbdev(interface)); + ifnum = interface->altsetting[0].desc.bInterfaceNumber; + + cx231xx_info(": Interface Number %d\n", ifnum); + + /* Interface number 0 - IR interface */ + if(ifnum == 0 ){ + /* Check to see next free device and mark as used */ + nr = find_first_zero_bit(&cx231xx_devused, CX231XX_MAXBOARDS); + cx231xx_devused |= 1<= CX231XX_MAXBOARDS) { + cx231xx_info(": Supports only %i cx231xx boards.\n", + CX231XX_MAXBOARDS); + cx231xx_devused &= ~(1<name, 29, "cx231xx #%d", nr); + dev->devno = nr; + dev->model = id->driver_info; + dev->video_mode.alt = -1; + dev->interface_count++; + + /* reset gpio dir and value */ + dev->gpio_dir = 0; + dev->gpio_val = 0; + dev->xc_fw_load_done = 0; + dev->has_alsa_audio = 1; + dev->power_mode = -1; + + dev->vbi_or_sliced_cc_mode = 0; /* 0 - vbi ; 1 -sliced cc mode */ + + /* get maximum no.of IAD interfaces */ + assoc_desc = udev->actconfig->intf_assoc[0]; + dev->max_iad_interface_count = assoc_desc->bInterfaceCount; + cx231xx_info(": Found IAD interface count %d\n", dev->max_iad_interface_count); + + /* init CIR module TBD */ + + /* store the current interface */ + lif = interface; + + } + else if(ifnum == 1 ){ + + /* Get dev structure first */ + dev = usb_get_intfdata(udev->actconfig->interface[0]); + if(dev == NULL){ + cx231xx_err(DRIVER_NAME ": out of first interface!\n"); + return -ENODEV; + } + + /* store the interface 0 back */ + lif = udev->actconfig->interface[0]; + + /* increment interface count */ + dev->interface_count++; + + /* get device number */ + nr = dev->devno; + + assoc_desc = udev->actconfig->intf_assoc[0]; + if(assoc_desc->bFirstInterface == ifnum){ + cx231xx_info(": Found IAD interface match: AV Descriptor Start!! \n"); + } else { + cx231xx_err(DRIVER_NAME " Not found matching interface\n"); + return -ENODEV; + } + + } + else if(ifnum >= 2) { + /* Get dev structure first */ + dev = usb_get_intfdata(udev->actconfig->interface[0]); + if(dev == NULL){ + cx231xx_err(DRIVER_NAME ": out of first interface!\n"); + return -ENODEV; + } + + /* store the interface 0 back */ + lif = udev->actconfig->interface[0]; + + /* increment interface count */ + dev->interface_count++; + + /* get device number */ + nr = dev->devno; + + /* set skip interface */ + if((dev->interface_count -1) != dev->max_iad_interface_count ) + skip_interface = 1; /* set skipping */ + else{ + cx231xx_info(": Found IAD interface number match with AV Device number!! \n"); + } + } + + switch (udev->speed) { + case USB_SPEED_LOW: + speed = "1.5"; + break; + case USB_SPEED_UNKNOWN: + case USB_SPEED_FULL: + speed = "12"; + break; + case USB_SPEED_HIGH: + speed = "480"; + break; + default: + speed = "unknown"; + } + + if (udev->manufacturer) + strlcpy(descr, udev->manufacturer, sizeof(descr)); + + if (udev->product) { + if (*descr) + strlcat(descr, " ", sizeof(descr)); + strlcat(descr, udev->product, sizeof(descr)); + } + if (*descr) + strlcat(descr, " ", sizeof(descr)); + + cx231xx_info("New device %s@ %s Mbps " + "(%04x:%04x, interface %d, class %d)\n", + descr, + speed, + le16_to_cpu(udev->descriptor.idVendor), + le16_to_cpu(udev->descriptor.idProduct), + ifnum, + interface->altsetting->desc.bInterfaceNumber); + + /* AV device initialization */ + if((dev->interface_count -1) == dev->max_iad_interface_count ) { + cx231xx_info(" Calling init_dev\n"); + /* allocate device struct */ + retval = cx231xx_init_dev(&dev, udev, nr); + if (retval) { + cx231xx_devused &= ~(1<devno); + kfree(dev); + + return retval; + } + + /* compute alternate max packet sizes for video */ + uif = udev->actconfig->interface[dev->current_pcb_config.hs_config_info[0].interface_info.video_index+1]; + + dev->video_mode.end_point_addr = le16_to_cpu(uif->altsetting[0].endpoint[isoc_pipe].desc.bEndpointAddress); + + dev->video_mode.num_alt = uif->num_altsetting; + cx231xx_info(": EndPoint Addr 0x%x, Alternate settings: %i\n", dev->video_mode.end_point_addr, + dev->video_mode.num_alt); + dev->video_mode.alt_max_pkt_size = kmalloc(32 * dev->video_mode.num_alt, GFP_KERNEL); + + if (dev->video_mode.alt_max_pkt_size == NULL) { + cx231xx_errdev("out of memory!\n"); + cx231xx_devused &= ~(1<video_mode.num_alt ; i++) { + u16 tmp = le16_to_cpu(uif->altsetting[i].endpoint[isoc_pipe].desc. + wMaxPacketSize); + dev->video_mode.alt_max_pkt_size[i] = + (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1); + cx231xx_info("Alternate setting %i, max size= %i\n", i, + dev->video_mode.alt_max_pkt_size[i]); + } + + + /* compute alternate max packet sizes for vbi */ + uif = udev->actconfig->interface[dev->current_pcb_config.hs_config_info[0].interface_info.vanc_index+1]; + + dev->vbi_mode.end_point_addr = + le16_to_cpu(uif->altsetting[0].endpoint[isoc_pipe].desc.bEndpointAddress); + + dev->vbi_mode.num_alt = uif->num_altsetting; + cx231xx_info(": EndPoint Addr 0x%x, Alternate settings: %i\n", dev->vbi_mode.end_point_addr, + dev->vbi_mode.num_alt); + dev->vbi_mode.alt_max_pkt_size = kmalloc(32 * dev->vbi_mode.num_alt, GFP_KERNEL); + + if (dev->vbi_mode.alt_max_pkt_size == NULL) { + cx231xx_errdev("out of memory!\n"); + cx231xx_devused &= ~(1<vbi_mode.num_alt ; i++) { + u16 tmp = le16_to_cpu(uif->altsetting[i].endpoint[isoc_pipe].desc. + wMaxPacketSize); + dev->vbi_mode.alt_max_pkt_size[i] = + (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1); + cx231xx_info("Alternate setting %i, max size= %i\n", i, + dev->vbi_mode.alt_max_pkt_size[i]); + } + + /* compute alternate max packet sizes for sliced CC */ + uif = udev->actconfig->interface[dev->current_pcb_config.hs_config_info[0].interface_info.hanc_index+1]; + + dev->sliced_cc_mode.end_point_addr = + le16_to_cpu(uif->altsetting[0].endpoint[isoc_pipe].desc.bEndpointAddress); + + dev->sliced_cc_mode.num_alt = uif->num_altsetting; + cx231xx_info(": EndPoint Addr 0x%x, Alternate settings: %i\n", dev->sliced_cc_mode.end_point_addr, + dev->sliced_cc_mode.num_alt); + dev->sliced_cc_mode.alt_max_pkt_size = kmalloc(32 * dev->sliced_cc_mode.num_alt, GFP_KERNEL); + + if (dev->sliced_cc_mode.alt_max_pkt_size == NULL) { + cx231xx_errdev("out of memory!\n"); + cx231xx_devused &= ~(1<sliced_cc_mode.num_alt ; i++) { + u16 tmp = le16_to_cpu(uif->altsetting[i].endpoint[isoc_pipe].desc. + wMaxPacketSize); + dev->sliced_cc_mode.alt_max_pkt_size[i] = + (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1); + cx231xx_info("Alternate setting %i, max size= %i\n", i, + dev->sliced_cc_mode.alt_max_pkt_size[i]); + } + + if(dev->current_pcb_config.ts1_source != 0xff ) { + + /* compute alternate max packet sizes for TS1 */ + uif = udev->actconfig->interface[dev->current_pcb_config.hs_config_info[0].interface_info.ts1_index+1]; + + dev->ts1_mode.end_point_addr = + le16_to_cpu(uif->altsetting[0].endpoint[isoc_pipe].desc.bEndpointAddress); + + dev->ts1_mode.num_alt = uif->num_altsetting; + cx231xx_info(": EndPoint Addr 0x%x, Alternate settings: %i\n", dev->ts1_mode.end_point_addr, + dev->ts1_mode.num_alt); + dev->ts1_mode.alt_max_pkt_size = kmalloc(32 * dev->ts1_mode.num_alt, GFP_KERNEL); + + if (dev->ts1_mode.alt_max_pkt_size == NULL) { + cx231xx_errdev("out of memory!\n"); + cx231xx_devused &= ~(1<ts1_mode.num_alt ; i++) { + u16 tmp = le16_to_cpu(uif->altsetting[i].endpoint[isoc_pipe].desc. + wMaxPacketSize); + dev->ts1_mode.alt_max_pkt_size[i] = + (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1); + cx231xx_info("Alternate setting %i, max size= %i\n", i, + dev->ts1_mode.alt_max_pkt_size[i]); + } + } + + } + + /* save our data pointer in this interface device */ + usb_set_intfdata(lif, dev); + + /* load other modules required */ + if((dev->interface_count -1) == dev->max_iad_interface_count ) + { + cx231xx_info("Calling request modules\n"); + request_modules(dev); + } + + if(skip_interface ) { + cx231xx_info("Skipping the interface\n"); + return -ENODEV; + } + + return 0; +} + +/* + * cx231xx_usb_disconnect() + * called when the device gets diconencted + * video device will be unregistered on v4l2_close in case it is still open + */ +static void cx231xx_usb_disconnect(struct usb_interface *interface) +{ + struct cx231xx *dev; + + dev = usb_get_intfdata(interface); + usb_set_intfdata(interface, NULL); + + if (!dev) + return; + + /* wait until all current v4l2 io is finished then deallocate + resources */ + mutex_lock(&dev->lock); + + wake_up_interruptible_all(&dev->open); + + if (dev->users) { + cx231xx_warn + ("device /dev/video%d is open! Deregistration and memory " + "deallocation are deferred on close.\n", + dev->vdev->num); + + dev->state |= DEV_MISCONFIGURED; + cx231xx_uninit_isoc(dev); + dev->state |= DEV_DISCONNECTED; + wake_up_interruptible(&dev->wait_frame); + wake_up_interruptible(&dev->wait_stream); + } else { + dev->state |= DEV_DISCONNECTED; + cx231xx_release_resources(dev); + } + + cx231xx_close_extension(dev); + + mutex_unlock(&dev->lock); + + if (!dev->users) { + kfree(dev->video_mode.alt_max_pkt_size); + kfree(dev->vbi_mode.alt_max_pkt_size); + kfree(dev->sliced_cc_mode.alt_max_pkt_size); + kfree(dev->ts1_mode.alt_max_pkt_size); + kfree(dev); + } +} + +static struct usb_driver cx231xx_usb_driver = { + .name = "cx231xx", + .probe = cx231xx_usb_probe, + .disconnect = cx231xx_usb_disconnect, + .id_table = cx231xx_id_table, +}; + +static int __init cx231xx_module_init(void) +{ + int result; + + printk(KERN_INFO DRIVER_NAME " v4l2 driver version %d.%d.%d loaded\n", + (CX231XX_VERSION_CODE >> 16) & 0xff, + (CX231XX_VERSION_CODE >> 8) & 0xff, CX231XX_VERSION_CODE & 0xff); + + /* register this driver with the USB subsystem */ + result = usb_register(&cx231xx_usb_driver); + if (result) + cx231xx_err(DRIVER_NAME + " usb_register failed. Error number %d.\n", result); + + return result; +} + +static void __exit cx231xx_module_exit(void) +{ + /* deregister this driver with the USB subsystem */ + usb_deregister(&cx231xx_usb_driver); +} + +module_init(cx231xx_module_init); +module_exit(cx231xx_module_exit); diff --git a/linux/drivers/media/video/cx231xx/cx231xx-conf-reg.h b/linux/drivers/media/video/cx231xx/cx231xx-conf-reg.h new file mode 100644 index 000000000..608867745 --- /dev/null +++ b/linux/drivers/media/video/cx231xx/cx231xx-conf-reg.h @@ -0,0 +1,491 @@ +/* + cx231xx_conf-reg.h - driver for Conexant Cx23100/101/102 USB + video capture devices + + Copyright (C) 2008 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + + +#ifndef _POLARIS_REG_H_ +#define _POLARIS_REG_H_ + +#define BOARD_CFG_STAT 0x0 +#define TS_MODE_REG 0x4 +#define TS1_CFG_REG 0x8 +#define TS1_LENGTH_REG 0xc +#define TS2_CFG_REG 0x10 +#define TS2_LENGTH_REG 0x14 +#define EP_MODE_SET 0x18 +#define CIR_PWR_PTN1 0x1c +#define CIR_PWR_PTN2 0x20 +#define CIR_PWR_PTN3 0x24 +#define CIR_PWR_MASK0 0x28 +#define CIR_PWR_MASK1 0x2c +#define CIR_PWR_MASK2 0x30 +#define CIR_GAIN 0x34 +#define CIR_CAR_REG 0x38 +#define CIR_OT_CFG1 0x40 +#define CIR_OT_CFG2 0x44 +#define PWR_CTL_EN 0x74 + +/* Polaris Endpoints capture mask for register EP_MODE_SET */ +#define ENABLE_EP1 0x01 /* Bit[0]=1 */ +#define ENABLE_EP2 0x02 /* Bit[1]=1 */ +#define ENABLE_EP3 0x04 /* Bit[2]=1 */ +#define ENABLE_EP4 0x08 /* Bit[3]=1 */ +#define ENABLE_EP5 0x10 /* Bit[4]=1 */ +#define ENABLE_EP6 0x20 /* Bit[5]=1 */ + +/* Bit definition for register PWR_CTL_EN */ +#define PWR_MODE_MASK 0x17f +#define PWR_AV_EN 0x08 /* bit3 */ +#define PWR_ISO_EN 0x40 /* bit6 */ +#define PWR_AV_MODE 0x30 /* bit4,5 */ +#define PWR_TUNER_EN 0x04 /* bit2 */ +#define PWR_DEMOD_EN 0x02 /* bit1 */ +#define I2C_DEMOD_EN 0x01 /* bit0 */ +#define PWR_RESETOUT_EN 0x100 /* bit8 */ + +typedef enum{ + POLARIS_AVMODE_DEFAULT = 0, + POLARIS_AVMODE_DIGITAL = 0x10, + POLARIS_AVMODE_ANALOGT_TV = 0x20, + POLARIS_AVMODE_ENXTERNAL_AV = 0x30, + +}AV_MODE; + +/* Colibri Registers */ + +#define SINGLE_ENDED 0x0 +#define LOW_IF 0x4 +#define EU_IF 0x9 +#define US_IF 0xa + + + +#define SUP_BLK_TUNE1 0x00 +#define SUP_BLK_TUNE2 0x01 +#define SUP_BLK_TUNE3 0x02 +#define SUP_BLK_XTAL 0x03 +#define SUP_BLK_PLL1 0x04 +#define SUP_BLK_PLL2 0x05 +#define SUP_BLK_PLL3 0x06 +#define SUP_BLK_REF 0x07 +#define SUP_BLK_PWRDN 0x08 +#define SUP_BLK_TESTPAD 0x09 +#define ADC_COM_INT5_STAB_REF 0x0a +#define ADC_COM_QUANT 0x0b +#define ADC_COM_BIAS1 0x0c +#define ADC_COM_BIAS2 0x0d +#define ADC_COM_BIAS3 0x0e +#define TESTBUS_CTRL 0x12 + +#define ADC_STATUS_CH1 0x20 +#define ADC_STATUS_CH2 0x40 +#define ADC_STATUS_CH3 0x60 + +#define ADC_STATUS2_CH1 0x21 +#define ADC_STATUS2_CH2 0x41 +#define ADC_STATUS2_CH3 0x61 + +#define ADC_CAL_ATEST_CH1 0x22 +#define ADC_CAL_ATEST_CH2 0x42 +#define ADC_CAL_ATEST_CH3 0x62 + +#define ADC_PWRDN_CLAMP_CH1 0x23 +#define ADC_PWRDN_CLAMP_CH2 0x43 +#define ADC_PWRDN_CLAMP_CH3 0x63 + +#define ADC_CTRL_DAC23_CH1 0x24 +#define ADC_CTRL_DAC23_CH2 0x44 +#define ADC_CTRL_DAC23_CH3 0x64 + +#define ADC_CTRL_DAC1_CH1 0x25 +#define ADC_CTRL_DAC1_CH2 0x45 +#define ADC_CTRL_DAC1_CH3 0x65 + +#define ADC_DCSERVO_DEM_CH1 0x26 +#define ADC_DCSERVO_DEM_CH2 0x46 +#define ADC_DCSERVO_DEM_CH3 0x66 + +#define ADC_FB_FRCRST_CH1 0x27 +#define ADC_FB_FRCRST_CH2 0x47 +#define ADC_FB_FRCRST_CH3 0x67 + +#define ADC_INPUT_CH1 0x28 +#define ADC_INPUT_CH2 0x48 +#define ADC_INPUT_CH3 0x68 +#define INPUT_SEL_MASK 0x30 /* [5:4] in_sel */ + +#define ADC_NTF_PRECLMP_EN_CH1 0x29 +#define ADC_NTF_PRECLMP_EN_CH2 0x49 +#define ADC_NTF_PRECLMP_EN_CH3 0x69 + +#define ADC_QGAIN_RES_TRM_CH1 0x2a +#define ADC_QGAIN_RES_TRM_CH2 0x4a +#define ADC_QGAIN_RES_TRM_CH3 0x6a + +#define ADC_SOC_PRECLMP_TERM_CH1 0x2b +#define ADC_SOC_PRECLMP_TERM_CH2 0x4b +#define ADC_SOC_PRECLMP_TERM_CH3 0x6b + +#define TESTBUS_CTRL_CH1 0x32 +#define TESTBUS_CTRL_CH2 0x52 +#define TESTBUS_CTRL_CH3 0x72 + +/****************************************************************************** + * DIF registers * + ******************************************************************************/ +#define DIRECT_IF_REVB_BASE 0x00300 + +/*****************************************************************************/ +#define DIF_PLL_FREQ_WORD (DIRECT_IF_REVB_BASE + 0x00000000) /* Reg Size 32 */ +/*****************************************************************************/ +#define FLD_DIF_PLL_LOCK 0x80000000 +/* Reserved [30:29] */ +#define FLD_DIF_PLL_FREE_RUN 0x10000000 +#define FLD_DIF_PLL_FREQ 0x0FFFFFFF + +/*****************************************************************************/ +#define DIF_PLL_CTRL (DIRECT_IF_REVB_BASE + 0x00000004) /* Reg Size 32 */ +/*****************************************************************************/ +#define FLD_DIF_KD_PD 0xFF000000 +/* Reserved [23:20] */ +#define FLD_DIF_KDS_PD 0x000F0000 +#define FLD_DIF_KI_PD 0x0000FF00 +/* Reserved [7:4] */ +#define FLD_DIF_KIS_PD 0x0000000F + +/*****************************************************************************/ +#define DIF_PLL_CTRL1 (DIRECT_IF_REVB_BASE + 0x00000008) /* Reg Size 32 */ +/*****************************************************************************/ +#define FLD_DIF_KD_FD 0xFF000000 +/* Reserved [23:20] */ +#define FLD_DIF_KDS_FD 0x000F0000 +#define FLD_DIF_KI_FD 0x0000FF00 +#define FLD_DIF_SIG_PROP_SZ 0x000000F0 +#define FLD_DIF_KIS_FD 0x0000000F + +/*****************************************************************************/ +#define DIF_PLL_CTRL2 (DIRECT_IF_REVB_BASE + 0x0000000C) /* Reg Size 32 */ +/*****************************************************************************/ +#define FLD_DIF_PLL_AGC_REF 0xFFF00000 +#define FLD_DIF_PLL_AGC_KI 0x000F0000 +/* Reserved [15] */ +#define FLD_DIF_FREQ_LIMIT 0x00007000 +#define FLD_DIF_K_FD 0x00000F00 +#define FLD_DIF_DOWNSMPL_FD 0x000000FF + +/*****************************************************************************/ +#define DIF_PLL_CTRL3 (DIRECT_IF_REVB_BASE + 0x00000010) /* Reg Size 32 */ +/*****************************************************************************/ +/* Reserved [31:16] */ +#define FLD_DIF_PLL_AGC_EN 0x00008000 +/* Reserved [14:12] */ +#define FLD_DIF_PLL_MAN_GAIN 0x00000FFF + +/*****************************************************************************/ +#define DIF_AGC_IF_REF (DIRECT_IF_REVB_BASE + 0x00000014) /* Reg Size 32 */ +/*****************************************************************************/ +#define FLD_DIF_K_AGC_RF 0xF0000000 +#define FLD_DIF_K_AGC_IF 0x0F000000 +#define FLD_DIF_K_AGC_INT 0x00F00000 +/* Reserved [19:12] */ +#define FLD_DIF_IF_REF 0x00000FFF + +/*****************************************************************************/ +#define DIF_AGC_CTRL_IF (DIRECT_IF_REVB_BASE + 0x00000018) /* Reg Size 32 */ +/*****************************************************************************/ +#define FLD_DIF_IF_MAX 0xFF000000 +#define FLD_DIF_IF_MIN 0x00FF0000 +#define FLD_DIF_IF_AGC 0x0000FFFF + +/*****************************************************************************/ +#define DIF_AGC_CTRL_INT (DIRECT_IF_REVB_BASE + 0x0000001C) /* Reg Size 32 */ +/*****************************************************************************/ +#define FLD_DIF_INT_MAX 0xFF000000 +#define FLD_DIF_INT_MIN 0x00FF0000 +#define FLD_DIF_INT_AGC 0x0000FFFF + +/*****************************************************************************/ +#define DIF_AGC_CTRL_RF (DIRECT_IF_REVB_BASE + 0x00000020) /* Reg Size 32 */ +/*****************************************************************************/ +#define FLD_DIF_RF_MAX 0xFF000000 +#define FLD_DIF_RF_MIN 0x00FF0000 +#define FLD_DIF_RF_AGC 0x0000FFFF + +/*****************************************************************************/ +#define DIF_AGC_IF_INT_CURRENT (DIRECT_IF_REVB_BASE + 0x00000024) /* Reg Size 32 */ +/*****************************************************************************/ +#define FLD_DIF_IF_AGC_IN 0xFFFF0000 +#define FLD_DIF_INT_AGC_IN 0x0000FFFF + +/*****************************************************************************/ +#define DIF_AGC_RF_CURRENT (DIRECT_IF_REVB_BASE + 0x00000028) /* Reg Size 32 */ +/*****************************************************************************/ +/* Reserved [31:16] */ +#define FLD_DIF_RF_AGC_IN 0x0000FFFF + +/*****************************************************************************/ +#define DIF_VIDEO_AGC_CTRL (DIRECT_IF_REVB_BASE + 0x0000002C) /* Reg Size 32 */ +/*****************************************************************************/ +#define FLD_DIF_AFD 0xC0000000 +#define FLD_DIF_K_VID_AGC 0x30000000 +#define FLD_DIF_LINE_LENGTH 0x0FFF0000 +#define FLD_DIF_AGC_GAIN 0x0000FFFF + +/*****************************************************************************/ +#define DIF_VID_AUD_OVERRIDE (DIRECT_IF_REVB_BASE + 0x00000030) /* Reg Size 32 */ +/*****************************************************************************/ +#define FLD_DIF_AUDIO_AGC_OVERRIDE 0x80000000 +/* Reserved [30:30] */ +#define FLD_DIF_AUDIO_MAN_GAIN 0x3F000000 +/* Reserved [23:17] */ +#define FLD_DIF_VID_AGC_OVERRIDE 0x00010000 +#define FLD_DIF_VID_MAN_GAIN 0x0000FFFF + +/*****************************************************************************/ +#define DIF_AV_SEP_CTRL (DIRECT_IF_REVB_BASE + 0x00000034) /* Reg Size 32 */ +/*****************************************************************************/ +#define FLD_DIF_LPF_FREQ 0xC0000000 +#define FLD_DIF_AV_PHASE_INC 0x3F000000 +#define FLD_DIF_AUDIO_FREQ 0x00FFFFFF + +/*****************************************************************************/ +#define DIF_COMP_FLT_CTRL (DIRECT_IF_REVB_BASE + 0x00000038) /* Reg Size 32 */ +/*****************************************************************************/ +/* Reserved [31:24] */ +#define FLD_DIF_IIR23_R2 0x00FF0000 +#define FLD_DIF_IIR23_R1 0x0000FF00 +#define FLD_DIF_IIR1_R1 0x000000FF + +/*****************************************************************************/ +#define DIF_MISC_CTRL (DIRECT_IF_REVB_BASE + 0x0000003C) /* Reg Size 32 */ +/*****************************************************************************/ +#define FLD_DIF_DIF_BYPASS 0x80000000 +#define FLD_DIF_FM_NYQ_GAIN 0x40000000 +#define FLD_DIF_RF_AGC_ENA 0x20000000 +#define FLD_DIF_INT_AGC_ENA 0x10000000 +#define FLD_DIF_IF_AGC_ENA 0x08000000 +#define FLD_DIF_FORCE_RF_IF_LOCK 0x04000000 +#define FLD_DIF_VIDEO_AGC_ENA 0x02000000 +#define FLD_DIF_RF_AGC_INV 0x01000000 +#define FLD_DIF_INT_AGC_INV 0x00800000 +#define FLD_DIF_IF_AGC_INV 0x00400000 +#define FLD_DIF_SPEC_INV 0x00200000 +#define FLD_DIF_AUD_FULL_BW 0x00100000 +#define FLD_DIF_AUD_SRC_SEL 0x00080000 +/* Reserved [18] */ +#define FLD_DIF_IF_FREQ 0x00030000 +/* Reserved [15:14] */ +#define FLD_DIF_TIP_OFFSET 0x00003F00 +/* Reserved [7:5] */ +#define FLD_DIF_DITHER_ENA 0x00000010 +/* Reserved [3:1] */ +#define FLD_DIF_RF_IF_LOCK 0x00000001 + +/*****************************************************************************/ +#define DIF_SRC_PHASE_INC (DIRECT_IF_REVB_BASE + 0x00000040) /* Reg Size 32 */ +/*****************************************************************************/ +/* Reserved [31:29] */ +#define FLD_DIF_PHASE_INC 0x1FFFFFFF + +/*****************************************************************************/ +#define DIF_SRC_GAIN_CONTROL (DIRECT_IF_REVB_BASE + 0x00000044) /* Reg Size 32 */ +/*****************************************************************************/ +/* Reserved [31:16] */ +#define FLD_DIF_SRC_KI 0x0000FF00 +#define FLD_DIF_SRC_KD 0x000000FF + +/*****************************************************************************/ +#define DIF_BPF_COEFF01 (DIRECT_IF_REVB_BASE + 0x00000048) /* Reg Size 32 */ +/*****************************************************************************/ +/* Reserved [31:19] */ +#define FLD_DIF_BPF_COEFF_0 0x00070000 +/* Reserved [15:4] */ +#define FLD_DIF_BPF_COEFF_1 0x0000000F + +/*****************************************************************************/ +#define DIF_BPF_COEFF23 (DIRECT_IF_REVB_BASE + 0x0000004c) /* Reg Size 32 */ +/*****************************************************************************/ +/* Reserved [31:22] */ +#define FLD_DIF_BPF_COEFF_2 0x003F0000 +/* Reserved [15:7] */ +#define FLD_DIF_BPF_COEFF_3 0x0000007F + +/*****************************************************************************/ +#define DIF_BPF_COEFF45 (DIRECT_IF_REVB_BASE + 0x00000050) /* Reg Size 32 */ +/*****************************************************************************/ +/* Reserved [31:24] */ +#define FLD_DIF_BPF_COEFF_4 0x00FF0000 +/* Reserved [15:8] */ +#define FLD_DIF_BPF_COEFF_5 0x000000FF + +/*****************************************************************************/ +#define DIF_BPF_COEFF67 (DIRECT_IF_REVB_BASE + 0x00000054) /* Reg Size 32 */ +/*****************************************************************************/ +/* Reserved [31:25] */ +#define FLD_DIF_BPF_COEFF_6 0x01FF0000 +/* Reserved [15:9] */ +#define FLD_DIF_BPF_COEFF_7 0x000001FF + +/*****************************************************************************/ +#define DIF_BPF_COEFF89 (DIRECT_IF_REVB_BASE + 0x00000058) /* Reg Size 32 */ +/*****************************************************************************/ +/* Reserved [31:26] */ +#define FLD_DIF_BPF_COEFF_8 0x03FF0000 +/* Reserved [15:10] */ +#define FLD_DIF_BPF_COEFF_9 0x000003FF + +/*****************************************************************************/ +#define DIF_BPF_COEFF1011 (DIRECT_IF_REVB_BASE + 0x0000005C) /* Reg Size 32 */ +/*****************************************************************************/ +/* Reserved [31:27] */ +#define FLD_DIF_BPF_COEFF_10 0x07FF0000 +/* Reserved [15:11] */ +#define FLD_DIF_BPF_COEFF_11 0x000007FF + +/*****************************************************************************/ +#define DIF_BPF_COEFF1213 (DIRECT_IF_REVB_BASE + 0x00000060) /* Reg Size 32 */ +/*****************************************************************************/ +/* Reserved [31:27] */ +#define FLD_DIF_BPF_COEFF_12 0x07FF0000 +/* Reserved [15:12] */ +#define FLD_DIF_BPF_COEFF_13 0x00000FFF + +/*****************************************************************************/ +#define DIF_BPF_COEFF1415 (DIRECT_IF_REVB_BASE + 0x00000064) /* Reg Size 32 */ +/*****************************************************************************/ +/* Reserved [31:28] */ +#define FLD_DIF_BPF_COEFF_14 0x0FFF0000 +/* Reserved [15:12] */ +#define FLD_DIF_BPF_COEFF_15 0x00000FFF + +/*****************************************************************************/ +#define DIF_BPF_COEFF1617 (DIRECT_IF_REVB_BASE + 0x00000068) /* Reg Size 32 */ +/*****************************************************************************/ +/* Reserved [31:29] */ +#define FLD_DIF_BPF_COEFF_16 0x1FFF0000 +/* Reserved [15:13] */ +#define FLD_DIF_BPF_COEFF_17 0x00001FFF + +/*****************************************************************************/ +#define DIF_BPF_COEFF1819 (DIRECT_IF_REVB_BASE + 0x0000006C) /* Reg Size 32 */ +/*****************************************************************************/ +/* Reserved [31:29] */ +#define FLD_DIF_BPF_COEFF_18 0x1FFF0000 +/* Reserved [15:13] */ +#define FLD_DIF_BPF_COEFF_19 0x00001FFF + +/*****************************************************************************/ +#define DIF_BPF_COEFF2021 (DIRECT_IF_REVB_BASE + 0x00000070) /* Reg Size 32 */ +/*****************************************************************************/ +/* Reserved [31:29] */ +#define FLD_DIF_BPF_COEFF_20 0x1FFF0000 +/* Reserved [15:14] */ +#define FLD_DIF_BPF_COEFF_21 0x00003FFF + +/*****************************************************************************/ +#define DIF_BPF_COEFF2223 (DIRECT_IF_REVB_BASE + 0x00000074) /* Reg Size 32 */ +/*****************************************************************************/ +/* Reserved [31:30] */ +#define FLD_DIF_BPF_COEFF_22 0x3FFF0000 +/* Reserved [15:14] */ +#define FLD_DIF_BPF_COEFF_23 0x00003FFF + +/*****************************************************************************/ +#define DIF_BPF_COEFF2425 (DIRECT_IF_REVB_BASE + 0x00000078) /* Reg Size 32 */ +/*****************************************************************************/ +/* Reserved [31:30] */ +#define FLD_DIF_BPF_COEFF_24 0x3FFF0000 +/* Reserved [15:14] */ +#define FLD_DIF_BPF_COEFF_25 0x00003FFF + +/*****************************************************************************/ +#define DIF_BPF_COEFF2627 (DIRECT_IF_REVB_BASE + 0x0000007C) /* Reg Size 32 */ +/*****************************************************************************/ +/* Reserved [31:30] */ +#define FLD_DIF_BPF_COEFF_26 0x3FFF0000 +/* Reserved [15:14] */ +#define FLD_DIF_BPF_COEFF_27 0x00003FFF + +/*****************************************************************************/ +#define DIF_BPF_COEFF2829 (DIRECT_IF_REVB_BASE + 0x00000080) /* Reg Size 32 */ +/*****************************************************************************/ +/* Reserved [31:30] */ +#define FLD_DIF_BPF_COEFF_28 0x3FFF0000 +/* Reserved [15:14] */ +#define FLD_DIF_BPF_COEFF_29 0x00003FFF + +/*****************************************************************************/ +#define DIF_BPF_COEFF3031 (DIRECT_IF_REVB_BASE + 0x00000084) /* Reg Size 32 */ +/*****************************************************************************/ +/* Reserved [31:30] */ +#define FLD_DIF_BPF_COEFF_30 0x3FFF0000 +/* Reserved [15:14] */ +#define FLD_DIF_BPF_COEFF_31 0x00003FFF + +/*****************************************************************************/ +#define DIF_BPF_COEFF3233 (DIRECT_IF_REVB_BASE + 0x00000088) /* Reg Size 32 */ +/*****************************************************************************/ +/* Reserved [31:30] */ +#define FLD_DIF_BPF_COEFF_32 0x3FFF0000 +/* Reserved [15:14] */ +#define FLD_DIF_BPF_COEFF_33 0x00003FFF + +/*****************************************************************************/ +#define DIF_BPF_COEFF3435 (DIRECT_IF_REVB_BASE + 0x0000008C) /* Reg Size 32 */ +/*****************************************************************************/ +/* Reserved [31:30] */ +#define FLD_DIF_BPF_COEFF_34 0x3FFF0000 +/* Reserved [15:14] */ +#define FLD_DIF_BPF_COEFF_35 0x00003FFF + +/*****************************************************************************/ +#define DIF_BPF_COEFF36 (DIRECT_IF_REVB_BASE + 0x00000090) /* Reg Size 32 */ +/*****************************************************************************/ +/* Reserved [31:30] */ +#define FLD_DIF_BPF_COEFF_36 0x3FFF0000 +/* Reserved [15:0] */ + +/*****************************************************************************/ +#define DIF_RPT_VARIANCE (DIRECT_IF_REVB_BASE + 0x00000094) /* Reg Size 32 */ +/*****************************************************************************/ +/* Reserved [31:20] */ +#define FLD_DIF_RPT_VARIANCE 0x000FFFFF + +/*****************************************************************************/ +#define DIF_SOFT_RST_CTRL_REVB (DIRECT_IF_REVB_BASE + 0x00000098) /* Reg Size 32 */ +/*****************************************************************************/ +/* Reserved [31:8] */ +#define FLD_DIF_DIF_SOFT_RST 0x00000080 +#define FLD_DIF_DIF_REG_RST_MSK 0x00000040 +#define FLD_DIF_AGC_RST_MSK 0x00000020 +#define FLD_DIF_CMP_RST_MSK 0x00000010 +#define FLD_DIF_AVS_RST_MSK 0x00000008 +#define FLD_DIF_NYQ_RST_MSK 0x00000004 +#define FLD_DIF_DIF_SRC_RST_MSK 0x00000002 +#define FLD_DIF_PLL_RST_MSK 0x00000001 + +/*****************************************************************************/ +#define DIF_PLL_FREQ_ERR (DIRECT_IF_REVB_BASE + 0x0000009C) /* Reg Size 32 */ +/*****************************************************************************/ +/* Reserved [31:25] */ +#define FLD_DIF_CTL_IP 0x01FFFFFF + + +#endif diff --git a/linux/drivers/media/video/cx231xx/cx231xx-core.c b/linux/drivers/media/video/cx231xx/cx231xx-core.c new file mode 100644 index 000000000..44bb8660a --- /dev/null +++ b/linux/drivers/media/video/cx231xx/cx231xx-core.c @@ -0,0 +1,1197 @@ +/* + cx231xx-core.c - driver for Conexant Cx23100/101/102 USB video capture devices + + Copyright (C) 2008 + Based on em28xx driver + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include + +#include "cx231xx.h" +#include "cx231xx-reg.h" + +/* #define ENABLE_DEBUG_ISOC_FRAMES */ + +static unsigned int core_debug; +module_param(core_debug,int,0644); +MODULE_PARM_DESC(core_debug,"enable debug messages [core]"); + +#define cx231xx_coredbg(fmt, arg...) do {\ + if (core_debug) \ + printk(KERN_INFO "%s %s :"fmt, \ + dev->name, __func__ , ##arg); } while (0) + +static unsigned int reg_debug; +module_param(reg_debug,int,0644); +MODULE_PARM_DESC(reg_debug,"enable debug messages [URB reg]"); + +#define cx231xx_regdbg(fmt, arg...) do {\ + if (reg_debug) \ + printk(KERN_INFO "%s %s :"fmt, \ + dev->name, __func__ , ##arg); } while (0) + +static int alt = CX231XX_PINOUT; +module_param(alt, int, 0644); +MODULE_PARM_DESC(alt, "alternate setting to use for video endpoint"); + +/* FIXME */ +#define cx231xx_isocdbg(fmt, arg...) do {\ + if (core_debug) \ + printk(KERN_INFO "%s %s :"fmt, \ + dev->name, __func__ , ##arg); } while (0) + + + +/************************************************************************************ +* Device control list functions * +*************************************************************************************/ + +static LIST_HEAD(cx231xx_devlist); +static DEFINE_MUTEX(cx231xx_devlist_mutex); + +struct cx231xx *cx231xx_get_device(int minor, + enum v4l2_buf_type *fh_type, + int *has_radio) +{ + struct cx231xx *h, *dev = NULL; + + *fh_type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + *has_radio = 0; + + mutex_lock(&cx231xx_devlist_mutex); + list_for_each_entry(h, &cx231xx_devlist, devlist) { + if (h->vdev->minor == minor) + dev = h; + if (h->vbi_dev->minor == minor) { + dev = h; + *fh_type = V4L2_BUF_TYPE_VBI_CAPTURE; + } + if (h->radio_dev && + h->radio_dev->minor == minor) { + dev = h; + *has_radio = 1; + } + } + mutex_unlock(&cx231xx_devlist_mutex); + + return dev; +} + +/* + * cx231xx_realease_resources() + * unregisters the v4l2,i2c and usb devices + * called when the device gets disconected or at module unload +*/ +void cx231xx_remove_from_devlist(struct cx231xx *dev) +{ + mutex_lock(&cx231xx_devlist_mutex); + list_del(&dev->devlist); + mutex_unlock(&cx231xx_devlist_mutex); +}; + +void cx231xx_add_into_devlist(struct cx231xx *dev) +{ + mutex_lock(&cx231xx_devlist_mutex); + list_add_tail(&dev->devlist, &cx231xx_devlist); + mutex_unlock(&cx231xx_devlist_mutex); +}; + + + + +static LIST_HEAD(cx231xx_extension_devlist); +static DEFINE_MUTEX(cx231xx_extension_devlist_lock); + +int cx231xx_register_extension(struct cx231xx_ops *ops) +{ + struct cx231xx *dev = NULL; + + mutex_lock(&cx231xx_devlist_mutex); + mutex_lock(&cx231xx_extension_devlist_lock); + list_add_tail(&ops->next, &cx231xx_extension_devlist); + list_for_each_entry(dev, &cx231xx_devlist, devlist) { + if (dev) + ops->init(dev); + } + cx231xx_info("Cx231xx: Initialized (%s) extension\n", ops->name); + mutex_unlock(&cx231xx_extension_devlist_lock); + mutex_unlock(&cx231xx_devlist_mutex); + return 0; +} +EXPORT_SYMBOL(cx231xx_register_extension); + +void cx231xx_unregister_extension(struct cx231xx_ops *ops) +{ + struct cx231xx *dev = NULL; + + mutex_lock(&cx231xx_devlist_mutex); + list_for_each_entry(dev, &cx231xx_devlist, devlist) { + if (dev) + ops->fini(dev); + } + + mutex_lock(&cx231xx_extension_devlist_lock); + cx231xx_info("Cx231xx: Removed (%s) extension\n", ops->name); + list_del(&ops->next); + mutex_unlock(&cx231xx_extension_devlist_lock); + mutex_unlock(&cx231xx_devlist_mutex); +} +EXPORT_SYMBOL(cx231xx_unregister_extension); + + +void cx231xx_init_extension(struct cx231xx *dev) +{ + struct cx231xx_ops *ops = NULL; + + mutex_lock(&cx231xx_extension_devlist_lock); + if (!list_empty(&cx231xx_extension_devlist)) { + list_for_each_entry(ops, &cx231xx_extension_devlist, next) { + if (ops->init) + ops->init(dev); + } + } + mutex_unlock(&cx231xx_extension_devlist_lock); +} + +void cx231xx_close_extension(struct cx231xx *dev) +{ + struct cx231xx_ops *ops = NULL; + + mutex_lock(&cx231xx_extension_devlist_lock); + if (!list_empty(&cx231xx_extension_devlist)) { + list_for_each_entry(ops, &cx231xx_extension_devlist, next) { + if (ops->fini) + ops->fini(dev); + } + } + mutex_unlock(&cx231xx_extension_devlist_lock); +} + +/************************************************************************************ +* U S B related functions * +*************************************************************************************/ +int cx231xx_send_usb_command(struct cx231xx_i2c *i2c_bus, + struct cx231xx_i2c_xfer_data *req_data) +{ + int status = 0; + struct cx231xx *dev = i2c_bus->dev; + VENDOR_REQUEST_IN ven_req; + + u8 saddr_len = 0; + u8 _i2c_period = 0; + u8 _i2c_nostop = 0; + u8 _i2c_reserve = 0; + + /* Get the I2C period, nostop and reserve parameters */ + _i2c_period = i2c_bus->i2c_period; + _i2c_nostop = i2c_bus->i2c_nostop; + _i2c_reserve = i2c_bus->i2c_reserve; + + saddr_len = req_data->saddr_len; + + /* Set wValue */ + if(saddr_len == 1) /* need check saddr_len == 0 */ + ven_req.wValue = req_data->dev_addr<<9|_i2c_period<<4|saddr_len<<2| + _i2c_nostop<<1|I2C_SYNC|_i2c_reserve<<6; + else + ven_req.wValue = req_data->dev_addr<<9|_i2c_period<<4|saddr_len<<2| + _i2c_nostop<<1|I2C_SYNC|_i2c_reserve<<6; + + /* set channel number */ + if(req_data->direction & I2C_M_RD) + ven_req.bRequest = i2c_bus->nr + 4; /* channel number, for read, + spec required channel_num +4 */ + else + ven_req.bRequest = i2c_bus->nr; /* channel number, */ + + /* set index value */ + switch(saddr_len){ + case 0: + ven_req.wIndex = 0; /* need check */ + break; + case 1: + ven_req.wIndex = (req_data->saddr_dat & 0xff); + break; + case 2: + ven_req.wIndex = req_data->saddr_dat; + break; + } + + /* set wLength value */ + ven_req.wLength = req_data->buf_size; + + /* set bData value */ + ven_req.bData = 0; + + /* set the direction */ + if(req_data->direction){ + ven_req.direction = USB_DIR_IN; + memset(req_data->p_buffer, 0x00, ven_req.wLength); + } + else + ven_req.direction = USB_DIR_OUT; + + /* set the buffer for read / write */ + ven_req.pBuff = req_data->p_buffer; + + +#if 0 + { + int i = 0; + + cx231xx_isocdbg(": USB Control Pipe Request: I2C Bus#%d\n",i2c_bus->nr); + cx231xx_isocdbg("bRequest = %x : ", ven_req.bRequest); + cx231xx_isocdbg("wValue = %x : ", ven_req.wValue); + cx231xx_isocdbg("wIndex = %x : ",ven_req.wIndex); + cx231xx_isocdbg("wLength = %x\n",ven_req.wLength); + cx231xx_isocdbg("pBuff : "); + for(i =0; i 0 ) && (i % 10 == 0 ) ) + cx231xx_isocdbg("\n "); + } + cx231xx_isocdbg("\n\n"); + } +#endif + + /* call common vendor command request */ + status = cx231xx_send_vendor_cmd(dev, &ven_req); + if (status < 0) { + cx231xx_info("UsbInterface::sendCommand, output buffer failed with status -%d\n", status); + } + + return status; +} + +EXPORT_SYMBOL_GPL(cx231xx_send_usb_command); +/* + * cx231xx_read_ctrl_reg() + * reads data from the usb device specifying bRequest and wValue + */ +int cx231xx_read_ctrl_reg(struct cx231xx *dev, u8 req, u16 reg, + char *buf, int len) +{ + u8 val = 0; + int ret; + int pipe = usb_rcvctrlpipe(dev->udev, 0); + + if (dev->state & DEV_DISCONNECTED) + return -ENODEV; + + if (len > URB_MAX_CTRL_SIZE) + return -EINVAL; + + switch(len) + { + case 1: + val = ENABLE_ONE_BYTE; + break; + case 2: + val = ENABLE_TWE_BYTE; + break; + case 3: + val = ENABLE_THREE_BYTE; + break; + case 4: + val = ENABLE_FOUR_BYTE; + break; + default: + val = 0xFF; /* invalid option */ + } + + if(val == 0xFF) + return -EINVAL; + + if (reg_debug) { + cx231xx_isocdbg("(pipe 0x%08x): " + "IN: %02x %02x %02x %02x %02x %02x %02x %02x ", + pipe, + USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, + req, 0, val, + reg & 0xff, reg >> 8, + len & 0xff, len >> 8); + } + + /* mutex_lock(&dev->ctrl_urb_lock); */ + ret = usb_control_msg(dev->udev, pipe, req, + USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, + val, reg, dev->urb_buf, len, HZ); + if (ret < 0) { + cx231xx_isocdbg(" failed!\n"); + /* mutex_unlock(&dev->ctrl_urb_lock); */ + return ret; + } + + if (len) + memcpy(buf, dev->urb_buf, len); + + /* mutex_unlock(&dev->ctrl_urb_lock); */ + + if (reg_debug) { + int byte; + + cx231xx_isocdbg("<<<"); + for (byte = 0; byte < len; byte++) + cx231xx_isocdbg(" %02x", (unsigned char)buf[byte]); + cx231xx_isocdbg("\n"); + } + + return ret; +} + + +int cx231xx_send_vendor_cmd(struct cx231xx *dev, VENDOR_REQUEST_IN *ven_req) +{ + int ret; + int pipe = 0; + + if (dev->state & DEV_DISCONNECTED) + return -ENODEV; + + if ((ven_req->wLength > URB_MAX_CTRL_SIZE)) + return -EINVAL; + + if(ven_req->direction) + pipe = usb_rcvctrlpipe(dev->udev, 0); + else + pipe = usb_sndctrlpipe(dev->udev, 0); + + + if (reg_debug) { + int byte; + + cx231xx_isocdbg("(pipe 0x%08x): " + "OUT: %02x %02x %02x %04x %04x %04x >>>", + pipe, + ven_req->direction | USB_TYPE_VENDOR | USB_RECIP_DEVICE, + ven_req->bRequest, 0, ven_req->wValue, + ven_req->wIndex, + ven_req->wLength); + + for (byte = 0; byte < ven_req->wLength; byte++) + cx231xx_isocdbg(" %02x", (unsigned char)ven_req->pBuff[byte]); + cx231xx_isocdbg("\n"); + } + + /* mutex_lock(&dev->ctrl_urb_lock); */ + ret = usb_control_msg(dev->udev, pipe, ven_req->bRequest, + ven_req->direction | USB_TYPE_VENDOR | USB_RECIP_DEVICE, + ven_req->wValue, ven_req->wIndex, ven_req->pBuff, ven_req->wLength, HZ); + /* mutex_unlock(&dev->ctrl_urb_lock); */ + + return ret; +} + +/* + * cx231xx_write_ctrl_reg() + * sends data to the usb device, specifying bRequest + */ +int cx231xx_write_ctrl_reg(struct cx231xx *dev, u8 req, u16 reg, char *buf, + int len) +{ + u8 val = 0; + int ret; + int pipe = usb_sndctrlpipe(dev->udev, 0); + + if (dev->state & DEV_DISCONNECTED) + return -ENODEV; + + if ((len < 1) || (len > URB_MAX_CTRL_SIZE)) + return -EINVAL; + + switch(len) + { + case 1: + val = ENABLE_ONE_BYTE; + break; + case 2: + val = ENABLE_TWE_BYTE; + break; + case 3: + val = ENABLE_THREE_BYTE; + break; + case 4: + val = ENABLE_FOUR_BYTE; + break; + default: + val = 0xFF; /* invalid option */ + } + + if(val == 0xFF) + return -EINVAL; + + if (reg_debug) { + int byte; + + cx231xx_isocdbg("(pipe 0x%08x): " + "OUT: %02x %02x %02x %02x %02x %02x %02x %02x >>>", + pipe, + USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, + req, 0, val, + reg & 0xff, reg >> 8, + len & 0xff, len >> 8); + + for (byte = 0; byte < len; byte++) + cx231xx_isocdbg(" %02x", (unsigned char)buf[byte]); + cx231xx_isocdbg("\n"); + } + + /* mutex_lock(&dev->ctrl_urb_lock); */ + memcpy(dev->urb_buf, buf, len); + ret = usb_control_msg(dev->udev, pipe, req, + USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, + val, reg, dev->urb_buf, len, HZ); + /* mutex_unlock(&dev->ctrl_urb_lock); */ + + return ret; +} + + +/************************************************************************************ +* USB Alternate Setting functions * +*************************************************************************************/ + +int cx231xx_set_video_alternate(struct cx231xx *dev) +{ + int errCode, prev_alt = dev->video_mode.alt; + unsigned int min_pkt_size = dev->width * 2 + 4; + u32 usb_interface_index = 0; + + /* When image size is bigger than a certain value, + the frame size should be increased, otherwise, only + green screen will be received. + */ + if (dev->width * 2 * dev->height > 720 * 240 * 2) + min_pkt_size *= 2; + + if(dev->width > 360) { + /* resolutions: 720,704,640 */ + dev->video_mode.alt = 3; + } else if(dev->width > 180) { + /* resolutions: 360,352,320,240 */ + dev->video_mode.alt = 2; + } else if(dev->width > 0) { + /* resolutions: 180,176,160,128,88 */ + dev->video_mode.alt = 1; + } else { + /* Change to alt0 BULK to release USB bandwidth */ + dev->video_mode.alt = 0; + } + + /* Get the correct video interface Index */ + usb_interface_index = dev->current_pcb_config.hs_config_info[0].interface_info.video_index+1; + + if (dev->video_mode.alt != prev_alt) { + cx231xx_coredbg("minimum isoc packet size: %u (alt=%d)\n", + min_pkt_size, dev->video_mode.alt); + dev->video_mode.max_pkt_size = dev->video_mode.alt_max_pkt_size[dev->video_mode.alt]; + cx231xx_coredbg("setting alternate %d with wMaxPacketSize=%u\n", + dev->video_mode.alt, dev->video_mode.max_pkt_size); + cx231xx_info(" setting alternate %d with wMaxPacketSize=%u , Interface = %d\n", + dev->video_mode.alt, dev->video_mode.max_pkt_size, usb_interface_index); + errCode = usb_set_interface(dev->udev, usb_interface_index, dev->video_mode.alt); + if (errCode < 0) { + cx231xx_errdev("cannot change alternate number to %d (error=%i)\n", + dev->video_mode.alt, errCode); + return errCode; + } + } + return 0; +} + +int cx231xx_set_alt_setting(struct cx231xx *dev, u8 index, u8 alt) +{ + int status = 0; + u32 usb_interface_index = 0; + u32 max_pkt_size = 0; + + switch(index) { + case INDEX_TS1: + usb_interface_index = dev->current_pcb_config.hs_config_info[0].interface_info.ts1_index+1; + dev->video_mode.alt = alt; + if(dev->ts1_mode.alt_max_pkt_size != NULL) + max_pkt_size = dev->ts1_mode.max_pkt_size = dev->ts1_mode.alt_max_pkt_size[dev->ts1_mode.alt]; + break; + case INDEX_TS2: + usb_interface_index = dev->current_pcb_config.hs_config_info[0].interface_info.ts2_index+1; + break; + case INDEX_AUDIO: + usb_interface_index = dev->current_pcb_config.hs_config_info[0].interface_info.audio_index+1; + dev->adev.alt = alt; + if( dev->adev.alt_max_pkt_size != NULL) + max_pkt_size = dev->adev.max_pkt_size = dev->adev.alt_max_pkt_size[dev->adev.alt]; + break; + case INDEX_VIDEO: + usb_interface_index = dev->current_pcb_config.hs_config_info[0].interface_info.video_index+1; + dev->video_mode.alt = alt; + if(dev->video_mode.alt_max_pkt_size != NULL) + max_pkt_size = dev->video_mode.max_pkt_size = dev->video_mode.alt_max_pkt_size[dev->video_mode.alt]; + break; + case INDEX_VANC: + usb_interface_index = dev->current_pcb_config.hs_config_info[0].interface_info.vanc_index+1; + dev->vbi_mode.alt = alt; + if(dev->vbi_mode.alt_max_pkt_size != NULL) + max_pkt_size = dev->vbi_mode.max_pkt_size = dev->vbi_mode.alt_max_pkt_size[dev->vbi_mode.alt]; + break; + case INDEX_HANC: + usb_interface_index = dev->current_pcb_config.hs_config_info[0].interface_info.hanc_index+1; + dev->sliced_cc_mode.alt = alt; + if(dev->sliced_cc_mode.alt_max_pkt_size != NULL) + max_pkt_size = dev->sliced_cc_mode.max_pkt_size = dev->sliced_cc_mode.alt_max_pkt_size[dev->sliced_cc_mode.alt]; + break; + default: + break; + } + + if(alt > 0 && max_pkt_size == 0 ) { + cx231xx_errdev("cannot change interface %d alternate number to %d : Max. Pkt size is ZERO\n", + usb_interface_index, alt); + return -1; + } + + cx231xx_info(" setting alternate %d with wMaxPacketSize=%u , Interface = %d\n", + alt, max_pkt_size, usb_interface_index); + + if(usb_interface_index > 0 ) { + status = usb_set_interface(dev->udev, usb_interface_index, alt); + if (status < 0) { + cx231xx_errdev("cannot change interface %d alternate number to %d (error=%i)\n", + usb_interface_index, alt, status); + return status; + } + } + + return status; +} +EXPORT_SYMBOL_GPL(cx231xx_set_alt_setting); + +int cx231xx_gpio_set(struct cx231xx *dev, struct cx231xx_reg_seq *gpio) +{ + int rc = 0; + + if (!gpio) + return rc; + + /* Send GPIO reset sequences specified at board entry */ + while (gpio->sleep >= 0) { + rc = cx231xx_set_gpio_value(dev, gpio->bit, + gpio->val); + if (rc < 0) + return rc; + + if (gpio->sleep > 0) + msleep(gpio->sleep); + + gpio++; + } + return rc; +} + +int cx231xx_set_mode(struct cx231xx *dev, enum cx231xx_mode set_mode) +{ + if (dev->mode == set_mode) + return 0; + + if (set_mode == CX231XX_SUSPEND) { + /* Set the chip in power saving mode */ + dev->mode = set_mode; + } + + /* Resource is locked */ + if (dev->mode != CX231XX_SUSPEND) + return -EINVAL; + + dev->mode = set_mode; + + if (dev->mode == CX231XX_DIGITAL_MODE) { + /* Set Digital power mode */ + } else { + /* Set Analog Power mode*/ + } + return 0; +} +EXPORT_SYMBOL_GPL(cx231xx_set_mode); + +/************************************************************************************ +* URB Streaming functions * +*************************************************************************************/ + +/* + * IRQ callback, called by URB callback + */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19) +static void cx231xx_irq_callback(struct urb *urb, struct pt_regs *regs) +#else +static void cx231xx_irq_callback(struct urb *urb) +#endif +{ + struct cx231xx_dmaqueue *dma_q = urb->context; + struct cx231xx_video_mode *vmode = container_of(dma_q, struct cx231xx_video_mode, vidq); + struct cx231xx *dev = container_of(vmode, struct cx231xx, video_mode); + int rc, i; + + + switch (urb->status) { + case 0: /* success */ + case -ETIMEDOUT: /* NAK */ + break; + case -ECONNRESET: /* kill */ + case -ENOENT: + case -ESHUTDOWN: + return; + default: /* error */ + cx231xx_isocdbg("urb completition error %d.\n", urb->status); + break; + } + + /* Copy data from URB */ + spin_lock(&dev->video_mode.slock); + rc = dev->video_mode.isoc_ctl.isoc_copy(dev, urb); + spin_unlock(&dev->video_mode.slock); + + /* Reset urb buffers */ + for (i = 0; i < urb->number_of_packets; i++) { + urb->iso_frame_desc[i].status = 0; + urb->iso_frame_desc[i].actual_length = 0; + } + urb->status = 0; + + urb->status = usb_submit_urb(urb, GFP_ATOMIC); + if (urb->status) { + cx231xx_isocdbg("urb resubmit failed (error=%i)\n", + urb->status); + } +} + +/* + * Stop and Deallocate URBs + */ +void cx231xx_uninit_isoc(struct cx231xx *dev) +{ + struct urb *urb; + int i; + + cx231xx_isocdbg("cx231xx: called cx231xx_uninit_isoc\n"); + + dev->video_mode.isoc_ctl.nfields = -1; + for (i = 0; i < dev->video_mode.isoc_ctl.num_bufs; i++) { + urb = dev->video_mode.isoc_ctl.urb[i]; + if (urb) { + if (!irqs_disabled()) + usb_kill_urb(urb); + else + usb_unlink_urb(urb); + + if (dev->video_mode.isoc_ctl.transfer_buffer[i]) { + usb_buffer_free(dev->udev, + urb->transfer_buffer_length, + dev->video_mode.isoc_ctl.transfer_buffer[i], + urb->transfer_dma); + } + usb_free_urb(urb); + dev->video_mode.isoc_ctl.urb[i] = NULL; + } + dev->video_mode.isoc_ctl.transfer_buffer[i] = NULL; + } + + kfree(dev->video_mode.isoc_ctl.urb); + kfree(dev->video_mode.isoc_ctl.transfer_buffer); + + dev->video_mode.isoc_ctl.urb = NULL; + dev->video_mode.isoc_ctl.transfer_buffer = NULL; + dev->video_mode.isoc_ctl.num_bufs = 0; + + cx231xx_capture_start(dev, 0, Raw_Video); +} +EXPORT_SYMBOL_GPL(cx231xx_uninit_isoc); + +/* + * Allocate URBs and start IRQ + */ +int cx231xx_init_isoc(struct cx231xx *dev, int max_packets, + int num_bufs, int max_pkt_size, + int (*isoc_copy) (struct cx231xx *dev, struct urb *urb)) +{ + struct cx231xx_dmaqueue *dma_q = &dev->video_mode.vidq; + int i; + int sb_size, pipe; + struct urb *urb; + int j, k; + int rc; + + cx231xx_isocdbg("cx231xx: called cx231xx_prepare_isoc\n"); + + dev->video_input = dev->video_input > 2?2:dev->video_input; + + cx231xx_info("Setting Video mux to %d\n",dev->video_input); + video_mux(dev, dev->video_input); + + + /* De-allocates all pending stuff */ + cx231xx_uninit_isoc(dev); + + dev->video_mode.isoc_ctl.isoc_copy = isoc_copy; + dev->video_mode.isoc_ctl.num_bufs = num_bufs; + dma_q->pos = 0; + dma_q->is_partial_line = 0; + dma_q->last_sav = 0; + dma_q->current_field = -1; + dma_q->field1_done = 0; + dma_q->lines_per_field = dev->height/2; + dma_q->bytes_left_in_line = dev->width << 1; + dma_q->lines_completed = 0; + for(i = 0; i < 8 ; i++) + dma_q->partial_buf[i] = 0; + + dev->video_mode.isoc_ctl.urb = kzalloc(sizeof(void *)*num_bufs, GFP_KERNEL); + if (!dev->video_mode.isoc_ctl.urb) { + cx231xx_errdev("cannot alloc memory for usb buffers\n"); + return -ENOMEM; + } + + dev->video_mode.isoc_ctl.transfer_buffer = kzalloc(sizeof(void *)*num_bufs, + GFP_KERNEL); + if (!dev->video_mode.isoc_ctl.transfer_buffer) { + cx231xx_errdev("cannot allocate memory for usbtransfer\n"); + kfree(dev->video_mode.isoc_ctl.urb); + return -ENOMEM; + } + + dev->video_mode.isoc_ctl.max_pkt_size = max_pkt_size; + dev->video_mode.isoc_ctl.buf = NULL; + + sb_size = max_packets * dev->video_mode.isoc_ctl.max_pkt_size; + + /* allocate urbs and transfer buffers */ + for (i = 0; i < dev->video_mode.isoc_ctl.num_bufs; i++) { + urb = usb_alloc_urb(max_packets, GFP_KERNEL); + if (!urb) { + cx231xx_err("cannot alloc isoc_ctl.urb %i\n", i); + cx231xx_uninit_isoc(dev); + return -ENOMEM; + } + dev->video_mode.isoc_ctl.urb[i] = urb; + + dev->video_mode.isoc_ctl.transfer_buffer[i] = usb_buffer_alloc(dev->udev, + sb_size, GFP_KERNEL, &urb->transfer_dma); + if (!dev->video_mode.isoc_ctl.transfer_buffer[i]) { + cx231xx_err("unable to allocate %i bytes for transfer" + " buffer %i%s\n", + sb_size, i, + in_interrupt()?" while in int":""); + cx231xx_uninit_isoc(dev); + return -ENOMEM; + } + memset(dev->video_mode.isoc_ctl.transfer_buffer[i], 0, sb_size); + + pipe = usb_rcvisocpipe(dev->udev, dev->video_mode.end_point_addr); + + usb_fill_int_urb(urb, dev->udev, pipe, + dev->video_mode.isoc_ctl.transfer_buffer[i], sb_size, + cx231xx_irq_callback, dma_q, 1); + + urb->number_of_packets = max_packets; + urb->transfer_flags = URB_ISO_ASAP; + + k = 0; + for (j = 0; j < max_packets; j++) { + urb->iso_frame_desc[j].offset = k; + urb->iso_frame_desc[j].length = + dev->video_mode.isoc_ctl.max_pkt_size; + k += dev->video_mode.isoc_ctl.max_pkt_size; + } + } + + init_waitqueue_head(&dma_q->wq); + + + /* submit urbs and enables IRQ */ + for (i = 0; i < dev->video_mode.isoc_ctl.num_bufs; i++) { + rc = usb_submit_urb(dev->video_mode.isoc_ctl.urb[i], GFP_ATOMIC); + if (rc) { + cx231xx_err("submit of urb %i failed (error=%i)\n", i, + rc); + cx231xx_uninit_isoc(dev); + return rc; + } + } + + cx231xx_capture_start(dev, 1, Raw_Video); + + return 0; +} +EXPORT_SYMBOL_GPL(cx231xx_init_isoc); + +/************************************************************************************ +* Device Init/UnInit functions * +*************************************************************************************/ +int cx231xx_dev_init(struct cx231xx *dev) +{ + int errCode = 0; + + /* Initialize I2C bus */ + + /* External Master 1 Bus */ + dev->i2c_bus[0].nr = 0; + dev->i2c_bus[0].dev = dev; + dev->i2c_bus[0].i2c_period = I2C_SPEED_1M; /* 1MHz */ + dev->i2c_bus[0].i2c_nostop = 0; + dev->i2c_bus[0].i2c_reserve = 0; + + /* External Master 2 Bus */ + dev->i2c_bus[1].nr = 1; + dev->i2c_bus[1].dev = dev; + dev->i2c_bus[1].i2c_period = I2C_SPEED_1M; /* 1MHz */ + dev->i2c_bus[1].i2c_nostop = 0; + dev->i2c_bus[1].i2c_reserve = 0; + + /* Internal Master 3 Bus */ + dev->i2c_bus[2].nr = 2; + dev->i2c_bus[2].dev = dev; + dev->i2c_bus[2].i2c_period = I2C_SPEED_400K; /* 400kHz */ + dev->i2c_bus[2].i2c_nostop = 0; + dev->i2c_bus[2].i2c_reserve = 0; + + /* register I2C buses */ + cx231xx_i2c_register(&dev->i2c_bus[0]); + cx231xx_i2c_register(&dev->i2c_bus[1]); + cx231xx_i2c_register(&dev->i2c_bus[2]); + + /* init hardware */ + /* Note : with out calling set power mode function, colibri can not be set up correctly */ + errCode = cx231xx_set_power_mode(dev, POLARIS_AVMODE_ANALOGT_TV); + if (errCode < 0) { + cx231xx_errdev("%s: cx231xx_set_power_mode : Failed to set Power - errCode [%d]!\n", + __func__, errCode); + return errCode; + } + + /* initialize Colibri block */ + errCode = cx231xx_colibri_init_super_block(dev, 0x23c); + if (errCode < 0) { + cx231xx_errdev("%s: cx231xx_colibri init super block - errCode [%d]!\n", + __func__, errCode); + return errCode; + } + errCode = cx231xx_colibri_init_channels(dev); + if (errCode < 0) { + cx231xx_errdev("%s: cx231xx_colibri init channels - errCode [%d]!\n", + __func__, errCode); + return errCode; + } + + /* Set DIF in By pass mode */ + errCode = cx231xx_dif_set_standard(dev, DIF_USE_BASEBAND); + if (errCode < 0) { + cx231xx_errdev("%s: cx231xx_dif set to By pass mode - errCode [%d]!\n", + __func__, errCode); + return errCode; + } + + /* flatiron related functions */ + errCode = cx231xx_flatiron_initialize(dev); + if (errCode < 0) { + cx231xx_errdev("%s: cx231xx_flatiron initialize - errCode [%d]!\n", + __func__, errCode); + return errCode; + } + + /* init control pins */ + errCode = cx231xx_init_ctrl_pin_status(dev); + if (errCode < 0) { + cx231xx_errdev("%s: cx231xx_init ctrl pins - errCode [%d]!\n", + __func__, errCode); + return errCode; + } + + /* set AGC mode to Analog */ + errCode = cx231xx_set_agc_analog_digital_mux_select(dev, 1); + if (errCode < 0) { + cx231xx_errdev("%s: cx231xx_AGC mode to Analog - errCode [%d]!\n", + __func__, errCode); + return errCode; + } + + /* set all alternate settings to zero initially */ + cx231xx_set_alt_setting(dev, INDEX_VIDEO, 0); + cx231xx_set_alt_setting(dev, INDEX_VANC, 0); + cx231xx_set_alt_setting(dev, INDEX_HANC, 0); + if(dev->board.has_dvb) + cx231xx_set_alt_setting(dev, INDEX_TS1, 0); + + /* set the I2C master port to 3 on channel 1 */ + errCode = cx231xx_enable_i2c_for_tuner(dev, I2C_3); + + return errCode; +} +EXPORT_SYMBOL_GPL(cx231xx_dev_init); + +void cx231xx_dev_uninit(struct cx231xx *dev) +{ + /* Un Initialize I2C bus */ + cx231xx_i2c_unregister(&dev->i2c_bus[2]); + cx231xx_i2c_unregister(&dev->i2c_bus[1]); + cx231xx_i2c_unregister(&dev->i2c_bus[0]); +} +EXPORT_SYMBOL_GPL(cx231xx_dev_uninit); + + +/************************************************************************************ +* G P I O related functions * +*************************************************************************************/ +int cx231xx_send_gpio_cmd(struct cx231xx *dev, u32 gpio_bit, u8* gpio_val, + u8 len, u8 request, u8 direction) +{ + int status = 0; + VENDOR_REQUEST_IN ven_req; + + /* Set wValue */ + ven_req.wValue = (u16)(gpio_bit>>16 & 0xffff); + + /* set request */ + if(!request){ + if(direction) + ven_req.bRequest = VRT_GET_GPIO; /* 0x8 gpio */ + else + ven_req.bRequest = VRT_SET_GPIO; /* 0x9 gpio */ + } + else { + if(direction) + ven_req.bRequest = VRT_GET_GPIE; /* 0xa gpie */ + else + ven_req.bRequest = VRT_SET_GPIE; /* 0xb gpie */ + } + + /* set index value */ + ven_req.wIndex = (u16)(gpio_bit & 0xffff); + + /* set wLength value */ + ven_req.wLength = len; + + /* set bData value */ + ven_req.bData = 0; + + /* set the buffer for read / write */ + ven_req.pBuff = gpio_val; + + /* set the direction */ + if(direction){ + ven_req.direction = USB_DIR_IN; + memset(ven_req.pBuff, 0x00, ven_req.wLength); + } + else + ven_req.direction = USB_DIR_OUT; + + +#if 0 + cx231xx_isocdbg("bRequest = %x\n", ven_req.bRequest); + cx231xx_isocdbg("wValue = %x\n", ven_req.wValue); + cx231xx_isocdbg("wIndex = %x\n",ven_req.wIndex); + cx231xx_isocdbg("wLength = %x\n",ven_req.wLength); + for(int i =0; i>8); + value[2]=(u8)(tmp>>16); + value[3]=(u8)(tmp>>24); + + status = cx231xx_write_ctrl_reg(dev,VRT_SET_REGISTER, address,value,4); + + return status; +} + +/************************************************************************************* + * I 2 C Internal C O N T R O L functions * + *************************************************************************************/ +int cx231xx_read_i2c_data(struct cx231xx *dev, u8 dev_addr, u16 saddr, + u8 saddr_len, u32 *data, u8 data_len) +{ + int status = 0; + struct cx231xx_i2c_xfer_data req_data; + u8 value[4] ={0,0,0,0}; + + if(saddr_len == 0) + saddr = 0; + else if(saddr_len == 0) + saddr &= 0xff; + + /* prepare xfer_data struct */ + req_data.dev_addr = dev_addr >> 1; + req_data.direction = I2C_M_RD; + req_data.saddr_len = saddr_len; + req_data.saddr_dat = saddr; + req_data.buf_size = data_len; + req_data.p_buffer = (u8*)value; + + /* usb send command */ + status = dev->cx231xx_send_usb_command(&dev->i2c_bus[0], &req_data); + + if(status >= 0) + { + /* Copy the data read back to main buffer */ + if(data_len == 1) + *data = value[0]; + else + *data = value[0] | value[1] << 8 | value[2] << 16 | value[3] << 24; + } + + return status; +} + +int cx231xx_write_i2c_data(struct cx231xx *dev, u8 dev_addr, u16 saddr, + u8 saddr_len, u32 data, u8 data_len) +{ + int status = 0; + u8 value[4] ={0,0,0,0}; + struct cx231xx_i2c_xfer_data req_data; + + value[0]=(u8)data; + value[1]=(u8)(data>>8); + value[2]=(u8)(data>>16); + value[3]=(u8)(data>>24); + + if(saddr_len == 0) + saddr = 0; + else if(saddr_len == 0) + saddr &= 0xff; + + /* prepare xfer_data struct */ + req_data.dev_addr = dev_addr >> 1; + req_data.direction = 0; + req_data.saddr_len = saddr_len; + req_data.saddr_dat = saddr; + req_data.buf_size = data_len; + req_data.p_buffer = value; + + /* usb send command */ + status = dev->cx231xx_send_usb_command(&dev->i2c_bus[0], &req_data); + + return status; +} + +int cx231xx_reg_mask_write(struct cx231xx *dev, u8 dev_addr, u8 size, u16 register_address, + u8 bit_start,u8 bit_end, u32 value) +{ + int status = 0; + u32 tmp; + u32 mask = 0; + int i; + + if (bit_start>(size-1) || bit_end>(size-1)) { + return -1; + } + + if (size==8){ + status = cx231xx_read_i2c_data(dev, dev_addr, register_address, 2, &tmp, 1); + } else { + status = cx231xx_read_i2c_data(dev, dev_addr, register_address, 2, &tmp, 4); + } + + if (status < 0) { + return status; + } + + mask = 1<bit_start&&i>0; i--) { + mask = mask + (1<<(i-1)); + } + + value <<= bit_start; + + if (size==8) + { + tmp &= ~mask; + tmp |= value; + tmp &= 0xff; + status = cx231xx_write_i2c_data(dev, dev_addr, register_address, 2, tmp, 1); + } + else + { + tmp &= ~mask; + tmp |= value; + status = cx231xx_write_i2c_data(dev, dev_addr, register_address, 2, tmp, 4); + } + + return status; +} + + + +int cx231xx_read_modify_write_i2c_dword(struct cx231xx *dev, u8 dev_addr, + u16 saddr, u32 mask, u32 value) +{ + u32 temp; + int status = 0; + + status = cx231xx_read_i2c_data(dev, dev_addr, saddr, 2, &temp, 4); + + if(status < 0) + return status; + + temp &= ~mask; + temp |= value; + + status = cx231xx_write_i2c_data(dev, dev_addr, saddr, 2, temp, 4); + + return status; +} + +u32 cx231xx_set_field(u32 field_mask, u32 data) +{ + u32 temp; + + for (temp = field_mask; (temp & 1) == 0; temp >>= 1) { + data <<= 1; + } + + return data; +} diff --git a/linux/drivers/media/video/cx231xx/cx231xx-dvb.c b/linux/drivers/media/video/cx231xx/cx231xx-dvb.c new file mode 100644 index 000000000..d2dd8dbd5 --- /dev/null +++ b/linux/drivers/media/video/cx231xx/cx231xx-dvb.c @@ -0,0 +1,566 @@ +/* + DVB device driver for cx231xx + + Copyright (C) 2008 + Based on em28xx driver + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include "compat.h" + +#include "cx231xx.h" +#include +#include + +#include "xc5000.h" +#include "dvb_dummy_fe.h" + + +MODULE_DESCRIPTION("driver for cx231xx based DVB cards"); +MODULE_AUTHOR("Srinivasa Deevi "); +MODULE_LICENSE("GPL"); + +static unsigned int debug; +module_param(debug, int, 0644); +MODULE_PARM_DESC(debug, "enable debug messages [dvb]"); + +DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); + +#define dprintk(level, fmt, arg...) do { \ +if (debug >= level) \ + printk(KERN_DEBUG "%s/2-dvb: " fmt, dev->name, ## arg); \ +} while (0) + +#define CX231XX_DVB_NUM_BUFS 5 +#define CX231XX_DVB_MAX_PACKETSIZE 564 +#define CX231XX_DVB_MAX_PACKETS 64 + +struct cx231xx_dvb { + struct dvb_frontend *frontend; + + /* feed count management */ + struct mutex lock; + int nfeeds; + + /* general boilerplate stuff */ + struct dvb_adapter adapter; + struct dvb_demux demux; + struct dmxdev dmxdev; + struct dmx_frontend fe_hw; + struct dmx_frontend fe_mem; + struct dvb_net net; +}; + + +static inline void print_err_status(struct cx231xx *dev, + int packet, int status) +{ + char *errmsg = "Unknown"; + + switch (status) { + case -ENOENT: + errmsg = "unlinked synchronuously"; + break; + case -ECONNRESET: + errmsg = "unlinked asynchronuously"; + break; + case -ENOSR: + errmsg = "Buffer error (overrun)"; + break; + case -EPIPE: + errmsg = "Stalled (device not responding)"; + break; + case -EOVERFLOW: + errmsg = "Babble (bad cable?)"; + break; + case -EPROTO: + errmsg = "Bit-stuff error (bad cable?)"; + break; + case -EILSEQ: + errmsg = "CRC/Timeout (could be anything)"; + break; + case -ETIME: + errmsg = "Device does not respond"; + break; + } + if (packet < 0) { + dprintk(1, "URB status %d [%s].\n", status, errmsg); + } else { + dprintk(1, "URB packet %d, status %d [%s].\n", + packet, status, errmsg); + } +} + +static inline int dvb_isoc_copy(struct cx231xx *dev, struct urb *urb) +{ + int i; + + if (!dev) + return 0; + + if ((dev->state & DEV_DISCONNECTED) || (dev->state & DEV_MISCONFIGURED)) + return 0; + + if (urb->status < 0) { + print_err_status(dev, -1, urb->status); + if (urb->status == -ENOENT) + return 0; + } + + for (i = 0; i < urb->number_of_packets; i++) { + int status = urb->iso_frame_desc[i].status; + + if (status < 0) { + print_err_status(dev, i, status); + if (urb->iso_frame_desc[i].status != -EPROTO) + continue; + } + + dvb_dmx_swfilter(&dev->dvb->demux, urb->transfer_buffer + + urb->iso_frame_desc[i].offset, + urb->iso_frame_desc[i].actual_length); + } + + return 0; +} + +static int start_streaming(struct cx231xx_dvb *dvb) +{ + int rc; + struct cx231xx *dev = dvb->adapter.priv; + + usb_set_interface(dev->udev, 0, 1); + rc = cx231xx_set_mode(dev, CX231XX_DIGITAL_MODE); + if (rc < 0) + return rc; + + return cx231xx_init_isoc(dev, CX231XX_DVB_MAX_PACKETS, + CX231XX_DVB_NUM_BUFS, CX231XX_DVB_MAX_PACKETSIZE, + dvb_isoc_copy); +} + +static int stop_streaming(struct cx231xx_dvb *dvb) +{ + struct cx231xx *dev = dvb->adapter.priv; + + cx231xx_uninit_isoc(dev); + + cx231xx_set_mode(dev, CX231XX_SUSPEND); + + return 0; +} + +static int start_feed(struct dvb_demux_feed *feed) +{ + struct dvb_demux *demux = feed->demux; + struct cx231xx_dvb *dvb = demux->priv; + int rc, ret; + + if (!demux->dmx.frontend) + return -EINVAL; + + mutex_lock(&dvb->lock); + dvb->nfeeds++; + rc = dvb->nfeeds; + + if (dvb->nfeeds == 1) { + ret = start_streaming(dvb); + if (ret < 0) + rc = ret; + } + + mutex_unlock(&dvb->lock); + return rc; +} + +static int stop_feed(struct dvb_demux_feed *feed) +{ + struct dvb_demux *demux = feed->demux; + struct cx231xx_dvb *dvb = demux->priv; + int err = 0; + + mutex_lock(&dvb->lock); + dvb->nfeeds--; + + if (0 == dvb->nfeeds) + err = stop_streaming(dvb); + + mutex_unlock(&dvb->lock); + return err; +} + + + +/* ------------------------------------------------------------------ */ +static int cx231xx_dvb_bus_ctrl(struct dvb_frontend *fe, int acquire) +{ + struct cx231xx *dev = fe->dvb->priv; + + if (acquire) + return cx231xx_set_mode(dev, CX231XX_DIGITAL_MODE); + else + return cx231xx_set_mode(dev, CX231XX_SUSPEND); +} + +/* ------------------------------------------------------------------ */ + + +static struct xc5000_config cnxt_rde250_tunerconfig = { + .i2c_address = 0x61, + .if_khz = 5380, +}; + + +/* ------------------------------------------------------------------ */ +#if 0 /* Keep */ +static int attach_xc5000(u8 addr, struct cx231xx *dev) +{ + + struct dvb_frontend *fe; + struct xc5000_config cfg; + + memset(&cfg, 0, sizeof(cfg)); + cfg.i2c_adap = &dev->i2c_bus[1].i2c_adap; + cfg.i2c_addr = addr; + + if (!dev->dvb->frontend) { + printk(KERN_ERR "%s/2: dvb frontend not attached. " + "Can't attach xc5000\n", + dev->name); + return -EINVAL; + } + + fe = dvb_attach(xc5000_attach, dev->dvb->frontend, &cfg); + if (!fe) { + printk(KERN_ERR "%s/2: xc5000 attach failed\n", dev->name); + dvb_frontend_detach(dev->dvb->frontend); + dev->dvb->frontend = NULL; + return -EINVAL; + } + + printk(KERN_INFO "%s/2: xc5000 attached\n", dev->name); + + return 0; +} +#endif + +int cx231xx_set_analog_freq(struct cx231xx *dev, u32 freq ) +{ + int status = 0; + + if( (dev->dvb != NULL) && (dev->dvb->frontend != NULL) ){ + + struct dvb_tuner_ops *dops = &dev->dvb->frontend->ops.tuner_ops; + + if(dops->set_analog_params != NULL) { + struct analog_parameters params; + + params.frequency = freq; + params.std = dev->norm; + params.mode = 0 ; /* 0- Air; 1 - cable */ + /*params.audmode = ; */ + + /* Set the analog parameters to set the frequency */ + cx231xx_info("Setting Frequency for XC5000\n"); + dops->set_analog_params(dev->dvb->frontend, ¶ms); + } + + } + + return status; +} + +int cx231xx_reset_analog_tuner(struct cx231xx *dev) +{ + int status = 0; + + if( (dev->dvb != NULL) && (dev->dvb->frontend != NULL) ){ + + struct dvb_tuner_ops *dops = &dev->dvb->frontend->ops.tuner_ops; + + if(dops->init != NULL && !dev->xc_fw_load_done) { + + cx231xx_info("Reloading firmware for XC5000\n"); + status = dops->init(dev->dvb->frontend); + if(status == 0 ) { + dev->xc_fw_load_done = 1; + cx231xx_info("XC5000 firmware download completed\n"); + } else { + dev->xc_fw_load_done = 0; + cx231xx_info("XC5000 firmware download failed !!!\n"); + } + } + + } + + return status; +} + + +/* ------------------------------------------------------------------ */ + +static int register_dvb(struct cx231xx_dvb *dvb, + struct module *module, + struct cx231xx *dev, + struct device *device) +{ + int result; + + mutex_init(&dvb->lock); + + /* register adapter */ + result = dvb_register_adapter(&dvb->adapter, dev->name, module, device, + adapter_nr); + if (result < 0) { + printk(KERN_WARNING "%s: dvb_register_adapter failed (errno = %d)\n", + dev->name, result); + goto fail_adapter; + } + + /* Ensure all frontends negotiate bus access */ + dvb->frontend->ops.ts_bus_ctrl = cx231xx_dvb_bus_ctrl; + + dvb->adapter.priv = dev; + + /* register frontend */ + result = dvb_register_frontend(&dvb->adapter, dvb->frontend); + if (result < 0) { + printk(KERN_WARNING "%s: dvb_register_frontend failed (errno = %d)\n", + dev->name, result); + goto fail_frontend; + } + + /* register demux stuff */ + dvb->demux.dmx.capabilities = + DMX_TS_FILTERING | DMX_SECTION_FILTERING | + DMX_MEMORY_BASED_FILTERING; + dvb->demux.priv = dvb; + dvb->demux.filternum = 256; + dvb->demux.feednum = 256; + dvb->demux.start_feed = start_feed; + dvb->demux.stop_feed = stop_feed; + + result = dvb_dmx_init(&dvb->demux); + if (result < 0) { + printk(KERN_WARNING "%s: dvb_dmx_init failed (errno = %d)\n", + dev->name, result); + goto fail_dmx; + } + + dvb->dmxdev.filternum = 256; + dvb->dmxdev.demux = &dvb->demux.dmx; + dvb->dmxdev.capabilities = 0; + result = dvb_dmxdev_init(&dvb->dmxdev, &dvb->adapter); + if (result < 0) { + printk(KERN_WARNING "%s: dvb_dmxdev_init failed (errno = %d)\n", + dev->name, result); + goto fail_dmxdev; + } + + dvb->fe_hw.source = DMX_FRONTEND_0; + result = dvb->demux.dmx.add_frontend(&dvb->demux.dmx, &dvb->fe_hw); + if (result < 0) { + printk(KERN_WARNING "%s: add_frontend failed (DMX_FRONTEND_0, errno = %d)\n", + dev->name, result); + goto fail_fe_hw; + } + + dvb->fe_mem.source = DMX_MEMORY_FE; + result = dvb->demux.dmx.add_frontend(&dvb->demux.dmx, &dvb->fe_mem); + if (result < 0) { + printk(KERN_WARNING "%s: add_frontend failed (DMX_MEMORY_FE, errno = %d)\n", + dev->name, result); + goto fail_fe_mem; + } + + result = dvb->demux.dmx.connect_frontend(&dvb->demux.dmx, &dvb->fe_hw); + if (result < 0) { + printk(KERN_WARNING "%s: connect_frontend failed (errno = %d)\n", + dev->name, result); + goto fail_fe_conn; + } + + /* register network adapter */ + dvb_net_init(&dvb->adapter, &dvb->net, &dvb->demux.dmx); + return 0; + +fail_fe_conn: + dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_mem); +fail_fe_mem: + dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_hw); +fail_fe_hw: + dvb_dmxdev_release(&dvb->dmxdev); +fail_dmxdev: + dvb_dmx_release(&dvb->demux); +fail_dmx: + dvb_unregister_frontend(dvb->frontend); +fail_frontend: + dvb_frontend_detach(dvb->frontend); + dvb_unregister_adapter(&dvb->adapter); +fail_adapter: + return result; +} + +static void unregister_dvb(struct cx231xx_dvb *dvb) +{ + dvb_net_release(&dvb->net); + dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_mem); + dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_hw); + dvb_dmxdev_release(&dvb->dmxdev); + dvb_dmx_release(&dvb->demux); + dvb_unregister_frontend(dvb->frontend); + dvb_frontend_detach(dvb->frontend); + dvb_unregister_adapter(&dvb->adapter); +} + + +static int dvb_init(struct cx231xx *dev) +{ + int result = 0; + struct cx231xx_dvb *dvb; + + if (!dev->board.has_dvb) { + /* This device does not support the extension */ + return 0; + } + + dvb = kzalloc(sizeof(struct cx231xx_dvb), GFP_KERNEL); + + if (dvb == NULL) { + printk(KERN_INFO "cx231xx_dvb: memory allocation failed\n"); + return -ENOMEM; + } + dev->dvb = dvb; + dev->cx231xx_set_analog_freq = cx231xx_set_analog_freq; + dev->cx231xx_reset_analog_tuner = cx231xx_reset_analog_tuner; + + cx231xx_set_mode(dev, CX231XX_DIGITAL_MODE); + /* init frontend */ + switch (dev->model) { + case CX231XX_BOARD_CNXT_RDE_250: + + /* dev->dvb->frontend = dvb_attach(s5h1411_attach, + &dvico_s5h1411_config, + &dev->i2c_bus[1].i2c_adap);*/ + dev->dvb->frontend = dvb_attach(dvb_dummy_fe_ofdm_attach); + + if(dev->dvb->frontend == NULL) { + printk(DRIVER_NAME ": Failed to attach dummy front end\n"); + result = -EINVAL; + goto out_free; + } + + /* define general-purpose callback pointer */ + dvb->frontend->callback = cx231xx_tuner_callback; + + if(dvb_attach(xc5000_attach, dev->dvb->frontend, + &dev->i2c_bus[1].i2c_adap, + &cnxt_rde250_tunerconfig) < 0) { + result = -EINVAL; + goto out_free; + } + + break; + case CX231XX_BOARD_CNXT_RDU_250: + + dev->dvb->frontend = dvb_attach(dvb_dummy_fe_ofdm_attach); + + if(dev->dvb->frontend == NULL) { + printk(DRIVER_NAME ": Failed to attach dummy front end\n"); + result = -EINVAL; + goto out_free; + } + + /* define general-purpose callback pointer */ + dvb->frontend->callback = cx231xx_tuner_callback; + + if(dvb_attach(xc5000_attach, dev->dvb->frontend, + &dev->i2c_bus[1].i2c_adap, + &cnxt_rde250_tunerconfig) < 0) { + result = -EINVAL; + goto out_free; + } + break; + + default: + printk(KERN_ERR "%s/2: The frontend of your DVB/ATSC card" + " isn't supported yet\n", + dev->name); + break; + } + if (NULL == dvb->frontend) { + printk(KERN_ERR + "%s/2: frontend initialization failed\n", + dev->name); + result = -EINVAL; + goto out_free; + } + + + /* register everything */ + result = register_dvb(dvb, THIS_MODULE, dev, &dev->udev->dev); + + if (result < 0) + goto out_free; + + cx231xx_set_mode(dev, CX231XX_SUSPEND); + printk(KERN_INFO "Successfully loaded cx231xx-dvb\n"); + return 0; + +out_free: + cx231xx_set_mode(dev, CX231XX_SUSPEND); + kfree(dvb); + dev->dvb = NULL; + return result; +} + +static int dvb_fini(struct cx231xx *dev) +{ + if (!dev->board.has_dvb) { + /* This device does not support the extension */ + return 0; + } + + if (dev->dvb) { + unregister_dvb(dev->dvb); + dev->dvb = NULL; + } + + return 0; +} + +static struct cx231xx_ops dvb_ops = { + .id = CX231XX_DVB, + .name = "Cx231xx dvb Extension", + .init = dvb_init, + .fini = dvb_fini, +}; + +static int __init cx231xx_dvb_register(void) +{ + return cx231xx_register_extension(&dvb_ops); +} + +static void __exit cx231xx_dvb_unregister(void) +{ + cx231xx_unregister_extension(&dvb_ops); +} + +module_init(cx231xx_dvb_register); +module_exit(cx231xx_dvb_unregister); + diff --git a/linux/drivers/media/video/cx231xx/cx231xx-i2c.c b/linux/drivers/media/video/cx231xx/cx231xx-i2c.c new file mode 100644 index 000000000..fd595ffaa --- /dev/null +++ b/linux/drivers/media/video/cx231xx/cx231xx-i2c.c @@ -0,0 +1,580 @@ +/* + cx231xx-i2c.c - driver for Conexant Cx23100/101/102 USB video capture devices + + Copyright (C) 2008 + Based on em28xx driver + Based on Cx23885 driver + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include + +#include "cx231xx.h" + + +/* ----------------------------------------------------------- */ + +static unsigned int i2c_scan; +module_param(i2c_scan, int, 0444); +MODULE_PARM_DESC(i2c_scan, "scan i2c bus at insmod time"); + +static unsigned int i2c_debug; +module_param(i2c_debug, int, 0644); +MODULE_PARM_DESC(i2c_debug, "enable debug messages [i2c]"); + + +#define dprintk1(lvl, fmt, args...) \ +do { \ + if (i2c_debug >= lvl) { \ + printk(fmt, ##args); \ + } \ +} while (0) + +#define dprintk2(lvl, fmt, args...) \ +do { \ + if (i2c_debug >= lvl) { \ + printk(KERN_DEBUG "%s at %s: " fmt, \ + dev->name, __func__ , ##args); \ + } \ +} while (0) + + +/* + * cx231xx_i2c_send_bytes() + */ +int cx231xx_i2c_send_bytes(struct i2c_adapter *i2c_adap, + const struct i2c_msg *msg) +{ + struct cx231xx_i2c *bus = i2c_adap->algo_data; + struct cx231xx *dev = bus->dev; + struct cx231xx_i2c_xfer_data req_data; + int status = 0; + u16 size = 0; + u8 loop = 0; + u8 saddr_len = 1; + u8 *buf_ptr = NULL; + u16 saddr = 0; + u8 need_gpio = 0; + + + if( (bus->nr ==1) && (msg->addr == 0x61) && (dev->tuner_type == TUNER_XC5000) ) { + + size = msg->len; + + if( size == 2 ) { /* register write sub addr*/ + + /* Just writing sub address will cause problem to XC5000 + So ignore the request */ + return 0; + + } else if( size == 4 ) { /* register write with sub addr*/ + + if(msg->len >= 2 ) + saddr = msg->buf[0] << 8 | msg->buf[1]; + else if ( msg->len == 1 ) + saddr = msg->buf[0]; + + switch(saddr) { + case 0x0000: /* start tuner calibration mode */ + need_gpio = 1; + dev->xc_fw_load_done = 1; /* FW Loading is done */ + break; + case 0x000D: /* Set signal source */ + case 0x0001: /* Set TV standard - Video */ + case 0x0002: /* Set TV standard - Audio */ + case 0x0003: /* Set RF Frequency */ + need_gpio = 1; + break; + default: + if(dev->xc_fw_load_done) + need_gpio = 1; + break; + } + + if(need_gpio ) { + dprintk1(1, " GPIO W R I T E : addr 0x%x, len %d, saddr 0x%x\n", + msg->addr, msg->len, saddr); + + return dev->cx231xx_gpio_i2c_write(dev, msg->addr, msg->buf, msg->len); + } + + } + + /* special case for Xc5000 tuner case */ + saddr_len = 1; + + /* adjust the length to correct length */ + size -= saddr_len; + buf_ptr = (u8*) (msg->buf + 1 ); + + do { + /* prepare xfer_data struct */ + req_data.dev_addr = msg->addr; + req_data.direction = msg->flags; + req_data.saddr_len = saddr_len; + req_data.saddr_dat = msg->buf[0]; + req_data.buf_size = size > 16 ? 16: size; + req_data.p_buffer = (u8*)(buf_ptr + loop * 16); + + bus->i2c_nostop = (size > 16) ? 1: 0; + bus->i2c_reserve = (loop == 0) ? 0: 1; + + /* usb send command */ + status = dev->cx231xx_send_usb_command(bus, &req_data); + loop++; + + if( size >= 16 ) + size -= 16; + else + size = 0; + + }while( size > 0 ); + + bus->i2c_nostop = 0; + bus->i2c_reserve = 0; + + } else { /* regular case */ + + /* prepare xfer_data struct */ + req_data.dev_addr = msg->addr; + req_data.direction = msg->flags; + req_data.saddr_len = 0; + req_data.saddr_dat = 0; + req_data.buf_size = msg->len; + req_data.p_buffer = msg->buf; + + /* usb send command */ + status = dev->cx231xx_send_usb_command(bus, &req_data); + } + + return status < 0 ? status: 0; +} + +/* + * cx231xx_i2c_recv_bytes() + * read a byte from the i2c device + */ +static int cx231xx_i2c_recv_bytes(struct i2c_adapter *i2c_adap, + const struct i2c_msg *msg) +{ + struct cx231xx_i2c *bus = i2c_adap->algo_data; + struct cx231xx *dev = bus->dev; + struct cx231xx_i2c_xfer_data req_data; + int status = 0; + u16 saddr = 0; + u8 need_gpio = 0; + + if((bus->nr ==1) && (msg->addr == 0x61) && dev->tuner_type == TUNER_XC5000) { + + if(msg->len == 2 ) + saddr = msg->buf[0] << 8 | msg->buf[1]; + else if ( msg->len == 1 ) + saddr = msg->buf[0]; + + if( dev->xc_fw_load_done) { + + switch(saddr) { + case 0x0009: /* BUSY check */ + dprintk1(1, " GPIO R E A D : Special case BUSY check \n"); + /* Try to read BUSY register, just set it to zero */ + msg->buf[0] = 0; + if(msg->len == 2 ) + msg->buf[1] = 0; + return 0; + case 0x0004: /* read Lock status */ + need_gpio = 1; + break; + + } + + if(need_gpio) { + /* this is a special case to handle Xceive tuner clock stretch issue + with gpio based I2C interface */ + dprintk1(1, " GPIO R E A D : addr 0x%x, len %d, saddr 0x%x\n", + msg->addr, msg->len, msg->buf[0] << 8| msg->buf[1]); + status = dev->cx231xx_gpio_i2c_write(dev, msg->addr, msg->buf, msg->len); + status = dev->cx231xx_gpio_i2c_read(dev, msg->addr, msg->buf, msg->len); + return status; + } + } + + /* prepare xfer_data struct */ + req_data.dev_addr = msg->addr; + req_data.direction = msg->flags; + req_data.saddr_len = msg->len; + req_data.saddr_dat = msg->buf[0] << 8 | msg->buf[1]; + req_data.buf_size = msg->len; + req_data.p_buffer = msg->buf; + + /* usb send command */ + status = dev->cx231xx_send_usb_command(bus, &req_data); + + } else { + + /* prepare xfer_data struct */ + req_data.dev_addr = msg->addr; + req_data.direction = msg->flags; + req_data.saddr_len = 0; + req_data.saddr_dat = 0; + req_data.buf_size = msg->len; + req_data.p_buffer = msg->buf; + + /* usb send command */ + status = dev->cx231xx_send_usb_command(bus, &req_data); + } + + return status < 0 ? status: 0; +} + +/* + * cx231xx_i2c_recv_bytes_with_saddr() + * read a byte from the i2c device + */ +static int cx231xx_i2c_recv_bytes_with_saddr(struct i2c_adapter *i2c_adap, + const struct i2c_msg *msg1, const struct i2c_msg *msg2) +{ + struct cx231xx_i2c *bus = i2c_adap->algo_data; + struct cx231xx *dev = bus->dev; + struct cx231xx_i2c_xfer_data req_data; + int status = 0; + u16 saddr = 0; + u8 need_gpio = 0; + + if(msg1->len == 2 ) + saddr = msg1->buf[0] << 8 | msg1->buf[1]; + else if ( msg1->len == 1 ) + saddr = msg1->buf[0]; + + if ( (bus->nr ==1) && (msg2->addr == 0x61) && dev->tuner_type == TUNER_XC5000) { + + if( (msg2->len < 16) ) { + + dprintk1(1, " i2c_read : addr 0x%x, len %d, subaddr 0x%x, leng %d\n", + msg2->addr, msg2->len, saddr, msg1->len); + + switch(saddr) { + case 0x0008: /* read FW load status */ + need_gpio = 1; + break; + case 0x0004: /* read Lock status */ + need_gpio = 1; + break; + } + + if(need_gpio ) { + status = dev->cx231xx_gpio_i2c_write(dev, msg1->addr, msg1->buf, msg1->len); + status = dev->cx231xx_gpio_i2c_read(dev, msg2->addr, msg2->buf, msg2->len); + return status; + } + } + } + + /* prepare xfer_data struct */ + req_data.dev_addr = msg2->addr; + req_data.direction = msg2->flags; + req_data.saddr_len = msg1->len; + req_data.saddr_dat = saddr; + req_data.buf_size = msg2->len; + req_data.p_buffer = msg2->buf; + + /* usb send command */ + status = dev->cx231xx_send_usb_command(bus, &req_data); + + return status < 0 ? status: 0; +} + +/* + * cx231xx_i2c_check_for_device() + * check if there is a i2c_device at the supplied address + */ +static int cx231xx_i2c_check_for_device(struct i2c_adapter *i2c_adap, + const struct i2c_msg *msg) +{ + struct cx231xx_i2c *bus = i2c_adap->algo_data; + struct cx231xx *dev = bus->dev; + struct cx231xx_i2c_xfer_data req_data; + int status = 0; + + /* prepare xfer_data struct */ + req_data.dev_addr = msg->addr; + req_data.direction = msg->flags; + req_data.saddr_len = 0; + req_data.saddr_dat = 0; + req_data.buf_size = 0; + req_data.p_buffer = NULL; + + /* usb send command */ + status = dev->cx231xx_send_usb_command(bus, &req_data); + + return status < 0 ? status: 0; +} + +/* + * cx231xx_i2c_xfer() + * the main i2c transfer function + */ +static int cx231xx_i2c_xfer(struct i2c_adapter *i2c_adap, + struct i2c_msg msgs[], int num) +{ + struct cx231xx_i2c *bus = i2c_adap->algo_data; + struct cx231xx *dev = bus->dev; + int addr, rc, i, byte; + + if (num <= 0) + return 0; + + for (i = 0; i < num; i++) { + + addr = msgs[i].addr >> 1; + + dprintk2(2, "%s %s addr=%x len=%d:", + (msgs[i].flags & I2C_M_RD) ? "read" : "write", + i == num - 1 ? "stop" : "nonstop", addr, msgs[i].len); + if (!msgs[i].len) { /* no len: check only for device presence */ + rc = cx231xx_i2c_check_for_device(i2c_adap, &msgs[i]); + if (rc < 0) { + dprintk2(2, " no device\n"); + return rc; + } + + } else if (msgs[i].flags & I2C_M_RD) { + /* read bytes */ + rc = cx231xx_i2c_recv_bytes(i2c_adap, &msgs[i]); + if (i2c_debug >= 2) { + for (byte = 0; byte < msgs[i].len; byte++) + printk(" %02x", msgs[i].buf[byte]); + } + } else if (i + 1 < num && (msgs[i + 1].flags & I2C_M_RD) && + msgs[i].addr == msgs[i + 1].addr && (msgs[i].len <= 2) && (bus->nr < 2)) { + /* read bytes */ + rc = cx231xx_i2c_recv_bytes_with_saddr(i2c_adap, &msgs[i], &msgs[i+1]); + if (i2c_debug >= 2) { + for (byte = 0; byte < msgs[i].len; byte++) + printk(" %02x", msgs[i].buf[byte]); + } + i++; + } else { + /* write bytes */ + if (i2c_debug >= 2) { + for (byte = 0; byte < msgs[i].len; byte++) + printk(" %02x", msgs[i].buf[byte]); + } + rc = cx231xx_i2c_send_bytes(i2c_adap,&msgs[i]); + } + if (rc < 0) + goto err; + if (i2c_debug >= 2) + printk("\n"); + } + + return num; +err: + dprintk2(2, " ERROR: %i\n", rc); + return rc; +} + +/* ----------------------------------------------------------- */ + +/* + * functionality() + */ +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 0x32: + dprintk1(1, "attach_inform: Geminit III detected.\n"); + break; + case 0x02: + dprintk1(1, "attach_inform: Acquarius detected.\n"); + break; + case 0xa0: + dprintk1(1, "attach_inform: eeprom detected.\n"); + break; + case 0x60: + dprintk1(1, "attach_inform: Colibri detected.\n"); + break; + 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; + } + case 0x80: + case 0x88: + dprintk1(1, "attach_inform: Hammerhead detected.\n"); + break; + + default: + if (!dev->tuner_addr) + dev->tuner_addr = client->addr; + + dprintk1(1, "attach inform: detected I2C address %x\n", + client->addr << 1); + } + + return 0; +} + +static int detach_inform(struct i2c_client *client) +{ + dprintk1(1, "i2c detach [client=%s]\n", client->name); + return 0; +} + + +static struct i2c_algorithm cx231xx_algo = { + .master_xfer = cx231xx_i2c_xfer, + .functionality = functionality, +#ifdef NEED_ALGO_CONTROL + .algo_control = dummy_algo_control, +#endif +}; + +static struct i2c_adapter cx231xx_adap_template = { + .owner = THIS_MODULE, + .class = I2C_CLASS_TV_ANALOG, + .name = "cx231xx", + .id = I2C_HW_B_CX231XX, + .algo = &cx231xx_algo, + .client_register = attach_inform, + .client_unregister = detach_inform, +}; + +static struct i2c_client cx231xx_client_template = { + .name = "cx231xx internal", +}; + +/* ----------------------------------------------------------- */ + +/* + * i2c_devs + * incomplete list of known devices + */ +static char *i2c_devs[128] = { + [0x60 >> 1] = "colibri", + [0x88 >> 1] = "hammerhead", + [0x8e >> 1] = "CIR", + [0x32 >> 1] = "GeminiIII", + [0x02 >> 1] = "Aquarius", + [0xa0 >> 1] = "eeprom", + [0xc0 >> 1] = "tuner/XC3028", + [0xc2 >> 1] = "tuner/XC5000", +}; + +/* + * cx231xx_do_i2c_scan() + * check i2c address range for devices + */ +void cx231xx_do_i2c_scan(struct cx231xx *dev, struct i2c_client *c) +{ + unsigned char buf; + int i, rc; + + cx231xx_info(": Checking for I2C devices ..\n"); + for (i = 0; i < 128; i++) { + c->addr = i; + rc = i2c_master_recv(c, &buf, 0); + if (rc < 0) + continue; + cx231xx_info("%s: i2c scan: found device @ 0x%x [%s]\n", + dev->name, i << 1, i2c_devs[i] ? i2c_devs[i] : "???"); + } + cx231xx_info(": Completed Checking for I2C devices.\n"); +} + +/* + * cx231xx_i2c_call_clients() + * send commands to all attached i2c devices + */ +void cx231xx_i2c_call_clients(struct cx231xx_i2c *bus, unsigned int cmd, void *arg) +{ + /* struct cx231xx *dev = bus->dev; */ + + BUG_ON(NULL == bus->i2c_adap.algo_data); + i2c_clients_command(&bus->i2c_adap, cmd, arg); +} + +/* + * cx231xx_i2c_register() + * register i2c bus + */ +int cx231xx_i2c_register(struct cx231xx_i2c *bus) +{ + struct cx231xx *dev = bus->dev; + + BUG_ON(!dev->cx231xx_send_usb_command); + + cx231xx_info("%s(bus = %d)\n", __func__, bus->nr); + + memcpy(&bus->i2c_adap, &cx231xx_adap_template, + sizeof(bus->i2c_adap)); + memcpy(&bus->i2c_algo, &cx231xx_algo, + sizeof(bus->i2c_algo)); + memcpy(&bus->i2c_client, &cx231xx_client_template, + sizeof(bus->i2c_client)); + + bus->i2c_adap.dev.parent = &dev->udev->dev; + + strlcpy(bus->i2c_adap.name, bus->dev->name, + sizeof(bus->i2c_adap.name)); + + bus->i2c_algo.data = bus; + bus->i2c_adap.algo_data = bus; + i2c_set_adapdata(&bus->i2c_adap, bus); + i2c_add_adapter(&bus->i2c_adap); + + bus->i2c_client.adapter = &bus->i2c_adap; + + if (0 == bus->i2c_rc) { + cx231xx_info("%s: i2c bus %d registered\n", dev->name, bus->nr); + if (i2c_scan) + cx231xx_do_i2c_scan(dev, &bus->i2c_client); + } else + cx231xx_warn("%s: i2c bus %d register FAILED\n", + dev->name, bus->nr); + + return bus->i2c_rc; +} + +/* + * cx231xx_i2c_unregister() + * unregister i2c_bus + */ +int cx231xx_i2c_unregister(struct cx231xx_i2c *bus) +{ + i2c_del_adapter(&bus->i2c_adap); + return 0; +} diff --git a/linux/drivers/media/video/cx231xx/cx231xx-input.c b/linux/drivers/media/video/cx231xx/cx231xx-input.c new file mode 100644 index 000000000..e2e0a2f2a --- /dev/null +++ b/linux/drivers/media/video/cx231xx/cx231xx-input.c @@ -0,0 +1,267 @@ +/* + handle cx231xx IR remotes via linux kernel input layer. + + Copyright (C) 2008 + Based on em28xx driver + + < This is a place holder for IR now.> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#include + +#include "compat.h" +#include "cx231xx.h" + + +static unsigned int ir_debug; +module_param(ir_debug, int, 0644); +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); \ + } + +#define dprintk(fmt, arg...) \ + if (ir_debug) { \ + printk(KERN_DEBUG "%s/ir: " fmt, ir->name , ## arg); \ + } + +/********************************************************** + Polling structure used by cx231xx IR's + **********************************************************/ + +struct cx231xx_ir_poll_result { + unsigned int toggle_bit:1; + unsigned int read_count:7; + u8 rc_address; + u8 rc_data[4]; +}; + +struct cx231xx_IR { + struct cx231xx *dev; + struct input_dev *input; + struct ir_input_state ir; + char name[32]; + char phys[32]; + + /* poll external decoder */ + int polling; + struct work_struct work; + struct timer_list timer; + unsigned int last_toggle:1; + unsigned int last_readcount; + unsigned int repeat_interval; + + int (*get_key)(struct cx231xx_IR *, struct cx231xx_ir_poll_result *); +}; + + + +/********************************************************** + Polling code for cx231xx + **********************************************************/ + +static void cx231xx_ir_handle_key(struct cx231xx_IR *ir) +{ + int result; + int do_sendkey = 0; + struct cx231xx_ir_poll_result poll_result; + + /* read the registers containing the IR status */ + result = ir->get_key(ir, &poll_result); + if (result < 0) { + dprintk("ir->get_key() failed %d\n", result); + return; + } + + dprintk("ir->get_key result tb=%02x rc=%02x lr=%02x data=%02x\n", + poll_result.toggle_bit, poll_result.read_count, + ir->last_readcount, poll_result.rc_data[0]); + + if (ir->dev->chip_id == CHIP_ID_EM2874) { + /* The em2874 clears the readcount field every time the + register is read. The em2860/2880 datasheet says that it + is supposed to clear the readcount, but it doesn't. So with + the em2874, we are looking for a non-zero read count as + opposed to a readcount that is incrementing */ + ir->last_readcount = 0; + } + + if (poll_result.read_count == 0) { + /* The button has not been pressed since the last read */ + } else if (ir->last_toggle != poll_result.toggle_bit) { + /* A button has been pressed */ + dprintk("button has been pressed\n"); + ir->last_toggle = poll_result.toggle_bit; + ir->repeat_interval = 0; + do_sendkey = 1; + } else if (poll_result.toggle_bit == ir->last_toggle && + poll_result.read_count > 0 && + poll_result.read_count != ir->last_readcount) { + /* The button is still being held down */ + dprintk("button being held down\n"); + + /* Debouncer for first keypress */ + if (ir->repeat_interval++ > 9) { + /* Start repeating after 1 second */ + do_sendkey = 1; + } + } + + if (do_sendkey) { + dprintk("sending keypress\n"); + ir_input_keydown(ir->input, &ir->ir, poll_result.rc_data[0], + poll_result.rc_data[0]); + ir_input_nokey(ir->input, &ir->ir); + } + + ir->last_readcount = poll_result.read_count; + return; +} + +static void ir_timer(unsigned long data) +{ + struct cx231xx_IR *ir = (struct cx231xx_IR *)data; + + schedule_work(&ir->work); +} + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20) +static void cx231xx_ir_work(void *data) +#else +static void cx231xx_ir_work(struct work_struct *work) +#endif +{ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20) + struct cx231xx_IR *ir = data; +#else + struct cx231xx_IR *ir = container_of(work, struct cx231xx_IR, work); +#endif + + cx231xx_ir_handle_key(ir); + mod_timer(&ir->timer, jiffies + msecs_to_jiffies(ir->polling)); +} + +void cx231xx_ir_start(struct cx231xx_IR *ir) +{ + setup_timer(&ir->timer, ir_timer, (unsigned long)ir); +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20) + INIT_WORK(&ir->work, cx231xx_ir_work, ir); +#else + INIT_WORK(&ir->work, cx231xx_ir_work); +#endif + schedule_work(&ir->work); +} + +static void cx231xx_ir_stop(struct cx231xx_IR *ir) +{ + del_timer_sync(&ir->timer); + flush_scheduled_work(); +} + +int cx231xx_ir_init(struct cx231xx *dev) +{ + struct cx231xx_IR *ir; + struct input_dev *input_dev; + u8 ir_config; + int err = -ENOMEM; + + if (dev->board.ir_codes == NULL) { + /* No remote control support */ + return 0; + } + + ir = kzalloc(sizeof(*ir), GFP_KERNEL); + input_dev = input_allocate_device(); + if (!ir || !input_dev) + goto err_out_free; + + ir->input = input_dev; + + /* Setup the proper handler based on the chip */ + switch (dev->chip_id) { + default: + printk("Unrecognized cx231xx chip id: IR not supported\n"); + goto err_out_free; + } + + /* This is how often we ask the chip for IR information */ + ir->polling = 100; /* ms */ + + /* init input device */ + snprintf(ir->name, sizeof(ir->name), "cx231xx IR (%s)", + dev->name); + + usb_make_path(dev->udev, ir->phys, sizeof(ir->phys)); + strlcat(ir->phys, "/input0", sizeof(ir->phys)); + + ir_input_init(input_dev, &ir->ir, IR_TYPE_OTHER, dev->board.ir_codes); + input_dev->name = ir->name; + input_dev->phys = ir->phys; + input_dev->id.bustype = BUS_USB; + input_dev->id.version = 1; + input_dev->id.vendor = le16_to_cpu(dev->udev->descriptor.idVendor); + input_dev->id.product = le16_to_cpu(dev->udev->descriptor.idProduct); + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 22) + input_dev->dev.parent = &dev->udev->dev; +#else + input_dev->cdev.dev = &dev->udev->dev; +#endif + /* record handles to ourself */ + ir->dev = dev; + dev->ir = ir; + + cx231xx_ir_start(ir); + + /* all done */ + err = input_register_device(ir->input); + if (err) + goto err_out_stop; + + return 0; + err_out_stop: + cx231xx_ir_stop(ir); + dev->ir = NULL; + err_out_free: + input_free_device(input_dev); + kfree(ir); + return err; +} + +int cx231xx_ir_fini(struct cx231xx *dev) +{ + struct cx231xx_IR *ir = dev->ir; + + /* skip detach on non attached boards */ + if (!ir) + return 0; + + cx231xx_ir_stop(ir); + input_unregister_device(ir->input); + kfree(ir); + + /* done */ + dev->ir = NULL; + return 0; +} \ No newline at end of file diff --git a/linux/drivers/media/video/cx231xx/cx231xx-reg.h b/linux/drivers/media/video/cx231xx/cx231xx-reg.h new file mode 100644 index 000000000..05bf86fc7 --- /dev/null +++ b/linux/drivers/media/video/cx231xx/cx231xx-reg.h @@ -0,0 +1,1574 @@ +/* + cx231xx-reg.h - driver for Conexant Cx23100/101/102 USB video capture devices + + Copyright (C) 2008 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef _CX231XX_REG_H +#define _CX231XX_REG_H + +/***************************************************************************** + * VBI codes * +*****************************************************************************/ + +#define SAV_ACTIVE_VIDEO_FIELD1 0x80 +#define EAV_ACTIVE_VIDEO_FIELD1 0x90 + +#define SAV_ACTIVE_VIDEO_FIELD2 0xC0 +#define EAV_ACTIVE_VIDEO_FIELD2 0xD0 + +#define SAV_VBLANK_FIELD1 0xA0 +#define EAV_VBLANK_FIELD1 0xB0 + +#define SAV_VBLANK_FIELD2 0xE0 +#define EAV_VBLANK_FIELD2 0xF0 + +#define SAV_VBI_FIELD1 0x20 +#define EAV_VBI_FIELD1 0x30 + +#define SAV_VBI_FIELD2 0x60 +#define EAV_VBI_FIELD2 0x70 + +/*****************************************************************************/ +/* Audio ADC Registers */ +#define CH_PWR_CTRL1 0x0000000E +#define CH_PWR_CTRL2 0x0000000F +/*****************************************************************************/ + +#define HOST_REG1 0x000 +#define FLD_FORCE_CHIP_SEL 0x80 +#define FLD_AUTO_INC_DIS 0x20 +#define FLD_PREFETCH_EN 0x10 +/* Reserved [2:3] */ +#define FLD_DIGITAL_PWR_DN 0x02 +#define FLD_SLEEP 0x01 + +/*****************************************************************************/ +#define HOST_REG2 0x001 + + +/*****************************************************************************/ +#define HOST_REG3 0x002 + +/*****************************************************************************/ +/* added for polaris */ +#define GPIO_PIN_CTL0 0x3 +#define GPIO_PIN_CTL1 0x4 +#define GPIO_PIN_CTL2 0x5 +#define GPIO_PIN_CTL3 0x6 +#define TS1_PIN_CTL0 0x7 +#define TS1_PIN_CTL1 0x8 +/*****************************************************************************/ + +#define FLD_CLK_IN_EN 0x80 +#define FLD_XTAL_CTRL 0x70 +#define FLD_BB_CLK_MODE 0x0C +#define FLD_REF_DIV_PLL 0x02 +#define FLD_REF_SEL_PLL1 0x01 + +/*****************************************************************************/ +#define CHIP_CTRL 0x100 +/* Reserved [27] */ +/* Reserved [31:21] */ +#define FLD_CHIP_ACFG_DIS 0x00100000 +/* Reserved [19] */ +#define FLD_DUAL_MODE_ADC2 0x00040000 +#define FLD_SIF_EN 0x00020000 +#define FLD_SOFT_RST 0x00010000 +#define FLD_DEVICE_ID 0x0000FFFF + +/*****************************************************************************/ +#define AFE_CTRL 0x104 +#define AFE_CTRL_C2HH_SRC_CTRL 0x104 +#define FLD_DIF_OUT_SEL 0xC0000000 +#define FLD_AUX_PLL_CLK_ALT_SEL 0x3C000000 +#define FLD_UV_ORDER_MODE 0x02000000 +#define FLD_FUNC_MODE 0x01800000 +#define FLD_ROT1_PHASE_CTL 0x007F8000 +#define FLD_AUD_IN_SEL 0x00004000 +#define FLD_LUMA_IN_SEL 0x00002000 +#define FLD_CHROMA_IN_SEL 0x00001000 +/* reserve [11:10] */ +#define FLD_INV_SPEC_DIS 0x00000200 +#define FLD_VGA_SEL_CH3 0x00000100 +#define FLD_VGA_SEL_CH2 0x00000080 +#define FLD_VGA_SEL_CH1 0x00000040 +#define FLD_DCR_BYP_CH1 0x00000020 +#define FLD_DCR_BYP_CH2 0x00000010 +#define FLD_DCR_BYP_CH3 0x00000008 +#define FLD_EN_12DB_CH3 0x00000004 +#define FLD_EN_12DB_CH2 0x00000002 +#define FLD_EN_12DB_CH1 0x00000001 + +/* redefine in Cx231xx */ +/*****************************************************************************/ +#define DC_CTRL1 0x108 +/* reserve [31:30] */ +#define FLD_CLAMP_LVL_CH1 0x3FFF8000 +#define FLD_CLAMP_LVL_CH2 0x00007FFF +/*****************************************************************************/ + +/*****************************************************************************/ +#define DC_CTRL2 0x10c +/* reserve [31:28] */ +#define FLD_CLAMP_LVL_CH3 0x00FFFE00 +#define FLD_CLAMP_WIND_LENTH 0x000001E0 +#define FLD_C2HH_SAT_MIN 0x0000001E +#define FLD_FLT_BYP_SEL 0x00000001 +/*****************************************************************************/ + +/*****************************************************************************/ +#define DC_CTRL3 0x110 +/* reserve [31:16] */ +#define FLD_ERR_GAIN_CTL 0x00070000 +#define FLD_LPF_MIN 0x0000FFFF +/*****************************************************************************/ + +/*****************************************************************************/ +#define DC_CTRL4 0x114 +/* reserve [31:31] */ +#define FLD_INTG_CH1 0x7FFFFFFF +/*****************************************************************************/ + +/*****************************************************************************/ +#define DC_CTRL5 0x118 +/* reserve [31:31] */ +#define FLD_INTG_CH2 0x7FFFFFFF +/*****************************************************************************/ + +/*****************************************************************************/ +#define DC_CTRL6 0x11c +/* reserve [31:31] */ +#define FLD_INTG_CH3 0x7FFFFFFF +/*****************************************************************************/ + +/*****************************************************************************/ +#define PIN_CTRL 0x120 +#define FLD_OEF_AGC_RF 0x00000001 +#define FLD_OEF_AGC_IFVGA 0x00000002 +#define FLD_OEF_AGC_IF 0x00000004 +#define FLD_REG_BO_PUD 0x80000000 +#define FLD_IR_IRQ_STAT 0x40000000 +#define FLD_AUD_IRQ_STAT 0x20000000 +#define FLD_VID_IRQ_STAT 0x10000000 +/* Reserved [27:26] */ +#define FLD_IRQ_N_OUT_EN 0x02000000 +#define FLD_IRQ_N_POLAR 0x01000000 +/* Reserved [23:6] */ +#define FLD_OE_AUX_PLL_CLK 0x00000020 +#define FLD_OE_I2S_BCLK 0x00000010 +#define FLD_OE_I2S_WCLK 0x00000008 +#define FLD_OE_AGC_IF 0x00000004 +#define FLD_OE_AGC_IFVGA 0x00000002 +#define FLD_OE_AGC_RF 0x00000001 + +/*****************************************************************************/ +#define AUD_IO_CTRL 0x124 +/* Reserved [31:8] */ +#define FLD_I2S_PORT_DIR 0x00000080 +#define FLD_I2S_OUT_SRC 0x00000040 +#define FLD_AUD_CHAN3_SRC 0x00000030 +#define FLD_AUD_CHAN2_SRC 0x0000000C +#define FLD_AUD_CHAN1_SRC 0x00000003 + +/*****************************************************************************/ +#define AUD_LOCK1 0x128 +#define FLD_AUD_LOCK_KI_SHIFT 0xC0000000 +#define FLD_AUD_LOCK_KD_SHIFT 0x30000000 +/* Reserved [27:25] */ +#define FLD_EN_AV_LOCK 0x01000000 +#define FLD_VID_COUNT 0x00FFFFFF + +/*****************************************************************************/ +#define AUD_LOCK2 0x12C +#define FLD_AUD_LOCK_KI_MULT 0xF0000000 +#define FLD_AUD_LOCK_KD_MULT 0x0F000000 +/* Reserved [23:22] */ +#define FLD_AUD_LOCK_FREQ_SHIFT 0x00300000 +#define FLD_AUD_COUNT 0x000FFFFF + +/*****************************************************************************/ +#define AFE_DIAG_CTRL1 0x134 +/* Reserved [31:16] */ +#define FLD_CUV_DLY_LENGTH 0x0000FF00 +#define FLD_YC_DLY_LENGTH 0x000000FF + +/*****************************************************************************/ +/* Poalris redefine */ +#define AFE_DIAG_CTRL3 0x138 +/* Reserved [31:26] */ +#define FLD_AUD_DUAL_FLAG_POL 0x02000000 +#define FLD_VID_DUAL_FLAG_POL 0x01000000 +/* Reserved [23:23] */ +#define FLD_COL_CLAMP_DIS_CH1 0x00400000 +#define FLD_COL_CLAMP_DIS_CH2 0x00200000 +#define FLD_COL_CLAMP_DIS_CH3 0x00100000 + +#define TEST_CTRL1 0x144 +/* Reserved [31:29] */ +#define FLD_LBIST_EN 0x10000000 +/* Reserved [27:10] */ +#define FLD_FI_BIST_INTR_R 0x0000200 +#define FLD_FI_BIST_INTR_L 0x0000100 +#define FLD_BIST_FAIL_AUD_PLL 0x0000080 +#define FLD_BIST_INTR_AUD_PLL 0x0000040 +#define FLD_BIST_FAIL_VID_PLL 0x0000020 +#define FLD_BIST_INTR_VID_PLL 0x0000010 +/* Reserved [3:1] */ +#define FLD_CIR_TEST_DIS 0x00000001 + + +/*****************************************************************************/ +#define TEST_CTRL2 0x148 +#define FLD_TSXCLK_POL_CTL 0x80000000 +#define FLD_ISO_CTL_SEL 0x40000000 +#define FLD_ISO_CTL_EN 0x20000000 +#define FLD_BIST_DEBUGZ 0x10000000 +#define FLD_AUD_BIST_TEST_H 0x0F000000 +/* Reserved [23:22] */ +#define FLD_FLTRN_BIST_TEST_H 0x00020000 +#define FLD_VID_BIST_TEST_H 0x00010000 +/* Reserved [19:17] */ +#define FLD_BIST_TEST_H 0x00010000 +/* Reserved [15:13] */ +#define FLD_TAB_EN 0x00001000 +/* Reserved [11:0] */ + +/*****************************************************************************/ +#define BIST_STAT 0x14C +#define FLD_AUD_BIST_FAIL_H 0xFFF00000 +#define FLD_FLTRN_BIST_FAIL_H 0x00180000 +#define FLD_VID_BIST_FAIL_H 0x00070000 +#define FLD_AUD_BIST_TST_DONE 0x0000FFF0 +#define FLD_FLTRN_BIST_TST_DONE 0x00000008 +#define FLD_VID_BIST_TST_DONE 0x00000007 + + +/*****************************************************************************/ +/* DirectIF registers definition have been moved to DIF_reg.h */ +/*****************************************************************************/ +#define MODE_CTRL 0x400 +#define FLD_AFD_PAL60_DIS 0x20000000 +#define FLD_AFD_FORCE_SECAM 0x10000000 +#define FLD_AFD_FORCE_PALNC 0x08000000 +#define FLD_AFD_FORCE_PAL 0x04000000 +#define FLD_AFD_PALM_SEL 0x03000000 +#define FLD_CKILL_MODE 0x00300000 +#define FLD_COMB_NOTCH_MODE 0x00c00000 /* bit[19:18] */ +#define FLD_CLR_LOCK_STAT 0x00020000 +#define FLD_FAST_LOCK_MD 0x00010000 +#define FLD_WCEN 0x00008000 +#define FLD_CAGCEN 0x00004000 +#define FLD_CKILLEN 0x00002000 +#define FLD_AUTO_SC_LOCK 0x00001000 +#define FLD_MAN_SC_FAST_LOCK 0x00000800 +#define FLD_INPUT_MODE 0x00000600 +#define FLD_AFD_ACQUIRE 0x00000100 +#define FLD_AFD_NTSC_SEL 0x00000080 +#define FLD_AFD_PAL_SEL 0x00000040 +#define FLD_ACFG_DIS 0x00000020 +#define FLD_SQ_PIXEL 0x00000010 +#define FLD_VID_FMT_SEL 0x0000000F + +/*****************************************************************************/ +#define OUT_CTRL1 0x404 +#define FLD_POLAR 0x7F000000 +/* Reserved [23] */ +#define FLD_RND_MODE 0x00600000 +#define FLD_VIPCLAMP_EN 0x00100000 +#define FLD_VIPBLANK_EN 0x00080000 +#define FLD_VIP_OPT_AL 0x00040000 +#define FLD_IDID0_SOURCE 0x00020000 +#define FLD_DCMODE 0x00010000 +#define FLD_CLK_GATING 0x0000C000 +#define FLD_CLK_INVERT 0x00002000 +#define FLD_HSFMT 0x00001000 +#define FLD_VALIDFMT 0x00000800 +#define FLD_ACTFMT 0x00000400 +#define FLD_SWAPRAW 0x00000200 +#define FLD_CLAMPRAW_EN 0x00000100 +#define FLD_BLUE_FIELD_EN 0x00000080 +#define FLD_BLUE_FIELD_ACT 0x00000040 +#define FLD_TASKBIT_VAL 0x00000020 +#define FLD_ANC_DATA_EN 0x00000010 +#define FLD_VBIHACTRAW_EN 0x00000008 +#define FLD_MODE10B 0x00000004 +#define FLD_OUT_MODE 0x00000003 + +/*****************************************************************************/ +#define OUT_CTRL2 0x408 +#define FLD_AUD_GRP 0xC0000000 +#define FLD_SAMPLE_RATE 0x30000000 +#define FLD_AUD_ANC_EN 0x08000000 +#define FLD_EN_C 0x04000000 +#define FLD_EN_B 0x02000000 +#define FLD_EN_A 0x01000000 +/* Reserved [23:20] */ +#define FLD_IDID1_LSB 0x000C0000 +#define FLD_IDID0_LSB 0x00030000 +#define FLD_IDID1_MSB 0x0000FF00 +#define FLD_IDID0_MSB 0x000000FF + +/*****************************************************************************/ +#define GEN_STAT 0x40C +#define FLD_VCR_DETECT 0x00800000 +#define FLD_SPECIAL_PLAY_N 0x00400000 +#define FLD_VPRES 0x00200000 +#define FLD_AGC_LOCK 0x00100000 +#define FLD_CSC_LOCK 0x00080000 +#define FLD_VLOCK 0x00040000 +#define FLD_SRC_LOCK 0x00020000 +#define FLD_HLOCK 0x00010000 +#define FLD_VSYNC_N 0x00008000 +#define FLD_SRC_FIFO_UFLOW 0x00004000 +#define FLD_SRC_FIFO_OFLOW 0x00002000 +#define FLD_FIELD 0x00001000 +#define FLD_AFD_FMT_STAT 0x00000F00 +#define FLD_MV_TYPE2_PAIR 0x00000080 +#define FLD_MV_T3CS 0x00000040 +#define FLD_MV_CS 0x00000020 +#define FLD_MV_PSP 0x00000010 +/* Reserved [3] */ +#define FLD_MV_CDAT 0x00000003 + +/*****************************************************************************/ +#define INT_STAT_MASK 0x410 +#define FLD_COMB_3D_FIFO_MSK 0x80000000 +#define FLD_WSS_DAT_AVAIL_MSK 0x40000000 +#define FLD_GS2_DAT_AVAIL_MSK 0x20000000 +#define FLD_GS1_DAT_AVAIL_MSK 0x10000000 +#define FLD_CC_DAT_AVAIL_MSK 0x08000000 +#define FLD_VPRES_CHANGE_MSK 0x04000000 +#define FLD_MV_CHANGE_MSK 0x02000000 +#define FLD_END_VBI_EVEN_MSK 0x01000000 +#define FLD_END_VBI_ODD_MSK 0x00800000 +#define FLD_FMT_CHANGE_MSK 0x00400000 +#define FLD_VSYNC_TRAIL_MSK 0x00200000 +#define FLD_HLOCK_CHANGE_MSK 0x00100000 +#define FLD_VLOCK_CHANGE_MSK 0x00080000 +#define FLD_CSC_LOCK_CHANGE_MSK 0x00040000 +#define FLD_SRC_FIFO_UFLOW_MSK 0x00020000 +#define FLD_SRC_FIFO_OFLOW_MSK 0x00010000 +#define FLD_COMB_3D_FIFO_STAT 0x00008000 +#define FLD_WSS_DAT_AVAIL_STAT 0x00004000 +#define FLD_GS2_DAT_AVAIL_STAT 0x00002000 +#define FLD_GS1_DAT_AVAIL_STAT 0x00001000 +#define FLD_CC_DAT_AVAIL_STAT 0x00000800 +#define FLD_VPRES_CHANGE_STAT 0x00000400 +#define FLD_MV_CHANGE_STAT 0x00000200 +#define FLD_END_VBI_EVEN_STAT 0x00000100 +#define FLD_END_VBI_ODD_STAT 0x00000080 +#define FLD_FMT_CHANGE_STAT 0x00000040 +#define FLD_VSYNC_TRAIL_STAT 0x00000020 +#define FLD_HLOCK_CHANGE_STAT 0x00000010 +#define FLD_VLOCK_CHANGE_STAT 0x00000008 +#define FLD_CSC_LOCK_CHANGE_STAT 0x00000004 +#define FLD_SRC_FIFO_UFLOW_STAT 0x00000002 +#define FLD_SRC_FIFO_OFLOW_STAT 0x00000001 + +/*****************************************************************************/ +#define LUMA_CTRL 0x414 +#define BRIGHTNESS_CTRL_BYTE 0x414 +#define CONTRAST_CTRL_BYTE 0x415 +#define LUMA_CTRL_BYTE_3 0x416 +#define FLD_LUMA_CORE_SEL 0x00C00000 +#define FLD_RANGE 0x00300000 +/* Reserved [19] */ +#define FLD_PEAK_EN 0x00040000 +#define FLD_PEAK_SEL 0x00030000 +#define FLD_CNTRST 0x0000FF00 +#define FLD_BRITE 0x000000FF + +/*****************************************************************************/ +#define HSCALE_CTRL 0x418 +#define FLD_HFILT 0x03000000 +#define FLD_HSCALE 0x00FFFFFF + +/*****************************************************************************/ +#define VSCALE_CTRL 0x41C +#define FLD_LINE_AVG_DIS 0x01000000 +/* Reserved [23:20] */ +#define FLD_VS_INTRLACE 0x00080000 +#define FLD_VFILT 0x00070000 +/* Reserved [15:13] */ +#define FLD_VSCALE 0x00001FFF + +/*****************************************************************************/ +#define CHROMA_CTRL 0x420 +#define USAT_CTRL_BYTE 0x420 +#define VSAT_CTRL_BYTE 0x421 +#define HUE_CTRL_BYTE 0x422 +#define FLD_C_LPF_EN 0x20000000 +#define FLD_CHR_DELAY 0x1C000000 +#define FLD_C_CORE_SEL 0x03000000 +#define FLD_HUE 0x00FF0000 +#define FLD_VSAT 0x0000FF00 +#define FLD_USAT 0x000000FF + +/*****************************************************************************/ +#define VBI_LINE_CTRL1 0x424 +#define FLD_VBI_MD_LINE4 0xFF000000 +#define FLD_VBI_MD_LINE3 0x00FF0000 +#define FLD_VBI_MD_LINE2 0x0000FF00 +#define FLD_VBI_MD_LINE1 0x000000FF + +/*****************************************************************************/ +#define VBI_LINE_CTRL2 0x428 +#define FLD_VBI_MD_LINE8 0xFF000000 +#define FLD_VBI_MD_LINE7 0x00FF0000 +#define FLD_VBI_MD_LINE6 0x0000FF00 +#define FLD_VBI_MD_LINE5 0x000000FF + +/*****************************************************************************/ +#define VBI_LINE_CTRL3 0x42C +#define FLD_VBI_MD_LINE12 0xFF000000 +#define FLD_VBI_MD_LINE11 0x00FF0000 +#define FLD_VBI_MD_LINE10 0x0000FF00 +#define FLD_VBI_MD_LINE9 0x000000FF + +/*****************************************************************************/ +#define VBI_LINE_CTRL4 0x430 +#define FLD_VBI_MD_LINE16 0xFF000000 +#define FLD_VBI_MD_LINE15 0x00FF0000 +#define FLD_VBI_MD_LINE14 0x0000FF00 +#define FLD_VBI_MD_LINE13 0x000000FF + +/*****************************************************************************/ +#define VBI_LINE_CTRL5 0x434 +#define FLD_VBI_MD_LINE17 0x000000FF + +/*****************************************************************************/ +#define VBI_FC_CFG 0x438 +#define FLD_FC_ALT2 0xFF000000 +#define FLD_FC_ALT1 0x00FF0000 +#define FLD_FC_ALT2_TYPE 0x0000F000 +#define FLD_FC_ALT1_TYPE 0x00000F00 +/* Reserved [7:1] */ +#define FLD_FC_SEARCH_MODE 0x00000001 + +/*****************************************************************************/ +#define VBI_MISC_CFG1 0x43C +#define FLD_TTX_PKTADRU 0xFFF00000 +#define FLD_TTX_PKTADRL 0x000FFF00 +/* Reserved [7:6] */ +#define FLD_MOJI_PACK_DIS 0x00000020 +#define FLD_VPS_DEC_DIS 0x00000010 +#define FLD_CRI_MARG_SCALE 0x0000000C +#define FLD_EDGE_RESYNC_EN 0x00000002 +#define FLD_ADAPT_SLICE_DIS 0x00000001 + +/*****************************************************************************/ +#define VBI_MISC_CFG2 0x440 +#define FLD_HAMMING_TYPE 0x0F000000 +/* Reserved [23:20] */ +#define FLD_WSS_FIFO_RST 0x00080000 +#define FLD_GS2_FIFO_RST 0x00040000 +#define FLD_GS1_FIFO_RST 0x00020000 +#define FLD_CC_FIFO_RST 0x00010000 +/* Reserved [15:12] */ +#define FLD_VBI3_SDID 0x00000F00 +#define FLD_VBI2_SDID 0x000000F0 +#define FLD_VBI1_SDID 0x0000000F + +/*****************************************************************************/ +#define VBI_PAY1 0x444 +#define FLD_GS1_FIFO_DAT 0xFF000000 +#define FLD_GS1_STAT 0x00FF0000 +#define FLD_CC_FIFO_DAT 0x0000FF00 +#define FLD_CC_STAT 0x000000FF + +/*****************************************************************************/ +#define VBI_PAY2 0x448 +#define FLD_WSS_FIFO_DAT 0xFF000000 +#define FLD_WSS_STAT 0x00FF0000 +#define FLD_GS2_FIFO_DAT 0x0000FF00 +#define FLD_GS2_STAT 0x000000FF + +/*****************************************************************************/ +#define VBI_CUST1_CFG1 0x44C +/* Reserved [31] */ +#define FLD_VBI1_CRIWIN 0x7F000000 +#define FLD_VBI1_SLICE_DIST 0x00F00000 +#define FLD_VBI1_BITINC 0x000FFF00 +#define FLD_VBI1_HDELAY 0x000000FF + +/*****************************************************************************/ +#define VBI_CUST1_CFG2 0x450 +#define FLD_VBI1_FC_LENGTH 0x1F000000 +#define FLD_VBI1_FRAME_CODE 0x00FFFFFF + +/*****************************************************************************/ +#define VBI_CUST1_CFG3 0x454 +#define FLD_VBI1_HAM_EN 0x80000000 +#define FLD_VBI1_FIFO_MODE 0x70000000 +#define FLD_VBI1_FORMAT_TYPE 0x0F000000 +#define FLD_VBI1_PAYLD_LENGTH 0x00FF0000 +#define FLD_VBI1_CRI_LENGTH 0x0000F000 +#define FLD_VBI1_CRI_MARGIN 0x00000F00 +#define FLD_VBI1_CRI_TIME 0x000000FF + +/*****************************************************************************/ +#define VBI_CUST2_CFG1 0x458 +/* Reserved [31] */ +#define FLD_VBI2_CRIWIN 0x7F000000 +#define FLD_VBI2_SLICE_DIST 0x00F00000 +#define FLD_VBI2_BITINC 0x000FFF00 +#define FLD_VBI2_HDELAY 0x000000FF + +/*****************************************************************************/ +#define VBI_CUST2_CFG2 0x45C +#define FLD_VBI2_FC_LENGTH 0x1F000000 +#define FLD_VBI2_FRAME_CODE 0x00FFFFFF + +/*****************************************************************************/ +#define VBI_CUST2_CFG3 0x460 +#define FLD_VBI2_HAM_EN 0x80000000 +#define FLD_VBI2_FIFO_MODE 0x70000000 +#define FLD_VBI2_FORMAT_TYPE 0x0F000000 +#define FLD_VBI2_PAYLD_LENGTH 0x00FF0000 +#define FLD_VBI2_CRI_LENGTH 0x0000F000 +#define FLD_VBI2_CRI_MARGIN 0x00000F00 +#define FLD_VBI2_CRI_TIME 0x000000FF + +/*****************************************************************************/ +#define VBI_CUST3_CFG1 0x464 +/* Reserved [31] */ +#define FLD_VBI3_CRIWIN 0x7F000000 +#define FLD_VBI3_SLICE_DIST 0x00F00000 +#define FLD_VBI3_BITINC 0x000FFF00 +#define FLD_VBI3_HDELAY 0x000000FF + +/*****************************************************************************/ +#define VBI_CUST3_CFG2 0x468 +#define FLD_VBI3_FC_LENGTH 0x1F000000 +#define FLD_VBI3_FRAME_CODE 0x00FFFFFF + +/*****************************************************************************/ +#define VBI_CUST3_CFG3 0x46C +#define FLD_VBI3_HAM_EN 0x80000000 +#define FLD_VBI3_FIFO_MODE 0x70000000 +#define FLD_VBI3_FORMAT_TYPE 0x0F000000 +#define FLD_VBI3_PAYLD_LENGTH 0x00FF0000 +#define FLD_VBI3_CRI_LENGTH 0x0000F000 +#define FLD_VBI3_CRI_MARGIN 0x00000F00 +#define FLD_VBI3_CRI_TIME 0x000000FF + +/*****************************************************************************/ +#define HORIZ_TIM_CTRL 0x470 +#define FLD_BGDEL_CNT 0xFF000000 +/* Reserved [23:22] */ +#define FLD_HACTIVE_CNT 0x003FF000 +/* Reserved [11:10] */ +#define FLD_HBLANK_CNT 0x000003FF + +/*****************************************************************************/ +#define VERT_TIM_CTRL 0x474 +#define FLD_V656BLANK_CNT 0xFF000000 +/* Reserved [23:22] */ +#define FLD_VACTIVE_CNT 0x003FF000 +/* Reserved [11:10] */ +#define FLD_VBLANK_CNT 0x000003FF + +/*****************************************************************************/ +#define SRC_COMB_CFG 0x478 +#define FLD_CCOMB_2LN_CHECK 0x80000000 +#define FLD_CCOMB_3LN_EN 0x40000000 +#define FLD_CCOMB_2LN_EN 0x20000000 +#define FLD_CCOMB_3D_EN 0x10000000 +/* Reserved [27] */ +#define FLD_LCOMB_3LN_EN 0x04000000 +#define FLD_LCOMB_2LN_EN 0x02000000 +#define FLD_LCOMB_3D_EN 0x01000000 +#define FLD_LUMA_LPF_SEL 0x00C00000 +#define FLD_UV_LPF_SEL 0x00300000 +#define FLD_BLEND_SLOPE 0x000F0000 +#define FLD_CCOMB_REDUCE_EN 0x00008000 +/* Reserved [14:10] */ +#define FLD_SRC_DECIM_RATIO 0x000003FF + +/*****************************************************************************/ +#define CHROMA_VBIOFF_CFG 0x47C +#define FLD_VBI_VOFFSET 0x1F000000 +/* Reserved [23:20] */ +#define FLD_SC_STEP 0x000FFFFF + +/*****************************************************************************/ +#define FIELD_COUNT 0x480 +#define FLD_FIELD_COUNT_FLD 0x000003FF + +/*****************************************************************************/ +#define MISC_TIM_CTRL 0x484 +#define FLD_DEBOUNCE_COUNT 0xC0000000 +#define FLD_VT_LINE_CNT_HYST 0x30000000 +/* Reserved [27] */ +#define FLD_AFD_STAT 0x07FF0000 +#define FLD_VPRES_VERT_EN 0x00008000 +/* Reserved [14:12] */ +#define FLD_HR32 0x00000800 +#define FLD_TDALGN 0x00000400 +#define FLD_TDFIELD 0x00000200 +/* Reserved [8:6] */ +#define FLD_TEMPDEC 0x0000003F + +/*****************************************************************************/ +#define DFE_CTRL1 0x488 +#define FLD_CLAMP_AUTO_EN 0x80000000 +#define FLD_AGC_AUTO_EN 0x40000000 +#define FLD_VGA_CRUSH_EN 0x20000000 +#define FLD_VGA_AUTO_EN 0x10000000 +#define FLD_VBI_GATE_EN 0x08000000 +#define FLD_CLAMP_LEVEL 0x07000000 +/* Reserved [23:22] */ +#define FLD_CLAMP_SKIP_CNT 0x00300000 +#define FLD_AGC_GAIN 0x000FFF00 +/* Reserved [7:6] */ +#define FLD_VGA_GAIN 0x0000003F + +/*****************************************************************************/ +#define DFE_CTRL2 0x48C +#define FLD_VGA_ACQUIRE_RANGE 0x00FF0000 +#define FLD_VGA_TRACK_RANGE 0x0000FF00 +#define FLD_VGA_SYNC 0x000000FF + +/*****************************************************************************/ +#define DFE_CTRL3 0x490 +#define FLD_BP_PERCENT 0xFF000000 +#define FLD_DFT_THRESHOLD 0x00FF0000 +/* Reserved [15:12] */ +#define FLD_SYNC_WIDTH_SEL 0x00000600 +#define FLD_BP_LOOP_GAIN 0x00000300 +#define FLD_SYNC_LOOP_GAIN 0x000000C0 +/* Reserved [5:4] */ +#define FLD_AGC_LOOP_GAIN 0x0000000C +#define FLD_DCC_LOOP_GAIN 0x00000003 + +/*****************************************************************************/ +#define PLL_CTRL 0x494 +#define FLD_PLL_KD 0xFF000000 +#define FLD_PLL_KI 0x00FF0000 +#define FLD_PLL_MAX_OFFSET 0x0000FFFF + + +/*****************************************************************************/ +#define HTL_CTRL 0x498 +/* Reserved [31:24] */ +#define FLD_AUTO_LOCK_SPD 0x00080000 +#define FLD_MAN_FAST_LOCK 0x00040000 +#define FLD_HTL_15K_EN 0x00020000 +#define FLD_HTL_500K_EN 0x00010000 +#define FLD_HTL_KD 0x0000FF00 +#define FLD_HTL_KI 0x000000FF + +/*****************************************************************************/ +#define COMB_CTRL 0x49C +#define FLD_COMB_PHASE_LIMIT 0xFF000000 +#define FLD_CCOMB_ERR_LIMIT 0x00FF0000 +#define FLD_LUMA_THRESHOLD 0x0000FF00 +#define FLD_LCOMB_ERR_LIMIT 0x000000FF + +/*****************************************************************************/ +#define CRUSH_CTRL 0x4A0 +#define FLD_WTW_EN 0x00400000 +#define FLD_CRUSH_FREQ 0x00200000 +#define FLD_MAJ_SEL_EN 0x00100000 +#define FLD_MAJ_SEL 0x000C0000 +/* Reserved [17:15] */ +#define FLD_SYNC_TIP_REDUCE 0x00007E00 +/* Reserved [8:6] */ +#define FLD_SYNC_TIP_INC 0x0000003F + +/*****************************************************************************/ +#define SOFT_RST_CTRL 0x4A4 +#define FLD_VD_SOFT_RST 0x00008000 +/* Reserved [14:12] */ +#define FLD_REG_RST_MSK 0x00000800 +#define FLD_VOF_RST_MSK 0x00000400 +#define FLD_MVDET_RST_MSK 0x00000200 +#define FLD_VBI_RST_MSK 0x00000100 +#define FLD_SCALE_RST_MSK 0x00000080 +#define FLD_CHROMA_RST_MSK 0x00000040 +#define FLD_LUMA_RST_MSK 0x00000020 +#define FLD_VTG_RST_MSK 0x00000010 +#define FLD_YCSEP_RST_MSK 0x00000008 +#define FLD_SRC_RST_MSK 0x00000004 +#define FLD_DFE_RST_MSK 0x00000002 +/* Reserved [0] */ + +/*****************************************************************************/ +#define MV_DT_CTRL1 0x4A8 +/* Reserved [31:29] */ +#define FLD_PSP_STOP_LINE 0x1F000000 +/* Reserved [23:21] */ +#define FLD_PSP_STRT_LINE 0x001F0000 +/* Reserved [15] */ +#define FLD_PSP_LLIMW 0x00007F00 +/* Reserved [7] */ +#define FLD_PSP_ULIMW 0x0000007F + +/*****************************************************************************/ +#define MV_DT_CTRL2 0x4AC +#define FLD_CS_STOPWIN 0xFF000000 +#define FLD_CS_STRTWIN 0x00FF0000 +#define FLD_CS_WIDTH 0x0000FF00 +#define FLD_PSP_SPEC_VAL 0x000000FF + +/*****************************************************************************/ +#define MV_DT_CTRL3 0x4B0 +#define FLD_AUTO_RATE_DIS 0x80000000 +#define FLD_HLOCK_DIS 0x40000000 +#define FLD_SEL_FIELD_CNT 0x20000000 +#define FLD_CS_TYPE2_SEL 0x10000000 +#define FLD_CS_LINE_THRSH_SEL 0x08000000 +#define FLD_CS_ATHRESH_SEL 0x04000000 +#define FLD_PSP_SPEC_SEL 0x02000000 +#define FLD_PSP_LINES_SEL 0x01000000 +#define FLD_FIELD_CNT 0x00F00000 +#define FLD_CS_TYPE2_CNT 0x000FC000 +#define FLD_CS_LINE_CNT 0x00003F00 +#define FLD_CS_ATHRESH_LEV 0x000000FF + +/*****************************************************************************/ +#define CHIP_VERSION 0x4B4 +/* Cx231xx redefine */ +#define VERSION 0x4B4 +#define FLD_REV_ID 0x000000FF + +/*****************************************************************************/ +#define MISC_DIAG_CTRL 0x4B8 +/* Reserved [31:24] */ +#define FLD_SC_CONVERGE_THRESH 0x00FF0000 +#define FLD_CCOMB_ERR_LIMIT_3D 0x0000FF00 +#define FLD_LCOMB_ERR_LIMIT_3D 0x000000FF + +/*****************************************************************************/ +#define VBI_PASS_CTRL 0x4BC +#define FLD_VBI_PASS_MD 0x00200000 +#define FLD_VBI_SETUP_DIS 0x00100000 +#define FLD_PASS_LINE_CTRL 0x000FFFFF + +/*****************************************************************************/ +/* Cx231xx redefine */ +#define VCR_DET_CTRL 0x4c0 +#define FLD_EN_FIELD_PHASE_DET 0x80000000 +#define FLD_EN_HEAD_SW_DET 0x40000000 +#define FLD_FIELD_PHASE_LENGTH 0x01FF0000 +/* Reserved [29:25] */ +#define FLD_FIELD_PHASE_DELAY 0x0000FF00 +#define FLD_FIELD_PHASE_LIMIT 0x000000F0 +#define FLD_HEAD_SW_DET_LIMIT 0x0000000F + + +/*****************************************************************************/ +#define DL_CTL 0x800 +#define DL_CTL_ADDRESS_LOW 0x800 /* Byte 1 in DL_CTL */ +#define DL_CTL_ADDRESS_HIGH 0x801 /* Byte 2 in DL_CTL */ +#define DL_CTL_DATA 0x802 /* Byte 3 in DL_CTL */ +#define DL_CTL_CONTROL 0x803 /* Byte 4 in DL_CTL */ +/* Reserved [31:5] */ +#define FLD_START_8051 0x10000000 +#define FLD_DL_ENABLE 0x08000000 +#define FLD_DL_AUTO_INC 0x04000000 +#define FLD_DL_MAP 0x03000000 + +/*****************************************************************************/ +#define STD_DET_STATUS 0x804 +#define FLD_SPARE_STATUS1 0xFF000000 +#define FLD_SPARE_STATUS0 0x00FF0000 +#define FLD_MOD_DET_STATUS1 0x0000FF00 +#define FLD_MOD_DET_STATUS0 0x000000FF + +/*****************************************************************************/ +#define AUD_BUILD_NUM 0x806 +#define AUD_VER_NUM 0x807 +#define STD_DET_CTL 0x808 +#define STD_DET_CTL_AUD_CTL 0x808 /* Byte 1 in STD_DET_CTL */ +#define STD_DET_CTL_PREF_MODE 0x809 /* Byte 2 in STD_DET_CTL */ +#define FLD_SPARE_CTL0 0xFF000000 +#define FLD_DIS_DBX 0x00800000 +#define FLD_DIS_BTSC 0x00400000 +#define FLD_DIS_NICAM_A2 0x00200000 +#define FLD_VIDEO_PRESENT 0x00100000 +#define FLD_DW8051_VIDEO_FORMAT 0x000F0000 +#define FLD_PREF_DEC_MODE 0x0000FF00 +#define FLD_AUD_CONFIG 0x000000FF + +/*****************************************************************************/ +#define DW8051_INT 0x80C +#define FLD_VIDEO_PRESENT_CHANGE 0x80000000 +#define FLD_VIDEO_CHANGE 0x40000000 +#define FLD_RDS_READY 0x20000000 +#define FLD_AC97_INT 0x10000000 +#define FLD_NICAM_BIT_ERROR_TOO_HIGH 0x08000000 +#define FLD_NICAM_LOCK 0x04000000 +#define FLD_NICAM_UNLOCK 0x02000000 +#define FLD_DFT4_TH_CMP 0x01000000 +/* Reserved [23:22] */ +#define FLD_LOCK_IND_INT 0x00200000 +#define FLD_DFT3_TH_CMP 0x00100000 +#define FLD_DFT2_TH_CMP 0x00080000 +#define FLD_DFT1_TH_CMP 0x00040000 +#define FLD_FM2_DFT_TH_CMP 0x00020000 +#define FLD_FM1_DFT_TH_CMP 0x00010000 +#define FLD_VIDEO_PRESENT_EN 0x00008000 +#define FLD_VIDEO_CHANGE_EN 0x00004000 +#define FLD_RDS_READY_EN 0x00002000 +#define FLD_AC97_INT_EN 0x00001000 +#define FLD_NICAM_BIT_ERROR_TOO_HIGH_EN 0x00000800 +#define FLD_NICAM_LOCK_EN 0x00000400 +#define FLD_NICAM_UNLOCK_EN 0x00000200 +#define FLD_DFT4_TH_CMP_EN 0x00000100 +/* Reserved [7] */ +#define FLD_DW8051_INT6_CTL1 0x00000040 +#define FLD_DW8051_INT5_CTL1 0x00000020 +#define FLD_DW8051_INT4_CTL1 0x00000010 +#define FLD_DW8051_INT3_CTL1 0x00000008 +#define FLD_DW8051_INT2_CTL1 0x00000004 +#define FLD_DW8051_INT1_CTL1 0x00000002 +#define FLD_DW8051_INT0_CTL1 0x00000001 + +/*****************************************************************************/ +#define GENERAL_CTL 0x810 +#define FLD_RDS_INT 0x80000000 +#define FLD_NBER_INT 0x40000000 +#define FLD_NLL_INT 0x20000000 +#define FLD_IFL_INT 0x10000000 +#define FLD_FDL_INT 0x08000000 +#define FLD_AFC_INT 0x04000000 +#define FLD_AMC_INT 0x02000000 +#define FLD_AC97_INT_CTL 0x01000000 +#define FLD_RDS_INT_DIS 0x00800000 +#define FLD_NBER_INT_DIS 0x00400000 +#define FLD_NLL_INT_DIS 0x00200000 +#define FLD_IFL_INT_DIS 0x00100000 +#define FLD_FDL_INT_DIS 0x00080000 +#define FLD_FC_INT_DIS 0x00040000 +#define FLD_AMC_INT_DIS 0x00020000 +#define FLD_AC97_INT_DIS 0x00010000 +#define FLD_REV_NUM 0x0000FF00 +/* Reserved [7:5] */ +#define FLD_DBX_SOFT_RESET_REG 0x00000010 +#define FLD_AD_SOFT_RESET_REG 0x00000008 +#define FLD_SRC_SOFT_RESET_REG 0x00000004 +#define FLD_CDMOD_SOFT_RESET 0x00000002 +#define FLD_8051_SOFT_RESET 0x00000001 + +/*****************************************************************************/ +#define AAGC_CTL 0x814 +#define FLD_AFE_12DB_EN 0x80000000 +#define FLD_AAGC_DEFAULT_EN 0x40000000 +#define FLD_AAGC_DEFAULT 0x3F000000 +/* Reserved [23] */ +#define FLD_AAGC_GAIN 0x00600000 +#define FLD_AAGC_TH 0x001F0000 +/* Reserved [15:14] */ +#define FLD_AAGC_HYST2 0x00003F00 +/* Reserved [7:6] */ +#define FLD_AAGC_HYST1 0x0000003F + +/*****************************************************************************/ +#define IF_SRC_CTL 0x818 +#define FLD_DBX_BYPASS 0x80000000 +/* Reserved [30:25] */ +#define FLD_IF_SRC_MODE 0x01000000 +/* Reserved [23:18] */ +#define FLD_IF_SRC_PHASE_INC 0x0001FFFF + +/*****************************************************************************/ +#define ANALOG_DEMOD_CTL 0x81C +#define FLD_ROT1_PHACC_PROG 0xFFFF0000 +/* Reserved [15] */ +#define FLD_FM1_DELAY_FIX 0x00007000 +#define FLD_PDF4_SHIFT 0x00000C00 +#define FLD_PDF3_SHIFT 0x00000300 +#define FLD_PDF2_SHIFT 0x000000C0 +#define FLD_PDF1_SHIFT 0x00000030 +#define FLD_FMBYPASS_MODE2 0x00000008 +#define FLD_FMBYPASS_MODE1 0x00000004 +#define FLD_NICAM_MODE 0x00000002 +#define FLD_BTSC_FMRADIO_MODE 0x00000001 + +/*****************************************************************************/ +#define ROT_FREQ_CTL 0x820 +#define FLD_ROT3_PHACC_PROG 0xFFFF0000 +#define FLD_ROT2_PHACC_PROG 0x0000FFFF + +/*****************************************************************************/ +#define FM_CTL 0x824 +#define FLD_FM2_DC_FB_SHIFT 0xF0000000 +#define FLD_FM2_DC_INT_SHIFT 0x0F000000 +#define FLD_FM2_AFC_RESET 0x00800000 +#define FLD_FM2_DC_PASS_IN 0x00400000 +#define FLD_FM2_DAGC_SHIFT 0x00380000 +#define FLD_FM2_CORDIC_SHIFT 0x00070000 +#define FLD_FM1_DC_FB_SHIFT 0x0000F000 +#define FLD_FM1_DC_INT_SHIFT 0x00000F00 +#define FLD_FM1_AFC_RESET 0x00000080 +#define FLD_FM1_DC_PASS_IN 0x00000040 +#define FLD_FM1_DAGC_SHIFT 0x00000038 +#define FLD_FM1_CORDIC_SHIFT 0x00000007 + +/*****************************************************************************/ +#define LPF_PDF_CTL 0x828 +/* Reserved [31:30] */ +#define FLD_LPF32_SHIFT1 0x30000000 +#define FLD_LPF32_SHIFT2 0x0C000000 +#define FLD_LPF160_SHIFTA 0x03000000 +#define FLD_LPF160_SHIFTB 0x00C00000 +#define FLD_LPF160_SHIFTC 0x00300000 +#define FLD_LPF32_COEF_SEL2 0x000C0000 +#define FLD_LPF32_COEF_SEL1 0x00030000 +#define FLD_LPF160_COEF_SELC 0x0000C000 +#define FLD_LPF160_COEF_SELB 0x00003000 +#define FLD_LPF160_COEF_SELA 0x00000C00 +#define FLD_LPF160_IN_EN_REG 0x00000300 +#define FLD_PDF4_PDF_SEL 0x000000C0 +#define FLD_PDF3_PDF_SEL 0x00000030 +#define FLD_PDF2_PDF_SEL 0x0000000C +#define FLD_PDF1_PDF_SEL 0x00000003 + +/*****************************************************************************/ +#define DFT1_CTL1 0x82C +#define FLD_DFT1_DWELL 0xFFFF0000 +#define FLD_DFT1_FREQ 0x0000FFFF + +/*****************************************************************************/ +#define DFT1_CTL2 0x830 +#define FLD_DFT1_THRESHOLD 0xFFFFFF00 +#define FLD_DFT1_CMP_CTL 0x00000080 +#define FLD_DFT1_AVG 0x00000070 +/* Reserved [3:1] */ +#define FLD_DFT1_START 0x00000001 + +/*****************************************************************************/ +#define DFT1_STATUS 0x834 +#define FLD_DFT1_DONE 0x80000000 +#define FLD_DFT1_TH_CMP_STAT 0x40000000 +#define FLD_DFT1_RESULT 0x3FFFFFFF + +/*****************************************************************************/ +#define DFT2_CTL1 0x838 +#define FLD_DFT2_DWELL 0xFFFF0000 +#define FLD_DFT2_FREQ 0x0000FFFF + +/*****************************************************************************/ +#define DFT2_CTL2 0x83C +#define FLD_DFT2_THRESHOLD 0xFFFFFF00 +#define FLD_DFT2_CMP_CTL 0x00000080 +#define FLD_DFT2_AVG 0x00000070 +/* Reserved [3:1] */ +#define FLD_DFT2_START 0x00000001 + +/*****************************************************************************/ +#define DFT2_STATUS 0x840 +#define FLD_DFT2_DONE 0x80000000 +#define FLD_DFT2_TH_CMP_STAT 0x40000000 +#define FLD_DFT2_RESULT 0x3FFFFFFF + +/*****************************************************************************/ +#define DFT3_CTL1 0x844 +#define FLD_DFT3_DWELL 0xFFFF0000 +#define FLD_DFT3_FREQ 0x0000FFFF + +/*****************************************************************************/ +#define DFT3_CTL2 0x848 +#define FLD_DFT3_THRESHOLD 0xFFFFFF00 +#define FLD_DFT3_CMP_CTL 0x00000080 +#define FLD_DFT3_AVG 0x00000070 +/* Reserved [3:1] */ +#define FLD_DFT3_START 0x00000001 + +/*****************************************************************************/ +#define DFT3_STATUS 0x84C +#define FLD_DFT3_DONE 0x80000000 +#define FLD_DFT3_TH_CMP_STAT 0x40000000 +#define FLD_DFT3_RESULT 0x3FFFFFFF + +/*****************************************************************************/ +#define DFT4_CTL1 0x850 +#define FLD_DFT4_DWELL 0xFFFF0000 +#define FLD_DFT4_FREQ 0x0000FFFF + +/*****************************************************************************/ +#define DFT4_CTL2 0x854 +#define FLD_DFT4_THRESHOLD 0xFFFFFF00 +#define FLD_DFT4_CMP_CTL 0x00000080 +#define FLD_DFT4_AVG 0x00000070 +/* Reserved [3:1] */ +#define FLD_DFT4_START 0x00000001 + +/*****************************************************************************/ +#define DFT4_STATUS 0x858 +#define FLD_DFT4_DONE 0x80000000 +#define FLD_DFT4_TH_CMP_STAT 0x40000000 +#define FLD_DFT4_RESULT 0x3FFFFFFF + +/*****************************************************************************/ +#define AM_MTS_DET 0x85C +#define FLD_AM_MTS_MODE 0x80000000 +/* Reserved [30:26] */ +#define FLD_AM_SUB 0x02000000 +#define FLD_AM_GAIN_EN 0x01000000 +/* Reserved [23:16] */ +#define FLD_AMMTS_GAIN_SCALE 0x0000E000 +#define FLD_MTS_PDF_SHIFT 0x00001800 +#define FLD_AM_REG_GAIN 0x00000700 +#define FLD_AGC_REF 0x000000FF + +/*****************************************************************************/ +#define ANALOG_MUX_CTL 0x860 +/* Reserved [31:29] */ +#define FLD_MUX21_SEL 0x10000000 +#define FLD_MUX20_SEL 0x08000000 +#define FLD_MUX19_SEL 0x04000000 +#define FLD_MUX18_SEL 0x02000000 +#define FLD_MUX17_SEL 0x01000000 +#define FLD_MUX16_SEL 0x00800000 +#define FLD_MUX15_SEL 0x00400000 +#define FLD_MUX14_SEL 0x00300000 +#define FLD_MUX13_SEL 0x000C0000 +#define FLD_MUX12_SEL 0x00020000 +#define FLD_MUX11_SEL 0x00018000 +#define FLD_MUX10_SEL 0x00004000 +#define FLD_MUX9_SEL 0x00002000 +#define FLD_MUX8_SEL 0x00001000 +#define FLD_MUX7_SEL 0x00000800 +#define FLD_MUX6_SEL 0x00000600 +#define FLD_MUX5_SEL 0x00000100 +#define FLD_MUX4_SEL 0x000000C0 +#define FLD_MUX3_SEL 0x00000030 +#define FLD_MUX2_SEL 0x0000000C +#define FLD_MUX1_SEL 0x00000003 + +/*****************************************************************************/ +/* Cx231xx redefine */ +#define DPLL_CTRL1 0x864 +#define DIG_PLL_CTL1 0x864 + +#define FLD_PLL_STATUS 0x07000000 +#define FLD_BANDWIDTH_SELECT 0x00030000 +#define FLD_PLL_SHIFT_REG 0x00007000 +#define FLD_PHASE_SHIFT 0x000007FF + +/*****************************************************************************/ +/* Cx231xx redefine */ +#define DPLL_CTRL2 0x868 +#define DIG_PLL_CTL2 0x868 +#define FLD_PLL_UNLOCK_THR 0xFF000000 +#define FLD_PLL_LOCK_THR 0x00FF0000 +/* Reserved [15:8] */ +#define FLD_AM_PDF_SEL2 0x000000C0 +#define FLD_AM_PDF_SEL1 0x00000030 +#define FLD_DPLL_FSM_CTRL 0x0000000C +/* Reserved [1] */ +#define FLD_PLL_PILOT_DET 0x00000001 + +/*****************************************************************************/ +/* Cx231xx redefine */ +#define DPLL_CTRL3 0x86C +#define DIG_PLL_CTL3 0x86C +#define FLD_DISABLE_LOOP 0x01000000 +#define FLD_A1_DS1_SEL 0x000C0000 +#define FLD_A1_DS2_SEL 0x00030000 +#define FLD_A1_KI 0x0000FF00 +#define FLD_A1_KD 0x000000FF + +/*****************************************************************************/ +/* Cx231xx redefine */ +#define DPLL_CTRL4 0x870 +#define DIG_PLL_CTL4 0x870 +#define FLD_A2_DS1_SEL 0x000C0000 +#define FLD_A2_DS2_SEL 0x00030000 +#define FLD_A2_KI 0x0000FF00 +#define FLD_A2_KD 0x000000FF + +/*****************************************************************************/ +/* Cx231xx redefine */ +#define DPLL_CTRL5 0x874 +#define DIG_PLL_CTL5 0x874 +#define FLD_TRK_DS1_SEL 0x000C0000 +#define FLD_TRK_DS2_SEL 0x00030000 +#define FLD_TRK_KI 0x0000FF00 +#define FLD_TRK_KD 0x000000FF + +/*****************************************************************************/ +#define DEEMPH_GAIN_CTL 0x878 +#define FLD_DEEMPH2_GAIN 0xFFFF0000 +#define FLD_DEEMPH1_GAIN 0x0000FFFF + +/*****************************************************************************/ +/* Cx231xx redefine */ +#define DEEMPH_COEFF1 0x87C +#define DEEMPH_COEF1 0x87C +#define FLD_DEEMPH_B0 0xFFFF0000 +#define FLD_DEEMPH_A0 0x0000FFFF + +/*****************************************************************************/ +/* Cx231xx redefine */ +#define DEEMPH_COEFF2 0x880 +#define DEEMPH_COEF2 0x880 +#define FLD_DEEMPH_B1 0xFFFF0000 +#define FLD_DEEMPH_A1 0x0000FFFF + +/*****************************************************************************/ +#define DBX1_CTL1 0x884 +#define FLD_DBX1_WBE_GAIN 0xFFFF0000 +#define FLD_DBX1_IN_GAIN 0x0000FFFF + +/*****************************************************************************/ +#define DBX1_CTL2 0x888 +#define FLD_DBX1_SE_BYPASS 0xFFFF0000 +#define FLD_DBX1_SE_GAIN 0x0000FFFF + +/*****************************************************************************/ +#define DBX1_RMS_SE 0x88C +#define FLD_DBX1_RMS_WBE 0xFFFF0000 +#define FLD_DBX1_RMS_SE_FLD 0x0000FFFF + +/*****************************************************************************/ +#define DBX2_CTL1 0x890 +#define FLD_DBX2_WBE_GAIN 0xFFFF0000 +#define FLD_DBX2_IN_GAIN 0x0000FFFF + +/*****************************************************************************/ +#define DBX2_CTL2 0x894 +#define FLD_DBX2_SE_BYPASS 0xFFFF0000 +#define FLD_DBX2_SE_GAIN 0x0000FFFF + +/*****************************************************************************/ +#define DBX2_RMS_SE 0x898 +#define FLD_DBX2_RMS_WBE 0xFFFF0000 +#define FLD_DBX2_RMS_SE_FLD 0x0000FFFF + +/*****************************************************************************/ +#define AM_FM_DIFF 0x89C +/* Reserved [31] */ +#define FLD_FM_DIFF_OUT 0x7FFF0000 +/* Reserved [15] */ +#define FLD_AM_DIFF_OUT 0x00007FFF + +/*****************************************************************************/ +#define NICAM_FAW 0x8A0 +#define FLD_FAWDETWINEND 0xFC000000 +#define FLD_FAWDETWINSTR 0x03FF0000 +/* Reserved [15:12] */ +#define FLD_FAWDETTHRSHLD3 0x00000F00 +#define FLD_FAWDETTHRSHLD2 0x000000F0 +#define FLD_FAWDETTHRSHLD1 0x0000000F + +/*****************************************************************************/ +/* Cx231xx redefine */ +#define DEEMPH_GAIN 0x8A4 +#define NICAM_DEEMPHGAIN 0x8A4 +/* Reserved [31:18] */ +#define FLD_DEEMPHGAIN 0x0003FFFF + +/*****************************************************************************/ +/* Cx231xx redefine */ +#define DEEMPH_NUMER1 0x8A8 +#define NICAM_DEEMPHNUMER1 0x8A8 +/* Reserved [31:18] */ +#define FLD_DEEMPHNUMER1 0x0003FFFF + +/*****************************************************************************/ +/* Cx231xx redefine */ +#define DEEMPH_NUMER2 0x8AC +#define NICAM_DEEMPHNUMER2 0x8AC +/* Reserved [31:18] */ +#define FLD_DEEMPHNUMER2 0x0003FFFF + +/*****************************************************************************/ +/* Cx231xx redefine */ +#define DEEMPH_DENOM1 0x8B0 +#define NICAM_DEEMPHDENOM1 0x8B0 +/* Reserved [31:18] */ +#define FLD_DEEMPHDENOM1 0x0003FFFF + +/*****************************************************************************/ +/* Cx231xx redefine */ +#define DEEMPH_DENOM2 0x8B4 +#define NICAM_DEEMPHDENOM2 0x8B4 +/* Reserved [31:18] */ +#define FLD_DEEMPHDENOM2 0x0003FFFF + +/*****************************************************************************/ +#define NICAM_ERRLOG_CTL1 0x8B8 +/* Reserved [31:28] */ +#define FLD_ERRINTRPTTHSHLD1 0x0FFF0000 +/* Reserved [15:12] */ +#define FLD_ERRLOGPERIOD 0x00000FFF + +/*****************************************************************************/ +#define NICAM_ERRLOG_CTL2 0x8BC +/* Reserved [31:28] */ +#define FLD_ERRINTRPTTHSHLD3 0x0FFF0000 +/* Reserved [15:12] */ +#define FLD_ERRINTRPTTHSHLD2 0x00000FFF + +/*****************************************************************************/ +#define NICAM_ERRLOG_STS1 0x8C0 +/* Reserved [31:28] */ +#define FLD_ERRLOG2 0x0FFF0000 +/* Reserved [15:12] */ +#define FLD_ERRLOG1 0x00000FFF + +/*****************************************************************************/ +#define NICAM_ERRLOG_STS2 0x8C4 +/* Reserved [31:12] */ +#define FLD_ERRLOG3 0x00000FFF + +/*****************************************************************************/ +#define NICAM_STATUS 0x8C8 +/* Reserved [31:20] */ +#define FLD_NICAM_CIB 0x000C0000 +#define FLD_NICAM_LOCK_STAT 0x00020000 +#define FLD_NICAM_MUTE 0x00010000 +#define FLD_NICAMADDIT_DATA 0x0000FFE0 +#define FLD_NICAMCNTRL 0x0000001F + +/*****************************************************************************/ +#define DEMATRIX_CTL 0x8CC +#define FLD_AC97_IN_SHIFT 0xF0000000 +#define FLD_I2S_IN_SHIFT 0x0F000000 +#define FLD_DEMATRIX_SEL_CTL 0x00FF0000 +/* Reserved [15:11] */ +#define FLD_DMTRX_BYPASS 0x00000400 +#define FLD_DEMATRIX_MODE 0x00000300 +/* Reserved [7:6] */ +#define FLD_PH_DBX_SEL 0x00000020 +#define FLD_PH_CH_SEL 0x00000010 +#define FLD_PHASE_FIX 0x0000000F + +/*****************************************************************************/ +#define PATH1_CTL1 0x8D0 +/* Reserved [31:29] */ +#define FLD_PATH1_MUTE_CTL 0x1F000000 +/* Reserved [23:22] */ +#define FLD_PATH1_AVC_CG 0x00300000 +#define FLD_PATH1_AVC_RT 0x000F0000 +#define FLD_PATH1_AVC_AT 0x0000F000 +#define FLD_PATH1_AVC_STEREO 0x00000800 +#define FLD_PATH1_AVC_CR 0x00000700 +#define FLD_PATH1_AVC_RMS_CON 0x000000F0 +#define FLD_PATH1_SEL_CTL 0x0000000F + +/*****************************************************************************/ +#define PATH1_VOL_CTL 0x8D4 +#define FLD_PATH1_AVC_THRESHOLD 0x7FFF0000 +#define FLD_PATH1_BAL_LEFT 0x00008000 +#define FLD_PATH1_BAL_LEVEL 0x00007F00 +#define FLD_PATH1_VOLUME 0x000000FF + +/*****************************************************************************/ +#define PATH1_EQ_CTL 0x8D8 +/* Reserved [31:30] */ +#define FLD_PATH1_EQ_TREBLE_VOL 0x3F000000 +/* Reserved [23:22] */ +#define FLD_PATH1_EQ_MID_VOL 0x003F0000 +/* Reserved [15:14] */ +#define FLD_PATH1_EQ_BASS_VOL 0x00003F00 +/* Reserved [7:1] */ +#define FLD_PATH1_EQ_BAND_SEL 0x00000001 + +/*****************************************************************************/ +#define PATH1_SC_CTL 0x8DC +#define FLD_PATH1_SC_THRESHOLD 0x7FFF0000 +#define FLD_PATH1_SC_RT 0x0000F000 +#define FLD_PATH1_SC_AT 0x00000F00 +#define FLD_PATH1_SC_STEREO 0x00000080 +#define FLD_PATH1_SC_CR 0x00000070 +#define FLD_PATH1_SC_RMS_CON 0x0000000F + +/*****************************************************************************/ +#define PATH2_CTL1 0x8E0 +/* Reserved [31:26] */ +#define FLD_PATH2_MUTE_CTL 0x03000000 +/* Reserved [23:22] */ +#define FLD_PATH2_AVC_CG 0x00300000 +#define FLD_PATH2_AVC_RT 0x000F0000 +#define FLD_PATH2_AVC_AT 0x0000F000 +#define FLD_PATH2_AVC_STEREO 0x00000800 +#define FLD_PATH2_AVC_CR 0x00000700 +#define FLD_PATH2_AVC_RMS_CON 0x000000F0 +#define FLD_PATH2_SEL_CTL 0x0000000F + +/*****************************************************************************/ +#define PATH2_VOL_CTL 0x8E4 +#define FLD_PATH2_AVC_THRESHOLD 0xFFFF0000 +#define FLD_PATH2_BAL_LEFT 0x00008000 +#define FLD_PATH2_BAL_LEVEL 0x00007F00 +#define FLD_PATH2_VOLUME 0x000000FF + +/*****************************************************************************/ +#define PATH2_EQ_CTL 0x8E8 +/* Reserved [31:30] */ +#define FLD_PATH2_EQ_TREBLE_VOL 0x3F000000 +/* Reserved [23:22] */ +#define FLD_PATH2_EQ_MID_VOL 0x003F0000 +/* Reserved [15:14] */ +#define FLD_PATH2_EQ_BASS_VOL 0x00003F00 +/* Reserved [7:1] */ +#define FLD_PATH2_EQ_BAND_SEL 0x00000001 + +/*****************************************************************************/ +#define PATH2_SC_CTL 0x8EC +#define FLD_PATH2_SC_THRESHOLD 0xFFFF0000 +#define FLD_PATH2_SC_RT 0x0000F000 +#define FLD_PATH2_SC_AT 0x00000F00 +#define FLD_PATH2_SC_STEREO 0x00000080 +#define FLD_PATH2_SC_CR 0x00000070 +#define FLD_PATH2_SC_RMS_CON 0x0000000F + +/*****************************************************************************/ +#define SRC_CTL 0x8F0 +#define FLD_SRC_STATUS 0xFFFFFF00 +#define FLD_FIFO_LF_EN 0x000000FC +#define FLD_BYPASS_LI 0x00000002 +#define FLD_BYPASS_PF 0x00000001 + +/*****************************************************************************/ +#define SRC_LF_COEF 0x8F4 +#define FLD_LOOP_FILTER_COEF2 0xFFFF0000 +#define FLD_LOOP_FILTER_COEF1 0x0000FFFF + +/*****************************************************************************/ +#define SRC1_CTL 0x8F8 +/* Reserved [31:28] */ +#define FLD_SRC1_FIFO_RD_TH 0x0F000000 +/* Reserved [23:18] */ +#define FLD_SRC1_PHASE_INC 0x0003FFFF + +/*****************************************************************************/ +#define SRC2_CTL 0x8FC +/* Reserved [31:28] */ +#define FLD_SRC2_FIFO_RD_TH 0x0F000000 +/* Reserved [23:18] */ +#define FLD_SRC2_PHASE_INC 0x0003FFFF + +/*****************************************************************************/ +#define SRC3_CTL 0x900 +/* Reserved [31:28] */ +#define FLD_SRC3_FIFO_RD_TH 0x0F000000 +/* Reserved [23:18] */ +#define FLD_SRC3_PHASE_INC 0x0003FFFF + +/*****************************************************************************/ +#define SRC4_CTL 0x904 +/* Reserved [31:28] */ +#define FLD_SRC4_FIFO_RD_TH 0x0F000000 +/* Reserved [23:18] */ +#define FLD_SRC4_PHASE_INC 0x0003FFFF + +/*****************************************************************************/ +#define SRC5_CTL 0x908 +/* Reserved [31:28] */ +#define FLD_SRC5_FIFO_RD_TH 0x0F000000 +/* Reserved [23:18] */ +#define FLD_SRC5_PHASE_INC 0x0003FFFF + +/*****************************************************************************/ +#define SRC6_CTL 0x90C +/* Reserved [31:28] */ +#define FLD_SRC6_FIFO_RD_TH 0x0F000000 +/* Reserved [23:18] */ +#define FLD_SRC6_PHASE_INC 0x0003FFFF + +/*****************************************************************************/ +#define BAND_OUT_SEL 0x910 +#define FLD_SRC6_IN_SEL 0xC0000000 +#define FLD_SRC6_CLK_SEL 0x30000000 +#define FLD_SRC5_IN_SEL 0x0C000000 +#define FLD_SRC5_CLK_SEL 0x03000000 +#define FLD_SRC4_IN_SEL 0x00C00000 +#define FLD_SRC4_CLK_SEL 0x00300000 +#define FLD_SRC3_IN_SEL 0x000C0000 +#define FLD_SRC3_CLK_SEL 0x00030000 +#define FLD_BASEBAND_BYPASS_CTL 0x0000FF00 +#define FLD_AC97_SRC_SEL 0x000000C0 +#define FLD_I2S_SRC_SEL 0x00000030 +#define FLD_PARALLEL2_SRC_SEL 0x0000000C +#define FLD_PARALLEL1_SRC_SEL 0x00000003 + +/*****************************************************************************/ +#define I2S_IN_CTL 0x914 +/* Reserved [31:11] */ +#define FLD_I2S_UP2X_BW20K 0x00000400 +#define FLD_I2S_UP2X_BYPASS 0x00000200 +#define FLD_I2S_IN_MASTER_MODE 0x00000100 +#define FLD_I2S_IN_SONY_MODE 0x00000080 +#define FLD_I2S_IN_RIGHT_JUST 0x00000040 +#define FLD_I2S_IN_WS_SEL 0x00000020 +#define FLD_I2S_IN_BCN_DEL 0x0000001F + +/*****************************************************************************/ +#define I2S_OUT_CTL 0x918 +/* Reserved [31:17] */ +#define FLD_I2S_OUT_SOFT_RESET_EN 0x00010000 +/* Reserved [15:9] */ +#define FLD_I2S_OUT_MASTER_MODE 0x00000100 +#define FLD_I2S_OUT_SONY_MODE 0x00000080 +#define FLD_I2S_OUT_RIGHT_JUST 0x00000040 +#define FLD_I2S_OUT_WS_SEL 0x00000020 +#define FLD_I2S_OUT_BCN_DEL 0x0000001F + + +/*****************************************************************************/ +#define AC97_CTL 0x91C +/* Reserved [31:26] */ +#define FLD_AC97_UP2X_BW20K 0x02000000 +#define FLD_AC97_UP2X_BYPASS 0x01000000 +/* Reserved [23:17] */ +#define FLD_AC97_RST_ACL 0x00010000 +/* Reserved [15:9] */ +#define FLD_AC97_WAKE_UP_SYNC 0x00000100 +/* Reserved [7:1] */ +#define FLD_AC97_SHUTDOWN 0x00000001 + + +/* Cx231xx redefine */ +#define QPSK_IAGC_CTL1 0x94c +#define QPSK_IAGC_CTL2 0x950 +#define QPSK_FEPR_FREQ 0x954 +#define QPSK_BTL_CTL1 0x958 +#define QPSK_BTL_CTL2 0x95c +#define QPSK_CTL_CTL1 0x960 +#define QPSK_CTL_CTL2 0x964 +#define QPSK_MF_FAGC_CTL 0x968 +#define QPSK_EQ_CTL 0x96c +#define QPSK_LOCK_CTL 0x970 + + +/*****************************************************************************/ +#define FM1_DFT_CTL 0x9A8 +#define FLD_FM1_DFT_THRESHOLD 0xFFFF0000 +/* Reserved [15:8] */ +#define FLD_FM1_DFT_CMP_CTL 0x00000080 +#define FLD_FM1_DFT_AVG 0x00000070 +/* Reserved [3:1] */ +#define FLD_FM1_DFT_START 0x00000001 + +/*****************************************************************************/ +#define FM1_DFT_STATUS 0x9AC +#define FLD_FM1_DFT_DONE 0x80000000 +/* Reserved [30:19] */ +#define FLD_FM_DFT_TH_CMP 0x00040000 +#define FLD_FM1_DFT 0x0003FFFF + +/*****************************************************************************/ +#define FM2_DFT_CTL 0x9B0 +#define FLD_FM2_DFT_THRESHOLD 0xFFFF0000 +/* Reserved [15:8] */ +#define FLD_FM2_DFT_CMP_CTL 0x00000080 +#define FLD_FM2_DFT_AVG 0x00000070 +/* Reserved [3:1] */ +#define FLD_FM2_DFT_START 0x00000001 + +/*****************************************************************************/ +#define FM2_DFT_STATUS 0x9B4 +#define FLD_FM2_DFT_DONE 0x80000000 +/* Reserved [30:19] */ +#define FLD_FM2_DFT_TH_CMP_STAT 0x00040000 +#define FLD_FM2_DFT 0x0003FFFF + +/*****************************************************************************/ +/* Cx231xx redefine */ +#define AAGC_STATUS_REG 0x9B8 +#define AAGC_STATUS 0x9B8 +/* Reserved [31:27] */ +#define FLD_FM2_DAGC_OUT 0x07000000 +/* Reserved [23:19] */ +#define FLD_FM1_DAGC_OUT 0x00070000 +/* Reserved [15:6] */ +#define FLD_AFE_VGA_OUT 0x0000003F + + + +/*****************************************************************************/ +#define MTS_GAIN_STATUS 0x9BC +/* Reserved [31:14] */ +#define FLD_MTS_GAIN 0x00003FFF + +#define RDS_OUT 0x9C0 +#define FLD_RDS_Q 0xFFFF0000 +#define FLD_RDS_I 0x0000FFFF + +/*****************************************************************************/ +#define AUTOCONFIG_REG 0x9C4 +/* Reserved [31:4] */ +#define FLD_AUTOCONFIG_MODE 0x0000000F + +#define FM_AFC 0x9C8 +#define FLD_FM2_AFC 0xFFFF0000 +#define FLD_FM1_AFC 0x0000FFFF + +/*****************************************************************************/ +/* Cx231xx redefine */ +#define NEW_SPARE 0x9CC +#define NEW_SPARE_REG 0x9CC + +/*****************************************************************************/ +#define DBX_ADJ 0x9D0 +/* Reserved [31:28] */ +#define FLD_DBX2_ADJ 0x0FFF0000 +/* Reserved [15:12] */ +#define FLD_DBX1_ADJ 0x00000FFF + +#define VID_FMT_AUTO 0 +#define VID_FMT_NTSC_M 1 +#define VID_FMT_NTSC_J 2 +#define VID_FMT_NTSC_443 3 +#define VID_FMT_PAL_BDGHI 4 +#define VID_FMT_PAL_M 5 +#define VID_FMT_PAL_N 6 +#define VID_FMT_PAL_NC 7 +#define VID_FMT_PAL_60 8 +#define VID_FMT_SECAM 12 +#define VID_FMT_SECAM_60 13 + +#define INPUT_MODE_CVBS_0 0 /* INPUT_MODE_VALUE(0) */ +#define INPUT_MODE_YC_1 1 /* INPUT_MODE_VALUE(1) */ +#define INPUT_MODE_YC2_2 2 /* INPUT_MODE_VALUE(2) */ +#define INPUT_MODE_YUV_3 3 /* INPUT_MODE_VALUE(3) */ + + +#define LUMA_LPF_LOW_BANDPASS 0 /* 0.6Mhz lowpass filter bandwidth */ +#define LUMA_LPF_MEDIUM_BANDPASS 1 /* 1.0Mhz lowpass filter bandwidth */ +#define LUMA_LPF_HIGH_BANDPASS 2 /* 1.5Mhz lowpass filter bandwidth */ + +#define UV_LPF_LOW_BANDPASS 0 /* 0.6Mhz lowpass filter bandwidth */ +#define UV_LPF_MEDIUM_BANDPASS 1 /* 1.0Mhz lowpass filter bandwidth */ +#define UV_LPF_HIGH_BANDPASS 2 /* 1.5Mhz lowpass filter bandwidth */ + +#define TWO_TAP_FILT 0 +#define THREE_TAP_FILT 1 +#define FOUR_TAP_FILT 2 +#define FIVE_TAP_FILT 3 + +#define AUD_CHAN_SRC_PARALLEL 0 +#define AUD_CHAN_SRC_I2S_INPUT 1 +#define AUD_CHAN_SRC_FLATIRON 2 +#define AUD_CHAN_SRC_PARALLEL3 3 + +#define OUT_MODE_601 0 +#define OUT_MODE_656 1 +#define OUT_MODE_VIP11 2 +#define OUT_MODE_VIP20 3 + +#define PHASE_INC_49MHZ 0x0DF22 +#define PHASE_INC_56MHZ 0x0FA5B +#define PHASE_INC_28MHZ 0x010000 + +#endif diff --git a/linux/drivers/media/video/cx231xx/cx231xx-vbi.c b/linux/drivers/media/video/cx231xx/cx231xx-vbi.c new file mode 100644 index 000000000..eeb6e5e92 --- /dev/null +++ b/linux/drivers/media/video/cx231xx/cx231xx-vbi.c @@ -0,0 +1,697 @@ +/* + cx231xx_vbi.c - driver for Conexant Cx23100/101/102 USB video capture devices + + Copyright (C) 2008 + Based on cx88 driver + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "cx231xx.h" +#include "cx231xx-vbi.h" + +static inline void print_err_status(struct cx231xx *dev, + int packet, int status) +{ + char *errmsg = "Unknown"; + + switch (status) { + case -ENOENT: + errmsg = "unlinked synchronuously"; + break; + case -ECONNRESET: + errmsg = "unlinked asynchronuously"; + break; + case -ENOSR: + errmsg = "Buffer error (overrun)"; + break; + case -EPIPE: + errmsg = "Stalled (device not responding)"; + break; + case -EOVERFLOW: + errmsg = "Babble (bad cable?)"; + break; + case -EPROTO: + errmsg = "Bit-stuff error (bad cable?)"; + break; + case -EILSEQ: + errmsg = "CRC/Timeout (could be anything)"; + break; + case -ETIME: + errmsg = "Device does not respond"; + break; + } + if (packet < 0) { + cx231xx_err(DRIVER_NAME "URB status %d [%s].\n", status, errmsg); + } else { + cx231xx_err(DRIVER_NAME "URB packet %d, status %d [%s].\n", + packet, status, errmsg); + } +} + +/* + * Controls the isoc copy of each urb packet + */ +static inline int cx231xx_isoc_vbi_copy(struct cx231xx *dev, struct urb *urb) +{ + struct cx231xx_buffer *buf; + struct cx231xx_dmaqueue *dma_q = urb->context; + int rc = 1; + unsigned char *p_buffer; + u32 bytes_parsed = 0, buffer_size = 0; + u8 sav_eav = 0; + + if (!dev) + return 0; + + if ((dev->state & DEV_DISCONNECTED) || (dev->state & DEV_MISCONFIGURED)) + return 0; + + if (urb->status < 0) { + print_err_status(dev, -1, urb->status); + if (urb->status == -ENOENT) + return 0; + } + + buf = dev->vbi_mode.isoc_ctl.buf; + + /* get buffer pointer and length */ + p_buffer = urb->transfer_buffer; + buffer_size = urb->actual_length; + + if (buffer_size > 0) { + + bytes_parsed = 0; + + if(dma_q->is_partial_line) { + /* Handle the case where we were working on a partial line */ + sav_eav = dma_q->last_sav; + } else { + /* Check for a SAV/EAV overlapping the buffer boundary */ + sav_eav = cx231xx_find_boundary_SAV_EAV(p_buffer, dma_q->partial_buf, &bytes_parsed); + } + + sav_eav &= 0xF0; + /* Get the first line if we have some portion of an SAV/EAV from the last buffer + or a partial line */ + if(sav_eav) { + bytes_parsed += cx231xx_get_vbi_line(dev, dma_q, + sav_eav, /* SAV/EAV */ + p_buffer + bytes_parsed, /* p_buffer */ + buffer_size - bytes_parsed); /* buffer size */ + } + + /* Now parse data that is completely in this buffer */ + dma_q->is_partial_line = 0; + + while(bytes_parsed < buffer_size) + { + u32 bytes_used = 0; + + sav_eav = cx231xx_find_next_SAV_EAV( + p_buffer + bytes_parsed, /* p_buffer */ + buffer_size - bytes_parsed, /* buffer size */ + &bytes_used); /* Receives bytes used to get SAV/EAV */ + + bytes_parsed += bytes_used; + + sav_eav &= 0xF0; + if(sav_eav && (bytes_parsed < buffer_size)) + { + bytes_parsed += cx231xx_get_vbi_line(dev, dma_q, + sav_eav, /* SAV/EAV */ + p_buffer + bytes_parsed, /* p_buffer */ + buffer_size - bytes_parsed); /* buffer size */ + } + } + + /* Save the last four bytes of the buffer so we can check the buffer boundary + condition next time */ + memcpy(dma_q->partial_buf, p_buffer + buffer_size - 4, 4); + bytes_parsed = 0; + } + + return rc; +} + +/* ------------------------------------------------------------------ + Vbi buf operations + ------------------------------------------------------------------*/ + +static int +vbi_buffer_setup(struct videobuf_queue *vq, unsigned int *count, unsigned int *size) +{ + struct cx231xx_fh *fh = vq->priv_data; + struct cx231xx *dev = fh->dev; + u32 height = 0; + + height = ((dev->norm & V4L2_STD_625_50) ? + PAL_VBI_LINES : NTSC_VBI_LINES) ; + + *size = ( dev->width * height * 2); + if (0 == *count) + *count = CX231XX_DEF_VBI_BUF; + + if (*count < CX231XX_MIN_BUF) + *count = CX231XX_MIN_BUF; + + /* call VBI setup if required */ + /* cx231xx_i2c_call_clients(&dev->i2c_bus[1], VIDIOC_S_FREQUENCY, &f); + */ + + return 0; +} + +/* This is called *without* dev->slock held; please keep it that way */ +static void free_buffer(struct videobuf_queue *vq, struct cx231xx_buffer *buf) +{ + struct cx231xx_fh *fh = vq->priv_data; + struct cx231xx *dev = fh->dev; + unsigned long flags = 0; + if (in_interrupt()) + BUG(); + + /* We used to wait for the buffer to finish here, but this didn't work + because, as we were keeping the state as VIDEOBUF_QUEUED, + videobuf_queue_cancel marked it as finished for us. + (Also, it could wedge forever if the hardware was misconfigured.) + + This should be safe; by the time we get here, the buffer isn't + queued anymore. If we ever start marking the buffers as + VIDEOBUF_ACTIVE, it won't be, though. + */ + spin_lock_irqsave(&dev->vbi_mode.slock, flags); + if (dev->vbi_mode.isoc_ctl.buf == buf) + dev->vbi_mode.isoc_ctl.buf = NULL; + spin_unlock_irqrestore(&dev->vbi_mode.slock, flags); + + videobuf_vmalloc_free(&buf->vb); + buf->vb.state = VIDEOBUF_NEEDS_INIT; +} + +static int +vbi_buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb, + enum v4l2_field field) +{ + struct cx231xx_fh *fh = vq->priv_data; + struct cx231xx_buffer *buf = container_of(vb, struct cx231xx_buffer, vb); + struct cx231xx *dev = fh->dev; + int rc = 0, urb_init = 0; + u32 height = 0; + + height = ((dev->norm & V4L2_STD_625_50) ? + PAL_VBI_LINES : NTSC_VBI_LINES) ; + buf->vb.size = ( (dev->width << 1) * height ); + + if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size) + return -EINVAL; + + buf->vb.width = dev->width; + buf->vb.height = height; + buf->vb.field = field; + buf->vb.field = V4L2_FIELD_SEQ_TB; + + if (VIDEOBUF_NEEDS_INIT == buf->vb.state) { + rc = videobuf_iolock(vq, &buf->vb, NULL); + if (rc < 0) + goto fail; + } + + if (!dev->vbi_mode.isoc_ctl.num_bufs) + urb_init = 1; + + if (urb_init) { + rc = cx231xx_init_vbi_isoc(dev, CX231XX_NUM_VBI_PACKETS, + CX231XX_NUM_VBI_BUFS, dev->vbi_mode.alt_max_pkt_size[0], + cx231xx_isoc_vbi_copy); + if (rc < 0) + goto fail; + } + + buf->vb.state = VIDEOBUF_PREPARED; + return 0; + +fail: + free_buffer(vq, buf); + return rc; +} + +static void +vbi_buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) +{ + struct cx231xx_buffer *buf = container_of(vb, struct cx231xx_buffer, vb); + struct cx231xx_fh *fh = vq->priv_data; + struct cx231xx *dev = fh->dev; + struct cx231xx_dmaqueue *vidq = &dev->vbi_mode.vidq; + + buf->vb.state = VIDEOBUF_QUEUED; + list_add_tail(&buf->vb.queue, &vidq->active); + +} + +static void vbi_buffer_release(struct videobuf_queue *vq, + struct videobuf_buffer *vb) +{ + struct cx231xx_buffer *buf = container_of(vb, struct cx231xx_buffer, vb); + /* + struct cx231xx_fh *fh = vq->priv_data; + struct cx231xx *dev = (struct cx231xx *)fh->dev; + + cx231xx_info(DRIVER_NAME "cx231xx: called vbi_buffer_release\n"); + */ + + free_buffer(vq, buf); +} + + +struct videobuf_queue_ops cx231xx_vbi_qops = { + .buf_setup = vbi_buffer_setup, + .buf_prepare = vbi_buffer_prepare, + .buf_queue = vbi_buffer_queue, + .buf_release = vbi_buffer_release, +}; + + + +/* ------------------------------------------------------------------ + URB control + ------------------------------------------------------------------*/ + +/* + * IRQ callback, called by URB callback + */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19) +static void cx231xx_irq_vbi_callback(struct urb *urb, struct pt_regs *regs) +#else +static void cx231xx_irq_vbi_callback(struct urb *urb) +#endif +{ + struct cx231xx_dmaqueue *dma_q = urb->context; + struct cx231xx_video_mode *vmode = container_of(dma_q, struct cx231xx_video_mode, vidq); + struct cx231xx *dev = container_of(vmode, struct cx231xx, vbi_mode); + int rc; + + + switch (urb->status) { + case 0: /* success */ + case -ETIMEDOUT: /* NAK */ + break; + case -ECONNRESET: /* kill */ + case -ENOENT: + case -ESHUTDOWN: + return; + default: /* error */ + cx231xx_err(DRIVER_NAME "urb completition error %d.\n", urb->status); + break; + } + + /* Copy data from URB */ + spin_lock(&dev->vbi_mode.slock); + rc = dev->vbi_mode.isoc_ctl.isoc_copy(dev, urb); + spin_unlock(&dev->vbi_mode.slock); + + /* Reset status */ + urb->status = 0; + + urb->status = usb_submit_urb(urb, GFP_ATOMIC); + if (urb->status) { + cx231xx_err(DRIVER_NAME "urb resubmit failed (error=%i)\n", + urb->status); + } +} + +/* + * Stop and Deallocate URBs + */ +void cx231xx_uninit_vbi_isoc(struct cx231xx *dev) +{ + struct urb *urb; + int i; + + cx231xx_info(DRIVER_NAME "cx231xx: called cx231xx_uninit_vbi_isoc\n"); + + dev->vbi_mode.isoc_ctl.nfields = -1; + for (i = 0; i < dev->vbi_mode.isoc_ctl.num_bufs; i++) { + urb = dev->vbi_mode.isoc_ctl.urb[i]; + if (urb) { + if (!irqs_disabled()) + usb_kill_urb(urb); + else + usb_unlink_urb(urb); + + if (dev->vbi_mode.isoc_ctl.transfer_buffer[i]) { + + kfree(dev->vbi_mode.isoc_ctl.transfer_buffer[i]); + dev->vbi_mode.isoc_ctl.transfer_buffer[i] = NULL; + } + usb_free_urb(urb); + dev->vbi_mode.isoc_ctl.urb[i] = NULL; + } + dev->vbi_mode.isoc_ctl.transfer_buffer[i] = NULL; + } + + kfree(dev->vbi_mode.isoc_ctl.urb); + kfree(dev->vbi_mode.isoc_ctl.transfer_buffer); + + dev->vbi_mode.isoc_ctl.urb = NULL; + dev->vbi_mode.isoc_ctl.transfer_buffer = NULL; + dev->vbi_mode.isoc_ctl.num_bufs = 0; + + cx231xx_capture_start(dev, 0, Vbi); +} +EXPORT_SYMBOL_GPL(cx231xx_uninit_vbi_isoc); + +/* + * Allocate URBs and start IRQ + */ +int cx231xx_init_vbi_isoc(struct cx231xx *dev, int max_packets, + int num_bufs, int max_pkt_size, + int (*isoc_copy) (struct cx231xx *dev, struct urb *urb)) +{ + struct cx231xx_dmaqueue *dma_q = &dev->vbi_mode.vidq; + int i; + int sb_size, pipe; + struct urb *urb; + int rc; + + cx231xx_info(DRIVER_NAME "cx231xx: called cx231xx_prepare_isoc\n"); + + /* De-allocates all pending stuff */ + cx231xx_uninit_vbi_isoc(dev); + + /* clear if any halt */ + usb_clear_halt(dev->udev, usb_rcvbulkpipe(dev->udev, dev->vbi_mode.end_point_addr)); + + + dev->vbi_mode.isoc_ctl.isoc_copy = isoc_copy; + dev->vbi_mode.isoc_ctl.num_bufs = num_bufs; + dma_q->pos = 0; + dma_q->is_partial_line = 0; + dma_q->last_sav = 0; + dma_q->current_field = -1; + dma_q->bytes_left_in_line = dev->width << 1; + dma_q->lines_per_field = ((dev->norm & V4L2_STD_625_50) ? + PAL_VBI_LINES : NTSC_VBI_LINES) ; + dma_q->lines_completed = 0; + for(i = 0; i < 8 ; i++) + dma_q->partial_buf[i] = 0; + + dev->vbi_mode.isoc_ctl.urb = kzalloc(sizeof(void *)*num_bufs, GFP_KERNEL); + if (!dev->vbi_mode.isoc_ctl.urb) { + cx231xx_errdev("cannot alloc memory for usb buffers\n"); + return -ENOMEM; + } + + dev->vbi_mode.isoc_ctl.transfer_buffer = kzalloc(sizeof(void *)*num_bufs, + GFP_KERNEL); + if (!dev->vbi_mode.isoc_ctl.transfer_buffer) { + cx231xx_errdev("cannot allocate memory for usbtransfer\n"); + kfree(dev->vbi_mode.isoc_ctl.urb); + return -ENOMEM; + } + + dev->vbi_mode.isoc_ctl.max_pkt_size = max_pkt_size; + dev->vbi_mode.isoc_ctl.buf = NULL; + + sb_size = max_packets * dev->vbi_mode.isoc_ctl.max_pkt_size; + + /* allocate urbs and transfer buffers */ + for (i = 0; i < dev->vbi_mode.isoc_ctl.num_bufs; i++) { + + urb = usb_alloc_urb(0, GFP_KERNEL); + if (!urb) { + cx231xx_err(DRIVER_NAME ": cannot alloc isoc_ctl.urb %i\n", i); + cx231xx_uninit_vbi_isoc(dev); + return -ENOMEM; + } + dev->vbi_mode.isoc_ctl.urb[i] = urb; + urb->transfer_flags = 0; + + dev->vbi_mode.isoc_ctl.transfer_buffer[i] = kzalloc(sb_size, GFP_KERNEL); + if (!dev->vbi_mode.isoc_ctl.transfer_buffer[i]) { + cx231xx_err(DRIVER_NAME ": unable to allocate %i bytes for transfer" + " buffer %i%s\n", + sb_size, i, + in_interrupt()?" while in int":""); + cx231xx_uninit_vbi_isoc(dev); + return -ENOMEM; + } + + pipe = usb_rcvbulkpipe(dev->udev, dev->vbi_mode.end_point_addr); + usb_fill_bulk_urb(urb, dev->udev, pipe, + dev->vbi_mode.isoc_ctl.transfer_buffer[i], sb_size, + cx231xx_irq_vbi_callback, dma_q); + } + + init_waitqueue_head(&dma_q->wq); + + /* submit urbs and enables IRQ */ + for (i = 0; i < dev->vbi_mode.isoc_ctl.num_bufs; i++) { + rc = usb_submit_urb(dev->vbi_mode.isoc_ctl.urb[i], GFP_ATOMIC); + if (rc) { + cx231xx_err(DRIVER_NAME ": submit of urb %i failed (error=%i)\n", i, + rc); + cx231xx_uninit_vbi_isoc(dev); + return rc; + } + } + + cx231xx_capture_start(dev, 1, Vbi); + + return 0; +} +EXPORT_SYMBOL_GPL(cx231xx_init_vbi_isoc); + + +u32 cx231xx_get_vbi_line(struct cx231xx *dev, struct cx231xx_dmaqueue *dma_q, + u8 sav_eav, u8 *p_buffer, u32 buffer_size) +{ + u32 bytes_copied = 0; + int current_field = -1; + + switch(sav_eav) { + + case SAV_VBI_FIELD1: + current_field = 1; + break; + + case SAV_VBI_FIELD2: + current_field = 2; + break; + default: + break; + } + + if(current_field < 0 ) + return bytes_copied; + + dma_q->last_sav = sav_eav; + + bytes_copied = cx231xx_copy_vbi_line(dev, dma_q, p_buffer, buffer_size, current_field); + + return bytes_copied; +} + +/* + * Announces that a buffer were filled and request the next + */ +static inline void vbi_buffer_filled(struct cx231xx *dev, + struct cx231xx_dmaqueue *dma_q, + struct cx231xx_buffer *buf) +{ + /* Advice that buffer was filled */ + /* cx231xx_info(DRIVER_NAME "[%p/%d] wakeup\n", buf, buf->vb.i); */ + + buf->vb.state = VIDEOBUF_DONE; + buf->vb.field_count++; + do_gettimeofday(&buf->vb.ts); + + dev->vbi_mode.isoc_ctl.buf = NULL; + + list_del(&buf->vb.queue); + wake_up(&buf->vb.done); +} + +u32 cx231xx_copy_vbi_line(struct cx231xx *dev, struct cx231xx_dmaqueue *dma_q, + u8 *p_line, u32 length, int field_number) +{ + u32 bytes_to_copy; + struct cx231xx_buffer *buf; + u32 _line_size = dev->width * 2; + + if( dma_q->current_field != field_number ) { + cx231xx_reset_vbi_buffer(dev, dma_q); + } + + /* get the buffer pointer */ + buf = dev->vbi_mode.isoc_ctl.buf; + + /* Remember the field number for next time */ + dma_q->current_field = field_number; + + bytes_to_copy = dma_q->bytes_left_in_line; + if(bytes_to_copy > length) + bytes_to_copy = length; + + if(dma_q->lines_completed >= dma_q->lines_per_field) { + dma_q->bytes_left_in_line -= bytes_to_copy; + dma_q->is_partial_line = (dma_q->bytes_left_in_line == 0) ? 0 : 1; + return 0; + } + + dma_q->is_partial_line = 1; + + /* If we don't have a buffer, just return the number of bytes we would + have copied if we had a buffer. */ + if(!buf) { + dma_q->bytes_left_in_line -= bytes_to_copy; + dma_q->is_partial_line = (dma_q->bytes_left_in_line == 0) ? 0 : 1; + return bytes_to_copy; + } + + /* copy the data to video buffer */ + cx231xx_do_vbi_copy(dev, dma_q, p_line, bytes_to_copy); + + dma_q->pos += bytes_to_copy; + dma_q->bytes_left_in_line -= bytes_to_copy; + + if(dma_q->bytes_left_in_line == 0) { + + dma_q->bytes_left_in_line = _line_size; + dma_q->lines_completed++; + dma_q->is_partial_line = 0; + + if(cx231xx_is_vbi_buffer_done(dev, dma_q) && buf ) { + + vbi_buffer_filled(dev, dma_q, buf); + + dma_q->pos = 0; + buf = NULL; + dma_q->lines_completed = 0; + } + } + + return bytes_to_copy; +} + +/* + * video-buf generic routine to get the next available buffer + */ +static inline void get_next_vbi_buf(struct cx231xx_dmaqueue *dma_q, + struct cx231xx_buffer **buf) +{ + struct cx231xx_video_mode *vmode = container_of(dma_q, struct cx231xx_video_mode, vidq); + struct cx231xx *dev = container_of(vmode, struct cx231xx, vbi_mode); + char *outp; + + if (list_empty(&dma_q->active)) { + cx231xx_err(DRIVER_NAME ": No active queue to serve\n"); + dev->vbi_mode.isoc_ctl.buf = NULL; + *buf = NULL; + return; + } + + /* Get the next buffer */ + *buf = list_entry(dma_q->active.next, struct cx231xx_buffer, vb.queue); + + /* Cleans up buffer - Usefull for testing for frame/URB loss */ + outp = videobuf_to_vmalloc(&(*buf)->vb); + memset(outp, 0, (*buf)->vb.size); + + dev->vbi_mode.isoc_ctl.buf = *buf; + + return; +} + + +void cx231xx_reset_vbi_buffer(struct cx231xx *dev, struct cx231xx_dmaqueue *dma_q) +{ + struct cx231xx_buffer *buf; + + buf = dev->vbi_mode.isoc_ctl.buf; + + if(buf == NULL) { + + /* first try to get the buffer */ + get_next_vbi_buf(dma_q, &buf); + + dma_q->pos = 0; + dma_q->current_field = -1; + } + + dma_q->bytes_left_in_line = dev->width << 1; + dma_q->lines_completed = 0; +} + +int cx231xx_do_vbi_copy(struct cx231xx *dev, struct cx231xx_dmaqueue *dma_q, + u8 *p_buffer, u32 bytes_to_copy) +{ + u8 *p_out_buffer = NULL; + u32 current_line_bytes_copied = 0; + struct cx231xx_buffer *buf; + u32 _line_size = dev->width << 1; + void *startwrite; + int offset, lencopy; + + buf = dev->vbi_mode.isoc_ctl.buf; + + if (buf == NULL) { + return -1; + } + + p_out_buffer = videobuf_to_vmalloc(&buf->vb); + + if(dma_q->bytes_left_in_line != _line_size ) { + current_line_bytes_copied = _line_size - dma_q->bytes_left_in_line; + } + + offset = ( dma_q->lines_completed * _line_size ) + current_line_bytes_copied; + + /* prepare destination address */ + startwrite = p_out_buffer + offset; + + lencopy = dma_q->bytes_left_in_line > bytes_to_copy ? bytes_to_copy : dma_q->bytes_left_in_line; + + memcpy(startwrite, p_buffer, lencopy); + + return 0; +} + + +u8 cx231xx_is_vbi_buffer_done(struct cx231xx *dev,struct cx231xx_dmaqueue *dma_q) +{ + u32 height = 0; + + height = ((dev->norm & V4L2_STD_625_50) ? + PAL_VBI_LINES : NTSC_VBI_LINES) ; + return (dma_q->lines_completed == height)?1:0; +} diff --git a/linux/drivers/media/video/cx231xx/cx231xx-vbi.h b/linux/drivers/media/video/cx231xx/cx231xx-vbi.h new file mode 100644 index 000000000..5faffaea0 --- /dev/null +++ b/linux/drivers/media/video/cx231xx/cx231xx-vbi.h @@ -0,0 +1,61 @@ +/* + cx231xx_vbi.h - driver for Conexant Cx23100/101/102 USB video capture devices + + Copyright (C) 2008 + Based on cx88 driver + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef _CX231XX_VBI_H +#define _CX231XX_VBI_H + +extern struct videobuf_queue_ops cx231xx_vbi_qops; + + +#define NTSC_VBI_START_LINE 10 /* line 10 - 21 */ +#define NTSC_VBI_END_LINE 21 +#define NTSC_VBI_LINES (NTSC_VBI_END_LINE - NTSC_VBI_START_LINE + 1) + +#define PAL_VBI_START_LINE 6 +#define PAL_VBI_END_LINE 23 +#define PAL_VBI_LINES (PAL_VBI_END_LINE - PAL_VBI_START_LINE + 1) + +#define VBI_STRIDE 1440 +#define VBI_SAMPLES_PER_LINE 1440 + +#define CX231XX_NUM_VBI_PACKETS 4 +#define CX231XX_NUM_VBI_BUFS 5 + +/* stream functions */ +int cx231xx_init_vbi_isoc(struct cx231xx *dev, int max_packets, + int num_bufs, int max_pkt_size, + int (*isoc_copy) (struct cx231xx *dev, struct urb *urb)); + +void cx231xx_uninit_vbi_isoc(struct cx231xx *dev); + +/* vbi data copy functions */ +u32 cx231xx_get_vbi_line(struct cx231xx *dev, struct cx231xx_dmaqueue *dma_q, + u8 sav_eav, u8 *p_buffer, u32 buffer_size); +u32 cx231xx_copy_vbi_line(struct cx231xx *dev, struct cx231xx_dmaqueue *dma_q, + u8 *p_line, u32 length, int field_number); +void cx231xx_reset_vbi_buffer(struct cx231xx *dev, struct cx231xx_dmaqueue *dma_q); + +int cx231xx_do_vbi_copy(struct cx231xx *dev, struct cx231xx_dmaqueue *dma_q, + u8 *p_buffer, u32 bytes_to_copy); + +u8 cx231xx_is_vbi_buffer_done(struct cx231xx *dev,struct cx231xx_dmaqueue *dma_q); + +#endif \ No newline at end of file diff --git a/linux/drivers/media/video/cx231xx/cx231xx-video.c b/linux/drivers/media/video/cx231xx/cx231xx-video.c new file mode 100644 index 000000000..2e8cba88d --- /dev/null +++ b/linux/drivers/media/video/cx231xx/cx231xx-video.c @@ -0,0 +1,2440 @@ +/* + cx231xx-video.c - driver for Conexant Cx23100/101/102 USB video capture devices + + Copyright (C) 2008 + Based on em28xx driver + Based on cx23885 driver + Based on cx88 driver + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "dvb_frontend.h" + +#include "cx231xx.h" +#include "cx231xx-vbi.h" + + +#define DRIVER_AUTHOR "Srinivasa Deevi " +#define DRIVER_DESC "Conexant cx231xx based USB video device driver" + + +#define cx231xx_videodbg(fmt, arg...) do {\ + if (video_debug) \ + printk(KERN_INFO "%s %s :"fmt, \ + dev->name, __func__ , ##arg); } while (0) + +static unsigned int isoc_debug; +module_param(isoc_debug, int, 0644); +MODULE_PARM_DESC(isoc_debug, "enable debug messages [isoc transfers]"); + +#define cx231xx_isocdbg(fmt, arg...) \ +do {\ + if (isoc_debug) { \ + printk(KERN_INFO "%s %s :"fmt, \ + dev->name, __func__ , ##arg); \ + } \ + } while (0) + +MODULE_AUTHOR(DRIVER_AUTHOR); +MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_LICENSE("GPL"); + + + +static unsigned int card[] = {[0 ... (CX231XX_MAXBOARDS - 1)] = UNSET }; +static unsigned int video_nr[] = {[0 ... (CX231XX_MAXBOARDS - 1)] = UNSET }; +static unsigned int vbi_nr[] = {[0 ... (CX231XX_MAXBOARDS - 1)] = UNSET }; +static unsigned int radio_nr[] = {[0 ... (CX231XX_MAXBOARDS - 1)] = UNSET }; + +module_param_array(card, int, NULL, 0444); +module_param_array(video_nr, int, NULL, 0444); +module_param_array(vbi_nr, int, NULL, 0444); +module_param_array(radio_nr, int, NULL, 0444); + +MODULE_PARM_DESC(card, "card type"); +MODULE_PARM_DESC(video_nr, "video device numbers"); +MODULE_PARM_DESC(vbi_nr, "vbi device numbers"); +MODULE_PARM_DESC(radio_nr, "radio device numbers"); + +static unsigned int video_debug; +module_param(video_debug, int, 0644); +MODULE_PARM_DESC(video_debug, "enable debug messages [video]"); + + + +/* supported video standards */ +static struct cx231xx_fmt format[] = { + { + .name = "16bpp YUY2, 4:2:2, packed", + .fourcc = V4L2_PIX_FMT_YUYV, + .depth = 16, + .reg = 0, + }, +}; + + +/* supported controls */ +/* Common to all boards */ + +/* ------------------------------------------------------------------- */ + +static const struct v4l2_queryctrl no_ctl = { + .name = "42", + .flags = V4L2_CTRL_FLAG_DISABLED, +}; + +static struct cx231xx_ctrl cx231xx_ctls[] = { + /* --- video --- */ + { + .v = { + .id = V4L2_CID_BRIGHTNESS, + .name = "Brightness", + .minimum = 0x00, + .maximum = 0xff, + .step = 1, + .default_value = 0x7f, + .type = V4L2_CTRL_TYPE_INTEGER, + }, + .off = 128, + .reg = LUMA_CTRL, + .mask = 0x00ff, + .shift = 0, + }, { + .v = { + .id = V4L2_CID_CONTRAST, + .name = "Contrast", + .minimum = 0, + .maximum = 0xff, + .step = 1, + .default_value = 0x3f, + .type = V4L2_CTRL_TYPE_INTEGER, + }, + .off = 0, + .reg = LUMA_CTRL, + .mask = 0xff00, + .shift = 8, + }, { + .v = { + .id = V4L2_CID_HUE, + .name = "Hue", + .minimum = 0, + .maximum = 0xff, + .step = 1, + .default_value = 0x7f, + .type = V4L2_CTRL_TYPE_INTEGER, + }, + .off = 128, + .reg = CHROMA_CTRL, + .mask = 0xff0000, + .shift = 16, + }, { + /* strictly, this only describes only U saturation. + * V saturation is handled specially through code. + */ + .v = { + .id = V4L2_CID_SATURATION, + .name = "Saturation", + .minimum = 0, + .maximum = 0xff, + .step = 1, + .default_value = 0x7f, + .type = V4L2_CTRL_TYPE_INTEGER, + }, + .off = 0, + .reg = CHROMA_CTRL, + .mask = 0x00ff, + .shift = 0, + }, { + /* --- audio --- */ + .v = { + .id = V4L2_CID_AUDIO_MUTE, + .name = "Mute", + .minimum = 0, + .maximum = 1, + .default_value = 1, + .type = V4L2_CTRL_TYPE_BOOLEAN, + }, + .reg = PATH1_CTL1, + .mask = (0x1f << 24), + .shift = 24, + }, { + .v = { + .id = V4L2_CID_AUDIO_VOLUME, + .name = "Volume", + .minimum = 0, + .maximum = 0x3f, + .step = 1, + .default_value = 0x3f, + .type = V4L2_CTRL_TYPE_INTEGER, + }, + .reg = PATH1_VOL_CTL, + .mask = 0xff, + .shift = 0, + } +}; +static const int CX231XX_CTLS = ARRAY_SIZE(cx231xx_ctls); + +static const u32 cx231xx_user_ctrls[] = { + V4L2_CID_USER_CLASS, + V4L2_CID_BRIGHTNESS, + V4L2_CID_CONTRAST, + V4L2_CID_SATURATION, + V4L2_CID_HUE, + V4L2_CID_AUDIO_VOLUME, +#if 0 /* Keep */ + V4L2_CID_AUDIO_BALANCE, +#endif + V4L2_CID_AUDIO_MUTE, + 0 +}; + +static const u32 *ctrl_classes[] = { + cx231xx_user_ctrls, + NULL +}; + + +/* ------------------------------------------------------------------ + Video buffer and parser functions + ------------------------------------------------------------------*/ + +/* + * Announces that a buffer were filled and request the next + */ +static inline void buffer_filled(struct cx231xx *dev, + struct cx231xx_dmaqueue *dma_q, + struct cx231xx_buffer *buf) +{ + /* Advice that buffer was filled */ + cx231xx_isocdbg("[%p/%d] wakeup\n", buf, buf->vb.i); + buf->vb.state = VIDEOBUF_DONE; + buf->vb.field_count++; + do_gettimeofday(&buf->vb.ts); + + dev->video_mode.isoc_ctl.buf = NULL; + + list_del(&buf->vb.queue); + wake_up(&buf->vb.done); +} + + +static inline void print_err_status(struct cx231xx *dev, + int packet, int status) +{ + char *errmsg = "Unknown"; + + switch (status) { + case -ENOENT: + errmsg = "unlinked synchronuously"; + break; + case -ECONNRESET: + errmsg = "unlinked asynchronuously"; + break; + case -ENOSR: + errmsg = "Buffer error (overrun)"; + break; + case -EPIPE: + errmsg = "Stalled (device not responding)"; + break; + case -EOVERFLOW: + errmsg = "Babble (bad cable?)"; + break; + case -EPROTO: + errmsg = "Bit-stuff error (bad cable?)"; + break; + case -EILSEQ: + errmsg = "CRC/Timeout (could be anything)"; + break; + case -ETIME: + errmsg = "Device does not respond"; + break; + } + if (packet < 0) { + cx231xx_isocdbg("URB status %d [%s].\n", status, errmsg); + } else { + cx231xx_isocdbg("URB packet %d, status %d [%s].\n", + packet, status, errmsg); + } +} + +/* + * video-buf generic routine to get the next available buffer + */ +static inline void get_next_buf(struct cx231xx_dmaqueue *dma_q, + struct cx231xx_buffer **buf) +{ + struct cx231xx_video_mode *vmode = container_of(dma_q, struct cx231xx_video_mode, vidq); + struct cx231xx *dev = container_of(vmode, struct cx231xx, video_mode); + + char *outp; + + + if (list_empty(&dma_q->active)) { + cx231xx_isocdbg("No active queue to serve\n"); + dev->video_mode.isoc_ctl.buf = NULL; + *buf = NULL; + return; + } + + /* Get the next buffer */ + *buf = list_entry(dma_q->active.next, struct cx231xx_buffer, vb.queue); + + /* Cleans up buffer - Usefull for testing for frame/URB loss */ + outp = videobuf_to_vmalloc(&(*buf)->vb); + memset(outp, 0, (*buf)->vb.size); + + dev->video_mode.isoc_ctl.buf = *buf; + + return; +} + +/* + * Controls the isoc copy of each urb packet + */ +static inline int cx231xx_isoc_copy(struct cx231xx *dev, struct urb *urb) +{ + struct cx231xx_buffer *buf; + struct cx231xx_dmaqueue *dma_q = urb->context; + unsigned char *outp = NULL; + int i, rc = 1; + unsigned char *p_buffer; + u32 bytes_parsed = 0, buffer_size = 0; + u8 sav_eav = 0; + + if (!dev) + return 0; + + if ((dev->state & DEV_DISCONNECTED) || (dev->state & DEV_MISCONFIGURED)) + return 0; + + if (urb->status < 0) { + print_err_status(dev, -1, urb->status); + if (urb->status == -ENOENT) + return 0; + } + + buf = dev->video_mode.isoc_ctl.buf; + if (buf != NULL) + outp = videobuf_to_vmalloc(&buf->vb); + + for (i = 0; i < urb->number_of_packets; i++) { + int status = urb->iso_frame_desc[i].status; + + if (status < 0) { + print_err_status(dev, i, status); + if (urb->iso_frame_desc[i].status != -EPROTO) + continue; + } + + if (urb->iso_frame_desc[i].actual_length <= 0) { + /* cx231xx_isocdbg("packet %d is empty",i); - spammy */ + continue; + } + if (urb->iso_frame_desc[i].actual_length > + dev->video_mode.max_pkt_size) { + cx231xx_isocdbg("packet bigger than packet size"); + continue; + } + + /* get buffer pointer and length */ + p_buffer = urb->transfer_buffer + urb->iso_frame_desc[i].offset; + buffer_size = urb->iso_frame_desc[i].actual_length; + bytes_parsed = 0; + + if(dma_q->is_partial_line) + { + /* Handle the case where we were working on a partial line */ + sav_eav = dma_q->last_sav; + } else { + /* Check for a SAV/EAV overlapping the buffer boundary */ + sav_eav = cx231xx_find_boundary_SAV_EAV(p_buffer, dma_q->partial_buf, &bytes_parsed); + } + + sav_eav &= 0xF0; + /* Get the first line if we have some portion of an SAV/EAV from the last buffer + or a partial line */ + if(sav_eav) { + bytes_parsed += cx231xx_get_video_line(dev, dma_q, + sav_eav, /* SAV/EAV */ + p_buffer + bytes_parsed, /* p_buffer */ + buffer_size - bytes_parsed); /* buffer size */ + } + + /* Now parse data that is completely in this buffer */ + /* dma_q->is_partial_line = 0; */ + + while(bytes_parsed < buffer_size) + { + u32 bytes_used = 0; + + sav_eav = cx231xx_find_next_SAV_EAV( + p_buffer + bytes_parsed, /* p_buffer */ + buffer_size - bytes_parsed, /* buffer size */ + &bytes_used); /* Receives bytes used to get SAV/EAV */ + + bytes_parsed += bytes_used; + + sav_eav &= 0xF0; + if(sav_eav && (bytes_parsed < buffer_size)) + { + bytes_parsed += cx231xx_get_video_line(dev, dma_q, + sav_eav, /* SAV/EAV */ + p_buffer + bytes_parsed, /* p_buffer */ + buffer_size - bytes_parsed); /* buffer size */ + } + } + + /* Save the last four bytes of the buffer so we can check the buffer boundary + condition next time */ + memcpy(dma_q->partial_buf, p_buffer + buffer_size - 4, 4); + bytes_parsed = 0; + + } + return rc; +} + +u8 cx231xx_find_boundary_SAV_EAV(u8 *p_buffer, u8 *partial_buf, u32 *p_bytes_used) +{ + u32 bytes_used; + u8 boundary_bytes[8]; + u8 sav_eav = 0; + + *p_bytes_used = 0; + + /* Create an array of the last 4 bytes of the last buffer and the first + 4 bytes of the current buffer. */ + + memcpy(boundary_bytes, partial_buf, 4); + memcpy(boundary_bytes + 4, p_buffer, 4); + + /* Check for the SAV/EAV in the boundary buffer */ + sav_eav = cx231xx_find_next_SAV_EAV((u8*)&boundary_bytes, 8, &bytes_used); + + if(sav_eav) { + /* found a boundary SAV/EAV. Updates the bytes used to reflect + only those used in the new buffer */ + *p_bytes_used = bytes_used - 4; + } + + return sav_eav; +} + +u8 cx231xx_find_next_SAV_EAV(u8 *p_buffer, u32 buffer_size, u32 *p_bytes_used) +{ + u32 i; + u8 sav_eav = 0; + + /* Don't search if the buffer size is less than 4. It causes a page fault since + buffer_size - 4 evaluates to a large number in that case. */ + if(buffer_size < 4) { + *p_bytes_used = buffer_size; + return 0; + } + + for(i = 0;i < (buffer_size - 3); i++) { + + if((p_buffer[i] == 0xFF) && + (p_buffer[i+1] == 0x00) && + (p_buffer[i+2] == 0x00)) { + + *p_bytes_used = i+4; + sav_eav = p_buffer[i+3]; + return sav_eav; + } + } + + *p_bytes_used = buffer_size; + return 0; +} + + + + +u32 cx231xx_get_video_line(struct cx231xx *dev, struct cx231xx_dmaqueue *dma_q, + u8 sav_eav, u8 *p_buffer, u32 buffer_size) +{ + u32 bytes_copied = 0; + int current_field = -1; + + + switch(sav_eav) { + case SAV_ACTIVE_VIDEO_FIELD1: + /* looking for skipped line which occurred in PAL 720x480 mode. In this case, + there will be no active data contained between the SAV and EAV */ + if ( (buffer_size > 3) && + (p_buffer[0] == 0xFF) && (p_buffer[1] == 0x00) && (p_buffer[2] == 0x00) && + ( (p_buffer[3] == EAV_ACTIVE_VIDEO_FIELD1) || (p_buffer[3] == EAV_ACTIVE_VIDEO_FIELD2) || + (p_buffer[3] == EAV_VBLANK_FIELD1) || (p_buffer[3] == EAV_VBLANK_FIELD2) + ) + ) + { + return bytes_copied; + } + current_field = 1; + break; + + case SAV_ACTIVE_VIDEO_FIELD2: + /* looking for skipped line which occurred in PAL 720x480 mode. In this case, + there will be no active data contained between the SAV and EAV */ + if ( (buffer_size > 3) && + (p_buffer[0] == 0xFF) && (p_buffer[1] == 0x00) && (p_buffer[2] == 0x00) && + ( (p_buffer[3] == EAV_ACTIVE_VIDEO_FIELD1) || (p_buffer[3] == EAV_ACTIVE_VIDEO_FIELD2) || + (p_buffer[3] == EAV_VBLANK_FIELD1) || (p_buffer[3] == EAV_VBLANK_FIELD2) + ) + ) + { + return bytes_copied; + } + current_field = 2; + break; + } + + dma_q->last_sav = sav_eav; + + bytes_copied = cx231xx_copy_video_line(dev, dma_q, p_buffer, buffer_size, current_field); + + return bytes_copied; +} + +u32 cx231xx_copy_video_line(struct cx231xx *dev, struct cx231xx_dmaqueue *dma_q, + u8 *p_line, u32 length, int field_number) +{ + u32 bytes_to_copy; + struct cx231xx_buffer *buf; + u32 _line_size = dev->width * 2; + + if( dma_q->current_field != field_number ) { + cx231xx_reset_video_buffer(dev, dma_q); + } + + /* get the buffer pointer */ + buf = dev->video_mode.isoc_ctl.buf; + + /* Remember the field number for next time */ + dma_q->current_field = field_number; + + bytes_to_copy = dma_q->bytes_left_in_line; + if(bytes_to_copy > length) + bytes_to_copy = length; + + + if(dma_q->lines_completed >= dma_q->lines_per_field) { + dma_q->bytes_left_in_line -= bytes_to_copy; + dma_q->is_partial_line = (dma_q->bytes_left_in_line == 0) ? 0 : 1; + return 0; + } + + dma_q->is_partial_line = 1; + + /* If we don't have a buffer, just return the number of bytes we would + have copied if we had a buffer. */ + if(!buf) + { + dma_q->bytes_left_in_line -= bytes_to_copy; + dma_q->is_partial_line = (dma_q->bytes_left_in_line == 0) ? 0 : 1; + return bytes_to_copy; + } + + /* copy the data to video buffer */ + cx231xx_do_copy(dev, dma_q, p_line, bytes_to_copy); + + dma_q->pos += bytes_to_copy; + dma_q->bytes_left_in_line -= bytes_to_copy; + + if(dma_q->bytes_left_in_line == 0) { + + dma_q->bytes_left_in_line = _line_size; + dma_q->lines_completed++; + dma_q->is_partial_line = 0; + + if(cx231xx_is_buffer_done(dev, dma_q) && buf) { + + buffer_filled(dev, dma_q, buf); + + dma_q->pos = 0; + buf = NULL; + dma_q->lines_completed = 0; + } + } + + return bytes_to_copy; +} + +void cx231xx_reset_video_buffer(struct cx231xx *dev, struct cx231xx_dmaqueue *dma_q) +{ + struct cx231xx_buffer *buf; + + /* handle the switch from field 1 to field 2 */ + if(dma_q->current_field == 1) { + if(dma_q->lines_completed >= dma_q->lines_per_field ) { + dma_q->field1_done = 1; + } else { + dma_q->field1_done = 0; + } + } + + buf = dev->video_mode.isoc_ctl.buf; + + if(buf == NULL) { + u8* outp = NULL; + /* first try to get the buffer */ + get_next_buf(dma_q, &buf); + + if(buf) + outp = videobuf_to_vmalloc(&buf->vb); + + dma_q->pos = 0; + dma_q->field1_done = 0; + dma_q->current_field = -1; + } + + /* reset the counters */ + dma_q->bytes_left_in_line = dev->width << 1; + dma_q->lines_completed = 0; +} + +int cx231xx_do_copy(struct cx231xx *dev, struct cx231xx_dmaqueue *dma_q, + u8 *p_buffer, u32 bytes_to_copy) +{ + u8 *p_out_buffer = NULL; + u32 current_line_bytes_copied = 0; + struct cx231xx_buffer *buf; + u32 _line_size = dev->width << 1; + void *startwrite; + int offset, lencopy; + + buf = dev->video_mode.isoc_ctl.buf; + + if (buf == NULL) + return -1; + + p_out_buffer = videobuf_to_vmalloc(&buf->vb); + + current_line_bytes_copied = _line_size - dma_q->bytes_left_in_line; + + /* Offset field 2 one line from the top of the buffer */ + offset = (dma_q->current_field == 1)? 0: _line_size; + + /* Offset for field 2 */ + startwrite = p_out_buffer + offset; + + /* lines already completed in the current field */ + startwrite += (dma_q->lines_completed * _line_size * 2); + + /* bytes already completed in the current line */ + startwrite += current_line_bytes_copied; + + lencopy = dma_q->bytes_left_in_line > bytes_to_copy ? bytes_to_copy : dma_q->bytes_left_in_line; + + if( (u8*)(startwrite +lencopy) > (u8*)(p_out_buffer+ buf->vb.size) ) { + return 0; + } + + /* The below copies the UYVY data straight into video buffer */ + cx231xx_swab( (u16*)p_buffer, (u16*)startwrite, (u16)lencopy); + + return 0; +} + +void cx231xx_swab(u16 *from, u16 *to, u16 len) +{ + u16 i; + + if( len <= 0) + return; + + for(i = 0; i < len/2; i++) { + to[i] = (from[i] << 8) | (from[i] >> 8); + } +} + +u8 cx231xx_is_buffer_done(struct cx231xx *dev,struct cx231xx_dmaqueue *dma_q) +{ + u8 buffer_complete = 0; + + /* Dual field stream */ + buffer_complete = + ((dma_q->current_field == 2) && + (dma_q->lines_completed >= dma_q->lines_per_field) && + dma_q->field1_done); + + return buffer_complete; +} + + +/* ------------------------------------------------------------------ + Videobuf operations + ------------------------------------------------------------------*/ + +static int +buffer_setup(struct videobuf_queue *vq, unsigned int *count, unsigned int *size) +{ + struct cx231xx_fh *fh = vq->priv_data; + struct cx231xx *dev = fh->dev; + struct v4l2_frequency f; + + *size = ( fh->dev->width * fh->dev->height * dev->format->depth + 7) >> 3; + if (0 == *count) + *count = CX231XX_DEF_BUF; + + if (*count < CX231XX_MIN_BUF) + *count = CX231XX_MIN_BUF; + + /* Ask tuner to go to analog mode */ + memset(&f, 0, sizeof(f)); + f.frequency = dev->ctl_freq; + f.type = fh->radio ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV; + + cx231xx_i2c_call_clients(&dev->i2c_bus[1], VIDIOC_S_FREQUENCY, &f); + + return 0; +} + +/* This is called *without* dev->slock held; please keep it that way */ +static void free_buffer(struct videobuf_queue *vq, struct cx231xx_buffer *buf) +{ + struct cx231xx_fh *fh = vq->priv_data; + struct cx231xx *dev = fh->dev; + unsigned long flags = 0; + if (in_interrupt()) + BUG(); + + /* We used to wait for the buffer to finish here, but this didn't work + because, as we were keeping the state as VIDEOBUF_QUEUED, + videobuf_queue_cancel marked it as finished for us. + (Also, it could wedge forever if the hardware was misconfigured.) + + This should be safe; by the time we get here, the buffer isn't + queued anymore. If we ever start marking the buffers as + VIDEOBUF_ACTIVE, it won't be, though. + */ + spin_lock_irqsave(&dev->video_mode.slock, flags); + if (dev->video_mode.isoc_ctl.buf == buf) + dev->video_mode.isoc_ctl.buf = NULL; + spin_unlock_irqrestore(&dev->video_mode.slock, flags); + + videobuf_vmalloc_free(&buf->vb); + buf->vb.state = VIDEOBUF_NEEDS_INIT; +} + +static int +buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb, + enum v4l2_field field) +{ + struct cx231xx_fh *fh = vq->priv_data; + struct cx231xx_buffer *buf = container_of(vb, struct cx231xx_buffer, vb); + struct cx231xx *dev = fh->dev; + int rc = 0, urb_init = 0; + + /* The only currently supported format is 16 bits/pixel */ + buf->vb.size = (fh->dev->width * fh->dev->height * dev->format->depth + 7) >> 3; + + if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size) + return -EINVAL; + + buf->vb.width = dev->width; + buf->vb.height = dev->height; + buf->vb.field = field; + + if (VIDEOBUF_NEEDS_INIT == buf->vb.state) { + rc = videobuf_iolock(vq, &buf->vb, NULL); + if (rc < 0) + goto fail; + } + + if (!dev->video_mode.isoc_ctl.num_bufs) + urb_init = 1; + + if (urb_init) { + rc = cx231xx_init_isoc(dev, CX231XX_NUM_PACKETS, + CX231XX_NUM_BUFS, dev->video_mode.max_pkt_size, + cx231xx_isoc_copy); + if (rc < 0) + goto fail; + } + + buf->vb.state = VIDEOBUF_PREPARED; + return 0; + +fail: + free_buffer(vq, buf); + return rc; +} + +static void +buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) +{ + struct cx231xx_buffer *buf = container_of(vb, struct cx231xx_buffer, vb); + struct cx231xx_fh *fh = vq->priv_data; + struct cx231xx *dev = fh->dev; + struct cx231xx_dmaqueue *vidq = &dev->video_mode.vidq; + + buf->vb.state = VIDEOBUF_QUEUED; + list_add_tail(&buf->vb.queue, &vidq->active); + +} + +static void buffer_release(struct videobuf_queue *vq, + struct videobuf_buffer *vb) +{ + struct cx231xx_buffer *buf = container_of(vb, struct cx231xx_buffer, vb); + struct cx231xx_fh *fh = vq->priv_data; + struct cx231xx *dev = (struct cx231xx *)fh->dev; + + cx231xx_isocdbg("cx231xx: called buffer_release\n"); + + free_buffer(vq, buf); +} + +static struct videobuf_queue_ops cx231xx_video_qops = { + .buf_setup = buffer_setup, + .buf_prepare = buffer_prepare, + .buf_queue = buffer_queue, + .buf_release = buffer_release, +}; + +/********************* v4l2 interface **************************************/ + + +void video_mux(struct cx231xx *dev, int index) +{ + + struct v4l2_routing route; + + route.input = INPUT(index)->vmux; + route.output = 0; + dev->video_input = index; + dev->ctl_ainput = INPUT(index)->amux; + + cx231xx_set_video_input_mux(dev,index); + + cx231xx_i2c_call_clients(&dev->i2c_bus[0], VIDIOC_INT_S_VIDEO_ROUTING, &route); + + cx231xx_set_audio_input(dev, dev->ctl_ainput ); + + cx231xx_info("video_mux : %d\n", index); + + /* do mode control overrides if required */ + cx231xx_do_mode_ctrl_overrides(dev); +} + +/* Usage lock check functions */ +static int res_get(struct cx231xx_fh *fh) +{ + struct cx231xx *dev = fh->dev; + int rc = 0; + + /* This instance already has stream_on */ + if (fh->stream_on) + return rc; + + if(fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { + if (dev->stream_on) + return -EBUSY; + dev->stream_on = 1; + } else if(fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) { + if (dev->vbi_stream_on) + return -EBUSY; + dev->vbi_stream_on = 1; + } else + return -EINVAL; + + fh->stream_on = 1; + + return rc; +} + +static int res_check(struct cx231xx_fh *fh) +{ + return (fh->stream_on); +} + +static void res_free(struct cx231xx_fh *fh) +{ + struct cx231xx *dev = fh->dev; + + fh->stream_on = 0; + + if(fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) + dev->stream_on = 0; + if(fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) + dev->vbi_stream_on = 0; +} + +static int check_dev(struct cx231xx *dev) +{ + if (dev->state & DEV_DISCONNECTED) { + cx231xx_errdev("v4l2 ioctl: device not present\n"); + return -ENODEV; + } + + if (dev->state & DEV_MISCONFIGURED) { + cx231xx_errdev("v4l2 ioctl: device is misconfigured; " + "close and open it again\n"); + return -EIO; + } + return 0; +} + +void get_scale(struct cx231xx *dev, + unsigned int width, unsigned int height, + unsigned int *hscale, unsigned int *vscale) +{ + unsigned int maxw = norm_maxw(dev); + unsigned int maxh = norm_maxh(dev); + + *hscale = (((unsigned long)maxw) << 12) / width - 4096L; + if (*hscale >= 0x4000) + *hscale = 0x3fff; + + *vscale = (((unsigned long)maxh) << 12) / height - 4096L; + if (*vscale >= 0x4000) + *vscale = 0x3fff; + + dev->hscale = *hscale; + dev->vscale = *vscale; + +} + +/* ------------------------------------------------------------------ + IOCTL vidioc handling + ------------------------------------------------------------------*/ + +static int vidioc_g_fmt_vid_cap(struct file *file, void *priv, + struct v4l2_format *f) +{ + struct cx231xx_fh *fh = priv; + struct cx231xx *dev = fh->dev; + + mutex_lock(&dev->lock); + + f->fmt.pix.width = dev->width; + f->fmt.pix.height = dev->height; + f->fmt.pix.pixelformat = dev->format->fourcc;; + f->fmt.pix.bytesperline = (dev->width * dev->format->depth + 7) >> 3;; + f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * dev->height; + f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; + + f->fmt.pix.field = V4L2_FIELD_INTERLACED; + + mutex_unlock(&dev->lock); + return 0; +} + +static struct cx231xx_fmt *format_by_fourcc(unsigned int fourcc) +{ + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(format); i++) + if (format[i].fourcc == fourcc) + return &format[i]; + + return NULL; +} + +static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, + struct v4l2_format *f) +{ + struct cx231xx_fh *fh = priv; + struct cx231xx *dev = fh->dev; + int width = f->fmt.pix.width; + int height = f->fmt.pix.height; + unsigned int maxw = norm_maxw(dev); + unsigned int maxh = norm_maxh(dev); + unsigned int hscale, vscale; + struct cx231xx_fmt *fmt; + + fmt = format_by_fourcc(f->fmt.pix.pixelformat); + if (!fmt) { + cx231xx_videodbg("Fourcc format (%08x) invalid.\n", + f->fmt.pix.pixelformat); + return -EINVAL; + } + + /* width must even because of the YUYV format + height must be even because of interlacing */ + height &= 0xfffe; + width &= 0xfffe; + + if (unlikely(height < 32)) + height = 32; + if (unlikely(height > maxh)) + height = maxh; + if (unlikely(width < 48)) + width = 48; + if (unlikely(width > maxw)) + width = maxw; + + get_scale(dev, width, height, &hscale, &vscale); + + width = (((unsigned long)maxw) << 12) / (hscale + 4096L); + height = (((unsigned long)maxh) << 12) / (vscale + 4096L); + + f->fmt.pix.width = width; + f->fmt.pix.height = height; + f->fmt.pix.pixelformat = fmt->fourcc; + f->fmt.pix.bytesperline = (dev->width * fmt->depth + 7) >> 3; + f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * height; + f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; + f->fmt.pix.field = V4L2_FIELD_INTERLACED; + + return 0; +} + +static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, + struct v4l2_format *f) +{ + struct cx231xx_fh *fh = priv; + struct cx231xx *dev = fh->dev; + int rc; + struct cx231xx_fmt *fmt; + + rc = check_dev(dev); + if (rc < 0) + return rc; + + + mutex_lock(&dev->lock); + + vidioc_try_fmt_vid_cap(file, priv, f); + + fmt = format_by_fourcc(f->fmt.pix.pixelformat); + if (!fmt) { + rc = -EINVAL; + goto out; + } + + if (videobuf_queue_is_busy(&fh->vb_vidq)) { + cx231xx_errdev("%s queue busy\n", __func__); + rc = -EBUSY; + goto out; + } + + if (dev->stream_on && !fh->stream_on) { + cx231xx_errdev("%s device in use by another fh\n", __func__); + rc = -EBUSY; + goto out; + } + + /* set new image size */ + dev->width = f->fmt.pix.width; + dev->height = f->fmt.pix.height; + dev->format = fmt; + get_scale(dev, dev->width, dev->height, &dev->hscale, &dev->vscale); + + cx231xx_i2c_call_clients(&dev->i2c_bus[0], VIDIOC_S_FMT, f); + + /* Set the correct alternate setting for this resolution */ + cx231xx_resolution_set(dev); + +out: + mutex_unlock(&dev->lock); + return rc; +} + +static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *id) +{ + struct cx231xx_fh *fh = priv; + struct cx231xx *dev = fh->dev; + + *id = dev->norm; + return 0; +} + +static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id * norm) +{ + struct cx231xx_fh *fh = priv; + struct cx231xx *dev = fh->dev; + struct v4l2_format f; + int rc; + + rc = check_dev(dev); + if (rc < 0) + return rc; + + cx231xx_info("vidioc_s_std : 0x%x\n", (unsigned int)*norm); + + mutex_lock(&dev->lock); + dev->norm = *norm; + + + /* Adjusts width/height, if needed */ + f.fmt.pix.width = dev->width; + f.fmt.pix.height = dev->height; + vidioc_try_fmt_vid_cap(file, priv, &f); + + /* set new image size */ + dev->width = f.fmt.pix.width; + dev->height = f.fmt.pix.height; + get_scale(dev, dev->width, dev->height, &dev->hscale, &dev->vscale); + + cx231xx_i2c_call_clients(&dev->i2c_bus[0], VIDIOC_S_STD, &dev->norm); + + mutex_unlock(&dev->lock); + + cx231xx_resolution_set(dev); + + /* do mode control overrides */ + cx231xx_do_mode_ctrl_overrides(dev); + + return 0; +} + +static const char *iname[] = { + [CX231XX_VMUX_COMPOSITE1] = "Composite1", + [CX231XX_VMUX_SVIDEO] = "S-Video", + [CX231XX_VMUX_TELEVISION] = "Television", + [CX231XX_VMUX_CABLE] = "Cable TV", + [CX231XX_VMUX_DVB] = "DVB", + [CX231XX_VMUX_DEBUG] = "for debug only", +}; + +static int vidioc_enum_input(struct file *file, void *priv, + struct v4l2_input *i) +{ + struct cx231xx_fh *fh = priv; + struct cx231xx *dev = fh->dev; + unsigned int n; + + n = i->index; + if (n >= MAX_CX231XX_INPUT) + return -EINVAL; + if (0 == INPUT(n)->type) + return -EINVAL; + + i->index = n; + i->type = V4L2_INPUT_TYPE_CAMERA; + + strcpy(i->name, iname[INPUT(n)->type]); + + if ((CX231XX_VMUX_TELEVISION == INPUT(n)->type) || + (CX231XX_VMUX_CABLE == INPUT(n)->type)) + i->type = V4L2_INPUT_TYPE_TUNER; + + i->std = dev->vdev->tvnorms; + + return 0; +} + +static int vidioc_g_input(struct file *file, void *priv, unsigned int *i) +{ + struct cx231xx_fh *fh = priv; + struct cx231xx *dev = fh->dev; + + *i = dev->video_input; + + return 0; +} + +static int vidioc_s_input(struct file *file, void *priv, unsigned int i) +{ + struct cx231xx_fh *fh = priv; + struct cx231xx *dev = fh->dev; + int rc; + + rc = check_dev(dev); + if (rc < 0) + return rc; + + if (i >= MAX_CX231XX_INPUT) + return -EINVAL; + if (0 == INPUT(i)->type) + return -EINVAL; + + mutex_lock(&dev->lock); + + video_mux(dev, i); + + mutex_unlock(&dev->lock); + return 0; +} + +static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a) +{ + struct cx231xx_fh *fh = priv; + struct cx231xx *dev = fh->dev; + + switch (a->index) { + case CX231XX_AMUX_VIDEO: + strcpy(a->name, "Television"); + break; + case CX231XX_AMUX_LINE_IN: + strcpy(a->name, "Line In"); + break; + default: + return -EINVAL; + } + + a->index = dev->ctl_ainput; + a->capability = V4L2_AUDCAP_STEREO; + + return 0; +} + +static int vidioc_s_audio(struct file *file, void *priv, struct v4l2_audio *a) +{ + struct cx231xx_fh *fh = priv; + struct cx231xx *dev = fh->dev; + int status = 0; + + + /* Doesn't allow manual routing */ + if (a->index != dev->ctl_ainput) + return -EINVAL; + + dev->ctl_ainput = INPUT(a->index)->amux; + status = cx231xx_set_audio_input(dev, dev->ctl_ainput); + + return status; +} + +static int vidioc_queryctrl(struct file *file, void *priv, + struct v4l2_queryctrl *qc) +{ + struct cx231xx_fh *fh = priv; + struct cx231xx *dev = fh->dev; + int id = qc->id; + int i; + int rc; + + rc = check_dev(dev); + if (rc < 0) + return rc; + + qc->id = v4l2_ctrl_next(ctrl_classes, qc->id); + if (unlikely(qc->id == 0)) + return -EINVAL; + + memset(qc, 0, sizeof(*qc)); + + qc->id = id; + + if (qc->id < V4L2_CID_BASE || + qc->id >= V4L2_CID_LASTP1) + return -EINVAL; + + for (i = 0; i < CX231XX_CTLS; i++) + if (cx231xx_ctls[i].v.id == qc->id) + break; + + if (i == CX231XX_CTLS) { + *qc = no_ctl; + return 0; + } + *qc = cx231xx_ctls[i].v; + + mutex_lock(&dev->lock); + cx231xx_i2c_call_clients(&dev->i2c_bus[0], VIDIOC_QUERYCTRL, qc); + mutex_unlock(&dev->lock); + + if (qc->type) + return 0; + else + return -EINVAL; +} + +static int vidioc_g_ctrl(struct file *file, void *priv, + struct v4l2_control *ctrl) +{ + struct cx231xx_fh *fh = priv; + struct cx231xx *dev = fh->dev; + int rc; + + rc = check_dev(dev); + if (rc < 0) + return rc; + + mutex_lock(&dev->lock); + + cx231xx_i2c_call_clients(&dev->i2c_bus[0], VIDIOC_G_CTRL, ctrl); + + mutex_unlock(&dev->lock); + return rc; +} + +static int vidioc_s_ctrl(struct file *file, void *priv, + struct v4l2_control *ctrl) +{ + struct cx231xx_fh *fh = priv; + struct cx231xx *dev = fh->dev; + int rc; + + rc = check_dev(dev); + if (rc < 0) + return rc; + + mutex_lock(&dev->lock); + + cx231xx_i2c_call_clients(&dev->i2c_bus[0], VIDIOC_S_CTRL, ctrl); + + mutex_unlock(&dev->lock); + return rc; +} + +static int vidioc_g_tuner(struct file *file, void *priv, + struct v4l2_tuner *t) +{ + struct cx231xx_fh *fh = priv; + struct cx231xx *dev = fh->dev; + int rc; + + rc = check_dev(dev); + if (rc < 0) + return rc; + + if (0 != t->index) + return -EINVAL; + + strcpy(t->name, "Tuner"); + + t->type = V4L2_TUNER_ANALOG_TV; + t->capability = V4L2_TUNER_CAP_NORM; + t->rangehigh = 0xffffffffUL; + t->signal = 0xffff ; /* LOCKED */ + + return 0; +} + +static int vidioc_s_tuner(struct file *file, void *priv, + struct v4l2_tuner *t) +{ + struct cx231xx_fh *fh = priv; + struct cx231xx *dev = fh->dev; + int rc; + + rc = check_dev(dev); + if (rc < 0) + return rc; + + if (0 != t->index) + return -EINVAL; +#if 0 /* Keep */ + mutex_lock(&dev->lock); + + cx231xx_i2c_call_clients(&dev->i2c_bus[1], VIDIOC_S_TUNER, t); + + mutex_unlock(&dev->lock); +#endif + return 0; +} + +static int vidioc_g_frequency(struct file *file, void *priv, + struct v4l2_frequency *f) +{ + struct cx231xx_fh *fh = priv; + struct cx231xx *dev = fh->dev; + + mutex_lock(&dev->lock); + f->type = fh->radio ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV; + f->frequency = dev->ctl_freq; + + cx231xx_i2c_call_clients(&dev->i2c_bus[1], VIDIOC_G_FREQUENCY, f); + + mutex_unlock(&dev->lock); + + return 0; +} + +static int vidioc_s_frequency(struct file *file, void *priv, + struct v4l2_frequency *f) +{ + struct cx231xx_fh *fh = priv; + struct cx231xx *dev = fh->dev; + int rc; + + rc = check_dev(dev); + if (rc < 0) + return rc; + + if (0 != f->tuner) + return -EINVAL; + + if (unlikely(0 == fh->radio && f->type != V4L2_TUNER_ANALOG_TV)) + return -EINVAL; + if (unlikely(1 == fh->radio && f->type != V4L2_TUNER_RADIO)) + return -EINVAL; + + /* set pre channel change settings in DIF first */ + rc = cx231xx_tuner_pre_channel_change(dev); + + mutex_lock(&dev->lock); + + dev->ctl_freq = f->frequency; + + if(dev->tuner_type == TUNER_XC5000) { + if( dev->cx231xx_set_analog_freq != NULL ) { + dev->cx231xx_set_analog_freq(dev, f->frequency ); + } + } else { + cx231xx_i2c_call_clients(&dev->i2c_bus[1], VIDIOC_S_FREQUENCY, f); + } + + mutex_unlock(&dev->lock); + + /* set post channel change settings in DIF first */ + rc = cx231xx_tuner_post_channel_change(dev); + + cx231xx_info("Set New FREQUENCY to %d\n",f->frequency); + + return rc; +} + +#ifdef CONFIG_VIDEO_ADV_DEBUG + + +/* + -R, --list-registers=type=,chip=[,min=,max=] + dump registers from to [VIDIOC_DBG_G_REGISTER] + -r, --set-register=type=,chip=,reg=,val= + set the register [VIDIOC_DBG_S_REGISTER] + + if type == host, then is the hosts chip ID (default 0) + if type == i2cdrv (default), then is the I2C driver name or ID + if type == i2caddr, then is the 7-bit I2C address +*/ + + +static int vidioc_g_register(struct file *file, void *priv, + struct v4l2_dbg_register *reg) +{ + struct cx231xx_fh *fh = priv; + struct cx231xx *dev = fh->dev; + int ret = 0; + u8 value[4] ={0,0,0,0}; + u32 data = 0; + + switch (reg->match.type) { + case V4L2_CHIP_MATCH_HOST: + switch(reg->match.addr) { + case 0: /* Cx231xx - internal registers */ + ret = cx231xx_read_ctrl_reg(dev,VRT_GET_REGISTER, (u16) reg->reg, value, 4); + reg->val = value[0] | value[1] << 8 | value[2] << 16 | value[3] << 24; + break; + case 1: /* Colibri - read byte */ + ret = cx231xx_read_i2c_data(dev, Colibri_DEVICE_ADDRESS, (u16) reg->reg, 2, &data, 1); + reg->val = le32_to_cpu(data & 0xff); + break; + case 14: /* Colibri - read dword */ + ret = cx231xx_read_i2c_data(dev, Colibri_DEVICE_ADDRESS, (u16) reg->reg, 2, &data, 4); + reg->val = le32_to_cpu(data); + break; + case 2: /* Hammerhead - read byte */ + ret = cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, (u16) reg->reg, 2, &data, 1); + reg->val = le32_to_cpu(data & 0xff); + break; + case 24: /* Hammerhead - read dword */ + ret = cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, (u16) reg->reg, 2, &data, 4); + reg->val = le32_to_cpu(data); + break; + case 3: /* flatiron - read byte */ + ret = cx231xx_read_i2c_data(dev, Flatrion_DEVICE_ADDRESS, (u16) reg->reg, 1, &data, 1); + reg->val = le32_to_cpu(data & 0xff); + break; + case 34: /* flatiron - read dword */ + ret = cx231xx_read_i2c_data(dev, Flatrion_DEVICE_ADDRESS, (u16) reg->reg, 1, &data, 4); + reg->val = le32_to_cpu(data); + break; + } + return ret < 0?ret:0; + + case V4L2_CHIP_MATCH_I2C_DRIVER: + cx231xx_i2c_call_clients(&dev->i2c_bus[0], VIDIOC_DBG_G_REGISTER, reg); + return 0; + case V4L2_CHIP_MATCH_I2C_ADDR: + /* Not supported yet */ + return -EINVAL; + default: + if (!v4l2_chip_match_host(®->match)) + return -EINVAL; + } + + + mutex_lock(&dev->lock); + + cx231xx_i2c_call_clients(&dev->i2c_bus[0], VIDIOC_DBG_G_REGISTER, reg); + + mutex_unlock(&dev->lock); + + return ret; +} + +static int vidioc_s_register(struct file *file, void *priv, + struct v4l2_dbg_register *reg) +{ + struct cx231xx_fh *fh = priv; + struct cx231xx *dev = fh->dev; + int ret = 0; + __le64 buf; + u32 value; + u8 data[4] ={0,0,0,0}; + + buf = cpu_to_le64(reg->val); + + switch (reg->match.type) { + case V4L2_CHIP_MATCH_HOST: + { + value = (u32) buf & 0xffffffff; + + switch(reg->match.addr) { + case 0: /* cx231xx internal registers */ + data[0]=(u8)value; + data[1]=(u8)(value>>8); + data[2]=(u8)(value>>16); + data[3]=(u8)(value>>24); + ret = cx231xx_write_ctrl_reg(dev,VRT_SET_REGISTER, (u16) reg->reg, data, 4); + break; + case 1: /* Colibri - read byte */ + ret = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, (u16) reg->reg, 2, value, 1); + break; + case 14: /* Colibri - read dword */ + ret = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, (u16) reg->reg, 2, value, 4); + break; + case 2: /* Hammerhead - read byte */ + ret = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, (u16) reg->reg, 2, value, 1); + break; + case 24: /* Hammerhead - read dword */ + ret = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, (u16) reg->reg, 2, value, 4); + break; + case 3: /* flatiron - read byte */ + ret = cx231xx_write_i2c_data(dev, Flatrion_DEVICE_ADDRESS, (u16) reg->reg, 1, value, 1); + break; + case 34: /* flatiron - read dword */ + ret = cx231xx_write_i2c_data(dev, Flatrion_DEVICE_ADDRESS, (u16) reg->reg, 1, value, 4); + break; + } + } + return ret < 0?ret:0; + + default: + break; + } + + mutex_lock(&dev->lock); + + cx231xx_i2c_call_clients(&dev->i2c_bus[0], VIDIOC_DBG_S_REGISTER, reg); + + mutex_unlock(&dev->lock); + + return ret; +} +#endif + + +static int vidioc_cropcap(struct file *file, void *priv, + struct v4l2_cropcap *cc) +{ + struct cx231xx_fh *fh = priv; + struct cx231xx *dev = fh->dev; + + if (cc->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + + cc->bounds.left = 0; + cc->bounds.top = 0; + cc->bounds.width = dev->width; + cc->bounds.height = dev->height; + cc->defrect = cc->bounds; + cc->pixelaspect.numerator = 54; /* 4:3 FIXME: remove magic numbers */ + cc->pixelaspect.denominator = 59; + + return 0; +} + +static int vidioc_streamon(struct file *file, void *priv, + enum v4l2_buf_type type) +{ + struct cx231xx_fh *fh = priv; + struct cx231xx *dev = fh->dev; + int rc; + + rc = check_dev(dev); + if (rc < 0) + return rc; + + mutex_lock(&dev->lock); + rc = res_get(fh); + + if (likely(rc >= 0)) + rc = videobuf_streamon(&fh->vb_vidq); + + mutex_unlock(&dev->lock); + + return rc; +} + +static int vidioc_streamoff(struct file *file, void *priv, + enum v4l2_buf_type type) +{ + struct cx231xx_fh *fh = priv; + struct cx231xx *dev = fh->dev; + int rc; + + rc = check_dev(dev); + if (rc < 0) + return rc; + + if ( (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) || + (fh->type != V4L2_BUF_TYPE_VBI_CAPTURE) ) + return -EINVAL; + if (type != fh->type) + return -EINVAL; + + mutex_lock(&dev->lock); + + videobuf_streamoff(&fh->vb_vidq); + res_free(fh); + + mutex_unlock(&dev->lock); + + return 0; +} + +static int vidioc_querycap(struct file *file, void *priv, + struct v4l2_capability *cap) +{ + struct cx231xx_fh *fh = priv; + struct cx231xx *dev = fh->dev; + + strlcpy(cap->driver, "cx231xx", sizeof(cap->driver)); + strlcpy(cap->card, cx231xx_boards[dev->model].name, sizeof(cap->card)); + strlcpy(cap->bus_info, dev_name(&dev->udev->dev), sizeof(cap->bus_info)); + + cap->version = CX231XX_VERSION_CODE; + + cap->capabilities = + V4L2_CAP_VBI_CAPTURE | +#if 0 /* Keep */ + V4L2_CAP_SLICED_VBI_CAPTURE | +#endif + V4L2_CAP_VIDEO_CAPTURE | + V4L2_CAP_AUDIO | + V4L2_CAP_READWRITE | V4L2_CAP_STREAMING; + + if (dev->tuner_type != TUNER_ABSENT) + cap->capabilities |= V4L2_CAP_TUNER; + + return 0; +} + +static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, + struct v4l2_fmtdesc *f) +{ + if (unlikely(f->index >= ARRAY_SIZE(format))) + return -EINVAL; + + strlcpy(f->description, format[f->index].name, sizeof(f->description)); + f->pixelformat = format[f->index].fourcc; + + return 0; +} + +/* Sliced VBI ioctls */ +static int vidioc_g_fmt_sliced_vbi_cap(struct file *file, void *priv, + struct v4l2_format *f) +{ + struct cx231xx_fh *fh = priv; + struct cx231xx *dev = fh->dev; + int rc; + + rc = check_dev(dev); + if (rc < 0) + return rc; + + mutex_lock(&dev->lock); + + f->fmt.sliced.service_set = 0; + + cx231xx_i2c_call_clients(&dev->i2c_bus[0], VIDIOC_G_FMT, f); + + if (f->fmt.sliced.service_set == 0) + rc = -EINVAL; + + mutex_unlock(&dev->lock); + return rc; +} + +static int vidioc_try_set_sliced_vbi_cap(struct file *file, void *priv, + struct v4l2_format *f) +{ + struct cx231xx_fh *fh = priv; + struct cx231xx *dev = fh->dev; + int rc; + + rc = check_dev(dev); + if (rc < 0) + return rc; + + mutex_lock(&dev->lock); + cx231xx_i2c_call_clients(&dev->i2c_bus[0], VIDIOC_G_FMT, f); + mutex_unlock(&dev->lock); + + if (f->fmt.sliced.service_set == 0) + return -EINVAL; + + return 0; +} + + +/* RAW VBI ioctls */ + +static int vidioc_g_fmt_vbi_cap(struct file *file, void *priv, + struct v4l2_format *f) +{ + struct cx231xx_fh *fh = priv; + struct cx231xx *dev = fh->dev; + + f->fmt.vbi.sampling_rate = (dev->norm & V4L2_STD_625_50) ? + 35468950:28636363; + f->fmt.vbi.samples_per_line = VBI_LINE_LENGTH; + f->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY; + f->fmt.vbi.offset = 64 * 4; + f->fmt.vbi.start[0] = (dev->norm & V4L2_STD_625_50) ? + PAL_VBI_START_LINE : NTSC_VBI_START_LINE; + f->fmt.vbi.count[0] = (dev->norm & V4L2_STD_625_50) ? + PAL_VBI_LINES : NTSC_VBI_LINES; + f->fmt.vbi.start[1] = (dev->norm & V4L2_STD_625_50) ? + PAL_VBI_START_LINE+312 : NTSC_VBI_START_LINE + 263; + f->fmt.vbi.count[1] = f->fmt.vbi.count[0]; + + return 0; + +} + +static int vidioc_try_fmt_vbi_cap(struct file *file, void *priv, + struct v4l2_format *f) +{ + struct cx231xx_fh *fh = priv; + struct cx231xx *dev = fh->dev; + + if (dev->vbi_stream_on && !fh->stream_on) { + cx231xx_errdev("%s device in use by another fh\n", __func__); + return -EBUSY; + } + + f->type = V4L2_BUF_TYPE_VBI_CAPTURE; + f->fmt.vbi.sampling_rate = (dev->norm & V4L2_STD_625_50) ? + 35468950:28636363; + f->fmt.vbi.samples_per_line = VBI_LINE_LENGTH; + f->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY; + f->fmt.vbi.offset = 244; + f->fmt.vbi.flags = 0; + f->fmt.vbi.start[0] = (dev->norm & V4L2_STD_625_50) ? + PAL_VBI_START_LINE : NTSC_VBI_START_LINE; + f->fmt.vbi.count[0] = (dev->norm & V4L2_STD_625_50) ? + PAL_VBI_LINES : NTSC_VBI_LINES; + f->fmt.vbi.start[1] = (dev->norm & V4L2_STD_625_50) ? + PAL_VBI_START_LINE+312 : NTSC_VBI_START_LINE + 263; + f->fmt.vbi.count[1] = f->fmt.vbi.count[0]; + + return 0; + +} + +static int vidioc_reqbufs(struct file *file, void *priv, + struct v4l2_requestbuffers *rb) +{ + struct cx231xx_fh *fh = priv; + struct cx231xx *dev = fh->dev; + int rc; + + rc = check_dev(dev); + if (rc < 0) + return rc; + + return (videobuf_reqbufs(&fh->vb_vidq, rb)); +} + +static int vidioc_querybuf(struct file *file, void *priv, + struct v4l2_buffer *b) +{ + struct cx231xx_fh *fh = priv; + struct cx231xx *dev = fh->dev; + int rc; + + rc = check_dev(dev); + if (rc < 0) + return rc; + + return (videobuf_querybuf(&fh->vb_vidq, b)); +} + +static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *b) +{ + struct cx231xx_fh *fh = priv; + struct cx231xx *dev = fh->dev; + int rc; + + rc = check_dev(dev); + if (rc < 0) + return rc; + + return (videobuf_qbuf(&fh->vb_vidq, b)); +} + +static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b) +{ + struct cx231xx_fh *fh = priv; + struct cx231xx *dev = fh->dev; + int rc; + + rc = check_dev(dev); + if (rc < 0) + return rc; + + return (videobuf_dqbuf(&fh->vb_vidq, b, + file->f_flags & O_NONBLOCK)); +} + +#ifdef CONFIG_VIDEO_V4L1_COMPAT +static int vidiocgmbuf(struct file *file, void *priv, struct video_mbuf *mbuf) +{ + struct cx231xx_fh *fh = priv; + + return videobuf_cgmbuf(&fh->vb_vidq, mbuf, 8); +} +#endif + + +/* ----------------------------------------------------------- */ +/* RADIO ESPECIFIC IOCTLS */ +/* ----------------------------------------------------------- */ + +static int radio_querycap(struct file *file, void *priv, + struct v4l2_capability *cap) +{ + struct cx231xx *dev = ((struct cx231xx_fh *)priv)->dev; + + strlcpy(cap->driver, "cx231xx", sizeof(cap->driver)); + strlcpy(cap->card, cx231xx_boards[dev->model].name, sizeof(cap->card)); + usb_make_path(dev->udev, cap->bus_info, sizeof(cap->bus_info)); + + cap->version = CX231XX_VERSION_CODE; + cap->capabilities = V4L2_CAP_TUNER; + return 0; +} + +static int radio_g_tuner(struct file *file, void *priv, + struct v4l2_tuner *t) +{ + struct cx231xx *dev = ((struct cx231xx_fh *)priv)->dev; + + if (unlikely(t->index > 0)) + return -EINVAL; + + strcpy(t->name, "Radio"); + t->type = V4L2_TUNER_RADIO; + + mutex_lock(&dev->lock); + cx231xx_i2c_call_clients(&dev->i2c_bus[1], VIDIOC_G_TUNER, t); + mutex_unlock(&dev->lock); + + return 0; +} + +static int radio_enum_input(struct file *file, void *priv, + struct v4l2_input *i) +{ + if (i->index != 0) + return -EINVAL; + strcpy(i->name, "Radio"); + i->type = V4L2_INPUT_TYPE_TUNER; + + return 0; +} + +static int radio_g_audio(struct file *file, void *priv, struct v4l2_audio *a) +{ + if (unlikely(a->index)) + return -EINVAL; + + strcpy(a->name, "Radio"); + return 0; +} + +static int radio_s_tuner(struct file *file, void *priv, + struct v4l2_tuner *t) +{ + struct cx231xx *dev = ((struct cx231xx_fh *)priv)->dev; + + if (0 != t->index) + return -EINVAL; + + mutex_lock(&dev->lock); + cx231xx_i2c_call_clients(&dev->i2c_bus[1], VIDIOC_S_TUNER, t); + mutex_unlock(&dev->lock); + + return 0; +} + +static int radio_s_audio(struct file *file, void *fh, + struct v4l2_audio *a) +{ + return 0; +} + +static int radio_s_input(struct file *file, void *fh, unsigned int i) +{ + return 0; +} + +static int radio_queryctrl(struct file *file, void *priv, + struct v4l2_queryctrl *c) +{ + int i; + + if (c->id < V4L2_CID_BASE || + c->id >= V4L2_CID_LASTP1) + return -EINVAL; + if (c->id == V4L2_CID_AUDIO_MUTE) { + for (i = 0; i < CX231XX_CTLS; i++) + if (cx231xx_ctls[i].v.id == c->id) + break; + *c = cx231xx_ctls[i].v; + } else + *c = no_ctl; + return 0; +} + +/* + * cx231xx_v4l2_open() + * inits the device and starts isoc transfer + */ +static int cx231xx_v4l2_open(struct file *filp) +{ + int minor = video_devdata(filp)->minor; + int errCode = 0, radio = 0; + struct cx231xx *dev = NULL; + struct cx231xx_fh *fh; + enum v4l2_buf_type fh_type = 0; + + dev = cx231xx_get_device(minor, &fh_type, &radio); + if (NULL == dev) + return -ENODEV; + + mutex_lock(&dev->lock); + + cx231xx_videodbg("open minor=%d type=%s users=%d\n", + minor, v4l2_type_names[fh_type], dev->users); + +#if 0 /* Keep */ + errCode = cx231xx_set_mode(dev, CX231XX_ANALOG_MODE); + if (errCode < 0) { + cx231xx_errdev("Device locked on digital mode. Can't open analog\n"); + mutex_unlock(&dev->lock); + return -EBUSY; + } +#endif + + fh = kzalloc(sizeof(struct cx231xx_fh), GFP_KERNEL); + if (!fh) { + cx231xx_errdev("cx231xx-video.c: Out of memory?!\n"); + mutex_unlock(&dev->lock); + return -ENOMEM; + } + fh->dev = dev; + fh->radio = radio; + fh->type = fh_type; + filp->private_data = fh; + + if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE && dev->users == 0) { + dev->width = norm_maxw(dev); + dev->height = norm_maxh(dev); + dev->hscale = 0; + dev->vscale = 0; + + + /* Power up in Analog TV mode */ + cx231xx_set_power_mode(dev, POLARIS_AVMODE_ANALOGT_TV); + +#if 0 /* Keep */ + cx231xx_set_mode(dev, CX231XX_ANALOG_MODE); +#endif + cx231xx_resolution_set(dev); + + /* set video alternate setting */ + cx231xx_set_video_alternate(dev); + + /* Needed, since GPIO might have disabled power of + some i2c device */ + cx231xx_config_i2c(dev); + + /* device needs to be initialized before isoc transfer */ + dev->video_input = dev->video_input > 2 ? 2: dev->video_input; + video_mux(dev, dev->video_input ); + + } + if (fh->radio) { + cx231xx_videodbg("video_open: setting radio device\n"); + + /* cx231xx_start_radio(dev); */ + + cx231xx_i2c_call_clients(&dev->i2c_bus[1], AUDC_SET_RADIO, NULL); + } + + dev->users++; + + if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { + videobuf_queue_vmalloc_init(&fh->vb_vidq, &cx231xx_video_qops, + NULL, &dev->video_mode.slock, fh->type, V4L2_FIELD_INTERLACED, /* V4L2_FIELD_SEQ_TB, */ + sizeof(struct cx231xx_buffer), fh); + } + + if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) { + + /* Set the required alternate setting VBI interface works in Bulk mode only */ + cx231xx_set_alt_setting(dev, INDEX_VANC, 0); + + videobuf_queue_vmalloc_init(&fh->vb_vidq, &cx231xx_vbi_qops, + NULL, &dev->vbi_mode.slock, fh->type, V4L2_FIELD_SEQ_TB, /* V4L2_FIELD_INTERLACED, */ + sizeof(struct cx231xx_buffer), fh); + } + + mutex_unlock(&dev->lock); + + return errCode; +} + +/* + * cx231xx_realease_resources() + * unregisters the v4l2,i2c and usb devices + * called when the device gets disconected or at module unload +*/ +void cx231xx_release_analog_resources(struct cx231xx *dev) +{ + + /*FIXME: I2C IR should be disconnected */ + + if (dev->radio_dev) { + if (-1 != dev->radio_dev->minor) + video_unregister_device(dev->radio_dev); + else + video_device_release(dev->radio_dev); + dev->radio_dev = NULL; + } + if (dev->vbi_dev) { + cx231xx_info("V4L2 device /dev/vbi%d deregistered\n", + dev->vbi_dev->num); + if (-1 != dev->vbi_dev->minor) + video_unregister_device(dev->vbi_dev); + else + video_device_release(dev->vbi_dev); + dev->vbi_dev = NULL; + } + if (dev->vdev) { + cx231xx_info("V4L2 device /dev/video%d deregistered\n", + dev->vdev->num); + if (-1 != dev->vdev->minor) + video_unregister_device(dev->vdev); + else + video_device_release(dev->vdev); + dev->vdev = NULL; + } +} + +/* + * cx231xx_v4l2_close() + * stops streaming and deallocates all resources allocated by the v4l2 + * calls and ioctls + */ +static int cx231xx_v4l2_close(struct file *filp) +{ + struct cx231xx_fh *fh = filp->private_data; + struct cx231xx *dev = fh->dev; + + cx231xx_videodbg("users=%d\n", dev->users); + + mutex_lock(&dev->lock); + + if (res_check(fh)) + res_free(fh); + + if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) { + videobuf_stop(&fh->vb_vidq); + videobuf_mmap_free(&fh->vb_vidq); + + /* the device is already disconnect, + free the remaining resources */ + if (dev->state & DEV_DISCONNECTED) { + cx231xx_release_resources(dev); + mutex_unlock(&dev->lock); + kfree(dev); + return 0; + } + + /* do this before setting alternate! */ + cx231xx_uninit_vbi_isoc(dev); + + /* set alternate 0 */ + if( !dev->vbi_or_sliced_cc_mode) { + cx231xx_set_alt_setting(dev, INDEX_VANC, 0); + } else { + cx231xx_set_alt_setting(dev, INDEX_HANC, 0); + } + + kfree(fh); + dev->users--; + wake_up_interruptible_nr(&dev->open, 1); + mutex_unlock(&dev->lock); + return 0; + } + + if (dev->users == 1) { + videobuf_stop(&fh->vb_vidq); + videobuf_mmap_free(&fh->vb_vidq); + + /* the device is already disconnect, + free the remaining resources */ + if (dev->state & DEV_DISCONNECTED) { + cx231xx_release_resources(dev); + mutex_unlock(&dev->lock); + kfree(dev); + return 0; + } + + /* Save some power by putting tuner to sleep */ + cx231xx_i2c_call_clients(&dev->i2c_bus[1], TUNER_SET_STANDBY, NULL); + + /* do this before setting alternate! */ + cx231xx_uninit_isoc(dev); + cx231xx_set_mode(dev, CX231XX_SUSPEND); + + /* set alternate 0 */ + cx231xx_set_alt_setting(dev, INDEX_VIDEO, 0); + } + kfree(fh); + dev->users--; + wake_up_interruptible_nr(&dev->open, 1); + mutex_unlock(&dev->lock); + return 0; +} + +/* + * cx231xx_v4l2_read() + * will allocate buffers when called for the first time + */ +static ssize_t +cx231xx_v4l2_read(struct file *filp, char __user *buf, size_t count, + loff_t *pos) +{ + struct cx231xx_fh *fh = filp->private_data; + struct cx231xx *dev = fh->dev; + int rc; + + rc = check_dev(dev); + if (rc < 0) + return rc; + + if ( (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) || + (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) ) { + mutex_lock(&dev->lock); + rc = res_get(fh); + mutex_unlock(&dev->lock); + + if (unlikely(rc < 0)) + return rc; + + return videobuf_read_stream(&fh->vb_vidq, buf, count, pos, 0, + filp->f_flags & O_NONBLOCK); + } + return 0; +} + +/* + * cx231xx_v4l2_poll() + * will allocate buffers when called for the first time + */ +static unsigned int cx231xx_v4l2_poll(struct file *filp, poll_table * wait) +{ + struct cx231xx_fh *fh = filp->private_data; + struct cx231xx *dev = fh->dev; + int rc; + + rc = check_dev(dev); + if (rc < 0) + return rc; + + mutex_lock(&dev->lock); + rc = res_get(fh); + mutex_unlock(&dev->lock); + + if (unlikely(rc < 0)) + return POLLERR; + + if ( (V4L2_BUF_TYPE_VIDEO_CAPTURE == fh->type) || + (V4L2_BUF_TYPE_VBI_CAPTURE == fh->type) ) + return videobuf_poll_stream(filp, &fh->vb_vidq, wait); + else + return POLLERR; +} + +/* + * cx231xx_v4l2_mmap() + */ +static int cx231xx_v4l2_mmap(struct file *filp, struct vm_area_struct *vma) +{ + struct cx231xx_fh *fh = filp->private_data; + struct cx231xx *dev = fh->dev; + int rc; + + rc = check_dev(dev); + if (rc < 0) + return rc; + + mutex_lock(&dev->lock); + rc = res_get(fh); + mutex_unlock(&dev->lock); + + if (unlikely(rc < 0)) + return rc; + + rc = videobuf_mmap_mapper(&fh->vb_vidq, vma); + + cx231xx_videodbg("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; +} + +static const struct v4l2_file_operations cx231xx_v4l_fops = { + .owner = THIS_MODULE, + .open = cx231xx_v4l2_open, + .release = cx231xx_v4l2_close, + .read = cx231xx_v4l2_read, + .poll = cx231xx_v4l2_poll, + .mmap = cx231xx_v4l2_mmap, + .ioctl = video_ioctl2, +}; + +static const struct v4l2_ioctl_ops video_ioctl_ops = { + .vidioc_querycap = vidioc_querycap, + .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, + .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, + .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, + .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, + .vidioc_g_fmt_vbi_cap = vidioc_g_fmt_vbi_cap, + .vidioc_try_fmt_vbi_cap = vidioc_try_fmt_vbi_cap, + .vidioc_s_fmt_vbi_cap = vidioc_try_fmt_vbi_cap, + .vidioc_g_audio = vidioc_g_audio, + .vidioc_s_audio = vidioc_s_audio, + .vidioc_cropcap = vidioc_cropcap, + .vidioc_g_fmt_sliced_vbi_cap = vidioc_g_fmt_sliced_vbi_cap, + .vidioc_try_fmt_sliced_vbi_cap = vidioc_try_set_sliced_vbi_cap, + .vidioc_reqbufs = vidioc_reqbufs, + .vidioc_querybuf = vidioc_querybuf, + .vidioc_qbuf = vidioc_qbuf, + .vidioc_dqbuf = vidioc_dqbuf, + .vidioc_s_std = vidioc_s_std, + .vidioc_g_std = vidioc_g_std, + .vidioc_enum_input = vidioc_enum_input, + .vidioc_g_input = vidioc_g_input, + .vidioc_s_input = vidioc_s_input, + .vidioc_queryctrl = vidioc_queryctrl, + .vidioc_g_ctrl = vidioc_g_ctrl, + .vidioc_s_ctrl = vidioc_s_ctrl, + .vidioc_streamon = vidioc_streamon, + .vidioc_streamoff = vidioc_streamoff, + .vidioc_g_tuner = vidioc_g_tuner, + .vidioc_s_tuner = vidioc_s_tuner, + .vidioc_g_frequency = vidioc_g_frequency, + .vidioc_s_frequency = vidioc_s_frequency, +#ifdef CONFIG_VIDEO_ADV_DEBUG + .vidioc_g_register = vidioc_g_register, + .vidioc_s_register = vidioc_s_register, +#endif +#ifdef CONFIG_VIDEO_V4L1_COMPAT + .vidiocgmbuf = vidiocgmbuf, +#endif +}; + +static struct video_device cx231xx_vbi_template; + +static const struct video_device cx231xx_video_template = { + .fops = &cx231xx_v4l_fops, + .release = video_device_release, + .ioctl_ops = &video_ioctl_ops, + .minor = -1, + .tvnorms = V4L2_STD_ALL, + .current_norm = V4L2_STD_PAL, +}; + +static const struct v4l2_file_operations radio_fops = { + .owner = THIS_MODULE, + .open = cx231xx_v4l2_open, + .release = cx231xx_v4l2_close, + .ioctl = video_ioctl2, +}; + +static const struct v4l2_ioctl_ops radio_ioctl_ops = { + .vidioc_querycap = radio_querycap, + .vidioc_g_tuner = radio_g_tuner, + .vidioc_enum_input = radio_enum_input, + .vidioc_g_audio = radio_g_audio, + .vidioc_s_tuner = radio_s_tuner, + .vidioc_s_audio = radio_s_audio, + .vidioc_s_input = radio_s_input, + .vidioc_queryctrl = radio_queryctrl, + .vidioc_g_ctrl = vidioc_g_ctrl, + .vidioc_s_ctrl = vidioc_s_ctrl, + .vidioc_g_frequency = vidioc_g_frequency, + .vidioc_s_frequency = vidioc_s_frequency, +#ifdef CONFIG_VIDEO_ADV_DEBUG + .vidioc_g_register = vidioc_g_register, + .vidioc_s_register = vidioc_s_register, +#endif +}; + +static struct video_device cx231xx_radio_template = { + .name = "cx231xx-radio", + .fops = &radio_fops, + .ioctl_ops = &radio_ioctl_ops, + .minor = -1, +}; + +/******************************** usb interface ******************************/ + + +static struct video_device *cx231xx_vdev_init(struct cx231xx *dev, + const struct video_device *template, + const char *type_name) +{ + struct video_device *vfd; + + vfd = video_device_alloc(); + if (NULL == vfd) + return NULL; + *vfd = *template; + vfd->minor = -1; + vfd->parent = &dev->udev->dev; + vfd->release = video_device_release; + vfd->debug = video_debug; + + snprintf(vfd->name, sizeof(vfd->name), "%s %s", + dev->name, type_name); + + return vfd; +} + +int cx231xx_register_analog_devices(struct cx231xx *dev) +{ + int ret; + + cx231xx_info("%s()\n", __func__); + + cx231xx_info("%s: v4l2 driver version %d.%d.%d\n", + dev->name, + (CX231XX_VERSION_CODE >> 16) & 0xff, + (CX231XX_VERSION_CODE >> 8) & 0xff, CX231XX_VERSION_CODE & 0xff); + + /* set default norm */ + /*dev->norm = cx231xx_video_template.current_norm;*/ + dev->width = norm_maxw(dev); + dev->height = norm_maxh(dev); + dev->interlaced = 0; + dev->hscale = 0; + dev->vscale = 0; + + /* Analog specific initialization */ + dev->format = &format[0]; + /* video_mux(dev, dev->video_input); */ + + /* Audio defaults */ + dev->mute = 1; + dev->volume = 0x1f; + + /* enable vbi capturing */ + /* write code here... */ + + /* allocate and fill video video_device struct */ + dev->vdev = cx231xx_vdev_init(dev, &cx231xx_video_template, "video"); + if (!dev->vdev) { + cx231xx_errdev("cannot allocate video_device.\n"); + return -ENODEV; + } + + /* register v4l2 video video_device */ + ret = video_register_device(dev->vdev, VFL_TYPE_GRABBER, + video_nr[dev->devno]); + if (ret) { + cx231xx_errdev("unable to register video device (error=%i).\n", ret); + return ret; + } + + cx231xx_info("%s/0: registered device video%d [v4l2]\n", + dev->name, dev->vdev->num); + + /* Initialize VBI template */ + memcpy( &cx231xx_vbi_template, &cx231xx_video_template, + sizeof(cx231xx_vbi_template) ); + strcpy(cx231xx_vbi_template.name,"cx231xx-vbi"); + + + /* Allocate and fill vbi video_device struct */ + dev->vbi_dev = cx231xx_vdev_init(dev, &cx231xx_vbi_template, "vbi"); + + /* register v4l2 vbi video_device */ + ret = video_register_device(dev->vbi_dev, VFL_TYPE_VBI, + vbi_nr[dev->devno]); + if (ret < 0) { + cx231xx_errdev("unable to register vbi device\n"); + return ret; + } + + cx231xx_info("%s/0: registered device vbi%d\n", + dev->name, dev->vbi_dev->num); + + if (cx231xx_boards[dev->model].radio.type == CX231XX_RADIO) { + dev->radio_dev = cx231xx_vdev_init(dev, &cx231xx_radio_template, "radio"); + if (!dev->radio_dev) { + cx231xx_errdev("cannot allocate video_device.\n"); + return -ENODEV; + } + ret = video_register_device(dev->radio_dev, VFL_TYPE_RADIO, + radio_nr[dev->devno]); + if (ret < 0) { + cx231xx_errdev("can't register radio device\n"); + return ret; + } + cx231xx_info("Registered radio device as /dev/radio%d\n", + dev->radio_dev->num); + } + + cx231xx_info("V4L2 device registered as /dev/video%d and /dev/vbi%d\n", + dev->vdev->num, dev->vbi_dev->num); + + return 0; +} + + diff --git a/linux/drivers/media/video/cx231xx/cx231xx.h b/linux/drivers/media/video/cx231xx/cx231xx.h new file mode 100644 index 000000000..5ac7135ea --- /dev/null +++ b/linux/drivers/media/video/cx231xx/cx231xx.h @@ -0,0 +1,771 @@ +/* + cx231xx.h - driver for Conexant Cx23100/101/102 USB video capture devices + + Copyright (C) 2008 + Based on em28xx driver + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef _CX231XX_H +#define _CX231XX_H + +#include "compat.h" +#include +#include + +#include +#include +#include +#include +#if defined(CONFIG_VIDEO_CX231XX_DVB) || defined(CONFIG_VIDEO_CX231XX_DVB_MODULE) +#include +#endif + +#include "cx231xx-reg.h" +#include "cx231xx-pcb-config.h" +#include "cx231xx-conf-reg.h" + +#define CX231XX_VERSION_CODE KERNEL_VERSION(0, 1, 0) +#define DRIVER_NAME "cx231xx" +#define PWR_SLEEP_INTERVAL 5 + +/* I2C addresses for control block in Cx231xx */ +#define Colibri_DEVICE_ADDRESS 0x60 +#define Flatrion_DEVICE_ADDRESS 0x98 +#define HAMMERHEAD_I2C_ADDRESS 0x88 +#define DIF_USE_BASEBAND 0xFFFFFFFF + +/* Boards supported by driver */ +#define CX231XX_BOARD_UNKNOWN 0 +#define CX231XX_BOARD_CNXT_RDE_250 1 +#define CX231XX_BOARD_CNXT_RDU_250 2 + +/* Limits minimum and default number of buffers */ +#define CX231XX_MIN_BUF 4 +#define CX231XX_DEF_BUF 12 +#define CX231XX_DEF_VBI_BUF 6 + +#define VBI_LINE_COUNT 17 +#define VBI_LINE_LENGTH 1440 + +/*Limits the max URB message size */ +#define URB_MAX_CTRL_SIZE 80 + +/* Params for validated field */ +#define CX231XX_BOARD_NOT_VALIDATED 1 +#define CX231XX_BOARD_VALIDATED 0 + +/* maximum number of cx231xx boards */ +#define CX231XX_MAXBOARDS 8 + +/* maximum number of frames that can be queued */ +#define CX231XX_NUM_FRAMES 5 + +/* number of buffers for isoc transfers */ +#define CX231XX_NUM_BUFS 8 + +/* number of packets for each buffer + windows requests only 40 packets .. so we better do the same + this is what I found out for all alternate numbers there! + */ +#define CX231XX_NUM_PACKETS 40 + + +/* default alternate; 0 means choose the best */ +#define CX231XX_PINOUT 0 + +#define CX231XX_INTERLACED_DEFAULT 1 + + +/* time to wait when stopping the isoc transfer */ +#define CX231XX_URB_TIMEOUT msecs_to_jiffies(CX231XX_NUM_BUFS * CX231XX_NUM_PACKETS) + + +enum cx231xx_mode { + CX231XX_SUSPEND, + CX231XX_ANALOG_MODE, + CX231XX_DIGITAL_MODE, +}; + +enum cx231xx_std_mode { + CX231XX_TV_AIR = 0, + CX231XX_TV_CABLE +}; + +enum cx231xx_stream_state { + STREAM_OFF, + STREAM_INTERRUPT, + STREAM_ON, +}; + +struct cx231xx; + +struct cx231xx_usb_isoc_ctl { + /* max packet size of isoc transaction */ + int max_pkt_size; + + /* number of allocated urbs */ + int num_bufs; + + /* urb for isoc transfers */ + struct urb **urb; + + /* transfer buffers for isoc transfer */ + char **transfer_buffer; + + /* Last buffer command and region */ + u8 cmd; + int pos, size, pktsize; + + /* Last field: ODD or EVEN? */ + int field; + + /* Stores incomplete commands */ + u32 tmp_buf; + int tmp_buf_len; + + /* Stores already requested buffers */ + struct cx231xx_buffer *buf; + + /* Stores the number of received fields */ + int nfields; + + /* isoc urb callback */ + int (*isoc_copy) (struct cx231xx *dev, struct urb *urb); + +}; + + + +struct cx231xx_fmt { + char *name; + u32 fourcc; /* v4l2 format id */ + int depth; + int reg; +}; + +/* buffer for one video frame */ +struct cx231xx_buffer { + /* common v4l buffer stuff -- must be first */ + struct videobuf_buffer vb; + + struct list_head frame; + int top_field; + int receiving; +}; + +struct cx231xx_dmaqueue { + struct list_head active; + struct list_head queued; + + wait_queue_head_t wq; + + /* Counters to control buffer fill */ + int pos; + u8 is_partial_line; + u8 partial_buf[8]; + u8 last_sav; + int current_field; + u32 bytes_left_in_line; + u32 lines_completed; + u8 field1_done; + u32 lines_per_field; +}; + + +/* inputs */ + +#define MAX_CX231XX_INPUT 4 + +enum cx231xx_itype { + CX231XX_VMUX_COMPOSITE1 = 1, + CX231XX_VMUX_SVIDEO, + CX231XX_VMUX_TELEVISION, + CX231XX_VMUX_CABLE, + CX231XX_RADIO, + CX231XX_VMUX_DVB, + CX231XX_VMUX_DEBUG +}; + +enum cx231xx_v_input { + CX231XX_VIN_1_1 = 0x1, + CX231XX_VIN_2_1, + CX231XX_VIN_3_1, + CX231XX_VIN_4_1, + CX231XX_VIN_1_2 = 0x01, + CX231XX_VIN_2_2, + CX231XX_VIN_3_2, + CX231XX_VIN_1_3 = 0x1, + CX231XX_VIN_2_3, + CX231XX_VIN_3_3, +}; + +/* cx231xx has two audio inputs: tuner and line in */ +enum cx231xx_amux { + /* This is the only entry for cx231xx tuner input */ + CX231XX_AMUX_VIDEO, /* cx231xx tuner*/ + CX231XX_AMUX_LINE_IN, /* Line In */ +}; + +struct cx231xx_reg_seq { + unsigned char bit; + unsigned char val; + int sleep; +}; + +struct cx231xx_input { + enum cx231xx_itype type; + unsigned int vmux; + enum cx231xx_amux amux; + struct cx231xx_reg_seq *gpio; +}; + +#define INPUT(nr) (&cx231xx_boards[dev->model].input[nr]) + +enum cx231xx_decoder { + CX231XX_NODECODER, + CX231XX_AVDECODER +}; + +typedef enum _I2C_MASTER_PORT +{ + I2C_0 =0, + I2C_1 =1, + I2C_2 =2, + I2C_3 =3 +}CX231XX_I2C_MASTER_PORT; + +struct cx231xx_board { + char *name; + int vchannels; + int tuner_type; + int tuner_addr; + v4l2_std_id norm; /* tv norm */ + + /* demod related */ + int demod_addr; + u8 demod_xfer_mode; /* 0 - Serial; 1 - parallel */ + + /* GPIO Pins */ + struct cx231xx_reg_seq *dvb_gpio; + struct cx231xx_reg_seq *suspend_gpio; + struct cx231xx_reg_seq *tuner_gpio; + u8 tuner_sif_gpio; + u8 tuner_scl_gpio; + u8 tuner_sda_gpio; + + /* PIN ctrl */ + u32 ctl_pin_status_mask; + u8 agc_analog_digital_select_gpio; + u32 gpio_pin_status_mask; + + /* i2c masters */ + u8 tuner_i2c_master; + u8 demod_i2c_master; + + unsigned int max_range_640_480:1; + unsigned int has_dvb:1; + unsigned int valid:1; + + unsigned char xclk, i2c_speed; + + enum cx231xx_decoder decoder; + + struct cx231xx_input input[MAX_CX231XX_INPUT]; + struct cx231xx_input radio; + IR_KEYTAB_TYPE *ir_codes; +}; + +/* device states */ +enum cx231xx_dev_state { + DEV_INITIALIZED = 0x01, + DEV_DISCONNECTED = 0x02, + DEV_MISCONFIGURED = 0x04, +}; + +enum AFE_MODE +{ + AFE_MODE_LOW_IF, + AFE_MODE_BASEBAND, + AFE_MODE_EU_HI_IF, + AFE_MODE_US_HI_IF, + AFE_MODE_JAPAN_HI_IF +}; + +enum AUDIO_INPUT +{ + AUDIO_INPUT_MUTE, + AUDIO_INPUT_LINE, + AUDIO_INPUT_TUNER_TV, + AUDIO_INPUT_SPDIF, + AUDIO_INPUT_TUNER_FM +}; + +#define CX231XX_AUDIO_BUFS 5 +#define CX231XX_NUM_AUDIO_PACKETS 64 +#define CX231XX_CAPTURE_STREAM_EN 1 +#define CX231XX_STOP_AUDIO 0 +#define CX231XX_START_AUDIO 1 + + +/* cx231xx extensions */ +#define CX231XX_AUDIO 0x10 +#define CX231XX_DVB 0x20 + +struct cx231xx_audio { + char name[50]; + char *transfer_buffer[CX231XX_AUDIO_BUFS]; + struct urb *urb[CX231XX_AUDIO_BUFS]; + struct usb_device *udev; + unsigned int capture_transfer_done; +#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 16) + snd_pcm_substream_t *capture_pcm_substream; +#else + struct snd_pcm_substream *capture_pcm_substream; +#endif + + unsigned int hwptr_done_capture; +#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 16) + snd_card_t *sndcard; +#else + struct snd_card *sndcard; +#endif + + int users, shutdown; + enum cx231xx_stream_state capture_stream; + spinlock_t slock; + + int alt; /* alternate */ + int max_pkt_size; /* max packet size of isoc transaction */ + int num_alt; /* Number of alternative settings */ + unsigned int *alt_max_pkt_size; /* array of wMaxPacketSize */ + u16 end_point_addr; +}; + +struct cx231xx; + +struct cx231xx_fh { + struct cx231xx *dev; + unsigned int stream_on:1; /* Locks streams */ + int radio; + + struct videobuf_queue vb_vidq; + + enum v4l2_buf_type type; +}; + +/**********************************************************************************/ +/* set/get i2c */ +#define I2C_SPEED_1M 0x0 /* 00--1Mb/s, 01-400kb/s, 10--100kb/s, 11--5Mb/s */ +#define I2C_SPEED_400K 0x1 /* 00--1Mb/s, 01-400kb/s, 10--100kb/s, 11--5Mb/s */ +#define I2C_SPEED_100K 0x2 /* 00--1Mb/s, 01-400kb/s, 10--100kb/s, 11--5Mb/s */ +#define I2C_SPEED_5M 0x3 /* 00--1Mb/s, 01-400kb/s, 10--100kb/s, 11--5Mb/s */ + +#define I2C_STOP 0x0 /* 0-- STOP transaction */ +#define I2C_NOSTOP 0x1 /* 1-- do not transmit STOP at end of transaction */ +#define I2C_SYNC 0x1 /* 1--alllow slave to insert clock wait states */ + +struct cx231xx_i2c { + struct cx231xx *dev; + + int nr; + + /* i2c i/o */ + struct i2c_adapter i2c_adap; + struct i2c_algo_bit_data i2c_algo; + struct i2c_client i2c_client; + u32 i2c_rc; + + /* different settings for each bus */ + u8 i2c_period; + u8 i2c_nostop; + u8 i2c_reserve; +}; + +struct cx231xx_i2c_xfer_data{ + u8 dev_addr; + u8 direction; /* 1 - IN, 0 - OUT */ + u8 saddr_len; /* sub address len */ + u16 saddr_dat; /* sub addr data */ + u8 buf_size; /* buffer size */ + u8* p_buffer; /* pointer to the buffer */ +}; + +typedef struct _VENDOR_REQUEST_IN +{ + u8 bRequest; + u16 wValue; + u16 wIndex; + u16 wLength; + u8 direction; + u8 bData; + u8 *pBuff; +} VENDOR_REQUEST_IN, *PVENDOR_REQUEST_IN; + +struct cx231xx_ctrl { + struct v4l2_queryctrl v; + u32 off; + u32 reg; + u32 mask; + u32 shift; +}; + +typedef enum{ + Raw_Video = 0, + Audio, + Vbi, /* VANC */ + Sliced_cc, /* HANC */ + TS1_serial_mode, + TS2, + TS1_parallel_mode +}TRANSFER_TYPE; + +struct cx231xx_video_mode { + /* Isoc control struct */ + struct cx231xx_dmaqueue vidq; + struct cx231xx_usb_isoc_ctl isoc_ctl; + spinlock_t slock; + + /* usb transfer */ + int alt; /* alternate */ + int max_pkt_size; /* max packet size of isoc transaction */ + int num_alt; /* Number of alternative settings */ + unsigned int *alt_max_pkt_size; /* array of wMaxPacketSize */ + u16 end_point_addr; +}; + + +/* main device struct */ +struct cx231xx { + /* generic device properties */ + char name[30]; /* name (including minor) of the device */ + int model; /* index in the device_data struct */ + int devno; /* marks the number of this device */ + + struct cx231xx_board board; + + unsigned int stream_on:1; /* Locks streams */ + unsigned int vbi_stream_on:1; /* Locks streams for VBI */ + unsigned int has_audio_class:1; + unsigned int has_alsa_audio:1; + + struct cx231xx_fmt *format; + + struct cx231xx_IR *ir; + + struct list_head devlist; + + int tuner_type; /* type of the tuner */ + int tuner_addr; /* tuner address */ + + /* I2C adapters: Master 1 & 2 (External) & Master 3 (Internal only) */ + struct cx231xx_i2c i2c_bus[3]; + unsigned int xc_fw_load_done:1; + struct mutex gpio_i2c_lock; + + /* video for linux */ + int users; /* user count for exclusive use */ + struct video_device *vdev; /* video for linux device struct */ + v4l2_std_id norm; /* selected tv norm */ + int ctl_freq; /* selected frequency */ + unsigned int ctl_ainput; /* selected audio input */ + int mute; + int volume; + + /* frame properties */ + int width; /* current frame width */ + int height; /* current frame height */ + unsigned hscale; /* horizontal scale factor (see datasheet) */ + unsigned vscale; /* vertical scale factor (see datasheet) */ + int interlaced; /* 1=interlace fileds, 0=just top fileds */ + + struct cx231xx_audio adev; + + /* states */ + enum cx231xx_dev_state state; + + struct work_struct request_module_wk; + + /* locks */ + struct mutex lock; + struct mutex ctrl_urb_lock; /* protects urb_buf */ + struct list_head inqueue, outqueue; + wait_queue_head_t open, wait_frame, wait_stream; + struct video_device *vbi_dev; + struct video_device *radio_dev; + + unsigned char eedata[256]; + + struct cx231xx_video_mode video_mode; + struct cx231xx_video_mode vbi_mode; + struct cx231xx_video_mode sliced_cc_mode; + struct cx231xx_video_mode ts1_mode; + + struct usb_device *udev; /* the usb device */ + char urb_buf[URB_MAX_CTRL_SIZE];/* urb control msg buffer */ + + + /* helper funcs that call usb_control_msg */ + int (*cx231xx_read_ctrl_reg) (struct cx231xx *dev, u8 req, u16 reg, + char *buf, int len); + int (*cx231xx_write_ctrl_reg)(struct cx231xx *dev, u8 req, u16 reg, + char *buf, int len); + int (*cx231xx_send_usb_command)(struct cx231xx_i2c *i2c_bus, + struct cx231xx_i2c_xfer_data *req_data); + int (*cx231xx_gpio_i2c_read)(struct cx231xx *dev, u8 dev_addr, u8 *buf ,u8 len); + int (*cx231xx_gpio_i2c_write)(struct cx231xx *dev, u8 dev_addr, u8 *buf ,u8 len); + + int (*cx231xx_set_analog_freq)(struct cx231xx *dev, u32 freq ) ; + int (*cx231xx_reset_analog_tuner)(struct cx231xx *dev) ; + + enum cx231xx_mode mode; + + struct cx231xx_dvb *dvb; + + /* Cx231xx supported PCB config's */ + struct pcb_config current_pcb_config; + u8 current_scenario_idx; + u8 interface_count; + u8 max_iad_interface_count; + + /* GPIO related register direction and values */ + u32 gpio_dir; + u32 gpio_val; + + /* Power Modes */ + int power_mode; + + /* colibri parameters */ + enum AFE_MODE colibri_mode; + u32 colibri_ref_count; + + /* video related parameters */ + u32 video_input; + u32 active_mode; + u8 vbi_or_sliced_cc_mode; /* 0 - vbi ; 1 - sliced cc mode */ + enum cx231xx_std_mode std_mode; /* 0 - Air; 1 - cable */ + +}; + +struct cx231xx_ops { + struct list_head next; + char *name; + int id; + int (*init)(struct cx231xx *); + int (*fini)(struct cx231xx *); +}; + +/* call back functions in dvb module */ +int cx231xx_set_analog_freq(struct cx231xx *dev, u32 freq ) ; +int cx231xx_reset_analog_tuner(struct cx231xx *dev) ; + +/* Provided by cx231xx-i2c.c */ +void cx231xx_i2c_call_clients(struct cx231xx_i2c *bus, unsigned int cmd, void *arg); +void cx231xx_do_i2c_scan(struct cx231xx *dev, struct i2c_client *c); +int cx231xx_i2c_register(struct cx231xx_i2c *bus); +int cx231xx_i2c_unregister(struct cx231xx_i2c *bus); + +/* Internal block control functions */ +int cx231xx_read_i2c_data(struct cx231xx *dev, u8 dev_addr, + u16 saddr, u8 saddr_len, u32 *data, u8 data_len); +int cx231xx_write_i2c_data(struct cx231xx *dev, u8 dev_addr, + u16 saddr, u8 saddr_len, u32 data, u8 data_len); +int cx231xx_reg_mask_write(struct cx231xx *dev, u8 dev_addr, u8 size, u16 register_address, + u8 bit_start,u8 bit_end, u32 value); +int cx231xx_read_modify_write_i2c_dword(struct cx231xx *dev, u8 dev_addr, + u16 saddr, u32 mask, u32 value); +u32 cx231xx_set_field(u32 field_mask, u32 data); + +/* Colibri related functions */ +int cx231xx_colibri_init_super_block(struct cx231xx *dev, u32 ref_count); +int cx231xx_colibri_init_channels(struct cx231xx *dev); +int cx231xx_colibri_setup_AFE_for_baseband(struct cx231xx *dev); +int cx231xx_colibri_set_input_mux(struct cx231xx *dev, u32 input_mux); +int cx231xx_colibri_set_mode(struct cx231xx *dev, enum AFE_MODE mode); +int cx231xx_colibri_update_power_control(struct cx231xx *dev, AV_MODE avmode); +int cx231xx_colibri_adjust_ref_count(struct cx231xx *dev, u32 video_input); + +/* flatiron related functions */ +int cx231xx_flatiron_initialize(struct cx231xx *dev); +int cx231xx_flatiron_update_power_control(struct cx231xx *dev, AV_MODE avmode); +int cx231xx_flatiron_set_audio_input(struct cx231xx *dev, u8 audio_input); + +/* DIF related functions */ +int cx231xx_dif_configure_C2HH_for_low_IF(struct cx231xx *dev, u32 mode, + u32 function_mode, u32 standard); +int cx231xx_dif_set_standard(struct cx231xx *dev, u32 standard); +int cx231xx_tuner_pre_channel_change(struct cx231xx *dev); +int cx231xx_tuner_post_channel_change(struct cx231xx *dev); + +/* video parser functions */ +u8 cx231xx_find_next_SAV_EAV(u8 *p_buffer, u32 buffer_size, u32 *p_bytes_used); +u8 cx231xx_find_boundary_SAV_EAV(u8 *p_buffer, u8 *partial_buf, u32 *p_bytes_used); +int cx231xx_do_copy(struct cx231xx *dev, struct cx231xx_dmaqueue *dma_q, + u8 *p_buffer, u32 bytes_to_copy); +void cx231xx_reset_video_buffer(struct cx231xx *dev, struct cx231xx_dmaqueue *dma_q); +u8 cx231xx_is_buffer_done(struct cx231xx *dev,struct cx231xx_dmaqueue *dma_q); +u32 cx231xx_copy_video_line(struct cx231xx *dev, struct cx231xx_dmaqueue *dma_q, + u8 *p_line, u32 length, int field_number); +u32 cx231xx_get_video_line(struct cx231xx *dev, struct cx231xx_dmaqueue *dma_q, + u8 sav_eav, u8 *p_buffer, u32 buffer_size); +void cx231xx_swab(u16 *from, u16 *to, u16 len); + +/* Provided by cx231xx-core.c */ + +u32 cx231xx_request_buffers(struct cx231xx *dev, u32 count); +void cx231xx_queue_unusedframes(struct cx231xx *dev); +void cx231xx_release_buffers(struct cx231xx *dev); + +/* read from control pipe */ +int cx231xx_read_ctrl_reg(struct cx231xx *dev, u8 req, u16 reg, + char *buf, int len); + +/* write to control pipe */ +int cx231xx_write_ctrl_reg(struct cx231xx *dev, u8 req, u16 reg, + char *buf, int len); +int cx231xx_mode_register(struct cx231xx *dev, u16 address, u32 mode); + +int cx231xx_send_vendor_cmd(struct cx231xx *dev, VENDOR_REQUEST_IN *ven_req); +int cx231xx_send_usb_command(struct cx231xx_i2c *i2c_bus, + struct cx231xx_i2c_xfer_data *req_data); + +/* Gpio related functions */ +int cx231xx_send_gpio_cmd(struct cx231xx *dev, u32 gpio_bit, u8* gpio_val, + u8 len, u8 request, u8 direction); +int cx231xx_set_gpio_bit(struct cx231xx *dev, u32 gpio_bit, u8* gpio_val); +int cx231xx_get_gpio_bit(struct cx231xx *dev, u32 gpio_bit, u8* gpio_val); +int cx231xx_set_gpio_value(struct cx231xx *dev, int pin_number, int pin_value); +int cx231xx_set_gpio_direction(struct cx231xx *dev, int pin_number, int pin_value); + +int cx231xx_gpio_i2c_start(struct cx231xx *dev); +int cx231xx_gpio_i2c_end(struct cx231xx *dev); +int cx231xx_gpio_i2c_write_byte(struct cx231xx *dev, u8 data); +int cx231xx_gpio_i2c_read_byte(struct cx231xx *dev, u8 *buf); +int cx231xx_gpio_i2c_read_ack(struct cx231xx *dev); +int cx231xx_gpio_i2c_write_ack(struct cx231xx *dev); +int cx231xx_gpio_i2c_write_nak(struct cx231xx *dev); + +int cx231xx_gpio_i2c_read(struct cx231xx *dev, u8 dev_addr, u8 *buf ,u8 len); +int cx231xx_gpio_i2c_write(struct cx231xx *dev, u8 dev_addr, u8 *buf ,u8 len); + +/* audio related functions */ +int cx231xx_set_audio_decoder_input(struct cx231xx *dev, enum AUDIO_INPUT audio_input); + +int cx231xx_capture_start(struct cx231xx *dev, int start, u8 media_type); +int cx231xx_resolution_set(struct cx231xx *dev); +int cx231xx_set_video_alternate(struct cx231xx *dev); +int cx231xx_set_alt_setting(struct cx231xx *dev, u8 index, u8 alt); +int cx231xx_init_isoc(struct cx231xx *dev, int max_packets, + int num_bufs, int max_pkt_size, + int (*isoc_copy) (struct cx231xx *dev, struct urb *urb)); +void cx231xx_uninit_isoc(struct cx231xx *dev); +int cx231xx_set_mode(struct cx231xx *dev, enum cx231xx_mode set_mode); +int cx231xx_gpio_set(struct cx231xx *dev, struct cx231xx_reg_seq *gpio); + +/* Device list functions */ +void cx231xx_release_resources(struct cx231xx *dev); +void cx231xx_release_analog_resources(struct cx231xx *dev); +int cx231xx_register_analog_devices(struct cx231xx *dev); +void cx231xx_remove_from_devlist(struct cx231xx *dev); +void cx231xx_add_into_devlist(struct cx231xx *dev); +struct cx231xx *cx231xx_get_device(int minor, + enum v4l2_buf_type *fh_type, int *has_radio); +void cx231xx_init_extension(struct cx231xx *dev); +void cx231xx_close_extension(struct cx231xx *dev); + +/* hardware init functions */ +int cx231xx_dev_init(struct cx231xx *dev); +void cx231xx_dev_uninit(struct cx231xx *dev); +void cx231xx_config_i2c(struct cx231xx *dev); +int cx231xx_config(struct cx231xx *dev); + +/* Stream control functions */ +int cx231xx_start_stream(struct cx231xx *dev, u32 ep_mask); +int cx231xx_stop_stream(struct cx231xx *dev, u32 ep_mask); + +int cx231xx_initialize_stream_xfer(struct cx231xx *dev, u32 media_type); + +/* Power control functions */ +int cx231xx_set_power_mode(struct cx231xx *dev, AV_MODE mode); +int cx231xx_power_suspend(struct cx231xx *dev); + +/* chip specific control functions */ +int cx231xx_init_ctrl_pin_status(struct cx231xx *dev); +int cx231xx_set_agc_analog_digital_mux_select(struct cx231xx *dev, u8 analog_or_digital); +int cx231xx_enable_i2c_for_tuner(struct cx231xx *dev, u8 I2CIndex); + +/* video audio decoder related functions */ +void video_mux(struct cx231xx *dev, int index); +int cx231xx_set_video_input_mux(struct cx231xx *dev, u8 input); +int cx231xx_set_decoder_video_input(struct cx231xx *dev, u8 pin_type, u8 input); +int cx231xx_do_mode_ctrl_overrides(struct cx231xx *dev); +int cx231xx_set_audio_input(struct cx231xx *dev, u8 input); +void get_scale(struct cx231xx *dev, + unsigned int width, unsigned int height, + unsigned int *hscale, unsigned int *vscale); + +/* Provided by cx231xx-video.c */ +int cx231xx_register_extension(struct cx231xx_ops *dev); +void cx231xx_unregister_extension(struct cx231xx_ops *dev); +void cx231xx_init_extension(struct cx231xx *dev); +void cx231xx_close_extension(struct cx231xx *dev); + +/* Provided by cx231xx-cards.c */ +extern void cx231xx_pre_card_setup(struct cx231xx *dev); +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_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 */ +int cx231xx_ir_init(struct cx231xx *dev); +int cx231xx_ir_fini(struct cx231xx *dev); + +/* printk macros */ + +#define cx231xx_err(fmt, arg...) do {\ + printk(KERN_ERR fmt , ##arg); } while (0) + +#define cx231xx_errdev(fmt, arg...) do {\ + printk(KERN_ERR "%s: "fmt,\ + dev->name , ##arg); } while (0) + +#define cx231xx_info(fmt, arg...) do {\ + printk(KERN_INFO "%s: "fmt,\ + dev->name , ##arg); } while (0) +#define cx231xx_warn(fmt, arg...) do {\ + printk(KERN_WARNING "%s: "fmt,\ + dev->name , ##arg); } while (0) + + +static inline unsigned int norm_maxw(struct cx231xx *dev) +{ + if (dev->board.max_range_640_480) + return 640; + else + return 720; +} + +static inline unsigned int norm_maxh(struct cx231xx *dev) +{ + if (dev->board.max_range_640_480) + return 480; + else + return (dev->norm & V4L2_STD_625_50) ? 576 : 480; +} +#endif -- cgit v1.2.3 From 92ce95e9f4fce5fb4deea9cd33e0723190d93498 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 3 Mar 2009 06:14:34 -0300 Subject: cx231xx: CodingStyle automatic fixes with Lindent From: Mauro Carvalho Chehab Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/cx231xx/cx231xx-audio.c | 302 +- linux/drivers/media/video/cx231xx/cx231xx-avcore.c | 4531 ++++++++++++-------- linux/drivers/media/video/cx231xx/cx231xx-cards.c | 997 +++-- .../drivers/media/video/cx231xx/cx231xx-conf-reg.h | 414 +- linux/drivers/media/video/cx231xx/cx231xx-core.c | 1209 +++--- linux/drivers/media/video/cx231xx/cx231xx-dvb.c | 290 +- linux/drivers/media/video/cx231xx/cx231xx-i2c.c | 573 +-- linux/drivers/media/video/cx231xx/cx231xx-input.c | 30 +- linux/drivers/media/video/cx231xx/cx231xx-reg.h | 2169 +++++----- linux/drivers/media/video/cx231xx/cx231xx-vbi.c | 577 +-- linux/drivers/media/video/cx231xx/cx231xx-vbi.h | 28 +- linux/drivers/media/video/cx231xx/cx231xx-video.c | 1894 ++++---- linux/drivers/media/video/cx231xx/cx231xx.h | 540 ++- 13 files changed, 7231 insertions(+), 6323 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/cx231xx/cx231xx-audio.c b/linux/drivers/media/video/cx231xx/cx231xx-audio.c index add97c701..b6db68a5c 100644 --- a/linux/drivers/media/video/cx231xx/cx231xx-audio.c +++ b/linux/drivers/media/video/cx231xx/cx231xx-audio.c @@ -57,24 +57,23 @@ static int cx231xx_isoc_audio_deinit(struct cx231xx *dev) { int i; - dprintk("Stopping isoc\n"); - + dprintk("Stopping isoc\n"); for (i = 0; i < CX231XX_AUDIO_BUFS; i++) { - if(dev->adev.urb[i]) { - if (!irqs_disabled()) - usb_kill_urb(dev->adev.urb[i]); - else - usb_unlink_urb(dev->adev.urb[i]); + if (dev->adev.urb[i]) { + if (!irqs_disabled()) + usb_kill_urb(dev->adev.urb[i]); + else + usb_unlink_urb(dev->adev.urb[i]); - usb_free_urb(dev->adev.urb[i]); - dev->adev.urb[i] = NULL; + usb_free_urb(dev->adev.urb[i]); + dev->adev.urb[i] = NULL; - kfree(dev->adev.transfer_buffer[i]); - dev->adev.transfer_buffer[i] = NULL; + kfree(dev->adev.transfer_buffer[i]); + dev->adev.transfer_buffer[i] = NULL; - } - } + } + } return 0; } @@ -85,35 +84,35 @@ static void cx231xx_audio_isocirq(struct urb *urb, struct pt_regs *regs) static void cx231xx_audio_isocirq(struct urb *urb) #endif { - struct cx231xx *dev = urb->context; - int i; - unsigned int oldptr; + struct cx231xx *dev = urb->context; + int i; + unsigned int oldptr; #ifdef NO_PCM_LOCK - unsigned long flags; + unsigned long flags; #endif - int period_elapsed = 0; - int status; - unsigned char *cp; - unsigned int stride; + int period_elapsed = 0; + int status; + unsigned char *cp; + unsigned int stride; #if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 16) snd_pcm_substream_t *substream; - snd_pcm_runtime_t *runtime; + snd_pcm_runtime_t *runtime; #else struct snd_pcm_substream *substream; - struct snd_pcm_runtime *runtime; + struct snd_pcm_runtime *runtime; #endif - switch (urb->status) { - case 0: /* success */ - case -ETIMEDOUT: /* NAK */ - break; - case -ECONNRESET: /* kill */ - case -ENOENT: - case -ESHUTDOWN: - return; - default: /* error */ - dprintk("urb completition error %d.\n", urb->status); - break; + switch (urb->status) { + case 0: /* success */ + case -ETIMEDOUT: /* NAK */ + break; + case -ECONNRESET: /* kill */ + case -ENOENT: + case -ESHUTDOWN: + return; + default: /* error */ + dprintk("urb completition error %d.\n", urb->status); + break; } if (dev->adev.capture_pcm_substream) { @@ -163,7 +162,6 @@ static void cx231xx_audio_isocirq(struct urb *urb) runtime->period_size; period_elapsed = 1; } - #ifdef NO_PCM_LOCK spin_unlock_irqrestore(&dev->adev.slock, flags); #else @@ -178,19 +176,19 @@ static void cx231xx_audio_isocirq(struct urb *urb) status = usb_submit_urb(urb, GFP_ATOMIC); if (status < 0) { cx231xx_errdev("resubmit of audio urb failed (error=%i)\n", - status); + status); } return; } static int cx231xx_init_audio_isoc(struct cx231xx *dev) { - int i, errCode; - int sb_size; - - cx231xx_info("%s: Starting AUDIO transfers\n",__func__); + int i, errCode; + int sb_size; + + cx231xx_info("%s: Starting AUDIO transfers\n", __func__); - sb_size = CX231XX_NUM_AUDIO_PACKETS * dev->adev.max_pkt_size; + sb_size = CX231XX_NUM_AUDIO_PACKETS * dev->adev.max_pkt_size; for (i = 0; i < CX231XX_AUDIO_BUFS; i++) { struct urb *urb; @@ -213,7 +211,8 @@ static int cx231xx_init_audio_isoc(struct cx231xx *dev) urb->dev = dev->udev; urb->context = dev; - urb->pipe = usb_rcvisocpipe(dev->udev, dev->adev.end_point_addr); + urb->pipe = + usb_rcvisocpipe(dev->udev, dev->adev.end_point_addr); urb->transfer_flags = URB_ISO_ASAP; urb->transfer_buffer = dev->adev.transfer_buffer[i]; urb->interval = 1; @@ -222,13 +221,12 @@ static int cx231xx_init_audio_isoc(struct cx231xx *dev) urb->transfer_buffer_length = sb_size; for (j = k = 0; j < CX231XX_NUM_AUDIO_PACKETS; - j++, k += dev->adev.max_pkt_size) { + j++, k += dev->adev.max_pkt_size) { urb->iso_frame_desc[j].offset = k; - urb->iso_frame_desc[j].length = - dev->adev.max_pkt_size; + urb->iso_frame_desc[j].length = dev->adev.max_pkt_size; } dev->adev.urb[i] = urb; - } + } for (i = 0; i < CX231XX_AUDIO_BUFS; i++) { errCode = usb_submit_urb(dev->adev.urb[i], GFP_ATOMIC); @@ -243,11 +241,11 @@ static int cx231xx_init_audio_isoc(struct cx231xx *dev) static int cx231xx_cmd(struct cx231xx *dev, int cmd, int arg) { - dprintk("%s transfer\n", (dev->adev.capture_stream == STREAM_ON)? - "stop" : "start"); + dprintk("%s transfer\n", (dev->adev.capture_stream == STREAM_ON) ? + "stop" : "start"); switch (cmd) { - case CX231XX_CAPTURE_STREAM_EN: + case CX231XX_CAPTURE_STREAM_EN: if (dev->adev.capture_stream == STREAM_OFF && arg == 1) { dev->adev.capture_stream = STREAM_ON; cx231xx_init_audio_isoc(dev); @@ -255,8 +253,8 @@ static int cx231xx_cmd(struct cx231xx *dev, int cmd, int arg) dev->adev.capture_stream = STREAM_OFF; cx231xx_isoc_audio_deinit(dev); } else { - cx231xx_errdev( "An underrun very likely occurred. " - "Ignoring it.\n"); + cx231xx_errdev("An underrun very likely occurred. " + "Ignoring it.\n"); } return 0; default: @@ -265,15 +263,14 @@ static int cx231xx_cmd(struct cx231xx *dev, int cmd, int arg) } #if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 16) -static int snd_pcm_alloc_vmalloc_buffer(snd_pcm_substream_t *subs, - size_t size) +static int snd_pcm_alloc_vmalloc_buffer(snd_pcm_substream_t * subs, size_t size) #else static int snd_pcm_alloc_vmalloc_buffer(struct snd_pcm_substream *subs, size_t size) #endif { #if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 16) - snd_pcm_runtime_t *runtime = subs->runtime; + snd_pcm_runtime_t *runtime = subs->runtime; #else struct snd_pcm_runtime *runtime = subs->runtime; #endif @@ -300,9 +297,8 @@ static snd_pcm_hardware_t snd_cx231xx_hw_capture = { static struct snd_pcm_hardware snd_cx231xx_hw_capture = { #endif .info = SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_MMAP_VALID, + SNDRV_PCM_INFO_MMAP | + SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_MMAP_VALID, .formats = SNDRV_PCM_FMTBIT_S16_LE, @@ -313,14 +309,14 @@ static struct snd_pcm_hardware snd_cx231xx_hw_capture = { .channels_min = 2, .channels_max = 2, .buffer_bytes_max = 62720 * 8, /* just about the value in usbaudio.c */ - .period_bytes_min = 64, /* 12544/2, */ + .period_bytes_min = 64, /* 12544/2, */ .period_bytes_max = 12544, .periods_min = 2, - .periods_max = 98, /* 12544, */ + .periods_max = 98, /* 12544, */ }; #if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 16) -static int snd_cx231xx_capture_open(snd_pcm_substream_t *substream) +static int snd_cx231xx_capture_open(snd_pcm_substream_t * substream) #else static int snd_cx231xx_capture_open(struct snd_pcm_substream *substream) #endif @@ -337,29 +333,29 @@ static int snd_cx231xx_capture_open(struct snd_pcm_substream *substream) if (!dev) { cx231xx_errdev("BUG: cx231xx can't find device struct." - " Can't proceed with open\n"); + " Can't proceed with open\n"); return -ENODEV; } /* Sets volume, mute, etc */ dev->mute = 0; - /* set alternate setting for audio interface */ - ret = cx231xx_set_alt_setting(dev, INDEX_AUDIO, 1); /* 1 - 48000 samples per sec */ - if (ret < 0) { - cx231xx_errdev("failed to set alternate setting !\n"); + /* set alternate setting for audio interface */ + ret = cx231xx_set_alt_setting(dev, INDEX_AUDIO, 1); /* 1 - 48000 samples per sec */ + if (ret < 0) { + cx231xx_errdev("failed to set alternate setting !\n"); - return ret; - } + return ret; + } - /* inform hardware to start streaming */ - ret = cx231xx_capture_start(dev, 1, Audio); + /* inform hardware to start streaming */ + ret = cx231xx_capture_start(dev, 1, Audio); - runtime->hw = snd_cx231xx_hw_capture; + runtime->hw = snd_cx231xx_hw_capture; - mutex_lock(&dev->lock); + mutex_lock(&dev->lock); dev->adev.users++; - mutex_unlock(&dev->lock); + mutex_unlock(&dev->lock); snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS); dev->adev.capture_pcm_substream = substream; @@ -369,31 +365,30 @@ static int snd_cx231xx_capture_open(struct snd_pcm_substream *substream) } #if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 16) -static int snd_cx231xx_pcm_close(snd_pcm_substream_t *substream) +static int snd_cx231xx_pcm_close(snd_pcm_substream_t * substream) #else static int snd_cx231xx_pcm_close(struct snd_pcm_substream *substream) #endif -{ - int ret; +{ + int ret; struct cx231xx *dev = snd_pcm_substream_chip(substream); - dprintk("closing device\n"); - /* set alternate setting for audio interface */ - ret = cx231xx_set_alt_setting(dev, INDEX_AUDIO, 0); /* 1 - 48000 samples per sec */ - if (ret < 0) { - cx231xx_errdev("failed to set alternate setting !\n"); + /* set alternate setting for audio interface */ + ret = cx231xx_set_alt_setting(dev, INDEX_AUDIO, 0); /* 1 - 48000 samples per sec */ + if (ret < 0) { + cx231xx_errdev("failed to set alternate setting !\n"); - return ret; - } + return ret; + } - /* inform hardware to start streaming */ - ret = cx231xx_capture_start(dev, 0, Audio); + /* inform hardware to start streaming */ + ret = cx231xx_capture_start(dev, 0, Audio); dev->mute = 1; mutex_lock(&dev->lock); - dev->adev.users--; + dev->adev.users--; mutex_unlock(&dev->lock); if (dev->adev.users == 0 && dev->adev.shutdown == 1) { @@ -407,11 +402,11 @@ static int snd_cx231xx_pcm_close(struct snd_pcm_substream *substream) } #if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 16) -static int snd_cx231xx_hw_capture_params(snd_pcm_substream_t *substream, - snd_pcm_hw_params_t *hw_params) +static int snd_cx231xx_hw_capture_params(snd_pcm_substream_t * substream, + snd_pcm_hw_params_t * hw_params) #else static int snd_cx231xx_hw_capture_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) + struct snd_pcm_hw_params *hw_params) #endif { unsigned int channels, rate, format; @@ -420,7 +415,7 @@ static int snd_cx231xx_hw_capture_params(struct snd_pcm_substream *substream, dprintk("Setting capture parameters\n"); ret = snd_pcm_alloc_vmalloc_buffer(substream, - params_buffer_bytes(hw_params)); + params_buffer_bytes(hw_params)); format = params_format(hw_params); rate = params_rate(hw_params); channels = params_channels(hw_params); @@ -432,7 +427,7 @@ static int snd_cx231xx_hw_capture_params(struct snd_pcm_substream *substream, } #if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 16) -static int snd_cx231xx_hw_capture_free(snd_pcm_substream_t *substream) +static int snd_cx231xx_hw_capture_free(snd_pcm_substream_t * substream) #else static int snd_cx231xx_hw_capture_free(struct snd_pcm_substream *substream) #endif @@ -448,7 +443,7 @@ static int snd_cx231xx_hw_capture_free(struct snd_pcm_substream *substream) } #if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 16) -static int snd_cx231xx_prepare(snd_pcm_substream_t *substream) +static int snd_cx231xx_prepare(snd_pcm_substream_t * substream) #else static int snd_cx231xx_prepare(struct snd_pcm_substream *substream) #endif @@ -457,60 +452,60 @@ static int snd_cx231xx_prepare(struct snd_pcm_substream *substream) } #if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 16) -static int snd_cx231xx_capture_trigger(snd_pcm_substream_t *substream, int cmd) +static int snd_cx231xx_capture_trigger(snd_pcm_substream_t * substream, int cmd) #else static int snd_cx231xx_capture_trigger(struct snd_pcm_substream *substream, - int cmd) + int cmd) #endif { struct cx231xx *dev = snd_pcm_substream_chip(substream); - int retval; - + int retval; + + dprintk("Should %s capture\n", (cmd == SNDRV_PCM_TRIGGER_START) ? + "start" : "stop"); - dprintk("Should %s capture\n", (cmd == SNDRV_PCM_TRIGGER_START)? - "start": "stop"); - - spin_lock(&dev->adev.slock); + spin_lock(&dev->adev.slock); switch (cmd) { case SNDRV_PCM_TRIGGER_START: - cx231xx_cmd(dev, CX231XX_CAPTURE_STREAM_EN, CX231XX_START_AUDIO); + cx231xx_cmd(dev, CX231XX_CAPTURE_STREAM_EN, + CX231XX_START_AUDIO); retval = 0; break; case SNDRV_PCM_TRIGGER_STOP: - cx231xx_cmd(dev, CX231XX_CAPTURE_STREAM_EN, CX231XX_STOP_AUDIO); + cx231xx_cmd(dev, CX231XX_CAPTURE_STREAM_EN, CX231XX_STOP_AUDIO); retval = 0; - break; + break; default: retval = -EINVAL; } - spin_unlock(&dev->adev.slock); + spin_unlock(&dev->adev.slock); return retval; } #if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 16) static snd_pcm_uframes_t snd_cx231xx_capture_pointer(snd_pcm_substream_t - *substream) + * substream) #else static snd_pcm_uframes_t snd_cx231xx_capture_pointer(struct snd_pcm_substream - *substream) + *substream) #endif { struct cx231xx *dev; - unsigned long flags; + unsigned long flags; snd_pcm_uframes_t hwptr_done; - + dev = snd_pcm_substream_chip(substream); - spin_lock_irqsave(&dev->adev.slock, flags); + spin_lock_irqsave(&dev->adev.slock, flags); hwptr_done = dev->adev.hwptr_done_capture; - spin_unlock_irqrestore(&dev->adev.slock, flags); + spin_unlock_irqrestore(&dev->adev.slock, flags); return hwptr_done; } #if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 16) -static struct page *snd_pcm_get_vmalloc_page(snd_pcm_substream_t *subs, +static struct page *snd_pcm_get_vmalloc_page(snd_pcm_substream_t * subs, unsigned long offset) #else static struct page *snd_pcm_get_vmalloc_page(struct snd_pcm_substream *subs, @@ -527,31 +522,31 @@ static snd_pcm_ops_t snd_cx231xx_pcm_capture = { #else static struct snd_pcm_ops snd_cx231xx_pcm_capture = { #endif - .open = snd_cx231xx_capture_open, - .close = snd_cx231xx_pcm_close, - .ioctl = snd_pcm_lib_ioctl, + .open = snd_cx231xx_capture_open, + .close = snd_cx231xx_pcm_close, + .ioctl = snd_pcm_lib_ioctl, .hw_params = snd_cx231xx_hw_capture_params, - .hw_free = snd_cx231xx_hw_capture_free, - .prepare = snd_cx231xx_prepare, - .trigger = snd_cx231xx_capture_trigger, - .pointer = snd_cx231xx_capture_pointer, - .page = snd_pcm_get_vmalloc_page, + .hw_free = snd_cx231xx_hw_capture_free, + .prepare = snd_cx231xx_prepare, + .trigger = snd_cx231xx_capture_trigger, + .pointer = snd_cx231xx_capture_pointer, + .page = snd_pcm_get_vmalloc_page, }; static int cx231xx_audio_init(struct cx231xx *dev) { struct cx231xx_audio *adev = &dev->adev; #if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 16) - snd_pcm_t *pcm; - snd_card_t *card; + snd_pcm_t *pcm; + snd_card_t *card; #else - struct snd_pcm *pcm; - struct snd_card *card; + struct snd_pcm *pcm; + struct snd_card *card; #endif - static int devnr; - int err; - struct usb_interface *uif; - int i, isoc_pipe = 0; + static int devnr; + int err; + struct usb_interface *uif; + int i, isoc_pipe = 0; if (dev->has_alsa_audio != 1) { /* This device does not support the extension (in this case @@ -561,8 +556,8 @@ static int cx231xx_audio_init(struct cx231xx *dev) } cx231xx_info("cx231xx-audio.c: probing for cx231xx " - "non standard usbaudio\n"); - + "non standard usbaudio\n"); + card = snd_card_new(index[devnr], "Cx231xx Audio", THIS_MODULE, 0); if (card == NULL) { return -ENOMEM; @@ -575,7 +570,8 @@ static int cx231xx_audio_init(struct cx231xx *dev) return err; } - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_cx231xx_pcm_capture); + snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, + &snd_cx231xx_pcm_capture); pcm->info_flags = 0; pcm->private_data = dev; strcpy(pcm->name, "Conexant cx231xx Capture"); @@ -591,29 +587,35 @@ static int cx231xx_audio_init(struct cx231xx *dev) adev->sndcard = card; adev->udev = dev->udev; - /* compute alternate max packet sizes for Audio */ - uif = dev->udev->actconfig->interface[dev->current_pcb_config.hs_config_info[0].interface_info.audio_index+1]; + /* compute alternate max packet sizes for Audio */ + uif = + dev->udev->actconfig->interface[dev->current_pcb_config. + hs_config_info[0].interface_info. + audio_index + 1]; - adev->end_point_addr = le16_to_cpu(uif->altsetting[0].endpoint[isoc_pipe].desc.bEndpointAddress); + adev->end_point_addr = + le16_to_cpu(uif->altsetting[0].endpoint[isoc_pipe].desc. + bEndpointAddress); - adev->num_alt = uif->num_altsetting; - cx231xx_info(": EndPoint Addr 0x%x, Alternate settings: %i\n", adev->end_point_addr, - adev->num_alt); - adev->alt_max_pkt_size = kmalloc(32 * adev->num_alt, GFP_KERNEL); + adev->num_alt = uif->num_altsetting; + cx231xx_info(": EndPoint Addr 0x%x, Alternate settings: %i\n", + adev->end_point_addr, adev->num_alt); + adev->alt_max_pkt_size = kmalloc(32 * adev->num_alt, GFP_KERNEL); - if (adev->alt_max_pkt_size == NULL) { - cx231xx_errdev("out of memory!\n"); - return -ENOMEM; - } + if (adev->alt_max_pkt_size == NULL) { + cx231xx_errdev("out of memory!\n"); + return -ENOMEM; + } - for (i = 0; i < adev->num_alt ; i++) { - u16 tmp = le16_to_cpu(uif->altsetting[i].endpoint[isoc_pipe].desc. - wMaxPacketSize); - adev->alt_max_pkt_size[i] = - (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1); - cx231xx_info("Alternate setting %i, max size= %i\n", i, - adev->alt_max_pkt_size[i]); - } + for (i = 0; i < adev->num_alt; i++) { + u16 tmp = + le16_to_cpu(uif->altsetting[i].endpoint[isoc_pipe].desc. + wMaxPacketSize); + adev->alt_max_pkt_size[i] = + (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1); + cx231xx_info("Alternate setting %i, max size= %i\n", i, + adev->alt_max_pkt_size[i]); + } return 0; } @@ -632,7 +634,7 @@ static int cx231xx_audio_fini(struct cx231xx *dev) if (dev->adev.sndcard) { snd_card_free(dev->adev.sndcard); - kfree(dev->adev.alt_max_pkt_size); + kfree(dev->adev.alt_max_pkt_size); dev->adev.sndcard = NULL; } @@ -640,7 +642,7 @@ static int cx231xx_audio_fini(struct cx231xx *dev) } static struct cx231xx_ops audio_ops = { - .id = CX231XX_AUDIO, + .id = CX231XX_AUDIO, .name = "Cx231xx Audio Extension", .init = cx231xx_audio_init, .fini = cx231xx_audio_fini, diff --git a/linux/drivers/media/video/cx231xx/cx231xx-avcore.c b/linux/drivers/media/video/cx231xx/cx231xx-avcore.c index 833967f46..3c09b9473 100644 --- a/linux/drivers/media/video/cx231xx/cx231xx-avcore.c +++ b/linux/drivers/media/video/cx231xx/cx231xx-avcore.c @@ -1,7 +1,7 @@ /* cx231xx_avcore.c - driver for Conexant Cx23100/101/102 USB video capture devices - Copyright (C) 2008 + Copyright (C) 2008 This program contains the specific code to control the avdecoder chip and other related usb control functions for cx231xx based chipset. @@ -38,115 +38,180 @@ #include "cx231xx.h" - /************************************************************************************* * C O L I B R I - B L O C K C O N T R O L functions * *************************************************************************************/ int cx231xx_colibri_init_super_block(struct cx231xx *dev, u32 ref_count) { - int status = 0; - u8 temp = 0; - u32 colibri_power_status = 0; - int i = 0; - - /* super block initialize */ - temp = (u8)(ref_count & 0xff); - status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, SUP_BLK_TUNE2, 2, temp, 1); - - status = cx231xx_read_i2c_data(dev, Colibri_DEVICE_ADDRESS, SUP_BLK_TUNE2, 2, &colibri_power_status, 1); - - temp = (u8)((ref_count & 0x300) >> 8); - temp |= 0x40; - status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, SUP_BLK_TUNE1, 2, temp, 1); - status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, SUP_BLK_PLL2, 2, 0x0f, 1); - - /* enable pll */ - while(colibri_power_status != 0x18) - { - status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, SUP_BLK_PWRDN, 2, 0x18, 1); - status = cx231xx_read_i2c_data(dev, Colibri_DEVICE_ADDRESS, SUP_BLK_PWRDN, 2, &colibri_power_status, 1); - colibri_power_status &= 0xff; - if(status < 0) { - cx231xx_info(": Init Super Block failed in sending/receiving cmds\n"); - break; - } - i++; - if( i == 10) { - cx231xx_info(": Init Super Block force break in loop !!!!\n"); - status = -1; - break; - } - } - - if(status < 0 ) - return status; - - /* start tuning filter */ - status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, SUP_BLK_TUNE3, 2, 0x40, 1); - msleep(5); - - /* exit tuning */ - status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, SUP_BLK_TUNE3, 2, 0x00, 1); - - return status; + int status = 0; + u8 temp = 0; + u32 colibri_power_status = 0; + int i = 0; + + /* super block initialize */ + temp = (u8) (ref_count & 0xff); + status = + cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, SUP_BLK_TUNE2, + 2, temp, 1); + + status = + cx231xx_read_i2c_data(dev, Colibri_DEVICE_ADDRESS, SUP_BLK_TUNE2, 2, + &colibri_power_status, 1); + + temp = (u8) ((ref_count & 0x300) >> 8); + temp |= 0x40; + status = + cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, SUP_BLK_TUNE1, + 2, temp, 1); + status = + cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, SUP_BLK_PLL2, 2, + 0x0f, 1); + + /* enable pll */ + while (colibri_power_status != 0x18) { + status = + cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, + SUP_BLK_PWRDN, 2, 0x18, 1); + status = + cx231xx_read_i2c_data(dev, Colibri_DEVICE_ADDRESS, + SUP_BLK_PWRDN, 2, + &colibri_power_status, 1); + colibri_power_status &= 0xff; + if (status < 0) { + cx231xx_info + (": Init Super Block failed in sending/receiving cmds\n"); + break; + } + i++; + if (i == 10) { + cx231xx_info + (": Init Super Block force break in loop !!!!\n"); + status = -1; + break; + } + } + + if (status < 0) + return status; + + /* start tuning filter */ + status = + cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, SUP_BLK_TUNE3, + 2, 0x40, 1); + msleep(5); + + /* exit tuning */ + status = + cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, SUP_BLK_TUNE3, + 2, 0x00, 1); + + return status; } int cx231xx_colibri_init_channels(struct cx231xx *dev) { - int status = 0; - - /* power up all 3 channels, clear pd_buffer */ - status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_PWRDN_CLAMP_CH1, 2, 0x00, 1); - status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_PWRDN_CLAMP_CH2, 2, 0x00, 1); - status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_PWRDN_CLAMP_CH3, 2, 0x00, 1); - - /* Enable quantizer calibration */ - status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_COM_QUANT, 2, 0x02, 1); - - /* channel initialize, force modulator (fb) reset */ - status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_FB_FRCRST_CH1, 2, 0x17, 1); - status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_FB_FRCRST_CH2, 2, 0x17, 1); - status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_FB_FRCRST_CH3, 2, 0x17, 1); - - /* start quantilizer calibration */ - status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_CAL_ATEST_CH1, 2, 0x10, 1); - status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_CAL_ATEST_CH2, 2, 0x10, 1); - status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_CAL_ATEST_CH3, 2, 0x10, 1); - msleep(5); - - /* exit modulator (fb) reset */ - status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_FB_FRCRST_CH1, 2, 0x07, 1); - status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_FB_FRCRST_CH2, 2, 0x07, 1); - status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_FB_FRCRST_CH3, 2, 0x07, 1); - - /* enable the pre_clamp in each channel for single-ended input */ - status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_NTF_PRECLMP_EN_CH1, 2, 0xf0, 1); - status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_NTF_PRECLMP_EN_CH2, 2, 0xf0, 1); - status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_NTF_PRECLMP_EN_CH3, 2, 0xf0, 1); - - /* use diode instead of resistor, so set term_en to 0, res_en to 0 */ - status = cx231xx_reg_mask_write(dev, Colibri_DEVICE_ADDRESS, 8, ADC_QGAIN_RES_TRM_CH1, 3, 7, 0x00); - status = cx231xx_reg_mask_write(dev, Colibri_DEVICE_ADDRESS, 8, ADC_QGAIN_RES_TRM_CH2, 3, 7, 0x00); - status = cx231xx_reg_mask_write(dev, Colibri_DEVICE_ADDRESS, 8, ADC_QGAIN_RES_TRM_CH3, 3, 7, 0x00); - - /* dynamic element matching off */ - status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_DCSERVO_DEM_CH1, 2, 0x03, 1); - status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_DCSERVO_DEM_CH2, 2, 0x03, 1); - status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_DCSERVO_DEM_CH3, 2, 0x03, 1); - - return status; + int status = 0; + + /* power up all 3 channels, clear pd_buffer */ + status = + cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, + ADC_PWRDN_CLAMP_CH1, 2, 0x00, 1); + status = + cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, + ADC_PWRDN_CLAMP_CH2, 2, 0x00, 1); + status = + cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, + ADC_PWRDN_CLAMP_CH3, 2, 0x00, 1); + + /* Enable quantizer calibration */ + status = + cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_COM_QUANT, + 2, 0x02, 1); + + /* channel initialize, force modulator (fb) reset */ + status = + cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, + ADC_FB_FRCRST_CH1, 2, 0x17, 1); + status = + cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, + ADC_FB_FRCRST_CH2, 2, 0x17, 1); + status = + cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, + ADC_FB_FRCRST_CH3, 2, 0x17, 1); + + /* start quantilizer calibration */ + status = + cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, + ADC_CAL_ATEST_CH1, 2, 0x10, 1); + status = + cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, + ADC_CAL_ATEST_CH2, 2, 0x10, 1); + status = + cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, + ADC_CAL_ATEST_CH3, 2, 0x10, 1); + msleep(5); + + /* exit modulator (fb) reset */ + status = + cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, + ADC_FB_FRCRST_CH1, 2, 0x07, 1); + status = + cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, + ADC_FB_FRCRST_CH2, 2, 0x07, 1); + status = + cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, + ADC_FB_FRCRST_CH3, 2, 0x07, 1); + + /* enable the pre_clamp in each channel for single-ended input */ + status = + cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, + ADC_NTF_PRECLMP_EN_CH1, 2, 0xf0, 1); + status = + cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, + ADC_NTF_PRECLMP_EN_CH2, 2, 0xf0, 1); + status = + cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, + ADC_NTF_PRECLMP_EN_CH3, 2, 0xf0, 1); + + /* use diode instead of resistor, so set term_en to 0, res_en to 0 */ + status = + cx231xx_reg_mask_write(dev, Colibri_DEVICE_ADDRESS, 8, + ADC_QGAIN_RES_TRM_CH1, 3, 7, 0x00); + status = + cx231xx_reg_mask_write(dev, Colibri_DEVICE_ADDRESS, 8, + ADC_QGAIN_RES_TRM_CH2, 3, 7, 0x00); + status = + cx231xx_reg_mask_write(dev, Colibri_DEVICE_ADDRESS, 8, + ADC_QGAIN_RES_TRM_CH3, 3, 7, 0x00); + + /* dynamic element matching off */ + status = + cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, + ADC_DCSERVO_DEM_CH1, 2, 0x03, 1); + status = + cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, + ADC_DCSERVO_DEM_CH2, 2, 0x03, 1); + status = + cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, + ADC_DCSERVO_DEM_CH3, 2, 0x03, 1); + + return status; } int cx231xx_colibri_setup_AFE_for_baseband(struct cx231xx *dev) -{ - u32 c_value = 0; - int status = 0; +{ + u32 c_value = 0; + int status = 0; - status = cx231xx_read_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_PWRDN_CLAMP_CH2, 2, &c_value, 1); - c_value &= (~(0x50)); - status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_PWRDN_CLAMP_CH2, 2, c_value, 1); + status = + cx231xx_read_i2c_data(dev, Colibri_DEVICE_ADDRESS, + ADC_PWRDN_CLAMP_CH2, 2, &c_value, 1); + c_value &= (~(0x50)); + status = + cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, + ADC_PWRDN_CLAMP_CH2, 2, c_value, 1); - return status; + return status; } /* @@ -157,559 +222,802 @@ int cx231xx_colibri_setup_AFE_for_baseband(struct cx231xx *dev) */ int cx231xx_colibri_set_input_mux(struct cx231xx *dev, u32 input_mux) { - u8 ch1_setting = (u8)input_mux; - u8 ch2_setting = (u8)(input_mux >> 8); - u8 ch3_setting = (u8)(input_mux >> 16); - int status = 0; - u32 value = 0; - - if(ch1_setting != 0) - { - status = cx231xx_read_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_INPUT_CH1, 2, &value, 1); - value &= (!INPUT_SEL_MASK); - value |= (ch1_setting-1)<<4; - value &= 0xff; - status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_INPUT_CH1, 2, value, 1); - } - - if(ch2_setting != 0) - { - status = cx231xx_read_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_INPUT_CH2, 2, &value, 1); - value &= (!INPUT_SEL_MASK); - value |= (ch2_setting-1)<<4; - value &= 0xff; - status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_INPUT_CH2, 2, value, 1); - } - - /* For ch3_setting, the value to put in the register is 7 less than the input number */ - if(ch3_setting != 0) - { - status = cx231xx_read_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_INPUT_CH3, 2, &value, 1); - value &= (!INPUT_SEL_MASK); - value |= (ch3_setting-1)<<4; - value &= 0xff; - status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_INPUT_CH3, 2, value, 1); - } - - return status; + u8 ch1_setting = (u8) input_mux; + u8 ch2_setting = (u8) (input_mux >> 8); + u8 ch3_setting = (u8) (input_mux >> 16); + int status = 0; + u32 value = 0; + + if (ch1_setting != 0) { + status = + cx231xx_read_i2c_data(dev, Colibri_DEVICE_ADDRESS, + ADC_INPUT_CH1, 2, &value, 1); + value &= (!INPUT_SEL_MASK); + value |= (ch1_setting - 1) << 4; + value &= 0xff; + status = + cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, + ADC_INPUT_CH1, 2, value, 1); + } + + if (ch2_setting != 0) { + status = + cx231xx_read_i2c_data(dev, Colibri_DEVICE_ADDRESS, + ADC_INPUT_CH2, 2, &value, 1); + value &= (!INPUT_SEL_MASK); + value |= (ch2_setting - 1) << 4; + value &= 0xff; + status = + cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, + ADC_INPUT_CH2, 2, value, 1); + } + + /* For ch3_setting, the value to put in the register is 7 less than the input number */ + if (ch3_setting != 0) { + status = + cx231xx_read_i2c_data(dev, Colibri_DEVICE_ADDRESS, + ADC_INPUT_CH3, 2, &value, 1); + value &= (!INPUT_SEL_MASK); + value |= (ch3_setting - 1) << 4; + value &= 0xff; + status = + cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, + ADC_INPUT_CH3, 2, value, 1); + } + + return status; } int cx231xx_colibri_set_mode(struct cx231xx *dev, enum AFE_MODE mode) { - int status = 0; - - switch(mode) { - case AFE_MODE_LOW_IF: - /* SetupAFEforLowIF(); */ - break; - case AFE_MODE_BASEBAND: - status = cx231xx_colibri_setup_AFE_for_baseband(dev); - break; - case AFE_MODE_EU_HI_IF: - /* SetupAFEforEuHiIF(); */ - break; - case AFE_MODE_US_HI_IF: - /* SetupAFEforUsHiIF(); */ - break; - case AFE_MODE_JAPAN_HI_IF: - /* SetupAFEforJapanHiIF(); */ - break; - } - - if((mode != dev->colibri_mode) && (dev->video_input == CX231XX_VMUX_TELEVISION)) { - status = cx231xx_colibri_adjust_ref_count(dev, CX231XX_VMUX_TELEVISION); - } - - dev->colibri_mode = mode; - - return status; + int status = 0; + + switch (mode) { + case AFE_MODE_LOW_IF: + /* SetupAFEforLowIF(); */ + break; + case AFE_MODE_BASEBAND: + status = cx231xx_colibri_setup_AFE_for_baseband(dev); + break; + case AFE_MODE_EU_HI_IF: + /* SetupAFEforEuHiIF(); */ + break; + case AFE_MODE_US_HI_IF: + /* SetupAFEforUsHiIF(); */ + break; + case AFE_MODE_JAPAN_HI_IF: + /* SetupAFEforJapanHiIF(); */ + break; + } + + if ((mode != dev->colibri_mode) + && (dev->video_input == CX231XX_VMUX_TELEVISION)) { + status = + cx231xx_colibri_adjust_ref_count(dev, + CX231XX_VMUX_TELEVISION); + } + + dev->colibri_mode = mode; + + return status; } /* For power saving in the EVK */ int cx231xx_colibri_update_power_control(struct cx231xx *dev, AV_MODE avmode) { - u32 colibri_power_status = 0; - int status = 0; - - switch (dev->model) { - case CX231XX_BOARD_CNXT_RDE_250: - case CX231XX_BOARD_CNXT_RDU_250: - - if(avmode==POLARIS_AVMODE_ANALOGT_TV) - { - while(colibri_power_status != 0x18) { - status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, - SUP_BLK_PWRDN, 2, 0x18, 1); - status = cx231xx_read_i2c_data(dev, Colibri_DEVICE_ADDRESS, - SUP_BLK_PWRDN, 2, &colibri_power_status, 1); - if(status < 0 ) - break; - } - - status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, - ADC_PWRDN_CLAMP_CH1, 2, 0x00, 1); - status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, - ADC_PWRDN_CLAMP_CH2, 2, 0x00, 1); - status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, - ADC_PWRDN_CLAMP_CH3, 2, 0x00, 1); - } - else if(avmode==POLARIS_AVMODE_DIGITAL) { - status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, - ADC_PWRDN_CLAMP_CH1, 2, 0x70, 1); - status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, - ADC_PWRDN_CLAMP_CH2, 2, 0x70, 1); - status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, - ADC_PWRDN_CLAMP_CH3, 2, 0x70, 1); - - status = cx231xx_read_i2c_data(dev, Colibri_DEVICE_ADDRESS, - SUP_BLK_PWRDN, 2, &colibri_power_status, 1); - colibri_power_status |=0x07; - status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, - SUP_BLK_PWRDN, 2, colibri_power_status, 1); - } - else if(avmode==POLARIS_AVMODE_ENXTERNAL_AV) { - - while(colibri_power_status != 0x18) { - status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, - SUP_BLK_PWRDN, 2, 0x18, 1); - status = cx231xx_read_i2c_data(dev, Colibri_DEVICE_ADDRESS, - SUP_BLK_PWRDN, 2, &colibri_power_status, 1); - if(status < 0 ) - break; - } - - status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, - ADC_PWRDN_CLAMP_CH1, 2, 0x00, 1); - status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, - ADC_PWRDN_CLAMP_CH2, 2, 0x00, 1); - status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, - ADC_PWRDN_CLAMP_CH3, 2, 0x00, 1); - } - else { - cx231xx_info("Invalid AV mode input\n"); - status = -1; - } - break; - default: - if(avmode==POLARIS_AVMODE_ANALOGT_TV) - { - while(colibri_power_status != 0x18) { - status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, - SUP_BLK_PWRDN, 2, 0x18, 1); - status = cx231xx_read_i2c_data(dev, Colibri_DEVICE_ADDRESS, - SUP_BLK_PWRDN, 2, &colibri_power_status, 1); - if(status < 0 ) - break; - } - - status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, - ADC_PWRDN_CLAMP_CH1, 2, 0x40, 1); - status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, - ADC_PWRDN_CLAMP_CH2, 2, 0x40, 1); - status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, - ADC_PWRDN_CLAMP_CH3, 2, 0x00, 1); - } - else if(avmode==POLARIS_AVMODE_DIGITAL) { - status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, - ADC_PWRDN_CLAMP_CH1, 2, 0x70, 1); - status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, - ADC_PWRDN_CLAMP_CH2, 2, 0x70, 1); - status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, - ADC_PWRDN_CLAMP_CH3, 2, 0x70, 1); - - status = cx231xx_read_i2c_data(dev, Colibri_DEVICE_ADDRESS, - SUP_BLK_PWRDN, 2, &colibri_power_status, 1); - colibri_power_status |=0x07; - status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, - SUP_BLK_PWRDN, 2, colibri_power_status, 1); - } - else if(avmode==POLARIS_AVMODE_ENXTERNAL_AV) { - while(colibri_power_status != 0x18) { - status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, - SUP_BLK_PWRDN, 2, 0x18, 1); - status = cx231xx_read_i2c_data(dev, Colibri_DEVICE_ADDRESS, - SUP_BLK_PWRDN, 2, &colibri_power_status, 1); - if(status < 0 ) - break; - } - - status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, - ADC_PWRDN_CLAMP_CH1, 2, 0x00, 1); - status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, - ADC_PWRDN_CLAMP_CH2, 2, 0x00, 1); - status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, - ADC_PWRDN_CLAMP_CH3, 2, 0x40, 1); - } - else { - cx231xx_info("Invalid AV mode input\n"); - status = -1; - } - } /* switch */ - - return status; + u32 colibri_power_status = 0; + int status = 0; + + switch (dev->model) { + case CX231XX_BOARD_CNXT_RDE_250: + case CX231XX_BOARD_CNXT_RDU_250: + + if (avmode == POLARIS_AVMODE_ANALOGT_TV) { + while (colibri_power_status != 0x18) { + status = + cx231xx_write_i2c_data(dev, + Colibri_DEVICE_ADDRESS, + SUP_BLK_PWRDN, 2, + 0x18, 1); + status = + cx231xx_read_i2c_data(dev, + Colibri_DEVICE_ADDRESS, + SUP_BLK_PWRDN, 2, + &colibri_power_status, + 1); + if (status < 0) + break; + } + + status = + cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, + ADC_PWRDN_CLAMP_CH1, 2, 0x00, + 1); + status = + cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, + ADC_PWRDN_CLAMP_CH2, 2, 0x00, + 1); + status = + cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, + ADC_PWRDN_CLAMP_CH3, 2, 0x00, + 1); + } else if (avmode == POLARIS_AVMODE_DIGITAL) { + status = + cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, + ADC_PWRDN_CLAMP_CH1, 2, 0x70, + 1); + status = + cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, + ADC_PWRDN_CLAMP_CH2, 2, 0x70, + 1); + status = + cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, + ADC_PWRDN_CLAMP_CH3, 2, 0x70, + 1); + + status = + cx231xx_read_i2c_data(dev, Colibri_DEVICE_ADDRESS, + SUP_BLK_PWRDN, 2, + &colibri_power_status, 1); + colibri_power_status |= 0x07; + status = + cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, + SUP_BLK_PWRDN, 2, + colibri_power_status, 1); + } else if (avmode == POLARIS_AVMODE_ENXTERNAL_AV) { + + while (colibri_power_status != 0x18) { + status = + cx231xx_write_i2c_data(dev, + Colibri_DEVICE_ADDRESS, + SUP_BLK_PWRDN, 2, + 0x18, 1); + status = + cx231xx_read_i2c_data(dev, + Colibri_DEVICE_ADDRESS, + SUP_BLK_PWRDN, 2, + &colibri_power_status, + 1); + if (status < 0) + break; + } + + status = + cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, + ADC_PWRDN_CLAMP_CH1, 2, 0x00, + 1); + status = + cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, + ADC_PWRDN_CLAMP_CH2, 2, 0x00, + 1); + status = + cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, + ADC_PWRDN_CLAMP_CH3, 2, 0x00, + 1); + } else { + cx231xx_info("Invalid AV mode input\n"); + status = -1; + } + break; + default: + if (avmode == POLARIS_AVMODE_ANALOGT_TV) { + while (colibri_power_status != 0x18) { + status = + cx231xx_write_i2c_data(dev, + Colibri_DEVICE_ADDRESS, + SUP_BLK_PWRDN, 2, + 0x18, 1); + status = + cx231xx_read_i2c_data(dev, + Colibri_DEVICE_ADDRESS, + SUP_BLK_PWRDN, 2, + &colibri_power_status, + 1); + if (status < 0) + break; + } + + status = + cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, + ADC_PWRDN_CLAMP_CH1, 2, 0x40, + 1); + status = + cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, + ADC_PWRDN_CLAMP_CH2, 2, 0x40, + 1); + status = + cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, + ADC_PWRDN_CLAMP_CH3, 2, 0x00, + 1); + } else if (avmode == POLARIS_AVMODE_DIGITAL) { + status = + cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, + ADC_PWRDN_CLAMP_CH1, 2, 0x70, + 1); + status = + cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, + ADC_PWRDN_CLAMP_CH2, 2, 0x70, + 1); + status = + cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, + ADC_PWRDN_CLAMP_CH3, 2, 0x70, + 1); + + status = + cx231xx_read_i2c_data(dev, Colibri_DEVICE_ADDRESS, + SUP_BLK_PWRDN, 2, + &colibri_power_status, 1); + colibri_power_status |= 0x07; + status = + cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, + SUP_BLK_PWRDN, 2, + colibri_power_status, 1); + } else if (avmode == POLARIS_AVMODE_ENXTERNAL_AV) { + while (colibri_power_status != 0x18) { + status = + cx231xx_write_i2c_data(dev, + Colibri_DEVICE_ADDRESS, + SUP_BLK_PWRDN, 2, + 0x18, 1); + status = + cx231xx_read_i2c_data(dev, + Colibri_DEVICE_ADDRESS, + SUP_BLK_PWRDN, 2, + &colibri_power_status, + 1); + if (status < 0) + break; + } + + status = + cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, + ADC_PWRDN_CLAMP_CH1, 2, 0x00, + 1); + status = + cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, + ADC_PWRDN_CLAMP_CH2, 2, 0x00, + 1); + status = + cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, + ADC_PWRDN_CLAMP_CH3, 2, 0x40, + 1); + } else { + cx231xx_info("Invalid AV mode input\n"); + status = -1; + } + } /* switch */ + + return status; } int cx231xx_colibri_adjust_ref_count(struct cx231xx *dev, u32 video_input) -{ - u32 input_mode = 0; - u32 ntf_mode = 0; - int status = 0; - - dev->video_input = video_input; - - if(video_input == CX231XX_VMUX_TELEVISION) { - status = cx231xx_read_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_INPUT_CH3, 2, &input_mode, 1); - status = cx231xx_read_i2c_data(dev, Colibri_DEVICE_ADDRESS, - ADC_NTF_PRECLMP_EN_CH3, 2, &ntf_mode, 1); - } - else { - status = cx231xx_read_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_INPUT_CH1, 2, &input_mode, 1); - status = cx231xx_read_i2c_data(dev, Colibri_DEVICE_ADDRESS, - ADC_NTF_PRECLMP_EN_CH1, 2, &ntf_mode, 1); - } - - input_mode = (ntf_mode & 0x3) | ((input_mode & 0x6) << 1); - - switch(input_mode) - { - case SINGLE_ENDED: - dev->colibri_ref_count = 0x23C; - break; - case LOW_IF: - dev->colibri_ref_count = 0x24C; - break; - case EU_IF: - dev->colibri_ref_count = 0x258; - break; - case US_IF: - dev->colibri_ref_count = 0x260; - break; - default: - break; - } - - status = cx231xx_colibri_init_super_block(dev, dev->colibri_ref_count); - - return status; -} +{ + u32 input_mode = 0; + u32 ntf_mode = 0; + int status = 0; + dev->video_input = video_input; + + if (video_input == CX231XX_VMUX_TELEVISION) { + status = + cx231xx_read_i2c_data(dev, Colibri_DEVICE_ADDRESS, + ADC_INPUT_CH3, 2, &input_mode, 1); + status = + cx231xx_read_i2c_data(dev, Colibri_DEVICE_ADDRESS, + ADC_NTF_PRECLMP_EN_CH3, 2, &ntf_mode, + 1); + } else { + status = + cx231xx_read_i2c_data(dev, Colibri_DEVICE_ADDRESS, + ADC_INPUT_CH1, 2, &input_mode, 1); + status = + cx231xx_read_i2c_data(dev, Colibri_DEVICE_ADDRESS, + ADC_NTF_PRECLMP_EN_CH1, 2, &ntf_mode, + 1); + } + + input_mode = (ntf_mode & 0x3) | ((input_mode & 0x6) << 1); + + switch (input_mode) { + case SINGLE_ENDED: + dev->colibri_ref_count = 0x23C; + break; + case LOW_IF: + dev->colibri_ref_count = 0x24C; + break; + case EU_IF: + dev->colibri_ref_count = 0x258; + break; + case US_IF: + dev->colibri_ref_count = 0x260; + break; + default: + break; + } + status = cx231xx_colibri_init_super_block(dev, dev->colibri_ref_count); + + return status; +} /************************************************************************************* * V I D E O / A U D I O D E C O D E R C O N T R O L functions * *************************************************************************************/ int cx231xx_set_video_input_mux(struct cx231xx *dev, u8 input) { - int status = 0; - - switch(INPUT(input)->type) { - case CX231XX_VMUX_COMPOSITE1: - case CX231XX_VMUX_SVIDEO: - if((dev->current_pcb_config.type == USB_BUS_POWER) && - (dev->power_mode != POLARIS_AVMODE_ENXTERNAL_AV)) { - status = cx231xx_set_power_mode(dev, POLARIS_AVMODE_ENXTERNAL_AV); /* External AV */ - if (status < 0) { - cx231xx_errdev("%s: cx231xx_set_power_mode : Failed to set Power - errCode [%d]!\n", - __func__, status); - return status; - } - } - status = cx231xx_set_decoder_video_input(dev, INPUT(input)->type, INPUT(input)->vmux); - break; - case CX231XX_VMUX_TELEVISION: - case CX231XX_VMUX_CABLE: - if((dev->current_pcb_config.type == USB_BUS_POWER) && - (dev->power_mode != POLARIS_AVMODE_ANALOGT_TV)) { - status = cx231xx_set_power_mode(dev, POLARIS_AVMODE_ANALOGT_TV); /* Tuner */ - if (status < 0) { - cx231xx_errdev("%s: cx231xx_set_power_mode : Failed to set Power - errCode [%d]!\n", - __func__, status); - return status; - } - } - status = cx231xx_set_decoder_video_input(dev, CX231XX_VMUX_COMPOSITE1, INPUT(input)->vmux); - break; - default: - cx231xx_errdev("%s: cx231xx_set_power_mode : Unknown Input %d !\n", - __func__, INPUT(input)->type); - break; - } - - /* save the selection */ - dev->video_input = input; - - return status; + int status = 0; + + switch (INPUT(input)->type) { + case CX231XX_VMUX_COMPOSITE1: + case CX231XX_VMUX_SVIDEO: + if ((dev->current_pcb_config.type == USB_BUS_POWER) && + (dev->power_mode != POLARIS_AVMODE_ENXTERNAL_AV)) { + status = cx231xx_set_power_mode(dev, POLARIS_AVMODE_ENXTERNAL_AV); /* External AV */ + if (status < 0) { + cx231xx_errdev + ("%s: cx231xx_set_power_mode : Failed to set Power - errCode [%d]!\n", + __func__, status); + return status; + } + } + status = + cx231xx_set_decoder_video_input(dev, INPUT(input)->type, + INPUT(input)->vmux); + break; + case CX231XX_VMUX_TELEVISION: + case CX231XX_VMUX_CABLE: + if ((dev->current_pcb_config.type == USB_BUS_POWER) && + (dev->power_mode != POLARIS_AVMODE_ANALOGT_TV)) { + status = cx231xx_set_power_mode(dev, POLARIS_AVMODE_ANALOGT_TV); /* Tuner */ + if (status < 0) { + cx231xx_errdev + ("%s: cx231xx_set_power_mode : Failed to set Power - errCode [%d]!\n", + __func__, status); + return status; + } + } + status = + cx231xx_set_decoder_video_input(dev, + CX231XX_VMUX_COMPOSITE1, + INPUT(input)->vmux); + break; + default: + cx231xx_errdev + ("%s: cx231xx_set_power_mode : Unknown Input %d !\n", + __func__, INPUT(input)->type); + break; + } + + /* save the selection */ + dev->video_input = input; + + return status; } int cx231xx_set_decoder_video_input(struct cx231xx *dev, u8 pin_type, u8 input) { - int status = 0; - u32 value = 0; - - if(pin_type != dev->video_input) { - status = cx231xx_colibri_adjust_ref_count(dev, pin_type); - if(status < 0 ) { - cx231xx_errdev("%s: cx231xx_colibri_adjust_ref_count :Failed to set Colibri input mux - errCode [%d]!\n", - __func__, status); - return status; - } - } - - /* call colibri block to set video inputs */ - status = cx231xx_colibri_set_input_mux(dev, input); - if(status < 0 ) { - cx231xx_errdev("%s: cx231xx_colibri_set_input_mux :Failed to set Colibri input mux - errCode [%d]!\n", - __func__, status); - return status; - } - - switch(pin_type) { - case CX231XX_VMUX_COMPOSITE1: - { - status = cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, AFE_CTRL, 2, &value, 4); - value |= (0<<13)|(1<<4); - value &= ~(1<<5); - - value &= (~(0x1FF8000)); /* set [24:23] [22:15] to 0 */ - value |= 0x1000000; /* set FUNC_MODE[24:23] = 2 IF_MOD[22:15] = 0 */ - status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, AFE_CTRL, 2, value, 4); - - status = cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, OUT_CTRL1, 2, &value, 4); - value |= (1<<7); - status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, OUT_CTRL1, 2, value, 4); - - /* Set vip 1.1 output mode */ - status = cx231xx_read_modify_write_i2c_dword(dev, HAMMERHEAD_I2C_ADDRESS, - OUT_CTRL1, FLD_OUT_MODE, OUT_MODE_VIP11); - - /* Tell DIF object to go to baseband mode */ - status = cx231xx_dif_set_standard(dev, DIF_USE_BASEBAND); - if (status < 0) { - cx231xx_errdev("%s: cx231xx_dif set to By pass mode - errCode [%d]!\n", - __func__, status); - return status; - } - - /* Read the DFE_CTRL1 register */ - status = cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DFE_CTRL1, 2, &value, 4); - - /* enable the VBI_GATE_EN */ - value |= FLD_VBI_GATE_EN; - - /* Enable the auto-VGA enable */ - value |= FLD_VGA_AUTO_EN; - - /* Write it back */ - status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DFE_CTRL1, 2, value, 4); - - /* Disable auto config of registers */ - status = cx231xx_read_modify_write_i2c_dword(dev, HAMMERHEAD_I2C_ADDRESS, - MODE_CTRL, FLD_ACFG_DIS, cx231xx_set_field(FLD_ACFG_DIS, 1)); - - /* Set CVBS input mode */ - status = cx231xx_read_modify_write_i2c_dword(dev, HAMMERHEAD_I2C_ADDRESS, - MODE_CTRL, FLD_INPUT_MODE, - cx231xx_set_field(FLD_INPUT_MODE, INPUT_MODE_CVBS_0)); - } - break; - case CX231XX_VMUX_SVIDEO: - { - /* Disable the use of DIF */ - - status = cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, AFE_CTRL, 2, &value, 4); - - value &= (~(0x1FF8000)); /* set [24:23] [22:15] to 0 */ - value |= 0x1000010; /* set FUNC_MODE[24:23] = 2 - IF_MOD[22:15] = 0 DCR_BYP_CH2[4:4] = 1; */ - status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, AFE_CTRL, 2, value, 4); - - /* Tell DIF object to go to baseband mode */ - status = cx231xx_dif_set_standard(dev, DIF_USE_BASEBAND); - if (status < 0) { - cx231xx_errdev("%s: cx231xx_dif set to By pass mode - errCode [%d]!\n", - __func__, status); - return status; - } - - /* Read the DFE_CTRL1 register */ - status = cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DFE_CTRL1, 2, &value, 4); - - /* enable the VBI_GATE_EN */ - value |= FLD_VBI_GATE_EN; - - /* Enable the auto-VGA enable */ - value |= FLD_VGA_AUTO_EN; - - /* Write it back */ - status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DFE_CTRL1, 2, value, 4); - - /* Disable auto config of registers */ - status = cx231xx_read_modify_write_i2c_dword(dev, HAMMERHEAD_I2C_ADDRESS, - MODE_CTRL, FLD_ACFG_DIS, cx231xx_set_field(FLD_ACFG_DIS, 1)); - - /* Set YC input mode */ - status = cx231xx_read_modify_write_i2c_dword(dev, HAMMERHEAD_I2C_ADDRESS, - MODE_CTRL, FLD_INPUT_MODE, - cx231xx_set_field(FLD_INPUT_MODE, INPUT_MODE_YC_1)); - - /* Chroma to ADC2 */ - status = cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, AFE_CTRL, 2, &value, 4); - value |= FLD_CHROMA_IN_SEL; /* set the chroma in select */ - - /* Clear VGA_SEL_CH2 and VGA_SEL_CH3 (bits 7 and 8) This sets them to use video - rather than audio. Only one of the two will be in use. */ - value &= ~(FLD_VGA_SEL_CH2 | FLD_VGA_SEL_CH3); - - status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, AFE_CTRL, 2, value, 4); - - status = cx231xx_colibri_set_mode(dev, AFE_MODE_BASEBAND); - } - break; - case CX231XX_VMUX_TELEVISION: - case CX231XX_VMUX_CABLE: - default: - { - switch(dev->model) { - case CX231XX_BOARD_CNXT_RDE_250: - case CX231XX_BOARD_CNXT_RDU_250: - { - /* Disable the use of DIF */ - - status = cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, AFE_CTRL, 2, &value, 4); - value |= (0<<13)|(1<<4); - value &= ~(1<<5); - - value &= (~(0x1FF8000)); /* set [24:23] [22:15] to 0 */ - value |= 0x1000000; /* set FUNC_MODE[24:23] = 2 IF_MOD[22:15] = 0 */ - status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, AFE_CTRL, 2, value, 4); - - status = cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, OUT_CTRL1, 2, &value, 4); - value |= (1<<7); - status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, OUT_CTRL1, 2, value, 4); - - /* Set vip 1.1 output mode */ - status = cx231xx_read_modify_write_i2c_dword(dev, HAMMERHEAD_I2C_ADDRESS, - OUT_CTRL1, FLD_OUT_MODE, OUT_MODE_VIP11); - - /* Tell DIF object to go to baseband mode */ - status = cx231xx_dif_set_standard(dev, DIF_USE_BASEBAND); - if (status < 0) { - cx231xx_errdev("%s: cx231xx_dif set to By pass mode - errCode [%d]!\n", - __func__, status); - return status; - } - - /* Read the DFE_CTRL1 register */ - status = cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DFE_CTRL1, 2, &value, 4); - - /* enable the VBI_GATE_EN */ - value |= FLD_VBI_GATE_EN; - - /* Enable the auto-VGA enable */ - value |= FLD_VGA_AUTO_EN; - - /* Write it back */ - status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DFE_CTRL1, 2, value, 4); - - /* Disable auto config of registers */ - status = cx231xx_read_modify_write_i2c_dword(dev, HAMMERHEAD_I2C_ADDRESS, - MODE_CTRL, FLD_ACFG_DIS, cx231xx_set_field(FLD_ACFG_DIS, 1)); - - /* Set CVBS input mode */ - status = cx231xx_read_modify_write_i2c_dword(dev, HAMMERHEAD_I2C_ADDRESS, - MODE_CTRL, FLD_INPUT_MODE, - cx231xx_set_field(FLD_INPUT_MODE, INPUT_MODE_CVBS_0)); - } - break; - default: - { - /* Enable the DIF for the tuner */ - - /* Reinitialize the DIF */ - status = cx231xx_dif_set_standard(dev, dev->norm); - if (status < 0) { - cx231xx_errdev("%s: cx231xx_dif set to By pass mode - errCode [%d]!\n", - __func__, status); - return status; - } - - /* Make sure bypass is cleared */ - status = cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_MISC_CTRL, 2, &value, 4); - - /* Clear the bypass bit */ - value &= ~FLD_DIF_DIF_BYPASS; - - /* Enable the use of the DIF block */ - status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_MISC_CTRL, 2, value, 4); - - /* Read the DFE_CTRL1 register */ - status = cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DFE_CTRL1, 2, &value, 4); - - /* Disable the VBI_GATE_EN */ - value &= ~FLD_VBI_GATE_EN; - - /* Enable the auto-VGA enable, AGC, and set the skip count to 2 */ - value |= FLD_VGA_AUTO_EN | FLD_AGC_AUTO_EN | 0x00200000; - - /* Write it back */ - status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DFE_CTRL1, 2, value, 4); - - /* Wait 15 ms */ - msleep(1); - - /* Disable the auto-VGA enable AGC */ - value &= ~(FLD_VGA_AUTO_EN); - - /* Write it back */ - status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DFE_CTRL1, 2, value, 4); - - /* Enable Polaris B0 AGC output */ - status = cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, PIN_CTRL, 2, &value, 4); - value |=(FLD_OEF_AGC_RF)|(FLD_OEF_AGC_IFVGA)|(FLD_OEF_AGC_IF); - status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, PIN_CTRL, 2, value, 4); - - /* Set vip 1.1 output mode */ - status = cx231xx_read_modify_write_i2c_dword(dev, HAMMERHEAD_I2C_ADDRESS, - OUT_CTRL1, FLD_OUT_MODE, OUT_MODE_VIP11); - - /* Disable auto config of registers */ - status = cx231xx_read_modify_write_i2c_dword(dev, HAMMERHEAD_I2C_ADDRESS, - MODE_CTRL, FLD_ACFG_DIS, cx231xx_set_field(FLD_ACFG_DIS, 1)); - - /* Set CVBS input mode */ - status = cx231xx_read_modify_write_i2c_dword(dev, HAMMERHEAD_I2C_ADDRESS, - MODE_CTRL, FLD_INPUT_MODE, - cx231xx_set_field(FLD_INPUT_MODE, INPUT_MODE_CVBS_0)); - - /* Set some bits in AFE_CTRL so that channel 2 or 3 is ready to receive audio */ - /* Clear clamp for channels 2 and 3 (bit 16-17) */ - /* Clear droop comp (bit 19-20) */ - /* Set VGA_SEL (for audio control) (bit 7-8) */ - status = cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, AFE_CTRL, 2, &value, 4); - - value |= FLD_VGA_SEL_CH3 | FLD_VGA_SEL_CH2; - - status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, AFE_CTRL, 2, value, 4); - } - break; - - } - } - break; - } - - /* Set raw VBI mode */ - status = cx231xx_read_modify_write_i2c_dword(dev, HAMMERHEAD_I2C_ADDRESS, - OUT_CTRL1, FLD_VBIHACTRAW_EN, - cx231xx_set_field(FLD_VBIHACTRAW_EN, 1)); - - status = cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, OUT_CTRL1, 2, &value, 4); - if(value & 0x02) { - value |=(1<<19); - status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, OUT_CTRL1, 2, value, 4); - } - - return status; + int status = 0; + u32 value = 0; + + if (pin_type != dev->video_input) { + status = cx231xx_colibri_adjust_ref_count(dev, pin_type); + if (status < 0) { + cx231xx_errdev + ("%s: cx231xx_colibri_adjust_ref_count :Failed to set Colibri input mux - errCode [%d]!\n", + __func__, status); + return status; + } + } + + /* call colibri block to set video inputs */ + status = cx231xx_colibri_set_input_mux(dev, input); + if (status < 0) { + cx231xx_errdev + ("%s: cx231xx_colibri_set_input_mux :Failed to set Colibri input mux - errCode [%d]!\n", + __func__, status); + return status; + } + + switch (pin_type) { + case CX231XX_VMUX_COMPOSITE1: + { + status = + cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + AFE_CTRL, 2, &value, 4); + value |= (0 << 13) | (1 << 4); + value &= ~(1 << 5); + + value &= (~(0x1FF8000)); /* set [24:23] [22:15] to 0 */ + value |= 0x1000000; /* set FUNC_MODE[24:23] = 2 IF_MOD[22:15] = 0 */ + status = + cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + AFE_CTRL, 2, value, 4); + + status = + cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + OUT_CTRL1, 2, &value, 4); + value |= (1 << 7); + status = + cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + OUT_CTRL1, 2, value, 4); + + /* Set vip 1.1 output mode */ + status = + cx231xx_read_modify_write_i2c_dword(dev, + HAMMERHEAD_I2C_ADDRESS, + OUT_CTRL1, + FLD_OUT_MODE, + OUT_MODE_VIP11); + + /* Tell DIF object to go to baseband mode */ + status = + cx231xx_dif_set_standard(dev, DIF_USE_BASEBAND); + if (status < 0) { + cx231xx_errdev + ("%s: cx231xx_dif set to By pass mode - errCode [%d]!\n", + __func__, status); + return status; + } + + /* Read the DFE_CTRL1 register */ + status = + cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + DFE_CTRL1, 2, &value, 4); + + /* enable the VBI_GATE_EN */ + value |= FLD_VBI_GATE_EN; + + /* Enable the auto-VGA enable */ + value |= FLD_VGA_AUTO_EN; + + /* Write it back */ + status = + cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + DFE_CTRL1, 2, value, 4); + + /* Disable auto config of registers */ + status = + cx231xx_read_modify_write_i2c_dword(dev, + HAMMERHEAD_I2C_ADDRESS, + MODE_CTRL, + FLD_ACFG_DIS, + cx231xx_set_field + (FLD_ACFG_DIS, + 1)); + + /* Set CVBS input mode */ + status = + cx231xx_read_modify_write_i2c_dword(dev, + HAMMERHEAD_I2C_ADDRESS, + MODE_CTRL, + FLD_INPUT_MODE, + cx231xx_set_field + (FLD_INPUT_MODE, + INPUT_MODE_CVBS_0)); + } + break; + case CX231XX_VMUX_SVIDEO: + { + /* Disable the use of DIF */ + + status = + cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + AFE_CTRL, 2, &value, 4); + + value &= (~(0x1FF8000)); /* set [24:23] [22:15] to 0 */ + value |= 0x1000010; /* set FUNC_MODE[24:23] = 2 + IF_MOD[22:15] = 0 DCR_BYP_CH2[4:4] = 1; */ + status = + cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + AFE_CTRL, 2, value, 4); + + /* Tell DIF object to go to baseband mode */ + status = + cx231xx_dif_set_standard(dev, DIF_USE_BASEBAND); + if (status < 0) { + cx231xx_errdev + ("%s: cx231xx_dif set to By pass mode - errCode [%d]!\n", + __func__, status); + return status; + } + + /* Read the DFE_CTRL1 register */ + status = + cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + DFE_CTRL1, 2, &value, 4); + + /* enable the VBI_GATE_EN */ + value |= FLD_VBI_GATE_EN; + + /* Enable the auto-VGA enable */ + value |= FLD_VGA_AUTO_EN; + + /* Write it back */ + status = + cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + DFE_CTRL1, 2, value, 4); + + /* Disable auto config of registers */ + status = + cx231xx_read_modify_write_i2c_dword(dev, + HAMMERHEAD_I2C_ADDRESS, + MODE_CTRL, + FLD_ACFG_DIS, + cx231xx_set_field + (FLD_ACFG_DIS, + 1)); + + /* Set YC input mode */ + status = + cx231xx_read_modify_write_i2c_dword(dev, + HAMMERHEAD_I2C_ADDRESS, + MODE_CTRL, + FLD_INPUT_MODE, + cx231xx_set_field + (FLD_INPUT_MODE, + INPUT_MODE_YC_1)); + + /* Chroma to ADC2 */ + status = + cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + AFE_CTRL, 2, &value, 4); + value |= FLD_CHROMA_IN_SEL; /* set the chroma in select */ + + /* Clear VGA_SEL_CH2 and VGA_SEL_CH3 (bits 7 and 8) This sets them to use video + rather than audio. Only one of the two will be in use. */ + value &= ~(FLD_VGA_SEL_CH2 | FLD_VGA_SEL_CH3); + + status = + cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + AFE_CTRL, 2, value, 4); + + status = + cx231xx_colibri_set_mode(dev, AFE_MODE_BASEBAND); + } + break; + case CX231XX_VMUX_TELEVISION: + case CX231XX_VMUX_CABLE: + default: + { + switch (dev->model) { + case CX231XX_BOARD_CNXT_RDE_250: + case CX231XX_BOARD_CNXT_RDU_250: + { + /* Disable the use of DIF */ + + status = + cx231xx_read_i2c_data(dev, + HAMMERHEAD_I2C_ADDRESS, + AFE_CTRL, 2, + &value, 4); + value |= (0 << 13) | (1 << 4); + value &= ~(1 << 5); + + value &= (~(0x1FF8000)); /* set [24:23] [22:15] to 0 */ + value |= 0x1000000; /* set FUNC_MODE[24:23] = 2 IF_MOD[22:15] = 0 */ + status = + cx231xx_write_i2c_data(dev, + HAMMERHEAD_I2C_ADDRESS, + AFE_CTRL, 2, + value, 4); + + status = + cx231xx_read_i2c_data(dev, + HAMMERHEAD_I2C_ADDRESS, + OUT_CTRL1, 2, + &value, 4); + value |= (1 << 7); + status = + cx231xx_write_i2c_data(dev, + HAMMERHEAD_I2C_ADDRESS, + OUT_CTRL1, 2, + value, 4); + + /* Set vip 1.1 output mode */ + status = + cx231xx_read_modify_write_i2c_dword + (dev, HAMMERHEAD_I2C_ADDRESS, + OUT_CTRL1, FLD_OUT_MODE, + OUT_MODE_VIP11); + + /* Tell DIF object to go to baseband mode */ + status = + cx231xx_dif_set_standard(dev, + DIF_USE_BASEBAND); + if (status < 0) { + cx231xx_errdev + ("%s: cx231xx_dif set to By pass mode - errCode [%d]!\n", + __func__, status); + return status; + } + + /* Read the DFE_CTRL1 register */ + status = + cx231xx_read_i2c_data(dev, + HAMMERHEAD_I2C_ADDRESS, + DFE_CTRL1, 2, + &value, 4); + + /* enable the VBI_GATE_EN */ + value |= FLD_VBI_GATE_EN; + + /* Enable the auto-VGA enable */ + value |= FLD_VGA_AUTO_EN; + + /* Write it back */ + status = + cx231xx_write_i2c_data(dev, + HAMMERHEAD_I2C_ADDRESS, + DFE_CTRL1, 2, + value, 4); + + /* Disable auto config of registers */ + status = + cx231xx_read_modify_write_i2c_dword + (dev, HAMMERHEAD_I2C_ADDRESS, + MODE_CTRL, FLD_ACFG_DIS, + cx231xx_set_field(FLD_ACFG_DIS, + 1)); + + /* Set CVBS input mode */ + status = + cx231xx_read_modify_write_i2c_dword + (dev, HAMMERHEAD_I2C_ADDRESS, + MODE_CTRL, FLD_INPUT_MODE, + cx231xx_set_field(FLD_INPUT_MODE, + INPUT_MODE_CVBS_0)); + } + break; + default: + { + /* Enable the DIF for the tuner */ + + /* Reinitialize the DIF */ + status = + cx231xx_dif_set_standard(dev, + dev->norm); + if (status < 0) { + cx231xx_errdev + ("%s: cx231xx_dif set to By pass mode - errCode [%d]!\n", + __func__, status); + return status; + } + + /* Make sure bypass is cleared */ + status = + cx231xx_read_i2c_data(dev, + HAMMERHEAD_I2C_ADDRESS, + DIF_MISC_CTRL, + 2, &value, 4); + + /* Clear the bypass bit */ + value &= ~FLD_DIF_DIF_BYPASS; + + /* Enable the use of the DIF block */ + status = + cx231xx_write_i2c_data(dev, + HAMMERHEAD_I2C_ADDRESS, + DIF_MISC_CTRL, + 2, value, 4); + + /* Read the DFE_CTRL1 register */ + status = + cx231xx_read_i2c_data(dev, + HAMMERHEAD_I2C_ADDRESS, + DFE_CTRL1, 2, + &value, 4); + + /* Disable the VBI_GATE_EN */ + value &= ~FLD_VBI_GATE_EN; + + /* Enable the auto-VGA enable, AGC, and set the skip count to 2 */ + value |= + FLD_VGA_AUTO_EN | FLD_AGC_AUTO_EN | + 0x00200000; + + /* Write it back */ + status = + cx231xx_write_i2c_data(dev, + HAMMERHEAD_I2C_ADDRESS, + DFE_CTRL1, 2, + value, 4); + + /* Wait 15 ms */ + msleep(1); + + /* Disable the auto-VGA enable AGC */ + value &= ~(FLD_VGA_AUTO_EN); + + /* Write it back */ + status = + cx231xx_write_i2c_data(dev, + HAMMERHEAD_I2C_ADDRESS, + DFE_CTRL1, 2, + value, 4); + + /* Enable Polaris B0 AGC output */ + status = + cx231xx_read_i2c_data(dev, + HAMMERHEAD_I2C_ADDRESS, + PIN_CTRL, 2, + &value, 4); + value |= + (FLD_OEF_AGC_RF) | + (FLD_OEF_AGC_IFVGA) | + (FLD_OEF_AGC_IF); + status = + cx231xx_write_i2c_data(dev, + HAMMERHEAD_I2C_ADDRESS, + PIN_CTRL, 2, + value, 4); + + /* Set vip 1.1 output mode */ + status = + cx231xx_read_modify_write_i2c_dword + (dev, HAMMERHEAD_I2C_ADDRESS, + OUT_CTRL1, FLD_OUT_MODE, + OUT_MODE_VIP11); + + /* Disable auto config of registers */ + status = + cx231xx_read_modify_write_i2c_dword + (dev, HAMMERHEAD_I2C_ADDRESS, + MODE_CTRL, FLD_ACFG_DIS, + cx231xx_set_field(FLD_ACFG_DIS, + 1)); + + /* Set CVBS input mode */ + status = + cx231xx_read_modify_write_i2c_dword + (dev, HAMMERHEAD_I2C_ADDRESS, + MODE_CTRL, FLD_INPUT_MODE, + cx231xx_set_field(FLD_INPUT_MODE, + INPUT_MODE_CVBS_0)); + + /* Set some bits in AFE_CTRL so that channel 2 or 3 is ready to receive audio */ + /* Clear clamp for channels 2 and 3 (bit 16-17) */ + /* Clear droop comp (bit 19-20) */ + /* Set VGA_SEL (for audio control) (bit 7-8) */ + status = + cx231xx_read_i2c_data(dev, + HAMMERHEAD_I2C_ADDRESS, + AFE_CTRL, 2, + &value, 4); + + value |= + FLD_VGA_SEL_CH3 | FLD_VGA_SEL_CH2; + + status = + cx231xx_write_i2c_data(dev, + HAMMERHEAD_I2C_ADDRESS, + AFE_CTRL, 2, + value, 4); + } + break; + + } + } + break; + } + + /* Set raw VBI mode */ + status = + cx231xx_read_modify_write_i2c_dword(dev, HAMMERHEAD_I2C_ADDRESS, + OUT_CTRL1, FLD_VBIHACTRAW_EN, + cx231xx_set_field + (FLD_VBIHACTRAW_EN, 1)); + + status = + cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, OUT_CTRL1, 2, + &value, 4); + if (value & 0x02) { + value |= (1 << 19); + status = + cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + OUT_CTRL1, 2, value, 4); + } + + return status; } /* @@ -718,207 +1026,310 @@ int cx231xx_set_decoder_video_input(struct cx231xx *dev, u8 pin_type, u8 input) */ int cx231xx_do_mode_ctrl_overrides(struct cx231xx *dev) { - int status = 0; - - cx231xx_info("do_mode_ctrl_overrides : 0x%x\n", (unsigned int)dev->norm); - - /* Change the DFE_CTRL3 bp_percent to fix flagging */ - status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DFE_CTRL3, 2, 0xCD3F0280, 4); - - if( dev->norm & (V4L2_STD_NTSC_M | V4L2_STD_NTSC_M_JP | V4L2_STD_PAL_M) ) { - cx231xx_info("do_mode_ctrl_overrides NTSC\n"); - - /* Move the close caption lines out of active video, adjust the active video start point */ - status = cx231xx_read_modify_write_i2c_dword(dev, HAMMERHEAD_I2C_ADDRESS, - VERT_TIM_CTRL, FLD_VBLANK_CNT,0x18); - status = cx231xx_read_modify_write_i2c_dword(dev, HAMMERHEAD_I2C_ADDRESS, - VERT_TIM_CTRL, FLD_VACTIVE_CNT,0x1E6000); - status = cx231xx_read_modify_write_i2c_dword(dev, HAMMERHEAD_I2C_ADDRESS, - VERT_TIM_CTRL, FLD_V656BLANK_CNT,0x1E000000); - - status = cx231xx_read_modify_write_i2c_dword(dev, HAMMERHEAD_I2C_ADDRESS, - HORIZ_TIM_CTRL, FLD_HBLANK_CNT, - cx231xx_set_field(FLD_HBLANK_CNT, 0x79)); - } else if ( dev->norm & ( V4L2_STD_PAL_B | V4L2_STD_PAL_G | V4L2_STD_PAL_D | - V4L2_STD_PAL_I | V4L2_STD_PAL_N | V4L2_STD_PAL_Nc) ) { - cx231xx_info("do_mode_ctrl_overrides PAL\n"); - status = cx231xx_read_modify_write_i2c_dword(dev, HAMMERHEAD_I2C_ADDRESS, - VERT_TIM_CTRL, FLD_VBLANK_CNT,0x24); - /* Adjust the active video horizontal start point */ - status = cx231xx_read_modify_write_i2c_dword(dev, HAMMERHEAD_I2C_ADDRESS, - HORIZ_TIM_CTRL, FLD_HBLANK_CNT, - cx231xx_set_field(FLD_HBLANK_CNT, 0x85)); - } else if (dev->norm & ( V4L2_STD_SECAM_B | V4L2_STD_SECAM_D | V4L2_STD_SECAM_G | - V4L2_STD_SECAM_K | V4L2_STD_SECAM_K1 | V4L2_STD_SECAM_L | - V4L2_STD_SECAM_LC) ) { - cx231xx_info("do_mode_ctrl_overrides SECAM\n"); - status = cx231xx_read_modify_write_i2c_dword(dev, HAMMERHEAD_I2C_ADDRESS, - VERT_TIM_CTRL, FLD_VBLANK_CNT,0x24); - /* Adjust the active video horizontal start point */ - status = cx231xx_read_modify_write_i2c_dword(dev, HAMMERHEAD_I2C_ADDRESS, - HORIZ_TIM_CTRL, FLD_HBLANK_CNT, - cx231xx_set_field(FLD_HBLANK_CNT, 0x85)); - } - - return status; + int status = 0; + + cx231xx_info("do_mode_ctrl_overrides : 0x%x\n", + (unsigned int)dev->norm); + + /* Change the DFE_CTRL3 bp_percent to fix flagging */ + status = + cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DFE_CTRL3, 2, + 0xCD3F0280, 4); + + if (dev->norm & (V4L2_STD_NTSC_M | V4L2_STD_NTSC_M_JP | V4L2_STD_PAL_M)) { + cx231xx_info("do_mode_ctrl_overrides NTSC\n"); + + /* Move the close caption lines out of active video, adjust the active video start point */ + status = + cx231xx_read_modify_write_i2c_dword(dev, + HAMMERHEAD_I2C_ADDRESS, + VERT_TIM_CTRL, + FLD_VBLANK_CNT, 0x18); + status = + cx231xx_read_modify_write_i2c_dword(dev, + HAMMERHEAD_I2C_ADDRESS, + VERT_TIM_CTRL, + FLD_VACTIVE_CNT, + 0x1E6000); + status = + cx231xx_read_modify_write_i2c_dword(dev, + HAMMERHEAD_I2C_ADDRESS, + VERT_TIM_CTRL, + FLD_V656BLANK_CNT, + 0x1E000000); + + status = + cx231xx_read_modify_write_i2c_dword(dev, + HAMMERHEAD_I2C_ADDRESS, + HORIZ_TIM_CTRL, + FLD_HBLANK_CNT, + cx231xx_set_field + (FLD_HBLANK_CNT, 0x79)); + } else if (dev-> + norm & (V4L2_STD_PAL_B | V4L2_STD_PAL_G | V4L2_STD_PAL_D | + V4L2_STD_PAL_I | V4L2_STD_PAL_N | V4L2_STD_PAL_Nc)) { + cx231xx_info("do_mode_ctrl_overrides PAL\n"); + status = + cx231xx_read_modify_write_i2c_dword(dev, + HAMMERHEAD_I2C_ADDRESS, + VERT_TIM_CTRL, + FLD_VBLANK_CNT, 0x24); + /* Adjust the active video horizontal start point */ + status = + cx231xx_read_modify_write_i2c_dword(dev, + HAMMERHEAD_I2C_ADDRESS, + HORIZ_TIM_CTRL, + FLD_HBLANK_CNT, + cx231xx_set_field + (FLD_HBLANK_CNT, 0x85)); + } else if (dev-> + norm & (V4L2_STD_SECAM_B | V4L2_STD_SECAM_D | + V4L2_STD_SECAM_G | V4L2_STD_SECAM_K | + V4L2_STD_SECAM_K1 | V4L2_STD_SECAM_L | + V4L2_STD_SECAM_LC)) { + cx231xx_info("do_mode_ctrl_overrides SECAM\n"); + status = + cx231xx_read_modify_write_i2c_dword(dev, + HAMMERHEAD_I2C_ADDRESS, + VERT_TIM_CTRL, + FLD_VBLANK_CNT, 0x24); + /* Adjust the active video horizontal start point */ + status = + cx231xx_read_modify_write_i2c_dword(dev, + HAMMERHEAD_I2C_ADDRESS, + HORIZ_TIM_CTRL, + FLD_HBLANK_CNT, + cx231xx_set_field + (FLD_HBLANK_CNT, 0x85)); + } + + return status; } int cx231xx_set_audio_input(struct cx231xx *dev, u8 input) { - int status = 0; - enum AUDIO_INPUT ainput = AUDIO_INPUT_LINE; - - switch(INPUT(input)->amux) { - case CX231XX_AMUX_VIDEO: - ainput = AUDIO_INPUT_TUNER_TV; - break; - case CX231XX_AMUX_LINE_IN: - status = cx231xx_flatiron_set_audio_input(dev, input); - ainput = AUDIO_INPUT_LINE; - break; - default: - break; - } - - status = cx231xx_set_audio_decoder_input(dev, ainput); - - return status; + int status = 0; + enum AUDIO_INPUT ainput = AUDIO_INPUT_LINE; + + switch (INPUT(input)->amux) { + case CX231XX_AMUX_VIDEO: + ainput = AUDIO_INPUT_TUNER_TV; + break; + case CX231XX_AMUX_LINE_IN: + status = cx231xx_flatiron_set_audio_input(dev, input); + ainput = AUDIO_INPUT_LINE; + break; + default: + break; + } + + status = cx231xx_set_audio_decoder_input(dev, ainput); + + return status; } -int cx231xx_set_audio_decoder_input(struct cx231xx *dev, enum AUDIO_INPUT audio_input) +int cx231xx_set_audio_decoder_input(struct cx231xx *dev, + enum AUDIO_INPUT audio_input) { - u32 dwval; - int status; - u32 gen_ctrl; - u32 value = 0; - - /* Put it in soft reset */ - status = cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, GENERAL_CTL, 2, &gen_ctrl, 1); - gen_ctrl |= 1; - status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, GENERAL_CTL, 2, gen_ctrl, 1); - - switch(audio_input) - { - case AUDIO_INPUT_LINE: - - /* setup AUD_IO control from Merlin paralle output */ - value = cx231xx_set_field(FLD_AUD_CHAN1_SRC, AUD_CHAN_SRC_PARALLEL); - status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, AUD_IO_CTRL, 2, value, 4); - - /* setup input to Merlin, SRC2 connect to AC97 - bypass upsample-by-2, slave mode, sony mode, left justify - adr 091c, dat 01000000 */ - status = cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, AC97_CTL, 2, &dwval, 4); - - status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, AC97_CTL, 2, (dwval | FLD_AC97_UP2X_BYPASS), 4); - - /* select the parallel1 and SRC3 */ - status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, BAND_OUT_SEL, 2, - cx231xx_set_field(FLD_SRC3_IN_SEL, 0x0)| - cx231xx_set_field(FLD_SRC3_CLK_SEL, 0x0)| - cx231xx_set_field(FLD_PARALLEL1_SRC_SEL, 0x0), 4); - - /* unmute all, AC97 in, independence mode - adr 08d0, data 0x00063073 */ - status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, PATH1_CTL1, 2, 0x00063073, 4); - - /* set AVC maximum threshold, adr 08d4, dat ffff0024 */ - status = cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, PATH1_VOL_CTL, 2, &dwval, 4); - status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, PATH1_VOL_CTL, 2, - (dwval | FLD_PATH1_AVC_THRESHOLD), 4); - - /* set SC maximum threshold, adr 08ec, dat ffffb3a3 */ - status = cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, PATH1_SC_CTL, 2, &dwval, 4); - status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, PATH1_SC_CTL, 2, - (dwval | FLD_PATH1_SC_THRESHOLD), 4); - break; - - case AUDIO_INPUT_TUNER_TV: - default: - - /* Setup SRC sources and clocks */ - status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, BAND_OUT_SEL, 2, - cx231xx_set_field(FLD_SRC6_IN_SEL, 0x00)| - cx231xx_set_field(FLD_SRC6_CLK_SEL, 0x01)| - cx231xx_set_field(FLD_SRC5_IN_SEL, 0x00)| - cx231xx_set_field(FLD_SRC5_CLK_SEL, 0x02)| - cx231xx_set_field(FLD_SRC4_IN_SEL, 0x02)| - cx231xx_set_field(FLD_SRC4_CLK_SEL, 0x03)| - cx231xx_set_field(FLD_SRC3_IN_SEL, 0x00)| - cx231xx_set_field(FLD_SRC3_CLK_SEL, 0x00)| - cx231xx_set_field(FLD_BASEBAND_BYPASS_CTL, 0x00)| - cx231xx_set_field(FLD_AC97_SRC_SEL, 0x03)| - cx231xx_set_field(FLD_I2S_SRC_SEL, 0x00)| - cx231xx_set_field(FLD_PARALLEL2_SRC_SEL, 0x02)| - cx231xx_set_field(FLD_PARALLEL1_SRC_SEL, 0x01) , 4); - - /* Setup the AUD_IO control */ - status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, AUD_IO_CTRL, 2, - cx231xx_set_field(FLD_I2S_PORT_DIR, 0x00)| - cx231xx_set_field(FLD_I2S_OUT_SRC, 0x00)| - cx231xx_set_field(FLD_AUD_CHAN3_SRC,0x00)| - cx231xx_set_field(FLD_AUD_CHAN2_SRC, 0x00)| - cx231xx_set_field(FLD_AUD_CHAN1_SRC,0x03 ), 4); - - status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, PATH1_CTL1, 2, 0x1F063870, 4); - - /* setAudioStandard(_audio_standard); */ - - status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, PATH1_CTL1, 2, 0x00063870, 4); - switch(dev->model) - { - case CX231XX_BOARD_CNXT_RDE_250: - case CX231XX_BOARD_CNXT_RDU_250: - status = cx231xx_read_modify_write_i2c_dword(dev, HAMMERHEAD_I2C_ADDRESS, - CHIP_CTRL, FLD_SIF_EN, - cx231xx_set_field(FLD_SIF_EN, 1)); - break; - default: - break; - } - break; - - case AUDIO_INPUT_TUNER_FM: - /* use SIF for FM radio - setupFM(); - setAudioStandard(_audio_standard); - */ - break; - - case AUDIO_INPUT_MUTE: - status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, PATH1_CTL1, 2, 0x1F011012, 4); - break; - } - - /* Take it out of soft reset */ - status = cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, GENERAL_CTL, 2, &gen_ctrl, 1); - gen_ctrl &= ~1; - status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, GENERAL_CTL, 2, gen_ctrl, 1); - - return status; -} + u32 dwval; + int status; + u32 gen_ctrl; + u32 value = 0; + + /* Put it in soft reset */ + status = + cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, GENERAL_CTL, 2, + &gen_ctrl, 1); + gen_ctrl |= 1; + status = + cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, GENERAL_CTL, 2, + gen_ctrl, 1); + + switch (audio_input) { + case AUDIO_INPUT_LINE: + + /* setup AUD_IO control from Merlin paralle output */ + value = + cx231xx_set_field(FLD_AUD_CHAN1_SRC, AUD_CHAN_SRC_PARALLEL); + status = + cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + AUD_IO_CTRL, 2, value, 4); + + /* setup input to Merlin, SRC2 connect to AC97 + bypass upsample-by-2, slave mode, sony mode, left justify + adr 091c, dat 01000000 */ + status = + cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, AC97_CTL, + 2, &dwval, 4); + + status = + cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + AC97_CTL, 2, + (dwval | FLD_AC97_UP2X_BYPASS), 4); + + /* select the parallel1 and SRC3 */ + status = + cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + BAND_OUT_SEL, 2, + cx231xx_set_field(FLD_SRC3_IN_SEL, + 0x0) | + cx231xx_set_field(FLD_SRC3_CLK_SEL, + 0x0) | + cx231xx_set_field + (FLD_PARALLEL1_SRC_SEL, 0x0), 4); + + /* unmute all, AC97 in, independence mode + adr 08d0, data 0x00063073 */ + status = + cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + PATH1_CTL1, 2, 0x00063073, 4); + + /* set AVC maximum threshold, adr 08d4, dat ffff0024 */ + status = + cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + PATH1_VOL_CTL, 2, &dwval, 4); + status = + cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + PATH1_VOL_CTL, 2, + (dwval | FLD_PATH1_AVC_THRESHOLD), + 4); + + /* set SC maximum threshold, adr 08ec, dat ffffb3a3 */ + status = + cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + PATH1_SC_CTL, 2, &dwval, 4); + status = + cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + PATH1_SC_CTL, 2, + (dwval | FLD_PATH1_SC_THRESHOLD), 4); + break; + + case AUDIO_INPUT_TUNER_TV: + default: + + /* Setup SRC sources and clocks */ + status = + cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + BAND_OUT_SEL, 2, + cx231xx_set_field(FLD_SRC6_IN_SEL, + 0x00) | + cx231xx_set_field(FLD_SRC6_CLK_SEL, + 0x01) | + cx231xx_set_field(FLD_SRC5_IN_SEL, + 0x00) | + cx231xx_set_field(FLD_SRC5_CLK_SEL, + 0x02) | + cx231xx_set_field(FLD_SRC4_IN_SEL, + 0x02) | + cx231xx_set_field(FLD_SRC4_CLK_SEL, + 0x03) | + cx231xx_set_field(FLD_SRC3_IN_SEL, + 0x00) | + cx231xx_set_field(FLD_SRC3_CLK_SEL, + 0x00) | + cx231xx_set_field + (FLD_BASEBAND_BYPASS_CTL, + 0x00) | + cx231xx_set_field(FLD_AC97_SRC_SEL, + 0x03) | + cx231xx_set_field(FLD_I2S_SRC_SEL, + 0x00) | + cx231xx_set_field + (FLD_PARALLEL2_SRC_SEL, + 0x02) | + cx231xx_set_field + (FLD_PARALLEL1_SRC_SEL, 0x01), 4); + + /* Setup the AUD_IO control */ + status = + cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + AUD_IO_CTRL, 2, + cx231xx_set_field(FLD_I2S_PORT_DIR, + 0x00) | + cx231xx_set_field(FLD_I2S_OUT_SRC, + 0x00) | + cx231xx_set_field(FLD_AUD_CHAN3_SRC, + 0x00) | + cx231xx_set_field(FLD_AUD_CHAN2_SRC, + 0x00) | + cx231xx_set_field(FLD_AUD_CHAN1_SRC, + 0x03), 4); + + status = + cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + PATH1_CTL1, 2, 0x1F063870, 4); + + /* setAudioStandard(_audio_standard); */ + + status = + cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + PATH1_CTL1, 2, 0x00063870, 4); + switch (dev->model) { + case CX231XX_BOARD_CNXT_RDE_250: + case CX231XX_BOARD_CNXT_RDU_250: + status = + cx231xx_read_modify_write_i2c_dword(dev, + HAMMERHEAD_I2C_ADDRESS, + CHIP_CTRL, + FLD_SIF_EN, + cx231xx_set_field + (FLD_SIF_EN, + 1)); + break; + default: + break; + } + break; + + case AUDIO_INPUT_TUNER_FM: + /* use SIF for FM radio + setupFM(); + setAudioStandard(_audio_standard); + */ + break; + + case AUDIO_INPUT_MUTE: + status = + cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + PATH1_CTL1, 2, 0x1F011012, 4); + break; + } + /* Take it out of soft reset */ + status = + cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, GENERAL_CTL, 2, + &gen_ctrl, 1); + gen_ctrl &= ~1; + status = + cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, GENERAL_CTL, 2, + gen_ctrl, 1); + return status; +} /* Set resolution of the video */ int cx231xx_resolution_set(struct cx231xx *dev) { int width, height; - u32 hscale, vscale; - int status = 0; + u32 hscale, vscale; + int status = 0; width = dev->width; height = dev->height; - get_scale(dev,width, height,&hscale, &vscale); + get_scale(dev, width, height, &hscale, &vscale); - /* set horzontal scale */ - status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, HSCALE_CTRL, 2, hscale, 4); + /* set horzontal scale */ + status = + cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, HSCALE_CTRL, 2, + hscale, 4); - /* set vertical scale */ - status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, VSCALE_CTRL, 2, vscale, 4); + /* set vertical scale */ + status = + cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, VSCALE_CTRL, 2, + vscale, 4); - return status; + return status; } /************************************************************************************* @@ -926,397 +1337,697 @@ int cx231xx_resolution_set(struct cx231xx *dev) *************************************************************************************/ int cx231xx_init_ctrl_pin_status(struct cx231xx *dev) { - u32 value; - int status = 0; + u32 value; + int status = 0; - status = cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, PIN_CTRL, 2, &value, 4); - value |=(~dev->board.ctl_pin_status_mask); - status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, PIN_CTRL, 2, value, 4); + status = + cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, PIN_CTRL, 2, + &value, 4); + value |= (~dev->board.ctl_pin_status_mask); + status = + cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, PIN_CTRL, 2, + value, 4); - return status; + return status; } -int cx231xx_set_agc_analog_digital_mux_select(struct cx231xx *dev, u8 analog_or_digital) +int cx231xx_set_agc_analog_digital_mux_select(struct cx231xx *dev, + u8 analog_or_digital) { - int status = 0; + int status = 0; - /* first set the direction to output */ - status = cx231xx_set_gpio_direction(dev, dev->board.agc_analog_digital_select_gpio, 1); + /* first set the direction to output */ + status = + cx231xx_set_gpio_direction(dev, + dev->board. + agc_analog_digital_select_gpio, 1); - /* 0 - demod ; 1 - Analog mode */ - status = cx231xx_set_gpio_value(dev, dev->board.agc_analog_digital_select_gpio, - analog_or_digital); + /* 0 - demod ; 1 - Analog mode */ + status = + cx231xx_set_gpio_value(dev, + dev->board.agc_analog_digital_select_gpio, + analog_or_digital); - return status; + return status; } int cx231xx_enable_i2c_for_tuner(struct cx231xx *dev, u8 I2CIndex) { - u8 value[4] ={0,0,0,0}; - int status = 0; + u8 value[4] = { 0, 0, 0, 0 }; + int status = 0; - cx231xx_info("Changing the i2c port for tuner to %d\n",I2CIndex); + cx231xx_info("Changing the i2c port for tuner to %d\n", I2CIndex); - status = cx231xx_read_ctrl_reg(dev,VRT_GET_REGISTER, PWR_CTL_EN, value, 4); - if(status < 0) - return status; + status = + cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, PWR_CTL_EN, value, 4); + if (status < 0) + return status; - if(I2CIndex==I2C_1) { - if(value[0] & I2C_DEMOD_EN) { - value[0] &= ~I2C_DEMOD_EN; - status = cx231xx_write_ctrl_reg(dev,VRT_SET_REGISTER, PWR_CTL_EN,value,4); - } - } else { - if(!(value[0] & I2C_DEMOD_EN)) { - value[0] |= I2C_DEMOD_EN; - status = cx231xx_write_ctrl_reg(dev,VRT_SET_REGISTER, PWR_CTL_EN,value,4); - } - } + if (I2CIndex == I2C_1) { + if (value[0] & I2C_DEMOD_EN) { + value[0] &= ~I2C_DEMOD_EN; + status = + cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER, + PWR_CTL_EN, value, 4); + } + } else { + if (!(value[0] & I2C_DEMOD_EN)) { + value[0] |= I2C_DEMOD_EN; + status = + cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER, + PWR_CTL_EN, value, 4); + } + } - return status; + return status; } - /************************************************************************************* * D I F - B L O C K C O N T R O L functions * *************************************************************************************/ -int cx231xx_dif_configure_C2HH_for_low_IF(struct cx231xx *dev, u32 mode, - u32 function_mode, u32 standard) -{ - int status = 0; - - if(mode == V4L2_TUNER_RADIO) { - /* C2HH */ - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, - AFE_CTRL_C2HH_SRC_CTRL, 30, 31, 0x1); /* lo if big signal */ - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, - AFE_CTRL_C2HH_SRC_CTRL, 23, 24, function_mode); /* FUNC_MODE = DIF */ - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, - AFE_CTRL_C2HH_SRC_CTRL, 15, 22, 0xFF); /* IF_MODE */ - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, - AFE_CTRL_C2HH_SRC_CTRL, 9, 9, 0x1); /* no inv */ - } - else { - switch(standard) { - case V4L2_STD_NTSC_M: /* 75 IRE Setup */ - case V4L2_STD_NTSC_M_JP: /* Japan, 0 IRE Setup */ - case V4L2_STD_PAL_M: - case V4L2_STD_PAL_N: - case V4L2_STD_PAL_Nc: - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, - AFE_CTRL_C2HH_SRC_CTRL, 30, 31, 0x1); /* lo if big signal */ - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, - AFE_CTRL_C2HH_SRC_CTRL, 23, 24, function_mode); /* FUNC_MODE = DIF */ - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, - AFE_CTRL_C2HH_SRC_CTRL, 15, 22, 0xb); /* IF_MODE */ - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, - AFE_CTRL_C2HH_SRC_CTRL, 9, 9, 0x1); /* no inv */ - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, - AUD_IO_CTRL, 0, 31, 0x00000003); /* 0x124, AUD_CHAN1_SRC = 0x3 */ - break; - - case V4L2_STD_PAL_B: - case V4L2_STD_PAL_G: - /* C2HH setup */ - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, - AFE_CTRL_C2HH_SRC_CTRL, 30, 31, 0x1); /* lo if big signal */ - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, - AFE_CTRL_C2HH_SRC_CTRL, 23, 24, function_mode); /* FUNC_MODE = DIF */ - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, - AFE_CTRL_C2HH_SRC_CTRL, 15, 22, 0xE); /* IF_MODE */ - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, - AFE_CTRL_C2HH_SRC_CTRL, 9, 9, 0x1); /* no inv */ - break; - - case V4L2_STD_PAL_D: - case V4L2_STD_PAL_I: - case V4L2_STD_SECAM_L: - case V4L2_STD_SECAM_LC: - case V4L2_STD_SECAM_B: - case V4L2_STD_SECAM_D: - case V4L2_STD_SECAM_G: - case V4L2_STD_SECAM_K: - case V4L2_STD_SECAM_K1: - /* C2HH setup */ - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, - AFE_CTRL_C2HH_SRC_CTRL, 30, 31, 0x1); /* lo if big signal */ - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, - AFE_CTRL_C2HH_SRC_CTRL, 23, 24, function_mode); /* FUNC_MODE = DIF */ - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, - AFE_CTRL_C2HH_SRC_CTRL, 15, 22, 0xF); /* IF_MODE */ - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, - AFE_CTRL_C2HH_SRC_CTRL, 9, 9, 0x1); /* no inv */ - break; - - case DIF_USE_BASEBAND: - default: - /* do nothing to config C2HH for baseband */ - break; - } - } - - return status; +int cx231xx_dif_configure_C2HH_for_low_IF(struct cx231xx *dev, u32 mode, + u32 function_mode, u32 standard) +{ + int status = 0; + + if (mode == V4L2_TUNER_RADIO) { + /* C2HH */ + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, AFE_CTRL_C2HH_SRC_CTRL, 30, 31, 0x1); /* lo if big signal */ + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, AFE_CTRL_C2HH_SRC_CTRL, 23, 24, function_mode); /* FUNC_MODE = DIF */ + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, AFE_CTRL_C2HH_SRC_CTRL, 15, 22, 0xFF); /* IF_MODE */ + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, AFE_CTRL_C2HH_SRC_CTRL, 9, 9, 0x1); /* no inv */ + } else { + switch (standard) { + case V4L2_STD_NTSC_M: /* 75 IRE Setup */ + case V4L2_STD_NTSC_M_JP: /* Japan, 0 IRE Setup */ + case V4L2_STD_PAL_M: + case V4L2_STD_PAL_N: + case V4L2_STD_PAL_Nc: + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, AFE_CTRL_C2HH_SRC_CTRL, 30, 31, 0x1); /* lo if big signal */ + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, AFE_CTRL_C2HH_SRC_CTRL, 23, 24, function_mode); /* FUNC_MODE = DIF */ + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, AFE_CTRL_C2HH_SRC_CTRL, 15, 22, 0xb); /* IF_MODE */ + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, AFE_CTRL_C2HH_SRC_CTRL, 9, 9, 0x1); /* no inv */ + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, AUD_IO_CTRL, 0, 31, 0x00000003); /* 0x124, AUD_CHAN1_SRC = 0x3 */ + break; + + case V4L2_STD_PAL_B: + case V4L2_STD_PAL_G: + /* C2HH setup */ + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, AFE_CTRL_C2HH_SRC_CTRL, 30, 31, 0x1); /* lo if big signal */ + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, AFE_CTRL_C2HH_SRC_CTRL, 23, 24, function_mode); /* FUNC_MODE = DIF */ + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, AFE_CTRL_C2HH_SRC_CTRL, 15, 22, 0xE); /* IF_MODE */ + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, AFE_CTRL_C2HH_SRC_CTRL, 9, 9, 0x1); /* no inv */ + break; + + case V4L2_STD_PAL_D: + case V4L2_STD_PAL_I: + case V4L2_STD_SECAM_L: + case V4L2_STD_SECAM_LC: + case V4L2_STD_SECAM_B: + case V4L2_STD_SECAM_D: + case V4L2_STD_SECAM_G: + case V4L2_STD_SECAM_K: + case V4L2_STD_SECAM_K1: + /* C2HH setup */ + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, AFE_CTRL_C2HH_SRC_CTRL, 30, 31, 0x1); /* lo if big signal */ + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, AFE_CTRL_C2HH_SRC_CTRL, 23, 24, function_mode); /* FUNC_MODE = DIF */ + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, AFE_CTRL_C2HH_SRC_CTRL, 15, 22, 0xF); /* IF_MODE */ + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, AFE_CTRL_C2HH_SRC_CTRL, 9, 9, 0x1); /* no inv */ + break; + + case DIF_USE_BASEBAND: + default: + /* do nothing to config C2HH for baseband */ + break; + } + } + + return status; } int cx231xx_dif_set_standard(struct cx231xx *dev, u32 standard) { - int status = 0; - u32 dif_misc_ctrl_value = 0; - u32 func_mode = 0; - - cx231xx_info("%s: setStandard to %x\n",__func__,standard); - - status = cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, - DIF_MISC_CTRL, 2, &dif_misc_ctrl_value, 4); - if(standard != DIF_USE_BASEBAND ) - dev->norm = standard; - - switch (dev->model) { - case CX231XX_BOARD_CNXT_RDE_250: - case CX231XX_BOARD_CNXT_RDU_250: - func_mode=0x03; - break; - default: - func_mode=0x01; - } - - status = cx231xx_dif_configure_C2HH_for_low_IF(dev, dev->active_mode, func_mode, standard); - - - if(standard == DIF_USE_BASEBAND ) { /* base band */ - - /* There is a different SRC_PHASE_INC value for baseband vs. DIF */ - status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, - DIF_SRC_PHASE_INC, 2, 0xDF7DF83, 4); - status = cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, - DIF_MISC_CTRL, 2, &dif_misc_ctrl_value, 4); - dif_misc_ctrl_value |= FLD_DIF_DIF_BYPASS; - status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, - DIF_MISC_CTRL, 2, dif_misc_ctrl_value, 4); - - } else if ( standard & (V4L2_STD_PAL_B | V4L2_STD_PAL_G) ) { - - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_PLL_CTRL, 0, 31, 0x6503bc0c); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_PLL_CTRL1, 0, 31, 0xbd038c85); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_PLL_CTRL2, 0, 31, 0x1db4640a); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_PLL_CTRL3, 0, 31, 0x00008800); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_AGC_IF_REF, 0, 31, 0x444C1380); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_AGC_CTRL_IF, 0, 31, 0xDA302600); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_AGC_CTRL_INT, 0, 31, 0xDA261700); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_AGC_CTRL_RF, 0, 31, 0xDA262600); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_AGC_IF_INT_CURRENT, 0, 31, 0x26001700); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_AGC_RF_CURRENT, 0, 31, 0x00002660); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_VIDEO_AGC_CTRL, 0, 31, 0x72500800); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_VID_AUD_OVERRIDE, 0, 31, 0x27000100); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_AV_SEP_CTRL, 0, 31, 0x3F3530EC); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_COMP_FLT_CTRL, 0, 31, 0x00A653A8); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_SRC_PHASE_INC, 0, 31, 0x1befbf06); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_SRC_GAIN_CONTROL, 0, 31, 0x000035e8); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_RPT_VARIANCE, 0, 31, 0x00000000); - /* Save the Spec Inversion value */ - dif_misc_ctrl_value &= FLD_DIF_SPEC_INV; - dif_misc_ctrl_value |=0x3a013F11; - - } else if( standard & V4L2_STD_PAL_D ) { - - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_PLL_CTRL, 0, 31, 0x6503bc0c); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_PLL_CTRL1, 0, 31, 0xbd038c85); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_PLL_CTRL2, 0, 31, 0x1db4640a); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_PLL_CTRL3, 0, 31, 0x00008800); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_AGC_IF_REF, 0, 31, 0x444C1380); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_AGC_CTRL_IF, 0, 31, 0xDA302600); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_AGC_CTRL_INT, 0, 31, 0xDA261700); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_AGC_CTRL_RF, 0, 31, 0xDA262600); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_AGC_IF_INT_CURRENT, 0, 31, 0x26001700); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_AGC_RF_CURRENT, 0, 31, 0x00002660); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_VIDEO_AGC_CTRL, 0, 31, 0x72500800); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_VID_AUD_OVERRIDE, 0, 31, 0x27000100); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_AV_SEP_CTRL, 0, 31, 0x3F3934EA); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_COMP_FLT_CTRL, 0, 31, 0x00000000); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_SRC_PHASE_INC, 0, 31, 0x1befbf06); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_SRC_GAIN_CONTROL, 0, 31, 0x000035e8); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_RPT_VARIANCE, 0, 31, 0x00000000); - /* Save the Spec Inversion value */ - dif_misc_ctrl_value &= FLD_DIF_SPEC_INV; - dif_misc_ctrl_value |=0x3a023F11; - - } else if( standard & V4L2_STD_PAL_I ) { - - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_PLL_CTRL, 0, 31, 0x6503bc0c); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_PLL_CTRL1, 0, 31, 0xbd038c85); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_PLL_CTRL2, 0, 31, 0x1db4640a); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_PLL_CTRL3, 0, 31, 0x00008800); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_AGC_IF_REF, 0, 31, 0x444C1380); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_AGC_CTRL_IF, 0, 31, 0xDA302600); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_AGC_CTRL_INT, 0, 31, 0xDA261700); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_AGC_CTRL_RF, 0, 31, 0xDA262600); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_AGC_IF_INT_CURRENT, 0, 31, 0x26001700); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_AGC_RF_CURRENT, 0, 31, 0x00002660); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_VIDEO_AGC_CTRL, 0, 31, 0x72500800); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_VID_AUD_OVERRIDE, 0, 31, 0x27000100); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_AV_SEP_CTRL, 0, 31, 0x5F39A934); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_COMP_FLT_CTRL, 0, 31, 0x00000000); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_SRC_PHASE_INC, 0, 31, 0x1befbf06); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_SRC_GAIN_CONTROL, 0, 31, 0x000035e8); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_RPT_VARIANCE, 0, 31, 0x00000000); - /* Save the Spec Inversion value */ - dif_misc_ctrl_value &= FLD_DIF_SPEC_INV; - dif_misc_ctrl_value |=0x3a033F11; - - } else if( standard & V4L2_STD_PAL_M ) { - - /* improved Low Frequency Phase Noise */ - status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, - DIF_PLL_CTRL, 2, 0xFF01FF0C, 4); - status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, - DIF_PLL_CTRL1, 2, 0xbd038c85, 4); - status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, - DIF_PLL_CTRL2, 2, 0x1db4640a, 4); - status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, - DIF_PLL_CTRL3, 2, 0x00008800, 4); - status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, - DIF_AGC_IF_REF, 2, 0x444C1380, 4); - status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, - DIF_AGC_IF_INT_CURRENT, 2, 0x26001700, 4); - status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, - DIF_AGC_RF_CURRENT, 2, 0x00002660, 4); - status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, - DIF_VIDEO_AGC_CTRL, 2, 0x72500800, 4); - status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, - DIF_VID_AUD_OVERRIDE, 2, 0x27000100, 4); - status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, - DIF_AV_SEP_CTRL, 2, 0x012c405d, 4); - status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, - DIF_COMP_FLT_CTRL, 2, 0x009f50c1, 4); - status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, - DIF_SRC_PHASE_INC, 2, 0x1befbf06, 4); - status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, - DIF_SRC_GAIN_CONTROL, 2, 0x000035e8, 4); - status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, - DIF_SOFT_RST_CTRL_REVB, 2, 0x00000000, 4); - - /* Save the Spec Inversion value */ - dif_misc_ctrl_value &= FLD_DIF_SPEC_INV; - dif_misc_ctrl_value |= 0x3A0A3F10; - - } else if( standard & (V4L2_STD_PAL_N | V4L2_STD_PAL_Nc) ) { - - /* improved Low Frequency Phase Noise */ - status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_PLL_CTRL, 2, 0xFF01FF0C, 4); - status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_PLL_CTRL1, 2, 0xbd038c85, 4); - status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_PLL_CTRL2, 2, 0x1db4640a, 4); - status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_PLL_CTRL3, 2, 0x00008800, 4); - status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_AGC_IF_REF, 2, 0x444C1380, 4); - status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_AGC_IF_INT_CURRENT, 2, 0x26001700, 4); - status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_AGC_RF_CURRENT, 2, 0x00002660, 4); - status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_VIDEO_AGC_CTRL, 2, 0x72500800, 4); - status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_VID_AUD_OVERRIDE, 2, 0x27000100, 4); - status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_AV_SEP_CTRL, 2, 0x012c405d, 4); - status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_COMP_FLT_CTRL, 2, 0x009f50c1, 4); - status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_SRC_PHASE_INC, 2, 0x1befbf06, 4); - status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_SRC_GAIN_CONTROL, 2, 0x000035e8, 4); - status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_SOFT_RST_CTRL_REVB, 2, 0x00000000, 4); - - /* Save the Spec Inversion value */ - dif_misc_ctrl_value &= FLD_DIF_SPEC_INV; - dif_misc_ctrl_value = 0x3A093F10; - - } else if( standard & ( V4L2_STD_SECAM_B | V4L2_STD_SECAM_D | V4L2_STD_SECAM_G | - V4L2_STD_SECAM_K | V4L2_STD_SECAM_K1) ) { - - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_PLL_CTRL, 0, 31, 0x6503bc0c); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_PLL_CTRL1, 0, 31, 0xbd038c85); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_PLL_CTRL2, 0, 31, 0x1db4640a); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_PLL_CTRL3, 0, 31, 0x00008800); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_AGC_IF_REF, 0, 31, 0x888C0380); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_AGC_CTRL_IF, 0, 31, 0xe0262600); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_AGC_CTRL_INT, 0, 31, 0xc2171700); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_AGC_CTRL_RF, 0, 31, 0xc2262600); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_AGC_IF_INT_CURRENT, 0, 31, 0x26001700); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_AGC_RF_CURRENT, 0, 31, 0x00002660); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_VID_AUD_OVERRIDE, 0, 31, 0x27000100); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_AV_SEP_CTRL, 0, 31, 0x3F3530ec); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_COMP_FLT_CTRL, 0, 31, 0x00000000); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_SRC_PHASE_INC, 0, 31, 0x1befbf06); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_SRC_GAIN_CONTROL, 0, 31, 0x000035e8); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_RPT_VARIANCE, 0, 31, 0x00000000); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_VIDEO_AGC_CTRL, 0, 31, 0xf4000000); - - /* Save the Spec Inversion value */ - dif_misc_ctrl_value &= FLD_DIF_SPEC_INV; - dif_misc_ctrl_value |=0x3a023F11; - - } else if( standard & (V4L2_STD_SECAM_L | V4L2_STD_SECAM_LC) ) { - - /* Is it SECAM_L1? */ - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_PLL_CTRL, 0, 31, 0x6503bc0c); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_PLL_CTRL1, 0, 31, 0xbd038c85); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_PLL_CTRL2, 0, 31, 0x1db4640a); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_PLL_CTRL3, 0, 31, 0x00008800); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_AGC_IF_REF, 0, 31, 0x888C0380); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_AGC_CTRL_IF, 0, 31, 0xe0262600); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_AGC_CTRL_INT, 0, 31, 0xc2171700); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_AGC_CTRL_RF, 0, 31, 0xc2262600); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_AGC_IF_INT_CURRENT, 0, 31, 0x26001700); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_AGC_RF_CURRENT, 0, 31, 0x00002660); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_VID_AUD_OVERRIDE, 0, 31, 0x27000100); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_AV_SEP_CTRL, 0, 31, 0x3F3530ec); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_COMP_FLT_CTRL, 0, 31, 0x00000000); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_SRC_PHASE_INC, 0, 31, 0x1befbf06); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_SRC_GAIN_CONTROL, 0, 31, 0x000035e8); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_RPT_VARIANCE, 0, 31, 0x00000000); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_VIDEO_AGC_CTRL, 0, 31, 0xf2560000); - - /* Save the Spec Inversion value */ - dif_misc_ctrl_value &= FLD_DIF_SPEC_INV; - dif_misc_ctrl_value |=0x3a023F11; - - } else { /* V4L2_STD_NTSC_M (75 IRE Setup) Or V4L2_STD_NTSC_M_JP (Japan, 0 IRE Setup) */ - - /* For NTSC the centre frequency of video coming out of sidewinder is - around 7.1MHz or 3.6MHz depending on the spectral inversion. - so for a non spectrally inverted channel the pll freq word is 0x03420c49 - */ - - status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_PLL_CTRL, 2, 0x6503BC0C, 4); - status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_PLL_CTRL1, 2, 0xBD038C85, 4); - status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_PLL_CTRL2, 2, 0x1DB4640A, 4); - status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_PLL_CTRL3, 2, 0x00008800, 4); - status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_AGC_IF_REF, 2, 0x444C0380, 4); - status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_AGC_IF_INT_CURRENT, 2, 0x26001700, 4); - status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_AGC_RF_CURRENT, 2, 0x00002660, 4); - status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_VIDEO_AGC_CTRL, 2, 0x04000800, 4); - status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_VID_AUD_OVERRIDE, 2, 0x27000100, 4); - status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_AV_SEP_CTRL, 2, 0x01296e1f, 4); - - status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_COMP_FLT_CTRL, 2, 0x009f50c1, 4); - status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_SRC_PHASE_INC, 2, 0x1befbf06, 4); - status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_SRC_GAIN_CONTROL, 2, 0x000035e8, 4); - - status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_AGC_CTRL_IF, 2, 0xC2262600, 4); - status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_AGC_CTRL_INT, 2, 0xC2262600, 4); - status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_AGC_CTRL_RF, 2, 0xC2262600, 4); - - /* Save the Spec Inversion value */ - dif_misc_ctrl_value &= FLD_DIF_SPEC_INV; - dif_misc_ctrl_value |= 0x3a003F10; - - } - - /* The AGC values should be the same for all standards, - AUD_SRC_SEL[19] should always be disabled */ - dif_misc_ctrl_value &= ~FLD_DIF_AUD_SRC_SEL; - - /* It is still possible to get Set Standard calls even when we are in FM mode - This is done to override the value for FM. */ - if (dev->active_mode == V4L2_TUNER_RADIO) - dif_misc_ctrl_value = 0x7a080000; - - /* Write the calculated value for misc ontrol register */ - status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_MISC_CTRL, 2, dif_misc_ctrl_value, 4); - - return status; + int status = 0; + u32 dif_misc_ctrl_value = 0; + u32 func_mode = 0; + + cx231xx_info("%s: setStandard to %x\n", __func__, standard); + + status = cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + DIF_MISC_CTRL, 2, &dif_misc_ctrl_value, + 4); + if (standard != DIF_USE_BASEBAND) + dev->norm = standard; + + switch (dev->model) { + case CX231XX_BOARD_CNXT_RDE_250: + case CX231XX_BOARD_CNXT_RDU_250: + func_mode = 0x03; + break; + default: + func_mode = 0x01; + } + + status = + cx231xx_dif_configure_C2HH_for_low_IF(dev, dev->active_mode, + func_mode, standard); + + if (standard == DIF_USE_BASEBAND) { /* base band */ + + /* There is a different SRC_PHASE_INC value for baseband vs. DIF */ + status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + DIF_SRC_PHASE_INC, 2, 0xDF7DF83, + 4); + status = + cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + DIF_MISC_CTRL, 2, + &dif_misc_ctrl_value, 4); + dif_misc_ctrl_value |= FLD_DIF_DIF_BYPASS; + status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + DIF_MISC_CTRL, 2, + dif_misc_ctrl_value, 4); + + } else if (standard & (V4L2_STD_PAL_B | V4L2_STD_PAL_G)) { + + status = + cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + DIF_PLL_CTRL, 0, 31, 0x6503bc0c); + status = + cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + DIF_PLL_CTRL1, 0, 31, 0xbd038c85); + status = + cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + DIF_PLL_CTRL2, 0, 31, 0x1db4640a); + status = + cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + DIF_PLL_CTRL3, 0, 31, 0x00008800); + status = + cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + DIF_AGC_IF_REF, 0, 31, 0x444C1380); + status = + cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + DIF_AGC_CTRL_IF, 0, 31, 0xDA302600); + status = + cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + DIF_AGC_CTRL_INT, 0, 31, 0xDA261700); + status = + cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + DIF_AGC_CTRL_RF, 0, 31, 0xDA262600); + status = + cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + DIF_AGC_IF_INT_CURRENT, 0, 31, + 0x26001700); + status = + cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + DIF_AGC_RF_CURRENT, 0, 31, + 0x00002660); + status = + cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + DIF_VIDEO_AGC_CTRL, 0, 31, + 0x72500800); + status = + cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + DIF_VID_AUD_OVERRIDE, 0, 31, + 0x27000100); + status = + cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + DIF_AV_SEP_CTRL, 0, 31, 0x3F3530EC); + status = + cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + DIF_COMP_FLT_CTRL, 0, 31, + 0x00A653A8); + status = + cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + DIF_SRC_PHASE_INC, 0, 31, + 0x1befbf06); + status = + cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + DIF_SRC_GAIN_CONTROL, 0, 31, + 0x000035e8); + status = + cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + DIF_RPT_VARIANCE, 0, 31, 0x00000000); + /* Save the Spec Inversion value */ + dif_misc_ctrl_value &= FLD_DIF_SPEC_INV; + dif_misc_ctrl_value |= 0x3a013F11; + + } else if (standard & V4L2_STD_PAL_D) { + + status = + cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + DIF_PLL_CTRL, 0, 31, 0x6503bc0c); + status = + cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + DIF_PLL_CTRL1, 0, 31, 0xbd038c85); + status = + cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + DIF_PLL_CTRL2, 0, 31, 0x1db4640a); + status = + cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + DIF_PLL_CTRL3, 0, 31, 0x00008800); + status = + cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + DIF_AGC_IF_REF, 0, 31, 0x444C1380); + status = + cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + DIF_AGC_CTRL_IF, 0, 31, 0xDA302600); + status = + cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + DIF_AGC_CTRL_INT, 0, 31, 0xDA261700); + status = + cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + DIF_AGC_CTRL_RF, 0, 31, 0xDA262600); + status = + cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + DIF_AGC_IF_INT_CURRENT, 0, 31, + 0x26001700); + status = + cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + DIF_AGC_RF_CURRENT, 0, 31, + 0x00002660); + status = + cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + DIF_VIDEO_AGC_CTRL, 0, 31, + 0x72500800); + status = + cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + DIF_VID_AUD_OVERRIDE, 0, 31, + 0x27000100); + status = + cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + DIF_AV_SEP_CTRL, 0, 31, 0x3F3934EA); + status = + cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + DIF_COMP_FLT_CTRL, 0, 31, + 0x00000000); + status = + cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + DIF_SRC_PHASE_INC, 0, 31, + 0x1befbf06); + status = + cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + DIF_SRC_GAIN_CONTROL, 0, 31, + 0x000035e8); + status = + cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + DIF_RPT_VARIANCE, 0, 31, 0x00000000); + /* Save the Spec Inversion value */ + dif_misc_ctrl_value &= FLD_DIF_SPEC_INV; + dif_misc_ctrl_value |= 0x3a023F11; + + } else if (standard & V4L2_STD_PAL_I) { + + status = + cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + DIF_PLL_CTRL, 0, 31, 0x6503bc0c); + status = + cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + DIF_PLL_CTRL1, 0, 31, 0xbd038c85); + status = + cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + DIF_PLL_CTRL2, 0, 31, 0x1db4640a); + status = + cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + DIF_PLL_CTRL3, 0, 31, 0x00008800); + status = + cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + DIF_AGC_IF_REF, 0, 31, 0x444C1380); + status = + cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + DIF_AGC_CTRL_IF, 0, 31, 0xDA302600); + status = + cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + DIF_AGC_CTRL_INT, 0, 31, 0xDA261700); + status = + cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + DIF_AGC_CTRL_RF, 0, 31, 0xDA262600); + status = + cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + DIF_AGC_IF_INT_CURRENT, 0, 31, + 0x26001700); + status = + cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + DIF_AGC_RF_CURRENT, 0, 31, + 0x00002660); + status = + cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + DIF_VIDEO_AGC_CTRL, 0, 31, + 0x72500800); + status = + cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + DIF_VID_AUD_OVERRIDE, 0, 31, + 0x27000100); + status = + cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + DIF_AV_SEP_CTRL, 0, 31, 0x5F39A934); + status = + cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + DIF_COMP_FLT_CTRL, 0, 31, + 0x00000000); + status = + cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + DIF_SRC_PHASE_INC, 0, 31, + 0x1befbf06); + status = + cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + DIF_SRC_GAIN_CONTROL, 0, 31, + 0x000035e8); + status = + cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + DIF_RPT_VARIANCE, 0, 31, 0x00000000); + /* Save the Spec Inversion value */ + dif_misc_ctrl_value &= FLD_DIF_SPEC_INV; + dif_misc_ctrl_value |= 0x3a033F11; + + } else if (standard & V4L2_STD_PAL_M) { + + /* improved Low Frequency Phase Noise */ + status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + DIF_PLL_CTRL, 2, 0xFF01FF0C, 4); + status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + DIF_PLL_CTRL1, 2, 0xbd038c85, + 4); + status = + cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + DIF_PLL_CTRL2, 2, 0x1db4640a, 4); + status = + cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + DIF_PLL_CTRL3, 2, 0x00008800, 4); + status = + cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + DIF_AGC_IF_REF, 2, 0x444C1380, 4); + status = + cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + DIF_AGC_IF_INT_CURRENT, 2, + 0x26001700, 4); + status = + cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + DIF_AGC_RF_CURRENT, 2, 0x00002660, + 4); + status = + cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + DIF_VIDEO_AGC_CTRL, 2, 0x72500800, + 4); + status = + cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + DIF_VID_AUD_OVERRIDE, 2, 0x27000100, + 4); + status = + cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + DIF_AV_SEP_CTRL, 2, 0x012c405d, 4); + status = + cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + DIF_COMP_FLT_CTRL, 2, 0x009f50c1, 4); + status = + cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + DIF_SRC_PHASE_INC, 2, 0x1befbf06, 4); + status = + cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + DIF_SRC_GAIN_CONTROL, 2, 0x000035e8, + 4); + status = + cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + DIF_SOFT_RST_CTRL_REVB, 2, + 0x00000000, 4); + + /* Save the Spec Inversion value */ + dif_misc_ctrl_value &= FLD_DIF_SPEC_INV; + dif_misc_ctrl_value |= 0x3A0A3F10; + + } else if (standard & (V4L2_STD_PAL_N | V4L2_STD_PAL_Nc)) { + + /* improved Low Frequency Phase Noise */ + status = + cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + DIF_PLL_CTRL, 2, 0xFF01FF0C, 4); + status = + cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + DIF_PLL_CTRL1, 2, 0xbd038c85, 4); + status = + cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + DIF_PLL_CTRL2, 2, 0x1db4640a, 4); + status = + cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + DIF_PLL_CTRL3, 2, 0x00008800, 4); + status = + cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + DIF_AGC_IF_REF, 2, 0x444C1380, 4); + status = + cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + DIF_AGC_IF_INT_CURRENT, 2, + 0x26001700, 4); + status = + cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + DIF_AGC_RF_CURRENT, 2, 0x00002660, + 4); + status = + cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + DIF_VIDEO_AGC_CTRL, 2, 0x72500800, + 4); + status = + cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + DIF_VID_AUD_OVERRIDE, 2, 0x27000100, + 4); + status = + cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + DIF_AV_SEP_CTRL, 2, 0x012c405d, 4); + status = + cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + DIF_COMP_FLT_CTRL, 2, 0x009f50c1, 4); + status = + cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + DIF_SRC_PHASE_INC, 2, 0x1befbf06, 4); + status = + cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + DIF_SRC_GAIN_CONTROL, 2, 0x000035e8, + 4); + status = + cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + DIF_SOFT_RST_CTRL_REVB, 2, + 0x00000000, 4); + + /* Save the Spec Inversion value */ + dif_misc_ctrl_value &= FLD_DIF_SPEC_INV; + dif_misc_ctrl_value = 0x3A093F10; + + } else if (standard & + (V4L2_STD_SECAM_B | V4L2_STD_SECAM_D | V4L2_STD_SECAM_G | + V4L2_STD_SECAM_K | V4L2_STD_SECAM_K1)) { + + status = + cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + DIF_PLL_CTRL, 0, 31, 0x6503bc0c); + status = + cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + DIF_PLL_CTRL1, 0, 31, 0xbd038c85); + status = + cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + DIF_PLL_CTRL2, 0, 31, 0x1db4640a); + status = + cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + DIF_PLL_CTRL3, 0, 31, 0x00008800); + status = + cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + DIF_AGC_IF_REF, 0, 31, 0x888C0380); + status = + cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + DIF_AGC_CTRL_IF, 0, 31, 0xe0262600); + status = + cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + DIF_AGC_CTRL_INT, 0, 31, 0xc2171700); + status = + cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + DIF_AGC_CTRL_RF, 0, 31, 0xc2262600); + status = + cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + DIF_AGC_IF_INT_CURRENT, 0, 31, + 0x26001700); + status = + cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + DIF_AGC_RF_CURRENT, 0, 31, + 0x00002660); + status = + cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + DIF_VID_AUD_OVERRIDE, 0, 31, + 0x27000100); + status = + cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + DIF_AV_SEP_CTRL, 0, 31, 0x3F3530ec); + status = + cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + DIF_COMP_FLT_CTRL, 0, 31, + 0x00000000); + status = + cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + DIF_SRC_PHASE_INC, 0, 31, + 0x1befbf06); + status = + cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + DIF_SRC_GAIN_CONTROL, 0, 31, + 0x000035e8); + status = + cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + DIF_RPT_VARIANCE, 0, 31, 0x00000000); + status = + cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + DIF_VIDEO_AGC_CTRL, 0, 31, + 0xf4000000); + + /* Save the Spec Inversion value */ + dif_misc_ctrl_value &= FLD_DIF_SPEC_INV; + dif_misc_ctrl_value |= 0x3a023F11; + + } else if (standard & (V4L2_STD_SECAM_L | V4L2_STD_SECAM_LC)) { + + /* Is it SECAM_L1? */ + status = + cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + DIF_PLL_CTRL, 0, 31, 0x6503bc0c); + status = + cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + DIF_PLL_CTRL1, 0, 31, 0xbd038c85); + status = + cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + DIF_PLL_CTRL2, 0, 31, 0x1db4640a); + status = + cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + DIF_PLL_CTRL3, 0, 31, 0x00008800); + status = + cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + DIF_AGC_IF_REF, 0, 31, 0x888C0380); + status = + cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + DIF_AGC_CTRL_IF, 0, 31, 0xe0262600); + status = + cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + DIF_AGC_CTRL_INT, 0, 31, 0xc2171700); + status = + cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + DIF_AGC_CTRL_RF, 0, 31, 0xc2262600); + status = + cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + DIF_AGC_IF_INT_CURRENT, 0, 31, + 0x26001700); + status = + cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + DIF_AGC_RF_CURRENT, 0, 31, + 0x00002660); + status = + cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + DIF_VID_AUD_OVERRIDE, 0, 31, + 0x27000100); + status = + cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + DIF_AV_SEP_CTRL, 0, 31, 0x3F3530ec); + status = + cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + DIF_COMP_FLT_CTRL, 0, 31, + 0x00000000); + status = + cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + DIF_SRC_PHASE_INC, 0, 31, + 0x1befbf06); + status = + cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + DIF_SRC_GAIN_CONTROL, 0, 31, + 0x000035e8); + status = + cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + DIF_RPT_VARIANCE, 0, 31, 0x00000000); + status = + cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + DIF_VIDEO_AGC_CTRL, 0, 31, + 0xf2560000); + + /* Save the Spec Inversion value */ + dif_misc_ctrl_value &= FLD_DIF_SPEC_INV; + dif_misc_ctrl_value |= 0x3a023F11; + + } else { /* V4L2_STD_NTSC_M (75 IRE Setup) Or V4L2_STD_NTSC_M_JP (Japan, 0 IRE Setup) */ + + /* For NTSC the centre frequency of video coming out of sidewinder is + around 7.1MHz or 3.6MHz depending on the spectral inversion. + so for a non spectrally inverted channel the pll freq word is 0x03420c49 + */ + + status = + cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + DIF_PLL_CTRL, 2, 0x6503BC0C, 4); + status = + cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + DIF_PLL_CTRL1, 2, 0xBD038C85, 4); + status = + cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + DIF_PLL_CTRL2, 2, 0x1DB4640A, 4); + status = + cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + DIF_PLL_CTRL3, 2, 0x00008800, 4); + status = + cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + DIF_AGC_IF_REF, 2, 0x444C0380, 4); + status = + cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + DIF_AGC_IF_INT_CURRENT, 2, + 0x26001700, 4); + status = + cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + DIF_AGC_RF_CURRENT, 2, 0x00002660, + 4); + status = + cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + DIF_VIDEO_AGC_CTRL, 2, 0x04000800, + 4); + status = + cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + DIF_VID_AUD_OVERRIDE, 2, 0x27000100, + 4); + status = + cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + DIF_AV_SEP_CTRL, 2, 0x01296e1f, 4); + + status = + cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + DIF_COMP_FLT_CTRL, 2, 0x009f50c1, 4); + status = + cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + DIF_SRC_PHASE_INC, 2, 0x1befbf06, 4); + status = + cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + DIF_SRC_GAIN_CONTROL, 2, 0x000035e8, + 4); + + status = + cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + DIF_AGC_CTRL_IF, 2, 0xC2262600, 4); + status = + cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + DIF_AGC_CTRL_INT, 2, 0xC2262600, 4); + status = + cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + DIF_AGC_CTRL_RF, 2, 0xC2262600, 4); + + /* Save the Spec Inversion value */ + dif_misc_ctrl_value &= FLD_DIF_SPEC_INV; + dif_misc_ctrl_value |= 0x3a003F10; + + } + + /* The AGC values should be the same for all standards, + AUD_SRC_SEL[19] should always be disabled */ + dif_misc_ctrl_value &= ~FLD_DIF_AUD_SRC_SEL; + + /* It is still possible to get Set Standard calls even when we are in FM mode + This is done to override the value for FM. */ + if (dev->active_mode == V4L2_TUNER_RADIO) + dif_misc_ctrl_value = 0x7a080000; + + /* Write the calculated value for misc ontrol register */ + status = + cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_MISC_CTRL, + 2, dif_misc_ctrl_value, 4); + + return status; } int cx231xx_tuner_pre_channel_change(struct cx231xx *dev) @@ -1325,540 +2036,571 @@ int cx231xx_tuner_pre_channel_change(struct cx231xx *dev) u32 dwval; /* Set the RF and IF k_agc values to 3 */ - status = cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, - DIF_AGC_IF_REF, 2, &dwval, 4); - dwval &= ~(FLD_DIF_K_AGC_RF | FLD_DIF_K_AGC_IF); - dwval |= 0x33000000; + status = cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + DIF_AGC_IF_REF, 2, &dwval, 4); + dwval &= ~(FLD_DIF_K_AGC_RF | FLD_DIF_K_AGC_IF); + dwval |= 0x33000000; - status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, - DIF_AGC_IF_REF, 2, dwval, 4); + status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + DIF_AGC_IF_REF, 2, dwval, 4); - return status; + return status; } int cx231xx_tuner_post_channel_change(struct cx231xx *dev) -{ - int status = 0; +{ + int status = 0; u32 dwval; - /* Set the RF and IF k_agc values to 4 for PAL/NTSC and 8 for SECAM */ - status = cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, - DIF_AGC_IF_REF, 2, &dwval, 4); - dwval &= ~(FLD_DIF_K_AGC_RF | FLD_DIF_K_AGC_IF); + /* Set the RF and IF k_agc values to 4 for PAL/NTSC and 8 for SECAM */ + status = cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + DIF_AGC_IF_REF, 2, &dwval, 4); + dwval &= ~(FLD_DIF_K_AGC_RF | FLD_DIF_K_AGC_IF); - if(dev->norm & ( V4L2_STD_SECAM_L | V4L2_STD_SECAM_B | V4L2_STD_SECAM_D) ) { - dwval |= 0x88000000; - } else { - dwval |= 0x44000000; - } + if (dev-> + norm & (V4L2_STD_SECAM_L | V4L2_STD_SECAM_B | V4L2_STD_SECAM_D)) { + dwval |= 0x88000000; + } else { + dwval |= 0x44000000; + } - status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, - DIF_AGC_IF_REF, 2, dwval, 4); + status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + DIF_AGC_IF_REF, 2, dwval, 4); - return status; + return status; } - - /************************************************************************************* * F L A T I R O N - B L O C K C O N T R O L functions * *************************************************************************************/ int cx231xx_flatiron_initialize(struct cx231xx *dev) { - int status = 0; - u32 value; - - status = cx231xx_read_i2c_data(dev, Flatrion_DEVICE_ADDRESS, CH_PWR_CTRL1, 1, &value, 1); - /* enables clock to delta-sigma and decimation filter */ - value |= 0x80; - status = cx231xx_write_i2c_data(dev, Flatrion_DEVICE_ADDRESS, - CH_PWR_CTRL1, 1, value, 1); - /* power up all channel */ - status = cx231xx_write_i2c_data(dev, Flatrion_DEVICE_ADDRESS, - CH_PWR_CTRL2, 1, 0x00, 1); - - return status; + int status = 0; + u32 value; + + status = + cx231xx_read_i2c_data(dev, Flatrion_DEVICE_ADDRESS, CH_PWR_CTRL1, 1, + &value, 1); + /* enables clock to delta-sigma and decimation filter */ + value |= 0x80; + status = cx231xx_write_i2c_data(dev, Flatrion_DEVICE_ADDRESS, + CH_PWR_CTRL1, 1, value, 1); + /* power up all channel */ + status = cx231xx_write_i2c_data(dev, Flatrion_DEVICE_ADDRESS, + CH_PWR_CTRL2, 1, 0x00, 1); + + return status; } int cx231xx_flatiron_update_power_control(struct cx231xx *dev, AV_MODE avmode) { - int status = 0; - u32 value=0; - - if(avmode!=POLARIS_AVMODE_ENXTERNAL_AV) { - status = cx231xx_read_i2c_data(dev, Flatrion_DEVICE_ADDRESS, CH_PWR_CTRL2, 1, &value, 1); - value |= 0xfe; - status = cx231xx_write_i2c_data(dev, Flatrion_DEVICE_ADDRESS, - CH_PWR_CTRL2, 1, value, 1); - } - else { - status = cx231xx_write_i2c_data(dev, Flatrion_DEVICE_ADDRESS, - CH_PWR_CTRL2, 1, 0x00, 1); - } - - return status; + int status = 0; + u32 value = 0; + + if (avmode != POLARIS_AVMODE_ENXTERNAL_AV) { + status = + cx231xx_read_i2c_data(dev, Flatrion_DEVICE_ADDRESS, + CH_PWR_CTRL2, 1, &value, 1); + value |= 0xfe; + status = cx231xx_write_i2c_data(dev, Flatrion_DEVICE_ADDRESS, + CH_PWR_CTRL2, 1, value, 1); + } else { + status = cx231xx_write_i2c_data(dev, Flatrion_DEVICE_ADDRESS, + CH_PWR_CTRL2, 1, 0x00, 1); + } + + return status; } /* set flatiron for audio input types */ int cx231xx_flatiron_set_audio_input(struct cx231xx *dev, u8 audio_input) -{ - int status = 0; - - switch(audio_input) { - case CX231XX_AMUX_LINE_IN: +{ + int status = 0; - status = cx231xx_write_i2c_data(dev, Flatrion_DEVICE_ADDRESS, - CH_PWR_CTRL2, 1, 0x00, 1); - status = cx231xx_write_i2c_data(dev, Flatrion_DEVICE_ADDRESS, - CH_PWR_CTRL1, 1, 0x80, 1); - break; - case CX231XX_AMUX_VIDEO: - default: - break; - } + switch (audio_input) { + case CX231XX_AMUX_LINE_IN: + + status = cx231xx_write_i2c_data(dev, Flatrion_DEVICE_ADDRESS, + CH_PWR_CTRL2, 1, 0x00, 1); + status = cx231xx_write_i2c_data(dev, Flatrion_DEVICE_ADDRESS, + CH_PWR_CTRL1, 1, 0x80, 1); + break; + case CX231XX_AMUX_VIDEO: + default: + break; + } - dev->ctl_ainput = audio_input; + dev->ctl_ainput = audio_input; - return status; + return status; } /************************************************************************************* * P O W E R C O N T R O L functions * *************************************************************************************/ int cx231xx_set_power_mode(struct cx231xx *dev, AV_MODE mode) -{ - u8 value[4] ={0,0,0,0}; - u32 tmp = 0; - int status = 0; - - if(dev->power_mode != mode) - dev->power_mode = mode; - else { - cx231xx_info(" setPowerMode::mode = %d, No Change req.\n",mode); - return 0; - } - - cx231xx_info(" setPowerMode::mode = %d\n",mode); - - status = cx231xx_read_ctrl_reg(dev,VRT_GET_REGISTER, PWR_CTL_EN, value, 4); - if(status < 0) - return status; - - tmp = *((u32 *)value); - - switch(mode) { - case POLARIS_AVMODE_ENXTERNAL_AV: - - tmp &= (~PWR_MODE_MASK); - - tmp |= PWR_AV_EN; - value[0]=(u8)tmp; - value[1]=(u8)(tmp>>8); - value[2]=(u8)(tmp>>16); - value[3]=(u8)(tmp>>24); - status = cx231xx_write_ctrl_reg(dev,VRT_SET_REGISTER, PWR_CTL_EN,value,4); - msleep(PWR_SLEEP_INTERVAL); - - tmp |= PWR_ISO_EN; - value[0]=(u8)tmp; - value[1]=(u8)(tmp>>8); - value[2]=(u8)(tmp>>16); - value[3]=(u8)(tmp>>24); - status = cx231xx_write_ctrl_reg(dev,VRT_SET_REGISTER, PWR_CTL_EN,value,4); - msleep(PWR_SLEEP_INTERVAL); - - tmp |=POLARIS_AVMODE_ENXTERNAL_AV; - value[0]=(u8)tmp; - value[1]=(u8)(tmp>>8); - value[2]=(u8)(tmp>>16); - value[3]=(u8)(tmp>>24); - status = cx231xx_write_ctrl_reg(dev,VRT_SET_REGISTER, PWR_CTL_EN,value,4); - - dev->xc_fw_load_done = 0; /* reset state of xceive tuner */ - break; - - case POLARIS_AVMODE_ANALOGT_TV: - - tmp &= (~PWR_DEMOD_EN); - tmp |= (I2C_DEMOD_EN); - value[0]=(u8)tmp; - value[1]=(u8)(tmp>>8); - value[2]=(u8)(tmp>>16); - value[3]=(u8)(tmp>>24); - status = cx231xx_write_ctrl_reg(dev,VRT_SET_REGISTER, PWR_CTL_EN,value,4); - msleep(PWR_SLEEP_INTERVAL); - - if(!(tmp & PWR_TUNER_EN)) { - tmp |= (PWR_TUNER_EN); - value[0]=(u8)tmp; - value[1]=(u8)(tmp>>8); - value[2]=(u8)(tmp>>16); - value[3]=(u8)(tmp>>24); - status = cx231xx_write_ctrl_reg(dev,VRT_SET_REGISTER, PWR_CTL_EN,value,4); - msleep(PWR_SLEEP_INTERVAL); - } - - if(!(tmp & PWR_AV_EN)) { - tmp |= PWR_AV_EN; - value[0]=(u8)tmp; - value[1]=(u8)(tmp>>8); - value[2]=(u8)(tmp>>16); - value[3]=(u8)(tmp>>24); - status = cx231xx_write_ctrl_reg(dev,VRT_SET_REGISTER, PWR_CTL_EN,value,4); - msleep(PWR_SLEEP_INTERVAL); - } - if(!(tmp & PWR_ISO_EN )) { - tmp |= PWR_ISO_EN; - value[0]=(u8)tmp; - value[1]=(u8)(tmp>>8); - value[2]=(u8)(tmp>>16); - value[3]=(u8)(tmp>>24); - status = cx231xx_write_ctrl_reg(dev,VRT_SET_REGISTER, PWR_CTL_EN,value,4); - msleep(PWR_SLEEP_INTERVAL); - } - - if(!(tmp & POLARIS_AVMODE_ANALOGT_TV )) { - tmp |= POLARIS_AVMODE_ANALOGT_TV; - value[0]=(u8)tmp; - value[1]=(u8)(tmp>>8); - value[2]=(u8)(tmp>>16); - value[3]=(u8)(tmp>>24); - status = cx231xx_write_ctrl_reg(dev,VRT_SET_REGISTER, PWR_CTL_EN,value,4); - msleep(PWR_SLEEP_INTERVAL); - } - - if( (dev->model == CX231XX_BOARD_CNXT_RDE_250) || - (dev->model == CX231XX_BOARD_CNXT_RDU_250)) { - - /* tuner path to channel 1 from port 3 */ - cx231xx_enable_i2c_for_tuner(dev, I2C_3); - - if(dev->cx231xx_reset_analog_tuner) - dev->cx231xx_reset_analog_tuner(dev); - } - break; - - case POLARIS_AVMODE_DIGITAL: - - if(!(tmp & PWR_TUNER_EN)) { - tmp |= (PWR_TUNER_EN); - value[0]=(u8)tmp; - value[1]=(u8)(tmp>>8); - value[2]=(u8)(tmp>>16); - value[3]=(u8)(tmp>>24); - status = cx231xx_write_ctrl_reg(dev,VRT_SET_REGISTER, PWR_CTL_EN,value,4); - msleep(PWR_SLEEP_INTERVAL); - } - if(!(tmp & PWR_AV_EN)) { - tmp |= PWR_AV_EN; - value[0]=(u8)tmp; - value[1]=(u8)(tmp>>8); - value[2]=(u8)(tmp>>16); - value[3]=(u8)(tmp>>24); - status = cx231xx_write_ctrl_reg(dev,VRT_SET_REGISTER, PWR_CTL_EN,value,4); - msleep(PWR_SLEEP_INTERVAL); - } - if(!(tmp & PWR_ISO_EN)) { - tmp |= PWR_ISO_EN; - value[0]=(u8)tmp; - value[1]=(u8)(tmp>>8); - value[2]=(u8)(tmp>>16); - value[3]=(u8)(tmp>>24); - status = cx231xx_write_ctrl_reg(dev,VRT_SET_REGISTER, PWR_CTL_EN,value,4); - msleep(PWR_SLEEP_INTERVAL); - } - - tmp |= POLARIS_AVMODE_DIGITAL|I2C_DEMOD_EN; - value[0]=(u8)tmp; - value[1]=(u8)(tmp>>8); - value[2]=(u8)(tmp>>16); - value[3]=(u8)(tmp>>24); - status = cx231xx_write_ctrl_reg(dev,VRT_SET_REGISTER, PWR_CTL_EN,value,4); - msleep(PWR_SLEEP_INTERVAL); - - if(!(tmp & PWR_DEMOD_EN)) { - tmp |= PWR_DEMOD_EN; - value[0]=(u8)tmp; - value[1]=(u8)(tmp>>8); - value[2]=(u8)(tmp>>16); - value[3]=(u8)(tmp>>24); - status = cx231xx_write_ctrl_reg(dev,VRT_SET_REGISTER, PWR_CTL_EN,value,4); - msleep(PWR_SLEEP_INTERVAL); - } - - if( (dev->model == CX231XX_BOARD_CNXT_RDE_250) || - (dev->model == CX231XX_BOARD_CNXT_RDU_250)) { - - /* tuner path to channel 1 from port 3 */ - cx231xx_enable_i2c_for_tuner(dev, I2C_3); - - if(dev->cx231xx_reset_analog_tuner) - dev->cx231xx_reset_analog_tuner(dev); - } - break; - - default: - break; - } - - msleep(PWR_SLEEP_INTERVAL); - - /* For power saving, only enable Pwr_resetout_n when digital TV is selected. */ - if(mode == POLARIS_AVMODE_DIGITAL) { - tmp |= PWR_RESETOUT_EN; - value[0]=(u8)tmp; - value[1]=(u8)(tmp>>8); - value[2]=(u8)(tmp>>16); - value[3]=(u8)(tmp>>24); - status = cx231xx_write_ctrl_reg(dev,VRT_SET_REGISTER, PWR_CTL_EN,value,4); - msleep(PWR_SLEEP_INTERVAL); - } - - /* update power control for colibri */ - status = cx231xx_colibri_update_power_control(dev, mode); - - /* update power control for flatiron */ - status = cx231xx_flatiron_update_power_control(dev, mode); - - status = cx231xx_read_ctrl_reg(dev,VRT_GET_REGISTER, PWR_CTL_EN, value, 4); - cx231xx_info(" The data of PWR_CTL_EN register 0x74=0x%0x,0x%0x,0x%0x,0x%0x\n",value[0],value[1],value[2],value[3]); - - return status; +{ + u8 value[4] = { 0, 0, 0, 0 }; + u32 tmp = 0; + int status = 0; + + if (dev->power_mode != mode) + dev->power_mode = mode; + else { + cx231xx_info(" setPowerMode::mode = %d, No Change req.\n", + mode); + return 0; + } + + cx231xx_info(" setPowerMode::mode = %d\n", mode); + + status = + cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, PWR_CTL_EN, value, 4); + if (status < 0) + return status; + + tmp = *((u32 *) value); + + switch (mode) { + case POLARIS_AVMODE_ENXTERNAL_AV: + + tmp &= (~PWR_MODE_MASK); + + tmp |= PWR_AV_EN; + value[0] = (u8) tmp; + value[1] = (u8) (tmp >> 8); + value[2] = (u8) (tmp >> 16); + value[3] = (u8) (tmp >> 24); + status = + cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER, PWR_CTL_EN, + value, 4); + msleep(PWR_SLEEP_INTERVAL); + + tmp |= PWR_ISO_EN; + value[0] = (u8) tmp; + value[1] = (u8) (tmp >> 8); + value[2] = (u8) (tmp >> 16); + value[3] = (u8) (tmp >> 24); + status = + cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER, PWR_CTL_EN, + value, 4); + msleep(PWR_SLEEP_INTERVAL); + + tmp |= POLARIS_AVMODE_ENXTERNAL_AV; + value[0] = (u8) tmp; + value[1] = (u8) (tmp >> 8); + value[2] = (u8) (tmp >> 16); + value[3] = (u8) (tmp >> 24); + status = + cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER, PWR_CTL_EN, + value, 4); + + dev->xc_fw_load_done = 0; /* reset state of xceive tuner */ + break; + + case POLARIS_AVMODE_ANALOGT_TV: + + tmp &= (~PWR_DEMOD_EN); + tmp |= (I2C_DEMOD_EN); + value[0] = (u8) tmp; + value[1] = (u8) (tmp >> 8); + value[2] = (u8) (tmp >> 16); + value[3] = (u8) (tmp >> 24); + status = + cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER, PWR_CTL_EN, + value, 4); + msleep(PWR_SLEEP_INTERVAL); + + if (!(tmp & PWR_TUNER_EN)) { + tmp |= (PWR_TUNER_EN); + value[0] = (u8) tmp; + value[1] = (u8) (tmp >> 8); + value[2] = (u8) (tmp >> 16); + value[3] = (u8) (tmp >> 24); + status = + cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER, + PWR_CTL_EN, value, 4); + msleep(PWR_SLEEP_INTERVAL); + } + + if (!(tmp & PWR_AV_EN)) { + tmp |= PWR_AV_EN; + value[0] = (u8) tmp; + value[1] = (u8) (tmp >> 8); + value[2] = (u8) (tmp >> 16); + value[3] = (u8) (tmp >> 24); + status = + cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER, + PWR_CTL_EN, value, 4); + msleep(PWR_SLEEP_INTERVAL); + } + if (!(tmp & PWR_ISO_EN)) { + tmp |= PWR_ISO_EN; + value[0] = (u8) tmp; + value[1] = (u8) (tmp >> 8); + value[2] = (u8) (tmp >> 16); + value[3] = (u8) (tmp >> 24); + status = + cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER, + PWR_CTL_EN, value, 4); + msleep(PWR_SLEEP_INTERVAL); + } + + if (!(tmp & POLARIS_AVMODE_ANALOGT_TV)) { + tmp |= POLARIS_AVMODE_ANALOGT_TV; + value[0] = (u8) tmp; + value[1] = (u8) (tmp >> 8); + value[2] = (u8) (tmp >> 16); + value[3] = (u8) (tmp >> 24); + status = + cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER, + PWR_CTL_EN, value, 4); + msleep(PWR_SLEEP_INTERVAL); + } + + if ((dev->model == CX231XX_BOARD_CNXT_RDE_250) || + (dev->model == CX231XX_BOARD_CNXT_RDU_250)) { + + /* tuner path to channel 1 from port 3 */ + cx231xx_enable_i2c_for_tuner(dev, I2C_3); + + if (dev->cx231xx_reset_analog_tuner) + dev->cx231xx_reset_analog_tuner(dev); + } + break; + + case POLARIS_AVMODE_DIGITAL: + + if (!(tmp & PWR_TUNER_EN)) { + tmp |= (PWR_TUNER_EN); + value[0] = (u8) tmp; + value[1] = (u8) (tmp >> 8); + value[2] = (u8) (tmp >> 16); + value[3] = (u8) (tmp >> 24); + status = + cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER, + PWR_CTL_EN, value, 4); + msleep(PWR_SLEEP_INTERVAL); + } + if (!(tmp & PWR_AV_EN)) { + tmp |= PWR_AV_EN; + value[0] = (u8) tmp; + value[1] = (u8) (tmp >> 8); + value[2] = (u8) (tmp >> 16); + value[3] = (u8) (tmp >> 24); + status = + cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER, + PWR_CTL_EN, value, 4); + msleep(PWR_SLEEP_INTERVAL); + } + if (!(tmp & PWR_ISO_EN)) { + tmp |= PWR_ISO_EN; + value[0] = (u8) tmp; + value[1] = (u8) (tmp >> 8); + value[2] = (u8) (tmp >> 16); + value[3] = (u8) (tmp >> 24); + status = + cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER, + PWR_CTL_EN, value, 4); + msleep(PWR_SLEEP_INTERVAL); + } + + tmp |= POLARIS_AVMODE_DIGITAL | I2C_DEMOD_EN; + value[0] = (u8) tmp; + value[1] = (u8) (tmp >> 8); + value[2] = (u8) (tmp >> 16); + value[3] = (u8) (tmp >> 24); + status = + cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER, PWR_CTL_EN, + value, 4); + msleep(PWR_SLEEP_INTERVAL); + + if (!(tmp & PWR_DEMOD_EN)) { + tmp |= PWR_DEMOD_EN; + value[0] = (u8) tmp; + value[1] = (u8) (tmp >> 8); + value[2] = (u8) (tmp >> 16); + value[3] = (u8) (tmp >> 24); + status = + cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER, + PWR_CTL_EN, value, 4); + msleep(PWR_SLEEP_INTERVAL); + } + + if ((dev->model == CX231XX_BOARD_CNXT_RDE_250) || + (dev->model == CX231XX_BOARD_CNXT_RDU_250)) { + + /* tuner path to channel 1 from port 3 */ + cx231xx_enable_i2c_for_tuner(dev, I2C_3); + + if (dev->cx231xx_reset_analog_tuner) + dev->cx231xx_reset_analog_tuner(dev); + } + break; + + default: + break; + } + + msleep(PWR_SLEEP_INTERVAL); + + /* For power saving, only enable Pwr_resetout_n when digital TV is selected. */ + if (mode == POLARIS_AVMODE_DIGITAL) { + tmp |= PWR_RESETOUT_EN; + value[0] = (u8) tmp; + value[1] = (u8) (tmp >> 8); + value[2] = (u8) (tmp >> 16); + value[3] = (u8) (tmp >> 24); + status = + cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER, PWR_CTL_EN, + value, 4); + msleep(PWR_SLEEP_INTERVAL); + } + + /* update power control for colibri */ + status = cx231xx_colibri_update_power_control(dev, mode); + + /* update power control for flatiron */ + status = cx231xx_flatiron_update_power_control(dev, mode); + + status = + cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, PWR_CTL_EN, value, 4); + cx231xx_info + (" The data of PWR_CTL_EN register 0x74=0x%0x,0x%0x,0x%0x,0x%0x\n", + value[0], value[1], value[2], value[3]); + + return status; } int cx231xx_power_suspend(struct cx231xx *dev) { - u8 value[4] ={0,0,0,0}; - u32 tmp = 0; - int status = 0; - - status = cx231xx_read_ctrl_reg(dev,VRT_GET_REGISTER, PWR_CTL_EN, value, 4); - if(status > 0) - return status; - - tmp = *((u32 *)value); - tmp &= (~PWR_MODE_MASK); - - value[0]=(u8)tmp; - value[1]=(u8)(tmp>>8); - value[2]=(u8)(tmp>>16); - value[3]=(u8)(tmp>>24); - status = cx231xx_write_ctrl_reg(dev,VRT_SET_REGISTER, PWR_CTL_EN,value,4); - - return status; -} + u8 value[4] = { 0, 0, 0, 0 }; + u32 tmp = 0; + int status = 0; + + status = + cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, PWR_CTL_EN, value, 4); + if (status > 0) + return status; + tmp = *((u32 *) value); + tmp &= (~PWR_MODE_MASK); + + value[0] = (u8) tmp; + value[1] = (u8) (tmp >> 8); + value[2] = (u8) (tmp >> 16); + value[3] = (u8) (tmp >> 24); + status = + cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER, PWR_CTL_EN, value, 4); + + return status; +} /************************************************************************************* * S T R E A M C O N T R O L functions * *************************************************************************************/ int cx231xx_start_stream(struct cx231xx *dev, u32 ep_mask) { - u8 value[4] = {0x0, 0x0, 0x0, 0x0}; - u32 tmp =0; - int status = 0; - - cx231xx_info("cx231xx_start_stream():: ep_mask = %x\n", ep_mask); - status = cx231xx_read_ctrl_reg(dev,VRT_GET_REGISTER, EP_MODE_SET,value,4); - if(status < 0) - return status; - - tmp = *((u32 *)value); - tmp |= ep_mask; - value[0]=(u8) tmp; - value[1]=(u8)(tmp>>8); - value[2]=(u8)(tmp>>16); - value[3]=(u8)(tmp>>24); - - status = cx231xx_write_ctrl_reg(dev,VRT_SET_REGISTER, EP_MODE_SET,value,4); - - return status; + u8 value[4] = { 0x0, 0x0, 0x0, 0x0 }; + u32 tmp = 0; + int status = 0; + + cx231xx_info("cx231xx_start_stream():: ep_mask = %x\n", ep_mask); + status = + cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, EP_MODE_SET, value, 4); + if (status < 0) + return status; + + tmp = *((u32 *) value); + tmp |= ep_mask; + value[0] = (u8) tmp; + value[1] = (u8) (tmp >> 8); + value[2] = (u8) (tmp >> 16); + value[3] = (u8) (tmp >> 24); + + status = + cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER, EP_MODE_SET, value, + 4); + + return status; } int cx231xx_stop_stream(struct cx231xx *dev, u32 ep_mask) -{ - u8 value[4] = {0x0, 0x0, 0x0, 0x0}; - u32 tmp =0; - int status = 0; - - cx231xx_info("cx231xx_stop_stream():: ep_mask = %x\n", ep_mask); - status = cx231xx_read_ctrl_reg(dev,VRT_GET_REGISTER, EP_MODE_SET,value,4); - if(status < 0) - return status; - - tmp = *((u32 *)value); - tmp&= (~ep_mask); - value[0]=(u8) tmp; - value[1]=(u8)(tmp>>8); - value[2]=(u8)(tmp>>16); - value[3]=(u8)(tmp>>24); - - status = cx231xx_write_ctrl_reg(dev,VRT_SET_REGISTER, EP_MODE_SET,value,4); - - return status; +{ + u8 value[4] = { 0x0, 0x0, 0x0, 0x0 }; + u32 tmp = 0; + int status = 0; + + cx231xx_info("cx231xx_stop_stream():: ep_mask = %x\n", ep_mask); + status = + cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, EP_MODE_SET, value, 4); + if (status < 0) + return status; + + tmp = *((u32 *) value); + tmp &= (~ep_mask); + value[0] = (u8) tmp; + value[1] = (u8) (tmp >> 8); + value[2] = (u8) (tmp >> 16); + value[3] = (u8) (tmp >> 24); + + status = + cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER, EP_MODE_SET, value, + 4); + + return status; } int cx231xx_initialize_stream_xfer(struct cx231xx *dev, u32 media_type) { - int status = 0; - - if(dev->udev->speed == USB_SPEED_HIGH) - { - switch(media_type) - { - case 81: /* audio */ - cx231xx_info("%s: Audio enter HANC\n",__func__); - status = cx231xx_mode_register(dev, TS_MODE_REG, 0x9300); - break; - - case 2: /* vbi */ - cx231xx_info("%s: set vanc registers\n",__func__); - status = cx231xx_mode_register(dev, TS_MODE_REG, 0x300); - break; - - case 3: /* sliced cc */ - cx231xx_info("%s: set hanc registers\n",__func__); - status = cx231xx_mode_register(dev, TS_MODE_REG, 0x1300); - break; - - case 0: /* video */ - cx231xx_info("%s: set video registers\n",__func__); - status = cx231xx_mode_register(dev, TS_MODE_REG, 0x100); - break; - - case 4: /* ts1 */ - cx231xx_info("%s: set ts1 registers\n",__func__); - status = cx231xx_mode_register(dev, TS_MODE_REG, 0x101); - status = cx231xx_mode_register(dev, TS1_CFG_REG, 0x400); - break; - case 6: /* ts1 parallel mode */ - cx231xx_info("%s: set ts1 parrallel mode registers\n",__func__); - status = cx231xx_mode_register(dev, TS_MODE_REG, 0x100); - status = cx231xx_mode_register(dev, TS1_CFG_REG, 0x400); - break; - } - } - else - { - status = cx231xx_mode_register(dev, TS_MODE_REG, 0x101); - } - - return status; -} - + int status = 0; + if (dev->udev->speed == USB_SPEED_HIGH) { + switch (media_type) { + case 81: /* audio */ + cx231xx_info("%s: Audio enter HANC\n", __func__); + status = + cx231xx_mode_register(dev, TS_MODE_REG, 0x9300); + break; + + case 2: /* vbi */ + cx231xx_info("%s: set vanc registers\n", __func__); + status = cx231xx_mode_register(dev, TS_MODE_REG, 0x300); + break; + + case 3: /* sliced cc */ + cx231xx_info("%s: set hanc registers\n", __func__); + status = + cx231xx_mode_register(dev, TS_MODE_REG, 0x1300); + break; + + case 0: /* video */ + cx231xx_info("%s: set video registers\n", __func__); + status = cx231xx_mode_register(dev, TS_MODE_REG, 0x100); + break; + + case 4: /* ts1 */ + cx231xx_info("%s: set ts1 registers\n", __func__); + status = cx231xx_mode_register(dev, TS_MODE_REG, 0x101); + status = cx231xx_mode_register(dev, TS1_CFG_REG, 0x400); + break; + case 6: /* ts1 parallel mode */ + cx231xx_info("%s: set ts1 parrallel mode registers\n", + __func__); + status = cx231xx_mode_register(dev, TS_MODE_REG, 0x100); + status = cx231xx_mode_register(dev, TS1_CFG_REG, 0x400); + break; + } + } else { + status = cx231xx_mode_register(dev, TS_MODE_REG, 0x101); + } + return status; +} int cx231xx_capture_start(struct cx231xx *dev, int start, u8 media_type) { int rc; - u32 ep_mask = -1; - PPCB_CONFIG pcb_config; - - /* get EP for media type */ - pcb_config = &dev->current_pcb_config; - - if(pcb_config->config_num==1) - { - switch (media_type) - { - case 0: /* Video */ - ep_mask =ENABLE_EP4; /* ep4 [00:1000] */ - break; - case 1: /* Audio */ - ep_mask =ENABLE_EP3; /* ep3 [00:0100] */ - break; - case 2: /* Vbi */ - ep_mask = ENABLE_EP5; /* ep5 [01:0000] */ - break; - case 3: /* Sliced_cc */ - ep_mask = ENABLE_EP6; /* ep6 [10:0000] */ - break; - case 4: /* ts1 */ - case 6: /* ts1 parallel mode */ - ep_mask = ENABLE_EP1; /* ep1 [00:0001] */ - break; - case 5: /* ts2 */ - ep_mask = ENABLE_EP2; /* ep2 [00:0010] */ - break; - } - - } - else if(pcb_config->config_num>1) - { - switch (media_type) - { - case 0: /* Video */ - ep_mask = ENABLE_EP4; /* ep4 [00:1000] */ - break; - case 1: /* Audio */ - ep_mask = ENABLE_EP3; /* ep3 [00:0100] */ - break; - case 2: /* Vbi */ - ep_mask = ENABLE_EP5; /* ep5 [01:0000] */ - break; - case 3: /* Sliced_cc */ - ep_mask = ENABLE_EP6; /* ep6 [10:0000] */ - break; - case 4: /* ts1 */ - case 6: /* ts1 parallel mode */ - ep_mask = ENABLE_EP1; /* ep1 [00:0001] */ - break; - case 5: /* ts2 */ - ep_mask = ENABLE_EP2; /* ep2 [00:0010] */ - break; - } - - } - - if(start) { - rc = cx231xx_initialize_stream_xfer(dev, media_type); - - if(rc < 0) { - return rc; - } - - /* enable video capture */ - if(ep_mask > 0 ) - rc = cx231xx_start_stream(dev, ep_mask); - } - else { - /* disable video capture */ - if(ep_mask > 0 ) - rc = cx231xx_stop_stream(dev, ep_mask); - } - - if (dev->mode == CX231XX_ANALOG_MODE){ - /* do any in Analog mode */ - } - else { - /* do any in digital mode */ - } + u32 ep_mask = -1; + PPCB_CONFIG pcb_config; + + /* get EP for media type */ + pcb_config = &dev->current_pcb_config; + + if (pcb_config->config_num == 1) { + switch (media_type) { + case 0: /* Video */ + ep_mask = ENABLE_EP4; /* ep4 [00:1000] */ + break; + case 1: /* Audio */ + ep_mask = ENABLE_EP3; /* ep3 [00:0100] */ + break; + case 2: /* Vbi */ + ep_mask = ENABLE_EP5; /* ep5 [01:0000] */ + break; + case 3: /* Sliced_cc */ + ep_mask = ENABLE_EP6; /* ep6 [10:0000] */ + break; + case 4: /* ts1 */ + case 6: /* ts1 parallel mode */ + ep_mask = ENABLE_EP1; /* ep1 [00:0001] */ + break; + case 5: /* ts2 */ + ep_mask = ENABLE_EP2; /* ep2 [00:0010] */ + break; + } + + } else if (pcb_config->config_num > 1) { + switch (media_type) { + case 0: /* Video */ + ep_mask = ENABLE_EP4; /* ep4 [00:1000] */ + break; + case 1: /* Audio */ + ep_mask = ENABLE_EP3; /* ep3 [00:0100] */ + break; + case 2: /* Vbi */ + ep_mask = ENABLE_EP5; /* ep5 [01:0000] */ + break; + case 3: /* Sliced_cc */ + ep_mask = ENABLE_EP6; /* ep6 [10:0000] */ + break; + case 4: /* ts1 */ + case 6: /* ts1 parallel mode */ + ep_mask = ENABLE_EP1; /* ep1 [00:0001] */ + break; + case 5: /* ts2 */ + ep_mask = ENABLE_EP2; /* ep2 [00:0010] */ + break; + } + + } + + if (start) { + rc = cx231xx_initialize_stream_xfer(dev, media_type); + + if (rc < 0) { + return rc; + } + + /* enable video capture */ + if (ep_mask > 0) + rc = cx231xx_start_stream(dev, ep_mask); + } else { + /* disable video capture */ + if (ep_mask > 0) + rc = cx231xx_stop_stream(dev, ep_mask); + } + + if (dev->mode == CX231XX_ANALOG_MODE) { + /* do any in Analog mode */ + } else { + /* do any in digital mode */ + } return rc; } -EXPORT_SYMBOL_GPL(cx231xx_capture_start); +EXPORT_SYMBOL_GPL(cx231xx_capture_start); /************************************************************************************ * G P I O B I T control functions * *************************************************************************************/ -int cx231xx_set_gpio_bit(struct cx231xx *dev, u32 gpio_bit, u8* gpio_val) +int cx231xx_set_gpio_bit(struct cx231xx *dev, u32 gpio_bit, u8 * gpio_val) { - int status = 0; + int status = 0; - status = cx231xx_send_gpio_cmd(dev, gpio_bit, gpio_val, 4, 0, 0); + status = cx231xx_send_gpio_cmd(dev, gpio_bit, gpio_val, 4, 0, 0); - return status; + return status; } -int cx231xx_get_gpio_bit(struct cx231xx *dev, u32 gpio_bit, u8* gpio_val) +int cx231xx_get_gpio_bit(struct cx231xx *dev, u32 gpio_bit, u8 * gpio_val) { - int status = 0; + int status = 0; - status = cx231xx_send_gpio_cmd(dev, gpio_bit, gpio_val, 4, 0, 1); + status = cx231xx_send_gpio_cmd(dev, gpio_bit, gpio_val, 4, 0, 1); - return status; + return status; } /* @@ -1873,32 +2615,30 @@ int cx231xx_get_gpio_bit(struct cx231xx *dev, u32 gpio_bit, u8* gpio_val) * 1 = Output direction */ int cx231xx_set_gpio_direction(struct cx231xx *dev, - int pin_number, - int pin_value) + int pin_number, int pin_value) { int status = 0; - u32 value = 0; + u32 value = 0; - /* Check for valid pin_number - if 32 , bail out */ - if (pin_number >= 32) { - return -EINVAL; - } + /* Check for valid pin_number - if 32 , bail out */ + if (pin_number >= 32) { + return -EINVAL; + } - if (pin_value == 0) { /* input */ - value = dev->gpio_dir &(~(1<gpio_dir | (1<gpio_dir & (~(1 << pin_number)); /* clear */ + } else { + value = dev->gpio_dir | (1 << pin_number); + } - status = cx231xx_set_gpio_bit(dev, value, (u8*) & dev->gpio_val); + status = cx231xx_set_gpio_bit(dev, value, (u8 *) & dev->gpio_val); - /* cache the value for future */ + /* cache the value for future */ dev->gpio_dir = value; - return status; + return status; } - /* * SetGpioPinLogicValue * Sets the value of the GPIO pin to Logic high or low. The Pin under @@ -1910,42 +2650,41 @@ int cx231xx_set_gpio_direction(struct cx231xx *dev, * 0 = set it to 0 * 1 = set it to 1 */ -int cx231xx_set_gpio_value(struct cx231xx *dev, - int pin_number, - int pin_value) +int cx231xx_set_gpio_value(struct cx231xx *dev, int pin_number, int pin_value) { - int status = 0; - u32 value = 0; - - /* Check for valid pin_number - if 0xFF , bail out */ - if (pin_number >= 32) - return -EINVAL; - - /* first do a sanity check - if the Pin is not output, make it output */ - if ((dev->gpio_dir & (1<gpio_dir | (1<gpio_dir = value; - status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8*) &dev->gpio_val); - value = 0; - } - - if (pin_value == 0) { - value = dev->gpio_val & (~(1<gpio_val | (1<gpio_val=value; - - /* toggle bit0 of GP_IO */ - status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8*) &dev->gpio_val); - - return status; -} + int status = 0; + u32 value = 0; + + /* Check for valid pin_number - if 0xFF , bail out */ + if (pin_number >= 32) + return -EINVAL; + + /* first do a sanity check - if the Pin is not output, make it output */ + if ((dev->gpio_dir & (1 << pin_number)) == 0x00) { + /* It was in input mode */ + value = dev->gpio_dir | (1 << pin_number); + dev->gpio_dir = value; + status = + cx231xx_set_gpio_bit(dev, dev->gpio_dir, + (u8 *) & dev->gpio_val); + value = 0; + } + if (pin_value == 0) { + value = dev->gpio_val & (~(1 << pin_number)); + } else { + value = dev->gpio_val | (1 << pin_number); + } + + /* store the value */ + dev->gpio_val = value; + + /* toggle bit0 of GP_IO */ + status = + cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8 *) & dev->gpio_val); + + return status; +} /************************************************************************************ * G P I O I2C related functions * @@ -1955,288 +2694,324 @@ int cx231xx_gpio_i2c_start(struct cx231xx *dev) int status = 0; /* set SCL to output 1 ; set SDA to output 1 */ - dev->gpio_dir |= 1<< dev->board.tuner_scl_gpio; - dev->gpio_dir |= 1<board.tuner_sda_gpio; - dev->gpio_val |= 1<board.tuner_scl_gpio; - dev->gpio_val |= 1<board.tuner_sda_gpio; - - status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8*) &dev->gpio_val); - if(status < 0){ + dev->gpio_dir |= 1 << dev->board.tuner_scl_gpio; + dev->gpio_dir |= 1 << dev->board.tuner_sda_gpio; + dev->gpio_val |= 1 << dev->board.tuner_scl_gpio; + dev->gpio_val |= 1 << dev->board.tuner_sda_gpio; + + status = + cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8 *) & dev->gpio_val); + if (status < 0) { return -EINVAL; } /* set SCL to output 1; set SDA to output 0 */ - dev->gpio_val |= 1<board.tuner_scl_gpio; - dev->gpio_val &= ~(1<board.tuner_sda_gpio); - - status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8*) &dev->gpio_val); - if(status < 0){ + dev->gpio_val |= 1 << dev->board.tuner_scl_gpio; + dev->gpio_val &= ~(1 << dev->board.tuner_sda_gpio); + + status = + cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8 *) & dev->gpio_val); + if (status < 0) { return -EINVAL; } - /* set SCL to output 0; set SDA to output 0 */ - dev->gpio_val &= ~(1<board.tuner_scl_gpio); - dev->gpio_val &= ~(1<board.tuner_sda_gpio); - - status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8*) &dev->gpio_val); - if(status < 0){ + /* set SCL to output 0; set SDA to output 0 */ + dev->gpio_val &= ~(1 << dev->board.tuner_scl_gpio); + dev->gpio_val &= ~(1 << dev->board.tuner_sda_gpio); + + status = + cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8 *) & dev->gpio_val); + if (status < 0) { return -EINVAL; } - + return status; } - int cx231xx_gpio_i2c_end(struct cx231xx *dev) { - int status = 0; - - /* set SCL to output 0; set SDA to output 0 */ - dev->gpio_dir |= 1<board.tuner_scl_gpio; - dev->gpio_dir |= 1<board.tuner_sda_gpio; - - dev->gpio_val &= ~(1<board.tuner_scl_gpio); - dev->gpio_val &= ~(1<board.tuner_sda_gpio); - - status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8*) &dev->gpio_val); - if(status < 0){ + int status = 0; + + /* set SCL to output 0; set SDA to output 0 */ + dev->gpio_dir |= 1 << dev->board.tuner_scl_gpio; + dev->gpio_dir |= 1 << dev->board.tuner_sda_gpio; + + dev->gpio_val &= ~(1 << dev->board.tuner_scl_gpio); + dev->gpio_val &= ~(1 << dev->board.tuner_sda_gpio); + + status = + cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8 *) & dev->gpio_val); + if (status < 0) { return -EINVAL; } - /* set SCL to output 1; set SDA to output 0 */ - dev->gpio_val |= 1<board.tuner_scl_gpio; - dev->gpio_val &= ~(1<board.tuner_sda_gpio); - - status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8*) &dev->gpio_val); - if(status < 0){ + /* set SCL to output 1; set SDA to output 0 */ + dev->gpio_val |= 1 << dev->board.tuner_scl_gpio; + dev->gpio_val &= ~(1 << dev->board.tuner_sda_gpio); + + status = + cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8 *) & dev->gpio_val); + if (status < 0) { return -EINVAL; } - - /* set SCL to input ,release SCL cable control + + /* set SCL to input ,release SCL cable control set SDA to input ,release SDA cable control */ - dev->gpio_dir &= ~(1<board.tuner_scl_gpio); - dev->gpio_dir &= ~(1<board.tuner_sda_gpio); - - status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8*) &dev->gpio_val); - if(status < 0){ + dev->gpio_dir &= ~(1 << dev->board.tuner_scl_gpio); + dev->gpio_dir &= ~(1 << dev->board.tuner_sda_gpio); + + status = + cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8 *) & dev->gpio_val); + if (status < 0) { return -EINVAL; } - return status; + return status; } - int cx231xx_gpio_i2c_write_byte(struct cx231xx *dev, u8 data) { - int status = 0; - u8 i; + int status = 0; + u8 i; /* set SCL to output ; set SDA to output */ - dev->gpio_dir |= 1<board.tuner_scl_gpio; - dev->gpio_dir |= 1<board.tuner_sda_gpio; - - for(i = 0;i<8;i++) { - if(((data<gpio_val &= ~(1<board.tuner_scl_gpio); - dev->gpio_val &= ~(1<board.tuner_sda_gpio); - status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8*) &dev->gpio_val); - - /* set SCL to output 1; set SDA to output 0 */ - dev->gpio_val |= 1<board.tuner_scl_gpio; - status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8*) &dev->gpio_val); - - /* set SCL to output 0; set SDA to output 0 */ - dev->gpio_val &= ~(1<board.tuner_scl_gpio); - status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8*) &dev->gpio_val); + dev->gpio_dir |= 1 << dev->board.tuner_scl_gpio; + dev->gpio_dir |= 1 << dev->board.tuner_sda_gpio; + + for (i = 0; i < 8; i++) { + if (((data << i) & 0x80) == 0) { + /* set SCL to output 0; set SDA to output 0 */ + dev->gpio_val &= ~(1 << dev->board.tuner_scl_gpio); + dev->gpio_val &= ~(1 << dev->board.tuner_sda_gpio); + status = + cx231xx_set_gpio_bit(dev, dev->gpio_dir, + (u8 *) & dev->gpio_val); + + /* set SCL to output 1; set SDA to output 0 */ + dev->gpio_val |= 1 << dev->board.tuner_scl_gpio; + status = + cx231xx_set_gpio_bit(dev, dev->gpio_dir, + (u8 *) & dev->gpio_val); + + /* set SCL to output 0; set SDA to output 0 */ + dev->gpio_val &= ~(1 << dev->board.tuner_scl_gpio); + status = + cx231xx_set_gpio_bit(dev, dev->gpio_dir, + (u8 *) & dev->gpio_val); } else { - /* set SCL to output 0; set SDA to output 1 */ - dev->gpio_val &= ~(1<board.tuner_scl_gpio); - dev->gpio_val |= 1<board.tuner_sda_gpio; - status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8*) &dev->gpio_val); - - /* set SCL to output 1; set SDA to output 1 */ - dev->gpio_val |= 1<board.tuner_scl_gpio; - status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8*) &dev->gpio_val); - - /* set SCL to output 0; set SDA to output 1 */ - dev->gpio_val &= ~(1<board.tuner_scl_gpio); - status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8*) &dev->gpio_val); - } + /* set SCL to output 0; set SDA to output 1 */ + dev->gpio_val &= ~(1 << dev->board.tuner_scl_gpio); + dev->gpio_val |= 1 << dev->board.tuner_sda_gpio; + status = + cx231xx_set_gpio_bit(dev, dev->gpio_dir, + (u8 *) & dev->gpio_val); + + /* set SCL to output 1; set SDA to output 1 */ + dev->gpio_val |= 1 << dev->board.tuner_scl_gpio; + status = + cx231xx_set_gpio_bit(dev, dev->gpio_dir, + (u8 *) & dev->gpio_val); + + /* set SCL to output 0; set SDA to output 1 */ + dev->gpio_val &= ~(1 << dev->board.tuner_scl_gpio); + status = + cx231xx_set_gpio_bit(dev, dev->gpio_dir, + (u8 *) & dev->gpio_val); + } } return status; } -int cx231xx_gpio_i2c_read_byte(struct cx231xx *dev, u8 *buf) +int cx231xx_gpio_i2c_read_byte(struct cx231xx *dev, u8 * buf) { u8 value = 0; - int status = 0; - u32 gpio_logic_value =0; - u8 i; + int status = 0; + u32 gpio_logic_value = 0; + u8 i; /* read byte */ - for(i=0;i<8;i++) { /* send write I2c addr */ + for (i = 0; i < 8; i++) { /* send write I2c addr */ /* set SCL to output 0; set SDA to input */ - dev->gpio_val &= ~(1<board.tuner_scl_gpio); - status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8*) &dev->gpio_val); - + dev->gpio_val &= ~(1 << dev->board.tuner_scl_gpio); + status = + cx231xx_set_gpio_bit(dev, dev->gpio_dir, + (u8 *) & dev->gpio_val); + /* set SCL to output 1; set SDA to input */ - dev->gpio_val |= 1<board.tuner_scl_gpio; - status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8*) &dev->gpio_val); - + dev->gpio_val |= 1 << dev->board.tuner_scl_gpio; + status = + cx231xx_set_gpio_bit(dev, dev->gpio_dir, + (u8 *) & dev->gpio_val); + /* get SDA data bit */ gpio_logic_value = dev->gpio_val; - status = cx231xx_get_gpio_bit(dev, dev->gpio_dir, (u8*) &dev->gpio_val); - if((dev->gpio_val & (1<board.tuner_sda_gpio)) != 0) { - value |= (1<<(8-i-1)); + status = + cx231xx_get_gpio_bit(dev, dev->gpio_dir, + (u8 *) & dev->gpio_val); + if ((dev->gpio_val & (1 << dev->board.tuner_sda_gpio)) != 0) { + value |= (1 << (8 - i - 1)); } - - dev->gpio_val = gpio_logic_value; + + dev->gpio_val = gpio_logic_value; } /* set SCL to output 0,finish the read latest SCL signal. !!!set SDA to input,never to modify SDA direction at the same times */ - dev->gpio_val &= ~(1<board.tuner_scl_gpio); - status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8*) &dev->gpio_val); - - /* store the value */ - *buf = value & 0xff; - + dev->gpio_val &= ~(1 << dev->board.tuner_scl_gpio); + status = + cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8 *) & dev->gpio_val); + + /* store the value */ + *buf = value & 0xff; + return status; } int cx231xx_gpio_i2c_read_ack(struct cx231xx *dev) { - int status = 0; + int status = 0; u32 gpio_logic_value = 0; - int nCnt=10; - int nInit=nCnt; + int nCnt = 10; + int nInit = nCnt; /* clock stretch; set SCL to input; set SDA to input; get SCL value till SCL = 1 */ - dev->gpio_dir &= ~(1<board.tuner_sda_gpio); - dev->gpio_dir &= ~(1<board.tuner_scl_gpio); + dev->gpio_dir &= ~(1 << dev->board.tuner_sda_gpio); + dev->gpio_dir &= ~(1 << dev->board.tuner_scl_gpio); gpio_logic_value = dev->gpio_val; - status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8*) &dev->gpio_val); - - do{ + status = + cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8 *) & dev->gpio_val); + + do { msleep(2); - status = cx231xx_get_gpio_bit(dev, dev->gpio_dir, (u8*) &dev->gpio_val); - nCnt--; - }while(((dev->gpio_val & (1<board.tuner_scl_gpio)) == 0) && (nCnt>0)); - - if(nCnt==0) { - cx231xx_info("No ACK after %d msec for clock stretch. GPIO I2C operation failed!",nInit*10); - } - + status = + cx231xx_get_gpio_bit(dev, dev->gpio_dir, + (u8 *) & dev->gpio_val); + nCnt--; + } while (((dev->gpio_val & (1 << dev->board.tuner_scl_gpio)) == 0) + && (nCnt > 0)); + + if (nCnt == 0) { + cx231xx_info + ("No ACK after %d msec for clock stretch. GPIO I2C operation failed!", + nInit * 10); + } + /* readAck throuth clock stretch ,slave has given a SCL signal,so the SDA data can be directly read. */ - status = cx231xx_get_gpio_bit(dev, dev->gpio_dir, (u8*) &dev->gpio_val); - - if((dev->gpio_val & 1<< dev->board.tuner_sda_gpio) == 0){ + status = + cx231xx_get_gpio_bit(dev, dev->gpio_dir, (u8 *) & dev->gpio_val); + + if ((dev->gpio_val & 1 << dev->board.tuner_sda_gpio) == 0) { dev->gpio_val = gpio_logic_value; - dev->gpio_val &= ~(1<< dev->board.tuner_sda_gpio); + dev->gpio_val &= ~(1 << dev->board.tuner_sda_gpio); status = 0; } else { dev->gpio_val = gpio_logic_value; - dev->gpio_val |= (1<< dev->board.tuner_sda_gpio); + dev->gpio_val |= (1 << dev->board.tuner_sda_gpio); } /* read SDA end, set the SCL to output 0, after this operation, SDA direction can be changed. */ dev->gpio_val = gpio_logic_value; - dev->gpio_dir |= (1<board.tuner_scl_gpio); - dev->gpio_val &= ~(1<board.tuner_scl_gpio); - status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8*) &dev->gpio_val); - + dev->gpio_dir |= (1 << dev->board.tuner_scl_gpio); + dev->gpio_val &= ~(1 << dev->board.tuner_scl_gpio); + status = + cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8 *) & dev->gpio_val); + return status; } - int cx231xx_gpio_i2c_write_ack(struct cx231xx *dev) { - int status = 0; - + int status = 0; + /* set SDA to ouput */ - dev->gpio_dir |= 1<board.tuner_sda_gpio; - status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8*) &dev->gpio_val); - + dev->gpio_dir |= 1 << dev->board.tuner_sda_gpio; + status = + cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8 *) & dev->gpio_val); + /* set SCL = 0 (output); set SDA = 0 (output) */ - dev->gpio_val &= ~(1<board.tuner_sda_gpio); - dev->gpio_val &= ~(1<board.tuner_scl_gpio); - status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8*) &dev->gpio_val); - + dev->gpio_val &= ~(1 << dev->board.tuner_sda_gpio); + dev->gpio_val &= ~(1 << dev->board.tuner_scl_gpio); + status = + cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8 *) & dev->gpio_val); + /* set SCL = 1 (output); set SDA = 0 (output) */ - dev->gpio_val |= 1<board.tuner_scl_gpio; - status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8*) &dev->gpio_val); - + dev->gpio_val |= 1 << dev->board.tuner_scl_gpio; + status = + cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8 *) & dev->gpio_val); + /* set SCL = 0 (output); set SDA = 0 (output) */ - dev->gpio_val &= ~(1<board.tuner_scl_gpio); - status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8*) &dev->gpio_val); - + dev->gpio_val &= ~(1 << dev->board.tuner_scl_gpio); + status = + cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8 *) & dev->gpio_val); + /* set SDA to input,and then the slave will read data from SDA. */ - dev->gpio_dir &= ~(1<board.tuner_sda_gpio); - status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8*) &dev->gpio_val); - - return status; + dev->gpio_dir &= ~(1 << dev->board.tuner_sda_gpio); + status = + cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8 *) & dev->gpio_val); + + return status; } int cx231xx_gpio_i2c_write_nak(struct cx231xx *dev) { - int status = 0; - + int status = 0; + /* set scl to output ; set sda to input */ - dev->gpio_dir |= 1<board.tuner_scl_gpio; - dev->gpio_dir &= ~(1<board.tuner_sda_gpio); - status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8*) &dev->gpio_val); - + dev->gpio_dir |= 1 << dev->board.tuner_scl_gpio; + dev->gpio_dir &= ~(1 << dev->board.tuner_sda_gpio); + status = + cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8 *) & dev->gpio_val); + /* set scl to output 0; set sda to input */ - dev->gpio_val &= ~(1<board.tuner_scl_gpio); - status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8*) &dev->gpio_val); - + dev->gpio_val &= ~(1 << dev->board.tuner_scl_gpio); + status = + cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8 *) & dev->gpio_val); + /* set scl to output 1; set sda to input */ - dev->gpio_val |= 1<board.tuner_scl_gpio; - status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8*) &dev->gpio_val); + dev->gpio_val |= 1 << dev->board.tuner_scl_gpio; + status = + cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8 *) & dev->gpio_val); - return status; + return status; } - - /************************************************************************************ * G P I O I2C related functions * *************************************************************************************/ /* cx231xx_gpio_i2c_read - * Function to read data from gpio based I2C interface + * Function to read data from gpio based I2C interface */ -int cx231xx_gpio_i2c_read(struct cx231xx *dev, u8 dev_addr, u8 *buf ,u8 len) +int cx231xx_gpio_i2c_read(struct cx231xx *dev, u8 dev_addr, u8 * buf, u8 len) { - int status = 0; - int i = 0; + int status = 0; + int i = 0; - /* get the lock */ + /* get the lock */ mutex_lock(&dev->gpio_i2c_lock); - + /* start */ status = cx231xx_gpio_i2c_start(dev); - + /* write dev_addr */ - status = cx231xx_gpio_i2c_write_byte(dev, (dev_addr << 1) +1); - + status = cx231xx_gpio_i2c_write_byte(dev, (dev_addr << 1) + 1); + /* readAck */ status = cx231xx_gpio_i2c_read_ack(dev); - /* read data */ - for(i = 0; i < len; i++ ) { - /* read data */ - buf[i] = 0; - status = cx231xx_gpio_i2c_read_byte(dev, & buf[i]); - - if( (i+1) != len) { - /* only do write ack if we more length */ - status = cx231xx_gpio_i2c_write_ack(dev); - } - } - + /* read data */ + for (i = 0; i < len; i++) { + /* read data */ + buf[i] = 0; + status = cx231xx_gpio_i2c_read_byte(dev, &buf[i]); + + if ((i + 1) != len) { + /* only do write ack if we more length */ + status = cx231xx_gpio_i2c_write_ack(dev); + } + } + /* write NAK - inform reads are complete */ status = cx231xx_gpio_i2c_write_nak(dev); @@ -2245,45 +3020,43 @@ int cx231xx_gpio_i2c_read(struct cx231xx *dev, u8 dev_addr, u8 *buf ,u8 len) /* release the lock */ mutex_unlock(&dev->gpio_i2c_lock); - + return status; } - /* cx231xx_gpio_i2c_write - * Function to write data to gpio based I2C interface + * Function to write data to gpio based I2C interface */ -int cx231xx_gpio_i2c_write(struct cx231xx *dev, u8 dev_addr, u8 *buf ,u8 len) +int cx231xx_gpio_i2c_write(struct cx231xx *dev, u8 dev_addr, u8 * buf, u8 len) { - int status = 0; - int i=0; - + int status = 0; + int i = 0; + /* get the lock */ mutex_lock(&dev->gpio_i2c_lock); /* start */ status = cx231xx_gpio_i2c_start(dev); - + /* write dev_addr */ status = cx231xx_gpio_i2c_write_byte(dev, dev_addr << 1); - + /* read Ack */ - status = cx231xx_gpio_i2c_read_ack(dev); + status = cx231xx_gpio_i2c_read_ack(dev); - for(i = 0; i < len; i++ ) { - /* Write data */ - status = cx231xx_gpio_i2c_write_byte(dev, buf[i]); + for (i = 0; i < len; i++) { + /* Write data */ + status = cx231xx_gpio_i2c_write_byte(dev, buf[i]); - /* read Ack */ - status = cx231xx_gpio_i2c_read_ack(dev); - } + /* read Ack */ + status = cx231xx_gpio_i2c_read_ack(dev); + } - /* write End */ + /* write End */ status = cx231xx_gpio_i2c_end(dev); /* release the lock */ mutex_unlock(&dev->gpio_i2c_lock); - + return 0; } - diff --git a/linux/drivers/media/video/cx231xx/cx231xx-cards.c b/linux/drivers/media/video/cx231xx/cx231xx-cards.c index b204c7be8..9ecbb4b75 100644 --- a/linux/drivers/media/video/cx231xx/cx231xx-cards.c +++ b/linux/drivers/media/video/cx231xx/cx231xx-cards.c @@ -2,7 +2,7 @@ cx231xx-cards.c - driver for Conexant Cx23100/101/102 USB video capture devices Copyright (C) 2008 - Based on em28xx driver + Based on em28xx driver 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 @@ -51,157 +51,182 @@ static unsigned long cx231xx_devused; */ static struct cx231xx_reg_seq RDE250_XCV_TUNER[] = { - { 0x03, 0x01, 10 }, - { 0x03, 0x00, 30 }, - { 0x03, 0x01, 10 }, - { -1, -1, -1 }, + {0x03, 0x01, 10}, + {0x03, 0x00, 30}, + {0x03, 0x01, 10}, + {-1, -1, -1}, }; - - /* * Board definitions */ struct cx231xx_board cx231xx_boards[] = { [CX231XX_BOARD_UNKNOWN] = { - .name = "Unknown CX231xx video grabber", - .tuner_type = TUNER_ABSENT, - .input = { { - .type = CX231XX_VMUX_TELEVISION, - .vmux = CX231XX_VIN_3_1, - .amux = CX231XX_AMUX_VIDEO, - .gpio = 0, - }, { - .type = CX231XX_VMUX_COMPOSITE1, - .vmux = CX231XX_VIN_2_1, - .amux = CX231XX_AMUX_LINE_IN, - .gpio = 0, - }, { - .type = CX231XX_VMUX_SVIDEO, - .vmux = CX231XX_VIN_1_1 | (CX231XX_VIN_1_2 << 8 ) | - CX25840_SVIDEO_ON, - .amux = CX231XX_AMUX_LINE_IN, - .gpio = 0, - } }, - }, + .name = "Unknown CX231xx video grabber", + .tuner_type = TUNER_ABSENT, + .input = {{ + .type = CX231XX_VMUX_TELEVISION, + .vmux = CX231XX_VIN_3_1, + .amux = CX231XX_AMUX_VIDEO, + .gpio = 0, + }, { + .type = + CX231XX_VMUX_COMPOSITE1, + .vmux = CX231XX_VIN_2_1, + .amux = CX231XX_AMUX_LINE_IN, + .gpio = 0, + }, { + .type = + CX231XX_VMUX_SVIDEO, + .vmux = + CX231XX_VIN_1_1 | + (CX231XX_VIN_1_2 << 8) | + CX25840_SVIDEO_ON, + .amux = + CX231XX_AMUX_LINE_IN, + .gpio = 0, + }}, + }, [CX231XX_BOARD_CNXT_RDE_250] = { - .name = "Conexant Hybrid TV - RDE250", - .valid = CX231XX_BOARD_VALIDATED, - .tuner_type = TUNER_XC5000, - .tuner_addr = 0x61, - .tuner_gpio = RDE250_XCV_TUNER, - .tuner_sif_gpio = 0x05, - .tuner_scl_gpio = 0x1a, - .tuner_sda_gpio = 0x1b, - .decoder = CX231XX_AVDECODER, - .demod_xfer_mode = 0, - .ctl_pin_status_mask = 0xFFFFFFC4, - .agc_analog_digital_select_gpio = 0x0c, - .gpio_pin_status_mask = 0x4001000, - .tuner_i2c_master = 1, - .demod_i2c_master = 2, - .has_dvb = 1, - .demod_addr = 0x02, - .norm = V4L2_STD_PAL, - - .input = { { - .type = CX231XX_VMUX_TELEVISION, - .vmux = CX231XX_VIN_3_1, - .amux = CX231XX_AMUX_VIDEO, - .gpio = 0, - }, { - .type = CX231XX_VMUX_COMPOSITE1, - .vmux = CX231XX_VIN_2_1, - .amux = CX231XX_AMUX_LINE_IN, - .gpio = 0, - }, { - .type = CX231XX_VMUX_SVIDEO, - .vmux = CX231XX_VIN_1_1 | (CX231XX_VIN_1_2 << 8 ) | - CX25840_SVIDEO_ON, - .amux = CX231XX_AMUX_LINE_IN, - .gpio = 0, - } }, - }, - - [CX231XX_BOARD_CNXT_RDU_250] = { - .name = "Conexant Hybrid TV - RDU250", - .valid = CX231XX_BOARD_VALIDATED, - .tuner_type = TUNER_XC5000, - .tuner_addr = 0x61, - .tuner_gpio = RDE250_XCV_TUNER, - .tuner_sif_gpio = 0x05, - .tuner_scl_gpio = 0x1a, - .tuner_sda_gpio = 0x1b, - .decoder = CX231XX_AVDECODER, - .demod_xfer_mode = 0, - .ctl_pin_status_mask = 0xFFFFFFC4, - .agc_analog_digital_select_gpio = 0x0c, - .gpio_pin_status_mask = 0x4001000, - .tuner_i2c_master = 1, - .demod_i2c_master = 2, - .has_dvb = 1, - .demod_addr = 0x32, - .norm = V4L2_STD_NTSC, - - .input = { { - .type = CX231XX_VMUX_TELEVISION, - .vmux = CX231XX_VIN_3_1, - .amux = CX231XX_AMUX_VIDEO, - .gpio = 0, - }, { - .type = CX231XX_VMUX_COMPOSITE1, - .vmux = CX231XX_VIN_2_1, - .amux = CX231XX_AMUX_LINE_IN, - .gpio = 0, - }, { - .type = CX231XX_VMUX_SVIDEO, - .vmux = CX231XX_VIN_1_1 | (CX231XX_VIN_1_2 << 8 ) | - CX25840_SVIDEO_ON, - .amux = CX231XX_AMUX_LINE_IN, - .gpio = 0, - } }, - }, + .name = "Conexant Hybrid TV - RDE250", + .valid = CX231XX_BOARD_VALIDATED, + .tuner_type = TUNER_XC5000, + .tuner_addr = 0x61, + .tuner_gpio = RDE250_XCV_TUNER, + .tuner_sif_gpio = 0x05, + .tuner_scl_gpio = 0x1a, + .tuner_sda_gpio = 0x1b, + .decoder = CX231XX_AVDECODER, + .demod_xfer_mode = 0, + .ctl_pin_status_mask = 0xFFFFFFC4, + .agc_analog_digital_select_gpio = 0x0c, + .gpio_pin_status_mask = 0x4001000, + .tuner_i2c_master = 1, + .demod_i2c_master = 2, + .has_dvb = 1, + .demod_addr = 0x02, + .norm = V4L2_STD_PAL, + + .input = {{ + .type = + CX231XX_VMUX_TELEVISION, + .vmux = CX231XX_VIN_3_1, + .amux = CX231XX_AMUX_VIDEO, + .gpio = 0, + }, { + .type = + CX231XX_VMUX_COMPOSITE1, + .vmux = CX231XX_VIN_2_1, + .amux = + CX231XX_AMUX_LINE_IN, + .gpio = 0, + }, { + .type = + CX231XX_VMUX_SVIDEO, + .vmux = + CX231XX_VIN_1_1 | + (CX231XX_VIN_1_2 << + 8) | + CX25840_SVIDEO_ON, + .amux = + CX231XX_AMUX_LINE_IN, + .gpio = 0, + }}, + }, + + [CX231XX_BOARD_CNXT_RDU_250] = { + .name = "Conexant Hybrid TV - RDU250", + .valid = CX231XX_BOARD_VALIDATED, + .tuner_type = TUNER_XC5000, + .tuner_addr = 0x61, + .tuner_gpio = RDE250_XCV_TUNER, + .tuner_sif_gpio = 0x05, + .tuner_scl_gpio = 0x1a, + .tuner_sda_gpio = 0x1b, + .decoder = CX231XX_AVDECODER, + .demod_xfer_mode = 0, + .ctl_pin_status_mask = 0xFFFFFFC4, + .agc_analog_digital_select_gpio = 0x0c, + .gpio_pin_status_mask = 0x4001000, + .tuner_i2c_master = 1, + .demod_i2c_master = 2, + .has_dvb = 1, + .demod_addr = 0x32, + .norm = V4L2_STD_NTSC, + + .input = {{ + .type = + CX231XX_VMUX_TELEVISION, + .vmux = CX231XX_VIN_3_1, + .amux = CX231XX_AMUX_VIDEO, + .gpio = 0, + }, { + .type = + CX231XX_VMUX_COMPOSITE1, + .vmux = CX231XX_VIN_2_1, + .amux = + CX231XX_AMUX_LINE_IN, + .gpio = 0, + }, { + .type = + CX231XX_VMUX_SVIDEO, + .vmux = + CX231XX_VIN_1_1 | + (CX231XX_VIN_1_2 << + 8) | + CX25840_SVIDEO_ON, + .amux = + CX231XX_AMUX_LINE_IN, + .gpio = 0, + }}, + }, }; const unsigned int cx231xx_bcount = ARRAY_SIZE(cx231xx_boards); /* table of devices that work with this driver */ -struct usb_device_id cx231xx_id_table [] = { - { USB_DEVICE(0x0572, 0x58A0), - .driver_info = CX231XX_BOARD_UNKNOWN }, - { USB_DEVICE(0x0572, 0x58A2), - .driver_info = CX231XX_BOARD_CNXT_RDE_250 }, - { USB_DEVICE(0x0572, 0x5A3C), - .driver_info = CX231XX_BOARD_CNXT_RDU_250 }, - { }, +struct usb_device_id cx231xx_id_table[] = { + {USB_DEVICE(0x0572, 0x58A0), + .driver_info = CX231XX_BOARD_UNKNOWN}, + {USB_DEVICE(0x0572, 0x58A2), + .driver_info = CX231XX_BOARD_CNXT_RDE_250}, + {USB_DEVICE(0x0572, 0x5A3C), + .driver_info = CX231XX_BOARD_CNXT_RDU_250}, + {}, }; + MODULE_DEVICE_TABLE(usb, cx231xx_id_table); /* cx231xx_tuner_callback - * will be used to reset XC5000 tuner using GPIO pin + * will be used to reset XC5000 tuner using GPIO pin */ int cx231xx_tuner_callback(void *ptr, int component, int command, int arg) { int rc = 0; - struct cx231xx *dev = ptr; - - if (dev->tuner_type == TUNER_XC5000) { - if (command == XC5000_TUNER_RESET) { - cx231xx_info("Tuner Call back : RESET : command %d : tuner type %d \n", - command, dev->tuner_type); - - cx231xx_set_gpio_value(dev, dev->board.tuner_gpio->bit,1); - msleep(10); - cx231xx_set_gpio_value(dev, dev->board.tuner_gpio->bit,0); - msleep(330); - cx231xx_set_gpio_value(dev, dev->board.tuner_gpio->bit,1); - msleep(10); - } - } + struct cx231xx *dev = ptr; + + if (dev->tuner_type == TUNER_XC5000) { + if (command == XC5000_TUNER_RESET) { + cx231xx_info + ("Tuner Call back : RESET : command %d : tuner type %d \n", + command, dev->tuner_type); + + cx231xx_set_gpio_value(dev, dev->board.tuner_gpio->bit, + 1); + msleep(10); + cx231xx_set_gpio_value(dev, dev->board.tuner_gpio->bit, + 0); + msleep(330); + cx231xx_set_gpio_value(dev, dev->board.tuner_gpio->bit, + 1); + msleep(10); + } + } return rc; } + EXPORT_SYMBOL_GPL(cx231xx_tuner_callback); static void inline cx231xx_set_model(struct cx231xx *dev) @@ -218,34 +243,34 @@ void cx231xx_pre_card_setup(struct cx231xx *dev) cx231xx_set_model(dev); cx231xx_info("Identified as %s (card=%d)\n", - dev->board.name, dev->model); + dev->board.name, dev->model); /* Do card specific if any */ switch (dev->model) { - case CX231XX_BOARD_CNXT_RDE_250: - /* do card specific GPIO settings if required */ - cx231xx_info("Precard: Board is Conexnat RDE 250\n"); - /* set the direction for GPIO pins */ - cx231xx_set_gpio_direction(dev, dev->board.tuner_gpio->bit,1); - cx231xx_set_gpio_value(dev, dev->board.tuner_gpio->bit,1); - cx231xx_set_gpio_direction(dev, dev->board.tuner_sif_gpio,1); - break; - case CX231XX_BOARD_CNXT_RDU_250: - /* do card specific GPIO settings if required */ - cx231xx_info("Precard: Board is Conexnat RDU 250\n"); - /* set the direction for GPIO pins */ - cx231xx_set_gpio_direction(dev, dev->board.tuner_gpio->bit,1); - cx231xx_set_gpio_value(dev, dev->board.tuner_gpio->bit,1); - cx231xx_set_gpio_direction(dev, dev->board.tuner_sif_gpio,1); - break; + case CX231XX_BOARD_CNXT_RDE_250: + /* do card specific GPIO settings if required */ + cx231xx_info("Precard: Board is Conexnat RDE 250\n"); + /* set the direction for GPIO pins */ + cx231xx_set_gpio_direction(dev, dev->board.tuner_gpio->bit, 1); + cx231xx_set_gpio_value(dev, dev->board.tuner_gpio->bit, 1); + cx231xx_set_gpio_direction(dev, dev->board.tuner_sif_gpio, 1); + break; + case CX231XX_BOARD_CNXT_RDU_250: + /* do card specific GPIO settings if required */ + cx231xx_info("Precard: Board is Conexnat RDU 250\n"); + /* set the direction for GPIO pins */ + cx231xx_set_gpio_direction(dev, dev->board.tuner_gpio->bit, 1); + cx231xx_set_gpio_value(dev, dev->board.tuner_gpio->bit, 1); + cx231xx_set_gpio_direction(dev, dev->board.tuner_sif_gpio, 1); + break; } /* request some modules if any required */ - /* reset the Tuner */ + /* reset the Tuner */ cx231xx_gpio_set(dev, dev->board.tuner_gpio); - /* set the mode to Analog mode initially */ + /* set the mode to Analog mode initially */ cx231xx_set_mode(dev, CX231XX_ANALOG_MODE); /* Unlock device */ @@ -253,12 +278,12 @@ void cx231xx_pre_card_setup(struct cx231xx *dev) } -#if 0 /* Keep */ +#if 0 /* Keep */ static void cx231xx_config_tuner(struct cx231xx *dev) { - struct tuner_setup tun_setup; - struct v4l2_frequency f; + struct tuner_setup tun_setup; + struct v4l2_frequency f; if (dev->tuner_type == TUNER_ABSENT) return; @@ -268,26 +293,28 @@ static void cx231xx_config_tuner(struct cx231xx *dev) tun_setup.addr = dev->tuner_addr; tun_setup.tuner_callback = cx231xx_tuner_callback; - cx231xx_i2c_call_clients(&dev->i2c_bus[1], TUNER_SET_TYPE_ADDR, &tun_setup); -#if 0 /* Keep */ - if (tun_setup.type == TUNER_XC5000) { + cx231xx_i2c_call_clients(&dev->i2c_bus[1], TUNER_SET_TYPE_ADDR, + &tun_setup); +#if 0 /* Keep */ + if (tun_setup.type == TUNER_XC5000) { static struct xc2028_ctrl ctrl = { .fname = XC5000_DEFAULT_FIRMWARE, .max_len = 64, - .demod = 0; + .demod = 0; }; struct v4l2_priv_tun_config cfg = { .tuner = dev->tuner_type, .priv = &ctrl, }; - cx231xx_i2c_call_clients(&dev->i2c_bus[1], TUNER_SET_CONFIG, &cfg); + cx231xx_i2c_call_clients(&dev->i2c_bus[1], TUNER_SET_CONFIG, + &cfg); } #endif /* configure tuner */ f.tuner = 0; f.type = V4L2_TUNER_ANALOG_TV; - f.frequency = 9076; /* just a magic number */ + f.frequency = 9076; /* just a magic number */ dev->ctl_freq = f.frequency; cx231xx_i2c_call_clients(&dev->i2c_bus[1], VIDIOC_S_FREQUENCY, &f); } @@ -299,18 +326,18 @@ void cx231xx_set_ir(struct cx231xx *dev, struct IR_i2c *ir) { if (disable_ir) { ir->get_key = NULL; - return ; + return; } /* detect & configure */ switch (dev->model) { - case CX231XX_BOARD_CNXT_RDE_250: - break; - case CX231XX_BOARD_CNXT_RDU_250: - break; - default: - break; + case CX231XX_BOARD_CNXT_RDE_250: + break; + case CX231XX_BOARD_CNXT_RDU_250: + break; + default: + break; } } @@ -322,58 +349,55 @@ void cx231xx_card_setup(struct cx231xx *dev) if (cx231xx_boards[dev->model].tuner_addr) dev->tuner_addr = cx231xx_boards[dev->model].tuner_addr; - cx231xx_info(": tuner type %d, tuner address %d \n", - dev->tuner_type, dev->tuner_addr); + cx231xx_info(": tuner type %d, tuner address %d \n", + dev->tuner_type, dev->tuner_addr); /* Do card specific if any */ switch (dev->model) { - case CX231XX_BOARD_CNXT_RDE_250: - /* do card specific GPIO settings if required */ - cx231xx_info("Board is Conexnat RDE 250\n"); - break; - case CX231XX_BOARD_CNXT_RDU_250: - /* do card specific GPIO settings if required */ - cx231xx_info("Board is Conexnat RDU 250\n"); - break; + case CX231XX_BOARD_CNXT_RDE_250: + /* do card specific GPIO settings if required */ + cx231xx_info("Board is Conexnat RDE 250\n"); + break; + case CX231XX_BOARD_CNXT_RDU_250: + /* do card specific GPIO settings if required */ + cx231xx_info("Board is Conexnat RDU 250\n"); + break; } if (dev->board.valid == CX231XX_BOARD_NOT_VALIDATED) { cx231xx_errdev("\n\n"); cx231xx_errdev("The support for this board weren't " - "valid yet.\n"); + "valid yet.\n"); cx231xx_errdev("Please send a report of having this working\n"); cx231xx_errdev("not to V4L mailing list (and/or to other " - "addresses)\n\n"); + "addresses)\n\n"); } - /* request some modules */ - if (dev->board.decoder == CX231XX_AVDECODER) { - cx231xx_info(": Requesting cx25840 module\n"); + if (dev->board.decoder == CX231XX_AVDECODER) { + cx231xx_info(": Requesting cx25840 module\n"); request_module("cx25840"); - } -#if 0 /* Keep */ - if (dev->board.tuner_type != TUNER_ABSENT) { - cx231xx_info(": Requesting Tuner module\n"); + } +#if 0 /* Keep */ + if (dev->board.tuner_type != TUNER_ABSENT) { + cx231xx_info(": Requesting Tuner module\n"); request_module("tuner"); - } + } cx231xx_config_tuner(dev); - - /* TBD IR will be added later */ + + /* TBD IR will be added later */ cx231xx_ir_init(dev); #endif } - - /* * cx231xx_config() * inits registers with sane defaults */ int cx231xx_config(struct cx231xx *dev) { - /* TBD need to add cx231xx specific code */ + /* TBD need to add cx231xx specific code */ dev->mute = 1; /* maybe not the right place... */ dev->volume = 0x1f; @@ -402,30 +426,29 @@ void cx231xx_config_i2c(struct cx231xx *dev) void cx231xx_release_resources(struct cx231xx *dev) { -#if 0 /* Keep */ /* TBD IR related */ +#if 0 /* Keep */ /* TBD IR related */ if (dev->ir) cx231xx_ir_fini(dev); #endif cx231xx_release_analog_resources(dev); - cx231xx_remove_from_devlist(dev); + cx231xx_remove_from_devlist(dev); - cx231xx_dev_uninit(dev); + cx231xx_dev_uninit(dev); usb_put_dev(dev->udev); /* Mark device as unused */ - cx231xx_devused &= ~(1<devno); + cx231xx_devused &= ~(1 << dev->devno); } - /* * cx231xx_init_dev() * allocates and inits the device structs, registers i2c bus and v4l device */ static int cx231xx_init_dev(struct cx231xx **devhandle, struct usb_device *udev, - int minor) + int minor) { struct cx231xx *dev = *devhandle; int retval = -ENOMEM; @@ -435,26 +458,26 @@ static int cx231xx_init_dev(struct cx231xx **devhandle, struct usb_device *udev, dev->udev = udev; mutex_init(&dev->lock); mutex_init(&dev->ctrl_urb_lock); - mutex_init(&dev->gpio_i2c_lock); - - spin_lock_init(&dev->video_mode.slock); - spin_lock_init(&dev->vbi_mode.slock); - spin_lock_init(&dev->sliced_cc_mode.slock); + mutex_init(&dev->gpio_i2c_lock); + + spin_lock_init(&dev->video_mode.slock); + spin_lock_init(&dev->vbi_mode.slock); + spin_lock_init(&dev->sliced_cc_mode.slock); init_waitqueue_head(&dev->open); init_waitqueue_head(&dev->wait_frame); init_waitqueue_head(&dev->wait_stream); - dev->cx231xx_read_ctrl_reg = cx231xx_read_ctrl_reg; - dev->cx231xx_write_ctrl_reg = cx231xx_write_ctrl_reg; - dev->cx231xx_send_usb_command = cx231xx_send_usb_command; - dev->cx231xx_gpio_i2c_read = cx231xx_gpio_i2c_read; - dev->cx231xx_gpio_i2c_write = cx231xx_gpio_i2c_write; + dev->cx231xx_read_ctrl_reg = cx231xx_read_ctrl_reg; + dev->cx231xx_write_ctrl_reg = cx231xx_write_ctrl_reg; + dev->cx231xx_send_usb_command = cx231xx_send_usb_command; + dev->cx231xx_gpio_i2c_read = cx231xx_gpio_i2c_read; + dev->cx231xx_gpio_i2c_write = cx231xx_gpio_i2c_write; - /* Query cx231xx to find what pcb config it is related to */ - initialize_cx231xx(dev); + /* Query cx231xx to find what pcb config it is related to */ + initialize_cx231xx(dev); - /* Cx231xx pre card setup */ + /* Cx231xx pre card setup */ cx231xx_pre_card_setup(dev); errCode = cx231xx_config(dev); @@ -463,14 +486,14 @@ static int cx231xx_init_dev(struct cx231xx **devhandle, struct usb_device *udev, return -ENOMEM; } - /* set default norm */ + /* set default norm */ dev->norm = dev->board.norm; /* register i2c bus */ errCode = cx231xx_dev_init(dev); if (errCode < 0) { cx231xx_errdev("%s: cx231xx_i2c_register - errCode [%d]!\n", - __func__, errCode); + __func__, errCode); return errCode; } @@ -478,7 +501,7 @@ static int cx231xx_init_dev(struct cx231xx **devhandle, struct usb_device *udev, cx231xx_card_setup(dev); /* configure the device */ - cx231xx_config_i2c(dev); + cx231xx_config_i2c(dev); maxw = norm_maxw(dev); maxh = norm_maxh(dev); @@ -494,7 +517,7 @@ static int cx231xx_init_dev(struct cx231xx **devhandle, struct usb_device *udev, errCode = cx231xx_config(dev); if (errCode < 0) { cx231xx_errdev("%s: cx231xx_config - errCode [%d]!\n", - __func__, errCode); + __func__, errCode); return errCode; } @@ -502,13 +525,13 @@ static int cx231xx_init_dev(struct cx231xx **devhandle, struct usb_device *udev, INIT_LIST_HEAD(&dev->video_mode.vidq.active); INIT_LIST_HEAD(&dev->video_mode.vidq.queued); - /* init vbi dma queues */ + /* init vbi dma queues */ INIT_LIST_HEAD(&dev->vbi_mode.vidq.active); INIT_LIST_HEAD(&dev->vbi_mode.vidq.queued); /* Reset other chips required if they are tied up with GPIO pins */ - cx231xx_add_into_devlist(dev); + cx231xx_add_into_devlist(dev); retval = cx231xx_register_analog_devices(dev); if (retval < 0) { @@ -520,7 +543,7 @@ static int cx231xx_init_dev(struct cx231xx **devhandle, struct usb_device *udev, return 0; -fail_reg_devices: + fail_reg_devices: mutex_unlock(&dev->lock); return retval; } @@ -534,10 +557,9 @@ static void request_module_async(void *ptr) static void request_module_async(struct work_struct *work) { struct cx231xx *dev = container_of(work, - struct cx231xx, request_module_wk); + struct cx231xx, request_module_wk); #endif - if (dev->has_alsa_audio) request_module("cx231xx-alsa"); @@ -549,8 +571,7 @@ static void request_module_async(struct work_struct *work) static void request_modules(struct cx231xx *dev) { #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20) - INIT_WORK(&dev->request_module_wk, request_module_async, - (void *)dev); + INIT_WORK(&dev->request_module_wk, request_module_async, (void *)dev); #else INIT_WORK(&dev->request_module_wk, request_module_async); #endif @@ -560,130 +581,130 @@ static void request_modules(struct cx231xx *dev) #define request_modules(dev) #endif /* CONFIG_MODULES */ - - /* * cx231xx_usb_probe() * checks for supported devices */ static int cx231xx_usb_probe(struct usb_interface *interface, - const struct usb_device_id *id) + const struct usb_device_id *id) { struct usb_device *udev; struct usb_interface *uif; struct cx231xx *dev = NULL; int retval = -ENODEV; - int nr, ifnum; + int nr, ifnum; int i, isoc_pipe = 0; char *speed; char descr[255] = ""; - struct usb_interface *lif = NULL; - int skip_interface = 0; - struct usb_interface_assoc_descriptor *assoc_desc; + struct usb_interface *lif = NULL; + int skip_interface = 0; + struct usb_interface_assoc_descriptor *assoc_desc; udev = usb_get_dev(interface_to_usbdev(interface)); ifnum = interface->altsetting[0].desc.bInterfaceNumber; - cx231xx_info(": Interface Number %d\n", ifnum); - - /* Interface number 0 - IR interface */ - if(ifnum == 0 ){ - /* Check to see next free device and mark as used */ - nr = find_first_zero_bit(&cx231xx_devused, CX231XX_MAXBOARDS); - cx231xx_devused |= 1<= CX231XX_MAXBOARDS) { - cx231xx_info(": Supports only %i cx231xx boards.\n", - CX231XX_MAXBOARDS); - cx231xx_devused &= ~(1<name, 29, "cx231xx #%d", nr); - dev->devno = nr; - dev->model = id->driver_info; - dev->video_mode.alt = -1; - dev->interface_count++; - - /* reset gpio dir and value */ - dev->gpio_dir = 0; - dev->gpio_val = 0; - dev->xc_fw_load_done = 0; + cx231xx_info(": Interface Number %d\n", ifnum); + + /* Interface number 0 - IR interface */ + if (ifnum == 0) { + /* Check to see next free device and mark as used */ + nr = find_first_zero_bit(&cx231xx_devused, CX231XX_MAXBOARDS); + cx231xx_devused |= 1 << nr; + + if (nr >= CX231XX_MAXBOARDS) { + cx231xx_info(": Supports only %i cx231xx boards.\n", + CX231XX_MAXBOARDS); + cx231xx_devused &= ~(1 << nr); + return -ENOMEM; + } + + /* allocate memory for our device state and initialize it */ + dev = kzalloc(sizeof(*dev), GFP_KERNEL); + if (dev == NULL) { + cx231xx_err(DRIVER_NAME ": out of memory!\n"); + cx231xx_devused &= ~(1 << nr); + return -ENOMEM; + } + + snprintf(dev->name, 29, "cx231xx #%d", nr); + dev->devno = nr; + dev->model = id->driver_info; + dev->video_mode.alt = -1; + dev->interface_count++; + + /* reset gpio dir and value */ + dev->gpio_dir = 0; + dev->gpio_val = 0; + dev->xc_fw_load_done = 0; dev->has_alsa_audio = 1; - dev->power_mode = -1; - - dev->vbi_or_sliced_cc_mode = 0; /* 0 - vbi ; 1 -sliced cc mode */ - - /* get maximum no.of IAD interfaces */ - assoc_desc = udev->actconfig->intf_assoc[0]; - dev->max_iad_interface_count = assoc_desc->bInterfaceCount; - cx231xx_info(": Found IAD interface count %d\n", dev->max_iad_interface_count); - - /* init CIR module TBD */ - - /* store the current interface */ - lif = interface; - - } - else if(ifnum == 1 ){ - - /* Get dev structure first */ - dev = usb_get_intfdata(udev->actconfig->interface[0]); - if(dev == NULL){ - cx231xx_err(DRIVER_NAME ": out of first interface!\n"); - return -ENODEV; - } - - /* store the interface 0 back */ - lif = udev->actconfig->interface[0]; - - /* increment interface count */ - dev->interface_count++; - - /* get device number */ - nr = dev->devno; - - assoc_desc = udev->actconfig->intf_assoc[0]; - if(assoc_desc->bFirstInterface == ifnum){ - cx231xx_info(": Found IAD interface match: AV Descriptor Start!! \n"); - } else { - cx231xx_err(DRIVER_NAME " Not found matching interface\n"); - return -ENODEV; - } - - } - else if(ifnum >= 2) { - /* Get dev structure first */ - dev = usb_get_intfdata(udev->actconfig->interface[0]); - if(dev == NULL){ - cx231xx_err(DRIVER_NAME ": out of first interface!\n"); - return -ENODEV; - } - - /* store the interface 0 back */ - lif = udev->actconfig->interface[0]; - - /* increment interface count */ - dev->interface_count++; - - /* get device number */ - nr = dev->devno; - - /* set skip interface */ - if((dev->interface_count -1) != dev->max_iad_interface_count ) - skip_interface = 1; /* set skipping */ - else{ - cx231xx_info(": Found IAD interface number match with AV Device number!! \n"); - } - } + dev->power_mode = -1; + + dev->vbi_or_sliced_cc_mode = 0; /* 0 - vbi ; 1 -sliced cc mode */ + + /* get maximum no.of IAD interfaces */ + assoc_desc = udev->actconfig->intf_assoc[0]; + dev->max_iad_interface_count = assoc_desc->bInterfaceCount; + cx231xx_info(": Found IAD interface count %d\n", + dev->max_iad_interface_count); + + /* init CIR module TBD */ + + /* store the current interface */ + lif = interface; + + } else if (ifnum == 1) { + + /* Get dev structure first */ + dev = usb_get_intfdata(udev->actconfig->interface[0]); + if (dev == NULL) { + cx231xx_err(DRIVER_NAME ": out of first interface!\n"); + return -ENODEV; + } + + /* store the interface 0 back */ + lif = udev->actconfig->interface[0]; + + /* increment interface count */ + dev->interface_count++; + + /* get device number */ + nr = dev->devno; + + assoc_desc = udev->actconfig->intf_assoc[0]; + if (assoc_desc->bFirstInterface == ifnum) { + cx231xx_info + (": Found IAD interface match: AV Descriptor Start!! \n"); + } else { + cx231xx_err(DRIVER_NAME + " Not found matching interface\n"); + return -ENODEV; + } + + } else if (ifnum >= 2) { + /* Get dev structure first */ + dev = usb_get_intfdata(udev->actconfig->interface[0]); + if (dev == NULL) { + cx231xx_err(DRIVER_NAME ": out of first interface!\n"); + return -ENODEV; + } + + /* store the interface 0 back */ + lif = udev->actconfig->interface[0]; + + /* increment interface count */ + dev->interface_count++; + + /* get device number */ + nr = dev->devno; + + /* set skip interface */ + if ((dev->interface_count - 1) != dev->max_iad_interface_count) + skip_interface = 1; /* set skipping */ + else { + cx231xx_info + (": Found IAD interface number match with AV Device number!! \n"); + } + } switch (udev->speed) { case USB_SPEED_LOW: @@ -712,153 +733,184 @@ static int cx231xx_usb_probe(struct usb_interface *interface, strlcat(descr, " ", sizeof(descr)); cx231xx_info("New device %s@ %s Mbps " - "(%04x:%04x, interface %d, class %d)\n", - descr, - speed, - le16_to_cpu(udev->descriptor.idVendor), - le16_to_cpu(udev->descriptor.idProduct), - ifnum, - interface->altsetting->desc.bInterfaceNumber); - - /* AV device initialization */ - if((dev->interface_count -1) == dev->max_iad_interface_count ) { - cx231xx_info(" Calling init_dev\n"); - /* allocate device struct */ - retval = cx231xx_init_dev(&dev, udev, nr); - if (retval) { - cx231xx_devused &= ~(1<devno); - kfree(dev); - - return retval; - } - - /* compute alternate max packet sizes for video */ - uif = udev->actconfig->interface[dev->current_pcb_config.hs_config_info[0].interface_info.video_index+1]; - - dev->video_mode.end_point_addr = le16_to_cpu(uif->altsetting[0].endpoint[isoc_pipe].desc.bEndpointAddress); - - dev->video_mode.num_alt = uif->num_altsetting; - cx231xx_info(": EndPoint Addr 0x%x, Alternate settings: %i\n", dev->video_mode.end_point_addr, - dev->video_mode.num_alt); - dev->video_mode.alt_max_pkt_size = kmalloc(32 * dev->video_mode.num_alt, GFP_KERNEL); - - if (dev->video_mode.alt_max_pkt_size == NULL) { - cx231xx_errdev("out of memory!\n"); - cx231xx_devused &= ~(1<video_mode.num_alt ; i++) { - u16 tmp = le16_to_cpu(uif->altsetting[i].endpoint[isoc_pipe].desc. - wMaxPacketSize); - dev->video_mode.alt_max_pkt_size[i] = - (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1); - cx231xx_info("Alternate setting %i, max size= %i\n", i, - dev->video_mode.alt_max_pkt_size[i]); - } - - - /* compute alternate max packet sizes for vbi */ - uif = udev->actconfig->interface[dev->current_pcb_config.hs_config_info[0].interface_info.vanc_index+1]; - - dev->vbi_mode.end_point_addr = - le16_to_cpu(uif->altsetting[0].endpoint[isoc_pipe].desc.bEndpointAddress); - - dev->vbi_mode.num_alt = uif->num_altsetting; - cx231xx_info(": EndPoint Addr 0x%x, Alternate settings: %i\n", dev->vbi_mode.end_point_addr, - dev->vbi_mode.num_alt); - dev->vbi_mode.alt_max_pkt_size = kmalloc(32 * dev->vbi_mode.num_alt, GFP_KERNEL); - - if (dev->vbi_mode.alt_max_pkt_size == NULL) { - cx231xx_errdev("out of memory!\n"); - cx231xx_devused &= ~(1<vbi_mode.num_alt ; i++) { - u16 tmp = le16_to_cpu(uif->altsetting[i].endpoint[isoc_pipe].desc. - wMaxPacketSize); - dev->vbi_mode.alt_max_pkt_size[i] = - (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1); - cx231xx_info("Alternate setting %i, max size= %i\n", i, - dev->vbi_mode.alt_max_pkt_size[i]); - } - - /* compute alternate max packet sizes for sliced CC */ - uif = udev->actconfig->interface[dev->current_pcb_config.hs_config_info[0].interface_info.hanc_index+1]; - - dev->sliced_cc_mode.end_point_addr = - le16_to_cpu(uif->altsetting[0].endpoint[isoc_pipe].desc.bEndpointAddress); - - dev->sliced_cc_mode.num_alt = uif->num_altsetting; - cx231xx_info(": EndPoint Addr 0x%x, Alternate settings: %i\n", dev->sliced_cc_mode.end_point_addr, - dev->sliced_cc_mode.num_alt); - dev->sliced_cc_mode.alt_max_pkt_size = kmalloc(32 * dev->sliced_cc_mode.num_alt, GFP_KERNEL); - - if (dev->sliced_cc_mode.alt_max_pkt_size == NULL) { - cx231xx_errdev("out of memory!\n"); - cx231xx_devused &= ~(1<sliced_cc_mode.num_alt ; i++) { - u16 tmp = le16_to_cpu(uif->altsetting[i].endpoint[isoc_pipe].desc. - wMaxPacketSize); - dev->sliced_cc_mode.alt_max_pkt_size[i] = - (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1); - cx231xx_info("Alternate setting %i, max size= %i\n", i, - dev->sliced_cc_mode.alt_max_pkt_size[i]); - } - - if(dev->current_pcb_config.ts1_source != 0xff ) { - - /* compute alternate max packet sizes for TS1 */ - uif = udev->actconfig->interface[dev->current_pcb_config.hs_config_info[0].interface_info.ts1_index+1]; - - dev->ts1_mode.end_point_addr = - le16_to_cpu(uif->altsetting[0].endpoint[isoc_pipe].desc.bEndpointAddress); - - dev->ts1_mode.num_alt = uif->num_altsetting; - cx231xx_info(": EndPoint Addr 0x%x, Alternate settings: %i\n", dev->ts1_mode.end_point_addr, - dev->ts1_mode.num_alt); - dev->ts1_mode.alt_max_pkt_size = kmalloc(32 * dev->ts1_mode.num_alt, GFP_KERNEL); - - if (dev->ts1_mode.alt_max_pkt_size == NULL) { - cx231xx_errdev("out of memory!\n"); - cx231xx_devused &= ~(1<ts1_mode.num_alt ; i++) { - u16 tmp = le16_to_cpu(uif->altsetting[i].endpoint[isoc_pipe].desc. - wMaxPacketSize); - dev->ts1_mode.alt_max_pkt_size[i] = - (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1); - cx231xx_info("Alternate setting %i, max size= %i\n", i, - dev->ts1_mode.alt_max_pkt_size[i]); - } - } - - } + "(%04x:%04x, interface %d, class %d)\n", + descr, + speed, + le16_to_cpu(udev->descriptor.idVendor), + le16_to_cpu(udev->descriptor.idProduct), + ifnum, interface->altsetting->desc.bInterfaceNumber); + + /* AV device initialization */ + if ((dev->interface_count - 1) == dev->max_iad_interface_count) { + cx231xx_info(" Calling init_dev\n"); + /* allocate device struct */ + retval = cx231xx_init_dev(&dev, udev, nr); + if (retval) { + cx231xx_devused &= ~(1 << dev->devno); + kfree(dev); + + return retval; + } + + /* compute alternate max packet sizes for video */ + uif = + udev->actconfig->interface[dev->current_pcb_config. + hs_config_info[0].interface_info. + video_index + 1]; + + dev->video_mode.end_point_addr = + le16_to_cpu(uif->altsetting[0].endpoint[isoc_pipe].desc. + bEndpointAddress); + + dev->video_mode.num_alt = uif->num_altsetting; + cx231xx_info(": EndPoint Addr 0x%x, Alternate settings: %i\n", + dev->video_mode.end_point_addr, + dev->video_mode.num_alt); + dev->video_mode.alt_max_pkt_size = + kmalloc(32 * dev->video_mode.num_alt, GFP_KERNEL); + + if (dev->video_mode.alt_max_pkt_size == NULL) { + cx231xx_errdev("out of memory!\n"); + cx231xx_devused &= ~(1 << nr); + kfree(dev); + return -ENOMEM; + } + + for (i = 0; i < dev->video_mode.num_alt; i++) { + u16 tmp = + le16_to_cpu(uif->altsetting[i].endpoint[isoc_pipe]. + desc.wMaxPacketSize); + dev->video_mode.alt_max_pkt_size[i] = + (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1); + cx231xx_info("Alternate setting %i, max size= %i\n", i, + dev->video_mode.alt_max_pkt_size[i]); + } + + /* compute alternate max packet sizes for vbi */ + uif = + udev->actconfig->interface[dev->current_pcb_config. + hs_config_info[0].interface_info. + vanc_index + 1]; + + dev->vbi_mode.end_point_addr = + le16_to_cpu(uif->altsetting[0].endpoint[isoc_pipe].desc. + bEndpointAddress); + + dev->vbi_mode.num_alt = uif->num_altsetting; + cx231xx_info(": EndPoint Addr 0x%x, Alternate settings: %i\n", + dev->vbi_mode.end_point_addr, + dev->vbi_mode.num_alt); + dev->vbi_mode.alt_max_pkt_size = + kmalloc(32 * dev->vbi_mode.num_alt, GFP_KERNEL); + + if (dev->vbi_mode.alt_max_pkt_size == NULL) { + cx231xx_errdev("out of memory!\n"); + cx231xx_devused &= ~(1 << nr); + kfree(dev); + return -ENOMEM; + } + + for (i = 0; i < dev->vbi_mode.num_alt; i++) { + u16 tmp = + le16_to_cpu(uif->altsetting[i].endpoint[isoc_pipe]. + desc.wMaxPacketSize); + dev->vbi_mode.alt_max_pkt_size[i] = + (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1); + cx231xx_info("Alternate setting %i, max size= %i\n", i, + dev->vbi_mode.alt_max_pkt_size[i]); + } + + /* compute alternate max packet sizes for sliced CC */ + uif = + udev->actconfig->interface[dev->current_pcb_config. + hs_config_info[0].interface_info. + hanc_index + 1]; + + dev->sliced_cc_mode.end_point_addr = + le16_to_cpu(uif->altsetting[0].endpoint[isoc_pipe].desc. + bEndpointAddress); + + dev->sliced_cc_mode.num_alt = uif->num_altsetting; + cx231xx_info(": EndPoint Addr 0x%x, Alternate settings: %i\n", + dev->sliced_cc_mode.end_point_addr, + dev->sliced_cc_mode.num_alt); + dev->sliced_cc_mode.alt_max_pkt_size = + kmalloc(32 * dev->sliced_cc_mode.num_alt, GFP_KERNEL); + + if (dev->sliced_cc_mode.alt_max_pkt_size == NULL) { + cx231xx_errdev("out of memory!\n"); + cx231xx_devused &= ~(1 << nr); + kfree(dev); + return -ENOMEM; + } + + for (i = 0; i < dev->sliced_cc_mode.num_alt; i++) { + u16 tmp = + le16_to_cpu(uif->altsetting[i].endpoint[isoc_pipe]. + desc.wMaxPacketSize); + dev->sliced_cc_mode.alt_max_pkt_size[i] = + (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1); + cx231xx_info("Alternate setting %i, max size= %i\n", i, + dev->sliced_cc_mode.alt_max_pkt_size[i]); + } + + if (dev->current_pcb_config.ts1_source != 0xff) { + + /* compute alternate max packet sizes for TS1 */ + uif = + udev->actconfig->interface[dev->current_pcb_config. + hs_config_info[0]. + interface_info. + ts1_index + 1]; + + dev->ts1_mode.end_point_addr = + le16_to_cpu(uif->altsetting[0].endpoint[isoc_pipe]. + desc.bEndpointAddress); + + dev->ts1_mode.num_alt = uif->num_altsetting; + cx231xx_info + (": EndPoint Addr 0x%x, Alternate settings: %i\n", + dev->ts1_mode.end_point_addr, + dev->ts1_mode.num_alt); + dev->ts1_mode.alt_max_pkt_size = + kmalloc(32 * dev->ts1_mode.num_alt, GFP_KERNEL); + + if (dev->ts1_mode.alt_max_pkt_size == NULL) { + cx231xx_errdev("out of memory!\n"); + cx231xx_devused &= ~(1 << nr); + kfree(dev); + return -ENOMEM; + } + + for (i = 0; i < dev->ts1_mode.num_alt; i++) { + u16 tmp = + le16_to_cpu(uif->altsetting[i]. + endpoint[isoc_pipe].desc. + wMaxPacketSize); + dev->ts1_mode.alt_max_pkt_size[i] = + (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + + 1); + cx231xx_info + ("Alternate setting %i, max size= %i\n", i, + dev->ts1_mode.alt_max_pkt_size[i]); + } + } + + } /* save our data pointer in this interface device */ usb_set_intfdata(lif, dev); - /* load other modules required */ - if((dev->interface_count -1) == dev->max_iad_interface_count ) - { - cx231xx_info("Calling request modules\n"); - request_modules(dev); - } + /* load other modules required */ + if ((dev->interface_count - 1) == dev->max_iad_interface_count) { + cx231xx_info("Calling request modules\n"); + request_modules(dev); + } - if(skip_interface ) { - cx231xx_info("Skipping the interface\n"); - return -ENODEV; - } + if (skip_interface) { + cx231xx_info("Skipping the interface\n"); + return -ENODEV; + } return 0; } @@ -872,7 +924,7 @@ static void cx231xx_usb_disconnect(struct usb_interface *interface) { struct cx231xx *dev; - dev = usb_get_intfdata(interface); + dev = usb_get_intfdata(interface); usb_set_intfdata(interface, NULL); if (!dev) @@ -887,8 +939,7 @@ static void cx231xx_usb_disconnect(struct usb_interface *interface) if (dev->users) { cx231xx_warn ("device /dev/video%d is open! Deregistration and memory " - "deallocation are deferred on close.\n", - dev->vdev->num); + "deallocation are deferred on close.\n", dev->vdev->num); dev->state |= DEV_MISCONFIGURED; cx231xx_uninit_isoc(dev); @@ -900,15 +951,15 @@ static void cx231xx_usb_disconnect(struct usb_interface *interface) cx231xx_release_resources(dev); } - cx231xx_close_extension(dev); + cx231xx_close_extension(dev); mutex_unlock(&dev->lock); if (!dev->users) { kfree(dev->video_mode.alt_max_pkt_size); - kfree(dev->vbi_mode.alt_max_pkt_size); - kfree(dev->sliced_cc_mode.alt_max_pkt_size); - kfree(dev->ts1_mode.alt_max_pkt_size); + kfree(dev->vbi_mode.alt_max_pkt_size); + kfree(dev->sliced_cc_mode.alt_max_pkt_size); + kfree(dev->ts1_mode.alt_max_pkt_size); kfree(dev); } } @@ -932,7 +983,7 @@ static int __init cx231xx_module_init(void) result = usb_register(&cx231xx_usb_driver); if (result) cx231xx_err(DRIVER_NAME - " usb_register failed. Error number %d.\n", result); + " usb_register failed. Error number %d.\n", result); return result; } diff --git a/linux/drivers/media/video/cx231xx/cx231xx-conf-reg.h b/linux/drivers/media/video/cx231xx/cx231xx-conf-reg.h index 608867745..a65f99ba1 100644 --- a/linux/drivers/media/video/cx231xx/cx231xx-conf-reg.h +++ b/linux/drivers/media/video/cx231xx/cx231xx-conf-reg.h @@ -1,8 +1,8 @@ /* - cx231xx_conf-reg.h - driver for Conexant Cx23100/101/102 USB - video capture devices + cx231xx_conf-reg.h - driver for Conexant Cx23100/101/102 USB + video capture devices - Copyright (C) 2008 + Copyright (C) 2008 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 @@ -19,7 +19,6 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ - #ifndef _POLARIS_REG_H_ #define _POLARIS_REG_H_ @@ -40,33 +39,33 @@ #define CIR_CAR_REG 0x38 #define CIR_OT_CFG1 0x40 #define CIR_OT_CFG2 0x44 -#define PWR_CTL_EN 0x74 +#define PWR_CTL_EN 0x74 /* Polaris Endpoints capture mask for register EP_MODE_SET */ -#define ENABLE_EP1 0x01 /* Bit[0]=1 */ -#define ENABLE_EP2 0x02 /* Bit[1]=1 */ -#define ENABLE_EP3 0x04 /* Bit[2]=1 */ -#define ENABLE_EP4 0x08 /* Bit[3]=1 */ -#define ENABLE_EP5 0x10 /* Bit[4]=1 */ -#define ENABLE_EP6 0x20 /* Bit[5]=1 */ +#define ENABLE_EP1 0x01 /* Bit[0]=1 */ +#define ENABLE_EP2 0x02 /* Bit[1]=1 */ +#define ENABLE_EP3 0x04 /* Bit[2]=1 */ +#define ENABLE_EP4 0x08 /* Bit[3]=1 */ +#define ENABLE_EP5 0x10 /* Bit[4]=1 */ +#define ENABLE_EP6 0x20 /* Bit[5]=1 */ /* Bit definition for register PWR_CTL_EN */ -#define PWR_MODE_MASK 0x17f -#define PWR_AV_EN 0x08 /* bit3 */ -#define PWR_ISO_EN 0x40 /* bit6 */ -#define PWR_AV_MODE 0x30 /* bit4,5 */ -#define PWR_TUNER_EN 0x04 /* bit2 */ -#define PWR_DEMOD_EN 0x02 /* bit1 */ -#define I2C_DEMOD_EN 0x01 /* bit0 */ -#define PWR_RESETOUT_EN 0x100 /* bit8 */ - -typedef enum{ - POLARIS_AVMODE_DEFAULT = 0, - POLARIS_AVMODE_DIGITAL = 0x10, - POLARIS_AVMODE_ANALOGT_TV = 0x20, - POLARIS_AVMODE_ENXTERNAL_AV = 0x30, - -}AV_MODE; +#define PWR_MODE_MASK 0x17f +#define PWR_AV_EN 0x08 /* bit3 */ +#define PWR_ISO_EN 0x40 /* bit6 */ +#define PWR_AV_MODE 0x30 /* bit4,5 */ +#define PWR_TUNER_EN 0x04 /* bit2 */ +#define PWR_DEMOD_EN 0x02 /* bit1 */ +#define I2C_DEMOD_EN 0x01 /* bit0 */ +#define PWR_RESETOUT_EN 0x100 /* bit8 */ + +typedef enum { + POLARIS_AVMODE_DEFAULT = 0, + POLARIS_AVMODE_DIGITAL = 0x10, + POLARIS_AVMODE_ANALOGT_TV = 0x20, + POLARIS_AVMODE_ENXTERNAL_AV = 0x30, + +} AV_MODE; /* Colibri Registers */ @@ -75,28 +74,26 @@ typedef enum{ #define EU_IF 0x9 #define US_IF 0xa - - #define SUP_BLK_TUNE1 0x00 #define SUP_BLK_TUNE2 0x01 #define SUP_BLK_TUNE3 0x02 -#define SUP_BLK_XTAL 0x03 +#define SUP_BLK_XTAL 0x03 #define SUP_BLK_PLL1 0x04 #define SUP_BLK_PLL2 0x05 -#define SUP_BLK_PLL3 0x06 +#define SUP_BLK_PLL3 0x06 #define SUP_BLK_REF 0x07 #define SUP_BLK_PWRDN 0x08 -#define SUP_BLK_TESTPAD 0x09 -#define ADC_COM_INT5_STAB_REF 0x0a +#define SUP_BLK_TESTPAD 0x09 +#define ADC_COM_INT5_STAB_REF 0x0a #define ADC_COM_QUANT 0x0b -#define ADC_COM_BIAS1 0x0c -#define ADC_COM_BIAS2 0x0d -#define ADC_COM_BIAS3 0x0e -#define TESTBUS_CTRL 0x12 +#define ADC_COM_BIAS1 0x0c +#define ADC_COM_BIAS2 0x0d +#define ADC_COM_BIAS3 0x0e +#define TESTBUS_CTRL 0x12 #define ADC_STATUS_CH1 0x20 -#define ADC_STATUS_CH2 0x40 -#define ADC_STATUS_CH3 0x60 +#define ADC_STATUS_CH2 0x40 +#define ADC_STATUS_CH3 0x60 #define ADC_STATUS2_CH1 0x21 #define ADC_STATUS2_CH2 0x41 @@ -129,363 +126,362 @@ typedef enum{ #define ADC_INPUT_CH1 0x28 #define ADC_INPUT_CH2 0x48 #define ADC_INPUT_CH3 0x68 -#define INPUT_SEL_MASK 0x30 /* [5:4] in_sel */ +#define INPUT_SEL_MASK 0x30 /* [5:4] in_sel */ #define ADC_NTF_PRECLMP_EN_CH1 0x29 #define ADC_NTF_PRECLMP_EN_CH2 0x49 #define ADC_NTF_PRECLMP_EN_CH3 0x69 -#define ADC_QGAIN_RES_TRM_CH1 0x2a -#define ADC_QGAIN_RES_TRM_CH2 0x4a -#define ADC_QGAIN_RES_TRM_CH3 0x6a +#define ADC_QGAIN_RES_TRM_CH1 0x2a +#define ADC_QGAIN_RES_TRM_CH2 0x4a +#define ADC_QGAIN_RES_TRM_CH3 0x6a -#define ADC_SOC_PRECLMP_TERM_CH1 0x2b -#define ADC_SOC_PRECLMP_TERM_CH2 0x4b -#define ADC_SOC_PRECLMP_TERM_CH3 0x6b +#define ADC_SOC_PRECLMP_TERM_CH1 0x2b +#define ADC_SOC_PRECLMP_TERM_CH2 0x4b +#define ADC_SOC_PRECLMP_TERM_CH3 0x6b -#define TESTBUS_CTRL_CH1 0x32 +#define TESTBUS_CTRL_CH1 0x32 #define TESTBUS_CTRL_CH2 0x52 #define TESTBUS_CTRL_CH3 0x72 /****************************************************************************** - * DIF registers * + * DIF registers * ******************************************************************************/ -#define DIRECT_IF_REVB_BASE 0x00300 +#define DIRECT_IF_REVB_BASE 0x00300 /*****************************************************************************/ -#define DIF_PLL_FREQ_WORD (DIRECT_IF_REVB_BASE + 0x00000000) /* Reg Size 32 */ +#define DIF_PLL_FREQ_WORD (DIRECT_IF_REVB_BASE + 0x00000000) /* Reg Size 32 */ /*****************************************************************************/ -#define FLD_DIF_PLL_LOCK 0x80000000 +#define FLD_DIF_PLL_LOCK 0x80000000 /* Reserved [30:29] */ -#define FLD_DIF_PLL_FREE_RUN 0x10000000 -#define FLD_DIF_PLL_FREQ 0x0FFFFFFF +#define FLD_DIF_PLL_FREE_RUN 0x10000000 +#define FLD_DIF_PLL_FREQ 0x0FFFFFFF /*****************************************************************************/ -#define DIF_PLL_CTRL (DIRECT_IF_REVB_BASE + 0x00000004) /* Reg Size 32 */ +#define DIF_PLL_CTRL (DIRECT_IF_REVB_BASE + 0x00000004) /* Reg Size 32 */ /*****************************************************************************/ -#define FLD_DIF_KD_PD 0xFF000000 +#define FLD_DIF_KD_PD 0xFF000000 /* Reserved [23:20] */ -#define FLD_DIF_KDS_PD 0x000F0000 -#define FLD_DIF_KI_PD 0x0000FF00 +#define FLD_DIF_KDS_PD 0x000F0000 +#define FLD_DIF_KI_PD 0x0000FF00 /* Reserved [7:4] */ -#define FLD_DIF_KIS_PD 0x0000000F +#define FLD_DIF_KIS_PD 0x0000000F /*****************************************************************************/ -#define DIF_PLL_CTRL1 (DIRECT_IF_REVB_BASE + 0x00000008) /* Reg Size 32 */ +#define DIF_PLL_CTRL1 (DIRECT_IF_REVB_BASE + 0x00000008) /* Reg Size 32 */ /*****************************************************************************/ -#define FLD_DIF_KD_FD 0xFF000000 +#define FLD_DIF_KD_FD 0xFF000000 /* Reserved [23:20] */ -#define FLD_DIF_KDS_FD 0x000F0000 -#define FLD_DIF_KI_FD 0x0000FF00 -#define FLD_DIF_SIG_PROP_SZ 0x000000F0 -#define FLD_DIF_KIS_FD 0x0000000F +#define FLD_DIF_KDS_FD 0x000F0000 +#define FLD_DIF_KI_FD 0x0000FF00 +#define FLD_DIF_SIG_PROP_SZ 0x000000F0 +#define FLD_DIF_KIS_FD 0x0000000F /*****************************************************************************/ -#define DIF_PLL_CTRL2 (DIRECT_IF_REVB_BASE + 0x0000000C) /* Reg Size 32 */ +#define DIF_PLL_CTRL2 (DIRECT_IF_REVB_BASE + 0x0000000C) /* Reg Size 32 */ /*****************************************************************************/ -#define FLD_DIF_PLL_AGC_REF 0xFFF00000 -#define FLD_DIF_PLL_AGC_KI 0x000F0000 +#define FLD_DIF_PLL_AGC_REF 0xFFF00000 +#define FLD_DIF_PLL_AGC_KI 0x000F0000 /* Reserved [15] */ -#define FLD_DIF_FREQ_LIMIT 0x00007000 -#define FLD_DIF_K_FD 0x00000F00 -#define FLD_DIF_DOWNSMPL_FD 0x000000FF +#define FLD_DIF_FREQ_LIMIT 0x00007000 +#define FLD_DIF_K_FD 0x00000F00 +#define FLD_DIF_DOWNSMPL_FD 0x000000FF /*****************************************************************************/ -#define DIF_PLL_CTRL3 (DIRECT_IF_REVB_BASE + 0x00000010) /* Reg Size 32 */ +#define DIF_PLL_CTRL3 (DIRECT_IF_REVB_BASE + 0x00000010) /* Reg Size 32 */ /*****************************************************************************/ /* Reserved [31:16] */ -#define FLD_DIF_PLL_AGC_EN 0x00008000 +#define FLD_DIF_PLL_AGC_EN 0x00008000 /* Reserved [14:12] */ -#define FLD_DIF_PLL_MAN_GAIN 0x00000FFF +#define FLD_DIF_PLL_MAN_GAIN 0x00000FFF /*****************************************************************************/ -#define DIF_AGC_IF_REF (DIRECT_IF_REVB_BASE + 0x00000014) /* Reg Size 32 */ +#define DIF_AGC_IF_REF (DIRECT_IF_REVB_BASE + 0x00000014) /* Reg Size 32 */ /*****************************************************************************/ -#define FLD_DIF_K_AGC_RF 0xF0000000 -#define FLD_DIF_K_AGC_IF 0x0F000000 -#define FLD_DIF_K_AGC_INT 0x00F00000 +#define FLD_DIF_K_AGC_RF 0xF0000000 +#define FLD_DIF_K_AGC_IF 0x0F000000 +#define FLD_DIF_K_AGC_INT 0x00F00000 /* Reserved [19:12] */ -#define FLD_DIF_IF_REF 0x00000FFF +#define FLD_DIF_IF_REF 0x00000FFF /*****************************************************************************/ -#define DIF_AGC_CTRL_IF (DIRECT_IF_REVB_BASE + 0x00000018) /* Reg Size 32 */ +#define DIF_AGC_CTRL_IF (DIRECT_IF_REVB_BASE + 0x00000018) /* Reg Size 32 */ /*****************************************************************************/ -#define FLD_DIF_IF_MAX 0xFF000000 -#define FLD_DIF_IF_MIN 0x00FF0000 -#define FLD_DIF_IF_AGC 0x0000FFFF +#define FLD_DIF_IF_MAX 0xFF000000 +#define FLD_DIF_IF_MIN 0x00FF0000 +#define FLD_DIF_IF_AGC 0x0000FFFF /*****************************************************************************/ -#define DIF_AGC_CTRL_INT (DIRECT_IF_REVB_BASE + 0x0000001C) /* Reg Size 32 */ +#define DIF_AGC_CTRL_INT (DIRECT_IF_REVB_BASE + 0x0000001C) /* Reg Size 32 */ /*****************************************************************************/ -#define FLD_DIF_INT_MAX 0xFF000000 -#define FLD_DIF_INT_MIN 0x00FF0000 -#define FLD_DIF_INT_AGC 0x0000FFFF +#define FLD_DIF_INT_MAX 0xFF000000 +#define FLD_DIF_INT_MIN 0x00FF0000 +#define FLD_DIF_INT_AGC 0x0000FFFF /*****************************************************************************/ -#define DIF_AGC_CTRL_RF (DIRECT_IF_REVB_BASE + 0x00000020) /* Reg Size 32 */ +#define DIF_AGC_CTRL_RF (DIRECT_IF_REVB_BASE + 0x00000020) /* Reg Size 32 */ /*****************************************************************************/ -#define FLD_DIF_RF_MAX 0xFF000000 -#define FLD_DIF_RF_MIN 0x00FF0000 -#define FLD_DIF_RF_AGC 0x0000FFFF +#define FLD_DIF_RF_MAX 0xFF000000 +#define FLD_DIF_RF_MIN 0x00FF0000 +#define FLD_DIF_RF_AGC 0x0000FFFF /*****************************************************************************/ -#define DIF_AGC_IF_INT_CURRENT (DIRECT_IF_REVB_BASE + 0x00000024) /* Reg Size 32 */ +#define DIF_AGC_IF_INT_CURRENT (DIRECT_IF_REVB_BASE + 0x00000024) /* Reg Size 32 */ /*****************************************************************************/ -#define FLD_DIF_IF_AGC_IN 0xFFFF0000 -#define FLD_DIF_INT_AGC_IN 0x0000FFFF +#define FLD_DIF_IF_AGC_IN 0xFFFF0000 +#define FLD_DIF_INT_AGC_IN 0x0000FFFF /*****************************************************************************/ -#define DIF_AGC_RF_CURRENT (DIRECT_IF_REVB_BASE + 0x00000028) /* Reg Size 32 */ +#define DIF_AGC_RF_CURRENT (DIRECT_IF_REVB_BASE + 0x00000028) /* Reg Size 32 */ /*****************************************************************************/ /* Reserved [31:16] */ -#define FLD_DIF_RF_AGC_IN 0x0000FFFF +#define FLD_DIF_RF_AGC_IN 0x0000FFFF /*****************************************************************************/ -#define DIF_VIDEO_AGC_CTRL (DIRECT_IF_REVB_BASE + 0x0000002C) /* Reg Size 32 */ +#define DIF_VIDEO_AGC_CTRL (DIRECT_IF_REVB_BASE + 0x0000002C) /* Reg Size 32 */ /*****************************************************************************/ -#define FLD_DIF_AFD 0xC0000000 -#define FLD_DIF_K_VID_AGC 0x30000000 -#define FLD_DIF_LINE_LENGTH 0x0FFF0000 -#define FLD_DIF_AGC_GAIN 0x0000FFFF +#define FLD_DIF_AFD 0xC0000000 +#define FLD_DIF_K_VID_AGC 0x30000000 +#define FLD_DIF_LINE_LENGTH 0x0FFF0000 +#define FLD_DIF_AGC_GAIN 0x0000FFFF /*****************************************************************************/ -#define DIF_VID_AUD_OVERRIDE (DIRECT_IF_REVB_BASE + 0x00000030) /* Reg Size 32 */ +#define DIF_VID_AUD_OVERRIDE (DIRECT_IF_REVB_BASE + 0x00000030) /* Reg Size 32 */ /*****************************************************************************/ -#define FLD_DIF_AUDIO_AGC_OVERRIDE 0x80000000 +#define FLD_DIF_AUDIO_AGC_OVERRIDE 0x80000000 /* Reserved [30:30] */ -#define FLD_DIF_AUDIO_MAN_GAIN 0x3F000000 +#define FLD_DIF_AUDIO_MAN_GAIN 0x3F000000 /* Reserved [23:17] */ -#define FLD_DIF_VID_AGC_OVERRIDE 0x00010000 -#define FLD_DIF_VID_MAN_GAIN 0x0000FFFF +#define FLD_DIF_VID_AGC_OVERRIDE 0x00010000 +#define FLD_DIF_VID_MAN_GAIN 0x0000FFFF /*****************************************************************************/ -#define DIF_AV_SEP_CTRL (DIRECT_IF_REVB_BASE + 0x00000034) /* Reg Size 32 */ +#define DIF_AV_SEP_CTRL (DIRECT_IF_REVB_BASE + 0x00000034) /* Reg Size 32 */ /*****************************************************************************/ -#define FLD_DIF_LPF_FREQ 0xC0000000 -#define FLD_DIF_AV_PHASE_INC 0x3F000000 -#define FLD_DIF_AUDIO_FREQ 0x00FFFFFF +#define FLD_DIF_LPF_FREQ 0xC0000000 +#define FLD_DIF_AV_PHASE_INC 0x3F000000 +#define FLD_DIF_AUDIO_FREQ 0x00FFFFFF /*****************************************************************************/ -#define DIF_COMP_FLT_CTRL (DIRECT_IF_REVB_BASE + 0x00000038) /* Reg Size 32 */ +#define DIF_COMP_FLT_CTRL (DIRECT_IF_REVB_BASE + 0x00000038) /* Reg Size 32 */ /*****************************************************************************/ /* Reserved [31:24] */ -#define FLD_DIF_IIR23_R2 0x00FF0000 -#define FLD_DIF_IIR23_R1 0x0000FF00 -#define FLD_DIF_IIR1_R1 0x000000FF - -/*****************************************************************************/ -#define DIF_MISC_CTRL (DIRECT_IF_REVB_BASE + 0x0000003C) /* Reg Size 32 */ -/*****************************************************************************/ -#define FLD_DIF_DIF_BYPASS 0x80000000 -#define FLD_DIF_FM_NYQ_GAIN 0x40000000 -#define FLD_DIF_RF_AGC_ENA 0x20000000 -#define FLD_DIF_INT_AGC_ENA 0x10000000 -#define FLD_DIF_IF_AGC_ENA 0x08000000 -#define FLD_DIF_FORCE_RF_IF_LOCK 0x04000000 -#define FLD_DIF_VIDEO_AGC_ENA 0x02000000 -#define FLD_DIF_RF_AGC_INV 0x01000000 -#define FLD_DIF_INT_AGC_INV 0x00800000 -#define FLD_DIF_IF_AGC_INV 0x00400000 -#define FLD_DIF_SPEC_INV 0x00200000 -#define FLD_DIF_AUD_FULL_BW 0x00100000 -#define FLD_DIF_AUD_SRC_SEL 0x00080000 +#define FLD_DIF_IIR23_R2 0x00FF0000 +#define FLD_DIF_IIR23_R1 0x0000FF00 +#define FLD_DIF_IIR1_R1 0x000000FF + +/*****************************************************************************/ +#define DIF_MISC_CTRL (DIRECT_IF_REVB_BASE + 0x0000003C) /* Reg Size 32 */ +/*****************************************************************************/ +#define FLD_DIF_DIF_BYPASS 0x80000000 +#define FLD_DIF_FM_NYQ_GAIN 0x40000000 +#define FLD_DIF_RF_AGC_ENA 0x20000000 +#define FLD_DIF_INT_AGC_ENA 0x10000000 +#define FLD_DIF_IF_AGC_ENA 0x08000000 +#define FLD_DIF_FORCE_RF_IF_LOCK 0x04000000 +#define FLD_DIF_VIDEO_AGC_ENA 0x02000000 +#define FLD_DIF_RF_AGC_INV 0x01000000 +#define FLD_DIF_INT_AGC_INV 0x00800000 +#define FLD_DIF_IF_AGC_INV 0x00400000 +#define FLD_DIF_SPEC_INV 0x00200000 +#define FLD_DIF_AUD_FULL_BW 0x00100000 +#define FLD_DIF_AUD_SRC_SEL 0x00080000 /* Reserved [18] */ -#define FLD_DIF_IF_FREQ 0x00030000 +#define FLD_DIF_IF_FREQ 0x00030000 /* Reserved [15:14] */ -#define FLD_DIF_TIP_OFFSET 0x00003F00 +#define FLD_DIF_TIP_OFFSET 0x00003F00 /* Reserved [7:5] */ -#define FLD_DIF_DITHER_ENA 0x00000010 +#define FLD_DIF_DITHER_ENA 0x00000010 /* Reserved [3:1] */ -#define FLD_DIF_RF_IF_LOCK 0x00000001 +#define FLD_DIF_RF_IF_LOCK 0x00000001 /*****************************************************************************/ -#define DIF_SRC_PHASE_INC (DIRECT_IF_REVB_BASE + 0x00000040) /* Reg Size 32 */ +#define DIF_SRC_PHASE_INC (DIRECT_IF_REVB_BASE + 0x00000040) /* Reg Size 32 */ /*****************************************************************************/ /* Reserved [31:29] */ -#define FLD_DIF_PHASE_INC 0x1FFFFFFF +#define FLD_DIF_PHASE_INC 0x1FFFFFFF /*****************************************************************************/ -#define DIF_SRC_GAIN_CONTROL (DIRECT_IF_REVB_BASE + 0x00000044) /* Reg Size 32 */ +#define DIF_SRC_GAIN_CONTROL (DIRECT_IF_REVB_BASE + 0x00000044) /* Reg Size 32 */ /*****************************************************************************/ /* Reserved [31:16] */ -#define FLD_DIF_SRC_KI 0x0000FF00 -#define FLD_DIF_SRC_KD 0x000000FF +#define FLD_DIF_SRC_KI 0x0000FF00 +#define FLD_DIF_SRC_KD 0x000000FF /*****************************************************************************/ -#define DIF_BPF_COEFF01 (DIRECT_IF_REVB_BASE + 0x00000048) /* Reg Size 32 */ +#define DIF_BPF_COEFF01 (DIRECT_IF_REVB_BASE + 0x00000048) /* Reg Size 32 */ /*****************************************************************************/ /* Reserved [31:19] */ -#define FLD_DIF_BPF_COEFF_0 0x00070000 +#define FLD_DIF_BPF_COEFF_0 0x00070000 /* Reserved [15:4] */ -#define FLD_DIF_BPF_COEFF_1 0x0000000F +#define FLD_DIF_BPF_COEFF_1 0x0000000F /*****************************************************************************/ -#define DIF_BPF_COEFF23 (DIRECT_IF_REVB_BASE + 0x0000004c) /* Reg Size 32 */ +#define DIF_BPF_COEFF23 (DIRECT_IF_REVB_BASE + 0x0000004c) /* Reg Size 32 */ /*****************************************************************************/ /* Reserved [31:22] */ -#define FLD_DIF_BPF_COEFF_2 0x003F0000 +#define FLD_DIF_BPF_COEFF_2 0x003F0000 /* Reserved [15:7] */ -#define FLD_DIF_BPF_COEFF_3 0x0000007F +#define FLD_DIF_BPF_COEFF_3 0x0000007F /*****************************************************************************/ -#define DIF_BPF_COEFF45 (DIRECT_IF_REVB_BASE + 0x00000050) /* Reg Size 32 */ +#define DIF_BPF_COEFF45 (DIRECT_IF_REVB_BASE + 0x00000050) /* Reg Size 32 */ /*****************************************************************************/ /* Reserved [31:24] */ -#define FLD_DIF_BPF_COEFF_4 0x00FF0000 +#define FLD_DIF_BPF_COEFF_4 0x00FF0000 /* Reserved [15:8] */ -#define FLD_DIF_BPF_COEFF_5 0x000000FF +#define FLD_DIF_BPF_COEFF_5 0x000000FF /*****************************************************************************/ -#define DIF_BPF_COEFF67 (DIRECT_IF_REVB_BASE + 0x00000054) /* Reg Size 32 */ +#define DIF_BPF_COEFF67 (DIRECT_IF_REVB_BASE + 0x00000054) /* Reg Size 32 */ /*****************************************************************************/ /* Reserved [31:25] */ -#define FLD_DIF_BPF_COEFF_6 0x01FF0000 +#define FLD_DIF_BPF_COEFF_6 0x01FF0000 /* Reserved [15:9] */ -#define FLD_DIF_BPF_COEFF_7 0x000001FF +#define FLD_DIF_BPF_COEFF_7 0x000001FF /*****************************************************************************/ -#define DIF_BPF_COEFF89 (DIRECT_IF_REVB_BASE + 0x00000058) /* Reg Size 32 */ +#define DIF_BPF_COEFF89 (DIRECT_IF_REVB_BASE + 0x00000058) /* Reg Size 32 */ /*****************************************************************************/ /* Reserved [31:26] */ -#define FLD_DIF_BPF_COEFF_8 0x03FF0000 +#define FLD_DIF_BPF_COEFF_8 0x03FF0000 /* Reserved [15:10] */ -#define FLD_DIF_BPF_COEFF_9 0x000003FF +#define FLD_DIF_BPF_COEFF_9 0x000003FF /*****************************************************************************/ -#define DIF_BPF_COEFF1011 (DIRECT_IF_REVB_BASE + 0x0000005C) /* Reg Size 32 */ +#define DIF_BPF_COEFF1011 (DIRECT_IF_REVB_BASE + 0x0000005C) /* Reg Size 32 */ /*****************************************************************************/ /* Reserved [31:27] */ -#define FLD_DIF_BPF_COEFF_10 0x07FF0000 +#define FLD_DIF_BPF_COEFF_10 0x07FF0000 /* Reserved [15:11] */ -#define FLD_DIF_BPF_COEFF_11 0x000007FF +#define FLD_DIF_BPF_COEFF_11 0x000007FF /*****************************************************************************/ -#define DIF_BPF_COEFF1213 (DIRECT_IF_REVB_BASE + 0x00000060) /* Reg Size 32 */ +#define DIF_BPF_COEFF1213 (DIRECT_IF_REVB_BASE + 0x00000060) /* Reg Size 32 */ /*****************************************************************************/ /* Reserved [31:27] */ -#define FLD_DIF_BPF_COEFF_12 0x07FF0000 +#define FLD_DIF_BPF_COEFF_12 0x07FF0000 /* Reserved [15:12] */ -#define FLD_DIF_BPF_COEFF_13 0x00000FFF +#define FLD_DIF_BPF_COEFF_13 0x00000FFF /*****************************************************************************/ -#define DIF_BPF_COEFF1415 (DIRECT_IF_REVB_BASE + 0x00000064) /* Reg Size 32 */ +#define DIF_BPF_COEFF1415 (DIRECT_IF_REVB_BASE + 0x00000064) /* Reg Size 32 */ /*****************************************************************************/ /* Reserved [31:28] */ -#define FLD_DIF_BPF_COEFF_14 0x0FFF0000 +#define FLD_DIF_BPF_COEFF_14 0x0FFF0000 /* Reserved [15:12] */ -#define FLD_DIF_BPF_COEFF_15 0x00000FFF +#define FLD_DIF_BPF_COEFF_15 0x00000FFF /*****************************************************************************/ -#define DIF_BPF_COEFF1617 (DIRECT_IF_REVB_BASE + 0x00000068) /* Reg Size 32 */ +#define DIF_BPF_COEFF1617 (DIRECT_IF_REVB_BASE + 0x00000068) /* Reg Size 32 */ /*****************************************************************************/ /* Reserved [31:29] */ -#define FLD_DIF_BPF_COEFF_16 0x1FFF0000 +#define FLD_DIF_BPF_COEFF_16 0x1FFF0000 /* Reserved [15:13] */ -#define FLD_DIF_BPF_COEFF_17 0x00001FFF +#define FLD_DIF_BPF_COEFF_17 0x00001FFF /*****************************************************************************/ -#define DIF_BPF_COEFF1819 (DIRECT_IF_REVB_BASE + 0x0000006C) /* Reg Size 32 */ +#define DIF_BPF_COEFF1819 (DIRECT_IF_REVB_BASE + 0x0000006C) /* Reg Size 32 */ /*****************************************************************************/ /* Reserved [31:29] */ -#define FLD_DIF_BPF_COEFF_18 0x1FFF0000 +#define FLD_DIF_BPF_COEFF_18 0x1FFF0000 /* Reserved [15:13] */ -#define FLD_DIF_BPF_COEFF_19 0x00001FFF +#define FLD_DIF_BPF_COEFF_19 0x00001FFF /*****************************************************************************/ -#define DIF_BPF_COEFF2021 (DIRECT_IF_REVB_BASE + 0x00000070) /* Reg Size 32 */ +#define DIF_BPF_COEFF2021 (DIRECT_IF_REVB_BASE + 0x00000070) /* Reg Size 32 */ /*****************************************************************************/ /* Reserved [31:29] */ -#define FLD_DIF_BPF_COEFF_20 0x1FFF0000 +#define FLD_DIF_BPF_COEFF_20 0x1FFF0000 /* Reserved [15:14] */ -#define FLD_DIF_BPF_COEFF_21 0x00003FFF +#define FLD_DIF_BPF_COEFF_21 0x00003FFF /*****************************************************************************/ -#define DIF_BPF_COEFF2223 (DIRECT_IF_REVB_BASE + 0x00000074) /* Reg Size 32 */ +#define DIF_BPF_COEFF2223 (DIRECT_IF_REVB_BASE + 0x00000074) /* Reg Size 32 */ /*****************************************************************************/ /* Reserved [31:30] */ -#define FLD_DIF_BPF_COEFF_22 0x3FFF0000 +#define FLD_DIF_BPF_COEFF_22 0x3FFF0000 /* Reserved [15:14] */ -#define FLD_DIF_BPF_COEFF_23 0x00003FFF +#define FLD_DIF_BPF_COEFF_23 0x00003FFF /*****************************************************************************/ -#define DIF_BPF_COEFF2425 (DIRECT_IF_REVB_BASE + 0x00000078) /* Reg Size 32 */ +#define DIF_BPF_COEFF2425 (DIRECT_IF_REVB_BASE + 0x00000078) /* Reg Size 32 */ /*****************************************************************************/ /* Reserved [31:30] */ -#define FLD_DIF_BPF_COEFF_24 0x3FFF0000 +#define FLD_DIF_BPF_COEFF_24 0x3FFF0000 /* Reserved [15:14] */ -#define FLD_DIF_BPF_COEFF_25 0x00003FFF +#define FLD_DIF_BPF_COEFF_25 0x00003FFF /*****************************************************************************/ -#define DIF_BPF_COEFF2627 (DIRECT_IF_REVB_BASE + 0x0000007C) /* Reg Size 32 */ +#define DIF_BPF_COEFF2627 (DIRECT_IF_REVB_BASE + 0x0000007C) /* Reg Size 32 */ /*****************************************************************************/ /* Reserved [31:30] */ -#define FLD_DIF_BPF_COEFF_26 0x3FFF0000 +#define FLD_DIF_BPF_COEFF_26 0x3FFF0000 /* Reserved [15:14] */ -#define FLD_DIF_BPF_COEFF_27 0x00003FFF +#define FLD_DIF_BPF_COEFF_27 0x00003FFF /*****************************************************************************/ -#define DIF_BPF_COEFF2829 (DIRECT_IF_REVB_BASE + 0x00000080) /* Reg Size 32 */ +#define DIF_BPF_COEFF2829 (DIRECT_IF_REVB_BASE + 0x00000080) /* Reg Size 32 */ /*****************************************************************************/ /* Reserved [31:30] */ -#define FLD_DIF_BPF_COEFF_28 0x3FFF0000 +#define FLD_DIF_BPF_COEFF_28 0x3FFF0000 /* Reserved [15:14] */ -#define FLD_DIF_BPF_COEFF_29 0x00003FFF +#define FLD_DIF_BPF_COEFF_29 0x00003FFF /*****************************************************************************/ -#define DIF_BPF_COEFF3031 (DIRECT_IF_REVB_BASE + 0x00000084) /* Reg Size 32 */ +#define DIF_BPF_COEFF3031 (DIRECT_IF_REVB_BASE + 0x00000084) /* Reg Size 32 */ /*****************************************************************************/ /* Reserved [31:30] */ -#define FLD_DIF_BPF_COEFF_30 0x3FFF0000 +#define FLD_DIF_BPF_COEFF_30 0x3FFF0000 /* Reserved [15:14] */ -#define FLD_DIF_BPF_COEFF_31 0x00003FFF +#define FLD_DIF_BPF_COEFF_31 0x00003FFF /*****************************************************************************/ -#define DIF_BPF_COEFF3233 (DIRECT_IF_REVB_BASE + 0x00000088) /* Reg Size 32 */ +#define DIF_BPF_COEFF3233 (DIRECT_IF_REVB_BASE + 0x00000088) /* Reg Size 32 */ /*****************************************************************************/ /* Reserved [31:30] */ -#define FLD_DIF_BPF_COEFF_32 0x3FFF0000 +#define FLD_DIF_BPF_COEFF_32 0x3FFF0000 /* Reserved [15:14] */ -#define FLD_DIF_BPF_COEFF_33 0x00003FFF +#define FLD_DIF_BPF_COEFF_33 0x00003FFF /*****************************************************************************/ -#define DIF_BPF_COEFF3435 (DIRECT_IF_REVB_BASE + 0x0000008C) /* Reg Size 32 */ +#define DIF_BPF_COEFF3435 (DIRECT_IF_REVB_BASE + 0x0000008C) /* Reg Size 32 */ /*****************************************************************************/ /* Reserved [31:30] */ -#define FLD_DIF_BPF_COEFF_34 0x3FFF0000 +#define FLD_DIF_BPF_COEFF_34 0x3FFF0000 /* Reserved [15:14] */ -#define FLD_DIF_BPF_COEFF_35 0x00003FFF +#define FLD_DIF_BPF_COEFF_35 0x00003FFF /*****************************************************************************/ -#define DIF_BPF_COEFF36 (DIRECT_IF_REVB_BASE + 0x00000090) /* Reg Size 32 */ +#define DIF_BPF_COEFF36 (DIRECT_IF_REVB_BASE + 0x00000090) /* Reg Size 32 */ /*****************************************************************************/ /* Reserved [31:30] */ -#define FLD_DIF_BPF_COEFF_36 0x3FFF0000 +#define FLD_DIF_BPF_COEFF_36 0x3FFF0000 /* Reserved [15:0] */ /*****************************************************************************/ -#define DIF_RPT_VARIANCE (DIRECT_IF_REVB_BASE + 0x00000094) /* Reg Size 32 */ +#define DIF_RPT_VARIANCE (DIRECT_IF_REVB_BASE + 0x00000094) /* Reg Size 32 */ /*****************************************************************************/ /* Reserved [31:20] */ -#define FLD_DIF_RPT_VARIANCE 0x000FFFFF +#define FLD_DIF_RPT_VARIANCE 0x000FFFFF /*****************************************************************************/ -#define DIF_SOFT_RST_CTRL_REVB (DIRECT_IF_REVB_BASE + 0x00000098) /* Reg Size 32 */ +#define DIF_SOFT_RST_CTRL_REVB (DIRECT_IF_REVB_BASE + 0x00000098) /* Reg Size 32 */ /*****************************************************************************/ /* Reserved [31:8] */ -#define FLD_DIF_DIF_SOFT_RST 0x00000080 -#define FLD_DIF_DIF_REG_RST_MSK 0x00000040 -#define FLD_DIF_AGC_RST_MSK 0x00000020 -#define FLD_DIF_CMP_RST_MSK 0x00000010 -#define FLD_DIF_AVS_RST_MSK 0x00000008 -#define FLD_DIF_NYQ_RST_MSK 0x00000004 -#define FLD_DIF_DIF_SRC_RST_MSK 0x00000002 -#define FLD_DIF_PLL_RST_MSK 0x00000001 +#define FLD_DIF_DIF_SOFT_RST 0x00000080 +#define FLD_DIF_DIF_REG_RST_MSK 0x00000040 +#define FLD_DIF_AGC_RST_MSK 0x00000020 +#define FLD_DIF_CMP_RST_MSK 0x00000010 +#define FLD_DIF_AVS_RST_MSK 0x00000008 +#define FLD_DIF_NYQ_RST_MSK 0x00000004 +#define FLD_DIF_DIF_SRC_RST_MSK 0x00000002 +#define FLD_DIF_PLL_RST_MSK 0x00000001 /*****************************************************************************/ -#define DIF_PLL_FREQ_ERR (DIRECT_IF_REVB_BASE + 0x0000009C) /* Reg Size 32 */ +#define DIF_PLL_FREQ_ERR (DIRECT_IF_REVB_BASE + 0x0000009C) /* Reg Size 32 */ /*****************************************************************************/ /* Reserved [31:25] */ -#define FLD_DIF_CTL_IP 0x01FFFFFF - +#define FLD_DIF_CTL_IP 0x01FFFFFF #endif diff --git a/linux/drivers/media/video/cx231xx/cx231xx-core.c b/linux/drivers/media/video/cx231xx/cx231xx-core.c index 44bb8660a..73e8837b7 100644 --- a/linux/drivers/media/video/cx231xx/cx231xx-core.c +++ b/linux/drivers/media/video/cx231xx/cx231xx-core.c @@ -2,7 +2,7 @@ cx231xx-core.c - driver for Conexant Cx23100/101/102 USB video capture devices Copyright (C) 2008 - Based on em28xx driver + Based on em28xx driver 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 @@ -32,8 +32,8 @@ /* #define ENABLE_DEBUG_ISOC_FRAMES */ static unsigned int core_debug; -module_param(core_debug,int,0644); -MODULE_PARM_DESC(core_debug,"enable debug messages [core]"); +module_param(core_debug, int, 0644); +MODULE_PARM_DESC(core_debug, "enable debug messages [core]"); #define cx231xx_coredbg(fmt, arg...) do {\ if (core_debug) \ @@ -41,8 +41,8 @@ MODULE_PARM_DESC(core_debug,"enable debug messages [core]"); dev->name, __func__ , ##arg); } while (0) static unsigned int reg_debug; -module_param(reg_debug,int,0644); -MODULE_PARM_DESC(reg_debug,"enable debug messages [URB reg]"); +module_param(reg_debug, int, 0644); +MODULE_PARM_DESC(reg_debug, "enable debug messages [URB reg]"); #define cx231xx_regdbg(fmt, arg...) do {\ if (reg_debug) \ @@ -59,8 +59,6 @@ MODULE_PARM_DESC(alt, "alternate setting to use for video endpoint"); printk(KERN_INFO "%s %s :"fmt, \ dev->name, __func__ , ##arg); } while (0) - - /************************************************************************************ * Device control list functions * *************************************************************************************/ @@ -69,8 +67,7 @@ static LIST_HEAD(cx231xx_devlist); static DEFINE_MUTEX(cx231xx_devlist_mutex); struct cx231xx *cx231xx_get_device(int minor, - enum v4l2_buf_type *fh_type, - int *has_radio) + enum v4l2_buf_type *fh_type, int *has_radio) { struct cx231xx *h, *dev = NULL; @@ -85,8 +82,7 @@ struct cx231xx *cx231xx_get_device(int minor, dev = h; *fh_type = V4L2_BUF_TYPE_VBI_CAPTURE; } - if (h->radio_dev && - h->radio_dev->minor == minor) { + if (h->radio_dev && h->radio_dev->minor == minor) { dev = h; *has_radio = 1; } @@ -115,9 +111,6 @@ void cx231xx_add_into_devlist(struct cx231xx *dev) mutex_unlock(&cx231xx_devlist_mutex); }; - - - static LIST_HEAD(cx231xx_extension_devlist); static DEFINE_MUTEX(cx231xx_extension_devlist_lock); @@ -137,6 +130,7 @@ int cx231xx_register_extension(struct cx231xx_ops *ops) mutex_unlock(&cx231xx_devlist_mutex); return 0; } + EXPORT_SYMBOL(cx231xx_register_extension); void cx231xx_unregister_extension(struct cx231xx_ops *ops) @@ -155,8 +149,8 @@ void cx231xx_unregister_extension(struct cx231xx_ops *ops) mutex_unlock(&cx231xx_extension_devlist_lock); mutex_unlock(&cx231xx_devlist_mutex); } -EXPORT_SYMBOL(cx231xx_unregister_extension); +EXPORT_SYMBOL(cx231xx_unregister_extension); void cx231xx_init_extension(struct cx231xx *dev) { @@ -189,97 +183,102 @@ void cx231xx_close_extension(struct cx231xx *dev) /************************************************************************************ * U S B related functions * *************************************************************************************/ -int cx231xx_send_usb_command(struct cx231xx_i2c *i2c_bus, - struct cx231xx_i2c_xfer_data *req_data) +int cx231xx_send_usb_command(struct cx231xx_i2c *i2c_bus, + struct cx231xx_i2c_xfer_data *req_data) { - int status = 0; - struct cx231xx *dev = i2c_bus->dev; - VENDOR_REQUEST_IN ven_req; - - u8 saddr_len = 0; - u8 _i2c_period = 0; - u8 _i2c_nostop = 0; - u8 _i2c_reserve = 0; - - /* Get the I2C period, nostop and reserve parameters */ - _i2c_period = i2c_bus->i2c_period; - _i2c_nostop = i2c_bus->i2c_nostop; - _i2c_reserve = i2c_bus->i2c_reserve; - - saddr_len = req_data->saddr_len; - - /* Set wValue */ - if(saddr_len == 1) /* need check saddr_len == 0 */ - ven_req.wValue = req_data->dev_addr<<9|_i2c_period<<4|saddr_len<<2| - _i2c_nostop<<1|I2C_SYNC|_i2c_reserve<<6; - else - ven_req.wValue = req_data->dev_addr<<9|_i2c_period<<4|saddr_len<<2| - _i2c_nostop<<1|I2C_SYNC|_i2c_reserve<<6; - - /* set channel number */ - if(req_data->direction & I2C_M_RD) - ven_req.bRequest = i2c_bus->nr + 4; /* channel number, for read, - spec required channel_num +4 */ - else - ven_req.bRequest = i2c_bus->nr; /* channel number, */ - - /* set index value */ - switch(saddr_len){ - case 0: - ven_req.wIndex = 0; /* need check */ - break; - case 1: - ven_req.wIndex = (req_data->saddr_dat & 0xff); - break; - case 2: - ven_req.wIndex = req_data->saddr_dat; - break; - } - - /* set wLength value */ - ven_req.wLength = req_data->buf_size; - - /* set bData value */ - ven_req.bData = 0; - - /* set the direction */ - if(req_data->direction){ - ven_req.direction = USB_DIR_IN; - memset(req_data->p_buffer, 0x00, ven_req.wLength); - } - else - ven_req.direction = USB_DIR_OUT; - - /* set the buffer for read / write */ - ven_req.pBuff = req_data->p_buffer; - + int status = 0; + struct cx231xx *dev = i2c_bus->dev; + VENDOR_REQUEST_IN ven_req; + + u8 saddr_len = 0; + u8 _i2c_period = 0; + u8 _i2c_nostop = 0; + u8 _i2c_reserve = 0; + + /* Get the I2C period, nostop and reserve parameters */ + _i2c_period = i2c_bus->i2c_period; + _i2c_nostop = i2c_bus->i2c_nostop; + _i2c_reserve = i2c_bus->i2c_reserve; + + saddr_len = req_data->saddr_len; + + /* Set wValue */ + if (saddr_len == 1) /* need check saddr_len == 0 */ + ven_req.wValue = + req_data-> + dev_addr << 9 | _i2c_period << 4 | saddr_len << 2 | + _i2c_nostop << 1 | I2C_SYNC | _i2c_reserve << 6; + else + ven_req.wValue = + req_data-> + dev_addr << 9 | _i2c_period << 4 | saddr_len << 2 | + _i2c_nostop << 1 | I2C_SYNC | _i2c_reserve << 6; + + /* set channel number */ + if (req_data->direction & I2C_M_RD) + ven_req.bRequest = i2c_bus->nr + 4; /* channel number, for read, + spec required channel_num +4 */ + else + ven_req.bRequest = i2c_bus->nr; /* channel number, */ + + /* set index value */ + switch (saddr_len) { + case 0: + ven_req.wIndex = 0; /* need check */ + break; + case 1: + ven_req.wIndex = (req_data->saddr_dat & 0xff); + break; + case 2: + ven_req.wIndex = req_data->saddr_dat; + break; + } + + /* set wLength value */ + ven_req.wLength = req_data->buf_size; + + /* set bData value */ + ven_req.bData = 0; + + /* set the direction */ + if (req_data->direction) { + ven_req.direction = USB_DIR_IN; + memset(req_data->p_buffer, 0x00, ven_req.wLength); + } else + ven_req.direction = USB_DIR_OUT; + + /* set the buffer for read / write */ + ven_req.pBuff = req_data->p_buffer; #if 0 - { - int i = 0; - - cx231xx_isocdbg(": USB Control Pipe Request: I2C Bus#%d\n",i2c_bus->nr); - cx231xx_isocdbg("bRequest = %x : ", ven_req.bRequest); - cx231xx_isocdbg("wValue = %x : ", ven_req.wValue); - cx231xx_isocdbg("wIndex = %x : ",ven_req.wIndex); - cx231xx_isocdbg("wLength = %x\n",ven_req.wLength); - cx231xx_isocdbg("pBuff : "); - for(i =0; i 0 ) && (i % 10 == 0 ) ) - cx231xx_isocdbg("\n "); - } - cx231xx_isocdbg("\n\n"); - } -#endif - - /* call common vendor command request */ - status = cx231xx_send_vendor_cmd(dev, &ven_req); - if (status < 0) { - cx231xx_info("UsbInterface::sendCommand, output buffer failed with status -%d\n", status); - } - - return status; + { + int i = 0; + + cx231xx_isocdbg(": USB Control Pipe Request: I2C Bus#%d\n", + i2c_bus->nr); + cx231xx_isocdbg("bRequest = %x : ", ven_req.bRequest); + cx231xx_isocdbg("wValue = %x : ", ven_req.wValue); + cx231xx_isocdbg("wIndex = %x : ", ven_req.wIndex); + cx231xx_isocdbg("wLength = %x\n", ven_req.wLength); + cx231xx_isocdbg("pBuff : "); + for (i = 0; i < ven_req.wLength; i++) { + cx231xx_isocdbg(" %2x", ven_req.pBuff[i]); + if ((i > 0) && (i % 10 == 0)) + cx231xx_isocdbg("\n "); + } + cx231xx_isocdbg("\n\n"); + } +#endif + + /* call common vendor command request */ + status = cx231xx_send_vendor_cmd(dev, &ven_req); + if (status < 0) { + cx231xx_info + ("UsbInterface::sendCommand, output buffer failed with status -%d\n", + status); + } + + return status; } EXPORT_SYMBOL_GPL(cx231xx_send_usb_command); @@ -288,9 +287,9 @@ EXPORT_SYMBOL_GPL(cx231xx_send_usb_command); * reads data from the usb device specifying bRequest and wValue */ int cx231xx_read_ctrl_reg(struct cx231xx *dev, u8 req, u16 reg, - char *buf, int len) + char *buf, int len) { - u8 val = 0; + u8 val = 0; int ret; int pipe = usb_rcvctrlpipe(dev->udev, 0); @@ -300,35 +299,33 @@ int cx231xx_read_ctrl_reg(struct cx231xx *dev, u8 req, u16 reg, if (len > URB_MAX_CTRL_SIZE) return -EINVAL; - switch(len) - { - case 1: - val = ENABLE_ONE_BYTE; - break; - case 2: - val = ENABLE_TWE_BYTE; - break; - case 3: - val = ENABLE_THREE_BYTE; - break; - case 4: - val = ENABLE_FOUR_BYTE; - break; - default: - val = 0xFF; /* invalid option */ - } - - if(val == 0xFF) - return -EINVAL; + switch (len) { + case 1: + val = ENABLE_ONE_BYTE; + break; + case 2: + val = ENABLE_TWE_BYTE; + break; + case 3: + val = ENABLE_THREE_BYTE; + break; + case 4: + val = ENABLE_FOUR_BYTE; + break; + default: + val = 0xFF; /* invalid option */ + } + + if (val == 0xFF) + return -EINVAL; if (reg_debug) { cx231xx_isocdbg("(pipe 0x%08x): " - "IN: %02x %02x %02x %02x %02x %02x %02x %02x ", - pipe, - USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - req, 0, val, - reg & 0xff, reg >> 8, - len & 0xff, len >> 8); + "IN: %02x %02x %02x %02x %02x %02x %02x %02x ", + pipe, + USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, + req, 0, val, + reg & 0xff, reg >> 8, len & 0xff, len >> 8); } /* mutex_lock(&dev->ctrl_urb_lock); */ @@ -358,44 +355,45 @@ int cx231xx_read_ctrl_reg(struct cx231xx *dev, u8 req, u16 reg, return ret; } - -int cx231xx_send_vendor_cmd(struct cx231xx *dev, VENDOR_REQUEST_IN *ven_req) +int cx231xx_send_vendor_cmd(struct cx231xx *dev, VENDOR_REQUEST_IN * ven_req) { - int ret; + int ret; int pipe = 0; - + if (dev->state & DEV_DISCONNECTED) return -ENODEV; if ((ven_req->wLength > URB_MAX_CTRL_SIZE)) return -EINVAL; - if(ven_req->direction) - pipe = usb_rcvctrlpipe(dev->udev, 0); - else - pipe = usb_sndctrlpipe(dev->udev, 0); - + if (ven_req->direction) + pipe = usb_rcvctrlpipe(dev->udev, 0); + else + pipe = usb_sndctrlpipe(dev->udev, 0); if (reg_debug) { int byte; cx231xx_isocdbg("(pipe 0x%08x): " - "OUT: %02x %02x %02x %04x %04x %04x >>>", - pipe, - ven_req->direction | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - ven_req->bRequest, 0, ven_req->wValue, - ven_req->wIndex, - ven_req->wLength); + "OUT: %02x %02x %02x %04x %04x %04x >>>", + pipe, + ven_req-> + direction | USB_TYPE_VENDOR | USB_RECIP_DEVICE, + ven_req->bRequest, 0, ven_req->wValue, + ven_req->wIndex, ven_req->wLength); for (byte = 0; byte < ven_req->wLength; byte++) - cx231xx_isocdbg(" %02x", (unsigned char)ven_req->pBuff[byte]); + cx231xx_isocdbg(" %02x", + (unsigned char)ven_req->pBuff[byte]); cx231xx_isocdbg("\n"); } /* mutex_lock(&dev->ctrl_urb_lock); */ ret = usb_control_msg(dev->udev, pipe, ven_req->bRequest, - ven_req->direction | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - ven_req->wValue, ven_req->wIndex, ven_req->pBuff, ven_req->wLength, HZ); + ven_req-> + direction | USB_TYPE_VENDOR | USB_RECIP_DEVICE, + ven_req->wValue, ven_req->wIndex, ven_req->pBuff, + ven_req->wLength, HZ); /* mutex_unlock(&dev->ctrl_urb_lock); */ return ret; @@ -406,9 +404,9 @@ int cx231xx_send_vendor_cmd(struct cx231xx *dev, VENDOR_REQUEST_IN *ven_req) * sends data to the usb device, specifying bRequest */ int cx231xx_write_ctrl_reg(struct cx231xx *dev, u8 req, u16 reg, char *buf, - int len) + int len) { - u8 val = 0; + u8 val = 0; int ret; int pipe = usb_sndctrlpipe(dev->udev, 0); @@ -418,37 +416,35 @@ int cx231xx_write_ctrl_reg(struct cx231xx *dev, u8 req, u16 reg, char *buf, if ((len < 1) || (len > URB_MAX_CTRL_SIZE)) return -EINVAL; - switch(len) - { - case 1: - val = ENABLE_ONE_BYTE; - break; - case 2: - val = ENABLE_TWE_BYTE; - break; - case 3: - val = ENABLE_THREE_BYTE; - break; - case 4: - val = ENABLE_FOUR_BYTE; - break; - default: - val = 0xFF; /* invalid option */ - } - - if(val == 0xFF) - return -EINVAL; + switch (len) { + case 1: + val = ENABLE_ONE_BYTE; + break; + case 2: + val = ENABLE_TWE_BYTE; + break; + case 3: + val = ENABLE_THREE_BYTE; + break; + case 4: + val = ENABLE_FOUR_BYTE; + break; + default: + val = 0xFF; /* invalid option */ + } + + if (val == 0xFF) + return -EINVAL; if (reg_debug) { int byte; cx231xx_isocdbg("(pipe 0x%08x): " - "OUT: %02x %02x %02x %02x %02x %02x %02x %02x >>>", - pipe, - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - req, 0, val, - reg & 0xff, reg >> 8, - len & 0xff, len >> 8); + "OUT: %02x %02x %02x %02x %02x %02x %02x %02x >>>", + pipe, + USB_DIR_OUT | USB_TYPE_VENDOR | + USB_RECIP_DEVICE, req, 0, val, reg & 0xff, + reg >> 8, len & 0xff, len >> 8); for (byte = 0; byte < len; byte++) cx231xx_isocdbg(" %02x", (unsigned char)buf[byte]); @@ -465,7 +461,6 @@ int cx231xx_write_ctrl_reg(struct cx231xx *dev, u8 req, u16 reg, char *buf, return ret; } - /************************************************************************************ * USB Alternate Setting functions * *************************************************************************************/ @@ -474,7 +469,7 @@ int cx231xx_set_video_alternate(struct cx231xx *dev) { int errCode, prev_alt = dev->video_mode.alt; unsigned int min_pkt_size = dev->width * 2 + 4; - u32 usb_interface_index = 0; + u32 usb_interface_index = 0; /* When image size is bigger than a certain value, the frame size should be increased, otherwise, only @@ -483,35 +478,44 @@ int cx231xx_set_video_alternate(struct cx231xx *dev) if (dev->width * 2 * dev->height > 720 * 240 * 2) min_pkt_size *= 2; - if(dev->width > 360) { - /* resolutions: 720,704,640 */ - dev->video_mode.alt = 3; - } else if(dev->width > 180) { - /* resolutions: 360,352,320,240 */ - dev->video_mode.alt = 2; - } else if(dev->width > 0) { - /* resolutions: 180,176,160,128,88 */ - dev->video_mode.alt = 1; - } else { - /* Change to alt0 BULK to release USB bandwidth */ - dev->video_mode.alt = 0; - } - - /* Get the correct video interface Index */ - usb_interface_index = dev->current_pcb_config.hs_config_info[0].interface_info.video_index+1; + if (dev->width > 360) { + /* resolutions: 720,704,640 */ + dev->video_mode.alt = 3; + } else if (dev->width > 180) { + /* resolutions: 360,352,320,240 */ + dev->video_mode.alt = 2; + } else if (dev->width > 0) { + /* resolutions: 180,176,160,128,88 */ + dev->video_mode.alt = 1; + } else { + /* Change to alt0 BULK to release USB bandwidth */ + dev->video_mode.alt = 0; + } + + /* Get the correct video interface Index */ + usb_interface_index = + dev->current_pcb_config.hs_config_info[0].interface_info. + video_index + 1; if (dev->video_mode.alt != prev_alt) { cx231xx_coredbg("minimum isoc packet size: %u (alt=%d)\n", min_pkt_size, dev->video_mode.alt); - dev->video_mode.max_pkt_size = dev->video_mode.alt_max_pkt_size[dev->video_mode.alt]; + dev->video_mode.max_pkt_size = + dev->video_mode.alt_max_pkt_size[dev->video_mode.alt]; cx231xx_coredbg("setting alternate %d with wMaxPacketSize=%u\n", - dev->video_mode.alt, dev->video_mode.max_pkt_size); - cx231xx_info(" setting alternate %d with wMaxPacketSize=%u , Interface = %d\n", - dev->video_mode.alt, dev->video_mode.max_pkt_size, usb_interface_index); - errCode = usb_set_interface(dev->udev, usb_interface_index, dev->video_mode.alt); + dev->video_mode.alt, + dev->video_mode.max_pkt_size); + cx231xx_info + (" setting alternate %d with wMaxPacketSize=%u , Interface = %d\n", + dev->video_mode.alt, dev->video_mode.max_pkt_size, + usb_interface_index); + errCode = + usb_set_interface(dev->udev, usb_interface_index, + dev->video_mode.alt); if (errCode < 0) { - cx231xx_errdev("cannot change alternate number to %d (error=%i)\n", - dev->video_mode.alt, errCode); + cx231xx_errdev + ("cannot change alternate number to %d (error=%i)\n", + dev->video_mode.alt, errCode); return errCode; } } @@ -520,68 +524,92 @@ int cx231xx_set_video_alternate(struct cx231xx *dev) int cx231xx_set_alt_setting(struct cx231xx *dev, u8 index, u8 alt) { - int status = 0; - u32 usb_interface_index = 0; - u32 max_pkt_size = 0; - - switch(index) { - case INDEX_TS1: - usb_interface_index = dev->current_pcb_config.hs_config_info[0].interface_info.ts1_index+1; - dev->video_mode.alt = alt; - if(dev->ts1_mode.alt_max_pkt_size != NULL) - max_pkt_size = dev->ts1_mode.max_pkt_size = dev->ts1_mode.alt_max_pkt_size[dev->ts1_mode.alt]; - break; - case INDEX_TS2: - usb_interface_index = dev->current_pcb_config.hs_config_info[0].interface_info.ts2_index+1; - break; - case INDEX_AUDIO: - usb_interface_index = dev->current_pcb_config.hs_config_info[0].interface_info.audio_index+1; - dev->adev.alt = alt; - if( dev->adev.alt_max_pkt_size != NULL) - max_pkt_size = dev->adev.max_pkt_size = dev->adev.alt_max_pkt_size[dev->adev.alt]; - break; - case INDEX_VIDEO: - usb_interface_index = dev->current_pcb_config.hs_config_info[0].interface_info.video_index+1; - dev->video_mode.alt = alt; - if(dev->video_mode.alt_max_pkt_size != NULL) - max_pkt_size = dev->video_mode.max_pkt_size = dev->video_mode.alt_max_pkt_size[dev->video_mode.alt]; - break; - case INDEX_VANC: - usb_interface_index = dev->current_pcb_config.hs_config_info[0].interface_info.vanc_index+1; - dev->vbi_mode.alt = alt; - if(dev->vbi_mode.alt_max_pkt_size != NULL) - max_pkt_size = dev->vbi_mode.max_pkt_size = dev->vbi_mode.alt_max_pkt_size[dev->vbi_mode.alt]; - break; - case INDEX_HANC: - usb_interface_index = dev->current_pcb_config.hs_config_info[0].interface_info.hanc_index+1; - dev->sliced_cc_mode.alt = alt; - if(dev->sliced_cc_mode.alt_max_pkt_size != NULL) - max_pkt_size = dev->sliced_cc_mode.max_pkt_size = dev->sliced_cc_mode.alt_max_pkt_size[dev->sliced_cc_mode.alt]; - break; - default: - break; - } - - if(alt > 0 && max_pkt_size == 0 ) { - cx231xx_errdev("cannot change interface %d alternate number to %d : Max. Pkt size is ZERO\n", - usb_interface_index, alt); - return -1; - } - - cx231xx_info(" setting alternate %d with wMaxPacketSize=%u , Interface = %d\n", - alt, max_pkt_size, usb_interface_index); - - if(usb_interface_index > 0 ) { - status = usb_set_interface(dev->udev, usb_interface_index, alt); + int status = 0; + u32 usb_interface_index = 0; + u32 max_pkt_size = 0; + + switch (index) { + case INDEX_TS1: + usb_interface_index = + dev->current_pcb_config.hs_config_info[0].interface_info. + ts1_index + 1; + dev->video_mode.alt = alt; + if (dev->ts1_mode.alt_max_pkt_size != NULL) + max_pkt_size = dev->ts1_mode.max_pkt_size = + dev->ts1_mode.alt_max_pkt_size[dev->ts1_mode.alt]; + break; + case INDEX_TS2: + usb_interface_index = + dev->current_pcb_config.hs_config_info[0].interface_info. + ts2_index + 1; + break; + case INDEX_AUDIO: + usb_interface_index = + dev->current_pcb_config.hs_config_info[0].interface_info. + audio_index + 1; + dev->adev.alt = alt; + if (dev->adev.alt_max_pkt_size != NULL) + max_pkt_size = dev->adev.max_pkt_size = + dev->adev.alt_max_pkt_size[dev->adev.alt]; + break; + case INDEX_VIDEO: + usb_interface_index = + dev->current_pcb_config.hs_config_info[0].interface_info. + video_index + 1; + dev->video_mode.alt = alt; + if (dev->video_mode.alt_max_pkt_size != NULL) + max_pkt_size = dev->video_mode.max_pkt_size = + dev->video_mode.alt_max_pkt_size[dev->video_mode. + alt]; + break; + case INDEX_VANC: + usb_interface_index = + dev->current_pcb_config.hs_config_info[0].interface_info. + vanc_index + 1; + dev->vbi_mode.alt = alt; + if (dev->vbi_mode.alt_max_pkt_size != NULL) + max_pkt_size = dev->vbi_mode.max_pkt_size = + dev->vbi_mode.alt_max_pkt_size[dev->vbi_mode.alt]; + break; + case INDEX_HANC: + usb_interface_index = + dev->current_pcb_config.hs_config_info[0].interface_info. + hanc_index + 1; + dev->sliced_cc_mode.alt = alt; + if (dev->sliced_cc_mode.alt_max_pkt_size != NULL) + max_pkt_size = dev->sliced_cc_mode.max_pkt_size = + dev->sliced_cc_mode.alt_max_pkt_size[dev-> + sliced_cc_mode. + alt]; + break; + default: + break; + } + + if (alt > 0 && max_pkt_size == 0) { + cx231xx_errdev + ("cannot change interface %d alternate number to %d : Max. Pkt size is ZERO\n", + usb_interface_index, alt); + return -1; + } + + cx231xx_info + (" setting alternate %d with wMaxPacketSize=%u , Interface = %d\n", + alt, max_pkt_size, usb_interface_index); + + if (usb_interface_index > 0) { + status = usb_set_interface(dev->udev, usb_interface_index, alt); if (status < 0) { - cx231xx_errdev("cannot change interface %d alternate number to %d (error=%i)\n", - usb_interface_index, alt, status); + cx231xx_errdev + ("cannot change interface %d alternate number to %d (error=%i)\n", + usb_interface_index, alt, status); return status; } - } + } - return status; + return status; } + EXPORT_SYMBOL_GPL(cx231xx_set_alt_setting); int cx231xx_gpio_set(struct cx231xx *dev, struct cx231xx_reg_seq *gpio) @@ -593,10 +621,9 @@ int cx231xx_gpio_set(struct cx231xx *dev, struct cx231xx_reg_seq *gpio) /* Send GPIO reset sequences specified at board entry */ while (gpio->sleep >= 0) { - rc = cx231xx_set_gpio_value(dev, gpio->bit, - gpio->val); - if (rc < 0) - return rc; + rc = cx231xx_set_gpio_value(dev, gpio->bit, gpio->val); + if (rc < 0) + return rc; if (gpio->sleep > 0) msleep(gpio->sleep); @@ -612,7 +639,7 @@ int cx231xx_set_mode(struct cx231xx *dev, enum cx231xx_mode set_mode) return 0; if (set_mode == CX231XX_SUSPEND) { - /* Set the chip in power saving mode */ + /* Set the chip in power saving mode */ dev->mode = set_mode; } @@ -622,13 +649,14 @@ int cx231xx_set_mode(struct cx231xx *dev, enum cx231xx_mode set_mode) dev->mode = set_mode; - if (dev->mode == CX231XX_DIGITAL_MODE) { - /* Set Digital power mode */ - } else { - /* Set Analog Power mode*/ - } - return 0; + if (dev->mode == CX231XX_DIGITAL_MODE) { + /* Set Digital power mode */ + } else { + /* Set Analog Power mode */ + } + return 0; } + EXPORT_SYMBOL_GPL(cx231xx_set_mode); /************************************************************************************ @@ -644,23 +672,23 @@ static void cx231xx_irq_callback(struct urb *urb, struct pt_regs *regs) static void cx231xx_irq_callback(struct urb *urb) #endif { - struct cx231xx_dmaqueue *dma_q = urb->context; - struct cx231xx_video_mode *vmode = container_of(dma_q, struct cx231xx_video_mode, vidq); - struct cx231xx *dev = container_of(vmode, struct cx231xx, video_mode); + struct cx231xx_dmaqueue *dma_q = urb->context; + struct cx231xx_video_mode *vmode = + container_of(dma_q, struct cx231xx_video_mode, vidq); + struct cx231xx *dev = container_of(vmode, struct cx231xx, video_mode); int rc, i; - - switch (urb->status) { - case 0: /* success */ - case -ETIMEDOUT: /* NAK */ - break; - case -ECONNRESET: /* kill */ - case -ENOENT: - case -ESHUTDOWN: - return; - default: /* error */ - cx231xx_isocdbg("urb completition error %d.\n", urb->status); - break; + switch (urb->status) { + case 0: /* success */ + case -ETIMEDOUT: /* NAK */ + break; + case -ECONNRESET: /* kill */ + case -ENOENT: + case -ESHUTDOWN: + return; + default: /* error */ + cx231xx_isocdbg("urb completition error %d.\n", urb->status); + break; } /* Copy data from URB */ @@ -678,7 +706,7 @@ static void cx231xx_irq_callback(struct urb *urb) urb->status = usb_submit_urb(urb, GFP_ATOMIC); if (urb->status) { cx231xx_isocdbg("urb resubmit failed (error=%i)\n", - urb->status); + urb->status); } } @@ -696,16 +724,17 @@ void cx231xx_uninit_isoc(struct cx231xx *dev) for (i = 0; i < dev->video_mode.isoc_ctl.num_bufs; i++) { urb = dev->video_mode.isoc_ctl.urb[i]; if (urb) { - if (!irqs_disabled()) - usb_kill_urb(urb); - else - usb_unlink_urb(urb); + if (!irqs_disabled()) + usb_kill_urb(urb); + else + usb_unlink_urb(urb); if (dev->video_mode.isoc_ctl.transfer_buffer[i]) { usb_buffer_free(dev->udev, - urb->transfer_buffer_length, - dev->video_mode.isoc_ctl.transfer_buffer[i], - urb->transfer_dma); + urb->transfer_buffer_length, + dev->video_mode.isoc_ctl. + transfer_buffer[i], + urb->transfer_dma); } usb_free_urb(urb); dev->video_mode.isoc_ctl.urb[i] = NULL; @@ -720,16 +749,17 @@ void cx231xx_uninit_isoc(struct cx231xx *dev) dev->video_mode.isoc_ctl.transfer_buffer = NULL; dev->video_mode.isoc_ctl.num_bufs = 0; - cx231xx_capture_start(dev, 0, Raw_Video); + cx231xx_capture_start(dev, 0, Raw_Video); } + EXPORT_SYMBOL_GPL(cx231xx_uninit_isoc); /* * Allocate URBs and start IRQ */ int cx231xx_init_isoc(struct cx231xx *dev, int max_packets, - int num_bufs, int max_pkt_size, - int (*isoc_copy) (struct cx231xx *dev, struct urb *urb)) + int num_bufs, int max_pkt_size, + int (*isoc_copy) (struct cx231xx * dev, struct urb * urb)) { struct cx231xx_dmaqueue *dma_q = &dev->video_mode.vidq; int i; @@ -740,36 +770,36 @@ int cx231xx_init_isoc(struct cx231xx *dev, int max_packets, cx231xx_isocdbg("cx231xx: called cx231xx_prepare_isoc\n"); - dev->video_input = dev->video_input > 2?2:dev->video_input; - - cx231xx_info("Setting Video mux to %d\n",dev->video_input); - video_mux(dev, dev->video_input); + dev->video_input = dev->video_input > 2 ? 2 : dev->video_input; + cx231xx_info("Setting Video mux to %d\n", dev->video_input); + video_mux(dev, dev->video_input); /* De-allocates all pending stuff */ - cx231xx_uninit_isoc(dev); + cx231xx_uninit_isoc(dev); dev->video_mode.isoc_ctl.isoc_copy = isoc_copy; dev->video_mode.isoc_ctl.num_bufs = num_bufs; - dma_q->pos = 0; - dma_q->is_partial_line = 0; - dma_q->last_sav = 0; - dma_q->current_field = -1; - dma_q->field1_done = 0; - dma_q->lines_per_field = dev->height/2; - dma_q->bytes_left_in_line = dev->width << 1; - dma_q->lines_completed = 0; - for(i = 0; i < 8 ; i++) - dma_q->partial_buf[i] = 0; - - dev->video_mode.isoc_ctl.urb = kzalloc(sizeof(void *)*num_bufs, GFP_KERNEL); + dma_q->pos = 0; + dma_q->is_partial_line = 0; + dma_q->last_sav = 0; + dma_q->current_field = -1; + dma_q->field1_done = 0; + dma_q->lines_per_field = dev->height / 2; + dma_q->bytes_left_in_line = dev->width << 1; + dma_q->lines_completed = 0; + for (i = 0; i < 8; i++) + dma_q->partial_buf[i] = 0; + + dev->video_mode.isoc_ctl.urb = + kzalloc(sizeof(void *) * num_bufs, GFP_KERNEL); if (!dev->video_mode.isoc_ctl.urb) { cx231xx_errdev("cannot alloc memory for usb buffers\n"); return -ENOMEM; } - dev->video_mode.isoc_ctl.transfer_buffer = kzalloc(sizeof(void *)*num_bufs, - GFP_KERNEL); + dev->video_mode.isoc_ctl.transfer_buffer = + kzalloc(sizeof(void *) * num_bufs, GFP_KERNEL); if (!dev->video_mode.isoc_ctl.transfer_buffer) { cx231xx_errdev("cannot allocate memory for usbtransfer\n"); kfree(dev->video_mode.isoc_ctl.urb); @@ -791,23 +821,25 @@ int cx231xx_init_isoc(struct cx231xx *dev, int max_packets, } dev->video_mode.isoc_ctl.urb[i] = urb; - dev->video_mode.isoc_ctl.transfer_buffer[i] = usb_buffer_alloc(dev->udev, - sb_size, GFP_KERNEL, &urb->transfer_dma); + dev->video_mode.isoc_ctl.transfer_buffer[i] = + usb_buffer_alloc(dev->udev, sb_size, GFP_KERNEL, + &urb->transfer_dma); if (!dev->video_mode.isoc_ctl.transfer_buffer[i]) { cx231xx_err("unable to allocate %i bytes for transfer" - " buffer %i%s\n", - sb_size, i, - in_interrupt()?" while in int":""); + " buffer %i%s\n", + sb_size, i, + in_interrupt()? " while in int" : ""); cx231xx_uninit_isoc(dev); return -ENOMEM; } memset(dev->video_mode.isoc_ctl.transfer_buffer[i], 0, sb_size); - pipe = usb_rcvisocpipe(dev->udev, dev->video_mode.end_point_addr); + pipe = + usb_rcvisocpipe(dev->udev, dev->video_mode.end_point_addr); usb_fill_int_urb(urb, dev->udev, pipe, - dev->video_mode.isoc_ctl.transfer_buffer[i], sb_size, - cx231xx_irq_callback, dma_q, 1); + dev->video_mode.isoc_ctl.transfer_buffer[i], + sb_size, cx231xx_irq_callback, dma_q, 1); urb->number_of_packets = max_packets; urb->transfer_flags = URB_ISO_ASAP; @@ -816,29 +848,30 @@ int cx231xx_init_isoc(struct cx231xx *dev, int max_packets, for (j = 0; j < max_packets; j++) { urb->iso_frame_desc[j].offset = k; urb->iso_frame_desc[j].length = - dev->video_mode.isoc_ctl.max_pkt_size; + dev->video_mode.isoc_ctl.max_pkt_size; k += dev->video_mode.isoc_ctl.max_pkt_size; } } init_waitqueue_head(&dma_q->wq); - /* submit urbs and enables IRQ */ for (i = 0; i < dev->video_mode.isoc_ctl.num_bufs; i++) { - rc = usb_submit_urb(dev->video_mode.isoc_ctl.urb[i], GFP_ATOMIC); + rc = usb_submit_urb(dev->video_mode.isoc_ctl.urb[i], + GFP_ATOMIC); if (rc) { cx231xx_err("submit of urb %i failed (error=%i)\n", i, - rc); + rc); cx231xx_uninit_isoc(dev); return rc; } } - - cx231xx_capture_start(dev, 1, Raw_Video); + + cx231xx_capture_start(dev, 1, Raw_Video); return 0; } + EXPORT_SYMBOL_GPL(cx231xx_init_isoc); /************************************************************************************ @@ -846,179 +879,184 @@ EXPORT_SYMBOL_GPL(cx231xx_init_isoc); *************************************************************************************/ int cx231xx_dev_init(struct cx231xx *dev) { - int errCode = 0; + int errCode = 0; - /* Initialize I2C bus */ + /* Initialize I2C bus */ /* External Master 1 Bus */ dev->i2c_bus[0].nr = 0; dev->i2c_bus[0].dev = dev; - dev->i2c_bus[0].i2c_period = I2C_SPEED_1M; /* 1MHz */ - dev->i2c_bus[0].i2c_nostop = 0; - dev->i2c_bus[0].i2c_reserve = 0; + dev->i2c_bus[0].i2c_period = I2C_SPEED_1M; /* 1MHz */ + dev->i2c_bus[0].i2c_nostop = 0; + dev->i2c_bus[0].i2c_reserve = 0; /* External Master 2 Bus */ dev->i2c_bus[1].nr = 1; dev->i2c_bus[1].dev = dev; - dev->i2c_bus[1].i2c_period = I2C_SPEED_1M; /* 1MHz */ - dev->i2c_bus[1].i2c_nostop = 0; - dev->i2c_bus[1].i2c_reserve = 0; + dev->i2c_bus[1].i2c_period = I2C_SPEED_1M; /* 1MHz */ + dev->i2c_bus[1].i2c_nostop = 0; + dev->i2c_bus[1].i2c_reserve = 0; /* Internal Master 3 Bus */ dev->i2c_bus[2].nr = 2; dev->i2c_bus[2].dev = dev; - dev->i2c_bus[2].i2c_period = I2C_SPEED_400K; /* 400kHz */ - dev->i2c_bus[2].i2c_nostop = 0; - dev->i2c_bus[2].i2c_reserve = 0; + dev->i2c_bus[2].i2c_period = I2C_SPEED_400K; /* 400kHz */ + dev->i2c_bus[2].i2c_nostop = 0; + dev->i2c_bus[2].i2c_reserve = 0; - /* register I2C buses */ + /* register I2C buses */ cx231xx_i2c_register(&dev->i2c_bus[0]); cx231xx_i2c_register(&dev->i2c_bus[1]); cx231xx_i2c_register(&dev->i2c_bus[2]); - - /* init hardware */ - /* Note : with out calling set power mode function, colibri can not be set up correctly */ - errCode = cx231xx_set_power_mode(dev, POLARIS_AVMODE_ANALOGT_TV); - if (errCode < 0) { - cx231xx_errdev("%s: cx231xx_set_power_mode : Failed to set Power - errCode [%d]!\n", - __func__, errCode); + + /* init hardware */ + /* Note : with out calling set power mode function, colibri can not be set up correctly */ + errCode = cx231xx_set_power_mode(dev, POLARIS_AVMODE_ANALOGT_TV); + if (errCode < 0) { + cx231xx_errdev + ("%s: cx231xx_set_power_mode : Failed to set Power - errCode [%d]!\n", + __func__, errCode); return errCode; } - /* initialize Colibri block */ - errCode = cx231xx_colibri_init_super_block(dev, 0x23c); + /* initialize Colibri block */ + errCode = cx231xx_colibri_init_super_block(dev, 0x23c); if (errCode < 0) { - cx231xx_errdev("%s: cx231xx_colibri init super block - errCode [%d]!\n", - __func__, errCode); + cx231xx_errdev + ("%s: cx231xx_colibri init super block - errCode [%d]!\n", + __func__, errCode); return errCode; } - errCode = cx231xx_colibri_init_channels(dev); - if (errCode < 0) { - cx231xx_errdev("%s: cx231xx_colibri init channels - errCode [%d]!\n", - __func__, errCode); + errCode = cx231xx_colibri_init_channels(dev); + if (errCode < 0) { + cx231xx_errdev + ("%s: cx231xx_colibri init channels - errCode [%d]!\n", + __func__, errCode); return errCode; } - /* Set DIF in By pass mode */ - errCode = cx231xx_dif_set_standard(dev, DIF_USE_BASEBAND); - if (errCode < 0) { - cx231xx_errdev("%s: cx231xx_dif set to By pass mode - errCode [%d]!\n", - __func__, errCode); + /* Set DIF in By pass mode */ + errCode = cx231xx_dif_set_standard(dev, DIF_USE_BASEBAND); + if (errCode < 0) { + cx231xx_errdev + ("%s: cx231xx_dif set to By pass mode - errCode [%d]!\n", + __func__, errCode); return errCode; } - /* flatiron related functions */ - errCode = cx231xx_flatiron_initialize(dev); - if (errCode < 0) { - cx231xx_errdev("%s: cx231xx_flatiron initialize - errCode [%d]!\n", - __func__, errCode); + /* flatiron related functions */ + errCode = cx231xx_flatiron_initialize(dev); + if (errCode < 0) { + cx231xx_errdev + ("%s: cx231xx_flatiron initialize - errCode [%d]!\n", + __func__, errCode); return errCode; } - /* init control pins */ - errCode = cx231xx_init_ctrl_pin_status(dev); - if (errCode < 0) { + /* init control pins */ + errCode = cx231xx_init_ctrl_pin_status(dev); + if (errCode < 0) { cx231xx_errdev("%s: cx231xx_init ctrl pins - errCode [%d]!\n", - __func__, errCode); + __func__, errCode); return errCode; } - /* set AGC mode to Analog */ - errCode = cx231xx_set_agc_analog_digital_mux_select(dev, 1); - if (errCode < 0) { - cx231xx_errdev("%s: cx231xx_AGC mode to Analog - errCode [%d]!\n", - __func__, errCode); + /* set AGC mode to Analog */ + errCode = cx231xx_set_agc_analog_digital_mux_select(dev, 1); + if (errCode < 0) { + cx231xx_errdev + ("%s: cx231xx_AGC mode to Analog - errCode [%d]!\n", + __func__, errCode); return errCode; } - /* set all alternate settings to zero initially */ - cx231xx_set_alt_setting(dev, INDEX_VIDEO, 0); - cx231xx_set_alt_setting(dev, INDEX_VANC, 0); - cx231xx_set_alt_setting(dev, INDEX_HANC, 0); - if(dev->board.has_dvb) - cx231xx_set_alt_setting(dev, INDEX_TS1, 0); + /* set all alternate settings to zero initially */ + cx231xx_set_alt_setting(dev, INDEX_VIDEO, 0); + cx231xx_set_alt_setting(dev, INDEX_VANC, 0); + cx231xx_set_alt_setting(dev, INDEX_HANC, 0); + if (dev->board.has_dvb) + cx231xx_set_alt_setting(dev, INDEX_TS1, 0); + + /* set the I2C master port to 3 on channel 1 */ + errCode = cx231xx_enable_i2c_for_tuner(dev, I2C_3); - /* set the I2C master port to 3 on channel 1 */ - errCode = cx231xx_enable_i2c_for_tuner(dev, I2C_3); - return errCode; } + EXPORT_SYMBOL_GPL(cx231xx_dev_init); void cx231xx_dev_uninit(struct cx231xx *dev) -{ - /* Un Initialize I2C bus */ +{ + /* Un Initialize I2C bus */ cx231xx_i2c_unregister(&dev->i2c_bus[2]); cx231xx_i2c_unregister(&dev->i2c_bus[1]); cx231xx_i2c_unregister(&dev->i2c_bus[0]); } -EXPORT_SYMBOL_GPL(cx231xx_dev_uninit); +EXPORT_SYMBOL_GPL(cx231xx_dev_uninit); /************************************************************************************ * G P I O related functions * *************************************************************************************/ -int cx231xx_send_gpio_cmd(struct cx231xx *dev, u32 gpio_bit, u8* gpio_val, - u8 len, u8 request, u8 direction) +int cx231xx_send_gpio_cmd(struct cx231xx *dev, u32 gpio_bit, u8 * gpio_val, + u8 len, u8 request, u8 direction) { - int status = 0; - VENDOR_REQUEST_IN ven_req; - - /* Set wValue */ - ven_req.wValue = (u16)(gpio_bit>>16 & 0xffff); - - /* set request */ - if(!request){ - if(direction) - ven_req.bRequest = VRT_GET_GPIO; /* 0x8 gpio */ - else - ven_req.bRequest = VRT_SET_GPIO; /* 0x9 gpio */ - } - else { - if(direction) - ven_req.bRequest = VRT_GET_GPIE; /* 0xa gpie */ - else - ven_req.bRequest = VRT_SET_GPIE; /* 0xb gpie */ - } - - /* set index value */ - ven_req.wIndex = (u16)(gpio_bit & 0xffff); - - /* set wLength value */ - ven_req.wLength = len; - - /* set bData value */ - ven_req.bData = 0; - + int status = 0; + VENDOR_REQUEST_IN ven_req; + + /* Set wValue */ + ven_req.wValue = (u16) (gpio_bit >> 16 & 0xffff); + + /* set request */ + if (!request) { + if (direction) + ven_req.bRequest = VRT_GET_GPIO; /* 0x8 gpio */ + else + ven_req.bRequest = VRT_SET_GPIO; /* 0x9 gpio */ + } else { + if (direction) + ven_req.bRequest = VRT_GET_GPIE; /* 0xa gpie */ + else + ven_req.bRequest = VRT_SET_GPIE; /* 0xb gpie */ + } + + /* set index value */ + ven_req.wIndex = (u16) (gpio_bit & 0xffff); + + /* set wLength value */ + ven_req.wLength = len; + + /* set bData value */ + ven_req.bData = 0; + /* set the buffer for read / write */ - ven_req.pBuff = gpio_val; + ven_req.pBuff = gpio_val; - /* set the direction */ - if(direction){ - ven_req.direction = USB_DIR_IN; - memset(ven_req.pBuff, 0x00, ven_req.wLength); - } - else - ven_req.direction = USB_DIR_OUT; - + /* set the direction */ + if (direction) { + ven_req.direction = USB_DIR_IN; + memset(ven_req.pBuff, 0x00, ven_req.wLength); + } else + ven_req.direction = USB_DIR_OUT; #if 0 - cx231xx_isocdbg("bRequest = %x\n", ven_req.bRequest); - cx231xx_isocdbg("wValue = %x\n", ven_req.wValue); - cx231xx_isocdbg("wIndex = %x\n",ven_req.wIndex); - cx231xx_isocdbg("wLength = %x\n",ven_req.wLength); - for(int i =0; i>8); - value[2]=(u8)(tmp>>16); - value[3]=(u8)(tmp>>24); - - status = cx231xx_write_ctrl_reg(dev,VRT_SET_REGISTER, address,value,4); - - return status; + u8 value[4] = { 0x0, 0x0, 0x0, 0x0 }; + u32 tmp = 0; + int status = 0; + + status = + cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, address, value, 4); + if (status < 0) + return status; + + tmp = *((u32 *) value); + tmp |= mode; + + value[0] = (u8) tmp; + value[1] = (u8) (tmp >> 8); + value[2] = (u8) (tmp >> 16); + value[3] = (u8) (tmp >> 24); + + status = + cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER, address, value, 4); + + return status; } /************************************************************************************* * I 2 C Internal C O N T R O L functions * *************************************************************************************/ -int cx231xx_read_i2c_data(struct cx231xx *dev, u8 dev_addr, u16 saddr, - u8 saddr_len, u32 *data, u8 data_len) +int cx231xx_read_i2c_data(struct cx231xx *dev, u8 dev_addr, u16 saddr, + u8 saddr_len, u32 * data, u8 data_len) { - int status = 0; - struct cx231xx_i2c_xfer_data req_data; - u8 value[4] ={0,0,0,0}; - - if(saddr_len == 0) - saddr = 0; - else if(saddr_len == 0) - saddr &= 0xff; - - /* prepare xfer_data struct */ - req_data.dev_addr = dev_addr >> 1; - req_data.direction = I2C_M_RD; - req_data.saddr_len = saddr_len; - req_data.saddr_dat = saddr; - req_data.buf_size = data_len; - req_data.p_buffer = (u8*)value; - - /* usb send command */ - status = dev->cx231xx_send_usb_command(&dev->i2c_bus[0], &req_data); - - if(status >= 0) - { - /* Copy the data read back to main buffer */ - if(data_len == 1) - *data = value[0]; - else - *data = value[0] | value[1] << 8 | value[2] << 16 | value[3] << 24; - } - - return status; + int status = 0; + struct cx231xx_i2c_xfer_data req_data; + u8 value[4] = { 0, 0, 0, 0 }; + + if (saddr_len == 0) + saddr = 0; + else if (saddr_len == 0) + saddr &= 0xff; + + /* prepare xfer_data struct */ + req_data.dev_addr = dev_addr >> 1; + req_data.direction = I2C_M_RD; + req_data.saddr_len = saddr_len; + req_data.saddr_dat = saddr; + req_data.buf_size = data_len; + req_data.p_buffer = (u8 *) value; + + /* usb send command */ + status = dev->cx231xx_send_usb_command(&dev->i2c_bus[0], &req_data); + + if (status >= 0) { + /* Copy the data read back to main buffer */ + if (data_len == 1) + *data = value[0]; + else + *data = + value[0] | value[1] << 8 | value[2] << 16 | value[3] + << 24; + } + + return status; } -int cx231xx_write_i2c_data(struct cx231xx *dev, u8 dev_addr, u16 saddr, - u8 saddr_len, u32 data, u8 data_len) +int cx231xx_write_i2c_data(struct cx231xx *dev, u8 dev_addr, u16 saddr, + u8 saddr_len, u32 data, u8 data_len) { - int status = 0; - u8 value[4] ={0,0,0,0}; - struct cx231xx_i2c_xfer_data req_data; - - value[0]=(u8)data; - value[1]=(u8)(data>>8); - value[2]=(u8)(data>>16); - value[3]=(u8)(data>>24); - - if(saddr_len == 0) - saddr = 0; - else if(saddr_len == 0) - saddr &= 0xff; - - /* prepare xfer_data struct */ - req_data.dev_addr = dev_addr >> 1; - req_data.direction = 0; - req_data.saddr_len = saddr_len; - req_data.saddr_dat = saddr; - req_data.buf_size = data_len; - req_data.p_buffer = value; - - /* usb send command */ - status = dev->cx231xx_send_usb_command(&dev->i2c_bus[0], &req_data); - - return status; + int status = 0; + u8 value[4] = { 0, 0, 0, 0 }; + struct cx231xx_i2c_xfer_data req_data; + + value[0] = (u8) data; + value[1] = (u8) (data >> 8); + value[2] = (u8) (data >> 16); + value[3] = (u8) (data >> 24); + + if (saddr_len == 0) + saddr = 0; + else if (saddr_len == 0) + saddr &= 0xff; + + /* prepare xfer_data struct */ + req_data.dev_addr = dev_addr >> 1; + req_data.direction = 0; + req_data.saddr_len = saddr_len; + req_data.saddr_dat = saddr; + req_data.buf_size = data_len; + req_data.p_buffer = value; + + /* usb send command */ + status = dev->cx231xx_send_usb_command(&dev->i2c_bus[0], &req_data); + + return status; } -int cx231xx_reg_mask_write(struct cx231xx *dev, u8 dev_addr, u8 size, u16 register_address, - u8 bit_start,u8 bit_end, u32 value) +int cx231xx_reg_mask_write(struct cx231xx *dev, u8 dev_addr, u8 size, + u16 register_address, u8 bit_start, u8 bit_end, + u32 value) { - int status = 0; - u32 tmp; - u32 mask = 0; - int i; - - if (bit_start>(size-1) || bit_end>(size-1)) { - return -1; - } - - if (size==8){ - status = cx231xx_read_i2c_data(dev, dev_addr, register_address, 2, &tmp, 1); - } else { - status = cx231xx_read_i2c_data(dev, dev_addr, register_address, 2, &tmp, 4); - } - - if (status < 0) { - return status; - } - - mask = 1<bit_start&&i>0; i--) { - mask = mask + (1<<(i-1)); - } - - value <<= bit_start; - - if (size==8) - { - tmp &= ~mask; - tmp |= value; - tmp &= 0xff; - status = cx231xx_write_i2c_data(dev, dev_addr, register_address, 2, tmp, 1); - } - else - { - tmp &= ~mask; - tmp |= value; - status = cx231xx_write_i2c_data(dev, dev_addr, register_address, 2, tmp, 4); - } - - return status; -} + int status = 0; + u32 tmp; + u32 mask = 0; + int i; + if (bit_start > (size - 1) || bit_end > (size - 1)) { + return -1; + } + + if (size == 8) { + status = + cx231xx_read_i2c_data(dev, dev_addr, register_address, 2, + &tmp, 1); + } else { + status = + cx231xx_read_i2c_data(dev, dev_addr, register_address, 2, + &tmp, 4); + } + if (status < 0) { + return status; + } + + mask = 1 << bit_end; + for (i = bit_end; i > bit_start && i > 0; i--) { + mask = mask + (1 << (i - 1)); + } -int cx231xx_read_modify_write_i2c_dword(struct cx231xx *dev, u8 dev_addr, - u16 saddr, u32 mask, u32 value) + value <<= bit_start; + + if (size == 8) { + tmp &= ~mask; + tmp |= value; + tmp &= 0xff; + status = + cx231xx_write_i2c_data(dev, dev_addr, register_address, 2, + tmp, 1); + } else { + tmp &= ~mask; + tmp |= value; + status = + cx231xx_write_i2c_data(dev, dev_addr, register_address, 2, + tmp, 4); + } + + return status; +} + +int cx231xx_read_modify_write_i2c_dword(struct cx231xx *dev, u8 dev_addr, + u16 saddr, u32 mask, u32 value) { - u32 temp; - int status = 0; + u32 temp; + int status = 0; - status = cx231xx_read_i2c_data(dev, dev_addr, saddr, 2, &temp, 4); + status = cx231xx_read_i2c_data(dev, dev_addr, saddr, 2, &temp, 4); - if(status < 0) - return status; + if (status < 0) + return status; - temp &= ~mask; - temp |= value; + temp &= ~mask; + temp |= value; - status = cx231xx_write_i2c_data(dev, dev_addr, saddr, 2, temp, 4); + status = cx231xx_write_i2c_data(dev, dev_addr, saddr, 2, temp, 4); - return status; + return status; } u32 cx231xx_set_field(u32 field_mask, u32 data) { - u32 temp; + u32 temp; - for (temp = field_mask; (temp & 1) == 0; temp >>= 1) { - data <<= 1; - } + for (temp = field_mask; (temp & 1) == 0; temp >>= 1) { + data <<= 1; + } - return data; + return data; } diff --git a/linux/drivers/media/video/cx231xx/cx231xx-dvb.c b/linux/drivers/media/video/cx231xx/cx231xx-dvb.c index d2dd8dbd5..fcf197e99 100644 --- a/linux/drivers/media/video/cx231xx/cx231xx-dvb.c +++ b/linux/drivers/media/video/cx231xx/cx231xx-dvb.c @@ -2,7 +2,7 @@ DVB device driver for cx231xx Copyright (C) 2008 - Based on em28xx driver + Based on em28xx driver 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 @@ -30,7 +30,6 @@ #include "xc5000.h" #include "dvb_dummy_fe.h" - MODULE_DESCRIPTION("driver for cx231xx based DVB cards"); MODULE_AUTHOR("Srinivasa Deevi "); MODULE_LICENSE("GPL"); @@ -51,24 +50,22 @@ if (debug >= level) \ #define CX231XX_DVB_MAX_PACKETS 64 struct cx231xx_dvb { - struct dvb_frontend *frontend; + struct dvb_frontend *frontend; /* feed count management */ - struct mutex lock; - int nfeeds; + struct mutex lock; + int nfeeds; /* general boilerplate stuff */ - struct dvb_adapter adapter; - struct dvb_demux demux; - struct dmxdev dmxdev; - struct dmx_frontend fe_hw; - struct dmx_frontend fe_mem; - struct dvb_net net; + struct dvb_adapter adapter; + struct dvb_demux demux; + struct dmxdev dmxdev; + struct dmx_frontend fe_hw; + struct dmx_frontend fe_mem; + struct dvb_net net; }; - -static inline void print_err_status(struct cx231xx *dev, - int packet, int status) +static inline void print_err_status(struct cx231xx *dev, int packet, int status) { char *errmsg = "Unknown"; @@ -150,8 +147,8 @@ static int start_streaming(struct cx231xx_dvb *dvb) return rc; return cx231xx_init_isoc(dev, CX231XX_DVB_MAX_PACKETS, - CX231XX_DVB_NUM_BUFS, CX231XX_DVB_MAX_PACKETSIZE, - dvb_isoc_copy); + CX231XX_DVB_NUM_BUFS, + CX231XX_DVB_MAX_PACKETSIZE, dvb_isoc_copy); } static int stop_streaming(struct cx231xx_dvb *dvb) @@ -167,7 +164,7 @@ static int stop_streaming(struct cx231xx_dvb *dvb) static int start_feed(struct dvb_demux_feed *feed) { - struct dvb_demux *demux = feed->demux; + struct dvb_demux *demux = feed->demux; struct cx231xx_dvb *dvb = demux->priv; int rc, ret; @@ -190,7 +187,7 @@ static int start_feed(struct dvb_demux_feed *feed) static int stop_feed(struct dvb_demux_feed *feed) { - struct dvb_demux *demux = feed->demux; + struct dvb_demux *demux = feed->demux; struct cx231xx_dvb *dvb = demux->priv; int err = 0; @@ -204,8 +201,6 @@ static int stop_feed(struct dvb_demux_feed *feed) return err; } - - /* ------------------------------------------------------------------ */ static int cx231xx_dvb_bus_ctrl(struct dvb_frontend *fe, int acquire) { @@ -219,15 +214,13 @@ static int cx231xx_dvb_bus_ctrl(struct dvb_frontend *fe, int acquire) /* ------------------------------------------------------------------ */ - static struct xc5000_config cnxt_rde250_tunerconfig = { - .i2c_address = 0x61, - .if_khz = 5380, + .i2c_address = 0x61, + .if_khz = 5380, }; - /* ------------------------------------------------------------------ */ -#if 0 /* Keep */ +#if 0 /* Keep */ static int attach_xc5000(u8 addr, struct cx231xx *dev) { @@ -235,13 +228,12 @@ static int attach_xc5000(u8 addr, struct cx231xx *dev) struct xc5000_config cfg; memset(&cfg, 0, sizeof(cfg)); - cfg.i2c_adap = &dev->i2c_bus[1].i2c_adap; - cfg.i2c_addr = addr; + cfg.i2c_adap = &dev->i2c_bus[1].i2c_adap; + cfg.i2c_addr = addr; if (!dev->dvb->frontend) { printk(KERN_ERR "%s/2: dvb frontend not attached. " - "Can't attach xc5000\n", - dev->name); + "Can't attach xc5000\n", dev->name); return -EINVAL; } @@ -259,65 +251,65 @@ static int attach_xc5000(u8 addr, struct cx231xx *dev) } #endif -int cx231xx_set_analog_freq(struct cx231xx *dev, u32 freq ) +int cx231xx_set_analog_freq(struct cx231xx *dev, u32 freq) { int status = 0; - - if( (dev->dvb != NULL) && (dev->dvb->frontend != NULL) ){ - - struct dvb_tuner_ops *dops = &dev->dvb->frontend->ops.tuner_ops; - - if(dops->set_analog_params != NULL) { - struct analog_parameters params; - - params.frequency = freq; - params.std = dev->norm; - params.mode = 0 ; /* 0- Air; 1 - cable */ - /*params.audmode = ; */ - - /* Set the analog parameters to set the frequency */ - cx231xx_info("Setting Frequency for XC5000\n"); - dops->set_analog_params(dev->dvb->frontend, ¶ms); - } - + + if ((dev->dvb != NULL) && (dev->dvb->frontend != NULL)) { + + struct dvb_tuner_ops *dops = &dev->dvb->frontend->ops.tuner_ops; + + if (dops->set_analog_params != NULL) { + struct analog_parameters params; + + params.frequency = freq; + params.std = dev->norm; + params.mode = 0; /* 0- Air; 1 - cable */ + /*params.audmode = ; */ + + /* Set the analog parameters to set the frequency */ + cx231xx_info("Setting Frequency for XC5000\n"); + dops->set_analog_params(dev->dvb->frontend, ¶ms); } - + + } + return status; } -int cx231xx_reset_analog_tuner(struct cx231xx *dev) +int cx231xx_reset_analog_tuner(struct cx231xx *dev) { - int status = 0; - - if( (dev->dvb != NULL) && (dev->dvb->frontend != NULL) ){ - - struct dvb_tuner_ops *dops = &dev->dvb->frontend->ops.tuner_ops; - - if(dops->init != NULL && !dev->xc_fw_load_done) { - - cx231xx_info("Reloading firmware for XC5000\n"); - status = dops->init(dev->dvb->frontend); - if(status == 0 ) { - dev->xc_fw_load_done = 1; - cx231xx_info("XC5000 firmware download completed\n"); - } else { - dev->xc_fw_load_done = 0; - cx231xx_info("XC5000 firmware download failed !!!\n"); - } + int status = 0; + + if ((dev->dvb != NULL) && (dev->dvb->frontend != NULL)) { + + struct dvb_tuner_ops *dops = &dev->dvb->frontend->ops.tuner_ops; + + if (dops->init != NULL && !dev->xc_fw_load_done) { + + cx231xx_info("Reloading firmware for XC5000\n"); + status = dops->init(dev->dvb->frontend); + if (status == 0) { + dev->xc_fw_load_done = 1; + cx231xx_info + ("XC5000 firmware download completed\n"); + } else { + dev->xc_fw_load_done = 0; + cx231xx_info + ("XC5000 firmware download failed !!!\n"); } - } - + + } + return status; } - /* ------------------------------------------------------------------ */ static int register_dvb(struct cx231xx_dvb *dvb, - struct module *module, - struct cx231xx *dev, - struct device *device) + struct module *module, + struct cx231xx *dev, struct device *device) { int result; @@ -327,7 +319,8 @@ static int register_dvb(struct cx231xx_dvb *dvb, result = dvb_register_adapter(&dvb->adapter, dev->name, module, device, adapter_nr); if (result < 0) { - printk(KERN_WARNING "%s: dvb_register_adapter failed (errno = %d)\n", + printk(KERN_WARNING + "%s: dvb_register_adapter failed (errno = %d)\n", dev->name, result); goto fail_adapter; } @@ -340,20 +333,21 @@ static int register_dvb(struct cx231xx_dvb *dvb, /* register frontend */ result = dvb_register_frontend(&dvb->adapter, dvb->frontend); if (result < 0) { - printk(KERN_WARNING "%s: dvb_register_frontend failed (errno = %d)\n", + printk(KERN_WARNING + "%s: dvb_register_frontend failed (errno = %d)\n", dev->name, result); goto fail_frontend; } /* register demux stuff */ dvb->demux.dmx.capabilities = - DMX_TS_FILTERING | DMX_SECTION_FILTERING | - DMX_MEMORY_BASED_FILTERING; - dvb->demux.priv = dvb; - dvb->demux.filternum = 256; - dvb->demux.feednum = 256; + DMX_TS_FILTERING | DMX_SECTION_FILTERING | + DMX_MEMORY_BASED_FILTERING; + dvb->demux.priv = dvb; + dvb->demux.filternum = 256; + dvb->demux.feednum = 256; dvb->demux.start_feed = start_feed; - dvb->demux.stop_feed = stop_feed; + dvb->demux.stop_feed = stop_feed; result = dvb_dmx_init(&dvb->demux); if (result < 0) { @@ -362,8 +356,8 @@ static int register_dvb(struct cx231xx_dvb *dvb, goto fail_dmx; } - dvb->dmxdev.filternum = 256; - dvb->dmxdev.demux = &dvb->demux.dmx; + dvb->dmxdev.filternum = 256; + dvb->dmxdev.demux = &dvb->demux.dmx; dvb->dmxdev.capabilities = 0; result = dvb_dmxdev_init(&dvb->dmxdev, &dvb->adapter); if (result < 0) { @@ -375,7 +369,8 @@ static int register_dvb(struct cx231xx_dvb *dvb, dvb->fe_hw.source = DMX_FRONTEND_0; result = dvb->demux.dmx.add_frontend(&dvb->demux.dmx, &dvb->fe_hw); if (result < 0) { - printk(KERN_WARNING "%s: add_frontend failed (DMX_FRONTEND_0, errno = %d)\n", + printk(KERN_WARNING + "%s: add_frontend failed (DMX_FRONTEND_0, errno = %d)\n", dev->name, result); goto fail_fe_hw; } @@ -383,15 +378,17 @@ static int register_dvb(struct cx231xx_dvb *dvb, dvb->fe_mem.source = DMX_MEMORY_FE; result = dvb->demux.dmx.add_frontend(&dvb->demux.dmx, &dvb->fe_mem); if (result < 0) { - printk(KERN_WARNING "%s: add_frontend failed (DMX_MEMORY_FE, errno = %d)\n", + printk(KERN_WARNING + "%s: add_frontend failed (DMX_MEMORY_FE, errno = %d)\n", dev->name, result); goto fail_fe_mem; } result = dvb->demux.dmx.connect_frontend(&dvb->demux.dmx, &dvb->fe_hw); if (result < 0) { - printk(KERN_WARNING "%s: connect_frontend failed (errno = %d)\n", - dev->name, result); + printk(KERN_WARNING + "%s: connect_frontend failed (errno = %d)\n", dev->name, + result); goto fail_fe_conn; } @@ -399,20 +396,20 @@ static int register_dvb(struct cx231xx_dvb *dvb, dvb_net_init(&dvb->adapter, &dvb->net, &dvb->demux.dmx); return 0; -fail_fe_conn: + fail_fe_conn: dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_mem); -fail_fe_mem: + fail_fe_mem: dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_hw); -fail_fe_hw: + fail_fe_hw: dvb_dmxdev_release(&dvb->dmxdev); -fail_dmxdev: + fail_dmxdev: dvb_dmx_release(&dvb->demux); -fail_dmx: + fail_dmx: dvb_unregister_frontend(dvb->frontend); -fail_frontend: + fail_frontend: dvb_frontend_detach(dvb->frontend); dvb_unregister_adapter(&dvb->adapter); -fail_adapter: + fail_adapter: return result; } @@ -428,7 +425,6 @@ static void unregister_dvb(struct cx231xx_dvb *dvb) dvb_unregister_adapter(&dvb->adapter); } - static int dvb_init(struct cx231xx *dev) { int result = 0; @@ -447,70 +443,69 @@ static int dvb_init(struct cx231xx *dev) } dev->dvb = dvb; dev->cx231xx_set_analog_freq = cx231xx_set_analog_freq; - dev->cx231xx_reset_analog_tuner = cx231xx_reset_analog_tuner; + dev->cx231xx_reset_analog_tuner = cx231xx_reset_analog_tuner; cx231xx_set_mode(dev, CX231XX_DIGITAL_MODE); /* init frontend */ switch (dev->model) { - case CX231XX_BOARD_CNXT_RDE_250: - - /* dev->dvb->frontend = dvb_attach(s5h1411_attach, - &dvico_s5h1411_config, - &dev->i2c_bus[1].i2c_adap);*/ - dev->dvb->frontend = dvb_attach(dvb_dummy_fe_ofdm_attach); - - if(dev->dvb->frontend == NULL) { - printk(DRIVER_NAME ": Failed to attach dummy front end\n"); - result = -EINVAL; - goto out_free; - } - - /* define general-purpose callback pointer */ - dvb->frontend->callback = cx231xx_tuner_callback; - - if(dvb_attach(xc5000_attach, dev->dvb->frontend, - &dev->i2c_bus[1].i2c_adap, - &cnxt_rde250_tunerconfig) < 0) { - result = -EINVAL; - goto out_free; - } - - break; - case CX231XX_BOARD_CNXT_RDU_250: - - dev->dvb->frontend = dvb_attach(dvb_dummy_fe_ofdm_attach); - - if(dev->dvb->frontend == NULL) { - printk(DRIVER_NAME ": Failed to attach dummy front end\n"); - result = -EINVAL; - goto out_free; - } - - /* define general-purpose callback pointer */ - dvb->frontend->callback = cx231xx_tuner_callback; - - if(dvb_attach(xc5000_attach, dev->dvb->frontend, - &dev->i2c_bus[1].i2c_adap, - &cnxt_rde250_tunerconfig) < 0) { - result = -EINVAL; - goto out_free; - } - break; + case CX231XX_BOARD_CNXT_RDE_250: + + /* dev->dvb->frontend = dvb_attach(s5h1411_attach, + &dvico_s5h1411_config, + &dev->i2c_bus[1].i2c_adap); */ + dev->dvb->frontend = dvb_attach(dvb_dummy_fe_ofdm_attach); + + if (dev->dvb->frontend == NULL) { + printk(DRIVER_NAME + ": Failed to attach dummy front end\n"); + result = -EINVAL; + goto out_free; + } + + /* define general-purpose callback pointer */ + dvb->frontend->callback = cx231xx_tuner_callback; + + if (dvb_attach(xc5000_attach, dev->dvb->frontend, + &dev->i2c_bus[1].i2c_adap, + &cnxt_rde250_tunerconfig) < 0) { + result = -EINVAL; + goto out_free; + } + + break; + case CX231XX_BOARD_CNXT_RDU_250: + + dev->dvb->frontend = dvb_attach(dvb_dummy_fe_ofdm_attach); + + if (dev->dvb->frontend == NULL) { + printk(DRIVER_NAME + ": Failed to attach dummy front end\n"); + result = -EINVAL; + goto out_free; + } + + /* define general-purpose callback pointer */ + dvb->frontend->callback = cx231xx_tuner_callback; + + if (dvb_attach(xc5000_attach, dev->dvb->frontend, + &dev->i2c_bus[1].i2c_adap, + &cnxt_rde250_tunerconfig) < 0) { + result = -EINVAL; + goto out_free; + } + break; default: printk(KERN_ERR "%s/2: The frontend of your DVB/ATSC card" - " isn't supported yet\n", - dev->name); + " isn't supported yet\n", dev->name); break; } if (NULL == dvb->frontend) { printk(KERN_ERR - "%s/2: frontend initialization failed\n", - dev->name); + "%s/2: frontend initialization failed\n", dev->name); result = -EINVAL; goto out_free; } - /* register everything */ result = register_dvb(dvb, THIS_MODULE, dev, &dev->udev->dev); @@ -522,7 +517,7 @@ static int dvb_init(struct cx231xx *dev) printk(KERN_INFO "Successfully loaded cx231xx-dvb\n"); return 0; -out_free: + out_free: cx231xx_set_mode(dev, CX231XX_SUSPEND); kfree(dvb); dev->dvb = NULL; @@ -545,7 +540,7 @@ static int dvb_fini(struct cx231xx *dev) } static struct cx231xx_ops dvb_ops = { - .id = CX231XX_DVB, + .id = CX231XX_DVB, .name = "Cx231xx dvb Extension", .init = dvb_init, .fini = dvb_fini, @@ -563,4 +558,3 @@ static void __exit cx231xx_dvb_unregister(void) module_init(cx231xx_dvb_register); module_exit(cx231xx_dvb_unregister); - diff --git a/linux/drivers/media/video/cx231xx/cx231xx-i2c.c b/linux/drivers/media/video/cx231xx/cx231xx-i2c.c index fd595ffaa..54b044a07 100644 --- a/linux/drivers/media/video/cx231xx/cx231xx-i2c.c +++ b/linux/drivers/media/video/cx231xx/cx231xx-i2c.c @@ -2,8 +2,8 @@ cx231xx-i2c.c - driver for Conexant Cx23100/101/102 USB video capture devices Copyright (C) 2008 - Based on em28xx driver - Based on Cx23885 driver + Based on em28xx driver + Based on Cx23885 driver 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 @@ -29,7 +29,6 @@ #include "cx231xx.h" - /* ----------------------------------------------------------- */ static unsigned int i2c_scan; @@ -40,7 +39,6 @@ static unsigned int i2c_debug; module_param(i2c_debug, int, 0644); MODULE_PARM_DESC(i2c_debug, "enable debug messages [i2c]"); - #define dprintk1(lvl, fmt, args...) \ do { \ if (i2c_debug >= lvl) { \ @@ -56,116 +54,119 @@ do { \ } \ } while (0) - /* * cx231xx_i2c_send_bytes() */ int cx231xx_i2c_send_bytes(struct i2c_adapter *i2c_adap, - const struct i2c_msg *msg) + const struct i2c_msg *msg) { struct cx231xx_i2c *bus = i2c_adap->algo_data; struct cx231xx *dev = bus->dev; - struct cx231xx_i2c_xfer_data req_data; - int status = 0; - u16 size = 0; - u8 loop = 0; - u8 saddr_len = 1; - u8 *buf_ptr = NULL; - u16 saddr = 0; - u8 need_gpio = 0; - - - if( (bus->nr ==1) && (msg->addr == 0x61) && (dev->tuner_type == TUNER_XC5000) ) { - - size = msg->len; - - if( size == 2 ) { /* register write sub addr*/ - - /* Just writing sub address will cause problem to XC5000 - So ignore the request */ - return 0; - - } else if( size == 4 ) { /* register write with sub addr*/ - - if(msg->len >= 2 ) - saddr = msg->buf[0] << 8 | msg->buf[1]; - else if ( msg->len == 1 ) - saddr = msg->buf[0]; - - switch(saddr) { - case 0x0000: /* start tuner calibration mode */ - need_gpio = 1; - dev->xc_fw_load_done = 1; /* FW Loading is done */ - break; - case 0x000D: /* Set signal source */ - case 0x0001: /* Set TV standard - Video */ - case 0x0002: /* Set TV standard - Audio */ - case 0x0003: /* Set RF Frequency */ - need_gpio = 1; - break; - default: - if(dev->xc_fw_load_done) - need_gpio = 1; - break; - } - - if(need_gpio ) { - dprintk1(1, " GPIO W R I T E : addr 0x%x, len %d, saddr 0x%x\n", - msg->addr, msg->len, saddr); - - return dev->cx231xx_gpio_i2c_write(dev, msg->addr, msg->buf, msg->len); - } - - } - - /* special case for Xc5000 tuner case */ - saddr_len = 1; - - /* adjust the length to correct length */ - size -= saddr_len; - buf_ptr = (u8*) (msg->buf + 1 ); - - do { - /* prepare xfer_data struct */ - req_data.dev_addr = msg->addr; - req_data.direction = msg->flags; - req_data.saddr_len = saddr_len; - req_data.saddr_dat = msg->buf[0]; - req_data.buf_size = size > 16 ? 16: size; - req_data.p_buffer = (u8*)(buf_ptr + loop * 16); - - bus->i2c_nostop = (size > 16) ? 1: 0; - bus->i2c_reserve = (loop == 0) ? 0: 1; - - /* usb send command */ - status = dev->cx231xx_send_usb_command(bus, &req_data); - loop++; - - if( size >= 16 ) - size -= 16; - else - size = 0; - - }while( size > 0 ); - - bus->i2c_nostop = 0; - bus->i2c_reserve = 0; - - } else { /* regular case */ - - /* prepare xfer_data struct */ - req_data.dev_addr = msg->addr; - req_data.direction = msg->flags; - req_data.saddr_len = 0; - req_data.saddr_dat = 0; - req_data.buf_size = msg->len; - req_data.p_buffer = msg->buf; - - /* usb send command */ - status = dev->cx231xx_send_usb_command(bus, &req_data); - } - - return status < 0 ? status: 0; + struct cx231xx_i2c_xfer_data req_data; + int status = 0; + u16 size = 0; + u8 loop = 0; + u8 saddr_len = 1; + u8 *buf_ptr = NULL; + u16 saddr = 0; + u8 need_gpio = 0; + + if ((bus->nr == 1) && (msg->addr == 0x61) + && (dev->tuner_type == TUNER_XC5000)) { + + size = msg->len; + + if (size == 2) { /* register write sub addr */ + + /* Just writing sub address will cause problem to XC5000 + So ignore the request */ + return 0; + + } else if (size == 4) { /* register write with sub addr */ + + if (msg->len >= 2) + saddr = msg->buf[0] << 8 | msg->buf[1]; + else if (msg->len == 1) + saddr = msg->buf[0]; + + switch (saddr) { + case 0x0000: /* start tuner calibration mode */ + need_gpio = 1; + dev->xc_fw_load_done = 1; /* FW Loading is done */ + break; + case 0x000D: /* Set signal source */ + case 0x0001: /* Set TV standard - Video */ + case 0x0002: /* Set TV standard - Audio */ + case 0x0003: /* Set RF Frequency */ + need_gpio = 1; + break; + default: + if (dev->xc_fw_load_done) + need_gpio = 1; + break; + } + + if (need_gpio) { + dprintk1(1, + " GPIO W R I T E : addr 0x%x, len %d, saddr 0x%x\n", + msg->addr, msg->len, saddr); + + return dev->cx231xx_gpio_i2c_write(dev, + msg->addr, + msg->buf, + msg->len); + } + + } + + /* special case for Xc5000 tuner case */ + saddr_len = 1; + + /* adjust the length to correct length */ + size -= saddr_len; + buf_ptr = (u8 *) (msg->buf + 1); + + do { + /* prepare xfer_data struct */ + req_data.dev_addr = msg->addr; + req_data.direction = msg->flags; + req_data.saddr_len = saddr_len; + req_data.saddr_dat = msg->buf[0]; + req_data.buf_size = size > 16 ? 16 : size; + req_data.p_buffer = (u8 *) (buf_ptr + loop * 16); + + bus->i2c_nostop = (size > 16) ? 1 : 0; + bus->i2c_reserve = (loop == 0) ? 0 : 1; + + /* usb send command */ + status = dev->cx231xx_send_usb_command(bus, &req_data); + loop++; + + if (size >= 16) + size -= 16; + else + size = 0; + + } while (size > 0); + + bus->i2c_nostop = 0; + bus->i2c_reserve = 0; + + } else { /* regular case */ + + /* prepare xfer_data struct */ + req_data.dev_addr = msg->addr; + req_data.direction = msg->flags; + req_data.saddr_len = 0; + req_data.saddr_dat = 0; + req_data.buf_size = msg->len; + req_data.p_buffer = msg->buf; + + /* usb send command */ + status = dev->cx231xx_send_usb_command(bus, &req_data); + } + + return status < 0 ? status : 0; } /* @@ -173,75 +174,85 @@ int cx231xx_i2c_send_bytes(struct i2c_adapter *i2c_adap, * read a byte from the i2c device */ static int cx231xx_i2c_recv_bytes(struct i2c_adapter *i2c_adap, - const struct i2c_msg *msg) + const struct i2c_msg *msg) { - struct cx231xx_i2c *bus = i2c_adap->algo_data; + struct cx231xx_i2c *bus = i2c_adap->algo_data; struct cx231xx *dev = bus->dev; - struct cx231xx_i2c_xfer_data req_data; - int status = 0; - u16 saddr = 0; - u8 need_gpio = 0; - - if((bus->nr ==1) && (msg->addr == 0x61) && dev->tuner_type == TUNER_XC5000) { - - if(msg->len == 2 ) - saddr = msg->buf[0] << 8 | msg->buf[1]; - else if ( msg->len == 1 ) - saddr = msg->buf[0]; - - if( dev->xc_fw_load_done) { - - switch(saddr) { - case 0x0009: /* BUSY check */ - dprintk1(1, " GPIO R E A D : Special case BUSY check \n"); - /* Try to read BUSY register, just set it to zero */ - msg->buf[0] = 0; - if(msg->len == 2 ) - msg->buf[1] = 0; - return 0; - case 0x0004: /* read Lock status */ - need_gpio = 1; - break; - - } - - if(need_gpio) { - /* this is a special case to handle Xceive tuner clock stretch issue - with gpio based I2C interface */ - dprintk1(1, " GPIO R E A D : addr 0x%x, len %d, saddr 0x%x\n", - msg->addr, msg->len, msg->buf[0] << 8| msg->buf[1]); - status = dev->cx231xx_gpio_i2c_write(dev, msg->addr, msg->buf, msg->len); - status = dev->cx231xx_gpio_i2c_read(dev, msg->addr, msg->buf, msg->len); - return status; - } - } - - /* prepare xfer_data struct */ - req_data.dev_addr = msg->addr; - req_data.direction = msg->flags; - req_data.saddr_len = msg->len; - req_data.saddr_dat = msg->buf[0] << 8 | msg->buf[1]; - req_data.buf_size = msg->len; - req_data.p_buffer = msg->buf; - - /* usb send command */ - status = dev->cx231xx_send_usb_command(bus, &req_data); - - } else { - - /* prepare xfer_data struct */ - req_data.dev_addr = msg->addr; - req_data.direction = msg->flags; - req_data.saddr_len = 0; - req_data.saddr_dat = 0; - req_data.buf_size = msg->len; - req_data.p_buffer = msg->buf; - - /* usb send command */ - status = dev->cx231xx_send_usb_command(bus, &req_data); - } - - return status < 0 ? status: 0; + struct cx231xx_i2c_xfer_data req_data; + int status = 0; + u16 saddr = 0; + u8 need_gpio = 0; + + if ((bus->nr == 1) && (msg->addr == 0x61) + && dev->tuner_type == TUNER_XC5000) { + + if (msg->len == 2) + saddr = msg->buf[0] << 8 | msg->buf[1]; + else if (msg->len == 1) + saddr = msg->buf[0]; + + if (dev->xc_fw_load_done) { + + switch (saddr) { + case 0x0009: /* BUSY check */ + dprintk1(1, + " GPIO R E A D : Special case BUSY check \n"); + /* Try to read BUSY register, just set it to zero */ + msg->buf[0] = 0; + if (msg->len == 2) + msg->buf[1] = 0; + return 0; + case 0x0004: /* read Lock status */ + need_gpio = 1; + break; + + } + + if (need_gpio) { + /* this is a special case to handle Xceive tuner clock stretch issue + with gpio based I2C interface */ + dprintk1(1, + " GPIO R E A D : addr 0x%x, len %d, saddr 0x%x\n", + msg->addr, msg->len, + msg->buf[0] << 8 | msg->buf[1]); + status = + dev->cx231xx_gpio_i2c_write(dev, msg->addr, + msg->buf, + msg->len); + status = + dev->cx231xx_gpio_i2c_read(dev, msg->addr, + msg->buf, + msg->len); + return status; + } + } + + /* prepare xfer_data struct */ + req_data.dev_addr = msg->addr; + req_data.direction = msg->flags; + req_data.saddr_len = msg->len; + req_data.saddr_dat = msg->buf[0] << 8 | msg->buf[1]; + req_data.buf_size = msg->len; + req_data.p_buffer = msg->buf; + + /* usb send command */ + status = dev->cx231xx_send_usb_command(bus, &req_data); + + } else { + + /* prepare xfer_data struct */ + req_data.dev_addr = msg->addr; + req_data.direction = msg->flags; + req_data.saddr_len = 0; + req_data.saddr_dat = 0; + req_data.buf_size = msg->len; + req_data.p_buffer = msg->buf; + + /* usb send command */ + status = dev->cx231xx_send_usb_command(bus, &req_data); + } + + return status < 0 ? status : 0; } /* @@ -249,56 +260,65 @@ static int cx231xx_i2c_recv_bytes(struct i2c_adapter *i2c_adap, * read a byte from the i2c device */ static int cx231xx_i2c_recv_bytes_with_saddr(struct i2c_adapter *i2c_adap, - const struct i2c_msg *msg1, const struct i2c_msg *msg2) + const struct i2c_msg *msg1, + const struct i2c_msg *msg2) { - struct cx231xx_i2c *bus = i2c_adap->algo_data; + struct cx231xx_i2c *bus = i2c_adap->algo_data; struct cx231xx *dev = bus->dev; - struct cx231xx_i2c_xfer_data req_data; - int status = 0; - u16 saddr = 0; - u8 need_gpio = 0; - - if(msg1->len == 2 ) - saddr = msg1->buf[0] << 8 | msg1->buf[1]; - else if ( msg1->len == 1 ) - saddr = msg1->buf[0]; - - if ( (bus->nr ==1) && (msg2->addr == 0x61) && dev->tuner_type == TUNER_XC5000) { - - if( (msg2->len < 16) ) { - - dprintk1(1, " i2c_read : addr 0x%x, len %d, subaddr 0x%x, leng %d\n", - msg2->addr, msg2->len, saddr, msg1->len); - - switch(saddr) { - case 0x0008: /* read FW load status */ - need_gpio = 1; - break; - case 0x0004: /* read Lock status */ - need_gpio = 1; - break; - } - - if(need_gpio ) { - status = dev->cx231xx_gpio_i2c_write(dev, msg1->addr, msg1->buf, msg1->len); - status = dev->cx231xx_gpio_i2c_read(dev, msg2->addr, msg2->buf, msg2->len); - return status; - } - } - } - - /* prepare xfer_data struct */ - req_data.dev_addr = msg2->addr; - req_data.direction = msg2->flags; - req_data.saddr_len = msg1->len; - req_data.saddr_dat = saddr; - req_data.buf_size = msg2->len; - req_data.p_buffer = msg2->buf; - - /* usb send command */ - status = dev->cx231xx_send_usb_command(bus, &req_data); - - return status < 0 ? status: 0; + struct cx231xx_i2c_xfer_data req_data; + int status = 0; + u16 saddr = 0; + u8 need_gpio = 0; + + if (msg1->len == 2) + saddr = msg1->buf[0] << 8 | msg1->buf[1]; + else if (msg1->len == 1) + saddr = msg1->buf[0]; + + if ((bus->nr == 1) && (msg2->addr == 0x61) + && dev->tuner_type == TUNER_XC5000) { + + if ((msg2->len < 16)) { + + dprintk1(1, + " i2c_read : addr 0x%x, len %d, subaddr 0x%x, leng %d\n", + msg2->addr, msg2->len, saddr, msg1->len); + + switch (saddr) { + case 0x0008: /* read FW load status */ + need_gpio = 1; + break; + case 0x0004: /* read Lock status */ + need_gpio = 1; + break; + } + + if (need_gpio) { + status = + dev->cx231xx_gpio_i2c_write(dev, msg1->addr, + msg1->buf, + msg1->len); + status = + dev->cx231xx_gpio_i2c_read(dev, msg2->addr, + msg2->buf, + msg2->len); + return status; + } + } + } + + /* prepare xfer_data struct */ + req_data.dev_addr = msg2->addr; + req_data.direction = msg2->flags; + req_data.saddr_len = msg1->len; + req_data.saddr_dat = saddr; + req_data.buf_size = msg2->len; + req_data.p_buffer = msg2->buf; + + /* usb send command */ + status = dev->cx231xx_send_usb_command(bus, &req_data); + + return status < 0 ? status : 0; } /* @@ -306,25 +326,25 @@ static int cx231xx_i2c_recv_bytes_with_saddr(struct i2c_adapter *i2c_adap, * check if there is a i2c_device at the supplied address */ static int cx231xx_i2c_check_for_device(struct i2c_adapter *i2c_adap, - const struct i2c_msg *msg) + const struct i2c_msg *msg) { - struct cx231xx_i2c *bus = i2c_adap->algo_data; + struct cx231xx_i2c *bus = i2c_adap->algo_data; struct cx231xx *dev = bus->dev; - struct cx231xx_i2c_xfer_data req_data; - int status = 0; + struct cx231xx_i2c_xfer_data req_data; + int status = 0; - /* prepare xfer_data struct */ - req_data.dev_addr = msg->addr; - req_data.direction = msg->flags; - req_data.saddr_len = 0; - req_data.saddr_dat = 0; - req_data.buf_size = 0; - req_data.p_buffer = NULL; + /* prepare xfer_data struct */ + req_data.dev_addr = msg->addr; + req_data.direction = msg->flags; + req_data.saddr_len = 0; + req_data.saddr_dat = 0; + req_data.buf_size = 0; + req_data.p_buffer = NULL; - /* usb send command */ - status = dev->cx231xx_send_usb_command(bus, &req_data); + /* usb send command */ + status = dev->cx231xx_send_usb_command(bus, &req_data); - return status < 0 ? status: 0; + return status < 0 ? status : 0; } /* @@ -332,7 +352,7 @@ static int cx231xx_i2c_check_for_device(struct i2c_adapter *i2c_adap, * the main i2c transfer function */ static int cx231xx_i2c_xfer(struct i2c_adapter *i2c_adap, - struct i2c_msg msgs[], int num) + struct i2c_msg msgs[], int num) { struct cx231xx_i2c *bus = i2c_adap->algo_data; struct cx231xx *dev = bus->dev; @@ -343,12 +363,12 @@ static int cx231xx_i2c_xfer(struct i2c_adapter *i2c_adap, for (i = 0; i < num; i++) { - addr = msgs[i].addr >> 1; + addr = msgs[i].addr >> 1; dprintk2(2, "%s %s addr=%x len=%d:", (msgs[i].flags & I2C_M_RD) ? "read" : "write", i == num - 1 ? "stop" : "nonstop", addr, msgs[i].len); - if (!msgs[i].len) { /* no len: check only for device presence */ + if (!msgs[i].len) { /* no len: check only for device presence */ rc = cx231xx_i2c_check_for_device(i2c_adap, &msgs[i]); if (rc < 0) { dprintk2(2, " no device\n"); @@ -363,21 +383,24 @@ static int cx231xx_i2c_xfer(struct i2c_adapter *i2c_adap, printk(" %02x", msgs[i].buf[byte]); } } else if (i + 1 < num && (msgs[i + 1].flags & I2C_M_RD) && - msgs[i].addr == msgs[i + 1].addr && (msgs[i].len <= 2) && (bus->nr < 2)) { + msgs[i].addr == msgs[i + 1].addr + && (msgs[i].len <= 2) && (bus->nr < 2)) { /* read bytes */ - rc = cx231xx_i2c_recv_bytes_with_saddr(i2c_adap, &msgs[i], &msgs[i+1]); + rc = cx231xx_i2c_recv_bytes_with_saddr(i2c_adap, + &msgs[i], + &msgs[i + 1]); if (i2c_debug >= 2) { for (byte = 0; byte < msgs[i].len; byte++) printk(" %02x", msgs[i].buf[byte]); } - i++; + i++; } else { /* write bytes */ if (i2c_debug >= 2) { for (byte = 0; byte < msgs[i].len; byte++) printk(" %02x", msgs[i].buf[byte]); } - rc = cx231xx_i2c_send_bytes(i2c_adap,&msgs[i]); + rc = cx231xx_i2c_send_bytes(i2c_adap, &msgs[i]); } if (rc < 0) goto err; @@ -386,7 +409,7 @@ static int cx231xx_i2c_xfer(struct i2c_adapter *i2c_adap, } return num; -err: + err: dprintk2(2, " ERROR: %i\n", rc); return rc; } @@ -408,10 +431,10 @@ static u32 functionality(struct i2c_adapter *adap) */ static int attach_inform(struct i2c_client *client) { - struct cx231xx_i2c *bus = i2c_get_adapdata(client->adapter); + struct cx231xx_i2c *bus = i2c_get_adapdata(client->adapter); struct cx231xx *dev = bus->dev; - switch (client->addr << 1) { + switch (client->addr << 1) { case 0x32: dprintk1(1, "attach_inform: Geminit III detected.\n"); break; @@ -422,16 +445,16 @@ static int attach_inform(struct i2c_client *client) dprintk1(1, "attach_inform: eeprom detected.\n"); break; case 0x60: - dprintk1(1, "attach_inform: Colibri detected.\n"); - break; - 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); + dprintk1(1, "attach_inform: Colibri detected.\n"); break; - } + 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; + } case 0x80: case 0x88: dprintk1(1, "attach_inform: Hammerhead detected.\n"); @@ -442,7 +465,7 @@ static int attach_inform(struct i2c_client *client) dev->tuner_addr = client->addr; dprintk1(1, "attach inform: detected I2C address %x\n", - client->addr << 1); + client->addr << 1); } return 0; @@ -454,9 +477,8 @@ static int detach_inform(struct i2c_client *client) return 0; } - static struct i2c_algorithm cx231xx_algo = { - .master_xfer = cx231xx_i2c_xfer, + .master_xfer = cx231xx_i2c_xfer, .functionality = functionality, #ifdef NEED_ALGO_CONTROL .algo_control = dummy_algo_control, @@ -469,7 +491,7 @@ static struct i2c_adapter cx231xx_adap_template = { .name = "cx231xx", .id = I2C_HW_B_CX231XX, .algo = &cx231xx_algo, - .client_register = attach_inform, + .client_register = attach_inform, .client_unregister = detach_inform, }; @@ -486,9 +508,9 @@ static struct i2c_client cx231xx_client_template = { static char *i2c_devs[128] = { [0x60 >> 1] = "colibri", [0x88 >> 1] = "hammerhead", - [0x8e >> 1] = "CIR", + [0x8e >> 1] = "CIR", [0x32 >> 1] = "GeminiIII", - [0x02 >> 1] = "Aquarius", + [0x02 >> 1] = "Aquarius", [0xa0 >> 1] = "eeprom", [0xc0 >> 1] = "tuner/XC3028", [0xc2 >> 1] = "tuner/XC5000", @@ -503,23 +525,25 @@ void cx231xx_do_i2c_scan(struct cx231xx *dev, struct i2c_client *c) unsigned char buf; int i, rc; - cx231xx_info(": Checking for I2C devices ..\n"); + cx231xx_info(": Checking for I2C devices ..\n"); for (i = 0; i < 128; i++) { c->addr = i; rc = i2c_master_recv(c, &buf, 0); if (rc < 0) continue; cx231xx_info("%s: i2c scan: found device @ 0x%x [%s]\n", - dev->name, i << 1, i2c_devs[i] ? i2c_devs[i] : "???"); + dev->name, i << 1, + i2c_devs[i] ? i2c_devs[i] : "???"); } - cx231xx_info(": Completed Checking for I2C devices.\n"); + cx231xx_info(": Completed Checking for I2C devices.\n"); } /* * cx231xx_i2c_call_clients() * send commands to all attached i2c devices */ -void cx231xx_i2c_call_clients(struct cx231xx_i2c *bus, unsigned int cmd, void *arg) +void cx231xx_i2c_call_clients(struct cx231xx_i2c *bus, unsigned int cmd, + void *arg) { /* struct cx231xx *dev = bus->dev; */ @@ -533,23 +557,20 @@ void cx231xx_i2c_call_clients(struct cx231xx_i2c *bus, unsigned int cmd, void *a */ int cx231xx_i2c_register(struct cx231xx_i2c *bus) { - struct cx231xx *dev = bus->dev; - - BUG_ON(!dev->cx231xx_send_usb_command); + struct cx231xx *dev = bus->dev; + + BUG_ON(!dev->cx231xx_send_usb_command); - cx231xx_info("%s(bus = %d)\n", __func__, bus->nr); + cx231xx_info("%s(bus = %d)\n", __func__, bus->nr); - memcpy(&bus->i2c_adap, &cx231xx_adap_template, - sizeof(bus->i2c_adap)); - memcpy(&bus->i2c_algo, &cx231xx_algo, - sizeof(bus->i2c_algo)); + memcpy(&bus->i2c_adap, &cx231xx_adap_template, sizeof(bus->i2c_adap)); + memcpy(&bus->i2c_algo, &cx231xx_algo, sizeof(bus->i2c_algo)); memcpy(&bus->i2c_client, &cx231xx_client_template, sizeof(bus->i2c_client)); bus->i2c_adap.dev.parent = &dev->udev->dev; - strlcpy(bus->i2c_adap.name, bus->dev->name, - sizeof(bus->i2c_adap.name)); + strlcpy(bus->i2c_adap.name, bus->dev->name, sizeof(bus->i2c_adap.name)); bus->i2c_algo.data = bus; bus->i2c_adap.algo_data = bus; @@ -564,7 +585,7 @@ int cx231xx_i2c_register(struct cx231xx_i2c *bus) cx231xx_do_i2c_scan(dev, &bus->i2c_client); } else cx231xx_warn("%s: i2c bus %d register FAILED\n", - dev->name, bus->nr); + dev->name, bus->nr); return bus->i2c_rc; } diff --git a/linux/drivers/media/video/cx231xx/cx231xx-input.c b/linux/drivers/media/video/cx231xx/cx231xx-input.c index e2e0a2f2a..32291630f 100644 --- a/linux/drivers/media/video/cx231xx/cx231xx-input.c +++ b/linux/drivers/media/video/cx231xx/cx231xx-input.c @@ -2,9 +2,9 @@ handle cx231xx IR remotes via linux kernel input layer. Copyright (C) 2008 - Based on em28xx driver + Based on em28xx driver - < This is a place holder for IR now.> + < This is a place holder for IR now.> 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 @@ -31,7 +31,6 @@ #include "compat.h" #include "cx231xx.h" - static unsigned int ir_debug; module_param(ir_debug, int, 0644); MODULE_PARM_DESC(ir_debug, "enable debug messages [IR]"); @@ -54,7 +53,7 @@ struct cx231xx_ir_poll_result { unsigned int toggle_bit:1; unsigned int read_count:7; u8 rc_address; - u8 rc_data[4]; + u8 rc_data[4]; }; struct cx231xx_IR { @@ -72,11 +71,9 @@ struct cx231xx_IR { unsigned int last_readcount; unsigned int repeat_interval; - int (*get_key)(struct cx231xx_IR *, struct cx231xx_ir_poll_result *); + int (*get_key) (struct cx231xx_IR *, struct cx231xx_ir_poll_result *); }; - - /********************************************************** Polling code for cx231xx **********************************************************/ @@ -199,18 +196,17 @@ int cx231xx_ir_init(struct cx231xx *dev) ir->input = input_dev; /* Setup the proper handler based on the chip */ - switch (dev->chip_id) { - default: - printk("Unrecognized cx231xx chip id: IR not supported\n"); - goto err_out_free; + switch (dev->chip_id) { + default: + printk("Unrecognized cx231xx chip id: IR not supported\n"); + goto err_out_free; } /* This is how often we ask the chip for IR information */ - ir->polling = 100; /* ms */ + ir->polling = 100; /* ms */ /* init input device */ - snprintf(ir->name, sizeof(ir->name), "cx231xx IR (%s)", - dev->name); + snprintf(ir->name, sizeof(ir->name), "cx231xx IR (%s)", dev->name); usb_make_path(dev->udev, ir->phys, sizeof(ir->phys)); strlcat(ir->phys, "/input0", sizeof(ir->phys)); @@ -240,10 +236,10 @@ int cx231xx_ir_init(struct cx231xx *dev) goto err_out_stop; return 0; - err_out_stop: + err_out_stop: cx231xx_ir_stop(ir); dev->ir = NULL; - err_out_free: + err_out_free: input_free_device(input_dev); kfree(ir); return err; @@ -264,4 +260,4 @@ int cx231xx_ir_fini(struct cx231xx *dev) /* done */ dev->ir = NULL; return 0; -} \ No newline at end of file +} diff --git a/linux/drivers/media/video/cx231xx/cx231xx-reg.h b/linux/drivers/media/video/cx231xx/cx231xx-reg.h index 05bf86fc7..7c8ba4e05 100644 --- a/linux/drivers/media/video/cx231xx/cx231xx-reg.h +++ b/linux/drivers/media/video/cx231xx/cx231xx-reg.h @@ -2,7 +2,7 @@ cx231xx-reg.h - driver for Conexant Cx23100/101/102 USB video capture devices Copyright (C) 2008 - + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or @@ -22,7 +22,7 @@ #define _CX231XX_REG_H /***************************************************************************** - * VBI codes * + * VBI codes * *****************************************************************************/ #define SAV_ACTIVE_VIDEO_FIELD1 0x80 @@ -37,1538 +37,1527 @@ #define SAV_VBLANK_FIELD2 0xE0 #define EAV_VBLANK_FIELD2 0xF0 -#define SAV_VBI_FIELD1 0x20 -#define EAV_VBI_FIELD1 0x30 +#define SAV_VBI_FIELD1 0x20 +#define EAV_VBI_FIELD1 0x30 -#define SAV_VBI_FIELD2 0x60 -#define EAV_VBI_FIELD2 0x70 +#define SAV_VBI_FIELD2 0x60 +#define EAV_VBI_FIELD2 0x70 /*****************************************************************************/ /* Audio ADC Registers */ -#define CH_PWR_CTRL1 0x0000000E -#define CH_PWR_CTRL2 0x0000000F +#define CH_PWR_CTRL1 0x0000000E +#define CH_PWR_CTRL2 0x0000000F /*****************************************************************************/ -#define HOST_REG1 0x000 -#define FLD_FORCE_CHIP_SEL 0x80 -#define FLD_AUTO_INC_DIS 0x20 -#define FLD_PREFETCH_EN 0x10 +#define HOST_REG1 0x000 +#define FLD_FORCE_CHIP_SEL 0x80 +#define FLD_AUTO_INC_DIS 0x20 +#define FLD_PREFETCH_EN 0x10 /* Reserved [2:3] */ -#define FLD_DIGITAL_PWR_DN 0x02 -#define FLD_SLEEP 0x01 +#define FLD_DIGITAL_PWR_DN 0x02 +#define FLD_SLEEP 0x01 /*****************************************************************************/ -#define HOST_REG2 0x001 - +#define HOST_REG2 0x001 /*****************************************************************************/ -#define HOST_REG3 0x002 +#define HOST_REG3 0x002 /*****************************************************************************/ /* added for polaris */ -#define GPIO_PIN_CTL0 0x3 -#define GPIO_PIN_CTL1 0x4 -#define GPIO_PIN_CTL2 0x5 -#define GPIO_PIN_CTL3 0x6 -#define TS1_PIN_CTL0 0x7 -#define TS1_PIN_CTL1 0x8 +#define GPIO_PIN_CTL0 0x3 +#define GPIO_PIN_CTL1 0x4 +#define GPIO_PIN_CTL2 0x5 +#define GPIO_PIN_CTL3 0x6 +#define TS1_PIN_CTL0 0x7 +#define TS1_PIN_CTL1 0x8 /*****************************************************************************/ -#define FLD_CLK_IN_EN 0x80 -#define FLD_XTAL_CTRL 0x70 -#define FLD_BB_CLK_MODE 0x0C -#define FLD_REF_DIV_PLL 0x02 -#define FLD_REF_SEL_PLL1 0x01 +#define FLD_CLK_IN_EN 0x80 +#define FLD_XTAL_CTRL 0x70 +#define FLD_BB_CLK_MODE 0x0C +#define FLD_REF_DIV_PLL 0x02 +#define FLD_REF_SEL_PLL1 0x01 /*****************************************************************************/ -#define CHIP_CTRL 0x100 +#define CHIP_CTRL 0x100 /* Reserved [27] */ /* Reserved [31:21] */ -#define FLD_CHIP_ACFG_DIS 0x00100000 +#define FLD_CHIP_ACFG_DIS 0x00100000 /* Reserved [19] */ -#define FLD_DUAL_MODE_ADC2 0x00040000 -#define FLD_SIF_EN 0x00020000 -#define FLD_SOFT_RST 0x00010000 -#define FLD_DEVICE_ID 0x0000FFFF - -/*****************************************************************************/ -#define AFE_CTRL 0x104 -#define AFE_CTRL_C2HH_SRC_CTRL 0x104 -#define FLD_DIF_OUT_SEL 0xC0000000 -#define FLD_AUX_PLL_CLK_ALT_SEL 0x3C000000 -#define FLD_UV_ORDER_MODE 0x02000000 -#define FLD_FUNC_MODE 0x01800000 -#define FLD_ROT1_PHASE_CTL 0x007F8000 -#define FLD_AUD_IN_SEL 0x00004000 -#define FLD_LUMA_IN_SEL 0x00002000 -#define FLD_CHROMA_IN_SEL 0x00001000 +#define FLD_DUAL_MODE_ADC2 0x00040000 +#define FLD_SIF_EN 0x00020000 +#define FLD_SOFT_RST 0x00010000 +#define FLD_DEVICE_ID 0x0000FFFF + +/*****************************************************************************/ +#define AFE_CTRL 0x104 +#define AFE_CTRL_C2HH_SRC_CTRL 0x104 +#define FLD_DIF_OUT_SEL 0xC0000000 +#define FLD_AUX_PLL_CLK_ALT_SEL 0x3C000000 +#define FLD_UV_ORDER_MODE 0x02000000 +#define FLD_FUNC_MODE 0x01800000 +#define FLD_ROT1_PHASE_CTL 0x007F8000 +#define FLD_AUD_IN_SEL 0x00004000 +#define FLD_LUMA_IN_SEL 0x00002000 +#define FLD_CHROMA_IN_SEL 0x00001000 /* reserve [11:10] */ -#define FLD_INV_SPEC_DIS 0x00000200 -#define FLD_VGA_SEL_CH3 0x00000100 -#define FLD_VGA_SEL_CH2 0x00000080 -#define FLD_VGA_SEL_CH1 0x00000040 -#define FLD_DCR_BYP_CH1 0x00000020 -#define FLD_DCR_BYP_CH2 0x00000010 -#define FLD_DCR_BYP_CH3 0x00000008 -#define FLD_EN_12DB_CH3 0x00000004 -#define FLD_EN_12DB_CH2 0x00000002 -#define FLD_EN_12DB_CH1 0x00000001 +#define FLD_INV_SPEC_DIS 0x00000200 +#define FLD_VGA_SEL_CH3 0x00000100 +#define FLD_VGA_SEL_CH2 0x00000080 +#define FLD_VGA_SEL_CH1 0x00000040 +#define FLD_DCR_BYP_CH1 0x00000020 +#define FLD_DCR_BYP_CH2 0x00000010 +#define FLD_DCR_BYP_CH3 0x00000008 +#define FLD_EN_12DB_CH3 0x00000004 +#define FLD_EN_12DB_CH2 0x00000002 +#define FLD_EN_12DB_CH1 0x00000001 /* redefine in Cx231xx */ /*****************************************************************************/ -#define DC_CTRL1 0x108 +#define DC_CTRL1 0x108 /* reserve [31:30] */ -#define FLD_CLAMP_LVL_CH1 0x3FFF8000 -#define FLD_CLAMP_LVL_CH2 0x00007FFF +#define FLD_CLAMP_LVL_CH1 0x3FFF8000 +#define FLD_CLAMP_LVL_CH2 0x00007FFF /*****************************************************************************/ /*****************************************************************************/ -#define DC_CTRL2 0x10c +#define DC_CTRL2 0x10c /* reserve [31:28] */ -#define FLD_CLAMP_LVL_CH3 0x00FFFE00 -#define FLD_CLAMP_WIND_LENTH 0x000001E0 -#define FLD_C2HH_SAT_MIN 0x0000001E -#define FLD_FLT_BYP_SEL 0x00000001 +#define FLD_CLAMP_LVL_CH3 0x00FFFE00 +#define FLD_CLAMP_WIND_LENTH 0x000001E0 +#define FLD_C2HH_SAT_MIN 0x0000001E +#define FLD_FLT_BYP_SEL 0x00000001 /*****************************************************************************/ /*****************************************************************************/ -#define DC_CTRL3 0x110 +#define DC_CTRL3 0x110 /* reserve [31:16] */ -#define FLD_ERR_GAIN_CTL 0x00070000 -#define FLD_LPF_MIN 0x0000FFFF +#define FLD_ERR_GAIN_CTL 0x00070000 +#define FLD_LPF_MIN 0x0000FFFF /*****************************************************************************/ /*****************************************************************************/ -#define DC_CTRL4 0x114 +#define DC_CTRL4 0x114 /* reserve [31:31] */ -#define FLD_INTG_CH1 0x7FFFFFFF +#define FLD_INTG_CH1 0x7FFFFFFF /*****************************************************************************/ /*****************************************************************************/ -#define DC_CTRL5 0x118 +#define DC_CTRL5 0x118 /* reserve [31:31] */ -#define FLD_INTG_CH2 0x7FFFFFFF +#define FLD_INTG_CH2 0x7FFFFFFF /*****************************************************************************/ /*****************************************************************************/ -#define DC_CTRL6 0x11c +#define DC_CTRL6 0x11c /* reserve [31:31] */ -#define FLD_INTG_CH3 0x7FFFFFFF +#define FLD_INTG_CH3 0x7FFFFFFF /*****************************************************************************/ /*****************************************************************************/ -#define PIN_CTRL 0x120 -#define FLD_OEF_AGC_RF 0x00000001 -#define FLD_OEF_AGC_IFVGA 0x00000002 -#define FLD_OEF_AGC_IF 0x00000004 -#define FLD_REG_BO_PUD 0x80000000 -#define FLD_IR_IRQ_STAT 0x40000000 -#define FLD_AUD_IRQ_STAT 0x20000000 -#define FLD_VID_IRQ_STAT 0x10000000 +#define PIN_CTRL 0x120 +#define FLD_OEF_AGC_RF 0x00000001 +#define FLD_OEF_AGC_IFVGA 0x00000002 +#define FLD_OEF_AGC_IF 0x00000004 +#define FLD_REG_BO_PUD 0x80000000 +#define FLD_IR_IRQ_STAT 0x40000000 +#define FLD_AUD_IRQ_STAT 0x20000000 +#define FLD_VID_IRQ_STAT 0x10000000 /* Reserved [27:26] */ -#define FLD_IRQ_N_OUT_EN 0x02000000 -#define FLD_IRQ_N_POLAR 0x01000000 +#define FLD_IRQ_N_OUT_EN 0x02000000 +#define FLD_IRQ_N_POLAR 0x01000000 /* Reserved [23:6] */ -#define FLD_OE_AUX_PLL_CLK 0x00000020 -#define FLD_OE_I2S_BCLK 0x00000010 -#define FLD_OE_I2S_WCLK 0x00000008 -#define FLD_OE_AGC_IF 0x00000004 -#define FLD_OE_AGC_IFVGA 0x00000002 -#define FLD_OE_AGC_RF 0x00000001 +#define FLD_OE_AUX_PLL_CLK 0x00000020 +#define FLD_OE_I2S_BCLK 0x00000010 +#define FLD_OE_I2S_WCLK 0x00000008 +#define FLD_OE_AGC_IF 0x00000004 +#define FLD_OE_AGC_IFVGA 0x00000002 +#define FLD_OE_AGC_RF 0x00000001 /*****************************************************************************/ -#define AUD_IO_CTRL 0x124 +#define AUD_IO_CTRL 0x124 /* Reserved [31:8] */ -#define FLD_I2S_PORT_DIR 0x00000080 -#define FLD_I2S_OUT_SRC 0x00000040 -#define FLD_AUD_CHAN3_SRC 0x00000030 -#define FLD_AUD_CHAN2_SRC 0x0000000C -#define FLD_AUD_CHAN1_SRC 0x00000003 +#define FLD_I2S_PORT_DIR 0x00000080 +#define FLD_I2S_OUT_SRC 0x00000040 +#define FLD_AUD_CHAN3_SRC 0x00000030 +#define FLD_AUD_CHAN2_SRC 0x0000000C +#define FLD_AUD_CHAN1_SRC 0x00000003 /*****************************************************************************/ -#define AUD_LOCK1 0x128 -#define FLD_AUD_LOCK_KI_SHIFT 0xC0000000 -#define FLD_AUD_LOCK_KD_SHIFT 0x30000000 +#define AUD_LOCK1 0x128 +#define FLD_AUD_LOCK_KI_SHIFT 0xC0000000 +#define FLD_AUD_LOCK_KD_SHIFT 0x30000000 /* Reserved [27:25] */ -#define FLD_EN_AV_LOCK 0x01000000 -#define FLD_VID_COUNT 0x00FFFFFF +#define FLD_EN_AV_LOCK 0x01000000 +#define FLD_VID_COUNT 0x00FFFFFF /*****************************************************************************/ -#define AUD_LOCK2 0x12C -#define FLD_AUD_LOCK_KI_MULT 0xF0000000 -#define FLD_AUD_LOCK_KD_MULT 0x0F000000 +#define AUD_LOCK2 0x12C +#define FLD_AUD_LOCK_KI_MULT 0xF0000000 +#define FLD_AUD_LOCK_KD_MULT 0x0F000000 /* Reserved [23:22] */ -#define FLD_AUD_LOCK_FREQ_SHIFT 0x00300000 -#define FLD_AUD_COUNT 0x000FFFFF +#define FLD_AUD_LOCK_FREQ_SHIFT 0x00300000 +#define FLD_AUD_COUNT 0x000FFFFF /*****************************************************************************/ -#define AFE_DIAG_CTRL1 0x134 +#define AFE_DIAG_CTRL1 0x134 /* Reserved [31:16] */ -#define FLD_CUV_DLY_LENGTH 0x0000FF00 -#define FLD_YC_DLY_LENGTH 0x000000FF +#define FLD_CUV_DLY_LENGTH 0x0000FF00 +#define FLD_YC_DLY_LENGTH 0x000000FF /*****************************************************************************/ /* Poalris redefine */ -#define AFE_DIAG_CTRL3 0x138 +#define AFE_DIAG_CTRL3 0x138 /* Reserved [31:26] */ -#define FLD_AUD_DUAL_FLAG_POL 0x02000000 -#define FLD_VID_DUAL_FLAG_POL 0x01000000 +#define FLD_AUD_DUAL_FLAG_POL 0x02000000 +#define FLD_VID_DUAL_FLAG_POL 0x01000000 /* Reserved [23:23] */ -#define FLD_COL_CLAMP_DIS_CH1 0x00400000 -#define FLD_COL_CLAMP_DIS_CH2 0x00200000 -#define FLD_COL_CLAMP_DIS_CH3 0x00100000 +#define FLD_COL_CLAMP_DIS_CH1 0x00400000 +#define FLD_COL_CLAMP_DIS_CH2 0x00200000 +#define FLD_COL_CLAMP_DIS_CH3 0x00100000 -#define TEST_CTRL1 0x144 +#define TEST_CTRL1 0x144 /* Reserved [31:29] */ -#define FLD_LBIST_EN 0x10000000 +#define FLD_LBIST_EN 0x10000000 /* Reserved [27:10] */ -#define FLD_FI_BIST_INTR_R 0x0000200 -#define FLD_FI_BIST_INTR_L 0x0000100 -#define FLD_BIST_FAIL_AUD_PLL 0x0000080 -#define FLD_BIST_INTR_AUD_PLL 0x0000040 -#define FLD_BIST_FAIL_VID_PLL 0x0000020 -#define FLD_BIST_INTR_VID_PLL 0x0000010 +#define FLD_FI_BIST_INTR_R 0x0000200 +#define FLD_FI_BIST_INTR_L 0x0000100 +#define FLD_BIST_FAIL_AUD_PLL 0x0000080 +#define FLD_BIST_INTR_AUD_PLL 0x0000040 +#define FLD_BIST_FAIL_VID_PLL 0x0000020 +#define FLD_BIST_INTR_VID_PLL 0x0000010 /* Reserved [3:1] */ -#define FLD_CIR_TEST_DIS 0x00000001 - +#define FLD_CIR_TEST_DIS 0x00000001 /*****************************************************************************/ -#define TEST_CTRL2 0x148 -#define FLD_TSXCLK_POL_CTL 0x80000000 -#define FLD_ISO_CTL_SEL 0x40000000 -#define FLD_ISO_CTL_EN 0x20000000 -#define FLD_BIST_DEBUGZ 0x10000000 -#define FLD_AUD_BIST_TEST_H 0x0F000000 +#define TEST_CTRL2 0x148 +#define FLD_TSXCLK_POL_CTL 0x80000000 +#define FLD_ISO_CTL_SEL 0x40000000 +#define FLD_ISO_CTL_EN 0x20000000 +#define FLD_BIST_DEBUGZ 0x10000000 +#define FLD_AUD_BIST_TEST_H 0x0F000000 /* Reserved [23:22] */ -#define FLD_FLTRN_BIST_TEST_H 0x00020000 -#define FLD_VID_BIST_TEST_H 0x00010000 +#define FLD_FLTRN_BIST_TEST_H 0x00020000 +#define FLD_VID_BIST_TEST_H 0x00010000 /* Reserved [19:17] */ -#define FLD_BIST_TEST_H 0x00010000 +#define FLD_BIST_TEST_H 0x00010000 /* Reserved [15:13] */ -#define FLD_TAB_EN 0x00001000 +#define FLD_TAB_EN 0x00001000 /* Reserved [11:0] */ /*****************************************************************************/ -#define BIST_STAT 0x14C -#define FLD_AUD_BIST_FAIL_H 0xFFF00000 -#define FLD_FLTRN_BIST_FAIL_H 0x00180000 -#define FLD_VID_BIST_FAIL_H 0x00070000 -#define FLD_AUD_BIST_TST_DONE 0x0000FFF0 -#define FLD_FLTRN_BIST_TST_DONE 0x00000008 -#define FLD_VID_BIST_TST_DONE 0x00000007 - +#define BIST_STAT 0x14C +#define FLD_AUD_BIST_FAIL_H 0xFFF00000 +#define FLD_FLTRN_BIST_FAIL_H 0x00180000 +#define FLD_VID_BIST_FAIL_H 0x00070000 +#define FLD_AUD_BIST_TST_DONE 0x0000FFF0 +#define FLD_FLTRN_BIST_TST_DONE 0x00000008 +#define FLD_VID_BIST_TST_DONE 0x00000007 /*****************************************************************************/ /* DirectIF registers definition have been moved to DIF_reg.h */ /*****************************************************************************/ -#define MODE_CTRL 0x400 -#define FLD_AFD_PAL60_DIS 0x20000000 -#define FLD_AFD_FORCE_SECAM 0x10000000 -#define FLD_AFD_FORCE_PALNC 0x08000000 -#define FLD_AFD_FORCE_PAL 0x04000000 -#define FLD_AFD_PALM_SEL 0x03000000 -#define FLD_CKILL_MODE 0x00300000 -#define FLD_COMB_NOTCH_MODE 0x00c00000 /* bit[19:18] */ -#define FLD_CLR_LOCK_STAT 0x00020000 -#define FLD_FAST_LOCK_MD 0x00010000 -#define FLD_WCEN 0x00008000 -#define FLD_CAGCEN 0x00004000 -#define FLD_CKILLEN 0x00002000 -#define FLD_AUTO_SC_LOCK 0x00001000 -#define FLD_MAN_SC_FAST_LOCK 0x00000800 -#define FLD_INPUT_MODE 0x00000600 -#define FLD_AFD_ACQUIRE 0x00000100 -#define FLD_AFD_NTSC_SEL 0x00000080 -#define FLD_AFD_PAL_SEL 0x00000040 -#define FLD_ACFG_DIS 0x00000020 -#define FLD_SQ_PIXEL 0x00000010 -#define FLD_VID_FMT_SEL 0x0000000F - -/*****************************************************************************/ -#define OUT_CTRL1 0x404 -#define FLD_POLAR 0x7F000000 +#define MODE_CTRL 0x400 +#define FLD_AFD_PAL60_DIS 0x20000000 +#define FLD_AFD_FORCE_SECAM 0x10000000 +#define FLD_AFD_FORCE_PALNC 0x08000000 +#define FLD_AFD_FORCE_PAL 0x04000000 +#define FLD_AFD_PALM_SEL 0x03000000 +#define FLD_CKILL_MODE 0x00300000 +#define FLD_COMB_NOTCH_MODE 0x00c00000 /* bit[19:18] */ +#define FLD_CLR_LOCK_STAT 0x00020000 +#define FLD_FAST_LOCK_MD 0x00010000 +#define FLD_WCEN 0x00008000 +#define FLD_CAGCEN 0x00004000 +#define FLD_CKILLEN 0x00002000 +#define FLD_AUTO_SC_LOCK 0x00001000 +#define FLD_MAN_SC_FAST_LOCK 0x00000800 +#define FLD_INPUT_MODE 0x00000600 +#define FLD_AFD_ACQUIRE 0x00000100 +#define FLD_AFD_NTSC_SEL 0x00000080 +#define FLD_AFD_PAL_SEL 0x00000040 +#define FLD_ACFG_DIS 0x00000020 +#define FLD_SQ_PIXEL 0x00000010 +#define FLD_VID_FMT_SEL 0x0000000F + +/*****************************************************************************/ +#define OUT_CTRL1 0x404 +#define FLD_POLAR 0x7F000000 /* Reserved [23] */ -#define FLD_RND_MODE 0x00600000 -#define FLD_VIPCLAMP_EN 0x00100000 -#define FLD_VIPBLANK_EN 0x00080000 -#define FLD_VIP_OPT_AL 0x00040000 -#define FLD_IDID0_SOURCE 0x00020000 -#define FLD_DCMODE 0x00010000 -#define FLD_CLK_GATING 0x0000C000 -#define FLD_CLK_INVERT 0x00002000 -#define FLD_HSFMT 0x00001000 -#define FLD_VALIDFMT 0x00000800 -#define FLD_ACTFMT 0x00000400 -#define FLD_SWAPRAW 0x00000200 -#define FLD_CLAMPRAW_EN 0x00000100 -#define FLD_BLUE_FIELD_EN 0x00000080 -#define FLD_BLUE_FIELD_ACT 0x00000040 -#define FLD_TASKBIT_VAL 0x00000020 -#define FLD_ANC_DATA_EN 0x00000010 -#define FLD_VBIHACTRAW_EN 0x00000008 -#define FLD_MODE10B 0x00000004 -#define FLD_OUT_MODE 0x00000003 - -/*****************************************************************************/ -#define OUT_CTRL2 0x408 -#define FLD_AUD_GRP 0xC0000000 -#define FLD_SAMPLE_RATE 0x30000000 -#define FLD_AUD_ANC_EN 0x08000000 -#define FLD_EN_C 0x04000000 -#define FLD_EN_B 0x02000000 -#define FLD_EN_A 0x01000000 +#define FLD_RND_MODE 0x00600000 +#define FLD_VIPCLAMP_EN 0x00100000 +#define FLD_VIPBLANK_EN 0x00080000 +#define FLD_VIP_OPT_AL 0x00040000 +#define FLD_IDID0_SOURCE 0x00020000 +#define FLD_DCMODE 0x00010000 +#define FLD_CLK_GATING 0x0000C000 +#define FLD_CLK_INVERT 0x00002000 +#define FLD_HSFMT 0x00001000 +#define FLD_VALIDFMT 0x00000800 +#define FLD_ACTFMT 0x00000400 +#define FLD_SWAPRAW 0x00000200 +#define FLD_CLAMPRAW_EN 0x00000100 +#define FLD_BLUE_FIELD_EN 0x00000080 +#define FLD_BLUE_FIELD_ACT 0x00000040 +#define FLD_TASKBIT_VAL 0x00000020 +#define FLD_ANC_DATA_EN 0x00000010 +#define FLD_VBIHACTRAW_EN 0x00000008 +#define FLD_MODE10B 0x00000004 +#define FLD_OUT_MODE 0x00000003 + +/*****************************************************************************/ +#define OUT_CTRL2 0x408 +#define FLD_AUD_GRP 0xC0000000 +#define FLD_SAMPLE_RATE 0x30000000 +#define FLD_AUD_ANC_EN 0x08000000 +#define FLD_EN_C 0x04000000 +#define FLD_EN_B 0x02000000 +#define FLD_EN_A 0x01000000 /* Reserved [23:20] */ -#define FLD_IDID1_LSB 0x000C0000 -#define FLD_IDID0_LSB 0x00030000 -#define FLD_IDID1_MSB 0x0000FF00 -#define FLD_IDID0_MSB 0x000000FF - -/*****************************************************************************/ -#define GEN_STAT 0x40C -#define FLD_VCR_DETECT 0x00800000 -#define FLD_SPECIAL_PLAY_N 0x00400000 -#define FLD_VPRES 0x00200000 -#define FLD_AGC_LOCK 0x00100000 -#define FLD_CSC_LOCK 0x00080000 -#define FLD_VLOCK 0x00040000 -#define FLD_SRC_LOCK 0x00020000 -#define FLD_HLOCK 0x00010000 -#define FLD_VSYNC_N 0x00008000 -#define FLD_SRC_FIFO_UFLOW 0x00004000 -#define FLD_SRC_FIFO_OFLOW 0x00002000 -#define FLD_FIELD 0x00001000 -#define FLD_AFD_FMT_STAT 0x00000F00 -#define FLD_MV_TYPE2_PAIR 0x00000080 -#define FLD_MV_T3CS 0x00000040 -#define FLD_MV_CS 0x00000020 -#define FLD_MV_PSP 0x00000010 +#define FLD_IDID1_LSB 0x000C0000 +#define FLD_IDID0_LSB 0x00030000 +#define FLD_IDID1_MSB 0x0000FF00 +#define FLD_IDID0_MSB 0x000000FF + +/*****************************************************************************/ +#define GEN_STAT 0x40C +#define FLD_VCR_DETECT 0x00800000 +#define FLD_SPECIAL_PLAY_N 0x00400000 +#define FLD_VPRES 0x00200000 +#define FLD_AGC_LOCK 0x00100000 +#define FLD_CSC_LOCK 0x00080000 +#define FLD_VLOCK 0x00040000 +#define FLD_SRC_LOCK 0x00020000 +#define FLD_HLOCK 0x00010000 +#define FLD_VSYNC_N 0x00008000 +#define FLD_SRC_FIFO_UFLOW 0x00004000 +#define FLD_SRC_FIFO_OFLOW 0x00002000 +#define FLD_FIELD 0x00001000 +#define FLD_AFD_FMT_STAT 0x00000F00 +#define FLD_MV_TYPE2_PAIR 0x00000080 +#define FLD_MV_T3CS 0x00000040 +#define FLD_MV_CS 0x00000020 +#define FLD_MV_PSP 0x00000010 /* Reserved [3] */ -#define FLD_MV_CDAT 0x00000003 - -/*****************************************************************************/ -#define INT_STAT_MASK 0x410 -#define FLD_COMB_3D_FIFO_MSK 0x80000000 -#define FLD_WSS_DAT_AVAIL_MSK 0x40000000 -#define FLD_GS2_DAT_AVAIL_MSK 0x20000000 -#define FLD_GS1_DAT_AVAIL_MSK 0x10000000 -#define FLD_CC_DAT_AVAIL_MSK 0x08000000 -#define FLD_VPRES_CHANGE_MSK 0x04000000 -#define FLD_MV_CHANGE_MSK 0x02000000 -#define FLD_END_VBI_EVEN_MSK 0x01000000 -#define FLD_END_VBI_ODD_MSK 0x00800000 -#define FLD_FMT_CHANGE_MSK 0x00400000 -#define FLD_VSYNC_TRAIL_MSK 0x00200000 -#define FLD_HLOCK_CHANGE_MSK 0x00100000 -#define FLD_VLOCK_CHANGE_MSK 0x00080000 -#define FLD_CSC_LOCK_CHANGE_MSK 0x00040000 -#define FLD_SRC_FIFO_UFLOW_MSK 0x00020000 -#define FLD_SRC_FIFO_OFLOW_MSK 0x00010000 -#define FLD_COMB_3D_FIFO_STAT 0x00008000 -#define FLD_WSS_DAT_AVAIL_STAT 0x00004000 -#define FLD_GS2_DAT_AVAIL_STAT 0x00002000 -#define FLD_GS1_DAT_AVAIL_STAT 0x00001000 -#define FLD_CC_DAT_AVAIL_STAT 0x00000800 -#define FLD_VPRES_CHANGE_STAT 0x00000400 -#define FLD_MV_CHANGE_STAT 0x00000200 -#define FLD_END_VBI_EVEN_STAT 0x00000100 -#define FLD_END_VBI_ODD_STAT 0x00000080 -#define FLD_FMT_CHANGE_STAT 0x00000040 -#define FLD_VSYNC_TRAIL_STAT 0x00000020 -#define FLD_HLOCK_CHANGE_STAT 0x00000010 -#define FLD_VLOCK_CHANGE_STAT 0x00000008 -#define FLD_CSC_LOCK_CHANGE_STAT 0x00000004 -#define FLD_SRC_FIFO_UFLOW_STAT 0x00000002 -#define FLD_SRC_FIFO_OFLOW_STAT 0x00000001 - -/*****************************************************************************/ -#define LUMA_CTRL 0x414 -#define BRIGHTNESS_CTRL_BYTE 0x414 -#define CONTRAST_CTRL_BYTE 0x415 -#define LUMA_CTRL_BYTE_3 0x416 -#define FLD_LUMA_CORE_SEL 0x00C00000 -#define FLD_RANGE 0x00300000 +#define FLD_MV_CDAT 0x00000003 + +/*****************************************************************************/ +#define INT_STAT_MASK 0x410 +#define FLD_COMB_3D_FIFO_MSK 0x80000000 +#define FLD_WSS_DAT_AVAIL_MSK 0x40000000 +#define FLD_GS2_DAT_AVAIL_MSK 0x20000000 +#define FLD_GS1_DAT_AVAIL_MSK 0x10000000 +#define FLD_CC_DAT_AVAIL_MSK 0x08000000 +#define FLD_VPRES_CHANGE_MSK 0x04000000 +#define FLD_MV_CHANGE_MSK 0x02000000 +#define FLD_END_VBI_EVEN_MSK 0x01000000 +#define FLD_END_VBI_ODD_MSK 0x00800000 +#define FLD_FMT_CHANGE_MSK 0x00400000 +#define FLD_VSYNC_TRAIL_MSK 0x00200000 +#define FLD_HLOCK_CHANGE_MSK 0x00100000 +#define FLD_VLOCK_CHANGE_MSK 0x00080000 +#define FLD_CSC_LOCK_CHANGE_MSK 0x00040000 +#define FLD_SRC_FIFO_UFLOW_MSK 0x00020000 +#define FLD_SRC_FIFO_OFLOW_MSK 0x00010000 +#define FLD_COMB_3D_FIFO_STAT 0x00008000 +#define FLD_WSS_DAT_AVAIL_STAT 0x00004000 +#define FLD_GS2_DAT_AVAIL_STAT 0x00002000 +#define FLD_GS1_DAT_AVAIL_STAT 0x00001000 +#define FLD_CC_DAT_AVAIL_STAT 0x00000800 +#define FLD_VPRES_CHANGE_STAT 0x00000400 +#define FLD_MV_CHANGE_STAT 0x00000200 +#define FLD_END_VBI_EVEN_STAT 0x00000100 +#define FLD_END_VBI_ODD_STAT 0x00000080 +#define FLD_FMT_CHANGE_STAT 0x00000040 +#define FLD_VSYNC_TRAIL_STAT 0x00000020 +#define FLD_HLOCK_CHANGE_STAT 0x00000010 +#define FLD_VLOCK_CHANGE_STAT 0x00000008 +#define FLD_CSC_LOCK_CHANGE_STAT 0x00000004 +#define FLD_SRC_FIFO_UFLOW_STAT 0x00000002 +#define FLD_SRC_FIFO_OFLOW_STAT 0x00000001 + +/*****************************************************************************/ +#define LUMA_CTRL 0x414 +#define BRIGHTNESS_CTRL_BYTE 0x414 +#define CONTRAST_CTRL_BYTE 0x415 +#define LUMA_CTRL_BYTE_3 0x416 +#define FLD_LUMA_CORE_SEL 0x00C00000 +#define FLD_RANGE 0x00300000 /* Reserved [19] */ -#define FLD_PEAK_EN 0x00040000 -#define FLD_PEAK_SEL 0x00030000 -#define FLD_CNTRST 0x0000FF00 -#define FLD_BRITE 0x000000FF +#define FLD_PEAK_EN 0x00040000 +#define FLD_PEAK_SEL 0x00030000 +#define FLD_CNTRST 0x0000FF00 +#define FLD_BRITE 0x000000FF /*****************************************************************************/ -#define HSCALE_CTRL 0x418 -#define FLD_HFILT 0x03000000 -#define FLD_HSCALE 0x00FFFFFF +#define HSCALE_CTRL 0x418 +#define FLD_HFILT 0x03000000 +#define FLD_HSCALE 0x00FFFFFF /*****************************************************************************/ -#define VSCALE_CTRL 0x41C -#define FLD_LINE_AVG_DIS 0x01000000 +#define VSCALE_CTRL 0x41C +#define FLD_LINE_AVG_DIS 0x01000000 /* Reserved [23:20] */ -#define FLD_VS_INTRLACE 0x00080000 -#define FLD_VFILT 0x00070000 +#define FLD_VS_INTRLACE 0x00080000 +#define FLD_VFILT 0x00070000 /* Reserved [15:13] */ -#define FLD_VSCALE 0x00001FFF +#define FLD_VSCALE 0x00001FFF /*****************************************************************************/ -#define CHROMA_CTRL 0x420 -#define USAT_CTRL_BYTE 0x420 -#define VSAT_CTRL_BYTE 0x421 -#define HUE_CTRL_BYTE 0x422 -#define FLD_C_LPF_EN 0x20000000 -#define FLD_CHR_DELAY 0x1C000000 -#define FLD_C_CORE_SEL 0x03000000 -#define FLD_HUE 0x00FF0000 -#define FLD_VSAT 0x0000FF00 -#define FLD_USAT 0x000000FF +#define CHROMA_CTRL 0x420 +#define USAT_CTRL_BYTE 0x420 +#define VSAT_CTRL_BYTE 0x421 +#define HUE_CTRL_BYTE 0x422 +#define FLD_C_LPF_EN 0x20000000 +#define FLD_CHR_DELAY 0x1C000000 +#define FLD_C_CORE_SEL 0x03000000 +#define FLD_HUE 0x00FF0000 +#define FLD_VSAT 0x0000FF00 +#define FLD_USAT 0x000000FF /*****************************************************************************/ -#define VBI_LINE_CTRL1 0x424 -#define FLD_VBI_MD_LINE4 0xFF000000 -#define FLD_VBI_MD_LINE3 0x00FF0000 -#define FLD_VBI_MD_LINE2 0x0000FF00 -#define FLD_VBI_MD_LINE1 0x000000FF +#define VBI_LINE_CTRL1 0x424 +#define FLD_VBI_MD_LINE4 0xFF000000 +#define FLD_VBI_MD_LINE3 0x00FF0000 +#define FLD_VBI_MD_LINE2 0x0000FF00 +#define FLD_VBI_MD_LINE1 0x000000FF /*****************************************************************************/ -#define VBI_LINE_CTRL2 0x428 -#define FLD_VBI_MD_LINE8 0xFF000000 -#define FLD_VBI_MD_LINE7 0x00FF0000 -#define FLD_VBI_MD_LINE6 0x0000FF00 -#define FLD_VBI_MD_LINE5 0x000000FF +#define VBI_LINE_CTRL2 0x428 +#define FLD_VBI_MD_LINE8 0xFF000000 +#define FLD_VBI_MD_LINE7 0x00FF0000 +#define FLD_VBI_MD_LINE6 0x0000FF00 +#define FLD_VBI_MD_LINE5 0x000000FF /*****************************************************************************/ -#define VBI_LINE_CTRL3 0x42C -#define FLD_VBI_MD_LINE12 0xFF000000 -#define FLD_VBI_MD_LINE11 0x00FF0000 -#define FLD_VBI_MD_LINE10 0x0000FF00 -#define FLD_VBI_MD_LINE9 0x000000FF +#define VBI_LINE_CTRL3 0x42C +#define FLD_VBI_MD_LINE12 0xFF000000 +#define FLD_VBI_MD_LINE11 0x00FF0000 +#define FLD_VBI_MD_LINE10 0x0000FF00 +#define FLD_VBI_MD_LINE9 0x000000FF /*****************************************************************************/ -#define VBI_LINE_CTRL4 0x430 -#define FLD_VBI_MD_LINE16 0xFF000000 -#define FLD_VBI_MD_LINE15 0x00FF0000 -#define FLD_VBI_MD_LINE14 0x0000FF00 -#define FLD_VBI_MD_LINE13 0x000000FF +#define VBI_LINE_CTRL4 0x430 +#define FLD_VBI_MD_LINE16 0xFF000000 +#define FLD_VBI_MD_LINE15 0x00FF0000 +#define FLD_VBI_MD_LINE14 0x0000FF00 +#define FLD_VBI_MD_LINE13 0x000000FF /*****************************************************************************/ -#define VBI_LINE_CTRL5 0x434 -#define FLD_VBI_MD_LINE17 0x000000FF +#define VBI_LINE_CTRL5 0x434 +#define FLD_VBI_MD_LINE17 0x000000FF /*****************************************************************************/ -#define VBI_FC_CFG 0x438 -#define FLD_FC_ALT2 0xFF000000 -#define FLD_FC_ALT1 0x00FF0000 -#define FLD_FC_ALT2_TYPE 0x0000F000 -#define FLD_FC_ALT1_TYPE 0x00000F00 +#define VBI_FC_CFG 0x438 +#define FLD_FC_ALT2 0xFF000000 +#define FLD_FC_ALT1 0x00FF0000 +#define FLD_FC_ALT2_TYPE 0x0000F000 +#define FLD_FC_ALT1_TYPE 0x00000F00 /* Reserved [7:1] */ -#define FLD_FC_SEARCH_MODE 0x00000001 +#define FLD_FC_SEARCH_MODE 0x00000001 /*****************************************************************************/ -#define VBI_MISC_CFG1 0x43C -#define FLD_TTX_PKTADRU 0xFFF00000 -#define FLD_TTX_PKTADRL 0x000FFF00 +#define VBI_MISC_CFG1 0x43C +#define FLD_TTX_PKTADRU 0xFFF00000 +#define FLD_TTX_PKTADRL 0x000FFF00 /* Reserved [7:6] */ -#define FLD_MOJI_PACK_DIS 0x00000020 -#define FLD_VPS_DEC_DIS 0x00000010 -#define FLD_CRI_MARG_SCALE 0x0000000C -#define FLD_EDGE_RESYNC_EN 0x00000002 -#define FLD_ADAPT_SLICE_DIS 0x00000001 +#define FLD_MOJI_PACK_DIS 0x00000020 +#define FLD_VPS_DEC_DIS 0x00000010 +#define FLD_CRI_MARG_SCALE 0x0000000C +#define FLD_EDGE_RESYNC_EN 0x00000002 +#define FLD_ADAPT_SLICE_DIS 0x00000001 /*****************************************************************************/ -#define VBI_MISC_CFG2 0x440 -#define FLD_HAMMING_TYPE 0x0F000000 +#define VBI_MISC_CFG2 0x440 +#define FLD_HAMMING_TYPE 0x0F000000 /* Reserved [23:20] */ -#define FLD_WSS_FIFO_RST 0x00080000 -#define FLD_GS2_FIFO_RST 0x00040000 -#define FLD_GS1_FIFO_RST 0x00020000 -#define FLD_CC_FIFO_RST 0x00010000 +#define FLD_WSS_FIFO_RST 0x00080000 +#define FLD_GS2_FIFO_RST 0x00040000 +#define FLD_GS1_FIFO_RST 0x00020000 +#define FLD_CC_FIFO_RST 0x00010000 /* Reserved [15:12] */ -#define FLD_VBI3_SDID 0x00000F00 -#define FLD_VBI2_SDID 0x000000F0 -#define FLD_VBI1_SDID 0x0000000F +#define FLD_VBI3_SDID 0x00000F00 +#define FLD_VBI2_SDID 0x000000F0 +#define FLD_VBI1_SDID 0x0000000F /*****************************************************************************/ -#define VBI_PAY1 0x444 -#define FLD_GS1_FIFO_DAT 0xFF000000 -#define FLD_GS1_STAT 0x00FF0000 -#define FLD_CC_FIFO_DAT 0x0000FF00 -#define FLD_CC_STAT 0x000000FF +#define VBI_PAY1 0x444 +#define FLD_GS1_FIFO_DAT 0xFF000000 +#define FLD_GS1_STAT 0x00FF0000 +#define FLD_CC_FIFO_DAT 0x0000FF00 +#define FLD_CC_STAT 0x000000FF /*****************************************************************************/ -#define VBI_PAY2 0x448 -#define FLD_WSS_FIFO_DAT 0xFF000000 -#define FLD_WSS_STAT 0x00FF0000 -#define FLD_GS2_FIFO_DAT 0x0000FF00 -#define FLD_GS2_STAT 0x000000FF +#define VBI_PAY2 0x448 +#define FLD_WSS_FIFO_DAT 0xFF000000 +#define FLD_WSS_STAT 0x00FF0000 +#define FLD_GS2_FIFO_DAT 0x0000FF00 +#define FLD_GS2_STAT 0x000000FF /*****************************************************************************/ -#define VBI_CUST1_CFG1 0x44C +#define VBI_CUST1_CFG1 0x44C /* Reserved [31] */ -#define FLD_VBI1_CRIWIN 0x7F000000 -#define FLD_VBI1_SLICE_DIST 0x00F00000 -#define FLD_VBI1_BITINC 0x000FFF00 -#define FLD_VBI1_HDELAY 0x000000FF +#define FLD_VBI1_CRIWIN 0x7F000000 +#define FLD_VBI1_SLICE_DIST 0x00F00000 +#define FLD_VBI1_BITINC 0x000FFF00 +#define FLD_VBI1_HDELAY 0x000000FF /*****************************************************************************/ -#define VBI_CUST1_CFG2 0x450 -#define FLD_VBI1_FC_LENGTH 0x1F000000 -#define FLD_VBI1_FRAME_CODE 0x00FFFFFF +#define VBI_CUST1_CFG2 0x450 +#define FLD_VBI1_FC_LENGTH 0x1F000000 +#define FLD_VBI1_FRAME_CODE 0x00FFFFFF /*****************************************************************************/ -#define VBI_CUST1_CFG3 0x454 -#define FLD_VBI1_HAM_EN 0x80000000 -#define FLD_VBI1_FIFO_MODE 0x70000000 -#define FLD_VBI1_FORMAT_TYPE 0x0F000000 -#define FLD_VBI1_PAYLD_LENGTH 0x00FF0000 -#define FLD_VBI1_CRI_LENGTH 0x0000F000 -#define FLD_VBI1_CRI_MARGIN 0x00000F00 -#define FLD_VBI1_CRI_TIME 0x000000FF +#define VBI_CUST1_CFG3 0x454 +#define FLD_VBI1_HAM_EN 0x80000000 +#define FLD_VBI1_FIFO_MODE 0x70000000 +#define FLD_VBI1_FORMAT_TYPE 0x0F000000 +#define FLD_VBI1_PAYLD_LENGTH 0x00FF0000 +#define FLD_VBI1_CRI_LENGTH 0x0000F000 +#define FLD_VBI1_CRI_MARGIN 0x00000F00 +#define FLD_VBI1_CRI_TIME 0x000000FF /*****************************************************************************/ -#define VBI_CUST2_CFG1 0x458 +#define VBI_CUST2_CFG1 0x458 /* Reserved [31] */ -#define FLD_VBI2_CRIWIN 0x7F000000 -#define FLD_VBI2_SLICE_DIST 0x00F00000 -#define FLD_VBI2_BITINC 0x000FFF00 -#define FLD_VBI2_HDELAY 0x000000FF +#define FLD_VBI2_CRIWIN 0x7F000000 +#define FLD_VBI2_SLICE_DIST 0x00F00000 +#define FLD_VBI2_BITINC 0x000FFF00 +#define FLD_VBI2_HDELAY 0x000000FF /*****************************************************************************/ -#define VBI_CUST2_CFG2 0x45C -#define FLD_VBI2_FC_LENGTH 0x1F000000 -#define FLD_VBI2_FRAME_CODE 0x00FFFFFF +#define VBI_CUST2_CFG2 0x45C +#define FLD_VBI2_FC_LENGTH 0x1F000000 +#define FLD_VBI2_FRAME_CODE 0x00FFFFFF /*****************************************************************************/ -#define VBI_CUST2_CFG3 0x460 -#define FLD_VBI2_HAM_EN 0x80000000 -#define FLD_VBI2_FIFO_MODE 0x70000000 -#define FLD_VBI2_FORMAT_TYPE 0x0F000000 -#define FLD_VBI2_PAYLD_LENGTH 0x00FF0000 -#define FLD_VBI2_CRI_LENGTH 0x0000F000 -#define FLD_VBI2_CRI_MARGIN 0x00000F00 -#define FLD_VBI2_CRI_TIME 0x000000FF +#define VBI_CUST2_CFG3 0x460 +#define FLD_VBI2_HAM_EN 0x80000000 +#define FLD_VBI2_FIFO_MODE 0x70000000 +#define FLD_VBI2_FORMAT_TYPE 0x0F000000 +#define FLD_VBI2_PAYLD_LENGTH 0x00FF0000 +#define FLD_VBI2_CRI_LENGTH 0x0000F000 +#define FLD_VBI2_CRI_MARGIN 0x00000F00 +#define FLD_VBI2_CRI_TIME 0x000000FF /*****************************************************************************/ -#define VBI_CUST3_CFG1 0x464 +#define VBI_CUST3_CFG1 0x464 /* Reserved [31] */ -#define FLD_VBI3_CRIWIN 0x7F000000 -#define FLD_VBI3_SLICE_DIST 0x00F00000 -#define FLD_VBI3_BITINC 0x000FFF00 -#define FLD_VBI3_HDELAY 0x000000FF +#define FLD_VBI3_CRIWIN 0x7F000000 +#define FLD_VBI3_SLICE_DIST 0x00F00000 +#define FLD_VBI3_BITINC 0x000FFF00 +#define FLD_VBI3_HDELAY 0x000000FF /*****************************************************************************/ -#define VBI_CUST3_CFG2 0x468 -#define FLD_VBI3_FC_LENGTH 0x1F000000 -#define FLD_VBI3_FRAME_CODE 0x00FFFFFF +#define VBI_CUST3_CFG2 0x468 +#define FLD_VBI3_FC_LENGTH 0x1F000000 +#define FLD_VBI3_FRAME_CODE 0x00FFFFFF /*****************************************************************************/ -#define VBI_CUST3_CFG3 0x46C -#define FLD_VBI3_HAM_EN 0x80000000 -#define FLD_VBI3_FIFO_MODE 0x70000000 -#define FLD_VBI3_FORMAT_TYPE 0x0F000000 -#define FLD_VBI3_PAYLD_LENGTH 0x00FF0000 -#define FLD_VBI3_CRI_LENGTH 0x0000F000 -#define FLD_VBI3_CRI_MARGIN 0x00000F00 -#define FLD_VBI3_CRI_TIME 0x000000FF +#define VBI_CUST3_CFG3 0x46C +#define FLD_VBI3_HAM_EN 0x80000000 +#define FLD_VBI3_FIFO_MODE 0x70000000 +#define FLD_VBI3_FORMAT_TYPE 0x0F000000 +#define FLD_VBI3_PAYLD_LENGTH 0x00FF0000 +#define FLD_VBI3_CRI_LENGTH 0x0000F000 +#define FLD_VBI3_CRI_MARGIN 0x00000F00 +#define FLD_VBI3_CRI_TIME 0x000000FF /*****************************************************************************/ -#define HORIZ_TIM_CTRL 0x470 -#define FLD_BGDEL_CNT 0xFF000000 +#define HORIZ_TIM_CTRL 0x470 +#define FLD_BGDEL_CNT 0xFF000000 /* Reserved [23:22] */ -#define FLD_HACTIVE_CNT 0x003FF000 +#define FLD_HACTIVE_CNT 0x003FF000 /* Reserved [11:10] */ -#define FLD_HBLANK_CNT 0x000003FF +#define FLD_HBLANK_CNT 0x000003FF /*****************************************************************************/ -#define VERT_TIM_CTRL 0x474 -#define FLD_V656BLANK_CNT 0xFF000000 +#define VERT_TIM_CTRL 0x474 +#define FLD_V656BLANK_CNT 0xFF000000 /* Reserved [23:22] */ -#define FLD_VACTIVE_CNT 0x003FF000 +#define FLD_VACTIVE_CNT 0x003FF000 /* Reserved [11:10] */ -#define FLD_VBLANK_CNT 0x000003FF +#define FLD_VBLANK_CNT 0x000003FF /*****************************************************************************/ -#define SRC_COMB_CFG 0x478 -#define FLD_CCOMB_2LN_CHECK 0x80000000 -#define FLD_CCOMB_3LN_EN 0x40000000 -#define FLD_CCOMB_2LN_EN 0x20000000 -#define FLD_CCOMB_3D_EN 0x10000000 +#define SRC_COMB_CFG 0x478 +#define FLD_CCOMB_2LN_CHECK 0x80000000 +#define FLD_CCOMB_3LN_EN 0x40000000 +#define FLD_CCOMB_2LN_EN 0x20000000 +#define FLD_CCOMB_3D_EN 0x10000000 /* Reserved [27] */ -#define FLD_LCOMB_3LN_EN 0x04000000 -#define FLD_LCOMB_2LN_EN 0x02000000 -#define FLD_LCOMB_3D_EN 0x01000000 -#define FLD_LUMA_LPF_SEL 0x00C00000 -#define FLD_UV_LPF_SEL 0x00300000 -#define FLD_BLEND_SLOPE 0x000F0000 -#define FLD_CCOMB_REDUCE_EN 0x00008000 +#define FLD_LCOMB_3LN_EN 0x04000000 +#define FLD_LCOMB_2LN_EN 0x02000000 +#define FLD_LCOMB_3D_EN 0x01000000 +#define FLD_LUMA_LPF_SEL 0x00C00000 +#define FLD_UV_LPF_SEL 0x00300000 +#define FLD_BLEND_SLOPE 0x000F0000 +#define FLD_CCOMB_REDUCE_EN 0x00008000 /* Reserved [14:10] */ -#define FLD_SRC_DECIM_RATIO 0x000003FF +#define FLD_SRC_DECIM_RATIO 0x000003FF /*****************************************************************************/ -#define CHROMA_VBIOFF_CFG 0x47C -#define FLD_VBI_VOFFSET 0x1F000000 +#define CHROMA_VBIOFF_CFG 0x47C +#define FLD_VBI_VOFFSET 0x1F000000 /* Reserved [23:20] */ -#define FLD_SC_STEP 0x000FFFFF +#define FLD_SC_STEP 0x000FFFFF /*****************************************************************************/ -#define FIELD_COUNT 0x480 -#define FLD_FIELD_COUNT_FLD 0x000003FF +#define FIELD_COUNT 0x480 +#define FLD_FIELD_COUNT_FLD 0x000003FF /*****************************************************************************/ -#define MISC_TIM_CTRL 0x484 -#define FLD_DEBOUNCE_COUNT 0xC0000000 -#define FLD_VT_LINE_CNT_HYST 0x30000000 +#define MISC_TIM_CTRL 0x484 +#define FLD_DEBOUNCE_COUNT 0xC0000000 +#define FLD_VT_LINE_CNT_HYST 0x30000000 /* Reserved [27] */ -#define FLD_AFD_STAT 0x07FF0000 -#define FLD_VPRES_VERT_EN 0x00008000 +#define FLD_AFD_STAT 0x07FF0000 +#define FLD_VPRES_VERT_EN 0x00008000 /* Reserved [14:12] */ -#define FLD_HR32 0x00000800 -#define FLD_TDALGN 0x00000400 -#define FLD_TDFIELD 0x00000200 +#define FLD_HR32 0x00000800 +#define FLD_TDALGN 0x00000400 +#define FLD_TDFIELD 0x00000200 /* Reserved [8:6] */ -#define FLD_TEMPDEC 0x0000003F +#define FLD_TEMPDEC 0x0000003F /*****************************************************************************/ -#define DFE_CTRL1 0x488 -#define FLD_CLAMP_AUTO_EN 0x80000000 -#define FLD_AGC_AUTO_EN 0x40000000 -#define FLD_VGA_CRUSH_EN 0x20000000 -#define FLD_VGA_AUTO_EN 0x10000000 -#define FLD_VBI_GATE_EN 0x08000000 -#define FLD_CLAMP_LEVEL 0x07000000 +#define DFE_CTRL1 0x488 +#define FLD_CLAMP_AUTO_EN 0x80000000 +#define FLD_AGC_AUTO_EN 0x40000000 +#define FLD_VGA_CRUSH_EN 0x20000000 +#define FLD_VGA_AUTO_EN 0x10000000 +#define FLD_VBI_GATE_EN 0x08000000 +#define FLD_CLAMP_LEVEL 0x07000000 /* Reserved [23:22] */ -#define FLD_CLAMP_SKIP_CNT 0x00300000 -#define FLD_AGC_GAIN 0x000FFF00 +#define FLD_CLAMP_SKIP_CNT 0x00300000 +#define FLD_AGC_GAIN 0x000FFF00 /* Reserved [7:6] */ -#define FLD_VGA_GAIN 0x0000003F +#define FLD_VGA_GAIN 0x0000003F /*****************************************************************************/ -#define DFE_CTRL2 0x48C -#define FLD_VGA_ACQUIRE_RANGE 0x00FF0000 -#define FLD_VGA_TRACK_RANGE 0x0000FF00 -#define FLD_VGA_SYNC 0x000000FF +#define DFE_CTRL2 0x48C +#define FLD_VGA_ACQUIRE_RANGE 0x00FF0000 +#define FLD_VGA_TRACK_RANGE 0x0000FF00 +#define FLD_VGA_SYNC 0x000000FF /*****************************************************************************/ -#define DFE_CTRL3 0x490 -#define FLD_BP_PERCENT 0xFF000000 -#define FLD_DFT_THRESHOLD 0x00FF0000 +#define DFE_CTRL3 0x490 +#define FLD_BP_PERCENT 0xFF000000 +#define FLD_DFT_THRESHOLD 0x00FF0000 /* Reserved [15:12] */ -#define FLD_SYNC_WIDTH_SEL 0x00000600 -#define FLD_BP_LOOP_GAIN 0x00000300 -#define FLD_SYNC_LOOP_GAIN 0x000000C0 +#define FLD_SYNC_WIDTH_SEL 0x00000600 +#define FLD_BP_LOOP_GAIN 0x00000300 +#define FLD_SYNC_LOOP_GAIN 0x000000C0 /* Reserved [5:4] */ -#define FLD_AGC_LOOP_GAIN 0x0000000C -#define FLD_DCC_LOOP_GAIN 0x00000003 +#define FLD_AGC_LOOP_GAIN 0x0000000C +#define FLD_DCC_LOOP_GAIN 0x00000003 /*****************************************************************************/ -#define PLL_CTRL 0x494 -#define FLD_PLL_KD 0xFF000000 -#define FLD_PLL_KI 0x00FF0000 -#define FLD_PLL_MAX_OFFSET 0x0000FFFF - +#define PLL_CTRL 0x494 +#define FLD_PLL_KD 0xFF000000 +#define FLD_PLL_KI 0x00FF0000 +#define FLD_PLL_MAX_OFFSET 0x0000FFFF /*****************************************************************************/ -#define HTL_CTRL 0x498 +#define HTL_CTRL 0x498 /* Reserved [31:24] */ -#define FLD_AUTO_LOCK_SPD 0x00080000 -#define FLD_MAN_FAST_LOCK 0x00040000 -#define FLD_HTL_15K_EN 0x00020000 -#define FLD_HTL_500K_EN 0x00010000 -#define FLD_HTL_KD 0x0000FF00 -#define FLD_HTL_KI 0x000000FF - -/*****************************************************************************/ -#define COMB_CTRL 0x49C -#define FLD_COMB_PHASE_LIMIT 0xFF000000 -#define FLD_CCOMB_ERR_LIMIT 0x00FF0000 -#define FLD_LUMA_THRESHOLD 0x0000FF00 -#define FLD_LCOMB_ERR_LIMIT 0x000000FF - -/*****************************************************************************/ -#define CRUSH_CTRL 0x4A0 -#define FLD_WTW_EN 0x00400000 -#define FLD_CRUSH_FREQ 0x00200000 -#define FLD_MAJ_SEL_EN 0x00100000 -#define FLD_MAJ_SEL 0x000C0000 +#define FLD_AUTO_LOCK_SPD 0x00080000 +#define FLD_MAN_FAST_LOCK 0x00040000 +#define FLD_HTL_15K_EN 0x00020000 +#define FLD_HTL_500K_EN 0x00010000 +#define FLD_HTL_KD 0x0000FF00 +#define FLD_HTL_KI 0x000000FF + +/*****************************************************************************/ +#define COMB_CTRL 0x49C +#define FLD_COMB_PHASE_LIMIT 0xFF000000 +#define FLD_CCOMB_ERR_LIMIT 0x00FF0000 +#define FLD_LUMA_THRESHOLD 0x0000FF00 +#define FLD_LCOMB_ERR_LIMIT 0x000000FF + +/*****************************************************************************/ +#define CRUSH_CTRL 0x4A0 +#define FLD_WTW_EN 0x00400000 +#define FLD_CRUSH_FREQ 0x00200000 +#define FLD_MAJ_SEL_EN 0x00100000 +#define FLD_MAJ_SEL 0x000C0000 /* Reserved [17:15] */ -#define FLD_SYNC_TIP_REDUCE 0x00007E00 +#define FLD_SYNC_TIP_REDUCE 0x00007E00 /* Reserved [8:6] */ -#define FLD_SYNC_TIP_INC 0x0000003F +#define FLD_SYNC_TIP_INC 0x0000003F /*****************************************************************************/ -#define SOFT_RST_CTRL 0x4A4 -#define FLD_VD_SOFT_RST 0x00008000 +#define SOFT_RST_CTRL 0x4A4 +#define FLD_VD_SOFT_RST 0x00008000 /* Reserved [14:12] */ -#define FLD_REG_RST_MSK 0x00000800 -#define FLD_VOF_RST_MSK 0x00000400 -#define FLD_MVDET_RST_MSK 0x00000200 -#define FLD_VBI_RST_MSK 0x00000100 -#define FLD_SCALE_RST_MSK 0x00000080 -#define FLD_CHROMA_RST_MSK 0x00000040 -#define FLD_LUMA_RST_MSK 0x00000020 -#define FLD_VTG_RST_MSK 0x00000010 -#define FLD_YCSEP_RST_MSK 0x00000008 -#define FLD_SRC_RST_MSK 0x00000004 -#define FLD_DFE_RST_MSK 0x00000002 +#define FLD_REG_RST_MSK 0x00000800 +#define FLD_VOF_RST_MSK 0x00000400 +#define FLD_MVDET_RST_MSK 0x00000200 +#define FLD_VBI_RST_MSK 0x00000100 +#define FLD_SCALE_RST_MSK 0x00000080 +#define FLD_CHROMA_RST_MSK 0x00000040 +#define FLD_LUMA_RST_MSK 0x00000020 +#define FLD_VTG_RST_MSK 0x00000010 +#define FLD_YCSEP_RST_MSK 0x00000008 +#define FLD_SRC_RST_MSK 0x00000004 +#define FLD_DFE_RST_MSK 0x00000002 /* Reserved [0] */ /*****************************************************************************/ -#define MV_DT_CTRL1 0x4A8 +#define MV_DT_CTRL1 0x4A8 /* Reserved [31:29] */ -#define FLD_PSP_STOP_LINE 0x1F000000 +#define FLD_PSP_STOP_LINE 0x1F000000 /* Reserved [23:21] */ -#define FLD_PSP_STRT_LINE 0x001F0000 +#define FLD_PSP_STRT_LINE 0x001F0000 /* Reserved [15] */ -#define FLD_PSP_LLIMW 0x00007F00 +#define FLD_PSP_LLIMW 0x00007F00 /* Reserved [7] */ -#define FLD_PSP_ULIMW 0x0000007F +#define FLD_PSP_ULIMW 0x0000007F /*****************************************************************************/ -#define MV_DT_CTRL2 0x4AC -#define FLD_CS_STOPWIN 0xFF000000 -#define FLD_CS_STRTWIN 0x00FF0000 -#define FLD_CS_WIDTH 0x0000FF00 -#define FLD_PSP_SPEC_VAL 0x000000FF +#define MV_DT_CTRL2 0x4AC +#define FLD_CS_STOPWIN 0xFF000000 +#define FLD_CS_STRTWIN 0x00FF0000 +#define FLD_CS_WIDTH 0x0000FF00 +#define FLD_PSP_SPEC_VAL 0x000000FF /*****************************************************************************/ -#define MV_DT_CTRL3 0x4B0 -#define FLD_AUTO_RATE_DIS 0x80000000 -#define FLD_HLOCK_DIS 0x40000000 -#define FLD_SEL_FIELD_CNT 0x20000000 -#define FLD_CS_TYPE2_SEL 0x10000000 -#define FLD_CS_LINE_THRSH_SEL 0x08000000 -#define FLD_CS_ATHRESH_SEL 0x04000000 -#define FLD_PSP_SPEC_SEL 0x02000000 -#define FLD_PSP_LINES_SEL 0x01000000 -#define FLD_FIELD_CNT 0x00F00000 -#define FLD_CS_TYPE2_CNT 0x000FC000 -#define FLD_CS_LINE_CNT 0x00003F00 -#define FLD_CS_ATHRESH_LEV 0x000000FF +#define MV_DT_CTRL3 0x4B0 +#define FLD_AUTO_RATE_DIS 0x80000000 +#define FLD_HLOCK_DIS 0x40000000 +#define FLD_SEL_FIELD_CNT 0x20000000 +#define FLD_CS_TYPE2_SEL 0x10000000 +#define FLD_CS_LINE_THRSH_SEL 0x08000000 +#define FLD_CS_ATHRESH_SEL 0x04000000 +#define FLD_PSP_SPEC_SEL 0x02000000 +#define FLD_PSP_LINES_SEL 0x01000000 +#define FLD_FIELD_CNT 0x00F00000 +#define FLD_CS_TYPE2_CNT 0x000FC000 +#define FLD_CS_LINE_CNT 0x00003F00 +#define FLD_CS_ATHRESH_LEV 0x000000FF /*****************************************************************************/ -#define CHIP_VERSION 0x4B4 +#define CHIP_VERSION 0x4B4 /* Cx231xx redefine */ -#define VERSION 0x4B4 -#define FLD_REV_ID 0x000000FF +#define VERSION 0x4B4 +#define FLD_REV_ID 0x000000FF /*****************************************************************************/ -#define MISC_DIAG_CTRL 0x4B8 +#define MISC_DIAG_CTRL 0x4B8 /* Reserved [31:24] */ -#define FLD_SC_CONVERGE_THRESH 0x00FF0000 -#define FLD_CCOMB_ERR_LIMIT_3D 0x0000FF00 -#define FLD_LCOMB_ERR_LIMIT_3D 0x000000FF +#define FLD_SC_CONVERGE_THRESH 0x00FF0000 +#define FLD_CCOMB_ERR_LIMIT_3D 0x0000FF00 +#define FLD_LCOMB_ERR_LIMIT_3D 0x000000FF /*****************************************************************************/ -#define VBI_PASS_CTRL 0x4BC -#define FLD_VBI_PASS_MD 0x00200000 -#define FLD_VBI_SETUP_DIS 0x00100000 -#define FLD_PASS_LINE_CTRL 0x000FFFFF +#define VBI_PASS_CTRL 0x4BC +#define FLD_VBI_PASS_MD 0x00200000 +#define FLD_VBI_SETUP_DIS 0x00100000 +#define FLD_PASS_LINE_CTRL 0x000FFFFF /*****************************************************************************/ /* Cx231xx redefine */ -#define VCR_DET_CTRL 0x4c0 -#define FLD_EN_FIELD_PHASE_DET 0x80000000 -#define FLD_EN_HEAD_SW_DET 0x40000000 -#define FLD_FIELD_PHASE_LENGTH 0x01FF0000 +#define VCR_DET_CTRL 0x4c0 +#define FLD_EN_FIELD_PHASE_DET 0x80000000 +#define FLD_EN_HEAD_SW_DET 0x40000000 +#define FLD_FIELD_PHASE_LENGTH 0x01FF0000 /* Reserved [29:25] */ -#define FLD_FIELD_PHASE_DELAY 0x0000FF00 -#define FLD_FIELD_PHASE_LIMIT 0x000000F0 -#define FLD_HEAD_SW_DET_LIMIT 0x0000000F - +#define FLD_FIELD_PHASE_DELAY 0x0000FF00 +#define FLD_FIELD_PHASE_LIMIT 0x000000F0 +#define FLD_HEAD_SW_DET_LIMIT 0x0000000F /*****************************************************************************/ -#define DL_CTL 0x800 -#define DL_CTL_ADDRESS_LOW 0x800 /* Byte 1 in DL_CTL */ -#define DL_CTL_ADDRESS_HIGH 0x801 /* Byte 2 in DL_CTL */ -#define DL_CTL_DATA 0x802 /* Byte 3 in DL_CTL */ -#define DL_CTL_CONTROL 0x803 /* Byte 4 in DL_CTL */ +#define DL_CTL 0x800 +#define DL_CTL_ADDRESS_LOW 0x800 /* Byte 1 in DL_CTL */ +#define DL_CTL_ADDRESS_HIGH 0x801 /* Byte 2 in DL_CTL */ +#define DL_CTL_DATA 0x802 /* Byte 3 in DL_CTL */ +#define DL_CTL_CONTROL 0x803 /* Byte 4 in DL_CTL */ /* Reserved [31:5] */ -#define FLD_START_8051 0x10000000 -#define FLD_DL_ENABLE 0x08000000 -#define FLD_DL_AUTO_INC 0x04000000 -#define FLD_DL_MAP 0x03000000 - -/*****************************************************************************/ -#define STD_DET_STATUS 0x804 -#define FLD_SPARE_STATUS1 0xFF000000 -#define FLD_SPARE_STATUS0 0x00FF0000 -#define FLD_MOD_DET_STATUS1 0x0000FF00 -#define FLD_MOD_DET_STATUS0 0x000000FF - -/*****************************************************************************/ -#define AUD_BUILD_NUM 0x806 -#define AUD_VER_NUM 0x807 -#define STD_DET_CTL 0x808 -#define STD_DET_CTL_AUD_CTL 0x808 /* Byte 1 in STD_DET_CTL */ -#define STD_DET_CTL_PREF_MODE 0x809 /* Byte 2 in STD_DET_CTL */ -#define FLD_SPARE_CTL0 0xFF000000 -#define FLD_DIS_DBX 0x00800000 -#define FLD_DIS_BTSC 0x00400000 -#define FLD_DIS_NICAM_A2 0x00200000 -#define FLD_VIDEO_PRESENT 0x00100000 -#define FLD_DW8051_VIDEO_FORMAT 0x000F0000 -#define FLD_PREF_DEC_MODE 0x0000FF00 -#define FLD_AUD_CONFIG 0x000000FF - -/*****************************************************************************/ -#define DW8051_INT 0x80C -#define FLD_VIDEO_PRESENT_CHANGE 0x80000000 -#define FLD_VIDEO_CHANGE 0x40000000 -#define FLD_RDS_READY 0x20000000 -#define FLD_AC97_INT 0x10000000 -#define FLD_NICAM_BIT_ERROR_TOO_HIGH 0x08000000 -#define FLD_NICAM_LOCK 0x04000000 -#define FLD_NICAM_UNLOCK 0x02000000 -#define FLD_DFT4_TH_CMP 0x01000000 +#define FLD_START_8051 0x10000000 +#define FLD_DL_ENABLE 0x08000000 +#define FLD_DL_AUTO_INC 0x04000000 +#define FLD_DL_MAP 0x03000000 + +/*****************************************************************************/ +#define STD_DET_STATUS 0x804 +#define FLD_SPARE_STATUS1 0xFF000000 +#define FLD_SPARE_STATUS0 0x00FF0000 +#define FLD_MOD_DET_STATUS1 0x0000FF00 +#define FLD_MOD_DET_STATUS0 0x000000FF + +/*****************************************************************************/ +#define AUD_BUILD_NUM 0x806 +#define AUD_VER_NUM 0x807 +#define STD_DET_CTL 0x808 +#define STD_DET_CTL_AUD_CTL 0x808 /* Byte 1 in STD_DET_CTL */ +#define STD_DET_CTL_PREF_MODE 0x809 /* Byte 2 in STD_DET_CTL */ +#define FLD_SPARE_CTL0 0xFF000000 +#define FLD_DIS_DBX 0x00800000 +#define FLD_DIS_BTSC 0x00400000 +#define FLD_DIS_NICAM_A2 0x00200000 +#define FLD_VIDEO_PRESENT 0x00100000 +#define FLD_DW8051_VIDEO_FORMAT 0x000F0000 +#define FLD_PREF_DEC_MODE 0x0000FF00 +#define FLD_AUD_CONFIG 0x000000FF + +/*****************************************************************************/ +#define DW8051_INT 0x80C +#define FLD_VIDEO_PRESENT_CHANGE 0x80000000 +#define FLD_VIDEO_CHANGE 0x40000000 +#define FLD_RDS_READY 0x20000000 +#define FLD_AC97_INT 0x10000000 +#define FLD_NICAM_BIT_ERROR_TOO_HIGH 0x08000000 +#define FLD_NICAM_LOCK 0x04000000 +#define FLD_NICAM_UNLOCK 0x02000000 +#define FLD_DFT4_TH_CMP 0x01000000 /* Reserved [23:22] */ -#define FLD_LOCK_IND_INT 0x00200000 -#define FLD_DFT3_TH_CMP 0x00100000 -#define FLD_DFT2_TH_CMP 0x00080000 -#define FLD_DFT1_TH_CMP 0x00040000 -#define FLD_FM2_DFT_TH_CMP 0x00020000 -#define FLD_FM1_DFT_TH_CMP 0x00010000 -#define FLD_VIDEO_PRESENT_EN 0x00008000 -#define FLD_VIDEO_CHANGE_EN 0x00004000 -#define FLD_RDS_READY_EN 0x00002000 -#define FLD_AC97_INT_EN 0x00001000 -#define FLD_NICAM_BIT_ERROR_TOO_HIGH_EN 0x00000800 -#define FLD_NICAM_LOCK_EN 0x00000400 -#define FLD_NICAM_UNLOCK_EN 0x00000200 -#define FLD_DFT4_TH_CMP_EN 0x00000100 +#define FLD_LOCK_IND_INT 0x00200000 +#define FLD_DFT3_TH_CMP 0x00100000 +#define FLD_DFT2_TH_CMP 0x00080000 +#define FLD_DFT1_TH_CMP 0x00040000 +#define FLD_FM2_DFT_TH_CMP 0x00020000 +#define FLD_FM1_DFT_TH_CMP 0x00010000 +#define FLD_VIDEO_PRESENT_EN 0x00008000 +#define FLD_VIDEO_CHANGE_EN 0x00004000 +#define FLD_RDS_READY_EN 0x00002000 +#define FLD_AC97_INT_EN 0x00001000 +#define FLD_NICAM_BIT_ERROR_TOO_HIGH_EN 0x00000800 +#define FLD_NICAM_LOCK_EN 0x00000400 +#define FLD_NICAM_UNLOCK_EN 0x00000200 +#define FLD_DFT4_TH_CMP_EN 0x00000100 /* Reserved [7] */ -#define FLD_DW8051_INT6_CTL1 0x00000040 -#define FLD_DW8051_INT5_CTL1 0x00000020 -#define FLD_DW8051_INT4_CTL1 0x00000010 -#define FLD_DW8051_INT3_CTL1 0x00000008 -#define FLD_DW8051_INT2_CTL1 0x00000004 -#define FLD_DW8051_INT1_CTL1 0x00000002 -#define FLD_DW8051_INT0_CTL1 0x00000001 - -/*****************************************************************************/ -#define GENERAL_CTL 0x810 -#define FLD_RDS_INT 0x80000000 -#define FLD_NBER_INT 0x40000000 -#define FLD_NLL_INT 0x20000000 -#define FLD_IFL_INT 0x10000000 -#define FLD_FDL_INT 0x08000000 -#define FLD_AFC_INT 0x04000000 -#define FLD_AMC_INT 0x02000000 -#define FLD_AC97_INT_CTL 0x01000000 -#define FLD_RDS_INT_DIS 0x00800000 -#define FLD_NBER_INT_DIS 0x00400000 -#define FLD_NLL_INT_DIS 0x00200000 -#define FLD_IFL_INT_DIS 0x00100000 -#define FLD_FDL_INT_DIS 0x00080000 -#define FLD_FC_INT_DIS 0x00040000 -#define FLD_AMC_INT_DIS 0x00020000 -#define FLD_AC97_INT_DIS 0x00010000 -#define FLD_REV_NUM 0x0000FF00 +#define FLD_DW8051_INT6_CTL1 0x00000040 +#define FLD_DW8051_INT5_CTL1 0x00000020 +#define FLD_DW8051_INT4_CTL1 0x00000010 +#define FLD_DW8051_INT3_CTL1 0x00000008 +#define FLD_DW8051_INT2_CTL1 0x00000004 +#define FLD_DW8051_INT1_CTL1 0x00000002 +#define FLD_DW8051_INT0_CTL1 0x00000001 + +/*****************************************************************************/ +#define GENERAL_CTL 0x810 +#define FLD_RDS_INT 0x80000000 +#define FLD_NBER_INT 0x40000000 +#define FLD_NLL_INT 0x20000000 +#define FLD_IFL_INT 0x10000000 +#define FLD_FDL_INT 0x08000000 +#define FLD_AFC_INT 0x04000000 +#define FLD_AMC_INT 0x02000000 +#define FLD_AC97_INT_CTL 0x01000000 +#define FLD_RDS_INT_DIS 0x00800000 +#define FLD_NBER_INT_DIS 0x00400000 +#define FLD_NLL_INT_DIS 0x00200000 +#define FLD_IFL_INT_DIS 0x00100000 +#define FLD_FDL_INT_DIS 0x00080000 +#define FLD_FC_INT_DIS 0x00040000 +#define FLD_AMC_INT_DIS 0x00020000 +#define FLD_AC97_INT_DIS 0x00010000 +#define FLD_REV_NUM 0x0000FF00 /* Reserved [7:5] */ -#define FLD_DBX_SOFT_RESET_REG 0x00000010 -#define FLD_AD_SOFT_RESET_REG 0x00000008 -#define FLD_SRC_SOFT_RESET_REG 0x00000004 -#define FLD_CDMOD_SOFT_RESET 0x00000002 -#define FLD_8051_SOFT_RESET 0x00000001 +#define FLD_DBX_SOFT_RESET_REG 0x00000010 +#define FLD_AD_SOFT_RESET_REG 0x00000008 +#define FLD_SRC_SOFT_RESET_REG 0x00000004 +#define FLD_CDMOD_SOFT_RESET 0x00000002 +#define FLD_8051_SOFT_RESET 0x00000001 /*****************************************************************************/ -#define AAGC_CTL 0x814 -#define FLD_AFE_12DB_EN 0x80000000 -#define FLD_AAGC_DEFAULT_EN 0x40000000 -#define FLD_AAGC_DEFAULT 0x3F000000 +#define AAGC_CTL 0x814 +#define FLD_AFE_12DB_EN 0x80000000 +#define FLD_AAGC_DEFAULT_EN 0x40000000 +#define FLD_AAGC_DEFAULT 0x3F000000 /* Reserved [23] */ -#define FLD_AAGC_GAIN 0x00600000 -#define FLD_AAGC_TH 0x001F0000 +#define FLD_AAGC_GAIN 0x00600000 +#define FLD_AAGC_TH 0x001F0000 /* Reserved [15:14] */ -#define FLD_AAGC_HYST2 0x00003F00 +#define FLD_AAGC_HYST2 0x00003F00 /* Reserved [7:6] */ -#define FLD_AAGC_HYST1 0x0000003F +#define FLD_AAGC_HYST1 0x0000003F /*****************************************************************************/ -#define IF_SRC_CTL 0x818 -#define FLD_DBX_BYPASS 0x80000000 +#define IF_SRC_CTL 0x818 +#define FLD_DBX_BYPASS 0x80000000 /* Reserved [30:25] */ -#define FLD_IF_SRC_MODE 0x01000000 +#define FLD_IF_SRC_MODE 0x01000000 /* Reserved [23:18] */ -#define FLD_IF_SRC_PHASE_INC 0x0001FFFF +#define FLD_IF_SRC_PHASE_INC 0x0001FFFF /*****************************************************************************/ -#define ANALOG_DEMOD_CTL 0x81C -#define FLD_ROT1_PHACC_PROG 0xFFFF0000 +#define ANALOG_DEMOD_CTL 0x81C +#define FLD_ROT1_PHACC_PROG 0xFFFF0000 /* Reserved [15] */ -#define FLD_FM1_DELAY_FIX 0x00007000 -#define FLD_PDF4_SHIFT 0x00000C00 -#define FLD_PDF3_SHIFT 0x00000300 -#define FLD_PDF2_SHIFT 0x000000C0 -#define FLD_PDF1_SHIFT 0x00000030 -#define FLD_FMBYPASS_MODE2 0x00000008 -#define FLD_FMBYPASS_MODE1 0x00000004 -#define FLD_NICAM_MODE 0x00000002 -#define FLD_BTSC_FMRADIO_MODE 0x00000001 - -/*****************************************************************************/ -#define ROT_FREQ_CTL 0x820 -#define FLD_ROT3_PHACC_PROG 0xFFFF0000 -#define FLD_ROT2_PHACC_PROG 0x0000FFFF - -/*****************************************************************************/ -#define FM_CTL 0x824 -#define FLD_FM2_DC_FB_SHIFT 0xF0000000 -#define FLD_FM2_DC_INT_SHIFT 0x0F000000 -#define FLD_FM2_AFC_RESET 0x00800000 -#define FLD_FM2_DC_PASS_IN 0x00400000 -#define FLD_FM2_DAGC_SHIFT 0x00380000 -#define FLD_FM2_CORDIC_SHIFT 0x00070000 -#define FLD_FM1_DC_FB_SHIFT 0x0000F000 -#define FLD_FM1_DC_INT_SHIFT 0x00000F00 -#define FLD_FM1_AFC_RESET 0x00000080 -#define FLD_FM1_DC_PASS_IN 0x00000040 -#define FLD_FM1_DAGC_SHIFT 0x00000038 -#define FLD_FM1_CORDIC_SHIFT 0x00000007 - -/*****************************************************************************/ -#define LPF_PDF_CTL 0x828 +#define FLD_FM1_DELAY_FIX 0x00007000 +#define FLD_PDF4_SHIFT 0x00000C00 +#define FLD_PDF3_SHIFT 0x00000300 +#define FLD_PDF2_SHIFT 0x000000C0 +#define FLD_PDF1_SHIFT 0x00000030 +#define FLD_FMBYPASS_MODE2 0x00000008 +#define FLD_FMBYPASS_MODE1 0x00000004 +#define FLD_NICAM_MODE 0x00000002 +#define FLD_BTSC_FMRADIO_MODE 0x00000001 + +/*****************************************************************************/ +#define ROT_FREQ_CTL 0x820 +#define FLD_ROT3_PHACC_PROG 0xFFFF0000 +#define FLD_ROT2_PHACC_PROG 0x0000FFFF + +/*****************************************************************************/ +#define FM_CTL 0x824 +#define FLD_FM2_DC_FB_SHIFT 0xF0000000 +#define FLD_FM2_DC_INT_SHIFT 0x0F000000 +#define FLD_FM2_AFC_RESET 0x00800000 +#define FLD_FM2_DC_PASS_IN 0x00400000 +#define FLD_FM2_DAGC_SHIFT 0x00380000 +#define FLD_FM2_CORDIC_SHIFT 0x00070000 +#define FLD_FM1_DC_FB_SHIFT 0x0000F000 +#define FLD_FM1_DC_INT_SHIFT 0x00000F00 +#define FLD_FM1_AFC_RESET 0x00000080 +#define FLD_FM1_DC_PASS_IN 0x00000040 +#define FLD_FM1_DAGC_SHIFT 0x00000038 +#define FLD_FM1_CORDIC_SHIFT 0x00000007 + +/*****************************************************************************/ +#define LPF_PDF_CTL 0x828 /* Reserved [31:30] */ -#define FLD_LPF32_SHIFT1 0x30000000 -#define FLD_LPF32_SHIFT2 0x0C000000 -#define FLD_LPF160_SHIFTA 0x03000000 -#define FLD_LPF160_SHIFTB 0x00C00000 -#define FLD_LPF160_SHIFTC 0x00300000 -#define FLD_LPF32_COEF_SEL2 0x000C0000 -#define FLD_LPF32_COEF_SEL1 0x00030000 -#define FLD_LPF160_COEF_SELC 0x0000C000 -#define FLD_LPF160_COEF_SELB 0x00003000 -#define FLD_LPF160_COEF_SELA 0x00000C00 -#define FLD_LPF160_IN_EN_REG 0x00000300 -#define FLD_PDF4_PDF_SEL 0x000000C0 -#define FLD_PDF3_PDF_SEL 0x00000030 -#define FLD_PDF2_PDF_SEL 0x0000000C -#define FLD_PDF1_PDF_SEL 0x00000003 - -/*****************************************************************************/ -#define DFT1_CTL1 0x82C -#define FLD_DFT1_DWELL 0xFFFF0000 -#define FLD_DFT1_FREQ 0x0000FFFF - -/*****************************************************************************/ -#define DFT1_CTL2 0x830 -#define FLD_DFT1_THRESHOLD 0xFFFFFF00 -#define FLD_DFT1_CMP_CTL 0x00000080 -#define FLD_DFT1_AVG 0x00000070 +#define FLD_LPF32_SHIFT1 0x30000000 +#define FLD_LPF32_SHIFT2 0x0C000000 +#define FLD_LPF160_SHIFTA 0x03000000 +#define FLD_LPF160_SHIFTB 0x00C00000 +#define FLD_LPF160_SHIFTC 0x00300000 +#define FLD_LPF32_COEF_SEL2 0x000C0000 +#define FLD_LPF32_COEF_SEL1 0x00030000 +#define FLD_LPF160_COEF_SELC 0x0000C000 +#define FLD_LPF160_COEF_SELB 0x00003000 +#define FLD_LPF160_COEF_SELA 0x00000C00 +#define FLD_LPF160_IN_EN_REG 0x00000300 +#define FLD_PDF4_PDF_SEL 0x000000C0 +#define FLD_PDF3_PDF_SEL 0x00000030 +#define FLD_PDF2_PDF_SEL 0x0000000C +#define FLD_PDF1_PDF_SEL 0x00000003 + +/*****************************************************************************/ +#define DFT1_CTL1 0x82C +#define FLD_DFT1_DWELL 0xFFFF0000 +#define FLD_DFT1_FREQ 0x0000FFFF + +/*****************************************************************************/ +#define DFT1_CTL2 0x830 +#define FLD_DFT1_THRESHOLD 0xFFFFFF00 +#define FLD_DFT1_CMP_CTL 0x00000080 +#define FLD_DFT1_AVG 0x00000070 /* Reserved [3:1] */ -#define FLD_DFT1_START 0x00000001 +#define FLD_DFT1_START 0x00000001 /*****************************************************************************/ -#define DFT1_STATUS 0x834 -#define FLD_DFT1_DONE 0x80000000 -#define FLD_DFT1_TH_CMP_STAT 0x40000000 -#define FLD_DFT1_RESULT 0x3FFFFFFF +#define DFT1_STATUS 0x834 +#define FLD_DFT1_DONE 0x80000000 +#define FLD_DFT1_TH_CMP_STAT 0x40000000 +#define FLD_DFT1_RESULT 0x3FFFFFFF /*****************************************************************************/ -#define DFT2_CTL1 0x838 -#define FLD_DFT2_DWELL 0xFFFF0000 -#define FLD_DFT2_FREQ 0x0000FFFF +#define DFT2_CTL1 0x838 +#define FLD_DFT2_DWELL 0xFFFF0000 +#define FLD_DFT2_FREQ 0x0000FFFF /*****************************************************************************/ -#define DFT2_CTL2 0x83C -#define FLD_DFT2_THRESHOLD 0xFFFFFF00 -#define FLD_DFT2_CMP_CTL 0x00000080 -#define FLD_DFT2_AVG 0x00000070 +#define DFT2_CTL2 0x83C +#define FLD_DFT2_THRESHOLD 0xFFFFFF00 +#define FLD_DFT2_CMP_CTL 0x00000080 +#define FLD_DFT2_AVG 0x00000070 /* Reserved [3:1] */ -#define FLD_DFT2_START 0x00000001 +#define FLD_DFT2_START 0x00000001 /*****************************************************************************/ -#define DFT2_STATUS 0x840 -#define FLD_DFT2_DONE 0x80000000 -#define FLD_DFT2_TH_CMP_STAT 0x40000000 -#define FLD_DFT2_RESULT 0x3FFFFFFF +#define DFT2_STATUS 0x840 +#define FLD_DFT2_DONE 0x80000000 +#define FLD_DFT2_TH_CMP_STAT 0x40000000 +#define FLD_DFT2_RESULT 0x3FFFFFFF /*****************************************************************************/ -#define DFT3_CTL1 0x844 -#define FLD_DFT3_DWELL 0xFFFF0000 -#define FLD_DFT3_FREQ 0x0000FFFF +#define DFT3_CTL1 0x844 +#define FLD_DFT3_DWELL 0xFFFF0000 +#define FLD_DFT3_FREQ 0x0000FFFF /*****************************************************************************/ -#define DFT3_CTL2 0x848 -#define FLD_DFT3_THRESHOLD 0xFFFFFF00 -#define FLD_DFT3_CMP_CTL 0x00000080 -#define FLD_DFT3_AVG 0x00000070 +#define DFT3_CTL2 0x848 +#define FLD_DFT3_THRESHOLD 0xFFFFFF00 +#define FLD_DFT3_CMP_CTL 0x00000080 +#define FLD_DFT3_AVG 0x00000070 /* Reserved [3:1] */ -#define FLD_DFT3_START 0x00000001 +#define FLD_DFT3_START 0x00000001 /*****************************************************************************/ -#define DFT3_STATUS 0x84C -#define FLD_DFT3_DONE 0x80000000 -#define FLD_DFT3_TH_CMP_STAT 0x40000000 -#define FLD_DFT3_RESULT 0x3FFFFFFF +#define DFT3_STATUS 0x84C +#define FLD_DFT3_DONE 0x80000000 +#define FLD_DFT3_TH_CMP_STAT 0x40000000 +#define FLD_DFT3_RESULT 0x3FFFFFFF /*****************************************************************************/ -#define DFT4_CTL1 0x850 -#define FLD_DFT4_DWELL 0xFFFF0000 -#define FLD_DFT4_FREQ 0x0000FFFF +#define DFT4_CTL1 0x850 +#define FLD_DFT4_DWELL 0xFFFF0000 +#define FLD_DFT4_FREQ 0x0000FFFF /*****************************************************************************/ -#define DFT4_CTL2 0x854 -#define FLD_DFT4_THRESHOLD 0xFFFFFF00 -#define FLD_DFT4_CMP_CTL 0x00000080 -#define FLD_DFT4_AVG 0x00000070 +#define DFT4_CTL2 0x854 +#define FLD_DFT4_THRESHOLD 0xFFFFFF00 +#define FLD_DFT4_CMP_CTL 0x00000080 +#define FLD_DFT4_AVG 0x00000070 /* Reserved [3:1] */ -#define FLD_DFT4_START 0x00000001 +#define FLD_DFT4_START 0x00000001 /*****************************************************************************/ -#define DFT4_STATUS 0x858 -#define FLD_DFT4_DONE 0x80000000 -#define FLD_DFT4_TH_CMP_STAT 0x40000000 -#define FLD_DFT4_RESULT 0x3FFFFFFF +#define DFT4_STATUS 0x858 +#define FLD_DFT4_DONE 0x80000000 +#define FLD_DFT4_TH_CMP_STAT 0x40000000 +#define FLD_DFT4_RESULT 0x3FFFFFFF /*****************************************************************************/ -#define AM_MTS_DET 0x85C -#define FLD_AM_MTS_MODE 0x80000000 +#define AM_MTS_DET 0x85C +#define FLD_AM_MTS_MODE 0x80000000 /* Reserved [30:26] */ -#define FLD_AM_SUB 0x02000000 -#define FLD_AM_GAIN_EN 0x01000000 +#define FLD_AM_SUB 0x02000000 +#define FLD_AM_GAIN_EN 0x01000000 /* Reserved [23:16] */ -#define FLD_AMMTS_GAIN_SCALE 0x0000E000 -#define FLD_MTS_PDF_SHIFT 0x00001800 -#define FLD_AM_REG_GAIN 0x00000700 -#define FLD_AGC_REF 0x000000FF +#define FLD_AMMTS_GAIN_SCALE 0x0000E000 +#define FLD_MTS_PDF_SHIFT 0x00001800 +#define FLD_AM_REG_GAIN 0x00000700 +#define FLD_AGC_REF 0x000000FF /*****************************************************************************/ -#define ANALOG_MUX_CTL 0x860 +#define ANALOG_MUX_CTL 0x860 /* Reserved [31:29] */ -#define FLD_MUX21_SEL 0x10000000 -#define FLD_MUX20_SEL 0x08000000 -#define FLD_MUX19_SEL 0x04000000 -#define FLD_MUX18_SEL 0x02000000 -#define FLD_MUX17_SEL 0x01000000 -#define FLD_MUX16_SEL 0x00800000 -#define FLD_MUX15_SEL 0x00400000 -#define FLD_MUX14_SEL 0x00300000 -#define FLD_MUX13_SEL 0x000C0000 -#define FLD_MUX12_SEL 0x00020000 -#define FLD_MUX11_SEL 0x00018000 -#define FLD_MUX10_SEL 0x00004000 -#define FLD_MUX9_SEL 0x00002000 -#define FLD_MUX8_SEL 0x00001000 -#define FLD_MUX7_SEL 0x00000800 -#define FLD_MUX6_SEL 0x00000600 -#define FLD_MUX5_SEL 0x00000100 -#define FLD_MUX4_SEL 0x000000C0 -#define FLD_MUX3_SEL 0x00000030 -#define FLD_MUX2_SEL 0x0000000C -#define FLD_MUX1_SEL 0x00000003 +#define FLD_MUX21_SEL 0x10000000 +#define FLD_MUX20_SEL 0x08000000 +#define FLD_MUX19_SEL 0x04000000 +#define FLD_MUX18_SEL 0x02000000 +#define FLD_MUX17_SEL 0x01000000 +#define FLD_MUX16_SEL 0x00800000 +#define FLD_MUX15_SEL 0x00400000 +#define FLD_MUX14_SEL 0x00300000 +#define FLD_MUX13_SEL 0x000C0000 +#define FLD_MUX12_SEL 0x00020000 +#define FLD_MUX11_SEL 0x00018000 +#define FLD_MUX10_SEL 0x00004000 +#define FLD_MUX9_SEL 0x00002000 +#define FLD_MUX8_SEL 0x00001000 +#define FLD_MUX7_SEL 0x00000800 +#define FLD_MUX6_SEL 0x00000600 +#define FLD_MUX5_SEL 0x00000100 +#define FLD_MUX4_SEL 0x000000C0 +#define FLD_MUX3_SEL 0x00000030 +#define FLD_MUX2_SEL 0x0000000C +#define FLD_MUX1_SEL 0x00000003 /*****************************************************************************/ /* Cx231xx redefine */ -#define DPLL_CTRL1 0x864 -#define DIG_PLL_CTL1 0x864 +#define DPLL_CTRL1 0x864 +#define DIG_PLL_CTL1 0x864 -#define FLD_PLL_STATUS 0x07000000 -#define FLD_BANDWIDTH_SELECT 0x00030000 -#define FLD_PLL_SHIFT_REG 0x00007000 -#define FLD_PHASE_SHIFT 0x000007FF +#define FLD_PLL_STATUS 0x07000000 +#define FLD_BANDWIDTH_SELECT 0x00030000 +#define FLD_PLL_SHIFT_REG 0x00007000 +#define FLD_PHASE_SHIFT 0x000007FF /*****************************************************************************/ /* Cx231xx redefine */ -#define DPLL_CTRL2 0x868 -#define DIG_PLL_CTL2 0x868 -#define FLD_PLL_UNLOCK_THR 0xFF000000 -#define FLD_PLL_LOCK_THR 0x00FF0000 +#define DPLL_CTRL2 0x868 +#define DIG_PLL_CTL2 0x868 +#define FLD_PLL_UNLOCK_THR 0xFF000000 +#define FLD_PLL_LOCK_THR 0x00FF0000 /* Reserved [15:8] */ -#define FLD_AM_PDF_SEL2 0x000000C0 -#define FLD_AM_PDF_SEL1 0x00000030 -#define FLD_DPLL_FSM_CTRL 0x0000000C +#define FLD_AM_PDF_SEL2 0x000000C0 +#define FLD_AM_PDF_SEL1 0x00000030 +#define FLD_DPLL_FSM_CTRL 0x0000000C /* Reserved [1] */ -#define FLD_PLL_PILOT_DET 0x00000001 +#define FLD_PLL_PILOT_DET 0x00000001 /*****************************************************************************/ /* Cx231xx redefine */ -#define DPLL_CTRL3 0x86C -#define DIG_PLL_CTL3 0x86C -#define FLD_DISABLE_LOOP 0x01000000 -#define FLD_A1_DS1_SEL 0x000C0000 -#define FLD_A1_DS2_SEL 0x00030000 -#define FLD_A1_KI 0x0000FF00 -#define FLD_A1_KD 0x000000FF +#define DPLL_CTRL3 0x86C +#define DIG_PLL_CTL3 0x86C +#define FLD_DISABLE_LOOP 0x01000000 +#define FLD_A1_DS1_SEL 0x000C0000 +#define FLD_A1_DS2_SEL 0x00030000 +#define FLD_A1_KI 0x0000FF00 +#define FLD_A1_KD 0x000000FF /*****************************************************************************/ /* Cx231xx redefine */ -#define DPLL_CTRL4 0x870 -#define DIG_PLL_CTL4 0x870 -#define FLD_A2_DS1_SEL 0x000C0000 -#define FLD_A2_DS2_SEL 0x00030000 -#define FLD_A2_KI 0x0000FF00 -#define FLD_A2_KD 0x000000FF +#define DPLL_CTRL4 0x870 +#define DIG_PLL_CTL4 0x870 +#define FLD_A2_DS1_SEL 0x000C0000 +#define FLD_A2_DS2_SEL 0x00030000 +#define FLD_A2_KI 0x0000FF00 +#define FLD_A2_KD 0x000000FF /*****************************************************************************/ /* Cx231xx redefine */ -#define DPLL_CTRL5 0x874 -#define DIG_PLL_CTL5 0x874 -#define FLD_TRK_DS1_SEL 0x000C0000 -#define FLD_TRK_DS2_SEL 0x00030000 -#define FLD_TRK_KI 0x0000FF00 -#define FLD_TRK_KD 0x000000FF +#define DPLL_CTRL5 0x874 +#define DIG_PLL_CTL5 0x874 +#define FLD_TRK_DS1_SEL 0x000C0000 +#define FLD_TRK_DS2_SEL 0x00030000 +#define FLD_TRK_KI 0x0000FF00 +#define FLD_TRK_KD 0x000000FF /*****************************************************************************/ -#define DEEMPH_GAIN_CTL 0x878 -#define FLD_DEEMPH2_GAIN 0xFFFF0000 -#define FLD_DEEMPH1_GAIN 0x0000FFFF +#define DEEMPH_GAIN_CTL 0x878 +#define FLD_DEEMPH2_GAIN 0xFFFF0000 +#define FLD_DEEMPH1_GAIN 0x0000FFFF /*****************************************************************************/ /* Cx231xx redefine */ -#define DEEMPH_COEFF1 0x87C -#define DEEMPH_COEF1 0x87C -#define FLD_DEEMPH_B0 0xFFFF0000 -#define FLD_DEEMPH_A0 0x0000FFFF +#define DEEMPH_COEFF1 0x87C +#define DEEMPH_COEF1 0x87C +#define FLD_DEEMPH_B0 0xFFFF0000 +#define FLD_DEEMPH_A0 0x0000FFFF /*****************************************************************************/ /* Cx231xx redefine */ -#define DEEMPH_COEFF2 0x880 -#define DEEMPH_COEF2 0x880 -#define FLD_DEEMPH_B1 0xFFFF0000 -#define FLD_DEEMPH_A1 0x0000FFFF +#define DEEMPH_COEFF2 0x880 +#define DEEMPH_COEF2 0x880 +#define FLD_DEEMPH_B1 0xFFFF0000 +#define FLD_DEEMPH_A1 0x0000FFFF /*****************************************************************************/ -#define DBX1_CTL1 0x884 -#define FLD_DBX1_WBE_GAIN 0xFFFF0000 -#define FLD_DBX1_IN_GAIN 0x0000FFFF +#define DBX1_CTL1 0x884 +#define FLD_DBX1_WBE_GAIN 0xFFFF0000 +#define FLD_DBX1_IN_GAIN 0x0000FFFF /*****************************************************************************/ -#define DBX1_CTL2 0x888 -#define FLD_DBX1_SE_BYPASS 0xFFFF0000 -#define FLD_DBX1_SE_GAIN 0x0000FFFF +#define DBX1_CTL2 0x888 +#define FLD_DBX1_SE_BYPASS 0xFFFF0000 +#define FLD_DBX1_SE_GAIN 0x0000FFFF /*****************************************************************************/ -#define DBX1_RMS_SE 0x88C -#define FLD_DBX1_RMS_WBE 0xFFFF0000 -#define FLD_DBX1_RMS_SE_FLD 0x0000FFFF +#define DBX1_RMS_SE 0x88C +#define FLD_DBX1_RMS_WBE 0xFFFF0000 +#define FLD_DBX1_RMS_SE_FLD 0x0000FFFF /*****************************************************************************/ -#define DBX2_CTL1 0x890 -#define FLD_DBX2_WBE_GAIN 0xFFFF0000 -#define FLD_DBX2_IN_GAIN 0x0000FFFF +#define DBX2_CTL1 0x890 +#define FLD_DBX2_WBE_GAIN 0xFFFF0000 +#define FLD_DBX2_IN_GAIN 0x0000FFFF /*****************************************************************************/ -#define DBX2_CTL2 0x894 -#define FLD_DBX2_SE_BYPASS 0xFFFF0000 -#define FLD_DBX2_SE_GAIN 0x0000FFFF +#define DBX2_CTL2 0x894 +#define FLD_DBX2_SE_BYPASS 0xFFFF0000 +#define FLD_DBX2_SE_GAIN 0x0000FFFF /*****************************************************************************/ -#define DBX2_RMS_SE 0x898 -#define FLD_DBX2_RMS_WBE 0xFFFF0000 -#define FLD_DBX2_RMS_SE_FLD 0x0000FFFF +#define DBX2_RMS_SE 0x898 +#define FLD_DBX2_RMS_WBE 0xFFFF0000 +#define FLD_DBX2_RMS_SE_FLD 0x0000FFFF /*****************************************************************************/ -#define AM_FM_DIFF 0x89C +#define AM_FM_DIFF 0x89C /* Reserved [31] */ -#define FLD_FM_DIFF_OUT 0x7FFF0000 +#define FLD_FM_DIFF_OUT 0x7FFF0000 /* Reserved [15] */ -#define FLD_AM_DIFF_OUT 0x00007FFF +#define FLD_AM_DIFF_OUT 0x00007FFF /*****************************************************************************/ -#define NICAM_FAW 0x8A0 -#define FLD_FAWDETWINEND 0xFC000000 -#define FLD_FAWDETWINSTR 0x03FF0000 +#define NICAM_FAW 0x8A0 +#define FLD_FAWDETWINEND 0xFC000000 +#define FLD_FAWDETWINSTR 0x03FF0000 /* Reserved [15:12] */ -#define FLD_FAWDETTHRSHLD3 0x00000F00 -#define FLD_FAWDETTHRSHLD2 0x000000F0 -#define FLD_FAWDETTHRSHLD1 0x0000000F +#define FLD_FAWDETTHRSHLD3 0x00000F00 +#define FLD_FAWDETTHRSHLD2 0x000000F0 +#define FLD_FAWDETTHRSHLD1 0x0000000F /*****************************************************************************/ /* Cx231xx redefine */ -#define DEEMPH_GAIN 0x8A4 -#define NICAM_DEEMPHGAIN 0x8A4 +#define DEEMPH_GAIN 0x8A4 +#define NICAM_DEEMPHGAIN 0x8A4 /* Reserved [31:18] */ -#define FLD_DEEMPHGAIN 0x0003FFFF +#define FLD_DEEMPHGAIN 0x0003FFFF /*****************************************************************************/ /* Cx231xx redefine */ -#define DEEMPH_NUMER1 0x8A8 -#define NICAM_DEEMPHNUMER1 0x8A8 +#define DEEMPH_NUMER1 0x8A8 +#define NICAM_DEEMPHNUMER1 0x8A8 /* Reserved [31:18] */ -#define FLD_DEEMPHNUMER1 0x0003FFFF +#define FLD_DEEMPHNUMER1 0x0003FFFF /*****************************************************************************/ /* Cx231xx redefine */ -#define DEEMPH_NUMER2 0x8AC -#define NICAM_DEEMPHNUMER2 0x8AC +#define DEEMPH_NUMER2 0x8AC +#define NICAM_DEEMPHNUMER2 0x8AC /* Reserved [31:18] */ -#define FLD_DEEMPHNUMER2 0x0003FFFF +#define FLD_DEEMPHNUMER2 0x0003FFFF /*****************************************************************************/ /* Cx231xx redefine */ -#define DEEMPH_DENOM1 0x8B0 -#define NICAM_DEEMPHDENOM1 0x8B0 +#define DEEMPH_DENOM1 0x8B0 +#define NICAM_DEEMPHDENOM1 0x8B0 /* Reserved [31:18] */ -#define FLD_DEEMPHDENOM1 0x0003FFFF +#define FLD_DEEMPHDENOM1 0x0003FFFF /*****************************************************************************/ /* Cx231xx redefine */ -#define DEEMPH_DENOM2 0x8B4 -#define NICAM_DEEMPHDENOM2 0x8B4 +#define DEEMPH_DENOM2 0x8B4 +#define NICAM_DEEMPHDENOM2 0x8B4 /* Reserved [31:18] */ -#define FLD_DEEMPHDENOM2 0x0003FFFF +#define FLD_DEEMPHDENOM2 0x0003FFFF /*****************************************************************************/ -#define NICAM_ERRLOG_CTL1 0x8B8 +#define NICAM_ERRLOG_CTL1 0x8B8 /* Reserved [31:28] */ -#define FLD_ERRINTRPTTHSHLD1 0x0FFF0000 +#define FLD_ERRINTRPTTHSHLD1 0x0FFF0000 /* Reserved [15:12] */ -#define FLD_ERRLOGPERIOD 0x00000FFF +#define FLD_ERRLOGPERIOD 0x00000FFF /*****************************************************************************/ -#define NICAM_ERRLOG_CTL2 0x8BC +#define NICAM_ERRLOG_CTL2 0x8BC /* Reserved [31:28] */ -#define FLD_ERRINTRPTTHSHLD3 0x0FFF0000 +#define FLD_ERRINTRPTTHSHLD3 0x0FFF0000 /* Reserved [15:12] */ -#define FLD_ERRINTRPTTHSHLD2 0x00000FFF +#define FLD_ERRINTRPTTHSHLD2 0x00000FFF /*****************************************************************************/ -#define NICAM_ERRLOG_STS1 0x8C0 +#define NICAM_ERRLOG_STS1 0x8C0 /* Reserved [31:28] */ -#define FLD_ERRLOG2 0x0FFF0000 +#define FLD_ERRLOG2 0x0FFF0000 /* Reserved [15:12] */ -#define FLD_ERRLOG1 0x00000FFF +#define FLD_ERRLOG1 0x00000FFF /*****************************************************************************/ -#define NICAM_ERRLOG_STS2 0x8C4 +#define NICAM_ERRLOG_STS2 0x8C4 /* Reserved [31:12] */ -#define FLD_ERRLOG3 0x00000FFF +#define FLD_ERRLOG3 0x00000FFF /*****************************************************************************/ -#define NICAM_STATUS 0x8C8 +#define NICAM_STATUS 0x8C8 /* Reserved [31:20] */ -#define FLD_NICAM_CIB 0x000C0000 -#define FLD_NICAM_LOCK_STAT 0x00020000 -#define FLD_NICAM_MUTE 0x00010000 -#define FLD_NICAMADDIT_DATA 0x0000FFE0 -#define FLD_NICAMCNTRL 0x0000001F +#define FLD_NICAM_CIB 0x000C0000 +#define FLD_NICAM_LOCK_STAT 0x00020000 +#define FLD_NICAM_MUTE 0x00010000 +#define FLD_NICAMADDIT_DATA 0x0000FFE0 +#define FLD_NICAMCNTRL 0x0000001F /*****************************************************************************/ -#define DEMATRIX_CTL 0x8CC -#define FLD_AC97_IN_SHIFT 0xF0000000 -#define FLD_I2S_IN_SHIFT 0x0F000000 -#define FLD_DEMATRIX_SEL_CTL 0x00FF0000 +#define DEMATRIX_CTL 0x8CC +#define FLD_AC97_IN_SHIFT 0xF0000000 +#define FLD_I2S_IN_SHIFT 0x0F000000 +#define FLD_DEMATRIX_SEL_CTL 0x00FF0000 /* Reserved [15:11] */ -#define FLD_DMTRX_BYPASS 0x00000400 -#define FLD_DEMATRIX_MODE 0x00000300 +#define FLD_DMTRX_BYPASS 0x00000400 +#define FLD_DEMATRIX_MODE 0x00000300 /* Reserved [7:6] */ -#define FLD_PH_DBX_SEL 0x00000020 -#define FLD_PH_CH_SEL 0x00000010 -#define FLD_PHASE_FIX 0x0000000F +#define FLD_PH_DBX_SEL 0x00000020 +#define FLD_PH_CH_SEL 0x00000010 +#define FLD_PHASE_FIX 0x0000000F /*****************************************************************************/ -#define PATH1_CTL1 0x8D0 +#define PATH1_CTL1 0x8D0 /* Reserved [31:29] */ -#define FLD_PATH1_MUTE_CTL 0x1F000000 +#define FLD_PATH1_MUTE_CTL 0x1F000000 /* Reserved [23:22] */ -#define FLD_PATH1_AVC_CG 0x00300000 -#define FLD_PATH1_AVC_RT 0x000F0000 -#define FLD_PATH1_AVC_AT 0x0000F000 -#define FLD_PATH1_AVC_STEREO 0x00000800 -#define FLD_PATH1_AVC_CR 0x00000700 -#define FLD_PATH1_AVC_RMS_CON 0x000000F0 -#define FLD_PATH1_SEL_CTL 0x0000000F +#define FLD_PATH1_AVC_CG 0x00300000 +#define FLD_PATH1_AVC_RT 0x000F0000 +#define FLD_PATH1_AVC_AT 0x0000F000 +#define FLD_PATH1_AVC_STEREO 0x00000800 +#define FLD_PATH1_AVC_CR 0x00000700 +#define FLD_PATH1_AVC_RMS_CON 0x000000F0 +#define FLD_PATH1_SEL_CTL 0x0000000F /*****************************************************************************/ -#define PATH1_VOL_CTL 0x8D4 -#define FLD_PATH1_AVC_THRESHOLD 0x7FFF0000 -#define FLD_PATH1_BAL_LEFT 0x00008000 -#define FLD_PATH1_BAL_LEVEL 0x00007F00 -#define FLD_PATH1_VOLUME 0x000000FF +#define PATH1_VOL_CTL 0x8D4 +#define FLD_PATH1_AVC_THRESHOLD 0x7FFF0000 +#define FLD_PATH1_BAL_LEFT 0x00008000 +#define FLD_PATH1_BAL_LEVEL 0x00007F00 +#define FLD_PATH1_VOLUME 0x000000FF /*****************************************************************************/ -#define PATH1_EQ_CTL 0x8D8 +#define PATH1_EQ_CTL 0x8D8 /* Reserved [31:30] */ -#define FLD_PATH1_EQ_TREBLE_VOL 0x3F000000 +#define FLD_PATH1_EQ_TREBLE_VOL 0x3F000000 /* Reserved [23:22] */ -#define FLD_PATH1_EQ_MID_VOL 0x003F0000 +#define FLD_PATH1_EQ_MID_VOL 0x003F0000 /* Reserved [15:14] */ -#define FLD_PATH1_EQ_BASS_VOL 0x00003F00 +#define FLD_PATH1_EQ_BASS_VOL 0x00003F00 /* Reserved [7:1] */ -#define FLD_PATH1_EQ_BAND_SEL 0x00000001 +#define FLD_PATH1_EQ_BAND_SEL 0x00000001 /*****************************************************************************/ -#define PATH1_SC_CTL 0x8DC -#define FLD_PATH1_SC_THRESHOLD 0x7FFF0000 -#define FLD_PATH1_SC_RT 0x0000F000 -#define FLD_PATH1_SC_AT 0x00000F00 -#define FLD_PATH1_SC_STEREO 0x00000080 -#define FLD_PATH1_SC_CR 0x00000070 -#define FLD_PATH1_SC_RMS_CON 0x0000000F +#define PATH1_SC_CTL 0x8DC +#define FLD_PATH1_SC_THRESHOLD 0x7FFF0000 +#define FLD_PATH1_SC_RT 0x0000F000 +#define FLD_PATH1_SC_AT 0x00000F00 +#define FLD_PATH1_SC_STEREO 0x00000080 +#define FLD_PATH1_SC_CR 0x00000070 +#define FLD_PATH1_SC_RMS_CON 0x0000000F /*****************************************************************************/ -#define PATH2_CTL1 0x8E0 +#define PATH2_CTL1 0x8E0 /* Reserved [31:26] */ -#define FLD_PATH2_MUTE_CTL 0x03000000 +#define FLD_PATH2_MUTE_CTL 0x03000000 /* Reserved [23:22] */ -#define FLD_PATH2_AVC_CG 0x00300000 -#define FLD_PATH2_AVC_RT 0x000F0000 -#define FLD_PATH2_AVC_AT 0x0000F000 -#define FLD_PATH2_AVC_STEREO 0x00000800 -#define FLD_PATH2_AVC_CR 0x00000700 -#define FLD_PATH2_AVC_RMS_CON 0x000000F0 -#define FLD_PATH2_SEL_CTL 0x0000000F +#define FLD_PATH2_AVC_CG 0x00300000 +#define FLD_PATH2_AVC_RT 0x000F0000 +#define FLD_PATH2_AVC_AT 0x0000F000 +#define FLD_PATH2_AVC_STEREO 0x00000800 +#define FLD_PATH2_AVC_CR 0x00000700 +#define FLD_PATH2_AVC_RMS_CON 0x000000F0 +#define FLD_PATH2_SEL_CTL 0x0000000F /*****************************************************************************/ -#define PATH2_VOL_CTL 0x8E4 -#define FLD_PATH2_AVC_THRESHOLD 0xFFFF0000 -#define FLD_PATH2_BAL_LEFT 0x00008000 -#define FLD_PATH2_BAL_LEVEL 0x00007F00 -#define FLD_PATH2_VOLUME 0x000000FF +#define PATH2_VOL_CTL 0x8E4 +#define FLD_PATH2_AVC_THRESHOLD 0xFFFF0000 +#define FLD_PATH2_BAL_LEFT 0x00008000 +#define FLD_PATH2_BAL_LEVEL 0x00007F00 +#define FLD_PATH2_VOLUME 0x000000FF /*****************************************************************************/ -#define PATH2_EQ_CTL 0x8E8 +#define PATH2_EQ_CTL 0x8E8 /* Reserved [31:30] */ -#define FLD_PATH2_EQ_TREBLE_VOL 0x3F000000 +#define FLD_PATH2_EQ_TREBLE_VOL 0x3F000000 /* Reserved [23:22] */ -#define FLD_PATH2_EQ_MID_VOL 0x003F0000 +#define FLD_PATH2_EQ_MID_VOL 0x003F0000 /* Reserved [15:14] */ -#define FLD_PATH2_EQ_BASS_VOL 0x00003F00 +#define FLD_PATH2_EQ_BASS_VOL 0x00003F00 /* Reserved [7:1] */ -#define FLD_PATH2_EQ_BAND_SEL 0x00000001 +#define FLD_PATH2_EQ_BAND_SEL 0x00000001 /*****************************************************************************/ -#define PATH2_SC_CTL 0x8EC -#define FLD_PATH2_SC_THRESHOLD 0xFFFF0000 -#define FLD_PATH2_SC_RT 0x0000F000 -#define FLD_PATH2_SC_AT 0x00000F00 -#define FLD_PATH2_SC_STEREO 0x00000080 -#define FLD_PATH2_SC_CR 0x00000070 -#define FLD_PATH2_SC_RMS_CON 0x0000000F +#define PATH2_SC_CTL 0x8EC +#define FLD_PATH2_SC_THRESHOLD 0xFFFF0000 +#define FLD_PATH2_SC_RT 0x0000F000 +#define FLD_PATH2_SC_AT 0x00000F00 +#define FLD_PATH2_SC_STEREO 0x00000080 +#define FLD_PATH2_SC_CR 0x00000070 +#define FLD_PATH2_SC_RMS_CON 0x0000000F /*****************************************************************************/ -#define SRC_CTL 0x8F0 -#define FLD_SRC_STATUS 0xFFFFFF00 -#define FLD_FIFO_LF_EN 0x000000FC -#define FLD_BYPASS_LI 0x00000002 -#define FLD_BYPASS_PF 0x00000001 +#define SRC_CTL 0x8F0 +#define FLD_SRC_STATUS 0xFFFFFF00 +#define FLD_FIFO_LF_EN 0x000000FC +#define FLD_BYPASS_LI 0x00000002 +#define FLD_BYPASS_PF 0x00000001 /*****************************************************************************/ -#define SRC_LF_COEF 0x8F4 -#define FLD_LOOP_FILTER_COEF2 0xFFFF0000 -#define FLD_LOOP_FILTER_COEF1 0x0000FFFF +#define SRC_LF_COEF 0x8F4 +#define FLD_LOOP_FILTER_COEF2 0xFFFF0000 +#define FLD_LOOP_FILTER_COEF1 0x0000FFFF /*****************************************************************************/ -#define SRC1_CTL 0x8F8 +#define SRC1_CTL 0x8F8 /* Reserved [31:28] */ -#define FLD_SRC1_FIFO_RD_TH 0x0F000000 +#define FLD_SRC1_FIFO_RD_TH 0x0F000000 /* Reserved [23:18] */ -#define FLD_SRC1_PHASE_INC 0x0003FFFF +#define FLD_SRC1_PHASE_INC 0x0003FFFF /*****************************************************************************/ -#define SRC2_CTL 0x8FC +#define SRC2_CTL 0x8FC /* Reserved [31:28] */ -#define FLD_SRC2_FIFO_RD_TH 0x0F000000 +#define FLD_SRC2_FIFO_RD_TH 0x0F000000 /* Reserved [23:18] */ -#define FLD_SRC2_PHASE_INC 0x0003FFFF +#define FLD_SRC2_PHASE_INC 0x0003FFFF /*****************************************************************************/ -#define SRC3_CTL 0x900 +#define SRC3_CTL 0x900 /* Reserved [31:28] */ -#define FLD_SRC3_FIFO_RD_TH 0x0F000000 +#define FLD_SRC3_FIFO_RD_TH 0x0F000000 /* Reserved [23:18] */ -#define FLD_SRC3_PHASE_INC 0x0003FFFF +#define FLD_SRC3_PHASE_INC 0x0003FFFF /*****************************************************************************/ -#define SRC4_CTL 0x904 +#define SRC4_CTL 0x904 /* Reserved [31:28] */ -#define FLD_SRC4_FIFO_RD_TH 0x0F000000 +#define FLD_SRC4_FIFO_RD_TH 0x0F000000 /* Reserved [23:18] */ -#define FLD_SRC4_PHASE_INC 0x0003FFFF +#define FLD_SRC4_PHASE_INC 0x0003FFFF /*****************************************************************************/ -#define SRC5_CTL 0x908 +#define SRC5_CTL 0x908 /* Reserved [31:28] */ -#define FLD_SRC5_FIFO_RD_TH 0x0F000000 +#define FLD_SRC5_FIFO_RD_TH 0x0F000000 /* Reserved [23:18] */ -#define FLD_SRC5_PHASE_INC 0x0003FFFF +#define FLD_SRC5_PHASE_INC 0x0003FFFF /*****************************************************************************/ -#define SRC6_CTL 0x90C +#define SRC6_CTL 0x90C /* Reserved [31:28] */ -#define FLD_SRC6_FIFO_RD_TH 0x0F000000 +#define FLD_SRC6_FIFO_RD_TH 0x0F000000 /* Reserved [23:18] */ -#define FLD_SRC6_PHASE_INC 0x0003FFFF - -/*****************************************************************************/ -#define BAND_OUT_SEL 0x910 -#define FLD_SRC6_IN_SEL 0xC0000000 -#define FLD_SRC6_CLK_SEL 0x30000000 -#define FLD_SRC5_IN_SEL 0x0C000000 -#define FLD_SRC5_CLK_SEL 0x03000000 -#define FLD_SRC4_IN_SEL 0x00C00000 -#define FLD_SRC4_CLK_SEL 0x00300000 -#define FLD_SRC3_IN_SEL 0x000C0000 -#define FLD_SRC3_CLK_SEL 0x00030000 -#define FLD_BASEBAND_BYPASS_CTL 0x0000FF00 -#define FLD_AC97_SRC_SEL 0x000000C0 -#define FLD_I2S_SRC_SEL 0x00000030 -#define FLD_PARALLEL2_SRC_SEL 0x0000000C -#define FLD_PARALLEL1_SRC_SEL 0x00000003 - -/*****************************************************************************/ -#define I2S_IN_CTL 0x914 +#define FLD_SRC6_PHASE_INC 0x0003FFFF + +/*****************************************************************************/ +#define BAND_OUT_SEL 0x910 +#define FLD_SRC6_IN_SEL 0xC0000000 +#define FLD_SRC6_CLK_SEL 0x30000000 +#define FLD_SRC5_IN_SEL 0x0C000000 +#define FLD_SRC5_CLK_SEL 0x03000000 +#define FLD_SRC4_IN_SEL 0x00C00000 +#define FLD_SRC4_CLK_SEL 0x00300000 +#define FLD_SRC3_IN_SEL 0x000C0000 +#define FLD_SRC3_CLK_SEL 0x00030000 +#define FLD_BASEBAND_BYPASS_CTL 0x0000FF00 +#define FLD_AC97_SRC_SEL 0x000000C0 +#define FLD_I2S_SRC_SEL 0x00000030 +#define FLD_PARALLEL2_SRC_SEL 0x0000000C +#define FLD_PARALLEL1_SRC_SEL 0x00000003 + +/*****************************************************************************/ +#define I2S_IN_CTL 0x914 /* Reserved [31:11] */ -#define FLD_I2S_UP2X_BW20K 0x00000400 -#define FLD_I2S_UP2X_BYPASS 0x00000200 -#define FLD_I2S_IN_MASTER_MODE 0x00000100 -#define FLD_I2S_IN_SONY_MODE 0x00000080 -#define FLD_I2S_IN_RIGHT_JUST 0x00000040 -#define FLD_I2S_IN_WS_SEL 0x00000020 -#define FLD_I2S_IN_BCN_DEL 0x0000001F +#define FLD_I2S_UP2X_BW20K 0x00000400 +#define FLD_I2S_UP2X_BYPASS 0x00000200 +#define FLD_I2S_IN_MASTER_MODE 0x00000100 +#define FLD_I2S_IN_SONY_MODE 0x00000080 +#define FLD_I2S_IN_RIGHT_JUST 0x00000040 +#define FLD_I2S_IN_WS_SEL 0x00000020 +#define FLD_I2S_IN_BCN_DEL 0x0000001F /*****************************************************************************/ -#define I2S_OUT_CTL 0x918 +#define I2S_OUT_CTL 0x918 /* Reserved [31:17] */ -#define FLD_I2S_OUT_SOFT_RESET_EN 0x00010000 +#define FLD_I2S_OUT_SOFT_RESET_EN 0x00010000 /* Reserved [15:9] */ -#define FLD_I2S_OUT_MASTER_MODE 0x00000100 -#define FLD_I2S_OUT_SONY_MODE 0x00000080 -#define FLD_I2S_OUT_RIGHT_JUST 0x00000040 -#define FLD_I2S_OUT_WS_SEL 0x00000020 -#define FLD_I2S_OUT_BCN_DEL 0x0000001F - +#define FLD_I2S_OUT_MASTER_MODE 0x00000100 +#define FLD_I2S_OUT_SONY_MODE 0x00000080 +#define FLD_I2S_OUT_RIGHT_JUST 0x00000040 +#define FLD_I2S_OUT_WS_SEL 0x00000020 +#define FLD_I2S_OUT_BCN_DEL 0x0000001F /*****************************************************************************/ -#define AC97_CTL 0x91C +#define AC97_CTL 0x91C /* Reserved [31:26] */ -#define FLD_AC97_UP2X_BW20K 0x02000000 -#define FLD_AC97_UP2X_BYPASS 0x01000000 +#define FLD_AC97_UP2X_BW20K 0x02000000 +#define FLD_AC97_UP2X_BYPASS 0x01000000 /* Reserved [23:17] */ -#define FLD_AC97_RST_ACL 0x00010000 +#define FLD_AC97_RST_ACL 0x00010000 /* Reserved [15:9] */ -#define FLD_AC97_WAKE_UP_SYNC 0x00000100 +#define FLD_AC97_WAKE_UP_SYNC 0x00000100 /* Reserved [7:1] */ -#define FLD_AC97_SHUTDOWN 0x00000001 - +#define FLD_AC97_SHUTDOWN 0x00000001 /* Cx231xx redefine */ -#define QPSK_IAGC_CTL1 0x94c -#define QPSK_IAGC_CTL2 0x950 -#define QPSK_FEPR_FREQ 0x954 -#define QPSK_BTL_CTL1 0x958 -#define QPSK_BTL_CTL2 0x95c -#define QPSK_CTL_CTL1 0x960 -#define QPSK_CTL_CTL2 0x964 -#define QPSK_MF_FAGC_CTL 0x968 -#define QPSK_EQ_CTL 0x96c -#define QPSK_LOCK_CTL 0x970 - - -/*****************************************************************************/ -#define FM1_DFT_CTL 0x9A8 -#define FLD_FM1_DFT_THRESHOLD 0xFFFF0000 +#define QPSK_IAGC_CTL1 0x94c +#define QPSK_IAGC_CTL2 0x950 +#define QPSK_FEPR_FREQ 0x954 +#define QPSK_BTL_CTL1 0x958 +#define QPSK_BTL_CTL2 0x95c +#define QPSK_CTL_CTL1 0x960 +#define QPSK_CTL_CTL2 0x964 +#define QPSK_MF_FAGC_CTL 0x968 +#define QPSK_EQ_CTL 0x96c +#define QPSK_LOCK_CTL 0x970 + +/*****************************************************************************/ +#define FM1_DFT_CTL 0x9A8 +#define FLD_FM1_DFT_THRESHOLD 0xFFFF0000 /* Reserved [15:8] */ -#define FLD_FM1_DFT_CMP_CTL 0x00000080 -#define FLD_FM1_DFT_AVG 0x00000070 +#define FLD_FM1_DFT_CMP_CTL 0x00000080 +#define FLD_FM1_DFT_AVG 0x00000070 /* Reserved [3:1] */ -#define FLD_FM1_DFT_START 0x00000001 +#define FLD_FM1_DFT_START 0x00000001 /*****************************************************************************/ -#define FM1_DFT_STATUS 0x9AC -#define FLD_FM1_DFT_DONE 0x80000000 +#define FM1_DFT_STATUS 0x9AC +#define FLD_FM1_DFT_DONE 0x80000000 /* Reserved [30:19] */ -#define FLD_FM_DFT_TH_CMP 0x00040000 -#define FLD_FM1_DFT 0x0003FFFF +#define FLD_FM_DFT_TH_CMP 0x00040000 +#define FLD_FM1_DFT 0x0003FFFF /*****************************************************************************/ -#define FM2_DFT_CTL 0x9B0 -#define FLD_FM2_DFT_THRESHOLD 0xFFFF0000 +#define FM2_DFT_CTL 0x9B0 +#define FLD_FM2_DFT_THRESHOLD 0xFFFF0000 /* Reserved [15:8] */ -#define FLD_FM2_DFT_CMP_CTL 0x00000080 -#define FLD_FM2_DFT_AVG 0x00000070 +#define FLD_FM2_DFT_CMP_CTL 0x00000080 +#define FLD_FM2_DFT_AVG 0x00000070 /* Reserved [3:1] */ -#define FLD_FM2_DFT_START 0x00000001 +#define FLD_FM2_DFT_START 0x00000001 /*****************************************************************************/ -#define FM2_DFT_STATUS 0x9B4 -#define FLD_FM2_DFT_DONE 0x80000000 +#define FM2_DFT_STATUS 0x9B4 +#define FLD_FM2_DFT_DONE 0x80000000 /* Reserved [30:19] */ -#define FLD_FM2_DFT_TH_CMP_STAT 0x00040000 -#define FLD_FM2_DFT 0x0003FFFF +#define FLD_FM2_DFT_TH_CMP_STAT 0x00040000 +#define FLD_FM2_DFT 0x0003FFFF /*****************************************************************************/ /* Cx231xx redefine */ -#define AAGC_STATUS_REG 0x9B8 -#define AAGC_STATUS 0x9B8 +#define AAGC_STATUS_REG 0x9B8 +#define AAGC_STATUS 0x9B8 /* Reserved [31:27] */ -#define FLD_FM2_DAGC_OUT 0x07000000 +#define FLD_FM2_DAGC_OUT 0x07000000 /* Reserved [23:19] */ -#define FLD_FM1_DAGC_OUT 0x00070000 +#define FLD_FM1_DAGC_OUT 0x00070000 /* Reserved [15:6] */ -#define FLD_AFE_VGA_OUT 0x0000003F - - +#define FLD_AFE_VGA_OUT 0x0000003F /*****************************************************************************/ -#define MTS_GAIN_STATUS 0x9BC +#define MTS_GAIN_STATUS 0x9BC /* Reserved [31:14] */ -#define FLD_MTS_GAIN 0x00003FFF +#define FLD_MTS_GAIN 0x00003FFF -#define RDS_OUT 0x9C0 -#define FLD_RDS_Q 0xFFFF0000 -#define FLD_RDS_I 0x0000FFFF +#define RDS_OUT 0x9C0 +#define FLD_RDS_Q 0xFFFF0000 +#define FLD_RDS_I 0x0000FFFF /*****************************************************************************/ -#define AUTOCONFIG_REG 0x9C4 +#define AUTOCONFIG_REG 0x9C4 /* Reserved [31:4] */ -#define FLD_AUTOCONFIG_MODE 0x0000000F +#define FLD_AUTOCONFIG_MODE 0x0000000F -#define FM_AFC 0x9C8 -#define FLD_FM2_AFC 0xFFFF0000 -#define FLD_FM1_AFC 0x0000FFFF +#define FM_AFC 0x9C8 +#define FLD_FM2_AFC 0xFFFF0000 +#define FLD_FM1_AFC 0x0000FFFF /*****************************************************************************/ /* Cx231xx redefine */ -#define NEW_SPARE 0x9CC -#define NEW_SPARE_REG 0x9CC +#define NEW_SPARE 0x9CC +#define NEW_SPARE_REG 0x9CC /*****************************************************************************/ -#define DBX_ADJ 0x9D0 +#define DBX_ADJ 0x9D0 /* Reserved [31:28] */ -#define FLD_DBX2_ADJ 0x0FFF0000 +#define FLD_DBX2_ADJ 0x0FFF0000 /* Reserved [15:12] */ -#define FLD_DBX1_ADJ 0x00000FFF - -#define VID_FMT_AUTO 0 -#define VID_FMT_NTSC_M 1 -#define VID_FMT_NTSC_J 2 -#define VID_FMT_NTSC_443 3 -#define VID_FMT_PAL_BDGHI 4 -#define VID_FMT_PAL_M 5 -#define VID_FMT_PAL_N 6 -#define VID_FMT_PAL_NC 7 -#define VID_FMT_PAL_60 8 -#define VID_FMT_SECAM 12 -#define VID_FMT_SECAM_60 13 - -#define INPUT_MODE_CVBS_0 0 /* INPUT_MODE_VALUE(0) */ -#define INPUT_MODE_YC_1 1 /* INPUT_MODE_VALUE(1) */ -#define INPUT_MODE_YC2_2 2 /* INPUT_MODE_VALUE(2) */ -#define INPUT_MODE_YUV_3 3 /* INPUT_MODE_VALUE(3) */ - - -#define LUMA_LPF_LOW_BANDPASS 0 /* 0.6Mhz lowpass filter bandwidth */ -#define LUMA_LPF_MEDIUM_BANDPASS 1 /* 1.0Mhz lowpass filter bandwidth */ -#define LUMA_LPF_HIGH_BANDPASS 2 /* 1.5Mhz lowpass filter bandwidth */ - -#define UV_LPF_LOW_BANDPASS 0 /* 0.6Mhz lowpass filter bandwidth */ -#define UV_LPF_MEDIUM_BANDPASS 1 /* 1.0Mhz lowpass filter bandwidth */ -#define UV_LPF_HIGH_BANDPASS 2 /* 1.5Mhz lowpass filter bandwidth */ - -#define TWO_TAP_FILT 0 -#define THREE_TAP_FILT 1 -#define FOUR_TAP_FILT 2 -#define FIVE_TAP_FILT 3 - -#define AUD_CHAN_SRC_PARALLEL 0 -#define AUD_CHAN_SRC_I2S_INPUT 1 -#define AUD_CHAN_SRC_FLATIRON 2 -#define AUD_CHAN_SRC_PARALLEL3 3 - -#define OUT_MODE_601 0 -#define OUT_MODE_656 1 -#define OUT_MODE_VIP11 2 -#define OUT_MODE_VIP20 3 - -#define PHASE_INC_49MHZ 0x0DF22 -#define PHASE_INC_56MHZ 0x0FA5B -#define PHASE_INC_28MHZ 0x010000 +#define FLD_DBX1_ADJ 0x00000FFF + +#define VID_FMT_AUTO 0 +#define VID_FMT_NTSC_M 1 +#define VID_FMT_NTSC_J 2 +#define VID_FMT_NTSC_443 3 +#define VID_FMT_PAL_BDGHI 4 +#define VID_FMT_PAL_M 5 +#define VID_FMT_PAL_N 6 +#define VID_FMT_PAL_NC 7 +#define VID_FMT_PAL_60 8 +#define VID_FMT_SECAM 12 +#define VID_FMT_SECAM_60 13 + +#define INPUT_MODE_CVBS_0 0 /* INPUT_MODE_VALUE(0) */ +#define INPUT_MODE_YC_1 1 /* INPUT_MODE_VALUE(1) */ +#define INPUT_MODE_YC2_2 2 /* INPUT_MODE_VALUE(2) */ +#define INPUT_MODE_YUV_3 3 /* INPUT_MODE_VALUE(3) */ + +#define LUMA_LPF_LOW_BANDPASS 0 /* 0.6Mhz lowpass filter bandwidth */ +#define LUMA_LPF_MEDIUM_BANDPASS 1 /* 1.0Mhz lowpass filter bandwidth */ +#define LUMA_LPF_HIGH_BANDPASS 2 /* 1.5Mhz lowpass filter bandwidth */ + +#define UV_LPF_LOW_BANDPASS 0 /* 0.6Mhz lowpass filter bandwidth */ +#define UV_LPF_MEDIUM_BANDPASS 1 /* 1.0Mhz lowpass filter bandwidth */ +#define UV_LPF_HIGH_BANDPASS 2 /* 1.5Mhz lowpass filter bandwidth */ + +#define TWO_TAP_FILT 0 +#define THREE_TAP_FILT 1 +#define FOUR_TAP_FILT 2 +#define FIVE_TAP_FILT 3 + +#define AUD_CHAN_SRC_PARALLEL 0 +#define AUD_CHAN_SRC_I2S_INPUT 1 +#define AUD_CHAN_SRC_FLATIRON 2 +#define AUD_CHAN_SRC_PARALLEL3 3 + +#define OUT_MODE_601 0 +#define OUT_MODE_656 1 +#define OUT_MODE_VIP11 2 +#define OUT_MODE_VIP20 3 + +#define PHASE_INC_49MHZ 0x0DF22 +#define PHASE_INC_56MHZ 0x0FA5B +#define PHASE_INC_28MHZ 0x010000 #endif diff --git a/linux/drivers/media/video/cx231xx/cx231xx-vbi.c b/linux/drivers/media/video/cx231xx/cx231xx-vbi.c index eeb6e5e92..a6e9add83 100644 --- a/linux/drivers/media/video/cx231xx/cx231xx-vbi.c +++ b/linux/drivers/media/video/cx231xx/cx231xx-vbi.c @@ -2,7 +2,7 @@ cx231xx_vbi.c - driver for Conexant Cx23100/101/102 USB video capture devices Copyright (C) 2008 - Based on cx88 driver + Based on cx88 driver 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 @@ -39,8 +39,7 @@ #include "cx231xx.h" #include "cx231xx-vbi.h" -static inline void print_err_status(struct cx231xx *dev, - int packet, int status) +static inline void print_err_status(struct cx231xx *dev, int packet, int status) { char *errmsg = "Unknown"; @@ -71,10 +70,11 @@ static inline void print_err_status(struct cx231xx *dev, break; } if (packet < 0) { - cx231xx_err(DRIVER_NAME "URB status %d [%s].\n", status, errmsg); + cx231xx_err(DRIVER_NAME "URB status %d [%s].\n", status, + errmsg); } else { cx231xx_err(DRIVER_NAME "URB packet %d, status %d [%s].\n", - packet, status, errmsg); + packet, status, errmsg); } } @@ -83,12 +83,12 @@ static inline void print_err_status(struct cx231xx *dev, */ static inline int cx231xx_isoc_vbi_copy(struct cx231xx *dev, struct urb *urb) { - struct cx231xx_buffer *buf; - struct cx231xx_dmaqueue *dma_q = urb->context; - int rc = 1; + struct cx231xx_buffer *buf; + struct cx231xx_dmaqueue *dma_q = urb->context; + int rc = 1; unsigned char *p_buffer; - u32 bytes_parsed = 0, buffer_size = 0; - u8 sav_eav = 0; + u32 bytes_parsed = 0, buffer_size = 0; + u8 sav_eav = 0; if (!dev) return 0; @@ -104,60 +104,58 @@ static inline int cx231xx_isoc_vbi_copy(struct cx231xx *dev, struct urb *urb) buf = dev->vbi_mode.isoc_ctl.buf; - /* get buffer pointer and length */ - p_buffer = urb->transfer_buffer; - buffer_size = urb->actual_length; - - if (buffer_size > 0) { - - bytes_parsed = 0; - - if(dma_q->is_partial_line) { - /* Handle the case where we were working on a partial line */ - sav_eav = dma_q->last_sav; - } else { - /* Check for a SAV/EAV overlapping the buffer boundary */ - sav_eav = cx231xx_find_boundary_SAV_EAV(p_buffer, dma_q->partial_buf, &bytes_parsed); - } - - sav_eav &= 0xF0; - /* Get the first line if we have some portion of an SAV/EAV from the last buffer - or a partial line */ - if(sav_eav) { - bytes_parsed += cx231xx_get_vbi_line(dev, dma_q, - sav_eav, /* SAV/EAV */ - p_buffer + bytes_parsed, /* p_buffer */ - buffer_size - bytes_parsed); /* buffer size */ - } - - /* Now parse data that is completely in this buffer */ - dma_q->is_partial_line = 0; - - while(bytes_parsed < buffer_size) - { - u32 bytes_used = 0; - - sav_eav = cx231xx_find_next_SAV_EAV( - p_buffer + bytes_parsed, /* p_buffer */ - buffer_size - bytes_parsed, /* buffer size */ - &bytes_used); /* Receives bytes used to get SAV/EAV */ - - bytes_parsed += bytes_used; - - sav_eav &= 0xF0; - if(sav_eav && (bytes_parsed < buffer_size)) - { - bytes_parsed += cx231xx_get_vbi_line(dev, dma_q, - sav_eav, /* SAV/EAV */ - p_buffer + bytes_parsed, /* p_buffer */ - buffer_size - bytes_parsed); /* buffer size */ - } - } - - /* Save the last four bytes of the buffer so we can check the buffer boundary - condition next time */ - memcpy(dma_q->partial_buf, p_buffer + buffer_size - 4, 4); - bytes_parsed = 0; + /* get buffer pointer and length */ + p_buffer = urb->transfer_buffer; + buffer_size = urb->actual_length; + + if (buffer_size > 0) { + + bytes_parsed = 0; + + if (dma_q->is_partial_line) { + /* Handle the case where we were working on a partial line */ + sav_eav = dma_q->last_sav; + } else { + /* Check for a SAV/EAV overlapping the buffer boundary */ + sav_eav = + cx231xx_find_boundary_SAV_EAV(p_buffer, + dma_q->partial_buf, + &bytes_parsed); + } + + sav_eav &= 0xF0; + /* Get the first line if we have some portion of an SAV/EAV from the last buffer + or a partial line */ + if (sav_eav) { + bytes_parsed += cx231xx_get_vbi_line(dev, dma_q, sav_eav, /* SAV/EAV */ + p_buffer + bytes_parsed, /* p_buffer */ + buffer_size - bytes_parsed); /* buffer size */ + } + + /* Now parse data that is completely in this buffer */ + dma_q->is_partial_line = 0; + + while (bytes_parsed < buffer_size) { + u32 bytes_used = 0; + + sav_eav = cx231xx_find_next_SAV_EAV(p_buffer + bytes_parsed, /* p_buffer */ + buffer_size - bytes_parsed, /* buffer size */ + &bytes_used); /* Receives bytes used to get SAV/EAV */ + + bytes_parsed += bytes_used; + + sav_eav &= 0xF0; + if (sav_eav && (bytes_parsed < buffer_size)) { + bytes_parsed += cx231xx_get_vbi_line(dev, dma_q, sav_eav, /* SAV/EAV */ + p_buffer + bytes_parsed, /* p_buffer */ + buffer_size - bytes_parsed); /* buffer size */ + } + } + + /* Save the last four bytes of the buffer so we can check the buffer boundary + condition next time */ + memcpy(dma_q->partial_buf, p_buffer + buffer_size - 4, 4); + bytes_parsed = 0; } return rc; @@ -168,25 +166,26 @@ static inline int cx231xx_isoc_vbi_copy(struct cx231xx *dev, struct urb *urb) ------------------------------------------------------------------*/ static int -vbi_buffer_setup(struct videobuf_queue *vq, unsigned int *count, unsigned int *size) +vbi_buffer_setup(struct videobuf_queue *vq, unsigned int *count, + unsigned int *size) { struct cx231xx_fh *fh = vq->priv_data; - struct cx231xx *dev = fh->dev; - u32 height = 0; + struct cx231xx *dev = fh->dev; + u32 height = 0; - height = ((dev->norm & V4L2_STD_625_50) ? - PAL_VBI_LINES : NTSC_VBI_LINES) ; + height = ((dev->norm & V4L2_STD_625_50) ? + PAL_VBI_LINES : NTSC_VBI_LINES); - *size = ( dev->width * height * 2); + *size = (dev->width * height * 2); if (0 == *count) *count = CX231XX_DEF_VBI_BUF; if (*count < CX231XX_MIN_BUF) *count = CX231XX_MIN_BUF; - /* call VBI setup if required */ + /* call VBI setup if required */ /* cx231xx_i2c_call_clients(&dev->i2c_bus[1], VIDIOC_S_FREQUENCY, &f); - */ + */ return 0; } @@ -194,8 +193,8 @@ vbi_buffer_setup(struct videobuf_queue *vq, unsigned int *count, unsigned int *s /* This is called *without* dev->slock held; please keep it that way */ static void free_buffer(struct videobuf_queue *vq, struct cx231xx_buffer *buf) { - struct cx231xx_fh *fh = vq->priv_data; - struct cx231xx *dev = fh->dev; + struct cx231xx_fh *fh = vq->priv_data; + struct cx231xx *dev = fh->dev; unsigned long flags = 0; if (in_interrupt()) BUG(); @@ -208,7 +207,7 @@ static void free_buffer(struct videobuf_queue *vq, struct cx231xx_buffer *buf) This should be safe; by the time we get here, the buffer isn't queued anymore. If we ever start marking the buffers as VIDEOBUF_ACTIVE, it won't be, though. - */ + */ spin_lock_irqsave(&dev->vbi_mode.slock, flags); if (dev->vbi_mode.isoc_ctl.buf == buf) dev->vbi_mode.isoc_ctl.buf = NULL; @@ -220,25 +219,26 @@ static void free_buffer(struct videobuf_queue *vq, struct cx231xx_buffer *buf) static int vbi_buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb, - enum v4l2_field field) + enum v4l2_field field) { - struct cx231xx_fh *fh = vq->priv_data; - struct cx231xx_buffer *buf = container_of(vb, struct cx231xx_buffer, vb); - struct cx231xx *dev = fh->dev; - int rc = 0, urb_init = 0; - u32 height = 0; + struct cx231xx_fh *fh = vq->priv_data; + struct cx231xx_buffer *buf = + container_of(vb, struct cx231xx_buffer, vb); + struct cx231xx *dev = fh->dev; + int rc = 0, urb_init = 0; + u32 height = 0; - height = ((dev->norm & V4L2_STD_625_50) ? - PAL_VBI_LINES : NTSC_VBI_LINES) ; - buf->vb.size = ( (dev->width << 1) * height ); + height = ((dev->norm & V4L2_STD_625_50) ? + PAL_VBI_LINES : NTSC_VBI_LINES); + buf->vb.size = ((dev->width << 1) * height); - if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size) + if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size) return -EINVAL; - buf->vb.width = dev->width; + buf->vb.width = dev->width; buf->vb.height = height; - buf->vb.field = field; - buf->vb.field = V4L2_FIELD_SEQ_TB; + buf->vb.field = field; + buf->vb.field = V4L2_FIELD_SEQ_TB; if (VIDEOBUF_NEEDS_INIT == buf->vb.state) { rc = videobuf_iolock(vq, &buf->vb, NULL); @@ -251,8 +251,9 @@ vbi_buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb, if (urb_init) { rc = cx231xx_init_vbi_isoc(dev, CX231XX_NUM_VBI_PACKETS, - CX231XX_NUM_VBI_BUFS, dev->vbi_mode.alt_max_pkt_size[0], - cx231xx_isoc_vbi_copy); + CX231XX_NUM_VBI_BUFS, + dev->vbi_mode.alt_max_pkt_size[0], + cx231xx_isoc_vbi_copy); if (rc < 0) goto fail; } @@ -260,7 +261,7 @@ vbi_buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb, buf->vb.state = VIDEOBUF_PREPARED; return 0; -fail: + fail: free_buffer(vq, buf); return rc; } @@ -268,10 +269,11 @@ fail: static void vbi_buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) { - struct cx231xx_buffer *buf = container_of(vb, struct cx231xx_buffer, vb); - struct cx231xx_fh *fh = vq->priv_data; - struct cx231xx *dev = fh->dev; - struct cx231xx_dmaqueue *vidq = &dev->vbi_mode.vidq; + struct cx231xx_buffer *buf = + container_of(vb, struct cx231xx_buffer, vb); + struct cx231xx_fh *fh = vq->priv_data; + struct cx231xx *dev = fh->dev; + struct cx231xx_dmaqueue *vidq = &dev->vbi_mode.vidq; buf->vb.state = VIDEOBUF_QUEUED; list_add_tail(&buf->vb.queue, &vidq->active); @@ -279,29 +281,27 @@ vbi_buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) } static void vbi_buffer_release(struct videobuf_queue *vq, - struct videobuf_buffer *vb) + struct videobuf_buffer *vb) { - struct cx231xx_buffer *buf = container_of(vb, struct cx231xx_buffer, vb); - /* - struct cx231xx_fh *fh = vq->priv_data; - struct cx231xx *dev = (struct cx231xx *)fh->dev; + struct cx231xx_buffer *buf = + container_of(vb, struct cx231xx_buffer, vb); + /* + struct cx231xx_fh *fh = vq->priv_data; + struct cx231xx *dev = (struct cx231xx *)fh->dev; - cx231xx_info(DRIVER_NAME "cx231xx: called vbi_buffer_release\n"); - */ + cx231xx_info(DRIVER_NAME "cx231xx: called vbi_buffer_release\n"); + */ free_buffer(vq, buf); } - struct videobuf_queue_ops cx231xx_vbi_qops = { - .buf_setup = vbi_buffer_setup, - .buf_prepare = vbi_buffer_prepare, - .buf_queue = vbi_buffer_queue, - .buf_release = vbi_buffer_release, + .buf_setup = vbi_buffer_setup, + .buf_prepare = vbi_buffer_prepare, + .buf_queue = vbi_buffer_queue, + .buf_release = vbi_buffer_release, }; - - /* ------------------------------------------------------------------ URB control ------------------------------------------------------------------*/ @@ -315,23 +315,24 @@ static void cx231xx_irq_vbi_callback(struct urb *urb, struct pt_regs *regs) static void cx231xx_irq_vbi_callback(struct urb *urb) #endif { - struct cx231xx_dmaqueue *dma_q = urb->context; - struct cx231xx_video_mode *vmode = container_of(dma_q, struct cx231xx_video_mode, vidq); - struct cx231xx *dev = container_of(vmode, struct cx231xx, vbi_mode); + struct cx231xx_dmaqueue *dma_q = urb->context; + struct cx231xx_video_mode *vmode = + container_of(dma_q, struct cx231xx_video_mode, vidq); + struct cx231xx *dev = container_of(vmode, struct cx231xx, vbi_mode); int rc; - - switch (urb->status) { - case 0: /* success */ - case -ETIMEDOUT: /* NAK */ - break; - case -ECONNRESET: /* kill */ - case -ENOENT: - case -ESHUTDOWN: - return; - default: /* error */ - cx231xx_err(DRIVER_NAME "urb completition error %d.\n", urb->status); - break; + switch (urb->status) { + case 0: /* success */ + case -ETIMEDOUT: /* NAK */ + break; + case -ECONNRESET: /* kill */ + case -ENOENT: + case -ESHUTDOWN: + return; + default: /* error */ + cx231xx_err(DRIVER_NAME "urb completition error %d.\n", + urb->status); + break; } /* Copy data from URB */ @@ -345,7 +346,7 @@ static void cx231xx_irq_vbi_callback(struct urb *urb) urb->status = usb_submit_urb(urb, GFP_ATOMIC); if (urb->status) { cx231xx_err(DRIVER_NAME "urb resubmit failed (error=%i)\n", - urb->status); + urb->status); } } @@ -357,21 +358,23 @@ void cx231xx_uninit_vbi_isoc(struct cx231xx *dev) struct urb *urb; int i; - cx231xx_info(DRIVER_NAME "cx231xx: called cx231xx_uninit_vbi_isoc\n"); + cx231xx_info(DRIVER_NAME "cx231xx: called cx231xx_uninit_vbi_isoc\n"); dev->vbi_mode.isoc_ctl.nfields = -1; for (i = 0; i < dev->vbi_mode.isoc_ctl.num_bufs; i++) { urb = dev->vbi_mode.isoc_ctl.urb[i]; if (urb) { - if (!irqs_disabled()) - usb_kill_urb(urb); - else - usb_unlink_urb(urb); + if (!irqs_disabled()) + usb_kill_urb(urb); + else + usb_unlink_urb(urb); if (dev->vbi_mode.isoc_ctl.transfer_buffer[i]) { - kfree(dev->vbi_mode.isoc_ctl.transfer_buffer[i]); - dev->vbi_mode.isoc_ctl.transfer_buffer[i] = NULL; + kfree(dev->vbi_mode.isoc_ctl. + transfer_buffer[i]); + dev->vbi_mode.isoc_ctl.transfer_buffer[i] = + NULL; } usb_free_urb(urb); dev->vbi_mode.isoc_ctl.urb[i] = NULL; @@ -388,14 +391,16 @@ void cx231xx_uninit_vbi_isoc(struct cx231xx *dev) cx231xx_capture_start(dev, 0, Vbi); } + EXPORT_SYMBOL_GPL(cx231xx_uninit_vbi_isoc); /* * Allocate URBs and start IRQ */ int cx231xx_init_vbi_isoc(struct cx231xx *dev, int max_packets, - int num_bufs, int max_pkt_size, - int (*isoc_copy) (struct cx231xx *dev, struct urb *urb)) + int num_bufs, int max_pkt_size, + int (*isoc_copy) (struct cx231xx * dev, + struct urb * urb)) { struct cx231xx_dmaqueue *dma_q = &dev->vbi_mode.vidq; int i; @@ -408,31 +413,33 @@ int cx231xx_init_vbi_isoc(struct cx231xx *dev, int max_packets, /* De-allocates all pending stuff */ cx231xx_uninit_vbi_isoc(dev); - /* clear if any halt */ - usb_clear_halt(dev->udev, usb_rcvbulkpipe(dev->udev, dev->vbi_mode.end_point_addr)); - + /* clear if any halt */ + usb_clear_halt(dev->udev, + usb_rcvbulkpipe(dev->udev, + dev->vbi_mode.end_point_addr)); dev->vbi_mode.isoc_ctl.isoc_copy = isoc_copy; dev->vbi_mode.isoc_ctl.num_bufs = num_bufs; - dma_q->pos = 0; - dma_q->is_partial_line = 0; - dma_q->last_sav = 0; - dma_q->current_field = -1; - dma_q->bytes_left_in_line = dev->width << 1; - dma_q->lines_per_field = ((dev->norm & V4L2_STD_625_50) ? - PAL_VBI_LINES : NTSC_VBI_LINES) ; - dma_q->lines_completed = 0; - for(i = 0; i < 8 ; i++) - dma_q->partial_buf[i] = 0; - - dev->vbi_mode.isoc_ctl.urb = kzalloc(sizeof(void *)*num_bufs, GFP_KERNEL); + dma_q->pos = 0; + dma_q->is_partial_line = 0; + dma_q->last_sav = 0; + dma_q->current_field = -1; + dma_q->bytes_left_in_line = dev->width << 1; + dma_q->lines_per_field = ((dev->norm & V4L2_STD_625_50) ? + PAL_VBI_LINES : NTSC_VBI_LINES); + dma_q->lines_completed = 0; + for (i = 0; i < 8; i++) + dma_q->partial_buf[i] = 0; + + dev->vbi_mode.isoc_ctl.urb = + kzalloc(sizeof(void *) * num_bufs, GFP_KERNEL); if (!dev->vbi_mode.isoc_ctl.urb) { cx231xx_errdev("cannot alloc memory for usb buffers\n"); return -ENOMEM; } - dev->vbi_mode.isoc_ctl.transfer_buffer = kzalloc(sizeof(void *)*num_bufs, - GFP_KERNEL); + dev->vbi_mode.isoc_ctl.transfer_buffer = + kzalloc(sizeof(void *) * num_bufs, GFP_KERNEL); if (!dev->vbi_mode.isoc_ctl.transfer_buffer) { cx231xx_errdev("cannot allocate memory for usbtransfer\n"); kfree(dev->vbi_mode.isoc_ctl.urb); @@ -449,84 +456,89 @@ int cx231xx_init_vbi_isoc(struct cx231xx *dev, int max_packets, urb = usb_alloc_urb(0, GFP_KERNEL); if (!urb) { - cx231xx_err(DRIVER_NAME ": cannot alloc isoc_ctl.urb %i\n", i); + cx231xx_err(DRIVER_NAME + ": cannot alloc isoc_ctl.urb %i\n", i); cx231xx_uninit_vbi_isoc(dev); return -ENOMEM; } dev->vbi_mode.isoc_ctl.urb[i] = urb; - urb->transfer_flags = 0; + urb->transfer_flags = 0; - dev->vbi_mode.isoc_ctl.transfer_buffer[i] = kzalloc(sb_size, GFP_KERNEL); + dev->vbi_mode.isoc_ctl.transfer_buffer[i] = + kzalloc(sb_size, GFP_KERNEL); if (!dev->vbi_mode.isoc_ctl.transfer_buffer[i]) { - cx231xx_err(DRIVER_NAME ": unable to allocate %i bytes for transfer" - " buffer %i%s\n", - sb_size, i, - in_interrupt()?" while in int":""); + cx231xx_err(DRIVER_NAME + ": unable to allocate %i bytes for transfer" + " buffer %i%s\n", sb_size, i, + in_interrupt()? " while in int" : ""); cx231xx_uninit_vbi_isoc(dev); return -ENOMEM; } pipe = usb_rcvbulkpipe(dev->udev, dev->vbi_mode.end_point_addr); - usb_fill_bulk_urb(urb, dev->udev, pipe, - dev->vbi_mode.isoc_ctl.transfer_buffer[i], sb_size, - cx231xx_irq_vbi_callback, dma_q); + usb_fill_bulk_urb(urb, dev->udev, pipe, + dev->vbi_mode.isoc_ctl.transfer_buffer[i], + sb_size, cx231xx_irq_vbi_callback, dma_q); } - init_waitqueue_head(&dma_q->wq); + init_waitqueue_head(&dma_q->wq); /* submit urbs and enables IRQ */ for (i = 0; i < dev->vbi_mode.isoc_ctl.num_bufs; i++) { rc = usb_submit_urb(dev->vbi_mode.isoc_ctl.urb[i], GFP_ATOMIC); if (rc) { - cx231xx_err(DRIVER_NAME ": submit of urb %i failed (error=%i)\n", i, - rc); + cx231xx_err(DRIVER_NAME + ": submit of urb %i failed (error=%i)\n", i, + rc); cx231xx_uninit_vbi_isoc(dev); return rc; } } - - cx231xx_capture_start(dev, 1, Vbi); + + cx231xx_capture_start(dev, 1, Vbi); return 0; } -EXPORT_SYMBOL_GPL(cx231xx_init_vbi_isoc); +EXPORT_SYMBOL_GPL(cx231xx_init_vbi_isoc); -u32 cx231xx_get_vbi_line(struct cx231xx *dev, struct cx231xx_dmaqueue *dma_q, - u8 sav_eav, u8 *p_buffer, u32 buffer_size) +u32 cx231xx_get_vbi_line(struct cx231xx * dev, struct cx231xx_dmaqueue * dma_q, + u8 sav_eav, u8 * p_buffer, u32 buffer_size) { - u32 bytes_copied = 0; - int current_field = -1; + u32 bytes_copied = 0; + int current_field = -1; - switch(sav_eav) { + switch (sav_eav) { - case SAV_VBI_FIELD1: - current_field = 1; - break; + case SAV_VBI_FIELD1: + current_field = 1; + break; - case SAV_VBI_FIELD2: - current_field = 2; - break; - default: - break; - } + case SAV_VBI_FIELD2: + current_field = 2; + break; + default: + break; + } - if(current_field < 0 ) - return bytes_copied; + if (current_field < 0) + return bytes_copied; - dma_q->last_sav = sav_eav; + dma_q->last_sav = sav_eav; - bytes_copied = cx231xx_copy_vbi_line(dev, dma_q, p_buffer, buffer_size, current_field); + bytes_copied = + cx231xx_copy_vbi_line(dev, dma_q, p_buffer, buffer_size, + current_field); - return bytes_copied; + return bytes_copied; } /* * Announces that a buffer were filled and request the next */ static inline void vbi_buffer_filled(struct cx231xx *dev, - struct cx231xx_dmaqueue *dma_q, - struct cx231xx_buffer *buf) + struct cx231xx_dmaqueue *dma_q, + struct cx231xx_buffer *buf) { /* Advice that buffer was filled */ /* cx231xx_info(DRIVER_NAME "[%p/%d] wakeup\n", buf, buf->vb.i); */ @@ -541,80 +553,83 @@ static inline void vbi_buffer_filled(struct cx231xx *dev, wake_up(&buf->vb.done); } -u32 cx231xx_copy_vbi_line(struct cx231xx *dev, struct cx231xx_dmaqueue *dma_q, - u8 *p_line, u32 length, int field_number) +u32 cx231xx_copy_vbi_line(struct cx231xx *dev, struct cx231xx_dmaqueue *dma_q, + u8 * p_line, u32 length, int field_number) { - u32 bytes_to_copy; - struct cx231xx_buffer *buf; - u32 _line_size = dev->width * 2; + u32 bytes_to_copy; + struct cx231xx_buffer *buf; + u32 _line_size = dev->width * 2; + + if (dma_q->current_field != field_number) { + cx231xx_reset_vbi_buffer(dev, dma_q); + } - if( dma_q->current_field != field_number ) { - cx231xx_reset_vbi_buffer(dev, dma_q); - } + /* get the buffer pointer */ + buf = dev->vbi_mode.isoc_ctl.buf; - /* get the buffer pointer */ - buf = dev->vbi_mode.isoc_ctl.buf; + /* Remember the field number for next time */ + dma_q->current_field = field_number; - /* Remember the field number for next time */ - dma_q->current_field = field_number; + bytes_to_copy = dma_q->bytes_left_in_line; + if (bytes_to_copy > length) + bytes_to_copy = length; - bytes_to_copy = dma_q->bytes_left_in_line; - if(bytes_to_copy > length) - bytes_to_copy = length; - - if(dma_q->lines_completed >= dma_q->lines_per_field) { - dma_q->bytes_left_in_line -= bytes_to_copy; - dma_q->is_partial_line = (dma_q->bytes_left_in_line == 0) ? 0 : 1; - return 0; - } + if (dma_q->lines_completed >= dma_q->lines_per_field) { + dma_q->bytes_left_in_line -= bytes_to_copy; + dma_q->is_partial_line = + (dma_q->bytes_left_in_line == 0) ? 0 : 1; + return 0; + } - dma_q->is_partial_line = 1; + dma_q->is_partial_line = 1; - /* If we don't have a buffer, just return the number of bytes we would - have copied if we had a buffer. */ - if(!buf) { - dma_q->bytes_left_in_line -= bytes_to_copy; - dma_q->is_partial_line = (dma_q->bytes_left_in_line == 0) ? 0 : 1; - return bytes_to_copy; - } + /* If we don't have a buffer, just return the number of bytes we would + have copied if we had a buffer. */ + if (!buf) { + dma_q->bytes_left_in_line -= bytes_to_copy; + dma_q->is_partial_line = + (dma_q->bytes_left_in_line == 0) ? 0 : 1; + return bytes_to_copy; + } - /* copy the data to video buffer */ - cx231xx_do_vbi_copy(dev, dma_q, p_line, bytes_to_copy); + /* copy the data to video buffer */ + cx231xx_do_vbi_copy(dev, dma_q, p_line, bytes_to_copy); - dma_q->pos += bytes_to_copy; - dma_q->bytes_left_in_line -= bytes_to_copy; + dma_q->pos += bytes_to_copy; + dma_q->bytes_left_in_line -= bytes_to_copy; - if(dma_q->bytes_left_in_line == 0) { + if (dma_q->bytes_left_in_line == 0) { - dma_q->bytes_left_in_line = _line_size; - dma_q->lines_completed++; - dma_q->is_partial_line = 0; + dma_q->bytes_left_in_line = _line_size; + dma_q->lines_completed++; + dma_q->is_partial_line = 0; - if(cx231xx_is_vbi_buffer_done(dev, dma_q) && buf ) { + if (cx231xx_is_vbi_buffer_done(dev, dma_q) && buf) { - vbi_buffer_filled(dev, dma_q, buf); + vbi_buffer_filled(dev, dma_q, buf); - dma_q->pos = 0; - buf = NULL; - dma_q->lines_completed = 0; - } - } + dma_q->pos = 0; + buf = NULL; + dma_q->lines_completed = 0; + } + } - return bytes_to_copy; + return bytes_to_copy; } /* * video-buf generic routine to get the next available buffer */ static inline void get_next_vbi_buf(struct cx231xx_dmaqueue *dma_q, - struct cx231xx_buffer **buf) + struct cx231xx_buffer **buf) { - struct cx231xx_video_mode *vmode = container_of(dma_q, struct cx231xx_video_mode, vidq); - struct cx231xx *dev = container_of(vmode, struct cx231xx, vbi_mode); + struct cx231xx_video_mode *vmode = + container_of(dma_q, struct cx231xx_video_mode, vidq); + struct cx231xx *dev = container_of(vmode, struct cx231xx, vbi_mode); char *outp; if (list_empty(&dma_q->active)) { - cx231xx_err(DRIVER_NAME ": No active queue to serve\n"); + cx231xx_err(DRIVER_NAME ": No active queue to serve\n"); dev->vbi_mode.isoc_ctl.buf = NULL; *buf = NULL; return; @@ -632,66 +647,70 @@ static inline void get_next_vbi_buf(struct cx231xx_dmaqueue *dma_q, return; } - -void cx231xx_reset_vbi_buffer(struct cx231xx *dev, struct cx231xx_dmaqueue *dma_q) +void cx231xx_reset_vbi_buffer(struct cx231xx *dev, + struct cx231xx_dmaqueue *dma_q) { - struct cx231xx_buffer *buf; - - buf = dev->vbi_mode.isoc_ctl.buf; - - if(buf == NULL) { - - /* first try to get the buffer */ - get_next_vbi_buf(dma_q, &buf); - - dma_q->pos = 0; - dma_q->current_field = -1; - } - - dma_q->bytes_left_in_line = dev->width << 1; - dma_q->lines_completed = 0; + struct cx231xx_buffer *buf; + + buf = dev->vbi_mode.isoc_ctl.buf; + + if (buf == NULL) { + + /* first try to get the buffer */ + get_next_vbi_buf(dma_q, &buf); + + dma_q->pos = 0; + dma_q->current_field = -1; + } + + dma_q->bytes_left_in_line = dev->width << 1; + dma_q->lines_completed = 0; } int cx231xx_do_vbi_copy(struct cx231xx *dev, struct cx231xx_dmaqueue *dma_q, - u8 *p_buffer, u32 bytes_to_copy) + u8 * p_buffer, u32 bytes_to_copy) { - u8 *p_out_buffer = NULL; - u32 current_line_bytes_copied = 0; - struct cx231xx_buffer *buf; - u32 _line_size = dev->width << 1; - void *startwrite; - int offset, lencopy; + u8 *p_out_buffer = NULL; + u32 current_line_bytes_copied = 0; + struct cx231xx_buffer *buf; + u32 _line_size = dev->width << 1; + void *startwrite; + int offset, lencopy; - buf = dev->vbi_mode.isoc_ctl.buf; + buf = dev->vbi_mode.isoc_ctl.buf; - if (buf == NULL) { - return -1; - } + if (buf == NULL) { + return -1; + } p_out_buffer = videobuf_to_vmalloc(&buf->vb); - if(dma_q->bytes_left_in_line != _line_size ) { - current_line_bytes_copied = _line_size - dma_q->bytes_left_in_line; - } + if (dma_q->bytes_left_in_line != _line_size) { + current_line_bytes_copied = + _line_size - dma_q->bytes_left_in_line; + } - offset = ( dma_q->lines_completed * _line_size ) + current_line_bytes_copied; + offset = + (dma_q->lines_completed * _line_size) + current_line_bytes_copied; - /* prepare destination address */ + /* prepare destination address */ startwrite = p_out_buffer + offset; - lencopy = dma_q->bytes_left_in_line > bytes_to_copy ? bytes_to_copy : dma_q->bytes_left_in_line; + lencopy = + dma_q->bytes_left_in_line > + bytes_to_copy ? bytes_to_copy : dma_q->bytes_left_in_line; - memcpy(startwrite, p_buffer, lencopy); + memcpy(startwrite, p_buffer, lencopy); - return 0; + return 0; } - -u8 cx231xx_is_vbi_buffer_done(struct cx231xx *dev,struct cx231xx_dmaqueue *dma_q) +u8 cx231xx_is_vbi_buffer_done(struct cx231xx * dev, + struct cx231xx_dmaqueue * dma_q) { - u32 height = 0; + u32 height = 0; - height = ((dev->norm & V4L2_STD_625_50) ? - PAL_VBI_LINES : NTSC_VBI_LINES) ; - return (dma_q->lines_completed == height)?1:0; + height = ((dev->norm & V4L2_STD_625_50) ? + PAL_VBI_LINES : NTSC_VBI_LINES); + return (dma_q->lines_completed == height) ? 1 : 0; } diff --git a/linux/drivers/media/video/cx231xx/cx231xx-vbi.h b/linux/drivers/media/video/cx231xx/cx231xx-vbi.h index 5faffaea0..c0d89b1e2 100644 --- a/linux/drivers/media/video/cx231xx/cx231xx-vbi.h +++ b/linux/drivers/media/video/cx231xx/cx231xx-vbi.h @@ -2,7 +2,7 @@ cx231xx_vbi.h - driver for Conexant Cx23100/101/102 USB video capture devices Copyright (C) 2008 - Based on cx88 driver + Based on cx88 driver 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 @@ -24,8 +24,7 @@ extern struct videobuf_queue_ops cx231xx_vbi_qops; - -#define NTSC_VBI_START_LINE 10 /* line 10 - 21 */ +#define NTSC_VBI_START_LINE 10 /* line 10 - 21 */ #define NTSC_VBI_END_LINE 21 #define NTSC_VBI_LINES (NTSC_VBI_END_LINE - NTSC_VBI_START_LINE + 1) @@ -41,21 +40,24 @@ extern struct videobuf_queue_ops cx231xx_vbi_qops; /* stream functions */ int cx231xx_init_vbi_isoc(struct cx231xx *dev, int max_packets, - int num_bufs, int max_pkt_size, - int (*isoc_copy) (struct cx231xx *dev, struct urb *urb)); + int num_bufs, int max_pkt_size, + int (*isoc_copy) (struct cx231xx * dev, + struct urb * urb)); void cx231xx_uninit_vbi_isoc(struct cx231xx *dev); /* vbi data copy functions */ -u32 cx231xx_get_vbi_line(struct cx231xx *dev, struct cx231xx_dmaqueue *dma_q, - u8 sav_eav, u8 *p_buffer, u32 buffer_size); -u32 cx231xx_copy_vbi_line(struct cx231xx *dev, struct cx231xx_dmaqueue *dma_q, - u8 *p_line, u32 length, int field_number); -void cx231xx_reset_vbi_buffer(struct cx231xx *dev, struct cx231xx_dmaqueue *dma_q); +u32 cx231xx_get_vbi_line(struct cx231xx *dev, struct cx231xx_dmaqueue *dma_q, + u8 sav_eav, u8 * p_buffer, u32 buffer_size); +u32 cx231xx_copy_vbi_line(struct cx231xx *dev, struct cx231xx_dmaqueue *dma_q, + u8 * p_line, u32 length, int field_number); +void cx231xx_reset_vbi_buffer(struct cx231xx *dev, + struct cx231xx_dmaqueue *dma_q); int cx231xx_do_vbi_copy(struct cx231xx *dev, struct cx231xx_dmaqueue *dma_q, - u8 *p_buffer, u32 bytes_to_copy); + u8 * p_buffer, u32 bytes_to_copy); -u8 cx231xx_is_vbi_buffer_done(struct cx231xx *dev,struct cx231xx_dmaqueue *dma_q); +u8 cx231xx_is_vbi_buffer_done(struct cx231xx *dev, + struct cx231xx_dmaqueue *dma_q); -#endif \ No newline at end of file +#endif diff --git a/linux/drivers/media/video/cx231xx/cx231xx-video.c b/linux/drivers/media/video/cx231xx/cx231xx-video.c index 2e8cba88d..4e0850e1c 100644 --- a/linux/drivers/media/video/cx231xx/cx231xx-video.c +++ b/linux/drivers/media/video/cx231xx/cx231xx-video.c @@ -2,9 +2,9 @@ cx231xx-video.c - driver for Conexant Cx23100/101/102 USB video capture devices Copyright (C) 2008 - Based on em28xx driver - Based on cx23885 driver - Based on cx88 driver + Based on em28xx driver + Based on cx23885 driver + Based on cx88 driver 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 @@ -21,7 +21,6 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ - #include #include #include @@ -44,11 +43,9 @@ #include "cx231xx.h" #include "cx231xx-vbi.h" - #define DRIVER_AUTHOR "Srinivasa Deevi " #define DRIVER_DESC "Conexant cx231xx based USB video device driver" - #define cx231xx_videodbg(fmt, arg...) do {\ if (video_debug) \ printk(KERN_INFO "%s %s :"fmt, \ @@ -70,138 +67,133 @@ MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); - - static unsigned int card[] = {[0 ... (CX231XX_MAXBOARDS - 1)] = UNSET }; static unsigned int video_nr[] = {[0 ... (CX231XX_MAXBOARDS - 1)] = UNSET }; static unsigned int vbi_nr[] = {[0 ... (CX231XX_MAXBOARDS - 1)] = UNSET }; static unsigned int radio_nr[] = {[0 ... (CX231XX_MAXBOARDS - 1)] = UNSET }; -module_param_array(card, int, NULL, 0444); +module_param_array(card, int, NULL, 0444); module_param_array(video_nr, int, NULL, 0444); module_param_array(vbi_nr, int, NULL, 0444); module_param_array(radio_nr, int, NULL, 0444); -MODULE_PARM_DESC(card, "card type"); +MODULE_PARM_DESC(card, "card type"); MODULE_PARM_DESC(video_nr, "video device numbers"); -MODULE_PARM_DESC(vbi_nr, "vbi device numbers"); +MODULE_PARM_DESC(vbi_nr, "vbi device numbers"); MODULE_PARM_DESC(radio_nr, "radio device numbers"); static unsigned int video_debug; module_param(video_debug, int, 0644); MODULE_PARM_DESC(video_debug, "enable debug messages [video]"); - - /* supported video standards */ static struct cx231xx_fmt format[] = { { - .name = "16bpp YUY2, 4:2:2, packed", - .fourcc = V4L2_PIX_FMT_YUYV, - .depth = 16, - .reg = 0, - }, + .name = "16bpp YUY2, 4:2:2, packed", + .fourcc = V4L2_PIX_FMT_YUYV, + .depth = 16, + .reg = 0, + }, }; - /* supported controls */ /* Common to all boards */ /* ------------------------------------------------------------------- */ static const struct v4l2_queryctrl no_ctl = { - .name = "42", + .name = "42", .flags = V4L2_CTRL_FLAG_DISABLED, }; static struct cx231xx_ctrl cx231xx_ctls[] = { /* --- video --- */ { - .v = { - .id = V4L2_CID_BRIGHTNESS, - .name = "Brightness", - .minimum = 0x00, - .maximum = 0xff, - .step = 1, - .default_value = 0x7f, - .type = V4L2_CTRL_TYPE_INTEGER, - }, - .off = 128, - .reg = LUMA_CTRL, - .mask = 0x00ff, - .shift = 0, - }, { - .v = { - .id = V4L2_CID_CONTRAST, - .name = "Contrast", - .minimum = 0, - .maximum = 0xff, - .step = 1, - .default_value = 0x3f, - .type = V4L2_CTRL_TYPE_INTEGER, - }, - .off = 0, - .reg = LUMA_CTRL, - .mask = 0xff00, - .shift = 8, - }, { - .v = { - .id = V4L2_CID_HUE, - .name = "Hue", - .minimum = 0, - .maximum = 0xff, - .step = 1, - .default_value = 0x7f, - .type = V4L2_CTRL_TYPE_INTEGER, - }, - .off = 128, - .reg = CHROMA_CTRL, - .mask = 0xff0000, - .shift = 16, - }, { - /* strictly, this only describes only U saturation. - * V saturation is handled specially through code. - */ - .v = { - .id = V4L2_CID_SATURATION, - .name = "Saturation", - .minimum = 0, - .maximum = 0xff, - .step = 1, - .default_value = 0x7f, - .type = V4L2_CTRL_TYPE_INTEGER, - }, - .off = 0, - .reg = CHROMA_CTRL, - .mask = 0x00ff, - .shift = 0, - }, { - /* --- audio --- */ - .v = { - .id = V4L2_CID_AUDIO_MUTE, - .name = "Mute", - .minimum = 0, - .maximum = 1, - .default_value = 1, - .type = V4L2_CTRL_TYPE_BOOLEAN, - }, - .reg = PATH1_CTL1, - .mask = (0x1f << 24), - .shift = 24, - }, { - .v = { - .id = V4L2_CID_AUDIO_VOLUME, - .name = "Volume", - .minimum = 0, - .maximum = 0x3f, - .step = 1, - .default_value = 0x3f, - .type = V4L2_CTRL_TYPE_INTEGER, - }, - .reg = PATH1_VOL_CTL, - .mask = 0xff, - .shift = 0, - } + .v = { + .id = V4L2_CID_BRIGHTNESS, + .name = "Brightness", + .minimum = 0x00, + .maximum = 0xff, + .step = 1, + .default_value = 0x7f, + .type = V4L2_CTRL_TYPE_INTEGER, + }, + .off = 128, + .reg = LUMA_CTRL, + .mask = 0x00ff, + .shift = 0, + }, { + .v = { + .id = V4L2_CID_CONTRAST, + .name = "Contrast", + .minimum = 0, + .maximum = 0xff, + .step = 1, + .default_value = 0x3f, + .type = V4L2_CTRL_TYPE_INTEGER, + }, + .off = 0, + .reg = LUMA_CTRL, + .mask = 0xff00, + .shift = 8, + }, { + .v = { + .id = V4L2_CID_HUE, + .name = "Hue", + .minimum = 0, + .maximum = 0xff, + .step = 1, + .default_value = 0x7f, + .type = V4L2_CTRL_TYPE_INTEGER, + }, + .off = 128, + .reg = CHROMA_CTRL, + .mask = 0xff0000, + .shift = 16, + }, { + /* strictly, this only describes only U saturation. + * V saturation is handled specially through code. + */ + .v = { + .id = V4L2_CID_SATURATION, + .name = "Saturation", + .minimum = 0, + .maximum = 0xff, + .step = 1, + .default_value = 0x7f, + .type = V4L2_CTRL_TYPE_INTEGER, + }, + .off = 0, + .reg = CHROMA_CTRL, + .mask = 0x00ff, + .shift = 0, + }, { + /* --- audio --- */ + .v = { + .id = V4L2_CID_AUDIO_MUTE, + .name = "Mute", + .minimum = 0, + .maximum = 1, + .default_value = 1, + .type = V4L2_CTRL_TYPE_BOOLEAN, + }, + .reg = PATH1_CTL1, + .mask = (0x1f << 24), + .shift = 24, + }, { + .v = { + .id = V4L2_CID_AUDIO_VOLUME, + .name = "Volume", + .minimum = 0, + .maximum = 0x3f, + .step = 1, + .default_value = 0x3f, + .type = V4L2_CTRL_TYPE_INTEGER, + }, + .reg = PATH1_VOL_CTL, + .mask = 0xff, + .shift = 0, + } }; static const int CX231XX_CTLS = ARRAY_SIZE(cx231xx_ctls); @@ -212,7 +204,7 @@ static const u32 cx231xx_user_ctrls[] = { V4L2_CID_SATURATION, V4L2_CID_HUE, V4L2_CID_AUDIO_VOLUME, -#if 0 /* Keep */ +#if 0 /* Keep */ V4L2_CID_AUDIO_BALANCE, #endif V4L2_CID_AUDIO_MUTE, @@ -224,7 +216,6 @@ static const u32 *ctrl_classes[] = { NULL }; - /* ------------------------------------------------------------------ Video buffer and parser functions ------------------------------------------------------------------*/ @@ -233,8 +224,8 @@ static const u32 *ctrl_classes[] = { * Announces that a buffer were filled and request the next */ static inline void buffer_filled(struct cx231xx *dev, - struct cx231xx_dmaqueue *dma_q, - struct cx231xx_buffer *buf) + struct cx231xx_dmaqueue *dma_q, + struct cx231xx_buffer *buf) { /* Advice that buffer was filled */ cx231xx_isocdbg("[%p/%d] wakeup\n", buf, buf->vb.i); @@ -248,9 +239,7 @@ static inline void buffer_filled(struct cx231xx *dev, wake_up(&buf->vb.done); } - -static inline void print_err_status(struct cx231xx *dev, - int packet, int status) +static inline void print_err_status(struct cx231xx *dev, int packet, int status) { char *errmsg = "Unknown"; @@ -281,10 +270,10 @@ static inline void print_err_status(struct cx231xx *dev, break; } if (packet < 0) { - cx231xx_isocdbg("URB status %d [%s].\n", status, errmsg); + cx231xx_isocdbg("URB status %d [%s].\n", status, errmsg); } else { cx231xx_isocdbg("URB packet %d, status %d [%s].\n", - packet, status, errmsg); + packet, status, errmsg); } } @@ -292,14 +281,14 @@ static inline void print_err_status(struct cx231xx *dev, * video-buf generic routine to get the next available buffer */ static inline void get_next_buf(struct cx231xx_dmaqueue *dma_q, - struct cx231xx_buffer **buf) + struct cx231xx_buffer **buf) { - struct cx231xx_video_mode *vmode = container_of(dma_q, struct cx231xx_video_mode, vidq); - struct cx231xx *dev = container_of(vmode, struct cx231xx, video_mode); + struct cx231xx_video_mode *vmode = + container_of(dma_q, struct cx231xx_video_mode, vidq); + struct cx231xx *dev = container_of(vmode, struct cx231xx, video_mode); char *outp; - if (list_empty(&dma_q->active)) { cx231xx_isocdbg("No active queue to serve\n"); dev->video_mode.isoc_ctl.buf = NULL; @@ -324,13 +313,13 @@ static inline void get_next_buf(struct cx231xx_dmaqueue *dma_q, */ static inline int cx231xx_isoc_copy(struct cx231xx *dev, struct urb *urb) { - struct cx231xx_buffer *buf; - struct cx231xx_dmaqueue *dma_q = urb->context; + struct cx231xx_buffer *buf; + struct cx231xx_dmaqueue *dma_q = urb->context; unsigned char *outp = NULL; - int i, rc = 1; + int i, rc = 1; unsigned char *p_buffer; - u32 bytes_parsed = 0, buffer_size = 0; - u8 sav_eav = 0; + u32 bytes_parsed = 0, buffer_size = 0; + u8 sav_eav = 0; if (!dev) return 0; @@ -357,342 +346,347 @@ static inline int cx231xx_isoc_copy(struct cx231xx *dev, struct urb *urb) continue; } - if (urb->iso_frame_desc[i].actual_length <= 0) { + if (urb->iso_frame_desc[i].actual_length <= 0) { /* cx231xx_isocdbg("packet %d is empty",i); - spammy */ continue; } if (urb->iso_frame_desc[i].actual_length > - dev->video_mode.max_pkt_size) { + dev->video_mode.max_pkt_size) { cx231xx_isocdbg("packet bigger than packet size"); continue; } - /* get buffer pointer and length */ + /* get buffer pointer and length */ p_buffer = urb->transfer_buffer + urb->iso_frame_desc[i].offset; - buffer_size = urb->iso_frame_desc[i].actual_length; - bytes_parsed = 0; - - if(dma_q->is_partial_line) - { - /* Handle the case where we were working on a partial line */ - sav_eav = dma_q->last_sav; - } else { - /* Check for a SAV/EAV overlapping the buffer boundary */ - sav_eav = cx231xx_find_boundary_SAV_EAV(p_buffer, dma_q->partial_buf, &bytes_parsed); - } - - sav_eav &= 0xF0; - /* Get the first line if we have some portion of an SAV/EAV from the last buffer - or a partial line */ - if(sav_eav) { - bytes_parsed += cx231xx_get_video_line(dev, dma_q, - sav_eav, /* SAV/EAV */ - p_buffer + bytes_parsed, /* p_buffer */ - buffer_size - bytes_parsed); /* buffer size */ - } - - /* Now parse data that is completely in this buffer */ - /* dma_q->is_partial_line = 0; */ - - while(bytes_parsed < buffer_size) - { - u32 bytes_used = 0; - - sav_eav = cx231xx_find_next_SAV_EAV( - p_buffer + bytes_parsed, /* p_buffer */ - buffer_size - bytes_parsed, /* buffer size */ - &bytes_used); /* Receives bytes used to get SAV/EAV */ - - bytes_parsed += bytes_used; - - sav_eav &= 0xF0; - if(sav_eav && (bytes_parsed < buffer_size)) - { - bytes_parsed += cx231xx_get_video_line(dev, dma_q, - sav_eav, /* SAV/EAV */ - p_buffer + bytes_parsed, /* p_buffer */ - buffer_size - bytes_parsed); /* buffer size */ - } - } - - /* Save the last four bytes of the buffer so we can check the buffer boundary - condition next time */ - memcpy(dma_q->partial_buf, p_buffer + buffer_size - 4, 4); - bytes_parsed = 0; + buffer_size = urb->iso_frame_desc[i].actual_length; + bytes_parsed = 0; + + if (dma_q->is_partial_line) { + /* Handle the case where we were working on a partial line */ + sav_eav = dma_q->last_sav; + } else { + /* Check for a SAV/EAV overlapping the buffer boundary */ + sav_eav = + cx231xx_find_boundary_SAV_EAV(p_buffer, + dma_q->partial_buf, + &bytes_parsed); + } - } - return rc; -} + sav_eav &= 0xF0; + /* Get the first line if we have some portion of an SAV/EAV from the last buffer + or a partial line */ + if (sav_eav) { + bytes_parsed += cx231xx_get_video_line(dev, dma_q, sav_eav, /* SAV/EAV */ + p_buffer + bytes_parsed, /* p_buffer */ + buffer_size - bytes_parsed); /* buffer size */ + } -u8 cx231xx_find_boundary_SAV_EAV(u8 *p_buffer, u8 *partial_buf, u32 *p_bytes_used) -{ - u32 bytes_used; - u8 boundary_bytes[8]; - u8 sav_eav = 0; - - *p_bytes_used = 0; + /* Now parse data that is completely in this buffer */ + /* dma_q->is_partial_line = 0; */ - /* Create an array of the last 4 bytes of the last buffer and the first - 4 bytes of the current buffer. */ - - memcpy(boundary_bytes, partial_buf, 4); - memcpy(boundary_bytes + 4, p_buffer, 4); + while (bytes_parsed < buffer_size) { + u32 bytes_used = 0; - /* Check for the SAV/EAV in the boundary buffer */ - sav_eav = cx231xx_find_next_SAV_EAV((u8*)&boundary_bytes, 8, &bytes_used); + sav_eav = cx231xx_find_next_SAV_EAV(p_buffer + bytes_parsed, /* p_buffer */ + buffer_size - bytes_parsed, /* buffer size */ + &bytes_used); /* Receives bytes used to get SAV/EAV */ + + bytes_parsed += bytes_used; + + sav_eav &= 0xF0; + if (sav_eav && (bytes_parsed < buffer_size)) { + bytes_parsed += cx231xx_get_video_line(dev, dma_q, sav_eav, /* SAV/EAV */ + p_buffer + bytes_parsed, /* p_buffer */ + buffer_size - bytes_parsed); /* buffer size */ + } + } - if(sav_eav) { - /* found a boundary SAV/EAV. Updates the bytes used to reflect - only those used in the new buffer */ - *p_bytes_used = bytes_used - 4; - } + /* Save the last four bytes of the buffer so we can check the buffer boundary + condition next time */ + memcpy(dma_q->partial_buf, p_buffer + buffer_size - 4, 4); + bytes_parsed = 0; - return sav_eav; + } + return rc; } -u8 cx231xx_find_next_SAV_EAV(u8 *p_buffer, u32 buffer_size, u32 *p_bytes_used) +u8 cx231xx_find_boundary_SAV_EAV(u8 * p_buffer, u8 * partial_buf, + u32 * p_bytes_used) { - u32 i; - u8 sav_eav = 0; + u32 bytes_used; + u8 boundary_bytes[8]; + u8 sav_eav = 0; - /* Don't search if the buffer size is less than 4. It causes a page fault since - buffer_size - 4 evaluates to a large number in that case. */ - if(buffer_size < 4) { - *p_bytes_used = buffer_size; - return 0; - } + *p_bytes_used = 0; - for(i = 0;i < (buffer_size - 3); i++) { + /* Create an array of the last 4 bytes of the last buffer and the first + 4 bytes of the current buffer. */ - if((p_buffer[i] == 0xFF) && - (p_buffer[i+1] == 0x00) && - (p_buffer[i+2] == 0x00)) { + memcpy(boundary_bytes, partial_buf, 4); + memcpy(boundary_bytes + 4, p_buffer, 4); - *p_bytes_used = i+4; - sav_eav = p_buffer[i+3]; - return sav_eav; - } - } + /* Check for the SAV/EAV in the boundary buffer */ + sav_eav = + cx231xx_find_next_SAV_EAV((u8 *) & boundary_bytes, 8, &bytes_used); + + if (sav_eav) { + /* found a boundary SAV/EAV. Updates the bytes used to reflect + only those used in the new buffer */ + *p_bytes_used = bytes_used - 4; + } - *p_bytes_used = buffer_size; - return 0; + return sav_eav; } +u8 cx231xx_find_next_SAV_EAV(u8 * p_buffer, u32 buffer_size, u32 * p_bytes_used) +{ + u32 i; + u8 sav_eav = 0; + /* Don't search if the buffer size is less than 4. It causes a page fault since + buffer_size - 4 evaluates to a large number in that case. */ + if (buffer_size < 4) { + *p_bytes_used = buffer_size; + return 0; + } + for (i = 0; i < (buffer_size - 3); i++) { -u32 cx231xx_get_video_line(struct cx231xx *dev, struct cx231xx_dmaqueue *dma_q, - u8 sav_eav, u8 *p_buffer, u32 buffer_size) -{ - u32 bytes_copied = 0; - int current_field = -1; - + if ((p_buffer[i] == 0xFF) && + (p_buffer[i + 1] == 0x00) && (p_buffer[i + 2] == 0x00)) { + + *p_bytes_used = i + 4; + sav_eav = p_buffer[i + 3]; + return sav_eav; + } + } + + *p_bytes_used = buffer_size; + return 0; +} - switch(sav_eav) { - case SAV_ACTIVE_VIDEO_FIELD1: - /* looking for skipped line which occurred in PAL 720x480 mode. In this case, - there will be no active data contained between the SAV and EAV */ - if ( (buffer_size > 3) && - (p_buffer[0] == 0xFF) && (p_buffer[1] == 0x00) && (p_buffer[2] == 0x00) && - ( (p_buffer[3] == EAV_ACTIVE_VIDEO_FIELD1) || (p_buffer[3] == EAV_ACTIVE_VIDEO_FIELD2) || - (p_buffer[3] == EAV_VBLANK_FIELD1) || (p_buffer[3] == EAV_VBLANK_FIELD2) - ) - ) - { - return bytes_copied; - } - current_field = 1; - break; +u32 cx231xx_get_video_line(struct cx231xx * dev, + struct cx231xx_dmaqueue * dma_q, u8 sav_eav, + u8 * p_buffer, u32 buffer_size) +{ + u32 bytes_copied = 0; + int current_field = -1; + + switch (sav_eav) { + case SAV_ACTIVE_VIDEO_FIELD1: + /* looking for skipped line which occurred in PAL 720x480 mode. In this case, + there will be no active data contained between the SAV and EAV */ + if ((buffer_size > 3) && + (p_buffer[0] == 0xFF) && (p_buffer[1] == 0x00) + && (p_buffer[2] == 0x00) + && ((p_buffer[3] == EAV_ACTIVE_VIDEO_FIELD1) + || (p_buffer[3] == EAV_ACTIVE_VIDEO_FIELD2) + || (p_buffer[3] == EAV_VBLANK_FIELD1) + || (p_buffer[3] == EAV_VBLANK_FIELD2) + ) + ) { + return bytes_copied; + } + current_field = 1; + break; - case SAV_ACTIVE_VIDEO_FIELD2: - /* looking for skipped line which occurred in PAL 720x480 mode. In this case, - there will be no active data contained between the SAV and EAV */ - if ( (buffer_size > 3) && - (p_buffer[0] == 0xFF) && (p_buffer[1] == 0x00) && (p_buffer[2] == 0x00) && - ( (p_buffer[3] == EAV_ACTIVE_VIDEO_FIELD1) || (p_buffer[3] == EAV_ACTIVE_VIDEO_FIELD2) || - (p_buffer[3] == EAV_VBLANK_FIELD1) || (p_buffer[3] == EAV_VBLANK_FIELD2) - ) - ) - { - return bytes_copied; - } - current_field = 2; - break; - } + case SAV_ACTIVE_VIDEO_FIELD2: + /* looking for skipped line which occurred in PAL 720x480 mode. In this case, + there will be no active data contained between the SAV and EAV */ + if ((buffer_size > 3) && + (p_buffer[0] == 0xFF) && (p_buffer[1] == 0x00) + && (p_buffer[2] == 0x00) + && ((p_buffer[3] == EAV_ACTIVE_VIDEO_FIELD1) + || (p_buffer[3] == EAV_ACTIVE_VIDEO_FIELD2) + || (p_buffer[3] == EAV_VBLANK_FIELD1) + || (p_buffer[3] == EAV_VBLANK_FIELD2) + ) + ) { + return bytes_copied; + } + current_field = 2; + break; + } - dma_q->last_sav = sav_eav; + dma_q->last_sav = sav_eav; - bytes_copied = cx231xx_copy_video_line(dev, dma_q, p_buffer, buffer_size, current_field); + bytes_copied = + cx231xx_copy_video_line(dev, dma_q, p_buffer, buffer_size, + current_field); - return bytes_copied; + return bytes_copied; } -u32 cx231xx_copy_video_line(struct cx231xx *dev, struct cx231xx_dmaqueue *dma_q, - u8 *p_line, u32 length, int field_number) +u32 cx231xx_copy_video_line(struct cx231xx * dev, + struct cx231xx_dmaqueue * dma_q, u8 * p_line, + u32 length, int field_number) { - u32 bytes_to_copy; - struct cx231xx_buffer *buf; - u32 _line_size = dev->width * 2; - - if( dma_q->current_field != field_number ) { - cx231xx_reset_video_buffer(dev, dma_q); - } + u32 bytes_to_copy; + struct cx231xx_buffer *buf; + u32 _line_size = dev->width * 2; - /* get the buffer pointer */ - buf = dev->video_mode.isoc_ctl.buf; + if (dma_q->current_field != field_number) { + cx231xx_reset_video_buffer(dev, dma_q); + } - /* Remember the field number for next time */ - dma_q->current_field = field_number; + /* get the buffer pointer */ + buf = dev->video_mode.isoc_ctl.buf; - bytes_to_copy = dma_q->bytes_left_in_line; - if(bytes_to_copy > length) - bytes_to_copy = length; + /* Remember the field number for next time */ + dma_q->current_field = field_number; + bytes_to_copy = dma_q->bytes_left_in_line; + if (bytes_to_copy > length) + bytes_to_copy = length; - if(dma_q->lines_completed >= dma_q->lines_per_field) { - dma_q->bytes_left_in_line -= bytes_to_copy; - dma_q->is_partial_line = (dma_q->bytes_left_in_line == 0) ? 0 : 1; - return 0; - } + if (dma_q->lines_completed >= dma_q->lines_per_field) { + dma_q->bytes_left_in_line -= bytes_to_copy; + dma_q->is_partial_line = + (dma_q->bytes_left_in_line == 0) ? 0 : 1; + return 0; + } - dma_q->is_partial_line = 1; + dma_q->is_partial_line = 1; - /* If we don't have a buffer, just return the number of bytes we would - have copied if we had a buffer. */ - if(!buf) - { - dma_q->bytes_left_in_line -= bytes_to_copy; - dma_q->is_partial_line = (dma_q->bytes_left_in_line == 0) ? 0 : 1; - return bytes_to_copy; - } + /* If we don't have a buffer, just return the number of bytes we would + have copied if we had a buffer. */ + if (!buf) { + dma_q->bytes_left_in_line -= bytes_to_copy; + dma_q->is_partial_line = + (dma_q->bytes_left_in_line == 0) ? 0 : 1; + return bytes_to_copy; + } - /* copy the data to video buffer */ - cx231xx_do_copy(dev, dma_q, p_line, bytes_to_copy); + /* copy the data to video buffer */ + cx231xx_do_copy(dev, dma_q, p_line, bytes_to_copy); - dma_q->pos += bytes_to_copy; - dma_q->bytes_left_in_line -= bytes_to_copy; + dma_q->pos += bytes_to_copy; + dma_q->bytes_left_in_line -= bytes_to_copy; - if(dma_q->bytes_left_in_line == 0) { + if (dma_q->bytes_left_in_line == 0) { - dma_q->bytes_left_in_line = _line_size; - dma_q->lines_completed++; - dma_q->is_partial_line = 0; + dma_q->bytes_left_in_line = _line_size; + dma_q->lines_completed++; + dma_q->is_partial_line = 0; - if(cx231xx_is_buffer_done(dev, dma_q) && buf) { + if (cx231xx_is_buffer_done(dev, dma_q) && buf) { - buffer_filled(dev, dma_q, buf); + buffer_filled(dev, dma_q, buf); - dma_q->pos = 0; - buf = NULL; - dma_q->lines_completed = 0; - } - } + dma_q->pos = 0; + buf = NULL; + dma_q->lines_completed = 0; + } + } - return bytes_to_copy; + return bytes_to_copy; } -void cx231xx_reset_video_buffer(struct cx231xx *dev, struct cx231xx_dmaqueue *dma_q) +void cx231xx_reset_video_buffer(struct cx231xx *dev, + struct cx231xx_dmaqueue *dma_q) { - struct cx231xx_buffer *buf; + struct cx231xx_buffer *buf; - /* handle the switch from field 1 to field 2 */ - if(dma_q->current_field == 1) { - if(dma_q->lines_completed >= dma_q->lines_per_field ) { - dma_q->field1_done = 1; - } else { - dma_q->field1_done = 0; - } - } + /* handle the switch from field 1 to field 2 */ + if (dma_q->current_field == 1) { + if (dma_q->lines_completed >= dma_q->lines_per_field) { + dma_q->field1_done = 1; + } else { + dma_q->field1_done = 0; + } + } - buf = dev->video_mode.isoc_ctl.buf; + buf = dev->video_mode.isoc_ctl.buf; - if(buf == NULL) { - u8* outp = NULL; - /* first try to get the buffer */ - get_next_buf(dma_q, &buf); + if (buf == NULL) { + u8 *outp = NULL; + /* first try to get the buffer */ + get_next_buf(dma_q, &buf); - if(buf) - outp = videobuf_to_vmalloc(&buf->vb); + if (buf) + outp = videobuf_to_vmalloc(&buf->vb); - dma_q->pos = 0; - dma_q->field1_done = 0; - dma_q->current_field = -1; - } + dma_q->pos = 0; + dma_q->field1_done = 0; + dma_q->current_field = -1; + } - /* reset the counters */ - dma_q->bytes_left_in_line = dev->width << 1; - dma_q->lines_completed = 0; + /* reset the counters */ + dma_q->bytes_left_in_line = dev->width << 1; + dma_q->lines_completed = 0; } int cx231xx_do_copy(struct cx231xx *dev, struct cx231xx_dmaqueue *dma_q, - u8 *p_buffer, u32 bytes_to_copy) + u8 * p_buffer, u32 bytes_to_copy) { - u8 *p_out_buffer = NULL; - u32 current_line_bytes_copied = 0; - struct cx231xx_buffer *buf; - u32 _line_size = dev->width << 1; - void *startwrite; - int offset, lencopy; + u8 *p_out_buffer = NULL; + u32 current_line_bytes_copied = 0; + struct cx231xx_buffer *buf; + u32 _line_size = dev->width << 1; + void *startwrite; + int offset, lencopy; - buf = dev->video_mode.isoc_ctl.buf; + buf = dev->video_mode.isoc_ctl.buf; - if (buf == NULL) - return -1; + if (buf == NULL) + return -1; p_out_buffer = videobuf_to_vmalloc(&buf->vb); - current_line_bytes_copied = _line_size - dma_q->bytes_left_in_line; + current_line_bytes_copied = _line_size - dma_q->bytes_left_in_line; - /* Offset field 2 one line from the top of the buffer */ - offset = (dma_q->current_field == 1)? 0: _line_size; + /* Offset field 2 one line from the top of the buffer */ + offset = (dma_q->current_field == 1) ? 0 : _line_size; - /* Offset for field 2 */ - startwrite = p_out_buffer + offset; + /* Offset for field 2 */ + startwrite = p_out_buffer + offset; - /* lines already completed in the current field */ - startwrite += (dma_q->lines_completed * _line_size * 2); + /* lines already completed in the current field */ + startwrite += (dma_q->lines_completed * _line_size * 2); - /* bytes already completed in the current line */ - startwrite += current_line_bytes_copied; + /* bytes already completed in the current line */ + startwrite += current_line_bytes_copied; - lencopy = dma_q->bytes_left_in_line > bytes_to_copy ? bytes_to_copy : dma_q->bytes_left_in_line; + lencopy = + dma_q->bytes_left_in_line > + bytes_to_copy ? bytes_to_copy : dma_q->bytes_left_in_line; - if( (u8*)(startwrite +lencopy) > (u8*)(p_out_buffer+ buf->vb.size) ) { - return 0; - } + if ((u8 *) (startwrite + lencopy) > + (u8 *) (p_out_buffer + buf->vb.size)) { + return 0; + } - /* The below copies the UYVY data straight into video buffer */ - cx231xx_swab( (u16*)p_buffer, (u16*)startwrite, (u16)lencopy); - - return 0; + /* The below copies the UYVY data straight into video buffer */ + cx231xx_swab((u16 *) p_buffer, (u16 *) startwrite, (u16) lencopy); + + return 0; } -void cx231xx_swab(u16 *from, u16 *to, u16 len) +void cx231xx_swab(u16 * from, u16 * to, u16 len) { - u16 i; + u16 i; - if( len <= 0) - return; + if (len <= 0) + return; - for(i = 0; i < len/2; i++) { - to[i] = (from[i] << 8) | (from[i] >> 8); - } + for (i = 0; i < len / 2; i++) { + to[i] = (from[i] << 8) | (from[i] >> 8); + } } -u8 cx231xx_is_buffer_done(struct cx231xx *dev,struct cx231xx_dmaqueue *dma_q) +u8 cx231xx_is_buffer_done(struct cx231xx *dev, struct cx231xx_dmaqueue *dma_q) { - u8 buffer_complete = 0; + u8 buffer_complete = 0; - /* Dual field stream */ - buffer_complete = - ((dma_q->current_field == 2) && - (dma_q->lines_completed >= dma_q->lines_per_field) && - dma_q->field1_done); + /* Dual field stream */ + buffer_complete = + ((dma_q->current_field == 2) && + (dma_q->lines_completed >= dma_q->lines_per_field) && + dma_q->field1_done); - return buffer_complete; + return buffer_complete; } - /* ------------------------------------------------------------------ Videobuf operations ------------------------------------------------------------------*/ @@ -701,10 +695,11 @@ static int buffer_setup(struct videobuf_queue *vq, unsigned int *count, unsigned int *size) { struct cx231xx_fh *fh = vq->priv_data; - struct cx231xx *dev = fh->dev; + struct cx231xx *dev = fh->dev; struct v4l2_frequency f; - *size = ( fh->dev->width * fh->dev->height * dev->format->depth + 7) >> 3; + *size = + (fh->dev->width * fh->dev->height * dev->format->depth + 7) >> 3; if (0 == *count) *count = CX231XX_DEF_BUF; @@ -714,7 +709,7 @@ buffer_setup(struct videobuf_queue *vq, unsigned int *count, unsigned int *size) /* Ask tuner to go to analog mode */ memset(&f, 0, sizeof(f)); f.frequency = dev->ctl_freq; - f.type = fh->radio ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV; + f.type = fh->radio ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV; cx231xx_i2c_call_clients(&dev->i2c_bus[1], VIDIOC_S_FREQUENCY, &f); @@ -724,8 +719,8 @@ buffer_setup(struct videobuf_queue *vq, unsigned int *count, unsigned int *size) /* This is called *without* dev->slock held; please keep it that way */ static void free_buffer(struct videobuf_queue *vq, struct cx231xx_buffer *buf) { - struct cx231xx_fh *fh = vq->priv_data; - struct cx231xx *dev = fh->dev; + struct cx231xx_fh *fh = vq->priv_data; + struct cx231xx *dev = fh->dev; unsigned long flags = 0; if (in_interrupt()) BUG(); @@ -738,7 +733,7 @@ static void free_buffer(struct videobuf_queue *vq, struct cx231xx_buffer *buf) This should be safe; by the time we get here, the buffer isn't queued anymore. If we ever start marking the buffers as VIDEOBUF_ACTIVE, it won't be, though. - */ + */ spin_lock_irqsave(&dev->video_mode.slock, flags); if (dev->video_mode.isoc_ctl.buf == buf) dev->video_mode.isoc_ctl.buf = NULL; @@ -750,22 +745,24 @@ static void free_buffer(struct videobuf_queue *vq, struct cx231xx_buffer *buf) static int buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb, - enum v4l2_field field) + enum v4l2_field field) { - struct cx231xx_fh *fh = vq->priv_data; - struct cx231xx_buffer *buf = container_of(vb, struct cx231xx_buffer, vb); - struct cx231xx *dev = fh->dev; - int rc = 0, urb_init = 0; + struct cx231xx_fh *fh = vq->priv_data; + struct cx231xx_buffer *buf = + container_of(vb, struct cx231xx_buffer, vb); + struct cx231xx *dev = fh->dev; + int rc = 0, urb_init = 0; /* The only currently supported format is 16 bits/pixel */ - buf->vb.size = (fh->dev->width * fh->dev->height * dev->format->depth + 7) >> 3; + buf->vb.size = + (fh->dev->width * fh->dev->height * dev->format->depth + 7) >> 3; - if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size) + if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size) return -EINVAL; - buf->vb.width = dev->width; + buf->vb.width = dev->width; buf->vb.height = dev->height; - buf->vb.field = field; + buf->vb.field = field; if (VIDEOBUF_NEEDS_INIT == buf->vb.state) { rc = videobuf_iolock(vq, &buf->vb, NULL); @@ -775,11 +772,12 @@ buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb, if (!dev->video_mode.isoc_ctl.num_bufs) urb_init = 1; - + if (urb_init) { rc = cx231xx_init_isoc(dev, CX231XX_NUM_PACKETS, - CX231XX_NUM_BUFS, dev->video_mode.max_pkt_size, - cx231xx_isoc_copy); + CX231XX_NUM_BUFS, + dev->video_mode.max_pkt_size, + cx231xx_isoc_copy); if (rc < 0) goto fail; } @@ -787,18 +785,18 @@ buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb, buf->vb.state = VIDEOBUF_PREPARED; return 0; -fail: + fail: free_buffer(vq, buf); return rc; } -static void -buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) +static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) { - struct cx231xx_buffer *buf = container_of(vb, struct cx231xx_buffer, vb); - struct cx231xx_fh *fh = vq->priv_data; - struct cx231xx *dev = fh->dev; - struct cx231xx_dmaqueue *vidq = &dev->video_mode.vidq; + struct cx231xx_buffer *buf = + container_of(vb, struct cx231xx_buffer, vb); + struct cx231xx_fh *fh = vq->priv_data; + struct cx231xx *dev = fh->dev; + struct cx231xx_dmaqueue *vidq = &dev->video_mode.vidq; buf->vb.state = VIDEOBUF_QUEUED; list_add_tail(&buf->vb.queue, &vidq->active); @@ -806,11 +804,12 @@ buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) } static void buffer_release(struct videobuf_queue *vq, - struct videobuf_buffer *vb) + struct videobuf_buffer *vb) { - struct cx231xx_buffer *buf = container_of(vb, struct cx231xx_buffer, vb); - struct cx231xx_fh *fh = vq->priv_data; - struct cx231xx *dev = (struct cx231xx *)fh->dev; + struct cx231xx_buffer *buf = + container_of(vb, struct cx231xx_buffer, vb); + struct cx231xx_fh *fh = vq->priv_data; + struct cx231xx *dev = (struct cx231xx *)fh->dev; cx231xx_isocdbg("cx231xx: called buffer_release\n"); @@ -818,15 +817,14 @@ static void buffer_release(struct videobuf_queue *vq, } static struct videobuf_queue_ops cx231xx_video_qops = { - .buf_setup = buffer_setup, - .buf_prepare = buffer_prepare, - .buf_queue = buffer_queue, - .buf_release = buffer_release, + .buf_setup = buffer_setup, + .buf_prepare = buffer_prepare, + .buf_queue = buffer_queue, + .buf_release = buffer_release, }; /********************* v4l2 interface **************************************/ - void video_mux(struct cx231xx *dev, int index) { @@ -837,40 +835,41 @@ void video_mux(struct cx231xx *dev, int index) dev->video_input = index; dev->ctl_ainput = INPUT(index)->amux; - cx231xx_set_video_input_mux(dev,index); + cx231xx_set_video_input_mux(dev, index); - cx231xx_i2c_call_clients(&dev->i2c_bus[0], VIDIOC_INT_S_VIDEO_ROUTING, &route); + cx231xx_i2c_call_clients(&dev->i2c_bus[0], VIDIOC_INT_S_VIDEO_ROUTING, + &route); - cx231xx_set_audio_input(dev, dev->ctl_ainput ); + cx231xx_set_audio_input(dev, dev->ctl_ainput); - cx231xx_info("video_mux : %d\n", index); + cx231xx_info("video_mux : %d\n", index); - /* do mode control overrides if required */ - cx231xx_do_mode_ctrl_overrides(dev); + /* do mode control overrides if required */ + cx231xx_do_mode_ctrl_overrides(dev); } /* Usage lock check functions */ static int res_get(struct cx231xx_fh *fh) { - struct cx231xx *dev = fh->dev; - int rc = 0; + struct cx231xx *dev = fh->dev; + int rc = 0; /* This instance already has stream_on */ if (fh->stream_on) return rc; - if(fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { - if (dev->stream_on) - return -EBUSY; - dev->stream_on = 1; - } else if(fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) { - if (dev->vbi_stream_on) - return -EBUSY; - dev->vbi_stream_on = 1; - } else - return -EINVAL; - - fh->stream_on = 1; + if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { + if (dev->stream_on) + return -EBUSY; + dev->stream_on = 1; + } else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) { + if (dev->vbi_stream_on) + return -EBUSY; + dev->vbi_stream_on = 1; + } else + return -EINVAL; + + fh->stream_on = 1; return rc; } @@ -882,14 +881,14 @@ static int res_check(struct cx231xx_fh *fh) static void res_free(struct cx231xx_fh *fh) { - struct cx231xx *dev = fh->dev; + struct cx231xx *dev = fh->dev; fh->stream_on = 0; - if(fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) - dev->stream_on = 0; - if(fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) - dev->vbi_stream_on = 0; + if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) + dev->stream_on = 0; + if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) + dev->vbi_stream_on = 0; } static int check_dev(struct cx231xx *dev) @@ -901,18 +900,18 @@ static int check_dev(struct cx231xx *dev) if (dev->state & DEV_MISCONFIGURED) { cx231xx_errdev("v4l2 ioctl: device is misconfigured; " - "close and open it again\n"); + "close and open it again\n"); return -EIO; } return 0; } void get_scale(struct cx231xx *dev, - unsigned int width, unsigned int height, - unsigned int *hscale, unsigned int *vscale) + unsigned int width, unsigned int height, + unsigned int *hscale, unsigned int *vscale) { - unsigned int maxw = norm_maxw(dev); - unsigned int maxh = norm_maxh(dev); + unsigned int maxw = norm_maxw(dev); + unsigned int maxh = norm_maxh(dev); *hscale = (((unsigned long)maxw) << 12) / width - 4096L; if (*hscale >= 0x4000) @@ -922,8 +921,8 @@ void get_scale(struct cx231xx *dev, if (*vscale >= 0x4000) *vscale = 0x3fff; - dev->hscale = *hscale; - dev->vscale = *vscale; + dev->hscale = *hscale; + dev->vscale = *vscale; } @@ -932,10 +931,10 @@ void get_scale(struct cx231xx *dev, ------------------------------------------------------------------*/ static int vidioc_g_fmt_vid_cap(struct file *file, void *priv, - struct v4l2_format *f) + struct v4l2_format *f) { - struct cx231xx_fh *fh = priv; - struct cx231xx *dev = fh->dev; + struct cx231xx_fh *fh = priv; + struct cx231xx *dev = fh->dev; mutex_lock(&dev->lock); @@ -943,7 +942,7 @@ static int vidioc_g_fmt_vid_cap(struct file *file, void *priv, f->fmt.pix.height = dev->height; f->fmt.pix.pixelformat = dev->format->fourcc;; f->fmt.pix.bytesperline = (dev->width * dev->format->depth + 7) >> 3;; - f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * dev->height; + f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * dev->height; f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; f->fmt.pix.field = V4L2_FIELD_INTERLACED; @@ -964,21 +963,21 @@ static struct cx231xx_fmt *format_by_fourcc(unsigned int fourcc) } static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, - struct v4l2_format *f) + struct v4l2_format *f) { - struct cx231xx_fh *fh = priv; - struct cx231xx *dev = fh->dev; - int width = f->fmt.pix.width; - int height = f->fmt.pix.height; - unsigned int maxw = norm_maxw(dev); - unsigned int maxh = norm_maxh(dev); - unsigned int hscale, vscale; - struct cx231xx_fmt *fmt; + struct cx231xx_fh *fh = priv; + struct cx231xx *dev = fh->dev; + int width = f->fmt.pix.width; + int height = f->fmt.pix.height; + unsigned int maxw = norm_maxw(dev); + unsigned int maxh = norm_maxh(dev); + unsigned int hscale, vscale; + struct cx231xx_fmt *fmt; fmt = format_by_fourcc(f->fmt.pix.pixelformat); if (!fmt) { cx231xx_videodbg("Fourcc format (%08x) invalid.\n", - f->fmt.pix.pixelformat); + f->fmt.pix.pixelformat); return -EINVAL; } @@ -1007,29 +1006,28 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, f->fmt.pix.bytesperline = (dev->width * fmt->depth + 7) >> 3; f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * height; f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; - f->fmt.pix.field = V4L2_FIELD_INTERLACED; + f->fmt.pix.field = V4L2_FIELD_INTERLACED; return 0; } static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, - struct v4l2_format *f) + struct v4l2_format *f) { - struct cx231xx_fh *fh = priv; - struct cx231xx *dev = fh->dev; - int rc; - struct cx231xx_fmt *fmt; + struct cx231xx_fh *fh = priv; + struct cx231xx *dev = fh->dev; + int rc; + struct cx231xx_fmt *fmt; rc = check_dev(dev); if (rc < 0) return rc; - mutex_lock(&dev->lock); - vidioc_try_fmt_vid_cap(file, priv, f); + vidioc_try_fmt_vid_cap(file, priv, f); - fmt = format_by_fourcc(f->fmt.pix.pixelformat); + fmt = format_by_fourcc(f->fmt.pix.pixelformat); if (!fmt) { rc = -EINVAL; goto out; @@ -1050,23 +1048,23 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, /* set new image size */ dev->width = f->fmt.pix.width; dev->height = f->fmt.pix.height; - dev->format = fmt; + dev->format = fmt; get_scale(dev, dev->width, dev->height, &dev->hscale, &dev->vscale); - - cx231xx_i2c_call_clients(&dev->i2c_bus[0], VIDIOC_S_FMT, f); - /* Set the correct alternate setting for this resolution */ + cx231xx_i2c_call_clients(&dev->i2c_bus[0], VIDIOC_S_FMT, f); + + /* Set the correct alternate setting for this resolution */ cx231xx_resolution_set(dev); -out: + out: mutex_unlock(&dev->lock); return rc; } -static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *id) +static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id * id) { - struct cx231xx_fh *fh = priv; - struct cx231xx *dev = fh->dev; + struct cx231xx_fh *fh = priv; + struct cx231xx *dev = fh->dev; *id = dev->norm; return 0; @@ -1074,20 +1072,19 @@ static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *id) static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id * norm) { - struct cx231xx_fh *fh = priv; - struct cx231xx *dev = fh->dev; + struct cx231xx_fh *fh = priv; + struct cx231xx *dev = fh->dev; struct v4l2_format f; - int rc; + int rc; rc = check_dev(dev); if (rc < 0) return rc; - cx231xx_info("vidioc_s_std : 0x%x\n", (unsigned int)*norm); + cx231xx_info("vidioc_s_std : 0x%x\n", (unsigned int)*norm); mutex_lock(&dev->lock); dev->norm = *norm; - /* Adjusts width/height, if needed */ f.fmt.pix.width = dev->width; @@ -1098,34 +1095,34 @@ static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id * norm) dev->width = f.fmt.pix.width; dev->height = f.fmt.pix.height; get_scale(dev, dev->width, dev->height, &dev->hscale, &dev->vscale); - + cx231xx_i2c_call_clients(&dev->i2c_bus[0], VIDIOC_S_STD, &dev->norm); mutex_unlock(&dev->lock); - cx231xx_resolution_set(dev); + cx231xx_resolution_set(dev); - /* do mode control overrides */ - cx231xx_do_mode_ctrl_overrides(dev); + /* do mode control overrides */ + cx231xx_do_mode_ctrl_overrides(dev); return 0; } static const char *iname[] = { [CX231XX_VMUX_COMPOSITE1] = "Composite1", - [CX231XX_VMUX_SVIDEO] = "S-Video", + [CX231XX_VMUX_SVIDEO] = "S-Video", [CX231XX_VMUX_TELEVISION] = "Television", - [CX231XX_VMUX_CABLE] = "Cable TV", - [CX231XX_VMUX_DVB] = "DVB", - [CX231XX_VMUX_DEBUG] = "for debug only", + [CX231XX_VMUX_CABLE] = "Cable TV", + [CX231XX_VMUX_DVB] = "DVB", + [CX231XX_VMUX_DEBUG] = "for debug only", }; static int vidioc_enum_input(struct file *file, void *priv, - struct v4l2_input *i) + struct v4l2_input *i) { - struct cx231xx_fh *fh = priv; - struct cx231xx *dev = fh->dev; - unsigned int n; + struct cx231xx_fh *fh = priv; + struct cx231xx *dev = fh->dev; + unsigned int n; n = i->index; if (n >= MAX_CX231XX_INPUT) @@ -1139,7 +1136,7 @@ static int vidioc_enum_input(struct file *file, void *priv, strcpy(i->name, iname[INPUT(n)->type]); if ((CX231XX_VMUX_TELEVISION == INPUT(n)->type) || - (CX231XX_VMUX_CABLE == INPUT(n)->type)) + (CX231XX_VMUX_CABLE == INPUT(n)->type)) i->type = V4L2_INPUT_TYPE_TUNER; i->std = dev->vdev->tvnorms; @@ -1149,8 +1146,8 @@ static int vidioc_enum_input(struct file *file, void *priv, static int vidioc_g_input(struct file *file, void *priv, unsigned int *i) { - struct cx231xx_fh *fh = priv; - struct cx231xx *dev = fh->dev; + struct cx231xx_fh *fh = priv; + struct cx231xx *dev = fh->dev; *i = dev->video_input; @@ -1159,9 +1156,9 @@ static int vidioc_g_input(struct file *file, void *priv, unsigned int *i) static int vidioc_s_input(struct file *file, void *priv, unsigned int i) { - struct cx231xx_fh *fh = priv; - struct cx231xx *dev = fh->dev; - int rc; + struct cx231xx_fh *fh = priv; + struct cx231xx *dev = fh->dev; + int rc; rc = check_dev(dev); if (rc < 0) @@ -1182,8 +1179,8 @@ static int vidioc_s_input(struct file *file, void *priv, unsigned int i) static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a) { - struct cx231xx_fh *fh = priv; - struct cx231xx *dev = fh->dev; + struct cx231xx_fh *fh = priv; + struct cx231xx *dev = fh->dev; switch (a->index) { case CX231XX_AMUX_VIDEO: @@ -1191,7 +1188,7 @@ static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a) break; case CX231XX_AMUX_LINE_IN: strcpy(a->name, "Line In"); - break; + break; default: return -EINVAL; } @@ -1204,35 +1201,34 @@ static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a) static int vidioc_s_audio(struct file *file, void *priv, struct v4l2_audio *a) { - struct cx231xx_fh *fh = priv; - struct cx231xx *dev = fh->dev; - int status = 0; - + struct cx231xx_fh *fh = priv; + struct cx231xx *dev = fh->dev; + int status = 0; /* Doesn't allow manual routing */ if (a->index != dev->ctl_ainput) return -EINVAL; dev->ctl_ainput = INPUT(a->index)->amux; - status = cx231xx_set_audio_input(dev, dev->ctl_ainput); + status = cx231xx_set_audio_input(dev, dev->ctl_ainput); return status; } static int vidioc_queryctrl(struct file *file, void *priv, - struct v4l2_queryctrl *qc) + struct v4l2_queryctrl *qc) { - struct cx231xx_fh *fh = priv; - struct cx231xx *dev = fh->dev; - int id = qc->id; - int i; - int rc; + struct cx231xx_fh *fh = priv; + struct cx231xx *dev = fh->dev; + int id = qc->id; + int i; + int rc; rc = check_dev(dev); if (rc < 0) return rc; - qc->id = v4l2_ctrl_next(ctrl_classes, qc->id); + qc->id = v4l2_ctrl_next(ctrl_classes, qc->id); if (unlikely(qc->id == 0)) return -EINVAL; @@ -1240,8 +1236,7 @@ static int vidioc_queryctrl(struct file *file, void *priv, qc->id = id; - if (qc->id < V4L2_CID_BASE || - qc->id >= V4L2_CID_LASTP1) + if (qc->id < V4L2_CID_BASE || qc->id >= V4L2_CID_LASTP1) return -EINVAL; for (i = 0; i < CX231XX_CTLS; i++) @@ -1255,7 +1250,7 @@ static int vidioc_queryctrl(struct file *file, void *priv, *qc = cx231xx_ctls[i].v; mutex_lock(&dev->lock); - cx231xx_i2c_call_clients(&dev->i2c_bus[0], VIDIOC_QUERYCTRL, qc); + cx231xx_i2c_call_clients(&dev->i2c_bus[0], VIDIOC_QUERYCTRL, qc); mutex_unlock(&dev->lock); if (qc->type) @@ -1265,11 +1260,11 @@ static int vidioc_queryctrl(struct file *file, void *priv, } static int vidioc_g_ctrl(struct file *file, void *priv, - struct v4l2_control *ctrl) + struct v4l2_control *ctrl) { - struct cx231xx_fh *fh = priv; - struct cx231xx *dev = fh->dev; - int rc; + struct cx231xx_fh *fh = priv; + struct cx231xx *dev = fh->dev; + int rc; rc = check_dev(dev); if (rc < 0) @@ -1284,11 +1279,11 @@ static int vidioc_g_ctrl(struct file *file, void *priv, } static int vidioc_s_ctrl(struct file *file, void *priv, - struct v4l2_control *ctrl) + struct v4l2_control *ctrl) { - struct cx231xx_fh *fh = priv; - struct cx231xx *dev = fh->dev; - int rc; + struct cx231xx_fh *fh = priv; + struct cx231xx *dev = fh->dev; + int rc; rc = check_dev(dev); if (rc < 0) @@ -1302,12 +1297,11 @@ static int vidioc_s_ctrl(struct file *file, void *priv, return rc; } -static int vidioc_g_tuner(struct file *file, void *priv, - struct v4l2_tuner *t) +static int vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t) { - struct cx231xx_fh *fh = priv; - struct cx231xx *dev = fh->dev; - int rc; + struct cx231xx_fh *fh = priv; + struct cx231xx *dev = fh->dev; + int rc; rc = check_dev(dev); if (rc < 0) @@ -1318,20 +1312,19 @@ static int vidioc_g_tuner(struct file *file, void *priv, strcpy(t->name, "Tuner"); - t->type = V4L2_TUNER_ANALOG_TV; + t->type = V4L2_TUNER_ANALOG_TV; t->capability = V4L2_TUNER_CAP_NORM; - t->rangehigh = 0xffffffffUL; - t->signal = 0xffff ; /* LOCKED */ + t->rangehigh = 0xffffffffUL; + t->signal = 0xffff; /* LOCKED */ return 0; } -static int vidioc_s_tuner(struct file *file, void *priv, - struct v4l2_tuner *t) +static int vidioc_s_tuner(struct file *file, void *priv, struct v4l2_tuner *t) { - struct cx231xx_fh *fh = priv; - struct cx231xx *dev = fh->dev; - int rc; + struct cx231xx_fh *fh = priv; + struct cx231xx *dev = fh->dev; + int rc; rc = check_dev(dev); if (rc < 0) @@ -1339,7 +1332,7 @@ static int vidioc_s_tuner(struct file *file, void *priv, if (0 != t->index) return -EINVAL; -#if 0 /* Keep */ +#if 0 /* Keep */ mutex_lock(&dev->lock); cx231xx_i2c_call_clients(&dev->i2c_bus[1], VIDIOC_S_TUNER, t); @@ -1350,28 +1343,28 @@ static int vidioc_s_tuner(struct file *file, void *priv, } static int vidioc_g_frequency(struct file *file, void *priv, - struct v4l2_frequency *f) + struct v4l2_frequency *f) { - struct cx231xx_fh *fh = priv; - struct cx231xx *dev = fh->dev; + struct cx231xx_fh *fh = priv; + struct cx231xx *dev = fh->dev; - mutex_lock(&dev->lock); + mutex_lock(&dev->lock); f->type = fh->radio ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV; f->frequency = dev->ctl_freq; - cx231xx_i2c_call_clients(&dev->i2c_bus[1], VIDIOC_G_FREQUENCY, f); + cx231xx_i2c_call_clients(&dev->i2c_bus[1], VIDIOC_G_FREQUENCY, f); - mutex_unlock(&dev->lock); + mutex_unlock(&dev->lock); return 0; } static int vidioc_s_frequency(struct file *file, void *priv, - struct v4l2_frequency *f) + struct v4l2_frequency *f) { - struct cx231xx_fh *fh = priv; - struct cx231xx *dev = fh->dev; - int rc; + struct cx231xx_fh *fh = priv; + struct cx231xx *dev = fh->dev; + int rc; rc = check_dev(dev); if (rc < 0) @@ -1385,106 +1378,121 @@ static int vidioc_s_frequency(struct file *file, void *priv, if (unlikely(1 == fh->radio && f->type != V4L2_TUNER_RADIO)) return -EINVAL; - /* set pre channel change settings in DIF first */ - rc = cx231xx_tuner_pre_channel_change(dev); + /* set pre channel change settings in DIF first */ + rc = cx231xx_tuner_pre_channel_change(dev); mutex_lock(&dev->lock); dev->ctl_freq = f->frequency; - - if(dev->tuner_type == TUNER_XC5000) { - if( dev->cx231xx_set_analog_freq != NULL ) { - dev->cx231xx_set_analog_freq(dev, f->frequency ); + + if (dev->tuner_type == TUNER_XC5000) { + if (dev->cx231xx_set_analog_freq != NULL) { + dev->cx231xx_set_analog_freq(dev, f->frequency); } } else { - cx231xx_i2c_call_clients(&dev->i2c_bus[1], VIDIOC_S_FREQUENCY, f); + cx231xx_i2c_call_clients(&dev->i2c_bus[1], VIDIOC_S_FREQUENCY, + f); } mutex_unlock(&dev->lock); - /* set post channel change settings in DIF first */ - rc = cx231xx_tuner_post_channel_change(dev); - - cx231xx_info("Set New FREQUENCY to %d\n",f->frequency); + /* set post channel change settings in DIF first */ + rc = cx231xx_tuner_post_channel_change(dev); + + cx231xx_info("Set New FREQUENCY to %d\n", f->frequency); return rc; } #ifdef CONFIG_VIDEO_ADV_DEBUG - /* - -R, --list-registers=type=,chip=[,min=,max=] - dump registers from to [VIDIOC_DBG_G_REGISTER] + -R, --list-registers=type=,chip=[,min=,max=] + dump registers from to [VIDIOC_DBG_G_REGISTER] -r, --set-register=type=,chip=,reg=,val= - set the register [VIDIOC_DBG_S_REGISTER] + set the register [VIDIOC_DBG_S_REGISTER] if type == host, then is the hosts chip ID (default 0) if type == i2cdrv (default), then is the I2C driver name or ID if type == i2caddr, then is the 7-bit I2C address */ - static int vidioc_g_register(struct file *file, void *priv, struct v4l2_dbg_register *reg) { - struct cx231xx_fh *fh = priv; - struct cx231xx *dev = fh->dev; + struct cx231xx_fh *fh = priv; + struct cx231xx *dev = fh->dev; int ret = 0; - u8 value[4] ={0,0,0,0}; - u32 data = 0; - - switch (reg->match.type) { - case V4L2_CHIP_MATCH_HOST: - switch(reg->match.addr) { - case 0: /* Cx231xx - internal registers */ - ret = cx231xx_read_ctrl_reg(dev,VRT_GET_REGISTER, (u16) reg->reg, value, 4); - reg->val = value[0] | value[1] << 8 | value[2] << 16 | value[3] << 24; - break; - case 1: /* Colibri - read byte */ - ret = cx231xx_read_i2c_data(dev, Colibri_DEVICE_ADDRESS, (u16) reg->reg, 2, &data, 1); - reg->val = le32_to_cpu(data & 0xff); - break; - case 14: /* Colibri - read dword */ - ret = cx231xx_read_i2c_data(dev, Colibri_DEVICE_ADDRESS, (u16) reg->reg, 2, &data, 4); - reg->val = le32_to_cpu(data); - break; - case 2: /* Hammerhead - read byte */ - ret = cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, (u16) reg->reg, 2, &data, 1); - reg->val = le32_to_cpu(data & 0xff); - break; - case 24: /* Hammerhead - read dword */ - ret = cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, (u16) reg->reg, 2, &data, 4); - reg->val = le32_to_cpu(data); - break; - case 3: /* flatiron - read byte */ - ret = cx231xx_read_i2c_data(dev, Flatrion_DEVICE_ADDRESS, (u16) reg->reg, 1, &data, 1); - reg->val = le32_to_cpu(data & 0xff); - break; - case 34: /* flatiron - read dword */ - ret = cx231xx_read_i2c_data(dev, Flatrion_DEVICE_ADDRESS, (u16) reg->reg, 1, &data, 4); - reg->val = le32_to_cpu(data); - break; - } - return ret < 0?ret:0; - - case V4L2_CHIP_MATCH_I2C_DRIVER: - cx231xx_i2c_call_clients(&dev->i2c_bus[0], VIDIOC_DBG_G_REGISTER, reg); - return 0; - case V4L2_CHIP_MATCH_I2C_ADDR: - /* Not supported yet */ - return -EINVAL; - default: - if (!v4l2_chip_match_host(®->match)) - return -EINVAL; - } - - - mutex_lock(&dev->lock); + u8 value[4] = { 0, 0, 0, 0 }; + u32 data = 0; + + switch (reg->match.type) { + case V4L2_CHIP_MATCH_HOST: + switch (reg->match.addr) { + case 0: /* Cx231xx - internal registers */ + ret = + cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, + (u16) reg->reg, value, 4); + reg->val = + value[0] | value[1] << 8 | value[2] << 16 | value[3] + << 24; + break; + case 1: /* Colibri - read byte */ + ret = + cx231xx_read_i2c_data(dev, Colibri_DEVICE_ADDRESS, + (u16) reg->reg, 2, &data, 1); + reg->val = le32_to_cpu(data & 0xff); + break; + case 14: /* Colibri - read dword */ + ret = + cx231xx_read_i2c_data(dev, Colibri_DEVICE_ADDRESS, + (u16) reg->reg, 2, &data, 4); + reg->val = le32_to_cpu(data); + break; + case 2: /* Hammerhead - read byte */ + ret = + cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + (u16) reg->reg, 2, &data, 1); + reg->val = le32_to_cpu(data & 0xff); + break; + case 24: /* Hammerhead - read dword */ + ret = + cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + (u16) reg->reg, 2, &data, 4); + reg->val = le32_to_cpu(data); + break; + case 3: /* flatiron - read byte */ + ret = + cx231xx_read_i2c_data(dev, Flatrion_DEVICE_ADDRESS, + (u16) reg->reg, 1, &data, 1); + reg->val = le32_to_cpu(data & 0xff); + break; + case 34: /* flatiron - read dword */ + ret = + cx231xx_read_i2c_data(dev, Flatrion_DEVICE_ADDRESS, + (u16) reg->reg, 1, &data, 4); + reg->val = le32_to_cpu(data); + break; + } + return ret < 0 ? ret : 0; + + case V4L2_CHIP_MATCH_I2C_DRIVER: + cx231xx_i2c_call_clients(&dev->i2c_bus[0], + VIDIOC_DBG_G_REGISTER, reg); + return 0; + case V4L2_CHIP_MATCH_I2C_ADDR: + /* Not supported yet */ + return -EINVAL; + default: + if (!v4l2_chip_match_host(®->match)) + return -EINVAL; + } + + mutex_lock(&dev->lock); cx231xx_i2c_call_clients(&dev->i2c_bus[0], VIDIOC_DBG_G_REGISTER, reg); - mutex_unlock(&dev->lock); + mutex_unlock(&dev->lock); return ret; } @@ -1492,70 +1500,97 @@ static int vidioc_g_register(struct file *file, void *priv, static int vidioc_s_register(struct file *file, void *priv, struct v4l2_dbg_register *reg) { - struct cx231xx_fh *fh = priv; - struct cx231xx *dev = fh->dev; - int ret = 0; + struct cx231xx_fh *fh = priv; + struct cx231xx *dev = fh->dev; + int ret = 0; __le64 buf; - u32 value; - u8 data[4] ={0,0,0,0}; - - buf = cpu_to_le64(reg->val); - - switch (reg->match.type) { - case V4L2_CHIP_MATCH_HOST: - { - value = (u32) buf & 0xffffffff; - - switch(reg->match.addr) { - case 0: /* cx231xx internal registers */ - data[0]=(u8)value; - data[1]=(u8)(value>>8); - data[2]=(u8)(value>>16); - data[3]=(u8)(value>>24); - ret = cx231xx_write_ctrl_reg(dev,VRT_SET_REGISTER, (u16) reg->reg, data, 4); - break; - case 1: /* Colibri - read byte */ - ret = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, (u16) reg->reg, 2, value, 1); - break; - case 14: /* Colibri - read dword */ - ret = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, (u16) reg->reg, 2, value, 4); - break; - case 2: /* Hammerhead - read byte */ - ret = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, (u16) reg->reg, 2, value, 1); - break; - case 24: /* Hammerhead - read dword */ - ret = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, (u16) reg->reg, 2, value, 4); - break; - case 3: /* flatiron - read byte */ - ret = cx231xx_write_i2c_data(dev, Flatrion_DEVICE_ADDRESS, (u16) reg->reg, 1, value, 1); - break; - case 34: /* flatiron - read dword */ - ret = cx231xx_write_i2c_data(dev, Flatrion_DEVICE_ADDRESS, (u16) reg->reg, 1, value, 4); - break; - } - } - return ret < 0?ret:0; - - default: - break; - } + u32 value; + u8 data[4] = { 0, 0, 0, 0 }; + + buf = cpu_to_le64(reg->val); + + switch (reg->match.type) { + case V4L2_CHIP_MATCH_HOST: + { + value = (u32) buf & 0xffffffff; + + switch (reg->match.addr) { + case 0: /* cx231xx internal registers */ + data[0] = (u8) value; + data[1] = (u8) (value >> 8); + data[2] = (u8) (value >> 16); + data[3] = (u8) (value >> 24); + ret = + cx231xx_write_ctrl_reg(dev, + VRT_SET_REGISTER, + (u16) reg->reg, data, + 4); + break; + case 1: /* Colibri - read byte */ + ret = + cx231xx_write_i2c_data(dev, + Colibri_DEVICE_ADDRESS, + (u16) reg->reg, 2, + value, 1); + break; + case 14: /* Colibri - read dword */ + ret = + cx231xx_write_i2c_data(dev, + Colibri_DEVICE_ADDRESS, + (u16) reg->reg, 2, + value, 4); + break; + case 2: /* Hammerhead - read byte */ + ret = + cx231xx_write_i2c_data(dev, + HAMMERHEAD_I2C_ADDRESS, + (u16) reg->reg, 2, + value, 1); + break; + case 24: /* Hammerhead - read dword */ + ret = + cx231xx_write_i2c_data(dev, + HAMMERHEAD_I2C_ADDRESS, + (u16) reg->reg, 2, + value, 4); + break; + case 3: /* flatiron - read byte */ + ret = + cx231xx_write_i2c_data(dev, + Flatrion_DEVICE_ADDRESS, + (u16) reg->reg, 1, + value, 1); + break; + case 34: /* flatiron - read dword */ + ret = + cx231xx_write_i2c_data(dev, + Flatrion_DEVICE_ADDRESS, + (u16) reg->reg, 1, + value, 4); + break; + } + } + return ret < 0 ? ret : 0; + + default: + break; + } mutex_lock(&dev->lock); cx231xx_i2c_call_clients(&dev->i2c_bus[0], VIDIOC_DBG_S_REGISTER, reg); - mutex_unlock(&dev->lock); + mutex_unlock(&dev->lock); - return ret; + return ret; } #endif - static int vidioc_cropcap(struct file *file, void *priv, - struct v4l2_cropcap *cc) + struct v4l2_cropcap *cc) { - struct cx231xx_fh *fh = priv; - struct cx231xx *dev = fh->dev; + struct cx231xx_fh *fh = priv; + struct cx231xx *dev = fh->dev; if (cc->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) return -EINVAL; @@ -1572,17 +1607,17 @@ static int vidioc_cropcap(struct file *file, void *priv, } static int vidioc_streamon(struct file *file, void *priv, - enum v4l2_buf_type type) + enum v4l2_buf_type type) { - struct cx231xx_fh *fh = priv; - struct cx231xx *dev = fh->dev; - int rc; + struct cx231xx_fh *fh = priv; + struct cx231xx *dev = fh->dev; + int rc; rc = check_dev(dev); if (rc < 0) return rc; - mutex_lock(&dev->lock); + mutex_lock(&dev->lock); rc = res_get(fh); if (likely(rc >= 0)) @@ -1594,52 +1629,51 @@ static int vidioc_streamon(struct file *file, void *priv, } static int vidioc_streamoff(struct file *file, void *priv, - enum v4l2_buf_type type) + enum v4l2_buf_type type) { - struct cx231xx_fh *fh = priv; - struct cx231xx *dev = fh->dev; - int rc; + struct cx231xx_fh *fh = priv; + struct cx231xx *dev = fh->dev; + int rc; rc = check_dev(dev); if (rc < 0) return rc; - if ( (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) || - (fh->type != V4L2_BUF_TYPE_VBI_CAPTURE) ) + if ((fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) || + (fh->type != V4L2_BUF_TYPE_VBI_CAPTURE)) return -EINVAL; if (type != fh->type) return -EINVAL; - mutex_lock(&dev->lock); + mutex_lock(&dev->lock); videobuf_streamoff(&fh->vb_vidq); res_free(fh); - mutex_unlock(&dev->lock); + mutex_unlock(&dev->lock); return 0; } -static int vidioc_querycap(struct file *file, void *priv, - struct v4l2_capability *cap) +static int vidioc_querycap(struct file *file, void *priv, + struct v4l2_capability *cap) { - struct cx231xx_fh *fh = priv; - struct cx231xx *dev = fh->dev; + struct cx231xx_fh *fh = priv; + struct cx231xx *dev = fh->dev; strlcpy(cap->driver, "cx231xx", sizeof(cap->driver)); strlcpy(cap->card, cx231xx_boards[dev->model].name, sizeof(cap->card)); - strlcpy(cap->bus_info, dev_name(&dev->udev->dev), sizeof(cap->bus_info)); + strlcpy(cap->bus_info, dev_name(&dev->udev->dev), + sizeof(cap->bus_info)); cap->version = CX231XX_VERSION_CODE; - cap->capabilities = - V4L2_CAP_VBI_CAPTURE | -#if 0 /* Keep */ - V4L2_CAP_SLICED_VBI_CAPTURE | + cap->capabilities = V4L2_CAP_VBI_CAPTURE | +#if 0 /* Keep */ + V4L2_CAP_SLICED_VBI_CAPTURE | #endif - V4L2_CAP_VIDEO_CAPTURE | - V4L2_CAP_AUDIO | - V4L2_CAP_READWRITE | V4L2_CAP_STREAMING; + V4L2_CAP_VIDEO_CAPTURE | + V4L2_CAP_AUDIO | V4L2_CAP_READWRITE | V4L2_CAP_STREAMING; if (dev->tuner_type != TUNER_ABSENT) cap->capabilities |= V4L2_CAP_TUNER; @@ -1647,10 +1681,10 @@ static int vidioc_querycap(struct file *file, void *priv, return 0; } -static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, - struct v4l2_fmtdesc *f) +static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, + struct v4l2_fmtdesc *f) { - if (unlikely(f->index >= ARRAY_SIZE(format))) + if (unlikely(f->index >= ARRAY_SIZE(format))) return -EINVAL; strlcpy(f->description, format[f->index].name, sizeof(f->description)); @@ -1661,11 +1695,11 @@ static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, /* Sliced VBI ioctls */ static int vidioc_g_fmt_sliced_vbi_cap(struct file *file, void *priv, - struct v4l2_format *f) + struct v4l2_format *f) { - struct cx231xx_fh *fh = priv; - struct cx231xx *dev = fh->dev; - int rc; + struct cx231xx_fh *fh = priv; + struct cx231xx *dev = fh->dev; + int rc; rc = check_dev(dev); if (rc < 0) @@ -1685,11 +1719,11 @@ static int vidioc_g_fmt_sliced_vbi_cap(struct file *file, void *priv, } static int vidioc_try_set_sliced_vbi_cap(struct file *file, void *priv, - struct v4l2_format *f) + struct v4l2_format *f) { - struct cx231xx_fh *fh = priv; - struct cx231xx *dev = fh->dev; - int rc; + struct cx231xx_fh *fh = priv; + struct cx231xx *dev = fh->dev; + int rc; rc = check_dev(dev); if (rc < 0) @@ -1705,26 +1739,25 @@ static int vidioc_try_set_sliced_vbi_cap(struct file *file, void *priv, return 0; } - /* RAW VBI ioctls */ static int vidioc_g_fmt_vbi_cap(struct file *file, void *priv, - struct v4l2_format *f) + struct v4l2_format *f) { - struct cx231xx_fh *fh = priv; - struct cx231xx *dev = fh->dev; + struct cx231xx_fh *fh = priv; + struct cx231xx *dev = fh->dev; f->fmt.vbi.sampling_rate = (dev->norm & V4L2_STD_625_50) ? - 35468950:28636363; + 35468950 : 28636363; f->fmt.vbi.samples_per_line = VBI_LINE_LENGTH; f->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY; f->fmt.vbi.offset = 64 * 4; - f->fmt.vbi.start[0] = (dev->norm & V4L2_STD_625_50) ? - PAL_VBI_START_LINE : NTSC_VBI_START_LINE; - f->fmt.vbi.count[0] = (dev->norm & V4L2_STD_625_50) ? - PAL_VBI_LINES : NTSC_VBI_LINES; - f->fmt.vbi.start[1] = (dev->norm & V4L2_STD_625_50) ? - PAL_VBI_START_LINE+312 : NTSC_VBI_START_LINE + 263; + f->fmt.vbi.start[0] = (dev->norm & V4L2_STD_625_50) ? + PAL_VBI_START_LINE : NTSC_VBI_START_LINE; + f->fmt.vbi.count[0] = (dev->norm & V4L2_STD_625_50) ? + PAL_VBI_LINES : NTSC_VBI_LINES; + f->fmt.vbi.start[1] = (dev->norm & V4L2_STD_625_50) ? + PAL_VBI_START_LINE + 312 : NTSC_VBI_START_LINE + 263; f->fmt.vbi.count[1] = f->fmt.vbi.count[0]; return 0; @@ -1732,29 +1765,29 @@ static int vidioc_g_fmt_vbi_cap(struct file *file, void *priv, } static int vidioc_try_fmt_vbi_cap(struct file *file, void *priv, - struct v4l2_format *f) + struct v4l2_format *f) { - struct cx231xx_fh *fh = priv; - struct cx231xx *dev = fh->dev; + struct cx231xx_fh *fh = priv; + struct cx231xx *dev = fh->dev; - if (dev->vbi_stream_on && !fh->stream_on) { + if (dev->vbi_stream_on && !fh->stream_on) { cx231xx_errdev("%s device in use by another fh\n", __func__); return -EBUSY; } f->type = V4L2_BUF_TYPE_VBI_CAPTURE; f->fmt.vbi.sampling_rate = (dev->norm & V4L2_STD_625_50) ? - 35468950:28636363; + 35468950 : 28636363; f->fmt.vbi.samples_per_line = VBI_LINE_LENGTH; f->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY; f->fmt.vbi.offset = 244; f->fmt.vbi.flags = 0; - f->fmt.vbi.start[0] = (dev->norm & V4L2_STD_625_50) ? - PAL_VBI_START_LINE : NTSC_VBI_START_LINE; - f->fmt.vbi.count[0] = (dev->norm & V4L2_STD_625_50) ? - PAL_VBI_LINES : NTSC_VBI_LINES; - f->fmt.vbi.start[1] = (dev->norm & V4L2_STD_625_50) ? - PAL_VBI_START_LINE+312 : NTSC_VBI_START_LINE + 263; + f->fmt.vbi.start[0] = (dev->norm & V4L2_STD_625_50) ? + PAL_VBI_START_LINE : NTSC_VBI_START_LINE; + f->fmt.vbi.count[0] = (dev->norm & V4L2_STD_625_50) ? + PAL_VBI_LINES : NTSC_VBI_LINES; + f->fmt.vbi.start[1] = (dev->norm & V4L2_STD_625_50) ? + PAL_VBI_START_LINE + 312 : NTSC_VBI_START_LINE + 263; f->fmt.vbi.count[1] = f->fmt.vbi.count[0]; return 0; @@ -1764,9 +1797,9 @@ static int vidioc_try_fmt_vbi_cap(struct file *file, void *priv, static int vidioc_reqbufs(struct file *file, void *priv, struct v4l2_requestbuffers *rb) { - struct cx231xx_fh *fh = priv; - struct cx231xx *dev = fh->dev; - int rc; + struct cx231xx_fh *fh = priv; + struct cx231xx *dev = fh->dev; + int rc; rc = check_dev(dev); if (rc < 0) @@ -1775,12 +1808,11 @@ static int vidioc_reqbufs(struct file *file, void *priv, return (videobuf_reqbufs(&fh->vb_vidq, rb)); } -static int vidioc_querybuf(struct file *file, void *priv, - struct v4l2_buffer *b) +static int vidioc_querybuf(struct file *file, void *priv, struct v4l2_buffer *b) { - struct cx231xx_fh *fh = priv; - struct cx231xx *dev = fh->dev; - int rc; + struct cx231xx_fh *fh = priv; + struct cx231xx *dev = fh->dev; + int rc; rc = check_dev(dev); if (rc < 0) @@ -1791,9 +1823,9 @@ static int vidioc_querybuf(struct file *file, void *priv, static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *b) { - struct cx231xx_fh *fh = priv; - struct cx231xx *dev = fh->dev; - int rc; + struct cx231xx_fh *fh = priv; + struct cx231xx *dev = fh->dev; + int rc; rc = check_dev(dev); if (rc < 0) @@ -1804,33 +1836,31 @@ static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *b) static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b) { - struct cx231xx_fh *fh = priv; - struct cx231xx *dev = fh->dev; - int rc; + struct cx231xx_fh *fh = priv; + struct cx231xx *dev = fh->dev; + int rc; rc = check_dev(dev); if (rc < 0) return rc; - return (videobuf_dqbuf(&fh->vb_vidq, b, - file->f_flags & O_NONBLOCK)); + return (videobuf_dqbuf(&fh->vb_vidq, b, file->f_flags & O_NONBLOCK)); } #ifdef CONFIG_VIDEO_V4L1_COMPAT static int vidiocgmbuf(struct file *file, void *priv, struct video_mbuf *mbuf) { - struct cx231xx_fh *fh = priv; + struct cx231xx_fh *fh = priv; return videobuf_cgmbuf(&fh->vb_vidq, mbuf, 8); } #endif - /* ----------------------------------------------------------- */ /* RADIO ESPECIFIC IOCTLS */ /* ----------------------------------------------------------- */ -static int radio_querycap(struct file *file, void *priv, +static int radio_querycap(struct file *file, void *priv, struct v4l2_capability *cap) { struct cx231xx *dev = ((struct cx231xx_fh *)priv)->dev; @@ -1844,8 +1874,7 @@ static int radio_querycap(struct file *file, void *priv, return 0; } -static int radio_g_tuner(struct file *file, void *priv, - struct v4l2_tuner *t) +static int radio_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t) { struct cx231xx *dev = ((struct cx231xx_fh *)priv)->dev; @@ -1855,15 +1884,14 @@ static int radio_g_tuner(struct file *file, void *priv, strcpy(t->name, "Radio"); t->type = V4L2_TUNER_RADIO; - mutex_lock(&dev->lock); + mutex_lock(&dev->lock); cx231xx_i2c_call_clients(&dev->i2c_bus[1], VIDIOC_G_TUNER, t); - mutex_unlock(&dev->lock); + mutex_unlock(&dev->lock); return 0; } -static int radio_enum_input(struct file *file, void *priv, - struct v4l2_input *i) +static int radio_enum_input(struct file *file, void *priv, struct v4l2_input *i) { if (i->index != 0) return -EINVAL; @@ -1882,23 +1910,21 @@ static int radio_g_audio(struct file *file, void *priv, struct v4l2_audio *a) return 0; } -static int radio_s_tuner(struct file *file, void *priv, - struct v4l2_tuner *t) +static int radio_s_tuner(struct file *file, void *priv, struct v4l2_tuner *t) { struct cx231xx *dev = ((struct cx231xx_fh *)priv)->dev; if (0 != t->index) return -EINVAL; - mutex_lock(&dev->lock); + mutex_lock(&dev->lock); cx231xx_i2c_call_clients(&dev->i2c_bus[1], VIDIOC_S_TUNER, t); - mutex_unlock(&dev->lock); + mutex_unlock(&dev->lock); return 0; } -static int radio_s_audio(struct file *file, void *fh, - struct v4l2_audio *a) +static int radio_s_audio(struct file *file, void *fh, struct v4l2_audio *a) { return 0; } @@ -1913,8 +1939,7 @@ static int radio_queryctrl(struct file *file, void *priv, { int i; - if (c->id < V4L2_CID_BASE || - c->id >= V4L2_CID_LASTP1) + if (c->id < V4L2_CID_BASE || c->id >= V4L2_CID_LASTP1) return -EINVAL; if (c->id == V4L2_CID_AUDIO_MUTE) { for (i = 0; i < CX231XX_CTLS; i++) @@ -1932,25 +1957,26 @@ static int radio_queryctrl(struct file *file, void *priv, */ static int cx231xx_v4l2_open(struct file *filp) { - int minor = video_devdata(filp)->minor; + int minor = video_devdata(filp)->minor; int errCode = 0, radio = 0; struct cx231xx *dev = NULL; struct cx231xx_fh *fh; enum v4l2_buf_type fh_type = 0; - dev = cx231xx_get_device(minor, &fh_type, &radio); + dev = cx231xx_get_device(minor, &fh_type, &radio); if (NULL == dev) return -ENODEV; mutex_lock(&dev->lock); cx231xx_videodbg("open minor=%d type=%s users=%d\n", - minor, v4l2_type_names[fh_type], dev->users); + minor, v4l2_type_names[fh_type], dev->users); -#if 0 /* Keep */ +#if 0 /* Keep */ errCode = cx231xx_set_mode(dev, CX231XX_ANALOG_MODE); if (errCode < 0) { - cx231xx_errdev("Device locked on digital mode. Can't open analog\n"); + cx231xx_errdev + ("Device locked on digital mode. Can't open analog\n"); mutex_unlock(&dev->lock); return -EBUSY; } @@ -1972,26 +1998,25 @@ static int cx231xx_v4l2_open(struct file *filp) dev->height = norm_maxh(dev); dev->hscale = 0; dev->vscale = 0; - - /* Power up in Analog TV mode */ - cx231xx_set_power_mode(dev, POLARIS_AVMODE_ANALOGT_TV); + /* Power up in Analog TV mode */ + cx231xx_set_power_mode(dev, POLARIS_AVMODE_ANALOGT_TV); -#if 0 /* Keep */ +#if 0 /* Keep */ cx231xx_set_mode(dev, CX231XX_ANALOG_MODE); -#endif +#endif cx231xx_resolution_set(dev); - /* set video alternate setting */ - cx231xx_set_video_alternate(dev); + /* set video alternate setting */ + cx231xx_set_video_alternate(dev); /* Needed, since GPIO might have disabled power of some i2c device */ cx231xx_config_i2c(dev); /* device needs to be initialized before isoc transfer */ - dev->video_input = dev->video_input > 2 ? 2: dev->video_input; - video_mux(dev, dev->video_input ); + dev->video_input = dev->video_input > 2 ? 2 : dev->video_input; + video_mux(dev, dev->video_input); } if (fh->radio) { @@ -1999,26 +2024,25 @@ static int cx231xx_v4l2_open(struct file *filp) /* cx231xx_start_radio(dev); */ - cx231xx_i2c_call_clients(&dev->i2c_bus[1], AUDC_SET_RADIO, NULL); + cx231xx_i2c_call_clients(&dev->i2c_bus[1], AUDC_SET_RADIO, + NULL); } dev->users++; - if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { - videobuf_queue_vmalloc_init(&fh->vb_vidq, &cx231xx_video_qops, - NULL, &dev->video_mode.slock, fh->type, V4L2_FIELD_INTERLACED, /* V4L2_FIELD_SEQ_TB, */ - sizeof(struct cx231xx_buffer), fh); - } - - if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) { - - /* Set the required alternate setting VBI interface works in Bulk mode only */ - cx231xx_set_alt_setting(dev, INDEX_VANC, 0); - - videobuf_queue_vmalloc_init(&fh->vb_vidq, &cx231xx_vbi_qops, - NULL, &dev->vbi_mode.slock, fh->type, V4L2_FIELD_SEQ_TB, /* V4L2_FIELD_INTERLACED, */ - sizeof(struct cx231xx_buffer), fh); - } + if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { + videobuf_queue_vmalloc_init(&fh->vb_vidq, &cx231xx_video_qops, NULL, &dev->video_mode.slock, fh->type, V4L2_FIELD_INTERLACED, /* V4L2_FIELD_SEQ_TB, */ + sizeof(struct cx231xx_buffer), fh); + } + + if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) { + + /* Set the required alternate setting VBI interface works in Bulk mode only */ + cx231xx_set_alt_setting(dev, INDEX_VANC, 0); + + videobuf_queue_vmalloc_init(&fh->vb_vidq, &cx231xx_vbi_qops, NULL, &dev->vbi_mode.slock, fh->type, V4L2_FIELD_SEQ_TB, /* V4L2_FIELD_INTERLACED, */ + sizeof(struct cx231xx_buffer), fh); + } mutex_unlock(&dev->lock); @@ -2044,7 +2068,7 @@ void cx231xx_release_analog_resources(struct cx231xx *dev) } if (dev->vbi_dev) { cx231xx_info("V4L2 device /dev/vbi%d deregistered\n", - dev->vbi_dev->num); + dev->vbi_dev->num); if (-1 != dev->vbi_dev->minor) video_unregister_device(dev->vbi_dev); else @@ -2053,7 +2077,7 @@ void cx231xx_release_analog_resources(struct cx231xx *dev) } if (dev->vdev) { cx231xx_info("V4L2 device /dev/video%d deregistered\n", - dev->vdev->num); + dev->vdev->num); if (-1 != dev->vdev->minor) video_unregister_device(dev->vdev); else @@ -2069,44 +2093,44 @@ void cx231xx_release_analog_resources(struct cx231xx *dev) */ static int cx231xx_v4l2_close(struct file *filp) { - struct cx231xx_fh *fh = filp->private_data; - struct cx231xx *dev = fh->dev; + struct cx231xx_fh *fh = filp->private_data; + struct cx231xx *dev = fh->dev; cx231xx_videodbg("users=%d\n", dev->users); - mutex_lock(&dev->lock); + mutex_lock(&dev->lock); if (res_check(fh)) - res_free(fh); - - if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) { - videobuf_stop(&fh->vb_vidq); - videobuf_mmap_free(&fh->vb_vidq); - - /* the device is already disconnect, - free the remaining resources */ - if (dev->state & DEV_DISCONNECTED) { - cx231xx_release_resources(dev); - mutex_unlock(&dev->lock); - kfree(dev); - return 0; - } - - /* do this before setting alternate! */ - cx231xx_uninit_vbi_isoc(dev); - - /* set alternate 0 */ - if( !dev->vbi_or_sliced_cc_mode) { - cx231xx_set_alt_setting(dev, INDEX_VANC, 0); - } else { - cx231xx_set_alt_setting(dev, INDEX_HANC, 0); - } - - kfree(fh); - dev->users--; - wake_up_interruptible_nr(&dev->open, 1); - mutex_unlock(&dev->lock); - return 0; + res_free(fh); + + if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) { + videobuf_stop(&fh->vb_vidq); + videobuf_mmap_free(&fh->vb_vidq); + + /* the device is already disconnect, + free the remaining resources */ + if (dev->state & DEV_DISCONNECTED) { + cx231xx_release_resources(dev); + mutex_unlock(&dev->lock); + kfree(dev); + return 0; + } + + /* do this before setting alternate! */ + cx231xx_uninit_vbi_isoc(dev); + + /* set alternate 0 */ + if (!dev->vbi_or_sliced_cc_mode) { + cx231xx_set_alt_setting(dev, INDEX_VANC, 0); + } else { + cx231xx_set_alt_setting(dev, INDEX_HANC, 0); + } + + kfree(fh); + dev->users--; + wake_up_interruptible_nr(&dev->open, 1); + mutex_unlock(&dev->lock); + return 0; } if (dev->users == 1) { @@ -2122,10 +2146,11 @@ static int cx231xx_v4l2_close(struct file *filp) return 0; } - /* Save some power by putting tuner to sleep */ - cx231xx_i2c_call_clients(&dev->i2c_bus[1], TUNER_SET_STANDBY, NULL); + /* Save some power by putting tuner to sleep */ + cx231xx_i2c_call_clients(&dev->i2c_bus[1], TUNER_SET_STANDBY, + NULL); - /* do this before setting alternate! */ + /* do this before setting alternate! */ cx231xx_uninit_isoc(dev); cx231xx_set_mode(dev, CX231XX_SUSPEND); @@ -2144,8 +2169,8 @@ static int cx231xx_v4l2_close(struct file *filp) * will allocate buffers when called for the first time */ static ssize_t -cx231xx_v4l2_read(struct file *filp, char __user *buf, size_t count, - loff_t *pos) +cx231xx_v4l2_read(struct file *filp, char __user * buf, size_t count, + loff_t * pos) { struct cx231xx_fh *fh = filp->private_data; struct cx231xx *dev = fh->dev; @@ -2155,8 +2180,8 @@ cx231xx_v4l2_read(struct file *filp, char __user *buf, size_t count, if (rc < 0) return rc; - if ( (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) || - (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) ) { + if ((fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) || + (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE)) { mutex_lock(&dev->lock); rc = res_get(fh); mutex_unlock(&dev->lock); @@ -2165,7 +2190,7 @@ cx231xx_v4l2_read(struct file *filp, char __user *buf, size_t count, return rc; return videobuf_read_stream(&fh->vb_vidq, buf, count, pos, 0, - filp->f_flags & O_NONBLOCK); + filp->f_flags & O_NONBLOCK); } return 0; } @@ -2191,11 +2216,11 @@ static unsigned int cx231xx_v4l2_poll(struct file *filp, poll_table * wait) if (unlikely(rc < 0)) return POLLERR; - if ( (V4L2_BUF_TYPE_VIDEO_CAPTURE == fh->type) || - (V4L2_BUF_TYPE_VBI_CAPTURE == fh->type) ) - return videobuf_poll_stream(filp, &fh->vb_vidq, wait); - else - return POLLERR; + if ((V4L2_BUF_TYPE_VIDEO_CAPTURE == fh->type) || + (V4L2_BUF_TYPE_VBI_CAPTURE == fh->type)) + return videobuf_poll_stream(filp, &fh->vb_vidq, wait); + else + return POLLERR; } /* @@ -2203,15 +2228,15 @@ static unsigned int cx231xx_v4l2_poll(struct file *filp, poll_table * wait) */ static int cx231xx_v4l2_mmap(struct file *filp, struct vm_area_struct *vma) { - struct cx231xx_fh *fh = filp->private_data; - struct cx231xx *dev = fh->dev; - int rc; + struct cx231xx_fh *fh = filp->private_data; + struct cx231xx *dev = fh->dev; + int rc; rc = check_dev(dev); if (rc < 0) return rc; - mutex_lock(&dev->lock); + mutex_lock(&dev->lock); rc = res_get(fh); mutex_unlock(&dev->lock); @@ -2221,114 +2246,112 @@ static int cx231xx_v4l2_mmap(struct file *filp, struct vm_area_struct *vma) rc = videobuf_mmap_mapper(&fh->vb_vidq, vma); cx231xx_videodbg("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); + (unsigned long)vma->vm_start, + (unsigned long)vma->vm_end - + (unsigned long)vma->vm_start, rc); return rc; } static const struct v4l2_file_operations cx231xx_v4l_fops = { - .owner = THIS_MODULE, - .open = cx231xx_v4l2_open, - .release = cx231xx_v4l2_close, - .read = cx231xx_v4l2_read, - .poll = cx231xx_v4l2_poll, - .mmap = cx231xx_v4l2_mmap, - .ioctl = video_ioctl2, + .owner = THIS_MODULE, + .open = cx231xx_v4l2_open, + .release = cx231xx_v4l2_close, + .read = cx231xx_v4l2_read, + .poll = cx231xx_v4l2_poll, + .mmap = cx231xx_v4l2_mmap, + .ioctl = video_ioctl2, }; static const struct v4l2_ioctl_ops video_ioctl_ops = { - .vidioc_querycap = vidioc_querycap, - .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, - .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, - .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, - .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, - .vidioc_g_fmt_vbi_cap = vidioc_g_fmt_vbi_cap, - .vidioc_try_fmt_vbi_cap = vidioc_try_fmt_vbi_cap, - .vidioc_s_fmt_vbi_cap = vidioc_try_fmt_vbi_cap, - .vidioc_g_audio = vidioc_g_audio, - .vidioc_s_audio = vidioc_s_audio, - .vidioc_cropcap = vidioc_cropcap, - .vidioc_g_fmt_sliced_vbi_cap = vidioc_g_fmt_sliced_vbi_cap, + .vidioc_querycap = vidioc_querycap, + .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, + .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, + .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, + .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, + .vidioc_g_fmt_vbi_cap = vidioc_g_fmt_vbi_cap, + .vidioc_try_fmt_vbi_cap = vidioc_try_fmt_vbi_cap, + .vidioc_s_fmt_vbi_cap = vidioc_try_fmt_vbi_cap, + .vidioc_g_audio = vidioc_g_audio, + .vidioc_s_audio = vidioc_s_audio, + .vidioc_cropcap = vidioc_cropcap, + .vidioc_g_fmt_sliced_vbi_cap = vidioc_g_fmt_sliced_vbi_cap, .vidioc_try_fmt_sliced_vbi_cap = vidioc_try_set_sliced_vbi_cap, - .vidioc_reqbufs = vidioc_reqbufs, - .vidioc_querybuf = vidioc_querybuf, - .vidioc_qbuf = vidioc_qbuf, - .vidioc_dqbuf = vidioc_dqbuf, - .vidioc_s_std = vidioc_s_std, - .vidioc_g_std = vidioc_g_std, - .vidioc_enum_input = vidioc_enum_input, - .vidioc_g_input = vidioc_g_input, - .vidioc_s_input = vidioc_s_input, - .vidioc_queryctrl = vidioc_queryctrl, - .vidioc_g_ctrl = vidioc_g_ctrl, - .vidioc_s_ctrl = vidioc_s_ctrl, - .vidioc_streamon = vidioc_streamon, - .vidioc_streamoff = vidioc_streamoff, - .vidioc_g_tuner = vidioc_g_tuner, - .vidioc_s_tuner = vidioc_s_tuner, - .vidioc_g_frequency = vidioc_g_frequency, - .vidioc_s_frequency = vidioc_s_frequency, + .vidioc_reqbufs = vidioc_reqbufs, + .vidioc_querybuf = vidioc_querybuf, + .vidioc_qbuf = vidioc_qbuf, + .vidioc_dqbuf = vidioc_dqbuf, + .vidioc_s_std = vidioc_s_std, + .vidioc_g_std = vidioc_g_std, + .vidioc_enum_input = vidioc_enum_input, + .vidioc_g_input = vidioc_g_input, + .vidioc_s_input = vidioc_s_input, + .vidioc_queryctrl = vidioc_queryctrl, + .vidioc_g_ctrl = vidioc_g_ctrl, + .vidioc_s_ctrl = vidioc_s_ctrl, + .vidioc_streamon = vidioc_streamon, + .vidioc_streamoff = vidioc_streamoff, + .vidioc_g_tuner = vidioc_g_tuner, + .vidioc_s_tuner = vidioc_s_tuner, + .vidioc_g_frequency = vidioc_g_frequency, + .vidioc_s_frequency = vidioc_s_frequency, #ifdef CONFIG_VIDEO_ADV_DEBUG - .vidioc_g_register = vidioc_g_register, - .vidioc_s_register = vidioc_s_register, + .vidioc_g_register = vidioc_g_register, + .vidioc_s_register = vidioc_s_register, #endif #ifdef CONFIG_VIDEO_V4L1_COMPAT - .vidiocgmbuf = vidiocgmbuf, + .vidiocgmbuf = vidiocgmbuf, #endif }; static struct video_device cx231xx_vbi_template; static const struct video_device cx231xx_video_template = { - .fops = &cx231xx_v4l_fops, - .release = video_device_release, - .ioctl_ops = &video_ioctl_ops, - .minor = -1, - .tvnorms = V4L2_STD_ALL, - .current_norm = V4L2_STD_PAL, + .fops = &cx231xx_v4l_fops, + .release = video_device_release, + .ioctl_ops = &video_ioctl_ops, + .minor = -1, + .tvnorms = V4L2_STD_ALL, + .current_norm = V4L2_STD_PAL, }; static const struct v4l2_file_operations radio_fops = { - .owner = THIS_MODULE, - .open = cx231xx_v4l2_open, - .release = cx231xx_v4l2_close, - .ioctl = video_ioctl2, + .owner = THIS_MODULE, + .open = cx231xx_v4l2_open, + .release = cx231xx_v4l2_close, + .ioctl = video_ioctl2, }; static const struct v4l2_ioctl_ops radio_ioctl_ops = { - .vidioc_querycap = radio_querycap, - .vidioc_g_tuner = radio_g_tuner, - .vidioc_enum_input = radio_enum_input, - .vidioc_g_audio = radio_g_audio, - .vidioc_s_tuner = radio_s_tuner, - .vidioc_s_audio = radio_s_audio, - .vidioc_s_input = radio_s_input, - .vidioc_queryctrl = radio_queryctrl, - .vidioc_g_ctrl = vidioc_g_ctrl, - .vidioc_s_ctrl = vidioc_s_ctrl, - .vidioc_g_frequency = vidioc_g_frequency, - .vidioc_s_frequency = vidioc_s_frequency, + .vidioc_querycap = radio_querycap, + .vidioc_g_tuner = radio_g_tuner, + .vidioc_enum_input = radio_enum_input, + .vidioc_g_audio = radio_g_audio, + .vidioc_s_tuner = radio_s_tuner, + .vidioc_s_audio = radio_s_audio, + .vidioc_s_input = radio_s_input, + .vidioc_queryctrl = radio_queryctrl, + .vidioc_g_ctrl = vidioc_g_ctrl, + .vidioc_s_ctrl = vidioc_s_ctrl, + .vidioc_g_frequency = vidioc_g_frequency, + .vidioc_s_frequency = vidioc_s_frequency, #ifdef CONFIG_VIDEO_ADV_DEBUG - .vidioc_g_register = vidioc_g_register, - .vidioc_s_register = vidioc_s_register, + .vidioc_g_register = vidioc_g_register, + .vidioc_s_register = vidioc_s_register, #endif }; static struct video_device cx231xx_radio_template = { - .name = "cx231xx-radio", - .fops = &radio_fops, - .ioctl_ops = &radio_ioctl_ops, - .minor = -1, + .name = "cx231xx-radio", + .fops = &radio_fops, + .ioctl_ops = &radio_ioctl_ops, + .minor = -1, }; /******************************** usb interface ******************************/ - -static struct video_device *cx231xx_vdev_init(struct cx231xx *dev, - const struct video_device *template, - const char *type_name) +static struct video_device *cx231xx_vdev_init(struct cx231xx *dev, const struct video_device + *template, const char *type_name) { struct video_device *vfd; @@ -2336,13 +2359,12 @@ static struct video_device *cx231xx_vdev_init(struct cx231xx *dev, if (NULL == vfd) return NULL; *vfd = *template; - vfd->minor = -1; + vfd->minor = -1; vfd->parent = &dev->udev->dev; vfd->release = video_device_release; vfd->debug = video_debug; - snprintf(vfd->name, sizeof(vfd->name), "%s %s", - dev->name, type_name); + snprintf(vfd->name, sizeof(vfd->name), "%s %s", dev->name, type_name); return vfd; } @@ -2351,15 +2373,16 @@ int cx231xx_register_analog_devices(struct cx231xx *dev) { int ret; - cx231xx_info("%s()\n", __func__); + cx231xx_info("%s()\n", __func__); cx231xx_info("%s: v4l2 driver version %d.%d.%d\n", - dev->name, - (CX231XX_VERSION_CODE >> 16) & 0xff, - (CX231XX_VERSION_CODE >> 8) & 0xff, CX231XX_VERSION_CODE & 0xff); + dev->name, + (CX231XX_VERSION_CODE >> 16) & 0xff, + (CX231XX_VERSION_CODE >> 8) & 0xff, + CX231XX_VERSION_CODE & 0xff); /* set default norm */ - /*dev->norm = cx231xx_video_template.current_norm;*/ + /*dev->norm = cx231xx_video_template.current_norm; */ dev->width = norm_maxw(dev); dev->height = norm_maxh(dev); dev->interlaced = 0; @@ -2375,7 +2398,7 @@ int cx231xx_register_analog_devices(struct cx231xx *dev) dev->volume = 0x1f; /* enable vbi capturing */ - /* write code here... */ + /* write code here... */ /* allocate and fill video video_device struct */ dev->vdev = cx231xx_vdev_init(dev, &cx231xx_video_template, "video"); @@ -2386,37 +2409,38 @@ int cx231xx_register_analog_devices(struct cx231xx *dev) /* register v4l2 video video_device */ ret = video_register_device(dev->vdev, VFL_TYPE_GRABBER, - video_nr[dev->devno]); + video_nr[dev->devno]); if (ret) { - cx231xx_errdev("unable to register video device (error=%i).\n", ret); + cx231xx_errdev("unable to register video device (error=%i).\n", + ret); return ret; } - cx231xx_info("%s/0: registered device video%d [v4l2]\n", - dev->name, dev->vdev->num); - - /* Initialize VBI template */ - memcpy( &cx231xx_vbi_template, &cx231xx_video_template, - sizeof(cx231xx_vbi_template) ); - strcpy(cx231xx_vbi_template.name,"cx231xx-vbi"); + cx231xx_info("%s/0: registered device video%d [v4l2]\n", + dev->name, dev->vdev->num); + /* Initialize VBI template */ + memcpy(&cx231xx_vbi_template, &cx231xx_video_template, + sizeof(cx231xx_vbi_template)); + strcpy(cx231xx_vbi_template.name, "cx231xx-vbi"); /* Allocate and fill vbi video_device struct */ dev->vbi_dev = cx231xx_vdev_init(dev, &cx231xx_vbi_template, "vbi"); /* register v4l2 vbi video_device */ ret = video_register_device(dev->vbi_dev, VFL_TYPE_VBI, - vbi_nr[dev->devno]); + vbi_nr[dev->devno]); if (ret < 0) { cx231xx_errdev("unable to register vbi device\n"); return ret; } - cx231xx_info("%s/0: registered device vbi%d\n", - dev->name, dev->vbi_dev->num); + cx231xx_info("%s/0: registered device vbi%d\n", + dev->name, dev->vbi_dev->num); if (cx231xx_boards[dev->model].radio.type == CX231XX_RADIO) { - dev->radio_dev = cx231xx_vdev_init(dev, &cx231xx_radio_template, "radio"); + dev->radio_dev = + cx231xx_vdev_init(dev, &cx231xx_radio_template, "radio"); if (!dev->radio_dev) { cx231xx_errdev("cannot allocate video_device.\n"); return -ENODEV; @@ -2428,13 +2452,11 @@ int cx231xx_register_analog_devices(struct cx231xx *dev) return ret; } cx231xx_info("Registered radio device as /dev/radio%d\n", - dev->radio_dev->num); + dev->radio_dev->num); } cx231xx_info("V4L2 device registered as /dev/video%d and /dev/vbi%d\n", - dev->vdev->num, dev->vbi_dev->num); + dev->vdev->num, dev->vbi_dev->num); return 0; } - - diff --git a/linux/drivers/media/video/cx231xx/cx231xx.h b/linux/drivers/media/video/cx231xx/cx231xx.h index 5ac7135ea..d88fc89c2 100644 --- a/linux/drivers/media/video/cx231xx/cx231xx.h +++ b/linux/drivers/media/video/cx231xx/cx231xx.h @@ -2,7 +2,7 @@ cx231xx.h - driver for Conexant Cx23100/101/102 USB video capture devices Copyright (C) 2008 - Based on em28xx driver + Based on em28xx driver 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 @@ -66,10 +66,10 @@ /* Params for validated field */ #define CX231XX_BOARD_NOT_VALIDATED 1 -#define CX231XX_BOARD_VALIDATED 0 +#define CX231XX_BOARD_VALIDATED 0 /* maximum number of cx231xx boards */ -#define CX231XX_MAXBOARDS 8 +#define CX231XX_MAXBOARDS 8 /* maximum number of frames that can be queued */ #define CX231XX_NUM_FRAMES 5 @@ -83,17 +83,14 @@ */ #define CX231XX_NUM_PACKETS 40 - /* default alternate; 0 means choose the best */ #define CX231XX_PINOUT 0 #define CX231XX_INTERLACED_DEFAULT 1 - /* time to wait when stopping the isoc transfer */ #define CX231XX_URB_TIMEOUT msecs_to_jiffies(CX231XX_NUM_BUFS * CX231XX_NUM_PACKETS) - enum cx231xx_mode { CX231XX_SUSPEND, CX231XX_ANALOG_MODE, @@ -114,47 +111,45 @@ enum cx231xx_stream_state { struct cx231xx; struct cx231xx_usb_isoc_ctl { - /* max packet size of isoc transaction */ - int max_pkt_size; + /* max packet size of isoc transaction */ + int max_pkt_size; - /* number of allocated urbs */ - int num_bufs; + /* number of allocated urbs */ + int num_bufs; - /* urb for isoc transfers */ - struct urb **urb; + /* urb for isoc transfers */ + struct urb **urb; - /* transfer buffers for isoc transfer */ - char **transfer_buffer; + /* transfer buffers for isoc transfer */ + char **transfer_buffer; - /* Last buffer command and region */ - u8 cmd; - int pos, size, pktsize; + /* Last buffer command and region */ + u8 cmd; + int pos, size, pktsize; - /* Last field: ODD or EVEN? */ - int field; + /* Last field: ODD or EVEN? */ + int field; - /* Stores incomplete commands */ - u32 tmp_buf; - int tmp_buf_len; + /* Stores incomplete commands */ + u32 tmp_buf; + int tmp_buf_len; - /* Stores already requested buffers */ - struct cx231xx_buffer *buf; + /* Stores already requested buffers */ + struct cx231xx_buffer *buf; - /* Stores the number of received fields */ - int nfields; + /* Stores the number of received fields */ + int nfields; - /* isoc urb callback */ - int (*isoc_copy) (struct cx231xx *dev, struct urb *urb); + /* isoc urb callback */ + int (*isoc_copy) (struct cx231xx * dev, struct urb * urb); }; - - struct cx231xx_fmt { - char *name; - u32 fourcc; /* v4l2 format id */ - int depth; - int reg; + char *name; + u32 fourcc; /* v4l2 format id */ + int depth; + int reg; }; /* buffer for one video frame */ @@ -168,24 +163,23 @@ struct cx231xx_buffer { }; struct cx231xx_dmaqueue { - struct list_head active; - struct list_head queued; + struct list_head active; + struct list_head queued; - wait_queue_head_t wq; + wait_queue_head_t wq; /* Counters to control buffer fill */ - int pos; - u8 is_partial_line; - u8 partial_buf[8]; - u8 last_sav; - int current_field; - u32 bytes_left_in_line; - u32 lines_completed; - u8 field1_done; - u32 lines_per_field; + int pos; + u8 is_partial_line; + u8 partial_buf[8]; + u8 last_sav; + int current_field; + u32 bytes_left_in_line; + u32 lines_completed; + u8 field1_done; + u32 lines_per_field; }; - /* inputs */ #define MAX_CX231XX_INPUT 4 @@ -194,35 +188,35 @@ enum cx231xx_itype { CX231XX_VMUX_COMPOSITE1 = 1, CX231XX_VMUX_SVIDEO, CX231XX_VMUX_TELEVISION, - CX231XX_VMUX_CABLE, - CX231XX_RADIO, - CX231XX_VMUX_DVB, + CX231XX_VMUX_CABLE, + CX231XX_RADIO, + CX231XX_VMUX_DVB, CX231XX_VMUX_DEBUG }; enum cx231xx_v_input { - CX231XX_VIN_1_1 = 0x1, - CX231XX_VIN_2_1, - CX231XX_VIN_3_1, - CX231XX_VIN_4_1, - CX231XX_VIN_1_2 = 0x01, - CX231XX_VIN_2_2, - CX231XX_VIN_3_2, - CX231XX_VIN_1_3 = 0x1, - CX231XX_VIN_2_3, - CX231XX_VIN_3_3, + CX231XX_VIN_1_1 = 0x1, + CX231XX_VIN_2_1, + CX231XX_VIN_3_1, + CX231XX_VIN_4_1, + CX231XX_VIN_1_2 = 0x01, + CX231XX_VIN_2_2, + CX231XX_VIN_3_2, + CX231XX_VIN_1_3 = 0x1, + CX231XX_VIN_2_3, + CX231XX_VIN_3_3, }; /* cx231xx has two audio inputs: tuner and line in */ enum cx231xx_amux { /* This is the only entry for cx231xx tuner input */ - CX231XX_AMUX_VIDEO, /* cx231xx tuner*/ + CX231XX_AMUX_VIDEO, /* cx231xx tuner */ CX231XX_AMUX_LINE_IN, /* Line In */ }; struct cx231xx_reg_seq { unsigned char bit; - unsigned char val; + unsigned char val; int sleep; }; @@ -240,41 +234,40 @@ enum cx231xx_decoder { CX231XX_AVDECODER }; -typedef enum _I2C_MASTER_PORT -{ - I2C_0 =0, - I2C_1 =1, - I2C_2 =2, - I2C_3 =3 -}CX231XX_I2C_MASTER_PORT; +typedef enum _I2C_MASTER_PORT { + I2C_0 = 0, + I2C_1 = 1, + I2C_2 = 2, + I2C_3 = 3 +} CX231XX_I2C_MASTER_PORT; struct cx231xx_board { char *name; int vchannels; int tuner_type; int tuner_addr; - v4l2_std_id norm; /* tv norm */ - - /* demod related */ - int demod_addr; - u8 demod_xfer_mode; /* 0 - Serial; 1 - parallel */ + v4l2_std_id norm; /* tv norm */ + + /* demod related */ + int demod_addr; + u8 demod_xfer_mode; /* 0 - Serial; 1 - parallel */ /* GPIO Pins */ struct cx231xx_reg_seq *dvb_gpio; struct cx231xx_reg_seq *suspend_gpio; struct cx231xx_reg_seq *tuner_gpio; - u8 tuner_sif_gpio; - u8 tuner_scl_gpio; - u8 tuner_sda_gpio; + u8 tuner_sif_gpio; + u8 tuner_scl_gpio; + u8 tuner_sda_gpio; - /* PIN ctrl */ - u32 ctl_pin_status_mask; - u8 agc_analog_digital_select_gpio; - u32 gpio_pin_status_mask; + /* PIN ctrl */ + u32 ctl_pin_status_mask; + u8 agc_analog_digital_select_gpio; + u32 gpio_pin_status_mask; - /* i2c masters */ - u8 tuner_i2c_master; - u8 demod_i2c_master; + /* i2c masters */ + u8 tuner_i2c_master; + u8 demod_i2c_master; unsigned int max_range_640_480:1; unsigned int has_dvb:1; @@ -284,9 +277,9 @@ struct cx231xx_board { enum cx231xx_decoder decoder; - struct cx231xx_input input[MAX_CX231XX_INPUT]; - struct cx231xx_input radio; - IR_KEYTAB_TYPE *ir_codes; + struct cx231xx_input input[MAX_CX231XX_INPUT]; + struct cx231xx_input radio; + IR_KEYTAB_TYPE *ir_codes; }; /* device states */ @@ -296,22 +289,20 @@ enum cx231xx_dev_state { DEV_MISCONFIGURED = 0x04, }; -enum AFE_MODE -{ - AFE_MODE_LOW_IF, - AFE_MODE_BASEBAND, - AFE_MODE_EU_HI_IF, - AFE_MODE_US_HI_IF, - AFE_MODE_JAPAN_HI_IF +enum AFE_MODE { + AFE_MODE_LOW_IF, + AFE_MODE_BASEBAND, + AFE_MODE_EU_HI_IF, + AFE_MODE_US_HI_IF, + AFE_MODE_JAPAN_HI_IF }; -enum AUDIO_INPUT -{ - AUDIO_INPUT_MUTE, - AUDIO_INPUT_LINE, - AUDIO_INPUT_TUNER_TV, - AUDIO_INPUT_SPDIF, - AUDIO_INPUT_TUNER_FM +enum AUDIO_INPUT { + AUDIO_INPUT_MUTE, + AUDIO_INPUT_LINE, + AUDIO_INPUT_TUNER_TV, + AUDIO_INPUT_SPDIF, + AUDIO_INPUT_TUNER_FM }; #define CX231XX_AUDIO_BUFS 5 @@ -320,7 +311,6 @@ enum AUDIO_INPUT #define CX231XX_STOP_AUDIO 0 #define CX231XX_START_AUDIO 1 - /* cx231xx extensions */ #define CX231XX_AUDIO 0x10 #define CX231XX_DVB 0x20 @@ -332,176 +322,174 @@ struct cx231xx_audio { struct usb_device *udev; unsigned int capture_transfer_done; #if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 16) - snd_pcm_substream_t *capture_pcm_substream; + snd_pcm_substream_t *capture_pcm_substream; #else - struct snd_pcm_substream *capture_pcm_substream; + struct snd_pcm_substream *capture_pcm_substream; #endif unsigned int hwptr_done_capture; #if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 16) - snd_card_t *sndcard; + snd_card_t *sndcard; #else - struct snd_card *sndcard; + struct snd_card *sndcard; #endif int users, shutdown; enum cx231xx_stream_state capture_stream; spinlock_t slock; - int alt; /* alternate */ - int max_pkt_size; /* max packet size of isoc transaction */ - int num_alt; /* Number of alternative settings */ + int alt; /* alternate */ + int max_pkt_size; /* max packet size of isoc transaction */ + int num_alt; /* Number of alternative settings */ unsigned int *alt_max_pkt_size; /* array of wMaxPacketSize */ - u16 end_point_addr; + u16 end_point_addr; }; struct cx231xx; struct cx231xx_fh { struct cx231xx *dev; - unsigned int stream_on:1; /* Locks streams */ - int radio; + unsigned int stream_on:1; /* Locks streams */ + int radio; - struct videobuf_queue vb_vidq; + struct videobuf_queue vb_vidq; - enum v4l2_buf_type type; + enum v4l2_buf_type type; }; /**********************************************************************************/ /* set/get i2c */ -#define I2C_SPEED_1M 0x0 /* 00--1Mb/s, 01-400kb/s, 10--100kb/s, 11--5Mb/s */ -#define I2C_SPEED_400K 0x1 /* 00--1Mb/s, 01-400kb/s, 10--100kb/s, 11--5Mb/s */ -#define I2C_SPEED_100K 0x2 /* 00--1Mb/s, 01-400kb/s, 10--100kb/s, 11--5Mb/s */ -#define I2C_SPEED_5M 0x3 /* 00--1Mb/s, 01-400kb/s, 10--100kb/s, 11--5Mb/s */ +#define I2C_SPEED_1M 0x0 /* 00--1Mb/s, 01-400kb/s, 10--100kb/s, 11--5Mb/s */ +#define I2C_SPEED_400K 0x1 /* 00--1Mb/s, 01-400kb/s, 10--100kb/s, 11--5Mb/s */ +#define I2C_SPEED_100K 0x2 /* 00--1Mb/s, 01-400kb/s, 10--100kb/s, 11--5Mb/s */ +#define I2C_SPEED_5M 0x3 /* 00--1Mb/s, 01-400kb/s, 10--100kb/s, 11--5Mb/s */ -#define I2C_STOP 0x0 /* 0-- STOP transaction */ -#define I2C_NOSTOP 0x1 /* 1-- do not transmit STOP at end of transaction */ -#define I2C_SYNC 0x1 /* 1--alllow slave to insert clock wait states */ +#define I2C_STOP 0x0 /* 0-- STOP transaction */ +#define I2C_NOSTOP 0x1 /* 1-- do not transmit STOP at end of transaction */ +#define I2C_SYNC 0x1 /* 1--alllow slave to insert clock wait states */ struct cx231xx_i2c { - struct cx231xx *dev; + struct cx231xx *dev; - int nr; + int nr; /* i2c i/o */ - struct i2c_adapter i2c_adap; - struct i2c_algo_bit_data i2c_algo; - struct i2c_client i2c_client; - u32 i2c_rc; + struct i2c_adapter i2c_adap; + struct i2c_algo_bit_data i2c_algo; + struct i2c_client i2c_client; + u32 i2c_rc; /* different settings for each bus */ - u8 i2c_period; - u8 i2c_nostop; - u8 i2c_reserve; + u8 i2c_period; + u8 i2c_nostop; + u8 i2c_reserve; }; -struct cx231xx_i2c_xfer_data{ - u8 dev_addr; - u8 direction; /* 1 - IN, 0 - OUT */ - u8 saddr_len; /* sub address len */ - u16 saddr_dat; /* sub addr data */ - u8 buf_size; /* buffer size */ - u8* p_buffer; /* pointer to the buffer */ +struct cx231xx_i2c_xfer_data { + u8 dev_addr; + u8 direction; /* 1 - IN, 0 - OUT */ + u8 saddr_len; /* sub address len */ + u16 saddr_dat; /* sub addr data */ + u8 buf_size; /* buffer size */ + u8 *p_buffer; /* pointer to the buffer */ }; -typedef struct _VENDOR_REQUEST_IN -{ - u8 bRequest; - u16 wValue; - u16 wIndex; - u16 wLength; - u8 direction; - u8 bData; - u8 *pBuff; +typedef struct _VENDOR_REQUEST_IN { + u8 bRequest; + u16 wValue; + u16 wIndex; + u16 wLength; + u8 direction; + u8 bData; + u8 *pBuff; } VENDOR_REQUEST_IN, *PVENDOR_REQUEST_IN; struct cx231xx_ctrl { struct v4l2_queryctrl v; - u32 off; - u32 reg; - u32 mask; - u32 shift; + u32 off; + u32 reg; + u32 mask; + u32 shift; }; -typedef enum{ - Raw_Video = 0, - Audio, - Vbi, /* VANC */ - Sliced_cc, /* HANC */ - TS1_serial_mode, - TS2, - TS1_parallel_mode -}TRANSFER_TYPE; +typedef enum { + Raw_Video = 0, + Audio, + Vbi, /* VANC */ + Sliced_cc, /* HANC */ + TS1_serial_mode, + TS2, + TS1_parallel_mode +} TRANSFER_TYPE; struct cx231xx_video_mode { - /* Isoc control struct */ + /* Isoc control struct */ struct cx231xx_dmaqueue vidq; struct cx231xx_usb_isoc_ctl isoc_ctl; spinlock_t slock; /* usb transfer */ - int alt; /* alternate */ - int max_pkt_size; /* max packet size of isoc transaction */ - int num_alt; /* Number of alternative settings */ + int alt; /* alternate */ + int max_pkt_size; /* max packet size of isoc transaction */ + int num_alt; /* Number of alternative settings */ unsigned int *alt_max_pkt_size; /* array of wMaxPacketSize */ - u16 end_point_addr; + u16 end_point_addr; }; - /* main device struct */ struct cx231xx { /* generic device properties */ - char name[30]; /* name (including minor) of the device */ - int model; /* index in the device_data struct */ - int devno; /* marks the number of this device */ + char name[30]; /* name (including minor) of the device */ + int model; /* index in the device_data struct */ + int devno; /* marks the number of this device */ struct cx231xx_board board; - unsigned int stream_on:1; /* Locks streams */ - unsigned int vbi_stream_on:1; /* Locks streams for VBI */ + unsigned int stream_on:1; /* Locks streams */ + unsigned int vbi_stream_on:1; /* Locks streams for VBI */ unsigned int has_audio_class:1; unsigned int has_alsa_audio:1; - struct cx231xx_fmt *format; + struct cx231xx_fmt *format; struct cx231xx_IR *ir; - struct list_head devlist; + struct list_head devlist; - int tuner_type; /* type of the tuner */ - int tuner_addr; /* tuner address */ + int tuner_type; /* type of the tuner */ + int tuner_addr; /* tuner address */ - /* I2C adapters: Master 1 & 2 (External) & Master 3 (Internal only) */ - struct cx231xx_i2c i2c_bus[3]; - unsigned int xc_fw_load_done:1; - struct mutex gpio_i2c_lock; + /* I2C adapters: Master 1 & 2 (External) & Master 3 (Internal only) */ + struct cx231xx_i2c i2c_bus[3]; + unsigned int xc_fw_load_done:1; + struct mutex gpio_i2c_lock; /* video for linux */ - int users; /* user count for exclusive use */ - struct video_device *vdev; /* video for linux device struct */ - v4l2_std_id norm; /* selected tv norm */ - int ctl_freq; /* selected frequency */ - unsigned int ctl_ainput; /* selected audio input */ + int users; /* user count for exclusive use */ + struct video_device *vdev; /* video for linux device struct */ + v4l2_std_id norm; /* selected tv norm */ + int ctl_freq; /* selected frequency */ + unsigned int ctl_ainput; /* selected audio input */ int mute; int volume; /* frame properties */ - int width; /* current frame width */ - int height; /* current frame height */ - unsigned hscale; /* horizontal scale factor (see datasheet) */ - unsigned vscale; /* vertical scale factor (see datasheet) */ - int interlaced; /* 1=interlace fileds, 0=just top fileds */ + int width; /* current frame width */ + int height; /* current frame height */ + unsigned hscale; /* horizontal scale factor (see datasheet) */ + unsigned vscale; /* vertical scale factor (see datasheet) */ + int interlaced; /* 1=interlace fileds, 0=just top fileds */ struct cx231xx_audio adev; /* states */ enum cx231xx_dev_state state; - struct work_struct request_module_wk; + struct work_struct request_module_wk; /* locks */ struct mutex lock; - struct mutex ctrl_urb_lock; /* protects urb_buf */ + struct mutex ctrl_urb_lock; /* protects urb_buf */ struct list_head inqueue, outqueue; wait_queue_head_t open, wait_frame, wait_stream; struct video_device *vbi_dev; @@ -509,54 +497,56 @@ struct cx231xx { unsigned char eedata[256]; - struct cx231xx_video_mode video_mode; - struct cx231xx_video_mode vbi_mode; - struct cx231xx_video_mode sliced_cc_mode; - struct cx231xx_video_mode ts1_mode; - - struct usb_device *udev; /* the usb device */ - char urb_buf[URB_MAX_CTRL_SIZE];/* urb control msg buffer */ + struct cx231xx_video_mode video_mode; + struct cx231xx_video_mode vbi_mode; + struct cx231xx_video_mode sliced_cc_mode; + struct cx231xx_video_mode ts1_mode; + struct usb_device *udev; /* the usb device */ + char urb_buf[URB_MAX_CTRL_SIZE]; /* urb control msg buffer */ /* helper funcs that call usb_control_msg */ - int (*cx231xx_read_ctrl_reg) (struct cx231xx *dev, u8 req, u16 reg, - char *buf, int len); - int (*cx231xx_write_ctrl_reg)(struct cx231xx *dev, u8 req, u16 reg, + int (*cx231xx_read_ctrl_reg) (struct cx231xx * dev, u8 req, u16 reg, char *buf, int len); - int (*cx231xx_send_usb_command)(struct cx231xx_i2c *i2c_bus, - struct cx231xx_i2c_xfer_data *req_data); - int (*cx231xx_gpio_i2c_read)(struct cx231xx *dev, u8 dev_addr, u8 *buf ,u8 len); - int (*cx231xx_gpio_i2c_write)(struct cx231xx *dev, u8 dev_addr, u8 *buf ,u8 len); - - int (*cx231xx_set_analog_freq)(struct cx231xx *dev, u32 freq ) ; - int (*cx231xx_reset_analog_tuner)(struct cx231xx *dev) ; + int (*cx231xx_write_ctrl_reg) (struct cx231xx * dev, u8 req, u16 reg, + char *buf, int len); + int (*cx231xx_send_usb_command) (struct cx231xx_i2c * i2c_bus, + struct cx231xx_i2c_xfer_data * + req_data); + int (*cx231xx_gpio_i2c_read) (struct cx231xx * dev, u8 dev_addr, + u8 * buf, u8 len); + int (*cx231xx_gpio_i2c_write) (struct cx231xx * dev, u8 dev_addr, + u8 * buf, u8 len); + + int (*cx231xx_set_analog_freq) (struct cx231xx * dev, u32 freq); + int (*cx231xx_reset_analog_tuner) (struct cx231xx * dev); enum cx231xx_mode mode; struct cx231xx_dvb *dvb; - /* Cx231xx supported PCB config's */ - struct pcb_config current_pcb_config; - u8 current_scenario_idx; - u8 interface_count; - u8 max_iad_interface_count; + /* Cx231xx supported PCB config's */ + struct pcb_config current_pcb_config; + u8 current_scenario_idx; + u8 interface_count; + u8 max_iad_interface_count; - /* GPIO related register direction and values */ - u32 gpio_dir; - u32 gpio_val; + /* GPIO related register direction and values */ + u32 gpio_dir; + u32 gpio_val; - /* Power Modes */ - int power_mode; + /* Power Modes */ + int power_mode; - /* colibri parameters */ - enum AFE_MODE colibri_mode; - u32 colibri_ref_count; + /* colibri parameters */ + enum AFE_MODE colibri_mode; + u32 colibri_ref_count; - /* video related parameters */ - u32 video_input; - u32 active_mode; - u8 vbi_or_sliced_cc_mode; /* 0 - vbi ; 1 - sliced cc mode */ - enum cx231xx_std_mode std_mode; /* 0 - Air; 1 - cable */ + /* video related parameters */ + u32 video_input; + u32 active_mode; + u8 vbi_or_sliced_cc_mode; /* 0 - vbi ; 1 - sliced cc mode */ + enum cx231xx_std_mode std_mode; /* 0 - Air; 1 - cable */ }; @@ -564,29 +554,31 @@ struct cx231xx_ops { struct list_head next; char *name; int id; - int (*init)(struct cx231xx *); - int (*fini)(struct cx231xx *); + int (*init) (struct cx231xx *); + int (*fini) (struct cx231xx *); }; /* call back functions in dvb module */ -int cx231xx_set_analog_freq(struct cx231xx *dev, u32 freq ) ; -int cx231xx_reset_analog_tuner(struct cx231xx *dev) ; +int cx231xx_set_analog_freq(struct cx231xx *dev, u32 freq); +int cx231xx_reset_analog_tuner(struct cx231xx *dev); /* Provided by cx231xx-i2c.c */ -void cx231xx_i2c_call_clients(struct cx231xx_i2c *bus, unsigned int cmd, void *arg); +void cx231xx_i2c_call_clients(struct cx231xx_i2c *bus, unsigned int cmd, + void *arg); void cx231xx_do_i2c_scan(struct cx231xx *dev, struct i2c_client *c); int cx231xx_i2c_register(struct cx231xx_i2c *bus); int cx231xx_i2c_unregister(struct cx231xx_i2c *bus); /* Internal block control functions */ -int cx231xx_read_i2c_data(struct cx231xx *dev, u8 dev_addr, - u16 saddr, u8 saddr_len, u32 *data, u8 data_len); -int cx231xx_write_i2c_data(struct cx231xx *dev, u8 dev_addr, - u16 saddr, u8 saddr_len, u32 data, u8 data_len); -int cx231xx_reg_mask_write(struct cx231xx *dev, u8 dev_addr, u8 size, u16 register_address, - u8 bit_start,u8 bit_end, u32 value); -int cx231xx_read_modify_write_i2c_dword(struct cx231xx *dev, u8 dev_addr, - u16 saddr, u32 mask, u32 value); +int cx231xx_read_i2c_data(struct cx231xx *dev, u8 dev_addr, + u16 saddr, u8 saddr_len, u32 * data, u8 data_len); +int cx231xx_write_i2c_data(struct cx231xx *dev, u8 dev_addr, + u16 saddr, u8 saddr_len, u32 data, u8 data_len); +int cx231xx_reg_mask_write(struct cx231xx *dev, u8 dev_addr, u8 size, + u16 register_address, u8 bit_start, u8 bit_end, + u32 value); +int cx231xx_read_modify_write_i2c_dword(struct cx231xx *dev, u8 dev_addr, + u16 saddr, u32 mask, u32 value); u32 cx231xx_set_field(u32 field_mask, u32 data); /* Colibri related functions */ @@ -604,24 +596,27 @@ int cx231xx_flatiron_update_power_control(struct cx231xx *dev, AV_MODE avmode); int cx231xx_flatiron_set_audio_input(struct cx231xx *dev, u8 audio_input); /* DIF related functions */ -int cx231xx_dif_configure_C2HH_for_low_IF(struct cx231xx *dev, u32 mode, - u32 function_mode, u32 standard); +int cx231xx_dif_configure_C2HH_for_low_IF(struct cx231xx *dev, u32 mode, + u32 function_mode, u32 standard); int cx231xx_dif_set_standard(struct cx231xx *dev, u32 standard); int cx231xx_tuner_pre_channel_change(struct cx231xx *dev); int cx231xx_tuner_post_channel_change(struct cx231xx *dev); /* video parser functions */ -u8 cx231xx_find_next_SAV_EAV(u8 *p_buffer, u32 buffer_size, u32 *p_bytes_used); -u8 cx231xx_find_boundary_SAV_EAV(u8 *p_buffer, u8 *partial_buf, u32 *p_bytes_used); +u8 cx231xx_find_next_SAV_EAV(u8 * p_buffer, u32 buffer_size, + u32 * p_bytes_used); +u8 cx231xx_find_boundary_SAV_EAV(u8 * p_buffer, u8 * partial_buf, + u32 * p_bytes_used); int cx231xx_do_copy(struct cx231xx *dev, struct cx231xx_dmaqueue *dma_q, - u8 *p_buffer, u32 bytes_to_copy); -void cx231xx_reset_video_buffer(struct cx231xx *dev, struct cx231xx_dmaqueue *dma_q); -u8 cx231xx_is_buffer_done(struct cx231xx *dev,struct cx231xx_dmaqueue *dma_q); -u32 cx231xx_copy_video_line(struct cx231xx *dev, struct cx231xx_dmaqueue *dma_q, - u8 *p_line, u32 length, int field_number); -u32 cx231xx_get_video_line(struct cx231xx *dev, struct cx231xx_dmaqueue *dma_q, - u8 sav_eav, u8 *p_buffer, u32 buffer_size); -void cx231xx_swab(u16 *from, u16 *to, u16 len); + u8 * p_buffer, u32 bytes_to_copy); +void cx231xx_reset_video_buffer(struct cx231xx *dev, + struct cx231xx_dmaqueue *dma_q); +u8 cx231xx_is_buffer_done(struct cx231xx *dev, struct cx231xx_dmaqueue *dma_q); +u32 cx231xx_copy_video_line(struct cx231xx *dev, struct cx231xx_dmaqueue *dma_q, + u8 * p_line, u32 length, int field_number); +u32 cx231xx_get_video_line(struct cx231xx *dev, struct cx231xx_dmaqueue *dma_q, + u8 sav_eav, u8 * p_buffer, u32 buffer_size); +void cx231xx_swab(u16 * from, u16 * to, u16 len); /* Provided by cx231xx-core.c */ @@ -631,46 +626,49 @@ void cx231xx_release_buffers(struct cx231xx *dev); /* read from control pipe */ int cx231xx_read_ctrl_reg(struct cx231xx *dev, u8 req, u16 reg, - char *buf, int len); + char *buf, int len); /* write to control pipe */ int cx231xx_write_ctrl_reg(struct cx231xx *dev, u8 req, u16 reg, - char *buf, int len); + char *buf, int len); int cx231xx_mode_register(struct cx231xx *dev, u16 address, u32 mode); -int cx231xx_send_vendor_cmd(struct cx231xx *dev, VENDOR_REQUEST_IN *ven_req); -int cx231xx_send_usb_command(struct cx231xx_i2c *i2c_bus, - struct cx231xx_i2c_xfer_data *req_data); +int cx231xx_send_vendor_cmd(struct cx231xx *dev, VENDOR_REQUEST_IN * ven_req); +int cx231xx_send_usb_command(struct cx231xx_i2c *i2c_bus, + struct cx231xx_i2c_xfer_data *req_data); /* Gpio related functions */ -int cx231xx_send_gpio_cmd(struct cx231xx *dev, u32 gpio_bit, u8* gpio_val, - u8 len, u8 request, u8 direction); -int cx231xx_set_gpio_bit(struct cx231xx *dev, u32 gpio_bit, u8* gpio_val); -int cx231xx_get_gpio_bit(struct cx231xx *dev, u32 gpio_bit, u8* gpio_val); +int cx231xx_send_gpio_cmd(struct cx231xx *dev, u32 gpio_bit, u8 * gpio_val, + u8 len, u8 request, u8 direction); +int cx231xx_set_gpio_bit(struct cx231xx *dev, u32 gpio_bit, u8 * gpio_val); +int cx231xx_get_gpio_bit(struct cx231xx *dev, u32 gpio_bit, u8 * gpio_val); int cx231xx_set_gpio_value(struct cx231xx *dev, int pin_number, int pin_value); -int cx231xx_set_gpio_direction(struct cx231xx *dev, int pin_number, int pin_value); +int cx231xx_set_gpio_direction(struct cx231xx *dev, int pin_number, + int pin_value); int cx231xx_gpio_i2c_start(struct cx231xx *dev); int cx231xx_gpio_i2c_end(struct cx231xx *dev); int cx231xx_gpio_i2c_write_byte(struct cx231xx *dev, u8 data); -int cx231xx_gpio_i2c_read_byte(struct cx231xx *dev, u8 *buf); +int cx231xx_gpio_i2c_read_byte(struct cx231xx *dev, u8 * buf); int cx231xx_gpio_i2c_read_ack(struct cx231xx *dev); int cx231xx_gpio_i2c_write_ack(struct cx231xx *dev); int cx231xx_gpio_i2c_write_nak(struct cx231xx *dev); -int cx231xx_gpio_i2c_read(struct cx231xx *dev, u8 dev_addr, u8 *buf ,u8 len); -int cx231xx_gpio_i2c_write(struct cx231xx *dev, u8 dev_addr, u8 *buf ,u8 len); +int cx231xx_gpio_i2c_read(struct cx231xx *dev, u8 dev_addr, u8 * buf, u8 len); +int cx231xx_gpio_i2c_write(struct cx231xx *dev, u8 dev_addr, u8 * buf, u8 len); /* audio related functions */ -int cx231xx_set_audio_decoder_input(struct cx231xx *dev, enum AUDIO_INPUT audio_input); +int cx231xx_set_audio_decoder_input(struct cx231xx *dev, + enum AUDIO_INPUT audio_input); int cx231xx_capture_start(struct cx231xx *dev, int start, u8 media_type); int cx231xx_resolution_set(struct cx231xx *dev); int cx231xx_set_video_alternate(struct cx231xx *dev); int cx231xx_set_alt_setting(struct cx231xx *dev, u8 index, u8 alt); int cx231xx_init_isoc(struct cx231xx *dev, int max_packets, - int num_bufs, int max_pkt_size, - int (*isoc_copy) (struct cx231xx *dev, struct urb *urb)); + int num_bufs, int max_pkt_size, + int (*isoc_copy) (struct cx231xx * dev, + struct urb * urb)); void cx231xx_uninit_isoc(struct cx231xx *dev); int cx231xx_set_mode(struct cx231xx *dev, enum cx231xx_mode set_mode); int cx231xx_gpio_set(struct cx231xx *dev, struct cx231xx_reg_seq *gpio); @@ -682,7 +680,7 @@ int cx231xx_register_analog_devices(struct cx231xx *dev); void cx231xx_remove_from_devlist(struct cx231xx *dev); void cx231xx_add_into_devlist(struct cx231xx *dev); struct cx231xx *cx231xx_get_device(int minor, - enum v4l2_buf_type *fh_type, int *has_radio); + enum v4l2_buf_type *fh_type, int *has_radio); void cx231xx_init_extension(struct cx231xx *dev); void cx231xx_close_extension(struct cx231xx *dev); @@ -704,7 +702,8 @@ int cx231xx_power_suspend(struct cx231xx *dev); /* chip specific control functions */ int cx231xx_init_ctrl_pin_status(struct cx231xx *dev); -int cx231xx_set_agc_analog_digital_mux_select(struct cx231xx *dev, u8 analog_or_digital); +int cx231xx_set_agc_analog_digital_mux_select(struct cx231xx *dev, + u8 analog_or_digital); int cx231xx_enable_i2c_for_tuner(struct cx231xx *dev, u8 I2CIndex); /* video audio decoder related functions */ @@ -714,8 +713,8 @@ int cx231xx_set_decoder_video_input(struct cx231xx *dev, u8 pin_type, u8 input); int cx231xx_do_mode_ctrl_overrides(struct cx231xx *dev); int cx231xx_set_audio_input(struct cx231xx *dev, u8 input); void get_scale(struct cx231xx *dev, - unsigned int width, unsigned int height, - unsigned int *hscale, unsigned int *vscale); + unsigned int width, unsigned int height, + unsigned int *hscale, unsigned int *vscale); /* Provided by cx231xx-video.c */ int cx231xx_register_extension(struct cx231xx_ops *dev); @@ -752,7 +751,6 @@ int cx231xx_ir_fini(struct cx231xx *dev); printk(KERN_WARNING "%s: "fmt,\ dev->name , ##arg); } while (0) - static inline unsigned int norm_maxw(struct cx231xx *dev) { if (dev->board.max_range_640_480) -- cgit v1.2.3 From 1e59b30169044ec05336c5df466b489b4f98c587 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 3 Mar 2009 13:31:36 -0300 Subject: cx231xx: First series of manual CodingStyle fixes From: Mauro Carvalho Chehab This patch cleans up CodingStyle on the following source files: There are still much more to be fixed on later patches Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/cx231xx/Kconfig | 8 +- linux/drivers/media/video/cx231xx/cx231xx-audio.c | 55 +- linux/drivers/media/video/cx231xx/cx231xx-avcore.c | 2104 +++++++++----------- linux/drivers/media/video/cx231xx/cx231xx-vbi.c | 86 +- linux/drivers/media/video/cx231xx/cx231xx-video.c | 595 +++--- linux/drivers/media/video/cx231xx/cx231xx.h | 60 +- 6 files changed, 1275 insertions(+), 1633 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/cx231xx/Kconfig b/linux/drivers/media/video/cx231xx/Kconfig index f39d26924..0f0e2b9d9 100644 --- a/linux/drivers/media/video/cx231xx/Kconfig +++ b/linux/drivers/media/video/cx231xx/Kconfig @@ -7,23 +7,23 @@ config VIDEO_CX231XX select VIDEOBUF_VMALLOC select VIDEO_CX25840 select VIDEO_CX231XX_ALSA - + ---help--- This is a video4linux driver for Conexant 231xx USB based TV cards. To compile this driver as a module, choose M here: the module will be called cx231xx - + config VIDEO_CX231XX_ALSA tristate "Conexant Cx231xx ALSA audio module" depends on VIDEO_CX231XX && SND select SND_PCM - + ---help--- This is an ALSA driver for Cx231xx USB based TV cards. To compile this driver as a module, choose M here: the - module will be called cx231xx-alsa + module will be called cx231xx-alsa config VIDEO_CX231XX_DVB tristate "DVB/ATSC Support for Cx231xx based TV cards" diff --git a/linux/drivers/media/video/cx231xx/cx231xx-audio.c b/linux/drivers/media/video/cx231xx/cx231xx-audio.c index b6db68a5c..69e5e6ed5 100644 --- a/linux/drivers/media/video/cx231xx/cx231xx-audio.c +++ b/linux/drivers/media/video/cx231xx/cx231xx-audio.c @@ -71,7 +71,6 @@ static int cx231xx_isoc_audio_deinit(struct cx231xx *dev) kfree(dev->adev.transfer_buffer[i]); dev->adev.transfer_buffer[i] = NULL; - } } @@ -121,10 +120,10 @@ static void cx231xx_audio_isocirq(struct urb *urb) stride = runtime->frame_bits >> 3; for (i = 0; i < urb->number_of_packets; i++) { - int length = - urb->iso_frame_desc[i].actual_length / stride; + int length = urb->iso_frame_desc[i].actual_length / + stride; cp = (unsigned char *)urb->transfer_buffer + - urb->iso_frame_desc[i].offset; + urb->iso_frame_desc[i].offset; if (!length) continue; @@ -134,8 +133,9 @@ static void cx231xx_audio_isocirq(struct urb *urb) #endif oldptr = dev->adev.hwptr_done_capture; if (oldptr + length >= runtime->buffer_size) { - unsigned int cnt = - runtime->buffer_size - oldptr; + unsigned int cnt; + + cnt = runtime->buffer_size - oldptr; memcpy(runtime->dma_area + oldptr * stride, cp, cnt * stride); memcpy(runtime->dma_area, cp + cnt * stride, @@ -150,16 +150,12 @@ static void cx231xx_audio_isocirq(struct urb *urb) #endif dev->adev.hwptr_done_capture += length; - if (dev->adev.hwptr_done_capture >= - runtime->buffer_size) - dev->adev.hwptr_done_capture -= - runtime->buffer_size; + if (dev->adev.hwptr_done_capture >= runtime->buffer_size) + dev->adev.hwptr_done_capture -= runtime->buffer_size; dev->adev.capture_transfer_done += length; - if (dev->adev.capture_transfer_done >= - runtime->period_size) { - dev->adev.capture_transfer_done -= - runtime->period_size; + if (dev->adev.capture_transfer_done >= runtime->period_size) { + dev->adev.capture_transfer_done -= runtime->period_size; period_elapsed = 1; } #ifdef NO_PCM_LOCK @@ -211,8 +207,7 @@ static int cx231xx_init_audio_isoc(struct cx231xx *dev) urb->dev = dev->udev; urb->context = dev; - urb->pipe = - usb_rcvisocpipe(dev->udev, dev->adev.end_point_addr); + urb->pipe = usb_rcvisocpipe(dev->udev, dev->adev.end_point_addr); urb->transfer_flags = URB_ISO_ASAP; urb->transfer_buffer = dev->adev.transfer_buffer[i]; urb->interval = 1; @@ -220,8 +215,7 @@ static int cx231xx_init_audio_isoc(struct cx231xx *dev) urb->number_of_packets = CX231XX_NUM_AUDIO_PACKETS; urb->transfer_buffer_length = sb_size; - for (j = k = 0; j < CX231XX_NUM_AUDIO_PACKETS; - j++, k += dev->adev.max_pkt_size) { + for (j = k = 0; j < CX231XX_NUM_AUDIO_PACKETS; j++, k += dev->adev.max_pkt_size) { urb->iso_frame_desc[j].offset = k; urb->iso_frame_desc[j].length = dev->adev.max_pkt_size; } @@ -263,7 +257,7 @@ static int cx231xx_cmd(struct cx231xx *dev, int cmd, int arg) } #if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 16) -static int snd_pcm_alloc_vmalloc_buffer(snd_pcm_substream_t * subs, size_t size) +static int snd_pcm_alloc_vmalloc_buffer(snd_pcm_substream_t *subs, size_t size) #else static int snd_pcm_alloc_vmalloc_buffer(struct snd_pcm_substream *subs, size_t size) @@ -309,14 +303,14 @@ static struct snd_pcm_hardware snd_cx231xx_hw_capture = { .channels_min = 2, .channels_max = 2, .buffer_bytes_max = 62720 * 8, /* just about the value in usbaudio.c */ - .period_bytes_min = 64, /* 12544/2, */ + .period_bytes_min = 64, /* 12544/2, */ .period_bytes_max = 12544, .periods_min = 2, - .periods_max = 98, /* 12544, */ + .periods_max = 98, /* 12544, */ }; #if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 16) -static int snd_cx231xx_capture_open(snd_pcm_substream_t * substream) +static int snd_cx231xx_capture_open(snd_pcm_substream_t *substream) #else static int snd_cx231xx_capture_open(struct snd_pcm_substream *substream) #endif @@ -365,7 +359,7 @@ static int snd_cx231xx_capture_open(struct snd_pcm_substream *substream) } #if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 16) -static int snd_cx231xx_pcm_close(snd_pcm_substream_t * substream) +static int snd_cx231xx_pcm_close(snd_pcm_substream_t *substream) #else static int snd_cx231xx_pcm_close(struct snd_pcm_substream *substream) #endif @@ -402,8 +396,8 @@ static int snd_cx231xx_pcm_close(struct snd_pcm_substream *substream) } #if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 16) -static int snd_cx231xx_hw_capture_params(snd_pcm_substream_t * substream, - snd_pcm_hw_params_t * hw_params) +static int snd_cx231xx_hw_capture_params(snd_pcm_substream_t *substream, + snd_pcm_hw_params_t *hw_params) #else static int snd_cx231xx_hw_capture_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *hw_params) @@ -427,7 +421,7 @@ static int snd_cx231xx_hw_capture_params(struct snd_pcm_substream *substream, } #if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 16) -static int snd_cx231xx_hw_capture_free(snd_pcm_substream_t * substream) +static int snd_cx231xx_hw_capture_free(snd_pcm_substream_t *substream) #else static int snd_cx231xx_hw_capture_free(struct snd_pcm_substream *substream) #endif @@ -443,7 +437,7 @@ static int snd_cx231xx_hw_capture_free(struct snd_pcm_substream *substream) } #if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 16) -static int snd_cx231xx_prepare(snd_pcm_substream_t * substream) +static int snd_cx231xx_prepare(snd_pcm_substream_t *substream) #else static int snd_cx231xx_prepare(struct snd_pcm_substream *substream) #endif @@ -452,7 +446,7 @@ static int snd_cx231xx_prepare(struct snd_pcm_substream *substream) } #if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 16) -static int snd_cx231xx_capture_trigger(snd_pcm_substream_t * substream, int cmd) +static int snd_cx231xx_capture_trigger(snd_pcm_substream_t *substream, int cmd) #else static int snd_cx231xx_capture_trigger(struct snd_pcm_substream *substream, int cmd) @@ -485,7 +479,7 @@ static int snd_cx231xx_capture_trigger(struct snd_pcm_substream *substream, #if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 16) static snd_pcm_uframes_t snd_cx231xx_capture_pointer(snd_pcm_substream_t - * substream) + *substream) #else static snd_pcm_uframes_t snd_cx231xx_capture_pointer(struct snd_pcm_substream *substream) @@ -559,9 +553,8 @@ static int cx231xx_audio_init(struct cx231xx *dev) "non standard usbaudio\n"); card = snd_card_new(index[devnr], "Cx231xx Audio", THIS_MODULE, 0); - if (card == NULL) { + if (card == NULL) return -ENOMEM; - } spin_lock_init(&adev->slock); err = snd_pcm_new(card, "Cx231xx Audio", 0, 0, 1, &pcm); diff --git a/linux/drivers/media/video/cx231xx/cx231xx-avcore.c b/linux/drivers/media/video/cx231xx/cx231xx-avcore.c index 3c09b9473..6eb63d078 100644 --- a/linux/drivers/media/video/cx231xx/cx231xx-avcore.c +++ b/linux/drivers/media/video/cx231xx/cx231xx-avcore.c @@ -1,5 +1,6 @@ /* - cx231xx_avcore.c - driver for Conexant Cx23100/101/102 USB video capture devices + cx231xx_avcore.c - driver for Conexant Cx23100/101/102 + USB video capture devices Copyright (C) 2008 @@ -38,9 +39,9 @@ #include "cx231xx.h" -/************************************************************************************* - * C O L I B R I - B L O C K C O N T R O L functions * - *************************************************************************************/ +/****************************************************************************** + * C O L I B R I - B L O C K C O N T R O L functions * + ********************************************************************* ********/ int cx231xx_colibri_init_super_block(struct cx231xx *dev, u32 ref_count) { int status = 0; @@ -50,42 +51,35 @@ int cx231xx_colibri_init_super_block(struct cx231xx *dev, u32 ref_count) /* super block initialize */ temp = (u8) (ref_count & 0xff); - status = - cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, SUP_BLK_TUNE2, - 2, temp, 1); + status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, + SUP_BLK_TUNE2, 2, temp, 1); - status = - cx231xx_read_i2c_data(dev, Colibri_DEVICE_ADDRESS, SUP_BLK_TUNE2, 2, - &colibri_power_status, 1); + status = cx231xx_read_i2c_data(dev, Colibri_DEVICE_ADDRESS, + SUP_BLK_TUNE2, 2, + &colibri_power_status, 1); temp = (u8) ((ref_count & 0x300) >> 8); temp |= 0x40; - status = - cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, SUP_BLK_TUNE1, - 2, temp, 1); - status = - cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, SUP_BLK_PLL2, 2, - 0x0f, 1); + status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, + SUP_BLK_TUNE1, 2, temp, 1); + status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, + SUP_BLK_PLL2, 2, 0x0f, 1); /* enable pll */ while (colibri_power_status != 0x18) { - status = - cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, - SUP_BLK_PWRDN, 2, 0x18, 1); - status = - cx231xx_read_i2c_data(dev, Colibri_DEVICE_ADDRESS, - SUP_BLK_PWRDN, 2, - &colibri_power_status, 1); + status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, + SUP_BLK_PWRDN, 2, 0x18, 1); + status = cx231xx_read_i2c_data(dev, Colibri_DEVICE_ADDRESS, + SUP_BLK_PWRDN, 2, + &colibri_power_status, 1); colibri_power_status &= 0xff; if (status < 0) { - cx231xx_info - (": Init Super Block failed in sending/receiving cmds\n"); + cx231xx_info(": Init Super Block failed in sending/receiving cmds\n"); break; } i++; if (i == 10) { - cx231xx_info - (": Init Super Block force break in loop !!!!\n"); + cx231xx_info(": Init Super Block force break in loop !!!!\n"); status = -1; break; } @@ -95,9 +89,8 @@ int cx231xx_colibri_init_super_block(struct cx231xx *dev, u32 ref_count) return status; /* start tuning filter */ - status = - cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, SUP_BLK_TUNE3, - 2, 0x40, 1); + status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, + SUP_BLK_TUNE3, 2, 0x40, 1); msleep(5); /* exit tuning */ @@ -113,86 +106,64 @@ int cx231xx_colibri_init_channels(struct cx231xx *dev) int status = 0; /* power up all 3 channels, clear pd_buffer */ - status = - cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, + status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_PWRDN_CLAMP_CH1, 2, 0x00, 1); - status = - cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, + status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_PWRDN_CLAMP_CH2, 2, 0x00, 1); - status = - cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, + status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_PWRDN_CLAMP_CH3, 2, 0x00, 1); /* Enable quantizer calibration */ - status = - cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_COM_QUANT, - 2, 0x02, 1); + status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, + ADC_COM_QUANT, 2, 0x02, 1); /* channel initialize, force modulator (fb) reset */ - status = - cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, + status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_FB_FRCRST_CH1, 2, 0x17, 1); - status = - cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, + status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_FB_FRCRST_CH2, 2, 0x17, 1); - status = - cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, + status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_FB_FRCRST_CH3, 2, 0x17, 1); /* start quantilizer calibration */ - status = - cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, + status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_CAL_ATEST_CH1, 2, 0x10, 1); - status = - cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, + status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_CAL_ATEST_CH2, 2, 0x10, 1); - status = - cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, + status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_CAL_ATEST_CH3, 2, 0x10, 1); msleep(5); /* exit modulator (fb) reset */ - status = - cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, + status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_FB_FRCRST_CH1, 2, 0x07, 1); - status = - cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, + status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_FB_FRCRST_CH2, 2, 0x07, 1); - status = - cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, + status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_FB_FRCRST_CH3, 2, 0x07, 1); /* enable the pre_clamp in each channel for single-ended input */ - status = - cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, + status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_NTF_PRECLMP_EN_CH1, 2, 0xf0, 1); - status = - cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, + status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_NTF_PRECLMP_EN_CH2, 2, 0xf0, 1); - status = - cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, + status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_NTF_PRECLMP_EN_CH3, 2, 0xf0, 1); /* use diode instead of resistor, so set term_en to 0, res_en to 0 */ - status = - cx231xx_reg_mask_write(dev, Colibri_DEVICE_ADDRESS, 8, + status = cx231xx_reg_mask_write(dev, Colibri_DEVICE_ADDRESS, 8, ADC_QGAIN_RES_TRM_CH1, 3, 7, 0x00); - status = - cx231xx_reg_mask_write(dev, Colibri_DEVICE_ADDRESS, 8, + status = cx231xx_reg_mask_write(dev, Colibri_DEVICE_ADDRESS, 8, ADC_QGAIN_RES_TRM_CH2, 3, 7, 0x00); - status = - cx231xx_reg_mask_write(dev, Colibri_DEVICE_ADDRESS, 8, + status = cx231xx_reg_mask_write(dev, Colibri_DEVICE_ADDRESS, 8, ADC_QGAIN_RES_TRM_CH3, 3, 7, 0x00); /* dynamic element matching off */ - status = - cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, + status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_DCSERVO_DEM_CH1, 2, 0x03, 1); - status = - cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, + status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_DCSERVO_DEM_CH2, 2, 0x03, 1); - status = - cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, + status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_DCSERVO_DEM_CH3, 2, 0x03, 1); return status; @@ -235,8 +206,7 @@ int cx231xx_colibri_set_input_mux(struct cx231xx *dev, u32 input_mux) value &= (!INPUT_SEL_MASK); value |= (ch1_setting - 1) << 4; value &= 0xff; - status = - cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, + status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_INPUT_CH1, 2, value, 1); } @@ -247,21 +217,19 @@ int cx231xx_colibri_set_input_mux(struct cx231xx *dev, u32 input_mux) value &= (!INPUT_SEL_MASK); value |= (ch2_setting - 1) << 4; value &= 0xff; - status = - cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, + status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_INPUT_CH2, 2, value, 1); } - /* For ch3_setting, the value to put in the register is 7 less than the input number */ + /* For ch3_setting, the value to put in the register is + 7 less than the input number */ if (ch3_setting != 0) { - status = - cx231xx_read_i2c_data(dev, Colibri_DEVICE_ADDRESS, + status = cx231xx_read_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_INPUT_CH3, 2, &value, 1); value &= (!INPUT_SEL_MASK); value |= (ch3_setting - 1) << 4; value &= 0xff; - status = - cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, + status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_INPUT_CH3, 2, value, 1); } @@ -290,12 +258,9 @@ int cx231xx_colibri_set_mode(struct cx231xx *dev, enum AFE_MODE mode) break; } - if ((mode != dev->colibri_mode) - && (dev->video_input == CX231XX_VMUX_TELEVISION)) { - status = - cx231xx_colibri_adjust_ref_count(dev, + if ((mode != dev->colibri_mode) && (dev->video_input == CX231XX_VMUX_TELEVISION)) + status = cx231xx_colibri_adjust_ref_count(dev, CX231XX_VMUX_TELEVISION); - } dev->colibri_mode = mode; @@ -314,84 +279,80 @@ int cx231xx_colibri_update_power_control(struct cx231xx *dev, AV_MODE avmode) if (avmode == POLARIS_AVMODE_ANALOGT_TV) { while (colibri_power_status != 0x18) { - status = - cx231xx_write_i2c_data(dev, - Colibri_DEVICE_ADDRESS, - SUP_BLK_PWRDN, 2, - 0x18, 1); - status = - cx231xx_read_i2c_data(dev, - Colibri_DEVICE_ADDRESS, - SUP_BLK_PWRDN, 2, - &colibri_power_status, - 1); + status = cx231xx_write_i2c_data(dev, + Colibri_DEVICE_ADDRESS, + SUP_BLK_PWRDN, 2, + 0x18, 1); + status = cx231xx_read_i2c_data(dev, + Colibri_DEVICE_ADDRESS, + SUP_BLK_PWRDN, 2, + &colibri_power_status, + 1); if (status < 0) break; } - status = - cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, + status = cx231xx_write_i2c_data(dev, + Colibri_DEVICE_ADDRESS, ADC_PWRDN_CLAMP_CH1, 2, 0x00, 1); - status = - cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, + status = cx231xx_write_i2c_data(dev, + Colibri_DEVICE_ADDRESS, ADC_PWRDN_CLAMP_CH2, 2, 0x00, 1); - status = - cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, + status = cx231xx_write_i2c_data(dev, + Colibri_DEVICE_ADDRESS, ADC_PWRDN_CLAMP_CH3, 2, 0x00, 1); } else if (avmode == POLARIS_AVMODE_DIGITAL) { - status = - cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, + status = cx231xx_write_i2c_data(dev, + Colibri_DEVICE_ADDRESS, ADC_PWRDN_CLAMP_CH1, 2, 0x70, 1); - status = - cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, + status = cx231xx_write_i2c_data(dev, + Colibri_DEVICE_ADDRESS, ADC_PWRDN_CLAMP_CH2, 2, 0x70, 1); - status = - cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, + status = cx231xx_write_i2c_data(dev, + Colibri_DEVICE_ADDRESS, ADC_PWRDN_CLAMP_CH3, 2, 0x70, 1); - status = - cx231xx_read_i2c_data(dev, Colibri_DEVICE_ADDRESS, + status = cx231xx_read_i2c_data(dev, + Colibri_DEVICE_ADDRESS, SUP_BLK_PWRDN, 2, &colibri_power_status, 1); colibri_power_status |= 0x07; - status = - cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, + status = cx231xx_write_i2c_data(dev, + Colibri_DEVICE_ADDRESS, SUP_BLK_PWRDN, 2, colibri_power_status, 1); } else if (avmode == POLARIS_AVMODE_ENXTERNAL_AV) { while (colibri_power_status != 0x18) { - status = - cx231xx_write_i2c_data(dev, - Colibri_DEVICE_ADDRESS, - SUP_BLK_PWRDN, 2, - 0x18, 1); - status = - cx231xx_read_i2c_data(dev, - Colibri_DEVICE_ADDRESS, - SUP_BLK_PWRDN, 2, - &colibri_power_status, - 1); + status = cx231xx_write_i2c_data(dev, + Colibri_DEVICE_ADDRESS, + SUP_BLK_PWRDN, 2, + 0x18, 1); + status = cx231xx_read_i2c_data(dev, + Colibri_DEVICE_ADDRESS, + SUP_BLK_PWRDN, 2, + &colibri_power_status, + 1); if (status < 0) break; } - status = - cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, + status = cx231xx_write_i2c_data(dev, + Colibri_DEVICE_ADDRESS, ADC_PWRDN_CLAMP_CH1, 2, 0x00, 1); - status = - cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, + status = cx231xx_write_i2c_data(dev, + Colibri_DEVICE_ADDRESS, ADC_PWRDN_CLAMP_CH2, 2, 0x00, 1); - status = - cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, + status = cx231xx_write_i2c_data(dev, + Colibri_DEVICE_ADDRESS, ADC_PWRDN_CLAMP_CH3, 2, 0x00, 1); } else { @@ -402,85 +363,83 @@ int cx231xx_colibri_update_power_control(struct cx231xx *dev, AV_MODE avmode) default: if (avmode == POLARIS_AVMODE_ANALOGT_TV) { while (colibri_power_status != 0x18) { - status = - cx231xx_write_i2c_data(dev, - Colibri_DEVICE_ADDRESS, - SUP_BLK_PWRDN, 2, - 0x18, 1); - status = - cx231xx_read_i2c_data(dev, - Colibri_DEVICE_ADDRESS, - SUP_BLK_PWRDN, 2, - &colibri_power_status, - 1); + status = cx231xx_write_i2c_data(dev, + Colibri_DEVICE_ADDRESS, + SUP_BLK_PWRDN, 2, + 0x18, 1); + status = cx231xx_read_i2c_data(dev, + Colibri_DEVICE_ADDRESS, + SUP_BLK_PWRDN, 2, + &colibri_power_status, + 1); if (status < 0) break; } - status = - cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, - ADC_PWRDN_CLAMP_CH1, 2, 0x40, - 1); - status = - cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, - ADC_PWRDN_CLAMP_CH2, 2, 0x40, - 1); - status = - cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, - ADC_PWRDN_CLAMP_CH3, 2, 0x00, - 1); + status = cx231xx_write_i2c_data(dev, + Colibri_DEVICE_ADDRESS, + ADC_PWRDN_CLAMP_CH1, 2, + 0x40, 1); + status = cx231xx_write_i2c_data(dev, + Colibri_DEVICE_ADDRESS, + ADC_PWRDN_CLAMP_CH2, 2, + 0x40, 1); + status = cx231xx_write_i2c_data(dev, + Colibri_DEVICE_ADDRESS, + ADC_PWRDN_CLAMP_CH3, 2, + 0x00, 1); } else if (avmode == POLARIS_AVMODE_DIGITAL) { - status = - cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, - ADC_PWRDN_CLAMP_CH1, 2, 0x70, - 1); - status = - cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, - ADC_PWRDN_CLAMP_CH2, 2, 0x70, - 1); - status = - cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, - ADC_PWRDN_CLAMP_CH3, 2, 0x70, - 1); - - status = - cx231xx_read_i2c_data(dev, Colibri_DEVICE_ADDRESS, - SUP_BLK_PWRDN, 2, - &colibri_power_status, 1); + status = cx231xx_write_i2c_data(dev, + Colibri_DEVICE_ADDRESS, + ADC_PWRDN_CLAMP_CH1, 2, + 0x70, 1); + status = cx231xx_write_i2c_data(dev, + Colibri_DEVICE_ADDRESS, + ADC_PWRDN_CLAMP_CH2, 2, + 0x70, 1); + status = cx231xx_write_i2c_data(dev, + Colibri_DEVICE_ADDRESS, + ADC_PWRDN_CLAMP_CH3, 2, + 0x70, 1); + + status = cx231xx_read_i2c_data(dev, + Colibri_DEVICE_ADDRESS, + SUP_BLK_PWRDN, 2, + &colibri_power_status, + 1); colibri_power_status |= 0x07; - status = - cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, - SUP_BLK_PWRDN, 2, - colibri_power_status, 1); + status = cx231xx_write_i2c_data(dev, + Colibri_DEVICE_ADDRESS, + SUP_BLK_PWRDN, 2, + colibri_power_status, + 1); } else if (avmode == POLARIS_AVMODE_ENXTERNAL_AV) { while (colibri_power_status != 0x18) { - status = - cx231xx_write_i2c_data(dev, - Colibri_DEVICE_ADDRESS, - SUP_BLK_PWRDN, 2, - 0x18, 1); - status = - cx231xx_read_i2c_data(dev, - Colibri_DEVICE_ADDRESS, - SUP_BLK_PWRDN, 2, - &colibri_power_status, - 1); + status = cx231xx_write_i2c_data(dev, + Colibri_DEVICE_ADDRESS, + SUP_BLK_PWRDN, 2, + 0x18, 1); + status = cx231xx_read_i2c_data(dev, + Colibri_DEVICE_ADDRESS, + SUP_BLK_PWRDN, 2, + &colibri_power_status, + 1); if (status < 0) break; } - status = - cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, - ADC_PWRDN_CLAMP_CH1, 2, 0x00, - 1); - status = - cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, - ADC_PWRDN_CLAMP_CH2, 2, 0x00, - 1); - status = - cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, - ADC_PWRDN_CLAMP_CH3, 2, 0x40, - 1); + status = cx231xx_write_i2c_data(dev, + Colibri_DEVICE_ADDRESS, + ADC_PWRDN_CLAMP_CH1, 2, + 0x00, 1); + status = cx231xx_write_i2c_data(dev, + Colibri_DEVICE_ADDRESS, + ADC_PWRDN_CLAMP_CH2, 2, + 0x00, 1); + status = cx231xx_write_i2c_data(dev, + Colibri_DEVICE_ADDRESS, + ADC_PWRDN_CLAMP_CH3, 2, + 0x40, 1); } else { cx231xx_info("Invalid AV mode input\n"); status = -1; @@ -499,19 +458,15 @@ int cx231xx_colibri_adjust_ref_count(struct cx231xx *dev, u32 video_input) dev->video_input = video_input; if (video_input == CX231XX_VMUX_TELEVISION) { - status = - cx231xx_read_i2c_data(dev, Colibri_DEVICE_ADDRESS, + status = cx231xx_read_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_INPUT_CH3, 2, &input_mode, 1); - status = - cx231xx_read_i2c_data(dev, Colibri_DEVICE_ADDRESS, + status = cx231xx_read_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_NTF_PRECLMP_EN_CH3, 2, &ntf_mode, 1); } else { - status = - cx231xx_read_i2c_data(dev, Colibri_DEVICE_ADDRESS, + status = cx231xx_read_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_INPUT_CH1, 2, &input_mode, 1); - status = - cx231xx_read_i2c_data(dev, Colibri_DEVICE_ADDRESS, + status = cx231xx_read_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_NTF_PRECLMP_EN_CH1, 2, &ntf_mode, 1); } @@ -540,9 +495,9 @@ int cx231xx_colibri_adjust_ref_count(struct cx231xx *dev, u32 video_input) return status; } -/************************************************************************************* - * V I D E O / A U D I O D E C O D E R C O N T R O L functions * - *************************************************************************************/ +/****************************************************************************** + * V I D E O / A U D I O D E C O D E R C O N T R O L functions * + ******************************************++**********************************/ int cx231xx_set_video_input_mux(struct cx231xx *dev, u8 input) { int status = 0; @@ -552,38 +507,38 @@ int cx231xx_set_video_input_mux(struct cx231xx *dev, u8 input) case CX231XX_VMUX_SVIDEO: if ((dev->current_pcb_config.type == USB_BUS_POWER) && (dev->power_mode != POLARIS_AVMODE_ENXTERNAL_AV)) { - status = cx231xx_set_power_mode(dev, POLARIS_AVMODE_ENXTERNAL_AV); /* External AV */ + /* External AV */ + status = cx231xx_set_power_mode(dev, + POLARIS_AVMODE_ENXTERNAL_AV); if (status < 0) { - cx231xx_errdev - ("%s: cx231xx_set_power_mode : Failed to set Power - errCode [%d]!\n", + cx231xx_errdev("%s: cx231xx_set_power_mode : Failed to set Power - errCode [%d]!\n", __func__, status); return status; } } - status = - cx231xx_set_decoder_video_input(dev, INPUT(input)->type, - INPUT(input)->vmux); + status = cx231xx_set_decoder_video_input(dev, + INPUT(input)->type, + INPUT(input)->vmux); break; case CX231XX_VMUX_TELEVISION: case CX231XX_VMUX_CABLE: if ((dev->current_pcb_config.type == USB_BUS_POWER) && (dev->power_mode != POLARIS_AVMODE_ANALOGT_TV)) { - status = cx231xx_set_power_mode(dev, POLARIS_AVMODE_ANALOGT_TV); /* Tuner */ + /* Tuner */ + status = cx231xx_set_power_mode(dev, + POLARIS_AVMODE_ANALOGT_TV); if (status < 0) { - cx231xx_errdev - ("%s: cx231xx_set_power_mode : Failed to set Power - errCode [%d]!\n", + cx231xx_errdev("%s: cx231xx_set_power_mode : Failed to set Power - errCode [%d]!\n", __func__, status); return status; } } - status = - cx231xx_set_decoder_video_input(dev, - CX231XX_VMUX_COMPOSITE1, - INPUT(input)->vmux); + status = cx231xx_set_decoder_video_input(dev, + CX231XX_VMUX_COMPOSITE1, + INPUT(input)->vmux); break; default: - cx231xx_errdev - ("%s: cx231xx_set_power_mode : Unknown Input %d !\n", + cx231xx_errdev("%s: cx231xx_set_power_mode : Unknown Input %d !\n", __func__, INPUT(input)->type); break; } @@ -602,8 +557,7 @@ int cx231xx_set_decoder_video_input(struct cx231xx *dev, u8 pin_type, u8 input) if (pin_type != dev->video_input) { status = cx231xx_colibri_adjust_ref_count(dev, pin_type); if (status < 0) { - cx231xx_errdev - ("%s: cx231xx_colibri_adjust_ref_count :Failed to set Colibri input mux - errCode [%d]!\n", + cx231xx_errdev("%s: cx231xx_colibri_adjust_ref_count :Failed to set Colibri input mux - errCode [%d]!\n", __func__, status); return status; } @@ -612,57 +566,190 @@ int cx231xx_set_decoder_video_input(struct cx231xx *dev, u8 pin_type, u8 input) /* call colibri block to set video inputs */ status = cx231xx_colibri_set_input_mux(dev, input); if (status < 0) { - cx231xx_errdev - ("%s: cx231xx_colibri_set_input_mux :Failed to set Colibri input mux - errCode [%d]!\n", + cx231xx_errdev("%s: cx231xx_colibri_set_input_mux :Failed to set Colibri input mux - errCode [%d]!\n", __func__, status); return status; } switch (pin_type) { case CX231XX_VMUX_COMPOSITE1: - { - status = - cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, - AFE_CTRL, 2, &value, 4); + status = cx231xx_read_i2c_data(dev, + HAMMERHEAD_I2C_ADDRESS, + AFE_CTRL, 2, &value, 4); + value |= (0 << 13) | (1 << 4); + value &= ~(1 << 5); + + value &= (~(0x1ff8000)); /* set [24:23] [22:15] to 0 */ + value |= 0x1000000; /* set FUNC_MODE[24:23] = 2 IF_MOD[22:15] = 0 */ + status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + AFE_CTRL, 2, value, 4); + + status = cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + OUT_CTRL1, 2, &value, 4); + value |= (1 << 7); + status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + OUT_CTRL1, 2, value, 4); + + /* Set vip 1.1 output mode */ + status = cx231xx_read_modify_write_i2c_dword(dev, + HAMMERHEAD_I2C_ADDRESS, + OUT_CTRL1, + FLD_OUT_MODE, + OUT_MODE_VIP11); + + /* Tell DIF object to go to baseband mode */ + status = cx231xx_dif_set_standard(dev, DIF_USE_BASEBAND); + if (status < 0) { + cx231xx_errdev("%s: cx231xx_dif set to By pass mode - errCode [%d]!\n", + __func__, status); + return status; + } + + /* Read the DFE_CTRL1 register */ + status = cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + DFE_CTRL1, 2, &value, 4); + + /* enable the VBI_GATE_EN */ + value |= FLD_VBI_GATE_EN; + + /* Enable the auto-VGA enable */ + value |= FLD_VGA_AUTO_EN; + + /* Write it back */ + status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + DFE_CTRL1, 2, value, 4); + + /* Disable auto config of registers */ + status = cx231xx_read_modify_write_i2c_dword(dev, + HAMMERHEAD_I2C_ADDRESS, + MODE_CTRL, FLD_ACFG_DIS, + cx231xx_set_field(FLD_ACFG_DIS, 1)); + + /* Set CVBS input mode */ + status = cx231xx_read_modify_write_i2c_dword(dev, + HAMMERHEAD_I2C_ADDRESS, + MODE_CTRL, FLD_INPUT_MODE, + cx231xx_set_field(FLD_INPUT_MODE, INPUT_MODE_CVBS_0)); + break; + case CX231XX_VMUX_SVIDEO: + /* Disable the use of DIF */ + + status = cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + AFE_CTRL, 2, &value, 4); + + value &= (~(0x1ff8000)); /* set [24:23] [22:15] to 0 */ + value |= 0x1000010; /* set FUNC_MODE[24:23] = 2 + IF_MOD[22:15] = 0 DCR_BYP_CH2[4:4] = 1; */ + status = cx231xx_write_i2c_data(dev, + HAMMERHEAD_I2C_ADDRESS, + AFE_CTRL, 2, value, 4); + + /* Tell DIF object to go to baseband mode */ + status = cx231xx_dif_set_standard(dev, DIF_USE_BASEBAND); + if (status < 0) { + cx231xx_errdev("%s: cx231xx_dif set to By pass mode - errCode [%d]!\n", + __func__, status); + return status; + } + + /* Read the DFE_CTRL1 register */ + status = cx231xx_read_i2c_data(dev, + HAMMERHEAD_I2C_ADDRESS, + DFE_CTRL1, 2, &value, 4); + + /* enable the VBI_GATE_EN */ + value |= FLD_VBI_GATE_EN; + + /* Enable the auto-VGA enable */ + value |= FLD_VGA_AUTO_EN; + + /* Write it back */ + status = cx231xx_write_i2c_data(dev, + HAMMERHEAD_I2C_ADDRESS, + DFE_CTRL1, 2, value, 4); + + /* Disable auto config of registers */ + status = cx231xx_read_modify_write_i2c_dword(dev, + HAMMERHEAD_I2C_ADDRESS, + MODE_CTRL, FLD_ACFG_DIS, + cx231xx_set_field(FLD_ACFG_DIS, 1)); + + /* Set YC input mode */ + status = cx231xx_read_modify_write_i2c_dword(dev, + HAMMERHEAD_I2C_ADDRESS, + MODE_CTRL, + FLD_INPUT_MODE, + cx231xx_set_field(FLD_INPUT_MODE, INPUT_MODE_YC_1)); + + /* Chroma to ADC2 */ + status = cx231xx_read_i2c_data(dev, + HAMMERHEAD_I2C_ADDRESS, + AFE_CTRL, 2, &value, 4); + value |= FLD_CHROMA_IN_SEL; /* set the chroma in select */ + + /* Clear VGA_SEL_CH2 and VGA_SEL_CH3 (bits 7 and 8) + This sets them to use video + rather than audio. Only one of the two will be in use. */ + value &= ~(FLD_VGA_SEL_CH2 | FLD_VGA_SEL_CH3); + + status = cx231xx_write_i2c_data(dev, + HAMMERHEAD_I2C_ADDRESS, + AFE_CTRL, 2, value, 4); + + status = cx231xx_colibri_set_mode(dev, AFE_MODE_BASEBAND); + break; + case CX231XX_VMUX_TELEVISION: + case CX231XX_VMUX_CABLE: + default: + switch (dev->model) { + case CX231XX_BOARD_CNXT_RDE_250: + case CX231XX_BOARD_CNXT_RDU_250: + /* Disable the use of DIF */ + + status = cx231xx_read_i2c_data(dev, + HAMMERHEAD_I2C_ADDRESS, + AFE_CTRL, 2, + &value, 4); value |= (0 << 13) | (1 << 4); value &= ~(1 << 5); - value &= (~(0x1FF8000)); /* set [24:23] [22:15] to 0 */ - value |= 0x1000000; /* set FUNC_MODE[24:23] = 2 IF_MOD[22:15] = 0 */ - status = - cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, - AFE_CTRL, 2, value, 4); + value &= (~(0x1FF8000)); /* set [24:23] [22:15] to 0 */ + value |= 0x1000000; /* set FUNC_MODE[24:23] = 2 IF_MOD[22:15] = 0 */ + status = cx231xx_write_i2c_data(dev, + HAMMERHEAD_I2C_ADDRESS, + AFE_CTRL, 2, + value, 4); - status = - cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, - OUT_CTRL1, 2, &value, 4); + status = cx231xx_read_i2c_data(dev, + HAMMERHEAD_I2C_ADDRESS, + OUT_CTRL1, 2, + &value, 4); value |= (1 << 7); - status = - cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, - OUT_CTRL1, 2, value, 4); + status = cx231xx_write_i2c_data(dev, + HAMMERHEAD_I2C_ADDRESS, + OUT_CTRL1, 2, + value, 4); /* Set vip 1.1 output mode */ - status = - cx231xx_read_modify_write_i2c_dword(dev, - HAMMERHEAD_I2C_ADDRESS, - OUT_CTRL1, - FLD_OUT_MODE, - OUT_MODE_VIP11); + status = cx231xx_read_modify_write_i2c_dword(dev, + HAMMERHEAD_I2C_ADDRESS, + OUT_CTRL1, FLD_OUT_MODE, + OUT_MODE_VIP11); - /* Tell DIF object to go to baseband mode */ - status = - cx231xx_dif_set_standard(dev, DIF_USE_BASEBAND); + /* Tell DIF object to go to baseband mode */ + status = cx231xx_dif_set_standard(dev, + DIF_USE_BASEBAND); if (status < 0) { - cx231xx_errdev - ("%s: cx231xx_dif set to By pass mode - errCode [%d]!\n", - __func__, status); + cx231xx_errdev("%s: cx231xx_dif set to By pass mode - errCode [%d]!\n", + __func__, status); return status; } /* Read the DFE_CTRL1 register */ - status = - cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, - DFE_CTRL1, 2, &value, 4); + status = cx231xx_read_i2c_data(dev, + HAMMERHEAD_I2C_ADDRESS, + DFE_CTRL1, 2, + &value, 4); /* enable the VBI_GATE_EN */ value |= FLD_VBI_GATE_EN; @@ -671,349 +758,144 @@ int cx231xx_set_decoder_video_input(struct cx231xx *dev, u8 pin_type, u8 input) value |= FLD_VGA_AUTO_EN; /* Write it back */ - status = - cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, - DFE_CTRL1, 2, value, 4); + status = cx231xx_write_i2c_data(dev, + HAMMERHEAD_I2C_ADDRESS, + DFE_CTRL1, 2, + value, 4); /* Disable auto config of registers */ - status = - cx231xx_read_modify_write_i2c_dword(dev, - HAMMERHEAD_I2C_ADDRESS, - MODE_CTRL, - FLD_ACFG_DIS, - cx231xx_set_field - (FLD_ACFG_DIS, - 1)); + status = cx231xx_read_modify_write_i2c_dword(dev, + HAMMERHEAD_I2C_ADDRESS, + MODE_CTRL, FLD_ACFG_DIS, + cx231xx_set_field(FLD_ACFG_DIS, 1)); /* Set CVBS input mode */ - status = - cx231xx_read_modify_write_i2c_dword(dev, - HAMMERHEAD_I2C_ADDRESS, - MODE_CTRL, - FLD_INPUT_MODE, - cx231xx_set_field - (FLD_INPUT_MODE, - INPUT_MODE_CVBS_0)); - } - break; - case CX231XX_VMUX_SVIDEO: - { - /* Disable the use of DIF */ - - status = - cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, - AFE_CTRL, 2, &value, 4); - - value &= (~(0x1FF8000)); /* set [24:23] [22:15] to 0 */ - value |= 0x1000010; /* set FUNC_MODE[24:23] = 2 - IF_MOD[22:15] = 0 DCR_BYP_CH2[4:4] = 1; */ - status = - cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, - AFE_CTRL, 2, value, 4); + status = cx231xx_read_modify_write_i2c_dword(dev, + HAMMERHEAD_I2C_ADDRESS, + MODE_CTRL, FLD_INPUT_MODE, + cx231xx_set_field(FLD_INPUT_MODE, INPUT_MODE_CVBS_0)); + break; + default: + /* Enable the DIF for the tuner */ - /* Tell DIF object to go to baseband mode */ - status = - cx231xx_dif_set_standard(dev, DIF_USE_BASEBAND); + /* Reinitialize the DIF */ + status = cx231xx_dif_set_standard(dev, dev->norm); if (status < 0) { - cx231xx_errdev - ("%s: cx231xx_dif set to By pass mode - errCode [%d]!\n", - __func__, status); + cx231xx_errdev("%s: cx231xx_dif set to By pass mode - errCode [%d]!\n", + __func__, status); return status; } + /* Make sure bypass is cleared */ + status = cx231xx_read_i2c_data(dev, + HAMMERHEAD_I2C_ADDRESS, + DIF_MISC_CTRL, + 2, &value, 4); + + /* Clear the bypass bit */ + value &= ~FLD_DIF_DIF_BYPASS; + + /* Enable the use of the DIF block */ + status = cx231xx_write_i2c_data(dev, + HAMMERHEAD_I2C_ADDRESS, + DIF_MISC_CTRL, + 2, value, 4); + /* Read the DFE_CTRL1 register */ - status = - cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, - DFE_CTRL1, 2, &value, 4); + status = cx231xx_read_i2c_data(dev, + HAMMERHEAD_I2C_ADDRESS, + DFE_CTRL1, 2, + &value, 4); - /* enable the VBI_GATE_EN */ - value |= FLD_VBI_GATE_EN; + /* Disable the VBI_GATE_EN */ + value &= ~FLD_VBI_GATE_EN; - /* Enable the auto-VGA enable */ - value |= FLD_VGA_AUTO_EN; + /* Enable the auto-VGA enable, AGC, and + set the skip count to 2 */ + value |= FLD_VGA_AUTO_EN | FLD_AGC_AUTO_EN | 0x00200000; /* Write it back */ - status = - cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, - DFE_CTRL1, 2, value, 4); + status = cx231xx_write_i2c_data(dev, + HAMMERHEAD_I2C_ADDRESS, + DFE_CTRL1, 2, + value, 4); - /* Disable auto config of registers */ - status = - cx231xx_read_modify_write_i2c_dword(dev, - HAMMERHEAD_I2C_ADDRESS, - MODE_CTRL, - FLD_ACFG_DIS, - cx231xx_set_field - (FLD_ACFG_DIS, - 1)); - - /* Set YC input mode */ - status = - cx231xx_read_modify_write_i2c_dword(dev, - HAMMERHEAD_I2C_ADDRESS, - MODE_CTRL, - FLD_INPUT_MODE, - cx231xx_set_field - (FLD_INPUT_MODE, - INPUT_MODE_YC_1)); - - /* Chroma to ADC2 */ - status = - cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, - AFE_CTRL, 2, &value, 4); - value |= FLD_CHROMA_IN_SEL; /* set the chroma in select */ + /* Wait 15 ms */ + msleep(1); - /* Clear VGA_SEL_CH2 and VGA_SEL_CH3 (bits 7 and 8) This sets them to use video - rather than audio. Only one of the two will be in use. */ - value &= ~(FLD_VGA_SEL_CH2 | FLD_VGA_SEL_CH3); + /* Disable the auto-VGA enable AGC */ + value &= ~(FLD_VGA_AUTO_EN); - status = - cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, - AFE_CTRL, 2, value, 4); + /* Write it back */ + status = cx231xx_write_i2c_data(dev, + HAMMERHEAD_I2C_ADDRESS, + DFE_CTRL1, 2, + value, 4); - status = - cx231xx_colibri_set_mode(dev, AFE_MODE_BASEBAND); - } - break; - case CX231XX_VMUX_TELEVISION: - case CX231XX_VMUX_CABLE: - default: - { - switch (dev->model) { - case CX231XX_BOARD_CNXT_RDE_250: - case CX231XX_BOARD_CNXT_RDU_250: - { - /* Disable the use of DIF */ - - status = - cx231xx_read_i2c_data(dev, - HAMMERHEAD_I2C_ADDRESS, - AFE_CTRL, 2, - &value, 4); - value |= (0 << 13) | (1 << 4); - value &= ~(1 << 5); - - value &= (~(0x1FF8000)); /* set [24:23] [22:15] to 0 */ - value |= 0x1000000; /* set FUNC_MODE[24:23] = 2 IF_MOD[22:15] = 0 */ - status = - cx231xx_write_i2c_data(dev, - HAMMERHEAD_I2C_ADDRESS, - AFE_CTRL, 2, - value, 4); - - status = - cx231xx_read_i2c_data(dev, - HAMMERHEAD_I2C_ADDRESS, - OUT_CTRL1, 2, - &value, 4); - value |= (1 << 7); - status = - cx231xx_write_i2c_data(dev, - HAMMERHEAD_I2C_ADDRESS, - OUT_CTRL1, 2, - value, 4); - - /* Set vip 1.1 output mode */ - status = - cx231xx_read_modify_write_i2c_dword - (dev, HAMMERHEAD_I2C_ADDRESS, - OUT_CTRL1, FLD_OUT_MODE, - OUT_MODE_VIP11); - - /* Tell DIF object to go to baseband mode */ - status = - cx231xx_dif_set_standard(dev, - DIF_USE_BASEBAND); - if (status < 0) { - cx231xx_errdev - ("%s: cx231xx_dif set to By pass mode - errCode [%d]!\n", - __func__, status); - return status; - } - - /* Read the DFE_CTRL1 register */ - status = - cx231xx_read_i2c_data(dev, - HAMMERHEAD_I2C_ADDRESS, - DFE_CTRL1, 2, - &value, 4); - - /* enable the VBI_GATE_EN */ - value |= FLD_VBI_GATE_EN; - - /* Enable the auto-VGA enable */ - value |= FLD_VGA_AUTO_EN; - - /* Write it back */ - status = - cx231xx_write_i2c_data(dev, - HAMMERHEAD_I2C_ADDRESS, - DFE_CTRL1, 2, - value, 4); - - /* Disable auto config of registers */ - status = - cx231xx_read_modify_write_i2c_dword - (dev, HAMMERHEAD_I2C_ADDRESS, - MODE_CTRL, FLD_ACFG_DIS, - cx231xx_set_field(FLD_ACFG_DIS, - 1)); - - /* Set CVBS input mode */ - status = - cx231xx_read_modify_write_i2c_dword - (dev, HAMMERHEAD_I2C_ADDRESS, - MODE_CTRL, FLD_INPUT_MODE, - cx231xx_set_field(FLD_INPUT_MODE, - INPUT_MODE_CVBS_0)); - } - break; - default: - { - /* Enable the DIF for the tuner */ - - /* Reinitialize the DIF */ - status = - cx231xx_dif_set_standard(dev, - dev->norm); - if (status < 0) { - cx231xx_errdev - ("%s: cx231xx_dif set to By pass mode - errCode [%d]!\n", - __func__, status); - return status; - } - - /* Make sure bypass is cleared */ - status = - cx231xx_read_i2c_data(dev, - HAMMERHEAD_I2C_ADDRESS, - DIF_MISC_CTRL, - 2, &value, 4); - - /* Clear the bypass bit */ - value &= ~FLD_DIF_DIF_BYPASS; - - /* Enable the use of the DIF block */ - status = - cx231xx_write_i2c_data(dev, - HAMMERHEAD_I2C_ADDRESS, - DIF_MISC_CTRL, - 2, value, 4); - - /* Read the DFE_CTRL1 register */ - status = - cx231xx_read_i2c_data(dev, - HAMMERHEAD_I2C_ADDRESS, - DFE_CTRL1, 2, - &value, 4); - - /* Disable the VBI_GATE_EN */ - value &= ~FLD_VBI_GATE_EN; - - /* Enable the auto-VGA enable, AGC, and set the skip count to 2 */ - value |= - FLD_VGA_AUTO_EN | FLD_AGC_AUTO_EN | - 0x00200000; - - /* Write it back */ - status = - cx231xx_write_i2c_data(dev, - HAMMERHEAD_I2C_ADDRESS, - DFE_CTRL1, 2, - value, 4); - - /* Wait 15 ms */ - msleep(1); - - /* Disable the auto-VGA enable AGC */ - value &= ~(FLD_VGA_AUTO_EN); - - /* Write it back */ - status = - cx231xx_write_i2c_data(dev, - HAMMERHEAD_I2C_ADDRESS, - DFE_CTRL1, 2, - value, 4); - - /* Enable Polaris B0 AGC output */ - status = - cx231xx_read_i2c_data(dev, - HAMMERHEAD_I2C_ADDRESS, - PIN_CTRL, 2, - &value, 4); - value |= - (FLD_OEF_AGC_RF) | - (FLD_OEF_AGC_IFVGA) | - (FLD_OEF_AGC_IF); - status = - cx231xx_write_i2c_data(dev, - HAMMERHEAD_I2C_ADDRESS, - PIN_CTRL, 2, - value, 4); - - /* Set vip 1.1 output mode */ - status = - cx231xx_read_modify_write_i2c_dword - (dev, HAMMERHEAD_I2C_ADDRESS, - OUT_CTRL1, FLD_OUT_MODE, - OUT_MODE_VIP11); - - /* Disable auto config of registers */ - status = - cx231xx_read_modify_write_i2c_dword - (dev, HAMMERHEAD_I2C_ADDRESS, - MODE_CTRL, FLD_ACFG_DIS, - cx231xx_set_field(FLD_ACFG_DIS, - 1)); - - /* Set CVBS input mode */ - status = - cx231xx_read_modify_write_i2c_dword - (dev, HAMMERHEAD_I2C_ADDRESS, - MODE_CTRL, FLD_INPUT_MODE, - cx231xx_set_field(FLD_INPUT_MODE, - INPUT_MODE_CVBS_0)); - - /* Set some bits in AFE_CTRL so that channel 2 or 3 is ready to receive audio */ - /* Clear clamp for channels 2 and 3 (bit 16-17) */ - /* Clear droop comp (bit 19-20) */ - /* Set VGA_SEL (for audio control) (bit 7-8) */ - status = - cx231xx_read_i2c_data(dev, - HAMMERHEAD_I2C_ADDRESS, - AFE_CTRL, 2, - &value, 4); - - value |= - FLD_VGA_SEL_CH3 | FLD_VGA_SEL_CH2; - - status = - cx231xx_write_i2c_data(dev, - HAMMERHEAD_I2C_ADDRESS, - AFE_CTRL, 2, - value, 4); - } - break; + /* Enable Polaris B0 AGC output */ + status = cx231xx_read_i2c_data(dev, + HAMMERHEAD_I2C_ADDRESS, + PIN_CTRL, 2, + &value, 4); + value |= (FLD_OEF_AGC_RF) | + (FLD_OEF_AGC_IFVGA) | + (FLD_OEF_AGC_IF); + status = cx231xx_write_i2c_data(dev, + HAMMERHEAD_I2C_ADDRESS, + PIN_CTRL, 2, + value, 4); + + /* Set vip 1.1 output mode */ + status = cx231xx_read_modify_write_i2c_dword(dev, + HAMMERHEAD_I2C_ADDRESS, + OUT_CTRL1, FLD_OUT_MODE, + OUT_MODE_VIP11); + + /* Disable auto config of registers */ + status = cx231xx_read_modify_write_i2c_dword(dev, + HAMMERHEAD_I2C_ADDRESS, + MODE_CTRL, FLD_ACFG_DIS, + cx231xx_set_field(FLD_ACFG_DIS, 1)); + + /* Set CVBS input mode */ + status = cx231xx_read_modify_write_i2c_dword(dev, + HAMMERHEAD_I2C_ADDRESS, + MODE_CTRL, FLD_INPUT_MODE, + cx231xx_set_field(FLD_INPUT_MODE, INPUT_MODE_CVBS_0)); + + /* Set some bits in AFE_CTRL so that channel 2 or 3 is ready to receive audio */ + /* Clear clamp for channels 2 and 3 (bit 16-17) */ + /* Clear droop comp (bit 19-20) */ + /* Set VGA_SEL (for audio control) (bit 7-8) */ + status = cx231xx_read_i2c_data(dev, + HAMMERHEAD_I2C_ADDRESS, + AFE_CTRL, 2, + &value, 4); + + value |= FLD_VGA_SEL_CH3 | FLD_VGA_SEL_CH2; + + status = cx231xx_write_i2c_data(dev, + HAMMERHEAD_I2C_ADDRESS, + AFE_CTRL, 2, + value, 4); + break; - } } break; } /* Set raw VBI mode */ - status = - cx231xx_read_modify_write_i2c_dword(dev, HAMMERHEAD_I2C_ADDRESS, - OUT_CTRL1, FLD_VBIHACTRAW_EN, - cx231xx_set_field - (FLD_VBIHACTRAW_EN, 1)); + status = cx231xx_read_modify_write_i2c_dword(dev, + HAMMERHEAD_I2C_ADDRESS, + OUT_CTRL1, FLD_VBIHACTRAW_EN, + cx231xx_set_field(FLD_VBIHACTRAW_EN, 1)); - status = - cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, OUT_CTRL1, 2, - &value, 4); + status = cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + OUT_CTRL1, 2, + &value, 4); if (value & 0x02) { value |= (1 << 19); - status = - cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, OUT_CTRL1, 2, value, 4); } @@ -1032,70 +914,62 @@ int cx231xx_do_mode_ctrl_overrides(struct cx231xx *dev) (unsigned int)dev->norm); /* Change the DFE_CTRL3 bp_percent to fix flagging */ - status = - cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DFE_CTRL3, 2, - 0xCD3F0280, 4); + status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + DFE_CTRL3, 2, + 0xCD3F0280, 4); if (dev->norm & (V4L2_STD_NTSC_M | V4L2_STD_NTSC_M_JP | V4L2_STD_PAL_M)) { cx231xx_info("do_mode_ctrl_overrides NTSC\n"); - /* Move the close caption lines out of active video, adjust the active video start point */ - status = - cx231xx_read_modify_write_i2c_dword(dev, + /* Move the close caption lines out of active video, + adjust the active video start point */ + status = cx231xx_read_modify_write_i2c_dword(dev, HAMMERHEAD_I2C_ADDRESS, VERT_TIM_CTRL, FLD_VBLANK_CNT, 0x18); - status = - cx231xx_read_modify_write_i2c_dword(dev, + status = cx231xx_read_modify_write_i2c_dword(dev, HAMMERHEAD_I2C_ADDRESS, VERT_TIM_CTRL, FLD_VACTIVE_CNT, 0x1E6000); - status = - cx231xx_read_modify_write_i2c_dword(dev, + status = cx231xx_read_modify_write_i2c_dword(dev, HAMMERHEAD_I2C_ADDRESS, VERT_TIM_CTRL, FLD_V656BLANK_CNT, 0x1E000000); - status = - cx231xx_read_modify_write_i2c_dword(dev, + status = cx231xx_read_modify_write_i2c_dword(dev, HAMMERHEAD_I2C_ADDRESS, HORIZ_TIM_CTRL, FLD_HBLANK_CNT, cx231xx_set_field (FLD_HBLANK_CNT, 0x79)); - } else if (dev-> - norm & (V4L2_STD_PAL_B | V4L2_STD_PAL_G | V4L2_STD_PAL_D | - V4L2_STD_PAL_I | V4L2_STD_PAL_N | V4L2_STD_PAL_Nc)) { + } else if (dev->norm & (V4L2_STD_PAL_B | V4L2_STD_PAL_G | + V4L2_STD_PAL_D | V4L2_STD_PAL_I | + V4L2_STD_PAL_N | V4L2_STD_PAL_Nc)) { cx231xx_info("do_mode_ctrl_overrides PAL\n"); - status = - cx231xx_read_modify_write_i2c_dword(dev, + status = cx231xx_read_modify_write_i2c_dword(dev, HAMMERHEAD_I2C_ADDRESS, VERT_TIM_CTRL, FLD_VBLANK_CNT, 0x24); /* Adjust the active video horizontal start point */ - status = - cx231xx_read_modify_write_i2c_dword(dev, + status = cx231xx_read_modify_write_i2c_dword(dev, HAMMERHEAD_I2C_ADDRESS, HORIZ_TIM_CTRL, FLD_HBLANK_CNT, cx231xx_set_field (FLD_HBLANK_CNT, 0x85)); - } else if (dev-> - norm & (V4L2_STD_SECAM_B | V4L2_STD_SECAM_D | - V4L2_STD_SECAM_G | V4L2_STD_SECAM_K | - V4L2_STD_SECAM_K1 | V4L2_STD_SECAM_L | - V4L2_STD_SECAM_LC)) { + } else if (dev->norm & (V4L2_STD_SECAM_B | V4L2_STD_SECAM_D | + V4L2_STD_SECAM_G | V4L2_STD_SECAM_K | + V4L2_STD_SECAM_K1 | V4L2_STD_SECAM_L | + V4L2_STD_SECAM_LC)) { cx231xx_info("do_mode_ctrl_overrides SECAM\n"); - status = - cx231xx_read_modify_write_i2c_dword(dev, + status = cx231xx_read_modify_write_i2c_dword(dev, HAMMERHEAD_I2C_ADDRESS, VERT_TIM_CTRL, FLD_VBLANK_CNT, 0x24); /* Adjust the active video horizontal start point */ - status = - cx231xx_read_modify_write_i2c_dword(dev, + status = cx231xx_read_modify_write_i2c_dword(dev, HAMMERHEAD_I2C_ADDRESS, HORIZ_TIM_CTRL, FLD_HBLANK_CNT, @@ -1137,69 +1011,57 @@ int cx231xx_set_audio_decoder_input(struct cx231xx *dev, u32 value = 0; /* Put it in soft reset */ - status = - cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, GENERAL_CTL, 2, - &gen_ctrl, 1); + status = cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + GENERAL_CTL, 2, &gen_ctrl, 1); gen_ctrl |= 1; - status = - cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, GENERAL_CTL, 2, - gen_ctrl, 1); + status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + GENERAL_CTL, 2, gen_ctrl, 1); switch (audio_input) { case AUDIO_INPUT_LINE: - /* setup AUD_IO control from Merlin paralle output */ - value = - cx231xx_set_field(FLD_AUD_CHAN1_SRC, AUD_CHAN_SRC_PARALLEL); - status = - cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, - AUD_IO_CTRL, 2, value, 4); + value = cx231xx_set_field(FLD_AUD_CHAN1_SRC, + AUD_CHAN_SRC_PARALLEL); + status = cx231xx_write_i2c_data(dev, + HAMMERHEAD_I2C_ADDRESS, + AUD_IO_CTRL, 2, value, 4); /* setup input to Merlin, SRC2 connect to AC97 bypass upsample-by-2, slave mode, sony mode, left justify adr 091c, dat 01000000 */ - status = - cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, AC97_CTL, + status = cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + AC97_CTL, 2, &dwval, 4); - status = - cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, AC97_CTL, 2, (dwval | FLD_AC97_UP2X_BYPASS), 4); /* select the parallel1 and SRC3 */ - status = - cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, - BAND_OUT_SEL, 2, - cx231xx_set_field(FLD_SRC3_IN_SEL, - 0x0) | - cx231xx_set_field(FLD_SRC3_CLK_SEL, - 0x0) | - cx231xx_set_field - (FLD_PARALLEL1_SRC_SEL, 0x0), 4); + status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + BAND_OUT_SEL, 2, + cx231xx_set_field(FLD_SRC3_IN_SEL, 0x0) | + cx231xx_set_field(FLD_SRC3_CLK_SEL, 0x0) | + cx231xx_set_field(FLD_PARALLEL1_SRC_SEL, 0x0), + 4); /* unmute all, AC97 in, independence mode adr 08d0, data 0x00063073 */ - status = - cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, PATH1_CTL1, 2, 0x00063073, 4); /* set AVC maximum threshold, adr 08d4, dat ffff0024 */ - status = - cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + status = cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, PATH1_VOL_CTL, 2, &dwval, 4); - status = - cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, PATH1_VOL_CTL, 2, (dwval | FLD_PATH1_AVC_THRESHOLD), 4); /* set SC maximum threshold, adr 08ec, dat ffffb3a3 */ - status = - cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + status = cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, PATH1_SC_CTL, 2, &dwval, 4); - status = - cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, PATH1_SC_CTL, 2, (dwval | FLD_PATH1_SC_THRESHOLD), 4); break; @@ -1208,73 +1070,46 @@ int cx231xx_set_audio_decoder_input(struct cx231xx *dev, default: /* Setup SRC sources and clocks */ - status = - cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, - BAND_OUT_SEL, 2, - cx231xx_set_field(FLD_SRC6_IN_SEL, - 0x00) | - cx231xx_set_field(FLD_SRC6_CLK_SEL, - 0x01) | - cx231xx_set_field(FLD_SRC5_IN_SEL, - 0x00) | - cx231xx_set_field(FLD_SRC5_CLK_SEL, - 0x02) | - cx231xx_set_field(FLD_SRC4_IN_SEL, - 0x02) | - cx231xx_set_field(FLD_SRC4_CLK_SEL, - 0x03) | - cx231xx_set_field(FLD_SRC3_IN_SEL, - 0x00) | - cx231xx_set_field(FLD_SRC3_CLK_SEL, - 0x00) | - cx231xx_set_field - (FLD_BASEBAND_BYPASS_CTL, - 0x00) | - cx231xx_set_field(FLD_AC97_SRC_SEL, - 0x03) | - cx231xx_set_field(FLD_I2S_SRC_SEL, - 0x00) | - cx231xx_set_field - (FLD_PARALLEL2_SRC_SEL, - 0x02) | - cx231xx_set_field - (FLD_PARALLEL1_SRC_SEL, 0x01), 4); + status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + BAND_OUT_SEL, 2, + cx231xx_set_field(FLD_SRC6_IN_SEL, 0x00) | + cx231xx_set_field(FLD_SRC6_CLK_SEL, 0x01) | + cx231xx_set_field(FLD_SRC5_IN_SEL, 0x00) | + cx231xx_set_field(FLD_SRC5_CLK_SEL, 0x02) | + cx231xx_set_field(FLD_SRC4_IN_SEL, 0x02) | + cx231xx_set_field(FLD_SRC4_CLK_SEL, 0x03) | + cx231xx_set_field(FLD_SRC3_IN_SEL, 0x00) | + cx231xx_set_field(FLD_SRC3_CLK_SEL, 0x00) | + cx231xx_set_field(FLD_BASEBAND_BYPASS_CTL, 0x00) | + cx231xx_set_field(FLD_AC97_SRC_SEL, 0x03) | + cx231xx_set_field(FLD_I2S_SRC_SEL, 0x00) | + cx231xx_set_field(FLD_PARALLEL2_SRC_SEL, 0x02) | + cx231xx_set_field(FLD_PARALLEL1_SRC_SEL, 0x01), 4); /* Setup the AUD_IO control */ - status = - cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, - AUD_IO_CTRL, 2, - cx231xx_set_field(FLD_I2S_PORT_DIR, - 0x00) | - cx231xx_set_field(FLD_I2S_OUT_SRC, - 0x00) | - cx231xx_set_field(FLD_AUD_CHAN3_SRC, - 0x00) | - cx231xx_set_field(FLD_AUD_CHAN2_SRC, - 0x00) | - cx231xx_set_field(FLD_AUD_CHAN1_SRC, - 0x03), 4); + status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + AUD_IO_CTRL, 2, + cx231xx_set_field(FLD_I2S_PORT_DIR, 0x00) | + cx231xx_set_field(FLD_I2S_OUT_SRC, 0x00) | + cx231xx_set_field(FLD_AUD_CHAN3_SRC, 0x00) | + cx231xx_set_field(FLD_AUD_CHAN2_SRC, 0x00) | + cx231xx_set_field(FLD_AUD_CHAN1_SRC, 0x03), 4); - status = - cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, PATH1_CTL1, 2, 0x1F063870, 4); /* setAudioStandard(_audio_standard); */ - status = - cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, PATH1_CTL1, 2, 0x00063870, 4); switch (dev->model) { case CX231XX_BOARD_CNXT_RDE_250: case CX231XX_BOARD_CNXT_RDU_250: - status = - cx231xx_read_modify_write_i2c_dword(dev, - HAMMERHEAD_I2C_ADDRESS, - CHIP_CTRL, - FLD_SIF_EN, - cx231xx_set_field - (FLD_SIF_EN, - 1)); + status = cx231xx_read_modify_write_i2c_dword(dev, + HAMMERHEAD_I2C_ADDRESS, + CHIP_CTRL, + FLD_SIF_EN, + cx231xx_set_field(FLD_SIF_EN, 1)); break; default: break; @@ -1289,20 +1124,17 @@ int cx231xx_set_audio_decoder_input(struct cx231xx *dev, break; case AUDIO_INPUT_MUTE: - status = - cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, PATH1_CTL1, 2, 0x1F011012, 4); break; } /* Take it out of soft reset */ - status = - cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, GENERAL_CTL, 2, - &gen_ctrl, 1); + status = cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + GENERAL_CTL, 2, &gen_ctrl, 1); gen_ctrl &= ~1; - status = - cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, GENERAL_CTL, 2, - gen_ctrl, 1); + status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + GENERAL_CTL, 2, gen_ctrl, 1); return status; } @@ -1320,33 +1152,29 @@ int cx231xx_resolution_set(struct cx231xx *dev) get_scale(dev, width, height, &hscale, &vscale); /* set horzontal scale */ - status = - cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, HSCALE_CTRL, 2, - hscale, 4); + status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + HSCALE_CTRL, 2, hscale, 4); /* set vertical scale */ - status = - cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, VSCALE_CTRL, 2, - vscale, 4); + status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + VSCALE_CTRL, 2, vscale, 4); return status; } -/************************************************************************************* - * C H I P Specific C O N T R O L functions * - *************************************************************************************/ +/****************************************************************************** + * C H I P Specific C O N T R O L functions * + ******************************************************************************/ int cx231xx_init_ctrl_pin_status(struct cx231xx *dev) { u32 value; int status = 0; - status = - cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, PIN_CTRL, 2, - &value, 4); + status = cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, PIN_CTRL, + 2, &value, 4); value |= (~dev->board.ctl_pin_status_mask); - status = - cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, PIN_CTRL, 2, - value, 4); + status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, PIN_CTRL, + 2, value, 4); return status; } @@ -1357,14 +1185,12 @@ int cx231xx_set_agc_analog_digital_mux_select(struct cx231xx *dev, int status = 0; /* first set the direction to output */ - status = - cx231xx_set_gpio_direction(dev, - dev->board. - agc_analog_digital_select_gpio, 1); + status = cx231xx_set_gpio_direction(dev, + dev->board. + agc_analog_digital_select_gpio, 1); /* 0 - demod ; 1 - Analog mode */ - status = - cx231xx_set_gpio_value(dev, + status = cx231xx_set_gpio_value(dev, dev->board.agc_analog_digital_select_gpio, analog_or_digital); @@ -1378,23 +1204,21 @@ int cx231xx_enable_i2c_for_tuner(struct cx231xx *dev, u8 I2CIndex) cx231xx_info("Changing the i2c port for tuner to %d\n", I2CIndex); - status = - cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, PWR_CTL_EN, value, 4); + status = cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, + PWR_CTL_EN, value, 4); if (status < 0) return status; if (I2CIndex == I2C_1) { if (value[0] & I2C_DEMOD_EN) { value[0] &= ~I2C_DEMOD_EN; - status = - cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER, + status = cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER, PWR_CTL_EN, value, 4); } } else { if (!(value[0] & I2C_DEMOD_EN)) { value[0] |= I2C_DEMOD_EN; - status = - cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER, + status = cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER, PWR_CTL_EN, value, 4); } } @@ -1403,9 +1227,9 @@ int cx231xx_enable_i2c_for_tuner(struct cx231xx *dev, u8 I2CIndex) } -/************************************************************************************* - * D I F - B L O C K C O N T R O L functions * - *************************************************************************************/ +/****************************************************************************** + * D I F - B L O C K C O N T R O L functions * + ******************************************************************************/ int cx231xx_dif_configure_C2HH_for_low_IF(struct cx231xx *dev, u32 mode, u32 function_mode, u32 standard) { @@ -1413,10 +1237,14 @@ int cx231xx_dif_configure_C2HH_for_low_IF(struct cx231xx *dev, u32 mode, if (mode == V4L2_TUNER_RADIO) { /* C2HH */ - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, AFE_CTRL_C2HH_SRC_CTRL, 30, 31, 0x1); /* lo if big signal */ - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, AFE_CTRL_C2HH_SRC_CTRL, 23, 24, function_mode); /* FUNC_MODE = DIF */ - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, AFE_CTRL_C2HH_SRC_CTRL, 15, 22, 0xFF); /* IF_MODE */ - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, AFE_CTRL_C2HH_SRC_CTRL, 9, 9, 0x1); /* no inv */ + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + AFE_CTRL_C2HH_SRC_CTRL, 30, 31, 0x1); /* lo if big signal */ + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + AFE_CTRL_C2HH_SRC_CTRL, 23, 24, function_mode); /* FUNC_MODE = DIF */ + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + AFE_CTRL_C2HH_SRC_CTRL, 15, 22, 0xFF); /* IF_MODE */ + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + AFE_CTRL_C2HH_SRC_CTRL, 9, 9, 0x1); /* no inv */ } else { switch (standard) { case V4L2_STD_NTSC_M: /* 75 IRE Setup */ @@ -1424,20 +1252,40 @@ int cx231xx_dif_configure_C2HH_for_low_IF(struct cx231xx *dev, u32 mode, case V4L2_STD_PAL_M: case V4L2_STD_PAL_N: case V4L2_STD_PAL_Nc: - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, AFE_CTRL_C2HH_SRC_CTRL, 30, 31, 0x1); /* lo if big signal */ - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, AFE_CTRL_C2HH_SRC_CTRL, 23, 24, function_mode); /* FUNC_MODE = DIF */ - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, AFE_CTRL_C2HH_SRC_CTRL, 15, 22, 0xb); /* IF_MODE */ - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, AFE_CTRL_C2HH_SRC_CTRL, 9, 9, 0x1); /* no inv */ - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, AUD_IO_CTRL, 0, 31, 0x00000003); /* 0x124, AUD_CHAN1_SRC = 0x3 */ + status = cx231xx_reg_mask_write(dev, + HAMMERHEAD_I2C_ADDRESS, 32, + AFE_CTRL_C2HH_SRC_CTRL, 30, 31, 0x1); /* lo if big signal */ + status = cx231xx_reg_mask_write(dev, + HAMMERHEAD_I2C_ADDRESS, 32, + AFE_CTRL_C2HH_SRC_CTRL, 23, 24, + function_mode); /* FUNC_MODE = DIF */ + status = cx231xx_reg_mask_write(dev, + HAMMERHEAD_I2C_ADDRESS, 32, + AFE_CTRL_C2HH_SRC_CTRL, 15, 22, 0xb); /* IF_MODE */ + status = cx231xx_reg_mask_write(dev, + HAMMERHEAD_I2C_ADDRESS, 32, + AFE_CTRL_C2HH_SRC_CTRL, 9, 9, 0x1); /* no inv */ + status = cx231xx_reg_mask_write(dev, + HAMMERHEAD_I2C_ADDRESS, 32, + AUD_IO_CTRL, 0, 31, 0x00000003); /* 0x124, AUD_CHAN1_SRC = 0x3 */ break; case V4L2_STD_PAL_B: case V4L2_STD_PAL_G: /* C2HH setup */ - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, AFE_CTRL_C2HH_SRC_CTRL, 30, 31, 0x1); /* lo if big signal */ - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, AFE_CTRL_C2HH_SRC_CTRL, 23, 24, function_mode); /* FUNC_MODE = DIF */ - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, AFE_CTRL_C2HH_SRC_CTRL, 15, 22, 0xE); /* IF_MODE */ - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, AFE_CTRL_C2HH_SRC_CTRL, 9, 9, 0x1); /* no inv */ + status = cx231xx_reg_mask_write(dev, + HAMMERHEAD_I2C_ADDRESS, 32, + AFE_CTRL_C2HH_SRC_CTRL, 30, 31, 0x1); /* lo if big signal */ + status = cx231xx_reg_mask_write(dev, + HAMMERHEAD_I2C_ADDRESS, 32, + AFE_CTRL_C2HH_SRC_CTRL, 23, 24, + function_mode); /* FUNC_MODE = DIF */ + status = cx231xx_reg_mask_write(dev, + HAMMERHEAD_I2C_ADDRESS, 32, + AFE_CTRL_C2HH_SRC_CTRL, 15, 22, 0xE); /* IF_MODE */ + status = cx231xx_reg_mask_write(dev, + HAMMERHEAD_I2C_ADDRESS, 32, + AFE_CTRL_C2HH_SRC_CTRL, 9, 9, 0x1); /* no inv */ break; case V4L2_STD_PAL_D: @@ -1450,10 +1298,19 @@ int cx231xx_dif_configure_C2HH_for_low_IF(struct cx231xx *dev, u32 mode, case V4L2_STD_SECAM_K: case V4L2_STD_SECAM_K1: /* C2HH setup */ - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, AFE_CTRL_C2HH_SRC_CTRL, 30, 31, 0x1); /* lo if big signal */ - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, AFE_CTRL_C2HH_SRC_CTRL, 23, 24, function_mode); /* FUNC_MODE = DIF */ - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, AFE_CTRL_C2HH_SRC_CTRL, 15, 22, 0xF); /* IF_MODE */ - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, AFE_CTRL_C2HH_SRC_CTRL, 9, 9, 0x1); /* no inv */ + status = cx231xx_reg_mask_write(dev, + HAMMERHEAD_I2C_ADDRESS, 32, + AFE_CTRL_C2HH_SRC_CTRL, 30, 31, 0x1); /* lo if big signal */ + status = cx231xx_reg_mask_write(dev, + HAMMERHEAD_I2C_ADDRESS, 32, + AFE_CTRL_C2HH_SRC_CTRL, 23, 24, + function_mode); /* FUNC_MODE = DIF */ + status = cx231xx_reg_mask_write(dev, + HAMMERHEAD_I2C_ADDRESS, 32, + AFE_CTRL_C2HH_SRC_CTRL, 15, 22, 0xF); /* IF_MODE */ + status = cx231xx_reg_mask_write(dev, + HAMMERHEAD_I2C_ADDRESS, 32, + AFE_CTRL_C2HH_SRC_CTRL, 9, 9, 0x1); /* no inv */ break; case DIF_USE_BASEBAND: @@ -1489,20 +1346,18 @@ int cx231xx_dif_set_standard(struct cx231xx *dev, u32 standard) func_mode = 0x01; } - status = - cx231xx_dif_configure_C2HH_for_low_IF(dev, dev->active_mode, + status = cx231xx_dif_configure_C2HH_for_low_IF(dev, dev->active_mode, func_mode, standard); if (standard == DIF_USE_BASEBAND) { /* base band */ - - /* There is a different SRC_PHASE_INC value for baseband vs. DIF */ + /* There is a different SRC_PHASE_INC value + for baseband vs. DIF */ status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_SRC_PHASE_INC, 2, 0xDF7DF83, 4); - status = - cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, - DIF_MISC_CTRL, 2, - &dif_misc_ctrl_value, 4); + status = cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + DIF_MISC_CTRL, 2, + &dif_misc_ctrl_value, 4); dif_misc_ctrl_value |= FLD_DIF_DIF_BYPASS; status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_MISC_CTRL, 2, @@ -1510,127 +1365,92 @@ int cx231xx_dif_set_standard(struct cx231xx *dev, u32 standard) } else if (standard & (V4L2_STD_PAL_B | V4L2_STD_PAL_G)) { - status = - cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_PLL_CTRL, 0, 31, 0x6503bc0c); - status = - cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_PLL_CTRL1, 0, 31, 0xbd038c85); - status = - cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_PLL_CTRL2, 0, 31, 0x1db4640a); - status = - cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_PLL_CTRL3, 0, 31, 0x00008800); - status = - cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_AGC_IF_REF, 0, 31, 0x444C1380); - status = - cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_AGC_CTRL_IF, 0, 31, 0xDA302600); - status = - cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_AGC_CTRL_INT, 0, 31, 0xDA261700); - status = - cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_AGC_CTRL_RF, 0, 31, 0xDA262600); - status = - cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_AGC_IF_INT_CURRENT, 0, 31, 0x26001700); - status = - cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_AGC_RF_CURRENT, 0, 31, 0x00002660); - status = - cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_VIDEO_AGC_CTRL, 0, 31, 0x72500800); - status = - cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_VID_AUD_OVERRIDE, 0, 31, 0x27000100); - status = - cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_AV_SEP_CTRL, 0, 31, 0x3F3530EC); - status = - cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_COMP_FLT_CTRL, 0, 31, 0x00A653A8); - status = - cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_SRC_PHASE_INC, 0, 31, 0x1befbf06); - status = - cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_SRC_GAIN_CONTROL, 0, 31, 0x000035e8); - status = - cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_RPT_VARIANCE, 0, 31, 0x00000000); /* Save the Spec Inversion value */ dif_misc_ctrl_value &= FLD_DIF_SPEC_INV; dif_misc_ctrl_value |= 0x3a013F11; } else if (standard & V4L2_STD_PAL_D) { - - status = - cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_PLL_CTRL, 0, 31, 0x6503bc0c); - status = - cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_PLL_CTRL1, 0, 31, 0xbd038c85); - status = - cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_PLL_CTRL2, 0, 31, 0x1db4640a); - status = - cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_PLL_CTRL3, 0, 31, 0x00008800); - status = - cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_AGC_IF_REF, 0, 31, 0x444C1380); - status = - cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_AGC_CTRL_IF, 0, 31, 0xDA302600); - status = - cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_AGC_CTRL_INT, 0, 31, 0xDA261700); - status = - cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_AGC_CTRL_RF, 0, 31, 0xDA262600); - status = - cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_AGC_IF_INT_CURRENT, 0, 31, 0x26001700); - status = - cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_AGC_RF_CURRENT, 0, 31, 0x00002660); - status = - cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_VIDEO_AGC_CTRL, 0, 31, 0x72500800); - status = - cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_VID_AUD_OVERRIDE, 0, 31, 0x27000100); - status = - cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_AV_SEP_CTRL, 0, 31, 0x3F3934EA); - status = - cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_COMP_FLT_CTRL, 0, 31, 0x00000000); - status = - cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_SRC_PHASE_INC, 0, 31, 0x1befbf06); - status = - cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_SRC_GAIN_CONTROL, 0, 31, 0x000035e8); - status = - cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_RPT_VARIANCE, 0, 31, 0x00000000); /* Save the Spec Inversion value */ dif_misc_ctrl_value &= FLD_DIF_SPEC_INV; @@ -1638,116 +1458,86 @@ int cx231xx_dif_set_standard(struct cx231xx *dev, u32 standard) } else if (standard & V4L2_STD_PAL_I) { - status = - cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_PLL_CTRL, 0, 31, 0x6503bc0c); - status = - cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_PLL_CTRL1, 0, 31, 0xbd038c85); - status = - cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_PLL_CTRL2, 0, 31, 0x1db4640a); - status = - cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_PLL_CTRL3, 0, 31, 0x00008800); - status = - cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_AGC_IF_REF, 0, 31, 0x444C1380); - status = - cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_AGC_CTRL_IF, 0, 31, 0xDA302600); - status = - cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_AGC_CTRL_INT, 0, 31, 0xDA261700); - status = - cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_AGC_CTRL_RF, 0, 31, 0xDA262600); - status = - cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_AGC_IF_INT_CURRENT, 0, 31, 0x26001700); - status = - cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_AGC_RF_CURRENT, 0, 31, 0x00002660); - status = - cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_VIDEO_AGC_CTRL, 0, 31, 0x72500800); - status = - cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_VID_AUD_OVERRIDE, 0, 31, 0x27000100); - status = - cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_AV_SEP_CTRL, 0, 31, 0x5F39A934); - status = - cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_COMP_FLT_CTRL, 0, 31, 0x00000000); - status = - cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_SRC_PHASE_INC, 0, 31, 0x1befbf06); - status = - cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_SRC_GAIN_CONTROL, 0, 31, 0x000035e8); - status = - cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_RPT_VARIANCE, 0, 31, 0x00000000); /* Save the Spec Inversion value */ dif_misc_ctrl_value &= FLD_DIF_SPEC_INV; dif_misc_ctrl_value |= 0x3a033F11; } else if (standard & V4L2_STD_PAL_M) { - /* improved Low Frequency Phase Noise */ status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_PLL_CTRL, 2, 0xFF01FF0C, 4); status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_PLL_CTRL1, 2, 0xbd038c85, 4); - status = - cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_PLL_CTRL2, 2, 0x1db4640a, 4); - status = - cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_PLL_CTRL3, 2, 0x00008800, 4); - status = - cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_AGC_IF_REF, 2, 0x444C1380, 4); - status = - cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_AGC_IF_INT_CURRENT, 2, 0x26001700, 4); - status = - cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_AGC_RF_CURRENT, 2, 0x00002660, 4); - status = - cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_VIDEO_AGC_CTRL, 2, 0x72500800, 4); - status = - cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_VID_AUD_OVERRIDE, 2, 0x27000100, 4); - status = - cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_AV_SEP_CTRL, 2, 0x012c405d, 4); - status = - cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_COMP_FLT_CTRL, 2, 0x009f50c1, 4); - status = - cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_SRC_PHASE_INC, 2, 0x1befbf06, 4); - status = - cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_SRC_GAIN_CONTROL, 2, 0x000035e8, 4); - status = - cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_SOFT_RST_CTRL_REVB, 2, 0x00000000, 4); @@ -1758,52 +1548,38 @@ int cx231xx_dif_set_standard(struct cx231xx *dev, u32 standard) } else if (standard & (V4L2_STD_PAL_N | V4L2_STD_PAL_Nc)) { /* improved Low Frequency Phase Noise */ - status = - cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_PLL_CTRL, 2, 0xFF01FF0C, 4); - status = - cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_PLL_CTRL1, 2, 0xbd038c85, 4); - status = - cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_PLL_CTRL2, 2, 0x1db4640a, 4); - status = - cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_PLL_CTRL3, 2, 0x00008800, 4); - status = - cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_AGC_IF_REF, 2, 0x444C1380, 4); - status = - cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_AGC_IF_INT_CURRENT, 2, 0x26001700, 4); - status = - cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_AGC_RF_CURRENT, 2, 0x00002660, 4); - status = - cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_VIDEO_AGC_CTRL, 2, 0x72500800, 4); - status = - cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_VID_AUD_OVERRIDE, 2, 0x27000100, 4); - status = - cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_AV_SEP_CTRL, 2, 0x012c405d, 4); - status = - cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_COMP_FLT_CTRL, 2, 0x009f50c1, 4); - status = - cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_SRC_PHASE_INC, 2, 0x1befbf06, 4); - status = - cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_SRC_GAIN_CONTROL, 2, 0x000035e8, 4); - status = - cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_SOFT_RST_CTRL_REVB, 2, 0x00000000, 4); @@ -1815,62 +1591,45 @@ int cx231xx_dif_set_standard(struct cx231xx *dev, u32 standard) (V4L2_STD_SECAM_B | V4L2_STD_SECAM_D | V4L2_STD_SECAM_G | V4L2_STD_SECAM_K | V4L2_STD_SECAM_K1)) { - status = - cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_PLL_CTRL, 0, 31, 0x6503bc0c); - status = - cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_PLL_CTRL1, 0, 31, 0xbd038c85); - status = - cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_PLL_CTRL2, 0, 31, 0x1db4640a); - status = - cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_PLL_CTRL3, 0, 31, 0x00008800); - status = - cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_AGC_IF_REF, 0, 31, 0x888C0380); - status = - cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_AGC_CTRL_IF, 0, 31, 0xe0262600); - status = - cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_AGC_CTRL_INT, 0, 31, 0xc2171700); - status = - cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_AGC_CTRL_RF, 0, 31, 0xc2262600); - status = - cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_AGC_IF_INT_CURRENT, 0, 31, 0x26001700); - status = - cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_AGC_RF_CURRENT, 0, 31, 0x00002660); - status = - cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_VID_AUD_OVERRIDE, 0, 31, 0x27000100); - status = - cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_AV_SEP_CTRL, 0, 31, 0x3F3530ec); - status = - cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_COMP_FLT_CTRL, 0, 31, 0x00000000); - status = - cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_SRC_PHASE_INC, 0, 31, 0x1befbf06); - status = - cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_SRC_GAIN_CONTROL, 0, 31, 0x000035e8); - status = - cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_RPT_VARIANCE, 0, 31, 0x00000000); - status = - cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_VIDEO_AGC_CTRL, 0, 31, 0xf4000000); @@ -1881,62 +1640,45 @@ int cx231xx_dif_set_standard(struct cx231xx *dev, u32 standard) } else if (standard & (V4L2_STD_SECAM_L | V4L2_STD_SECAM_LC)) { /* Is it SECAM_L1? */ - status = - cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_PLL_CTRL, 0, 31, 0x6503bc0c); - status = - cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_PLL_CTRL1, 0, 31, 0xbd038c85); - status = - cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_PLL_CTRL2, 0, 31, 0x1db4640a); - status = - cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_PLL_CTRL3, 0, 31, 0x00008800); - status = - cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_AGC_IF_REF, 0, 31, 0x888C0380); - status = - cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_AGC_CTRL_IF, 0, 31, 0xe0262600); - status = - cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_AGC_CTRL_INT, 0, 31, 0xc2171700); - status = - cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_AGC_CTRL_RF, 0, 31, 0xc2262600); - status = - cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_AGC_IF_INT_CURRENT, 0, 31, 0x26001700); - status = - cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_AGC_RF_CURRENT, 0, 31, 0x00002660); - status = - cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_VID_AUD_OVERRIDE, 0, 31, 0x27000100); - status = - cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_AV_SEP_CTRL, 0, 31, 0x3F3530ec); - status = - cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_COMP_FLT_CTRL, 0, 31, 0x00000000); - status = - cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_SRC_PHASE_INC, 0, 31, 0x1befbf06); - status = - cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_SRC_GAIN_CONTROL, 0, 31, 0x000035e8); - status = - cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_RPT_VARIANCE, 0, 31, 0x00000000); - status = - cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_VIDEO_AGC_CTRL, 0, 31, 0xf2560000); @@ -1944,67 +1686,54 @@ int cx231xx_dif_set_standard(struct cx231xx *dev, u32 standard) dif_misc_ctrl_value &= FLD_DIF_SPEC_INV; dif_misc_ctrl_value |= 0x3a023F11; - } else { /* V4L2_STD_NTSC_M (75 IRE Setup) Or V4L2_STD_NTSC_M_JP (Japan, 0 IRE Setup) */ + } else { + /* V4L2_STD_NTSC_M (75 IRE Setup) Or + V4L2_STD_NTSC_M_JP (Japan, 0 IRE Setup) */ - /* For NTSC the centre frequency of video coming out of sidewinder is - around 7.1MHz or 3.6MHz depending on the spectral inversion. - so for a non spectrally inverted channel the pll freq word is 0x03420c49 + /* For NTSC the centre frequency of video coming out of + sidewinder is around 7.1MHz or 3.6MHz depending on the + spectral inversion. so for a non spectrally inverted channel + the pll freq word is 0x03420c49 */ - status = - cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_PLL_CTRL, 2, 0x6503BC0C, 4); - status = - cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_PLL_CTRL1, 2, 0xBD038C85, 4); - status = - cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_PLL_CTRL2, 2, 0x1DB4640A, 4); - status = - cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_PLL_CTRL3, 2, 0x00008800, 4); - status = - cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_AGC_IF_REF, 2, 0x444C0380, 4); - status = - cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_AGC_IF_INT_CURRENT, 2, 0x26001700, 4); - status = - cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_AGC_RF_CURRENT, 2, 0x00002660, 4); - status = - cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_VIDEO_AGC_CTRL, 2, 0x04000800, 4); - status = - cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_VID_AUD_OVERRIDE, 2, 0x27000100, 4); - status = - cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_AV_SEP_CTRL, 2, 0x01296e1f, 4); - status = - cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_COMP_FLT_CTRL, 2, 0x009f50c1, 4); - status = - cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_SRC_PHASE_INC, 2, 0x1befbf06, 4); - status = - cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_SRC_GAIN_CONTROL, 2, 0x000035e8, 4); - status = - cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_AGC_CTRL_IF, 2, 0xC2262600, 4); - status = - cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_AGC_CTRL_INT, 2, 0xC2262600, 4); - status = - cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_AGC_CTRL_RF, 2, 0xC2262600, 4); /* Save the Spec Inversion value */ @@ -2017,7 +1746,8 @@ int cx231xx_dif_set_standard(struct cx231xx *dev, u32 standard) AUD_SRC_SEL[19] should always be disabled */ dif_misc_ctrl_value &= ~FLD_DIF_AUD_SRC_SEL; - /* It is still possible to get Set Standard calls even when we are in FM mode + /* It is still possible to get Set Standard calls even when we + are in FM mode. This is done to override the value for FM. */ if (dev->active_mode == V4L2_TUNER_RADIO) dif_misc_ctrl_value = 0x7a080000; @@ -2057,12 +1787,11 @@ int cx231xx_tuner_post_channel_change(struct cx231xx *dev) DIF_AGC_IF_REF, 2, &dwval, 4); dwval &= ~(FLD_DIF_K_AGC_RF | FLD_DIF_K_AGC_IF); - if (dev-> - norm & (V4L2_STD_SECAM_L | V4L2_STD_SECAM_B | V4L2_STD_SECAM_D)) { + if (dev->norm & (V4L2_STD_SECAM_L | V4L2_STD_SECAM_B | + V4L2_STD_SECAM_D)) dwval |= 0x88000000; - } else { + else dwval |= 0x44000000; - } status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_AGC_IF_REF, 2, dwval, 4); @@ -2070,17 +1799,16 @@ int cx231xx_tuner_post_channel_change(struct cx231xx *dev) return status; } -/************************************************************************************* - * F L A T I R O N - B L O C K C O N T R O L functions * - *************************************************************************************/ +/****************************************************************************** + * F L A T I R O N - B L O C K C O N T R O L functions * + ******************************************************************************/ int cx231xx_flatiron_initialize(struct cx231xx *dev) { int status = 0; u32 value; - status = - cx231xx_read_i2c_data(dev, Flatrion_DEVICE_ADDRESS, CH_PWR_CTRL1, 1, - &value, 1); + status = cx231xx_read_i2c_data(dev, Flatrion_DEVICE_ADDRESS, + CH_PWR_CTRL1, 1, &value, 1); /* enables clock to delta-sigma and decimation filter */ value |= 0x80; status = cx231xx_write_i2c_data(dev, Flatrion_DEVICE_ADDRESS, @@ -2098,8 +1826,7 @@ int cx231xx_flatiron_update_power_control(struct cx231xx *dev, AV_MODE avmode) u32 value = 0; if (avmode != POLARIS_AVMODE_ENXTERNAL_AV) { - status = - cx231xx_read_i2c_data(dev, Flatrion_DEVICE_ADDRESS, + status = cx231xx_read_i2c_data(dev, Flatrion_DEVICE_ADDRESS, CH_PWR_CTRL2, 1, &value, 1); value |= 0xfe; status = cx231xx_write_i2c_data(dev, Flatrion_DEVICE_ADDRESS, @@ -2119,7 +1846,6 @@ int cx231xx_flatiron_set_audio_input(struct cx231xx *dev, u8 audio_input) switch (audio_input) { case CX231XX_AMUX_LINE_IN: - status = cx231xx_write_i2c_data(dev, Flatrion_DEVICE_ADDRESS, CH_PWR_CTRL2, 1, 0x00, 1); status = cx231xx_write_i2c_data(dev, Flatrion_DEVICE_ADDRESS, @@ -2135,9 +1861,9 @@ int cx231xx_flatiron_set_audio_input(struct cx231xx *dev, u8 audio_input) return status; } -/************************************************************************************* - * P O W E R C O N T R O L functions * - *************************************************************************************/ +/****************************************************************************** + * P O W E R C O N T R O L functions * + ******************************************************************************/ int cx231xx_set_power_mode(struct cx231xx *dev, AV_MODE mode) { u8 value[4] = { 0, 0, 0, 0 }; @@ -2154,8 +1880,8 @@ int cx231xx_set_power_mode(struct cx231xx *dev, AV_MODE mode) cx231xx_info(" setPowerMode::mode = %d\n", mode); - status = - cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, PWR_CTL_EN, value, 4); + status = cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, PWR_CTL_EN, value, + 4); if (status < 0) return status; @@ -2171,9 +1897,8 @@ int cx231xx_set_power_mode(struct cx231xx *dev, AV_MODE mode) value[1] = (u8) (tmp >> 8); value[2] = (u8) (tmp >> 16); value[3] = (u8) (tmp >> 24); - status = - cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER, PWR_CTL_EN, - value, 4); + status = cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER, + PWR_CTL_EN, value, 4); msleep(PWR_SLEEP_INTERVAL); tmp |= PWR_ISO_EN; @@ -2191,9 +1916,8 @@ int cx231xx_set_power_mode(struct cx231xx *dev, AV_MODE mode) value[1] = (u8) (tmp >> 8); value[2] = (u8) (tmp >> 16); value[3] = (u8) (tmp >> 24); - status = - cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER, PWR_CTL_EN, - value, 4); + status = cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER, + PWR_CTL_EN, value, 4); dev->xc_fw_load_done = 0; /* reset state of xceive tuner */ break; @@ -2206,9 +1930,8 @@ int cx231xx_set_power_mode(struct cx231xx *dev, AV_MODE mode) value[1] = (u8) (tmp >> 8); value[2] = (u8) (tmp >> 16); value[3] = (u8) (tmp >> 24); - status = - cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER, PWR_CTL_EN, - value, 4); + status = cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER, + PWR_CTL_EN, value, 4); msleep(PWR_SLEEP_INTERVAL); if (!(tmp & PWR_TUNER_EN)) { @@ -2217,9 +1940,8 @@ int cx231xx_set_power_mode(struct cx231xx *dev, AV_MODE mode) value[1] = (u8) (tmp >> 8); value[2] = (u8) (tmp >> 16); value[3] = (u8) (tmp >> 24); - status = - cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER, - PWR_CTL_EN, value, 4); + status = cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER, + PWR_CTL_EN, value, 4); msleep(PWR_SLEEP_INTERVAL); } @@ -2229,9 +1951,8 @@ int cx231xx_set_power_mode(struct cx231xx *dev, AV_MODE mode) value[1] = (u8) (tmp >> 8); value[2] = (u8) (tmp >> 16); value[3] = (u8) (tmp >> 24); - status = - cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER, - PWR_CTL_EN, value, 4); + status = cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER, + PWR_CTL_EN, value, 4); msleep(PWR_SLEEP_INTERVAL); } if (!(tmp & PWR_ISO_EN)) { @@ -2240,9 +1961,8 @@ int cx231xx_set_power_mode(struct cx231xx *dev, AV_MODE mode) value[1] = (u8) (tmp >> 8); value[2] = (u8) (tmp >> 16); value[3] = (u8) (tmp >> 24); - status = - cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER, - PWR_CTL_EN, value, 4); + status = cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER, + PWR_CTL_EN, value, 4); msleep(PWR_SLEEP_INTERVAL); } @@ -2252,15 +1972,13 @@ int cx231xx_set_power_mode(struct cx231xx *dev, AV_MODE mode) value[1] = (u8) (tmp >> 8); value[2] = (u8) (tmp >> 16); value[3] = (u8) (tmp >> 24); - status = - cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER, - PWR_CTL_EN, value, 4); + status = cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER, + PWR_CTL_EN, value, 4); msleep(PWR_SLEEP_INTERVAL); } if ((dev->model == CX231XX_BOARD_CNXT_RDE_250) || (dev->model == CX231XX_BOARD_CNXT_RDU_250)) { - /* tuner path to channel 1 from port 3 */ cx231xx_enable_i2c_for_tuner(dev, I2C_3); @@ -2270,16 +1988,14 @@ int cx231xx_set_power_mode(struct cx231xx *dev, AV_MODE mode) break; case POLARIS_AVMODE_DIGITAL: - if (!(tmp & PWR_TUNER_EN)) { tmp |= (PWR_TUNER_EN); value[0] = (u8) tmp; value[1] = (u8) (tmp >> 8); value[2] = (u8) (tmp >> 16); value[3] = (u8) (tmp >> 24); - status = - cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER, - PWR_CTL_EN, value, 4); + status = cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER, + PWR_CTL_EN, value, 4); msleep(PWR_SLEEP_INTERVAL); } if (!(tmp & PWR_AV_EN)) { @@ -2288,9 +2004,8 @@ int cx231xx_set_power_mode(struct cx231xx *dev, AV_MODE mode) value[1] = (u8) (tmp >> 8); value[2] = (u8) (tmp >> 16); value[3] = (u8) (tmp >> 24); - status = - cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER, - PWR_CTL_EN, value, 4); + status = cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER, + PWR_CTL_EN, value, 4); msleep(PWR_SLEEP_INTERVAL); } if (!(tmp & PWR_ISO_EN)) { @@ -2299,9 +2014,8 @@ int cx231xx_set_power_mode(struct cx231xx *dev, AV_MODE mode) value[1] = (u8) (tmp >> 8); value[2] = (u8) (tmp >> 16); value[3] = (u8) (tmp >> 24); - status = - cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER, - PWR_CTL_EN, value, 4); + status = cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER, + PWR_CTL_EN, value, 4); msleep(PWR_SLEEP_INTERVAL); } @@ -2310,9 +2024,8 @@ int cx231xx_set_power_mode(struct cx231xx *dev, AV_MODE mode) value[1] = (u8) (tmp >> 8); value[2] = (u8) (tmp >> 16); value[3] = (u8) (tmp >> 24); - status = - cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER, PWR_CTL_EN, - value, 4); + status = cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER, + PWR_CTL_EN, value, 4); msleep(PWR_SLEEP_INTERVAL); if (!(tmp & PWR_DEMOD_EN)) { @@ -2321,15 +2034,13 @@ int cx231xx_set_power_mode(struct cx231xx *dev, AV_MODE mode) value[1] = (u8) (tmp >> 8); value[2] = (u8) (tmp >> 16); value[3] = (u8) (tmp >> 24); - status = - cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER, - PWR_CTL_EN, value, 4); + status = cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER, + PWR_CTL_EN, value, 4); msleep(PWR_SLEEP_INTERVAL); } if ((dev->model == CX231XX_BOARD_CNXT_RDE_250) || (dev->model == CX231XX_BOARD_CNXT_RDU_250)) { - /* tuner path to channel 1 from port 3 */ cx231xx_enable_i2c_for_tuner(dev, I2C_3); @@ -2344,16 +2055,16 @@ int cx231xx_set_power_mode(struct cx231xx *dev, AV_MODE mode) msleep(PWR_SLEEP_INTERVAL); - /* For power saving, only enable Pwr_resetout_n when digital TV is selected. */ + /* For power saving, only enable Pwr_resetout_n + when digital TV is selected. */ if (mode == POLARIS_AVMODE_DIGITAL) { tmp |= PWR_RESETOUT_EN; value[0] = (u8) tmp; value[1] = (u8) (tmp >> 8); value[2] = (u8) (tmp >> 16); value[3] = (u8) (tmp >> 24); - status = - cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER, PWR_CTL_EN, - value, 4); + status = cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER, + PWR_CTL_EN, value, 4); msleep(PWR_SLEEP_INTERVAL); } @@ -2363,11 +2074,10 @@ int cx231xx_set_power_mode(struct cx231xx *dev, AV_MODE mode) /* update power control for flatiron */ status = cx231xx_flatiron_update_power_control(dev, mode); - status = - cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, PWR_CTL_EN, value, 4); - cx231xx_info - (" The data of PWR_CTL_EN register 0x74=0x%0x,0x%0x,0x%0x,0x%0x\n", - value[0], value[1], value[2], value[3]); + status = cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, PWR_CTL_EN, value, + 4); + cx231xx_info(" The data of PWR_CTL_EN register 0x74=0x%0x,0x%0x,0x%0x,0x%0x\n", + value[0], value[1], value[2], value[3]); return status; } @@ -2378,8 +2088,8 @@ int cx231xx_power_suspend(struct cx231xx *dev) u32 tmp = 0; int status = 0; - status = - cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, PWR_CTL_EN, value, 4); + status = cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, PWR_CTL_EN, + value, 4); if (status > 0) return status; @@ -2390,15 +2100,15 @@ int cx231xx_power_suspend(struct cx231xx *dev) value[1] = (u8) (tmp >> 8); value[2] = (u8) (tmp >> 16); value[3] = (u8) (tmp >> 24); - status = - cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER, PWR_CTL_EN, value, 4); + status = cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER, PWR_CTL_EN, + value, 4); return status; } -/************************************************************************************* - * S T R E A M C O N T R O L functions * - *************************************************************************************/ +/****************************************************************************** + * S T R E A M C O N T R O L functions * + ******************************************************************************/ int cx231xx_start_stream(struct cx231xx *dev, u32 ep_mask) { u8 value[4] = { 0x0, 0x0, 0x0, 0x0 }; @@ -2406,8 +2116,8 @@ int cx231xx_start_stream(struct cx231xx *dev, u32 ep_mask) int status = 0; cx231xx_info("cx231xx_start_stream():: ep_mask = %x\n", ep_mask); - status = - cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, EP_MODE_SET, value, 4); + status = cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, EP_MODE_SET, + value, 4); if (status < 0) return status; @@ -2418,9 +2128,8 @@ int cx231xx_start_stream(struct cx231xx *dev, u32 ep_mask) value[2] = (u8) (tmp >> 16); value[3] = (u8) (tmp >> 24); - status = - cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER, EP_MODE_SET, value, - 4); + status = cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER, EP_MODE_SET, + value, 4); return status; } @@ -2444,9 +2153,8 @@ int cx231xx_stop_stream(struct cx231xx *dev, u32 ep_mask) value[2] = (u8) (tmp >> 16); value[3] = (u8) (tmp >> 24); - status = - cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER, EP_MODE_SET, value, - 4); + status = cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER, EP_MODE_SET, + value, 4); return status; } @@ -2558,9 +2266,8 @@ int cx231xx_capture_start(struct cx231xx *dev, int start, u8 media_type) if (start) { rc = cx231xx_initialize_stream_xfer(dev, media_type); - if (rc < 0) { + if (rc < 0) return rc; - } /* enable video capture */ if (ep_mask > 0) @@ -2571,20 +2278,21 @@ int cx231xx_capture_start(struct cx231xx *dev, int start, u8 media_type) rc = cx231xx_stop_stream(dev, ep_mask); } +#if 0 if (dev->mode == CX231XX_ANALOG_MODE) { /* do any in Analog mode */ } else { /* do any in digital mode */ } +#endif return rc; } - EXPORT_SYMBOL_GPL(cx231xx_capture_start); -/************************************************************************************ -* G P I O B I T control functions * -*************************************************************************************/ +/***************************************************************************** +* G P I O B I T control functions * +******************************************************************************/ int cx231xx_set_gpio_bit(struct cx231xx *dev, u32 gpio_bit, u8 * gpio_val) { int status = 0; @@ -2621,17 +2329,16 @@ int cx231xx_set_gpio_direction(struct cx231xx *dev, u32 value = 0; /* Check for valid pin_number - if 32 , bail out */ - if (pin_number >= 32) { + if (pin_number >= 32) return -EINVAL; - } - if (pin_value == 0) { /* input */ + /* input */ + if (pin_value == 0) value = dev->gpio_dir & (~(1 << pin_number)); /* clear */ - } else { + else value = dev->gpio_dir | (1 << pin_number); - } - status = cx231xx_set_gpio_bit(dev, value, (u8 *) & dev->gpio_val); + status = cx231xx_set_gpio_bit(dev, value, (u8 *) &dev->gpio_val); /* cache the value for future */ dev->gpio_dir = value; @@ -2664,31 +2371,28 @@ int cx231xx_set_gpio_value(struct cx231xx *dev, int pin_number, int pin_value) /* It was in input mode */ value = dev->gpio_dir | (1 << pin_number); dev->gpio_dir = value; - status = - cx231xx_set_gpio_bit(dev, dev->gpio_dir, - (u8 *) & dev->gpio_val); + status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, + (u8 *) &dev->gpio_val); value = 0; } - if (pin_value == 0) { + if (pin_value == 0) value = dev->gpio_val & (~(1 << pin_number)); - } else { + else value = dev->gpio_val | (1 << pin_number); - } /* store the value */ dev->gpio_val = value; /* toggle bit0 of GP_IO */ - status = - cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8 *) & dev->gpio_val); + status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8 *)&dev->gpio_val); return status; } -/************************************************************************************ -* G P I O I2C related functions * -*************************************************************************************/ +/***************************************************************************** +* G P I O I2C related functions * +******************************************************************************/ int cx231xx_gpio_i2c_start(struct cx231xx *dev) { int status = 0; @@ -2699,31 +2403,25 @@ int cx231xx_gpio_i2c_start(struct cx231xx *dev) dev->gpio_val |= 1 << dev->board.tuner_scl_gpio; dev->gpio_val |= 1 << dev->board.tuner_sda_gpio; - status = - cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8 *) & dev->gpio_val); - if (status < 0) { + status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8 *)&dev->gpio_val); + if (status < 0) return -EINVAL; - } /* set SCL to output 1; set SDA to output 0 */ dev->gpio_val |= 1 << dev->board.tuner_scl_gpio; dev->gpio_val &= ~(1 << dev->board.tuner_sda_gpio); - status = - cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8 *) & dev->gpio_val); - if (status < 0) { + status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8 *)&dev->gpio_val); + if (status < 0) return -EINVAL; - } /* set SCL to output 0; set SDA to output 0 */ dev->gpio_val &= ~(1 << dev->board.tuner_scl_gpio); dev->gpio_val &= ~(1 << dev->board.tuner_sda_gpio); - status = - cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8 *) & dev->gpio_val); - if (status < 0) { + status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8 *)&dev->gpio_val); + if (status < 0) return -EINVAL; - } return status; } @@ -2739,21 +2437,17 @@ int cx231xx_gpio_i2c_end(struct cx231xx *dev) dev->gpio_val &= ~(1 << dev->board.tuner_scl_gpio); dev->gpio_val &= ~(1 << dev->board.tuner_sda_gpio); - status = - cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8 *) & dev->gpio_val); - if (status < 0) { + status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8 *)&dev->gpio_val); + if (status < 0) return -EINVAL; - } /* set SCL to output 1; set SDA to output 0 */ dev->gpio_val |= 1 << dev->board.tuner_scl_gpio; dev->gpio_val &= ~(1 << dev->board.tuner_sda_gpio); - status = - cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8 *) & dev->gpio_val); - if (status < 0) { + status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8 *)&dev->gpio_val); + if (status < 0) return -EINVAL; - } /* set SCL to input ,release SCL cable control set SDA to input ,release SDA cable control */ @@ -2761,10 +2455,10 @@ int cx231xx_gpio_i2c_end(struct cx231xx *dev) dev->gpio_dir &= ~(1 << dev->board.tuner_sda_gpio); status = - cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8 *) & dev->gpio_val); - if (status < 0) { + cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8 *)&dev->gpio_val); + if (status < 0) return -EINVAL; - } + return status; } @@ -2782,40 +2476,34 @@ int cx231xx_gpio_i2c_write_byte(struct cx231xx *dev, u8 data) /* set SCL to output 0; set SDA to output 0 */ dev->gpio_val &= ~(1 << dev->board.tuner_scl_gpio); dev->gpio_val &= ~(1 << dev->board.tuner_sda_gpio); - status = - cx231xx_set_gpio_bit(dev, dev->gpio_dir, - (u8 *) & dev->gpio_val); + status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, + (u8 *)&dev->gpio_val); /* set SCL to output 1; set SDA to output 0 */ dev->gpio_val |= 1 << dev->board.tuner_scl_gpio; - status = - cx231xx_set_gpio_bit(dev, dev->gpio_dir, - (u8 *) & dev->gpio_val); + status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, + (u8 *)&dev->gpio_val); /* set SCL to output 0; set SDA to output 0 */ dev->gpio_val &= ~(1 << dev->board.tuner_scl_gpio); - status = - cx231xx_set_gpio_bit(dev, dev->gpio_dir, - (u8 *) & dev->gpio_val); + status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, + (u8 *)&dev->gpio_val); } else { /* set SCL to output 0; set SDA to output 1 */ dev->gpio_val &= ~(1 << dev->board.tuner_scl_gpio); dev->gpio_val |= 1 << dev->board.tuner_sda_gpio; - status = - cx231xx_set_gpio_bit(dev, dev->gpio_dir, - (u8 *) & dev->gpio_val); + status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, + (u8 *)&dev->gpio_val); /* set SCL to output 1; set SDA to output 1 */ dev->gpio_val |= 1 << dev->board.tuner_scl_gpio; - status = - cx231xx_set_gpio_bit(dev, dev->gpio_dir, - (u8 *) & dev->gpio_val); + status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, + (u8 *)&dev->gpio_val); /* set SCL to output 0; set SDA to output 1 */ dev->gpio_val &= ~(1 << dev->board.tuner_scl_gpio); - status = - cx231xx_set_gpio_bit(dev, dev->gpio_dir, - (u8 *) & dev->gpio_val); + status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, + (u8 *)&dev->gpio_val); } } return status; @@ -2833,33 +2521,29 @@ int cx231xx_gpio_i2c_read_byte(struct cx231xx *dev, u8 * buf) /* set SCL to output 0; set SDA to input */ dev->gpio_val &= ~(1 << dev->board.tuner_scl_gpio); - status = - cx231xx_set_gpio_bit(dev, dev->gpio_dir, - (u8 *) & dev->gpio_val); + status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, + (u8 *)&dev->gpio_val); /* set SCL to output 1; set SDA to input */ dev->gpio_val |= 1 << dev->board.tuner_scl_gpio; - status = - cx231xx_set_gpio_bit(dev, dev->gpio_dir, - (u8 *) & dev->gpio_val); + status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, + (u8 *)&dev->gpio_val); /* get SDA data bit */ gpio_logic_value = dev->gpio_val; - status = - cx231xx_get_gpio_bit(dev, dev->gpio_dir, - (u8 *) & dev->gpio_val); - if ((dev->gpio_val & (1 << dev->board.tuner_sda_gpio)) != 0) { + status = cx231xx_get_gpio_bit(dev, dev->gpio_dir, + (u8 *)&dev->gpio_val); + if ((dev->gpio_val & (1 << dev->board.tuner_sda_gpio)) != 0) value |= (1 << (8 - i - 1)); - } dev->gpio_val = gpio_logic_value; } /* set SCL to output 0,finish the read latest SCL signal. - !!!set SDA to input,never to modify SDA direction at the same times */ + !!!set SDA to input, never to modify SDA direction at + the same times */ dev->gpio_val &= ~(1 << dev->board.tuner_scl_gpio); - status = - cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8 *) & dev->gpio_val); + status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8 *)&dev->gpio_val); /* store the value */ *buf = value & 0xff; @@ -2874,33 +2558,29 @@ int cx231xx_gpio_i2c_read_ack(struct cx231xx *dev) int nCnt = 10; int nInit = nCnt; - /* clock stretch; set SCL to input; set SDA to input; get SCL value till SCL = 1 */ + /* clock stretch; set SCL to input; set SDA to input; + get SCL value till SCL = 1 */ dev->gpio_dir &= ~(1 << dev->board.tuner_sda_gpio); dev->gpio_dir &= ~(1 << dev->board.tuner_scl_gpio); gpio_logic_value = dev->gpio_val; - status = - cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8 *) & dev->gpio_val); + status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8 *)&dev->gpio_val); do { msleep(2); - status = - cx231xx_get_gpio_bit(dev, dev->gpio_dir, - (u8 *) & dev->gpio_val); + status = cx231xx_get_gpio_bit(dev, dev->gpio_dir, + (u8 *)&dev->gpio_val); nCnt--; - } while (((dev->gpio_val & (1 << dev->board.tuner_scl_gpio)) == 0) - && (nCnt > 0)); + } while (((dev->gpio_val & (1 << dev->board.tuner_scl_gpio)) == 0) && (nCnt > 0)); - if (nCnt == 0) { - cx231xx_info - ("No ACK after %d msec for clock stretch. GPIO I2C operation failed!", - nInit * 10); - } + if (nCnt == 0) + cx231xx_info("No ACK after %d msec for clock stretch. GPIO I2C operation failed!", + nInit * 10); /* readAck - throuth clock stretch ,slave has given a SCL signal,so the SDA data can be directly read. */ - status = - cx231xx_get_gpio_bit(dev, dev->gpio_dir, (u8 *) & dev->gpio_val); + throuth clock stretch ,slave has given a SCL signal, + so the SDA data can be directly read. */ + status = cx231xx_get_gpio_bit(dev, dev->gpio_dir, (u8 *)&dev->gpio_val); if ((dev->gpio_val & 1 << dev->board.tuner_sda_gpio) == 0) { dev->gpio_val = gpio_logic_value; @@ -2911,12 +2591,12 @@ int cx231xx_gpio_i2c_read_ack(struct cx231xx *dev) dev->gpio_val |= (1 << dev->board.tuner_sda_gpio); } - /* read SDA end, set the SCL to output 0, after this operation, SDA direction can be changed. */ + /* read SDA end, set the SCL to output 0, after this operation, + SDA direction can be changed. */ dev->gpio_val = gpio_logic_value; dev->gpio_dir |= (1 << dev->board.tuner_scl_gpio); dev->gpio_val &= ~(1 << dev->board.tuner_scl_gpio); - status = - cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8 *) & dev->gpio_val); + status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8 *)&dev->gpio_val); return status; } @@ -2927,29 +2607,24 @@ int cx231xx_gpio_i2c_write_ack(struct cx231xx *dev) /* set SDA to ouput */ dev->gpio_dir |= 1 << dev->board.tuner_sda_gpio; - status = - cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8 *) & dev->gpio_val); + status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8 *)&dev->gpio_val); /* set SCL = 0 (output); set SDA = 0 (output) */ dev->gpio_val &= ~(1 << dev->board.tuner_sda_gpio); dev->gpio_val &= ~(1 << dev->board.tuner_scl_gpio); - status = - cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8 *) & dev->gpio_val); + status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8 *)&dev->gpio_val); /* set SCL = 1 (output); set SDA = 0 (output) */ dev->gpio_val |= 1 << dev->board.tuner_scl_gpio; - status = - cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8 *) & dev->gpio_val); + status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8 *)&dev->gpio_val); /* set SCL = 0 (output); set SDA = 0 (output) */ dev->gpio_val &= ~(1 << dev->board.tuner_scl_gpio); - status = - cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8 *) & dev->gpio_val); + status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8 *)&dev->gpio_val); /* set SDA to input,and then the slave will read data from SDA. */ dev->gpio_dir &= ~(1 << dev->board.tuner_sda_gpio); - status = - cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8 *) & dev->gpio_val); + status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8 *)&dev->gpio_val); return status; } @@ -2961,25 +2636,22 @@ int cx231xx_gpio_i2c_write_nak(struct cx231xx *dev) /* set scl to output ; set sda to input */ dev->gpio_dir |= 1 << dev->board.tuner_scl_gpio; dev->gpio_dir &= ~(1 << dev->board.tuner_sda_gpio); - status = - cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8 *) & dev->gpio_val); + status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8 *)&dev->gpio_val); /* set scl to output 0; set sda to input */ dev->gpio_val &= ~(1 << dev->board.tuner_scl_gpio); - status = - cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8 *) & dev->gpio_val); + status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8 *)&dev->gpio_val); /* set scl to output 1; set sda to input */ dev->gpio_val |= 1 << dev->board.tuner_scl_gpio; - status = - cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8 *) & dev->gpio_val); + status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8 *)&dev->gpio_val); return status; } -/************************************************************************************ -* G P I O I2C related functions * -*************************************************************************************/ +/***************************************************************************** +* G P I O I2C related functions * +******************************************************************************/ /* cx231xx_gpio_i2c_read * Function to read data from gpio based I2C interface */ diff --git a/linux/drivers/media/video/cx231xx/cx231xx-vbi.c b/linux/drivers/media/video/cx231xx/cx231xx-vbi.c index a6e9add83..de78ce140 100644 --- a/linux/drivers/media/video/cx231xx/cx231xx-vbi.c +++ b/linux/drivers/media/video/cx231xx/cx231xx-vbi.c @@ -109,27 +109,29 @@ static inline int cx231xx_isoc_vbi_copy(struct cx231xx *dev, struct urb *urb) buffer_size = urb->actual_length; if (buffer_size > 0) { - bytes_parsed = 0; if (dma_q->is_partial_line) { - /* Handle the case where we were working on a partial line */ + /* Handle the case where we were working on a partial + line */ sav_eav = dma_q->last_sav; } else { - /* Check for a SAV/EAV overlapping the buffer boundary */ - sav_eav = - cx231xx_find_boundary_SAV_EAV(p_buffer, + /* Check for a SAV/EAV overlapping the + buffer boundary */ + + sav_eav = cx231xx_find_boundary_SAV_EAV(p_buffer, dma_q->partial_buf, &bytes_parsed); } sav_eav &= 0xF0; - /* Get the first line if we have some portion of an SAV/EAV from the last buffer - or a partial line */ + /* Get the first line if we have some portion of an SAV/EAV from + the last buffer or a partial line */ if (sav_eav) { - bytes_parsed += cx231xx_get_vbi_line(dev, dma_q, sav_eav, /* SAV/EAV */ - p_buffer + bytes_parsed, /* p_buffer */ - buffer_size - bytes_parsed); /* buffer size */ + bytes_parsed += cx231xx_get_vbi_line(dev, dma_q, + sav_eav, /* SAV/EAV */ + p_buffer + bytes_parsed, /* p_buffer */ + buffer_size - bytes_parsed); /* buffer size */ } /* Now parse data that is completely in this buffer */ @@ -139,16 +141,17 @@ static inline int cx231xx_isoc_vbi_copy(struct cx231xx *dev, struct urb *urb) u32 bytes_used = 0; sav_eav = cx231xx_find_next_SAV_EAV(p_buffer + bytes_parsed, /* p_buffer */ - buffer_size - bytes_parsed, /* buffer size */ - &bytes_used); /* Receives bytes used to get SAV/EAV */ + buffer_size - bytes_parsed, /* buffer size */ + &bytes_used); /* Receives bytes used to get SAV/EAV */ bytes_parsed += bytes_used; sav_eav &= 0xF0; if (sav_eav && (bytes_parsed < buffer_size)) { - bytes_parsed += cx231xx_get_vbi_line(dev, dma_q, sav_eav, /* SAV/EAV */ - p_buffer + bytes_parsed, /* p_buffer */ - buffer_size - bytes_parsed); /* buffer size */ + bytes_parsed += cx231xx_get_vbi_line(dev, + dma_q, sav_eav, /* SAV/EAV */ + p_buffer + bytes_parsed, /* p_buffer */ + buffer_size - bytes_parsed); /* buffer size */ } } @@ -261,7 +264,7 @@ vbi_buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb, buf->vb.state = VIDEOBUF_PREPARED; return 0; - fail: +fail: free_buffer(vq, buf); return rc; } @@ -285,20 +288,21 @@ static void vbi_buffer_release(struct videobuf_queue *vq, { struct cx231xx_buffer *buf = container_of(vb, struct cx231xx_buffer, vb); - /* + +#if 0 struct cx231xx_fh *fh = vq->priv_data; struct cx231xx *dev = (struct cx231xx *)fh->dev; cx231xx_info(DRIVER_NAME "cx231xx: called vbi_buffer_release\n"); - */ +#endif free_buffer(vq, buf); } struct videobuf_queue_ops cx231xx_vbi_qops = { - .buf_setup = vbi_buffer_setup, + .buf_setup = vbi_buffer_setup, .buf_prepare = vbi_buffer_prepare, - .buf_queue = vbi_buffer_queue, + .buf_queue = vbi_buffer_queue, .buf_release = vbi_buffer_release, }; @@ -391,7 +395,6 @@ void cx231xx_uninit_vbi_isoc(struct cx231xx *dev) cx231xx_capture_start(dev, 0, Vbi); } - EXPORT_SYMBOL_GPL(cx231xx_uninit_vbi_isoc); /* @@ -399,8 +402,8 @@ EXPORT_SYMBOL_GPL(cx231xx_uninit_vbi_isoc); */ int cx231xx_init_vbi_isoc(struct cx231xx *dev, int max_packets, int num_bufs, int max_pkt_size, - int (*isoc_copy) (struct cx231xx * dev, - struct urb * urb)) + int (*isoc_copy) (struct cx231xx *dev, + struct urb *urb)) { struct cx231xx_dmaqueue *dma_q = &dev->vbi_mode.vidq; int i; @@ -431,8 +434,8 @@ int cx231xx_init_vbi_isoc(struct cx231xx *dev, int max_packets, for (i = 0; i < 8; i++) dma_q->partial_buf[i] = 0; - dev->vbi_mode.isoc_ctl.urb = - kzalloc(sizeof(void *) * num_bufs, GFP_KERNEL); + dev->vbi_mode.isoc_ctl.urb = kzalloc(sizeof(void *) * num_bufs, + GFP_KERNEL); if (!dev->vbi_mode.isoc_ctl.urb) { cx231xx_errdev("cannot alloc memory for usb buffers\n"); return -ENOMEM; @@ -470,7 +473,7 @@ int cx231xx_init_vbi_isoc(struct cx231xx *dev, int max_packets, cx231xx_err(DRIVER_NAME ": unable to allocate %i bytes for transfer" " buffer %i%s\n", sb_size, i, - in_interrupt()? " while in int" : ""); + in_interrupt() ? " while in int" : ""); cx231xx_uninit_vbi_isoc(dev); return -ENOMEM; } @@ -499,11 +502,10 @@ int cx231xx_init_vbi_isoc(struct cx231xx *dev, int max_packets, return 0; } - EXPORT_SYMBOL_GPL(cx231xx_init_vbi_isoc); -u32 cx231xx_get_vbi_line(struct cx231xx * dev, struct cx231xx_dmaqueue * dma_q, - u8 sav_eav, u8 * p_buffer, u32 buffer_size) +u32 cx231xx_get_vbi_line(struct cx231xx *dev, struct cx231xx_dmaqueue *dma_q, + u8 sav_eav, u8 *p_buffer, u32 buffer_size) { u32 bytes_copied = 0; int current_field = -1; @@ -554,15 +556,14 @@ static inline void vbi_buffer_filled(struct cx231xx *dev, } u32 cx231xx_copy_vbi_line(struct cx231xx *dev, struct cx231xx_dmaqueue *dma_q, - u8 * p_line, u32 length, int field_number) + u8 *p_line, u32 length, int field_number) { u32 bytes_to_copy; struct cx231xx_buffer *buf; u32 _line_size = dev->width * 2; - if (dma_q->current_field != field_number) { + if (dma_q->current_field != field_number) cx231xx_reset_vbi_buffer(dev, dma_q); - } /* get the buffer pointer */ buf = dev->vbi_mode.isoc_ctl.buf; @@ -655,7 +656,6 @@ void cx231xx_reset_vbi_buffer(struct cx231xx *dev, buf = dev->vbi_mode.isoc_ctl.buf; if (buf == NULL) { - /* first try to get the buffer */ get_next_vbi_buf(dma_q, &buf); @@ -668,7 +668,7 @@ void cx231xx_reset_vbi_buffer(struct cx231xx *dev, } int cx231xx_do_vbi_copy(struct cx231xx *dev, struct cx231xx_dmaqueue *dma_q, - u8 * p_buffer, u32 bytes_to_copy) + u8 *p_buffer, u32 bytes_to_copy) { u8 *p_out_buffer = NULL; u32 current_line_bytes_copied = 0; @@ -679,9 +679,8 @@ int cx231xx_do_vbi_copy(struct cx231xx *dev, struct cx231xx_dmaqueue *dma_q, buf = dev->vbi_mode.isoc_ctl.buf; - if (buf == NULL) { - return -1; - } + if (buf == NULL) + return -EINVAL; p_out_buffer = videobuf_to_vmalloc(&buf->vb); @@ -690,23 +689,22 @@ int cx231xx_do_vbi_copy(struct cx231xx *dev, struct cx231xx_dmaqueue *dma_q, _line_size - dma_q->bytes_left_in_line; } - offset = - (dma_q->lines_completed * _line_size) + current_line_bytes_copied; + offset = (dma_q->lines_completed * _line_size) + + current_line_bytes_copied; /* prepare destination address */ startwrite = p_out_buffer + offset; - lencopy = - dma_q->bytes_left_in_line > - bytes_to_copy ? bytes_to_copy : dma_q->bytes_left_in_line; + lencopy = dma_q->bytes_left_in_line > bytes_to_copy ? + bytes_to_copy : dma_q->bytes_left_in_line; memcpy(startwrite, p_buffer, lencopy); return 0; } -u8 cx231xx_is_vbi_buffer_done(struct cx231xx * dev, - struct cx231xx_dmaqueue * dma_q) +u8 cx231xx_is_vbi_buffer_done(struct cx231xx *dev, + struct cx231xx_dmaqueue *dma_q) { u32 height = 0; diff --git a/linux/drivers/media/video/cx231xx/cx231xx-video.c b/linux/drivers/media/video/cx231xx/cx231xx-video.c index 4e0850e1c..025569d81 100644 --- a/linux/drivers/media/video/cx231xx/cx231xx-video.c +++ b/linux/drivers/media/video/cx231xx/cx231xx-video.c @@ -1,5 +1,6 @@ /* - cx231xx-video.c - driver for Conexant Cx23100/101/102 USB video capture devices + cx231xx-video.c - driver for Conexant Cx23100/101/102 + USB video capture devices Copyright (C) 2008 Based on em28xx driver @@ -109,91 +110,91 @@ static const struct v4l2_queryctrl no_ctl = { static struct cx231xx_ctrl cx231xx_ctls[] = { /* --- video --- */ { - .v = { - .id = V4L2_CID_BRIGHTNESS, - .name = "Brightness", - .minimum = 0x00, - .maximum = 0xff, - .step = 1, - .default_value = 0x7f, - .type = V4L2_CTRL_TYPE_INTEGER, - }, - .off = 128, - .reg = LUMA_CTRL, - .mask = 0x00ff, - .shift = 0, - }, { - .v = { - .id = V4L2_CID_CONTRAST, - .name = "Contrast", - .minimum = 0, - .maximum = 0xff, - .step = 1, - .default_value = 0x3f, - .type = V4L2_CTRL_TYPE_INTEGER, - }, - .off = 0, - .reg = LUMA_CTRL, - .mask = 0xff00, - .shift = 8, - }, { - .v = { - .id = V4L2_CID_HUE, - .name = "Hue", - .minimum = 0, - .maximum = 0xff, - .step = 1, - .default_value = 0x7f, - .type = V4L2_CTRL_TYPE_INTEGER, - }, - .off = 128, - .reg = CHROMA_CTRL, - .mask = 0xff0000, - .shift = 16, - }, { - /* strictly, this only describes only U saturation. - * V saturation is handled specially through code. - */ - .v = { - .id = V4L2_CID_SATURATION, - .name = "Saturation", - .minimum = 0, - .maximum = 0xff, - .step = 1, - .default_value = 0x7f, - .type = V4L2_CTRL_TYPE_INTEGER, - }, - .off = 0, - .reg = CHROMA_CTRL, - .mask = 0x00ff, - .shift = 0, - }, { - /* --- audio --- */ - .v = { - .id = V4L2_CID_AUDIO_MUTE, - .name = "Mute", - .minimum = 0, - .maximum = 1, - .default_value = 1, - .type = V4L2_CTRL_TYPE_BOOLEAN, - }, - .reg = PATH1_CTL1, - .mask = (0x1f << 24), - .shift = 24, - }, { - .v = { - .id = V4L2_CID_AUDIO_VOLUME, - .name = "Volume", - .minimum = 0, - .maximum = 0x3f, - .step = 1, - .default_value = 0x3f, - .type = V4L2_CTRL_TYPE_INTEGER, - }, - .reg = PATH1_VOL_CTL, - .mask = 0xff, - .shift = 0, - } + .v = { + .id = V4L2_CID_BRIGHTNESS, + .name = "Brightness", + .minimum = 0x00, + .maximum = 0xff, + .step = 1, + .default_value = 0x7f, + .type = V4L2_CTRL_TYPE_INTEGER, + }, + .off = 128, + .reg = LUMA_CTRL, + .mask = 0x00ff, + .shift = 0, + }, { + .v = { + .id = V4L2_CID_CONTRAST, + .name = "Contrast", + .minimum = 0, + .maximum = 0xff, + .step = 1, + .default_value = 0x3f, + .type = V4L2_CTRL_TYPE_INTEGER, + }, + .off = 0, + .reg = LUMA_CTRL, + .mask = 0xff00, + .shift = 8, + }, { + .v = { + .id = V4L2_CID_HUE, + .name = "Hue", + .minimum = 0, + .maximum = 0xff, + .step = 1, + .default_value = 0x7f, + .type = V4L2_CTRL_TYPE_INTEGER, + }, + .off = 128, + .reg = CHROMA_CTRL, + .mask = 0xff0000, + .shift = 16, + }, { + /* strictly, this only describes only U saturation. + * V saturation is handled specially through code. + */ + .v = { + .id = V4L2_CID_SATURATION, + .name = "Saturation", + .minimum = 0, + .maximum = 0xff, + .step = 1, + .default_value = 0x7f, + .type = V4L2_CTRL_TYPE_INTEGER, + }, + .off = 0, + .reg = CHROMA_CTRL, + .mask = 0x00ff, + .shift = 0, + }, { + /* --- audio --- */ + .v = { + .id = V4L2_CID_AUDIO_MUTE, + .name = "Mute", + .minimum = 0, + .maximum = 1, + .default_value = 1, + .type = V4L2_CTRL_TYPE_BOOLEAN, + }, + .reg = PATH1_CTL1, + .mask = (0x1f << 24), + .shift = 24, + }, { + .v = { + .id = V4L2_CID_AUDIO_VOLUME, + .name = "Volume", + .minimum = 0, + .maximum = 0x3f, + .step = 1, + .default_value = 0x3f, + .type = V4L2_CTRL_TYPE_INTEGER, + }, + .reg = PATH1_VOL_CTL, + .mask = 0xff, + .shift = 0, + } }; static const int CX231XX_CTLS = ARRAY_SIZE(cx231xx_ctls); @@ -373,12 +374,13 @@ static inline int cx231xx_isoc_copy(struct cx231xx *dev, struct urb *urb) } sav_eav &= 0xF0; - /* Get the first line if we have some portion of an SAV/EAV from the last buffer - or a partial line */ + /* Get the first line if we have some portion of an SAV/EAV from + the last buffer or a partial line */ if (sav_eav) { - bytes_parsed += cx231xx_get_video_line(dev, dma_q, sav_eav, /* SAV/EAV */ - p_buffer + bytes_parsed, /* p_buffer */ - buffer_size - bytes_parsed); /* buffer size */ + bytes_parsed += cx231xx_get_video_line(dev, dma_q, + sav_eav, /* SAV/EAV */ + p_buffer + bytes_parsed, /* p_buffer */ + buffer_size - bytes_parsed); /* buffer size */ } /* Now parse data that is completely in this buffer */ @@ -388,21 +390,22 @@ static inline int cx231xx_isoc_copy(struct cx231xx *dev, struct urb *urb) u32 bytes_used = 0; sav_eav = cx231xx_find_next_SAV_EAV(p_buffer + bytes_parsed, /* p_buffer */ - buffer_size - bytes_parsed, /* buffer size */ - &bytes_used); /* Receives bytes used to get SAV/EAV */ + buffer_size - bytes_parsed, /* buffer size */ + &bytes_used); /* Receives bytes used to get SAV/EAV */ bytes_parsed += bytes_used; sav_eav &= 0xF0; if (sav_eav && (bytes_parsed < buffer_size)) { - bytes_parsed += cx231xx_get_video_line(dev, dma_q, sav_eav, /* SAV/EAV */ - p_buffer + bytes_parsed, /* p_buffer */ - buffer_size - bytes_parsed); /* buffer size */ + bytes_parsed += cx231xx_get_video_line(dev, + dma_q, sav_eav, /* SAV/EAV */ + p_buffer + bytes_parsed, /* p_buffer */ + buffer_size - bytes_parsed); /* buffer size */ } } - /* Save the last four bytes of the buffer so we can check the buffer boundary - condition next time */ + /* Save the last four bytes of the buffer so we can check the + buffer boundary condition next time */ memcpy(dma_q->partial_buf, p_buffer + buffer_size - 4, 4); bytes_parsed = 0; @@ -410,8 +413,8 @@ static inline int cx231xx_isoc_copy(struct cx231xx *dev, struct urb *urb) return rc; } -u8 cx231xx_find_boundary_SAV_EAV(u8 * p_buffer, u8 * partial_buf, - u32 * p_bytes_used) +u8 cx231xx_find_boundary_SAV_EAV(u8 *p_buffer, u8 *partial_buf, + u32 *p_bytes_used) { u32 bytes_used; u8 boundary_bytes[8]; @@ -426,8 +429,8 @@ u8 cx231xx_find_boundary_SAV_EAV(u8 * p_buffer, u8 * partial_buf, memcpy(boundary_bytes + 4, p_buffer, 4); /* Check for the SAV/EAV in the boundary buffer */ - sav_eav = - cx231xx_find_next_SAV_EAV((u8 *) & boundary_bytes, 8, &bytes_used); + sav_eav = cx231xx_find_next_SAV_EAV((u8 *)&boundary_bytes, 8, + &bytes_used); if (sav_eav) { /* found a boundary SAV/EAV. Updates the bytes used to reflect @@ -438,13 +441,16 @@ u8 cx231xx_find_boundary_SAV_EAV(u8 * p_buffer, u8 * partial_buf, return sav_eav; } -u8 cx231xx_find_next_SAV_EAV(u8 * p_buffer, u32 buffer_size, u32 * p_bytes_used) +u8 cx231xx_find_next_SAV_EAV(u8 *p_buffer, u32 buffer_size, u32 *p_bytes_used) { u32 i; u8 sav_eav = 0; - /* Don't search if the buffer size is less than 4. It causes a page fault since - buffer_size - 4 evaluates to a large number in that case. */ + /* + * Don't search if the buffer size is less than 4. It causes a page + * fault since buffer_size - 4 evaluates to a large number in that + * case. + */ if (buffer_size < 4) { *p_bytes_used = buffer_size; return 0; @@ -465,69 +471,61 @@ u8 cx231xx_find_next_SAV_EAV(u8 * p_buffer, u32 buffer_size, u32 * p_bytes_used) return 0; } -u32 cx231xx_get_video_line(struct cx231xx * dev, - struct cx231xx_dmaqueue * dma_q, u8 sav_eav, - u8 * p_buffer, u32 buffer_size) +u32 cx231xx_get_video_line(struct cx231xx *dev, + struct cx231xx_dmaqueue *dma_q, u8 sav_eav, + u8 *p_buffer, u32 buffer_size) { u32 bytes_copied = 0; int current_field = -1; switch (sav_eav) { case SAV_ACTIVE_VIDEO_FIELD1: - /* looking for skipped line which occurred in PAL 720x480 mode. In this case, - there will be no active data contained between the SAV and EAV */ - if ((buffer_size > 3) && - (p_buffer[0] == 0xFF) && (p_buffer[1] == 0x00) - && (p_buffer[2] == 0x00) - && ((p_buffer[3] == EAV_ACTIVE_VIDEO_FIELD1) - || (p_buffer[3] == EAV_ACTIVE_VIDEO_FIELD2) - || (p_buffer[3] == EAV_VBLANK_FIELD1) - || (p_buffer[3] == EAV_VBLANK_FIELD2) - ) - ) { + /* looking for skipped line which occurred in PAL 720x480 mode. + In this case, there will be no active data contained + between the SAV and EAV */ + if ((buffer_size > 3) && (p_buffer[0] == 0xFF) && + (p_buffer[1] == 0x00) && (p_buffer[2] == 0x00) && + ((p_buffer[3] == EAV_ACTIVE_VIDEO_FIELD1) || + (p_buffer[3] == EAV_ACTIVE_VIDEO_FIELD2) || + (p_buffer[3] == EAV_VBLANK_FIELD1) || + (p_buffer[3] == EAV_VBLANK_FIELD2))) return bytes_copied; - } current_field = 1; break; case SAV_ACTIVE_VIDEO_FIELD2: - /* looking for skipped line which occurred in PAL 720x480 mode. In this case, - there will be no active data contained between the SAV and EAV */ - if ((buffer_size > 3) && - (p_buffer[0] == 0xFF) && (p_buffer[1] == 0x00) - && (p_buffer[2] == 0x00) - && ((p_buffer[3] == EAV_ACTIVE_VIDEO_FIELD1) - || (p_buffer[3] == EAV_ACTIVE_VIDEO_FIELD2) - || (p_buffer[3] == EAV_VBLANK_FIELD1) - || (p_buffer[3] == EAV_VBLANK_FIELD2) - ) - ) { + /* looking for skipped line which occurred in PAL 720x480 mode. + In this case, there will be no active data contained between + the SAV and EAV */ + if ((buffer_size > 3) && (p_buffer[0] == 0xFF) && + (p_buffer[1] == 0x00) && (p_buffer[2] == 0x00) && + ((p_buffer[3] == EAV_ACTIVE_VIDEO_FIELD1) || + (p_buffer[3] == EAV_ACTIVE_VIDEO_FIELD2) || + (p_buffer[3] == EAV_VBLANK_FIELD1) || + (p_buffer[3] == EAV_VBLANK_FIELD2))) return bytes_copied; - } current_field = 2; break; } dma_q->last_sav = sav_eav; - bytes_copied = - cx231xx_copy_video_line(dev, dma_q, p_buffer, buffer_size, - current_field); + bytes_copied = cx231xx_copy_video_line(dev, dma_q, p_buffer, + buffer_size, current_field); return bytes_copied; } -u32 cx231xx_copy_video_line(struct cx231xx * dev, - struct cx231xx_dmaqueue * dma_q, u8 * p_line, +u32 cx231xx_copy_video_line(struct cx231xx *dev, + struct cx231xx_dmaqueue *dma_q, u8 *p_line, u32 length, int field_number) { u32 bytes_to_copy; struct cx231xx_buffer *buf; u32 _line_size = dev->width * 2; - if (dma_q->current_field != field_number) { + if (dma_q->current_field != field_number) cx231xx_reset_video_buffer(dev, dma_q); - } /* get the buffer pointer */ buf = dev->video_mode.isoc_ctl.buf; @@ -541,8 +539,8 @@ u32 cx231xx_copy_video_line(struct cx231xx * dev, if (dma_q->lines_completed >= dma_q->lines_per_field) { dma_q->bytes_left_in_line -= bytes_to_copy; - dma_q->is_partial_line = - (dma_q->bytes_left_in_line == 0) ? 0 : 1; + dma_q->is_partial_line = (dma_q->bytes_left_in_line == 0) ? + 0 : 1; return 0; } @@ -552,8 +550,8 @@ u32 cx231xx_copy_video_line(struct cx231xx * dev, have copied if we had a buffer. */ if (!buf) { dma_q->bytes_left_in_line -= bytes_to_copy; - dma_q->is_partial_line = - (dma_q->bytes_left_in_line == 0) ? 0 : 1; + dma_q->is_partial_line = (dma_q->bytes_left_in_line == 0) + ? 0 : 1; return bytes_to_copy; } @@ -564,13 +562,11 @@ u32 cx231xx_copy_video_line(struct cx231xx * dev, dma_q->bytes_left_in_line -= bytes_to_copy; if (dma_q->bytes_left_in_line == 0) { - dma_q->bytes_left_in_line = _line_size; dma_q->lines_completed++; dma_q->is_partial_line = 0; if (cx231xx_is_buffer_done(dev, dma_q) && buf) { - buffer_filled(dev, dma_q, buf); dma_q->pos = 0; @@ -589,11 +585,10 @@ void cx231xx_reset_video_buffer(struct cx231xx *dev, /* handle the switch from field 1 to field 2 */ if (dma_q->current_field == 1) { - if (dma_q->lines_completed >= dma_q->lines_per_field) { + if (dma_q->lines_completed >= dma_q->lines_per_field) dma_q->field1_done = 1; - } else { + else dma_q->field1_done = 0; - } } buf = dev->video_mode.isoc_ctl.buf; @@ -617,7 +612,7 @@ void cx231xx_reset_video_buffer(struct cx231xx *dev, } int cx231xx_do_copy(struct cx231xx *dev, struct cx231xx_dmaqueue *dma_q, - u8 * p_buffer, u32 bytes_to_copy) + u8 *p_buffer, u32 bytes_to_copy) { u8 *p_out_buffer = NULL; u32 current_line_bytes_copied = 0; @@ -647,14 +642,11 @@ int cx231xx_do_copy(struct cx231xx *dev, struct cx231xx_dmaqueue *dma_q, /* bytes already completed in the current line */ startwrite += current_line_bytes_copied; - lencopy = - dma_q->bytes_left_in_line > - bytes_to_copy ? bytes_to_copy : dma_q->bytes_left_in_line; + lencopy = dma_q->bytes_left_in_line > bytes_to_copy ? + bytes_to_copy : dma_q->bytes_left_in_line; - if ((u8 *) (startwrite + lencopy) > - (u8 *) (p_out_buffer + buf->vb.size)) { + if ((u8 *)(startwrite + lencopy) > (u8 *)(p_out_buffer + buf->vb.size)) return 0; - } /* The below copies the UYVY data straight into video buffer */ cx231xx_swab((u16 *) p_buffer, (u16 *) startwrite, (u16) lencopy); @@ -662,16 +654,15 @@ int cx231xx_do_copy(struct cx231xx *dev, struct cx231xx_dmaqueue *dma_q, return 0; } -void cx231xx_swab(u16 * from, u16 * to, u16 len) +void cx231xx_swab(u16 *from, u16 *to, u16 len) { u16 i; if (len <= 0) return; - for (i = 0; i < len / 2; i++) { + for (i = 0; i < len / 2; i++) to[i] = (from[i] << 8) | (from[i] >> 8); - } } u8 cx231xx_is_buffer_done(struct cx231xx *dev, struct cx231xx_dmaqueue *dma_q) @@ -679,10 +670,9 @@ u8 cx231xx_is_buffer_done(struct cx231xx *dev, struct cx231xx_dmaqueue *dma_q) u8 buffer_complete = 0; /* Dual field stream */ - buffer_complete = - ((dma_q->current_field == 2) && - (dma_q->lines_completed >= dma_q->lines_per_field) && - dma_q->field1_done); + buffer_complete = ((dma_q->current_field == 2) && + (dma_q->lines_completed >= dma_q->lines_per_field) && + dma_q->field1_done); return buffer_complete; } @@ -698,8 +688,7 @@ buffer_setup(struct videobuf_queue *vq, unsigned int *count, unsigned int *size) struct cx231xx *dev = fh->dev; struct v4l2_frequency f; - *size = - (fh->dev->width * fh->dev->height * dev->format->depth + 7) >> 3; + *size = (fh->dev->width * fh->dev->height * dev->format->depth + 7)>>3; if (0 == *count) *count = CX231XX_DEF_BUF; @@ -722,6 +711,7 @@ static void free_buffer(struct videobuf_queue *vq, struct cx231xx_buffer *buf) struct cx231xx_fh *fh = vq->priv_data; struct cx231xx *dev = fh->dev; unsigned long flags = 0; + if (in_interrupt()) BUG(); @@ -754,9 +744,8 @@ buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb, int rc = 0, urb_init = 0; /* The only currently supported format is 16 bits/pixel */ - buf->vb.size = - (fh->dev->width * fh->dev->height * dev->format->depth + 7) >> 3; - + buf->vb.size = (fh->dev->width * fh->dev->height * dev->format->depth + + 7) >> 3; if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size) return -EINVAL; @@ -785,7 +774,7 @@ buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb, buf->vb.state = VIDEOBUF_PREPARED; return 0; - fail: +fail: free_buffer(vq, buf); return rc; } @@ -876,7 +865,7 @@ static int res_get(struct cx231xx_fh *fh) static int res_check(struct cx231xx_fh *fh) { - return (fh->stream_on); + return fh->stream_on; } static void res_free(struct cx231xx_fh *fh) @@ -948,6 +937,7 @@ static int vidioc_g_fmt_vid_cap(struct file *file, void *priv, f->fmt.pix.field = V4L2_FIELD_INTERLACED; mutex_unlock(&dev->lock); + return 0; } @@ -1056,7 +1046,7 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, /* Set the correct alternate setting for this resolution */ cx231xx_resolution_set(dev); - out: +out: mutex_unlock(&dev->lock); return rc; } @@ -1110,11 +1100,11 @@ static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id * norm) static const char *iname[] = { [CX231XX_VMUX_COMPOSITE1] = "Composite1", - [CX231XX_VMUX_SVIDEO] = "S-Video", + [CX231XX_VMUX_SVIDEO] = "S-Video", [CX231XX_VMUX_TELEVISION] = "Television", - [CX231XX_VMUX_CABLE] = "Cable TV", - [CX231XX_VMUX_DVB] = "DVB", - [CX231XX_VMUX_DEBUG] = "for debug only", + [CX231XX_VMUX_CABLE] = "Cable TV", + [CX231XX_VMUX_DVB] = "DVB", + [CX231XX_VMUX_DEBUG] = "for debug only", }; static int vidioc_enum_input(struct file *file, void *priv, @@ -1386,12 +1376,11 @@ static int vidioc_s_frequency(struct file *file, void *priv, dev->ctl_freq = f->frequency; if (dev->tuner_type == TUNER_XC5000) { - if (dev->cx231xx_set_analog_freq != NULL) { + if (dev->cx231xx_set_analog_freq != NULL) dev->cx231xx_set_analog_freq(dev, f->frequency); - } } else { - cx231xx_i2c_call_clients(&dev->i2c_bus[1], VIDIOC_S_FREQUENCY, - f); + cx231xx_i2c_call_clients(&dev->i2c_bus[1], + VIDIOC_S_FREQUENCY, f); } mutex_unlock(&dev->lock); @@ -1430,47 +1419,42 @@ static int vidioc_g_register(struct file *file, void *priv, case V4L2_CHIP_MATCH_HOST: switch (reg->match.addr) { case 0: /* Cx231xx - internal registers */ - ret = - cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, - (u16) reg->reg, value, 4); - reg->val = - value[0] | value[1] << 8 | value[2] << 16 | value[3] - << 24; + ret = cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, + (u16)reg->reg, value, 4); + reg->val = value[0] | value[1] << 8 | + value[2] << 16 | value[3] << 24; break; case 1: /* Colibri - read byte */ - ret = - cx231xx_read_i2c_data(dev, Colibri_DEVICE_ADDRESS, - (u16) reg->reg, 2, &data, 1); + ret = cx231xx_read_i2c_data(dev, Colibri_DEVICE_ADDRESS, + (u16)reg->reg, 2, &data, 1); reg->val = le32_to_cpu(data & 0xff); break; case 14: /* Colibri - read dword */ - ret = - cx231xx_read_i2c_data(dev, Colibri_DEVICE_ADDRESS, - (u16) reg->reg, 2, &data, 4); + ret = cx231xx_read_i2c_data(dev, Colibri_DEVICE_ADDRESS, + (u16)reg->reg, 2, &data, 4); reg->val = le32_to_cpu(data); break; case 2: /* Hammerhead - read byte */ - ret = - cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, - (u16) reg->reg, 2, &data, 1); + ret = cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + (u16)reg->reg, 2, &data, 1); reg->val = le32_to_cpu(data & 0xff); break; case 24: /* Hammerhead - read dword */ - ret = - cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, - (u16) reg->reg, 2, &data, 4); + ret = cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + (u16)reg->reg, 2, &data, 4); reg->val = le32_to_cpu(data); break; case 3: /* flatiron - read byte */ - ret = - cx231xx_read_i2c_data(dev, Flatrion_DEVICE_ADDRESS, - (u16) reg->reg, 1, &data, 1); + ret = cx231xx_read_i2c_data(dev, + Flatrion_DEVICE_ADDRESS, + (u16)reg->reg, 1, + &data, 1); reg->val = le32_to_cpu(data & 0xff); break; case 34: /* flatiron - read dword */ ret = cx231xx_read_i2c_data(dev, Flatrion_DEVICE_ADDRESS, - (u16) reg->reg, 1, &data, 4); + (u16)reg->reg, 1, &data, 4); reg->val = le32_to_cpu(data); break; } @@ -1489,9 +1473,7 @@ static int vidioc_g_register(struct file *file, void *priv, } mutex_lock(&dev->lock); - cx231xx_i2c_call_clients(&dev->i2c_bus[0], VIDIOC_DBG_G_REGISTER, reg); - mutex_unlock(&dev->lock); return ret; @@ -1520,53 +1502,50 @@ static int vidioc_s_register(struct file *file, void *priv, data[1] = (u8) (value >> 8); data[2] = (u8) (value >> 16); data[3] = (u8) (value >> 24); - ret = - cx231xx_write_ctrl_reg(dev, + ret = cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER, - (u16) reg->reg, data, + (u16)reg->reg, data, 4); break; case 1: /* Colibri - read byte */ - ret = - cx231xx_write_i2c_data(dev, - Colibri_DEVICE_ADDRESS, - (u16) reg->reg, 2, - value, 1); + ret = cx231xx_write_i2c_data(dev, + Colibri_DEVICE_ADDRESS, + (u16)reg->reg, 2, + value, 1); break; case 14: /* Colibri - read dword */ - ret = - cx231xx_write_i2c_data(dev, - Colibri_DEVICE_ADDRESS, - (u16) reg->reg, 2, - value, 4); + ret = cx231xx_write_i2c_data(dev, + Colibri_DEVICE_ADDRESS, + (u16)reg->reg, 2, + value, 4); break; case 2: /* Hammerhead - read byte */ ret = cx231xx_write_i2c_data(dev, - HAMMERHEAD_I2C_ADDRESS, - (u16) reg->reg, 2, - value, 1); + HAMMERHEAD_I2C_ADDRESS, + (u16)reg->reg, 2, + value, 1); break; case 24: /* Hammerhead - read dword */ ret = cx231xx_write_i2c_data(dev, - HAMMERHEAD_I2C_ADDRESS, - (u16) reg->reg, 2, - value, 4); + HAMMERHEAD_I2C_ADDRESS, + (u16)reg->reg, 2, + value, 4); break; case 3: /* flatiron - read byte */ ret = cx231xx_write_i2c_data(dev, - Flatrion_DEVICE_ADDRESS, - (u16) reg->reg, 1, - value, 1); + Flatrion_DEVICE_ADDRESS, + (u16)reg->reg, 1, + value, 1); break; case 34: /* flatiron - read dword */ ret = cx231xx_write_i2c_data(dev, - Flatrion_DEVICE_ADDRESS, - (u16) reg->reg, 1, - value, 4); + Flatrion_DEVICE_ADDRESS, + (u16)reg->reg, 1, + value, 4); break; } } @@ -1805,7 +1784,7 @@ static int vidioc_reqbufs(struct file *file, void *priv, if (rc < 0) return rc; - return (videobuf_reqbufs(&fh->vb_vidq, rb)); + return videobuf_reqbufs(&fh->vb_vidq, rb); } static int vidioc_querybuf(struct file *file, void *priv, struct v4l2_buffer *b) @@ -1818,7 +1797,7 @@ static int vidioc_querybuf(struct file *file, void *priv, struct v4l2_buffer *b) if (rc < 0) return rc; - return (videobuf_querybuf(&fh->vb_vidq, b)); + return videobuf_querybuf(&fh->vb_vidq, b); } static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *b) @@ -1831,7 +1810,7 @@ static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *b) if (rc < 0) return rc; - return (videobuf_qbuf(&fh->vb_vidq, b)); + return videobuf_qbuf(&fh->vb_vidq, b); } static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b) @@ -1844,7 +1823,7 @@ static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b) if (rc < 0) return rc; - return (videobuf_dqbuf(&fh->vb_vidq, b, file->f_flags & O_NONBLOCK)); + return videobuf_dqbuf(&fh->vb_vidq, b, file->f_flags & O_NONBLOCK); } #ifdef CONFIG_VIDEO_V4L1_COMPAT @@ -2030,17 +2009,19 @@ static int cx231xx_v4l2_open(struct file *filp) dev->users++; - if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { - videobuf_queue_vmalloc_init(&fh->vb_vidq, &cx231xx_video_qops, NULL, &dev->video_mode.slock, fh->type, V4L2_FIELD_INTERLACED, /* V4L2_FIELD_SEQ_TB, */ + if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) + videobuf_queue_vmalloc_init(&fh->vb_vidq, &cx231xx_video_qops, + NULL, &dev->video_mode.slock, + fh->type, V4L2_FIELD_INTERLACED, sizeof(struct cx231xx_buffer), fh); - } - if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) { - - /* Set the required alternate setting VBI interface works in Bulk mode only */ + /* Set the required alternate setting VBI interface works in + Bulk mode only */ cx231xx_set_alt_setting(dev, INDEX_VANC, 0); - videobuf_queue_vmalloc_init(&fh->vb_vidq, &cx231xx_vbi_qops, NULL, &dev->vbi_mode.slock, fh->type, V4L2_FIELD_SEQ_TB, /* V4L2_FIELD_INTERLACED, */ + videobuf_queue_vmalloc_init(&fh->vb_vidq, &cx231xx_vbi_qops, + NULL, &dev->vbi_mode.slock, + fh->type, V4L2_FIELD_SEQ_TB, sizeof(struct cx231xx_buffer), fh); } @@ -2120,11 +2101,10 @@ static int cx231xx_v4l2_close(struct file *filp) cx231xx_uninit_vbi_isoc(dev); /* set alternate 0 */ - if (!dev->vbi_or_sliced_cc_mode) { + if (!dev->vbi_or_sliced_cc_mode) cx231xx_set_alt_setting(dev, INDEX_VANC, 0); - } else { + else cx231xx_set_alt_setting(dev, INDEX_HANC, 0); - } kfree(fh); dev->users--; @@ -2169,8 +2149,8 @@ static int cx231xx_v4l2_close(struct file *filp) * will allocate buffers when called for the first time */ static ssize_t -cx231xx_v4l2_read(struct file *filp, char __user * buf, size_t count, - loff_t * pos) +cx231xx_v4l2_read(struct file *filp, char __user *buf, size_t count, + loff_t *pos) { struct cx231xx_fh *fh = filp->private_data; struct cx231xx *dev = fh->dev; @@ -2254,98 +2234,98 @@ static int cx231xx_v4l2_mmap(struct file *filp, struct vm_area_struct *vma) } static const struct v4l2_file_operations cx231xx_v4l_fops = { - .owner = THIS_MODULE, - .open = cx231xx_v4l2_open, + .owner = THIS_MODULE, + .open = cx231xx_v4l2_open, .release = cx231xx_v4l2_close, - .read = cx231xx_v4l2_read, - .poll = cx231xx_v4l2_poll, - .mmap = cx231xx_v4l2_mmap, - .ioctl = video_ioctl2, + .read = cx231xx_v4l2_read, + .poll = cx231xx_v4l2_poll, + .mmap = cx231xx_v4l2_mmap, + .ioctl = video_ioctl2, }; static const struct v4l2_ioctl_ops video_ioctl_ops = { - .vidioc_querycap = vidioc_querycap, - .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, - .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, - .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, - .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, - .vidioc_g_fmt_vbi_cap = vidioc_g_fmt_vbi_cap, - .vidioc_try_fmt_vbi_cap = vidioc_try_fmt_vbi_cap, - .vidioc_s_fmt_vbi_cap = vidioc_try_fmt_vbi_cap, - .vidioc_g_audio = vidioc_g_audio, - .vidioc_s_audio = vidioc_s_audio, - .vidioc_cropcap = vidioc_cropcap, - .vidioc_g_fmt_sliced_vbi_cap = vidioc_g_fmt_sliced_vbi_cap, + .vidioc_querycap = vidioc_querycap, + .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, + .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, + .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, + .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, + .vidioc_g_fmt_vbi_cap = vidioc_g_fmt_vbi_cap, + .vidioc_try_fmt_vbi_cap = vidioc_try_fmt_vbi_cap, + .vidioc_s_fmt_vbi_cap = vidioc_try_fmt_vbi_cap, + .vidioc_g_audio = vidioc_g_audio, + .vidioc_s_audio = vidioc_s_audio, + .vidioc_cropcap = vidioc_cropcap, + .vidioc_g_fmt_sliced_vbi_cap = vidioc_g_fmt_sliced_vbi_cap, .vidioc_try_fmt_sliced_vbi_cap = vidioc_try_set_sliced_vbi_cap, - .vidioc_reqbufs = vidioc_reqbufs, - .vidioc_querybuf = vidioc_querybuf, - .vidioc_qbuf = vidioc_qbuf, - .vidioc_dqbuf = vidioc_dqbuf, - .vidioc_s_std = vidioc_s_std, - .vidioc_g_std = vidioc_g_std, - .vidioc_enum_input = vidioc_enum_input, - .vidioc_g_input = vidioc_g_input, - .vidioc_s_input = vidioc_s_input, - .vidioc_queryctrl = vidioc_queryctrl, - .vidioc_g_ctrl = vidioc_g_ctrl, - .vidioc_s_ctrl = vidioc_s_ctrl, - .vidioc_streamon = vidioc_streamon, - .vidioc_streamoff = vidioc_streamoff, - .vidioc_g_tuner = vidioc_g_tuner, - .vidioc_s_tuner = vidioc_s_tuner, - .vidioc_g_frequency = vidioc_g_frequency, - .vidioc_s_frequency = vidioc_s_frequency, + .vidioc_reqbufs = vidioc_reqbufs, + .vidioc_querybuf = vidioc_querybuf, + .vidioc_qbuf = vidioc_qbuf, + .vidioc_dqbuf = vidioc_dqbuf, + .vidioc_s_std = vidioc_s_std, + .vidioc_g_std = vidioc_g_std, + .vidioc_enum_input = vidioc_enum_input, + .vidioc_g_input = vidioc_g_input, + .vidioc_s_input = vidioc_s_input, + .vidioc_queryctrl = vidioc_queryctrl, + .vidioc_g_ctrl = vidioc_g_ctrl, + .vidioc_s_ctrl = vidioc_s_ctrl, + .vidioc_streamon = vidioc_streamon, + .vidioc_streamoff = vidioc_streamoff, + .vidioc_g_tuner = vidioc_g_tuner, + .vidioc_s_tuner = vidioc_s_tuner, + .vidioc_g_frequency = vidioc_g_frequency, + .vidioc_s_frequency = vidioc_s_frequency, #ifdef CONFIG_VIDEO_ADV_DEBUG - .vidioc_g_register = vidioc_g_register, - .vidioc_s_register = vidioc_s_register, + .vidioc_g_register = vidioc_g_register, + .vidioc_s_register = vidioc_s_register, #endif #ifdef CONFIG_VIDEO_V4L1_COMPAT - .vidiocgmbuf = vidiocgmbuf, + .vidiocgmbuf = vidiocgmbuf, #endif }; static struct video_device cx231xx_vbi_template; static const struct video_device cx231xx_video_template = { - .fops = &cx231xx_v4l_fops, - .release = video_device_release, - .ioctl_ops = &video_ioctl_ops, - .minor = -1, - .tvnorms = V4L2_STD_ALL, + .fops = &cx231xx_v4l_fops, + .release = video_device_release, + .ioctl_ops = &video_ioctl_ops, + .minor = -1, + .tvnorms = V4L2_STD_ALL, .current_norm = V4L2_STD_PAL, }; static const struct v4l2_file_operations radio_fops = { - .owner = THIS_MODULE, - .open = cx231xx_v4l2_open, + .owner = THIS_MODULE, + .open = cx231xx_v4l2_open, .release = cx231xx_v4l2_close, - .ioctl = video_ioctl2, + .ioctl = video_ioctl2, }; static const struct v4l2_ioctl_ops radio_ioctl_ops = { - .vidioc_querycap = radio_querycap, - .vidioc_g_tuner = radio_g_tuner, - .vidioc_enum_input = radio_enum_input, - .vidioc_g_audio = radio_g_audio, - .vidioc_s_tuner = radio_s_tuner, - .vidioc_s_audio = radio_s_audio, - .vidioc_s_input = radio_s_input, - .vidioc_queryctrl = radio_queryctrl, - .vidioc_g_ctrl = vidioc_g_ctrl, - .vidioc_s_ctrl = vidioc_s_ctrl, + .vidioc_querycap = radio_querycap, + .vidioc_g_tuner = radio_g_tuner, + .vidioc_enum_input = radio_enum_input, + .vidioc_g_audio = radio_g_audio, + .vidioc_s_tuner = radio_s_tuner, + .vidioc_s_audio = radio_s_audio, + .vidioc_s_input = radio_s_input, + .vidioc_queryctrl = radio_queryctrl, + .vidioc_g_ctrl = vidioc_g_ctrl, + .vidioc_s_ctrl = vidioc_s_ctrl, .vidioc_g_frequency = vidioc_g_frequency, .vidioc_s_frequency = vidioc_s_frequency, #ifdef CONFIG_VIDEO_ADV_DEBUG - .vidioc_g_register = vidioc_g_register, - .vidioc_s_register = vidioc_s_register, + .vidioc_g_register = vidioc_g_register, + .vidioc_s_register = vidioc_s_register, #endif }; static struct video_device cx231xx_radio_template = { - .name = "cx231xx-radio", - .fops = &radio_fops, + .name = "cx231xx-radio", + .fops = &radio_fops, .ioctl_ops = &radio_ioctl_ops, - .minor = -1, + .minor = -1, }; /******************************** usb interface ******************************/ @@ -2358,6 +2338,7 @@ static struct video_device *cx231xx_vdev_init(struct cx231xx *dev, const struct vfd = video_device_alloc(); if (NULL == vfd) return NULL; + *vfd = *template; vfd->minor = -1; vfd->parent = &dev->udev->dev; @@ -2439,8 +2420,8 @@ int cx231xx_register_analog_devices(struct cx231xx *dev) dev->name, dev->vbi_dev->num); if (cx231xx_boards[dev->model].radio.type == CX231XX_RADIO) { - dev->radio_dev = - cx231xx_vdev_init(dev, &cx231xx_radio_template, "radio"); + dev->radio_dev = cx231xx_vdev_init(dev, &cx231xx_radio_template, + "radio"); if (!dev->radio_dev) { cx231xx_errdev("cannot allocate video_device.\n"); return -ENODEV; diff --git a/linux/drivers/media/video/cx231xx/cx231xx.h b/linux/drivers/media/video/cx231xx/cx231xx.h index d88fc89c2..67ecff8e5 100644 --- a/linux/drivers/media/video/cx231xx/cx231xx.h +++ b/linux/drivers/media/video/cx231xx/cx231xx.h @@ -141,8 +141,7 @@ struct cx231xx_usb_isoc_ctl { int nfields; /* isoc urb callback */ - int (*isoc_copy) (struct cx231xx * dev, struct urb * urb); - + int (*isoc_copy) (struct cx231xx *dev, struct urb *urb); }; struct cx231xx_fmt { @@ -506,20 +505,19 @@ struct cx231xx { char urb_buf[URB_MAX_CTRL_SIZE]; /* urb control msg buffer */ /* helper funcs that call usb_control_msg */ - int (*cx231xx_read_ctrl_reg) (struct cx231xx * dev, u8 req, u16 reg, + int (*cx231xx_read_ctrl_reg) (struct cx231xx *dev, u8 req, u16 reg, char *buf, int len); - int (*cx231xx_write_ctrl_reg) (struct cx231xx * dev, u8 req, u16 reg, + int (*cx231xx_write_ctrl_reg) (struct cx231xx *dev, u8 req, u16 reg, char *buf, int len); - int (*cx231xx_send_usb_command) (struct cx231xx_i2c * i2c_bus, - struct cx231xx_i2c_xfer_data * - req_data); - int (*cx231xx_gpio_i2c_read) (struct cx231xx * dev, u8 dev_addr, - u8 * buf, u8 len); - int (*cx231xx_gpio_i2c_write) (struct cx231xx * dev, u8 dev_addr, - u8 * buf, u8 len); + int (*cx231xx_send_usb_command) (struct cx231xx_i2c *i2c_bus, + struct cx231xx_i2c_xfer_data *req_data); + int (*cx231xx_gpio_i2c_read) (struct cx231xx *dev, u8 dev_addr, + u8 *buf, u8 len); + int (*cx231xx_gpio_i2c_write) (struct cx231xx *dev, u8 dev_addr, + u8 *buf, u8 len); - int (*cx231xx_set_analog_freq) (struct cx231xx * dev, u32 freq); - int (*cx231xx_reset_analog_tuner) (struct cx231xx * dev); + int (*cx231xx_set_analog_freq) (struct cx231xx *dev, u32 freq); + int (*cx231xx_reset_analog_tuner) (struct cx231xx *dev); enum cx231xx_mode mode; @@ -571,7 +569,7 @@ int cx231xx_i2c_unregister(struct cx231xx_i2c *bus); /* Internal block control functions */ int cx231xx_read_i2c_data(struct cx231xx *dev, u8 dev_addr, - u16 saddr, u8 saddr_len, u32 * data, u8 data_len); + u16 saddr, u8 saddr_len, u32 *data, u8 data_len); int cx231xx_write_i2c_data(struct cx231xx *dev, u8 dev_addr, u16 saddr, u8 saddr_len, u32 data, u8 data_len); int cx231xx_reg_mask_write(struct cx231xx *dev, u8 dev_addr, u8 size, @@ -603,20 +601,20 @@ int cx231xx_tuner_pre_channel_change(struct cx231xx *dev); int cx231xx_tuner_post_channel_change(struct cx231xx *dev); /* video parser functions */ -u8 cx231xx_find_next_SAV_EAV(u8 * p_buffer, u32 buffer_size, - u32 * p_bytes_used); -u8 cx231xx_find_boundary_SAV_EAV(u8 * p_buffer, u8 * partial_buf, - u32 * p_bytes_used); +u8 cx231xx_find_next_SAV_EAV(u8 *p_buffer, u32 buffer_size, + u32 *p_bytes_used); +u8 cx231xx_find_boundary_SAV_EAV(u8 *p_buffer, u8 *partial_buf, + u32 *p_bytes_used); int cx231xx_do_copy(struct cx231xx *dev, struct cx231xx_dmaqueue *dma_q, - u8 * p_buffer, u32 bytes_to_copy); + u8 *p_buffer, u32 bytes_to_copy); void cx231xx_reset_video_buffer(struct cx231xx *dev, struct cx231xx_dmaqueue *dma_q); u8 cx231xx_is_buffer_done(struct cx231xx *dev, struct cx231xx_dmaqueue *dma_q); u32 cx231xx_copy_video_line(struct cx231xx *dev, struct cx231xx_dmaqueue *dma_q, - u8 * p_line, u32 length, int field_number); + u8 *p_line, u32 length, int field_number); u32 cx231xx_get_video_line(struct cx231xx *dev, struct cx231xx_dmaqueue *dma_q, - u8 sav_eav, u8 * p_buffer, u32 buffer_size); -void cx231xx_swab(u16 * from, u16 * to, u16 len); + u8 sav_eav, u8 *p_buffer, u32 buffer_size); +void cx231xx_swab(u16 *from, u16 *to, u16 len); /* Provided by cx231xx-core.c */ @@ -633,15 +631,15 @@ int cx231xx_write_ctrl_reg(struct cx231xx *dev, u8 req, u16 reg, char *buf, int len); int cx231xx_mode_register(struct cx231xx *dev, u16 address, u32 mode); -int cx231xx_send_vendor_cmd(struct cx231xx *dev, VENDOR_REQUEST_IN * ven_req); +int cx231xx_send_vendor_cmd(struct cx231xx *dev, VENDOR_REQUEST_IN *ven_req); int cx231xx_send_usb_command(struct cx231xx_i2c *i2c_bus, struct cx231xx_i2c_xfer_data *req_data); /* Gpio related functions */ -int cx231xx_send_gpio_cmd(struct cx231xx *dev, u32 gpio_bit, u8 * gpio_val, +int cx231xx_send_gpio_cmd(struct cx231xx *dev, u32 gpio_bit, u8 *gpio_val, u8 len, u8 request, u8 direction); -int cx231xx_set_gpio_bit(struct cx231xx *dev, u32 gpio_bit, u8 * gpio_val); -int cx231xx_get_gpio_bit(struct cx231xx *dev, u32 gpio_bit, u8 * gpio_val); +int cx231xx_set_gpio_bit(struct cx231xx *dev, u32 gpio_bit, u8 *gpio_val); +int cx231xx_get_gpio_bit(struct cx231xx *dev, u32 gpio_bit, u8 *gpio_val); int cx231xx_set_gpio_value(struct cx231xx *dev, int pin_number, int pin_value); int cx231xx_set_gpio_direction(struct cx231xx *dev, int pin_number, int pin_value); @@ -649,13 +647,13 @@ int cx231xx_set_gpio_direction(struct cx231xx *dev, int pin_number, int cx231xx_gpio_i2c_start(struct cx231xx *dev); int cx231xx_gpio_i2c_end(struct cx231xx *dev); int cx231xx_gpio_i2c_write_byte(struct cx231xx *dev, u8 data); -int cx231xx_gpio_i2c_read_byte(struct cx231xx *dev, u8 * buf); +int cx231xx_gpio_i2c_read_byte(struct cx231xx *dev, u8 *buf); int cx231xx_gpio_i2c_read_ack(struct cx231xx *dev); int cx231xx_gpio_i2c_write_ack(struct cx231xx *dev); int cx231xx_gpio_i2c_write_nak(struct cx231xx *dev); -int cx231xx_gpio_i2c_read(struct cx231xx *dev, u8 dev_addr, u8 * buf, u8 len); -int cx231xx_gpio_i2c_write(struct cx231xx *dev, u8 dev_addr, u8 * buf, u8 len); +int cx231xx_gpio_i2c_read(struct cx231xx *dev, u8 dev_addr, u8 *buf, u8 len); +int cx231xx_gpio_i2c_write(struct cx231xx *dev, u8 dev_addr, u8 *buf, u8 len); /* audio related functions */ int cx231xx_set_audio_decoder_input(struct cx231xx *dev, @@ -667,8 +665,8 @@ int cx231xx_set_video_alternate(struct cx231xx *dev); int cx231xx_set_alt_setting(struct cx231xx *dev, u8 index, u8 alt); int cx231xx_init_isoc(struct cx231xx *dev, int max_packets, int num_bufs, int max_pkt_size, - int (*isoc_copy) (struct cx231xx * dev, - struct urb * urb)); + int (*isoc_copy) (struct cx231xx *dev, + struct urb *urb)); void cx231xx_uninit_isoc(struct cx231xx *dev); int cx231xx_set_mode(struct cx231xx *dev, enum cx231xx_mode set_mode); int cx231xx_gpio_set(struct cx231xx *dev, struct cx231xx_reg_seq *gpio); -- cgit v1.2.3 From 688b148d5028295349c3cd5c14cf539fd46a58a5 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 4 Mar 2009 17:49:01 -0300 Subject: cx231xx: Fix CodingStyle From: Sri Deevi Fixes several CodingStyle issues on the driver. Signed-off-by: Srinivasa Deevi Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/cx231xx/cx231xx-audio.c | 24 ++- linux/drivers/media/video/cx231xx/cx231xx-avcore.c | 179 +++++++++++++-------- linux/drivers/media/video/cx231xx/cx231xx-cards.c | 33 ++-- linux/drivers/media/video/cx231xx/cx231xx-core.c | 138 ++++++++-------- linux/drivers/media/video/cx231xx/cx231xx-dvb.c | 18 +-- linux/drivers/media/video/cx231xx/cx231xx-i2c.c | 44 ++--- linux/drivers/media/video/cx231xx/cx231xx-input.c | 8 +- linux/drivers/media/video/cx231xx/cx231xx-reg.h | 17 +- linux/drivers/media/video/cx231xx/cx231xx-vbi.c | 17 +- linux/drivers/media/video/cx231xx/cx231xx-vbi.h | 30 ++-- linux/drivers/media/video/cx231xx/cx231xx-video.c | 35 ++-- linux/drivers/media/video/cx231xx/cx231xx.h | 47 +++--- 12 files changed, 326 insertions(+), 264 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/cx231xx/cx231xx-audio.c b/linux/drivers/media/video/cx231xx/cx231xx-audio.c index 69e5e6ed5..67d3952c7 100644 --- a/linux/drivers/media/video/cx231xx/cx231xx-audio.c +++ b/linux/drivers/media/video/cx231xx/cx231xx-audio.c @@ -150,12 +150,16 @@ static void cx231xx_audio_isocirq(struct urb *urb) #endif dev->adev.hwptr_done_capture += length; - if (dev->adev.hwptr_done_capture >= runtime->buffer_size) - dev->adev.hwptr_done_capture -= runtime->buffer_size; + if (dev->adev.hwptr_done_capture >= + runtime->buffer_size) + dev->adev.hwptr_done_capture -= + runtime->buffer_size; dev->adev.capture_transfer_done += length; - if (dev->adev.capture_transfer_done >= runtime->period_size) { - dev->adev.capture_transfer_done -= runtime->period_size; + if (dev->adev.capture_transfer_done >= + runtime->period_size) { + dev->adev.capture_transfer_done -= + runtime->period_size; period_elapsed = 1; } #ifdef NO_PCM_LOCK @@ -207,7 +211,8 @@ static int cx231xx_init_audio_isoc(struct cx231xx *dev) urb->dev = dev->udev; urb->context = dev; - urb->pipe = usb_rcvisocpipe(dev->udev, dev->adev.end_point_addr); + urb->pipe = usb_rcvisocpipe(dev->udev, + dev->adev.end_point_addr); urb->transfer_flags = URB_ISO_ASAP; urb->transfer_buffer = dev->adev.transfer_buffer[i]; urb->interval = 1; @@ -215,7 +220,8 @@ static int cx231xx_init_audio_isoc(struct cx231xx *dev) urb->number_of_packets = CX231XX_NUM_AUDIO_PACKETS; urb->transfer_buffer_length = sb_size; - for (j = k = 0; j < CX231XX_NUM_AUDIO_PACKETS; j++, k += dev->adev.max_pkt_size) { + for (j = k = 0; j < CX231XX_NUM_AUDIO_PACKETS; + j++, k += dev->adev.max_pkt_size) { urb->iso_frame_desc[j].offset = k; urb->iso_frame_desc[j].length = dev->adev.max_pkt_size; } @@ -335,7 +341,8 @@ static int snd_cx231xx_capture_open(struct snd_pcm_substream *substream) dev->mute = 0; /* set alternate setting for audio interface */ - ret = cx231xx_set_alt_setting(dev, INDEX_AUDIO, 1); /* 1 - 48000 samples per sec */ + /* 1 - 48000 samples per sec */ + ret = cx231xx_set_alt_setting(dev, INDEX_AUDIO, 1); if (ret < 0) { cx231xx_errdev("failed to set alternate setting !\n"); @@ -370,7 +377,8 @@ static int snd_cx231xx_pcm_close(struct snd_pcm_substream *substream) dprintk("closing device\n"); /* set alternate setting for audio interface */ - ret = cx231xx_set_alt_setting(dev, INDEX_AUDIO, 0); /* 1 - 48000 samples per sec */ + /* 1 - 48000 samples per sec */ + ret = cx231xx_set_alt_setting(dev, INDEX_AUDIO, 0); if (ret < 0) { cx231xx_errdev("failed to set alternate setting !\n"); diff --git a/linux/drivers/media/video/cx231xx/cx231xx-avcore.c b/linux/drivers/media/video/cx231xx/cx231xx-avcore.c index 6eb63d078..8bbe518f4 100644 --- a/linux/drivers/media/video/cx231xx/cx231xx-avcore.c +++ b/linux/drivers/media/video/cx231xx/cx231xx-avcore.c @@ -74,12 +74,14 @@ int cx231xx_colibri_init_super_block(struct cx231xx *dev, u32 ref_count) &colibri_power_status, 1); colibri_power_status &= 0xff; if (status < 0) { - cx231xx_info(": Init Super Block failed in sending/receiving cmds\n"); + cx231xx_info( + ": Init Super Block failed in send/receive cmds\n"); break; } i++; if (i == 10) { - cx231xx_info(": Init Super Block force break in loop !!!!\n"); + cx231xx_info( + ": Init Super Block force break in loop !!!!\n"); status = -1; break; } @@ -258,7 +260,8 @@ int cx231xx_colibri_set_mode(struct cx231xx *dev, enum AFE_MODE mode) break; } - if ((mode != dev->colibri_mode) && (dev->video_input == CX231XX_VMUX_TELEVISION)) + if ((mode != dev->colibri_mode) && + (dev->video_input == CX231XX_VMUX_TELEVISION)) status = cx231xx_colibri_adjust_ref_count(dev, CX231XX_VMUX_TELEVISION); @@ -511,8 +514,9 @@ int cx231xx_set_video_input_mux(struct cx231xx *dev, u8 input) status = cx231xx_set_power_mode(dev, POLARIS_AVMODE_ENXTERNAL_AV); if (status < 0) { - cx231xx_errdev("%s: cx231xx_set_power_mode : Failed to set Power - errCode [%d]!\n", - __func__, status); + cx231xx_errdev("%s: set_power_mode : Failed to" + " set Power - errCode [%d]!\n", + __func__, status); return status; } } @@ -528,8 +532,9 @@ int cx231xx_set_video_input_mux(struct cx231xx *dev, u8 input) status = cx231xx_set_power_mode(dev, POLARIS_AVMODE_ANALOGT_TV); if (status < 0) { - cx231xx_errdev("%s: cx231xx_set_power_mode : Failed to set Power - errCode [%d]!\n", - __func__, status); + cx231xx_errdev("%s: set_power_mode:Failed" + " to set Power - errCode [%d]!\n", + __func__, status); return status; } } @@ -538,7 +543,7 @@ int cx231xx_set_video_input_mux(struct cx231xx *dev, u8 input) INPUT(input)->vmux); break; default: - cx231xx_errdev("%s: cx231xx_set_power_mode : Unknown Input %d !\n", + cx231xx_errdev("%s: set_power_mode : Unknown Input %d !\n", __func__, INPUT(input)->type); break; } @@ -549,7 +554,8 @@ int cx231xx_set_video_input_mux(struct cx231xx *dev, u8 input) return status; } -int cx231xx_set_decoder_video_input(struct cx231xx *dev, u8 pin_type, u8 input) +int cx231xx_set_decoder_video_input(struct cx231xx *dev, + u8 pin_type, u8 input) { int status = 0; u32 value = 0; @@ -557,8 +563,9 @@ int cx231xx_set_decoder_video_input(struct cx231xx *dev, u8 pin_type, u8 input) if (pin_type != dev->video_input) { status = cx231xx_colibri_adjust_ref_count(dev, pin_type); if (status < 0) { - cx231xx_errdev("%s: cx231xx_colibri_adjust_ref_count :Failed to set Colibri input mux - errCode [%d]!\n", - __func__, status); + cx231xx_errdev("%s: adjust_ref_count :Failed to set" + "Colibri input mux - errCode [%d]!\n", + __func__, status); return status; } } @@ -566,8 +573,9 @@ int cx231xx_set_decoder_video_input(struct cx231xx *dev, u8 pin_type, u8 input) /* call colibri block to set video inputs */ status = cx231xx_colibri_set_input_mux(dev, input); if (status < 0) { - cx231xx_errdev("%s: cx231xx_colibri_set_input_mux :Failed to set Colibri input mux - errCode [%d]!\n", - __func__, status); + cx231xx_errdev("%s: set_input_mux :Failed to set" + " Colibri input mux - errCode [%d]!\n", + __func__, status); return status; } @@ -579,8 +587,10 @@ int cx231xx_set_decoder_video_input(struct cx231xx *dev, u8 pin_type, u8 input) value |= (0 << 13) | (1 << 4); value &= ~(1 << 5); - value &= (~(0x1ff8000)); /* set [24:23] [22:15] to 0 */ - value |= 0x1000000; /* set FUNC_MODE[24:23] = 2 IF_MOD[22:15] = 0 */ + /* set [24:23] [22:15] to 0 */ + value &= (~(0x1ff8000)); + /* set FUNC_MODE[24:23] = 2 IF_MOD[22:15] = 0 */ + value |= 0x1000000; status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, AFE_CTRL, 2, value, 4); @@ -600,7 +610,8 @@ int cx231xx_set_decoder_video_input(struct cx231xx *dev, u8 pin_type, u8 input) /* Tell DIF object to go to baseband mode */ status = cx231xx_dif_set_standard(dev, DIF_USE_BASEBAND); if (status < 0) { - cx231xx_errdev("%s: cx231xx_dif set to By pass mode - errCode [%d]!\n", + cx231xx_errdev("%s: cx231xx_dif set to By pass" + " mode- errCode [%d]!\n", __func__, status); return status; } @@ -637,9 +648,11 @@ int cx231xx_set_decoder_video_input(struct cx231xx *dev, u8 pin_type, u8 input) status = cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, AFE_CTRL, 2, &value, 4); - value &= (~(0x1ff8000)); /* set [24:23] [22:15] to 0 */ - value |= 0x1000010; /* set FUNC_MODE[24:23] = 2 - IF_MOD[22:15] = 0 DCR_BYP_CH2[4:4] = 1; */ + /* set [24:23] [22:15] to 0 */ + value &= (~(0x1ff8000)); + /* set FUNC_MODE[24:23] = 2 + IF_MOD[22:15] = 0 DCR_BYP_CH2[4:4] = 1; */ + value |= 0x1000010; status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, AFE_CTRL, 2, value, 4); @@ -647,7 +660,8 @@ int cx231xx_set_decoder_video_input(struct cx231xx *dev, u8 pin_type, u8 input) /* Tell DIF object to go to baseband mode */ status = cx231xx_dif_set_standard(dev, DIF_USE_BASEBAND); if (status < 0) { - cx231xx_errdev("%s: cx231xx_dif set to By pass mode - errCode [%d]!\n", + cx231xx_errdev("%s: cx231xx_dif set to By pass" + " mode- errCode [%d]!\n", __func__, status); return status; } @@ -713,8 +727,10 @@ int cx231xx_set_decoder_video_input(struct cx231xx *dev, u8 pin_type, u8 input) value |= (0 << 13) | (1 << 4); value &= ~(1 << 5); - value &= (~(0x1FF8000)); /* set [24:23] [22:15] to 0 */ - value |= 0x1000000; /* set FUNC_MODE[24:23] = 2 IF_MOD[22:15] = 0 */ + /* set [24:23] [22:15] to 0 */ + value &= (~(0x1FF8000)); + /* set FUNC_MODE[24:23] = 2 IF_MOD[22:15] = 0 */ + value |= 0x1000000; status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, AFE_CTRL, 2, @@ -740,8 +756,9 @@ int cx231xx_set_decoder_video_input(struct cx231xx *dev, u8 pin_type, u8 input) status = cx231xx_dif_set_standard(dev, DIF_USE_BASEBAND); if (status < 0) { - cx231xx_errdev("%s: cx231xx_dif set to By pass mode - errCode [%d]!\n", - __func__, status); + cx231xx_errdev("%s: cx231xx_dif set to By pass" + " mode- errCode [%d]!\n", + __func__, status); return status; } @@ -773,7 +790,8 @@ int cx231xx_set_decoder_video_input(struct cx231xx *dev, u8 pin_type, u8 input) status = cx231xx_read_modify_write_i2c_dword(dev, HAMMERHEAD_I2C_ADDRESS, MODE_CTRL, FLD_INPUT_MODE, - cx231xx_set_field(FLD_INPUT_MODE, INPUT_MODE_CVBS_0)); + cx231xx_set_field(FLD_INPUT_MODE, + INPUT_MODE_CVBS_0)); break; default: /* Enable the DIF for the tuner */ @@ -781,8 +799,9 @@ int cx231xx_set_decoder_video_input(struct cx231xx *dev, u8 pin_type, u8 input) /* Reinitialize the DIF */ status = cx231xx_dif_set_standard(dev, dev->norm); if (status < 0) { - cx231xx_errdev("%s: cx231xx_dif set to By pass mode - errCode [%d]!\n", - __func__, status); + cx231xx_errdev("%s: cx231xx_dif set to By pass" + " mode- errCode [%d]!\n", + __func__, status); return status; } @@ -861,9 +880,11 @@ int cx231xx_set_decoder_video_input(struct cx231xx *dev, u8 pin_type, u8 input) status = cx231xx_read_modify_write_i2c_dword(dev, HAMMERHEAD_I2C_ADDRESS, MODE_CTRL, FLD_INPUT_MODE, - cx231xx_set_field(FLD_INPUT_MODE, INPUT_MODE_CVBS_0)); + cx231xx_set_field(FLD_INPUT_MODE, + INPUT_MODE_CVBS_0)); - /* Set some bits in AFE_CTRL so that channel 2 or 3 is ready to receive audio */ + /* Set some bits in AFE_CTRL so that channel 2 or 3 + * is ready to receive audio */ /* Clear clamp for channels 2 and 3 (bit 16-17) */ /* Clear droop comp (bit 19-20) */ /* Set VGA_SEL (for audio control) (bit 7-8) */ @@ -903,8 +924,9 @@ int cx231xx_set_decoder_video_input(struct cx231xx *dev, u8 pin_type, u8 input) } /* - * Handle any video-mode specific overrides that are different on a per video standards - * basis after touching the MODE_CTRL register which resets many values for autodetect + * Handle any video-mode specific overrides that are different + * on a per video standards basis after touching the MODE_CTRL + * register which resets many values for autodetect */ int cx231xx_do_mode_ctrl_overrides(struct cx231xx *dev) { @@ -918,7 +940,8 @@ int cx231xx_do_mode_ctrl_overrides(struct cx231xx *dev) DFE_CTRL3, 2, 0xCD3F0280, 4); - if (dev->norm & (V4L2_STD_NTSC_M | V4L2_STD_NTSC_M_JP | V4L2_STD_PAL_M)) { + if (dev->norm & (V4L2_STD_NTSC_M | V4L2_STD_NTSC_M_JP | + V4L2_STD_PAL_M)) { cx231xx_info("do_mode_ctrl_overrides NTSC\n"); /* Move the close caption lines out of active video, @@ -1237,55 +1260,72 @@ int cx231xx_dif_configure_C2HH_for_low_IF(struct cx231xx *dev, u32 mode, if (mode == V4L2_TUNER_RADIO) { /* C2HH */ - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, - AFE_CTRL_C2HH_SRC_CTRL, 30, 31, 0x1); /* lo if big signal */ - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, - AFE_CTRL_C2HH_SRC_CTRL, 23, 24, function_mode); /* FUNC_MODE = DIF */ - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, - AFE_CTRL_C2HH_SRC_CTRL, 15, 22, 0xFF); /* IF_MODE */ - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, - AFE_CTRL_C2HH_SRC_CTRL, 9, 9, 0x1); /* no inv */ + /* lo if big signal */ + status = cx231xx_reg_mask_write(dev, + HAMMERHEAD_I2C_ADDRESS, 32, + AFE_CTRL_C2HH_SRC_CTRL, 30, 31, 0x1); + /* FUNC_MODE = DIF */ + status = cx231xx_reg_mask_write(dev, + HAMMERHEAD_I2C_ADDRESS, 32, + AFE_CTRL_C2HH_SRC_CTRL, 23, 24, function_mode); + /* IF_MODE */ + status = cx231xx_reg_mask_write(dev, + HAMMERHEAD_I2C_ADDRESS, 32, + AFE_CTRL_C2HH_SRC_CTRL, 15, 22, 0xFF); + /* no inv */ + status = cx231xx_reg_mask_write(dev, + HAMMERHEAD_I2C_ADDRESS, 32, + AFE_CTRL_C2HH_SRC_CTRL, 9, 9, 0x1); } else { switch (standard) { case V4L2_STD_NTSC_M: /* 75 IRE Setup */ - case V4L2_STD_NTSC_M_JP: /* Japan, 0 IRE Setup */ + case V4L2_STD_NTSC_M_JP:/* Japan, 0 IRE Setup */ case V4L2_STD_PAL_M: case V4L2_STD_PAL_N: case V4L2_STD_PAL_Nc: + /* lo if big signal */ status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, - AFE_CTRL_C2HH_SRC_CTRL, 30, 31, 0x1); /* lo if big signal */ + AFE_CTRL_C2HH_SRC_CTRL, 30, 31, 0x1); + /* FUNC_MODE = DIF */ status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, AFE_CTRL_C2HH_SRC_CTRL, 23, 24, - function_mode); /* FUNC_MODE = DIF */ + function_mode); + /* IF_MODE */ status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, - AFE_CTRL_C2HH_SRC_CTRL, 15, 22, 0xb); /* IF_MODE */ + AFE_CTRL_C2HH_SRC_CTRL, 15, 22, 0xb); + /* no inv */ status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, - AFE_CTRL_C2HH_SRC_CTRL, 9, 9, 0x1); /* no inv */ + AFE_CTRL_C2HH_SRC_CTRL, 9, 9, 0x1); + /* 0x124, AUD_CHAN1_SRC = 0x3 */ status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, - AUD_IO_CTRL, 0, 31, 0x00000003); /* 0x124, AUD_CHAN1_SRC = 0x3 */ + AUD_IO_CTRL, 0, 31, 0x00000003); break; case V4L2_STD_PAL_B: case V4L2_STD_PAL_G: /* C2HH setup */ + /* lo if big signal */ status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, - AFE_CTRL_C2HH_SRC_CTRL, 30, 31, 0x1); /* lo if big signal */ + AFE_CTRL_C2HH_SRC_CTRL, 30, 31, 0x1); + /* FUNC_MODE = DIF */ status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, AFE_CTRL_C2HH_SRC_CTRL, 23, 24, - function_mode); /* FUNC_MODE = DIF */ + function_mode); + /* IF_MODE */ status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, - AFE_CTRL_C2HH_SRC_CTRL, 15, 22, 0xE); /* IF_MODE */ + AFE_CTRL_C2HH_SRC_CTRL, 15, 22, 0xE); + /* no inv */ status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, - AFE_CTRL_C2HH_SRC_CTRL, 9, 9, 0x1); /* no inv */ + AFE_CTRL_C2HH_SRC_CTRL, 9, 9, 0x1); break; case V4L2_STD_PAL_D: @@ -1298,19 +1338,23 @@ int cx231xx_dif_configure_C2HH_for_low_IF(struct cx231xx *dev, u32 mode, case V4L2_STD_SECAM_K: case V4L2_STD_SECAM_K1: /* C2HH setup */ + /* lo if big signal */ status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, - AFE_CTRL_C2HH_SRC_CTRL, 30, 31, 0x1); /* lo if big signal */ + AFE_CTRL_C2HH_SRC_CTRL, 30, 31, 0x1); + /* FUNC_MODE = DIF */ status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, AFE_CTRL_C2HH_SRC_CTRL, 23, 24, - function_mode); /* FUNC_MODE = DIF */ + function_mode); + /* IF_MODE */ status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, - AFE_CTRL_C2HH_SRC_CTRL, 15, 22, 0xF); /* IF_MODE */ + AFE_CTRL_C2HH_SRC_CTRL, 15, 22, 0xF); + /* no inv */ status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, - AFE_CTRL_C2HH_SRC_CTRL, 9, 9, 0x1); /* no inv */ + AFE_CTRL_C2HH_SRC_CTRL, 9, 9, 0x1); break; case DIF_USE_BASEBAND: @@ -1919,7 +1963,8 @@ int cx231xx_set_power_mode(struct cx231xx *dev, AV_MODE mode) status = cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER, PWR_CTL_EN, value, 4); - dev->xc_fw_load_done = 0; /* reset state of xceive tuner */ + /* reset state of xceive tuner */ + dev->xc_fw_load_done = 0; break; case POLARIS_AVMODE_ANALOGT_TV: @@ -2076,7 +2121,8 @@ int cx231xx_set_power_mode(struct cx231xx *dev, AV_MODE mode) status = cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, PWR_CTL_EN, value, 4); - cx231xx_info(" The data of PWR_CTL_EN register 0x74=0x%0x,0x%0x,0x%0x,0x%0x\n", + cx231xx_info(" The data of PWR_CTL_EN register 0x74" + "=0x%0x,0x%0x,0x%0x,0x%0x\n", value[0], value[1], value[2], value[3]); return status; @@ -2210,10 +2256,10 @@ int cx231xx_capture_start(struct cx231xx *dev, int start, u8 media_type) { int rc; u32 ep_mask = -1; - PPCB_CONFIG pcb_config; + struct pcb_config *pcb_config; /* get EP for media type */ - pcb_config = &dev->current_pcb_config; + pcb_config = (struct pcb_config *)&dev->current_pcb_config; if (pcb_config->config_num == 1) { switch (media_type) { @@ -2278,13 +2324,10 @@ int cx231xx_capture_start(struct cx231xx *dev, int start, u8 media_type) rc = cx231xx_stop_stream(dev, ep_mask); } -#if 0 - if (dev->mode == CX231XX_ANALOG_MODE) { - /* do any in Analog mode */ - } else { - /* do any in digital mode */ - } -#endif + if (dev->mode == CX231XX_ANALOG_MODE) + ;/* do any in Analog mode */ + else + ;/* do any in digital mode */ return rc; } @@ -2571,10 +2614,12 @@ int cx231xx_gpio_i2c_read_ack(struct cx231xx *dev) status = cx231xx_get_gpio_bit(dev, dev->gpio_dir, (u8 *)&dev->gpio_val); nCnt--; - } while (((dev->gpio_val & (1 << dev->board.tuner_scl_gpio)) == 0) && (nCnt > 0)); + } while (((dev->gpio_val & + (1 << dev->board.tuner_scl_gpio)) == 0) && + (nCnt > 0)); if (nCnt == 0) - cx231xx_info("No ACK after %d msec for clock stretch. GPIO I2C operation failed!", + cx231xx_info("No ACK after %d msec -GPIO I2C failed!", nInit * 10); /* readAck diff --git a/linux/drivers/media/video/cx231xx/cx231xx-cards.c b/linux/drivers/media/video/cx231xx/cx231xx-cards.c index 9ecbb4b75..3a97f5eb4 100644 --- a/linux/drivers/media/video/cx231xx/cx231xx-cards.c +++ b/linux/drivers/media/video/cx231xx/cx231xx-cards.c @@ -1,8 +1,9 @@ /* - cx231xx-cards.c - driver for Conexant Cx23100/101/102 USB video capture devices + cx231xx-cards.c - driver for Conexant Cx23100/101/102 + USB video capture devices Copyright (C) 2008 - Based on em28xx driver + Based on em28xx driver 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 @@ -86,7 +87,7 @@ struct cx231xx_board cx231xx_boards[] = { .amux = CX231XX_AMUX_LINE_IN, .gpio = 0, - }}, + } }, }, [CX231XX_BOARD_CNXT_RDE_250] = { @@ -133,7 +134,7 @@ struct cx231xx_board cx231xx_boards[] = { .amux = CX231XX_AMUX_LINE_IN, .gpio = 0, - }}, + } }, }, [CX231XX_BOARD_CNXT_RDU_250] = { @@ -180,7 +181,7 @@ struct cx231xx_board cx231xx_boards[] = { .amux = CX231XX_AMUX_LINE_IN, .gpio = 0, - }}, + } }, }, }; const unsigned int cx231xx_bcount = ARRAY_SIZE(cx231xx_boards); @@ -210,9 +211,8 @@ int cx231xx_tuner_callback(void *ptr, int component, int command, int arg) if (dev->tuner_type == TUNER_XC5000) { if (command == XC5000_TUNER_RESET) { cx231xx_info - ("Tuner Call back : RESET : command %d : tuner type %d \n", - command, dev->tuner_type); - + ("Tuner CB: RESET: cmd %d : tuner type %d \n", + command, dev->tuner_type); cx231xx_set_gpio_value(dev, dev->board.tuner_gpio->bit, 1); msleep(10); @@ -226,10 +226,9 @@ int cx231xx_tuner_callback(void *ptr, int component, int command, int arg) } return rc; } - EXPORT_SYMBOL_GPL(cx231xx_tuner_callback); -static void inline cx231xx_set_model(struct cx231xx *dev) +static inline void cx231xx_set_model(struct cx231xx *dev) { memcpy(&dev->board, &cx231xx_boards[dev->model], sizeof(dev->board)); } @@ -543,7 +542,7 @@ static int cx231xx_init_dev(struct cx231xx **devhandle, struct usb_device *udev, return 0; - fail_reg_devices: +fail_reg_devices: mutex_unlock(&dev->lock); return retval; } @@ -639,12 +638,13 @@ static int cx231xx_usb_probe(struct usb_interface *interface, dev->has_alsa_audio = 1; dev->power_mode = -1; - dev->vbi_or_sliced_cc_mode = 0; /* 0 - vbi ; 1 -sliced cc mode */ + /* 0 - vbi ; 1 -sliced cc mode */ + dev->vbi_or_sliced_cc_mode = 0; /* get maximum no.of IAD interfaces */ assoc_desc = udev->actconfig->intf_assoc[0]; dev->max_iad_interface_count = assoc_desc->bInterfaceCount; - cx231xx_info(": Found IAD interface count %d\n", + cx231xx_info("Found IAD interface count %d\n", dev->max_iad_interface_count); /* init CIR module TBD */ @@ -673,10 +673,9 @@ static int cx231xx_usb_probe(struct usb_interface *interface, assoc_desc = udev->actconfig->intf_assoc[0]; if (assoc_desc->bFirstInterface == ifnum) { cx231xx_info - (": Found IAD interface match: AV Descriptor Start!! \n"); + ("Found IAD interface match: AV Desc Start!! \n"); } else { - cx231xx_err(DRIVER_NAME - " Not found matching interface\n"); + cx231xx_err(" Not found matching interface\n"); return -ENODEV; } @@ -702,7 +701,7 @@ static int cx231xx_usb_probe(struct usb_interface *interface, skip_interface = 1; /* set skipping */ else { cx231xx_info - (": Found IAD interface number match with AV Device number!! \n"); + ("Found IAD interface no. match with AV Device no.!\n"); } } diff --git a/linux/drivers/media/video/cx231xx/cx231xx-core.c b/linux/drivers/media/video/cx231xx/cx231xx-core.c index 73e8837b7..945eb6196 100644 --- a/linux/drivers/media/video/cx231xx/cx231xx-core.c +++ b/linux/drivers/media/video/cx231xx/cx231xx-core.c @@ -1,8 +1,9 @@ /* - cx231xx-core.c - driver for Conexant Cx23100/101/102 USB video capture devices + cx231xx-core.c - driver for Conexant Cx23100/101/102 + USB video capture devices Copyright (C) 2008 - Based on em28xx driver + Based on em28xx driver 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 @@ -59,9 +60,9 @@ MODULE_PARM_DESC(alt, "alternate setting to use for video endpoint"); printk(KERN_INFO "%s %s :"fmt, \ dev->name, __func__ , ##arg); } while (0) -/************************************************************************************ -* Device control list functions * -*************************************************************************************/ +/***************************************************************** +* Device control list functions * +******************************************************************/ static LIST_HEAD(cx231xx_devlist); static DEFINE_MUTEX(cx231xx_devlist_mutex); @@ -130,7 +131,6 @@ int cx231xx_register_extension(struct cx231xx_ops *ops) mutex_unlock(&cx231xx_devlist_mutex); return 0; } - EXPORT_SYMBOL(cx231xx_register_extension); void cx231xx_unregister_extension(struct cx231xx_ops *ops) @@ -149,7 +149,6 @@ void cx231xx_unregister_extension(struct cx231xx_ops *ops) mutex_unlock(&cx231xx_extension_devlist_lock); mutex_unlock(&cx231xx_devlist_mutex); } - EXPORT_SYMBOL(cx231xx_unregister_extension); void cx231xx_init_extension(struct cx231xx *dev) @@ -180,15 +179,15 @@ void cx231xx_close_extension(struct cx231xx *dev) mutex_unlock(&cx231xx_extension_devlist_lock); } -/************************************************************************************ -* U S B related functions * -*************************************************************************************/ +/**************************************************************** +* U S B related functions * +*****************************************************************/ int cx231xx_send_usb_command(struct cx231xx_i2c *i2c_bus, struct cx231xx_i2c_xfer_data *req_data) { int status = 0; struct cx231xx *dev = i2c_bus->dev; - VENDOR_REQUEST_IN ven_req; + struct VENDOR_REQUEST_IN ven_req; u8 saddr_len = 0; u8 _i2c_period = 0; @@ -215,10 +214,10 @@ int cx231xx_send_usb_command(struct cx231xx_i2c *i2c_bus, _i2c_nostop << 1 | I2C_SYNC | _i2c_reserve << 6; /* set channel number */ - if (req_data->direction & I2C_M_RD) - ven_req.bRequest = i2c_bus->nr + 4; /* channel number, for read, - spec required channel_num +4 */ - else + if (req_data->direction & I2C_M_RD) { + /* channel number, for read,spec required channel_num +4 */ + ven_req.bRequest = i2c_bus->nr + 4; + } else ven_req.bRequest = i2c_bus->nr; /* channel number, */ /* set index value */ @@ -274,14 +273,14 @@ int cx231xx_send_usb_command(struct cx231xx_i2c *i2c_bus, status = cx231xx_send_vendor_cmd(dev, &ven_req); if (status < 0) { cx231xx_info - ("UsbInterface::sendCommand, output buffer failed with status -%d\n", + ("UsbInterface::sendCommand, failed with status -%d\n", status); } return status; } - EXPORT_SYMBOL_GPL(cx231xx_send_usb_command); + /* * cx231xx_read_ctrl_reg() * reads data from the usb device specifying bRequest and wValue @@ -355,7 +354,8 @@ int cx231xx_read_ctrl_reg(struct cx231xx *dev, u8 req, u16 reg, return ret; } -int cx231xx_send_vendor_cmd(struct cx231xx *dev, VENDOR_REQUEST_IN * ven_req) +int cx231xx_send_vendor_cmd(struct cx231xx *dev, + struct VENDOR_REQUEST_IN *ven_req) { int ret; int pipe = 0; @@ -440,11 +440,11 @@ int cx231xx_write_ctrl_reg(struct cx231xx *dev, u8 req, u16 reg, char *buf, int byte; cx231xx_isocdbg("(pipe 0x%08x): " - "OUT: %02x %02x %02x %02x %02x %02x %02x %02x >>>", - pipe, - USB_DIR_OUT | USB_TYPE_VENDOR | - USB_RECIP_DEVICE, req, 0, val, reg & 0xff, - reg >> 8, len & 0xff, len >> 8); + "OUT: %02x %02x %02x %02x %02x %02x %02x %02x >>>", + pipe, + USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, + req, 0, val, reg & 0xff, + reg >> 8, len & 0xff, len >> 8); for (byte = 0; byte < len; byte++) cx231xx_isocdbg(" %02x", (unsigned char)buf[byte]); @@ -461,9 +461,9 @@ int cx231xx_write_ctrl_reg(struct cx231xx *dev, u8 req, u16 reg, char *buf, return ret; } -/************************************************************************************ -* USB Alternate Setting functions * -*************************************************************************************/ +/**************************************************************** +* USB Alternate Setting functions * +*****************************************************************/ int cx231xx_set_video_alternate(struct cx231xx *dev) { @@ -506,7 +506,7 @@ int cx231xx_set_video_alternate(struct cx231xx *dev) dev->video_mode.alt, dev->video_mode.max_pkt_size); cx231xx_info - (" setting alternate %d with wMaxPacketSize=%u , Interface = %d\n", + (" setting alt %d with wMaxPktSize=%u , Interface = %d\n", dev->video_mode.alt, dev->video_mode.max_pkt_size, usb_interface_index); errCode = @@ -514,7 +514,7 @@ int cx231xx_set_video_alternate(struct cx231xx *dev) dev->video_mode.alt); if (errCode < 0) { cx231xx_errdev - ("cannot change alternate number to %d (error=%i)\n", + ("cannot change alt number to %d (error=%i)\n", dev->video_mode.alt, errCode); return errCode; } @@ -588,8 +588,8 @@ int cx231xx_set_alt_setting(struct cx231xx *dev, u8 index, u8 alt) if (alt > 0 && max_pkt_size == 0) { cx231xx_errdev - ("cannot change interface %d alternate number to %d : Max. Pkt size is ZERO\n", - usb_interface_index, alt); + ("can't change interface %d alt no. to %d: Max. Pkt size = 0\n", + usb_interface_index, alt); return -1; } @@ -601,15 +601,14 @@ int cx231xx_set_alt_setting(struct cx231xx *dev, u8 index, u8 alt) status = usb_set_interface(dev->udev, usb_interface_index, alt); if (status < 0) { cx231xx_errdev - ("cannot change interface %d alternate number to %d (error=%i)\n", - usb_interface_index, alt, status); + ("can't change interface %d alt no. to %d (err=%i)\n", + usb_interface_index, alt, status); return status; } } return status; } - EXPORT_SYMBOL_GPL(cx231xx_set_alt_setting); int cx231xx_gpio_set(struct cx231xx *dev, struct cx231xx_reg_seq *gpio) @@ -649,19 +648,18 @@ int cx231xx_set_mode(struct cx231xx *dev, enum cx231xx_mode set_mode) dev->mode = set_mode; - if (dev->mode == CX231XX_DIGITAL_MODE) { - /* Set Digital power mode */ - } else { - /* Set Analog Power mode */ - } + if (dev->mode == CX231XX_DIGITAL_MODE) + ;/* Set Digital power mode */ + else + ;/* Set Analog Power mode */ + return 0; } - EXPORT_SYMBOL_GPL(cx231xx_set_mode); -/************************************************************************************ -* URB Streaming functions * -*************************************************************************************/ +/***************************************************************** +* URB Streaming functions * +******************************************************************/ /* * IRQ callback, called by URB callback @@ -751,7 +749,6 @@ void cx231xx_uninit_isoc(struct cx231xx *dev) cx231xx_capture_start(dev, 0, Raw_Video); } - EXPORT_SYMBOL_GPL(cx231xx_uninit_isoc); /* @@ -759,7 +756,7 @@ EXPORT_SYMBOL_GPL(cx231xx_uninit_isoc); */ int cx231xx_init_isoc(struct cx231xx *dev, int max_packets, int num_bufs, int max_pkt_size, - int (*isoc_copy) (struct cx231xx * dev, struct urb * urb)) + int (*isoc_copy) (struct cx231xx *dev, struct urb *urb)) { struct cx231xx_dmaqueue *dma_q = &dev->video_mode.vidq; int i; @@ -828,7 +825,7 @@ int cx231xx_init_isoc(struct cx231xx *dev, int max_packets, cx231xx_err("unable to allocate %i bytes for transfer" " buffer %i%s\n", sb_size, i, - in_interrupt()? " while in int" : ""); + in_interrupt() ? " while in int" : ""); cx231xx_uninit_isoc(dev); return -ENOMEM; } @@ -871,12 +868,11 @@ int cx231xx_init_isoc(struct cx231xx *dev, int max_packets, return 0; } - EXPORT_SYMBOL_GPL(cx231xx_init_isoc); -/************************************************************************************ -* Device Init/UnInit functions * -*************************************************************************************/ +/***************************************************************** +* Device Init/UnInit functions * +******************************************************************/ int cx231xx_dev_init(struct cx231xx *dev) { int errCode = 0; @@ -910,11 +906,12 @@ int cx231xx_dev_init(struct cx231xx *dev) cx231xx_i2c_register(&dev->i2c_bus[2]); /* init hardware */ - /* Note : with out calling set power mode function, colibri can not be set up correctly */ + /* Note : with out calling set power mode function, + colibri can not be set up correctly */ errCode = cx231xx_set_power_mode(dev, POLARIS_AVMODE_ANALOGT_TV); if (errCode < 0) { cx231xx_errdev - ("%s: cx231xx_set_power_mode : Failed to set Power - errCode [%d]!\n", + ("%s: Failed to set Power - errCode [%d]!\n", __func__, errCode); return errCode; } @@ -982,7 +979,6 @@ int cx231xx_dev_init(struct cx231xx *dev) return errCode; } - EXPORT_SYMBOL_GPL(cx231xx_dev_init); void cx231xx_dev_uninit(struct cx231xx *dev) @@ -992,17 +988,16 @@ void cx231xx_dev_uninit(struct cx231xx *dev) cx231xx_i2c_unregister(&dev->i2c_bus[1]); cx231xx_i2c_unregister(&dev->i2c_bus[0]); } - EXPORT_SYMBOL_GPL(cx231xx_dev_uninit); -/************************************************************************************ -* G P I O related functions * -*************************************************************************************/ +/***************************************************************** +* G P I O related functions * +******************************************************************/ int cx231xx_send_gpio_cmd(struct cx231xx *dev, u32 gpio_bit, u8 * gpio_val, u8 len, u8 request, u8 direction) { int status = 0; - VENDOR_REQUEST_IN ven_req; + struct VENDOR_REQUEST_IN ven_req; /* Set wValue */ ven_req.wValue = (u16) (gpio_bit >> 16 & 0xffff); @@ -1052,18 +1047,17 @@ int cx231xx_send_gpio_cmd(struct cx231xx *dev, u32 gpio_bit, u8 * gpio_val, status = cx231xx_send_vendor_cmd(dev, &ven_req); if (status < 0) { cx231xx_info - ("UsbInterface::sendCommand, output buffer failed with status -%d\n", + ("UsbInterface::sendCommand, failed with status -%d\n", status); } return status; } - EXPORT_SYMBOL_GPL(cx231xx_send_gpio_cmd); -/************************************************************************************* - * C O N T R O L - Register R E A D / W R I T E functions * - *************************************************************************************/ +/***************************************************************** + * C O N T R O L - Register R E A D / W R I T E functions * + *****************************************************************/ int cx231xx_mode_register(struct cx231xx *dev, u16 address, u32 mode) { u8 value[4] = { 0x0, 0x0, 0x0, 0x0 }; @@ -1089,11 +1083,11 @@ int cx231xx_mode_register(struct cx231xx *dev, u16 address, u32 mode) return status; } -/************************************************************************************* - * I 2 C Internal C O N T R O L functions * - *************************************************************************************/ +/***************************************************************** + * I 2 C Internal C O N T R O L functions * + *****************************************************************/ int cx231xx_read_i2c_data(struct cx231xx *dev, u8 dev_addr, u16 saddr, - u8 saddr_len, u32 * data, u8 data_len) + u8 saddr_len, u32 *data, u8 data_len) { int status = 0; struct cx231xx_i2c_xfer_data req_data; @@ -1168,9 +1162,8 @@ int cx231xx_reg_mask_write(struct cx231xx *dev, u8 dev_addr, u8 size, u32 mask = 0; int i; - if (bit_start > (size - 1) || bit_end > (size - 1)) { + if (bit_start > (size - 1) || bit_end > (size - 1)) return -1; - } if (size == 8) { status = @@ -1182,14 +1175,12 @@ int cx231xx_reg_mask_write(struct cx231xx *dev, u8 dev_addr, u8 size, &tmp, 4); } - if (status < 0) { + if (status < 0) return status; - } mask = 1 << bit_end; - for (i = bit_end; i > bit_start && i > 0; i--) { + for (i = bit_end; i > bit_start && i > 0; i--) mask = mask + (1 << (i - 1)); - } value <<= bit_start; @@ -1234,9 +1225,8 @@ u32 cx231xx_set_field(u32 field_mask, u32 data) { u32 temp; - for (temp = field_mask; (temp & 1) == 0; temp >>= 1) { + for (temp = field_mask; (temp & 1) == 0; temp >>= 1) data <<= 1; - } return data; } diff --git a/linux/drivers/media/video/cx231xx/cx231xx-dvb.c b/linux/drivers/media/video/cx231xx/cx231xx-dvb.c index fcf197e99..9ff097055 100644 --- a/linux/drivers/media/video/cx231xx/cx231xx-dvb.c +++ b/linux/drivers/media/video/cx231xx/cx231xx-dvb.c @@ -2,7 +2,7 @@ DVB device driver for cx231xx Copyright (C) 2008 - Based on em28xx driver + Based on em28xx driver 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 @@ -396,20 +396,20 @@ static int register_dvb(struct cx231xx_dvb *dvb, dvb_net_init(&dvb->adapter, &dvb->net, &dvb->demux.dmx); return 0; - fail_fe_conn: +fail_fe_conn: dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_mem); - fail_fe_mem: +fail_fe_mem: dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_hw); - fail_fe_hw: +fail_fe_hw: dvb_dmxdev_release(&dvb->dmxdev); - fail_dmxdev: +fail_dmxdev: dvb_dmx_release(&dvb->demux); - fail_dmx: +fail_dmx: dvb_unregister_frontend(dvb->frontend); - fail_frontend: +fail_frontend: dvb_frontend_detach(dvb->frontend); dvb_unregister_adapter(&dvb->adapter); - fail_adapter: +fail_adapter: return result; } @@ -517,7 +517,7 @@ static int dvb_init(struct cx231xx *dev) printk(KERN_INFO "Successfully loaded cx231xx-dvb\n"); return 0; - out_free: +out_free: cx231xx_set_mode(dev, CX231XX_SUSPEND); kfree(dvb); dev->dvb = NULL; diff --git a/linux/drivers/media/video/cx231xx/cx231xx-i2c.c b/linux/drivers/media/video/cx231xx/cx231xx-i2c.c index 54b044a07..1d64f913a 100644 --- a/linux/drivers/media/video/cx231xx/cx231xx-i2c.c +++ b/linux/drivers/media/video/cx231xx/cx231xx-i2c.c @@ -2,8 +2,8 @@ cx231xx-i2c.c - driver for Conexant Cx23100/101/102 USB video capture devices Copyright (C) 2008 - Based on em28xx driver - Based on Cx23885 driver + Based on em28xx driver + Based on Cx23885 driver 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 @@ -42,8 +42,8 @@ MODULE_PARM_DESC(i2c_debug, "enable debug messages [i2c]"); #define dprintk1(lvl, fmt, args...) \ do { \ if (i2c_debug >= lvl) { \ - printk(fmt, ##args); \ - } \ + printk(fmt, ##args); \ + } \ } while (0) #define dprintk2(lvl, fmt, args...) \ @@ -78,8 +78,8 @@ int cx231xx_i2c_send_bytes(struct i2c_adapter *i2c_adap, if (size == 2) { /* register write sub addr */ - /* Just writing sub address will cause problem to XC5000 - So ignore the request */ + /* Just writing sub address will cause problem to XC5000 + So ignore the request */ return 0; } else if (size == 4) { /* register write with sub addr */ @@ -92,7 +92,8 @@ int cx231xx_i2c_send_bytes(struct i2c_adapter *i2c_adap, switch (saddr) { case 0x0000: /* start tuner calibration mode */ need_gpio = 1; - dev->xc_fw_load_done = 1; /* FW Loading is done */ + /* FW Loading is done */ + dev->xc_fw_load_done = 1; break; case 0x000D: /* Set signal source */ case 0x0001: /* Set TV standard - Video */ @@ -108,8 +109,8 @@ int cx231xx_i2c_send_bytes(struct i2c_adapter *i2c_adap, if (need_gpio) { dprintk1(1, - " GPIO W R I T E : addr 0x%x, len %d, saddr 0x%x\n", - msg->addr, msg->len, saddr); + "GPIO WRITE: addr 0x%x, len %d, saddr 0x%x\n", + msg->addr, msg->len, saddr); return dev->cx231xx_gpio_i2c_write(dev, msg->addr, @@ -196,8 +197,8 @@ static int cx231xx_i2c_recv_bytes(struct i2c_adapter *i2c_adap, switch (saddr) { case 0x0009: /* BUSY check */ dprintk1(1, - " GPIO R E A D : Special case BUSY check \n"); - /* Try to read BUSY register, just set it to zero */ + "GPIO R E A D: Special case BUSY check \n"); + /*Try read BUSY register, just set it to zero*/ msg->buf[0] = 0; if (msg->len == 2) msg->buf[1] = 0; @@ -209,12 +210,14 @@ static int cx231xx_i2c_recv_bytes(struct i2c_adapter *i2c_adap, } if (need_gpio) { - /* this is a special case to handle Xceive tuner clock stretch issue - with gpio based I2C interface */ + /* this is a special case to handle Xceive tuner + clock stretch issue with gpio based I2C */ + dprintk1(1, - " GPIO R E A D : addr 0x%x, len %d, saddr 0x%x\n", - msg->addr, msg->len, - msg->buf[0] << 8 | msg->buf[1]); + "GPIO R E A D: addr 0x%x, len %d, saddr 0x%x\n", + msg->addr, msg->len, + msg->buf[0] << 8 | msg->buf[1]); + status = dev->cx231xx_gpio_i2c_write(dev, msg->addr, msg->buf, @@ -281,8 +284,8 @@ static int cx231xx_i2c_recv_bytes_with_saddr(struct i2c_adapter *i2c_adap, if ((msg2->len < 16)) { dprintk1(1, - " i2c_read : addr 0x%x, len %d, subaddr 0x%x, leng %d\n", - msg2->addr, msg2->len, saddr, msg1->len); + "i2c_read: addr 0x%x, len %d, saddr 0x%x, len %d\n", + msg2->addr, msg2->len, saddr, msg1->len); switch (saddr) { case 0x0008: /* read FW load status */ @@ -368,7 +371,8 @@ static int cx231xx_i2c_xfer(struct i2c_adapter *i2c_adap, dprintk2(2, "%s %s addr=%x len=%d:", (msgs[i].flags & I2C_M_RD) ? "read" : "write", i == num - 1 ? "stop" : "nonstop", addr, msgs[i].len); - if (!msgs[i].len) { /* no len: check only for device presence */ + if (!msgs[i].len) { + /* no len: check only for device presence */ rc = cx231xx_i2c_check_for_device(i2c_adap, &msgs[i]); if (rc < 0) { dprintk2(2, " no device\n"); @@ -409,7 +413,7 @@ static int cx231xx_i2c_xfer(struct i2c_adapter *i2c_adap, } return num; - err: +err: dprintk2(2, " ERROR: %i\n", rc); return rc; } diff --git a/linux/drivers/media/video/cx231xx/cx231xx-input.c b/linux/drivers/media/video/cx231xx/cx231xx-input.c index 32291630f..04d954cca 100644 --- a/linux/drivers/media/video/cx231xx/cx231xx-input.c +++ b/linux/drivers/media/video/cx231xx/cx231xx-input.c @@ -2,9 +2,9 @@ handle cx231xx IR remotes via linux kernel input layer. Copyright (C) 2008 - Based on em28xx driver + Based on em28xx driver - < This is a place holder for IR now.> + < This is a place holder for IR now.> 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 @@ -236,10 +236,10 @@ int cx231xx_ir_init(struct cx231xx *dev) goto err_out_stop; return 0; - err_out_stop: +err_out_stop: cx231xx_ir_stop(ir); dev->ir = NULL; - err_out_free: +err_out_free: input_free_device(input_dev); kfree(ir); return err; diff --git a/linux/drivers/media/video/cx231xx/cx231xx-reg.h b/linux/drivers/media/video/cx231xx/cx231xx-reg.h index 7c8ba4e05..d2d325b21 100644 --- a/linux/drivers/media/video/cx231xx/cx231xx-reg.h +++ b/linux/drivers/media/video/cx231xx/cx231xx-reg.h @@ -1,5 +1,6 @@ /* - cx231xx-reg.h - driver for Conexant Cx23100/101/102 USB video capture devices + cx231xx-reg.h - driver for Conexant Cx23100/101/102 + USB video capture devices Copyright (C) 2008 @@ -22,7 +23,7 @@ #define _CX231XX_REG_H /***************************************************************************** - * VBI codes * + * VBI codes * *****************************************************************************/ #define SAV_ACTIVE_VIDEO_FIELD1 0x80 @@ -1533,13 +1534,13 @@ #define INPUT_MODE_YC2_2 2 /* INPUT_MODE_VALUE(2) */ #define INPUT_MODE_YUV_3 3 /* INPUT_MODE_VALUE(3) */ -#define LUMA_LPF_LOW_BANDPASS 0 /* 0.6Mhz lowpass filter bandwidth */ -#define LUMA_LPF_MEDIUM_BANDPASS 1 /* 1.0Mhz lowpass filter bandwidth */ -#define LUMA_LPF_HIGH_BANDPASS 2 /* 1.5Mhz lowpass filter bandwidth */ +#define LUMA_LPF_LOW_BANDPASS 0 /* 0.6Mhz LPF BW */ +#define LUMA_LPF_MEDIUM_BANDPASS 1 /* 1.0Mhz LPF BW */ +#define LUMA_LPF_HIGH_BANDPASS 2 /* 1.5Mhz LPF BW */ -#define UV_LPF_LOW_BANDPASS 0 /* 0.6Mhz lowpass filter bandwidth */ -#define UV_LPF_MEDIUM_BANDPASS 1 /* 1.0Mhz lowpass filter bandwidth */ -#define UV_LPF_HIGH_BANDPASS 2 /* 1.5Mhz lowpass filter bandwidth */ +#define UV_LPF_LOW_BANDPASS 0 /* 0.6Mhz LPF BW */ +#define UV_LPF_MEDIUM_BANDPASS 1 /* 1.0Mhz LPF BW */ +#define UV_LPF_HIGH_BANDPASS 2 /* 1.5Mhz LPF BW */ #define TWO_TAP_FILT 0 #define THREE_TAP_FILT 1 diff --git a/linux/drivers/media/video/cx231xx/cx231xx-vbi.c b/linux/drivers/media/video/cx231xx/cx231xx-vbi.c index de78ce140..9080d1755 100644 --- a/linux/drivers/media/video/cx231xx/cx231xx-vbi.c +++ b/linux/drivers/media/video/cx231xx/cx231xx-vbi.c @@ -140,23 +140,24 @@ static inline int cx231xx_isoc_vbi_copy(struct cx231xx *dev, struct urb *urb) while (bytes_parsed < buffer_size) { u32 bytes_used = 0; - sav_eav = cx231xx_find_next_SAV_EAV(p_buffer + bytes_parsed, /* p_buffer */ - buffer_size - bytes_parsed, /* buffer size */ - &bytes_used); /* Receives bytes used to get SAV/EAV */ + sav_eav = cx231xx_find_next_SAV_EAV( + p_buffer + bytes_parsed, /* p_buffer */ + buffer_size - bytes_parsed, /* buffer size */ + &bytes_used); /* bytes used to get SAV/EAV */ bytes_parsed += bytes_used; sav_eav &= 0xF0; if (sav_eav && (bytes_parsed < buffer_size)) { bytes_parsed += cx231xx_get_vbi_line(dev, - dma_q, sav_eav, /* SAV/EAV */ - p_buffer + bytes_parsed, /* p_buffer */ - buffer_size - bytes_parsed); /* buffer size */ + dma_q, sav_eav, /* SAV/EAV */ + p_buffer+bytes_parsed, /* p_buffer */ + buffer_size-bytes_parsed);/*buf size*/ } } - /* Save the last four bytes of the buffer so we can check the buffer boundary - condition next time */ + /* Save the last four bytes of the buffer so we can + check the buffer boundary condition next time */ memcpy(dma_q->partial_buf, p_buffer + buffer_size - 4, 4); bytes_parsed = 0; } diff --git a/linux/drivers/media/video/cx231xx/cx231xx-vbi.h b/linux/drivers/media/video/cx231xx/cx231xx-vbi.h index c0d89b1e2..89c7fe80b 100644 --- a/linux/drivers/media/video/cx231xx/cx231xx-vbi.h +++ b/linux/drivers/media/video/cx231xx/cx231xx-vbi.h @@ -2,7 +2,7 @@ cx231xx_vbi.h - driver for Conexant Cx23100/101/102 USB video capture devices Copyright (C) 2008 - Based on cx88 driver + Based on cx88 driver 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 @@ -24,16 +24,16 @@ extern struct videobuf_queue_ops cx231xx_vbi_qops; -#define NTSC_VBI_START_LINE 10 /* line 10 - 21 */ -#define NTSC_VBI_END_LINE 21 -#define NTSC_VBI_LINES (NTSC_VBI_END_LINE - NTSC_VBI_START_LINE + 1) +#define NTSC_VBI_START_LINE 10 /* line 10 - 21 */ +#define NTSC_VBI_END_LINE 21 +#define NTSC_VBI_LINES (NTSC_VBI_END_LINE-NTSC_VBI_START_LINE+1) -#define PAL_VBI_START_LINE 6 -#define PAL_VBI_END_LINE 23 -#define PAL_VBI_LINES (PAL_VBI_END_LINE - PAL_VBI_START_LINE + 1) +#define PAL_VBI_START_LINE 6 +#define PAL_VBI_END_LINE 23 +#define PAL_VBI_LINES (PAL_VBI_END_LINE-PAL_VBI_START_LINE+1) -#define VBI_STRIDE 1440 -#define VBI_SAMPLES_PER_LINE 1440 +#define VBI_STRIDE 1440 +#define VBI_SAMPLES_PER_LINE 1440 #define CX231XX_NUM_VBI_PACKETS 4 #define CX231XX_NUM_VBI_BUFS 5 @@ -41,21 +41,23 @@ extern struct videobuf_queue_ops cx231xx_vbi_qops; /* stream functions */ int cx231xx_init_vbi_isoc(struct cx231xx *dev, int max_packets, int num_bufs, int max_pkt_size, - int (*isoc_copy) (struct cx231xx * dev, - struct urb * urb)); + int (*isoc_copy) (struct cx231xx *dev, + struct urb *urb)); void cx231xx_uninit_vbi_isoc(struct cx231xx *dev); /* vbi data copy functions */ u32 cx231xx_get_vbi_line(struct cx231xx *dev, struct cx231xx_dmaqueue *dma_q, - u8 sav_eav, u8 * p_buffer, u32 buffer_size); + u8 sav_eav, u8 *p_buffer, u32 buffer_size); + u32 cx231xx_copy_vbi_line(struct cx231xx *dev, struct cx231xx_dmaqueue *dma_q, - u8 * p_line, u32 length, int field_number); + u8 *p_line, u32 length, int field_number); + void cx231xx_reset_vbi_buffer(struct cx231xx *dev, struct cx231xx_dmaqueue *dma_q); int cx231xx_do_vbi_copy(struct cx231xx *dev, struct cx231xx_dmaqueue *dma_q, - u8 * p_buffer, u32 bytes_to_copy); + u8 *p_buffer, u32 bytes_to_copy); u8 cx231xx_is_vbi_buffer_done(struct cx231xx *dev, struct cx231xx_dmaqueue *dma_q); diff --git a/linux/drivers/media/video/cx231xx/cx231xx-video.c b/linux/drivers/media/video/cx231xx/cx231xx-video.c index 025569d81..3cf1f23ff 100644 --- a/linux/drivers/media/video/cx231xx/cx231xx-video.c +++ b/linux/drivers/media/video/cx231xx/cx231xx-video.c @@ -363,10 +363,11 @@ static inline int cx231xx_isoc_copy(struct cx231xx *dev, struct urb *urb) bytes_parsed = 0; if (dma_q->is_partial_line) { - /* Handle the case where we were working on a partial line */ + /* Handle the case of a partial line */ sav_eav = dma_q->last_sav; } else { - /* Check for a SAV/EAV overlapping the buffer boundary */ + /* Check for a SAV/EAV overlapping + the buffer boundary */ sav_eav = cx231xx_find_boundary_SAV_EAV(p_buffer, dma_q->partial_buf, @@ -378,9 +379,9 @@ static inline int cx231xx_isoc_copy(struct cx231xx *dev, struct urb *urb) the last buffer or a partial line */ if (sav_eav) { bytes_parsed += cx231xx_get_video_line(dev, dma_q, - sav_eav, /* SAV/EAV */ - p_buffer + bytes_parsed, /* p_buffer */ - buffer_size - bytes_parsed); /* buffer size */ + sav_eav, /* SAV/EAV */ + p_buffer + bytes_parsed, /* p_buffer */ + buffer_size - bytes_parsed);/* buf size */ } /* Now parse data that is completely in this buffer */ @@ -389,18 +390,19 @@ static inline int cx231xx_isoc_copy(struct cx231xx *dev, struct urb *urb) while (bytes_parsed < buffer_size) { u32 bytes_used = 0; - sav_eav = cx231xx_find_next_SAV_EAV(p_buffer + bytes_parsed, /* p_buffer */ - buffer_size - bytes_parsed, /* buffer size */ - &bytes_used); /* Receives bytes used to get SAV/EAV */ + sav_eav = cx231xx_find_next_SAV_EAV( + p_buffer + bytes_parsed, /* p_buffer */ + buffer_size - bytes_parsed, /* buf size */ + &bytes_used);/* bytes used to get SAV/EAV */ bytes_parsed += bytes_used; sav_eav &= 0xF0; if (sav_eav && (bytes_parsed < buffer_size)) { bytes_parsed += cx231xx_get_video_line(dev, - dma_q, sav_eav, /* SAV/EAV */ - p_buffer + bytes_parsed, /* p_buffer */ - buffer_size - bytes_parsed); /* buffer size */ + dma_q, sav_eav, /* SAV/EAV */ + p_buffer + bytes_parsed,/* p_buffer */ + buffer_size - bytes_parsed);/*buf size*/ } } @@ -1396,9 +1398,11 @@ static int vidioc_s_frequency(struct file *file, void *priv, #ifdef CONFIG_VIDEO_ADV_DEBUG /* - -R, --list-registers=type=,chip=[,min=,max=] + -R, --list-registers=type=, + chip=[,min=,max=] dump registers from to [VIDIOC_DBG_G_REGISTER] - -r, --set-register=type=,chip=,reg=,val= + -r, --set-register=type=, + chip=,reg=,val= set the register [VIDIOC_DBG_S_REGISTER] if type == host, then is the hosts chip ID (default 0) @@ -2330,8 +2334,9 @@ static struct video_device cx231xx_radio_template = { /******************************** usb interface ******************************/ -static struct video_device *cx231xx_vdev_init(struct cx231xx *dev, const struct video_device - *template, const char *type_name) +static struct video_device *cx231xx_vdev_init(struct cx231xx *dev, + const struct video_device + *template, const char *type_name) { struct video_device *vfd; diff --git a/linux/drivers/media/video/cx231xx/cx231xx.h b/linux/drivers/media/video/cx231xx/cx231xx.h index 67ecff8e5..0783fb2c3 100644 --- a/linux/drivers/media/video/cx231xx/cx231xx.h +++ b/linux/drivers/media/video/cx231xx/cx231xx.h @@ -30,7 +30,8 @@ #include #include #include -#if defined(CONFIG_VIDEO_CX231XX_DVB) || defined(CONFIG_VIDEO_CX231XX_DVB_MODULE) +#if defined(CONFIG_VIDEO_CX231XX_DVB) || \ + defined(CONFIG_VIDEO_CX231XX_DVB_MODULE) #include #endif @@ -89,7 +90,8 @@ #define CX231XX_INTERLACED_DEFAULT 1 /* time to wait when stopping the isoc transfer */ -#define CX231XX_URB_TIMEOUT msecs_to_jiffies(CX231XX_NUM_BUFS * CX231XX_NUM_PACKETS) +#define CX231XX_URB_TIMEOUT \ + msecs_to_jiffies(CX231XX_NUM_BUFS * CX231XX_NUM_PACKETS) enum cx231xx_mode { CX231XX_SUSPEND, @@ -233,12 +235,12 @@ enum cx231xx_decoder { CX231XX_AVDECODER }; -typedef enum _I2C_MASTER_PORT { +enum CX231XX_I2C_MASTER_PORT { I2C_0 = 0, I2C_1 = 1, I2C_2 = 2, I2C_3 = 3 -} CX231XX_I2C_MASTER_PORT; +}; struct cx231xx_board { char *name; @@ -356,16 +358,20 @@ struct cx231xx_fh { enum v4l2_buf_type type; }; -/**********************************************************************************/ +/*****************************************************************/ /* set/get i2c */ -#define I2C_SPEED_1M 0x0 /* 00--1Mb/s, 01-400kb/s, 10--100kb/s, 11--5Mb/s */ -#define I2C_SPEED_400K 0x1 /* 00--1Mb/s, 01-400kb/s, 10--100kb/s, 11--5Mb/s */ -#define I2C_SPEED_100K 0x2 /* 00--1Mb/s, 01-400kb/s, 10--100kb/s, 11--5Mb/s */ -#define I2C_SPEED_5M 0x3 /* 00--1Mb/s, 01-400kb/s, 10--100kb/s, 11--5Mb/s */ - -#define I2C_STOP 0x0 /* 0-- STOP transaction */ -#define I2C_NOSTOP 0x1 /* 1-- do not transmit STOP at end of transaction */ -#define I2C_SYNC 0x1 /* 1--alllow slave to insert clock wait states */ +/* 00--1Mb/s, 01-400kb/s, 10--100kb/s, 11--5Mb/s */ +#define I2C_SPEED_1M 0x0 +#define I2C_SPEED_400K 0x1 +#define I2C_SPEED_100K 0x2 +#define I2C_SPEED_5M 0x3 + +/* 0-- STOP transaction */ +#define I2C_STOP 0x0 +/* 1-- do not transmit STOP at end of transaction */ +#define I2C_NOSTOP 0x1 +/* 1--alllow slave to insert clock wait states */ +#define I2C_SYNC 0x1 struct cx231xx_i2c { struct cx231xx *dev; @@ -393,7 +399,7 @@ struct cx231xx_i2c_xfer_data { u8 *p_buffer; /* pointer to the buffer */ }; -typedef struct _VENDOR_REQUEST_IN { +struct VENDOR_REQUEST_IN{ u8 bRequest; u16 wValue; u16 wIndex; @@ -401,7 +407,7 @@ typedef struct _VENDOR_REQUEST_IN { u8 direction; u8 bData; u8 *pBuff; -} VENDOR_REQUEST_IN, *PVENDOR_REQUEST_IN; +}; struct cx231xx_ctrl { struct v4l2_queryctrl v; @@ -411,7 +417,7 @@ struct cx231xx_ctrl { u32 shift; }; -typedef enum { +enum TRANSFER_TYPE{ Raw_Video = 0, Audio, Vbi, /* VANC */ @@ -419,7 +425,7 @@ typedef enum { TS1_serial_mode, TS2, TS1_parallel_mode -} TRANSFER_TYPE; +} ; struct cx231xx_video_mode { /* Isoc control struct */ @@ -510,7 +516,7 @@ struct cx231xx { int (*cx231xx_write_ctrl_reg) (struct cx231xx *dev, u8 req, u16 reg, char *buf, int len); int (*cx231xx_send_usb_command) (struct cx231xx_i2c *i2c_bus, - struct cx231xx_i2c_xfer_data *req_data); + struct cx231xx_i2c_xfer_data *req_data); int (*cx231xx_gpio_i2c_read) (struct cx231xx *dev, u8 dev_addr, u8 *buf, u8 len); int (*cx231xx_gpio_i2c_write) (struct cx231xx *dev, u8 dev_addr, @@ -631,9 +637,10 @@ int cx231xx_write_ctrl_reg(struct cx231xx *dev, u8 req, u16 reg, char *buf, int len); int cx231xx_mode_register(struct cx231xx *dev, u16 address, u32 mode); -int cx231xx_send_vendor_cmd(struct cx231xx *dev, VENDOR_REQUEST_IN *ven_req); +int cx231xx_send_vendor_cmd(struct cx231xx *dev, + struct VENDOR_REQUEST_IN *ven_req); int cx231xx_send_usb_command(struct cx231xx_i2c *i2c_bus, - struct cx231xx_i2c_xfer_data *req_data); + struct cx231xx_i2c_xfer_data *req_data); /* Gpio related functions */ int cx231xx_send_gpio_cmd(struct cx231xx *dev, u32 gpio_bit, u8 *gpio_val, -- cgit v1.2.3 From 2b325438911b426807991cb0cbe94fa3c30d087c Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 6 Mar 2009 13:29:09 +0100 Subject: tvmixer: remove last remaining references to this deleted module. From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/Makefile | 1 - 1 file changed, 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/Makefile b/linux/drivers/media/video/Makefile index 307490ebc..08a0675fe 100644 --- a/linux/drivers/media/video/Makefile +++ b/linux/drivers/media/video/Makefile @@ -30,7 +30,6 @@ obj-$(CONFIG_VIDEO_IR_I2C) += ir-kbd-i2c.o obj-$(CONFIG_VIDEO_TVAUDIO) += tvaudio.o obj-$(CONFIG_VIDEO_TDA7432) += tda7432.o obj-$(CONFIG_VIDEO_TDA9875) += tda9875.o -obj-$(CONFIG_SOUND_TVMIXER) += tvmixer.o obj-$(CONFIG_VIDEO_SAA6588) += saa6588.o obj-$(CONFIG_VIDEO_SAA5246A) += saa5246a.o -- cgit v1.2.3 From 6313f620a8d129514b70eafb0f73e93e50fba02a Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 6 Mar 2009 13:55:42 +0100 Subject: videodev2.h: remove deprecated VIDIOC_G_CHIP_IDENT_OLD From: Hans Verkuil As announced VIDIOC_G_CHIP_IDENT_OLD is now removed for 2.6.30. Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/v4l2-compat-ioctl32.c | 1 - linux/drivers/media/video/v4l2-ioctl.c | 5 ----- 2 files changed, 6 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/v4l2-compat-ioctl32.c b/linux/drivers/media/video/v4l2-compat-ioctl32.c index 05a356776..d9cee38cd 100644 --- a/linux/drivers/media/video/v4l2-compat-ioctl32.c +++ b/linux/drivers/media/video/v4l2-compat-ioctl32.c @@ -1052,7 +1052,6 @@ long v4l2_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg) case VIDIOC_DBG_S_REGISTER: case VIDIOC_DBG_G_REGISTER: case VIDIOC_DBG_G_CHIP_IDENT: - case VIDIOC_G_CHIP_IDENT_OLD: case VIDIOC_S_HW_FREQ_SEEK: ret = do_video_ioctl(file, cmd, arg); break; diff --git a/linux/drivers/media/video/v4l2-ioctl.c b/linux/drivers/media/video/v4l2-ioctl.c index e079a343a..fa7d49482 100644 --- a/linux/drivers/media/video/v4l2-ioctl.c +++ b/linux/drivers/media/video/v4l2-ioctl.c @@ -1706,11 +1706,6 @@ static long __video_do_ioctl(struct file *file, dbgarg(cmd, "chip_ident=%u, revision=0x%x\n", p->ident, p->revision); break; } - case VIDIOC_G_CHIP_IDENT_OLD: - printk(KERN_ERR "VIDIOC_G_CHIP_IDENT has been deprecated and will disappear in 2.6.30.\n"); - printk(KERN_ERR "It is a debugging ioctl and must not be used in applications!\n"); - return -EINVAL; - case VIDIOC_S_HW_FREQ_SEEK: { struct v4l2_hw_freq_seek *p = arg; -- cgit v1.2.3 From f34cf596ba7f91a95e60b60a9058f42ae7fb84de Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 6 Mar 2009 13:56:49 +0100 Subject: zl10036: fix compile warning on kernel 2.6.23. From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/dvb/frontends/zl10036.c | 1 + 1 file changed, 1 insertion(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/frontends/zl10036.c b/linux/drivers/media/dvb/frontends/zl10036.c index e22a0b381..67cdb056f 100644 --- a/linux/drivers/media/dvb/frontends/zl10036.c +++ b/linux/drivers/media/dvb/frontends/zl10036.c @@ -30,6 +30,7 @@ #include #include #include +#include "compat.h" #include "zl10036.h" -- cgit v1.2.3 From 5504a83e1c3b04b1845eb63484a301738919372a Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 6 Mar 2009 13:58:12 +0100 Subject: vivi: fix compile warning. From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/vivi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/vivi.c b/linux/drivers/media/video/vivi.c index 76f7dfc32..e853547c4 100644 --- a/linux/drivers/media/video/vivi.c +++ b/linux/drivers/media/video/vivi.c @@ -1413,7 +1413,7 @@ free_dev: */ static int __init vivi_init(void) { - int ret, i; + int ret = 0, i; if (n_devs <= 0) n_devs = 1; -- cgit v1.2.3 From 8ff9ed6b3df6436c1f12119309667c3621c08bab Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 6 Mar 2009 14:15:01 +0100 Subject: v4l2: fix compile warnings when printing u64 value. From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/adv7170.c | 7 ++++--- linux/drivers/media/video/adv7175.c | 5 +++-- linux/drivers/media/video/bt819.c | 5 +++-- linux/drivers/media/video/bt856.c | 2 +- linux/drivers/media/video/bt866.c | 2 +- linux/drivers/media/video/ks0127.c | 4 ++-- linux/drivers/media/video/saa7110.c | 2 +- linux/drivers/media/video/vpx3220.c | 2 +- 8 files changed, 16 insertions(+), 13 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/adv7170.c b/linux/drivers/media/video/adv7170.c index 87bc8ed46..04e6125f2 100644 --- a/linux/drivers/media/video/adv7170.c +++ b/linux/drivers/media/video/adv7170.c @@ -205,7 +205,7 @@ static int adv7170_s_std_output(struct v4l2_subdev *sd, v4l2_std_id std) { struct adv7170 *encoder = to_adv7170(sd); - v4l2_dbg(1, debug, sd, "set norm %llx\n", std); + v4l2_dbg(1, debug, sd, "set norm %llx\n", (unsigned long long)std); if (std & V4L2_STD_NTSC) { adv7170_write_block(sd, init_NTSC, sizeof(init_NTSC)); @@ -220,10 +220,11 @@ static int adv7170_s_std_output(struct v4l2_subdev *sd, v4l2_std_id std) adv7170_write(sd, 0x07, TR0MODE | TR0RST); adv7170_write(sd, 0x07, TR0MODE); } else { - v4l2_dbg(1, debug, sd, "illegal norm: %llx\n", std); + v4l2_dbg(1, debug, sd, "illegal norm: %llx\n", + (unsigned long long)std); return -EINVAL; } - v4l2_dbg(1, debug, sd, "switched to %llx\n", std); + v4l2_dbg(1, debug, sd, "switched to %llx\n", (unsigned long long)std); encoder->norm = std; return 0; } diff --git a/linux/drivers/media/video/adv7175.c b/linux/drivers/media/video/adv7175.c index dc036d2fa..c38f648f8 100644 --- a/linux/drivers/media/video/adv7175.c +++ b/linux/drivers/media/video/adv7175.c @@ -238,10 +238,11 @@ static int adv7175_s_std_output(struct v4l2_subdev *sd, v4l2_std_id std) adv7175_write(sd, 0x07, TR0MODE | TR0RST); adv7175_write(sd, 0x07, TR0MODE); } else { - v4l2_dbg(1, debug, sd, "illegal norm: %llx\n", std); + v4l2_dbg(1, debug, sd, "illegal norm: %llx\n", + (unsigned long long)std); return -EINVAL; } - v4l2_dbg(1, debug, sd, "switched to %llx\n", std); + v4l2_dbg(1, debug, sd, "switched to %llx\n", (unsigned long long)std); encoder->norm = std; return 0; } diff --git a/linux/drivers/media/video/bt819.c b/linux/drivers/media/video/bt819.c index ec64197e9..9f9596c7c 100644 --- a/linux/drivers/media/video/bt819.c +++ b/linux/drivers/media/video/bt819.c @@ -254,7 +254,7 @@ static int bt819_s_std(struct v4l2_subdev *sd, v4l2_std_id std) struct bt819 *decoder = to_bt819(sd); struct timing *timing = NULL; - v4l2_dbg(1, debug, sd, "set norm %llx\n", std); + v4l2_dbg(1, debug, sd, "set norm %llx\n", (unsigned long long)std); if (std & V4L2_STD_NTSC) { bt819_setbit(decoder, 0x01, 0, 1); @@ -273,7 +273,8 @@ static int bt819_s_std(struct v4l2_subdev *sd, v4l2_std_id std) /* bt819_setbit(decoder, 0x1a, 5, 0); */ timing = &timing_data[0]; } else { - v4l2_dbg(1, debug, sd, "unsupported norm %llx\n", std); + v4l2_dbg(1, debug, sd, "unsupported norm %llx\n", + (unsigned long long)std); return -EINVAL; } bt819_write(decoder, 0x03, diff --git a/linux/drivers/media/video/bt856.c b/linux/drivers/media/video/bt856.c index fc7b64d91..ab56d7d6e 100644 --- a/linux/drivers/media/video/bt856.c +++ b/linux/drivers/media/video/bt856.c @@ -131,7 +131,7 @@ static int bt856_s_std_output(struct v4l2_subdev *sd, v4l2_std_id std) { struct bt856 *encoder = to_bt856(sd); - v4l2_dbg(1, debug, sd, "set norm %llx\n", std); + v4l2_dbg(1, debug, sd, "set norm %llx\n", (unsigned long long)std); if (std & V4L2_STD_NTSC) { bt856_setbit(encoder, 0xdc, 2, 0); diff --git a/linux/drivers/media/video/bt866.c b/linux/drivers/media/video/bt866.c index edc1aa348..5ea31375e 100644 --- a/linux/drivers/media/video/bt866.c +++ b/linux/drivers/media/video/bt866.c @@ -97,7 +97,7 @@ static int bt866_write(struct bt866 *encoder, u8 subaddr, u8 data) static int bt866_s_std_output(struct v4l2_subdev *sd, v4l2_std_id std) { - v4l2_dbg(1, debug, sd, "set norm %llx\n", std); + v4l2_dbg(1, debug, sd, "set norm %llx\n", (unsigned long long)std); /* Only PAL supported by this driver at the moment! */ if (!(std & V4L2_STD_NTSC)) diff --git a/linux/drivers/media/video/ks0127.c b/linux/drivers/media/video/ks0127.c index eaa481a57..3dbda6e92 100644 --- a/linux/drivers/media/video/ks0127.c +++ b/linux/drivers/media/video/ks0127.c @@ -589,8 +589,8 @@ static int ks0127_s_std(struct v4l2_subdev *sd, v4l2_std_id std) /* force to secam mode */ ks0127_and_or(sd, KS_DEMOD, 0xf0, 0x0f); } else { - v4l2_dbg(1, debug, sd, - "VIDIOC_S_STD: Unknown norm %llx\n", std); + v4l2_dbg(1, debug, sd, "VIDIOC_S_STD: Unknown norm %llx\n", + (unsigned long long)std); } return 0; } diff --git a/linux/drivers/media/video/saa7110.c b/linux/drivers/media/video/saa7110.c index ad21fdec1..bb58477e5 100644 --- a/linux/drivers/media/video/saa7110.c +++ b/linux/drivers/media/video/saa7110.c @@ -257,7 +257,7 @@ static int saa7110_g_input_status(struct v4l2_subdev *sd, u32 *pstatus) int status = saa7110_read(sd); v4l2_dbg(1, debug, sd, "status=0x%02x norm=%llx\n", - status, decoder->norm); + status, (unsigned long long)decoder->norm); if (!(status & 0x40)) res = 0; if (!(status & 0x03)) diff --git a/linux/drivers/media/video/vpx3220.c b/linux/drivers/media/video/vpx3220.c index 0c1c97f2f..ee6c74176 100644 --- a/linux/drivers/media/video/vpx3220.c +++ b/linux/drivers/media/video/vpx3220.c @@ -374,7 +374,7 @@ static int vpx3220_s_std(struct v4l2_subdev *sd, v4l2_std_id std) choosen video norm */ temp_input = vpx3220_fp_read(sd, 0xf2); - v4l2_dbg(1, debug, sd, "VIDIOC_S_STD %llx\n", std); + v4l2_dbg(1, debug, sd, "VIDIOC_S_STD %llx\n", (unsigned long long)std); if (std & V4L2_STD_NTSC) { vpx3220_write_fp_block(sd, init_ntsc, sizeof(init_ntsc) >> 1); v4l2_dbg(1, debug, sd, "norm switched to NTSC\n"); -- cgit v1.2.3 From e8d96ecabebb5b6311c9af066cf80f5018d59b9a Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 6 Mar 2009 14:20:00 +0100 Subject: stv0900: fix some compile warnings on 64-bit systems. From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/dvb/frontends/stv0900_core.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/frontends/stv0900_core.c b/linux/drivers/media/dvb/frontends/stv0900_core.c index c86c3017e..e9d03d0d2 100644 --- a/linux/drivers/media/dvb/frontends/stv0900_core.c +++ b/linux/drivers/media/dvb/frontends/stv0900_core.c @@ -62,16 +62,16 @@ static struct stv0900_inode *find_inode(struct i2c_adapter *i2c_adap, (temp_chip->internal->i2c_addr != i2c_addr))) { temp_chip = temp_chip->next_inode; - dprintk(KERN_INFO "%s: store.adap %x\n", __func__, - (int)&(*temp_chip->internal->i2c_adap)); - dprintk(KERN_INFO "%s: init.adap %x\n", __func__, - (int)&(*i2c_adap)); + dprintk(KERN_INFO "%s: store.adap %p\n", __func__, + temp_chip->internal->i2c_adap); + dprintk(KERN_INFO "%s: init.adap %p\n", __func__, + i2c_adap); } if (temp_chip != NULL) {/* find by i2c adapter & address */ - dprintk(KERN_INFO "%s: store.adap %x\n", __func__, - (int)temp_chip->internal->i2c_adap); - dprintk(KERN_INFO "%s: init.adap %x\n", __func__, - (int)i2c_adap); + dprintk(KERN_INFO "%s: store.adap %p\n", __func__, + temp_chip->internal->i2c_adap); + dprintk(KERN_INFO "%s: init.adap %p\n", __func__, + i2c_adap); } } @@ -1496,7 +1496,7 @@ static enum dvbfe_search stv0900_search(struct dvb_frontend *fe, enum fe_stv0900_error error = STV0900_NO_ERROR; - dprintk(KERN_INFO "%s: Internal = %x\n", __func__, (u32)i_params); + dprintk(KERN_INFO "%s: Internal = %p\n", __func__, i_params); p_result.locked = FALSE; p_search.path = state->demod; @@ -1619,7 +1619,7 @@ static int stv0900_read_status(struct dvb_frontend *fe, enum fe_status *status) { struct stv0900_state *state = fe->demodulator_priv; - dprintk("%s: Internal = %x\n", __func__, (unsigned int)state->internal); + dprintk("%s: Internal = %p\n", __func__, state->internal); if ((stv0900_status(state->internal, state->demod)) == TRUE) { dprintk("DEMOD LOCK OK\n"); @@ -1935,8 +1935,8 @@ struct dvb_frontend *stv0900_attach(const struct stv0900_config *config, if (err_stv0900) goto error; - dprintk(KERN_INFO "%s: Init Result = %d, handle_stv0900 = %x\n", - __func__, err_stv0900, (unsigned int)state->internal); + dprintk(KERN_INFO "%s: Init Result = %d, handle_stv0900 = %p\n", + __func__, err_stv0900, state->internal); break; default: goto error; -- cgit v1.2.3 From af06f2cdff1ca6217d3a46fe988e3704125b106d Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 6 Mar 2009 14:35:27 +0100 Subject: bttv: fix compile warnings for kernels < 2.6.20. From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/bt8xx/bttv-cards.c | 4 ++++ linux/drivers/media/video/bt8xx/bttv-i2c.c | 4 ++++ 2 files changed, 8 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/bt8xx/bttv-cards.c b/linux/drivers/media/video/bt8xx/bttv-cards.c index aed55398d..6868de9bd 100644 --- a/linux/drivers/media/video/bt8xx/bttv-cards.c +++ b/linux/drivers/media/video/bt8xx/bttv-cards.c @@ -3744,7 +3744,11 @@ static void __devinit osprey_eeprom(struct bttv *btv, const u8 ee[256]) unsigned short type; for (i = 4*16; i < 8*16; i += 16) { +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20) + u16 checksum = ip_compute_csum((unsigned char *)(ee + i), 16); +#else u16 checksum = ip_compute_csum(ee + i, 16); +#endif if ((checksum&0xff) + (checksum>>8) == 0xff) break; diff --git a/linux/drivers/media/video/bt8xx/bttv-i2c.c b/linux/drivers/media/video/bt8xx/bttv-i2c.c index 66fc4e480..3e7812c5a 100644 --- a/linux/drivers/media/video/bt8xx/bttv-i2c.c +++ b/linux/drivers/media/video/bt8xx/bttv-i2c.c @@ -401,7 +401,11 @@ int __devinit init_bttv_i2c(struct bttv *btv) strlcpy(btv->c.i2c_adap.name, "bt878", sizeof(btv->c.i2c_adap.name)); btv->c.i2c_adap.id = I2C_HW_B_BT848; /* FIXME */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19) + btv->c.i2c_adap.algo = (struct i2c_algorithm *)&bttv_algo; +#else btv->c.i2c_adap.algo = &bttv_algo; +#endif } else { /* bt848 */ /* Prevents usage of invalid delay values */ -- cgit v1.2.3 From c27f8418ab28efbbf2ccf9384c59bc31d1497a56 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 6 Mar 2009 14:41:13 +0100 Subject: cx88-alsa: fix compile warning for kernels <=2.6.20. From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/cx88/cx88-alsa.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/cx88/cx88-alsa.c b/linux/drivers/media/video/cx88/cx88-alsa.c index f7171586d..1e78faba6 100644 --- a/linux/drivers/media/video/cx88/cx88-alsa.c +++ b/linux/drivers/media/video/cx88/cx88-alsa.c @@ -657,8 +657,12 @@ static int snd_cx88_volume_put(struct snd_kcontrol *kcontrol, return changed; } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,19) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 21) static const DECLARE_TLV_DB_SCALE(snd_cx88_db_scale, -6300, 100, 0); +#else +static DECLARE_TLV_DB_SCALE(snd_cx88_db_scale, -6300, 100, 0); +#endif #endif static struct snd_kcontrol_new snd_cx88_volume = { -- cgit v1.2.3 From 7c7af993cc14112fbcb88c86c94ec1a546a2263b Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 6 Mar 2009 17:45:27 +0100 Subject: radio-aimslab: convert to v4l2_device. From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/radio/radio-aimslab.c | 350 ++++++++++++++---------------- 1 file changed, 168 insertions(+), 182 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/radio/radio-aimslab.c b/linux/drivers/media/radio/radio-aimslab.c index 384aa928f..57b896968 100644 --- a/linux/drivers/media/radio/radio-aimslab.c +++ b/linux/drivers/media/radio/radio-aimslab.c @@ -32,15 +32,17 @@ #include /* Initdata */ #include /* request_region */ #include /* udelay */ -#include /* outb, outb_p */ -#include /* copy to/from user */ -#include "compat.h" #include /* kernel radio structs */ -#include +#include /* for KERNEL_VERSION MACRO */ +#include /* outb, outb_p */ +#include /* copy to/from user */ +#include #include +#include "compat.h" -#include /* for KERNEL_VERSION MACRO */ -#define RADIO_VERSION KERNEL_VERSION(0,0,2) +MODULE_AUTHOR("M.Kirkwood"); +MODULE_DESCRIPTION("A driver for the RadioTrack/RadioReveal radio card."); +MODULE_LICENSE("GPL"); #ifndef CONFIG_RADIO_RTRACK_PORT #define CONFIG_RADIO_RTRACK_PORT -1 @@ -48,86 +50,95 @@ static int io = CONFIG_RADIO_RTRACK_PORT; static int radio_nr = -1; -static struct mutex lock; -struct rt_device +module_param(io, int, 0); +MODULE_PARM_DESC(io, "I/O address of the RadioTrack card (0x20f or 0x30f)"); +module_param(radio_nr, int, 0); + +#define RADIO_VERSION KERNEL_VERSION(0, 0, 2) + +struct rtrack { - unsigned long in_use; + struct v4l2_device v4l2_dev; + struct video_device vdev; int port; int curvol; unsigned long curfreq; int muted; + int io; + struct mutex lock; }; +static struct rtrack rtrack_card; /* local things */ static void sleep_delay(long n) { /* Sleep nicely for 'n' uS */ - int d=n/msecs_to_jiffies(1000); - if(!d) + int d = n / msecs_to_jiffies(1000); + if (!d) udelay(n); else msleep(jiffies_to_msecs(d)); } -static void rt_decvol(void) +static void rt_decvol(struct rtrack *rt) { - outb(0x58, io); /* volume down + sigstr + on */ + outb(0x58, rt->io); /* volume down + sigstr + on */ sleep_delay(100000); - outb(0xd8, io); /* volume steady + sigstr + on */ + outb(0xd8, rt->io); /* volume steady + sigstr + on */ } -static void rt_incvol(void) +static void rt_incvol(struct rtrack *rt) { - outb(0x98, io); /* volume up + sigstr + on */ + outb(0x98, rt->io); /* volume up + sigstr + on */ sleep_delay(100000); - outb(0xd8, io); /* volume steady + sigstr + on */ + outb(0xd8, rt->io); /* volume steady + sigstr + on */ } -static void rt_mute(struct rt_device *dev) +static void rt_mute(struct rtrack *rt) { - dev->muted = 1; - mutex_lock(&lock); - outb(0xd0, io); /* volume steady, off */ - mutex_unlock(&lock); + rt->muted = 1; + mutex_lock(&rt->lock); + outb(0xd0, rt->io); /* volume steady, off */ + mutex_unlock(&rt->lock); } -static int rt_setvol(struct rt_device *dev, int vol) +static int rt_setvol(struct rtrack *rt, int vol) { int i; - mutex_lock(&lock); + mutex_lock(&rt->lock); - if(vol == dev->curvol) { /* requested volume = current */ - if (dev->muted) { /* user is unmuting the card */ - dev->muted = 0; - outb (0xd8, io); /* enable card */ + if (vol == rt->curvol) { /* requested volume = current */ + if (rt->muted) { /* user is unmuting the card */ + rt->muted = 0; + outb(0xd8, rt->io); /* enable card */ } - mutex_unlock(&lock); + mutex_unlock(&rt->lock); return 0; } - if(vol == 0) { /* volume = 0 means mute the card */ - outb(0x48, io); /* volume down but still "on" */ + if (vol == 0) { /* volume = 0 means mute the card */ + outb(0x48, rt->io); /* volume down but still "on" */ sleep_delay(2000000); /* make sure it's totally down */ - outb(0xd0, io); /* volume steady, off */ - dev->curvol = 0; /* track the volume state! */ - mutex_unlock(&lock); + outb(0xd0, rt->io); /* volume steady, off */ + rt->curvol = 0; /* track the volume state! */ + mutex_unlock(&rt->lock); return 0; } - dev->muted = 0; - if(vol > dev->curvol) - for(i = dev->curvol; i < vol; i++) - rt_incvol(); + rt->muted = 0; + if (vol > rt->curvol) + for (i = rt->curvol; i < vol; i++) + rt_incvol(rt); else - for(i = dev->curvol; i > vol; i--) - rt_decvol(); + for (i = rt->curvol; i > vol; i--) + rt_decvol(rt); - dev->curvol = vol; - mutex_unlock(&lock); + rt->curvol = vol; + mutex_unlock(&rt->lock); return 0; } @@ -136,155 +147,137 @@ static int rt_setvol(struct rt_device *dev, int vol) * and bit 4 (+16) is to keep the signal strength meter enabled */ -static void send_0_byte(int port, struct rt_device *dev) +static void send_0_byte(struct rtrack *rt) { - if ((dev->curvol == 0) || (dev->muted)) { - outb_p(128+64+16+ 1, port); /* wr-enable + data low */ - outb_p(128+64+16+2+1, port); /* clock */ + if (rt->curvol == 0 || rt->muted) { + outb_p(128+64+16+ 1, rt->io); /* wr-enable + data low */ + outb_p(128+64+16+2+1, rt->io); /* clock */ } else { - outb_p(128+64+16+8+ 1, port); /* on + wr-enable + data low */ - outb_p(128+64+16+8+2+1, port); /* clock */ + outb_p(128+64+16+8+ 1, rt->io); /* on + wr-enable + data low */ + outb_p(128+64+16+8+2+1, rt->io); /* clock */ } sleep_delay(1000); } -static void send_1_byte(int port, struct rt_device *dev) +static void send_1_byte(struct rtrack *rt) { - if ((dev->curvol == 0) || (dev->muted)) { - outb_p(128+64+16+4 +1, port); /* wr-enable+data high */ - outb_p(128+64+16+4+2+1, port); /* clock */ + if (rt->curvol == 0 || rt->muted) { + outb_p(128+64+16+4 +1, rt->io); /* wr-enable+data high */ + outb_p(128+64+16+4+2+1, rt->io); /* clock */ } else { - outb_p(128+64+16+8+4 +1, port); /* on+wr-enable+data high */ - outb_p(128+64+16+8+4+2+1, port); /* clock */ + outb_p(128+64+16+8+4 +1, rt->io); /* on+wr-enable+data high */ + outb_p(128+64+16+8+4+2+1, rt->io); /* clock */ } sleep_delay(1000); } -static int rt_setfreq(struct rt_device *dev, unsigned long freq) +static int rt_setfreq(struct rtrack *rt, unsigned long freq) { int i; - /* adapted from radio-aztech.c */ + mutex_lock(&rt->lock); /* Stop other ops interfering */ + + rt->curfreq = freq; /* now uses VIDEO_TUNER_LOW for fine tuning */ freq += 171200; /* Add 10.7 MHz IF */ freq /= 800; /* Convert to 50 kHz units */ - mutex_lock(&lock); /* Stop other ops interfering */ - - send_0_byte (io, dev); /* 0: LSB of frequency */ + send_0_byte(rt); /* 0: LSB of frequency */ for (i = 0; i < 13; i++) /* : frequency bits (1-13) */ if (freq & (1 << i)) - send_1_byte (io, dev); + send_1_byte(rt); else - send_0_byte (io, dev); + send_0_byte(rt); - send_0_byte (io, dev); /* 14: test bit - always 0 */ - send_0_byte (io, dev); /* 15: test bit - always 0 */ + send_0_byte(rt); /* 14: test bit - always 0 */ + send_0_byte(rt); /* 15: test bit - always 0 */ - send_0_byte (io, dev); /* 16: band data 0 - always 0 */ - send_0_byte (io, dev); /* 17: band data 1 - always 0 */ - send_0_byte (io, dev); /* 18: band data 2 - always 0 */ - send_0_byte (io, dev); /* 19: time base - always 0 */ + send_0_byte(rt); /* 16: band data 0 - always 0 */ + send_0_byte(rt); /* 17: band data 1 - always 0 */ + send_0_byte(rt); /* 18: band data 2 - always 0 */ + send_0_byte(rt); /* 19: time base - always 0 */ - send_0_byte (io, dev); /* 20: spacing (0 = 25 kHz) */ - send_1_byte (io, dev); /* 21: spacing (1 = 25 kHz) */ - send_0_byte (io, dev); /* 22: spacing (0 = 25 kHz) */ - send_1_byte (io, dev); /* 23: AM/FM (FM = 1, always) */ + send_0_byte(rt); /* 20: spacing (0 = 25 kHz) */ + send_1_byte(rt); /* 21: spacing (1 = 25 kHz) */ + send_0_byte(rt); /* 22: spacing (0 = 25 kHz) */ + send_1_byte(rt); /* 23: AM/FM (FM = 1, always) */ - if ((dev->curvol == 0) || (dev->muted)) - outb (0xd0, io); /* volume steady + sigstr */ + if (rt->curvol == 0 || rt->muted) + outb(0xd0, rt->io); /* volume steady + sigstr */ else - outb (0xd8, io); /* volume steady + sigstr + on */ + outb(0xd8, rt->io); /* volume steady + sigstr + on */ - mutex_unlock(&lock); + mutex_unlock(&rt->lock); return 0; } -static int rt_getsigstr(struct rt_device *dev) +static int rt_getsigstr(struct rtrack *rt) { - if (inb(io) & 2) /* bit set = no signal present */ - return 0; - return 1; /* signal present */ -} + int sig = 1; -static struct v4l2_queryctrl radio_qctrl[] = { - { - .id = V4L2_CID_AUDIO_MUTE, - .name = "Mute", - .minimum = 0, - .maximum = 1, - .default_value = 1, - .type = V4L2_CTRL_TYPE_BOOLEAN, - },{ - .id = V4L2_CID_AUDIO_VOLUME, - .name = "Volume", - .minimum = 0, - .maximum = 0xff, - .step = 1, - .default_value = 0xff, - .type = V4L2_CTRL_TYPE_INTEGER, - } -}; + mutex_lock(&rt->lock); + if (inb(rt->io) & 2) /* bit set = no signal present */ + sig = 0; + mutex_unlock(&rt->lock); + return sig; +} static int vidioc_querycap(struct file *file, void *priv, struct v4l2_capability *v) { strlcpy(v->driver, "radio-aimslab", sizeof(v->driver)); strlcpy(v->card, "RadioTrack", sizeof(v->card)); - sprintf(v->bus_info, "ISA"); + strlcpy(v->bus_info, "ISA", sizeof(v->bus_info)); v->version = RADIO_VERSION; - v->capabilities = V4L2_CAP_TUNER; + v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO; return 0; } static int vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *v) { - struct rt_device *rt = video_drvdata(file); + struct rtrack *rt = video_drvdata(file); if (v->index > 0) return -EINVAL; - strcpy(v->name, "FM"); + strlcpy(v->name, "FM", sizeof(v->name)); v->type = V4L2_TUNER_RADIO; - v->rangelow = (87*16000); - v->rangehigh = (108*16000); + v->rangelow = 87 * 16000; + v->rangehigh = 108 * 16000; v->rxsubchans = V4L2_TUNER_SUB_MONO; v->capability = V4L2_TUNER_CAP_LOW; v->audmode = V4L2_TUNER_MODE_MONO; - v->signal = 0xffff*rt_getsigstr(rt); + v->signal = 0xffff * rt_getsigstr(rt); return 0; } static int vidioc_s_tuner(struct file *file, void *priv, struct v4l2_tuner *v) { - if (v->index > 0) - return -EINVAL; - return 0; + return v->index ? -EINVAL : 0; } static int vidioc_s_frequency(struct file *file, void *priv, struct v4l2_frequency *f) { - struct rt_device *rt = video_drvdata(file); + struct rtrack *rt = video_drvdata(file); - rt->curfreq = f->frequency; - rt_setfreq(rt, rt->curfreq); + rt_setfreq(rt, f->frequency); return 0; } static int vidioc_g_frequency(struct file *file, void *priv, struct v4l2_frequency *f) { - struct rt_device *rt = video_drvdata(file); + struct rtrack *rt = video_drvdata(file); f->type = V4L2_TUNER_RADIO; f->frequency = rt->curfreq; @@ -294,14 +287,11 @@ static int vidioc_g_frequency(struct file *file, void *priv, static int vidioc_queryctrl(struct file *file, void *priv, struct v4l2_queryctrl *qc) { - int i; - - for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) { - if (qc->id && qc->id == radio_qctrl[i].id) { - memcpy(qc, &(radio_qctrl[i]), - sizeof(*qc)); - return 0; - } + switch (qc->id) { + case V4L2_CID_AUDIO_MUTE: + return v4l2_ctrl_query_fill(qc, 0, 1, 1, 1); + case V4L2_CID_AUDIO_VOLUME: + return v4l2_ctrl_query_fill(qc, 0, 0xff, 1, 0xff); } return -EINVAL; } @@ -309,14 +299,14 @@ static int vidioc_queryctrl(struct file *file, void *priv, static int vidioc_g_ctrl(struct file *file, void *priv, struct v4l2_control *ctrl) { - struct rt_device *rt = video_drvdata(file); + struct rtrack *rt = video_drvdata(file); switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: ctrl->value = rt->muted; return 0; case V4L2_CID_AUDIO_VOLUME: - ctrl->value = rt->curvol * 6554; + ctrl->value = rt->curvol; return 0; } return -EINVAL; @@ -325,33 +315,22 @@ static int vidioc_g_ctrl(struct file *file, void *priv, static int vidioc_s_ctrl(struct file *file, void *priv, struct v4l2_control *ctrl) { - struct rt_device *rt = video_drvdata(file); + struct rtrack *rt = video_drvdata(file); switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: if (ctrl->value) rt_mute(rt); else - rt_setvol(rt,rt->curvol); + rt_setvol(rt, rt->curvol); return 0; case V4L2_CID_AUDIO_VOLUME: - rt_setvol(rt,ctrl->value); + rt_setvol(rt, ctrl->value); return 0; } return -EINVAL; } -static int vidioc_g_audio (struct file *file, void *priv, - struct v4l2_audio *a) -{ - if (a->index > 1) - return -EINVAL; - - strcpy(a->name, "Radio"); - a->capability = V4L2_AUDCAP_STEREO; - return 0; -} - static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i) { *i = 0; @@ -360,36 +339,38 @@ static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i) static int vidioc_s_input(struct file *filp, void *priv, unsigned int i) { - if (i != 0) - return -EINVAL; - return 0; + return i ? -EINVAL : 0; } -static int vidioc_s_audio(struct file *file, void *priv, +static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a) { - if (a->index != 0) - return -EINVAL; + a->index = 0; + strlcpy(a->name, "Radio", sizeof(a->name)); + a->capability = V4L2_AUDCAP_STEREO; return 0; } -static struct rt_device rtrack_unit; +static int vidioc_s_audio(struct file *file, void *priv, + struct v4l2_audio *a) +{ + return a->index ? -EINVAL : 0; +} -static int rtrack_exclusive_open(struct file *file) +static int rtrack_open(struct file *file) { - return test_and_set_bit(0, &rtrack_unit.in_use) ? -EBUSY : 0; + return 0; } -static int rtrack_exclusive_release(struct file *file) +static int rtrack_release(struct file *file) { - clear_bit(0, &rtrack_unit.in_use); return 0; } static const struct v4l2_file_operations rtrack_fops = { .owner = THIS_MODULE, - .open = rtrack_exclusive_open, - .release = rtrack_exclusive_release, + .open = rtrack_open, + .release = rtrack_release, .ioctl = video_ioctl2, }; @@ -408,64 +389,69 @@ static const struct v4l2_ioctl_ops rtrack_ioctl_ops = { .vidioc_s_ctrl = vidioc_s_ctrl, }; -static struct video_device rtrack_radio = { - .name = "RadioTrack radio", - .fops = &rtrack_fops, - .ioctl_ops = &rtrack_ioctl_ops, - .release = video_device_release_empty, -}; - static int __init rtrack_init(void) { - if(io==-1) - { - printk(KERN_ERR "You must set an I/O address with io=0x???\n"); + struct rtrack *rt = &rtrack_card; + struct v4l2_device *v4l2_dev = &rt->v4l2_dev; + int res; + + strlcpy(v4l2_dev->name, "rtrack", sizeof(v4l2_dev->name)); + rt->io = io; + + if (rt->io == -1) { + v4l2_err(v4l2_dev, "you must set an I/O address with io=0x???\n"); return -EINVAL; } - if (!request_region(io, 2, "rtrack")) - { - printk(KERN_ERR "rtrack: port 0x%x already in use\n", io); + if (!request_region(rt->io, 2, "rtrack")) { + v4l2_err(v4l2_dev, "port 0x%x already in use\n", rt->io); return -EBUSY; } - video_set_drvdata(&rtrack_radio, &rtrack_unit); + res = v4l2_device_register(NULL, v4l2_dev); + if (res < 0) { + release_region(rt->io, 2); + v4l2_err(v4l2_dev, "could not register v4l2_device\n"); + return res; + } + + strlcpy(rt->vdev.name, v4l2_dev->name, sizeof(rt->vdev.name)); + rt->vdev.v4l2_dev = v4l2_dev; + rt->vdev.fops = &rtrack_fops; + rt->vdev.ioctl_ops = &rtrack_ioctl_ops; + rt->vdev.release = video_device_release_empty; + video_set_drvdata(&rt->vdev, rt); - if (video_register_device(&rtrack_radio, VFL_TYPE_RADIO, radio_nr) < 0) { - release_region(io, 2); + if (video_register_device(&rt->vdev, VFL_TYPE_RADIO, radio_nr) < 0) { + v4l2_device_unregister(&rt->v4l2_dev); + release_region(rt->io, 2); return -EINVAL; } - printk(KERN_INFO "AIMSlab RadioTrack/RadioReveal card driver.\n"); + v4l2_info(v4l2_dev, "AIMSlab RadioTrack/RadioReveal card driver.\n"); /* Set up the I/O locking */ - mutex_init(&lock); + mutex_init(&rt->lock); /* mute card - prevents noisy bootups */ /* this ensures that the volume is all the way down */ - outb(0x48, io); /* volume down but still "on" */ + outb(0x48, rt->io); /* volume down but still "on" */ sleep_delay(2000000); /* make sure it's totally down */ - outb(0xc0, io); /* steady volume, mute card */ - rtrack_unit.curvol = 0; + outb(0xc0, rt->io); /* steady volume, mute card */ return 0; } -MODULE_AUTHOR("M.Kirkwood"); -MODULE_DESCRIPTION("A driver for the RadioTrack/RadioReveal radio card."); -MODULE_LICENSE("GPL"); - -module_param(io, int, 0); -MODULE_PARM_DESC(io, "I/O address of the RadioTrack card (0x20f or 0x30f)"); -module_param(radio_nr, int, 0); - -static void __exit cleanup_rtrack_module(void) +static void __exit rtrack_exit(void) { - video_unregister_device(&rtrack_radio); - release_region(io,2); + struct rtrack *rt = &rtrack_card; + + video_unregister_device(&rt->vdev); + v4l2_device_unregister(&rt->v4l2_dev); + release_region(rt->io, 2); } module_init(rtrack_init); -module_exit(cleanup_rtrack_module); +module_exit(rtrack_exit); -- cgit v1.2.3 From e307d0fca84d4a54dd56ab786481a76e40f19d77 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 6 Mar 2009 17:48:18 +0100 Subject: radio-aztech: convert to v4l2_device. From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/radio/radio-aztech.c | 381 +++++++++++++++---------------- 1 file changed, 182 insertions(+), 199 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/radio/radio-aztech.c b/linux/drivers/media/radio/radio-aztech.c index d4d5babcd..dcf53edc2 100644 --- a/linux/drivers/media/radio/radio-aztech.c +++ b/linux/drivers/media/radio/radio-aztech.c @@ -29,34 +29,17 @@ #include /* Initdata */ #include /* request_region */ #include /* udelay */ -#include /* outb, outb_p */ -#include /* copy to/from user */ -#include "compat.h" #include /* kernel radio structs */ -#include +#include /* for KERNEL_VERSION MACRO */ +#include /* outb, outb_p */ +#include /* copy to/from user */ +#include #include +#include "compat.h" -#include /* for KERNEL_VERSION MACRO */ -#define RADIO_VERSION KERNEL_VERSION(0,0,2) - -static struct v4l2_queryctrl radio_qctrl[] = { - { - .id = V4L2_CID_AUDIO_MUTE, - .name = "Mute", - .minimum = 0, - .maximum = 1, - .default_value = 1, - .type = V4L2_CTRL_TYPE_BOOLEAN, - },{ - .id = V4L2_CID_AUDIO_VOLUME, - .name = "Volume", - .minimum = 0, - .maximum = 0xff, - .step = 1, - .default_value = 0xff, - .type = V4L2_CTRL_TYPE_INTEGER, - } -}; +MODULE_AUTHOR("Russell Kroll, Quay Lu, Donald Song, Jason Lewis, Scott McGrath, William McGrath"); +MODULE_DESCRIPTION("A driver for the Aztech radio card."); +MODULE_LICENSE("GPL"); /* acceptable ports: 0x350 (JP3 shorted), 0x358 (JP3 open) */ @@ -67,55 +50,64 @@ static struct v4l2_queryctrl radio_qctrl[] = { static int io = CONFIG_RADIO_AZTECH_PORT; static int radio_nr = -1; static int radio_wait_time = 1000; -static struct mutex lock; -struct az_device +module_param(io, int, 0); +module_param(radio_nr, int, 0); +MODULE_PARM_DESC(io, "I/O address of the Aztech card (0x350 or 0x358)"); + +#define RADIO_VERSION KERNEL_VERSION(0, 0, 2) + +struct aztech { - unsigned long in_use; + struct v4l2_device v4l2_dev; + struct video_device vdev; + int io; int curvol; unsigned long curfreq; int stereo; + struct mutex lock; }; +static struct aztech aztech_card; + static int volconvert(int level) { - level>>=14; /* Map 16bits down to 2 bit */ - level&=3; + level >>= 14; /* Map 16bits down to 2 bit */ + level &= 3; /* convert to card-friendly values */ - switch (level) - { - case 0: - return 0; - case 1: - return 1; - case 2: - return 4; - case 3: - return 5; + switch (level) { + case 0: + return 0; + case 1: + return 1; + case 2: + return 4; + case 3: + return 5; } return 0; /* Quieten gcc */ } -static void send_0_byte (struct az_device *dev) +static void send_0_byte(struct aztech *az) { udelay(radio_wait_time); - outb_p(2+volconvert(dev->curvol), io); - outb_p(64+2+volconvert(dev->curvol), io); + outb_p(2 + volconvert(az->curvol), az->io); + outb_p(64 + 2 + volconvert(az->curvol), az->io); } -static void send_1_byte (struct az_device *dev) +static void send_1_byte(struct aztech *az) { udelay (radio_wait_time); - outb_p(128+2+volconvert(dev->curvol), io); - outb_p(128+64+2+volconvert(dev->curvol), io); + outb_p(128 + 2 + volconvert(az->curvol), az->io); + outb_p(128 + 64 + 2 + volconvert(az->curvol), az->io); } -static int az_setvol(struct az_device *dev, int vol) +static int az_setvol(struct aztech *az, int vol) { - mutex_lock(&lock); - outb (volconvert(vol), io); - mutex_unlock(&lock); + mutex_lock(&az->lock); + outb(volconvert(vol), az->io); + mutex_unlock(&az->lock); return 0; } @@ -127,116 +119,110 @@ static int az_setvol(struct az_device *dev, int vol) * */ -static int az_getsigstr(struct az_device *dev) +static int az_getsigstr(struct aztech *az) { - if (inb(io) & 2) /* bit set = no signal present */ - return 0; - return 1; /* signal present */ + int sig = 1; + + mutex_lock(&az->lock); + if (inb(az->io) & 2) /* bit set = no signal present */ + sig = 0; + mutex_unlock(&az->lock); + return sig; } -static int az_getstereo(struct az_device *dev) +static int az_getstereo(struct aztech *az) { - if (inb(io) & 1) /* bit set = mono */ - return 0; - return 1; /* stereo */ + int stereo = 1; + + mutex_lock(&az->lock); + if (inb(az->io) & 1) /* bit set = mono */ + stereo = 0; + mutex_unlock(&az->lock); + return stereo; } -static int az_setfreq(struct az_device *dev, unsigned long frequency) +static int az_setfreq(struct aztech *az, unsigned long frequency) { int i; + mutex_lock(&az->lock); + + az->curfreq = frequency; frequency += 171200; /* Add 10.7 MHz IF */ frequency /= 800; /* Convert to 50 kHz units */ - mutex_lock(&lock); - - send_0_byte (dev); /* 0: LSB of frequency */ + send_0_byte(az); /* 0: LSB of frequency */ for (i = 0; i < 13; i++) /* : frequency bits (1-13) */ if (frequency & (1 << i)) - send_1_byte (dev); + send_1_byte(az); else - send_0_byte (dev); + send_0_byte(az); - send_0_byte (dev); /* 14: test bit - always 0 */ - send_0_byte (dev); /* 15: test bit - always 0 */ - send_0_byte (dev); /* 16: band data 0 - always 0 */ - if (dev->stereo) /* 17: stereo (1 to enable) */ - send_1_byte (dev); + send_0_byte(az); /* 14: test bit - always 0 */ + send_0_byte(az); /* 15: test bit - always 0 */ + send_0_byte(az); /* 16: band data 0 - always 0 */ + if (az->stereo) /* 17: stereo (1 to enable) */ + send_1_byte(az); else - send_0_byte (dev); + send_0_byte(az); - send_1_byte (dev); /* 18: band data 1 - unknown */ - send_0_byte (dev); /* 19: time base - always 0 */ - send_0_byte (dev); /* 20: spacing (0 = 25 kHz) */ - send_1_byte (dev); /* 21: spacing (1 = 25 kHz) */ - send_0_byte (dev); /* 22: spacing (0 = 25 kHz) */ - send_1_byte (dev); /* 23: AM/FM (FM = 1, always) */ + send_1_byte(az); /* 18: band data 1 - unknown */ + send_0_byte(az); /* 19: time base - always 0 */ + send_0_byte(az); /* 20: spacing (0 = 25 kHz) */ + send_1_byte(az); /* 21: spacing (1 = 25 kHz) */ + send_0_byte(az); /* 22: spacing (0 = 25 kHz) */ + send_1_byte(az); /* 23: AM/FM (FM = 1, always) */ /* latch frequency */ - udelay (radio_wait_time); - outb_p(128+64+volconvert(dev->curvol), io); + udelay(radio_wait_time); + outb_p(128 + 64 + volconvert(az->curvol), az->io); - mutex_unlock(&lock); + mutex_unlock(&az->lock); return 0; } -static int vidioc_querycap (struct file *file, void *priv, +static int vidioc_querycap(struct file *file, void *priv, struct v4l2_capability *v) { - strlcpy(v->driver, "radio-aztech", sizeof (v->driver)); - strlcpy(v->card, "Aztech Radio", sizeof (v->card)); - sprintf(v->bus_info,"ISA"); + strlcpy(v->driver, "radio-aztech", sizeof(v->driver)); + strlcpy(v->card, "Aztech Radio", sizeof(v->card)); + strlcpy(v->bus_info, "ISA", sizeof(v->bus_info)); v->version = RADIO_VERSION; - v->capabilities = V4L2_CAP_TUNER; + v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO; return 0; } -static int vidioc_g_tuner (struct file *file, void *priv, +static int vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *v) { - struct az_device *az = video_drvdata(file); + struct aztech *az = video_drvdata(file); if (v->index > 0) return -EINVAL; - strcpy(v->name, "FM"); + strlcpy(v->name, "FM", sizeof(v->name)); v->type = V4L2_TUNER_RADIO; - v->rangelow=(87*16000); - v->rangehigh=(108*16000); - v->rxsubchans =V4L2_TUNER_SUB_MONO|V4L2_TUNER_SUB_STEREO; - v->capability=V4L2_TUNER_CAP_LOW; - if(az_getstereo(az)) + v->rangelow = 87 * 16000; + v->rangehigh = 108 * 16000; + v->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO; + v->capability = V4L2_TUNER_CAP_LOW; + if (az_getstereo(az)) v->audmode = V4L2_TUNER_MODE_STEREO; else v->audmode = V4L2_TUNER_MODE_MONO; - v->signal=0xFFFF*az_getsigstr(az); + v->signal = 0xFFFF * az_getsigstr(az); return 0; } - -static int vidioc_s_tuner (struct file *file, void *priv, +static int vidioc_s_tuner(struct file *file, void *priv, struct v4l2_tuner *v) { - if (v->index > 0) - return -EINVAL; - - return 0; -} - -static int vidioc_g_audio (struct file *file, void *priv, - struct v4l2_audio *a) -{ - if (a->index > 1) - return -EINVAL; - - strcpy(a->name, "Radio"); - a->capability = V4L2_AUDCAP_STEREO; - return 0; + return v->index ? -EINVAL : 0; } static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i) @@ -247,113 +233,107 @@ static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i) static int vidioc_s_input(struct file *filp, void *priv, unsigned int i) { - if (i != 0) - return -EINVAL; - return 0; + return i ? -EINVAL : 0; } - -static int vidioc_s_audio (struct file *file, void *priv, +static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a) { - if (a->index != 0) - return -EINVAL; - + a->index = 0; + strlcpy(a->name, "Radio", sizeof(a->name)); + a->capability = V4L2_AUDCAP_STEREO; return 0; } -static int vidioc_s_frequency (struct file *file, void *priv, +static int vidioc_s_audio(struct file *file, void *priv, + struct v4l2_audio *a) +{ + return a->index ? -EINVAL : 0; +} + +static int vidioc_s_frequency(struct file *file, void *priv, struct v4l2_frequency *f) { - struct az_device *az = video_drvdata(file); + struct aztech *az = video_drvdata(file); - az->curfreq = f->frequency; - az_setfreq(az, az->curfreq); + az_setfreq(az, f->frequency); return 0; } -static int vidioc_g_frequency (struct file *file, void *priv, +static int vidioc_g_frequency(struct file *file, void *priv, struct v4l2_frequency *f) { - struct az_device *az = video_drvdata(file); + struct aztech *az = video_drvdata(file); f->type = V4L2_TUNER_RADIO; f->frequency = az->curfreq; - return 0; } -static int vidioc_queryctrl (struct file *file, void *priv, +static int vidioc_queryctrl(struct file *file, void *priv, struct v4l2_queryctrl *qc) { - int i; - - for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) { - if (qc->id && qc->id == radio_qctrl[i].id) { - memcpy(qc, &(radio_qctrl[i]), - sizeof(*qc)); - return (0); - } + switch (qc->id) { + case V4L2_CID_AUDIO_MUTE: + return v4l2_ctrl_query_fill(qc, 0, 1, 1, 1); + case V4L2_CID_AUDIO_VOLUME: + return v4l2_ctrl_query_fill(qc, 0, 0xff, 1, 0xff); } return -EINVAL; } -static int vidioc_g_ctrl (struct file *file, void *priv, +static int vidioc_g_ctrl(struct file *file, void *priv, struct v4l2_control *ctrl) { - struct az_device *az = video_drvdata(file); + struct aztech *az = video_drvdata(file); switch (ctrl->id) { - case V4L2_CID_AUDIO_MUTE: - if (az->curvol==0) - ctrl->value=1; - else - ctrl->value=0; - return (0); - case V4L2_CID_AUDIO_VOLUME: - ctrl->value=az->curvol * 6554; - return (0); + case V4L2_CID_AUDIO_MUTE: + if (az->curvol == 0) + ctrl->value = 1; + else + ctrl->value = 0; + return 0; + case V4L2_CID_AUDIO_VOLUME: + ctrl->value = az->curvol * 6554; + return 0; } return -EINVAL; } -static int vidioc_s_ctrl (struct file *file, void *priv, +static int vidioc_s_ctrl(struct file *file, void *priv, struct v4l2_control *ctrl) { - struct az_device *az = video_drvdata(file); + struct aztech *az = video_drvdata(file); switch (ctrl->id) { - case V4L2_CID_AUDIO_MUTE: - if (ctrl->value) { - az_setvol(az,0); - } else { - az_setvol(az,az->curvol); - } - return (0); - case V4L2_CID_AUDIO_VOLUME: - az_setvol(az,ctrl->value); - return (0); + case V4L2_CID_AUDIO_MUTE: + if (ctrl->value) + az_setvol(az, 0); + else + az_setvol(az, az->curvol); + return 0; + case V4L2_CID_AUDIO_VOLUME: + az_setvol(az, ctrl->value); + return 0; } return -EINVAL; } -static struct az_device aztech_unit; - -static int aztech_exclusive_open(struct file *file) +static int aztech_open(struct file *file) { - return test_and_set_bit(0, &aztech_unit.in_use) ? -EBUSY : 0; + return 0; } -static int aztech_exclusive_release(struct file *file) +static int aztech_release(struct file *file) { - clear_bit(0, &aztech_unit.in_use); return 0; } static const struct v4l2_file_operations aztech_fops = { .owner = THIS_MODULE, - .open = aztech_exclusive_open, - .release = aztech_exclusive_release, + .open = aztech_open, + .release = aztech_release, .ioctl = video_ioctl2, }; @@ -372,57 +352,60 @@ static const struct v4l2_ioctl_ops aztech_ioctl_ops = { .vidioc_s_ctrl = vidioc_s_ctrl, }; -static struct video_device aztech_radio = { - .name = "Aztech radio", - .fops = &aztech_fops, - .ioctl_ops = &aztech_ioctl_ops, - .release = video_device_release_empty, -}; - -module_param_named(debug,aztech_radio.debug, int, 0644); -MODULE_PARM_DESC(debug,"activates debug info"); - static int __init aztech_init(void) { - if(io==-1) - { - printk(KERN_ERR "You must set an I/O address with io=0x???\n"); + struct aztech *az = &aztech_card; + struct v4l2_device *v4l2_dev = &az->v4l2_dev; + int res; + + strlcpy(v4l2_dev->name, "aztech", sizeof(v4l2_dev->name)); + az->io = io; + + if (az->io == -1) { + v4l2_err(v4l2_dev, "you must set an I/O address with io=0x???\n"); return -EINVAL; } - if (!request_region(io, 2, "aztech")) - { - printk(KERN_ERR "aztech: port 0x%x already in use\n", io); + if (!request_region(az->io, 2, "aztech")) { + v4l2_err(v4l2_dev, "port 0x%x already in use\n", az->io); return -EBUSY; } - mutex_init(&lock); - video_set_drvdata(&aztech_radio, &aztech_unit); + res = v4l2_device_register(NULL, v4l2_dev); + if (res < 0) { + release_region(az->io, 2); + v4l2_err(v4l2_dev, "Could not register v4l2_device\n"); + return res; + } - if (video_register_device(&aztech_radio, VFL_TYPE_RADIO, radio_nr) < 0) { - release_region(io,2); + mutex_init(&az->lock); + strlcpy(az->vdev.name, v4l2_dev->name, sizeof(az->vdev.name)); + az->vdev.v4l2_dev = v4l2_dev; + az->vdev.fops = &aztech_fops; + az->vdev.ioctl_ops = &aztech_ioctl_ops; + az->vdev.release = video_device_release_empty; + video_set_drvdata(&az->vdev, az); + + if (video_register_device(&az->vdev, VFL_TYPE_RADIO, radio_nr) < 0) { + v4l2_device_unregister(v4l2_dev); + release_region(az->io, 2); return -EINVAL; } - printk(KERN_INFO "Aztech radio card driver v1.00/19990224 rkroll@exploits.org\n"); + v4l2_info(v4l2_dev, "Aztech radio card driver v1.00/19990224 rkroll@exploits.org\n"); /* mute card - prevents noisy bootups */ - outb (0, io); + outb(0, az->io); return 0; } -MODULE_AUTHOR("Russell Kroll, Quay Lu, Donald Song, Jason Lewis, Scott McGrath, William McGrath"); -MODULE_DESCRIPTION("A driver for the Aztech radio card."); -MODULE_LICENSE("GPL"); - -module_param(io, int, 0); -module_param(radio_nr, int, 0); -MODULE_PARM_DESC(io, "I/O address of the Aztech card (0x350 or 0x358)"); - -static void __exit aztech_cleanup(void) +static void __exit aztech_exit(void) { - video_unregister_device(&aztech_radio); - release_region(io,2); + struct aztech *az = &aztech_card; + + video_unregister_device(&az->vdev); + v4l2_device_unregister(&az->v4l2_dev); + release_region(az->io, 2); } module_init(aztech_init); -module_exit(aztech_cleanup); +module_exit(aztech_exit); -- cgit v1.2.3 From cbc98821002e4065b69ce74c892bb9ad2085428f Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 6 Mar 2009 17:48:47 +0100 Subject: radio-cadet: convert to v4l2_device. From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/radio/radio-cadet.c | 622 ++++++++++++++++---------------- 1 file changed, 307 insertions(+), 315 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/radio/radio-cadet.c b/linux/drivers/media/radio/radio-cadet.c index 7425aef88..03e76bc74 100644 --- a/linux/drivers/media/radio/radio-cadet.c +++ b/linux/drivers/media/radio/radio-cadet.c @@ -35,363 +35,346 @@ #include /* Initdata */ #include /* request_region */ #include /* udelay */ -#include /* outb, outb_p */ -#include /* copy to/from user */ -#include "compat.h" #include /* V4L2 API defs */ -#include -#include #include #include +#include /* outb, outb_p */ +#include /* copy to/from user */ +#include +#include +#include "compat.h" + +MODULE_AUTHOR("Fred Gleason, Russell Kroll, Quay Lu, Donald Song, Jason Lewis, Scott McGrath, William McGrath"); +MODULE_DESCRIPTION("A driver for the ADS Cadet AM/FM/RDS radio card."); +MODULE_LICENSE("GPL"); + +static int io = -1; /* default to isapnp activation */ +static int radio_nr = -1; + +module_param(io, int, 0); +MODULE_PARM_DESC(io, "I/O address of Cadet card (0x330,0x332,0x334,0x336,0x338,0x33a,0x33c,0x33e)"); +module_param(radio_nr, int, 0); + +#define CADET_VERSION KERNEL_VERSION(0, 3, 3) #define RDS_BUFFER 256 #define RDS_RX_FLAG 1 #define MBS_RX_FLAG 2 -#define CADET_VERSION KERNEL_VERSION(0,3,3) - -static struct v4l2_queryctrl radio_qctrl[] = { - { - .id = V4L2_CID_AUDIO_MUTE, - .name = "Mute", - .minimum = 0, - .maximum = 1, - .default_value = 1, - .type = V4L2_CTRL_TYPE_BOOLEAN, - },{ - .id = V4L2_CID_AUDIO_VOLUME, - .name = "Volume", - .minimum = 0, - .maximum = 0xff, - .step = 1, - .default_value = 0xff, - .type = V4L2_CTRL_TYPE_INTEGER, - } +struct cadet { + struct v4l2_device v4l2_dev; + struct video_device vdev; + int io; + int users; + int curtuner; + int tunestat; + int sigstrength; + wait_queue_head_t read_queue; + struct timer_list readtimer; + __u8 rdsin, rdsout, rdsstat; + unsigned char rdsbuf[RDS_BUFFER]; + struct mutex lock; + int reading; }; -static int io=-1; /* default to isapnp activation */ -static int radio_nr = -1; -static int users; -static int curtuner; -static int tunestat; -static int sigstrength; -static wait_queue_head_t read_queue; -static struct timer_list readtimer; -static __u8 rdsin, rdsout, rdsstat; -static unsigned char rdsbuf[RDS_BUFFER]; -static spinlock_t cadet_io_lock; - -static int cadet_probe(void); +static struct cadet cadet_card; /* * Signal Strength Threshold Values * The V4L API spec does not define any particular unit for the signal * strength value. These values are in microvolts of RF at the tuner's input. */ -static __u16 sigtable[2][4]={{5,10,30,150},{28,40,63,1000}}; +static __u16 sigtable[2][4] = { + { 5, 10, 30, 150 }, + { 28, 40, 63, 1000 } +}; #if 0 /* Note: cadet_getrds() is not used at the moment. It will be useful for future extensions, e.g. an ioctl to query RDS reception quality. - Hans J. Koch */ -static int -cadet_getrds(void) +static int cadet_getrds(struct cadet *dev) { - int rds_mbs_stat=0; + int rds_mbs_stat = 0; - spin_lock(&cadet_io_lock); - outb(3,io); /* Select Decoder Control/Status */ - outb(inb(io+1)&0x7f,io+1); /* Reset RDS detection */ - spin_unlock(&cadet_io_lock); + mutex_lock(&dev->lock); + outb(3, dev->io); /* Select Decoder Control/Status */ + outb(inb(dev->io + 1) & 0x7f, dev->io + 1); /* Reset RDS detection */ + mutex_unlock(&dev->lock); msleep(100); - spin_lock(&cadet_io_lock); - outb(3,io); /* Select Decoder Control/Status */ - if((inb(io+1)&0x80)!=0) { + mutex_lock(&dev->lock); + outb(3, dev->io); /* Select Decoder Control/Status */ + if ((inb(dev->io + 1) & 0x80) != 0) rds_mbs_stat |= RDS_RX_FLAG; - } - if((inb(io+1)&0x10)!=0) { + if ((inb(dev->io + 1) & 0x10) != 0) rds_mbs_stat |= MBS_RX_FLAG; - } - spin_unlock(&cadet_io_lock); + mutex_unlock(&dev->lock); return rds_mbs_stat; } #endif -static int -cadet_getstereo(void) +static int cadet_getstereo(struct cadet *dev) { int ret = V4L2_TUNER_SUB_MONO; - if(curtuner != 0) /* Only FM has stereo capability! */ + + if (dev->curtuner != 0) /* Only FM has stereo capability! */ return V4L2_TUNER_SUB_MONO; - spin_lock(&cadet_io_lock); - outb(7,io); /* Select tuner control */ - if( (inb(io+1) & 0x40) == 0) + mutex_lock(&dev->lock); + outb(7, dev->io); /* Select tuner control */ + if ((inb(dev->io + 1) & 0x40) == 0) ret = V4L2_TUNER_SUB_STEREO; - spin_unlock(&cadet_io_lock); + mutex_unlock(&dev->lock); return ret; } -static unsigned -cadet_gettune(void) +static unsigned cadet_gettune(struct cadet *dev) { - int curvol,i; - unsigned fifo=0; + int curvol, i; + unsigned fifo = 0; /* * Prepare for read */ - spin_lock(&cadet_io_lock); + mutex_lock(&dev->lock); - outb(7,io); /* Select tuner control */ - curvol=inb(io+1); /* Save current volume/mute setting */ - outb(0x00,io+1); /* Ensure WRITE-ENABLE is LOW */ - tunestat=0xffff; + outb(7, dev->io); /* Select tuner control */ + curvol = inb(dev->io + 1); /* Save current volume/mute setting */ + outb(0x00, dev->io + 1); /* Ensure WRITE-ENABLE is LOW */ + dev->tunestat = 0xffff; /* * Read the shift register */ - for(i=0;i<25;i++) { - fifo=(fifo<<1)|((inb(io+1)>>7)&0x01); - if(i<24) { - outb(0x01,io+1); - tunestat&=inb(io+1); - outb(0x00,io+1); + for (i = 0; i < 25; i++) { + fifo = (fifo << 1) | ((inb(dev->io + 1) >> 7) & 0x01); + if (i < 24) { + outb(0x01, dev->io + 1); + dev->tunestat &= inb(dev->io + 1); + outb(0x00, dev->io + 1); } } /* * Restore volume/mute setting */ - outb(curvol,io+1); - spin_unlock(&cadet_io_lock); + outb(curvol, dev->io + 1); + mutex_unlock(&dev->lock); return fifo; } -static unsigned -cadet_getfreq(void) +static unsigned cadet_getfreq(struct cadet *dev) { int i; - unsigned freq=0,test,fifo=0; + unsigned freq = 0, test, fifo = 0; /* * Read current tuning */ - fifo=cadet_gettune(); + fifo = cadet_gettune(dev); /* * Convert to actual frequency */ - if(curtuner==0) { /* FM */ - test=12500; - for(i=0;i<14;i++) { - if((fifo&0x01)!=0) { - freq+=test; - } - test=test<<1; - fifo=fifo>>1; + if (dev->curtuner == 0) { /* FM */ + test = 12500; + for (i = 0; i < 14; i++) { + if ((fifo & 0x01) != 0) + freq += test; + test = test << 1; + fifo = fifo >> 1; } - freq-=10700000; /* IF frequency is 10.7 MHz */ - freq=(freq*16)/1000000; /* Make it 1/16 MHz */ - } - if(curtuner==1) { /* AM */ - freq=((fifo&0x7fff)-2010)*16; + freq -= 10700000; /* IF frequency is 10.7 MHz */ + freq = (freq * 16) / 1000000; /* Make it 1/16 MHz */ } + if (dev->curtuner == 1) /* AM */ + freq = ((fifo & 0x7fff) - 2010) * 16; return freq; } -static void -cadet_settune(unsigned fifo) +static void cadet_settune(struct cadet *dev, unsigned fifo) { int i; unsigned test; - spin_lock(&cadet_io_lock); + mutex_lock(&dev->lock); - outb(7,io); /* Select tuner control */ + outb(7, dev->io); /* Select tuner control */ /* * Write the shift register */ - test=0; - test=(fifo>>23)&0x02; /* Align data for SDO */ - test|=0x1c; /* SDM=1, SWE=1, SEN=1, SCK=0 */ - outb(7,io); /* Select tuner control */ - outb(test,io+1); /* Initialize for write */ - for(i=0;i<25;i++) { - test|=0x01; /* Toggle SCK High */ - outb(test,io+1); - test&=0xfe; /* Toggle SCK Low */ - outb(test,io+1); - fifo=fifo<<1; /* Prepare the next bit */ - test=0x1c|((fifo>>23)&0x02); - outb(test,io+1); + test = 0; + test = (fifo >> 23) & 0x02; /* Align data for SDO */ + test |= 0x1c; /* SDM=1, SWE=1, SEN=1, SCK=0 */ + outb(7, dev->io); /* Select tuner control */ + outb(test, dev->io + 1); /* Initialize for write */ + for (i = 0; i < 25; i++) { + test |= 0x01; /* Toggle SCK High */ + outb(test, dev->io + 1); + test &= 0xfe; /* Toggle SCK Low */ + outb(test, dev->io + 1); + fifo = fifo << 1; /* Prepare the next bit */ + test = 0x1c | ((fifo >> 23) & 0x02); + outb(test, dev->io + 1); } - spin_unlock(&cadet_io_lock); + mutex_unlock(&dev->lock); } -static void -cadet_setfreq(unsigned freq) +static void cadet_setfreq(struct cadet *dev, unsigned freq) { unsigned fifo; - int i,j,test; + int i, j, test; int curvol; /* * Formulate a fifo command */ - fifo=0; - if(curtuner==0) { /* FM */ - test=102400; - freq=(freq*1000)/16; /* Make it kHz */ - freq+=10700; /* IF is 10700 kHz */ - for(i=0;i<14;i++) { - fifo=fifo<<1; - if(freq>=test) { - fifo|=0x01; - freq-=test; + fifo = 0; + if (dev->curtuner == 0) { /* FM */ + test = 102400; + freq = (freq * 1000) / 16; /* Make it kHz */ + freq += 10700; /* IF is 10700 kHz */ + for (i = 0; i < 14; i++) { + fifo = fifo << 1; + if (freq >= test) { + fifo |= 0x01; + freq -= test; } - test=test>>1; + test = test >> 1; } } - if(curtuner==1) { /* AM */ - fifo=(freq/16)+2010; /* Make it kHz */ - fifo|=0x100000; /* Select AM Band */ + if (dev->curtuner == 1) { /* AM */ + fifo = (freq / 16) + 2010; /* Make it kHz */ + fifo |= 0x100000; /* Select AM Band */ } /* * Save current volume/mute setting */ - spin_lock(&cadet_io_lock); - outb(7,io); /* Select tuner control */ - curvol=inb(io+1); - spin_unlock(&cadet_io_lock); + mutex_lock(&dev->lock); + outb(7, dev->io); /* Select tuner control */ + curvol = inb(dev->io + 1); + mutex_unlock(&dev->lock); /* * Tune the card */ - for(j=3;j>-1;j--) { - cadet_settune(fifo|(j<<16)); + for (j = 3; j > -1; j--) { + cadet_settune(dev, fifo | (j << 16)); - spin_lock(&cadet_io_lock); - outb(7,io); /* Select tuner control */ - outb(curvol,io+1); - spin_unlock(&cadet_io_lock); + mutex_lock(&dev->lock); + outb(7, dev->io); /* Select tuner control */ + outb(curvol, dev->io + 1); + mutex_unlock(&dev->lock); msleep(100); - cadet_gettune(); - if((tunestat & 0x40) == 0) { /* Tuned */ - sigstrength=sigtable[curtuner][j]; + cadet_gettune(dev); + if ((dev->tunestat & 0x40) == 0) { /* Tuned */ + dev->sigstrength = sigtable[dev->curtuner][j]; return; } } - sigstrength=0; + dev->sigstrength = 0; } -static int -cadet_getvol(void) +static int cadet_getvol(struct cadet *dev) { int ret = 0; - spin_lock(&cadet_io_lock); + mutex_lock(&dev->lock); - outb(7,io); /* Select tuner control */ - if((inb(io + 1) & 0x20) != 0) + outb(7, dev->io); /* Select tuner control */ + if ((inb(dev->io + 1) & 0x20) != 0) ret = 0xffff; - spin_unlock(&cadet_io_lock); + mutex_unlock(&dev->lock); return ret; } -static void -cadet_setvol(int vol) +static void cadet_setvol(struct cadet *dev, int vol) { - spin_lock(&cadet_io_lock); - outb(7,io); /* Select tuner control */ - if(vol>0) - outb(0x20,io+1); + mutex_lock(&dev->lock); + outb(7, dev->io); /* Select tuner control */ + if (vol > 0) + outb(0x20, dev->io + 1); else - outb(0x00,io+1); - spin_unlock(&cadet_io_lock); + outb(0x00, dev->io + 1); + mutex_unlock(&dev->lock); } -static void -cadet_handler(unsigned long data) +static void cadet_handler(unsigned long data) { - /* - * Service the RDS fifo - */ + struct cadet *dev = (void *)data; - if(spin_trylock(&cadet_io_lock)) - { - outb(0x3,io); /* Select RDS Decoder Control */ - if((inb(io+1)&0x20)!=0) { + /* Service the RDS fifo */ + if (mutex_trylock(&dev->lock)) { + outb(0x3, dev->io); /* Select RDS Decoder Control */ + if ((inb(dev->io + 1) & 0x20) != 0) printk(KERN_CRIT "cadet: RDS fifo overflow\n"); - } - outb(0x80,io); /* Select RDS fifo */ - while((inb(io)&0x80)!=0) { - rdsbuf[rdsin]=inb(io+1); - if(rdsin==rdsout) + outb(0x80, dev->io); /* Select RDS fifo */ + while ((inb(dev->io) & 0x80) != 0) { + dev->rdsbuf[dev->rdsin] = inb(dev->io + 1); + if (dev->rdsin == dev->rdsout) printk(KERN_WARNING "cadet: RDS buffer overflow\n"); else - rdsin++; + dev->rdsin++; } - spin_unlock(&cadet_io_lock); + mutex_unlock(&dev->lock); } /* * Service pending read */ - if( rdsin!=rdsout) - wake_up_interruptible(&read_queue); + if (dev->rdsin != dev->rdsout) + wake_up_interruptible(&dev->read_queue); /* * Clean up and exit */ - init_timer(&readtimer); - readtimer.function=cadet_handler; - readtimer.data=(unsigned long)0; - readtimer.expires=jiffies+msecs_to_jiffies(50); - add_timer(&readtimer); + init_timer(&dev->readtimer); + dev->readtimer.function = cadet_handler; + dev->readtimer.data = (unsigned long)0; + dev->readtimer.expires = jiffies + msecs_to_jiffies(50); + add_timer(&dev->readtimer); } - -static ssize_t -cadet_read(struct file *file, char __user *data, size_t count, loff_t *ppos) +static ssize_t cadet_read(struct file *file, char __user *data, size_t count, loff_t *ppos) { - int i=0; + struct cadet *dev = video_drvdata(file); unsigned char readbuf[RDS_BUFFER]; - - if(rdsstat==0) { - spin_lock(&cadet_io_lock); - rdsstat=1; - outb(0x80,io); /* Select RDS fifo */ - spin_unlock(&cadet_io_lock); - init_timer(&readtimer); - readtimer.function=cadet_handler; - readtimer.data=(unsigned long)0; - readtimer.expires=jiffies+msecs_to_jiffies(50); - add_timer(&readtimer); + int i = 0; + + if (dev->rdsstat == 0) { + mutex_lock(&dev->lock); + dev->rdsstat = 1; + outb(0x80, dev->io); /* Select RDS fifo */ + mutex_unlock(&dev->lock); + init_timer(&dev->readtimer); + dev->readtimer.function = cadet_handler; + dev->readtimer.data = (unsigned long)dev; + dev->readtimer.expires = jiffies + msecs_to_jiffies(50); + add_timer(&dev->readtimer); } - if(rdsin==rdsout) { + if (dev->rdsin == dev->rdsout) { if (file->f_flags & O_NONBLOCK) return -EWOULDBLOCK; - interruptible_sleep_on(&read_queue); + interruptible_sleep_on(&dev->read_queue); } - while( irdsin != dev->rdsout) + readbuf[i++] = dev->rdsbuf[dev->rdsout++]; - if (copy_to_user(data,readbuf,i)) + if (copy_to_user(data, readbuf, i)) return -EFAULT; return i; } @@ -400,38 +383,40 @@ cadet_read(struct file *file, char __user *data, size_t count, loff_t *ppos) static int vidioc_querycap(struct file *file, void *priv, struct v4l2_capability *v) { - v->capabilities = - V4L2_CAP_TUNER | - V4L2_CAP_READWRITE; + strlcpy(v->driver, "ADS Cadet", sizeof(v->driver)); + strlcpy(v->card, "ADS Cadet", sizeof(v->card)); + strlcpy(v->bus_info, "ISA", sizeof(v->bus_info)); v->version = CADET_VERSION; - strcpy(v->driver, "ADS Cadet"); - strcpy(v->card, "ADS Cadet"); + v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO | V4L2_CAP_READWRITE; return 0; } static int vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *v) { + struct cadet *dev = video_drvdata(file); + v->type = V4L2_TUNER_RADIO; switch (v->index) { case 0: - strcpy(v->name, "FM"); + strlcpy(v->name, "FM", sizeof(v->name)); v->capability = V4L2_TUNER_CAP_STEREO; v->rangelow = 1400; /* 87.5 MHz */ v->rangehigh = 1728; /* 108.0 MHz */ - v->rxsubchans=cadet_getstereo(); - switch (v->rxsubchans){ + v->rxsubchans = cadet_getstereo(dev); + switch (v->rxsubchans) { case V4L2_TUNER_SUB_MONO: v->audmode = V4L2_TUNER_MODE_MONO; break; case V4L2_TUNER_SUB_STEREO: v->audmode = V4L2_TUNER_MODE_STEREO; break; - default: ; + default: + break; } break; case 1: - strcpy(v->name, "AM"); + strlcpy(v->name, "AM", sizeof(v->name)); v->capability = V4L2_TUNER_CAP_LOW; v->rangelow = 8320; /* 520 kHz */ v->rangehigh = 26400; /* 1650 kHz */ @@ -441,25 +426,29 @@ static int vidioc_g_tuner(struct file *file, void *priv, default: return -EINVAL; } - v->signal = sigstrength; /* We might need to modify scaling of this */ + v->signal = dev->sigstrength; /* We might need to modify scaling of this */ return 0; } static int vidioc_s_tuner(struct file *file, void *priv, struct v4l2_tuner *v) { - if((v->index != 0)&&(v->index != 1)) + struct cadet *dev = video_drvdata(file); + + if (v->index != 0 && v->index != 1) return -EINVAL; - curtuner = v->index; + dev->curtuner = v->index; return 0; } static int vidioc_g_frequency(struct file *file, void *priv, struct v4l2_frequency *f) { - f->tuner = curtuner; + struct cadet *dev = video_drvdata(file); + + f->tuner = dev->curtuner; f->type = V4L2_TUNER_RADIO; - f->frequency = cadet_getfreq(); + f->frequency = cadet_getfreq(dev); return 0; } @@ -467,27 +456,26 @@ static int vidioc_g_frequency(struct file *file, void *priv, static int vidioc_s_frequency(struct file *file, void *priv, struct v4l2_frequency *f) { + struct cadet *dev = video_drvdata(file); + if (f->type != V4L2_TUNER_RADIO) return -EINVAL; - if((curtuner==0)&&((f->frequency<1400)||(f->frequency>1728))) + if (dev->curtuner == 0 && (f->frequency < 1400 || f->frequency > 1728)) return -EINVAL; - if((curtuner==1)&&((f->frequency<8320)||(f->frequency>26400))) + if (dev->curtuner == 1 && (f->frequency < 8320 || f->frequency > 26400)) return -EINVAL; - cadet_setfreq(f->frequency); + cadet_setfreq(dev, f->frequency); return 0; } static int vidioc_queryctrl(struct file *file, void *priv, struct v4l2_queryctrl *qc) { - int i; - - for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) { - if (qc->id && qc->id == radio_qctrl[i].id) { - memcpy(qc, &(radio_qctrl[i]), - sizeof(*qc)); - return 0; - } + switch (qc->id) { + case V4L2_CID_AUDIO_MUTE: + return v4l2_ctrl_query_fill(qc, 0, 1, 1, 1); + case V4L2_CID_AUDIO_VOLUME: + return v4l2_ctrl_query_fill(qc, 0, 0xff, 1, 0xff); } return -EINVAL; } @@ -495,12 +483,14 @@ static int vidioc_queryctrl(struct file *file, void *priv, static int vidioc_g_ctrl(struct file *file, void *priv, struct v4l2_control *ctrl) { - switch (ctrl->id){ + struct cadet *dev = video_drvdata(file); + + switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: /* TODO: Handle this correctly */ - ctrl->value = (cadet_getvol() == 0); + ctrl->value = (cadet_getvol(dev) == 0); break; case V4L2_CID_AUDIO_VOLUME: - ctrl->value = cadet_getvol(); + ctrl->value = cadet_getvol(dev); break; default: return -EINVAL; @@ -511,15 +501,17 @@ static int vidioc_g_ctrl(struct file *file, void *priv, static int vidioc_s_ctrl(struct file *file, void *priv, struct v4l2_control *ctrl) { + struct cadet *dev = video_drvdata(file); + switch (ctrl->id){ case V4L2_CID_AUDIO_MUTE: /* TODO: Handle this correctly */ if (ctrl->value) - cadet_setvol(0); + cadet_setvol(dev, 0); else - cadet_setvol(0xffff); + cadet_setvol(dev, 0xffff); break; case V4L2_CID_AUDIO_VOLUME: - cadet_setvol(ctrl->value); + cadet_setvol(dev, ctrl->value); break; default: return -EINVAL; @@ -527,16 +519,6 @@ static int vidioc_s_ctrl(struct file *file, void *priv, return 0; } -static int vidioc_g_audio(struct file *file, void *priv, - struct v4l2_audio *a) -{ - if (a->index > 1) - return -EINVAL; - strcpy(a->name, "Radio"); - a->capability = V4L2_AUDCAP_STEREO; - return 0; -} - static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i) { *i = 0; @@ -545,43 +527,52 @@ static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i) static int vidioc_s_input(struct file *filp, void *priv, unsigned int i) { - if (i != 0) - return -EINVAL; + return i ? -EINVAL : 0; +} + +static int vidioc_g_audio(struct file *file, void *priv, + struct v4l2_audio *a) +{ + a->index = 0; + strlcpy(a->name, "Radio", sizeof(a->name)); + a->capability = V4L2_AUDCAP_STEREO; return 0; } static int vidioc_s_audio(struct file *file, void *priv, struct v4l2_audio *a) { - if (a->index != 0) - return -EINVAL; - return 0; + return a->index ? -EINVAL : 0; } -static int -cadet_open(struct file *file) +static int cadet_open(struct file *file) { - users++; - if (1 == users) init_waitqueue_head(&read_queue); + struct cadet *dev = video_drvdata(file); + + dev->users++; + if (1 == dev->users) + init_waitqueue_head(&dev->read_queue); return 0; } -static int -cadet_release(struct file *file) +static int cadet_release(struct file *file) { - users--; - if (0 == users){ - del_timer_sync(&readtimer); - rdsstat=0; + struct cadet *dev = video_drvdata(file); + + dev->users--; + if (0 == dev->users) { + del_timer_sync(&dev->readtimer); + dev->rdsstat = 0; } return 0; } -static unsigned int -cadet_poll(struct file *file, struct poll_table_struct *wait) +static unsigned int cadet_poll(struct file *file, struct poll_table_struct *wait) { - poll_wait(file,&read_queue,wait); - if(rdsin != rdsout) + struct cadet *dev = video_drvdata(file); + + poll_wait(file, &dev->read_queue, wait); + if (dev->rdsin != dev->rdsout) return POLLIN | POLLRDNORM; return 0; } @@ -611,13 +602,6 @@ static const struct v4l2_ioctl_ops cadet_ioctl_ops = { .vidioc_s_input = vidioc_s_input, }; -static struct video_device cadet_radio = { - .name = "Cadet radio", - .fops = &cadet_fops, - .ioctl_ops = &cadet_ioctl_ops, - .release = video_device_release_empty, -}; - #ifdef CONFIG_PNP static struct pnp_device_id cadet_pnp_devices[] = { @@ -628,7 +612,7 @@ static struct pnp_device_id cadet_pnp_devices[] = { MODULE_DEVICE_TABLE(pnp, cadet_pnp_devices); -static int cadet_pnp_probe(struct pnp_dev * dev, const struct pnp_device_id *dev_id) +static int cadet_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id) { if (!dev) return -ENODEV; @@ -636,13 +620,12 @@ static int cadet_pnp_probe(struct pnp_dev * dev, const struct pnp_device_id *dev if (io > 0) return -EBUSY; - if (!pnp_port_valid(dev, 0)) { + if (!pnp_port_valid(dev, 0)) return -ENODEV; - } io = pnp_port_start(dev, 0); - printk ("radio-cadet: PnP reports device at %#x\n", io); + printk(KERN_INFO "radio-cadet: PnP reports device at %#x\n", io); return io; } @@ -658,23 +641,23 @@ static struct pnp_driver cadet_pnp_driver = { static struct pnp_driver cadet_pnp_driver; #endif -static int cadet_probe(void) +static void cadet_probe(struct cadet *dev) { - static int iovals[8]={0x330,0x332,0x334,0x336,0x338,0x33a,0x33c,0x33e}; + static int iovals[8] = { 0x330, 0x332, 0x334, 0x336, 0x338, 0x33a, 0x33c, 0x33e }; int i; - for(i=0;i<8;i++) { - io=iovals[i]; - if (request_region(io, 2, "cadet-probe")) { - cadet_setfreq(1410); - if(cadet_getfreq()==1410) { - release_region(io, 2); - return io; + for (i = 0; i < 8; i++) { + dev->io = iovals[i]; + if (request_region(dev->io, 2, "cadet-probe")) { + cadet_setfreq(dev, 1410); + if (cadet_getfreq(dev) == 1410) { + release_region(dev->io, 2); + return; } - release_region(io, 2); + release_region(dev->io, 2); } } - return -1; + dev->io = -1; } /* @@ -684,59 +667,68 @@ static int cadet_probe(void) static int __init cadet_init(void) { - spin_lock_init(&cadet_io_lock); + struct cadet *dev = &cadet_card; + struct v4l2_device *v4l2_dev = &dev->v4l2_dev; + int res; - /* - * If a probe was requested then probe ISAPnP first (safest) - */ + strlcpy(v4l2_dev->name, "cadet", sizeof(v4l2_dev->name)); + mutex_init(&dev->lock); + + /* If a probe was requested then probe ISAPnP first (safest) */ if (io < 0) pnp_register_driver(&cadet_pnp_driver); - /* - * If that fails then probe unsafely if probe is requested - */ - if(io < 0) - io = cadet_probe (); + dev->io = io; - /* - * Else we bail out - */ + /* If that fails then probe unsafely if probe is requested */ + if (dev->io < 0) + cadet_probe(dev); - if(io < 0) { + /* Else we bail out */ + if (dev->io < 0) { #ifdef MODULE - printk(KERN_ERR "You must set an I/O address with io=0x???\n"); + v4l2_err(v4l2_dev, "you must set an I/O address with io=0x???\n"); #endif goto fail; } - if (!request_region(io,2,"cadet")) + if (!request_region(dev->io, 2, "cadet")) goto fail; - if (video_register_device(&cadet_radio, VFL_TYPE_RADIO, radio_nr) < 0) { - release_region(io,2); + + res = v4l2_device_register(NULL, v4l2_dev); + if (res < 0) { + release_region(dev->io, 2); + v4l2_err(v4l2_dev, "could not register v4l2_device\n"); goto fail; } - printk(KERN_INFO "ADS Cadet Radio Card at 0x%x\n",io); + + strlcpy(dev->vdev.name, v4l2_dev->name, sizeof(dev->vdev.name)); + dev->vdev.v4l2_dev = v4l2_dev; + dev->vdev.fops = &cadet_fops; + dev->vdev.ioctl_ops = &cadet_ioctl_ops; + dev->vdev.release = video_device_release_empty; + video_set_drvdata(&dev->vdev, dev); + + if (video_register_device(&dev->vdev, VFL_TYPE_RADIO, radio_nr) < 0) { + v4l2_device_unregister(v4l2_dev); + release_region(dev->io, 2); + goto fail; + } + v4l2_info(v4l2_dev, "ADS Cadet Radio Card at 0x%x\n", dev->io); return 0; fail: pnp_unregister_driver(&cadet_pnp_driver); - return -1; + return -ENODEV; } - - -MODULE_AUTHOR("Fred Gleason, Russell Kroll, Quay Lu, Donald Song, Jason Lewis, Scott McGrath, William McGrath"); -MODULE_DESCRIPTION("A driver for the ADS Cadet AM/FM/RDS radio card."); -MODULE_LICENSE("GPL"); - -module_param(io, int, 0); -MODULE_PARM_DESC(io, "I/O address of Cadet card (0x330,0x332,0x334,0x336,0x338,0x33a,0x33c,0x33e)"); -module_param(radio_nr, int, 0); - -static void __exit cadet_cleanup_module(void) +static void __exit cadet_exit(void) { - video_unregister_device(&cadet_radio); - release_region(io,2); + struct cadet *dev = &cadet_card; + + video_unregister_device(&dev->vdev); + v4l2_device_unregister(&dev->v4l2_dev); + release_region(dev->io, 2); pnp_unregister_driver(&cadet_pnp_driver); } module_init(cadet_init); -module_exit(cadet_cleanup_module); +module_exit(cadet_exit); -- cgit v1.2.3 From 4a0a23dc3b75fa7ca0bb514cb7ad2a51eb2236eb Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 6 Mar 2009 17:50:07 +0100 Subject: radio-gemtek-pci: convert to v4l2_device. From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/radio/radio-gemtek-pci.c | 340 +++++++++++++-------------- 1 file changed, 165 insertions(+), 175 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/radio/radio-gemtek-pci.c b/linux/drivers/media/radio/radio-gemtek-pci.c index 7edd3e594..b68e2ba4c 100644 --- a/linux/drivers/media/radio/radio-gemtek-pci.c +++ b/linux/drivers/media/radio/radio-gemtek-pci.c @@ -44,36 +44,28 @@ #include #include #include -#include "compat.h" #include -#include -#include #include - #include /* for KERNEL_VERSION MACRO */ -#define RADIO_VERSION KERNEL_VERSION(0,0,2) - -static struct v4l2_queryctrl radio_qctrl[] = { - { - .id = V4L2_CID_AUDIO_MUTE, - .name = "Mute", - .minimum = 0, - .maximum = 1, - .default_value = 1, - .type = V4L2_CTRL_TYPE_BOOLEAN, - },{ - .id = V4L2_CID_AUDIO_VOLUME, - .name = "Volume", - .minimum = 0, - .maximum = 65535, - .step = 65535, - .default_value = 0xff, - .type = V4L2_CTRL_TYPE_INTEGER, - } -}; +#include +#include +#include +#include +#include "compat.h" -#include -#include +MODULE_AUTHOR("Vladimir Shebordaev "); +MODULE_DESCRIPTION("The video4linux driver for the Gemtek PCI Radio Card"); +MODULE_LICENSE("GPL"); + +static int nr_radio = -1; +static int mx = 1; + +module_param(mx, bool, 0); +MODULE_PARM_DESC(mx, "single digit: 1 - turn off the turner upon module exit (default), 0 - do not"); +module_param(nr_radio, int, 0); +MODULE_PARM_DESC(nr_radio, "video4linux device number to use"); + +#define RADIO_VERSION KERNEL_VERSION(0, 0, 2) #ifndef PCI_VENDOR_ID_GEMTEK #define PCI_VENDOR_ID_GEMTEK 0x5046 @@ -91,8 +83,11 @@ static struct v4l2_queryctrl radio_qctrl[] = { #define GEMTEK_PCI_RANGE_HIGH (108*16000) #endif -struct gemtek_pci_card { - struct video_device *videodev; +struct gemtek_pci { + struct v4l2_device v4l2_dev; + struct video_device vdev; + struct mutex lock; + struct pci_dev *pdev; u32 iobase; u32 length; @@ -101,116 +96,133 @@ struct gemtek_pci_card { u8 mute; }; -static int nr_radio = -1; -static unsigned long in_use; +static inline struct gemtek_pci *to_gemtek_pci(struct v4l2_device *v4l2_dev) +{ + return container_of(v4l2_dev, struct gemtek_pci, v4l2_dev); +} -static inline u8 gemtek_pci_out( u16 value, u32 port ) +static inline u8 gemtek_pci_out(u16 value, u32 port) { - outw( value, port ); + outw(value, port); return (u8)value; } -#define _b0( v ) *((u8 *)&v) -static void __gemtek_pci_cmd( u16 value, u32 port, u8 *last_byte, int keep ) +#define _b0(v) (*((u8 *)&v)) + +static void __gemtek_pci_cmd(u16 value, u32 port, u8 *last_byte, int keep) { - register u8 byte = *last_byte; + u8 byte = *last_byte; - if ( !value ) { - if ( !keep ) + if (!value) { + if (!keep) value = (u16)port; byte &= 0xfd; } else byte |= 2; - _b0( value ) = byte; - outw( value, port ); + _b0(value) = byte; + outw(value, port); byte |= 1; - _b0( value ) = byte; - outw( value, port ); + _b0(value) = byte; + outw(value, port); byte &= 0xfe; - _b0( value ) = byte; - outw( value, port ); + _b0(value) = byte; + outw(value, port); *last_byte = byte; } -static inline void gemtek_pci_nil( u32 port, u8 *last_byte ) +static inline void gemtek_pci_nil(u32 port, u8 *last_byte) { - __gemtek_pci_cmd( 0x00, port, last_byte, false ); + __gemtek_pci_cmd(0x00, port, last_byte, false); } -static inline void gemtek_pci_cmd( u16 cmd, u32 port, u8 *last_byte ) +static inline void gemtek_pci_cmd(u16 cmd, u32 port, u8 *last_byte) { - __gemtek_pci_cmd( cmd, port, last_byte, true ); + __gemtek_pci_cmd(cmd, port, last_byte, true); } -static void gemtek_pci_setfrequency( struct gemtek_pci_card *card, unsigned long frequency ) +static void gemtek_pci_setfrequency(struct gemtek_pci *card, unsigned long frequency) { - register int i; - register u32 value = frequency / 200 + 856; - register u16 mask = 0x8000; + int i; + u32 value = frequency / 200 + 856; + u16 mask = 0x8000; u8 last_byte; u32 port = card->iobase; - last_byte = gemtek_pci_out( 0x06, port ); + mutex_lock(&card->lock); + card->current_frequency = frequency; + last_byte = gemtek_pci_out(0x06, port); i = 0; do { - gemtek_pci_nil( port, &last_byte ); + gemtek_pci_nil(port, &last_byte); i++; - } while ( i < 9 ); + } while (i < 9); i = 0; do { - gemtek_pci_cmd( value & mask, port, &last_byte ); + gemtek_pci_cmd(value & mask, port, &last_byte); mask >>= 1; i++; - } while ( i < 16 ); + } while (i < 16); - outw( 0x10, port ); + outw(0x10, port); + mutex_unlock(&card->lock); } -static inline void gemtek_pci_mute( struct gemtek_pci_card *card ) +static void gemtek_pci_mute(struct gemtek_pci *card) { - outb( 0x1f, card->iobase ); + mutex_lock(&card->lock); + outb(0x1f, card->iobase); card->mute = true; + mutex_unlock(&card->lock); } -static inline void gemtek_pci_unmute( struct gemtek_pci_card *card ) +static void gemtek_pci_unmute(struct gemtek_pci *card) { - if ( card->mute ) { - gemtek_pci_setfrequency( card, card->current_frequency ); + mutex_lock(&card->lock); + if (card->mute) { + gemtek_pci_setfrequency(card, card->current_frequency); card->mute = false; } + mutex_unlock(&card->lock); } -static inline unsigned int gemtek_pci_getsignal( struct gemtek_pci_card *card ) +static int gemtek_pci_getsignal(struct gemtek_pci *card) { - return ( inb( card->iobase ) & 0x08 ) ? 0 : 1; + int sig; + + mutex_lock(&card->lock); + sig = (inb(card->iobase) & 0x08) ? 0 : 1; + mutex_unlock(&card->lock); + return sig; } static int vidioc_querycap(struct file *file, void *priv, struct v4l2_capability *v) { + struct gemtek_pci *card = video_drvdata(file); + strlcpy(v->driver, "radio-gemtek-pci", sizeof(v->driver)); strlcpy(v->card, "GemTek PCI Radio", sizeof(v->card)); - sprintf(v->bus_info, "ISA"); + snprintf(v->bus_info, sizeof(v->bus_info), "PCI:%s", pci_name(card->pdev)); v->version = RADIO_VERSION; - v->capabilities = V4L2_CAP_TUNER; + v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO; return 0; } static int vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *v) { - struct gemtek_pci_card *card = video_drvdata(file); + struct gemtek_pci *card = video_drvdata(file); if (v->index > 0) return -EINVAL; - strcpy(v->name, "FM"); + strlcpy(v->name, "FM", sizeof(v->name)); v->type = V4L2_TUNER_RADIO; v->rangelow = GEMTEK_PCI_RANGE_LOW; v->rangehigh = GEMTEK_PCI_RANGE_HIGH; @@ -224,21 +236,18 @@ static int vidioc_g_tuner(struct file *file, void *priv, static int vidioc_s_tuner(struct file *file, void *priv, struct v4l2_tuner *v) { - if (v->index > 0) - return -EINVAL; - return 0; + return v->index ? -EINVAL : 0; } static int vidioc_s_frequency(struct file *file, void *priv, struct v4l2_frequency *f) { - struct gemtek_pci_card *card = video_drvdata(file); + struct gemtek_pci *card = video_drvdata(file); - if ( (f->frequency < GEMTEK_PCI_RANGE_LOW) || - (f->frequency > GEMTEK_PCI_RANGE_HIGH) ) + if (f->frequency < GEMTEK_PCI_RANGE_LOW || + f->frequency > GEMTEK_PCI_RANGE_HIGH) return -EINVAL; gemtek_pci_setfrequency(card, f->frequency); - card->current_frequency = f->frequency; card->mute = false; return 0; } @@ -246,7 +255,7 @@ static int vidioc_s_frequency(struct file *file, void *priv, static int vidioc_g_frequency(struct file *file, void *priv, struct v4l2_frequency *f) { - struct gemtek_pci_card *card = video_drvdata(file); + struct gemtek_pci *card = video_drvdata(file); f->type = V4L2_TUNER_RADIO; f->frequency = card->current_frequency; @@ -256,13 +265,11 @@ static int vidioc_g_frequency(struct file *file, void *priv, static int vidioc_queryctrl(struct file *file, void *priv, struct v4l2_queryctrl *qc) { - int i; - for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) { - if (qc->id && qc->id == radio_qctrl[i].id) { - memcpy(qc, &(radio_qctrl[i]), - sizeof(*qc)); - return 0; - } + switch (qc->id) { + case V4L2_CID_AUDIO_MUTE: + return v4l2_ctrl_query_fill(qc, 0, 1, 1, 1); + case V4L2_CID_AUDIO_VOLUME: + return v4l2_ctrl_query_fill(qc, 0, 65535, 65535, 65535); } return -EINVAL; } @@ -270,7 +277,7 @@ static int vidioc_queryctrl(struct file *file, void *priv, static int vidioc_g_ctrl(struct file *file, void *priv, struct v4l2_control *ctrl) { - struct gemtek_pci_card *card = video_drvdata(file); + struct gemtek_pci *card = video_drvdata(file); switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: @@ -289,7 +296,7 @@ static int vidioc_g_ctrl(struct file *file, void *priv, static int vidioc_s_ctrl(struct file *file, void *priv, struct v4l2_control *ctrl) { - struct gemtek_pci_card *card = video_drvdata(file); + struct gemtek_pci *card = video_drvdata(file); switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: @@ -308,17 +315,6 @@ static int vidioc_s_ctrl(struct file *file, void *priv, return -EINVAL; } -static int vidioc_g_audio(struct file *file, void *priv, - struct v4l2_audio *a) -{ - if (a->index > 1) - return -EINVAL; - - strcpy(a->name, "Radio"); - a->capability = V4L2_AUDCAP_STEREO; - return 0; -} - static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i) { *i = 0; @@ -327,17 +323,22 @@ static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i) static int vidioc_s_input(struct file *filp, void *priv, unsigned int i) { - if (i != 0) - return -EINVAL; + return i ? -EINVAL : 0; +} + +static int vidioc_g_audio(struct file *file, void *priv, + struct v4l2_audio *a) +{ + a->index = 0; + strlcpy(a->name, "Radio", sizeof(a->name)); + a->capability = V4L2_AUDCAP_STEREO; return 0; } static int vidioc_s_audio(struct file *file, void *priv, struct v4l2_audio *a) { - if (a->index != 0) - return -EINVAL; - return 0; + return a->index ? -EINVAL : 0; } enum { @@ -355,25 +356,22 @@ static struct pci_device_id gemtek_pci_id[] = { 0 } }; -MODULE_DEVICE_TABLE( pci, gemtek_pci_id ); - -static int mx = 1; +MODULE_DEVICE_TABLE(pci, gemtek_pci_id); -static int gemtek_pci_exclusive_open(struct file *file) +static int gemtek_pci_open(struct file *file) { - return test_and_set_bit(0, &in_use) ? -EBUSY : 0; + return 0; } -static int gemtek_pci_exclusive_release(struct file *file) +static int gemtek_pci_release(struct file *file) { - clear_bit(0, &in_use); return 0; } static const struct v4l2_file_operations gemtek_pci_fops = { .owner = THIS_MODULE, - .open = gemtek_pci_exclusive_open, - .release = gemtek_pci_exclusive_release, + .open = gemtek_pci_open, + .release = gemtek_pci_release, .ioctl = video_ioctl2, }; @@ -392,114 +390,106 @@ static const struct v4l2_ioctl_ops gemtek_pci_ioctl_ops = { .vidioc_s_ctrl = vidioc_s_ctrl, }; -static struct video_device vdev_template = { - .name = "Gemtek PCI Radio", - .fops = &gemtek_pci_fops, - .ioctl_ops = &gemtek_pci_ioctl_ops, - .release = video_device_release_empty, -}; - -static int __devinit gemtek_pci_probe( struct pci_dev *pci_dev, const struct pci_device_id *pci_id ) +static int __devinit gemtek_pci_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id) { - struct gemtek_pci_card *card; - struct video_device *devradio; + struct gemtek_pci *card; + struct v4l2_device *v4l2_dev; + int res; - if ( (card = kzalloc( sizeof( struct gemtek_pci_card ), GFP_KERNEL )) == NULL ) { - printk( KERN_ERR "gemtek_pci: out of memory\n" ); + card = kzalloc(sizeof(struct gemtek_pci), GFP_KERNEL); + if (card == NULL) { + dev_err(&pdev->dev, "out of memory\n"); return -ENOMEM; } - if ( pci_enable_device( pci_dev ) ) - goto err_pci; + v4l2_dev = &card->v4l2_dev; + mutex_init(&card->lock); + card->pdev = pdev; - card->iobase = pci_resource_start( pci_dev, 0 ); - card->length = pci_resource_len( pci_dev, 0 ); + strlcpy(v4l2_dev->name, "gemtek_pci", sizeof(v4l2_dev->name)); - if ( request_region( card->iobase, card->length, card_names[pci_id->driver_data] ) == NULL ) { - printk( KERN_ERR "gemtek_pci: i/o port already in use\n" ); - goto err_pci; + res = v4l2_device_register(&pdev->dev, v4l2_dev); + if (res < 0) { + v4l2_err(v4l2_dev, "Could not register v4l2_device\n"); + kfree(card); + return res; } - pci_set_drvdata( pci_dev, card ); + if (pci_enable_device(pdev)) + goto err_pci; - if ( (devradio = kmalloc( sizeof( struct video_device ), GFP_KERNEL )) == NULL ) { - printk( KERN_ERR "gemtek_pci: out of memory\n" ); - goto err_video; + card->iobase = pci_resource_start(pdev, 0); + card->length = pci_resource_len(pdev, 0); + + if (request_region(card->iobase, card->length, card_names[pci_id->driver_data]) == NULL) { + v4l2_err(v4l2_dev, "i/o port already in use\n"); + goto err_pci; } - *devradio = vdev_template; - if (video_register_device(devradio, VFL_TYPE_RADIO, nr_radio) < 0) { - kfree( devradio ); + strlcpy(card->vdev.name, v4l2_dev->name, sizeof(card->vdev.name)); + card->vdev.v4l2_dev = v4l2_dev; + card->vdev.fops = &gemtek_pci_fops; + card->vdev.ioctl_ops = &gemtek_pci_ioctl_ops; + card->vdev.release = video_device_release_empty; + video_set_drvdata(&card->vdev, card); + + if (video_register_device(&card->vdev, VFL_TYPE_RADIO, nr_radio) < 0) goto err_video; - } - card->videodev = devradio; - video_set_drvdata(devradio, card); - gemtek_pci_mute( card ); + gemtek_pci_mute(card); -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,22) - printk( KERN_INFO "Gemtek PCI Radio (rev. %d) found at 0x%04x-0x%04x.\n", - pci_dev->revision, card->iobase, card->iobase + card->length - 1 ); +#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 22) + v4l2_info(v4l2_dev, "Gemtek PCI Radio (rev. %d) found at 0x%04x-0x%04x.\n", + pdev->revision, card->iobase, card->iobase + card->length - 1); #else - printk( KERN_INFO "Gemtek PCI Radio (rev. %d) found at 0x%04x-0x%04x.\n", - v4l_compat_pci_rev(pci_dev), card->iobase, - card->iobase + card->length - 1 ); + v4l2_info(v4l2_dev, "Gemtek PCI Radio (rev. %d) found at 0x%04x-0x%04x.\n", + v4l_compat_pci_rev(pdev), card->iobase, + card->iobase + card->length - 1); #endif return 0; err_video: - release_region( card->iobase, card->length ); + release_region(card->iobase, card->length); err_pci: - kfree( card ); + v4l2_device_unregister(v4l2_dev); + kfree(card); return -ENODEV; } -static void __devexit gemtek_pci_remove( struct pci_dev *pci_dev ) +static void __devexit gemtek_pci_remove(struct pci_dev *pdev) { - struct gemtek_pci_card *card = pci_get_drvdata( pci_dev ); + struct v4l2_device *v4l2_dev = dev_get_drvdata(&pdev->dev); + struct gemtek_pci *card = to_gemtek_pci(v4l2_dev); - video_unregister_device( card->videodev ); - kfree( card->videodev ); + video_unregister_device(&card->vdev); + v4l2_device_unregister(v4l2_dev); - release_region( card->iobase, card->length ); + release_region(card->iobase, card->length); - if ( mx ) - gemtek_pci_mute( card ); + if (mx) + gemtek_pci_mute(card); - kfree( card ); - - pci_set_drvdata( pci_dev, NULL ); + kfree(card); } -static struct pci_driver gemtek_pci_driver = -{ +static struct pci_driver gemtek_pci_driver = { .name = "gemtek_pci", .id_table = gemtek_pci_id, .probe = gemtek_pci_probe, .remove = __devexit_p(gemtek_pci_remove), }; -static int __init gemtek_pci_init_module( void ) +static int __init gemtek_pci_init(void) { - return pci_register_driver( &gemtek_pci_driver ); + return pci_register_driver(&gemtek_pci_driver); } -static void __exit gemtek_pci_cleanup_module( void ) +static void __exit gemtek_pci_exit(void) { pci_unregister_driver(&gemtek_pci_driver); } -MODULE_AUTHOR( "Vladimir Shebordaev " ); -MODULE_DESCRIPTION( "The video4linux driver for the Gemtek PCI Radio Card" ); -MODULE_LICENSE("GPL"); - -module_param(mx, bool, 0); -MODULE_PARM_DESC( mx, "single digit: 1 - turn off the turner upon module exit (default), 0 - do not" ); -module_param(nr_radio, int, 0); -MODULE_PARM_DESC( nr_radio, "video4linux device number to use"); - -module_init( gemtek_pci_init_module ); -module_exit( gemtek_pci_cleanup_module ); - +module_init(gemtek_pci_init); +module_exit(gemtek_pci_exit); -- cgit v1.2.3 From 48a5a5d79f817cd2646721c2deaf2a357a5f4f7c Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 6 Mar 2009 17:50:42 +0100 Subject: radio-gemtek: convert to v4l2_device. From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/radio/radio-gemtek.c | 399 +++++++++++++++---------------- 1 file changed, 188 insertions(+), 211 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/radio/radio-gemtek.c b/linux/drivers/media/radio/radio-gemtek.c index a1ae890c8..0cb1cb0a1 100644 --- a/linux/drivers/media/radio/radio-gemtek.c +++ b/linux/drivers/media/radio/radio-gemtek.c @@ -20,17 +20,16 @@ #include /* Initdata */ #include /* request_region */ #include /* udelay */ -#include /* outb, outb_p */ -#include /* copy to/from user */ -#include "compat.h" #include /* kernel radio structs */ +#include /* for KERNEL_VERSION MACRO */ +#include +#include /* outb, outb_p */ +#include /* copy to/from user */ #include -#include -#include +#include +#include "compat.h" -#include /* for KERNEL_VERSION MACRO */ -#define RADIO_VERSION KERNEL_VERSION(0,0,3) -#define RADIO_BANNER "GemTek Radio card driver: v0.0.3" +#define RADIO_VERSION KERNEL_VERSION(0, 0, 3) /* * Module info. @@ -58,7 +57,6 @@ static int shutdown = 1; static int keepmuted = 1; static int initmute = 1; static int radio_nr = -1; -static unsigned long in_use; module_param(io, int, 0444); MODULE_PARM_DESC(io, "Force I/O port for the GemTek Radio card if automatic " @@ -113,12 +111,19 @@ module_param(radio_nr, int, 0444); #define SHORT_DELAY 5 /* usec */ #define LONG_DELAY 75 /* usec */ -struct gemtek_device { +struct gemtek { + struct v4l2_device v4l2_dev; + struct video_device vdev; + struct mutex lock; unsigned long lastfreq; int muted; + int verified; + int io; u32 bu2614data; }; +static struct gemtek gemtek_card; + #define BU2614_FREQ_BITS 16 /* D0..D15, Frequency data */ #define BU2614_PORT_BITS 3 /* P0..P2, Output port control data */ #define BU2614_VOID_BITS 4 /* unused */ @@ -154,10 +159,6 @@ struct gemtek_device { #define BU2614_FMUN_MASK MKMASK(FMUN) #define BU2614_TEST_MASK MKMASK(TEST) -static struct gemtek_device gemtek_unit; - -static spinlock_t lock; - /* * Set data which will be sent to BU2614FS. */ @@ -167,33 +168,33 @@ static spinlock_t lock; /* * Transmit settings to BU2614FS over GemTek IC. */ -static void gemtek_bu2614_transmit(struct gemtek_device *dev) +static void gemtek_bu2614_transmit(struct gemtek *gt) { int i, bit, q, mute; - spin_lock(&lock); + mutex_lock(>->lock); - mute = dev->muted ? GEMTEK_MT : 0x00; + mute = gt->muted ? GEMTEK_MT : 0x00; - outb_p(mute | GEMTEK_DA | GEMTEK_CK, io); + outb_p(mute | GEMTEK_DA | GEMTEK_CK, gt->io); udelay(SHORT_DELAY); - outb_p(mute | GEMTEK_CE | GEMTEK_DA | GEMTEK_CK, io); + outb_p(mute | GEMTEK_CE | GEMTEK_DA | GEMTEK_CK, gt->io); udelay(LONG_DELAY); - for (i = 0, q = dev->bu2614data; i < 32; i++, q >>= 1) { - bit = (q & 1) ? GEMTEK_DA : 0; - outb_p(mute | GEMTEK_CE | bit, io); - udelay(SHORT_DELAY); - outb_p(mute | GEMTEK_CE | bit | GEMTEK_CK, io); - udelay(SHORT_DELAY); + for (i = 0, q = gt->bu2614data; i < 32; i++, q >>= 1) { + bit = (q & 1) ? GEMTEK_DA : 0; + outb_p(mute | GEMTEK_CE | bit, gt->io); + udelay(SHORT_DELAY); + outb_p(mute | GEMTEK_CE | bit | GEMTEK_CK, gt->io); + udelay(SHORT_DELAY); } - outb_p(mute | GEMTEK_DA | GEMTEK_CK, io); + outb_p(mute | GEMTEK_DA | GEMTEK_CK, gt->io); udelay(SHORT_DELAY); - outb_p(mute | GEMTEK_CE | GEMTEK_DA | GEMTEK_CK, io); + outb_p(mute | GEMTEK_CE | GEMTEK_DA | GEMTEK_CK, gt->io); udelay(LONG_DELAY); - spin_unlock(&lock); + mutex_unlock(>->lock); } /* @@ -207,107 +208,109 @@ static unsigned long gemtek_convfreq(unsigned long freq) /* * Set FM-frequency. */ -static void gemtek_setfreq(struct gemtek_device *dev, unsigned long freq) +static void gemtek_setfreq(struct gemtek *gt, unsigned long freq) { - - if (keepmuted && hardmute && dev->muted) + if (keepmuted && hardmute && gt->muted) return; - if (freq < GEMTEK_LOWFREQ) - freq = GEMTEK_LOWFREQ; - else if (freq > GEMTEK_HIGHFREQ) - freq = GEMTEK_HIGHFREQ; + freq = clamp_val(freq, GEMTEK_LOWFREQ, GEMTEK_HIGHFREQ); - dev->lastfreq = freq; - dev->muted = 0; + gt->lastfreq = freq; + gt->muted = 0; - gemtek_bu2614_set(dev, BU2614_PORT, 0); - gemtek_bu2614_set(dev, BU2614_FMES, 0); - gemtek_bu2614_set(dev, BU2614_SWIN, 0); /* FM-mode */ - gemtek_bu2614_set(dev, BU2614_SWAL, 0); - gemtek_bu2614_set(dev, BU2614_FMUN, 1); /* GT bit set */ - gemtek_bu2614_set(dev, BU2614_TEST, 0); + gemtek_bu2614_set(gt, BU2614_PORT, 0); + gemtek_bu2614_set(gt, BU2614_FMES, 0); + gemtek_bu2614_set(gt, BU2614_SWIN, 0); /* FM-mode */ + gemtek_bu2614_set(gt, BU2614_SWAL, 0); + gemtek_bu2614_set(gt, BU2614_FMUN, 1); /* GT bit set */ + gemtek_bu2614_set(gt, BU2614_TEST, 0); - gemtek_bu2614_set(dev, BU2614_STDF, GEMTEK_STDF_3_125_KHZ); - gemtek_bu2614_set(dev, BU2614_FREQ, gemtek_convfreq(freq)); + gemtek_bu2614_set(gt, BU2614_STDF, GEMTEK_STDF_3_125_KHZ); + gemtek_bu2614_set(gt, BU2614_FREQ, gemtek_convfreq(freq)); - gemtek_bu2614_transmit(dev); + gemtek_bu2614_transmit(gt); } /* * Set mute flag. */ -static void gemtek_mute(struct gemtek_device *dev) +static void gemtek_mute(struct gemtek *gt) { int i; - dev->muted = 1; + + gt->muted = 1; if (hardmute) { /* Turn off PLL, disable data output */ - gemtek_bu2614_set(dev, BU2614_PORT, 0); - gemtek_bu2614_set(dev, BU2614_FMES, 0); /* CT bit off */ - gemtek_bu2614_set(dev, BU2614_SWIN, 0); /* FM-mode */ - gemtek_bu2614_set(dev, BU2614_SWAL, 0); - gemtek_bu2614_set(dev, BU2614_FMUN, 0); /* GT bit off */ - gemtek_bu2614_set(dev, BU2614_TEST, 0); - gemtek_bu2614_set(dev, BU2614_STDF, GEMTEK_PLL_OFF); - gemtek_bu2614_set(dev, BU2614_FREQ, 0); - gemtek_bu2614_transmit(dev); - } else { - spin_lock(&lock); + gemtek_bu2614_set(gt, BU2614_PORT, 0); + gemtek_bu2614_set(gt, BU2614_FMES, 0); /* CT bit off */ + gemtek_bu2614_set(gt, BU2614_SWIN, 0); /* FM-mode */ + gemtek_bu2614_set(gt, BU2614_SWAL, 0); + gemtek_bu2614_set(gt, BU2614_FMUN, 0); /* GT bit off */ + gemtek_bu2614_set(gt, BU2614_TEST, 0); + gemtek_bu2614_set(gt, BU2614_STDF, GEMTEK_PLL_OFF); + gemtek_bu2614_set(gt, BU2614_FREQ, 0); + gemtek_bu2614_transmit(gt); + return; + } - /* Read bus contents (CE, CK and DA). */ - i = inb_p(io); - /* Write it back with mute flag set. */ - outb_p((i >> 5) | GEMTEK_MT, io); - udelay(SHORT_DELAY); + mutex_lock(>->lock); - spin_unlock(&lock); - } + /* Read bus contents (CE, CK and DA). */ + i = inb_p(gt->io); + /* Write it back with mute flag set. */ + outb_p((i >> 5) | GEMTEK_MT, gt->io); + udelay(SHORT_DELAY); + + mutex_unlock(>->lock); } /* * Unset mute flag. */ -static void gemtek_unmute(struct gemtek_device *dev) +static void gemtek_unmute(struct gemtek *gt) { int i; - dev->muted = 0; + gt->muted = 0; if (hardmute) { /* Turn PLL back on. */ - gemtek_setfreq(dev, dev->lastfreq); - } else { - spin_lock(&lock); + gemtek_setfreq(gt, gt->lastfreq); + return; + } + mutex_lock(>->lock); - i = inb_p(io); - outb_p(i >> 5, io); - udelay(SHORT_DELAY); + i = inb_p(gt->io); + outb_p(i >> 5, gt->io); + udelay(SHORT_DELAY); - spin_unlock(&lock); - } + mutex_unlock(>->lock); } /* * Get signal strength (= stereo status). */ -static inline int gemtek_getsigstr(void) +static inline int gemtek_getsigstr(struct gemtek *gt) { - return inb_p(io) & GEMTEK_NS ? 0 : 1; + int sig; + + mutex_lock(>->lock); + sig = inb_p(gt->io) & GEMTEK_NS ? 0 : 1; + mutex_unlock(>->lock); + return sig; } /* * Check if requested card acts like GemTek Radio card. */ -static int gemtek_verify(int port) +static int gemtek_verify(struct gemtek *gt, int port) { - static int verified = -1; int i, q; - if (verified == port) + if (gt->verified == port) return 1; - spin_lock(&lock); + mutex_lock(>->lock); q = inb_p(port); /* Read bus contents before probing. */ /* Try to turn on CE, CK and DA respectively and check if card responds @@ -317,15 +320,15 @@ static int gemtek_verify(int port) udelay(SHORT_DELAY); if ((inb_p(port) & (~GEMTEK_NS)) != (0x17 | (1 << (i + 5)))) { - spin_unlock(&lock); + mutex_unlock(>->lock); return 0; } } outb_p(q >> 5, port); /* Write bus contents back. */ udelay(SHORT_DELAY); - spin_unlock(&lock); - verified = port; + mutex_unlock(>->lock); + gt->verified = port; return 1; } @@ -333,83 +336,61 @@ static int gemtek_verify(int port) /* * Automatic probing for card. */ -static int gemtek_probe(void) +static int gemtek_probe(struct gemtek *gt) { + struct v4l2_device *v4l2_dev = >->v4l2_dev; int ioports[] = { 0x20c, 0x30c, 0x24c, 0x34c, 0x248, 0x28c }; int i; if (!probe) { - printk(KERN_INFO "Automatic device probing disabled.\n"); + v4l2_info(v4l2_dev, "Automatic device probing disabled.\n"); return -1; } - printk(KERN_INFO "Automatic device probing enabled.\n"); + v4l2_info(v4l2_dev, "Automatic device probing enabled.\n"); for (i = 0; i < ARRAY_SIZE(ioports); ++i) { - printk(KERN_INFO "Trying I/O port 0x%x...\n", ioports[i]); + v4l2_info(v4l2_dev, "Trying I/O port 0x%x...\n", ioports[i]); if (!request_region(ioports[i], 1, "gemtek-probe")) { - printk(KERN_WARNING "I/O port 0x%x busy!\n", + v4l2_warn(v4l2_dev, "I/O port 0x%x busy!\n", ioports[i]); continue; } - if (gemtek_verify(ioports[i])) { - printk(KERN_INFO "Card found from I/O port " + if (gemtek_verify(gt, ioports[i])) { + v4l2_info(v4l2_dev, "Card found from I/O port " "0x%x!\n", ioports[i]); release_region(ioports[i], 1); - - io = ioports[i]; - return io; + gt->io = ioports[i]; + return gt->io; } release_region(ioports[i], 1); } - printk(KERN_ERR "Automatic probing failed!\n"); - + v4l2_err(v4l2_dev, "Automatic probing failed!\n"); return -1; } /* * Video 4 Linux stuff. */ - -static struct v4l2_queryctrl radio_qctrl[] = { - { - .id = V4L2_CID_AUDIO_MUTE, - .name = "Mute", - .minimum = 0, - .maximum = 1, - .default_value = 1, - .type = V4L2_CTRL_TYPE_BOOLEAN, - }, { - .id = V4L2_CID_AUDIO_VOLUME, - .name = "Volume", - .minimum = 0, - .maximum = 65535, - .step = 65535, - .default_value = 0xff, - .type = V4L2_CTRL_TYPE_INTEGER, - } -}; - -static int gemtek_exclusive_open(struct file *file) +static int gemtek_open(struct file *file) { - return test_and_set_bit(0, &in_use) ? -EBUSY : 0; + return 0; } -static int gemtek_exclusive_release(struct file *file) +static int gemtek_release(struct file *file) { - clear_bit(0, &in_use); return 0; } static const struct v4l2_file_operations gemtek_fops = { .owner = THIS_MODULE, - .open = gemtek_exclusive_open, - .release = gemtek_exclusive_release, + .open = gemtek_open, + .release = gemtek_release, .ioctl = video_ioctl2, }; @@ -418,23 +399,25 @@ static int vidioc_querycap(struct file *file, void *priv, { strlcpy(v->driver, "radio-gemtek", sizeof(v->driver)); strlcpy(v->card, "GemTek", sizeof(v->card)); - sprintf(v->bus_info, "ISA"); + strlcpy(v->bus_info, "ISA", sizeof(v->bus_info)); v->version = RADIO_VERSION; - v->capabilities = V4L2_CAP_TUNER; + v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO; return 0; } static int vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *v) { + struct gemtek *gt = video_drvdata(file); + if (v->index > 0) return -EINVAL; - strcpy(v->name, "FM"); + strlcpy(v->name, "FM", sizeof(v->name)); v->type = V4L2_TUNER_RADIO; v->rangelow = GEMTEK_LOWFREQ; v->rangehigh = GEMTEK_HIGHFREQ; v->capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO; - v->signal = 0xffff * gemtek_getsigstr(); + v->signal = 0xffff * gemtek_getsigstr(gt); if (v->signal) { v->audmode = V4L2_TUNER_MODE_STEREO; v->rxsubchans = V4L2_TUNER_SUB_STEREO; @@ -442,65 +425,56 @@ static int vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *v) v->audmode = V4L2_TUNER_MODE_MONO; v->rxsubchans = V4L2_TUNER_SUB_MONO; } - return 0; } static int vidioc_s_tuner(struct file *file, void *priv, struct v4l2_tuner *v) { - if (v->index > 0) - return -EINVAL; - return 0; + return (v->index != 0) ? -EINVAL : 0; } -static int vidioc_s_frequency(struct file *file, void *priv, +static int vidioc_g_frequency(struct file *file, void *priv, struct v4l2_frequency *f) { - struct gemtek_device *rt = video_drvdata(file); - - gemtek_setfreq(rt, f->frequency); + struct gemtek *gt = video_drvdata(file); + if (f->tuner != 0) + return -EINVAL; + f->type = V4L2_TUNER_RADIO; + f->frequency = gt->lastfreq; return 0; } -static int vidioc_g_frequency(struct file *file, void *priv, +static int vidioc_s_frequency(struct file *file, void *priv, struct v4l2_frequency *f) { - struct gemtek_device *rt = video_drvdata(file); + struct gemtek *gt = video_drvdata(file); - f->type = V4L2_TUNER_RADIO; - f->frequency = rt->lastfreq; + if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO) + return -EINVAL; + gemtek_setfreq(gt, f->frequency); return 0; } static int vidioc_queryctrl(struct file *file, void *priv, struct v4l2_queryctrl *qc) { - int i; - - for (i = 0; i < ARRAY_SIZE(radio_qctrl); ++i) { - if (qc->id && qc->id == radio_qctrl[i].id) { - memcpy(qc, &(radio_qctrl[i]), sizeof(*qc)); - return 0; - } + switch (qc->id) { + case V4L2_CID_AUDIO_MUTE: + return v4l2_ctrl_query_fill(qc, 0, 1, 1, 0); + default: + return -EINVAL; } - return -EINVAL; } static int vidioc_g_ctrl(struct file *file, void *priv, struct v4l2_control *ctrl) { - struct gemtek_device *rt = video_drvdata(file); + struct gemtek *gt = video_drvdata(file); switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: - ctrl->value = rt->muted; - return 0; - case V4L2_CID_AUDIO_VOLUME: - if (rt->muted) - ctrl->value = 0; - else - ctrl->value = 65535; + ctrl->value = gt->muted; return 0; } return -EINVAL; @@ -509,35 +483,19 @@ static int vidioc_g_ctrl(struct file *file, void *priv, static int vidioc_s_ctrl(struct file *file, void *priv, struct v4l2_control *ctrl) { - struct gemtek_device *rt = video_drvdata(file); + struct gemtek *gt = video_drvdata(file); switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: if (ctrl->value) - gemtek_mute(rt); - else - gemtek_unmute(rt); - return 0; - case V4L2_CID_AUDIO_VOLUME: - if (ctrl->value) - gemtek_unmute(rt); + gemtek_mute(gt); else - gemtek_mute(rt); + gemtek_unmute(gt); return 0; } return -EINVAL; } -static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a) -{ - if (a->index > 1) - return -EINVAL; - - strcpy(a->name, "Radio"); - a->capability = V4L2_AUDCAP_STEREO; - return 0; -} - static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i) { *i = 0; @@ -546,16 +504,20 @@ static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i) static int vidioc_s_input(struct file *filp, void *priv, unsigned int i) { - if (i != 0) - return -EINVAL; + return (i != 0) ? -EINVAL : 0; +} + +static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a) +{ + a->index = 0; + strlcpy(a->name, "Radio", sizeof(a->name)); + a->capability = V4L2_AUDCAP_STEREO; return 0; } static int vidioc_s_audio(struct file *file, void *priv, struct v4l2_audio *a) { - if (a->index != 0) - return -EINVAL; - return 0; + return (a->index != 0) ? -EINVAL : 0; } static const struct v4l2_ioctl_ops gemtek_ioctl_ops = { @@ -573,62 +535,73 @@ static const struct v4l2_ioctl_ops gemtek_ioctl_ops = { .vidioc_s_ctrl = vidioc_s_ctrl }; -static struct video_device gemtek_radio = { - .name = "GemTek Radio card", - .fops = &gemtek_fops, - .ioctl_ops = &gemtek_ioctl_ops, - .release = video_device_release_empty, -}; - /* * Initialization / cleanup related stuff. */ -/* - * Initilize card. - */ static int __init gemtek_init(void) { - printk(KERN_INFO RADIO_BANNER "\n"); + struct gemtek *gt = &gemtek_card; + struct v4l2_device *v4l2_dev = >->v4l2_dev; + int res; - spin_lock_init(&lock); + strlcpy(v4l2_dev->name, "gemtek", sizeof(v4l2_dev->name)); - gemtek_probe(); - if (io) { - if (!request_region(io, 1, "gemtek")) { - printk(KERN_ERR "I/O port 0x%x already in use.\n", io); + v4l2_info(v4l2_dev, "GemTek Radio card driver: v0.0.3\n"); + + mutex_init(>->lock); + + gt->verified = -1; + gt->io = io; + gemtek_probe(gt); + if (gt->io) { + if (!request_region(gt->io, 1, "gemtek")) { + v4l2_err(v4l2_dev, "I/O port 0x%x already in use.\n", gt->io); return -EBUSY; } - if (!gemtek_verify(io)) - printk(KERN_WARNING "Card at I/O port 0x%x does not " + if (!gemtek_verify(gt, gt->io)) + v4l2_warn(v4l2_dev, "Card at I/O port 0x%x does not " "respond properly, check your " - "configuration.\n", io); + "configuration.\n", gt->io); else - printk(KERN_INFO "Using I/O port 0x%x.\n", io); + v4l2_info(v4l2_dev, "Using I/O port 0x%x.\n", gt->io); } else if (probe) { - printk(KERN_ERR "Automatic probing failed and no " + v4l2_err(v4l2_dev, "Automatic probing failed and no " "fixed I/O port defined.\n"); return -ENODEV; } else { - printk(KERN_ERR "Automatic probing disabled but no fixed " + v4l2_err(v4l2_dev, "Automatic probing disabled but no fixed " "I/O port defined."); return -EINVAL; } - video_set_drvdata(&gemtek_radio, &gemtek_unit); + res = v4l2_device_register(NULL, v4l2_dev); + if (res < 0) { + v4l2_err(v4l2_dev, "Could not register v4l2_device\n"); + release_region(gt->io, 1); + return res; + } - if (video_register_device(&gemtek_radio, VFL_TYPE_RADIO, radio_nr) < 0) { - release_region(io, 1); + strlcpy(gt->vdev.name, v4l2_dev->name, sizeof(gt->vdev.name)); + gt->vdev.v4l2_dev = v4l2_dev; + gt->vdev.fops = &gemtek_fops; + gt->vdev.ioctl_ops = &gemtek_ioctl_ops; + gt->vdev.release = video_device_release_empty; + video_set_drvdata(>->vdev, gt); + + if (video_register_device(>->vdev, VFL_TYPE_RADIO, radio_nr) < 0) { + v4l2_device_unregister(v4l2_dev); + release_region(gt->io, 1); return -EBUSY; } /* Set defaults */ - gemtek_unit.lastfreq = GEMTEK_LOWFREQ; - gemtek_unit.bu2614data = 0; + gt->lastfreq = GEMTEK_LOWFREQ; + gt->bu2614data = 0; if (initmute) - gemtek_mute(&gemtek_unit); + gemtek_mute(gt); return 0; } @@ -638,15 +611,19 @@ static int __init gemtek_init(void) */ static void __exit gemtek_exit(void) { + struct gemtek *gt = &gemtek_card; + struct v4l2_device *v4l2_dev = >->v4l2_dev; + if (shutdown) { hardmute = 1; /* Turn off PLL */ - gemtek_mute(&gemtek_unit); + gemtek_mute(gt); } else { - printk(KERN_INFO "Module unloaded but card not muted!\n"); + v4l2_info(v4l2_dev, "Module unloaded but card not muted!\n"); } - video_unregister_device(&gemtek_radio); - release_region(io, 1); + video_unregister_device(>->vdev); + v4l2_device_unregister(>->v4l2_dev); + release_region(gt->io, 1); } module_init(gemtek_init); -- cgit v1.2.3 From a6922f733d048625fdb478ea22a1964acad3ef58 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 6 Mar 2009 17:51:08 +0100 Subject: radio-maestro: convert to v4l2_device. From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/radio/radio-maestro.c | 338 +++++++++++++++--------------- 1 file changed, 164 insertions(+), 174 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/radio/radio-maestro.c b/linux/drivers/media/radio/radio-maestro.c index 7442be614..b35092f30 100644 --- a/linux/drivers/media/radio/radio-maestro.c +++ b/linux/drivers/media/radio/radio-maestro.c @@ -22,28 +22,24 @@ #include #include #include -#include -#include +#include /* for KERNEL_VERSION MACRO */ #include #include -#include +#include +#include +#include #include #include "compat.h" -#include /* for KERNEL_VERSION MACRO */ -#define RADIO_VERSION KERNEL_VERSION(0,0,6) -#define DRIVER_VERSION "0.06" +MODULE_AUTHOR("Adam Tlalka, atlka@pg.gda.pl"); +MODULE_DESCRIPTION("Radio driver for the Maestro PCI sound card radio."); +MODULE_LICENSE("GPL"); -static struct v4l2_queryctrl radio_qctrl[] = { - { - .id = V4L2_CID_AUDIO_MUTE, - .name = "Mute", - .minimum = 0, - .maximum = 1, - .default_value = 1, - .type = V4L2_CTRL_TYPE_BOOLEAN, - } -}; +static int radio_nr = -1; +module_param(radio_nr, int, 0); + +#define RADIO_VERSION KERNEL_VERSION(0, 0, 6) +#define DRIVER_VERSION "0.06" #define GPIO_DATA 0x60 /* port offset from ESS_IO_BASE */ @@ -73,62 +69,27 @@ static struct v4l2_queryctrl radio_qctrl[] = { #define BITS2FREQ(x) ((x) * FREQ_STEP - FREQ_IF) -static int radio_nr = -1; -module_param(radio_nr, int, 0); +struct maestro { + struct v4l2_device v4l2_dev; + struct video_device vdev; + struct pci_dev *pdev; + struct mutex lock; -static unsigned long in_use; - -static int maestro_probe(struct pci_dev *pdev, const struct pci_device_id *ent); + u16 io; /* base of Maestro card radio io (GPIO_DATA)*/ + u16 muted; /* VIDEO_AUDIO_MUTE */ + u16 stereo; /* VIDEO_TUNER_STEREO_ON */ + u16 tuned; /* signal strength (0 or 0xffff) */ +}; -static int maestro_exclusive_open(struct file *file) +static inline struct maestro *to_maestro(struct v4l2_device *v4l2_dev) { - return test_and_set_bit(0, &in_use) ? -EBUSY : 0; + return container_of(v4l2_dev, struct maestro, v4l2_dev); } -static int maestro_exclusive_release(struct file *file) +static u32 radio_bits_get(struct maestro *dev) { - clear_bit(0, &in_use); - return 0; -} - -static void maestro_remove(struct pci_dev *pdev); - -static struct pci_device_id maestro_r_pci_tbl[] = { - { PCI_DEVICE(PCI_VENDOR_ID_ESS, PCI_DEVICE_ID_ESS_ESS1968), - .class = PCI_CLASS_MULTIMEDIA_AUDIO << 8, - .class_mask = 0xffff00 }, - { PCI_DEVICE(PCI_VENDOR_ID_ESS, PCI_DEVICE_ID_ESS_ESS1978), - .class = PCI_CLASS_MULTIMEDIA_AUDIO << 8, - .class_mask = 0xffff00 }, - { 0 } -}; -MODULE_DEVICE_TABLE(pci, maestro_r_pci_tbl); - -static struct pci_driver maestro_r_driver = { - .name = "maestro_radio", - .id_table = maestro_r_pci_tbl, - .probe = maestro_probe, - .remove = __devexit_p(maestro_remove), -}; - -static const struct v4l2_file_operations maestro_fops = { - .owner = THIS_MODULE, - .open = maestro_exclusive_open, - .release = maestro_exclusive_release, - .ioctl = video_ioctl2, -}; - -struct radio_device { - u16 io, /* base of Maestro card radio io (GPIO_DATA)*/ - muted, /* VIDEO_AUDIO_MUTE */ - stereo, /* VIDEO_TUNER_STEREO_ON */ - tuned; /* signal strength (0 or 0xffff) */ -}; - -static u32 radio_bits_get(struct radio_device *dev) -{ - register u16 io=dev->io, l, rdata; - register u32 data=0; + u16 io = dev->io, l, rdata; + u32 data = 0; u16 omask; omask = inw(io + IO_MASK); @@ -136,25 +97,23 @@ static u32 radio_bits_get(struct radio_device *dev) outw(0, io); udelay(16); - for (l=24;l--;) { + for (l = 24; l--;) { outw(STR_CLK, io); /* HI state */ udelay(2); - if(!l) + if (!l) dev->tuned = inw(io) & STR_MOST ? 0 : 0xffff; outw(0, io); /* LO state */ udelay(2); data <<= 1; /* shift data */ rdata = inw(io); - if(!l) - dev->stereo = rdata & STR_MOST ? - 0 : 1; - else - if(rdata & STR_DATA) - data++; + if (!l) + dev->stereo = (rdata & STR_MOST) ? 0 : 1; + else if (rdata & STR_DATA) + data++; udelay(2); } - if(dev->muted) + if (dev->muted) outw(STR_WREN, io); udelay(4); @@ -163,18 +122,18 @@ static u32 radio_bits_get(struct radio_device *dev) return data & 0x3ffe; } -static void radio_bits_set(struct radio_device *dev, u32 data) +static void radio_bits_set(struct maestro *dev, u32 data) { - register u16 io=dev->io, l, bits; + u16 io = dev->io, l, bits; u16 omask, odir; omask = inw(io + IO_MASK); - odir = (inw(io + IO_DIR) & ~STR_DATA) | (STR_CLK | STR_WREN); + odir = (inw(io + IO_DIR) & ~STR_DATA) | (STR_CLK | STR_WREN); outw(odir | STR_DATA, io + IO_DIR); outw(~(STR_DATA | STR_CLK | STR_WREN), io + IO_MASK); udelay(16); - for (l=25;l;l--) { - bits = ((data >> 18) & STR_DATA) | STR_WREN ; + for (l = 25; l; l--) { + bits = ((data >> 18) & STR_DATA) | STR_WREN; data <<= 1; /* shift data */ outw(bits, io); /* start strobe */ udelay(2); @@ -184,7 +143,7 @@ static void radio_bits_set(struct radio_device *dev, u32 data) udelay(4); } - if(!dev->muted) + if (!dev->muted) outw(0, io); udelay(4); @@ -196,78 +155,79 @@ static void radio_bits_set(struct radio_device *dev, u32 data) static int vidioc_querycap(struct file *file, void *priv, struct v4l2_capability *v) { + struct maestro *dev = video_drvdata(file); + strlcpy(v->driver, "radio-maestro", sizeof(v->driver)); strlcpy(v->card, "Maestro Radio", sizeof(v->card)); - sprintf(v->bus_info, "PCI"); + snprintf(v->bus_info, sizeof(v->bus_info), "PCI:%s", pci_name(dev->pdev)); v->version = RADIO_VERSION; - v->capabilities = V4L2_CAP_TUNER; + v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO; return 0; } static int vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *v) { - struct radio_device *card = video_drvdata(file); + struct maestro *dev = video_drvdata(file); if (v->index > 0) return -EINVAL; - (void)radio_bits_get(card); + mutex_lock(&dev->lock); + radio_bits_get(dev); - strcpy(v->name, "FM"); + strlcpy(v->name, "FM", sizeof(v->name)); v->type = V4L2_TUNER_RADIO; v->rangelow = FREQ_LO; v->rangehigh = FREQ_HI; - v->rxsubchans = V4L2_TUNER_SUB_MONO|V4L2_TUNER_SUB_STEREO; + v->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO; v->capability = V4L2_TUNER_CAP_LOW; - if(card->stereo) + if (dev->stereo) v->audmode = V4L2_TUNER_MODE_STEREO; else v->audmode = V4L2_TUNER_MODE_MONO; - v->signal = card->tuned; + v->signal = dev->tuned; + mutex_unlock(&dev->lock); return 0; } static int vidioc_s_tuner(struct file *file, void *priv, struct v4l2_tuner *v) { - if (v->index > 0) - return -EINVAL; - return 0; + return v->index ? -EINVAL : 0; } static int vidioc_s_frequency(struct file *file, void *priv, struct v4l2_frequency *f) { - struct radio_device *card = video_drvdata(file); + struct maestro *dev = video_drvdata(file); if (f->frequency < FREQ_LO || f->frequency > FREQ_HI) return -EINVAL; - radio_bits_set(card, FREQ2BITS(f->frequency)); + mutex_lock(&dev->lock); + radio_bits_set(dev, FREQ2BITS(f->frequency)); + mutex_unlock(&dev->lock); return 0; } static int vidioc_g_frequency(struct file *file, void *priv, struct v4l2_frequency *f) { - struct radio_device *card = video_drvdata(file); + struct maestro *dev = video_drvdata(file); f->type = V4L2_TUNER_RADIO; - f->frequency = BITS2FREQ(radio_bits_get(card)); + mutex_lock(&dev->lock); + f->frequency = BITS2FREQ(radio_bits_get(dev)); + mutex_unlock(&dev->lock); return 0; } static int vidioc_queryctrl(struct file *file, void *priv, struct v4l2_queryctrl *qc) { - int i; - - for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) { - if (qc->id && qc->id == radio_qctrl[i].id) { - memcpy(qc, &(radio_qctrl[i]), - sizeof(*qc)); - return 0; - } + switch (qc->id) { + case V4L2_CID_AUDIO_MUTE: + return v4l2_ctrl_query_fill(qc, 0, 1, 1, 1); } return -EINVAL; } @@ -275,11 +235,11 @@ static int vidioc_queryctrl(struct file *file, void *priv, static int vidioc_g_ctrl(struct file *file, void *priv, struct v4l2_control *ctrl) { - struct radio_device *card = video_drvdata(file); + struct maestro *dev = video_drvdata(file); switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: - ctrl->value = card->muted; + ctrl->value = dev->muted; return 0; } return -EINVAL; @@ -288,56 +248,85 @@ static int vidioc_g_ctrl(struct file *file, void *priv, static int vidioc_s_ctrl(struct file *file, void *priv, struct v4l2_control *ctrl) { - struct radio_device *card = video_drvdata(file); - register u16 io = card->io; - register u16 omask = inw(io + IO_MASK); + struct maestro *dev = video_drvdata(file); + u16 io = dev->io; + u16 omask; switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: + mutex_lock(&dev->lock); + omask = inw(io + IO_MASK); outw(~STR_WREN, io + IO_MASK); - outw((card->muted = ctrl->value ) ? - STR_WREN : 0, io); + dev->muted = ctrl->value; + outw(dev->muted ? STR_WREN : 0, io); udelay(4); outw(omask, io + IO_MASK); msleep(125); + mutex_unlock(&dev->lock); return 0; } return -EINVAL; } +static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i) +{ + *i = 0; + return 0; +} + +static int vidioc_s_input(struct file *filp, void *priv, unsigned int i) +{ + return i ? -EINVAL : 0; +} + static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a) { - if (a->index > 1) - return -EINVAL; - - strcpy(a->name, "Radio"); + a->index = 0; + strlcpy(a->name, "Radio", sizeof(a->name)); a->capability = V4L2_AUDCAP_STEREO; return 0; } -static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i) +static int vidioc_s_audio(struct file *file, void *priv, + struct v4l2_audio *a) { - *i = 0; - return 0; + return a->index ? -EINVAL : 0; } -static int vidioc_s_input(struct file *filp, void *priv, unsigned int i) +static int maestro_open(struct file *file) { - if (i != 0) - return -EINVAL; return 0; } -static int vidioc_s_audio(struct file *file, void *priv, - struct v4l2_audio *a) +static int maestro_release(struct file *file) { - if (a->index != 0) - return -EINVAL; return 0; } -static u16 __devinit radio_power_on(struct radio_device *dev) +static const struct v4l2_file_operations maestro_fops = { + .owner = THIS_MODULE, + .open = maestro_open, + .release = maestro_release, + .ioctl = video_ioctl2, +}; + +static const struct v4l2_ioctl_ops maestro_ioctl_ops = { + .vidioc_querycap = vidioc_querycap, + .vidioc_g_tuner = vidioc_g_tuner, + .vidioc_s_tuner = vidioc_s_tuner, + .vidioc_g_audio = vidioc_g_audio, + .vidioc_s_audio = vidioc_s_audio, + .vidioc_g_input = vidioc_g_input, + .vidioc_s_input = vidioc_s_input, + .vidioc_g_frequency = vidioc_g_frequency, + .vidioc_s_frequency = vidioc_s_frequency, + .vidioc_queryctrl = vidioc_queryctrl, + .vidioc_g_ctrl = vidioc_g_ctrl, + .vidioc_s_ctrl = vidioc_s_ctrl, +}; + +static u16 __devinit radio_power_on(struct maestro *dev) { register u16 io = dev->io; register u32 ofreq; @@ -361,33 +350,11 @@ static u16 __devinit radio_power_on(struct radio_device *dev) return (ofreq == radio_bits_get(dev)); } -static const struct v4l2_ioctl_ops maestro_ioctl_ops = { - .vidioc_querycap = vidioc_querycap, - .vidioc_g_tuner = vidioc_g_tuner, - .vidioc_s_tuner = vidioc_s_tuner, - .vidioc_g_audio = vidioc_g_audio, - .vidioc_s_audio = vidioc_s_audio, - .vidioc_g_input = vidioc_g_input, - .vidioc_s_input = vidioc_s_input, - .vidioc_g_frequency = vidioc_g_frequency, - .vidioc_s_frequency = vidioc_s_frequency, - .vidioc_queryctrl = vidioc_queryctrl, - .vidioc_g_ctrl = vidioc_g_ctrl, - .vidioc_s_ctrl = vidioc_s_ctrl, -}; - -static struct video_device maestro_radio = { - .name = "Maestro radio", - .fops = &maestro_fops, - .ioctl_ops = &maestro_ioctl_ops, - .release = video_device_release, -}; - static int __devinit maestro_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { - struct radio_device *radio_unit; - struct video_device *maestro_radio_inst; + struct maestro *dev; + struct v4l2_device *v4l2_dev; int retval; retval = pci_enable_device(pdev); @@ -398,46 +365,53 @@ static int __devinit maestro_probe(struct pci_dev *pdev, retval = -ENOMEM; - radio_unit = kzalloc(sizeof(*radio_unit), GFP_KERNEL); - if (radio_unit == NULL) { + dev = kzalloc(sizeof(*dev), GFP_KERNEL); + if (dev == NULL) { dev_err(&pdev->dev, "not enough memory\n"); goto err; } - radio_unit->io = pci_resource_start(pdev, 0) + GPIO_DATA; + v4l2_dev = &dev->v4l2_dev; + mutex_init(&dev->lock); + dev->pdev = pdev; - maestro_radio_inst = video_device_alloc(); - if (maestro_radio_inst == NULL) { - dev_err(&pdev->dev, "not enough memory\n"); + strlcpy(v4l2_dev->name, "maestro", sizeof(v4l2_dev->name)); + + retval = v4l2_device_register(&pdev->dev, v4l2_dev); + if (retval < 0) { + v4l2_err(v4l2_dev, "Could not register v4l2_device\n"); goto errfr; } - memcpy(maestro_radio_inst, &maestro_radio, sizeof(maestro_radio)); - video_set_drvdata(maestro_radio_inst, radio_unit); - pci_set_drvdata(pdev, maestro_radio_inst); + dev->io = pci_resource_start(pdev, 0) + GPIO_DATA; - retval = video_register_device(maestro_radio_inst, VFL_TYPE_RADIO, radio_nr); + strlcpy(dev->vdev.name, v4l2_dev->name, sizeof(dev->vdev.name)); + dev->vdev.v4l2_dev = v4l2_dev; + dev->vdev.fops = &maestro_fops; + dev->vdev.ioctl_ops = &maestro_ioctl_ops; + dev->vdev.release = video_device_release_empty; + video_set_drvdata(&dev->vdev, dev); + + retval = video_register_device(&dev->vdev, VFL_TYPE_RADIO, radio_nr); if (retval) { - printk(KERN_ERR "can't register video device!\n"); + v4l2_err(v4l2_dev, "can't register video device!\n"); goto errfr1; } - if (!radio_power_on(radio_unit)) { + if (!radio_power_on(dev)) { retval = -EIO; goto errunr; } - dev_info(&pdev->dev, "version " DRIVER_VERSION " time " __TIME__ " " - __DATE__ "\n"); - dev_info(&pdev->dev, "radio chip initialized\n"); + v4l2_info(v4l2_dev, "version " DRIVER_VERSION "\n"); return 0; errunr: - video_unregister_device(maestro_radio_inst); + video_unregister_device(&dev->vdev); errfr1: - video_device_release(maestro_radio_inst); + v4l2_device_unregister(v4l2_dev); errfr: - kfree(radio_unit); + kfree(dev); err: return retval; @@ -445,11 +419,31 @@ err: static void __devexit maestro_remove(struct pci_dev *pdev) { - struct video_device *vdev = pci_get_drvdata(pdev); + struct v4l2_device *v4l2_dev = dev_get_drvdata(&pdev->dev); + struct maestro *dev = to_maestro(v4l2_dev); - video_unregister_device(vdev); + video_unregister_device(&dev->vdev); + v4l2_device_unregister(&dev->v4l2_dev); } +static struct pci_device_id maestro_r_pci_tbl[] = { + { PCI_DEVICE(PCI_VENDOR_ID_ESS, PCI_DEVICE_ID_ESS_ESS1968), + .class = PCI_CLASS_MULTIMEDIA_AUDIO << 8, + .class_mask = 0xffff00 }, + { PCI_DEVICE(PCI_VENDOR_ID_ESS, PCI_DEVICE_ID_ESS_ESS1978), + .class = PCI_CLASS_MULTIMEDIA_AUDIO << 8, + .class_mask = 0xffff00 }, + { 0 } +}; +MODULE_DEVICE_TABLE(pci, maestro_r_pci_tbl); + +static struct pci_driver maestro_r_driver = { + .name = "maestro_radio", + .id_table = maestro_r_pci_tbl, + .probe = maestro_probe, + .remove = __devexit_p(maestro_remove), +}; + static int __init maestro_radio_init(void) { int retval = pci_register_driver(&maestro_r_driver); @@ -467,7 +461,3 @@ static void __exit maestro_radio_exit(void) module_init(maestro_radio_init); module_exit(maestro_radio_exit); - -MODULE_AUTHOR("Adam Tlalka, atlka@pg.gda.pl"); -MODULE_DESCRIPTION("Radio driver for the Maestro PCI sound card radio."); -MODULE_LICENSE("GPL"); -- cgit v1.2.3 From 8dcdc9fab2af7f5123f3660b04f2ca497d6ec098 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 6 Mar 2009 17:51:33 +0100 Subject: radio-maxiradio: convert to v4l2_device. From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/radio/radio-maxiradio.c | 375 ++++++++++++++-------------- 1 file changed, 186 insertions(+), 189 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/radio/radio-maxiradio.c b/linux/drivers/media/radio/radio-maxiradio.c index cb9d07bc7..fa2c5f1ef 100644 --- a/linux/drivers/media/radio/radio-maxiradio.c +++ b/linux/drivers/media/radio/radio-maxiradio.c @@ -37,39 +37,34 @@ #include #include #include -#include -#include #include - #include #include -#include +#include /* for KERNEL_VERSION MACRO */ +#include +#include +#include #include #include "compat.h" +MODULE_AUTHOR("Dimitromanolakis Apostolos, apdim@grecian.net"); +MODULE_DESCRIPTION("Radio driver for the Guillemot Maxi Radio FM2000 radio."); +MODULE_LICENSE("GPL"); + +static int radio_nr = -1; +module_param(radio_nr, int, 0); + +static int debug; + +module_param(debug, int, 0644); +MODULE_PARM_DESC(debug, "activates debug info"); + #define DRIVER_VERSION "0.77" -#include /* for KERNEL_VERSION MACRO */ -#define RADIO_VERSION KERNEL_VERSION(0,7,7) - -static struct video_device maxiradio_radio; - -#define dprintk(num, fmt, arg...) \ - do { \ - if (maxiradio_radio.debug >= num) \ - printk(KERN_DEBUG "%s: " fmt, \ - maxiradio_radio.name, ## arg); } while (0) - -static struct v4l2_queryctrl radio_qctrl[] = { - { - .id = V4L2_CID_AUDIO_MUTE, - .name = "Mute", - .minimum = 0, - .maximum = 1, - .default_value = 1, - .type = V4L2_CTRL_TYPE_BOOLEAN, - } -}; +#define RADIO_VERSION KERNEL_VERSION(0, 7, 7) + +#define dprintk(dev, num, fmt, arg...) \ + v4l2_dbg(num, debug, &dev->v4l2_dev, fmt, ## arg) #ifndef PCI_VENDOR_ID_GUILLEMOT #define PCI_VENDOR_ID_GUILLEMOT 0x5046 @@ -81,90 +76,70 @@ static struct v4l2_queryctrl radio_qctrl[] = { /* TEA5757 pin mappings */ -static const int clk = 1, data = 2, wren = 4, mo_st = 8, power = 16 ; - -static int radio_nr = -1; -module_param(radio_nr, int, 0); +static const int clk = 1, data = 2, wren = 4, mo_st = 8, power = 16; -static unsigned long in_use; - -#define FREQ_LO 50*16000 -#define FREQ_HI 150*16000 +#define FREQ_LO (50 * 16000) +#define FREQ_HI (150 * 16000) #define FREQ_IF 171200 /* 10.7*16000 */ #define FREQ_STEP 200 /* 12.5*16 */ /* (x==fmhz*16*1000) -> bits */ -#define FREQ2BITS(x) ((( (unsigned int)(x)+FREQ_IF+(FREQ_STEP<<1)) \ - /(FREQ_STEP<<2))<<2) +#define FREQ2BITS(x) \ + ((((unsigned int)(x) + FREQ_IF + (FREQ_STEP << 1)) / (FREQ_STEP << 2)) << 2) #define BITS2FREQ(x) ((x) * FREQ_STEP - FREQ_IF) -static int maxiradio_exclusive_open(struct file *file) +struct maxiradio { - return test_and_set_bit(0, &in_use) ? -EBUSY : 0; -} - -static int maxiradio_exclusive_release(struct file *file) -{ - clear_bit(0, &in_use); - return 0; -} - -static const struct v4l2_file_operations maxiradio_fops = { - .owner = THIS_MODULE, - .open = maxiradio_exclusive_open, - .release = maxiradio_exclusive_release, - .ioctl = video_ioctl2, -}; + struct v4l2_device v4l2_dev; + struct video_device vdev; + struct pci_dev *pdev; -static struct radio_device -{ - __u16 io, /* base of radio io */ - muted, /* VIDEO_AUDIO_MUTE */ - stereo, /* VIDEO_TUNER_STEREO_ON */ - tuned; /* signal strength (0 or 0xffff) */ + u16 io; /* base of radio io */ + u16 muted; /* VIDEO_AUDIO_MUTE */ + u16 stereo; /* VIDEO_TUNER_STEREO_ON */ + u16 tuned; /* signal strength (0 or 0xffff) */ unsigned long freq; struct mutex lock; -} radio_unit = { - .muted =1, - .freq = FREQ_LO, }; -static void outbit(unsigned long bit, __u16 io) +static inline struct maxiradio *to_maxiradio(struct v4l2_device *v4l2_dev) { - if (bit != 0) - { - outb( power|wren|data ,io); udelay(4); - outb( power|wren|data|clk ,io); udelay(4); - outb( power|wren|data ,io); udelay(4); - } - else - { - outb( power|wren ,io); udelay(4); - outb( power|wren|clk ,io); udelay(4); - outb( power|wren ,io); udelay(4); - } + return container_of(v4l2_dev, struct maxiradio, v4l2_dev); } -static void turn_power(__u16 io, int p) +static void outbit(unsigned long bit, u16 io) +{ + int val = power | wren | (bit ? data : 0); + + outb(val, io); + udelay(4); + outb(val | clk, io); + udelay(4); + outb(val, io); + udelay(4); +} + +static void turn_power(struct maxiradio *dev, int p) { if (p != 0) { - dprintk(1, "Radio powered on\n"); - outb(power, io); + dprintk(dev, 1, "Radio powered on\n"); + outb(power, dev->io); } else { - dprintk(1, "Radio powered off\n"); - outb(0,io); + dprintk(dev, 1, "Radio powered off\n"); + outb(0, dev->io); } } -static void set_freq(__u16 io, __u32 freq) +static void set_freq(struct maxiradio *dev, u32 freq) { unsigned long int si; int bl; + int io = dev->io; int val = FREQ2BITS(freq); /* TEA5757 shift register bits (see pdf) */ @@ -189,14 +164,14 @@ static void set_freq(__u16 io, __u32 freq) si >>= 1; } - dprintk(1, "Radio freq set to %d.%02d MHz\n", + dprintk(dev, 1, "Radio freq set to %d.%02d MHz\n", freq / 16000, freq % 16000 * 100 / 16000); - turn_power(io, 1); + turn_power(dev, 1); } -static int get_stereo(__u16 io) +static int get_stereo(u16 io) { outb(power,io); udelay(4); @@ -204,7 +179,7 @@ static int get_stereo(__u16 io) return !(inb(io) & mo_st); } -static int get_tune(__u16 io) +static int get_tune(u16 io) { outb(power+clk,io); udelay(4); @@ -213,95 +188,84 @@ static int get_tune(__u16 io) } -static int vidioc_querycap (struct file *file, void *priv, +static int vidioc_querycap(struct file *file, void *priv, struct v4l2_capability *v) { - strlcpy(v->driver, "radio-maxiradio", sizeof (v->driver)); - strlcpy(v->card, "Maxi Radio FM2000 radio", sizeof (v->card)); - sprintf(v->bus_info,"ISA"); - v->version = RADIO_VERSION; - v->capabilities = V4L2_CAP_TUNER; + struct maxiradio *dev = video_drvdata(file); + strlcpy(v->driver, "radio-maxiradio", sizeof(v->driver)); + strlcpy(v->card, "Maxi Radio FM2000 radio", sizeof(v->card)); + snprintf(v->bus_info, sizeof(v->bus_info), "PCI:%s", pci_name(dev->pdev)); + v->version = RADIO_VERSION; + v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO; return 0; } -static int vidioc_g_tuner (struct file *file, void *priv, +static int vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *v) { - struct radio_device *card = video_drvdata(file); + struct maxiradio *dev = video_drvdata(file); if (v->index > 0) return -EINVAL; - memset(v,0,sizeof(*v)); - strcpy(v->name, "FM"); + mutex_lock(&dev->lock); + strlcpy(v->name, "FM", sizeof(v->name)); v->type = V4L2_TUNER_RADIO; - - v->rangelow=FREQ_LO; - v->rangehigh=FREQ_HI; - v->rxsubchans =V4L2_TUNER_SUB_MONO|V4L2_TUNER_SUB_STEREO; - v->capability=V4L2_TUNER_CAP_LOW; - if(get_stereo(card->io)) + v->rangelow = FREQ_LO; + v->rangehigh = FREQ_HI; + v->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO; + v->capability = V4L2_TUNER_CAP_LOW; + if (get_stereo(dev->io)) v->audmode = V4L2_TUNER_MODE_STEREO; else v->audmode = V4L2_TUNER_MODE_MONO; - v->signal=0xffff*get_tune(card->io); + v->signal = 0xffff * get_tune(dev->io); + mutex_unlock(&dev->lock); return 0; } -static int vidioc_s_tuner (struct file *file, void *priv, +static int vidioc_s_tuner(struct file *file, void *priv, struct v4l2_tuner *v) { - if (v->index > 0) - return -EINVAL; - - return 0; -} - -static int vidioc_g_audio (struct file *file, void *priv, - struct v4l2_audio *a) -{ - if (a->index > 1) - return -EINVAL; - - strcpy(a->name, "FM"); - a->capability = V4L2_AUDCAP_STEREO; - return 0; + return v->index ? -EINVAL : 0; } static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i) { *i = 0; - return 0; } static int vidioc_s_input(struct file *filp, void *priv, unsigned int i) { - if (i != 0) - return -EINVAL; + return i ? -EINVAL : 0; +} +static int vidioc_g_audio(struct file *file, void *priv, + struct v4l2_audio *a) +{ + a->index = 0; + strlcpy(a->name, "Radio", sizeof(a->name)); + a->capability = V4L2_AUDCAP_STEREO; return 0; } -static int vidioc_s_audio (struct file *file, void *priv, +static int vidioc_s_audio(struct file *file, void *priv, struct v4l2_audio *a) { - if (a->index != 0) - return -EINVAL; - - return 0; + return a->index ? -EINVAL : 0; } -static int vidioc_s_frequency (struct file *file, void *priv, +static int vidioc_s_frequency(struct file *file, void *priv, struct v4l2_frequency *f) { - struct radio_device *card = video_drvdata(file); + struct maxiradio *dev = video_drvdata(file); if (f->frequency < FREQ_LO || f->frequency > FREQ_HI) { - dprintk(1, "radio freq (%d.%02d MHz) out of range (%d-%d)\n", + dprintk(dev, 1, "radio freq (%d.%02d MHz) out of range (%d-%d)\n", f->frequency / 16000, f->frequency % 16000 * 100 / 16000, FREQ_LO / 16000, FREQ_HI / 16000); @@ -309,75 +273,91 @@ static int vidioc_s_frequency (struct file *file, void *priv, return -EINVAL; } - card->freq = f->frequency; - set_freq(card->io, card->freq); + mutex_lock(&dev->lock); + dev->freq = f->frequency; + set_freq(dev, dev->freq); msleep(125); + mutex_unlock(&dev->lock); return 0; } -static int vidioc_g_frequency (struct file *file, void *priv, +static int vidioc_g_frequency(struct file *file, void *priv, struct v4l2_frequency *f) { - struct radio_device *card = video_drvdata(file); + struct maxiradio *dev = video_drvdata(file); f->type = V4L2_TUNER_RADIO; - f->frequency = card->freq; + f->frequency = dev->freq; - dprintk(4, "radio freq is %d.%02d MHz", + dprintk(dev, 4, "radio freq is %d.%02d MHz", f->frequency / 16000, f->frequency % 16000 * 100 / 16000); return 0; } -static int vidioc_queryctrl (struct file *file, void *priv, +static int vidioc_queryctrl(struct file *file, void *priv, struct v4l2_queryctrl *qc) { - int i; - - for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) { - if (qc->id && qc->id == radio_qctrl[i].id) { - memcpy(qc, &(radio_qctrl[i]), sizeof(*qc)); - return (0); - } + switch (qc->id) { + case V4L2_CID_AUDIO_MUTE: + return v4l2_ctrl_query_fill(qc, 0, 1, 1, 1); } - return -EINVAL; } -static int vidioc_g_ctrl (struct file *file, void *priv, - struct v4l2_control *ctrl) +static int vidioc_g_ctrl(struct file *file, void *priv, + struct v4l2_control *ctrl) { - struct radio_device *card = video_drvdata(file); + struct maxiradio *dev = video_drvdata(file); switch (ctrl->id) { - case V4L2_CID_AUDIO_MUTE: - ctrl->value=card->muted; - return (0); + case V4L2_CID_AUDIO_MUTE: + ctrl->value = dev->muted; + return 0; } return -EINVAL; } -static int vidioc_s_ctrl (struct file *file, void *priv, - struct v4l2_control *ctrl) +static int vidioc_s_ctrl(struct file *file, void *priv, + struct v4l2_control *ctrl) { - struct radio_device *card = video_drvdata(file); + struct maxiradio *dev = video_drvdata(file); switch (ctrl->id) { - case V4L2_CID_AUDIO_MUTE: - card->muted = ctrl->value; - if(card->muted) - turn_power(card->io, 0); - else - set_freq(card->io, card->freq); - return 0; + case V4L2_CID_AUDIO_MUTE: + mutex_lock(&dev->lock); + dev->muted = ctrl->value; + if (dev->muted) + turn_power(dev, 0); + else + set_freq(dev, dev->freq); + mutex_unlock(&dev->lock); + return 0; } return -EINVAL; } +static int maxiradio_open(struct file *file) +{ + return 0; +} + +static int maxiradio_release(struct file *file) +{ + return 0; +} + +static const struct v4l2_file_operations maxiradio_fops = { + .owner = THIS_MODULE, + .open = maxiradio_open, + .release = maxiradio_release, + .ioctl = video_ioctl2, +}; + static const struct v4l2_ioctl_ops maxiradio_ioctl_ops = { .vidioc_querycap = vidioc_querycap, .vidioc_g_tuner = vidioc_g_tuner, @@ -393,60 +373,84 @@ static const struct v4l2_ioctl_ops maxiradio_ioctl_ops = { .vidioc_s_ctrl = vidioc_s_ctrl, }; -static struct video_device maxiradio_radio = { - .name = "Maxi Radio FM2000 radio", - .fops = &maxiradio_fops, - .ioctl_ops = &maxiradio_ioctl_ops, - .release = video_device_release_empty, -}; - static int __devinit maxiradio_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { - if(!request_region(pci_resource_start(pdev, 0), + struct maxiradio *dev; + struct v4l2_device *v4l2_dev; + int retval = -ENOMEM; + + dev = kzalloc(sizeof(*dev), GFP_KERNEL); + if (dev == NULL) { + dev_err(&pdev->dev, "not enough memory\n"); + return -ENOMEM; + } + + v4l2_dev = &dev->v4l2_dev; + mutex_init(&dev->lock); + dev->pdev = pdev; + dev->muted = 1; + dev->freq = FREQ_LO; + + strlcpy(v4l2_dev->name, "maxiradio", sizeof(v4l2_dev->name)); + + retval = v4l2_device_register(&pdev->dev, v4l2_dev); + if (retval < 0) { + v4l2_err(v4l2_dev, "Could not register v4l2_device\n"); + goto errfr; + } + + if (!request_region(pci_resource_start(pdev, 0), pci_resource_len(pdev, 0), "Maxi Radio FM 2000")) { - printk(KERN_ERR "radio-maxiradio: can't reserve I/O ports\n"); + v4l2_err(v4l2_dev, "can't reserve I/O ports\n"); goto err_out; } if (pci_enable_device(pdev)) goto err_out_free_region; - radio_unit.io = pci_resource_start(pdev, 0); - mutex_init(&radio_unit.lock); - video_set_drvdata(&maxiradio_radio, &radio_unit); + dev->io = pci_resource_start(pdev, 0); + strlcpy(dev->vdev.name, v4l2_dev->name, sizeof(dev->vdev.name)); + dev->vdev.v4l2_dev = v4l2_dev; + dev->vdev.fops = &maxiradio_fops; + dev->vdev.ioctl_ops = &maxiradio_ioctl_ops; + dev->vdev.release = video_device_release_empty; + video_set_drvdata(&dev->vdev, dev); - if (video_register_device(&maxiradio_radio, VFL_TYPE_RADIO, radio_nr) < 0) { - printk("radio-maxiradio: can't register device!"); + if (video_register_device(&dev->vdev, VFL_TYPE_RADIO, radio_nr) < 0) { + v4l2_err(v4l2_dev, "can't register device!"); goto err_out_free_region; } - printk(KERN_INFO "radio-maxiradio: version " - DRIVER_VERSION - " time " - __TIME__ " " - __DATE__ - "\n"); + v4l2_info(v4l2_dev, "version " DRIVER_VERSION + " time " __TIME__ " " __DATE__ "\n"); - printk(KERN_INFO "radio-maxiradio: found Guillemot MAXI Radio device (io = 0x%x)\n", - radio_unit.io); + v4l2_info(v4l2_dev, "found Guillemot MAXI Radio device (io = 0x%x)\n", + dev->io); return 0; err_out_free_region: release_region(pci_resource_start(pdev, 0), pci_resource_len(pdev, 0)); err_out: + v4l2_device_unregister(v4l2_dev); +errfr: + kfree(dev); return -ENODEV; } static void __devexit maxiradio_remove_one(struct pci_dev *pdev) { - video_unregister_device(&maxiradio_radio); + struct v4l2_device *v4l2_dev = dev_get_drvdata(&pdev->dev); + struct maxiradio *dev = to_maxiradio(v4l2_dev); + + video_unregister_device(&dev->vdev); + v4l2_device_unregister(&dev->v4l2_dev); release_region(pci_resource_start(pdev, 0), pci_resource_len(pdev, 0)); } static struct pci_device_id maxiradio_pci_tbl[] = { { PCI_VENDOR_ID_GUILLEMOT, PCI_DEVICE_ID_GUILLEMOT_MAXIRADIO, PCI_ANY_ID, PCI_ANY_ID, }, - { 0,} + { 0 } }; MODULE_DEVICE_TABLE(pci, maxiradio_pci_tbl); @@ -470,10 +474,3 @@ static void __exit maxiradio_radio_exit(void) module_init(maxiradio_radio_init); module_exit(maxiradio_radio_exit); - -MODULE_AUTHOR("Dimitromanolakis Apostolos, apdim@grecian.net"); -MODULE_DESCRIPTION("Radio driver for the Guillemot Maxi Radio FM2000 radio."); -MODULE_LICENSE("GPL"); - -module_param_named(debug,maxiradio_radio.debug, int, 0644); -MODULE_PARM_DESC(debug,"activates debug info"); -- cgit v1.2.3 From 62c50db1615e612d466a6bfcd9badcd300b54609 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 6 Mar 2009 17:52:06 +0100 Subject: radio-rtrack2: convert to v4l2_device. From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/radio/radio-rtrack2.c | 280 ++++++++++++++---------------- 1 file changed, 130 insertions(+), 150 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/radio/radio-rtrack2.c b/linux/drivers/media/radio/radio-rtrack2.c index fa9e243c8..93b3da04a 100644 --- a/linux/drivers/media/radio/radio-rtrack2.c +++ b/linux/drivers/media/radio/radio-rtrack2.c @@ -13,35 +13,18 @@ #include /* Initdata */ #include /* request_region */ #include /* udelay */ -#include /* outb, outb_p */ -#include /* copy to/from user */ -#include "compat.h" #include /* kernel radio structs */ -#include +#include +#include /* for KERNEL_VERSION MACRO */ +#include /* outb, outb_p */ +#include /* copy to/from user */ +#include #include -#include +#include "compat.h" -#include /* for KERNEL_VERSION MACRO */ -#define RADIO_VERSION KERNEL_VERSION(0,0,2) - -static struct v4l2_queryctrl radio_qctrl[] = { - { - .id = V4L2_CID_AUDIO_MUTE, - .name = "Mute", - .minimum = 0, - .maximum = 1, - .default_value = 1, - .type = V4L2_CTRL_TYPE_BOOLEAN, - },{ - .id = V4L2_CID_AUDIO_VOLUME, - .name = "Volume", - .minimum = 0, - .maximum = 65535, - .step = 65535, - .default_value = 0xff, - .type = V4L2_CTRL_TYPE_INTEGER, - } -}; +MODULE_AUTHOR("Ben Pfaff"); +MODULE_DESCRIPTION("A driver for the RadioTrack II radio card."); +MODULE_LICENSE("GPL"); #ifndef CONFIG_RADIO_RTRACK2_PORT #define CONFIG_RADIO_RTRACK2_PORT -1 @@ -49,79 +32,89 @@ static struct v4l2_queryctrl radio_qctrl[] = { static int io = CONFIG_RADIO_RTRACK2_PORT; static int radio_nr = -1; -static spinlock_t lock; -struct rt_device +module_param(io, int, 0); +MODULE_PARM_DESC(io, "I/O address of the RadioTrack card (0x20c or 0x30c)"); +module_param(radio_nr, int, 0); + +#define RADIO_VERSION KERNEL_VERSION(0, 0, 2) + +struct rtrack2 { - unsigned long in_use; - int port; + struct v4l2_device v4l2_dev; + struct video_device vdev; + int io; unsigned long curfreq; int muted; + struct mutex lock; }; +static struct rtrack2 rtrack2_card; + /* local things */ -static void rt_mute(struct rt_device *dev) +static void rt_mute(struct rtrack2 *dev) { - if(dev->muted) + if (dev->muted) return; - spin_lock(&lock); - outb(1, io); - spin_unlock(&lock); + mutex_lock(&dev->lock); + outb(1, dev->io); + mutex_unlock(&dev->lock); + mutex_unlock(&dev->lock); dev->muted = 1; } -static void rt_unmute(struct rt_device *dev) +static void rt_unmute(struct rtrack2 *dev) { if(dev->muted == 0) return; - spin_lock(&lock); - outb(0, io); - spin_unlock(&lock); + mutex_lock(&dev->lock); + outb(0, dev->io); + mutex_unlock(&dev->lock); dev->muted = 0; } -static void zero(void) +static void zero(struct rtrack2 *dev) { - outb_p(1, io); - outb_p(3, io); - outb_p(1, io); + outb_p(1, dev->io); + outb_p(3, dev->io); + outb_p(1, dev->io); } -static void one(void) +static void one(struct rtrack2 *dev) { - outb_p(5, io); - outb_p(7, io); - outb_p(5, io); + outb_p(5, dev->io); + outb_p(7, dev->io); + outb_p(5, dev->io); } -static int rt_setfreq(struct rt_device *dev, unsigned long freq) +static int rt_setfreq(struct rtrack2 *dev, unsigned long freq) { int i; + mutex_lock(&dev->lock); + dev->curfreq = freq; freq = freq / 200 + 856; - spin_lock(&lock); - - outb_p(0xc8, io); - outb_p(0xc9, io); - outb_p(0xc9, io); + outb_p(0xc8, dev->io); + outb_p(0xc9, dev->io); + outb_p(0xc9, dev->io); for (i = 0; i < 10; i++) - zero (); + zero(dev); for (i = 14; i >= 0; i--) if (freq & (1 << i)) - one (); + one(dev); else - zero (); + zero(dev); - outb_p(0xc8, io); + outb_p(0xc8, dev->io); if (!dev->muted) - outb_p(0, io); + outb_p(0, dev->io); - spin_unlock(&lock); + mutex_unlock(&dev->lock); return 0; } @@ -130,61 +123,61 @@ static int vidioc_querycap(struct file *file, void *priv, { strlcpy(v->driver, "radio-rtrack2", sizeof(v->driver)); strlcpy(v->card, "RadioTrack II", sizeof(v->card)); - sprintf(v->bus_info, "ISA"); + strlcpy(v->bus_info, "ISA", sizeof(v->bus_info)); v->version = RADIO_VERSION; - v->capabilities = V4L2_CAP_TUNER; + v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO; return 0; } static int vidioc_s_tuner(struct file *file, void *priv, struct v4l2_tuner *v) { - if (v->index > 0) - return -EINVAL; - - return 0; + return v->index ? -EINVAL : 0; } -static int rt_getsigstr(struct rt_device *dev) +static int rt_getsigstr(struct rtrack2 *dev) { - if (inb(io) & 2) /* bit set = no signal present */ - return 0; - return 1; /* signal present */ + int sig = 1; + + mutex_lock(&dev->lock); + if (inb(dev->io) & 2) /* bit set = no signal present */ + sig = 0; + mutex_unlock(&dev->lock); + return sig; } static int vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *v) { - struct rt_device *rt = video_drvdata(file); + struct rtrack2 *rt = video_drvdata(file); if (v->index > 0) return -EINVAL; - strcpy(v->name, "FM"); + strlcpy(v->name, "FM", sizeof(v->name)); v->type = V4L2_TUNER_RADIO; - v->rangelow = (88*16000); - v->rangehigh = (108*16000); + v->rangelow = 88 * 16000; + v->rangehigh = 108 * 16000; v->rxsubchans = V4L2_TUNER_SUB_MONO; v->capability = V4L2_TUNER_CAP_LOW; v->audmode = V4L2_TUNER_MODE_MONO; - v->signal = 0xFFFF*rt_getsigstr(rt); + v->signal = 0xFFFF * rt_getsigstr(rt); return 0; } static int vidioc_s_frequency(struct file *file, void *priv, struct v4l2_frequency *f) { - struct rt_device *rt = video_drvdata(file); + struct rtrack2 *rt = video_drvdata(file); - rt->curfreq = f->frequency; - rt_setfreq(rt, rt->curfreq); + rt_setfreq(rt, f->frequency); return 0; } static int vidioc_g_frequency(struct file *file, void *priv, struct v4l2_frequency *f) { - struct rt_device *rt = video_drvdata(file); + struct rtrack2 *rt = video_drvdata(file); f->type = V4L2_TUNER_RADIO; f->frequency = rt->curfreq; @@ -194,14 +187,11 @@ static int vidioc_g_frequency(struct file *file, void *priv, static int vidioc_queryctrl(struct file *file, void *priv, struct v4l2_queryctrl *qc) { - int i; - - for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) { - if (qc->id && qc->id == radio_qctrl[i].id) { - memcpy(qc, &(radio_qctrl[i]), - sizeof(*qc)); - return 0; - } + switch (qc->id) { + case V4L2_CID_AUDIO_MUTE: + return v4l2_ctrl_query_fill(qc, 0, 1, 1, 1); + case V4L2_CID_AUDIO_VOLUME: + return v4l2_ctrl_query_fill(qc, 0, 65535, 65535, 65535); } return -EINVAL; } @@ -209,7 +199,7 @@ static int vidioc_queryctrl(struct file *file, void *priv, static int vidioc_g_ctrl(struct file *file, void *priv, struct v4l2_control *ctrl) { - struct rt_device *rt = video_drvdata(file); + struct rtrack2 *rt = video_drvdata(file); switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: @@ -228,7 +218,7 @@ static int vidioc_g_ctrl(struct file *file, void *priv, static int vidioc_s_ctrl(struct file *file, void *priv, struct v4l2_control *ctrl) { - struct rt_device *rt = video_drvdata(file); + struct rtrack2 *rt = video_drvdata(file); switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: @@ -247,17 +237,6 @@ static int vidioc_s_ctrl(struct file *file, void *priv, return -EINVAL; } -static int vidioc_g_audio(struct file *file, void *priv, - struct v4l2_audio *a) -{ - if (a->index > 1) - return -EINVAL; - - strcpy(a->name, "Radio"); - a->capability = V4L2_AUDCAP_STEREO; - return 0; -} - static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i) { *i = 0; @@ -266,36 +245,38 @@ static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i) static int vidioc_s_input(struct file *filp, void *priv, unsigned int i) { - if (i != 0) - return -EINVAL; - return 0; + return i ? -EINVAL : 0; } -static int vidioc_s_audio(struct file *file, void *priv, +static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a) { - if (a->index != 0) - return -EINVAL; + a->index = 0; + strlcpy(a->name, "Radio", sizeof(a->name)); + a->capability = V4L2_AUDCAP_STEREO; return 0; } -static struct rt_device rtrack2_unit; +static int vidioc_s_audio(struct file *file, void *priv, + struct v4l2_audio *a) +{ + return a->index ? -EINVAL : 0; +} -static int rtrack2_exclusive_open(struct file *file) +static int rtrack2_open(struct file *file) { - return test_and_set_bit(0, &rtrack2_unit.in_use) ? -EBUSY : 0; + return 0; } -static int rtrack2_exclusive_release(struct file *file) +static int rtrack2_release(struct file *file) { - clear_bit(0, &rtrack2_unit.in_use); return 0; } static const struct v4l2_file_operations rtrack2_fops = { .owner = THIS_MODULE, - .open = rtrack2_exclusive_open, - .release = rtrack2_exclusive_release, + .open = rtrack2_open, + .release = rtrack2_release, .ioctl = video_ioctl2, }; @@ -314,62 +295,61 @@ static const struct v4l2_ioctl_ops rtrack2_ioctl_ops = { .vidioc_s_input = vidioc_s_input, }; -static struct video_device rtrack2_radio = { - .name = "RadioTrack II radio", - .fops = &rtrack2_fops, - .ioctl_ops = &rtrack2_ioctl_ops, - .release = video_device_release_empty, -}; - static int __init rtrack2_init(void) { - if(io==-1) - { - printk(KERN_ERR "You must set an I/O address with io=0x20c or io=0x30c\n"); + struct rtrack2 *dev = &rtrack2_card; + struct v4l2_device *v4l2_dev = &dev->v4l2_dev; + int res; + + strlcpy(v4l2_dev->name, "rtrack2", sizeof(v4l2_dev->name)); + dev->io = io; + if (dev->io == -1) { + v4l2_err(v4l2_dev, "You must set an I/O address with io=0x20c or io=0x30c\n"); return -EINVAL; } - if (!request_region(io, 4, "rtrack2")) - { - printk(KERN_ERR "rtrack2: port 0x%x already in use\n", io); + if (!request_region(dev->io, 4, "rtrack2")) { + v4l2_err(v4l2_dev, "port 0x%x already in use\n", dev->io); return -EBUSY; } - video_set_drvdata(&rtrack2_radio, &rtrack2_unit); + res = v4l2_device_register(NULL, v4l2_dev); + if (res < 0) { + release_region(dev->io, 4); + v4l2_err(v4l2_dev, "Could not register v4l2_device\n"); + return res; + } - spin_lock_init(&lock); - if (video_register_device(&rtrack2_radio, VFL_TYPE_RADIO, radio_nr) < 0) { - release_region(io, 4); + strlcpy(dev->vdev.name, v4l2_dev->name, sizeof(dev->vdev.name)); + dev->vdev.v4l2_dev = v4l2_dev; + dev->vdev.fops = &rtrack2_fops; + dev->vdev.ioctl_ops = &rtrack2_ioctl_ops; + dev->vdev.release = video_device_release_empty; + video_set_drvdata(&dev->vdev, dev); + + mutex_init(&dev->lock); + if (video_register_device(&dev->vdev, VFL_TYPE_RADIO, radio_nr) < 0) { + v4l2_device_unregister(v4l2_dev); + release_region(dev->io, 4); return -EINVAL; } - printk(KERN_INFO "AIMSlab Radiotrack II card driver.\n"); + v4l2_info(v4l2_dev, "AIMSlab Radiotrack II card driver.\n"); /* mute card - prevents noisy bootups */ - outb(1, io); - rtrack2_unit.muted = 1; + outb(1, dev->io); + dev->muted = 1; return 0; } -MODULE_AUTHOR("Ben Pfaff"); -MODULE_DESCRIPTION("A driver for the RadioTrack II radio card."); -MODULE_LICENSE("GPL"); - -module_param(io, int, 0); -MODULE_PARM_DESC(io, "I/O address of the RadioTrack card (0x20c or 0x30c)"); -module_param(radio_nr, int, 0); - -static void __exit rtrack2_cleanup_module(void) +static void __exit rtrack2_exit(void) { - video_unregister_device(&rtrack2_radio); - release_region(io,4); + struct rtrack2 *dev = &rtrack2_card; + + video_unregister_device(&dev->vdev); + v4l2_device_unregister(&dev->v4l2_dev); + release_region(dev->io, 4); } module_init(rtrack2_init); -module_exit(rtrack2_cleanup_module); - -/* - Local variables: - compile-command: "mmake" - End: -*/ +module_exit(rtrack2_exit); -- cgit v1.2.3 From cf853d565db80b0025c0f9d25582b7825d258f21 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 6 Mar 2009 17:52:34 +0100 Subject: radio-sf16fmi: convert to v4l2_device. From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/radio/radio-sf16fmi.c | 286 ++++++++++++++---------------- 1 file changed, 136 insertions(+), 150 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/radio/radio-sf16fmi.c b/linux/drivers/media/radio/radio-sf16fmi.c index 3cce0afb4..392aa27e0 100644 --- a/linux/drivers/media/radio/radio-sf16fmi.c +++ b/linux/drivers/media/radio/radio-sf16fmi.c @@ -22,114 +22,111 @@ #include /* Initdata */ #include /* request_region */ #include /* udelay */ -#include "compat.h" -#include /* kernel radio structs */ -#include -#include #include -#include /* outb, outb_p */ -#include /* copy to/from user */ #include +#include /* kernel radio structs */ +#include /* outb, outb_p */ +#include /* copy to/from user */ +#include +#include +#include "compat.h" -#define RADIO_VERSION KERNEL_VERSION(0,0,2) +MODULE_AUTHOR("Petr Vandrovec, vandrove@vc.cvut.cz and M. Kirkwood"); +MODULE_DESCRIPTION("A driver for the SF16MI radio."); +MODULE_LICENSE("GPL"); -static struct v4l2_queryctrl radio_qctrl[] = { - { - .id = V4L2_CID_AUDIO_MUTE, - .name = "Mute", - .minimum = 0, - .maximum = 1, - .default_value = 1, - .type = V4L2_CTRL_TYPE_BOOLEAN, - } -}; +static int io = -1; +static int radio_nr = -1; + +module_param(io, int, 0); +MODULE_PARM_DESC(io, "I/O address of the SF16MI card (0x284 or 0x384)"); +module_param(radio_nr, int, 0); -struct fmi_device +#define RADIO_VERSION KERNEL_VERSION(0, 0, 2) + +struct fmi { - unsigned long in_use; - int port; + struct v4l2_device v4l2_dev; + struct video_device vdev; + int io; int curvol; /* 1 or 0 */ unsigned long curfreq; /* freq in kHz */ __u32 flags; + struct mutex lock; }; -static int io = -1; -static int radio_nr = -1; -static struct pnp_dev *dev = NULL; -static struct mutex lock; +static struct fmi fmi_card; +static struct pnp_dev *dev; /* freq is in 1/16 kHz to internal number, hw precision is 50 kHz */ /* It is only useful to give freq in intervall of 800 (=0.05Mhz), * other bits will be truncated, e.g 92.7400016 -> 92.7, but * 92.7400017 -> 92.75 */ -#define RSF16_ENCODE(x) ((x)/800+214) -#define RSF16_MINFREQ 87*16000 -#define RSF16_MAXFREQ 108*16000 +#define RSF16_ENCODE(x) ((x) / 800 + 214) +#define RSF16_MINFREQ (87 * 16000) +#define RSF16_MAXFREQ (108 * 16000) -static void outbits(int bits, unsigned int data, int port) +static void outbits(int bits, unsigned int data, int io) { - while(bits--) { - if(data & 1) { - outb(5, port); + while (bits--) { + if (data & 1) { + outb(5, io); udelay(6); - outb(7, port); + outb(7, io); udelay(6); } else { - outb(1, port); + outb(1, io); udelay(6); - outb(3, port); + outb(3, io); udelay(6); } - data>>=1; + data >>= 1; } } -static inline void fmi_mute(int port) +static inline void fmi_mute(struct fmi *fmi) { - mutex_lock(&lock); - outb(0x00, port); - mutex_unlock(&lock); + mutex_lock(&fmi->lock); + outb(0x00, fmi->io); + mutex_unlock(&fmi->lock); } -static inline void fmi_unmute(int port) +static inline void fmi_unmute(struct fmi *fmi) { - mutex_lock(&lock); - outb(0x08, port); - mutex_unlock(&lock); + mutex_lock(&fmi->lock); + outb(0x08, fmi->io); + mutex_unlock(&fmi->lock); } -static inline int fmi_setfreq(struct fmi_device *dev) +static inline int fmi_setfreq(struct fmi *fmi, unsigned long freq) { - int myport = dev->port; - unsigned long freq = dev->curfreq; - - mutex_lock(&lock); + mutex_lock(&fmi->lock); + fmi->curfreq = freq; - outbits(16, RSF16_ENCODE(freq), myport); - outbits(8, 0xC0, myport); + outbits(16, RSF16_ENCODE(freq), fmi->io); + outbits(8, 0xC0, fmi->io); msleep(143); /* was schedule_timeout(HZ/7) */ - mutex_unlock(&lock); - if (dev->curvol) fmi_unmute(myport); + mutex_unlock(&fmi->lock); + if (fmi->curvol) + fmi_unmute(fmi); return 0; } -static inline int fmi_getsigstr(struct fmi_device *dev) +static inline int fmi_getsigstr(struct fmi *fmi) { int val; int res; - int myport = dev->port; - - mutex_lock(&lock); - val = dev->curvol ? 0x08 : 0x00; /* unmute/mute */ - outb(val, myport); - outb(val | 0x10, myport); + mutex_lock(&fmi->lock); + val = fmi->curvol ? 0x08 : 0x00; /* unmute/mute */ + outb(val, fmi->io); + outb(val | 0x10, fmi->io); msleep(143); /* was schedule_timeout(HZ/7) */ - res = (int)inb(myport+1); - outb(val, myport); + res = (int)inb(fmi->io + 1); + outb(val, fmi->io); - mutex_unlock(&lock); + mutex_unlock(&fmi->lock); return (res & 2) ? 0 : 0xFFFF; } @@ -138,9 +135,9 @@ static int vidioc_querycap(struct file *file, void *priv, { strlcpy(v->driver, "radio-sf16fmi", sizeof(v->driver)); strlcpy(v->card, "SF16-FMx radio", sizeof(v->card)); - sprintf(v->bus_info, "ISA"); + strlcpy(v->bus_info, "ISA", sizeof(v->bus_info)); v->version = RADIO_VERSION; - v->capabilities = V4L2_CAP_TUNER; + v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO; return 0; } @@ -148,18 +145,18 @@ static int vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *v) { int mult; - struct fmi_device *fmi = video_drvdata(file); + struct fmi *fmi = video_drvdata(file); if (v->index > 0) return -EINVAL; - strcpy(v->name, "FM"); + strlcpy(v->name, "FM", sizeof(v->name)); v->type = V4L2_TUNER_RADIO; mult = (fmi->flags & V4L2_TUNER_CAP_LOW) ? 1 : 1000; - v->rangelow = RSF16_MINFREQ/mult; - v->rangehigh = RSF16_MAXFREQ/mult; + v->rangelow = RSF16_MINFREQ / mult; + v->rangehigh = RSF16_MAXFREQ / mult; v->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_MODE_STEREO; - v->capability = fmi->flags&V4L2_TUNER_CAP_LOW; + v->capability = fmi->flags & V4L2_TUNER_CAP_LOW; v->audmode = V4L2_TUNER_MODE_STEREO; v->signal = fmi_getsigstr(fmi); return 0; @@ -168,32 +165,29 @@ static int vidioc_g_tuner(struct file *file, void *priv, static int vidioc_s_tuner(struct file *file, void *priv, struct v4l2_tuner *v) { - if (v->index > 0) - return -EINVAL; - return 0; + return v->index ? -EINVAL : 0; } static int vidioc_s_frequency(struct file *file, void *priv, struct v4l2_frequency *f) { - struct fmi_device *fmi = video_drvdata(file); + struct fmi *fmi = video_drvdata(file); if (!(fmi->flags & V4L2_TUNER_CAP_LOW)) f->frequency *= 1000; if (f->frequency < RSF16_MINFREQ || - f->frequency > RSF16_MAXFREQ ) + f->frequency > RSF16_MAXFREQ) return -EINVAL; - /*rounding in steps of 800 to match th freq - that will be used */ - fmi->curfreq = (f->frequency/800)*800; - fmi_setfreq(fmi); + /* rounding in steps of 800 to match the freq + that will be used */ + fmi_setfreq(fmi, (f->frequency / 800) * 800); return 0; } static int vidioc_g_frequency(struct file *file, void *priv, struct v4l2_frequency *f) { - struct fmi_device *fmi = video_drvdata(file); + struct fmi *fmi = video_drvdata(file); f->type = V4L2_TUNER_RADIO; f->frequency = fmi->curfreq; @@ -205,14 +199,9 @@ static int vidioc_g_frequency(struct file *file, void *priv, static int vidioc_queryctrl(struct file *file, void *priv, struct v4l2_queryctrl *qc) { - int i; - - for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) { - if (qc->id && qc->id == radio_qctrl[i].id) { - memcpy(qc, &(radio_qctrl[i]), - sizeof(*qc)); - return 0; - } + switch (qc->id) { + case V4L2_CID_AUDIO_MUTE: + return v4l2_ctrl_query_fill(qc, 0, 1, 1, 1); } return -EINVAL; } @@ -220,7 +209,7 @@ static int vidioc_queryctrl(struct file *file, void *priv, static int vidioc_g_ctrl(struct file *file, void *priv, struct v4l2_control *ctrl) { - struct fmi_device *fmi = video_drvdata(file); + struct fmi *fmi = video_drvdata(file); switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: @@ -233,31 +222,20 @@ static int vidioc_g_ctrl(struct file *file, void *priv, static int vidioc_s_ctrl(struct file *file, void *priv, struct v4l2_control *ctrl) { - struct fmi_device *fmi = video_drvdata(file); + struct fmi *fmi = video_drvdata(file); switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: if (ctrl->value) - fmi_mute(fmi->port); + fmi_mute(fmi); else - fmi_unmute(fmi->port); + fmi_unmute(fmi); fmi->curvol = ctrl->value; return 0; } return -EINVAL; } -static int vidioc_g_audio(struct file *file, void *priv, - struct v4l2_audio *a) -{ - if (a->index > 1) - return -EINVAL; - - strcpy(a->name, "Radio"); - a->capability = V4L2_AUDCAP_STEREO; - return 0; -} - static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i) { *i = 0; @@ -266,36 +244,38 @@ static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i) static int vidioc_s_input(struct file *filp, void *priv, unsigned int i) { - if (i != 0) - return -EINVAL; - return 0; + return i ? -EINVAL : 0; } -static int vidioc_s_audio(struct file *file, void *priv, +static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a) { - if (a->index != 0) - return -EINVAL; + a->index = 0; + strlcpy(a->name, "Radio", sizeof(a->name)); + a->capability = V4L2_AUDCAP_STEREO; return 0; } -static struct fmi_device fmi_unit; +static int vidioc_s_audio(struct file *file, void *priv, + struct v4l2_audio *a) +{ + return a->index ? -EINVAL : 0; +} -static int fmi_exclusive_open(struct file *file) +static int fmi_open(struct file *file) { - return test_and_set_bit(0, &fmi_unit.in_use) ? -EBUSY : 0; + return 0; } -static int fmi_exclusive_release(struct file *file) +static int fmi_release(struct file *file) { - clear_bit(0, &fmi_unit.in_use); return 0; } static const struct v4l2_file_operations fmi_fops = { .owner = THIS_MODULE, - .open = fmi_exclusive_open, - .release = fmi_exclusive_release, + .open = fmi_open, + .release = fmi_release, .ioctl = video_ioctl2, }; @@ -314,13 +294,6 @@ static const struct v4l2_ioctl_ops fmi_ioctl_ops = { .vidioc_s_ctrl = vidioc_s_ctrl, }; -static struct video_device fmi_radio = { - .name = "SF16FMx radio", - .fops = &fmi_fops, - .ioctl_ops = &fmi_ioctl_ops, - .release = video_device_release_empty, -}; - /* ladis: this is my card. does any other types exist? */ static struct isapnp_device_id id_table[] __devinitdata = { { ISAPNP_ANY_ID, ISAPNP_ANY_ID, @@ -345,7 +318,7 @@ static int __init isapnp_fmi_probe(void) if (pnp_device_attach(dev) < 0) return -EAGAIN; if (pnp_activate_dev(dev) < 0) { - printk ("radio-sf16fmi: PnP configure failed (out of resources?)\n"); + printk(KERN_ERR "radio-sf16fmi: PnP configure failed (out of resources?)\n"); pnp_device_detach(dev); return -ENOMEM; } @@ -355,59 +328,72 @@ static int __init isapnp_fmi_probe(void) } i = pnp_port_start(dev, 0); - printk ("radio-sf16fmi: PnP reports card at %#x\n", i); + printk(KERN_INFO "radio-sf16fmi: PnP reports card at %#x\n", i); return i; } static int __init fmi_init(void) { + struct fmi *fmi = &fmi_card; + struct v4l2_device *v4l2_dev = &fmi->v4l2_dev; + int res; + if (io < 0) io = isapnp_fmi_probe(); - if (io < 0) { - printk(KERN_ERR "radio-sf16fmi: No PnP card found.\n"); - return io; + strlcpy(v4l2_dev->name, "sf16fmi", sizeof(v4l2_dev->name)); + fmi->io = io; + if (fmi->io < 0) { + v4l2_err(v4l2_dev, "No PnP card found.\n"); + return fmi->io; } if (!request_region(io, 2, "radio-sf16fmi")) { - printk(KERN_ERR "radio-sf16fmi: port 0x%x already in use\n", io); + v4l2_err(v4l2_dev, "port 0x%x already in use\n", fmi->io); pnp_device_detach(dev); return -EBUSY; } - fmi_unit.port = io; - fmi_unit.curvol = 0; - fmi_unit.curfreq = 0; - fmi_unit.flags = V4L2_TUNER_CAP_LOW; - video_set_drvdata(&fmi_radio, &fmi_unit); + res = v4l2_device_register(NULL, v4l2_dev); + if (res < 0) { + release_region(fmi->io, 2); + pnp_device_detach(dev); + v4l2_err(v4l2_dev, "Could not register v4l2_device\n"); + return res; + } + + fmi->flags = V4L2_TUNER_CAP_LOW; + strlcpy(fmi->vdev.name, v4l2_dev->name, sizeof(fmi->vdev.name)); + fmi->vdev.v4l2_dev = v4l2_dev; + fmi->vdev.fops = &fmi_fops; + fmi->vdev.ioctl_ops = &fmi_ioctl_ops; + fmi->vdev.release = video_device_release_empty; + video_set_drvdata(&fmi->vdev, fmi); - mutex_init(&lock); + mutex_init(&fmi->lock); - if (video_register_device(&fmi_radio, VFL_TYPE_RADIO, radio_nr) < 0) { - release_region(io, 2); + if (video_register_device(&fmi->vdev, VFL_TYPE_RADIO, radio_nr) < 0) { + v4l2_device_unregister(v4l2_dev); + release_region(fmi->io, 2); + pnp_device_detach(dev); return -EINVAL; } - printk(KERN_INFO "SF16FMx radio card driver at 0x%x\n", io); + v4l2_info(v4l2_dev, "card driver at 0x%x\n", fmi->io); /* mute card - prevents noisy bootups */ - fmi_mute(io); + fmi_mute(fmi); return 0; } -MODULE_AUTHOR("Petr Vandrovec, vandrove@vc.cvut.cz and M. Kirkwood"); -MODULE_DESCRIPTION("A driver for the SF16MI radio."); -MODULE_LICENSE("GPL"); - -module_param(io, int, 0); -MODULE_PARM_DESC(io, "I/O address of the SF16MI card (0x284 or 0x384)"); -module_param(radio_nr, int, 0); - -static void __exit fmi_cleanup_module(void) +static void __exit fmi_exit(void) { - video_unregister_device(&fmi_radio); - release_region(io, 2); + struct fmi *fmi = &fmi_card; + + video_unregister_device(&fmi->vdev); + v4l2_device_unregister(&fmi->v4l2_dev); + release_region(fmi->io, 2); if (dev) pnp_device_detach(dev); } module_init(fmi_init); -module_exit(fmi_cleanup_module); +module_exit(fmi_exit); -- cgit v1.2.3 From b4fe8e07fa8e6266902aa003db9f8653a9190e2f Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 6 Mar 2009 17:53:26 +0100 Subject: radio-sf16fmr2: convert to v4l2_device. From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/radio/radio-sf16fmr2.c | 374 ++++++++++++++--------------- 1 file changed, 176 insertions(+), 198 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/radio/radio-sf16fmr2.c b/linux/drivers/media/radio/radio-sf16fmr2.c index 69a28d1ff..34de92f82 100644 --- a/linux/drivers/media/radio/radio-sf16fmr2.c +++ b/linux/drivers/media/radio/radio-sf16fmr2.c @@ -18,41 +18,30 @@ #include /* Initdata */ #include /* request_region */ #include /* udelay */ -#include /* outb, outb_p */ -#include /* copy to/from user */ -#include "compat.h" #include /* kernel radio structs */ -#include -#include #include +#include /* for KERNEL_VERSION MACRO */ +#include /* outb, outb_p */ +#include /* copy to/from user */ +#include +#include +#include "compat.h" -static struct mutex lock; +MODULE_AUTHOR("Ziglio Frediano, freddy77@angelfire.com"); +MODULE_DESCRIPTION("A driver for the SF16FMR2 radio."); +MODULE_LICENSE("GPL"); + +static int io = 0x384; +static int radio_nr = -1; + +module_param(io, int, 0); +MODULE_PARM_DESC(io, "I/O address of the SF16FMR2 card (should be 0x384, if do not work try 0x284)"); +module_param(radio_nr, int, 0); -#include /* for KERNEL_VERSION MACRO */ #define RADIO_VERSION KERNEL_VERSION(0,0,2) #define AUD_VOL_INDEX 1 -static struct v4l2_queryctrl radio_qctrl[] = { - { - .id = V4L2_CID_AUDIO_MUTE, - .name = "Mute", - .minimum = 0, - .maximum = 1, - .default_value = 1, - .type = V4L2_CTRL_TYPE_BOOLEAN, - }, - [AUD_VOL_INDEX] = { - .id = V4L2_CID_AUDIO_VOLUME, - .name = "Volume", - .minimum = 0, - .maximum = 15, - .step = 1, - .default_value = 0, - .type = V4L2_CTRL_TYPE_INTEGER, - } -}; - #undef DEBUG //#define DEBUG 1 @@ -63,156 +52,160 @@ static struct v4l2_queryctrl radio_qctrl[] = { #endif /* this should be static vars for module size */ -struct fmr2_device +struct fmr2 { - unsigned long in_use; - int port; + struct v4l2_device v4l2_dev; + struct video_device vdev; + struct mutex lock; + int io; int curvol; /* 0-15 */ int mute; int stereo; /* card is producing stereo audio */ unsigned long curfreq; /* freq in kHz */ int card_type; - __u32 flags; + u32 flags; }; -static int io = 0x384; -static int radio_nr = -1; +static struct fmr2 fmr2_card; /* hw precision is 12.5 kHz * It is only useful to give freq in intervall of 200 (=0.0125Mhz), * other bits will be truncated */ -#define RSF16_ENCODE(x) ((x)/200+856) -#define RSF16_MINFREQ 87*16000 -#define RSF16_MAXFREQ 108*16000 +#define RSF16_ENCODE(x) ((x) / 200 + 856) +#define RSF16_MINFREQ (87 * 16000) +#define RSF16_MAXFREQ (108 * 16000) -static inline void wait(int n,int port) +static inline void wait(int n, int io) { - for (;n;--n) inb(port); + for (; n; --n) + inb(io); } -static void outbits(int bits, unsigned int data, int nWait, int port) +static void outbits(int bits, unsigned int data, int nWait, int io) { int bit; - for(;--bits>=0;) { - bit = (data>>bits) & 1; - outb(bit,port); - wait(nWait,port); - outb(bit|2,port); - wait(nWait,port); - outb(bit,port); - wait(nWait,port); + + for (; --bits >= 0;) { + bit = (data >> bits) & 1; + outb(bit, io); + wait(nWait, io); + outb(bit | 2, io); + wait(nWait, io); + outb(bit, io); + wait(nWait, io); } } -static inline void fmr2_mute(int port) +static inline void fmr2_mute(int io) { - outb(0x00, port); - wait(4,port); + outb(0x00, io); + wait(4, io); } -static inline void fmr2_unmute(int port) +static inline void fmr2_unmute(int io) { - outb(0x04, port); - wait(4,port); + outb(0x04, io); + wait(4, io); } -static inline int fmr2_stereo_mode(int port) +static inline int fmr2_stereo_mode(int io) { - int n = inb(port); - outb(6,port); - inb(port); - n = ((n>>3)&1)^1; + int n = inb(io); + + outb(6, io); + inb(io); + n = ((n >> 3) & 1) ^ 1; debug_print((KERN_DEBUG "stereo: %d\n", n)); return n; } -static int fmr2_product_info(struct fmr2_device *dev) +static int fmr2_product_info(struct fmr2 *dev) { - int n = inb(dev->port); + int n = inb(dev->io); + n &= 0xC1; - if (n == 0) - { + if (n == 0) { /* this should support volume set */ dev->card_type = 12; return 0; } /* not volume (mine is 11) */ - dev->card_type = (n==128)?11:0; + dev->card_type = (n == 128) ? 11 : 0; return n; } -static inline int fmr2_getsigstr(struct fmr2_device *dev) +static inline int fmr2_getsigstr(struct fmr2 *dev) { - /* !!! work only if scanning freq */ - int port = dev->port, res = 0xffff; - outb(5,port); - wait(4,port); - if (!(inb(port)&1)) res = 0; + /* !!! works only if scanning freq */ + int res = 0xffff; + + outb(5, dev->io); + wait(4, dev->io); + if (!(inb(dev->io) & 1)) + res = 0; debug_print((KERN_DEBUG "signal: %d\n", res)); return res; } /* set frequency and unmute card */ -static int fmr2_setfreq(struct fmr2_device *dev) +static int fmr2_setfreq(struct fmr2 *dev) { - int port = dev->port; unsigned long freq = dev->curfreq; - fmr2_mute(port); + fmr2_mute(dev->io); /* 0x42 for mono output * 0x102 forward scanning * 0x182 scansione avanti */ - outbits(9,0x2,3,port); - outbits(16,RSF16_ENCODE(freq),2,port); + outbits(9, 0x2, 3, dev->io); + outbits(16, RSF16_ENCODE(freq), 2, dev->io); - fmr2_unmute(port); + fmr2_unmute(dev->io); /* wait 0.11 sec */ msleep(110); /* NOTE if mute this stop radio you must set freq on unmute */ - dev->stereo = fmr2_stereo_mode(port); + dev->stereo = fmr2_stereo_mode(dev->io); return 0; } /* !!! not tested, in my card this does't work !!! */ -static int fmr2_setvolume(struct fmr2_device *dev) +static int fmr2_setvolume(struct fmr2 *dev) { int vol[16] = { 0x021, 0x084, 0x090, 0x104, 0x110, 0x204, 0x210, 0x402, 0x404, 0x408, 0x410, 0x801, 0x802, 0x804, 0x808, 0x810 }; - int i, a, port = dev->port; + int i, a; int n = vol[dev->curvol & 0x0f]; if (dev->card_type != 11) return 1; for (i = 12; --i >= 0; ) { - a = ((n >> i) & 1) << 6; /* if (a=0) a= 0; else a= 0x40; */ - outb(a | 4, port); - wait(4, port); - outb(a | 0x24, port); - wait(4, port); - outb(a | 4, port); - wait(4, port); + a = ((n >> i) & 1) << 6; /* if (a==0) a = 0; else a = 0x40; */ + outb(a | 4, dev->io); + wait(4, dev->io); + outb(a | 0x24, dev->io); + wait(4, dev->io); + outb(a | 4, dev->io); + wait(4, dev->io); } for (i = 6; --i >= 0; ) { a = ((0x18 >> i) & 1) << 6; - outb(a | 4, port); - wait(4,port); - outb(a | 0x24, port); - wait(4,port); - outb(a|4, port); - wait(4,port); + outb(a | 4, dev->io); + wait(4, dev->io); + outb(a | 0x24, dev->io); + wait(4, dev->io); + outb(a | 4, dev->io); + wait(4, dev->io); } - wait(4, port); - outb(0x14, port); - + wait(4, dev->io); + outb(0x14, dev->io); return 0; } @@ -221,9 +214,9 @@ static int vidioc_querycap(struct file *file, void *priv, { strlcpy(v->driver, "radio-sf16fmr2", sizeof(v->driver)); strlcpy(v->card, "SF16-FMR2 radio", sizeof(v->card)); - sprintf(v->bus_info, "ISA"); + strlcpy(v->bus_info, "ISA", sizeof(v->bus_info)); v->version = RADIO_VERSION; - v->capabilities = V4L2_CAP_TUNER; + v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO; return 0; } @@ -231,54 +224,52 @@ static int vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *v) { int mult; - struct fmr2_device *fmr2 = video_drvdata(file); + struct fmr2 *fmr2 = video_drvdata(file); if (v->index > 0) return -EINVAL; - strcpy(v->name, "FM"); + strlcpy(v->name, "FM", sizeof(v->name)); v->type = V4L2_TUNER_RADIO; mult = (fmr2->flags & V4L2_TUNER_CAP_LOW) ? 1 : 1000; - v->rangelow = RSF16_MINFREQ/mult; - v->rangehigh = RSF16_MAXFREQ/mult; + v->rangelow = RSF16_MINFREQ / mult; + v->rangehigh = RSF16_MAXFREQ / mult; v->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_MODE_STEREO; v->capability = fmr2->flags&V4L2_TUNER_CAP_LOW; v->audmode = fmr2->stereo ? V4L2_TUNER_MODE_STEREO: V4L2_TUNER_MODE_MONO; - mutex_lock(&lock); + mutex_lock(&fmr2->lock); v->signal = fmr2_getsigstr(fmr2); - mutex_unlock(&lock); + mutex_unlock(&fmr2->lock); return 0; } static int vidioc_s_tuner(struct file *file, void *priv, struct v4l2_tuner *v) { - if (v->index > 0) - return -EINVAL; - return 0; + return v->index ? -EINVAL : 0; } static int vidioc_s_frequency(struct file *file, void *priv, struct v4l2_frequency *f) { - struct fmr2_device *fmr2 = video_drvdata(file); + struct fmr2 *fmr2 = video_drvdata(file); if (!(fmr2->flags & V4L2_TUNER_CAP_LOW)) f->frequency *= 1000; if (f->frequency < RSF16_MINFREQ || - f->frequency > RSF16_MAXFREQ ) + f->frequency > RSF16_MAXFREQ) return -EINVAL; - /*rounding in steps of 200 to match th freq - that will be used */ - fmr2->curfreq = (f->frequency/200)*200; + /* rounding in steps of 200 to match the freq + that will be used */ + fmr2->curfreq = (f->frequency / 200) * 200; /* set card freq (if not muted) */ if (fmr2->curvol && !fmr2->mute) { - mutex_lock(&lock); + mutex_lock(&fmr2->lock); fmr2_setfreq(fmr2); - mutex_unlock(&lock); + mutex_unlock(&fmr2->lock); } return 0; } @@ -286,7 +277,7 @@ static int vidioc_s_frequency(struct file *file, void *priv, static int vidioc_g_frequency(struct file *file, void *priv, struct v4l2_frequency *f) { - struct fmr2_device *fmr2 = video_drvdata(file); + struct fmr2 *fmr2 = video_drvdata(file); f->type = V4L2_TUNER_RADIO; f->frequency = fmr2->curfreq; @@ -298,13 +289,16 @@ static int vidioc_g_frequency(struct file *file, void *priv, static int vidioc_queryctrl(struct file *file, void *priv, struct v4l2_queryctrl *qc) { - int i; + struct fmr2 *fmr2 = video_drvdata(file); - for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) { - if (qc->id && qc->id == radio_qctrl[i].id) { - memcpy(qc, &radio_qctrl[i], sizeof(*qc)); - return 0; - } + switch (qc->id) { + case V4L2_CID_AUDIO_MUTE: + return v4l2_ctrl_query_fill(qc, 0, 1, 1, 1); + case V4L2_CID_AUDIO_VOLUME: + /* Only card_type == 11 implements volume */ + if (fmr2->card_type == 11) + return v4l2_ctrl_query_fill(qc, 0, 15, 1, 0); + return v4l2_ctrl_query_fill(qc, 0, 1, 1, 0); } return -EINVAL; } @@ -312,7 +306,7 @@ static int vidioc_queryctrl(struct file *file, void *priv, static int vidioc_g_ctrl(struct file *file, void *priv, struct v4l2_control *ctrl) { - struct fmr2_device *fmr2 = video_drvdata(file); + struct fmr2 *fmr2 = video_drvdata(file); switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: @@ -328,18 +322,14 @@ static int vidioc_g_ctrl(struct file *file, void *priv, static int vidioc_s_ctrl(struct file *file, void *priv, struct v4l2_control *ctrl) { - struct fmr2_device *fmr2 = video_drvdata(file); + struct fmr2 *fmr2 = video_drvdata(file); switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: fmr2->mute = ctrl->value; break; case V4L2_CID_AUDIO_VOLUME: - if (ctrl->value > radio_qctrl[AUD_VOL_INDEX].maximum) - fmr2->curvol = radio_qctrl[AUD_VOL_INDEX].maximum; - else - fmr2->curvol = ctrl->value; - + fmr2->curvol = ctrl->value; break; default: return -EINVAL; @@ -352,25 +342,14 @@ static int vidioc_s_ctrl(struct file *file, void *priv, printk(KERN_DEBUG "mute\n"); #endif - mutex_lock(&lock); + mutex_lock(&fmr2->lock); if (fmr2->curvol && !fmr2->mute) { fmr2_setvolume(fmr2); /* Set frequency and unmute card */ fmr2_setfreq(fmr2); } else - fmr2_mute(fmr2->port); - mutex_unlock(&lock); - return 0; -} - -static int vidioc_g_audio(struct file *file, void *priv, - struct v4l2_audio *a) -{ - if (a->index > 1) - return -EINVAL; - - strcpy(a->name, "Radio"); - a->capability = V4L2_AUDCAP_STEREO; + fmr2_mute(fmr2->io); + mutex_unlock(&fmr2->lock); return 0; } @@ -382,36 +361,38 @@ static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i) static int vidioc_s_input(struct file *filp, void *priv, unsigned int i) { - if (i != 0) - return -EINVAL; - return 0; + return i ? -EINVAL : 0; } -static int vidioc_s_audio(struct file *file, void *priv, +static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a) { - if (a->index != 0) - return -EINVAL; + a->index = 0; + strlcpy(a->name, "Radio", sizeof(a->name)); + a->capability = V4L2_AUDCAP_STEREO; return 0; } -static struct fmr2_device fmr2_unit; +static int vidioc_s_audio(struct file *file, void *priv, + struct v4l2_audio *a) +{ + return a->index ? -EINVAL : 0; +} -static int fmr2_exclusive_open(struct file *file) +static int fmr2_open(struct file *file) { - return test_and_set_bit(0, &fmr2_unit.in_use) ? -EBUSY : 0; + return 0; } -static int fmr2_exclusive_release(struct file *file) +static int fmr2_release(struct file *file) { - clear_bit(0, &fmr2_unit.in_use); return 0; } static const struct v4l2_file_operations fmr2_fops = { .owner = THIS_MODULE, - .open = fmr2_exclusive_open, - .release = fmr2_exclusive_release, + .open = fmr2_open, + .release = fmr2_release, .ioctl = video_ioctl2, }; @@ -430,67 +411,64 @@ static const struct v4l2_ioctl_ops fmr2_ioctl_ops = { .vidioc_s_ctrl = vidioc_s_ctrl, }; -static struct video_device fmr2_radio = { - .name = "SF16FMR2 radio", - .fops = &fmr2_fops, - .ioctl_ops = &fmr2_ioctl_ops, - .release = video_device_release_empty, -}; - static int __init fmr2_init(void) { - fmr2_unit.port = io; - fmr2_unit.curvol = 0; - fmr2_unit.mute = 0; - fmr2_unit.curfreq = 0; - fmr2_unit.stereo = 1; - fmr2_unit.flags = V4L2_TUNER_CAP_LOW; - fmr2_unit.card_type = 0; - video_set_drvdata(&fmr2_radio, &fmr2_unit); - - mutex_init(&lock); - - if (!request_region(io, 2, "sf16fmr2")) { - printk(KERN_ERR "radio-sf16fmr2: request_region failed!\n"); + struct fmr2 *fmr2 = &fmr2_card; + struct v4l2_device *v4l2_dev = &fmr2->v4l2_dev; + int res; + + strlcpy(v4l2_dev->name, "sf16fmr2", sizeof(v4l2_dev->name)); + fmr2->io = io; + fmr2->stereo = 1; + fmr2->flags = V4L2_TUNER_CAP_LOW; + mutex_init(&fmr2->lock); + + if (!request_region(fmr2->io, 2, "sf16fmr2")) { + v4l2_err(v4l2_dev, "request_region failed!\n"); return -EBUSY; } - if (video_register_device(&fmr2_radio, VFL_TYPE_RADIO, radio_nr) < 0) { - release_region(io, 2); - return -EINVAL; + res = v4l2_device_register(NULL, v4l2_dev); + if (res < 0) { + release_region(fmr2->io, 2); + v4l2_err(v4l2_dev, "Could not register v4l2_device\n"); + return res; } - printk(KERN_INFO "SF16FMR2 radio card driver at 0x%x.\n", io); - /* mute card - prevents noisy bootups */ - mutex_lock(&lock); - fmr2_mute(io); - fmr2_product_info(&fmr2_unit); - mutex_unlock(&lock); - debug_print((KERN_DEBUG "card_type %d\n", fmr2_unit.card_type)); + strlcpy(fmr2->vdev.name, v4l2_dev->name, sizeof(fmr2->vdev.name)); + fmr2->vdev.v4l2_dev = v4l2_dev; + fmr2->vdev.fops = &fmr2_fops; + fmr2->vdev.ioctl_ops = &fmr2_ioctl_ops; + fmr2->vdev.release = video_device_release_empty; + video_set_drvdata(&fmr2->vdev, fmr2); - /* Only card_type == 11 implements volume */ - if (fmr2_unit.card_type != 11) - radio_qctrl[AUD_VOL_INDEX].maximum = 1; + if (video_register_device(&fmr2->vdev, VFL_TYPE_RADIO, radio_nr) < 0) { + v4l2_device_unregister(v4l2_dev); + release_region(fmr2->io, 2); + return -EINVAL; + } + v4l2_info(v4l2_dev, "SF16FMR2 radio card driver at 0x%x.\n", fmr2->io); + /* mute card - prevents noisy bootups */ + mutex_lock(&fmr2->lock); + fmr2_mute(fmr2->io); + fmr2_product_info(fmr2); + mutex_unlock(&fmr2->lock); + debug_print((KERN_DEBUG "card_type %d\n", fmr2->card_type)); return 0; } -MODULE_AUTHOR("Ziglio Frediano, freddy77@angelfire.com"); -MODULE_DESCRIPTION("A driver for the SF16FMR2 radio."); -MODULE_LICENSE("GPL"); - -module_param(io, int, 0); -MODULE_PARM_DESC(io, "I/O address of the SF16FMR2 card (should be 0x384, if do not work try 0x284)"); -module_param(radio_nr, int, 0); - -static void __exit fmr2_cleanup_module(void) +static void __exit fmr2_exit(void) { - video_unregister_device(&fmr2_radio); - release_region(io,2); + struct fmr2 *fmr2 = &fmr2_card; + + video_unregister_device(&fmr2->vdev); + v4l2_device_unregister(&fmr2->v4l2_dev); + release_region(fmr2->io, 2); } module_init(fmr2_init); -module_exit(fmr2_cleanup_module); +module_exit(fmr2_exit); #ifndef MODULE -- cgit v1.2.3 From 241f0d88b7d45102e0c58b0532cbc4b4b3090a87 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 6 Mar 2009 17:53:58 +0100 Subject: radio-terratec: convert to v4l2_device. From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/radio/radio-terratec.c | 312 ++++++++++++++--------------- 1 file changed, 148 insertions(+), 164 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/radio/radio-terratec.c b/linux/drivers/media/radio/radio-terratec.c index 1c2b4db2d..b63443076 100644 --- a/linux/drivers/media/radio/radio-terratec.c +++ b/linux/drivers/media/radio/radio-terratec.c @@ -28,16 +28,31 @@ #include /* Initdata */ #include /* request_region */ #include /* udelay */ -#include /* outb, outb_p */ -#include /* copy to/from user */ -#include "compat.h" #include /* kernel radio structs */ -#include +#include +#include /* for KERNEL_VERSION MACRO */ +#include /* outb, outb_p */ +#include /* copy to/from user */ +#include #include -#include +#include "compat.h" -#include /* for KERNEL_VERSION MACRO */ -#define RADIO_VERSION KERNEL_VERSION(0,0,2) +MODULE_AUTHOR("R.OFFERMANNS & others"); +MODULE_DESCRIPTION("A driver for the TerraTec ActiveRadio Standalone radio card."); +MODULE_LICENSE("GPL"); + +#ifndef CONFIG_RADIO_TERRATEC_PORT +#define CONFIG_RADIO_TERRATEC_PORT 0x590 +#endif + +static int io = CONFIG_RADIO_TERRATEC_PORT; +static int radio_nr = -1; + +module_param(io, int, 0); +MODULE_PARM_DESC(io, "I/O address of the TerraTec ActiveRadio card (0x590 or 0x591)"); +module_param(radio_nr, int, 0); + +#define RADIO_VERSION KERNEL_VERSION(0, 0, 2) static struct v4l2_queryctrl radio_qctrl[] = { { @@ -58,13 +73,6 @@ static struct v4l2_queryctrl radio_qctrl[] = { } }; -#ifndef CONFIG_RADIO_TERRATEC_PORT -#define CONFIG_RADIO_TERRATEC_PORT 0x590 -#endif - -/**************** this ones are for the terratec *******************/ -#define BASEPORT 0x590 -#define VOLPORT 0x591 #define WRT_DIS 0x00 #define CLK_OFF 0x00 #define IIC_DATA 0x01 @@ -72,138 +80,124 @@ static struct v4l2_queryctrl radio_qctrl[] = { #define DATA 0x04 #define CLK_ON 0x08 #define WRT_EN 0x10 -/*******************************************************************/ - -static int io = CONFIG_RADIO_TERRATEC_PORT; -static int radio_nr = -1; -static spinlock_t lock; -struct tt_device +struct terratec { - unsigned long in_use; - int port; + struct v4l2_device v4l2_dev; + struct video_device vdev; + int io; int curvol; unsigned long curfreq; int muted; + struct mutex lock; }; +static struct terratec terratec_card; /* local things */ -static void cardWriteVol(int volume) +static void tt_write_vol(struct terratec *tt, int volume) { int i; - volume = volume+(volume * 32); // change both channels - spin_lock(&lock); - for (i=0;i<8;i++) - { - if (volume & (0x80>>i)) - outb(0x80, VOLPORT); - else outb(0x00, VOLPORT); + + volume = volume + (volume * 32); /* change both channels */ + mutex_lock(&tt->lock); + for (i = 0; i < 8; i++) { + if (volume & (0x80 >> i)) + outb(0x80, tt->io + 1); + else + outb(0x00, tt->io + 1); } - spin_unlock(&lock); + mutex_unlock(&tt->lock); } -static void tt_mute(struct tt_device *dev) +static void tt_mute(struct terratec *tt) { - dev->muted = 1; - cardWriteVol(0); + tt->muted = 1; + tt_write_vol(tt, 0); } -static int tt_setvol(struct tt_device *dev, int vol) +static int tt_setvol(struct terratec *tt, int vol) { - -// printk(KERN_ERR "setvol called, vol = %d\n", vol); - - if(vol == dev->curvol) { /* requested volume = current */ - if (dev->muted) { /* user is unmuting the card */ - dev->muted = 0; - cardWriteVol(vol); /* enable card */ + if (vol == tt->curvol) { /* requested volume = current */ + if (tt->muted) { /* user is unmuting the card */ + tt->muted = 0; + tt_write_vol(tt, vol); /* enable card */ } - return 0; } - if(vol == 0) { /* volume = 0 means mute the card */ - cardWriteVol(0); /* "turn off card" by setting vol to 0 */ - dev->curvol = vol; /* track the volume state! */ + if (vol == 0) { /* volume = 0 means mute the card */ + tt_write_vol(tt, 0); /* "turn off card" by setting vol to 0 */ + tt->curvol = vol; /* track the volume state! */ return 0; } - dev->muted = 0; - - cardWriteVol(vol); - - dev->curvol = vol; - + tt->muted = 0; + tt_write_vol(tt, vol); + tt->curvol = vol; return 0; - } /* this is the worst part in this driver */ /* many more or less strange things are going on here, but hey, it works :) */ -static int tt_setfreq(struct tt_device *dev, unsigned long freq1) +static int tt_setfreq(struct terratec *tt, unsigned long freq1) { int freq; int i; int p; int temp; long rest; - unsigned char buffer[25]; /* we have to bit shift 25 registers */ - freq = freq1/160; /* convert the freq. to a nice to handle value */ - for(i=24;i>-1;i--) - buffer[i]=0; - rest = freq*10+10700; /* i once had understood what is going on here */ + mutex_lock(&tt->lock); + + tt->curfreq = freq1; + + freq = freq1 / 160; /* convert the freq. to a nice to handle value */ + memset(buffer, 0, sizeof(buffer)); + + rest = freq * 10 + 10700; /* I once had understood what is going on here */ /* maybe some wise guy (friedhelm?) can comment this stuff */ - i=13; - p=10; - temp=102400; - while (rest!=0) - { - if (rest%temp == rest) + i = 13; + p = 10; + temp = 102400; + while (rest != 0) { + if (rest % temp == rest) buffer[i] = 0; - else - { + else { buffer[i] = 1; - rest = rest-temp; + rest = rest - temp; } i--; p--; - temp = temp/2; + temp = temp / 2; } - spin_lock(&lock); - - for (i=24;i>-1;i--) /* bit shift the values to the radiocard */ - { - if (buffer[i]==1) - { - outb(WRT_EN|DATA, BASEPORT); - outb(WRT_EN|DATA|CLK_ON , BASEPORT); - outb(WRT_EN|DATA, BASEPORT); - } - else - { - outb(WRT_EN|0x00, BASEPORT); - outb(WRT_EN|0x00|CLK_ON , BASEPORT); + for (i = 24; i > -1; i--) { /* bit shift the values to the radiocard */ + if (buffer[i] == 1) { + outb(WRT_EN | DATA, tt->io); + outb(WRT_EN | DATA | CLK_ON, tt->io); + outb(WRT_EN | DATA, tt->io); + } else { + outb(WRT_EN | 0x00, tt->io); + outb(WRT_EN | 0x00 | CLK_ON, tt->io); } } - outb(0x00, BASEPORT); + outb(0x00, tt->io); - spin_unlock(&lock); + mutex_unlock(&tt->lock); return 0; } -static int tt_getsigstr(struct tt_device *dev) /* TODO */ +static int tt_getsigstr(struct terratec *tt) { - if (inb(io) & 2) /* bit set = no signal present */ + if (inb(tt->io) & 2) /* bit set = no signal present */ return 0; return 1; /* signal present */ } @@ -213,53 +207,50 @@ static int vidioc_querycap(struct file *file, void *priv, { strlcpy(v->driver, "radio-terratec", sizeof(v->driver)); strlcpy(v->card, "ActiveRadio", sizeof(v->card)); - sprintf(v->bus_info, "ISA"); + strlcpy(v->bus_info, "ISA", sizeof(v->bus_info)); v->version = RADIO_VERSION; - v->capabilities = V4L2_CAP_TUNER; + v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO; return 0; } static int vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *v) { - struct tt_device *tt = video_drvdata(file); + struct terratec *tt = video_drvdata(file); if (v->index > 0) return -EINVAL; - strcpy(v->name, "FM"); + strlcpy(v->name, "FM", sizeof(v->name)); v->type = V4L2_TUNER_RADIO; - v->rangelow = (87*16000); - v->rangehigh = (108*16000); + v->rangelow = 87 * 16000; + v->rangehigh = 108 * 16000; v->rxsubchans = V4L2_TUNER_SUB_MONO; v->capability = V4L2_TUNER_CAP_LOW; v->audmode = V4L2_TUNER_MODE_MONO; - v->signal = 0xFFFF*tt_getsigstr(tt); + v->signal = 0xFFFF * tt_getsigstr(tt); return 0; } static int vidioc_s_tuner(struct file *file, void *priv, struct v4l2_tuner *v) { - if (v->index > 0) - return -EINVAL; - return 0; + return v->index ? -EINVAL : 0; } static int vidioc_s_frequency(struct file *file, void *priv, struct v4l2_frequency *f) { - struct tt_device *tt = video_drvdata(file); + struct terratec *tt = video_drvdata(file); - tt->curfreq = f->frequency; - tt_setfreq(tt, tt->curfreq); + tt_setfreq(tt, f->frequency); return 0; } static int vidioc_g_frequency(struct file *file, void *priv, struct v4l2_frequency *f) { - struct tt_device *tt = video_drvdata(file); + struct terratec *tt = video_drvdata(file); f->type = V4L2_TUNER_RADIO; f->frequency = tt->curfreq; @@ -273,8 +264,7 @@ static int vidioc_queryctrl(struct file *file, void *priv, for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) { if (qc->id && qc->id == radio_qctrl[i].id) { - memcpy(qc, &(radio_qctrl[i]), - sizeof(*qc)); + memcpy(qc, &(radio_qctrl[i]), sizeof(*qc)); return 0; } } @@ -284,7 +274,7 @@ static int vidioc_queryctrl(struct file *file, void *priv, static int vidioc_g_ctrl(struct file *file, void *priv, struct v4l2_control *ctrl) { - struct tt_device *tt = video_drvdata(file); + struct terratec *tt = video_drvdata(file); switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: @@ -303,7 +293,7 @@ static int vidioc_g_ctrl(struct file *file, void *priv, static int vidioc_s_ctrl(struct file *file, void *priv, struct v4l2_control *ctrl) { - struct tt_device *tt = video_drvdata(file); + struct terratec *tt = video_drvdata(file); switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: @@ -319,17 +309,6 @@ static int vidioc_s_ctrl(struct file *file, void *priv, return -EINVAL; } -static int vidioc_g_audio(struct file *file, void *priv, - struct v4l2_audio *a) -{ - if (a->index > 1) - return -EINVAL; - - strcpy(a->name, "Radio"); - a->capability = V4L2_AUDCAP_STEREO; - return 0; -} - static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i) { *i = 0; @@ -338,36 +317,38 @@ static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i) static int vidioc_s_input(struct file *filp, void *priv, unsigned int i) { - if (i != 0) - return -EINVAL; - return 0; + return i ? -EINVAL : 0; } -static int vidioc_s_audio(struct file *file, void *priv, +static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a) { - if (a->index != 0) - return -EINVAL; + a->index = 0; + strlcpy(a->name, "Radio", sizeof(a->name)); + a->capability = V4L2_AUDCAP_STEREO; return 0; } -static struct tt_device terratec_unit; +static int vidioc_s_audio(struct file *file, void *priv, + struct v4l2_audio *a) +{ + return a->index ? -EINVAL : 0; +} -static int terratec_exclusive_open(struct file *file) +static int terratec_open(struct file *file) { - return test_and_set_bit(0, &terratec_unit.in_use) ? -EBUSY : 0; + return 0; } -static int terratec_exclusive_release(struct file *file) +static int terratec_release(struct file *file) { - clear_bit(0, &terratec_unit.in_use); return 0; } static const struct v4l2_file_operations terratec_fops = { .owner = THIS_MODULE, - .open = terratec_exclusive_open, - .release = terratec_exclusive_release, + .open = terratec_open, + .release = terratec_release, .ioctl = video_ioctl2, }; @@ -386,60 +367,63 @@ static const struct v4l2_ioctl_ops terratec_ioctl_ops = { .vidioc_s_input = vidioc_s_input, }; -static struct video_device terratec_radio = { - .name = "TerraTec ActiveRadio", - .fops = &terratec_fops, - .ioctl_ops = &terratec_ioctl_ops, - .release = video_device_release_empty, -}; - static int __init terratec_init(void) { - if(io==-1) - { - printk(KERN_ERR "You must set an I/O address with io=0x???\n"); + struct terratec *tt = &terratec_card; + struct v4l2_device *v4l2_dev = &tt->v4l2_dev; + int res; + + strlcpy(v4l2_dev->name, "terratec", sizeof(v4l2_dev->name)); + tt->io = io; + if (tt->io == -1) { + v4l2_err(v4l2_dev, "you must set an I/O address with io=0x???\n"); return -EINVAL; } - if (!request_region(io, 2, "terratec")) - { - printk(KERN_ERR "TerraTec: port 0x%x already in use\n", io); + if (!request_region(tt->io, 2, "terratec")) { + v4l2_err(v4l2_dev, "port 0x%x already in use\n", io); return -EBUSY; } - video_set_drvdata(&terratec_radio, &terratec_unit); + res = v4l2_device_register(NULL, v4l2_dev); + if (res < 0) { + release_region(tt->io, 2); + v4l2_err(v4l2_dev, "Could not register v4l2_device\n"); + return res; + } + + strlcpy(tt->vdev.name, v4l2_dev->name, sizeof(tt->vdev.name)); + tt->vdev.v4l2_dev = v4l2_dev; + tt->vdev.fops = &terratec_fops; + tt->vdev.ioctl_ops = &terratec_ioctl_ops; + tt->vdev.release = video_device_release_empty; + video_set_drvdata(&tt->vdev, tt); - spin_lock_init(&lock); + mutex_init(&tt->lock); - if (video_register_device(&terratec_radio, VFL_TYPE_RADIO, radio_nr) < 0) { - release_region(io,2); + if (video_register_device(&tt->vdev, VFL_TYPE_RADIO, radio_nr) < 0) { + v4l2_device_unregister(&tt->v4l2_dev); + release_region(tt->io, 2); return -EINVAL; } - printk(KERN_INFO "TERRATEC ActivRadio Standalone card driver.\n"); + v4l2_info(v4l2_dev, "TERRATEC ActivRadio Standalone card driver.\n"); /* mute card - prevents noisy bootups */ - - /* this ensures that the volume is all the way down */ - cardWriteVol(0); - terratec_unit.curvol = 0; - + tt_write_vol(tt, 0); return 0; } -MODULE_AUTHOR("R.OFFERMANNS & others"); -MODULE_DESCRIPTION("A driver for the TerraTec ActiveRadio Standalone radio card."); -MODULE_LICENSE("GPL"); -module_param(io, int, 0); -MODULE_PARM_DESC(io, "I/O address of the TerraTec ActiveRadio card (0x590 or 0x591)"); -module_param(radio_nr, int, 0); - -static void __exit terratec_cleanup_module(void) +static void __exit terratec_exit(void) { - video_unregister_device(&terratec_radio); - release_region(io,2); - printk(KERN_INFO "TERRATEC ActivRadio Standalone card driver unloaded.\n"); + struct terratec *tt = &terratec_card; + struct v4l2_device *v4l2_dev = &tt->v4l2_dev; + + video_unregister_device(&tt->vdev); + v4l2_device_unregister(&tt->v4l2_dev); + release_region(tt->io, 2); + v4l2_info(v4l2_dev, "TERRATEC ActivRadio Standalone card driver unloaded.\n"); } module_init(terratec_init); -module_exit(terratec_cleanup_module); +module_exit(terratec_exit); -- cgit v1.2.3 From ea7413e897555d76567d20e4124ba38502f71e52 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 6 Mar 2009 17:54:23 +0100 Subject: radio-trust: convert to v4l2_device. From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/radio/radio-trust.c | 349 ++++++++++++++++---------------- 1 file changed, 180 insertions(+), 169 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/radio/radio-trust.c b/linux/drivers/media/radio/radio-trust.c index 5ce7a9d1d..196db11de 100644 --- a/linux/drivers/media/radio/radio-trust.c +++ b/linux/drivers/media/radio/radio-trust.c @@ -19,50 +19,17 @@ #include #include #include -#include -#include -#include "compat.h" +#include /* for KERNEL_VERSION MACRO */ #include -#include +#include +#include +#include #include +#include "compat.h" -#include /* for KERNEL_VERSION MACRO */ -#define RADIO_VERSION KERNEL_VERSION(0,0,2) - -static struct v4l2_queryctrl radio_qctrl[] = { - { - .id = V4L2_CID_AUDIO_MUTE, - .name = "Mute", - .minimum = 0, - .maximum = 1, - .default_value = 1, - .type = V4L2_CTRL_TYPE_BOOLEAN, - },{ - .id = V4L2_CID_AUDIO_VOLUME, - .name = "Volume", - .minimum = 0, - .maximum = 65535, - .step = 2048, - .default_value = 65535, - .type = V4L2_CTRL_TYPE_INTEGER, - },{ - .id = V4L2_CID_AUDIO_BASS, - .name = "Bass", - .minimum = 0, - .maximum = 65535, - .step = 4370, - .default_value = 32768, - .type = V4L2_CTRL_TYPE_INTEGER, - },{ - .id = V4L2_CID_AUDIO_TREBLE, - .name = "Treble", - .minimum = 0, - .maximum = 65535, - .step = 4370, - .default_value = 32768, - .type = V4L2_CTRL_TYPE_INTEGER, - }, -}; +MODULE_AUTHOR("Eric Lammerts, Russell Kroll, Quay Lu, Donald Song, Jason Lewis, Scott McGrath, William McGrath"); +MODULE_DESCRIPTION("A driver for the Trust FM Radio card."); +MODULE_LICENSE("GPL"); /* acceptable ports: 0x350 (JP3 shorted), 0x358 (JP3 open) */ @@ -72,26 +39,41 @@ static struct v4l2_queryctrl radio_qctrl[] = { static int io = CONFIG_RADIO_TRUST_PORT; static int radio_nr = -1; -static int ioval = 0xf; -static __u16 curvol; -static __u16 curbass; -static __u16 curtreble; -static unsigned long curfreq; -static int curstereo; -static int curmute; -static unsigned long in_use; + +module_param(io, int, 0); +MODULE_PARM_DESC(io, "I/O address of the Trust FM Radio card (0x350 or 0x358)"); +module_param(radio_nr, int, 0); + +#define RADIO_VERSION KERNEL_VERSION(0, 0, 2) + +struct trust { + struct v4l2_device v4l2_dev; + struct video_device vdev; + int io; + int ioval; + __u16 curvol; + __u16 curbass; + __u16 curtreble; + int muted; + unsigned long curfreq; + int curstereo; + int curmute; + struct mutex lock; +}; + +static struct trust trust_card; /* i2c addresses */ #define TDA7318_ADDR 0x88 #define TSA6060T_ADDR 0xc4 -#define TR_DELAY do { inb(io); inb(io); inb(io); } while(0) -#define TR_SET_SCL outb(ioval |= 2, io) -#define TR_CLR_SCL outb(ioval &= 0xfd, io) -#define TR_SET_SDA outb(ioval |= 1, io) -#define TR_CLR_SDA outb(ioval &= 0xfe, io) +#define TR_DELAY do { inb(tr->io); inb(tr->io); inb(tr->io); } while (0) +#define TR_SET_SCL outb(tr->ioval |= 2, tr->io) +#define TR_CLR_SCL outb(tr->ioval &= 0xfd, tr->io) +#define TR_SET_SDA outb(tr->ioval |= 1, tr->io) +#define TR_CLR_SDA outb(tr->ioval &= 0xfe, tr->io) -static void write_i2c(int n, ...) +static void write_i2c(struct trust *tr, int n, ...) { unsigned char val, mask; va_list args; @@ -137,62 +119,77 @@ static void write_i2c(int n, ...) va_end(args); } -static void tr_setvol(__u16 vol) +static void tr_setvol(struct trust *tr, __u16 vol) { - curvol = vol / 2048; - write_i2c(2, TDA7318_ADDR, curvol ^ 0x1f); + mutex_lock(&tr->lock); + tr->curvol = vol / 2048; + write_i2c(tr, 2, TDA7318_ADDR, tr->curvol ^ 0x1f); + mutex_unlock(&tr->lock); } static int basstreble2chip[15] = { 0, 1, 2, 3, 4, 5, 6, 7, 14, 13, 12, 11, 10, 9, 8 }; -static void tr_setbass(__u16 bass) +static void tr_setbass(struct trust *tr, __u16 bass) { - curbass = bass / 4370; - write_i2c(2, TDA7318_ADDR, 0x60 | basstreble2chip[curbass]); + mutex_lock(&tr->lock); + tr->curbass = bass / 4370; + write_i2c(tr, 2, TDA7318_ADDR, 0x60 | basstreble2chip[tr->curbass]); + mutex_unlock(&tr->lock); } -static void tr_settreble(__u16 treble) +static void tr_settreble(struct trust *tr, __u16 treble) { - curtreble = treble / 4370; - write_i2c(2, TDA7318_ADDR, 0x70 | basstreble2chip[curtreble]); + mutex_lock(&tr->lock); + tr->curtreble = treble / 4370; + write_i2c(tr, 2, TDA7318_ADDR, 0x70 | basstreble2chip[tr->curtreble]); + mutex_unlock(&tr->lock); } -static void tr_setstereo(int stereo) +static void tr_setstereo(struct trust *tr, int stereo) { - curstereo = !!stereo; - ioval = (ioval & 0xfb) | (!curstereo << 2); - outb(ioval, io); + mutex_lock(&tr->lock); + tr->curstereo = !!stereo; + tr->ioval = (tr->ioval & 0xfb) | (!tr->curstereo << 2); + outb(tr->ioval, tr->io); + mutex_unlock(&tr->lock); } -static void tr_setmute(int mute) +static void tr_setmute(struct trust *tr, int mute) { - curmute = !!mute; - ioval = (ioval & 0xf7) | (curmute << 3); - outb(ioval, io); + mutex_lock(&tr->lock); + tr->curmute = !!mute; + tr->ioval = (tr->ioval & 0xf7) | (tr->curmute << 3); + outb(tr->ioval, tr->io); + mutex_unlock(&tr->lock); } -static int tr_getsigstr(void) +static int tr_getsigstr(struct trust *tr) { int i, v; - for(i = 0, v = 0; i < 100; i++) v |= inb(io); - return (v & 1)? 0 : 0xffff; + mutex_lock(&tr->lock); + for (i = 0, v = 0; i < 100; i++) + v |= inb(tr->io); + mutex_unlock(&tr->lock); + return (v & 1) ? 0 : 0xffff; } -static int tr_getstereo(void) +static int tr_getstereo(struct trust *tr) { /* don't know how to determine it, just return the setting */ - return curstereo; + return tr->curstereo; } -static void tr_setfreq(unsigned long f) +static void tr_setfreq(struct trust *tr, unsigned long f) { + mutex_lock(&tr->lock); + tr->curfreq = f; f /= 160; /* Convert to 10 kHz units */ - f += 1070; /* Add 10.7 MHz IF */ - - write_i2c(5, TSA6060T_ADDR, (f << 1) | 1, f >> 7, 0x60 | ((f >> 15) & 1), 0); + f += 1070; /* Add 10.7 MHz IF */ + write_i2c(tr, 5, TSA6060T_ADDR, (f << 1) | 1, f >> 7, 0x60 | ((f >> 15) & 1), 0); + mutex_unlock(&tr->lock); } static int vidioc_querycap(struct file *file, void *priv, @@ -200,68 +197,75 @@ static int vidioc_querycap(struct file *file, void *priv, { strlcpy(v->driver, "radio-trust", sizeof(v->driver)); strlcpy(v->card, "Trust FM Radio", sizeof(v->card)); - sprintf(v->bus_info, "ISA"); + strlcpy(v->bus_info, "ISA", sizeof(v->bus_info)); v->version = RADIO_VERSION; - v->capabilities = V4L2_CAP_TUNER; + v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO; return 0; } static int vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *v) { + struct trust *tr = video_drvdata(file); + if (v->index > 0) return -EINVAL; - strcpy(v->name, "FM"); + strlcpy(v->name, "FM", sizeof(v->name)); v->type = V4L2_TUNER_RADIO; - v->rangelow = (87.5*16000); - v->rangehigh = (108*16000); - v->rxsubchans = V4L2_TUNER_SUB_MONO|V4L2_TUNER_SUB_STEREO; + v->rangelow = 87.5 * 16000; + v->rangehigh = 108 * 16000; + v->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO; v->capability = V4L2_TUNER_CAP_LOW; - if (tr_getstereo()) + if (tr_getstereo(tr)) v->audmode = V4L2_TUNER_MODE_STEREO; else v->audmode = V4L2_TUNER_MODE_MONO; - v->signal = tr_getsigstr(); + v->signal = tr_getsigstr(tr); return 0; } static int vidioc_s_tuner(struct file *file, void *priv, struct v4l2_tuner *v) { - if (v->index > 0) - return -EINVAL; + struct trust *tr = video_drvdata(file); + if (v->index) + return -EINVAL; + tr_setstereo(tr, v->audmode == V4L2_TUNER_MODE_STEREO); return 0; } static int vidioc_s_frequency(struct file *file, void *priv, struct v4l2_frequency *f) { - curfreq = f->frequency; - tr_setfreq(curfreq); + struct trust *tr = video_drvdata(file); + + tr_setfreq(tr, f->frequency); return 0; } static int vidioc_g_frequency(struct file *file, void *priv, struct v4l2_frequency *f) { + struct trust *tr = video_drvdata(file); + f->type = V4L2_TUNER_RADIO; - f->frequency = curfreq; + f->frequency = tr->curfreq; return 0; } static int vidioc_queryctrl(struct file *file, void *priv, struct v4l2_queryctrl *qc) { - int i; - - for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) { - if (qc->id && qc->id == radio_qctrl[i].id) { - memcpy(qc, &(radio_qctrl[i]), - sizeof(*qc)); - return 0; - } + switch (qc->id) { + case V4L2_CID_AUDIO_MUTE: + return v4l2_ctrl_query_fill(qc, 0, 1, 1, 1); + case V4L2_CID_AUDIO_VOLUME: + return v4l2_ctrl_query_fill(qc, 0, 65535, 2048, 65535); + case V4L2_CID_AUDIO_BASS: + case V4L2_CID_AUDIO_TREBLE: + return v4l2_ctrl_query_fill(qc, 0, 65535, 4370, 32768); } return -EINVAL; } @@ -269,18 +273,20 @@ static int vidioc_queryctrl(struct file *file, void *priv, static int vidioc_g_ctrl(struct file *file, void *priv, struct v4l2_control *ctrl) { + struct trust *tr = video_drvdata(file); + switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: - ctrl->value = curmute; + ctrl->value = tr->curmute; return 0; case V4L2_CID_AUDIO_VOLUME: - ctrl->value = curvol * 2048; + ctrl->value = tr->curvol * 2048; return 0; case V4L2_CID_AUDIO_BASS: - ctrl->value = curbass * 4370; + ctrl->value = tr->curbass * 4370; return 0; case V4L2_CID_AUDIO_TREBLE: - ctrl->value = curtreble * 4370; + ctrl->value = tr->curtreble * 4370; return 0; } return -EINVAL; @@ -289,37 +295,25 @@ static int vidioc_g_ctrl(struct file *file, void *priv, static int vidioc_s_ctrl(struct file *file, void *priv, struct v4l2_control *ctrl) { + struct trust *tr = video_drvdata(file); + switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: - tr_setmute(ctrl->value); + tr_setmute(tr, ctrl->value); return 0; case V4L2_CID_AUDIO_VOLUME: - tr_setvol(ctrl->value); + tr_setvol(tr, ctrl->value); return 0; case V4L2_CID_AUDIO_BASS: - tr_setbass(ctrl->value); + tr_setbass(tr, ctrl->value); return 0; case V4L2_CID_AUDIO_TREBLE: - tr_settreble(ctrl->value); + tr_settreble(tr, ctrl->value); return 0; } -#if 0 /* Should implement mono/stereo on V4L2 */ - tr_setstereo(v->mode & VIDEO_SOUND_STEREO); -#endif return -EINVAL; } -static int vidioc_g_audio(struct file *file, void *priv, - struct v4l2_audio *a) -{ - if (a->index > 1) - return -EINVAL; - - strcpy(a->name, "Radio"); - a->capability = V4L2_AUDCAP_STEREO; - return 0; -} - static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i) { *i = 0; @@ -328,34 +322,38 @@ static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i) static int vidioc_s_input(struct file *filp, void *priv, unsigned int i) { - if (i != 0) - return -EINVAL; + return i ? -EINVAL : 0; +} + +static int vidioc_g_audio(struct file *file, void *priv, + struct v4l2_audio *a) +{ + a->index = 0; + strlcpy(a->name, "Radio", sizeof(a->name)); + a->capability = V4L2_AUDCAP_STEREO; return 0; } static int vidioc_s_audio(struct file *file, void *priv, struct v4l2_audio *a) { - if (a->index != 0) - return -EINVAL; - return 0; + return a->index ? -EINVAL : 0; } -static int trust_exclusive_open(struct file *file) +static int trust_open(struct file *file) { - return test_and_set_bit(0, &in_use) ? -EBUSY : 0; + return 0; } -static int trust_exclusive_release(struct file *file) +static int trust_release(struct file *file) { - clear_bit(0, &in_use); return 0; } static const struct v4l2_file_operations trust_fops = { .owner = THIS_MODULE, - .open = trust_exclusive_open, - .release = trust_exclusive_release, + .open = trust_open, + .release = trust_release, .ioctl = video_ioctl2, }; @@ -374,59 +372,72 @@ static const struct v4l2_ioctl_ops trust_ioctl_ops = { .vidioc_s_input = vidioc_s_input, }; -static struct video_device trust_radio = { - .name = "Trust FM Radio", - .fops = &trust_fops, - .ioctl_ops = &trust_ioctl_ops, - .release = video_device_release_empty, -}; - static int __init trust_init(void) { - if(io == -1) { - printk(KERN_ERR "You must set an I/O address with io=0x???\n"); + struct trust *tr = &trust_card; + struct v4l2_device *v4l2_dev = &tr->v4l2_dev; + int res; + + strlcpy(v4l2_dev->name, "trust", sizeof(v4l2_dev->name)); + tr->io = io; + tr->ioval = 0xf; + mutex_init(&tr->lock); + + if (tr->io == -1) { + v4l2_err(v4l2_dev, "You must set an I/O address with io=0x???\n"); return -EINVAL; } - if(!request_region(io, 2, "Trust FM Radio")) { - printk(KERN_ERR "trust: port 0x%x already in use\n", io); + if (!request_region(tr->io, 2, "Trust FM Radio")) { + v4l2_err(v4l2_dev, "port 0x%x already in use\n", tr->io); return -EBUSY; } - if (video_register_device(&trust_radio, VFL_TYPE_RADIO, radio_nr) < 0) { - release_region(io, 2); + + res = v4l2_device_register(NULL, v4l2_dev); + if (res < 0) { + release_region(tr->io, 2); + v4l2_err(v4l2_dev, "Could not register v4l2_device\n"); + return res; + } + + strlcpy(tr->vdev.name, v4l2_dev->name, sizeof(tr->vdev.name)); + tr->vdev.v4l2_dev = v4l2_dev; + tr->vdev.fops = &trust_fops; + tr->vdev.ioctl_ops = &trust_ioctl_ops; + tr->vdev.release = video_device_release_empty; + video_set_drvdata(&tr->vdev, tr); + + if (video_register_device(&tr->vdev, VFL_TYPE_RADIO, radio_nr) < 0) { + v4l2_device_unregister(v4l2_dev); + release_region(tr->io, 2); return -EINVAL; } - printk(KERN_INFO "Trust FM Radio card driver v1.0.\n"); + v4l2_info(v4l2_dev, "Trust FM Radio card driver v1.0.\n"); - write_i2c(2, TDA7318_ADDR, 0x80); /* speaker att. LF = 0 dB */ - write_i2c(2, TDA7318_ADDR, 0xa0); /* speaker att. RF = 0 dB */ - write_i2c(2, TDA7318_ADDR, 0xc0); /* speaker att. LR = 0 dB */ - write_i2c(2, TDA7318_ADDR, 0xe0); /* speaker att. RR = 0 dB */ - write_i2c(2, TDA7318_ADDR, 0x40); /* stereo 1 input, gain = 18.75 dB */ + write_i2c(tr, 2, TDA7318_ADDR, 0x80); /* speaker att. LF = 0 dB */ + write_i2c(tr, 2, TDA7318_ADDR, 0xa0); /* speaker att. RF = 0 dB */ + write_i2c(tr, 2, TDA7318_ADDR, 0xc0); /* speaker att. LR = 0 dB */ + write_i2c(tr, 2, TDA7318_ADDR, 0xe0); /* speaker att. RR = 0 dB */ + write_i2c(tr, 2, TDA7318_ADDR, 0x40); /* stereo 1 input, gain = 18.75 dB */ - tr_setvol(0x8000); - tr_setbass(0x8000); - tr_settreble(0x8000); - tr_setstereo(1); + tr_setvol(tr, 0xffff); + tr_setbass(tr, 0x8000); + tr_settreble(tr, 0x8000); + tr_setstereo(tr, 1); /* mute card - prevents noisy bootups */ - tr_setmute(1); + tr_setmute(tr, 1); return 0; } -MODULE_AUTHOR("Eric Lammerts, Russell Kroll, Quay Lu, Donald Song, Jason Lewis, Scott McGrath, William McGrath"); -MODULE_DESCRIPTION("A driver for the Trust FM Radio card."); -MODULE_LICENSE("GPL"); - -module_param(io, int, 0); -MODULE_PARM_DESC(io, "I/O address of the Trust FM Radio card (0x350 or 0x358)"); -module_param(radio_nr, int, 0); - static void __exit cleanup_trust_module(void) { - video_unregister_device(&trust_radio); - release_region(io, 2); + struct trust *tr = &trust_card; + + video_unregister_device(&tr->vdev); + v4l2_device_unregister(&tr->v4l2_dev); + release_region(tr->io, 2); } module_init(trust_init); -- cgit v1.2.3 From 60f11d69155659eb8ed46eb60c0fa3fa2c48fb77 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 6 Mar 2009 17:54:52 +0100 Subject: radio-typhoon: convert to v4l2_device. From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/radio/radio-typhoon.c | 352 ++++++++++++------------------ 1 file changed, 142 insertions(+), 210 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/radio/radio-typhoon.c b/linux/drivers/media/radio/radio-typhoon.c index bf812fbb5..11e3775ab 100644 --- a/linux/drivers/media/radio/radio-typhoon.c +++ b/linux/drivers/media/radio/radio-typhoon.c @@ -34,38 +34,17 @@ #include /* Modules */ #include /* Initdata */ #include /* request_region */ -#include /* radio card status report */ -#include -#include /* outb, outb_p */ -#include /* copy to/from user */ -#include "compat.h" +#include /* for KERNEL_VERSION MACRO */ #include /* kernel radio structs */ -#include +#include /* outb, outb_p */ +#include /* copy to/from user */ +#include #include +#include "compat.h" -#include /* for KERNEL_VERSION MACRO */ -#define RADIO_VERSION KERNEL_VERSION(0,1,1) -#define BANNER "Typhoon Radio Card driver v0.1.1\n" - -static struct v4l2_queryctrl radio_qctrl[] = { - { - .id = V4L2_CID_AUDIO_MUTE, - .name = "Mute", - .minimum = 0, - .maximum = 1, - .default_value = 1, - .type = V4L2_CTRL_TYPE_BOOLEAN, - },{ - .id = V4L2_CID_AUDIO_VOLUME, - .name = "Volume", - .minimum = 0, - .maximum = 65535, - .step = 1<<14, - .default_value = 0xff, - .type = V4L2_CTRL_TYPE_INTEGER, - } -}; - +MODULE_AUTHOR("Dr. Henrik Seidel"); +MODULE_DESCRIPTION("A driver for the Typhoon radio card (a.k.a. EcoRadio)."); +MODULE_LICENSE("GPL"); #ifndef CONFIG_RADIO_TYPHOON_PORT #define CONFIG_RADIO_TYPHOON_PORT -1 @@ -75,13 +54,26 @@ static struct v4l2_queryctrl radio_qctrl[] = { #define CONFIG_RADIO_TYPHOON_MUTEFREQ 0 #endif -#ifndef CONFIG_PROC_FS -#undef CONFIG_RADIO_TYPHOON_PROC_FS -#endif +static int io = CONFIG_RADIO_TYPHOON_PORT; +static int radio_nr = -1; + +module_param(io, int, 0); +MODULE_PARM_DESC(io, "I/O address of the Typhoon card (0x316 or 0x336)"); + +module_param(radio_nr, int, 0); + +static unsigned long mutefreq = CONFIG_RADIO_TYPHOON_MUTEFREQ; +module_param(mutefreq, ulong, 0); +MODULE_PARM_DESC(mutefreq, "Frequency used when muting the card (in kHz)"); + +#define RADIO_VERSION KERNEL_VERSION(0, 1, 1) + +#define BANNER "Typhoon Radio Card driver v0.1.1\n" -struct typhoon_device { - unsigned long in_use; - int iobase; +struct typhoon { + struct v4l2_device v4l2_dev; + struct video_device vdev; + int io; int curvol; int muted; unsigned long curfreq; @@ -89,25 +81,19 @@ struct typhoon_device { struct mutex lock; }; -static void typhoon_setvol_generic(struct typhoon_device *dev, int vol); -static int typhoon_setfreq_generic(struct typhoon_device *dev, - unsigned long frequency); -static int typhoon_setfreq(struct typhoon_device *dev, unsigned long frequency); -static void typhoon_mute(struct typhoon_device *dev); -static void typhoon_unmute(struct typhoon_device *dev); -static int typhoon_setvol(struct typhoon_device *dev, int vol); +static struct typhoon typhoon_card; -static void typhoon_setvol_generic(struct typhoon_device *dev, int vol) +static void typhoon_setvol_generic(struct typhoon *dev, int vol) { mutex_lock(&dev->lock); vol >>= 14; /* Map 16 bit to 2 bit */ vol &= 3; - outb_p(vol / 2, dev->iobase); /* Set the volume, high bit. */ - outb_p(vol % 2, dev->iobase + 2); /* Set the volume, low bit. */ + outb_p(vol / 2, dev->io); /* Set the volume, high bit. */ + outb_p(vol % 2, dev->io + 2); /* Set the volume, low bit. */ mutex_unlock(&dev->lock); } -static int typhoon_setfreq_generic(struct typhoon_device *dev, +static int typhoon_setfreq_generic(struct typhoon *dev, unsigned long frequency) { unsigned long outval; @@ -131,22 +117,22 @@ static int typhoon_setfreq_generic(struct typhoon_device *dev, outval -= (10 * x * x + 10433) / 20866; outval += 4 * x - 11505; - outb_p((outval >> 8) & 0x01, dev->iobase + 4); - outb_p(outval >> 9, dev->iobase + 6); - outb_p(outval & 0xff, dev->iobase + 8); + outb_p((outval >> 8) & 0x01, dev->io + 4); + outb_p(outval >> 9, dev->io + 6); + outb_p(outval & 0xff, dev->io + 8); mutex_unlock(&dev->lock); return 0; } -static int typhoon_setfreq(struct typhoon_device *dev, unsigned long frequency) +static int typhoon_setfreq(struct typhoon *dev, unsigned long frequency) { typhoon_setfreq_generic(dev, frequency); dev->curfreq = frequency; return 0; } -static void typhoon_mute(struct typhoon_device *dev) +static void typhoon_mute(struct typhoon *dev) { if (dev->muted == 1) return; @@ -155,7 +141,7 @@ static void typhoon_mute(struct typhoon_device *dev) dev->muted = 1; } -static void typhoon_unmute(struct typhoon_device *dev) +static void typhoon_unmute(struct typhoon *dev) { if (dev->muted == 0) return; @@ -164,7 +150,7 @@ static void typhoon_unmute(struct typhoon_device *dev) dev->muted = 0; } -static int typhoon_setvol(struct typhoon_device *dev, int vol) +static int typhoon_setvol(struct typhoon *dev, int vol) { if (dev->muted && vol != 0) { /* user is unmuting the card */ dev->curvol = vol; @@ -189,9 +175,9 @@ static int vidioc_querycap(struct file *file, void *priv, { strlcpy(v->driver, "radio-typhoon", sizeof(v->driver)); strlcpy(v->card, "Typhoon Radio", sizeof(v->card)); - sprintf(v->bus_info, "ISA"); + strlcpy(v->bus_info, "ISA", sizeof(v->bus_info)); v->version = RADIO_VERSION; - v->capabilities = V4L2_CAP_TUNER; + v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO; return 0; } @@ -201,10 +187,10 @@ static int vidioc_g_tuner(struct file *file, void *priv, if (v->index > 0) return -EINVAL; - strcpy(v->name, "FM"); + strlcpy(v->name, "FM", sizeof(v->name)); v->type = V4L2_TUNER_RADIO; - v->rangelow = (87.5*16000); - v->rangehigh = (108*16000); + v->rangelow = 87.5 * 16000; + v->rangehigh = 108 * 16000; v->rxsubchans = V4L2_TUNER_SUB_MONO; v->capability = V4L2_TUNER_CAP_LOW; v->audmode = V4L2_TUNER_MODE_MONO; @@ -215,44 +201,37 @@ static int vidioc_g_tuner(struct file *file, void *priv, static int vidioc_s_tuner(struct file *file, void *priv, struct v4l2_tuner *v) { - if (v->index > 0) - return -EINVAL; - - return 0; + return v->index ? -EINVAL : 0; } -static int vidioc_s_frequency(struct file *file, void *priv, +static int vidioc_g_frequency(struct file *file, void *priv, struct v4l2_frequency *f) { - struct typhoon_device *typhoon = video_drvdata(file); + struct typhoon *dev = video_drvdata(file); - typhoon->curfreq = f->frequency; - typhoon_setfreq(typhoon, typhoon->curfreq); + f->type = V4L2_TUNER_RADIO; + f->frequency = dev->curfreq; return 0; } -static int vidioc_g_frequency(struct file *file, void *priv, +static int vidioc_s_frequency(struct file *file, void *priv, struct v4l2_frequency *f) { - struct typhoon_device *typhoon = video_drvdata(file); - - f->type = V4L2_TUNER_RADIO; - f->frequency = typhoon->curfreq; + struct typhoon *dev = video_drvdata(file); + dev->curfreq = f->frequency; + typhoon_setfreq(dev, dev->curfreq); return 0; } static int vidioc_queryctrl(struct file *file, void *priv, struct v4l2_queryctrl *qc) { - int i; - - for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) { - if (qc->id && qc->id == radio_qctrl[i].id) { - memcpy(qc, &(radio_qctrl[i]), - sizeof(*qc)); - return 0; - } + switch (qc->id) { + case V4L2_CID_AUDIO_MUTE: + return v4l2_ctrl_query_fill(qc, 0, 1, 1, 1); + case V4L2_CID_AUDIO_VOLUME: + return v4l2_ctrl_query_fill(qc, 0, 65535, 16384, 65535); } return -EINVAL; } @@ -260,14 +239,14 @@ static int vidioc_queryctrl(struct file *file, void *priv, static int vidioc_g_ctrl(struct file *file, void *priv, struct v4l2_control *ctrl) { - struct typhoon_device *typhoon = video_drvdata(file); + struct typhoon *dev = video_drvdata(file); switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: - ctrl->value = typhoon->muted; + ctrl->value = dev->muted; return 0; case V4L2_CID_AUDIO_VOLUME: - ctrl->value = typhoon->curvol; + ctrl->value = dev->curvol; return 0; } return -EINVAL; @@ -276,33 +255,22 @@ static int vidioc_g_ctrl(struct file *file, void *priv, static int vidioc_s_ctrl (struct file *file, void *priv, struct v4l2_control *ctrl) { - struct typhoon_device *typhoon = video_drvdata(file); + struct typhoon *dev = video_drvdata(file); switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: if (ctrl->value) - typhoon_mute(typhoon); + typhoon_mute(dev); else - typhoon_unmute(typhoon); + typhoon_unmute(dev); return 0; case V4L2_CID_AUDIO_VOLUME: - typhoon_setvol(typhoon, ctrl->value); + typhoon_setvol(dev, ctrl->value); return 0; } return -EINVAL; } -static int vidioc_g_audio(struct file *file, void *priv, - struct v4l2_audio *a) -{ - if (a->index > 1) - return -EINVAL; - - strcpy(a->name, "Radio"); - a->capability = V4L2_AUDCAP_STEREO; - return 0; -} - static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i) { *i = 0; @@ -311,45 +279,62 @@ static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i) static int vidioc_s_input(struct file *filp, void *priv, unsigned int i) { - if (i != 0) - return -EINVAL; + return i ? -EINVAL : 0; +} + +static int vidioc_g_audio(struct file *file, void *priv, + struct v4l2_audio *a) +{ + a->index = 0; + strlcpy(a->name, "Radio", sizeof(a->name)); + a->capability = V4L2_AUDCAP_STEREO; return 0; } static int vidioc_s_audio(struct file *file, void *priv, struct v4l2_audio *a) { - if (a->index != 0) - return -EINVAL; - return 0; + return a->index ? -EINVAL : 0; } -static struct typhoon_device typhoon_unit = +static int vidioc_log_status(struct file *file, void *priv) { - .iobase = CONFIG_RADIO_TYPHOON_PORT, - .curfreq = CONFIG_RADIO_TYPHOON_MUTEFREQ, - .mutefreq = CONFIG_RADIO_TYPHOON_MUTEFREQ, -}; + struct typhoon *dev = video_drvdata(file); + struct v4l2_device *v4l2_dev = &dev->v4l2_dev; + + v4l2_info(v4l2_dev, BANNER); +#ifdef MODULE + v4l2_info(v4l2_dev, "Load type: Driver loaded as a module\n\n"); +#else + v4l2_info(v4l2_dev, "Load type: Driver compiled into kernel\n\n"); +#endif + v4l2_info(v4l2_dev, "frequency = %lu kHz\n", dev->curfreq >> 4); + v4l2_info(v4l2_dev, "volume = %d\n", dev->curvol); + v4l2_info(v4l2_dev, "mute = %s\n", dev->muted ? "on" : "off"); + v4l2_info(v4l2_dev, "io = 0x%x\n", dev->io); + v4l2_info(v4l2_dev, "mute frequency = %lu kHz\n", dev->mutefreq >> 4); + return 0; +} -static int typhoon_exclusive_open(struct file *file) +static int typhoon_open(struct file *file) { - return test_and_set_bit(0, &typhoon_unit.in_use) ? -EBUSY : 0; + return 0; } -static int typhoon_exclusive_release(struct file *file) +static int typhoon_release(struct file *file) { - clear_bit(0, &typhoon_unit.in_use); return 0; } static const struct v4l2_file_operations typhoon_fops = { .owner = THIS_MODULE, - .open = typhoon_exclusive_open, - .release = typhoon_exclusive_release, + .open = typhoon_open, + .release = typhoon_release, .ioctl = video_ioctl2, }; static const struct v4l2_ioctl_ops typhoon_ioctl_ops = { + .vidioc_log_status = vidioc_log_status, .vidioc_querycap = vidioc_querycap, .vidioc_g_tuner = vidioc_g_tuner, .vidioc_s_tuner = vidioc_s_tuner, @@ -364,125 +349,72 @@ static const struct v4l2_ioctl_ops typhoon_ioctl_ops = { .vidioc_s_ctrl = vidioc_s_ctrl, }; -static struct video_device typhoon_radio = { - .name = "Typhoon Radio", - .fops = &typhoon_fops, - .ioctl_ops = &typhoon_ioctl_ops, - .release = video_device_release_empty, -}; - -#ifdef CONFIG_RADIO_TYPHOON_PROC_FS - -static int typhoon_proc_show(struct seq_file *m, void *v) -{ - #ifdef MODULE - #define MODULEPROCSTRING "Driver loaded as a module" - #else - #define MODULEPROCSTRING "Driver compiled into kernel" - #endif - - seq_puts(m, BANNER); - seq_puts(m, "Load type: " MODULEPROCSTRING "\n\n"); - seq_printf(m, "frequency = %lu kHz\n", - typhoon_unit.curfreq >> 4); - seq_printf(m, "volume = %d\n", typhoon_unit.curvol); - seq_printf(m, "mute = %s\n", typhoon_unit.muted ? - "on" : "off"); - seq_printf(m, "iobase = 0x%x\n", typhoon_unit.iobase); - seq_printf(m, "mute frequency = %lu kHz\n", - typhoon_unit.mutefreq >> 4); - return 0; -} - -static int typhoon_proc_open(struct inode *inode, struct file *file) +static int __init typhoon_init(void) { - return single_open(file, typhoon_proc_show, NULL); -} + struct typhoon *dev = &typhoon_card; + struct v4l2_device *v4l2_dev = &dev->v4l2_dev; + int res; -static const struct file_operations typhoon_proc_fops = { - .owner = THIS_MODULE, - .open = typhoon_proc_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; -#endif /* CONFIG_RADIO_TYPHOON_PROC_FS */ + strlcpy(v4l2_dev->name, "typhoon", sizeof(v4l2_dev->name)); + dev->io = io; + dev->curfreq = dev->mutefreq = mutefreq; -MODULE_AUTHOR("Dr. Henrik Seidel"); -MODULE_DESCRIPTION("A driver for the Typhoon radio card (a.k.a. EcoRadio)."); -MODULE_LICENSE("GPL"); - -static int io = -1; -static int radio_nr = -1; - -module_param(io, int, 0); -MODULE_PARM_DESC(io, "I/O address of the Typhoon card (0x316 or 0x336)"); -module_param(radio_nr, int, 0); - -#ifdef MODULE -static unsigned long mutefreq; -module_param(mutefreq, ulong, 0); -MODULE_PARM_DESC(mutefreq, "Frequency used when muting the card (in kHz)"); -#endif - -static int __init typhoon_init(void) -{ -#ifdef MODULE - if (io == -1) { - printk(KERN_ERR "radio-typhoon: You must set an I/O address with io=0x316 or io=0x336\n"); + if (dev->io == -1) { + v4l2_err(v4l2_dev, "You must set an I/O address with io=0x316 or io=0x336\n"); return -EINVAL; } - typhoon_unit.iobase = io; - if (mutefreq < 87000 || mutefreq > 108500) { - printk(KERN_ERR "radio-typhoon: You must set a frequency (in kHz) used when muting the card,\n"); - printk(KERN_ERR "radio-typhoon: e.g. with \"mutefreq=87500\" (87000 <= mutefreq <= 108500)\n"); + if (dev->mutefreq < 87000 || dev->mutefreq > 108500) { + v4l2_err(v4l2_dev, "You must set a frequency (in kHz) used when muting the card,\n"); + v4l2_err(v4l2_dev, "e.g. with \"mutefreq=87500\" (87000 <= mutefreq <= 108500)\n"); return -EINVAL; } - typhoon_unit.mutefreq = mutefreq; -#endif /* MODULE */ - - printk(KERN_INFO BANNER); - mutex_init(&typhoon_unit.lock); - io = typhoon_unit.iobase; - if (!request_region(io, 8, "typhoon")) { - printk(KERN_ERR "radio-typhoon: port 0x%x already in use\n", - typhoon_unit.iobase); + + mutex_init(&dev->lock); + if (!request_region(dev->io, 8, "typhoon")) { + v4l2_err(v4l2_dev, "port 0x%x already in use\n", + dev->io); return -EBUSY; } - video_set_drvdata(&typhoon_radio, &typhoon_unit); - if (video_register_device(&typhoon_radio, VFL_TYPE_RADIO, radio_nr) < 0) { - release_region(io, 8); + res = v4l2_device_register(NULL, v4l2_dev); + if (res < 0) { + release_region(dev->io, 8); + v4l2_err(v4l2_dev, "Could not register v4l2_device\n"); + return res; + } + v4l2_info(v4l2_dev, BANNER); + + strlcpy(dev->vdev.name, v4l2_dev->name, sizeof(dev->vdev.name)); + dev->vdev.v4l2_dev = v4l2_dev; + dev->vdev.fops = &typhoon_fops; + dev->vdev.ioctl_ops = &typhoon_ioctl_ops; + dev->vdev.release = video_device_release_empty; + video_set_drvdata(&dev->vdev, dev); + if (video_register_device(&dev->vdev, VFL_TYPE_RADIO, radio_nr) < 0) { + v4l2_device_unregister(&dev->v4l2_dev); + release_region(dev->io, 8); return -EINVAL; } - printk(KERN_INFO "radio-typhoon: port 0x%x.\n", typhoon_unit.iobase); - printk(KERN_INFO "radio-typhoon: mute frequency is %lu kHz.\n", - typhoon_unit.mutefreq); - typhoon_unit.mutefreq <<= 4; + v4l2_info(v4l2_dev, "port 0x%x.\n", dev->io); + v4l2_info(v4l2_dev, "mute frequency is %lu kHz.\n", dev->mutefreq); + dev->mutefreq <<= 4; /* mute card - prevents noisy bootups */ - typhoon_mute(&typhoon_unit); - -#ifdef CONFIG_RADIO_TYPHOON_PROC_FS - if (!proc_create("driver/radio-typhoon", 0, NULL, &typhoon_proc_fops)) - printk(KERN_ERR "radio-typhoon: registering /proc/driver/radio-typhoon failed\n"); -#endif + typhoon_mute(dev); return 0; } -static void __exit typhoon_cleanup_module(void) +static void __exit typhoon_exit(void) { + struct typhoon *dev = &typhoon_card; -#ifdef CONFIG_RADIO_TYPHOON_PROC_FS - remove_proc_entry("driver/radio-typhoon", NULL); -#endif - - video_unregister_device(&typhoon_radio); - release_region(io, 8); + video_unregister_device(&dev->vdev); + v4l2_device_unregister(&dev->v4l2_dev); + release_region(dev->io, 8); } module_init(typhoon_init); -module_exit(typhoon_cleanup_module); +module_exit(typhoon_exit); -- cgit v1.2.3 From 8cf31fefb7f2a3a6c95c9f66fc63e00ec6b0bec0 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 6 Mar 2009 17:55:34 +0100 Subject: radio-zoltrix: convert to v4l2_device. From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/radio/radio-zoltrix.c | 381 ++++++++++++++---------------- 1 file changed, 179 insertions(+), 202 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/radio/radio-zoltrix.c b/linux/drivers/media/radio/radio-zoltrix.c index 4654ecd8b..93bc72adb 100644 --- a/linux/drivers/media/radio/radio-zoltrix.c +++ b/linux/drivers/media/radio/radio-zoltrix.c @@ -33,34 +33,18 @@ #include /* Initdata */ #include /* request_region */ #include /* udelay, msleep */ -#include /* outb, outb_p */ -#include /* copy to/from user */ -#include "compat.h" #include /* kernel radio structs */ -#include +#include +#include /* for KERNEL_VERSION MACRO */ +#include /* outb, outb_p */ +#include /* copy to/from user */ +#include #include +#include "compat.h" -#include /* for KERNEL_VERSION MACRO */ -#define RADIO_VERSION KERNEL_VERSION(0,0,2) - -static struct v4l2_queryctrl radio_qctrl[] = { - { - .id = V4L2_CID_AUDIO_MUTE, - .name = "Mute", - .minimum = 0, - .maximum = 1, - .default_value = 1, - .type = V4L2_CTRL_TYPE_BOOLEAN, - },{ - .id = V4L2_CID_AUDIO_VOLUME, - .name = "Volume", - .minimum = 0, - .maximum = 65535, - .step = 4096, - .default_value = 0xff, - .type = V4L2_CTRL_TYPE_INTEGER, - } -}; +MODULE_AUTHOR("C.van Schaik"); +MODULE_DESCRIPTION("A driver for the Zoltrix Radio Plus."); +MODULE_LICENSE("GPL"); #ifndef CONFIG_RADIO_ZOLTRIX_PORT #define CONFIG_RADIO_ZOLTRIX_PORT -1 @@ -69,9 +53,16 @@ static struct v4l2_queryctrl radio_qctrl[] = { static int io = CONFIG_RADIO_ZOLTRIX_PORT; static int radio_nr = -1; -struct zol_device { - unsigned long in_use; - int port; +module_param(io, int, 0); +MODULE_PARM_DESC(io, "I/O address of the Zoltrix Radio Plus (0x20c or 0x30c)"); +module_param(radio_nr, int, 0); + +#define RADIO_VERSION KERNEL_VERSION(0, 0, 2) + +struct zoltrix { + struct v4l2_device v4l2_dev; + struct video_device vdev; + int io; int curvol; unsigned long curfreq; int muted; @@ -79,161 +70,158 @@ struct zol_device { struct mutex lock; }; -static int zol_setvol(struct zol_device *dev, int vol) +static struct zoltrix zoltrix_card; + +static int zol_setvol(struct zoltrix *zol, int vol) { - dev->curvol = vol; - if (dev->muted) + zol->curvol = vol; + if (zol->muted) return 0; - mutex_lock(&dev->lock); + mutex_lock(&zol->lock); if (vol == 0) { - outb(0, io); - outb(0, io); - inb(io + 3); /* Zoltrix needs to be read to confirm */ - mutex_unlock(&dev->lock); + outb(0, zol->io); + outb(0, zol->io); + inb(zol->io + 3); /* Zoltrix needs to be read to confirm */ + mutex_unlock(&zol->lock); return 0; } - outb(dev->curvol-1, io); + outb(zol->curvol-1, zol->io); msleep(10); - inb(io + 2); - mutex_unlock(&dev->lock); + inb(zol->io + 2); + mutex_unlock(&zol->lock); return 0; } -static void zol_mute(struct zol_device *dev) +static void zol_mute(struct zoltrix *zol) { - dev->muted = 1; - mutex_lock(&dev->lock); - outb(0, io); - outb(0, io); - inb(io + 3); /* Zoltrix needs to be read to confirm */ - mutex_unlock(&dev->lock); + zol->muted = 1; + mutex_lock(&zol->lock); + outb(0, zol->io); + outb(0, zol->io); + inb(zol->io + 3); /* Zoltrix needs to be read to confirm */ + mutex_unlock(&zol->lock); } -static void zol_unmute(struct zol_device *dev) +static void zol_unmute(struct zoltrix *zol) { - dev->muted = 0; - zol_setvol(dev, dev->curvol); + zol->muted = 0; + zol_setvol(zol, zol->curvol); } -static int zol_setfreq(struct zol_device *dev, unsigned long freq) +static int zol_setfreq(struct zoltrix *zol, unsigned long freq) { /* tunes the radio to the desired frequency */ + struct v4l2_device *v4l2_dev = &zol->v4l2_dev; unsigned long long bitmask, f, m; - unsigned int stereo = dev->stereo; + unsigned int stereo = zol->stereo; int i; if (freq == 0) { - printk(KERN_WARNING "zoltrix: received zero freq. Failed to set.\n"); + v4l2_warn(v4l2_dev, "cannot set a frequency of 0.\n"); return -EINVAL; } m = (freq / 160 - 8800) * 2; - f = (unsigned long long) m + 0x4d1c; + f = (unsigned long long)m + 0x4d1c; bitmask = 0xc480402c10080000ull; i = 45; - mutex_lock(&dev->lock); + mutex_lock(&zol->lock); - outb(0, io); - outb(0, io); - inb(io + 3); /* Zoltrix needs to be read to confirm */ + zol->curfreq = freq; - outb(0x40, io); - outb(0xc0, io); + outb(0, zol->io); + outb(0, zol->io); + inb(zol->io + 3); /* Zoltrix needs to be read to confirm */ - bitmask = (bitmask ^ ((f & 0xff) << 47) ^ ((f & 0xff00) << 30) ^ ( stereo << 31)); + outb(0x40, zol->io); + outb(0xc0, zol->io); + + bitmask = (bitmask ^ ((f & 0xff) << 47) ^ ((f & 0xff00) << 30) ^ (stereo << 31)); while (i--) { if ((bitmask & 0x8000000000000000ull) != 0) { - outb(0x80, io); + outb(0x80, zol->io); udelay(50); - outb(0x00, io); + outb(0x00, zol->io); udelay(50); - outb(0x80, io); + outb(0x80, zol->io); udelay(50); } else { - outb(0xc0, io); + outb(0xc0, zol->io); udelay(50); - outb(0x40, io); + outb(0x40, zol->io); udelay(50); - outb(0xc0, io); + outb(0xc0, zol->io); udelay(50); } bitmask *= 2; } /* termination sequence */ - outb(0x80, io); - outb(0xc0, io); - outb(0x40, io); + outb(0x80, zol->io); + outb(0xc0, zol->io); + outb(0x40, zol->io); udelay(1000); - inb(io+2); + inb(zol->io + 2); udelay(1000); - if (dev->muted) - { - outb(0, io); - outb(0, io); - inb(io + 3); + if (zol->muted) { + outb(0, zol->io); + outb(0, zol->io); + inb(zol->io + 3); udelay(1000); } - mutex_unlock(&dev->lock); + mutex_unlock(&zol->lock); - if(!dev->muted) - { - zol_setvol(dev, dev->curvol); - } + if (!zol->muted) + zol_setvol(zol, zol->curvol); return 0; } /* Get signal strength */ - -static int zol_getsigstr(struct zol_device *dev) +static int zol_getsigstr(struct zoltrix *zol) { int a, b; - mutex_lock(&dev->lock); - outb(0x00, io); /* This stuff I found to do nothing */ - outb(dev->curvol, io); + mutex_lock(&zol->lock); + outb(0x00, zol->io); /* This stuff I found to do nothing */ + outb(zol->curvol, zol->io); msleep(20); - a = inb(io); + a = inb(zol->io); msleep(10); - b = inb(io); + b = inb(zol->io); - mutex_unlock(&dev->lock); + mutex_unlock(&zol->lock); if (a != b) - return (0); + return 0; - if ((a == 0xcf) || (a == 0xdf) /* I found this out by playing */ - || (a == 0xef)) /* with a binary scanner on the card io */ - return (1); - return (0); + /* I found this out by playing with a binary scanner on the card io */ + return a == 0xcf || a == 0xdf || a == 0xef; } -static int zol_is_stereo (struct zol_device *dev) +static int zol_is_stereo(struct zoltrix *zol) { int x1, x2; - mutex_lock(&dev->lock); + mutex_lock(&zol->lock); - outb(0x00, io); - outb(dev->curvol, io); + outb(0x00, zol->io); + outb(zol->curvol, zol->io); msleep(20); - x1 = inb(io); + x1 = inb(zol->io); msleep(10); - x2 = inb(io); + x2 = inb(zol->io); - mutex_unlock(&dev->lock); + mutex_unlock(&zol->lock); - if ((x1 == x2) && (x1 == 0xcf)) - return 1; - return 0; + return x1 == x2 && x1 == 0xcf; } static int vidioc_querycap(struct file *file, void *priv, @@ -241,59 +229,54 @@ static int vidioc_querycap(struct file *file, void *priv, { strlcpy(v->driver, "radio-zoltrix", sizeof(v->driver)); strlcpy(v->card, "Zoltrix Radio", sizeof(v->card)); - sprintf(v->bus_info, "ISA"); + strlcpy(v->bus_info, "ISA", sizeof(v->bus_info)); v->version = RADIO_VERSION; - v->capabilities = V4L2_CAP_TUNER; + v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO; return 0; } static int vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *v) { - struct zol_device *zol = video_drvdata(file); + struct zoltrix *zol = video_drvdata(file); if (v->index > 0) return -EINVAL; - strcpy(v->name, "FM"); + strlcpy(v->name, "FM", sizeof(v->name)); v->type = V4L2_TUNER_RADIO; - v->rangelow = (88*16000); - v->rangehigh = (108*16000); - v->rxsubchans = V4L2_TUNER_SUB_MONO|V4L2_TUNER_SUB_STEREO; + v->rangelow = 88 * 16000; + v->rangehigh = 108 * 16000; + v->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO; v->capability = V4L2_TUNER_CAP_LOW; if (zol_is_stereo(zol)) v->audmode = V4L2_TUNER_MODE_STEREO; else v->audmode = V4L2_TUNER_MODE_MONO; - v->signal = 0xFFFF*zol_getsigstr(zol); + v->signal = 0xFFFF * zol_getsigstr(zol); return 0; } static int vidioc_s_tuner(struct file *file, void *priv, struct v4l2_tuner *v) { - if (v->index > 0) - return -EINVAL; - return 0; + return v->index ? -EINVAL : 0; } static int vidioc_s_frequency(struct file *file, void *priv, struct v4l2_frequency *f) { - struct zol_device *zol = video_drvdata(file); + struct zoltrix *zol = video_drvdata(file); - zol->curfreq = f->frequency; - if (zol_setfreq(zol, zol->curfreq) != 0) { - printk(KERN_WARNING "zoltrix: Set frequency failed.\n"); + if (zol_setfreq(zol, f->frequency) != 0) return -EINVAL; - } return 0; } static int vidioc_g_frequency(struct file *file, void *priv, struct v4l2_frequency *f) { - struct zol_device *zol = video_drvdata(file); + struct zoltrix *zol = video_drvdata(file); f->type = V4L2_TUNER_RADIO; f->frequency = zol->curfreq; @@ -303,14 +286,11 @@ static int vidioc_g_frequency(struct file *file, void *priv, static int vidioc_queryctrl(struct file *file, void *priv, struct v4l2_queryctrl *qc) { - int i; - - for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) { - if (qc->id && qc->id == radio_qctrl[i].id) { - memcpy(qc, &(radio_qctrl[i]), - sizeof(*qc)); - return 0; - } + switch (qc->id) { + case V4L2_CID_AUDIO_MUTE: + return v4l2_ctrl_query_fill(qc, 0, 1, 1, 1); + case V4L2_CID_AUDIO_VOLUME: + return v4l2_ctrl_query_fill(qc, 0, 65535, 4096, 65535); } return -EINVAL; } @@ -318,7 +298,7 @@ static int vidioc_queryctrl(struct file *file, void *priv, static int vidioc_g_ctrl(struct file *file, void *priv, struct v4l2_control *ctrl) { - struct zol_device *zol = video_drvdata(file); + struct zoltrix *zol = video_drvdata(file); switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: @@ -334,7 +314,7 @@ static int vidioc_g_ctrl(struct file *file, void *priv, static int vidioc_s_ctrl(struct file *file, void *priv, struct v4l2_control *ctrl) { - struct zol_device *zol = video_drvdata(file); + struct zoltrix *zol = video_drvdata(file); switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: @@ -342,43 +322,30 @@ static int vidioc_s_ctrl(struct file *file, void *priv, zol_mute(zol); else { zol_unmute(zol); - zol_setvol(zol,zol->curvol); + zol_setvol(zol, zol->curvol); } return 0; case V4L2_CID_AUDIO_VOLUME: - zol_setvol(zol,ctrl->value/4096); + zol_setvol(zol, ctrl->value / 4096); return 0; } zol->stereo = 1; - if (zol_setfreq(zol, zol->curfreq) != 0) { - printk(KERN_WARNING "zoltrix: Set frequency failed.\n"); + if (zol_setfreq(zol, zol->curfreq) != 0) return -EINVAL; - } #if 0 /*keep*/ /* FIXME: Implement stereo/mono switch on V4L2 */ - if (v->mode & VIDEO_SOUND_STEREO) { - zol->stereo = 1; - zol_setfreq(zol, zol->curfreq); - } - if (v->mode & VIDEO_SOUND_MONO) { - zol->stereo = 0; - zol_setfreq(zol, zol->curfreq); - } + if (v->mode & VIDEO_SOUND_STEREO) { + zol->stereo = 1; + zol_setfreq(zol, zol->curfreq); + } + if (v->mode & VIDEO_SOUND_MONO) { + zol->stereo = 0; + zol_setfreq(zol, zol->curfreq); + } #endif return -EINVAL; } -static int vidioc_g_audio(struct file *file, void *priv, - struct v4l2_audio *a) -{ - if (a->index > 1) - return -EINVAL; - - strcpy(a->name, "Radio"); - a->capability = V4L2_AUDCAP_STEREO; - return 0; -} - static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i) { *i = 0; @@ -387,37 +354,39 @@ static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i) static int vidioc_s_input(struct file *filp, void *priv, unsigned int i) { - if (i != 0) - return -EINVAL; - return 0; + return i ? -EINVAL : 0; } -static int vidioc_s_audio(struct file *file, void *priv, +static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a) { - if (a->index != 0) - return -EINVAL; + a->index = 0; + strlcpy(a->name, "Radio", sizeof(a->name)); + a->capability = V4L2_AUDCAP_STEREO; return 0; } -static struct zol_device zoltrix_unit; +static int vidioc_s_audio(struct file *file, void *priv, + struct v4l2_audio *a) +{ + return a->index ? -EINVAL : 0; +} -static int zoltrix_exclusive_open(struct file *file) +static int zoltrix_open(struct file *file) { - return test_and_set_bit(0, &zoltrix_unit.in_use) ? -EBUSY : 0; + return 0; } -static int zoltrix_exclusive_release(struct file *file) +static int zoltrix_release(struct file *file) { - clear_bit(0, &zoltrix_unit.in_use); return 0; } static const struct v4l2_file_operations zoltrix_fops = { .owner = THIS_MODULE, - .open = zoltrix_exclusive_open, - .release = zoltrix_exclusive_release, + .open = zoltrix_open, + .release = zoltrix_release, .ioctl = video_ioctl2, }; @@ -436,67 +405,75 @@ static const struct v4l2_ioctl_ops zoltrix_ioctl_ops = { .vidioc_s_ctrl = vidioc_s_ctrl, }; -static struct video_device zoltrix_radio = { - .name = "Zoltrix Radio Plus", - .fops = &zoltrix_fops, - .ioctl_ops = &zoltrix_ioctl_ops, - .release = video_device_release_empty, -}; - static int __init zoltrix_init(void) { - if (io == -1) { - printk(KERN_ERR "You must set an I/O address with io=0x???\n"); + struct zoltrix *zol = &zoltrix_card; + struct v4l2_device *v4l2_dev = &zol->v4l2_dev; + int res; + + strlcpy(v4l2_dev->name, "zoltrix", sizeof(v4l2_dev->name)); + zol->io = io; + if (zol->io == -1) { + v4l2_err(v4l2_dev, "You must set an I/O address with io=0x???\n"); return -EINVAL; } - if ((io != 0x20c) && (io != 0x30c)) { - printk(KERN_ERR "zoltrix: invalid port, try 0x20c or 0x30c\n"); + if (zol->io != 0x20c && zol->io != 0x30c) { + v4l2_err(v4l2_dev, "invalid port, try 0x20c or 0x30c\n"); return -ENXIO; } - video_set_drvdata(&zoltrix_radio, &zoltrix_unit); - if (!request_region(io, 2, "zoltrix")) { - printk(KERN_ERR "zoltrix: port 0x%x already in use\n", io); + if (!request_region(zol->io, 2, "zoltrix")) { + v4l2_err(v4l2_dev, "port 0x%x already in use\n", zol->io); return -EBUSY; } - if (video_register_device(&zoltrix_radio, VFL_TYPE_RADIO, radio_nr) < 0) { - release_region(io, 2); + res = v4l2_device_register(NULL, v4l2_dev); + if (res < 0) { + release_region(zol->io, 2); + v4l2_err(v4l2_dev, "Could not register v4l2_device\n"); + return res; + } + + strlcpy(zol->vdev.name, v4l2_dev->name, sizeof(zol->vdev.name)); + zol->vdev.v4l2_dev = v4l2_dev; + zol->vdev.fops = &zoltrix_fops; + zol->vdev.ioctl_ops = &zoltrix_ioctl_ops; + zol->vdev.release = video_device_release_empty; + video_set_drvdata(&zol->vdev, zol); + + if (video_register_device(&zol->vdev, VFL_TYPE_RADIO, radio_nr) < 0) { + v4l2_device_unregister(v4l2_dev); + release_region(zol->io, 2); return -EINVAL; } - printk(KERN_INFO "Zoltrix Radio Plus card driver.\n"); + v4l2_info(v4l2_dev, "Zoltrix Radio Plus card driver.\n"); - mutex_init(&zoltrix_unit.lock); + mutex_init(&zol->lock); /* mute card - prevents noisy bootups */ /* this ensures that the volume is all the way down */ - outb(0, io); - outb(0, io); + outb(0, zol->io); + outb(0, zol->io); msleep(20); - inb(io + 3); + inb(zol->io + 3); - zoltrix_unit.curvol = 0; - zoltrix_unit.stereo = 1; + zol->curvol = 0; + zol->stereo = 1; return 0; } -MODULE_AUTHOR("C.van Schaik"); -MODULE_DESCRIPTION("A driver for the Zoltrix Radio Plus."); -MODULE_LICENSE("GPL"); - -module_param(io, int, 0); -MODULE_PARM_DESC(io, "I/O address of the Zoltrix Radio Plus (0x20c or 0x30c)"); -module_param(radio_nr, int, 0); - -static void __exit zoltrix_cleanup_module(void) +static void __exit zoltrix_exit(void) { - video_unregister_device(&zoltrix_radio); - release_region(io, 2); + struct zoltrix *zol = &zoltrix_card; + + video_unregister_device(&zol->vdev); + v4l2_device_unregister(&zol->v4l2_dev); + release_region(zol->io, 2); } module_init(zoltrix_init); -module_exit(zoltrix_cleanup_module); +module_exit(zoltrix_exit); -- cgit v1.2.3 From 2c96263b343a7a5eb2d017b7727227941a00fc3d Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Sat, 7 Mar 2009 00:06:09 -0600 Subject: pvrusb2: Split i2c module handling from i2c adapter From: Mike Isely This is the first step in the effort to move the pvrusb2 driver over to using the v4l2-subdev framework. This commit involves mainly splitting apart pvrusb2-i2c-core - part of it is the driver's I2C adapter driver and the rest is the old i2c module handling logic. The i2c module handling junk is moved out to pvrusb2-i2c-track and various header references are correspondingly updated. Yes, this patch has a huge pile of checkpatch complaints, but I'm NOT going to fix any of it. Why? First, I'm moving a large chunk of existing code and I'm not going to spend time adjusting it to match someone's idea of coding style. Second, in the end I expect all that moved code to go away by the time the rework is done so wasting time on it now to adhere to the standard is in the end a large waste of time. Priority: normal Signed-off-by: Mike Isely --- linux/drivers/media/video/pvrusb2/Makefile | 1 + linux/drivers/media/video/pvrusb2/pvrusb2-audio.h | 2 +- .../media/video/pvrusb2/pvrusb2-cx2584x-v4l.h | 2 +- .../drivers/media/video/pvrusb2/pvrusb2-debugifc.c | 2 +- linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c | 3 + .../media/video/pvrusb2/pvrusb2-i2c-chips-v4l2.c | 2 +- .../media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.h | 2 +- .../drivers/media/video/pvrusb2/pvrusb2-i2c-core.c | 417 +----------------- .../drivers/media/video/pvrusb2/pvrusb2-i2c-core.h | 57 +-- .../media/video/pvrusb2/pvrusb2-i2c-track.c | 481 +++++++++++++++++++++ .../media/video/pvrusb2/pvrusb2-i2c-track.h | 97 +++++ linux/drivers/media/video/pvrusb2/pvrusb2-tuner.h | 2 +- .../media/video/pvrusb2/pvrusb2-video-v4l.h | 2 +- linux/drivers/media/video/pvrusb2/pvrusb2-wm8775.h | 2 +- 14 files changed, 596 insertions(+), 476 deletions(-) create mode 100644 linux/drivers/media/video/pvrusb2/pvrusb2-i2c-track.c create mode 100644 linux/drivers/media/video/pvrusb2/pvrusb2-i2c-track.h (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/pvrusb2/Makefile b/linux/drivers/media/video/pvrusb2/Makefile index 4fda2de69..931d9d1a0 100644 --- a/linux/drivers/media/video/pvrusb2/Makefile +++ b/linux/drivers/media/video/pvrusb2/Makefile @@ -3,6 +3,7 @@ obj-pvrusb2-debugifc-$(CONFIG_VIDEO_PVRUSB2_DEBUGIFC) := pvrusb2-debugifc.o obj-pvrusb2-dvb-$(CONFIG_VIDEO_PVRUSB2_DVB) := pvrusb2-dvb.o pvrusb2-objs := pvrusb2-i2c-core.o pvrusb2-i2c-cmd-v4l2.o \ + pvrusb2-i2c-track.o \ pvrusb2-audio.o pvrusb2-i2c-chips-v4l2.o \ pvrusb2-encoder.o pvrusb2-video-v4l.o \ pvrusb2-eeprom.o pvrusb2-tuner.o \ diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-audio.h b/linux/drivers/media/video/pvrusb2/pvrusb2-audio.h index ac54eed37..f7f0a408a 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-audio.h +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-audio.h @@ -22,7 +22,7 @@ #ifndef __PVRUSB2_AUDIO_H #define __PVRUSB2_AUDIO_H -#include "pvrusb2-i2c-core.h" +#include "pvrusb2-i2c-track.h" int pvr2_i2c_msp3400_setup(struct pvr2_hdw *,struct pvr2_i2c_client *); diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.h b/linux/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.h index 66abf77f5..f664f5942 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.h +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.h @@ -34,7 +34,7 @@ -#include "pvrusb2-i2c-core.h" +#include "pvrusb2-i2c-track.h" int pvr2_i2c_cx2584x_v4l_setup(struct pvr2_hdw *,struct pvr2_i2c_client *); diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-debugifc.c b/linux/drivers/media/video/pvrusb2/pvrusb2-debugifc.c index ca892fb78..cc4ef891b 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-debugifc.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-debugifc.c @@ -23,7 +23,7 @@ #include "pvrusb2-debugifc.h" #include "pvrusb2-hdw.h" #include "pvrusb2-debug.h" -#include "pvrusb2-i2c-core.h" +#include "pvrusb2-i2c-track.h" struct debugifc_mask_item { const char *name; diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c index 19e12c5aa..e6306dd8e 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -29,6 +29,7 @@ #include "pvrusb2-util.h" #include "pvrusb2-hdw.h" #include "pvrusb2-i2c-core.h" +#include "pvrusb2-i2c-track.h" #include "pvrusb2-tuner.h" #include "pvrusb2-eeprom.h" #include "pvrusb2-hdw-internal.h" @@ -2007,6 +2008,7 @@ static void pvr2_hdw_setup_low(struct pvr2_hdw *hdw) } // This step MUST happen after the earlier powerup step. + pvr2_i2c_track_init(hdw); pvr2_i2c_core_init(hdw); if (!pvr2_hdw_dev_ok(hdw)) return; @@ -2525,6 +2527,7 @@ void pvr2_hdw_destroy(struct pvr2_hdw *hdw) hdw->decoder_ctrl->detach(hdw->decoder_ctrl->ctxt); } pvr2_i2c_core_done(hdw); + pvr2_i2c_track_done(hdw); pvr2_hdw_remove_usb_stuff(hdw); mutex_lock(&pvr2_unit_mtx); do { if ((hdw->unit_number >= 0) && diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-chips-v4l2.c b/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-chips-v4l2.c index 073b02a4b..d8674ce36 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-chips-v4l2.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-chips-v4l2.c @@ -19,7 +19,7 @@ */ #include -#include "pvrusb2-i2c-core.h" +#include "pvrusb2-i2c-track.h" #include "pvrusb2-hdw-internal.h" #include "pvrusb2-debug.h" #include "pvrusb2-i2c-cmd-v4l2.h" diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.h b/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.h index 69a63f2a8..8472637e4 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.h +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.h @@ -22,7 +22,7 @@ #ifndef __PVRUSB2_CMD_V4L2_H #define __PVRUSB2_CMD_V4L2_H -#include "pvrusb2-i2c-core.h" +#include "pvrusb2-i2c-track.h" extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_init; extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_standard; diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c b/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c index d95abcc55..1601921b9 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c @@ -18,7 +18,9 @@ * */ +#include #include "pvrusb2-i2c-core.h" +#include "pvrusb2-i2c-track.h" #include "pvrusb2-hdw-internal.h" #include "pvrusb2-debug.h" #include "pvrusb2-fx2-cmd.h" @@ -30,8 +32,7 @@ /* This module attempts to implement a compliant I2C adapter for the pvrusb2 - device. By doing this we can then make use of existing functionality in - V4L (e.g. tuner.c) rather than rolling our own. + device. */ @@ -43,10 +44,6 @@ static int ir_mode[PVR_NUM] = { [0 ... PVR_NUM-1] = 1 }; module_param_array(ir_mode, int, NULL, 0444); MODULE_PARM_DESC(ir_mode,"specify: 0=disable IR reception, 1=normal IR"); -static unsigned int pvr2_i2c_client_describe(struct pvr2_i2c_client *cp, - unsigned int detail, - char *buf,unsigned int maxlen); - static int pvr2_i2c_write(struct pvr2_hdw *hdw, /* Context */ u8 i2c_addr, /* I2C address we're talking to */ u8 *data, /* Data to write */ @@ -599,414 +596,15 @@ static u32 pvr2_i2c_functionality(struct i2c_adapter *adap) return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_I2C; } -static int pvr2_i2c_core_singleton(struct i2c_client *cp, - unsigned int cmd,void *arg) -{ - int stat; - if (!cp) return -EINVAL; - if (!(cp->driver)) return -EINVAL; - if (!(cp->driver->command)) return -EINVAL; - if (!try_module_get(cp->driver->driver.owner)) return -EAGAIN; - stat = cp->driver->command(cp,cmd,arg); - module_put(cp->driver->driver.owner); - return stat; -} - -int pvr2_i2c_client_cmd(struct pvr2_i2c_client *cp,unsigned int cmd,void *arg) -{ - int stat; - if (pvrusb2_debug & PVR2_TRACE_I2C_CMD) { - char buf[100]; - unsigned int cnt; - cnt = pvr2_i2c_client_describe(cp,PVR2_I2C_DETAIL_DEBUG, - buf,sizeof(buf)); - pvr2_trace(PVR2_TRACE_I2C_CMD, - "i2c COMMAND (code=%u 0x%x) to %.*s", - cmd,cmd,cnt,buf); - } - stat = pvr2_i2c_core_singleton(cp->client,cmd,arg); - if (pvrusb2_debug & PVR2_TRACE_I2C_CMD) { - char buf[100]; - unsigned int cnt; - cnt = pvr2_i2c_client_describe(cp,PVR2_I2C_DETAIL_DEBUG, - buf,sizeof(buf)); - pvr2_trace(PVR2_TRACE_I2C_CMD, - "i2c COMMAND to %.*s (ret=%d)",cnt,buf,stat); - } - return stat; -} - -int pvr2_i2c_core_cmd(struct pvr2_hdw *hdw,unsigned int cmd,void *arg) -{ - struct pvr2_i2c_client *cp, *ncp; - int stat = -EINVAL; - - if (!hdw) return stat; - - mutex_lock(&hdw->i2c_list_lock); - list_for_each_entry_safe(cp, ncp, &hdw->i2c_clients, list) { - if (!cp->recv_enable) continue; - mutex_unlock(&hdw->i2c_list_lock); - stat = pvr2_i2c_client_cmd(cp,cmd,arg); - mutex_lock(&hdw->i2c_list_lock); - } - mutex_unlock(&hdw->i2c_list_lock); - return stat; -} - - -static int handler_check(struct pvr2_i2c_client *cp) -{ - struct pvr2_i2c_handler *hp = cp->handler; - if (!hp) return 0; - if (!hp->func_table->check) return 0; - return hp->func_table->check(hp->func_data) != 0; -} - -#define BUFSIZE 500 - - -void pvr2_i2c_core_status_poll(struct pvr2_hdw *hdw) -{ - struct pvr2_i2c_client *cp; - mutex_lock(&hdw->i2c_list_lock); do { - struct v4l2_tuner *vtp = &hdw->tuner_signal_info; - memset(vtp,0,sizeof(*vtp)); - list_for_each_entry(cp, &hdw->i2c_clients, list) { - if (!cp->detected_flag) continue; - if (!cp->status_poll) continue; - cp->status_poll(cp); - } - hdw->tuner_signal_stale = 0; - pvr2_trace(PVR2_TRACE_CHIPS,"i2c status poll" - " type=%u strength=%u audio=0x%x cap=0x%x" - " low=%u hi=%u", - vtp->type, - vtp->signal,vtp->rxsubchans,vtp->capability, - vtp->rangelow,vtp->rangehigh); - } while (0); mutex_unlock(&hdw->i2c_list_lock); -} - - -/* Issue various I2C operations to bring chip-level drivers into sync with - state stored in this driver. */ -void pvr2_i2c_core_sync(struct pvr2_hdw *hdw) -{ - unsigned long msk; - unsigned int idx; - struct pvr2_i2c_client *cp, *ncp; - - if (!hdw->i2c_linked) return; - if (!(hdw->i2c_pend_types & PVR2_I2C_PEND_ALL)) { - return; - } - mutex_lock(&hdw->i2c_list_lock); do { - pvr2_trace(PVR2_TRACE_I2C_CORE,"i2c: core_sync BEGIN"); - if (hdw->i2c_pend_types & PVR2_I2C_PEND_DETECT) { - /* One or more I2C clients have attached since we - last synced. So scan the list and identify the - new clients. */ - char *buf; - unsigned int cnt; - unsigned long amask = 0; - buf = kmalloc(BUFSIZE,GFP_KERNEL); - pvr2_trace(PVR2_TRACE_I2C_CORE,"i2c: PEND_DETECT"); - hdw->i2c_pend_types &= ~PVR2_I2C_PEND_DETECT; - list_for_each_entry(cp, &hdw->i2c_clients, list) { - if (!cp->detected_flag) { - cp->ctl_mask = 0; - pvr2_i2c_probe(hdw,cp); - cp->detected_flag = !0; - msk = cp->ctl_mask; - cnt = 0; - if (buf) { - cnt = pvr2_i2c_client_describe( - cp, - PVR2_I2C_DETAIL_ALL, - buf,BUFSIZE); - } - trace_i2c("Probed: %.*s",cnt,buf); - if (handler_check(cp)) { - hdw->i2c_pend_types |= - PVR2_I2C_PEND_CLIENT; - } - cp->pend_mask = msk; - hdw->i2c_pend_mask |= msk; - hdw->i2c_pend_types |= - PVR2_I2C_PEND_REFRESH; - } - amask |= cp->ctl_mask; - } - hdw->i2c_active_mask = amask; - if (buf) kfree(buf); - } - if (hdw->i2c_pend_types & PVR2_I2C_PEND_STALE) { - /* Need to do one or more global updates. Arrange - for this to happen. */ - unsigned long m2; - pvr2_trace(PVR2_TRACE_I2C_CORE, - "i2c: PEND_STALE (0x%lx)", - hdw->i2c_stale_mask); - hdw->i2c_pend_types &= ~PVR2_I2C_PEND_STALE; - list_for_each_entry(cp, &hdw->i2c_clients, list) { - m2 = hdw->i2c_stale_mask; - m2 &= cp->ctl_mask; - m2 &= ~cp->pend_mask; - if (m2) { - pvr2_trace(PVR2_TRACE_I2C_CORE, - "i2c: cp=%p setting 0x%lx", - cp,m2); - cp->pend_mask |= m2; - } - } - hdw->i2c_pend_mask |= hdw->i2c_stale_mask; - hdw->i2c_stale_mask = 0; - hdw->i2c_pend_types |= PVR2_I2C_PEND_REFRESH; - } - if (hdw->i2c_pend_types & PVR2_I2C_PEND_CLIENT) { - /* One or more client handlers are asking for an - update. Run through the list of known clients - and update each one. */ - pvr2_trace(PVR2_TRACE_I2C_CORE,"i2c: PEND_CLIENT"); - hdw->i2c_pend_types &= ~PVR2_I2C_PEND_CLIENT; - list_for_each_entry_safe(cp, ncp, &hdw->i2c_clients, - list) { - if (!cp->handler) continue; - if (!cp->handler->func_table->update) continue; - pvr2_trace(PVR2_TRACE_I2C_CORE, - "i2c: cp=%p update",cp); - mutex_unlock(&hdw->i2c_list_lock); - cp->handler->func_table->update( - cp->handler->func_data); - mutex_lock(&hdw->i2c_list_lock); - /* If client's update function set some - additional pending bits, account for that - here. */ - if (cp->pend_mask & ~hdw->i2c_pend_mask) { - hdw->i2c_pend_mask |= cp->pend_mask; - hdw->i2c_pend_types |= - PVR2_I2C_PEND_REFRESH; - } - } - } - if (hdw->i2c_pend_types & PVR2_I2C_PEND_REFRESH) { - const struct pvr2_i2c_op *opf; - unsigned long pm; - /* Some actual updates are pending. Walk through - each update type and perform it. */ - pvr2_trace(PVR2_TRACE_I2C_CORE,"i2c: PEND_REFRESH" - " (0x%lx)",hdw->i2c_pend_mask); - hdw->i2c_pend_types &= ~PVR2_I2C_PEND_REFRESH; - pm = hdw->i2c_pend_mask; - hdw->i2c_pend_mask = 0; - for (idx = 0, msk = 1; pm; idx++, msk <<= 1) { - if (!(pm & msk)) continue; - pm &= ~msk; - list_for_each_entry(cp, &hdw->i2c_clients, - list) { - if (cp->pend_mask & msk) { - cp->pend_mask &= ~msk; - cp->recv_enable = !0; - } else { - cp->recv_enable = 0; - } - } - opf = pvr2_i2c_get_op(idx); - if (!opf) continue; - mutex_unlock(&hdw->i2c_list_lock); - opf->update(hdw); - mutex_lock(&hdw->i2c_list_lock); - } - } - pvr2_trace(PVR2_TRACE_I2C_CORE,"i2c: core_sync END"); - } while (0); mutex_unlock(&hdw->i2c_list_lock); -} - -int pvr2_i2c_core_check_stale(struct pvr2_hdw *hdw) -{ - unsigned long msk,sm,pm; - unsigned int idx; - const struct pvr2_i2c_op *opf; - struct pvr2_i2c_client *cp; - unsigned int pt = 0; - - pvr2_trace(PVR2_TRACE_I2C_CORE,"pvr2_i2c_core_check_stale BEGIN"); - - pm = hdw->i2c_active_mask; - sm = 0; - for (idx = 0, msk = 1; pm; idx++, msk <<= 1) { - if (!(msk & pm)) continue; - pm &= ~msk; - opf = pvr2_i2c_get_op(idx); - if (!(opf && opf->check)) continue; - if (opf->check(hdw)) { - sm |= msk; - } - } - if (sm) pt |= PVR2_I2C_PEND_STALE; - - list_for_each_entry(cp, &hdw->i2c_clients, list) - if (handler_check(cp)) - pt |= PVR2_I2C_PEND_CLIENT; - - if (pt) { - mutex_lock(&hdw->i2c_list_lock); do { - hdw->i2c_pend_types |= pt; - hdw->i2c_stale_mask |= sm; - hdw->i2c_pend_mask |= hdw->i2c_stale_mask; - } while (0); mutex_unlock(&hdw->i2c_list_lock); - } - - pvr2_trace(PVR2_TRACE_I2C_CORE, - "i2c: types=0x%x stale=0x%lx pend=0x%lx", - hdw->i2c_pend_types, - hdw->i2c_stale_mask, - hdw->i2c_pend_mask); - pvr2_trace(PVR2_TRACE_I2C_CORE,"pvr2_i2c_core_check_stale END"); - - return (hdw->i2c_pend_types & PVR2_I2C_PEND_ALL) != 0; -} - -static unsigned int pvr2_i2c_client_describe(struct pvr2_i2c_client *cp, - unsigned int detail, - char *buf,unsigned int maxlen) -{ - unsigned int ccnt,bcnt; - int spcfl = 0; - const struct pvr2_i2c_op *opf; - - ccnt = 0; - if (detail & PVR2_I2C_DETAIL_DEBUG) { - bcnt = scnprintf(buf,maxlen, - "ctxt=%p ctl_mask=0x%lx", - cp,cp->ctl_mask); - ccnt += bcnt; buf += bcnt; maxlen -= bcnt; - spcfl = !0; - } - bcnt = scnprintf(buf,maxlen, - "%s%s @ 0x%x", - (spcfl ? " " : ""), - cp->client->name, - cp->client->addr); - ccnt += bcnt; buf += bcnt; maxlen -= bcnt; - if ((detail & PVR2_I2C_DETAIL_HANDLER) && - cp->handler && cp->handler->func_table->describe) { - bcnt = scnprintf(buf,maxlen," ("); - ccnt += bcnt; buf += bcnt; maxlen -= bcnt; - bcnt = cp->handler->func_table->describe( - cp->handler->func_data,buf,maxlen); - ccnt += bcnt; buf += bcnt; maxlen -= bcnt; - bcnt = scnprintf(buf,maxlen,")"); - ccnt += bcnt; buf += bcnt; maxlen -= bcnt; - } - if ((detail & PVR2_I2C_DETAIL_CTLMASK) && cp->ctl_mask) { - unsigned int idx; - unsigned long msk,sm; - - bcnt = scnprintf(buf,maxlen," ["); - ccnt += bcnt; buf += bcnt; maxlen -= bcnt; - sm = 0; - spcfl = 0; - for (idx = 0, msk = 1; msk; idx++, msk <<= 1) { - if (!(cp->ctl_mask & msk)) continue; - opf = pvr2_i2c_get_op(idx); - if (opf) { - bcnt = scnprintf(buf,maxlen,"%s%s", - spcfl ? " " : "", - opf->name); - ccnt += bcnt; buf += bcnt; maxlen -= bcnt; - spcfl = !0; - } else { - sm |= msk; - } - } - if (sm) { - bcnt = scnprintf(buf,maxlen,"%s%lx", - idx != 0 ? " " : "",sm); - ccnt += bcnt; buf += bcnt; maxlen -= bcnt; - } - bcnt = scnprintf(buf,maxlen,"]"); - ccnt += bcnt; buf += bcnt; maxlen -= bcnt; - } - return ccnt; -} - -unsigned int pvr2_i2c_report(struct pvr2_hdw *hdw, - char *buf,unsigned int maxlen) -{ - unsigned int ccnt,bcnt; - struct pvr2_i2c_client *cp; - ccnt = 0; - mutex_lock(&hdw->i2c_list_lock); do { - list_for_each_entry(cp, &hdw->i2c_clients, list) { - bcnt = pvr2_i2c_client_describe( - cp, - (PVR2_I2C_DETAIL_HANDLER| - PVR2_I2C_DETAIL_CTLMASK), - buf,maxlen); - ccnt += bcnt; buf += bcnt; maxlen -= bcnt; - bcnt = scnprintf(buf,maxlen,"\n"); - ccnt += bcnt; buf += bcnt; maxlen -= bcnt; - } - } while (0); mutex_unlock(&hdw->i2c_list_lock); - return ccnt; -} - static int pvr2_i2c_attach_inform(struct i2c_client *client) { - struct pvr2_hdw *hdw = (struct pvr2_hdw *)(client->adapter->algo_data); - struct pvr2_i2c_client *cp; - int fl = !(hdw->i2c_pend_types & PVR2_I2C_PEND_ALL); - cp = kzalloc(sizeof(*cp),GFP_KERNEL); - trace_i2c("i2c_attach [client=%s @ 0x%x ctxt=%p]", - client->name, - client->addr,cp); - if (!cp) return -ENOMEM; - cp->hdw = hdw; - INIT_LIST_HEAD(&cp->list); - cp->client = client; - mutex_lock(&hdw->i2c_list_lock); do { - hdw->cropcap_stale = !0; - list_add_tail(&cp->list,&hdw->i2c_clients); - hdw->i2c_pend_types |= PVR2_I2C_PEND_DETECT; - } while (0); mutex_unlock(&hdw->i2c_list_lock); - if (fl) queue_work(hdw->workqueue,&hdw->worki2csync); + pvr2_i2c_track_attach_inform(client); return 0; } static int pvr2_i2c_detach_inform(struct i2c_client *client) { - struct pvr2_hdw *hdw = (struct pvr2_hdw *)(client->adapter->algo_data); - struct pvr2_i2c_client *cp, *ncp; - unsigned long amask = 0; - int foundfl = 0; - mutex_lock(&hdw->i2c_list_lock); do { - hdw->cropcap_stale = !0; - list_for_each_entry_safe(cp, ncp, &hdw->i2c_clients, list) { - if (cp->client == client) { - trace_i2c("pvr2_i2c_detach" - " [client=%s @ 0x%x ctxt=%p]", - client->name, - client->addr,cp); - if (cp->handler && - cp->handler->func_table->detach) { - cp->handler->func_table->detach( - cp->handler->func_data); - } - list_del(&cp->list); - kfree(cp); - foundfl = !0; - continue; - } - amask |= cp->ctl_mask; - } - hdw->i2c_active_mask = amask; - } while (0); mutex_unlock(&hdw->i2c_list_lock); - if (!foundfl) { - trace_i2c("pvr2_i2c_detach [client=%s @ 0x%x ctxt=]", - client->name, - client->addr); - } + pvr2_i2c_track_detach_inform(client); return 0; } @@ -1087,11 +685,6 @@ void pvr2_i2c_core_init(struct pvr2_hdw *hdw) hdw->i2c_adap.dev.parent = &hdw->usb_dev->dev; hdw->i2c_adap.algo = &hdw->i2c_algo; hdw->i2c_adap.algo_data = hdw; - hdw->i2c_pend_mask = 0; - hdw->i2c_stale_mask = 0; - hdw->i2c_active_mask = 0; - INIT_LIST_HEAD(&hdw->i2c_clients); - mutex_init(&hdw->i2c_list_lock); hdw->i2c_linked = !0; i2c_add_adapter(&hdw->i2c_adap); if (hdw->i2c_func[0x18] == i2c_24xxx_ir) { diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-core.h b/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-core.h index 6ef7a1c0e..6a7576920 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-core.h +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-core.h @@ -20,68 +20,13 @@ #ifndef __PVRUSB2_I2C_CORE_H #define __PVRUSB2_I2C_CORE_H -#include -#include - struct pvr2_hdw; -struct pvr2_i2c_client; -struct pvr2_i2c_handler; -struct pvr2_i2c_handler_functions; -struct pvr2_i2c_op; -struct pvr2_i2c_op_functions; - -struct pvr2_i2c_client { - struct i2c_client *client; - struct pvr2_i2c_handler *handler; - struct list_head list; - struct pvr2_hdw *hdw; - int detected_flag; - int recv_enable; - unsigned long pend_mask; - unsigned long ctl_mask; - void (*status_poll)(struct pvr2_i2c_client *); -}; - -struct pvr2_i2c_handler { - void *func_data; - const struct pvr2_i2c_handler_functions *func_table; -}; - -struct pvr2_i2c_handler_functions { - void (*detach)(void *); - int (*check)(void *); - void (*update)(void *); - unsigned int (*describe)(void *,char *,unsigned int); -}; - -struct pvr2_i2c_op { - int (*check)(struct pvr2_hdw *); - void (*update)(struct pvr2_hdw *); - const char *name; -}; void pvr2_i2c_core_init(struct pvr2_hdw *); void pvr2_i2c_core_done(struct pvr2_hdw *); -int pvr2_i2c_client_cmd(struct pvr2_i2c_client *,unsigned int cmd,void *arg); -int pvr2_i2c_core_cmd(struct pvr2_hdw *,unsigned int cmd,void *arg); - -int pvr2_i2c_core_check_stale(struct pvr2_hdw *); -void pvr2_i2c_core_sync(struct pvr2_hdw *); -void pvr2_i2c_core_status_poll(struct pvr2_hdw *); -unsigned int pvr2_i2c_report(struct pvr2_hdw *,char *buf,unsigned int maxlen); -#define PVR2_I2C_DETAIL_DEBUG 0x0001 -#define PVR2_I2C_DETAIL_HANDLER 0x0002 -#define PVR2_I2C_DETAIL_CTLMASK 0x0004 -#define PVR2_I2C_DETAIL_ALL (\ - PVR2_I2C_DETAIL_DEBUG |\ - PVR2_I2C_DETAIL_HANDLER |\ - PVR2_I2C_DETAIL_CTLMASK) - -void pvr2_i2c_probe(struct pvr2_hdw *,struct pvr2_i2c_client *); -const struct pvr2_i2c_op *pvr2_i2c_get_op(unsigned int idx); -#endif /* __PVRUSB2_I2C_CORE_H */ +#endif /* __PVRUSB2_I2C_ADAPTER_H */ /* diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-track.c b/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-track.c new file mode 100644 index 000000000..08c11c6a9 --- /dev/null +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-track.c @@ -0,0 +1,481 @@ +/* + * + * + * Copyright (C) 2005 Mike Isely + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include "pvrusb2-i2c-track.h" +#include "pvrusb2-hdw-internal.h" +#include "pvrusb2-debug.h" +#include "pvrusb2-fx2-cmd.h" +#include "pvrusb2.h" +#include "compat.h" + +#define trace_i2c(...) pvr2_trace(PVR2_TRACE_I2C,__VA_ARGS__) + +/* + + This module implements the foundation of a rather large architecture for + tracking state in all the various V4L I2C modules. This is obsolete with + kernels later than roughly 2.6.24, but it is still present in the + standalone pvrusb2 driver to allow continued operation with older + kernel. + +*/ + +static unsigned int pvr2_i2c_client_describe(struct pvr2_i2c_client *cp, + unsigned int detail, + char *buf,unsigned int maxlen); + +static int pvr2_i2c_core_singleton(struct i2c_client *cp, + unsigned int cmd,void *arg) +{ + int stat; + if (!cp) return -EINVAL; + if (!(cp->driver)) return -EINVAL; + if (!(cp->driver->command)) return -EINVAL; + if (!try_module_get(cp->driver->driver.owner)) return -EAGAIN; + stat = cp->driver->command(cp,cmd,arg); + module_put(cp->driver->driver.owner); + return stat; +} + +int pvr2_i2c_client_cmd(struct pvr2_i2c_client *cp,unsigned int cmd,void *arg) +{ + int stat; + if (pvrusb2_debug & PVR2_TRACE_I2C_CMD) { + char buf[100]; + unsigned int cnt; + cnt = pvr2_i2c_client_describe(cp,PVR2_I2C_DETAIL_DEBUG, + buf,sizeof(buf)); + pvr2_trace(PVR2_TRACE_I2C_CMD, + "i2c COMMAND (code=%u 0x%x) to %.*s", + cmd,cmd,cnt,buf); + } + stat = pvr2_i2c_core_singleton(cp->client,cmd,arg); + if (pvrusb2_debug & PVR2_TRACE_I2C_CMD) { + char buf[100]; + unsigned int cnt; + cnt = pvr2_i2c_client_describe(cp,PVR2_I2C_DETAIL_DEBUG, + buf,sizeof(buf)); + pvr2_trace(PVR2_TRACE_I2C_CMD, + "i2c COMMAND to %.*s (ret=%d)",cnt,buf,stat); + } + return stat; +} + +int pvr2_i2c_core_cmd(struct pvr2_hdw *hdw,unsigned int cmd,void *arg) +{ + struct pvr2_i2c_client *cp, *ncp; + int stat = -EINVAL; + + if (!hdw) return stat; + + mutex_lock(&hdw->i2c_list_lock); + list_for_each_entry_safe(cp, ncp, &hdw->i2c_clients, list) { + if (!cp->recv_enable) continue; + mutex_unlock(&hdw->i2c_list_lock); + stat = pvr2_i2c_client_cmd(cp,cmd,arg); + mutex_lock(&hdw->i2c_list_lock); + } + mutex_unlock(&hdw->i2c_list_lock); + return stat; +} + + +static int handler_check(struct pvr2_i2c_client *cp) +{ + struct pvr2_i2c_handler *hp = cp->handler; + if (!hp) return 0; + if (!hp->func_table->check) return 0; + return hp->func_table->check(hp->func_data) != 0; +} + +#define BUFSIZE 500 + + +void pvr2_i2c_core_status_poll(struct pvr2_hdw *hdw) +{ + struct pvr2_i2c_client *cp; + mutex_lock(&hdw->i2c_list_lock); do { + struct v4l2_tuner *vtp = &hdw->tuner_signal_info; + memset(vtp,0,sizeof(*vtp)); + list_for_each_entry(cp, &hdw->i2c_clients, list) { + if (!cp->detected_flag) continue; + if (!cp->status_poll) continue; + cp->status_poll(cp); + } + hdw->tuner_signal_stale = 0; + pvr2_trace(PVR2_TRACE_CHIPS,"i2c status poll" + " type=%u strength=%u audio=0x%x cap=0x%x" + " low=%u hi=%u", + vtp->type, + vtp->signal,vtp->rxsubchans,vtp->capability, + vtp->rangelow,vtp->rangehigh); + } while (0); mutex_unlock(&hdw->i2c_list_lock); +} + + +/* Issue various I2C operations to bring chip-level drivers into sync with + state stored in this driver. */ +void pvr2_i2c_core_sync(struct pvr2_hdw *hdw) +{ + unsigned long msk; + unsigned int idx; + struct pvr2_i2c_client *cp, *ncp; + + if (!hdw->i2c_linked) return; + if (!(hdw->i2c_pend_types & PVR2_I2C_PEND_ALL)) { + return; + } + mutex_lock(&hdw->i2c_list_lock); do { + pvr2_trace(PVR2_TRACE_I2C_CORE,"i2c: core_sync BEGIN"); + if (hdw->i2c_pend_types & PVR2_I2C_PEND_DETECT) { + /* One or more I2C clients have attached since we + last synced. So scan the list and identify the + new clients. */ + char *buf; + unsigned int cnt; + unsigned long amask = 0; + buf = kmalloc(BUFSIZE,GFP_KERNEL); + pvr2_trace(PVR2_TRACE_I2C_CORE,"i2c: PEND_DETECT"); + hdw->i2c_pend_types &= ~PVR2_I2C_PEND_DETECT; + list_for_each_entry(cp, &hdw->i2c_clients, list) { + if (!cp->detected_flag) { + cp->ctl_mask = 0; + pvr2_i2c_probe(hdw,cp); + cp->detected_flag = !0; + msk = cp->ctl_mask; + cnt = 0; + if (buf) { + cnt = pvr2_i2c_client_describe( + cp, + PVR2_I2C_DETAIL_ALL, + buf,BUFSIZE); + } + trace_i2c("Probed: %.*s",cnt,buf); + if (handler_check(cp)) { + hdw->i2c_pend_types |= + PVR2_I2C_PEND_CLIENT; + } + cp->pend_mask = msk; + hdw->i2c_pend_mask |= msk; + hdw->i2c_pend_types |= + PVR2_I2C_PEND_REFRESH; + } + amask |= cp->ctl_mask; + } + hdw->i2c_active_mask = amask; + if (buf) kfree(buf); + } + if (hdw->i2c_pend_types & PVR2_I2C_PEND_STALE) { + /* Need to do one or more global updates. Arrange + for this to happen. */ + unsigned long m2; + pvr2_trace(PVR2_TRACE_I2C_CORE, + "i2c: PEND_STALE (0x%lx)", + hdw->i2c_stale_mask); + hdw->i2c_pend_types &= ~PVR2_I2C_PEND_STALE; + list_for_each_entry(cp, &hdw->i2c_clients, list) { + m2 = hdw->i2c_stale_mask; + m2 &= cp->ctl_mask; + m2 &= ~cp->pend_mask; + if (m2) { + pvr2_trace(PVR2_TRACE_I2C_CORE, + "i2c: cp=%p setting 0x%lx", + cp,m2); + cp->pend_mask |= m2; + } + } + hdw->i2c_pend_mask |= hdw->i2c_stale_mask; + hdw->i2c_stale_mask = 0; + hdw->i2c_pend_types |= PVR2_I2C_PEND_REFRESH; + } + if (hdw->i2c_pend_types & PVR2_I2C_PEND_CLIENT) { + /* One or more client handlers are asking for an + update. Run through the list of known clients + and update each one. */ + pvr2_trace(PVR2_TRACE_I2C_CORE,"i2c: PEND_CLIENT"); + hdw->i2c_pend_types &= ~PVR2_I2C_PEND_CLIENT; + list_for_each_entry_safe(cp, ncp, &hdw->i2c_clients, + list) { + if (!cp->handler) continue; + if (!cp->handler->func_table->update) continue; + pvr2_trace(PVR2_TRACE_I2C_CORE, + "i2c: cp=%p update",cp); + mutex_unlock(&hdw->i2c_list_lock); + cp->handler->func_table->update( + cp->handler->func_data); + mutex_lock(&hdw->i2c_list_lock); + /* If client's update function set some + additional pending bits, account for that + here. */ + if (cp->pend_mask & ~hdw->i2c_pend_mask) { + hdw->i2c_pend_mask |= cp->pend_mask; + hdw->i2c_pend_types |= + PVR2_I2C_PEND_REFRESH; + } + } + } + if (hdw->i2c_pend_types & PVR2_I2C_PEND_REFRESH) { + const struct pvr2_i2c_op *opf; + unsigned long pm; + /* Some actual updates are pending. Walk through + each update type and perform it. */ + pvr2_trace(PVR2_TRACE_I2C_CORE,"i2c: PEND_REFRESH" + " (0x%lx)",hdw->i2c_pend_mask); + hdw->i2c_pend_types &= ~PVR2_I2C_PEND_REFRESH; + pm = hdw->i2c_pend_mask; + hdw->i2c_pend_mask = 0; + for (idx = 0, msk = 1; pm; idx++, msk <<= 1) { + if (!(pm & msk)) continue; + pm &= ~msk; + list_for_each_entry(cp, &hdw->i2c_clients, + list) { + if (cp->pend_mask & msk) { + cp->pend_mask &= ~msk; + cp->recv_enable = !0; + } else { + cp->recv_enable = 0; + } + } + opf = pvr2_i2c_get_op(idx); + if (!opf) continue; + mutex_unlock(&hdw->i2c_list_lock); + opf->update(hdw); + mutex_lock(&hdw->i2c_list_lock); + } + } + pvr2_trace(PVR2_TRACE_I2C_CORE,"i2c: core_sync END"); + } while (0); mutex_unlock(&hdw->i2c_list_lock); +} + +int pvr2_i2c_core_check_stale(struct pvr2_hdw *hdw) +{ + unsigned long msk,sm,pm; + unsigned int idx; + const struct pvr2_i2c_op *opf; + struct pvr2_i2c_client *cp; + unsigned int pt = 0; + + pvr2_trace(PVR2_TRACE_I2C_CORE,"pvr2_i2c_core_check_stale BEGIN"); + + pm = hdw->i2c_active_mask; + sm = 0; + for (idx = 0, msk = 1; pm; idx++, msk <<= 1) { + if (!(msk & pm)) continue; + pm &= ~msk; + opf = pvr2_i2c_get_op(idx); + if (!(opf && opf->check)) continue; + if (opf->check(hdw)) { + sm |= msk; + } + } + if (sm) pt |= PVR2_I2C_PEND_STALE; + + list_for_each_entry(cp, &hdw->i2c_clients, list) + if (handler_check(cp)) + pt |= PVR2_I2C_PEND_CLIENT; + + if (pt) { + mutex_lock(&hdw->i2c_list_lock); do { + hdw->i2c_pend_types |= pt; + hdw->i2c_stale_mask |= sm; + hdw->i2c_pend_mask |= hdw->i2c_stale_mask; + } while (0); mutex_unlock(&hdw->i2c_list_lock); + } + + pvr2_trace(PVR2_TRACE_I2C_CORE, + "i2c: types=0x%x stale=0x%lx pend=0x%lx", + hdw->i2c_pend_types, + hdw->i2c_stale_mask, + hdw->i2c_pend_mask); + pvr2_trace(PVR2_TRACE_I2C_CORE,"pvr2_i2c_core_check_stale END"); + + return (hdw->i2c_pend_types & PVR2_I2C_PEND_ALL) != 0; +} + +static unsigned int pvr2_i2c_client_describe(struct pvr2_i2c_client *cp, + unsigned int detail, + char *buf,unsigned int maxlen) +{ + unsigned int ccnt,bcnt; + int spcfl = 0; + const struct pvr2_i2c_op *opf; + + ccnt = 0; + if (detail & PVR2_I2C_DETAIL_DEBUG) { + bcnt = scnprintf(buf,maxlen, + "ctxt=%p ctl_mask=0x%lx", + cp,cp->ctl_mask); + ccnt += bcnt; buf += bcnt; maxlen -= bcnt; + spcfl = !0; + } + bcnt = scnprintf(buf,maxlen, + "%s%s @ 0x%x", + (spcfl ? " " : ""), + cp->client->name, + cp->client->addr); + ccnt += bcnt; buf += bcnt; maxlen -= bcnt; + if ((detail & PVR2_I2C_DETAIL_HANDLER) && + cp->handler && cp->handler->func_table->describe) { + bcnt = scnprintf(buf,maxlen," ("); + ccnt += bcnt; buf += bcnt; maxlen -= bcnt; + bcnt = cp->handler->func_table->describe( + cp->handler->func_data,buf,maxlen); + ccnt += bcnt; buf += bcnt; maxlen -= bcnt; + bcnt = scnprintf(buf,maxlen,")"); + ccnt += bcnt; buf += bcnt; maxlen -= bcnt; + } + if ((detail & PVR2_I2C_DETAIL_CTLMASK) && cp->ctl_mask) { + unsigned int idx; + unsigned long msk,sm; + + bcnt = scnprintf(buf,maxlen," ["); + ccnt += bcnt; buf += bcnt; maxlen -= bcnt; + sm = 0; + spcfl = 0; + for (idx = 0, msk = 1; msk; idx++, msk <<= 1) { + if (!(cp->ctl_mask & msk)) continue; + opf = pvr2_i2c_get_op(idx); + if (opf) { + bcnt = scnprintf(buf,maxlen,"%s%s", + spcfl ? " " : "", + opf->name); + ccnt += bcnt; buf += bcnt; maxlen -= bcnt; + spcfl = !0; + } else { + sm |= msk; + } + } + if (sm) { + bcnt = scnprintf(buf,maxlen,"%s%lx", + idx != 0 ? " " : "",sm); + ccnt += bcnt; buf += bcnt; maxlen -= bcnt; + } + bcnt = scnprintf(buf,maxlen,"]"); + ccnt += bcnt; buf += bcnt; maxlen -= bcnt; + } + return ccnt; +} + +unsigned int pvr2_i2c_report(struct pvr2_hdw *hdw, + char *buf,unsigned int maxlen) +{ + unsigned int ccnt,bcnt; + struct pvr2_i2c_client *cp; + ccnt = 0; + mutex_lock(&hdw->i2c_list_lock); do { + list_for_each_entry(cp, &hdw->i2c_clients, list) { + bcnt = pvr2_i2c_client_describe( + cp, + (PVR2_I2C_DETAIL_HANDLER| + PVR2_I2C_DETAIL_CTLMASK), + buf,maxlen); + ccnt += bcnt; buf += bcnt; maxlen -= bcnt; + bcnt = scnprintf(buf,maxlen,"\n"); + ccnt += bcnt; buf += bcnt; maxlen -= bcnt; + } + } while (0); mutex_unlock(&hdw->i2c_list_lock); + return ccnt; +} + +void pvr2_i2c_track_attach_inform(struct i2c_client *client) +{ + struct pvr2_hdw *hdw = (struct pvr2_hdw *)(client->adapter->algo_data); + struct pvr2_i2c_client *cp; + int fl = !(hdw->i2c_pend_types & PVR2_I2C_PEND_ALL); + cp = kzalloc(sizeof(*cp),GFP_KERNEL); + trace_i2c("i2c_attach [client=%s @ 0x%x ctxt=%p]", + client->name, + client->addr,cp); + if (!cp) { + pvr2_trace(PVR2_TRACE_ERROR_LEGS, + "Unable to allocate tracking memory for incoming" + " i2c module; ignoring module. This is likely" + " going to be a problem."); + return; + } + cp->hdw = hdw; + INIT_LIST_HEAD(&cp->list); + cp->client = client; + mutex_lock(&hdw->i2c_list_lock); do { + hdw->cropcap_stale = !0; + list_add_tail(&cp->list,&hdw->i2c_clients); + hdw->i2c_pend_types |= PVR2_I2C_PEND_DETECT; + } while (0); mutex_unlock(&hdw->i2c_list_lock); + if (fl) queue_work(hdw->workqueue,&hdw->worki2csync); +} + +void pvr2_i2c_track_detach_inform(struct i2c_client *client) +{ + struct pvr2_hdw *hdw = (struct pvr2_hdw *)(client->adapter->algo_data); + struct pvr2_i2c_client *cp, *ncp; + unsigned long amask = 0; + int foundfl = 0; + mutex_lock(&hdw->i2c_list_lock); do { + hdw->cropcap_stale = !0; + list_for_each_entry_safe(cp, ncp, &hdw->i2c_clients, list) { + if (cp->client == client) { + trace_i2c("pvr2_i2c_detach" + " [client=%s @ 0x%x ctxt=%p]", + client->name, + client->addr,cp); + if (cp->handler && + cp->handler->func_table->detach) { + cp->handler->func_table->detach( + cp->handler->func_data); + } + list_del(&cp->list); + kfree(cp); + foundfl = !0; + continue; + } + amask |= cp->ctl_mask; + } + hdw->i2c_active_mask = amask; + } while (0); mutex_unlock(&hdw->i2c_list_lock); + if (!foundfl) { + trace_i2c("pvr2_i2c_detach [client=%s @ 0x%x ctxt=]", + client->name, + client->addr); + } +} + +void pvr2_i2c_track_init(struct pvr2_hdw *hdw) +{ + hdw->i2c_pend_mask = 0; + hdw->i2c_stale_mask = 0; + hdw->i2c_active_mask = 0; + INIT_LIST_HEAD(&hdw->i2c_clients); + mutex_init(&hdw->i2c_list_lock); +} + +void pvr2_i2c_track_done(struct pvr2_hdw *hdw) +{ + /* Empty for now */ +} + +/* + Stuff for Emacs to see, in order to encourage consistent editing style: + *** Local Variables: *** + *** mode: c *** + *** fill-column: 75 *** + *** tab-width: 8 *** + *** c-basic-offset: 8 *** + *** End: *** + */ diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-track.h b/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-track.h new file mode 100644 index 000000000..7d0e4fb63 --- /dev/null +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-track.h @@ -0,0 +1,97 @@ +/* + * + * + * Copyright (C) 2005 Mike Isely + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +#ifndef __PVRUSB2_I2C_TRACK_H +#define __PVRUSB2_I2C_TRACK_H + +#include +#include + +struct pvr2_hdw; +struct pvr2_i2c_client; +struct pvr2_i2c_handler; +struct pvr2_i2c_handler_functions; +struct pvr2_i2c_op; +struct pvr2_i2c_op_functions; + +struct pvr2_i2c_client { + struct i2c_client *client; + struct pvr2_i2c_handler *handler; + struct list_head list; + struct pvr2_hdw *hdw; + int detected_flag; + int recv_enable; + unsigned long pend_mask; + unsigned long ctl_mask; + void (*status_poll)(struct pvr2_i2c_client *); +}; + +struct pvr2_i2c_handler { + void *func_data; + const struct pvr2_i2c_handler_functions *func_table; +}; + +struct pvr2_i2c_handler_functions { + void (*detach)(void *); + int (*check)(void *); + void (*update)(void *); + unsigned int (*describe)(void *,char *,unsigned int); +}; + +struct pvr2_i2c_op { + int (*check)(struct pvr2_hdw *); + void (*update)(struct pvr2_hdw *); + const char *name; +}; + +void pvr2_i2c_track_init(struct pvr2_hdw *); +void pvr2_i2c_track_done(struct pvr2_hdw *); +void pvr2_i2c_track_attach_inform(struct i2c_client *); +void pvr2_i2c_track_detach_inform(struct i2c_client *); + +int pvr2_i2c_client_cmd(struct pvr2_i2c_client *,unsigned int cmd,void *arg); +int pvr2_i2c_core_cmd(struct pvr2_hdw *,unsigned int cmd,void *arg); + +int pvr2_i2c_core_check_stale(struct pvr2_hdw *); +void pvr2_i2c_core_sync(struct pvr2_hdw *); +void pvr2_i2c_core_status_poll(struct pvr2_hdw *); +unsigned int pvr2_i2c_report(struct pvr2_hdw *,char *buf,unsigned int maxlen); +#define PVR2_I2C_DETAIL_DEBUG 0x0001 +#define PVR2_I2C_DETAIL_HANDLER 0x0002 +#define PVR2_I2C_DETAIL_CTLMASK 0x0004 +#define PVR2_I2C_DETAIL_ALL (\ + PVR2_I2C_DETAIL_DEBUG |\ + PVR2_I2C_DETAIL_HANDLER |\ + PVR2_I2C_DETAIL_CTLMASK) + +void pvr2_i2c_probe(struct pvr2_hdw *,struct pvr2_i2c_client *); +const struct pvr2_i2c_op *pvr2_i2c_get_op(unsigned int idx); + +#endif /* __PVRUSB2_I2C_CORE_H */ + + +/* + Stuff for Emacs to see, in order to encourage consistent editing style: + *** Local Variables: *** + *** mode: c *** + *** fill-column: 75 *** + *** tab-width: 8 *** + *** c-basic-offset: 8 *** + *** End: *** + */ diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-tuner.h b/linux/drivers/media/video/pvrusb2/pvrusb2-tuner.h index ef4afaf37..3643e2c78 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-tuner.h +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-tuner.h @@ -20,7 +20,7 @@ #ifndef __PVRUSB2_TUNER_H #define __PVRUSB2_TUNER_H -#include "pvrusb2-i2c-core.h" +#include "pvrusb2-i2c-track.h" int pvr2_i2c_tuner_setup(struct pvr2_hdw *,struct pvr2_i2c_client *); diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-video-v4l.h b/linux/drivers/media/video/pvrusb2/pvrusb2-video-v4l.h index 4ff5b892b..b2cd3875b 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-video-v4l.h +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-video-v4l.h @@ -33,7 +33,7 @@ -#include "pvrusb2-i2c-core.h" +#include "pvrusb2-i2c-track.h" int pvr2_i2c_decoder_v4l_setup(struct pvr2_hdw *,struct pvr2_i2c_client *); diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-wm8775.h b/linux/drivers/media/video/pvrusb2/pvrusb2-wm8775.h index 807090961..5b2cb6183 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-wm8775.h +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-wm8775.h @@ -34,7 +34,7 @@ -#include "pvrusb2-i2c-core.h" +#include "pvrusb2-i2c-track.h" int pvr2_i2c_wm8775_setup(struct pvr2_hdw *,struct pvr2_i2c_client *); -- cgit v1.2.3 From 3472c5f6e471cbe81091eb4f014a9991365270c5 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Fri, 6 Mar 2009 20:20:31 -0600 Subject: pvrusb2: Set up v4l2_device instance From: Mike Isely Define a v4l2_device instance in the pvrusb2 driver and initialize / tear it down appropriately. This is a step in the v4l2-subdev adoption effort. Priority: normal Signed-off-by: Mike Isely --- .../drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h | 3 +++ linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c | 18 +++++++++++++++++- 2 files changed, 20 insertions(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h index d96f0f510..09798403e 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h @@ -38,6 +38,7 @@ #include #include "pvrusb2-hdw.h" #include "pvrusb2-io.h" +#include #include #include "pvrusb2-devattr.h" @@ -179,6 +180,8 @@ struct pvr2_hdw { struct usb_device *usb_dev; struct usb_interface *usb_intf; + /* Our handle into the v4l2 sub-device architecture */ + struct v4l2_device v4l2_dev; /* Device description, anything that must adjust behavior based on device specific info will use information held here. */ const struct pvr2_device_desc *hdw_desc; diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c index e6306dd8e..008de843d 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -2209,11 +2209,14 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf, struct pvr2_hdw *hdw = NULL; int valid_std_mask; struct pvr2_ctrl *cptr; + struct usb_device *usb_dev; const struct pvr2_device_desc *hdw_desc; __u8 ifnum; struct v4l2_queryctrl qctrl; struct pvr2_ctl_info *ciptr; + usb_dev = interface_to_usbdev(intf); + hdw_desc = (const struct pvr2_device_desc *)(devid->driver_info); if (hdw_desc == NULL) { @@ -2398,6 +2401,11 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf, hdw->ctl_read_urb = usb_alloc_urb(0,GFP_KERNEL); if (!hdw->ctl_read_urb) goto fail; + if (v4l2_device_register(&usb_dev->dev, &hdw->v4l2_dev) != 0) { + pvr2_trace(PVR2_TRACE_ERROR_LEGS, + "Error registering with v4l core, giving up"); + goto fail; + } mutex_lock(&pvr2_unit_mtx); do { for (idx = 0; idx < PVR_NUM; idx++) { if (unit_pointers[idx]) continue; @@ -2436,7 +2444,7 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf, hdw->flag_ok = !0; hdw->usb_intf = intf; - hdw->usb_dev = interface_to_usbdev(intf); + hdw->usb_dev = usb_dev; usb_make_path(hdw->usb_dev, hdw->bus_info, sizeof(hdw->bus_info)); @@ -2496,6 +2504,13 @@ static void pvr2_hdw_remove_usb_stuff(struct pvr2_hdw *hdw) hdw->ctl_write_buffer = NULL; } hdw->flag_disconnected = !0; + /* If we don't do this, then there will be a dangling struct device + reference to our disappearing device persisting inside the V4L + core... */ + if (hdw->v4l2_dev.dev) { + dev_set_drvdata(hdw->v4l2_dev.dev, NULL); + hdw->v4l2_dev.dev = NULL; + } hdw->usb_dev = NULL; hdw->usb_intf = NULL; pvr2_hdw_render_useless(hdw); @@ -2528,6 +2543,7 @@ void pvr2_hdw_destroy(struct pvr2_hdw *hdw) } pvr2_i2c_core_done(hdw); pvr2_i2c_track_done(hdw); + v4l2_device_unregister(&hdw->v4l2_dev); pvr2_hdw_remove_usb_stuff(hdw); mutex_lock(&pvr2_unit_mtx); do { if ((hdw->unit_number >= 0) && -- cgit v1.2.3 From 888de8a79f8c6289a00826435686ed77a2e6faf5 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Fri, 6 Mar 2009 20:30:37 -0600 Subject: pvrusb2: Changes to further isolate old i2c layer From: Mike Isely This introduces some additional isolation in the pvrusb2 from the old i2c layer, a step along the way to separate the driver from that layer and to make it easier to introduce the common v4l2-subdev framework as the eventual replacement. Priority: normal Signed-off-by: Mike Isely --- .../media/video/pvrusb2/pvrusb2-hdw-internal.h | 2 ++ linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c | 22 ++++++++++++++-------- .../media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.c | 4 +++- 3 files changed, 19 insertions(+), 9 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h index 09798403e..b3cb0bbd8 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h @@ -408,6 +408,8 @@ struct pvr2_hdw { unsigned long pvr2_hdw_get_cur_freq(struct pvr2_hdw *); void pvr2_hdw_set_decoder(struct pvr2_hdw *,struct pvr2_decoder_ctrl *); +void pvr2_hdw_status_poll(struct pvr2_hdw *); + #endif /* __PVRUSB2_HDW_INTERNAL_H */ /* diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c index 008de843d..f56783a30 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -644,7 +644,7 @@ static int ctrl_freq_max_get(struct pvr2_ctrl *cptr, int *vp) unsigned long fv; struct pvr2_hdw *hdw = cptr->hdw; if (hdw->tuner_signal_stale) { - pvr2_i2c_core_status_poll(hdw); + pvr2_hdw_status_poll(hdw); } fv = hdw->tuner_signal_info.rangehigh; if (!fv) { @@ -666,7 +666,7 @@ static int ctrl_freq_min_get(struct pvr2_ctrl *cptr, int *vp) unsigned long fv; struct pvr2_hdw *hdw = cptr->hdw; if (hdw->tuner_signal_stale) { - pvr2_i2c_core_status_poll(hdw); + pvr2_hdw_status_poll(hdw); } fv = hdw->tuner_signal_info.rangelow; if (!fv) { @@ -860,7 +860,7 @@ static void ctrl_stdcur_clear_dirty(struct pvr2_ctrl *cptr) static int ctrl_signal_get(struct pvr2_ctrl *cptr,int *vp) { struct pvr2_hdw *hdw = cptr->hdw; - pvr2_i2c_core_status_poll(hdw); + pvr2_hdw_status_poll(hdw); *vp = hdw->tuner_signal_info.signal; return 0; } @@ -870,7 +870,7 @@ static int ctrl_audio_modes_present_get(struct pvr2_ctrl *cptr,int *vp) int val = 0; unsigned int subchan; struct pvr2_hdw *hdw = cptr->hdw; - pvr2_i2c_core_status_poll(hdw); + pvr2_hdw_status_poll(hdw); subchan = hdw->tuner_signal_info.rxsubchans; if (subchan & V4L2_TUNER_SUB_MONO) { val |= (1 << V4L2_TUNER_MODE_MONO); @@ -3032,7 +3032,7 @@ int pvr2_hdw_is_hsm(struct pvr2_hdw *hdw) void pvr2_hdw_execute_tuner_poll(struct pvr2_hdw *hdw) { LOCK_TAKE(hdw->big_lock); do { - pvr2_i2c_core_status_poll(hdw); + pvr2_hdw_status_poll(hdw); } while (0); LOCK_GIVE(hdw->big_lock); } @@ -3042,7 +3042,7 @@ static int pvr2_hdw_check_cropcap(struct pvr2_hdw *hdw) if (!hdw->cropcap_stale) { return 0; } - pvr2_i2c_core_status_poll(hdw); + pvr2_hdw_status_poll(hdw); if (hdw->cropcap_stale) { return -EIO; } @@ -3069,7 +3069,7 @@ int pvr2_hdw_get_tuner_status(struct pvr2_hdw *hdw,struct v4l2_tuner *vtp) { LOCK_TAKE(hdw->big_lock); do { if (hdw->tuner_signal_stale) { - pvr2_i2c_core_status_poll(hdw); + pvr2_hdw_status_poll(hdw); } memcpy(vtp,&hdw->tuner_signal_info,sizeof(struct v4l2_tuner)); } while (0); LOCK_GIVE(hdw->big_lock); @@ -3091,8 +3091,8 @@ void pvr2_hdw_trigger_module_log(struct pvr2_hdw *hdw) hdw->log_requested = !0; printk(KERN_INFO "pvrusb2: ================= START STATUS CARD #%d =================\n", nr); pvr2_i2c_core_check_stale(hdw); - hdw->log_requested = 0; pvr2_i2c_core_sync(hdw); + hdw->log_requested = 0; pvr2_trace(PVR2_TRACE_INFO,"cx2341x config:"); cx2341x_log_status(&hdw->enc_ctl_state, "pvrusb2"); pvr2_hdw_state_log_state(hdw); @@ -4815,6 +4815,12 @@ int pvr2_hdw_gpio_chg_out(struct pvr2_hdw *hdw,u32 msk,u32 val) } +void pvr2_hdw_status_poll(struct pvr2_hdw *hdw) +{ + pvr2_i2c_core_status_poll(hdw); +} + + unsigned int pvr2_hdw_get_input_available(struct pvr2_hdw *hdw) { return hdw->input_avail_mask; diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.c b/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.c index db61c1fb0..a477e1ebd 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.c @@ -26,6 +26,7 @@ #include #include "compat.h" + static void execute_init(struct pvr2_hdw *hdw) { u32 dummy = 0; @@ -185,7 +186,7 @@ static void set_frequency(struct pvr2_hdw *hdw) fv = pvr2_hdw_get_cur_freq(hdw); pvr2_trace(PVR2_TRACE_CHIPS,"i2c v4l2 set_freq(%lu)",fv); if (hdw->tuner_signal_stale) { - pvr2_i2c_core_status_poll(hdw); + pvr2_hdw_status_poll(hdw); } memset(&freq,0,sizeof(freq)); if (hdw->tuner_signal_info.capability & V4L2_TUNER_CAP_LOW) { @@ -326,6 +327,7 @@ void pvr2_v4l2_cmd_status_poll(struct pvr2_i2c_client *cp) } + /* Stuff for Emacs to see, in order to encourage consistent editing style: *** Local Variables: *** -- cgit v1.2.3 From 17e0d776259f0c81372dd813e9146b3c66377133 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Fri, 6 Mar 2009 20:32:02 -0600 Subject: pvrusb2: whitespace trivial tweaks From: Mike Isely Priority: normal Signed-off-by: Mike Isely --- linux/drivers/media/video/pvrusb2/pvrusb2-audio.c | 2 ++ linux/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c | 1 + linux/drivers/media/video/pvrusb2/pvrusb2-i2c-chips-v4l2.c | 2 ++ linux/drivers/media/video/pvrusb2/pvrusb2-i2c-track.c | 2 ++ linux/drivers/media/video/pvrusb2/pvrusb2-tuner.c | 1 + 5 files changed, 8 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-audio.c b/linux/drivers/media/video/pvrusb2/pvrusb2-audio.c index 65babb878..f2fb5cf5b 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-audio.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-audio.c @@ -36,6 +36,7 @@ struct pvr2_msp3400_handler { + struct routing_scheme { const int *def; unsigned int cnt; @@ -181,6 +182,7 @@ int pvr2_i2c_msp3400_setup(struct pvr2_hdw *hdw,struct pvr2_i2c_client *cp) } + /* Stuff for Emacs to see, in order to encourage consistent editing style: *** Local Variables: *** diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c b/linux/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c index 2f051f797..750c379df 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c @@ -324,6 +324,7 @@ int pvr2_i2c_cx2584x_v4l_setup(struct pvr2_hdw *hdw, + /* Stuff for Emacs to see, in order to encourage consistent editing style: *** Local Variables: *** diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-chips-v4l2.c b/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-chips-v4l2.c index d8674ce36..0f8fd830c 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-chips-v4l2.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-chips-v4l2.c @@ -30,6 +30,7 @@ #include "pvrusb2-wm8775.h" #include "compat.h" + #define trace_i2c(...) pvr2_trace(PVR2_TRACE_I2C,__VA_ARGS__) #define OP_INIT 0 /* MUST come first so it is run first */ @@ -106,6 +107,7 @@ const struct pvr2_i2c_op *pvr2_i2c_get_op(unsigned int idx) } + /* Stuff for Emacs to see, in order to encourage consistent editing style: *** Local Variables: *** diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-track.c b/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-track.c index 08c11c6a9..ae18a344e 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-track.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-track.c @@ -27,6 +27,7 @@ #define trace_i2c(...) pvr2_trace(PVR2_TRACE_I2C,__VA_ARGS__) + /* This module implements the foundation of a rather large architecture for @@ -470,6 +471,7 @@ void pvr2_i2c_track_done(struct pvr2_hdw *hdw) /* Empty for now */ } + /* Stuff for Emacs to see, in order to encourage consistent editing style: *** Local Variables: *** diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-tuner.c b/linux/drivers/media/video/pvrusb2/pvrusb2-tuner.c index efec78516..2aeedbc75 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-tuner.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-tuner.c @@ -29,6 +29,7 @@ #include #include + struct pvr2_tuner_handler { struct pvr2_hdw *hdw; struct pvr2_i2c_client *client; -- cgit v1.2.3 From 2d7288563e5661e8b6cad4bc41ddc175b92fae9e Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Fri, 6 Mar 2009 20:42:20 -0600 Subject: pvrusb2: New device attribute mechanism to specify sub-devices From: Mike Isely Set up new mechanism for declaring and loading appropriate sub-devices when driver initializes. This is another part of the v4l2-subdev adoption. Priority: normal Signed-off-by: Mike Isely --- .../drivers/media/video/pvrusb2/pvrusb2-devattr.h | 28 +++++ linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c | 119 ++++++++++++++++++++- .../drivers/media/video/pvrusb2/pvrusb2-i2c-core.c | 1 + 3 files changed, 144 insertions(+), 4 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-devattr.h b/linux/drivers/media/video/pvrusb2/pvrusb2-devattr.h index cb3a33eb0..f06923986 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-devattr.h +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-devattr.h @@ -33,6 +33,31 @@ */ +#define PVR2_CLIENT_ID_MSP3400 1 +#define PVR2_CLIENT_ID_CX25840 2 +#define PVR2_CLIENT_ID_SAA7115 3 +#define PVR2_CLIENT_ID_TUNER 4 +#define PVR2_CLIENT_ID_CS53132A 5 + +struct pvr2_device_client_desc { + /* One ovr PVR2_CLIENT_ID_xxxx */ + unsigned char module_id; + + /* Null-terminated array of I2C addresses to try in order + initialize the module. It's safe to make this null terminated + since we're never going to encounter an i2c device with an + address of zero. If this is a null pointer or zero-length, + then no I2C addresses have been specified, in which case we'll + try some compiled in defaults for now. */ + unsigned char *i2c_address_list; +}; + +struct pvr2_device_client_table { + const struct pvr2_device_client_desc *lst; + unsigned char cnt; +}; + + struct pvr2_string_table { const char **lst; unsigned int cnt; @@ -66,6 +91,9 @@ struct pvr2_device_desc { /* List of additional client modules we need to load */ struct pvr2_string_table client_modules; + /* List of defined client modules we need to load */ + struct pvr2_device_client_table client_table; + /* List of FX2 firmware file names we should search; if empty then FX2 firmware check / load is skipped and we assume the device was initialized from internal ROM. */ diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c index f56783a30..e6131e636 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -106,6 +106,20 @@ MODULE_PARM_DESC(radio_freq, "specify initial radio frequency"); /* size of a firmware chunk */ #define FIRMWARE_CHUNK_SIZE 0x2000 +static const char *module_names[] = { + [PVR2_CLIENT_ID_MSP3400] = "msp3400", + [PVR2_CLIENT_ID_CX25840] = "cx25840", + [PVR2_CLIENT_ID_SAA7115] = "saa7115", + [PVR2_CLIENT_ID_TUNER] = "tuner", + [PVR2_CLIENT_ID_CS53132A] = "cs53132a", +}; + + +static const unsigned char *module_i2c_addresses[] = { + [PVR2_CLIENT_ID_TUNER] = "\x60\x61\x62\x63", +}; + + /* Define the list of additional controls we'll dynamically construct based on query of the cx2341x module. */ struct pvr2_mpeg_ids { @@ -1951,6 +1965,105 @@ static void pvr2_hdw_setup_std(struct pvr2_hdw *hdw) } +static unsigned int pvr2_copy_i2c_addr_list( + unsigned short *dst, const unsigned char *src, + unsigned int dst_max) +{ + unsigned int cnt; + if (!src) return 0; + while (src[cnt] && (cnt + 1) < dst_max) { + dst[cnt] = src[cnt]; + cnt++; + } + dst[cnt] = I2C_CLIENT_END; + return cnt; +} + + +static void pvr2_hdw_load_subdev(struct pvr2_hdw *hdw, + const struct pvr2_device_client_desc *cd) +{ + const char *fname; + unsigned char mid; + struct v4l2_subdev *sd; + unsigned int i2ccnt; + const unsigned char *p; + /* Arbitrary count - max # i2c addresses we will probe */ + unsigned short i2caddr[25]; + + mid = cd->module_id; + fname = (mid < ARRAY_SIZE(module_names)) ? module_names[mid] : NULL; + if (!fname) { + pvr2_trace(PVR2_TRACE_ERROR_LEGS, + "Module ID %u for device %s is unknown" + " (this is probably a bad thing...)", + mid, + hdw->hdw_desc->description); + return; + } + + i2ccnt = pvr2_copy_i2c_addr_list(i2caddr, cd->i2c_address_list, + ARRAY_SIZE(i2caddr)); + if (!i2ccnt && ((p = (mid < ARRAY_SIZE(module_i2c_addresses)) ? + module_i2c_addresses[mid] : NULL) != NULL)) { + /* Second chance: Try default i2c address list */ + i2ccnt = pvr2_copy_i2c_addr_list(i2caddr, p, + ARRAY_SIZE(i2caddr)); + } + + if (!i2ccnt) { + pvr2_trace(PVR2_TRACE_ERROR_LEGS, + "Module ID %u for device %s:" + " No i2c addresses" + " (this is probably a bad thing...)", + mid, hdw->hdw_desc->description); + return; + } + + /* Note how the 2nd and 3rd arguments are the same for both + * v4l2_i2c_new_subdev() and v4l2_i2c_new_probed_subdev(). Why? + * Well the 2nd argument is the module name to load, while the 3rd + * argument is documented in the framework as being the "chipid" - + * and every other place where I can find examples of this, the + * "chipid" appears to just be the module name again. So here we + * just do the same thing. */ + if (i2ccnt == 1) { + sd = v4l2_i2c_new_subdev(&hdw->i2c_adap, + fname, fname, + i2caddr[0]); + } else { + sd = v4l2_i2c_new_probed_subdev(&hdw->i2c_adap, + fname, fname, + i2caddr); + } + + // ????? + /* Based on module ID, we should remember subdev pointers + so that we can send certain custom commands where + needed. */ + // ????? + +} + + +static void pvr2_hdw_load_modules(struct pvr2_hdw *hdw) +{ + unsigned int idx; + const struct pvr2_string_table *cm; + const struct pvr2_device_client_table *ct; + + cm = &hdw->hdw_desc->client_modules; + for (idx = 0; idx < cm->cnt; idx++) { + request_module(cm->lst[idx]); + } + + ct = &hdw->hdw_desc->client_table; + for (idx = 0; idx < ct->cnt; idx++) { + pvr2_hdw_load_subdev(hdw,&ct->lst[idx]); + } +} + + static void pvr2_hdw_setup_low(struct pvr2_hdw *hdw) { int ret; @@ -1990,10 +2103,6 @@ static void pvr2_hdw_setup_low(struct pvr2_hdw *hdw) if (!pvr2_hdw_dev_ok(hdw)) return; - for (idx = 0; idx < hdw->hdw_desc->client_modules.cnt; idx++) { - request_module(hdw->hdw_desc->client_modules.lst[idx]); - } - if (!hdw->hdw_desc->flag_no_powerup) { pvr2_hdw_cmd_powerup(hdw); if (!pvr2_hdw_dev_ok(hdw)) return; @@ -2012,6 +2121,8 @@ static void pvr2_hdw_setup_low(struct pvr2_hdw *hdw) pvr2_i2c_core_init(hdw); if (!pvr2_hdw_dev_ok(hdw)) return; + pvr2_hdw_load_modules(hdw); + for (idx = 0; idx < CTRLDEF_COUNT; idx++) { cptr = hdw->controls + idx; if (cptr->info->skip_init) continue; diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c b/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c index 1601921b9..5c959e467 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c @@ -686,6 +686,7 @@ void pvr2_i2c_core_init(struct pvr2_hdw *hdw) hdw->i2c_adap.algo = &hdw->i2c_algo; hdw->i2c_adap.algo_data = hdw; hdw->i2c_linked = !0; + i2c_set_adapdata(&hdw->i2c_adap, &hdw->v4l2_dev); i2c_add_adapter(&hdw->i2c_adap); if (hdw->i2c_func[0x18] == i2c_24xxx_ir) { /* Probe for a different type of IR receiver on this -- cgit v1.2.3 From fcad47474d494728c3e41e3ebbec7ef3da828e84 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Fri, 6 Mar 2009 20:47:10 -0600 Subject: pvrusb2: Providing means to stop tracking an old i2c module From: Mike Isely This implements a temporary mechanism to "untrack" an i2c module from the old i2c layer. The v4l2-subdev related code in the driver will use this to remove a sub-device from the old i2c layer. In the end, once the old i2c layer is removed, this will also eventually go away. Priority: normal Signed-off-by: Mike Isely --- linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c | 6 ++ .../media/video/pvrusb2/pvrusb2-i2c-track.c | 76 +++++++++++++++------- .../media/video/pvrusb2/pvrusb2-i2c-track.h | 5 ++ 3 files changed, 64 insertions(+), 23 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c index e6131e636..605e47368 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -2037,6 +2037,12 @@ static void pvr2_hdw_load_subdev(struct pvr2_hdw *hdw, i2caddr); } + /* If we have both old and new i2c layers enabled, make sure that + old layer isn't also tracking this module. This is a debugging + aid, in normal situations there's no reason for both mechanisms + to be enabled. */ + pvr2_i2c_untrack_subdev(hdw, sd); + // ????? /* Based on module ID, we should remember subdev pointers so that we can send certain custom commands where diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-track.c b/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-track.c index ae18a344e..fb738385d 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-track.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-track.c @@ -422,41 +422,71 @@ void pvr2_i2c_track_attach_inform(struct i2c_client *client) if (fl) queue_work(hdw->workqueue,&hdw->worki2csync); } +static void pvr2_i2c_client_disconnect(struct pvr2_i2c_client *cp) +{ + if (cp->handler && cp->handler->func_table->detach) { + cp->handler->func_table->detach(cp->handler->func_data); + } + list_del(&cp->list); + kfree(cp); +} + void pvr2_i2c_track_detach_inform(struct i2c_client *client) { struct pvr2_hdw *hdw = (struct pvr2_hdw *)(client->adapter->algo_data); struct pvr2_i2c_client *cp, *ncp; unsigned long amask = 0; int foundfl = 0; - mutex_lock(&hdw->i2c_list_lock); do { - hdw->cropcap_stale = !0; - list_for_each_entry_safe(cp, ncp, &hdw->i2c_clients, list) { - if (cp->client == client) { - trace_i2c("pvr2_i2c_detach" - " [client=%s @ 0x%x ctxt=%p]", - client->name, - client->addr,cp); - if (cp->handler && - cp->handler->func_table->detach) { - cp->handler->func_table->detach( - cp->handler->func_data); - } - list_del(&cp->list); - kfree(cp); - foundfl = !0; - continue; - } - amask |= cp->ctl_mask; + mutex_lock(&hdw->i2c_list_lock); + hdw->cropcap_stale = !0; + list_for_each_entry_safe(cp, ncp, &hdw->i2c_clients, list) { + if (cp->client == client) { + trace_i2c("pvr2_i2c_detach" + " [client=%s @ 0x%x ctxt=%p]", + client->name, + client->addr, cp); + pvr2_i2c_client_disconnect(cp); + foundfl = !0; + continue; } - hdw->i2c_active_mask = amask; - } while (0); mutex_unlock(&hdw->i2c_list_lock); + amask |= cp->ctl_mask; + } + hdw->i2c_active_mask = amask; + mutex_unlock(&hdw->i2c_list_lock); if (!foundfl) { trace_i2c("pvr2_i2c_detach [client=%s @ 0x%x ctxt=]", - client->name, - client->addr); + client->name, client->addr); } } +/* This function is used to remove an i2c client from our tracking + structure if the client happens to be the specified v4l2 sub-device. + The idea here is to ensure that sub-devices are not also tracked with + the old tracking mechanism - it's one or the other not both. This is + only for debugging. In a "real" environment, only one of these two + mechanisms should even be compiled in. But by enabling both we can + incrementally test control of each sub-device. */ +void pvr2_i2c_untrack_subdev(struct pvr2_hdw *hdw, struct v4l2_subdev *sd) +{ + struct i2c_client *client; + struct pvr2_i2c_client *cp, *ncp; + unsigned long amask = 0; + mutex_lock(&hdw->i2c_list_lock); + list_for_each_entry_safe(cp, ncp, &hdw->i2c_clients, list) { + client = cp->client; + if (i2c_get_clientdata(client) == sd) { + trace_i2c("pvr2_i2c_detach (subdev active)" + " [client=%s @ 0x%x ctxt=%p]", + client->name, client->addr, cp); + pvr2_i2c_client_disconnect(cp); + continue; + } + amask |= cp->ctl_mask; + } + hdw->i2c_active_mask = amask; + mutex_unlock(&hdw->i2c_list_lock); +} + void pvr2_i2c_track_init(struct pvr2_hdw *hdw) { hdw->i2c_pend_mask = 0; diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-track.h b/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-track.h index 7d0e4fb63..eba48e4c9 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-track.h +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-track.h @@ -22,6 +22,8 @@ #include #include +#include + struct pvr2_hdw; struct pvr2_i2c_client; @@ -83,6 +85,9 @@ unsigned int pvr2_i2c_report(struct pvr2_hdw *,char *buf,unsigned int maxlen); void pvr2_i2c_probe(struct pvr2_hdw *,struct pvr2_i2c_client *); const struct pvr2_i2c_op *pvr2_i2c_get_op(unsigned int idx); +void pvr2_i2c_untrack_subdev(struct pvr2_hdw *, struct v4l2_subdev *sd); + + #endif /* __PVRUSB2_I2C_CORE_H */ -- cgit v1.2.3 From 0e8baa62ef0d5a0ffe4b2372f670cd8308f6d7e9 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Fri, 6 Mar 2009 20:48:42 -0600 Subject: pvrusb2: whitespace tweaks From: Mike Isely Priority: normal Signed-off-by: Mike Isely --- linux/drivers/media/video/pvrusb2/pvrusb2-audio.c | 2 +- linux/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.h | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-audio.c b/linux/drivers/media/video/pvrusb2/pvrusb2-audio.c index f2fb5cf5b..a6e0896d9 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-audio.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-audio.c @@ -27,6 +27,7 @@ #include #include "compat.h" + struct pvr2_msp3400_handler { struct pvr2_hdw *hdw; struct pvr2_i2c_client *client; @@ -36,7 +37,6 @@ struct pvr2_msp3400_handler { - struct routing_scheme { const int *def; unsigned int cnt; diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.h b/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.h index 8472637e4..fa42497b4 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.h +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.h @@ -24,6 +24,7 @@ #include "pvrusb2-i2c-track.h" + extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_init; extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_standard; extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_radio; @@ -38,6 +39,7 @@ extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_log; void pvr2_v4l2_cmd_stream(struct pvr2_i2c_client *,int); void pvr2_v4l2_cmd_status_poll(struct pvr2_i2c_client *); + #endif /* __PVRUSB2_CMD_V4L2_H */ /* -- cgit v1.2.3 From 2fda0e83cd23f41e475d8170f9dfbc67a4ffa249 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Fri, 6 Mar 2009 20:51:35 -0600 Subject: pvrusb2: Set i2c autoprobing to be off by default From: Mike Isely In order to keep a sub-device from promiscuously attaching to the pvrusb2 driver, the i2c adapter's class must be cleared. This change clears that class by default. Priority: normal Signed-off-by: Mike Isely --- linux/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c | 3 ++- 1 file changed, 2 insertions(+), 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 5c959e467..c1f613591 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c @@ -618,7 +618,7 @@ static struct i2c_algorithm pvr2_i2c_algo_template = { static struct i2c_adapter pvr2_i2c_adap_template = { .owner = THIS_MODULE, - .class = I2C_CLASS_TV_ANALOG, + .class = 0, .id = I2C_HW_B_BT848, .client_register = pvr2_i2c_attach_inform, .client_unregister = pvr2_i2c_detach_inform, @@ -685,6 +685,7 @@ void pvr2_i2c_core_init(struct pvr2_hdw *hdw) hdw->i2c_adap.dev.parent = &hdw->usb_dev->dev; hdw->i2c_adap.algo = &hdw->i2c_algo; hdw->i2c_adap.algo_data = hdw; + hdw->i2c_adap.class = I2C_CLASS_TV_ANALOG; hdw->i2c_linked = !0; i2c_set_adapdata(&hdw->i2c_adap, &hdw->v4l2_dev); i2c_add_adapter(&hdw->i2c_adap); -- cgit v1.2.3 From fda8259d29b321bcacec067d25f37655942503d3 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Fri, 6 Mar 2009 20:58:15 -0600 Subject: pvrusb2: Tie up loose ends with v4l2-subdev setup From: Mike Isely Tie up loose ends with v4l2-subdev setup. Set attached module's group ID to match our internal ID, emit a few useful messages when sub-devices are dealt with, implement better error legs, and fix an error in the old i2c layer (caused by changes related to the v4l2-subdev work here). Priority: normal Signed-off-by: Mike Isely --- linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c index 605e47368..66c9a99ad 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -2037,17 +2037,26 @@ static void pvr2_hdw_load_subdev(struct pvr2_hdw *hdw, i2caddr); } + if (!sd) { + pvr2_trace(PVR2_TRACE_ERROR_LEGS, + "Module ID %u for device %s failed to load" + " (this is probably a bad thing...)", + mid, hdw->hdw_desc->description); + return; + } + + /* Tag this sub-device instance with the module ID we know about. + In other places we'll use that tag to determine if the instance + requires special handling. */ + sd->grp_id = mid; + /* If we have both old and new i2c layers enabled, make sure that old layer isn't also tracking this module. This is a debugging aid, in normal situations there's no reason for both mechanisms to be enabled. */ pvr2_i2c_untrack_subdev(hdw, sd); + pvr2_trace(PVR2_TRACE_INIT, "Attached sub-driver %s", fname); - // ????? - /* Based on module ID, we should remember subdev pointers - so that we can send certain custom commands where - needed. */ - // ????? } -- cgit v1.2.3 From 32a52d6b73a50a715bebb6dc4c0dba4d872b1a01 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Fri, 6 Mar 2009 21:01:20 -0600 Subject: pvrusb2: Lay foundation for triggering sub-device updates From: Mike Isely These changes set up the spot where we'll check for and set general updates to any attached sub-devices. Priority: normal Signed-off-by: Mike Isely --- linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c index 66c9a99ad..3180fc03e 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -2863,6 +2863,14 @@ static const char *get_ctrl_typename(enum pvr2_ctl_type tp) } +/* Execute whatever commands are required to update the state of all the + sub-devices so that it matches our current control values. */ +static void pvr2_subdev_update(struct pvr2_hdw *hdw) +{ + /* ????? */ +} + + /* Figure out if we need to commit control changes. If so, mark internal state flags to indicate this fact and return true. Otherwise do nothing else and return false. */ @@ -3033,12 +3041,6 @@ static int pvr2_hdw_commit_execute(struct pvr2_hdw *hdw) the client drivers in order to keep everything in sync */ pvr2_i2c_core_check_stale(hdw); - for (idx = 0; idx < hdw->control_cnt; idx++) { - cptr = hdw->controls + idx; - if (!cptr->info->clear_dirty) continue; - cptr->info->clear_dirty(cptr); - } - if (hdw->active_stream_type != hdw->desired_stream_type) { /* Handle any side effects of stream config here */ hdw->active_stream_type = hdw->desired_stream_type; @@ -3058,6 +3060,15 @@ static int pvr2_hdw_commit_execute(struct pvr2_hdw *hdw) } } + for (idx = 0; idx < hdw->control_cnt; idx++) { + cptr = hdw->controls + idx; + if (!cptr->info->clear_dirty) continue; + cptr->info->clear_dirty(cptr); + } + + /* Check and update state for all sub-devices. */ + pvr2_subdev_update(hdw); + /* Now execute i2c core update */ pvr2_i2c_core_sync(hdw); @@ -3214,8 +3225,8 @@ void pvr2_hdw_trigger_module_log(struct pvr2_hdw *hdw) { int nr = pvr2_hdw_get_unit_number(hdw); LOCK_TAKE(hdw->big_lock); do { - hdw->log_requested = !0; printk(KERN_INFO "pvrusb2: ================= START STATUS CARD #%d =================\n", nr); + hdw->log_requested = !0; pvr2_i2c_core_check_stale(hdw); pvr2_i2c_core_sync(hdw); hdw->log_requested = 0; -- cgit v1.2.3 From 86556cd81c5ddb910d85f1635729255eaa4da504 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Fri, 6 Mar 2009 21:02:33 -0600 Subject: pvrusb2: Tie-in sub-device log requests From: Mike Isely Trigger a broadcast to attached sub-devices when a logging request is made. Priority: normal Signed-off-by: Mike Isely --- linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c | 1 + 1 file changed, 1 insertion(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c index 3180fc03e..1f9e62111 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -3230,6 +3230,7 @@ void pvr2_hdw_trigger_module_log(struct pvr2_hdw *hdw) pvr2_i2c_core_check_stale(hdw); pvr2_i2c_core_sync(hdw); hdw->log_requested = 0; + v4l2_device_call_all(&hdw->v4l2_dev, 0, core, log_status); pvr2_trace(PVR2_TRACE_INFO,"cx2341x config:"); cx2341x_log_status(&hdw->enc_ctl_state, "pvrusb2"); pvr2_hdw_state_log_state(hdw); -- cgit v1.2.3 From 9fee9b0bdc0b84b220c18ef30cfc7b107966424b Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Fri, 6 Mar 2009 21:05:00 -0600 Subject: pvrusb2: Tie in debug register access to sub-devices From: Mike Isely Implement tie-in for v4l2 debug register access such that the appropriate attached sub-device is handled. Priority: normal Signed-off-by: Mike Isely --- linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c index 1f9e62111..975d56825 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -5064,7 +5064,10 @@ int pvr2_hdw_register_access(struct pvr2_hdw *hdw, req.match = *match; req.reg = reg_id; if (setFl) req.val = *val_ptr; - mutex_lock(&hdw->i2c_list_lock); do { + /* It would be nice to know if a sub-device answered the request */ + v4l2_device_call_all(&hdw->v4l2_dev, 0, core, g_register, &req); + if (!setFl) *val_ptr = req.val; + if (!okFl) mutex_lock(&hdw->i2c_list_lock); do { list_for_each_entry(cp, &hdw->i2c_clients, list) { if (!v4l2_chip_match_i2c_client( cp->client, -- cgit v1.2.3 From 71de949bd82e5ca76a64b50b77ffdcb6c33ab8ff Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Fri, 6 Mar 2009 21:08:17 -0600 Subject: pvrusb2: Implement status fetching from sub-devices From: Mike Isely Implement status fetching operations in terms of calling out to sub-device(s). Priority: normal Signed-off-by: Mike Isely --- linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c | 14 ++++++++++++++ linux/drivers/media/video/pvrusb2/pvrusb2-i2c-track.c | 8 -------- 2 files changed, 14 insertions(+), 8 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c index 975d56825..3d6aab2f6 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -4955,7 +4955,21 @@ int pvr2_hdw_gpio_chg_out(struct pvr2_hdw *hdw,u32 msk,u32 val) void pvr2_hdw_status_poll(struct pvr2_hdw *hdw) { + struct v4l2_tuner *vtp = &hdw->tuner_signal_info; + memset(vtp, 0, sizeof(*vtp)); pvr2_i2c_core_status_poll(hdw); + /* Note: There apparently is no replacement for VIDIOC_CROPCAP + using v4l2-subdev - therefore we can't support that AT ALL right + now. (Of course, no sub-drivers seem to implement it either. + But now it's a a chicken and egg problem...) */ + v4l2_device_call_all(&hdw->v4l2_dev, 0, tuner, g_tuner, + &hdw->tuner_signal_info); + pvr2_trace(PVR2_TRACE_CHIPS, "client status poll" + " type=%u strength=%u audio=0x%x cap=0x%x" + " low=%u hi=%u", + vtp->type, + vtp->signal, vtp->rxsubchans, vtp->capability, + vtp->rangelow, vtp->rangehigh); } diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-track.c b/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-track.c index fb738385d..78ff57773 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-track.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-track.c @@ -113,20 +113,12 @@ void pvr2_i2c_core_status_poll(struct pvr2_hdw *hdw) { struct pvr2_i2c_client *cp; mutex_lock(&hdw->i2c_list_lock); do { - struct v4l2_tuner *vtp = &hdw->tuner_signal_info; - memset(vtp,0,sizeof(*vtp)); list_for_each_entry(cp, &hdw->i2c_clients, list) { if (!cp->detected_flag) continue; if (!cp->status_poll) continue; cp->status_poll(cp); } hdw->tuner_signal_stale = 0; - pvr2_trace(PVR2_TRACE_CHIPS,"i2c status poll" - " type=%u strength=%u audio=0x%x cap=0x%x" - " low=%u hi=%u", - vtp->type, - vtp->signal,vtp->rxsubchans,vtp->capability, - vtp->rangelow,vtp->rangehigh); } while (0); mutex_unlock(&hdw->i2c_list_lock); } -- cgit v1.2.3 From a135e605f086ea307c83a75ad9efee9a9f609757 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Fri, 6 Mar 2009 21:13:25 -0600 Subject: pvrusb2: Tie in various v4l2 operations into the sub-device mechanism From: Mike Isely This is another step in the v42l-subdev assimilation. This implements various call-outs to sub-devices based on state changes within the pvrusb2 driver. Priority: normal Signed-off-by: Mike Isely --- linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c | 102 ++++++++++++++++++++- .../media/video/pvrusb2/pvrusb2-i2c-track.c | 1 - 2 files changed, 99 insertions(+), 4 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c index 3d6aab2f6..2050ce208 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -2863,11 +2863,102 @@ static const char *get_ctrl_typename(enum pvr2_ctl_type tp) } +static void pvr2_subdev_set_control(struct pvr2_hdw *hdw, int id, + const char *name, int val) +{ + struct v4l2_control ctrl; + pvr2_trace(PVR2_TRACE_CHIPS, "subdev v4l2 %s=%d", name, val); + memset(&ctrl, 0, sizeof(ctrl)); + ctrl.id = id; + ctrl.value = val; + v4l2_device_call_all(&hdw->v4l2_dev, 0, core, s_ctrl, &ctrl); +} + +#define PVR2_SUBDEV_SET_CONTROL(hdw, id, lab) \ + if ((hdw)->lab##_dirty) { \ + pvr2_subdev_set_control(hdw, id, #lab, (hdw)->lab##_val); \ + } + /* Execute whatever commands are required to update the state of all the - sub-devices so that it matches our current control values. */ + sub-devices so that they match our current control values. */ static void pvr2_subdev_update(struct pvr2_hdw *hdw) { - /* ????? */ + if (hdw->input_dirty || hdw->std_dirty) { + pvr2_trace(PVR2_TRACE_CHIPS,"subdev v4l2 set_standard"); + if (hdw->input_val == PVR2_CVAL_INPUT_RADIO) { + v4l2_device_call_all(&hdw->v4l2_dev, 0, + tuner, s_radio); + } else { + v4l2_std_id vs; + vs = hdw->std_mask_cur; + v4l2_device_call_all(&hdw->v4l2_dev, 0, + tuner, s_std, vs); + } + hdw->tuner_signal_stale = !0; + hdw->cropcap_stale = !0; + } + + PVR2_SUBDEV_SET_CONTROL(hdw, V4L2_CID_BRIGHTNESS, brightness); + PVR2_SUBDEV_SET_CONTROL(hdw, V4L2_CID_CONTRAST, contrast); + PVR2_SUBDEV_SET_CONTROL(hdw, V4L2_CID_SATURATION, saturation); + PVR2_SUBDEV_SET_CONTROL(hdw, V4L2_CID_HUE, hue); + PVR2_SUBDEV_SET_CONTROL(hdw, V4L2_CID_AUDIO_MUTE, mute); + PVR2_SUBDEV_SET_CONTROL(hdw, V4L2_CID_AUDIO_VOLUME, volume); + PVR2_SUBDEV_SET_CONTROL(hdw, V4L2_CID_AUDIO_BALANCE, balance); + PVR2_SUBDEV_SET_CONTROL(hdw, V4L2_CID_AUDIO_BASS, bass); + PVR2_SUBDEV_SET_CONTROL(hdw, V4L2_CID_AUDIO_TREBLE, treble); + + if (hdw->input_dirty || hdw->audiomode_dirty) { + struct v4l2_tuner vt; + memset(&vt, 0, sizeof(vt)); + vt.audmode = hdw->audiomode_val; + v4l2_device_call_all(&hdw->v4l2_dev, 0, tuner, s_tuner, &vt); + } + + if (hdw->freqDirty) { + unsigned long fv; + struct v4l2_frequency freq; + fv = pvr2_hdw_get_cur_freq(hdw); + pvr2_trace(PVR2_TRACE_CHIPS, "subdev v4l2 set_freq(%lu)", fv); + if (hdw->tuner_signal_stale) pvr2_hdw_status_poll(hdw); + memset(&freq, 0, sizeof(freq)); + if (hdw->tuner_signal_info.capability & V4L2_TUNER_CAP_LOW) { + /* ((fv * 1000) / 62500) */ + freq.frequency = (fv * 2) / 125; + } else { + freq.frequency = fv / 62500; + } + /* tuner-core currently doesn't seem to care about this, but + let's set it anyway for completeness. */ + if (hdw->input_val == PVR2_CVAL_INPUT_RADIO) { + freq.type = V4L2_TUNER_RADIO; + } else { + freq.type = V4L2_TUNER_ANALOG_TV; + } + freq.tuner = 0; + v4l2_device_call_all(&hdw->v4l2_dev, 0, tuner, + s_frequency, &freq); + } + + if (hdw->res_hor_dirty || hdw->res_ver_dirty) { + struct v4l2_format fmt; + memset(&fmt, 0, sizeof(fmt)); + fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + fmt.fmt.pix.width = hdw->res_hor_val; + fmt.fmt.pix.height = hdw->res_ver_val; + pvr2_trace(PVR2_TRACE_CHIPS,"subdev v4l2 set_size(%dx%d)", + fmt.fmt.pix.width, fmt.fmt.pix.height); + v4l2_device_call_all(&hdw->v4l2_dev, 0, video, s_fmt, &fmt); + } + + /* Unable to set crop parameters; there is apparently no equivalent + for VIDIOC_S_CROP */ + + /* ????? Cover special cases for specific sub-devices. */ + + if (hdw->tuner_signal_stale && hdw->cropcap_stale) { + pvr2_hdw_status_poll(hdw); + } } @@ -4957,6 +5048,7 @@ void pvr2_hdw_status_poll(struct pvr2_hdw *hdw) { struct v4l2_tuner *vtp = &hdw->tuner_signal_info; memset(vtp, 0, sizeof(*vtp)); + hdw->tuner_signal_stale = 0; pvr2_i2c_core_status_poll(hdw); /* Note: There apparently is no replacement for VIDIOC_CROPCAP using v4l2-subdev - therefore we can't support that AT ALL right @@ -4964,12 +5056,16 @@ void pvr2_hdw_status_poll(struct pvr2_hdw *hdw) But now it's a a chicken and egg problem...) */ v4l2_device_call_all(&hdw->v4l2_dev, 0, tuner, g_tuner, &hdw->tuner_signal_info); - pvr2_trace(PVR2_TRACE_CHIPS, "client status poll" + pvr2_trace(PVR2_TRACE_CHIPS, "subdev status poll" " type=%u strength=%u audio=0x%x cap=0x%x" " low=%u hi=%u", vtp->type, vtp->signal, vtp->rxsubchans, vtp->capability, vtp->rangelow, vtp->rangehigh); + + /* We have to do this to avoid getting into constant polling if + there's nobody to answer a poll of cropcap info. */ + hdw->cropcap_stale = 0; } diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-track.c b/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-track.c index 78ff57773..cec2526cb 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-track.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-track.c @@ -118,7 +118,6 @@ void pvr2_i2c_core_status_poll(struct pvr2_hdw *hdw) if (!cp->status_poll) continue; cp->status_poll(cp); } - hdw->tuner_signal_stale = 0; } while (0); mutex_unlock(&hdw->i2c_list_lock); } -- cgit v1.2.3 From 6f3588fa9e45a2ffce4509d03d7f00754cccd8c6 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Fri, 6 Mar 2009 21:14:13 -0600 Subject: pvrusb2: Define value for a null sub-device ID From: Mike Isely Priority: normal Signed-off-by: Mike Isely --- linux/drivers/media/video/pvrusb2/pvrusb2-devattr.h | 1 + 1 file changed, 1 insertion(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-devattr.h b/linux/drivers/media/video/pvrusb2/pvrusb2-devattr.h index f06923986..abf3e37fa 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-devattr.h +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-devattr.h @@ -33,6 +33,7 @@ */ +#define PVR2_CLIENT_ID_NULL 0 #define PVR2_CLIENT_ID_MSP3400 1 #define PVR2_CLIENT_ID_CX25840 2 #define PVR2_CLIENT_ID_SAA7115 3 -- cgit v1.2.3 From e7f9662a72fd63a0b8a7fc4b1b7b178fba9c7a93 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Fri, 6 Mar 2009 21:17:11 -0600 Subject: pvrusb2: Note who our video decoder sub-device is, and set it up From: Mike Isely Other code may need to treat the video decoder sub-device in a special manner, so this change implements code to recognize when such a sub-device is connected to the driver, does any special processing for it, and notes who the device is for future reference. Priority: normal Signed-off-by: Mike Isely --- .../media/video/pvrusb2/pvrusb2-hdw-internal.h | 1 + linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c | 28 ++++++++++++++++++++++ 2 files changed, 29 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h index b3cb0bbd8..c8192d8a6 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h @@ -299,6 +299,7 @@ struct pvr2_hdw { int flag_tripped; /* Indicates overall failure to start */ struct pvr2_decoder_ctrl *decoder_ctrl; + unsigned int decoder_client_id; // CPU firmware info (used to help find / save firmware data) char *fw_buffer; diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c index 2050ce208..34412db68 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -2058,6 +2058,34 @@ static void pvr2_hdw_load_subdev(struct pvr2_hdw *hdw, pvr2_trace(PVR2_TRACE_INIT, "Attached sub-driver %s", fname); + /* client-specific setup... */ + switch (mid) { + case PVR2_CLIENT_ID_CX25840: + hdw->decoder_client_id = mid; + { + /* + Mike Isely 19-Nov-2006 - This + bit of nuttiness for cx25840 causes that module + to correctly set up its video scaling. This is + really a problem in the cx25840 module itself, + but we work around it here. The problem has not + been seen in ivtv because there VBI is supported + and set up. We don't do VBI here (at least not + yet) and thus we never attempted to even set it + up. + */ + struct v4l2_format fmt; + memset(&fmt, 0, sizeof(fmt)); + fmt.type = V4L2_BUF_TYPE_SLICED_VBI_CAPTURE; + v4l2_device_call_all(&hdw->v4l2_dev, mid, + video, s_fmt, &fmt); + } + break; + case PVR2_CLIENT_ID_SAA7115: + hdw->decoder_client_id = mid; + break; + default: break; + } } -- cgit v1.2.3 From 982d2fcc073a9f500cd9192bf2fb3fea7dca002a Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Fri, 6 Mar 2009 21:19:43 -0600 Subject: pvrusb2: Clean-up / placeholders inserted for additional development From: Mike Isely Priority: normal Signed-off-by: Mike Isely --- linux/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h | 2 -- linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c | 2 ++ 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h index c8192d8a6..299bf58ad 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h @@ -58,8 +58,6 @@ #define LOCK_TAKE(x) do { mutex_lock(&x##_mutex); x##_held = !0; } while (0) #define LOCK_GIVE(x) do { x##_held = 0; mutex_unlock(&x##_mutex); } while (0) -struct pvr2_decoder; - typedef int (*pvr2_ctlf_is_dirty)(struct pvr2_ctrl *); typedef void (*pvr2_ctlf_clear_dirty)(struct pvr2_ctrl *); typedef int (*pvr2_ctlf_check_value)(struct pvr2_ctrl *,int); diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c index 34412db68..673820594 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -1676,6 +1676,7 @@ static int pvr2_decoder_enable(struct pvr2_hdw *hdw,int enablefl) return -EIO; } hdw->decoder_ctrl->enable(hdw->decoder_ctrl->ctxt,enablefl); + // ????? return 0; } @@ -4119,6 +4120,7 @@ int pvr2_hdw_cmd_decoder_reset(struct pvr2_hdw *hdw) pvr2_trace(PVR2_TRACE_INIT, "Requesting decoder reset"); hdw->decoder_ctrl->force_reset(hdw->decoder_ctrl->ctxt); + // ????? return 0; } -- cgit v1.2.3 From f46785b14c231ff3999ad3923be2d18cce941e5c Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Fri, 6 Mar 2009 21:21:30 -0600 Subject: pvrusb2: Tie in sub-device decoder start/stop From: Mike Isely Implement code to send appropriate streaming start/stop commands to attached sub-devices Priority: normal Signed-off-by: Mike Isely --- linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c | 65 +++++++++++++++---------- 1 file changed, 39 insertions(+), 26 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c index 673820594..ce7d272a5 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -1665,19 +1665,29 @@ static const char *pvr2_get_state_name(unsigned int st) static int pvr2_decoder_enable(struct pvr2_hdw *hdw,int enablefl) { - if (!hdw->decoder_ctrl) { - if (!hdw->flag_decoder_missed) { - pvr2_trace(PVR2_TRACE_ERROR_LEGS, - "WARNING: No decoder present"); - hdw->flag_decoder_missed = !0; - trace_stbit("flag_decoder_missed", - hdw->flag_decoder_missed); - } - return -EIO; + if (hdw->decoder_ctrl) { + hdw->decoder_ctrl->enable(hdw->decoder_ctrl->ctxt, enablefl); + return 0; } - hdw->decoder_ctrl->enable(hdw->decoder_ctrl->ctxt,enablefl); - // ????? - return 0; + /* Even though we really only care about the video decoder chip at + this point, we'll broadcast stream on/off to all sub-devices + anyway, just in case somebody else wants to hear the + command... */ + v4l2_device_call_all(&hdw->v4l2_dev, 0, video, s_stream, enablefl); + if (hdw->decoder_client_id) { + /* We get here if the encoder has been noticed. Otherwise + we'll issue a warning to the user (which should + normally never happen). */ + return 0; + } + if (!hdw->flag_decoder_missed) { + pvr2_trace(PVR2_TRACE_ERROR_LEGS, + "WARNING: No decoder present"); + hdw->flag_decoder_missed = !0; + trace_stbit("flag_decoder_missed", + hdw->flag_decoder_missed); + } + return -EIO; } @@ -4105,23 +4115,26 @@ int pvr2_hdw_cmd_powerdown(struct pvr2_hdw *hdw) int pvr2_hdw_cmd_decoder_reset(struct pvr2_hdw *hdw) { - if (!hdw->decoder_ctrl) { - pvr2_trace(PVR2_TRACE_INIT, - "Unable to reset decoder: nothing attached"); - return -ENOTTY; + pvr2_trace(PVR2_TRACE_INIT, + "Requesting decoder reset"); + if (hdw->decoder_ctrl) { + if (!hdw->decoder_ctrl->force_reset) { + pvr2_trace(PVR2_TRACE_INIT, + "Unable to reset decoder: not implemented"); + return -ENOTTY; + } + hdw->decoder_ctrl->force_reset(hdw->decoder_ctrl->ctxt); + return 0; + } else { } - - if (!hdw->decoder_ctrl->force_reset) { - pvr2_trace(PVR2_TRACE_INIT, - "Unable to reset decoder: not implemented"); - return -ENOTTY; + if (hdw->decoder_client_id) { + v4l2_device_call_all(&hdw->v4l2_dev, hdw->decoder_client_id, + core, reset, 0); + return 0; } - pvr2_trace(PVR2_TRACE_INIT, - "Requesting decoder reset"); - hdw->decoder_ctrl->force_reset(hdw->decoder_ctrl->ctxt); - // ????? - return 0; + "Unable to reset decoder: nothing attached"); + return -ENOTTY; } -- cgit v1.2.3 From 11cad91bcc776256090cbc0c1690256e4a429976 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Fri, 6 Mar 2009 21:24:24 -0600 Subject: pvrusb2: Cause overall initialization to fail if sub-driver(s) fail From: Mike Isely Priority: normal Signed-off-by: Mike Isely --- linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c | 32 +++++++++++++------------ 1 file changed, 17 insertions(+), 15 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c index ce7d272a5..75aea30c3 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -1991,8 +1991,8 @@ static unsigned int pvr2_copy_i2c_addr_list( } -static void pvr2_hdw_load_subdev(struct pvr2_hdw *hdw, - const struct pvr2_device_client_desc *cd) +static int pvr2_hdw_load_subdev(struct pvr2_hdw *hdw, + const struct pvr2_device_client_desc *cd) { const char *fname; unsigned char mid; @@ -2006,11 +2006,10 @@ static void pvr2_hdw_load_subdev(struct pvr2_hdw *hdw, fname = (mid < ARRAY_SIZE(module_names)) ? module_names[mid] : NULL; if (!fname) { pvr2_trace(PVR2_TRACE_ERROR_LEGS, - "Module ID %u for device %s is unknown" - " (this is probably a bad thing...)", + "Module ID %u for device %s has no name", mid, hdw->hdw_desc->description); - return; + return -EINVAL; } i2ccnt = pvr2_copy_i2c_addr_list(i2caddr, cd->i2c_address_list, @@ -2024,11 +2023,10 @@ static void pvr2_hdw_load_subdev(struct pvr2_hdw *hdw, if (!i2ccnt) { pvr2_trace(PVR2_TRACE_ERROR_LEGS, - "Module ID %u for device %s:" - " No i2c addresses" - " (this is probably a bad thing...)", - mid, hdw->hdw_desc->description); - return; + "Module ID %u (%s) for device %s:" + " No i2c addresses", + mid, fname, hdw->hdw_desc->description); + return -EINVAL; } /* Note how the 2nd and 3rd arguments are the same for both @@ -2050,10 +2048,9 @@ static void pvr2_hdw_load_subdev(struct pvr2_hdw *hdw, if (!sd) { pvr2_trace(PVR2_TRACE_ERROR_LEGS, - "Module ID %u for device %s failed to load" - " (this is probably a bad thing...)", - mid, hdw->hdw_desc->description); - return; + "Module ID %u (%s) for device %s failed to load", + mid, fname, hdw->hdw_desc->description); + return -EIO; } /* Tag this sub-device instance with the module ID we know about. @@ -2097,6 +2094,8 @@ static void pvr2_hdw_load_subdev(struct pvr2_hdw *hdw, break; default: break; } + + return 0; } @@ -2105,6 +2104,7 @@ static void pvr2_hdw_load_modules(struct pvr2_hdw *hdw) unsigned int idx; const struct pvr2_string_table *cm; const struct pvr2_device_client_table *ct; + int okFl = !0; cm = &hdw->hdw_desc->client_modules; for (idx = 0; idx < cm->cnt; idx++) { @@ -2113,8 +2113,9 @@ static void pvr2_hdw_load_modules(struct pvr2_hdw *hdw) ct = &hdw->hdw_desc->client_table; for (idx = 0; idx < ct->cnt; idx++) { - pvr2_hdw_load_subdev(hdw,&ct->lst[idx]); + if (!pvr2_hdw_load_subdev(hdw, &ct->lst[idx])) okFl = 0; } + if (!okFl) pvr2_hdw_render_useless(hdw); } @@ -2176,6 +2177,7 @@ static void pvr2_hdw_setup_low(struct pvr2_hdw *hdw) if (!pvr2_hdw_dev_ok(hdw)) return; pvr2_hdw_load_modules(hdw); + if (!pvr2_hdw_dev_ok(hdw)) return; for (idx = 0; idx < CTRLDEF_COUNT; idx++) { cptr = hdw->controls + idx; -- cgit v1.2.3 From 62a5d8ccb027ef29425a3a1df6f47777b229d305 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Fri, 6 Mar 2009 21:26:24 -0600 Subject: pvrusb2: Fix backwards function header comments From: Mike Isely Priority: normal Signed-off-by: Mike Isely --- linux/drivers/media/video/pvrusb2/pvrusb2-debugifc.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-debugifc.h b/linux/drivers/media/video/pvrusb2/pvrusb2-debugifc.h index e24ff59f8..2f8d46761 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-debugifc.h +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-debugifc.h @@ -22,16 +22,16 @@ struct pvr2_hdw; -/* Non-intrusively print some useful debugging info from inside the - driver. This should work even if the driver appears to be - wedged. */ -int pvr2_debugifc_print_info(struct pvr2_hdw *, - char *buf_ptr,unsigned int buf_size); - /* Print general status of driver. This will also trigger a probe of the USB link. Unlike print_info(), this one synchronizes with the driver so the information should be self-consistent (but it will hang if the driver is wedged). */ +int pvr2_debugifc_print_info(struct pvr2_hdw *, + char *buf_ptr, unsigned int buf_size); + +/* Non-intrusively print some useful debugging info from inside the + driver. This should work even if the driver appears to be + wedged. */ int pvr2_debugifc_print_status(struct pvr2_hdw *, char *buf_ptr,unsigned int buf_size); -- cgit v1.2.3 From 778ae30db1fe43b100612fadbd15cf51e9bb630b Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Fri, 6 Mar 2009 21:28:28 -0600 Subject: pvrusb2: Implement reporting of connected sub-devices From: Mike Isely The pvrusb2 driver has a function that reports internal state. It can be accessed from either the debug interface or as the result of a v4l log status request. This change adds information listing sub-devices to the report. Priority: normal Signed-off-by: Mike Isely --- linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c index 75aea30c3..96a9729e6 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -4875,6 +4875,29 @@ static unsigned int pvr2_hdw_report_unlocked(struct pvr2_hdw *hdw,int which, stats.buffers_processed, stats.buffers_failed); } + case 6: { + struct v4l2_subdev *sd; + unsigned int tcnt = 0; + unsigned int ccnt; + const char *p; + unsigned int id; + ccnt = scnprintf(buf, + acnt, + "Associted v4l2_subdev drivers:"); + tcnt += ccnt; + v4l2_device_for_each_subdev(sd, &hdw->v4l2_dev) { + id = sd->grp_id; + p = NULL; + if (id < ARRAY_SIZE(module_names)) { + p = module_names[id]; + } + if (!p) p = "(unknown)"; + ccnt = scnprintf(buf + tcnt, + acnt - tcnt, + " %s (%u)", p, id); + } + return tcnt; + } default: break; } return 0; -- cgit v1.2.3 From d22a03cd627da69843d2a79a7587179c19df4a40 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Fri, 6 Mar 2009 21:37:10 -0600 Subject: pvrusb2: Implement sub-device specific update framework From: Mike Isely Lay down a foundation whereby it becomes possible to send customized updates to specific sub-devices. (This becomes useful for routing configuration, which is a very sub-device specific operation.) Priority: normal Signed-off-by: Mike Isely --- linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c index 96a9729e6..9aaf20acc 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -106,6 +106,13 @@ MODULE_PARM_DESC(radio_freq, "specify initial radio frequency"); /* size of a firmware chunk */ #define FIRMWARE_CHUNK_SIZE 0x2000 +typedef void (*pvr2_subdev_update_func)(struct pvr2_hdw *, + struct v4l2_subdev *); + +static const pvr2_subdev_update_func pvr2_module_update_functions[] = { + /* ????? */ +}; + static const char *module_names[] = { [PVR2_CLIENT_ID_MSP3400] = "msp3400", [PVR2_CLIENT_ID_CX25840] = "cx25840", @@ -2924,6 +2931,10 @@ static void pvr2_subdev_set_control(struct pvr2_hdw *hdw, int id, sub-devices so that they match our current control values. */ static void pvr2_subdev_update(struct pvr2_hdw *hdw) { + struct v4l2_subdev *sd; + unsigned int id; + pvr2_subdev_update_func fp; + if (hdw->input_dirty || hdw->std_dirty) { pvr2_trace(PVR2_TRACE_CHIPS,"subdev v4l2 set_standard"); if (hdw->input_val == PVR2_CVAL_INPUT_RADIO) { @@ -2995,7 +3006,13 @@ static void pvr2_subdev_update(struct pvr2_hdw *hdw) /* Unable to set crop parameters; there is apparently no equivalent for VIDIOC_S_CROP */ - /* ????? Cover special cases for specific sub-devices. */ + v4l2_device_for_each_subdev(sd, &hdw->v4l2_dev) { + id = sd->grp_id; + if (id >= ARRAY_SIZE(pvr2_module_update_functions)) continue; + fp = pvr2_module_update_functions[id]; + if (!fp) continue; + (*fp)(hdw, sd); + } if (hdw->tuner_signal_stale && hdw->cropcap_stale) { pvr2_hdw_status_poll(hdw); -- cgit v1.2.3 From 0f16c4cd5b6c0c18492d34470bd380aa23d0f862 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Fri, 6 Mar 2009 21:39:34 -0600 Subject: pvrusb2: Tie in wm8775 sub-device handling From: Mike Isely Priority: normal Signed-off-by: Mike Isely --- .../drivers/media/video/pvrusb2/pvrusb2-devattr.h | 1 + linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c | 4 +++- linux/drivers/media/video/pvrusb2/pvrusb2-wm8775.c | 26 ++++++++++++++++++++++ linux/drivers/media/video/pvrusb2/pvrusb2-wm8775.h | 3 +++ 4 files changed, 33 insertions(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-devattr.h b/linux/drivers/media/video/pvrusb2/pvrusb2-devattr.h index abf3e37fa..1339a32a2 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-devattr.h +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-devattr.h @@ -39,6 +39,7 @@ #define PVR2_CLIENT_ID_SAA7115 3 #define PVR2_CLIENT_ID_TUNER 4 #define PVR2_CLIENT_ID_CS53132A 5 +#define PVR2_CLIENT_ID_WM8775 6 struct pvr2_device_client_desc { /* One ovr PVR2_CLIENT_ID_xxxx */ diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c index 9aaf20acc..7e88b87aa 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -36,6 +36,7 @@ #include "pvrusb2-encoder.h" #include "pvrusb2-debug.h" #include "pvrusb2-fx2-cmd.h" +#include "pvrusb2-wm8775.h" #include "compat.h" #define TV_MIN_FREQ 55250000L @@ -110,7 +111,7 @@ typedef void (*pvr2_subdev_update_func)(struct pvr2_hdw *, struct v4l2_subdev *); static const pvr2_subdev_update_func pvr2_module_update_functions[] = { - /* ????? */ + [PVR2_CLIENT_ID_WM8775] = pvr2_wm8775_update, }; static const char *module_names[] = { @@ -119,6 +120,7 @@ static const char *module_names[] = { [PVR2_CLIENT_ID_SAA7115] = "saa7115", [PVR2_CLIENT_ID_TUNER] = "tuner", [PVR2_CLIENT_ID_CS53132A] = "cs53132a", + [PVR2_CLIENT_ID_WM8775] = "wm8775", }; diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-wm8775.c b/linux/drivers/media/video/pvrusb2/pvrusb2-wm8775.c index 6cdcbf2fe..b5b2d0b72 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-wm8775.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-wm8775.c @@ -38,6 +38,8 @@ #include #include "compat.h" + + struct pvr2_v4l_wm8775 { struct pvr2_i2c_handler handler; struct pvr2_i2c_client *client; @@ -159,6 +161,30 @@ int pvr2_i2c_wm8775_setup(struct pvr2_hdw *hdw,struct pvr2_i2c_client *cp) } +void pvr2_wm8775_update(struct pvr2_hdw *hdw, struct v4l2_subdev *sd) +{ + if (hdw->input_dirty) { + struct v4l2_routing route; + + memset(&route, 0, sizeof(route)); + + switch (hdw->input_val) { + case PVR2_CVAL_INPUT_RADIO: + route.input = 1; + break; + default: + /* All other cases just use the second input */ + route.input = 2; + break; + } + pvr2_trace(PVR2_TRACE_CHIPS, "subdev wm8775" + " set_input(val=%d route=0x%x)", + hdw->input_val, route.input); + + sd->ops->audio->s_routing(sd, &route); + } +} + /* diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-wm8775.h b/linux/drivers/media/video/pvrusb2/pvrusb2-wm8775.h index 5b2cb6183..d2d4e7eb1 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-wm8775.h +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-wm8775.h @@ -37,6 +37,9 @@ #include "pvrusb2-i2c-track.h" int pvr2_i2c_wm8775_setup(struct pvr2_hdw *,struct pvr2_i2c_client *); +#include "pvrusb2-hdw-internal.h" + +void pvr2_wm8775_update(struct pvr2_hdw *, struct v4l2_subdev *sd); #endif /* __PVRUSB2_WM8775_H */ -- cgit v1.2.3 From c2d235d8b62f32064c7bf3762660e0b376c1b6f9 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Fri, 6 Mar 2009 21:43:26 -0600 Subject: pvrusb2: Tie in saa7115 sub-device handling From: Mike Isely Priority: normal Signed-off-by: Mike Isely --- linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c | 2 + .../media/video/pvrusb2/pvrusb2-video-v4l.c | 64 ++++++++++++++++++---- .../media/video/pvrusb2/pvrusb2-video-v4l.h | 2 + 3 files changed, 58 insertions(+), 10 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c index 7e88b87aa..2c31969c5 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -37,6 +37,7 @@ #include "pvrusb2-debug.h" #include "pvrusb2-fx2-cmd.h" #include "pvrusb2-wm8775.h" +#include "pvrusb2-video-v4l.h" #include "compat.h" #define TV_MIN_FREQ 55250000L @@ -112,6 +113,7 @@ typedef void (*pvr2_subdev_update_func)(struct pvr2_hdw *, static const pvr2_subdev_update_func pvr2_module_update_functions[] = { [PVR2_CLIENT_ID_WM8775] = pvr2_wm8775_update, + [PVR2_CLIENT_ID_SAA7115] = pvr2_saa7115_subdev_update, }; static const char *module_names[] = { diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-video-v4l.c b/linux/drivers/media/video/pvrusb2/pvrusb2-video-v4l.c index b1ff3803f..3c392e9a2 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-video-v4l.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-video-v4l.c @@ -28,9 +28,10 @@ */ #include "pvrusb2-video-v4l.h" -#include "pvrusb2-i2c-cmd-v4l2.h" +#include "pvrusb2-i2c-cmd-v4l2.h" + #include "pvrusb2-hdw-internal.h" #include "pvrusb2-debug.h" #include @@ -40,15 +41,6 @@ #include #include "compat.h" -struct pvr2_v4l_decoder { - struct pvr2_i2c_handler handler; - struct pvr2_decoder_ctrl ctrl; - struct pvr2_i2c_client *client; - struct pvr2_hdw *hdw; - unsigned long stale_mask; -}; - - struct routing_scheme { const int *def; unsigned int cnt; @@ -71,6 +63,16 @@ static const struct routing_scheme routing_schemes[] = { }, }; +struct pvr2_v4l_decoder { + struct pvr2_i2c_handler handler; + struct pvr2_decoder_ctrl ctrl; + struct pvr2_i2c_client *client; + struct pvr2_hdw *hdw; + unsigned long stale_mask; +}; + + + static void set_input(struct pvr2_v4l_decoder *ctxt) { struct pvr2_hdw *hdw = ctxt->hdw; @@ -246,6 +248,48 @@ int pvr2_i2c_decoder_v4l_setup(struct pvr2_hdw *hdw, } +void pvr2_saa7115_subdev_update(struct pvr2_hdw *hdw, struct v4l2_subdev *sd) +{ + if (hdw->srate_dirty) { + u32 val; + pvr2_trace(PVR2_TRACE_CHIPS, "subdev v4l2 set_audio %d", + hdw->srate_val); + switch (hdw->srate_val) { + default: + case V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000: + val = 48000; + break; + case V4L2_MPEG_AUDIO_SAMPLING_FREQ_44100: + val = 44100; + break; + case V4L2_MPEG_AUDIO_SAMPLING_FREQ_32000: + val = 32000; + break; + } + sd->ops->audio->s_clock_freq(sd, val); + } + if (hdw->input_dirty) { + struct v4l2_routing route; + const struct routing_scheme *sp; + unsigned int sid = hdw->hdw_desc->signal_routing_scheme; + pvr2_trace(PVR2_TRACE_CHIPS, "subdev v4l2 set_input(%d)", + hdw->input_val); + if ((sid < ARRAY_SIZE(routing_schemes)) && + ((sp = routing_schemes + sid) != NULL) && + (hdw->input_val >= 0) && + (hdw->input_val < sp->cnt)) { + route.input = sp->def[hdw->input_val]; + } else { + pvr2_trace(PVR2_TRACE_ERROR_LEGS, + "*** WARNING *** subdev v4l2 set_input:" + " Invalid routing scheme (%u) and/or input (%d)", + sid, hdw->input_val); + return; + } + route.output = 0; + sd->ops->video->s_routing(sd, &route); + } +} /* diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-video-v4l.h b/linux/drivers/media/video/pvrusb2/pvrusb2-video-v4l.h index b2cd3875b..dac4b1ad3 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-video-v4l.h +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-video-v4l.h @@ -37,6 +37,8 @@ int pvr2_i2c_decoder_v4l_setup(struct pvr2_hdw *,struct pvr2_i2c_client *); +#include "pvrusb2-hdw-internal.h" +void pvr2_saa7115_subdev_update(struct pvr2_hdw *, struct v4l2_subdev *); #endif /* __PVRUSB2_VIDEO_V4L_H */ -- cgit v1.2.3 From ddf32a4802df1c4720de90d6214b270395af4ded Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Fri, 6 Mar 2009 21:48:09 -0600 Subject: pvrusb2: Make audio sample rate update into a sub-device broadcast From: Mike Isely The pvrusb2 driver had previously been using i2c module specific calls to set the sample rate (a long long time ago this was needed). These days it is safe to use a broadcast so let's just broadcast this when communicating audio sample rate to sub-devices. Priority: normal Signed-off-by: Mike Isely --- linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c | 20 ++++++++++++++++++++ .../drivers/media/video/pvrusb2/pvrusb2-video-v4l.c | 18 ------------------ 2 files changed, 20 insertions(+), 18 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c index 2c31969c5..e671f7e81 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -3007,6 +3007,26 @@ static void pvr2_subdev_update(struct pvr2_hdw *hdw) v4l2_device_call_all(&hdw->v4l2_dev, 0, video, s_fmt, &fmt); } + if (hdw->srate_dirty) { + u32 val; + pvr2_trace(PVR2_TRACE_CHIPS, "subdev v4l2 set_audio %d", + hdw->srate_val); + switch (hdw->srate_val) { + default: + case V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000: + val = 48000; + break; + case V4L2_MPEG_AUDIO_SAMPLING_FREQ_44100: + val = 44100; + break; + case V4L2_MPEG_AUDIO_SAMPLING_FREQ_32000: + val = 32000; + break; + } + v4l2_device_call_all(&hdw->v4l2_dev, 0, + audio, s_clock_freq, val); + } + /* Unable to set crop parameters; there is apparently no equivalent for VIDIOC_S_CROP */ diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-video-v4l.c b/linux/drivers/media/video/pvrusb2/pvrusb2-video-v4l.c index 3c392e9a2..6a0e207e6 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-video-v4l.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-video-v4l.c @@ -250,24 +250,6 @@ int pvr2_i2c_decoder_v4l_setup(struct pvr2_hdw *hdw, void pvr2_saa7115_subdev_update(struct pvr2_hdw *hdw, struct v4l2_subdev *sd) { - if (hdw->srate_dirty) { - u32 val; - pvr2_trace(PVR2_TRACE_CHIPS, "subdev v4l2 set_audio %d", - hdw->srate_val); - switch (hdw->srate_val) { - default: - case V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000: - val = 48000; - break; - case V4L2_MPEG_AUDIO_SAMPLING_FREQ_44100: - val = 44100; - break; - case V4L2_MPEG_AUDIO_SAMPLING_FREQ_32000: - val = 32000; - break; - } - sd->ops->audio->s_clock_freq(sd, val); - } if (hdw->input_dirty) { struct v4l2_routing route; const struct routing_scheme *sp; -- cgit v1.2.3 From 24b1e380d582aa066f67e2561d2e8a49605e6399 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Fri, 6 Mar 2009 21:49:19 -0600 Subject: pvrusb2: make sub-device specific update function names uniform From: Mike Isely Priority: normal Signed-off-by: Mike Isely --- linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c | 2 +- linux/drivers/media/video/pvrusb2/pvrusb2-wm8775.c | 2 +- linux/drivers/media/video/pvrusb2/pvrusb2-wm8775.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c index e671f7e81..aa2db330c 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -112,7 +112,7 @@ typedef void (*pvr2_subdev_update_func)(struct pvr2_hdw *, struct v4l2_subdev *); static const pvr2_subdev_update_func pvr2_module_update_functions[] = { - [PVR2_CLIENT_ID_WM8775] = pvr2_wm8775_update, + [PVR2_CLIENT_ID_WM8775] = pvr2_wm8775_subdev_update, [PVR2_CLIENT_ID_SAA7115] = pvr2_saa7115_subdev_update, }; diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-wm8775.c b/linux/drivers/media/video/pvrusb2/pvrusb2-wm8775.c index b5b2d0b72..8fabc2c29 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-wm8775.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-wm8775.c @@ -161,7 +161,7 @@ int pvr2_i2c_wm8775_setup(struct pvr2_hdw *hdw,struct pvr2_i2c_client *cp) } -void pvr2_wm8775_update(struct pvr2_hdw *hdw, struct v4l2_subdev *sd) +void pvr2_wm8775_subdev_update(struct pvr2_hdw *hdw, struct v4l2_subdev *sd) { if (hdw->input_dirty) { struct v4l2_routing route; diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-wm8775.h b/linux/drivers/media/video/pvrusb2/pvrusb2-wm8775.h index d2d4e7eb1..a304988b1 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-wm8775.h +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-wm8775.h @@ -39,7 +39,7 @@ int pvr2_i2c_wm8775_setup(struct pvr2_hdw *,struct pvr2_i2c_client *); #include "pvrusb2-hdw-internal.h" -void pvr2_wm8775_update(struct pvr2_hdw *, struct v4l2_subdev *sd); +void pvr2_wm8775_subdev_update(struct pvr2_hdw *, struct v4l2_subdev *sd); #endif /* __PVRUSB2_WM8775_H */ -- cgit v1.2.3 From ce6fda6ed152e5f323c5c573de8db26e9549ebfb Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Fri, 6 Mar 2009 21:52:06 -0600 Subject: pvrusb2: Tie in msp3400 sub-device support From: Mike Isely Priority: normal Signed-off-by: Mike Isely --- linux/drivers/media/video/pvrusb2/pvrusb2-audio.c | 47 ++++++++++++++++++----- linux/drivers/media/video/pvrusb2/pvrusb2-audio.h | 2 + linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c | 2 + 3 files changed, 41 insertions(+), 10 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-audio.c b/linux/drivers/media/video/pvrusb2/pvrusb2-audio.c index a6e0896d9..6e63d56bd 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-audio.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-audio.c @@ -28,15 +28,6 @@ #include "compat.h" -struct pvr2_msp3400_handler { - struct pvr2_hdw *hdw; - struct pvr2_i2c_client *client; - struct pvr2_i2c_handler i2c_handler; - unsigned long stale_mask; -}; - - - struct routing_scheme { const int *def; unsigned int cnt; @@ -65,6 +56,17 @@ static const struct routing_scheme routing_schemes[] = { }, }; + +struct pvr2_msp3400_handler { + struct pvr2_hdw *hdw; + struct pvr2_i2c_client *client; + struct pvr2_i2c_handler i2c_handler; + unsigned long stale_mask; +}; + + + + /* This function selects the correct audio input source */ static void set_stereo(struct pvr2_msp3400_handler *ctxt) { @@ -181,7 +183,32 @@ int pvr2_i2c_msp3400_setup(struct pvr2_hdw *hdw,struct pvr2_i2c_client *cp) return !0; } - +void pvr2_msp3400_subdev_update(struct pvr2_hdw *hdw, struct v4l2_subdev *sd) +{ + if (hdw->input_dirty) { + struct v4l2_routing route; + const struct routing_scheme *sp; + unsigned int sid = hdw->hdw_desc->signal_routing_scheme; + + pvr2_trace(PVR2_TRACE_CHIPS, "subdev msp3400 v4l2 set_stereo"); + + if ((sid < ARRAY_SIZE(routing_schemes)) && + ((sp = routing_schemes + sid) != NULL) && + (hdw->input_val >= 0) && + (hdw->input_val < sp->cnt)) { + route.input = sp->def[hdw->input_val]; + } else { + pvr2_trace(PVR2_TRACE_ERROR_LEGS, + "*** WARNING *** subdev msp3400 set_input:" + " Invalid routing scheme (%u)" + " and/or input (%d)", + sid, hdw->input_val); + return; + } + route.output = MSP_OUTPUT(MSP_SC_IN_DSP_SCART1); + sd->ops->audio->s_routing(sd, &route); + } +} /* Stuff for Emacs to see, in order to encourage consistent editing style: diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-audio.h b/linux/drivers/media/video/pvrusb2/pvrusb2-audio.h index f7f0a408a..c47c8de3b 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-audio.h +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-audio.h @@ -26,6 +26,8 @@ int pvr2_i2c_msp3400_setup(struct pvr2_hdw *,struct pvr2_i2c_client *); +#include "pvrusb2-hdw-internal.h" +void pvr2_msp3400_subdev_update(struct pvr2_hdw *, struct v4l2_subdev *); #endif /* __PVRUSB2_AUDIO_H */ /* diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c index aa2db330c..2a5911d39 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -38,6 +38,7 @@ #include "pvrusb2-fx2-cmd.h" #include "pvrusb2-wm8775.h" #include "pvrusb2-video-v4l.h" +#include "pvrusb2-audio.h" #include "compat.h" #define TV_MIN_FREQ 55250000L @@ -114,6 +115,7 @@ typedef void (*pvr2_subdev_update_func)(struct pvr2_hdw *, static const pvr2_subdev_update_func pvr2_module_update_functions[] = { [PVR2_CLIENT_ID_WM8775] = pvr2_wm8775_subdev_update, [PVR2_CLIENT_ID_SAA7115] = pvr2_saa7115_subdev_update, + [PVR2_CLIENT_ID_MSP3400] = pvr2_msp3400_subdev_update, }; static const char *module_names[] = { -- cgit v1.2.3 From a7ef36c95a0f966e2bc300a24046b8b38dca44fb Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Fri, 6 Mar 2009 21:52:42 -0600 Subject: pvrusb2: Fix silly 80 column issue From: Mike Isely Priority: normal Signed-off-by: Mike Isely --- linux/drivers/media/video/pvrusb2/pvrusb2-video-v4l.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-video-v4l.c b/linux/drivers/media/video/pvrusb2/pvrusb2-video-v4l.c index 6a0e207e6..09cc9eb7c 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-video-v4l.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-video-v4l.c @@ -264,7 +264,8 @@ void pvr2_saa7115_subdev_update(struct pvr2_hdw *hdw, struct v4l2_subdev *sd) } else { pvr2_trace(PVR2_TRACE_ERROR_LEGS, "*** WARNING *** subdev v4l2 set_input:" - " Invalid routing scheme (%u) and/or input (%d)", + " Invalid routing scheme (%u)" + " and/or input (%d)", sid, hdw->input_val); return; } -- cgit v1.2.3 From 32cc69a646b98851074dfb9a7cf5487954e79ea4 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Fri, 6 Mar 2009 21:54:02 -0600 Subject: pvrusb2: Tie in cx25840 sub-device support From: Mike Isely Priority: normal Signed-off-by: Mike Isely --- .../media/video/pvrusb2/pvrusb2-cx2584x-v4l.c | 52 ++++++++++++++++++---- .../media/video/pvrusb2/pvrusb2-cx2584x-v4l.h | 5 +++ linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c | 2 + 3 files changed, 51 insertions(+), 8 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c b/linux/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c index 750c379df..94986b9b0 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c @@ -40,14 +40,6 @@ #include #include "compat.h" -struct pvr2_v4l_cx2584x { - struct pvr2_i2c_handler handler; - struct pvr2_decoder_ctrl ctrl; - struct pvr2_i2c_client *client; - struct pvr2_hdw *hdw; - unsigned long stale_mask; -}; - struct routing_scheme_item { int vid; @@ -111,6 +103,15 @@ static const struct routing_scheme routing_schemes[] = { }, }; +struct pvr2_v4l_cx2584x { + struct pvr2_i2c_handler handler; + struct pvr2_decoder_ctrl ctrl; + struct pvr2_i2c_client *client; + struct pvr2_hdw *hdw; + unsigned long stale_mask; +}; + + static void set_input(struct pvr2_v4l_cx2584x *ctxt) { struct pvr2_hdw *hdw = ctxt->hdw; @@ -322,6 +323,41 @@ int pvr2_i2c_cx2584x_v4l_setup(struct pvr2_hdw *hdw, } +void pvr2_cx25840_subdev_update(struct pvr2_hdw *hdw, struct v4l2_subdev *sd) +{ + if (hdw->input_dirty) { + struct v4l2_routing route; + enum cx25840_video_input vid_input; + enum cx25840_audio_input aud_input; + const struct routing_scheme *sp; + unsigned int sid = hdw->hdw_desc->signal_routing_scheme; + + memset(&route, 0, sizeof(route)); + + if ((sid < ARRAY_SIZE(routing_schemes)) && + ((sp = routing_schemes + sid) != NULL) && + (hdw->input_val >= 0) && + (hdw->input_val < sp->cnt)) { + vid_input = sp->def[hdw->input_val].vid; + aud_input = sp->def[hdw->input_val].aud; + } else { + pvr2_trace(PVR2_TRACE_ERROR_LEGS, + "*** WARNING *** subdev cx2584x set_input:" + " Invalid routing scheme (%u)" + " and/or input (%d)", + sid, hdw->input_val); + return; + } + + pvr2_trace(PVR2_TRACE_CHIPS, + "i2c cx2584x set_input vid=0x%x aud=0x%x", + vid_input, aud_input); + route.input = (u32)vid_input; + sd->ops->video->s_routing(sd, &route); + route.input = (u32)aud_input; + sd->ops->audio->s_routing(sd, &route); + } +} diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.h b/linux/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.h index f664f5942..e48ce808b 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.h +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.h @@ -39,6 +39,11 @@ int pvr2_i2c_cx2584x_v4l_setup(struct pvr2_hdw *,struct pvr2_i2c_client *); +#include "pvrusb2-hdw-internal.h" + +void pvr2_cx25840_subdev_update(struct pvr2_hdw *, struct v4l2_subdev *sd); + + #endif /* __PVRUSB2_CX2584X_V4L_H */ /* diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c index 2a5911d39..fbc7083b4 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -38,6 +38,7 @@ #include "pvrusb2-fx2-cmd.h" #include "pvrusb2-wm8775.h" #include "pvrusb2-video-v4l.h" +#include "pvrusb2-cx2584x-v4l.h" #include "pvrusb2-audio.h" #include "compat.h" @@ -116,6 +117,7 @@ static const pvr2_subdev_update_func pvr2_module_update_functions[] = { [PVR2_CLIENT_ID_WM8775] = pvr2_wm8775_subdev_update, [PVR2_CLIENT_ID_SAA7115] = pvr2_saa7115_subdev_update, [PVR2_CLIENT_ID_MSP3400] = pvr2_msp3400_subdev_update, + [PVR2_CLIENT_ID_CX25840] = pvr2_cx25840_subdev_update, }; static const char *module_names[] = { -- cgit v1.2.3 From 58feddf524008cc0d6952c36103c4071e383e9f2 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Fri, 6 Mar 2009 21:56:52 -0600 Subject: pvrusb2: Implement more sub-device loading trace and improve error handling From: Mike Isely Priority: normal Signed-off-by: Mike Isely --- linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c | 26 +++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c index fbc7083b4..b6573731a 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -2026,6 +2026,10 @@ static int pvr2_hdw_load_subdev(struct pvr2_hdw *hdw, hdw->hdw_desc->description); return -EINVAL; } + pvr2_trace(PVR2_TRACE_INIT, + "Module ID %u (%s) for device %s being loaded...", + mid, fname, + hdw->hdw_desc->description); i2ccnt = pvr2_copy_i2c_addr_list(i2caddr, cd->i2c_address_list, ARRAY_SIZE(i2caddr)); @@ -2034,6 +2038,12 @@ static int pvr2_hdw_load_subdev(struct pvr2_hdw *hdw, /* Second chance: Try default i2c address list */ i2ccnt = pvr2_copy_i2c_addr_list(i2caddr, p, ARRAY_SIZE(i2caddr)); + if (i2ccnt) { + pvr2_trace(PVR2_TRACE_INIT, + "Module ID %u:" + " Using default i2c address list", + mid); + } } if (!i2ccnt) { @@ -2052,10 +2062,18 @@ static int pvr2_hdw_load_subdev(struct pvr2_hdw *hdw, * "chipid" appears to just be the module name again. So here we * just do the same thing. */ if (i2ccnt == 1) { + pvr2_trace(PVR2_TRACE_INIT, + "Module ID %u:" + " Setting up with specified i2c address 0x%x", + mid, i2caddr[0]); sd = v4l2_i2c_new_subdev(&hdw->i2c_adap, fname, fname, i2caddr[0]); } else { + pvr2_trace(PVR2_TRACE_INIT, + "Module ID %u:" + " Setting up with address probe list", + mid); sd = v4l2_i2c_new_probed_subdev(&hdw->i2c_adap, fname, fname, i2caddr); @@ -2078,7 +2096,7 @@ static int pvr2_hdw_load_subdev(struct pvr2_hdw *hdw, aid, in normal situations there's no reason for both mechanisms to be enabled. */ pvr2_i2c_untrack_subdev(hdw, sd); - pvr2_trace(PVR2_TRACE_INIT, "Attached sub-driver %s", fname); + pvr2_trace(PVR2_TRACE_INFO, "Attached sub-driver %s", fname); /* client-specific setup... */ @@ -2098,6 +2116,10 @@ static int pvr2_hdw_load_subdev(struct pvr2_hdw *hdw, up. */ struct v4l2_format fmt; + pvr2_trace(PVR2_TRACE_INIT, + "Module ID %u:" + " Executing cx25840 VBI hack", + mid); memset(&fmt, 0, sizeof(fmt)); fmt.type = V4L2_BUF_TYPE_SLICED_VBI_CAPTURE; v4l2_device_call_all(&hdw->v4l2_dev, mid, @@ -2128,7 +2150,7 @@ static void pvr2_hdw_load_modules(struct pvr2_hdw *hdw) ct = &hdw->hdw_desc->client_table; for (idx = 0; idx < ct->cnt; idx++) { - if (!pvr2_hdw_load_subdev(hdw, &ct->lst[idx])) okFl = 0; + if (pvr2_hdw_load_subdev(hdw, &ct->lst[idx]) < 0) okFl = 0; } if (!okFl) pvr2_hdw_render_useless(hdw); } -- cgit v1.2.3 From 0fd2fbc142962b497d3a0edd2ff43c07b085d674 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Fri, 6 Mar 2009 21:57:42 -0600 Subject: pvrusb2: Define default i2c address for wm8775 sub-device From: Mike Isely Priority: normal Signed-off-by: Mike Isely --- linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c | 1 + 1 file changed, 1 insertion(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c index b6573731a..3753c3cff 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -132,6 +132,7 @@ static const char *module_names[] = { static const unsigned char *module_i2c_addresses[] = { [PVR2_CLIENT_ID_TUNER] = "\x60\x61\x62\x63", + [PVR2_CLIENT_ID_WM8775] = "\x1b", }; -- cgit v1.2.3 From 98489577d3b3394896046026d693d350abf659c5 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Fri, 6 Mar 2009 22:37:58 -0600 Subject: pvrusb2: Fix uninitialized counter From: Mike Isely Priority: normal Signed-off-by: Mike Isely --- linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c index 3753c3cff..e6411e2c4 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -1996,7 +1996,7 @@ static unsigned int pvr2_copy_i2c_addr_list( unsigned short *dst, const unsigned char *src, unsigned int dst_max) { - unsigned int cnt; + unsigned int cnt = 0; if (!src) return 0; while (src[cnt] && (cnt + 1) < dst_max) { dst[cnt] = src[cnt]; -- cgit v1.2.3 From 0f62cc7a5dbd33059d58e9e944c6af741dcc0ce6 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Fri, 6 Mar 2009 22:39:40 -0600 Subject: pvrusb2: Fix bugs involved in listing of sub-devices From: Mike Isely Priority: normal Signed-off-by: Mike Isely --- linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c index e6411e2c4..8ac5b9f11 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -4951,7 +4951,7 @@ static unsigned int pvr2_hdw_report_unlocked(struct pvr2_hdw *hdw,int which, unsigned int id; ccnt = scnprintf(buf, acnt, - "Associted v4l2_subdev drivers:"); + "Associated v4l2_subdev drivers:"); tcnt += ccnt; v4l2_device_for_each_subdev(sd, &hdw->v4l2_dev) { id = sd->grp_id; @@ -4959,10 +4959,16 @@ static unsigned int pvr2_hdw_report_unlocked(struct pvr2_hdw *hdw,int which, if (id < ARRAY_SIZE(module_names)) { p = module_names[id]; } - if (!p) p = "(unknown)"; - ccnt = scnprintf(buf + tcnt, - acnt - tcnt, - " %s (%u)", p, id); + if (p) { + ccnt = scnprintf(buf + tcnt, + acnt - tcnt, + " %s", p); + } else { + ccnt = scnprintf(buf + tcnt, + acnt - tcnt, + " (unknown id=%u)", id); + } + tcnt += ccnt; } return tcnt; } -- cgit v1.2.3 From eece3353234a98e74f8d3a93f0b6f21d1950e45d Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Fri, 6 Mar 2009 22:42:40 -0600 Subject: pvrusb2: Allow sub-devices to insert correctly From: Mike Isely A sub-device won't successfully attach to our I2C adapter if its class isn't set to zero. Right the class is still set to I2C_CLASS_TV_ANALOG in order to allow the old mechanism to still work. This change temporarily sets the class to zero during the interval when the sub-device attaches. This code will get removed when the old i2c layer is finally removed from the driver. Priority: normal Signed-off-by: Mike Isely --- linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c index 8ac5b9f11..81afb6f87 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -2062,6 +2062,7 @@ static int pvr2_hdw_load_subdev(struct pvr2_hdw *hdw, * and every other place where I can find examples of this, the * "chipid" appears to just be the module name again. So here we * just do the same thing. */ + hdw->i2c_adap.class = 0; if (i2ccnt == 1) { pvr2_trace(PVR2_TRACE_INIT, "Module ID %u:" @@ -2079,6 +2080,7 @@ static int pvr2_hdw_load_subdev(struct pvr2_hdw *hdw, fname, fname, i2caddr); } + hdw->i2c_adap.class = I2C_CLASS_TV_ANALOG; if (!sd) { pvr2_trace(PVR2_TRACE_ERROR_LEGS, -- cgit v1.2.3 From bd4d80eea06a1b77b39fec47762370bb6cd6492f Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Fri, 6 Mar 2009 22:45:10 -0600 Subject: pvrusb2: Sub-device update must happen BEFORE state dirty bits are cleared From: Mike Isely The sub-device update mechanism relies on various "dirty" bits in the driver in order to know what pieces of state need to be propagated out to the various sub-devices. But that won't work if the dirty bits are cleared before the update gets a chance to run. This change ensures that the update takes place before the dirty bits are cleared. Priority: normal Signed-off-by: Mike Isely --- linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c index 81afb6f87..632fa7211 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -3262,15 +3262,15 @@ static int pvr2_hdw_commit_execute(struct pvr2_hdw *hdw) } } + /* Check and update state for all sub-devices. */ + pvr2_subdev_update(hdw); + for (idx = 0; idx < hdw->control_cnt; idx++) { cptr = hdw->controls + idx; if (!cptr->info->clear_dirty) continue; cptr->info->clear_dirty(cptr); } - /* Check and update state for all sub-devices. */ - pvr2_subdev_update(hdw); - /* Now execute i2c core update */ pvr2_i2c_core_sync(hdw); -- cgit v1.2.3 From d87e757220b43c2ffafac3e602c5f8ba8ebbcac5 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Fri, 6 Mar 2009 22:46:17 -0600 Subject: pvrusb2: Deal with space-after-comma coding style idiocy From: Mike Isely Priority: normal Signed-off-by: Mike Isely --- linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c index 632fa7211..675ce1664 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -2969,7 +2969,7 @@ static void pvr2_subdev_update(struct pvr2_hdw *hdw) pvr2_subdev_update_func fp; if (hdw->input_dirty || hdw->std_dirty) { - pvr2_trace(PVR2_TRACE_CHIPS,"subdev v4l2 set_standard"); + pvr2_trace(PVR2_TRACE_CHIPS, "subdev v4l2 set_standard"); if (hdw->input_val == PVR2_CVAL_INPUT_RADIO) { v4l2_device_call_all(&hdw->v4l2_dev, 0, tuner, s_radio); -- cgit v1.2.3 From d238333928061f1804de72a188640fcee8176bd9 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Fri, 6 Mar 2009 22:48:42 -0600 Subject: pvrusb2: Broadcast tuner type change to sub-devices From: Mike Isely The tuner sub-device isn't going to work very well unless we tell it the correct tuner type to use... Priority: normal Signed-off-by: Mike Isely --- linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c index 675ce1664..0e892a783 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -24,6 +24,7 @@ #include #include #include +#include #include "pvrusb2.h" #include "pvrusb2-std.h" #include "pvrusb2-util.h" @@ -2278,7 +2279,6 @@ static void pvr2_hdw_setup_low(struct pvr2_hdw *hdw) } pvr2_i2c_core_check_stale(hdw); - hdw->tuner_updated = 0; if (!pvr2_hdw_dev_ok(hdw)) return; @@ -2968,6 +2968,21 @@ static void pvr2_subdev_update(struct pvr2_hdw *hdw) unsigned int id; pvr2_subdev_update_func fp; + pvr2_trace(PVR2_TRACE_CHIPS, "subdev update..."); + + if (hdw->tuner_updated) { + struct tuner_setup setup; + pvr2_trace(PVR2_TRACE_CHIPS, "subdev tuner set_type(%d)", + hdw->tuner_type); + if (((int)(hdw->tuner_type)) >= 0) { + setup.addr = ADDR_UNSET; + setup.type = hdw->tuner_type; + setup.mode_mask = T_RADIO | T_ANALOG_TV; + v4l2_device_call_all(&hdw->v4l2_dev, 0, + tuner, s_type_addr, &setup); + } + } + if (hdw->input_dirty || hdw->std_dirty) { pvr2_trace(PVR2_TRACE_CHIPS, "subdev v4l2 set_standard"); if (hdw->input_val == PVR2_CVAL_INPUT_RADIO) { @@ -3265,6 +3280,7 @@ static int pvr2_hdw_commit_execute(struct pvr2_hdw *hdw) /* Check and update state for all sub-devices. */ pvr2_subdev_update(hdw); + hdw->tuner_updated = 0; for (idx = 0; idx < hdw->control_cnt; idx++) { cptr = hdw->controls + idx; if (!cptr->info->clear_dirty) continue; -- cgit v1.2.3 From 2d590f47db0a9ed1bfcb5210a1c5fd65d14842a6 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Fri, 6 Mar 2009 22:49:37 -0600 Subject: pvrusb2: Define default I2C address for cx25840 sub-device From: Mike Isely Priority: normal Signed-off-by: Mike Isely --- linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c | 1 + 1 file changed, 1 insertion(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c index 0e892a783..341e0aa85 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -134,6 +134,7 @@ static const char *module_names[] = { static const unsigned char *module_i2c_addresses[] = { [PVR2_CLIENT_ID_TUNER] = "\x60\x61\x62\x63", [PVR2_CLIENT_ID_WM8775] = "\x1b", + [PVR2_CLIENT_ID_CX25840] = "\x44", }; -- cgit v1.2.3 From c536aebeeeafcdb7e48316d0d029d35f0294dda7 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Fri, 6 Mar 2009 22:50:48 -0600 Subject: pvrusb2: Implement trace print for stream on / off action From: Mike Isely Priority: normal Signed-off-by: Mike Isely --- linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c index 341e0aa85..c27c841af 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -1691,6 +1691,8 @@ static int pvr2_decoder_enable(struct pvr2_hdw *hdw,int enablefl) this point, we'll broadcast stream on/off to all sub-devices anyway, just in case somebody else wants to hear the command... */ + pvr2_trace(PVR2_TRACE_CHIPS, "subdev v4l2 stream=%s", + (enablefl ? "on" : "off")); v4l2_device_call_all(&hdw->v4l2_dev, 0, video, s_stream, enablefl); if (hdw->decoder_client_id) { /* We get here if the encoder has been noticed. Otherwise -- cgit v1.2.3 From 1aee4a5d51f50e895af02d8e976d56656d65b58e Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Fri, 6 Mar 2009 22:51:54 -0600 Subject: pvrusb2: Correct some trace print inaccuracies From: Mike Isely Priority: normal Signed-off-by: Mike Isely --- linux/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c b/linux/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c index 94986b9b0..b73694e8c 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c @@ -325,6 +325,7 @@ int pvr2_i2c_cx2584x_v4l_setup(struct pvr2_hdw *hdw, void pvr2_cx25840_subdev_update(struct pvr2_hdw *hdw, struct v4l2_subdev *sd) { + pvr2_trace(PVR2_TRACE_CHIPS, "subdev cx2584x update..."); if (hdw->input_dirty) { struct v4l2_routing route; enum cx25840_video_input vid_input; @@ -350,7 +351,7 @@ void pvr2_cx25840_subdev_update(struct pvr2_hdw *hdw, struct v4l2_subdev *sd) } pvr2_trace(PVR2_TRACE_CHIPS, - "i2c cx2584x set_input vid=0x%x aud=0x%x", + "subdev cx2584x set_input vid=0x%x aud=0x%x", vid_input, aud_input); route.input = (u32)vid_input; sd->ops->video->s_routing(sd, &route); -- cgit v1.2.3 From 8299e0bc7422fc44591a910a1c011e959e623a1a Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Fri, 6 Mar 2009 22:57:25 -0600 Subject: pvrusb2: Implement mechanism to force a full sub-device update From: Mike Isely When a pvrusb2 driver instance first initializes, we need to be sure to send out a complete state update for everything to all attached modules. The old i2c layer did this by keeping a separate mask of "stale" bits for each attached module - and setting that mask to all stale when that module attaches. But the new sub-device adaptation I've implemented here no longer has per-module stale bits. So instead there's now a global "force dirty" bit that is set upon instance initialization, before the sub-devices are attached. After the first update, this bit is cleared, allowing for normal update-on-dirty behavior. In this manner, we ensure that all sub-devices have been properly synchronized at initialization. Priority: normal Signed-off-by: Mike Isely --- linux/drivers/media/video/pvrusb2/pvrusb2-audio.c | 2 +- .../media/video/pvrusb2/pvrusb2-cx2584x-v4l.c | 2 +- .../media/video/pvrusb2/pvrusb2-hdw-internal.h | 1 + linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c | 21 ++++++++++++--------- .../drivers/media/video/pvrusb2/pvrusb2-video-v4l.c | 2 +- linux/drivers/media/video/pvrusb2/pvrusb2-wm8775.c | 2 +- 6 files changed, 17 insertions(+), 13 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-audio.c b/linux/drivers/media/video/pvrusb2/pvrusb2-audio.c index 6e63d56bd..5eef93b50 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-audio.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-audio.c @@ -185,7 +185,7 @@ int pvr2_i2c_msp3400_setup(struct pvr2_hdw *hdw,struct pvr2_i2c_client *cp) void pvr2_msp3400_subdev_update(struct pvr2_hdw *hdw, struct v4l2_subdev *sd) { - if (hdw->input_dirty) { + if (hdw->input_dirty || hdw->force_dirty) { struct v4l2_routing route; const struct routing_scheme *sp; unsigned int sid = hdw->hdw_desc->signal_routing_scheme; diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c b/linux/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c index b73694e8c..c32d4a1cb 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c @@ -326,7 +326,7 @@ int pvr2_i2c_cx2584x_v4l_setup(struct pvr2_hdw *hdw, void pvr2_cx25840_subdev_update(struct pvr2_hdw *hdw, struct v4l2_subdev *sd) { pvr2_trace(PVR2_TRACE_CHIPS, "subdev cx2584x update..."); - if (hdw->input_dirty) { + if (hdw->input_dirty || hdw->force_dirty) { struct v4l2_routing route; enum cx25840_video_input vid_input; enum cx25840_audio_input aud_input; diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h index 299bf58ad..2afbd9bce 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h @@ -288,6 +288,7 @@ struct pvr2_hdw { wait_queue_head_t state_wait_data; + int force_dirty; /* consider all controls dirty if true */ int flag_ok; /* device in known good state */ int flag_disconnected; /* flag_ok == 0 due to disconnect */ int flag_init_ok; /* true if structure is fully initialized */ diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c index c27c841af..c4cb3b5e4 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -2202,6 +2202,8 @@ static void pvr2_hdw_setup_low(struct pvr2_hdw *hdw) if (!pvr2_hdw_dev_ok(hdw)) return; + hdw->force_dirty = !0; + if (!hdw->hdw_desc->flag_no_powerup) { pvr2_hdw_cmd_powerup(hdw); if (!pvr2_hdw_dev_ok(hdw)) return; @@ -2959,7 +2961,7 @@ static void pvr2_subdev_set_control(struct pvr2_hdw *hdw, int id, } #define PVR2_SUBDEV_SET_CONTROL(hdw, id, lab) \ - if ((hdw)->lab##_dirty) { \ + if ((hdw)->lab##_dirty || (hdw)->force_dirty) { \ pvr2_subdev_set_control(hdw, id, #lab, (hdw)->lab##_val); \ } @@ -2973,7 +2975,7 @@ static void pvr2_subdev_update(struct pvr2_hdw *hdw) pvr2_trace(PVR2_TRACE_CHIPS, "subdev update..."); - if (hdw->tuner_updated) { + if (hdw->tuner_updated || hdw->force_dirty) { struct tuner_setup setup; pvr2_trace(PVR2_TRACE_CHIPS, "subdev tuner set_type(%d)", hdw->tuner_type); @@ -2986,7 +2988,7 @@ static void pvr2_subdev_update(struct pvr2_hdw *hdw) } } - if (hdw->input_dirty || hdw->std_dirty) { + if (hdw->input_dirty || hdw->std_dirty || hdw->force_dirty) { pvr2_trace(PVR2_TRACE_CHIPS, "subdev v4l2 set_standard"); if (hdw->input_val == PVR2_CVAL_INPUT_RADIO) { v4l2_device_call_all(&hdw->v4l2_dev, 0, @@ -3011,14 +3013,14 @@ static void pvr2_subdev_update(struct pvr2_hdw *hdw) PVR2_SUBDEV_SET_CONTROL(hdw, V4L2_CID_AUDIO_BASS, bass); PVR2_SUBDEV_SET_CONTROL(hdw, V4L2_CID_AUDIO_TREBLE, treble); - if (hdw->input_dirty || hdw->audiomode_dirty) { + if (hdw->input_dirty || hdw->audiomode_dirty || hdw->force_dirty) { struct v4l2_tuner vt; memset(&vt, 0, sizeof(vt)); vt.audmode = hdw->audiomode_val; v4l2_device_call_all(&hdw->v4l2_dev, 0, tuner, s_tuner, &vt); } - if (hdw->freqDirty) { + if (hdw->freqDirty || hdw->force_dirty) { unsigned long fv; struct v4l2_frequency freq; fv = pvr2_hdw_get_cur_freq(hdw); @@ -3043,7 +3045,7 @@ static void pvr2_subdev_update(struct pvr2_hdw *hdw) s_frequency, &freq); } - if (hdw->res_hor_dirty || hdw->res_ver_dirty) { + if (hdw->res_hor_dirty || hdw->res_ver_dirty || hdw->force_dirty) { struct v4l2_format fmt; memset(&fmt, 0, sizeof(fmt)); fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; @@ -3054,7 +3056,7 @@ static void pvr2_subdev_update(struct pvr2_hdw *hdw) v4l2_device_call_all(&hdw->v4l2_dev, 0, video, s_fmt, &fmt); } - if (hdw->srate_dirty) { + if (hdw->srate_dirty || hdw->force_dirty) { u32 val; pvr2_trace(PVR2_TRACE_CHIPS, "subdev v4l2 set_audio %d", hdw->srate_val); @@ -3085,7 +3087,7 @@ static void pvr2_subdev_update(struct pvr2_hdw *hdw) (*fp)(hdw, sd); } - if (hdw->tuner_signal_stale && hdw->cropcap_stale) { + if (hdw->tuner_signal_stale || hdw->cropcap_stale) { pvr2_hdw_status_poll(hdw); } } @@ -3099,7 +3101,7 @@ static int pvr2_hdw_commit_setup(struct pvr2_hdw *hdw) unsigned int idx; struct pvr2_ctrl *cptr; int value; - int commit_flag = 0; + int commit_flag = hdw->force_dirty; char buf[100]; unsigned int bcnt,ccnt; @@ -3284,6 +3286,7 @@ static int pvr2_hdw_commit_execute(struct pvr2_hdw *hdw) pvr2_subdev_update(hdw); hdw->tuner_updated = 0; + hdw->force_dirty = 0; for (idx = 0; idx < hdw->control_cnt; idx++) { cptr = hdw->controls + idx; if (!cptr->info->clear_dirty) continue; diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-video-v4l.c b/linux/drivers/media/video/pvrusb2/pvrusb2-video-v4l.c index 09cc9eb7c..a60637ae7 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-video-v4l.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-video-v4l.c @@ -250,7 +250,7 @@ int pvr2_i2c_decoder_v4l_setup(struct pvr2_hdw *hdw, void pvr2_saa7115_subdev_update(struct pvr2_hdw *hdw, struct v4l2_subdev *sd) { - if (hdw->input_dirty) { + if (hdw->input_dirty || hdw->force_dirty) { struct v4l2_routing route; const struct routing_scheme *sp; unsigned int sid = hdw->hdw_desc->signal_routing_scheme; diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-wm8775.c b/linux/drivers/media/video/pvrusb2/pvrusb2-wm8775.c index 8fabc2c29..e2b949102 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-wm8775.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-wm8775.c @@ -163,7 +163,7 @@ int pvr2_i2c_wm8775_setup(struct pvr2_hdw *hdw,struct pvr2_i2c_client *cp) void pvr2_wm8775_subdev_update(struct pvr2_hdw *hdw, struct v4l2_subdev *sd) { - if (hdw->input_dirty) { + if (hdw->input_dirty || hdw->force_dirty) { struct v4l2_routing route; memset(&route, 0, sizeof(route)); -- cgit v1.2.3 From 4d479b4a45faee008fde536747affbf070d28379 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Fri, 6 Mar 2009 22:59:34 -0600 Subject: pvrusb2: Issue required core init broadcast to all sub-devices From: Mike Isely The v4l2-subdev infrastructure requires that an initialization call must be issued to all attached sub-devices before normal operation can start. This change satisfies that requirement. Priority: normal Signed-off-by: Mike Isely --- linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c index c4cb3b5e4..8e368e004 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -2225,6 +2225,8 @@ static void pvr2_hdw_setup_low(struct pvr2_hdw *hdw) pvr2_hdw_load_modules(hdw); if (!pvr2_hdw_dev_ok(hdw)) return; + v4l2_device_call_all(&hdw->v4l2_dev, 0, core, init, 0); + for (idx = 0; idx < CTRLDEF_COUNT; idx++) { cptr = hdw->controls + idx; if (cptr->info->skip_init) continue; -- cgit v1.2.3 From ec1b93f7a0f4ab3340349ce00eb6f5a4e486b0a6 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Fri, 6 Mar 2009 23:00:21 -0600 Subject: pvrusb2: Define default I2C addresses for msp3400 and saa7115 sub-devices From: Mike Isely Priority: normal Signed-off-by: Mike Isely --- linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c index 8e368e004..22948b5b6 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -133,6 +133,8 @@ static const char *module_names[] = { static const unsigned char *module_i2c_addresses[] = { [PVR2_CLIENT_ID_TUNER] = "\x60\x61\x62\x63", + [PVR2_CLIENT_ID_MSP3400] = "\x40", + [PVR2_CLIENT_ID_SAA7115] = "\x21", [PVR2_CLIENT_ID_WM8775] = "\x1b", [PVR2_CLIENT_ID_CX25840] = "\x44", }; -- cgit v1.2.3 From ff7178ecb7762433d0d52745ac42c2e8b70d7df0 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Fri, 6 Mar 2009 23:02:32 -0600 Subject: pvrusb2: Fix incorrectly named sub-device ID From: Mike Isely Priority: normal Signed-off-by: Mike Isely --- linux/drivers/media/video/pvrusb2/pvrusb2-devattr.h | 2 +- linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-devattr.h b/linux/drivers/media/video/pvrusb2/pvrusb2-devattr.h index 1339a32a2..30aa7a440 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-devattr.h +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-devattr.h @@ -38,7 +38,7 @@ #define PVR2_CLIENT_ID_CX25840 2 #define PVR2_CLIENT_ID_SAA7115 3 #define PVR2_CLIENT_ID_TUNER 4 -#define PVR2_CLIENT_ID_CS53132A 5 +#define PVR2_CLIENT_ID_CS53L32A 5 #define PVR2_CLIENT_ID_WM8775 6 struct pvr2_device_client_desc { diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c index 22948b5b6..1d807238c 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -126,7 +126,7 @@ static const char *module_names[] = { [PVR2_CLIENT_ID_CX25840] = "cx25840", [PVR2_CLIENT_ID_SAA7115] = "saa7115", [PVR2_CLIENT_ID_TUNER] = "tuner", - [PVR2_CLIENT_ID_CS53132A] = "cs53132a", + [PVR2_CLIENT_ID_CS53L32A] = "cs53l32a", [PVR2_CLIENT_ID_WM8775] = "wm8775", }; -- cgit v1.2.3 From 401e4b9b2f24e11c9967c925645d03994fbbef37 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Fri, 6 Mar 2009 23:03:28 -0600 Subject: pvrusb2: Define default I2C address for CS53L32A sub-device From: Mike Isely Priority: normal Signed-off-by: Mike Isely --- linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c | 1 + 1 file changed, 1 insertion(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c index 1d807238c..f82335122 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -137,6 +137,7 @@ static const unsigned char *module_i2c_addresses[] = { [PVR2_CLIENT_ID_SAA7115] = "\x21", [PVR2_CLIENT_ID_WM8775] = "\x1b", [PVR2_CLIENT_ID_CX25840] = "\x44", + [PVR2_CLIENT_ID_CS53L32A] = "\x11", }; -- cgit v1.2.3 From 944644eb136dcfcb3dc5e88e1cee6f3007313eda Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Fri, 6 Mar 2009 23:07:12 -0600 Subject: pvrusb2: Convert all device definitions to use new sub-device declarations From: Mike Isely Priority: normal Signed-off-by: Mike Isely --- .../drivers/media/video/pvrusb2/pvrusb2-devattr.c | 86 +++++++++++----------- 1 file changed, 41 insertions(+), 45 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-devattr.c b/linux/drivers/media/video/pvrusb2/pvrusb2-devattr.c index cbe2a3417..de4daa7f4 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-devattr.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-devattr.c @@ -46,10 +46,10 @@ pvr2_device_desc structures. /*------------------------------------------------------------------------*/ /* Hauppauge PVR-USB2 Model 29xxx */ -static const char *pvr2_client_29xxx[] = { - "msp3400", - "saa7115", - "tuner", +static const struct pvr2_device_client_desc pvr2_cli_29xxx[] = { + { .module_id = PVR2_CLIENT_ID_SAA7115 }, + { .module_id = PVR2_CLIENT_ID_MSP3400 }, + { .module_id = PVR2_CLIENT_ID_TUNER }, }; static const char *pvr2_fw1_names_29xxx[] = { @@ -59,8 +59,8 @@ static const char *pvr2_fw1_names_29xxx[] = { static const struct pvr2_device_desc pvr2_device_29xxx = { .description = "WinTV PVR USB2 Model Category 29xxx", .shortname = "29xxx", - .client_modules.lst = pvr2_client_29xxx, - .client_modules.cnt = ARRAY_SIZE(pvr2_client_29xxx), + .client_table.lst = pvr2_cli_29xxx, + .client_table.cnt = ARRAY_SIZE(pvr2_cli_29xxx), .fx2_firmware.lst = pvr2_fw1_names_29xxx, .fx2_firmware.cnt = ARRAY_SIZE(pvr2_fw1_names_29xxx), .flag_has_hauppauge_rom = !0, @@ -77,10 +77,10 @@ static const struct pvr2_device_desc pvr2_device_29xxx = { /*------------------------------------------------------------------------*/ /* Hauppauge PVR-USB2 Model 24xxx */ -static const char *pvr2_client_24xxx[] = { - "cx25840", - "tuner", - "wm8775", +static const struct pvr2_device_client_desc pvr2_cli_24xxx[] = { + { .module_id = PVR2_CLIENT_ID_CX25840 }, + { .module_id = PVR2_CLIENT_ID_TUNER }, + { .module_id = PVR2_CLIENT_ID_WM8775 }, }; static const char *pvr2_fw1_names_24xxx[] = { @@ -90,8 +90,8 @@ static const char *pvr2_fw1_names_24xxx[] = { static const struct pvr2_device_desc pvr2_device_24xxx = { .description = "WinTV PVR USB2 Model Category 24xxx", .shortname = "24xxx", - .client_modules.lst = pvr2_client_24xxx, - .client_modules.cnt = ARRAY_SIZE(pvr2_client_24xxx), + .client_table.lst = pvr2_cli_24xxx, + .client_table.cnt = ARRAY_SIZE(pvr2_cli_24xxx), .fx2_firmware.lst = pvr2_fw1_names_24xxx, .fx2_firmware.cnt = ARRAY_SIZE(pvr2_fw1_names_24xxx), .flag_has_cx25840 = !0, @@ -111,16 +111,16 @@ static const struct pvr2_device_desc pvr2_device_24xxx = { /*------------------------------------------------------------------------*/ /* GOTVIEW USB2.0 DVD2 */ -static const char *pvr2_client_gotview_2[] = { - "cx25840", - "tuner", +static const struct pvr2_device_client_desc pvr2_cli_gotview_2[] = { + { .module_id = PVR2_CLIENT_ID_CX25840 }, + { .module_id = PVR2_CLIENT_ID_TUNER }, }; static const struct pvr2_device_desc pvr2_device_gotview_2 = { .description = "Gotview USB 2.0 DVD 2", .shortname = "gv2", - .client_modules.lst = pvr2_client_gotview_2, - .client_modules.cnt = ARRAY_SIZE(pvr2_client_gotview_2), + .client_table.lst = pvr2_cli_gotview_2, + .client_table.cnt = ARRAY_SIZE(pvr2_cli_gotview_2), .flag_has_cx25840 = !0, .default_tuner_type = TUNER_PHILIPS_FM1216ME_MK3, .flag_has_analogtuner = !0, @@ -140,8 +140,8 @@ static const struct pvr2_device_desc pvr2_device_gotview_2 = { static const struct pvr2_device_desc pvr2_device_gotview_2d = { .description = "Gotview USB 2.0 DVD Deluxe", .shortname = "gv2d", - .client_modules.lst = pvr2_client_gotview_2, - .client_modules.cnt = ARRAY_SIZE(pvr2_client_gotview_2), + .client_table.lst = pvr2_cli_gotview_2, + .client_table.cnt = ARRAY_SIZE(pvr2_cli_gotview_2), .flag_has_cx25840 = !0, .default_tuner_type = TUNER_PHILIPS_FM1216ME_MK3, .flag_has_analogtuner = !0, @@ -187,17 +187,17 @@ static struct pvr2_dvb_props pvr2_onair_creator_fe_props = { }; #endif -static const char *pvr2_client_onair_creator[] = { - "saa7115", - "tuner", - "cs53l32a", +static const struct pvr2_device_client_desc pvr2_cli_onair_creator[] = { + { .module_id = PVR2_CLIENT_ID_SAA7115 }, + { .module_id = PVR2_CLIENT_ID_CS53L32A }, + { .module_id = PVR2_CLIENT_ID_TUNER }, }; static const struct pvr2_device_desc pvr2_device_onair_creator = { .description = "OnAir Creator Hybrid USB tuner", .shortname = "oac", - .client_modules.lst = pvr2_client_onair_creator, - .client_modules.cnt = ARRAY_SIZE(pvr2_client_onair_creator), + .client_table.lst = pvr2_cli_onair_creator, + .client_table.cnt = ARRAY_SIZE(pvr2_cli_onair_creator), .default_tuner_type = TUNER_LG_TDVS_H06XF, .flag_has_analogtuner = !0, .flag_has_composite = !0, @@ -247,17 +247,17 @@ static struct pvr2_dvb_props pvr2_onair_usb2_fe_props = { }; #endif -static const char *pvr2_client_onair_usb2[] = { - "saa7115", - "tuner", - "cs53l32a", +static const struct pvr2_device_client_desc pvr2_cli_onair_usb2[] = { + { .module_id = PVR2_CLIENT_ID_SAA7115 }, + { .module_id = PVR2_CLIENT_ID_CS53L32A }, + { .module_id = PVR2_CLIENT_ID_TUNER }, }; static const struct pvr2_device_desc pvr2_device_onair_usb2 = { .description = "OnAir USB2 Hybrid USB tuner", .shortname = "oa2", - .client_modules.lst = pvr2_client_onair_usb2, - .client_modules.cnt = ARRAY_SIZE(pvr2_client_onair_usb2), + .client_table.lst = pvr2_cli_onair_usb2, + .client_table.cnt = ARRAY_SIZE(pvr2_cli_onair_usb2), .default_tuner_type = TUNER_PHILIPS_FCV1236D, .flag_has_analogtuner = !0, .flag_has_composite = !0, @@ -320,9 +320,10 @@ static struct pvr2_dvb_props pvr2_73xxx_dvb_props = { }; #endif -static const char *pvr2_client_73xxx[] = { - "cx25840", - "tuner", +static const struct pvr2_device_client_desc pvr2_cli_73xxx[] = { + { .module_id = PVR2_CLIENT_ID_CX25840 }, + { .module_id = PVR2_CLIENT_ID_TUNER, + .i2c_address_list = "\x42"}, }; static const char *pvr2_fw1_names_73xxx[] = { @@ -332,8 +333,8 @@ static const char *pvr2_fw1_names_73xxx[] = { static const struct pvr2_device_desc pvr2_device_73xxx = { .description = "WinTV HVR-1900 Model Category 73xxx", .shortname = "73xxx", - .client_modules.lst = pvr2_client_73xxx, - .client_modules.cnt = ARRAY_SIZE(pvr2_client_73xxx), + .client_table.lst = pvr2_cli_73xxx, + .client_table.cnt = ARRAY_SIZE(pvr2_cli_73xxx), .fx2_firmware.lst = pvr2_fw1_names_73xxx, .fx2_firmware.cnt = ARRAY_SIZE(pvr2_fw1_names_73xxx), .flag_has_cx25840 = !0, @@ -429,11 +430,6 @@ static struct pvr2_dvb_props pvr2_751xx_dvb_props = { }; #endif -static const char *pvr2_client_75xxx[] = { - "cx25840", - "tuner", -}; - static const char *pvr2_fw1_names_75xxx[] = { "v4l-pvrusb2-73xxx-01.fw", }; @@ -441,8 +437,8 @@ static const char *pvr2_fw1_names_75xxx[] = { static const struct pvr2_device_desc pvr2_device_750xx = { .description = "WinTV HVR-1950 Model Category 750xx", .shortname = "750xx", - .client_modules.lst = pvr2_client_75xxx, - .client_modules.cnt = ARRAY_SIZE(pvr2_client_75xxx), + .client_table.lst = pvr2_cli_73xxx, + .client_table.cnt = ARRAY_SIZE(pvr2_cli_73xxx), .fx2_firmware.lst = pvr2_fw1_names_75xxx, .fx2_firmware.cnt = ARRAY_SIZE(pvr2_fw1_names_75xxx), .flag_has_cx25840 = !0, @@ -463,8 +459,8 @@ static const struct pvr2_device_desc pvr2_device_750xx = { static const struct pvr2_device_desc pvr2_device_751xx = { .description = "WinTV HVR-1950 Model Category 751xx", .shortname = "751xx", - .client_modules.lst = pvr2_client_75xxx, - .client_modules.cnt = ARRAY_SIZE(pvr2_client_75xxx), + .client_table.lst = pvr2_cli_73xxx, + .client_table.cnt = ARRAY_SIZE(pvr2_cli_73xxx), .fx2_firmware.lst = pvr2_fw1_names_75xxx, .fx2_firmware.cnt = ARRAY_SIZE(pvr2_fw1_names_75xxx), .flag_has_cx25840 = !0, -- cgit v1.2.3 From f48d9c5b647ccfda47dc431fb0b8ca9aa5f0327e Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Fri, 6 Mar 2009 23:08:58 -0600 Subject: pvrusb2: Make a bunch of dvb config structures const (trivial) From: Mike Isely Priority: normal Signed-off-by: Mike Isely --- linux/drivers/media/video/pvrusb2/pvrusb2-devattr.c | 10 +++++----- linux/drivers/media/video/pvrusb2/pvrusb2-devattr.h | 2 +- linux/drivers/media/video/pvrusb2/pvrusb2-dvb.c | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-devattr.c b/linux/drivers/media/video/pvrusb2/pvrusb2-devattr.c index de4daa7f4..e6c876f3a 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-devattr.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-devattr.c @@ -181,7 +181,7 @@ static int pvr2_lgh06xf_attach(struct pvr2_dvb_adapter *adap) return 0; } -static struct pvr2_dvb_props pvr2_onair_creator_fe_props = { +static const struct pvr2_dvb_props pvr2_onair_creator_fe_props = { .frontend_attach = pvr2_lgdt3303_attach, .tuner_attach = pvr2_lgh06xf_attach, }; @@ -241,7 +241,7 @@ static int pvr2_fcv1236d_attach(struct pvr2_dvb_adapter *adap) return 0; } -static struct pvr2_dvb_props pvr2_onair_usb2_fe_props = { +static const struct pvr2_dvb_props pvr2_onair_usb2_fe_props = { .frontend_attach = pvr2_lgdt3302_attach, .tuner_attach = pvr2_fcv1236d_attach, }; @@ -314,7 +314,7 @@ static int pvr2_73xxx_tda18271_8295_attach(struct pvr2_dvb_adapter *adap) return 0; } -static struct pvr2_dvb_props pvr2_73xxx_dvb_props = { +static const struct pvr2_dvb_props pvr2_73xxx_dvb_props = { .frontend_attach = pvr2_tda10048_attach, .tuner_attach = pvr2_73xxx_tda18271_8295_attach, }; @@ -419,12 +419,12 @@ static int pvr2_tda18271_8295_attach(struct pvr2_dvb_adapter *adap) return 0; } -static struct pvr2_dvb_props pvr2_750xx_dvb_props = { +static const struct pvr2_dvb_props pvr2_750xx_dvb_props = { .frontend_attach = pvr2_s5h1409_attach, .tuner_attach = pvr2_tda18271_8295_attach, }; -static struct pvr2_dvb_props pvr2_751xx_dvb_props = { +static const struct pvr2_dvb_props pvr2_751xx_dvb_props = { .frontend_attach = pvr2_s5h1411_attach, .tuner_attach = pvr2_tda18271_8295_attach, }; diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-devattr.h b/linux/drivers/media/video/pvrusb2/pvrusb2-devattr.h index 30aa7a440..ed9cdedcc 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-devattr.h +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-devattr.h @@ -103,7 +103,7 @@ struct pvr2_device_desc { #ifdef CONFIG_VIDEO_PVRUSB2_DVB /* callback functions to handle attachment of digital tuner & demod */ - struct pvr2_dvb_props *dvb_props; + const struct pvr2_dvb_props *dvb_props; #endif /* Initial standard bits to use for this device, if not zero. diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-dvb.c b/linux/drivers/media/video/pvrusb2/pvrusb2-dvb.c index 29d18e867..14decf216 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-dvb.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-dvb.c @@ -326,7 +326,7 @@ static int pvr2_dvb_adapter_exit(struct pvr2_dvb_adapter *adap) static int pvr2_dvb_frontend_init(struct pvr2_dvb_adapter *adap) { struct pvr2_hdw *hdw = adap->channel.hdw; - struct pvr2_dvb_props *dvb_props = hdw->hdw_desc->dvb_props; + const struct pvr2_dvb_props *dvb_props = hdw->hdw_desc->dvb_props; int ret = 0; if (dvb_props == NULL) { -- cgit v1.2.3 From d614c15a04ddb5279914b53ae97b37d9d50e80f9 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Fri, 6 Mar 2009 23:11:12 -0600 Subject: pvrusb2: Fix space-after-comma idiocy From: Mike Isely Priority: normal Signed-off-by: Mike Isely --- linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c index f82335122..f1e7c48eb 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -3056,7 +3056,7 @@ static void pvr2_subdev_update(struct pvr2_hdw *hdw) fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; fmt.fmt.pix.width = hdw->res_hor_val; fmt.fmt.pix.height = hdw->res_ver_val; - pvr2_trace(PVR2_TRACE_CHIPS,"subdev v4l2 set_size(%dx%d)", + pvr2_trace(PVR2_TRACE_CHIPS, "subdev v4l2 set_size(%dx%d)", fmt.fmt.pix.width, fmt.fmt.pix.height); v4l2_device_call_all(&hdw->v4l2_dev, 0, video, s_fmt, &fmt); } -- cgit v1.2.3 From 899781b36c5d5e792a6eaa9e0ad594fab9b9a430 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 7 Mar 2009 17:10:43 +0100 Subject: tlv320aic23b: use v4l2-i2c-drv.h instead of drv-legacy.h From: Hans Verkuil This driver isn't used in any legacy mode, so no need for v4l2-i2c-drv-legacy.h. Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/tlv320aic23b.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/tlv320aic23b.c b/linux/drivers/media/video/tlv320aic23b.c index 46671fb87..1eac4f7e7 100644 --- a/linux/drivers/media/video/tlv320aic23b.c +++ b/linux/drivers/media/video/tlv320aic23b.c @@ -31,16 +31,18 @@ #include #include #include -#include +#include #include "compat.h" MODULE_DESCRIPTION("tlv320aic23b driver"); MODULE_AUTHOR("Scott Alfter, Ulf Eklund, Hans Verkuil"); MODULE_LICENSE("GPL"); +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22) static unsigned short normal_i2c[] = { 0x34 >> 1, I2C_CLIENT_END }; I2C_CLIENT_INSMOD; +#endif /* ----------------------------------------------------------------------- */ -- cgit v1.2.3 From 1455fd856dbf6a576a6e896dfd0aa2ee818158f3 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sun, 8 Mar 2009 14:35:23 +0100 Subject: v4l2-ioctl: fix partial-copy code. From: Hans Verkuil The code to optimize the usercopy only checked the ioctl NR field. However, this code is also called for non-V4L2 ioctls (either private or ioctls from linux/dvb/audio.h and linux/dvb/video.h for decoder drivers like ivtv). If such an ioctl has the same NR as a V4L2 ioctl, then disaster strikes. Modified the code to check on the full command ID. Thanks to Martin Dauskardt for tracing the ivtv breakage to this particular change. Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/v4l2-ioctl.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/v4l2-ioctl.c b/linux/drivers/media/video/v4l2-ioctl.c index fa7d49482..21d93192d 100644 --- a/linux/drivers/media/video/v4l2-ioctl.c +++ b/linux/drivers/media/video/v4l2-ioctl.c @@ -1810,11 +1810,12 @@ static long __video_do_ioctl(struct file *file, static unsigned long cmd_input_size(unsigned int cmd) { /* Size of structure up to and including 'field' */ -#define CMDINSIZE(cmd, type, field) case _IOC_NR(VIDIOC_##cmd): return \ - offsetof(struct v4l2_##type, field) + \ - sizeof(((struct v4l2_##type *)0)->field); +#define CMDINSIZE(cmd, type, field) \ + case VIDIOC_##cmd: \ + return offsetof(struct v4l2_##type, field) + \ + sizeof(((struct v4l2_##type *)0)->field); - switch (_IOC_NR(cmd)) { + switch (cmd) { CMDINSIZE(ENUM_FMT, fmtdesc, type); CMDINSIZE(G_FMT, format, type); CMDINSIZE(QUERYBUF, buffer, type); -- cgit v1.2.3 From 70e434a0770289c85c4cf61a2956160e24d76bcf Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sun, 8 Mar 2009 21:04:38 +0100 Subject: zoran/bt819: use new notify functionality. From: Hans Verkuil Bt819 needs the parent driver to drive a GPIO pin low and high in order to reset its fifo. Use the new notify callback for this. Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/bt819.c | 14 +++++++++- linux/drivers/media/video/zoran/zoran_card.c | 22 +++++++++++++--- linux/drivers/media/video/zoran/zoran_device.c | 36 ++------------------------ linux/drivers/media/video/zoran/zoran_device.h | 3 --- linux/drivers/media/video/zoran/zoran_driver.c | 12 ++++----- 5 files changed, 39 insertions(+), 48 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/bt819.c b/linux/drivers/media/video/bt819.c index ec64197e9..a024783e5 100644 --- a/linux/drivers/media/video/bt819.c +++ b/linux/drivers/media/video/bt819.c @@ -32,13 +32,14 @@ #include #include #include -#include +#include #include #include #include #include #include #include +#include #include "compat.h" MODULE_DESCRIPTION("Brooktree-819 video decoder driver"); @@ -256,7 +257,11 @@ static int bt819_s_std(struct v4l2_subdev *sd, v4l2_std_id std) v4l2_dbg(1, debug, sd, "set norm %llx\n", std); + if (sd->v4l2_dev == NULL || sd->v4l2_dev->notify == NULL) + v4l2_err(sd, "no notify found!\n"); + if (std & V4L2_STD_NTSC) { + v4l2_subdev_notify(sd, BT819_FIFO_RESET_LOW, 0); bt819_setbit(decoder, 0x01, 0, 1); bt819_setbit(decoder, 0x01, 1, 0); bt819_setbit(decoder, 0x01, 5, 0); @@ -265,6 +270,7 @@ static int bt819_s_std(struct v4l2_subdev *sd, v4l2_std_id std) /* bt819_setbit(decoder, 0x1a, 5, 1); */ timing = &timing_data[1]; } else if (std & V4L2_STD_PAL) { + v4l2_subdev_notify(sd, BT819_FIFO_RESET_LOW, 0); bt819_setbit(decoder, 0x01, 0, 1); bt819_setbit(decoder, 0x01, 1, 1); bt819_setbit(decoder, 0x01, 5, 1); @@ -288,6 +294,7 @@ static int bt819_s_std(struct v4l2_subdev *sd, v4l2_std_id std) bt819_write(decoder, 0x08, (timing->hscale >> 8) & 0xff); bt819_write(decoder, 0x09, timing->hscale & 0xff); decoder->norm = std; + v4l2_subdev_notify(sd, BT819_FIFO_RESET_HIGH, 0); return 0; } @@ -300,7 +307,11 @@ static int bt819_s_routing(struct v4l2_subdev *sd, const struct v4l2_routing *ro if (route->input < 0 || route->input > 7) return -EINVAL; + if (sd->v4l2_dev == NULL || sd->v4l2_dev->notify == NULL) + v4l2_err(sd, "no notify found!\n"); + if (decoder->input != route->input) { + v4l2_subdev_notify(sd, BT819_FIFO_RESET_LOW, 0); decoder->input = route->input; /* select mode */ if (decoder->input == 0) { @@ -310,6 +321,7 @@ static int bt819_s_routing(struct v4l2_subdev *sd, const struct v4l2_routing *ro bt819_setbit(decoder, 0x0b, 6, 1); bt819_setbit(decoder, 0x1a, 1, 0); } + v4l2_subdev_notify(sd, BT819_FIFO_RESET_HIGH, 0); } return 0; } diff --git a/linux/drivers/media/video/zoran/zoran_card.c b/linux/drivers/media/video/zoran/zoran_card.c index 57cc62d82..4bd73d3ae 100644 --- a/linux/drivers/media/video/zoran/zoran_card.c +++ b/linux/drivers/media/video/zoran/zoran_card.c @@ -38,9 +38,7 @@ #include #include #include -#include "compat.h" #include -#include #include #include #include @@ -49,8 +47,10 @@ #include #include #include - -#include +#include +#include +#include +#include "compat.h" #include "videocodec.h" #include "zoran.h" @@ -1201,6 +1201,19 @@ zoran_setup_videocodec (struct zoran *zr, return m; } +static int zoran_subdev_notify(struct v4l2_subdev *sd, unsigned int cmd, void *arg) +{ + struct zoran *zr = to_zoran(sd->v4l2_dev); + + /* Bt819 needs to reset its FIFO buffer using #FRST pin and + LML33 card uses GPIO(7) for that. */ + if (cmd == BT819_FIFO_RESET_LOW) + GPIO(zr, 7, 0); + else if (cmd == BT819_FIFO_RESET_HIGH) + GPIO(zr, 7, 1); + return 0; +} + /* * Scan for a Buz card (actually for the PCI controller ZR36057), * request the irq and map the io memory @@ -1235,6 +1248,7 @@ static int __devinit zoran_probe(struct pci_dev *pdev, ZORAN_NAME); return -ENOMEM; } + zr->v4l2_dev.notify = zoran_subdev_notify; if (v4l2_device_register(&pdev->dev, &zr->v4l2_dev)) goto zr_free_mem; zr->pci_dev = pdev; diff --git a/linux/drivers/media/video/zoran/zoran_device.c b/linux/drivers/media/video/zoran/zoran_device.c index c2dfd4b67..409e0d5e1 100644 --- a/linux/drivers/media/video/zoran/zoran_device.c +++ b/linux/drivers/media/video/zoran/zoran_device.c @@ -1594,8 +1594,8 @@ zoran_init_hardware (struct zoran *zr) route.input = zr->card.input[zr->input].muxsel; decoder_call(zr, core, init, 0); - decoder_s_std(zr, zr->norm); - decoder_s_routing(zr, &route); + decoder_call(zr, tuner, s_std, zr->norm); + decoder_call(zr, video, s_routing, &route); encoder_call(zr, core, init, 0); encoder_call(zr, video, s_std_output, zr->norm); @@ -1660,35 +1660,3 @@ zr36057_init_vfe (struct zoran *zr) reg |= ZR36057_VDCR_Triton; btwrite(reg, ZR36057_VDCR); } - -/* - * Interface to decoder and encoder chips using i2c bus - */ - -int decoder_s_std(struct zoran *zr, v4l2_std_id std) -{ - int res; - - /* Bt819 needs to reset its FIFO buffer using #FRST pin and - LML33 card uses GPIO(7) for that. */ - if (zr->card.type == LML33) - GPIO(zr, 7, 0); - res = decoder_call(zr, tuner, s_std, std); - if (zr->card.type == LML33) - GPIO(zr, 7, 1); /* Pull #FRST high. */ - return res; -} - -int decoder_s_routing(struct zoran *zr, struct v4l2_routing *route) -{ - int res; - - /* Bt819 needs to reset its FIFO buffer using #FRST pin and - LML33 card uses GPIO(7) for that. */ - if (zr->card.type == LML33) - GPIO(zr, 7, 0); - res = decoder_call(zr, video, s_routing, route); - if (zr->card.type == LML33) - GPIO(zr, 7, 1); /* Pull #FRST high. */ - return res; -} diff --git a/linux/drivers/media/video/zoran/zoran_device.h b/linux/drivers/media/video/zoran/zoran_device.h index 2eb645904..72d691567 100644 --- a/linux/drivers/media/video/zoran/zoran_device.h +++ b/linux/drivers/media/video/zoran/zoran_device.h @@ -98,7 +98,4 @@ extern int pass_through; #define encoder_call(zr, o, f, args...) \ v4l2_subdev_call(zr->encoder, o, f, ##args) -int decoder_s_std(struct zoran *zr, v4l2_std_id std); -int decoder_s_routing(struct zoran *zr, struct v4l2_routing *route); - #endif /* __ZORAN_DEVICE_H__ */ diff --git a/linux/drivers/media/video/zoran/zoran_driver.c b/linux/drivers/media/video/zoran/zoran_driver.c index 8eda83b06..e7b0aba57 100644 --- a/linux/drivers/media/video/zoran/zoran_driver.c +++ b/linux/drivers/media/video/zoran/zoran_driver.c @@ -1525,7 +1525,7 @@ zoran_set_norm (struct zoran *zr, v4l2_std_id std = 0; decoder_call(zr, video, querystd, &std); - decoder_s_std(zr, std); + decoder_call(zr, tuner, s_std, std); /* let changes come into effect */ ssleep(2); @@ -1537,7 +1537,7 @@ zoran_set_norm (struct zoran *zr, "%s: set_norm() - no norm detected\n", ZR_DEVNAME(zr)); /* reset norm */ - decoder_s_std(zr, zr->norm); + decoder_call(zr, tuner, s_std, zr->norm); return -EIO; } @@ -1556,7 +1556,7 @@ zoran_set_norm (struct zoran *zr, if (on) zr36057_overlay(zr, 0); - decoder_s_std(zr, norm); + decoder_call(zr, tuner, s_std, norm); encoder_call(zr, video, s_std_output, norm); if (on) @@ -1598,7 +1598,7 @@ zoran_set_input (struct zoran *zr, route.input = zr->card.input[input].muxsel; zr->input = input; - decoder_s_routing(zr, &route); + decoder_call(zr, video, s_routing, &route); return 0; } @@ -1843,7 +1843,7 @@ jpgreqbuf_unlock_and_return: goto gstat_unlock_and_return; } - decoder_s_routing(zr, &route); + decoder_call(zr, video, s_routing, &route); /* sleep 1 second */ ssleep(1); @@ -1854,7 +1854,7 @@ jpgreqbuf_unlock_and_return: /* restore previous input and norm */ route.input = zr->card.input[zr->input].muxsel; - decoder_s_routing(zr, &route); + decoder_call(zr, video, s_routing, &route); gstat_unlock_and_return: mutex_unlock(&zr->resource_lock); -- cgit v1.2.3 From c913152cfea2d04fe7a55d869a4bcb38fd3f6e79 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Sun, 8 Mar 2009 16:22:48 -0500 Subject: pvrusb2: Fix slightly mis-leading header in debug interface output From: Mike Isely Priority: normal Signed-off-by: Mike Isely --- linux/drivers/media/video/pvrusb2/pvrusb2-debugifc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-debugifc.c b/linux/drivers/media/video/pvrusb2/pvrusb2-debugifc.c index cc4ef891b..2074ce05c 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-debugifc.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-debugifc.c @@ -147,7 +147,7 @@ int pvr2_debugifc_print_info(struct pvr2_hdw *hdw,char *buf,unsigned int acnt) bcnt += ccnt; acnt -= ccnt; buf += ccnt; ccnt = pvr2_hdw_state_report(hdw,buf,acnt); bcnt += ccnt; acnt -= ccnt; buf += ccnt; - ccnt = scnprintf(buf,acnt,"Attached I2C modules:\n"); + ccnt = scnprintf(buf, acnt, "Attached old-style I2C modules:\n"); bcnt += ccnt; acnt -= ccnt; buf += ccnt; ccnt = pvr2_i2c_report(hdw,buf,acnt); bcnt += ccnt; acnt -= ccnt; buf += ccnt; -- cgit v1.2.3 From 723966b18ec4f61970bff93af2dcb4457f8a19b2 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Sun, 8 Mar 2009 16:25:46 -0500 Subject: pvrusb2: Implement better reporting on attached sub-devices From: Mike Isely Priority: normal Signed-off-by: Mike Isely --- linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c | 115 ++++++++++++++++++------ 1 file changed, 86 insertions(+), 29 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c index f1e7c48eb..72769d10b 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -4972,38 +4972,82 @@ static unsigned int pvr2_hdw_report_unlocked(struct pvr2_hdw *hdw,int which, stats.buffers_processed, stats.buffers_failed); } - case 6: { - struct v4l2_subdev *sd; - unsigned int tcnt = 0; - unsigned int ccnt; - const char *p; - unsigned int id; - ccnt = scnprintf(buf, - acnt, - "Associated v4l2_subdev drivers:"); + default: break; + } + return 0; +} + + +/* Generate report containing info about attached sub-devices and attached + i2c clients, including an indication of which attached i2c clients are + actually sub-devices. */ +static unsigned int pvr2_hdw_report_clients(struct pvr2_hdw *hdw, + char *buf, unsigned int acnt) +{ + struct v4l2_subdev *sd; + unsigned int tcnt = 0; + unsigned int ccnt; + struct i2c_client *client; + struct list_head *item; + void *cd; + const char *p; + unsigned int id; + + ccnt = scnprintf(buf, acnt, "Associated v4l2-subdev drivers:"); + tcnt += ccnt; + v4l2_device_for_each_subdev(sd, &hdw->v4l2_dev) { + id = sd->grp_id; + p = NULL; + if (id < ARRAY_SIZE(module_names)) p = module_names[id]; + if (p) { + ccnt = scnprintf(buf + tcnt, acnt - tcnt, " %s", p); + tcnt += ccnt; + } else { + ccnt = scnprintf(buf + tcnt, acnt - tcnt, + " (unknown id=%u)", id); + tcnt += ccnt; + } + } + ccnt = scnprintf(buf + tcnt, acnt - tcnt, "\n"); + tcnt += ccnt; + + ccnt = scnprintf(buf + tcnt, acnt - tcnt, "I2C clients:\n"); + tcnt += ccnt; + + mutex_lock(&hdw->i2c_adap.clist_lock); + list_for_each(item, &hdw->i2c_adap.clients) { + client = list_entry(item, struct i2c_client, list); + ccnt = scnprintf(buf + tcnt, acnt - tcnt, + " %s: i2c=%02x", client->name, client->addr); tcnt += ccnt; + cd = i2c_get_clientdata(client); v4l2_device_for_each_subdev(sd, &hdw->v4l2_dev) { - id = sd->grp_id; - p = NULL; - if (id < ARRAY_SIZE(module_names)) { - p = module_names[id]; - } - if (p) { - ccnt = scnprintf(buf + tcnt, - acnt - tcnt, - " %s", p); - } else { - ccnt = scnprintf(buf + tcnt, - acnt - tcnt, - " (unknown id=%u)", id); + if (cd == sd) { + id = sd->grp_id; + p = NULL; + if (id < ARRAY_SIZE(module_names)) { + p = module_names[id]; + } + if (p) { + ccnt = scnprintf(buf + tcnt, + acnt - tcnt, + " subdev=%s", p); + tcnt += ccnt; + } else { + ccnt = scnprintf(buf + tcnt, + acnt - tcnt, + " subdev= id %u)", + id); + tcnt += ccnt; + } + break; } - tcnt += ccnt; } - return tcnt; - } - default: break; + ccnt = scnprintf(buf + tcnt, acnt - tcnt, "\n"); + tcnt += ccnt; } - return 0; + mutex_unlock(&hdw->i2c_adap.clist_lock); + return tcnt; } @@ -5021,6 +5065,8 @@ unsigned int pvr2_hdw_state_report(struct pvr2_hdw *hdw, buf[0] = '\n'; ccnt = 1; bcnt += ccnt; acnt -= ccnt; buf += ccnt; } + ccnt = pvr2_hdw_report_clients(hdw, buf, acnt); + bcnt += ccnt; acnt -= ccnt; buf += ccnt; LOCK_GIVE(hdw->big_lock); return bcnt; } @@ -5028,14 +5074,25 @@ unsigned int pvr2_hdw_state_report(struct pvr2_hdw *hdw, static void pvr2_hdw_state_log_state(struct pvr2_hdw *hdw) { - char buf[128]; - unsigned int idx,ccnt; + char buf[256]; + unsigned int idx, ccnt; + unsigned int lcnt, ucnt; for (idx = 0; ; idx++) { ccnt = pvr2_hdw_report_unlocked(hdw,idx,buf,sizeof(buf)); if (!ccnt) break; printk(KERN_INFO "%s %.*s\n",hdw->name,ccnt,buf); } + ccnt = pvr2_hdw_report_clients(hdw, buf, sizeof(buf)); + ucnt = 0; + while (ucnt < ccnt) { + lcnt = 0; + while ((lcnt + ucnt < ccnt) && (buf[lcnt + ucnt] != '\n')) { + lcnt++; + } + printk(KERN_INFO "%s %.*s\n", hdw->name, lcnt, buf + ucnt); + ucnt += lcnt + 1; + } } -- cgit v1.2.3 From 9b919a585341293a2ba14e0cdfad93a7a2342b4f Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Sun, 8 Mar 2009 16:47:47 -0500 Subject: pvrusb2: Remove old i2c layer; we use v4l2-subdev now From: Mike Isely This change removes the old i2c module controlling layer from the pvrusb2 driver. This is code that first had appeared in the driver back in December 2005. It's history. Now we use v4l2-subdev. Please note also that with this change, the driver will no longer be usable in kernels older that 2.6.22. Priority: normal Signed-off-by: Mike Isely --- linux/drivers/media/video/pvrusb2/Makefile | 7 +- linux/drivers/media/video/pvrusb2/pvrusb2-audio.c | 127 ------ linux/drivers/media/video/pvrusb2/pvrusb2-audio.h | 4 - .../media/video/pvrusb2/pvrusb2-cx2584x-v4l.c | 221 --------- .../media/video/pvrusb2/pvrusb2-cx2584x-v4l.h | 5 - .../drivers/media/video/pvrusb2/pvrusb2-debugifc.c | 5 - .../media/video/pvrusb2/pvrusb2-hdw-internal.h | 29 -- linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c | 87 ---- .../media/video/pvrusb2/pvrusb2-i2c-chips-v4l2.c | 119 ----- .../media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.c | 339 -------------- .../media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.h | 53 --- .../drivers/media/video/pvrusb2/pvrusb2-i2c-core.c | 4 - .../media/video/pvrusb2/pvrusb2-i2c-track.c | 504 --------------------- .../media/video/pvrusb2/pvrusb2-i2c-track.h | 102 ----- linux/drivers/media/video/pvrusb2/pvrusb2-tuner.c | 122 ----- linux/drivers/media/video/pvrusb2/pvrusb2-tuner.h | 37 -- .../media/video/pvrusb2/pvrusb2-video-v4l.c | 186 -------- .../media/video/pvrusb2/pvrusb2-video-v4l.h | 5 - linux/drivers/media/video/pvrusb2/pvrusb2-wm8775.c | 124 ----- linux/drivers/media/video/pvrusb2/pvrusb2-wm8775.h | 3 - 20 files changed, 3 insertions(+), 2080 deletions(-) delete mode 100644 linux/drivers/media/video/pvrusb2/pvrusb2-i2c-chips-v4l2.c delete mode 100644 linux/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.c delete mode 100644 linux/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.h delete mode 100644 linux/drivers/media/video/pvrusb2/pvrusb2-i2c-track.c delete mode 100644 linux/drivers/media/video/pvrusb2/pvrusb2-i2c-track.h delete mode 100644 linux/drivers/media/video/pvrusb2/pvrusb2-tuner.c delete mode 100644 linux/drivers/media/video/pvrusb2/pvrusb2-tuner.h (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/pvrusb2/Makefile b/linux/drivers/media/video/pvrusb2/Makefile index 931d9d1a0..a4478618a 100644 --- a/linux/drivers/media/video/pvrusb2/Makefile +++ b/linux/drivers/media/video/pvrusb2/Makefile @@ -2,11 +2,10 @@ obj-pvrusb2-sysfs-$(CONFIG_VIDEO_PVRUSB2_SYSFS) := pvrusb2-sysfs.o obj-pvrusb2-debugifc-$(CONFIG_VIDEO_PVRUSB2_DEBUGIFC) := pvrusb2-debugifc.o obj-pvrusb2-dvb-$(CONFIG_VIDEO_PVRUSB2_DVB) := pvrusb2-dvb.o -pvrusb2-objs := pvrusb2-i2c-core.o pvrusb2-i2c-cmd-v4l2.o \ - pvrusb2-i2c-track.o \ - pvrusb2-audio.o pvrusb2-i2c-chips-v4l2.o \ +pvrusb2-objs := pvrusb2-i2c-core.o \ + pvrusb2-audio.o \ pvrusb2-encoder.o pvrusb2-video-v4l.o \ - pvrusb2-eeprom.o pvrusb2-tuner.o \ + pvrusb2-eeprom.o \ pvrusb2-main.o pvrusb2-hdw.o pvrusb2-v4l2.o \ pvrusb2-ctrl.o pvrusb2-std.o pvrusb2-devattr.o \ pvrusb2-context.o pvrusb2-io.o pvrusb2-ioread.o \ diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-audio.c b/linux/drivers/media/video/pvrusb2/pvrusb2-audio.c index 5eef93b50..61cc80ef2 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-audio.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-audio.c @@ -56,133 +56,6 @@ static const struct routing_scheme routing_schemes[] = { }, }; - -struct pvr2_msp3400_handler { - struct pvr2_hdw *hdw; - struct pvr2_i2c_client *client; - struct pvr2_i2c_handler i2c_handler; - unsigned long stale_mask; -}; - - - - -/* This function selects the correct audio input source */ -static void set_stereo(struct pvr2_msp3400_handler *ctxt) -{ - struct pvr2_hdw *hdw = ctxt->hdw; - struct v4l2_routing route; - const struct routing_scheme *sp; - unsigned int sid = hdw->hdw_desc->signal_routing_scheme; - - pvr2_trace(PVR2_TRACE_CHIPS,"i2c msp3400 v4l2 set_stereo"); - - if ((sid < ARRAY_SIZE(routing_schemes)) && - ((sp = routing_schemes + sid) != NULL) && - (hdw->input_val >= 0) && - (hdw->input_val < sp->cnt)) { - route.input = sp->def[hdw->input_val]; - } else { - pvr2_trace(PVR2_TRACE_ERROR_LEGS, - "*** WARNING *** i2c msp3400 v4l2 set_stereo:" - " Invalid routing scheme (%u) and/or input (%d)", - sid,hdw->input_val); - return; - } - route.output = MSP_OUTPUT(MSP_SC_IN_DSP_SCART1); - pvr2_i2c_client_cmd(ctxt->client,VIDIOC_INT_S_AUDIO_ROUTING,&route); -} - - -static int check_stereo(struct pvr2_msp3400_handler *ctxt) -{ - struct pvr2_hdw *hdw = ctxt->hdw; - return hdw->input_dirty; -} - - -struct pvr2_msp3400_ops { - void (*update)(struct pvr2_msp3400_handler *); - int (*check)(struct pvr2_msp3400_handler *); -}; - - -static const struct pvr2_msp3400_ops msp3400_ops[] = { - { .update = set_stereo, .check = check_stereo}, -}; - - -static int msp3400_check(struct pvr2_msp3400_handler *ctxt) -{ - unsigned long msk; - unsigned int idx; - - for (idx = 0; idx < ARRAY_SIZE(msp3400_ops); idx++) { - msk = 1 << idx; - if (ctxt->stale_mask & msk) continue; - if (msp3400_ops[idx].check(ctxt)) { - ctxt->stale_mask |= msk; - } - } - return ctxt->stale_mask != 0; -} - - -static void msp3400_update(struct pvr2_msp3400_handler *ctxt) -{ - unsigned long msk; - unsigned int idx; - - for (idx = 0; idx < ARRAY_SIZE(msp3400_ops); idx++) { - msk = 1 << idx; - if (!(ctxt->stale_mask & msk)) continue; - ctxt->stale_mask &= ~msk; - msp3400_ops[idx].update(ctxt); - } -} - - -static void pvr2_msp3400_detach(struct pvr2_msp3400_handler *ctxt) -{ - ctxt->client->handler = NULL; - kfree(ctxt); -} - - -static unsigned int pvr2_msp3400_describe(struct pvr2_msp3400_handler *ctxt, - char *buf,unsigned int cnt) -{ - return scnprintf(buf,cnt,"handler: pvrusb2-audio v4l2"); -} - - -static const struct pvr2_i2c_handler_functions msp3400_funcs = { - .detach = (void (*)(void *))pvr2_msp3400_detach, - .check = (int (*)(void *))msp3400_check, - .update = (void (*)(void *))msp3400_update, - .describe = (unsigned int (*)(void *,char *,unsigned int))pvr2_msp3400_describe, -}; - - -int pvr2_i2c_msp3400_setup(struct pvr2_hdw *hdw,struct pvr2_i2c_client *cp) -{ - struct pvr2_msp3400_handler *ctxt; - if (cp->handler) return 0; - - ctxt = kzalloc(sizeof(*ctxt),GFP_KERNEL); - if (!ctxt) return 0; - - ctxt->i2c_handler.func_data = ctxt; - ctxt->i2c_handler.func_table = &msp3400_funcs; - ctxt->client = cp; - ctxt->hdw = hdw; - ctxt->stale_mask = (1 << ARRAY_SIZE(msp3400_ops)) - 1; - cp->handler = &ctxt->i2c_handler; - pvr2_trace(PVR2_TRACE_CHIPS,"i2c 0x%x msp3400 V4L2 handler set up", - cp->client->addr); - return !0; -} - void pvr2_msp3400_subdev_update(struct pvr2_hdw *hdw, struct v4l2_subdev *sd) { if (hdw->input_dirty || hdw->force_dirty) { diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-audio.h b/linux/drivers/media/video/pvrusb2/pvrusb2-audio.h index c47c8de3b..e3e63d750 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-audio.h +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-audio.h @@ -22,10 +22,6 @@ #ifndef __PVRUSB2_AUDIO_H #define __PVRUSB2_AUDIO_H -#include "pvrusb2-i2c-track.h" - -int pvr2_i2c_msp3400_setup(struct pvr2_hdw *,struct pvr2_i2c_client *); - #include "pvrusb2-hdw-internal.h" void pvr2_msp3400_subdev_update(struct pvr2_hdw *, struct v4l2_subdev *); #endif /* __PVRUSB2_AUDIO_H */ diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c b/linux/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c index c32d4a1cb..e0a6de5ae 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c @@ -28,7 +28,6 @@ #include "pvrusb2-cx2584x-v4l.h" #include "pvrusb2-video-v4l.h" -#include "pvrusb2-i2c-cmd-v4l2.h" #include "pvrusb2-hdw-internal.h" @@ -103,226 +102,6 @@ static const struct routing_scheme routing_schemes[] = { }, }; -struct pvr2_v4l_cx2584x { - struct pvr2_i2c_handler handler; - struct pvr2_decoder_ctrl ctrl; - struct pvr2_i2c_client *client; - struct pvr2_hdw *hdw; - unsigned long stale_mask; -}; - - -static void set_input(struct pvr2_v4l_cx2584x *ctxt) -{ - struct pvr2_hdw *hdw = ctxt->hdw; - struct v4l2_routing route; - enum cx25840_video_input vid_input; - enum cx25840_audio_input aud_input; - const struct routing_scheme *sp; - unsigned int sid = hdw->hdw_desc->signal_routing_scheme; - - memset(&route,0,sizeof(route)); - - if ((sid < ARRAY_SIZE(routing_schemes)) && - ((sp = routing_schemes + sid) != NULL) && - (hdw->input_val >= 0) && - (hdw->input_val < sp->cnt)) { - vid_input = sp->def[hdw->input_val].vid; - aud_input = sp->def[hdw->input_val].aud; - } else { - pvr2_trace(PVR2_TRACE_ERROR_LEGS, - "*** WARNING *** i2c cx2584x set_input:" - " Invalid routing scheme (%u) and/or input (%d)", - sid,hdw->input_val); - return; - } - - pvr2_trace(PVR2_TRACE_CHIPS,"i2c cx2584x set_input vid=0x%x aud=0x%x", - vid_input,aud_input); - route.input = (u32)vid_input; - pvr2_i2c_client_cmd(ctxt->client,VIDIOC_INT_S_VIDEO_ROUTING,&route); - route.input = (u32)aud_input; - pvr2_i2c_client_cmd(ctxt->client,VIDIOC_INT_S_AUDIO_ROUTING,&route); -} - - -static int check_input(struct pvr2_v4l_cx2584x *ctxt) -{ - struct pvr2_hdw *hdw = ctxt->hdw; - return hdw->input_dirty != 0; -} - - -static void set_audio(struct pvr2_v4l_cx2584x *ctxt) -{ - u32 val; - struct pvr2_hdw *hdw = ctxt->hdw; - - pvr2_trace(PVR2_TRACE_CHIPS,"i2c cx2584x set_audio %d", - hdw->srate_val); - switch (hdw->srate_val) { - default: - case V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000: - val = 48000; - break; - case V4L2_MPEG_AUDIO_SAMPLING_FREQ_44100: - val = 44100; - break; - case V4L2_MPEG_AUDIO_SAMPLING_FREQ_32000: - val = 32000; - break; - } - pvr2_i2c_client_cmd(ctxt->client,VIDIOC_INT_AUDIO_CLOCK_FREQ,&val); -} - - -static int check_audio(struct pvr2_v4l_cx2584x *ctxt) -{ - struct pvr2_hdw *hdw = ctxt->hdw; - return hdw->srate_dirty != 0; -} - - -struct pvr2_v4l_cx2584x_ops { - void (*update)(struct pvr2_v4l_cx2584x *); - int (*check)(struct pvr2_v4l_cx2584x *); -}; - - -static const struct pvr2_v4l_cx2584x_ops decoder_ops[] = { - { .update = set_input, .check = check_input}, - { .update = set_audio, .check = check_audio}, -}; - - -static void decoder_detach(struct pvr2_v4l_cx2584x *ctxt) -{ - ctxt->client->handler = NULL; - pvr2_hdw_set_decoder(ctxt->hdw,NULL); - kfree(ctxt); -} - - -static int decoder_check(struct pvr2_v4l_cx2584x *ctxt) -{ - unsigned long msk; - unsigned int idx; - - for (idx = 0; idx < ARRAY_SIZE(decoder_ops); idx++) { - msk = 1 << idx; - if (ctxt->stale_mask & msk) continue; - if (decoder_ops[idx].check(ctxt)) { - ctxt->stale_mask |= msk; - } - } - return ctxt->stale_mask != 0; -} - - -static void decoder_update(struct pvr2_v4l_cx2584x *ctxt) -{ - unsigned long msk; - unsigned int idx; - - for (idx = 0; idx < ARRAY_SIZE(decoder_ops); idx++) { - msk = 1 << idx; - if (!(ctxt->stale_mask & msk)) continue; - ctxt->stale_mask &= ~msk; - decoder_ops[idx].update(ctxt); - } -} - - -static void decoder_enable(struct pvr2_v4l_cx2584x *ctxt,int fl) -{ - pvr2_trace(PVR2_TRACE_CHIPS,"i2c cx25840 decoder_enable(%d)",fl); - pvr2_v4l2_cmd_stream(ctxt->client,fl); -} - - -static int decoder_detect(struct pvr2_i2c_client *cp) -{ - int ret; - /* Attempt to query the decoder - let's see if it will answer */ - struct v4l2_queryctrl qc; - - memset(&qc,0,sizeof(qc)); - - qc.id = V4L2_CID_BRIGHTNESS; - - ret = pvr2_i2c_client_cmd(cp,VIDIOC_QUERYCTRL,&qc); - return ret == 0; /* Return true if it answered */ -} - - -static unsigned int decoder_describe(struct pvr2_v4l_cx2584x *ctxt, - char *buf,unsigned int cnt) -{ - return scnprintf(buf,cnt,"handler: pvrusb2-cx2584x-v4l"); -} - - -static void decoder_reset(struct pvr2_v4l_cx2584x *ctxt) -{ - int ret; - ret = pvr2_i2c_client_cmd(ctxt->client,VIDIOC_INT_RESET,NULL); - pvr2_trace(PVR2_TRACE_CHIPS,"i2c cx25840 decoder_reset (ret=%d)",ret); -} - - -static const struct pvr2_i2c_handler_functions hfuncs = { - .detach = (void (*)(void *))decoder_detach, - .check = (int (*)(void *))decoder_check, - .update = (void (*)(void *))decoder_update, - .describe = (unsigned int (*)(void *,char *,unsigned int))decoder_describe, -}; - - -int pvr2_i2c_cx2584x_v4l_setup(struct pvr2_hdw *hdw, - struct pvr2_i2c_client *cp) -{ - struct pvr2_v4l_cx2584x *ctxt; - - if (hdw->decoder_ctrl) return 0; - if (cp->handler) return 0; - if (!decoder_detect(cp)) return 0; - - ctxt = kzalloc(sizeof(*ctxt),GFP_KERNEL); - if (!ctxt) return 0; - - ctxt->handler.func_data = ctxt; - ctxt->handler.func_table = &hfuncs; - ctxt->ctrl.ctxt = ctxt; - ctxt->ctrl.detach = (void (*)(void *))decoder_detach; - ctxt->ctrl.enable = (void (*)(void *,int))decoder_enable; - ctxt->ctrl.force_reset = (void (*)(void*))decoder_reset; - ctxt->client = cp; - ctxt->hdw = hdw; - ctxt->stale_mask = (1 << ARRAY_SIZE(decoder_ops)) - 1; - pvr2_hdw_set_decoder(hdw,&ctxt->ctrl); - cp->handler = &ctxt->handler; - { - /* - Mike Isely 19-Nov-2006 - This bit - of nuttiness for cx25840 causes that module to - correctly set up its video scaling. This is really - a problem in the cx25840 module itself, but we work - around it here. The problem has not been seen in - ivtv because there VBI is supported and set up. We - don't do VBI here (at least not yet) and thus we - never attempted to even set it up. - */ - struct v4l2_format fmt; - memset(&fmt,0,sizeof(fmt)); - fmt.type = V4L2_BUF_TYPE_SLICED_VBI_CAPTURE; - pvr2_i2c_client_cmd(ctxt->client,VIDIOC_S_FMT,&fmt); - } - pvr2_trace(PVR2_TRACE_CHIPS,"i2c 0x%x cx2584x V4L2 handler set up", - cp->client->addr); - return !0; -} - - void pvr2_cx25840_subdev_update(struct pvr2_hdw *hdw, struct v4l2_subdev *sd) { pvr2_trace(PVR2_TRACE_CHIPS, "subdev cx2584x update..."); diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.h b/linux/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.h index e48ce808b..e35c2322a 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.h +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.h @@ -34,11 +34,6 @@ -#include "pvrusb2-i2c-track.h" - -int pvr2_i2c_cx2584x_v4l_setup(struct pvr2_hdw *,struct pvr2_i2c_client *); - - #include "pvrusb2-hdw-internal.h" void pvr2_cx25840_subdev_update(struct pvr2_hdw *, struct v4l2_subdev *sd); diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-debugifc.c b/linux/drivers/media/video/pvrusb2/pvrusb2-debugifc.c index 2074ce05c..fbe3856bd 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-debugifc.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-debugifc.c @@ -23,7 +23,6 @@ #include "pvrusb2-debugifc.h" #include "pvrusb2-hdw.h" #include "pvrusb2-debug.h" -#include "pvrusb2-i2c-track.h" struct debugifc_mask_item { const char *name; @@ -147,10 +146,6 @@ int pvr2_debugifc_print_info(struct pvr2_hdw *hdw,char *buf,unsigned int acnt) bcnt += ccnt; acnt -= ccnt; buf += ccnt; ccnt = pvr2_hdw_state_report(hdw,buf,acnt); bcnt += ccnt; acnt -= ccnt; buf += ccnt; - ccnt = scnprintf(buf, acnt, "Attached old-style I2C modules:\n"); - bcnt += ccnt; acnt -= ccnt; buf += ccnt; - ccnt = pvr2_i2c_report(hdw,buf,acnt); - bcnt += ccnt; acnt -= ccnt; buf += ccnt; return bcnt; } diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h index 2afbd9bce..5d75eb521 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h @@ -138,22 +138,6 @@ struct pvr2_ctrl { }; -struct pvr2_decoder_ctrl { - void *ctxt; - void (*detach)(void *); - void (*enable)(void *,int); - void (*force_reset)(void *); -}; - -#define PVR2_I2C_PEND_DETECT 0x01 /* Need to detect a client type */ -#define PVR2_I2C_PEND_CLIENT 0x02 /* Client needs a specific update */ -#define PVR2_I2C_PEND_REFRESH 0x04 /* Client has specific pending bits */ -#define PVR2_I2C_PEND_STALE 0x08 /* Broadcast pending bits */ - -#define PVR2_I2C_PEND_ALL (PVR2_I2C_PEND_DETECT |\ - PVR2_I2C_PEND_CLIENT |\ - PVR2_I2C_PEND_REFRESH |\ - PVR2_I2C_PEND_STALE) /* Disposition of firmware1 loading situation */ #define FW1_STATE_UNKNOWN 0 @@ -187,7 +171,6 @@ struct pvr2_hdw { /* Kernel worker thread handling */ struct workqueue_struct *workqueue; struct work_struct workpoll; /* Update driver state */ - struct work_struct worki2csync; /* Update i2c clients */ /* Video spigot */ struct pvr2_stream *vid_stream; @@ -216,12 +199,6 @@ struct pvr2_hdw { pvr2_i2c_func i2c_func[PVR2_I2C_FUNC_CNT]; int i2c_cx25840_hack_state; int i2c_linked; - unsigned int i2c_pend_types; /* Which types of update are needed */ - unsigned long i2c_pend_mask; /* Change bits we need to scan */ - unsigned long i2c_stale_mask; /* Pending broadcast change bits */ - unsigned long i2c_active_mask; /* All change bits currently in use */ - struct list_head i2c_clients; - struct mutex i2c_list_lock; /* Frequency table */ unsigned int freqTable[FREQTABLE_SIZE]; @@ -297,7 +274,6 @@ struct pvr2_hdw { int flag_decoder_missed;/* We've noticed missing decoder */ int flag_tripped; /* Indicates overall failure to start */ - struct pvr2_decoder_ctrl *decoder_ctrl; unsigned int decoder_client_id; // CPU firmware info (used to help find / save firmware data) @@ -305,10 +281,6 @@ struct pvr2_hdw { unsigned int fw_size; int fw_cpu_flag; /* True if we are dealing with the CPU */ - // True if there is a request to trigger logging of state in each - // module. - int log_requested; - /* Tuner / frequency control stuff */ unsigned int tuner_type; int tuner_updated; @@ -406,7 +378,6 @@ struct pvr2_hdw { /* This function gets the current frequency */ unsigned long pvr2_hdw_get_cur_freq(struct pvr2_hdw *); -void pvr2_hdw_set_decoder(struct pvr2_hdw *,struct pvr2_decoder_ctrl *); void pvr2_hdw_status_poll(struct pvr2_hdw *); diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c index 72769d10b..1ecca14c7 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -30,8 +30,6 @@ #include "pvrusb2-util.h" #include "pvrusb2-hdw.h" #include "pvrusb2-i2c-core.h" -#include "pvrusb2-i2c-track.h" -#include "pvrusb2-tuner.h" #include "pvrusb2-eeprom.h" #include "pvrusb2-hdw-internal.h" #include "pvrusb2-encoder.h" @@ -314,7 +312,6 @@ static int pvr2_hdw_set_input(struct pvr2_hdw *hdw,int v); static void pvr2_hdw_state_sched(struct pvr2_hdw *); static int pvr2_hdw_state_eval(struct pvr2_hdw *); static void pvr2_hdw_set_cur_freq(struct pvr2_hdw *,unsigned long); -static void pvr2_hdw_worker_i2c(struct work_struct *work); static void pvr2_hdw_worker_poll(struct work_struct *work); static int pvr2_hdw_wait(struct pvr2_hdw *,int state); static int pvr2_hdw_untrip_unlocked(struct pvr2_hdw *); @@ -1686,10 +1683,6 @@ static const char *pvr2_get_state_name(unsigned int st) static int pvr2_decoder_enable(struct pvr2_hdw *hdw,int enablefl) { - if (hdw->decoder_ctrl) { - hdw->decoder_ctrl->enable(hdw->decoder_ctrl->ctxt, enablefl); - return 0; - } /* Even though we really only care about the video decoder chip at this point, we'll broadcast stream on/off to all sub-devices anyway, just in case somebody else wants to hear the @@ -1714,21 +1707,6 @@ static int pvr2_decoder_enable(struct pvr2_hdw *hdw,int enablefl) } -void pvr2_hdw_set_decoder(struct pvr2_hdw *hdw,struct pvr2_decoder_ctrl *ptr) -{ - if (hdw->decoder_ctrl == ptr) return; - hdw->decoder_ctrl = ptr; - if (hdw->decoder_ctrl && hdw->flag_decoder_missed) { - hdw->flag_decoder_missed = 0; - trace_stbit("flag_decoder_missed", - hdw->flag_decoder_missed); - pvr2_trace(PVR2_TRACE_ERROR_LEGS, - "Decoder has appeared"); - pvr2_hdw_state_sched(hdw); - } -} - - int pvr2_hdw_get_state(struct pvr2_hdw *hdw) { return hdw->master_state; @@ -2069,7 +2047,6 @@ static int pvr2_hdw_load_subdev(struct pvr2_hdw *hdw, * and every other place where I can find examples of this, the * "chipid" appears to just be the module name again. So here we * just do the same thing. */ - hdw->i2c_adap.class = 0; if (i2ccnt == 1) { pvr2_trace(PVR2_TRACE_INIT, "Module ID %u:" @@ -2087,7 +2064,6 @@ static int pvr2_hdw_load_subdev(struct pvr2_hdw *hdw, fname, fname, i2caddr); } - hdw->i2c_adap.class = I2C_CLASS_TV_ANALOG; if (!sd) { pvr2_trace(PVR2_TRACE_ERROR_LEGS, @@ -2101,11 +2077,6 @@ static int pvr2_hdw_load_subdev(struct pvr2_hdw *hdw, requires special handling. */ sd->grp_id = mid; - /* If we have both old and new i2c layers enabled, make sure that - old layer isn't also tracking this module. This is a debugging - aid, in normal situations there's no reason for both mechanisms - to be enabled. */ - pvr2_i2c_untrack_subdev(hdw, sd); pvr2_trace(PVR2_TRACE_INFO, "Attached sub-driver %s", fname); @@ -2221,7 +2192,6 @@ static void pvr2_hdw_setup_low(struct pvr2_hdw *hdw) } // This step MUST happen after the earlier powerup step. - pvr2_i2c_track_init(hdw); pvr2_i2c_core_init(hdw); if (!pvr2_hdw_dev_ok(hdw)) return; @@ -2288,7 +2258,6 @@ static void pvr2_hdw_setup_low(struct pvr2_hdw *hdw) hdw->tuner_type); } - pvr2_i2c_core_check_stale(hdw); if (!pvr2_hdw_dev_ok(hdw)) return; @@ -2647,11 +2616,8 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf, #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) INIT_WORK(&hdw->workpoll,(void (*)(void*))pvr2_hdw_worker_poll, &hdw->workpoll); - INIT_WORK(&hdw->worki2csync,(void (*)(void*))pvr2_hdw_worker_i2c, - &hdw->worki2csync); #else INIT_WORK(&hdw->workpoll,pvr2_hdw_worker_poll); - INIT_WORK(&hdw->worki2csync,pvr2_hdw_worker_i2c); #endif pvr2_trace(PVR2_TRACE_INIT,"Driver unit number is %d, name is %s", @@ -2755,11 +2721,7 @@ void pvr2_hdw_destroy(struct pvr2_hdw *hdw) pvr2_stream_destroy(hdw->vid_stream); hdw->vid_stream = NULL; } - if (hdw->decoder_ctrl) { - hdw->decoder_ctrl->detach(hdw->decoder_ctrl->ctxt); - } pvr2_i2c_core_done(hdw); - pvr2_i2c_track_done(hdw); v4l2_device_unregister(&hdw->v4l2_dev); pvr2_hdw_remove_usb_stuff(hdw); mutex_lock(&pvr2_unit_mtx); do { @@ -3262,12 +3224,6 @@ static int pvr2_hdw_commit_execute(struct pvr2_hdw *hdw) cx2341x_ext_ctrls(&hdw->enc_ctl_state, 0, &cs,VIDIOC_S_EXT_CTRLS); } - /* Scan i2c core at this point - before we clear all the dirty - bits. Various parts of the i2c core will notice dirty bits as - appropriate and arrange to broadcast or directly send updates to - the client drivers in order to keep everything in sync */ - pvr2_i2c_core_check_stale(hdw); - if (hdw->active_stream_type != hdw->desired_stream_type) { /* Handle any side effects of stream config here */ hdw->active_stream_type = hdw->desired_stream_type; @@ -3298,9 +3254,6 @@ static int pvr2_hdw_commit_execute(struct pvr2_hdw *hdw) cptr->info->clear_dirty(cptr); } - /* Now execute i2c core update */ - pvr2_i2c_core_sync(hdw); - if ((hdw->pathway_state == PVR2_PATHWAY_ANALOG) && hdw->state_encoder_run) { /* If encoder isn't running or it can't be touched, then @@ -3329,15 +3282,6 @@ int pvr2_hdw_commit_ctl(struct pvr2_hdw *hdw) } -static void pvr2_hdw_worker_i2c(struct work_struct *work) -{ - struct pvr2_hdw *hdw = container_of(work,struct pvr2_hdw,worki2csync); - LOCK_TAKE(hdw->big_lock); do { - pvr2_i2c_core_sync(hdw); - } while (0); LOCK_GIVE(hdw->big_lock); -} - - static void pvr2_hdw_worker_poll(struct work_struct *work) { int fl = 0; @@ -3455,10 +3399,6 @@ void pvr2_hdw_trigger_module_log(struct pvr2_hdw *hdw) int nr = pvr2_hdw_get_unit_number(hdw); LOCK_TAKE(hdw->big_lock); do { printk(KERN_INFO "pvrusb2: ================= START STATUS CARD #%d =================\n", nr); - hdw->log_requested = !0; - pvr2_i2c_core_check_stale(hdw); - pvr2_i2c_core_sync(hdw); - hdw->log_requested = 0; v4l2_device_call_all(&hdw->v4l2_dev, 0, core, log_status); pvr2_trace(PVR2_TRACE_INFO,"cx2341x config:"); cx2341x_log_status(&hdw->enc_ctl_state, "pvrusb2"); @@ -4216,16 +4156,6 @@ int pvr2_hdw_cmd_decoder_reset(struct pvr2_hdw *hdw) { pvr2_trace(PVR2_TRACE_INIT, "Requesting decoder reset"); - if (hdw->decoder_ctrl) { - if (!hdw->decoder_ctrl->force_reset) { - pvr2_trace(PVR2_TRACE_INIT, - "Unable to reset decoder: not implemented"); - return -ENOTTY; - } - hdw->decoder_ctrl->force_reset(hdw->decoder_ctrl->ctxt); - return 0; - } else { - } if (hdw->decoder_client_id) { v4l2_device_call_all(&hdw->v4l2_dev, hdw->decoder_client_id, core, reset, 0); @@ -5277,7 +5207,6 @@ void pvr2_hdw_status_poll(struct pvr2_hdw *hdw) struct v4l2_tuner *vtp = &hdw->tuner_signal_info; memset(vtp, 0, sizeof(*vtp)); hdw->tuner_signal_stale = 0; - pvr2_i2c_core_status_poll(hdw); /* Note: There apparently is no replacement for VIDIOC_CROPCAP using v4l2-subdev - therefore we can't support that AT ALL right now. (Of course, no sub-drivers seem to implement it either. @@ -5392,7 +5321,6 @@ int pvr2_hdw_register_access(struct pvr2_hdw *hdw, int setFl, u64 *val_ptr) { #ifdef CONFIG_VIDEO_ADV_DEBUG - struct pvr2_i2c_client *cp; struct v4l2_dbg_register req; int stat = 0; int okFl = 0; @@ -5405,21 +5333,6 @@ int pvr2_hdw_register_access(struct pvr2_hdw *hdw, /* It would be nice to know if a sub-device answered the request */ v4l2_device_call_all(&hdw->v4l2_dev, 0, core, g_register, &req); if (!setFl) *val_ptr = req.val; - if (!okFl) mutex_lock(&hdw->i2c_list_lock); do { - list_for_each_entry(cp, &hdw->i2c_clients, list) { - if (!v4l2_chip_match_i2c_client( - cp->client, - &req.match)) { - continue; - } - stat = pvr2_i2c_client_cmd( - cp,(setFl ? VIDIOC_DBG_S_REGISTER : - VIDIOC_DBG_G_REGISTER),&req); - if (!setFl) *val_ptr = req.val; - okFl = !0; - break; - } - } while (0); mutex_unlock(&hdw->i2c_list_lock); if (okFl) { return stat; } diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-chips-v4l2.c b/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-chips-v4l2.c deleted file mode 100644 index 0f8fd830c..000000000 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-chips-v4l2.c +++ /dev/null @@ -1,119 +0,0 @@ -/* - * - * - * Copyright (C) 2005 Mike Isely - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include -#include "pvrusb2-i2c-track.h" -#include "pvrusb2-hdw-internal.h" -#include "pvrusb2-debug.h" -#include "pvrusb2-i2c-cmd-v4l2.h" -#include "pvrusb2-audio.h" -#include "pvrusb2-tuner.h" -#include "pvrusb2-video-v4l.h" -#include "pvrusb2-cx2584x-v4l.h" -#include "pvrusb2-wm8775.h" -#include "compat.h" - - -#define trace_i2c(...) pvr2_trace(PVR2_TRACE_I2C,__VA_ARGS__) - -#define OP_INIT 0 /* MUST come first so it is run first */ -#define OP_STANDARD 1 -#define OP_AUDIOMODE 2 -#define OP_BCSH 3 -#define OP_VOLUME 4 -#define OP_FREQ 5 -#define OP_AUDIORATE 6 -#define OP_CROP 7 -#define OP_SIZE 8 -#define OP_LOG 9 - -static const struct pvr2_i2c_op * const ops[] = { - [OP_INIT] = &pvr2_i2c_op_v4l2_init, - [OP_STANDARD] = &pvr2_i2c_op_v4l2_standard, - [OP_AUDIOMODE] = &pvr2_i2c_op_v4l2_audiomode, - [OP_BCSH] = &pvr2_i2c_op_v4l2_bcsh, - [OP_VOLUME] = &pvr2_i2c_op_v4l2_volume, - [OP_FREQ] = &pvr2_i2c_op_v4l2_frequency, - [OP_CROP] = &pvr2_i2c_op_v4l2_crop, - [OP_SIZE] = &pvr2_i2c_op_v4l2_size, - [OP_LOG] = &pvr2_i2c_op_v4l2_log, -}; - -void pvr2_i2c_probe(struct pvr2_hdw *hdw,struct pvr2_i2c_client *cp) -{ - int id; - id = cp->client->driver->id; - cp->ctl_mask = ((1 << OP_INIT) | - (1 << OP_STANDARD) | - (1 << OP_AUDIOMODE) | - (1 << OP_BCSH) | - (1 << OP_VOLUME) | - (1 << OP_FREQ) | - (1 << OP_CROP) | - (1 << OP_SIZE) | - (1 << OP_LOG)); - cp->status_poll = pvr2_v4l2_cmd_status_poll; - - if (id == I2C_DRIVERID_MSP3400) { - if (pvr2_i2c_msp3400_setup(hdw,cp)) { - return; - } - } - if (id == I2C_DRIVERID_TUNER) { - if (pvr2_i2c_tuner_setup(hdw,cp)) { - return; - } - } - if (id == I2C_DRIVERID_CX25840) { - if (pvr2_i2c_cx2584x_v4l_setup(hdw,cp)) { - return; - } - } - if (id == I2C_DRIVERID_WM8775) { - if (pvr2_i2c_wm8775_setup(hdw,cp)) { - return; - } - } - if (id == I2C_DRIVERID_SAA711X) { - if (pvr2_i2c_decoder_v4l_setup(hdw,cp)) { - return; - } - } -} - - -const struct pvr2_i2c_op *pvr2_i2c_get_op(unsigned int idx) -{ - if (idx >= ARRAY_SIZE(ops)) - return NULL; - return ops[idx]; -} - - - -/* - Stuff for Emacs to see, in order to encourage consistent editing style: - *** Local Variables: *** - *** mode: c *** - *** fill-column: 75 *** - *** tab-width: 8 *** - *** c-basic-offset: 8 *** - *** End: *** - */ diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.c b/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.c deleted file mode 100644 index a477e1ebd..000000000 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.c +++ /dev/null @@ -1,339 +0,0 @@ -/* - * - * - * Copyright (C) 2005 Mike Isely - * Copyright (C) 2004 Aurelien Alleaume - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include "pvrusb2-i2c-cmd-v4l2.h" -#include "pvrusb2-hdw-internal.h" -#include "pvrusb2-debug.h" -#include -#include -#include "compat.h" - - -static void execute_init(struct pvr2_hdw *hdw) -{ - u32 dummy = 0; - pvr2_trace(PVR2_TRACE_CHIPS, "i2c v4l2 init"); - pvr2_i2c_core_cmd(hdw, VIDIOC_INT_INIT, &dummy); -} - - -const struct pvr2_i2c_op pvr2_i2c_op_v4l2_init = { - .update = execute_init, - .name = "v4l2_init", -}; - - -static void set_standard(struct pvr2_hdw *hdw) -{ - pvr2_trace(PVR2_TRACE_CHIPS,"i2c v4l2 set_standard"); - - if (hdw->input_val == PVR2_CVAL_INPUT_RADIO) { - pvr2_i2c_core_cmd(hdw,AUDC_SET_RADIO,NULL); - } else { - v4l2_std_id vs; - vs = hdw->std_mask_cur; - pvr2_i2c_core_cmd(hdw,VIDIOC_S_STD,&vs); - } - hdw->tuner_signal_stale = !0; - hdw->cropcap_stale = !0; -} - - -static int check_standard(struct pvr2_hdw *hdw) -{ - return (hdw->input_dirty != 0) || (hdw->std_dirty != 0); -} - - -const struct pvr2_i2c_op pvr2_i2c_op_v4l2_standard = { - .check = check_standard, - .update = set_standard, - .name = "v4l2_standard", -}; - - -static void set_bcsh(struct pvr2_hdw *hdw) -{ - struct v4l2_control ctrl; - pvr2_trace(PVR2_TRACE_CHIPS,"i2c v4l2 set_bcsh" - " b=%d c=%d s=%d h=%d", - hdw->brightness_val,hdw->contrast_val, - hdw->saturation_val,hdw->hue_val); - memset(&ctrl,0,sizeof(ctrl)); - ctrl.id = V4L2_CID_BRIGHTNESS; - ctrl.value = hdw->brightness_val; - pvr2_i2c_core_cmd(hdw,VIDIOC_S_CTRL,&ctrl); - ctrl.id = V4L2_CID_CONTRAST; - ctrl.value = hdw->contrast_val; - pvr2_i2c_core_cmd(hdw,VIDIOC_S_CTRL,&ctrl); - ctrl.id = V4L2_CID_SATURATION; - ctrl.value = hdw->saturation_val; - pvr2_i2c_core_cmd(hdw,VIDIOC_S_CTRL,&ctrl); - ctrl.id = V4L2_CID_HUE; - ctrl.value = hdw->hue_val; - pvr2_i2c_core_cmd(hdw,VIDIOC_S_CTRL,&ctrl); -} - - -static int check_bcsh(struct pvr2_hdw *hdw) -{ - return (hdw->brightness_dirty || - hdw->contrast_dirty || - hdw->saturation_dirty || - hdw->hue_dirty); -} - - -const struct pvr2_i2c_op pvr2_i2c_op_v4l2_bcsh = { - .check = check_bcsh, - .update = set_bcsh, - .name = "v4l2_bcsh", -}; - - -static void set_volume(struct pvr2_hdw *hdw) -{ - struct v4l2_control ctrl; - pvr2_trace(PVR2_TRACE_CHIPS, - "i2c v4l2 set_volume" - "(vol=%d bal=%d bas=%d treb=%d mute=%d)", - hdw->volume_val, - hdw->balance_val, - hdw->bass_val, - hdw->treble_val, - hdw->mute_val); - memset(&ctrl,0,sizeof(ctrl)); - ctrl.id = V4L2_CID_AUDIO_MUTE; - ctrl.value = hdw->mute_val ? 1 : 0; - pvr2_i2c_core_cmd(hdw,VIDIOC_S_CTRL,&ctrl); - ctrl.id = V4L2_CID_AUDIO_VOLUME; - ctrl.value = hdw->volume_val; - pvr2_i2c_core_cmd(hdw,VIDIOC_S_CTRL,&ctrl); - ctrl.id = V4L2_CID_AUDIO_BALANCE; - ctrl.value = hdw->balance_val; - pvr2_i2c_core_cmd(hdw,VIDIOC_S_CTRL,&ctrl); - ctrl.id = V4L2_CID_AUDIO_BASS; - ctrl.value = hdw->bass_val; - pvr2_i2c_core_cmd(hdw,VIDIOC_S_CTRL,&ctrl); - ctrl.id = V4L2_CID_AUDIO_TREBLE; - ctrl.value = hdw->treble_val; - pvr2_i2c_core_cmd(hdw,VIDIOC_S_CTRL,&ctrl); -} - - -static int check_volume(struct pvr2_hdw *hdw) -{ - return (hdw->volume_dirty || - hdw->balance_dirty || - hdw->bass_dirty || - hdw->treble_dirty || - hdw->mute_dirty); -} - - -const struct pvr2_i2c_op pvr2_i2c_op_v4l2_volume = { - .check = check_volume, - .update = set_volume, - .name = "v4l2_volume", -}; - - -static void set_audiomode(struct pvr2_hdw *hdw) -{ - struct v4l2_tuner vt; - memset(&vt,0,sizeof(vt)); - vt.audmode = hdw->audiomode_val; - pvr2_i2c_core_cmd(hdw,VIDIOC_S_TUNER,&vt); -} - - -static int check_audiomode(struct pvr2_hdw *hdw) -{ - return (hdw->input_dirty || - hdw->audiomode_dirty); -} - - -const struct pvr2_i2c_op pvr2_i2c_op_v4l2_audiomode = { - .check = check_audiomode, - .update = set_audiomode, - .name = "v4l2_audiomode", -}; - - -static void set_frequency(struct pvr2_hdw *hdw) -{ - unsigned long fv; - struct v4l2_frequency freq; - fv = pvr2_hdw_get_cur_freq(hdw); - pvr2_trace(PVR2_TRACE_CHIPS,"i2c v4l2 set_freq(%lu)",fv); - if (hdw->tuner_signal_stale) { - pvr2_hdw_status_poll(hdw); - } - memset(&freq,0,sizeof(freq)); - if (hdw->tuner_signal_info.capability & V4L2_TUNER_CAP_LOW) { - // ((fv * 1000) / 62500) - freq.frequency = (fv * 2) / 125; - } else { - freq.frequency = fv / 62500; - } - /* tuner-core currently doesn't seem to care about this, but - let's set it anyway for completeness. */ - if (hdw->input_val == PVR2_CVAL_INPUT_RADIO) { - freq.type = V4L2_TUNER_RADIO; - } else { - freq.type = V4L2_TUNER_ANALOG_TV; - } - freq.tuner = 0; - pvr2_i2c_core_cmd(hdw,VIDIOC_S_FREQUENCY,&freq); -} - - -static int check_frequency(struct pvr2_hdw *hdw) -{ - return hdw->freqDirty != 0; -} - - -const struct pvr2_i2c_op pvr2_i2c_op_v4l2_frequency = { - .check = check_frequency, - .update = set_frequency, - .name = "v4l2_freq", -}; - - -static void set_size(struct pvr2_hdw *hdw) -{ - struct v4l2_format fmt; - - memset(&fmt,0,sizeof(fmt)); - - fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - fmt.fmt.pix.width = hdw->res_hor_val; - fmt.fmt.pix.height = hdw->res_ver_val; - - pvr2_trace(PVR2_TRACE_CHIPS,"i2c v4l2 set_size(%dx%d)", - fmt.fmt.pix.width,fmt.fmt.pix.height); - - pvr2_i2c_core_cmd(hdw,VIDIOC_S_FMT,&fmt); -} - - -static int check_size(struct pvr2_hdw *hdw) -{ - return (hdw->res_hor_dirty || hdw->res_ver_dirty); -} - - -const struct pvr2_i2c_op pvr2_i2c_op_v4l2_size = { - .check = check_size, - .update = set_size, - .name = "v4l2_size", -}; - - -static void set_crop(struct pvr2_hdw *hdw) -{ - struct v4l2_crop crop; - - memset(&crop, 0, sizeof crop); - crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - crop.c.left = hdw->cropl_val; - crop.c.top = hdw->cropt_val; - crop.c.height = hdw->croph_val; - crop.c.width = hdw->cropw_val; - - pvr2_trace(PVR2_TRACE_CHIPS, - "i2c v4l2 set_crop crop=%d:%d:%d:%d", - crop.c.width, crop.c.height, crop.c.left, crop.c.top); - - pvr2_i2c_core_cmd(hdw, VIDIOC_S_CROP, &crop); -} - -static int check_crop(struct pvr2_hdw *hdw) -{ - return (hdw->cropl_dirty || hdw->cropt_dirty || - hdw->cropw_dirty || hdw->croph_dirty); -} - -const struct pvr2_i2c_op pvr2_i2c_op_v4l2_crop = { - .check = check_crop, - .update = set_crop, - .name = "v4l2_crop", -}; - - -static void do_log(struct pvr2_hdw *hdw) -{ - pvr2_trace(PVR2_TRACE_CHIPS,"i2c v4l2 do_log()"); - pvr2_i2c_core_cmd(hdw,VIDIOC_LOG_STATUS,NULL); - -} - - -static int check_log(struct pvr2_hdw *hdw) -{ - return hdw->log_requested != 0; -} - - -const struct pvr2_i2c_op pvr2_i2c_op_v4l2_log = { - .check = check_log, - .update = do_log, - .name = "v4l2_log", -}; - - -void pvr2_v4l2_cmd_stream(struct pvr2_i2c_client *cp,int fl) -{ - pvr2_i2c_client_cmd(cp, - (fl ? VIDIOC_STREAMON : VIDIOC_STREAMOFF),NULL); -} - - -void pvr2_v4l2_cmd_status_poll(struct pvr2_i2c_client *cp) -{ - int stat; - struct pvr2_hdw *hdw = cp->hdw; - if (hdw->cropcap_stale) { - hdw->cropcap_info.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - stat = pvr2_i2c_client_cmd(cp, VIDIOC_CROPCAP, - &hdw->cropcap_info); - if (stat == 0) { - /* Check was successful, so the data is no - longer considered stale. */ - hdw->cropcap_stale = 0; - } - } - pvr2_i2c_client_cmd(cp, VIDIOC_G_TUNER, &hdw->tuner_signal_info); -} - - - -/* - Stuff for Emacs to see, in order to encourage consistent editing style: - *** Local Variables: *** - *** mode: c *** - *** fill-column: 70 *** - *** tab-width: 8 *** - *** c-basic-offset: 8 *** - *** End: *** - */ diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.h b/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.h deleted file mode 100644 index fa42497b4..000000000 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * - * - * Copyright (C) 2005 Mike Isely - * Copyright (C) 2004 Aurelien Alleaume - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#ifndef __PVRUSB2_CMD_V4L2_H -#define __PVRUSB2_CMD_V4L2_H - -#include "pvrusb2-i2c-track.h" - - -extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_init; -extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_standard; -extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_radio; -extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_bcsh; -extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_volume; -extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_frequency; -extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_crop; -extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_size; -extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_audiomode; -extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_log; - -void pvr2_v4l2_cmd_stream(struct pvr2_i2c_client *,int); -void pvr2_v4l2_cmd_status_poll(struct pvr2_i2c_client *); - - -#endif /* __PVRUSB2_CMD_V4L2_H */ - -/* - Stuff for Emacs to see, in order to encourage consistent editing style: - *** Local Variables: *** - *** mode: c *** - *** fill-column: 70 *** - *** tab-width: 8 *** - *** c-basic-offset: 8 *** - *** End: *** - */ diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c b/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c index c1f613591..fde4d3bd1 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c @@ -20,7 +20,6 @@ #include #include "pvrusb2-i2c-core.h" -#include "pvrusb2-i2c-track.h" #include "pvrusb2-hdw-internal.h" #include "pvrusb2-debug.h" #include "pvrusb2-fx2-cmd.h" @@ -598,13 +597,11 @@ static u32 pvr2_i2c_functionality(struct i2c_adapter *adap) static int pvr2_i2c_attach_inform(struct i2c_client *client) { - pvr2_i2c_track_attach_inform(client); return 0; } static int pvr2_i2c_detach_inform(struct i2c_client *client) { - pvr2_i2c_track_detach_inform(client); return 0; } @@ -685,7 +682,6 @@ void pvr2_i2c_core_init(struct pvr2_hdw *hdw) hdw->i2c_adap.dev.parent = &hdw->usb_dev->dev; hdw->i2c_adap.algo = &hdw->i2c_algo; hdw->i2c_adap.algo_data = hdw; - hdw->i2c_adap.class = I2C_CLASS_TV_ANALOG; hdw->i2c_linked = !0; i2c_set_adapdata(&hdw->i2c_adap, &hdw->v4l2_dev); i2c_add_adapter(&hdw->i2c_adap); diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-track.c b/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-track.c deleted file mode 100644 index cec2526cb..000000000 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-track.c +++ /dev/null @@ -1,504 +0,0 @@ -/* - * - * - * Copyright (C) 2005 Mike Isely - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include "pvrusb2-i2c-track.h" -#include "pvrusb2-hdw-internal.h" -#include "pvrusb2-debug.h" -#include "pvrusb2-fx2-cmd.h" -#include "pvrusb2.h" -#include "compat.h" - -#define trace_i2c(...) pvr2_trace(PVR2_TRACE_I2C,__VA_ARGS__) - - -/* - - This module implements the foundation of a rather large architecture for - tracking state in all the various V4L I2C modules. This is obsolete with - kernels later than roughly 2.6.24, but it is still present in the - standalone pvrusb2 driver to allow continued operation with older - kernel. - -*/ - -static unsigned int pvr2_i2c_client_describe(struct pvr2_i2c_client *cp, - unsigned int detail, - char *buf,unsigned int maxlen); - -static int pvr2_i2c_core_singleton(struct i2c_client *cp, - unsigned int cmd,void *arg) -{ - int stat; - if (!cp) return -EINVAL; - if (!(cp->driver)) return -EINVAL; - if (!(cp->driver->command)) return -EINVAL; - if (!try_module_get(cp->driver->driver.owner)) return -EAGAIN; - stat = cp->driver->command(cp,cmd,arg); - module_put(cp->driver->driver.owner); - return stat; -} - -int pvr2_i2c_client_cmd(struct pvr2_i2c_client *cp,unsigned int cmd,void *arg) -{ - int stat; - if (pvrusb2_debug & PVR2_TRACE_I2C_CMD) { - char buf[100]; - unsigned int cnt; - cnt = pvr2_i2c_client_describe(cp,PVR2_I2C_DETAIL_DEBUG, - buf,sizeof(buf)); - pvr2_trace(PVR2_TRACE_I2C_CMD, - "i2c COMMAND (code=%u 0x%x) to %.*s", - cmd,cmd,cnt,buf); - } - stat = pvr2_i2c_core_singleton(cp->client,cmd,arg); - if (pvrusb2_debug & PVR2_TRACE_I2C_CMD) { - char buf[100]; - unsigned int cnt; - cnt = pvr2_i2c_client_describe(cp,PVR2_I2C_DETAIL_DEBUG, - buf,sizeof(buf)); - pvr2_trace(PVR2_TRACE_I2C_CMD, - "i2c COMMAND to %.*s (ret=%d)",cnt,buf,stat); - } - return stat; -} - -int pvr2_i2c_core_cmd(struct pvr2_hdw *hdw,unsigned int cmd,void *arg) -{ - struct pvr2_i2c_client *cp, *ncp; - int stat = -EINVAL; - - if (!hdw) return stat; - - mutex_lock(&hdw->i2c_list_lock); - list_for_each_entry_safe(cp, ncp, &hdw->i2c_clients, list) { - if (!cp->recv_enable) continue; - mutex_unlock(&hdw->i2c_list_lock); - stat = pvr2_i2c_client_cmd(cp,cmd,arg); - mutex_lock(&hdw->i2c_list_lock); - } - mutex_unlock(&hdw->i2c_list_lock); - return stat; -} - - -static int handler_check(struct pvr2_i2c_client *cp) -{ - struct pvr2_i2c_handler *hp = cp->handler; - if (!hp) return 0; - if (!hp->func_table->check) return 0; - return hp->func_table->check(hp->func_data) != 0; -} - -#define BUFSIZE 500 - - -void pvr2_i2c_core_status_poll(struct pvr2_hdw *hdw) -{ - struct pvr2_i2c_client *cp; - mutex_lock(&hdw->i2c_list_lock); do { - list_for_each_entry(cp, &hdw->i2c_clients, list) { - if (!cp->detected_flag) continue; - if (!cp->status_poll) continue; - cp->status_poll(cp); - } - } while (0); mutex_unlock(&hdw->i2c_list_lock); -} - - -/* Issue various I2C operations to bring chip-level drivers into sync with - state stored in this driver. */ -void pvr2_i2c_core_sync(struct pvr2_hdw *hdw) -{ - unsigned long msk; - unsigned int idx; - struct pvr2_i2c_client *cp, *ncp; - - if (!hdw->i2c_linked) return; - if (!(hdw->i2c_pend_types & PVR2_I2C_PEND_ALL)) { - return; - } - mutex_lock(&hdw->i2c_list_lock); do { - pvr2_trace(PVR2_TRACE_I2C_CORE,"i2c: core_sync BEGIN"); - if (hdw->i2c_pend_types & PVR2_I2C_PEND_DETECT) { - /* One or more I2C clients have attached since we - last synced. So scan the list and identify the - new clients. */ - char *buf; - unsigned int cnt; - unsigned long amask = 0; - buf = kmalloc(BUFSIZE,GFP_KERNEL); - pvr2_trace(PVR2_TRACE_I2C_CORE,"i2c: PEND_DETECT"); - hdw->i2c_pend_types &= ~PVR2_I2C_PEND_DETECT; - list_for_each_entry(cp, &hdw->i2c_clients, list) { - if (!cp->detected_flag) { - cp->ctl_mask = 0; - pvr2_i2c_probe(hdw,cp); - cp->detected_flag = !0; - msk = cp->ctl_mask; - cnt = 0; - if (buf) { - cnt = pvr2_i2c_client_describe( - cp, - PVR2_I2C_DETAIL_ALL, - buf,BUFSIZE); - } - trace_i2c("Probed: %.*s",cnt,buf); - if (handler_check(cp)) { - hdw->i2c_pend_types |= - PVR2_I2C_PEND_CLIENT; - } - cp->pend_mask = msk; - hdw->i2c_pend_mask |= msk; - hdw->i2c_pend_types |= - PVR2_I2C_PEND_REFRESH; - } - amask |= cp->ctl_mask; - } - hdw->i2c_active_mask = amask; - if (buf) kfree(buf); - } - if (hdw->i2c_pend_types & PVR2_I2C_PEND_STALE) { - /* Need to do one or more global updates. Arrange - for this to happen. */ - unsigned long m2; - pvr2_trace(PVR2_TRACE_I2C_CORE, - "i2c: PEND_STALE (0x%lx)", - hdw->i2c_stale_mask); - hdw->i2c_pend_types &= ~PVR2_I2C_PEND_STALE; - list_for_each_entry(cp, &hdw->i2c_clients, list) { - m2 = hdw->i2c_stale_mask; - m2 &= cp->ctl_mask; - m2 &= ~cp->pend_mask; - if (m2) { - pvr2_trace(PVR2_TRACE_I2C_CORE, - "i2c: cp=%p setting 0x%lx", - cp,m2); - cp->pend_mask |= m2; - } - } - hdw->i2c_pend_mask |= hdw->i2c_stale_mask; - hdw->i2c_stale_mask = 0; - hdw->i2c_pend_types |= PVR2_I2C_PEND_REFRESH; - } - if (hdw->i2c_pend_types & PVR2_I2C_PEND_CLIENT) { - /* One or more client handlers are asking for an - update. Run through the list of known clients - and update each one. */ - pvr2_trace(PVR2_TRACE_I2C_CORE,"i2c: PEND_CLIENT"); - hdw->i2c_pend_types &= ~PVR2_I2C_PEND_CLIENT; - list_for_each_entry_safe(cp, ncp, &hdw->i2c_clients, - list) { - if (!cp->handler) continue; - if (!cp->handler->func_table->update) continue; - pvr2_trace(PVR2_TRACE_I2C_CORE, - "i2c: cp=%p update",cp); - mutex_unlock(&hdw->i2c_list_lock); - cp->handler->func_table->update( - cp->handler->func_data); - mutex_lock(&hdw->i2c_list_lock); - /* If client's update function set some - additional pending bits, account for that - here. */ - if (cp->pend_mask & ~hdw->i2c_pend_mask) { - hdw->i2c_pend_mask |= cp->pend_mask; - hdw->i2c_pend_types |= - PVR2_I2C_PEND_REFRESH; - } - } - } - if (hdw->i2c_pend_types & PVR2_I2C_PEND_REFRESH) { - const struct pvr2_i2c_op *opf; - unsigned long pm; - /* Some actual updates are pending. Walk through - each update type and perform it. */ - pvr2_trace(PVR2_TRACE_I2C_CORE,"i2c: PEND_REFRESH" - " (0x%lx)",hdw->i2c_pend_mask); - hdw->i2c_pend_types &= ~PVR2_I2C_PEND_REFRESH; - pm = hdw->i2c_pend_mask; - hdw->i2c_pend_mask = 0; - for (idx = 0, msk = 1; pm; idx++, msk <<= 1) { - if (!(pm & msk)) continue; - pm &= ~msk; - list_for_each_entry(cp, &hdw->i2c_clients, - list) { - if (cp->pend_mask & msk) { - cp->pend_mask &= ~msk; - cp->recv_enable = !0; - } else { - cp->recv_enable = 0; - } - } - opf = pvr2_i2c_get_op(idx); - if (!opf) continue; - mutex_unlock(&hdw->i2c_list_lock); - opf->update(hdw); - mutex_lock(&hdw->i2c_list_lock); - } - } - pvr2_trace(PVR2_TRACE_I2C_CORE,"i2c: core_sync END"); - } while (0); mutex_unlock(&hdw->i2c_list_lock); -} - -int pvr2_i2c_core_check_stale(struct pvr2_hdw *hdw) -{ - unsigned long msk,sm,pm; - unsigned int idx; - const struct pvr2_i2c_op *opf; - struct pvr2_i2c_client *cp; - unsigned int pt = 0; - - pvr2_trace(PVR2_TRACE_I2C_CORE,"pvr2_i2c_core_check_stale BEGIN"); - - pm = hdw->i2c_active_mask; - sm = 0; - for (idx = 0, msk = 1; pm; idx++, msk <<= 1) { - if (!(msk & pm)) continue; - pm &= ~msk; - opf = pvr2_i2c_get_op(idx); - if (!(opf && opf->check)) continue; - if (opf->check(hdw)) { - sm |= msk; - } - } - if (sm) pt |= PVR2_I2C_PEND_STALE; - - list_for_each_entry(cp, &hdw->i2c_clients, list) - if (handler_check(cp)) - pt |= PVR2_I2C_PEND_CLIENT; - - if (pt) { - mutex_lock(&hdw->i2c_list_lock); do { - hdw->i2c_pend_types |= pt; - hdw->i2c_stale_mask |= sm; - hdw->i2c_pend_mask |= hdw->i2c_stale_mask; - } while (0); mutex_unlock(&hdw->i2c_list_lock); - } - - pvr2_trace(PVR2_TRACE_I2C_CORE, - "i2c: types=0x%x stale=0x%lx pend=0x%lx", - hdw->i2c_pend_types, - hdw->i2c_stale_mask, - hdw->i2c_pend_mask); - pvr2_trace(PVR2_TRACE_I2C_CORE,"pvr2_i2c_core_check_stale END"); - - return (hdw->i2c_pend_types & PVR2_I2C_PEND_ALL) != 0; -} - -static unsigned int pvr2_i2c_client_describe(struct pvr2_i2c_client *cp, - unsigned int detail, - char *buf,unsigned int maxlen) -{ - unsigned int ccnt,bcnt; - int spcfl = 0; - const struct pvr2_i2c_op *opf; - - ccnt = 0; - if (detail & PVR2_I2C_DETAIL_DEBUG) { - bcnt = scnprintf(buf,maxlen, - "ctxt=%p ctl_mask=0x%lx", - cp,cp->ctl_mask); - ccnt += bcnt; buf += bcnt; maxlen -= bcnt; - spcfl = !0; - } - bcnt = scnprintf(buf,maxlen, - "%s%s @ 0x%x", - (spcfl ? " " : ""), - cp->client->name, - cp->client->addr); - ccnt += bcnt; buf += bcnt; maxlen -= bcnt; - if ((detail & PVR2_I2C_DETAIL_HANDLER) && - cp->handler && cp->handler->func_table->describe) { - bcnt = scnprintf(buf,maxlen," ("); - ccnt += bcnt; buf += bcnt; maxlen -= bcnt; - bcnt = cp->handler->func_table->describe( - cp->handler->func_data,buf,maxlen); - ccnt += bcnt; buf += bcnt; maxlen -= bcnt; - bcnt = scnprintf(buf,maxlen,")"); - ccnt += bcnt; buf += bcnt; maxlen -= bcnt; - } - if ((detail & PVR2_I2C_DETAIL_CTLMASK) && cp->ctl_mask) { - unsigned int idx; - unsigned long msk,sm; - - bcnt = scnprintf(buf,maxlen," ["); - ccnt += bcnt; buf += bcnt; maxlen -= bcnt; - sm = 0; - spcfl = 0; - for (idx = 0, msk = 1; msk; idx++, msk <<= 1) { - if (!(cp->ctl_mask & msk)) continue; - opf = pvr2_i2c_get_op(idx); - if (opf) { - bcnt = scnprintf(buf,maxlen,"%s%s", - spcfl ? " " : "", - opf->name); - ccnt += bcnt; buf += bcnt; maxlen -= bcnt; - spcfl = !0; - } else { - sm |= msk; - } - } - if (sm) { - bcnt = scnprintf(buf,maxlen,"%s%lx", - idx != 0 ? " " : "",sm); - ccnt += bcnt; buf += bcnt; maxlen -= bcnt; - } - bcnt = scnprintf(buf,maxlen,"]"); - ccnt += bcnt; buf += bcnt; maxlen -= bcnt; - } - return ccnt; -} - -unsigned int pvr2_i2c_report(struct pvr2_hdw *hdw, - char *buf,unsigned int maxlen) -{ - unsigned int ccnt,bcnt; - struct pvr2_i2c_client *cp; - ccnt = 0; - mutex_lock(&hdw->i2c_list_lock); do { - list_for_each_entry(cp, &hdw->i2c_clients, list) { - bcnt = pvr2_i2c_client_describe( - cp, - (PVR2_I2C_DETAIL_HANDLER| - PVR2_I2C_DETAIL_CTLMASK), - buf,maxlen); - ccnt += bcnt; buf += bcnt; maxlen -= bcnt; - bcnt = scnprintf(buf,maxlen,"\n"); - ccnt += bcnt; buf += bcnt; maxlen -= bcnt; - } - } while (0); mutex_unlock(&hdw->i2c_list_lock); - return ccnt; -} - -void pvr2_i2c_track_attach_inform(struct i2c_client *client) -{ - struct pvr2_hdw *hdw = (struct pvr2_hdw *)(client->adapter->algo_data); - struct pvr2_i2c_client *cp; - int fl = !(hdw->i2c_pend_types & PVR2_I2C_PEND_ALL); - cp = kzalloc(sizeof(*cp),GFP_KERNEL); - trace_i2c("i2c_attach [client=%s @ 0x%x ctxt=%p]", - client->name, - client->addr,cp); - if (!cp) { - pvr2_trace(PVR2_TRACE_ERROR_LEGS, - "Unable to allocate tracking memory for incoming" - " i2c module; ignoring module. This is likely" - " going to be a problem."); - return; - } - cp->hdw = hdw; - INIT_LIST_HEAD(&cp->list); - cp->client = client; - mutex_lock(&hdw->i2c_list_lock); do { - hdw->cropcap_stale = !0; - list_add_tail(&cp->list,&hdw->i2c_clients); - hdw->i2c_pend_types |= PVR2_I2C_PEND_DETECT; - } while (0); mutex_unlock(&hdw->i2c_list_lock); - if (fl) queue_work(hdw->workqueue,&hdw->worki2csync); -} - -static void pvr2_i2c_client_disconnect(struct pvr2_i2c_client *cp) -{ - if (cp->handler && cp->handler->func_table->detach) { - cp->handler->func_table->detach(cp->handler->func_data); - } - list_del(&cp->list); - kfree(cp); -} - -void pvr2_i2c_track_detach_inform(struct i2c_client *client) -{ - struct pvr2_hdw *hdw = (struct pvr2_hdw *)(client->adapter->algo_data); - struct pvr2_i2c_client *cp, *ncp; - unsigned long amask = 0; - int foundfl = 0; - mutex_lock(&hdw->i2c_list_lock); - hdw->cropcap_stale = !0; - list_for_each_entry_safe(cp, ncp, &hdw->i2c_clients, list) { - if (cp->client == client) { - trace_i2c("pvr2_i2c_detach" - " [client=%s @ 0x%x ctxt=%p]", - client->name, - client->addr, cp); - pvr2_i2c_client_disconnect(cp); - foundfl = !0; - continue; - } - amask |= cp->ctl_mask; - } - hdw->i2c_active_mask = amask; - mutex_unlock(&hdw->i2c_list_lock); - if (!foundfl) { - trace_i2c("pvr2_i2c_detach [client=%s @ 0x%x ctxt=]", - client->name, client->addr); - } -} - -/* This function is used to remove an i2c client from our tracking - structure if the client happens to be the specified v4l2 sub-device. - The idea here is to ensure that sub-devices are not also tracked with - the old tracking mechanism - it's one or the other not both. This is - only for debugging. In a "real" environment, only one of these two - mechanisms should even be compiled in. But by enabling both we can - incrementally test control of each sub-device. */ -void pvr2_i2c_untrack_subdev(struct pvr2_hdw *hdw, struct v4l2_subdev *sd) -{ - struct i2c_client *client; - struct pvr2_i2c_client *cp, *ncp; - unsigned long amask = 0; - mutex_lock(&hdw->i2c_list_lock); - list_for_each_entry_safe(cp, ncp, &hdw->i2c_clients, list) { - client = cp->client; - if (i2c_get_clientdata(client) == sd) { - trace_i2c("pvr2_i2c_detach (subdev active)" - " [client=%s @ 0x%x ctxt=%p]", - client->name, client->addr, cp); - pvr2_i2c_client_disconnect(cp); - continue; - } - amask |= cp->ctl_mask; - } - hdw->i2c_active_mask = amask; - mutex_unlock(&hdw->i2c_list_lock); -} - -void pvr2_i2c_track_init(struct pvr2_hdw *hdw) -{ - hdw->i2c_pend_mask = 0; - hdw->i2c_stale_mask = 0; - hdw->i2c_active_mask = 0; - INIT_LIST_HEAD(&hdw->i2c_clients); - mutex_init(&hdw->i2c_list_lock); -} - -void pvr2_i2c_track_done(struct pvr2_hdw *hdw) -{ - /* Empty for now */ -} - - -/* - Stuff for Emacs to see, in order to encourage consistent editing style: - *** Local Variables: *** - *** mode: c *** - *** fill-column: 75 *** - *** tab-width: 8 *** - *** c-basic-offset: 8 *** - *** End: *** - */ diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-track.h b/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-track.h deleted file mode 100644 index eba48e4c9..000000000 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-track.h +++ /dev/null @@ -1,102 +0,0 @@ -/* - * - * - * Copyright (C) 2005 Mike Isely - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ -#ifndef __PVRUSB2_I2C_TRACK_H -#define __PVRUSB2_I2C_TRACK_H - -#include -#include -#include - - -struct pvr2_hdw; -struct pvr2_i2c_client; -struct pvr2_i2c_handler; -struct pvr2_i2c_handler_functions; -struct pvr2_i2c_op; -struct pvr2_i2c_op_functions; - -struct pvr2_i2c_client { - struct i2c_client *client; - struct pvr2_i2c_handler *handler; - struct list_head list; - struct pvr2_hdw *hdw; - int detected_flag; - int recv_enable; - unsigned long pend_mask; - unsigned long ctl_mask; - void (*status_poll)(struct pvr2_i2c_client *); -}; - -struct pvr2_i2c_handler { - void *func_data; - const struct pvr2_i2c_handler_functions *func_table; -}; - -struct pvr2_i2c_handler_functions { - void (*detach)(void *); - int (*check)(void *); - void (*update)(void *); - unsigned int (*describe)(void *,char *,unsigned int); -}; - -struct pvr2_i2c_op { - int (*check)(struct pvr2_hdw *); - void (*update)(struct pvr2_hdw *); - const char *name; -}; - -void pvr2_i2c_track_init(struct pvr2_hdw *); -void pvr2_i2c_track_done(struct pvr2_hdw *); -void pvr2_i2c_track_attach_inform(struct i2c_client *); -void pvr2_i2c_track_detach_inform(struct i2c_client *); - -int pvr2_i2c_client_cmd(struct pvr2_i2c_client *,unsigned int cmd,void *arg); -int pvr2_i2c_core_cmd(struct pvr2_hdw *,unsigned int cmd,void *arg); - -int pvr2_i2c_core_check_stale(struct pvr2_hdw *); -void pvr2_i2c_core_sync(struct pvr2_hdw *); -void pvr2_i2c_core_status_poll(struct pvr2_hdw *); -unsigned int pvr2_i2c_report(struct pvr2_hdw *,char *buf,unsigned int maxlen); -#define PVR2_I2C_DETAIL_DEBUG 0x0001 -#define PVR2_I2C_DETAIL_HANDLER 0x0002 -#define PVR2_I2C_DETAIL_CTLMASK 0x0004 -#define PVR2_I2C_DETAIL_ALL (\ - PVR2_I2C_DETAIL_DEBUG |\ - PVR2_I2C_DETAIL_HANDLER |\ - PVR2_I2C_DETAIL_CTLMASK) - -void pvr2_i2c_probe(struct pvr2_hdw *,struct pvr2_i2c_client *); -const struct pvr2_i2c_op *pvr2_i2c_get_op(unsigned int idx); - -void pvr2_i2c_untrack_subdev(struct pvr2_hdw *, struct v4l2_subdev *sd); - - -#endif /* __PVRUSB2_I2C_CORE_H */ - - -/* - Stuff for Emacs to see, in order to encourage consistent editing style: - *** Local Variables: *** - *** mode: c *** - *** fill-column: 75 *** - *** tab-width: 8 *** - *** c-basic-offset: 8 *** - *** End: *** - */ diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-tuner.c b/linux/drivers/media/video/pvrusb2/pvrusb2-tuner.c deleted file mode 100644 index 2aeedbc75..000000000 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-tuner.c +++ /dev/null @@ -1,122 +0,0 @@ -/* - * - * - * Copyright (C) 2005 Mike Isely - * Copyright (C) 2004 Aurelien Alleaume - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include "pvrusb2.h" -#include "pvrusb2-util.h" -#include "pvrusb2-tuner.h" -#include "pvrusb2-hdw-internal.h" -#include "pvrusb2-debug.h" -#include "compat.h" -#include -#include -#include - - -struct pvr2_tuner_handler { - struct pvr2_hdw *hdw; - struct pvr2_i2c_client *client; - struct pvr2_i2c_handler i2c_handler; - int type_update_fl; -}; - - -static void set_type(struct pvr2_tuner_handler *ctxt) -{ - struct pvr2_hdw *hdw = ctxt->hdw; - struct tuner_setup setup; - pvr2_trace(PVR2_TRACE_CHIPS,"i2c tuner set_type(%d)",hdw->tuner_type); - if (((int)(hdw->tuner_type)) < 0) return; - - setup.addr = ADDR_UNSET; - setup.type = hdw->tuner_type; - setup.mode_mask = T_RADIO | T_ANALOG_TV; - /* We may really want mode_mask to be T_ANALOG_TV for now */ - pvr2_i2c_client_cmd(ctxt->client,TUNER_SET_TYPE_ADDR,&setup); - ctxt->type_update_fl = 0; -} - - -static int tuner_check(struct pvr2_tuner_handler *ctxt) -{ - struct pvr2_hdw *hdw = ctxt->hdw; - if (hdw->tuner_updated) ctxt->type_update_fl = !0; - return ctxt->type_update_fl != 0; -} - - -static void tuner_update(struct pvr2_tuner_handler *ctxt) -{ - if (ctxt->type_update_fl) set_type(ctxt); -} - - -static void pvr2_tuner_detach(struct pvr2_tuner_handler *ctxt) -{ - ctxt->client->handler = NULL; - kfree(ctxt); -} - - -static unsigned int pvr2_tuner_describe(struct pvr2_tuner_handler *ctxt,char *buf,unsigned int cnt) -{ - return scnprintf(buf,cnt,"handler: pvrusb2-tuner"); -} - - -static const struct pvr2_i2c_handler_functions tuner_funcs = { - .detach = (void (*)(void *))pvr2_tuner_detach, - .check = (int (*)(void *))tuner_check, - .update = (void (*)(void *))tuner_update, - .describe = (unsigned int (*)(void *,char *,unsigned int))pvr2_tuner_describe, -}; - - -int pvr2_i2c_tuner_setup(struct pvr2_hdw *hdw,struct pvr2_i2c_client *cp) -{ - struct pvr2_tuner_handler *ctxt; - if (cp->handler) return 0; - - ctxt = kzalloc(sizeof(*ctxt),GFP_KERNEL); - if (!ctxt) return 0; - - ctxt->i2c_handler.func_data = ctxt; - ctxt->i2c_handler.func_table = &tuner_funcs; - ctxt->type_update_fl = !0; - ctxt->client = cp; - ctxt->hdw = hdw; - cp->handler = &ctxt->i2c_handler; - pvr2_trace(PVR2_TRACE_CHIPS,"i2c 0x%x tuner handler set up", - cp->client->addr); - return !0; -} - - - - -/* - Stuff for Emacs to see, in order to encourage consistent editing style: - *** Local Variables: *** - *** mode: c *** - *** fill-column: 70 *** - *** tab-width: 8 *** - *** c-basic-offset: 8 *** - *** End: *** - */ diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-tuner.h b/linux/drivers/media/video/pvrusb2/pvrusb2-tuner.h deleted file mode 100644 index 3643e2c78..000000000 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-tuner.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * - * - * Copyright (C) 2005 Mike Isely - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ -#ifndef __PVRUSB2_TUNER_H -#define __PVRUSB2_TUNER_H - -#include "pvrusb2-i2c-track.h" - -int pvr2_i2c_tuner_setup(struct pvr2_hdw *,struct pvr2_i2c_client *); - -#endif /* __PVRUSB2_TUNER_H */ - -/* - Stuff for Emacs to see, in order to encourage consistent editing style: - *** Local Variables: *** - *** mode: c *** - *** fill-column: 70 *** - *** tab-width: 8 *** - *** c-basic-offset: 8 *** - *** End: *** - */ diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-video-v4l.c b/linux/drivers/media/video/pvrusb2/pvrusb2-video-v4l.c index a60637ae7..776f20f77 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-video-v4l.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-video-v4l.c @@ -30,7 +30,6 @@ #include "pvrusb2-video-v4l.h" -#include "pvrusb2-i2c-cmd-v4l2.h" #include "pvrusb2-hdw-internal.h" #include "pvrusb2-debug.h" @@ -63,191 +62,6 @@ static const struct routing_scheme routing_schemes[] = { }, }; -struct pvr2_v4l_decoder { - struct pvr2_i2c_handler handler; - struct pvr2_decoder_ctrl ctrl; - struct pvr2_i2c_client *client; - struct pvr2_hdw *hdw; - unsigned long stale_mask; -}; - - - -static void set_input(struct pvr2_v4l_decoder *ctxt) -{ - struct pvr2_hdw *hdw = ctxt->hdw; - struct v4l2_routing route; - const struct routing_scheme *sp; - unsigned int sid = hdw->hdw_desc->signal_routing_scheme; - - pvr2_trace(PVR2_TRACE_CHIPS,"i2c v4l2 set_input(%d)",hdw->input_val); - - if ((sid < ARRAY_SIZE(routing_schemes)) && - ((sp = routing_schemes + sid) != NULL) && - (hdw->input_val >= 0) && - (hdw->input_val < sp->cnt)) { - route.input = sp->def[hdw->input_val]; - } else { - pvr2_trace(PVR2_TRACE_ERROR_LEGS, - "*** WARNING *** i2c v4l2 set_input:" - " Invalid routing scheme (%u) and/or input (%d)", - sid,hdw->input_val); - return; - } - - route.output = 0; - pvr2_i2c_client_cmd(ctxt->client,VIDIOC_INT_S_VIDEO_ROUTING,&route); -} - - -static int check_input(struct pvr2_v4l_decoder *ctxt) -{ - struct pvr2_hdw *hdw = ctxt->hdw; - return hdw->input_dirty != 0; -} - - -static void set_audio(struct pvr2_v4l_decoder *ctxt) -{ - u32 val; - struct pvr2_hdw *hdw = ctxt->hdw; - - pvr2_trace(PVR2_TRACE_CHIPS,"i2c v4l2 set_audio %d", - hdw->srate_val); - switch (hdw->srate_val) { - default: - case V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000: - val = 48000; - break; - case V4L2_MPEG_AUDIO_SAMPLING_FREQ_44100: - val = 44100; - break; - case V4L2_MPEG_AUDIO_SAMPLING_FREQ_32000: - val = 32000; - break; - } - pvr2_i2c_client_cmd(ctxt->client,VIDIOC_INT_AUDIO_CLOCK_FREQ,&val); -} - - -static int check_audio(struct pvr2_v4l_decoder *ctxt) -{ - struct pvr2_hdw *hdw = ctxt->hdw; - return hdw->srate_dirty != 0; -} - - -struct pvr2_v4l_decoder_ops { - void (*update)(struct pvr2_v4l_decoder *); - int (*check)(struct pvr2_v4l_decoder *); -}; - - -static const struct pvr2_v4l_decoder_ops decoder_ops[] = { - { .update = set_input, .check = check_input}, - { .update = set_audio, .check = check_audio}, -}; - - -static void decoder_detach(struct pvr2_v4l_decoder *ctxt) -{ - ctxt->client->handler = NULL; - pvr2_hdw_set_decoder(ctxt->hdw,NULL); - kfree(ctxt); -} - - -static int decoder_check(struct pvr2_v4l_decoder *ctxt) -{ - unsigned long msk; - unsigned int idx; - - for (idx = 0; idx < ARRAY_SIZE(decoder_ops); idx++) { - msk = 1 << idx; - if (ctxt->stale_mask & msk) continue; - if (decoder_ops[idx].check(ctxt)) { - ctxt->stale_mask |= msk; - } - } - return ctxt->stale_mask != 0; -} - - -static void decoder_update(struct pvr2_v4l_decoder *ctxt) -{ - unsigned long msk; - unsigned int idx; - - for (idx = 0; idx < ARRAY_SIZE(decoder_ops); idx++) { - msk = 1 << idx; - if (!(ctxt->stale_mask & msk)) continue; - ctxt->stale_mask &= ~msk; - decoder_ops[idx].update(ctxt); - } -} - - -static int decoder_detect(struct pvr2_i2c_client *cp) -{ - /* Attempt to query the decoder - let's see if it will answer */ - struct v4l2_tuner vt; - int ret; - - memset(&vt,0,sizeof(vt)); - ret = pvr2_i2c_client_cmd(cp,VIDIOC_G_TUNER,&vt); - return ret == 0; /* Return true if it answered */ -} - - -static void decoder_enable(struct pvr2_v4l_decoder *ctxt,int fl) -{ - pvr2_trace(PVR2_TRACE_CHIPS,"i2c v4l2 decoder_enable(%d)",fl); - pvr2_v4l2_cmd_stream(ctxt->client,fl); -} - - -static unsigned int decoder_describe(struct pvr2_v4l_decoder *ctxt,char *buf,unsigned int cnt) -{ - return scnprintf(buf,cnt,"handler: pvrusb2-video-v4l"); -} - - -static const struct pvr2_i2c_handler_functions hfuncs = { - .detach = (void (*)(void *))decoder_detach, - .check = (int (*)(void *))decoder_check, - .update = (void (*)(void *))decoder_update, - .describe = (unsigned int (*)(void *,char *,unsigned int))decoder_describe, -}; - - -int pvr2_i2c_decoder_v4l_setup(struct pvr2_hdw *hdw, - struct pvr2_i2c_client *cp) -{ - struct pvr2_v4l_decoder *ctxt; - - if (hdw->decoder_ctrl) return 0; - if (cp->handler) return 0; - if (!decoder_detect(cp)) return 0; - - ctxt = kzalloc(sizeof(*ctxt),GFP_KERNEL); - if (!ctxt) return 0; - - ctxt->handler.func_data = ctxt; - ctxt->handler.func_table = &hfuncs; - ctxt->ctrl.ctxt = ctxt; - ctxt->ctrl.detach = (void (*)(void *))decoder_detach; - ctxt->ctrl.enable = (void (*)(void *,int))decoder_enable; - ctxt->client = cp; - ctxt->hdw = hdw; - ctxt->stale_mask = (1 << ARRAY_SIZE(decoder_ops)) - 1; - pvr2_hdw_set_decoder(hdw,&ctxt->ctrl); - cp->handler = &ctxt->handler; - pvr2_trace(PVR2_TRACE_CHIPS,"i2c 0x%x saa711x V4L2 handler set up", - cp->client->addr); - return !0; -} - - void pvr2_saa7115_subdev_update(struct pvr2_hdw *hdw, struct v4l2_subdev *sd) { if (hdw->input_dirty || hdw->force_dirty) { diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-video-v4l.h b/linux/drivers/media/video/pvrusb2/pvrusb2-video-v4l.h index dac4b1ad3..3b0bd5db6 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-video-v4l.h +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-video-v4l.h @@ -32,11 +32,6 @@ */ - -#include "pvrusb2-i2c-track.h" - -int pvr2_i2c_decoder_v4l_setup(struct pvr2_hdw *,struct pvr2_i2c_client *); - #include "pvrusb2-hdw-internal.h" void pvr2_saa7115_subdev_update(struct pvr2_hdw *, struct v4l2_subdev *); diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-wm8775.c b/linux/drivers/media/video/pvrusb2/pvrusb2-wm8775.c index e2b949102..6364434a5 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-wm8775.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-wm8775.c @@ -27,7 +27,6 @@ */ #include "pvrusb2-wm8775.h" -#include "pvrusb2-i2c-cmd-v4l2.h" #include "pvrusb2-hdw-internal.h" @@ -38,129 +37,6 @@ #include #include "compat.h" - - -struct pvr2_v4l_wm8775 { - struct pvr2_i2c_handler handler; - struct pvr2_i2c_client *client; - struct pvr2_hdw *hdw; - unsigned long stale_mask; -}; - - -static void set_input(struct pvr2_v4l_wm8775 *ctxt) -{ - struct v4l2_routing route; - struct pvr2_hdw *hdw = ctxt->hdw; - - memset(&route,0,sizeof(route)); - - switch(hdw->input_val) { - case PVR2_CVAL_INPUT_RADIO: - route.input = 1; - break; - default: - /* All other cases just use the second input */ - route.input = 2; - break; - } - pvr2_trace(PVR2_TRACE_CHIPS,"i2c wm8775 set_input(val=%d route=0x%x)", - hdw->input_val,route.input); - - pvr2_i2c_client_cmd(ctxt->client,VIDIOC_INT_S_AUDIO_ROUTING,&route); -} - -static int check_input(struct pvr2_v4l_wm8775 *ctxt) -{ - struct pvr2_hdw *hdw = ctxt->hdw; - return hdw->input_dirty != 0; -} - - -struct pvr2_v4l_wm8775_ops { - void (*update)(struct pvr2_v4l_wm8775 *); - int (*check)(struct pvr2_v4l_wm8775 *); -}; - - -static const struct pvr2_v4l_wm8775_ops wm8775_ops[] = { - { .update = set_input, .check = check_input}, -}; - - -static unsigned int wm8775_describe(struct pvr2_v4l_wm8775 *ctxt, - char *buf,unsigned int cnt) -{ - return scnprintf(buf,cnt,"handler: pvrusb2-wm8775"); -} - - -static void wm8775_detach(struct pvr2_v4l_wm8775 *ctxt) -{ - ctxt->client->handler = NULL; - kfree(ctxt); -} - - -static int wm8775_check(struct pvr2_v4l_wm8775 *ctxt) -{ - unsigned long msk; - unsigned int idx; - - for (idx = 0; idx < ARRAY_SIZE(wm8775_ops); idx++) { - msk = 1 << idx; - if (ctxt->stale_mask & msk) continue; - if (wm8775_ops[idx].check(ctxt)) { - ctxt->stale_mask |= msk; - } - } - return ctxt->stale_mask != 0; -} - - -static void wm8775_update(struct pvr2_v4l_wm8775 *ctxt) -{ - unsigned long msk; - unsigned int idx; - - for (idx = 0; idx < ARRAY_SIZE(wm8775_ops); idx++) { - msk = 1 << idx; - if (!(ctxt->stale_mask & msk)) continue; - ctxt->stale_mask &= ~msk; - wm8775_ops[idx].update(ctxt); - } -} - - -static const struct pvr2_i2c_handler_functions hfuncs = { - .detach = (void (*)(void *))wm8775_detach, - .check = (int (*)(void *))wm8775_check, - .update = (void (*)(void *))wm8775_update, - .describe = (unsigned int (*)(void *,char *,unsigned int))wm8775_describe, -}; - - -int pvr2_i2c_wm8775_setup(struct pvr2_hdw *hdw,struct pvr2_i2c_client *cp) -{ - struct pvr2_v4l_wm8775 *ctxt; - - if (cp->handler) return 0; - - ctxt = kzalloc(sizeof(*ctxt),GFP_KERNEL); - if (!ctxt) return 0; - - ctxt->handler.func_data = ctxt; - ctxt->handler.func_table = &hfuncs; - ctxt->client = cp; - ctxt->hdw = hdw; - ctxt->stale_mask = (1 << ARRAY_SIZE(wm8775_ops)) - 1; - cp->handler = &ctxt->handler; - pvr2_trace(PVR2_TRACE_CHIPS,"i2c 0x%x wm8775 V4L2 handler set up", - cp->client->addr); - return !0; -} - - void pvr2_wm8775_subdev_update(struct pvr2_hdw *hdw, struct v4l2_subdev *sd) { if (hdw->input_dirty || hdw->force_dirty) { diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-wm8775.h b/linux/drivers/media/video/pvrusb2/pvrusb2-wm8775.h index a304988b1..0577bc724 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-wm8775.h +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-wm8775.h @@ -34,9 +34,6 @@ -#include "pvrusb2-i2c-track.h" - -int pvr2_i2c_wm8775_setup(struct pvr2_hdw *,struct pvr2_i2c_client *); #include "pvrusb2-hdw-internal.h" void pvr2_wm8775_subdev_update(struct pvr2_hdw *, struct v4l2_subdev *sd); -- cgit v1.2.3 From cc6c6b33bf652251302178b5e44a35c876a51277 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Sun, 8 Mar 2009 17:14:07 -0500 Subject: pvrusb2: Remove ancient IVTV specific ioctl functions From: Mike Isely Remove ancient IVTV_IOC_G_CODEC and IVTV_IOC_S_CODEC ioctl functions from the pvrusb2 driver. These are very very old, were non-standard, and were only present to keep MythTV happy (their implementation did nothing except to report success). That was long ago; no recent versions of MythTV should require this anymore. Priority: normal Signed-off-by: Mike Isely --- linux/drivers/media/video/pvrusb2/pvrusb2-v4l2.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-v4l2.c b/linux/drivers/media/video/pvrusb2/pvrusb2-v4l2.c index e4bf0278c..c7fc605f8 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-v4l2.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-v4l2.c @@ -953,10 +953,6 @@ static long pvr2_v4l2_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { -/* Temporary hack : use ivtv api until a v4l2 one is available. */ -#define IVTV_IOC_G_CODEC 0xFFEE7703 -#define IVTV_IOC_S_CODEC 0xFFEE7704 - if (cmd == IVTV_IOC_G_CODEC || cmd == IVTV_IOC_S_CODEC) return 0; return video_usercopy(file, cmd, arg, pvr2_v4l2_do_ioctl); } -- cgit v1.2.3 From 62a243115aca4914efcae622563c65a0e6875790 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Sun, 8 Mar 2009 23:03:25 -0400 Subject: remove build-time dependencies on dib7000m From: Michael Krufky Priority: normal Signed-off-by: Michael Krufky --- linux/drivers/media/dvb/frontends/dib7000m.h | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/frontends/dib7000m.h b/linux/drivers/media/dvb/frontends/dib7000m.h index 597e9cc2d..f93db0fda 100644 --- a/linux/drivers/media/dvb/frontends/dib7000m.h +++ b/linux/drivers/media/dvb/frontends/dib7000m.h @@ -38,8 +38,28 @@ struct dib7000m_config { #define DEFAULT_DIB7000M_I2C_ADDRESS 18 +#if defined(CONFIG_DVB_DIB7000M) || (defined(CONFIG_DVB_DIB7000M_MODULE) && \ + defined(MODULE)) extern struct dvb_frontend * dib7000m_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib7000m_config *cfg); extern struct i2c_adapter * dib7000m_get_i2c_master(struct dvb_frontend *, enum dibx000_i2c_interface, int); +#else +static inline +struct dvb_frontend *dib7000m_attach(struct i2c_adapter *i2c_adap, + u8 i2c_addr, struct dib7000m_config *cfg) +{ + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); + return NULL; +} + +static inline +struct i2c_adapter *dib7000m_get_i2c_master(struct dvb_frontend *demod, + enum dibx000_i2c_interface intf, + int gating) +{ + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); + return NULL; +} +#endif /* TODO extern INT dib7000m_set_gpio(struct dibDemod *demod, UCHAR num, UCHAR dir, UCHAR val); -- cgit v1.2.3 From 673d5418120f435a64966ef481502f7d6d72b039 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Sun, 8 Mar 2009 23:04:17 -0400 Subject: remove build-time dependencies on dib7000p From: Michael Krufky Priority: normal Signed-off-by: Michael Krufky --- linux/drivers/media/dvb/frontends/dib7000p.h | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/frontends/dib7000p.h b/linux/drivers/media/dvb/frontends/dib7000p.h index aab8112e2..4e3fd7639 100644 --- a/linux/drivers/media/dvb/frontends/dib7000p.h +++ b/linux/drivers/media/dvb/frontends/dib7000p.h @@ -49,6 +49,7 @@ extern int dib7000p_i2c_enumeration(struct i2c_adapter *i2c, struct dib7000p_config cfg[]); extern int dib7000p_set_gpio(struct dvb_frontend *, u8 num, u8 dir, u8 val); extern int dib7000p_set_wbd_ref(struct dvb_frontend *, u16 value); +extern int dib7000pc_detection(struct i2c_adapter *i2c_adap); #else static inline struct dvb_frontend *dib7000p_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, @@ -88,8 +89,12 @@ int dib7000p_set_wbd_ref(struct dvb_frontend *fe, u16 value) printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); return -ENODEV; } -#endif -extern int dib7000pc_detection(struct i2c_adapter *i2c_adap); +static inline int dib7000pc_detection(struct i2c_adapter *i2c_adap) +{ + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); + return -ENODEV; +} +#endif #endif -- cgit v1.2.3 From b887b4881914e00e3aab150d571d6ce9b8fd3f79 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Sun, 8 Mar 2009 23:59:09 -0400 Subject: remove build-time dependencies on dib3000mc From: Michael Krufky Priority: normal Signed-off-by: Michael Krufky --- linux/drivers/media/dvb/frontends/dib3000mc.h | 33 +++++++++++++++++++++++---- 1 file changed, 28 insertions(+), 5 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/frontends/dib3000mc.h b/linux/drivers/media/dvb/frontends/dib3000mc.h index 4142ed7a4..b49bf3cb1 100644 --- a/linux/drivers/media/dvb/frontends/dib3000mc.h +++ b/linux/drivers/media/dvb/frontends/dib3000mc.h @@ -40,18 +40,41 @@ struct dib3000mc_config { #define DEFAULT_DIB3000P_I2C_ADDRESS 24 #if defined(CONFIG_DVB_DIB3000MC) || (defined(CONFIG_DVB_DIB3000MC_MODULE) && defined(MODULE)) -extern struct dvb_frontend * dib3000mc_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib3000mc_config *cfg); +extern struct dvb_frontend *dib3000mc_attach(struct i2c_adapter *i2c_adap, + u8 i2c_addr, + struct dib3000mc_config *cfg); +extern int dib3000mc_i2c_enumeration(struct i2c_adapter *i2c, + int no_of_demods, u8 default_addr, + struct dib3000mc_config cfg[]); +extern +struct i2c_adapter *dib3000mc_get_tuner_i2c_master(struct dvb_frontend *demod, + int gating); #else -static inline struct dvb_frontend * dib3000mc_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib3000mc_config *cfg) +static inline +struct dvb_frontend *dib3000mc_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, + struct dib3000mc_config *cfg) { printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); return NULL; } -#endif // CONFIG_DVB_DIB3000MC -extern int dib3000mc_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 default_addr, struct dib3000mc_config cfg[]); +static inline +int dib3000mc_i2c_enumeration(struct i2c_adapter *i2c, + int no_of_demods, u8 default_addr, + struct dib3000mc_config cfg[]) +{ + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); + return -ENODEV; +} -extern struct i2c_adapter * dib3000mc_get_tuner_i2c_master(struct dvb_frontend *demod, int gating); +static inline +struct i2c_adapter *dib3000mc_get_tuner_i2c_master(struct dvb_frontend *demod, + int gating) +{ + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); + return NULL; +} +#endif // CONFIG_DVB_DIB3000MC extern int dib3000mc_pid_control(struct dvb_frontend *fe, int index, int pid,int onoff); extern int dib3000mc_pid_parse(struct dvb_frontend *fe, int onoff); -- cgit v1.2.3 From e1af4dfaf16276af7245872e76f74e21ef43ae24 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Mon, 9 Mar 2009 01:29:01 -0400 Subject: cleanup linewraps in dib7000p.h From: Michael Krufky Priority: normal Signed-off-by: Michael Krufky --- linux/drivers/media/dvb/frontends/dib7000p.h | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/frontends/dib7000p.h b/linux/drivers/media/dvb/frontends/dib7000p.h index 4e3fd7639..02a4c82f0 100644 --- a/linux/drivers/media/dvb/frontends/dib7000p.h +++ b/linux/drivers/media/dvb/frontends/dib7000p.h @@ -37,7 +37,8 @@ struct dib7000p_config { #define DEFAULT_DIB7000P_I2C_ADDRESS 18 -#if defined(CONFIG_DVB_DIB7000P) || (defined(CONFIG_DVB_DIB7000P_MODULE) && defined(MODULE)) +#if defined(CONFIG_DVB_DIB7000P) || (defined(CONFIG_DVB_DIB7000P_MODULE) && \ + defined(MODULE)) extern struct dvb_frontend *dib7000p_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib7000p_config *cfg); @@ -51,9 +52,9 @@ extern int dib7000p_set_gpio(struct dvb_frontend *, u8 num, u8 dir, u8 val); extern int dib7000p_set_wbd_ref(struct dvb_frontend *, u16 value); extern int dib7000pc_detection(struct i2c_adapter *i2c_adap); #else -static inline struct dvb_frontend *dib7000p_attach(struct i2c_adapter *i2c_adap, - u8 i2c_addr, - struct dib7000p_config *cfg) +static inline +struct dvb_frontend *dib7000p_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, + struct dib7000p_config *cfg) { printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); return NULL; @@ -61,30 +62,29 @@ static inline struct dvb_frontend *dib7000p_attach(struct i2c_adapter *i2c_adap, static inline struct i2c_adapter *dib7000p_get_i2c_master(struct dvb_frontend *fe, - enum dibx000_i2c_interface i, int x) + enum dibx000_i2c_interface i, + int x) { printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); return NULL; } -static inline -int dib7000p_i2c_enumeration(struct i2c_adapter *i2c, - int no_of_demods, u8 default_addr, - struct dib7000p_config cfg[]) +static inline int dib7000p_i2c_enumeration(struct i2c_adapter *i2c, + int no_of_demods, u8 default_addr, + struct dib7000p_config cfg[]) { printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); return -ENODEV; } -static inline -int dib7000p_set_gpio(struct dvb_frontend *fe, u8 num, u8 dir, u8 val) +static inline int dib7000p_set_gpio(struct dvb_frontend *fe, + u8 num, u8 dir, u8 val) { printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); return -ENODEV; } -static inline -int dib7000p_set_wbd_ref(struct dvb_frontend *fe, u16 value) +static inline int dib7000p_set_wbd_ref(struct dvb_frontend *fe, u16 value) { printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); return -ENODEV; -- cgit v1.2.3 From 8cd2e542d23ac4828db65c0cd55e9fb028fe786c Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Mon, 9 Mar 2009 01:37:55 -0400 Subject: cleanup linewraps in dib7000m.h From: Michael Krufky Priority: normal Signed-off-by: Michael Krufky --- linux/drivers/media/dvb/frontends/dib7000m.h | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/frontends/dib7000m.h b/linux/drivers/media/dvb/frontends/dib7000m.h index f93db0fda..113819ce9 100644 --- a/linux/drivers/media/dvb/frontends/dib7000m.h +++ b/linux/drivers/media/dvb/frontends/dib7000m.h @@ -40,8 +40,12 @@ struct dib7000m_config { #if defined(CONFIG_DVB_DIB7000M) || (defined(CONFIG_DVB_DIB7000M_MODULE) && \ defined(MODULE)) -extern struct dvb_frontend * dib7000m_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib7000m_config *cfg); -extern struct i2c_adapter * dib7000m_get_i2c_master(struct dvb_frontend *, enum dibx000_i2c_interface, int); +extern struct dvb_frontend *dib7000m_attach(struct i2c_adapter *i2c_adap, + u8 i2c_addr, + struct dib7000m_config *cfg); +extern struct i2c_adapter *dib7000m_get_i2c_master(struct dvb_frontend *, + enum dibx000_i2c_interface, + int); #else static inline struct dvb_frontend *dib7000m_attach(struct i2c_adapter *i2c_adap, -- cgit v1.2.3 From 096ca313d3f1dc9c98253944988c0eb0febb1fe2 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Mon, 9 Mar 2009 23:53:57 -0400 Subject: cleanup linewraps in dib3000mc.h From: Michael Krufky Priority: normal Signed-off-by: Michael Krufky --- linux/drivers/media/dvb/frontends/dib3000mc.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/frontends/dib3000mc.h b/linux/drivers/media/dvb/frontends/dib3000mc.h index b49bf3cb1..d75ffad2d 100644 --- a/linux/drivers/media/dvb/frontends/dib3000mc.h +++ b/linux/drivers/media/dvb/frontends/dib3000mc.h @@ -39,7 +39,8 @@ struct dib3000mc_config { #define DEFAULT_DIB3000MC_I2C_ADDRESS 16 #define DEFAULT_DIB3000P_I2C_ADDRESS 24 -#if defined(CONFIG_DVB_DIB3000MC) || (defined(CONFIG_DVB_DIB3000MC_MODULE) && defined(MODULE)) +#if defined(CONFIG_DVB_DIB3000MC) || (defined(CONFIG_DVB_DIB3000MC_MODULE) && \ + defined(MODULE)) extern struct dvb_frontend *dib3000mc_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib3000mc_config *cfg); -- cgit v1.2.3 From 5c3098fa20613d222446061e93a9035d5b26122d Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Mon, 9 Mar 2009 01:39:58 -0400 Subject: remove dib0070_ctrl_agc_filter from dib0070.h From: Michael Krufky This function prototype is defined but the function itself does not exist. Priority: normal Signed-off-by: Michael Krufky --- linux/drivers/media/dvb/frontends/dib0070.h | 2 -- 1 file changed, 2 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/frontends/dib0070.h b/linux/drivers/media/dvb/frontends/dib0070.h index 21f2c5161..9670f5d20 100644 --- a/linux/drivers/media/dvb/frontends/dib0070.h +++ b/linux/drivers/media/dvb/frontends/dib0070.h @@ -58,6 +58,4 @@ static inline u16 dib0070_wbd_offset(struct dvb_frontend *fe) } #endif -extern void dib0070_ctrl_agc_filter(struct dvb_frontend *, uint8_t open); - #endif -- cgit v1.2.3 From 74c1d5f410c25958fd587a05987e654bb9104d22 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 9 Mar 2009 12:11:21 +0100 Subject: ISA radio drivers: improve kernel log message From: Hans Verkuil It's much nicer if the log message tells you which io ports are possible, rather than having to run modinfo or look it up in the source or manual. Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/radio/radio-aimslab.c | 2 +- linux/drivers/media/radio/radio-aztech.c | 2 +- linux/drivers/media/radio/radio-cadet.c | 3 ++- linux/drivers/media/radio/radio-terratec.c | 2 +- linux/drivers/media/radio/radio-trust.c | 2 +- linux/drivers/media/radio/radio-zoltrix.c | 2 +- 6 files changed, 7 insertions(+), 6 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/radio/radio-aimslab.c b/linux/drivers/media/radio/radio-aimslab.c index 57b896968..7c3a81ad9 100644 --- a/linux/drivers/media/radio/radio-aimslab.c +++ b/linux/drivers/media/radio/radio-aimslab.c @@ -399,7 +399,7 @@ static int __init rtrack_init(void) rt->io = io; if (rt->io == -1) { - v4l2_err(v4l2_dev, "you must set an I/O address with io=0x???\n"); + v4l2_err(v4l2_dev, "you must set an I/O address with io=0x20f or 0x30f\n"); return -EINVAL; } diff --git a/linux/drivers/media/radio/radio-aztech.c b/linux/drivers/media/radio/radio-aztech.c index dcf53edc2..8826b90a3 100644 --- a/linux/drivers/media/radio/radio-aztech.c +++ b/linux/drivers/media/radio/radio-aztech.c @@ -362,7 +362,7 @@ static int __init aztech_init(void) az->io = io; if (az->io == -1) { - v4l2_err(v4l2_dev, "you must set an I/O address with io=0x???\n"); + v4l2_err(v4l2_dev, "you must set an I/O address with io=0x350 or 0x358\n"); return -EINVAL; } diff --git a/linux/drivers/media/radio/radio-cadet.c b/linux/drivers/media/radio/radio-cadet.c index 03e76bc74..373a34fde 100644 --- a/linux/drivers/media/radio/radio-cadet.c +++ b/linux/drivers/media/radio/radio-cadet.c @@ -686,7 +686,8 @@ static int __init cadet_init(void) /* Else we bail out */ if (dev->io < 0) { #ifdef MODULE - v4l2_err(v4l2_dev, "you must set an I/O address with io=0x???\n"); + v4l2_err(v4l2_dev, "you must set an I/O address with io=0x330, 0x332, 0x334,\n"); + v4l2_err(v4l2_dev, "0x336, 0x338, 0x33a, 0x33c or 0x33e\n"); #endif goto fail; } diff --git a/linux/drivers/media/radio/radio-terratec.c b/linux/drivers/media/radio/radio-terratec.c index b63443076..9bb1773ca 100644 --- a/linux/drivers/media/radio/radio-terratec.c +++ b/linux/drivers/media/radio/radio-terratec.c @@ -376,7 +376,7 @@ static int __init terratec_init(void) strlcpy(v4l2_dev->name, "terratec", sizeof(v4l2_dev->name)); tt->io = io; if (tt->io == -1) { - v4l2_err(v4l2_dev, "you must set an I/O address with io=0x???\n"); + v4l2_err(v4l2_dev, "you must set an I/O address with io=0x590 or 0x591\n"); return -EINVAL; } if (!request_region(tt->io, 2, "terratec")) { diff --git a/linux/drivers/media/radio/radio-trust.c b/linux/drivers/media/radio/radio-trust.c index 196db11de..9d2dcb0a7 100644 --- a/linux/drivers/media/radio/radio-trust.c +++ b/linux/drivers/media/radio/radio-trust.c @@ -384,7 +384,7 @@ static int __init trust_init(void) mutex_init(&tr->lock); if (tr->io == -1) { - v4l2_err(v4l2_dev, "You must set an I/O address with io=0x???\n"); + v4l2_err(v4l2_dev, "You must set an I/O address with io=0x0x350 or 0x358\n"); return -EINVAL; } if (!request_region(tr->io, 2, "Trust FM Radio")) { diff --git a/linux/drivers/media/radio/radio-zoltrix.c b/linux/drivers/media/radio/radio-zoltrix.c index 93bc72adb..3662f68da 100644 --- a/linux/drivers/media/radio/radio-zoltrix.c +++ b/linux/drivers/media/radio/radio-zoltrix.c @@ -414,7 +414,7 @@ static int __init zoltrix_init(void) strlcpy(v4l2_dev->name, "zoltrix", sizeof(v4l2_dev->name)); zol->io = io; if (zol->io == -1) { - v4l2_err(v4l2_dev, "You must set an I/O address with io=0x???\n"); + v4l2_err(v4l2_dev, "You must set an I/O address with io=0x20c or 0x30c\n"); return -EINVAL; } if (zol->io != 0x20c && zol->io != 0x30c) { -- cgit v1.2.3 From cc7dac29c9d92dd6beeb364950c93682d25e997e Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 10 Mar 2009 00:49:58 -0300 Subject: /frontends/Kconfig: Move af9013 Kconfig option to its proper place From: Mauro Carvalho Chehab af9013 is not a development tool. It is, instead, a DVB-T module. Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/frontends/Kconfig | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/frontends/Kconfig b/linux/drivers/media/dvb/frontends/Kconfig index 3205e302d..2887d3398 100644 --- a/linux/drivers/media/dvb/frontends/Kconfig +++ b/linux/drivers/media/dvb/frontends/Kconfig @@ -3,7 +3,7 @@ config DVB_FE_CUSTOMISE depends on DVB_CORE default N help - This allows the user to select/deselect frontend drivers for their + This allows the user to select/deselect frontend drivers for their hardware from the build. Use this option with care as deselecting frontends which are in fact @@ -14,7 +14,7 @@ config DVB_FE_CUSTOMISE if DVB_FE_CUSTOMISE -menu "Customise DVB Frontends" +menu "Customise DVB Frontends" comment "Multistandard (satellite) frontends" depends on DVB_CORE @@ -313,6 +313,13 @@ config DVB_TDA10048 help A DVB-T tuner module. Say Y when you want to support this frontend. +config DVB_AF9013 + tristate "Afatech AF9013 demodulator" + depends on DVB_CORE && I2C + default m if DVB_FE_CUSTOMISE + help + Say Y when you want to support this frontend. + comment "DVB-C (cable) frontends" depends on DVB_CORE @@ -503,13 +510,6 @@ comment "Tools to develop new frontends" config DVB_DUMMY_FE tristate "Dummy frontend driver" default n - -config DVB_AF9013 - tristate "Afatech AF9013 demodulator" - depends on DVB_CORE && I2C - default m if DVB_FE_CUSTOMISE - help - Say Y when you want to support this frontend. endmenu endif -- cgit v1.2.3 From 9469f9975ef9cd00fb23ec27109511c4b2a27350 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 10 Mar 2009 00:21:14 -0400 Subject: dib0700: enable DVB_FE_CUSTOMISE for dibcom frontends From: Michael Krufky There was never any build-time dependency of the dib0700 usb module on the dib0070 tuner module. Now that the build-time dependencies of dib0700 on dib3000mc, dib7000p and dib7000m have been removed in the previous changesets, we can enable DVB_FE_CUSTOMISE for these modules under config DVB_USB_DIB0700 Priority: normal Signed-off-by: Michael Krufky --- linux/drivers/media/dvb/dvb-usb/Kconfig | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/dvb-usb/Kconfig b/linux/drivers/media/dvb/dvb-usb/Kconfig index bbddc9fb6..310da6398 100644 --- a/linux/drivers/media/dvb/dvb-usb/Kconfig +++ b/linux/drivers/media/dvb/dvb-usb/Kconfig @@ -69,11 +69,11 @@ config DVB_USB_DIBUSB_MC config DVB_USB_DIB0700 tristate "DiBcom DiB0700 USB DVB devices (see help for supported devices)" depends on DVB_USB - select DVB_DIB7000P - select DVB_DIB7000M - select DVB_DIB3000MC + select DVB_DIB7000P if !DVB_FE_CUSTOMISE + select DVB_DIB7000M if !DVB_FE_CUSTOMISE + select DVB_DIB3000MC if !DVB_FE_CUSTOMISE select DVB_S5H1411 if !DVB_FE_CUSTOMISE - select DVB_TUNER_DIB0070 + select DVB_TUNER_DIB0070 if !DVB_FE_CUSTOMISE select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMIZE select MEDIA_TUNER_MT2266 if !MEDIA_TUNER_CUSTOMIZE select MEDIA_TUNER_XC2028 if !MEDIA_TUNER_CUSTOMIZE -- cgit v1.2.3 From b08b8d66d6c66efb91344fad801cabb14ced6c33 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 10 Mar 2009 02:30:23 -0300 Subject: Fix Kbuild MEDIA_TUNER_CUSTOMIZE dependencies From: Mauro Carvalho Chehab Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/common/tuners/Kconfig | 20 ++++++++++---------- linux/drivers/media/video/au0828/Kconfig | 6 +++--- linux/drivers/media/video/cx23885/Kconfig | 8 ++++---- linux/drivers/media/video/pvrusb2/Kconfig | 4 ++-- 4 files changed, 19 insertions(+), 19 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/common/tuners/Kconfig b/linux/drivers/media/common/tuners/Kconfig index 7969b695c..724e6870c 100644 --- a/linux/drivers/media/common/tuners/Kconfig +++ b/linux/drivers/media/common/tuners/Kconfig @@ -66,14 +66,14 @@ config MEDIA_TUNER_TDA8290 config MEDIA_TUNER_TDA827X tristate "Philips TDA827X silicon tuner" depends on VIDEO_MEDIA && I2C - default m if DVB_FE_CUSTOMISE + default m if MEDIA_TUNER_CUSTOMIZE help A DVB-T silicon tuner module. Say Y when you want to support this tuner. config MEDIA_TUNER_TDA18271 tristate "NXP TDA18271 silicon tuner" depends on VIDEO_MEDIA && I2C - default m if DVB_FE_CUSTOMISE + default m if MEDIA_TUNER_CUSTOMIZE help A silicon tuner module. Say Y when you want to support this tuner. @@ -110,28 +110,28 @@ config MEDIA_TUNER_MT20XX config MEDIA_TUNER_MT2060 tristate "Microtune MT2060 silicon IF tuner" depends on VIDEO_MEDIA && I2C - default m if DVB_FE_CUSTOMISE + default m if MEDIA_TUNER_CUSTOMIZE help A driver for the silicon IF tuner MT2060 from Microtune. config MEDIA_TUNER_MT2266 tristate "Microtune MT2266 silicon tuner" depends on VIDEO_MEDIA && I2C - default m if DVB_FE_CUSTOMISE + default m if MEDIA_TUNER_CUSTOMIZE help A driver for the silicon baseband tuner MT2266 from Microtune. config MEDIA_TUNER_MT2131 tristate "Microtune MT2131 silicon tuner" depends on VIDEO_MEDIA && I2C - default m if DVB_FE_CUSTOMISE + default m if MEDIA_TUNER_CUSTOMIZE help A driver for the silicon baseband tuner MT2131 from Microtune. config MEDIA_TUNER_QT1010 tristate "Quantek QT1010 silicon tuner" depends on VIDEO_MEDIA && I2C - default m if DVB_FE_CUSTOMISE + default m if MEDIA_TUNER_CUSTOMIZE help A driver for the silicon tuner QT1010 from Quantek. @@ -145,7 +145,7 @@ config MEDIA_TUNER_XC2028 config MEDIA_TUNER_XC5000 tristate "Xceive XC5000 silicon tuner" depends on VIDEO_MEDIA && I2C - default m if DVB_FE_CUSTOMISE + default m if MEDIA_TUNER_CUSTOMIZE help A driver for the silicon tuner XC5000 from Xceive. This device is only used inside a SiP called togther with a @@ -154,21 +154,21 @@ config MEDIA_TUNER_XC5000 config MEDIA_TUNER_MXL5005S tristate "MaxLinear MSL5005S silicon tuner" depends on VIDEO_MEDIA && I2C - default m if DVB_FE_CUSTOMISE + default m if MEDIA_TUNER_CUSTOMIZE help A driver for the silicon tuner MXL5005S from MaxLinear. config MEDIA_TUNER_MXL5007T tristate "MaxLinear MxL5007T silicon tuner" depends on VIDEO_MEDIA && I2C - default m if DVB_FE_CUSTOMISE + default m if MEDIA_TUNER_CUSTOMIZE help A driver for the silicon tuner MxL5007T from MaxLinear. config MEDIA_TUNER_MC44S803 tristate "Freescale MC44S803 Low Power CMOS Broadband tuners" depends on VIDEO_MEDIA && I2C - default m if DVB_FE_CUSTOMISE + default m if MEDIA_TUNER_CUSTOMIZE help Say Y here to support the Freescale MC44S803 based tuners diff --git a/linux/drivers/media/video/au0828/Kconfig b/linux/drivers/media/video/au0828/Kconfig index deb00e4ac..20993ae17 100644 --- a/linux/drivers/media/video/au0828/Kconfig +++ b/linux/drivers/media/video/au0828/Kconfig @@ -5,9 +5,9 @@ config VIDEO_AU0828 select I2C_ALGOBIT select VIDEO_TVEEPROM select DVB_AU8522 if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_XC5000 if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_MXL5007T if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_TDA18271 if !DVB_FE_CUSTOMISE + select MEDIA_TUNER_XC5000 if !MEDIA_TUNER_CUSTOMIZE + select MEDIA_TUNER_MXL5007T if !MEDIA_TUNER_CUSTOMIZE + select MEDIA_TUNER_TDA18271 if !MEDIA_TUNER_CUSTOMIZE ---help--- This is a video4linux driver for Auvitek's USB device. diff --git a/linux/drivers/media/video/cx23885/Kconfig b/linux/drivers/media/video/cx23885/Kconfig index 28896aa31..e603ceb28 100644 --- a/linux/drivers/media/video/cx23885/Kconfig +++ b/linux/drivers/media/video/cx23885/Kconfig @@ -20,10 +20,10 @@ config VIDEO_CX23885 select DVB_STV6110 if !DVB_FE_CUSTOMISE select DVB_STV0900 if !DVB_FE_CUSTOMISE select MEDIA_TUNER_MT2131 if !MEDIA_TUNER_CUSTOMIZE - select MEDIA_TUNER_XC2028 if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_TDA8290 if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_TDA18271 if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_XC5000 if !DVB_FE_CUSTOMISE + select MEDIA_TUNER_XC2028 if !MEDIA_TUNER_CUSTOMIZE + select MEDIA_TUNER_TDA8290 if !MEDIA_TUNER_CUSTOMIZE + select MEDIA_TUNER_TDA18271 if !MEDIA_TUNER_CUSTOMIZE + select MEDIA_TUNER_XC5000 if !MEDIA_TUNER_CUSTOMIZE ---help--- This is a video4linux driver for Conexant 23885 based TV cards. diff --git a/linux/drivers/media/video/pvrusb2/Kconfig b/linux/drivers/media/video/pvrusb2/Kconfig index bb4271393..17cde1757 100644 --- a/linux/drivers/media/video/pvrusb2/Kconfig +++ b/linux/drivers/media/video/pvrusb2/Kconfig @@ -41,9 +41,9 @@ config VIDEO_PVRUSB2_DVB select DVB_S5H1409 if !DVB_FE_CUSTOMISE select DVB_S5H1411 if !DVB_FE_CUSTOMISE select DVB_TDA10048 if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_TDA18271 if !DVB_FE_CUSTOMISE + select MEDIA_TUNER_TDA18271 if !MEDIA_TUNER_CUSTOMIZE select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMIZE - select MEDIA_TUNER_TDA8290 if !DVB_FE_CUSTOMISE + select MEDIA_TUNER_TDA8290 if !MEDIA_TUNER_CUSTOMIZE ---help--- This option enables a DVB interface for the pvrusb2 driver. -- cgit v1.2.3 From ea258810bf8de7d5d78d74aafe44e0ea8e7f8783 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 10 Mar 2009 05:31:34 -0300 Subject: avoid loading the entire videodev.h header for drivers that are already V4L2 only From: Mauro Carvalho Chehab Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/bt8xx/bttv.h | 2 +- linux/drivers/media/video/bt8xx/bttvp.h | 1 - linux/drivers/media/video/cpia2/cpia2_v4l.c | 1 + linux/drivers/media/video/cx23885/cx23885-video.c | 5 ----- linux/drivers/media/video/cx88/cx88-video.c | 5 ----- linux/drivers/media/video/msp3400-driver.c | 2 +- linux/drivers/media/video/mxb.c | 1 - linux/drivers/media/video/ov7670.c | 2 +- linux/drivers/media/video/saa7134/saa7134-video.c | 5 ----- linux/drivers/media/video/saa7146.h | 2 -- linux/drivers/media/video/v4l2-ioctl.c | 1 + linux/drivers/media/video/vivi.c | 4 ---- linux/drivers/media/video/w9966.c | 2 +- linux/drivers/media/video/w9968cf.c | 1 + linux/drivers/media/video/zoran/zoran_driver.c | 2 +- 15 files changed, 8 insertions(+), 28 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/bt8xx/bttv.h b/linux/drivers/media/video/bt8xx/bttv.h index 35f943337..93a1e989a 100644 --- a/linux/drivers/media/video/bt8xx/bttv.h +++ b/linux/drivers/media/video/bt8xx/bttv.h @@ -14,7 +14,7 @@ #ifndef _BTTV_H_ #define _BTTV_H_ -#include +#include #include #include "compat.h" #include diff --git a/linux/drivers/media/video/bt8xx/bttvp.h b/linux/drivers/media/video/bt8xx/bttvp.h index 20b1ad68a..113f28320 100644 --- a/linux/drivers/media/video/bt8xx/bttvp.h +++ b/linux/drivers/media/video/bt8xx/bttvp.h @@ -32,7 +32,6 @@ #include #include #include -#include #include #include #include diff --git a/linux/drivers/media/video/cpia2/cpia2_v4l.c b/linux/drivers/media/video/cpia2/cpia2_v4l.c index 9c25894fd..d4099f531 100644 --- a/linux/drivers/media/video/cpia2/cpia2_v4l.c +++ b/linux/drivers/media/video/cpia2/cpia2_v4l.c @@ -37,6 +37,7 @@ #include #include #include +#include #include #include "cpia2.h" diff --git a/linux/drivers/media/video/cx23885/cx23885-video.c b/linux/drivers/media/video/cx23885/cx23885-video.c index 131fc740a..ba22520a2 100644 --- a/linux/drivers/media/video/cx23885/cx23885-video.c +++ b/linux/drivers/media/video/cx23885/cx23885-video.c @@ -36,11 +36,6 @@ #include #include -#ifdef CONFIG_VIDEO_V4L1_COMPAT -/* Include V4L1 specific functions. Should be removed soon */ -#include -#endif - MODULE_DESCRIPTION("v4l2 driver module for cx23885 based TV cards"); MODULE_AUTHOR("Steven Toth "); MODULE_LICENSE("GPL"); diff --git a/linux/drivers/media/video/cx88/cx88-video.c b/linux/drivers/media/video/cx88/cx88-video.c index 005a78aab..827168d67 100644 --- a/linux/drivers/media/video/cx88/cx88-video.c +++ b/linux/drivers/media/video/cx88/cx88-video.c @@ -42,11 +42,6 @@ #include #include -#ifdef CONFIG_VIDEO_V4L1_COMPAT -/* Include V4L1 specific functions. Should be removed soon */ -#include -#endif - MODULE_DESCRIPTION("v4l2 driver module for cx2388x based TV cards"); MODULE_AUTHOR("Gerd Knorr [SuSE Labs]"); MODULE_LICENSE("GPL"); diff --git a/linux/drivers/media/video/msp3400-driver.c b/linux/drivers/media/video/msp3400-driver.c index 61b54317f..f1dc5739b 100644 --- a/linux/drivers/media/video/msp3400-driver.c +++ b/linux/drivers/media/video/msp3400-driver.c @@ -57,7 +57,7 @@ #else #include #endif -#include +#include #include #include #include diff --git a/linux/drivers/media/video/mxb.c b/linux/drivers/media/video/mxb.c index fda3b7581..c85cfd27e 100644 --- a/linux/drivers/media/video/mxb.c +++ b/linux/drivers/media/video/mxb.c @@ -25,7 +25,6 @@ #include #include -#include #include #include #include "compat.h" diff --git a/linux/drivers/media/video/ov7670.c b/linux/drivers/media/video/ov7670.c index e03154536..f0e1a56eb 100644 --- a/linux/drivers/media/video/ov7670.c +++ b/linux/drivers/media/video/ov7670.c @@ -14,7 +14,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/linux/drivers/media/video/saa7134/saa7134-video.c b/linux/drivers/media/video/saa7134/saa7134-video.c index be7f98bc0..d188aae14 100644 --- a/linux/drivers/media/video/saa7134/saa7134-video.c +++ b/linux/drivers/media/video/saa7134/saa7134-video.c @@ -31,11 +31,6 @@ #include "saa7134.h" #include -#ifdef CONFIG_VIDEO_V4L1_COMPAT -/* Include V4L1 specific functions. Should be removed soon */ -#include -#endif - /* ------------------------------------------------------------------ */ unsigned int video_debug; diff --git a/linux/drivers/media/video/saa7146.h b/linux/drivers/media/video/saa7146.h index 2830b5e33..9fadb331a 100644 --- a/linux/drivers/media/video/saa7146.h +++ b/linux/drivers/media/video/saa7146.h @@ -25,8 +25,6 @@ #include #include -#include - #ifndef O_NONCAP #define O_NONCAP O_TRUNC #endif diff --git a/linux/drivers/media/video/v4l2-ioctl.c b/linux/drivers/media/video/v4l2-ioctl.c index 230299801..d33730fc0 100644 --- a/linux/drivers/media/video/v4l2-ioctl.c +++ b/linux/drivers/media/video/v4l2-ioctl.c @@ -17,6 +17,7 @@ #include #define __OLD_VIDIOC_ /* To allow fixing old calls */ +#include #include #ifdef CONFIG_VIDEO_V4L1 diff --git a/linux/drivers/media/video/vivi.c b/linux/drivers/media/video/vivi.c index 76f7dfc32..a6f19b594 100644 --- a/linux/drivers/media/video/vivi.c +++ b/linux/drivers/media/video/vivi.c @@ -29,10 +29,6 @@ #include "compat.h" #include #include -#ifdef CONFIG_VIDEO_V4L1_COMPAT -/* Include V4L1 specific functions. Should be removed soon */ -#include -#endif #include #include #include diff --git a/linux/drivers/media/video/w9966.c b/linux/drivers/media/video/w9966.c index b8ede9e3f..75d8debe7 100644 --- a/linux/drivers/media/video/w9966.c +++ b/linux/drivers/media/video/w9966.c @@ -58,7 +58,7 @@ #include #include #include "compat.h" -#include +#include #include #include #include diff --git a/linux/drivers/media/video/w9968cf.c b/linux/drivers/media/video/w9968cf.c index dd519e48c..0478ee33e 100644 --- a/linux/drivers/media/video/w9968cf.c +++ b/linux/drivers/media/video/w9968cf.c @@ -42,6 +42,7 @@ #include #include #include +#include #include #include "w9968cf.h" diff --git a/linux/drivers/media/video/zoran/zoran_driver.c b/linux/drivers/media/video/zoran/zoran_driver.c index 1560c1e4c..4afd14308 100644 --- a/linux/drivers/media/video/zoran/zoran_driver.c +++ b/linux/drivers/media/video/zoran/zoran_driver.c @@ -59,7 +59,7 @@ #include -#include +#include #include #include #include "videocodec.h" -- cgit v1.2.3 From 1c1afdf2276238132ec99de72499b60b1944b887 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Tue, 10 Mar 2009 14:42:44 +0100 Subject: msp3400: remove obsolete V4L1 code From: Hans Verkuil There are no drivers left that call msp3400 with V4L1 commands. Remove it from this driver. Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/msp3400-driver.c | 116 ----------------------------- 1 file changed, 116 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/msp3400-driver.c b/linux/drivers/media/video/msp3400-driver.c index 61b54317f..fbe69a62d 100644 --- a/linux/drivers/media/video/msp3400-driver.c +++ b/linux/drivers/media/video/msp3400-driver.c @@ -371,29 +371,6 @@ int msp_sleep(struct msp_state *state, int timeout) } /* ------------------------------------------------------------------------ */ -#ifdef CONFIG_VIDEO_ALLOW_V4L1 -static int msp_mode_v4l2_to_v4l1(int rxsubchans, int audmode) -{ - if (rxsubchans == V4L2_TUNER_SUB_MONO) - return VIDEO_SOUND_MONO; - if (rxsubchans == V4L2_TUNER_SUB_STEREO) - return VIDEO_SOUND_STEREO; - if (audmode == V4L2_TUNER_MODE_LANG2) - return VIDEO_SOUND_LANG2; - return VIDEO_SOUND_LANG1; -} - -static int msp_mode_v4l1_to_v4l2(int mode) -{ - if (mode & VIDEO_SOUND_STEREO) - return V4L2_TUNER_MODE_STEREO; - if (mode & VIDEO_SOUND_LANG2) - return V4L2_TUNER_MODE_LANG2; - if (mode & VIDEO_SOUND_LANG1) - return V4L2_TUNER_MODE_LANG1; - return V4L2_TUNER_MODE_MONO; -} -#endif static int msp_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) { @@ -487,96 +464,6 @@ static int msp_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) return 0; } -#ifdef CONFIG_VIDEO_ALLOW_V4L1 -static long msp_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) -{ - struct msp_state *state = to_state(sd); - struct i2c_client *client = v4l2_get_subdevdata(sd); - - switch (cmd) { - /* --- v4l ioctls --- */ - /* take care: bttv does userspace copying, we'll get a - kernel pointer here... */ - case VIDIOCGAUDIO: - { - struct video_audio *va = arg; - - va->flags |= VIDEO_AUDIO_VOLUME | VIDEO_AUDIO_MUTABLE; - if (state->has_sound_processing) - va->flags |= VIDEO_AUDIO_BALANCE | - VIDEO_AUDIO_BASS | - VIDEO_AUDIO_TREBLE; - if (state->muted) - va->flags |= VIDEO_AUDIO_MUTE; - va->volume = state->volume; - va->balance = state->volume ? state->balance : 32768; - va->bass = state->bass; - va->treble = state->treble; - - if (state->radio) - break; - if (state->opmode == OPMODE_AUTOSELECT) - msp_detect_stereo(client); - va->mode = msp_mode_v4l2_to_v4l1(state->rxsubchans, state->audmode); - break; - } - - case VIDIOCSAUDIO: - { - struct video_audio *va = arg; - - state->muted = (va->flags & VIDEO_AUDIO_MUTE); - state->volume = va->volume; - state->balance = va->balance; - state->bass = va->bass; - state->treble = va->treble; - msp_set_audio(client); - - if (va->mode != 0 && state->radio == 0 && - state->audmode != msp_mode_v4l1_to_v4l2(va->mode)) { - state->audmode = msp_mode_v4l1_to_v4l2(va->mode); - msp_set_audmode(client); - } - break; - } - - case VIDIOCSCHAN: - { - struct video_channel *vc = arg; - int update = 0; - v4l2_std_id std; - - if (state->radio) - update = 1; - state->radio = 0; - if (vc->norm == VIDEO_MODE_PAL) - std = V4L2_STD_PAL; - else if (vc->norm == VIDEO_MODE_SECAM) - std = V4L2_STD_SECAM; - else - std = V4L2_STD_NTSC; - if (std != state->v4l2_std) { - state->v4l2_std = std; - update = 1; - } - if (update) - msp_wake_thread(client); - break; - } - - case VIDIOCSFREQ: - { - /* new channel -- kick audio carrier scan */ - msp_wake_thread(client); - break; - } - default: - return -ENOIOCTLCMD; - } - return 0; -} -#endif - /* --- v4l2 ioctls --- */ static int msp_s_radio(struct v4l2_subdev *sd) { @@ -827,9 +714,6 @@ static const struct v4l2_subdev_core_ops msp_core_ops = { .g_ctrl = msp_g_ctrl, .s_ctrl = msp_s_ctrl, .queryctrl = msp_queryctrl, -#ifdef CONFIG_VIDEO_ALLOW_V4L1 - .ioctl = msp_ioctl, -#endif }; static const struct v4l2_subdev_tuner_ops msp_tuner_ops = { -- cgit v1.2.3 From 11fac5cc5ec5cdba94e722f55d09a91dfc0df95a Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Tue, 10 Mar 2009 18:06:40 +0200 Subject: zl10353: i2c_gate_ctrl bug fix From: Antti Palosaari zl10353 i2c-gate was always closed and due to that devices having tuner behind i2c-gate were broken. Add module configuration which allows disabling i2c-gate only when really needed. Priority: high Signed-off-by: Antti Palosaari --- linux/drivers/media/dvb/frontends/zl10353.c | 2 +- linux/drivers/media/dvb/frontends/zl10353.h | 3 +++ linux/drivers/media/video/saa7134/saa7134-dvb.c | 1 + 3 files changed, 5 insertions(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/frontends/zl10353.c b/linux/drivers/media/dvb/frontends/zl10353.c index be5d7ef7c..96ccc1720 100644 --- a/linux/drivers/media/dvb/frontends/zl10353.c +++ b/linux/drivers/media/dvb/frontends/zl10353.c @@ -601,7 +601,7 @@ static int zl10353_i2c_gate_ctrl(struct dvb_frontend* fe, int enable) struct zl10353_state *state = fe->demodulator_priv; u8 val = 0x0a; - if (state->config.no_tuner) { + if (state->config.disable_i2c_gate_ctrl) { /* No tuner attached to the internal I2C bus */ /* If set enable I2C bridge, the main I2C bus stopped hardly */ return 0; diff --git a/linux/drivers/media/dvb/frontends/zl10353.h b/linux/drivers/media/dvb/frontends/zl10353.h index fdbb88ff7..2287bac46 100644 --- a/linux/drivers/media/dvb/frontends/zl10353.h +++ b/linux/drivers/media/dvb/frontends/zl10353.h @@ -38,6 +38,9 @@ struct zl10353_config /* set if parallel ts output is required */ int parallel_ts; + + /* set if i2c_gate_ctrl disable is required */ + u8 disable_i2c_gate_ctrl:1; }; #if defined(CONFIG_DVB_ZL10353) || (defined(CONFIG_DVB_ZL10353_MODULE) && defined(MODULE)) diff --git a/linux/drivers/media/video/saa7134/saa7134-dvb.c b/linux/drivers/media/video/saa7134/saa7134-dvb.c index 7745cad95..176aebda9 100644 --- a/linux/drivers/media/video/saa7134/saa7134-dvb.c +++ b/linux/drivers/media/video/saa7134/saa7134-dvb.c @@ -863,6 +863,7 @@ static struct zl10353_config behold_h6_config = { .demod_address = 0x1e>>1, .no_tuner = 1, .parallel_ts = 1, + .disable_i2c_gate_ctrl = 1, }; /* ================================================================== -- cgit v1.2.3 From 170f8d4937939b9a0252e62983e0a508b3954897 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 10 Mar 2009 16:55:14 +0000 Subject: flexcop-pci: Print a message in case the new stream watchdog detects a problem From: Matthias Schwarzott Print a message in case the new software IRQ watchdog detects a problem. I choose the info message category, this can be changed if not appropriate. Signed-off-by: Matthias Schwarzott CC: Patrick Boettcher Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/b2c2/flexcop-pci.c | 1 + 1 file changed, 1 insertion(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/b2c2/flexcop-pci.c b/linux/drivers/media/dvb/b2c2/flexcop-pci.c index 2905ffccf..72710fee2 100644 --- a/linux/drivers/media/dvb/b2c2/flexcop-pci.c +++ b/linux/drivers/media/dvb/b2c2/flexcop-pci.c @@ -133,6 +133,7 @@ static void flexcop_pci_irq_check_work(struct work_struct *work) deb_chk("no IRQ since the last check\n"); if (fc_pci->stream_problem++ == 3) { struct dvb_demux_feed *feed; + deb_info("flexcop-pci: stream problem, resetting pid filter\n"); spin_lock_irq(&fc->demux.lock); list_for_each_entry(feed, &fc->demux.feed_list, -- cgit v1.2.3 From 931dc1b26d45e6f38c491e30aeaa32534d56f6ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20Andr=C3=A9n?= Date: Tue, 10 Mar 2009 20:45:57 +0100 Subject: gspca - m5602-ov9650: Add ASUS A6K vflip quirk MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: Erik Andrén The ASUS A6K needs the vflip quirk. Thanks to Marco Baldo for reporting the issue. Priority: normal Signed-off-by: Erik Andrén --- linux/drivers/media/video/gspca/m5602/m5602_ov9650.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c index 5378b8d40..bbf9935df 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c @@ -89,6 +89,13 @@ static DMI_MATCH(DMI_PRODUCT_NAME, "A6Kt") } }, + { + .ident = "ASUS A6K", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "A6K") + } + }, { .ident = "Alienware Aurora m9700", .matches = { -- cgit v1.2.3 From 47b7123665629b4f3d24173609a0d3b398c7132c Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 10 Mar 2009 22:08:06 +0000 Subject: Add support for Terratec Cinergy HT PCI MKII From: Stephan Wienczny This patch adds support for Terratec Cinergy HT PCI MKII with card id 79. Its more or less a copy of Pinnacle Hybrid PCTV. Thanks to k1ngf1sher on forum.ubuntuusers.de for the idea to copy that card. Priority: normal Signed-off-by: Stephan Wienczny Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/cx88/cx88-cards.c | 38 +++++++++++++++++++++++++++++ linux/drivers/media/video/cx88/cx88-dvb.c | 16 ++++++++++++ linux/drivers/media/video/cx88/cx88.h | 1 + 3 files changed, 55 insertions(+) (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 f9b5a9c09..b3d966ad5 100644 --- a/linux/drivers/media/video/cx88/cx88-cards.c +++ b/linux/drivers/media/video/cx88/cx88-cards.c @@ -1967,6 +1967,39 @@ static const struct cx88_board cx88_boards[] = { } }, .mpeg = CX88_MPEG_DVB, }, + [CX88_BOARD_TERRATEC_CINERGY_HT_PCI_MKII] = { + .name = "Terratec Cinergy HT PCI MKII", + .tuner_type = TUNER_XC2028, + .tuner_addr = 0x61, + .radio_type = TUNER_XC2028, + .radio_addr = 0x61, + .input = { { + .type = CX88_VMUX_TELEVISION, + .vmux = 0, + .gpio0 = 0x004ff, + .gpio1 = 0x010ff, + .gpio2 = 0x00001, + }, { + .type = CX88_VMUX_COMPOSITE1, + .vmux = 1, + .gpio0 = 0x004fb, + .gpio1 = 0x010ef, + .audioroute = 1, + }, { + .type = CX88_VMUX_SVIDEO, + .vmux = 2, + .gpio0 = 0x004fb, + .gpio1 = 0x010ef, + .audioroute = 1, + } }, + .radio = { + .type = CX88_RADIO, + .gpio0 = 0x004ff, + .gpio1 = 0x010ff, + .gpio2 = 0x0ff, + }, + .mpeg = CX88_MPEG_DVB, + }, }; /* ------------------------------------------------------------------ */ @@ -2376,6 +2409,10 @@ static const struct cx88_subid cx88_subids[] = { .subvendor = 0xb200, .subdevice = 0x4200, .card = CX88_BOARD_SATTRADE_ST4200, + }, { + .subvendor = 0x153b, + .subdevice = 0x1177, + .card = CX88_BOARD_TERRATEC_CINERGY_HT_PCI_MKII, }, }; @@ -2852,6 +2889,7 @@ void cx88_setup_xc3028(struct cx88_core *core, struct xc2028_ctrl *ctl) */ break; case CX88_BOARD_PINNACLE_HYBRID_PCTV: + case CX88_BOARD_TERRATEC_CINERGY_HT_PCI_MKII: ctl->demod = XC3028_FE_ZARLINK456; ctl->mts = 1; break; diff --git a/linux/drivers/media/video/cx88/cx88-dvb.c b/linux/drivers/media/video/cx88/cx88-dvb.c index 488126ad6..10cf470ce 100644 --- a/linux/drivers/media/video/cx88/cx88-dvb.c +++ b/linux/drivers/media/video/cx88/cx88-dvb.c @@ -242,6 +242,12 @@ static struct mt352_config dvico_fusionhdtv_dual = { .demod_init = dvico_dual_demod_init, }; +static struct zl10353_config cx88_terratec_cinergy_ht_pci_mkii_config = { + .demod_address = (0x1e >> 1), + .no_tuner = 1, + .if2 = 45600, +}; + #if defined(CONFIG_VIDEO_CX88_VP3054) || (defined(CONFIG_VIDEO_CX88_VP3054_MODULE) && defined(MODULE)) static int dntv_live_dvbt_pro_demod_init(struct dvb_frontend* fe) { @@ -1138,6 +1144,16 @@ static int dvb_register(struct cx8802_dev *dev) if (fe0->dvb.frontend != NULL) fe0->dvb.frontend->ops.set_voltage = tevii_dvbs_set_voltage; break; + case CX88_BOARD_TERRATEC_CINERGY_HT_PCI_MKII: + fe0->dvb.frontend = dvb_attach(zl10353_attach, + &cx88_terratec_cinergy_ht_pci_mkii_config, + &core->i2c_adap); + if (fe0->dvb.frontend) { + fe0->dvb.frontend->ops.i2c_gate_ctrl = NULL; + if (attach_xc3028(0x61, dev) < 0) + goto frontend_detach; + } + break; default: printk(KERN_ERR "%s/2: The frontend of your DVB/ATSC card isn't supported yet\n", core->name); diff --git a/linux/drivers/media/video/cx88/cx88.h b/linux/drivers/media/video/cx88/cx88.h index 2227d93c7..1372d2b7b 100644 --- a/linux/drivers/media/video/cx88/cx88.h +++ b/linux/drivers/media/video/cx88/cx88.h @@ -232,6 +232,7 @@ extern struct sram_channel cx88_sram_channels[]; #define CX88_BOARD_SATTRADE_ST4200 76 #define CX88_BOARD_TBS_8910 77 #define CX88_BOARD_PROF_6200 78 +#define CX88_BOARD_TERRATEC_CINERGY_HT_PCI_MKII 79 enum cx88_itype { CX88_VMUX_COMPOSITE1 = 1, -- cgit v1.2.3 From 24633f3642291c4afb7f6839f0d7e2c1ea7c2be1 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 10 Mar 2009 21:16:26 -0300 Subject: Some additional CodingStyle and minor fixes From: Srinivasa Deevi > changed the pcb-config.c/h to pcb-cfg.c/h for short names. Signed-off-by: Srinivasa Deevi > Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/cx231xx/Kconfig | 50 +- linux/drivers/media/video/cx231xx/Makefile | 7 +- linux/drivers/media/video/cx231xx/cx231xx-audio.c | 14 +- linux/drivers/media/video/cx231xx/cx231xx-avcore.c | 305 +++---- linux/drivers/media/video/cx231xx/cx231xx-cards.c | 248 +++--- .../drivers/media/video/cx231xx/cx231xx-conf-reg.h | 299 +++---- linux/drivers/media/video/cx231xx/cx231xx-core.c | 13 +- linux/drivers/media/video/cx231xx/cx231xx-i2c.c | 12 +- .../drivers/media/video/cx231xx/cx231xx-pcb-cfg.c | 793 +++++++++++++++++ .../drivers/media/video/cx231xx/cx231xx-pcb-cfg.h | 235 ++++++ linux/drivers/media/video/cx231xx/cx231xx-reg.h | 934 ++++++++++----------- linux/drivers/media/video/cx231xx/cx231xx-video.c | 8 +- linux/drivers/media/video/cx231xx/cx231xx.h | 14 +- 13 files changed, 1961 insertions(+), 971 deletions(-) create mode 100644 linux/drivers/media/video/cx231xx/cx231xx-pcb-cfg.c create mode 100644 linux/drivers/media/video/cx231xx/cx231xx-pcb-cfg.h (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/cx231xx/Kconfig b/linux/drivers/media/video/cx231xx/Kconfig index 0f0e2b9d9..7a6700fb0 100644 --- a/linux/drivers/media/video/cx231xx/Kconfig +++ b/linux/drivers/media/video/cx231xx/Kconfig @@ -1,35 +1,35 @@ config VIDEO_CX231XX - tristate "Conexant cx231xx USB video capture support" - depends on VIDEO_DEV && I2C && INPUT - select VIDEO_TUNER - select VIDEO_TVEEPROM - select VIDEO_IR - select VIDEOBUF_VMALLOC - select VIDEO_CX25840 - select VIDEO_CX231XX_ALSA + tristate "Conexant cx231xx USB video capture support" + depends on VIDEO_DEV && I2C && INPUT + select VIDEO_TUNER + select VIDEO_TVEEPROM + select VIDEO_IR + select VIDEOBUF_VMALLOC + select VIDEO_CX25840 + select VIDEO_CX231XX_ALSA - ---help--- - This is a video4linux driver for Conexant 231xx USB based TV cards. + ---help--- + This is a video4linux driver for Conexant 231xx USB based TV cards. - To compile this driver as a module, choose M here: the - module will be called cx231xx + To compile this driver as a module, choose M here: the + module will be called cx231xx config VIDEO_CX231XX_ALSA tristate "Conexant Cx231xx ALSA audio module" - depends on VIDEO_CX231XX && SND - select SND_PCM + depends on VIDEO_CX231XX && SND + select SND_PCM - ---help--- - This is an ALSA driver for Cx231xx USB based TV cards. + ---help--- + This is an ALSA driver for Cx231xx USB based TV cards. - To compile this driver as a module, choose M here: the - module will be called cx231xx-alsa + To compile this driver as a module, choose M here: the + module will be called cx231xx-alsa config VIDEO_CX231XX_DVB - tristate "DVB/ATSC Support for Cx231xx based TV cards" - depends on VIDEO_CX231XX && DVB_CORE - select VIDEOBUF_DVB - select MEDIA_TUNER_XC5000 if !DVB_FE_CUSTOMIZE - ---help--- - This adds support for DVB cards based on the - Conexant cx231xx chips. + tristate "DVB/ATSC Support for Cx231xx based TV cards" + depends on VIDEO_CX231XX && DVB_CORE + select VIDEOBUF_DVB + select MEDIA_TUNER_XC5000 if !DVB_FE_CUSTOMISE + ---help--- + This adds support for DVB cards based on the + Conexant cx231xx chips. diff --git a/linux/drivers/media/video/cx231xx/Makefile b/linux/drivers/media/video/cx231xx/Makefile index 2590a09f3..1dad93619 100644 --- a/linux/drivers/media/video/cx231xx/Makefile +++ b/linux/drivers/media/video/cx231xx/Makefile @@ -1,11 +1,8 @@ cx231xx-objs := cx231xx-video.o cx231xx-i2c.o cx231xx-cards.o cx231xx-core.o \ - cx231xx-avcore.o cx231xx-pcb-config.o cx231xx-vbi.o - -cx231xx-alsa-objs := cx231xx-audio.o - + cx231xx-avcore.o cx231xx-pcb-cfg.o cx231xx-vbi.o obj-$(CONFIG_VIDEO_CX231XX) += cx231xx.o -obj-$(CONFIG_VIDEO_CX231XX_ALSA) += cx231xx-alsa.o +obj-$(CONFIG_VIDEO_CX231XX_ALSA) += cx231xx-audio.o obj-$(CONFIG_VIDEO_CX231XX_DVB) += cx231xx-dvb.o EXTRA_CFLAGS += -Idrivers/media/video diff --git a/linux/drivers/media/video/cx231xx/cx231xx-audio.c b/linux/drivers/media/video/cx231xx/cx231xx-audio.c index 67d3952c7..b6f099042 100644 --- a/linux/drivers/media/video/cx231xx/cx231xx-audio.c +++ b/linux/drivers/media/video/cx231xx/cx231xx-audio.c @@ -39,16 +39,15 @@ #include #include #include "cx231xx.h" -#include "cx231xx-pcb-config.h" static int debug; module_param(debug, int, 0644); MODULE_PARM_DESC(debug, "activates debug info"); #define dprintk(fmt, arg...) do { \ - if (debug) \ - printk(KERN_INFO "cx231xx-audio %s: " fmt, \ - __func__, ##arg); \ + if (debug) \ + printk(KERN_INFO "cx231xx-audio %s: " fmt, \ + __func__, ##arg); \ } while (0) static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; @@ -296,9 +295,10 @@ static snd_pcm_hardware_t snd_cx231xx_hw_capture = { #else static struct snd_pcm_hardware snd_cx231xx_hw_capture = { #endif - .info = SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_MMAP_VALID, + .info = SNDRV_PCM_INFO_BLOCK_TRANSFER | + SNDRV_PCM_INFO_MMAP | + SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_MMAP_VALID, .formats = SNDRV_PCM_FMTBIT_S16_LE, diff --git a/linux/drivers/media/video/cx231xx/cx231xx-avcore.c b/linux/drivers/media/video/cx231xx/cx231xx-avcore.c index 8bbe518f4..226299d62 100644 --- a/linux/drivers/media/video/cx231xx/cx231xx-avcore.c +++ b/linux/drivers/media/video/cx231xx/cx231xx-avcore.c @@ -41,7 +41,7 @@ /****************************************************************************** * C O L I B R I - B L O C K C O N T R O L functions * - ********************************************************************* ********/ + ******************************************************************************/ int cx231xx_colibri_init_super_block(struct cx231xx *dev, u32 ref_count) { int status = 0; @@ -53,29 +53,44 @@ int cx231xx_colibri_init_super_block(struct cx231xx *dev, u32 ref_count) temp = (u8) (ref_count & 0xff); status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, SUP_BLK_TUNE2, 2, temp, 1); + if (status < 0) + return status; status = cx231xx_read_i2c_data(dev, Colibri_DEVICE_ADDRESS, SUP_BLK_TUNE2, 2, &colibri_power_status, 1); + if (status < 0) + return status; temp = (u8) ((ref_count & 0x300) >> 8); temp |= 0x40; status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, SUP_BLK_TUNE1, 2, temp, 1); + if (status < 0) + return status; + status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, SUP_BLK_PLL2, 2, 0x0f, 1); + if (status < 0) + return status; /* enable pll */ while (colibri_power_status != 0x18) { status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, SUP_BLK_PWRDN, 2, 0x18, 1); + if (status < 0) { + cx231xx_info( + ": Init Super Block failed in send cmd\n"); + break; + } + status = cx231xx_read_i2c_data(dev, Colibri_DEVICE_ADDRESS, SUP_BLK_PWRDN, 2, &colibri_power_status, 1); colibri_power_status &= 0xff; if (status < 0) { cx231xx_info( - ": Init Super Block failed in send/receive cmds\n"); + ": Init Super Block failed in receive cmd\n"); break; } i++; @@ -93,6 +108,9 @@ int cx231xx_colibri_init_super_block(struct cx231xx *dev, u32 ref_count) /* start tuning filter */ status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, SUP_BLK_TUNE3, 2, 0x40, 1); + if (status < 0) + return status; + msleep(5); /* exit tuning */ @@ -188,7 +206,10 @@ int cx231xx_colibri_setup_AFE_for_baseband(struct cx231xx *dev) } /* - we have 3 channel + The Analog Front End in Cx231xx has 3 channels. These + channels are used to share between different inputs + like tuner, s-video and composite inputs. + channel 1 ----- pin 1 to pin4(in reg is 1-4) channel 2 ----- pin 5 to pin8(in reg is 5-8) channel 3 ----- pin 9 to pin 12(in reg is 9-11) @@ -242,6 +263,11 @@ int cx231xx_colibri_set_mode(struct cx231xx *dev, enum AFE_MODE mode) { int status = 0; + /* + * FIXME: We need to implement the AFE code for LOW IF and for HI IF. + * Currently, only baseband works. + */ + switch (mode) { case AFE_MODE_LOW_IF: /* SetupAFEforLowIF(); */ @@ -270,8 +296,8 @@ int cx231xx_colibri_set_mode(struct cx231xx *dev, enum AFE_MODE mode) return status; } -/* For power saving in the EVK */ -int cx231xx_colibri_update_power_control(struct cx231xx *dev, AV_MODE avmode) +int cx231xx_colibri_update_power_control(struct cx231xx *dev, + enum AV_MODE avmode) { u32 colibri_power_status = 0; int status = 0; @@ -279,14 +305,16 @@ int cx231xx_colibri_update_power_control(struct cx231xx *dev, AV_MODE avmode) switch (dev->model) { case CX231XX_BOARD_CNXT_RDE_250: case CX231XX_BOARD_CNXT_RDU_250: - if (avmode == POLARIS_AVMODE_ANALOGT_TV) { - while (colibri_power_status != 0x18) { + while (colibri_power_status != (FLD_PWRDN_TUNING_BIAS | + FLD_PWRDN_ENABLE_PLL)) { status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, SUP_BLK_PWRDN, 2, - 0x18, 1); - status = cx231xx_read_i2c_data(dev, + FLD_PWRDN_TUNING_BIAS | + FLD_PWRDN_ENABLE_PLL, + 1); + status |= cx231xx_read_i2c_data(dev, Colibri_DEVICE_ADDRESS, SUP_BLK_PWRDN, 2, &colibri_power_status, @@ -299,11 +327,11 @@ int cx231xx_colibri_update_power_control(struct cx231xx *dev, AV_MODE avmode) Colibri_DEVICE_ADDRESS, ADC_PWRDN_CLAMP_CH1, 2, 0x00, 1); - status = cx231xx_write_i2c_data(dev, + status |= cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_PWRDN_CLAMP_CH2, 2, 0x00, 1); - status = cx231xx_write_i2c_data(dev, + status |= cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_PWRDN_CLAMP_CH3, 2, 0x00, 1); @@ -312,32 +340,36 @@ int cx231xx_colibri_update_power_control(struct cx231xx *dev, AV_MODE avmode) Colibri_DEVICE_ADDRESS, ADC_PWRDN_CLAMP_CH1, 2, 0x70, 1); - status = cx231xx_write_i2c_data(dev, + status |= cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_PWRDN_CLAMP_CH2, 2, 0x70, 1); - status = cx231xx_write_i2c_data(dev, + status |= cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_PWRDN_CLAMP_CH3, 2, 0x70, 1); - status = cx231xx_read_i2c_data(dev, + status |= cx231xx_read_i2c_data(dev, Colibri_DEVICE_ADDRESS, SUP_BLK_PWRDN, 2, &colibri_power_status, 1); - colibri_power_status |= 0x07; - status = cx231xx_write_i2c_data(dev, + colibri_power_status |= FLD_PWRDN_PD_BANDGAP | + FLD_PWRDN_PD_BIAS | + FLD_PWRDN_PD_TUNECK; + status |= cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, SUP_BLK_PWRDN, 2, colibri_power_status, 1); } else if (avmode == POLARIS_AVMODE_ENXTERNAL_AV) { - - while (colibri_power_status != 0x18) { + while (colibri_power_status != (FLD_PWRDN_TUNING_BIAS | + FLD_PWRDN_ENABLE_PLL)) { status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, SUP_BLK_PWRDN, 2, - 0x18, 1); - status = cx231xx_read_i2c_data(dev, + FLD_PWRDN_TUNING_BIAS | + FLD_PWRDN_ENABLE_PLL, + 1); + status |= cx231xx_read_i2c_data(dev, Colibri_DEVICE_ADDRESS, SUP_BLK_PWRDN, 2, &colibri_power_status, @@ -346,15 +378,15 @@ int cx231xx_colibri_update_power_control(struct cx231xx *dev, AV_MODE avmode) break; } - status = cx231xx_write_i2c_data(dev, + status |= cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_PWRDN_CLAMP_CH1, 2, 0x00, 1); - status = cx231xx_write_i2c_data(dev, + status |= cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_PWRDN_CLAMP_CH2, 2, 0x00, 1); - status = cx231xx_write_i2c_data(dev, + status |= cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_PWRDN_CLAMP_CH3, 2, 0x00, 1); @@ -365,12 +397,15 @@ int cx231xx_colibri_update_power_control(struct cx231xx *dev, AV_MODE avmode) break; default: if (avmode == POLARIS_AVMODE_ANALOGT_TV) { - while (colibri_power_status != 0x18) { + while (colibri_power_status != (FLD_PWRDN_TUNING_BIAS | + FLD_PWRDN_ENABLE_PLL)) { status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, SUP_BLK_PWRDN, 2, - 0x18, 1); - status = cx231xx_read_i2c_data(dev, + FLD_PWRDN_TUNING_BIAS | + FLD_PWRDN_ENABLE_PLL, + 1); + status |= cx231xx_read_i2c_data(dev, Colibri_DEVICE_ADDRESS, SUP_BLK_PWRDN, 2, &colibri_power_status, @@ -379,15 +414,15 @@ int cx231xx_colibri_update_power_control(struct cx231xx *dev, AV_MODE avmode) break; } - status = cx231xx_write_i2c_data(dev, + status |= cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_PWRDN_CLAMP_CH1, 2, 0x40, 1); - status = cx231xx_write_i2c_data(dev, + status |= cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_PWRDN_CLAMP_CH2, 2, 0x40, 1); - status = cx231xx_write_i2c_data(dev, + status |= cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_PWRDN_CLAMP_CH3, 2, 0x00, 1); @@ -396,33 +431,38 @@ int cx231xx_colibri_update_power_control(struct cx231xx *dev, AV_MODE avmode) Colibri_DEVICE_ADDRESS, ADC_PWRDN_CLAMP_CH1, 2, 0x70, 1); - status = cx231xx_write_i2c_data(dev, + status |= cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_PWRDN_CLAMP_CH2, 2, 0x70, 1); - status = cx231xx_write_i2c_data(dev, + status |= cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_PWRDN_CLAMP_CH3, 2, 0x70, 1); - status = cx231xx_read_i2c_data(dev, + status |= cx231xx_read_i2c_data(dev, Colibri_DEVICE_ADDRESS, SUP_BLK_PWRDN, 2, &colibri_power_status, 1); - colibri_power_status |= 0x07; - status = cx231xx_write_i2c_data(dev, + colibri_power_status |= FLD_PWRDN_PD_BANDGAP | + FLD_PWRDN_PD_BIAS | + FLD_PWRDN_PD_TUNECK; + status |= cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, SUP_BLK_PWRDN, 2, colibri_power_status, 1); } else if (avmode == POLARIS_AVMODE_ENXTERNAL_AV) { - while (colibri_power_status != 0x18) { + while (colibri_power_status != (FLD_PWRDN_TUNING_BIAS | + FLD_PWRDN_ENABLE_PLL)) { status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, SUP_BLK_PWRDN, 2, - 0x18, 1); - status = cx231xx_read_i2c_data(dev, + FLD_PWRDN_TUNING_BIAS | + FLD_PWRDN_ENABLE_PLL, + 1); + status |= cx231xx_read_i2c_data(dev, Colibri_DEVICE_ADDRESS, SUP_BLK_PWRDN, 2, &colibri_power_status, @@ -431,15 +471,15 @@ int cx231xx_colibri_update_power_control(struct cx231xx *dev, AV_MODE avmode) break; } - status = cx231xx_write_i2c_data(dev, + status |= cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_PWRDN_CLAMP_CH1, 2, 0x00, 1); - status = cx231xx_write_i2c_data(dev, + status |= cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_PWRDN_CLAMP_CH2, 2, 0x00, 1); - status = cx231xx_write_i2c_data(dev, + status |= cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_PWRDN_CLAMP_CH3, 2, 0x40, 1); @@ -500,7 +540,7 @@ int cx231xx_colibri_adjust_ref_count(struct cx231xx *dev, u32 video_input) /****************************************************************************** * V I D E O / A U D I O D E C O D E R C O N T R O L functions * - ******************************************++**********************************/ + ******************************************************************************/ int cx231xx_set_video_input_mux(struct cx231xx *dev, u8 input) { int status = 0; @@ -839,7 +879,7 @@ int cx231xx_set_decoder_video_input(struct cx231xx *dev, DFE_CTRL1, 2, value, 4); - /* Wait 15 ms */ + /* Wait until AGC locks up */ msleep(1); /* Disable the auto-VGA enable AGC */ @@ -940,8 +980,7 @@ int cx231xx_do_mode_ctrl_overrides(struct cx231xx *dev) DFE_CTRL3, 2, 0xCD3F0280, 4); - if (dev->norm & (V4L2_STD_NTSC_M | V4L2_STD_NTSC_M_JP | - V4L2_STD_PAL_M)) { + if (dev->norm & (V4L2_STD_NTSC | V4L2_STD_PAL_M)) { cx231xx_info("do_mode_ctrl_overrides NTSC\n"); /* Move the close caption lines out of active video, @@ -967,11 +1006,9 @@ int cx231xx_do_mode_ctrl_overrides(struct cx231xx *dev) FLD_HBLANK_CNT, cx231xx_set_field (FLD_HBLANK_CNT, 0x79)); - } else if (dev->norm & (V4L2_STD_PAL_B | V4L2_STD_PAL_G | - V4L2_STD_PAL_D | V4L2_STD_PAL_I | - V4L2_STD_PAL_N | V4L2_STD_PAL_Nc)) { - cx231xx_info("do_mode_ctrl_overrides PAL\n"); - status = cx231xx_read_modify_write_i2c_dword(dev, + } else if (dev->norm & V4L2_STD_SECAM) { + cx231xx_info("do_mode_ctrl_overrides SECAM\n"); + status = cx231xx_read_modify_write_i2c_dword(dev, HAMMERHEAD_I2C_ADDRESS, VERT_TIM_CTRL, FLD_VBLANK_CNT, 0x24); @@ -982,12 +1019,9 @@ int cx231xx_do_mode_ctrl_overrides(struct cx231xx *dev) FLD_HBLANK_CNT, cx231xx_set_field (FLD_HBLANK_CNT, 0x85)); - } else if (dev->norm & (V4L2_STD_SECAM_B | V4L2_STD_SECAM_D | - V4L2_STD_SECAM_G | V4L2_STD_SECAM_K | - V4L2_STD_SECAM_K1 | V4L2_STD_SECAM_L | - V4L2_STD_SECAM_LC)) { - cx231xx_info("do_mode_ctrl_overrides SECAM\n"); - status = cx231xx_read_modify_write_i2c_dword(dev, + } else { + cx231xx_info("do_mode_ctrl_overrides PAL\n"); + status = cx231xx_read_modify_write_i2c_dword(dev, HAMMERHEAD_I2C_ADDRESS, VERT_TIM_CTRL, FLD_VBLANK_CNT, 0x24); @@ -1276,13 +1310,8 @@ int cx231xx_dif_configure_C2HH_for_low_IF(struct cx231xx *dev, u32 mode, status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, AFE_CTRL_C2HH_SRC_CTRL, 9, 9, 0x1); - } else { - switch (standard) { - case V4L2_STD_NTSC_M: /* 75 IRE Setup */ - case V4L2_STD_NTSC_M_JP:/* Japan, 0 IRE Setup */ - case V4L2_STD_PAL_M: - case V4L2_STD_PAL_N: - case V4L2_STD_PAL_Nc: + } else if (standard != DIF_USE_BASEBAND) { + if (standard & V4L2_STD_MN) { /* lo if big signal */ status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, @@ -1304,10 +1333,8 @@ int cx231xx_dif_configure_C2HH_for_low_IF(struct cx231xx *dev, u32 mode, status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, AUD_IO_CTRL, 0, 31, 0x00000003); - break; - - case V4L2_STD_PAL_B: - case V4L2_STD_PAL_G: + } else if ((standard == V4L2_STD_PAL_I) | + (standard & V4L2_STD_SECAM)) { /* C2HH setup */ /* lo if big signal */ status = cx231xx_reg_mask_write(dev, @@ -1321,22 +1348,13 @@ int cx231xx_dif_configure_C2HH_for_low_IF(struct cx231xx *dev, u32 mode, /* IF_MODE */ status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, - AFE_CTRL_C2HH_SRC_CTRL, 15, 22, 0xE); + AFE_CTRL_C2HH_SRC_CTRL, 15, 22, 0xF); /* no inv */ status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, AFE_CTRL_C2HH_SRC_CTRL, 9, 9, 0x1); - break; - - case V4L2_STD_PAL_D: - case V4L2_STD_PAL_I: - case V4L2_STD_SECAM_L: - case V4L2_STD_SECAM_LC: - case V4L2_STD_SECAM_B: - case V4L2_STD_SECAM_D: - case V4L2_STD_SECAM_G: - case V4L2_STD_SECAM_K: - case V4L2_STD_SECAM_K1: + } else { + /* default PAL BG */ /* C2HH setup */ /* lo if big signal */ status = cx231xx_reg_mask_write(dev, @@ -1350,17 +1368,11 @@ int cx231xx_dif_configure_C2HH_for_low_IF(struct cx231xx *dev, u32 mode, /* IF_MODE */ status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, - AFE_CTRL_C2HH_SRC_CTRL, 15, 22, 0xF); + AFE_CTRL_C2HH_SRC_CTRL, 15, 22, 0xE); /* no inv */ status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, AFE_CTRL_C2HH_SRC_CTRL, 9, 9, 0x1); - break; - - case DIF_USE_BASEBAND: - default: - /* do nothing to config C2HH for baseband */ - break; } } @@ -1406,54 +1418,6 @@ int cx231xx_dif_set_standard(struct cx231xx *dev, u32 standard) status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_MISC_CTRL, 2, dif_misc_ctrl_value, 4); - - } else if (standard & (V4L2_STD_PAL_B | V4L2_STD_PAL_G)) { - - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, - DIF_PLL_CTRL, 0, 31, 0x6503bc0c); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, - DIF_PLL_CTRL1, 0, 31, 0xbd038c85); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, - DIF_PLL_CTRL2, 0, 31, 0x1db4640a); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, - DIF_PLL_CTRL3, 0, 31, 0x00008800); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, - DIF_AGC_IF_REF, 0, 31, 0x444C1380); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, - DIF_AGC_CTRL_IF, 0, 31, 0xDA302600); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, - DIF_AGC_CTRL_INT, 0, 31, 0xDA261700); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, - DIF_AGC_CTRL_RF, 0, 31, 0xDA262600); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, - DIF_AGC_IF_INT_CURRENT, 0, 31, - 0x26001700); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, - DIF_AGC_RF_CURRENT, 0, 31, - 0x00002660); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, - DIF_VIDEO_AGC_CTRL, 0, 31, - 0x72500800); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, - DIF_VID_AUD_OVERRIDE, 0, 31, - 0x27000100); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, - DIF_AV_SEP_CTRL, 0, 31, 0x3F3530EC); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, - DIF_COMP_FLT_CTRL, 0, 31, - 0x00A653A8); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, - DIF_SRC_PHASE_INC, 0, 31, - 0x1befbf06); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, - DIF_SRC_GAIN_CONTROL, 0, 31, - 0x000035e8); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, - DIF_RPT_VARIANCE, 0, 31, 0x00000000); - /* Save the Spec Inversion value */ - dif_misc_ctrl_value &= FLD_DIF_SPEC_INV; - dif_misc_ctrl_value |= 0x3a013F11; - } else if (standard & V4L2_STD_PAL_D) { status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_PLL_CTRL, 0, 31, 0x6503bc0c); @@ -1499,9 +1463,7 @@ int cx231xx_dif_set_standard(struct cx231xx *dev, u32 standard) /* Save the Spec Inversion value */ dif_misc_ctrl_value &= FLD_DIF_SPEC_INV; dif_misc_ctrl_value |= 0x3a023F11; - } else if (standard & V4L2_STD_PAL_I) { - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_PLL_CTRL, 0, 31, 0x6503bc0c); status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, @@ -1546,7 +1508,6 @@ int cx231xx_dif_set_standard(struct cx231xx *dev, u32 standard) /* Save the Spec Inversion value */ dif_misc_ctrl_value &= FLD_DIF_SPEC_INV; dif_misc_ctrl_value |= 0x3a033F11; - } else if (standard & V4L2_STD_PAL_M) { /* improved Low Frequency Phase Noise */ status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, @@ -1584,13 +1545,10 @@ int cx231xx_dif_set_standard(struct cx231xx *dev, u32 standard) status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_SOFT_RST_CTRL_REVB, 2, 0x00000000, 4); - /* Save the Spec Inversion value */ dif_misc_ctrl_value &= FLD_DIF_SPEC_INV; dif_misc_ctrl_value |= 0x3A0A3F10; - } else if (standard & (V4L2_STD_PAL_N | V4L2_STD_PAL_Nc)) { - /* improved Low Frequency Phase Noise */ status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_PLL_CTRL, 2, 0xFF01FF0C, 4); @@ -1626,14 +1584,12 @@ int cx231xx_dif_set_standard(struct cx231xx *dev, u32 standard) status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_SOFT_RST_CTRL_REVB, 2, 0x00000000, 4); - /* Save the Spec Inversion value */ dif_misc_ctrl_value &= FLD_DIF_SPEC_INV; dif_misc_ctrl_value = 0x3A093F10; - } else if (standard & - (V4L2_STD_SECAM_B | V4L2_STD_SECAM_D | V4L2_STD_SECAM_G | - V4L2_STD_SECAM_K | V4L2_STD_SECAM_K1)) { + (V4L2_STD_SECAM_B | V4L2_STD_SECAM_D | V4L2_STD_SECAM_G | + V4L2_STD_SECAM_K | V4L2_STD_SECAM_K1)) { status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_PLL_CTRL, 0, 31, 0x6503bc0c); @@ -1680,9 +1636,7 @@ int cx231xx_dif_set_standard(struct cx231xx *dev, u32 standard) /* Save the Spec Inversion value */ dif_misc_ctrl_value &= FLD_DIF_SPEC_INV; dif_misc_ctrl_value |= 0x3a023F11; - } else if (standard & (V4L2_STD_SECAM_L | V4L2_STD_SECAM_LC)) { - /* Is it SECAM_L1? */ status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, DIF_PLL_CTRL, 0, 31, 0x6503bc0c); @@ -1730,7 +1684,7 @@ int cx231xx_dif_set_standard(struct cx231xx *dev, u32 standard) dif_misc_ctrl_value &= FLD_DIF_SPEC_INV; dif_misc_ctrl_value |= 0x3a023F11; - } else { + } else if (standard & V4L2_STD_NTSC_M) { /* V4L2_STD_NTSC_M (75 IRE Setup) Or V4L2_STD_NTSC_M_JP (Japan, 0 IRE Setup) */ @@ -1783,7 +1737,52 @@ int cx231xx_dif_set_standard(struct cx231xx *dev, u32 standard) /* Save the Spec Inversion value */ dif_misc_ctrl_value &= FLD_DIF_SPEC_INV; dif_misc_ctrl_value |= 0x3a003F10; - + } else { + /* default PAL BG */ + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + DIF_PLL_CTRL, 0, 31, 0x6503bc0c); + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + DIF_PLL_CTRL1, 0, 31, 0xbd038c85); + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + DIF_PLL_CTRL2, 0, 31, 0x1db4640a); + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + DIF_PLL_CTRL3, 0, 31, 0x00008800); + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + DIF_AGC_IF_REF, 0, 31, 0x444C1380); + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + DIF_AGC_CTRL_IF, 0, 31, 0xDA302600); + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + DIF_AGC_CTRL_INT, 0, 31, 0xDA261700); + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + DIF_AGC_CTRL_RF, 0, 31, 0xDA262600); + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + DIF_AGC_IF_INT_CURRENT, 0, 31, + 0x26001700); + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + DIF_AGC_RF_CURRENT, 0, 31, + 0x00002660); + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + DIF_VIDEO_AGC_CTRL, 0, 31, + 0x72500800); + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + DIF_VID_AUD_OVERRIDE, 0, 31, + 0x27000100); + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + DIF_AV_SEP_CTRL, 0, 31, 0x3F3530EC); + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + DIF_COMP_FLT_CTRL, 0, 31, + 0x00A653A8); + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + DIF_SRC_PHASE_INC, 0, 31, + 0x1befbf06); + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + DIF_SRC_GAIN_CONTROL, 0, 31, + 0x000035e8); + status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + DIF_RPT_VARIANCE, 0, 31, 0x00000000); + /* Save the Spec Inversion value */ + dif_misc_ctrl_value &= FLD_DIF_SPEC_INV; + dif_misc_ctrl_value |= 0x3a013F11; } /* The AGC values should be the same for all standards, @@ -1826,7 +1825,8 @@ int cx231xx_tuner_post_channel_change(struct cx231xx *dev) int status = 0; u32 dwval; - /* Set the RF and IF k_agc values to 4 for PAL/NTSC and 8 for SECAM */ + /* Set the RF and IF k_agc values to 4 for PAL/NTSC and 8 for + * SECAM L/B/D standards */ status = cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_AGC_IF_REF, 2, &dwval, 4); dwval &= ~(FLD_DIF_K_AGC_RF | FLD_DIF_K_AGC_IF); @@ -1864,7 +1864,8 @@ int cx231xx_flatiron_initialize(struct cx231xx *dev) return status; } -int cx231xx_flatiron_update_power_control(struct cx231xx *dev, AV_MODE avmode) +int cx231xx_flatiron_update_power_control(struct cx231xx *dev, + enum AV_MODE avmode) { int status = 0; u32 value = 0; @@ -1908,7 +1909,7 @@ int cx231xx_flatiron_set_audio_input(struct cx231xx *dev, u8 audio_input) /****************************************************************************** * P O W E R C O N T R O L functions * ******************************************************************************/ -int cx231xx_set_power_mode(struct cx231xx *dev, AV_MODE mode) +int cx231xx_set_power_mode(struct cx231xx *dev, enum AV_MODE mode) { u8 value[4] = { 0, 0, 0, 0 }; u32 tmp = 0; @@ -2211,7 +2212,7 @@ int cx231xx_initialize_stream_xfer(struct cx231xx *dev, u32 media_type) if (dev->udev->speed == USB_SPEED_HIGH) { switch (media_type) { - case 81: /* audio */ + case 81: /* audio */ cx231xx_info("%s: Audio enter HANC\n", __func__); status = cx231xx_mode_register(dev, TS_MODE_REG, 0x9300); @@ -2390,7 +2391,7 @@ int cx231xx_set_gpio_direction(struct cx231xx *dev, } /* -* SetGpioPinLogicValue +* cx231xx_set_gpio_value * Sets the value of the GPIO pin to Logic high or low. The Pin under * reference should ALREADY BE SET IN OUTPUT MODE !!!!!!!!! * diff --git a/linux/drivers/media/video/cx231xx/cx231xx-cards.c b/linux/drivers/media/video/cx231xx/cx231xx-cards.c index 3a97f5eb4..3539ce19b 100644 --- a/linux/drivers/media/video/cx231xx/cx231xx-cards.c +++ b/linux/drivers/media/video/cx231xx/cx231xx-cards.c @@ -62,127 +62,108 @@ static struct cx231xx_reg_seq RDE250_XCV_TUNER[] = { * Board definitions */ struct cx231xx_board cx231xx_boards[] = { - [CX231XX_BOARD_UNKNOWN] = { - .name = "Unknown CX231xx video grabber", - .tuner_type = TUNER_ABSENT, - .input = {{ - .type = CX231XX_VMUX_TELEVISION, - .vmux = CX231XX_VIN_3_1, - .amux = CX231XX_AMUX_VIDEO, - .gpio = 0, - }, { - .type = - CX231XX_VMUX_COMPOSITE1, - .vmux = CX231XX_VIN_2_1, - .amux = CX231XX_AMUX_LINE_IN, - .gpio = 0, - }, { - .type = - CX231XX_VMUX_SVIDEO, - .vmux = - CX231XX_VIN_1_1 | - (CX231XX_VIN_1_2 << 8) | - CX25840_SVIDEO_ON, - .amux = - CX231XX_AMUX_LINE_IN, - .gpio = 0, - } }, - }, - + .name = "Unknown CX231xx video grabber", + .tuner_type = TUNER_ABSENT, + .input = {{ + .type = CX231XX_VMUX_TELEVISION, + .vmux = CX231XX_VIN_3_1, + .amux = CX231XX_AMUX_VIDEO, + .gpio = 0, + }, { + .type = CX231XX_VMUX_COMPOSITE1, + .vmux = CX231XX_VIN_2_1, + .amux = CX231XX_AMUX_LINE_IN, + .gpio = 0, + }, { + .type = CX231XX_VMUX_SVIDEO, + .vmux = CX231XX_VIN_1_1 | + (CX231XX_VIN_1_2 << 8) | + CX25840_SVIDEO_ON, + .amux = CX231XX_AMUX_LINE_IN, + .gpio = 0, + } + }, + }, [CX231XX_BOARD_CNXT_RDE_250] = { - .name = "Conexant Hybrid TV - RDE250", - .valid = CX231XX_BOARD_VALIDATED, - .tuner_type = TUNER_XC5000, - .tuner_addr = 0x61, - .tuner_gpio = RDE250_XCV_TUNER, - .tuner_sif_gpio = 0x05, - .tuner_scl_gpio = 0x1a, - .tuner_sda_gpio = 0x1b, - .decoder = CX231XX_AVDECODER, - .demod_xfer_mode = 0, - .ctl_pin_status_mask = 0xFFFFFFC4, - .agc_analog_digital_select_gpio = 0x0c, - .gpio_pin_status_mask = 0x4001000, - .tuner_i2c_master = 1, - .demod_i2c_master = 2, - .has_dvb = 1, - .demod_addr = 0x02, - .norm = V4L2_STD_PAL, - - .input = {{ - .type = - CX231XX_VMUX_TELEVISION, - .vmux = CX231XX_VIN_3_1, - .amux = CX231XX_AMUX_VIDEO, - .gpio = 0, - }, { - .type = - CX231XX_VMUX_COMPOSITE1, - .vmux = CX231XX_VIN_2_1, - .amux = - CX231XX_AMUX_LINE_IN, - .gpio = 0, - }, { - .type = - CX231XX_VMUX_SVIDEO, - .vmux = - CX231XX_VIN_1_1 | - (CX231XX_VIN_1_2 << - 8) | - CX25840_SVIDEO_ON, - .amux = - CX231XX_AMUX_LINE_IN, - .gpio = 0, - } }, - }, + .name = "Conexant Hybrid TV - RDE250", + .tuner_type = TUNER_XC5000, + .tuner_addr = 0x61, + .tuner_gpio = RDE250_XCV_TUNER, + .tuner_sif_gpio = 0x05, + .tuner_scl_gpio = 0x1a, + .tuner_sda_gpio = 0x1b, + .decoder = CX231XX_AVDECODER, + .demod_xfer_mode = 0, + .ctl_pin_status_mask = 0xFFFFFFC4, + .agc_analog_digital_select_gpio = 0x0c, + .gpio_pin_status_mask = 0x4001000, + .tuner_i2c_master = 1, + .demod_i2c_master = 2, + .has_dvb = 1, + .demod_addr = 0x02, + .norm = V4L2_STD_PAL, + + .input = {{ + .type = CX231XX_VMUX_TELEVISION, + .vmux = CX231XX_VIN_3_1, + .amux = CX231XX_AMUX_VIDEO, + .gpio = 0, + }, { + .type = CX231XX_VMUX_COMPOSITE1, + .vmux = CX231XX_VIN_2_1, + .amux = CX231XX_AMUX_LINE_IN, + .gpio = 0, + }, { + .type = CX231XX_VMUX_SVIDEO, + .vmux = CX231XX_VIN_1_1 | + (CX231XX_VIN_1_2 << 8) | + CX25840_SVIDEO_ON, + .amux = CX231XX_AMUX_LINE_IN, + .gpio = 0, + } + }, + }, [CX231XX_BOARD_CNXT_RDU_250] = { - .name = "Conexant Hybrid TV - RDU250", - .valid = CX231XX_BOARD_VALIDATED, - .tuner_type = TUNER_XC5000, - .tuner_addr = 0x61, - .tuner_gpio = RDE250_XCV_TUNER, - .tuner_sif_gpio = 0x05, - .tuner_scl_gpio = 0x1a, - .tuner_sda_gpio = 0x1b, - .decoder = CX231XX_AVDECODER, - .demod_xfer_mode = 0, - .ctl_pin_status_mask = 0xFFFFFFC4, - .agc_analog_digital_select_gpio = 0x0c, - .gpio_pin_status_mask = 0x4001000, - .tuner_i2c_master = 1, - .demod_i2c_master = 2, - .has_dvb = 1, - .demod_addr = 0x32, - .norm = V4L2_STD_NTSC, - - .input = {{ - .type = - CX231XX_VMUX_TELEVISION, - .vmux = CX231XX_VIN_3_1, - .amux = CX231XX_AMUX_VIDEO, - .gpio = 0, - }, { - .type = - CX231XX_VMUX_COMPOSITE1, - .vmux = CX231XX_VIN_2_1, - .amux = - CX231XX_AMUX_LINE_IN, - .gpio = 0, - }, { - .type = - CX231XX_VMUX_SVIDEO, - .vmux = - CX231XX_VIN_1_1 | - (CX231XX_VIN_1_2 << - 8) | - CX25840_SVIDEO_ON, - .amux = - CX231XX_AMUX_LINE_IN, - .gpio = 0, - } }, - }, + .name = "Conexant Hybrid TV - RDU250", + .tuner_type = TUNER_XC5000, + .tuner_addr = 0x61, + .tuner_gpio = RDE250_XCV_TUNER, + .tuner_sif_gpio = 0x05, + .tuner_scl_gpio = 0x1a, + .tuner_sda_gpio = 0x1b, + .decoder = CX231XX_AVDECODER, + .demod_xfer_mode = 0, + .ctl_pin_status_mask = 0xFFFFFFC4, + .agc_analog_digital_select_gpio = 0x0c, + .gpio_pin_status_mask = 0x4001000, + .tuner_i2c_master = 1, + .demod_i2c_master = 2, + .has_dvb = 1, + .demod_addr = 0x32, + .norm = V4L2_STD_NTSC, + + .input = {{ + .type = CX231XX_VMUX_TELEVISION, + .vmux = CX231XX_VIN_3_1, + .amux = CX231XX_AMUX_VIDEO, + .gpio = 0, + }, { + .type = CX231XX_VMUX_COMPOSITE1, + .vmux = CX231XX_VIN_2_1, + .amux = CX231XX_AMUX_LINE_IN, + .gpio = 0, + }, { + .type = CX231XX_VMUX_SVIDEO, + .vmux = CX231XX_VIN_1_1 | + (CX231XX_VIN_1_2 << 8) | + CX25840_SVIDEO_ON, + .amux = CX231XX_AMUX_LINE_IN, + .gpio = 0, + } + }, + }, }; const unsigned int cx231xx_bcount = ARRAY_SIZE(cx231xx_boards); @@ -244,25 +225,11 @@ void cx231xx_pre_card_setup(struct cx231xx *dev) cx231xx_info("Identified as %s (card=%d)\n", dev->board.name, dev->model); - /* Do card specific if any */ - switch (dev->model) { - case CX231XX_BOARD_CNXT_RDE_250: - /* do card specific GPIO settings if required */ - cx231xx_info("Precard: Board is Conexnat RDE 250\n"); - /* set the direction for GPIO pins */ - cx231xx_set_gpio_direction(dev, dev->board.tuner_gpio->bit, 1); - cx231xx_set_gpio_value(dev, dev->board.tuner_gpio->bit, 1); - cx231xx_set_gpio_direction(dev, dev->board.tuner_sif_gpio, 1); - break; - case CX231XX_BOARD_CNXT_RDU_250: - /* do card specific GPIO settings if required */ - cx231xx_info("Precard: Board is Conexnat RDU 250\n"); - /* set the direction for GPIO pins */ - cx231xx_set_gpio_direction(dev, dev->board.tuner_gpio->bit, 1); - cx231xx_set_gpio_value(dev, dev->board.tuner_gpio->bit, 1); - cx231xx_set_gpio_direction(dev, dev->board.tuner_sif_gpio, 1); - break; - } + cx231xx_info("Precard: Board is %s\n", dev->board.name); + /* set the direction for GPIO pins */ + cx231xx_set_gpio_direction(dev, dev->board.tuner_gpio->bit, 1); + cx231xx_set_gpio_value(dev, dev->board.tuner_gpio->bit, 1); + cx231xx_set_gpio_direction(dev, dev->board.tuner_sif_gpio, 1); /* request some modules if any required */ @@ -363,15 +330,6 @@ void cx231xx_card_setup(struct cx231xx *dev) break; } - if (dev->board.valid == CX231XX_BOARD_NOT_VALIDATED) { - cx231xx_errdev("\n\n"); - cx231xx_errdev("The support for this board weren't " - "valid yet.\n"); - cx231xx_errdev("Please send a report of having this working\n"); - cx231xx_errdev("not to V4L mailing list (and/or to other " - "addresses)\n\n"); - } - /* request some modules */ if (dev->board.decoder == CX231XX_AVDECODER) { cx231xx_info(": Requesting cx25840 module\n"); diff --git a/linux/drivers/media/video/cx231xx/cx231xx-conf-reg.h b/linux/drivers/media/video/cx231xx/cx231xx-conf-reg.h index a65f99ba1..a6f398a17 100644 --- a/linux/drivers/media/video/cx231xx/cx231xx-conf-reg.h +++ b/linux/drivers/media/video/cx231xx/cx231xx-conf-reg.h @@ -42,30 +42,30 @@ #define PWR_CTL_EN 0x74 /* Polaris Endpoints capture mask for register EP_MODE_SET */ -#define ENABLE_EP1 0x01 /* Bit[0]=1 */ -#define ENABLE_EP2 0x02 /* Bit[1]=1 */ -#define ENABLE_EP3 0x04 /* Bit[2]=1 */ -#define ENABLE_EP4 0x08 /* Bit[3]=1 */ -#define ENABLE_EP5 0x10 /* Bit[4]=1 */ -#define ENABLE_EP6 0x20 /* Bit[5]=1 */ +#define ENABLE_EP1 0x01 /* Bit[0]=1 */ +#define ENABLE_EP2 0x02 /* Bit[1]=1 */ +#define ENABLE_EP3 0x04 /* Bit[2]=1 */ +#define ENABLE_EP4 0x08 /* Bit[3]=1 */ +#define ENABLE_EP5 0x10 /* Bit[4]=1 */ +#define ENABLE_EP6 0x20 /* Bit[5]=1 */ /* Bit definition for register PWR_CTL_EN */ #define PWR_MODE_MASK 0x17f -#define PWR_AV_EN 0x08 /* bit3 */ -#define PWR_ISO_EN 0x40 /* bit6 */ -#define PWR_AV_MODE 0x30 /* bit4,5 */ -#define PWR_TUNER_EN 0x04 /* bit2 */ -#define PWR_DEMOD_EN 0x02 /* bit1 */ -#define I2C_DEMOD_EN 0x01 /* bit0 */ -#define PWR_RESETOUT_EN 0x100 /* bit8 */ - -typedef enum { - POLARIS_AVMODE_DEFAULT = 0, - POLARIS_AVMODE_DIGITAL = 0x10, - POLARIS_AVMODE_ANALOGT_TV = 0x20, - POLARIS_AVMODE_ENXTERNAL_AV = 0x30, - -} AV_MODE; +#define PWR_AV_EN 0x08 /* bit3 */ +#define PWR_ISO_EN 0x40 /* bit6 */ +#define PWR_AV_MODE 0x30 /* bit4,5 */ +#define PWR_TUNER_EN 0x04 /* bit2 */ +#define PWR_DEMOD_EN 0x02 /* bit1 */ +#define I2C_DEMOD_EN 0x01 /* bit0 */ +#define PWR_RESETOUT_EN 0x100 /* bit8 */ + +enum AV_MODE{ + POLARIS_AVMODE_DEFAULT = 0, + POLARIS_AVMODE_DIGITAL = 0x10, + POLARIS_AVMODE_ANALOGT_TV = 0x20, + POLARIS_AVMODE_ENXTERNAL_AV = 0x30, + +}; /* Colibri Registers */ @@ -91,6 +91,13 @@ typedef enum { #define ADC_COM_BIAS3 0x0e #define TESTBUS_CTRL 0x12 +#define FLD_PWRDN_TUNING_BIAS 0x10 +#define FLD_PWRDN_ENABLE_PLL 0x08 +#define FLD_PWRDN_PD_BANDGAP 0x04 +#define FLD_PWRDN_PD_BIAS 0x02 +#define FLD_PWRDN_PD_TUNECK 0x01 + + #define ADC_STATUS_CH1 0x20 #define ADC_STATUS_CH2 0x40 #define ADC_STATUS_CH3 0x60 @@ -126,7 +133,7 @@ typedef enum { #define ADC_INPUT_CH1 0x28 #define ADC_INPUT_CH2 0x48 #define ADC_INPUT_CH3 0x68 -#define INPUT_SEL_MASK 0x30 /* [5:4] in_sel */ +#define INPUT_SEL_MASK 0x30 /* [5:4] in_sel */ #define ADC_NTF_PRECLMP_EN_CH1 0x29 #define ADC_NTF_PRECLMP_EN_CH2 0x49 @@ -150,128 +157,128 @@ typedef enum { #define DIRECT_IF_REVB_BASE 0x00300 /*****************************************************************************/ -#define DIF_PLL_FREQ_WORD (DIRECT_IF_REVB_BASE + 0x00000000) /* Reg Size 32 */ +#define DIF_PLL_FREQ_WORD (DIRECT_IF_REVB_BASE + 0x00000000) /*****************************************************************************/ #define FLD_DIF_PLL_LOCK 0x80000000 /* Reserved [30:29] */ #define FLD_DIF_PLL_FREE_RUN 0x10000000 -#define FLD_DIF_PLL_FREQ 0x0FFFFFFF +#define FLD_DIF_PLL_FREQ 0x0fffffff /*****************************************************************************/ -#define DIF_PLL_CTRL (DIRECT_IF_REVB_BASE + 0x00000004) /* Reg Size 32 */ +#define DIF_PLL_CTRL (DIRECT_IF_REVB_BASE + 0x00000004) /*****************************************************************************/ -#define FLD_DIF_KD_PD 0xFF000000 +#define FLD_DIF_KD_PD 0xff000000 /* Reserved [23:20] */ -#define FLD_DIF_KDS_PD 0x000F0000 -#define FLD_DIF_KI_PD 0x0000FF00 +#define FLD_DIF_KDS_PD 0x000f0000 +#define FLD_DIF_KI_PD 0x0000ff00 /* Reserved [7:4] */ -#define FLD_DIF_KIS_PD 0x0000000F +#define FLD_DIF_KIS_PD 0x0000000f /*****************************************************************************/ -#define DIF_PLL_CTRL1 (DIRECT_IF_REVB_BASE + 0x00000008) /* Reg Size 32 */ +#define DIF_PLL_CTRL1 (DIRECT_IF_REVB_BASE + 0x00000008) /*****************************************************************************/ -#define FLD_DIF_KD_FD 0xFF000000 +#define FLD_DIF_KD_FD 0xff000000 /* Reserved [23:20] */ -#define FLD_DIF_KDS_FD 0x000F0000 -#define FLD_DIF_KI_FD 0x0000FF00 -#define FLD_DIF_SIG_PROP_SZ 0x000000F0 -#define FLD_DIF_KIS_FD 0x0000000F +#define FLD_DIF_KDS_FD 0x000f0000 +#define FLD_DIF_KI_FD 0x0000ff00 +#define FLD_DIF_SIG_PROP_SZ 0x000000f0 +#define FLD_DIF_KIS_FD 0x0000000f /*****************************************************************************/ -#define DIF_PLL_CTRL2 (DIRECT_IF_REVB_BASE + 0x0000000C) /* Reg Size 32 */ +#define DIF_PLL_CTRL2 (DIRECT_IF_REVB_BASE + 0x0000000c) /*****************************************************************************/ -#define FLD_DIF_PLL_AGC_REF 0xFFF00000 -#define FLD_DIF_PLL_AGC_KI 0x000F0000 +#define FLD_DIF_PLL_AGC_REF 0xfff00000 +#define FLD_DIF_PLL_AGC_KI 0x000f0000 /* Reserved [15] */ #define FLD_DIF_FREQ_LIMIT 0x00007000 -#define FLD_DIF_K_FD 0x00000F00 -#define FLD_DIF_DOWNSMPL_FD 0x000000FF +#define FLD_DIF_K_FD 0x00000f00 +#define FLD_DIF_DOWNSMPL_FD 0x000000ff /*****************************************************************************/ -#define DIF_PLL_CTRL3 (DIRECT_IF_REVB_BASE + 0x00000010) /* Reg Size 32 */ +#define DIF_PLL_CTRL3 (DIRECT_IF_REVB_BASE + 0x00000010) /*****************************************************************************/ /* Reserved [31:16] */ #define FLD_DIF_PLL_AGC_EN 0x00008000 /* Reserved [14:12] */ -#define FLD_DIF_PLL_MAN_GAIN 0x00000FFF +#define FLD_DIF_PLL_MAN_GAIN 0x00000fff /*****************************************************************************/ -#define DIF_AGC_IF_REF (DIRECT_IF_REVB_BASE + 0x00000014) /* Reg Size 32 */ +#define DIF_AGC_IF_REF (DIRECT_IF_REVB_BASE + 0x00000014) /*****************************************************************************/ -#define FLD_DIF_K_AGC_RF 0xF0000000 -#define FLD_DIF_K_AGC_IF 0x0F000000 -#define FLD_DIF_K_AGC_INT 0x00F00000 +#define FLD_DIF_K_AGC_RF 0xf0000000 +#define FLD_DIF_K_AGC_IF 0x0f000000 +#define FLD_DIF_K_AGC_INT 0x00f00000 /* Reserved [19:12] */ -#define FLD_DIF_IF_REF 0x00000FFF +#define FLD_DIF_IF_REF 0x00000fff /*****************************************************************************/ -#define DIF_AGC_CTRL_IF (DIRECT_IF_REVB_BASE + 0x00000018) /* Reg Size 32 */ +#define DIF_AGC_CTRL_IF (DIRECT_IF_REVB_BASE + 0x00000018) /*****************************************************************************/ -#define FLD_DIF_IF_MAX 0xFF000000 -#define FLD_DIF_IF_MIN 0x00FF0000 -#define FLD_DIF_IF_AGC 0x0000FFFF +#define FLD_DIF_IF_MAX 0xff000000 +#define FLD_DIF_IF_MIN 0x00ff0000 +#define FLD_DIF_IF_AGC 0x0000ffff /*****************************************************************************/ -#define DIF_AGC_CTRL_INT (DIRECT_IF_REVB_BASE + 0x0000001C) /* Reg Size 32 */ +#define DIF_AGC_CTRL_INT (DIRECT_IF_REVB_BASE + 0x0000001c) /*****************************************************************************/ -#define FLD_DIF_INT_MAX 0xFF000000 -#define FLD_DIF_INT_MIN 0x00FF0000 -#define FLD_DIF_INT_AGC 0x0000FFFF +#define FLD_DIF_INT_MAX 0xff000000 +#define FLD_DIF_INT_MIN 0x00ff0000 +#define FLD_DIF_INT_AGC 0x0000ffff /*****************************************************************************/ -#define DIF_AGC_CTRL_RF (DIRECT_IF_REVB_BASE + 0x00000020) /* Reg Size 32 */ +#define DIF_AGC_CTRL_RF (DIRECT_IF_REVB_BASE + 0x00000020) /*****************************************************************************/ -#define FLD_DIF_RF_MAX 0xFF000000 -#define FLD_DIF_RF_MIN 0x00FF0000 -#define FLD_DIF_RF_AGC 0x0000FFFF +#define FLD_DIF_RF_MAX 0xff000000 +#define FLD_DIF_RF_MIN 0x00ff0000 +#define FLD_DIF_RF_AGC 0x0000ffff /*****************************************************************************/ -#define DIF_AGC_IF_INT_CURRENT (DIRECT_IF_REVB_BASE + 0x00000024) /* Reg Size 32 */ +#define DIF_AGC_IF_INT_CURRENT (DIRECT_IF_REVB_BASE + 0x00000024) /*****************************************************************************/ -#define FLD_DIF_IF_AGC_IN 0xFFFF0000 -#define FLD_DIF_INT_AGC_IN 0x0000FFFF +#define FLD_DIF_IF_AGC_IN 0xffff0000 +#define FLD_DIF_INT_AGC_IN 0x0000ffff /*****************************************************************************/ -#define DIF_AGC_RF_CURRENT (DIRECT_IF_REVB_BASE + 0x00000028) /* Reg Size 32 */ +#define DIF_AGC_RF_CURRENT (DIRECT_IF_REVB_BASE + 0x00000028) /*****************************************************************************/ /* Reserved [31:16] */ -#define FLD_DIF_RF_AGC_IN 0x0000FFFF +#define FLD_DIF_RF_AGC_IN 0x0000ffff /*****************************************************************************/ -#define DIF_VIDEO_AGC_CTRL (DIRECT_IF_REVB_BASE + 0x0000002C) /* Reg Size 32 */ +#define DIF_VIDEO_AGC_CTRL (DIRECT_IF_REVB_BASE + 0x0000002c) /*****************************************************************************/ -#define FLD_DIF_AFD 0xC0000000 +#define FLD_DIF_AFD 0xc0000000 #define FLD_DIF_K_VID_AGC 0x30000000 -#define FLD_DIF_LINE_LENGTH 0x0FFF0000 -#define FLD_DIF_AGC_GAIN 0x0000FFFF +#define FLD_DIF_LINE_LENGTH 0x0fff0000 +#define FLD_DIF_AGC_GAIN 0x0000ffff /*****************************************************************************/ -#define DIF_VID_AUD_OVERRIDE (DIRECT_IF_REVB_BASE + 0x00000030) /* Reg Size 32 */ +#define DIF_VID_AUD_OVERRIDE (DIRECT_IF_REVB_BASE + 0x00000030) /*****************************************************************************/ #define FLD_DIF_AUDIO_AGC_OVERRIDE 0x80000000 /* Reserved [30:30] */ -#define FLD_DIF_AUDIO_MAN_GAIN 0x3F000000 +#define FLD_DIF_AUDIO_MAN_GAIN 0x3f000000 /* Reserved [23:17] */ #define FLD_DIF_VID_AGC_OVERRIDE 0x00010000 -#define FLD_DIF_VID_MAN_GAIN 0x0000FFFF +#define FLD_DIF_VID_MAN_GAIN 0x0000ffff /*****************************************************************************/ -#define DIF_AV_SEP_CTRL (DIRECT_IF_REVB_BASE + 0x00000034) /* Reg Size 32 */ +#define DIF_AV_SEP_CTRL (DIRECT_IF_REVB_BASE + 0x00000034) /*****************************************************************************/ -#define FLD_DIF_LPF_FREQ 0xC0000000 -#define FLD_DIF_AV_PHASE_INC 0x3F000000 -#define FLD_DIF_AUDIO_FREQ 0x00FFFFFF +#define FLD_DIF_LPF_FREQ 0xc0000000 +#define FLD_DIF_AV_PHASE_INC 0x3f000000 +#define FLD_DIF_AUDIO_FREQ 0x00ffffff /*****************************************************************************/ -#define DIF_COMP_FLT_CTRL (DIRECT_IF_REVB_BASE + 0x00000038) /* Reg Size 32 */ +#define DIF_COMP_FLT_CTRL (DIRECT_IF_REVB_BASE + 0x00000038) /*****************************************************************************/ /* Reserved [31:24] */ -#define FLD_DIF_IIR23_R2 0x00FF0000 -#define FLD_DIF_IIR23_R1 0x0000FF00 -#define FLD_DIF_IIR1_R1 0x000000FF +#define FLD_DIF_IIR23_R2 0x00ff0000 +#define FLD_DIF_IIR23_R1 0x0000ff00 +#define FLD_DIF_IIR1_R1 0x000000ff /*****************************************************************************/ -#define DIF_MISC_CTRL (DIRECT_IF_REVB_BASE + 0x0000003C) /* Reg Size 32 */ +#define DIF_MISC_CTRL (DIRECT_IF_REVB_BASE + 0x0000003c) /*****************************************************************************/ #define FLD_DIF_DIF_BYPASS 0x80000000 #define FLD_DIF_FM_NYQ_GAIN 0x40000000 @@ -289,184 +296,184 @@ typedef enum { /* Reserved [18] */ #define FLD_DIF_IF_FREQ 0x00030000 /* Reserved [15:14] */ -#define FLD_DIF_TIP_OFFSET 0x00003F00 +#define FLD_DIF_TIP_OFFSET 0x00003f00 /* Reserved [7:5] */ #define FLD_DIF_DITHER_ENA 0x00000010 /* Reserved [3:1] */ #define FLD_DIF_RF_IF_LOCK 0x00000001 /*****************************************************************************/ -#define DIF_SRC_PHASE_INC (DIRECT_IF_REVB_BASE + 0x00000040) /* Reg Size 32 */ +#define DIF_SRC_PHASE_INC (DIRECT_IF_REVB_BASE + 0x00000040) /*****************************************************************************/ /* Reserved [31:29] */ -#define FLD_DIF_PHASE_INC 0x1FFFFFFF +#define FLD_DIF_PHASE_INC 0x1fffffff /*****************************************************************************/ -#define DIF_SRC_GAIN_CONTROL (DIRECT_IF_REVB_BASE + 0x00000044) /* Reg Size 32 */ +#define DIF_SRC_GAIN_CONTROL (DIRECT_IF_REVB_BASE + 0x00000044) /*****************************************************************************/ /* Reserved [31:16] */ -#define FLD_DIF_SRC_KI 0x0000FF00 -#define FLD_DIF_SRC_KD 0x000000FF +#define FLD_DIF_SRC_KI 0x0000ff00 +#define FLD_DIF_SRC_KD 0x000000ff /*****************************************************************************/ -#define DIF_BPF_COEFF01 (DIRECT_IF_REVB_BASE + 0x00000048) /* Reg Size 32 */ +#define DIF_BPF_COEFF01 (DIRECT_IF_REVB_BASE + 0x00000048) /*****************************************************************************/ /* Reserved [31:19] */ #define FLD_DIF_BPF_COEFF_0 0x00070000 /* Reserved [15:4] */ -#define FLD_DIF_BPF_COEFF_1 0x0000000F +#define FLD_DIF_BPF_COEFF_1 0x0000000f /*****************************************************************************/ -#define DIF_BPF_COEFF23 (DIRECT_IF_REVB_BASE + 0x0000004c) /* Reg Size 32 */ +#define DIF_BPF_COEFF23 (DIRECT_IF_REVB_BASE + 0x0000004c) /*****************************************************************************/ /* Reserved [31:22] */ -#define FLD_DIF_BPF_COEFF_2 0x003F0000 +#define FLD_DIF_BPF_COEFF_2 0x003f0000 /* Reserved [15:7] */ -#define FLD_DIF_BPF_COEFF_3 0x0000007F +#define FLD_DIF_BPF_COEFF_3 0x0000007f /*****************************************************************************/ -#define DIF_BPF_COEFF45 (DIRECT_IF_REVB_BASE + 0x00000050) /* Reg Size 32 */ +#define DIF_BPF_COEFF45 (DIRECT_IF_REVB_BASE + 0x00000050) /*****************************************************************************/ /* Reserved [31:24] */ -#define FLD_DIF_BPF_COEFF_4 0x00FF0000 +#define FLD_DIF_BPF_COEFF_4 0x00ff0000 /* Reserved [15:8] */ -#define FLD_DIF_BPF_COEFF_5 0x000000FF +#define FLD_DIF_BPF_COEFF_5 0x000000ff /*****************************************************************************/ -#define DIF_BPF_COEFF67 (DIRECT_IF_REVB_BASE + 0x00000054) /* Reg Size 32 */ +#define DIF_BPF_COEFF67 (DIRECT_IF_REVB_BASE + 0x00000054) /*****************************************************************************/ /* Reserved [31:25] */ -#define FLD_DIF_BPF_COEFF_6 0x01FF0000 +#define FLD_DIF_BPF_COEFF_6 0x01ff0000 /* Reserved [15:9] */ -#define FLD_DIF_BPF_COEFF_7 0x000001FF +#define FLD_DIF_BPF_COEFF_7 0x000001ff /*****************************************************************************/ -#define DIF_BPF_COEFF89 (DIRECT_IF_REVB_BASE + 0x00000058) /* Reg Size 32 */ +#define DIF_BPF_COEFF89 (DIRECT_IF_REVB_BASE + 0x00000058) /*****************************************************************************/ /* Reserved [31:26] */ -#define FLD_DIF_BPF_COEFF_8 0x03FF0000 +#define FLD_DIF_BPF_COEFF_8 0x03ff0000 /* Reserved [15:10] */ -#define FLD_DIF_BPF_COEFF_9 0x000003FF +#define FLD_DIF_BPF_COEFF_9 0x000003ff /*****************************************************************************/ -#define DIF_BPF_COEFF1011 (DIRECT_IF_REVB_BASE + 0x0000005C) /* Reg Size 32 */ +#define DIF_BPF_COEFF1011 (DIRECT_IF_REVB_BASE + 0x0000005c) /*****************************************************************************/ /* Reserved [31:27] */ -#define FLD_DIF_BPF_COEFF_10 0x07FF0000 +#define FLD_DIF_BPF_COEFF_10 0x07ff0000 /* Reserved [15:11] */ -#define FLD_DIF_BPF_COEFF_11 0x000007FF +#define FLD_DIF_BPF_COEFF_11 0x000007ff /*****************************************************************************/ -#define DIF_BPF_COEFF1213 (DIRECT_IF_REVB_BASE + 0x00000060) /* Reg Size 32 */ +#define DIF_BPF_COEFF1213 (DIRECT_IF_REVB_BASE + 0x00000060) /*****************************************************************************/ /* Reserved [31:27] */ -#define FLD_DIF_BPF_COEFF_12 0x07FF0000 +#define FLD_DIF_BPF_COEFF_12 0x07ff0000 /* Reserved [15:12] */ -#define FLD_DIF_BPF_COEFF_13 0x00000FFF +#define FLD_DIF_BPF_COEFF_13 0x00000fff /*****************************************************************************/ -#define DIF_BPF_COEFF1415 (DIRECT_IF_REVB_BASE + 0x00000064) /* Reg Size 32 */ +#define DIF_BPF_COEFF1415 (DIRECT_IF_REVB_BASE + 0x00000064) /*****************************************************************************/ /* Reserved [31:28] */ -#define FLD_DIF_BPF_COEFF_14 0x0FFF0000 +#define FLD_DIF_BPF_COEFF_14 0x0fff0000 /* Reserved [15:12] */ -#define FLD_DIF_BPF_COEFF_15 0x00000FFF +#define FLD_DIF_BPF_COEFF_15 0x00000fff /*****************************************************************************/ -#define DIF_BPF_COEFF1617 (DIRECT_IF_REVB_BASE + 0x00000068) /* Reg Size 32 */ +#define DIF_BPF_COEFF1617 (DIRECT_IF_REVB_BASE + 0x00000068) /*****************************************************************************/ /* Reserved [31:29] */ -#define FLD_DIF_BPF_COEFF_16 0x1FFF0000 +#define FLD_DIF_BPF_COEFF_16 0x1fff0000 /* Reserved [15:13] */ -#define FLD_DIF_BPF_COEFF_17 0x00001FFF +#define FLD_DIF_BPF_COEFF_17 0x00001fff /*****************************************************************************/ -#define DIF_BPF_COEFF1819 (DIRECT_IF_REVB_BASE + 0x0000006C) /* Reg Size 32 */ +#define DIF_BPF_COEFF1819 (DIRECT_IF_REVB_BASE + 0x0000006c) /*****************************************************************************/ /* Reserved [31:29] */ -#define FLD_DIF_BPF_COEFF_18 0x1FFF0000 +#define FLD_DIF_BPF_COEFF_18 0x1fff0000 /* Reserved [15:13] */ -#define FLD_DIF_BPF_COEFF_19 0x00001FFF +#define FLD_DIF_BPF_COEFF_19 0x00001fff /*****************************************************************************/ -#define DIF_BPF_COEFF2021 (DIRECT_IF_REVB_BASE + 0x00000070) /* Reg Size 32 */ +#define DIF_BPF_COEFF2021 (DIRECT_IF_REVB_BASE + 0x00000070) /*****************************************************************************/ /* Reserved [31:29] */ -#define FLD_DIF_BPF_COEFF_20 0x1FFF0000 +#define FLD_DIF_BPF_COEFF_20 0x1fff0000 /* Reserved [15:14] */ -#define FLD_DIF_BPF_COEFF_21 0x00003FFF +#define FLD_DIF_BPF_COEFF_21 0x00003fff /*****************************************************************************/ -#define DIF_BPF_COEFF2223 (DIRECT_IF_REVB_BASE + 0x00000074) /* Reg Size 32 */ +#define DIF_BPF_COEFF2223 (DIRECT_IF_REVB_BASE + 0x00000074) /*****************************************************************************/ /* Reserved [31:30] */ -#define FLD_DIF_BPF_COEFF_22 0x3FFF0000 +#define FLD_DIF_BPF_COEFF_22 0x3fff0000 /* Reserved [15:14] */ -#define FLD_DIF_BPF_COEFF_23 0x00003FFF +#define FLD_DIF_BPF_COEFF_23 0x00003fff /*****************************************************************************/ -#define DIF_BPF_COEFF2425 (DIRECT_IF_REVB_BASE + 0x00000078) /* Reg Size 32 */ +#define DIF_BPF_COEFF2425 (DIRECT_IF_REVB_BASE + 0x00000078) /*****************************************************************************/ /* Reserved [31:30] */ -#define FLD_DIF_BPF_COEFF_24 0x3FFF0000 +#define FLD_DIF_BPF_COEFF_24 0x3fff0000 /* Reserved [15:14] */ -#define FLD_DIF_BPF_COEFF_25 0x00003FFF +#define FLD_DIF_BPF_COEFF_25 0x00003fff /*****************************************************************************/ -#define DIF_BPF_COEFF2627 (DIRECT_IF_REVB_BASE + 0x0000007C) /* Reg Size 32 */ +#define DIF_BPF_COEFF2627 (DIRECT_IF_REVB_BASE + 0x0000007c) /*****************************************************************************/ /* Reserved [31:30] */ -#define FLD_DIF_BPF_COEFF_26 0x3FFF0000 +#define FLD_DIF_BPF_COEFF_26 0x3fff0000 /* Reserved [15:14] */ -#define FLD_DIF_BPF_COEFF_27 0x00003FFF +#define FLD_DIF_BPF_COEFF_27 0x00003fff /*****************************************************************************/ -#define DIF_BPF_COEFF2829 (DIRECT_IF_REVB_BASE + 0x00000080) /* Reg Size 32 */ +#define DIF_BPF_COEFF2829 (DIRECT_IF_REVB_BASE + 0x00000080) /*****************************************************************************/ /* Reserved [31:30] */ -#define FLD_DIF_BPF_COEFF_28 0x3FFF0000 +#define FLD_DIF_BPF_COEFF_28 0x3fff0000 /* Reserved [15:14] */ -#define FLD_DIF_BPF_COEFF_29 0x00003FFF +#define FLD_DIF_BPF_COEFF_29 0x00003fff /*****************************************************************************/ -#define DIF_BPF_COEFF3031 (DIRECT_IF_REVB_BASE + 0x00000084) /* Reg Size 32 */ +#define DIF_BPF_COEFF3031 (DIRECT_IF_REVB_BASE + 0x00000084) /*****************************************************************************/ /* Reserved [31:30] */ -#define FLD_DIF_BPF_COEFF_30 0x3FFF0000 +#define FLD_DIF_BPF_COEFF_30 0x3fff0000 /* Reserved [15:14] */ -#define FLD_DIF_BPF_COEFF_31 0x00003FFF +#define FLD_DIF_BPF_COEFF_31 0x00003fff /*****************************************************************************/ -#define DIF_BPF_COEFF3233 (DIRECT_IF_REVB_BASE + 0x00000088) /* Reg Size 32 */ +#define DIF_BPF_COEFF3233 (DIRECT_IF_REVB_BASE + 0x00000088) /*****************************************************************************/ /* Reserved [31:30] */ -#define FLD_DIF_BPF_COEFF_32 0x3FFF0000 +#define FLD_DIF_BPF_COEFF_32 0x3fff0000 /* Reserved [15:14] */ -#define FLD_DIF_BPF_COEFF_33 0x00003FFF +#define FLD_DIF_BPF_COEFF_33 0x00003fff /*****************************************************************************/ -#define DIF_BPF_COEFF3435 (DIRECT_IF_REVB_BASE + 0x0000008C) /* Reg Size 32 */ +#define DIF_BPF_COEFF3435 (DIRECT_IF_REVB_BASE + 0x0000008c) /*****************************************************************************/ /* Reserved [31:30] */ -#define FLD_DIF_BPF_COEFF_34 0x3FFF0000 +#define FLD_DIF_BPF_COEFF_34 0x3fff0000 /* Reserved [15:14] */ -#define FLD_DIF_BPF_COEFF_35 0x00003FFF +#define FLD_DIF_BPF_COEFF_35 0x00003fff /*****************************************************************************/ -#define DIF_BPF_COEFF36 (DIRECT_IF_REVB_BASE + 0x00000090) /* Reg Size 32 */ +#define DIF_BPF_COEFF36 (DIRECT_IF_REVB_BASE + 0x00000090) /*****************************************************************************/ /* Reserved [31:30] */ -#define FLD_DIF_BPF_COEFF_36 0x3FFF0000 +#define FLD_DIF_BPF_COEFF_36 0x3fff0000 /* Reserved [15:0] */ /*****************************************************************************/ -#define DIF_RPT_VARIANCE (DIRECT_IF_REVB_BASE + 0x00000094) /* Reg Size 32 */ +#define DIF_RPT_VARIANCE (DIRECT_IF_REVB_BASE + 0x00000094) /*****************************************************************************/ /* Reserved [31:20] */ -#define FLD_DIF_RPT_VARIANCE 0x000FFFFF +#define FLD_DIF_RPT_VARIANCE 0x000fffff /*****************************************************************************/ -#define DIF_SOFT_RST_CTRL_REVB (DIRECT_IF_REVB_BASE + 0x00000098) /* Reg Size 32 */ +#define DIF_SOFT_RST_CTRL_REVB (DIRECT_IF_REVB_BASE + 0x00000098) /*****************************************************************************/ /* Reserved [31:8] */ #define FLD_DIF_DIF_SOFT_RST 0x00000080 @@ -479,9 +486,9 @@ typedef enum { #define FLD_DIF_PLL_RST_MSK 0x00000001 /*****************************************************************************/ -#define DIF_PLL_FREQ_ERR (DIRECT_IF_REVB_BASE + 0x0000009C) /* Reg Size 32 */ +#define DIF_PLL_FREQ_ERR (DIRECT_IF_REVB_BASE + 0x0000009c) /*****************************************************************************/ /* Reserved [31:25] */ -#define FLD_DIF_CTL_IP 0x01FFFFFF +#define FLD_DIF_CTL_IP 0x01ffffff #endif diff --git a/linux/drivers/media/video/cx231xx/cx231xx-core.c b/linux/drivers/media/video/cx231xx/cx231xx-core.c index 945eb6196..2aec3a842 100644 --- a/linux/drivers/media/video/cx231xx/cx231xx-core.c +++ b/linux/drivers/media/video/cx231xx/cx231xx-core.c @@ -54,7 +54,6 @@ static int alt = CX231XX_PINOUT; module_param(alt, int, 0644); MODULE_PARM_DESC(alt, "alternate setting to use for video endpoint"); -/* FIXME */ #define cx231xx_isocdbg(fmt, arg...) do {\ if (core_debug) \ printk(KERN_INFO "%s %s :"fmt, \ @@ -327,7 +326,7 @@ int cx231xx_read_ctrl_reg(struct cx231xx *dev, u8 req, u16 reg, reg & 0xff, reg >> 8, len & 0xff, len >> 8); } - /* mutex_lock(&dev->ctrl_urb_lock); */ + mutex_lock(&dev->ctrl_urb_lock); ret = usb_control_msg(dev->udev, pipe, req, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, val, reg, dev->urb_buf, len, HZ); @@ -340,7 +339,7 @@ int cx231xx_read_ctrl_reg(struct cx231xx *dev, u8 req, u16 reg, if (len) memcpy(buf, dev->urb_buf, len); - /* mutex_unlock(&dev->ctrl_urb_lock); */ + mutex_unlock(&dev->ctrl_urb_lock); if (reg_debug) { int byte; @@ -388,13 +387,13 @@ int cx231xx_send_vendor_cmd(struct cx231xx *dev, cx231xx_isocdbg("\n"); } - /* mutex_lock(&dev->ctrl_urb_lock); */ + mutex_lock(&dev->ctrl_urb_lock); ret = usb_control_msg(dev->udev, pipe, ven_req->bRequest, ven_req-> direction | USB_TYPE_VENDOR | USB_RECIP_DEVICE, ven_req->wValue, ven_req->wIndex, ven_req->pBuff, ven_req->wLength, HZ); - /* mutex_unlock(&dev->ctrl_urb_lock); */ + mutex_unlock(&dev->ctrl_urb_lock); return ret; } @@ -451,12 +450,12 @@ int cx231xx_write_ctrl_reg(struct cx231xx *dev, u8 req, u16 reg, char *buf, cx231xx_isocdbg("\n"); } - /* mutex_lock(&dev->ctrl_urb_lock); */ + mutex_lock(&dev->ctrl_urb_lock); memcpy(dev->urb_buf, buf, len); ret = usb_control_msg(dev->udev, pipe, req, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, val, reg, dev->urb_buf, len, HZ); - /* mutex_unlock(&dev->ctrl_urb_lock); */ + mutex_unlock(&dev->ctrl_urb_lock); return ret; } diff --git a/linux/drivers/media/video/cx231xx/cx231xx-i2c.c b/linux/drivers/media/video/cx231xx/cx231xx-i2c.c index 1d64f913a..87dbd4e4e 100644 --- a/linux/drivers/media/video/cx231xx/cx231xx-i2c.c +++ b/linux/drivers/media/video/cx231xx/cx231xx-i2c.c @@ -42,8 +42,8 @@ MODULE_PARM_DESC(i2c_debug, "enable debug messages [i2c]"); #define dprintk1(lvl, fmt, args...) \ do { \ if (i2c_debug >= lvl) { \ - printk(fmt, ##args); \ - } \ + printk(fmt, ##args); \ + } \ } while (0) #define dprintk2(lvl, fmt, args...) \ @@ -77,13 +77,10 @@ int cx231xx_i2c_send_bytes(struct i2c_adapter *i2c_adap, size = msg->len; if (size == 2) { /* register write sub addr */ - - /* Just writing sub address will cause problem to XC5000 - So ignore the request */ + /* Just writing sub address will cause problem + * to XC5000. So ignore the request */ return 0; - } else if (size == 4) { /* register write with sub addr */ - if (msg->len >= 2) saddr = msg->buf[0] << 8 | msg->buf[1]; else if (msg->len == 1) @@ -117,7 +114,6 @@ int cx231xx_i2c_send_bytes(struct i2c_adapter *i2c_adap, msg->buf, msg->len); } - } /* special case for Xc5000 tuner case */ diff --git a/linux/drivers/media/video/cx231xx/cx231xx-pcb-cfg.c b/linux/drivers/media/video/cx231xx/cx231xx-pcb-cfg.c new file mode 100644 index 000000000..c00f51eae --- /dev/null +++ b/linux/drivers/media/video/cx231xx/cx231xx-pcb-cfg.c @@ -0,0 +1,793 @@ +/* + cx231xx-pcb-config.c - driver for Conexant + Cx23100/101/102 USB video capture devices + + Copyright (C) 2008 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "cx231xx.h" +#include "cx231xx-conf-reg.h" + +/******************************************************************************/ + +struct pcb_config cx231xx_Scenario[] = { + { + INDEX_SELFPOWER_DIGITAL_ONLY, /* index */ + USB_SELF_POWER, /* power_type */ + 0, /* speed , not decide yet */ + MOD_DIGITAL, /* mode */ + SOURCE_TS_BDA, /* ts1_source, digital tv only */ + NOT_SUPPORTED, /* ts2_source */ + NOT_SUPPORTED, /* analog source */ + + 0, /* digital_index */ + 0, /* analog index */ + 0, /* dif_index */ + 0, /* external_index */ + + 1, /* only one configuration */ + { + { + 0, /* config index */ + { + 0, /* interrupt ep index */ + 1, /* ts1 index */ + NOT_SUPPORTED, /* TS2 index */ + NOT_SUPPORTED, /* AUDIO */ + NOT_SUPPORTED, /* VIDEO */ + NOT_SUPPORTED, /* VANC */ + NOT_SUPPORTED, /* HANC */ + NOT_SUPPORTED /* ir_index */ + } + , + } + , + {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED, + NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED, + NOT_SUPPORTED} + } + , + {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED, + NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED, + NOT_SUPPORTED} + } + } + , + /* full-speed config */ + { + { + 0, /* config index */ + { + 0, /* interrupt ep index */ + 1, /* ts1 index */ + NOT_SUPPORTED, /* TS2 index */ + NOT_SUPPORTED, /* AUDIO */ + NOT_SUPPORTED, /* VIDEO */ + NOT_SUPPORTED, /* VANC */ + NOT_SUPPORTED, /* HANC */ + NOT_SUPPORTED /* ir_index */ + } + } + , + {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED, + NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED, + NOT_SUPPORTED} + } + , + {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED, + NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED, + NOT_SUPPORTED} + } + } + } + , + + { + INDEX_SELFPOWER_DUAL_DIGITAL, /* index */ + USB_SELF_POWER, /* power_type */ + 0, /* speed , not decide yet */ + MOD_DIGITAL, /* mode */ + SOURCE_TS_BDA, /* ts1_source, digital tv only */ + 0, /* ts2_source,need update from register */ + NOT_SUPPORTED, /* analog source */ + 0, /* digital_index */ + 0, /* analog index */ + 0, /* dif_index */ + 0, /* external_index */ + + 1, /* only one configuration */ + { + { + 0, /* config index */ + { + 0, /* interrupt ep index */ + 1, /* ts1 index */ + 2, /* TS2 index */ + NOT_SUPPORTED, /* AUDIO */ + NOT_SUPPORTED, /* VIDEO */ + NOT_SUPPORTED, /* VANC */ + NOT_SUPPORTED, /* HANC */ + NOT_SUPPORTED /* ir_index */ + } + } + , + {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED, + NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED, + NOT_SUPPORTED} + } + , + {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED, + NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED, + NOT_SUPPORTED} + } + } + , + /* full-speed */ + { + { + 0, /* config index */ + { + 0, /* interrupt ep index */ + 1, /* ts1 index */ + 2, /* TS2 index */ + NOT_SUPPORTED, /* AUDIO */ + NOT_SUPPORTED, /* VIDEO */ + NOT_SUPPORTED, /* VANC */ + NOT_SUPPORTED, /* HANC */ + NOT_SUPPORTED /* ir_index */ + } + } + , + {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED, + NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED, + NOT_SUPPORTED} + } + , + {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED, + NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED, + NOT_SUPPORTED} + } + } + } + , + + { + INDEX_SELFPOWER_ANALOG_ONLY, /* index */ + USB_SELF_POWER, /* power_type */ + 0, /* speed , not decide yet */ + MOD_ANALOG | MOD_DIF | MOD_EXTERNAL, /* mode ,analog tv only */ + NOT_SUPPORTED, /* ts1_source, NOT SUPPORT */ + NOT_SUPPORTED, /* ts2_source,NOT SUPPORT */ + 0, /* analog source, need update */ + + 0, /* digital_index */ + 0, /* analog index */ + 0, /* dif_index */ + 0, /* external_index */ + + 1, /* only one configuration */ + { + { + 0, /* config index */ + { + 0, /* interrupt ep index */ + NOT_SUPPORTED, /* ts1 index */ + NOT_SUPPORTED, /* TS2 index */ + 1, /* AUDIO */ + 2, /* VIDEO */ + 3, /* VANC */ + 4, /* HANC */ + NOT_SUPPORTED /* ir_index */ + } + } + , + {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED, + NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED, + NOT_SUPPORTED} + } + , + {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED, + NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED, + NOT_SUPPORTED} + } + } + , + /* full-speed */ + { + { + 0, /* config index */ + { + 0, /* interrupt ep index */ + NOT_SUPPORTED, /* ts1 index */ + NOT_SUPPORTED, /* TS2 index */ + 1, /* AUDIO */ + 2, /* VIDEO */ + NOT_SUPPORTED, /* VANC */ + NOT_SUPPORTED, /* HANC */ + NOT_SUPPORTED /* ir_index */ + } + } + , + {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED, + NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED, + NOT_SUPPORTED} + } + , + {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED, + NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED, + NOT_SUPPORTED} + } + } + } + , + + { + INDEX_SELFPOWER_DUAL, /* index */ + USB_SELF_POWER, /* power_type */ + 0, /* speed , not decide yet */ + /* mode ,analog tv and digital path */ + MOD_ANALOG | MOD_DIF | MOD_DIGITAL | MOD_EXTERNAL, + 0, /* ts1_source,will update in register */ + NOT_SUPPORTED, /* ts2_source,NOT SUPPORT */ + 0, /* analog source need update */ + 0, /* digital_index */ + 0, /* analog index */ + 0, /* dif_index */ + 0, /* external_index */ + 1, /* only one configuration */ + { + { + 0, /* config index */ + { + 0, /* interrupt ep index */ + 1, /* ts1 index */ + NOT_SUPPORTED, /* TS2 index */ + 2, /* AUDIO */ + 3, /* VIDEO */ + 4, /* VANC */ + 5, /* HANC */ + NOT_SUPPORTED /* ir_index */ + } + } + , + {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED, + NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED, + NOT_SUPPORTED} + } + , + {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED, + NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED, + NOT_SUPPORTED} + } + } + , + /* full-speed */ + { + { + 0, /* config index */ + { + 0, /* interrupt ep index */ + 1, /* ts1 index */ + NOT_SUPPORTED, /* TS2 index */ + 2, /* AUDIO */ + 3, /* VIDEO */ + NOT_SUPPORTED, /* VANC */ + NOT_SUPPORTED, /* HANC */ + NOT_SUPPORTED /* ir_index */ + } + } + , + {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED, + NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED, + NOT_SUPPORTED} + } + , + {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED, + NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED, + NOT_SUPPORTED} + } + } + } + , + + { + INDEX_SELFPOWER_TRIPLE, /* index */ + USB_SELF_POWER, /* power_type */ + 0, /* speed , not decide yet */ + /* mode ,analog tv and digital path */ + MOD_ANALOG | MOD_DIF | MOD_DIGITAL | MOD_EXTERNAL, + 0, /* ts1_source, update in register */ + 0, /* ts2_source,update in register */ + 0, /* analog source, need update */ + + 0, /* digital_index */ + 0, /* analog index */ + 0, /* dif_index */ + 0, /* external_index */ + 1, /* only one configuration */ + { + { + 0, /* config index */ + { + 0, /* interrupt ep index */ + 1, /* ts1 index */ + 2, /* TS2 index */ + 3, /* AUDIO */ + 4, /* VIDEO */ + 5, /* VANC */ + 6, /* HANC */ + NOT_SUPPORTED /* ir_index */ + } + } + , + {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED, + NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED, + NOT_SUPPORTED} + } + , + {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED, + NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED, + NOT_SUPPORTED} + } + } + , + /* full-speed */ + { + { + 0, /* config index */ + { + 0, /* interrupt ep index */ + 1, /* ts1 index */ + 2, /* TS2 index */ + 3, /* AUDIO */ + 4, /* VIDEO */ + NOT_SUPPORTED, /* VANC */ + NOT_SUPPORTED, /* HANC */ + NOT_SUPPORTED /* ir_index */ + } + } + , + {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED, + NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED, + NOT_SUPPORTED} + } + , + {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED, + NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED, + NOT_SUPPORTED} + } + } + } + , + + { + INDEX_SELFPOWER_COMPRESSOR, /* index */ + USB_SELF_POWER, /* power_type */ + 0, /* speed , not decide yet */ + /* mode ,analog tv AND DIGITAL path */ + MOD_ANALOG | MOD_DIF | MOD_DIGITAL | MOD_EXTERNAL, + NOT_SUPPORTED, /* ts1_source, disable */ + SOURCE_TS_BDA, /* ts2_source */ + 0, /* analog source,need update */ + 0, /* digital_index */ + 0, /* analog index */ + 0, /* dif_index */ + 0, /* external_index */ + 1, /* only one configuration */ + { + { + 0, /* config index */ + { + 0, /* interrupt ep index */ + NOT_SUPPORTED, /* ts1 index */ + 1, /* TS2 index */ + 2, /* AUDIO */ + 3, /* VIDEO */ + 4, /* VANC */ + 5, /* HANC */ + NOT_SUPPORTED /* ir_index */ + } + } + , + {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED, + NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED, + NOT_SUPPORTED} + } + , + {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED, + NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED, + NOT_SUPPORTED} + } + } + , + /* full-speed */ + { + { + 0, /* config index */ + { + 0, /* interrupt ep index */ + NOT_SUPPORTED, /* ts1 index */ + 1, /* TS2 index */ + 2, /* AUDIO */ + 3, /* VIDEO */ + NOT_SUPPORTED, /* VANC */ + NOT_SUPPORTED, /* HANC */ + NOT_SUPPORTED /* ir_index */ + } + } + , + {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED, + NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED, + NOT_SUPPORTED} + } + , + {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED, + NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED, + NOT_SUPPORTED} + } + } + } + , + + { + INDEX_BUSPOWER_DIGITAL_ONLY, /* index */ + USB_BUS_POWER, /* power_type */ + 0, /* speed , not decide yet */ + MOD_DIGITAL, /* mode ,analog tv AND DIGITAL path */ + SOURCE_TS_BDA, /* ts1_source, disable */ + NOT_SUPPORTED, /* ts2_source */ + NOT_SUPPORTED, /* analog source */ + + 0, /* digital_index */ + 0, /* analog index */ + 0, /* dif_index */ + 0, /* external_index */ + + 1, /* only one configuration */ + { + { + 0, /* config index */ + { + 0, /* interrupt ep index = 2 */ + 1, /* ts1 index */ + NOT_SUPPORTED, /* TS2 index */ + NOT_SUPPORTED, /* AUDIO */ + NOT_SUPPORTED, /* VIDEO */ + NOT_SUPPORTED, /* VANC */ + NOT_SUPPORTED, /* HANC */ + NOT_SUPPORTED /* ir_index */ + } + } + , + {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED, + NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED, + NOT_SUPPORTED} + } + , + {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED, + NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED, + NOT_SUPPORTED} + } + } + , + /* full-speed */ + { + { + 0, /* config index */ + { + 0, /* interrupt ep index = 2 */ + 1, /* ts1 index */ + NOT_SUPPORTED, /* TS2 index */ + NOT_SUPPORTED, /* AUDIO */ + NOT_SUPPORTED, /* VIDEO */ + NOT_SUPPORTED, /* VANC */ + NOT_SUPPORTED, /* HANC */ + NOT_SUPPORTED /* ir_index */ + } + } + , + {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED, + NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED, + NOT_SUPPORTED} + } + , + {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED, + NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED, + NOT_SUPPORTED} + } + } + } + , + { + INDEX_BUSPOWER_ANALOG_ONLY, /* index */ + USB_BUS_POWER, /* power_type */ + 0, /* speed , not decide yet */ + MOD_ANALOG, /* mode ,analog tv AND DIGITAL path */ + NOT_SUPPORTED, /* ts1_source, disable */ + NOT_SUPPORTED, /* ts2_source */ + SOURCE_ANALOG, /* analog source--analog */ + 0, /* digital_index */ + 0, /* analog index */ + 0, /* dif_index */ + 0, /* external_index */ + 1, /* only one configuration */ + { + { + 0, /* config index */ + { + 0, /* interrupt ep index */ + NOT_SUPPORTED, /* ts1 index */ + NOT_SUPPORTED, /* TS2 index */ + 1, /* AUDIO */ + 2, /* VIDEO */ + 3, /* VANC */ + 4, /* HANC */ + NOT_SUPPORTED /* ir_index */ + } + } + , + {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED, + NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED, + NOT_SUPPORTED} + } + , + {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED, + NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED, + NOT_SUPPORTED} + } + } + , + { /* full-speed */ + { + 0, /* config index */ + { + 0, /* interrupt ep index */ + NOT_SUPPORTED, /* ts1 index */ + NOT_SUPPORTED, /* TS2 index */ + 1, /* AUDIO */ + 2, /* VIDEO */ + NOT_SUPPORTED, /* VANC */ + NOT_SUPPORTED, /* HANC */ + NOT_SUPPORTED /* ir_index */ + } + } + , + {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED, + NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED, + NOT_SUPPORTED} + } + , + {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED, + NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED, + NOT_SUPPORTED} + } + } + } + , + { + INDEX_BUSPOWER_DIF_ONLY, /* index */ + USB_BUS_POWER, /* power_type */ + 0, /* speed , not decide yet */ + /* mode ,analog tv AND DIGITAL path */ + MOD_DIF | MOD_ANALOG | MOD_DIGITAL | MOD_EXTERNAL, + SOURCE_TS_BDA, /* ts1_source, disable */ + NOT_SUPPORTED, /* ts2_source */ + SOURCE_DIF | SOURCE_ANALOG | SOURCE_EXTERNAL, /* analog source, dif */ + 0, /* digital_index */ + 0, /* analog index */ + 0, /* dif_index */ + 0, /* external_index */ + 1, /* only one configuration */ + { + { + 0, /* config index */ + { + 0, /* interrupt ep index */ + 1, /* ts1 index */ + NOT_SUPPORTED, /* TS2 index */ + 2, /* AUDIO */ + 3, /* VIDEO */ + 4, /* VANC */ + 5, /* HANC */ + NOT_SUPPORTED /* ir_index */ + } + } + , + {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED, + NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED, + NOT_SUPPORTED} + } + , + {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED, + NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED, + NOT_SUPPORTED} + } + } + , + { /* full speed */ + { + 0, /* config index */ + { + 0, /* interrupt ep index */ + 1, /* ts1 index */ + NOT_SUPPORTED, /* TS2 index */ + 2, /* AUDIO */ + 3, /* VIDEO */ + NOT_SUPPORTED, /* VANC */ + NOT_SUPPORTED, /* HANC */ + NOT_SUPPORTED /* ir_index */ + } + } + , + {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED, + NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED, + NOT_SUPPORTED} + } + , + {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED, + NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED, + NOT_SUPPORTED} + } + } + } + , + +}; + +/*****************************************************************/ + +u32 initialize_cx231xx(struct cx231xx *dev) +{ + u32 config_info = 0; + struct pcb_config *p_pcb_info; + u8 usb_speed = 1; /* from register,1--HS, 0--FS */ + u8 data[4] = { 0, 0, 0, 0 }; + u32 ts1_source = 0; + u32 ts2_source = 0; + u32 analog_source = 0; + u8 tmp = 0; + u8 _current_scenario_idx = 0xff; + + cx231xx_info("PcbConfig::initialize \n"); + + ts1_source = SOURCE_TS_BDA; + ts2_source = SOURCE_TS_BDA; + + /* read board config register to find out which + pcb config it is related to */ + cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, BOARD_CFG_STAT, data, 4); + + config_info = *((u32 *) data); + cx231xx_info("SC(0x00) register = 0x%x\n", config_info); + usb_speed = (u8) (config_info & 0x1); + + /* Verify this device belongs to Bus power or Self power device */ + if (config_info & BUS_POWER) { /* bus-power */ + switch (config_info & BUSPOWER_MASK) { + case TS1_PORT | BUS_POWER: + cx231xx_Scenario[INDEX_BUSPOWER_DIGITAL_ONLY].speed = + usb_speed; + p_pcb_info = + &cx231xx_Scenario[INDEX_BUSPOWER_DIGITAL_ONLY]; + _current_scenario_idx = INDEX_BUSPOWER_DIGITAL_ONLY; + break; + case AVDEC_ENABLE | BUS_POWER: + cx231xx_Scenario[INDEX_BUSPOWER_ANALOG_ONLY].speed = + usb_speed; + p_pcb_info = + &cx231xx_Scenario[INDEX_BUSPOWER_ANALOG_ONLY]; + _current_scenario_idx = INDEX_BUSPOWER_ANALOG_ONLY; + break; + case AVDEC_ENABLE | BUS_POWER | TS1_PORT: + cx231xx_Scenario[INDEX_BUSPOWER_DIF_ONLY].speed = + usb_speed; + p_pcb_info = &cx231xx_Scenario[INDEX_BUSPOWER_DIF_ONLY]; + _current_scenario_idx = INDEX_BUSPOWER_DIF_ONLY; + break; + default: + cx231xx_info("bad config in buspower!!!!\n"); + cx231xx_info("config_info=%x\n", + (config_info & BUSPOWER_MASK)); + return 1; + } + } else { /* self-power */ + + switch (config_info & SELFPOWER_MASK) { + case TS1_PORT | SELF_POWER: + cx231xx_Scenario[INDEX_SELFPOWER_DIGITAL_ONLY].speed = + usb_speed; + p_pcb_info = + &cx231xx_Scenario[INDEX_SELFPOWER_DIGITAL_ONLY]; + _current_scenario_idx = INDEX_SELFPOWER_DIGITAL_ONLY; + break; + case TS1_TS2_PORT | SELF_POWER: + cx231xx_Scenario[INDEX_SELFPOWER_DUAL_DIGITAL].speed = + usb_speed; + cx231xx_Scenario[INDEX_SELFPOWER_DUAL_DIGITAL]. + ts2_source = ts2_source; + p_pcb_info = + &cx231xx_Scenario[INDEX_SELFPOWER_DUAL_DIGITAL]; + _current_scenario_idx = INDEX_SELFPOWER_DUAL_DIGITAL; + break; + case AVDEC_ENABLE | SELF_POWER: + cx231xx_Scenario[INDEX_SELFPOWER_ANALOG_ONLY].speed = + usb_speed; + cx231xx_Scenario[INDEX_SELFPOWER_ANALOG_ONLY]. + analog_source = analog_source; + p_pcb_info = + &cx231xx_Scenario[INDEX_SELFPOWER_ANALOG_ONLY]; + _current_scenario_idx = INDEX_SELFPOWER_ANALOG_ONLY; + break; + case AVDEC_ENABLE | TS1_PORT | SELF_POWER: + cx231xx_Scenario[INDEX_SELFPOWER_DUAL].speed = + usb_speed; + cx231xx_Scenario[INDEX_SELFPOWER_DUAL].ts1_source = + ts1_source; + cx231xx_Scenario[INDEX_SELFPOWER_DUAL].analog_source = + analog_source; + p_pcb_info = &cx231xx_Scenario[INDEX_SELFPOWER_DUAL]; + _current_scenario_idx = INDEX_SELFPOWER_DUAL; + break; + case AVDEC_ENABLE | TS1_TS2_PORT | SELF_POWER: + cx231xx_Scenario[INDEX_SELFPOWER_TRIPLE].speed = + usb_speed; + cx231xx_Scenario[INDEX_SELFPOWER_TRIPLE].ts1_source = + ts1_source; + cx231xx_Scenario[INDEX_SELFPOWER_TRIPLE].ts2_source = + ts2_source; + cx231xx_Scenario[INDEX_SELFPOWER_TRIPLE].analog_source = + analog_source; + p_pcb_info = &cx231xx_Scenario[INDEX_SELFPOWER_TRIPLE]; + _current_scenario_idx = INDEX_SELFPOWER_TRIPLE; + break; + case AVDEC_ENABLE | TS1VIP_TS2_PORT | SELF_POWER: + cx231xx_Scenario[INDEX_SELFPOWER_COMPRESSOR].speed = + usb_speed; + cx231xx_Scenario[INDEX_SELFPOWER_COMPRESSOR]. + analog_source = analog_source; + p_pcb_info = + &cx231xx_Scenario[INDEX_SELFPOWER_COMPRESSOR]; + _current_scenario_idx = INDEX_SELFPOWER_COMPRESSOR; + break; + default: + cx231xx_info("bad senario!!!!!\n"); + cx231xx_info("config_info=%x\n", + (config_info & SELFPOWER_MASK)); + return 1; + } + } + + dev->current_scenario_idx = _current_scenario_idx; + + memcpy(&dev->current_pcb_config, p_pcb_info, + sizeof(struct pcb_config)); + + /*******************************************************************/ + tmp = (dev->current_pcb_config.index) + 1; + + cx231xx_info("scenario %d\n", tmp); + cx231xx_info("type=%x\n", dev->current_pcb_config.type); + cx231xx_info("mode=%x\n", dev->current_pcb_config.mode); + cx231xx_info("speed=%x\n", dev->current_pcb_config.speed); + cx231xx_info("ts1_source=%x\n", dev->current_pcb_config.ts1_source); + cx231xx_info("ts2_source=%x\n", dev->current_pcb_config.ts2_source); + cx231xx_info("analog_source=%x\n", + dev->current_pcb_config.analog_source); + /*******************************************************************/ + + return 0; +} diff --git a/linux/drivers/media/video/cx231xx/cx231xx-pcb-cfg.h b/linux/drivers/media/video/cx231xx/cx231xx-pcb-cfg.h new file mode 100644 index 000000000..86fec113f --- /dev/null +++ b/linux/drivers/media/video/cx231xx/cx231xx-pcb-cfg.h @@ -0,0 +1,235 @@ +/* + cx231xx-pcb-cfg.h - driver for Conexant + Cx23100/101/102 USB video capture devices + + Copyright (C) 2008 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef _PCB_CONFIG_H_ +#define _PCB_CONFIG_H_ + +#include +#include + +/*************************************************************************** + * Class Information * +***************************************************************************/ +#define CLASS_DEFAULT 0xFF + +enum VENDOR_REQUEST_TYPE { + /* Set/Get I2C */ + VRT_SET_I2C0 = 0x0, + VRT_SET_I2C1 = 0x1, + VRT_SET_I2C2 = 0x2, + VRT_GET_I2C0 = 0x4, + VRT_GET_I2C1 = 0x5, + VRT_GET_I2C2 = 0x6, + + /* Set/Get GPIO */ + VRT_SET_GPIO = 0x8, + VRT_GET_GPIO = 0x9, + + /* Set/Get GPIE */ + VRT_SET_GPIE = 0xA, + VRT_GET_GPIE = 0xB, + + /* Set/Get Register Control/Status */ + VRT_SET_REGISTER = 0xC, + VRT_GET_REGISTER = 0xD, + + /* Get Extended Compat ID Descriptor */ + VRT_GET_EXTCID_DESC = 0xFF, +}; + +enum BYTE_ENABLE_MASK { + ENABLE_ONE_BYTE = 0x1, + ENABLE_TWE_BYTE = 0x3, + ENABLE_THREE_BYTE = 0x7, + ENABLE_FOUR_BYTE = 0xF, +}; + +#define SPEED_MASK 0x1 +enum USB_SPEED{ + FULL_SPEED = 0x0, /* 0: full speed */ + HIGH_SPEED = 0x1 /* 1: high speed */ +}; + +enum _true_false{ + FALSE = 0, + TRUE = 1 +}; + +#define TS_MASK 0x6 +enum TS_PORT{ + NO_TS_PORT = 0x0, /* 2'b00: Neither port used. PCB not a Hybrid, + only offers Analog TV or Video */ + TS1_PORT = 0x4, /* 2'b10: TS1 Input (Hybrid mode : + Digital or External Analog/Compressed source) */ + TS1_TS2_PORT = 0x6, /* 2'b11: TS1 & TS2 Inputs + (Dual inputs from Digital and/or + External Analog/Compressed sources) */ + TS1_EXT_CLOCK = 0x6, /* 2'b11: TS1 & TS2 as selector + to external clock */ + TS1VIP_TS2_PORT = 0x2 /* 2'b01: TS1 used as 656/VIP Output, + TS2 Input (from Compressor) */ +}; + +#define EAVP_MASK 0x8 +enum EAV_PRESENT{ + NO_EXTERNAL_AV = 0x0, /* 0: No External A/V inputs + (no need for Flatiron), + Analog Tuner must be present */ + EXTERNAL_AV = 0x8 /* 1: External A/V inputs + present (requires Flatiron) */ +}; + +#define ATM_MASK 0x30 +enum AT_MODE{ + DIF_TUNER = 0x30, /* 2'b11: IF Tuner (requires use of DIF) */ + BASEBAND_SOUND = 0x20, /* 2'b10: Baseband Composite & + Sound-IF Signals present */ + NO_TUNER = 0x10 /* 2'b0x: No Analog Tuner present */ +}; + +#define PWR_SEL_MASK 0x40 +enum POWE_TYPE{ + SELF_POWER = 0x0, /* 0: self power */ + BUS_POWER = 0x40 /* 1: bus power */ +}; + +enum USB_POWE_TYPE{ + USB_SELF_POWER = 0, + USB_BUS_POWER +}; + +#define BO_0_MASK 0x80 +enum AVDEC_STATUS{ + AVDEC_DISABLE = 0x0, /* 0: A/V Decoder Disabled */ + AVDEC_ENABLE = 0x80 /* 1: A/V Decoder Enabled */ +}; + +#define BO_1_MASK 0x100 +enum HAMMERHEAD__STATUS{ + HAMMERHEAD_ONLY = 0x0, /* 0:Hammerhead Only */ + HAMMERHEAD_SC = 0x100 /* 1:Hammerhead and SC */ +}; + +#define BUSPOWER_MASK 0xC4 /* for Polaris spec 0.8 */ +#define SELFPOWER_MASK 0x86 + +/***************************************************************************/ +#define NOT_DECIDE_YET 0xFE +#define NOT_SUPPORTED 0xFF + +/*************************************************************************** + * for mod field use * +***************************************************************************/ +#define MOD_DIGITAL 0x1 +#define MOD_ANALOG 0x2 +#define MOD_DIF 0x4 +#define MOD_EXTERNAL 0x8 +#define CAP_ALL_MOD 0x0f + +/*************************************************************************** + * source define * +***************************************************************************/ +#define SOURCE_DIGITAL 0x1 +#define SOURCE_ANALOG 0x2 +#define SOURCE_DIF 0x4 +#define SOURCE_EXTERNAL 0x8 +#define SOURCE_TS_BDA 0x10 +#define SOURCE_TS_ENCODE 0x20 +#define SOURCE_TS_EXTERNAL 0x40 + +/*************************************************************************** + * interface information define * +***************************************************************************/ +struct INTERFACE_INFO { + u8 interrupt_index; + u8 ts1_index; + u8 ts2_index; + u8 audio_index; + u8 video_index; + u8 vanc_index; /* VBI */ + u8 hanc_index; /* Sliced CC */ + u8 ir_index; +}; + +enum INDEX_INTERFACE_INFO{ + INDEX_INTERRUPT = 0x0, + INDEX_TS1, + INDEX_TS2, + INDEX_AUDIO, + INDEX_VIDEO, + INDEX_VANC, + INDEX_HANC, + INDEX_IR, +}; + +/*************************************************************************** + * configuration information define * +***************************************************************************/ +struct CONFIG_INFO { + u8 config_index; + struct INTERFACE_INFO interface_info; +}; + +struct pcb_config { + u8 index; + u8 type; /* bus power or self power, + self power--0, bus_power--1 */ + u8 speed; /* usb speed, 2.0--1, 1.1--0 */ + u8 mode; /* digital , anlog, dif or external A/V */ + u32 ts1_source; /* three source -- BDA,External,encode */ + u32 ts2_source; + u32 analog_source; + u8 digital_index; /* bus-power used */ + u8 analog_index; /* bus-power used */ + u8 dif_index; /* bus-power used */ + u8 external_index; /* bus-power used */ + u8 config_num; /* current config num, 0,1,2, + for self-power, always 0 */ + struct CONFIG_INFO hs_config_info[3]; + struct CONFIG_INFO fs_config_info[3]; +}; + +enum INDEX_PCB_CONFIG{ + INDEX_SELFPOWER_DIGITAL_ONLY = 0x0, + INDEX_SELFPOWER_DUAL_DIGITAL, + INDEX_SELFPOWER_ANALOG_ONLY, + INDEX_SELFPOWER_DUAL, + INDEX_SELFPOWER_TRIPLE, + INDEX_SELFPOWER_COMPRESSOR, + INDEX_BUSPOWER_DIGITAL_ONLY, + INDEX_BUSPOWER_ANALOG_ONLY, + INDEX_BUSPOWER_DIF_ONLY, + INDEX_BUSPOWER_EXTERNAL_ONLY, + INDEX_BUSPOWER_EXTERNAL_ANALOG, + INDEX_BUSPOWER_EXTERNAL_DIF, + INDEX_BUSPOWER_EXTERNAL_DIGITAL, + INDEX_BUSPOWER_DIGITAL_ANALOG, + INDEX_BUSPOWER_DIGITAL_DIF, + INDEX_BUSPOWER_DIGITAL_ANALOG_EXTERNAL, + INDEX_BUSPOWER_DIGITAL_DIF_EXTERNAL, +}; + +/***************************************************************************/ +struct cx231xx; + +u32 initialize_cx231xx(struct cx231xx *p_dev); + +#endif diff --git a/linux/drivers/media/video/cx231xx/cx231xx-reg.h b/linux/drivers/media/video/cx231xx/cx231xx-reg.h index d2d325b21..750c5d37d 100644 --- a/linux/drivers/media/video/cx231xx/cx231xx-reg.h +++ b/linux/drivers/media/video/cx231xx/cx231xx-reg.h @@ -1,6 +1,6 @@ /* cx231xx-reg.h - driver for Conexant Cx23100/101/102 - USB video capture devices + USB video capture devices Copyright (C) 2008 @@ -23,31 +23,31 @@ #define _CX231XX_REG_H /***************************************************************************** - * VBI codes * + * VBI codes * *****************************************************************************/ -#define SAV_ACTIVE_VIDEO_FIELD1 0x80 -#define EAV_ACTIVE_VIDEO_FIELD1 0x90 +#define SAV_ACTIVE_VIDEO_FIELD1 0x80 +#define EAV_ACTIVE_VIDEO_FIELD1 0x90 -#define SAV_ACTIVE_VIDEO_FIELD2 0xC0 -#define EAV_ACTIVE_VIDEO_FIELD2 0xD0 +#define SAV_ACTIVE_VIDEO_FIELD2 0xc0 +#define EAV_ACTIVE_VIDEO_FIELD2 0xd0 -#define SAV_VBLANK_FIELD1 0xA0 -#define EAV_VBLANK_FIELD1 0xB0 +#define SAV_VBLANK_FIELD1 0xa0 +#define EAV_VBLANK_FIELD1 0xb0 -#define SAV_VBLANK_FIELD2 0xE0 -#define EAV_VBLANK_FIELD2 0xF0 +#define SAV_VBLANK_FIELD2 0xe0 +#define EAV_VBLANK_FIELD2 0xf0 -#define SAV_VBI_FIELD1 0x20 -#define EAV_VBI_FIELD1 0x30 +#define SAV_VBI_FIELD1 0x20 +#define EAV_VBI_FIELD1 0x30 -#define SAV_VBI_FIELD2 0x60 -#define EAV_VBI_FIELD2 0x70 +#define SAV_VBI_FIELD2 0x60 +#define EAV_VBI_FIELD2 0x70 /*****************************************************************************/ /* Audio ADC Registers */ -#define CH_PWR_CTRL1 0x0000000E -#define CH_PWR_CTRL2 0x0000000F +#define CH_PWR_CTRL1 0x0000000e +#define CH_PWR_CTRL2 0x0000000f /*****************************************************************************/ #define HOST_REG1 0x000 @@ -74,11 +74,11 @@ #define TS1_PIN_CTL1 0x8 /*****************************************************************************/ -#define FLD_CLK_IN_EN 0x80 -#define FLD_XTAL_CTRL 0x70 -#define FLD_BB_CLK_MODE 0x0C -#define FLD_REF_DIV_PLL 0x02 -#define FLD_REF_SEL_PLL1 0x01 +#define FLD_CLK_IN_EN 0x80 +#define FLD_XTAL_CTRL 0x70 +#define FLD_BB_CLK_MODE 0x0C +#define FLD_REF_DIV_PLL 0x02 +#define FLD_REF_SEL_PLL1 0x01 /*****************************************************************************/ #define CHIP_CTRL 0x100 @@ -89,16 +89,16 @@ #define FLD_DUAL_MODE_ADC2 0x00040000 #define FLD_SIF_EN 0x00020000 #define FLD_SOFT_RST 0x00010000 -#define FLD_DEVICE_ID 0x0000FFFF +#define FLD_DEVICE_ID 0x0000ffff /*****************************************************************************/ #define AFE_CTRL 0x104 #define AFE_CTRL_C2HH_SRC_CTRL 0x104 -#define FLD_DIF_OUT_SEL 0xC0000000 -#define FLD_AUX_PLL_CLK_ALT_SEL 0x3C000000 +#define FLD_DIF_OUT_SEL 0xc0000000 +#define FLD_AUX_PLL_CLK_ALT_SEL 0x3c000000 #define FLD_UV_ORDER_MODE 0x02000000 #define FLD_FUNC_MODE 0x01800000 -#define FLD_ROT1_PHASE_CTL 0x007F8000 +#define FLD_ROT1_PHASE_CTL 0x007f8000 #define FLD_AUD_IN_SEL 0x00004000 #define FLD_LUMA_IN_SEL 0x00002000 #define FLD_CHROMA_IN_SEL 0x00001000 @@ -118,16 +118,16 @@ /*****************************************************************************/ #define DC_CTRL1 0x108 /* reserve [31:30] */ -#define FLD_CLAMP_LVL_CH1 0x3FFF8000 -#define FLD_CLAMP_LVL_CH2 0x00007FFF +#define FLD_CLAMP_LVL_CH1 0x3fff8000 +#define FLD_CLAMP_LVL_CH2 0x00007fff /*****************************************************************************/ /*****************************************************************************/ #define DC_CTRL2 0x10c /* reserve [31:28] */ -#define FLD_CLAMP_LVL_CH3 0x00FFFE00 -#define FLD_CLAMP_WIND_LENTH 0x000001E0 -#define FLD_C2HH_SAT_MIN 0x0000001E +#define FLD_CLAMP_LVL_CH3 0x00fffe00 +#define FLD_CLAMP_WIND_LENTH 0x000001e0 +#define FLD_C2HH_SAT_MIN 0x0000001e #define FLD_FLT_BYP_SEL 0x00000001 /*****************************************************************************/ @@ -135,25 +135,25 @@ #define DC_CTRL3 0x110 /* reserve [31:16] */ #define FLD_ERR_GAIN_CTL 0x00070000 -#define FLD_LPF_MIN 0x0000FFFF +#define FLD_LPF_MIN 0x0000ffff /*****************************************************************************/ /*****************************************************************************/ #define DC_CTRL4 0x114 /* reserve [31:31] */ -#define FLD_INTG_CH1 0x7FFFFFFF +#define FLD_INTG_CH1 0x7fffffff /*****************************************************************************/ /*****************************************************************************/ #define DC_CTRL5 0x118 /* reserve [31:31] */ -#define FLD_INTG_CH2 0x7FFFFFFF +#define FLD_INTG_CH2 0x7fffffff /*****************************************************************************/ /*****************************************************************************/ #define DC_CTRL6 0x11c /* reserve [31:31] */ -#define FLD_INTG_CH3 0x7FFFFFFF +#define FLD_INTG_CH3 0x7fffffff /*****************************************************************************/ /*****************************************************************************/ @@ -182,30 +182,30 @@ #define FLD_I2S_PORT_DIR 0x00000080 #define FLD_I2S_OUT_SRC 0x00000040 #define FLD_AUD_CHAN3_SRC 0x00000030 -#define FLD_AUD_CHAN2_SRC 0x0000000C +#define FLD_AUD_CHAN2_SRC 0x0000000c #define FLD_AUD_CHAN1_SRC 0x00000003 /*****************************************************************************/ #define AUD_LOCK1 0x128 -#define FLD_AUD_LOCK_KI_SHIFT 0xC0000000 +#define FLD_AUD_LOCK_KI_SHIFT 0xc0000000 #define FLD_AUD_LOCK_KD_SHIFT 0x30000000 /* Reserved [27:25] */ #define FLD_EN_AV_LOCK 0x01000000 -#define FLD_VID_COUNT 0x00FFFFFF +#define FLD_VID_COUNT 0x00ffffff /*****************************************************************************/ -#define AUD_LOCK2 0x12C -#define FLD_AUD_LOCK_KI_MULT 0xF0000000 +#define AUD_LOCK2 0x12c +#define FLD_AUD_LOCK_KI_MULT 0xf0000000 #define FLD_AUD_LOCK_KD_MULT 0x0F000000 /* Reserved [23:22] */ #define FLD_AUD_LOCK_FREQ_SHIFT 0x00300000 -#define FLD_AUD_COUNT 0x000FFFFF +#define FLD_AUD_COUNT 0x000fffff /*****************************************************************************/ #define AFE_DIAG_CTRL1 0x134 /* Reserved [31:16] */ -#define FLD_CUV_DLY_LENGTH 0x0000FF00 -#define FLD_YC_DLY_LENGTH 0x000000FF +#define FLD_CUV_DLY_LENGTH 0x0000ff00 +#define FLD_YC_DLY_LENGTH 0x000000ff /*****************************************************************************/ /* Poalris redefine */ @@ -218,18 +218,18 @@ #define FLD_COL_CLAMP_DIS_CH2 0x00200000 #define FLD_COL_CLAMP_DIS_CH3 0x00100000 -#define TEST_CTRL1 0x144 +#define TEST_CTRL1 0x144 /* Reserved [31:29] */ -#define FLD_LBIST_EN 0x10000000 +#define FLD_LBIST_EN 0x10000000 /* Reserved [27:10] */ -#define FLD_FI_BIST_INTR_R 0x0000200 -#define FLD_FI_BIST_INTR_L 0x0000100 -#define FLD_BIST_FAIL_AUD_PLL 0x0000080 -#define FLD_BIST_INTR_AUD_PLL 0x0000040 -#define FLD_BIST_FAIL_VID_PLL 0x0000020 -#define FLD_BIST_INTR_VID_PLL 0x0000010 +#define FLD_FI_BIST_INTR_R 0x0000200 +#define FLD_FI_BIST_INTR_L 0x0000100 +#define FLD_BIST_FAIL_AUD_PLL 0x0000080 +#define FLD_BIST_INTR_AUD_PLL 0x0000040 +#define FLD_BIST_FAIL_VID_PLL 0x0000020 +#define FLD_BIST_INTR_VID_PLL 0x0000010 /* Reserved [3:1] */ -#define FLD_CIR_TEST_DIS 0x00000001 +#define FLD_CIR_TEST_DIS 0x00000001 /*****************************************************************************/ #define TEST_CTRL2 0x148 @@ -237,7 +237,7 @@ #define FLD_ISO_CTL_SEL 0x40000000 #define FLD_ISO_CTL_EN 0x20000000 #define FLD_BIST_DEBUGZ 0x10000000 -#define FLD_AUD_BIST_TEST_H 0x0F000000 +#define FLD_AUD_BIST_TEST_H 0x0f000000 /* Reserved [23:22] */ #define FLD_FLTRN_BIST_TEST_H 0x00020000 #define FLD_VID_BIST_TEST_H 0x00010000 @@ -248,11 +248,11 @@ /* Reserved [11:0] */ /*****************************************************************************/ -#define BIST_STAT 0x14C -#define FLD_AUD_BIST_FAIL_H 0xFFF00000 +#define BIST_STAT 0x14c +#define FLD_AUD_BIST_FAIL_H 0xfff00000 #define FLD_FLTRN_BIST_FAIL_H 0x00180000 #define FLD_VID_BIST_FAIL_H 0x00070000 -#define FLD_AUD_BIST_TST_DONE 0x0000FFF0 +#define FLD_AUD_BIST_TST_DONE 0x0000fff0 #define FLD_FLTRN_BIST_TST_DONE 0x00000008 #define FLD_VID_BIST_TST_DONE 0x00000007 @@ -266,7 +266,7 @@ #define FLD_AFD_FORCE_PAL 0x04000000 #define FLD_AFD_PALM_SEL 0x03000000 #define FLD_CKILL_MODE 0x00300000 -#define FLD_COMB_NOTCH_MODE 0x00c00000 /* bit[19:18] */ +#define FLD_COMB_NOTCH_MODE 0x00c00000 /* bit[19:18] */ #define FLD_CLR_LOCK_STAT 0x00020000 #define FLD_FAST_LOCK_MD 0x00010000 #define FLD_WCEN 0x00008000 @@ -280,11 +280,11 @@ #define FLD_AFD_PAL_SEL 0x00000040 #define FLD_ACFG_DIS 0x00000020 #define FLD_SQ_PIXEL 0x00000010 -#define FLD_VID_FMT_SEL 0x0000000F +#define FLD_VID_FMT_SEL 0x0000000f /*****************************************************************************/ #define OUT_CTRL1 0x404 -#define FLD_POLAR 0x7F000000 +#define FLD_POLAR 0x7f000000 /* Reserved [23] */ #define FLD_RND_MODE 0x00600000 #define FLD_VIPCLAMP_EN 0x00100000 @@ -292,7 +292,7 @@ #define FLD_VIP_OPT_AL 0x00040000 #define FLD_IDID0_SOURCE 0x00020000 #define FLD_DCMODE 0x00010000 -#define FLD_CLK_GATING 0x0000C000 +#define FLD_CLK_GATING 0x0000c000 #define FLD_CLK_INVERT 0x00002000 #define FLD_HSFMT 0x00001000 #define FLD_VALIDFMT 0x00000800 @@ -309,20 +309,20 @@ /*****************************************************************************/ #define OUT_CTRL2 0x408 -#define FLD_AUD_GRP 0xC0000000 +#define FLD_AUD_GRP 0xc0000000 #define FLD_SAMPLE_RATE 0x30000000 #define FLD_AUD_ANC_EN 0x08000000 #define FLD_EN_C 0x04000000 #define FLD_EN_B 0x02000000 #define FLD_EN_A 0x01000000 /* Reserved [23:20] */ -#define FLD_IDID1_LSB 0x000C0000 +#define FLD_IDID1_LSB 0x000c0000 #define FLD_IDID0_LSB 0x00030000 -#define FLD_IDID1_MSB 0x0000FF00 -#define FLD_IDID0_MSB 0x000000FF +#define FLD_IDID1_MSB 0x0000ff00 +#define FLD_IDID0_MSB 0x000000ff /*****************************************************************************/ -#define GEN_STAT 0x40C +#define GEN_STAT 0x40c #define FLD_VCR_DETECT 0x00800000 #define FLD_SPECIAL_PLAY_N 0x00400000 #define FLD_VPRES 0x00200000 @@ -335,7 +335,7 @@ #define FLD_SRC_FIFO_UFLOW 0x00004000 #define FLD_SRC_FIFO_OFLOW 0x00002000 #define FLD_FIELD 0x00001000 -#define FLD_AFD_FMT_STAT 0x00000F00 +#define FLD_AFD_FMT_STAT 0x00000f00 #define FLD_MV_TYPE2_PAIR 0x00000080 #define FLD_MV_T3CS 0x00000040 #define FLD_MV_CS 0x00000020 @@ -383,27 +383,27 @@ #define BRIGHTNESS_CTRL_BYTE 0x414 #define CONTRAST_CTRL_BYTE 0x415 #define LUMA_CTRL_BYTE_3 0x416 -#define FLD_LUMA_CORE_SEL 0x00C00000 +#define FLD_LUMA_CORE_SEL 0x00c00000 #define FLD_RANGE 0x00300000 /* Reserved [19] */ #define FLD_PEAK_EN 0x00040000 #define FLD_PEAK_SEL 0x00030000 -#define FLD_CNTRST 0x0000FF00 -#define FLD_BRITE 0x000000FF +#define FLD_CNTRST 0x0000ff00 +#define FLD_BRITE 0x000000ff /*****************************************************************************/ #define HSCALE_CTRL 0x418 #define FLD_HFILT 0x03000000 -#define FLD_HSCALE 0x00FFFFFF +#define FLD_HSCALE 0x00ffffff /*****************************************************************************/ -#define VSCALE_CTRL 0x41C +#define VSCALE_CTRL 0x41c #define FLD_LINE_AVG_DIS 0x01000000 /* Reserved [23:20] */ #define FLD_VS_INTRLACE 0x00080000 #define FLD_VFILT 0x00070000 /* Reserved [15:13] */ -#define FLD_VSCALE 0x00001FFF +#define FLD_VSCALE 0x00001fff /*****************************************************************************/ #define CHROMA_CTRL 0x420 @@ -411,76 +411,76 @@ #define VSAT_CTRL_BYTE 0x421 #define HUE_CTRL_BYTE 0x422 #define FLD_C_LPF_EN 0x20000000 -#define FLD_CHR_DELAY 0x1C000000 +#define FLD_CHR_DELAY 0x1c000000 #define FLD_C_CORE_SEL 0x03000000 -#define FLD_HUE 0x00FF0000 -#define FLD_VSAT 0x0000FF00 -#define FLD_USAT 0x000000FF +#define FLD_HUE 0x00ff0000 +#define FLD_VSAT 0x0000ff00 +#define FLD_USAT 0x000000ff /*****************************************************************************/ #define VBI_LINE_CTRL1 0x424 -#define FLD_VBI_MD_LINE4 0xFF000000 -#define FLD_VBI_MD_LINE3 0x00FF0000 -#define FLD_VBI_MD_LINE2 0x0000FF00 -#define FLD_VBI_MD_LINE1 0x000000FF +#define FLD_VBI_MD_LINE4 0xff000000 +#define FLD_VBI_MD_LINE3 0x00ff0000 +#define FLD_VBI_MD_LINE2 0x0000ff00 +#define FLD_VBI_MD_LINE1 0x000000ff /*****************************************************************************/ #define VBI_LINE_CTRL2 0x428 -#define FLD_VBI_MD_LINE8 0xFF000000 -#define FLD_VBI_MD_LINE7 0x00FF0000 -#define FLD_VBI_MD_LINE6 0x0000FF00 -#define FLD_VBI_MD_LINE5 0x000000FF +#define FLD_VBI_MD_LINE8 0xff000000 +#define FLD_VBI_MD_LINE7 0x00ff0000 +#define FLD_VBI_MD_LINE6 0x0000ff00 +#define FLD_VBI_MD_LINE5 0x000000ff /*****************************************************************************/ -#define VBI_LINE_CTRL3 0x42C -#define FLD_VBI_MD_LINE12 0xFF000000 -#define FLD_VBI_MD_LINE11 0x00FF0000 -#define FLD_VBI_MD_LINE10 0x0000FF00 -#define FLD_VBI_MD_LINE9 0x000000FF +#define VBI_LINE_CTRL3 0x42c +#define FLD_VBI_MD_LINE12 0xff000000 +#define FLD_VBI_MD_LINE11 0x00ff0000 +#define FLD_VBI_MD_LINE10 0x0000ff00 +#define FLD_VBI_MD_LINE9 0x000000ff /*****************************************************************************/ #define VBI_LINE_CTRL4 0x430 -#define FLD_VBI_MD_LINE16 0xFF000000 -#define FLD_VBI_MD_LINE15 0x00FF0000 -#define FLD_VBI_MD_LINE14 0x0000FF00 -#define FLD_VBI_MD_LINE13 0x000000FF +#define FLD_VBI_MD_LINE16 0xff000000 +#define FLD_VBI_MD_LINE15 0x00ff0000 +#define FLD_VBI_MD_LINE14 0x0000ff00 +#define FLD_VBI_MD_LINE13 0x000000ff /*****************************************************************************/ #define VBI_LINE_CTRL5 0x434 -#define FLD_VBI_MD_LINE17 0x000000FF +#define FLD_VBI_MD_LINE17 0x000000ff /*****************************************************************************/ #define VBI_FC_CFG 0x438 -#define FLD_FC_ALT2 0xFF000000 -#define FLD_FC_ALT1 0x00FF0000 -#define FLD_FC_ALT2_TYPE 0x0000F000 -#define FLD_FC_ALT1_TYPE 0x00000F00 +#define FLD_FC_ALT2 0xff000000 +#define FLD_FC_ALT1 0x00ff0000 +#define FLD_FC_ALT2_TYPE 0x0000f000 +#define FLD_FC_ALT1_TYPE 0x00000f00 /* Reserved [7:1] */ #define FLD_FC_SEARCH_MODE 0x00000001 /*****************************************************************************/ -#define VBI_MISC_CFG1 0x43C -#define FLD_TTX_PKTADRU 0xFFF00000 -#define FLD_TTX_PKTADRL 0x000FFF00 +#define VBI_MISC_CFG1 0x43c +#define FLD_TTX_PKTADRU 0xfff00000 +#define FLD_TTX_PKTADRL 0x000fff00 /* Reserved [7:6] */ #define FLD_MOJI_PACK_DIS 0x00000020 #define FLD_VPS_DEC_DIS 0x00000010 -#define FLD_CRI_MARG_SCALE 0x0000000C +#define FLD_CRI_MARG_SCALE 0x0000000c #define FLD_EDGE_RESYNC_EN 0x00000002 #define FLD_ADAPT_SLICE_DIS 0x00000001 /*****************************************************************************/ #define VBI_MISC_CFG2 0x440 -#define FLD_HAMMING_TYPE 0x0F000000 +#define FLD_HAMMING_TYPE 0x0f000000 /* Reserved [23:20] */ #define FLD_WSS_FIFO_RST 0x00080000 #define FLD_GS2_FIFO_RST 0x00040000 #define FLD_GS1_FIFO_RST 0x00020000 #define FLD_CC_FIFO_RST 0x00010000 /* Reserved [15:12] */ -#define FLD_VBI3_SDID 0x00000F00 -#define FLD_VBI2_SDID 0x000000F0 -#define FLD_VBI1_SDID 0x0000000F +#define FLD_VBI3_SDID 0x00000f00 +#define FLD_VBI2_SDID 0x000000f0 +#define FLD_VBI1_SDID 0x0000000f /*****************************************************************************/ #define VBI_PAY1 0x444 @@ -491,95 +491,95 @@ /*****************************************************************************/ #define VBI_PAY2 0x448 -#define FLD_WSS_FIFO_DAT 0xFF000000 -#define FLD_WSS_STAT 0x00FF0000 -#define FLD_GS2_FIFO_DAT 0x0000FF00 -#define FLD_GS2_STAT 0x000000FF +#define FLD_WSS_FIFO_DAT 0xff000000 +#define FLD_WSS_STAT 0x00ff0000 +#define FLD_GS2_FIFO_DAT 0x0000ff00 +#define FLD_GS2_STAT 0x000000ff /*****************************************************************************/ -#define VBI_CUST1_CFG1 0x44C +#define VBI_CUST1_CFG1 0x44c /* Reserved [31] */ -#define FLD_VBI1_CRIWIN 0x7F000000 -#define FLD_VBI1_SLICE_DIST 0x00F00000 -#define FLD_VBI1_BITINC 0x000FFF00 -#define FLD_VBI1_HDELAY 0x000000FF +#define FLD_VBI1_CRIWIN 0x7f000000 +#define FLD_VBI1_SLICE_DIST 0x00f00000 +#define FLD_VBI1_BITINC 0x000fff00 +#define FLD_VBI1_HDELAY 0x000000ff /*****************************************************************************/ #define VBI_CUST1_CFG2 0x450 -#define FLD_VBI1_FC_LENGTH 0x1F000000 -#define FLD_VBI1_FRAME_CODE 0x00FFFFFF +#define FLD_VBI1_FC_LENGTH 0x1f000000 +#define FLD_VBI1_FRAME_CODE 0x00ffffff /*****************************************************************************/ #define VBI_CUST1_CFG3 0x454 #define FLD_VBI1_HAM_EN 0x80000000 #define FLD_VBI1_FIFO_MODE 0x70000000 -#define FLD_VBI1_FORMAT_TYPE 0x0F000000 -#define FLD_VBI1_PAYLD_LENGTH 0x00FF0000 -#define FLD_VBI1_CRI_LENGTH 0x0000F000 -#define FLD_VBI1_CRI_MARGIN 0x00000F00 -#define FLD_VBI1_CRI_TIME 0x000000FF +#define FLD_VBI1_FORMAT_TYPE 0x0f000000 +#define FLD_VBI1_PAYLD_LENGTH 0x00ff0000 +#define FLD_VBI1_CRI_LENGTH 0x0000f000 +#define FLD_VBI1_CRI_MARGIN 0x00000f00 +#define FLD_VBI1_CRI_TIME 0x000000ff /*****************************************************************************/ #define VBI_CUST2_CFG1 0x458 /* Reserved [31] */ -#define FLD_VBI2_CRIWIN 0x7F000000 -#define FLD_VBI2_SLICE_DIST 0x00F00000 -#define FLD_VBI2_BITINC 0x000FFF00 -#define FLD_VBI2_HDELAY 0x000000FF +#define FLD_VBI2_CRIWIN 0x7f000000 +#define FLD_VBI2_SLICE_DIST 0x00f00000 +#define FLD_VBI2_BITINC 0x000fff00 +#define FLD_VBI2_HDELAY 0x000000ff /*****************************************************************************/ -#define VBI_CUST2_CFG2 0x45C -#define FLD_VBI2_FC_LENGTH 0x1F000000 -#define FLD_VBI2_FRAME_CODE 0x00FFFFFF +#define VBI_CUST2_CFG2 0x45c +#define FLD_VBI2_FC_LENGTH 0x1f000000 +#define FLD_VBI2_FRAME_CODE 0x00ffffff /*****************************************************************************/ #define VBI_CUST2_CFG3 0x460 #define FLD_VBI2_HAM_EN 0x80000000 #define FLD_VBI2_FIFO_MODE 0x70000000 -#define FLD_VBI2_FORMAT_TYPE 0x0F000000 -#define FLD_VBI2_PAYLD_LENGTH 0x00FF0000 -#define FLD_VBI2_CRI_LENGTH 0x0000F000 -#define FLD_VBI2_CRI_MARGIN 0x00000F00 -#define FLD_VBI2_CRI_TIME 0x000000FF +#define FLD_VBI2_FORMAT_TYPE 0x0f000000 +#define FLD_VBI2_PAYLD_LENGTH 0x00ff0000 +#define FLD_VBI2_CRI_LENGTH 0x0000f000 +#define FLD_VBI2_CRI_MARGIN 0x00000f00 +#define FLD_VBI2_CRI_TIME 0x000000ff /*****************************************************************************/ #define VBI_CUST3_CFG1 0x464 /* Reserved [31] */ -#define FLD_VBI3_CRIWIN 0x7F000000 -#define FLD_VBI3_SLICE_DIST 0x00F00000 -#define FLD_VBI3_BITINC 0x000FFF00 -#define FLD_VBI3_HDELAY 0x000000FF +#define FLD_VBI3_CRIWIN 0x7f000000 +#define FLD_VBI3_SLICE_DIST 0x00f00000 +#define FLD_VBI3_BITINC 0x000fff00 +#define FLD_VBI3_HDELAY 0x000000ff /*****************************************************************************/ #define VBI_CUST3_CFG2 0x468 -#define FLD_VBI3_FC_LENGTH 0x1F000000 -#define FLD_VBI3_FRAME_CODE 0x00FFFFFF +#define FLD_VBI3_FC_LENGTH 0x1f000000 +#define FLD_VBI3_FRAME_CODE 0x00ffffff /*****************************************************************************/ -#define VBI_CUST3_CFG3 0x46C +#define VBI_CUST3_CFG3 0x46c #define FLD_VBI3_HAM_EN 0x80000000 #define FLD_VBI3_FIFO_MODE 0x70000000 -#define FLD_VBI3_FORMAT_TYPE 0x0F000000 -#define FLD_VBI3_PAYLD_LENGTH 0x00FF0000 -#define FLD_VBI3_CRI_LENGTH 0x0000F000 -#define FLD_VBI3_CRI_MARGIN 0x00000F00 -#define FLD_VBI3_CRI_TIME 0x000000FF +#define FLD_VBI3_FORMAT_TYPE 0x0f000000 +#define FLD_VBI3_PAYLD_LENGTH 0x00ff0000 +#define FLD_VBI3_CRI_LENGTH 0x0000f000 +#define FLD_VBI3_CRI_MARGIN 0x00000f00 +#define FLD_VBI3_CRI_TIME 0x000000ff /*****************************************************************************/ #define HORIZ_TIM_CTRL 0x470 -#define FLD_BGDEL_CNT 0xFF000000 +#define FLD_BGDEL_CNT 0xff000000 /* Reserved [23:22] */ -#define FLD_HACTIVE_CNT 0x003FF000 +#define FLD_HACTIVE_CNT 0x003ff000 /* Reserved [11:10] */ -#define FLD_HBLANK_CNT 0x000003FF +#define FLD_HBLANK_CNT 0x000003ff /*****************************************************************************/ #define VERT_TIM_CTRL 0x474 -#define FLD_V656BLANK_CNT 0xFF000000 +#define FLD_V656BLANK_CNT 0xff000000 /* Reserved [23:22] */ -#define FLD_VACTIVE_CNT 0x003FF000 +#define FLD_VACTIVE_CNT 0x003ff000 /* Reserved [11:10] */ -#define FLD_VBLANK_CNT 0x000003FF +#define FLD_VBLANK_CNT 0x000003ff /*****************************************************************************/ #define SRC_COMB_CFG 0x478 @@ -591,36 +591,36 @@ #define FLD_LCOMB_3LN_EN 0x04000000 #define FLD_LCOMB_2LN_EN 0x02000000 #define FLD_LCOMB_3D_EN 0x01000000 -#define FLD_LUMA_LPF_SEL 0x00C00000 +#define FLD_LUMA_LPF_SEL 0x00c00000 #define FLD_UV_LPF_SEL 0x00300000 -#define FLD_BLEND_SLOPE 0x000F0000 +#define FLD_BLEND_SLOPE 0x000f0000 #define FLD_CCOMB_REDUCE_EN 0x00008000 /* Reserved [14:10] */ -#define FLD_SRC_DECIM_RATIO 0x000003FF +#define FLD_SRC_DECIM_RATIO 0x000003ff /*****************************************************************************/ -#define CHROMA_VBIOFF_CFG 0x47C -#define FLD_VBI_VOFFSET 0x1F000000 +#define CHROMA_VBIOFF_CFG 0x47c +#define FLD_VBI_VOFFSET 0x1f000000 /* Reserved [23:20] */ -#define FLD_SC_STEP 0x000FFFFF +#define FLD_SC_STEP 0x000fffff /*****************************************************************************/ #define FIELD_COUNT 0x480 -#define FLD_FIELD_COUNT_FLD 0x000003FF +#define FLD_FIELD_COUNT_FLD 0x000003ff /*****************************************************************************/ #define MISC_TIM_CTRL 0x484 -#define FLD_DEBOUNCE_COUNT 0xC0000000 +#define FLD_DEBOUNCE_COUNT 0xc0000000 #define FLD_VT_LINE_CNT_HYST 0x30000000 /* Reserved [27] */ -#define FLD_AFD_STAT 0x07FF0000 +#define FLD_AFD_STAT 0x07ff0000 #define FLD_VPRES_VERT_EN 0x00008000 /* Reserved [14:12] */ #define FLD_HR32 0x00000800 #define FLD_TDALGN 0x00000400 #define FLD_TDFIELD 0x00000200 /* Reserved [8:6] */ -#define FLD_TEMPDEC 0x0000003F +#define FLD_TEMPDEC 0x0000003f /*****************************************************************************/ #define DFE_CTRL1 0x488 @@ -632,33 +632,33 @@ #define FLD_CLAMP_LEVEL 0x07000000 /* Reserved [23:22] */ #define FLD_CLAMP_SKIP_CNT 0x00300000 -#define FLD_AGC_GAIN 0x000FFF00 +#define FLD_AGC_GAIN 0x000fff00 /* Reserved [7:6] */ -#define FLD_VGA_GAIN 0x0000003F +#define FLD_VGA_GAIN 0x0000003f /*****************************************************************************/ -#define DFE_CTRL2 0x48C -#define FLD_VGA_ACQUIRE_RANGE 0x00FF0000 -#define FLD_VGA_TRACK_RANGE 0x0000FF00 -#define FLD_VGA_SYNC 0x000000FF +#define DFE_CTRL2 0x48c +#define FLD_VGA_ACQUIRE_RANGE 0x00ff0000 +#define FLD_VGA_TRACK_RANGE 0x0000ff00 +#define FLD_VGA_SYNC 0x000000ff /*****************************************************************************/ #define DFE_CTRL3 0x490 -#define FLD_BP_PERCENT 0xFF000000 -#define FLD_DFT_THRESHOLD 0x00FF0000 +#define FLD_BP_PERCENT 0xff000000 +#define FLD_DFT_THRESHOLD 0x00ff0000 /* Reserved [15:12] */ #define FLD_SYNC_WIDTH_SEL 0x00000600 #define FLD_BP_LOOP_GAIN 0x00000300 -#define FLD_SYNC_LOOP_GAIN 0x000000C0 +#define FLD_SYNC_LOOP_GAIN 0x000000c0 /* Reserved [5:4] */ -#define FLD_AGC_LOOP_GAIN 0x0000000C +#define FLD_AGC_LOOP_GAIN 0x0000000c #define FLD_DCC_LOOP_GAIN 0x00000003 /*****************************************************************************/ #define PLL_CTRL 0x494 -#define FLD_PLL_KD 0xFF000000 -#define FLD_PLL_KI 0x00FF0000 -#define FLD_PLL_MAX_OFFSET 0x0000FFFF +#define FLD_PLL_KD 0xff000000 +#define FLD_PLL_KI 0x00ff0000 +#define FLD_PLL_MAX_OFFSET 0x0000ffff /*****************************************************************************/ #define HTL_CTRL 0x498 @@ -667,29 +667,29 @@ #define FLD_MAN_FAST_LOCK 0x00040000 #define FLD_HTL_15K_EN 0x00020000 #define FLD_HTL_500K_EN 0x00010000 -#define FLD_HTL_KD 0x0000FF00 -#define FLD_HTL_KI 0x000000FF +#define FLD_HTL_KD 0x0000ff00 +#define FLD_HTL_KI 0x000000ff /*****************************************************************************/ -#define COMB_CTRL 0x49C -#define FLD_COMB_PHASE_LIMIT 0xFF000000 -#define FLD_CCOMB_ERR_LIMIT 0x00FF0000 -#define FLD_LUMA_THRESHOLD 0x0000FF00 -#define FLD_LCOMB_ERR_LIMIT 0x000000FF +#define COMB_CTRL 0x49c +#define FLD_COMB_PHASE_LIMIT 0xff000000 +#define FLD_CCOMB_ERR_LIMIT 0x00ff0000 +#define FLD_LUMA_THRESHOLD 0x0000ff00 +#define FLD_LCOMB_ERR_LIMIT 0x000000ff /*****************************************************************************/ -#define CRUSH_CTRL 0x4A0 +#define CRUSH_CTRL 0x4a0 #define FLD_WTW_EN 0x00400000 #define FLD_CRUSH_FREQ 0x00200000 #define FLD_MAJ_SEL_EN 0x00100000 -#define FLD_MAJ_SEL 0x000C0000 +#define FLD_MAJ_SEL 0x000c0000 /* Reserved [17:15] */ -#define FLD_SYNC_TIP_REDUCE 0x00007E00 +#define FLD_SYNC_TIP_REDUCE 0x00007e00 /* Reserved [8:6] */ -#define FLD_SYNC_TIP_INC 0x0000003F +#define FLD_SYNC_TIP_INC 0x0000003f /*****************************************************************************/ -#define SOFT_RST_CTRL 0x4A4 +#define SOFT_RST_CTRL 0x4a4 #define FLD_VD_SOFT_RST 0x00008000 /* Reserved [14:12] */ #define FLD_REG_RST_MSK 0x00000800 @@ -706,22 +706,22 @@ /* Reserved [0] */ /*****************************************************************************/ -#define MV_DT_CTRL1 0x4A8 +#define MV_DT_CTRL1 0x4a8 /* Reserved [31:29] */ -#define FLD_PSP_STOP_LINE 0x1F000000 +#define FLD_PSP_STOP_LINE 0x1f000000 /* Reserved [23:21] */ -#define FLD_PSP_STRT_LINE 0x001F0000 +#define FLD_PSP_STRT_LINE 0x001f0000 /* Reserved [15] */ -#define FLD_PSP_LLIMW 0x00007F00 +#define FLD_PSP_LLIMW 0x00007f00 /* Reserved [7] */ -#define FLD_PSP_ULIMW 0x0000007F +#define FLD_PSP_ULIMW 0x0000007f /*****************************************************************************/ -#define MV_DT_CTRL2 0x4AC -#define FLD_CS_STOPWIN 0xFF000000 -#define FLD_CS_STRTWIN 0x00FF0000 -#define FLD_CS_WIDTH 0x0000FF00 -#define FLD_PSP_SPEC_VAL 0x000000FF +#define MV_DT_CTRL2 0x4aC +#define FLD_CS_STOPWIN 0xff000000 +#define FLD_CS_STRTWIN 0x00ff0000 +#define FLD_CS_WIDTH 0x0000ff00 +#define FLD_PSP_SPEC_VAL 0x000000ff /*****************************************************************************/ #define MV_DT_CTRL3 0x4B0 @@ -733,47 +733,47 @@ #define FLD_CS_ATHRESH_SEL 0x04000000 #define FLD_PSP_SPEC_SEL 0x02000000 #define FLD_PSP_LINES_SEL 0x01000000 -#define FLD_FIELD_CNT 0x00F00000 -#define FLD_CS_TYPE2_CNT 0x000FC000 -#define FLD_CS_LINE_CNT 0x00003F00 -#define FLD_CS_ATHRESH_LEV 0x000000FF +#define FLD_FIELD_CNT 0x00f00000 +#define FLD_CS_TYPE2_CNT 0x000fc000 +#define FLD_CS_LINE_CNT 0x00003f00 +#define FLD_CS_ATHRESH_LEV 0x000000ff /*****************************************************************************/ -#define CHIP_VERSION 0x4B4 +#define CHIP_VERSION 0x4b4 /* Cx231xx redefine */ -#define VERSION 0x4B4 -#define FLD_REV_ID 0x000000FF +#define VERSION 0x4b4 +#define FLD_REV_ID 0x000000ff /*****************************************************************************/ -#define MISC_DIAG_CTRL 0x4B8 +#define MISC_DIAG_CTRL 0x4b8 /* Reserved [31:24] */ -#define FLD_SC_CONVERGE_THRESH 0x00FF0000 -#define FLD_CCOMB_ERR_LIMIT_3D 0x0000FF00 -#define FLD_LCOMB_ERR_LIMIT_3D 0x000000FF +#define FLD_SC_CONVERGE_THRESH 0x00ff0000 +#define FLD_CCOMB_ERR_LIMIT_3D 0x0000ff00 +#define FLD_LCOMB_ERR_LIMIT_3D 0x000000ff /*****************************************************************************/ -#define VBI_PASS_CTRL 0x4BC +#define VBI_PASS_CTRL 0x4bc #define FLD_VBI_PASS_MD 0x00200000 #define FLD_VBI_SETUP_DIS 0x00100000 -#define FLD_PASS_LINE_CTRL 0x000FFFFF +#define FLD_PASS_LINE_CTRL 0x000fffff /*****************************************************************************/ /* Cx231xx redefine */ #define VCR_DET_CTRL 0x4c0 #define FLD_EN_FIELD_PHASE_DET 0x80000000 #define FLD_EN_HEAD_SW_DET 0x40000000 -#define FLD_FIELD_PHASE_LENGTH 0x01FF0000 +#define FLD_FIELD_PHASE_LENGTH 0x01ff0000 /* Reserved [29:25] */ -#define FLD_FIELD_PHASE_DELAY 0x0000FF00 -#define FLD_FIELD_PHASE_LIMIT 0x000000F0 -#define FLD_HEAD_SW_DET_LIMIT 0x0000000F +#define FLD_FIELD_PHASE_DELAY 0x0000ff00 +#define FLD_FIELD_PHASE_LIMIT 0x000000f0 +#define FLD_HEAD_SW_DET_LIMIT 0x0000000f /*****************************************************************************/ #define DL_CTL 0x800 -#define DL_CTL_ADDRESS_LOW 0x800 /* Byte 1 in DL_CTL */ -#define DL_CTL_ADDRESS_HIGH 0x801 /* Byte 2 in DL_CTL */ -#define DL_CTL_DATA 0x802 /* Byte 3 in DL_CTL */ -#define DL_CTL_CONTROL 0x803 /* Byte 4 in DL_CTL */ +#define DL_CTL_ADDRESS_LOW 0x800 /* Byte 1 in DL_CTL */ +#define DL_CTL_ADDRESS_HIGH 0x801 /* Byte 2 in DL_CTL */ +#define DL_CTL_DATA 0x802 /* Byte 3 in DL_CTL */ +#define DL_CTL_CONTROL 0x803 /* Byte 4 in DL_CTL */ /* Reserved [31:5] */ #define FLD_START_8051 0x10000000 #define FLD_DL_ENABLE 0x08000000 @@ -782,28 +782,28 @@ /*****************************************************************************/ #define STD_DET_STATUS 0x804 -#define FLD_SPARE_STATUS1 0xFF000000 -#define FLD_SPARE_STATUS0 0x00FF0000 -#define FLD_MOD_DET_STATUS1 0x0000FF00 -#define FLD_MOD_DET_STATUS0 0x000000FF +#define FLD_SPARE_STATUS1 0xff000000 +#define FLD_SPARE_STATUS0 0x00ff0000 +#define FLD_MOD_DET_STATUS1 0x0000ff00 +#define FLD_MOD_DET_STATUS0 0x000000ff /*****************************************************************************/ #define AUD_BUILD_NUM 0x806 #define AUD_VER_NUM 0x807 #define STD_DET_CTL 0x808 -#define STD_DET_CTL_AUD_CTL 0x808 /* Byte 1 in STD_DET_CTL */ -#define STD_DET_CTL_PREF_MODE 0x809 /* Byte 2 in STD_DET_CTL */ -#define FLD_SPARE_CTL0 0xFF000000 +#define STD_DET_CTL_AUD_CTL 0x808 /* Byte 1 in STD_DET_CTL */ +#define STD_DET_CTL_PREF_MODE 0x809 /* Byte 2 in STD_DET_CTL */ +#define FLD_SPARE_CTL0 0xff000000 #define FLD_DIS_DBX 0x00800000 #define FLD_DIS_BTSC 0x00400000 #define FLD_DIS_NICAM_A2 0x00200000 #define FLD_VIDEO_PRESENT 0x00100000 -#define FLD_DW8051_VIDEO_FORMAT 0x000F0000 -#define FLD_PREF_DEC_MODE 0x0000FF00 -#define FLD_AUD_CONFIG 0x000000FF +#define FLD_DW8051_VIDEO_FORMAT 0x000f0000 +#define FLD_PREF_DEC_MODE 0x0000ff00 +#define FLD_AUD_CONFIG 0x000000ff /*****************************************************************************/ -#define DW8051_INT 0x80C +#define DW8051_INT 0x80c #define FLD_VIDEO_PRESENT_CHANGE 0x80000000 #define FLD_VIDEO_CHANGE 0x40000000 #define FLD_RDS_READY 0x20000000 @@ -854,7 +854,7 @@ #define FLD_FC_INT_DIS 0x00040000 #define FLD_AMC_INT_DIS 0x00020000 #define FLD_AC97_INT_DIS 0x00010000 -#define FLD_REV_NUM 0x0000FF00 +#define FLD_REV_NUM 0x0000ff00 /* Reserved [7:5] */ #define FLD_DBX_SOFT_RESET_REG 0x00000010 #define FLD_AD_SOFT_RESET_REG 0x00000008 @@ -866,14 +866,14 @@ #define AAGC_CTL 0x814 #define FLD_AFE_12DB_EN 0x80000000 #define FLD_AAGC_DEFAULT_EN 0x40000000 -#define FLD_AAGC_DEFAULT 0x3F000000 +#define FLD_AAGC_DEFAULT 0x3f000000 /* Reserved [23] */ #define FLD_AAGC_GAIN 0x00600000 -#define FLD_AAGC_TH 0x001F0000 +#define FLD_AAGC_TH 0x001f0000 /* Reserved [15:14] */ -#define FLD_AAGC_HYST2 0x00003F00 +#define FLD_AAGC_HYST2 0x00003f00 /* Reserved [7:6] */ -#define FLD_AAGC_HYST1 0x0000003F +#define FLD_AAGC_HYST1 0x0000003f /*****************************************************************************/ #define IF_SRC_CTL 0x818 @@ -881,16 +881,16 @@ /* Reserved [30:25] */ #define FLD_IF_SRC_MODE 0x01000000 /* Reserved [23:18] */ -#define FLD_IF_SRC_PHASE_INC 0x0001FFFF +#define FLD_IF_SRC_PHASE_INC 0x0001ffff /*****************************************************************************/ -#define ANALOG_DEMOD_CTL 0x81C -#define FLD_ROT1_PHACC_PROG 0xFFFF0000 +#define ANALOG_DEMOD_CTL 0x81c +#define FLD_ROT1_PHACC_PROG 0xffff0000 /* Reserved [15] */ #define FLD_FM1_DELAY_FIX 0x00007000 -#define FLD_PDF4_SHIFT 0x00000C00 +#define FLD_PDF4_SHIFT 0x00000c00 #define FLD_PDF3_SHIFT 0x00000300 -#define FLD_PDF2_SHIFT 0x000000C0 +#define FLD_PDF2_SHIFT 0x000000c0 #define FLD_PDF1_SHIFT 0x00000030 #define FLD_FMBYPASS_MODE2 0x00000008 #define FLD_FMBYPASS_MODE1 0x00000004 @@ -899,19 +899,19 @@ /*****************************************************************************/ #define ROT_FREQ_CTL 0x820 -#define FLD_ROT3_PHACC_PROG 0xFFFF0000 -#define FLD_ROT2_PHACC_PROG 0x0000FFFF +#define FLD_ROT3_PHACC_PROG 0xffff0000 +#define FLD_ROT2_PHACC_PROG 0x0000ffff /*****************************************************************************/ #define FM_CTL 0x824 -#define FLD_FM2_DC_FB_SHIFT 0xF0000000 -#define FLD_FM2_DC_INT_SHIFT 0x0F000000 +#define FLD_FM2_DC_FB_SHIFT 0xf0000000 +#define FLD_FM2_DC_INT_SHIFT 0x0f000000 #define FLD_FM2_AFC_RESET 0x00800000 #define FLD_FM2_DC_PASS_IN 0x00400000 #define FLD_FM2_DAGC_SHIFT 0x00380000 #define FLD_FM2_CORDIC_SHIFT 0x00070000 -#define FLD_FM1_DC_FB_SHIFT 0x0000F000 -#define FLD_FM1_DC_INT_SHIFT 0x00000F00 +#define FLD_FM1_DC_FB_SHIFT 0x0000f000 +#define FLD_FM1_DC_INT_SHIFT 0x00000f00 #define FLD_FM1_AFC_RESET 0x00000080 #define FLD_FM1_DC_PASS_IN 0x00000040 #define FLD_FM1_DAGC_SHIFT 0x00000038 @@ -921,29 +921,29 @@ #define LPF_PDF_CTL 0x828 /* Reserved [31:30] */ #define FLD_LPF32_SHIFT1 0x30000000 -#define FLD_LPF32_SHIFT2 0x0C000000 +#define FLD_LPF32_SHIFT2 0x0c000000 #define FLD_LPF160_SHIFTA 0x03000000 -#define FLD_LPF160_SHIFTB 0x00C00000 +#define FLD_LPF160_SHIFTB 0x00c00000 #define FLD_LPF160_SHIFTC 0x00300000 -#define FLD_LPF32_COEF_SEL2 0x000C0000 +#define FLD_LPF32_COEF_SEL2 0x000c0000 #define FLD_LPF32_COEF_SEL1 0x00030000 -#define FLD_LPF160_COEF_SELC 0x0000C000 +#define FLD_LPF160_COEF_SELC 0x0000c000 #define FLD_LPF160_COEF_SELB 0x00003000 -#define FLD_LPF160_COEF_SELA 0x00000C00 +#define FLD_LPF160_COEF_SELA 0x00000c00 #define FLD_LPF160_IN_EN_REG 0x00000300 -#define FLD_PDF4_PDF_SEL 0x000000C0 +#define FLD_PDF4_PDF_SEL 0x000000c0 #define FLD_PDF3_PDF_SEL 0x00000030 -#define FLD_PDF2_PDF_SEL 0x0000000C +#define FLD_PDF2_PDF_SEL 0x0000000c #define FLD_PDF1_PDF_SEL 0x00000003 /*****************************************************************************/ -#define DFT1_CTL1 0x82C -#define FLD_DFT1_DWELL 0xFFFF0000 -#define FLD_DFT1_FREQ 0x0000FFFF +#define DFT1_CTL1 0x82c +#define FLD_DFT1_DWELL 0xffff0000 +#define FLD_DFT1_FREQ 0x0000ffff /*****************************************************************************/ #define DFT1_CTL2 0x830 -#define FLD_DFT1_THRESHOLD 0xFFFFFF00 +#define FLD_DFT1_THRESHOLD 0xffffff00 #define FLD_DFT1_CMP_CTL 0x00000080 #define FLD_DFT1_AVG 0x00000070 /* Reserved [3:1] */ @@ -953,16 +953,16 @@ #define DFT1_STATUS 0x834 #define FLD_DFT1_DONE 0x80000000 #define FLD_DFT1_TH_CMP_STAT 0x40000000 -#define FLD_DFT1_RESULT 0x3FFFFFFF +#define FLD_DFT1_RESULT 0x3fffffff /*****************************************************************************/ #define DFT2_CTL1 0x838 -#define FLD_DFT2_DWELL 0xFFFF0000 -#define FLD_DFT2_FREQ 0x0000FFFF +#define FLD_DFT2_DWELL 0xffff0000 +#define FLD_DFT2_FREQ 0x0000ffff /*****************************************************************************/ #define DFT2_CTL2 0x83C -#define FLD_DFT2_THRESHOLD 0xFFFFFF00 +#define FLD_DFT2_THRESHOLD 0xffffff00 #define FLD_DFT2_CMP_CTL 0x00000080 #define FLD_DFT2_AVG 0x00000070 /* Reserved [3:1] */ @@ -972,35 +972,35 @@ #define DFT2_STATUS 0x840 #define FLD_DFT2_DONE 0x80000000 #define FLD_DFT2_TH_CMP_STAT 0x40000000 -#define FLD_DFT2_RESULT 0x3FFFFFFF +#define FLD_DFT2_RESULT 0x3fffffff /*****************************************************************************/ #define DFT3_CTL1 0x844 -#define FLD_DFT3_DWELL 0xFFFF0000 -#define FLD_DFT3_FREQ 0x0000FFFF +#define FLD_DFT3_DWELL 0xffff0000 +#define FLD_DFT3_FREQ 0x0000ffff /*****************************************************************************/ #define DFT3_CTL2 0x848 -#define FLD_DFT3_THRESHOLD 0xFFFFFF00 +#define FLD_DFT3_THRESHOLD 0xffffff00 #define FLD_DFT3_CMP_CTL 0x00000080 #define FLD_DFT3_AVG 0x00000070 /* Reserved [3:1] */ #define FLD_DFT3_START 0x00000001 /*****************************************************************************/ -#define DFT3_STATUS 0x84C +#define DFT3_STATUS 0x84c #define FLD_DFT3_DONE 0x80000000 #define FLD_DFT3_TH_CMP_STAT 0x40000000 -#define FLD_DFT3_RESULT 0x3FFFFFFF +#define FLD_DFT3_RESULT 0x3fffffff /*****************************************************************************/ #define DFT4_CTL1 0x850 -#define FLD_DFT4_DWELL 0xFFFF0000 -#define FLD_DFT4_FREQ 0x0000FFFF +#define FLD_DFT4_DWELL 0xffff0000 +#define FLD_DFT4_FREQ 0x0000ffff /*****************************************************************************/ #define DFT4_CTL2 0x854 -#define FLD_DFT4_THRESHOLD 0xFFFFFF00 +#define FLD_DFT4_THRESHOLD 0xffffff00 #define FLD_DFT4_CMP_CTL 0x00000080 #define FLD_DFT4_AVG 0x00000070 /* Reserved [3:1] */ @@ -1010,19 +1010,19 @@ #define DFT4_STATUS 0x858 #define FLD_DFT4_DONE 0x80000000 #define FLD_DFT4_TH_CMP_STAT 0x40000000 -#define FLD_DFT4_RESULT 0x3FFFFFFF +#define FLD_DFT4_RESULT 0x3fffffff /*****************************************************************************/ -#define AM_MTS_DET 0x85C +#define AM_MTS_DET 0x85c #define FLD_AM_MTS_MODE 0x80000000 /* Reserved [30:26] */ #define FLD_AM_SUB 0x02000000 #define FLD_AM_GAIN_EN 0x01000000 /* Reserved [23:16] */ -#define FLD_AMMTS_GAIN_SCALE 0x0000E000 +#define FLD_AMMTS_GAIN_SCALE 0x0000e000 #define FLD_MTS_PDF_SHIFT 0x00001800 #define FLD_AM_REG_GAIN 0x00000700 -#define FLD_AGC_REF 0x000000FF +#define FLD_AGC_REF 0x000000ff /*****************************************************************************/ #define ANALOG_MUX_CTL 0x860 @@ -1044,9 +1044,9 @@ #define FLD_MUX7_SEL 0x00000800 #define FLD_MUX6_SEL 0x00000600 #define FLD_MUX5_SEL 0x00000100 -#define FLD_MUX4_SEL 0x000000C0 +#define FLD_MUX4_SEL 0x000000c0 #define FLD_MUX3_SEL 0x00000030 -#define FLD_MUX2_SEL 0x0000000C +#define FLD_MUX2_SEL 0x0000000c #define FLD_MUX1_SEL 0x00000003 /*****************************************************************************/ @@ -1057,48 +1057,48 @@ #define FLD_PLL_STATUS 0x07000000 #define FLD_BANDWIDTH_SELECT 0x00030000 #define FLD_PLL_SHIFT_REG 0x00007000 -#define FLD_PHASE_SHIFT 0x000007FF +#define FLD_PHASE_SHIFT 0x000007ff /*****************************************************************************/ /* Cx231xx redefine */ #define DPLL_CTRL2 0x868 #define DIG_PLL_CTL2 0x868 -#define FLD_PLL_UNLOCK_THR 0xFF000000 -#define FLD_PLL_LOCK_THR 0x00FF0000 +#define FLD_PLL_UNLOCK_THR 0xff000000 +#define FLD_PLL_LOCK_THR 0x00ff0000 /* Reserved [15:8] */ -#define FLD_AM_PDF_SEL2 0x000000C0 +#define FLD_AM_PDF_SEL2 0x000000c0 #define FLD_AM_PDF_SEL1 0x00000030 -#define FLD_DPLL_FSM_CTRL 0x0000000C +#define FLD_DPLL_FSM_CTRL 0x0000000c /* Reserved [1] */ #define FLD_PLL_PILOT_DET 0x00000001 /*****************************************************************************/ /* Cx231xx redefine */ -#define DPLL_CTRL3 0x86C -#define DIG_PLL_CTL3 0x86C +#define DPLL_CTRL3 0x86c +#define DIG_PLL_CTL3 0x86c #define FLD_DISABLE_LOOP 0x01000000 -#define FLD_A1_DS1_SEL 0x000C0000 +#define FLD_A1_DS1_SEL 0x000c0000 #define FLD_A1_DS2_SEL 0x00030000 -#define FLD_A1_KI 0x0000FF00 -#define FLD_A1_KD 0x000000FF +#define FLD_A1_KI 0x0000ff00 +#define FLD_A1_KD 0x000000ff /*****************************************************************************/ /* Cx231xx redefine */ #define DPLL_CTRL4 0x870 #define DIG_PLL_CTL4 0x870 -#define FLD_A2_DS1_SEL 0x000C0000 +#define FLD_A2_DS1_SEL 0x000c0000 #define FLD_A2_DS2_SEL 0x00030000 -#define FLD_A2_KI 0x0000FF00 -#define FLD_A2_KD 0x000000FF +#define FLD_A2_KI 0x0000ff00 +#define FLD_A2_KD 0x000000ff /*****************************************************************************/ /* Cx231xx redefine */ #define DPLL_CTRL5 0x874 #define DIG_PLL_CTL5 0x874 -#define FLD_TRK_DS1_SEL 0x000C0000 +#define FLD_TRK_DS1_SEL 0x000c0000 #define FLD_TRK_DS2_SEL 0x00030000 -#define FLD_TRK_KI 0x0000FF00 -#define FLD_TRK_KD 0x000000FF +#define FLD_TRK_KI 0x0000ff00 +#define FLD_TRK_KD 0x000000ff /*****************************************************************************/ #define DEEMPH_GAIN_CTL 0x878 @@ -1107,10 +1107,10 @@ /*****************************************************************************/ /* Cx231xx redefine */ -#define DEEMPH_COEFF1 0x87C -#define DEEMPH_COEF1 0x87C -#define FLD_DEEMPH_B0 0xFFFF0000 -#define FLD_DEEMPH_A0 0x0000FFFF +#define DEEMPH_COEFF1 0x87c +#define DEEMPH_COEF1 0x87c +#define FLD_DEEMPH_B0 0xffff0000 +#define FLD_DEEMPH_A0 0x0000ffff /*****************************************************************************/ /* Cx231xx redefine */ @@ -1121,281 +1121,281 @@ /*****************************************************************************/ #define DBX1_CTL1 0x884 -#define FLD_DBX1_WBE_GAIN 0xFFFF0000 -#define FLD_DBX1_IN_GAIN 0x0000FFFF +#define FLD_DBX1_WBE_GAIN 0xffff0000 +#define FLD_DBX1_IN_GAIN 0x0000ffff /*****************************************************************************/ #define DBX1_CTL2 0x888 -#define FLD_DBX1_SE_BYPASS 0xFFFF0000 -#define FLD_DBX1_SE_GAIN 0x0000FFFF +#define FLD_DBX1_SE_BYPASS 0xffff0000 +#define FLD_DBX1_SE_GAIN 0x0000ffff /*****************************************************************************/ #define DBX1_RMS_SE 0x88C -#define FLD_DBX1_RMS_WBE 0xFFFF0000 -#define FLD_DBX1_RMS_SE_FLD 0x0000FFFF +#define FLD_DBX1_RMS_WBE 0xffff0000 +#define FLD_DBX1_RMS_SE_FLD 0x0000ffff /*****************************************************************************/ #define DBX2_CTL1 0x890 -#define FLD_DBX2_WBE_GAIN 0xFFFF0000 -#define FLD_DBX2_IN_GAIN 0x0000FFFF +#define FLD_DBX2_WBE_GAIN 0xffff0000 +#define FLD_DBX2_IN_GAIN 0x0000ffff /*****************************************************************************/ #define DBX2_CTL2 0x894 -#define FLD_DBX2_SE_BYPASS 0xFFFF0000 -#define FLD_DBX2_SE_GAIN 0x0000FFFF +#define FLD_DBX2_SE_BYPASS 0xffff0000 +#define FLD_DBX2_SE_GAIN 0x0000ffff /*****************************************************************************/ #define DBX2_RMS_SE 0x898 -#define FLD_DBX2_RMS_WBE 0xFFFF0000 -#define FLD_DBX2_RMS_SE_FLD 0x0000FFFF +#define FLD_DBX2_RMS_WBE 0xffff0000 +#define FLD_DBX2_RMS_SE_FLD 0x0000ffff /*****************************************************************************/ -#define AM_FM_DIFF 0x89C +#define AM_FM_DIFF 0x89c /* Reserved [31] */ -#define FLD_FM_DIFF_OUT 0x7FFF0000 +#define FLD_FM_DIFF_OUT 0x7fff0000 /* Reserved [15] */ -#define FLD_AM_DIFF_OUT 0x00007FFF +#define FLD_AM_DIFF_OUT 0x00007fff /*****************************************************************************/ -#define NICAM_FAW 0x8A0 -#define FLD_FAWDETWINEND 0xFC000000 -#define FLD_FAWDETWINSTR 0x03FF0000 +#define NICAM_FAW 0x8a0 +#define FLD_FAWDETWINEND 0xFc000000 +#define FLD_FAWDETWINSTR 0x03ff0000 /* Reserved [15:12] */ -#define FLD_FAWDETTHRSHLD3 0x00000F00 -#define FLD_FAWDETTHRSHLD2 0x000000F0 -#define FLD_FAWDETTHRSHLD1 0x0000000F +#define FLD_FAWDETTHRSHLD3 0x00000f00 +#define FLD_FAWDETTHRSHLD2 0x000000f0 +#define FLD_FAWDETTHRSHLD1 0x0000000f /*****************************************************************************/ /* Cx231xx redefine */ -#define DEEMPH_GAIN 0x8A4 -#define NICAM_DEEMPHGAIN 0x8A4 +#define DEEMPH_GAIN 0x8a4 +#define NICAM_DEEMPHGAIN 0x8a4 /* Reserved [31:18] */ -#define FLD_DEEMPHGAIN 0x0003FFFF +#define FLD_DEEMPHGAIN 0x0003ffff /*****************************************************************************/ /* Cx231xx redefine */ -#define DEEMPH_NUMER1 0x8A8 -#define NICAM_DEEMPHNUMER1 0x8A8 +#define DEEMPH_NUMER1 0x8a8 +#define NICAM_DEEMPHNUMER1 0x8a8 /* Reserved [31:18] */ -#define FLD_DEEMPHNUMER1 0x0003FFFF +#define FLD_DEEMPHNUMER1 0x0003ffff /*****************************************************************************/ /* Cx231xx redefine */ -#define DEEMPH_NUMER2 0x8AC -#define NICAM_DEEMPHNUMER2 0x8AC +#define DEEMPH_NUMER2 0x8ac +#define NICAM_DEEMPHNUMER2 0x8ac /* Reserved [31:18] */ -#define FLD_DEEMPHNUMER2 0x0003FFFF +#define FLD_DEEMPHNUMER2 0x0003ffff /*****************************************************************************/ /* Cx231xx redefine */ -#define DEEMPH_DENOM1 0x8B0 -#define NICAM_DEEMPHDENOM1 0x8B0 +#define DEEMPH_DENOM1 0x8b0 +#define NICAM_DEEMPHDENOM1 0x8b0 /* Reserved [31:18] */ -#define FLD_DEEMPHDENOM1 0x0003FFFF +#define FLD_DEEMPHDENOM1 0x0003ffff /*****************************************************************************/ /* Cx231xx redefine */ -#define DEEMPH_DENOM2 0x8B4 -#define NICAM_DEEMPHDENOM2 0x8B4 +#define DEEMPH_DENOM2 0x8b4 +#define NICAM_DEEMPHDENOM2 0x8b4 /* Reserved [31:18] */ -#define FLD_DEEMPHDENOM2 0x0003FFFF +#define FLD_DEEMPHDENOM2 0x0003ffff /*****************************************************************************/ #define NICAM_ERRLOG_CTL1 0x8B8 /* Reserved [31:28] */ -#define FLD_ERRINTRPTTHSHLD1 0x0FFF0000 +#define FLD_ERRINTRPTTHSHLD1 0x0fff0000 /* Reserved [15:12] */ -#define FLD_ERRLOGPERIOD 0x00000FFF +#define FLD_ERRLOGPERIOD 0x00000fff /*****************************************************************************/ -#define NICAM_ERRLOG_CTL2 0x8BC +#define NICAM_ERRLOG_CTL2 0x8bc /* Reserved [31:28] */ -#define FLD_ERRINTRPTTHSHLD3 0x0FFF0000 +#define FLD_ERRINTRPTTHSHLD3 0x0fff0000 /* Reserved [15:12] */ -#define FLD_ERRINTRPTTHSHLD2 0x00000FFF +#define FLD_ERRINTRPTTHSHLD2 0x00000fff /*****************************************************************************/ -#define NICAM_ERRLOG_STS1 0x8C0 +#define NICAM_ERRLOG_STS1 0x8c0 /* Reserved [31:28] */ -#define FLD_ERRLOG2 0x0FFF0000 +#define FLD_ERRLOG2 0x0fff0000 /* Reserved [15:12] */ -#define FLD_ERRLOG1 0x00000FFF +#define FLD_ERRLOG1 0x00000fff /*****************************************************************************/ -#define NICAM_ERRLOG_STS2 0x8C4 +#define NICAM_ERRLOG_STS2 0x8c4 /* Reserved [31:12] */ -#define FLD_ERRLOG3 0x00000FFF +#define FLD_ERRLOG3 0x00000fff /*****************************************************************************/ -#define NICAM_STATUS 0x8C8 +#define NICAM_STATUS 0x8c8 /* Reserved [31:20] */ -#define FLD_NICAM_CIB 0x000C0000 +#define FLD_NICAM_CIB 0x000c0000 #define FLD_NICAM_LOCK_STAT 0x00020000 #define FLD_NICAM_MUTE 0x00010000 -#define FLD_NICAMADDIT_DATA 0x0000FFE0 -#define FLD_NICAMCNTRL 0x0000001F +#define FLD_NICAMADDIT_DATA 0x0000ffe0 +#define FLD_NICAMCNTRL 0x0000001f /*****************************************************************************/ -#define DEMATRIX_CTL 0x8CC -#define FLD_AC97_IN_SHIFT 0xF0000000 -#define FLD_I2S_IN_SHIFT 0x0F000000 -#define FLD_DEMATRIX_SEL_CTL 0x00FF0000 +#define DEMATRIX_CTL 0x8cc +#define FLD_AC97_IN_SHIFT 0xf0000000 +#define FLD_I2S_IN_SHIFT 0x0f000000 +#define FLD_DEMATRIX_SEL_CTL 0x00ff0000 /* Reserved [15:11] */ #define FLD_DMTRX_BYPASS 0x00000400 #define FLD_DEMATRIX_MODE 0x00000300 /* Reserved [7:6] */ #define FLD_PH_DBX_SEL 0x00000020 #define FLD_PH_CH_SEL 0x00000010 -#define FLD_PHASE_FIX 0x0000000F +#define FLD_PHASE_FIX 0x0000000f /*****************************************************************************/ -#define PATH1_CTL1 0x8D0 +#define PATH1_CTL1 0x8d0 /* Reserved [31:29] */ -#define FLD_PATH1_MUTE_CTL 0x1F000000 +#define FLD_PATH1_MUTE_CTL 0x1f000000 /* Reserved [23:22] */ #define FLD_PATH1_AVC_CG 0x00300000 -#define FLD_PATH1_AVC_RT 0x000F0000 -#define FLD_PATH1_AVC_AT 0x0000F000 +#define FLD_PATH1_AVC_RT 0x000f0000 +#define FLD_PATH1_AVC_AT 0x0000f000 #define FLD_PATH1_AVC_STEREO 0x00000800 #define FLD_PATH1_AVC_CR 0x00000700 -#define FLD_PATH1_AVC_RMS_CON 0x000000F0 -#define FLD_PATH1_SEL_CTL 0x0000000F +#define FLD_PATH1_AVC_RMS_CON 0x000000f0 +#define FLD_PATH1_SEL_CTL 0x0000000f /*****************************************************************************/ -#define PATH1_VOL_CTL 0x8D4 -#define FLD_PATH1_AVC_THRESHOLD 0x7FFF0000 +#define PATH1_VOL_CTL 0x8d4 +#define FLD_PATH1_AVC_THRESHOLD 0x7fff0000 #define FLD_PATH1_BAL_LEFT 0x00008000 -#define FLD_PATH1_BAL_LEVEL 0x00007F00 -#define FLD_PATH1_VOLUME 0x000000FF +#define FLD_PATH1_BAL_LEVEL 0x00007f00 +#define FLD_PATH1_VOLUME 0x000000ff /*****************************************************************************/ -#define PATH1_EQ_CTL 0x8D8 +#define PATH1_EQ_CTL 0x8d8 /* Reserved [31:30] */ -#define FLD_PATH1_EQ_TREBLE_VOL 0x3F000000 +#define FLD_PATH1_EQ_TREBLE_VOL 0x3f000000 /* Reserved [23:22] */ -#define FLD_PATH1_EQ_MID_VOL 0x003F0000 +#define FLD_PATH1_EQ_MID_VOL 0x003f0000 /* Reserved [15:14] */ -#define FLD_PATH1_EQ_BASS_VOL 0x00003F00 +#define FLD_PATH1_EQ_BASS_VOL 0x00003f00 /* Reserved [7:1] */ #define FLD_PATH1_EQ_BAND_SEL 0x00000001 /*****************************************************************************/ -#define PATH1_SC_CTL 0x8DC -#define FLD_PATH1_SC_THRESHOLD 0x7FFF0000 -#define FLD_PATH1_SC_RT 0x0000F000 -#define FLD_PATH1_SC_AT 0x00000F00 +#define PATH1_SC_CTL 0x8dc +#define FLD_PATH1_SC_THRESHOLD 0x7fff0000 +#define FLD_PATH1_SC_RT 0x0000f000 +#define FLD_PATH1_SC_AT 0x00000f00 #define FLD_PATH1_SC_STEREO 0x00000080 #define FLD_PATH1_SC_CR 0x00000070 -#define FLD_PATH1_SC_RMS_CON 0x0000000F +#define FLD_PATH1_SC_RMS_CON 0x0000000f /*****************************************************************************/ -#define PATH2_CTL1 0x8E0 +#define PATH2_CTL1 0x8e0 /* Reserved [31:26] */ #define FLD_PATH2_MUTE_CTL 0x03000000 /* Reserved [23:22] */ #define FLD_PATH2_AVC_CG 0x00300000 -#define FLD_PATH2_AVC_RT 0x000F0000 -#define FLD_PATH2_AVC_AT 0x0000F000 +#define FLD_PATH2_AVC_RT 0x000f0000 +#define FLD_PATH2_AVC_AT 0x0000f000 #define FLD_PATH2_AVC_STEREO 0x00000800 #define FLD_PATH2_AVC_CR 0x00000700 -#define FLD_PATH2_AVC_RMS_CON 0x000000F0 -#define FLD_PATH2_SEL_CTL 0x0000000F +#define FLD_PATH2_AVC_RMS_CON 0x000000f0 +#define FLD_PATH2_SEL_CTL 0x0000000f /*****************************************************************************/ -#define PATH2_VOL_CTL 0x8E4 -#define FLD_PATH2_AVC_THRESHOLD 0xFFFF0000 +#define PATH2_VOL_CTL 0x8e4 +#define FLD_PATH2_AVC_THRESHOLD 0xffff0000 #define FLD_PATH2_BAL_LEFT 0x00008000 -#define FLD_PATH2_BAL_LEVEL 0x00007F00 -#define FLD_PATH2_VOLUME 0x000000FF +#define FLD_PATH2_BAL_LEVEL 0x00007f00 +#define FLD_PATH2_VOLUME 0x000000ff /*****************************************************************************/ -#define PATH2_EQ_CTL 0x8E8 +#define PATH2_EQ_CTL 0x8e8 /* Reserved [31:30] */ -#define FLD_PATH2_EQ_TREBLE_VOL 0x3F000000 +#define FLD_PATH2_EQ_TREBLE_VOL 0x3f000000 /* Reserved [23:22] */ -#define FLD_PATH2_EQ_MID_VOL 0x003F0000 +#define FLD_PATH2_EQ_MID_VOL 0x003f0000 /* Reserved [15:14] */ -#define FLD_PATH2_EQ_BASS_VOL 0x00003F00 +#define FLD_PATH2_EQ_BASS_VOL 0x00003f00 /* Reserved [7:1] */ #define FLD_PATH2_EQ_BAND_SEL 0x00000001 /*****************************************************************************/ -#define PATH2_SC_CTL 0x8EC -#define FLD_PATH2_SC_THRESHOLD 0xFFFF0000 -#define FLD_PATH2_SC_RT 0x0000F000 -#define FLD_PATH2_SC_AT 0x00000F00 +#define PATH2_SC_CTL 0x8eC +#define FLD_PATH2_SC_THRESHOLD 0xffff0000 +#define FLD_PATH2_SC_RT 0x0000f000 +#define FLD_PATH2_SC_AT 0x00000f00 #define FLD_PATH2_SC_STEREO 0x00000080 #define FLD_PATH2_SC_CR 0x00000070 -#define FLD_PATH2_SC_RMS_CON 0x0000000F +#define FLD_PATH2_SC_RMS_CON 0x0000000f /*****************************************************************************/ -#define SRC_CTL 0x8F0 -#define FLD_SRC_STATUS 0xFFFFFF00 -#define FLD_FIFO_LF_EN 0x000000FC +#define SRC_CTL 0x8f0 +#define FLD_SRC_STATUS 0xffffff00 +#define FLD_FIFO_LF_EN 0x000000fc #define FLD_BYPASS_LI 0x00000002 #define FLD_BYPASS_PF 0x00000001 /*****************************************************************************/ -#define SRC_LF_COEF 0x8F4 -#define FLD_LOOP_FILTER_COEF2 0xFFFF0000 -#define FLD_LOOP_FILTER_COEF1 0x0000FFFF +#define SRC_LF_COEF 0x8f4 +#define FLD_LOOP_FILTER_COEF2 0xffff0000 +#define FLD_LOOP_FILTER_COEF1 0x0000ffff /*****************************************************************************/ -#define SRC1_CTL 0x8F8 +#define SRC1_CTL 0x8f8 /* Reserved [31:28] */ -#define FLD_SRC1_FIFO_RD_TH 0x0F000000 +#define FLD_SRC1_FIFO_RD_TH 0x0f000000 /* Reserved [23:18] */ -#define FLD_SRC1_PHASE_INC 0x0003FFFF +#define FLD_SRC1_PHASE_INC 0x0003ffff /*****************************************************************************/ -#define SRC2_CTL 0x8FC +#define SRC2_CTL 0x8fc /* Reserved [31:28] */ -#define FLD_SRC2_FIFO_RD_TH 0x0F000000 +#define FLD_SRC2_FIFO_RD_TH 0x0f000000 /* Reserved [23:18] */ -#define FLD_SRC2_PHASE_INC 0x0003FFFF +#define FLD_SRC2_PHASE_INC 0x0003ffff /*****************************************************************************/ #define SRC3_CTL 0x900 /* Reserved [31:28] */ -#define FLD_SRC3_FIFO_RD_TH 0x0F000000 +#define FLD_SRC3_FIFO_RD_TH 0x0f000000 /* Reserved [23:18] */ -#define FLD_SRC3_PHASE_INC 0x0003FFFF +#define FLD_SRC3_PHASE_INC 0x0003ffff /*****************************************************************************/ #define SRC4_CTL 0x904 /* Reserved [31:28] */ -#define FLD_SRC4_FIFO_RD_TH 0x0F000000 +#define FLD_SRC4_FIFO_RD_TH 0x0f000000 /* Reserved [23:18] */ -#define FLD_SRC4_PHASE_INC 0x0003FFFF +#define FLD_SRC4_PHASE_INC 0x0003ffff /*****************************************************************************/ #define SRC5_CTL 0x908 /* Reserved [31:28] */ -#define FLD_SRC5_FIFO_RD_TH 0x0F000000 +#define FLD_SRC5_FIFO_RD_TH 0x0f000000 /* Reserved [23:18] */ -#define FLD_SRC5_PHASE_INC 0x0003FFFF +#define FLD_SRC5_PHASE_INC 0x0003ffff /*****************************************************************************/ -#define SRC6_CTL 0x90C +#define SRC6_CTL 0x90c /* Reserved [31:28] */ -#define FLD_SRC6_FIFO_RD_TH 0x0F000000 +#define FLD_SRC6_FIFO_RD_TH 0x0f000000 /* Reserved [23:18] */ -#define FLD_SRC6_PHASE_INC 0x0003FFFF +#define FLD_SRC6_PHASE_INC 0x0003ffff /*****************************************************************************/ #define BAND_OUT_SEL 0x910 -#define FLD_SRC6_IN_SEL 0xC0000000 +#define FLD_SRC6_IN_SEL 0xc0000000 #define FLD_SRC6_CLK_SEL 0x30000000 -#define FLD_SRC5_IN_SEL 0x0C000000 +#define FLD_SRC5_IN_SEL 0x0c000000 #define FLD_SRC5_CLK_SEL 0x03000000 -#define FLD_SRC4_IN_SEL 0x00C00000 +#define FLD_SRC4_IN_SEL 0x00c00000 #define FLD_SRC4_CLK_SEL 0x00300000 -#define FLD_SRC3_IN_SEL 0x000C0000 +#define FLD_SRC3_IN_SEL 0x000c0000 #define FLD_SRC3_CLK_SEL 0x00030000 -#define FLD_BASEBAND_BYPASS_CTL 0x0000FF00 -#define FLD_AC97_SRC_SEL 0x000000C0 +#define FLD_BASEBAND_BYPASS_CTL 0x0000ff00 +#define FLD_AC97_SRC_SEL 0x000000c0 #define FLD_I2S_SRC_SEL 0x00000030 -#define FLD_PARALLEL2_SRC_SEL 0x0000000C +#define FLD_PARALLEL2_SRC_SEL 0x0000000c #define FLD_PARALLEL1_SRC_SEL 0x00000003 /*****************************************************************************/ @@ -1407,7 +1407,7 @@ #define FLD_I2S_IN_SONY_MODE 0x00000080 #define FLD_I2S_IN_RIGHT_JUST 0x00000040 #define FLD_I2S_IN_WS_SEL 0x00000020 -#define FLD_I2S_IN_BCN_DEL 0x0000001F +#define FLD_I2S_IN_BCN_DEL 0x0000001f /*****************************************************************************/ #define I2S_OUT_CTL 0x918 @@ -1418,10 +1418,10 @@ #define FLD_I2S_OUT_SONY_MODE 0x00000080 #define FLD_I2S_OUT_RIGHT_JUST 0x00000040 #define FLD_I2S_OUT_WS_SEL 0x00000020 -#define FLD_I2S_OUT_BCN_DEL 0x0000001F +#define FLD_I2S_OUT_BCN_DEL 0x0000001f /*****************************************************************************/ -#define AC97_CTL 0x91C +#define AC97_CTL 0x91c /* Reserved [31:26] */ #define FLD_AC97_UP2X_BW20K 0x02000000 #define FLD_AC97_UP2X_BYPASS 0x01000000 @@ -1433,20 +1433,20 @@ #define FLD_AC97_SHUTDOWN 0x00000001 /* Cx231xx redefine */ -#define QPSK_IAGC_CTL1 0x94c -#define QPSK_IAGC_CTL2 0x950 -#define QPSK_FEPR_FREQ 0x954 -#define QPSK_BTL_CTL1 0x958 -#define QPSK_BTL_CTL2 0x95c -#define QPSK_CTL_CTL1 0x960 -#define QPSK_CTL_CTL2 0x964 -#define QPSK_MF_FAGC_CTL 0x968 -#define QPSK_EQ_CTL 0x96c -#define QPSK_LOCK_CTL 0x970 - -/*****************************************************************************/ -#define FM1_DFT_CTL 0x9A8 -#define FLD_FM1_DFT_THRESHOLD 0xFFFF0000 +#define QPSK_IAGC_CTL1 0x94c +#define QPSK_IAGC_CTL2 0x950 +#define QPSK_FEPR_FREQ 0x954 +#define QPSK_BTL_CTL1 0x958 +#define QPSK_BTL_CTL2 0x95c +#define QPSK_CTL_CTL1 0x960 +#define QPSK_CTL_CTL2 0x964 +#define QPSK_MF_FAGC_CTL 0x968 +#define QPSK_EQ_CTL 0x96c +#define QPSK_LOCK_CTL 0x970 + +/*****************************************************************************/ +#define FM1_DFT_CTL 0x9a8 +#define FLD_FM1_DFT_THRESHOLD 0xffff0000 /* Reserved [15:8] */ #define FLD_FM1_DFT_CMP_CTL 0x00000080 #define FLD_FM1_DFT_AVG 0x00000070 @@ -1454,15 +1454,15 @@ #define FLD_FM1_DFT_START 0x00000001 /*****************************************************************************/ -#define FM1_DFT_STATUS 0x9AC +#define FM1_DFT_STATUS 0x9ac #define FLD_FM1_DFT_DONE 0x80000000 /* Reserved [30:19] */ #define FLD_FM_DFT_TH_CMP 0x00040000 -#define FLD_FM1_DFT 0x0003FFFF +#define FLD_FM1_DFT 0x0003ffff /*****************************************************************************/ -#define FM2_DFT_CTL 0x9B0 -#define FLD_FM2_DFT_THRESHOLD 0xFFFF0000 +#define FM2_DFT_CTL 0x9b0 +#define FLD_FM2_DFT_THRESHOLD 0xffff0000 /* Reserved [15:8] */ #define FLD_FM2_DFT_CMP_CTL 0x00000080 #define FLD_FM2_DFT_AVG 0x00000070 @@ -1470,52 +1470,52 @@ #define FLD_FM2_DFT_START 0x00000001 /*****************************************************************************/ -#define FM2_DFT_STATUS 0x9B4 +#define FM2_DFT_STATUS 0x9b4 #define FLD_FM2_DFT_DONE 0x80000000 /* Reserved [30:19] */ #define FLD_FM2_DFT_TH_CMP_STAT 0x00040000 -#define FLD_FM2_DFT 0x0003FFFF +#define FLD_FM2_DFT 0x0003ffff /*****************************************************************************/ /* Cx231xx redefine */ -#define AAGC_STATUS_REG 0x9B8 -#define AAGC_STATUS 0x9B8 +#define AAGC_STATUS_REG 0x9b8 +#define AAGC_STATUS 0x9b8 /* Reserved [31:27] */ #define FLD_FM2_DAGC_OUT 0x07000000 /* Reserved [23:19] */ #define FLD_FM1_DAGC_OUT 0x00070000 /* Reserved [15:6] */ -#define FLD_AFE_VGA_OUT 0x0000003F +#define FLD_AFE_VGA_OUT 0x0000003f /*****************************************************************************/ -#define MTS_GAIN_STATUS 0x9BC +#define MTS_GAIN_STATUS 0x9bc /* Reserved [31:14] */ -#define FLD_MTS_GAIN 0x00003FFF +#define FLD_MTS_GAIN 0x00003fff -#define RDS_OUT 0x9C0 -#define FLD_RDS_Q 0xFFFF0000 -#define FLD_RDS_I 0x0000FFFF +#define RDS_OUT 0x9c0 +#define FLD_RDS_Q 0xffff0000 +#define FLD_RDS_I 0x0000ffff /*****************************************************************************/ -#define AUTOCONFIG_REG 0x9C4 +#define AUTOCONFIG_REG 0x9c4 /* Reserved [31:4] */ -#define FLD_AUTOCONFIG_MODE 0x0000000F +#define FLD_AUTOCONFIG_MODE 0x0000000f -#define FM_AFC 0x9C8 -#define FLD_FM2_AFC 0xFFFF0000 -#define FLD_FM1_AFC 0x0000FFFF +#define FM_AFC 0x9c8 +#define FLD_FM2_AFC 0xffff0000 +#define FLD_FM1_AFC 0x0000ffff /*****************************************************************************/ /* Cx231xx redefine */ -#define NEW_SPARE 0x9CC -#define NEW_SPARE_REG 0x9CC +#define NEW_SPARE 0x9cc +#define NEW_SPARE_REG 0x9cc /*****************************************************************************/ -#define DBX_ADJ 0x9D0 +#define DBX_ADJ 0x9d0 /* Reserved [31:28] */ -#define FLD_DBX2_ADJ 0x0FFF0000 +#define FLD_DBX2_ADJ 0x0fff0000 /* Reserved [15:12] */ -#define FLD_DBX1_ADJ 0x00000FFF +#define FLD_DBX1_ADJ 0x00000fff #define VID_FMT_AUTO 0 #define VID_FMT_NTSC_M 1 @@ -1529,18 +1529,18 @@ #define VID_FMT_SECAM 12 #define VID_FMT_SECAM_60 13 -#define INPUT_MODE_CVBS_0 0 /* INPUT_MODE_VALUE(0) */ -#define INPUT_MODE_YC_1 1 /* INPUT_MODE_VALUE(1) */ -#define INPUT_MODE_YC2_2 2 /* INPUT_MODE_VALUE(2) */ -#define INPUT_MODE_YUV_3 3 /* INPUT_MODE_VALUE(3) */ +#define INPUT_MODE_CVBS_0 0 /* INPUT_MODE_VALUE(0) */ +#define INPUT_MODE_YC_1 1 /* INPUT_MODE_VALUE(1) */ +#define INPUT_MODE_YC2_2 2 /* INPUT_MODE_VALUE(2) */ +#define INPUT_MODE_YUV_3 3 /* INPUT_MODE_VALUE(3) */ -#define LUMA_LPF_LOW_BANDPASS 0 /* 0.6Mhz LPF BW */ -#define LUMA_LPF_MEDIUM_BANDPASS 1 /* 1.0Mhz LPF BW */ -#define LUMA_LPF_HIGH_BANDPASS 2 /* 1.5Mhz LPF BW */ +#define LUMA_LPF_LOW_BANDPASS 0 /* 0.6Mhz LPF BW */ +#define LUMA_LPF_MEDIUM_BANDPASS 1 /* 1.0Mhz LPF BW */ +#define LUMA_LPF_HIGH_BANDPASS 2 /* 1.5Mhz LPF BW */ -#define UV_LPF_LOW_BANDPASS 0 /* 0.6Mhz LPF BW */ -#define UV_LPF_MEDIUM_BANDPASS 1 /* 1.0Mhz LPF BW */ -#define UV_LPF_HIGH_BANDPASS 2 /* 1.5Mhz LPF BW */ +#define UV_LPF_LOW_BANDPASS 0 /* 0.6Mhz LPF BW */ +#define UV_LPF_MEDIUM_BANDPASS 1 /* 1.0Mhz LPF BW */ +#define UV_LPF_HIGH_BANDPASS 2 /* 1.5Mhz LPF BW */ #define TWO_TAP_FILT 0 #define THREE_TAP_FILT 1 @@ -1557,8 +1557,8 @@ #define OUT_MODE_VIP11 2 #define OUT_MODE_VIP20 3 -#define PHASE_INC_49MHZ 0x0DF22 -#define PHASE_INC_56MHZ 0x0FA5B +#define PHASE_INC_49MHZ 0x0df22 +#define PHASE_INC_56MHZ 0x0fa5b #define PHASE_INC_28MHZ 0x010000 #endif diff --git a/linux/drivers/media/video/cx231xx/cx231xx-video.c b/linux/drivers/media/video/cx231xx/cx231xx-video.c index 3cf1f23ff..2dbe65b83 100644 --- a/linux/drivers/media/video/cx231xx/cx231xx-video.c +++ b/linux/drivers/media/video/cx231xx/cx231xx-video.c @@ -1653,10 +1653,12 @@ static int vidioc_querycap(struct file *file, void *priv, cap->capabilities = V4L2_CAP_VBI_CAPTURE | #if 0 /* Keep */ - V4L2_CAP_SLICED_VBI_CAPTURE | + V4L2_CAP_SLICED_VBI_CAPTURE | #endif - V4L2_CAP_VIDEO_CAPTURE | - V4L2_CAP_AUDIO | V4L2_CAP_READWRITE | V4L2_CAP_STREAMING; + V4L2_CAP_VIDEO_CAPTURE | + V4L2_CAP_AUDIO | + V4L2_CAP_READWRITE | + V4L2_CAP_STREAMING; if (dev->tuner_type != TUNER_ABSENT) cap->capabilities |= V4L2_CAP_TUNER; diff --git a/linux/drivers/media/video/cx231xx/cx231xx.h b/linux/drivers/media/video/cx231xx/cx231xx.h index 0783fb2c3..4606f27b4 100644 --- a/linux/drivers/media/video/cx231xx/cx231xx.h +++ b/linux/drivers/media/video/cx231xx/cx231xx.h @@ -36,7 +36,7 @@ #endif #include "cx231xx-reg.h" -#include "cx231xx-pcb-config.h" +#include "cx231xx-pcb-cfg.h" #include "cx231xx-conf-reg.h" #define CX231XX_VERSION_CODE KERNEL_VERSION(0, 1, 0) @@ -399,7 +399,7 @@ struct cx231xx_i2c_xfer_data { u8 *p_buffer; /* pointer to the buffer */ }; -struct VENDOR_REQUEST_IN{ +struct VENDOR_REQUEST_IN { u8 bRequest; u16 wValue; u16 wIndex; @@ -417,7 +417,7 @@ struct cx231xx_ctrl { u32 shift; }; -enum TRANSFER_TYPE{ +enum TRANSFER_TYPE { Raw_Video = 0, Audio, Vbi, /* VANC */ @@ -591,12 +591,14 @@ int cx231xx_colibri_init_channels(struct cx231xx *dev); int cx231xx_colibri_setup_AFE_for_baseband(struct cx231xx *dev); int cx231xx_colibri_set_input_mux(struct cx231xx *dev, u32 input_mux); int cx231xx_colibri_set_mode(struct cx231xx *dev, enum AFE_MODE mode); -int cx231xx_colibri_update_power_control(struct cx231xx *dev, AV_MODE avmode); +int cx231xx_colibri_update_power_control(struct cx231xx *dev, + enum AV_MODE avmode); int cx231xx_colibri_adjust_ref_count(struct cx231xx *dev, u32 video_input); /* flatiron related functions */ int cx231xx_flatiron_initialize(struct cx231xx *dev); -int cx231xx_flatiron_update_power_control(struct cx231xx *dev, AV_MODE avmode); +int cx231xx_flatiron_update_power_control(struct cx231xx *dev, + enum AV_MODE avmode); int cx231xx_flatiron_set_audio_input(struct cx231xx *dev, u8 audio_input); /* DIF related functions */ @@ -702,7 +704,7 @@ int cx231xx_stop_stream(struct cx231xx *dev, u32 ep_mask); int cx231xx_initialize_stream_xfer(struct cx231xx *dev, u32 media_type); /* Power control functions */ -int cx231xx_set_power_mode(struct cx231xx *dev, AV_MODE mode); +int cx231xx_set_power_mode(struct cx231xx *dev, enum AV_MODE mode); int cx231xx_power_suspend(struct cx231xx *dev); /* chip specific control functions */ -- cgit v1.2.3 From a5efdf6be9cdb58a3990d6981228bc2abcc53619 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Wed, 11 Mar 2009 00:45:44 -0400 Subject: lgdt3305: add email address to MODULE_AUTHOR From: Michael Krufky Priority: normal Signed-off-by: Michael Krufky --- linux/drivers/media/dvb/frontends/lgdt3305.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/frontends/lgdt3305.c b/linux/drivers/media/dvb/frontends/lgdt3305.c index aeb34e924..780981557 100644 --- a/linux/drivers/media/dvb/frontends/lgdt3305.c +++ b/linux/drivers/media/dvb/frontends/lgdt3305.c @@ -1105,7 +1105,7 @@ static struct dvb_frontend_ops lgdt3305_ops = { }; MODULE_DESCRIPTION("LG Electronics LGDT3305 ATSC/QAM-B Demodulator Driver"); -MODULE_AUTHOR("Michael Krufky"); +MODULE_AUTHOR("Michael Krufky "); MODULE_LICENSE("GPL"); /* -- cgit v1.2.3 From 128ef238ca1c652004419d9183144e4c6e492a99 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Wed, 11 Mar 2009 00:47:53 -0400 Subject: lgdt3305: add missing space in comment From: Michael Krufky small whitespace cleanup - space missing after the * Priority: normal Signed-off-by: Michael Krufky --- linux/drivers/media/dvb/frontends/lgdt3305.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/frontends/lgdt3305.c b/linux/drivers/media/dvb/frontends/lgdt3305.c index 780981557..85a40fe1e 100644 --- a/linux/drivers/media/dvb/frontends/lgdt3305.c +++ b/linux/drivers/media/dvb/frontends/lgdt3305.c @@ -936,7 +936,7 @@ static int lgdt3305_read_snr(struct dvb_frontend *fe, u16 *snr) /* convert from 8.24 fixed-point to 8.8 */ *snr = (state->snr) >> 16; #else - /*report SNR in dB * 10 */ + /* report SNR in dB * 10 */ *snr = (state->snr / ((1 << 24) / 10)); #endif lg_dbg("noise = 0x%08x, snr = %d.%02d dB\n", noise, -- cgit v1.2.3 From 3c00de0d74330e4761f5592f873d1a2b7553e8b3 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Wed, 11 Mar 2009 00:46:44 -0400 Subject: lgdt3305: add MODULE_VERSION From: Michael Krufky We'll start off with MODULE_VERSION("0.1") Priority: normal Signed-off-by: Michael Krufky --- linux/drivers/media/dvb/frontends/lgdt3305.c | 1 + 1 file changed, 1 insertion(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/frontends/lgdt3305.c b/linux/drivers/media/dvb/frontends/lgdt3305.c index 85a40fe1e..8d62d1257 100644 --- a/linux/drivers/media/dvb/frontends/lgdt3305.c +++ b/linux/drivers/media/dvb/frontends/lgdt3305.c @@ -1107,6 +1107,7 @@ static struct dvb_frontend_ops lgdt3305_ops = { MODULE_DESCRIPTION("LG Electronics LGDT3305 ATSC/QAM-B Demodulator Driver"); MODULE_AUTHOR("Michael Krufky "); MODULE_LICENSE("GPL"); +MODULE_VERSION("0.1"); /* * Local variables: -- cgit v1.2.3 From 50f5fcb71020940ea1d520eb2faa59c76253cfed Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Wed, 11 Mar 2009 01:58:53 -0400 Subject: xc5000: fix bug for hybrid xc5000 devices with IF other than 5380 From: Devin Heitmueller The xc5000 driver has a bug where the IF is always set to whatever the first caller to dvb_attach() provides. This fails when the device requires an IF other than 5380 and the analog driver is loaded first through tuner-core (which always supplies the hard-coded value of 5380). Thanks to Michael Krufky and Steven Toth for providing sample hardware, engineering level support, and testing. Priority: normal Signed-off-by: Devin Heitmueller Signed-off-by: Michael Krufky --- linux/drivers/media/common/tuners/xc5000.c | 9 +++++++-- linux/drivers/media/video/tuner-core.c | 3 ++- 2 files changed, 9 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 36c81febb..a64c52171 100644 --- a/linux/drivers/media/common/tuners/xc5000.c +++ b/linux/drivers/media/common/tuners/xc5000.c @@ -989,8 +989,6 @@ struct dvb_frontend *xc5000_attach(struct dvb_frontend *fe, case 1: /* new tuner instance */ priv->bandwidth = BANDWIDTH_6_MHZ; - priv->if_khz = cfg->if_khz; - fe->tuner_priv = priv; break; default: @@ -999,6 +997,13 @@ struct dvb_frontend *xc5000_attach(struct dvb_frontend *fe, break; } + if (priv->if_khz == 0) { + /* If the IF hasn't been set yet, use the value provided by + the caller (occurs in hybrid devices where the analog + call to xc5000_attach occurs before the digital side) */ + priv->if_khz = cfg->if_khz; + } + /* Check if firmware has been loaded. It is possible that another instance of the driver has loaded the firmware. */ diff --git a/linux/drivers/media/video/tuner-core.c b/linux/drivers/media/video/tuner-core.c index 0188d87ea..9a0ddd57c 100644 --- a/linux/drivers/media/video/tuner-core.c +++ b/linux/drivers/media/video/tuner-core.c @@ -453,7 +453,8 @@ static void set_type(struct i2c_client *c, unsigned int type, struct dvb_tuner_ops *xc_tuner_ops; xc5000_cfg.i2c_address = t->i2c->addr; - xc5000_cfg.if_khz = 5380; + /* if_khz will be set when the digital dvb_attach() occurs */ + xc5000_cfg.if_khz = 0; if (!dvb_attach(xc5000_attach, &t->fe, t->i2c->adapter, &xc5000_cfg)) goto attach_failed; -- cgit v1.2.3 From 5553d1020de15eea0f217aed78847db3c976ed4d Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Wed, 11 Mar 2009 01:59:30 -0400 Subject: au8522: rename the au8522.c source file From: Devin Heitmueller Rename the au8522.c file to au8522_dig.c so that more source files can be added to the driver while preserving the original name of au8522.ko Thanks to Michael Krufky and Steven Toth for providing sample hardware, engineering level support, and testing. Priority: normal Signed-off-by: Devin Heitmueller Signed-off-by: Michael Krufky --- linux/drivers/media/dvb/frontends/Makefile | 1 + linux/drivers/media/dvb/frontends/au8522.c | 880 ------------------------- linux/drivers/media/dvb/frontends/au8522_dig.c | 880 +++++++++++++++++++++++++ 3 files changed, 881 insertions(+), 880 deletions(-) delete mode 100644 linux/drivers/media/dvb/frontends/au8522.c create mode 100644 linux/drivers/media/dvb/frontends/au8522_dig.c (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/frontends/Makefile b/linux/drivers/media/dvb/frontends/Makefile index 1e3866b2f..fa3ab69f7 100644 --- a/linux/drivers/media/dvb/frontends/Makefile +++ b/linux/drivers/media/dvb/frontends/Makefile @@ -8,6 +8,7 @@ EXTRA_CFLAGS += -Idrivers/media/common/tuners/ s921-objs := s921_module.o s921_core.o stb0899-objs = stb0899_drv.o stb0899_algo.o stv0900-objs = stv0900_core.o stv0900_sw.o +au8522-objs = au8522_dig.o obj-$(CONFIG_DVB_PLL) += dvb-pll.o obj-$(CONFIG_DVB_STV0299) += stv0299.o diff --git a/linux/drivers/media/dvb/frontends/au8522.c b/linux/drivers/media/dvb/frontends/au8522.c deleted file mode 100644 index 1e3ad2302..000000000 --- a/linux/drivers/media/dvb/frontends/au8522.c +++ /dev/null @@ -1,880 +0,0 @@ -/* - Auvitek AU8522 QAM/8VSB demodulator driver - - Copyright (C) 2008 Steven Toth - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -*/ - -#include -#include -#include -#include -#include -#include -#include "dvb_frontend.h" -#include "au8522.h" - -struct au8522_state { - - struct i2c_adapter *i2c; - - /* configuration settings */ - const struct au8522_config *config; - - struct dvb_frontend frontend; - - u32 current_frequency; - fe_modulation_t current_modulation; - - u32 fe_status; - unsigned int led_state; -}; - -static int debug; - -#define dprintk(arg...) do { \ - if (debug) \ - printk(arg); \ - } while (0) - -/* 16 bit registers, 8 bit values */ -static int au8522_writereg(struct au8522_state *state, u16 reg, u8 data) -{ - int ret; - u8 buf [] = { reg >> 8, reg & 0xff, data }; - - struct i2c_msg msg = { .addr = state->config->demod_address, - .flags = 0, .buf = buf, .len = 3 }; - - ret = i2c_transfer(state->i2c, &msg, 1); - - if (ret != 1) - printk("%s: writereg error (reg == 0x%02x, val == 0x%04x, " - "ret == %i)\n", __func__, reg, data, ret); - - return (ret != 1) ? -1 : 0; -} - -static u8 au8522_readreg(struct au8522_state *state, u16 reg) -{ - int ret; - u8 b0 [] = { reg >> 8, reg & 0xff }; - u8 b1 [] = { 0 }; - - struct i2c_msg msg [] = { - { .addr = state->config->demod_address, .flags = 0, - .buf = b0, .len = 2 }, - { .addr = state->config->demod_address, .flags = I2C_M_RD, - .buf = b1, .len = 1 } }; - - ret = i2c_transfer(state->i2c, msg, 2); - - if (ret != 2) - printk(KERN_ERR "%s: readreg error (ret == %i)\n", - __func__, ret); - return b1[0]; -} - -static int au8522_i2c_gate_ctrl(struct dvb_frontend *fe, int enable) -{ - struct au8522_state *state = fe->demodulator_priv; - - dprintk("%s(%d)\n", __func__, enable); - - if (enable) - return au8522_writereg(state, 0x106, 1); - else - return au8522_writereg(state, 0x106, 0); -} - -struct mse2snr_tab { - u16 val; - u16 data; -}; - -/* VSB SNR lookup table */ -static struct mse2snr_tab vsb_mse2snr_tab[] = { - { 0, 270 }, - { 2, 250 }, - { 3, 240 }, - { 5, 230 }, - { 7, 220 }, - { 9, 210 }, - { 12, 200 }, - { 13, 195 }, - { 15, 190 }, - { 17, 185 }, - { 19, 180 }, - { 21, 175 }, - { 24, 170 }, - { 27, 165 }, - { 31, 160 }, - { 32, 158 }, - { 33, 156 }, - { 36, 152 }, - { 37, 150 }, - { 39, 148 }, - { 40, 146 }, - { 41, 144 }, - { 43, 142 }, - { 44, 140 }, - { 48, 135 }, - { 50, 130 }, - { 43, 142 }, - { 53, 125 }, - { 56, 120 }, - { 256, 115 }, -}; - -/* QAM64 SNR lookup table */ -static struct mse2snr_tab qam64_mse2snr_tab[] = { - { 15, 0 }, - { 16, 290 }, - { 17, 288 }, - { 18, 286 }, - { 19, 284 }, - { 20, 282 }, - { 21, 281 }, - { 22, 279 }, - { 23, 277 }, - { 24, 275 }, - { 25, 273 }, - { 26, 271 }, - { 27, 269 }, - { 28, 268 }, - { 29, 266 }, - { 30, 264 }, - { 31, 262 }, - { 32, 260 }, - { 33, 259 }, - { 34, 258 }, - { 35, 256 }, - { 36, 255 }, - { 37, 254 }, - { 38, 252 }, - { 39, 251 }, - { 40, 250 }, - { 41, 249 }, - { 42, 248 }, - { 43, 246 }, - { 44, 245 }, - { 45, 244 }, - { 46, 242 }, - { 47, 241 }, - { 48, 240 }, - { 50, 239 }, - { 51, 238 }, - { 53, 237 }, - { 54, 236 }, - { 56, 235 }, - { 57, 234 }, - { 59, 233 }, - { 60, 232 }, - { 62, 231 }, - { 63, 230 }, - { 65, 229 }, - { 67, 228 }, - { 68, 227 }, - { 70, 226 }, - { 71, 225 }, - { 73, 224 }, - { 74, 223 }, - { 76, 222 }, - { 78, 221 }, - { 80, 220 }, - { 82, 219 }, - { 85, 218 }, - { 88, 217 }, - { 90, 216 }, - { 92, 215 }, - { 93, 214 }, - { 94, 212 }, - { 95, 211 }, - { 97, 210 }, - { 99, 209 }, - { 101, 208 }, - { 102, 207 }, - { 104, 206 }, - { 107, 205 }, - { 111, 204 }, - { 114, 203 }, - { 118, 202 }, - { 122, 201 }, - { 125, 200 }, - { 128, 199 }, - { 130, 198 }, - { 132, 197 }, - { 256, 190 }, -}; - -/* QAM256 SNR lookup table */ -static struct mse2snr_tab qam256_mse2snr_tab[] = { - { 16, 0 }, - { 17, 400 }, - { 18, 398 }, - { 19, 396 }, - { 20, 394 }, - { 21, 392 }, - { 22, 390 }, - { 23, 388 }, - { 24, 386 }, - { 25, 384 }, - { 26, 382 }, - { 27, 380 }, - { 28, 379 }, - { 29, 378 }, - { 30, 377 }, - { 31, 376 }, - { 32, 375 }, - { 33, 374 }, - { 34, 373 }, - { 35, 372 }, - { 36, 371 }, - { 37, 370 }, - { 38, 362 }, - { 39, 354 }, - { 40, 346 }, - { 41, 338 }, - { 42, 330 }, - { 43, 328 }, - { 44, 326 }, - { 45, 324 }, - { 46, 322 }, - { 47, 320 }, - { 48, 319 }, - { 49, 318 }, - { 50, 317 }, - { 51, 316 }, - { 52, 315 }, - { 53, 314 }, - { 54, 313 }, - { 55, 312 }, - { 56, 311 }, - { 57, 310 }, - { 58, 308 }, - { 59, 306 }, - { 60, 304 }, - { 61, 302 }, - { 62, 300 }, - { 63, 298 }, - { 65, 295 }, - { 68, 294 }, - { 70, 293 }, - { 73, 292 }, - { 76, 291 }, - { 78, 290 }, - { 79, 289 }, - { 81, 288 }, - { 82, 287 }, - { 83, 286 }, - { 84, 285 }, - { 85, 284 }, - { 86, 283 }, - { 88, 282 }, - { 89, 281 }, - { 256, 280 }, -}; - -static int au8522_mse2snr_lookup(struct mse2snr_tab *tab, int sz, int mse, - u16 *snr) -{ - int i, ret = -EINVAL; - dprintk("%s()\n", __func__); - - for (i = 0; i < sz; i++) { - if (mse < tab[i].val) { - *snr = tab[i].data; - ret = 0; - break; - } - } - dprintk("%s() snr=%d\n", __func__, *snr); - return ret; -} - -static int au8522_set_if(struct dvb_frontend *fe, enum au8522_if_freq if_freq) -{ - struct au8522_state *state = fe->demodulator_priv; - u8 r0b5, r0b6, r0b7; - char *ifmhz; - - switch (if_freq) { - case AU8522_IF_3_25MHZ: - ifmhz = "3.25"; - r0b5 = 0x00; - r0b6 = 0x3d; - r0b7 = 0xa0; - break; - case AU8522_IF_4MHZ: - ifmhz = "4.00"; - r0b5 = 0x00; - r0b6 = 0x4b; - r0b7 = 0xd9; - break; - case AU8522_IF_6MHZ: - ifmhz = "6.00"; - r0b5 = 0xfb; - r0b6 = 0x8e; - r0b7 = 0x39; - break; - default: - dprintk("%s() IF Frequency not supported\n", __func__); - return -EINVAL; - } - dprintk("%s() %s MHz\n", __func__, ifmhz); - au8522_writereg(state, 0x80b5, r0b5); - au8522_writereg(state, 0x80b6, r0b6); - au8522_writereg(state, 0x80b7, r0b7); - - return 0; -} - -/* VSB Modulation table */ -static struct { - u16 reg; - u16 data; -} VSB_mod_tab[] = { - { 0x8090, 0x84 }, - { 0x4092, 0x11 }, - { 0x2005, 0x00 }, - { 0x8091, 0x80 }, - { 0x80a3, 0x0c }, - { 0x80a4, 0xe8 }, - { 0x8081, 0xc4 }, - { 0x80a5, 0x40 }, - { 0x80a7, 0x40 }, - { 0x80a6, 0x67 }, - { 0x8262, 0x20 }, - { 0x821c, 0x30 }, - { 0x80d8, 0x1a }, - { 0x8227, 0xa0 }, - { 0x8121, 0xff }, - { 0x80a8, 0xf0 }, - { 0x80a9, 0x05 }, - { 0x80aa, 0x77 }, - { 0x80ab, 0xf0 }, - { 0x80ac, 0x05 }, - { 0x80ad, 0x77 }, - { 0x80ae, 0x41 }, - { 0x80af, 0x66 }, - { 0x821b, 0xcc }, - { 0x821d, 0x80 }, - { 0x80a4, 0xe8 }, - { 0x8231, 0x13 }, -}; - -/* QAM Modulation table */ -static struct { - u16 reg; - u16 data; -} QAM_mod_tab[] = { - { 0x80a3, 0x09 }, - { 0x80a4, 0x00 }, - { 0x8081, 0xc4 }, - { 0x80a5, 0x40 }, - { 0x80aa, 0x77 }, - { 0x80ad, 0x77 }, - { 0x80a6, 0x67 }, - { 0x8262, 0x20 }, - { 0x821c, 0x30 }, - { 0x80b8, 0x3e }, - { 0x80b9, 0xf0 }, - { 0x80ba, 0x01 }, - { 0x80bb, 0x18 }, - { 0x80bc, 0x50 }, - { 0x80bd, 0x00 }, - { 0x80be, 0xea }, - { 0x80bf, 0xef }, - { 0x80c0, 0xfc }, - { 0x80c1, 0xbd }, - { 0x80c2, 0x1f }, - { 0x80c3, 0xfc }, - { 0x80c4, 0xdd }, - { 0x80c5, 0xaf }, - { 0x80c6, 0x00 }, - { 0x80c7, 0x38 }, - { 0x80c8, 0x30 }, - { 0x80c9, 0x05 }, - { 0x80ca, 0x4a }, - { 0x80cb, 0xd0 }, - { 0x80cc, 0x01 }, - { 0x80cd, 0xd9 }, - { 0x80ce, 0x6f }, - { 0x80cf, 0xf9 }, - { 0x80d0, 0x70 }, - { 0x80d1, 0xdf }, - { 0x80d2, 0xf7 }, - { 0x80d3, 0xc2 }, - { 0x80d4, 0xdf }, - { 0x80d5, 0x02 }, - { 0x80d6, 0x9a }, - { 0x80d7, 0xd0 }, - { 0x8250, 0x0d }, - { 0x8251, 0xcd }, - { 0x8252, 0xe0 }, - { 0x8253, 0x05 }, - { 0x8254, 0xa7 }, - { 0x8255, 0xff }, - { 0x8256, 0xed }, - { 0x8257, 0x5b }, - { 0x8258, 0xae }, - { 0x8259, 0xe6 }, - { 0x825a, 0x3d }, - { 0x825b, 0x0f }, - { 0x825c, 0x0d }, - { 0x825d, 0xea }, - { 0x825e, 0xf2 }, - { 0x825f, 0x51 }, - { 0x8260, 0xf5 }, - { 0x8261, 0x06 }, - { 0x821a, 0x00 }, - { 0x8546, 0x40 }, - { 0x8210, 0x26 }, - { 0x8211, 0xf6 }, - { 0x8212, 0x84 }, - { 0x8213, 0x02 }, - { 0x8502, 0x01 }, - { 0x8121, 0x04 }, - { 0x8122, 0x04 }, - { 0x852e, 0x10 }, - { 0x80a4, 0xca }, - { 0x80a7, 0x40 }, - { 0x8526, 0x01 }, -}; - -static int au8522_enable_modulation(struct dvb_frontend *fe, - fe_modulation_t m) -{ - struct au8522_state *state = fe->demodulator_priv; - int i; - - dprintk("%s(0x%08x)\n", __func__, m); - - switch (m) { - case VSB_8: - dprintk("%s() VSB_8\n", __func__); - for (i = 0; i < ARRAY_SIZE(VSB_mod_tab); i++) - au8522_writereg(state, - VSB_mod_tab[i].reg, - VSB_mod_tab[i].data); - au8522_set_if(fe, state->config->vsb_if); - break; - case QAM_64: - case QAM_256: - dprintk("%s() QAM 64/256\n", __func__); - for (i = 0; i < ARRAY_SIZE(QAM_mod_tab); i++) - au8522_writereg(state, - QAM_mod_tab[i].reg, - QAM_mod_tab[i].data); - au8522_set_if(fe, state->config->qam_if); - break; - default: - dprintk("%s() Invalid modulation\n", __func__); - return -EINVAL; - } - - state->current_modulation = m; - - return 0; -} - -/* Talk to the demod, set the FEC, GUARD, QAM settings etc */ -static int au8522_set_frontend(struct dvb_frontend *fe, - struct dvb_frontend_parameters *p) -{ - struct au8522_state *state = fe->demodulator_priv; - int ret = -EINVAL; - - dprintk("%s(frequency=%d)\n", __func__, p->frequency); - - if ((state->current_frequency == p->frequency) && - (state->current_modulation == p->u.vsb.modulation)) - return 0; - - au8522_enable_modulation(fe, p->u.vsb.modulation); - - /* Allow the demod to settle */ - msleep(100); - - if (fe->ops.tuner_ops.set_params) { - if (fe->ops.i2c_gate_ctrl) - fe->ops.i2c_gate_ctrl(fe, 1); - ret = fe->ops.tuner_ops.set_params(fe, p); - if (fe->ops.i2c_gate_ctrl) - fe->ops.i2c_gate_ctrl(fe, 0); - } - - if (ret < 0) - return ret; - - state->current_frequency = p->frequency; - - return 0; -} - -/* Reset the demod hardware and reset all of the configuration registers - to a default state. */ -static int au8522_init(struct dvb_frontend *fe) -{ - struct au8522_state *state = fe->demodulator_priv; - dprintk("%s()\n", __func__); - - au8522_writereg(state, 0xa4, 1 << 5); - - au8522_i2c_gate_ctrl(fe, 1); - - return 0; -} - -static int au8522_led_gpio_enable(struct au8522_state *state, int onoff) -{ - struct au8522_led_config *led_config = state->config->led_cfg; - u8 val; - - /* bail out if we cant control an LED */ - if (!led_config || !led_config->gpio_output || - !led_config->gpio_output_enable || !led_config->gpio_output_disable) - return 0; - - val = au8522_readreg(state, 0x4000 | - (led_config->gpio_output & ~0xc000)); - if (onoff) { - /* enable GPIO output */ - val &= ~((led_config->gpio_output_enable >> 8) & 0xff); - val |= (led_config->gpio_output_enable & 0xff); - } else { - /* disable GPIO output */ - val &= ~((led_config->gpio_output_disable >> 8) & 0xff); - val |= (led_config->gpio_output_disable & 0xff); - } - return au8522_writereg(state, 0x8000 | - (led_config->gpio_output & ~0xc000), val); -} - -/* led = 0 | off - * led = 1 | signal ok - * led = 2 | signal strong - * led < 0 | only light led if leds are currently off - */ -static int au8522_led_ctrl(struct au8522_state *state, int led) -{ - struct au8522_led_config *led_config = state->config->led_cfg; - int i, ret = 0; - - /* bail out if we cant control an LED */ - if (!led_config || !led_config->gpio_leds || - !led_config->num_led_states || !led_config->led_states) - return 0; - - if (led < 0) { - /* if LED is already lit, then leave it as-is */ - if (state->led_state) - return 0; - else - led *= -1; - } - - /* toggle LED if changing state */ - if (state->led_state != led) { - u8 val; - - dprintk("%s: %d\n", __func__, led); - - au8522_led_gpio_enable(state, 1); - - val = au8522_readreg(state, 0x4000 | - (led_config->gpio_leds & ~0xc000)); - - /* start with all leds off */ - for (i = 0; i < led_config->num_led_states; i++) - val &= ~led_config->led_states[i]; - - /* set selected LED state */ - if (led < led_config->num_led_states) - val |= led_config->led_states[led]; - else if (led_config->num_led_states) - val |= - led_config->led_states[led_config->num_led_states - 1]; - - ret = au8522_writereg(state, 0x8000 | - (led_config->gpio_leds & ~0xc000), val); - if (ret < 0) - return ret; - - state->led_state = led; - - if (led == 0) - au8522_led_gpio_enable(state, 0); - } - - return 0; -} - -static int au8522_sleep(struct dvb_frontend *fe) -{ - struct au8522_state *state = fe->demodulator_priv; - dprintk("%s()\n", __func__); - - /* turn off led */ - au8522_led_ctrl(state, 0); - - state->current_frequency = 0; - - return 0; -} - -static int au8522_read_status(struct dvb_frontend *fe, fe_status_t *status) -{ - struct au8522_state *state = fe->demodulator_priv; - u8 reg; - u32 tuner_status = 0; - - *status = 0; - - if (state->current_modulation == VSB_8) { - dprintk("%s() Checking VSB_8\n", __func__); - reg = au8522_readreg(state, 0x4088); - if ((reg & 0x03) == 0x03) - *status |= FE_HAS_LOCK | FE_HAS_SYNC | FE_HAS_VITERBI; - } else { - dprintk("%s() Checking QAM\n", __func__); - reg = au8522_readreg(state, 0x4541); - if (reg & 0x80) - *status |= FE_HAS_VITERBI; - if (reg & 0x20) - *status |= FE_HAS_LOCK | FE_HAS_SYNC; - } - - switch (state->config->status_mode) { - case AU8522_DEMODLOCKING: - dprintk("%s() DEMODLOCKING\n", __func__); - if (*status & FE_HAS_VITERBI) - *status |= FE_HAS_CARRIER | FE_HAS_SIGNAL; - break; - case AU8522_TUNERLOCKING: - /* Get the tuner status */ - dprintk("%s() TUNERLOCKING\n", __func__); - if (fe->ops.tuner_ops.get_status) { - if (fe->ops.i2c_gate_ctrl) - fe->ops.i2c_gate_ctrl(fe, 1); - - fe->ops.tuner_ops.get_status(fe, &tuner_status); - - if (fe->ops.i2c_gate_ctrl) - fe->ops.i2c_gate_ctrl(fe, 0); - } - if (tuner_status) - *status |= FE_HAS_CARRIER | FE_HAS_SIGNAL; - break; - } - state->fe_status = *status; - - if (*status & FE_HAS_LOCK) - /* turn on LED, if it isn't on already */ - au8522_led_ctrl(state, -1); - else - /* turn off LED */ - au8522_led_ctrl(state, 0); - - dprintk("%s() status 0x%08x\n", __func__, *status); - - return 0; -} - -static int au8522_led_status(struct au8522_state *state, const u16 *snr) -{ - struct au8522_led_config *led_config = state->config->led_cfg; - int led; - u16 strong; - - /* bail out if we cant control an LED */ - if (!led_config) - return 0; - - if (0 == (state->fe_status & FE_HAS_LOCK)) - return au8522_led_ctrl(state, 0); - else if (state->current_modulation == QAM_256) - strong = led_config->qam256_strong; - else if (state->current_modulation == QAM_64) - strong = led_config->qam64_strong; - else /* (state->current_modulation == VSB_8) */ - strong = led_config->vsb8_strong; - - if (*snr >= strong) - led = 2; - else - led = 1; - - if ((state->led_state) && - (((strong < *snr) ? (*snr - strong) : (strong - *snr)) <= 10)) - /* snr didn't change enough to bother - * changing the color of the led */ - return 0; - - return au8522_led_ctrl(state, led); -} - -static int au8522_read_snr(struct dvb_frontend *fe, u16 *snr) -{ - struct au8522_state *state = fe->demodulator_priv; - int ret = -EINVAL; - - dprintk("%s()\n", __func__); - - if (state->current_modulation == QAM_256) - ret = au8522_mse2snr_lookup(qam256_mse2snr_tab, - ARRAY_SIZE(qam256_mse2snr_tab), - au8522_readreg(state, 0x4522), - snr); - else if (state->current_modulation == QAM_64) - ret = au8522_mse2snr_lookup(qam64_mse2snr_tab, - ARRAY_SIZE(qam64_mse2snr_tab), - au8522_readreg(state, 0x4522), - snr); - else /* VSB_8 */ - ret = au8522_mse2snr_lookup(vsb_mse2snr_tab, - ARRAY_SIZE(vsb_mse2snr_tab), - au8522_readreg(state, 0x4311), - snr); - - if (state->config->led_cfg) - au8522_led_status(state, snr); - - return ret; -} - -static int au8522_read_signal_strength(struct dvb_frontend *fe, - u16 *signal_strength) -{ - return au8522_read_snr(fe, signal_strength); -} - -static int au8522_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) -{ - struct au8522_state *state = fe->demodulator_priv; - - if (state->current_modulation == VSB_8) - *ucblocks = au8522_readreg(state, 0x4087); - else - *ucblocks = au8522_readreg(state, 0x4543); - - return 0; -} - -static int au8522_read_ber(struct dvb_frontend *fe, u32 *ber) -{ - return au8522_read_ucblocks(fe, ber); -} - -static int au8522_get_frontend(struct dvb_frontend *fe, - struct dvb_frontend_parameters *p) -{ - struct au8522_state *state = fe->demodulator_priv; - - p->frequency = state->current_frequency; - p->u.vsb.modulation = state->current_modulation; - - return 0; -} - -static int au8522_get_tune_settings(struct dvb_frontend *fe, - struct dvb_frontend_tune_settings *tune) -{ - tune->min_delay_ms = 1000; - return 0; -} - -static void au8522_release(struct dvb_frontend *fe) -{ - struct au8522_state *state = fe->demodulator_priv; - kfree(state); -} - -static struct dvb_frontend_ops au8522_ops; - -struct dvb_frontend *au8522_attach(const struct au8522_config *config, - struct i2c_adapter *i2c) -{ - struct au8522_state *state = NULL; - - /* allocate memory for the internal state */ - state = kmalloc(sizeof(struct au8522_state), GFP_KERNEL); - if (state == NULL) - goto error; - - /* setup the state */ - state->config = config; - state->i2c = i2c; -#if 0 - /* check if the demod exists */ - reg = au8522_readreg(state, 0x04); - if ((reg != 0x0066) && (reg != 0x007f)) - goto error; -#endif - /* create dvb_frontend */ - memcpy(&state->frontend.ops, &au8522_ops, - sizeof(struct dvb_frontend_ops)); - state->frontend.demodulator_priv = state; - - if (au8522_init(&state->frontend) != 0) { - printk(KERN_ERR "%s: Failed to initialize correctly\n", - __func__); - goto error; - } - - /* Note: Leaving the I2C gate open here. */ - au8522_i2c_gate_ctrl(&state->frontend, 1); - - return &state->frontend; - -error: - kfree(state); - return NULL; -} -EXPORT_SYMBOL(au8522_attach); - -static struct dvb_frontend_ops au8522_ops = { - - .info = { - .name = "Auvitek AU8522 QAM/8VSB Frontend", - .type = FE_ATSC, - .frequency_min = 54000000, - .frequency_max = 858000000, - .frequency_stepsize = 62500, - .caps = FE_CAN_QAM_64 | FE_CAN_QAM_256 | FE_CAN_8VSB - }, - - .init = au8522_init, - .sleep = au8522_sleep, - .i2c_gate_ctrl = au8522_i2c_gate_ctrl, - .set_frontend = au8522_set_frontend, - .get_frontend = au8522_get_frontend, - .get_tune_settings = au8522_get_tune_settings, - .read_status = au8522_read_status, - .read_ber = au8522_read_ber, - .read_signal_strength = au8522_read_signal_strength, - .read_snr = au8522_read_snr, - .read_ucblocks = au8522_read_ucblocks, - .release = au8522_release, -}; - -module_param(debug, int, 0644); -MODULE_PARM_DESC(debug, "Enable verbose debug messages"); - -MODULE_DESCRIPTION("Auvitek AU8522 QAM-B/ATSC Demodulator driver"); -MODULE_AUTHOR("Steven Toth"); -MODULE_LICENSE("GPL"); diff --git a/linux/drivers/media/dvb/frontends/au8522_dig.c b/linux/drivers/media/dvb/frontends/au8522_dig.c new file mode 100644 index 000000000..1e3ad2302 --- /dev/null +++ b/linux/drivers/media/dvb/frontends/au8522_dig.c @@ -0,0 +1,880 @@ +/* + Auvitek AU8522 QAM/8VSB demodulator driver + + Copyright (C) 2008 Steven Toth + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#include +#include +#include +#include +#include +#include +#include "dvb_frontend.h" +#include "au8522.h" + +struct au8522_state { + + struct i2c_adapter *i2c; + + /* configuration settings */ + const struct au8522_config *config; + + struct dvb_frontend frontend; + + u32 current_frequency; + fe_modulation_t current_modulation; + + u32 fe_status; + unsigned int led_state; +}; + +static int debug; + +#define dprintk(arg...) do { \ + if (debug) \ + printk(arg); \ + } while (0) + +/* 16 bit registers, 8 bit values */ +static int au8522_writereg(struct au8522_state *state, u16 reg, u8 data) +{ + int ret; + u8 buf [] = { reg >> 8, reg & 0xff, data }; + + struct i2c_msg msg = { .addr = state->config->demod_address, + .flags = 0, .buf = buf, .len = 3 }; + + ret = i2c_transfer(state->i2c, &msg, 1); + + if (ret != 1) + printk("%s: writereg error (reg == 0x%02x, val == 0x%04x, " + "ret == %i)\n", __func__, reg, data, ret); + + return (ret != 1) ? -1 : 0; +} + +static u8 au8522_readreg(struct au8522_state *state, u16 reg) +{ + int ret; + u8 b0 [] = { reg >> 8, reg & 0xff }; + u8 b1 [] = { 0 }; + + struct i2c_msg msg [] = { + { .addr = state->config->demod_address, .flags = 0, + .buf = b0, .len = 2 }, + { .addr = state->config->demod_address, .flags = I2C_M_RD, + .buf = b1, .len = 1 } }; + + ret = i2c_transfer(state->i2c, msg, 2); + + if (ret != 2) + printk(KERN_ERR "%s: readreg error (ret == %i)\n", + __func__, ret); + return b1[0]; +} + +static int au8522_i2c_gate_ctrl(struct dvb_frontend *fe, int enable) +{ + struct au8522_state *state = fe->demodulator_priv; + + dprintk("%s(%d)\n", __func__, enable); + + if (enable) + return au8522_writereg(state, 0x106, 1); + else + return au8522_writereg(state, 0x106, 0); +} + +struct mse2snr_tab { + u16 val; + u16 data; +}; + +/* VSB SNR lookup table */ +static struct mse2snr_tab vsb_mse2snr_tab[] = { + { 0, 270 }, + { 2, 250 }, + { 3, 240 }, + { 5, 230 }, + { 7, 220 }, + { 9, 210 }, + { 12, 200 }, + { 13, 195 }, + { 15, 190 }, + { 17, 185 }, + { 19, 180 }, + { 21, 175 }, + { 24, 170 }, + { 27, 165 }, + { 31, 160 }, + { 32, 158 }, + { 33, 156 }, + { 36, 152 }, + { 37, 150 }, + { 39, 148 }, + { 40, 146 }, + { 41, 144 }, + { 43, 142 }, + { 44, 140 }, + { 48, 135 }, + { 50, 130 }, + { 43, 142 }, + { 53, 125 }, + { 56, 120 }, + { 256, 115 }, +}; + +/* QAM64 SNR lookup table */ +static struct mse2snr_tab qam64_mse2snr_tab[] = { + { 15, 0 }, + { 16, 290 }, + { 17, 288 }, + { 18, 286 }, + { 19, 284 }, + { 20, 282 }, + { 21, 281 }, + { 22, 279 }, + { 23, 277 }, + { 24, 275 }, + { 25, 273 }, + { 26, 271 }, + { 27, 269 }, + { 28, 268 }, + { 29, 266 }, + { 30, 264 }, + { 31, 262 }, + { 32, 260 }, + { 33, 259 }, + { 34, 258 }, + { 35, 256 }, + { 36, 255 }, + { 37, 254 }, + { 38, 252 }, + { 39, 251 }, + { 40, 250 }, + { 41, 249 }, + { 42, 248 }, + { 43, 246 }, + { 44, 245 }, + { 45, 244 }, + { 46, 242 }, + { 47, 241 }, + { 48, 240 }, + { 50, 239 }, + { 51, 238 }, + { 53, 237 }, + { 54, 236 }, + { 56, 235 }, + { 57, 234 }, + { 59, 233 }, + { 60, 232 }, + { 62, 231 }, + { 63, 230 }, + { 65, 229 }, + { 67, 228 }, + { 68, 227 }, + { 70, 226 }, + { 71, 225 }, + { 73, 224 }, + { 74, 223 }, + { 76, 222 }, + { 78, 221 }, + { 80, 220 }, + { 82, 219 }, + { 85, 218 }, + { 88, 217 }, + { 90, 216 }, + { 92, 215 }, + { 93, 214 }, + { 94, 212 }, + { 95, 211 }, + { 97, 210 }, + { 99, 209 }, + { 101, 208 }, + { 102, 207 }, + { 104, 206 }, + { 107, 205 }, + { 111, 204 }, + { 114, 203 }, + { 118, 202 }, + { 122, 201 }, + { 125, 200 }, + { 128, 199 }, + { 130, 198 }, + { 132, 197 }, + { 256, 190 }, +}; + +/* QAM256 SNR lookup table */ +static struct mse2snr_tab qam256_mse2snr_tab[] = { + { 16, 0 }, + { 17, 400 }, + { 18, 398 }, + { 19, 396 }, + { 20, 394 }, + { 21, 392 }, + { 22, 390 }, + { 23, 388 }, + { 24, 386 }, + { 25, 384 }, + { 26, 382 }, + { 27, 380 }, + { 28, 379 }, + { 29, 378 }, + { 30, 377 }, + { 31, 376 }, + { 32, 375 }, + { 33, 374 }, + { 34, 373 }, + { 35, 372 }, + { 36, 371 }, + { 37, 370 }, + { 38, 362 }, + { 39, 354 }, + { 40, 346 }, + { 41, 338 }, + { 42, 330 }, + { 43, 328 }, + { 44, 326 }, + { 45, 324 }, + { 46, 322 }, + { 47, 320 }, + { 48, 319 }, + { 49, 318 }, + { 50, 317 }, + { 51, 316 }, + { 52, 315 }, + { 53, 314 }, + { 54, 313 }, + { 55, 312 }, + { 56, 311 }, + { 57, 310 }, + { 58, 308 }, + { 59, 306 }, + { 60, 304 }, + { 61, 302 }, + { 62, 300 }, + { 63, 298 }, + { 65, 295 }, + { 68, 294 }, + { 70, 293 }, + { 73, 292 }, + { 76, 291 }, + { 78, 290 }, + { 79, 289 }, + { 81, 288 }, + { 82, 287 }, + { 83, 286 }, + { 84, 285 }, + { 85, 284 }, + { 86, 283 }, + { 88, 282 }, + { 89, 281 }, + { 256, 280 }, +}; + +static int au8522_mse2snr_lookup(struct mse2snr_tab *tab, int sz, int mse, + u16 *snr) +{ + int i, ret = -EINVAL; + dprintk("%s()\n", __func__); + + for (i = 0; i < sz; i++) { + if (mse < tab[i].val) { + *snr = tab[i].data; + ret = 0; + break; + } + } + dprintk("%s() snr=%d\n", __func__, *snr); + return ret; +} + +static int au8522_set_if(struct dvb_frontend *fe, enum au8522_if_freq if_freq) +{ + struct au8522_state *state = fe->demodulator_priv; + u8 r0b5, r0b6, r0b7; + char *ifmhz; + + switch (if_freq) { + case AU8522_IF_3_25MHZ: + ifmhz = "3.25"; + r0b5 = 0x00; + r0b6 = 0x3d; + r0b7 = 0xa0; + break; + case AU8522_IF_4MHZ: + ifmhz = "4.00"; + r0b5 = 0x00; + r0b6 = 0x4b; + r0b7 = 0xd9; + break; + case AU8522_IF_6MHZ: + ifmhz = "6.00"; + r0b5 = 0xfb; + r0b6 = 0x8e; + r0b7 = 0x39; + break; + default: + dprintk("%s() IF Frequency not supported\n", __func__); + return -EINVAL; + } + dprintk("%s() %s MHz\n", __func__, ifmhz); + au8522_writereg(state, 0x80b5, r0b5); + au8522_writereg(state, 0x80b6, r0b6); + au8522_writereg(state, 0x80b7, r0b7); + + return 0; +} + +/* VSB Modulation table */ +static struct { + u16 reg; + u16 data; +} VSB_mod_tab[] = { + { 0x8090, 0x84 }, + { 0x4092, 0x11 }, + { 0x2005, 0x00 }, + { 0x8091, 0x80 }, + { 0x80a3, 0x0c }, + { 0x80a4, 0xe8 }, + { 0x8081, 0xc4 }, + { 0x80a5, 0x40 }, + { 0x80a7, 0x40 }, + { 0x80a6, 0x67 }, + { 0x8262, 0x20 }, + { 0x821c, 0x30 }, + { 0x80d8, 0x1a }, + { 0x8227, 0xa0 }, + { 0x8121, 0xff }, + { 0x80a8, 0xf0 }, + { 0x80a9, 0x05 }, + { 0x80aa, 0x77 }, + { 0x80ab, 0xf0 }, + { 0x80ac, 0x05 }, + { 0x80ad, 0x77 }, + { 0x80ae, 0x41 }, + { 0x80af, 0x66 }, + { 0x821b, 0xcc }, + { 0x821d, 0x80 }, + { 0x80a4, 0xe8 }, + { 0x8231, 0x13 }, +}; + +/* QAM Modulation table */ +static struct { + u16 reg; + u16 data; +} QAM_mod_tab[] = { + { 0x80a3, 0x09 }, + { 0x80a4, 0x00 }, + { 0x8081, 0xc4 }, + { 0x80a5, 0x40 }, + { 0x80aa, 0x77 }, + { 0x80ad, 0x77 }, + { 0x80a6, 0x67 }, + { 0x8262, 0x20 }, + { 0x821c, 0x30 }, + { 0x80b8, 0x3e }, + { 0x80b9, 0xf0 }, + { 0x80ba, 0x01 }, + { 0x80bb, 0x18 }, + { 0x80bc, 0x50 }, + { 0x80bd, 0x00 }, + { 0x80be, 0xea }, + { 0x80bf, 0xef }, + { 0x80c0, 0xfc }, + { 0x80c1, 0xbd }, + { 0x80c2, 0x1f }, + { 0x80c3, 0xfc }, + { 0x80c4, 0xdd }, + { 0x80c5, 0xaf }, + { 0x80c6, 0x00 }, + { 0x80c7, 0x38 }, + { 0x80c8, 0x30 }, + { 0x80c9, 0x05 }, + { 0x80ca, 0x4a }, + { 0x80cb, 0xd0 }, + { 0x80cc, 0x01 }, + { 0x80cd, 0xd9 }, + { 0x80ce, 0x6f }, + { 0x80cf, 0xf9 }, + { 0x80d0, 0x70 }, + { 0x80d1, 0xdf }, + { 0x80d2, 0xf7 }, + { 0x80d3, 0xc2 }, + { 0x80d4, 0xdf }, + { 0x80d5, 0x02 }, + { 0x80d6, 0x9a }, + { 0x80d7, 0xd0 }, + { 0x8250, 0x0d }, + { 0x8251, 0xcd }, + { 0x8252, 0xe0 }, + { 0x8253, 0x05 }, + { 0x8254, 0xa7 }, + { 0x8255, 0xff }, + { 0x8256, 0xed }, + { 0x8257, 0x5b }, + { 0x8258, 0xae }, + { 0x8259, 0xe6 }, + { 0x825a, 0x3d }, + { 0x825b, 0x0f }, + { 0x825c, 0x0d }, + { 0x825d, 0xea }, + { 0x825e, 0xf2 }, + { 0x825f, 0x51 }, + { 0x8260, 0xf5 }, + { 0x8261, 0x06 }, + { 0x821a, 0x00 }, + { 0x8546, 0x40 }, + { 0x8210, 0x26 }, + { 0x8211, 0xf6 }, + { 0x8212, 0x84 }, + { 0x8213, 0x02 }, + { 0x8502, 0x01 }, + { 0x8121, 0x04 }, + { 0x8122, 0x04 }, + { 0x852e, 0x10 }, + { 0x80a4, 0xca }, + { 0x80a7, 0x40 }, + { 0x8526, 0x01 }, +}; + +static int au8522_enable_modulation(struct dvb_frontend *fe, + fe_modulation_t m) +{ + struct au8522_state *state = fe->demodulator_priv; + int i; + + dprintk("%s(0x%08x)\n", __func__, m); + + switch (m) { + case VSB_8: + dprintk("%s() VSB_8\n", __func__); + for (i = 0; i < ARRAY_SIZE(VSB_mod_tab); i++) + au8522_writereg(state, + VSB_mod_tab[i].reg, + VSB_mod_tab[i].data); + au8522_set_if(fe, state->config->vsb_if); + break; + case QAM_64: + case QAM_256: + dprintk("%s() QAM 64/256\n", __func__); + for (i = 0; i < ARRAY_SIZE(QAM_mod_tab); i++) + au8522_writereg(state, + QAM_mod_tab[i].reg, + QAM_mod_tab[i].data); + au8522_set_if(fe, state->config->qam_if); + break; + default: + dprintk("%s() Invalid modulation\n", __func__); + return -EINVAL; + } + + state->current_modulation = m; + + return 0; +} + +/* Talk to the demod, set the FEC, GUARD, QAM settings etc */ +static int au8522_set_frontend(struct dvb_frontend *fe, + struct dvb_frontend_parameters *p) +{ + struct au8522_state *state = fe->demodulator_priv; + int ret = -EINVAL; + + dprintk("%s(frequency=%d)\n", __func__, p->frequency); + + if ((state->current_frequency == p->frequency) && + (state->current_modulation == p->u.vsb.modulation)) + return 0; + + au8522_enable_modulation(fe, p->u.vsb.modulation); + + /* Allow the demod to settle */ + msleep(100); + + if (fe->ops.tuner_ops.set_params) { + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); + ret = fe->ops.tuner_ops.set_params(fe, p); + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 0); + } + + if (ret < 0) + return ret; + + state->current_frequency = p->frequency; + + return 0; +} + +/* Reset the demod hardware and reset all of the configuration registers + to a default state. */ +static int au8522_init(struct dvb_frontend *fe) +{ + struct au8522_state *state = fe->demodulator_priv; + dprintk("%s()\n", __func__); + + au8522_writereg(state, 0xa4, 1 << 5); + + au8522_i2c_gate_ctrl(fe, 1); + + return 0; +} + +static int au8522_led_gpio_enable(struct au8522_state *state, int onoff) +{ + struct au8522_led_config *led_config = state->config->led_cfg; + u8 val; + + /* bail out if we cant control an LED */ + if (!led_config || !led_config->gpio_output || + !led_config->gpio_output_enable || !led_config->gpio_output_disable) + return 0; + + val = au8522_readreg(state, 0x4000 | + (led_config->gpio_output & ~0xc000)); + if (onoff) { + /* enable GPIO output */ + val &= ~((led_config->gpio_output_enable >> 8) & 0xff); + val |= (led_config->gpio_output_enable & 0xff); + } else { + /* disable GPIO output */ + val &= ~((led_config->gpio_output_disable >> 8) & 0xff); + val |= (led_config->gpio_output_disable & 0xff); + } + return au8522_writereg(state, 0x8000 | + (led_config->gpio_output & ~0xc000), val); +} + +/* led = 0 | off + * led = 1 | signal ok + * led = 2 | signal strong + * led < 0 | only light led if leds are currently off + */ +static int au8522_led_ctrl(struct au8522_state *state, int led) +{ + struct au8522_led_config *led_config = state->config->led_cfg; + int i, ret = 0; + + /* bail out if we cant control an LED */ + if (!led_config || !led_config->gpio_leds || + !led_config->num_led_states || !led_config->led_states) + return 0; + + if (led < 0) { + /* if LED is already lit, then leave it as-is */ + if (state->led_state) + return 0; + else + led *= -1; + } + + /* toggle LED if changing state */ + if (state->led_state != led) { + u8 val; + + dprintk("%s: %d\n", __func__, led); + + au8522_led_gpio_enable(state, 1); + + val = au8522_readreg(state, 0x4000 | + (led_config->gpio_leds & ~0xc000)); + + /* start with all leds off */ + for (i = 0; i < led_config->num_led_states; i++) + val &= ~led_config->led_states[i]; + + /* set selected LED state */ + if (led < led_config->num_led_states) + val |= led_config->led_states[led]; + else if (led_config->num_led_states) + val |= + led_config->led_states[led_config->num_led_states - 1]; + + ret = au8522_writereg(state, 0x8000 | + (led_config->gpio_leds & ~0xc000), val); + if (ret < 0) + return ret; + + state->led_state = led; + + if (led == 0) + au8522_led_gpio_enable(state, 0); + } + + return 0; +} + +static int au8522_sleep(struct dvb_frontend *fe) +{ + struct au8522_state *state = fe->demodulator_priv; + dprintk("%s()\n", __func__); + + /* turn off led */ + au8522_led_ctrl(state, 0); + + state->current_frequency = 0; + + return 0; +} + +static int au8522_read_status(struct dvb_frontend *fe, fe_status_t *status) +{ + struct au8522_state *state = fe->demodulator_priv; + u8 reg; + u32 tuner_status = 0; + + *status = 0; + + if (state->current_modulation == VSB_8) { + dprintk("%s() Checking VSB_8\n", __func__); + reg = au8522_readreg(state, 0x4088); + if ((reg & 0x03) == 0x03) + *status |= FE_HAS_LOCK | FE_HAS_SYNC | FE_HAS_VITERBI; + } else { + dprintk("%s() Checking QAM\n", __func__); + reg = au8522_readreg(state, 0x4541); + if (reg & 0x80) + *status |= FE_HAS_VITERBI; + if (reg & 0x20) + *status |= FE_HAS_LOCK | FE_HAS_SYNC; + } + + switch (state->config->status_mode) { + case AU8522_DEMODLOCKING: + dprintk("%s() DEMODLOCKING\n", __func__); + if (*status & FE_HAS_VITERBI) + *status |= FE_HAS_CARRIER | FE_HAS_SIGNAL; + break; + case AU8522_TUNERLOCKING: + /* Get the tuner status */ + dprintk("%s() TUNERLOCKING\n", __func__); + if (fe->ops.tuner_ops.get_status) { + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); + + fe->ops.tuner_ops.get_status(fe, &tuner_status); + + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 0); + } + if (tuner_status) + *status |= FE_HAS_CARRIER | FE_HAS_SIGNAL; + break; + } + state->fe_status = *status; + + if (*status & FE_HAS_LOCK) + /* turn on LED, if it isn't on already */ + au8522_led_ctrl(state, -1); + else + /* turn off LED */ + au8522_led_ctrl(state, 0); + + dprintk("%s() status 0x%08x\n", __func__, *status); + + return 0; +} + +static int au8522_led_status(struct au8522_state *state, const u16 *snr) +{ + struct au8522_led_config *led_config = state->config->led_cfg; + int led; + u16 strong; + + /* bail out if we cant control an LED */ + if (!led_config) + return 0; + + if (0 == (state->fe_status & FE_HAS_LOCK)) + return au8522_led_ctrl(state, 0); + else if (state->current_modulation == QAM_256) + strong = led_config->qam256_strong; + else if (state->current_modulation == QAM_64) + strong = led_config->qam64_strong; + else /* (state->current_modulation == VSB_8) */ + strong = led_config->vsb8_strong; + + if (*snr >= strong) + led = 2; + else + led = 1; + + if ((state->led_state) && + (((strong < *snr) ? (*snr - strong) : (strong - *snr)) <= 10)) + /* snr didn't change enough to bother + * changing the color of the led */ + return 0; + + return au8522_led_ctrl(state, led); +} + +static int au8522_read_snr(struct dvb_frontend *fe, u16 *snr) +{ + struct au8522_state *state = fe->demodulator_priv; + int ret = -EINVAL; + + dprintk("%s()\n", __func__); + + if (state->current_modulation == QAM_256) + ret = au8522_mse2snr_lookup(qam256_mse2snr_tab, + ARRAY_SIZE(qam256_mse2snr_tab), + au8522_readreg(state, 0x4522), + snr); + else if (state->current_modulation == QAM_64) + ret = au8522_mse2snr_lookup(qam64_mse2snr_tab, + ARRAY_SIZE(qam64_mse2snr_tab), + au8522_readreg(state, 0x4522), + snr); + else /* VSB_8 */ + ret = au8522_mse2snr_lookup(vsb_mse2snr_tab, + ARRAY_SIZE(vsb_mse2snr_tab), + au8522_readreg(state, 0x4311), + snr); + + if (state->config->led_cfg) + au8522_led_status(state, snr); + + return ret; +} + +static int au8522_read_signal_strength(struct dvb_frontend *fe, + u16 *signal_strength) +{ + return au8522_read_snr(fe, signal_strength); +} + +static int au8522_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) +{ + struct au8522_state *state = fe->demodulator_priv; + + if (state->current_modulation == VSB_8) + *ucblocks = au8522_readreg(state, 0x4087); + else + *ucblocks = au8522_readreg(state, 0x4543); + + return 0; +} + +static int au8522_read_ber(struct dvb_frontend *fe, u32 *ber) +{ + return au8522_read_ucblocks(fe, ber); +} + +static int au8522_get_frontend(struct dvb_frontend *fe, + struct dvb_frontend_parameters *p) +{ + struct au8522_state *state = fe->demodulator_priv; + + p->frequency = state->current_frequency; + p->u.vsb.modulation = state->current_modulation; + + return 0; +} + +static int au8522_get_tune_settings(struct dvb_frontend *fe, + struct dvb_frontend_tune_settings *tune) +{ + tune->min_delay_ms = 1000; + return 0; +} + +static void au8522_release(struct dvb_frontend *fe) +{ + struct au8522_state *state = fe->demodulator_priv; + kfree(state); +} + +static struct dvb_frontend_ops au8522_ops; + +struct dvb_frontend *au8522_attach(const struct au8522_config *config, + struct i2c_adapter *i2c) +{ + struct au8522_state *state = NULL; + + /* allocate memory for the internal state */ + state = kmalloc(sizeof(struct au8522_state), GFP_KERNEL); + if (state == NULL) + goto error; + + /* setup the state */ + state->config = config; + state->i2c = i2c; +#if 0 + /* check if the demod exists */ + reg = au8522_readreg(state, 0x04); + if ((reg != 0x0066) && (reg != 0x007f)) + goto error; +#endif + /* create dvb_frontend */ + memcpy(&state->frontend.ops, &au8522_ops, + sizeof(struct dvb_frontend_ops)); + state->frontend.demodulator_priv = state; + + if (au8522_init(&state->frontend) != 0) { + printk(KERN_ERR "%s: Failed to initialize correctly\n", + __func__); + goto error; + } + + /* Note: Leaving the I2C gate open here. */ + au8522_i2c_gate_ctrl(&state->frontend, 1); + + return &state->frontend; + +error: + kfree(state); + return NULL; +} +EXPORT_SYMBOL(au8522_attach); + +static struct dvb_frontend_ops au8522_ops = { + + .info = { + .name = "Auvitek AU8522 QAM/8VSB Frontend", + .type = FE_ATSC, + .frequency_min = 54000000, + .frequency_max = 858000000, + .frequency_stepsize = 62500, + .caps = FE_CAN_QAM_64 | FE_CAN_QAM_256 | FE_CAN_8VSB + }, + + .init = au8522_init, + .sleep = au8522_sleep, + .i2c_gate_ctrl = au8522_i2c_gate_ctrl, + .set_frontend = au8522_set_frontend, + .get_frontend = au8522_get_frontend, + .get_tune_settings = au8522_get_tune_settings, + .read_status = au8522_read_status, + .read_ber = au8522_read_ber, + .read_signal_strength = au8522_read_signal_strength, + .read_snr = au8522_read_snr, + .read_ucblocks = au8522_read_ucblocks, + .release = au8522_release, +}; + +module_param(debug, int, 0644); +MODULE_PARM_DESC(debug, "Enable verbose debug messages"); + +MODULE_DESCRIPTION("Auvitek AU8522 QAM-B/ATSC Demodulator driver"); +MODULE_AUTHOR("Steven Toth"); +MODULE_LICENSE("GPL"); -- cgit v1.2.3 From 442d082f75069d464542421d3e3d6da68c2ddbc4 Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Wed, 11 Mar 2009 01:59:56 -0400 Subject: au8522: move shared state and common functions into a separate header files From: Devin Heitmueller Move the au8522 state structure, as well as exposing functions needed by the analog side of the demodulator into a common header file. Thanks to Michael Krufky and Steven Toth for providing sample hardware, engineering level support, and testing. Priority: normal Signed-off-by: Devin Heitmueller Signed-off-by: Michael Krufky --- linux/drivers/media/dvb/frontends/au8522_dig.c | 25 +++-------- linux/drivers/media/dvb/frontends/au8522_priv.h | 57 +++++++++++++++++++++++++ 2 files changed, 62 insertions(+), 20 deletions(-) create mode 100644 linux/drivers/media/dvb/frontends/au8522_priv.h (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/frontends/au8522_dig.c b/linux/drivers/media/dvb/frontends/au8522_dig.c index 1e3ad2302..cd8f1ec3e 100644 --- a/linux/drivers/media/dvb/frontends/au8522_dig.c +++ b/linux/drivers/media/dvb/frontends/au8522_dig.c @@ -27,22 +27,7 @@ #include #include "dvb_frontend.h" #include "au8522.h" - -struct au8522_state { - - struct i2c_adapter *i2c; - - /* configuration settings */ - const struct au8522_config *config; - - struct dvb_frontend frontend; - - u32 current_frequency; - fe_modulation_t current_modulation; - - u32 fe_status; - unsigned int led_state; -}; +#include "au8522_priv.h" static int debug; @@ -52,7 +37,7 @@ static int debug; } while (0) /* 16 bit registers, 8 bit values */ -static int au8522_writereg(struct au8522_state *state, u16 reg, u8 data) +int au8522_writereg(struct au8522_state *state, u16 reg, u8 data) { int ret; u8 buf [] = { reg >> 8, reg & 0xff, data }; @@ -69,7 +54,7 @@ static int au8522_writereg(struct au8522_state *state, u16 reg, u8 data) return (ret != 1) ? -1 : 0; } -static u8 au8522_readreg(struct au8522_state *state, u16 reg) +u8 au8522_readreg(struct au8522_state *state, u16 reg) { int ret; u8 b0 [] = { reg >> 8, reg & 0xff }; @@ -528,7 +513,7 @@ static int au8522_set_frontend(struct dvb_frontend *fe, /* Reset the demod hardware and reset all of the configuration registers to a default state. */ -static int au8522_init(struct dvb_frontend *fe) +int au8522_init(struct dvb_frontend *fe) { struct au8522_state *state = fe->demodulator_priv; dprintk("%s()\n", __func__); @@ -624,7 +609,7 @@ static int au8522_led_ctrl(struct au8522_state *state, int led) return 0; } -static int au8522_sleep(struct dvb_frontend *fe) +int au8522_sleep(struct dvb_frontend *fe) { struct au8522_state *state = fe->demodulator_priv; dprintk("%s()\n", __func__); diff --git a/linux/drivers/media/dvb/frontends/au8522_priv.h b/linux/drivers/media/dvb/frontends/au8522_priv.h new file mode 100644 index 000000000..569675d29 --- /dev/null +++ b/linux/drivers/media/dvb/frontends/au8522_priv.h @@ -0,0 +1,57 @@ +/* + Auvitek AU8522 QAM/8VSB demodulator driver + + Copyright (C) 2008 Steven Toth + Copyright (C) 2008 Devin Heitmueller + Copyright (C) 2005-2008 Auvitek International, Ltd. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "dvb_frontend.h" +#include "au8522.h" +#include "tuner-i2c.h" + +struct au8522_state { + struct i2c_adapter *i2c; + + /* configuration settings */ + const struct au8522_config *config; + + struct dvb_frontend frontend; + + u32 current_frequency; + fe_modulation_t current_modulation; + + u32 fe_status; + unsigned int led_state; +}; + +/* These are routines shared by both the VSB/QAM demodulator and the analog + decoder */ +int au8522_writereg(struct au8522_state *state, u16 reg, u8 data); +u8 au8522_readreg(struct au8522_state *state, u16 reg); +int au8522_init(struct dvb_frontend *fe); +int au8522_sleep(struct dvb_frontend *fe); -- cgit v1.2.3 From fe041f64faf5fecd2b6a9edecf7c74bb7cf71c95 Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Wed, 11 Mar 2009 02:00:19 -0400 Subject: au8522: fix register read/write high bits From: Devin Heitmueller For the i2c messages to read and write registers, the two high order bits of the first byte dictates whether it is a read or a write operation. Thanks to Michael Krufky and Steven Toth for providing sample hardware, engineering level support, and testing. Priority: normal Signed-off-by: Devin Heitmueller Signed-off-by: Michael Krufky --- linux/drivers/media/dvb/frontends/au8522_dig.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/frontends/au8522_dig.c b/linux/drivers/media/dvb/frontends/au8522_dig.c index cd8f1ec3e..e63e17827 100644 --- a/linux/drivers/media/dvb/frontends/au8522_dig.c +++ b/linux/drivers/media/dvb/frontends/au8522_dig.c @@ -40,7 +40,7 @@ static int debug; int au8522_writereg(struct au8522_state *state, u16 reg, u8 data) { int ret; - u8 buf [] = { reg >> 8, reg & 0xff, data }; + u8 buf [] = { (reg >> 8) | 0x80, reg & 0xff, data }; struct i2c_msg msg = { .addr = state->config->demod_address, .flags = 0, .buf = buf, .len = 3 }; @@ -57,7 +57,7 @@ int au8522_writereg(struct au8522_state *state, u16 reg, u8 data) u8 au8522_readreg(struct au8522_state *state, u16 reg) { int ret; - u8 b0 [] = { reg >> 8, reg & 0xff }; + u8 b0 [] = { (reg >> 8) | 0x40, reg & 0xff }; u8 b1 [] = { 0 }; struct i2c_msg msg [] = { -- cgit v1.2.3 From c55d671ee9eb267b04c218863cd9a577fa036dbc Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Wed, 11 Mar 2009 02:00:34 -0400 Subject: au8522: power down the digital demod when not in use From: Devin Heitmueller When the au8522 is idle, put the chip into a low power mode (reduces power consumption from 450ma to 346ma) Thanks to Michael Krufky and Steven Toth for providing sample hardware, engineering level support, and testing. Priority: normal Signed-off-by: Devin Heitmueller Signed-off-by: Michael Krufky --- linux/drivers/media/dvb/frontends/au8522_dig.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/frontends/au8522_dig.c b/linux/drivers/media/dvb/frontends/au8522_dig.c index e63e17827..a78636286 100644 --- a/linux/drivers/media/dvb/frontends/au8522_dig.c +++ b/linux/drivers/media/dvb/frontends/au8522_dig.c @@ -617,6 +617,9 @@ int au8522_sleep(struct dvb_frontend *fe) /* turn off led */ au8522_led_ctrl(state, 0); + /* Power down the chip */ + au8522_writereg(state, 0xa4, 1 << 5); + state->current_frequency = 0; return 0; -- cgit v1.2.3 From 552d2a4fdce766a81187b285e8114ee089b7a721 Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Wed, 11 Mar 2009 02:00:36 -0400 Subject: au8522: make use of hybrid framework so analog/digital demod can share state From: Devin Heitmueller Make use of the hybrid tuner framework so the analog and digital parts of the au8522 demodulator can make use of the same shared state. Thanks to Michael Krufky and Steven Toth for providing sample hardware, engineering level support, and testing. Priority: normal Signed-off-by: Devin Heitmueller Signed-off-by: Michael Krufky --- linux/drivers/media/dvb/frontends/au8522_dig.c | 45 +++++++++++++++++++++---- linux/drivers/media/dvb/frontends/au8522_priv.h | 8 +++++ 2 files changed, 46 insertions(+), 7 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/frontends/au8522_dig.c b/linux/drivers/media/dvb/frontends/au8522_dig.c index a78636286..00d783ce2 100644 --- a/linux/drivers/media/dvb/frontends/au8522_dig.c +++ b/linux/drivers/media/dvb/frontends/au8522_dig.c @@ -31,6 +31,10 @@ static int debug; +/* Despite the name "hybrid_tuner", the framework works just as well for + hybrid demodulators as well... */ +static LIST_HEAD(hybrid_tuner_instance_list); + #define dprintk(arg...) do { \ if (debug) \ printk(arg); \ @@ -786,23 +790,50 @@ static int au8522_get_tune_settings(struct dvb_frontend *fe, return 0; } +static struct dvb_frontend_ops au8522_ops; + +int au8522_get_state(struct au8522_state **state, struct i2c_adapter *i2c, + u8 client_address) +{ + return hybrid_tuner_request_state(struct au8522_state, (*state), + hybrid_tuner_instance_list, + i2c, client_address, "au8522"); +} + +void au8522_release_state(struct au8522_state *state) +{ + if (state != NULL) + hybrid_tuner_release_state(state); +} + + static void au8522_release(struct dvb_frontend *fe) { struct au8522_state *state = fe->demodulator_priv; - kfree(state); + au8522_release_state(state); } -static struct dvb_frontend_ops au8522_ops; - struct dvb_frontend *au8522_attach(const struct au8522_config *config, struct i2c_adapter *i2c) { struct au8522_state *state = NULL; + int instance; /* allocate memory for the internal state */ - state = kmalloc(sizeof(struct au8522_state), GFP_KERNEL); - if (state == NULL) - goto error; + instance = au8522_get_state(&state, i2c, config->demod_address); + switch (instance) { + case 0: + dprintk("%s state allocation failed\n", __func__); + break; + case 1: + /* new demod instance */ + dprintk("%s using new instance\n", __func__); + break; + default: + /* existing demod instance */ + dprintk("%s using existing instance\n", __func__); + break; + } /* setup the state */ state->config = config; @@ -830,7 +861,7 @@ struct dvb_frontend *au8522_attach(const struct au8522_config *config, return &state->frontend; error: - kfree(state); + au8522_release_state(state); return NULL; } EXPORT_SYMBOL(au8522_attach); diff --git a/linux/drivers/media/dvb/frontends/au8522_priv.h b/linux/drivers/media/dvb/frontends/au8522_priv.h index 569675d29..98b09caa2 100644 --- a/linux/drivers/media/dvb/frontends/au8522_priv.h +++ b/linux/drivers/media/dvb/frontends/au8522_priv.h @@ -37,6 +37,10 @@ struct au8522_state { struct i2c_adapter *i2c; + /* Used for sharing of the state between analog and digital mode */ + struct tuner_i2c_props i2c_props; + struct list_head hybrid_tuner_instance_list; + /* configuration settings */ const struct au8522_config *config; @@ -55,3 +59,7 @@ int au8522_writereg(struct au8522_state *state, u16 reg, u8 data); u8 au8522_readreg(struct au8522_state *state, u16 reg); int au8522_init(struct dvb_frontend *fe); int au8522_sleep(struct dvb_frontend *fe); + +int au8522_get_state(struct au8522_state **state, struct i2c_adapter *i2c, + u8 client_address); +void au8522_release_state(struct au8522_state *state); -- cgit v1.2.3 From 23e405c74fb529c9afc894ebc22d2b289a78628f Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Wed, 11 Mar 2009 02:00:38 -0400 Subject: au8522: add support for analog side of demodulator From: Devin Heitmueller Add support for the analog functionality in the au8522 analog/digital demodulator Thanks to Michael Krufky and Steven Toth for providing sample hardware, engineering level support, and testing. Priority: normal Signed-off-by: Devin Heitmueller Signed-off-by: Michael Krufky --- linux/drivers/media/dvb/frontends/Makefile | 2 +- linux/drivers/media/dvb/frontends/au8522.h | 16 + linux/drivers/media/dvb/frontends/au8522_priv.h | 347 ++++++++++ linux/drivers/media/video/au8522_decoder.c | 844 ++++++++++++++++++++++++ 4 files changed, 1208 insertions(+), 1 deletion(-) create mode 100644 linux/drivers/media/video/au8522_decoder.c (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/frontends/Makefile b/linux/drivers/media/dvb/frontends/Makefile index fa3ab69f7..cffe25e2a 100644 --- a/linux/drivers/media/dvb/frontends/Makefile +++ b/linux/drivers/media/dvb/frontends/Makefile @@ -8,7 +8,7 @@ EXTRA_CFLAGS += -Idrivers/media/common/tuners/ s921-objs := s921_module.o s921_core.o stb0899-objs = stb0899_drv.o stb0899_algo.o stv0900-objs = stv0900_core.o stv0900_sw.o -au8522-objs = au8522_dig.o +au8522-objs = au8522_dig.o au8522_decoder.o obj-$(CONFIG_DVB_PLL) += dvb-pll.o obj-$(CONFIG_DVB_STV0299) += stv0299.o diff --git a/linux/drivers/media/dvb/frontends/au8522.h b/linux/drivers/media/dvb/frontends/au8522.h index 7b94f554a..565dcf31a 100644 --- a/linux/drivers/media/dvb/frontends/au8522.h +++ b/linux/drivers/media/dvb/frontends/au8522.h @@ -74,6 +74,22 @@ struct dvb_frontend *au8522_attach(const struct au8522_config *config, } #endif /* CONFIG_DVB_AU8522 */ +/* Other modes may need to be added later */ +enum au8522_video_input { + AU8522_COMPOSITE_CH1 = 1, + AU8522_COMPOSITE_CH2, + AU8522_COMPOSITE_CH3, + AU8522_COMPOSITE_CH4, + AU8522_COMPOSITE_CH4_SIF, + AU8522_SVIDEO_CH13, + AU8522_SVIDEO_CH24, +}; + +enum au8522_audio_input { + AU8522_AUDIO_NONE, + AU8522_AUDIO_SIF, +}; + #endif /* __AU8522_H__ */ /* diff --git a/linux/drivers/media/dvb/frontends/au8522_priv.h b/linux/drivers/media/dvb/frontends/au8522_priv.h index 98b09caa2..f328f2b3a 100644 --- a/linux/drivers/media/dvb/frontends/au8522_priv.h +++ b/linux/drivers/media/dvb/frontends/au8522_priv.h @@ -35,6 +35,7 @@ #include "tuner-i2c.h" struct au8522_state { + struct i2c_client *c; struct i2c_adapter *i2c; /* Used for sharing of the state between analog and digital mode */ @@ -51,6 +52,16 @@ struct au8522_state { u32 fe_status; unsigned int led_state; + + /* Analog settings */ + struct v4l2_subdev sd; + v4l2_std_id std; + int vid_input; + int aud_input; + u32 id; + u32 rev; + u8 brightness; + u8 contrast; }; /* These are routines shared by both the VSB/QAM demodulator and the analog @@ -63,3 +74,339 @@ int au8522_sleep(struct dvb_frontend *fe); int au8522_get_state(struct au8522_state **state, struct i2c_adapter *i2c, u8 client_address); void au8522_release_state(struct au8522_state *state); + +/* REGISTERS */ +#define AU8522_INPUT_CONTROL_REG081H 0x081 +#define AU8522_PGA_CONTROL_REG082H 0x082 +#define AU8522_CLAMPING_CONTROL_REG083H 0x083 + +#define AU8522_MODULE_CLOCK_CONTROL_REG0A3H 0x0A3 +#define AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H 0x0A4 +#define AU8522_SYSTEM_MODULE_CONTROL_1_REG0A5H 0x0A5 +#define AU8522_AGC_CONTROL_RANGE_REG0A6H 0x0A6 +#define AU8522_SYSTEM_GAIN_CONTROL_REG0A7H 0x0A7 +#define AU8522_TUNER_AGC_RF_STOP_REG0A8H 0x0A8 +#define AU8522_TUNER_AGC_RF_START_REG0A9H 0x0A9 +#define AU8522_TUNER_RF_AGC_DEFAULT_REG0AAH 0x0AA +#define AU8522_TUNER_AGC_IF_STOP_REG0ABH 0x0AB +#define AU8522_TUNER_AGC_IF_START_REG0ACH 0x0AC +#define AU8522_TUNER_AGC_IF_DEFAULT_REG0ADH 0x0AD +#define AU8522_TUNER_AGC_STEP_REG0AEH 0x0AE +#define AU8522_TUNER_GAIN_STEP_REG0AFH 0x0AF + +/* Receiver registers */ +#define AU8522_FRMREGTHRD1_REG0B0H 0x0B0 +#define AU8522_FRMREGAGC1H_REG0B1H 0x0B1 +#define AU8522_FRMREGSHIFT1_REG0B2H 0x0B2 +#define AU8522_TOREGAGC1_REG0B3H 0x0B3 +#define AU8522_TOREGASHIFT1_REG0B4H 0x0B4 +#define AU8522_FRMREGBBH_REG0B5H 0x0B5 +#define AU8522_FRMREGBBM_REG0B6H 0x0B6 +#define AU8522_FRMREGBBL_REG0B7H 0x0B7 +/* 0xB8 TO 0xD7 are the filter coefficients */ +#define AU8522_FRMREGTHRD2_REG0D8H 0x0D8 +#define AU8522_FRMREGAGC2H_REG0D9H 0x0D9 +#define AU8522_TOREGAGC2_REG0DAH 0x0DA +#define AU8522_TOREGSHIFT2_REG0DBH 0x0DB +#define AU8522_FRMREGPILOTH_REG0DCH 0x0DC +#define AU8522_FRMREGPILOTM_REG0DDH 0x0DD +#define AU8522_FRMREGPILOTL_REG0DEH 0x0DE +#define AU8522_TOREGFREQ_REG0DFH 0x0DF + +#define AU8522_RX_PGA_RFOUT_REG0EBH 0x0EB +#define AU8522_RX_PGA_IFOUT_REG0ECH 0x0EC +#define AU8522_RX_PGA_PGAOUT_REG0EDH 0x0ED + +#define AU8522_CHIP_MODE_REG0FEH 0x0FE + +/* I2C bus control registers */ +#define AU8522_I2C_CONTROL_REG0_REG090H 0x090 +#define AU8522_I2C_CONTROL_REG1_REG091H 0x091 +#define AU8522_I2C_STATUS_REG092H 0x092 +#define AU8522_I2C_WR_DATA0_REG093H 0x093 +#define AU8522_I2C_WR_DATA1_REG094H 0x094 +#define AU8522_I2C_WR_DATA2_REG095H 0x095 +#define AU8522_I2C_WR_DATA3_REG096H 0x096 +#define AU8522_I2C_WR_DATA4_REG097H 0x097 +#define AU8522_I2C_WR_DATA5_REG098H 0x098 +#define AU8522_I2C_WR_DATA6_REG099H 0x099 +#define AU8522_I2C_WR_DATA7_REG09AH 0x09A +#define AU8522_I2C_RD_DATA0_REG09BH 0x09B +#define AU8522_I2C_RD_DATA1_REG09CH 0x09C +#define AU8522_I2C_RD_DATA2_REG09DH 0x09D +#define AU8522_I2C_RD_DATA3_REG09EH 0x09E +#define AU8522_I2C_RD_DATA4_REG09FH 0x09F +#define AU8522_I2C_RD_DATA5_REG0A0H 0x0A0 +#define AU8522_I2C_RD_DATA6_REG0A1H 0x0A1 +#define AU8522_I2C_RD_DATA7_REG0A2H 0x0A2 + +#define AU8522_ENA_USB_REG101H 0x101 + +#define AU8522_I2S_CTRL_0_REG110H 0x110 +#define AU8522_I2S_CTRL_1_REG111H 0x111 +#define AU8522_I2S_CTRL_2_REG112H 0x112 + +#define AU8522_FRMREGFFECONTROL_REG121H 0x121 +#define AU8522_FRMREGDFECONTROL_REG122H 0x122 + +#define AU8522_CARRFREQOFFSET0_REG201H 0x201 +#define AU8522_CARRFREQOFFSET1_REG202H 0x202 + +#define AU8522_DECIMATION_GAIN_REG21AH 0x21A +#define AU8522_FRMREGIFSLP_REG21BH 0x21B +#define AU8522_FRMREGTHRDL2_REG21CH 0x21C +#define AU8522_FRMREGSTEP3DB_REG21DH 0x21D +#define AU8522_DAGC_GAIN_ADJUSTMENT_REG21EH 0x21E +#define AU8522_FRMREGPLLMODE_REG21FH 0x21F +#define AU8522_FRMREGCSTHRD_REG220H 0x220 +#define AU8522_FRMREGCRLOCKDMAX_REG221H 0x221 +#define AU8522_FRMREGCRPERIODMASK_REG222H 0x222 +#define AU8522_FRMREGCRLOCK0THH_REG223H 0x223 +#define AU8522_FRMREGCRLOCK1THH_REG224H 0x224 +#define AU8522_FRMREGCRLOCK0THL_REG225H 0x225 +#define AU8522_FRMREGCRLOCK1THL_REG226H 0x226 +#define AU_FRMREGPLLACQPHASESCL_REG227H 0x227 +#define AU8522_FRMREGFREQFBCTRL_REG228H 0x228 + +/* Analog TV Decoder */ +#define AU8522_TVDEC_STATUS_REG000H 0x000 +#define AU8522_TVDEC_INT_STATUS_REG001H 0x001 +#define AU8522_TVDEC_MACROVISION_STATUS_REG002H 0x002 +#define AU8522_TVDEC_SHARPNESSREG009H 0x009 +#define AU8522_TVDEC_BRIGHTNESS_REG00AH 0x00A +#define AU8522_TVDEC_CONTRAST_REG00BH 0x00B +#define AU8522_TVDEC_SATURATION_CB_REG00CH 0x00C +#define AU8522_TVDEC_SATURATION_CR_REG00DH 0x00D +#define AU8522_TVDEC_HUE_H_REG00EH 0x00E +#define AU8522_TVDEC_HUE_L_REG00FH 0x00F +#define AU8522_TVDEC_INT_MASK_REG010H 0x010 +#define AU8522_VIDEO_MODE_REG011H 0x011 +#define AU8522_TVDEC_PGA_REG012H 0x012 +#define AU8522_TVDEC_COMB_MODE_REG015H 0x015 +#define AU8522_REG016H 0x016 +#define AU8522_TVDED_DBG_MODE_REG060H 0x060 +#define AU8522_TVDEC_FORMAT_CTRL1_REG061H 0x061 +#define AU8522_TVDEC_FORMAT_CTRL2_REG062H 0x062 +#define AU8522_TVDEC_VCR_DET_LLIM_REG063H 0x063 +#define AU8522_TVDEC_VCR_DET_HLIM_REG064H 0x064 +#define AU8522_TVDEC_COMB_VDIF_THR1_REG065H 0x065 +#define AU8522_TVDEC_COMB_VDIF_THR2_REG066H 0x066 +#define AU8522_TVDEC_COMB_VDIF_THR3_REG067H 0x067 +#define AU8522_TVDEC_COMB_NOTCH_THR_REG068H 0x068 +#define AU8522_TVDEC_COMB_HDIF_THR1_REG069H 0x069 +#define AU8522_TVDEC_COMB_HDIF_THR2_REG06AH 0x06A +#define AU8522_TVDEC_COMB_HDIF_THR3_REG06BH 0x06B +#define AU8522_TVDEC_COMB_DCDIF_THR1_REG06CH 0x06C +#define AU8522_TVDEC_COMB_DCDIF_THR2_REG06DH 0x06D +#define AU8522_TVDEC_COMB_DCDIF_THR3_REG06EH 0x06E +#define AU8522_TVDEC_UV_SEP_THR_REG06FH 0x06F +#define AU8522_TVDEC_COMB_DC_THR1_NTSC_REG070H 0x070 +#define AU8522_TVDEC_COMB_DC_THR2_NTSC_REG073H 0x073 +#define AU8522_TVDEC_DCAGC_CTRL_REG077H 0x077 +#define AU8522_TVDEC_PIC_START_ADJ_REG078H 0x078 +#define AU8522_TVDEC_AGC_HIGH_LIMIT_REG079H 0x079 +#define AU8522_TVDEC_MACROVISION_SYNC_THR_REG07AH 0x07A +#define AU8522_TVDEC_INTRP_CTRL_REG07BH 0x07B +#define AU8522_TVDEC_PLL_STATUS_REG07EH 0x07E +#define AU8522_TVDEC_FSC_FREQ_REG07FH 0x07F + +#define AU8522_TVDEC_AGC_LOW_LIMIT_REG0E4H 0x0E4 +#define AU8522_TOREGAAGC_REG0E5H 0x0E5 + +#define AU8522_TVDEC_CHROMA_AGC_REG401H 0x401 +#define AU8522_TVDEC_CHROMA_SFT_REG402H 0x402 +#define AU8522_FILTER_COEF_R410 0x410 +#define AU8522_FILTER_COEF_R411 0x411 +#define AU8522_FILTER_COEF_R412 0x412 +#define AU8522_FILTER_COEF_R413 0x413 +#define AU8522_FILTER_COEF_R414 0x414 +#define AU8522_FILTER_COEF_R415 0x415 +#define AU8522_FILTER_COEF_R416 0x416 +#define AU8522_FILTER_COEF_R417 0x417 +#define AU8522_FILTER_COEF_R418 0x418 +#define AU8522_FILTER_COEF_R419 0x419 +#define AU8522_FILTER_COEF_R41A 0x41A +#define AU8522_FILTER_COEF_R41B 0x41B +#define AU8522_FILTER_COEF_R41C 0x41C +#define AU8522_FILTER_COEF_R41D 0x41D +#define AU8522_FILTER_COEF_R41E 0x41E +#define AU8522_FILTER_COEF_R41F 0x41F +#define AU8522_FILTER_COEF_R420 0x420 +#define AU8522_FILTER_COEF_R421 0x421 +#define AU8522_FILTER_COEF_R422 0x422 +#define AU8522_FILTER_COEF_R423 0x423 +#define AU8522_FILTER_COEF_R424 0x424 +#define AU8522_FILTER_COEF_R425 0x425 +#define AU8522_FILTER_COEF_R426 0x426 +#define AU8522_FILTER_COEF_R427 0x427 +#define AU8522_FILTER_COEF_R428 0x428 +#define AU8522_FILTER_COEF_R429 0x429 +#define AU8522_FILTER_COEF_R42A 0x42A +#define AU8522_FILTER_COEF_R42B 0x42B +#define AU8522_FILTER_COEF_R42C 0x42C +#define AU8522_FILTER_COEF_R42D 0x42D + +/* VBI Control Registers */ +#define AU8522_TVDEC_VBI_RX_FIFO_CONTAIN_REG004H 0x004 +#define AU8522_TVDEC_VBI_TX_FIFO_CONTAIN_REG005H 0x005 +#define AU8522_TVDEC_VBI_RX_FIFO_READ_REG006H 0x006 +#define AU8522_TVDEC_VBI_FIFO_STATUS_REG007H 0x007 +#define AU8522_TVDEC_VBI_CTRL_H_REG017H 0x017 +#define AU8522_TVDEC_VBI_CTRL_L_REG018H 0x018 +#define AU8522_TVDEC_VBI_USER_TOTAL_BITS_REG019H 0x019 +#define AU8522_TVDEC_VBI_USER_TUNIT_H_REG01AH 0x01A +#define AU8522_TVDEC_VBI_USER_TUNIT_L_REG01BH 0x01B +#define AU8522_TVDEC_VBI_USER_THRESH1_REG01CH 0x01C +#define AU8522_TVDEC_VBI_USER_FRAME_PAT2_REG01EH 0x01E +#define AU8522_TVDEC_VBI_USER_FRAME_PAT1_REG01FH 0x01F +#define AU8522_TVDEC_VBI_USER_FRAME_PAT0_REG020H 0x020 +#define AU8522_TVDEC_VBI_USER_FRAME_MASK2_REG021H 0x021 +#define AU8522_TVDEC_VBI_USER_FRAME_MASK1_REG022H 0x022 +#define AU8522_TVDEC_VBI_USER_FRAME_MASK0_REG023H 0x023 + +#define AU8522_REG071H 0x071 +#define AU8522_REG072H 0x072 +#define AU8522_REG074H 0x074 +#define AU8522_REG075H 0x075 + +/* Digital Demodulator Registers */ +#define AU8522_FRAME_COUNT0_REG084H 0x084 +#define AU8522_RS_STATUS_G0_REG085H 0x085 +#define AU8522_RS_STATUS_B0_REG086H 0x086 +#define AU8522_RS_STATUS_E_REG087H 0x087 +#define AU8522_DEMODULATION_STATUS_REG088H 0x088 +#define AU8522_TOREGTRESTATUS_REG0E6H 0x0E6 +#define AU8522_TSPORT_CONTROL_REG10BH 0x10B +#define AU8522_TSTHES_REG10CH 0x10C +#define AU8522_FRMREGDFEKEEP_REG301H 0x301 +#define AU8522_DFE_AVERAGE_REG302H 0x302 +#define AU8522_FRMREGEQLERRWIN_REG303H 0x303 +#define AU8522_FRMREGFFEKEEP_REG304H 0x304 +#define AU8522_FRMREGDFECONTROL1_REG305H 0x305 +#define AU8522_FRMREGEQLERRLOW_REG306H 0x306 + +#define AU8522_REG42EH 0x42E +#define AU8522_REG42FH 0x42F +#define AU8522_REG430H 0x430 +#define AU8522_REG431H 0x431 +#define AU8522_REG432H 0x432 +#define AU8522_REG433H 0x433 +#define AU8522_REG434H 0x434 +#define AU8522_REG435H 0x435 +#define AU8522_REG436H 0x436 + +/* GPIO Registers */ +#define AU8522_GPIO_CONTROL_REG0E0H 0x0E0 +#define AU8522_GPIO_STATUS_REG0E1H 0x0E1 +#define AU8522_GPIO_DATA_REG0E2H 0x0E2 + +/* Audio Control Registers */ +#define AU8522_AUDIOAGC_REG0EEH 0x0EE +#define AU8522_AUDIO_STATUS_REG0F0H 0x0F0 +#define AU8522_AUDIO_MODE_REG0F1H 0x0F1 +#define AU8522_AUDIO_VOLUME_L_REG0F2H 0x0F2 +#define AU8522_AUDIO_VOLUME_R_REG0F3H 0x0F3 +#define AU8522_AUDIO_VOLUME_REG0F4H 0x0F4 +#define AU8522_FRMREGAUPHASE_REG0F7H 0x0F7 +#define AU8522_REG0F9H 0x0F9 + +#define AU8522_AUDIOAGC2_REG605H 0x605 +#define AU8522_AUDIOFREQ_REG606H 0x606 + + +/**************************************************************/ + +#define AU8522_INPUT_CONTROL_REG081H_ATSC 0xC4 +#define AU8522_INPUT_CONTROL_REG081H_ATVRF 0xC4 +#define AU8522_INPUT_CONTROL_REG081H_ATVRF13 0xC4 +#define AU8522_INPUT_CONTROL_REG081H_J83B64 0xC4 +#define AU8522_INPUT_CONTROL_REG081H_J83B256 0xC4 +#define AU8522_INPUT_CONTROL_REG081H_CVBS 0x20 +#define AU8522_INPUT_CONTROL_REG081H_CVBS_CH1 0xA2 +#define AU8522_INPUT_CONTROL_REG081H_CVBS_CH2 0xA0 +#define AU8522_INPUT_CONTROL_REG081H_CVBS_CH3 0x69 +#define AU8522_INPUT_CONTROL_REG081H_CVBS_CH4 0x68 +#define AU8522_INPUT_CONTROL_REG081H_CVBS_CH4_SIF 0x28 +/* CH1 AS Y,CH3 AS C */ +#define AU8522_INPUT_CONTROL_REG081H_SVIDEO_CH13 0x23 +/* CH2 AS Y,CH4 AS C */ +#define AU8522_INPUT_CONTROL_REG081H_SVIDEO_CH24 0x20 +#define AU8522_MODULE_CLOCK_CONTROL_REG0A3H_ATSC 0x0C +#define AU8522_MODULE_CLOCK_CONTROL_REG0A3H_J83B64 0x09 +#define AU8522_MODULE_CLOCK_CONTROL_REG0A3H_J83B256 0x09 +#define AU8522_MODULE_CLOCK_CONTROL_REG0A3H_CVBS 0x12 +#define AU8522_MODULE_CLOCK_CONTROL_REG0A3H_ATVRF 0x1A +#define AU8522_MODULE_CLOCK_CONTROL_REG0A3H_ATVRF13 0x1A +#define AU8522_MODULE_CLOCK_CONTROL_REG0A3H_SVIDEO 0x02 + +#define AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H_CLEAR 0x00 +#define AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H_SVIDEO 0x9C +#define AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H_CVBS 0x9D +#define AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H_ATSC 0xE8 +#define AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H_J83B256 0xCA +#define AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H_J83B64 0xCA +#define AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H_ATVRF 0xDD +#define AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H_ATVRF13 0xDD +#define AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H_PAL 0xDD +#define AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H_FM 0xDD + +#define AU8522_SYSTEM_MODULE_CONTROL_1_REG0A5H_ATSC 0x80 +#define AU8522_SYSTEM_MODULE_CONTROL_1_REG0A5H_J83B256 0x80 +#define AU8522_SYSTEM_MODULE_CONTROL_1_REG0A5H_J83B64 0x80 +#define AU8522_SYSTEM_MODULE_CONTROL_1_REG0A5H_DONGLE_ATSC 0x40 +#define AU8522_SYSTEM_MODULE_CONTROL_1_REG0A5H_DONGLE_J83B256 0x40 +#define AU8522_SYSTEM_MODULE_CONTROL_1_REG0A5H_DONGLE_J83B64 0x40 +#define AU8522_SYSTEM_MODULE_CONTROL_1_REG0A5H_DONGLE_CLEAR 0x00 +#define AU8522_SYSTEM_MODULE_CONTROL_1_REG0A5H_ATVRF 0x01 +#define AU8522_SYSTEM_MODULE_CONTROL_1_REG0A5H_ATVRF13 0x01 +#define AU8522_SYSTEM_MODULE_CONTROL_1_REG0A5H_SVIDEO 0x04 +#define AU8522_SYSTEM_MODULE_CONTROL_1_REG0A5H_CVBS 0x01 +#define AU8522_SYSTEM_MODULE_CONTROL_1_REG0A5H_PWM 0x03 +#define AU8522_SYSTEM_MODULE_CONTROL_1_REG0A5H_IIS 0x09 +#define AU8522_SYSTEM_MODULE_CONTROL_1_REG0A5H_PAL 0x01 +#define AU8522_SYSTEM_MODULE_CONTROL_1_REG0A5H_FM 0x01 + +/* STILL NEED TO BE REFACTORED @@@@@@@@@@@@@@ */ +#define AU8522_TVDEC_CONTRAST_REG00BH_CVBS 0x79 +#define AU8522_TVDEC_SATURATION_CB_REG00CH_CVBS 0x80 +#define AU8522_TVDEC_SATURATION_CR_REG00DH_CVBS 0x80 +#define AU8522_TVDEC_HUE_H_REG00EH_CVBS 0x00 +#define AU8522_TVDEC_HUE_L_REG00FH_CVBS 0x00 +#define AU8522_TVDEC_PGA_REG012H_CVBS 0x0F +#define AU8522_TVDEC_COMB_MODE_REG015H_CVBS 0x00 +#define AU8522_REG016H_CVBS 0x00 +#define AU8522_TVDED_DBG_MODE_REG060H_CVBS 0x00 +#define AU8522_TVDEC_FORMAT_CTRL1_REG061H_CVBS 0x0B +#define AU8522_TVDEC_FORMAT_CTRL1_REG061H_CVBS13 0x03 +#define AU8522_TVDEC_FORMAT_CTRL2_REG062H_CVBS13 0x00 +#define AU8522_TVDEC_VCR_DET_LLIM_REG063H_CVBS 0x19 +#define AU8522_REG0F9H_AUDIO 0x20 +#define AU8522_TVDEC_VCR_DET_HLIM_REG064H_CVBS 0xA7 +#define AU8522_TVDEC_COMB_VDIF_THR1_REG065H_CVBS 0x0A +#define AU8522_TVDEC_COMB_VDIF_THR2_REG066H_CVBS 0x32 +#define AU8522_TVDEC_COMB_VDIF_THR3_REG067H_CVBS 0x19 +#define AU8522_TVDEC_COMB_NOTCH_THR_REG068H_CVBS 0x23 +#define AU8522_TVDEC_COMB_HDIF_THR1_REG069H_CVBS 0x41 +#define AU8522_TVDEC_COMB_HDIF_THR2_REG06AH_CVBS 0x0A +#define AU8522_TVDEC_COMB_HDIF_THR3_REG06BH_CVBS 0x32 +#define AU8522_TVDEC_COMB_DCDIF_THR1_REG06CH_CVBS 0x34 +#define AU8522_TVDEC_COMB_DCDIF_THR2_REG06DH_CVBS 0x05 +#define AU8522_TVDEC_COMB_DCDIF_THR3_REG06EH_CVBS 0x6E +#define AU8522_TVDEC_UV_SEP_THR_REG06FH_CVBS 0x0F +#define AU8522_TVDEC_COMB_DC_THR1_NTSC_REG070H_CVBS 0x80 +#define AU8522_REG071H_CVBS 0x18 +#define AU8522_REG072H_CVBS 0x30 +#define AU8522_TVDEC_COMB_DC_THR2_NTSC_REG073H_CVBS 0xF0 +#define AU8522_REG074H_CVBS 0x80 +#define AU8522_REG075H_CVBS 0xF0 +#define AU8522_TVDEC_DCAGC_CTRL_REG077H_CVBS 0xFB +#define AU8522_TVDEC_PIC_START_ADJ_REG078H_CVBS 0x04 +#define AU8522_TVDEC_AGC_HIGH_LIMIT_REG079H_CVBS 0x00 +#define AU8522_TVDEC_MACROVISION_SYNC_THR_REG07AH_CVBS 0x00 +#define AU8522_TVDEC_INTRP_CTRL_REG07BH_CVBS 0xEE +#define AU8522_TVDEC_AGC_LOW_LIMIT_REG0E4H_CVBS 0xFE +#define AU8522_TOREGAAGC_REG0E5H_CVBS 0x00 +#define AU8522_TVDEC_VBI6A_REG035H_CVBS 0x40 + +/* Enables Closed captioning */ +#define AU8522_TVDEC_VBI_CTRL_H_REG017H_CCON 0x21 diff --git a/linux/drivers/media/video/au8522_decoder.c b/linux/drivers/media/video/au8522_decoder.c new file mode 100644 index 000000000..556b012fc --- /dev/null +++ b/linux/drivers/media/video/au8522_decoder.c @@ -0,0 +1,844 @@ +/* + * Auvitek AU8522 QAM/8VSB demodulator driver and video decoder + * + * Copyright (C) 2009 Devin Heitmueller + * Copyright (C) 2005-2008 Auvitek International, Ltd. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * As published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +/* Developer notes: + * + * VBI support is not yet working + * Saturation and hue setting are not yet working + * Enough is implemented here for CVBS and S-Video inputs, but the actual + * analog demodulator code isn't implemented (not needed for xc5000 since it + * has its own demodulator and outputs CVBS) + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "compat.h" +#include "au8522.h" +#include "au8522_priv.h" + +MODULE_AUTHOR("Devin Heitmueller"); +MODULE_LICENSE("GPL"); + +static int au8522_analog_debug; + +static unsigned short normal_i2c[] = { 0x8e >> 1, I2C_CLIENT_END }; + +module_param_named(analog_debug, au8522_analog_debug, int, 0644); + +MODULE_PARM_DESC(analog_debug, + "Analog debugging messages [0=Off (default) 1=On]"); + +I2C_CLIENT_INSMOD; + +struct au8522_register_config { + u16 reg_name; + u8 reg_val[8]; +}; + + +/* Video Decoder Filter Coefficients + The values are as follows from left to right + 0="ATV RF" 1="ATV RF13" 2="CVBS" 3="S-Video" 4="PAL" 5=CVBS13" 6="SVideo13" +*/ +struct au8522_register_config filter_coef[] = { + {AU8522_FILTER_COEF_R410, {0x25, 0x00, 0x25, 0x25, 0x00, 0x00, 0x00}}, + {AU8522_FILTER_COEF_R411, {0x20, 0x00, 0x20, 0x20, 0x00, 0x00, 0x00}}, + {AU8522_FILTER_COEF_R412, {0x03, 0x00, 0x03, 0x03, 0x00, 0x00, 0x00}}, + {AU8522_FILTER_COEF_R413, {0xe6, 0x00, 0xe6, 0xe6, 0x00, 0x00, 0x00}}, + {AU8522_FILTER_COEF_R414, {0x40, 0x00, 0x40, 0x40, 0x00, 0x00, 0x00}}, + {AU8522_FILTER_COEF_R415, {0x1b, 0x00, 0x1b, 0x1b, 0x00, 0x00, 0x00}}, + {AU8522_FILTER_COEF_R416, {0xc0, 0x00, 0xc0, 0x04, 0x00, 0x00, 0x00}}, + {AU8522_FILTER_COEF_R417, {0x04, 0x00, 0x04, 0x04, 0x00, 0x00, 0x00}}, + {AU8522_FILTER_COEF_R418, {0x8c, 0x00, 0x8c, 0x8c, 0x00, 0x00, 0x00}}, + {AU8522_FILTER_COEF_R419, {0xa0, 0x40, 0xa0, 0xa0, 0x40, 0x40, 0x40}}, + {AU8522_FILTER_COEF_R41A, {0x21, 0x09, 0x21, 0x21, 0x09, 0x09, 0x09}}, + {AU8522_FILTER_COEF_R41B, {0x6c, 0x38, 0x6c, 0x6c, 0x38, 0x38, 0x38}}, + {AU8522_FILTER_COEF_R41C, {0x03, 0xff, 0x03, 0x03, 0xff, 0xff, 0xff}}, + {AU8522_FILTER_COEF_R41D, {0xbf, 0xc7, 0xbf, 0xbf, 0xc7, 0xc7, 0xc7}}, + {AU8522_FILTER_COEF_R41E, {0xa0, 0xdf, 0xa0, 0xa0, 0xdf, 0xdf, 0xdf}}, + {AU8522_FILTER_COEF_R41F, {0x10, 0x06, 0x10, 0x10, 0x06, 0x06, 0x06}}, + {AU8522_FILTER_COEF_R420, {0xae, 0x30, 0xae, 0xae, 0x30, 0x30, 0x30}}, + {AU8522_FILTER_COEF_R421, {0xc4, 0x01, 0xc4, 0xc4, 0x01, 0x01, 0x01}}, + {AU8522_FILTER_COEF_R422, {0x54, 0xdd, 0x54, 0x54, 0xdd, 0xdd, 0xdd}}, + {AU8522_FILTER_COEF_R423, {0xd0, 0xaf, 0xd0, 0xd0, 0xaf, 0xaf, 0xaf}}, + {AU8522_FILTER_COEF_R424, {0x1c, 0xf7, 0x1c, 0x1c, 0xf7, 0xf7, 0xf7}}, + {AU8522_FILTER_COEF_R425, {0x76, 0xdb, 0x76, 0x76, 0xdb, 0xdb, 0xdb}}, + {AU8522_FILTER_COEF_R426, {0x61, 0xc0, 0x61, 0x61, 0xc0, 0xc0, 0xc0}}, + {AU8522_FILTER_COEF_R427, {0xd1, 0x2f, 0xd1, 0xd1, 0x2f, 0x2f, 0x2f}}, + {AU8522_FILTER_COEF_R428, {0x84, 0xd8, 0x84, 0x84, 0xd8, 0xd8, 0xd8}}, + {AU8522_FILTER_COEF_R429, {0x06, 0xfb, 0x06, 0x06, 0xfb, 0xfb, 0xfb}}, + {AU8522_FILTER_COEF_R42A, {0x21, 0xd5, 0x21, 0x21, 0xd5, 0xd5, 0xd5}}, + {AU8522_FILTER_COEF_R42B, {0x0a, 0x3e, 0x0a, 0x0a, 0x3e, 0x3e, 0x3e}}, + {AU8522_FILTER_COEF_R42C, {0xe6, 0x15, 0xe6, 0xe6, 0x15, 0x15, 0x15}}, + {AU8522_FILTER_COEF_R42D, {0x01, 0x34, 0x01, 0x01, 0x34, 0x34, 0x34}}, + +}; +#define NUM_FILTER_COEF (sizeof (filter_coef) / sizeof(struct au8522_register_config)) + + +/* Registers 0x060b through 0x0652 are the LP Filter coefficients + The values are as follows from left to right + 0="SIF" 1="ATVRF/ATVRF13" + Note: the "ATVRF/ATVRF13" mode has never been tested +*/ +struct au8522_register_config lpfilter_coef[] = { + {0x060b, {0x21, 0x0b}}, + {0x060c, {0xad, 0xad}}, + {0x060d, {0x70, 0xf0}}, + {0x060e, {0xea, 0xe9}}, + {0x060f, {0xdd, 0xdd}}, + {0x0610, {0x08, 0x64}}, + {0x0611, {0x60, 0x60}}, + {0x0612, {0xf8, 0xb2}}, + {0x0613, {0x01, 0x02}}, + {0x0614, {0xe4, 0xb4}}, + {0x0615, {0x19, 0x02}}, + {0x0616, {0xae, 0x2e}}, + {0x0617, {0xee, 0xc5}}, + {0x0618, {0x56, 0x56}}, + {0x0619, {0x30, 0x58}}, + {0x061a, {0xf9, 0xf8}}, + {0x061b, {0x24, 0x64}}, + {0x061c, {0x07, 0x07}}, + {0x061d, {0x30, 0x30}}, + {0x061e, {0xa9, 0xed}}, + {0x061f, {0x09, 0x0b}}, + {0x0620, {0x42, 0xc2}}, + {0x0621, {0x1d, 0x2a}}, + {0x0622, {0xd6, 0x56}}, + {0x0623, {0x95, 0x8b}}, + {0x0624, {0x2b, 0x2b}}, + {0x0625, {0x30, 0x24}}, + {0x0626, {0x3e, 0x3e}}, + {0x0627, {0x62, 0xe2}}, + {0x0628, {0xe9, 0xf5}}, + {0x0629, {0x99, 0x19}}, + {0x062a, {0xd4, 0x11}}, + {0x062b, {0x03, 0x04}}, + {0x062c, {0xb5, 0x85}}, + {0x062d, {0x1e, 0x20}}, + {0x062e, {0x2a, 0xea}}, + {0x062f, {0xd7, 0xd2}}, + {0x0630, {0x15, 0x15}}, + {0x0631, {0xa3, 0xa9}}, + {0x0632, {0x1f, 0x1f}}, + {0x0633, {0xf9, 0xd1}}, + {0x0634, {0xc0, 0xc3}}, + {0x0635, {0x4d, 0x8d}}, + {0x0636, {0x21, 0x31}}, + {0x0637, {0x83, 0x83}}, + {0x0638, {0x08, 0x8c}}, + {0x0639, {0x19, 0x19}}, + {0x063a, {0x45, 0xa5}}, + {0x063b, {0xef, 0xec}}, + {0x063c, {0x8a, 0x8a}}, + {0x063d, {0xf4, 0xf6}}, + {0x063e, {0x8f, 0x8f}}, + {0x063f, {0x44, 0x0c}}, + {0x0640, {0xef, 0xf0}}, + {0x0641, {0x66, 0x66}}, + {0x0642, {0xcc, 0xd2}}, + {0x0643, {0x41, 0x41}}, + {0x0644, {0x63, 0x93}}, + {0x0645, {0x8e, 0x8e}}, + {0x0646, {0xa2, 0x42}}, + {0x0647, {0x7b, 0x7b}}, + {0x0648, {0x04, 0x04}}, + {0x0649, {0x00, 0x00}}, + {0x064a, {0x40, 0x40}}, + {0x064b, {0x8c, 0x98}}, + {0x064c, {0x00, 0x00}}, + {0x064d, {0x63, 0xc3}}, + {0x064e, {0x04, 0x04}}, + {0x064f, {0x20, 0x20}}, + {0x0650, {0x00, 0x00}}, + {0x0651, {0x40 ,0x40}}, + {0x0652, {0x01, 0x01}}, +}; +#define NUM_LPFILTER_COEF (sizeof (lpfilter_coef) / sizeof(struct au8522_register_config)) + +static inline struct au8522_state *to_state(struct v4l2_subdev *sd) +{ + return container_of(sd, struct au8522_state, sd); +} + +static void setup_vbi(struct au8522_state *state, int aud_input) +{ + int i; + + /* These are set to zero regardless of what mode we're in */ + au8522_writereg(state, AU8522_TVDEC_VBI_CTRL_H_REG017H, 0x00); + au8522_writereg(state, AU8522_TVDEC_VBI_CTRL_L_REG018H, 0x00); + au8522_writereg(state, AU8522_TVDEC_VBI_USER_TOTAL_BITS_REG019H, 0x00); + au8522_writereg(state, AU8522_TVDEC_VBI_USER_TUNIT_H_REG01AH, 0x00); + au8522_writereg(state, AU8522_TVDEC_VBI_USER_TUNIT_L_REG01BH, 0x00); + au8522_writereg(state, AU8522_TVDEC_VBI_USER_THRESH1_REG01CH, 0x00); + au8522_writereg(state, AU8522_TVDEC_VBI_USER_FRAME_PAT2_REG01EH, 0x00); + au8522_writereg(state, AU8522_TVDEC_VBI_USER_FRAME_PAT1_REG01FH, 0x00); + au8522_writereg(state, AU8522_TVDEC_VBI_USER_FRAME_PAT0_REG020H, 0x00); + au8522_writereg(state, AU8522_TVDEC_VBI_USER_FRAME_MASK2_REG021H,0x00); + au8522_writereg(state, AU8522_TVDEC_VBI_USER_FRAME_MASK1_REG022H,0x00); + au8522_writereg(state, AU8522_TVDEC_VBI_USER_FRAME_MASK0_REG023H,0x00); + + /* Setup the VBI registers */ + for (i = 0x30; i < 0x60; i++) { + au8522_writereg(state, i, 0x40); + } + /* For some reason, every register is 0x40 except register 0x44 + (confirmed via the HVR-950q USB capture) */ + au8522_writereg(state, 0x44, 0x60); + + /* Enable VBI (we always do this regardless of whether the user is + viewing closed caption info) */ + au8522_writereg(state, AU8522_TVDEC_VBI_CTRL_H_REG017H, + AU8522_TVDEC_VBI_CTRL_H_REG017H_CCON); + +} + +static void setup_decoder_defaults(struct au8522_state *state, u8 input_mode) +{ + int i; + int filter_coef_type; + + /* Provide reasonable defaults for picture tuning values */ + au8522_writereg(state, AU8522_TVDEC_SHARPNESSREG009H, 0x07); + au8522_writereg(state, AU8522_TVDEC_BRIGHTNESS_REG00AH, 0xed); + state->brightness = 0xed - 128; + au8522_writereg(state, AU8522_TVDEC_CONTRAST_REG00BH, 0x79); + state->contrast = 0x79; + au8522_writereg(state, AU8522_TVDEC_SATURATION_CB_REG00CH, 0x80); + au8522_writereg(state, AU8522_TVDEC_SATURATION_CR_REG00DH, 0x80); + au8522_writereg(state, AU8522_TVDEC_HUE_H_REG00EH, 0x00); + au8522_writereg(state, AU8522_TVDEC_HUE_L_REG00FH, 0x00); + + /* Other decoder registers */ + au8522_writereg(state, AU8522_TVDEC_INT_MASK_REG010H, 0x00); + + if (input_mode == 0x23) { + /* S-Video input mapping */ + au8522_writereg(state, AU8522_VIDEO_MODE_REG011H, 0x04); + } else { + /* All other modes (CVBS/ATVRF etc.) */ + au8522_writereg(state, AU8522_VIDEO_MODE_REG011H, 0x00); + } + + au8522_writereg(state, AU8522_TVDEC_PGA_REG012H, + AU8522_TVDEC_PGA_REG012H_CVBS); + au8522_writereg(state, AU8522_TVDEC_COMB_MODE_REG015H, + AU8522_TVDEC_COMB_MODE_REG015H_CVBS); + au8522_writereg(state, AU8522_TVDED_DBG_MODE_REG060H, + AU8522_TVDED_DBG_MODE_REG060H_CVBS); + au8522_writereg(state, AU8522_TVDEC_FORMAT_CTRL1_REG061H, + AU8522_TVDEC_FORMAT_CTRL1_REG061H_CVBS13); + au8522_writereg(state, AU8522_TVDEC_FORMAT_CTRL2_REG062H, + AU8522_TVDEC_FORMAT_CTRL2_REG062H_CVBS13); + au8522_writereg(state, AU8522_TVDEC_VCR_DET_LLIM_REG063H, + AU8522_TVDEC_VCR_DET_LLIM_REG063H_CVBS); + au8522_writereg(state, AU8522_TVDEC_VCR_DET_HLIM_REG064H, + AU8522_TVDEC_VCR_DET_HLIM_REG064H_CVBS); + au8522_writereg(state, AU8522_TVDEC_COMB_VDIF_THR1_REG065H, + AU8522_TVDEC_COMB_VDIF_THR1_REG065H_CVBS); + au8522_writereg(state, AU8522_TVDEC_COMB_VDIF_THR2_REG066H, + AU8522_TVDEC_COMB_VDIF_THR2_REG066H_CVBS); + au8522_writereg(state, AU8522_TVDEC_COMB_VDIF_THR3_REG067H, + AU8522_TVDEC_COMB_VDIF_THR3_REG067H_CVBS); + au8522_writereg(state, AU8522_TVDEC_COMB_NOTCH_THR_REG068H, + AU8522_TVDEC_COMB_NOTCH_THR_REG068H_CVBS); + au8522_writereg(state, AU8522_TVDEC_COMB_HDIF_THR1_REG069H, + AU8522_TVDEC_COMB_HDIF_THR1_REG069H_CVBS); + au8522_writereg(state, AU8522_TVDEC_COMB_HDIF_THR2_REG06AH, + AU8522_TVDEC_COMB_HDIF_THR2_REG06AH_CVBS); + au8522_writereg(state, AU8522_TVDEC_COMB_HDIF_THR3_REG06BH, + AU8522_TVDEC_COMB_HDIF_THR3_REG06BH_CVBS); + au8522_writereg(state, AU8522_TVDEC_COMB_DCDIF_THR1_REG06CH, + AU8522_TVDEC_COMB_DCDIF_THR1_REG06CH_CVBS); + au8522_writereg(state, AU8522_TVDEC_COMB_DCDIF_THR2_REG06DH, + AU8522_TVDEC_COMB_DCDIF_THR2_REG06DH_CVBS); + au8522_writereg(state, AU8522_TVDEC_COMB_DCDIF_THR3_REG06EH, + AU8522_TVDEC_COMB_DCDIF_THR3_REG06EH_CVBS); + au8522_writereg(state, AU8522_TVDEC_UV_SEP_THR_REG06FH, + AU8522_TVDEC_UV_SEP_THR_REG06FH_CVBS); + au8522_writereg(state, AU8522_TVDEC_COMB_DC_THR1_NTSC_REG070H, + AU8522_TVDEC_COMB_DC_THR1_NTSC_REG070H_CVBS); + au8522_writereg(state, AU8522_REG071H, AU8522_REG071H_CVBS); + au8522_writereg(state, AU8522_REG072H, AU8522_REG072H_CVBS); + au8522_writereg(state, AU8522_TVDEC_COMB_DC_THR2_NTSC_REG073H, + AU8522_TVDEC_COMB_DC_THR2_NTSC_REG073H_CVBS); + au8522_writereg(state, AU8522_REG074H, AU8522_REG074H_CVBS); + au8522_writereg(state, AU8522_REG075H, AU8522_REG075H_CVBS); + au8522_writereg(state, AU8522_TVDEC_DCAGC_CTRL_REG077H, + AU8522_TVDEC_DCAGC_CTRL_REG077H_CVBS); + au8522_writereg(state, AU8522_TVDEC_PIC_START_ADJ_REG078H, + AU8522_TVDEC_PIC_START_ADJ_REG078H_CVBS); + au8522_writereg(state, AU8522_TVDEC_AGC_HIGH_LIMIT_REG079H, + AU8522_TVDEC_AGC_HIGH_LIMIT_REG079H_CVBS); + au8522_writereg(state, AU8522_TVDEC_MACROVISION_SYNC_THR_REG07AH, + AU8522_TVDEC_MACROVISION_SYNC_THR_REG07AH_CVBS); + au8522_writereg(state, AU8522_TVDEC_INTRP_CTRL_REG07BH, + AU8522_TVDEC_INTRP_CTRL_REG07BH_CVBS); + au8522_writereg(state, AU8522_TVDEC_AGC_LOW_LIMIT_REG0E4H, + AU8522_TVDEC_AGC_LOW_LIMIT_REG0E4H_CVBS); + au8522_writereg(state, AU8522_TOREGAAGC_REG0E5H, + AU8522_TOREGAAGC_REG0E5H_CVBS); + au8522_writereg(state, AU8522_REG016H, AU8522_REG016H_CVBS); + + setup_vbi(state, 0); + + if (input_mode == AU8522_INPUT_CONTROL_REG081H_SVIDEO_CH13 || + input_mode == AU8522_INPUT_CONTROL_REG081H_SVIDEO_CH24) { + /* Despite what the table says, for the HVR-950q we still need + to be in CVBS mode for the S-Video input (reason uknown). */ + /* filter_coef_type = 3; */ + filter_coef_type = 5; + } else { + filter_coef_type = 5; + } + + /* Load the Video Decoder Filter Coefficients */ + for (i = 0; i < NUM_FILTER_COEF; i++) { + au8522_writereg(state, filter_coef[i].reg_name, + filter_coef[i].reg_val[filter_coef_type]); + } + + /* It's not clear what these registers are for, but they are always + set to the same value regardless of what mode we're in */ + au8522_writereg(state, AU8522_REG42EH, 0x87); + au8522_writereg(state, AU8522_REG42FH, 0xa2); + au8522_writereg(state, AU8522_REG430H, 0xbf); + au8522_writereg(state, AU8522_REG431H, 0xcb); + au8522_writereg(state, AU8522_REG432H, 0xa1); + au8522_writereg(state, AU8522_REG433H, 0x41); + au8522_writereg(state, AU8522_REG434H, 0x88); + au8522_writereg(state, AU8522_REG435H, 0xc2); + au8522_writereg(state, AU8522_REG436H, 0x3c); +} + +static void au8522_setup_cvbs_mode(struct au8522_state *state) +{ + /* here we're going to try the pre-programmed route */ + au8522_writereg(state, AU8522_MODULE_CLOCK_CONTROL_REG0A3H, + AU8522_MODULE_CLOCK_CONTROL_REG0A3H_CVBS); + + au8522_writereg(state, AU8522_PGA_CONTROL_REG082H, 0x00); + au8522_writereg(state, AU8522_CLAMPING_CONTROL_REG083H, 0x0e); + au8522_writereg(state, AU8522_PGA_CONTROL_REG082H, 0x10); + + au8522_writereg(state, AU8522_INPUT_CONTROL_REG081H, + AU8522_INPUT_CONTROL_REG081H_CVBS_CH1); + + setup_decoder_defaults(state, AU8522_INPUT_CONTROL_REG081H_CVBS_CH1); + + au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H, + AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H_CVBS); +} + +static void au8522_setup_cvbs_tuner_mode(struct au8522_state *state) +{ + /* here we're going to try the pre-programmed route */ + au8522_writereg(state, AU8522_MODULE_CLOCK_CONTROL_REG0A3H, + AU8522_MODULE_CLOCK_CONTROL_REG0A3H_CVBS); + + /* It's not clear why they turn off the PGA before enabling the clamp + control, but the Windows trace does it so we will too... */ + au8522_writereg(state, AU8522_PGA_CONTROL_REG082H, 0x00); + + /* Enable clamping control */ + au8522_writereg(state, AU8522_CLAMPING_CONTROL_REG083H, 0x0e); + + /* Turn on the PGA */ + au8522_writereg(state, AU8522_PGA_CONTROL_REG082H, 0x10); + + /* Set input mode to CVBS on channel 4 with SIF audio input enabled */ + au8522_writereg(state, AU8522_INPUT_CONTROL_REG081H, + AU8522_INPUT_CONTROL_REG081H_CVBS_CH4_SIF); + + setup_decoder_defaults(state, + AU8522_INPUT_CONTROL_REG081H_CVBS_CH4_SIF); + + au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H, + AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H_CVBS); +} + +static void au8522_setup_svideo_mode(struct au8522_state *state) +{ + au8522_writereg(state, AU8522_MODULE_CLOCK_CONTROL_REG0A3H, + AU8522_MODULE_CLOCK_CONTROL_REG0A3H_SVIDEO); + + /* Set input to Y on Channe1, C on Channel 3 */ + au8522_writereg(state, AU8522_INPUT_CONTROL_REG081H, + AU8522_INPUT_CONTROL_REG081H_SVIDEO_CH13); + + /* Disable clamping control (required for S-video) */ + au8522_writereg(state, AU8522_CLAMPING_CONTROL_REG083H, 0x00); + + setup_decoder_defaults(state, + AU8522_INPUT_CONTROL_REG081H_SVIDEO_CH13); + + au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H, + AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H_CVBS); +} + +/* ----------------------------------------------------------------------- */ + +static void disable_audio_input(struct au8522_state *state) +{ + /* This can probably be optimized */ + au8522_writereg(state, AU8522_AUDIO_VOLUME_L_REG0F2H, 0x00); + au8522_writereg(state, AU8522_AUDIO_VOLUME_R_REG0F3H, 0x00); + au8522_writereg(state, AU8522_AUDIO_VOLUME_REG0F4H, 0x00); + au8522_writereg(state, AU8522_I2C_CONTROL_REG1_REG091H, 0x80); + au8522_writereg(state, AU8522_I2C_CONTROL_REG0_REG090H, 0x84); + + au8522_writereg(state, AU8522_ENA_USB_REG101H, 0x00); + au8522_writereg(state, AU8522_AUDIO_VOLUME_L_REG0F2H, 0x7F); + au8522_writereg(state, AU8522_AUDIO_VOLUME_R_REG0F3H, 0x7F); + au8522_writereg(state, AU8522_REG0F9H, AU8522_REG0F9H_AUDIO); + au8522_writereg(state, AU8522_AUDIO_MODE_REG0F1H, 0x40); + + au8522_writereg(state, AU8522_GPIO_DATA_REG0E2H, 0x11); + msleep(5); + au8522_writereg(state, AU8522_GPIO_DATA_REG0E2H, 0x00); + + au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_1_REG0A5H, 0x04); + au8522_writereg(state, AU8522_AUDIOFREQ_REG606H, 0x03); + au8522_writereg(state, AU8522_I2S_CTRL_2_REG112H, 0x02); + + au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H, + AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H_CVBS); +} + +/* 0=disable, 1=SIF */ +static void set_audio_input(struct au8522_state *state, int aud_input) +{ + int i; + + /* Note that this function needs to be used in conjunction with setting + the input routing via register 0x81 */ + + if (aud_input == AU8522_AUDIO_NONE) { + disable_audio_input(state); + return; + } + + if (aud_input != AU8522_AUDIO_SIF) { + /* The caller asked for a mode we don't currently support */ + printk("Unsupported audio mode requested! mode=%d\n", + aud_input); + return; + } + + /* Load the Audio Decoder Filter Coefficients */ + for (i = 0; i < NUM_LPFILTER_COEF; i++) { + au8522_writereg(state, lpfilter_coef[i].reg_name, + lpfilter_coef[i].reg_val[0]); + } + + /* Setup audio */ + au8522_writereg(state, AU8522_AUDIO_VOLUME_L_REG0F2H, 0x00); + au8522_writereg(state, AU8522_AUDIO_VOLUME_R_REG0F3H, 0x00); + au8522_writereg(state, AU8522_AUDIO_VOLUME_REG0F4H, 0x00); + au8522_writereg(state, AU8522_I2C_CONTROL_REG1_REG091H, 0x80); + au8522_writereg(state, AU8522_I2C_CONTROL_REG0_REG090H, 0x84); + msleep(150); + au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H, 0x00); + msleep(1); + au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H, 0x9d); + msleep(50); + au8522_writereg(state, AU8522_AUDIO_VOLUME_L_REG0F2H, 0x7F); + au8522_writereg(state, AU8522_AUDIO_VOLUME_R_REG0F3H, 0x7F); + au8522_writereg(state, AU8522_AUDIO_VOLUME_REG0F4H, 0xff); + msleep(80); + au8522_writereg(state, AU8522_AUDIO_VOLUME_L_REG0F2H, 0x7F); + au8522_writereg(state, AU8522_AUDIO_VOLUME_R_REG0F3H, 0x7F); + au8522_writereg(state, AU8522_REG0F9H, AU8522_REG0F9H_AUDIO); + au8522_writereg(state, AU8522_AUDIO_MODE_REG0F1H, 0x82); + msleep(70); + au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_1_REG0A5H, 0x09); + au8522_writereg(state, AU8522_AUDIOFREQ_REG606H, 0x03); + au8522_writereg(state, AU8522_I2S_CTRL_2_REG112H, 0xc2); +} + +/* ----------------------------------------------------------------------- */ + +static int au8522_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) +{ + struct au8522_state *state = to_state(sd); + + switch (ctrl->id) { + case V4L2_CID_BRIGHTNESS: + state->brightness = ctrl->value; + au8522_writereg(state, AU8522_TVDEC_BRIGHTNESS_REG00AH, + ctrl->value - 128); + break; + case V4L2_CID_CONTRAST: + state->contrast = ctrl->value; + au8522_writereg(state, AU8522_TVDEC_CONTRAST_REG00BH, + ctrl->value); + break; + case V4L2_CID_SATURATION: + case V4L2_CID_HUE: + case V4L2_CID_AUDIO_VOLUME: + case V4L2_CID_AUDIO_BASS: + case V4L2_CID_AUDIO_TREBLE: + case V4L2_CID_AUDIO_BALANCE: + case V4L2_CID_AUDIO_MUTE: + /* Not yet implemented */ + default: + return -EINVAL; + } + + return 0; +} + +static int au8522_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) +{ + struct au8522_state *state = to_state(sd); + + /* Note that we are using values cached in the state structure instead + of reading the registers due to issues with i2c reads not working + properly/consistently yet on the HVR-950q */ + + switch (ctrl->id) { + case V4L2_CID_BRIGHTNESS: + ctrl->value = state->brightness; + break; + case V4L2_CID_CONTRAST: + ctrl->value = state->contrast; + break; + case V4L2_CID_SATURATION: + case V4L2_CID_HUE: + case V4L2_CID_AUDIO_VOLUME: + case V4L2_CID_AUDIO_BASS: + case V4L2_CID_AUDIO_TREBLE: + case V4L2_CID_AUDIO_BALANCE: + case V4L2_CID_AUDIO_MUTE: + /* Not yet supported */ + default: + return -EINVAL; + } + + return 0; +} + +/* ----------------------------------------------------------------------- */ + +static int au8522_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) +{ + switch (fmt->type) { + default: + return -EINVAL; + } + return 0; +} + +static int au8522_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) +{ + switch (fmt->type) { + case V4L2_BUF_TYPE_VIDEO_CAPTURE: + /* Not yet implemented */ + break; + default: + return -EINVAL; + } + + return 0; +} + +/* ----------------------------------------------------------------------- */ + +#ifdef CONFIG_VIDEO_ADV_DEBUG +static int au8522_g_register(struct v4l2_subdev *sd, + struct v4l2_dbg_register *reg) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + struct au8522_state *state = to_state(sd); + + if (!v4l2_chip_match_i2c_client(client, ®->match)) + return -EINVAL; + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + reg->val = au8522_readreg(state, reg->reg & 0xffff); + return 0; +} + +static int au8522_s_register(struct v4l2_subdev *sd, + struct v4l2_dbg_register *reg) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + struct au8522_state *state = to_state(sd); + + if (!v4l2_chip_match_i2c_client(client, ®->match)) + return -EINVAL; + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + au8522_writereg(state, reg->reg, reg->val & 0xff); + return 0; +} +#endif + +static int au8522_s_stream(struct v4l2_subdev *sd, int enable) +{ + struct au8522_state *state = to_state(sd); + + if (enable) { + au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H, + 0x01); + msleep(1); + au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H, + AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H_CVBS); + } else { + /* This does not completely power down the device + (it only reduces it from around 140ma to 80ma) */ + au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H, + 1 << 5); + } + return 0; +} + +static int au8522_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc) +{ + switch (qc->id) { + case V4L2_CID_CONTRAST: + return v4l2_ctrl_query_fill(qc, 0, 255, 1, + AU8522_TVDEC_CONTRAST_REG00BH_CVBS); + case V4L2_CID_BRIGHTNESS: + return v4l2_ctrl_query_fill(qc, 0, 255, 1, 128); + case V4L2_CID_SATURATION: + case V4L2_CID_HUE: + /* Not yet implemented */ + default: + break; + } + + return -EINVAL; +} + +static int au8522_reset(struct v4l2_subdev *sd, u32 val) +{ + struct au8522_state *state = to_state(sd); + + au8522_writereg(state, 0xa4, 1 << 5); + + return 0; +} + +static int au8522_s_video_routing(struct v4l2_subdev *sd, + const struct v4l2_routing *route) +{ + struct au8522_state *state = to_state(sd); + + au8522_reset(sd, 0); + + /* Jam open the i2c gate to the tuner. We do this here to handle the + case where the user went into digital mode (causing the gate to be + closed), and then came back to analog mode */ + au8522_writereg(state, 0x106, 1); + + if (route->input == AU8522_COMPOSITE_CH1) { + au8522_setup_cvbs_mode(state); + } else if (route->input == AU8522_SVIDEO_CH13) { + au8522_setup_svideo_mode(state); + } else if (route->input == AU8522_COMPOSITE_CH4_SIF) { + au8522_setup_cvbs_tuner_mode(state); + } else { + printk("au8522 mode not currently supported\n"); + return -EINVAL; + } + return 0; +} + +static int au8522_s_audio_routing(struct v4l2_subdev *sd, + const struct v4l2_routing *route) +{ + struct au8522_state *state = to_state(sd); + set_audio_input(state, route->input); + return 0; +} + +static int au8522_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt) +{ + int val = 0; + struct au8522_state *state = to_state(sd); + u8 lock_status; + + /* Interrogate the decoder to see if we are getting a real signal */ + lock_status = au8522_readreg(state, 0x00); + if (lock_status == 0xa2) + vt->signal = 0x01; + else + vt->signal = 0x00; + + vt->capability |= + V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_LANG1 | + V4L2_TUNER_CAP_LANG2 | V4L2_TUNER_CAP_SAP; + + val = V4L2_TUNER_SUB_MONO; + vt->rxsubchans = val; + vt->audmode = V4L2_TUNER_MODE_STEREO; + return 0; +} + +static int au8522_g_chip_ident(struct v4l2_subdev *sd, + struct v4l2_dbg_chip_ident *chip) +{ + struct au8522_state *state = to_state(sd); + struct i2c_client *client = v4l2_get_subdevdata(sd); + + return v4l2_chip_ident_i2c_client(client, chip, state->id, state->rev); +} + +static int au8522_log_status(struct v4l2_subdev *sd) +{ + /* FIXME: Add some status info here */ + return 0; +} + +static int au8522_command(struct i2c_client *client, unsigned cmd, void *arg) +{ + return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg); +} + +/* ----------------------------------------------------------------------- */ + +static const struct v4l2_subdev_core_ops au8522_core_ops = { + .log_status = au8522_log_status, + .g_chip_ident = au8522_g_chip_ident, + .g_ctrl = au8522_g_ctrl, + .s_ctrl = au8522_s_ctrl, + .queryctrl = au8522_queryctrl, + .reset = au8522_reset, +#ifdef CONFIG_VIDEO_ADV_DEBUG + .g_register = au8522_g_register, + .s_register = au8522_s_register, +#endif +}; + +static const struct v4l2_subdev_tuner_ops au8522_tuner_ops = { + .g_tuner = au8522_g_tuner, +}; + +static const struct v4l2_subdev_audio_ops au8522_audio_ops = { + .s_routing = au8522_s_audio_routing, +}; + +static const struct v4l2_subdev_video_ops au8522_video_ops = { + .s_routing = au8522_s_video_routing, + .g_fmt = au8522_g_fmt, + .s_fmt = au8522_s_fmt, + .s_stream = au8522_s_stream, +}; + +static const struct v4l2_subdev_ops au8522_ops = { + .core = &au8522_core_ops, + .tuner = &au8522_tuner_ops, + .audio = &au8522_audio_ops, + .video = &au8522_video_ops, +}; + +/* ----------------------------------------------------------------------- */ + +static int au8522_probe(struct i2c_client *client, + const struct i2c_device_id *did) +{ + struct au8522_state *state; + struct v4l2_subdev *sd; + int instance; + struct au8522_config *demod_config; + + /* Check if the adapter supports the needed features */ + if (!i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_BYTE_DATA)) { + return -EIO; + } + + /* allocate memory for the internal state */ + instance = au8522_get_state(&state, client->adapter, client->addr); + switch (instance) { + case 0: + printk("au8522_decoder allocation failed\n"); + return -EIO; + case 1: + /* new demod instance */ + printk("au8522_decoder creating new instance...\n"); + break; + default: + /* existing demod instance */ + printk("au8522_decoder attaching to existing instance...\n"); + break; + } + + demod_config = kzalloc(sizeof(struct au8522_config), GFP_KERNEL); + demod_config->demod_address = 0x8e >> 1; + + state->config = demod_config; + state->i2c = client->adapter; + + sd = &state->sd; + v4l2_i2c_subdev_init(sd, client, &au8522_ops); + + state->c = client; + state->vid_input = AU8522_COMPOSITE_CH1; + state->aud_input = AU8522_AUDIO_NONE; + state->id = 8522; + state->rev = 0; + + /* Jam open the i2c gate to the tuner */ + au8522_writereg(state, 0x106, 1); + + return 0; +} + +static int au8522_remove(struct i2c_client *client) +{ + struct v4l2_subdev *sd = i2c_get_clientdata(client); + v4l2_device_unregister_subdev(sd); + au8522_release_state(to_state(sd)); + return 0; +} + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) +static const struct i2c_device_id au8522_id[] = { + {"au8522", 0}, + {} +}; + +MODULE_DEVICE_TABLE(i2c, au8522_id); + +#endif +static struct v4l2_i2c_driver_data v4l2_i2c_data = { + .name = "au8522", + .driverid = I2C_DRIVERID_AU8522, + .command = au8522_command, + .probe = au8522_probe, + .remove = au8522_remove, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) + .id_table = au8522_id, +#endif +}; -- cgit v1.2.3 From 785193038155c17372457bbf37b241b4893f9698 Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Wed, 11 Mar 2009 02:00:40 -0400 Subject: au0828: add support for analog functionality in bridge From: Devin Heitmueller Add support for the analog functionality found in the au0828 bridge Thanks to Michael Krufky and Steven Toth for providing sample hardware, engineering level support, and testing. Priority: normal Signed-off-by: Devin Heitmueller Signed-off-by: Michael Krufky --- linux/drivers/media/video/au0828/Makefile | 2 +- linux/drivers/media/video/au0828/au0828-cards.c | 41 +- linux/drivers/media/video/au0828/au0828-core.c | 33 +- linux/drivers/media/video/au0828/au0828-reg.h | 6 + linux/drivers/media/video/au0828/au0828-video.c | 1686 +++++++++++++++++++++++ linux/drivers/media/video/au0828/au0828.h | 174 ++- 6 files changed, 1929 insertions(+), 13 deletions(-) create mode 100644 linux/drivers/media/video/au0828/au0828-video.c (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/au0828/Makefile b/linux/drivers/media/video/au0828/Makefile index cd2c58281..4d2623158 100644 --- a/linux/drivers/media/video/au0828/Makefile +++ b/linux/drivers/media/video/au0828/Makefile @@ -1,4 +1,4 @@ -au0828-objs := au0828-core.o au0828-i2c.o au0828-cards.o au0828-dvb.o +au0828-objs := au0828-core.o au0828-i2c.o au0828-cards.o au0828-dvb.o au0828-video.o obj-$(CONFIG_VIDEO_AU0828) += au0828.o diff --git a/linux/drivers/media/video/au0828/au0828-cards.c b/linux/drivers/media/video/au0828/au0828-cards.c index d60123b41..aa79e6b7e 100644 --- a/linux/drivers/media/video/au0828/au0828-cards.c +++ b/linux/drivers/media/video/au0828/au0828-cards.c @@ -21,6 +21,18 @@ #include "au0828.h" #include "au0828-cards.h" +#include "au8522.h" + +void hvr950q_cs5340_audio(void *priv, int enable) +{ + /* Because the HVR-950q shares an i2s bus between the cs5340 and the + au8522, we need to hold cs5340 in reset when using the au8522 */ + struct au0828_dev *dev = priv; + if (enable == 1) + au0828_set(dev, REG_000, 0x10); + else + au0828_clear(dev, REG_000, 0x10); +} struct au0828_board au0828_boards[] = { [AU0828_BOARD_UNKNOWN] = { @@ -31,6 +43,25 @@ struct au0828_board au0828_boards[] = { }, [AU0828_BOARD_HAUPPAUGE_HVR950Q] = { .name = "Hauppauge HVR950Q", + .input = { + { + .type = AU0828_VMUX_TELEVISION, + .vmux = AU8522_COMPOSITE_CH4_SIF, + .amux = AU8522_AUDIO_SIF, + }, + { + .type = AU0828_VMUX_COMPOSITE, + .vmux = AU8522_COMPOSITE_CH1, + .amux = AU8522_AUDIO_NONE, + .audio_setup = hvr950q_cs5340_audio, + }, + { + .type = AU0828_VMUX_SVIDEO, + .vmux = AU8522_SVIDEO_CH13, + .amux = AU8522_AUDIO_NONE, + .audio_setup = hvr950q_cs5340_audio, + }, + }, }, [AU0828_BOARD_HAUPPAUGE_HVR950Q_MXL] = { .name = "Hauppauge HVR950Q rev xxF8", @@ -144,21 +175,23 @@ void au0828_gpio_setup(struct au0828_dev *dev) * 4 - CS5340 * 5 - AU8522 Demodulator * 6 - eeprom W/P + * 7 - power supply * 9 - XC5000 Tuner */ /* Into reset */ au0828_write(dev, REG_003, 0x02); - au0828_write(dev, REG_002, 0x88 | 0x20); + au0828_write(dev, REG_002, 0x80 | 0x20 | 0x10); au0828_write(dev, REG_001, 0x0); au0828_write(dev, REG_000, 0x0); msleep(100); - /* Out of reset */ + /* Out of reset (leave the cs5340 in reset until needed) */ au0828_write(dev, REG_003, 0x02); au0828_write(dev, REG_001, 0x02); - au0828_write(dev, REG_002, 0x88 | 0x20); - au0828_write(dev, REG_000, 0x88 | 0x20 | 0x40); + au0828_write(dev, REG_002, 0x80 | 0x20 | 0x10); + au0828_write(dev, REG_000, 0x80 | 0x40 | 0x20); + msleep(250); break; case AU0828_BOARD_DVICO_FUSIONHDTV7: diff --git a/linux/drivers/media/video/au0828/au0828-core.c b/linux/drivers/media/video/au0828/au0828-core.c index 05e38f41c..0ed270d22 100644 --- a/linux/drivers/media/video/au0828/au0828-core.c +++ b/linux/drivers/media/video/au0828/au0828-core.c @@ -147,6 +147,8 @@ static void au0828_usb_disconnect(struct usb_interface *interface) /* Digital TV */ au0828_dvb_unregister(dev); + au0828_analog_unregister(dev); + /* I2C */ au0828_i2c_unregister(dev); @@ -163,9 +165,11 @@ static void au0828_usb_disconnect(struct usb_interface *interface) static int au0828_usb_probe(struct usb_interface *interface, const struct usb_device_id *id) { - int ifnum; + int ifnum, i; struct au0828_dev *dev; struct usb_device *usbdev = interface_to_usbdev(interface); + struct usb_host_interface *iface_desc; + struct usb_endpoint_descriptor *endpoint; ifnum = interface->altsetting->desc.bInterfaceNumber; @@ -190,6 +194,30 @@ static int au0828_usb_probe(struct usb_interface *interface, usb_set_intfdata(interface, dev); + /* set au0828 usb interface0 to as5 */ + usb_set_interface(usbdev, + interface->cur_altsetting->desc.bInterfaceNumber, 5); + + /* Figure out which endpoint has the isoc interface */ + iface_desc = interface->cur_altsetting; + for(i = 0; i < iface_desc->desc.bNumEndpoints; i++){ + endpoint = &iface_desc->endpoint[i].desc; + if(((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN) && + ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_ISOC)){ + + /* we find our isoc in endpoint */ + u16 tmp = le16_to_cpu(endpoint->wMaxPacketSize); + dev->max_pkt_size = (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1); + dev->isoc_in_endpointaddr = endpoint->bEndpointAddress; + } + } + if(!(dev->isoc_in_endpointaddr)) { + printk("Could not locate isoc endpoint\n"); + kfree(dev); + return -ENODEV; + } + + /* Power Up the bridge */ au0828_write(dev, REG_600, 1 << 4); @@ -202,6 +230,9 @@ static int au0828_usb_probe(struct usb_interface *interface, /* Setup */ au0828_card_setup(dev); + /* Analog TV */ + au0828_analog_register(dev); + /* Digital TV */ au0828_dvb_register(dev); diff --git a/linux/drivers/media/video/au0828/au0828-reg.h b/linux/drivers/media/video/au0828/au0828-reg.h index 1e87fa0c6..b15e4a3b6 100644 --- a/linux/drivers/media/video/au0828/au0828-reg.h +++ b/linux/drivers/media/video/au0828/au0828-reg.h @@ -27,6 +27,9 @@ #define REG_002 0x002 #define REG_003 0x003 +#define AU0828_SENSORCTRL_100 0x100 +#define AU0828_SENSORCTRL_VBI_103 0x103 + #define REG_200 0x200 #define REG_201 0x201 #define REG_202 0x202 @@ -35,4 +38,7 @@ #define REG_209 0x209 #define REG_2FF 0x2ff +/* Audio registers */ +#define AU0828_AUDIOCTRL_50C 0x50C + #define REG_600 0x600 diff --git a/linux/drivers/media/video/au0828/au0828-video.c b/linux/drivers/media/video/au0828/au0828-video.c new file mode 100644 index 000000000..016596b1e --- /dev/null +++ b/linux/drivers/media/video/au0828/au0828-video.c @@ -0,0 +1,1686 @@ +/* + * Auvitek AU0828 USB Bridge (Analog video support) + * + * Copyright (C) 2009 Devin Heitmueller + * Copyright (C) 2005-2008 Auvitek International, Ltd. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * As published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +/* Developer Notes: + * + * VBI support is not yet working + * The hardware scaler supported is unimplemented + * AC97 audio support is unimplemented (only i2s audio mode) + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "compat.h" +#include "au0828.h" +#include "au0828-reg.h" + +static LIST_HEAD(au0828_devlist); +static DEFINE_MUTEX(au0828_sysfs_lock); + +#define AU0828_VERSION_CODE KERNEL_VERSION(0, 0, 1) + +/* Forward declarations */ +void au0828_analog_stream_reset(struct au0828_dev *dev); + +/* ------------------------------------------------------------------ + Videobuf operations + ------------------------------------------------------------------*/ + +static unsigned int isoc_debug; +module_param(isoc_debug, int, 0644); +MODULE_PARM_DESC(isoc_debug, "enable debug messages [isoc transfers]"); + +#define au0828_isocdbg(fmt, arg...) \ +do {\ + if (isoc_debug) { \ + printk(KERN_INFO "au0828 %s :"fmt, \ + __func__ , ##arg); \ + } \ + } while (0) + +static inline void print_err_status(struct au0828_dev *dev, + int packet, int status) +{ + char *errmsg = "Unknown"; + + switch (status) { + case -ENOENT: + errmsg = "unlinked synchronuously"; + break; + case -ECONNRESET: + errmsg = "unlinked asynchronuously"; + break; + case -ENOSR: + errmsg = "Buffer error (overrun)"; + break; + case -EPIPE: + errmsg = "Stalled (device not responding)"; + break; + case -EOVERFLOW: + errmsg = "Babble (bad cable?)"; + break; + case -EPROTO: + errmsg = "Bit-stuff error (bad cable?)"; + break; + case -EILSEQ: + errmsg = "CRC/Timeout (could be anything)"; + break; + case -ETIME: + errmsg = "Device does not respond"; + break; + } + if (packet < 0) { + au0828_isocdbg("URB status %d [%s].\n", status, errmsg); + } else { + au0828_isocdbg("URB packet %d, status %d [%s].\n", + packet, status, errmsg); + } +} + +static int check_dev(struct au0828_dev *dev) +{ + if (dev->dev_state & DEV_DISCONNECTED) { + printk("v4l2 ioctl: device not present\n"); + return -ENODEV; + } + + if (dev->dev_state & DEV_MISCONFIGURED) { + printk("v4l2 ioctl: device is misconfigured; " + "close and open it again\n"); + return -EIO; + } + return 0; +} + +/* + * IRQ callback, called by URB callback + */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19) +static void au0828_irq_callback(struct urb *urb, struct pt_regs *regs) +#else +static void au0828_irq_callback(struct urb *urb) +#endif +{ + struct au0828_dmaqueue *dma_q = urb->context; + struct au0828_dev *dev = container_of(dma_q, struct au0828_dev, vidq); + int rc, i; + + switch (urb->status) { + case 0: /* success */ + case -ETIMEDOUT: /* NAK */ + break; + case -ECONNRESET: /* kill */ + case -ENOENT: + case -ESHUTDOWN: + au0828_isocdbg("au0828_irq_callback called: status kill\n"); + return; + default: /* unknown error */ + au0828_isocdbg("urb completition error %d.\n", urb->status); + break; + } + + /* Copy data from URB */ + spin_lock(&dev->slock); + rc = dev->isoc_ctl.isoc_copy(dev, urb); + spin_unlock(&dev->slock); + + /* Reset urb buffers */ + for (i = 0; i < urb->number_of_packets; i++) { + urb->iso_frame_desc[i].status = 0; + urb->iso_frame_desc[i].actual_length = 0; + } + urb->status = 0; + + urb->status = usb_submit_urb(urb, GFP_ATOMIC); + if (urb->status) { + au0828_isocdbg("urb resubmit failed (error=%i)\n", + urb->status); + } +} + +/* + * Stop and Deallocate URBs + */ +void au0828_uninit_isoc(struct au0828_dev *dev) +{ + struct urb *urb; + int i; + + au0828_isocdbg("au0828: called au0828_uninit_isoc\n"); + + dev->isoc_ctl.nfields = -1; + for (i = 0; i < dev->isoc_ctl.num_bufs; i++) { + urb = dev->isoc_ctl.urb[i]; + if (urb) { + if (!irqs_disabled()) + usb_kill_urb(urb); + else + usb_unlink_urb(urb); + + if (dev->isoc_ctl.transfer_buffer[i]) { + usb_buffer_free(dev->usbdev, + urb->transfer_buffer_length, + dev->isoc_ctl.transfer_buffer[i], + urb->transfer_dma); + } + usb_free_urb(urb); + dev->isoc_ctl.urb[i] = NULL; + } + dev->isoc_ctl.transfer_buffer[i] = NULL; + } + + kfree(dev->isoc_ctl.urb); + kfree(dev->isoc_ctl.transfer_buffer); + + dev->isoc_ctl.urb = NULL; + dev->isoc_ctl.transfer_buffer = NULL; + dev->isoc_ctl.num_bufs = 0; +} + +/* + * Allocate URBs and start IRQ + */ +int au0828_init_isoc(struct au0828_dev *dev, int max_packets, + int num_bufs, int max_pkt_size, + int (*isoc_copy) (struct au0828_dev *dev, struct urb *urb)) +{ + struct au0828_dmaqueue *dma_q = &dev->vidq; + int i; + int sb_size, pipe; + struct urb *urb; + int j, k; + int rc; + + au0828_isocdbg("au0828: called au0828_prepare_isoc\n"); + + /* De-allocates all pending stuff */ + au0828_uninit_isoc(dev); + + dev->isoc_ctl.isoc_copy = isoc_copy; + dev->isoc_ctl.num_bufs = num_bufs; + + dev->isoc_ctl.urb = kzalloc(sizeof(void *)*num_bufs, GFP_KERNEL); + if (!dev->isoc_ctl.urb) { + au0828_isocdbg("cannot alloc memory for usb buffers\n"); + return -ENOMEM; + } + + dev->isoc_ctl.transfer_buffer = kzalloc(sizeof(void *)*num_bufs, + GFP_KERNEL); + if (!dev->isoc_ctl.transfer_buffer) { + au0828_isocdbg("cannot allocate memory for usb transfer\n"); + kfree(dev->isoc_ctl.urb); + return -ENOMEM; + } + + dev->isoc_ctl.max_pkt_size = max_pkt_size; + dev->isoc_ctl.buf = NULL; + + sb_size = max_packets * dev->isoc_ctl.max_pkt_size; + + /* allocate urbs and transfer buffers */ + for (i = 0; i < dev->isoc_ctl.num_bufs; i++) { + urb = usb_alloc_urb(max_packets, GFP_KERNEL); + if (!urb) { + au0828_isocdbg("cannot alloc isoc_ctl.urb %i\n", i); + au0828_uninit_isoc(dev); + return -ENOMEM; + } + dev->isoc_ctl.urb[i] = urb; + + dev->isoc_ctl.transfer_buffer[i] = usb_buffer_alloc(dev->usbdev, + sb_size, GFP_KERNEL, &urb->transfer_dma); + if (!dev->isoc_ctl.transfer_buffer[i]) { + printk("unable to allocate %i bytes for transfer" + " buffer %i%s\n", + sb_size, i, + in_interrupt() ? " while in int" : ""); + au0828_uninit_isoc(dev); + return -ENOMEM; + } + memset(dev->isoc_ctl.transfer_buffer[i], 0, sb_size); + + pipe = usb_rcvisocpipe(dev->usbdev, + dev->isoc_in_endpointaddr), + + usb_fill_int_urb(urb, dev->usbdev, pipe, + dev->isoc_ctl.transfer_buffer[i], sb_size, + au0828_irq_callback, dma_q, 1); + + urb->number_of_packets = max_packets; + urb->transfer_flags = URB_ISO_ASAP; + + k = 0; + for (j = 0; j < max_packets; j++) { + urb->iso_frame_desc[j].offset = k; + urb->iso_frame_desc[j].length = + dev->isoc_ctl.max_pkt_size; + k += dev->isoc_ctl.max_pkt_size; + } + } + + init_waitqueue_head(&dma_q->wq); + + /* submit urbs and enables IRQ */ + for (i = 0; i < dev->isoc_ctl.num_bufs; i++) { + rc = usb_submit_urb(dev->isoc_ctl.urb[i], GFP_ATOMIC); + if (rc) { + au0828_isocdbg("submit of urb %i failed (error=%i)\n", + i, rc); + au0828_uninit_isoc(dev); + return rc; + } + } + + return 0; +} + +/* + * Announces that a buffer were filled and request the next + */ +static inline void buffer_filled(struct au0828_dev *dev, + struct au0828_dmaqueue *dma_q, + struct au0828_buffer *buf) +{ + /* Advice that buffer was filled */ + au0828_isocdbg("[%p/%d] wakeup\n", buf, buf->vb.i); + + buf->vb.state = VIDEOBUF_DONE; + buf->vb.field_count++; + do_gettimeofday(&buf->vb.ts); + + dev->isoc_ctl.buf = NULL; + + list_del(&buf->vb.queue); + wake_up(&buf->vb.done); +} + +/* + * Identify the buffer header type and properly handles + */ +static void au0828_copy_video(struct au0828_dev *dev, + struct au0828_dmaqueue *dma_q, + struct au0828_buffer *buf, + unsigned char *p, + unsigned char *outp, unsigned long len) +{ + void *fieldstart, *startwrite, *startread; + int linesdone, currlinedone, offset, lencopy, remain; + int bytesperline = dev->width << 1; /* Assumes 16-bit depth @@@@ */ + + if (dma_q->pos + len > buf->vb.size) + len = buf->vb.size - dma_q->pos; + + startread = p; + remain = len; + + /* Interlaces frame */ + if (buf->top_field) + fieldstart = outp; + else + fieldstart = outp + bytesperline; + + linesdone = dma_q->pos / bytesperline; + currlinedone = dma_q->pos % bytesperline; + offset = linesdone * bytesperline * 2 + currlinedone; + startwrite = fieldstart + offset; + lencopy = bytesperline - currlinedone; + lencopy = lencopy > remain ? remain : lencopy; + + if ((char *)startwrite + lencopy > (char *)outp + buf->vb.size) { + au0828_isocdbg("Overflow of %zi bytes past buffer end (1)\n", + ((char *)startwrite + lencopy) - + ((char *)outp + buf->vb.size)); + remain = (char *)outp + buf->vb.size - (char *)startwrite; + lencopy = remain; + } + if (lencopy <= 0) + return; + memcpy(startwrite, startread, lencopy); + + remain -= lencopy; + + while (remain > 0) { + startwrite += lencopy + bytesperline; + startread += lencopy; + if (bytesperline > remain) + lencopy = remain; + else + lencopy = bytesperline; + + if ((char *)startwrite + lencopy > (char *)outp + + buf->vb.size) { + au0828_isocdbg("Overflow of %zi bytes past buffer end (2)\n", + ((char *)startwrite + lencopy) - + ((char *)outp + buf->vb.size)); + lencopy = remain = (char *)outp + buf->vb.size - + (char *)startwrite; + } + if (lencopy <= 0) + break; + + memcpy(startwrite, startread, lencopy); + + remain -= lencopy; + } + + if (offset > 1440) { + /* We have enough data to check for greenscreen */ + if (outp[0] < 0x60 && outp[1440] < 0x60) { + dev->greenscreen_detected = 1; + } + } + + dma_q->pos += len; +} + +/* + * video-buf generic routine to get the next available buffer + */ +static inline void get_next_buf(struct au0828_dmaqueue *dma_q, + struct au0828_buffer **buf) +{ + struct au0828_dev *dev = container_of(dma_q, struct au0828_dev, vidq); + + if (list_empty(&dma_q->active)) { + au0828_isocdbg("No active queue to serve\n"); + dev->isoc_ctl.buf = NULL; + *buf = NULL; + return; + } + + /* Get the next buffer */ + *buf = list_entry(dma_q->active.next, struct au0828_buffer, vb.queue); + dev->isoc_ctl.buf = *buf; + + return; +} + +/* + * Controls the isoc copy of each urb packet + */ +static inline int au0828_isoc_copy(struct au0828_dev *dev, struct urb *urb) +{ + struct au0828_buffer *buf; + struct au0828_dmaqueue *dma_q = urb->context; + unsigned char *outp = NULL; + int i, len = 0, rc = 1; + unsigned char *p; + unsigned char fbyte; + + if (!dev) + return 0; + + if ((dev->dev_state & DEV_DISCONNECTED) || + (dev->dev_state & DEV_MISCONFIGURED)) + return 0; + + if (urb->status < 0) { + print_err_status(dev, -1, urb->status); + if (urb->status == -ENOENT) + return 0; + } + + buf = dev->isoc_ctl.buf; + if (buf != NULL) + outp = videobuf_to_vmalloc(&buf->vb); + + for (i = 0; i < urb->number_of_packets; i++) { + int status = urb->iso_frame_desc[i].status; + + if (status < 0) { + print_err_status(dev, i, status); + if (urb->iso_frame_desc[i].status != -EPROTO) + continue; + } + + if (urb->iso_frame_desc[i].actual_length <= 0) { + continue; + } + if (urb->iso_frame_desc[i].actual_length > + dev->max_pkt_size) { + au0828_isocdbg("packet bigger than packet size"); + continue; + } + + p = urb->transfer_buffer + urb->iso_frame_desc[i].offset; + fbyte = p[0]; + len = urb->iso_frame_desc[i].actual_length - 4; + p += 4; + + if (fbyte & 0x80) { + len -= 4; + p += 4; + au0828_isocdbg("Video frame %s\n", + (fbyte & 0x40) ? "odd" : "even"); + if (!(fbyte & 0x40)) { + if (buf != NULL) + buffer_filled(dev, dma_q, buf); + get_next_buf(dma_q, &buf); + if (buf == NULL) { + outp = NULL; + } else + outp = videobuf_to_vmalloc(&buf->vb); + } + + if (buf != NULL) { + if (fbyte & 0x40) { + buf->top_field = 1; + } else { + buf->top_field = 0; + } + } + + dma_q->pos = 0; + } + if (buf != NULL) { + au0828_copy_video(dev, dma_q, buf, p, outp, len); + } + } + return rc; +} + +static int +buffer_setup(struct videobuf_queue *vq, unsigned int *count, + unsigned int *size) +{ + struct au0828_fh *fh = vq->priv_data; + *size = (fh->dev->width * fh->dev->height * 16 + 7) >> 3; + + if (0 == *count) + *count = AU0828_DEF_BUF; + + if (*count < AU0828_MIN_BUF) + *count = AU0828_MIN_BUF; + return 0; +} + +/* This is called *without* dev->slock held; please keep it that way */ +static void free_buffer(struct videobuf_queue *vq, struct au0828_buffer *buf) +{ + struct au0828_fh *fh = vq->priv_data; + struct au0828_dev *dev = fh->dev; + unsigned long flags = 0; + if (in_interrupt()) + BUG(); + + /* We used to wait for the buffer to finish here, but this didn't work + because, as we were keeping the state as VIDEOBUF_QUEUED, + videobuf_queue_cancel marked it as finished for us. + (Also, it could wedge forever if the hardware was misconfigured.) + + This should be safe; by the time we get here, the buffer isn't + queued anymore. If we ever start marking the buffers as + VIDEOBUF_ACTIVE, it won't be, though. + */ + spin_lock_irqsave(&dev->slock, flags); + if (dev->isoc_ctl.buf == buf) + dev->isoc_ctl.buf = NULL; + spin_unlock_irqrestore(&dev->slock, flags); + + videobuf_vmalloc_free(&buf->vb); + buf->vb.state = VIDEOBUF_NEEDS_INIT; +} + +static int +buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb, + enum v4l2_field field) +{ + struct au0828_fh *fh = vq->priv_data; + struct au0828_buffer *buf = container_of(vb, struct au0828_buffer, vb); + struct au0828_dev *dev = fh->dev; + int rc = 0, urb_init = 0; + + buf->vb.size = (fh->dev->width * fh->dev->height * 16 + 7) >> 3; + + if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size) + return -EINVAL; + + buf->vb.width = dev->width; + buf->vb.height = dev->height; + buf->vb.field = field; + + if (VIDEOBUF_NEEDS_INIT == buf->vb.state) { + rc = videobuf_iolock(vq, &buf->vb, NULL); + if (rc < 0) { + printk("videobuf_iolock failed\n"); + goto fail; + } + } + + if (!dev->isoc_ctl.num_bufs) + urb_init = 1; + + if (urb_init) { + rc = au0828_init_isoc(dev, AU0828_ISO_PACKETS_PER_URB, + AU0828_MAX_ISO_BUFS, dev->max_pkt_size, + au0828_isoc_copy); + if (rc < 0) { + printk("au0828_init_isoc failed\n"); + goto fail; + } + } + + buf->vb.state = VIDEOBUF_PREPARED; + return 0; + +fail: + free_buffer(vq, buf); + return rc; +} + +static void +buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) +{ + struct au0828_buffer *buf = container_of(vb, + struct au0828_buffer, + vb); + struct au0828_fh *fh = vq->priv_data; + struct au0828_dev *dev = fh->dev; + struct au0828_dmaqueue *vidq = &dev->vidq; + + buf->vb.state = VIDEOBUF_QUEUED; + list_add_tail(&buf->vb.queue, &vidq->active); +} + +static void buffer_release(struct videobuf_queue *vq, + struct videobuf_buffer *vb) +{ + struct au0828_buffer *buf = container_of(vb, + struct au0828_buffer, + vb); + + free_buffer(vq, buf); +} + +static struct videobuf_queue_ops au0828_video_qops = { + .buf_setup = buffer_setup, + .buf_prepare = buffer_prepare, + .buf_queue = buffer_queue, + .buf_release = buffer_release, +}; + +/* ------------------------------------------------------------------ + V4L2 interface + ------------------------------------------------------------------*/ + +static int au0828_i2s_init(struct au0828_dev *dev) +{ + /* Enable i2s mode */ + au0828_writereg(dev, AU0828_AUDIOCTRL_50C, 0x01); + return 0; +} + +/* + * Auvitek au0828 analog stream enable + * Please set interface0 to AS5 before enable the stream + */ +int au0828_analog_stream_enable(struct au0828_dev *d) +{ + dprintk(1, "au0828_analog_stream_enable called\n"); + au0828_writereg(d, AU0828_SENSORCTRL_VBI_103, 0x00); + au0828_writereg(d, 0x106, 0x00); + /* set x position */ + au0828_writereg(d, 0x110, 0x00); + au0828_writereg(d, 0x111, 0x00); + au0828_writereg(d, 0x114, 0xa0); + au0828_writereg(d, 0x115, 0x05); + /* set y position */ + au0828_writereg(d, 0x112, 0x02); + au0828_writereg(d, 0x113, 0x00); + au0828_writereg(d, 0x116, 0xf2); + au0828_writereg(d, 0x117, 0x00); + au0828_writereg(d, AU0828_SENSORCTRL_100, 0xb3); + + return 0; +} + +int au0828_analog_stream_disable(struct au0828_dev *d) +{ + dprintk(1, "au0828_analog_stream_disable called\n"); + au0828_writereg(d, AU0828_SENSORCTRL_100, 0x0); + return 0; +} + +void au0828_analog_stream_reset(struct au0828_dev *dev) +{ + dprintk(1, "au0828_analog_stream_reset called\n"); + au0828_writereg(dev, AU0828_SENSORCTRL_100, 0x0); + mdelay(30); + au0828_writereg(dev, AU0828_SENSORCTRL_100, 0xb3); +} + +/* + * Some operations needs to stop current streaming + */ +static int au0828_stream_interrupt(struct au0828_dev *dev) +{ + int ret = 0; + + dev->stream_state = STREAM_INTERRUPT; + if(dev->dev_state == DEV_DISCONNECTED) + return -ENODEV; + else if(ret) { + dev->dev_state = DEV_MISCONFIGURED; + dprintk(1, "%s device is misconfigured!\n", __FUNCTION__); + return ret; + } + return 0; +} + +/* + * au0828_release_resources + * unregister v4l2 devices + */ +void au0828_analog_unregister(struct au0828_dev *dev) +{ + dprintk(1, "au0828_release_resources called\n"); + mutex_lock(&au0828_sysfs_lock); + + list_del(&dev->au0828list); + video_unregister_device(dev->vdev); + video_unregister_device(dev->vbi_dev); + + mutex_unlock(&au0828_sysfs_lock); +} + + +/* Usage lock check functions */ +static int res_get(struct au0828_fh *fh) +{ + struct au0828_dev *dev = fh->dev; + int rc = 0; + + /* This instance already has stream_on */ + if (fh->stream_on) + return rc; + + if (dev->stream_on) + return -EBUSY; + + dev->stream_on = 1; + fh->stream_on = 1; + return rc; +} + +static int res_check(struct au0828_fh *fh) +{ + return fh->stream_on; +} + +static void res_free(struct au0828_fh *fh) +{ + struct au0828_dev *dev = fh->dev; + + fh->stream_on = 0; + dev->stream_on = 0; +} + +static int au0828_v4l2_open(struct file *filp) +{ + int minor = video_devdata(filp)->minor; + int ret = 0; + struct au0828_dev *h, *dev = NULL; + struct au0828_fh *fh; + int type = 0; + struct list_head *list; + + list_for_each(list, &au0828_devlist) { + h = list_entry(list, struct au0828_dev, au0828list); + if(h->vdev->minor == minor) { + dev = h; + type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + } + if(h->vbi_dev->minor == minor) { + dev = h; + type = V4L2_BUF_TYPE_VBI_CAPTURE; + } + } + + if(NULL == dev) + return -ENODEV; + + fh = kzalloc(sizeof(struct au0828_fh), GFP_KERNEL); + if(NULL == fh) { + dprintk(1, "Failed allocate au0828_fh struct!\n"); + return -ENOMEM; + } + + fh->type = type; + fh->dev = dev; + filp->private_data = fh; + + if(fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE && dev->users == 0) { + /* set au0828 interface0 to AS5 here again */ + ret = usb_set_interface(dev->usbdev, 0, 5); + if(ret < 0) { + printk("Au0828 can't set alt setting to 5!\n"); + return -EBUSY; + } + dev->width = NTSC_STD_W; + dev->height = NTSC_STD_H; + dev->frame_size = dev->width * dev->height * 2; + dev->field_size = dev->width * dev->height; + dev->bytesperline = dev->width * 2; + + au0828_analog_stream_enable(dev); + au0828_analog_stream_reset(dev); + + /* If we were doing ac97 instead of i2s, it would go here...*/ + au0828_i2s_init(dev); + + dev->stream_state = STREAM_OFF; + dev->dev_state |= DEV_INITIALIZED; + } + + dev->users++; + + videobuf_queue_vmalloc_init(&fh->vb_vidq, &au0828_video_qops, + NULL, &dev->slock, fh->type, + V4L2_FIELD_INTERLACED, + sizeof(struct au0828_buffer), fh); + + return ret; +} + +static int au0828_v4l2_close(struct file *filp) +{ + int ret; + struct au0828_fh *fh = filp->private_data; + struct au0828_dev *dev = fh->dev; + + mutex_lock(&dev->lock); + if (res_check(fh)) + res_free(fh); + + if(dev->users == 1) { + videobuf_stop(&fh->vb_vidq); + videobuf_mmap_free(&fh->vb_vidq); + + if(dev->dev_state & DEV_DISCONNECTED) { + au0828_analog_unregister(dev); + mutex_unlock(&dev->lock); + kfree(dev); + return 0; + } + + au0828_analog_stream_disable(dev); + + au0828_uninit_isoc(dev); + + /* When close the device, set the usb intf0 into alt0 to free + USB bandwidth */ + ret = usb_set_interface(dev->usbdev, 0, 0); + if(ret < 0) + printk("Au0828 can't set alt setting to 0!\n"); + } + + kfree(fh); + dev->users--; + wake_up_interruptible_nr(&dev->open, 1); + mutex_unlock(&dev->lock); + return 0; +} + +static ssize_t au0828_v4l2_read(struct file *filp, char __user *buf, + size_t count, loff_t *pos) +{ + struct au0828_fh *fh = filp->private_data; + struct au0828_dev *dev = fh->dev; + int rc; + + rc = check_dev(dev); + if (rc < 0) + return rc; + + if(fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { + mutex_lock(&dev->lock); + rc = res_get(fh); + mutex_unlock(&dev->lock); + + if (unlikely(rc < 0)) + return rc; + + return videobuf_read_stream(&fh->vb_vidq, buf, count, pos, 0, + filp->f_flags & O_NONBLOCK); + } + return 0; +} + +static unsigned int au0828_v4l2_poll(struct file *filp, poll_table *wait) +{ + struct au0828_fh *fh = filp->private_data; + struct au0828_dev *dev = fh->dev; + int rc; + + rc = check_dev(dev); + if (rc < 0) + return rc; + + mutex_lock(&dev->lock); + rc = res_get(fh); + mutex_unlock(&dev->lock); + + if (unlikely(rc < 0)) + return POLLERR; + + if (V4L2_BUF_TYPE_VIDEO_CAPTURE != fh->type) + return POLLERR; + + return videobuf_poll_stream(filp, &fh->vb_vidq, wait); +} + +static int au0828_v4l2_mmap(struct file *filp, struct vm_area_struct *vma) +{ + struct au0828_fh *fh = filp->private_data; + struct au0828_dev *dev = fh->dev; + int rc; + + rc = check_dev(dev); + if (rc < 0) + return rc; + + mutex_lock(&dev->lock); + rc = res_get(fh); + mutex_unlock(&dev->lock); + + if (unlikely(rc < 0)) + return rc; + + 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; +} + +static int au0828_set_format(struct au0828_dev *dev, unsigned int cmd, + struct v4l2_format *format) +{ + int ret; + int width = format->fmt.pix.width; + int height = format->fmt.pix.height; + unsigned int maxwidth, maxheight; + + maxwidth = 720; + maxheight = 480; + + if(format->type == V4L2_BUF_TYPE_SLICED_VBI_CAPTURE) { + dprintk(1, "VBI format set: to be supported!\n"); + return 0; + } + if(format->type == V4L2_BUF_TYPE_VBI_CAPTURE) { + return 0; + } + if(format->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { + return -EINVAL; + } + + /* If they are demanding a format other than the one we support, + bail out (tvtime asks for UYVY and then retries with YUYV) */ + if (format->fmt.pix.pixelformat != V4L2_PIX_FMT_UYVY) { + return -EINVAL; + } + + /* format->fmt.pix.width only support 720 and height 480 */ + if(width != 720) + width = 720; + if(height != 480) + height = 480; + + format->fmt.pix.width = width; + format->fmt.pix.height = height; + format->fmt.pix.pixelformat = V4L2_PIX_FMT_UYVY; + format->fmt.pix.bytesperline = width * 2; + format->fmt.pix.sizeimage = width * height * 2; + format->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; + format->fmt.pix.field = V4L2_FIELD_INTERLACED; + + if(cmd == VIDIOC_TRY_FMT) + return 0; + + /* maybe set new image format, driver current only support 720*480 */ + dev->width = width; + dev->height = height; + dev->frame_size = width * height * 2; + dev->field_size = width * height; + dev->bytesperline = width * 2; + + if(dev->stream_state == STREAM_ON) { + dprintk(1, "VIDIOC_SET_FMT: interrupting stream!\n"); + if((ret = au0828_stream_interrupt(dev))) { + dprintk(1, "error interrupting video stream!\n"); + return ret; + } + } + + /* set au0828 interface0 to AS5 here again */ + ret = usb_set_interface(dev->usbdev, 0, 5); + if(ret < 0) { + printk("Au0828 can't set alt setting to 5!\n"); + return -EBUSY; + } + + au0828_analog_stream_enable(dev); + + return 0; +} + + +static int vidioc_queryctrl(struct file *file, void *priv, + struct v4l2_queryctrl *qc) +{ + struct au0828_fh *fh = priv; + struct au0828_dev *dev = fh->dev; + au0828_call_i2c_clients(dev, VIDIOC_QUERYCTRL, qc); + if (qc->type) + return 0; + else + return -EINVAL; +} + +static int vidioc_querycap(struct file *file, void *priv, + struct v4l2_capability *cap) +{ + struct au0828_fh *fh = priv; + struct au0828_dev *dev = fh->dev; + + memset(cap, 0, sizeof(*cap)); + strlcpy(cap->driver, "au0828", sizeof(cap->driver)); + strlcpy(cap->card, au0828_boards[dev->board].name, sizeof(cap->card)); + strlcpy(cap->bus_info, dev->usbdev->dev.bus_id, sizeof(cap->bus_info)); + + cap->version = AU0828_VERSION_CODE; + + /*set the device capabilities */ + cap->capabilities = V4L2_CAP_VBI_CAPTURE | + V4L2_CAP_VIDEO_CAPTURE | + V4L2_CAP_AUDIO | + V4L2_CAP_READWRITE | + V4L2_CAP_STREAMING | + V4L2_CAP_TUNER; + return 0; +} + +static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, + struct v4l2_fmtdesc *f) +{ + if(f->index) + return -EINVAL; + + memset(f, 0, sizeof(*f)); + f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + strcpy(f->description, "Packed YUV2"); + + f->flags = 0; + f->pixelformat = V4L2_PIX_FMT_UYVY; + + memset(f->reserved, 0, sizeof(f->reserved)); + return 0; +} + +static int vidioc_g_fmt_vid_cap(struct file *file, void *priv, + struct v4l2_format *f) +{ + struct au0828_fh *fh = priv; + struct au0828_dev *dev = fh->dev; + + f->fmt.pix.width = dev->width; + f->fmt.pix.height = dev->height; + f->fmt.pix.pixelformat = V4L2_PIX_FMT_UYVY; + f->fmt.pix.bytesperline = dev->bytesperline; + f->fmt.pix.sizeimage = dev->frame_size; + f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; /* NTSC/PAL */ + f->fmt.pix.field = V4L2_FIELD_INTERLACED; + return 0; +} + +static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, + struct v4l2_format *f) +{ + struct au0828_fh *fh = priv; + struct au0828_dev *dev = fh->dev; + + return au0828_set_format(dev, VIDIOC_TRY_FMT, f); +} + +static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, + struct v4l2_format *f) +{ + struct au0828_fh *fh = priv; + struct au0828_dev *dev = fh->dev; + int rc; + + if (videobuf_queue_is_busy(&fh->vb_vidq)) { + printk("%s queue busy\n", __func__); + rc = -EBUSY; + goto out; + } + + if (dev->stream_on && !fh->stream_on) { + printk("%s device in use by another fh\n", __func__); + rc = -EBUSY; + goto out; + } + + return au0828_set_format(dev, VIDIOC_S_FMT, f); +out: + return rc; +} + +static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id * norm) +{ + struct au0828_fh *fh = priv; + struct au0828_dev *dev = fh->dev; + + /* FIXME: when we support something other than NTSC, we are going to + have to make the au0828 bridge adjust the size of its capture + buffer, which is currently hardcoded at 720x480 */ + + au0828_call_i2c_clients(dev, VIDIOC_S_STD, norm); + return 0; +} + +static int vidioc_enum_input(struct file *file, void *priv, + struct v4l2_input *input) +{ + struct au0828_fh *fh = priv; + struct au0828_dev *dev = fh->dev; + unsigned int tmp; + + static const char *inames[] = { + [AU0828_VMUX_COMPOSITE] = "Composite", + [AU0828_VMUX_SVIDEO] = "S-Video", + [AU0828_VMUX_CABLE] = "Cable TV", + [AU0828_VMUX_TELEVISION] = "Television", + [AU0828_VMUX_DVB] = "DVB", + [AU0828_VMUX_DEBUG] = "tv debug" + }; + + tmp = input->index; + + if(tmp > AU0828_MAX_INPUT) + return -EINVAL; + if(AUVI_INPUT(tmp)->type == 0) + return -EINVAL; + + memset(input, 0, sizeof(*input)); + input->index = tmp; + strcpy(input->name, inames[AUVI_INPUT(tmp)->type]); + if((AUVI_INPUT(tmp)->type == AU0828_VMUX_TELEVISION) || + (AUVI_INPUT(tmp)->type == AU0828_VMUX_CABLE)) + input->type |= V4L2_INPUT_TYPE_TUNER; + else + input->type |= V4L2_INPUT_TYPE_CAMERA; + + input->std = dev->vdev->tvnorms; + + return 0; +} + +static int vidioc_g_input(struct file *file, void *priv, unsigned int *i) +{ + struct au0828_fh *fh = priv; + struct au0828_dev *dev = fh->dev; + *i = dev->ctrl_input; + return 0; +} + +static int vidioc_s_input(struct file *file, void *priv, unsigned int index) +{ + struct au0828_fh *fh = priv; + struct au0828_dev *dev = fh->dev; + int i; + struct v4l2_routing route; + + dprintk(1, "VIDIOC_S_INPUT in function %s, input=%d\n", __FUNCTION__, + index); + if(index >= AU0828_MAX_INPUT) + return -EINVAL; + if(AUVI_INPUT(index)->type == 0) + return -EINVAL; + dev->ctrl_input = index; + + switch(AUVI_INPUT(index)->type) { + case AU0828_VMUX_SVIDEO: + { + dev->input_type = AU0828_VMUX_SVIDEO; + break; + } + case AU0828_VMUX_COMPOSITE: + { + dev->input_type = AU0828_VMUX_COMPOSITE; + break; + } + case AU0828_VMUX_TELEVISION: + { + dev->input_type = AU0828_VMUX_TELEVISION; + break; + } + default: + ; + } + + route.input = AUVI_INPUT(index)->vmux; + route.output = 0; + au0828_call_i2c_clients(dev, VIDIOC_INT_S_VIDEO_ROUTING, &route); + + for (i = 0; i < AU0828_MAX_INPUT; i++) { + int enable = 0; + if (AUVI_INPUT(i)->audio_setup == NULL) { + continue; + } + + if (i == index) + enable = 1; + else + enable = 0; + if (enable) { + (AUVI_INPUT(i)->audio_setup)(dev, enable); + } else { + /* Make sure we leave it turned on if some + other input is routed to this callback */ + if ((AUVI_INPUT(i)->audio_setup) != + ((AUVI_INPUT(index)->audio_setup))) { + (AUVI_INPUT(i)->audio_setup)(dev, enable); + } + } + } + + route.input = AUVI_INPUT(index)->amux; + au0828_call_i2c_clients(dev, VIDIOC_INT_S_AUDIO_ROUTING, + &route); + return 0; +} + +static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a) +{ + struct au0828_fh *fh = priv; + struct au0828_dev *dev = fh->dev; + unsigned int index = a->index; + + if(a->index > 1) + return -EINVAL; + + memset(a, 0, sizeof(*a)); + index = dev->ctrl_ainput; + if(index == 0) + strcpy(a->name, "Television"); + else + strcpy(a->name, "Line in"); + + a->capability = V4L2_AUDCAP_STEREO; + a->index = index; + return 0; +} + +static int vidioc_s_audio(struct file *file, void *priv, struct v4l2_audio *a) +{ + struct au0828_fh *fh = priv; + struct au0828_dev *dev = fh->dev; + if(a->index != dev->ctrl_ainput) + return -EINVAL; + return 0; +} + +static int vidioc_g_ctrl(struct file *file, void *priv, + struct v4l2_control *ctrl) +{ + struct au0828_fh *fh = priv; + struct au0828_dev *dev = fh->dev; + + au0828_call_i2c_clients(dev, VIDIOC_G_CTRL, ctrl); + return 0; + +} + +static int vidioc_s_ctrl(struct file *file, void *priv, + struct v4l2_control *ctrl) +{ + struct au0828_fh *fh = priv; + struct au0828_dev *dev = fh->dev; + au0828_call_i2c_clients(dev, VIDIOC_S_CTRL, ctrl); + return 0; +} + +static int vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t) +{ + struct au0828_fh *fh = priv; + struct au0828_dev *dev = fh->dev; + + if(t->index != 0) + return -EINVAL; + + memset(t, 0, sizeof(*t)); + strcpy(t->name, "Auvitek tuner"); + + au0828_call_i2c_clients(dev, VIDIOC_G_TUNER, t); + return 0; +} + +static int vidioc_s_tuner(struct file *file, void *priv, + struct v4l2_tuner *t) +{ + struct au0828_fh *fh = priv; + struct au0828_dev *dev = fh->dev; + + if(t->index != 0) + return -EINVAL; + + t->type = V4L2_TUNER_ANALOG_TV; + au0828_call_i2c_clients(dev, VIDIOC_S_TUNER, t); + dprintk(1, "VIDIOC_S_TUNER: signal = %x, afc = %x\n", t->signal, + t->afc); + return 0; + +} + +static int vidioc_g_frequency(struct file *file, void *priv, + struct v4l2_frequency *freq) +{ + struct au0828_fh *fh = priv; + struct au0828_dev *dev = fh->dev; + memset(freq, 0, sizeof(*freq)); + freq->type = V4L2_TUNER_ANALOG_TV; + freq->frequency = dev->ctrl_freq; + return 0; +} + +static int vidioc_s_frequency(struct file *file, void *priv, + struct v4l2_frequency *freq) +{ + struct au0828_fh *fh = priv; + struct au0828_dev *dev = fh->dev; + + if(freq->tuner != 0) + return -EINVAL; + if(freq->type != V4L2_TUNER_ANALOG_TV) + return -EINVAL; + + dev->ctrl_freq = freq->frequency; + + au0828_call_i2c_clients(dev, VIDIOC_S_FREQUENCY, freq); + + au0828_analog_stream_reset(dev); + + return 0; +} + +static int vidioc_g_chip_ident(struct file *file, void *priv, + struct v4l2_dbg_chip_ident *chip) +{ + struct au0828_fh *fh = priv; + struct au0828_dev *dev = fh->dev; + chip->ident = V4L2_IDENT_NONE; + chip->revision = 0; + + au0828_call_i2c_clients(dev, VIDIOC_DBG_G_CHIP_IDENT, chip); + return 0; +} + +static int vidioc_cropcap(struct file *file, void *priv, + struct v4l2_cropcap *cc) +{ + struct au0828_fh *fh = priv; + struct au0828_dev *dev = fh->dev; + + if(cc->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + + cc->bounds.left = 0; + cc->bounds.top = 0; + cc->bounds.width = dev->width; + cc->bounds.height = dev->height; + + cc->defrect = cc->bounds; + + cc->pixelaspect.numerator = 54; + cc->pixelaspect.denominator = 59; + + return 0; +} + +static int vidioc_streamon(struct file *file, void *priv, + enum v4l2_buf_type type) +{ + struct au0828_fh *fh = priv; + struct au0828_dev *dev = fh->dev; + int b = V4L2_BUF_TYPE_VIDEO_CAPTURE; + int rc; + + rc = check_dev(dev); + if (rc < 0) + return rc; + + if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { + au0828_analog_stream_enable(dev); + au0828_call_i2c_clients(dev, VIDIOC_STREAMON, &b); + } + + mutex_lock(&dev->lock); + rc = res_get(fh); + + if (likely(rc >= 0)) + rc = videobuf_streamon(&fh->vb_vidq); + mutex_unlock(&dev->lock); + + return rc; +} + +static int vidioc_streamoff(struct file *file, void *priv, + enum v4l2_buf_type type) +{ + struct au0828_fh *fh = priv; + struct au0828_dev *dev = fh->dev; + int b = V4L2_BUF_TYPE_VIDEO_CAPTURE; + int i; + int ret; + int rc; + + rc = check_dev(dev); + if (rc < 0) + return rc; + + if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + if (type != fh->type) + return -EINVAL; + + if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { + au0828_call_i2c_clients(dev, VIDIOC_STREAMOFF, &b); + if((ret = au0828_stream_interrupt(dev)) != 0) + return ret; + } + + for (i = 0; i < AU0828_MAX_INPUT; i++) { + if (AUVI_INPUT(i)->audio_setup == NULL) { + continue; + } + (AUVI_INPUT(i)->audio_setup)(dev, 0); + } + + mutex_lock(&dev->lock); + videobuf_streamoff(&fh->vb_vidq); + res_free(fh); + mutex_unlock(&dev->lock); + + return 0; +} + +static int vidioc_g_register(struct file *file, void *priv, + struct v4l2_dbg_register *reg) +{ + struct au0828_fh *fh = priv; + struct au0828_dev *dev = fh->dev; + + switch (reg->match.type) { + case V4L2_CHIP_MATCH_I2C_DRIVER: + au0828_call_i2c_clients(dev, VIDIOC_DBG_G_REGISTER, reg); + return 0; + default: + return -EINVAL; + } +} + +static int vidioc_s_register(struct file *file, void *priv, + struct v4l2_dbg_register *reg) +{ + struct au0828_fh *fh = priv; + struct au0828_dev *dev = fh->dev; + + switch (reg->match.type) { + case V4L2_CHIP_MATCH_I2C_DRIVER: + au0828_call_i2c_clients(dev, VIDIOC_DBG_S_REGISTER, reg); + return 0; + default: + return -EINVAL; + } + return 0; +} + +static int vidioc_reqbufs(struct file *file, void *priv, + struct v4l2_requestbuffers *rb) +{ + struct au0828_fh *fh = priv; + struct au0828_dev *dev = fh->dev; + int rc; + + rc = check_dev(dev); + if (rc < 0) + return rc; + + return videobuf_reqbufs(&fh->vb_vidq, rb); +} + +static int vidioc_querybuf(struct file *file, void *priv, + struct v4l2_buffer *b) +{ + struct au0828_fh *fh = priv; + struct au0828_dev *dev = fh->dev; + int rc; + + rc = check_dev(dev); + if (rc < 0) + return rc; + + return videobuf_querybuf(&fh->vb_vidq, b); +} + +static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *b) +{ + struct au0828_fh *fh = priv; + struct au0828_dev *dev = fh->dev; + int rc; + + rc = check_dev(dev); + if (rc < 0) + return rc; + + return videobuf_qbuf(&fh->vb_vidq, b); +} + +static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b) +{ + struct au0828_fh *fh = priv; + struct au0828_dev *dev = fh->dev; + int rc; + + rc = check_dev(dev); + if (rc < 0) + return rc; + + /* Workaround for a bug in the au0828 hardware design that sometimes + results in the colorspace being inverted */ + if (dev->greenscreen_detected == 1) { + dprintk(1, "Detected green frame. Resetting stream...\n"); + au0828_analog_stream_reset(dev); + dev->greenscreen_detected = 0; + } + + return videobuf_dqbuf(&fh->vb_vidq, b, file->f_flags & O_NONBLOCK); +} + +#ifdef CONFIG_VIDEO_V4L1_COMPAT +static int vidiocgmbuf(struct file *file, void *priv, struct video_mbuf *mbuf) +{ + struct au0828_fh *fh = priv; + + return videobuf_cgmbuf(&fh->vb_vidq, mbuf, 8); +} +#endif + +static struct v4l2_file_operations au0828_v4l_fops = { + .owner = THIS_MODULE, + .open = au0828_v4l2_open, + .release = au0828_v4l2_close, + .read = au0828_v4l2_read, + .poll = au0828_v4l2_poll, + .mmap = au0828_v4l2_mmap, + .ioctl = video_ioctl2, +}; + +static const struct v4l2_ioctl_ops video_ioctl_ops = { + .vidioc_querycap = vidioc_querycap, + .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, + .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, + .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, + .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, +#if 0 + .vidioc_g_fmt_vbi_cap = vidioc_g_fmt_vbi_cap, + .vidioc_try_fmt_vbi_cap = vidioc_s_fmt_vbi_cap, + .vidioc_s_fmt_vbi_cap = vidioc_s_fmt_vbi_cap, +#endif + .vidioc_g_audio = vidioc_g_audio, + .vidioc_s_audio = vidioc_s_audio, + .vidioc_cropcap = vidioc_cropcap, +#ifdef AAA + .vidioc_g_fmt_sliced_vbi_cap = vidioc_g_fmt_sliced_vbi_cap, + .vidioc_try_fmt_sliced_vbi_cap = vidioc_try_set_sliced_vbi_cap, + .vidioc_s_fmt_sliced_vbi_cap = vidioc_try_set_sliced_vbi_cap, +#endif + .vidioc_reqbufs = vidioc_reqbufs, + .vidioc_querybuf = vidioc_querybuf, + .vidioc_qbuf = vidioc_qbuf, + .vidioc_dqbuf = vidioc_dqbuf, + .vidioc_s_std = vidioc_s_std, + .vidioc_enum_input = vidioc_enum_input, + .vidioc_g_input = vidioc_g_input, + .vidioc_s_input = vidioc_s_input, + .vidioc_queryctrl = vidioc_queryctrl, + .vidioc_g_ctrl = vidioc_g_ctrl, + .vidioc_s_ctrl = vidioc_s_ctrl, + .vidioc_streamon = vidioc_streamon, + .vidioc_streamoff = vidioc_streamoff, + .vidioc_g_tuner = vidioc_g_tuner, + .vidioc_s_tuner = vidioc_s_tuner, + .vidioc_g_frequency = vidioc_g_frequency, + .vidioc_s_frequency = vidioc_s_frequency, +#ifdef CONFIG_VIDEO_ADV_DEBUG + .vidioc_g_register = vidioc_g_register, + .vidioc_s_register = vidioc_s_register, + .vidioc_g_chip_ident = vidioc_g_chip_ident, +#endif +#ifdef CONFIG_VIDEO_V4L1_COMPAT + .vidiocgmbuf = vidiocgmbuf, +#endif +}; + +static const struct video_device au0828_video_template = { + .fops = &au0828_v4l_fops, + .release = video_device_release, + .ioctl_ops = &video_ioctl_ops, + .minor = -1, + .tvnorms = V4L2_STD_NTSC, + .current_norm = V4L2_STD_NTSC, +}; + +/**************************************************************************/ + +int au0828_analog_register(struct au0828_dev *dev) +{ + int retval = -ENOMEM; + + dprintk(1, "au0828_analog_register called!\n"); + + /* Load the analog demodulator driver (note this would need to be + abstracted out if we ever need to support a different demod) */ + request_module("au8522"); + + /* Load the tuner module, which results in i2c enumeration and + attachment of whatever tuner is on the bus */ + request_module("tuner"); + + init_waitqueue_head(&dev->open); + spin_lock_init(&dev->slock); + mutex_init(&dev->lock); + + INIT_LIST_HEAD(&dev->vidq.active); + INIT_LIST_HEAD(&dev->vidq.queued); + + dev->width = NTSC_STD_W; + dev->height = NTSC_STD_H; + dev->field_size = dev->width * dev->height; + dev->frame_size = dev->field_size << 1; + dev->bytesperline = dev->width << 1; + dev->ctrl_ainput = 0; + + /* allocate and fill v4l2 video struct */ + dev->vdev = video_device_alloc(); + if(NULL == dev->vdev) { + dprintk(1, "Can't allocate video_device.\n"); + return -ENOMEM; + } + + dev->vbi_dev = video_device_alloc(); + if(NULL == dev->vbi_dev) { + dprintk(1, "Can't allocate vbi_device.\n"); + kfree(dev->vdev); + return -ENOMEM; + } + + /* Fill the video capture device struct */ + *dev->vdev = au0828_video_template; + dev->vdev->vfl_type = VID_TYPE_CAPTURE | VID_TYPE_TUNER; + dev->vdev->parent = &dev->usbdev->dev; + strcpy(dev->vdev->name, "au0828a video"); + + /* Setup the VBI device */ + *dev->vbi_dev = au0828_video_template; + dev->vbi_dev->vfl_type = VFL_TYPE_VBI; + dev->vbi_dev->parent = &dev->usbdev->dev; + strcpy(dev->vbi_dev->name, "au0828a vbi"); + + list_add_tail(&dev->au0828list, &au0828_devlist); + + /* Register the v4l2 device */ + if((retval = video_register_device(dev->vdev, VFL_TYPE_GRABBER, -1)) != 0) { + dprintk(1, "unable to register video device (error = %d).\n", retval); + list_del(&dev->au0828list); + video_device_release(dev->vdev); + return -ENODEV; + } + + /* Register the vbi device */ + if((retval = video_register_device(dev->vbi_dev, VFL_TYPE_VBI, -1)) != 0) { + dprintk(1, "unable to register vbi device (error = %d).\n", retval); + list_del(&dev->au0828list); + video_device_release(dev->vbi_dev); + video_device_release(dev->vdev); + return -ENODEV; + } + + dprintk(1, "%s completed!\n", __FUNCTION__); + + return 0; +} + diff --git a/linux/drivers/media/video/au0828/au0828.h b/linux/drivers/media/video/au0828/au0828.h index 9d6a1161d..3b8e3e913 100644 --- a/linux/drivers/media/video/au0828/au0828.h +++ b/linux/drivers/media/video/au0828/au0828.h @@ -24,6 +24,10 @@ #include #include +/* Analog */ +#include +#include + /* DVB */ #include "demux.h" #include "dmxdev.h" @@ -39,8 +43,48 @@ #define URB_COUNT 16 #define URB_BUFSIZE (0xe522) +/* Analog constants */ +#define NTSC_STD_W 720 +#define NTSC_STD_H 480 + +#define AU0828_INTERLACED_DEFAULT 1 +#define V4L2_CID_PRIVATE_SHARPNESS (V4L2_CID_PRIVATE_BASE + 0) + +/* Defination for AU0828 USB transfer */ +#define AU0828_MAX_ISO_BUFS 12 /* maybe resize this value in the future */ +#define AU0828_ISO_PACKETS_PER_URB 10 +#define AU0828_ISO_MAX_FRAME_SIZE (3 * 1024) +#define AU0828_ISO_BUFFER_SIZE (AU0828_ISO_PACKETS_PER_URB * AU0828_ISO_MAX_FRAME_SIZE) + +#define AU0828_MIN_BUF 4 +#define AU0828_DEF_BUF 8 + +#define AU0828_MAX_IMAGES 10 +#define AU0828_FRAME_SIZE (1028 * 1024 * 4) +#define AU0828_URB_TIMEOUT msecs_to_jiffies(AU0828_MAX_ISO_BUFS * AU0828_ISO_PACKETS_PER_URB) + +#define AU0828_MAX_INPUT 4 + +enum au0828_itype { + AU0828_VMUX_COMPOSITE = 1, + AU0828_VMUX_SVIDEO, + AU0828_VMUX_CABLE, + AU0828_VMUX_TELEVISION, + AU0828_VMUX_DVB, + AU0828_VMUX_DEBUG +}; + +struct au0828_input { + enum au0828_itype type; + unsigned int vmux; + unsigned int amux; + void (*audio_setup) (void *priv, int enable); +}; + struct au0828_board { char *name; + struct au0828_input input[AU0828_MAX_INPUT]; + }; struct au0828_dvb { @@ -55,6 +99,83 @@ struct au0828_dvb { int feeding; }; +enum au0828_stream_state { + STREAM_OFF, + STREAM_INTERRUPT, + STREAM_ON +}; + +#define AUVI_INPUT(nr) (&au0828_boards[dev->board].input[nr]) + +/* device state */ +enum au0828_dev_state { + DEV_INITIALIZED = 0x01, + DEV_DISCONNECTED = 0x02, + DEV_MISCONFIGURED = 0x04 +}; + +struct au0828_fh { + struct au0828_dev *dev; + unsigned int stream_on:1; /* Locks streams */ + struct videobuf_queue vb_vidq; + enum v4l2_buf_type type; +}; + +struct au0828_usb_isoc_ctl { + /* max packet size of isoc transaction */ + int max_pkt_size; + + /* number of allocated urbs */ + int num_bufs; + + /* urb for isoc transfers */ + struct urb **urb; + + /* transfer buffers for isoc transfer */ + char **transfer_buffer; + + /* Last buffer command and region */ + u8 cmd; + int pos, size, pktsize; + + /* Last field: ODD or EVEN? */ + int field; + + /* Stores incomplete commands */ + u32 tmp_buf; + int tmp_buf_len; + + /* Stores already requested buffers */ + struct au0828_buffer *buf; + + /* Stores the number of received fields */ + int nfields; + + /* isoc urb callback */ + int (*isoc_copy) (struct au0828_dev *dev, struct urb *urb); + +}; + +/* buffer for one video frame */ +struct au0828_buffer { + /* common v4l buffer stuff -- must be first */ + struct videobuf_buffer vb; + + struct list_head frame; + int top_field; + int receiving; +}; + +struct au0828_dmaqueue { + struct list_head active; + struct list_head queued; + + wait_queue_head_t wq; + + /* Counters to control buffer fill */ + int pos; +}; + struct au0828_dev { struct mutex mutex; struct usb_device *usbdev; @@ -70,16 +191,49 @@ struct au0828_dev { /* Digital */ struct au0828_dvb dvb; + /* Analog */ + struct list_head au0828list; + int users; + unsigned int stream_on:1; /* Locks streams */ + struct video_device *vdev; + struct video_device *vbi_dev; + int width; + int height; + u32 field_size; + u32 frame_size; + u32 bytesperline; + int type; + u8 ctrl_ainput; + __u8 isoc_in_endpointaddr; + u8 isoc_init_ok; + int greenscreen_detected; + unsigned int frame_count; + int ctrl_freq; + int input_type; + unsigned int ctrl_input; + enum au0828_dev_state dev_state; + enum au0828_stream_state stream_state; + wait_queue_head_t open; + + struct mutex lock; + + /* Isoc control struct */ + struct au0828_dmaqueue vidq; + struct au0828_usb_isoc_ctl isoc_ctl; + spinlock_t slock; + + /* usb transfer */ + int alt; /* alternate */ + int max_pkt_size; /* max packet size of isoc transaction */ + int num_alt; /* Number of alternative settings */ + unsigned int *alt_max_pkt_size; /* array of wMaxPacketSize */ + struct urb *urb[AU0828_MAX_ISO_BUFS]; /* urb for isoc transfers */ + char *transfer_buffer[AU0828_MAX_ISO_BUFS];/* transfer buffers for isoc + transfer */ + /* USB / URB Related */ int urb_streaming; struct urb *urbs[URB_COUNT]; - -}; - -struct au0828_buff { - struct au0828_dev *dev; - struct urb *purb; - struct list_head buff_list; }; /* ----------------------------------------------------------- */ @@ -114,6 +268,12 @@ extern int au0828_i2c_unregister(struct au0828_dev *dev); extern void au0828_call_i2c_clients(struct au0828_dev *dev, unsigned int cmd, void *arg); +/* ----------------------------------------------------------- */ +/* au0828-video.c */ +int au0828_analog_register(struct au0828_dev *dev); +int au0828_analog_stream_disable(struct au0828_dev *d); +void au0828_analog_unregister(struct au0828_dev *dev); + /* ----------------------------------------------------------- */ /* au0828-dvb.c */ extern int au0828_dvb_register(struct au0828_dev *dev); -- cgit v1.2.3 From 1ea9fbb3a817b7afd092a07f301699fe53a1d4d6 Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Wed, 11 Mar 2009 02:00:41 -0400 Subject: au0828: workaround a bug in the au0828 i2c handling From: Devin Heitmueller There is an issue related to the i2c clock for addressing the xc5000. The au0828 chip does not support clock stretching, which the xc5000 makes use of. This results in cases where we silently get back garbage in i2c read operations. To work around this issue until we slow down the i2c clock when talking with that specific device. This was not an issue before we had analog support because we never needed to enumerate the i2c bus, and digital tuning never actually needed to perform read operations against the xc5000. Thanks to Michael Krufky and Steven Toth for providing sample hardware, engineering level support, and testing. Priority: normal Signed-off-by: Devin Heitmueller --- linux/drivers/media/video/au0828/au0828-i2c.c | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/au0828/au0828-i2c.c b/linux/drivers/media/video/au0828/au0828-i2c.c index d8cef6ccc..243e98b1d 100644 --- a/linux/drivers/media/video/au0828/au0828-i2c.c +++ b/linux/drivers/media/video/au0828/au0828-i2c.c @@ -141,7 +141,16 @@ static int i2c_sendbytes(struct i2c_adapter *i2c_adap, dprintk(4, "%s()\n", __func__); au0828_write(dev, REG_2FF, 0x01); - au0828_write(dev, REG_202, 0x07); + + /* FIXME: There is a problem with i2c communications with xc5000 that + requires us to slow down the i2c clock until we have a better + strategy (such as using the secondary i2c bus to do firmware + loading */ + if ((msg->addr << 1) == 0xc2) { + au0828_write(dev, REG_202, 0x40); + } else { + au0828_write(dev, REG_202, 0x07); + } /* Hardware needs 8 bit addresses */ au0828_write(dev, REG_203, msg->addr << 1); @@ -192,7 +201,16 @@ static int i2c_readbytes(struct i2c_adapter *i2c_adap, dprintk(4, "%s()\n", __func__); au0828_write(dev, REG_2FF, 0x01); - au0828_write(dev, REG_202, 0x07); + + /* FIXME: There is a problem with i2c communications with xc5000 that + requires us to slow down the i2c clock until we have a better + strategy (such as using the secondary i2c bus to do firmware + loading */ + if ((msg->addr << 1) == 0xc2) { + au0828_write(dev, REG_202, 0x40); + } else { + au0828_write(dev, REG_202, 0x07); + } /* Hardware needs 8 bit addresses */ au0828_write(dev, REG_203, msg->addr << 1); -- cgit v1.2.3 From 923bf375eea7fd01b29ae6f94e88d9c39c5affb1 Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Wed, 11 Mar 2009 02:00:43 -0400 Subject: au0828: add analog profile for the HVR-850 From: Devin Heitmueller Add the analog parameters to the device profile for the HVR-850 Thanks to Michael Krufky and Steven Toth for providing sample hardware, engineering level support, and testing. Priority: normal Signed-off-by: Devin Heitmueller Signed-off-by: Michael Krufky --- linux/drivers/media/video/au0828/au0828-cards.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) (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 aa79e6b7e..8b7ad43ed 100644 --- a/linux/drivers/media/video/au0828/au0828-cards.c +++ b/linux/drivers/media/video/au0828/au0828-cards.c @@ -40,6 +40,25 @@ struct au0828_board au0828_boards[] = { }, [AU0828_BOARD_HAUPPAUGE_HVR850] = { .name = "Hauppauge HVR850", + .input = { + { + .type = AU0828_VMUX_TELEVISION, + .vmux = AU8522_COMPOSITE_CH4_SIF, + .amux = AU8522_AUDIO_SIF, + }, + { + .type = AU0828_VMUX_COMPOSITE, + .vmux = AU8522_COMPOSITE_CH1, + .amux = AU8522_AUDIO_NONE, + .audio_setup = hvr950q_cs5340_audio, + }, + { + .type = AU0828_VMUX_SVIDEO, + .vmux = AU8522_SVIDEO_CH13, + .amux = AU8522_AUDIO_NONE, + .audio_setup = hvr950q_cs5340_audio, + }, + }, }, [AU0828_BOARD_HAUPPAUGE_HVR950Q] = { .name = "Hauppauge HVR950Q", -- cgit v1.2.3 From 7f62cf2d7360ac3b7f2fac64950706a588db8977 Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Wed, 11 Mar 2009 02:00:45 -0400 Subject: au8522: add mutex protecting use of hybrid state From: Devin Heitmueller Access using the hybrid state framework requires the list to be protected by a mutex. Thanks to Michael Krufky for reporting this during a code review. Priority: normal Signed-off-by: Devin Heitmueller Signed-off-by: Michael Krufky --- linux/drivers/media/dvb/frontends/au8522_dig.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/frontends/au8522_dig.c b/linux/drivers/media/dvb/frontends/au8522_dig.c index 00d783ce2..27e2e0730 100644 --- a/linux/drivers/media/dvb/frontends/au8522_dig.c +++ b/linux/drivers/media/dvb/frontends/au8522_dig.c @@ -34,6 +34,7 @@ static int debug; /* Despite the name "hybrid_tuner", the framework works just as well for hybrid demodulators as well... */ static LIST_HEAD(hybrid_tuner_instance_list); +static DEFINE_MUTEX(au8522_list_mutex); #define dprintk(arg...) do { \ if (debug) \ @@ -795,15 +796,23 @@ static struct dvb_frontend_ops au8522_ops; int au8522_get_state(struct au8522_state **state, struct i2c_adapter *i2c, u8 client_address) { - return hybrid_tuner_request_state(struct au8522_state, (*state), - hybrid_tuner_instance_list, - i2c, client_address, "au8522"); + int ret; + + mutex_lock(&au8522_list_mutex); + ret = hybrid_tuner_request_state(struct au8522_state, (*state), + hybrid_tuner_instance_list, + i2c, client_address, "au8522"); + mutex_unlock(&au8522_list_mutex); + + return ret; } void au8522_release_state(struct au8522_state *state) { + mutex_lock(&au8522_list_mutex); if (state != NULL) hybrid_tuner_release_state(state); + mutex_unlock(&au8522_list_mutex); } -- cgit v1.2.3 From 3c1c7dc1d05a143350b6c3467e6bf52144189db0 Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Wed, 11 Mar 2009 02:00:47 -0400 Subject: au0828: Rework the way the analog video binding occurs From: Devin Heitmueller Rework the way boards are managed so that we can change the board description based on the Hauppauge eeprom (modeled after cx88-cards.c). Also, make sure that we don't load the analog stack if there are no analog inputs defined in the board profile. Thanks to Michael Krufky for providing information on the various ways different Hauppauge boards can be configured. Priority: normal Signed-off-by: Devin Heitmueller Signed-off-by: Michael Krufky --- linux/drivers/media/video/au0828/au0828-cards.c | 45 +++++++++++++++++++++++-- linux/drivers/media/video/au0828/au0828-core.c | 11 +++--- linux/drivers/media/video/au0828/au0828-dvb.c | 2 +- linux/drivers/media/video/au0828/au0828-video.c | 40 +++++++++------------- linux/drivers/media/video/au0828/au0828.h | 7 ++-- 5 files changed, 70 insertions(+), 35 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 8b7ad43ed..e10b1b922 100644 --- a/linux/drivers/media/video/au0828/au0828-cards.c +++ b/linux/drivers/media/video/au0828/au0828-cards.c @@ -22,6 +22,8 @@ #include "au0828.h" #include "au0828-cards.h" #include "au8522.h" +#include "media/tuner.h" +#include "media/v4l2-common.h" void hvr950q_cs5340_audio(void *priv, int enable) { @@ -37,9 +39,13 @@ void hvr950q_cs5340_audio(void *priv, int enable) struct au0828_board au0828_boards[] = { [AU0828_BOARD_UNKNOWN] = { .name = "Unknown board", + .tuner_type = UNSET, + .tuner_addr = ADDR_UNSET, }, [AU0828_BOARD_HAUPPAUGE_HVR850] = { .name = "Hauppauge HVR850", + .tuner_type = TUNER_XC5000, + .tuner_addr = 0x61, .input = { { .type = AU0828_VMUX_TELEVISION, @@ -62,6 +68,8 @@ struct au0828_board au0828_boards[] = { }, [AU0828_BOARD_HAUPPAUGE_HVR950Q] = { .name = "Hauppauge HVR950Q", + .tuner_type = TUNER_XC5000, + .tuner_addr = 0x61, .input = { { .type = AU0828_VMUX_TELEVISION, @@ -84,12 +92,18 @@ struct au0828_board au0828_boards[] = { }, [AU0828_BOARD_HAUPPAUGE_HVR950Q_MXL] = { .name = "Hauppauge HVR950Q rev xxF8", + .tuner_type = UNSET, + .tuner_addr = ADDR_UNSET, }, [AU0828_BOARD_DVICO_FUSIONHDTV7] = { .name = "DViCO FusionHDTV USB", + .tuner_type = UNSET, + .tuner_addr = ADDR_UNSET, }, [AU0828_BOARD_HAUPPAUGE_WOODBURY] = { .name = "Hauppauge Woodbury", + .tuner_type = UNSET, + .tuner_addr = ADDR_UNSET, }, }; @@ -102,7 +116,7 @@ int au0828_tuner_callback(void *priv, int component, int command, int arg) dprintk(1, "%s()\n", __func__); - switch (dev->board) { + switch (dev->boardnr) { case AU0828_BOARD_HAUPPAUGE_HVR850: case AU0828_BOARD_HAUPPAUGE_HVR950Q: case AU0828_BOARD_HAUPPAUGE_HVR950Q_MXL: @@ -131,6 +145,7 @@ static void hauppauge_eeprom(struct au0828_dev *dev, u8 *eeprom_data) struct tveeprom tv; tveeprom_hauppauge_analog(&dev->i2c_client, &tv, eeprom_data); + dev->board.tuner_type = tv.tuner_type; /* Make sure we support the board model */ switch (tv.model) { @@ -157,15 +172,20 @@ static void hauppauge_eeprom(struct au0828_dev *dev, u8 *eeprom_data) void au0828_card_setup(struct au0828_dev *dev) { static u8 eeprom[256]; + struct tuner_setup tun_setup; + unsigned int mode_mask = T_ANALOG_TV | + T_DIGITAL_TV; dprintk(1, "%s()\n", __func__); + memcpy(&dev->board, &au0828_boards[dev->boardnr], sizeof(dev->board)); + if (dev->i2c_rc == 0) { dev->i2c_client.addr = 0xa0 >> 1; tveeprom_read(&dev->i2c_client, eeprom, sizeof(eeprom)); } - switch (dev->board) { + switch (dev->boardnr) { case AU0828_BOARD_HAUPPAUGE_HVR850: case AU0828_BOARD_HAUPPAUGE_HVR950Q: case AU0828_BOARD_HAUPPAUGE_HVR950Q_MXL: @@ -174,6 +194,25 @@ void au0828_card_setup(struct au0828_dev *dev) hauppauge_eeprom(dev, eeprom+0xa0); break; } + + if (dev->board.input != NULL) { + /* Load the analog demodulator driver (note this would need to + be abstracted out if we ever need to support a different + demod) */ + request_module("au8522"); + } + + /* Setup tuners */ + if (dev->board.tuner_type != TUNER_ABSENT) { + /* Load the tuner module, which does the attach */ + request_module("tuner"); + + tun_setup.mode_mask = mode_mask; + tun_setup.type = dev->board.tuner_type; + tun_setup.addr = dev->board.tuner_addr; + tun_setup.tuner_callback = au0828_tuner_callback; + au0828_call_i2c_clients(dev, TUNER_SET_TYPE_ADDR, &tun_setup); + } } /* @@ -185,7 +224,7 @@ void au0828_gpio_setup(struct au0828_dev *dev) { dprintk(1, "%s()\n", __func__); - switch (dev->board) { + switch (dev->boardnr) { case AU0828_BOARD_HAUPPAUGE_HVR850: case AU0828_BOARD_HAUPPAUGE_HVR950Q: case AU0828_BOARD_HAUPPAUGE_HVR950Q_MXL: diff --git a/linux/drivers/media/video/au0828/au0828-core.c b/linux/drivers/media/video/au0828/au0828-core.c index 0ed270d22..4eca268bb 100644 --- a/linux/drivers/media/video/au0828/au0828-core.c +++ b/linux/drivers/media/video/au0828/au0828-core.c @@ -147,7 +147,8 @@ static void au0828_usb_disconnect(struct usb_interface *interface) /* Digital TV */ au0828_dvb_unregister(dev); - au0828_analog_unregister(dev); + if (dev->board.input != NULL) + au0828_analog_unregister(dev); /* I2C */ au0828_i2c_unregister(dev); @@ -190,7 +191,7 @@ static int au0828_usb_probe(struct usb_interface *interface, mutex_init(&dev->mutex); mutex_init(&dev->dvb.lock); dev->usbdev = usbdev; - dev->board = id->driver_info; + dev->boardnr = id->driver_info; usb_set_intfdata(interface, dev); @@ -231,14 +232,14 @@ static int au0828_usb_probe(struct usb_interface *interface, au0828_card_setup(dev); /* Analog TV */ - au0828_analog_register(dev); + if (dev->board.input != NULL) + au0828_analog_register(dev); /* Digital TV */ au0828_dvb_register(dev); printk(KERN_INFO "Registered device AU0828 [%s]\n", - au0828_boards[dev->board].name == NULL ? "Unset" : - au0828_boards[dev->board].name); + dev->board.name == NULL ? "Unset" : dev->board.name); return 0; } diff --git a/linux/drivers/media/video/au0828/au0828-dvb.c b/linux/drivers/media/video/au0828/au0828-dvb.c index 9966f83d5..104f15cc3 100644 --- a/linux/drivers/media/video/au0828/au0828-dvb.c +++ b/linux/drivers/media/video/au0828/au0828-dvb.c @@ -383,7 +383,7 @@ int au0828_dvb_register(struct au0828_dev *dev) dprintk(1, "%s()\n", __func__); /* init frontend */ - switch (dev->board) { + switch (dev->boardnr) { case AU0828_BOARD_HAUPPAUGE_HVR850: case AU0828_BOARD_HAUPPAUGE_HVR950Q: dvb->frontend = dvb_attach(au8522_attach, diff --git a/linux/drivers/media/video/au0828/au0828-video.c b/linux/drivers/media/video/au0828/au0828-video.c index 016596b1e..7e3fbdf54 100644 --- a/linux/drivers/media/video/au0828/au0828-video.c +++ b/linux/drivers/media/video/au0828/au0828-video.c @@ -1017,7 +1017,7 @@ static int vidioc_querycap(struct file *file, void *priv, memset(cap, 0, sizeof(*cap)); strlcpy(cap->driver, "au0828", sizeof(cap->driver)); - strlcpy(cap->card, au0828_boards[dev->board].name, sizeof(cap->card)); + strlcpy(cap->card, dev->board.name, sizeof(cap->card)); strlcpy(cap->bus_info, dev->usbdev->dev.bus_id, sizeof(cap->bus_info)); cap->version = AU0828_VERSION_CODE; @@ -1131,14 +1131,14 @@ static int vidioc_enum_input(struct file *file, void *priv, if(tmp > AU0828_MAX_INPUT) return -EINVAL; - if(AUVI_INPUT(tmp)->type == 0) + if(AUVI_INPUT(tmp).type == 0) return -EINVAL; memset(input, 0, sizeof(*input)); input->index = tmp; - strcpy(input->name, inames[AUVI_INPUT(tmp)->type]); - if((AUVI_INPUT(tmp)->type == AU0828_VMUX_TELEVISION) || - (AUVI_INPUT(tmp)->type == AU0828_VMUX_CABLE)) + strcpy(input->name, inames[AUVI_INPUT(tmp).type]); + if((AUVI_INPUT(tmp).type == AU0828_VMUX_TELEVISION) || + (AUVI_INPUT(tmp).type == AU0828_VMUX_CABLE)) input->type |= V4L2_INPUT_TYPE_TUNER; else input->type |= V4L2_INPUT_TYPE_CAMERA; @@ -1167,11 +1167,11 @@ static int vidioc_s_input(struct file *file, void *priv, unsigned int index) index); if(index >= AU0828_MAX_INPUT) return -EINVAL; - if(AUVI_INPUT(index)->type == 0) + if(AUVI_INPUT(index).type == 0) return -EINVAL; dev->ctrl_input = index; - switch(AUVI_INPUT(index)->type) { + switch(AUVI_INPUT(index).type) { case AU0828_VMUX_SVIDEO: { dev->input_type = AU0828_VMUX_SVIDEO; @@ -1191,13 +1191,13 @@ static int vidioc_s_input(struct file *file, void *priv, unsigned int index) ; } - route.input = AUVI_INPUT(index)->vmux; + route.input = AUVI_INPUT(index).vmux; route.output = 0; au0828_call_i2c_clients(dev, VIDIOC_INT_S_VIDEO_ROUTING, &route); for (i = 0; i < AU0828_MAX_INPUT; i++) { int enable = 0; - if (AUVI_INPUT(i)->audio_setup == NULL) { + if (AUVI_INPUT(i).audio_setup == NULL) { continue; } @@ -1206,18 +1206,18 @@ static int vidioc_s_input(struct file *file, void *priv, unsigned int index) else enable = 0; if (enable) { - (AUVI_INPUT(i)->audio_setup)(dev, enable); + (AUVI_INPUT(i).audio_setup)(dev, enable); } else { /* Make sure we leave it turned on if some other input is routed to this callback */ - if ((AUVI_INPUT(i)->audio_setup) != - ((AUVI_INPUT(index)->audio_setup))) { - (AUVI_INPUT(i)->audio_setup)(dev, enable); + if ((AUVI_INPUT(i).audio_setup) != + ((AUVI_INPUT(index).audio_setup))) { + (AUVI_INPUT(i).audio_setup)(dev, enable); } } } - route.input = AUVI_INPUT(index)->amux; + route.input = AUVI_INPUT(index).amux; au0828_call_i2c_clients(dev, VIDIOC_INT_S_AUDIO_ROUTING, &route); return 0; @@ -1423,10 +1423,10 @@ static int vidioc_streamoff(struct file *file, void *priv, } for (i = 0; i < AU0828_MAX_INPUT; i++) { - if (AUVI_INPUT(i)->audio_setup == NULL) { + if (AUVI_INPUT(i).audio_setup == NULL) { continue; } - (AUVI_INPUT(i)->audio_setup)(dev, 0); + (AUVI_INPUT(i).audio_setup)(dev, 0); } mutex_lock(&dev->lock); @@ -1612,14 +1612,6 @@ int au0828_analog_register(struct au0828_dev *dev) dprintk(1, "au0828_analog_register called!\n"); - /* Load the analog demodulator driver (note this would need to be - abstracted out if we ever need to support a different demod) */ - request_module("au8522"); - - /* Load the tuner module, which results in i2c enumeration and - attachment of whatever tuner is on the bus */ - request_module("tuner"); - init_waitqueue_head(&dev->open); spin_lock_init(&dev->slock); mutex_init(&dev->lock); diff --git a/linux/drivers/media/video/au0828/au0828.h b/linux/drivers/media/video/au0828/au0828.h index 3b8e3e913..2f48ec213 100644 --- a/linux/drivers/media/video/au0828/au0828.h +++ b/linux/drivers/media/video/au0828/au0828.h @@ -83,6 +83,8 @@ struct au0828_input { struct au0828_board { char *name; + unsigned int tuner_type; + unsigned char tuner_addr; struct au0828_input input[AU0828_MAX_INPUT]; }; @@ -105,7 +107,7 @@ enum au0828_stream_state { STREAM_ON }; -#define AUVI_INPUT(nr) (&au0828_boards[dev->board].input[nr]) +#define AUVI_INPUT(nr) (dev->board.input[nr]) /* device state */ enum au0828_dev_state { @@ -179,7 +181,8 @@ struct au0828_dmaqueue { struct au0828_dev { struct mutex mutex; struct usb_device *usbdev; - int board; + int boardnr; + struct au0828_board board; u8 ctrlmsg[64]; /* I2C */ -- cgit v1.2.3 From bebbcb664be46fdeca98fb14b67966b4fa58b667 Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Wed, 11 Mar 2009 02:00:49 -0400 Subject: tveeprom: add the xc5000 tuner to the tveeprom definition From: Devin Heitmueller Prior to now, we never relied on the Hauppauge tveeprom to identify which tuner is associated with the board. Now that the HVR-950q determines what the tuner is based on the eeprom, set the tuner ID appropriately. Thanks to Michael Krufky for providing information on the tveeprom organization. Priority: normal Signed-off-by: Devin Heitmueller Signed-off-by: Michael Krufky --- linux/drivers/media/video/tveeprom.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/tveeprom.c b/linux/drivers/media/video/tveeprom.c index acd601a52..cdea91aae 100644 --- a/linux/drivers/media/video/tveeprom.c +++ b/linux/drivers/media/video/tveeprom.c @@ -262,7 +262,7 @@ hauppauge_tuner[] = { TUNER_ABSENT, "MaxLinear MXL5005_v2"}, { TUNER_PHILIPS_TDA8290, "Philips 18271_8295"}, /* 150-159 */ - { TUNER_ABSENT, "Xceive XC5000"}, + { TUNER_XC5000, "Xceive XC5000"}, { TUNER_ABSENT, "Xceive XC3028L"}, { TUNER_ABSENT, "NXP 18271C2_716x"}, { TUNER_ABSENT, "Xceive XC4000"}, -- cgit v1.2.3 From de945fa2e9213ecf4dba1f9b3a96cc45d18da56c Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Wed, 11 Mar 2009 02:00:53 -0400 Subject: au0828: advertise only NTSC-M (as opposed to all NTSC standards) From: Devin Heitmueller We don't now how to make any variant of NTSC work other than NTSC-M, so don't advertise that we support the other variants. Priority: normal Signed-off-by: Devin Heitmueller --- linux/drivers/media/video/au0828/au0828-video.c | 4 ++-- 1 file changed, 2 insertions(+), 2 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 7e3fbdf54..0162a58c8 100644 --- a/linux/drivers/media/video/au0828/au0828-video.c +++ b/linux/drivers/media/video/au0828/au0828-video.c @@ -1600,8 +1600,8 @@ static const struct video_device au0828_video_template = { .release = video_device_release, .ioctl_ops = &video_ioctl_ops, .minor = -1, - .tvnorms = V4L2_STD_NTSC, - .current_norm = V4L2_STD_NTSC, + .tvnorms = V4L2_STD_NTSC_M, + .current_norm = V4L2_STD_NTSC_M, }; /**************************************************************************/ -- cgit v1.2.3 From 5f01441f863dd75318eba7d46e33689605a7b68a Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Wed, 11 Mar 2009 02:00:55 -0400 Subject: au0828: disable VBI code since it doesn't yet work From: Devin Heitmueller Since the VBI support is not yet working for the au0828, don't advertise the capability or create the /dev/vbi device. Priority: normal Signed-off-by: Devin Heitmueller Signed-off-by: Michael Krufky --- linux/drivers/media/video/au0828/au0828-video.c | 26 +++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 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 0162a58c8..b675df838 100644 --- a/linux/drivers/media/video/au0828/au0828-video.c +++ b/linux/drivers/media/video/au0828/au0828-video.c @@ -705,8 +705,10 @@ void au0828_analog_unregister(struct au0828_dev *dev) mutex_lock(&au0828_sysfs_lock); list_del(&dev->au0828list); - video_unregister_device(dev->vdev); - video_unregister_device(dev->vbi_dev); + if (dev->vdev) + video_unregister_device(dev->vdev); + if (dev->vbi_dev) + video_unregister_device(dev->vbi_dev); mutex_unlock(&au0828_sysfs_lock); } @@ -758,10 +760,12 @@ static int au0828_v4l2_open(struct file *filp) dev = h; type = V4L2_BUF_TYPE_VIDEO_CAPTURE; } +#ifdef VBI_NOT_YET_WORKING if(h->vbi_dev->minor == minor) { dev = h; type = V4L2_BUF_TYPE_VBI_CAPTURE; } +#endif } if(NULL == dev) @@ -935,6 +939,7 @@ static int au0828_set_format(struct au0828_dev *dev, unsigned int cmd, maxwidth = 720; maxheight = 480; +#ifdef VBI_NOT_YET_WORKING if(format->type == V4L2_BUF_TYPE_SLICED_VBI_CAPTURE) { dprintk(1, "VBI format set: to be supported!\n"); return 0; @@ -942,6 +947,7 @@ static int au0828_set_format(struct au0828_dev *dev, unsigned int cmd, if(format->type == V4L2_BUF_TYPE_VBI_CAPTURE) { return 0; } +#endif if(format->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { return -EINVAL; } @@ -1023,8 +1029,10 @@ static int vidioc_querycap(struct file *file, void *priv, cap->version = AU0828_VERSION_CODE; /*set the device capabilities */ - cap->capabilities = V4L2_CAP_VBI_CAPTURE | - V4L2_CAP_VIDEO_CAPTURE | + cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | +#ifdef VBI_NOT_YET_WORKING + V4L2_CAP_VBI_CAPTURE | +#endif V4L2_CAP_AUDIO | V4L2_CAP_READWRITE | V4L2_CAP_STREAMING | @@ -1555,7 +1563,7 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = { .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, -#if 0 +#ifdef VBI_NOT_YET_WORKING .vidioc_g_fmt_vbi_cap = vidioc_g_fmt_vbi_cap, .vidioc_try_fmt_vbi_cap = vidioc_s_fmt_vbi_cap, .vidioc_s_fmt_vbi_cap = vidioc_s_fmt_vbi_cap, @@ -1563,7 +1571,7 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = { .vidioc_g_audio = vidioc_g_audio, .vidioc_s_audio = vidioc_s_audio, .vidioc_cropcap = vidioc_cropcap, -#ifdef AAA +#ifdef VBI_NOT_YET_WORKING .vidioc_g_fmt_sliced_vbi_cap = vidioc_g_fmt_sliced_vbi_cap, .vidioc_try_fmt_sliced_vbi_cap = vidioc_try_set_sliced_vbi_cap, .vidioc_s_fmt_sliced_vbi_cap = vidioc_try_set_sliced_vbi_cap, @@ -1633,12 +1641,14 @@ int au0828_analog_register(struct au0828_dev *dev) return -ENOMEM; } +#ifdef VBI_NOT_YET_WORKING dev->vbi_dev = video_device_alloc(); if(NULL == dev->vbi_dev) { dprintk(1, "Can't allocate vbi_device.\n"); kfree(dev->vdev); return -ENOMEM; } +#endif /* Fill the video capture device struct */ *dev->vdev = au0828_video_template; @@ -1646,11 +1656,13 @@ int au0828_analog_register(struct au0828_dev *dev) dev->vdev->parent = &dev->usbdev->dev; strcpy(dev->vdev->name, "au0828a video"); +#ifdef VBI_NOT_YET_WORKING /* Setup the VBI device */ *dev->vbi_dev = au0828_video_template; dev->vbi_dev->vfl_type = VFL_TYPE_VBI; dev->vbi_dev->parent = &dev->usbdev->dev; strcpy(dev->vbi_dev->name, "au0828a vbi"); +#endif list_add_tail(&dev->au0828list, &au0828_devlist); @@ -1662,6 +1674,7 @@ int au0828_analog_register(struct au0828_dev *dev) return -ENODEV; } +#ifdef VBI_NOT_YET_WORKING /* Register the vbi device */ if((retval = video_register_device(dev->vbi_dev, VFL_TYPE_VBI, -1)) != 0) { dprintk(1, "unable to register vbi device (error = %d).\n", retval); @@ -1670,6 +1683,7 @@ int au0828_analog_register(struct au0828_dev *dev) video_device_release(dev->vdev); return -ENODEV; } +#endif dprintk(1, "%s completed!\n", __FUNCTION__); -- cgit v1.2.3 From 410e73da32e723f9ec79be9d6940568dec36c828 Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Wed, 11 Mar 2009 02:00:56 -0400 Subject: au0828: fix i2c enumeration bug From: Devin Heitmueller There was a bug where enumerating the i2c for devices would result in false positives. The root of the issue was the scanning was using SMBUS_QUICK messages, which are zero length write requests (which our i2c adapter implementation didn't handle). Because we never strobed any bytes onto the bus, the status register would still contain the value from the previous request. Thanks to Michael Krufky and Steven Toth for providing sample hardware, engineering level support, and testing. Priority: normal Signed-off-by: Devin Heitmueller Signed-off-by: Michael Krufky --- linux/drivers/media/video/au0828/au0828-i2c.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/au0828/au0828-i2c.c b/linux/drivers/media/video/au0828/au0828-i2c.c index 243e98b1d..bf0906b52 100644 --- a/linux/drivers/media/video/au0828/au0828-i2c.c +++ b/linux/drivers/media/video/au0828/au0828-i2c.c @@ -157,6 +157,24 @@ static int i2c_sendbytes(struct i2c_adapter *i2c_adap, dprintk(4, "SEND: %02x\n", msg->addr); + /* Deal with i2c_scan */ + if (msg->len == 0) { + /* The analog tuner detection code makes use of the SMBUS_QUICK + message (which involves a zero length i2c write). To avoid + checking the status register when we didn't strobe out any + actual bytes to the bus, just do a read check. This is + consistent with how I saw i2c device checking done in the + USB trace of the Windows driver */ + au0828_write(dev, REG_200, 0x20); + if (!i2c_wait_done(i2c_adap)) + return -EIO; + + if (i2c_wait_read_ack(i2c_adap)) + return -EIO; + + return 0; + } + for (i = 0; i < msg->len;) { dprintk(4, " %02x\n", msg->buf[i]); -- cgit v1.2.3 From bfd1ef181a59f27524db364c847f27957694de75 Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Wed, 11 Mar 2009 02:00:57 -0400 Subject: au0828: make register debug lines easier to read From: Devin Heitmueller Make it a little easier to read the debug messages for register read/write operations Priority: normal Signed-off-by: Devin Heitmueller Signed-off-by: Michael Krufky --- linux/drivers/media/video/au0828/au0828-core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/au0828/au0828-core.c b/linux/drivers/media/video/au0828/au0828-core.c index 4eca268bb..e5c399902 100644 --- a/linux/drivers/media/video/au0828/au0828-core.c +++ b/linux/drivers/media/video/au0828/au0828-core.c @@ -52,13 +52,13 @@ static int recv_control_msg(struct au0828_dev *dev, u16 request, u32 value, u32 au0828_readreg(struct au0828_dev *dev, u16 reg) { recv_control_msg(dev, CMD_REQUEST_IN, 0, reg, dev->ctrlmsg, 1); - dprintk(8, "%s(0x%x) = 0x%x\n", __func__, reg, dev->ctrlmsg[0]); + dprintk(8, "%s(0x%04x) = 0x%02x\n", __func__, reg, dev->ctrlmsg[0]); return dev->ctrlmsg[0]; } u32 au0828_writereg(struct au0828_dev *dev, u16 reg, u32 val) { - dprintk(8, "%s(0x%x, 0x%x)\n", __func__, reg, val); + dprintk(8, "%s(0x%04x, 0x%02x)\n", __func__, reg, val); return send_control_msg(dev, CMD_REQUEST_OUT, val, reg, dev->ctrlmsg, 0); } -- cgit v1.2.3 From 66833094069d442ee8db6a6a95d59c6598335302 Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Wed, 11 Mar 2009 02:00:58 -0400 Subject: au0828: make g_chip_ident call work properly From: Devin Heitmueller Make the g_chip_ident call work for the au0828/au8522. Discovered when testing with the v4l2_compliance tool Priority: normal Signed-off-by: Devin Heitmueller Signed-off-by: Michael Krufky --- linux/drivers/media/video/au0828/au0828-video.c | 8 ++++++++ linux/drivers/media/video/au8522_decoder.c | 1 + 2 files changed, 9 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 b675df838..ae6dac3f2 100644 --- a/linux/drivers/media/video/au0828/au0828-video.c +++ b/linux/drivers/media/video/au0828/au0828-video.c @@ -1352,7 +1352,15 @@ static int vidioc_g_chip_ident(struct file *file, void *priv, chip->ident = V4L2_IDENT_NONE; chip->revision = 0; + if (v4l2_chip_match_host(&chip->match)) { + chip->ident = V4L2_IDENT_AU0828; + return 0; + } + au0828_call_i2c_clients(dev, VIDIOC_DBG_G_CHIP_IDENT, chip); + if (chip->ident == V4L2_IDENT_NONE) + return -EINVAL; + return 0; } diff --git a/linux/drivers/media/video/au8522_decoder.c b/linux/drivers/media/video/au8522_decoder.c index 556b012fc..93f119508 100644 --- a/linux/drivers/media/video/au8522_decoder.c +++ b/linux/drivers/media/video/au8522_decoder.c @@ -637,6 +637,7 @@ static int au8522_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc) break; } + qc->type = 0; return -EINVAL; } -- cgit v1.2.3 From 954299a93e6d076c844770136c359f48049b3d88 Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Wed, 11 Mar 2009 02:01:00 -0400 Subject: au0828: properly handle missing analog USB endpoint From: Devin Heitmueller Move the setup of the analog isoc handler into au0828-video.c, so it does not occur if there is not an .input section defined for the board. Also fixes a case where if there is an input section but the board does not actually have analog support, the digital support will continue to work as expected. Thanks to Michael Krufky for providing sample hardware of various configurations to test with. Priority: normal Signed-off-by: Devin Heitmueller Signed-off-by: Michael Krufky --- linux/drivers/media/video/au0828/au0828-core.c | 30 ++-------------------- linux/drivers/media/video/au0828/au0828-video.c | 33 ++++++++++++++++++++++++- linux/drivers/media/video/au0828/au0828.h | 3 ++- 3 files changed, 36 insertions(+), 30 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/au0828/au0828-core.c b/linux/drivers/media/video/au0828/au0828-core.c index e5c399902..3e1ce6080 100644 --- a/linux/drivers/media/video/au0828/au0828-core.c +++ b/linux/drivers/media/video/au0828/au0828-core.c @@ -166,11 +166,9 @@ static void au0828_usb_disconnect(struct usb_interface *interface) static int au0828_usb_probe(struct usb_interface *interface, const struct usb_device_id *id) { - int ifnum, i; + int ifnum; struct au0828_dev *dev; struct usb_device *usbdev = interface_to_usbdev(interface); - struct usb_host_interface *iface_desc; - struct usb_endpoint_descriptor *endpoint; ifnum = interface->altsetting->desc.bInterfaceNumber; @@ -195,30 +193,6 @@ static int au0828_usb_probe(struct usb_interface *interface, usb_set_intfdata(interface, dev); - /* set au0828 usb interface0 to as5 */ - usb_set_interface(usbdev, - interface->cur_altsetting->desc.bInterfaceNumber, 5); - - /* Figure out which endpoint has the isoc interface */ - iface_desc = interface->cur_altsetting; - for(i = 0; i < iface_desc->desc.bNumEndpoints; i++){ - endpoint = &iface_desc->endpoint[i].desc; - if(((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN) && - ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_ISOC)){ - - /* we find our isoc in endpoint */ - u16 tmp = le16_to_cpu(endpoint->wMaxPacketSize); - dev->max_pkt_size = (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1); - dev->isoc_in_endpointaddr = endpoint->bEndpointAddress; - } - } - if(!(dev->isoc_in_endpointaddr)) { - printk("Could not locate isoc endpoint\n"); - kfree(dev); - return -ENODEV; - } - - /* Power Up the bridge */ au0828_write(dev, REG_600, 1 << 4); @@ -233,7 +207,7 @@ static int au0828_usb_probe(struct usb_interface *interface, /* Analog TV */ if (dev->board.input != NULL) - au0828_analog_register(dev); + au0828_analog_register(dev, interface); /* Digital TV */ au0828_dvb_register(dev); diff --git a/linux/drivers/media/video/au0828/au0828-video.c b/linux/drivers/media/video/au0828/au0828-video.c index ae6dac3f2..e75b8b530 100644 --- a/linux/drivers/media/video/au0828/au0828-video.c +++ b/linux/drivers/media/video/au0828/au0828-video.c @@ -1622,12 +1622,43 @@ static const struct video_device au0828_video_template = { /**************************************************************************/ -int au0828_analog_register(struct au0828_dev *dev) +int au0828_analog_register(struct au0828_dev *dev, + struct usb_interface *interface) { int retval = -ENOMEM; + struct usb_host_interface *iface_desc; + struct usb_endpoint_descriptor *endpoint; + int i; dprintk(1, "au0828_analog_register called!\n"); + /* set au0828 usb interface0 to as5 */ + retval = usb_set_interface(dev->usbdev, + interface->cur_altsetting->desc.bInterfaceNumber, 5); + if (retval != 0) { + printk("Failure setting usb interface0 to as5\n"); + return retval; + } + + /* Figure out which endpoint has the isoc interface */ + iface_desc = interface->cur_altsetting; + for(i = 0; i < iface_desc->desc.bNumEndpoints; i++){ + endpoint = &iface_desc->endpoint[i].desc; + if(((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN) && + ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_ISOC)){ + + /* we find our isoc in endpoint */ + u16 tmp = le16_to_cpu(endpoint->wMaxPacketSize); + dev->max_pkt_size = (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1); + dev->isoc_in_endpointaddr = endpoint->bEndpointAddress; + } + } + if(!(dev->isoc_in_endpointaddr)) { + printk("Could not locate isoc endpoint\n"); + kfree(dev); + return -ENODEV; + } + init_waitqueue_head(&dev->open); spin_lock_init(&dev->slock); mutex_init(&dev->lock); diff --git a/linux/drivers/media/video/au0828/au0828.h b/linux/drivers/media/video/au0828/au0828.h index 2f48ec213..d2e54c8e1 100644 --- a/linux/drivers/media/video/au0828/au0828.h +++ b/linux/drivers/media/video/au0828/au0828.h @@ -273,7 +273,8 @@ extern void au0828_call_i2c_clients(struct au0828_dev *dev, /* ----------------------------------------------------------- */ /* au0828-video.c */ -int au0828_analog_register(struct au0828_dev *dev); +int au0828_analog_register(struct au0828_dev *dev, + struct usb_interface *interface); int au0828_analog_stream_disable(struct au0828_dev *d); void au0828_analog_unregister(struct au0828_dev *dev); -- cgit v1.2.3 From 3f7bd4e3eef22d1416780db3ae3300c16bc21961 Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Wed, 11 Mar 2009 02:01:01 -0400 Subject: au0828: properly handle non-existent analog inputs From: Devin Heitmueller It is not valid to look for dev->board.input == NULL to detect an undefined analog configuration section, since it is a member of the struct and not a pointer (hence it will *always* be non-NULL). Do the check based on whether the first input is actually a valid input type instead. Thanks to Michael Krufky for providing sample hardware of various configurations to test with. Priority: normal Signed-off-by: Devin Heitmueller Signed-off-by: Michael Krufky --- linux/drivers/media/video/au0828/au0828-cards.c | 2 +- linux/drivers/media/video/au0828/au0828-core.c | 4 ++-- linux/drivers/media/video/au0828/au0828.h | 3 ++- 3 files changed, 5 insertions(+), 4 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 e10b1b922..0516c0608 100644 --- a/linux/drivers/media/video/au0828/au0828-cards.c +++ b/linux/drivers/media/video/au0828/au0828-cards.c @@ -195,7 +195,7 @@ void au0828_card_setup(struct au0828_dev *dev) break; } - if (dev->board.input != NULL) { + if (AUVI_INPUT(0).type != AU0828_VMUX_UNDEFINED) { /* Load the analog demodulator driver (note this would need to be abstracted out if we ever need to support a different demod) */ diff --git a/linux/drivers/media/video/au0828/au0828-core.c b/linux/drivers/media/video/au0828/au0828-core.c index 3e1ce6080..a477c8587 100644 --- a/linux/drivers/media/video/au0828/au0828-core.c +++ b/linux/drivers/media/video/au0828/au0828-core.c @@ -147,7 +147,7 @@ static void au0828_usb_disconnect(struct usb_interface *interface) /* Digital TV */ au0828_dvb_unregister(dev); - if (dev->board.input != NULL) + if (AUVI_INPUT(0).type != AU0828_VMUX_UNDEFINED) au0828_analog_unregister(dev); /* I2C */ @@ -206,7 +206,7 @@ static int au0828_usb_probe(struct usb_interface *interface, au0828_card_setup(dev); /* Analog TV */ - if (dev->board.input != NULL) + if (AUVI_INPUT(0).type != AU0828_VMUX_UNDEFINED) au0828_analog_register(dev, interface); /* Digital TV */ diff --git a/linux/drivers/media/video/au0828/au0828.h b/linux/drivers/media/video/au0828/au0828.h index d2e54c8e1..590d15e46 100644 --- a/linux/drivers/media/video/au0828/au0828.h +++ b/linux/drivers/media/video/au0828/au0828.h @@ -66,7 +66,8 @@ #define AU0828_MAX_INPUT 4 enum au0828_itype { - AU0828_VMUX_COMPOSITE = 1, + AU0828_VMUX_UNDEFINED = 0, + AU0828_VMUX_COMPOSITE, AU0828_VMUX_SVIDEO, AU0828_VMUX_CABLE, AU0828_VMUX_TELEVISION, -- cgit v1.2.3 From 10fd27b598ce42b251b665f6922961ddac7ff90e Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Wed, 11 Mar 2009 02:01:02 -0400 Subject: au0828: fix panic on disconnect if analog initialization failed From: Devin Heitmueller If the analog initialization failed to create the video device, we never actually add the entry to the au0828_devlist. Therefore a panic occurs when unregistering the analog subsystem. Make it so we only remove the entry from the list if we added it to the list in the first place. Priority: normal Signed-off-by: Devin Heitmueller Signed-off-by: Michael Krufky --- linux/drivers/media/video/au0828/au0828-video.c | 5 +++-- 1 file changed, 3 insertions(+), 2 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 e75b8b530..b9ce10508 100644 --- a/linux/drivers/media/video/au0828/au0828-video.c +++ b/linux/drivers/media/video/au0828/au0828-video.c @@ -704,9 +704,10 @@ void au0828_analog_unregister(struct au0828_dev *dev) dprintk(1, "au0828_release_resources called\n"); mutex_lock(&au0828_sysfs_lock); - list_del(&dev->au0828list); - if (dev->vdev) + if (dev->vdev) { + list_del(&dev->au0828list); video_unregister_device(dev->vdev); + } if (dev->vbi_dev) video_unregister_device(dev->vbi_dev); -- cgit v1.2.3 From 1c6b90fa7084d63133a8418affbf10267f674abb Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Wed, 11 Mar 2009 02:01:04 -0400 Subject: au0828: Convert to use v4l2_device/subdev framework From: Devin Heitmueller Convert over to using the new subdev framework for the au0828 bridge. This includes using the new i2c probing mechanism. Priority: normal Signed-off-by: Devin Heitmueller --- linux/drivers/media/video/au0828/au0828-cards.c | 13 +++++++++++-- linux/drivers/media/video/au0828/au0828-core.c | 15 ++++++++++++++- linux/drivers/media/video/au0828/au0828-i2c.c | 5 ++--- linux/drivers/media/video/au0828/au0828-video.c | 2 +- linux/drivers/media/video/au0828/au0828.h | 4 +++- 5 files changed, 31 insertions(+), 8 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 0516c0608..a12c92c03 100644 --- a/linux/drivers/media/video/au0828/au0828-cards.c +++ b/linux/drivers/media/video/au0828/au0828-cards.c @@ -173,6 +173,7 @@ void au0828_card_setup(struct au0828_dev *dev) { static u8 eeprom[256]; struct tuner_setup tun_setup; + struct v4l2_subdev *sd; unsigned int mode_mask = T_ANALOG_TV | T_DIGITAL_TV; @@ -199,13 +200,21 @@ void au0828_card_setup(struct au0828_dev *dev) /* Load the analog demodulator driver (note this would need to be abstracted out if we ever need to support a different demod) */ - request_module("au8522"); + sd = v4l2_i2c_new_subdev(&dev->i2c_adap, "au8522", "au8522", + 0x8e >> 1); + if (sd == NULL) { + printk("analog subdev registration failure\n"); + } } /* Setup tuners */ if (dev->board.tuner_type != TUNER_ABSENT) { /* Load the tuner module, which does the attach */ - request_module("tuner"); + sd = v4l2_i2c_new_subdev(&dev->i2c_adap, "tuner", "tuner", + dev->board.tuner_addr); + if (sd == NULL) { + printk("analog tuner subdev registration failure\n"); + } tun_setup.mode_mask = mode_mask; tun_setup.type = dev->board.tuner_type; diff --git a/linux/drivers/media/video/au0828/au0828-core.c b/linux/drivers/media/video/au0828/au0828-core.c index a477c8587..327c6edde 100644 --- a/linux/drivers/media/video/au0828/au0828-core.c +++ b/linux/drivers/media/video/au0828/au0828-core.c @@ -153,6 +153,8 @@ static void au0828_usb_disconnect(struct usb_interface *interface) /* I2C */ au0828_i2c_unregister(dev); + v4l2_device_unregister(&dev->v4l2_dev); + usb_set_intfdata(interface, NULL); mutex_lock(&dev->mutex); @@ -166,7 +168,7 @@ static void au0828_usb_disconnect(struct usb_interface *interface) static int au0828_usb_probe(struct usb_interface *interface, const struct usb_device_id *id) { - int ifnum; + int ifnum, retval; struct au0828_dev *dev; struct usb_device *usbdev = interface_to_usbdev(interface); @@ -193,6 +195,17 @@ static int au0828_usb_probe(struct usb_interface *interface, usb_set_intfdata(interface, dev); + /* Create the v4l2_device */ + snprintf(dev->v4l2_dev.name, sizeof(dev->v4l2_dev.name), "%s-%03d", + "au0828", 0); + retval = v4l2_device_register(&dev->usbdev->dev, &dev->v4l2_dev); + if (retval) { + printk(KERN_ERR "%s() v4l2_device_register failed\n", + __func__); + kfree(dev); + return -EIO; + } + /* Power Up the bridge */ au0828_write(dev, REG_600, 1 << 4); diff --git a/linux/drivers/media/video/au0828/au0828-i2c.c b/linux/drivers/media/video/au0828/au0828-i2c.c index bf0906b52..9f3818723 100644 --- a/linux/drivers/media/video/au0828/au0828-i2c.c +++ b/linux/drivers/media/video/au0828/au0828-i2c.c @@ -349,7 +349,6 @@ static struct i2c_adapter au0828_i2c_adap_template = { .owner = THIS_MODULE, .id = I2C_HW_B_AU0828, .algo = &au0828_i2c_algo_template, - .class = I2C_CLASS_TV_ANALOG, .client_register = attach_inform, .client_unregister = detach_inform, }; @@ -396,9 +395,9 @@ int au0828_i2c_register(struct au0828_dev *dev) strlcpy(dev->i2c_adap.name, DRIVER_NAME, sizeof(dev->i2c_adap.name)); - dev->i2c_algo.data = dev; + dev->i2c_adap.algo = &dev->i2c_algo; dev->i2c_adap.algo_data = dev; - i2c_set_adapdata(&dev->i2c_adap, dev); + i2c_set_adapdata(&dev->i2c_adap, &dev->v4l2_dev); i2c_add_adapter(&dev->i2c_adap); dev->i2c_client.adapter = &dev->i2c_adap; diff --git a/linux/drivers/media/video/au0828/au0828-video.c b/linux/drivers/media/video/au0828/au0828-video.c index b9ce10508..72f2b67cb 100644 --- a/linux/drivers/media/video/au0828/au0828-video.c +++ b/linux/drivers/media/video/au0828/au0828-video.c @@ -1025,7 +1025,7 @@ static int vidioc_querycap(struct file *file, void *priv, memset(cap, 0, sizeof(*cap)); strlcpy(cap->driver, "au0828", sizeof(cap->driver)); strlcpy(cap->card, dev->board.name, sizeof(cap->card)); - strlcpy(cap->bus_info, dev->usbdev->dev.bus_id, sizeof(cap->bus_info)); + strlcpy(cap->bus_info, dev->v4l2_dev.name, sizeof(cap->bus_info)); cap->version = AU0828_VERSION_CODE; diff --git a/linux/drivers/media/video/au0828/au0828.h b/linux/drivers/media/video/au0828/au0828.h index 590d15e46..876b18cfb 100644 --- a/linux/drivers/media/video/au0828/au0828.h +++ b/linux/drivers/media/video/au0828/au0828.h @@ -27,6 +27,7 @@ /* Analog */ #include #include +#include /* DVB */ #include "demux.h" @@ -188,7 +189,7 @@ struct au0828_dev { /* I2C */ struct i2c_adapter i2c_adap; - struct i2c_algo_bit_data i2c_algo; + struct i2c_algorithm i2c_algo; struct i2c_client i2c_client; u32 i2c_rc; @@ -197,6 +198,7 @@ struct au0828_dev { /* Analog */ struct list_head au0828list; + struct v4l2_device v4l2_dev; int users; unsigned int stream_on:1; /* Locks streams */ struct video_device *vdev; -- cgit v1.2.3 From 702a5e887ca16703b8eba2a7f3ee4e62a1f52658 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 11 Mar 2009 08:25:47 +0100 Subject: radio: remove uaccess include From: Hans Verkuil This include isn't needed and so can be removed. Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/radio/radio-aimslab.c | 1 - linux/drivers/media/radio/radio-aztech.c | 1 - linux/drivers/media/radio/radio-cadet.c | 1 - linux/drivers/media/radio/radio-gemtek-pci.c | 1 - linux/drivers/media/radio/radio-gemtek.c | 1 - linux/drivers/media/radio/radio-maestro.c | 1 - linux/drivers/media/radio/radio-maxiradio.c | 1 - linux/drivers/media/radio/radio-rtrack2.c | 1 - linux/drivers/media/radio/radio-sf16fmi.c | 1 - linux/drivers/media/radio/radio-sf16fmr2.c | 1 - linux/drivers/media/radio/radio-terratec.c | 1 - linux/drivers/media/radio/radio-trust.c | 1 - linux/drivers/media/radio/radio-typhoon.c | 1 - linux/drivers/media/radio/radio-zoltrix.c | 1 - 14 files changed, 14 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/radio/radio-aimslab.c b/linux/drivers/media/radio/radio-aimslab.c index 7c3a81ad9..29834df05 100644 --- a/linux/drivers/media/radio/radio-aimslab.c +++ b/linux/drivers/media/radio/radio-aimslab.c @@ -35,7 +35,6 @@ #include /* kernel radio structs */ #include /* for KERNEL_VERSION MACRO */ #include /* outb, outb_p */ -#include /* copy to/from user */ #include #include #include "compat.h" diff --git a/linux/drivers/media/radio/radio-aztech.c b/linux/drivers/media/radio/radio-aztech.c index 8826b90a3..6b4081a51 100644 --- a/linux/drivers/media/radio/radio-aztech.c +++ b/linux/drivers/media/radio/radio-aztech.c @@ -32,7 +32,6 @@ #include /* kernel radio structs */ #include /* for KERNEL_VERSION MACRO */ #include /* outb, outb_p */ -#include /* copy to/from user */ #include #include #include "compat.h" diff --git a/linux/drivers/media/radio/radio-cadet.c b/linux/drivers/media/radio/radio-cadet.c index 373a34fde..2fd4aae2e 100644 --- a/linux/drivers/media/radio/radio-cadet.c +++ b/linux/drivers/media/radio/radio-cadet.c @@ -39,7 +39,6 @@ #include #include #include /* outb, outb_p */ -#include /* copy to/from user */ #include #include #include "compat.h" diff --git a/linux/drivers/media/radio/radio-gemtek-pci.c b/linux/drivers/media/radio/radio-gemtek-pci.c index b68e2ba4c..13972c431 100644 --- a/linux/drivers/media/radio/radio-gemtek-pci.c +++ b/linux/drivers/media/radio/radio-gemtek-pci.c @@ -48,7 +48,6 @@ #include #include /* for KERNEL_VERSION MACRO */ #include -#include #include #include #include "compat.h" diff --git a/linux/drivers/media/radio/radio-gemtek.c b/linux/drivers/media/radio/radio-gemtek.c index 0cb1cb0a1..d991476e8 100644 --- a/linux/drivers/media/radio/radio-gemtek.c +++ b/linux/drivers/media/radio/radio-gemtek.c @@ -24,7 +24,6 @@ #include /* for KERNEL_VERSION MACRO */ #include #include /* outb, outb_p */ -#include /* copy to/from user */ #include #include #include "compat.h" diff --git a/linux/drivers/media/radio/radio-maestro.c b/linux/drivers/media/radio/radio-maestro.c index b35092f30..387bf416b 100644 --- a/linux/drivers/media/radio/radio-maestro.c +++ b/linux/drivers/media/radio/radio-maestro.c @@ -26,7 +26,6 @@ #include #include #include -#include #include #include #include "compat.h" diff --git a/linux/drivers/media/radio/radio-maxiradio.c b/linux/drivers/media/radio/radio-maxiradio.c index fa2c5f1ef..a31ea2f5e 100644 --- a/linux/drivers/media/radio/radio-maxiradio.c +++ b/linux/drivers/media/radio/radio-maxiradio.c @@ -42,7 +42,6 @@ #include #include /* for KERNEL_VERSION MACRO */ #include -#include #include #include #include "compat.h" diff --git a/linux/drivers/media/radio/radio-rtrack2.c b/linux/drivers/media/radio/radio-rtrack2.c index 92fae4acd..20153db92 100644 --- a/linux/drivers/media/radio/radio-rtrack2.c +++ b/linux/drivers/media/radio/radio-rtrack2.c @@ -17,7 +17,6 @@ #include #include /* for KERNEL_VERSION MACRO */ #include /* outb, outb_p */ -#include /* copy to/from user */ #include #include #include "compat.h" diff --git a/linux/drivers/media/radio/radio-sf16fmi.c b/linux/drivers/media/radio/radio-sf16fmi.c index 392aa27e0..b517b3671 100644 --- a/linux/drivers/media/radio/radio-sf16fmi.c +++ b/linux/drivers/media/radio/radio-sf16fmi.c @@ -26,7 +26,6 @@ #include #include /* kernel radio structs */ #include /* outb, outb_p */ -#include /* copy to/from user */ #include #include #include "compat.h" diff --git a/linux/drivers/media/radio/radio-sf16fmr2.c b/linux/drivers/media/radio/radio-sf16fmr2.c index 34de92f82..65e303dba 100644 --- a/linux/drivers/media/radio/radio-sf16fmr2.c +++ b/linux/drivers/media/radio/radio-sf16fmr2.c @@ -22,7 +22,6 @@ #include #include /* for KERNEL_VERSION MACRO */ #include /* outb, outb_p */ -#include /* copy to/from user */ #include #include #include "compat.h" diff --git a/linux/drivers/media/radio/radio-terratec.c b/linux/drivers/media/radio/radio-terratec.c index 9bb1773ca..db5481119 100644 --- a/linux/drivers/media/radio/radio-terratec.c +++ b/linux/drivers/media/radio/radio-terratec.c @@ -32,7 +32,6 @@ #include #include /* for KERNEL_VERSION MACRO */ #include /* outb, outb_p */ -#include /* copy to/from user */ #include #include #include "compat.h" diff --git a/linux/drivers/media/radio/radio-trust.c b/linux/drivers/media/radio/radio-trust.c index 9d2dcb0a7..8b925adb5 100644 --- a/linux/drivers/media/radio/radio-trust.c +++ b/linux/drivers/media/radio/radio-trust.c @@ -22,7 +22,6 @@ #include /* for KERNEL_VERSION MACRO */ #include #include -#include #include #include #include "compat.h" diff --git a/linux/drivers/media/radio/radio-typhoon.c b/linux/drivers/media/radio/radio-typhoon.c index 11e3775ab..98e4ce142 100644 --- a/linux/drivers/media/radio/radio-typhoon.c +++ b/linux/drivers/media/radio/radio-typhoon.c @@ -37,7 +37,6 @@ #include /* for KERNEL_VERSION MACRO */ #include /* kernel radio structs */ #include /* outb, outb_p */ -#include /* copy to/from user */ #include #include #include "compat.h" diff --git a/linux/drivers/media/radio/radio-zoltrix.c b/linux/drivers/media/radio/radio-zoltrix.c index 3662f68da..0ae5f0d19 100644 --- a/linux/drivers/media/radio/radio-zoltrix.c +++ b/linux/drivers/media/radio/radio-zoltrix.c @@ -37,7 +37,6 @@ #include #include /* for KERNEL_VERSION MACRO */ #include /* outb, outb_p */ -#include /* copy to/from user */ #include #include #include "compat.h" -- cgit v1.2.3 From 2c1c5e3cf1b2ae3e5212211fad2e578a12143f2d Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 11 Mar 2009 08:34:09 +0100 Subject: omap24xxcam: don't set vfl_type. From: Hans Verkuil The vfl_type field is set by the core, so anything you fill in here will be overwritten. And it will be set to a VFL_TYPE_ value, not a VID_TYPE_ value which is an obsolete V4L1 type. Since these V4L1 types have been made unavailable for V4L2 drivers, this driver stopped compiling. In this case the fix is just removing this assignment. Priority: normal Signed-off-by: Hans Verkuil CC: Sakari Ailus --- linux/drivers/media/video/omap24xxcam.c | 1 - 1 file changed, 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/omap24xxcam.c b/linux/drivers/media/video/omap24xxcam.c index 73eb656ac..61f3c83db 100644 --- a/linux/drivers/media/video/omap24xxcam.c +++ b/linux/drivers/media/video/omap24xxcam.c @@ -1665,7 +1665,6 @@ static int omap24xxcam_device_register(struct v4l2_int_device *s) vfd->parent = cam->dev; strlcpy(vfd->name, CAM_NAME, sizeof(vfd->name)); - vfd->vfl_type = VID_TYPE_CAPTURE | VID_TYPE_CHROMAKEY; vfd->fops = &omap24xxcam_fops; vfd->minor = -1; vfd->ioctl_ops = &omap24xxcam_ioctl_fops; -- cgit v1.2.3 From 90d1718cf0e7da298f845c2691ff713c9fe4ef83 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 11 Mar 2009 11:37:04 +0100 Subject: radio-terratec: remove linux/delay.h which hadn't been used. From: Alexey Klimov Priority: normal Signed-off-by: Alexey Klimov Signed-off-by: Hans Verkuil --- linux/drivers/media/radio/radio-terratec.c | 1 - 1 file changed, 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/radio/radio-terratec.c b/linux/drivers/media/radio/radio-terratec.c index db5481119..0bec5f7e2 100644 --- a/linux/drivers/media/radio/radio-terratec.c +++ b/linux/drivers/media/radio/radio-terratec.c @@ -27,7 +27,6 @@ #include /* Modules */ #include /* Initdata */ #include /* request_region */ -#include /* udelay */ #include /* kernel radio structs */ #include #include /* for KERNEL_VERSION MACRO */ -- cgit v1.2.3 From 60202da763db2446be57359a18882470715e68f8 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 11 Mar 2009 22:29:19 +0100 Subject: fired-avc: fix printk formatting warning. From: Hans Verkuil size_t should be printed with %zu. Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/dvb/firewire/firedtv-avc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/firewire/firedtv-avc.c b/linux/drivers/media/dvb/firewire/firedtv-avc.c index b55d9ccaf..af8fdf706 100644 --- a/linux/drivers/media/dvb/firewire/firedtv-avc.c +++ b/linux/drivers/media/dvb/firewire/firedtv-avc.c @@ -150,7 +150,7 @@ static void debug_fcp(const u8 *data, size_t length) subunit_type = data[1] >> 3; subunit_id = data[1] & 7; op = subunit_type == 0x1e || subunit_id == 5 ? ~0 : data[2]; - printk(KERN_INFO "%ssu=%x.%x l=%d: %-8s - %s\n", + printk(KERN_INFO "%ssu=%x.%x l=%zu: %-8s - %s\n", prefix, subunit_type, subunit_id, length, debug_fcp_ctype(data[0]), debug_fcp_opcode(op, data, length)); -- cgit v1.2.3 From 4c282610aefee1fbf050e390ad0f1cccbb245e7a Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 11 Mar 2009 22:37:06 +0100 Subject: ir-kbd-i2c: fix compat for old kernels. From: Hans Verkuil compat.h was included too late. Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/ir-kbd-i2c.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (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 a0b78706d..7bae57ad3 100644 --- a/linux/drivers/media/video/ir-kbd-i2c.c +++ b/linux/drivers/media/video/ir-kbd-i2c.c @@ -47,9 +47,9 @@ #include #include +#include "compat.h" #include #include -#include "compat.h" /* ----------------------------------------------------------------------- */ /* insmod parameters */ -- cgit v1.2.3 From a9f7a944fa810879c33504a9081eaaafd3fe305e Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 11 Mar 2009 22:48:33 +0100 Subject: fired-avc: fix print_hex_dump warning on 2.6.22. From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/dvb/firewire/firedtv-avc.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/firewire/firedtv-avc.c b/linux/drivers/media/dvb/firewire/firedtv-avc.c index af8fdf706..d8dae2599 100644 --- a/linux/drivers/media/dvb/firewire/firedtv-avc.c +++ b/linux/drivers/media/dvb/firewire/firedtv-avc.c @@ -157,8 +157,13 @@ static void debug_fcp(const u8 *data, size_t length) } if (avc_debug & AVC_DEBUG_FCP_PAYLOADS) +#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 22) print_hex_dump(KERN_INFO, prefix, DUMP_PREFIX_NONE, 16, 1, data, length, false); +#else + print_hex_dump(KERN_INFO, prefix, DUMP_PREFIX_NONE, 16, 1, + (void *)data, length, false); +#endif } static int __avc_write(struct firedtv *fdtv, -- cgit v1.2.3 From 169802c05f1d866f908365460b89269bf1d48247 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 11 Mar 2009 22:50:04 +0100 Subject: ivtv: bump version From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/ivtv/ivtv-version.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/ivtv/ivtv-version.h b/linux/drivers/media/video/ivtv/ivtv-version.h index 8cd753d30..b530dec39 100644 --- a/linux/drivers/media/video/ivtv/ivtv-version.h +++ b/linux/drivers/media/video/ivtv/ivtv-version.h @@ -23,7 +23,7 @@ #define IVTV_DRIVER_NAME "ivtv" #define IVTV_DRIVER_VERSION_MAJOR 1 #define IVTV_DRIVER_VERSION_MINOR 4 -#define IVTV_DRIVER_VERSION_PATCHLEVEL 0 +#define IVTV_DRIVER_VERSION_PATCHLEVEL 1 #define IVTV_VERSION __stringify(IVTV_DRIVER_VERSION_MAJOR) "." __stringify(IVTV_DRIVER_VERSION_MINOR) "." __stringify(IVTV_DRIVER_VERSION_PATCHLEVEL) #define IVTV_DRIVER_VERSION KERNEL_VERSION(IVTV_DRIVER_VERSION_MAJOR,IVTV_DRIVER_VERSION_MINOR,IVTV_DRIVER_VERSION_PATCHLEVEL) -- cgit v1.2.3 From a0600eb3e37815b9a780193dc7c9e4dff4cc9291 Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Wed, 11 Mar 2009 20:58:04 -0400 Subject: au0828: make sure v4l2_device name is unique From: Devin Heitmueller Make sure newly created v4l2 devices have a unique name, modeling the logic after the cx18 driver. Thanks to Andy Walls for pointing out the issue. Priority: normal Signed-off-by: Devin Heitmueller --- linux/drivers/media/video/au0828/au0828-core.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/au0828/au0828-core.c b/linux/drivers/media/video/au0828/au0828-core.c index 327c6edde..ffe1bf019 100644 --- a/linux/drivers/media/video/au0828/au0828-core.c +++ b/linux/drivers/media/video/au0828/au0828-core.c @@ -37,6 +37,8 @@ int au0828_debug; module_param_named(debug, au0828_debug, int, 0644); MODULE_PARM_DESC(debug, "enable debug messages"); +static atomic_t au0828_instance = ATOMIC_INIT(0); + #define _AU0828_BULKPIPE 0x03 #define _BULKPIPESIZE 0xffff @@ -168,7 +170,7 @@ static void au0828_usb_disconnect(struct usb_interface *interface) static int au0828_usb_probe(struct usb_interface *interface, const struct usb_device_id *id) { - int ifnum, retval; + int ifnum, retval, i; struct au0828_dev *dev; struct usb_device *usbdev = interface_to_usbdev(interface); @@ -196,8 +198,9 @@ static int au0828_usb_probe(struct usb_interface *interface, usb_set_intfdata(interface, dev); /* Create the v4l2_device */ + i = atomic_inc_return(&au0828_instance) - 1; snprintf(dev->v4l2_dev.name, sizeof(dev->v4l2_dev.name), "%s-%03d", - "au0828", 0); + "au0828", i); retval = v4l2_device_register(&dev->usbdev->dev, &dev->v4l2_dev); if (retval) { printk(KERN_ERR "%s() v4l2_device_register failed\n", -- cgit v1.2.3 From 885a23d5d3b31b99d23ef1d05b212d9e3fbba93f Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Mon, 23 Mar 2009 21:32:35 -0400 Subject: mxl5005s: Switch in mxl5005s_set_params should operate on correct values From: Andy Walls Priority: normal Signed-off-by: Andy Walls --- linux/drivers/media/common/tuners/mxl5005s.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/common/tuners/mxl5005s.c b/linux/drivers/media/common/tuners/mxl5005s.c index 58418277a..bea599fbc 100644 --- a/linux/drivers/media/common/tuners/mxl5005s.c +++ b/linux/drivers/media/common/tuners/mxl5005s.c @@ -4005,12 +4005,11 @@ static int mxl5005s_set_params(struct dvb_frontend *fe, /* Change tuner for new modulation type if reqd */ if (req_mode != state->current_mode) { switch (req_mode) { - case VSB_8: - case QAM_64: - case QAM_256: - case QAM_AUTO: + case MXL_ATSC: + case MXL_QAM: req_bw = MXL5005S_BANDWIDTH_6MHZ; break; + case MXL_DVBT: default: /* Assume DVB-T */ switch (params->u.ofdm.bandwidth) { -- cgit v1.2.3 From d46e36f00dd4f2aa8aa84141dd2576385b7ffe90 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 26 Mar 2009 11:14:44 -0300 Subject: pvrusb2: add a missing source at Makefile From: Kyle McMartin As pointed by Steve Dickson, pvrusb2 Makefile was not compiling pvrusb2-cx53l32a driver. Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/pvrusb2/Makefile | 1 + 1 file changed, 1 insertion(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/pvrusb2/Makefile b/linux/drivers/media/video/pvrusb2/Makefile index a4478618a..de2fc14f0 100644 --- a/linux/drivers/media/video/pvrusb2/Makefile +++ b/linux/drivers/media/video/pvrusb2/Makefile @@ -10,6 +10,7 @@ pvrusb2-objs := pvrusb2-i2c-core.o \ pvrusb2-ctrl.o pvrusb2-std.o pvrusb2-devattr.o \ pvrusb2-context.o pvrusb2-io.o pvrusb2-ioread.o \ pvrusb2-cx2584x-v4l.o pvrusb2-wm8775.o \ + pvrusb2-cs53l32a.o \ $(obj-pvrusb2-dvb-y) \ $(obj-pvrusb2-sysfs-y) $(obj-pvrusb2-debugifc-y) -- cgit v1.2.3 From efea5a90212a1f82531f7fc661a4e15e7df15571 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 26 Mar 2009 12:24:46 -0300 Subject: avoid warnings for request_ihex_firmware on dabusb and vicam MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: Mauro Carvalho Chehab drivers/media/video/usbvideo/vicam.c: In function ‘vicam_open’: drivers/media/video/usbvideo/vicam.c:194: warning: ‘fw’ may be used uninitialized in this function drivers/media/video/dabusb.c: In function ‘dabusb_probe’: drivers/media/video/dabusb.c:337: warning: ‘fw’ may be used uninitialized in this function Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/dabusb.c | 2 +- linux/drivers/media/video/usbvideo/vicam.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/dabusb.c b/linux/drivers/media/video/dabusb.c index b399f18c1..8c0cab8b2 100644 --- a/linux/drivers/media/video/dabusb.c +++ b/linux/drivers/media/video/dabusb.c @@ -351,7 +351,7 @@ static int dabusb_loadmem (pdabusb_t s, const char *fname) PINTEL_HEX_RECORD ptr = firmware; #else const struct ihex_binrec *rec; - const struct firmware *fw; + const struct firmware *uninitialized_var(fw); #endif dbg("Enter dabusb_loadmem (internal)"); diff --git a/linux/drivers/media/video/usbvideo/vicam.c b/linux/drivers/media/video/usbvideo/vicam.c index 5a039b5d6..3b332ef52 100644 --- a/linux/drivers/media/video/usbvideo/vicam.c +++ b/linux/drivers/media/video/usbvideo/vicam.c @@ -489,7 +489,7 @@ initialize_camera(struct vicam_camera *cam) #else int err; const struct ihex_binrec *rec; - const struct firmware *fw; + const struct firmware *uninitialized_var(fw); err = request_ihex_firmware(&fw, "vicam/firmware.fw", &cam->udev->dev); if (err) { -- cgit v1.2.3 From 9731acdee8858e02b65a411ba6bd7050540b4c27 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 26 Mar 2009 12:26:48 -0300 Subject: ce6230: avoid using unitialized var MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: Mauro Carvalho Chehab drivers/media/dvb/dvb-usb/ce6230.c: In function ‘ce6230_i2c_xfer’: drivers/media/dvb/dvb-usb/ce6230.c:107: warning: ‘ret’ may be used uninitialized in this function Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/dvb-usb/ce6230.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/dvb-usb/ce6230.c b/linux/drivers/media/dvb/dvb-usb/ce6230.c index 2a959c4bd..1682af62f 100644 --- a/linux/drivers/media/dvb/dvb-usb/ce6230.c +++ b/linux/drivers/media/dvb/dvb-usb/ce6230.c @@ -104,7 +104,7 @@ static int ce6230_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], struct dvb_usb_device *d = i2c_get_adapdata(adap); int i = 0; struct req_t req; - int ret; + int ret = 0; memset(&req, 0, sizeof(&req)); if (num > 2) -- cgit v1.2.3 From f3ac90549a85ff26ab911d4daf8d57ebb39293c9 Mon Sep 17 00:00:00 2001 From: Janne Grunau Date: Fri, 27 Mar 2009 00:29:39 +0100 Subject: hdpvr: use debugging macro for buffer status From: Janne Grunau Priority: normal Signed-off-by: Janne Grunau --- linux/drivers/media/video/hdpvr/hdpvr-video.c | 27 ++++++++++----------------- 1 file changed, 10 insertions(+), 17 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/hdpvr/hdpvr-video.c b/linux/drivers/media/video/hdpvr/hdpvr-video.c index 235978003..d63bfccf7 100644 --- a/linux/drivers/media/video/hdpvr/hdpvr-video.c +++ b/linux/drivers/media/video/hdpvr/hdpvr-video.c @@ -28,6 +28,12 @@ #define BULK_URB_TIMEOUT 1250 /* 1.25 seconds */ +#define print_buffer_status() v4l2_dbg(MSG_BUFFER, hdpvr_debug, dev->video_dev,\ + "%s:%d buffer stat: %d free, %d proc\n",\ + __func__, __LINE__, \ + list_size(&dev->free_buff_list), \ + list_size(&dev->rec_buff_list)) + struct hdpvr_fh { struct hdpvr_device *dev; }; @@ -191,10 +197,7 @@ static int hdpvr_submit_buffers(struct hdpvr_device *dev) list_move_tail(&buf->buff_list, &dev->rec_buff_list); } err: - v4l2_dbg(MSG_BUFFER, hdpvr_debug, dev->video_dev, - "buffer queue stat: %d free, %d proc\n", - list_size(&dev->free_buff_list), - list_size(&dev->rec_buff_list)); + print_buffer_status(); mutex_unlock(&dev->io_mutex); return ret; } @@ -399,11 +402,7 @@ static ssize_t hdpvr_read(struct file *file, char __user *buffer, size_t count, mutex_unlock(&dev->io_mutex); goto err; } - - v4l2_dbg(MSG_BUFFER, hdpvr_debug, dev->video_dev, - "buffer queue stat: %d free, %d proc\n", - list_size(&dev->free_buff_list), - list_size(&dev->rec_buff_list)); + print_buffer_status(); } mutex_unlock(&dev->io_mutex); @@ -463,10 +462,7 @@ static ssize_t hdpvr_read(struct file *file, char __user *buffer, size_t count, list_move_tail(&buf->buff_list, &dev->free_buff_list); - v4l2_dbg(MSG_BUFFER, hdpvr_debug, dev->video_dev, - "buffer queue stat: %d free, %d proc\n", - list_size(&dev->free_buff_list), - list_size(&dev->rec_buff_list)); + print_buffer_status(); mutex_unlock(&dev->io_mutex); @@ -499,10 +495,7 @@ static unsigned int hdpvr_poll(struct file *filp, poll_table *wait) dev->status = STATUS_IDLE; } - v4l2_dbg(MSG_BUFFER, hdpvr_debug, dev->video_dev, - "buffer queue stat: %d free, %d proc\n", - list_size(&dev->free_buff_list), - list_size(&dev->rec_buff_list)); + print_buffer_status(); } mutex_unlock(&dev->io_mutex); -- cgit v1.2.3 From b16183f4e679f7248f72e89d10dfcf73cfb83d49 Mon Sep 17 00:00:00 2001 From: Janne Grunau Date: Thu, 26 Mar 2009 18:40:55 +0100 Subject: hdpvr: set usb interface dev as parent in struct video_device From: Janne Grunau Priority: normal Signed-off-by: Janne Grunau --- linux/drivers/media/video/hdpvr/hdpvr-core.c | 2 +- linux/drivers/media/video/hdpvr/hdpvr-video.c | 5 +++-- linux/drivers/media/video/hdpvr/hdpvr.h | 3 ++- 3 files changed, 6 insertions(+), 4 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/hdpvr/hdpvr-core.c b/linux/drivers/media/video/hdpvr/hdpvr-core.c index e96aed42d..2c49862b6 100644 --- a/linux/drivers/media/video/hdpvr/hdpvr-core.c +++ b/linux/drivers/media/video/hdpvr/hdpvr-core.c @@ -342,7 +342,7 @@ static int hdpvr_probe(struct usb_interface *interface, } mutex_unlock(&dev->io_mutex); - if (hdpvr_register_videodev(dev, + if (hdpvr_register_videodev(dev, &interface->dev, video_nr[atomic_inc_return(&dev_nr)])) { err("registering videodev failed"); goto error; diff --git a/linux/drivers/media/video/hdpvr/hdpvr-video.c b/linux/drivers/media/video/hdpvr/hdpvr-video.c index d63bfccf7..9560e19d7 100644 --- a/linux/drivers/media/video/hdpvr/hdpvr-video.c +++ b/linux/drivers/media/video/hdpvr/hdpvr-video.c @@ -1193,7 +1193,8 @@ static const struct video_device hdpvr_video_template = { V4L2_STD_PAL_60, }; -int hdpvr_register_videodev(struct hdpvr_device *dev, int devnum) +int hdpvr_register_videodev(struct hdpvr_device *dev, struct device *parent, + int devnum) { /* setup and register video device */ dev->video_dev = video_device_alloc(); @@ -1204,7 +1205,7 @@ int hdpvr_register_videodev(struct hdpvr_device *dev, int devnum) *(dev->video_dev) = hdpvr_video_template; strcpy(dev->video_dev->name, "Hauppauge HD PVR"); - dev->video_dev->parent = &dev->udev->dev; + dev->video_dev->parent = parent; video_set_drvdata(dev->video_dev, dev); if (video_register_device(dev->video_dev, VFL_TYPE_GRABBER, devnum)) { diff --git a/linux/drivers/media/video/hdpvr/hdpvr.h b/linux/drivers/media/video/hdpvr/hdpvr.h index 9bc8051b5..3af415d81 100644 --- a/linux/drivers/media/video/hdpvr/hdpvr.h +++ b/linux/drivers/media/video/hdpvr/hdpvr.h @@ -284,7 +284,8 @@ int get_input_lines_info(struct hdpvr_device *dev); /*========================================================================*/ /* v4l2 registration */ -int hdpvr_register_videodev(struct hdpvr_device *dev, int devnumber); +int hdpvr_register_videodev(struct hdpvr_device *dev, struct device *parent, + int devnumber); int hdpvr_cancel_queue(struct hdpvr_device *dev); -- cgit v1.2.3 From 3d73a21a3b0fb96a08c796016ae66cb734327490 Mon Sep 17 00:00:00 2001 From: Janne Grunau Date: Thu, 26 Mar 2009 18:32:54 +0100 Subject: hdpvr: return immediately from hdpvr_poll if data is available From: Janne Grunau simplifies check for available data with hdpvr_get_next_buffer Priority: normal Signed-off-by: Janne Grunau --- linux/drivers/media/video/hdpvr/hdpvr-video.c | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/hdpvr/hdpvr-video.c b/linux/drivers/media/video/hdpvr/hdpvr-video.c index 9560e19d7..e9078cded 100644 --- a/linux/drivers/media/video/hdpvr/hdpvr-video.c +++ b/linux/drivers/media/video/hdpvr/hdpvr-video.c @@ -479,6 +479,7 @@ err: static unsigned int hdpvr_poll(struct file *filp, poll_table *wait) { + struct hdpvr_buffer *buf = NULL; struct hdpvr_fh *fh = (struct hdpvr_fh *)filp->private_data; struct hdpvr_device *dev = fh->dev; unsigned int mask = 0; @@ -499,19 +500,14 @@ static unsigned int hdpvr_poll(struct file *filp, poll_table *wait) } mutex_unlock(&dev->io_mutex); - poll_wait(filp, &dev->wait_data, wait); - - mutex_lock(&dev->io_mutex); - if (!list_empty(&dev->rec_buff_list)) { - - struct hdpvr_buffer *buf = list_entry(dev->rec_buff_list.next, - struct hdpvr_buffer, - buff_list); - - if (buf->status == BUFSTAT_READY) - mask |= POLLIN | POLLRDNORM; + buf = hdpvr_get_next_buffer(dev); + /* only wait if no data is available */ + if (!buf || buf->status != BUFSTAT_READY) { + poll_wait(filp, &dev->wait_data, wait); + buf = hdpvr_get_next_buffer(dev); } - mutex_unlock(&dev->io_mutex); + if (buf && buf->status == BUFSTAT_READY) + mask |= POLLIN | POLLRDNORM; return mask; } -- cgit v1.2.3 From fcf939c56e5b32cbd2f6e77d9de6d190186a4c1a Mon Sep 17 00:00:00 2001 From: Janne Grunau Date: Fri, 27 Mar 2009 00:56:06 +0100 Subject: hdpvr: locking fixes From: Janne Grunau unlock io_mutex in hdpvr_stop_streaming hdpvr_disconnect to allow the streaming worker to stop before we flush the workqueue. do not return to user space with mutex held in vidioc_encoder_cmd with an unknown encoder command. Priority: normal Signed-off-by: Janne Grunau --- linux/drivers/media/video/hdpvr/hdpvr-core.c | 2 ++ linux/drivers/media/video/hdpvr/hdpvr-video.c | 4 +++- 2 files changed, 5 insertions(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/hdpvr/hdpvr-core.c b/linux/drivers/media/video/hdpvr/hdpvr-core.c index 2c49862b6..547833eb6 100644 --- a/linux/drivers/media/video/hdpvr/hdpvr-core.c +++ b/linux/drivers/media/video/hdpvr/hdpvr-core.c @@ -390,8 +390,10 @@ static void hdpvr_disconnect(struct usb_interface *interface) video_unregister_device(dev->video_dev); wake_up_interruptible(&dev->wait_data); wake_up_interruptible(&dev->wait_buffer); + mutex_unlock(&dev->io_mutex); msleep(100); flush_workqueue(dev->workqueue); + mutex_lock(&dev->io_mutex); hdpvr_cancel_queue(dev); destroy_workqueue(dev->workqueue); mutex_unlock(&dev->io_mutex); diff --git a/linux/drivers/media/video/hdpvr/hdpvr-video.c b/linux/drivers/media/video/hdpvr/hdpvr-video.c index e9078cded..2fe57303c 100644 --- a/linux/drivers/media/video/hdpvr/hdpvr-video.c +++ b/linux/drivers/media/video/hdpvr/hdpvr-video.c @@ -300,12 +300,14 @@ static int hdpvr_stop_streaming(struct hdpvr_device *dev) dev->status = STATUS_SHUTTING_DOWN; hdpvr_config_call(dev, CTRL_STOP_STREAMING_VALUE, 0x00); + mutex_unlock(&dev->io_mutex); wake_up_interruptible(&dev->wait_buffer); msleep(50); flush_workqueue(dev->workqueue); + mutex_lock(&dev->io_mutex); /* kill the still outstanding urbs */ hdpvr_cancel_queue(dev); @@ -1130,7 +1132,7 @@ static int vidioc_encoder_cmd(struct file *filp, void *priv, default: v4l2_dbg(MSG_INFO, hdpvr_debug, dev->video_dev, "Unsupported encoder cmd %d\n", a->cmd); - return -EINVAL; + res = -EINVAL; } mutex_unlock(&dev->io_mutex); return res; -- cgit v1.2.3 From 9a161310d7fbbc285576a6d822bbcdf93744e836 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 24 Mar 2009 21:12:47 +0000 Subject: changed ioctls to unlocked From: Stoyan Gaydarov Signed-off-by: Stoyan Gaydarov Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/bt8xx/dst_ca.c | 7 +++++-- linux/drivers/media/video/dabusb.c | 11 ++++++++--- 2 files changed, 13 insertions(+), 5 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/bt8xx/dst_ca.c b/linux/drivers/media/dvb/bt8xx/dst_ca.c index 68aef6786..e71c269c1 100644 --- a/linux/drivers/media/dvb/bt8xx/dst_ca.c +++ b/linux/drivers/media/dvb/bt8xx/dst_ca.c @@ -648,8 +648,10 @@ free_mem_and_exit: return result; } -static int dst_ca_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long ioctl_arg) +static long dst_ca_ioctl(struct file *file, unsigned int cmd, unsigned long ioctl_arg) { + lock_kernel(); + struct dvb_device* dvbdev = (struct dvb_device*) file->private_data; struct dst_state* state = (struct dst_state*) dvbdev->priv; struct ca_slot_info *p_ca_slot_info; @@ -743,6 +745,7 @@ static int dst_ca_ioctl(struct inode *inode, struct file *file, unsigned int cmd kfree (p_ca_slot_info); kfree (p_ca_caps); + unlock_kernel(); return result; } @@ -780,7 +783,7 @@ static ssize_t dst_ca_write(struct file *file, const char __user *buffer, size_t static const struct file_operations dst_ca_fops = { .owner = THIS_MODULE, - .ioctl = dst_ca_ioctl, + .unlocked_ioctl = dst_ca_ioctl, .open = dst_ca_open, .release = dst_ca_release, .read = dst_ca_read, diff --git a/linux/drivers/media/video/dabusb.c b/linux/drivers/media/video/dabusb.c index 8c0cab8b2..5585f46dd 100644 --- a/linux/drivers/media/video/dabusb.c +++ b/linux/drivers/media/video/dabusb.c @@ -734,8 +734,9 @@ static int dabusb_release (struct inode *inode, struct file *file) return 0; } -static int dabusb_ioctl (struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) +static long dabusb_ioctl (struct file *file, unsigned int cmd, unsigned long arg) { + lock_kernel(); pdabusb_t s = (pdabusb_t) file->private_data; pbulk_transfer_t pbulk; int ret = 0; @@ -743,13 +744,16 @@ static int dabusb_ioctl (struct inode *inode, struct file *file, unsigned int cm dbg("dabusb_ioctl"); - if (s->remove_pending) + if (s->remove_pending) { + unlock_kernel(); return -EIO; + } mutex_lock(&s->mutex); if (!s->usbdev) { mutex_unlock(&s->mutex); + unlock_kernel(); return -EIO; } @@ -790,6 +794,7 @@ static int dabusb_ioctl (struct inode *inode, struct file *file, unsigned int cm break; } mutex_unlock(&s->mutex); + unlock_kernel(); return ret; } @@ -802,7 +807,7 @@ static struct file_operations dabusb_fops = .owner = THIS_MODULE, .llseek = no_llseek, .read = dabusb_read, - .ioctl = dabusb_ioctl, + .unlocked_ioctl = dabusb_ioctl, .open = dabusb_open, .release = dabusb_release, }; -- cgit v1.2.3 From 86948a72d224082ef87b1a46b9bc7ce3292e1003 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 25 Mar 2009 20:53:02 +0000 Subject: tda827x: fix locking issues with DVB-C From: klaas de waal Separate tuning table for DVB-C solves tuning problem at 388MHz TechnoTrend C-1501 DVB-C card does not lock on 388MHz. I assume that existing frequency table is valid for DVB-T. This is suggested by the name of the table: tda827xa_dvbt. Added a table for DVB-C with the name tda827xa_dvbc. Added runtime selection of the DVB-C table when the tuner is type FE_QAM. This should leave the behaviour of this driver with with DVB_T tuners unchanged. This modification is in file tda827x.c The tda827x.c gives the following warning message when debug=1: tda827x: tda827x_config not defined, cannot set LNA gain! Solved this by adding a tda827x_config struct in budget-ci.c. Priority: normal Signed-off-by: Klaas de Waal Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/common/tuners/tda827x.c | 54 ++++++++++++++++++++++++----- linux/drivers/media/dvb/ttpci/budget-ci.c | 6 +++- 2 files changed, 50 insertions(+), 10 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/common/tuners/tda827x.c b/linux/drivers/media/common/tuners/tda827x.c index eb989c241..6653ebcdf 100644 --- a/linux/drivers/media/common/tuners/tda827x.c +++ b/linux/drivers/media/common/tuners/tda827x.c @@ -352,7 +352,7 @@ struct tda827xa_data { u8 gc3; }; -static const struct tda827xa_data tda827xa_dvbt[] = { +static struct tda827xa_data tda827xa_dvbt[] = { { .lomax = 56875000, .svco = 3, .spd = 4, .scr = 0, .sbs = 0, .gc3 = 1}, { .lomax = 67250000, .svco = 0, .spd = 3, .scr = 0, .sbs = 0, .gc3 = 1}, { .lomax = 81250000, .svco = 1, .spd = 3, .scr = 0, .sbs = 0, .gc3 = 1}, @@ -382,6 +382,36 @@ static const struct tda827xa_data tda827xa_dvbt[] = { { .lomax = 0, .svco = 0, .spd = 0, .scr = 0, .sbs = 0, .gc3 = 0} }; +static struct tda827xa_data tda827xa_dvbc[] = { + { .lomax = 50125000, .svco = 2, .spd = 4, .scr = 2, .sbs = 0, .gc3 = 3}, + { .lomax = 58500000, .svco = 3, .spd = 4, .scr = 2, .sbs = 0, .gc3 = 3}, + { .lomax = 69250000, .svco = 0, .spd = 3, .scr = 2, .sbs = 0, .gc3 = 3}, + { .lomax = 83625000, .svco = 1, .spd = 3, .scr = 2, .sbs = 0, .gc3 = 3}, + { .lomax = 97500000, .svco = 2, .spd = 3, .scr = 2, .sbs = 0, .gc3 = 3}, + { .lomax = 100250000, .svco = 2, .spd = 3, .scr = 2, .sbs = 1, .gc3 = 1}, + { .lomax = 117000000, .svco = 3, .spd = 3, .scr = 2, .sbs = 1, .gc3 = 1}, + { .lomax = 138500000, .svco = 0, .spd = 2, .scr = 2, .sbs = 1, .gc3 = 1}, + { .lomax = 167250000, .svco = 1, .spd = 2, .scr = 2, .sbs = 1, .gc3 = 1}, + { .lomax = 187000000, .svco = 2, .spd = 2, .scr = 2, .sbs = 1, .gc3 = 1}, + { .lomax = 200500000, .svco = 2, .spd = 2, .scr = 2, .sbs = 2, .gc3 = 1}, + { .lomax = 234000000, .svco = 3, .spd = 2, .scr = 2, .sbs = 2, .gc3 = 3}, + { .lomax = 277000000, .svco = 0, .spd = 1, .scr = 2, .sbs = 2, .gc3 = 3}, + { .lomax = 325000000, .svco = 1, .spd = 1, .scr = 2, .sbs = 2, .gc3 = 1}, + { .lomax = 334500000, .svco = 1, .spd = 1, .scr = 2, .sbs = 3, .gc3 = 3}, + { .lomax = 401000000, .svco = 2, .spd = 1, .scr = 2, .sbs = 3, .gc3 = 3}, + { .lomax = 468000000, .svco = 3, .spd = 1, .scr = 2, .sbs = 3, .gc3 = 1}, + { .lomax = 535000000, .svco = 0, .spd = 0, .scr = 1, .sbs = 3, .gc3 = 1}, + { .lomax = 554000000, .svco = 0, .spd = 0, .scr = 2, .sbs = 3, .gc3 = 1}, + { .lomax = 638000000, .svco = 1, .spd = 0, .scr = 1, .sbs = 4, .gc3 = 1}, + { .lomax = 669000000, .svco = 1, .spd = 0, .scr = 2, .sbs = 4, .gc3 = 1}, + { .lomax = 720000000, .svco = 2, .spd = 0, .scr = 1, .sbs = 4, .gc3 = 1}, + { .lomax = 802000000, .svco = 2, .spd = 0, .scr = 2, .sbs = 4, .gc3 = 1}, + { .lomax = 835000000, .svco = 3, .spd = 0, .scr = 1, .sbs = 4, .gc3 = 1}, + { .lomax = 885000000, .svco = 3, .spd = 0, .scr = 1, .sbs = 4, .gc3 = 1}, + { .lomax = 911000000, .svco = 3, .spd = 0, .scr = 2, .sbs = 4, .gc3 = 1}, + { .lomax = 0, .svco = 0, .spd = 0, .scr = 0, .sbs = 0, .gc3 = 0} +}; + static struct tda827xa_data tda827xa_analog[] = { { .lomax = 56875000, .svco = 3, .spd = 4, .scr = 0, .sbs = 0, .gc3 = 3}, { .lomax = 67250000, .svco = 0, .spd = 3, .scr = 0, .sbs = 0, .gc3 = 3}, @@ -485,6 +515,7 @@ static int tda827xa_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params) { struct tda827x_priv *priv = fe->tuner_priv; + struct tda827xa_data *frequency_map = tda827xa_dvbt; u8 buf[11]; struct i2c_msg msg = { .addr = priv->i2c_addr, .flags = 0, @@ -511,22 +542,27 @@ static int tda827xa_set_params(struct dvb_frontend *fe, } tuner_freq = params->frequency + if_freq; + if (fe->ops.info.type == FE_QAM) { + dprintk("%s select tda827xa_dvbc\n", __func__); + frequency_map = tda827xa_dvbc; + } + i = 0; - while (tda827xa_dvbt[i].lomax < tuner_freq) { - if(tda827xa_dvbt[i + 1].lomax == 0) + while (frequency_map[i].lomax < tuner_freq) { + if (frequency_map[i + 1].lomax == 0) break; i++; } - N = ((tuner_freq + 31250) / 62500) << tda827xa_dvbt[i].spd; + N = ((tuner_freq + 31250) / 62500) << frequency_map[i].spd; buf[0] = 0; // subaddress buf[1] = N >> 8; buf[2] = N & 0xff; buf[3] = 0; buf[4] = 0x16; - buf[5] = (tda827xa_dvbt[i].spd << 5) + (tda827xa_dvbt[i].svco << 3) + - tda827xa_dvbt[i].sbs; - buf[6] = 0x4b + (tda827xa_dvbt[i].gc3 << 4); + buf[5] = (frequency_map[i].spd << 5) + (frequency_map[i].svco << 3) + + frequency_map[i].sbs; + buf[6] = 0x4b + (frequency_map[i].gc3 << 4); buf[7] = 0x1c; buf[8] = 0x06; buf[9] = 0x24; @@ -585,7 +621,7 @@ static int tda827xa_set_params(struct dvb_frontend *fe, /* correct CP value */ buf[0] = 0x30; - buf[1] = 0x10 + tda827xa_dvbt[i].scr; + buf[1] = 0x10 + frequency_map[i].scr; rc = tuner_transfer(fe, &msg, 1); if (rc < 0) goto err; @@ -600,7 +636,7 @@ static int tda827xa_set_params(struct dvb_frontend *fe, msleep(3); /* freeze AGC1 */ buf[0] = 0x50; - buf[1] = 0x4f + (tda827xa_dvbt[i].gc3 << 4); + buf[1] = 0x4f + (frequency_map[i].gc3 << 4); rc = tuner_transfer(fe, &msg, 1); if (rc < 0) goto err; diff --git a/linux/drivers/media/dvb/ttpci/budget-ci.c b/linux/drivers/media/dvb/ttpci/budget-ci.c index 99fcb55d5..1b564eb79 100644 --- a/linux/drivers/media/dvb/ttpci/budget-ci.c +++ b/linux/drivers/media/dvb/ttpci/budget-ci.c @@ -1084,6 +1084,10 @@ static struct tda10023_config tda10023_config = { .deltaf = 0xa511, }; +static struct tda827x_config tda827x_config = { + .config = 0, +}; + /* TT S2-3200 DVB-S (STB0899) Inittab */ static const struct stb0899_s1_reg tt3200_stb0899_s1_init_1[] = { @@ -1422,7 +1426,7 @@ static void frontend_init(struct budget_ci *budget_ci) case 0x101a: /* TT Budget-C-1501 (philips tda10023/philips tda8274A) */ budget_ci->budget.dvb_frontend = dvb_attach(tda10023_attach, &tda10023_config, &budget_ci->budget.i2c_adap, 0x48); if (budget_ci->budget.dvb_frontend) { - if (dvb_attach(tda827x_attach, budget_ci->budget.dvb_frontend, 0x61, &budget_ci->budget.i2c_adap, NULL) == NULL) { + if (dvb_attach(tda827x_attach, budget_ci->budget.dvb_frontend, 0x61, &budget_ci->budget.i2c_adap, &tda827x_config) == NULL) { printk(KERN_ERR "%s: No tda827x found!\n", __func__); dvb_frontend_detach(budget_ci->budget.dvb_frontend); budget_ci->budget.dvb_frontend = NULL; -- cgit v1.2.3 From 4b807c926e097767bb1b8c3bf09bffb52b406295 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 27 Mar 2009 14:01:11 -0300 Subject: Fix printk format warning: From: Randy Dunlap drivers/media/video/zoran/zoran_driver.c:345: warning: format '%lx' expects type 'long unsigned int', but argument 5 has type 'phys_addr_t' Signed-off-by: Randy Dunlap Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/zoran/zoran_driver.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/zoran/zoran_driver.c b/linux/drivers/media/video/zoran/zoran_driver.c index 7ef3c015d..c702ea0fe 100644 --- a/linux/drivers/media/video/zoran/zoran_driver.c +++ b/linux/drivers/media/video/zoran/zoran_driver.c @@ -246,9 +246,9 @@ static int v4l_fbuffer_alloc(struct zoran_fh *fh) SetPageReserved(virt_to_page(mem + off)); dprintk(4, KERN_INFO - "%s: %s - V4L frame %d mem 0x%lx (bus: 0x%lx)\n", + "%s: %s - V4L frame %d mem 0x%lx (bus: 0x%llx)\n", ZR_DEVNAME(zr), __func__, i, (unsigned long) mem, - virt_to_bus(mem)); + (unsigned long long)virt_to_bus(mem)); } fh->buffers.allocated = 1; -- cgit v1.2.3 From 6716df924ee6f2791b1939b04028f01dd37a9e9e Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Thu, 12 Mar 2009 09:12:16 -0400 Subject: lgdt3305: avoid OOPS in error path of lgdt3305_attach From: Michael Krufky Setting state->frontend.demodulator_priv to NULL in the event of a kzalloc error will result in an OOPS. Just remove that line. Thanks to Matthias Schwarzott for pointing this out. Priority: normal Signed-off-by: Michael Krufky Cc: Matthias Schwarzott --- linux/drivers/media/dvb/frontends/lgdt3305.c | 1 - 1 file changed, 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/frontends/lgdt3305.c b/linux/drivers/media/dvb/frontends/lgdt3305.c index 8d62d1257..f0c0c8199 100644 --- a/linux/drivers/media/dvb/frontends/lgdt3305.c +++ b/linux/drivers/media/dvb/frontends/lgdt3305.c @@ -1075,7 +1075,6 @@ struct dvb_frontend *lgdt3305_attach(const struct lgdt3305_config *config, return &state->frontend; fail: lg_warn("unable to detect LGDT3305 hardware\n"); - state->frontend.demodulator_priv = NULL; kfree(state); return NULL; } -- cgit v1.2.3 From e3752e7d1b2f53cf53597d07faac7d9f65d43ff1 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Thu, 12 Mar 2009 22:38:40 +0100 Subject: cx231xx: fix compile warning From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/cx231xx/cx231xx-cards.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (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 3539ce19b..bc8e375ca 100644 --- a/linux/drivers/media/video/cx231xx/cx231xx-cards.c +++ b/linux/drivers/media/video/cx231xx/cx231xx-cards.c @@ -549,7 +549,7 @@ static int cx231xx_usb_probe(struct usb_interface *interface, struct usb_interface *uif; struct cx231xx *dev = NULL; int retval = -ENODEV; - int nr, ifnum; + int nr = 0, ifnum; int i, isoc_pipe = 0; char *speed; char descr[255] = ""; -- cgit v1.2.3 From 0efc193045eedcc05a28b5502f6dfaed87b434e8 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Thu, 12 Mar 2009 22:56:15 +0100 Subject: v4l2-common: add missing i2c_unregister_device. From: Hans Verkuil If the i2c sub-device cannot be found, then we must unregister the i2c_client. Otherwise this will prevent a possible probe for a different device on that same address. Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/v4l2-common.c | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/v4l2-common.c b/linux/drivers/media/video/v4l2-common.c index a5ce43102..32d0246d5 100644 --- a/linux/drivers/media/video/v4l2-common.c +++ b/linux/drivers/media/video/v4l2-common.c @@ -856,11 +856,11 @@ struct v4l2_subdev *v4l2_i2c_new_subdev(struct i2c_adapter *adapter, We need better support from the kernel so that we can easily wait for the load to finish. */ if (client == NULL || client->driver == NULL) - return NULL; + goto error; /* Lock the module so we can safely get the v4l2_subdev pointer */ if (!try_module_get(client->driver->driver.owner)) - return NULL; + goto error; sd = i2c_get_clientdata(client); /* Register with the v4l2_device which increases the module's @@ -869,8 +869,15 @@ struct v4l2_subdev *v4l2_i2c_new_subdev(struct i2c_adapter *adapter, sd = NULL; /* Decrease the module use count to match the first try_module_get. */ module_put(client->driver->driver.owner); - return sd; +error: +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 22) + /* If we have a client but no subdev, then something went wrong and + we must unregister the client. */ + if (client && sd == NULL) + i2c_unregister_device(client); +#endif + return sd; } EXPORT_SYMBOL_GPL(v4l2_i2c_new_subdev); @@ -918,11 +925,11 @@ struct v4l2_subdev *v4l2_i2c_new_probed_subdev(struct i2c_adapter *adapter, We need better support from the kernel so that we can easily wait for the load to finish. */ if (client == NULL || client->driver == NULL) - return NULL; + goto error; /* Lock the module so we can safely get the v4l2_subdev pointer */ if (!try_module_get(client->driver->driver.owner)) - return NULL; + goto error; sd = i2c_get_clientdata(client); /* Register with the v4l2_device which increases the module's @@ -931,6 +938,14 @@ struct v4l2_subdev *v4l2_i2c_new_probed_subdev(struct i2c_adapter *adapter, sd = NULL; /* Decrease the module use count to match the first try_module_get. */ module_put(client->driver->driver.owner); + +error: +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 22) + /* If we have a client but no subdev, then something went wrong and + we must unregister the client. */ + if (client && sd == NULL) + i2c_unregister_device(client); +#endif return sd; } EXPORT_SYMBOL_GPL(v4l2_i2c_new_probed_subdev); -- cgit v1.2.3 From a2a490b433324f89475c3ebd476769c94325173a Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 18 Mar 2009 17:01:06 +0100 Subject: ov7670: convert to v4l2_subdev From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil Acked-by: Jonathan Corbet --- linux/drivers/media/video/ov7670.c | 391 ++++++++++++++++++------------------- 1 file changed, 189 insertions(+), 202 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/ov7670.c b/linux/drivers/media/video/ov7670.c index f0e1a56eb..3a2fb8e29 100644 --- a/linux/drivers/media/video/ov7670.c +++ b/linux/drivers/media/video/ov7670.c @@ -12,12 +12,11 @@ */ #include #include -#include -#include +#include #include -#include +#include #include -#include +#include #include "compat.h" @@ -25,6 +24,10 @@ MODULE_AUTHOR("Jonathan Corbet "); MODULE_DESCRIPTION("A low-level driver for OmniVision ov7670 sensors"); MODULE_LICENSE("GPL"); +static int debug; +module_param(debug, bool, 0644); +MODULE_PARM_DESC(debug, "Debug level (0-1)"); + /* * Basic window sizes. These probably belong somewhere more globally * useful. @@ -190,11 +193,16 @@ MODULE_LICENSE("GPL"); */ struct ov7670_format_struct; /* coming later */ struct ov7670_info { + struct v4l2_subdev sd; struct ov7670_format_struct *fmt; /* Current format */ unsigned char sat; /* Saturation value */ int hue; /* Hue value */ }; +static inline struct ov7670_info *to_state(struct v4l2_subdev *sd) +{ + return container_of(sd, struct ov7670_info, sd); +} @@ -401,24 +409,27 @@ static struct regval_list ov7670_fmt_raw[] = { * Low-level register I/O. */ -static int ov7670_read(struct i2c_client *c, unsigned char reg, +static int ov7670_read(struct v4l2_subdev *sd, unsigned char reg, unsigned char *value) { + struct i2c_client *client = v4l2_get_subdevdata(sd); int ret; - ret = i2c_smbus_read_byte_data(c, reg); + ret = i2c_smbus_read_byte_data(client, reg); if (ret >= 0) { - *value = (unsigned char) ret; + *value = (unsigned char)ret; ret = 0; } return ret; } -static int ov7670_write(struct i2c_client *c, unsigned char reg, +static int ov7670_write(struct v4l2_subdev *sd, unsigned char reg, unsigned char value) { - int ret = i2c_smbus_write_byte_data(c, reg, value); + struct i2c_client *client = v4l2_get_subdevdata(sd); + int ret = i2c_smbus_write_byte_data(client, reg, value); + if (reg == REG_COM7 && (value & COM7_RESET)) msleep(2); /* Wait for reset to run */ return ret; @@ -426,20 +437,20 @@ static int ov7670_write(struct i2c_client *c, unsigned char reg, #if 0 /* Not currently used, but maybe should be */ -static int ov7670_write_mask(struct i2c_client *c, unsigned char reg, +static int ov7670_write_mask(struct v4l2_subdev *sd, unsigned char reg, unsigned char value, unsigned char mask) { unsigned char v; int ret, tries = 0; - ret = ov7670_read(c, reg, &v); + ret = ov7670_read(sd, reg, &v); if (ret < 0) return ret; v &= ~mask; v |= (value & mask); msleep(10); /* FIXME experiment */ do { - ret = ov7670_write(c, reg, v); + ret = ov7670_write(sd, reg, v); } while (ret < 0 && ++tries < 3); return ret; } @@ -449,10 +460,10 @@ static int ov7670_write_mask(struct i2c_client *c, unsigned char reg, /* * Write a list of register settings; ff/ff stops the process. */ -static int ov7670_write_array(struct i2c_client *c, struct regval_list *vals) +static int ov7670_write_array(struct v4l2_subdev *sd, struct regval_list *vals) { while (vals->reg_num != 0xff || vals->value != 0xff) { - int ret = ov7670_write(c, vals->reg_num, vals->value); + int ret = ov7670_write(sd, vals->reg_num, vals->value); if (ret < 0) return ret; vals++; @@ -464,34 +475,35 @@ static int ov7670_write_array(struct i2c_client *c, struct regval_list *vals) /* * Stuff that knows about the sensor. */ -static void ov7670_reset(struct i2c_client *client) +static int ov7670_reset(struct v4l2_subdev *sd, u32 val) { - ov7670_write(client, REG_COM7, COM7_RESET); + ov7670_write(sd, REG_COM7, COM7_RESET); msleep(1); + return 0; } -static int ov7670_init(struct i2c_client *client) +static int ov7670_init(struct v4l2_subdev *sd, u32 val) { - return ov7670_write_array(client, ov7670_default_regs); + return ov7670_write_array(sd, ov7670_default_regs); } -static int ov7670_detect(struct i2c_client *client) +static int ov7670_detect(struct v4l2_subdev *sd) { unsigned char v; int ret; - ret = ov7670_init(client); + ret = ov7670_init(sd, 0); if (ret < 0) return ret; - ret = ov7670_read(client, REG_MIDH, &v); + ret = ov7670_read(sd, REG_MIDH, &v); if (ret < 0) return ret; if (v != 0x7f) /* OV manuf. id. */ return -ENODEV; - ret = ov7670_read(client, REG_MIDL, &v); + ret = ov7670_read(sd, REG_MIDL, &v); if (ret < 0) return ret; if (v != 0xa2) @@ -499,12 +511,12 @@ static int ov7670_detect(struct i2c_client *client) /* * OK, we know we have an OmniVision chip...but which one? */ - ret = ov7670_read(client, REG_PID, &v); + ret = ov7670_read(sd, REG_PID, &v); if (ret < 0) return ret; if (v != 0x76) /* PID + VER = 0x76 / 0x73 */ return -ENODEV; - ret = ov7670_read(client, REG_VER, &v); + ret = ov7670_read(sd, REG_VER, &v); if (ret < 0) return ret; if (v != 0x73) /* PID + VER = 0x76 / 0x73 */ @@ -649,7 +661,7 @@ static struct ov7670_win_size { /* * Store a set of start/stop values into the camera. */ -static int ov7670_set_hw(struct i2c_client *client, int hstart, int hstop, +static int ov7670_set_hw(struct v4l2_subdev *sd, int hstart, int hstop, int vstart, int vstop) { int ret; @@ -659,26 +671,26 @@ static int ov7670_set_hw(struct i2c_client *client, int hstart, int hstop, * hstart are in href[2:0], bottom 3 of hstop in href[5:3]. There is * a mystery "edge offset" value in the top two bits of href. */ - ret = ov7670_write(client, REG_HSTART, (hstart >> 3) & 0xff); - ret += ov7670_write(client, REG_HSTOP, (hstop >> 3) & 0xff); - ret += ov7670_read(client, REG_HREF, &v); + ret = ov7670_write(sd, REG_HSTART, (hstart >> 3) & 0xff); + ret += ov7670_write(sd, REG_HSTOP, (hstop >> 3) & 0xff); + ret += ov7670_read(sd, REG_HREF, &v); v = (v & 0xc0) | ((hstop & 0x7) << 3) | (hstart & 0x7); msleep(10); - ret += ov7670_write(client, REG_HREF, v); + ret += ov7670_write(sd, REG_HREF, v); /* * Vertical: similar arrangement, but only 10 bits. */ - ret += ov7670_write(client, REG_VSTART, (vstart >> 2) & 0xff); - ret += ov7670_write(client, REG_VSTOP, (vstop >> 2) & 0xff); - ret += ov7670_read(client, REG_VREF, &v); + ret += ov7670_write(sd, REG_VSTART, (vstart >> 2) & 0xff); + ret += ov7670_write(sd, REG_VSTOP, (vstop >> 2) & 0xff); + ret += ov7670_read(sd, REG_VREF, &v); v = (v & 0xf0) | ((vstop & 0x3) << 2) | (vstart & 0x3); msleep(10); - ret += ov7670_write(client, REG_VREF, v); + ret += ov7670_write(sd, REG_VREF, v); return ret; } -static int ov7670_enum_fmt(struct i2c_client *c, struct v4l2_fmtdesc *fmt) +static int ov7670_enum_fmt(struct v4l2_subdev *sd, struct v4l2_fmtdesc *fmt) { struct ov7670_format_struct *ofmt; @@ -693,7 +705,8 @@ static int ov7670_enum_fmt(struct i2c_client *c, struct v4l2_fmtdesc *fmt) } -static int ov7670_try_fmt(struct i2c_client *c, struct v4l2_format *fmt, +static int ov7670_try_fmt_internal(struct v4l2_subdev *sd, + struct v4l2_format *fmt, struct ov7670_format_struct **ret_fmt, struct ov7670_win_size **ret_wsize) { @@ -737,18 +750,23 @@ static int ov7670_try_fmt(struct i2c_client *c, struct v4l2_format *fmt, return 0; } +static int ov7670_try_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) +{ + return ov7670_try_fmt_internal(sd, fmt, NULL, NULL); +} + /* * Set a format. */ -static int ov7670_s_fmt(struct i2c_client *c, struct v4l2_format *fmt) +static int ov7670_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) { int ret; struct ov7670_format_struct *ovfmt; struct ov7670_win_size *wsize; - struct ov7670_info *info = i2c_get_clientdata(c); - unsigned char com7, clkrc; + struct ov7670_info *info = to_state(sd); + unsigned char com7, clkrc = 0; - ret = ov7670_try_fmt(c, fmt, &ovfmt, &wsize); + ret = ov7670_try_fmt_internal(sd, fmt, &ovfmt, &wsize); if (ret) return ret; /* @@ -757,7 +775,7 @@ static int ov7670_s_fmt(struct i2c_client *c, struct v4l2_format *fmt) * the colors. */ if (fmt->fmt.pix.pixelformat == V4L2_PIX_FMT_RGB565) { - ret = ov7670_read(c, REG_CLKRC, &clkrc); + ret = ov7670_read(sd, REG_CLKRC, &clkrc); if (ret) return ret; } @@ -769,20 +787,20 @@ static int ov7670_s_fmt(struct i2c_client *c, struct v4l2_format *fmt) */ com7 = ovfmt->regs[0].value; com7 |= wsize->com7_bit; - ov7670_write(c, REG_COM7, com7); + ov7670_write(sd, REG_COM7, com7); /* * Now write the rest of the array. Also store start/stops */ - ov7670_write_array(c, ovfmt->regs + 1); - ov7670_set_hw(c, wsize->hstart, wsize->hstop, wsize->vstart, + ov7670_write_array(sd, ovfmt->regs + 1); + ov7670_set_hw(sd, wsize->hstart, wsize->hstop, wsize->vstart, wsize->vstop); ret = 0; if (wsize->regs) - ret = ov7670_write_array(c, wsize->regs); + ret = ov7670_write_array(sd, wsize->regs); info->fmt = ovfmt; if (fmt->fmt.pix.pixelformat == V4L2_PIX_FMT_RGB565 && ret == 0) - ret = ov7670_write(c, REG_CLKRC, clkrc); + ret = ov7670_write(sd, REG_CLKRC, clkrc); return ret; } @@ -790,7 +808,7 @@ static int ov7670_s_fmt(struct i2c_client *c, struct v4l2_format *fmt) * Implement G/S_PARM. There is a "high quality" mode we could try * to do someday; for now, we just do the frame rate tweak. */ -static int ov7670_g_parm(struct i2c_client *c, struct v4l2_streamparm *parms) +static int ov7670_g_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *parms) { struct v4l2_captureparm *cp = &parms->parm.capture; unsigned char clkrc; @@ -798,7 +816,7 @@ static int ov7670_g_parm(struct i2c_client *c, struct v4l2_streamparm *parms) if (parms->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) return -EINVAL; - ret = ov7670_read(c, REG_CLKRC, &clkrc); + ret = ov7670_read(sd, REG_CLKRC, &clkrc); if (ret < 0) return ret; memset(cp, 0, sizeof(struct v4l2_captureparm)); @@ -810,7 +828,7 @@ static int ov7670_g_parm(struct i2c_client *c, struct v4l2_streamparm *parms) return 0; } -static int ov7670_s_parm(struct i2c_client *c, struct v4l2_streamparm *parms) +static int ov7670_s_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *parms) { struct v4l2_captureparm *cp = &parms->parm.capture; struct v4l2_fract *tpf = &cp->timeperframe; @@ -824,7 +842,7 @@ static int ov7670_s_parm(struct i2c_client *c, struct v4l2_streamparm *parms) /* * CLKRC has a reserved bit, so let's preserve it. */ - ret = ov7670_read(c, REG_CLKRC, &clkrc); + ret = ov7670_read(sd, REG_CLKRC, &clkrc); if (ret < 0) return ret; if (tpf->numerator == 0 || tpf->denominator == 0) @@ -838,7 +856,7 @@ static int ov7670_s_parm(struct i2c_client *c, struct v4l2_streamparm *parms) clkrc = (clkrc & 0x80) | div; tpf->numerator = 1; tpf->denominator = OV7670_FRAME_RATE/div; - return ov7670_write(c, REG_CLKRC, clkrc); + return ov7670_write(sd, REG_CLKRC, clkrc); } @@ -851,17 +869,17 @@ static int ov7670_s_parm(struct i2c_client *c, struct v4l2_streamparm *parms) /* * Fetch and store the color matrix. */ -static int ov7670_get_cmatrix(struct i2c_client *client, +static int ov7670_get_cmatrix(struct v4l2_subdev *sd, int matrix[CMATRIX_LEN]) { int i, ret; unsigned char signbits; - ret = ov7670_read(client, REG_CMATRIX_SIGN, &signbits); + ret = ov7670_read(sd, REG_CMATRIX_SIGN, &signbits); for (i = 0; i < CMATRIX_LEN; i++) { unsigned char raw; - ret += ov7670_read(client, REG_CMATRIX_BASE + i, &raw); + ret += ov7670_read(sd, REG_CMATRIX_BASE + i, &raw); matrix[i] = (int) raw; if (signbits & (1 << i)) matrix[i] *= -1; @@ -873,7 +891,7 @@ static int ov7670_get_cmatrix(struct i2c_client *client, -static int ov7670_store_cmatrix(struct i2c_client *client, +static int ov7670_store_cmatrix(struct v4l2_subdev *sd, int matrix[CMATRIX_LEN]) { int i, ret; @@ -883,7 +901,7 @@ static int ov7670_store_cmatrix(struct i2c_client *client, * Weird crap seems to exist in the upper part of * the sign bits register, so let's preserve it. */ - ret = ov7670_read(client, REG_CMATRIX_SIGN, &signbits); + ret = ov7670_read(sd, REG_CMATRIX_SIGN, &signbits); signbits &= 0xc0; for (i = 0; i < CMATRIX_LEN; i++) { @@ -902,9 +920,9 @@ static int ov7670_store_cmatrix(struct i2c_client *client, else raw = matrix[i] & 0xff; } - ret += ov7670_write(client, REG_CMATRIX_BASE + i, raw); + ret += ov7670_write(sd, REG_CMATRIX_BASE + i, raw); } - ret += ov7670_write(client, REG_CMATRIX_SIGN, signbits); + ret += ov7670_write(sd, REG_CMATRIX_SIGN, signbits); return ret; } @@ -987,29 +1005,29 @@ static void ov7670_calc_cmatrix(struct ov7670_info *info, -static int ov7670_t_sat(struct i2c_client *client, int value) +static int ov7670_t_sat(struct v4l2_subdev *sd, int value) { - struct ov7670_info *info = i2c_get_clientdata(client); + struct ov7670_info *info = to_state(sd); int matrix[CMATRIX_LEN]; int ret; info->sat = value; ov7670_calc_cmatrix(info, matrix); - ret = ov7670_store_cmatrix(client, matrix); + ret = ov7670_store_cmatrix(sd, matrix); return ret; } -static int ov7670_q_sat(struct i2c_client *client, __s32 *value) +static int ov7670_q_sat(struct v4l2_subdev *sd, __s32 *value) { - struct ov7670_info *info = i2c_get_clientdata(client); + struct ov7670_info *info = to_state(sd); *value = info->sat; return 0; } -static int ov7670_t_hue(struct i2c_client *client, int value) +static int ov7670_t_hue(struct v4l2_subdev *sd, int value) { - struct ov7670_info *info = i2c_get_clientdata(client); + struct ov7670_info *info = to_state(sd); int matrix[CMATRIX_LEN]; int ret; @@ -1017,14 +1035,14 @@ static int ov7670_t_hue(struct i2c_client *client, int value) return -EINVAL; info->hue = value; ov7670_calc_cmatrix(info, matrix); - ret = ov7670_store_cmatrix(client, matrix); + ret = ov7670_store_cmatrix(sd, matrix); return ret; } -static int ov7670_q_hue(struct i2c_client *client, __s32 *value) +static int ov7670_q_hue(struct v4l2_subdev *sd, __s32 *value) { - struct ov7670_info *info = i2c_get_clientdata(client); + struct ov7670_info *info = to_state(sd); *value = info->hue; return 0; @@ -1038,8 +1056,7 @@ static unsigned char ov7670_sm_to_abs(unsigned char v) { if ((v & 0x80) == 0) return v + 128; - else - return 128 - (v & 0x7f); + return 128 - (v & 0x7f); } @@ -1047,105 +1064,104 @@ static unsigned char ov7670_abs_to_sm(unsigned char v) { if (v > 127) return v & 0x7f; - else - return (128 - v) | 0x80; + return (128 - v) | 0x80; } -static int ov7670_t_brightness(struct i2c_client *client, int value) +static int ov7670_t_brightness(struct v4l2_subdev *sd, int value) { unsigned char com8 = 0, v; int ret; - ov7670_read(client, REG_COM8, &com8); + ov7670_read(sd, REG_COM8, &com8); com8 &= ~COM8_AEC; - ov7670_write(client, REG_COM8, com8); + ov7670_write(sd, REG_COM8, com8); v = ov7670_abs_to_sm(value); - ret = ov7670_write(client, REG_BRIGHT, v); + ret = ov7670_write(sd, REG_BRIGHT, v); return ret; } -static int ov7670_q_brightness(struct i2c_client *client, __s32 *value) +static int ov7670_q_brightness(struct v4l2_subdev *sd, __s32 *value) { unsigned char v = 0; - int ret = ov7670_read(client, REG_BRIGHT, &v); + int ret = ov7670_read(sd, REG_BRIGHT, &v); *value = ov7670_sm_to_abs(v); return ret; } -static int ov7670_t_contrast(struct i2c_client *client, int value) +static int ov7670_t_contrast(struct v4l2_subdev *sd, int value) { - return ov7670_write(client, REG_CONTRAS, (unsigned char) value); + return ov7670_write(sd, REG_CONTRAS, (unsigned char) value); } -static int ov7670_q_contrast(struct i2c_client *client, __s32 *value) +static int ov7670_q_contrast(struct v4l2_subdev *sd, __s32 *value) { unsigned char v = 0; - int ret = ov7670_read(client, REG_CONTRAS, &v); + int ret = ov7670_read(sd, REG_CONTRAS, &v); *value = v; return ret; } -static int ov7670_q_hflip(struct i2c_client *client, __s32 *value) +static int ov7670_q_hflip(struct v4l2_subdev *sd, __s32 *value) { int ret; unsigned char v = 0; - ret = ov7670_read(client, REG_MVFP, &v); + ret = ov7670_read(sd, REG_MVFP, &v); *value = (v & MVFP_MIRROR) == MVFP_MIRROR; return ret; } -static int ov7670_t_hflip(struct i2c_client *client, int value) +static int ov7670_t_hflip(struct v4l2_subdev *sd, int value) { unsigned char v = 0; int ret; - ret = ov7670_read(client, REG_MVFP, &v); + ret = ov7670_read(sd, REG_MVFP, &v); if (value) v |= MVFP_MIRROR; else v &= ~MVFP_MIRROR; msleep(10); /* FIXME */ - ret += ov7670_write(client, REG_MVFP, v); + ret += ov7670_write(sd, REG_MVFP, v); return ret; } -static int ov7670_q_vflip(struct i2c_client *client, __s32 *value) +static int ov7670_q_vflip(struct v4l2_subdev *sd, __s32 *value) { int ret; unsigned char v = 0; - ret = ov7670_read(client, REG_MVFP, &v); + ret = ov7670_read(sd, REG_MVFP, &v); *value = (v & MVFP_FLIP) == MVFP_FLIP; return ret; } -static int ov7670_t_vflip(struct i2c_client *client, int value) +static int ov7670_t_vflip(struct v4l2_subdev *sd, int value) { unsigned char v = 0; int ret; - ret = ov7670_read(client, REG_MVFP, &v); + ret = ov7670_read(sd, REG_MVFP, &v); if (value) v |= MVFP_FLIP; else v &= ~MVFP_FLIP; msleep(10); /* FIXME */ - ret += ov7670_write(client, REG_MVFP, v); + ret += ov7670_write(sd, REG_MVFP, v); return ret; } static struct ov7670_control { struct v4l2_queryctrl qc; - int (*query)(struct i2c_client *c, __s32 *value); - int (*tweak)(struct i2c_client *c, int value); + int (*query)(struct v4l2_subdev *sd, __s32 *value); + int (*tweak)(struct v4l2_subdev *sd, int value); } ov7670_controls[] = { { @@ -1244,7 +1260,7 @@ static struct ov7670_control *ov7670_find_control(__u32 id) } -static int ov7670_queryctrl(struct i2c_client *client, +static int ov7670_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc) { struct ov7670_control *ctrl = ov7670_find_control(qc->id); @@ -1255,161 +1271,132 @@ static int ov7670_queryctrl(struct i2c_client *client, return 0; } -static int ov7670_g_ctrl(struct i2c_client *client, struct v4l2_control *ctrl) +static int ov7670_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) { struct ov7670_control *octrl = ov7670_find_control(ctrl->id); int ret; if (octrl == NULL) return -EINVAL; - ret = octrl->query(client, &ctrl->value); + ret = octrl->query(sd, &ctrl->value); if (ret >= 0) return 0; return ret; } -static int ov7670_s_ctrl(struct i2c_client *client, struct v4l2_control *ctrl) +static int ov7670_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) { struct ov7670_control *octrl = ov7670_find_control(ctrl->id); int ret; if (octrl == NULL) return -EINVAL; - ret = octrl->tweak(client, ctrl->value); + ret = octrl->tweak(sd, ctrl->value); if (ret >= 0) return 0; return ret; } +static int ov7670_g_chip_ident(struct v4l2_subdev *sd, + struct v4l2_dbg_chip_ident *chip) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + + return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_OV7670, 0); +} + +static int ov7670_command(struct i2c_client *client, unsigned cmd, void *arg) +{ + return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg); +} +/* ----------------------------------------------------------------------- */ +static const struct v4l2_subdev_core_ops ov7670_core_ops = { + .g_chip_ident = ov7670_g_chip_ident, + .g_ctrl = ov7670_g_ctrl, + .s_ctrl = ov7670_s_ctrl, + .queryctrl = ov7670_queryctrl, + .reset = ov7670_reset, + .init = ov7670_init, +}; +static const struct v4l2_subdev_video_ops ov7670_video_ops = { + .enum_fmt = ov7670_enum_fmt, + .try_fmt = ov7670_try_fmt, + .s_fmt = ov7670_s_fmt, + .s_parm = ov7670_s_parm, + .g_parm = ov7670_g_parm, +}; +static const struct v4l2_subdev_ops ov7670_ops = { + .core = &ov7670_core_ops, + .video = &ov7670_video_ops, +}; -/* - * Basic i2c stuff. - */ -static struct i2c_driver ov7670_driver; +/* ----------------------------------------------------------------------- */ -static int ov7670_attach(struct i2c_adapter *adapter) +static int ov7670_probe(struct i2c_client *client, + const struct i2c_device_id *id) { - int ret; - struct i2c_client *client; + struct v4l2_subdev *sd; struct ov7670_info *info; + int ret; /* * For now: only deal with adapters we recognize. */ - if (adapter->id != I2C_HW_SMBUS_CAFE) + if (client->adapter->id != I2C_HW_SMBUS_CAFE) return -ENODEV; - - client = kzalloc(sizeof (struct i2c_client), GFP_KERNEL); - if (! client) + info = kzalloc(sizeof(struct ov7670_info), GFP_KERNEL); + if (info == NULL) return -ENOMEM; - client->adapter = adapter; - client->addr = OV7670_I2C_ADDR; - client->driver = &ov7670_driver, - strcpy(client->name, "OV7670"); - /* - * Set up our info structure. - */ - info = kzalloc(sizeof (struct ov7670_info), GFP_KERNEL); - if (! info) { - ret = -ENOMEM; - goto out_free; + sd = &info->sd; + v4l2_i2c_subdev_init(sd, client, &ov7670_ops); + + /* Make sure it's an ov7670 */ + ret = ov7670_detect(sd); + if (ret) { + v4l_dbg(1, debug, client, + "chip found @ 0x%x (%s) is not an ov7670 chip.\n", + client->addr << 1, client->adapter->name); + kfree(info); + return ret; } + v4l_info(client, "chip found @ 0x%02x (%s)\n", + client->addr << 1, client->adapter->name); + info->fmt = &ov7670_formats[0]; info->sat = 128; /* Review this */ - i2c_set_clientdata(client, info); - /* - * Make sure it's an ov7670 - */ - ret = ov7670_detect(client); - if (ret) - goto out_free_info; - ret = i2c_attach_client(client); - if (ret) - goto out_free_info; return 0; - - out_free_info: - kfree(info); - out_free: - kfree(client); - return ret; } -static int ov7670_detach(struct i2c_client *client) +static int ov7670_remove(struct i2c_client *client) { - i2c_detach_client(client); - kfree(i2c_get_clientdata(client)); - kfree(client); - return 0; -} + struct v4l2_subdev *sd = i2c_get_clientdata(client); - -static int ov7670_command(struct i2c_client *client, unsigned int cmd, - void *arg) -{ - switch (cmd) { - case VIDIOC_DBG_G_CHIP_IDENT: - return v4l2_chip_ident_i2c_client(client, arg, V4L2_IDENT_OV7670, 0); - - case VIDIOC_INT_RESET: - ov7670_reset(client); - return 0; - - case VIDIOC_INT_INIT: - return ov7670_init(client); - - case VIDIOC_ENUM_FMT: - return ov7670_enum_fmt(client, (struct v4l2_fmtdesc *) arg); - case VIDIOC_TRY_FMT: - return ov7670_try_fmt(client, (struct v4l2_format *) arg, NULL, NULL); - case VIDIOC_S_FMT: - return ov7670_s_fmt(client, (struct v4l2_format *) arg); - case VIDIOC_QUERYCTRL: - return ov7670_queryctrl(client, (struct v4l2_queryctrl *) arg); - case VIDIOC_S_CTRL: - return ov7670_s_ctrl(client, (struct v4l2_control *) arg); - case VIDIOC_G_CTRL: - return ov7670_g_ctrl(client, (struct v4l2_control *) arg); - case VIDIOC_S_PARM: - return ov7670_s_parm(client, (struct v4l2_streamparm *) arg); - case VIDIOC_G_PARM: - return ov7670_g_parm(client, (struct v4l2_streamparm *) arg); - } - return -EINVAL; + v4l2_device_unregister_subdev(sd); + kfree(to_state(sd)); + return 0; } - - -static struct i2c_driver ov7670_driver = { - .driver = { - .name = "ov7670", - }, - .id = I2C_DRIVERID_OV7670, - .attach_adapter = ov7670_attach, - .detach_client = ov7670_detach, - .command = ov7670_command, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) +static const struct i2c_device_id ov7670_id[] = { + { "ov7670", 0 }, + { } }; +MODULE_DEVICE_TABLE(i2c, ov7670_id); - -/* - * Module initialization - */ -static int __init ov7670_mod_init(void) -{ - printk(KERN_NOTICE "OmniVision ov7670 sensor driver, at your service\n"); - return i2c_add_driver(&ov7670_driver); -} - -static void __exit ov7670_mod_exit(void) -{ - i2c_del_driver(&ov7670_driver); -} - -module_init(ov7670_mod_init); -module_exit(ov7670_mod_exit); +#endif +static struct v4l2_i2c_driver_data v4l2_i2c_data = { + .name = "ov7670", + .command = ov7670_command, + .probe = ov7670_probe, + .remove = ov7670_remove, + .legacy_class = I2C_CLASS_TV_ANALOG, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) + .id_table = ov7670_id, +#endif +}; -- cgit v1.2.3 From 871386093b5fd196d9629a5dd995a6e1c060bd37 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 18 Mar 2009 17:13:09 +0100 Subject: cafe_ccic: convert to v4l2_device. From: Hans Verkuil Convert this driver to v4l2_device and removed the unnecessary cafe_dev_list. Priority: normal Signed-off-by: Hans Verkuil Acked-by: Jonathan Corbet --- linux/drivers/media/video/cafe_ccic.c | 158 ++++++++++++---------------------- 1 file changed, 54 insertions(+), 104 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/cafe_ccic.c b/linux/drivers/media/video/cafe_ccic.c index b6c328187..8df215cb2 100644 --- a/linux/drivers/media/video/cafe_ccic.c +++ b/linux/drivers/media/video/cafe_ccic.c @@ -26,7 +26,7 @@ #include #include #include "compat.h" -#include +#include #include #include #include @@ -137,6 +137,7 @@ struct cafe_sio_buffer { */ struct cafe_camera { + struct v4l2_device v4l2_dev; enum cafe_state state; unsigned long flags; /* Buffer status, mainly (dev_lock) */ int users; /* How many open FDs */ @@ -146,7 +147,7 @@ struct cafe_camera * Subsystem structures. */ struct pci_dev *pdev; - struct video_device v4ldev; + struct video_device vdev; struct i2c_adapter i2c_adapter; struct i2c_client *sensor; @@ -197,6 +198,11 @@ struct cafe_camera #define CF_CONFIG_NEEDED 4 /* Must configure hardware */ +static inline struct cafe_camera *to_cam(struct v4l2_device *dev) +{ + return container_of(dev, struct cafe_camera, v4l2_dev); +} + /* * Start over with DMA buffers - dev_lock needed. @@ -239,59 +245,7 @@ static void cafe_set_config_needed(struct cafe_camera *cam, int needed) /* ---------------------------------------------------------------------*/ -/* - * We keep a simple list of known devices to search at open time. - */ -static LIST_HEAD(cafe_dev_list); -static DEFINE_MUTEX(cafe_dev_list_lock); - -static void cafe_add_dev(struct cafe_camera *cam) -{ - mutex_lock(&cafe_dev_list_lock); - list_add_tail(&cam->dev_list, &cafe_dev_list); - mutex_unlock(&cafe_dev_list_lock); -} - -static void cafe_remove_dev(struct cafe_camera *cam) -{ - mutex_lock(&cafe_dev_list_lock); - list_del(&cam->dev_list); - mutex_unlock(&cafe_dev_list_lock); -} - -static struct cafe_camera *cafe_find_dev(int minor) -{ - struct cafe_camera *cam; - mutex_lock(&cafe_dev_list_lock); - list_for_each_entry(cam, &cafe_dev_list, dev_list) { - if (cam->v4ldev.minor == minor) - goto done; - } - cam = NULL; - done: - mutex_unlock(&cafe_dev_list_lock); - return cam; -} - - -static struct cafe_camera *cafe_find_by_pdev(struct pci_dev *pdev) -{ - struct cafe_camera *cam; - - mutex_lock(&cafe_dev_list_lock); - list_for_each_entry(cam, &cafe_dev_list, dev_list) { - if (cam->pdev == pdev) - goto done; - } - cam = NULL; - done: - mutex_unlock(&cafe_dev_list_lock); - return cam; -} - - -/* ------------------------------------------------------------------------ */ /* * Device register I/O */ @@ -482,7 +436,8 @@ static int cafe_smbus_xfer(struct i2c_adapter *adapter, u16 addr, unsigned short flags, char rw, u8 command, int size, union i2c_smbus_data *data) { - struct cafe_camera *cam = i2c_get_adapdata(adapter); + struct v4l2_device *v4l2_dev = i2c_get_adapdata(adapter); + struct cafe_camera *cam = to_cam(v4l2_dev); int ret = -EINVAL; /* @@ -543,7 +498,8 @@ static void cafe_ctlr_power_down(struct cafe_camera *cam); static int cafe_smbus_attach(struct i2c_client *client) { - struct cafe_camera *cam = i2c_get_adapdata(client->adapter); + struct v4l2_device *v4l2_dev = i2c_get_adapdata(client->adapter); + struct cafe_camera *cam = to_cam(v4l2_dev); /* * Don't talk to chips we don't recognize. @@ -557,7 +513,8 @@ static int cafe_smbus_attach(struct i2c_client *client) static int cafe_smbus_detach(struct i2c_client *client) { - struct cafe_camera *cam = i2c_get_adapdata(client->adapter); + struct v4l2_device *v4l2_dev = i2c_get_adapdata(client->adapter); + struct cafe_camera *cam = to_cam(v4l2_dev); if (cam->sensor == client) { cafe_ctlr_stop_dma(cam); @@ -582,7 +539,7 @@ static int cafe_smbus_setup(struct cafe_camera *cam) adap->algo = &cafe_smbus_algo; strcpy(adap->name, "cafe_ccic"); adap->dev.parent = &cam->pdev->dev; - i2c_set_adapdata(adap, cam); + i2c_set_adapdata(adap, &cam->v4l2_dev); ret = i2c_add_adapter(adap); if (ret) printk(KERN_ERR "Unable to register cafe i2c adapter\n"); @@ -816,9 +773,9 @@ static void cafe_ctlr_power_up(struct cafe_camera *cam) * Control 1 is power down, set to 0 to operate. */ cafe_reg_write(cam, REG_GPR, GPR_C1EN|GPR_C0EN); /* pwr up, reset */ -// mdelay(1); /* Marvell says 1ms will do it */ +/* mdelay(1); */ /* Marvell says 1ms will do it */ cafe_reg_write(cam, REG_GPR, GPR_C1EN|GPR_C0EN|GPR_C0); -// mdelay(1); /* Enough? */ +/* mdelay(1); */ /* Enough? */ spin_unlock_irqrestore(&cam->dev_lock, flags); msleep(5); /* Just to be sure */ } @@ -881,7 +838,7 @@ static int cafe_cam_init(struct cafe_camera *cam) if (ret) goto out; cam->sensor_type = chip.ident; -// if (cam->sensor->addr != OV7xx0_SID) { +/* if (cam->sensor->addr != OV7xx0_SID) { */ if (cam->sensor_type != V4L2_IDENT_OV7670) { cam_err(cam, "Unsupported sensor type %d", cam->sensor->addr); ret = -EINVAL; @@ -1481,11 +1438,8 @@ static int cafe_v4l_mmap(struct file *filp, struct vm_area_struct *vma) static int cafe_v4l_open(struct file *filp) { - struct cafe_camera *cam; + struct cafe_camera *cam = video_drvdata(filp); - cam = cafe_find_dev(video_devdata(filp)->minor); - if (cam == NULL) - return -ENODEV; filp->private_data = cam; mutex_lock(&cam->s_mutex); @@ -1539,7 +1493,7 @@ static unsigned int cafe_v4l_poll(struct file *filp, static int cafe_vidioc_queryctrl(struct file *filp, void *priv, struct v4l2_queryctrl *qc) { - struct cafe_camera *cam = filp->private_data; + struct cafe_camera *cam = priv; int ret; mutex_lock(&cam->s_mutex); @@ -1552,7 +1506,7 @@ static int cafe_vidioc_queryctrl(struct file *filp, void *priv, static int cafe_vidioc_g_ctrl(struct file *filp, void *priv, struct v4l2_control *ctrl) { - struct cafe_camera *cam = filp->private_data; + struct cafe_camera *cam = priv; int ret; mutex_lock(&cam->s_mutex); @@ -1565,7 +1519,7 @@ static int cafe_vidioc_g_ctrl(struct file *filp, void *priv, static int cafe_vidioc_s_ctrl(struct file *filp, void *priv, struct v4l2_control *ctrl) { - struct cafe_camera *cam = filp->private_data; + struct cafe_camera *cam = priv; int ret; mutex_lock(&cam->s_mutex); @@ -1752,15 +1706,6 @@ static int cafe_vidioc_s_parm(struct file *filp, void *priv, return ret; } - -static void cafe_v4l_dev_release(struct video_device *vd) -{ - struct cafe_camera *cam = container_of(vd, struct cafe_camera, v4ldev); - - kfree(cam); -} - - /* * This template device holds all of those v4l2 methods; we * clone it for specific real devices. @@ -1807,15 +1752,10 @@ static struct video_device cafe_v4l_template = { .fops = &cafe_v4l_fops, .ioctl_ops = &cafe_v4l_ioctl_ops, - .release = cafe_v4l_dev_release, + .release = video_device_release_empty, }; - - - - - /* ---------------------------------------------------------------------- */ /* * Interrupt handler stuff @@ -2061,10 +2001,10 @@ static void cafe_dfs_cam_setup(struct cafe_camera *cam) if (!cafe_dfs_root) return; - sprintf(fname, "regs-%d", cam->v4ldev.num); + sprintf(fname, "regs-%d", cam->vdev.num); cam->dfs_regs = debugfs_create_file(fname, 0444, cafe_dfs_root, cam, &cafe_dfs_reg_ops); - sprintf(fname, "cam-%d", cam->v4ldev.num); + sprintf(fname, "cam-%d", cam->vdev.num); cam->dfs_cam_regs = debugfs_create_file(fname, 0444, cafe_dfs_root, cam, &cafe_dfs_cam_ops); } @@ -2107,6 +2047,10 @@ static int cafe_pci_probe(struct pci_dev *pdev, cam = kzalloc(sizeof(struct cafe_camera), GFP_KERNEL); if (cam == NULL) goto out; + ret = v4l2_device_register(&pdev->dev, &cam->v4l2_dev); + if (ret) + goto out_free; + mutex_init(&cam->s_mutex); mutex_lock(&cam->s_mutex); spin_lock_init(&cam->dev_lock); @@ -2125,14 +2069,14 @@ static int cafe_pci_probe(struct pci_dev *pdev, */ ret = pci_enable_device(pdev); if (ret) - goto out_free; + goto out_unreg; pci_set_master(pdev); ret = -EIO; cam->regs = pci_iomap(pdev, 0, 0); if (! cam->regs) { printk(KERN_ERR "Unable to ioremap cafe-ccic regs\n"); - goto out_free; + goto out_unreg; } ret = request_irq(pdev->irq, cafe_irq, IRQF_SHARED, "cafe-ccic", cam); if (ret) @@ -2156,13 +2100,15 @@ static int cafe_pci_probe(struct pci_dev *pdev, * Get the v4l2 setup done. */ mutex_lock(&cam->s_mutex); - cam->v4ldev = cafe_v4l_template; - cam->v4ldev.debug = 0; -// cam->v4ldev.debug = V4L2_DEBUG_IOCTL_ARG; - cam->v4ldev.parent = &pdev->dev; - ret = video_register_device(&cam->v4ldev, VFL_TYPE_GRABBER, -1); + cam->vdev = cafe_v4l_template; + cam->vdev.debug = 0; +/* cam->vdev.debug = V4L2_DEBUG_IOCTL_ARG;*/ + cam->vdev.v4l2_dev = &cam->v4l2_dev; + ret = video_register_device(&cam->vdev, VFL_TYPE_GRABBER, -1); if (ret) goto out_smbus; + video_set_drvdata(&cam->vdev, cam); + /* * If so requested, try to get our DMA buffers now. */ @@ -2174,19 +2120,20 @@ static int cafe_pci_probe(struct pci_dev *pdev, cafe_dfs_cam_setup(cam); mutex_unlock(&cam->s_mutex); - cafe_add_dev(cam); return 0; - out_smbus: +out_smbus: cafe_smbus_shutdown(cam); - out_freeirq: +out_freeirq: cafe_ctlr_power_down(cam); free_irq(pdev->irq, cam); - out_iounmap: +out_iounmap: pci_iounmap(pdev, cam->regs); - out_free: +out_free: + v4l2_device_unregister(&cam->v4l2_dev); +out_unreg: kfree(cam); - out: +out: return ret; } @@ -2201,21 +2148,20 @@ static void cafe_shutdown(struct cafe_camera *cam) if (cam->n_sbufs > 0) /* What if they are still mapped? Shouldn't be, but... */ cafe_free_sio_buffers(cam); - cafe_remove_dev(cam); cafe_ctlr_stop_dma(cam); cafe_ctlr_power_down(cam); cafe_smbus_shutdown(cam); cafe_free_dma_bufs(cam); free_irq(cam->pdev->irq, cam); pci_iounmap(cam->pdev, cam->regs); - video_unregister_device(&cam->v4ldev); - /* kfree(cam); done in v4l_release () */ + video_unregister_device(&cam->vdev); } static void cafe_pci_remove(struct pci_dev *pdev) { - struct cafe_camera *cam = cafe_find_by_pdev(pdev); + struct v4l2_device *v4l2_dev = dev_get_drvdata(&pdev->dev); + struct cafe_camera *cam = to_cam(v4l2_dev); if (cam == NULL) { printk(KERN_WARNING "pci_remove on unknown pdev %p\n", pdev); @@ -2225,6 +2171,8 @@ static void cafe_pci_remove(struct pci_dev *pdev) if (cam->users > 0) cam_warn(cam, "Removing a device with users!\n"); cafe_shutdown(cam); + v4l2_device_unregister(&cam->v4l2_dev); + kfree(cam); /* No unlock - it no longer exists */ } @@ -2235,7 +2183,8 @@ static void cafe_pci_remove(struct pci_dev *pdev) */ static int cafe_pci_suspend(struct pci_dev *pdev, pm_message_t state) { - struct cafe_camera *cam = cafe_find_by_pdev(pdev); + struct v4l2_device *v4l2_dev = dev_get_drvdata(&pdev->dev); + struct cafe_camera *cam = to_cam(v4l2_dev); int ret; enum cafe_state cstate; @@ -2253,7 +2202,8 @@ static int cafe_pci_suspend(struct pci_dev *pdev, pm_message_t state) static int cafe_pci_resume(struct pci_dev *pdev) { - struct cafe_camera *cam = cafe_find_by_pdev(pdev); + struct v4l2_device *v4l2_dev = dev_get_drvdata(&pdev->dev); + struct cafe_camera *cam = to_cam(v4l2_dev); int ret = 0; ret = pci_restore_state(pdev); -- cgit v1.2.3 From b22be92f8c1f2b9bd58c64497cce7a3cc46430c8 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 18 Mar 2009 17:16:44 +0100 Subject: cafe_ccic: use v4l2_subdev to talk to the ov7670 sensor. From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil Acked-by: Jonathan Corbet --- linux/drivers/media/video/cafe_ccic.c | 112 ++++++++++------------------------ 1 file changed, 32 insertions(+), 80 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/cafe_ccic.c b/linux/drivers/media/video/cafe_ccic.c index 8df215cb2..cb0333484 100644 --- a/linux/drivers/media/video/cafe_ccic.c +++ b/linux/drivers/media/video/cafe_ccic.c @@ -149,7 +149,8 @@ struct cafe_camera struct pci_dev *pdev; struct video_device vdev; struct i2c_adapter i2c_adapter; - struct i2c_client *sensor; + struct v4l2_subdev *sensor; + unsigned short sensor_addr; unsigned char __iomem *regs; struct list_head dev_list; /* link to other devices */ @@ -197,6 +198,8 @@ struct cafe_camera #define CF_DMA_ACTIVE 3 /* A frame is incoming */ #define CF_CONFIG_NEEDED 4 /* Must configure hardware */ +#define sensor_call(cam, o, f, args...) \ + v4l2_subdev_call(cam->sensor, o, f, ##args) static inline struct cafe_camera *to_cam(struct v4l2_device *dev) { @@ -440,20 +443,6 @@ static int cafe_smbus_xfer(struct i2c_adapter *adapter, u16 addr, struct cafe_camera *cam = to_cam(v4l2_dev); int ret = -EINVAL; - /* - * Refuse to talk to anything but OV cam chips. We should - * never even see an attempt to do so, but one never knows. - */ -#if 0 /* client needs to talk during attach process */ - if (! cam->sensor) { - cam_err(cam, "SMBUS xfer with no client\n"); - return -EINVAL; - } -#endif - if (cam->sensor && addr != cam->sensor->addr) { - cam_err(cam, "funky smbus addr %d\n", addr); - return -EINVAL; - } /* * This interface would appear to only do byte data ops. OK * it can do word too, but the cam chip has no use for that. @@ -492,40 +481,9 @@ static struct i2c_algorithm cafe_smbus_algo = { }; /* Somebody is on the bus */ -static int cafe_cam_init(struct cafe_camera *cam); static void cafe_ctlr_stop_dma(struct cafe_camera *cam); static void cafe_ctlr_power_down(struct cafe_camera *cam); -static int cafe_smbus_attach(struct i2c_client *client) -{ - struct v4l2_device *v4l2_dev = i2c_get_adapdata(client->adapter); - struct cafe_camera *cam = to_cam(v4l2_dev); - - /* - * Don't talk to chips we don't recognize. - */ - if (client->driver->id == I2C_DRIVERID_OV7670) { - cam->sensor = client; - return cafe_cam_init(cam); - } - return -EINVAL; -} - -static int cafe_smbus_detach(struct i2c_client *client) -{ - struct v4l2_device *v4l2_dev = i2c_get_adapdata(client->adapter); - struct cafe_camera *cam = to_cam(v4l2_dev); - - if (cam->sensor == client) { - cafe_ctlr_stop_dma(cam); - cafe_ctlr_power_down(cam); - cam_err(cam, "lost the sensor!\n"); - cam->sensor = NULL; /* Bummer, no camera */ - cam->state = S_NOTREADY; - } - return 0; -} - static int cafe_smbus_setup(struct cafe_camera *cam) { struct i2c_adapter *adap = &cam->i2c_adapter; @@ -534,8 +492,6 @@ static int cafe_smbus_setup(struct cafe_camera *cam) cafe_smbus_enable_irq(cam); adap->id = I2C_HW_SMBUS_CAFE; adap->owner = THIS_MODULE; - adap->client_register = cafe_smbus_attach; - adap->client_unregister = cafe_smbus_detach; adap->algo = &cafe_smbus_algo; strcpy(adap->name, "cafe_ccic"); adap->dev.parent = &cam->pdev->dev; @@ -797,23 +753,9 @@ static void cafe_ctlr_power_down(struct cafe_camera *cam) * Communications with the sensor. */ -static int __cafe_cam_cmd(struct cafe_camera *cam, int cmd, void *arg) -{ - struct i2c_client *sc = cam->sensor; - int ret; - - if (sc == NULL || sc->driver == NULL || sc->driver->command == NULL) - return -EINVAL; - ret = sc->driver->command(sc, cmd, arg); - if (ret == -EPERM) /* Unsupported command */ - return 0; - return ret; -} - static int __cafe_cam_reset(struct cafe_camera *cam) { - int zero = 0; - return __cafe_cam_cmd(cam, VIDIOC_INT_RESET, &zero); + return sensor_call(cam, core, reset, 0); } /* @@ -833,14 +775,13 @@ static int cafe_cam_init(struct cafe_camera *cam) if (ret) goto out; chip.match.type = V4L2_CHIP_MATCH_I2C_ADDR; - chip.match.addr = cam->sensor->addr; - ret = __cafe_cam_cmd(cam, VIDIOC_DBG_G_CHIP_IDENT, &chip); + chip.match.addr = cam->sensor_addr; + ret = sensor_call(cam, core, g_chip_ident, &chip); if (ret) goto out; cam->sensor_type = chip.ident; -/* if (cam->sensor->addr != OV7xx0_SID) { */ if (cam->sensor_type != V4L2_IDENT_OV7670) { - cam_err(cam, "Unsupported sensor type %d", cam->sensor->addr); + cam_err(cam, "Unsupported sensor type 0x%x", cam->sensor_type); ret = -EINVAL; goto out; } @@ -864,21 +805,21 @@ static int cafe_cam_set_flip(struct cafe_camera *cam) memset(&ctrl, 0, sizeof(ctrl)); ctrl.id = V4L2_CID_VFLIP; ctrl.value = flip; - return __cafe_cam_cmd(cam, VIDIOC_S_CTRL, &ctrl); + return sensor_call(cam, core, s_ctrl, &ctrl); } static int cafe_cam_configure(struct cafe_camera *cam) { struct v4l2_format fmt; - int ret, zero = 0; + int ret; if (cam->state != S_IDLE) return -EINVAL; fmt.fmt.pix = cam->pix_format; - ret = __cafe_cam_cmd(cam, VIDIOC_INT_INIT, &zero); + ret = sensor_call(cam, core, init, 0); if (ret == 0) - ret = __cafe_cam_cmd(cam, VIDIOC_S_FMT, &fmt); + ret = sensor_call(cam, video, s_fmt, &fmt); /* * OV7670 does weird things if flip is set *before* format... */ @@ -1497,7 +1438,7 @@ static int cafe_vidioc_queryctrl(struct file *filp, void *priv, int ret; mutex_lock(&cam->s_mutex); - ret = __cafe_cam_cmd(cam, VIDIOC_QUERYCTRL, qc); + ret = sensor_call(cam, core, queryctrl, qc); mutex_unlock(&cam->s_mutex); return ret; } @@ -1510,7 +1451,7 @@ static int cafe_vidioc_g_ctrl(struct file *filp, void *priv, int ret; mutex_lock(&cam->s_mutex); - ret = __cafe_cam_cmd(cam, VIDIOC_G_CTRL, ctrl); + ret = sensor_call(cam, core, g_ctrl, ctrl); mutex_unlock(&cam->s_mutex); return ret; } @@ -1523,7 +1464,7 @@ static int cafe_vidioc_s_ctrl(struct file *filp, void *priv, int ret; mutex_lock(&cam->s_mutex); - ret = __cafe_cam_cmd(cam, VIDIOC_S_CTRL, ctrl); + ret = sensor_call(cam, core, s_ctrl, ctrl); mutex_unlock(&cam->s_mutex); return ret; } @@ -1565,7 +1506,7 @@ static int cafe_vidioc_enum_fmt_vid_cap(struct file *filp, if (fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) return -EINVAL; mutex_lock(&cam->s_mutex); - ret = __cafe_cam_cmd(cam, VIDIOC_ENUM_FMT, fmt); + ret = sensor_call(cam, video, enum_fmt, fmt); mutex_unlock(&cam->s_mutex); return ret; } @@ -1578,7 +1519,7 @@ static int cafe_vidioc_try_fmt_vid_cap(struct file *filp, void *priv, int ret; mutex_lock(&cam->s_mutex); - ret = __cafe_cam_cmd(cam, VIDIOC_TRY_FMT, fmt); + ret = sensor_call(cam, video, try_fmt, fmt); mutex_unlock(&cam->s_mutex); return ret; } @@ -1687,7 +1628,7 @@ static int cafe_vidioc_g_parm(struct file *filp, void *priv, int ret; mutex_lock(&cam->s_mutex); - ret = __cafe_cam_cmd(cam, VIDIOC_G_PARM, parms); + ret = sensor_call(cam, video, g_parm, parms); mutex_unlock(&cam->s_mutex); parms->parm.capture.readbuffers = n_dma_bufs; return ret; @@ -1700,7 +1641,7 @@ static int cafe_vidioc_s_parm(struct file *filp, void *priv, int ret; mutex_lock(&cam->s_mutex); - ret = __cafe_cam_cmd(cam, VIDIOC_S_PARM, parms); + ret = sensor_call(cam, video, s_parm, parms); mutex_unlock(&cam->s_mutex); parms->parm.capture.readbuffers = n_dma_bufs; return ret; @@ -1980,7 +1921,7 @@ static ssize_t cafe_dfs_read_cam(struct file *file, { u8 v; - cafe_smbus_read_data(cam, cam->sensor->addr, offset, &v); + cafe_smbus_read_data(cam, cam->sensor_addr, offset, &v); s += sprintf(s, "%02x: %02x\n", offset, v); } return simple_read_from_buffer(buf, count, ppos, cafe_debug_buf, @@ -2096,6 +2037,18 @@ static int cafe_pci_probe(struct pci_dev *pdev, ret = cafe_smbus_setup(cam); if (ret) goto out_freeirq; + + cam->sensor_addr = 0x42; + cam->sensor = v4l2_i2c_new_subdev(&cam->i2c_adapter, + "ov7670", "ov7670", cam->sensor_addr); + if (cam->sensor == NULL) { + ret = -ENODEV; + goto out_smbus; + } + ret = cafe_cam_init(cam); + if (ret) + goto out_smbus; + /* * Get the v4l2 setup done. */ @@ -2270,7 +2223,6 @@ static int __init cafe_init(void) printk(KERN_ERR "Unable to register cafe_ccic driver\n"); goto out; } - request_module("ov7670"); /* FIXME want something more general */ ret = 0; out: -- cgit v1.2.3 From 9586770579fda1a7ffe16db0ca1a94aae4f58113 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 18 Mar 2009 17:23:13 +0100 Subject: ov7670: cleanup and remove legacy code. From: Hans Verkuil v4l2-i2c-drv-legacy.h and ov7670_command are no longer needed after the cafe driver is converted to use v4l2_subdev. Rather than using a large ov7670_control array, just call the handlers via a simple switch and use v4l2_ctrl_query_fill() to handle queryctrl. Priority: normal Signed-off-by: Hans Verkuil Acked-by: Jonathan Corbet --- linux/drivers/media/video/ov7670.c | 210 ++++++++++--------------------------- 1 file changed, 58 insertions(+), 152 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/ov7670.c b/linux/drivers/media/video/ov7670.c index 3a2fb8e29..2a048645c 100644 --- a/linux/drivers/media/video/ov7670.c +++ b/linux/drivers/media/video/ov7670.c @@ -16,7 +16,7 @@ #include #include #include -#include +#include #include "compat.h" @@ -1005,7 +1005,7 @@ static void ov7670_calc_cmatrix(struct ov7670_info *info, -static int ov7670_t_sat(struct v4l2_subdev *sd, int value) +static int ov7670_s_sat(struct v4l2_subdev *sd, int value) { struct ov7670_info *info = to_state(sd); int matrix[CMATRIX_LEN]; @@ -1017,7 +1017,7 @@ static int ov7670_t_sat(struct v4l2_subdev *sd, int value) return ret; } -static int ov7670_q_sat(struct v4l2_subdev *sd, __s32 *value) +static int ov7670_g_sat(struct v4l2_subdev *sd, __s32 *value) { struct ov7670_info *info = to_state(sd); @@ -1025,7 +1025,7 @@ static int ov7670_q_sat(struct v4l2_subdev *sd, __s32 *value) return 0; } -static int ov7670_t_hue(struct v4l2_subdev *sd, int value) +static int ov7670_s_hue(struct v4l2_subdev *sd, int value) { struct ov7670_info *info = to_state(sd); int matrix[CMATRIX_LEN]; @@ -1040,7 +1040,7 @@ static int ov7670_t_hue(struct v4l2_subdev *sd, int value) } -static int ov7670_q_hue(struct v4l2_subdev *sd, __s32 *value) +static int ov7670_g_hue(struct v4l2_subdev *sd, __s32 *value) { struct ov7670_info *info = to_state(sd); @@ -1067,7 +1067,7 @@ static unsigned char ov7670_abs_to_sm(unsigned char v) return (128 - v) | 0x80; } -static int ov7670_t_brightness(struct v4l2_subdev *sd, int value) +static int ov7670_s_brightness(struct v4l2_subdev *sd, int value) { unsigned char com8 = 0, v; int ret; @@ -1080,7 +1080,7 @@ static int ov7670_t_brightness(struct v4l2_subdev *sd, int value) return ret; } -static int ov7670_q_brightness(struct v4l2_subdev *sd, __s32 *value) +static int ov7670_g_brightness(struct v4l2_subdev *sd, __s32 *value) { unsigned char v = 0; int ret = ov7670_read(sd, REG_BRIGHT, &v); @@ -1089,12 +1089,12 @@ static int ov7670_q_brightness(struct v4l2_subdev *sd, __s32 *value) return ret; } -static int ov7670_t_contrast(struct v4l2_subdev *sd, int value) +static int ov7670_s_contrast(struct v4l2_subdev *sd, int value) { return ov7670_write(sd, REG_CONTRAS, (unsigned char) value); } -static int ov7670_q_contrast(struct v4l2_subdev *sd, __s32 *value) +static int ov7670_g_contrast(struct v4l2_subdev *sd, __s32 *value) { unsigned char v = 0; int ret = ov7670_read(sd, REG_CONTRAS, &v); @@ -1103,7 +1103,7 @@ static int ov7670_q_contrast(struct v4l2_subdev *sd, __s32 *value) return ret; } -static int ov7670_q_hflip(struct v4l2_subdev *sd, __s32 *value) +static int ov7670_g_hflip(struct v4l2_subdev *sd, __s32 *value) { int ret; unsigned char v = 0; @@ -1114,7 +1114,7 @@ static int ov7670_q_hflip(struct v4l2_subdev *sd, __s32 *value) } -static int ov7670_t_hflip(struct v4l2_subdev *sd, int value) +static int ov7670_s_hflip(struct v4l2_subdev *sd, int value) { unsigned char v = 0; int ret; @@ -1131,7 +1131,7 @@ static int ov7670_t_hflip(struct v4l2_subdev *sd, int value) -static int ov7670_q_vflip(struct v4l2_subdev *sd, __s32 *value) +static int ov7670_g_vflip(struct v4l2_subdev *sd, __s32 *value) { int ret; unsigned char v = 0; @@ -1142,7 +1142,7 @@ static int ov7670_q_vflip(struct v4l2_subdev *sd, __s32 *value) } -static int ov7670_t_vflip(struct v4l2_subdev *sd, int value) +static int ov7670_s_vflip(struct v4l2_subdev *sd, int value) { unsigned char v = 0; int ret; @@ -1157,144 +1157,62 @@ static int ov7670_t_vflip(struct v4l2_subdev *sd, int value) return ret; } - -static struct ov7670_control { - struct v4l2_queryctrl qc; - int (*query)(struct v4l2_subdev *sd, __s32 *value); - int (*tweak)(struct v4l2_subdev *sd, int value); -} ov7670_controls[] = -{ - { - .qc = { - .id = V4L2_CID_BRIGHTNESS, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "Brightness", - .minimum = 0, - .maximum = 255, - .step = 1, - .default_value = 0x80, - .flags = V4L2_CTRL_FLAG_SLIDER - }, - .tweak = ov7670_t_brightness, - .query = ov7670_q_brightness, - }, - { - .qc = { - .id = V4L2_CID_CONTRAST, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "Contrast", - .minimum = 0, - .maximum = 127, - .step = 1, - .default_value = 0x40, /* XXX ov7670 spec */ - .flags = V4L2_CTRL_FLAG_SLIDER - }, - .tweak = ov7670_t_contrast, - .query = ov7670_q_contrast, - }, - { - .qc = { - .id = V4L2_CID_SATURATION, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "Saturation", - .minimum = 0, - .maximum = 256, - .step = 1, - .default_value = 0x80, - .flags = V4L2_CTRL_FLAG_SLIDER - }, - .tweak = ov7670_t_sat, - .query = ov7670_q_sat, - }, - { - .qc = { - .id = V4L2_CID_HUE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "HUE", - .minimum = -180, - .maximum = 180, - .step = 5, - .default_value = 0, - .flags = V4L2_CTRL_FLAG_SLIDER - }, - .tweak = ov7670_t_hue, - .query = ov7670_q_hue, - }, - { - .qc = { - .id = V4L2_CID_VFLIP, - .type = V4L2_CTRL_TYPE_BOOLEAN, - .name = "Vertical flip", - .minimum = 0, - .maximum = 1, - .step = 1, - .default_value = 0, - }, - .tweak = ov7670_t_vflip, - .query = ov7670_q_vflip, - }, - { - .qc = { - .id = V4L2_CID_HFLIP, - .type = V4L2_CTRL_TYPE_BOOLEAN, - .name = "Horizontal mirror", - .minimum = 0, - .maximum = 1, - .step = 1, - .default_value = 0, - }, - .tweak = ov7670_t_hflip, - .query = ov7670_q_hflip, - }, -}; -#define N_CONTROLS (ARRAY_SIZE(ov7670_controls)) - -static struct ov7670_control *ov7670_find_control(__u32 id) -{ - int i; - - for (i = 0; i < N_CONTROLS; i++) - if (ov7670_controls[i].qc.id == id) - return ov7670_controls + i; - return NULL; -} - - static int ov7670_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc) { - struct ov7670_control *ctrl = ov7670_find_control(qc->id); - - if (ctrl == NULL) - return -EINVAL; - *qc = ctrl->qc; - return 0; + /* Fill in min, max, step and default value for these controls. */ + switch (qc->id) { + case V4L2_CID_BRIGHTNESS: + return v4l2_ctrl_query_fill(qc, 0, 255, 1, 128); + case V4L2_CID_CONTRAST: + return v4l2_ctrl_query_fill(qc, 0, 127, 1, 64); + case V4L2_CID_VFLIP: + case V4L2_CID_HFLIP: + return v4l2_ctrl_query_fill(qc, 0, 1, 1, 0); + case V4L2_CID_SATURATION: + return v4l2_ctrl_query_fill(qc, 0, 256, 1, 128); + case V4L2_CID_HUE: + return v4l2_ctrl_query_fill(qc, -180, 180, 5, 0); + } + return -EINVAL; } static int ov7670_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) { - struct ov7670_control *octrl = ov7670_find_control(ctrl->id); - int ret; - - if (octrl == NULL) - return -EINVAL; - ret = octrl->query(sd, &ctrl->value); - if (ret >= 0) - return 0; - return ret; + switch (ctrl->id) { + case V4L2_CID_BRIGHTNESS: + return ov7670_g_brightness(sd, &ctrl->value); + case V4L2_CID_CONTRAST: + return ov7670_g_contrast(sd, &ctrl->value); + case V4L2_CID_SATURATION: + return ov7670_g_sat(sd, &ctrl->value); + case V4L2_CID_HUE: + return ov7670_g_hue(sd, &ctrl->value); + case V4L2_CID_VFLIP: + return ov7670_g_vflip(sd, &ctrl->value); + case V4L2_CID_HFLIP: + return ov7670_g_hflip(sd, &ctrl->value); + } + return -EINVAL; } static int ov7670_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) { - struct ov7670_control *octrl = ov7670_find_control(ctrl->id); - int ret; - - if (octrl == NULL) - return -EINVAL; - ret = octrl->tweak(sd, ctrl->value); - if (ret >= 0) - return 0; - return ret; + switch (ctrl->id) { + case V4L2_CID_BRIGHTNESS: + return ov7670_s_brightness(sd, ctrl->value); + case V4L2_CID_CONTRAST: + return ov7670_s_contrast(sd, ctrl->value); + case V4L2_CID_SATURATION: + return ov7670_s_sat(sd, ctrl->value); + case V4L2_CID_HUE: + return ov7670_s_hue(sd, ctrl->value); + case V4L2_CID_VFLIP: + return ov7670_s_vflip(sd, ctrl->value); + case V4L2_CID_HFLIP: + return ov7670_s_hflip(sd, ctrl->value); + } + return -EINVAL; } static int ov7670_g_chip_ident(struct v4l2_subdev *sd, @@ -1305,11 +1223,6 @@ static int ov7670_g_chip_ident(struct v4l2_subdev *sd, return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_OV7670, 0); } -static int ov7670_command(struct i2c_client *client, unsigned cmd, void *arg) -{ - return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg); -} - /* ----------------------------------------------------------------------- */ static const struct v4l2_subdev_core_ops ov7670_core_ops = { @@ -1343,11 +1256,6 @@ static int ov7670_probe(struct i2c_client *client, struct ov7670_info *info; int ret; - /* - * For now: only deal with adapters we recognize. - */ - if (client->adapter->id != I2C_HW_SMBUS_CAFE) - return -ENODEV; info = kzalloc(sizeof(struct ov7670_info), GFP_KERNEL); if (info == NULL) return -ENOMEM; @@ -1392,10 +1300,8 @@ MODULE_DEVICE_TABLE(i2c, ov7670_id); #endif static struct v4l2_i2c_driver_data v4l2_i2c_data = { .name = "ov7670", - .command = ov7670_command, .probe = ov7670_probe, .remove = ov7670_remove, - .legacy_class = I2C_CLASS_TV_ANALOG, #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) .id_table = ov7670_id, #endif -- cgit v1.2.3 From 8d931e8c8a626b3828f0fd1805f7ef17a43f223e Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 18 Mar 2009 17:24:05 +0100 Subject: ov7670: add support to get/set registers From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil Acked-by: Jonathan Corbet --- linux/drivers/media/video/ov7670.c | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/ov7670.c b/linux/drivers/media/video/ov7670.c index 2a048645c..263f20669 100644 --- a/linux/drivers/media/video/ov7670.c +++ b/linux/drivers/media/video/ov7670.c @@ -1223,6 +1223,36 @@ static int ov7670_g_chip_ident(struct v4l2_subdev *sd, return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_OV7670, 0); } +#ifdef CONFIG_VIDEO_ADV_DEBUG +static int ov7670_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + unsigned char val = 0; + int ret; + + if (!v4l2_chip_match_i2c_client(client, ®->match)) + return -EINVAL; + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + ret = ov7670_read(sd, reg->reg & 0xff, &val); + reg->val = val; + reg->size = 1; + return ret; +} + +static int ov7670_s_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + + if (!v4l2_chip_match_i2c_client(client, ®->match)) + return -EINVAL; + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + ov7670_write(sd, reg->reg & 0xff, reg->val & 0xff); + return 0; +} +#endif + /* ----------------------------------------------------------------------- */ static const struct v4l2_subdev_core_ops ov7670_core_ops = { @@ -1232,6 +1262,10 @@ static const struct v4l2_subdev_core_ops ov7670_core_ops = { .queryctrl = ov7670_queryctrl, .reset = ov7670_reset, .init = ov7670_init, +#ifdef CONFIG_VIDEO_ADV_DEBUG + .g_register = ov7670_g_register, + .s_register = ov7670_s_register, +#endif }; static const struct v4l2_subdev_video_ops ov7670_video_ops = { -- cgit v1.2.3 From 92ad1343de9f9ffcd487fa43ebc8a64ac2ecf04c Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 18 Mar 2009 17:25:54 +0100 Subject: cafe_ccic: replace debugfs with g/s_register ioctls. From: Hans Verkuil Using VIDIOC_DBG_S/G_REGISTER is the standard way of reading/writing register for advanced debugging under v4l2. In addition, using this means that the cafe_ccic driver doesn't need to have knowledge about the used sensor: the debug ioctl can be passed on to the sensor if it isn't for the host. Priority: normal Signed-off-by: Hans Verkuil Acked-by: Jonathan Corbet --- linux/drivers/media/video/cafe_ccic.c | 176 +++++++++------------------------- 1 file changed, 46 insertions(+), 130 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/cafe_ccic.c b/linux/drivers/media/video/cafe_ccic.c index cb0333484..4b4b67a20 100644 --- a/linux/drivers/media/video/cafe_ccic.c +++ b/linux/drivers/media/video/cafe_ccic.c @@ -34,7 +34,6 @@ #include #include #include -#include #include #include @@ -183,10 +182,6 @@ struct cafe_camera /* Misc */ wait_queue_head_t smbus_wait; /* Waiting on i2c events */ wait_queue_head_t iowait; /* Waiting on frame data */ -#ifdef CONFIG_VIDEO_ADV_DEBUG - struct dentry *dfs_regs; - struct dentry *dfs_cam_regs; -#endif }; /* @@ -1647,6 +1642,47 @@ static int cafe_vidioc_s_parm(struct file *filp, void *priv, return ret; } +static int cafe_vidioc_g_chip_ident(struct file *file, void *priv, + struct v4l2_dbg_chip_ident *chip) +{ + struct cafe_camera *cam = priv; + + chip->ident = V4L2_IDENT_NONE; + chip->revision = 0; + if (v4l2_chip_match_host(&chip->match)) { + chip->ident = V4L2_IDENT_CAFE; + return 0; + } + return sensor_call(cam, core, g_chip_ident, chip); +} + +#ifdef CONFIG_VIDEO_ADV_DEBUG +static int cafe_vidioc_g_register(struct file *file, void *priv, + struct v4l2_dbg_register *reg) +{ + struct cafe_camera *cam = priv; + + if (v4l2_chip_match_host(®->match)) { + reg->val = cafe_reg_read(cam, reg->reg); + reg->size = 4; + return 0; + } + return sensor_call(cam, core, g_register, reg); +} + +static int cafe_vidioc_s_register(struct file *file, void *priv, + struct v4l2_dbg_register *reg) +{ + struct cafe_camera *cam = priv; + + if (v4l2_chip_match_host(®->match)) { + cafe_reg_write(cam, reg->reg, reg->val); + return 0; + } + return sensor_call(cam, core, s_register, reg); +} +#endif + /* * This template device holds all of those v4l2 methods; we * clone it for specific real devices. @@ -1683,6 +1719,11 @@ static const struct v4l2_ioctl_ops cafe_v4l_ioctl_ops = { .vidioc_s_ctrl = cafe_vidioc_s_ctrl, .vidioc_g_parm = cafe_vidioc_g_parm, .vidioc_s_parm = cafe_vidioc_s_parm, + .vidioc_g_chip_ident = cafe_vidioc_g_chip_ident, +#ifdef CONFIG_VIDEO_ADV_DEBUG + .vidioc_g_register = cafe_vidioc_g_register, + .vidioc_s_register = cafe_vidioc_s_register, +#endif }; static struct video_device cafe_v4l_template = { @@ -1850,127 +1891,6 @@ static irqreturn_t cafe_irq(int irq, void *data) /* -------------------------------------------------------------------------- */ -#ifdef CONFIG_VIDEO_ADV_DEBUG -/* - * Debugfs stuff. - */ - -static char cafe_debug_buf[1024]; -static struct dentry *cafe_dfs_root; - -static void cafe_dfs_setup(void) -{ - cafe_dfs_root = debugfs_create_dir("cafe_ccic", NULL); - if (IS_ERR(cafe_dfs_root)) { - cafe_dfs_root = NULL; /* Never mind */ - printk(KERN_NOTICE "cafe_ccic unable to set up debugfs\n"); - } -} - -static void cafe_dfs_shutdown(void) -{ - if (cafe_dfs_root) - debugfs_remove(cafe_dfs_root); -} - -static int cafe_dfs_open(struct inode *inode, struct file *file) -{ - file->private_data = inode->i_private; - return 0; -} - -static ssize_t cafe_dfs_read_regs(struct file *file, - char __user *buf, size_t count, loff_t *ppos) -{ - struct cafe_camera *cam = file->private_data; - char *s = cafe_debug_buf; - int offset; - - for (offset = 0; offset < 0x44; offset += 4) - s += sprintf(s, "%02x: %08x\n", offset, - cafe_reg_read(cam, offset)); - for (offset = 0x88; offset <= 0x90; offset += 4) - s += sprintf(s, "%02x: %08x\n", offset, - cafe_reg_read(cam, offset)); - for (offset = 0xb4; offset <= 0xbc; offset += 4) - s += sprintf(s, "%02x: %08x\n", offset, - cafe_reg_read(cam, offset)); - for (offset = 0x3000; offset <= 0x300c; offset += 4) - s += sprintf(s, "%04x: %08x\n", offset, - cafe_reg_read(cam, offset)); - return simple_read_from_buffer(buf, count, ppos, cafe_debug_buf, - s - cafe_debug_buf); -} - -static const struct file_operations cafe_dfs_reg_ops = { - .owner = THIS_MODULE, - .read = cafe_dfs_read_regs, - .open = cafe_dfs_open -}; - -static ssize_t cafe_dfs_read_cam(struct file *file, - char __user *buf, size_t count, loff_t *ppos) -{ - struct cafe_camera *cam = file->private_data; - char *s = cafe_debug_buf; - int offset; - - if (! cam->sensor) - return -EINVAL; - for (offset = 0x0; offset < 0x8a; offset++) - { - u8 v; - - cafe_smbus_read_data(cam, cam->sensor_addr, offset, &v); - s += sprintf(s, "%02x: %02x\n", offset, v); - } - return simple_read_from_buffer(buf, count, ppos, cafe_debug_buf, - s - cafe_debug_buf); -} - -static const struct file_operations cafe_dfs_cam_ops = { - .owner = THIS_MODULE, - .read = cafe_dfs_read_cam, - .open = cafe_dfs_open -}; - - - -static void cafe_dfs_cam_setup(struct cafe_camera *cam) -{ - char fname[40]; - - if (!cafe_dfs_root) - return; - sprintf(fname, "regs-%d", cam->vdev.num); - cam->dfs_regs = debugfs_create_file(fname, 0444, cafe_dfs_root, - cam, &cafe_dfs_reg_ops); - sprintf(fname, "cam-%d", cam->vdev.num); - cam->dfs_cam_regs = debugfs_create_file(fname, 0444, cafe_dfs_root, - cam, &cafe_dfs_cam_ops); -} - - -static void cafe_dfs_cam_shutdown(struct cafe_camera *cam) -{ - if (! IS_ERR(cam->dfs_regs)) - debugfs_remove(cam->dfs_regs); - if (! IS_ERR(cam->dfs_cam_regs)) - debugfs_remove(cam->dfs_cam_regs); -} - -#else - -#define cafe_dfs_setup() -#define cafe_dfs_shutdown() -#define cafe_dfs_cam_setup(cam) -#define cafe_dfs_cam_shutdown(cam) -#endif /* CONFIG_VIDEO_ADV_DEBUG */ - - - - -/* ------------------------------------------------------------------------*/ /* * PCI interface stuff. */ @@ -2071,7 +1991,6 @@ static int cafe_pci_probe(struct pci_dev *pdev, " will try again later."); } - cafe_dfs_cam_setup(cam); mutex_unlock(&cam->s_mutex); return 0; @@ -2097,7 +2016,6 @@ out: static void cafe_shutdown(struct cafe_camera *cam) { /* FIXME: Make sure we take care of everything here */ - cafe_dfs_cam_shutdown(cam); if (cam->n_sbufs > 0) /* What if they are still mapped? Shouldn't be, but... */ cafe_free_sio_buffers(cam); @@ -2217,7 +2135,6 @@ static int __init cafe_init(void) printk(KERN_NOTICE "Marvell M88ALP01 'CAFE' Camera Controller version %d\n", CAFE_VERSION); - cafe_dfs_setup(); ret = pci_register_driver(&cafe_pci_driver); if (ret) { printk(KERN_ERR "Unable to register cafe_ccic driver\n"); @@ -2233,7 +2150,6 @@ static int __init cafe_init(void) static void __exit cafe_exit(void) { pci_unregister_driver(&cafe_pci_driver); - cafe_dfs_shutdown(); } module_init(cafe_init); -- cgit v1.2.3 From 94a0e644a33260b89beb679752d5da322e1474c4 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 18 Mar 2009 17:31:56 +0100 Subject: cafe_ccic: stick in a comment with a request for test results From: Hans Verkuil Due to lack of hardware this conversion to v4l2_device/v4l2_subdev is untested. If all goes well I should be able to test it in about a month, but just in case I can't manage that it should be made clear in the code that this isn't tested. Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/cafe_ccic.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/cafe_ccic.c b/linux/drivers/media/video/cafe_ccic.c index 4b4b67a20..2619d77ef 100644 --- a/linux/drivers/media/video/cafe_ccic.c +++ b/linux/drivers/media/video/cafe_ccic.c @@ -11,6 +11,12 @@ * * Written by Jonathan Corbet, corbet@lwn.net. * + * v4l2_device/v4l2_subdev conversion by: + * Copyright (C) 2009 Hans Verkuil + * + * Note: this conversion is untested! Please contact the linux-media + * mailinglist if you can test this, together with the test results. + * * This file may be distributed under the terms of the GNU General * Public License, version 2. */ -- cgit v1.2.3 From 9120970b21b6c7d5f12afd6569359870295d34d7 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 19 Mar 2009 19:26:23 -0300 Subject: au0828: Fix compilation when VIDEO_ADV_DEBUG = n From: Mauro Carvalho Chehab As reported by Kyle McMartin and Randy Dunlap: drivers/media/video/au0828/au0828-video.c:1438: error: 'const struct v4l2_subdev_core_ops' has no member named 'g_register' drivers/media/video/au0828/au0828-video.c:1453: error: 'const struct v4l2_subdev_core_ops' has no member named 's_register' This patch properly implements those two API ioctls only when debug is enabled. Priority: normal CC: Devin Heitmueller Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/au0828/au0828-video.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (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 ac5662c59..fc76b2e20 100644 --- a/linux/drivers/media/video/au0828/au0828-video.c +++ b/linux/drivers/media/video/au0828/au0828-video.c @@ -1433,6 +1433,7 @@ static int vidioc_streamoff(struct file *file, void *priv, return 0; } +#ifdef CONFIG_VIDEO_ADV_DEBUG static int vidioc_g_register(struct file *file, void *priv, struct v4l2_dbg_register *reg) { @@ -1463,6 +1464,7 @@ static int vidioc_s_register(struct file *file, void *priv, } return 0; } +#endif static int vidioc_reqbufs(struct file *file, void *priv, struct v4l2_requestbuffers *rb) @@ -1584,8 +1586,8 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = { #ifdef CONFIG_VIDEO_ADV_DEBUG .vidioc_g_register = vidioc_g_register, .vidioc_s_register = vidioc_s_register, - .vidioc_g_chip_ident = vidioc_g_chip_ident, #endif + .vidioc_g_chip_ident = vidioc_g_chip_ident, #ifdef CONFIG_VIDEO_V4L1_COMPAT .vidiocgmbuf = vidiocgmbuf, #endif -- cgit v1.2.3 From d149bb041dbb783fcd3b56dafd8a719e217335b3 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 19 Mar 2009 21:03:09 -0300 Subject: au8522/au0828: Fix Kconfig dependencies From: Mauro Carvalho Chehab au8522 is now dependent of V4L2, as reported by Randy Dunlap : au8522_decoder.c:(.text+0x199898): undefined reference to `v4l2_ctrl_query_fill' au8522_decoder.c:(.text+0x1998b3): undefined reference to `v4l2_ctrl_query_fill' au8522_decoder.c:(.text+0x199944): undefined reference to `v4l2_device_unregister_subdev' au8522_decoder.c:(.text+0x19997c): undefined reference to `v4l2_chip_ident_i2c_client' au8522_decoder.c:(.text+0x199f1e): undefined reference to `v4l2_i2c_subdev_init' Priority: normal CC: Devin Heitmueller Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/frontends/Kconfig | 2 +- linux/drivers/media/video/au0828/Kconfig | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/frontends/Kconfig b/linux/drivers/media/dvb/frontends/Kconfig index 5c78f6329..a206cee23 100644 --- a/linux/drivers/media/dvb/frontends/Kconfig +++ b/linux/drivers/media/dvb/frontends/Kconfig @@ -437,7 +437,7 @@ config DVB_S5H1409 config DVB_AU8522 tristate "Auvitek AU8522 based" - depends on DVB_CORE && I2C + depends on DVB_CORE && I2C && VIDEO_V4L2 default m if DVB_FE_CUSTOMISE help An ATSC 8VSB and QAM64/256 tuner module. Say Y when you want diff --git a/linux/drivers/media/video/au0828/Kconfig b/linux/drivers/media/video/au0828/Kconfig index 20993ae17..551f9ba63 100644 --- a/linux/drivers/media/video/au0828/Kconfig +++ b/linux/drivers/media/video/au0828/Kconfig @@ -1,7 +1,7 @@ config VIDEO_AU0828 tristate "Auvitek AU0828 support" - depends on I2C && INPUT && DVB_CORE && USB + depends on I2C && INPUT && DVB_CORE && USB && VIDEO_V4L2 select I2C_ALGOBIT select VIDEO_TVEEPROM select DVB_AU8522 if !DVB_FE_CUSTOMISE -- cgit v1.2.3 From d1f8343e844fdb906b58a31d33e5d69c8e7853ad Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 19 Mar 2009 21:41:08 -0300 Subject: dvb_dummy_fe: Fix compilation breakage From: Mauro Carvalho Chehab As reported by Randy Dunlap : ERROR: "dvb_dummy_fe_ofdm_attach" [drivers/media/video/cx231xx/cx231xx-dvb.ko] undefined! This happens since cx231xx DVB part still misses the frontend modules. So, the dummy frontend were used for development. The proper fix is to implement the DVB modules there, as they will be required. While this won't happen, lets allow the compilation with or without the dummy FE testing module. Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/frontends/dvb_dummy_fe.h | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/frontends/dvb_dummy_fe.h b/linux/drivers/media/dvb/frontends/dvb_dummy_fe.h index 8210f19d5..1fcb987d6 100644 --- a/linux/drivers/media/dvb/frontends/dvb_dummy_fe.h +++ b/linux/drivers/media/dvb/frontends/dvb_dummy_fe.h @@ -25,8 +25,27 @@ #include #include "dvb_frontend.h" +#if defined(CONFIG_DVB_DUMMY_FE) || (defined(CONFIG_DVB_DUMMY_FE_MODULE) && \ +defined(MODULE)) extern struct dvb_frontend* dvb_dummy_fe_ofdm_attach(void); extern struct dvb_frontend* dvb_dummy_fe_qpsk_attach(void); extern struct dvb_frontend* dvb_dummy_fe_qam_attach(void); +#else +static inline struct dvb_frontend *dvb_dummy_fe_ofdm_attach(void) +{ + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); + return NULL; +} +static inline struct dvb_frontend *dvb_dummy_fe_qpsk_attach(void) +{ + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); + return NULL; +} +static inline struct dvb_frontend *dvb_dummy_fe_qam_attach(void) +{ + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); + return NULL; +} +#endif /* CONFIG_DVB_DUMMY_FE */ #endif // DVB_DUMMY_FE_H -- cgit v1.2.3 From 76942dc03d982eb126ab1f62f4832b797c1119ca Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 13 Mar 2009 00:43:34 +0000 Subject: Add support for ProVideo PV-183 to bttv From: Alan McIvor Add support for ProVideo PV-183 to bttv This patch adds support for the ProVideo PV-183 card to the bttv device driver. The PV-183 is a PCI card with 8 BT878 devices plus a Hint Corp HiNT HB4 PCI-PCI Bridge. Each BT878 has two composite input channels available. There are no tuners on this card. Priority: normal Signed-off-by: Alan McIvor Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/bt8xx/bttv-cards.c | 24 ++++++++++++++++++++++++ linux/drivers/media/video/bt8xx/bttv.h | 1 + 2 files changed, 25 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/bt8xx/bttv-cards.c b/linux/drivers/media/video/bt8xx/bttv-cards.c index 40dac4b95..d2136141e 100644 --- a/linux/drivers/media/video/bt8xx/bttv-cards.c +++ b/linux/drivers/media/video/bt8xx/bttv-cards.c @@ -321,6 +321,16 @@ static struct CARD { { 0x763d800b, BTTV_BOARD_GEOVISION_GV800S_SL, "GeoVision GV-800(S) (slave)" }, { 0x763d800c, BTTV_BOARD_GEOVISION_GV800S_SL, "GeoVision GV-800(S) (slave)" }, { 0x763d800d, BTTV_BOARD_GEOVISION_GV800S_SL, "GeoVision GV-800(S) (slave)" }, + + { 0x15401830, BTTV_BOARD_PV183, "Provideo PV183-1" }, + { 0x15401831, BTTV_BOARD_PV183, "Provideo PV183-2" }, + { 0x15401832, BTTV_BOARD_PV183, "Provideo PV183-3" }, + { 0x15401833, BTTV_BOARD_PV183, "Provideo PV183-4" }, + { 0x15401834, BTTV_BOARD_PV183, "Provideo PV183-5" }, + { 0x15401835, BTTV_BOARD_PV183, "Provideo PV183-6" }, + { 0x15401836, BTTV_BOARD_PV183, "Provideo PV183-7" }, + { 0x15401837, BTTV_BOARD_PV183, "Provideo PV183-8" }, + { 0, -1, NULL } }; @@ -2910,6 +2920,20 @@ struct tvcard bttv_tvcards[] = { .no_tda9875 = 1, .muxsel_hook = gv800s_muxsel, }, + [BTTV_BOARD_PV183] = { + .name = "ProVideo PV183", /* 0x9f */ + .video_inputs = 2, + /* .audio_inputs= 0, */ + .svhs = NO_SVHS, + .gpiomask = 0, + .muxsel = MUXSEL(2, 3), + .gpiomux = { 0 }, + .needs_tvaudio = 0, + .no_msp34xx = 1, + .pll = PLL_28, + .tuner_type = TUNER_ABSENT, + .tuner_addr = ADDR_UNSET, + }, }; static const unsigned int bttv_num_tvcards = ARRAY_SIZE(bttv_tvcards); diff --git a/linux/drivers/media/video/bt8xx/bttv.h b/linux/drivers/media/video/bt8xx/bttv.h index da7690fa8..947f6e51a 100644 --- a/linux/drivers/media/video/bt8xx/bttv.h +++ b/linux/drivers/media/video/bt8xx/bttv.h @@ -185,6 +185,7 @@ #define BTTV_BOARD_IVCE8784 0x9c #define BTTV_BOARD_GEOVISION_GV800S 0x9d #define BTTV_BOARD_GEOVISION_GV800S_SL 0x9e +#define BTTV_BOARD_PV183 0x9f /* more card-specific defines */ -- cgit v1.2.3 From ada365c021ff668eae8fa17042a39d33a4cdf4e1 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Fri, 13 Mar 2009 10:08:20 +0100 Subject: soc-camera: separate S_FMT and S_CROP operations From: Guennadi Liakhovetski As host and camera drivers become more complex, differences between S_FMT and S_CROP functionality grow, this patch separates them. Signed-off-by: Guennadi Liakhovetski --- drivers/media/video/mt9m001.c | 19 +++- drivers/media/video/mt9m111.c | 56 +++++++--- drivers/media/video/mt9t031.c | 84 ++++++++++------ drivers/media/video/mt9v022.c | 62 +++++++---- drivers/media/video/mx3_camera.c | 157 +++++++++++++++++----------- drivers/media/video/ov772x.c | 31 +++++- drivers/media/video/pxa_camera.c | 67 +++++++++--- drivers/media/video/sh_mobile_ceu_camera.c | 17 ++- drivers/media/video/soc_camera.c | 20 ++-- drivers/media/video/soc_camera_platform.c | 9 ++- drivers/media/video/tw9910.c | 45 +++++--- include/media/soc_camera.h | 6 +- 12 files changed, 381 insertions(+), 192 deletions(-) --- linux/drivers/media/video/mt9m001.c | 19 ++- linux/drivers/media/video/mt9m111.c | 56 +++++--- linux/drivers/media/video/mt9t031.c | 84 +++++++----- linux/drivers/media/video/mt9v022.c | 62 +++++---- linux/drivers/media/video/mx3_camera.c | 157 ++++++++++++++--------- linux/drivers/media/video/ov772x.c | 31 ++++- linux/drivers/media/video/pxa_camera.c | 67 +++++++--- linux/drivers/media/video/sh_mobile_ceu_camera.c | 17 ++- linux/drivers/media/video/soc_camera.c | 20 ++- linux/drivers/media/video/soc_camera_platform.c | 9 +- linux/drivers/media/video/tw9910.c | 45 ++++--- 11 files changed, 377 insertions(+), 190 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/mt9m001.c b/linux/drivers/media/video/mt9m001.c index c2e52100a..079be8a1b 100644 --- a/linux/drivers/media/video/mt9m001.c +++ b/linux/drivers/media/video/mt9m001.c @@ -284,8 +284,8 @@ static unsigned long mt9m001_query_bus_param(struct soc_camera_device *icd) return soc_camera_apply_sensor_flags(icl, flags); } -static int mt9m001_set_fmt(struct soc_camera_device *icd, - __u32 pixfmt, struct v4l2_rect *rect) +static int mt9m001_set_crop(struct soc_camera_device *icd, + struct v4l2_rect *rect) { struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd); int ret; @@ -324,6 +324,20 @@ static int mt9m001_set_fmt(struct soc_camera_device *icd, return ret; } +static int mt9m001_set_fmt(struct soc_camera_device *icd, + struct v4l2_format *f) +{ + struct v4l2_rect rect = { + .left = icd->x_current, + .top = icd->y_current, + .width = f->fmt.pix.width, + .height = f->fmt.pix.height, + }; + + /* No support for scaling so far, just crop. TODO: use skipping */ + return mt9m001_set_crop(icd, &rect); +} + static int mt9m001_try_fmt(struct soc_camera_device *icd, struct v4l2_format *f) { @@ -449,6 +463,7 @@ static struct soc_camera_ops mt9m001_ops = { .release = mt9m001_release, .start_capture = mt9m001_start_capture, .stop_capture = mt9m001_stop_capture, + .set_crop = mt9m001_set_crop, .set_fmt = mt9m001_set_fmt, .try_fmt = mt9m001_try_fmt, .set_bus_param = mt9m001_set_bus_param, diff --git a/linux/drivers/media/video/mt9m111.c b/linux/drivers/media/video/mt9m111.c index 3ae675a42..69498d519 100644 --- a/linux/drivers/media/video/mt9m111.c +++ b/linux/drivers/media/video/mt9m111.c @@ -152,7 +152,7 @@ struct mt9m111 { struct soc_camera_device icd; int model; /* V4L2_IDENT_MT9M11x* codes from v4l2-chip-ident.h */ enum mt9m111_context context; - unsigned int left, top, width, height; + struct v4l2_rect rect; u32 pixfmt; unsigned char autoexposure; unsigned char datawidth; @@ -249,12 +249,13 @@ static int mt9m111_set_context(struct soc_camera_device *icd, return reg_write(CONTEXT_CONTROL, valA); } -static int mt9m111_setup_rect(struct soc_camera_device *icd) +static int mt9m111_setup_rect(struct soc_camera_device *icd, + struct v4l2_rect *rect) { struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); int ret, is_raw_format; - int width = mt9m111->width; - int height = mt9m111->height; + int width = rect->width; + int height = rect->height; if ((mt9m111->pixfmt == V4L2_PIX_FMT_SBGGR8) || (mt9m111->pixfmt == V4L2_PIX_FMT_SBGGR16)) @@ -262,9 +263,9 @@ static int mt9m111_setup_rect(struct soc_camera_device *icd) else is_raw_format = 0; - ret = reg_write(COLUMN_START, mt9m111->left); + ret = reg_write(COLUMN_START, rect->left); if (!ret) - ret = reg_write(ROW_START, mt9m111->top); + ret = reg_write(ROW_START, rect->top); if (is_raw_format) { if (!ret) @@ -436,6 +437,22 @@ static int mt9m111_set_bus_param(struct soc_camera_device *icd, unsigned long f) return 0; } +static int mt9m111_set_crop(struct soc_camera_device *icd, + struct v4l2_rect *rect) +{ + struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); + int ret; + + dev_dbg(&icd->dev, "%s left=%d, top=%d, width=%d, height=%d\n", + __func__, rect->left, rect->top, rect->width, + rect->height); + + ret = mt9m111_setup_rect(icd, rect); + if (!ret) + mt9m111->rect = *rect; + return ret; +} + static int mt9m111_set_pixfmt(struct soc_camera_device *icd, u32 pixfmt) { struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); @@ -486,23 +503,27 @@ static int mt9m111_set_pixfmt(struct soc_camera_device *icd, u32 pixfmt) } static int mt9m111_set_fmt(struct soc_camera_device *icd, - __u32 pixfmt, struct v4l2_rect *rect) + struct v4l2_format *f) { struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); + struct v4l2_pix_format *pix = &f->fmt.pix; + struct v4l2_rect rect = { + .left = mt9m111->rect.left, + .top = mt9m111->rect.top, + .width = pix->width, + .height = pix->height, + }; int ret; - mt9m111->left = rect->left; - mt9m111->top = rect->top; - mt9m111->width = rect->width; - mt9m111->height = rect->height; - dev_dbg(&icd->dev, "%s fmt=%x left=%d, top=%d, width=%d, height=%d\n", - __func__, pixfmt, mt9m111->left, mt9m111->top, mt9m111->width, - mt9m111->height); + __func__, pix->pixelformat, rect.left, rect.top, rect.width, + rect.height); - ret = mt9m111_setup_rect(icd); + ret = mt9m111_setup_rect(icd, &rect); + if (!ret) + ret = mt9m111_set_pixfmt(icd, pix->pixelformat); if (!ret) - ret = mt9m111_set_pixfmt(icd, pixfmt); + mt9m111->rect = rect; return ret; } @@ -633,6 +654,7 @@ static struct soc_camera_ops mt9m111_ops = { .release = mt9m111_release, .start_capture = mt9m111_start_capture, .stop_capture = mt9m111_stop_capture, + .set_crop = mt9m111_set_crop, .set_fmt = mt9m111_set_fmt, .try_fmt = mt9m111_try_fmt, .query_bus_param = mt9m111_query_bus_param, @@ -817,7 +839,7 @@ static int mt9m111_restore_state(struct soc_camera_device *icd) mt9m111_set_context(icd, mt9m111->context); mt9m111_set_pixfmt(icd, mt9m111->pixfmt); - mt9m111_setup_rect(icd); + mt9m111_setup_rect(icd, &mt9m111->rect); mt9m111_set_flip(icd, mt9m111->hflip, MT9M111_RMB_MIRROR_COLS); mt9m111_set_flip(icd, mt9m111->vflip, MT9M111_RMB_MIRROR_ROWS); mt9m111_set_global_gain(icd, icd->gain); diff --git a/linux/drivers/media/video/mt9t031.c b/linux/drivers/media/video/mt9t031.c index aa0e8ec34..34b8f5cee 100644 --- a/linux/drivers/media/video/mt9t031.c +++ b/linux/drivers/media/video/mt9t031.c @@ -213,36 +213,14 @@ static void recalculate_limits(struct soc_camera_device *icd, icd->height_max = MT9T031_MAX_HEIGHT / yskip; } -static int mt9t031_set_fmt(struct soc_camera_device *icd, - __u32 pixfmt, struct v4l2_rect *rect) +static int mt9t031_set_params(struct soc_camera_device *icd, + struct v4l2_rect *rect, u16 xskip, u16 yskip) { struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd); int ret; + u16 xbin, ybin, width, height, left, top; const u16 hblank = MT9T031_HORIZONTAL_BLANK, vblank = MT9T031_VERTICAL_BLANK; - u16 xbin, xskip, ybin, yskip, width, height, left, top; - - if (pixfmt) { - /* - * try_fmt has put rectangle within limits. - * S_FMT - use binning and skipping for scaling, recalculate - * limits, used for cropping - */ - /* Is this more optimal than just a division? */ - for (xskip = 8; xskip > 1; xskip--) - if (rect->width * xskip <= MT9T031_MAX_WIDTH) - break; - - for (yskip = 8; yskip > 1; yskip--) - if (rect->height * yskip <= MT9T031_MAX_HEIGHT) - break; - - recalculate_limits(icd, xskip, yskip); - } else { - /* CROP - no change in scaling, or in limits */ - xskip = mt9t031->xskip; - yskip = mt9t031->yskip; - } /* Make sure we don't exceed sensor limits */ if (rect->left + rect->width > icd->width_max) @@ -289,7 +267,7 @@ static int mt9t031_set_fmt(struct soc_camera_device *icd, if (ret >= 0) ret = reg_write(icd, MT9T031_VERTICAL_BLANKING, vblank); - if (pixfmt) { + if (yskip != mt9t031->yskip || xskip != mt9t031->xskip) { /* Binning, skipping */ if (ret >= 0) ret = reg_write(icd, MT9T031_COLUMN_ADDRESS_MODE, @@ -325,15 +303,58 @@ static int mt9t031_set_fmt(struct soc_camera_device *icd, } } - if (!ret && pixfmt) { + /* Re-enable register update, commit all changes */ + if (ret >= 0) + ret = reg_clear(icd, MT9T031_OUTPUT_CONTROL, 1); + + return ret < 0 ? ret : 0; +} + +static int mt9t031_set_crop(struct soc_camera_device *icd, + struct v4l2_rect *rect) +{ + struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd); + + /* CROP - no change in scaling, or in limits */ + return mt9t031_set_params(icd, rect, mt9t031->xskip, mt9t031->yskip); +} + +static int mt9t031_set_fmt(struct soc_camera_device *icd, + struct v4l2_format *f) +{ + struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd); + int ret; + u16 xskip, yskip; + struct v4l2_rect rect = { + .left = icd->x_current, + .top = icd->y_current, + .width = f->fmt.pix.width, + .height = f->fmt.pix.height, + }; + + /* + * try_fmt has put rectangle within limits. + * S_FMT - use binning and skipping for scaling, recalculate + * limits, used for cropping + */ + /* Is this more optimal than just a division? */ + for (xskip = 8; xskip > 1; xskip--) + if (rect.width * xskip <= MT9T031_MAX_WIDTH) + break; + + for (yskip = 8; yskip > 1; yskip--) + if (rect.height * yskip <= MT9T031_MAX_HEIGHT) + break; + + recalculate_limits(icd, xskip, yskip); + + ret = mt9t031_set_params(icd, &rect, xskip, yskip); + if (!ret) { mt9t031->xskip = xskip; mt9t031->yskip = yskip; } - /* Re-enable register update, commit all changes */ - reg_clear(icd, MT9T031_OUTPUT_CONTROL, 1); - - return ret < 0 ? ret : 0; + return ret; } static int mt9t031_try_fmt(struct soc_camera_device *icd, @@ -470,6 +491,7 @@ static struct soc_camera_ops mt9t031_ops = { .release = mt9t031_release, .start_capture = mt9t031_start_capture, .stop_capture = mt9t031_stop_capture, + .set_crop = mt9t031_set_crop, .set_fmt = mt9t031_set_fmt, .try_fmt = mt9t031_try_fmt, .set_bus_param = mt9t031_set_bus_param, diff --git a/linux/drivers/media/video/mt9v022.c b/linux/drivers/media/video/mt9v022.c index 59efb8ff0..09d3679e5 100644 --- a/linux/drivers/media/video/mt9v022.c +++ b/linux/drivers/media/video/mt9v022.c @@ -340,32 +340,11 @@ static unsigned long mt9v022_query_bus_param(struct soc_camera_device *icd) width_flag; } -static int mt9v022_set_fmt(struct soc_camera_device *icd, - __u32 pixfmt, struct v4l2_rect *rect) +static int mt9v022_set_crop(struct soc_camera_device *icd, + struct v4l2_rect *rect) { - struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd); int ret; - /* The caller provides a supported format, as verified per call to - * icd->try_fmt(), datawidth is from our supported format list */ - switch (pixfmt) { - case V4L2_PIX_FMT_GREY: - case V4L2_PIX_FMT_Y16: - if (mt9v022->model != V4L2_IDENT_MT9V022IX7ATM) - return -EINVAL; - break; - case V4L2_PIX_FMT_SBGGR8: - case V4L2_PIX_FMT_SBGGR16: - if (mt9v022->model != V4L2_IDENT_MT9V022IX7ATC) - return -EINVAL; - break; - case 0: - /* No format change, only geometry */ - break; - default: - return -EINVAL; - } - /* Like in example app. Contradicts the datasheet though */ ret = reg_read(icd, MT9V022_AEC_AGC_ENABLE); if (ret >= 0) { @@ -403,6 +382,42 @@ static int mt9v022_set_fmt(struct soc_camera_device *icd, return 0; } +static int mt9v022_set_fmt(struct soc_camera_device *icd, + struct v4l2_format *f) +{ + struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd); + struct v4l2_pix_format *pix = &f->fmt.pix; + struct v4l2_rect rect = { + .left = icd->x_current, + .top = icd->y_current, + .width = pix->width, + .height = pix->height, + }; + + /* The caller provides a supported format, as verified per call to + * icd->try_fmt(), datawidth is from our supported format list */ + switch (pix->pixelformat) { + case V4L2_PIX_FMT_GREY: + case V4L2_PIX_FMT_Y16: + if (mt9v022->model != V4L2_IDENT_MT9V022IX7ATM) + return -EINVAL; + break; + case V4L2_PIX_FMT_SBGGR8: + case V4L2_PIX_FMT_SBGGR16: + if (mt9v022->model != V4L2_IDENT_MT9V022IX7ATC) + return -EINVAL; + break; + case 0: + /* No format change, only geometry */ + break; + default: + return -EINVAL; + } + + /* No support for scaling on this camera, just crop. */ + return mt9v022_set_crop(icd, &rect); +} + static int mt9v022_try_fmt(struct soc_camera_device *icd, struct v4l2_format *f) { @@ -544,6 +559,7 @@ static struct soc_camera_ops mt9v022_ops = { .release = mt9v022_release, .start_capture = mt9v022_start_capture, .stop_capture = mt9v022_stop_capture, + .set_crop = mt9v022_set_crop, .set_fmt = mt9v022_set_fmt, .try_fmt = mt9v022_try_fmt, .set_bus_param = mt9v022_set_bus_param, diff --git a/linux/drivers/media/video/mx3_camera.c b/linux/drivers/media/video/mx3_camera.c index f525dc48f..70629e172 100644 --- a/linux/drivers/media/video/mx3_camera.c +++ b/linux/drivers/media/video/mx3_camera.c @@ -544,16 +544,14 @@ static void mx3_camera_remove_device(struct soc_camera_device *icd) } static bool channel_change_requested(struct soc_camera_device *icd, - const struct soc_camera_format_xlate *xlate, - __u32 pixfmt, struct v4l2_rect *rect) + struct v4l2_rect *rect) { struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); struct mx3_camera_dev *mx3_cam = ici->priv; struct idmac_channel *ichan = mx3_cam->idmac_channel[0]; - /* So far only one configuration is supported */ - return pixfmt || (ichan && rect->width * rect->height > - icd->width * icd->height); + /* Do buffers have to be re-allocated or channel re-configured? */ + return ichan && rect->width * rect->height > icd->width * icd->height; } static int test_platform_param(struct mx3_camera_dev *mx3_cam, @@ -733,61 +731,10 @@ passthrough: return formats; } -static int mx3_camera_set_fmt(struct soc_camera_device *icd, - __u32 pixfmt, struct v4l2_rect *rect) +static void configure_geometry(struct mx3_camera_dev *mx3_cam, + struct v4l2_rect *rect) { - struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); - struct mx3_camera_dev *mx3_cam = ici->priv; - const struct soc_camera_format_xlate *xlate; u32 ctrl, width_field, height_field; - int ret; - - xlate = soc_camera_xlate_by_fourcc(icd, pixfmt); - if (pixfmt && !xlate) { - dev_warn(&ici->dev, "Format %x not found\n", pixfmt); - return -EINVAL; - } - - /* - * We now know pixel formats and can decide upon DMA-channel(s) - * So far only direct camera-to-memory is supported - */ - if (channel_change_requested(icd, xlate, pixfmt, rect)) { - dma_cap_mask_t mask; - struct dma_chan *chan; - struct idmac_channel **ichan = &mx3_cam->idmac_channel[0]; - /* We have to use IDMAC_IC_7 for Bayer / generic data */ - struct dma_chan_request rq = {.mx3_cam = mx3_cam, - .id = IDMAC_IC_7}; - - if (*ichan) { - struct videobuf_buffer *vb, *_vb; - dma_release_channel(&(*ichan)->dma_chan); - *ichan = NULL; - mx3_cam->active = NULL; - list_for_each_entry_safe(vb, _vb, &mx3_cam->capture, queue) { - list_del_init(&vb->queue); - vb->state = VIDEOBUF_ERROR; - wake_up(&vb->done); - } - } - - dma_cap_zero(mask); - dma_cap_set(DMA_SLAVE, mask); - dma_cap_set(DMA_PRIVATE, mask); - chan = dma_request_channel(mask, chan_filter, &rq); - if (!chan) - return -EBUSY; - - *ichan = to_idmac_chan(chan); - (*ichan)->client = mx3_cam; - } - - /* - * Might have to perform a complete interface initialisation like in - * ipu_csi_init_interface() in mxc_v4l2_s_param(). Also consider - * mxc_v4l2_s_fmt() - */ /* Setup frame size - this cannot be changed on-the-fly... */ width_field = rect->width - 1; @@ -808,9 +755,98 @@ static int mx3_camera_set_fmt(struct soc_camera_device *icd, * No need to free resources here if we fail, we'll see if we need to * do this next time we are called */ +} + +static int acquire_dma_channel(struct mx3_camera_dev *mx3_cam) +{ + dma_cap_mask_t mask; + struct dma_chan *chan; + struct idmac_channel **ichan = &mx3_cam->idmac_channel[0]; + /* We have to use IDMAC_IC_7 for Bayer / generic data */ + struct dma_chan_request rq = {.mx3_cam = mx3_cam, + .id = IDMAC_IC_7}; + + if (*ichan) { + struct videobuf_buffer *vb, *_vb; + dma_release_channel(&(*ichan)->dma_chan); + *ichan = NULL; + mx3_cam->active = NULL; + list_for_each_entry_safe(vb, _vb, &mx3_cam->capture, queue) { + list_del_init(&vb->queue); + vb->state = VIDEOBUF_ERROR; + wake_up(&vb->done); + } + } + + dma_cap_zero(mask); + dma_cap_set(DMA_SLAVE, mask); + dma_cap_set(DMA_PRIVATE, mask); + chan = dma_request_channel(mask, chan_filter, &rq); + if (!chan) + return -EBUSY; + + *ichan = to_idmac_chan(chan); + (*ichan)->client = mx3_cam; + + return 0; +} + +static int mx3_camera_set_crop(struct soc_camera_device *icd, + struct v4l2_rect *rect) +{ + struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); + struct mx3_camera_dev *mx3_cam = ici->priv; + + /* + * We now know pixel formats and can decide upon DMA-channel(s) + * So far only direct camera-to-memory is supported + */ + if (channel_change_requested(icd, rect)) { + int ret = acquire_dma_channel(mx3_cam); + if (ret < 0) + return ret; + } + + configure_geometry(mx3_cam, rect); + + return icd->ops->set_crop(icd, rect); +} + +static int mx3_camera_set_fmt(struct soc_camera_device *icd, + struct v4l2_format *f) +{ + struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); + struct mx3_camera_dev *mx3_cam = ici->priv; + const struct soc_camera_format_xlate *xlate; + struct v4l2_pix_format *pix = &f->fmt.pix; + struct v4l2_rect rect = { + .left = icd->x_current, + .top = icd->y_current, + .width = pix->width, + .height = pix->height, + }; + int ret; + + xlate = soc_camera_xlate_by_fourcc(icd, pix->pixelformat); + if (!xlate) { + dev_warn(&ici->dev, "Format %x not found\n", pix->pixelformat); + return -EINVAL; + } + + ret = acquire_dma_channel(mx3_cam); + if (ret < 0) + return ret; + + /* + * Might have to perform a complete interface initialisation like in + * ipu_csi_init_interface() in mxc_v4l2_s_param(). Also consider + * mxc_v4l2_s_fmt() + */ + + configure_geometry(mx3_cam, &rect); - ret = icd->ops->set_fmt(icd, pixfmt ? xlate->cam_fmt->fourcc : 0, rect); - if (pixfmt && !ret) { + ret = icd->ops->set_fmt(icd, f); + if (!ret) { icd->buswidth = xlate->buswidth; icd->current_fmt = xlate->host_fmt; } @@ -1031,6 +1067,7 @@ static struct soc_camera_host_ops mx3_soc_camera_host_ops = { .suspend = mx3_camera_suspend, .resume = mx3_camera_resume, #endif + .set_crop = mx3_camera_set_crop, .set_fmt = mx3_camera_set_fmt, .try_fmt = mx3_camera_try_fmt, .get_formats = mx3_camera_get_formats, diff --git a/linux/drivers/media/video/ov772x.c b/linux/drivers/media/video/ov772x.c index 2f3313524..73d447247 100644 --- a/linux/drivers/media/video/ov772x.c +++ b/linux/drivers/media/video/ov772x.c @@ -781,11 +781,9 @@ ov772x_select_win(u32 width, u32 height) return win; } -static int ov772x_set_fmt(struct soc_camera_device *icd, - __u32 pixfmt, - struct v4l2_rect *rect) +static int ov772x_set_params(struct ov772x_priv *priv, u32 width, u32 height, + u32 pixfmt) { - struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd); int ret = -EINVAL; u8 val; int i; @@ -806,7 +804,7 @@ static int ov772x_set_fmt(struct soc_camera_device *icd, /* * select win */ - priv->win = ov772x_select_win(rect->width, rect->height); + priv->win = ov772x_select_win(width, height); /* * reset hardware @@ -870,6 +868,28 @@ ov772x_set_fmt_error: return ret; } +static int ov772x_set_crop(struct soc_camera_device *icd, + struct v4l2_rect *rect) +{ + struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd); + + if (!priv->fmt) + return -EINVAL; + + return ov772x_set_params(priv, rect->width, rect->height, + priv->fmt->fourcc); +} + +static int ov772x_set_fmt(struct soc_camera_device *icd, + struct v4l2_format *f) +{ + struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd); + struct v4l2_pix_format *pix = &f->fmt.pix; + + return ov772x_set_params(priv, pix->width, pix->height, + pix->pixelformat); +} + static int ov772x_try_fmt(struct soc_camera_device *icd, struct v4l2_format *f) { @@ -959,6 +979,7 @@ static struct soc_camera_ops ov772x_ops = { .release = ov772x_release, .start_capture = ov772x_start_capture, .stop_capture = ov772x_stop_capture, + .set_crop = ov772x_set_crop, .set_fmt = ov772x_set_fmt, .try_fmt = ov772x_try_fmt, .set_bus_param = ov772x_set_bus_param, diff --git a/linux/drivers/media/video/pxa_camera.c b/linux/drivers/media/video/pxa_camera.c index dd524b3c6..d1aa540ba 100644 --- a/linux/drivers/media/video/pxa_camera.c +++ b/linux/drivers/media/video/pxa_camera.c @@ -1160,8 +1160,43 @@ static int pxa_camera_get_formats(struct soc_camera_device *icd, int idx, return formats; } +static int pxa_camera_set_crop(struct soc_camera_device *icd, + struct v4l2_rect *rect) +{ + struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); + struct pxa_camera_dev *pcdev = ici->priv; + struct soc_camera_sense sense = { + .master_clock = pcdev->mclk, + .pixel_clock_max = pcdev->ciclk / 4, + }; + int ret; + + /* If PCLK is used to latch data from the sensor, check sense */ + if (pcdev->platform_flags & PXA_CAMERA_PCLK_EN) + icd->sense = &sense; + + ret = icd->ops->set_crop(icd, rect); + + icd->sense = NULL; + + if (ret < 0) { + dev_warn(&ici->dev, "Failed to crop to %ux%u@%u:%u\n", + rect->width, rect->height, rect->left, rect->top); + } else if (sense.flags & SOCAM_SENSE_PCLK_CHANGED) { + if (sense.pixel_clock > sense.pixel_clock_max) { + dev_err(&ici->dev, + "pixel clock %lu set by the camera too high!", + sense.pixel_clock); + return -EIO; + } + recalculate_fifo_timeout(pcdev, sense.pixel_clock); + } + + return ret; +} + static int pxa_camera_set_fmt(struct soc_camera_device *icd, - __u32 pixfmt, struct v4l2_rect *rect) + struct v4l2_format *f) { struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); struct pxa_camera_dev *pcdev = ici->priv; @@ -1171,35 +1206,30 @@ static int pxa_camera_set_fmt(struct soc_camera_device *icd, .master_clock = pcdev->mclk, .pixel_clock_max = pcdev->ciclk / 4, }; + struct v4l2_pix_format *pix = &f->fmt.pix; + struct v4l2_format cam_f = *f; int ret; - if (pixfmt) { - xlate = soc_camera_xlate_by_fourcc(icd, pixfmt); - if (!xlate) { - dev_warn(&ici->dev, "Format %x not found\n", pixfmt); - return -EINVAL; - } - - cam_fmt = xlate->cam_fmt; + xlate = soc_camera_xlate_by_fourcc(icd, pix->pixelformat); + if (!xlate) { + dev_warn(&ici->dev, "Format %x not found\n", pix->pixelformat); + return -EINVAL; } + cam_fmt = xlate->cam_fmt; + /* If PCLK is used to latch data from the sensor, check sense */ if (pcdev->platform_flags & PXA_CAMERA_PCLK_EN) icd->sense = &sense; - switch (pixfmt) { - case 0: /* Only geometry change */ - ret = icd->ops->set_fmt(icd, pixfmt, rect); - break; - default: - ret = icd->ops->set_fmt(icd, cam_fmt->fourcc, rect); - } + cam_f.fmt.pix.pixelformat = cam_fmt->fourcc; + ret = icd->ops->set_fmt(icd, &cam_f); icd->sense = NULL; if (ret < 0) { dev_warn(&ici->dev, "Failed to configure for format %x\n", - pixfmt); + pix->pixelformat); } else if (sense.flags & SOCAM_SENSE_PCLK_CHANGED) { if (sense.pixel_clock > sense.pixel_clock_max) { dev_err(&ici->dev, @@ -1210,7 +1240,7 @@ static int pxa_camera_set_fmt(struct soc_camera_device *icd, recalculate_fifo_timeout(pcdev, sense.pixel_clock); } - if (pixfmt && !ret) { + if (!ret) { icd->buswidth = xlate->buswidth; icd->current_fmt = xlate->host_fmt; } @@ -1374,6 +1404,7 @@ static struct soc_camera_host_ops pxa_soc_camera_host_ops = { .remove = pxa_camera_remove_device, .suspend = pxa_camera_suspend, .resume = pxa_camera_resume, + .set_crop = pxa_camera_set_crop, .get_formats = pxa_camera_get_formats, .set_fmt = pxa_camera_set_fmt, .try_fmt = pxa_camera_try_fmt, diff --git a/linux/drivers/media/video/sh_mobile_ceu_camera.c b/linux/drivers/media/video/sh_mobile_ceu_camera.c index 29ff02802..feaf257d6 100644 --- a/linux/drivers/media/video/sh_mobile_ceu_camera.c +++ b/linux/drivers/media/video/sh_mobile_ceu_camera.c @@ -639,24 +639,30 @@ add_single_format: return formats; } +static int sh_mobile_ceu_set_crop(struct soc_camera_device *icd, + struct v4l2_rect *rect) +{ + return icd->ops->set_crop(icd, rect); +} + static int sh_mobile_ceu_set_fmt(struct soc_camera_device *icd, - __u32 pixfmt, struct v4l2_rect *rect) + struct v4l2_format *f) { struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); struct sh_mobile_ceu_dev *pcdev = ici->priv; + __u32 pixfmt = f->fmt.pix.pixelformat; const struct soc_camera_format_xlate *xlate; + struct v4l2_format cam_f = *f; int ret; - if (!pixfmt) - return icd->ops->set_fmt(icd, pixfmt, rect); - xlate = soc_camera_xlate_by_fourcc(icd, pixfmt); if (!xlate) { dev_warn(&ici->dev, "Format %x not found\n", pixfmt); return -EINVAL; } - ret = icd->ops->set_fmt(icd, xlate->cam_fmt->fourcc, rect); + cam_f.fmt.pix.pixelformat = xlate->cam_fmt->fourcc; + ret = icd->ops->set_fmt(icd, &cam_f); if (!ret) { icd->buswidth = xlate->buswidth; @@ -788,6 +794,7 @@ static struct soc_camera_host_ops sh_mobile_ceu_host_ops = { .add = sh_mobile_ceu_add_device, .remove = sh_mobile_ceu_remove_device, .get_formats = sh_mobile_ceu_get_formats, + .set_crop = sh_mobile_ceu_set_crop, .set_fmt = sh_mobile_ceu_set_fmt, .try_fmt = sh_mobile_ceu_try_fmt, .reqbufs = sh_mobile_ceu_reqbufs, diff --git a/linux/drivers/media/video/soc_camera.c b/linux/drivers/media/video/soc_camera.c index 356b77e10..4c2a784fb 100644 --- a/linux/drivers/media/video/soc_camera.c +++ b/linux/drivers/media/video/soc_camera.c @@ -418,9 +418,7 @@ static int soc_camera_s_fmt_vid_cap(struct file *file, void *priv, struct soc_camera_device *icd = icf->icd; struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); struct v4l2_pix_format *pix = &f->fmt.pix; - __u32 pixfmt = pix->pixelformat; int ret; - struct v4l2_rect rect; WARN_ON(priv != file->private_data); @@ -436,23 +434,19 @@ static int soc_camera_s_fmt_vid_cap(struct file *file, void *priv, goto unlock; } - rect.left = icd->x_current; - rect.top = icd->y_current; - rect.width = pix->width; - rect.height = pix->height; - ret = ici->ops->set_fmt(icd, pix->pixelformat, &rect); + ret = ici->ops->set_fmt(icd, f); if (ret < 0) { goto unlock; } else if (!icd->current_fmt || - icd->current_fmt->fourcc != pixfmt) { + icd->current_fmt->fourcc != pix->pixelformat) { dev_err(&ici->dev, "Host driver hasn't set up current format correctly!\n"); ret = -EINVAL; goto unlock; } - icd->width = rect.width; - icd->height = rect.height; + icd->width = f->fmt.pix.width; + icd->height = f->fmt.pix.height; icf->vb_vidq.field = pix->field; if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) dev_warn(&icd->dev, "Attention! Wrong buf-type %d\n", @@ -462,7 +456,7 @@ static int soc_camera_s_fmt_vid_cap(struct file *file, void *priv, icd->width, icd->height); /* set physical bus parameters */ - ret = ici->ops->set_bus_param(icd, pixfmt); + ret = ici->ops->set_bus_param(icd, pix->pixelformat); unlock: mutex_unlock(&icf->vb_vidq.vb_lock); @@ -686,7 +680,7 @@ static int soc_camera_s_crop(struct file *file, void *fh, /* Cropping is allowed during a running capture, guard consistency */ mutex_lock(&icf->vb_vidq.vb_lock); - ret = ici->ops->set_fmt(icd, 0, &a->c); + ret = ici->ops->set_crop(icd, &a->c); if (!ret) { icd->width = a->c.width; icd->height = a->c.height; @@ -919,6 +913,7 @@ int soc_camera_host_register(struct soc_camera_host *ici) if (!ici || !ici->ops || !ici->ops->try_fmt || !ici->ops->set_fmt || + !ici->ops->set_crop || !ici->ops->set_bus_param || !ici->ops->querycap || !ici->ops->init_videobuf || @@ -999,6 +994,7 @@ int soc_camera_device_register(struct soc_camera_device *icd) !icd->ops->release || !icd->ops->start_capture || !icd->ops->stop_capture || + !icd->ops->set_crop || !icd->ops->set_fmt || !icd->ops->try_fmt || !icd->ops->query_bus_param || diff --git a/linux/drivers/media/video/soc_camera_platform.c b/linux/drivers/media/video/soc_camera_platform.c index 013ab06e3..c48676356 100644 --- a/linux/drivers/media/video/soc_camera_platform.c +++ b/linux/drivers/media/video/soc_camera_platform.c @@ -79,8 +79,14 @@ soc_camera_platform_query_bus_param(struct soc_camera_device *icd) return p->bus_param; } +static int soc_camera_platform_set_crop(struct soc_camera_device *icd, + struct v4l2_rect *rect) +{ + return 0; +} + static int soc_camera_platform_set_fmt(struct soc_camera_device *icd, - __u32 pixfmt, struct v4l2_rect *rect) + struct v4l2_format *f) { return 0; } @@ -125,6 +131,7 @@ static struct soc_camera_ops soc_camera_platform_ops = { .release = soc_camera_platform_release, .start_capture = soc_camera_platform_start_capture, .stop_capture = soc_camera_platform_stop_capture, + .set_crop = soc_camera_platform_set_crop, .set_fmt = soc_camera_platform_set_fmt, .try_fmt = soc_camera_platform_try_fmt, .set_bus_param = soc_camera_platform_set_bus_param, diff --git a/linux/drivers/media/video/tw9910.c b/linux/drivers/media/video/tw9910.c index ed8dca3bf..5c145085a 100644 --- a/linux/drivers/media/video/tw9910.c +++ b/linux/drivers/media/video/tw9910.c @@ -641,25 +641,12 @@ static int tw9910_set_register(struct soc_camera_device *icd, } #endif -static int tw9910_set_fmt(struct soc_camera_device *icd, __u32 pixfmt, - struct v4l2_rect *rect) +static int tw9910_set_crop(struct soc_camera_device *icd, + struct v4l2_rect *rect) { struct tw9910_priv *priv = container_of(icd, struct tw9910_priv, icd); int ret = -EINVAL; u8 val; - int i; - - /* - * check color format - */ - for (i = 0 ; i < ARRAY_SIZE(tw9910_color_fmt) ; i++) { - if (pixfmt == tw9910_color_fmt[i].fourcc) { - ret = 0; - break; - } - } - if (ret < 0) - goto tw9910_set_fmt_error; /* * select suitable norm @@ -746,8 +733,33 @@ tw9910_set_fmt_error: return ret; } +static int tw9910_set_fmt(struct soc_camera_device *icd, + struct v4l2_format *f) +{ + struct v4l2_pix_format *pix = &f->fmt.pix; + struct v4l2_rect rect = { + .left = icd->x_current, + .top = icd->y_current, + .width = pix->width, + .height = pix->height, + }; + int i; + + /* + * check color format + */ + for (i = 0; i < ARRAY_SIZE(tw9910_color_fmt); i++) + if (pix->pixelformat == tw9910_color_fmt[i].fourcc) + break; + + if (i == ARRAY_SIZE(tw9910_color_fmt)) + return -EINVAL; + + return tw9910_set_crop(icd, &rect); +} + static int tw9910_try_fmt(struct soc_camera_device *icd, - struct v4l2_format *f) + struct v4l2_format *f) { struct v4l2_pix_format *pix = &f->fmt.pix; const struct tw9910_scale_ctrl *scale; @@ -835,6 +847,7 @@ static struct soc_camera_ops tw9910_ops = { .release = tw9910_release, .start_capture = tw9910_start_capture, .stop_capture = tw9910_stop_capture, + .set_crop = tw9910_set_crop, .set_fmt = tw9910_set_fmt, .try_fmt = tw9910_try_fmt, .set_bus_param = tw9910_set_bus_param, -- cgit v1.2.3 From 7bc0a7a6ccbab2bff6c1ed73297765e4855db4be Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Fri, 13 Mar 2009 10:08:20 +0100 Subject: soc-camera: configure drivers with a default format on open From: Guennadi Liakhovetski Currently soc-camera doesn't set up any image format without an explicit S_FMT. It seems this should be supported, since, for example, capture-example.c from v4l2-apps by default doesn't issue an S_FMT. This patch configures a default image format on open(). Signed-off-by: Guennadi Liakhovetski --- drivers/media/video/soc_camera.c | 100 ++++++++++++++++++++++++++------------ 1 files changed, 68 insertions(+), 32 deletions(-) --- linux/drivers/media/video/soc_camera.c | 100 ++++++++++++++++++++++----------- 1 file changed, 68 insertions(+), 32 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/soc_camera.c b/linux/drivers/media/video/soc_camera.c index 4c2a784fb..10d8ecad1 100644 --- a/linux/drivers/media/video/soc_camera.c +++ b/linux/drivers/media/video/soc_camera.c @@ -31,6 +31,10 @@ #include #include "compat.h" +/* Default to VGA resolution */ +#define DEFAULT_WIDTH 640 +#define DEFAULT_HEIGHT 480 + static LIST_HEAD(hosts); static LIST_HEAD(devices); static DEFINE_MUTEX(list_lock); @@ -257,6 +261,44 @@ static void soc_camera_free_user_formats(struct soc_camera_device *icd) vfree(icd->user_formats); } +/* Called with .vb_lock held */ +static int soc_camera_set_fmt(struct soc_camera_file *icf, + struct v4l2_format *f) +{ + struct soc_camera_device *icd = icf->icd; + struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); + struct v4l2_pix_format *pix = &f->fmt.pix; + int ret; + + /* We always call try_fmt() before set_fmt() or set_crop() */ + ret = ici->ops->try_fmt(icd, f); + if (ret < 0) + return ret; + + ret = ici->ops->set_fmt(icd, f); + if (ret < 0) { + return ret; + } else if (!icd->current_fmt || + icd->current_fmt->fourcc != pix->pixelformat) { + dev_err(&ici->dev, + "Host driver hasn't set up current format correctly!\n"); + return -EINVAL; + } + + icd->width = pix->width; + icd->height = pix->height; + icf->vb_vidq.field = pix->field; + if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + dev_warn(&icd->dev, "Attention! Wrong buf-type %d\n", + f->type); + + dev_dbg(&icd->dev, "set width: %d height: %d\n", + icd->width, icd->height); + + /* set physical bus parameters */ + return ici->ops->set_bus_param(icd, pix->pixelformat); +} + static int soc_camera_open(struct file *file) { struct video_device *vdev; @@ -298,6 +340,15 @@ static int soc_camera_open(struct file *file) /* Now we really have to activate the camera */ if (icd->use_count == 1) { + struct v4l2_format f = { + .type = V4L2_BUF_TYPE_VIDEO_CAPTURE, + .fmt.pix = { + .width = DEFAULT_WIDTH, + .height = DEFAULT_HEIGHT, + .field = V4L2_FIELD_ANY, + }, + }; + ret = soc_camera_init_user_formats(icd); if (ret < 0) goto eiufmt; @@ -306,6 +357,14 @@ static int soc_camera_open(struct file *file) dev_err(&icd->dev, "Couldn't activate the camera: %d\n", ret); goto eiciadd; } + + f.fmt.pix.pixelformat = icd->current_fmt->fourcc; + f.fmt.pix.colorspace = icd->current_fmt->colorspace; + + /* Try to configure with default parameters */ + ret = soc_camera_set_fmt(icf, &f); + if (ret < 0) + goto esfmt; } mutex_unlock(&icd->video_lock); @@ -317,7 +376,12 @@ static int soc_camera_open(struct file *file) return 0; - /* First two errors are entered with the .video_lock held */ + /* + * First three errors are entered with the .video_lock held + * and use_count == 1 + */ +esfmt: + ici->ops->remove(icd); eiciadd: soc_camera_free_user_formats(icd); eiufmt: @@ -416,16 +480,10 @@ static int soc_camera_s_fmt_vid_cap(struct file *file, void *priv, { struct soc_camera_file *icf = file->private_data; struct soc_camera_device *icd = icf->icd; - struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); - struct v4l2_pix_format *pix = &f->fmt.pix; int ret; WARN_ON(priv != file->private_data); - ret = soc_camera_try_fmt_vid_cap(file, priv, f); - if (ret < 0) - return ret; - mutex_lock(&icf->vb_vidq.vb_lock); if (videobuf_queue_is_busy(&icf->vb_vidq)) { @@ -434,29 +492,7 @@ static int soc_camera_s_fmt_vid_cap(struct file *file, void *priv, goto unlock; } - ret = ici->ops->set_fmt(icd, f); - if (ret < 0) { - goto unlock; - } else if (!icd->current_fmt || - icd->current_fmt->fourcc != pix->pixelformat) { - dev_err(&ici->dev, - "Host driver hasn't set up current format correctly!\n"); - ret = -EINVAL; - goto unlock; - } - - icd->width = f->fmt.pix.width; - icd->height = f->fmt.pix.height; - icf->vb_vidq.field = pix->field; - if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - dev_warn(&icd->dev, "Attention! Wrong buf-type %d\n", - f->type); - - dev_dbg(&icd->dev, "set width: %d height: %d\n", - icd->width, icd->height); - - /* set physical bus parameters */ - ret = ici->ops->set_bus_param(icd, pix->pixelformat); + ret = soc_camera_set_fmt(icf, f); unlock: mutex_unlock(&icf->vb_vidq.vb_lock); @@ -643,8 +679,8 @@ static int soc_camera_cropcap(struct file *file, void *fh, a->bounds.height = icd->height_max; a->defrect.left = icd->x_min; a->defrect.top = icd->y_min; - a->defrect.width = 640; - a->defrect.height = 480; + a->defrect.width = DEFAULT_WIDTH; + a->defrect.height = DEFAULT_HEIGHT; a->pixelaspect.numerator = 1; a->pixelaspect.denominator = 1; -- cgit v1.2.3 From edd96a81211ebded1ed720e24e5f81ffec94c455 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Fri, 13 Mar 2009 10:08:20 +0100 Subject: sh-mobile-ceu-camera: set field to the value, configured at open() From: Guennadi Liakhovetski For the case, that we have to capture with a default format, i.e., when the user doesn't call S_FMT, we have to use the field value according to the default, configured at open() time. Signed-off-by: Guennadi Liakhovetski --- drivers/media/video/sh_mobile_ceu_camera.c | 17 +++++++++-------- 1 files changed, 9 insertions(+), 8 deletions(-) --- linux/drivers/media/video/sh_mobile_ceu_camera.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/sh_mobile_ceu_camera.c b/linux/drivers/media/video/sh_mobile_ceu_camera.c index feaf257d6..1a4026a95 100644 --- a/linux/drivers/media/video/sh_mobile_ceu_camera.c +++ b/linux/drivers/media/video/sh_mobile_ceu_camera.c @@ -95,7 +95,7 @@ struct sh_mobile_ceu_dev { spinlock_t lock; struct list_head capture; struct videobuf_buffer *active; - int is_interlace; + int is_interlaced; struct sh_mobile_ceu_info *pdata; @@ -206,7 +206,7 @@ static void sh_mobile_ceu_capture(struct sh_mobile_ceu_dev *pcdev) phys_addr_top = videobuf_to_dma_contig(pcdev->active); ceu_write(pcdev, CDAYR, phys_addr_top); - if (pcdev->is_interlace) { + if (pcdev->is_interlaced) { phys_addr_bottom = phys_addr_top + icd->width; ceu_write(pcdev, CDBYR, phys_addr_bottom); } @@ -218,7 +218,7 @@ static void sh_mobile_ceu_capture(struct sh_mobile_ceu_dev *pcdev) case V4L2_PIX_FMT_NV61: phys_addr_top += icd->width * icd->height; ceu_write(pcdev, CDACR, phys_addr_top); - if (pcdev->is_interlace) { + if (pcdev->is_interlaced) { phys_addr_bottom = phys_addr_top + icd->width; ceu_write(pcdev, CDBCR, phys_addr_bottom); } @@ -482,7 +482,7 @@ static int sh_mobile_ceu_set_bus_param(struct soc_camera_device *icd, ceu_write(pcdev, CAMCR, value); ceu_write(pcdev, CAPCR, 0x00300000); - ceu_write(pcdev, CAIFR, (pcdev->is_interlace) ? 0x101 : 0); + ceu_write(pcdev, CAIFR, pcdev->is_interlaced ? 0x101 : 0); mdelay(1); @@ -498,7 +498,7 @@ static int sh_mobile_ceu_set_bus_param(struct soc_camera_device *icd, } height = icd->height; - if (pcdev->is_interlace) { + if (pcdev->is_interlaced) { height /= 2; cdwdr_width *= 2; } @@ -712,13 +712,13 @@ static int sh_mobile_ceu_try_fmt(struct soc_camera_device *icd, switch (f->fmt.pix.field) { case V4L2_FIELD_INTERLACED: - pcdev->is_interlace = 1; + pcdev->is_interlaced = 1; break; case V4L2_FIELD_ANY: f->fmt.pix.field = V4L2_FIELD_NONE; /* fall-through */ case V4L2_FIELD_NONE: - pcdev->is_interlace = 0; + pcdev->is_interlaced = 0; break; default: ret = -EINVAL; @@ -784,7 +784,8 @@ static void sh_mobile_ceu_init_videobuf(struct videobuf_queue *q, &sh_mobile_ceu_videobuf_ops, &ici->dev, &pcdev->lock, V4L2_BUF_TYPE_VIDEO_CAPTURE, - V4L2_FIELD_ANY, + pcdev->is_interlaced ? + V4L2_FIELD_INTERLACED : V4L2_FIELD_NONE, sizeof(struct sh_mobile_ceu_buffer), icd); } -- cgit v1.2.3 From a00a0b74b7fe24e815f70f49ac8b8cc073cdad80 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Fri, 13 Mar 2009 10:08:20 +0100 Subject: soc-camera: configure drivers with a default format at probe time From: Guennadi Liakhovetski Currently soc-camera doesn't set up any image format without an explicit S_FMT. According to the API this should be supported, for example, capture-example.c from v4l2-apps by default doesn't issue an S_FMT. This patch moves negotiating of available host-camera format translations to probe() time, and restores the state from the last close() on the next open(). This is needed for some drivers, which power down or reset hardware after the last user closes the interface. This patch also has a nice side-effect of avoiding multiple allocation anf freeing of format translation tables. Signed-off-by: Guennadi Liakhovetski --- drivers/media/video/soc_camera.c | 39 ++++++++++++++++++++++--------------- include/media/soc_camera.h | 1 + 2 files changed, 24 insertions(+), 16 deletions(-) --- linux/drivers/media/video/soc_camera.c | 39 ++++++++++++++++++++-------------- 1 file changed, 23 insertions(+), 16 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/soc_camera.c b/linux/drivers/media/video/soc_camera.c index 10d8ecad1..da6d224eb 100644 --- a/linux/drivers/media/video/soc_camera.c +++ b/linux/drivers/media/video/soc_camera.c @@ -287,7 +287,9 @@ static int soc_camera_set_fmt(struct soc_camera_file *icf, icd->width = pix->width; icd->height = pix->height; - icf->vb_vidq.field = pix->field; + icf->vb_vidq.field = + icd->field = pix->field; + if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) dev_warn(&icd->dev, "Attention! Wrong buf-type %d\n", f->type); @@ -340,27 +342,24 @@ static int soc_camera_open(struct file *file) /* Now we really have to activate the camera */ if (icd->use_count == 1) { + /* Restore parameters before the last close() per V4L2 API */ struct v4l2_format f = { .type = V4L2_BUF_TYPE_VIDEO_CAPTURE, .fmt.pix = { - .width = DEFAULT_WIDTH, - .height = DEFAULT_HEIGHT, - .field = V4L2_FIELD_ANY, + .width = icd->width, + .height = icd->height, + .field = icd->field, + .pixelformat = icd->current_fmt->fourcc, + .colorspace = icd->current_fmt->colorspace, }, }; - ret = soc_camera_init_user_formats(icd); - if (ret < 0) - goto eiufmt; ret = ici->ops->add(icd); if (ret < 0) { dev_err(&icd->dev, "Couldn't activate the camera: %d\n", ret); goto eiciadd; } - f.fmt.pix.pixelformat = icd->current_fmt->fourcc; - f.fmt.pix.colorspace = icd->current_fmt->colorspace; - /* Try to configure with default parameters */ ret = soc_camera_set_fmt(icf, &f); if (ret < 0) @@ -383,8 +382,6 @@ static int soc_camera_open(struct file *file) esfmt: ici->ops->remove(icd); eiciadd: - soc_camera_free_user_formats(icd); -eiufmt: icd->use_count--; mutex_unlock(&icd->video_lock); module_put(ici->ops->owner); @@ -404,10 +401,9 @@ static int soc_camera_close(struct file *file) mutex_lock(&icd->video_lock); icd->use_count--; - if (!icd->use_count) { + if (!icd->use_count) ici->ops->remove(icd); - soc_camera_free_user_formats(icd); - } + mutex_unlock(&icd->video_lock); module_put(icd->ops->owner); @@ -875,9 +871,18 @@ static int soc_camera_probe(struct device *dev) qctrl = soc_camera_find_qctrl(icd->ops, V4L2_CID_EXPOSURE); icd->exposure = qctrl ? qctrl->default_value : (unsigned short)~0; + + ret = soc_camera_init_user_formats(icd); + if (ret < 0) + goto eiufmt; + + icd->height = DEFAULT_HEIGHT; + icd->width = DEFAULT_WIDTH; + icd->field = V4L2_FIELD_ANY; } - ici->ops->remove(icd); +eiufmt: + ici->ops->remove(icd); eiadd: mutex_unlock(&icd->video_lock); module_put(ici->ops->owner); @@ -896,6 +901,8 @@ static int soc_camera_remove(struct device *dev) if (icd->ops->remove) icd->ops->remove(icd); + soc_camera_free_user_formats(icd); + return 0; } -- cgit v1.2.3 From 823ea474f6ef741eb378f550d4c7b2aaf233b23f Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Fri, 13 Mar 2009 10:08:20 +0100 Subject: ov772x: use soft sleep mode in stop_capture From: Kuninori Morimoto Signed-off-by: Kuninori Morimoto Signed-off-by: Guennadi Liakhovetski --- drivers/media/video/ov772x.c | 4 ++++ 1 files changed, 4 insertions(+), 0 deletions(-) --- linux/drivers/media/video/ov772x.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/ov772x.c b/linux/drivers/media/video/ov772x.c index 73d447247..cde3a1019 100644 --- a/linux/drivers/media/video/ov772x.c +++ b/linux/drivers/media/video/ov772x.c @@ -646,6 +646,8 @@ static int ov772x_start_capture(struct soc_camera_device *icd) return -EPERM; } + ov772x_mask_set(priv->client, COM2, SOFT_SLEEP_MODE, 0); + dev_dbg(&icd->dev, "format %s, win %s\n", priv->fmt->name, priv->win->name); @@ -654,6 +656,8 @@ static int ov772x_start_capture(struct soc_camera_device *icd) static int ov772x_stop_capture(struct soc_camera_device *icd) { + struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd); + ov772x_mask_set(priv->client, COM2, SOFT_SLEEP_MODE, SOFT_SLEEP_MODE); return 0; } -- cgit v1.2.3 From 9fd188a1ab044c7613e040e38da6a990e3a5a416 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Fri, 13 Mar 2009 10:08:20 +0100 Subject: video: use videobuf_waiton() in sh_mobile_ceu free_buffer() From: Magnus Damm Make sure videobuf_waiton() is used before freeing a buffer. Without this fix we may return the buffer to the allocator before the bus mastering operation is finished. Reported-by: Matthieu CASTET Tested-by: Kuninori Morimoto Signed-off-by: Magnus Damm Signed-off-by: Guennadi Liakhovetski --- drivers/media/video/sh_mobile_ceu_camera.c | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) --- linux/drivers/media/video/sh_mobile_ceu_camera.c | 1 + 1 file changed, 1 insertion(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/sh_mobile_ceu_camera.c b/linux/drivers/media/video/sh_mobile_ceu_camera.c index 1a4026a95..cd796b33f 100644 --- a/linux/drivers/media/video/sh_mobile_ceu_camera.c +++ b/linux/drivers/media/video/sh_mobile_ceu_camera.c @@ -175,6 +175,7 @@ static void free_buffer(struct videobuf_queue *vq, if (in_interrupt()) BUG(); + videobuf_waiton(&buf->vb, 0, 0); videobuf_dma_contig_free(vq, &buf->vb); dev_dbg(&icd->dev, "%s freed\n", __func__); buf->vb.state = VIDEOBUF_NEEDS_INIT; -- cgit v1.2.3 From faab76d40d690089f67e674332234001dd88d42d Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Fri, 13 Mar 2009 10:08:20 +0100 Subject: mt9m001: allow setting of bus width from board code From: Sascha Hauer This patch removes the phytec specific setting of the bus width and switches to the more generic query_bus_param/set_bus_param hooks Signed-off-by: Sascha Hauer Signed-off-by: Guennadi Liakhovetski --- drivers/media/video/Kconfig | 7 -- drivers/media/video/mt9m001.c | 143 +++++++++++----------------------------- 2 files changed, 40 insertions(+), 110 deletions(-) --- linux/drivers/media/video/Kconfig | 7 -- linux/drivers/media/video/mt9m001.c | 143 ++++++++++-------------------------- 2 files changed, 40 insertions(+), 110 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/Kconfig b/linux/drivers/media/video/Kconfig index 27f639763..429c29bf0 100644 --- a/linux/drivers/media/video/Kconfig +++ b/linux/drivers/media/video/Kconfig @@ -707,13 +707,6 @@ config SOC_CAMERA_MT9M001 This driver supports MT9M001 cameras from Micron, monochrome and colour models. -config MT9M001_PCA9536_SWITCH - bool "pca9536 datawidth switch for mt9m001" - depends on SOC_CAMERA_MT9M001 && GENERIC_GPIO - help - Select this if your MT9M001 camera uses a PCA9536 I2C GPIO - extender to switch between 8 and 10 bit datawidth modes - config SOC_CAMERA_MT9M111 tristate "mt9m111 and mt9m112 support" depends on SOC_CAMERA && I2C diff --git a/linux/drivers/media/video/mt9m001.c b/linux/drivers/media/video/mt9m001.c index 079be8a1b..e3dab2119 100644 --- a/linux/drivers/media/video/mt9m001.c +++ b/linux/drivers/media/video/mt9m001.c @@ -12,7 +12,6 @@ #include #include #include -#include #include #include @@ -73,9 +72,7 @@ struct mt9m001 { struct i2c_client *client; struct soc_camera_device icd; int model; /* V4L2_IDENT_MT9M001* codes from v4l2-chip-ident.h */ - int switch_gpio; unsigned char autoexposure; - unsigned char datawidth; }; static int reg_read(struct soc_camera_device *icd, const u8 reg) @@ -181,92 +178,28 @@ static int mt9m001_stop_capture(struct soc_camera_device *icd) return 0; } -static int bus_switch_request(struct mt9m001 *mt9m001, - struct soc_camera_link *icl) -{ -#ifdef CONFIG_MT9M001_PCA9536_SWITCH - int ret; - unsigned int gpio = icl->gpio; - - if (gpio_is_valid(gpio)) { - /* We have a data bus switch. */ - ret = gpio_request(gpio, "mt9m001"); - if (ret < 0) { - dev_err(&mt9m001->client->dev, "Cannot get GPIO %u\n", - gpio); - return ret; - } - - ret = gpio_direction_output(gpio, 0); - if (ret < 0) { - dev_err(&mt9m001->client->dev, - "Cannot set GPIO %u to output\n", gpio); - gpio_free(gpio); - return ret; - } - } - - mt9m001->switch_gpio = gpio; -#else - mt9m001->switch_gpio = -EINVAL; -#endif - return 0; -} - -static void bus_switch_release(struct mt9m001 *mt9m001) -{ -#ifdef CONFIG_MT9M001_PCA9536_SWITCH - if (gpio_is_valid(mt9m001->switch_gpio)) - gpio_free(mt9m001->switch_gpio); -#endif -} - -static int bus_switch_act(struct mt9m001 *mt9m001, int go8bit) -{ -#ifdef CONFIG_MT9M001_PCA9536_SWITCH - if (!gpio_is_valid(mt9m001->switch_gpio)) - return -ENODEV; - - gpio_set_value_cansleep(mt9m001->switch_gpio, go8bit); - return 0; -#else - return -ENODEV; -#endif -} - -static int bus_switch_possible(struct mt9m001 *mt9m001) -{ -#ifdef CONFIG_MT9M001_PCA9536_SWITCH - return gpio_is_valid(mt9m001->switch_gpio); -#else - return 0; -#endif -} - static int mt9m001_set_bus_param(struct soc_camera_device *icd, unsigned long flags) { struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd); - unsigned int width_flag = flags & SOCAM_DATAWIDTH_MASK; - int ret; + struct soc_camera_link *icl = mt9m001->client->dev.platform_data; + unsigned long width_flag = flags & SOCAM_DATAWIDTH_MASK; - /* Flags validity verified in test_bus_param */ + /* Only one width bit may be set */ + if (!is_power_of_2(width_flag)) + return -EINVAL; - if ((mt9m001->datawidth != 10 && (width_flag == SOCAM_DATAWIDTH_10)) || - (mt9m001->datawidth != 9 && (width_flag == SOCAM_DATAWIDTH_9)) || - (mt9m001->datawidth != 8 && (width_flag == SOCAM_DATAWIDTH_8))) { - /* Well, we actually only can do 10 or 8 bits... */ - if (width_flag == SOCAM_DATAWIDTH_9) - return -EINVAL; - ret = bus_switch_act(mt9m001, - width_flag == SOCAM_DATAWIDTH_8); - if (ret < 0) - return ret; + if (icl->set_bus_param) + return icl->set_bus_param(icl, width_flag); - mt9m001->datawidth = width_flag == SOCAM_DATAWIDTH_8 ? 8 : 10; - } + /* + * Without board specific bus width settings we only support the + * sensors native bus width + */ + if (width_flag == SOCAM_DATAWIDTH_10) + return 0; - return 0; + return -EINVAL; } static unsigned long mt9m001_query_bus_param(struct soc_camera_device *icd) @@ -274,12 +207,14 @@ static unsigned long mt9m001_query_bus_param(struct soc_camera_device *icd) struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd); struct soc_camera_link *icl = mt9m001->client->dev.platform_data; /* MT9M001 has all capture_format parameters fixed */ - unsigned long flags = SOCAM_DATAWIDTH_10 | SOCAM_PCLK_SAMPLE_RISING | + unsigned long flags = SOCAM_PCLK_SAMPLE_RISING | SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_DATA_ACTIVE_HIGH | SOCAM_MASTER; - if (bus_switch_possible(mt9m001)) - flags |= SOCAM_DATAWIDTH_8; + if (icl->query_bus_param) + flags |= icl->query_bus_param(icl) & SOCAM_DATAWIDTH_MASK; + else + flags |= SOCAM_DATAWIDTH_10; return soc_camera_apply_sensor_flags(icl, flags); } @@ -598,6 +533,7 @@ static int mt9m001_video_probe(struct soc_camera_device *icd) struct soc_camera_link *icl = mt9m001->client->dev.platform_data; s32 data; int ret; + unsigned long flags; /* We must have a parent by now. And it cannot be a wrong one. * So this entire test is completely redundant. */ @@ -618,18 +554,10 @@ static int mt9m001_video_probe(struct soc_camera_device *icd) case 0x8421: mt9m001->model = V4L2_IDENT_MT9M001C12ST; icd->formats = mt9m001_colour_formats; - if (gpio_is_valid(icl->gpio)) - icd->num_formats = ARRAY_SIZE(mt9m001_colour_formats); - else - icd->num_formats = 1; break; case 0x8431: mt9m001->model = V4L2_IDENT_MT9M001C12STM; icd->formats = mt9m001_monochrome_formats; - if (gpio_is_valid(icl->gpio)) - icd->num_formats = ARRAY_SIZE(mt9m001_monochrome_formats); - else - icd->num_formats = 1; break; default: ret = -ENODEV; @@ -638,6 +566,26 @@ static int mt9m001_video_probe(struct soc_camera_device *icd) goto ei2c; } + icd->num_formats = 0; + + /* + * This is a 10bit sensor, so by default we only allow 10bit. + * The platform may support different bus widths due to + * different routing of the data lines. + */ + if (icl->query_bus_param) + flags = icl->query_bus_param(icl); + else + flags = SOCAM_DATAWIDTH_10; + + if (flags & SOCAM_DATAWIDTH_10) + icd->num_formats++; + else + icd->formats++; + + if (flags & SOCAM_DATAWIDTH_8) + icd->num_formats++; + dev_info(&icd->dev, "Detected a MT9M001 chip ID %x (%s)\n", data, data == 0x8431 ? "C12STM" : "C12ST"); @@ -707,18 +655,10 @@ static int mt9m001_probe(struct i2c_client *client) icd->height_max = 1024; icd->y_skip_top = 1; icd->iface = icl->bus_id; - /* Default datawidth - this is the only width this camera (normally) - * supports. It is only with extra logic that it can support - * other widths. Therefore it seems to be a sensible default. */ - mt9m001->datawidth = 10; /* Simulated autoexposure. If enabled, we calculate shutter width * ourselves in the driver based on vertical blanking and frame width */ mt9m001->autoexposure = 1; - ret = bus_switch_request(mt9m001, icl); - if (ret) - goto eswinit; - ret = soc_camera_device_register(icd); if (ret) goto eisdr; @@ -726,8 +666,6 @@ static int mt9m001_probe(struct i2c_client *client) return 0; eisdr: - bus_switch_release(mt9m001); -eswinit: kfree(mt9m001); return ret; } @@ -737,7 +675,6 @@ static int mt9m001_remove(struct i2c_client *client) struct mt9m001 *mt9m001 = i2c_get_clientdata(client); soc_camera_device_unregister(&mt9m001->icd); - bus_switch_release(mt9m001); kfree(mt9m001); return 0; -- cgit v1.2.3 From f82d4bc25191557bf1b256557c693ba25bd8bb66 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Fri, 13 Mar 2009 10:08:20 +0100 Subject: mt9v022: allow setting of bus width from board code From: Sascha Hauer This patch removes the phytec specific setting of the bus width and switches to the more generic query_bus_param/set_bus_param hooks Signed-off-by: Sascha Hauer Signed-off-by: Guennadi Liakhovetski --- drivers/media/video/Kconfig | 7 -- drivers/media/video/mt9v022.c | 141 ++++++++++++----------------------------- 2 files changed, 42 insertions(+), 106 deletions(-) --- linux/drivers/media/video/Kconfig | 7 -- linux/drivers/media/video/mt9v022.c | 141 +++++++++++------------------------- 2 files changed, 42 insertions(+), 106 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/Kconfig b/linux/drivers/media/video/Kconfig index 429c29bf0..42562e348 100644 --- a/linux/drivers/media/video/Kconfig +++ b/linux/drivers/media/video/Kconfig @@ -726,13 +726,6 @@ config SOC_CAMERA_MT9V022 help This driver supports MT9V022 cameras from Micron -config MT9V022_PCA9536_SWITCH - bool "pca9536 datawidth switch for mt9v022" - depends on SOC_CAMERA_MT9V022 && GENERIC_GPIO - help - Select this if your MT9V022 camera uses a PCA9536 I2C GPIO - extender to switch between 8 and 10 bit datawidth modes - config SOC_CAMERA_TW9910 tristate "tw9910 support" depends on SOC_CAMERA && I2C diff --git a/linux/drivers/media/video/mt9v022.c b/linux/drivers/media/video/mt9v022.c index 09d3679e5..bec6859b3 100644 --- a/linux/drivers/media/video/mt9v022.c +++ b/linux/drivers/media/video/mt9v022.c @@ -13,7 +13,6 @@ #include #include #include -#include #include #include @@ -89,9 +88,7 @@ struct mt9v022 { struct i2c_client *client; struct soc_camera_device icd; int model; /* V4L2_IDENT_MT9V022* codes from v4l2-chip-ident.h */ - int switch_gpio; u16 chip_control; - unsigned char datawidth; }; static int reg_read(struct soc_camera_device *icd, const u8 reg) @@ -209,66 +206,6 @@ static int mt9v022_stop_capture(struct soc_camera_device *icd) return 0; } -static int bus_switch_request(struct mt9v022 *mt9v022, struct soc_camera_link *icl) -{ -#ifdef CONFIG_MT9V022_PCA9536_SWITCH - int ret; - unsigned int gpio = icl->gpio; - - if (gpio_is_valid(gpio)) { - /* We have a data bus switch. */ - ret = gpio_request(gpio, "mt9v022"); - if (ret < 0) { - dev_err(&mt9v022->client->dev, "Cannot get GPIO %u\n", gpio); - return ret; - } - - ret = gpio_direction_output(gpio, 0); - if (ret < 0) { - dev_err(&mt9v022->client->dev, - "Cannot set GPIO %u to output\n", gpio); - gpio_free(gpio); - return ret; - } - } - - mt9v022->switch_gpio = gpio; -#else - mt9v022->switch_gpio = -EINVAL; -#endif - return 0; -} - -static void bus_switch_release(struct mt9v022 *mt9v022) -{ -#ifdef CONFIG_MT9V022_PCA9536_SWITCH - if (gpio_is_valid(mt9v022->switch_gpio)) - gpio_free(mt9v022->switch_gpio); -#endif -} - -static int bus_switch_act(struct mt9v022 *mt9v022, int go8bit) -{ -#ifdef CONFIG_MT9V022_PCA9536_SWITCH - if (!gpio_is_valid(mt9v022->switch_gpio)) - return -ENODEV; - - gpio_set_value_cansleep(mt9v022->switch_gpio, go8bit); - return 0; -#else - return -ENODEV; -#endif -} - -static int bus_switch_possible(struct mt9v022 *mt9v022) -{ -#ifdef CONFIG_MT9V022_PCA9536_SWITCH - return gpio_is_valid(mt9v022->switch_gpio); -#else - return 0; -#endif -} - static int mt9v022_set_bus_param(struct soc_camera_device *icd, unsigned long flags) { @@ -282,19 +219,17 @@ static int mt9v022_set_bus_param(struct soc_camera_device *icd, if (!is_power_of_2(width_flag)) return -EINVAL; - if ((mt9v022->datawidth != 10 && (width_flag == SOCAM_DATAWIDTH_10)) || - (mt9v022->datawidth != 9 && (width_flag == SOCAM_DATAWIDTH_9)) || - (mt9v022->datawidth != 8 && (width_flag == SOCAM_DATAWIDTH_8))) { - /* Well, we actually only can do 10 or 8 bits... */ - if (width_flag == SOCAM_DATAWIDTH_9) - return -EINVAL; - - ret = bus_switch_act(mt9v022, - width_flag == SOCAM_DATAWIDTH_8); - if (ret < 0) + if (icl->set_bus_param) { + ret = icl->set_bus_param(icl, width_flag); + if (ret) return ret; - - mt9v022->datawidth = width_flag == SOCAM_DATAWIDTH_8 ? 8 : 10; + } else { + /* + * Without board specific bus width settings we only support the + * sensors native bus width + */ + if (width_flag != SOCAM_DATAWIDTH_10) + return -EINVAL; } flags = soc_camera_apply_sensor_flags(icl, flags); @@ -328,10 +263,14 @@ static int mt9v022_set_bus_param(struct soc_camera_device *icd, static unsigned long mt9v022_query_bus_param(struct soc_camera_device *icd) { struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd); - unsigned int width_flag = SOCAM_DATAWIDTH_10; + struct soc_camera_link *icl = mt9v022->client->dev.platform_data; + unsigned int width_flag; - if (bus_switch_possible(mt9v022)) - width_flag |= SOCAM_DATAWIDTH_8; + if (icl->query_bus_param) + width_flag = icl->query_bus_param(icl) & + SOCAM_DATAWIDTH_MASK; + else + width_flag = SOCAM_DATAWIDTH_10; return SOCAM_PCLK_SAMPLE_RISING | SOCAM_PCLK_SAMPLE_FALLING | SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_HSYNC_ACTIVE_LOW | @@ -715,6 +654,7 @@ static int mt9v022_video_probe(struct soc_camera_device *icd) struct soc_camera_link *icl = mt9v022->client->dev.platform_data; s32 data; int ret; + unsigned long flags; if (!icd->dev.parent || to_soc_camera_host(icd->dev.parent)->nr != icd->iface) @@ -748,22 +688,36 @@ static int mt9v022_video_probe(struct soc_camera_device *icd) ret = reg_write(icd, MT9V022_PIXEL_OPERATION_MODE, 4 | 0x11); mt9v022->model = V4L2_IDENT_MT9V022IX7ATC; icd->formats = mt9v022_colour_formats; - if (gpio_is_valid(icl->gpio)) - icd->num_formats = ARRAY_SIZE(mt9v022_colour_formats); - else - icd->num_formats = 1; } else { ret = reg_write(icd, MT9V022_PIXEL_OPERATION_MODE, 0x11); mt9v022->model = V4L2_IDENT_MT9V022IX7ATM; icd->formats = mt9v022_monochrome_formats; - if (gpio_is_valid(icl->gpio)) - icd->num_formats = ARRAY_SIZE(mt9v022_monochrome_formats); - else - icd->num_formats = 1; } - if (!ret) - ret = soc_camera_video_start(icd); + if (ret < 0) + goto eisis; + + icd->num_formats = 0; + + /* + * This is a 10bit sensor, so by default we only allow 10bit. + * The platform may support different bus widths due to + * different routing of the data lines. + */ + if (icl->query_bus_param) + flags = icl->query_bus_param(icl); + else + flags = SOCAM_DATAWIDTH_10; + + if (flags & SOCAM_DATAWIDTH_10) + icd->num_formats++; + else + icd->formats++; + + if (flags & SOCAM_DATAWIDTH_8) + icd->num_formats++; + + ret = soc_camera_video_start(icd); if (ret < 0) goto eisis; @@ -828,14 +782,6 @@ static int mt9v022_probe(struct i2c_client *client, icd->height_max = 480; icd->y_skip_top = 1; icd->iface = icl->bus_id; - /* Default datawidth - this is the only width this camera (normally) - * supports. It is only with extra logic that it can support - * other widths. Therefore it seems to be a sensible default. */ - mt9v022->datawidth = 10; - - ret = bus_switch_request(mt9v022, icl); - if (ret) - goto eswinit; ret = soc_camera_device_register(icd); if (ret) @@ -844,8 +790,6 @@ static int mt9v022_probe(struct i2c_client *client, return 0; eisdr: - bus_switch_release(mt9v022); -eswinit: kfree(mt9v022); return ret; } @@ -855,7 +799,6 @@ static int mt9v022_remove(struct i2c_client *client) struct mt9v022 *mt9v022 = i2c_get_clientdata(client); soc_camera_device_unregister(&mt9v022->icd); - bus_switch_release(mt9v022); kfree(mt9v022); return 0; -- cgit v1.2.3 From 611e15a080c06e90f91feee1be742463a0e256d6 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 13 Mar 2009 12:02:43 +0100 Subject: cx23885: convert to v4l2_device. From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/cx23885/cx23885-core.c | 17 +++++++++++------ linux/drivers/media/video/cx23885/cx23885-i2c.c | 9 +++++---- linux/drivers/media/video/cx23885/cx23885-video.c | 4 ++-- linux/drivers/media/video/cx23885/cx23885.h | 8 +++++++- 4 files changed, 25 insertions(+), 13 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/cx23885/cx23885-core.c b/linux/drivers/media/video/cx23885/cx23885-core.c index d894d4900..eea0bc650 100644 --- a/linux/drivers/media/video/cx23885/cx23885-core.c +++ b/linux/drivers/media/video/cx23885/cx23885-core.c @@ -1750,16 +1750,20 @@ static int __devinit cx23885_initdev(struct pci_dev *pci_dev, if (NULL == dev) return -ENOMEM; + err = v4l2_device_register(&pci_dev->dev, &dev->v4l2_dev); + if (err < 0) + goto fail_free; + /* pci init */ dev->pci = pci_dev; if (pci_enable_device(pci_dev)) { err = -EIO; - goto fail_free; + goto fail_unreg; } if (cx23885_dev_setup(dev) < 0) { err = -EINVAL; - goto fail_free; + goto fail_unreg; } /* print pci info */ @@ -1786,8 +1790,6 @@ static int __devinit cx23885_initdev(struct pci_dev *pci_dev, goto fail_irq; } - pci_set_drvdata(pci_dev, dev); - switch (dev->board) { case CX23885_BOARD_NETUP_DUAL_DVBS2_CI: cx_set(PCI_INT_MSK, 0x01800000); /* for NetUP */ @@ -1798,6 +1800,8 @@ static int __devinit cx23885_initdev(struct pci_dev *pci_dev, fail_irq: cx23885_dev_unregister(dev); +fail_unreg: + v4l2_device_unregister(&dev->v4l2_dev); fail_free: kfree(dev); return err; @@ -1805,7 +1809,8 @@ fail_free: static void __devexit cx23885_finidev(struct pci_dev *pci_dev) { - struct cx23885_dev *dev = pci_get_drvdata(pci_dev); + struct v4l2_device *v4l2_dev = pci_get_drvdata(pci_dev); + struct cx23885_dev *dev = to_cx23885(v4l2_dev); cx23885_shutdown(dev); @@ -1813,13 +1818,13 @@ static void __devexit cx23885_finidev(struct pci_dev *pci_dev) /* unregister stuff */ free_irq(pci_dev->irq, dev); - pci_set_drvdata(pci_dev, NULL); mutex_lock(&devlist); list_del(&dev->devlist); mutex_unlock(&devlist); cx23885_dev_unregister(dev); + v4l2_device_unregister(v4l2_dev); kfree(dev); } diff --git a/linux/drivers/media/video/cx23885/cx23885-i2c.c b/linux/drivers/media/video/cx23885/cx23885-i2c.c index 2210b47d2..86493da33 100644 --- a/linux/drivers/media/video/cx23885/cx23885-i2c.c +++ b/linux/drivers/media/video/cx23885/cx23885-i2c.c @@ -271,8 +271,8 @@ static int i2c_xfer(struct i2c_adapter *i2c_adap, static int attach_inform(struct i2c_client *client) { - struct cx23885_i2c *bus = i2c_get_adapdata(client->adapter); - struct cx23885_dev *dev = bus->dev; + struct v4l2_device *v4l2_dev = i2c_get_adapdata(client->adapter); + struct cx23885_dev *dev = to_cx23885(v4l2_dev); struct tuner_setup tun_setup; dprintk(1, "%s i2c attach [addr=0x%x,client=%s]\n", @@ -329,7 +329,8 @@ static int attach_inform(struct i2c_client *client) static int detach_inform(struct i2c_client *client) { - struct cx23885_dev *dev = i2c_get_adapdata(client->adapter); + struct v4l2_device *v4l2_dev = i2c_get_adapdata(client->adapter); + struct cx23885_dev *dev = to_cx23885(v4l2_dev); dprintk(1, "i2c detach [client=%s]\n", client->name); @@ -424,7 +425,7 @@ int cx23885_i2c_register(struct cx23885_i2c *bus) bus->i2c_algo.data = bus; bus->i2c_adap.algo_data = bus; - i2c_set_adapdata(&bus->i2c_adap, bus); + i2c_set_adapdata(&bus->i2c_adap, &dev->v4l2_dev); i2c_add_adapter(&bus->i2c_adap); bus->i2c_client.adapter = &bus->i2c_adap; diff --git a/linux/drivers/media/video/cx23885/cx23885-video.c b/linux/drivers/media/video/cx23885/cx23885-video.c index ba22520a2..dd6e1f70e 100644 --- a/linux/drivers/media/video/cx23885/cx23885-video.c +++ b/linux/drivers/media/video/cx23885/cx23885-video.c @@ -355,8 +355,8 @@ static struct video_device *cx23885_vdev_init(struct cx23885_dev *dev, if (NULL == vfd) return NULL; *vfd = *template; - vfd->minor = -1; - vfd->parent = &pci->dev; + vfd->minor = -1; + vfd->v4l2_dev = &dev->v4l2_dev; vfd->release = video_device_release; snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)", dev->name, type, cx23885_boards[dev->board].name); diff --git a/linux/drivers/media/video/cx23885/cx23885.h b/linux/drivers/media/video/cx23885/cx23885.h index e8118c6bd..80031ddfa 100644 --- a/linux/drivers/media/video/cx23885/cx23885.h +++ b/linux/drivers/media/video/cx23885/cx23885.h @@ -24,7 +24,7 @@ #include #include -#include +#include #include #include #include @@ -278,6 +278,7 @@ struct cx23885_tsport { struct cx23885_dev { struct list_head devlist; atomic_t refcount; + struct v4l2_device v4l2_dev; /* pci stuff */ struct pci_dev *pci; @@ -343,6 +344,11 @@ struct cx23885_dev { }; +static inline struct cx23885_dev *to_cx23885(struct v4l2_device *v4l2_dev) +{ + return container_of(v4l2_dev, struct cx23885_dev, v4l2_dev); +} + extern struct list_head cx23885_devlist; #define SRAM_CH01 0 /* Video A */ -- cgit v1.2.3 From 3e0273a7209d6a20bd422beec8b46dd6b79a00a7 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Fri, 13 Mar 2009 13:42:32 +0100 Subject: =?UTF-8?q?mt9t031=20bugfix=20From:=20Philippe=20R=C3=A9tornaz=20?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - The video device is not allocated when mt9t031_init() is called, don't use it in debug printk. - The clock polarity is inverted in mt9t031_set_bus_param(), use the correct one. Signed-off-by: Philippe Rétornaz Signed-off-by: Guennadi Liakhovetski --- drivers/media/video/mt9t031.c | 6 ++---- 1 files changed, 2 insertions(+), 4 deletions(-) --- linux/drivers/media/video/mt9t031.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/mt9t031.c b/linux/drivers/media/video/mt9t031.c index 34b8f5cee..8a9ca0b27 100644 --- a/linux/drivers/media/video/mt9t031.c +++ b/linux/drivers/media/video/mt9t031.c @@ -144,8 +144,6 @@ static int mt9t031_init(struct soc_camera_device *icd) int ret; /* Disable chip output, synchronous option update */ - dev_dbg(icd->vdev->parent, "%s\n", __func__); - ret = reg_write(icd, MT9T031_RESET, 1); if (ret >= 0) ret = reg_write(icd, MT9T031_RESET, 0); @@ -186,9 +184,9 @@ static int mt9t031_set_bus_param(struct soc_camera_device *icd, return -EINVAL; if (flags & SOCAM_PCLK_SAMPLE_FALLING) - reg_set(icd, MT9T031_PIXEL_CLOCK_CONTROL, 0x8000); - else reg_clear(icd, MT9T031_PIXEL_CLOCK_CONTROL, 0x8000); + else + reg_set(icd, MT9T031_PIXEL_CLOCK_CONTROL, 0x8000); return 0; } -- cgit v1.2.3 From 5da9d7f5f979a7489135b5030c3c5cfe68a2a4fb Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 13 Mar 2009 13:04:31 -0300 Subject: mr97310a: don't discard frame headers on stream output From: Theodore Kilgore Fix a bug where all frame headers were being discarded, instead of being part of the stream output, on MR97310A cameras. The frame headers contain information which may be useful in processing the video output and therefore should be kept and not discarded. A corresponding patch to the decompression algorithm in libv4lconvert/mr97310a.c corrects the change in frame offset. Priority: high Signed-off-by: Theodore Kilgore Signed-off-by: Hans de Goede Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/gspca/mr97310a.c | 22 +++------------------- 1 file changed, 3 insertions(+), 19 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/mr97310a.c b/linux/drivers/media/video/gspca/mr97310a.c index 5ec5ce6e3..2a901a4a6 100644 --- a/linux/drivers/media/video/gspca/mr97310a.c +++ b/linux/drivers/media/video/gspca/mr97310a.c @@ -29,9 +29,7 @@ MODULE_LICENSE("GPL"); /* specific webcam descriptor */ struct sd { struct gspca_dev gspca_dev; /* !! must be the first item */ - u8 sof_read; - u8 header_read; }; /* V4L2 controls supported by the driver */ @@ -285,7 +283,6 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, __u8 *data, /* isoc packet */ int len) /* iso packet length */ { - struct sd *sd = (struct sd *) gspca_dev; unsigned char *sof; sof = pac_find_sof(gspca_dev, data, len); @@ -300,25 +297,12 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, n = 0; frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame, data, n); - sd->header_read = 0; - gspca_frame_add(gspca_dev, FIRST_PACKET, frame, NULL, 0); + /* Start next frame. */ + gspca_frame_add(gspca_dev, FIRST_PACKET, frame, + pac_sof_marker, sizeof pac_sof_marker); len -= sof - data; data = sof; } - if (sd->header_read < 7) { - int needed; - - /* skip the rest of the header */ - needed = 7 - sd->header_read; - if (len <= needed) { - sd->header_read += len; - return; - } - data += needed; - len -= needed; - sd->header_read = 7; - } - gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len); } -- cgit v1.2.3 From 01cbd287bd3f93c3402e8bd46d5c92aec838da2e Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 13 Mar 2009 17:24:19 +0100 Subject: cx23885: fix crash on non-netup cards From: Hans Verkuil The new support for the CX23885_BOARD_NETUP_DUAL_DVBS2_CI board broke the existing boards. Interrupts for the netup part were enabled and handled without testing whether the current board actually had a netup -> instant and fatal crash. I've added tests to do this only for the CX23885_BOARD_NETUP_DUAL_DVBS2_CI board. Priority: normal Signed-off-by: Hans Verkuil Reviewed-by: Michael Krufky --- linux/drivers/media/video/cx23885/cx23885-core.c | 10 ++++++++-- linux/drivers/media/video/cx23885/cx23885-dvb.c | 6 +++++- 2 files changed, 13 insertions(+), 3 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/cx23885/cx23885-core.c b/linux/drivers/media/video/cx23885/cx23885-core.c index 6ae7ee247..d894d4900 100644 --- a/linux/drivers/media/video/cx23885/cx23885-core.c +++ b/linux/drivers/media/video/cx23885/cx23885-core.c @@ -1710,7 +1710,8 @@ static irqreturn_t cx23885_irq(int irq, void *dev_id) PCI_MSK_GPIO1); } - if ((pci_status & PCI_MSK_GPIO0) || (pci_status & PCI_MSK_GPIO1)) + if (cx23885_boards[dev->board].cimax > 0 && + ((pci_status & PCI_MSK_GPIO0) || (pci_status & PCI_MSK_GPIO1))) /* handled += cx23885_irq_gpio(dev, pci_status); */ handled += netup_ci_slot_status(dev, pci_status); @@ -1786,7 +1787,12 @@ static int __devinit cx23885_initdev(struct pci_dev *pci_dev, } pci_set_drvdata(pci_dev, dev); - cx_set(PCI_INT_MSK, 0x01800000); /* for NetUP */ + + switch (dev->board) { + case CX23885_BOARD_NETUP_DUAL_DVBS2_CI: + cx_set(PCI_INT_MSK, 0x01800000); /* for NetUP */ + break; + } return 0; diff --git a/linux/drivers/media/video/cx23885/cx23885-dvb.c b/linux/drivers/media/video/cx23885/cx23885-dvb.c index 5529dcf6a..364543987 100644 --- a/linux/drivers/media/video/cx23885/cx23885-dvb.c +++ b/linux/drivers/media/video/cx23885/cx23885-dvb.c @@ -779,7 +779,11 @@ int cx23885_dvb_unregister(struct cx23885_tsport *port) if (fe0->dvb.frontend) videobuf_dvb_unregister_bus(&port->frontends); - netup_ci_exit(port); + switch (port->dev->board) { + case CX23885_BOARD_NETUP_DUAL_DVBS2_CI: + netup_ci_exit(port); + break; + } return 0; } -- cgit v1.2.3 From e0880a34f81b5282fa1be0f8872664992db9cdfd Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 13 Mar 2009 14:03:04 +0100 Subject: v4l2-dev: use parent field if the v4l2_device has no parent set. From: Hans Verkuil Normally the parent device of v4l2_device is used as the video device node's parent. But if it was not set, then use the parent field in the video_device struct. This is needed in the cx88 driver, which has one core v4l2_device but creates multiple pci devices (one each for raw and mpeg video). So you cannot associate the core v4l2_device with a particular PCI device, but you can do that for each video_device. Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/v4l2-dev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/v4l2-dev.c b/linux/drivers/media/video/v4l2-dev.c index 110cde853..5e9b46c21 100644 --- a/linux/drivers/media/video/v4l2-dev.c +++ b/linux/drivers/media/video/v4l2-dev.c @@ -433,7 +433,7 @@ int video_register_device_index(struct video_device *vdev, int type, int nr, vdev->vfl_type = type; vdev->cdev = NULL; - if (vdev->v4l2_dev) + if (vdev->v4l2_dev && vdev->v4l2_dev->dev) vdev->parent = vdev->v4l2_dev->dev; /* Part 2: find a free minor, kernel number and device index. */ -- cgit v1.2.3 From c3ce9d2f22c72aa484146a24d87be98d1a29ab9f Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 13 Mar 2009 17:36:00 +0100 Subject: cx25840: cx23885 detection was broken From: Hans Verkuil An earlier commit accidentally broke the detection of the cx25837 part of the cx23885. Reinstated the commented out code. Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/cx25840/cx25840-core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/cx25840/cx25840-core.c b/linux/drivers/media/video/cx25840/cx25840-core.c index b10f2bb8b..5387a846f 100644 --- a/linux/drivers/media/video/cx25840/cx25840-core.c +++ b/linux/drivers/media/video/cx25840/cx25840-core.c @@ -1594,9 +1594,9 @@ static int cx25840_probe(struct i2c_client *client, } else if ((device_id & 0xff00) == 0x8400) { id = V4L2_IDENT_CX25840 + ((device_id >> 4) & 0xf); - } /* else if (device_id == 0x0000) { + } else if (device_id == 0x0000) { id = V4L2_IDENT_CX25836 + ((device_id >> 4) & 0xf) - 6; - } */ else if (device_id == 0x1313) { + } else if (device_id == 0x1313) { id = V4L2_IDENT_CX25836 + ((device_id >> 4) & 0xf) - 6; } else if ((device_id & 0xfff0) == 0x5A30) { id = V4L2_IDENT_CX25840 + ((device_id >> 4) & 0xf); -- cgit v1.2.3 From 38acf457413a9fdec97a0ac3457ced727a76a289 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 13 Mar 2009 21:07:33 -0300 Subject: Fix compilation with -git tree From: Mauro Carvalho Chehab Due to the out-of-tree and in-kernel -git tree, a few changes are required, in order to properly compile cx231xx with -git. kernel-sync: CC: Sri Deevi Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/cx231xx/Kconfig | 44 +++++++++++------------ linux/drivers/media/video/cx231xx/cx231xx-cards.c | 4 +-- linux/drivers/media/video/cx231xx/cx231xx-video.c | 2 ++ linux/drivers/media/video/cx231xx/cx231xx.h | 1 - 4 files changed, 25 insertions(+), 26 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/cx231xx/Kconfig b/linux/drivers/media/video/cx231xx/Kconfig index 7a6700fb0..aba05d3bd 100644 --- a/linux/drivers/media/video/cx231xx/Kconfig +++ b/linux/drivers/media/video/cx231xx/Kconfig @@ -1,12 +1,11 @@ config VIDEO_CX231XX - tristate "Conexant cx231xx USB video capture support" - depends on VIDEO_DEV && I2C && INPUT - select VIDEO_TUNER - select VIDEO_TVEEPROM - select VIDEO_IR - select VIDEOBUF_VMALLOC - select VIDEO_CX25840 - select VIDEO_CX231XX_ALSA + tristate "Conexant cx231xx USB video capture support" + depends on VIDEO_DEV && I2C && INPUT + select VIDEO_TUNER + select VIDEO_TVEEPROM + select VIDEO_IR + select VIDEOBUF_VMALLOC + select VIDEO_CX25840 ---help--- This is a video4linux driver for Conexant 231xx USB based TV cards. @@ -15,21 +14,22 @@ config VIDEO_CX231XX module will be called cx231xx config VIDEO_CX231XX_ALSA - tristate "Conexant Cx231xx ALSA audio module" - depends on VIDEO_CX231XX && SND - select SND_PCM + tristate "Conexant Cx231xx ALSA audio module" + depends on VIDEO_CX231XX && SND + select SND_PCM - ---help--- - This is an ALSA driver for Cx231xx USB based TV cards. + ---help--- + This is an ALSA driver for Cx231xx USB based TV cards. - To compile this driver as a module, choose M here: the - module will be called cx231xx-alsa + To compile this driver as a module, choose M here: the + module will be called cx231xx-alsa config VIDEO_CX231XX_DVB - tristate "DVB/ATSC Support for Cx231xx based TV cards" - depends on VIDEO_CX231XX && DVB_CORE - select VIDEOBUF_DVB - select MEDIA_TUNER_XC5000 if !DVB_FE_CUSTOMISE - ---help--- - This adds support for DVB cards based on the - Conexant cx231xx chips. + tristate "DVB/ATSC Support for Cx231xx based TV cards" + depends on VIDEO_CX231XX && DVB_CORE + select VIDEOBUF_DVB + select MEDIA_TUNER_XC5000 if !DVB_FE_CUSTOMISE + + ---help--- + This adds support for DVB cards based on the + Conexant cx231xx chips. diff --git a/linux/drivers/media/video/cx231xx/cx231xx-cards.c b/linux/drivers/media/video/cx231xx/cx231xx-cards.c index bc8e375ca..b4e9aa38f 100644 --- a/linux/drivers/media/video/cx231xx/cx231xx-cards.c +++ b/linux/drivers/media/video/cx231xx/cx231xx-cards.c @@ -932,9 +932,7 @@ static int __init cx231xx_module_init(void) { int result; - printk(KERN_INFO DRIVER_NAME " v4l2 driver version %d.%d.%d loaded\n", - (CX231XX_VERSION_CODE >> 16) & 0xff, - (CX231XX_VERSION_CODE >> 8) & 0xff, CX231XX_VERSION_CODE & 0xff); + printk(KERN_INFO DRIVER_NAME " v4l2 driver loaded.\n"); /* register this driver with the USB subsystem */ result = usb_register(&cx231xx_usb_driver); diff --git a/linux/drivers/media/video/cx231xx/cx231xx-video.c b/linux/drivers/media/video/cx231xx/cx231xx-video.c index 2dbe65b83..6cb3ae90e 100644 --- a/linux/drivers/media/video/cx231xx/cx231xx-video.c +++ b/linux/drivers/media/video/cx231xx/cx231xx-video.c @@ -44,6 +44,8 @@ #include "cx231xx.h" #include "cx231xx-vbi.h" +#define CX231XX_VERSION_CODE KERNEL_VERSION(0, 0, 1) + #define DRIVER_AUTHOR "Srinivasa Deevi " #define DRIVER_DESC "Conexant cx231xx based USB video device driver" diff --git a/linux/drivers/media/video/cx231xx/cx231xx.h b/linux/drivers/media/video/cx231xx/cx231xx.h index 4606f27b4..8ab6c615e 100644 --- a/linux/drivers/media/video/cx231xx/cx231xx.h +++ b/linux/drivers/media/video/cx231xx/cx231xx.h @@ -39,7 +39,6 @@ #include "cx231xx-pcb-cfg.h" #include "cx231xx-conf-reg.h" -#define CX231XX_VERSION_CODE KERNEL_VERSION(0, 1, 0) #define DRIVER_NAME "cx231xx" #define PWR_SLEEP_INTERVAL 5 -- cgit v1.2.3 From 823c2d8d6994da5af8399edffb4472992c90b62e Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 13 Mar 2009 14:35:14 -0700 Subject: Fix the issue with audio module & correction of Names From: Sri Deevi The audio module requested in driver differs with module created by Makefile. Makefile is corrected to create the same module name required by driver. Also, corrected the strings that shows wrong name. Priority: normal Signed-off-by: Srinivasa Deevi Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/cx231xx/Makefile | 4 +++- linux/drivers/media/video/cx231xx/cx231xx-cards.c | 8 ++++---- 2 files changed, 7 insertions(+), 5 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/cx231xx/Makefile b/linux/drivers/media/video/cx231xx/Makefile index 1dad93619..755dd0ce6 100644 --- a/linux/drivers/media/video/cx231xx/Makefile +++ b/linux/drivers/media/video/cx231xx/Makefile @@ -1,8 +1,10 @@ cx231xx-objs := cx231xx-video.o cx231xx-i2c.o cx231xx-cards.o cx231xx-core.o \ cx231xx-avcore.o cx231xx-pcb-cfg.o cx231xx-vbi.o +cx231xx-alsa-objs := cx231xx-audio.o + obj-$(CONFIG_VIDEO_CX231XX) += cx231xx.o -obj-$(CONFIG_VIDEO_CX231XX_ALSA) += cx231xx-audio.o +obj-$(CONFIG_VIDEO_CX231XX_ALSA) += cx231xx-alsa.o obj-$(CONFIG_VIDEO_CX231XX_DVB) += cx231xx-dvb.o EXTRA_CFLAGS += -Idrivers/media/video diff --git a/linux/drivers/media/video/cx231xx/cx231xx-cards.c b/linux/drivers/media/video/cx231xx/cx231xx-cards.c index b4e9aa38f..435ecf58d 100644 --- a/linux/drivers/media/video/cx231xx/cx231xx-cards.c +++ b/linux/drivers/media/video/cx231xx/cx231xx-cards.c @@ -169,11 +169,11 @@ const unsigned int cx231xx_bcount = ARRAY_SIZE(cx231xx_boards); /* table of devices that work with this driver */ struct usb_device_id cx231xx_id_table[] = { - {USB_DEVICE(0x0572, 0x58A0), + {USB_DEVICE(0x0572, 0x5A3C), .driver_info = CX231XX_BOARD_UNKNOWN}, {USB_DEVICE(0x0572, 0x58A2), .driver_info = CX231XX_BOARD_CNXT_RDE_250}, - {USB_DEVICE(0x0572, 0x5A3C), + {USB_DEVICE(0x0572, 0x58A1), .driver_info = CX231XX_BOARD_CNXT_RDU_250}, {}, }; @@ -322,11 +322,11 @@ void cx231xx_card_setup(struct cx231xx *dev) switch (dev->model) { case CX231XX_BOARD_CNXT_RDE_250: /* do card specific GPIO settings if required */ - cx231xx_info("Board is Conexnat RDE 250\n"); + cx231xx_info("Board is Conexant RDE 250\n"); break; case CX231XX_BOARD_CNXT_RDU_250: /* do card specific GPIO settings if required */ - cx231xx_info("Board is Conexnat RDU 250\n"); + cx231xx_info("Board is Conexant RDU 250\n"); break; } -- cgit v1.2.3 From 48beb6bb3e66daddf4c339f5c02710a060d3a0be Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 14 Mar 2009 12:28:45 +0100 Subject: v4l2-device: add v4l2_device_disconnect From: Hans Verkuil Call v4l2_device_disconnect when the parent of a hotpluggable device disconnects. This ensures that you do not have a pointer to a device that is no longer present. Priority: normal Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/v4l2-device.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/v4l2-device.c b/linux/drivers/media/video/v4l2-device.c index 35e42e947..2cb81c210 100644 --- a/linux/drivers/media/video/v4l2-device.c +++ b/linux/drivers/media/video/v4l2-device.c @@ -50,19 +50,26 @@ int v4l2_device_register(struct device *dev, struct v4l2_device *v4l2_dev) } EXPORT_SYMBOL_GPL(v4l2_device_register); +void v4l2_device_disconnect(struct v4l2_device *v4l2_dev) +{ + if (v4l2_dev->dev) { + dev_set_drvdata(v4l2_dev->dev, NULL); + v4l2_dev->dev = NULL; + } +} +EXPORT_SYMBOL_GPL(v4l2_device_disconnect); + void v4l2_device_unregister(struct v4l2_device *v4l2_dev) { struct v4l2_subdev *sd, *next; if (v4l2_dev == NULL) return; - if (v4l2_dev->dev) - dev_set_drvdata(v4l2_dev->dev, NULL); + v4l2_device_disconnect(v4l2_dev); + /* Unregister subdevs */ list_for_each_entry_safe(sd, next, &v4l2_dev->subdevs, list) v4l2_device_unregister_subdev(sd); - - v4l2_dev->dev = NULL; } EXPORT_SYMBOL_GPL(v4l2_device_unregister); -- cgit v1.2.3 From 9a4b796fec5b96cb6d0f637fc86983bb376c7628 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 14 Mar 2009 16:27:01 +0100 Subject: v4l2: call v4l2_device_disconnect in USB drivers. From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/usbvision/usbvision-video.c | 2 ++ linux/drivers/media/video/w9968cf.c | 4 +++- 2 files changed, 5 insertions(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/usbvision/usbvision-video.c b/linux/drivers/media/video/usbvision/usbvision-video.c index 3d400e4b7..74a7652de 100644 --- a/linux/drivers/media/video/usbvision/usbvision-video.c +++ b/linux/drivers/media/video/usbvision/usbvision-video.c @@ -1771,6 +1771,8 @@ static void __devexit usbvision_disconnect(struct usb_interface *intf) // At this time we ask to cancel outstanding URBs usbvision_stop_isoc(usbvision); + v4l2_device_disconnect(&usbvision->v4l2_dev); + if (usbvision->power) { usbvision_i2c_unregister(usbvision); usbvision_power_off(usbvision); diff --git a/linux/drivers/media/video/w9968cf.c b/linux/drivers/media/video/w9968cf.c index 0478ee33e..cf8548a7f 100644 --- a/linux/drivers/media/video/w9968cf.c +++ b/linux/drivers/media/video/w9968cf.c @@ -3571,7 +3571,9 @@ static void w9968cf_usb_disconnect(struct usb_interface* intf) cam->disconnected = 1; - DBG(2, "Disconnecting %s...", symbolic(camlist, cam->id)) + DBG(2, "Disconnecting %s...", symbolic(camlist, cam->id)); + + v4l2_device_disconnect(&cam->v4l2_dev); wake_up_interruptible_all(&cam->open); -- cgit v1.2.3 From c5b41e23cfa080a22b48bdf0e6e2a8028f340a70 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 14 Mar 2009 16:36:54 +0100 Subject: bttv: convert to v4l2_device. From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/bt8xx/dvb-bt8xx.c | 2 +- linux/drivers/media/video/bt8xx/bttv-driver.c | 47 ++++++++++++++++++--------- linux/drivers/media/video/bt8xx/bttv-i2c.c | 10 +++--- linux/drivers/media/video/bt8xx/bttv.h | 3 +- linux/drivers/media/video/bt8xx/bttvp.h | 5 +++ 5 files changed, 45 insertions(+), 22 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/bt8xx/dvb-bt8xx.c b/linux/drivers/media/dvb/bt8xx/dvb-bt8xx.c index c4b8b0677..08c63014c 100644 --- a/linux/drivers/media/dvb/bt8xx/dvb-bt8xx.c +++ b/linux/drivers/media/dvb/bt8xx/dvb-bt8xx.c @@ -815,7 +815,7 @@ static int __devinit dvb_bt8xx_probe(struct bttv_sub_device *sub) mutex_init(&card->lock); card->bttv_nr = sub->core->nr; - strncpy(card->card_name, sub->core->name, sizeof(sub->core->name)); + strlcpy(card->card_name, sub->core->v4l2_dev.name, sizeof(card->card_name)); card->i2c_adapter = &sub->core->i2c_adap; switch(sub->core->type) { diff --git a/linux/drivers/media/video/bt8xx/bttv-driver.c b/linux/drivers/media/video/bt8xx/bttv-driver.c index d34898f95..acb7b5e3d 100644 --- a/linux/drivers/media/video/bt8xx/bttv-driver.c +++ b/linux/drivers/media/video/bt8xx/bttv-driver.c @@ -171,7 +171,7 @@ static ssize_t show_card(struct class_device *cd, char *buf) #endif { struct video_device *vfd = container_of(cd, struct video_device, dev); - struct bttv *btv = dev_get_drvdata(vfd->parent); + struct bttv *btv = video_get_drvdata(vfd); return sprintf(buf, "%d\n", btv ? btv->c.type : UNSET); } #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19) @@ -3720,14 +3720,14 @@ static void bttv_risc_disasm(struct bttv *btv, unsigned int i,j,n; printk("%s: risc disasm: %p [dma=0x%08lx]\n", - btv->c.name, risc->cpu, (unsigned long)risc->dma); + btv->c.v4l2_dev.name, risc->cpu, (unsigned long)risc->dma); for (i = 0; i < (risc->size >> 2); i += n) { - printk("%s: 0x%lx: ", btv->c.name, + printk("%s: 0x%lx: ", btv->c.v4l2_dev.name, (unsigned long)(risc->dma + (i<<2))); n = bttv_risc_decode(le32_to_cpu(risc->cpu[i])); for (j = 1; j < n; j++) printk("%s: 0x%lx: 0x%08x [ arg #%d ]\n", - btv->c.name, (unsigned long)(risc->dma + ((i+j)<<2)), + btv->c.v4l2_dev.name, (unsigned long)(risc->dma + ((i+j)<<2)), risc->cpu[i+j], j); if (0 == risc->cpu[i]) break; @@ -4207,7 +4207,7 @@ static struct video_device *vdev_init(struct bttv *btv, return NULL; *vfd = *template; vfd->minor = -1; - vfd->parent = &btv->c.pci->dev; + vfd->v4l2_dev = &btv->c.v4l2_dev; vfd->release = video_device_release; vfd->debug = bttv_debug; video_set_drvdata(vfd, btv); @@ -4326,8 +4326,13 @@ static int __devinit bttv_probe(struct pci_dev *dev, return -ENOMEM; printk(KERN_INFO "bttv: Bt8xx card found (%d).\n", bttv_num); bttvs[bttv_num] = btv = kzalloc(sizeof(*btv), GFP_KERNEL); + if (btv == NULL) { + printk(KERN_ERR "bttv: out of memory.\n"); + return -ENOMEM; + } btv->c.nr = bttv_num; - sprintf(btv->c.name,"bttv%d",btv->c.nr); + snprintf(btv->c.v4l2_dev.name, sizeof(btv->c.v4l2_dev.name), + "bttv%d", btv->c.nr); /* initialize structs / fill in defaults */ mutex_init(&btv->lock); @@ -4364,7 +4369,7 @@ static int __devinit bttv_probe(struct pci_dev *dev, } if (!request_mem_region(pci_resource_start(dev,0), pci_resource_len(dev,0), - btv->c.name)) { + btv->c.v4l2_dev.name)) { printk(KERN_WARNING "bttv%d: can't request iomem (0x%llx).\n", btv->c.nr, (unsigned long long)pci_resource_start(dev,0)); @@ -4372,7 +4377,12 @@ static int __devinit bttv_probe(struct pci_dev *dev, } pci_set_master(dev); pci_set_command(dev); - pci_set_drvdata(dev,btv); + + result = v4l2_device_register(&dev->dev, &btv->c.v4l2_dev); + if (result < 0) { + printk(KERN_WARNING "bttv%d: v4l2_device_register() failed\n", btv->c.nr); + goto fail0; + } pci_read_config_byte(dev, PCI_CLASS_REVISION, &btv->revision); pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat); @@ -4396,7 +4406,7 @@ static int __devinit bttv_probe(struct pci_dev *dev, /* disable irqs, register irq handler */ btwrite(0, BT848_INT_MASK); result = request_irq(btv->c.pci->irq, bttv_irq, - IRQF_SHARED | IRQF_DISABLED,btv->c.name,(void *)btv); + IRQF_SHARED | IRQF_DISABLED, btv->c.v4l2_dev.name, (void *)btv); if (result < 0) { printk(KERN_ERR "bttv%d: can't get IRQ %d\n", bttv_num,btv->c.pci->irq); @@ -4480,21 +4490,24 @@ static int __devinit bttv_probe(struct pci_dev *dev, bttv_num++; return 0; - fail2: +fail2: free_irq(btv->c.pci->irq,btv); - fail1: +fail1: + v4l2_device_unregister(&btv->c.v4l2_dev); + +fail0: if (btv->bt848_mmio) iounmap(btv->bt848_mmio); release_mem_region(pci_resource_start(btv->c.pci,0), pci_resource_len(btv->c.pci,0)); - pci_set_drvdata(dev,NULL); return result; } static void __devexit bttv_remove(struct pci_dev *pci_dev) { - struct bttv *btv = pci_get_drvdata(pci_dev); + struct v4l2_device *v4l2_dev = pci_get_drvdata(pci_dev); + struct bttv *btv = to_bttv(v4l2_dev); if (bttv_verbose) printk("bttv%d: unloading\n",btv->c.nr); @@ -4528,7 +4541,7 @@ static void __devexit bttv_remove(struct pci_dev *pci_dev) release_mem_region(pci_resource_start(btv->c.pci,0), pci_resource_len(btv->c.pci,0)); - pci_set_drvdata(pci_dev, NULL); + v4l2_device_unregister(&btv->c.v4l2_dev); bttvs[btv->c.nr] = NULL; kfree(btv); @@ -4538,7 +4551,8 @@ static void __devexit bttv_remove(struct pci_dev *pci_dev) #ifdef CONFIG_PM static int bttv_suspend(struct pci_dev *pci_dev, pm_message_t state) { - struct bttv *btv = pci_get_drvdata(pci_dev); + struct v4l2_device *v4l2_dev = pci_get_drvdata(pci_dev); + struct bttv *btv = to_bttv(v4l2_dev); struct bttv_buffer_set idle; unsigned long flags; @@ -4573,7 +4587,8 @@ static int bttv_suspend(struct pci_dev *pci_dev, pm_message_t state) static int bttv_resume(struct pci_dev *pci_dev) { - struct bttv *btv = pci_get_drvdata(pci_dev); + struct v4l2_device *v4l2_dev = pci_get_drvdata(pci_dev); + struct bttv *btv = to_bttv(v4l2_dev); unsigned long flags; int err; diff --git a/linux/drivers/media/video/bt8xx/bttv-i2c.c b/linux/drivers/media/video/bt8xx/bttv-i2c.c index 3e7812c5a..c35f09cf4 100644 --- a/linux/drivers/media/video/bt8xx/bttv-i2c.c +++ b/linux/drivers/media/video/bt8xx/bttv-i2c.c @@ -231,7 +231,8 @@ bttv_i2c_readbytes(struct bttv *btv, const struct i2c_msg *msg, int last) static int bttv_i2c_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs, int num) { - struct bttv *btv = i2c_get_adapdata(i2c_adap); + struct v4l2_device *v4l2_dev = i2c_get_adapdata(i2c_adap); + struct bttv *btv = to_bttv(v4l2_dev); int retval = 0; int i; @@ -270,7 +271,8 @@ static const struct i2c_algorithm bttv_algo = { static int attach_inform(struct i2c_client *client) { - struct bttv *btv = i2c_get_adapdata(client->adapter); + struct v4l2_device *v4l2_dev = i2c_get_adapdata(client->adapter); + struct bttv *btv = to_bttv(v4l2_dev); int addr=ADDR_UNSET; @@ -430,7 +432,7 @@ int __devinit init_bttv_i2c(struct bttv *btv) "bt%d #%d [%s]", btv->id, btv->c.nr, btv->use_i2c_hw ? "hw" : "sw"); - i2c_set_adapdata(&btv->c.i2c_adap, btv); + i2c_set_adapdata(&btv->c.i2c_adap, &btv->c.v4l2_dev); btv->i2c_client.adapter = &btv->c.i2c_adap; if (bttv_tvcards[btv->c.type].no_video) @@ -446,7 +448,7 @@ int __devinit init_bttv_i2c(struct bttv *btv) btv->i2c_rc = i2c_bit_add_bus(&btv->c.i2c_adap); } if (0 == btv->i2c_rc && i2c_scan) - do_i2c_scan(btv->c.name,&btv->i2c_client); + do_i2c_scan(btv->c.v4l2_dev.name, &btv->i2c_client); return btv->i2c_rc; } diff --git a/linux/drivers/media/video/bt8xx/bttv.h b/linux/drivers/media/video/bt8xx/bttv.h index 93a1e989a..da7690fa8 100644 --- a/linux/drivers/media/video/bt8xx/bttv.h +++ b/linux/drivers/media/video/bt8xx/bttv.h @@ -17,6 +17,7 @@ #include #include #include "compat.h" +#include #include #include #include @@ -197,6 +198,7 @@ struct bttv_core { /* device structs */ + struct v4l2_device v4l2_dev; struct pci_dev *pci; struct i2c_adapter i2c_adap; struct list_head subs; /* struct bttv_sub_device */ @@ -204,7 +206,6 @@ struct bttv_core { /* device config */ unsigned int nr; /* dev nr (for printk("bttv%d: ..."); */ unsigned int type; /* card type (pointer into tvcards[]) */ - char name[8]; /* dev name */ }; struct bttv; diff --git a/linux/drivers/media/video/bt8xx/bttvp.h b/linux/drivers/media/video/bt8xx/bttvp.h index 113f28320..5915c261e 100644 --- a/linux/drivers/media/video/bt8xx/bttvp.h +++ b/linux/drivers/media/video/bt8xx/bttvp.h @@ -460,6 +460,11 @@ struct bttv { __s32 crop_start; }; +static inline struct bttv *to_bttv(struct v4l2_device *v4l2_dev) +{ + return container_of(v4l2_dev, struct bttv, c.v4l2_dev); +} + /* our devices */ #define BTTV_MAX 32 extern unsigned int bttv_num; -- cgit v1.2.3 From 98067ab29acca0eafb57f28d72ae299eb41d6642 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 14 Mar 2009 16:40:51 +0100 Subject: cx88: convert to v4l2_device. From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/cx88/cx88-cards.c | 8 ++++++++ linux/drivers/media/video/cx88/cx88-core.c | 4 +++- linux/drivers/media/video/cx88/cx88-i2c.c | 8 +++++--- linux/drivers/media/video/cx88/cx88.h | 8 +++++++- 4 files changed, 23 insertions(+), 5 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 b3d966ad5..719315d02 100644 --- a/linux/drivers/media/video/cx88/cx88-cards.c +++ b/linux/drivers/media/video/cx88/cx88-cards.c @@ -3171,7 +3171,15 @@ struct cx88_core *cx88_core_create(struct pci_dev *pci, int nr) core->nr = nr; sprintf(core->name, "cx88[%d]", core->nr); + + strcpy(core->v4l2_dev.name, core->name); + if (v4l2_device_register(NULL, &core->v4l2_dev)) { + kfree(core); + return NULL; + } + if (0 != cx88_get_resources(core, pci)) { + v4l2_device_unregister(&core->v4l2_dev); kfree(core); return NULL; } diff --git a/linux/drivers/media/video/cx88/cx88-core.c b/linux/drivers/media/video/cx88/cx88-core.c index c9de13b56..ca36a48fa 100644 --- a/linux/drivers/media/video/cx88/cx88-core.c +++ b/linux/drivers/media/video/cx88/cx88-core.c @@ -1040,7 +1040,8 @@ struct video_device *cx88_vdev_init(struct cx88_core *core, return NULL; *vfd = *template; vfd->minor = -1; - vfd->parent = &pci->dev; + vfd->v4l2_dev = &core->v4l2_dev; + vfd->parent = &pci->dev; vfd->release = video_device_release; snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)", core->name, type, core->board.name); @@ -1093,6 +1094,7 @@ void cx88_core_put(struct cx88_core *core, struct pci_dev *pci) iounmap(core->lmmio); cx88_devcount--; mutex_unlock(&devlist); + v4l2_device_unregister(&core->v4l2_dev); kfree(core); } diff --git a/linux/drivers/media/video/cx88/cx88-i2c.c b/linux/drivers/media/video/cx88/cx88-i2c.c index c0ff2305d..4a17a7579 100644 --- a/linux/drivers/media/video/cx88/cx88-i2c.c +++ b/linux/drivers/media/video/cx88/cx88-i2c.c @@ -99,7 +99,8 @@ static int cx8800_bit_getsda(void *data) static int attach_inform(struct i2c_client *client) { - struct cx88_core *core = i2c_get_adapdata(client->adapter); + struct v4l2_device *v4l2_dev = i2c_get_adapdata(client->adapter); + struct cx88_core *core = to_core(v4l2_dev); dprintk(1, "%s i2c attach [addr=0x%x,client=%s]\n", client->driver->driver.name, client->addr, client->name); @@ -108,7 +109,8 @@ static int attach_inform(struct i2c_client *client) static int detach_inform(struct i2c_client *client) { - struct cx88_core *core = i2c_get_adapdata(client->adapter); + struct v4l2_device *v4l2_dev = i2c_get_adapdata(client->adapter); + struct cx88_core *core = to_core(v4l2_dev); dprintk(1, "i2c detach [client=%s]\n", client->name); return 0; @@ -186,7 +188,7 @@ int cx88_i2c_init(struct cx88_core *core, struct pci_dev *pci) core->i2c_adap.client_unregister = detach_inform; core->i2c_algo.udelay = i2c_udelay; core->i2c_algo.data = core; - i2c_set_adapdata(&core->i2c_adap,core); + i2c_set_adapdata(&core->i2c_adap, &core->v4l2_dev); core->i2c_adap.algo_data = &core->i2c_algo; core->i2c_client.adapter = &core->i2c_adap; strlcpy(core->i2c_client.name, "cx88xx internal", I2C_NAME_SIZE); diff --git a/linux/drivers/media/video/cx88/cx88.h b/linux/drivers/media/video/cx88/cx88.h index 1372d2b7b..d70e26000 100644 --- a/linux/drivers/media/video/cx88/cx88.h +++ b/linux/drivers/media/video/cx88/cx88.h @@ -25,7 +25,7 @@ #include #include -#include +#include #include #include #include @@ -331,6 +331,7 @@ struct cx88_core { u32 i2c_state, i2c_rc; /* config info -- analog */ + struct v4l2_device v4l2_dev; unsigned int boardnr; struct cx88_board board; @@ -369,6 +370,11 @@ struct cx88_core { int active_fe_id; }; +static inline struct cx88_core *to_core(struct v4l2_device *v4l2_dev) +{ + return container_of(v4l2_dev, struct cx88_core, v4l2_dev); +} + struct cx8800_dev; struct cx8802_dev; -- cgit v1.2.3 From 8cbd6527524b2013a34446961953e5424bc7f764 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 14 Mar 2009 16:53:37 +0100 Subject: zoran: fix incorrect return type of notify function. From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/zoran/zoran_card.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/zoran/zoran_card.c b/linux/drivers/media/video/zoran/zoran_card.c index 29007f9b5..b7dea2b8a 100644 --- a/linux/drivers/media/video/zoran/zoran_card.c +++ b/linux/drivers/media/video/zoran/zoran_card.c @@ -1197,7 +1197,7 @@ zoran_setup_videocodec (struct zoran *zr, return m; } -static int zoran_subdev_notify(struct v4l2_subdev *sd, unsigned int cmd, void *arg) +static void zoran_subdev_notify(struct v4l2_subdev *sd, unsigned int cmd, void *arg) { struct zoran *zr = to_zoran(sd->v4l2_dev); @@ -1207,7 +1207,6 @@ static int zoran_subdev_notify(struct v4l2_subdev *sd, unsigned int cmd, void *a GPIO(zr, 7, 0); else if (cmd == BT819_FIFO_RESET_HIGH) GPIO(zr, 7, 1); - return 0; } /* -- cgit v1.2.3 From 33e7070c615213cf08bf653358d2cc64696a3a1c Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Sat, 14 Mar 2009 12:09:04 -0500 Subject: pvrusb2: Add sub-device for demod From: Mike Isely Forgot to include the tda9887 component when moving to v4l2-subdev. I got fooled because its name is "tuner", the same as the tuner module. Silly me. Priority: normal Signed-off-by: Mike Isely --- linux/drivers/media/video/pvrusb2/pvrusb2-devattr.c | 2 ++ linux/drivers/media/video/pvrusb2/pvrusb2-devattr.h | 1 + linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c | 2 ++ 3 files changed, 5 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-devattr.c b/linux/drivers/media/video/pvrusb2/pvrusb2-devattr.c index e6c876f3a..7483c1746 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-devattr.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-devattr.c @@ -50,6 +50,7 @@ static const struct pvr2_device_client_desc pvr2_cli_29xxx[] = { { .module_id = PVR2_CLIENT_ID_SAA7115 }, { .module_id = PVR2_CLIENT_ID_MSP3400 }, { .module_id = PVR2_CLIENT_ID_TUNER }, + { .module_id = PVR2_CLIENT_ID_DEMOD }, }; static const char *pvr2_fw1_names_29xxx[] = { @@ -81,6 +82,7 @@ static const struct pvr2_device_client_desc pvr2_cli_24xxx[] = { { .module_id = PVR2_CLIENT_ID_CX25840 }, { .module_id = PVR2_CLIENT_ID_TUNER }, { .module_id = PVR2_CLIENT_ID_WM8775 }, + { .module_id = PVR2_CLIENT_ID_DEMOD }, }; static const char *pvr2_fw1_names_24xxx[] = { diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-devattr.h b/linux/drivers/media/video/pvrusb2/pvrusb2-devattr.h index ed9cdedcc..13a59c4f9 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-devattr.h +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-devattr.h @@ -40,6 +40,7 @@ #define PVR2_CLIENT_ID_TUNER 4 #define PVR2_CLIENT_ID_CS53L32A 5 #define PVR2_CLIENT_ID_WM8775 6 +#define PVR2_CLIENT_ID_DEMOD 7 struct pvr2_device_client_desc { /* One ovr PVR2_CLIENT_ID_xxxx */ diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c index 1ecca14c7..3edc34b2e 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -124,6 +124,7 @@ static const char *module_names[] = { [PVR2_CLIENT_ID_CX25840] = "cx25840", [PVR2_CLIENT_ID_SAA7115] = "saa7115", [PVR2_CLIENT_ID_TUNER] = "tuner", + [PVR2_CLIENT_ID_DEMOD] = "tuner", [PVR2_CLIENT_ID_CS53L32A] = "cs53l32a", [PVR2_CLIENT_ID_WM8775] = "wm8775", }; @@ -131,6 +132,7 @@ static const char *module_names[] = { static const unsigned char *module_i2c_addresses[] = { [PVR2_CLIENT_ID_TUNER] = "\x60\x61\x62\x63", + [PVR2_CLIENT_ID_DEMOD] = "\x43", [PVR2_CLIENT_ID_MSP3400] = "\x40", [PVR2_CLIENT_ID_SAA7115] = "\x21", [PVR2_CLIENT_ID_WM8775] = "\x1b", -- cgit v1.2.3 From cefda1e7d13fcad67d398dbc8c5cc291e27084e0 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 14 Mar 2009 19:06:08 +0100 Subject: v4l-dvb: replace remaining references to the old mailinglist. From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/radio/radio-si470x.c | 2 +- linux/drivers/media/video/bt8xx/bttv-cards.c | 2 +- linux/drivers/media/video/usbvision/usbvision.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/radio/radio-si470x.c b/linux/drivers/media/radio/radio-si470x.c index a5ba4bf21..599fc0dcf 100644 --- a/linux/drivers/media/radio/radio-si470x.c +++ b/linux/drivers/media/radio/radio-si470x.c @@ -1714,7 +1714,7 @@ static int si470x_usb_driver_probe(struct usb_interface *intf, ": If you have some trouble using this driver,\n"); printk(KERN_WARNING DRIVER_NAME ": please report to V4L ML at " - "video4linux-list@redhat.com\n"); + "linux-media@vger.kernel.org\n"); } /* set initial frequency */ diff --git a/linux/drivers/media/video/bt8xx/bttv-cards.c b/linux/drivers/media/video/bt8xx/bttv-cards.c index 57448806c..40dac4b95 100644 --- a/linux/drivers/media/video/bt8xx/bttv-cards.c +++ b/linux/drivers/media/video/bt8xx/bttv-cards.c @@ -2953,7 +2953,7 @@ void __devinit bttv_idcard(struct bttv *btv) btv->c.nr, btv->cardid & 0xffff, (btv->cardid >> 16) & 0xffff); printk(KERN_DEBUG "please mail id, board name and " - "the correct card= insmod option to video4linux-list@redhat.com\n"); + "the correct card= insmod option to linux-media@vger.kernel.org\n"); } } diff --git a/linux/drivers/media/video/usbvision/usbvision.h b/linux/drivers/media/video/usbvision/usbvision.h index dc86c2139..42a926799 100644 --- a/linux/drivers/media/video/usbvision/usbvision.h +++ b/linux/drivers/media/video/usbvision/usbvision.h @@ -6,7 +6,7 @@ * Dwaine Garden * * - * Report problems to v4l MailingList : http://www.redhat.com/mailman/listinfo/video4linux-list + * Report problems to v4l MailingList: linux-media@vger.kernel.org * * This module is part of usbvision driver project. * Updates to driver completed by Dwaine P. Garden -- cgit v1.2.3 From 4903a08eff7b34a3ed5aff511ffcf25ee198c883 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 14 Mar 2009 20:34:07 +0100 Subject: bt819: fix compile error for old kernels. From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/bt819.c | 1 - 1 file changed, 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/bt819.c b/linux/drivers/media/video/bt819.c index ea4d0fbc4..b8c084acf 100644 --- a/linux/drivers/media/video/bt819.c +++ b/linux/drivers/media/video/bt819.c @@ -32,7 +32,6 @@ #include #include #include -#include #include #include #include -- cgit v1.2.3 From e78f2286ef0ab031e5141669487b2c6a90178eb9 Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Sat, 14 Mar 2009 19:03:26 -0400 Subject: cx18, ivtv: Ensure endianess for linemasks in VBI embedded in MPEG stream From: Andy Walls The sliced VBI payloads that cx18 and ivtv would insert in the MPEG stream did not have consistent endianess for the linemasks in the payload (a big endian platform would write them out big endian). This change ensures the linemasks are always stored as little-endian in the MPEG stream to ensure cross platform consistency in parsing the generated MPEG stream. Priority: normal Signed-off-by: Andy Walls --- linux/drivers/media/video/cx18/cx18-vbi.c | 2 ++ linux/drivers/media/video/ivtv/ivtv-vbi.c | 2 ++ 2 files changed, 4 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/cx18/cx18-vbi.c b/linux/drivers/media/video/cx18/cx18-vbi.c index 355737bff..99f9b2c86 100644 --- a/linux/drivers/media/video/cx18/cx18-vbi.c +++ b/linux/drivers/media/video/cx18/cx18-vbi.c @@ -88,6 +88,8 @@ static void copy_vbi_data(struct cx18 *cx, int lines, u32 pts_stamp) size = 4 + ((43 * line + 3) & ~3); } else { memcpy(dst + sd, "itv0", 4); + cpu_to_le32s(&linemask[0]); + cpu_to_le32s(&linemask[1]); memcpy(dst + sd + 4, &linemask[0], 8); size = 12 + ((43 * line + 3) & ~3); } diff --git a/linux/drivers/media/video/ivtv/ivtv-vbi.c b/linux/drivers/media/video/ivtv/ivtv-vbi.c index 5c5d1c462..f420d31b9 100644 --- a/linux/drivers/media/video/ivtv/ivtv-vbi.c +++ b/linux/drivers/media/video/ivtv/ivtv-vbi.c @@ -185,6 +185,8 @@ static void copy_vbi_data(struct ivtv *itv, int lines, u32 pts_stamp) size = 4 + ((43 * line + 3) & ~3); } else { memcpy(dst + sd, "itv0", 4); + cpu_to_le32s(&linemask[0]); + cpu_to_le32s(&linemask[1]); memcpy(dst + sd + 4, &linemask[0], 8); size = 12 + ((43 * line + 3) & ~3); } -- cgit v1.2.3 From 53c5d79124323a6862c2ec0f3c73edba4f35eb89 Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Sat, 14 Mar 2009 22:20:49 -0400 Subject: cx18: Optimize processing of VBI buffers from the capture unit From: Andy Walls Removed some unnecessary memcpy()'s by reworking the compress_*_vbi_buf() functions. Priority: normal Signed-off-by: Andy Walls --- linux/drivers/media/video/cx18/cx18-vbi.c | 103 ++++++++++++++---------------- 1 file changed, 49 insertions(+), 54 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/cx18/cx18-vbi.c b/linux/drivers/media/video/cx18/cx18-vbi.c index 99f9b2c86..c2aef4add 100644 --- a/linux/drivers/media/video/cx18/cx18-vbi.c +++ b/linux/drivers/media/video/cx18/cx18-vbi.c @@ -105,54 +105,72 @@ static void copy_vbi_data(struct cx18 *cx, int lines, u32 pts_stamp) /* Compress raw VBI format, removes leading SAV codes and surplus space after the frame. Returns new compressed size. */ -static u32 compress_raw_buf(struct cx18 *cx, u8 *buf, u32 size) +static u32 compress_raw_buf(struct cx18 *cx, u8 *buf, u32 size, u32 hdr_size) { u32 line_size = vbi_active_samples; u32 lines = cx->vbi.count * 2; - u8 sav1 = raw_vbi_sav_rp[0]; - u8 sav2 = raw_vbi_sav_rp[1]; u8 *q = buf; u8 *p; int i; + /* Skip the header */ + buf += hdr_size; + for (i = 0; i < lines; i++) { p = buf + i * line_size; /* Look for SAV code */ if (p[0] != 0xff || p[1] || p[2] || - (p[3] != sav1 && p[3] != sav2)) + (p[3] != raw_vbi_sav_rp[0] && + p[3] != raw_vbi_sav_rp[1])) break; - memcpy(q, p + 4, line_size - 4); - q += line_size - 4; + if (i == lines - 1) { + /* last line is hdr_size bytes short - extrapolate it */ + memcpy(q, p + 4, line_size - 4 - hdr_size); + q += line_size - 4 - hdr_size; + p += line_size - hdr_size - 1; + memset(q, (int) *p, hdr_size); + } else { + memcpy(q, p + 4, line_size - 4); + q += line_size - 4; + } } return lines * (line_size - 4); } - -/* Compressed VBI format, all found sliced blocks put next to one another - Returns new compressed size */ -static u32 compress_sliced_buf(struct cx18 *cx, u32 line, u8 *buf, - u32 size, u8 eav) +static u32 compress_sliced_buf(struct cx18 *cx, u8 *buf, u32 size, + const u32 hdr_size) { struct v4l2_decode_vbi_line vbi; int i; + u32 line = 0; u32 line_size = cx->is_60hz ? vbi_hblank_samples_60Hz : vbi_hblank_samples_50Hz; /* find the first valid line */ - for (i = 0; i < size; i++, buf++) { - if (buf[0] == 0xff && !buf[1] && !buf[2] && buf[3] == eav) + for (i = hdr_size, buf += hdr_size; i < size; i++, buf++) { + if (buf[0] == 0xff && !buf[1] && !buf[2] && + (buf[3] == sliced_vbi_eav_rp[0] || + buf[3] == sliced_vbi_eav_rp[1])) break; } - size -= i; + /* + * The last line is short by hdr_size bytes, but for the remaining + * checks against size, we pretend that it is not, by counting the + * header bytes we knowingly skipped + */ + size -= (i - hdr_size); if (size < line_size) return line; + for (i = 0; i < size / line_size; i++) { u8 *p = buf + i * line_size; /* Look for EAV code */ - if (p[0] != 0xff || p[1] || p[2] || p[3] != eav) + if (p[0] != 0xff || p[1] || p[2] || + (p[3] != sliced_vbi_eav_rp[0] && + p[3] != sliced_vbi_eav_rp[1])) continue; vbi.p = p + 4; v4l2_subdev_call(cx->sd_av, video, decode_vbi_line, &vbi); @@ -170,8 +188,17 @@ static u32 compress_sliced_buf(struct cx18 *cx, u32 line, u8 *buf, void cx18_process_vbi_data(struct cx18 *cx, struct cx18_buffer *buf, int streamtype) { + /* + * The CX23418 provides a 12 byte header in its raw VBI buffers to us: + * 0x3fffffff [4 bytes of something] [4 byte presentation time stamp] + */ + struct vbi_data_hdr { + __be32 magic; + __be32 unknown; + __be32 pts; + } *hdr = (struct vbi_data_hdr *) buf->buf; + u8 *p = (u8 *) buf->buf; - __be32 *q = (__be32 *) buf->buf; u32 size = buf->bytesused; u32 pts; int lines; @@ -182,32 +209,15 @@ void cx18_process_vbi_data(struct cx18 *cx, struct cx18_buffer *buf, /* * The CX23418 sends us data that is 32 bit little-endian swapped, * but we want the raw VBI bytes in the order they were in the raster - * line. This has a side effect of making the 12 byte header big endian + * line. This has a side effect of making the header big endian */ cx18_buf_swap(buf); - /* - * The CX23418 provides a 12 byte header in it's raw VBI buffers to us: - * 0x3fffffff [4 bytes of something] [4 byte presentation time stamp?] - */ - /* Raw VBI data */ if (cx18_raw_vbi(cx)) { - u8 type; - - /* - * We've set up to get a frame's worth of VBI data at a time. - * Skip 12 bytes of header prefixing the first field. - */ - size -= 12; - memcpy(p, &buf->buf[12], size); - type = p[3]; - /* Extrapolate the last 12 bytes of the frame's last line */ - memset(&p[size], (int) p[size - 1], 12); - size += 12; - - size = buf->bytesused = compress_raw_buf(cx, p, size); + size = buf->bytesused = + compress_raw_buf(cx, p, size, sizeof(struct vbi_data_hdr)); /* * Hack needed for compatibility with old VBI software. @@ -221,26 +231,11 @@ void cx18_process_vbi_data(struct cx18 *cx, struct cx18_buffer *buf, /* Sliced VBI data with data insertion */ - pts = (be32_to_cpu(q[0]) == 0x3fffffff) ? be32_to_cpu(q[2]) : 0; + pts = (be32_to_cpu(hdr->magic) == 0x3fffffff) ? be32_to_cpu(hdr->pts) + : 0; - /* - * For calls to compress_sliced_buf(), ensure there are an integral - * number of lines by shifting the real data up over the 12 bytes header - * that got stuffed in. - * FIXME - there's a smarter way to do this with pointers, but for some - * reason I can't get it to work correctly right now. - */ - memcpy(p, &buf->buf[12], size-12); + lines = compress_sliced_buf(cx, p, size, sizeof(struct vbi_data_hdr)); - /* first field */ - lines = compress_sliced_buf(cx, 0, p, size / 2, sliced_vbi_eav_rp[0]); - /* - * second field - * In case the second half does not always begin at the exact address, - * start a bit earlier (hence 32). - */ - lines = compress_sliced_buf(cx, lines, p + size / 2 - 32, - size / 2 + 32, sliced_vbi_eav_rp[1]); /* always return at least one empty line */ if (lines == 0) { cx->vbi.sliced_data[0].id = 0; -- cgit v1.2.3 From 2c783d535370caf906c325483998a842b5e0920a Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 15 Mar 2009 10:53:32 +0100 Subject: saa7134: set v4l2_dev field of video_device From: Hans Verkuil The v4l2_dev field of video_device wasn't initialized. The parent field is derived from v4l2_dev, so that doesn't need to be set anymore. Priority: normal Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/saa7134/saa7134-core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/saa7134/saa7134-core.c b/linux/drivers/media/video/saa7134/saa7134-core.c index d499064ee..b99b1ed1c 100644 --- a/linux/drivers/media/video/saa7134/saa7134-core.c +++ b/linux/drivers/media/video/saa7134/saa7134-core.c @@ -837,7 +837,7 @@ static struct video_device *vdev_init(struct saa7134_dev *dev, return NULL; *vfd = *template; vfd->minor = -1; - vfd->parent = &dev->pci->dev; + vfd->v4l2_dev = &dev->v4l2_dev; vfd->release = video_device_release; vfd->debug = video_debug; snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)", -- cgit v1.2.3 From f0878865f48611e7662e50450e128e8d046b646c Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 27 Mar 2009 14:16:57 -0300 Subject: siano: add high level SDIO interface driver for SMS based cards From: Uri Shkolnik This patch provides SDIO interface driver for SMS (Siano Mobile Silicon) based devices. The patch includes SMS high level SDIO driver and requires patching the kernel SDIO stack, those stack patches had been provided previously. I would like to thank Pierre Ossman, MMC maintainer, who wrote this driver. Priority: low Signed-off-by: Pierre Ossman Signed-off-by: Uri Shkolnik Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/siano/smssdio.c | 356 ++++++++++++++++++++++++++++++++ 1 file changed, 356 insertions(+) create mode 100644 linux/drivers/media/dvb/siano/smssdio.c (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/siano/smssdio.c b/linux/drivers/media/dvb/siano/smssdio.c new file mode 100644 index 000000000..31ba8c5af --- /dev/null +++ b/linux/drivers/media/dvb/siano/smssdio.c @@ -0,0 +1,356 @@ +/* + * smssdio.c - Siano 1xxx SDIO interface driver + * + * Copyright 2008 Pierre Ossman + * + * Based on code by Siano Mobile Silicon, Inc., + * Copyright (C) 2006-2008, Uri Shkolnik + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * + * This hardware is a bit odd in that all transfers should be done + * to/from the SMSSDIO_DATA register, yet the "increase address" bit + * always needs to be set. + * + * Also, buffers from the card are always aligned to 128 byte + * boundaries. + */ + +/* + * General cleanup notes: + * + * - only typedefs should be name *_t + * + * - use ERR_PTR and friends for smscore_register_device() + * + * - smscore_getbuffer should zero fields + * + * Fix stop command + */ + +#include +#include +#include +#include +#include +#include + +#include "smscoreapi.h" +#include "sms-cards.h" + +/* Registers */ + +#define SMSSDIO_DATA 0x00 +#define SMSSDIO_INT 0x04 + +static const struct sdio_device_id smssdio_ids[] = { + {SDIO_DEVICE(SDIO_VENDOR_ID_SIANO, SDIO_DEVICE_ID_SIANO_STELLAR), + .driver_data = SMS1XXX_BOARD_SIANO_STELLAR}, + {SDIO_DEVICE(SDIO_VENDOR_ID_SIANO, SDIO_DEVICE_ID_SIANO_NOVA_A0), + .driver_data = SMS1XXX_BOARD_SIANO_NOVA_A}, + {SDIO_DEVICE(SDIO_VENDOR_ID_SIANO, SDIO_DEVICE_ID_SIANO_NOVA_B0), + .driver_data = SMS1XXX_BOARD_SIANO_NOVA_B}, + {SDIO_DEVICE(SDIO_VENDOR_ID_SIANO, SDIO_DEVICE_ID_SIANO_VEGA_A0), + .driver_data = SMS1XXX_BOARD_SIANO_VEGA}, + {SDIO_DEVICE(SDIO_VENDOR_ID_SIANO, SDIO_DEVICE_ID_SIANO_VENICE), + .driver_data = SMS1XXX_BOARD_SIANO_VEGA}, + { /* end: all zeroes */ }, +}; + +MODULE_DEVICE_TABLE(sdio, smssdio_ids); + +struct smssdio_device { + struct sdio_func *func; + + struct smscore_device_t *coredev; + + struct smscore_buffer_t *split_cb; +}; + +/*******************************************************************/ +/* Siano core callbacks */ +/*******************************************************************/ + +static int smssdio_sendrequest(void *context, void *buffer, size_t size) +{ + int ret; + struct smssdio_device *smsdev; + + smsdev = context; + + sdio_claim_host(smsdev->func); + + while (size >= smsdev->func->cur_blksize) { + ret = sdio_write_blocks(smsdev->func, SMSSDIO_DATA, buffer, 1); + if (ret) + goto out; + + buffer += smsdev->func->cur_blksize; + size -= smsdev->func->cur_blksize; + } + + if (size) { + ret = sdio_write_bytes(smsdev->func, SMSSDIO_DATA, + buffer, size); + if (ret) + goto out; + } + +out: + sdio_release_host(smsdev->func); + + return ret; +} + +/*******************************************************************/ +/* SDIO callbacks */ +/*******************************************************************/ + +static void smssdio_interrupt(struct sdio_func *func) +{ + int ret, isr; + + struct smssdio_device *smsdev; + struct smscore_buffer_t *cb; + struct SmsMsgHdr_ST *hdr; + size_t size; + + smsdev = sdio_get_drvdata(func); + + /* + * The interrupt register has no defined meaning. It is just + * a way of turning of the level triggered interrupt. + */ + isr = sdio_readb(func, SMSSDIO_INT, &ret); + if (ret) { + dev_err(&smsdev->func->dev, + "Unable to read interrupt register!\n"); + return; + } + + if (smsdev->split_cb == NULL) { + cb = smscore_getbuffer(smsdev->coredev); + if (!cb) { + dev_err(&smsdev->func->dev, + "Unable to allocate data buffer!\n"); + return; + } + + ret = sdio_read_blocks(smsdev->func, cb->p, SMSSDIO_DATA, 1); + if (ret) { + dev_err(&smsdev->func->dev, + "Error %d reading initial block!\n", ret); + return; + } + + hdr = cb->p; + + if (hdr->msgFlags & MSG_HDR_FLAG_SPLIT_MSG) { + smsdev->split_cb = cb; + return; + } + + size = hdr->msgLength - smsdev->func->cur_blksize; + } else { + cb = smsdev->split_cb; + hdr = cb->p; + + size = hdr->msgLength - sizeof(struct SmsMsgHdr_ST); + + smsdev->split_cb = NULL; + } + + if (hdr->msgLength > smsdev->func->cur_blksize) { + void *buffer; + + size = ALIGN(size, 128); + buffer = cb->p + hdr->msgLength; + + BUG_ON(smsdev->func->cur_blksize != 128); + + /* + * First attempt to transfer all of it in one go... + */ + ret = sdio_read_blocks(smsdev->func, buffer, + SMSSDIO_DATA, size / 128); + if (ret && ret != -EINVAL) { + smscore_putbuffer(smsdev->coredev, cb); + dev_err(&smsdev->func->dev, + "Error %d reading data from card!\n", ret); + return; + } + + /* + * ..then fall back to one block at a time if that is + * not possible... + * + * (we have to do this manually because of the + * problem with the "increase address" bit) + */ + if (ret == -EINVAL) { + while (size) { + ret = sdio_read_blocks(smsdev->func, + buffer, SMSSDIO_DATA, 1); + if (ret) { + smscore_putbuffer(smsdev->coredev, cb); + dev_err(&smsdev->func->dev, + "Error %d reading " + "data from card!\n", ret); + return; + } + + buffer += smsdev->func->cur_blksize; + if (size > smsdev->func->cur_blksize) + size -= smsdev->func->cur_blksize; + else + size = 0; + } + } + } + + cb->size = hdr->msgLength; + cb->offset = 0; + + smscore_onresponse(smsdev->coredev, cb); +} + +static int smssdio_probe(struct sdio_func *func, + const struct sdio_device_id *id) +{ + int ret; + + int board_id; + struct smssdio_device *smsdev; + struct smsdevice_params_t params; + + board_id = id->driver_data; + + smsdev = kzalloc(sizeof(struct smssdio_device), GFP_KERNEL); + if (!smsdev) + return -ENOMEM; + + smsdev->func = func; + + memset(¶ms, 0, sizeof(struct smsdevice_params_t)); + + params.device = &func->dev; + params.buffer_size = 0x5000; /* ?? */ + params.num_buffers = 22; /* ?? */ + params.context = smsdev; + + snprintf(params.devpath, sizeof(params.devpath), + "sdio\\%s", sdio_func_id(func)); + + params.sendrequest_handler = smssdio_sendrequest; + + params.device_type = sms_get_board(board_id)->type; + + if (params.device_type != SMS_STELLAR) + params.flags |= SMS_DEVICE_FAMILY2; + else { + /* + * FIXME: Stellar needs special handling... + */ + ret = -ENODEV; + goto free; + } + + ret = smscore_register_device(¶ms, &smsdev->coredev); + if (ret < 0) + goto free; + + smscore_set_board_id(smsdev->coredev, board_id); + + sdio_claim_host(func); + + ret = sdio_enable_func(func); + if (ret) + goto release; + + ret = sdio_set_block_size(func, 128); + if (ret) + goto disable; + + ret = sdio_claim_irq(func, smssdio_interrupt); + if (ret) + goto disable; + + sdio_set_drvdata(func, smsdev); + + sdio_release_host(func); + + ret = smscore_start_device(smsdev->coredev); + if (ret < 0) + goto reclaim; + + return 0; + +reclaim: + sdio_claim_host(func); + sdio_release_irq(func); +disable: + sdio_disable_func(func); +release: + sdio_release_host(func); + smscore_unregister_device(smsdev->coredev); +free: + kfree(smsdev); + + return ret; +} + +static void smssdio_remove(struct sdio_func *func) +{ + struct smssdio_device *smsdev; + + smsdev = sdio_get_drvdata(func); + + /* FIXME: racy! */ + if (smsdev->split_cb) + smscore_putbuffer(smsdev->coredev, smsdev->split_cb); + + smscore_unregister_device(smsdev->coredev); + + sdio_claim_host(func); + sdio_release_irq(func); + sdio_disable_func(func); + sdio_release_host(func); + + kfree(smsdev); +} + +static struct sdio_driver smssdio_driver = { + .name = "smssdio", + .id_table = smssdio_ids, + .probe = smssdio_probe, + .remove = smssdio_remove, +}; + +/*******************************************************************/ +/* Module functions */ +/*******************************************************************/ + +int smssdio_register(void) +{ + int ret = 0; + + printk(KERN_INFO "smssdio: Siano SMS1xxx SDIO driver\n"); + printk(KERN_INFO "smssdio: Copyright Pierre Ossman\n"); + + ret = sdio_register_driver(&smssdio_driver); + + return ret; +} + +void smssdio_unregister(void) +{ + sdio_unregister_driver(&smssdio_driver); +} + +MODULE_DESCRIPTION("Siano SMS1xxx SDIO driver"); +MODULE_AUTHOR("Pierre Ossman"); +MODULE_LICENSE("GPL"); -- cgit v1.2.3 From 69bcabeaf801c5c21c31e534501c8b77769944b7 Mon Sep 17 00:00:00 2001 From: "Igor M. Liplianin" Date: Sun, 15 Mar 2009 13:28:45 +0300 Subject: Shorten some lines in stv0900 to less then 81 characters From: Igor M. Liplianin Signed-off-by: Igor M. Liplianin --- linux/drivers/media/dvb/frontends/stv0900_core.c | 41 ++++++++++++++++-------- 1 file changed, 28 insertions(+), 13 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/frontends/stv0900_core.c b/linux/drivers/media/dvb/frontends/stv0900_core.c index 1fde0e255..0cd313cd0 100644 --- a/linux/drivers/media/dvb/frontends/stv0900_core.c +++ b/linux/drivers/media/dvb/frontends/stv0900_core.c @@ -660,13 +660,18 @@ static s32 stv0900_carr_get_quality(struct dvb_frontend *fe, dprintk(KERN_INFO "%s\n", __func__); - dmd_reg(lock_flag_field, F0900_P1_LOCK_DEFINITIF, F0900_P2_LOCK_DEFINITIF); + dmd_reg(lock_flag_field, F0900_P1_LOCK_DEFINITIF, + F0900_P2_LOCK_DEFINITIF); if (stv0900_get_standard(fe, demod) == STV0900_DVBS2_STANDARD) { - dmd_reg(noise_field1, F0900_P1_NOSPLHT_NORMED1, F0900_P2_NOSPLHT_NORMED1); - dmd_reg(noise_field0, F0900_P1_NOSPLHT_NORMED0, F0900_P2_NOSPLHT_NORMED0); + dmd_reg(noise_field1, F0900_P1_NOSPLHT_NORMED1, + F0900_P2_NOSPLHT_NORMED1); + dmd_reg(noise_field0, F0900_P1_NOSPLHT_NORMED0, + F0900_P2_NOSPLHT_NORMED0); } else { - dmd_reg(noise_field1, F0900_P1_NOSDATAT_NORMED1, F0900_P2_NOSDATAT_NORMED1); - dmd_reg(noise_field0, F0900_P1_NOSDATAT_NORMED0, F0900_P1_NOSDATAT_NORMED0); + dmd_reg(noise_field1, F0900_P1_NOSDATAT_NORMED1, + F0900_P2_NOSDATAT_NORMED1); + dmd_reg(noise_field0, F0900_P1_NOSDATAT_NORMED0, + F0900_P1_NOSDATAT_NORMED0); } if (stv0900_get_bits(i_params, lock_flag_field)) { @@ -674,27 +679,34 @@ static s32 stv0900_carr_get_quality(struct dvb_frontend *fe, regval = 0; msleep(5); for (i = 0; i < 16; i++) { - regval += MAKEWORD(stv0900_get_bits(i_params, noise_field1), - stv0900_get_bits(i_params, noise_field0)); + regval += MAKEWORD(stv0900_get_bits(i_params, + noise_field1), + stv0900_get_bits(i_params, + noise_field0)); msleep(1); } regval /= 16; imin = 0; imax = lookup->size - 1; - if (INRANGE(lookup->table[imin].regval, regval, lookup->table[imax].regval)) { + if (INRANGE(lookup->table[imin].regval, + regval, + lookup->table[imax].regval)) { while ((imax - imin) > 1) { i = (imax + imin) >> 1; - - if (INRANGE(lookup->table[imin].regval, regval, lookup->table[i].regval)) + if (INRANGE(lookup->table[imin].regval, + regval, + lookup->table[i].regval)) imax = i; else imin = i; } c_n = ((regval - lookup->table[imin].regval) - * (lookup->table[imax].realval - lookup->table[imin].realval) - / (lookup->table[imax].regval - lookup->table[imin].regval)) + * (lookup->table[imax].realval + - lookup->table[imin].realval) + / (lookup->table[imax].regval + - lookup->table[imin].regval)) + lookup->table[imin].realval; } else if (regval < lookup->table[imin].regval) c_n = 1000; @@ -706,7 +718,10 @@ static s32 stv0900_carr_get_quality(struct dvb_frontend *fe, static int stv0900_read_snr(struct dvb_frontend *fe, u16 *snr) { - *snr = (16383 / 1030) * (30 + stv0900_carr_get_quality(fe, (const struct stv0900_table *)&stv0900_s2_cn)); + *snr = stv0900_carr_get_quality(fe, + (const struct stv0900_table *)&stv0900_s2_cn); + *snr += 30; + *snr *= (16383 / 1030); return 0; } -- cgit v1.2.3 From aebdd9e3f65e084f513eea41a8b37444f4e99cc6 Mon Sep 17 00:00:00 2001 From: "Igor M. Liplianin" Date: Sun, 15 Mar 2009 13:31:45 +0300 Subject: Fix typo in stv0900 From: Igor M. Liplianin Signed-off-by: Igor M. Liplianin --- linux/drivers/media/dvb/frontends/stv0900_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/frontends/stv0900_core.c b/linux/drivers/media/dvb/frontends/stv0900_core.c index 0cd313cd0..67cce764f 100644 --- a/linux/drivers/media/dvb/frontends/stv0900_core.c +++ b/linux/drivers/media/dvb/frontends/stv0900_core.c @@ -671,7 +671,7 @@ static s32 stv0900_carr_get_quality(struct dvb_frontend *fe, dmd_reg(noise_field1, F0900_P1_NOSDATAT_NORMED1, F0900_P2_NOSDATAT_NORMED1); dmd_reg(noise_field0, F0900_P1_NOSDATAT_NORMED0, - F0900_P1_NOSDATAT_NORMED0); + F0900_P2_NOSDATAT_NORMED0); } if (stv0900_get_bits(i_params, lock_flag_field)) { -- cgit v1.2.3 From daf697d13efd2ada0b4f50128adc6b8e88ff5252 Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Sun, 15 Mar 2009 16:38:47 -0400 Subject: au0828: remove memset calls in v4l2 routines. From: Devin Heitmueller The userland callers are responsible for clearing the output buffers, so remove the unneeded memset calls. Thanks to Mauro Carvalho Chehab for pointing this out. Priority: normal Signed-off-by: Devin Heitmueller --- linux/drivers/media/video/au0828/au0828-video.c | 8 +------- 1 file changed, 1 insertion(+), 7 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 72f2b67cb..5c590c52c 100644 --- a/linux/drivers/media/video/au0828/au0828-video.c +++ b/linux/drivers/media/video/au0828/au0828-video.c @@ -1022,7 +1022,6 @@ static int vidioc_querycap(struct file *file, void *priv, struct au0828_fh *fh = priv; struct au0828_dev *dev = fh->dev; - memset(cap, 0, sizeof(*cap)); strlcpy(cap->driver, "au0828", sizeof(cap->driver)); strlcpy(cap->card, dev->board.name, sizeof(cap->card)); strlcpy(cap->bus_info, dev->v4l2_dev.name, sizeof(cap->bus_info)); @@ -1047,14 +1046,12 @@ static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, if(f->index) return -EINVAL; - memset(f, 0, sizeof(*f)); f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; strcpy(f->description, "Packed YUV2"); f->flags = 0; f->pixelformat = V4L2_PIX_FMT_UYVY; - memset(f->reserved, 0, sizeof(f->reserved)); return 0; } @@ -1143,7 +1140,6 @@ static int vidioc_enum_input(struct file *file, void *priv, if(AUVI_INPUT(tmp).type == 0) return -EINVAL; - memset(input, 0, sizeof(*input)); input->index = tmp; strcpy(input->name, inames[AUVI_INPUT(tmp).type]); if((AUVI_INPUT(tmp).type == AU0828_VMUX_TELEVISION) || @@ -1241,7 +1237,6 @@ static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a) if(a->index > 1) return -EINVAL; - memset(a, 0, sizeof(*a)); index = dev->ctrl_ainput; if(index == 0) strcpy(a->name, "Television"); @@ -1290,7 +1285,6 @@ static int vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t) if(t->index != 0) return -EINVAL; - memset(t, 0, sizeof(*t)); strcpy(t->name, "Auvitek tuner"); au0828_call_i2c_clients(dev, VIDIOC_G_TUNER, t); @@ -1319,7 +1313,7 @@ static int vidioc_g_frequency(struct file *file, void *priv, { struct au0828_fh *fh = priv; struct au0828_dev *dev = fh->dev; - memset(freq, 0, sizeof(*freq)); + freq->type = V4L2_TUNER_ANALOG_TV; freq->frequency = dev->ctrl_freq; return 0; -- cgit v1.2.3 From 62a832506f2df93526288be35218f3d33be7acb3 Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Sun, 15 Mar 2009 16:43:13 -0400 Subject: au0828: remove some unneeded braces From: Devin Heitmueller There were some braces left behind from when there was more code in the block. Remove it. Thanks to Mauro Carvalho Chehab for pointing this out. Priority: normal Signed-off-by: Devin Heitmueller --- linux/drivers/media/video/au0828/au0828-video.c | 10 +++------- 1 file changed, 3 insertions(+), 7 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 5c590c52c..8c5e4fae1 100644 --- a/linux/drivers/media/video/au0828/au0828-video.c +++ b/linux/drivers/media/video/au0828/au0828-video.c @@ -1178,22 +1178,18 @@ static int vidioc_s_input(struct file *file, void *priv, unsigned int index) switch(AUVI_INPUT(index).type) { case AU0828_VMUX_SVIDEO: - { dev->input_type = AU0828_VMUX_SVIDEO; break; - } case AU0828_VMUX_COMPOSITE: - { dev->input_type = AU0828_VMUX_COMPOSITE; break; - } case AU0828_VMUX_TELEVISION: - { dev->input_type = AU0828_VMUX_TELEVISION; break; - } default: - ; + dprintk(1, "VIDIOC_S_INPUT unknown input type set [%d]\n", + AUVI_INPUT(index).type); + break; } route.input = AUVI_INPUT(index).vmux; -- cgit v1.2.3 From 3cedac6c69ef6d18745b56f4d3e88c70b5559d5a Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Sun, 15 Mar 2009 16:48:26 -0400 Subject: au0828: add entry for undefined input type From: Devin Heitmueller For the sake of completeness, include the "undefined" input type enumeration, even though there is no path that can actually call it. Thanks to Mauro Carvalho Chehab for pointing this out. Priority: normal Signed-off-by: Devin Heitmueller --- linux/drivers/media/video/au0828/au0828-video.c | 1 + 1 file changed, 1 insertion(+) (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 8c5e4fae1..a525040fb 100644 --- a/linux/drivers/media/video/au0828/au0828-video.c +++ b/linux/drivers/media/video/au0828/au0828-video.c @@ -1125,6 +1125,7 @@ static int vidioc_enum_input(struct file *file, void *priv, unsigned int tmp; static const char *inames[] = { + [AU0828_VMUX_UNDEFINED] = "Undefined", [AU0828_VMUX_COMPOSITE] = "Composite", [AU0828_VMUX_SVIDEO] = "S-Video", [AU0828_VMUX_CABLE] = "Cable TV", -- cgit v1.2.3 From 7bf1b26abd6ac7e886d6a82096d7fd18957f6e7c Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Sun, 15 Mar 2009 15:53:29 -0500 Subject: pvrusb2: Add composite and s-video input support for OnAir devices From: Mike Isely Priority: normal Signed-off-by: Mike Isely --- .../drivers/media/video/pvrusb2/pvrusb2-cs53l32a.c | 96 ++++++++++++++++++++++ .../drivers/media/video/pvrusb2/pvrusb2-cs53l32a.h | 48 +++++++++++ .../drivers/media/video/pvrusb2/pvrusb2-devattr.c | 4 +- .../drivers/media/video/pvrusb2/pvrusb2-devattr.h | 1 + linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c | 2 + .../media/video/pvrusb2/pvrusb2-video-v4l.c | 11 +++ 6 files changed, 160 insertions(+), 2 deletions(-) create mode 100644 linux/drivers/media/video/pvrusb2/pvrusb2-cs53l32a.c create mode 100644 linux/drivers/media/video/pvrusb2/pvrusb2-cs53l32a.h (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-cs53l32a.c b/linux/drivers/media/video/pvrusb2/pvrusb2-cs53l32a.c new file mode 100644 index 000000000..932943bd7 --- /dev/null +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-cs53l32a.c @@ -0,0 +1,96 @@ +/* + * + * + * Copyright (C) 2005 Mike Isely + * Copyright (C) 2004 Aurelien Alleaume + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +/* + + This source file is specifically designed to interface with the + v4l-dvb cs53l32a module. + +*/ + +#include "pvrusb2-cs53l32a.h" + + +#include "pvrusb2-hdw-internal.h" +#include "pvrusb2-debug.h" +#include +#include +#include +#include +#include "compat.h" + +struct routing_scheme { + const int *def; + unsigned int cnt; +}; + + +static const int routing_scheme1[] = { + [PVR2_CVAL_INPUT_TV] = 2, /* 1 or 2 seems to work here */ + [PVR2_CVAL_INPUT_RADIO] = 2, + [PVR2_CVAL_INPUT_COMPOSITE] = 0, + [PVR2_CVAL_INPUT_SVIDEO] = 0, +}; + +static const struct routing_scheme routing_schemes[] = { + [PVR2_ROUTING_SCHEME_ONAIR] = { + .def = routing_scheme1, + .cnt = ARRAY_SIZE(routing_scheme1), + }, +}; + + +void pvr2_cs53l32a_subdev_update(struct pvr2_hdw *hdw, struct v4l2_subdev *sd) +{ + if (hdw->input_dirty || hdw->force_dirty) { + struct v4l2_routing route; + const struct routing_scheme *sp; + unsigned int sid = hdw->hdw_desc->signal_routing_scheme; + pvr2_trace(PVR2_TRACE_CHIPS, "subdev v4l2 set_input(%d)", + hdw->input_val); + if ((sid < ARRAY_SIZE(routing_schemes)) && + ((sp = routing_schemes + sid) != NULL) && + (hdw->input_val >= 0) && + (hdw->input_val < sp->cnt)) { + route.input = sp->def[hdw->input_val]; + } else { + pvr2_trace(PVR2_TRACE_ERROR_LEGS, + "*** WARNING *** subdev v4l2 set_input:" + " Invalid routing scheme (%u)" + " and/or input (%d)", + sid, hdw->input_val); + return; + } + route.output = 0; + sd->ops->audio->s_routing(sd, &route); + } +} + + +/* + Stuff for Emacs to see, in order to encourage consistent editing style: + *** Local Variables: *** + *** mode: c *** + *** fill-column: 70 *** + *** tab-width: 8 *** + *** c-basic-offset: 8 *** + *** End: *** + */ diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-cs53l32a.h b/linux/drivers/media/video/pvrusb2/pvrusb2-cs53l32a.h new file mode 100644 index 000000000..53ba548b7 --- /dev/null +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-cs53l32a.h @@ -0,0 +1,48 @@ +/* + * + * + * Copyright (C) 2005 Mike Isely + * Copyright (C) 2004 Aurelien Alleaume + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#ifndef __PVRUSB2_CS53L32A_H +#define __PVRUSB2_CS53L32A_H + +/* + + This module connects the pvrusb2 driver to the I2C chip level + driver which handles device video processing. This interface is + used internally by the driver; higher level code should only + interact through the interface provided by pvrusb2-hdw.h. + +*/ + + +#include "pvrusb2-hdw-internal.h" +void pvr2_cs53l32a_subdev_update(struct pvr2_hdw *, struct v4l2_subdev *); + +#endif /* __PVRUSB2_AUDIO_CS53L32A_H */ + +/* + Stuff for Emacs to see, in order to encourage consistent editing style: + *** Local Variables: *** + *** mode: c *** + *** fill-column: 70 *** + *** tab-width: 8 *** + *** c-basic-offset: 8 *** + *** End: *** + */ diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-devattr.c b/linux/drivers/media/video/pvrusb2/pvrusb2-devattr.c index 7483c1746..1cb6a260e 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-devattr.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-devattr.c @@ -205,7 +205,7 @@ static const struct pvr2_device_desc pvr2_device_onair_creator = { .flag_has_composite = !0, .flag_has_svideo = !0, .flag_digital_requires_cx23416 = !0, - .signal_routing_scheme = PVR2_ROUTING_SCHEME_HAUPPAUGE, + .signal_routing_scheme = PVR2_ROUTING_SCHEME_ONAIR, .digital_control_scheme = PVR2_DIGITAL_SCHEME_ONAIR, .default_std_mask = V4L2_STD_NTSC_M, #ifdef CONFIG_VIDEO_PVRUSB2_DVB @@ -265,7 +265,7 @@ static const struct pvr2_device_desc pvr2_device_onair_usb2 = { .flag_has_composite = !0, .flag_has_svideo = !0, .flag_digital_requires_cx23416 = !0, - .signal_routing_scheme = PVR2_ROUTING_SCHEME_HAUPPAUGE, + .signal_routing_scheme = PVR2_ROUTING_SCHEME_ONAIR, .digital_control_scheme = PVR2_DIGITAL_SCHEME_ONAIR, .default_std_mask = V4L2_STD_NTSC_M, #ifdef CONFIG_VIDEO_PVRUSB2_DVB diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-devattr.h b/linux/drivers/media/video/pvrusb2/pvrusb2-devattr.h index 13a59c4f9..3e553389c 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-devattr.h +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-devattr.h @@ -68,6 +68,7 @@ struct pvr2_string_table { #define PVR2_ROUTING_SCHEME_HAUPPAUGE 0 #define PVR2_ROUTING_SCHEME_GOTVIEW 1 +#define PVR2_ROUTING_SCHEME_ONAIR 2 #define PVR2_DIGITAL_SCHEME_NONE 0 #define PVR2_DIGITAL_SCHEME_HAUPPAUGE 1 diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c index 3edc34b2e..2e21181c3 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -38,6 +38,7 @@ #include "pvrusb2-wm8775.h" #include "pvrusb2-video-v4l.h" #include "pvrusb2-cx2584x-v4l.h" +#include "pvrusb2-cs53l32a.h" #include "pvrusb2-audio.h" #include "compat.h" @@ -117,6 +118,7 @@ static const pvr2_subdev_update_func pvr2_module_update_functions[] = { [PVR2_CLIENT_ID_SAA7115] = pvr2_saa7115_subdev_update, [PVR2_CLIENT_ID_MSP3400] = pvr2_msp3400_subdev_update, [PVR2_CLIENT_ID_CX25840] = pvr2_cx25840_subdev_update, + [PVR2_CLIENT_ID_CS53L32A] = pvr2_cs53l32a_subdev_update, }; static const char *module_names[] = { diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-video-v4l.c b/linux/drivers/media/video/pvrusb2/pvrusb2-video-v4l.c index 776f20f77..b29a42ef5 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-video-v4l.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-video-v4l.c @@ -55,11 +55,22 @@ static const int routing_scheme0[] = { [PVR2_CVAL_INPUT_SVIDEO] = SAA7115_SVIDEO2, }; +static const int routing_scheme1[] = { + [PVR2_CVAL_INPUT_TV] = SAA7115_COMPOSITE4, + [PVR2_CVAL_INPUT_RADIO] = SAA7115_COMPOSITE5, + [PVR2_CVAL_INPUT_COMPOSITE] = SAA7115_COMPOSITE3, + [PVR2_CVAL_INPUT_SVIDEO] = SAA7115_SVIDEO2, /* or SVIDEO0, it seems */ +}; + static const struct routing_scheme routing_schemes[] = { [PVR2_ROUTING_SCHEME_HAUPPAUGE] = { .def = routing_scheme0, .cnt = ARRAY_SIZE(routing_scheme0), }, + [PVR2_ROUTING_SCHEME_ONAIR] = { + .def = routing_scheme1, + .cnt = ARRAY_SIZE(routing_scheme1), + }, }; void pvr2_saa7115_subdev_update(struct pvr2_hdw *hdw, struct v4l2_subdev *sd) -- cgit v1.2.3 From 3381b31112a4b0a5321384bf4e339bc12a103731 Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Sun, 15 Mar 2009 17:48:52 -0400 Subject: au0828/au8522: Codingstyle fixes From: Devin Heitmueller Take a pass over all of the au0828/au8522 files and cleanup all the codingstyle issues. This patch does not make *any* functional change to the code. Priority: normal Signed-off-by: Devin Heitmueller --- linux/drivers/media/dvb/frontends/au8522_dig.c | 14 +- linux/drivers/media/video/au0828/au0828-cards.c | 24 ++- linux/drivers/media/video/au0828/au0828-i2c.c | 10 +- linux/drivers/media/video/au0828/au0828-video.c | 175 +++++++++--------- linux/drivers/media/video/au0828/au0828.h | 6 - linux/drivers/media/video/au8522_decoder.c | 233 ++++++++++++------------ 6 files changed, 226 insertions(+), 236 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/frontends/au8522_dig.c b/linux/drivers/media/dvb/frontends/au8522_dig.c index 27e2e0730..41aedcc99 100644 --- a/linux/drivers/media/dvb/frontends/au8522_dig.c +++ b/linux/drivers/media/dvb/frontends/au8522_dig.c @@ -36,16 +36,16 @@ static int debug; static LIST_HEAD(hybrid_tuner_instance_list); static DEFINE_MUTEX(au8522_list_mutex); -#define dprintk(arg...) do { \ - if (debug) \ - printk(arg); \ +#define dprintk(arg...)\ + do { if (debug)\ + printk(arg);\ } while (0) /* 16 bit registers, 8 bit values */ int au8522_writereg(struct au8522_state *state, u16 reg, u8 data) { int ret; - u8 buf [] = { (reg >> 8) | 0x80, reg & 0xff, data }; + u8 buf[] = { (reg >> 8) | 0x80, reg & 0xff, data }; struct i2c_msg msg = { .addr = state->config->demod_address, .flags = 0, .buf = buf, .len = 3 }; @@ -62,10 +62,10 @@ int au8522_writereg(struct au8522_state *state, u16 reg, u8 data) u8 au8522_readreg(struct au8522_state *state, u16 reg) { int ret; - u8 b0 [] = { (reg >> 8) | 0x40, reg & 0xff }; - u8 b1 [] = { 0 }; + u8 b0[] = { (reg >> 8) | 0x40, reg & 0xff }; + u8 b1[] = { 0 }; - struct i2c_msg msg [] = { + struct i2c_msg msg[] = { { .addr = state->config->demod_address, .flags = 0, .buf = b0, .len = 2 }, { .addr = state->config->demod_address, .flags = I2C_M_RD, diff --git a/linux/drivers/media/video/au0828/au0828-cards.c b/linux/drivers/media/video/au0828/au0828-cards.c index a12c92c03..1b48eb58a 100644 --- a/linux/drivers/media/video/au0828/au0828-cards.c +++ b/linux/drivers/media/video/au0828/au0828-cards.c @@ -150,13 +150,13 @@ static void hauppauge_eeprom(struct au0828_dev *dev, u8 *eeprom_data) /* Make sure we support the board model */ switch (tv.model) { case 72000: /* WinTV-HVR950q (Retail, IR, ATSC/QAM */ - case 72001: /* WinTV-HVR950q (Retail, IR, ATSC/QAM and basic analog video */ - case 72211: /* WinTV-HVR950q (OEM, IR, ATSC/QAM and basic analog video */ - case 72221: /* WinTV-HVR950q (OEM, IR, ATSC/QAM and basic analog video */ - case 72231: /* WinTV-HVR950q (OEM, IR, ATSC/QAM and basic analog video */ - case 72241: /* WinTV-HVR950q (OEM, No IR, ATSC/QAM and basic analog video */ - case 72251: /* WinTV-HVR950q (Retail, IR, ATSC/QAM and basic analog video */ - case 72301: /* WinTV-HVR850 (Retail, IR, ATSC and basic analog video */ + case 72001: /* WinTV-HVR950q (Retail, IR, ATSC/QAM and analog video */ + case 72211: /* WinTV-HVR950q (OEM, IR, ATSC/QAM and analog video */ + case 72221: /* WinTV-HVR950q (OEM, IR, ATSC/QAM and analog video */ + case 72231: /* WinTV-HVR950q (OEM, IR, ATSC/QAM and analog video */ + case 72241: /* WinTV-HVR950q (OEM, No IR, ATSC/QAM and analog video */ + case 72251: /* WinTV-HVR950q (Retail, IR, ATSC/QAM and analog video */ + case 72301: /* WinTV-HVR850 (Retail, IR, ATSC and analog video */ case 72500: /* WinTV-HVR950q (OEM, No IR, ATSC/QAM */ break; default: @@ -202,9 +202,8 @@ void au0828_card_setup(struct au0828_dev *dev) demod) */ sd = v4l2_i2c_new_subdev(&dev->i2c_adap, "au8522", "au8522", 0x8e >> 1); - if (sd == NULL) { - printk("analog subdev registration failure\n"); - } + if (sd == NULL) + printk(KERN_ERR "analog subdev registration failed\n"); } /* Setup tuners */ @@ -212,9 +211,8 @@ void au0828_card_setup(struct au0828_dev *dev) /* Load the tuner module, which does the attach */ sd = v4l2_i2c_new_subdev(&dev->i2c_adap, "tuner", "tuner", dev->board.tuner_addr); - if (sd == NULL) { - printk("analog tuner subdev registration failure\n"); - } + if (sd == NULL) + printk(KERN_ERR "tuner subdev registration fail\n"); tun_setup.mode_mask = mode_mask; tun_setup.type = dev->board.tuner_type; diff --git a/linux/drivers/media/video/au0828/au0828-i2c.c b/linux/drivers/media/video/au0828/au0828-i2c.c index 9f3818723..3f99b4153 100644 --- a/linux/drivers/media/video/au0828/au0828-i2c.c +++ b/linux/drivers/media/video/au0828/au0828-i2c.c @@ -146,11 +146,10 @@ static int i2c_sendbytes(struct i2c_adapter *i2c_adap, requires us to slow down the i2c clock until we have a better strategy (such as using the secondary i2c bus to do firmware loading */ - if ((msg->addr << 1) == 0xc2) { + if ((msg->addr << 1) == 0xc2) au0828_write(dev, REG_202, 0x40); - } else { + else au0828_write(dev, REG_202, 0x07); - } /* Hardware needs 8 bit addresses */ au0828_write(dev, REG_203, msg->addr << 1); @@ -224,11 +223,10 @@ static int i2c_readbytes(struct i2c_adapter *i2c_adap, requires us to slow down the i2c clock until we have a better strategy (such as using the secondary i2c bus to do firmware loading */ - if ((msg->addr << 1) == 0xc2) { + if ((msg->addr << 1) == 0xc2) au0828_write(dev, REG_202, 0x40); - } else { + else au0828_write(dev, REG_202, 0x07); - } /* Hardware needs 8 bit addresses */ au0828_write(dev, REG_203, msg->addr << 1); diff --git a/linux/drivers/media/video/au0828/au0828-video.c b/linux/drivers/media/video/au0828/au0828-video.c index a525040fb..82443d51e 100644 --- a/linux/drivers/media/video/au0828/au0828-video.c +++ b/linux/drivers/media/video/au0828/au0828-video.c @@ -32,7 +32,6 @@ #include #include #include -#include #include #include #include @@ -46,9 +45,6 @@ static DEFINE_MUTEX(au0828_sysfs_lock); #define AU0828_VERSION_CODE KERNEL_VERSION(0, 0, 1) -/* Forward declarations */ -void au0828_analog_stream_reset(struct au0828_dev *dev); - /* ------------------------------------------------------------------ Videobuf operations ------------------------------------------------------------------*/ @@ -107,12 +103,12 @@ static inline void print_err_status(struct au0828_dev *dev, static int check_dev(struct au0828_dev *dev) { if (dev->dev_state & DEV_DISCONNECTED) { - printk("v4l2 ioctl: device not present\n"); + printk(KERN_INFO "v4l2 ioctl: device not present\n"); return -ENODEV; } if (dev->dev_state & DEV_MISCONFIGURED) { - printk("v4l2 ioctl: device is misconfigured; " + printk(KERN_INFO "v4l2 ioctl: device is misconfigured; " "close and open it again\n"); return -EIO; } @@ -377,7 +373,7 @@ static void au0828_copy_video(struct au0828_dev *dev, if ((char *)startwrite + lencopy > (char *)outp + buf->vb.size) { - au0828_isocdbg("Overflow of %zi bytes past buffer end (2)\n", + au0828_isocdbg("Overflow %zi bytes past buf end (2)\n", ((char *)startwrite + lencopy) - ((char *)outp + buf->vb.size)); lencopy = remain = (char *)outp + buf->vb.size - @@ -393,9 +389,8 @@ static void au0828_copy_video(struct au0828_dev *dev, if (offset > 1440) { /* We have enough data to check for greenscreen */ - if (outp[0] < 0x60 && outp[1440] < 0x60) { + if (outp[0] < 0x60 && outp[1440] < 0x60) dev->greenscreen_detected = 1; - } } dma_q->pos += len; @@ -461,9 +456,9 @@ static inline int au0828_isoc_copy(struct au0828_dev *dev, struct urb *urb) continue; } - if (urb->iso_frame_desc[i].actual_length <= 0) { + if (urb->iso_frame_desc[i].actual_length <= 0) continue; - } + if (urb->iso_frame_desc[i].actual_length > dev->max_pkt_size) { au0828_isocdbg("packet bigger than packet size"); @@ -484,25 +479,23 @@ static inline int au0828_isoc_copy(struct au0828_dev *dev, struct urb *urb) if (buf != NULL) buffer_filled(dev, dma_q, buf); get_next_buf(dma_q, &buf); - if (buf == NULL) { + if (buf == NULL) outp = NULL; - } else + else outp = videobuf_to_vmalloc(&buf->vb); } if (buf != NULL) { - if (fbyte & 0x40) { + if (fbyte & 0x40) buf->top_field = 1; - } else { + else buf->top_field = 0; - } } dma_q->pos = 0; } - if (buf != NULL) { + if (buf != NULL) au0828_copy_video(dev, dma_q, buf, p, outp, len); - } } return rc; } @@ -570,7 +563,7 @@ buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb, if (VIDEOBUF_NEEDS_INIT == buf->vb.state) { rc = videobuf_iolock(vq, &buf->vb, NULL); if (rc < 0) { - printk("videobuf_iolock failed\n"); + printk(KERN_INFO "videobuf_iolock failed\n"); goto fail; } } @@ -583,7 +576,7 @@ buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb, AU0828_MAX_ISO_BUFS, dev->max_pkt_size, au0828_isoc_copy); if (rc < 0) { - printk("au0828_init_isoc failed\n"); + printk(KERN_INFO "au0828_init_isoc failed\n"); goto fail; } } @@ -685,11 +678,11 @@ static int au0828_stream_interrupt(struct au0828_dev *dev) int ret = 0; dev->stream_state = STREAM_INTERRUPT; - if(dev->dev_state == DEV_DISCONNECTED) + if (dev->dev_state == DEV_DISCONNECTED) return -ENODEV; - else if(ret) { + else if (ret) { dev->dev_state = DEV_MISCONFIGURED; - dprintk(1, "%s device is misconfigured!\n", __FUNCTION__); + dprintk(1, "%s device is misconfigured!\n", __func__); return ret; } return 0; @@ -757,23 +750,23 @@ static int au0828_v4l2_open(struct file *filp) list_for_each(list, &au0828_devlist) { h = list_entry(list, struct au0828_dev, au0828list); - if(h->vdev->minor == minor) { + if (h->vdev->minor == minor) { dev = h; type = V4L2_BUF_TYPE_VIDEO_CAPTURE; } #ifdef VBI_NOT_YET_WORKING - if(h->vbi_dev->minor == minor) { + if (h->vbi_dev->minor == minor) { dev = h; type = V4L2_BUF_TYPE_VBI_CAPTURE; } #endif } - if(NULL == dev) + if (NULL == dev) return -ENODEV; fh = kzalloc(sizeof(struct au0828_fh), GFP_KERNEL); - if(NULL == fh) { + if (NULL == fh) { dprintk(1, "Failed allocate au0828_fh struct!\n"); return -ENOMEM; } @@ -782,11 +775,11 @@ static int au0828_v4l2_open(struct file *filp) fh->dev = dev; filp->private_data = fh; - if(fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE && dev->users == 0) { + if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE && dev->users == 0) { /* set au0828 interface0 to AS5 here again */ ret = usb_set_interface(dev->usbdev, 0, 5); - if(ret < 0) { - printk("Au0828 can't set alt setting to 5!\n"); + if (ret < 0) { + printk(KERN_INFO "Au0828 can't set alternate to 5!\n"); return -EBUSY; } dev->width = NTSC_STD_W; @@ -825,11 +818,11 @@ static int au0828_v4l2_close(struct file *filp) if (res_check(fh)) res_free(fh); - if(dev->users == 1) { + if (dev->users == 1) { videobuf_stop(&fh->vb_vidq); videobuf_mmap_free(&fh->vb_vidq); - if(dev->dev_state & DEV_DISCONNECTED) { + if (dev->dev_state & DEV_DISCONNECTED) { au0828_analog_unregister(dev); mutex_unlock(&dev->lock); kfree(dev); @@ -843,8 +836,8 @@ static int au0828_v4l2_close(struct file *filp) /* When close the device, set the usb intf0 into alt0 to free USB bandwidth */ ret = usb_set_interface(dev->usbdev, 0, 0); - if(ret < 0) - printk("Au0828 can't set alt setting to 0!\n"); + if (ret < 0) + printk(KERN_INFO "Au0828 can't set alternate to 0!\n"); } kfree(fh); @@ -865,7 +858,7 @@ static ssize_t au0828_v4l2_read(struct file *filp, char __user *buf, if (rc < 0) return rc; - if(fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { + if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { mutex_lock(&dev->lock); rc = res_get(fh); mutex_unlock(&dev->lock); @@ -941,28 +934,25 @@ static int au0828_set_format(struct au0828_dev *dev, unsigned int cmd, maxheight = 480; #ifdef VBI_NOT_YET_WORKING - if(format->type == V4L2_BUF_TYPE_SLICED_VBI_CAPTURE) { + if (format->type == V4L2_BUF_TYPE_SLICED_VBI_CAPTURE) { dprintk(1, "VBI format set: to be supported!\n"); return 0; } - if(format->type == V4L2_BUF_TYPE_VBI_CAPTURE) { + if (format->type == V4L2_BUF_TYPE_VBI_CAPTURE) return 0; - } #endif - if(format->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { + if (format->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) return -EINVAL; - } /* If they are demanding a format other than the one we support, bail out (tvtime asks for UYVY and then retries with YUYV) */ - if (format->fmt.pix.pixelformat != V4L2_PIX_FMT_UYVY) { + if (format->fmt.pix.pixelformat != V4L2_PIX_FMT_UYVY) return -EINVAL; - } /* format->fmt.pix.width only support 720 and height 480 */ - if(width != 720) + if (width != 720) width = 720; - if(height != 480) + if (height != 480) height = 480; format->fmt.pix.width = width; @@ -973,7 +963,7 @@ static int au0828_set_format(struct au0828_dev *dev, unsigned int cmd, format->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; format->fmt.pix.field = V4L2_FIELD_INTERLACED; - if(cmd == VIDIOC_TRY_FMT) + if (cmd == VIDIOC_TRY_FMT) return 0; /* maybe set new image format, driver current only support 720*480 */ @@ -983,9 +973,10 @@ static int au0828_set_format(struct au0828_dev *dev, unsigned int cmd, dev->field_size = width * height; dev->bytesperline = width * 2; - if(dev->stream_state == STREAM_ON) { + if (dev->stream_state == STREAM_ON) { dprintk(1, "VIDIOC_SET_FMT: interrupting stream!\n"); - if((ret = au0828_stream_interrupt(dev))) { + ret = au0828_stream_interrupt(dev); + if (ret != 0) { dprintk(1, "error interrupting video stream!\n"); return ret; } @@ -993,8 +984,8 @@ static int au0828_set_format(struct au0828_dev *dev, unsigned int cmd, /* set au0828 interface0 to AS5 here again */ ret = usb_set_interface(dev->usbdev, 0, 5); - if(ret < 0) { - printk("Au0828 can't set alt setting to 5!\n"); + if (ret < 0) { + printk(KERN_INFO "Au0828 can't set alt setting to 5!\n"); return -EBUSY; } @@ -1043,7 +1034,7 @@ static int vidioc_querycap(struct file *file, void *priv, static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, struct v4l2_fmtdesc *f) { - if(f->index) + if (f->index) return -EINVAL; f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; @@ -1088,13 +1079,13 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, int rc; if (videobuf_queue_is_busy(&fh->vb_vidq)) { - printk("%s queue busy\n", __func__); + printk(KERN_INFO "%s queue busy\n", __func__); rc = -EBUSY; goto out; } if (dev->stream_on && !fh->stream_on) { - printk("%s device in use by another fh\n", __func__); + printk(KERN_INFO "%s device in use by another fh\n", __func__); rc = -EBUSY; goto out; } @@ -1136,15 +1127,15 @@ static int vidioc_enum_input(struct file *file, void *priv, tmp = input->index; - if(tmp > AU0828_MAX_INPUT) + if (tmp > AU0828_MAX_INPUT) return -EINVAL; - if(AUVI_INPUT(tmp).type == 0) + if (AUVI_INPUT(tmp).type == 0) return -EINVAL; input->index = tmp; strcpy(input->name, inames[AUVI_INPUT(tmp).type]); - if((AUVI_INPUT(tmp).type == AU0828_VMUX_TELEVISION) || - (AUVI_INPUT(tmp).type == AU0828_VMUX_CABLE)) + if ((AUVI_INPUT(tmp).type == AU0828_VMUX_TELEVISION) || + (AUVI_INPUT(tmp).type == AU0828_VMUX_CABLE)) input->type |= V4L2_INPUT_TYPE_TUNER; else input->type |= V4L2_INPUT_TYPE_CAMERA; @@ -1169,15 +1160,15 @@ static int vidioc_s_input(struct file *file, void *priv, unsigned int index) int i; struct v4l2_routing route; - dprintk(1, "VIDIOC_S_INPUT in function %s, input=%d\n", __FUNCTION__, + dprintk(1, "VIDIOC_S_INPUT in function %s, input=%d\n", __func__, index); - if(index >= AU0828_MAX_INPUT) + if (index >= AU0828_MAX_INPUT) return -EINVAL; - if(AUVI_INPUT(index).type == 0) + if (AUVI_INPUT(index).type == 0) return -EINVAL; dev->ctrl_input = index; - switch(AUVI_INPUT(index).type) { + switch (AUVI_INPUT(index).type) { case AU0828_VMUX_SVIDEO: dev->input_type = AU0828_VMUX_SVIDEO; break; @@ -1199,9 +1190,8 @@ static int vidioc_s_input(struct file *file, void *priv, unsigned int index) for (i = 0; i < AU0828_MAX_INPUT; i++) { int enable = 0; - if (AUVI_INPUT(i).audio_setup == NULL) { + if (AUVI_INPUT(i).audio_setup == NULL) continue; - } if (i == index) enable = 1; @@ -1231,11 +1221,11 @@ static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a) struct au0828_dev *dev = fh->dev; unsigned int index = a->index; - if(a->index > 1) + if (a->index > 1) return -EINVAL; index = dev->ctrl_ainput; - if(index == 0) + if (index == 0) strcpy(a->name, "Television"); else strcpy(a->name, "Line in"); @@ -1249,7 +1239,7 @@ static int vidioc_s_audio(struct file *file, void *priv, struct v4l2_audio *a) { struct au0828_fh *fh = priv; struct au0828_dev *dev = fh->dev; - if(a->index != dev->ctrl_ainput) + if (a->index != dev->ctrl_ainput) return -EINVAL; return 0; } @@ -1279,7 +1269,7 @@ static int vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t) struct au0828_fh *fh = priv; struct au0828_dev *dev = fh->dev; - if(t->index != 0) + if (t->index != 0) return -EINVAL; strcpy(t->name, "Auvitek tuner"); @@ -1294,7 +1284,7 @@ static int vidioc_s_tuner(struct file *file, void *priv, struct au0828_fh *fh = priv; struct au0828_dev *dev = fh->dev; - if(t->index != 0) + if (t->index != 0) return -EINVAL; t->type = V4L2_TUNER_ANALOG_TV; @@ -1322,9 +1312,9 @@ static int vidioc_s_frequency(struct file *file, void *priv, struct au0828_fh *fh = priv; struct au0828_dev *dev = fh->dev; - if(freq->tuner != 0) + if (freq->tuner != 0) return -EINVAL; - if(freq->type != V4L2_TUNER_ANALOG_TV) + if (freq->type != V4L2_TUNER_ANALOG_TV) return -EINVAL; dev->ctrl_freq = freq->frequency; @@ -1362,7 +1352,7 @@ static int vidioc_cropcap(struct file *file, void *priv, struct au0828_fh *fh = priv; struct au0828_dev *dev = fh->dev; - if(cc->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + if (cc->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) return -EINVAL; cc->bounds.left = 0; @@ -1426,14 +1416,14 @@ static int vidioc_streamoff(struct file *file, void *priv, if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { au0828_call_i2c_clients(dev, VIDIOC_STREAMOFF, &b); - if((ret = au0828_stream_interrupt(dev)) != 0) + ret = au0828_stream_interrupt(dev); + if (ret != 0) return ret; } for (i = 0; i < AU0828_MAX_INPUT; i++) { - if (AUVI_INPUT(i).audio_setup == NULL) { + if (AUVI_INPUT(i).audio_setup == NULL) continue; - } (AUVI_INPUT(i).audio_setup)(dev, 0); } @@ -1626,27 +1616,30 @@ int au0828_analog_register(struct au0828_dev *dev, /* set au0828 usb interface0 to as5 */ retval = usb_set_interface(dev->usbdev, - interface->cur_altsetting->desc.bInterfaceNumber, 5); + interface->cur_altsetting->desc.bInterfaceNumber, 5); if (retval != 0) { - printk("Failure setting usb interface0 to as5\n"); + printk(KERN_INFO "Failure setting usb interface0 to as5\n"); return retval; } /* Figure out which endpoint has the isoc interface */ iface_desc = interface->cur_altsetting; - for(i = 0; i < iface_desc->desc.bNumEndpoints; i++){ + for (i = 0; i < iface_desc->desc.bNumEndpoints; i++) { endpoint = &iface_desc->endpoint[i].desc; - if(((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN) && - ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_ISOC)){ + if (((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) + == USB_DIR_IN) && + ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) + == USB_ENDPOINT_XFER_ISOC)) { /* we find our isoc in endpoint */ u16 tmp = le16_to_cpu(endpoint->wMaxPacketSize); - dev->max_pkt_size = (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1); + dev->max_pkt_size = (tmp & 0x07ff) * + (((tmp & 0x1800) >> 11) + 1); dev->isoc_in_endpointaddr = endpoint->bEndpointAddress; } } - if(!(dev->isoc_in_endpointaddr)) { - printk("Could not locate isoc endpoint\n"); + if (!(dev->isoc_in_endpointaddr)) { + printk(KERN_INFO "Could not locate isoc endpoint\n"); kfree(dev); return -ENODEV; } @@ -1667,14 +1660,14 @@ int au0828_analog_register(struct au0828_dev *dev, /* allocate and fill v4l2 video struct */ dev->vdev = video_device_alloc(); - if(NULL == dev->vdev) { + if (NULL == dev->vdev) { dprintk(1, "Can't allocate video_device.\n"); return -ENOMEM; } #ifdef VBI_NOT_YET_WORKING dev->vbi_dev = video_device_alloc(); - if(NULL == dev->vbi_dev) { + if (NULL == dev->vbi_dev) { dprintk(1, "Can't allocate vbi_device.\n"); kfree(dev->vdev); return -ENOMEM; @@ -1683,14 +1676,12 @@ int au0828_analog_register(struct au0828_dev *dev, /* Fill the video capture device struct */ *dev->vdev = au0828_video_template; - dev->vdev->vfl_type = VID_TYPE_CAPTURE | VID_TYPE_TUNER; dev->vdev->parent = &dev->usbdev->dev; strcpy(dev->vdev->name, "au0828a video"); #ifdef VBI_NOT_YET_WORKING /* Setup the VBI device */ *dev->vbi_dev = au0828_video_template; - dev->vbi_dev->vfl_type = VFL_TYPE_VBI; dev->vbi_dev->parent = &dev->usbdev->dev; strcpy(dev->vbi_dev->name, "au0828a vbi"); #endif @@ -1698,8 +1689,10 @@ int au0828_analog_register(struct au0828_dev *dev, list_add_tail(&dev->au0828list, &au0828_devlist); /* Register the v4l2 device */ - if((retval = video_register_device(dev->vdev, VFL_TYPE_GRABBER, -1)) != 0) { - dprintk(1, "unable to register video device (error = %d).\n", retval); + retval = video_register_device(dev->vdev, VFL_TYPE_GRABBER, -1); + if (retval != 0) { + dprintk(1, "unable to register video device (error = %d).\n", + retval); list_del(&dev->au0828list); video_device_release(dev->vdev); return -ENODEV; @@ -1707,8 +1700,10 @@ int au0828_analog_register(struct au0828_dev *dev, #ifdef VBI_NOT_YET_WORKING /* Register the vbi device */ - if((retval = video_register_device(dev->vbi_dev, VFL_TYPE_VBI, -1)) != 0) { - dprintk(1, "unable to register vbi device (error = %d).\n", retval); + retval = video_register_device(dev->vbi_dev, VFL_TYPE_VBI, -1); + if (retval != 0) { + dprintk(1, "unable to register vbi device (error = %d).\n", + retval); list_del(&dev->au0828list); video_device_release(dev->vbi_dev); video_device_release(dev->vdev); @@ -1716,7 +1711,7 @@ int au0828_analog_register(struct au0828_dev *dev, } #endif - dprintk(1, "%s completed!\n", __FUNCTION__); + dprintk(1, "%s completed!\n", __func__); return 0; } diff --git a/linux/drivers/media/video/au0828/au0828.h b/linux/drivers/media/video/au0828/au0828.h index 876b18cfb..6d9bd454e 100644 --- a/linux/drivers/media/video/au0828/au0828.h +++ b/linux/drivers/media/video/au0828/au0828.h @@ -54,16 +54,10 @@ /* Defination for AU0828 USB transfer */ #define AU0828_MAX_ISO_BUFS 12 /* maybe resize this value in the future */ #define AU0828_ISO_PACKETS_PER_URB 10 -#define AU0828_ISO_MAX_FRAME_SIZE (3 * 1024) -#define AU0828_ISO_BUFFER_SIZE (AU0828_ISO_PACKETS_PER_URB * AU0828_ISO_MAX_FRAME_SIZE) #define AU0828_MIN_BUF 4 #define AU0828_DEF_BUF 8 -#define AU0828_MAX_IMAGES 10 -#define AU0828_FRAME_SIZE (1028 * 1024 * 4) -#define AU0828_URB_TIMEOUT msecs_to_jiffies(AU0828_MAX_ISO_BUFS * AU0828_ISO_PACKETS_PER_URB) - #define AU0828_MAX_INPUT 4 enum au0828_itype { diff --git a/linux/drivers/media/video/au8522_decoder.c b/linux/drivers/media/video/au8522_decoder.c index 93f119508..b4a205809 100644 --- a/linux/drivers/media/video/au8522_decoder.c +++ b/linux/drivers/media/video/au8522_decoder.c @@ -68,39 +68,40 @@ struct au8522_register_config { 0="ATV RF" 1="ATV RF13" 2="CVBS" 3="S-Video" 4="PAL" 5=CVBS13" 6="SVideo13" */ struct au8522_register_config filter_coef[] = { - {AU8522_FILTER_COEF_R410, {0x25, 0x00, 0x25, 0x25, 0x00, 0x00, 0x00}}, - {AU8522_FILTER_COEF_R411, {0x20, 0x00, 0x20, 0x20, 0x00, 0x00, 0x00}}, - {AU8522_FILTER_COEF_R412, {0x03, 0x00, 0x03, 0x03, 0x00, 0x00, 0x00}}, - {AU8522_FILTER_COEF_R413, {0xe6, 0x00, 0xe6, 0xe6, 0x00, 0x00, 0x00}}, - {AU8522_FILTER_COEF_R414, {0x40, 0x00, 0x40, 0x40, 0x00, 0x00, 0x00}}, - {AU8522_FILTER_COEF_R415, {0x1b, 0x00, 0x1b, 0x1b, 0x00, 0x00, 0x00}}, - {AU8522_FILTER_COEF_R416, {0xc0, 0x00, 0xc0, 0x04, 0x00, 0x00, 0x00}}, - {AU8522_FILTER_COEF_R417, {0x04, 0x00, 0x04, 0x04, 0x00, 0x00, 0x00}}, - {AU8522_FILTER_COEF_R418, {0x8c, 0x00, 0x8c, 0x8c, 0x00, 0x00, 0x00}}, - {AU8522_FILTER_COEF_R419, {0xa0, 0x40, 0xa0, 0xa0, 0x40, 0x40, 0x40}}, - {AU8522_FILTER_COEF_R41A, {0x21, 0x09, 0x21, 0x21, 0x09, 0x09, 0x09}}, - {AU8522_FILTER_COEF_R41B, {0x6c, 0x38, 0x6c, 0x6c, 0x38, 0x38, 0x38}}, - {AU8522_FILTER_COEF_R41C, {0x03, 0xff, 0x03, 0x03, 0xff, 0xff, 0xff}}, - {AU8522_FILTER_COEF_R41D, {0xbf, 0xc7, 0xbf, 0xbf, 0xc7, 0xc7, 0xc7}}, - {AU8522_FILTER_COEF_R41E, {0xa0, 0xdf, 0xa0, 0xa0, 0xdf, 0xdf, 0xdf}}, - {AU8522_FILTER_COEF_R41F, {0x10, 0x06, 0x10, 0x10, 0x06, 0x06, 0x06}}, - {AU8522_FILTER_COEF_R420, {0xae, 0x30, 0xae, 0xae, 0x30, 0x30, 0x30}}, - {AU8522_FILTER_COEF_R421, {0xc4, 0x01, 0xc4, 0xc4, 0x01, 0x01, 0x01}}, - {AU8522_FILTER_COEF_R422, {0x54, 0xdd, 0x54, 0x54, 0xdd, 0xdd, 0xdd}}, - {AU8522_FILTER_COEF_R423, {0xd0, 0xaf, 0xd0, 0xd0, 0xaf, 0xaf, 0xaf}}, - {AU8522_FILTER_COEF_R424, {0x1c, 0xf7, 0x1c, 0x1c, 0xf7, 0xf7, 0xf7}}, - {AU8522_FILTER_COEF_R425, {0x76, 0xdb, 0x76, 0x76, 0xdb, 0xdb, 0xdb}}, - {AU8522_FILTER_COEF_R426, {0x61, 0xc0, 0x61, 0x61, 0xc0, 0xc0, 0xc0}}, - {AU8522_FILTER_COEF_R427, {0xd1, 0x2f, 0xd1, 0xd1, 0x2f, 0x2f, 0x2f}}, - {AU8522_FILTER_COEF_R428, {0x84, 0xd8, 0x84, 0x84, 0xd8, 0xd8, 0xd8}}, - {AU8522_FILTER_COEF_R429, {0x06, 0xfb, 0x06, 0x06, 0xfb, 0xfb, 0xfb}}, - {AU8522_FILTER_COEF_R42A, {0x21, 0xd5, 0x21, 0x21, 0xd5, 0xd5, 0xd5}}, - {AU8522_FILTER_COEF_R42B, {0x0a, 0x3e, 0x0a, 0x0a, 0x3e, 0x3e, 0x3e}}, - {AU8522_FILTER_COEF_R42C, {0xe6, 0x15, 0xe6, 0xe6, 0x15, 0x15, 0x15}}, - {AU8522_FILTER_COEF_R42D, {0x01, 0x34, 0x01, 0x01, 0x34, 0x34, 0x34}}, + {AU8522_FILTER_COEF_R410, {0x25, 0x00, 0x25, 0x25, 0x00, 0x00, 0x00} }, + {AU8522_FILTER_COEF_R411, {0x20, 0x00, 0x20, 0x20, 0x00, 0x00, 0x00} }, + {AU8522_FILTER_COEF_R412, {0x03, 0x00, 0x03, 0x03, 0x00, 0x00, 0x00} }, + {AU8522_FILTER_COEF_R413, {0xe6, 0x00, 0xe6, 0xe6, 0x00, 0x00, 0x00} }, + {AU8522_FILTER_COEF_R414, {0x40, 0x00, 0x40, 0x40, 0x00, 0x00, 0x00} }, + {AU8522_FILTER_COEF_R415, {0x1b, 0x00, 0x1b, 0x1b, 0x00, 0x00, 0x00} }, + {AU8522_FILTER_COEF_R416, {0xc0, 0x00, 0xc0, 0x04, 0x00, 0x00, 0x00} }, + {AU8522_FILTER_COEF_R417, {0x04, 0x00, 0x04, 0x04, 0x00, 0x00, 0x00} }, + {AU8522_FILTER_COEF_R418, {0x8c, 0x00, 0x8c, 0x8c, 0x00, 0x00, 0x00} }, + {AU8522_FILTER_COEF_R419, {0xa0, 0x40, 0xa0, 0xa0, 0x40, 0x40, 0x40} }, + {AU8522_FILTER_COEF_R41A, {0x21, 0x09, 0x21, 0x21, 0x09, 0x09, 0x09} }, + {AU8522_FILTER_COEF_R41B, {0x6c, 0x38, 0x6c, 0x6c, 0x38, 0x38, 0x38} }, + {AU8522_FILTER_COEF_R41C, {0x03, 0xff, 0x03, 0x03, 0xff, 0xff, 0xff} }, + {AU8522_FILTER_COEF_R41D, {0xbf, 0xc7, 0xbf, 0xbf, 0xc7, 0xc7, 0xc7} }, + {AU8522_FILTER_COEF_R41E, {0xa0, 0xdf, 0xa0, 0xa0, 0xdf, 0xdf, 0xdf} }, + {AU8522_FILTER_COEF_R41F, {0x10, 0x06, 0x10, 0x10, 0x06, 0x06, 0x06} }, + {AU8522_FILTER_COEF_R420, {0xae, 0x30, 0xae, 0xae, 0x30, 0x30, 0x30} }, + {AU8522_FILTER_COEF_R421, {0xc4, 0x01, 0xc4, 0xc4, 0x01, 0x01, 0x01} }, + {AU8522_FILTER_COEF_R422, {0x54, 0xdd, 0x54, 0x54, 0xdd, 0xdd, 0xdd} }, + {AU8522_FILTER_COEF_R423, {0xd0, 0xaf, 0xd0, 0xd0, 0xaf, 0xaf, 0xaf} }, + {AU8522_FILTER_COEF_R424, {0x1c, 0xf7, 0x1c, 0x1c, 0xf7, 0xf7, 0xf7} }, + {AU8522_FILTER_COEF_R425, {0x76, 0xdb, 0x76, 0x76, 0xdb, 0xdb, 0xdb} }, + {AU8522_FILTER_COEF_R426, {0x61, 0xc0, 0x61, 0x61, 0xc0, 0xc0, 0xc0} }, + {AU8522_FILTER_COEF_R427, {0xd1, 0x2f, 0xd1, 0xd1, 0x2f, 0x2f, 0x2f} }, + {AU8522_FILTER_COEF_R428, {0x84, 0xd8, 0x84, 0x84, 0xd8, 0xd8, 0xd8} }, + {AU8522_FILTER_COEF_R429, {0x06, 0xfb, 0x06, 0x06, 0xfb, 0xfb, 0xfb} }, + {AU8522_FILTER_COEF_R42A, {0x21, 0xd5, 0x21, 0x21, 0xd5, 0xd5, 0xd5} }, + {AU8522_FILTER_COEF_R42B, {0x0a, 0x3e, 0x0a, 0x0a, 0x3e, 0x3e, 0x3e} }, + {AU8522_FILTER_COEF_R42C, {0xe6, 0x15, 0xe6, 0xe6, 0x15, 0x15, 0x15} }, + {AU8522_FILTER_COEF_R42D, {0x01, 0x34, 0x01, 0x01, 0x34, 0x34, 0x34} }, }; -#define NUM_FILTER_COEF (sizeof (filter_coef) / sizeof(struct au8522_register_config)) +#define NUM_FILTER_COEF (sizeof(filter_coef)\ + / sizeof(struct au8522_register_config)) /* Registers 0x060b through 0x0652 are the LP Filter coefficients @@ -109,80 +110,81 @@ struct au8522_register_config filter_coef[] = { Note: the "ATVRF/ATVRF13" mode has never been tested */ struct au8522_register_config lpfilter_coef[] = { - {0x060b, {0x21, 0x0b}}, - {0x060c, {0xad, 0xad}}, - {0x060d, {0x70, 0xf0}}, - {0x060e, {0xea, 0xe9}}, - {0x060f, {0xdd, 0xdd}}, - {0x0610, {0x08, 0x64}}, - {0x0611, {0x60, 0x60}}, - {0x0612, {0xf8, 0xb2}}, - {0x0613, {0x01, 0x02}}, - {0x0614, {0xe4, 0xb4}}, - {0x0615, {0x19, 0x02}}, - {0x0616, {0xae, 0x2e}}, - {0x0617, {0xee, 0xc5}}, - {0x0618, {0x56, 0x56}}, - {0x0619, {0x30, 0x58}}, - {0x061a, {0xf9, 0xf8}}, - {0x061b, {0x24, 0x64}}, - {0x061c, {0x07, 0x07}}, - {0x061d, {0x30, 0x30}}, - {0x061e, {0xa9, 0xed}}, - {0x061f, {0x09, 0x0b}}, - {0x0620, {0x42, 0xc2}}, - {0x0621, {0x1d, 0x2a}}, - {0x0622, {0xd6, 0x56}}, - {0x0623, {0x95, 0x8b}}, - {0x0624, {0x2b, 0x2b}}, - {0x0625, {0x30, 0x24}}, - {0x0626, {0x3e, 0x3e}}, - {0x0627, {0x62, 0xe2}}, - {0x0628, {0xe9, 0xf5}}, - {0x0629, {0x99, 0x19}}, - {0x062a, {0xd4, 0x11}}, - {0x062b, {0x03, 0x04}}, - {0x062c, {0xb5, 0x85}}, - {0x062d, {0x1e, 0x20}}, - {0x062e, {0x2a, 0xea}}, - {0x062f, {0xd7, 0xd2}}, - {0x0630, {0x15, 0x15}}, - {0x0631, {0xa3, 0xa9}}, - {0x0632, {0x1f, 0x1f}}, - {0x0633, {0xf9, 0xd1}}, - {0x0634, {0xc0, 0xc3}}, - {0x0635, {0x4d, 0x8d}}, - {0x0636, {0x21, 0x31}}, - {0x0637, {0x83, 0x83}}, - {0x0638, {0x08, 0x8c}}, - {0x0639, {0x19, 0x19}}, - {0x063a, {0x45, 0xa5}}, - {0x063b, {0xef, 0xec}}, - {0x063c, {0x8a, 0x8a}}, - {0x063d, {0xf4, 0xf6}}, - {0x063e, {0x8f, 0x8f}}, - {0x063f, {0x44, 0x0c}}, - {0x0640, {0xef, 0xf0}}, - {0x0641, {0x66, 0x66}}, - {0x0642, {0xcc, 0xd2}}, - {0x0643, {0x41, 0x41}}, - {0x0644, {0x63, 0x93}}, - {0x0645, {0x8e, 0x8e}}, - {0x0646, {0xa2, 0x42}}, - {0x0647, {0x7b, 0x7b}}, - {0x0648, {0x04, 0x04}}, - {0x0649, {0x00, 0x00}}, - {0x064a, {0x40, 0x40}}, - {0x064b, {0x8c, 0x98}}, - {0x064c, {0x00, 0x00}}, - {0x064d, {0x63, 0xc3}}, - {0x064e, {0x04, 0x04}}, - {0x064f, {0x20, 0x20}}, - {0x0650, {0x00, 0x00}}, - {0x0651, {0x40 ,0x40}}, - {0x0652, {0x01, 0x01}}, + {0x060b, {0x21, 0x0b} }, + {0x060c, {0xad, 0xad} }, + {0x060d, {0x70, 0xf0} }, + {0x060e, {0xea, 0xe9} }, + {0x060f, {0xdd, 0xdd} }, + {0x0610, {0x08, 0x64} }, + {0x0611, {0x60, 0x60} }, + {0x0612, {0xf8, 0xb2} }, + {0x0613, {0x01, 0x02} }, + {0x0614, {0xe4, 0xb4} }, + {0x0615, {0x19, 0x02} }, + {0x0616, {0xae, 0x2e} }, + {0x0617, {0xee, 0xc5} }, + {0x0618, {0x56, 0x56} }, + {0x0619, {0x30, 0x58} }, + {0x061a, {0xf9, 0xf8} }, + {0x061b, {0x24, 0x64} }, + {0x061c, {0x07, 0x07} }, + {0x061d, {0x30, 0x30} }, + {0x061e, {0xa9, 0xed} }, + {0x061f, {0x09, 0x0b} }, + {0x0620, {0x42, 0xc2} }, + {0x0621, {0x1d, 0x2a} }, + {0x0622, {0xd6, 0x56} }, + {0x0623, {0x95, 0x8b} }, + {0x0624, {0x2b, 0x2b} }, + {0x0625, {0x30, 0x24} }, + {0x0626, {0x3e, 0x3e} }, + {0x0627, {0x62, 0xe2} }, + {0x0628, {0xe9, 0xf5} }, + {0x0629, {0x99, 0x19} }, + {0x062a, {0xd4, 0x11} }, + {0x062b, {0x03, 0x04} }, + {0x062c, {0xb5, 0x85} }, + {0x062d, {0x1e, 0x20} }, + {0x062e, {0x2a, 0xea} }, + {0x062f, {0xd7, 0xd2} }, + {0x0630, {0x15, 0x15} }, + {0x0631, {0xa3, 0xa9} }, + {0x0632, {0x1f, 0x1f} }, + {0x0633, {0xf9, 0xd1} }, + {0x0634, {0xc0, 0xc3} }, + {0x0635, {0x4d, 0x8d} }, + {0x0636, {0x21, 0x31} }, + {0x0637, {0x83, 0x83} }, + {0x0638, {0x08, 0x8c} }, + {0x0639, {0x19, 0x19} }, + {0x063a, {0x45, 0xa5} }, + {0x063b, {0xef, 0xec} }, + {0x063c, {0x8a, 0x8a} }, + {0x063d, {0xf4, 0xf6} }, + {0x063e, {0x8f, 0x8f} }, + {0x063f, {0x44, 0x0c} }, + {0x0640, {0xef, 0xf0} }, + {0x0641, {0x66, 0x66} }, + {0x0642, {0xcc, 0xd2} }, + {0x0643, {0x41, 0x41} }, + {0x0644, {0x63, 0x93} }, + {0x0645, {0x8e, 0x8e} }, + {0x0646, {0xa2, 0x42} }, + {0x0647, {0x7b, 0x7b} }, + {0x0648, {0x04, 0x04} }, + {0x0649, {0x00, 0x00} }, + {0x064a, {0x40, 0x40} }, + {0x064b, {0x8c, 0x98} }, + {0x064c, {0x00, 0x00} }, + {0x064d, {0x63, 0xc3} }, + {0x064e, {0x04, 0x04} }, + {0x064f, {0x20, 0x20} }, + {0x0650, {0x00, 0x00} }, + {0x0651, {0x40, 0x40} }, + {0x0652, {0x01, 0x01} }, }; -#define NUM_LPFILTER_COEF (sizeof (lpfilter_coef) / sizeof(struct au8522_register_config)) +#define NUM_LPFILTER_COEF (sizeof(lpfilter_coef)\ + / sizeof(struct au8522_register_config)) static inline struct au8522_state *to_state(struct v4l2_subdev *sd) { @@ -203,14 +205,17 @@ static void setup_vbi(struct au8522_state *state, int aud_input) au8522_writereg(state, AU8522_TVDEC_VBI_USER_FRAME_PAT2_REG01EH, 0x00); au8522_writereg(state, AU8522_TVDEC_VBI_USER_FRAME_PAT1_REG01FH, 0x00); au8522_writereg(state, AU8522_TVDEC_VBI_USER_FRAME_PAT0_REG020H, 0x00); - au8522_writereg(state, AU8522_TVDEC_VBI_USER_FRAME_MASK2_REG021H,0x00); - au8522_writereg(state, AU8522_TVDEC_VBI_USER_FRAME_MASK1_REG022H,0x00); - au8522_writereg(state, AU8522_TVDEC_VBI_USER_FRAME_MASK0_REG023H,0x00); + au8522_writereg(state, AU8522_TVDEC_VBI_USER_FRAME_MASK2_REG021H, + 0x00); + au8522_writereg(state, AU8522_TVDEC_VBI_USER_FRAME_MASK1_REG022H, + 0x00); + au8522_writereg(state, AU8522_TVDEC_VBI_USER_FRAME_MASK0_REG023H, + 0x00); /* Setup the VBI registers */ - for (i = 0x30; i < 0x60; i++) { + for (i = 0x30; i < 0x60; i++) au8522_writereg(state, i, 0x40); - } + /* For some reason, every register is 0x40 except register 0x44 (confirmed via the HVR-950q USB capture) */ au8522_writereg(state, 0x44, 0x60); @@ -449,7 +454,7 @@ static void set_audio_input(struct au8522_state *state, int aud_input) if (aud_input != AU8522_AUDIO_SIF) { /* The caller asked for a mode we don't currently support */ - printk("Unsupported audio mode requested! mode=%d\n", + printk(KERN_ERR "Unsupported audio mode requested! mode=%d\n", aud_input); return; } @@ -669,7 +674,7 @@ static int au8522_s_video_routing(struct v4l2_subdev *sd, } else if (route->input == AU8522_COMPOSITE_CH4_SIF) { au8522_setup_cvbs_tuner_mode(state); } else { - printk("au8522 mode not currently supported\n"); + printk(KERN_ERR "au8522 mode not currently supported\n"); return -EINVAL; } return 0; @@ -783,15 +788,15 @@ static int au8522_probe(struct i2c_client *client, instance = au8522_get_state(&state, client->adapter, client->addr); switch (instance) { case 0: - printk("au8522_decoder allocation failed\n"); + printk(KERN_ERR "au8522_decoder allocation failed\n"); return -EIO; case 1: /* new demod instance */ - printk("au8522_decoder creating new instance...\n"); + printk(KERN_INFO "au8522_decoder creating new instance...\n"); break; default: /* existing demod instance */ - printk("au8522_decoder attaching to existing instance...\n"); + printk(KERN_INFO "au8522_decoder attach existing instance.\n"); break; } -- cgit v1.2.3 From f56f889fb05b6bb1a02725bea0f42236c32f3fbc Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Sun, 15 Mar 2009 17:52:10 -0400 Subject: au0828: rename macro for currently non-function VBI support From: Devin Heitmueller The VBI support or the au0828 has the framework written but it does not yet work. Rename the macro per Mauro's request. Priority: normal Signed-off-by: Devin Heitmueller --- linux/drivers/media/video/au0828/au0828-video.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 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 82443d51e..d3e7cd98c 100644 --- a/linux/drivers/media/video/au0828/au0828-video.c +++ b/linux/drivers/media/video/au0828/au0828-video.c @@ -754,7 +754,7 @@ static int au0828_v4l2_open(struct file *filp) dev = h; type = V4L2_BUF_TYPE_VIDEO_CAPTURE; } -#ifdef VBI_NOT_YET_WORKING +#ifdef VBI_IS_WORKING if (h->vbi_dev->minor == minor) { dev = h; type = V4L2_BUF_TYPE_VBI_CAPTURE; @@ -933,7 +933,7 @@ static int au0828_set_format(struct au0828_dev *dev, unsigned int cmd, maxwidth = 720; maxheight = 480; -#ifdef VBI_NOT_YET_WORKING +#ifdef VBI_IS_WORKING if (format->type == V4L2_BUF_TYPE_SLICED_VBI_CAPTURE) { dprintk(1, "VBI format set: to be supported!\n"); return 0; @@ -1021,7 +1021,7 @@ static int vidioc_querycap(struct file *file, void *priv, /*set the device capabilities */ cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | -#ifdef VBI_NOT_YET_WORKING +#ifdef VBI_IS_WORKING V4L2_CAP_VBI_CAPTURE | #endif V4L2_CAP_AUDIO | @@ -1553,7 +1553,7 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = { .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, -#ifdef VBI_NOT_YET_WORKING +#ifdef VBI_IS_WORKING .vidioc_g_fmt_vbi_cap = vidioc_g_fmt_vbi_cap, .vidioc_try_fmt_vbi_cap = vidioc_s_fmt_vbi_cap, .vidioc_s_fmt_vbi_cap = vidioc_s_fmt_vbi_cap, @@ -1561,7 +1561,7 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = { .vidioc_g_audio = vidioc_g_audio, .vidioc_s_audio = vidioc_s_audio, .vidioc_cropcap = vidioc_cropcap, -#ifdef VBI_NOT_YET_WORKING +#ifdef VBI_IS_WORKING .vidioc_g_fmt_sliced_vbi_cap = vidioc_g_fmt_sliced_vbi_cap, .vidioc_try_fmt_sliced_vbi_cap = vidioc_try_set_sliced_vbi_cap, .vidioc_s_fmt_sliced_vbi_cap = vidioc_try_set_sliced_vbi_cap, @@ -1665,7 +1665,7 @@ int au0828_analog_register(struct au0828_dev *dev, return -ENOMEM; } -#ifdef VBI_NOT_YET_WORKING +#ifdef VBI_IS_WORKING dev->vbi_dev = video_device_alloc(); if (NULL == dev->vbi_dev) { dprintk(1, "Can't allocate vbi_device.\n"); @@ -1679,7 +1679,7 @@ int au0828_analog_register(struct au0828_dev *dev, dev->vdev->parent = &dev->usbdev->dev; strcpy(dev->vdev->name, "au0828a video"); -#ifdef VBI_NOT_YET_WORKING +#ifdef VBI_IS_WORKING /* Setup the VBI device */ *dev->vbi_dev = au0828_video_template; dev->vbi_dev->parent = &dev->usbdev->dev; @@ -1698,7 +1698,7 @@ int au0828_analog_register(struct au0828_dev *dev, return -ENODEV; } -#ifdef VBI_NOT_YET_WORKING +#ifdef VBI_IS_WORKING /* Register the vbi device */ retval = video_register_device(dev->vbi_dev, VFL_TYPE_VBI, -1); if (retval != 0) { -- cgit v1.2.3 From e349a2e984faf451597ceea0fc7e1ffb077314d8 Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Sun, 15 Mar 2009 18:04:45 -0400 Subject: au8522: move the analog decoder source file From: Devin Heitmueller As Mauro pointed out, for a given driver you cannot have one file in media/video and another in dvb/frontends. Until we have a better scheme for managing the source tree in terms of a single chip that has both a digital demod and an analog demod, make sure both files reside in the dvb/frontends dir. This patch is strictly a file move - there are no changes to the file itself. This change was required so that the code works in the mainline kernel (without it the code only compiles in the out-of-tree v4l-dvb branch). Priority: normal Signed-off-by: Devin Heitmueller --- linux/drivers/media/dvb/frontends/au8522_decoder.c | 850 +++++++++++++++++++++ linux/drivers/media/video/au8522_decoder.c | 850 --------------------- 2 files changed, 850 insertions(+), 850 deletions(-) create mode 100644 linux/drivers/media/dvb/frontends/au8522_decoder.c delete mode 100644 linux/drivers/media/video/au8522_decoder.c (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/frontends/au8522_decoder.c b/linux/drivers/media/dvb/frontends/au8522_decoder.c new file mode 100644 index 000000000..b4a205809 --- /dev/null +++ b/linux/drivers/media/dvb/frontends/au8522_decoder.c @@ -0,0 +1,850 @@ +/* + * Auvitek AU8522 QAM/8VSB demodulator driver and video decoder + * + * Copyright (C) 2009 Devin Heitmueller + * Copyright (C) 2005-2008 Auvitek International, Ltd. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * As published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +/* Developer notes: + * + * VBI support is not yet working + * Saturation and hue setting are not yet working + * Enough is implemented here for CVBS and S-Video inputs, but the actual + * analog demodulator code isn't implemented (not needed for xc5000 since it + * has its own demodulator and outputs CVBS) + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "compat.h" +#include "au8522.h" +#include "au8522_priv.h" + +MODULE_AUTHOR("Devin Heitmueller"); +MODULE_LICENSE("GPL"); + +static int au8522_analog_debug; + +static unsigned short normal_i2c[] = { 0x8e >> 1, I2C_CLIENT_END }; + +module_param_named(analog_debug, au8522_analog_debug, int, 0644); + +MODULE_PARM_DESC(analog_debug, + "Analog debugging messages [0=Off (default) 1=On]"); + +I2C_CLIENT_INSMOD; + +struct au8522_register_config { + u16 reg_name; + u8 reg_val[8]; +}; + + +/* Video Decoder Filter Coefficients + The values are as follows from left to right + 0="ATV RF" 1="ATV RF13" 2="CVBS" 3="S-Video" 4="PAL" 5=CVBS13" 6="SVideo13" +*/ +struct au8522_register_config filter_coef[] = { + {AU8522_FILTER_COEF_R410, {0x25, 0x00, 0x25, 0x25, 0x00, 0x00, 0x00} }, + {AU8522_FILTER_COEF_R411, {0x20, 0x00, 0x20, 0x20, 0x00, 0x00, 0x00} }, + {AU8522_FILTER_COEF_R412, {0x03, 0x00, 0x03, 0x03, 0x00, 0x00, 0x00} }, + {AU8522_FILTER_COEF_R413, {0xe6, 0x00, 0xe6, 0xe6, 0x00, 0x00, 0x00} }, + {AU8522_FILTER_COEF_R414, {0x40, 0x00, 0x40, 0x40, 0x00, 0x00, 0x00} }, + {AU8522_FILTER_COEF_R415, {0x1b, 0x00, 0x1b, 0x1b, 0x00, 0x00, 0x00} }, + {AU8522_FILTER_COEF_R416, {0xc0, 0x00, 0xc0, 0x04, 0x00, 0x00, 0x00} }, + {AU8522_FILTER_COEF_R417, {0x04, 0x00, 0x04, 0x04, 0x00, 0x00, 0x00} }, + {AU8522_FILTER_COEF_R418, {0x8c, 0x00, 0x8c, 0x8c, 0x00, 0x00, 0x00} }, + {AU8522_FILTER_COEF_R419, {0xa0, 0x40, 0xa0, 0xa0, 0x40, 0x40, 0x40} }, + {AU8522_FILTER_COEF_R41A, {0x21, 0x09, 0x21, 0x21, 0x09, 0x09, 0x09} }, + {AU8522_FILTER_COEF_R41B, {0x6c, 0x38, 0x6c, 0x6c, 0x38, 0x38, 0x38} }, + {AU8522_FILTER_COEF_R41C, {0x03, 0xff, 0x03, 0x03, 0xff, 0xff, 0xff} }, + {AU8522_FILTER_COEF_R41D, {0xbf, 0xc7, 0xbf, 0xbf, 0xc7, 0xc7, 0xc7} }, + {AU8522_FILTER_COEF_R41E, {0xa0, 0xdf, 0xa0, 0xa0, 0xdf, 0xdf, 0xdf} }, + {AU8522_FILTER_COEF_R41F, {0x10, 0x06, 0x10, 0x10, 0x06, 0x06, 0x06} }, + {AU8522_FILTER_COEF_R420, {0xae, 0x30, 0xae, 0xae, 0x30, 0x30, 0x30} }, + {AU8522_FILTER_COEF_R421, {0xc4, 0x01, 0xc4, 0xc4, 0x01, 0x01, 0x01} }, + {AU8522_FILTER_COEF_R422, {0x54, 0xdd, 0x54, 0x54, 0xdd, 0xdd, 0xdd} }, + {AU8522_FILTER_COEF_R423, {0xd0, 0xaf, 0xd0, 0xd0, 0xaf, 0xaf, 0xaf} }, + {AU8522_FILTER_COEF_R424, {0x1c, 0xf7, 0x1c, 0x1c, 0xf7, 0xf7, 0xf7} }, + {AU8522_FILTER_COEF_R425, {0x76, 0xdb, 0x76, 0x76, 0xdb, 0xdb, 0xdb} }, + {AU8522_FILTER_COEF_R426, {0x61, 0xc0, 0x61, 0x61, 0xc0, 0xc0, 0xc0} }, + {AU8522_FILTER_COEF_R427, {0xd1, 0x2f, 0xd1, 0xd1, 0x2f, 0x2f, 0x2f} }, + {AU8522_FILTER_COEF_R428, {0x84, 0xd8, 0x84, 0x84, 0xd8, 0xd8, 0xd8} }, + {AU8522_FILTER_COEF_R429, {0x06, 0xfb, 0x06, 0x06, 0xfb, 0xfb, 0xfb} }, + {AU8522_FILTER_COEF_R42A, {0x21, 0xd5, 0x21, 0x21, 0xd5, 0xd5, 0xd5} }, + {AU8522_FILTER_COEF_R42B, {0x0a, 0x3e, 0x0a, 0x0a, 0x3e, 0x3e, 0x3e} }, + {AU8522_FILTER_COEF_R42C, {0xe6, 0x15, 0xe6, 0xe6, 0x15, 0x15, 0x15} }, + {AU8522_FILTER_COEF_R42D, {0x01, 0x34, 0x01, 0x01, 0x34, 0x34, 0x34} }, + +}; +#define NUM_FILTER_COEF (sizeof(filter_coef)\ + / sizeof(struct au8522_register_config)) + + +/* Registers 0x060b through 0x0652 are the LP Filter coefficients + The values are as follows from left to right + 0="SIF" 1="ATVRF/ATVRF13" + Note: the "ATVRF/ATVRF13" mode has never been tested +*/ +struct au8522_register_config lpfilter_coef[] = { + {0x060b, {0x21, 0x0b} }, + {0x060c, {0xad, 0xad} }, + {0x060d, {0x70, 0xf0} }, + {0x060e, {0xea, 0xe9} }, + {0x060f, {0xdd, 0xdd} }, + {0x0610, {0x08, 0x64} }, + {0x0611, {0x60, 0x60} }, + {0x0612, {0xf8, 0xb2} }, + {0x0613, {0x01, 0x02} }, + {0x0614, {0xe4, 0xb4} }, + {0x0615, {0x19, 0x02} }, + {0x0616, {0xae, 0x2e} }, + {0x0617, {0xee, 0xc5} }, + {0x0618, {0x56, 0x56} }, + {0x0619, {0x30, 0x58} }, + {0x061a, {0xf9, 0xf8} }, + {0x061b, {0x24, 0x64} }, + {0x061c, {0x07, 0x07} }, + {0x061d, {0x30, 0x30} }, + {0x061e, {0xa9, 0xed} }, + {0x061f, {0x09, 0x0b} }, + {0x0620, {0x42, 0xc2} }, + {0x0621, {0x1d, 0x2a} }, + {0x0622, {0xd6, 0x56} }, + {0x0623, {0x95, 0x8b} }, + {0x0624, {0x2b, 0x2b} }, + {0x0625, {0x30, 0x24} }, + {0x0626, {0x3e, 0x3e} }, + {0x0627, {0x62, 0xe2} }, + {0x0628, {0xe9, 0xf5} }, + {0x0629, {0x99, 0x19} }, + {0x062a, {0xd4, 0x11} }, + {0x062b, {0x03, 0x04} }, + {0x062c, {0xb5, 0x85} }, + {0x062d, {0x1e, 0x20} }, + {0x062e, {0x2a, 0xea} }, + {0x062f, {0xd7, 0xd2} }, + {0x0630, {0x15, 0x15} }, + {0x0631, {0xa3, 0xa9} }, + {0x0632, {0x1f, 0x1f} }, + {0x0633, {0xf9, 0xd1} }, + {0x0634, {0xc0, 0xc3} }, + {0x0635, {0x4d, 0x8d} }, + {0x0636, {0x21, 0x31} }, + {0x0637, {0x83, 0x83} }, + {0x0638, {0x08, 0x8c} }, + {0x0639, {0x19, 0x19} }, + {0x063a, {0x45, 0xa5} }, + {0x063b, {0xef, 0xec} }, + {0x063c, {0x8a, 0x8a} }, + {0x063d, {0xf4, 0xf6} }, + {0x063e, {0x8f, 0x8f} }, + {0x063f, {0x44, 0x0c} }, + {0x0640, {0xef, 0xf0} }, + {0x0641, {0x66, 0x66} }, + {0x0642, {0xcc, 0xd2} }, + {0x0643, {0x41, 0x41} }, + {0x0644, {0x63, 0x93} }, + {0x0645, {0x8e, 0x8e} }, + {0x0646, {0xa2, 0x42} }, + {0x0647, {0x7b, 0x7b} }, + {0x0648, {0x04, 0x04} }, + {0x0649, {0x00, 0x00} }, + {0x064a, {0x40, 0x40} }, + {0x064b, {0x8c, 0x98} }, + {0x064c, {0x00, 0x00} }, + {0x064d, {0x63, 0xc3} }, + {0x064e, {0x04, 0x04} }, + {0x064f, {0x20, 0x20} }, + {0x0650, {0x00, 0x00} }, + {0x0651, {0x40, 0x40} }, + {0x0652, {0x01, 0x01} }, +}; +#define NUM_LPFILTER_COEF (sizeof(lpfilter_coef)\ + / sizeof(struct au8522_register_config)) + +static inline struct au8522_state *to_state(struct v4l2_subdev *sd) +{ + return container_of(sd, struct au8522_state, sd); +} + +static void setup_vbi(struct au8522_state *state, int aud_input) +{ + int i; + + /* These are set to zero regardless of what mode we're in */ + au8522_writereg(state, AU8522_TVDEC_VBI_CTRL_H_REG017H, 0x00); + au8522_writereg(state, AU8522_TVDEC_VBI_CTRL_L_REG018H, 0x00); + au8522_writereg(state, AU8522_TVDEC_VBI_USER_TOTAL_BITS_REG019H, 0x00); + au8522_writereg(state, AU8522_TVDEC_VBI_USER_TUNIT_H_REG01AH, 0x00); + au8522_writereg(state, AU8522_TVDEC_VBI_USER_TUNIT_L_REG01BH, 0x00); + au8522_writereg(state, AU8522_TVDEC_VBI_USER_THRESH1_REG01CH, 0x00); + au8522_writereg(state, AU8522_TVDEC_VBI_USER_FRAME_PAT2_REG01EH, 0x00); + au8522_writereg(state, AU8522_TVDEC_VBI_USER_FRAME_PAT1_REG01FH, 0x00); + au8522_writereg(state, AU8522_TVDEC_VBI_USER_FRAME_PAT0_REG020H, 0x00); + au8522_writereg(state, AU8522_TVDEC_VBI_USER_FRAME_MASK2_REG021H, + 0x00); + au8522_writereg(state, AU8522_TVDEC_VBI_USER_FRAME_MASK1_REG022H, + 0x00); + au8522_writereg(state, AU8522_TVDEC_VBI_USER_FRAME_MASK0_REG023H, + 0x00); + + /* Setup the VBI registers */ + for (i = 0x30; i < 0x60; i++) + au8522_writereg(state, i, 0x40); + + /* For some reason, every register is 0x40 except register 0x44 + (confirmed via the HVR-950q USB capture) */ + au8522_writereg(state, 0x44, 0x60); + + /* Enable VBI (we always do this regardless of whether the user is + viewing closed caption info) */ + au8522_writereg(state, AU8522_TVDEC_VBI_CTRL_H_REG017H, + AU8522_TVDEC_VBI_CTRL_H_REG017H_CCON); + +} + +static void setup_decoder_defaults(struct au8522_state *state, u8 input_mode) +{ + int i; + int filter_coef_type; + + /* Provide reasonable defaults for picture tuning values */ + au8522_writereg(state, AU8522_TVDEC_SHARPNESSREG009H, 0x07); + au8522_writereg(state, AU8522_TVDEC_BRIGHTNESS_REG00AH, 0xed); + state->brightness = 0xed - 128; + au8522_writereg(state, AU8522_TVDEC_CONTRAST_REG00BH, 0x79); + state->contrast = 0x79; + au8522_writereg(state, AU8522_TVDEC_SATURATION_CB_REG00CH, 0x80); + au8522_writereg(state, AU8522_TVDEC_SATURATION_CR_REG00DH, 0x80); + au8522_writereg(state, AU8522_TVDEC_HUE_H_REG00EH, 0x00); + au8522_writereg(state, AU8522_TVDEC_HUE_L_REG00FH, 0x00); + + /* Other decoder registers */ + au8522_writereg(state, AU8522_TVDEC_INT_MASK_REG010H, 0x00); + + if (input_mode == 0x23) { + /* S-Video input mapping */ + au8522_writereg(state, AU8522_VIDEO_MODE_REG011H, 0x04); + } else { + /* All other modes (CVBS/ATVRF etc.) */ + au8522_writereg(state, AU8522_VIDEO_MODE_REG011H, 0x00); + } + + au8522_writereg(state, AU8522_TVDEC_PGA_REG012H, + AU8522_TVDEC_PGA_REG012H_CVBS); + au8522_writereg(state, AU8522_TVDEC_COMB_MODE_REG015H, + AU8522_TVDEC_COMB_MODE_REG015H_CVBS); + au8522_writereg(state, AU8522_TVDED_DBG_MODE_REG060H, + AU8522_TVDED_DBG_MODE_REG060H_CVBS); + au8522_writereg(state, AU8522_TVDEC_FORMAT_CTRL1_REG061H, + AU8522_TVDEC_FORMAT_CTRL1_REG061H_CVBS13); + au8522_writereg(state, AU8522_TVDEC_FORMAT_CTRL2_REG062H, + AU8522_TVDEC_FORMAT_CTRL2_REG062H_CVBS13); + au8522_writereg(state, AU8522_TVDEC_VCR_DET_LLIM_REG063H, + AU8522_TVDEC_VCR_DET_LLIM_REG063H_CVBS); + au8522_writereg(state, AU8522_TVDEC_VCR_DET_HLIM_REG064H, + AU8522_TVDEC_VCR_DET_HLIM_REG064H_CVBS); + au8522_writereg(state, AU8522_TVDEC_COMB_VDIF_THR1_REG065H, + AU8522_TVDEC_COMB_VDIF_THR1_REG065H_CVBS); + au8522_writereg(state, AU8522_TVDEC_COMB_VDIF_THR2_REG066H, + AU8522_TVDEC_COMB_VDIF_THR2_REG066H_CVBS); + au8522_writereg(state, AU8522_TVDEC_COMB_VDIF_THR3_REG067H, + AU8522_TVDEC_COMB_VDIF_THR3_REG067H_CVBS); + au8522_writereg(state, AU8522_TVDEC_COMB_NOTCH_THR_REG068H, + AU8522_TVDEC_COMB_NOTCH_THR_REG068H_CVBS); + au8522_writereg(state, AU8522_TVDEC_COMB_HDIF_THR1_REG069H, + AU8522_TVDEC_COMB_HDIF_THR1_REG069H_CVBS); + au8522_writereg(state, AU8522_TVDEC_COMB_HDIF_THR2_REG06AH, + AU8522_TVDEC_COMB_HDIF_THR2_REG06AH_CVBS); + au8522_writereg(state, AU8522_TVDEC_COMB_HDIF_THR3_REG06BH, + AU8522_TVDEC_COMB_HDIF_THR3_REG06BH_CVBS); + au8522_writereg(state, AU8522_TVDEC_COMB_DCDIF_THR1_REG06CH, + AU8522_TVDEC_COMB_DCDIF_THR1_REG06CH_CVBS); + au8522_writereg(state, AU8522_TVDEC_COMB_DCDIF_THR2_REG06DH, + AU8522_TVDEC_COMB_DCDIF_THR2_REG06DH_CVBS); + au8522_writereg(state, AU8522_TVDEC_COMB_DCDIF_THR3_REG06EH, + AU8522_TVDEC_COMB_DCDIF_THR3_REG06EH_CVBS); + au8522_writereg(state, AU8522_TVDEC_UV_SEP_THR_REG06FH, + AU8522_TVDEC_UV_SEP_THR_REG06FH_CVBS); + au8522_writereg(state, AU8522_TVDEC_COMB_DC_THR1_NTSC_REG070H, + AU8522_TVDEC_COMB_DC_THR1_NTSC_REG070H_CVBS); + au8522_writereg(state, AU8522_REG071H, AU8522_REG071H_CVBS); + au8522_writereg(state, AU8522_REG072H, AU8522_REG072H_CVBS); + au8522_writereg(state, AU8522_TVDEC_COMB_DC_THR2_NTSC_REG073H, + AU8522_TVDEC_COMB_DC_THR2_NTSC_REG073H_CVBS); + au8522_writereg(state, AU8522_REG074H, AU8522_REG074H_CVBS); + au8522_writereg(state, AU8522_REG075H, AU8522_REG075H_CVBS); + au8522_writereg(state, AU8522_TVDEC_DCAGC_CTRL_REG077H, + AU8522_TVDEC_DCAGC_CTRL_REG077H_CVBS); + au8522_writereg(state, AU8522_TVDEC_PIC_START_ADJ_REG078H, + AU8522_TVDEC_PIC_START_ADJ_REG078H_CVBS); + au8522_writereg(state, AU8522_TVDEC_AGC_HIGH_LIMIT_REG079H, + AU8522_TVDEC_AGC_HIGH_LIMIT_REG079H_CVBS); + au8522_writereg(state, AU8522_TVDEC_MACROVISION_SYNC_THR_REG07AH, + AU8522_TVDEC_MACROVISION_SYNC_THR_REG07AH_CVBS); + au8522_writereg(state, AU8522_TVDEC_INTRP_CTRL_REG07BH, + AU8522_TVDEC_INTRP_CTRL_REG07BH_CVBS); + au8522_writereg(state, AU8522_TVDEC_AGC_LOW_LIMIT_REG0E4H, + AU8522_TVDEC_AGC_LOW_LIMIT_REG0E4H_CVBS); + au8522_writereg(state, AU8522_TOREGAAGC_REG0E5H, + AU8522_TOREGAAGC_REG0E5H_CVBS); + au8522_writereg(state, AU8522_REG016H, AU8522_REG016H_CVBS); + + setup_vbi(state, 0); + + if (input_mode == AU8522_INPUT_CONTROL_REG081H_SVIDEO_CH13 || + input_mode == AU8522_INPUT_CONTROL_REG081H_SVIDEO_CH24) { + /* Despite what the table says, for the HVR-950q we still need + to be in CVBS mode for the S-Video input (reason uknown). */ + /* filter_coef_type = 3; */ + filter_coef_type = 5; + } else { + filter_coef_type = 5; + } + + /* Load the Video Decoder Filter Coefficients */ + for (i = 0; i < NUM_FILTER_COEF; i++) { + au8522_writereg(state, filter_coef[i].reg_name, + filter_coef[i].reg_val[filter_coef_type]); + } + + /* It's not clear what these registers are for, but they are always + set to the same value regardless of what mode we're in */ + au8522_writereg(state, AU8522_REG42EH, 0x87); + au8522_writereg(state, AU8522_REG42FH, 0xa2); + au8522_writereg(state, AU8522_REG430H, 0xbf); + au8522_writereg(state, AU8522_REG431H, 0xcb); + au8522_writereg(state, AU8522_REG432H, 0xa1); + au8522_writereg(state, AU8522_REG433H, 0x41); + au8522_writereg(state, AU8522_REG434H, 0x88); + au8522_writereg(state, AU8522_REG435H, 0xc2); + au8522_writereg(state, AU8522_REG436H, 0x3c); +} + +static void au8522_setup_cvbs_mode(struct au8522_state *state) +{ + /* here we're going to try the pre-programmed route */ + au8522_writereg(state, AU8522_MODULE_CLOCK_CONTROL_REG0A3H, + AU8522_MODULE_CLOCK_CONTROL_REG0A3H_CVBS); + + au8522_writereg(state, AU8522_PGA_CONTROL_REG082H, 0x00); + au8522_writereg(state, AU8522_CLAMPING_CONTROL_REG083H, 0x0e); + au8522_writereg(state, AU8522_PGA_CONTROL_REG082H, 0x10); + + au8522_writereg(state, AU8522_INPUT_CONTROL_REG081H, + AU8522_INPUT_CONTROL_REG081H_CVBS_CH1); + + setup_decoder_defaults(state, AU8522_INPUT_CONTROL_REG081H_CVBS_CH1); + + au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H, + AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H_CVBS); +} + +static void au8522_setup_cvbs_tuner_mode(struct au8522_state *state) +{ + /* here we're going to try the pre-programmed route */ + au8522_writereg(state, AU8522_MODULE_CLOCK_CONTROL_REG0A3H, + AU8522_MODULE_CLOCK_CONTROL_REG0A3H_CVBS); + + /* It's not clear why they turn off the PGA before enabling the clamp + control, but the Windows trace does it so we will too... */ + au8522_writereg(state, AU8522_PGA_CONTROL_REG082H, 0x00); + + /* Enable clamping control */ + au8522_writereg(state, AU8522_CLAMPING_CONTROL_REG083H, 0x0e); + + /* Turn on the PGA */ + au8522_writereg(state, AU8522_PGA_CONTROL_REG082H, 0x10); + + /* Set input mode to CVBS on channel 4 with SIF audio input enabled */ + au8522_writereg(state, AU8522_INPUT_CONTROL_REG081H, + AU8522_INPUT_CONTROL_REG081H_CVBS_CH4_SIF); + + setup_decoder_defaults(state, + AU8522_INPUT_CONTROL_REG081H_CVBS_CH4_SIF); + + au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H, + AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H_CVBS); +} + +static void au8522_setup_svideo_mode(struct au8522_state *state) +{ + au8522_writereg(state, AU8522_MODULE_CLOCK_CONTROL_REG0A3H, + AU8522_MODULE_CLOCK_CONTROL_REG0A3H_SVIDEO); + + /* Set input to Y on Channe1, C on Channel 3 */ + au8522_writereg(state, AU8522_INPUT_CONTROL_REG081H, + AU8522_INPUT_CONTROL_REG081H_SVIDEO_CH13); + + /* Disable clamping control (required for S-video) */ + au8522_writereg(state, AU8522_CLAMPING_CONTROL_REG083H, 0x00); + + setup_decoder_defaults(state, + AU8522_INPUT_CONTROL_REG081H_SVIDEO_CH13); + + au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H, + AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H_CVBS); +} + +/* ----------------------------------------------------------------------- */ + +static void disable_audio_input(struct au8522_state *state) +{ + /* This can probably be optimized */ + au8522_writereg(state, AU8522_AUDIO_VOLUME_L_REG0F2H, 0x00); + au8522_writereg(state, AU8522_AUDIO_VOLUME_R_REG0F3H, 0x00); + au8522_writereg(state, AU8522_AUDIO_VOLUME_REG0F4H, 0x00); + au8522_writereg(state, AU8522_I2C_CONTROL_REG1_REG091H, 0x80); + au8522_writereg(state, AU8522_I2C_CONTROL_REG0_REG090H, 0x84); + + au8522_writereg(state, AU8522_ENA_USB_REG101H, 0x00); + au8522_writereg(state, AU8522_AUDIO_VOLUME_L_REG0F2H, 0x7F); + au8522_writereg(state, AU8522_AUDIO_VOLUME_R_REG0F3H, 0x7F); + au8522_writereg(state, AU8522_REG0F9H, AU8522_REG0F9H_AUDIO); + au8522_writereg(state, AU8522_AUDIO_MODE_REG0F1H, 0x40); + + au8522_writereg(state, AU8522_GPIO_DATA_REG0E2H, 0x11); + msleep(5); + au8522_writereg(state, AU8522_GPIO_DATA_REG0E2H, 0x00); + + au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_1_REG0A5H, 0x04); + au8522_writereg(state, AU8522_AUDIOFREQ_REG606H, 0x03); + au8522_writereg(state, AU8522_I2S_CTRL_2_REG112H, 0x02); + + au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H, + AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H_CVBS); +} + +/* 0=disable, 1=SIF */ +static void set_audio_input(struct au8522_state *state, int aud_input) +{ + int i; + + /* Note that this function needs to be used in conjunction with setting + the input routing via register 0x81 */ + + if (aud_input == AU8522_AUDIO_NONE) { + disable_audio_input(state); + return; + } + + if (aud_input != AU8522_AUDIO_SIF) { + /* The caller asked for a mode we don't currently support */ + printk(KERN_ERR "Unsupported audio mode requested! mode=%d\n", + aud_input); + return; + } + + /* Load the Audio Decoder Filter Coefficients */ + for (i = 0; i < NUM_LPFILTER_COEF; i++) { + au8522_writereg(state, lpfilter_coef[i].reg_name, + lpfilter_coef[i].reg_val[0]); + } + + /* Setup audio */ + au8522_writereg(state, AU8522_AUDIO_VOLUME_L_REG0F2H, 0x00); + au8522_writereg(state, AU8522_AUDIO_VOLUME_R_REG0F3H, 0x00); + au8522_writereg(state, AU8522_AUDIO_VOLUME_REG0F4H, 0x00); + au8522_writereg(state, AU8522_I2C_CONTROL_REG1_REG091H, 0x80); + au8522_writereg(state, AU8522_I2C_CONTROL_REG0_REG090H, 0x84); + msleep(150); + au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H, 0x00); + msleep(1); + au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H, 0x9d); + msleep(50); + au8522_writereg(state, AU8522_AUDIO_VOLUME_L_REG0F2H, 0x7F); + au8522_writereg(state, AU8522_AUDIO_VOLUME_R_REG0F3H, 0x7F); + au8522_writereg(state, AU8522_AUDIO_VOLUME_REG0F4H, 0xff); + msleep(80); + au8522_writereg(state, AU8522_AUDIO_VOLUME_L_REG0F2H, 0x7F); + au8522_writereg(state, AU8522_AUDIO_VOLUME_R_REG0F3H, 0x7F); + au8522_writereg(state, AU8522_REG0F9H, AU8522_REG0F9H_AUDIO); + au8522_writereg(state, AU8522_AUDIO_MODE_REG0F1H, 0x82); + msleep(70); + au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_1_REG0A5H, 0x09); + au8522_writereg(state, AU8522_AUDIOFREQ_REG606H, 0x03); + au8522_writereg(state, AU8522_I2S_CTRL_2_REG112H, 0xc2); +} + +/* ----------------------------------------------------------------------- */ + +static int au8522_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) +{ + struct au8522_state *state = to_state(sd); + + switch (ctrl->id) { + case V4L2_CID_BRIGHTNESS: + state->brightness = ctrl->value; + au8522_writereg(state, AU8522_TVDEC_BRIGHTNESS_REG00AH, + ctrl->value - 128); + break; + case V4L2_CID_CONTRAST: + state->contrast = ctrl->value; + au8522_writereg(state, AU8522_TVDEC_CONTRAST_REG00BH, + ctrl->value); + break; + case V4L2_CID_SATURATION: + case V4L2_CID_HUE: + case V4L2_CID_AUDIO_VOLUME: + case V4L2_CID_AUDIO_BASS: + case V4L2_CID_AUDIO_TREBLE: + case V4L2_CID_AUDIO_BALANCE: + case V4L2_CID_AUDIO_MUTE: + /* Not yet implemented */ + default: + return -EINVAL; + } + + return 0; +} + +static int au8522_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) +{ + struct au8522_state *state = to_state(sd); + + /* Note that we are using values cached in the state structure instead + of reading the registers due to issues with i2c reads not working + properly/consistently yet on the HVR-950q */ + + switch (ctrl->id) { + case V4L2_CID_BRIGHTNESS: + ctrl->value = state->brightness; + break; + case V4L2_CID_CONTRAST: + ctrl->value = state->contrast; + break; + case V4L2_CID_SATURATION: + case V4L2_CID_HUE: + case V4L2_CID_AUDIO_VOLUME: + case V4L2_CID_AUDIO_BASS: + case V4L2_CID_AUDIO_TREBLE: + case V4L2_CID_AUDIO_BALANCE: + case V4L2_CID_AUDIO_MUTE: + /* Not yet supported */ + default: + return -EINVAL; + } + + return 0; +} + +/* ----------------------------------------------------------------------- */ + +static int au8522_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) +{ + switch (fmt->type) { + default: + return -EINVAL; + } + return 0; +} + +static int au8522_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) +{ + switch (fmt->type) { + case V4L2_BUF_TYPE_VIDEO_CAPTURE: + /* Not yet implemented */ + break; + default: + return -EINVAL; + } + + return 0; +} + +/* ----------------------------------------------------------------------- */ + +#ifdef CONFIG_VIDEO_ADV_DEBUG +static int au8522_g_register(struct v4l2_subdev *sd, + struct v4l2_dbg_register *reg) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + struct au8522_state *state = to_state(sd); + + if (!v4l2_chip_match_i2c_client(client, ®->match)) + return -EINVAL; + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + reg->val = au8522_readreg(state, reg->reg & 0xffff); + return 0; +} + +static int au8522_s_register(struct v4l2_subdev *sd, + struct v4l2_dbg_register *reg) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + struct au8522_state *state = to_state(sd); + + if (!v4l2_chip_match_i2c_client(client, ®->match)) + return -EINVAL; + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + au8522_writereg(state, reg->reg, reg->val & 0xff); + return 0; +} +#endif + +static int au8522_s_stream(struct v4l2_subdev *sd, int enable) +{ + struct au8522_state *state = to_state(sd); + + if (enable) { + au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H, + 0x01); + msleep(1); + au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H, + AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H_CVBS); + } else { + /* This does not completely power down the device + (it only reduces it from around 140ma to 80ma) */ + au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H, + 1 << 5); + } + return 0; +} + +static int au8522_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc) +{ + switch (qc->id) { + case V4L2_CID_CONTRAST: + return v4l2_ctrl_query_fill(qc, 0, 255, 1, + AU8522_TVDEC_CONTRAST_REG00BH_CVBS); + case V4L2_CID_BRIGHTNESS: + return v4l2_ctrl_query_fill(qc, 0, 255, 1, 128); + case V4L2_CID_SATURATION: + case V4L2_CID_HUE: + /* Not yet implemented */ + default: + break; + } + + qc->type = 0; + return -EINVAL; +} + +static int au8522_reset(struct v4l2_subdev *sd, u32 val) +{ + struct au8522_state *state = to_state(sd); + + au8522_writereg(state, 0xa4, 1 << 5); + + return 0; +} + +static int au8522_s_video_routing(struct v4l2_subdev *sd, + const struct v4l2_routing *route) +{ + struct au8522_state *state = to_state(sd); + + au8522_reset(sd, 0); + + /* Jam open the i2c gate to the tuner. We do this here to handle the + case where the user went into digital mode (causing the gate to be + closed), and then came back to analog mode */ + au8522_writereg(state, 0x106, 1); + + if (route->input == AU8522_COMPOSITE_CH1) { + au8522_setup_cvbs_mode(state); + } else if (route->input == AU8522_SVIDEO_CH13) { + au8522_setup_svideo_mode(state); + } else if (route->input == AU8522_COMPOSITE_CH4_SIF) { + au8522_setup_cvbs_tuner_mode(state); + } else { + printk(KERN_ERR "au8522 mode not currently supported\n"); + return -EINVAL; + } + return 0; +} + +static int au8522_s_audio_routing(struct v4l2_subdev *sd, + const struct v4l2_routing *route) +{ + struct au8522_state *state = to_state(sd); + set_audio_input(state, route->input); + return 0; +} + +static int au8522_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt) +{ + int val = 0; + struct au8522_state *state = to_state(sd); + u8 lock_status; + + /* Interrogate the decoder to see if we are getting a real signal */ + lock_status = au8522_readreg(state, 0x00); + if (lock_status == 0xa2) + vt->signal = 0x01; + else + vt->signal = 0x00; + + vt->capability |= + V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_LANG1 | + V4L2_TUNER_CAP_LANG2 | V4L2_TUNER_CAP_SAP; + + val = V4L2_TUNER_SUB_MONO; + vt->rxsubchans = val; + vt->audmode = V4L2_TUNER_MODE_STEREO; + return 0; +} + +static int au8522_g_chip_ident(struct v4l2_subdev *sd, + struct v4l2_dbg_chip_ident *chip) +{ + struct au8522_state *state = to_state(sd); + struct i2c_client *client = v4l2_get_subdevdata(sd); + + return v4l2_chip_ident_i2c_client(client, chip, state->id, state->rev); +} + +static int au8522_log_status(struct v4l2_subdev *sd) +{ + /* FIXME: Add some status info here */ + return 0; +} + +static int au8522_command(struct i2c_client *client, unsigned cmd, void *arg) +{ + return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg); +} + +/* ----------------------------------------------------------------------- */ + +static const struct v4l2_subdev_core_ops au8522_core_ops = { + .log_status = au8522_log_status, + .g_chip_ident = au8522_g_chip_ident, + .g_ctrl = au8522_g_ctrl, + .s_ctrl = au8522_s_ctrl, + .queryctrl = au8522_queryctrl, + .reset = au8522_reset, +#ifdef CONFIG_VIDEO_ADV_DEBUG + .g_register = au8522_g_register, + .s_register = au8522_s_register, +#endif +}; + +static const struct v4l2_subdev_tuner_ops au8522_tuner_ops = { + .g_tuner = au8522_g_tuner, +}; + +static const struct v4l2_subdev_audio_ops au8522_audio_ops = { + .s_routing = au8522_s_audio_routing, +}; + +static const struct v4l2_subdev_video_ops au8522_video_ops = { + .s_routing = au8522_s_video_routing, + .g_fmt = au8522_g_fmt, + .s_fmt = au8522_s_fmt, + .s_stream = au8522_s_stream, +}; + +static const struct v4l2_subdev_ops au8522_ops = { + .core = &au8522_core_ops, + .tuner = &au8522_tuner_ops, + .audio = &au8522_audio_ops, + .video = &au8522_video_ops, +}; + +/* ----------------------------------------------------------------------- */ + +static int au8522_probe(struct i2c_client *client, + const struct i2c_device_id *did) +{ + struct au8522_state *state; + struct v4l2_subdev *sd; + int instance; + struct au8522_config *demod_config; + + /* Check if the adapter supports the needed features */ + if (!i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_BYTE_DATA)) { + return -EIO; + } + + /* allocate memory for the internal state */ + instance = au8522_get_state(&state, client->adapter, client->addr); + switch (instance) { + case 0: + printk(KERN_ERR "au8522_decoder allocation failed\n"); + return -EIO; + case 1: + /* new demod instance */ + printk(KERN_INFO "au8522_decoder creating new instance...\n"); + break; + default: + /* existing demod instance */ + printk(KERN_INFO "au8522_decoder attach existing instance.\n"); + break; + } + + demod_config = kzalloc(sizeof(struct au8522_config), GFP_KERNEL); + demod_config->demod_address = 0x8e >> 1; + + state->config = demod_config; + state->i2c = client->adapter; + + sd = &state->sd; + v4l2_i2c_subdev_init(sd, client, &au8522_ops); + + state->c = client; + state->vid_input = AU8522_COMPOSITE_CH1; + state->aud_input = AU8522_AUDIO_NONE; + state->id = 8522; + state->rev = 0; + + /* Jam open the i2c gate to the tuner */ + au8522_writereg(state, 0x106, 1); + + return 0; +} + +static int au8522_remove(struct i2c_client *client) +{ + struct v4l2_subdev *sd = i2c_get_clientdata(client); + v4l2_device_unregister_subdev(sd); + au8522_release_state(to_state(sd)); + return 0; +} + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) +static const struct i2c_device_id au8522_id[] = { + {"au8522", 0}, + {} +}; + +MODULE_DEVICE_TABLE(i2c, au8522_id); + +#endif +static struct v4l2_i2c_driver_data v4l2_i2c_data = { + .name = "au8522", + .driverid = I2C_DRIVERID_AU8522, + .command = au8522_command, + .probe = au8522_probe, + .remove = au8522_remove, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) + .id_table = au8522_id, +#endif +}; diff --git a/linux/drivers/media/video/au8522_decoder.c b/linux/drivers/media/video/au8522_decoder.c deleted file mode 100644 index b4a205809..000000000 --- a/linux/drivers/media/video/au8522_decoder.c +++ /dev/null @@ -1,850 +0,0 @@ -/* - * Auvitek AU8522 QAM/8VSB demodulator driver and video decoder - * - * Copyright (C) 2009 Devin Heitmueller - * Copyright (C) 2005-2008 Auvitek International, Ltd. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * As published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ - -/* Developer notes: - * - * VBI support is not yet working - * Saturation and hue setting are not yet working - * Enough is implemented here for CVBS and S-Video inputs, but the actual - * analog demodulator code isn't implemented (not needed for xc5000 since it - * has its own demodulator and outputs CVBS) - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "compat.h" -#include "au8522.h" -#include "au8522_priv.h" - -MODULE_AUTHOR("Devin Heitmueller"); -MODULE_LICENSE("GPL"); - -static int au8522_analog_debug; - -static unsigned short normal_i2c[] = { 0x8e >> 1, I2C_CLIENT_END }; - -module_param_named(analog_debug, au8522_analog_debug, int, 0644); - -MODULE_PARM_DESC(analog_debug, - "Analog debugging messages [0=Off (default) 1=On]"); - -I2C_CLIENT_INSMOD; - -struct au8522_register_config { - u16 reg_name; - u8 reg_val[8]; -}; - - -/* Video Decoder Filter Coefficients - The values are as follows from left to right - 0="ATV RF" 1="ATV RF13" 2="CVBS" 3="S-Video" 4="PAL" 5=CVBS13" 6="SVideo13" -*/ -struct au8522_register_config filter_coef[] = { - {AU8522_FILTER_COEF_R410, {0x25, 0x00, 0x25, 0x25, 0x00, 0x00, 0x00} }, - {AU8522_FILTER_COEF_R411, {0x20, 0x00, 0x20, 0x20, 0x00, 0x00, 0x00} }, - {AU8522_FILTER_COEF_R412, {0x03, 0x00, 0x03, 0x03, 0x00, 0x00, 0x00} }, - {AU8522_FILTER_COEF_R413, {0xe6, 0x00, 0xe6, 0xe6, 0x00, 0x00, 0x00} }, - {AU8522_FILTER_COEF_R414, {0x40, 0x00, 0x40, 0x40, 0x00, 0x00, 0x00} }, - {AU8522_FILTER_COEF_R415, {0x1b, 0x00, 0x1b, 0x1b, 0x00, 0x00, 0x00} }, - {AU8522_FILTER_COEF_R416, {0xc0, 0x00, 0xc0, 0x04, 0x00, 0x00, 0x00} }, - {AU8522_FILTER_COEF_R417, {0x04, 0x00, 0x04, 0x04, 0x00, 0x00, 0x00} }, - {AU8522_FILTER_COEF_R418, {0x8c, 0x00, 0x8c, 0x8c, 0x00, 0x00, 0x00} }, - {AU8522_FILTER_COEF_R419, {0xa0, 0x40, 0xa0, 0xa0, 0x40, 0x40, 0x40} }, - {AU8522_FILTER_COEF_R41A, {0x21, 0x09, 0x21, 0x21, 0x09, 0x09, 0x09} }, - {AU8522_FILTER_COEF_R41B, {0x6c, 0x38, 0x6c, 0x6c, 0x38, 0x38, 0x38} }, - {AU8522_FILTER_COEF_R41C, {0x03, 0xff, 0x03, 0x03, 0xff, 0xff, 0xff} }, - {AU8522_FILTER_COEF_R41D, {0xbf, 0xc7, 0xbf, 0xbf, 0xc7, 0xc7, 0xc7} }, - {AU8522_FILTER_COEF_R41E, {0xa0, 0xdf, 0xa0, 0xa0, 0xdf, 0xdf, 0xdf} }, - {AU8522_FILTER_COEF_R41F, {0x10, 0x06, 0x10, 0x10, 0x06, 0x06, 0x06} }, - {AU8522_FILTER_COEF_R420, {0xae, 0x30, 0xae, 0xae, 0x30, 0x30, 0x30} }, - {AU8522_FILTER_COEF_R421, {0xc4, 0x01, 0xc4, 0xc4, 0x01, 0x01, 0x01} }, - {AU8522_FILTER_COEF_R422, {0x54, 0xdd, 0x54, 0x54, 0xdd, 0xdd, 0xdd} }, - {AU8522_FILTER_COEF_R423, {0xd0, 0xaf, 0xd0, 0xd0, 0xaf, 0xaf, 0xaf} }, - {AU8522_FILTER_COEF_R424, {0x1c, 0xf7, 0x1c, 0x1c, 0xf7, 0xf7, 0xf7} }, - {AU8522_FILTER_COEF_R425, {0x76, 0xdb, 0x76, 0x76, 0xdb, 0xdb, 0xdb} }, - {AU8522_FILTER_COEF_R426, {0x61, 0xc0, 0x61, 0x61, 0xc0, 0xc0, 0xc0} }, - {AU8522_FILTER_COEF_R427, {0xd1, 0x2f, 0xd1, 0xd1, 0x2f, 0x2f, 0x2f} }, - {AU8522_FILTER_COEF_R428, {0x84, 0xd8, 0x84, 0x84, 0xd8, 0xd8, 0xd8} }, - {AU8522_FILTER_COEF_R429, {0x06, 0xfb, 0x06, 0x06, 0xfb, 0xfb, 0xfb} }, - {AU8522_FILTER_COEF_R42A, {0x21, 0xd5, 0x21, 0x21, 0xd5, 0xd5, 0xd5} }, - {AU8522_FILTER_COEF_R42B, {0x0a, 0x3e, 0x0a, 0x0a, 0x3e, 0x3e, 0x3e} }, - {AU8522_FILTER_COEF_R42C, {0xe6, 0x15, 0xe6, 0xe6, 0x15, 0x15, 0x15} }, - {AU8522_FILTER_COEF_R42D, {0x01, 0x34, 0x01, 0x01, 0x34, 0x34, 0x34} }, - -}; -#define NUM_FILTER_COEF (sizeof(filter_coef)\ - / sizeof(struct au8522_register_config)) - - -/* Registers 0x060b through 0x0652 are the LP Filter coefficients - The values are as follows from left to right - 0="SIF" 1="ATVRF/ATVRF13" - Note: the "ATVRF/ATVRF13" mode has never been tested -*/ -struct au8522_register_config lpfilter_coef[] = { - {0x060b, {0x21, 0x0b} }, - {0x060c, {0xad, 0xad} }, - {0x060d, {0x70, 0xf0} }, - {0x060e, {0xea, 0xe9} }, - {0x060f, {0xdd, 0xdd} }, - {0x0610, {0x08, 0x64} }, - {0x0611, {0x60, 0x60} }, - {0x0612, {0xf8, 0xb2} }, - {0x0613, {0x01, 0x02} }, - {0x0614, {0xe4, 0xb4} }, - {0x0615, {0x19, 0x02} }, - {0x0616, {0xae, 0x2e} }, - {0x0617, {0xee, 0xc5} }, - {0x0618, {0x56, 0x56} }, - {0x0619, {0x30, 0x58} }, - {0x061a, {0xf9, 0xf8} }, - {0x061b, {0x24, 0x64} }, - {0x061c, {0x07, 0x07} }, - {0x061d, {0x30, 0x30} }, - {0x061e, {0xa9, 0xed} }, - {0x061f, {0x09, 0x0b} }, - {0x0620, {0x42, 0xc2} }, - {0x0621, {0x1d, 0x2a} }, - {0x0622, {0xd6, 0x56} }, - {0x0623, {0x95, 0x8b} }, - {0x0624, {0x2b, 0x2b} }, - {0x0625, {0x30, 0x24} }, - {0x0626, {0x3e, 0x3e} }, - {0x0627, {0x62, 0xe2} }, - {0x0628, {0xe9, 0xf5} }, - {0x0629, {0x99, 0x19} }, - {0x062a, {0xd4, 0x11} }, - {0x062b, {0x03, 0x04} }, - {0x062c, {0xb5, 0x85} }, - {0x062d, {0x1e, 0x20} }, - {0x062e, {0x2a, 0xea} }, - {0x062f, {0xd7, 0xd2} }, - {0x0630, {0x15, 0x15} }, - {0x0631, {0xa3, 0xa9} }, - {0x0632, {0x1f, 0x1f} }, - {0x0633, {0xf9, 0xd1} }, - {0x0634, {0xc0, 0xc3} }, - {0x0635, {0x4d, 0x8d} }, - {0x0636, {0x21, 0x31} }, - {0x0637, {0x83, 0x83} }, - {0x0638, {0x08, 0x8c} }, - {0x0639, {0x19, 0x19} }, - {0x063a, {0x45, 0xa5} }, - {0x063b, {0xef, 0xec} }, - {0x063c, {0x8a, 0x8a} }, - {0x063d, {0xf4, 0xf6} }, - {0x063e, {0x8f, 0x8f} }, - {0x063f, {0x44, 0x0c} }, - {0x0640, {0xef, 0xf0} }, - {0x0641, {0x66, 0x66} }, - {0x0642, {0xcc, 0xd2} }, - {0x0643, {0x41, 0x41} }, - {0x0644, {0x63, 0x93} }, - {0x0645, {0x8e, 0x8e} }, - {0x0646, {0xa2, 0x42} }, - {0x0647, {0x7b, 0x7b} }, - {0x0648, {0x04, 0x04} }, - {0x0649, {0x00, 0x00} }, - {0x064a, {0x40, 0x40} }, - {0x064b, {0x8c, 0x98} }, - {0x064c, {0x00, 0x00} }, - {0x064d, {0x63, 0xc3} }, - {0x064e, {0x04, 0x04} }, - {0x064f, {0x20, 0x20} }, - {0x0650, {0x00, 0x00} }, - {0x0651, {0x40, 0x40} }, - {0x0652, {0x01, 0x01} }, -}; -#define NUM_LPFILTER_COEF (sizeof(lpfilter_coef)\ - / sizeof(struct au8522_register_config)) - -static inline struct au8522_state *to_state(struct v4l2_subdev *sd) -{ - return container_of(sd, struct au8522_state, sd); -} - -static void setup_vbi(struct au8522_state *state, int aud_input) -{ - int i; - - /* These are set to zero regardless of what mode we're in */ - au8522_writereg(state, AU8522_TVDEC_VBI_CTRL_H_REG017H, 0x00); - au8522_writereg(state, AU8522_TVDEC_VBI_CTRL_L_REG018H, 0x00); - au8522_writereg(state, AU8522_TVDEC_VBI_USER_TOTAL_BITS_REG019H, 0x00); - au8522_writereg(state, AU8522_TVDEC_VBI_USER_TUNIT_H_REG01AH, 0x00); - au8522_writereg(state, AU8522_TVDEC_VBI_USER_TUNIT_L_REG01BH, 0x00); - au8522_writereg(state, AU8522_TVDEC_VBI_USER_THRESH1_REG01CH, 0x00); - au8522_writereg(state, AU8522_TVDEC_VBI_USER_FRAME_PAT2_REG01EH, 0x00); - au8522_writereg(state, AU8522_TVDEC_VBI_USER_FRAME_PAT1_REG01FH, 0x00); - au8522_writereg(state, AU8522_TVDEC_VBI_USER_FRAME_PAT0_REG020H, 0x00); - au8522_writereg(state, AU8522_TVDEC_VBI_USER_FRAME_MASK2_REG021H, - 0x00); - au8522_writereg(state, AU8522_TVDEC_VBI_USER_FRAME_MASK1_REG022H, - 0x00); - au8522_writereg(state, AU8522_TVDEC_VBI_USER_FRAME_MASK0_REG023H, - 0x00); - - /* Setup the VBI registers */ - for (i = 0x30; i < 0x60; i++) - au8522_writereg(state, i, 0x40); - - /* For some reason, every register is 0x40 except register 0x44 - (confirmed via the HVR-950q USB capture) */ - au8522_writereg(state, 0x44, 0x60); - - /* Enable VBI (we always do this regardless of whether the user is - viewing closed caption info) */ - au8522_writereg(state, AU8522_TVDEC_VBI_CTRL_H_REG017H, - AU8522_TVDEC_VBI_CTRL_H_REG017H_CCON); - -} - -static void setup_decoder_defaults(struct au8522_state *state, u8 input_mode) -{ - int i; - int filter_coef_type; - - /* Provide reasonable defaults for picture tuning values */ - au8522_writereg(state, AU8522_TVDEC_SHARPNESSREG009H, 0x07); - au8522_writereg(state, AU8522_TVDEC_BRIGHTNESS_REG00AH, 0xed); - state->brightness = 0xed - 128; - au8522_writereg(state, AU8522_TVDEC_CONTRAST_REG00BH, 0x79); - state->contrast = 0x79; - au8522_writereg(state, AU8522_TVDEC_SATURATION_CB_REG00CH, 0x80); - au8522_writereg(state, AU8522_TVDEC_SATURATION_CR_REG00DH, 0x80); - au8522_writereg(state, AU8522_TVDEC_HUE_H_REG00EH, 0x00); - au8522_writereg(state, AU8522_TVDEC_HUE_L_REG00FH, 0x00); - - /* Other decoder registers */ - au8522_writereg(state, AU8522_TVDEC_INT_MASK_REG010H, 0x00); - - if (input_mode == 0x23) { - /* S-Video input mapping */ - au8522_writereg(state, AU8522_VIDEO_MODE_REG011H, 0x04); - } else { - /* All other modes (CVBS/ATVRF etc.) */ - au8522_writereg(state, AU8522_VIDEO_MODE_REG011H, 0x00); - } - - au8522_writereg(state, AU8522_TVDEC_PGA_REG012H, - AU8522_TVDEC_PGA_REG012H_CVBS); - au8522_writereg(state, AU8522_TVDEC_COMB_MODE_REG015H, - AU8522_TVDEC_COMB_MODE_REG015H_CVBS); - au8522_writereg(state, AU8522_TVDED_DBG_MODE_REG060H, - AU8522_TVDED_DBG_MODE_REG060H_CVBS); - au8522_writereg(state, AU8522_TVDEC_FORMAT_CTRL1_REG061H, - AU8522_TVDEC_FORMAT_CTRL1_REG061H_CVBS13); - au8522_writereg(state, AU8522_TVDEC_FORMAT_CTRL2_REG062H, - AU8522_TVDEC_FORMAT_CTRL2_REG062H_CVBS13); - au8522_writereg(state, AU8522_TVDEC_VCR_DET_LLIM_REG063H, - AU8522_TVDEC_VCR_DET_LLIM_REG063H_CVBS); - au8522_writereg(state, AU8522_TVDEC_VCR_DET_HLIM_REG064H, - AU8522_TVDEC_VCR_DET_HLIM_REG064H_CVBS); - au8522_writereg(state, AU8522_TVDEC_COMB_VDIF_THR1_REG065H, - AU8522_TVDEC_COMB_VDIF_THR1_REG065H_CVBS); - au8522_writereg(state, AU8522_TVDEC_COMB_VDIF_THR2_REG066H, - AU8522_TVDEC_COMB_VDIF_THR2_REG066H_CVBS); - au8522_writereg(state, AU8522_TVDEC_COMB_VDIF_THR3_REG067H, - AU8522_TVDEC_COMB_VDIF_THR3_REG067H_CVBS); - au8522_writereg(state, AU8522_TVDEC_COMB_NOTCH_THR_REG068H, - AU8522_TVDEC_COMB_NOTCH_THR_REG068H_CVBS); - au8522_writereg(state, AU8522_TVDEC_COMB_HDIF_THR1_REG069H, - AU8522_TVDEC_COMB_HDIF_THR1_REG069H_CVBS); - au8522_writereg(state, AU8522_TVDEC_COMB_HDIF_THR2_REG06AH, - AU8522_TVDEC_COMB_HDIF_THR2_REG06AH_CVBS); - au8522_writereg(state, AU8522_TVDEC_COMB_HDIF_THR3_REG06BH, - AU8522_TVDEC_COMB_HDIF_THR3_REG06BH_CVBS); - au8522_writereg(state, AU8522_TVDEC_COMB_DCDIF_THR1_REG06CH, - AU8522_TVDEC_COMB_DCDIF_THR1_REG06CH_CVBS); - au8522_writereg(state, AU8522_TVDEC_COMB_DCDIF_THR2_REG06DH, - AU8522_TVDEC_COMB_DCDIF_THR2_REG06DH_CVBS); - au8522_writereg(state, AU8522_TVDEC_COMB_DCDIF_THR3_REG06EH, - AU8522_TVDEC_COMB_DCDIF_THR3_REG06EH_CVBS); - au8522_writereg(state, AU8522_TVDEC_UV_SEP_THR_REG06FH, - AU8522_TVDEC_UV_SEP_THR_REG06FH_CVBS); - au8522_writereg(state, AU8522_TVDEC_COMB_DC_THR1_NTSC_REG070H, - AU8522_TVDEC_COMB_DC_THR1_NTSC_REG070H_CVBS); - au8522_writereg(state, AU8522_REG071H, AU8522_REG071H_CVBS); - au8522_writereg(state, AU8522_REG072H, AU8522_REG072H_CVBS); - au8522_writereg(state, AU8522_TVDEC_COMB_DC_THR2_NTSC_REG073H, - AU8522_TVDEC_COMB_DC_THR2_NTSC_REG073H_CVBS); - au8522_writereg(state, AU8522_REG074H, AU8522_REG074H_CVBS); - au8522_writereg(state, AU8522_REG075H, AU8522_REG075H_CVBS); - au8522_writereg(state, AU8522_TVDEC_DCAGC_CTRL_REG077H, - AU8522_TVDEC_DCAGC_CTRL_REG077H_CVBS); - au8522_writereg(state, AU8522_TVDEC_PIC_START_ADJ_REG078H, - AU8522_TVDEC_PIC_START_ADJ_REG078H_CVBS); - au8522_writereg(state, AU8522_TVDEC_AGC_HIGH_LIMIT_REG079H, - AU8522_TVDEC_AGC_HIGH_LIMIT_REG079H_CVBS); - au8522_writereg(state, AU8522_TVDEC_MACROVISION_SYNC_THR_REG07AH, - AU8522_TVDEC_MACROVISION_SYNC_THR_REG07AH_CVBS); - au8522_writereg(state, AU8522_TVDEC_INTRP_CTRL_REG07BH, - AU8522_TVDEC_INTRP_CTRL_REG07BH_CVBS); - au8522_writereg(state, AU8522_TVDEC_AGC_LOW_LIMIT_REG0E4H, - AU8522_TVDEC_AGC_LOW_LIMIT_REG0E4H_CVBS); - au8522_writereg(state, AU8522_TOREGAAGC_REG0E5H, - AU8522_TOREGAAGC_REG0E5H_CVBS); - au8522_writereg(state, AU8522_REG016H, AU8522_REG016H_CVBS); - - setup_vbi(state, 0); - - if (input_mode == AU8522_INPUT_CONTROL_REG081H_SVIDEO_CH13 || - input_mode == AU8522_INPUT_CONTROL_REG081H_SVIDEO_CH24) { - /* Despite what the table says, for the HVR-950q we still need - to be in CVBS mode for the S-Video input (reason uknown). */ - /* filter_coef_type = 3; */ - filter_coef_type = 5; - } else { - filter_coef_type = 5; - } - - /* Load the Video Decoder Filter Coefficients */ - for (i = 0; i < NUM_FILTER_COEF; i++) { - au8522_writereg(state, filter_coef[i].reg_name, - filter_coef[i].reg_val[filter_coef_type]); - } - - /* It's not clear what these registers are for, but they are always - set to the same value regardless of what mode we're in */ - au8522_writereg(state, AU8522_REG42EH, 0x87); - au8522_writereg(state, AU8522_REG42FH, 0xa2); - au8522_writereg(state, AU8522_REG430H, 0xbf); - au8522_writereg(state, AU8522_REG431H, 0xcb); - au8522_writereg(state, AU8522_REG432H, 0xa1); - au8522_writereg(state, AU8522_REG433H, 0x41); - au8522_writereg(state, AU8522_REG434H, 0x88); - au8522_writereg(state, AU8522_REG435H, 0xc2); - au8522_writereg(state, AU8522_REG436H, 0x3c); -} - -static void au8522_setup_cvbs_mode(struct au8522_state *state) -{ - /* here we're going to try the pre-programmed route */ - au8522_writereg(state, AU8522_MODULE_CLOCK_CONTROL_REG0A3H, - AU8522_MODULE_CLOCK_CONTROL_REG0A3H_CVBS); - - au8522_writereg(state, AU8522_PGA_CONTROL_REG082H, 0x00); - au8522_writereg(state, AU8522_CLAMPING_CONTROL_REG083H, 0x0e); - au8522_writereg(state, AU8522_PGA_CONTROL_REG082H, 0x10); - - au8522_writereg(state, AU8522_INPUT_CONTROL_REG081H, - AU8522_INPUT_CONTROL_REG081H_CVBS_CH1); - - setup_decoder_defaults(state, AU8522_INPUT_CONTROL_REG081H_CVBS_CH1); - - au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H, - AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H_CVBS); -} - -static void au8522_setup_cvbs_tuner_mode(struct au8522_state *state) -{ - /* here we're going to try the pre-programmed route */ - au8522_writereg(state, AU8522_MODULE_CLOCK_CONTROL_REG0A3H, - AU8522_MODULE_CLOCK_CONTROL_REG0A3H_CVBS); - - /* It's not clear why they turn off the PGA before enabling the clamp - control, but the Windows trace does it so we will too... */ - au8522_writereg(state, AU8522_PGA_CONTROL_REG082H, 0x00); - - /* Enable clamping control */ - au8522_writereg(state, AU8522_CLAMPING_CONTROL_REG083H, 0x0e); - - /* Turn on the PGA */ - au8522_writereg(state, AU8522_PGA_CONTROL_REG082H, 0x10); - - /* Set input mode to CVBS on channel 4 with SIF audio input enabled */ - au8522_writereg(state, AU8522_INPUT_CONTROL_REG081H, - AU8522_INPUT_CONTROL_REG081H_CVBS_CH4_SIF); - - setup_decoder_defaults(state, - AU8522_INPUT_CONTROL_REG081H_CVBS_CH4_SIF); - - au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H, - AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H_CVBS); -} - -static void au8522_setup_svideo_mode(struct au8522_state *state) -{ - au8522_writereg(state, AU8522_MODULE_CLOCK_CONTROL_REG0A3H, - AU8522_MODULE_CLOCK_CONTROL_REG0A3H_SVIDEO); - - /* Set input to Y on Channe1, C on Channel 3 */ - au8522_writereg(state, AU8522_INPUT_CONTROL_REG081H, - AU8522_INPUT_CONTROL_REG081H_SVIDEO_CH13); - - /* Disable clamping control (required for S-video) */ - au8522_writereg(state, AU8522_CLAMPING_CONTROL_REG083H, 0x00); - - setup_decoder_defaults(state, - AU8522_INPUT_CONTROL_REG081H_SVIDEO_CH13); - - au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H, - AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H_CVBS); -} - -/* ----------------------------------------------------------------------- */ - -static void disable_audio_input(struct au8522_state *state) -{ - /* This can probably be optimized */ - au8522_writereg(state, AU8522_AUDIO_VOLUME_L_REG0F2H, 0x00); - au8522_writereg(state, AU8522_AUDIO_VOLUME_R_REG0F3H, 0x00); - au8522_writereg(state, AU8522_AUDIO_VOLUME_REG0F4H, 0x00); - au8522_writereg(state, AU8522_I2C_CONTROL_REG1_REG091H, 0x80); - au8522_writereg(state, AU8522_I2C_CONTROL_REG0_REG090H, 0x84); - - au8522_writereg(state, AU8522_ENA_USB_REG101H, 0x00); - au8522_writereg(state, AU8522_AUDIO_VOLUME_L_REG0F2H, 0x7F); - au8522_writereg(state, AU8522_AUDIO_VOLUME_R_REG0F3H, 0x7F); - au8522_writereg(state, AU8522_REG0F9H, AU8522_REG0F9H_AUDIO); - au8522_writereg(state, AU8522_AUDIO_MODE_REG0F1H, 0x40); - - au8522_writereg(state, AU8522_GPIO_DATA_REG0E2H, 0x11); - msleep(5); - au8522_writereg(state, AU8522_GPIO_DATA_REG0E2H, 0x00); - - au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_1_REG0A5H, 0x04); - au8522_writereg(state, AU8522_AUDIOFREQ_REG606H, 0x03); - au8522_writereg(state, AU8522_I2S_CTRL_2_REG112H, 0x02); - - au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H, - AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H_CVBS); -} - -/* 0=disable, 1=SIF */ -static void set_audio_input(struct au8522_state *state, int aud_input) -{ - int i; - - /* Note that this function needs to be used in conjunction with setting - the input routing via register 0x81 */ - - if (aud_input == AU8522_AUDIO_NONE) { - disable_audio_input(state); - return; - } - - if (aud_input != AU8522_AUDIO_SIF) { - /* The caller asked for a mode we don't currently support */ - printk(KERN_ERR "Unsupported audio mode requested! mode=%d\n", - aud_input); - return; - } - - /* Load the Audio Decoder Filter Coefficients */ - for (i = 0; i < NUM_LPFILTER_COEF; i++) { - au8522_writereg(state, lpfilter_coef[i].reg_name, - lpfilter_coef[i].reg_val[0]); - } - - /* Setup audio */ - au8522_writereg(state, AU8522_AUDIO_VOLUME_L_REG0F2H, 0x00); - au8522_writereg(state, AU8522_AUDIO_VOLUME_R_REG0F3H, 0x00); - au8522_writereg(state, AU8522_AUDIO_VOLUME_REG0F4H, 0x00); - au8522_writereg(state, AU8522_I2C_CONTROL_REG1_REG091H, 0x80); - au8522_writereg(state, AU8522_I2C_CONTROL_REG0_REG090H, 0x84); - msleep(150); - au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H, 0x00); - msleep(1); - au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H, 0x9d); - msleep(50); - au8522_writereg(state, AU8522_AUDIO_VOLUME_L_REG0F2H, 0x7F); - au8522_writereg(state, AU8522_AUDIO_VOLUME_R_REG0F3H, 0x7F); - au8522_writereg(state, AU8522_AUDIO_VOLUME_REG0F4H, 0xff); - msleep(80); - au8522_writereg(state, AU8522_AUDIO_VOLUME_L_REG0F2H, 0x7F); - au8522_writereg(state, AU8522_AUDIO_VOLUME_R_REG0F3H, 0x7F); - au8522_writereg(state, AU8522_REG0F9H, AU8522_REG0F9H_AUDIO); - au8522_writereg(state, AU8522_AUDIO_MODE_REG0F1H, 0x82); - msleep(70); - au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_1_REG0A5H, 0x09); - au8522_writereg(state, AU8522_AUDIOFREQ_REG606H, 0x03); - au8522_writereg(state, AU8522_I2S_CTRL_2_REG112H, 0xc2); -} - -/* ----------------------------------------------------------------------- */ - -static int au8522_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) -{ - struct au8522_state *state = to_state(sd); - - switch (ctrl->id) { - case V4L2_CID_BRIGHTNESS: - state->brightness = ctrl->value; - au8522_writereg(state, AU8522_TVDEC_BRIGHTNESS_REG00AH, - ctrl->value - 128); - break; - case V4L2_CID_CONTRAST: - state->contrast = ctrl->value; - au8522_writereg(state, AU8522_TVDEC_CONTRAST_REG00BH, - ctrl->value); - break; - case V4L2_CID_SATURATION: - case V4L2_CID_HUE: - case V4L2_CID_AUDIO_VOLUME: - case V4L2_CID_AUDIO_BASS: - case V4L2_CID_AUDIO_TREBLE: - case V4L2_CID_AUDIO_BALANCE: - case V4L2_CID_AUDIO_MUTE: - /* Not yet implemented */ - default: - return -EINVAL; - } - - return 0; -} - -static int au8522_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) -{ - struct au8522_state *state = to_state(sd); - - /* Note that we are using values cached in the state structure instead - of reading the registers due to issues with i2c reads not working - properly/consistently yet on the HVR-950q */ - - switch (ctrl->id) { - case V4L2_CID_BRIGHTNESS: - ctrl->value = state->brightness; - break; - case V4L2_CID_CONTRAST: - ctrl->value = state->contrast; - break; - case V4L2_CID_SATURATION: - case V4L2_CID_HUE: - case V4L2_CID_AUDIO_VOLUME: - case V4L2_CID_AUDIO_BASS: - case V4L2_CID_AUDIO_TREBLE: - case V4L2_CID_AUDIO_BALANCE: - case V4L2_CID_AUDIO_MUTE: - /* Not yet supported */ - default: - return -EINVAL; - } - - return 0; -} - -/* ----------------------------------------------------------------------- */ - -static int au8522_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) -{ - switch (fmt->type) { - default: - return -EINVAL; - } - return 0; -} - -static int au8522_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) -{ - switch (fmt->type) { - case V4L2_BUF_TYPE_VIDEO_CAPTURE: - /* Not yet implemented */ - break; - default: - return -EINVAL; - } - - return 0; -} - -/* ----------------------------------------------------------------------- */ - -#ifdef CONFIG_VIDEO_ADV_DEBUG -static int au8522_g_register(struct v4l2_subdev *sd, - struct v4l2_dbg_register *reg) -{ - struct i2c_client *client = v4l2_get_subdevdata(sd); - struct au8522_state *state = to_state(sd); - - if (!v4l2_chip_match_i2c_client(client, ®->match)) - return -EINVAL; - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; - reg->val = au8522_readreg(state, reg->reg & 0xffff); - return 0; -} - -static int au8522_s_register(struct v4l2_subdev *sd, - struct v4l2_dbg_register *reg) -{ - struct i2c_client *client = v4l2_get_subdevdata(sd); - struct au8522_state *state = to_state(sd); - - if (!v4l2_chip_match_i2c_client(client, ®->match)) - return -EINVAL; - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; - au8522_writereg(state, reg->reg, reg->val & 0xff); - return 0; -} -#endif - -static int au8522_s_stream(struct v4l2_subdev *sd, int enable) -{ - struct au8522_state *state = to_state(sd); - - if (enable) { - au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H, - 0x01); - msleep(1); - au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H, - AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H_CVBS); - } else { - /* This does not completely power down the device - (it only reduces it from around 140ma to 80ma) */ - au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H, - 1 << 5); - } - return 0; -} - -static int au8522_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc) -{ - switch (qc->id) { - case V4L2_CID_CONTRAST: - return v4l2_ctrl_query_fill(qc, 0, 255, 1, - AU8522_TVDEC_CONTRAST_REG00BH_CVBS); - case V4L2_CID_BRIGHTNESS: - return v4l2_ctrl_query_fill(qc, 0, 255, 1, 128); - case V4L2_CID_SATURATION: - case V4L2_CID_HUE: - /* Not yet implemented */ - default: - break; - } - - qc->type = 0; - return -EINVAL; -} - -static int au8522_reset(struct v4l2_subdev *sd, u32 val) -{ - struct au8522_state *state = to_state(sd); - - au8522_writereg(state, 0xa4, 1 << 5); - - return 0; -} - -static int au8522_s_video_routing(struct v4l2_subdev *sd, - const struct v4l2_routing *route) -{ - struct au8522_state *state = to_state(sd); - - au8522_reset(sd, 0); - - /* Jam open the i2c gate to the tuner. We do this here to handle the - case where the user went into digital mode (causing the gate to be - closed), and then came back to analog mode */ - au8522_writereg(state, 0x106, 1); - - if (route->input == AU8522_COMPOSITE_CH1) { - au8522_setup_cvbs_mode(state); - } else if (route->input == AU8522_SVIDEO_CH13) { - au8522_setup_svideo_mode(state); - } else if (route->input == AU8522_COMPOSITE_CH4_SIF) { - au8522_setup_cvbs_tuner_mode(state); - } else { - printk(KERN_ERR "au8522 mode not currently supported\n"); - return -EINVAL; - } - return 0; -} - -static int au8522_s_audio_routing(struct v4l2_subdev *sd, - const struct v4l2_routing *route) -{ - struct au8522_state *state = to_state(sd); - set_audio_input(state, route->input); - return 0; -} - -static int au8522_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt) -{ - int val = 0; - struct au8522_state *state = to_state(sd); - u8 lock_status; - - /* Interrogate the decoder to see if we are getting a real signal */ - lock_status = au8522_readreg(state, 0x00); - if (lock_status == 0xa2) - vt->signal = 0x01; - else - vt->signal = 0x00; - - vt->capability |= - V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_LANG1 | - V4L2_TUNER_CAP_LANG2 | V4L2_TUNER_CAP_SAP; - - val = V4L2_TUNER_SUB_MONO; - vt->rxsubchans = val; - vt->audmode = V4L2_TUNER_MODE_STEREO; - return 0; -} - -static int au8522_g_chip_ident(struct v4l2_subdev *sd, - struct v4l2_dbg_chip_ident *chip) -{ - struct au8522_state *state = to_state(sd); - struct i2c_client *client = v4l2_get_subdevdata(sd); - - return v4l2_chip_ident_i2c_client(client, chip, state->id, state->rev); -} - -static int au8522_log_status(struct v4l2_subdev *sd) -{ - /* FIXME: Add some status info here */ - return 0; -} - -static int au8522_command(struct i2c_client *client, unsigned cmd, void *arg) -{ - return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg); -} - -/* ----------------------------------------------------------------------- */ - -static const struct v4l2_subdev_core_ops au8522_core_ops = { - .log_status = au8522_log_status, - .g_chip_ident = au8522_g_chip_ident, - .g_ctrl = au8522_g_ctrl, - .s_ctrl = au8522_s_ctrl, - .queryctrl = au8522_queryctrl, - .reset = au8522_reset, -#ifdef CONFIG_VIDEO_ADV_DEBUG - .g_register = au8522_g_register, - .s_register = au8522_s_register, -#endif -}; - -static const struct v4l2_subdev_tuner_ops au8522_tuner_ops = { - .g_tuner = au8522_g_tuner, -}; - -static const struct v4l2_subdev_audio_ops au8522_audio_ops = { - .s_routing = au8522_s_audio_routing, -}; - -static const struct v4l2_subdev_video_ops au8522_video_ops = { - .s_routing = au8522_s_video_routing, - .g_fmt = au8522_g_fmt, - .s_fmt = au8522_s_fmt, - .s_stream = au8522_s_stream, -}; - -static const struct v4l2_subdev_ops au8522_ops = { - .core = &au8522_core_ops, - .tuner = &au8522_tuner_ops, - .audio = &au8522_audio_ops, - .video = &au8522_video_ops, -}; - -/* ----------------------------------------------------------------------- */ - -static int au8522_probe(struct i2c_client *client, - const struct i2c_device_id *did) -{ - struct au8522_state *state; - struct v4l2_subdev *sd; - int instance; - struct au8522_config *demod_config; - - /* Check if the adapter supports the needed features */ - if (!i2c_check_functionality(client->adapter, - I2C_FUNC_SMBUS_BYTE_DATA)) { - return -EIO; - } - - /* allocate memory for the internal state */ - instance = au8522_get_state(&state, client->adapter, client->addr); - switch (instance) { - case 0: - printk(KERN_ERR "au8522_decoder allocation failed\n"); - return -EIO; - case 1: - /* new demod instance */ - printk(KERN_INFO "au8522_decoder creating new instance...\n"); - break; - default: - /* existing demod instance */ - printk(KERN_INFO "au8522_decoder attach existing instance.\n"); - break; - } - - demod_config = kzalloc(sizeof(struct au8522_config), GFP_KERNEL); - demod_config->demod_address = 0x8e >> 1; - - state->config = demod_config; - state->i2c = client->adapter; - - sd = &state->sd; - v4l2_i2c_subdev_init(sd, client, &au8522_ops); - - state->c = client; - state->vid_input = AU8522_COMPOSITE_CH1; - state->aud_input = AU8522_AUDIO_NONE; - state->id = 8522; - state->rev = 0; - - /* Jam open the i2c gate to the tuner */ - au8522_writereg(state, 0x106, 1); - - return 0; -} - -static int au8522_remove(struct i2c_client *client) -{ - struct v4l2_subdev *sd = i2c_get_clientdata(client); - v4l2_device_unregister_subdev(sd); - au8522_release_state(to_state(sd)); - return 0; -} - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) -static const struct i2c_device_id au8522_id[] = { - {"au8522", 0}, - {} -}; - -MODULE_DEVICE_TABLE(i2c, au8522_id); - -#endif -static struct v4l2_i2c_driver_data v4l2_i2c_data = { - .name = "au8522", - .driverid = I2C_DRIVERID_AU8522, - .command = au8522_command, - .probe = au8522_probe, - .remove = au8522_remove, -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) - .id_table = au8522_id, -#endif -}; -- cgit v1.2.3 From 90392426eb668074c09657baee8b2f4cf06c8b5e Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Sun, 15 Mar 2009 19:01:53 -0400 Subject: au0828: finish videodev/subdev conversion From: Devin Heitmueller Per Hans Verkuil instruction, remove the deprecated attach_inform/detach_inform routines, and convert over the i2c calls to subdev calls. Thanks to Hans Verkuil for providing feedback on the au0828 analog support. Priority: normal Signed-off-by: Devin Heitmueller --- linux/drivers/media/video/au0828/au0828-cards.c | 3 ++- linux/drivers/media/video/au0828/au0828-i2c.c | 29 ---------------------- linux/drivers/media/video/au0828/au0828-video.c | 32 +++++++++++-------------- linux/drivers/media/video/au0828/au0828.h | 2 -- 4 files changed, 16 insertions(+), 50 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 1b48eb58a..1aabaa7e5 100644 --- a/linux/drivers/media/video/au0828/au0828-cards.c +++ b/linux/drivers/media/video/au0828/au0828-cards.c @@ -218,7 +218,8 @@ void au0828_card_setup(struct au0828_dev *dev) tun_setup.type = dev->board.tuner_type; tun_setup.addr = dev->board.tuner_addr; tun_setup.tuner_callback = au0828_tuner_callback; - au0828_call_i2c_clients(dev, TUNER_SET_TYPE_ADDR, &tun_setup); + v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_type_addr, + &tun_setup); } } diff --git a/linux/drivers/media/video/au0828/au0828-i2c.c b/linux/drivers/media/video/au0828/au0828-i2c.c index 3f99b4153..eb63166f6 100644 --- a/linux/drivers/media/video/au0828/au0828-i2c.c +++ b/linux/drivers/media/video/au0828/au0828-i2c.c @@ -300,33 +300,6 @@ err: return retval; } -static int attach_inform(struct i2c_client *client) -{ - dprintk(1, "%s i2c attach [addr=0x%x,client=%s]\n", - client->driver->driver.name, client->addr, client->name); - - if (!client->driver->command) - return 0; - - return 0; -} - -static int detach_inform(struct i2c_client *client) -{ - dprintk(1, "i2c detach [client=%s]\n", client->name); - - return 0; -} - -void au0828_call_i2c_clients(struct au0828_dev *dev, - unsigned int cmd, void *arg) -{ - if (dev->i2c_rc != 0) - return; - - i2c_clients_command(&dev->i2c_adap, cmd, arg); -} - static u32 au0828_functionality(struct i2c_adapter *adap) { return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_I2C; @@ -347,8 +320,6 @@ static struct i2c_adapter au0828_i2c_adap_template = { .owner = THIS_MODULE, .id = I2C_HW_B_AU0828, .algo = &au0828_i2c_algo_template, - .client_register = attach_inform, - .client_unregister = detach_inform, }; static struct i2c_client au0828_i2c_client_template = { diff --git a/linux/drivers/media/video/au0828/au0828-video.c b/linux/drivers/media/video/au0828/au0828-video.c index d3e7cd98c..ab3fe32e8 100644 --- a/linux/drivers/media/video/au0828/au0828-video.c +++ b/linux/drivers/media/video/au0828/au0828-video.c @@ -1000,7 +1000,7 @@ static int vidioc_queryctrl(struct file *file, void *priv, { struct au0828_fh *fh = priv; struct au0828_dev *dev = fh->dev; - au0828_call_i2c_clients(dev, VIDIOC_QUERYCTRL, qc); + v4l2_device_call_all(&dev->v4l2_dev, 0, core, queryctrl, qc); if (qc->type) return 0; else @@ -1104,7 +1104,7 @@ static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id * norm) have to make the au0828 bridge adjust the size of its capture buffer, which is currently hardcoded at 720x480 */ - au0828_call_i2c_clients(dev, VIDIOC_S_STD, norm); + v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_std, *norm); return 0; } @@ -1186,7 +1186,7 @@ static int vidioc_s_input(struct file *file, void *priv, unsigned int index) route.input = AUVI_INPUT(index).vmux; route.output = 0; - au0828_call_i2c_clients(dev, VIDIOC_INT_S_VIDEO_ROUTING, &route); + v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_routing, &route); for (i = 0; i < AU0828_MAX_INPUT; i++) { int enable = 0; @@ -1210,8 +1210,7 @@ static int vidioc_s_input(struct file *file, void *priv, unsigned int index) } route.input = AUVI_INPUT(index).amux; - au0828_call_i2c_clients(dev, VIDIOC_INT_S_AUDIO_ROUTING, - &route); + v4l2_device_call_all(&dev->v4l2_dev, 0, audio, s_routing, &route); return 0; } @@ -1250,7 +1249,7 @@ static int vidioc_g_ctrl(struct file *file, void *priv, struct au0828_fh *fh = priv; struct au0828_dev *dev = fh->dev; - au0828_call_i2c_clients(dev, VIDIOC_G_CTRL, ctrl); + v4l2_device_call_all(&dev->v4l2_dev, 0, core, g_ctrl, ctrl); return 0; } @@ -1260,7 +1259,7 @@ static int vidioc_s_ctrl(struct file *file, void *priv, { struct au0828_fh *fh = priv; struct au0828_dev *dev = fh->dev; - au0828_call_i2c_clients(dev, VIDIOC_S_CTRL, ctrl); + v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_ctrl, ctrl); return 0; } @@ -1273,8 +1272,7 @@ static int vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t) return -EINVAL; strcpy(t->name, "Auvitek tuner"); - - au0828_call_i2c_clients(dev, VIDIOC_G_TUNER, t); + v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, g_tuner, t); return 0; } @@ -1288,7 +1286,7 @@ static int vidioc_s_tuner(struct file *file, void *priv, return -EINVAL; t->type = V4L2_TUNER_ANALOG_TV; - au0828_call_i2c_clients(dev, VIDIOC_S_TUNER, t); + v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_tuner, t); dprintk(1, "VIDIOC_S_TUNER: signal = %x, afc = %x\n", t->signal, t->afc); return 0; @@ -1319,7 +1317,7 @@ static int vidioc_s_frequency(struct file *file, void *priv, dev->ctrl_freq = freq->frequency; - au0828_call_i2c_clients(dev, VIDIOC_S_FREQUENCY, freq); + v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_frequency, freq); au0828_analog_stream_reset(dev); @@ -1339,7 +1337,7 @@ static int vidioc_g_chip_ident(struct file *file, void *priv, return 0; } - au0828_call_i2c_clients(dev, VIDIOC_DBG_G_CHIP_IDENT, chip); + v4l2_device_call_all(&dev->v4l2_dev, 0, core, g_chip_ident, chip); if (chip->ident == V4L2_IDENT_NONE) return -EINVAL; @@ -1373,7 +1371,6 @@ static int vidioc_streamon(struct file *file, void *priv, { struct au0828_fh *fh = priv; struct au0828_dev *dev = fh->dev; - int b = V4L2_BUF_TYPE_VIDEO_CAPTURE; int rc; rc = check_dev(dev); @@ -1382,7 +1379,7 @@ static int vidioc_streamon(struct file *file, void *priv, if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { au0828_analog_stream_enable(dev); - au0828_call_i2c_clients(dev, VIDIOC_STREAMON, &b); + v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_stream, 1); } mutex_lock(&dev->lock); @@ -1400,7 +1397,6 @@ static int vidioc_streamoff(struct file *file, void *priv, { struct au0828_fh *fh = priv; struct au0828_dev *dev = fh->dev; - int b = V4L2_BUF_TYPE_VIDEO_CAPTURE; int i; int ret; int rc; @@ -1415,7 +1411,7 @@ static int vidioc_streamoff(struct file *file, void *priv, return -EINVAL; if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { - au0828_call_i2c_clients(dev, VIDIOC_STREAMOFF, &b); + v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_stream, 0); ret = au0828_stream_interrupt(dev); if (ret != 0) return ret; @@ -1443,7 +1439,7 @@ static int vidioc_g_register(struct file *file, void *priv, switch (reg->match.type) { case V4L2_CHIP_MATCH_I2C_DRIVER: - au0828_call_i2c_clients(dev, VIDIOC_DBG_G_REGISTER, reg); + v4l2_device_call_all(&dev->v4l2_dev, 0, core, g_register, reg); return 0; default: return -EINVAL; @@ -1458,7 +1454,7 @@ static int vidioc_s_register(struct file *file, void *priv, switch (reg->match.type) { case V4L2_CHIP_MATCH_I2C_DRIVER: - au0828_call_i2c_clients(dev, VIDIOC_DBG_S_REGISTER, reg); + v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_register, reg); return 0; default: return -EINVAL; diff --git a/linux/drivers/media/video/au0828/au0828.h b/linux/drivers/media/video/au0828/au0828.h index 6d9bd454e..6ed1a6129 100644 --- a/linux/drivers/media/video/au0828/au0828.h +++ b/linux/drivers/media/video/au0828/au0828.h @@ -265,8 +265,6 @@ extern void au0828_card_setup(struct au0828_dev *dev); /* au0828-i2c.c */ extern int au0828_i2c_register(struct au0828_dev *dev); extern int au0828_i2c_unregister(struct au0828_dev *dev); -extern void au0828_call_i2c_clients(struct au0828_dev *dev, - unsigned int cmd, void *arg); /* ----------------------------------------------------------- */ /* au0828-video.c */ -- cgit v1.2.3 From d42d95e43ed8a60e001ff0a8a4f323380098be7d Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Sun, 15 Mar 2009 19:05:51 -0400 Subject: au8522: finish conversion to v4l2_device/subdev From: Devin Heitmueller Per Hans Verkuil instruction, remove the au8522_command and replace v4l2-i2c-drv-legacy.h with v4l2-i2c-drv.h Thanks to Hans Verkuil for reviewing the au8522 analog support. Priority: normal Signed-off-by: Devin Heitmueller --- linux/drivers/media/dvb/frontends/au8522_decoder.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/frontends/au8522_decoder.c b/linux/drivers/media/dvb/frontends/au8522_decoder.c index b4a205809..7c782b8d5 100644 --- a/linux/drivers/media/dvb/frontends/au8522_decoder.c +++ b/linux/drivers/media/dvb/frontends/au8522_decoder.c @@ -37,7 +37,7 @@ #include #include #include -#include +#include #include #include "compat.h" #include "au8522.h" @@ -726,11 +726,6 @@ static int au8522_log_status(struct v4l2_subdev *sd) return 0; } -static int au8522_command(struct i2c_client *client, unsigned cmd, void *arg) -{ - return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg); -} - /* ----------------------------------------------------------------------- */ static const struct v4l2_subdev_core_ops au8522_core_ops = { @@ -841,7 +836,6 @@ MODULE_DEVICE_TABLE(i2c, au8522_id); static struct v4l2_i2c_driver_data v4l2_i2c_data = { .name = "au8522", .driverid = I2C_DRIVERID_AU8522, - .command = au8522_command, .probe = au8522_probe, .remove = au8522_remove, #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) -- cgit v1.2.3 From 1240f4399ff2f3a7bd5c82ade669cdb388809dda Mon Sep 17 00:00:00 2001 From: Abylay Ospan Date: Wed, 18 Mar 2009 00:13:52 +0300 Subject: Bug fix in NetUP: restore high address lines in CI From: Abylay Ospan CI high address lines disappears due to wrong data type used. Patch to fix it. Signed-off-by: Abylay Ospan --- linux/drivers/media/video/cx23885/cimax2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/cx23885/cimax2.c b/linux/drivers/media/video/cx23885/cimax2.c index 193d9b4cc..0e29f97f3 100644 --- a/linux/drivers/media/video/cx23885/cimax2.c +++ b/linux/drivers/media/video/cx23885/cimax2.c @@ -157,7 +157,7 @@ int netup_ci_get_mem(struct cx23885_dev *dev) } int netup_ci_op_cam(struct dvb_ca_en50221 *en50221, int slot, - u8 flag, u8 read, u8 addr, u8 data) + u8 flag, u8 read, int addr, u8 data) { struct netup_ci_state *state = en50221->data; struct cx23885_tsport *port = state->priv; -- cgit v1.2.3 From 72323c965e7e5472d7e8bc29775b1205cad63c78 Mon Sep 17 00:00:00 2001 From: Abylay Ospan Date: Wed, 18 Mar 2009 00:21:18 +0300 Subject: Fix CiMax stability in Netup Dual DVB-S2 CI From: Abylay Ospan It appears TS discontinuity about one per 10 hrs if CAM used. Patch to fix it. Signed-off-by: Abylay Ospan --- linux/drivers/media/dvb/frontends/stv0900_core.c | 2 +- linux/drivers/media/dvb/frontends/stv0900_init.h | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/frontends/stv0900_core.c b/linux/drivers/media/dvb/frontends/stv0900_core.c index 67cce764f..899b1e7ed 100644 --- a/linux/drivers/media/dvb/frontends/stv0900_core.c +++ b/linux/drivers/media/dvb/frontends/stv0900_core.c @@ -254,7 +254,7 @@ enum fe_stv0900_error stv0900_initialize(struct stv0900_internal *i_params) } msleep(3); - for (i = 0; i < 180; i++) + for (i = 0; i < 182; i++) stv0900_write_reg(i_params, STV0900_InitVal[i][0], STV0900_InitVal[i][1]); if (stv0900_read_reg(i_params, R0900_MID) >= 0x20) { diff --git a/linux/drivers/media/dvb/frontends/stv0900_init.h b/linux/drivers/media/dvb/frontends/stv0900_init.h index fa8dbe197..ff388b47a 100644 --- a/linux/drivers/media/dvb/frontends/stv0900_init.h +++ b/linux/drivers/media/dvb/frontends/stv0900_init.h @@ -217,7 +217,7 @@ static const struct stv0900_short_frames_car_loop_optim FE_STV0900_S2ShortCarLoo { STV0900_32APSK, 0x1B, 0x1E, 0x1B, 0x1E, 0x1B, 0x1E, 0x3A, 0x3D, 0x2A, 0x2D } }; -static const u16 STV0900_InitVal[180][2] = { +static const u16 STV0900_InitVal[182][2] = { { R0900_OUTCFG , 0x00 }, { R0900_MODECFG , 0xff }, { R0900_AGCRF1CFG , 0x11 }, @@ -396,6 +396,8 @@ static const u16 STV0900_InitVal[180][2] = { { R0900_DATA72CFG , 0x52 }, { R0900_P1_TSCFGM , 0xc0 }, { R0900_P2_TSCFGM , 0xc0 }, + { R0900_P1_TSCFGH , 0xe0 }, /* DVB-CI timings */ + { R0900_P2_TSCFGH , 0xe0 }, /* DVB-CI timings */ { R0900_P1_TSSPEED , 0x40 }, { R0900_P2_TSSPEED , 0x40 }, }; -- cgit v1.2.3 From d6571db03763326af6865e6af1b993f29cf48316 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 18 Mar 2009 13:13:19 -0300 Subject: au0828-video: needs linux/version.h for in-kernel build From: Mauro Carvalho Chehab kernel-sync: Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/au0828/au0828-video.c | 1 + 1 file changed, 1 insertion(+) (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 ab3fe32e8..cd75b5dbf 100644 --- a/linux/drivers/media/video/au0828/au0828-video.c +++ b/linux/drivers/media/video/au0828/au0828-video.c @@ -32,6 +32,7 @@ #include #include #include +#include #include #include #include -- cgit v1.2.3 From 50273dcede46249b603809c83a2cc5df83c0b2d1 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 18 Mar 2009 17:59:34 +0100 Subject: tvaudio: fix mute and s/g_tuner handling From: Hans Verkuil The mute control depends on CHIP_HAS_INPUTSEL, so test for that first. The s/g_tuner code should check whether getmode/setmode is set at the beginning instead of filling in the struct and discovering at the end that this chip doesn't implement audiomodes after all (i.e. is a simple muxer chip). Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/tvaudio.c | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/tvaudio.c b/linux/drivers/media/video/tvaudio.c index d630dca83..062fa6e36 100644 --- a/linux/drivers/media/video/tvaudio.c +++ b/linux/drivers/media/video/tvaudio.c @@ -1519,6 +1519,8 @@ static int tvaudio_g_ctrl(struct v4l2_subdev *sd, switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: + if (!(desc->flags & CHIP_HAS_INPUTSEL)) + break; ctrl->value=chip->muted; return 0; case V4L2_CID_AUDIO_VOLUME: @@ -1560,6 +1562,9 @@ static int tvaudio_s_ctrl(struct v4l2_subdev *sd, switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: + if (!(desc->flags & CHIP_HAS_INPUTSEL)) + break; + if (ctrl->value < 0 || ctrl->value >= 2) return -ERANGE; chip->muted = ctrl->value; @@ -1644,7 +1649,9 @@ static int tvaudio_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc) switch (qc->id) { case V4L2_CID_AUDIO_MUTE: - return v4l2_ctrl_query_fill(qc, 0, 1, 1, 0); + if (desc->flags & CHIP_HAS_INPUTSEL) + return v4l2_ctrl_query_fill(qc, 0, 1, 1, 0); + break; case V4L2_CID_AUDIO_VOLUME: if (desc->flags & CHIP_HAS_VOLUME) return v4l2_ctrl_query_fill(qc, 0, 65535, 65535 / 100, 58880); @@ -1669,7 +1676,9 @@ static int tvaudio_s_routing(struct v4l2_subdev *sd, const struct v4l2_routing * struct CHIPSTATE *chip = to_state(sd); struct CHIPDESC *desc = chip->desc; - if (!(desc->flags & CHIP_HAS_INPUTSEL) || rt->input >= 4) + if (!(desc->flags & CHIP_HAS_INPUTSEL)) + return 0; + if (rt->input >= 4) return -EINVAL; /* There are four inputs: tuner, radio, extern and intern. */ chip->input = rt->input; @@ -1686,8 +1695,11 @@ static int tvaudio_s_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt) struct CHIPDESC *desc = chip->desc; int mode = 0; + if (!desc->setmode) + return 0; if (chip->radio) return 0; + switch (vt->audmode) { case V4L2_TUNER_MODE_MONO: case V4L2_TUNER_MODE_STEREO: @@ -1703,7 +1715,7 @@ static int tvaudio_s_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt) } chip->audmode = vt->audmode; - if (desc->setmode && mode) { + if (mode) { chip->watch_stereo = 0; /* del_timer(&chip->wt); */ chip->mode = mode; @@ -1718,15 +1730,17 @@ static int tvaudio_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt) struct CHIPDESC *desc = chip->desc; int mode = V4L2_TUNER_MODE_MONO; + if (!desc->getmode) + return 0; if (chip->radio) return 0; + vt->audmode = chip->audmode; vt->rxsubchans = 0; vt->capability = V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_LANG1 | V4L2_TUNER_CAP_LANG2; - if (desc->getmode) - mode = desc->getmode(chip); + mode = desc->getmode(chip); if (mode & V4L2_TUNER_MODE_MONO) vt->rxsubchans |= V4L2_TUNER_SUB_MONO; -- cgit v1.2.3 From ceb4d90514c368c0353069f902ab419f0957f142 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 18 Mar 2009 18:02:36 +0100 Subject: tvaudio: add tda9875 support. From: Hans Verkuil This change allows bttv to use tvaudio for this device. Since this device has the same i2c address as the tda9874 we need to support both in the same tvaudio driver. This makes it possible for tvaudio to detect which chip is used. Originally the tda9875 was only available in the dedicated tda9875 driver, but that makes life very hard for bttv since loading tvaudio might misdetect a tda9875 as a tda9874. Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/tvaudio.c | 132 ++++++++++++++++++++++++++++++++++++ 1 file changed, 132 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/tvaudio.c b/linux/drivers/media/video/tvaudio.c index 062fa6e36..d92b2d4b5 100644 --- a/linux/drivers/media/video/tvaudio.c +++ b/linux/drivers/media/video/tvaudio.c @@ -1055,6 +1055,116 @@ static int tda9874a_initialize(struct CHIPSTATE *chip) return 0; } +/* ---------------------------------------------------------------------- */ +/* audio chip description - defines+functions for tda9875 */ +/* The TDA9875 is made by Philips Semiconductor + * http://www.semiconductors.philips.com + * TDA9875: I2C-bus controlled DSP audio processor, FM demodulator + * + */ + +/* subaddresses for TDA9875 */ +#define TDA9875_MUT 0x12 /*General mute (value --> 0b11001100*/ +#define TDA9875_CFG 0x01 /* Config register (value --> 0b00000000 */ +#define TDA9875_DACOS 0x13 /*DAC i/o select (ADC) 0b0000100*/ +#define TDA9875_LOSR 0x16 /*Line output select regirter 0b0100 0001*/ + +#define TDA9875_CH1V 0x0c /*Channel 1 volume (mute)*/ +#define TDA9875_CH2V 0x0d /*Channel 2 volume (mute)*/ +#define TDA9875_SC1 0x14 /*SCART 1 in (mono)*/ +#define TDA9875_SC2 0x15 /*SCART 2 in (mono)*/ + +#define TDA9875_ADCIS 0x17 /*ADC input select (mono) 0b0110 000*/ +#define TDA9875_AER 0x19 /*Audio effect (AVL+Pseudo) 0b0000 0110*/ +#define TDA9875_MCS 0x18 /*Main channel select (DAC) 0b0000100*/ +#define TDA9875_MVL 0x1a /* Main volume gauche */ +#define TDA9875_MVR 0x1b /* Main volume droite */ +#define TDA9875_MBA 0x1d /* Main Basse */ +#define TDA9875_MTR 0x1e /* Main treble */ +#define TDA9875_ACS 0x1f /* Auxilary channel select (FM) 0b0000000*/ +#define TDA9875_AVL 0x20 /* Auxilary volume gauche */ +#define TDA9875_AVR 0x21 /* Auxilary volume droite */ +#define TDA9875_ABA 0x22 /* Auxilary Basse */ +#define TDA9875_ATR 0x23 /* Auxilary treble */ + +#define TDA9875_MSR 0x02 /* Monitor select register */ +#define TDA9875_C1MSB 0x03 /* Carrier 1 (FM) frequency register MSB */ +#define TDA9875_C1MIB 0x04 /* Carrier 1 (FM) frequency register (16-8]b */ +#define TDA9875_C1LSB 0x05 /* Carrier 1 (FM) frequency register LSB */ +#define TDA9875_C2MSB 0x06 /* Carrier 2 (nicam) frequency register MSB */ +#define TDA9875_C2MIB 0x07 /* Carrier 2 (nicam) frequency register (16-8]b */ +#define TDA9875_C2LSB 0x08 /* Carrier 2 (nicam) frequency register LSB */ +#define TDA9875_DCR 0x09 /* Demodulateur configuration regirter*/ +#define TDA9875_DEEM 0x0a /* FM de-emphasis regirter*/ +#define TDA9875_FMAT 0x0b /* FM Matrix regirter*/ + +/* values */ +#define TDA9875_MUTE_ON 0xff /* general mute */ +#define TDA9875_MUTE_OFF 0xcc /* general no mute */ + +static int tda9875_initialize(struct CHIPSTATE *chip) +{ + chip_write(chip, TDA9875_CFG, 0xd0); /*reg de config 0 (reset)*/ + chip_write(chip, TDA9875_MSR, 0x03); /* Monitor 0b00000XXX*/ + chip_write(chip, TDA9875_C1MSB, 0x00); /*Car1(FM) MSB XMHz*/ + chip_write(chip, TDA9875_C1MIB, 0x00); /*Car1(FM) MIB XMHz*/ + chip_write(chip, TDA9875_C1LSB, 0x00); /*Car1(FM) LSB XMHz*/ + chip_write(chip, TDA9875_C2MSB, 0x00); /*Car2(NICAM) MSB XMHz*/ + chip_write(chip, TDA9875_C2MIB, 0x00); /*Car2(NICAM) MIB XMHz*/ + chip_write(chip, TDA9875_C2LSB, 0x00); /*Car2(NICAM) LSB XMHz*/ + chip_write(chip, TDA9875_DCR, 0x00); /*Demod config 0x00*/ + chip_write(chip, TDA9875_DEEM, 0x44); /*DE-Emph 0b0100 0100*/ + chip_write(chip, TDA9875_FMAT, 0x00); /*FM Matrix reg 0x00*/ + chip_write(chip, TDA9875_SC1, 0x00); /* SCART 1 (SC1)*/ + chip_write(chip, TDA9875_SC2, 0x01); /* SCART 2 (sc2)*/ + + chip_write(chip, TDA9875_CH1V, 0x10); /* Channel volume 1 mute*/ + chip_write(chip, TDA9875_CH2V, 0x10); /* Channel volume 2 mute */ + chip_write(chip, TDA9875_DACOS, 0x02); /* sig DAC i/o(in:nicam)*/ + chip_write(chip, TDA9875_ADCIS, 0x6f); /* sig ADC input(in:mono)*/ + chip_write(chip, TDA9875_LOSR, 0x00); /* line out (in:mono)*/ + chip_write(chip, TDA9875_AER, 0x00); /*06 Effect (AVL+PSEUDO) */ + chip_write(chip, TDA9875_MCS, 0x44); /* Main ch select (DAC) */ + chip_write(chip, TDA9875_MVL, 0x03); /* Vol Main left 10dB */ + chip_write(chip, TDA9875_MVR, 0x03); /* Vol Main right 10dB*/ + chip_write(chip, TDA9875_MBA, 0x00); /* Main Bass Main 0dB*/ + chip_write(chip, TDA9875_MTR, 0x00); /* Main Treble Main 0dB*/ + chip_write(chip, TDA9875_ACS, 0x44); /* Aux chan select (dac)*/ + chip_write(chip, TDA9875_AVL, 0x00); /* Vol Aux left 0dB*/ + chip_write(chip, TDA9875_AVR, 0x00); /* Vol Aux right 0dB*/ + chip_write(chip, TDA9875_ABA, 0x00); /* Aux Bass Main 0dB*/ + chip_write(chip, TDA9875_ATR, 0x00); /* Aux Aigus Main 0dB*/ + + chip_write(chip, TDA9875_MUT, 0xcc); /* General mute */ + return 0; +} + +static int tda9875_volume(int val) { return (unsigned char)(val / 602 - 84); } +static int tda9875_bass(int val) { return (unsigned char)(max(-12, val / 2115 - 15)); } +static int tda9875_treble(int val) { return (unsigned char)(val / 2622 - 12); } + +/* ----------------------------------------------------------------------- */ + + +/* *********************** * + * i2c interface functions * + * *********************** */ + +static int tda9875_checkit(struct CHIPSTATE *chip) +{ + struct v4l2_subdev *sd = &chip->sd; + int dic, rev; + + dic = chip_read2(chip, 254); + rev = chip_read2(chip, 255); + + if (dic == 0 || dic == 2) { /* tda9875 and tda9875A */ + v4l2_info(sd, "found tda9875%s rev. %d.\n", + dic == 0 ? "" : "A", rev); + return 1; + } + return 0; +} /* ---------------------------------------------------------------------- */ /* audio chip descriptions - defines+functions for tea6420 */ @@ -1288,6 +1398,7 @@ static int tda9850 = 1; static int tda9855 = 1; static int tda9873 = 1; static int tda9874a = 1; +static int tda9875 = 1; static int tea6300; /* default 0 - address clash with msp34xx */ static int tea6320; /* default 0 - address clash with msp34xx */ static int tea6420 = 1; @@ -1300,6 +1411,7 @@ module_param(tda9850, int, 0444); module_param(tda9855, int, 0444); module_param(tda9873, int, 0444); module_param(tda9874a, int, 0444); +module_param(tda9875, int, 0444); module_param(tea6300, int, 0444); module_param(tea6320, int, 0444); module_param(tea6420, int, 0444); @@ -1356,6 +1468,26 @@ static struct CHIPDESC chiplist[] = { .getmode = tda9874a_getmode, .setmode = tda9874a_setmode, }, + { + .name = "tda9875", + .insmodopt = &tda9875, + .addr_lo = I2C_ADDR_TDA9875 >> 1, + .addr_hi = I2C_ADDR_TDA9875 >> 1, + .flags = CHIP_HAS_VOLUME | CHIP_HAS_BASSTREBLE, + + /* callbacks */ + .initialize = tda9875_initialize, + .checkit = tda9875_checkit, + .volfunc = tda9875_volume, + .bassfunc = tda9875_bass, + .treblefunc = tda9875_treble, + .leftreg = TDA9875_MVL, + .rightreg = TDA9875_MVR, + .bassreg = TDA9875_MBA, + .treblereg = TDA9875_MTR, + .leftinit = 58880, + .rightinit = 58880, + }, { .name = "tda9850", .insmodopt = &tda9850, -- cgit v1.2.3 From edcff71d60fb21a8813c06ab97fc0d8746c238b4 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 18 Mar 2009 19:48:01 +0100 Subject: v4l2-common: remove incorrect MODULE test From: Hans Verkuil v4l2-common doesn't have to be a module for it to call request_module(). Just remove that test. Priority: normal Signed-off-by: Hans Verkuil Thanks-to: Guennadi Liakhovetski --- linux/drivers/media/video/v4l2-common.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/v4l2-common.c b/linux/drivers/media/video/v4l2-common.c index 32d0246d5..426a93e8e 100644 --- a/linux/drivers/media/video/v4l2-common.c +++ b/linux/drivers/media/video/v4l2-common.c @@ -828,10 +828,10 @@ struct v4l2_subdev *v4l2_i2c_new_subdev(struct i2c_adapter *adapter, #endif BUG_ON(!dev); -#ifdef MODULE + if (module_name) request_module(module_name); -#endif + #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 22) /* Setup the i2c board info with the device type and the device address. */ @@ -896,10 +896,10 @@ struct v4l2_subdev *v4l2_i2c_new_probed_subdev(struct i2c_adapter *adapter, #endif BUG_ON(!dev); -#ifdef MODULE + if (module_name) request_module(module_name); -#endif + #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 22) /* Setup the i2c board info with the device type and the device address. */ -- cgit v1.2.3 From d36407337888d03d02f7eb6c378a1fd31d6230db Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 18 Mar 2009 20:34:40 +0100 Subject: au0828: fix compilation on kernels 2.6.20 and 2.6.21. From: Hans Verkuil Add missing linux/mm.h include. Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/au0828/au0828-video.c | 1 + 1 file changed, 1 insertion(+) (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 cd75b5dbf..ac5662c59 100644 --- a/linux/drivers/media/video/au0828/au0828-video.c +++ b/linux/drivers/media/video/au0828/au0828-video.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include -- cgit v1.2.3 From 5248d72ef4f84010b6c5d5c2c04face875655ea2 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 18 Mar 2009 20:39:07 +0100 Subject: au8522: fix compilation warning. From: Hans Verkuil normal_i2c and I2C_CLIENT_INSMOD are only necessary for kernels < 2.6.22. Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/dvb/frontends/au8522_decoder.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/frontends/au8522_decoder.c b/linux/drivers/media/dvb/frontends/au8522_decoder.c index 7c782b8d5..70af9cda7 100644 --- a/linux/drivers/media/dvb/frontends/au8522_decoder.c +++ b/linux/drivers/media/dvb/frontends/au8522_decoder.c @@ -48,15 +48,17 @@ MODULE_LICENSE("GPL"); static int au8522_analog_debug; +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22) static unsigned short normal_i2c[] = { 0x8e >> 1, I2C_CLIENT_END }; +I2C_CLIENT_INSMOD; +#endif + module_param_named(analog_debug, au8522_analog_debug, int, 0644); MODULE_PARM_DESC(analog_debug, "Analog debugging messages [0=Off (default) 1=On]"); -I2C_CLIENT_INSMOD; - struct au8522_register_config { u16 reg_name; u8 reg_val[8]; -- cgit v1.2.3 From 06ef9c25f9cb3d2917bdbec1442d954c77b5e66c Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 18 Mar 2009 20:43:14 +0100 Subject: mt9v022: fix compilation warning for kernels < 2.6.26. From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/mt9v022.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/mt9v022.c b/linux/drivers/media/video/mt9v022.c index bec6859b3..3bee30caa 100644 --- a/linux/drivers/media/video/mt9v022.c +++ b/linux/drivers/media/video/mt9v022.c @@ -741,8 +741,12 @@ static void mt9v022_video_remove(struct soc_camera_device *icd) soc_camera_video_stop(icd); } +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) static int mt9v022_probe(struct i2c_client *client, const struct i2c_device_id *did) +#else +static int mt9v022_probe(struct i2c_client *client) +#endif { struct mt9v022 *mt9v022; struct soc_camera_device *icd; -- cgit v1.2.3 From 1b9ff790c05ba49e240edd1f06a6aee8f4a2b194 Mon Sep 17 00:00:00 2001 From: Janne Grunau Date: Wed, 18 Mar 2009 21:00:39 +0100 Subject: adds V4L2_CID_SHARPNESS to v4l2_ctrl_query_fill() From: Janne Grunau Priority: normal Signed-off-by: Janne Grunau --- linux/drivers/media/video/v4l2-common.c | 1 + 1 file changed, 1 insertion(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/v4l2-common.c b/linux/drivers/media/video/v4l2-common.c index 32d0246d5..3c42316c3 100644 --- a/linux/drivers/media/video/v4l2-common.c +++ b/linux/drivers/media/video/v4l2-common.c @@ -570,6 +570,7 @@ int v4l2_ctrl_query_fill(struct v4l2_queryctrl *qctrl, s32 min, s32 max, s32 ste case V4L2_CID_RED_BALANCE: case V4L2_CID_BLUE_BALANCE: case V4L2_CID_GAMMA: + case V4L2_CID_SHARPNESS: qctrl->flags |= V4L2_CTRL_FLAG_SLIDER; break; case V4L2_CID_PAN_RELATIVE: -- cgit v1.2.3 From e0adc6a155bb772f75bb7ce705a226d2c758198b Mon Sep 17 00:00:00 2001 From: Janne Grunau Date: Wed, 18 Mar 2009 22:10:04 +0100 Subject: V4L2 Driver for the Hauppauge HD PVR usb capture device From: Janne Grunau The device encodes component video up to 1080i to a MPEG-TS stream with H.264 video and stereo AAC audio. Newer firmwares accept also AC3 (up to 5.1) audio over optical SPDIF without reencoding. Firmware upgrade is unimplemeted but rather unimportant since the firmware sits on a flash chip. The I2C adapter to drive the integrated infrared receiver/sender is currently disabled due to a conflict with cx18-based devices. Priority: normal Signed-off-by: Janne Grunau Tested-by: Jarod Wilson --- linux/drivers/media/video/Kconfig | 2 + linux/drivers/media/video/Makefile | 2 + linux/drivers/media/video/hdpvr/Kconfig | 10 + linux/drivers/media/video/hdpvr/Makefile | 7 + linux/drivers/media/video/hdpvr/hdpvr-control.c | 201 ++++ linux/drivers/media/video/hdpvr/hdpvr-core.c | 446 ++++++++ linux/drivers/media/video/hdpvr/hdpvr-i2c.c | 145 +++ linux/drivers/media/video/hdpvr/hdpvr-video.c | 1228 +++++++++++++++++++++++ linux/drivers/media/video/hdpvr/hdpvr.h | 298 ++++++ 9 files changed, 2339 insertions(+) create mode 100644 linux/drivers/media/video/hdpvr/Kconfig create mode 100644 linux/drivers/media/video/hdpvr/Makefile create mode 100644 linux/drivers/media/video/hdpvr/hdpvr-control.c create mode 100644 linux/drivers/media/video/hdpvr/hdpvr-core.c create mode 100644 linux/drivers/media/video/hdpvr/hdpvr-i2c.c create mode 100644 linux/drivers/media/video/hdpvr/hdpvr-video.c create mode 100644 linux/drivers/media/video/hdpvr/hdpvr.h (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/Kconfig b/linux/drivers/media/video/Kconfig index 42562e348..114bf04a6 100644 --- a/linux/drivers/media/video/Kconfig +++ b/linux/drivers/media/video/Kconfig @@ -789,6 +789,8 @@ source "drivers/media/video/gspca/Kconfig" source "drivers/media/video/pvrusb2/Kconfig" +source "drivers/media/video/hdpvr/Kconfig" + source "drivers/media/video/em28xx/Kconfig" source "drivers/media/video/cx231xx/Kconfig" diff --git a/linux/drivers/media/video/Makefile b/linux/drivers/media/video/Makefile index 99b448e6c..08765d874 100644 --- a/linux/drivers/media/video/Makefile +++ b/linux/drivers/media/video/Makefile @@ -120,6 +120,8 @@ obj-$(CONFIG_USB_PWC) += pwc/ obj-$(CONFIG_USB_ZC0301) += zc0301/ obj-$(CONFIG_USB_GSPCA) += gspca/ +obj-$(CONFIG_VIDEO_HDPVR) += hdpvr/ + obj-$(CONFIG_USB_IBMCAM) += usbvideo/ obj-$(CONFIG_USB_KONICAWC) += usbvideo/ obj-$(CONFIG_USB_VICAM) += usbvideo/ diff --git a/linux/drivers/media/video/hdpvr/Kconfig b/linux/drivers/media/video/hdpvr/Kconfig new file mode 100644 index 000000000..de247f3c7 --- /dev/null +++ b/linux/drivers/media/video/hdpvr/Kconfig @@ -0,0 +1,10 @@ + +config VIDEO_HDPVR + tristate "Hauppauge HD PVR support" + depends on VIDEO_DEV + ---help--- + This is a video4linux driver for Hauppauge's HD PVR USB device. + + To compile this driver as a module, choose M here: the + module will be called hdpvr + diff --git a/linux/drivers/media/video/hdpvr/Makefile b/linux/drivers/media/video/hdpvr/Makefile new file mode 100644 index 000000000..79ad2e16c --- /dev/null +++ b/linux/drivers/media/video/hdpvr/Makefile @@ -0,0 +1,7 @@ +hdpvr-objs := hdpvr-control.o hdpvr-core.o hdpvr-i2c.o hdpvr-video.o + +obj-$(CONFIG_VIDEO_HDPVR) += hdpvr.o + +EXTRA_CFLAGS += -Idrivers/media/video + +EXTRA_CFLAGS += $(extra-cflags-y) $(extra-cflags-m) diff --git a/linux/drivers/media/video/hdpvr/hdpvr-control.c b/linux/drivers/media/video/hdpvr/hdpvr-control.c new file mode 100644 index 000000000..ecf02c621 --- /dev/null +++ b/linux/drivers/media/video/hdpvr/hdpvr-control.c @@ -0,0 +1,201 @@ +/* + * Hauppage HD PVR USB driver - video 4 linux 2 interface + * + * Copyright (C) 2008 Janne Grunau (j@jannau.net) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, version 2. + * + */ + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include "hdpvr.h" + + +int hdpvr_config_call(struct hdpvr_device *dev, uint value, u8 valbuf) +{ + int ret; + char request_type = 0x38, snd_request = 0x01; + + msleep(10); + + mutex_lock(&dev->usbc_mutex); + dev->usbc_buf[0] = valbuf; + ret = usb_control_msg(dev->udev, + usb_sndctrlpipe(dev->udev, 0), + snd_request, 0x00 | request_type, + value, CTRL_DEFAULT_INDEX, + dev->usbc_buf, 1, 10000); + + mutex_unlock(&dev->usbc_mutex); + dev_dbg(&dev->udev->dev, + "config call request for value 0x%x returned %d\n", value, + ret); + + return ret < 0 ? ret : 0; +} + +struct hdpvr_video_info *get_video_info(struct hdpvr_device *dev) +{ + struct hdpvr_video_info *vidinf = NULL; +#ifdef HDPVR_DEBUG + char print_buf[15]; +#endif + int ret; + + vidinf = kzalloc(sizeof(struct hdpvr_video_info), GFP_KERNEL); + if (!vidinf) { + dev_err(&dev->udev->dev, "out of memory"); + goto err; + } + + mutex_lock(&dev->usbc_mutex); + ret = usb_control_msg(dev->udev, + usb_rcvctrlpipe(dev->udev, 0), + 0x81, 0x80 | 0x38, + 0x1400, 0x0003, + dev->usbc_buf, 5, + 1000); + if (ret == 5) { + vidinf->width = dev->usbc_buf[1] << 8 | dev->usbc_buf[0]; + vidinf->height = dev->usbc_buf[3] << 8 | dev->usbc_buf[2]; + vidinf->fps = dev->usbc_buf[4]; + } + +#ifdef HDPVR_DEBUG + if (hdpvr_debug & MSG_INFO) { + hex_dump_to_buffer(dev->usbc_buf, 5, 16, 1, print_buf, + sizeof(print_buf), 0); + dev_dbg(&dev->udev->dev, "get video info returned: %d, %s\n", + ret, print_buf); + } +#endif + mutex_unlock(&dev->usbc_mutex); + + if (!vidinf->width || !vidinf->height || !vidinf->fps) { + kfree(vidinf); + vidinf = NULL; + } +err: + return vidinf; +} + +int get_input_lines_info(struct hdpvr_device *dev) +{ +#ifdef HDPVR_DEBUG + char print_buf[9]; +#endif + int ret, lines; + + mutex_lock(&dev->usbc_mutex); + ret = usb_control_msg(dev->udev, + usb_rcvctrlpipe(dev->udev, 0), + 0x81, 0x80 | 0x38, + 0x1800, 0x0003, + dev->usbc_buf, 3, + 1000); + +#ifdef HDPVR_DEBUG + if (hdpvr_debug & MSG_INFO) { + hex_dump_to_buffer(dev->usbc_buf, 3, 16, 1, print_buf, + sizeof(print_buf), 0); + dev_dbg(&dev->udev->dev, + "get input lines info returned: %d, %s\n", ret, + print_buf); + } +#endif + lines = dev->usbc_buf[1] << 8 | dev->usbc_buf[0]; + mutex_unlock(&dev->usbc_mutex); + return lines; +} + + +int hdpvr_set_bitrate(struct hdpvr_device *dev) +{ + int ret; + + mutex_lock(&dev->usbc_mutex); + memset(dev->usbc_buf, 0, 4); + dev->usbc_buf[0] = dev->options.bitrate; + dev->usbc_buf[2] = dev->options.peak_bitrate; + + ret = usb_control_msg(dev->udev, + usb_sndctrlpipe(dev->udev, 0), + 0x01, 0x38, CTRL_BITRATE_VALUE, + CTRL_DEFAULT_INDEX, dev->usbc_buf, 4, 1000); + mutex_unlock(&dev->usbc_mutex); + + return ret; +} + +int hdpvr_set_audio(struct hdpvr_device *dev, u8 input, + enum v4l2_mpeg_audio_encoding codec) +{ + int ret = 0; + + if (dev->flags & HDPVR_FLAG_AC3_CAP) { + mutex_lock(&dev->usbc_mutex); + memset(dev->usbc_buf, 0, 2); + dev->usbc_buf[0] = input; + if (codec == V4L2_MPEG_AUDIO_ENCODING_AAC) + dev->usbc_buf[1] = 0; + else if (codec == V4L2_MPEG_AUDIO_ENCODING_AC3) + dev->usbc_buf[1] = 1; + else { + mutex_unlock(&dev->usbc_mutex); + dev_err(&dev->udev->dev, "invalid audio codec %d\n", + codec); + ret = -EINVAL; + goto error; + } + + ret = usb_control_msg(dev->udev, + usb_sndctrlpipe(dev->udev, 0), + 0x01, 0x38, CTRL_AUDIO_INPUT_VALUE, + CTRL_DEFAULT_INDEX, dev->usbc_buf, 2, + 1000); + mutex_unlock(&dev->usbc_mutex); + if (ret == 2) + ret = 0; + } else + ret = hdpvr_config_call(dev, CTRL_AUDIO_INPUT_VALUE, + dev->options.audio_input+1); +error: + return ret; +} + +int hdpvr_set_options(struct hdpvr_device *dev) +{ + hdpvr_config_call(dev, CTRL_VIDEO_STD_TYPE, dev->options.video_std); + + hdpvr_config_call(dev, CTRL_VIDEO_INPUT_VALUE, + dev->options.video_input+1); + + hdpvr_set_audio(dev, dev->options.audio_input+1, + dev->options.audio_codec); + + hdpvr_set_bitrate(dev); + hdpvr_config_call(dev, CTRL_BITRATE_MODE_VALUE, + dev->options.bitrate_mode); + hdpvr_config_call(dev, CTRL_GOP_MODE_VALUE, dev->options.gop_mode); + + hdpvr_config_call(dev, CTRL_BRIGHTNESS, dev->options.brightness); + hdpvr_config_call(dev, CTRL_CONTRAST, dev->options.contrast); + hdpvr_config_call(dev, CTRL_HUE, dev->options.hue); + hdpvr_config_call(dev, CTRL_SATURATION, dev->options.saturation); + hdpvr_config_call(dev, CTRL_SHARPNESS, dev->options.sharpness); + + return 0; +} diff --git a/linux/drivers/media/video/hdpvr/hdpvr-core.c b/linux/drivers/media/video/hdpvr/hdpvr-core.c new file mode 100644 index 000000000..a33b03df0 --- /dev/null +++ b/linux/drivers/media/video/hdpvr/hdpvr-core.c @@ -0,0 +1,446 @@ +/* + * Hauppage HD PVR USB driver + * + * Copyright (C) 2001-2004 Greg Kroah-Hartman (greg@kroah.com) + * Copyright (C) 2008 Janne Grunau (j@jannau.net) + * Copyright (C) 2008 John Poet + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, version 2. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "hdpvr.h" + +static int video_nr[HDPVR_MAX] = {[0 ... (HDPVR_MAX - 1)] = UNSET}; +module_param_array(video_nr, int, NULL, 0); +MODULE_PARM_DESC(video_nr, "video device number (-1=Auto)"); + +/* holds the number of currently registered devices */ +static atomic_t dev_nr = ATOMIC_INIT(-1); + +int hdpvr_debug; +module_param(hdpvr_debug, int, S_IRUGO|S_IWUSR); +MODULE_PARM_DESC(hdpvr_debug, "enable debugging output"); + +uint default_video_input = HDPVR_VIDEO_INPUTS; +module_param(default_video_input, uint, S_IRUGO|S_IWUSR); +MODULE_PARM_DESC(default_video_input, "default video input: 0=Component / " + "1=S-Video / 2=Composite"); + +uint default_audio_input = HDPVR_AUDIO_INPUTS; +module_param(default_audio_input, uint, S_IRUGO|S_IWUSR); +MODULE_PARM_DESC(default_audio_input, "default audio input: 0=RCA back / " + "1=RCA front / 2=S/PDIF"); + +static int boost_audio; +module_param(boost_audio, bool, S_IRUGO|S_IWUSR); +MODULE_PARM_DESC(boost_audio, "boost the audio signal"); + + +/* table of devices that work with this driver */ +static struct usb_device_id hdpvr_table[] = { + { USB_DEVICE(HD_PVR_VENDOR_ID, HD_PVR_PRODUCT_ID) }, + { USB_DEVICE(HD_PVR_VENDOR_ID, HD_PVR_PRODUCT_ID1) }, + { USB_DEVICE(HD_PVR_VENDOR_ID, HD_PVR_PRODUCT_ID2) }, + { } /* Terminating entry */ +}; +MODULE_DEVICE_TABLE(usb, hdpvr_table); + + +void hdpvr_delete(struct hdpvr_device *dev) +{ + hdpvr_free_buffers(dev); + + if (dev->video_dev) + video_device_release(dev->video_dev); + + usb_put_dev(dev->udev); +} + +static void challenge(u8 *bytes) +{ + u64 *i64P, tmp64; + uint i, idx; + + for (idx = 0; idx < 32; ++idx) { + + if (idx & 0x3) + bytes[(idx >> 3) + 3] = bytes[(idx >> 2) & 0x3]; + + switch (idx & 0x3) { + case 0x3: + bytes[2] += bytes[3] * 4 + bytes[4] + bytes[5]; + bytes[4] += bytes[(idx & 0x1) * 2] * 9 + 9; + break; + case 0x1: + bytes[0] *= 8; + bytes[0] += 7*idx + 4; + bytes[6] += bytes[3] * 3; + break; + case 0x0: + bytes[3 - (idx >> 3)] = bytes[idx >> 2]; + bytes[5] += bytes[6] * 3; + for (i = 0; i < 3; i++) + bytes[3] *= bytes[3] + 1; + break; + case 0x2: + for (i = 0; i < 3; i++) + bytes[1] *= bytes[6] + 1; + for (i = 0; i < 3; i++) { + i64P = (u64 *)bytes; + tmp64 = le64_to_cpup(i64P); + tmp64 <<= bytes[7] & 0x0f; + *i64P += cpu_to_le64(tmp64); + } + break; + } + } +} + +/* try to init the device like the windows driver */ +static int device_authorization(struct hdpvr_device *dev) +{ + + int ret, retval = -ENOMEM; + char request_type = 0x38, rcv_request = 0x81; + char *response; +#ifdef HDPVR_DEBUG + size_t buf_size = 46; + char *print_buf = kzalloc(5*buf_size+1, GFP_KERNEL); + if (!print_buf) { + dev_err(&dev->udev->dev, "Out of memory"); + goto error; + } +#endif + + mutex_lock(&dev->usbc_mutex); + ret = usb_control_msg(dev->udev, + usb_rcvctrlpipe(dev->udev, 0), + rcv_request, 0x80 | request_type, + 0x0400, 0x0003, + dev->usbc_buf, 46, + 10000); + if (ret != 46) { + dev_err(&dev->udev->dev, + "unexpected answer of status request, len %d", ret); + goto error; + } +#ifdef HDPVR_DEBUG + else { + hex_dump_to_buffer(dev->usbc_buf, 46, 16, 1, print_buf, + sizeof(print_buf), 0); + dev_dbg(&dev->udev->dev, + "Status request returned, len %d: %s\n", + ret, print_buf); + } +#endif + if (dev->usbc_buf[1] == HDPVR_FIRMWARE_VERSION) { + dev->flags &= ~HDPVR_FLAG_AC3_CAP; + } else if (dev->usbc_buf[1] == HDPVR_FIRMWARE_VERSION_AC3) { + dev->flags |= HDPVR_FLAG_AC3_CAP; + } else if (dev->usbc_buf[1] > HDPVR_FIRMWARE_VERSION_AC3) { + dev_notice(&dev->udev->dev, "untested firmware version 0x%x, " + "the driver might not work\n", dev->usbc_buf[1]); + dev->flags |= HDPVR_FLAG_AC3_CAP; + } else { + dev_err(&dev->udev->dev, "unknown firmware version 0x%x\n", + dev->usbc_buf[1]); + ret = -EINVAL; + goto error; + } + + response = dev->usbc_buf+38; +#ifdef HDPVR_DEBUG + hex_dump_to_buffer(response, 8, 16, 1, print_buf, sizeof(print_buf), 0); + dev_dbg(&dev->udev->dev, "challenge: %s\n", print_buf); +#endif + challenge(response); +#ifdef HDPVR_DEBUG + hex_dump_to_buffer(response, 8, 16, 1, print_buf, sizeof(print_buf), 0); + dev_dbg(&dev->udev->dev, " response: %s\n", print_buf); +#endif + + msleep(100); + ret = usb_control_msg(dev->udev, + usb_sndctrlpipe(dev->udev, 0), + 0xd1, 0x00 | request_type, + 0x0000, 0x0000, + response, 8, + 10000); + dev_dbg(&dev->udev->dev, "magic request returned %d\n", ret); + mutex_unlock(&dev->usbc_mutex); + + retval = ret != 8; +error: + return retval; +} + +static int hdpvr_device_init(struct hdpvr_device *dev) +{ + int ret; + u8 *buf; + struct hdpvr_video_info *vidinf; + + if (device_authorization(dev)) + return -EACCES; + + /* default options for init */ + hdpvr_set_options(dev); + + /* set filter options */ + mutex_lock(&dev->usbc_mutex); + buf = dev->usbc_buf; + buf[0] = 0x03; buf[1] = 0x03; buf[2] = 0x00; buf[3] = 0x00; + ret = usb_control_msg(dev->udev, + usb_sndctrlpipe(dev->udev, 0), + 0x01, 0x38, + CTRL_LOW_PASS_FILTER_VALUE, CTRL_DEFAULT_INDEX, + buf, 4, + 1000); + dev_dbg(&dev->udev->dev, "control request returned %d\n", ret); + mutex_unlock(&dev->usbc_mutex); + + vidinf = get_video_info(dev); + if (!vidinf) + dev_dbg(&dev->udev->dev, + "no valid video signal or device init failed\n"); + else + kfree(vidinf); + + /* enable fan and bling leds */ + mutex_lock(&dev->usbc_mutex); + buf[0] = 0x1; + ret = usb_control_msg(dev->udev, + usb_sndctrlpipe(dev->udev, 0), + 0xd4, 0x38, 0, 0, buf, 1, + 1000); + dev_dbg(&dev->udev->dev, "control request returned %d\n", ret); + + /* boost analog audio */ + buf[0] = boost_audio; + ret = usb_control_msg(dev->udev, + usb_sndctrlpipe(dev->udev, 0), + 0xd5, 0x38, 0, 0, buf, 1, + 1000); + dev_dbg(&dev->udev->dev, "control request returned %d\n", ret); + mutex_unlock(&dev->usbc_mutex); + + dev->status = STATUS_IDLE; + return 0; +} + +static const struct hdpvr_options hdpvr_default_options = { + .video_std = HDPVR_60HZ, + .video_input = HDPVR_COMPONENT, + .audio_input = HDPVR_RCA_BACK, + .bitrate = 65, /* 6 mbps */ + .peak_bitrate = 90, /* 9 mbps */ + .bitrate_mode = HDPVR_CONSTANT, + .gop_mode = HDPVR_SIMPLE_IDR_GOP, + .audio_codec = V4L2_MPEG_AUDIO_ENCODING_AAC, + .brightness = 0x86, + .contrast = 0x80, + .hue = 0x80, + .saturation = 0x80, + .sharpness = 0x80, +}; + +static int hdpvr_probe(struct usb_interface *interface, + const struct usb_device_id *id) +{ + struct hdpvr_device *dev; + struct usb_host_interface *iface_desc; + struct usb_endpoint_descriptor *endpoint; + size_t buffer_size; + int i; + int retval = -ENOMEM; + + /* allocate memory for our device state and initialize it */ + dev = kzalloc(sizeof(*dev), GFP_KERNEL); + if (!dev) { + err("Out of memory"); + goto error; + } + mutex_init(&dev->io_mutex); + mutex_init(&dev->i2c_mutex); + mutex_init(&dev->usbc_mutex); + dev->usbc_buf = kmalloc(64, GFP_KERNEL); + if (!dev->usbc_buf) { + dev_err(&dev->udev->dev, "Out of memory"); + goto error; + } + + init_waitqueue_head(&dev->wait_buffer); + init_waitqueue_head(&dev->wait_data); + + dev->workqueue = create_singlethread_workqueue("hdpvr_buffer"); + if (!dev->workqueue) + goto error; + + /* init video transfer queues */ + INIT_LIST_HEAD(&dev->free_buff_list); + INIT_LIST_HEAD(&dev->rec_buff_list); + + dev->options = hdpvr_default_options; + + if (default_video_input < HDPVR_VIDEO_INPUTS) + dev->options.video_input = default_video_input; + + if (default_audio_input < HDPVR_AUDIO_INPUTS) + dev->options.audio_input = default_audio_input; + + dev->udev = usb_get_dev(interface_to_usbdev(interface)); + + /* set up the endpoint information */ + /* use only the first bulk-in and bulk-out endpoints */ + iface_desc = interface->cur_altsetting; + for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { + endpoint = &iface_desc->endpoint[i].desc; + + if (!dev->bulk_in_endpointAddr && + usb_endpoint_is_bulk_in(endpoint)) { + /* USB interface description is buggy, reported max + * packet size is 512 bytes, windows driver uses 8192 */ + buffer_size = 8192; + dev->bulk_in_size = buffer_size; + dev->bulk_in_endpointAddr = endpoint->bEndpointAddress; + } + + } + if (!dev->bulk_in_endpointAddr) { + err("Could not find bulk-in endpoint"); + goto error; + } + + /* init the device */ + if (hdpvr_device_init(dev)) { + err("device init failed"); + goto error; + } + + mutex_lock(&dev->io_mutex); + if (hdpvr_alloc_buffers(dev, NUM_BUFFERS)) { + err("allocating transfer buffers failed"); + goto error; + } + mutex_unlock(&dev->io_mutex); + + if (hdpvr_register_videodev(dev, + video_nr[atomic_inc_return(&dev_nr)])) { + err("registering videodev failed"); + goto error; + } + +#if 0 /* until i2c is working properly */ + retval = hdpvr_register_i2c_adapter(dev); + if (retval < 0) { + err("registering i2c adapter failed"); + goto error; + } +#endif + + /* save our data pointer in this interface device */ + usb_set_intfdata(interface, dev); + + /* let the user know what node this device is now attached to */ + v4l2_info(dev->video_dev, "device now attached to /dev/video%d\n", + dev->video_dev->minor); + return 0; + +error: + if (dev) { + mutex_unlock(&dev->io_mutex); + /* this frees allocated memory */ + hdpvr_delete(dev); + } + return retval; +} + +static void hdpvr_disconnect(struct usb_interface *interface) +{ + struct hdpvr_device *dev; + int minor; + + dev = usb_get_intfdata(interface); + usb_set_intfdata(interface, NULL); + + minor = dev->video_dev->minor; + + /* prevent more I/O from starting and stop any ongoing */ + mutex_lock(&dev->io_mutex); + dev->status = STATUS_DISCONNECTED; + video_unregister_device(dev->video_dev); + wake_up_interruptible(&dev->wait_data); + wake_up_interruptible(&dev->wait_buffer); + msleep(100); + flush_workqueue(dev->workqueue); + hdpvr_cancel_queue(dev); + destroy_workqueue(dev->workqueue); + mutex_unlock(&dev->io_mutex); + + /* deregister I2C adapter */ + mutex_lock(&dev->i2c_mutex); + if (dev->i2c_adapter) + i2c_del_adapter(dev->i2c_adapter); + kfree(dev->i2c_adapter); + dev->i2c_adapter = NULL; + mutex_unlock(&dev->i2c_mutex); + + atomic_dec(&dev_nr); + + printk(KERN_INFO "Hauppauge HD PVR: device /dev/video%d disconnected\n", + minor); + + kfree(dev->usbc_buf); + kfree(dev); +} + + +static struct usb_driver hdpvr_usb_driver = { + .name = "hdpvr", + .probe = hdpvr_probe, + .disconnect = hdpvr_disconnect, + .id_table = hdpvr_table, +}; + +static int __init hdpvr_init(void) +{ + int result; + + /* register this driver with the USB subsystem */ + result = usb_register(&hdpvr_usb_driver); + if (result) + err("usb_register failed. Error number %d", result); + + return result; +} + +static void __exit hdpvr_exit(void) +{ + /* deregister this driver with the USB subsystem */ + usb_deregister(&hdpvr_usb_driver); +} + +module_init(hdpvr_init); +module_exit(hdpvr_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Janne Grunau"); +MODULE_DESCRIPTION("Hauppauge HD PVR driver"); diff --git a/linux/drivers/media/video/hdpvr/hdpvr-i2c.c b/linux/drivers/media/video/hdpvr/hdpvr-i2c.c new file mode 100644 index 000000000..35096dec2 --- /dev/null +++ b/linux/drivers/media/video/hdpvr/hdpvr-i2c.c @@ -0,0 +1,145 @@ + +/* + * Hauppage HD PVR USB driver + * + * Copyright (C) 2008 Janne Grunau (j@jannau.net) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, version 2. + * + */ + +#include + +#include "hdpvr.h" + +#define CTRL_READ_REQUEST 0xb8 +#define CTRL_WRITE_REQUEST 0x38 + +#define REQTYPE_I2C_READ 0xb1 +#define REQTYPE_I2C_WRITE 0xb0 +#define REQTYPE_I2C_WRITE_STATT 0xd0 + +static int hdpvr_i2c_read(struct hdpvr_device *dev, unsigned char addr, + char *data, int len) +{ + int ret; + char *buf = kmalloc(len, GFP_KERNEL); + if (!buf) + return -ENOMEM; + + ret = usb_control_msg(dev->udev, + usb_rcvctrlpipe(dev->udev, 0), + REQTYPE_I2C_READ, CTRL_READ_REQUEST, + 0x100|addr, 0, buf, len, 1000); + + if (ret == len) { + memcpy(data, buf, len); + ret = 0; + } else if (ret >= 0) + ret = -EIO; + + kfree(buf); + + return ret; +} + +static int hdpvr_i2c_write(struct hdpvr_device *dev, unsigned char addr, + char *data, int len) +{ + int ret; + char *buf = kmalloc(len, GFP_KERNEL); + if (!buf) + return -ENOMEM; + + memcpy(buf, data, len); + ret = usb_control_msg(dev->udev, + usb_sndctrlpipe(dev->udev, 0), + REQTYPE_I2C_WRITE, CTRL_WRITE_REQUEST, + 0x100|addr, 0, buf, len, 1000); + + if (ret < 0) + goto error; + + ret = usb_control_msg(dev->udev, + usb_rcvctrlpipe(dev->udev, 0), + REQTYPE_I2C_WRITE_STATT, CTRL_READ_REQUEST, + 0, 0, buf, 2, 1000); + + if (ret == 2) + ret = 0; + else if (ret >= 0) + ret = -EIO; + +error: + kfree(buf); + return ret; +} + +static int hdpvr_transfer(struct i2c_adapter *i2c_adapter, struct i2c_msg *msgs, + int num) +{ + struct hdpvr_device *dev = i2c_get_adapdata(i2c_adapter); + int retval = 0, i, addr; + + if (num <= 0) + return 0; + + mutex_lock(&dev->i2c_mutex); + + for (i = 0; i < num && !retval; i++) { + addr = msgs[i].addr << 1; + + if (msgs[i].flags & I2C_M_RD) + retval = hdpvr_i2c_read(dev, addr, msgs[i].buf, + msgs[i].len); + else + retval = hdpvr_i2c_write(dev, addr, msgs[i].buf, + msgs[i].len); + } + + mutex_unlock(&dev->i2c_mutex); + + return retval ? retval : num; +} + +static u32 hdpvr_functionality(struct i2c_adapter *adapter) +{ + return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; +} + +static struct i2c_algorithm hdpvr_algo = { + .master_xfer = hdpvr_transfer, + .functionality = hdpvr_functionality, +}; + +int hdpvr_register_i2c_adapter(struct hdpvr_device *dev) +{ + struct i2c_adapter *i2c_adap; + int retval = -ENOMEM; + + i2c_adap = kzalloc(sizeof(struct i2c_adapter), GFP_KERNEL); + if (i2c_adap == NULL) + goto error; + + strlcpy(i2c_adap->name, "Hauppauge HD PVR I2C", + sizeof(i2c_adap->name)); + i2c_adap->algo = &hdpvr_algo; + i2c_adap->class = I2C_CLASS_TV_ANALOG; + i2c_adap->id = I2C_HW_B_HDPVR; + i2c_adap->owner = THIS_MODULE; + i2c_adap->dev.parent = &dev->udev->dev; + + i2c_set_adapdata(i2c_adap, dev); + + retval = i2c_add_adapter(i2c_adap); + + if (!retval) + dev->i2c_adapter = i2c_adap; + else + kfree(i2c_adap); + +error: + return retval; +} diff --git a/linux/drivers/media/video/hdpvr/hdpvr-video.c b/linux/drivers/media/video/hdpvr/hdpvr-video.c new file mode 100644 index 000000000..ee481495e --- /dev/null +++ b/linux/drivers/media/video/hdpvr/hdpvr-video.c @@ -0,0 +1,1228 @@ +/* + * Hauppage HD PVR USB driver - video 4 linux 2 interface + * + * Copyright (C) 2008 Janne Grunau (j@jannau.net) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, version 2. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include "hdpvr.h" + +#define BULK_URB_TIMEOUT 1250 /* 1.25 seconds */ + +struct hdpvr_fh { + struct hdpvr_device *dev; +}; + +static uint list_size(struct list_head *list) +{ + struct list_head *tmp; + uint count = 0; + + list_for_each(tmp, list) { + count++; + } + + return count; +} + +/*=========================================================================*/ +/* urb callback */ +static void hdpvr_read_bulk_callback(struct urb *urb) +{ + struct hdpvr_buffer *buf = (struct hdpvr_buffer *)urb->context; + struct hdpvr_device *dev = buf->dev; + + /* marking buffer as received and wake waiting */ + buf->status = BUFSTAT_READY; + wake_up_interruptible(&dev->wait_data); +} + +/*=========================================================================*/ +/* bufffer bits */ + +/* function expects dev->io_mutex to be hold by caller */ +int hdpvr_cancel_queue(struct hdpvr_device *dev) +{ + struct hdpvr_buffer *buf; + + list_for_each_entry(buf, &dev->rec_buff_list, buff_list) { + usb_kill_urb(buf->urb); + buf->status = BUFSTAT_AVAILABLE; + } + + list_splice_init(&dev->rec_buff_list, dev->free_buff_list.prev); + + return 0; +} + +static int hdpvr_free_queue(struct list_head *q) +{ + struct list_head *tmp; + struct list_head *p; + struct hdpvr_buffer *buf; + struct urb *urb; + + for (p = q->next; p != q;) { + buf = list_entry(p, struct hdpvr_buffer, buff_list); + + urb = buf->urb; + usb_buffer_free(urb->dev, urb->transfer_buffer_length, + urb->transfer_buffer, urb->transfer_dma); + usb_free_urb(urb); + tmp = p->next; + list_del(p); + kfree(buf); + p = tmp; + } + + return 0; +} + +/* function expects dev->io_mutex to be hold by caller */ +int hdpvr_free_buffers(struct hdpvr_device *dev) +{ + hdpvr_cancel_queue(dev); + + hdpvr_free_queue(&dev->free_buff_list); + hdpvr_free_queue(&dev->rec_buff_list); + + return 0; +} + +/* function expects dev->io_mutex to be hold by caller */ +int hdpvr_alloc_buffers(struct hdpvr_device *dev, uint count) +{ + uint i; + int retval = -ENOMEM; + u8 *mem; + struct hdpvr_buffer *buf; + struct urb *urb; + + v4l2_dbg(MSG_INFO, hdpvr_debug, dev->video_dev, + "allocating %u buffers\n", count); + + for (i = 0; i < count; i++) { + + buf = kzalloc(sizeof(struct hdpvr_buffer), GFP_KERNEL); + if (!buf) { + err("cannot allocate buffer"); + goto exit; + } + buf->dev = dev; + + urb = usb_alloc_urb(0, GFP_KERNEL); + if (!urb) { + err("cannot allocate urb"); + goto exit; + } + buf->urb = urb; + + mem = usb_buffer_alloc(dev->udev, dev->bulk_in_size, GFP_KERNEL, + &urb->transfer_dma); + if (!mem) { + err("cannot allocate usb transfer buffer"); + goto exit; + } + + usb_fill_bulk_urb(buf->urb, dev->udev, + usb_rcvbulkpipe(dev->udev, + dev->bulk_in_endpointAddr), + mem, dev->bulk_in_size, + hdpvr_read_bulk_callback, buf); + + buf->status = BUFSTAT_AVAILABLE; + list_add_tail(&buf->buff_list, &dev->free_buff_list); + } + return 0; +exit: + hdpvr_free_buffers(dev); + return retval; +} + +static int hdpvr_submit_buffers(struct hdpvr_device *dev) +{ + struct hdpvr_buffer *buf; + struct urb *urb; + int ret = 0, err_count = 0; + + mutex_lock(&dev->io_mutex); + + while (dev->status == STATUS_STREAMING && + !list_empty(&dev->free_buff_list)) { + + buf = list_entry(dev->free_buff_list.next, struct hdpvr_buffer, + buff_list); + if (buf->status != BUFSTAT_AVAILABLE) { + err("buffer not marked as availbale"); + ret = -EFAULT; + goto err; + } + + urb = buf->urb; + urb->status = 0; + urb->actual_length = 0; + ret = usb_submit_urb(urb, GFP_KERNEL); + if (ret) { + err("usb_submit_urb in %s returned %d", __func__, ret); + if (++err_count > 2) + break; + continue; + } + buf->status = BUFSTAT_INPROGRESS; + list_move_tail(&buf->buff_list, &dev->rec_buff_list); + } +err: + v4l2_dbg(MSG_BUFFER, hdpvr_debug, dev->video_dev, + "buffer queue stat: %d free, %d proc\n", + list_size(&dev->free_buff_list), + list_size(&dev->rec_buff_list)); + mutex_unlock(&dev->io_mutex); + return ret; +} + +static struct hdpvr_buffer *hdpvr_get_next_buffer(struct hdpvr_device *dev) +{ + struct hdpvr_buffer *buf; + + mutex_lock(&dev->io_mutex); + + if (list_empty(&dev->rec_buff_list)) { + mutex_unlock(&dev->io_mutex); + return NULL; + } + + buf = list_entry(dev->rec_buff_list.next, struct hdpvr_buffer, + buff_list); + mutex_unlock(&dev->io_mutex); + + return buf; +} + +static void hdpvr_transmit_buffers(struct work_struct *work) +{ + struct hdpvr_device *dev = container_of(work, struct hdpvr_device, + worker); + + while (dev->status == STATUS_STREAMING) { + + if (hdpvr_submit_buffers(dev)) { + v4l2_err(dev->video_dev, "couldn't submit buffers\n"); + goto error; + } + if (wait_event_interruptible(dev->wait_buffer, + !list_empty(&dev->free_buff_list) || + dev->status != STATUS_STREAMING)) + goto error; + } + + v4l2_dbg(MSG_INFO, hdpvr_debug, dev->video_dev, + "transmit worker exited\n"); + return; +error: + v4l2_dbg(MSG_INFO, hdpvr_debug, dev->video_dev, + "transmit buffers errored\n"); + dev->status = STATUS_ERROR; +} + +/* function expects dev->io_mutex to be hold by caller */ +static int hdpvr_start_streaming(struct hdpvr_device *dev) +{ + int ret; + struct hdpvr_video_info *vidinf; + + if (dev->status == STATUS_STREAMING) + return 0; + else if (dev->status != STATUS_IDLE) + return -EAGAIN; + + vidinf = get_video_info(dev); + + if (vidinf) { + v4l2_dbg(MSG_BUFFER, hdpvr_debug, dev->video_dev, + "video signal: %dx%d@%dhz\n", vidinf->width, + vidinf->height, vidinf->fps); + kfree(vidinf); + + /* start streaming 2 request */ + ret = usb_control_msg(dev->udev, + usb_sndctrlpipe(dev->udev, 0), + 0xb8, 0x38, 0x1, 0, NULL, 0, 8000); + v4l2_dbg(MSG_BUFFER, hdpvr_debug, dev->video_dev, + "encoder start control request returned %d\n", ret); + + hdpvr_config_call(dev, CTRL_START_STREAMING_VALUE, 0x00); + + INIT_WORK(&dev->worker, hdpvr_transmit_buffers); + queue_work(dev->workqueue, &dev->worker); + + v4l2_dbg(MSG_BUFFER, hdpvr_debug, dev->video_dev, + "streaming started\n"); + dev->status = STATUS_STREAMING; + + return 0; + } + msleep(250); + v4l2_dbg(MSG_INFO, hdpvr_debug, dev->video_dev, + "no video signal at input %d\n", dev->options.video_input); + return -EAGAIN; +} + + +/* function expects dev->io_mutex to be hold by caller */ +static int hdpvr_stop_streaming(struct hdpvr_device *dev) +{ + if (dev->status == STATUS_IDLE) + return 0; + else if (dev->status != STATUS_STREAMING) + return -EAGAIN; + + dev->status = STATUS_SHUTTING_DOWN; + hdpvr_config_call(dev, CTRL_STOP_STREAMING_VALUE, 0x00); + + wake_up_interruptible(&dev->wait_buffer); + msleep(50); + + flush_workqueue(dev->workqueue); + + /* kill the still outstanding urbs */ + hdpvr_cancel_queue(dev); + + dev->status = STATUS_IDLE; + + return 0; +} + + +/*=======================================================================*/ +/* + * video 4 linux 2 file operations + */ + +static int hdpvr_open(struct file *file) +{ + struct hdpvr_device *dev; + struct hdpvr_fh *fh; + int retval = -ENOMEM; + + dev = (struct hdpvr_device *)video_get_drvdata(video_devdata(file)); + if (!dev) { + err("open failing with with ENODEV"); + retval = -ENODEV; + goto err; + } + + fh = kzalloc(sizeof(struct hdpvr_fh), GFP_KERNEL); + if (!fh) { + err("Out of memory?"); + goto err; + } + /* lock the device to allow correctly handling errors + * in resumption */ + mutex_lock(&dev->io_mutex); + dev->open_count++; + + fh->dev = dev; + + /* save our object in the file's private structure */ + file->private_data = fh; + + retval = 0; +err: + mutex_unlock(&dev->io_mutex); + return retval; +} + +static int hdpvr_release(struct file *file) +{ + struct hdpvr_fh *fh = (struct hdpvr_fh *)file->private_data; + struct hdpvr_device *dev = fh->dev; + + if (!dev) + return -ENODEV; + + mutex_lock(&dev->io_mutex); + if (!(--dev->open_count) && dev->status == STATUS_STREAMING) + hdpvr_stop_streaming(dev); + + mutex_unlock(&dev->io_mutex); + + return 0; +} + +/* + * hdpvr_v4l2_read() + * will allocate buffers when called for the first time + */ +static ssize_t hdpvr_read(struct file *file, char __user *buffer, size_t count, + loff_t *pos) +{ + struct hdpvr_fh *fh = file->private_data; + struct hdpvr_device *dev = fh->dev; + struct hdpvr_buffer *buf = NULL; + struct urb *urb; + unsigned int ret = 0; + int rem, cnt; + + if (*pos) + return -ESPIPE; + + if (!dev) + return -ENODEV; + + mutex_lock(&dev->io_mutex); + if (dev->status == STATUS_IDLE) { + if (hdpvr_start_streaming(dev)) { + v4l2_dbg(MSG_INFO, hdpvr_debug, dev->video_dev, + "start_streaming failed"); + ret = -EIO; + msleep(200); + dev->status = STATUS_IDLE; + mutex_unlock(&dev->io_mutex); + goto err; + } + + v4l2_dbg(MSG_BUFFER, hdpvr_debug, dev->video_dev, + "buffer queue stat: %d free, %d proc\n", + list_size(&dev->free_buff_list), + list_size(&dev->rec_buff_list)); + } + mutex_unlock(&dev->io_mutex); + + /* wait for the first buffer */ + if (!(file->f_flags & O_NONBLOCK)) { + if (wait_event_interruptible(dev->wait_data, + hdpvr_get_next_buffer(dev))) + return -ERESTARTSYS; + } + + buf = hdpvr_get_next_buffer(dev); + + while (count > 0 && buf) { + + if (buf->status != BUFSTAT_READY && + dev->status != STATUS_DISCONNECTED) { + /* return nonblocking */ + if (file->f_flags & O_NONBLOCK) { + if (!ret) + ret = -EAGAIN; + goto err; + } + + if (wait_event_interruptible(dev->wait_data, + buf->status == BUFSTAT_READY)) { + ret = -ERESTARTSYS; + goto err; + } + } + + if (buf->status != BUFSTAT_READY) + break; + + /* set remaining bytes to copy */ + urb = buf->urb; + rem = urb->actual_length - buf->pos; + cnt = rem > count ? count : rem; + + if (copy_to_user(buffer, urb->transfer_buffer + buf->pos, + cnt)) { + err("read: copy_to_user failed"); + if (!ret) + ret = -EFAULT; + goto err; + } + + buf->pos += cnt; + count -= cnt; + buffer += cnt; + ret += cnt; + + /* finished, take next buffer */ + if (buf->pos == urb->actual_length) { + mutex_lock(&dev->io_mutex); + buf->pos = 0; + buf->status = BUFSTAT_AVAILABLE; + + list_move_tail(&buf->buff_list, &dev->free_buff_list); + + v4l2_dbg(MSG_BUFFER, hdpvr_debug, dev->video_dev, + "buffer queue stat: %d free, %d proc\n", + list_size(&dev->free_buff_list), + list_size(&dev->rec_buff_list)); + + mutex_unlock(&dev->io_mutex); + + wake_up_interruptible(&dev->wait_buffer); + + buf = hdpvr_get_next_buffer(dev); + } + } +err: + if (!ret && !buf) + ret = -EAGAIN; + return ret; +} + +static unsigned int hdpvr_poll(struct file *filp, poll_table *wait) +{ + struct hdpvr_fh *fh = (struct hdpvr_fh *)filp->private_data; + struct hdpvr_device *dev = fh->dev; + unsigned int mask = 0; + + mutex_lock(&dev->io_mutex); + + if (video_is_unregistered(dev->video_dev)) + return -EIO; + + if (dev->status == STATUS_IDLE) { + if (hdpvr_start_streaming(dev)) { + v4l2_dbg(MSG_BUFFER, hdpvr_debug, dev->video_dev, + "start_streaming failed"); + dev->status = STATUS_IDLE; + } + + v4l2_dbg(MSG_BUFFER, hdpvr_debug, dev->video_dev, + "buffer queue stat: %d free, %d proc\n", + list_size(&dev->free_buff_list), + list_size(&dev->rec_buff_list)); + } + mutex_unlock(&dev->io_mutex); + + poll_wait(filp, &dev->wait_data, wait); + + mutex_lock(&dev->io_mutex); + if (!list_empty(&dev->rec_buff_list)) { + + struct hdpvr_buffer *buf = list_entry(dev->rec_buff_list.next, + struct hdpvr_buffer, + buff_list); + + if (buf->status == BUFSTAT_READY) + mask |= POLLIN | POLLRDNORM; + } + mutex_unlock(&dev->io_mutex); + + return mask; +} + + +static long hdpvr_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) +{ + struct hdpvr_fh *fh = (struct hdpvr_fh *)filp->private_data; + struct hdpvr_device *dev = fh->dev; + int res; + + if (video_is_unregistered(dev->video_dev)) + return -EIO; + + mutex_lock(&dev->io_mutex); + switch (cmd) { + case VIDIOC_TRY_ENCODER_CMD: + case VIDIOC_ENCODER_CMD: { + struct v4l2_encoder_cmd *enc = (struct v4l2_encoder_cmd *)arg; + int try = cmd == VIDIOC_TRY_ENCODER_CMD; + + memset(&enc->raw, 0, sizeof(enc->raw)); + switch (enc->cmd) { + case V4L2_ENC_CMD_START: + enc->flags = 0; + if (try) + return 0; + res = hdpvr_start_streaming(dev); + break; + case V4L2_ENC_CMD_STOP: + if (try) + return 0; + res = hdpvr_stop_streaming(dev); + break; + default: + v4l2_dbg(MSG_INFO, hdpvr_debug, dev->video_dev, + "Unsupported encoder cmd %d\n", enc->cmd); + return -EINVAL; + } + break; + } + default: + res = video_ioctl2(filp, cmd, arg); + } + mutex_unlock(&dev->io_mutex); + return res; +} + +static const struct v4l2_file_operations hdpvr_fops = { + .owner = THIS_MODULE, + .open = hdpvr_open, + .release = hdpvr_release, + .read = hdpvr_read, + .poll = hdpvr_poll, + .unlocked_ioctl = hdpvr_ioctl, +}; + +/*=======================================================================*/ +/* + * V4L2 ioctl handling + */ + +static int vidioc_querycap(struct file *file, void *priv, + struct v4l2_capability *cap) +{ + struct hdpvr_device *dev = video_drvdata(file); + + strcpy(cap->driver, "hdpvr"); + strcpy(cap->card, "Haupauge HD PVR"); + usb_make_path(dev->udev, cap->bus_info, sizeof(cap->bus_info)); + cap->version = HDPVR_VERSION; + cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | + V4L2_CAP_AUDIO | + V4L2_CAP_READWRITE; + return 0; +} + +static int vidioc_s_std(struct file *file, void *private_data, + v4l2_std_id *std) +{ + struct hdpvr_fh *fh = file->private_data; + struct hdpvr_device *dev = fh->dev; + u8 std_type = 1; + + if (*std & (V4L2_STD_NTSC | V4L2_STD_PAL_60)) + std_type = 0; + + return hdpvr_config_call(dev, CTRL_VIDEO_STD_TYPE, std_type); +} + +static const char *iname[] = { + [HDPVR_COMPONENT] = "Component", + [HDPVR_SVIDEO] = "S-Video", + [HDPVR_COMPOSITE] = "Composite", +}; + +static int vidioc_enum_input(struct file *file, void *priv, + struct v4l2_input *i) +{ + struct hdpvr_fh *fh = file->private_data; + struct hdpvr_device *dev = fh->dev; + unsigned int n; + + n = i->index; + if (n >= HDPVR_VIDEO_INPUTS) + return -EINVAL; + + i->type = V4L2_INPUT_TYPE_CAMERA; + + strncpy(i->name, iname[n], sizeof(i->name) - 1); + i->name[sizeof(i->name) - 1] = '\0'; + + i->audioset = 1<std = dev->video_dev->tvnorms; + + return 0; +} + +static int vidioc_s_input(struct file *file, void *private_data, + unsigned int index) +{ + struct hdpvr_fh *fh = file->private_data; + struct hdpvr_device *dev = fh->dev; + int retval; + + if (index >= HDPVR_VIDEO_INPUTS) + return -EINVAL; + + if (dev->status != STATUS_IDLE) + return -EAGAIN; + + retval = hdpvr_config_call(dev, CTRL_VIDEO_INPUT_VALUE, index+1); + if (!retval) + dev->options.video_input = index; + + return retval; +} + +static int vidioc_g_input(struct file *file, void *private_data, + unsigned int *index) +{ + struct hdpvr_fh *fh = file->private_data; + struct hdpvr_device *dev = fh->dev; + + *index = dev->options.video_input; + return 0; +} + + +static const char *audio_iname[] = { + [HDPVR_RCA_FRONT] = "RCA front", + [HDPVR_RCA_BACK] = "RCA back", + [HDPVR_SPDIF] = "SPDIF", +}; + +static int vidioc_enumaudio(struct file *file, void *priv, + struct v4l2_audio *audio) +{ + unsigned int n; + + n = audio->index; + if (n >= HDPVR_AUDIO_INPUTS) + return -EINVAL; + + audio->capability = V4L2_AUDCAP_STEREO; + + strncpy(audio->name, audio_iname[n], sizeof(audio->name) - 1); + audio->name[sizeof(audio->name) - 1] = '\0'; + + return 0; +} + +static int vidioc_s_audio(struct file *file, void *private_data, + struct v4l2_audio *audio) +{ + struct hdpvr_fh *fh = file->private_data; + struct hdpvr_device *dev = fh->dev; + int retval; + + if (audio->index >= HDPVR_AUDIO_INPUTS) + return -EINVAL; + + if (dev->status != STATUS_IDLE) + return -EAGAIN; + + retval = hdpvr_set_audio(dev, audio->index+1, dev->options.audio_codec); + if (!retval) + dev->options.audio_input = audio->index; + + return retval; +} + +static int vidioc_g_audio(struct file *file, void *private_data, + struct v4l2_audio *audio) +{ + struct hdpvr_fh *fh = file->private_data; + struct hdpvr_device *dev = fh->dev; + + audio->index = dev->options.audio_input; + audio->capability = V4L2_AUDCAP_STEREO; + strncpy(audio->name, audio_iname[audio->index], sizeof(audio->name)); + audio->name[sizeof(audio->name) - 1] = '\0'; + return 0; +} + +static const s32 supported_v4l2_ctrls[] = { + V4L2_CID_BRIGHTNESS, + V4L2_CID_CONTRAST, + V4L2_CID_SATURATION, + V4L2_CID_HUE, + V4L2_CID_SHARPNESS, + V4L2_CID_MPEG_AUDIO_ENCODING, + V4L2_CID_MPEG_VIDEO_ENCODING, + V4L2_CID_MPEG_VIDEO_BITRATE_MODE, + V4L2_CID_MPEG_VIDEO_BITRATE, + V4L2_CID_MPEG_VIDEO_BITRATE_PEAK, +}; + +static int fill_queryctrl(struct hdpvr_options *opt, struct v4l2_queryctrl *qc, + int ac3) +{ + int err; + + switch (qc->id) { + case V4L2_CID_BRIGHTNESS: + return v4l2_ctrl_query_fill(qc, 0x0, 0xff, 1, 0x86); + case V4L2_CID_CONTRAST: + return v4l2_ctrl_query_fill(qc, 0x0, 0xff, 1, 0x80); + case V4L2_CID_SATURATION: + return v4l2_ctrl_query_fill(qc, 0x0, 0xff, 1, 0x80); + case V4L2_CID_HUE: + return v4l2_ctrl_query_fill(qc, 0x0, 0xff, 1, 0x80); + case V4L2_CID_SHARPNESS: + return v4l2_ctrl_query_fill(qc, 0x0, 0xff, 1, 0x80); + case V4L2_CID_MPEG_AUDIO_ENCODING: + return v4l2_ctrl_query_fill( + qc, V4L2_MPEG_AUDIO_ENCODING_AAC, + ac3 ? V4L2_MPEG_AUDIO_ENCODING_AC3 + : V4L2_MPEG_AUDIO_ENCODING_AAC, + 1, V4L2_MPEG_AUDIO_ENCODING_AAC); + case V4L2_CID_MPEG_VIDEO_ENCODING: + return v4l2_ctrl_query_fill( + qc, V4L2_MPEG_VIDEO_ENCODING_MPEG_4_AVC, + V4L2_MPEG_VIDEO_ENCODING_MPEG_4_AVC, 1, + V4L2_MPEG_VIDEO_ENCODING_MPEG_4_AVC); + +/* case V4L2_CID_MPEG_VIDEO_? maybe keyframe interval: */ +/* return v4l2_ctrl_query_fill(qc, 0, 128, 128, 0); */ + case V4L2_CID_MPEG_VIDEO_BITRATE_MODE: + return v4l2_ctrl_query_fill( + qc, V4L2_MPEG_VIDEO_BITRATE_MODE_VBR, + V4L2_MPEG_VIDEO_BITRATE_MODE_CBR, 1, + V4L2_MPEG_VIDEO_BITRATE_MODE_CBR); + + case V4L2_CID_MPEG_VIDEO_BITRATE: + return v4l2_ctrl_query_fill(qc, 1000000, 13500000, 100000, + 6500000); + case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK: + err = v4l2_ctrl_query_fill(qc, 1100000, 20200000, 100000, + 9000000); + if (!err && opt->bitrate_mode == HDPVR_CONSTANT) + qc->flags |= V4L2_CTRL_FLAG_INACTIVE; + return err; + default: + return -EINVAL; + } +} + +static int vidioc_queryctrl(struct file *file, void *private_data, + struct v4l2_queryctrl *qc) +{ + struct hdpvr_fh *fh = file->private_data; + struct hdpvr_device *dev = fh->dev; + int i, next; + u32 id = qc->id; + + memset(qc, 0, sizeof(*qc)); + + next = !!(id & V4L2_CTRL_FLAG_NEXT_CTRL); + qc->id = id & ~V4L2_CTRL_FLAG_NEXT_CTRL; + + for (i = 0; i < ARRAY_SIZE(supported_v4l2_ctrls); i++) { + if (next) { + if (qc->id < supported_v4l2_ctrls[i]) + qc->id = supported_v4l2_ctrls[i]; + else + continue; + } + + if (qc->id == supported_v4l2_ctrls[i]) + return fill_queryctrl(&dev->options, qc, + dev->flags & HDPVR_FLAG_AC3_CAP); + + if (qc->id < supported_v4l2_ctrls[i]) + break; + } + + return -EINVAL; +} + +static int vidioc_g_ctrl(struct file *file, void *private_data, + struct v4l2_control *ctrl) +{ + struct hdpvr_fh *fh = file->private_data; + struct hdpvr_device *dev = fh->dev; + + switch (ctrl->id) { + case V4L2_CID_BRIGHTNESS: + ctrl->value = dev->options.brightness; + break; + case V4L2_CID_CONTRAST: + ctrl->value = dev->options.contrast; + break; + case V4L2_CID_SATURATION: + ctrl->value = dev->options.saturation; + break; + case V4L2_CID_HUE: + ctrl->value = dev->options.hue; + break; + case V4L2_CID_SHARPNESS: + ctrl->value = dev->options.sharpness; + break; + default: + return -EINVAL; + } + return 0; +} + +static int vidioc_s_ctrl(struct file *file, void *private_data, + struct v4l2_control *ctrl) +{ + struct hdpvr_fh *fh = file->private_data; + struct hdpvr_device *dev = fh->dev; + int retval; + + switch (ctrl->id) { + case V4L2_CID_BRIGHTNESS: + retval = hdpvr_config_call(dev, CTRL_BRIGHTNESS, ctrl->value); + if (!retval) + dev->options.brightness = ctrl->value; + break; + case V4L2_CID_CONTRAST: + retval = hdpvr_config_call(dev, CTRL_CONTRAST, ctrl->value); + if (!retval) + dev->options.contrast = ctrl->value; + break; + case V4L2_CID_SATURATION: + retval = hdpvr_config_call(dev, CTRL_SATURATION, ctrl->value); + if (!retval) + dev->options.saturation = ctrl->value; + break; + case V4L2_CID_HUE: + retval = hdpvr_config_call(dev, CTRL_HUE, ctrl->value); + if (!retval) + dev->options.hue = ctrl->value; + break; + case V4L2_CID_SHARPNESS: + retval = hdpvr_config_call(dev, CTRL_SHARPNESS, ctrl->value); + if (!retval) + dev->options.sharpness = ctrl->value; + break; + default: + return -EINVAL; + } + + return retval; +} + + +static int hdpvr_get_ctrl(struct hdpvr_options *opt, + struct v4l2_ext_control *ctrl) +{ + switch (ctrl->id) { + case V4L2_CID_MPEG_AUDIO_ENCODING: + ctrl->value = opt->audio_codec; + break; + case V4L2_CID_MPEG_VIDEO_ENCODING: + ctrl->value = V4L2_MPEG_VIDEO_ENCODING_MPEG_4_AVC; + break; +/* case V4L2_CID_MPEG_VIDEO_B_FRAMES: */ +/* ctrl->value = (opt->gop_mode & 0x2) ? 0 : 128; */ +/* break; */ + case V4L2_CID_MPEG_VIDEO_BITRATE_MODE: + ctrl->value = opt->bitrate_mode == HDPVR_CONSTANT + ? V4L2_MPEG_VIDEO_BITRATE_MODE_CBR + : V4L2_MPEG_VIDEO_BITRATE_MODE_VBR; + break; + case V4L2_CID_MPEG_VIDEO_BITRATE: + ctrl->value = opt->bitrate * 100000; + break; + case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK: + ctrl->value = opt->peak_bitrate * 100000; + break; + case V4L2_CID_MPEG_STREAM_TYPE: + ctrl->value = V4L2_MPEG_STREAM_TYPE_MPEG2_TS; + break; + default: + return -EINVAL; + } + return 0; +} + +static int vidioc_g_ext_ctrls(struct file *file, void *priv, + struct v4l2_ext_controls *ctrls) +{ + struct hdpvr_fh *fh = file->private_data; + struct hdpvr_device *dev = fh->dev; + int i, err = 0; + + if (ctrls->ctrl_class == V4L2_CTRL_CLASS_MPEG) { + for (i = 0; i < ctrls->count; i++) { + struct v4l2_ext_control *ctrl = ctrls->controls + i; + + err = hdpvr_get_ctrl(&dev->options, ctrl); + if (err) { + ctrls->error_idx = i; + break; + } + } + return err; + + } + + return -EINVAL; +} + + +static int hdpvr_try_ctrl(struct v4l2_ext_control *ctrl, int ac3) +{ + int ret = -EINVAL; + + switch (ctrl->id) { + case V4L2_CID_MPEG_AUDIO_ENCODING: + if (ctrl->value == V4L2_MPEG_AUDIO_ENCODING_AAC || + (ac3 && ctrl->value == V4L2_MPEG_AUDIO_ENCODING_AC3)) + ret = 0; + break; + case V4L2_CID_MPEG_VIDEO_ENCODING: + if (ctrl->value == V4L2_MPEG_VIDEO_ENCODING_MPEG_4_AVC) + ret = 0; + break; +/* case V4L2_CID_MPEG_VIDEO_B_FRAMES: */ +/* if (ctrl->value == 0 || ctrl->value == 128) */ +/* ret = 0; */ +/* break; */ + case V4L2_CID_MPEG_VIDEO_BITRATE_MODE: + if (ctrl->value == V4L2_MPEG_VIDEO_BITRATE_MODE_CBR || + ctrl->value == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR) + ret = 0; + break; + case V4L2_CID_MPEG_VIDEO_BITRATE: + { + uint bitrate = ctrl->value / 100000; + if (bitrate >= 10 && bitrate <= 135) + ret = 0; + break; + } + case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK: + { + uint peak_bitrate = ctrl->value / 100000; + if (peak_bitrate >= 10 && peak_bitrate <= 202) + ret = 0; + break; + } + case V4L2_CID_MPEG_STREAM_TYPE: + if (ctrl->value == V4L2_MPEG_STREAM_TYPE_MPEG2_TS) + ret = 0; + break; + default: + return -EINVAL; + } + return 0; +} + +static int vidioc_try_ext_ctrls(struct file *file, void *priv, + struct v4l2_ext_controls *ctrls) +{ + struct hdpvr_fh *fh = file->private_data; + struct hdpvr_device *dev = fh->dev; + int i, err = 0; + + if (ctrls->ctrl_class == V4L2_CTRL_CLASS_MPEG) { + for (i = 0; i < ctrls->count; i++) { + struct v4l2_ext_control *ctrl = ctrls->controls + i; + + err = hdpvr_try_ctrl(ctrl, + dev->flags & HDPVR_FLAG_AC3_CAP); + if (err) { + ctrls->error_idx = i; + break; + } + } + return err; + } + + return -EINVAL; +} + + +static int hdpvr_set_ctrl(struct hdpvr_device *dev, + struct v4l2_ext_control *ctrl) +{ + struct hdpvr_options *opt = &dev->options; + int ret = 0; + + switch (ctrl->id) { + case V4L2_CID_MPEG_AUDIO_ENCODING: + if (dev->flags & HDPVR_FLAG_AC3_CAP) { + opt->audio_codec = ctrl->value; + ret = hdpvr_set_audio(dev, opt->audio_input, + opt->audio_codec); + } + break; + case V4L2_CID_MPEG_VIDEO_ENCODING: + break; +/* case V4L2_CID_MPEG_VIDEO_B_FRAMES: */ +/* if (ctrl->value == 0 && !(opt->gop_mode & 0x2)) { */ +/* opt->gop_mode |= 0x2; */ +/* hdpvr_config_call(dev, CTRL_GOP_MODE_VALUE, */ +/* opt->gop_mode); */ +/* } */ +/* if (ctrl->value == 128 && opt->gop_mode & 0x2) { */ +/* opt->gop_mode &= ~0x2; */ +/* hdpvr_config_call(dev, CTRL_GOP_MODE_VALUE, */ +/* opt->gop_mode); */ +/* } */ +/* break; */ + case V4L2_CID_MPEG_VIDEO_BITRATE_MODE: + if (ctrl->value == V4L2_MPEG_VIDEO_BITRATE_MODE_CBR && + opt->bitrate_mode != HDPVR_CONSTANT) { + opt->bitrate_mode = HDPVR_CONSTANT; + hdpvr_config_call(dev, CTRL_BITRATE_MODE_VALUE, + opt->bitrate_mode); + } + if (ctrl->value == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR && + opt->bitrate_mode == HDPVR_CONSTANT) { + opt->bitrate_mode = HDPVR_VARIABLE_AVERAGE; + hdpvr_config_call(dev, CTRL_BITRATE_MODE_VALUE, + opt->bitrate_mode); + } + break; + case V4L2_CID_MPEG_VIDEO_BITRATE: { + uint bitrate = ctrl->value / 100000; + + opt->bitrate = bitrate; + if (bitrate >= opt->peak_bitrate) + opt->peak_bitrate = bitrate+1; + + hdpvr_set_bitrate(dev); + break; + } + case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK: { + uint peak_bitrate = ctrl->value / 100000; + + if (opt->bitrate_mode == HDPVR_CONSTANT) + break; + + if (opt->bitrate < peak_bitrate) { + opt->peak_bitrate = peak_bitrate; + hdpvr_set_bitrate(dev); + } else + ret = -EINVAL; + break; + } + case V4L2_CID_MPEG_STREAM_TYPE: + break; + default: + return -EINVAL; + } + return ret; +} + +static int vidioc_s_ext_ctrls(struct file *file, void *priv, + struct v4l2_ext_controls *ctrls) +{ + struct hdpvr_fh *fh = file->private_data; + struct hdpvr_device *dev = fh->dev; + int i, err = 0; + + if (ctrls->ctrl_class == V4L2_CTRL_CLASS_MPEG) { + for (i = 0; i < ctrls->count; i++) { + struct v4l2_ext_control *ctrl = ctrls->controls + i; + + err = hdpvr_try_ctrl(ctrl, + dev->flags & HDPVR_FLAG_AC3_CAP); + if (err) { + ctrls->error_idx = i; + break; + } + err = hdpvr_set_ctrl(dev, ctrl); + if (err) { + ctrls->error_idx = i; + break; + } + } + return err; + + } + + return -EINVAL; +} + +static int vidioc_enum_fmt_vid_cap(struct file *file, void *private_data, + struct v4l2_fmtdesc *f) +{ + + if (f->index != 0 || f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + + f->flags = V4L2_FMT_FLAG_COMPRESSED; + strncpy(f->description, "MPEG2-TS with AVC/AAC streams", 32); + f->pixelformat = V4L2_PIX_FMT_MPEG; + + return 0; +} + +static int vidioc_g_fmt_vid_cap(struct file *file, void *private_data, + struct v4l2_format *f) +{ + struct hdpvr_fh *fh = file->private_data; + struct hdpvr_device *dev = fh->dev; + struct hdpvr_video_info *vid_info; + + if (!dev) + return -ENODEV; + + vid_info = get_video_info(dev); + if (!vid_info) + return -EFAULT; + + f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG; + f->fmt.pix.width = vid_info->width; + f->fmt.pix.height = vid_info->height; + f->fmt.pix.sizeimage = dev->bulk_in_size; + f->fmt.pix.colorspace = 0; + f->fmt.pix.bytesperline = 0; + f->fmt.pix.field = V4L2_FIELD_ANY; + + kfree(vid_info); + return 0; +} + + +static const struct v4l2_ioctl_ops hdpvr_ioctl_ops = { + .vidioc_querycap = vidioc_querycap, + .vidioc_s_std = vidioc_s_std, + .vidioc_enum_input = vidioc_enum_input, + .vidioc_g_input = vidioc_g_input, + .vidioc_s_input = vidioc_s_input, + .vidioc_enumaudio = vidioc_enumaudio, + .vidioc_g_audio = vidioc_g_audio, + .vidioc_s_audio = vidioc_s_audio, + .vidioc_queryctrl = vidioc_queryctrl, + .vidioc_g_ctrl = vidioc_g_ctrl, + .vidioc_s_ctrl = vidioc_s_ctrl, + .vidioc_g_ext_ctrls = vidioc_g_ext_ctrls, + .vidioc_s_ext_ctrls = vidioc_s_ext_ctrls, + .vidioc_try_ext_ctrls = vidioc_try_ext_ctrls, + .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, + .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, +}; + +static void hdpvr_device_release(struct video_device *vdev) +{ + struct hdpvr_device *dev = video_get_drvdata(vdev); + + hdpvr_delete(dev); +} + +static const struct video_device hdpvr_video_template = { +/* .type = VFL_TYPE_GRABBER, */ +/* .type2 = VID_TYPE_CAPTURE | VID_TYPE_MPEG_ENCODER, */ + .fops = &hdpvr_fops, + .release = hdpvr_device_release, + .ioctl_ops = &hdpvr_ioctl_ops, + .tvnorms = + V4L2_STD_NTSC | V4L2_STD_SECAM | V4L2_STD_PAL_B | + V4L2_STD_PAL_G | V4L2_STD_PAL_H | V4L2_STD_PAL_I | + V4L2_STD_PAL_D | V4L2_STD_PAL_M | V4L2_STD_PAL_N | + V4L2_STD_PAL_60, +}; + +int hdpvr_register_videodev(struct hdpvr_device *dev, int devnum) +{ + /* setup and register video device */ + dev->video_dev = video_device_alloc(); + if (!dev->video_dev) { + err("video_device_alloc() failed"); + goto error; + } + + *(dev->video_dev) = hdpvr_video_template; + strcpy(dev->video_dev->name, "Hauppauge HD PVR"); + dev->video_dev->parent = &dev->udev->dev; + video_set_drvdata(dev->video_dev, dev); + + if (video_register_device(dev->video_dev, VFL_TYPE_GRABBER, devnum)) { + err("V4L2 device registration failed"); + goto error; + } + + return 0; +error: + return -ENOMEM; +} diff --git a/linux/drivers/media/video/hdpvr/hdpvr.h b/linux/drivers/media/video/hdpvr/hdpvr.h new file mode 100644 index 000000000..17db74feb --- /dev/null +++ b/linux/drivers/media/video/hdpvr/hdpvr.h @@ -0,0 +1,298 @@ +/* + * Hauppage HD PVR USB driver + * + * Copyright (C) 2008 Janne Grunau (j@jannau.net) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, version 2. + * + */ + +#include +#include +#include +#include +#include + +#define HDPVR_MAJOR_VERSION 0 +#define HDPVR_MINOR_VERSION 2 +#define HDPVR_RELEASE 0 +#define HDPVR_VERSION \ + KERNEL_VERSION(HDPVR_MAJOR_VERSION, HDPVR_MINOR_VERSION, HDPVR_RELEASE) + +#define HDPVR_MAX 8 + +/* Define these values to match your devices */ +#define HD_PVR_VENDOR_ID 0x2040 +#define HD_PVR_PRODUCT_ID 0x4900 +#define HD_PVR_PRODUCT_ID1 0x4901 +#define HD_PVR_PRODUCT_ID2 0x4902 + +#define UNSET (-1U) + +#define NUM_BUFFERS 64 + +#define HDPVR_FIRMWARE_VERSION 0x8 +#define HDPVR_FIRMWARE_VERSION_AC3 0xd + +/* #define HDPVR_DEBUG */ + +extern int hdpvr_debug; + +#define MSG_INFO 1 +#define MSG_BUFFER 2 + +struct hdpvr_options { + u8 video_std; + u8 video_input; + u8 audio_input; + u8 bitrate; /* in 100kbps */ + u8 peak_bitrate; /* in 100kbps */ + u8 bitrate_mode; + u8 gop_mode; + enum v4l2_mpeg_audio_encoding audio_codec; + u8 brightness; + u8 contrast; + u8 hue; + u8 saturation; + u8 sharpness; +}; + +/* Structure to hold all of our device specific stuff */ +struct hdpvr_device { + /* the v4l device for this device */ + struct video_device *video_dev; + /* the usb device for this device */ + struct usb_device *udev; + + /* the max packet size of the bulk endpoint */ + size_t bulk_in_size; + /* the address of the bulk in endpoint */ + __u8 bulk_in_endpointAddr; + + /* holds the current device status */ + __u8 status; + /* count the number of openers */ + uint open_count; + + /* holds the cureent set options */ + struct hdpvr_options options; + + uint flags; + + /* synchronize I/O */ + struct mutex io_mutex; + /* available buffers */ + struct list_head free_buff_list; + /* in progress buffers */ + struct list_head rec_buff_list; + /* waitqueue for buffers */ + wait_queue_head_t wait_buffer; + /* waitqueue for data */ + wait_queue_head_t wait_data; + /**/ + struct workqueue_struct *workqueue; + /**/ + struct work_struct worker; + + /* I2C adapter */ + struct i2c_adapter *i2c_adapter; + /* I2C lock */ + struct mutex i2c_mutex; + + /* usb control transfer buffer and lock */ + struct mutex usbc_mutex; + u8 *usbc_buf; +}; + + +/* buffer one bulk urb of data */ +struct hdpvr_buffer { + struct list_head buff_list; + + struct urb *urb; + + struct hdpvr_device *dev; + + uint pos; + + __u8 status; +}; + +/* */ + +struct hdpvr_video_info { + u16 width; + u16 height; + u8 fps; +}; + +enum { + STATUS_UNINITIALIZED = 0, + STATUS_IDLE, + STATUS_STARTING, + STATUS_SHUTTING_DOWN, + STATUS_STREAMING, + STATUS_ERROR, + STATUS_DISCONNECTED, +}; + +enum { + HDPVR_FLAG_AC3_CAP = 1, +}; + +enum { + BUFSTAT_UNINITIALIZED = 0, + BUFSTAT_AVAILABLE, + BUFSTAT_INPROGRESS, + BUFSTAT_READY, +}; + +#define CTRL_START_STREAMING_VALUE 0x0700 +#define CTRL_STOP_STREAMING_VALUE 0x0800 +#define CTRL_BITRATE_VALUE 0x1000 +#define CTRL_BITRATE_MODE_VALUE 0x1200 +#define CTRL_GOP_MODE_VALUE 0x1300 +#define CTRL_VIDEO_INPUT_VALUE 0x1500 +#define CTRL_VIDEO_STD_TYPE 0x1700 +#define CTRL_AUDIO_INPUT_VALUE 0x2500 +#define CTRL_BRIGHTNESS 0x2900 +#define CTRL_CONTRAST 0x2a00 +#define CTRL_HUE 0x2b00 +#define CTRL_SATURATION 0x2c00 +#define CTRL_SHARPNESS 0x2d00 +#define CTRL_LOW_PASS_FILTER_VALUE 0x3100 + +#define CTRL_DEFAULT_INDEX 0x0003 + + + /* :0 s 38 01 1000 0003 0004 4 = 0a00ca00 + * BITRATE SETTING + * 1st and 2nd byte (little endian): average bitrate in 100 000 bit/s + * min: 1 mbit/s, max: 13.5 mbit/s + * 3rd and 4th byte (little endian): peak bitrate in 100 000 bit/s + * min: average + 100kbit/s, + * max: 20.2 mbit/s + */ + + /* :0 s 38 01 1200 0003 0001 1 = 02 + * BIT RATE MODE + * constant = 1, variable (peak) = 2, variable (average) = 3 + */ + + /* :0 s 38 01 1300 0003 0001 1 = 03 + * GOP MODE (2 bit) + * low bit 0/1: advanced/simple GOP + * high bit 0/1: IDR(4/32/128) / no IDR (4/32/0) + */ + + /* :0 s 38 01 1700 0003 0001 1 = 00 + * VIDEO STANDARD or FREQUNCY 0 = 60hz, 1 = 50hz + */ + + /* :0 s 38 01 3100 0003 0004 4 = 03030000 + * FILTER CONTROL + * 1st byte luma low pass filter strength, + * 2nd byte chroma low pass filter strength, + * 3rd byte MF enable chroma, min=0, max=1 + * 4th byte n + */ + + + /* :0 s 38 b9 0001 0000 0000 0 */ + + + +/* :0 s 38 d3 0000 0000 0001 1 = 00 */ +/* ret = usb_control_msg(dev->udev, */ +/* usb_sndctrlpipe(dev->udev, 0), */ +/* 0xd3, 0x38, */ +/* 0, 0, */ +/* "\0", 1, */ +/* 1000); */ + +/* info("control request returned %d", ret); */ +/* msleep(5000); */ + + + /* :0 s b8 81 1400 0003 0005 5 < + * :0 0 5 = d0024002 19 + * QUERY FRAME SIZE AND RATE + * 1st and 2nd byte (little endian): horizontal resolution + * 3rd and 4th byte (little endian): vertical resolution + * 5th byte: frame rate + */ + + /* :0 s b8 81 1800 0003 0003 3 < + * :0 0 3 = 030104 + * QUERY SIGNAL AND DETECTED LINES, maybe INPUT + */ + +enum hdpvr_video_std { + HDPVR_60HZ = 0, + HDPVR_50HZ, +}; + +enum hdpvr_video_input { + HDPVR_COMPONENT = 0, + HDPVR_SVIDEO, + HDPVR_COMPOSITE, + HDPVR_VIDEO_INPUTS +}; + +enum hdpvr_audio_inputs { + HDPVR_RCA_BACK = 0, + HDPVR_RCA_FRONT, + HDPVR_SPDIF, + HDPVR_AUDIO_INPUTS +}; + +enum hdpvr_bitrate_mode { + HDPVR_CONSTANT = 1, + HDPVR_VARIABLE_PEAK, + HDPVR_VARIABLE_AVERAGE, +}; + +enum hdpvr_gop_mode { + HDPVR_ADVANCED_IDR_GOP = 0, + HDPVR_SIMPLE_IDR_GOP, + HDPVR_ADVANCED_NOIDR_GOP, + HDPVR_SIMPLE_NOIDR_GOP, +}; + +void hdpvr_delete(struct hdpvr_device *dev); + +/*========================================================================*/ +/* hardware control functions */ +int hdpvr_set_options(struct hdpvr_device *dev); + +int hdpvr_set_bitrate(struct hdpvr_device *dev); + +int hdpvr_set_audio(struct hdpvr_device *dev, u8 input, + enum v4l2_mpeg_audio_encoding codec); + +int hdpvr_config_call(struct hdpvr_device *dev, uint value, + unsigned char valbuf); + +struct hdpvr_video_info *get_video_info(struct hdpvr_device *dev); + +/* :0 s b8 81 1800 0003 0003 3 < */ +/* :0 0 3 = 0301ff */ +int get_input_lines_info(struct hdpvr_device *dev); + + +/*========================================================================*/ +/* v4l2 registration */ +int hdpvr_register_videodev(struct hdpvr_device *dev, int devnumber); + +int hdpvr_cancel_queue(struct hdpvr_device *dev); + +/*========================================================================*/ +/* i2c adapter registration */ +int hdpvr_register_i2c_adapter(struct hdpvr_device *dev); + +/*========================================================================*/ +/* buffer management */ +int hdpvr_free_buffers(struct hdpvr_device *dev); +int hdpvr_alloc_buffers(struct hdpvr_device *dev, uint count); -- cgit v1.2.3 From b06321e32a39a1462e511309762821ae740914f7 Mon Sep 17 00:00:00 2001 From: Janne Grunau Date: Thu, 19 Mar 2009 00:57:04 +0100 Subject: use video_ioctl2 as ioctl handler directly From: Janne Grunau The encoder commands ioctls are available in v4l2_ioctl_ops. Use them and get rid of the custom ioctl handler and use video_ioctl2. Priority: normal Signed-off-by: Janne Grunau --- linux/drivers/media/video/hdpvr/hdpvr-video.c | 85 +++++++++++++-------------- 1 file changed, 41 insertions(+), 44 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/hdpvr/hdpvr-video.c b/linux/drivers/media/video/hdpvr/hdpvr-video.c index ee481495e..6dd11f490 100644 --- a/linux/drivers/media/video/hdpvr/hdpvr-video.c +++ b/linux/drivers/media/video/hdpvr/hdpvr-video.c @@ -524,56 +524,13 @@ static unsigned int hdpvr_poll(struct file *filp, poll_table *wait) } -static long hdpvr_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) -{ - struct hdpvr_fh *fh = (struct hdpvr_fh *)filp->private_data; - struct hdpvr_device *dev = fh->dev; - int res; - - if (video_is_unregistered(dev->video_dev)) - return -EIO; - - mutex_lock(&dev->io_mutex); - switch (cmd) { - case VIDIOC_TRY_ENCODER_CMD: - case VIDIOC_ENCODER_CMD: { - struct v4l2_encoder_cmd *enc = (struct v4l2_encoder_cmd *)arg; - int try = cmd == VIDIOC_TRY_ENCODER_CMD; - - memset(&enc->raw, 0, sizeof(enc->raw)); - switch (enc->cmd) { - case V4L2_ENC_CMD_START: - enc->flags = 0; - if (try) - return 0; - res = hdpvr_start_streaming(dev); - break; - case V4L2_ENC_CMD_STOP: - if (try) - return 0; - res = hdpvr_stop_streaming(dev); - break; - default: - v4l2_dbg(MSG_INFO, hdpvr_debug, dev->video_dev, - "Unsupported encoder cmd %d\n", enc->cmd); - return -EINVAL; - } - break; - } - default: - res = video_ioctl2(filp, cmd, arg); - } - mutex_unlock(&dev->io_mutex); - return res; -} - static const struct v4l2_file_operations hdpvr_fops = { .owner = THIS_MODULE, .open = hdpvr_open, .release = hdpvr_release, .read = hdpvr_read, .poll = hdpvr_poll, - .unlocked_ioctl = hdpvr_ioctl, + .unlocked_ioctl = video_ioctl2, }; /*=======================================================================*/ @@ -1163,6 +1120,44 @@ static int vidioc_g_fmt_vid_cap(struct file *file, void *private_data, return 0; } +static int vidioc_encoder_cmd(struct file *filp, void *priv, + struct v4l2_encoder_cmd *a) +{ + struct hdpvr_fh *fh = filp->private_data; + struct hdpvr_device *dev = fh->dev; + int res; + + mutex_lock(&dev->io_mutex); + + memset(&a->raw, 0, sizeof(a->raw)); + switch (a->cmd) { + case V4L2_ENC_CMD_START: + a->flags = 0; + res = hdpvr_start_streaming(dev); + break; + case V4L2_ENC_CMD_STOP: + res = hdpvr_stop_streaming(dev); + break; + default: + v4l2_dbg(MSG_INFO, hdpvr_debug, dev->video_dev, + "Unsupported encoder cmd %d\n", a->cmd); + return -EINVAL; + } + mutex_unlock(&dev->io_mutex); + return res; +} + +static int vidioc_try_encoder_cmd(struct file *filp, void *priv, + struct v4l2_encoder_cmd *a) +{ + switch (a->cmd) { + case V4L2_ENC_CMD_START: + case V4L2_ENC_CMD_STOP: + return 0; + default: + return -EINVAL; + } +} static const struct v4l2_ioctl_ops hdpvr_ioctl_ops = { .vidioc_querycap = vidioc_querycap, @@ -1181,6 +1176,8 @@ static const struct v4l2_ioctl_ops hdpvr_ioctl_ops = { .vidioc_try_ext_ctrls = vidioc_try_ext_ctrls, .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, + .vidioc_encoder_cmd = vidioc_encoder_cmd, + .vidioc_try_encoder_cmd = vidioc_try_encoder_cmd, }; static void hdpvr_device_release(struct video_device *vdev) -- cgit v1.2.3 From 4d2f7316ade12329d6431989db0f367d7806eb87 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Thu, 19 Mar 2009 09:55:22 +0100 Subject: gspca - main: May have isochronous transfers on altsetting 0. From: Jean-Francois Moine Priority: normal Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/gspca.c | 12 +++++++----- linux/drivers/media/video/gspca/gspca.h | 1 + 2 files changed, 8 insertions(+), 5 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/gspca.c b/linux/drivers/media/video/gspca/gspca.c index d629ce1dc..88de8b865 100644 --- a/linux/drivers/media/video/gspca/gspca.c +++ b/linux/drivers/media/video/gspca/gspca.c @@ -486,14 +486,14 @@ static struct usb_host_endpoint *get_ep(struct gspca_dev *gspca_dev) i = gspca_dev->alt; /* previous alt setting */ /* try isoc */ - while (--i > 0) { /* alt 0 is unusable */ + while (--i >= 0) { ep = alt_xfer(&intf->altsetting[i], USB_ENDPOINT_XFER_ISOC); if (ep) break; } - /* if no isoc, try bulk */ + /* if no isoc, try bulk (alt 0 only) */ if (ep == NULL) { ep = alt_xfer(&intf->altsetting[0], USB_ENDPOINT_XFER_BULK); @@ -501,6 +501,8 @@ static struct usb_host_endpoint *get_ep(struct gspca_dev *gspca_dev) err("no transfer endpoint found"); return NULL; } + i = 0; + gspca_dev->bulk = 1; } PDEBUG(D_STREAM, "use alt %d ep 0x%02x", i, ep->desc.bEndpointAddress); @@ -527,7 +529,7 @@ static int create_urbs(struct gspca_dev *gspca_dev, /* calculate the packet size and the number of packets */ psize = le16_to_cpu(ep->desc.wMaxPacketSize); - if (gspca_dev->alt != 0) { /* isoc */ + if (!gspca_dev->bulk) { /* isoc */ /* See paragraph 5.9 / table 5-11 of the usb 2.0 spec. */ psize = (psize & 0x07ff) * (1 + ((psize >> 11) & 3)); @@ -627,7 +629,7 @@ static int gspca_init_transfer(struct gspca_dev *gspca_dev) goto out; /* clear the bulk endpoint */ - if (gspca_dev->alt == 0) /* if bulk transfer */ + if (gspca_dev->bulk) usb_clear_halt(gspca_dev->dev, gspca_dev->urb[0]->pipe); @@ -640,7 +642,7 @@ static int gspca_init_transfer(struct gspca_dev *gspca_dev) gspca_dev->streaming = 1; /* some bulk transfers are started by the subdriver */ - if (gspca_dev->alt == 0 && gspca_dev->cam.bulk_nurbs == 0) + if (gspca_dev->bulk && gspca_dev->cam.bulk_nurbs == 0) break; /* submit the URBs */ diff --git a/linux/drivers/media/video/gspca/gspca.h b/linux/drivers/media/video/gspca/gspca.h index 6f172e9e5..e4d4cf6ce 100644 --- a/linux/drivers/media/video/gspca/gspca.h +++ b/linux/drivers/media/video/gspca/gspca.h @@ -167,6 +167,7 @@ struct gspca_dev { __u8 iface; /* USB interface number */ __u8 alt; /* USB alternate setting */ __u8 nbalt; /* number of USB alternate settings */ + u8 bulk; /* image transfer by 0:isoc / 1:bulk */ }; int gspca_dev_probe(struct usb_interface *intf, -- cgit v1.2.3 From c114356c9ba4583ba29beb0b7fcbee70130ab6b1 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Thu, 19 Mar 2009 10:05:06 +0100 Subject: gspca - ov534: Bad frame pointer after adding the last packet. From: Jean-Francois Moine Priority: normal Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/ov534.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/ov534.c b/linux/drivers/media/video/gspca/ov534.c index de0ab8e06..09bc8aaf1 100644 --- a/linux/drivers/media/video/gspca/ov534.c +++ b/linux/drivers/media/video/gspca/ov534.c @@ -487,8 +487,9 @@ scan_next: goto discard; } - gspca_frame_add(gspca_dev, LAST_PACKET, frame, NULL, 0); - } + frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame, + NULL, 0); + } /* Done this payload */ goto scan_next; -- cgit v1.2.3 From 0fbee78ef38aaa0a6a0a98bc557adf10ef7c67a2 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Thu, 19 Mar 2009 10:12:59 +0100 Subject: gspca - ov534: Adjust the packet scan function. From: Jean-Francois Moine - change max payload size to 2040 bytes (was 2048) - optimize Priority: normal Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/ov534.c | 115 ++++++++++++++++---------------- 1 file changed, 57 insertions(+), 58 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/ov534.c b/linux/drivers/media/video/gspca/ov534.c index 09bc8aaf1..0ffb56256 100644 --- a/linux/drivers/media/video/gspca/ov534.c +++ b/linux/drivers/media/video/gspca/ov534.c @@ -46,9 +46,9 @@ MODULE_LICENSE("GPL"); /* specific webcam descriptor */ struct sd { struct gspca_dev gspca_dev; /* !! must be the first item */ - __u32 last_fid; __u32 last_pts; - int frame_rate; + u16 last_fid; + u8 frame_rate; }; /* V4L2 controls supported by the driver */ @@ -428,76 +428,75 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, struct gspca_frame *frame, { struct sd *sd = (struct sd *) gspca_dev; __u32 this_pts; - int this_fid; + u16 this_fid; int remaining_len = len; - __u8 *next_data = data; -scan_next: - if (remaining_len <= 0) - return; - - data = next_data; - len = min(remaining_len, 2048); - remaining_len -= len; - next_data += len; - - /* Payloads are prefixed with a UVC-style header. We - consider a frame to start when the FID toggles, or the PTS - changes. A frame ends when EOF is set, and we've received - the correct number of bytes. */ - - /* Verify UVC header. Header length is always 12 */ - if (data[0] != 12 || len < 12) { - PDEBUG(D_PACK, "bad header"); - goto discard; - } + do { + len = min(remaining_len, 2040); /*fixme: was 2048*/ - /* Check errors */ - if (data[1] & UVC_STREAM_ERR) { - PDEBUG(D_PACK, "payload error"); - goto discard; - } + /* Payloads are prefixed with a UVC-style header. We + consider a frame to start when the FID toggles, or the PTS + changes. A frame ends when EOF is set, and we've received + the correct number of bytes. */ - /* Extract PTS and FID */ - if (!(data[1] & UVC_STREAM_PTS)) { - PDEBUG(D_PACK, "PTS not present"); - goto discard; - } - this_pts = (data[5] << 24) | (data[4] << 16) | (data[3] << 8) | data[2]; - this_fid = (data[1] & UVC_STREAM_FID) ? 1 : 0; - - /* If PTS or FID has changed, start a new frame. */ - if (this_pts != sd->last_pts || this_fid != sd->last_fid) { - gspca_frame_add(gspca_dev, FIRST_PACKET, frame, NULL, 0); - sd->last_pts = this_pts; - sd->last_fid = this_fid; - } - - /* Add the data from this payload */ - gspca_frame_add(gspca_dev, INTER_PACKET, frame, - data + 12, len - 12); + /* Verify UVC header. Header length is always 12 */ + if (data[0] != 12 || len < 12) { + PDEBUG(D_PACK, "bad header"); + goto discard; + } - /* If this packet is marked as EOF, end the frame */ - if (data[1] & UVC_STREAM_EOF) { - sd->last_pts = 0; + /* Check errors */ + if (data[1] & UVC_STREAM_ERR) { + PDEBUG(D_PACK, "payload error"); + goto discard; + } - if ((frame->data_end - frame->data) != - (gspca_dev->width * gspca_dev->height * 2)) { - PDEBUG(D_PACK, "short frame"); + /* Extract PTS and FID */ + if (!(data[1] & UVC_STREAM_PTS)) { + PDEBUG(D_PACK, "PTS not present"); goto discard; } + this_pts = (data[5] << 24) | (data[4] << 16) + | (data[3] << 8) | data[2]; + this_fid = (data[1] & UVC_STREAM_FID) ? 1 : 0; - frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame, + /* If PTS or FID has changed, start a new frame. */ + if (this_pts != sd->last_pts || this_fid != sd->last_fid) { + gspca_frame_add(gspca_dev, FIRST_PACKET, frame, NULL, 0); + sd->last_pts = this_pts; + sd->last_fid = this_fid; + } + + /* Add the data from this payload */ + gspca_frame_add(gspca_dev, INTER_PACKET, frame, + data + 12, len - 12); + + /* If this packet is marked as EOF, end the frame */ + if (data[1] & UVC_STREAM_EOF) { + sd->last_pts = 0; + + if (frame->data_end - frame->data != + gspca_dev->width * gspca_dev->height * 2) { + PDEBUG(D_PACK, "short frame"); + goto discard; + } + + frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame, + NULL, 0); } - /* Done this payload */ - goto scan_next; + /* Done this payload */ + goto scan_next; discard: - /* Discard data until a new frame starts. */ - gspca_frame_add(gspca_dev, DISCARD_PACKET, frame, NULL, 0); - goto scan_next; + /* Discard data until a new frame starts. */ + gspca_frame_add(gspca_dev, DISCARD_PACKET, frame, NULL, 0); + +scan_next: + remaining_len -= len; + data += len; + } while (remaining_len > 0); } /* get stream parameters (framerate) */ -- cgit v1.2.3 From d6e87708161f26972d91eca3edb0aeebfc4b0afa Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Thu, 19 Mar 2009 10:15:21 +0100 Subject: gspca - ov534: New sensor ov965x and re-enable the webcam 06f8:3003. From: Jean-Francois Moine Priority: normal Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/ov534.c | 721 +++++++++++++++++++++++++------- 1 file changed, 573 insertions(+), 148 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/ov534.c b/linux/drivers/media/video/gspca/ov534.c index 0ffb56256..0f5ec9317 100644 --- a/linux/drivers/media/video/gspca/ov534.c +++ b/linux/drivers/media/video/gspca/ov534.c @@ -1,7 +1,8 @@ /* - * ov534/ov772x gspca driver + * ov534 gspca driver * Copyright (C) 2008 Antonio Ospite * Copyright (C) 2008 Jim Paris + * Copyright (C) 2009 Jean-Francois Moine http://moinejf.free.fr * * Based on a prototype written by Mark Ferrell * USB protocol reverse engineered by Jim Paris @@ -26,7 +27,7 @@ #include "gspca.h" -#define OV534_REG_ADDRESS 0xf1 /* ? */ +#define OV534_REG_ADDRESS 0xf1 /* sensor address */ #define OV534_REG_SUBADDR 0xf2 #define OV534_REG_WRITE 0xf3 #define OV534_REG_READ 0xf4 @@ -49,6 +50,10 @@ struct sd { __u32 last_pts; u16 last_fid; u8 frame_rate; + + u8 sensor; +#define SENSOR_OV772X 0 +#define SENSOR_OV965X 1 }; /* V4L2 controls supported by the driver */ @@ -63,114 +68,7 @@ static const struct v4l2_pix_format vga_mode[] = { .priv = 0}, }; -static void ov534_reg_write(struct gspca_dev *gspca_dev, u16 reg, u8 val) -{ - struct usb_device *udev = gspca_dev->dev; - int ret; - - PDEBUG(D_USBO, "reg=0x%04x, val=0%02x", reg, val); - gspca_dev->usb_buf[0] = val; - ret = usb_control_msg(udev, - usb_sndctrlpipe(udev, 0), - 0x1, - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - 0x0, reg, gspca_dev->usb_buf, 1, CTRL_TIMEOUT); - if (ret < 0) - PDEBUG(D_ERR, "write failed"); -} - -static u8 ov534_reg_read(struct gspca_dev *gspca_dev, u16 reg) -{ - struct usb_device *udev = gspca_dev->dev; - int ret; - - ret = usb_control_msg(udev, - usb_rcvctrlpipe(udev, 0), - 0x1, - USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - 0x0, reg, gspca_dev->usb_buf, 1, CTRL_TIMEOUT); - PDEBUG(D_USBI, "reg=0x%04x, data=0x%02x", reg, gspca_dev->usb_buf[0]); - if (ret < 0) - PDEBUG(D_ERR, "read failed"); - return gspca_dev->usb_buf[0]; -} - -/* Two bits control LED: 0x21 bit 7 and 0x23 bit 7. - * (direction and output)? */ -static void ov534_set_led(struct gspca_dev *gspca_dev, int status) -{ - u8 data; - - PDEBUG(D_CONF, "led status: %d", status); - - data = ov534_reg_read(gspca_dev, 0x21); - data |= 0x80; - ov534_reg_write(gspca_dev, 0x21, data); - - data = ov534_reg_read(gspca_dev, 0x23); - if (status) - data |= 0x80; - else - data &= ~(0x80); - - ov534_reg_write(gspca_dev, 0x23, data); -} - -static int sccb_check_status(struct gspca_dev *gspca_dev) -{ - u8 data; - int i; - - for (i = 0; i < 5; i++) { - data = ov534_reg_read(gspca_dev, OV534_REG_STATUS); - - switch (data) { - case 0x00: - return 1; - case 0x04: - return 0; - case 0x03: - break; - default: - PDEBUG(D_ERR, "sccb status 0x%02x, attempt %d/5", - data, i + 1); - } - } - return 0; -} - -static void sccb_reg_write(struct gspca_dev *gspca_dev, u16 reg, u8 val) -{ - PDEBUG(D_USBO, "reg: 0x%04x, val: 0x%02x", reg, val); - ov534_reg_write(gspca_dev, OV534_REG_SUBADDR, reg); - ov534_reg_write(gspca_dev, OV534_REG_WRITE, val); - ov534_reg_write(gspca_dev, OV534_REG_OPERATION, OV534_OP_WRITE_3); - - if (!sccb_check_status(gspca_dev)) - PDEBUG(D_ERR, "sccb_reg_write failed"); -} - -#ifdef GSPCA_DEBUG -static u8 sccb_reg_read(struct gspca_dev *gspca_dev, u16 reg) -{ - ov534_reg_write(gspca_dev, OV534_REG_SUBADDR, reg); - ov534_reg_write(gspca_dev, OV534_REG_OPERATION, OV534_OP_WRITE_2); - if (!sccb_check_status(gspca_dev)) - PDEBUG(D_ERR, "sccb_reg_read failed 1"); - - ov534_reg_write(gspca_dev, OV534_REG_OPERATION, OV534_OP_READ_2); - if (!sccb_check_status(gspca_dev)) - PDEBUG(D_ERR, "sccb_reg_read failed 2"); - - return ov534_reg_read(gspca_dev, OV534_REG_READ); -} -#endif - -static const __u8 ov534_reg_initdata[][2] = { - { 0xe7, 0x3a }, - - { OV534_REG_ADDRESS, 0x42 }, /* select OV772x sensor */ - +static const u8 bridge_init_ov722x[][2] = { { 0xc2, 0x0c }, { 0x88, 0xf8 }, { 0xc3, 0x69 }, @@ -228,7 +126,7 @@ static const __u8 ov534_reg_initdata[][2] = { { 0xc2, 0x0c }, }; -static const __u8 ov772x_reg_initdata[][2] = { +static const u8 sensor_init_ov722x[][2] = { { 0x12, 0x80 }, { 0x11, 0x01 }, @@ -311,6 +209,475 @@ static const __u8 ov772x_reg_initdata[][2] = { { 0x0c, 0xd0 } }; +static const u8 bridge_init_ov965x[][2] = { + {0x88, 0xf8}, + {0x89, 0xff}, + {0x76, 0x03}, + {0x92, 0x03}, + {0x95, 0x10}, + {0xe2, 0x00}, + {0xe7, 0x3e}, + {0x8d, 0x1c}, + {0x8e, 0x00}, + {0x8f, 0x00}, + {0x1f, 0x00}, + {0xc3, 0xf9}, + {0x89, 0xff}, + {0x88, 0xf8}, + {0x76, 0x03}, + {0x92, 0x01}, + {0x93, 0x18}, + {0x1c, 0x0a}, + {0x1d, 0x48}, + {0xc0, 0x50}, + {0xc1, 0x3c}, + {0x34, 0x05}, + {0xc2, 0x0c}, + {0xc3, 0xf9}, + {0x34, 0x05}, + {0xe7, 0x2e}, + {0x31, 0xf9}, + {0x35, 0x02}, + {0xd9, 0x10}, + {0x25, 0x42}, + {0x94, 0x11}, +}; + +static const u8 sensor_init_ov965x[][2] = { + {0x12, 0x80}, /* com7 - reset */ + {0x00, 0x00}, /* gain */ + {0x01, 0x80}, /* blue */ + {0x02, 0x80}, /* red */ + {0x03, 0x1b}, /* vref */ + {0x04, 0x03}, /* com1 - exposure low bits */ + {0x0b, 0x57}, /* ver */ + {0x0e, 0x61}, /* com5 */ + {0x0f, 0x42}, /* com6 */ + {0x11, 0x00}, /* clkrc */ + {0x12, 0x02}, /* com7 */ + {0x13, 0xe7}, /* com8 - everything (AGC, AWB and AEC) */ + {0x14, 0x28}, /* com9 */ + {0x16, 0x24}, /* rsvd16 */ + {0x17, 0x1d}, /* hstart*/ + {0x18, 0xbd}, /* hstop */ + {0x19, 0x01}, /* vstrt */ + {0x1a, 0x81}, /* vstop*/ + {0x1e, 0x04}, /* mvfp */ + {0x24, 0x3c}, /* aew */ + {0x25, 0x36}, /* aeb */ + {0x26, 0x71}, /* vpt */ + {0x27, 0x08}, /* bbias */ + {0x28, 0x08}, /* gbbias */ + {0x29, 0x15}, /* gr com */ + {0x2a, 0x00}, + {0x2b, 0x00}, + {0x2c, 0x08}, /* rbias */ + {0x32, 0xff}, /* href */ + {0x33, 0x00}, /* chlf */ + {0x34, 0x3f}, /* arblm */ + {0x35, 0x00}, /* rsvd35 */ + {0x36, 0xf8}, /* rsvd36 */ + {0x38, 0x72}, /* acom38 */ + {0x39, 0x57}, /* ofon */ + {0x3a, 0x80}, /* tslb */ + {0x3b, 0xc4}, + {0x3d, 0x99}, /* com13 */ + {0x3f, 0xc1}, + {0x40, 0xc0}, /* com15 */ + {0x41, 0x40}, /* com16 */ + {0x42, 0xc0}, + {0x43, 0x0a}, + {0x44, 0xf0}, + {0x45, 0x46}, + {0x46, 0x62}, + {0x47, 0x2a}, + {0x48, 0x3c}, + {0x4a, 0xfc}, + {0x4b, 0xfc}, + {0x4c, 0x7f}, + {0x4d, 0x7f}, + {0x4e, 0x7f}, + {0x4f, 0x98}, + {0x50, 0x98}, + {0x51, 0x00}, + {0x52, 0x28}, + {0x53, 0x70}, + {0x54, 0x98}, + {0x58, 0x1a}, + {0x59, 0x85}, + {0x5a, 0xa9}, + {0x5b, 0x64}, + {0x5c, 0x84}, + {0x5d, 0x53}, + {0x5e, 0x0e}, + {0x5f, 0xf0}, + {0x60, 0xf0}, + {0x61, 0xf0}, + {0x62, 0x00}, /* lcc1 */ + {0x63, 0x00}, /* lcc2 */ + {0x64, 0x02}, /* lcc3 */ + {0x65, 0x16}, /* lcc4 */ + {0x66, 0x01}, /* lcc5 */ + {0x69, 0x02}, /* hv */ + {0x6b, 0x5a}, /* dbvl */ + {0x6c, 0x04}, + {0x6d, 0x55}, + {0x6e, 0x00}, + {0x6f, 0x9d}, + {0x70, 0x21}, + {0x71, 0x78}, + {0x72, 0x00}, + {0x73, 0x01}, + {0x74, 0x3a}, + {0x75, 0x35}, + {0x76, 0x01}, + {0x77, 0x02}, + {0x7a, 0x12}, + {0x7b, 0x08}, + {0x7c, 0x16}, + {0x7d, 0x30}, + {0x7e, 0x5e}, + {0x7f, 0x72}, + {0x80, 0x82}, + {0x81, 0x8e}, + {0x82, 0x9a}, + {0x83, 0xa4}, + {0x84, 0xac}, + {0x85, 0xb8}, + {0x86, 0xc3}, + {0x87, 0xd6}, + {0x88, 0xe6}, + {0x89, 0xf2}, + {0x8a, 0x03}, + {0x8c, 0x89}, + {0x14, 0x28}, /* com9 */ + {0x90, 0x7d}, + {0x91, 0x7b}, + {0x9d, 0x03}, + {0x9e, 0x04}, + {0x9f, 0x7a}, + {0xa0, 0x79}, + {0xa1, 0x40}, /* aechm */ + {0xa4, 0x50}, + {0xa5, 0x68}, /* com26 */ + {0xa6, 0x4a}, + {0xa8, 0xc1}, /* acoma8 */ + {0xa9, 0xef}, /* acoma9 */ + {0xaa, 0x92}, + {0xab, 0x04}, + {0xac, 0x80}, + {0xad, 0x80}, + {0xae, 0x80}, + {0xaf, 0x80}, + {0xb2, 0xf2}, + {0xb3, 0x20}, + {0xb4, 0x20}, + {0xb5, 0x00}, + {0xb6, 0xaf}, + {0xbb, 0xae}, + {0xbc, 0x7f}, + {0xdb, 0x7f}, + {0xbe, 0x7f}, + {0xbf, 0x7f}, + {0xc0, 0xe2}, + {0xc1, 0xc0}, + {0xc2, 0x01}, + {0xc3, 0x4e}, + {0xc6, 0x85}, + {0xc7, 0x80}, + {0xc9, 0xe0}, + {0xca, 0xe8}, + {0xcb, 0xf0}, + {0xcc, 0xd8}, + {0xcd, 0xf1}, + {0x4f, 0x98}, + {0x50, 0x98}, + {0x51, 0x00}, + {0x52, 0x28}, + {0x53, 0x70}, + {0x54, 0x98}, + {0x58, 0x1a}, + {0xff, 0x41}, /* read 41, write ff 00 */ + {0x41, 0x40}, /* com16 */ + {0xc5, 0x03}, + {0x6a, 0x02}, + + {0x12, 0x62}, /* com7 - VGA + CIF */ + {0x36, 0xfa}, /* rsvd36 */ + {0x69, 0x0a}, /* hv */ + {0x8c, 0x89}, /* com22 */ + {0x14, 0x28}, /* com9 */ + {0x3e, 0x0c}, + {0x41, 0x40}, /* com16 */ + {0x72, 0x00}, + {0x73, 0x00}, + {0x74, 0x3a}, + {0x75, 0x35}, + {0x76, 0x01}, + {0xc7, 0x80}, + {0x03, 0x12}, /* vref */ + {0x17, 0x16}, /* hstart */ + {0x18, 0x02}, /* hstop */ + {0x19, 0x01}, /* vstrt */ + {0x1a, 0x3d}, /* vstop */ + {0x32, 0xff}, /* href */ + {0xc0, 0xaa}, +}; + +static const u8 bridge_init_ov965x_2[][2] = { + {0x94, 0xaa}, + {0xf1, 0x60}, + {0xe5, 0x04}, + {0xc0, 0x50}, + {0xc1, 0x3c}, + {0x8c, 0x00}, + {0x8d, 0x1c}, + {0x34, 0x05}, + + {0xc2, 0x0c}, + {0xc3, 0xf9}, + {0xda, 0x01}, + {0x50, 0x00}, + {0x51, 0xa0}, + {0x52, 0x3c}, + {0x53, 0x00}, + {0x54, 0x00}, + {0x55, 0x00}, + {0x57, 0x00}, + {0x5c, 0x00}, + {0x5a, 0xa0}, + {0x5b, 0x78}, + {0x35, 0x02}, + {0xd9, 0x10}, + {0x94, 0x11}, +}; + +static const u8 sensor_init_ov965x_2[][2] = { + {0x3b, 0xc4}, + {0x1e, 0x04}, /* mvfp */ + {0x13, 0xe0}, /* com8 */ + {0x00, 0x00}, /* gain */ + {0x13, 0xe7}, /* com8 - everything (AGC, AWB and AEC) */ + {0x11, 0x03}, /* clkrc */ + {0x6b, 0x5a}, /* dblv */ + {0x6a, 0x05}, + {0xc5, 0x07}, + {0xa2, 0x4b}, + {0xa3, 0x3e}, + {0x2d, 0x00}, + {0xff, 0x42}, /* read 42, write ff 00 */ + {0x42, 0xc0}, + {0x2d, 0x00}, + {0xff, 0x42}, /* read 42, write ff 00 */ + {0x42, 0xc1}, + {0x3f, 0x01}, + {0xff, 0x42}, /* read 42, write ff 00 */ + {0x42, 0xc1}, + {0x4f, 0x98}, + {0x50, 0x98}, + {0x51, 0x00}, + {0x52, 0x28}, + {0x53, 0x70}, + {0x54, 0x98}, + {0x58, 0x1a}, + {0xff, 0x41}, /* read 41, write ff 00 */ + {0x41, 0x40}, /* com16 */ + {0x56, 0x40}, + {0x55, 0x8f}, + {0x10, 0x25}, /* aech - exposure high bits */ + {0xff, 0x13}, /* read 13, write ff 00 */ + {0x13, 0xe7}, /* com8 - everything (AGC, AWB and AEC) */ +}; + +static const u8 bridge_start_ov965x[][2] = { +#if 0 + {0x94, 0xaa}, + {0xf1, 0x60}, + {0xe5, 0x04}, + {0xc0, 0x50}, + {0xc1, 0x3c}, + {0x8c, 0x00}, + {0x8d, 0x1c}, + {0x34, 0x05}, +#endif + {0xc2, 0x4c}, + {0xc3, 0xf9}, + {0x50, 0x00}, + {0x51, 0xa0}, + {0x52, 0x78}, + {0x53, 0x00}, + {0x54, 0x00}, + {0x55, 0x00}, + {0x57, 0x00}, + {0x5c, 0x00}, + {0x5a, 0x28}, + {0x5b, 0x1e}, + {0x35, 0x00}, + {0xd9, 0x21}, + {0x94, 0x11}, +}; + +static const u8 sensor_start_ov965x[][2] = { + {0x3b, 0xe4}, + {0x1e, 0x04}, /* mvfp */ + {0x13, 0xe0}, /* com8 */ + {0x00, 0x00}, + {0x13, 0xe7}, /* com8 - everything (AGC, AWB and AEC) */ + {0x11, 0x01}, /* clkrc */ + {0x6b, 0x5a}, /* dblv */ + {0x6a, 0x02}, + {0xc5, 0x03}, + {0xa2, 0x96}, + {0xa3, 0x7d}, + {0xff, 0x13}, /* read 13, write ff 00 */ + {0x13, 0xe7}, + {0x3a, 0x80}, + {0xff, 0x42}, /* read 42, write ff 00 */ + {0x42, 0xc1}, +}; + +#if 0 +static const u8 sensor_start_ov965x_2[][2] = { + {0xff, 0x13}, /* read 13, write ff 00 */ + {0x13, 0xe7}, + {0x3a, 0x80}, + {0xff, 0x42}, /* read 42, write ff 00 */ + {0x42, 0xc1}, +}; +#endif + +static void ov534_reg_write(struct gspca_dev *gspca_dev, u16 reg, u8 val) +{ + struct usb_device *udev = gspca_dev->dev; + int ret; + + PDEBUG(D_USBO, "reg=0x%04x, val=0%02x", reg, val); + gspca_dev->usb_buf[0] = val; + ret = usb_control_msg(udev, + usb_sndctrlpipe(udev, 0), + 0x01, + USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, + 0x00, reg, gspca_dev->usb_buf, 1, CTRL_TIMEOUT); + if (ret < 0) + PDEBUG(D_ERR, "write failed"); +} + +static u8 ov534_reg_read(struct gspca_dev *gspca_dev, u16 reg) +{ + struct usb_device *udev = gspca_dev->dev; + int ret; + + ret = usb_control_msg(udev, + usb_rcvctrlpipe(udev, 0), + 0x01, + USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, + 0x00, reg, gspca_dev->usb_buf, 1, CTRL_TIMEOUT); + PDEBUG(D_USBI, "reg=0x%04x, data=0x%02x", reg, gspca_dev->usb_buf[0]); + if (ret < 0) + PDEBUG(D_ERR, "read failed"); + return gspca_dev->usb_buf[0]; +} + +/* Two bits control LED: 0x21 bit 7 and 0x23 bit 7. + * (direction and output)? */ +static void ov534_set_led(struct gspca_dev *gspca_dev, int status) +{ + u8 data; + + PDEBUG(D_CONF, "led status: %d", status); + + data = ov534_reg_read(gspca_dev, 0x21); + data |= 0x80; + ov534_reg_write(gspca_dev, 0x21, data); + + data = ov534_reg_read(gspca_dev, 0x23); + if (status) + data |= 0x80; + else + data &= ~0x80; + + ov534_reg_write(gspca_dev, 0x23, data); + + if (!status) { + data = ov534_reg_read(gspca_dev, 0x21); + data &= ~0x80; + ov534_reg_write(gspca_dev, 0x21, data); + } +} + +static int sccb_check_status(struct gspca_dev *gspca_dev) +{ + u8 data; + int i; + + for (i = 0; i < 5; i++) { + data = ov534_reg_read(gspca_dev, OV534_REG_STATUS); + + switch (data) { + case 0x00: + return 1; + case 0x04: + return 0; + case 0x03: + break; + default: + PDEBUG(D_ERR, "sccb status 0x%02x, attempt %d/5", + data, i + 1); + } + } + return 0; +} + +static void sccb_reg_write(struct gspca_dev *gspca_dev, u8 reg, u8 val) +{ + PDEBUG(D_USBO, "reg: 0x%02x, val: 0x%02x", reg, val); + ov534_reg_write(gspca_dev, OV534_REG_SUBADDR, reg); + ov534_reg_write(gspca_dev, OV534_REG_WRITE, val); + ov534_reg_write(gspca_dev, OV534_REG_OPERATION, OV534_OP_WRITE_3); + + if (!sccb_check_status(gspca_dev)) + PDEBUG(D_ERR, "sccb_reg_write failed"); +} + +static u8 sccb_reg_read(struct gspca_dev *gspca_dev, u16 reg) +{ + ov534_reg_write(gspca_dev, OV534_REG_SUBADDR, reg); + ov534_reg_write(gspca_dev, OV534_REG_OPERATION, OV534_OP_WRITE_2); + if (!sccb_check_status(gspca_dev)) + PDEBUG(D_ERR, "sccb_reg_read failed 1"); + + ov534_reg_write(gspca_dev, OV534_REG_OPERATION, OV534_OP_READ_2); + if (!sccb_check_status(gspca_dev)) + PDEBUG(D_ERR, "sccb_reg_read failed 2"); + + return ov534_reg_read(gspca_dev, OV534_REG_READ); +} + +/* output a bridge sequence (reg - val) */ +static void reg_w_array(struct gspca_dev *gspca_dev, + const u8 (*data)[2], int len) +{ + while (--len >= 0) { + ov534_reg_write(gspca_dev, (*data)[0], (*data)[1]); + data++; + } +} + +/* output a sensor sequence (reg - val) */ +static void sccb_w_array(struct gspca_dev *gspca_dev, + const u8 (*data)[2], int len) +{ + while (--len >= 0) { + if ((*data)[0] != 0xff) { + sccb_reg_write(gspca_dev, (*data)[0], (*data)[1]); + } else { + sccb_reg_read(gspca_dev, (*data)[1]); + sccb_reg_write(gspca_dev, 0xff, 0x00); + } + data++; + } +} + /* set framerate */ static void ov534_set_frame_rate(struct gspca_dev *gspca_dev) { @@ -346,37 +713,15 @@ static void ov534_set_frame_rate(struct gspca_dev *gspca_dev) PDEBUG(D_PROBE, "frame_rate: %d", fr); } -/* setup method */ -static void ov534_setup(struct gspca_dev *gspca_dev) -{ - int i; - - /* Initialize bridge chip */ - for (i = 0; i < ARRAY_SIZE(ov534_reg_initdata); i++) - ov534_reg_write(gspca_dev, ov534_reg_initdata[i][0], - ov534_reg_initdata[i][1]); - - PDEBUG(D_PROBE, "sensor is ov%02x%02x", - sccb_reg_read(gspca_dev, 0x0a), - sccb_reg_read(gspca_dev, 0x0b)); - - ov534_set_led(gspca_dev, 1); - - /* Initialize sensor */ - for (i = 0; i < ARRAY_SIZE(ov772x_reg_initdata); i++) - sccb_reg_write(gspca_dev, ov772x_reg_initdata[i][0], - ov772x_reg_initdata[i][1]); - - ov534_reg_write(gspca_dev, 0xe0, 0x09); - ov534_set_led(gspca_dev, 0); -} - /* this function is called at probe time */ static int sd_config(struct gspca_dev *gspca_dev, const struct usb_device_id *id) { + struct sd *sd = (struct sd *) gspca_dev; struct cam *cam; + sd->sensor = id->driver_info; + cam = &gspca_dev->cam; cam->cam_mode = vga_mode; @@ -391,26 +736,106 @@ static int sd_config(struct gspca_dev *gspca_dev, /* this function is called at probe and resume time */ static int sd_init(struct gspca_dev *gspca_dev) { - ov534_setup(gspca_dev); - ov534_set_frame_rate(gspca_dev); + struct sd *sd = (struct sd *) gspca_dev; + u16 sensor_id; + static const u8 sensor_addr[2] = { + 0x42, /* 0 SENSOR_OV772X */ + 0x60, /* 1 SENSOR_OV965X */ + }; + + /* reset bridge */ + ov534_reg_write(gspca_dev, 0xe7, 0x3a); + ov534_reg_write(gspca_dev, 0xe0, 0x08); + msleep(100); + + /* initialize the sensor address */ + ov534_reg_write(gspca_dev, OV534_REG_ADDRESS, + sensor_addr[sd->sensor]); + + /* reset sensor */ + sccb_reg_write(gspca_dev, 0x12, 0x80); + msleep(10); + + /* probe the sensor */ + sccb_reg_read(gspca_dev, 0x0a); + sensor_id = sccb_reg_read(gspca_dev, 0x0a) << 8; + sccb_reg_read(gspca_dev, 0x0b); + sensor_id |= sccb_reg_read(gspca_dev, 0x0b); + PDEBUG(D_PROBE, "Sensor ID: %04x", sensor_id); + + /* initialize */ + switch (sd->sensor) { + case SENSOR_OV772X: + reg_w_array(gspca_dev, bridge_init_ov722x, + ARRAY_SIZE(bridge_init_ov722x)); + ov534_set_led(gspca_dev, 1); + sccb_w_array(gspca_dev, sensor_init_ov722x, + ARRAY_SIZE(sensor_init_ov722x)); + ov534_reg_write(gspca_dev, 0xe0, 0x09); + ov534_set_led(gspca_dev, 0); + ov534_set_frame_rate(gspca_dev); + break; + default: +/* case SENSOR_OV965X: */ + reg_w_array(gspca_dev, bridge_init_ov965x, + ARRAY_SIZE(bridge_init_ov965x)); + sccb_w_array(gspca_dev, sensor_init_ov965x, + ARRAY_SIZE(sensor_init_ov965x)); + reg_w_array(gspca_dev, bridge_init_ov965x_2, + ARRAY_SIZE(bridge_init_ov965x_2)); + sccb_w_array(gspca_dev, sensor_init_ov965x_2, + ARRAY_SIZE(sensor_init_ov965x_2)); + ov534_reg_write(gspca_dev, 0xe0, 0x00); + ov534_reg_write(gspca_dev, 0xe0, 0x01); + ov534_set_led(gspca_dev, 0); + ov534_reg_write(gspca_dev, 0xe0, 0x00); + } return 0; } static int sd_start(struct gspca_dev *gspca_dev) { - /* start streaming data */ - ov534_set_led(gspca_dev, 1); - ov534_reg_write(gspca_dev, 0xe0, 0x00); + struct sd *sd = (struct sd *) gspca_dev; + switch (sd->sensor) { + case SENSOR_OV772X: + ov534_set_led(gspca_dev, 1); + ov534_reg_write(gspca_dev, 0xe0, 0x00); + break; + default: +/* case SENSOR_OV965X: */ +#if 0 + sccb_w_array(gspca_dev, sensor_init_ov965x, + ARRAY_SIZE(sensor_init_ov965x)); +#endif + reg_w_array(gspca_dev, bridge_start_ov965x, + ARRAY_SIZE(bridge_start_ov965x)); + sccb_w_array(gspca_dev, sensor_start_ov965x, + ARRAY_SIZE(sensor_start_ov965x)); + ov534_reg_write(gspca_dev, 0xe0, 0x00); + ov534_set_led(gspca_dev, 1); +/*fixme: other sensor start omitted*/ + } return 0; } static void sd_stopN(struct gspca_dev *gspca_dev) { - /* stop streaming data */ - ov534_reg_write(gspca_dev, 0xe0, 0x09); - ov534_set_led(gspca_dev, 0); + struct sd *sd = (struct sd *) gspca_dev; + + switch (sd->sensor) { + case SENSOR_OV772X: + ov534_reg_write(gspca_dev, 0xe0, 0x09); + ov534_set_led(gspca_dev, 0); + break; + default: +/* case SENSOR_OV965X: */ + ov534_reg_write(gspca_dev, 0xe0, 0x01); + ov534_set_led(gspca_dev, 0); + ov534_reg_write(gspca_dev, 0xe0, 0x00); + break; + } } /* Values for bmHeaderInfo (Video and Still Image Payload Headers, 2.4.3.3) */ @@ -556,11 +981,11 @@ static const struct sd_desc sd_desc = { /* -- module initialisation -- */ static const __devinitdata struct usb_device_id device_table[] = { #if 0 - /* these two are not supported yet, different sensors */ - {USB_DEVICE(0x06f8, 0x3002)}, /* Hercules Blog Webcam */ - {USB_DEVICE(0x06f8, 0x3003)}, /* Hercules Dualpix HD Weblog */ + /* not supported yet */ + {USB_DEVICE(0x06f8, 0x3002), .driver_info = SENSOR_unknown}, #endif - {USB_DEVICE(0x1415, 0x2000)}, /* Sony HD Eye for PS3 (SLEH 00201) */ + {USB_DEVICE(0x06f8, 0x3003), .driver_info = SENSOR_OV965X}, + {USB_DEVICE(0x1415, 0x2000), .driver_info = SENSOR_OV772X}, {} }; -- cgit v1.2.3 From 811459fbe3478562cf110f89057144f59d4f78d5 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Thu, 19 Mar 2009 20:53:32 +0100 Subject: tvaudio: always call init_timer to prevent rmmod crash. From: Hans Verkuil In the tvaudio_remove function del_timer_sync(&chip->wt) is called. However, chip->wt isn't always initialized depending on the type of audio chip. Since del_timer_sync hangs when given an uninitialized timer we should always initialize it. Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/tvaudio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/tvaudio.c b/linux/drivers/media/video/tvaudio.c index d92b2d4b5..39d796908 100644 --- a/linux/drivers/media/video/tvaudio.c +++ b/linux/drivers/media/video/tvaudio.c @@ -2062,6 +2062,7 @@ static int tvaudio_probe(struct i2c_client *client, const struct i2c_device_id * } chip->thread = NULL; + init_timer(&chip->wt); if (desc->flags & CHIP_NEED_CHECKMODE) { if (!desc->getmode || !desc->setmode) { /* This shouldn't be happen. Warn user, but keep working @@ -2071,7 +2072,6 @@ static int tvaudio_probe(struct i2c_client *client, const struct i2c_device_id * return 0; } /* start async thread */ - init_timer(&chip->wt); chip->wt.function = chip_thread_wake; chip->wt.data = (unsigned long)chip; chip->thread = kthread_run(chip_thread, chip, client->name); -- cgit v1.2.3 From a053ae2d2e29f959bc6fd2ec190963df9a24a48e Mon Sep 17 00:00:00 2001 From: Janne Grunau Date: Thu, 19 Mar 2009 23:00:35 +0100 Subject: fix mispelled Hauppauge in HD PVR and PVR USB2 driver comments Priority: normal Signed-off-by: Janne Grunau --- linux/drivers/media/video/hdpvr/hdpvr-control.c | 2 +- linux/drivers/media/video/hdpvr/hdpvr-core.c | 2 +- linux/drivers/media/video/hdpvr/hdpvr-i2c.c | 2 +- linux/drivers/media/video/hdpvr/hdpvr-video.c | 2 +- linux/drivers/media/video/hdpvr/hdpvr.h | 2 +- linux/drivers/media/video/pvrusb2/pvrusb2-encoder.c | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/hdpvr/hdpvr-control.c b/linux/drivers/media/video/hdpvr/hdpvr-control.c index ecf02c621..51de74aeb 100644 --- a/linux/drivers/media/video/hdpvr/hdpvr-control.c +++ b/linux/drivers/media/video/hdpvr/hdpvr-control.c @@ -1,5 +1,5 @@ /* - * Hauppage HD PVR USB driver - video 4 linux 2 interface + * Hauppauge HD PVR USB driver - video 4 linux 2 interface * * Copyright (C) 2008 Janne Grunau (j@jannau.net) * diff --git a/linux/drivers/media/video/hdpvr/hdpvr-core.c b/linux/drivers/media/video/hdpvr/hdpvr-core.c index a33b03df0..4a2bbb72b 100644 --- a/linux/drivers/media/video/hdpvr/hdpvr-core.c +++ b/linux/drivers/media/video/hdpvr/hdpvr-core.c @@ -1,5 +1,5 @@ /* - * Hauppage HD PVR USB driver + * Hauppauge HD PVR USB driver * * Copyright (C) 2001-2004 Greg Kroah-Hartman (greg@kroah.com) * Copyright (C) 2008 Janne Grunau (j@jannau.net) diff --git a/linux/drivers/media/video/hdpvr/hdpvr-i2c.c b/linux/drivers/media/video/hdpvr/hdpvr-i2c.c index 35096dec2..c4b5d1515 100644 --- a/linux/drivers/media/video/hdpvr/hdpvr-i2c.c +++ b/linux/drivers/media/video/hdpvr/hdpvr-i2c.c @@ -1,6 +1,6 @@ /* - * Hauppage HD PVR USB driver + * Hauppauge HD PVR USB driver * * Copyright (C) 2008 Janne Grunau (j@jannau.net) * diff --git a/linux/drivers/media/video/hdpvr/hdpvr-video.c b/linux/drivers/media/video/hdpvr/hdpvr-video.c index 6dd11f490..235978003 100644 --- a/linux/drivers/media/video/hdpvr/hdpvr-video.c +++ b/linux/drivers/media/video/hdpvr/hdpvr-video.c @@ -1,5 +1,5 @@ /* - * Hauppage HD PVR USB driver - video 4 linux 2 interface + * Hauppauge HD PVR USB driver - video 4 linux 2 interface * * Copyright (C) 2008 Janne Grunau (j@jannau.net) * diff --git a/linux/drivers/media/video/hdpvr/hdpvr.h b/linux/drivers/media/video/hdpvr/hdpvr.h index 17db74feb..9bc8051b5 100644 --- a/linux/drivers/media/video/hdpvr/hdpvr.h +++ b/linux/drivers/media/video/hdpvr/hdpvr.h @@ -1,5 +1,5 @@ /* - * Hauppage HD PVR USB driver + * Hauppauge HD PVR USB driver * * Copyright (C) 2008 Janne Grunau (j@jannau.net) * diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-encoder.c b/linux/drivers/media/video/pvrusb2/pvrusb2-encoder.c index 744bc192c..452981827 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-encoder.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-encoder.c @@ -380,7 +380,7 @@ static int pvr2_encoder_prep_config(struct pvr2_hdw *hdw) int encMisc3Arg = 0; #if 0 /* keep */ - /* This inexplicable bit happens in the Hauppage windows + /* This inexplicable bit happens in the Hauppauge windows driver (for both 24xxx and 29xxx devices). However I currently see no difference in behavior with or without this stuff. Leave this here as a note of its existence, -- cgit v1.2.3 From a728c348653d59c62786e26db627004f9b402519 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 20 Mar 2009 19:33:59 -0300 Subject: Kconfig: replace all occurrences of CUSTOMIZE to CUSTOMISE From: Mauro Carvalho Chehab There are several Kconfig items using CUSTOMIZE. Yet, most use the English writing CUSTOMISE. This generates lots of trouble, because people sometimes type the Kbuild item different. Let's standardise every occurrence using the same syntax. The changes were generated by this small shell script: for i in `find linux -type f`; do sed s,CUSTOMIZE,CUSTOMISE,g $i >/tmp/a && mv /tmp/a $i; done Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/common/tuners/Kconfig | 60 +++++++++++++++---------------- linux/drivers/media/dvb/b2c2/Kconfig | 2 +- linux/drivers/media/dvb/bt8xx/Kconfig | 2 +- linux/drivers/media/dvb/dvb-usb/Kconfig | 48 ++++++++++++------------- linux/drivers/media/dvb/ttpci/Kconfig | 2 +- linux/drivers/media/video/au0828/Kconfig | 6 ++-- linux/drivers/media/video/cx18/Kconfig | 2 +- linux/drivers/media/video/cx23885/Kconfig | 10 +++--- linux/drivers/media/video/cx88/Kconfig | 2 +- linux/drivers/media/video/pvrusb2/Kconfig | 6 ++-- linux/drivers/media/video/saa7134/Kconfig | 8 ++--- 11 files changed, 74 insertions(+), 74 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/common/tuners/Kconfig b/linux/drivers/media/common/tuners/Kconfig index 724e6870c..52c3f65b1 100644 --- a/linux/drivers/media/common/tuners/Kconfig +++ b/linux/drivers/media/common/tuners/Kconfig @@ -21,17 +21,17 @@ config MEDIA_TUNER tristate default VIDEO_MEDIA && I2C depends on VIDEO_MEDIA && I2C - select MEDIA_TUNER_XC2028 if !MEDIA_TUNER_CUSTOMIZE - select MEDIA_TUNER_XC5000 if !MEDIA_TUNER_CUSTOMIZE - select MEDIA_TUNER_MT20XX if !MEDIA_TUNER_CUSTOMIZE - select MEDIA_TUNER_TDA8290 if !MEDIA_TUNER_CUSTOMIZE - select MEDIA_TUNER_TEA5761 if !MEDIA_TUNER_CUSTOMIZE - select MEDIA_TUNER_TEA5767 if !MEDIA_TUNER_CUSTOMIZE - select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMIZE - select MEDIA_TUNER_TDA9887 if !MEDIA_TUNER_CUSTOMIZE - select MEDIA_TUNER_MC44S803 if !MEDIA_TUNER_CUSTOMIZE - -menuconfig MEDIA_TUNER_CUSTOMIZE + select MEDIA_TUNER_XC2028 if !MEDIA_TUNER_CUSTOMISE + select MEDIA_TUNER_XC5000 if !MEDIA_TUNER_CUSTOMISE + select MEDIA_TUNER_MT20XX if !MEDIA_TUNER_CUSTOMISE + select MEDIA_TUNER_TDA8290 if !MEDIA_TUNER_CUSTOMISE + select MEDIA_TUNER_TEA5761 if !MEDIA_TUNER_CUSTOMISE + select MEDIA_TUNER_TEA5767 if !MEDIA_TUNER_CUSTOMISE + select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMISE + select MEDIA_TUNER_TDA9887 if !MEDIA_TUNER_CUSTOMISE + select MEDIA_TUNER_MC44S803 if !MEDIA_TUNER_CUSTOMISE + +menuconfig MEDIA_TUNER_CUSTOMISE bool "Customize analog and hybrid tuner modules to build" depends on MEDIA_TUNER default n @@ -44,13 +44,13 @@ menuconfig MEDIA_TUNER_CUSTOMIZE If unsure say N. -if MEDIA_TUNER_CUSTOMIZE +if MEDIA_TUNER_CUSTOMISE config MEDIA_TUNER_SIMPLE tristate "Simple tuner support" depends on VIDEO_MEDIA && I2C select MEDIA_TUNER_TDA9887 - default m if MEDIA_TUNER_CUSTOMIZE + default m if MEDIA_TUNER_CUSTOMISE help Say Y here to include support for various simple tuners. @@ -59,28 +59,28 @@ config MEDIA_TUNER_TDA8290 depends on VIDEO_MEDIA && I2C select MEDIA_TUNER_TDA827X select MEDIA_TUNER_TDA18271 - default m if MEDIA_TUNER_CUSTOMIZE + default m if MEDIA_TUNER_CUSTOMISE help Say Y here to include support for Philips TDA8290+8275(a) tuner. config MEDIA_TUNER_TDA827X tristate "Philips TDA827X silicon tuner" depends on VIDEO_MEDIA && I2C - default m if MEDIA_TUNER_CUSTOMIZE + default m if MEDIA_TUNER_CUSTOMISE help A DVB-T silicon tuner module. Say Y when you want to support this tuner. config MEDIA_TUNER_TDA18271 tristate "NXP TDA18271 silicon tuner" depends on VIDEO_MEDIA && I2C - default m if MEDIA_TUNER_CUSTOMIZE + default m if MEDIA_TUNER_CUSTOMISE help A silicon tuner module. Say Y when you want to support this tuner. config MEDIA_TUNER_TDA9887 tristate "TDA 9885/6/7 analog IF demodulator" depends on VIDEO_MEDIA && I2C - default m if MEDIA_TUNER_CUSTOMIZE + default m if MEDIA_TUNER_CUSTOMISE help Say Y here to include support for Philips TDA9885/6/7 analog IF demodulator. @@ -89,63 +89,63 @@ config MEDIA_TUNER_TEA5761 tristate "TEA 5761 radio tuner (EXPERIMENTAL)" depends on VIDEO_MEDIA && I2C depends on EXPERIMENTAL - default m if MEDIA_TUNER_CUSTOMIZE + default m if MEDIA_TUNER_CUSTOMISE help Say Y here to include support for the Philips TEA5761 radio tuner. config MEDIA_TUNER_TEA5767 tristate "TEA 5767 radio tuner" depends on VIDEO_MEDIA && I2C - default m if MEDIA_TUNER_CUSTOMIZE + default m if MEDIA_TUNER_CUSTOMISE help Say Y here to include support for the Philips TEA5767 radio tuner. config MEDIA_TUNER_MT20XX tristate "Microtune 2032 / 2050 tuners" depends on VIDEO_MEDIA && I2C - default m if MEDIA_TUNER_CUSTOMIZE + default m if MEDIA_TUNER_CUSTOMISE help Say Y here to include support for the MT2032 / MT2050 tuner. config MEDIA_TUNER_MT2060 tristate "Microtune MT2060 silicon IF tuner" depends on VIDEO_MEDIA && I2C - default m if MEDIA_TUNER_CUSTOMIZE + default m if MEDIA_TUNER_CUSTOMISE help A driver for the silicon IF tuner MT2060 from Microtune. config MEDIA_TUNER_MT2266 tristate "Microtune MT2266 silicon tuner" depends on VIDEO_MEDIA && I2C - default m if MEDIA_TUNER_CUSTOMIZE + default m if MEDIA_TUNER_CUSTOMISE help A driver for the silicon baseband tuner MT2266 from Microtune. config MEDIA_TUNER_MT2131 tristate "Microtune MT2131 silicon tuner" depends on VIDEO_MEDIA && I2C - default m if MEDIA_TUNER_CUSTOMIZE + default m if MEDIA_TUNER_CUSTOMISE help A driver for the silicon baseband tuner MT2131 from Microtune. config MEDIA_TUNER_QT1010 tristate "Quantek QT1010 silicon tuner" depends on VIDEO_MEDIA && I2C - default m if MEDIA_TUNER_CUSTOMIZE + default m if MEDIA_TUNER_CUSTOMISE help A driver for the silicon tuner QT1010 from Quantek. config MEDIA_TUNER_XC2028 tristate "XCeive xc2028/xc3028 tuners" depends on VIDEO_MEDIA && I2C - default m if MEDIA_TUNER_CUSTOMIZE + default m if MEDIA_TUNER_CUSTOMISE help Say Y here to include support for the xc2028/xc3028 tuners. config MEDIA_TUNER_XC5000 tristate "Xceive XC5000 silicon tuner" depends on VIDEO_MEDIA && I2C - default m if MEDIA_TUNER_CUSTOMIZE + default m if MEDIA_TUNER_CUSTOMISE help A driver for the silicon tuner XC5000 from Xceive. This device is only used inside a SiP called togther with a @@ -154,22 +154,22 @@ config MEDIA_TUNER_XC5000 config MEDIA_TUNER_MXL5005S tristate "MaxLinear MSL5005S silicon tuner" depends on VIDEO_MEDIA && I2C - default m if MEDIA_TUNER_CUSTOMIZE + default m if MEDIA_TUNER_CUSTOMISE help A driver for the silicon tuner MXL5005S from MaxLinear. config MEDIA_TUNER_MXL5007T tristate "MaxLinear MxL5007T silicon tuner" depends on VIDEO_MEDIA && I2C - default m if MEDIA_TUNER_CUSTOMIZE + default m if MEDIA_TUNER_CUSTOMISE help A driver for the silicon tuner MxL5007T from MaxLinear. config MEDIA_TUNER_MC44S803 tristate "Freescale MC44S803 Low Power CMOS Broadband tuners" depends on VIDEO_MEDIA && I2C - default m if MEDIA_TUNER_CUSTOMIZE + default m if MEDIA_TUNER_CUSTOMISE help Say Y here to support the Freescale MC44S803 based tuners -endif # MEDIA_TUNER_CUSTOMIZE +endif # MEDIA_TUNER_CUSTOMISE diff --git a/linux/drivers/media/dvb/b2c2/Kconfig b/linux/drivers/media/dvb/b2c2/Kconfig index a8c6249c4..9e5781400 100644 --- a/linux/drivers/media/dvb/b2c2/Kconfig +++ b/linux/drivers/media/dvb/b2c2/Kconfig @@ -13,7 +13,7 @@ config DVB_B2C2_FLEXCOP select DVB_TUNER_ITD1000 if !DVB_FE_CUSTOMISE select DVB_ISL6421 if !DVB_FE_CUSTOMISE select DVB_CX24123 if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMIZE + select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMISE select DVB_TUNER_CX24113 if !DVB_FE_CUSTOMISE help Support for the digital TV receiver chip made by B2C2 Inc. included in diff --git a/linux/drivers/media/dvb/bt8xx/Kconfig b/linux/drivers/media/dvb/bt8xx/Kconfig index 27edb0ece..8668e634c 100644 --- a/linux/drivers/media/dvb/bt8xx/Kconfig +++ b/linux/drivers/media/dvb/bt8xx/Kconfig @@ -8,7 +8,7 @@ config DVB_BT8XX select DVB_OR51211 if !DVB_FE_CUSTOMISE select DVB_LGDT330X if !DVB_FE_CUSTOMISE select DVB_ZL10353 if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMIZE + select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMISE help Support for PCI cards based on the Bt8xx PCI bridge. Examples are the Nebula cards, the Pinnacle PCTV cards, the Twinhan DST cards, diff --git a/linux/drivers/media/dvb/dvb-usb/Kconfig b/linux/drivers/media/dvb/dvb-usb/Kconfig index b899d509a..5b0c8cc25 100644 --- a/linux/drivers/media/dvb/dvb-usb/Kconfig +++ b/linux/drivers/media/dvb/dvb-usb/Kconfig @@ -25,7 +25,7 @@ config DVB_USB_A800 depends on DVB_USB select DVB_DIB3000MC select DVB_PLL if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMIZE + select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMISE help Say Y here to support the AVerMedia AverTV DVB-T USB 2.0 (A800) receiver. @@ -34,7 +34,7 @@ config DVB_USB_DIBUSB_MB depends on DVB_USB select DVB_PLL if !DVB_FE_CUSTOMISE select DVB_DIB3000MB - select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMIZE + select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMISE help Support for USB 1.1 and 2.0 DVB-T receivers based on reference designs made by DiBcom () equipped with a DiB3000M-B demodulator. @@ -55,7 +55,7 @@ config DVB_USB_DIBUSB_MC tristate "DiBcom USB DVB-T devices (based on the DiB3000M-C/P) (see help for device list)" depends on DVB_USB select DVB_DIB3000MC - select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMIZE + select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMISE help Support for USB2.0 DVB-T receivers based on reference designs made by DiBcom () equipped with a DiB3000M-C/P demodulator. @@ -75,11 +75,11 @@ config DVB_USB_DIB0700 select DVB_S5H1411 if !DVB_FE_CUSTOMISE select DVB_LGDT3305 if !DVB_FE_CUSTOMISE select DVB_TUNER_DIB0070 if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMIZE - select MEDIA_TUNER_MT2266 if !MEDIA_TUNER_CUSTOMIZE - select MEDIA_TUNER_XC2028 if !MEDIA_TUNER_CUSTOMIZE - select MEDIA_TUNER_XC5000 if !MEDIA_TUNER_CUSTOMIZE - select MEDIA_TUNER_MXL5007T if !MEDIA_TUNER_CUSTOMIZE + select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMISE + select MEDIA_TUNER_MT2266 if !MEDIA_TUNER_CUSTOMISE + select MEDIA_TUNER_XC2028 if !MEDIA_TUNER_CUSTOMISE + select MEDIA_TUNER_XC5000 if !MEDIA_TUNER_CUSTOMISE + select MEDIA_TUNER_MXL5007T if !MEDIA_TUNER_CUSTOMISE help Support for USB2.0/1.1 DVB receivers based on the DiB0700 USB bridge. The USB bridge is also present in devices having the DiB7700 DVB-T-USB @@ -97,7 +97,7 @@ config DVB_USB_UMT_010 depends on DVB_USB select DVB_PLL if !DVB_FE_CUSTOMISE select DVB_DIB3000MC - select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMIZE + select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMISE select DVB_MT352 if !DVB_FE_CUSTOMISE help Say Y here to support the HanfTek UMT-010 USB2.0 stick-sized DVB-T receiver. @@ -113,9 +113,9 @@ config DVB_USB_CXUSB select DVB_DIB7000P if !DVB_FE_CUSTOMISE select DVB_LGS8GL5 if !DVB_FE_CUSTOMISE select DVB_TUNER_DIB0070 if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMIZE - select MEDIA_TUNER_XC2028 if !MEDIA_TUNER_CUSTOMIZE - select MEDIA_TUNER_MXL5005S if !MEDIA_TUNER_CUSTOMIZE + select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMISE + select MEDIA_TUNER_XC2028 if !MEDIA_TUNER_CUSTOMISE + select MEDIA_TUNER_MXL5005S if !MEDIA_TUNER_CUSTOMISE help Say Y here to support the Conexant USB2.0 hybrid reference design. Currently, only DVB and ATSC modes are supported, analog mode @@ -129,8 +129,8 @@ config DVB_USB_M920X depends on DVB_USB select DVB_MT352 if !DVB_FE_CUSTOMISE select DVB_TDA1004X if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_QT1010 if !MEDIA_TUNER_CUSTOMIZE - select MEDIA_TUNER_TDA827X if !MEDIA_TUNER_CUSTOMIZE + select MEDIA_TUNER_QT1010 if !MEDIA_TUNER_CUSTOMISE + select MEDIA_TUNER_TDA827X if !MEDIA_TUNER_CUSTOMISE help Say Y here to support the MSI Mega Sky 580 USB2.0 DVB-T receiver. Currently, only devices with a product id of @@ -141,7 +141,7 @@ config DVB_USB_GL861 tristate "Genesys Logic GL861 USB2.0 support" depends on DVB_USB select DVB_ZL10353 if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_QT1010 if !MEDIA_TUNER_CUSTOMIZE + select MEDIA_TUNER_QT1010 if !MEDIA_TUNER_CUSTOMISE help Say Y here to support the MSI Megasky 580 (55801) DVB-T USB2.0 receiver with USB ID 0db0:5581. @@ -150,7 +150,7 @@ config DVB_USB_AU6610 tristate "Alcor Micro AU6610 USB2.0 support" depends on DVB_USB select DVB_ZL10353 if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_QT1010 if !MEDIA_TUNER_CUSTOMIZE + select MEDIA_TUNER_QT1010 if !MEDIA_TUNER_CUSTOMISE help Say Y here to support the Sigmatek DVB-110 DVB-T USB2.0 receiver. @@ -203,7 +203,7 @@ config DVB_USB_NOVA_T_USB2 depends on DVB_USB select DVB_DIB3000MC select DVB_PLL if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMIZE + select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMISE help Say Y here to support the Hauppauge WinTV-NOVA-T usb2 DVB-T USB2.0 receiver. @@ -239,8 +239,8 @@ config DVB_USB_OPERA1 config DVB_USB_AF9005 tristate "Afatech AF9005 DVB-T USB1.1 support" depends on DVB_USB && EXPERIMENTAL - select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMIZE - select MEDIA_TUNER_QT1010 if !MEDIA_TUNER_CUSTOMIZE + select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMISE + select MEDIA_TUNER_QT1010 if !MEDIA_TUNER_CUSTOMISE help Say Y here to support the Afatech AF9005 based DVB-T USB1.1 receiver and the TerraTec Cinergy T USB XE (Rev.1) @@ -288,7 +288,7 @@ config DVB_USB_DTV5100 tristate "AME DTV-5100 USB2.0 DVB-T support" depends on DVB_USB select DVB_ZL10353 if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_QT1010 if !MEDIA_TUNER_CUSTOMIZE + select MEDIA_TUNER_QT1010 if !MEDIA_TUNER_CUSTOMISE help Say Y here to support the AME DTV-5100 USB2.0 DVB-T receiver. @@ -297,10 +297,10 @@ config DVB_USB_AF9015 depends on DVB_USB && EXPERIMENTAL select DVB_AF9013 select DVB_PLL if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMIZE - select MEDIA_TUNER_QT1010 if !MEDIA_TUNER_CUSTOMIZE - select MEDIA_TUNER_TDA18271 if !MEDIA_TUNER_CUSTOMIZE - select MEDIA_TUNER_MXL5005S if !MEDIA_TUNER_CUSTOMIZE + select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMISE + select MEDIA_TUNER_QT1010 if !MEDIA_TUNER_CUSTOMISE + select MEDIA_TUNER_TDA18271 if !MEDIA_TUNER_CUSTOMISE + select MEDIA_TUNER_MXL5005S if !MEDIA_TUNER_CUSTOMISE select MEDIA_TUNER_MC44S803 if !MEDIA_TUNER_CUSTOMISE help Say Y here to support the Afatech AF9015 based DVB-T USB2.0 receiver diff --git a/linux/drivers/media/dvb/ttpci/Kconfig b/linux/drivers/media/dvb/ttpci/Kconfig index ab0bcd208..772990415 100644 --- a/linux/drivers/media/dvb/ttpci/Kconfig +++ b/linux/drivers/media/dvb/ttpci/Kconfig @@ -108,7 +108,7 @@ config DVB_BUDGET_CI select DVB_STB6100 if !DVB_FE_CUSTOMISE select DVB_LNBP21 if !DVB_FE_CUSTOMISE select DVB_TDA10023 if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_TDA827X if !MEDIA_TUNER_CUSTOMIZE + select MEDIA_TUNER_TDA827X if !MEDIA_TUNER_CUSTOMISE select VIDEO_IR help Support for simple SAA7146 based DVB cards diff --git a/linux/drivers/media/video/au0828/Kconfig b/linux/drivers/media/video/au0828/Kconfig index 551f9ba63..05cdf494d 100644 --- a/linux/drivers/media/video/au0828/Kconfig +++ b/linux/drivers/media/video/au0828/Kconfig @@ -5,9 +5,9 @@ config VIDEO_AU0828 select I2C_ALGOBIT select VIDEO_TVEEPROM select DVB_AU8522 if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_XC5000 if !MEDIA_TUNER_CUSTOMIZE - select MEDIA_TUNER_MXL5007T if !MEDIA_TUNER_CUSTOMIZE - select MEDIA_TUNER_TDA18271 if !MEDIA_TUNER_CUSTOMIZE + select MEDIA_TUNER_XC5000 if !MEDIA_TUNER_CUSTOMISE + select MEDIA_TUNER_MXL5007T if !MEDIA_TUNER_CUSTOMISE + select MEDIA_TUNER_TDA18271 if !MEDIA_TUNER_CUSTOMISE ---help--- This is a video4linux driver for Auvitek's USB device. diff --git a/linux/drivers/media/video/cx18/Kconfig b/linux/drivers/media/video/cx18/Kconfig index 8940b5387..e8a50a611 100644 --- a/linux/drivers/media/video/cx18/Kconfig +++ b/linux/drivers/media/video/cx18/Kconfig @@ -9,7 +9,7 @@ config VIDEO_CX18 select VIDEO_CX2341X select VIDEO_CS5345 select DVB_S5H1409 if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_MXL5005S if !MEDIA_TUNER_CUSTOMIZE + select MEDIA_TUNER_MXL5005S if !MEDIA_TUNER_CUSTOMISE ---help--- This is a video4linux driver for Conexant cx23418 based PCI combo video recorder devices. diff --git a/linux/drivers/media/video/cx23885/Kconfig b/linux/drivers/media/video/cx23885/Kconfig index e603ceb28..fd3fc3e31 100644 --- a/linux/drivers/media/video/cx23885/Kconfig +++ b/linux/drivers/media/video/cx23885/Kconfig @@ -19,11 +19,11 @@ config VIDEO_CX23885 select DVB_LNBP21 if !DVB_FE_CUSTOMISE select DVB_STV6110 if !DVB_FE_CUSTOMISE select DVB_STV0900 if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_MT2131 if !MEDIA_TUNER_CUSTOMIZE - select MEDIA_TUNER_XC2028 if !MEDIA_TUNER_CUSTOMIZE - select MEDIA_TUNER_TDA8290 if !MEDIA_TUNER_CUSTOMIZE - select MEDIA_TUNER_TDA18271 if !MEDIA_TUNER_CUSTOMIZE - select MEDIA_TUNER_XC5000 if !MEDIA_TUNER_CUSTOMIZE + select MEDIA_TUNER_MT2131 if !MEDIA_TUNER_CUSTOMISE + select MEDIA_TUNER_XC2028 if !MEDIA_TUNER_CUSTOMISE + select MEDIA_TUNER_TDA8290 if !MEDIA_TUNER_CUSTOMISE + select MEDIA_TUNER_TDA18271 if !MEDIA_TUNER_CUSTOMISE + select MEDIA_TUNER_XC5000 if !MEDIA_TUNER_CUSTOMISE ---help--- This is a video4linux driver for Conexant 23885 based TV cards. diff --git a/linux/drivers/media/video/cx88/Kconfig b/linux/drivers/media/video/cx88/Kconfig index 2d250a2a7..49952980d 100644 --- a/linux/drivers/media/video/cx88/Kconfig +++ b/linux/drivers/media/video/cx88/Kconfig @@ -61,7 +61,7 @@ config VIDEO_CX88_DVB select DVB_STV0299 if !DVB_FE_CUSTOMISE select DVB_STV0288 if !DVB_FE_CUSTOMISE select DVB_STB6000 if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMIZE + select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMISE ---help--- This adds support for DVB/ATSC cards based on the Conexant 2388x chip. diff --git a/linux/drivers/media/video/pvrusb2/Kconfig b/linux/drivers/media/video/pvrusb2/Kconfig index 17cde1757..f9b6001e1 100644 --- a/linux/drivers/media/video/pvrusb2/Kconfig +++ b/linux/drivers/media/video/pvrusb2/Kconfig @@ -41,9 +41,9 @@ config VIDEO_PVRUSB2_DVB select DVB_S5H1409 if !DVB_FE_CUSTOMISE select DVB_S5H1411 if !DVB_FE_CUSTOMISE select DVB_TDA10048 if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_TDA18271 if !MEDIA_TUNER_CUSTOMIZE - select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMIZE - select MEDIA_TUNER_TDA8290 if !MEDIA_TUNER_CUSTOMIZE + select MEDIA_TUNER_TDA18271 if !MEDIA_TUNER_CUSTOMISE + select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMISE + select MEDIA_TUNER_TDA8290 if !MEDIA_TUNER_CUSTOMISE ---help--- This option enables a DVB interface for the pvrusb2 driver. diff --git a/linux/drivers/media/video/saa7134/Kconfig b/linux/drivers/media/video/saa7134/Kconfig index e62b29967..a2089acb0 100644 --- a/linux/drivers/media/video/saa7134/Kconfig +++ b/linux/drivers/media/video/saa7134/Kconfig @@ -36,15 +36,15 @@ config VIDEO_SAA7134_DVB select DVB_TDA826X if !DVB_FE_CUSTOMISE select DVB_ISL6421 if !DVB_FE_CUSTOMISE select DVB_ISL6405 if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_TDA827X if !MEDIA_TUNER_CUSTOMIZE - select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMIZE + select MEDIA_TUNER_TDA827X if !MEDIA_TUNER_CUSTOMISE + select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMISE select DVB_ZL10036 if !DVB_FE_CUSTOMISE select DVB_MT312 if !DVB_FE_CUSTOMISE select DVB_LNBP21 if !DVB_FE_CUSTOMISE select DVB_ZL10353 if !DVB_FE_CUSTOMISE select DVB_LGDT3305 if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_TDA18271 if !MEDIA_TUNER_CUSTOMIZE - select MEDIA_TUNER_TDA8290 if !MEDIA_TUNER_CUSTOMIZE + select MEDIA_TUNER_TDA18271 if !MEDIA_TUNER_CUSTOMISE + select MEDIA_TUNER_TDA8290 if !MEDIA_TUNER_CUSTOMISE ---help--- This adds support for DVB cards based on the Philips saa7134 chip. -- cgit v1.2.3 From 7a55de60b3e11b6d8f17465246d9cba22df9f502 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 20 Mar 2009 19:33:48 -0700 Subject: cx231xx: convert the calls to subdev format From: Sri Deevi This patch converts cx231xx to the new v4l2 dev/subdev, doing: - Conversion of i2c calls to subdev calls; - all subdev calls to call_all(); - Corrected the header file order in cx231xx.h; - Added tuner frequency setting. Priority: normal Signed-off-by: Srinivasa Deevi Reviewed-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/cx231xx/cx231xx-cards.c | 61 +++++++++++++++------ linux/drivers/media/video/cx231xx/cx231xx-i2c.c | 44 +--------------- linux/drivers/media/video/cx231xx/cx231xx-vbi.c | 4 -- linux/drivers/media/video/cx231xx/cx231xx-video.c | 64 ++++++++++------------- linux/drivers/media/video/cx231xx/cx231xx.h | 23 ++++++-- 5 files changed, 92 insertions(+), 104 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 435ecf58d..31c9c93bd 100644 --- a/linux/drivers/media/video/cx231xx/cx231xx-cards.c +++ b/linux/drivers/media/video/cx231xx/cx231xx-cards.c @@ -244,8 +244,6 @@ void cx231xx_pre_card_setup(struct cx231xx *dev) } -#if 0 /* Keep */ - static void cx231xx_config_tuner(struct cx231xx *dev) { struct tuner_setup tun_setup; @@ -259,8 +257,8 @@ static void cx231xx_config_tuner(struct cx231xx *dev) tun_setup.addr = dev->tuner_addr; tun_setup.tuner_callback = cx231xx_tuner_callback; - cx231xx_i2c_call_clients(&dev->i2c_bus[1], TUNER_SET_TYPE_ADDR, - &tun_setup); + tuner_call(dev, tuner, s_type_addr, &tun_setup); + #if 0 /* Keep */ if (tun_setup.type == TUNER_XC5000) { static struct xc2028_ctrl ctrl = { @@ -272,20 +270,17 @@ static void cx231xx_config_tuner(struct cx231xx *dev) .tuner = dev->tuner_type, .priv = &ctrl, }; - cx231xx_i2c_call_clients(&dev->i2c_bus[1], TUNER_SET_CONFIG, - &cfg); + tuner_call(dev, tuner, s_config, &cfg); } #endif - /* configure tuner */ f.tuner = 0; f.type = V4L2_TUNER_ANALOG_TV; f.frequency = 9076; /* just a magic number */ dev->ctl_freq = f.frequency; - cx231xx_i2c_call_clients(&dev->i2c_bus[1], VIDIOC_S_FREQUENCY, &f); -} + call_all(dev, tuner, s_frequency, &f); -#endif +} /* ----------------------------------------------------------------------- */ void cx231xx_set_ir(struct cx231xx *dev, struct IR_i2c *ir) @@ -309,6 +304,7 @@ void cx231xx_set_ir(struct cx231xx *dev, struct IR_i2c *ir) void cx231xx_card_setup(struct cx231xx *dev) { + cx231xx_set_model(dev); dev->tuner_type = cx231xx_boards[dev->model].tuner_type; @@ -333,16 +329,29 @@ void cx231xx_card_setup(struct cx231xx *dev) /* request some modules */ if (dev->board.decoder == CX231XX_AVDECODER) { cx231xx_info(": Requesting cx25840 module\n"); - request_module("cx25840"); + dev->sd_cx25840 = + v4l2_i2c_new_subdev(&dev->i2c_bus[0].i2c_adap, + "cx25840", "cx25840", 0x88 >> 1); + if (dev->sd_cx25840 == NULL) + cx231xx_info("cx25840 subdev registration failure\n"); + cx25840_call(dev, core, init, 0); + } -#if 0 /* Keep */ + if (dev->board.tuner_type != TUNER_ABSENT) { cx231xx_info(": Requesting Tuner module\n"); - request_module("tuner"); + dev->sd_tuner = + v4l2_i2c_new_subdev(&dev->i2c_bus[1].i2c_adap, + "tuner", "tuner", 0xc2 >> 1); + if (dev->sd_tuner == NULL) + cx231xx_info("tuner subdev registration failure\n"); + + cx231xx_config_tuner(dev); } cx231xx_config_tuner(dev); +#if 0 /* Keep */ /* TBD IR will be added later */ cx231xx_ir_init(dev); #endif @@ -372,7 +381,7 @@ void cx231xx_config_i2c(struct cx231xx *dev) route.input = INPUT(dev->video_input)->vmux; route.output = 0; - cx231xx_i2c_call_clients(&dev->i2c_bus[0], VIDIOC_STREAMON, NULL); + call_all(dev, video, s_stream, 1); } /* @@ -560,7 +569,7 @@ static int cx231xx_usb_probe(struct usb_interface *interface, udev = usb_get_dev(interface_to_usbdev(interface)); ifnum = interface->altsetting[0].desc.bInterfaceNumber; - cx231xx_info(": Interface Number %d\n", ifnum); + printk(DRIVER_NAME ": Interface Number %d\n", ifnum); /* Interface number 0 - IR interface */ if (ifnum == 0) { @@ -700,12 +709,25 @@ static int cx231xx_usb_probe(struct usb_interface *interface, /* AV device initialization */ if ((dev->interface_count - 1) == dev->max_iad_interface_count) { cx231xx_info(" Calling init_dev\n"); + + /* Create v4l2 device */ + snprintf(dev->v4l2_dev.name, sizeof(dev->v4l2_dev.name), + "%s-%03d", "cx231xx", nr); + retval = v4l2_device_register(&udev->dev, &dev->v4l2_dev); + if (retval) { + printk(KERN_ERR "%s() v4l2_device_register failed\n", + __func__); + cx231xx_devused &= ~(1 << nr); + kfree(dev); + return -EIO; + } + /* allocate device struct */ retval = cx231xx_init_dev(&dev, udev, nr); if (retval) { cx231xx_devused &= ~(1 << dev->devno); + v4l2_device_unregister(&dev->v4l2_dev); kfree(dev); - return retval; } @@ -729,6 +751,7 @@ static int cx231xx_usb_probe(struct usb_interface *interface, if (dev->video_mode.alt_max_pkt_size == NULL) { cx231xx_errdev("out of memory!\n"); cx231xx_devused &= ~(1 << nr); + v4l2_device_unregister(&dev->v4l2_dev); kfree(dev); return -ENOMEM; } @@ -763,6 +786,7 @@ static int cx231xx_usb_probe(struct usb_interface *interface, if (dev->vbi_mode.alt_max_pkt_size == NULL) { cx231xx_errdev("out of memory!\n"); cx231xx_devused &= ~(1 << nr); + v4l2_device_unregister(&dev->v4l2_dev); kfree(dev); return -ENOMEM; } @@ -797,6 +821,7 @@ static int cx231xx_usb_probe(struct usb_interface *interface, if (dev->sliced_cc_mode.alt_max_pkt_size == NULL) { cx231xx_errdev("out of memory!\n"); cx231xx_devused &= ~(1 << nr); + v4l2_device_unregister(&dev->v4l2_dev); kfree(dev); return -ENOMEM; } @@ -835,6 +860,7 @@ static int cx231xx_usb_probe(struct usb_interface *interface, if (dev->ts1_mode.alt_max_pkt_size == NULL) { cx231xx_errdev("out of memory!\n"); cx231xx_devused &= ~(1 << nr); + v4l2_device_unregister(&dev->v4l2_dev); kfree(dev); return -ENOMEM; } @@ -887,6 +913,9 @@ static void cx231xx_usb_disconnect(struct usb_interface *interface) if (!dev) return; + /* delete v4l2 device */ + v4l2_device_unregister(&dev->v4l2_dev); + /* wait until all current v4l2 io is finished then deallocate resources */ mutex_lock(&dev->lock); diff --git a/linux/drivers/media/video/cx231xx/cx231xx-i2c.c b/linux/drivers/media/video/cx231xx/cx231xx-i2c.c index 87dbd4e4e..c87203f80 100644 --- a/linux/drivers/media/video/cx231xx/cx231xx-i2c.c +++ b/linux/drivers/media/video/cx231xx/cx231xx-i2c.c @@ -435,18 +435,6 @@ static int attach_inform(struct i2c_client *client) struct cx231xx *dev = bus->dev; switch (client->addr << 1) { - case 0x32: - dprintk1(1, "attach_inform: Geminit III detected.\n"); - break; - case 0x02: - dprintk1(1, "attach_inform: Acquarius detected.\n"); - break; - case 0xa0: - dprintk1(1, "attach_inform: eeprom detected.\n"); - break; - case 0x60: - dprintk1(1, "attach_inform: Colibri detected.\n"); - break; case 0x8e: { struct IR_i2c *ir = i2c_get_clientdata(client); @@ -455,28 +443,15 @@ static int attach_inform(struct i2c_client *client) cx231xx_set_ir(dev, ir); break; } - case 0x80: - case 0x88: - dprintk1(1, "attach_inform: Hammerhead detected.\n"); break; default: - if (!dev->tuner_addr) - dev->tuner_addr = client->addr; - - dprintk1(1, "attach inform: detected I2C address %x\n", - client->addr << 1); + break; } return 0; } -static int detach_inform(struct i2c_client *client) -{ - dprintk1(1, "i2c detach [client=%s]\n", client->name); - return 0; -} - static struct i2c_algorithm cx231xx_algo = { .master_xfer = cx231xx_i2c_xfer, .functionality = functionality, @@ -487,12 +462,10 @@ static struct i2c_algorithm cx231xx_algo = { static struct i2c_adapter cx231xx_adap_template = { .owner = THIS_MODULE, - .class = I2C_CLASS_TV_ANALOG, .name = "cx231xx", .id = I2C_HW_B_CX231XX, .algo = &cx231xx_algo, .client_register = attach_inform, - .client_unregister = detach_inform, }; static struct i2c_client cx231xx_client_template = { @@ -538,19 +511,6 @@ void cx231xx_do_i2c_scan(struct cx231xx *dev, struct i2c_client *c) cx231xx_info(": Completed Checking for I2C devices.\n"); } -/* - * cx231xx_i2c_call_clients() - * send commands to all attached i2c devices - */ -void cx231xx_i2c_call_clients(struct cx231xx_i2c *bus, unsigned int cmd, - void *arg) -{ - /* struct cx231xx *dev = bus->dev; */ - - BUG_ON(NULL == bus->i2c_adap.algo_data); - i2c_clients_command(&bus->i2c_adap, cmd, arg); -} - /* * cx231xx_i2c_register() * register i2c bus @@ -574,7 +534,7 @@ int cx231xx_i2c_register(struct cx231xx_i2c *bus) bus->i2c_algo.data = bus; bus->i2c_adap.algo_data = bus; - i2c_set_adapdata(&bus->i2c_adap, bus); + i2c_set_adapdata(&bus->i2c_adap, &dev->v4l2_dev); i2c_add_adapter(&bus->i2c_adap); bus->i2c_client.adapter = &bus->i2c_adap; diff --git a/linux/drivers/media/video/cx231xx/cx231xx-vbi.c b/linux/drivers/media/video/cx231xx/cx231xx-vbi.c index 9080d1755..020aa13b8 100644 --- a/linux/drivers/media/video/cx231xx/cx231xx-vbi.c +++ b/linux/drivers/media/video/cx231xx/cx231xx-vbi.c @@ -187,10 +187,6 @@ vbi_buffer_setup(struct videobuf_queue *vq, unsigned int *count, if (*count < CX231XX_MIN_BUF) *count = CX231XX_MIN_BUF; - /* call VBI setup if required */ - /* cx231xx_i2c_call_clients(&dev->i2c_bus[1], VIDIOC_S_FREQUENCY, &f); - */ - return 0; } diff --git a/linux/drivers/media/video/cx231xx/cx231xx-video.c b/linux/drivers/media/video/cx231xx/cx231xx-video.c index 6cb3ae90e..e706d0bcb 100644 --- a/linux/drivers/media/video/cx231xx/cx231xx-video.c +++ b/linux/drivers/media/video/cx231xx/cx231xx-video.c @@ -704,7 +704,7 @@ buffer_setup(struct videobuf_queue *vq, unsigned int *count, unsigned int *size) f.frequency = dev->ctl_freq; f.type = fh->radio ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV; - cx231xx_i2c_call_clients(&dev->i2c_bus[1], VIDIOC_S_FREQUENCY, &f); + call_all(dev, tuner, s_frequency, &f); return 0; } @@ -830,8 +830,7 @@ void video_mux(struct cx231xx *dev, int index) cx231xx_set_video_input_mux(dev, index); - cx231xx_i2c_call_clients(&dev->i2c_bus[0], VIDIOC_INT_S_VIDEO_ROUTING, - &route); + cx25840_call(dev, video, s_routing, &route); cx231xx_set_audio_input(dev, dev->ctl_ainput); @@ -1045,7 +1044,7 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, dev->format = fmt; get_scale(dev, dev->width, dev->height, &dev->hscale, &dev->vscale); - cx231xx_i2c_call_clients(&dev->i2c_bus[0], VIDIOC_S_FMT, f); + call_all(dev, video, s_fmt, f); /* Set the correct alternate setting for this resolution */ cx231xx_resolution_set(dev); @@ -1064,7 +1063,7 @@ static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id * id) return 0; } -static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id * norm) +static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *norm) { struct cx231xx_fh *fh = priv; struct cx231xx *dev = fh->dev; @@ -1090,7 +1089,7 @@ static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id * norm) dev->height = f.fmt.pix.height; get_scale(dev, dev->width, dev->height, &dev->hscale, &dev->vscale); - cx231xx_i2c_call_clients(&dev->i2c_bus[0], VIDIOC_S_STD, &dev->norm); + call_all(dev, tuner, s_std, dev->norm); mutex_unlock(&dev->lock); @@ -1244,7 +1243,7 @@ static int vidioc_queryctrl(struct file *file, void *priv, *qc = cx231xx_ctls[i].v; mutex_lock(&dev->lock); - cx231xx_i2c_call_clients(&dev->i2c_bus[0], VIDIOC_QUERYCTRL, qc); + call_all(dev, core, queryctrl, qc); mutex_unlock(&dev->lock); if (qc->type) @@ -1265,9 +1264,7 @@ static int vidioc_g_ctrl(struct file *file, void *priv, return rc; mutex_lock(&dev->lock); - - cx231xx_i2c_call_clients(&dev->i2c_bus[0], VIDIOC_G_CTRL, ctrl); - + call_all(dev, core, g_ctrl, ctrl); mutex_unlock(&dev->lock); return rc; } @@ -1284,9 +1281,7 @@ static int vidioc_s_ctrl(struct file *file, void *priv, return rc; mutex_lock(&dev->lock); - - cx231xx_i2c_call_clients(&dev->i2c_bus[0], VIDIOC_S_CTRL, ctrl); - + call_all(dev, core, s_ctrl, ctrl); mutex_unlock(&dev->lock); return rc; } @@ -1328,9 +1323,7 @@ static int vidioc_s_tuner(struct file *file, void *priv, struct v4l2_tuner *t) return -EINVAL; #if 0 /* Keep */ mutex_lock(&dev->lock); - - cx231xx_i2c_call_clients(&dev->i2c_bus[1], VIDIOC_S_TUNER, t); - + call_all(dev, tuner, s_tuner, t); mutex_unlock(&dev->lock); #endif return 0; @@ -1346,7 +1339,7 @@ static int vidioc_g_frequency(struct file *file, void *priv, f->type = fh->radio ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV; f->frequency = dev->ctl_freq; - cx231xx_i2c_call_clients(&dev->i2c_bus[1], VIDIOC_G_FREQUENCY, f); + call_all(dev, tuner, g_frequency, f); mutex_unlock(&dev->lock); @@ -1382,10 +1375,8 @@ static int vidioc_s_frequency(struct file *file, void *priv, if (dev->tuner_type == TUNER_XC5000) { if (dev->cx231xx_set_analog_freq != NULL) dev->cx231xx_set_analog_freq(dev, f->frequency); - } else { - cx231xx_i2c_call_clients(&dev->i2c_bus[1], - VIDIOC_S_FREQUENCY, f); - } + } else + call_all(dev, tuner, s_frequency, f); mutex_unlock(&dev->lock); @@ -1467,8 +1458,7 @@ static int vidioc_g_register(struct file *file, void *priv, return ret < 0 ? ret : 0; case V4L2_CHIP_MATCH_I2C_DRIVER: - cx231xx_i2c_call_clients(&dev->i2c_bus[0], - VIDIOC_DBG_G_REGISTER, reg); + call_all(dev, core, g_register, reg); return 0; case V4L2_CHIP_MATCH_I2C_ADDR: /* Not supported yet */ @@ -1479,7 +1469,7 @@ static int vidioc_g_register(struct file *file, void *priv, } mutex_lock(&dev->lock); - cx231xx_i2c_call_clients(&dev->i2c_bus[0], VIDIOC_DBG_G_REGISTER, reg); + call_all(dev, core, g_register, reg); mutex_unlock(&dev->lock); return ret; @@ -1562,9 +1552,7 @@ static int vidioc_s_register(struct file *file, void *priv, } mutex_lock(&dev->lock); - - cx231xx_i2c_call_clients(&dev->i2c_bus[0], VIDIOC_DBG_S_REGISTER, reg); - + call_all(dev, core, s_register, reg); mutex_unlock(&dev->lock); return ret; @@ -1608,6 +1596,8 @@ static int vidioc_streamon(struct file *file, void *priv, if (likely(rc >= 0)) rc = videobuf_streamon(&fh->vb_vidq); + call_all(dev, video, s_stream, 1); + mutex_unlock(&dev->lock); return rc; @@ -1632,6 +1622,8 @@ static int vidioc_streamoff(struct file *file, void *priv, mutex_lock(&dev->lock); + cx25840_call(dev, video, s_stream, 0); + videobuf_streamoff(&fh->vb_vidq); res_free(fh); @@ -1648,7 +1640,7 @@ static int vidioc_querycap(struct file *file, void *priv, strlcpy(cap->driver, "cx231xx", sizeof(cap->driver)); strlcpy(cap->card, cx231xx_boards[dev->model].name, sizeof(cap->card)); - strlcpy(cap->bus_info, dev_name(&dev->udev->dev), + strlcpy(cap->bus_info, dev->v4l2_dev.name, sizeof(cap->bus_info)); cap->version = CX231XX_VERSION_CODE; @@ -1696,7 +1688,7 @@ static int vidioc_g_fmt_sliced_vbi_cap(struct file *file, void *priv, f->fmt.sliced.service_set = 0; - cx231xx_i2c_call_clients(&dev->i2c_bus[0], VIDIOC_G_FMT, f); + call_all(dev, video, g_fmt, f); if (f->fmt.sliced.service_set == 0) rc = -EINVAL; @@ -1717,7 +1709,7 @@ static int vidioc_try_set_sliced_vbi_cap(struct file *file, void *priv, return rc; mutex_lock(&dev->lock); - cx231xx_i2c_call_clients(&dev->i2c_bus[0], VIDIOC_G_FMT, f); + call_all(dev, video, g_fmt, f); mutex_unlock(&dev->lock); if (f->fmt.sliced.service_set == 0) @@ -1872,7 +1864,7 @@ static int radio_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t) t->type = V4L2_TUNER_RADIO; mutex_lock(&dev->lock); - cx231xx_i2c_call_clients(&dev->i2c_bus[1], VIDIOC_G_TUNER, t); + call_all(dev, tuner, s_tuner, t); mutex_unlock(&dev->lock); return 0; @@ -1905,7 +1897,7 @@ static int radio_s_tuner(struct file *file, void *priv, struct v4l2_tuner *t) return -EINVAL; mutex_lock(&dev->lock); - cx231xx_i2c_call_clients(&dev->i2c_bus[1], VIDIOC_S_TUNER, t); + call_all(dev, tuner, s_tuner, t); mutex_unlock(&dev->lock); return 0; @@ -2011,8 +2003,7 @@ static int cx231xx_v4l2_open(struct file *filp) /* cx231xx_start_radio(dev); */ - cx231xx_i2c_call_clients(&dev->i2c_bus[1], AUDC_SET_RADIO, - NULL); + call_all(dev, tuner, s_radio); } dev->users++; @@ -2135,8 +2126,7 @@ static int cx231xx_v4l2_close(struct file *filp) } /* Save some power by putting tuner to sleep */ - cx231xx_i2c_call_clients(&dev->i2c_bus[1], TUNER_SET_STANDBY, - NULL); + call_all(dev, core, s_standby, 0); /* do this before setting alternate! */ cx231xx_uninit_isoc(dev); @@ -2350,7 +2340,7 @@ static struct video_device *cx231xx_vdev_init(struct cx231xx *dev, *vfd = *template; vfd->minor = -1; - vfd->parent = &dev->udev->dev; + vfd->v4l2_dev = &dev->v4l2_dev; vfd->release = video_device_release; vfd->debug = video_debug; diff --git a/linux/drivers/media/video/cx231xx/cx231xx.h b/linux/drivers/media/video/cx231xx/cx231xx.h index 8ab6c615e..8a86b3227 100644 --- a/linux/drivers/media/video/cx231xx/cx231xx.h +++ b/linux/drivers/media/video/cx231xx/cx231xx.h @@ -22,13 +22,17 @@ #ifndef _CX231XX_H #define _CX231XX_H -#include "compat.h" #include -#include - +#include +#include #include #include #include + +#include "compat.h" + +#include +#include #include #if defined(CONFIG_VIDEO_CX231XX_DVB) || \ defined(CONFIG_VIDEO_CX231XX_DVB_MODULE) @@ -456,6 +460,10 @@ struct cx231xx { struct cx231xx_fmt *format; + struct v4l2_device v4l2_dev; + struct v4l2_subdev *sd_cx25840; + struct v4l2_subdev *sd_tuner; + struct cx231xx_IR *ir; struct list_head devlist; @@ -553,6 +561,13 @@ struct cx231xx { }; +#define cx25840_call(cx231xx, o, f, args...) \ + v4l2_subdev_call(cx231xx->sd_cx25840, o, f, ##args) +#define tuner_call(cx231xx, o, f, args...) \ + v4l2_subdev_call(cx231xx->sd_tuner, o, f, ##args) +#define call_all(dev, o, f, args...) \ + v4l2_device_call_until_err(&dev->v4l2_dev, 0, o, f, ##args) + struct cx231xx_ops { struct list_head next; char *name; @@ -566,8 +581,6 @@ int cx231xx_set_analog_freq(struct cx231xx *dev, u32 freq); int cx231xx_reset_analog_tuner(struct cx231xx *dev); /* Provided by cx231xx-i2c.c */ -void cx231xx_i2c_call_clients(struct cx231xx_i2c *bus, unsigned int cmd, - void *arg); void cx231xx_do_i2c_scan(struct cx231xx *dev, struct i2c_client *c); int cx231xx_i2c_register(struct cx231xx_i2c *bus); int cx231xx_i2c_unregister(struct cx231xx_i2c *bus); -- cgit v1.2.3 From abd67a8824bedd0562212ae4c205722d08ace135 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 21 Mar 2009 22:00:20 -0300 Subject: cx231xx: Use generic names for each device block From: Sri Deevi Priority: normal Signed-off-by: Srinivasa Deevi Reviewed-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/cx231xx/cx231xx-avcore.c | 1171 ++++++++------------ linux/drivers/media/video/cx231xx/cx231xx-core.c | 16 +- .../drivers/media/video/cx231xx/cx231xx-pcb-cfg.h | 8 +- linux/drivers/media/video/cx231xx/cx231xx-video.c | 48 +- linux/drivers/media/video/cx231xx/cx231xx.h | 36 +- 5 files changed, 538 insertions(+), 741 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/cx231xx/cx231xx-avcore.c b/linux/drivers/media/video/cx231xx/cx231xx-avcore.c index 226299d62..1be3881be 100644 --- a/linux/drivers/media/video/cx231xx/cx231xx-avcore.c +++ b/linux/drivers/media/video/cx231xx/cx231xx-avcore.c @@ -40,54 +40,77 @@ #include "cx231xx.h" /****************************************************************************** - * C O L I B R I - B L O C K C O N T R O L functions * + -: BLOCK ARRANGEMENT :- + I2S block ----------------------| + [I2S audio] | + | + Analog Front End --> Direct IF -|-> Cx25840 --> Audio + [video & audio] | [Audio] + | + |-> Cx25840 --> Video + [Video] + +*******************************************************************************/ + +/****************************************************************************** + * A F E - B L O C K C O N T R O L functions * + * [ANALOG FRONT END] * ******************************************************************************/ -int cx231xx_colibri_init_super_block(struct cx231xx *dev, u32 ref_count) +static int afe_write_byte(struct cx231xx *dev, u16 saddr, u8 data) +{ + return cx231xx_write_i2c_data(dev, AFE_DEVICE_ADDRESS, + saddr, 2, data, 1); +} + +static int afe_read_byte(struct cx231xx *dev, u16 saddr, u8 *data) +{ + int status; + u32 temp = 0; + + status = cx231xx_read_i2c_data(dev, AFE_DEVICE_ADDRESS, + saddr, 2, &temp, 1); + *data = (u8) temp; + return status; +} + +int cx231xx_afe_init_super_block(struct cx231xx *dev, u32 ref_count) { int status = 0; u8 temp = 0; - u32 colibri_power_status = 0; + u8 afe_power_status = 0; int i = 0; /* super block initialize */ temp = (u8) (ref_count & 0xff); - status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, - SUP_BLK_TUNE2, 2, temp, 1); + status = afe_write_byte(dev, SUP_BLK_TUNE2, temp); if (status < 0) return status; - status = cx231xx_read_i2c_data(dev, Colibri_DEVICE_ADDRESS, - SUP_BLK_TUNE2, 2, - &colibri_power_status, 1); + status = afe_read_byte(dev, SUP_BLK_TUNE2, &afe_power_status); if (status < 0) return status; temp = (u8) ((ref_count & 0x300) >> 8); temp |= 0x40; - status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, - SUP_BLK_TUNE1, 2, temp, 1); + status = afe_write_byte(dev, SUP_BLK_TUNE1, temp); if (status < 0) return status; - status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, - SUP_BLK_PLL2, 2, 0x0f, 1); + status = afe_write_byte(dev, SUP_BLK_PLL2, 0x0f); if (status < 0) return status; /* enable pll */ - while (colibri_power_status != 0x18) { - status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, - SUP_BLK_PWRDN, 2, 0x18, 1); + while (afe_power_status != 0x18) { + status = afe_write_byte(dev, SUP_BLK_PWRDN, 0x18); if (status < 0) { cx231xx_info( ": Init Super Block failed in send cmd\n"); break; } - status = cx231xx_read_i2c_data(dev, Colibri_DEVICE_ADDRESS, - SUP_BLK_PWRDN, 2, - &colibri_power_status, 1); - colibri_power_status &= 0xff; + status = afe_read_byte(dev, SUP_BLK_PWRDN, &afe_power_status); + afe_power_status &= 0xff; if (status < 0) { cx231xx_info( ": Init Super Block failed in receive cmd\n"); @@ -106,101 +129,75 @@ int cx231xx_colibri_init_super_block(struct cx231xx *dev, u32 ref_count) return status; /* start tuning filter */ - status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, - SUP_BLK_TUNE3, 2, 0x40, 1); + status = afe_write_byte(dev, SUP_BLK_TUNE3, 0x40); if (status < 0) return status; msleep(5); /* exit tuning */ - status = - cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, SUP_BLK_TUNE3, - 2, 0x00, 1); + status = afe_write_byte(dev, SUP_BLK_TUNE3, 0x00); return status; } -int cx231xx_colibri_init_channels(struct cx231xx *dev) +int cx231xx_afe_init_channels(struct cx231xx *dev) { int status = 0; /* power up all 3 channels, clear pd_buffer */ - status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, - ADC_PWRDN_CLAMP_CH1, 2, 0x00, 1); - status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, - ADC_PWRDN_CLAMP_CH2, 2, 0x00, 1); - status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, - ADC_PWRDN_CLAMP_CH3, 2, 0x00, 1); + status = afe_write_byte(dev, ADC_PWRDN_CLAMP_CH1, 0x00); + status = afe_write_byte(dev, ADC_PWRDN_CLAMP_CH2, 0x00); + status = afe_write_byte(dev, ADC_PWRDN_CLAMP_CH3, 0x00); /* Enable quantizer calibration */ - status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, - ADC_COM_QUANT, 2, 0x02, 1); + status = afe_write_byte(dev, ADC_COM_QUANT, 0x02); /* channel initialize, force modulator (fb) reset */ - status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, - ADC_FB_FRCRST_CH1, 2, 0x17, 1); - status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, - ADC_FB_FRCRST_CH2, 2, 0x17, 1); - status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, - ADC_FB_FRCRST_CH3, 2, 0x17, 1); + status = afe_write_byte(dev, ADC_FB_FRCRST_CH1, 0x17); + status = afe_write_byte(dev, ADC_FB_FRCRST_CH2, 0x17); + status = afe_write_byte(dev, ADC_FB_FRCRST_CH3, 0x17); /* start quantilizer calibration */ - status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, - ADC_CAL_ATEST_CH1, 2, 0x10, 1); - status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, - ADC_CAL_ATEST_CH2, 2, 0x10, 1); - status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, - ADC_CAL_ATEST_CH3, 2, 0x10, 1); + status = afe_write_byte(dev, ADC_CAL_ATEST_CH1, 0x10); + status = afe_write_byte(dev, ADC_CAL_ATEST_CH2, 0x10); + status = afe_write_byte(dev, ADC_CAL_ATEST_CH3, 0x10); msleep(5); /* exit modulator (fb) reset */ - status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, - ADC_FB_FRCRST_CH1, 2, 0x07, 1); - status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, - ADC_FB_FRCRST_CH2, 2, 0x07, 1); - status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, - ADC_FB_FRCRST_CH3, 2, 0x07, 1); + status = afe_write_byte(dev, ADC_FB_FRCRST_CH1, 0x07); + status = afe_write_byte(dev, ADC_FB_FRCRST_CH2, 0x07); + status = afe_write_byte(dev, ADC_FB_FRCRST_CH3, 0x07); /* enable the pre_clamp in each channel for single-ended input */ - status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, - ADC_NTF_PRECLMP_EN_CH1, 2, 0xf0, 1); - status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, - ADC_NTF_PRECLMP_EN_CH2, 2, 0xf0, 1); - status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, - ADC_NTF_PRECLMP_EN_CH3, 2, 0xf0, 1); + status = afe_write_byte(dev, ADC_NTF_PRECLMP_EN_CH1, 0xf0); + status = afe_write_byte(dev, ADC_NTF_PRECLMP_EN_CH2, 0xf0); + status = afe_write_byte(dev, ADC_NTF_PRECLMP_EN_CH3, 0xf0); /* use diode instead of resistor, so set term_en to 0, res_en to 0 */ - status = cx231xx_reg_mask_write(dev, Colibri_DEVICE_ADDRESS, 8, + status = cx231xx_reg_mask_write(dev, AFE_DEVICE_ADDRESS, 8, ADC_QGAIN_RES_TRM_CH1, 3, 7, 0x00); - status = cx231xx_reg_mask_write(dev, Colibri_DEVICE_ADDRESS, 8, + status = cx231xx_reg_mask_write(dev, AFE_DEVICE_ADDRESS, 8, ADC_QGAIN_RES_TRM_CH2, 3, 7, 0x00); - status = cx231xx_reg_mask_write(dev, Colibri_DEVICE_ADDRESS, 8, + status = cx231xx_reg_mask_write(dev, AFE_DEVICE_ADDRESS, 8, ADC_QGAIN_RES_TRM_CH3, 3, 7, 0x00); /* dynamic element matching off */ - status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, - ADC_DCSERVO_DEM_CH1, 2, 0x03, 1); - status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, - ADC_DCSERVO_DEM_CH2, 2, 0x03, 1); - status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, - ADC_DCSERVO_DEM_CH3, 2, 0x03, 1); + status = afe_write_byte(dev, ADC_DCSERVO_DEM_CH1, 0x03); + status = afe_write_byte(dev, ADC_DCSERVO_DEM_CH2, 0x03); + status = afe_write_byte(dev, ADC_DCSERVO_DEM_CH3, 0x03); return status; } -int cx231xx_colibri_setup_AFE_for_baseband(struct cx231xx *dev) +int cx231xx_afe_setup_AFE_for_baseband(struct cx231xx *dev) { - u32 c_value = 0; + u8 c_value = 0; int status = 0; - status = - cx231xx_read_i2c_data(dev, Colibri_DEVICE_ADDRESS, - ADC_PWRDN_CLAMP_CH2, 2, &c_value, 1); + status = afe_read_byte(dev, ADC_PWRDN_CLAMP_CH2, &c_value); c_value &= (~(0x50)); - status = - cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, - ADC_PWRDN_CLAMP_CH2, 2, c_value, 1); + status = afe_write_byte(dev, ADC_PWRDN_CLAMP_CH2, c_value); return status; } @@ -214,52 +211,44 @@ int cx231xx_colibri_setup_AFE_for_baseband(struct cx231xx *dev) channel 2 ----- pin 5 to pin8(in reg is 5-8) channel 3 ----- pin 9 to pin 12(in reg is 9-11) */ -int cx231xx_colibri_set_input_mux(struct cx231xx *dev, u32 input_mux) +int cx231xx_afe_set_input_mux(struct cx231xx *dev, u32 input_mux) { u8 ch1_setting = (u8) input_mux; u8 ch2_setting = (u8) (input_mux >> 8); u8 ch3_setting = (u8) (input_mux >> 16); int status = 0; - u32 value = 0; + u8 value = 0; if (ch1_setting != 0) { - status = - cx231xx_read_i2c_data(dev, Colibri_DEVICE_ADDRESS, - ADC_INPUT_CH1, 2, &value, 1); + status = afe_read_byte(dev, ADC_INPUT_CH1, &value); value &= (!INPUT_SEL_MASK); value |= (ch1_setting - 1) << 4; value &= 0xff; - status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, - ADC_INPUT_CH1, 2, value, 1); + status = afe_write_byte(dev, ADC_INPUT_CH1, value); } if (ch2_setting != 0) { - status = - cx231xx_read_i2c_data(dev, Colibri_DEVICE_ADDRESS, - ADC_INPUT_CH2, 2, &value, 1); + status = afe_read_byte(dev, ADC_INPUT_CH2, &value); value &= (!INPUT_SEL_MASK); value |= (ch2_setting - 1) << 4; value &= 0xff; - status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, - ADC_INPUT_CH2, 2, value, 1); + status = afe_write_byte(dev, ADC_INPUT_CH2, value); } /* For ch3_setting, the value to put in the register is 7 less than the input number */ if (ch3_setting != 0) { - status = cx231xx_read_i2c_data(dev, Colibri_DEVICE_ADDRESS, - ADC_INPUT_CH3, 2, &value, 1); + status = afe_read_byte(dev, ADC_INPUT_CH3, &value); value &= (!INPUT_SEL_MASK); value |= (ch3_setting - 1) << 4; value &= 0xff; - status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, - ADC_INPUT_CH3, 2, value, 1); + status = afe_write_byte(dev, ADC_INPUT_CH3, value); } return status; } -int cx231xx_colibri_set_mode(struct cx231xx *dev, enum AFE_MODE mode) +int cx231xx_afe_set_mode(struct cx231xx *dev, enum AFE_MODE mode) { int status = 0; @@ -273,7 +262,7 @@ int cx231xx_colibri_set_mode(struct cx231xx *dev, enum AFE_MODE mode) /* SetupAFEforLowIF(); */ break; case AFE_MODE_BASEBAND: - status = cx231xx_colibri_setup_AFE_for_baseband(dev); + status = cx231xx_afe_setup_AFE_for_baseband(dev); break; case AFE_MODE_EU_HI_IF: /* SetupAFEforEuHiIF(); */ @@ -286,110 +275,76 @@ int cx231xx_colibri_set_mode(struct cx231xx *dev, enum AFE_MODE mode) break; } - if ((mode != dev->colibri_mode) && + if ((mode != dev->afe_mode) && (dev->video_input == CX231XX_VMUX_TELEVISION)) - status = cx231xx_colibri_adjust_ref_count(dev, + status = cx231xx_afe_adjust_ref_count(dev, CX231XX_VMUX_TELEVISION); - dev->colibri_mode = mode; + dev->afe_mode = mode; return status; } -int cx231xx_colibri_update_power_control(struct cx231xx *dev, +int cx231xx_afe_update_power_control(struct cx231xx *dev, enum AV_MODE avmode) { - u32 colibri_power_status = 0; + u8 afe_power_status = 0; int status = 0; switch (dev->model) { case CX231XX_BOARD_CNXT_RDE_250: case CX231XX_BOARD_CNXT_RDU_250: if (avmode == POLARIS_AVMODE_ANALOGT_TV) { - while (colibri_power_status != (FLD_PWRDN_TUNING_BIAS | + while (afe_power_status != (FLD_PWRDN_TUNING_BIAS | FLD_PWRDN_ENABLE_PLL)) { - status = cx231xx_write_i2c_data(dev, - Colibri_DEVICE_ADDRESS, - SUP_BLK_PWRDN, 2, + status = afe_write_byte(dev, SUP_BLK_PWRDN, FLD_PWRDN_TUNING_BIAS | - FLD_PWRDN_ENABLE_PLL, - 1); - status |= cx231xx_read_i2c_data(dev, - Colibri_DEVICE_ADDRESS, - SUP_BLK_PWRDN, 2, - &colibri_power_status, - 1); + FLD_PWRDN_ENABLE_PLL); + status |= afe_read_byte(dev, SUP_BLK_PWRDN, + &afe_power_status); if (status < 0) break; } - status = cx231xx_write_i2c_data(dev, - Colibri_DEVICE_ADDRESS, - ADC_PWRDN_CLAMP_CH1, 2, 0x00, - 1); - status |= cx231xx_write_i2c_data(dev, - Colibri_DEVICE_ADDRESS, - ADC_PWRDN_CLAMP_CH2, 2, 0x00, - 1); - status |= cx231xx_write_i2c_data(dev, - Colibri_DEVICE_ADDRESS, - ADC_PWRDN_CLAMP_CH3, 2, 0x00, - 1); + status = afe_write_byte(dev, ADC_PWRDN_CLAMP_CH1, + 0x00); + status |= afe_write_byte(dev, ADC_PWRDN_CLAMP_CH2, + 0x00); + status |= afe_write_byte(dev, ADC_PWRDN_CLAMP_CH3, + 0x00); } else if (avmode == POLARIS_AVMODE_DIGITAL) { - status = cx231xx_write_i2c_data(dev, - Colibri_DEVICE_ADDRESS, - ADC_PWRDN_CLAMP_CH1, 2, 0x70, - 1); - status |= cx231xx_write_i2c_data(dev, - Colibri_DEVICE_ADDRESS, - ADC_PWRDN_CLAMP_CH2, 2, 0x70, - 1); - status |= cx231xx_write_i2c_data(dev, - Colibri_DEVICE_ADDRESS, - ADC_PWRDN_CLAMP_CH3, 2, 0x70, - 1); - - status |= cx231xx_read_i2c_data(dev, - Colibri_DEVICE_ADDRESS, - SUP_BLK_PWRDN, 2, - &colibri_power_status, 1); - colibri_power_status |= FLD_PWRDN_PD_BANDGAP | + status = afe_write_byte(dev, ADC_PWRDN_CLAMP_CH1, + 0x70); + status |= afe_write_byte(dev, ADC_PWRDN_CLAMP_CH2, + 0x70); + status |= afe_write_byte(dev, ADC_PWRDN_CLAMP_CH3, + 0x70); + + status |= afe_read_byte(dev, SUP_BLK_PWRDN, + &afe_power_status); + afe_power_status |= FLD_PWRDN_PD_BANDGAP | FLD_PWRDN_PD_BIAS | FLD_PWRDN_PD_TUNECK; - status |= cx231xx_write_i2c_data(dev, - Colibri_DEVICE_ADDRESS, - SUP_BLK_PWRDN, 2, - colibri_power_status, 1); + status |= afe_write_byte(dev, SUP_BLK_PWRDN, + afe_power_status); } else if (avmode == POLARIS_AVMODE_ENXTERNAL_AV) { - while (colibri_power_status != (FLD_PWRDN_TUNING_BIAS | + while (afe_power_status != (FLD_PWRDN_TUNING_BIAS | FLD_PWRDN_ENABLE_PLL)) { - status = cx231xx_write_i2c_data(dev, - Colibri_DEVICE_ADDRESS, - SUP_BLK_PWRDN, 2, + status = afe_write_byte(dev, SUP_BLK_PWRDN, FLD_PWRDN_TUNING_BIAS | - FLD_PWRDN_ENABLE_PLL, - 1); - status |= cx231xx_read_i2c_data(dev, - Colibri_DEVICE_ADDRESS, - SUP_BLK_PWRDN, 2, - &colibri_power_status, - 1); + FLD_PWRDN_ENABLE_PLL); + status |= afe_read_byte(dev, SUP_BLK_PWRDN, + &afe_power_status); if (status < 0) break; } - status |= cx231xx_write_i2c_data(dev, - Colibri_DEVICE_ADDRESS, - ADC_PWRDN_CLAMP_CH1, 2, 0x00, - 1); - status |= cx231xx_write_i2c_data(dev, - Colibri_DEVICE_ADDRESS, - ADC_PWRDN_CLAMP_CH2, 2, 0x00, - 1); - status |= cx231xx_write_i2c_data(dev, - Colibri_DEVICE_ADDRESS, - ADC_PWRDN_CLAMP_CH3, 2, 0x00, - 1); + status |= afe_write_byte(dev, ADC_PWRDN_CLAMP_CH1, + 0x00); + status |= afe_write_byte(dev, ADC_PWRDN_CLAMP_CH2, + 0x00); + status |= afe_write_byte(dev, ADC_PWRDN_CLAMP_CH3, + 0x00); } else { cx231xx_info("Invalid AV mode input\n"); status = -1; @@ -397,92 +352,56 @@ int cx231xx_colibri_update_power_control(struct cx231xx *dev, break; default: if (avmode == POLARIS_AVMODE_ANALOGT_TV) { - while (colibri_power_status != (FLD_PWRDN_TUNING_BIAS | + while (afe_power_status != (FLD_PWRDN_TUNING_BIAS | FLD_PWRDN_ENABLE_PLL)) { - status = cx231xx_write_i2c_data(dev, - Colibri_DEVICE_ADDRESS, - SUP_BLK_PWRDN, 2, + status = afe_write_byte(dev, SUP_BLK_PWRDN, FLD_PWRDN_TUNING_BIAS | - FLD_PWRDN_ENABLE_PLL, - 1); - status |= cx231xx_read_i2c_data(dev, - Colibri_DEVICE_ADDRESS, - SUP_BLK_PWRDN, 2, - &colibri_power_status, - 1); + FLD_PWRDN_ENABLE_PLL); + status |= afe_read_byte(dev, SUP_BLK_PWRDN, + &afe_power_status); if (status < 0) break; } - status |= cx231xx_write_i2c_data(dev, - Colibri_DEVICE_ADDRESS, - ADC_PWRDN_CLAMP_CH1, 2, - 0x40, 1); - status |= cx231xx_write_i2c_data(dev, - Colibri_DEVICE_ADDRESS, - ADC_PWRDN_CLAMP_CH2, 2, - 0x40, 1); - status |= cx231xx_write_i2c_data(dev, - Colibri_DEVICE_ADDRESS, - ADC_PWRDN_CLAMP_CH3, 2, - 0x00, 1); + status |= afe_write_byte(dev, ADC_PWRDN_CLAMP_CH1, + 0x40); + status |= afe_write_byte(dev, ADC_PWRDN_CLAMP_CH2, + 0x40); + status |= afe_write_byte(dev, ADC_PWRDN_CLAMP_CH3, + 0x00); } else if (avmode == POLARIS_AVMODE_DIGITAL) { - status = cx231xx_write_i2c_data(dev, - Colibri_DEVICE_ADDRESS, - ADC_PWRDN_CLAMP_CH1, 2, - 0x70, 1); - status |= cx231xx_write_i2c_data(dev, - Colibri_DEVICE_ADDRESS, - ADC_PWRDN_CLAMP_CH2, 2, - 0x70, 1); - status |= cx231xx_write_i2c_data(dev, - Colibri_DEVICE_ADDRESS, - ADC_PWRDN_CLAMP_CH3, 2, - 0x70, 1); - - status |= cx231xx_read_i2c_data(dev, - Colibri_DEVICE_ADDRESS, - SUP_BLK_PWRDN, 2, - &colibri_power_status, - 1); - colibri_power_status |= FLD_PWRDN_PD_BANDGAP | + status = afe_write_byte(dev, ADC_PWRDN_CLAMP_CH1, + 0x70); + status |= afe_write_byte(dev, ADC_PWRDN_CLAMP_CH2, + 0x70); + status |= afe_write_byte(dev, ADC_PWRDN_CLAMP_CH3, + 0x70); + + status |= afe_read_byte(dev, SUP_BLK_PWRDN, + &afe_power_status); + afe_power_status |= FLD_PWRDN_PD_BANDGAP | FLD_PWRDN_PD_BIAS | FLD_PWRDN_PD_TUNECK; - status |= cx231xx_write_i2c_data(dev, - Colibri_DEVICE_ADDRESS, - SUP_BLK_PWRDN, 2, - colibri_power_status, - 1); + status |= afe_write_byte(dev, SUP_BLK_PWRDN, + afe_power_status); } else if (avmode == POLARIS_AVMODE_ENXTERNAL_AV) { - while (colibri_power_status != (FLD_PWRDN_TUNING_BIAS | + while (afe_power_status != (FLD_PWRDN_TUNING_BIAS | FLD_PWRDN_ENABLE_PLL)) { - status = cx231xx_write_i2c_data(dev, - Colibri_DEVICE_ADDRESS, - SUP_BLK_PWRDN, 2, + status = afe_write_byte(dev, SUP_BLK_PWRDN, FLD_PWRDN_TUNING_BIAS | - FLD_PWRDN_ENABLE_PLL, - 1); - status |= cx231xx_read_i2c_data(dev, - Colibri_DEVICE_ADDRESS, - SUP_BLK_PWRDN, 2, - &colibri_power_status, - 1); + FLD_PWRDN_ENABLE_PLL); + status |= afe_read_byte(dev, SUP_BLK_PWRDN, + &afe_power_status); if (status < 0) break; } - status |= cx231xx_write_i2c_data(dev, - Colibri_DEVICE_ADDRESS, - ADC_PWRDN_CLAMP_CH1, 2, - 0x00, 1); - status |= cx231xx_write_i2c_data(dev, - Colibri_DEVICE_ADDRESS, - ADC_PWRDN_CLAMP_CH2, 2, - 0x00, 1); - status |= cx231xx_write_i2c_data(dev, - Colibri_DEVICE_ADDRESS, - ADC_PWRDN_CLAMP_CH3, 2, - 0x40, 1); + status |= afe_write_byte(dev, ADC_PWRDN_CLAMP_CH1, + 0x00); + status |= afe_write_byte(dev, ADC_PWRDN_CLAMP_CH2, + 0x00); + status |= afe_write_byte(dev, ADC_PWRDN_CLAMP_CH3, + 0x40); } else { cx231xx_info("Invalid AV mode input\n"); status = -1; @@ -492,48 +411,44 @@ int cx231xx_colibri_update_power_control(struct cx231xx *dev, return status; } -int cx231xx_colibri_adjust_ref_count(struct cx231xx *dev, u32 video_input) +int cx231xx_afe_adjust_ref_count(struct cx231xx *dev, u32 video_input) { - u32 input_mode = 0; - u32 ntf_mode = 0; + u8 input_mode = 0; + u8 ntf_mode = 0; int status = 0; dev->video_input = video_input; if (video_input == CX231XX_VMUX_TELEVISION) { - status = cx231xx_read_i2c_data(dev, Colibri_DEVICE_ADDRESS, - ADC_INPUT_CH3, 2, &input_mode, 1); - status = cx231xx_read_i2c_data(dev, Colibri_DEVICE_ADDRESS, - ADC_NTF_PRECLMP_EN_CH3, 2, &ntf_mode, - 1); + status = afe_read_byte(dev, ADC_INPUT_CH3, &input_mode); + status = afe_read_byte(dev, ADC_NTF_PRECLMP_EN_CH3, + &ntf_mode); } else { - status = cx231xx_read_i2c_data(dev, Colibri_DEVICE_ADDRESS, - ADC_INPUT_CH1, 2, &input_mode, 1); - status = cx231xx_read_i2c_data(dev, Colibri_DEVICE_ADDRESS, - ADC_NTF_PRECLMP_EN_CH1, 2, &ntf_mode, - 1); + status = afe_read_byte(dev, ADC_INPUT_CH1, &input_mode); + status = afe_read_byte(dev, ADC_NTF_PRECLMP_EN_CH1, + &ntf_mode); } input_mode = (ntf_mode & 0x3) | ((input_mode & 0x6) << 1); switch (input_mode) { case SINGLE_ENDED: - dev->colibri_ref_count = 0x23C; + dev->afe_ref_count = 0x23C; break; case LOW_IF: - dev->colibri_ref_count = 0x24C; + dev->afe_ref_count = 0x24C; break; case EU_IF: - dev->colibri_ref_count = 0x258; + dev->afe_ref_count = 0x258; break; case US_IF: - dev->colibri_ref_count = 0x260; + dev->afe_ref_count = 0x260; break; default: break; } - status = cx231xx_colibri_init_super_block(dev, dev->colibri_ref_count); + status = cx231xx_afe_init_super_block(dev, dev->afe_ref_count); return status; } @@ -541,6 +456,35 @@ int cx231xx_colibri_adjust_ref_count(struct cx231xx *dev, u32 video_input) /****************************************************************************** * V I D E O / A U D I O D E C O D E R C O N T R O L functions * ******************************************************************************/ +static int vid_blk_write_byte(struct cx231xx *dev, u16 saddr, u8 data) +{ + return cx231xx_write_i2c_data(dev, VID_BLK_I2C_ADDRESS, + saddr, 2, data, 1); +} + +static int vid_blk_read_byte(struct cx231xx *dev, u16 saddr, u8 *data) +{ + int status; + u32 temp = 0; + + status = cx231xx_read_i2c_data(dev, VID_BLK_I2C_ADDRESS, + saddr, 2, &temp, 1); + *data = (u8) temp; + return status; +} + +static int vid_blk_write_word(struct cx231xx *dev, u16 saddr, u32 data) +{ + return cx231xx_write_i2c_data(dev, VID_BLK_I2C_ADDRESS, + saddr, 2, data, 4); +} + +static int vid_blk_read_word(struct cx231xx *dev, u16 saddr, u32 *data) +{ + return cx231xx_read_i2c_data(dev, VID_BLK_I2C_ADDRESS, + saddr, 2, data, 4); +} + int cx231xx_set_video_input_mux(struct cx231xx *dev, u8 input) { int status = 0; @@ -601,29 +545,27 @@ int cx231xx_set_decoder_video_input(struct cx231xx *dev, u32 value = 0; if (pin_type != dev->video_input) { - status = cx231xx_colibri_adjust_ref_count(dev, pin_type); + status = cx231xx_afe_adjust_ref_count(dev, pin_type); if (status < 0) { cx231xx_errdev("%s: adjust_ref_count :Failed to set" - "Colibri input mux - errCode [%d]!\n", + "AFE input mux - errCode [%d]!\n", __func__, status); return status; } } - /* call colibri block to set video inputs */ - status = cx231xx_colibri_set_input_mux(dev, input); + /* call afe block to set video inputs */ + status = cx231xx_afe_set_input_mux(dev, input); if (status < 0) { cx231xx_errdev("%s: set_input_mux :Failed to set" - " Colibri input mux - errCode [%d]!\n", + " AFE input mux - errCode [%d]!\n", __func__, status); return status; } switch (pin_type) { case CX231XX_VMUX_COMPOSITE1: - status = cx231xx_read_i2c_data(dev, - HAMMERHEAD_I2C_ADDRESS, - AFE_CTRL, 2, &value, 4); + status = vid_blk_read_word(dev, AFE_CTRL, &value); value |= (0 << 13) | (1 << 4); value &= ~(1 << 5); @@ -631,18 +573,15 @@ int cx231xx_set_decoder_video_input(struct cx231xx *dev, value &= (~(0x1ff8000)); /* set FUNC_MODE[24:23] = 2 IF_MOD[22:15] = 0 */ value |= 0x1000000; - status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, - AFE_CTRL, 2, value, 4); + status = vid_blk_write_word(dev, AFE_CTRL, value); - status = cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, - OUT_CTRL1, 2, &value, 4); + status = vid_blk_read_word(dev, OUT_CTRL1, &value); value |= (1 << 7); - status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, - OUT_CTRL1, 2, value, 4); + status = vid_blk_write_word(dev, OUT_CTRL1, value); /* Set vip 1.1 output mode */ status = cx231xx_read_modify_write_i2c_dword(dev, - HAMMERHEAD_I2C_ADDRESS, + VID_BLK_I2C_ADDRESS, OUT_CTRL1, FLD_OUT_MODE, OUT_MODE_VIP11); @@ -657,8 +596,7 @@ int cx231xx_set_decoder_video_input(struct cx231xx *dev, } /* Read the DFE_CTRL1 register */ - status = cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, - DFE_CTRL1, 2, &value, 4); + status = vid_blk_read_word(dev, DFE_CTRL1, &value); /* enable the VBI_GATE_EN */ value |= FLD_VBI_GATE_EN; @@ -667,35 +605,31 @@ int cx231xx_set_decoder_video_input(struct cx231xx *dev, value |= FLD_VGA_AUTO_EN; /* Write it back */ - status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, - DFE_CTRL1, 2, value, 4); + status = vid_blk_write_word(dev, DFE_CTRL1, value); /* Disable auto config of registers */ status = cx231xx_read_modify_write_i2c_dword(dev, - HAMMERHEAD_I2C_ADDRESS, + VID_BLK_I2C_ADDRESS, MODE_CTRL, FLD_ACFG_DIS, cx231xx_set_field(FLD_ACFG_DIS, 1)); /* Set CVBS input mode */ status = cx231xx_read_modify_write_i2c_dword(dev, - HAMMERHEAD_I2C_ADDRESS, + VID_BLK_I2C_ADDRESS, MODE_CTRL, FLD_INPUT_MODE, cx231xx_set_field(FLD_INPUT_MODE, INPUT_MODE_CVBS_0)); break; case CX231XX_VMUX_SVIDEO: /* Disable the use of DIF */ - status = cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, - AFE_CTRL, 2, &value, 4); + status = vid_blk_read_word(dev, AFE_CTRL, &value); /* set [24:23] [22:15] to 0 */ value &= (~(0x1ff8000)); /* set FUNC_MODE[24:23] = 2 IF_MOD[22:15] = 0 DCR_BYP_CH2[4:4] = 1; */ value |= 0x1000010; - status = cx231xx_write_i2c_data(dev, - HAMMERHEAD_I2C_ADDRESS, - AFE_CTRL, 2, value, 4); + status = vid_blk_write_word(dev, AFE_CTRL, value); /* Tell DIF object to go to baseband mode */ status = cx231xx_dif_set_standard(dev, DIF_USE_BASEBAND); @@ -707,9 +641,7 @@ int cx231xx_set_decoder_video_input(struct cx231xx *dev, } /* Read the DFE_CTRL1 register */ - status = cx231xx_read_i2c_data(dev, - HAMMERHEAD_I2C_ADDRESS, - DFE_CTRL1, 2, &value, 4); + status = vid_blk_read_word(dev, DFE_CTRL1, &value); /* enable the VBI_GATE_EN */ value |= FLD_VBI_GATE_EN; @@ -718,27 +650,23 @@ int cx231xx_set_decoder_video_input(struct cx231xx *dev, value |= FLD_VGA_AUTO_EN; /* Write it back */ - status = cx231xx_write_i2c_data(dev, - HAMMERHEAD_I2C_ADDRESS, - DFE_CTRL1, 2, value, 4); + status = vid_blk_write_word(dev, DFE_CTRL1, value); /* Disable auto config of registers */ status = cx231xx_read_modify_write_i2c_dword(dev, - HAMMERHEAD_I2C_ADDRESS, + VID_BLK_I2C_ADDRESS, MODE_CTRL, FLD_ACFG_DIS, cx231xx_set_field(FLD_ACFG_DIS, 1)); /* Set YC input mode */ status = cx231xx_read_modify_write_i2c_dword(dev, - HAMMERHEAD_I2C_ADDRESS, + VID_BLK_I2C_ADDRESS, MODE_CTRL, FLD_INPUT_MODE, cx231xx_set_field(FLD_INPUT_MODE, INPUT_MODE_YC_1)); /* Chroma to ADC2 */ - status = cx231xx_read_i2c_data(dev, - HAMMERHEAD_I2C_ADDRESS, - AFE_CTRL, 2, &value, 4); + status = vid_blk_read_word(dev, AFE_CTRL, &value); value |= FLD_CHROMA_IN_SEL; /* set the chroma in select */ /* Clear VGA_SEL_CH2 and VGA_SEL_CH3 (bits 7 and 8) @@ -746,11 +674,9 @@ int cx231xx_set_decoder_video_input(struct cx231xx *dev, rather than audio. Only one of the two will be in use. */ value &= ~(FLD_VGA_SEL_CH2 | FLD_VGA_SEL_CH3); - status = cx231xx_write_i2c_data(dev, - HAMMERHEAD_I2C_ADDRESS, - AFE_CTRL, 2, value, 4); + status = vid_blk_write_word(dev, AFE_CTRL, value); - status = cx231xx_colibri_set_mode(dev, AFE_MODE_BASEBAND); + status = cx231xx_afe_set_mode(dev, AFE_MODE_BASEBAND); break; case CX231XX_VMUX_TELEVISION: case CX231XX_VMUX_CABLE: @@ -760,10 +686,7 @@ int cx231xx_set_decoder_video_input(struct cx231xx *dev, case CX231XX_BOARD_CNXT_RDU_250: /* Disable the use of DIF */ - status = cx231xx_read_i2c_data(dev, - HAMMERHEAD_I2C_ADDRESS, - AFE_CTRL, 2, - &value, 4); + status = vid_blk_read_word(dev, AFE_CTRL, &value); value |= (0 << 13) | (1 << 4); value &= ~(1 << 5); @@ -771,24 +694,15 @@ int cx231xx_set_decoder_video_input(struct cx231xx *dev, value &= (~(0x1FF8000)); /* set FUNC_MODE[24:23] = 2 IF_MOD[22:15] = 0 */ value |= 0x1000000; - status = cx231xx_write_i2c_data(dev, - HAMMERHEAD_I2C_ADDRESS, - AFE_CTRL, 2, - value, 4); - - status = cx231xx_read_i2c_data(dev, - HAMMERHEAD_I2C_ADDRESS, - OUT_CTRL1, 2, - &value, 4); + status = vid_blk_write_word(dev, AFE_CTRL, value); + + status = vid_blk_read_word(dev, OUT_CTRL1, &value); value |= (1 << 7); - status = cx231xx_write_i2c_data(dev, - HAMMERHEAD_I2C_ADDRESS, - OUT_CTRL1, 2, - value, 4); + status = vid_blk_write_word(dev, OUT_CTRL1, value); /* Set vip 1.1 output mode */ status = cx231xx_read_modify_write_i2c_dword(dev, - HAMMERHEAD_I2C_ADDRESS, + VID_BLK_I2C_ADDRESS, OUT_CTRL1, FLD_OUT_MODE, OUT_MODE_VIP11); @@ -803,10 +717,7 @@ int cx231xx_set_decoder_video_input(struct cx231xx *dev, } /* Read the DFE_CTRL1 register */ - status = cx231xx_read_i2c_data(dev, - HAMMERHEAD_I2C_ADDRESS, - DFE_CTRL1, 2, - &value, 4); + status = vid_blk_read_word(dev, DFE_CTRL1, &value); /* enable the VBI_GATE_EN */ value |= FLD_VBI_GATE_EN; @@ -815,20 +726,17 @@ int cx231xx_set_decoder_video_input(struct cx231xx *dev, value |= FLD_VGA_AUTO_EN; /* Write it back */ - status = cx231xx_write_i2c_data(dev, - HAMMERHEAD_I2C_ADDRESS, - DFE_CTRL1, 2, - value, 4); + status = vid_blk_write_word(dev, DFE_CTRL1, value); /* Disable auto config of registers */ status = cx231xx_read_modify_write_i2c_dword(dev, - HAMMERHEAD_I2C_ADDRESS, + VID_BLK_I2C_ADDRESS, MODE_CTRL, FLD_ACFG_DIS, cx231xx_set_field(FLD_ACFG_DIS, 1)); /* Set CVBS input mode */ status = cx231xx_read_modify_write_i2c_dword(dev, - HAMMERHEAD_I2C_ADDRESS, + VID_BLK_I2C_ADDRESS, MODE_CTRL, FLD_INPUT_MODE, cx231xx_set_field(FLD_INPUT_MODE, INPUT_MODE_CVBS_0)); @@ -846,25 +754,16 @@ int cx231xx_set_decoder_video_input(struct cx231xx *dev, } /* Make sure bypass is cleared */ - status = cx231xx_read_i2c_data(dev, - HAMMERHEAD_I2C_ADDRESS, - DIF_MISC_CTRL, - 2, &value, 4); + status = vid_blk_read_word(dev, DIF_MISC_CTRL, &value); /* Clear the bypass bit */ value &= ~FLD_DIF_DIF_BYPASS; /* Enable the use of the DIF block */ - status = cx231xx_write_i2c_data(dev, - HAMMERHEAD_I2C_ADDRESS, - DIF_MISC_CTRL, - 2, value, 4); + status = vid_blk_write_word(dev, DIF_MISC_CTRL, value); /* Read the DFE_CTRL1 register */ - status = cx231xx_read_i2c_data(dev, - HAMMERHEAD_I2C_ADDRESS, - DFE_CTRL1, 2, - &value, 4); + status = vid_blk_read_word(dev, DFE_CTRL1, &value); /* Disable the VBI_GATE_EN */ value &= ~FLD_VBI_GATE_EN; @@ -874,10 +773,7 @@ int cx231xx_set_decoder_video_input(struct cx231xx *dev, value |= FLD_VGA_AUTO_EN | FLD_AGC_AUTO_EN | 0x00200000; /* Write it back */ - status = cx231xx_write_i2c_data(dev, - HAMMERHEAD_I2C_ADDRESS, - DFE_CTRL1, 2, - value, 4); + status = vid_blk_write_word(dev, DFE_CTRL1, value); /* Wait until AGC locks up */ msleep(1); @@ -886,39 +782,30 @@ int cx231xx_set_decoder_video_input(struct cx231xx *dev, value &= ~(FLD_VGA_AUTO_EN); /* Write it back */ - status = cx231xx_write_i2c_data(dev, - HAMMERHEAD_I2C_ADDRESS, - DFE_CTRL1, 2, - value, 4); + status = vid_blk_write_word(dev, DFE_CTRL1, value); /* Enable Polaris B0 AGC output */ - status = cx231xx_read_i2c_data(dev, - HAMMERHEAD_I2C_ADDRESS, - PIN_CTRL, 2, - &value, 4); + status = vid_blk_read_word(dev, PIN_CTRL, &value); value |= (FLD_OEF_AGC_RF) | (FLD_OEF_AGC_IFVGA) | (FLD_OEF_AGC_IF); - status = cx231xx_write_i2c_data(dev, - HAMMERHEAD_I2C_ADDRESS, - PIN_CTRL, 2, - value, 4); + status = vid_blk_write_word(dev, PIN_CTRL, value); /* Set vip 1.1 output mode */ status = cx231xx_read_modify_write_i2c_dword(dev, - HAMMERHEAD_I2C_ADDRESS, + VID_BLK_I2C_ADDRESS, OUT_CTRL1, FLD_OUT_MODE, OUT_MODE_VIP11); /* Disable auto config of registers */ status = cx231xx_read_modify_write_i2c_dword(dev, - HAMMERHEAD_I2C_ADDRESS, + VID_BLK_I2C_ADDRESS, MODE_CTRL, FLD_ACFG_DIS, cx231xx_set_field(FLD_ACFG_DIS, 1)); /* Set CVBS input mode */ status = cx231xx_read_modify_write_i2c_dword(dev, - HAMMERHEAD_I2C_ADDRESS, + VID_BLK_I2C_ADDRESS, MODE_CTRL, FLD_INPUT_MODE, cx231xx_set_field(FLD_INPUT_MODE, INPUT_MODE_CVBS_0)); @@ -928,17 +815,11 @@ int cx231xx_set_decoder_video_input(struct cx231xx *dev, /* Clear clamp for channels 2 and 3 (bit 16-17) */ /* Clear droop comp (bit 19-20) */ /* Set VGA_SEL (for audio control) (bit 7-8) */ - status = cx231xx_read_i2c_data(dev, - HAMMERHEAD_I2C_ADDRESS, - AFE_CTRL, 2, - &value, 4); + status = vid_blk_read_word(dev, AFE_CTRL, &value); value |= FLD_VGA_SEL_CH3 | FLD_VGA_SEL_CH2; - status = cx231xx_write_i2c_data(dev, - HAMMERHEAD_I2C_ADDRESS, - AFE_CTRL, 2, - value, 4); + status = vid_blk_write_word(dev, AFE_CTRL, value); break; } @@ -947,17 +828,14 @@ int cx231xx_set_decoder_video_input(struct cx231xx *dev, /* Set raw VBI mode */ status = cx231xx_read_modify_write_i2c_dword(dev, - HAMMERHEAD_I2C_ADDRESS, + VID_BLK_I2C_ADDRESS, OUT_CTRL1, FLD_VBIHACTRAW_EN, cx231xx_set_field(FLD_VBIHACTRAW_EN, 1)); - status = cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, - OUT_CTRL1, 2, - &value, 4); + status = vid_blk_read_word(dev, OUT_CTRL1, &value); if (value & 0x02) { value |= (1 << 19); - status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, - OUT_CTRL1, 2, value, 4); + status = vid_blk_write_word(dev, OUT_CTRL1, value); } return status; @@ -976,9 +854,7 @@ int cx231xx_do_mode_ctrl_overrides(struct cx231xx *dev) (unsigned int)dev->norm); /* Change the DFE_CTRL3 bp_percent to fix flagging */ - status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, - DFE_CTRL3, 2, - 0xCD3F0280, 4); + status = vid_blk_write_word(dev, DFE_CTRL3, 0xCD3F0280); if (dev->norm & (V4L2_STD_NTSC | V4L2_STD_PAL_M)) { cx231xx_info("do_mode_ctrl_overrides NTSC\n"); @@ -986,22 +862,22 @@ int cx231xx_do_mode_ctrl_overrides(struct cx231xx *dev) /* Move the close caption lines out of active video, adjust the active video start point */ status = cx231xx_read_modify_write_i2c_dword(dev, - HAMMERHEAD_I2C_ADDRESS, + VID_BLK_I2C_ADDRESS, VERT_TIM_CTRL, FLD_VBLANK_CNT, 0x18); status = cx231xx_read_modify_write_i2c_dword(dev, - HAMMERHEAD_I2C_ADDRESS, + VID_BLK_I2C_ADDRESS, VERT_TIM_CTRL, FLD_VACTIVE_CNT, 0x1E6000); status = cx231xx_read_modify_write_i2c_dword(dev, - HAMMERHEAD_I2C_ADDRESS, + VID_BLK_I2C_ADDRESS, VERT_TIM_CTRL, FLD_V656BLANK_CNT, 0x1E000000); status = cx231xx_read_modify_write_i2c_dword(dev, - HAMMERHEAD_I2C_ADDRESS, + VID_BLK_I2C_ADDRESS, HORIZ_TIM_CTRL, FLD_HBLANK_CNT, cx231xx_set_field @@ -1009,12 +885,12 @@ int cx231xx_do_mode_ctrl_overrides(struct cx231xx *dev) } else if (dev->norm & V4L2_STD_SECAM) { cx231xx_info("do_mode_ctrl_overrides SECAM\n"); status = cx231xx_read_modify_write_i2c_dword(dev, - HAMMERHEAD_I2C_ADDRESS, + VID_BLK_I2C_ADDRESS, VERT_TIM_CTRL, FLD_VBLANK_CNT, 0x24); /* Adjust the active video horizontal start point */ status = cx231xx_read_modify_write_i2c_dword(dev, - HAMMERHEAD_I2C_ADDRESS, + VID_BLK_I2C_ADDRESS, HORIZ_TIM_CTRL, FLD_HBLANK_CNT, cx231xx_set_field @@ -1022,12 +898,12 @@ int cx231xx_do_mode_ctrl_overrides(struct cx231xx *dev) } else { cx231xx_info("do_mode_ctrl_overrides PAL\n"); status = cx231xx_read_modify_write_i2c_dword(dev, - HAMMERHEAD_I2C_ADDRESS, + VID_BLK_I2C_ADDRESS, VERT_TIM_CTRL, FLD_VBLANK_CNT, 0x24); /* Adjust the active video horizontal start point */ status = cx231xx_read_modify_write_i2c_dword(dev, - HAMMERHEAD_I2C_ADDRESS, + VID_BLK_I2C_ADDRESS, HORIZ_TIM_CTRL, FLD_HBLANK_CNT, cx231xx_set_field @@ -1047,7 +923,7 @@ int cx231xx_set_audio_input(struct cx231xx *dev, u8 input) ainput = AUDIO_INPUT_TUNER_TV; break; case CX231XX_AMUX_LINE_IN: - status = cx231xx_flatiron_set_audio_input(dev, input); + status = cx231xx_i2s_blk_set_audio_input(dev, input); ainput = AUDIO_INPUT_LINE; break; default: @@ -1064,71 +940,55 @@ int cx231xx_set_audio_decoder_input(struct cx231xx *dev, { u32 dwval; int status; - u32 gen_ctrl; + u8 gen_ctrl; u32 value = 0; /* Put it in soft reset */ - status = cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, - GENERAL_CTL, 2, &gen_ctrl, 1); + status = vid_blk_read_byte(dev, GENERAL_CTL, &gen_ctrl); gen_ctrl |= 1; - status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, - GENERAL_CTL, 2, gen_ctrl, 1); + status = vid_blk_write_byte(dev, GENERAL_CTL, gen_ctrl); switch (audio_input) { case AUDIO_INPUT_LINE: /* setup AUD_IO control from Merlin paralle output */ value = cx231xx_set_field(FLD_AUD_CHAN1_SRC, AUD_CHAN_SRC_PARALLEL); - status = cx231xx_write_i2c_data(dev, - HAMMERHEAD_I2C_ADDRESS, - AUD_IO_CTRL, 2, value, 4); + status = vid_blk_write_word(dev, AUD_IO_CTRL, value); /* setup input to Merlin, SRC2 connect to AC97 bypass upsample-by-2, slave mode, sony mode, left justify adr 091c, dat 01000000 */ - status = cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, - AC97_CTL, - 2, &dwval, 4); + status = vid_blk_read_word(dev, AC97_CTL, &dwval); - status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, - AC97_CTL, 2, - (dwval | FLD_AC97_UP2X_BYPASS), 4); + status = vid_blk_write_word(dev, AC97_CTL, + (dwval | FLD_AC97_UP2X_BYPASS)); /* select the parallel1 and SRC3 */ - status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, - BAND_OUT_SEL, 2, + status = vid_blk_write_word(dev, BAND_OUT_SEL, cx231xx_set_field(FLD_SRC3_IN_SEL, 0x0) | cx231xx_set_field(FLD_SRC3_CLK_SEL, 0x0) | - cx231xx_set_field(FLD_PARALLEL1_SRC_SEL, 0x0), - 4); + cx231xx_set_field(FLD_PARALLEL1_SRC_SEL, 0x0)); /* unmute all, AC97 in, independence mode adr 08d0, data 0x00063073 */ - status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, - PATH1_CTL1, 2, 0x00063073, 4); + status = vid_blk_write_word(dev, PATH1_CTL1, 0x00063073); /* set AVC maximum threshold, adr 08d4, dat ffff0024 */ - status = cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, - PATH1_VOL_CTL, 2, &dwval, 4); - status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, - PATH1_VOL_CTL, 2, - (dwval | FLD_PATH1_AVC_THRESHOLD), - 4); + status = vid_blk_read_word(dev, PATH1_VOL_CTL, &dwval); + status = vid_blk_write_word(dev, PATH1_VOL_CTL, + (dwval | FLD_PATH1_AVC_THRESHOLD)); /* set SC maximum threshold, adr 08ec, dat ffffb3a3 */ - status = cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, - PATH1_SC_CTL, 2, &dwval, 4); - status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, - PATH1_SC_CTL, 2, - (dwval | FLD_PATH1_SC_THRESHOLD), 4); + status = vid_blk_read_word(dev, PATH1_SC_CTL, &dwval); + status = vid_blk_write_word(dev, PATH1_SC_CTL, + (dwval | FLD_PATH1_SC_THRESHOLD)); break; case AUDIO_INPUT_TUNER_TV: default: /* Setup SRC sources and clocks */ - status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, - BAND_OUT_SEL, 2, + status = vid_blk_write_word(dev, BAND_OUT_SEL, cx231xx_set_field(FLD_SRC6_IN_SEL, 0x00) | cx231xx_set_field(FLD_SRC6_CLK_SEL, 0x01) | cx231xx_set_field(FLD_SRC5_IN_SEL, 0x00) | @@ -1141,29 +1001,26 @@ int cx231xx_set_audio_decoder_input(struct cx231xx *dev, cx231xx_set_field(FLD_AC97_SRC_SEL, 0x03) | cx231xx_set_field(FLD_I2S_SRC_SEL, 0x00) | cx231xx_set_field(FLD_PARALLEL2_SRC_SEL, 0x02) | - cx231xx_set_field(FLD_PARALLEL1_SRC_SEL, 0x01), 4); + cx231xx_set_field(FLD_PARALLEL1_SRC_SEL, 0x01)); /* Setup the AUD_IO control */ - status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, - AUD_IO_CTRL, 2, + status = vid_blk_write_word(dev, AUD_IO_CTRL, cx231xx_set_field(FLD_I2S_PORT_DIR, 0x00) | cx231xx_set_field(FLD_I2S_OUT_SRC, 0x00) | cx231xx_set_field(FLD_AUD_CHAN3_SRC, 0x00) | cx231xx_set_field(FLD_AUD_CHAN2_SRC, 0x00) | - cx231xx_set_field(FLD_AUD_CHAN1_SRC, 0x03), 4); + cx231xx_set_field(FLD_AUD_CHAN1_SRC, 0x03)); - status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, - PATH1_CTL1, 2, 0x1F063870, 4); + status = vid_blk_write_word(dev, PATH1_CTL1, 0x1F063870); /* setAudioStandard(_audio_standard); */ - status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, - PATH1_CTL1, 2, 0x00063870, 4); + status = vid_blk_write_word(dev, PATH1_CTL1, 0x00063870); switch (dev->model) { case CX231XX_BOARD_CNXT_RDE_250: case CX231XX_BOARD_CNXT_RDU_250: status = cx231xx_read_modify_write_i2c_dword(dev, - HAMMERHEAD_I2C_ADDRESS, + VID_BLK_I2C_ADDRESS, CHIP_CTRL, FLD_SIF_EN, cx231xx_set_field(FLD_SIF_EN, 1)); @@ -1181,17 +1038,14 @@ int cx231xx_set_audio_decoder_input(struct cx231xx *dev, break; case AUDIO_INPUT_MUTE: - status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, - PATH1_CTL1, 2, 0x1F011012, 4); + status = vid_blk_write_word(dev, PATH1_CTL1, 0x1F011012); break; } /* Take it out of soft reset */ - status = cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, - GENERAL_CTL, 2, &gen_ctrl, 1); + status = vid_blk_read_byte(dev, GENERAL_CTL, &gen_ctrl); gen_ctrl &= ~1; - status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, - GENERAL_CTL, 2, gen_ctrl, 1); + status = vid_blk_write_byte(dev, GENERAL_CTL, gen_ctrl); return status; } @@ -1209,12 +1063,10 @@ int cx231xx_resolution_set(struct cx231xx *dev) get_scale(dev, width, height, &hscale, &vscale); /* set horzontal scale */ - status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, - HSCALE_CTRL, 2, hscale, 4); + status = vid_blk_write_word(dev, HSCALE_CTRL, hscale); /* set vertical scale */ - status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, - VSCALE_CTRL, 2, vscale, 4); + status = vid_blk_write_word(dev, VSCALE_CTRL, vscale); return status; } @@ -1227,11 +1079,9 @@ int cx231xx_init_ctrl_pin_status(struct cx231xx *dev) u32 value; int status = 0; - status = cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, PIN_CTRL, - 2, &value, 4); + status = vid_blk_read_word(dev, PIN_CTRL, &value); value |= (~dev->board.ctl_pin_status_mask); - status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, PIN_CTRL, - 2, value, 4); + status = vid_blk_write_word(dev, PIN_CTRL, value); return status; } @@ -1296,82 +1146,82 @@ int cx231xx_dif_configure_C2HH_for_low_IF(struct cx231xx *dev, u32 mode, /* C2HH */ /* lo if big signal */ status = cx231xx_reg_mask_write(dev, - HAMMERHEAD_I2C_ADDRESS, 32, + VID_BLK_I2C_ADDRESS, 32, AFE_CTRL_C2HH_SRC_CTRL, 30, 31, 0x1); /* FUNC_MODE = DIF */ status = cx231xx_reg_mask_write(dev, - HAMMERHEAD_I2C_ADDRESS, 32, + VID_BLK_I2C_ADDRESS, 32, AFE_CTRL_C2HH_SRC_CTRL, 23, 24, function_mode); /* IF_MODE */ status = cx231xx_reg_mask_write(dev, - HAMMERHEAD_I2C_ADDRESS, 32, + VID_BLK_I2C_ADDRESS, 32, AFE_CTRL_C2HH_SRC_CTRL, 15, 22, 0xFF); /* no inv */ status = cx231xx_reg_mask_write(dev, - HAMMERHEAD_I2C_ADDRESS, 32, + VID_BLK_I2C_ADDRESS, 32, AFE_CTRL_C2HH_SRC_CTRL, 9, 9, 0x1); } else if (standard != DIF_USE_BASEBAND) { if (standard & V4L2_STD_MN) { /* lo if big signal */ status = cx231xx_reg_mask_write(dev, - HAMMERHEAD_I2C_ADDRESS, 32, + VID_BLK_I2C_ADDRESS, 32, AFE_CTRL_C2HH_SRC_CTRL, 30, 31, 0x1); /* FUNC_MODE = DIF */ status = cx231xx_reg_mask_write(dev, - HAMMERHEAD_I2C_ADDRESS, 32, + VID_BLK_I2C_ADDRESS, 32, AFE_CTRL_C2HH_SRC_CTRL, 23, 24, function_mode); /* IF_MODE */ status = cx231xx_reg_mask_write(dev, - HAMMERHEAD_I2C_ADDRESS, 32, + VID_BLK_I2C_ADDRESS, 32, AFE_CTRL_C2HH_SRC_CTRL, 15, 22, 0xb); /* no inv */ status = cx231xx_reg_mask_write(dev, - HAMMERHEAD_I2C_ADDRESS, 32, + VID_BLK_I2C_ADDRESS, 32, AFE_CTRL_C2HH_SRC_CTRL, 9, 9, 0x1); /* 0x124, AUD_CHAN1_SRC = 0x3 */ status = cx231xx_reg_mask_write(dev, - HAMMERHEAD_I2C_ADDRESS, 32, + VID_BLK_I2C_ADDRESS, 32, AUD_IO_CTRL, 0, 31, 0x00000003); } else if ((standard == V4L2_STD_PAL_I) | (standard & V4L2_STD_SECAM)) { /* C2HH setup */ /* lo if big signal */ status = cx231xx_reg_mask_write(dev, - HAMMERHEAD_I2C_ADDRESS, 32, + VID_BLK_I2C_ADDRESS, 32, AFE_CTRL_C2HH_SRC_CTRL, 30, 31, 0x1); /* FUNC_MODE = DIF */ status = cx231xx_reg_mask_write(dev, - HAMMERHEAD_I2C_ADDRESS, 32, + VID_BLK_I2C_ADDRESS, 32, AFE_CTRL_C2HH_SRC_CTRL, 23, 24, function_mode); /* IF_MODE */ status = cx231xx_reg_mask_write(dev, - HAMMERHEAD_I2C_ADDRESS, 32, + VID_BLK_I2C_ADDRESS, 32, AFE_CTRL_C2HH_SRC_CTRL, 15, 22, 0xF); /* no inv */ status = cx231xx_reg_mask_write(dev, - HAMMERHEAD_I2C_ADDRESS, 32, + VID_BLK_I2C_ADDRESS, 32, AFE_CTRL_C2HH_SRC_CTRL, 9, 9, 0x1); } else { /* default PAL BG */ /* C2HH setup */ /* lo if big signal */ status = cx231xx_reg_mask_write(dev, - HAMMERHEAD_I2C_ADDRESS, 32, + VID_BLK_I2C_ADDRESS, 32, AFE_CTRL_C2HH_SRC_CTRL, 30, 31, 0x1); /* FUNC_MODE = DIF */ status = cx231xx_reg_mask_write(dev, - HAMMERHEAD_I2C_ADDRESS, 32, + VID_BLK_I2C_ADDRESS, 32, AFE_CTRL_C2HH_SRC_CTRL, 23, 24, function_mode); /* IF_MODE */ status = cx231xx_reg_mask_write(dev, - HAMMERHEAD_I2C_ADDRESS, 32, + VID_BLK_I2C_ADDRESS, 32, AFE_CTRL_C2HH_SRC_CTRL, 15, 22, 0xE); /* no inv */ status = cx231xx_reg_mask_write(dev, - HAMMERHEAD_I2C_ADDRESS, 32, + VID_BLK_I2C_ADDRESS, 32, AFE_CTRL_C2HH_SRC_CTRL, 9, 9, 0x1); } } @@ -1387,9 +1237,7 @@ int cx231xx_dif_set_standard(struct cx231xx *dev, u32 standard) cx231xx_info("%s: setStandard to %x\n", __func__, standard); - status = cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, - DIF_MISC_CTRL, 2, &dif_misc_ctrl_value, - 4); + status = vid_blk_read_word(dev, DIF_MISC_CTRL, &dif_misc_ctrl_value); if (standard != DIF_USE_BASEBAND) dev->norm = standard; @@ -1408,182 +1256,154 @@ int cx231xx_dif_set_standard(struct cx231xx *dev, u32 standard) if (standard == DIF_USE_BASEBAND) { /* base band */ /* There is a different SRC_PHASE_INC value for baseband vs. DIF */ - status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, - DIF_SRC_PHASE_INC, 2, 0xDF7DF83, - 4); - status = cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, - DIF_MISC_CTRL, 2, - &dif_misc_ctrl_value, 4); + status = vid_blk_write_word(dev, DIF_SRC_PHASE_INC, 0xDF7DF83); + status = vid_blk_read_word(dev, DIF_MISC_CTRL, + &dif_misc_ctrl_value); dif_misc_ctrl_value |= FLD_DIF_DIF_BYPASS; - status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, - DIF_MISC_CTRL, 2, - dif_misc_ctrl_value, 4); + status = vid_blk_write_word(dev, DIF_MISC_CTRL, + dif_misc_ctrl_value); } else if (standard & V4L2_STD_PAL_D) { - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, DIF_PLL_CTRL, 0, 31, 0x6503bc0c); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, DIF_PLL_CTRL1, 0, 31, 0xbd038c85); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, DIF_PLL_CTRL2, 0, 31, 0x1db4640a); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, DIF_PLL_CTRL3, 0, 31, 0x00008800); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, DIF_AGC_IF_REF, 0, 31, 0x444C1380); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, DIF_AGC_CTRL_IF, 0, 31, 0xDA302600); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, DIF_AGC_CTRL_INT, 0, 31, 0xDA261700); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, DIF_AGC_CTRL_RF, 0, 31, 0xDA262600); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, DIF_AGC_IF_INT_CURRENT, 0, 31, 0x26001700); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, DIF_AGC_RF_CURRENT, 0, 31, 0x00002660); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, DIF_VIDEO_AGC_CTRL, 0, 31, 0x72500800); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, DIF_VID_AUD_OVERRIDE, 0, 31, 0x27000100); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, DIF_AV_SEP_CTRL, 0, 31, 0x3F3934EA); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, DIF_COMP_FLT_CTRL, 0, 31, 0x00000000); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, DIF_SRC_PHASE_INC, 0, 31, 0x1befbf06); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, DIF_SRC_GAIN_CONTROL, 0, 31, 0x000035e8); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, DIF_RPT_VARIANCE, 0, 31, 0x00000000); /* Save the Spec Inversion value */ dif_misc_ctrl_value &= FLD_DIF_SPEC_INV; dif_misc_ctrl_value |= 0x3a023F11; } else if (standard & V4L2_STD_PAL_I) { - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, DIF_PLL_CTRL, 0, 31, 0x6503bc0c); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, DIF_PLL_CTRL1, 0, 31, 0xbd038c85); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, DIF_PLL_CTRL2, 0, 31, 0x1db4640a); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, DIF_PLL_CTRL3, 0, 31, 0x00008800); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, DIF_AGC_IF_REF, 0, 31, 0x444C1380); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, DIF_AGC_CTRL_IF, 0, 31, 0xDA302600); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, DIF_AGC_CTRL_INT, 0, 31, 0xDA261700); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, DIF_AGC_CTRL_RF, 0, 31, 0xDA262600); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, DIF_AGC_IF_INT_CURRENT, 0, 31, 0x26001700); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, DIF_AGC_RF_CURRENT, 0, 31, 0x00002660); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, DIF_VIDEO_AGC_CTRL, 0, 31, 0x72500800); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, DIF_VID_AUD_OVERRIDE, 0, 31, 0x27000100); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, DIF_AV_SEP_CTRL, 0, 31, 0x5F39A934); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, DIF_COMP_FLT_CTRL, 0, 31, 0x00000000); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, DIF_SRC_PHASE_INC, 0, 31, 0x1befbf06); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, DIF_SRC_GAIN_CONTROL, 0, 31, 0x000035e8); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, DIF_RPT_VARIANCE, 0, 31, 0x00000000); /* Save the Spec Inversion value */ dif_misc_ctrl_value &= FLD_DIF_SPEC_INV; dif_misc_ctrl_value |= 0x3a033F11; } else if (standard & V4L2_STD_PAL_M) { /* improved Low Frequency Phase Noise */ - status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, - DIF_PLL_CTRL, 2, 0xFF01FF0C, 4); - status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, - DIF_PLL_CTRL1, 2, 0xbd038c85, - 4); - status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, - DIF_PLL_CTRL2, 2, 0x1db4640a, 4); - status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, - DIF_PLL_CTRL3, 2, 0x00008800, 4); - status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, - DIF_AGC_IF_REF, 2, 0x444C1380, 4); - status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, - DIF_AGC_IF_INT_CURRENT, 2, - 0x26001700, 4); - status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, - DIF_AGC_RF_CURRENT, 2, 0x00002660, - 4); - status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, - DIF_VIDEO_AGC_CTRL, 2, 0x72500800, - 4); - status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, - DIF_VID_AUD_OVERRIDE, 2, 0x27000100, - 4); - status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, - DIF_AV_SEP_CTRL, 2, 0x012c405d, 4); - status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, - DIF_COMP_FLT_CTRL, 2, 0x009f50c1, 4); - status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, - DIF_SRC_PHASE_INC, 2, 0x1befbf06, 4); - status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, - DIF_SRC_GAIN_CONTROL, 2, 0x000035e8, - 4); - status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, - DIF_SOFT_RST_CTRL_REVB, 2, - 0x00000000, 4); + status = vid_blk_write_word(dev, DIF_PLL_CTRL, 0xFF01FF0C); + status = vid_blk_write_word(dev, DIF_PLL_CTRL1, 0xbd038c85); + status = vid_blk_write_word(dev, DIF_PLL_CTRL2, 0x1db4640a); + status = vid_blk_write_word(dev, DIF_PLL_CTRL3, 0x00008800); + status = vid_blk_write_word(dev, DIF_AGC_IF_REF, 0x444C1380); + status = vid_blk_write_word(dev, DIF_AGC_IF_INT_CURRENT, + 0x26001700); + status = vid_blk_write_word(dev, DIF_AGC_RF_CURRENT, + 0x00002660); + status = vid_blk_write_word(dev, DIF_VIDEO_AGC_CTRL, + 0x72500800); + status = vid_blk_write_word(dev, DIF_VID_AUD_OVERRIDE, + 0x27000100); + status = vid_blk_write_word(dev, DIF_AV_SEP_CTRL, 0x012c405d); + status = vid_blk_write_word(dev, DIF_COMP_FLT_CTRL, + 0x009f50c1); + status = vid_blk_write_word(dev, DIF_SRC_PHASE_INC, + 0x1befbf06); + status = vid_blk_write_word(dev, DIF_SRC_GAIN_CONTROL, + 0x000035e8); + status = vid_blk_write_word(dev, DIF_SOFT_RST_CTRL_REVB, + 0x00000000); /* Save the Spec Inversion value */ dif_misc_ctrl_value &= FLD_DIF_SPEC_INV; dif_misc_ctrl_value |= 0x3A0A3F10; } else if (standard & (V4L2_STD_PAL_N | V4L2_STD_PAL_Nc)) { /* improved Low Frequency Phase Noise */ - status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, - DIF_PLL_CTRL, 2, 0xFF01FF0C, 4); - status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, - DIF_PLL_CTRL1, 2, 0xbd038c85, 4); - status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, - DIF_PLL_CTRL2, 2, 0x1db4640a, 4); - status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, - DIF_PLL_CTRL3, 2, 0x00008800, 4); - status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, - DIF_AGC_IF_REF, 2, 0x444C1380, 4); - status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, - DIF_AGC_IF_INT_CURRENT, 2, - 0x26001700, 4); - status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, - DIF_AGC_RF_CURRENT, 2, 0x00002660, - 4); - status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, - DIF_VIDEO_AGC_CTRL, 2, 0x72500800, - 4); - status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, - DIF_VID_AUD_OVERRIDE, 2, 0x27000100, - 4); - status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, - DIF_AV_SEP_CTRL, 2, 0x012c405d, 4); - status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, - DIF_COMP_FLT_CTRL, 2, 0x009f50c1, 4); - status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, - DIF_SRC_PHASE_INC, 2, 0x1befbf06, 4); - status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, - DIF_SRC_GAIN_CONTROL, 2, 0x000035e8, - 4); - status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, - DIF_SOFT_RST_CTRL_REVB, 2, - 0x00000000, 4); + status = vid_blk_write_word(dev, DIF_PLL_CTRL, 0xFF01FF0C); + status = vid_blk_write_word(dev, DIF_PLL_CTRL1, 0xbd038c85); + status = vid_blk_write_word(dev, DIF_PLL_CTRL2, 0x1db4640a); + status = vid_blk_write_word(dev, DIF_PLL_CTRL3, 0x00008800); + status = vid_blk_write_word(dev, DIF_AGC_IF_REF, 0x444C1380); + status = vid_blk_write_word(dev, DIF_AGC_IF_INT_CURRENT, + 0x26001700); + status = vid_blk_write_word(dev, DIF_AGC_RF_CURRENT, + 0x00002660); + status = vid_blk_write_word(dev, DIF_VIDEO_AGC_CTRL, + 0x72500800); + status = vid_blk_write_word(dev, DIF_VID_AUD_OVERRIDE, + 0x27000100); + status = vid_blk_write_word(dev, DIF_AV_SEP_CTRL, + 0x012c405d); + status = vid_blk_write_word(dev, DIF_COMP_FLT_CTRL, + 0x009f50c1); + status = vid_blk_write_word(dev, DIF_SRC_PHASE_INC, + 0x1befbf06); + status = vid_blk_write_word(dev, DIF_SRC_GAIN_CONTROL, + 0x000035e8); + status = vid_blk_write_word(dev, DIF_SOFT_RST_CTRL_REVB, + 0x00000000); /* Save the Spec Inversion value */ dif_misc_ctrl_value &= FLD_DIF_SPEC_INV; dif_misc_ctrl_value = 0x3A093F10; @@ -1591,45 +1411,45 @@ int cx231xx_dif_set_standard(struct cx231xx *dev, u32 standard) (V4L2_STD_SECAM_B | V4L2_STD_SECAM_D | V4L2_STD_SECAM_G | V4L2_STD_SECAM_K | V4L2_STD_SECAM_K1)) { - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, DIF_PLL_CTRL, 0, 31, 0x6503bc0c); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, DIF_PLL_CTRL1, 0, 31, 0xbd038c85); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, DIF_PLL_CTRL2, 0, 31, 0x1db4640a); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, DIF_PLL_CTRL3, 0, 31, 0x00008800); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, DIF_AGC_IF_REF, 0, 31, 0x888C0380); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, DIF_AGC_CTRL_IF, 0, 31, 0xe0262600); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, DIF_AGC_CTRL_INT, 0, 31, 0xc2171700); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, DIF_AGC_CTRL_RF, 0, 31, 0xc2262600); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, DIF_AGC_IF_INT_CURRENT, 0, 31, 0x26001700); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, DIF_AGC_RF_CURRENT, 0, 31, 0x00002660); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, DIF_VID_AUD_OVERRIDE, 0, 31, 0x27000100); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, DIF_AV_SEP_CTRL, 0, 31, 0x3F3530ec); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, DIF_COMP_FLT_CTRL, 0, 31, 0x00000000); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, DIF_SRC_PHASE_INC, 0, 31, 0x1befbf06); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, DIF_SRC_GAIN_CONTROL, 0, 31, 0x000035e8); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, DIF_RPT_VARIANCE, 0, 31, 0x00000000); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, DIF_VIDEO_AGC_CTRL, 0, 31, 0xf4000000); @@ -1638,45 +1458,45 @@ int cx231xx_dif_set_standard(struct cx231xx *dev, u32 standard) dif_misc_ctrl_value |= 0x3a023F11; } else if (standard & (V4L2_STD_SECAM_L | V4L2_STD_SECAM_LC)) { /* Is it SECAM_L1? */ - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, DIF_PLL_CTRL, 0, 31, 0x6503bc0c); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, DIF_PLL_CTRL1, 0, 31, 0xbd038c85); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, DIF_PLL_CTRL2, 0, 31, 0x1db4640a); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, DIF_PLL_CTRL3, 0, 31, 0x00008800); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, DIF_AGC_IF_REF, 0, 31, 0x888C0380); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, DIF_AGC_CTRL_IF, 0, 31, 0xe0262600); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, DIF_AGC_CTRL_INT, 0, 31, 0xc2171700); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, DIF_AGC_CTRL_RF, 0, 31, 0xc2262600); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, DIF_AGC_IF_INT_CURRENT, 0, 31, 0x26001700); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, DIF_AGC_RF_CURRENT, 0, 31, 0x00002660); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, DIF_VID_AUD_OVERRIDE, 0, 31, 0x27000100); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, DIF_AV_SEP_CTRL, 0, 31, 0x3F3530ec); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, DIF_COMP_FLT_CTRL, 0, 31, 0x00000000); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, DIF_SRC_PHASE_INC, 0, 31, 0x1befbf06); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, DIF_SRC_GAIN_CONTROL, 0, 31, 0x000035e8); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, DIF_RPT_VARIANCE, 0, 31, 0x00000000); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, DIF_VIDEO_AGC_CTRL, 0, 31, 0xf2560000); @@ -1694,91 +1514,78 @@ int cx231xx_dif_set_standard(struct cx231xx *dev, u32 standard) the pll freq word is 0x03420c49 */ - status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, - DIF_PLL_CTRL, 2, 0x6503BC0C, 4); - status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, - DIF_PLL_CTRL1, 2, 0xBD038C85, 4); - status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, - DIF_PLL_CTRL2, 2, 0x1DB4640A, 4); - status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, - DIF_PLL_CTRL3, 2, 0x00008800, 4); - status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, - DIF_AGC_IF_REF, 2, 0x444C0380, 4); - status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, - DIF_AGC_IF_INT_CURRENT, 2, - 0x26001700, 4); - status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, - DIF_AGC_RF_CURRENT, 2, 0x00002660, - 4); - status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, - DIF_VIDEO_AGC_CTRL, 2, 0x04000800, - 4); - status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, - DIF_VID_AUD_OVERRIDE, 2, 0x27000100, - 4); - status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, - DIF_AV_SEP_CTRL, 2, 0x01296e1f, 4); - - status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, - DIF_COMP_FLT_CTRL, 2, 0x009f50c1, 4); - status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, - DIF_SRC_PHASE_INC, 2, 0x1befbf06, 4); - status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, - DIF_SRC_GAIN_CONTROL, 2, 0x000035e8, - 4); - - status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, - DIF_AGC_CTRL_IF, 2, 0xC2262600, 4); - status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, - DIF_AGC_CTRL_INT, 2, 0xC2262600, 4); - status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, - DIF_AGC_CTRL_RF, 2, 0xC2262600, 4); + status = vid_blk_write_word(dev, DIF_PLL_CTRL, 0x6503BC0C); + status = vid_blk_write_word(dev, DIF_PLL_CTRL1, 0xBD038C85); + status = vid_blk_write_word(dev, DIF_PLL_CTRL2, 0x1DB4640A); + status = vid_blk_write_word(dev, DIF_PLL_CTRL3, 0x00008800); + status = vid_blk_write_word(dev, DIF_AGC_IF_REF, 0x444C0380); + status = vid_blk_write_word(dev, DIF_AGC_IF_INT_CURRENT, + 0x26001700); + status = vid_blk_write_word(dev, DIF_AGC_RF_CURRENT, + 0x00002660); + status = vid_blk_write_word(dev, DIF_VIDEO_AGC_CTRL, + 0x04000800); + status = vid_blk_write_word(dev, DIF_VID_AUD_OVERRIDE, + 0x27000100); + status = vid_blk_write_word(dev, DIF_AV_SEP_CTRL, 0x01296e1f); + + status = vid_blk_write_word(dev, DIF_COMP_FLT_CTRL, + 0x009f50c1); + status = vid_blk_write_word(dev, DIF_SRC_PHASE_INC, + 0x1befbf06); + status = vid_blk_write_word(dev, DIF_SRC_GAIN_CONTROL, + 0x000035e8); + + status = vid_blk_write_word(dev, DIF_AGC_CTRL_IF, 0xC2262600); + status = vid_blk_write_word(dev, DIF_AGC_CTRL_INT, + 0xC2262600); + status = vid_blk_write_word(dev, DIF_AGC_CTRL_RF, 0xC2262600); /* Save the Spec Inversion value */ dif_misc_ctrl_value &= FLD_DIF_SPEC_INV; dif_misc_ctrl_value |= 0x3a003F10; } else { /* default PAL BG */ - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, DIF_PLL_CTRL, 0, 31, 0x6503bc0c); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, DIF_PLL_CTRL1, 0, 31, 0xbd038c85); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, DIF_PLL_CTRL2, 0, 31, 0x1db4640a); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, DIF_PLL_CTRL3, 0, 31, 0x00008800); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, DIF_AGC_IF_REF, 0, 31, 0x444C1380); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, DIF_AGC_CTRL_IF, 0, 31, 0xDA302600); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, DIF_AGC_CTRL_INT, 0, 31, 0xDA261700); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, DIF_AGC_CTRL_RF, 0, 31, 0xDA262600); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, DIF_AGC_IF_INT_CURRENT, 0, 31, 0x26001700); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, DIF_AGC_RF_CURRENT, 0, 31, 0x00002660); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, DIF_VIDEO_AGC_CTRL, 0, 31, 0x72500800); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, DIF_VID_AUD_OVERRIDE, 0, 31, 0x27000100); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, DIF_AV_SEP_CTRL, 0, 31, 0x3F3530EC); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, DIF_COMP_FLT_CTRL, 0, 31, 0x00A653A8); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, DIF_SRC_PHASE_INC, 0, 31, 0x1befbf06); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, DIF_SRC_GAIN_CONTROL, 0, 31, 0x000035e8); - status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32, + status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, DIF_RPT_VARIANCE, 0, 31, 0x00000000); /* Save the Spec Inversion value */ dif_misc_ctrl_value &= FLD_DIF_SPEC_INV; @@ -1796,9 +1603,7 @@ int cx231xx_dif_set_standard(struct cx231xx *dev, u32 standard) dif_misc_ctrl_value = 0x7a080000; /* Write the calculated value for misc ontrol register */ - status = - cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_MISC_CTRL, - 2, dif_misc_ctrl_value, 4); + status = vid_blk_write_word(dev, DIF_MISC_CTRL, dif_misc_ctrl_value); return status; } @@ -1809,13 +1614,11 @@ int cx231xx_tuner_pre_channel_change(struct cx231xx *dev) u32 dwval; /* Set the RF and IF k_agc values to 3 */ - status = cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, - DIF_AGC_IF_REF, 2, &dwval, 4); + status = vid_blk_read_word(dev, DIF_AGC_IF_REF, &dwval); dwval &= ~(FLD_DIF_K_AGC_RF | FLD_DIF_K_AGC_IF); dwval |= 0x33000000; - status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, - DIF_AGC_IF_REF, 2, dwval, 4); + status = vid_blk_write_word(dev, DIF_AGC_IF_REF, dwval); return status; } @@ -1827,8 +1630,7 @@ int cx231xx_tuner_post_channel_change(struct cx231xx *dev) /* Set the RF and IF k_agc values to 4 for PAL/NTSC and 8 for * SECAM L/B/D standards */ - status = cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, - DIF_AGC_IF_REF, 2, &dwval, 4); + status = vid_blk_read_word(dev, DIF_AGC_IF_REF, &dwval); dwval &= ~(FLD_DIF_K_AGC_RF | FLD_DIF_K_AGC_IF); if (dev->norm & (V4L2_STD_SECAM_L | V4L2_STD_SECAM_B | @@ -1837,63 +1639,62 @@ int cx231xx_tuner_post_channel_change(struct cx231xx *dev) else dwval |= 0x44000000; - status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, - DIF_AGC_IF_REF, 2, dwval, 4); + status = vid_blk_write_word(dev, DIF_AGC_IF_REF, dwval); return status; } /****************************************************************************** - * F L A T I R O N - B L O C K C O N T R O L functions * + * I 2 S - B L O C K C O N T R O L functions * ******************************************************************************/ -int cx231xx_flatiron_initialize(struct cx231xx *dev) +int cx231xx_i2s_blk_initialize(struct cx231xx *dev) { int status = 0; u32 value; - status = cx231xx_read_i2c_data(dev, Flatrion_DEVICE_ADDRESS, + status = cx231xx_read_i2c_data(dev, I2S_BLK_DEVICE_ADDRESS, CH_PWR_CTRL1, 1, &value, 1); /* enables clock to delta-sigma and decimation filter */ value |= 0x80; - status = cx231xx_write_i2c_data(dev, Flatrion_DEVICE_ADDRESS, + status = cx231xx_write_i2c_data(dev, I2S_BLK_DEVICE_ADDRESS, CH_PWR_CTRL1, 1, value, 1); /* power up all channel */ - status = cx231xx_write_i2c_data(dev, Flatrion_DEVICE_ADDRESS, + status = cx231xx_write_i2c_data(dev, I2S_BLK_DEVICE_ADDRESS, CH_PWR_CTRL2, 1, 0x00, 1); return status; } -int cx231xx_flatiron_update_power_control(struct cx231xx *dev, +int cx231xx_i2s_blk_update_power_control(struct cx231xx *dev, enum AV_MODE avmode) { int status = 0; u32 value = 0; if (avmode != POLARIS_AVMODE_ENXTERNAL_AV) { - status = cx231xx_read_i2c_data(dev, Flatrion_DEVICE_ADDRESS, + status = cx231xx_read_i2c_data(dev, I2S_BLK_DEVICE_ADDRESS, CH_PWR_CTRL2, 1, &value, 1); value |= 0xfe; - status = cx231xx_write_i2c_data(dev, Flatrion_DEVICE_ADDRESS, + status = cx231xx_write_i2c_data(dev, I2S_BLK_DEVICE_ADDRESS, CH_PWR_CTRL2, 1, value, 1); } else { - status = cx231xx_write_i2c_data(dev, Flatrion_DEVICE_ADDRESS, + status = cx231xx_write_i2c_data(dev, I2S_BLK_DEVICE_ADDRESS, CH_PWR_CTRL2, 1, 0x00, 1); } return status; } -/* set flatiron for audio input types */ -int cx231xx_flatiron_set_audio_input(struct cx231xx *dev, u8 audio_input) +/* set i2s_blk for audio input types */ +int cx231xx_i2s_blk_set_audio_input(struct cx231xx *dev, u8 audio_input) { int status = 0; switch (audio_input) { case CX231XX_AMUX_LINE_IN: - status = cx231xx_write_i2c_data(dev, Flatrion_DEVICE_ADDRESS, + status = cx231xx_write_i2c_data(dev, I2S_BLK_DEVICE_ADDRESS, CH_PWR_CTRL2, 1, 0x00, 1); - status = cx231xx_write_i2c_data(dev, Flatrion_DEVICE_ADDRESS, + status = cx231xx_write_i2c_data(dev, I2S_BLK_DEVICE_ADDRESS, CH_PWR_CTRL1, 1, 0x80, 1); break; case CX231XX_AMUX_VIDEO: @@ -2114,11 +1915,11 @@ int cx231xx_set_power_mode(struct cx231xx *dev, enum AV_MODE mode) msleep(PWR_SLEEP_INTERVAL); } - /* update power control for colibri */ - status = cx231xx_colibri_update_power_control(dev, mode); + /* update power control for afe */ + status = cx231xx_afe_update_power_control(dev, mode); - /* update power control for flatiron */ - status = cx231xx_flatiron_update_power_control(dev, mode); + /* update power control for i2s_blk */ + status = cx231xx_i2s_blk_update_power_control(dev, mode); status = cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, PWR_CTL_EN, value, 4); diff --git a/linux/drivers/media/video/cx231xx/cx231xx-core.c b/linux/drivers/media/video/cx231xx/cx231xx-core.c index 2aec3a842..405819ac1 100644 --- a/linux/drivers/media/video/cx231xx/cx231xx-core.c +++ b/linux/drivers/media/video/cx231xx/cx231xx-core.c @@ -906,7 +906,7 @@ int cx231xx_dev_init(struct cx231xx *dev) /* init hardware */ /* Note : with out calling set power mode function, - colibri can not be set up correctly */ + afe can not be set up correctly */ errCode = cx231xx_set_power_mode(dev, POLARIS_AVMODE_ANALOGT_TV); if (errCode < 0) { cx231xx_errdev @@ -916,17 +916,17 @@ int cx231xx_dev_init(struct cx231xx *dev) } /* initialize Colibri block */ - errCode = cx231xx_colibri_init_super_block(dev, 0x23c); + errCode = cx231xx_afe_init_super_block(dev, 0x23c); if (errCode < 0) { cx231xx_errdev - ("%s: cx231xx_colibri init super block - errCode [%d]!\n", + ("%s: cx231xx_afe init super block - errCode [%d]!\n", __func__, errCode); return errCode; } - errCode = cx231xx_colibri_init_channels(dev); + errCode = cx231xx_afe_init_channels(dev); if (errCode < 0) { cx231xx_errdev - ("%s: cx231xx_colibri init channels - errCode [%d]!\n", + ("%s: cx231xx_afe init channels - errCode [%d]!\n", __func__, errCode); return errCode; } @@ -940,11 +940,11 @@ int cx231xx_dev_init(struct cx231xx *dev) return errCode; } - /* flatiron related functions */ - errCode = cx231xx_flatiron_initialize(dev); + /* I2S block related functions */ + errCode = cx231xx_i2s_blk_initialize(dev); if (errCode < 0) { cx231xx_errdev - ("%s: cx231xx_flatiron initialize - errCode [%d]!\n", + ("%s: cx231xx_i2s block initialize - errCode [%d]!\n", __func__, errCode); return errCode; } diff --git a/linux/drivers/media/video/cx231xx/cx231xx-pcb-cfg.h b/linux/drivers/media/video/cx231xx/cx231xx-pcb-cfg.h index 86fec113f..f5e46e89f 100644 --- a/linux/drivers/media/video/cx231xx/cx231xx-pcb-cfg.h +++ b/linux/drivers/media/video/cx231xx/cx231xx-pcb-cfg.h @@ -91,10 +91,10 @@ enum TS_PORT{ #define EAVP_MASK 0x8 enum EAV_PRESENT{ NO_EXTERNAL_AV = 0x0, /* 0: No External A/V inputs - (no need for Flatiron), + (no need for i2s blcok), Analog Tuner must be present */ EXTERNAL_AV = 0x8 /* 1: External A/V inputs - present (requires Flatiron) */ + present (requires i2s blk) */ }; #define ATM_MASK 0x30 @@ -123,10 +123,6 @@ enum AVDEC_STATUS{ }; #define BO_1_MASK 0x100 -enum HAMMERHEAD__STATUS{ - HAMMERHEAD_ONLY = 0x0, /* 0:Hammerhead Only */ - HAMMERHEAD_SC = 0x100 /* 1:Hammerhead and SC */ -}; #define BUSPOWER_MASK 0xC4 /* for Polaris spec 0.8 */ #define SELFPOWER_MASK 0x86 diff --git a/linux/drivers/media/video/cx231xx/cx231xx-video.c b/linux/drivers/media/video/cx231xx/cx231xx-video.c index e706d0bcb..c0a43a0dc 100644 --- a/linux/drivers/media/video/cx231xx/cx231xx-video.c +++ b/linux/drivers/media/video/cx231xx/cx231xx-video.c @@ -1421,36 +1421,36 @@ static int vidioc_g_register(struct file *file, void *priv, reg->val = value[0] | value[1] << 8 | value[2] << 16 | value[3] << 24; break; - case 1: /* Colibri - read byte */ - ret = cx231xx_read_i2c_data(dev, Colibri_DEVICE_ADDRESS, + case 1: /* AFE - read byte */ + ret = cx231xx_read_i2c_data(dev, AFE_DEVICE_ADDRESS, (u16)reg->reg, 2, &data, 1); reg->val = le32_to_cpu(data & 0xff); break; - case 14: /* Colibri - read dword */ - ret = cx231xx_read_i2c_data(dev, Colibri_DEVICE_ADDRESS, + case 14: /* AFE - read dword */ + ret = cx231xx_read_i2c_data(dev, AFE_DEVICE_ADDRESS, (u16)reg->reg, 2, &data, 4); reg->val = le32_to_cpu(data); break; - case 2: /* Hammerhead - read byte */ - ret = cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + case 2: /* Video Block - read byte */ + ret = cx231xx_read_i2c_data(dev, VID_BLK_I2C_ADDRESS, (u16)reg->reg, 2, &data, 1); reg->val = le32_to_cpu(data & 0xff); break; - case 24: /* Hammerhead - read dword */ - ret = cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, + case 24: /* Video Block - read dword */ + ret = cx231xx_read_i2c_data(dev, VID_BLK_I2C_ADDRESS, (u16)reg->reg, 2, &data, 4); reg->val = le32_to_cpu(data); break; - case 3: /* flatiron - read byte */ + case 3: /* I2S block - read byte */ ret = cx231xx_read_i2c_data(dev, - Flatrion_DEVICE_ADDRESS, + I2S_BLK_DEVICE_ADDRESS, (u16)reg->reg, 1, &data, 1); reg->val = le32_to_cpu(data & 0xff); break; - case 34: /* flatiron - read dword */ + case 34: /* I2S Block - read dword */ ret = - cx231xx_read_i2c_data(dev, Flatrion_DEVICE_ADDRESS, + cx231xx_read_i2c_data(dev, I2S_BLK_DEVICE_ADDRESS, (u16)reg->reg, 1, &data, 4); reg->val = le32_to_cpu(data); break; @@ -1503,43 +1503,43 @@ static int vidioc_s_register(struct file *file, void *priv, (u16)reg->reg, data, 4); break; - case 1: /* Colibri - read byte */ + case 1: /* AFE - read byte */ ret = cx231xx_write_i2c_data(dev, - Colibri_DEVICE_ADDRESS, + AFE_DEVICE_ADDRESS, (u16)reg->reg, 2, value, 1); break; - case 14: /* Colibri - read dword */ + case 14: /* AFE - read dword */ ret = cx231xx_write_i2c_data(dev, - Colibri_DEVICE_ADDRESS, + AFE_DEVICE_ADDRESS, (u16)reg->reg, 2, value, 4); break; - case 2: /* Hammerhead - read byte */ + case 2: /* Video Block - read byte */ ret = cx231xx_write_i2c_data(dev, - HAMMERHEAD_I2C_ADDRESS, + VID_BLK_I2C_ADDRESS, (u16)reg->reg, 2, value, 1); break; - case 24: /* Hammerhead - read dword */ + case 24: /* Video Block - read dword */ ret = cx231xx_write_i2c_data(dev, - HAMMERHEAD_I2C_ADDRESS, + VID_BLK_I2C_ADDRESS, (u16)reg->reg, 2, value, 4); break; - case 3: /* flatiron - read byte */ + case 3: /* I2S block - read byte */ ret = cx231xx_write_i2c_data(dev, - Flatrion_DEVICE_ADDRESS, + I2S_BLK_DEVICE_ADDRESS, (u16)reg->reg, 1, value, 1); break; - case 34: /* flatiron - read dword */ + case 34: /* I2S block - read dword */ ret = cx231xx_write_i2c_data(dev, - Flatrion_DEVICE_ADDRESS, + I2S_BLK_DEVICE_ADDRESS, (u16)reg->reg, 1, value, 4); break; diff --git a/linux/drivers/media/video/cx231xx/cx231xx.h b/linux/drivers/media/video/cx231xx/cx231xx.h index 8a86b3227..21b4023dd 100644 --- a/linux/drivers/media/video/cx231xx/cx231xx.h +++ b/linux/drivers/media/video/cx231xx/cx231xx.h @@ -47,9 +47,9 @@ #define PWR_SLEEP_INTERVAL 5 /* I2C addresses for control block in Cx231xx */ -#define Colibri_DEVICE_ADDRESS 0x60 -#define Flatrion_DEVICE_ADDRESS 0x98 -#define HAMMERHEAD_I2C_ADDRESS 0x88 +#define AFE_DEVICE_ADDRESS 0x60 +#define I2S_BLK_DEVICE_ADDRESS 0x98 +#define VID_BLK_I2C_ADDRESS 0x88 #define DIF_USE_BASEBAND 0xFFFFFFFF /* Boards supported by driver */ @@ -549,9 +549,9 @@ struct cx231xx { /* Power Modes */ int power_mode; - /* colibri parameters */ - enum AFE_MODE colibri_mode; - u32 colibri_ref_count; + /* afe parameters */ + enum AFE_MODE afe_mode; + u32 afe_ref_count; /* video related parameters */ u32 video_input; @@ -597,21 +597,21 @@ int cx231xx_read_modify_write_i2c_dword(struct cx231xx *dev, u8 dev_addr, u16 saddr, u32 mask, u32 value); u32 cx231xx_set_field(u32 field_mask, u32 data); -/* Colibri related functions */ -int cx231xx_colibri_init_super_block(struct cx231xx *dev, u32 ref_count); -int cx231xx_colibri_init_channels(struct cx231xx *dev); -int cx231xx_colibri_setup_AFE_for_baseband(struct cx231xx *dev); -int cx231xx_colibri_set_input_mux(struct cx231xx *dev, u32 input_mux); -int cx231xx_colibri_set_mode(struct cx231xx *dev, enum AFE_MODE mode); -int cx231xx_colibri_update_power_control(struct cx231xx *dev, +/* afe related functions */ +int cx231xx_afe_init_super_block(struct cx231xx *dev, u32 ref_count); +int cx231xx_afe_init_channels(struct cx231xx *dev); +int cx231xx_afe_setup_AFE_for_baseband(struct cx231xx *dev); +int cx231xx_afe_set_input_mux(struct cx231xx *dev, u32 input_mux); +int cx231xx_afe_set_mode(struct cx231xx *dev, enum AFE_MODE mode); +int cx231xx_afe_update_power_control(struct cx231xx *dev, enum AV_MODE avmode); -int cx231xx_colibri_adjust_ref_count(struct cx231xx *dev, u32 video_input); +int cx231xx_afe_adjust_ref_count(struct cx231xx *dev, u32 video_input); -/* flatiron related functions */ -int cx231xx_flatiron_initialize(struct cx231xx *dev); -int cx231xx_flatiron_update_power_control(struct cx231xx *dev, +/* i2s block related functions */ +int cx231xx_i2s_blk_initialize(struct cx231xx *dev); +int cx231xx_i2s_blk_update_power_control(struct cx231xx *dev, enum AV_MODE avmode); -int cx231xx_flatiron_set_audio_input(struct cx231xx *dev, u8 audio_input); +int cx231xx_i2s_blk_set_audio_input(struct cx231xx *dev, u8 audio_input); /* DIF related functions */ int cx231xx_dif_configure_C2HH_for_low_IF(struct cx231xx *dev, u32 mode, -- cgit v1.2.3 From a20d311c162fb0c2c6d5fc499852211e8936054d Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 21 Mar 2009 22:16:34 -0300 Subject: cx231xx: fix an inverted logic at vidioc_streamoff From: Mauro Carvalho Chehab Priority: normal CC: Srinivasa Deevi Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/cx231xx/cx231xx-video.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/cx231xx/cx231xx-video.c b/linux/drivers/media/video/cx231xx/cx231xx-video.c index c0a43a0dc..144eb9dd7 100644 --- a/linux/drivers/media/video/cx231xx/cx231xx-video.c +++ b/linux/drivers/media/video/cx231xx/cx231xx-video.c @@ -1614,7 +1614,7 @@ static int vidioc_streamoff(struct file *file, void *priv, if (rc < 0) return rc; - if ((fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) || + if ((fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) && (fh->type != V4L2_BUF_TYPE_VBI_CAPTURE)) return -EINVAL; if (type != fh->type) -- cgit v1.2.3 From ad50b0ea773765f3e80aec5fb66b59aa2bc404f2 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 22 Mar 2009 05:46:36 -0300 Subject: cx231xx: avoid trying to access unfilled dev struct From: Mauro Carvalho Chehab cx231xxinfo needs dev->name. However, this is not declared on the time the check for the max number of supported devices is done. Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/cx231xx/cx231xx-cards.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (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 31c9c93bd..e7d6633d2 100644 --- a/linux/drivers/media/video/cx231xx/cx231xx-cards.c +++ b/linux/drivers/media/video/cx231xx/cx231xx-cards.c @@ -578,7 +578,7 @@ static int cx231xx_usb_probe(struct usb_interface *interface, cx231xx_devused |= 1 << nr; if (nr >= CX231XX_MAXBOARDS) { - cx231xx_info(": Supports only %i cx231xx boards.\n", + cx231xx_err(DRIVER_NAME ": Supports only %i cx231xx boards.\n", CX231XX_MAXBOARDS); cx231xx_devused &= ~(1 << nr); return -ENOMEM; -- cgit v1.2.3 From 85f66bd70183e630eb879d67337a7df1d36b71cc Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 22 Mar 2009 07:52:02 -0300 Subject: cx231xx: usb probe cleanups From: Mauro Carvalho Chehab Simplifies the usb probe logic, cleaning the printed messages during the probing phase. Priority: normal CC: Srinivasa Deevi Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/cx231xx/cx231xx-cards.c | 412 ++++++++++------------ 1 file changed, 189 insertions(+), 223 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 e7d6633d2..b63e8c44b 100644 --- a/linux/drivers/media/video/cx231xx/cx231xx-cards.c +++ b/linux/drivers/media/video/cx231xx/cx231xx-cards.c @@ -569,10 +569,10 @@ static int cx231xx_usb_probe(struct usb_interface *interface, udev = usb_get_dev(interface_to_usbdev(interface)); ifnum = interface->altsetting[0].desc.bInterfaceNumber; - printk(DRIVER_NAME ": Interface Number %d\n", ifnum); - - /* Interface number 0 - IR interface */ - if (ifnum == 0) { + if (!ifnum) { + /* + * Interface number 0 - IR interface + */ /* Check to see next free device and mark as used */ nr = find_first_zero_bit(&cx231xx_devused, CX231XX_MAXBOARDS); cx231xx_devused |= 1 << nr; @@ -611,42 +611,46 @@ static int cx231xx_usb_probe(struct usb_interface *interface, /* get maximum no.of IAD interfaces */ assoc_desc = udev->actconfig->intf_assoc[0]; dev->max_iad_interface_count = assoc_desc->bInterfaceCount; - cx231xx_info("Found IAD interface count %d\n", - dev->max_iad_interface_count); /* init CIR module TBD */ /* store the current interface */ lif = interface; - } else if (ifnum == 1) { - - /* Get dev structure first */ - dev = usb_get_intfdata(udev->actconfig->interface[0]); - if (dev == NULL) { - cx231xx_err(DRIVER_NAME ": out of first interface!\n"); - return -ENODEV; + switch (udev->speed) { + case USB_SPEED_LOW: + speed = "1.5"; + break; + case USB_SPEED_UNKNOWN: + case USB_SPEED_FULL: + speed = "12"; + break; + case USB_SPEED_HIGH: + speed = "480"; + break; + default: + speed = "unknown"; } - /* store the interface 0 back */ - lif = udev->actconfig->interface[0]; - - /* increment interface count */ - dev->interface_count++; - - /* get device number */ - nr = dev->devno; + if (udev->manufacturer) + strlcpy(descr, udev->manufacturer, sizeof(descr)); - assoc_desc = udev->actconfig->intf_assoc[0]; - if (assoc_desc->bFirstInterface == ifnum) { - cx231xx_info - ("Found IAD interface match: AV Desc Start!! \n"); - } else { - cx231xx_err(" Not found matching interface\n"); - return -ENODEV; + if (udev->product) { + if (*descr) + strlcat(descr, " ", sizeof(descr)); + strlcat(descr, udev->product, sizeof(descr)); } + if (*descr) + strlcat(descr, " ", sizeof(descr)); - } else if (ifnum >= 2) { + cx231xx_info("New device %s@ %s Mbps " + "(%04x:%04x) with %d interfaces\n", + descr, + speed, + le16_to_cpu(udev->descriptor.idVendor), + le16_to_cpu(udev->descriptor.idProduct), + dev->max_iad_interface_count); + } else { /* Get dev structure first */ dev = usb_get_intfdata(udev->actconfig->interface[0]); if (dev == NULL) { @@ -663,162 +667,176 @@ static int cx231xx_usb_probe(struct usb_interface *interface, /* get device number */ nr = dev->devno; - /* set skip interface */ - if ((dev->interface_count - 1) != dev->max_iad_interface_count) - skip_interface = 1; /* set skipping */ - else { - cx231xx_info - ("Found IAD interface no. match with AV Device no.!\n"); + /* + * set skip interface, for all interfaces but + * interface 1 and the last one + */ + if ((ifnum != 1) && ((dev->interface_count - 1) + != dev->max_iad_interface_count)) + skip_interface = 1; + + if (ifnum == 1) { + assoc_desc = udev->actconfig->intf_assoc[0]; + if (assoc_desc->bFirstInterface != ifnum) { + cx231xx_err(DRIVER_NAME ": Not found " + "matching IAD interface\n"); + return -ENODEV; + } } } - switch (udev->speed) { - case USB_SPEED_LOW: - speed = "1.5"; - break; - case USB_SPEED_UNKNOWN: - case USB_SPEED_FULL: - speed = "12"; - break; - case USB_SPEED_HIGH: - speed = "480"; - break; - default: - speed = "unknown"; - } + if (skip_interface) + return -ENODEV; - if (udev->manufacturer) - strlcpy(descr, udev->manufacturer, sizeof(descr)); + cx231xx_info("registering interface %d\n", ifnum); - if (udev->product) { - if (*descr) - strlcat(descr, " ", sizeof(descr)); - strlcat(descr, udev->product, sizeof(descr)); - } - if (*descr) - strlcat(descr, " ", sizeof(descr)); + /* save our data pointer in this interface device */ + usb_set_intfdata(lif, dev); - cx231xx_info("New device %s@ %s Mbps " - "(%04x:%04x, interface %d, class %d)\n", - descr, - speed, - le16_to_cpu(udev->descriptor.idVendor), - le16_to_cpu(udev->descriptor.idProduct), - ifnum, interface->altsetting->desc.bInterfaceNumber); + if ((dev->interface_count - 1) != dev->max_iad_interface_count) + return 0; - /* AV device initialization */ - if ((dev->interface_count - 1) == dev->max_iad_interface_count) { - cx231xx_info(" Calling init_dev\n"); + /* + * AV device initialization - only done at the last interface + */ - /* Create v4l2 device */ - snprintf(dev->v4l2_dev.name, sizeof(dev->v4l2_dev.name), + /* Create v4l2 device */ + snprintf(dev->v4l2_dev.name, sizeof(dev->v4l2_dev.name), "%s-%03d", "cx231xx", nr); - retval = v4l2_device_register(&udev->dev, &dev->v4l2_dev); - if (retval) { - printk(KERN_ERR "%s() v4l2_device_register failed\n", - __func__); - cx231xx_devused &= ~(1 << nr); - kfree(dev); - return -EIO; - } - - /* allocate device struct */ - retval = cx231xx_init_dev(&dev, udev, nr); - if (retval) { - cx231xx_devused &= ~(1 << dev->devno); - v4l2_device_unregister(&dev->v4l2_dev); - kfree(dev); - return retval; - } + retval = v4l2_device_register(&udev->dev, &dev->v4l2_dev); + if (retval) { + cx231xx_errdev("v4l2_device_register failed\n"); + cx231xx_devused &= ~(1 << nr); + kfree(dev); + return -EIO; + } - /* compute alternate max packet sizes for video */ - uif = - udev->actconfig->interface[dev->current_pcb_config. - hs_config_info[0].interface_info. - video_index + 1]; + /* allocate device struct */ + retval = cx231xx_init_dev(&dev, udev, nr); + if (retval) { + cx231xx_devused &= ~(1 << dev->devno); + v4l2_device_unregister(&dev->v4l2_dev); + kfree(dev); + return retval; + } - dev->video_mode.end_point_addr = - le16_to_cpu(uif->altsetting[0].endpoint[isoc_pipe].desc. - bEndpointAddress); + /* compute alternate max packet sizes for video */ + uif = udev->actconfig->interface[dev->current_pcb_config. + hs_config_info[0].interface_info.video_index + 1]; - dev->video_mode.num_alt = uif->num_altsetting; - cx231xx_info(": EndPoint Addr 0x%x, Alternate settings: %i\n", - dev->video_mode.end_point_addr, - dev->video_mode.num_alt); - dev->video_mode.alt_max_pkt_size = - kmalloc(32 * dev->video_mode.num_alt, GFP_KERNEL); + dev->video_mode.end_point_addr = le16_to_cpu(uif->altsetting[0]. + endpoint[isoc_pipe].desc.bEndpointAddress); - if (dev->video_mode.alt_max_pkt_size == NULL) { - cx231xx_errdev("out of memory!\n"); - cx231xx_devused &= ~(1 << nr); - v4l2_device_unregister(&dev->v4l2_dev); - kfree(dev); - return -ENOMEM; - } + dev->video_mode.num_alt = uif->num_altsetting; + cx231xx_info("EndPoint Addr 0x%x, Alternate settings: %i\n", + dev->video_mode.end_point_addr, + dev->video_mode.num_alt); + dev->video_mode.alt_max_pkt_size = + kmalloc(32 * dev->video_mode.num_alt, GFP_KERNEL); - for (i = 0; i < dev->video_mode.num_alt; i++) { - u16 tmp = - le16_to_cpu(uif->altsetting[i].endpoint[isoc_pipe]. - desc.wMaxPacketSize); - dev->video_mode.alt_max_pkt_size[i] = - (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1); - cx231xx_info("Alternate setting %i, max size= %i\n", i, - dev->video_mode.alt_max_pkt_size[i]); - } + if (dev->video_mode.alt_max_pkt_size == NULL) { + cx231xx_errdev("out of memory!\n"); + cx231xx_devused &= ~(1 << nr); + v4l2_device_unregister(&dev->v4l2_dev); + kfree(dev); + return -ENOMEM; + } - /* compute alternate max packet sizes for vbi */ - uif = - udev->actconfig->interface[dev->current_pcb_config. - hs_config_info[0].interface_info. - vanc_index + 1]; + for (i = 0; i < dev->video_mode.num_alt; i++) { + u16 tmp = le16_to_cpu(uif->altsetting[i].endpoint[isoc_pipe]. + desc.wMaxPacketSize); + dev->video_mode.alt_max_pkt_size[i] = + (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1); + cx231xx_info("Alternate setting %i, max size= %i\n", i, + dev->video_mode.alt_max_pkt_size[i]); + } - dev->vbi_mode.end_point_addr = - le16_to_cpu(uif->altsetting[0].endpoint[isoc_pipe].desc. - bEndpointAddress); + /* compute alternate max packet sizes for vbi */ + uif = udev->actconfig->interface[dev->current_pcb_config. + hs_config_info[0].interface_info. + vanc_index + 1]; + + dev->vbi_mode.end_point_addr = + le16_to_cpu(uif->altsetting[0].endpoint[isoc_pipe].desc. + bEndpointAddress); + + dev->vbi_mode.num_alt = uif->num_altsetting; + cx231xx_info("EndPoint Addr 0x%x, Alternate settings: %i\n", + dev->vbi_mode.end_point_addr, + dev->vbi_mode.num_alt); + dev->vbi_mode.alt_max_pkt_size = + kmalloc(32 * dev->vbi_mode.num_alt, GFP_KERNEL); + + if (dev->vbi_mode.alt_max_pkt_size == NULL) { + cx231xx_errdev("out of memory!\n"); + cx231xx_devused &= ~(1 << nr); + v4l2_device_unregister(&dev->v4l2_dev); + kfree(dev); + return -ENOMEM; + } - dev->vbi_mode.num_alt = uif->num_altsetting; - cx231xx_info(": EndPoint Addr 0x%x, Alternate settings: %i\n", - dev->vbi_mode.end_point_addr, - dev->vbi_mode.num_alt); - dev->vbi_mode.alt_max_pkt_size = - kmalloc(32 * dev->vbi_mode.num_alt, GFP_KERNEL); + for (i = 0; i < dev->vbi_mode.num_alt; i++) { + u16 tmp = + le16_to_cpu(uif->altsetting[i].endpoint[isoc_pipe]. + desc.wMaxPacketSize); + dev->vbi_mode.alt_max_pkt_size[i] = + (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1); + cx231xx_info("Alternate setting %i, max size= %i\n", i, + dev->vbi_mode.alt_max_pkt_size[i]); + } - if (dev->vbi_mode.alt_max_pkt_size == NULL) { - cx231xx_errdev("out of memory!\n"); - cx231xx_devused &= ~(1 << nr); - v4l2_device_unregister(&dev->v4l2_dev); - kfree(dev); - return -ENOMEM; - } + /* compute alternate max packet sizes for sliced CC */ + uif = udev->actconfig->interface[dev->current_pcb_config. + hs_config_info[0].interface_info. + hanc_index + 1]; + + dev->sliced_cc_mode.end_point_addr = + le16_to_cpu(uif->altsetting[0].endpoint[isoc_pipe].desc. + bEndpointAddress); + + dev->sliced_cc_mode.num_alt = uif->num_altsetting; + cx231xx_info("EndPoint Addr 0x%x, Alternate settings: %i\n", + dev->sliced_cc_mode.end_point_addr, + dev->sliced_cc_mode.num_alt); + dev->sliced_cc_mode.alt_max_pkt_size = + kmalloc(32 * dev->sliced_cc_mode.num_alt, GFP_KERNEL); + + if (dev->sliced_cc_mode.alt_max_pkt_size == NULL) { + cx231xx_errdev("out of memory!\n"); + cx231xx_devused &= ~(1 << nr); + v4l2_device_unregister(&dev->v4l2_dev); + kfree(dev); + return -ENOMEM; + } - for (i = 0; i < dev->vbi_mode.num_alt; i++) { - u16 tmp = - le16_to_cpu(uif->altsetting[i].endpoint[isoc_pipe]. - desc.wMaxPacketSize); - dev->vbi_mode.alt_max_pkt_size[i] = - (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1); - cx231xx_info("Alternate setting %i, max size= %i\n", i, - dev->vbi_mode.alt_max_pkt_size[i]); - } + for (i = 0; i < dev->sliced_cc_mode.num_alt; i++) { + u16 tmp = le16_to_cpu(uif->altsetting[i].endpoint[isoc_pipe]. + desc.wMaxPacketSize); + dev->sliced_cc_mode.alt_max_pkt_size[i] = + (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1); + cx231xx_info("Alternate setting %i, max size= %i\n", i, + dev->sliced_cc_mode.alt_max_pkt_size[i]); + } - /* compute alternate max packet sizes for sliced CC */ - uif = - udev->actconfig->interface[dev->current_pcb_config. - hs_config_info[0].interface_info. - hanc_index + 1]; + if (dev->current_pcb_config.ts1_source != 0xff) { + /* compute alternate max packet sizes for TS1 */ + uif = udev->actconfig->interface[dev->current_pcb_config. + hs_config_info[0]. + interface_info. + ts1_index + 1]; - dev->sliced_cc_mode.end_point_addr = - le16_to_cpu(uif->altsetting[0].endpoint[isoc_pipe].desc. - bEndpointAddress); + dev->ts1_mode.end_point_addr = + le16_to_cpu(uif->altsetting[0].endpoint[isoc_pipe]. + desc.bEndpointAddress); - dev->sliced_cc_mode.num_alt = uif->num_altsetting; - cx231xx_info(": EndPoint Addr 0x%x, Alternate settings: %i\n", - dev->sliced_cc_mode.end_point_addr, - dev->sliced_cc_mode.num_alt); - dev->sliced_cc_mode.alt_max_pkt_size = - kmalloc(32 * dev->sliced_cc_mode.num_alt, GFP_KERNEL); + dev->ts1_mode.num_alt = uif->num_altsetting; + cx231xx_info("EndPoint Addr 0x%x, Alternate settings: %i\n", + dev->ts1_mode.end_point_addr, + dev->ts1_mode.num_alt); + dev->ts1_mode.alt_max_pkt_size = + kmalloc(32 * dev->ts1_mode.num_alt, GFP_KERNEL); - if (dev->sliced_cc_mode.alt_max_pkt_size == NULL) { + if (dev->ts1_mode.alt_max_pkt_size == NULL) { cx231xx_errdev("out of memory!\n"); cx231xx_devused &= ~(1 << nr); v4l2_device_unregister(&dev->v4l2_dev); @@ -826,74 +844,19 @@ static int cx231xx_usb_probe(struct usb_interface *interface, return -ENOMEM; } - for (i = 0; i < dev->sliced_cc_mode.num_alt; i++) { - u16 tmp = - le16_to_cpu(uif->altsetting[i].endpoint[isoc_pipe]. - desc.wMaxPacketSize); - dev->sliced_cc_mode.alt_max_pkt_size[i] = - (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1); - cx231xx_info("Alternate setting %i, max size= %i\n", i, - dev->sliced_cc_mode.alt_max_pkt_size[i]); - } - - if (dev->current_pcb_config.ts1_source != 0xff) { - - /* compute alternate max packet sizes for TS1 */ - uif = - udev->actconfig->interface[dev->current_pcb_config. - hs_config_info[0]. - interface_info. - ts1_index + 1]; - - dev->ts1_mode.end_point_addr = - le16_to_cpu(uif->altsetting[0].endpoint[isoc_pipe]. - desc.bEndpointAddress); - - dev->ts1_mode.num_alt = uif->num_altsetting; - cx231xx_info - (": EndPoint Addr 0x%x, Alternate settings: %i\n", - dev->ts1_mode.end_point_addr, - dev->ts1_mode.num_alt); - dev->ts1_mode.alt_max_pkt_size = - kmalloc(32 * dev->ts1_mode.num_alt, GFP_KERNEL); - - if (dev->ts1_mode.alt_max_pkt_size == NULL) { - cx231xx_errdev("out of memory!\n"); - cx231xx_devused &= ~(1 << nr); - v4l2_device_unregister(&dev->v4l2_dev); - kfree(dev); - return -ENOMEM; - } - - for (i = 0; i < dev->ts1_mode.num_alt; i++) { - u16 tmp = - le16_to_cpu(uif->altsetting[i]. + for (i = 0; i < dev->ts1_mode.num_alt; i++) { + u16 tmp = le16_to_cpu(uif->altsetting[i]. endpoint[isoc_pipe].desc. wMaxPacketSize); - dev->ts1_mode.alt_max_pkt_size[i] = - (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + - 1); - cx231xx_info - ("Alternate setting %i, max size= %i\n", i, + dev->ts1_mode.alt_max_pkt_size[i] = + (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1); + cx231xx_info("Alternate setting %i, max size= %i\n", i, dev->ts1_mode.alt_max_pkt_size[i]); - } } - } - /* save our data pointer in this interface device */ - usb_set_intfdata(lif, dev); - /* load other modules required */ - if ((dev->interface_count - 1) == dev->max_iad_interface_count) { - cx231xx_info("Calling request modules\n"); - request_modules(dev); - } - - if (skip_interface) { - cx231xx_info("Skipping the interface\n"); - return -ENODEV; - } + request_modules(dev); return 0; } @@ -913,6 +876,9 @@ static void cx231xx_usb_disconnect(struct usb_interface *interface) if (!dev) return; + if (!dev->udev) + return; + /* delete v4l2 device */ v4l2_device_unregister(&dev->v4l2_dev); -- cgit v1.2.3 From b9f6ffec04bbe099974ad8932652b0fdab70e2a2 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 22 Mar 2009 08:02:12 -0300 Subject: cx231xx: don't print pcb config debug messages by default From: Mauro Carvalho Chehab Priority: normal CC: Srinivasa Deevi Signed-off-by: Mauro Carvalho Chehab --- .../drivers/media/video/cx231xx/cx231xx-pcb-cfg.c | 34 ++++++++++++---------- 1 file changed, 18 insertions(+), 16 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/cx231xx/cx231xx-pcb-cfg.c b/linux/drivers/media/video/cx231xx/cx231xx-pcb-cfg.c index c00f51eae..7473c33e8 100644 --- a/linux/drivers/media/video/cx231xx/cx231xx-pcb-cfg.c +++ b/linux/drivers/media/video/cx231xx/cx231xx-pcb-cfg.c @@ -22,6 +22,10 @@ #include "cx231xx.h" #include "cx231xx-conf-reg.h" +static unsigned int pcb_debug; +module_param(pcb_debug, int, 0644); +MODULE_PARM_DESC(pcb_debug, "enable pcb config debug messages [video]"); + /******************************************************************************/ struct pcb_config cx231xx_Scenario[] = { @@ -659,11 +663,8 @@ u32 initialize_cx231xx(struct cx231xx *dev) u32 ts1_source = 0; u32 ts2_source = 0; u32 analog_source = 0; - u8 tmp = 0; u8 _current_scenario_idx = 0xff; - cx231xx_info("PcbConfig::initialize \n"); - ts1_source = SOURCE_TS_BDA; ts2_source = SOURCE_TS_BDA; @@ -672,7 +673,6 @@ u32 initialize_cx231xx(struct cx231xx *dev) cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, BOARD_CFG_STAT, data, 4); config_info = *((u32 *) data); - cx231xx_info("SC(0x00) register = 0x%x\n", config_info); usb_speed = (u8) (config_info & 0x1); /* Verify this device belongs to Bus power or Self power device */ @@ -776,18 +776,20 @@ u32 initialize_cx231xx(struct cx231xx *dev) memcpy(&dev->current_pcb_config, p_pcb_info, sizeof(struct pcb_config)); - /*******************************************************************/ - tmp = (dev->current_pcb_config.index) + 1; - - cx231xx_info("scenario %d\n", tmp); - cx231xx_info("type=%x\n", dev->current_pcb_config.type); - cx231xx_info("mode=%x\n", dev->current_pcb_config.mode); - cx231xx_info("speed=%x\n", dev->current_pcb_config.speed); - cx231xx_info("ts1_source=%x\n", dev->current_pcb_config.ts1_source); - cx231xx_info("ts2_source=%x\n", dev->current_pcb_config.ts2_source); - cx231xx_info("analog_source=%x\n", - dev->current_pcb_config.analog_source); - /*******************************************************************/ + if (pcb_debug) { + cx231xx_info("SC(0x00) register = 0x%x\n", config_info); + cx231xx_info("scenario %d\n", + (dev->current_pcb_config.index) + 1); + cx231xx_info("type=%x\n", dev->current_pcb_config.type); + cx231xx_info("mode=%x\n", dev->current_pcb_config.mode); + cx231xx_info("speed=%x\n", dev->current_pcb_config.speed); + cx231xx_info("ts1_source=%x\n", + dev->current_pcb_config.ts1_source); + cx231xx_info("ts2_source=%x\n", + dev->current_pcb_config.ts2_source); + cx231xx_info("analog_source=%x\n", + dev->current_pcb_config.analog_source); + } return 0; } -- cgit v1.2.3 From 0ac5c38bc31a5a5a1913df3492a45cd0cc97038a Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 22 Mar 2009 08:28:30 -0300 Subject: cx231xx: dmesg cleanup From: Mauro Carvalho Chehab Remove some printk's that were needed only during development phase. Also, cleans the printed messages to produce a nicer result. Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/cx231xx/cx231xx-audio.c | 2 +- linux/drivers/media/video/cx231xx/cx231xx-cards.c | 20 +------------------- linux/drivers/media/video/cx231xx/cx231xx-core.c | 4 ++-- linux/drivers/media/video/cx231xx/cx231xx-i2c.c | 3 --- linux/drivers/media/video/cx231xx/cx231xx-video.c | 2 -- 5 files changed, 4 insertions(+), 27 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/cx231xx/cx231xx-audio.c b/linux/drivers/media/video/cx231xx/cx231xx-audio.c index b6f099042..0f7fb3ca7 100644 --- a/linux/drivers/media/video/cx231xx/cx231xx-audio.c +++ b/linux/drivers/media/video/cx231xx/cx231xx-audio.c @@ -599,7 +599,7 @@ static int cx231xx_audio_init(struct cx231xx *dev) bEndpointAddress); adev->num_alt = uif->num_altsetting; - cx231xx_info(": EndPoint Addr 0x%x, Alternate settings: %i\n", + cx231xx_info("EndPoint Addr 0x%x, Alternate settings: %i\n", adev->end_point_addr, adev->num_alt); adev->alt_max_pkt_size = kmalloc(32 * adev->num_alt, GFP_KERNEL); diff --git a/linux/drivers/media/video/cx231xx/cx231xx-cards.c b/linux/drivers/media/video/cx231xx/cx231xx-cards.c index b63e8c44b..d1872988a 100644 --- a/linux/drivers/media/video/cx231xx/cx231xx-cards.c +++ b/linux/drivers/media/video/cx231xx/cx231xx-cards.c @@ -225,7 +225,6 @@ void cx231xx_pre_card_setup(struct cx231xx *dev) cx231xx_info("Identified as %s (card=%d)\n", dev->board.name, dev->model); - cx231xx_info("Precard: Board is %s\n", dev->board.name); /* set the direction for GPIO pins */ cx231xx_set_gpio_direction(dev, dev->board.tuner_gpio->bit, 1); cx231xx_set_gpio_value(dev, dev->board.tuner_gpio->bit, 1); @@ -311,27 +310,11 @@ void cx231xx_card_setup(struct cx231xx *dev) if (cx231xx_boards[dev->model].tuner_addr) dev->tuner_addr = cx231xx_boards[dev->model].tuner_addr; - cx231xx_info(": tuner type %d, tuner address %d \n", - dev->tuner_type, dev->tuner_addr); - - /* Do card specific if any */ - switch (dev->model) { - case CX231XX_BOARD_CNXT_RDE_250: - /* do card specific GPIO settings if required */ - cx231xx_info("Board is Conexant RDE 250\n"); - break; - case CX231XX_BOARD_CNXT_RDU_250: - /* do card specific GPIO settings if required */ - cx231xx_info("Board is Conexant RDU 250\n"); - break; - } - /* request some modules */ if (dev->board.decoder == CX231XX_AVDECODER) { - cx231xx_info(": Requesting cx25840 module\n"); dev->sd_cx25840 = v4l2_i2c_new_subdev(&dev->i2c_bus[0].i2c_adap, - "cx25840", "cx25840", 0x88 >> 1); + "cx25840", "cx25840", 0x88 >> 1); if (dev->sd_cx25840 == NULL) cx231xx_info("cx25840 subdev registration failure\n"); cx25840_call(dev, core, init, 0); @@ -339,7 +322,6 @@ void cx231xx_card_setup(struct cx231xx *dev) } if (dev->board.tuner_type != TUNER_ABSENT) { - cx231xx_info(": Requesting Tuner module\n"); dev->sd_tuner = v4l2_i2c_new_subdev(&dev->i2c_bus[1].i2c_adap, "tuner", "tuner", 0xc2 >> 1); diff --git a/linux/drivers/media/video/cx231xx/cx231xx-core.c b/linux/drivers/media/video/cx231xx/cx231xx-core.c index 405819ac1..70478aa8b 100644 --- a/linux/drivers/media/video/cx231xx/cx231xx-core.c +++ b/linux/drivers/media/video/cx231xx/cx231xx-core.c @@ -125,7 +125,7 @@ int cx231xx_register_extension(struct cx231xx_ops *ops) if (dev) ops->init(dev); } - cx231xx_info("Cx231xx: Initialized (%s) extension\n", ops->name); + printk(KERN_INFO DRIVER_NAME ": %s initialized\n", ops->name); mutex_unlock(&cx231xx_extension_devlist_lock); mutex_unlock(&cx231xx_devlist_mutex); return 0; @@ -143,7 +143,7 @@ void cx231xx_unregister_extension(struct cx231xx_ops *ops) } mutex_lock(&cx231xx_extension_devlist_lock); - cx231xx_info("Cx231xx: Removed (%s) extension\n", ops->name); + printk(KERN_INFO DRIVER_NAME ": %s removed\n", ops->name); list_del(&ops->next); mutex_unlock(&cx231xx_extension_devlist_lock); mutex_unlock(&cx231xx_devlist_mutex); diff --git a/linux/drivers/media/video/cx231xx/cx231xx-i2c.c b/linux/drivers/media/video/cx231xx/cx231xx-i2c.c index c87203f80..d196fe666 100644 --- a/linux/drivers/media/video/cx231xx/cx231xx-i2c.c +++ b/linux/drivers/media/video/cx231xx/cx231xx-i2c.c @@ -521,8 +521,6 @@ int cx231xx_i2c_register(struct cx231xx_i2c *bus) BUG_ON(!dev->cx231xx_send_usb_command); - cx231xx_info("%s(bus = %d)\n", __func__, bus->nr); - memcpy(&bus->i2c_adap, &cx231xx_adap_template, sizeof(bus->i2c_adap)); memcpy(&bus->i2c_algo, &cx231xx_algo, sizeof(bus->i2c_algo)); memcpy(&bus->i2c_client, &cx231xx_client_template, @@ -540,7 +538,6 @@ int cx231xx_i2c_register(struct cx231xx_i2c *bus) bus->i2c_client.adapter = &bus->i2c_adap; if (0 == bus->i2c_rc) { - cx231xx_info("%s: i2c bus %d registered\n", dev->name, bus->nr); if (i2c_scan) cx231xx_do_i2c_scan(dev, &bus->i2c_client); } else diff --git a/linux/drivers/media/video/cx231xx/cx231xx-video.c b/linux/drivers/media/video/cx231xx/cx231xx-video.c index 144eb9dd7..5ca747ffe 100644 --- a/linux/drivers/media/video/cx231xx/cx231xx-video.c +++ b/linux/drivers/media/video/cx231xx/cx231xx-video.c @@ -2353,8 +2353,6 @@ int cx231xx_register_analog_devices(struct cx231xx *dev) { int ret; - cx231xx_info("%s()\n", __func__); - cx231xx_info("%s: v4l2 driver version %d.%d.%d\n", dev->name, (CX231XX_VERSION_CODE >> 16) & 0xff, -- cgit v1.2.3 From 1b7ec081b57402bbfb04a1e04dc14739f9b8262a Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 22 Mar 2009 08:53:36 -0300 Subject: cx231xx: use usb_make_path() for bus_info From: Mauro Carvalho Chehab VIDIOC_QUERYCAP should return the proper bus info. In the case of USB, this should be generated by usb_make_path(), being something like: usb-0000:00:1d.7-2 Priority: normal CC: Srinivasa Deevi Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/cx231xx/cx231xx-video.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/cx231xx/cx231xx-video.c b/linux/drivers/media/video/cx231xx/cx231xx-video.c index 5ca747ffe..d53ddcb6a 100644 --- a/linux/drivers/media/video/cx231xx/cx231xx-video.c +++ b/linux/drivers/media/video/cx231xx/cx231xx-video.c @@ -1640,8 +1640,7 @@ static int vidioc_querycap(struct file *file, void *priv, strlcpy(cap->driver, "cx231xx", sizeof(cap->driver)); strlcpy(cap->card, cx231xx_boards[dev->model].name, sizeof(cap->card)); - strlcpy(cap->bus_info, dev->v4l2_dev.name, - sizeof(cap->bus_info)); + usb_make_path(dev->udev, cap->bus_info, sizeof(cap->bus_info)); cap->version = CX231XX_VERSION_CODE; -- cgit v1.2.3 From 738f0a744e7ac46dabf075a1f1a0e707ad74e207 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Sun, 22 Mar 2009 20:29:36 +0100 Subject: gspca - t613: Bad sensor detection. From: Jean-Francois Moine Priority: normal Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/t613.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/t613.c b/linux/drivers/media/video/gspca/t613.c index f60a4c21a..0a39646b2 100644 --- a/linux/drivers/media/video/gspca/t613.c +++ b/linux/drivers/media/video/gspca/t613.c @@ -679,7 +679,7 @@ static int sd_init(struct gspca_dev *gspca_dev) sensor_id = (reg_r(gspca_dev, 0x06) << 8) | reg_r(gspca_dev, 0x07); - switch (sensor_id) { + switch (sensor_id & 0xff0f) { case 0x0801: PDEBUG(D_PROBE, "sensor tas5130a"); sd->sensor = SENSOR_TAS5130A; -- cgit v1.2.3 From b2a097ac68d1d5ce536f91c9205395aabafbe437 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Sun, 22 Mar 2009 20:30:42 +0100 Subject: gspca - t613: Don't re-read the ID registers at probe time. From: Jean-Francois Moine Priority: normal Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/t613.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/t613.c b/linux/drivers/media/video/gspca/t613.c index 0a39646b2..8e5804f08 100644 --- a/linux/drivers/media/video/gspca/t613.c +++ b/linux/drivers/media/video/gspca/t613.c @@ -639,7 +639,7 @@ static int sd_init(struct gspca_dev *gspca_dev) u16 reg80, reg8e; static const u8 read_indexs[] = - { 0x06, 0x07, 0x0a, 0x0b, 0x66, 0x80, 0x81, 0x8e, 0x8f, 0xa5, + { 0x0a, 0x0b, 0x66, 0x80, 0x81, 0x8e, 0x8f, 0xa5, 0xa6, 0xa8, 0xbb, 0xbc, 0xc6, 0x00 }; static const u8 n1[] = {0x08, 0x03, 0x09, 0x03, 0x12, 0x04}; -- cgit v1.2.3 From 3fe3dd84be3eb0c545bc5a5291d606334fc7ffdb Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Sun, 22 Mar 2009 20:31:32 +0100 Subject: gspca - t613: Greater delay after om6802 reset. From: Jean-Francois Moine Priority: normal Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/t613.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/t613.c b/linux/drivers/media/video/gspca/t613.c index 8e5804f08..f6ff3e1ea 100644 --- a/linux/drivers/media/video/gspca/t613.c +++ b/linux/drivers/media/video/gspca/t613.c @@ -495,7 +495,7 @@ static void om6802_sensor_init(struct gspca_dev *gspca_dev) }; reg_w_buf(gspca_dev, sensor_reset, sizeof sensor_reset); - msleep(5); + msleep(100); i = 4; while (--i > 0) { byte = reg_r(gspca_dev, 0x0060); -- cgit v1.2.3 From 096cd688dacfd3e526a50a19f7bfcd5f9e92e2bc Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Sun, 22 Mar 2009 20:33:47 +0100 Subject: gspca - vc032x: Change the probe sequence. From: Jean-Francois Moine Priority: normal Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/vc032x.c | 79 ++++++++++++++++++++++++-------- 1 file changed, 59 insertions(+), 20 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/vc032x.c b/linux/drivers/media/video/gspca/vc032x.c index f1c149476..581cbff38 100644 --- a/linux/drivers/media/video/gspca/vc032x.c +++ b/linux/drivers/media/video/gspca/vc032x.c @@ -1903,26 +1903,54 @@ static const __u8 po1200_initVGA_data[][4] = { }; struct sensor_info { - int sensorId; - __u8 I2cAdd; - __u8 IdAdd; - __u16 VpId; - __u8 m1; - __u8 m2; - __u8 op; - }; + s8 sensorId; + u8 I2cAdd; + u8 IdAdd; + u16 VpId; + u8 m1; + u8 m2; + u8 op; +}; static const struct sensor_info sensor_info_data[] = { /* sensorId, I2cAdd, IdAdd, VpId, m1, m2, op */ +#if 1 + {-1, 0x80 | 0x30, 0x0a, 0x0000, 0x25, 0x24, 0x05}, + {-1, 0x80 | 0x20, 0x82, 0x0000, 0x24, 0x25, 0x01}, +/* (tested in vc032x_probe_sensor) */ +/* {-1, 0x80 | 0x20, 0x83, 0x0000, 0x24, 0x25, 0x01}, */ + {SENSOR_PO3130NC, 0x80 | 0x76, 0x00, 0x3130, 0x24, 0x25, 0x01}, + {SENSOR_MI1310_SOC, 0x80 | 0x5d, 0x00, 0x143a, 0x24, 0x25, 0x01}, +/* (tested in vc032x_probe_sensor) */ +/* {SENSOR_MI0360, 0x80 | 0x5d, 0x00, 0x8243, 0x24, 0x25, 0x01}, */ + {SENSOR_HV7131R, 0x80 | 0x11, 0x00, 0x0209, 0x24, 0x25, 0x01}, + {-1, 0x80 | 0x21, 0x0a, 0x0000, 0x21, 0x20, 0x05}, + {-1, 0x80 | 0x40, 0x00, 0x0000, 0x20, 0x22, 0x05}, + {SENSOR_OV7660, 0x80 | 0x21, 0x0a, 0x7660, 0x26, 0x26, 0x05}, +/* {SENSOR_PO3130NC, 0x80 | 0x76, 0x00, 0x0000, 0x24, 0x25, 0x01}, */ + {-1, 0x80 | 0x6e, 0x00, 0x0000, 0x24, 0x25, 0x01}, +/* {SENSOR_MI1310_SOC, 0x80 | 0x5d, 0x00, 0x0000, 0x24, 0x25, 0x01}, */ +/* {-1, 0x80 | 0x30, 0x0a, 0x0000, 0x25, 0x24, 0x05}, */ + {-1, 0x80 | 0x11, 0x39, 0x0000, 0x24, 0x25, 0x01}, + {SENSOR_PO1200, 0x80 | 0x5c, 0x00, 0x1200, 0x67, 0x67, 0x01}, + {-1, 0x80 | 0x2d, 0x00, 0x0000, 0x65, 0x67, 0x01}, + {-1, 0x80 | 0x6e, 0x00, 0x0000, 0x24, 0x25, 0x01}, + {-1, 0x80 | 0x56, 0x01, 0x0000, 0x64, 0x67, 0x01}, + {-1, 0x80 | 0x48, 0x00, 0x0000, 0x64, 0x67, 0x01}, +/*fixme: not in the ms-win probe - may be found before?*/ + {SENSOR_MI1320, 0x80 | 0x48, 0x00, 0x148c, 0x64, 0x65, 0x01}, + {SENSOR_OV7670, 0x80 | 0x21, 0x0a, 0x7673, 0x66, 0x67, 0x05}, +#else {SENSOR_HV7131R, 0x80 | 0x11, 0x00, 0x0209, 0x24, 0x25, 0x01}, {SENSOR_OV7660, 0x80 | 0x21, 0x0a, 0x7660, 0x26, 0x26, 0x05}, {SENSOR_PO3130NC, 0x80 | 0x76, 0x00, 0x3130, 0x24, 0x25, 0x01}, - {SENSOR_MI1320, 0x80 | 0xc8, 0x00, 0x148c, 0x64, 0x65, 0x01}, + {SENSOR_MI1320, 0x80 | 0x48, 0x00, 0x148c, 0x64, 0x65, 0x01}, {SENSOR_OV7670, 0x80 | 0x21, 0x0a, 0x7673, 0x66, 0x67, 0x05}, {SENSOR_MI1310_SOC, 0x80 | 0x5d, 0x00, 0x143a, 0x24, 0x25, 0x01}, /* (tested in vc032x_probe_sensor) */ /* {SENSOR_MI0360, 0x80 | 0x5d, 0x00, 0x8243, 0x24, 0x25, 0x01}, */ {SENSOR_PO1200, 0x80 | 0x5c, 0x00, 0x1200, 0x67, 0x67, 0x01}, +#endif }; /* read 'len' bytes in gspca_dev->usb_buf */ @@ -1957,7 +1985,7 @@ static u16 read_sensor_register(struct gspca_dev *gspca_dev, u16 address) { struct usb_device *dev = gspca_dev->dev; - __u8 ldata, mdata, hdata; + u8 ldata, mdata, hdata; int retry = 50; reg_r(gspca_dev, 0xa1, 0xb33f, 1); @@ -1970,9 +1998,11 @@ static u16 read_sensor_register(struct gspca_dev *gspca_dev, reg_w(dev, 0xa0, 0x02, 0xb339); do { - msleep(8); reg_r(gspca_dev, 0xa1, 0xb33b, 1); - } while (retry-- && gspca_dev->usb_buf[0]); + if (gspca_dev->usb_buf[0] == 0x00) + break; + msleep(40); + } while (--retry >= 0); reg_r(gspca_dev, 0xa1, 0xb33e, 1); ldata = gspca_dev->usb_buf[0]; @@ -1993,7 +2023,7 @@ static int vc032x_probe_sensor(struct gspca_dev *gspca_dev) { struct usb_device *dev = gspca_dev->dev; int i; - __u16 value; + u16 value; const struct sensor_info *ptsensor_info; reg_r(gspca_dev, 0xa1, 0xbfcf, 1); @@ -2008,13 +2038,22 @@ static int vc032x_probe_sensor(struct gspca_dev *gspca_dev) reg_w(dev, 0xa0, ptsensor_info->I2cAdd, 0xb335); reg_w(dev, 0xa0, ptsensor_info->op, 0xb301); value = read_sensor_register(gspca_dev, ptsensor_info->IdAdd); - if (value == ptsensor_info->VpId) - return ptsensor_info->sensorId; - - /* special case for MI0360 */ - if (ptsensor_info->sensorId == SENSOR_MI1310_SOC - && value == 0x8243) - return SENSOR_MI0360; + if (value == 0 && ptsensor_info->IdAdd == 0x82) + value = read_sensor_register(gspca_dev, 0x83); + if (value != 0) { + PDEBUG(D_ERR|D_PROBE, "Sensor ID %04x (%d)", + value, i); + if (value == ptsensor_info->VpId) + return ptsensor_info->sensorId; + + switch (value) { + case 0x7673: + return SENSOR_OV7670; + case 0x8243: + return SENSOR_MI0360; + } +/*fixme: should return here*/ + } } return -1; } -- cgit v1.2.3 From 95a062b34a2c47e2c835863577939dee4d5e60a6 Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Sun, 22 Mar 2009 21:58:46 -0400 Subject: em28xx: add remote control definition for HVR-900 (both versions) From: Devin Heitmueller The HVR-900 did not have a remote control defined, so it would not work. Add the line for both versions of the product. Thanks to Jens-Michael Hoffmann (#linuxtv user "jmho") for pointing out the issue and testing the patch. Priority: normal Signed-off-by: Devin Heitmueller --- linux/drivers/media/video/em28xx/em28xx-cards.c | 2 ++ 1 file changed, 2 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 fcb8131e6..6b4a204a9 100644 --- a/linux/drivers/media/video/em28xx/em28xx-cards.c +++ b/linux/drivers/media/video/em28xx/em28xx-cards.c @@ -652,6 +652,7 @@ struct em28xx_board em28xx_boards[] = { .mts_firmware = 1, .has_dvb = 1, .dvb_gpio = hauppauge_wintv_hvr_900_digital, + .ir_codes = ir_codes_hauppauge_new, .decoder = EM28XX_TVP5150, .input = { { .type = EM28XX_VMUX_TELEVISION, @@ -676,6 +677,7 @@ struct em28xx_board em28xx_boards[] = { .tuner_type = TUNER_XC2028, .tuner_gpio = default_tuner_gpio, .mts_firmware = 1, + .ir_codes = ir_codes_hauppauge_new, .decoder = EM28XX_TVP5150, #if 0 /* FIXME: add an entry at em28xx-dvb */ .has_dvb = 1, -- cgit v1.2.3 From 2413031a7724106ce8294abc566587691b04dc25 Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Sun, 22 Mar 2009 22:39:12 -0400 Subject: usbvision: fix oops on ARM platform when allocating transfer buffers From: Devin Heitmueller Add missing URB_NO_TRANSFER_DMA_MAP flag, since the use of consistent memory is not permitted for DMA on the ARM platform. Thanks to Paul Thomas for providing sample ARM hardware that was experiencing the oops (tested on the at91rm9200 based LinuxStamp). Thanks to David Brownell for providing insight into the ARM memory architecture. Priority: normal Signed-off-by: Devin Heitmueller --- linux/drivers/media/video/usbvision/usbvision-core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/usbvision/usbvision-core.c b/linux/drivers/media/video/usbvision/usbvision-core.c index 7fe361668..734df263f 100644 --- a/linux/drivers/media/video/usbvision/usbvision-core.c +++ b/linux/drivers/media/video/usbvision/usbvision-core.c @@ -2524,7 +2524,7 @@ int usbvision_init_isoc(struct usb_usbvision *usbvision) urb->dev = dev; urb->context = usbvision; urb->pipe = usb_rcvisocpipe(dev, usbvision->video_endp); - urb->transfer_flags = URB_ISO_ASAP; + urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP; urb->interval = 1; urb->transfer_buffer = usbvision->sbuf[bufIdx].data; urb->complete = usbvision_isocIrq; -- cgit v1.2.3 From 81fd7559efe367f3a8ce4f4e2ff0b90d6688b724 Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Sun, 22 Mar 2009 22:41:28 -0400 Subject: em28xx: fix oops on ARM platform when allocating transfer buffers From: Devin Heitmueller Add missing URB_NO_TRANSFER_DMA_MAP flag, since the use of consistent memory is not permitted for DMA on the ARM platform. Thanks to Paul Thomas for providing sample ARM hardware that was experiencing the oops (tested on the at91rm9200 based LinuxStamp). Thanks to David Brownell for providing insight into the ARM memory architecture. Priority: high Signed-off-by: Devin Heitmueller --- linux/drivers/media/video/em28xx/em28xx-core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (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 0d4c9fcc2..4edd3870e 100644 --- a/linux/drivers/media/video/em28xx/em28xx-core.c +++ b/linux/drivers/media/video/em28xx/em28xx-core.c @@ -991,7 +991,7 @@ int em28xx_init_isoc(struct em28xx *dev, int max_packets, em28xx_irq_callback, dma_q, 1); urb->number_of_packets = max_packets; - urb->transfer_flags = URB_ISO_ASAP; + urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP; k = 0; for (j = 0; j < max_packets; j++) { -- cgit v1.2.3 From 67db6dc70c25afa359db09bf6ca885caebfb5a62 Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Sun, 22 Mar 2009 22:42:26 -0400 Subject: au0828: fix oops on ARM platform when allocating transfer buffers From: Devin Heitmueller Add missing URB_NO_TRANSFER_DMA_MAP flag, since the use of consistent memory is not permitted for DMA on the ARM platform. Thanks to Paul Thomas for providing sample ARM hardware that was experiencing the oops (tested on the at91rm9200 based LinuxStamp). Thanks to David Brownell for providing insight into the ARM memory architecture. Priority: normal Signed-off-by: Devin Heitmueller --- linux/drivers/media/video/au0828/au0828-video.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (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 fc76b2e20..5eac5cde5 100644 --- a/linux/drivers/media/video/au0828/au0828-video.c +++ b/linux/drivers/media/video/au0828/au0828-video.c @@ -273,7 +273,7 @@ int au0828_init_isoc(struct au0828_dev *dev, int max_packets, au0828_irq_callback, dma_q, 1); urb->number_of_packets = max_packets; - urb->transfer_flags = URB_ISO_ASAP; + urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP; k = 0; for (j = 0; j < max_packets; j++) { -- cgit v1.2.3 From 7218ee25243cf0fb19b66fb1068a900bb49ba9d6 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Mon, 23 Mar 2009 10:03:52 +0100 Subject: gspca - vc032x: New sensor mi1320_soc and webcam 15b8:6001 added. From: Jean-Francois Moine Priority: normal Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/vc032x.c | 427 ++++++++++++++++++++++++++++++- 1 file changed, 415 insertions(+), 12 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/vc032x.c b/linux/drivers/media/video/gspca/vc032x.c index 581cbff38..81d2054b5 100644 --- a/linux/drivers/media/video/gspca/vc032x.c +++ b/linux/drivers/media/video/gspca/vc032x.c @@ -43,12 +43,13 @@ struct sd { char sensor; #define SENSOR_HV7131R 0 #define SENSOR_MI0360 1 -#define SENSOR_MI1320 2 -#define SENSOR_MI1310_SOC 3 -#define SENSOR_OV7660 4 -#define SENSOR_OV7670 5 -#define SENSOR_PO1200 6 -#define SENSOR_PO3130NC 7 +#define SENSOR_MI1310_SOC 2 +#define SENSOR_MI1320 3 +#define SENSOR_MI1320_SOC 4 +#define SENSOR_OV7660 5 +#define SENSOR_OV7670 6 +#define SENSOR_PO1200 7 +#define SENSOR_PO3130NC 8 }; /* V4L2 controls supported by the driver */ @@ -149,7 +150,7 @@ static const struct v4l2_pix_format vc0323_mode[] = { .sizeimage = 640 * 480 * 3 / 8 + 590, .colorspace = V4L2_COLORSPACE_JPEG, .priv = 0}, - {1280, 1024, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, /* mi1310_soc only */ + {1280, 1024, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, /* mi13x0_soc only */ .bytesperline = 1280, .sizeimage = 1280 * 1024 * 1 / 4 + 590, .colorspace = V4L2_COLORSPACE_JPEG, @@ -891,6 +892,383 @@ static const __u8 mi1320_initQVGA_data[][4] = { {} }; +static const u8 mi1320_soc_InitVGA_JPG[][4] = { + {0xb3, 0x01, 0x01, 0xcc}, + {0xb0, 0x03, 0x19, 0xcc}, + {0xb0, 0x04, 0x02, 0xcc}, + {0x00, 0x00, 0x30, 0xdd}, + {0xb3, 0x00, 0x64, 0xcc}, + {0xb3, 0x00, 0x67, 0xcc}, + {0xb3, 0x05, 0x01, 0xcc}, + {0xb3, 0x06, 0x01, 0xcc}, + {0xb3, 0x08, 0x01, 0xcc}, + {0xb3, 0x09, 0x0c, 0xcc}, + {0xb3, 0x34, 0x02, 0xcc}, + {0xb3, 0x35, 0xc8, 0xcc}, + {0xb3, 0x02, 0x00, 0xcc}, + {0xb3, 0x03, 0x0a, 0xcc}, + {0xb3, 0x04, 0x05, 0xcc}, + {0xb3, 0x20, 0x00, 0xcc}, + {0xb3, 0x21, 0x00, 0xcc}, + {0xb3, 0x22, 0x01, 0xcc}, + {0xb3, 0x23, 0xe0, 0xcc}, + {0xb3, 0x14, 0x00, 0xcc}, + {0xb3, 0x15, 0x00, 0xcc}, + {0xb3, 0x16, 0x02, 0xcc}, + {0xb3, 0x17, 0x7f, 0xcc}, + {0xb3, 0x00, 0x67, 0xcc}, + {0xb8, 0x00, 0x00, 0xcc}, + {0xbc, 0x00, 0x71, 0xcc}, + {0xbc, 0x01, 0x01, 0xcc}, + {0xb3, 0x5c, 0x01, 0xcc}, + {0xf0, 0x00, 0x02, 0xbb}, + {0x00, 0x00, 0x10, 0xdd}, + {0xc8, 0x00, 0x00, 0xbb}, + {0x00, 0x00, 0x30, 0xdd}, + {0xf0, 0x00, 0x00, 0xbb}, + {0x00, 0x00, 0x10, 0xdd}, + {0x07, 0x00, 0xe0, 0xbb}, + {0x08, 0x00, 0x0b, 0xbb}, + {0x21, 0x00, 0x0c, 0xbb}, + {0x20, 0x01, 0x03, 0xbb}, + {0xb6, 0x00, 0x00, 0xcc}, + {0xb6, 0x03, 0x02, 0xcc}, + {0xb6, 0x02, 0x80, 0xcc}, + {0xb6, 0x05, 0x01, 0xcc}, + {0xb6, 0x04, 0xe0, 0xcc}, + {0xb6, 0x12, 0xf8, 0xcc}, + {0xb6, 0x13, 0x05, 0xcc}, + {0xb6, 0x18, 0x02, 0xcc}, + {0xb6, 0x17, 0x58, 0xcc}, + {0xb6, 0x16, 0x00, 0xcc}, + {0xb6, 0x22, 0x12, 0xcc}, + {0xb6, 0x23, 0x0b, 0xcc}, + {0xbf, 0xc0, 0x39, 0xcc}, + {0xbf, 0xc1, 0x04, 0xcc}, + {0xbf, 0xcc, 0x00, 0xcc}, + {0xb3, 0x01, 0x41, 0xcc}, + {0xf0, 0x00, 0x00, 0xbb}, + {0x05, 0x01, 0x78, 0xbb}, + {0x06, 0x00, 0x11, 0xbb}, + {0x07, 0x01, 0x42, 0xbb}, + {0x08, 0x00, 0x11, 0xbb}, + {0x20, 0x01, 0x03, 0xbb}, + {0x21, 0x80, 0x00, 0xbb}, + {0x22, 0x0d, 0x0f, 0xbb}, + {0x24, 0x80, 0x00, 0xbb}, + {0x59, 0x00, 0xff, 0xbb}, + {0xf0, 0x00, 0x02, 0xbb}, + {0x39, 0x03, 0xca, 0xbb}, + {0x3a, 0x06, 0x80, 0xbb}, + {0x3b, 0x01, 0x52, 0xbb}, + {0x3c, 0x05, 0x40, 0xbb}, + {0x57, 0x01, 0x9c, 0xbb}, + {0x58, 0x01, 0xee, 0xbb}, + {0x59, 0x00, 0xf0, 0xbb}, + {0x5a, 0x01, 0x20, 0xbb}, + {0x5c, 0x1d, 0x17, 0xbb}, + {0x5d, 0x22, 0x1c, 0xbb}, + {0x64, 0x1e, 0x1c, 0xbb}, + {0x5b, 0x00, 0x00, 0xbb}, + {0xf0, 0x00, 0x02, 0xbb}, + {0x22, 0xa0, 0x78, 0xbb}, + {0x23, 0xa0, 0x78, 0xbb}, + {0x24, 0x7f, 0x00, 0xbb}, + {0x28, 0xea, 0x02, 0xbb}, + {0x29, 0x86, 0x7a, 0xbb}, + {0x5e, 0x52, 0x4c, 0xbb}, + {0x5f, 0x20, 0x24, 0xbb}, + {0x60, 0x00, 0x02, 0xbb}, + {0x02, 0x00, 0xee, 0xbb}, + {0x03, 0x39, 0x23, 0xbb}, + {0x04, 0x07, 0x24, 0xbb}, + {0x09, 0x00, 0xc0, 0xbb}, + {0x0a, 0x00, 0x79, 0xbb}, + {0x0b, 0x00, 0x04, 0xbb}, + {0x0c, 0x00, 0x5c, 0xbb}, + {0x0d, 0x00, 0xd9, 0xbb}, + {0x0e, 0x00, 0x53, 0xbb}, + {0x0f, 0x00, 0x21, 0xbb}, + {0x10, 0x00, 0xa4, 0xbb}, + {0x11, 0x00, 0xe5, 0xbb}, + {0x15, 0x00, 0x00, 0xbb}, + {0x16, 0x00, 0x00, 0xbb}, + {0x17, 0x00, 0x00, 0xbb}, + {0x18, 0x00, 0x00, 0xbb}, + {0x19, 0x00, 0x00, 0xbb}, + {0x1a, 0x00, 0x00, 0xbb}, + {0x1b, 0x00, 0x00, 0xbb}, + {0x1c, 0x00, 0x00, 0xbb}, + {0x1d, 0x00, 0x00, 0xbb}, + {0x1e, 0x00, 0x00, 0xbb}, + {0xf0, 0x00, 0x01, 0xbb}, + {0x06, 0xe0, 0x0e, 0xbb}, + {0x06, 0x60, 0x0e, 0xbb}, + {0xb3, 0x5c, 0x01, 0xcc}, + {} +}; +static const u8 mi1320_soc_InitQVGA_JPG[][4] = { + {0xb3, 0x01, 0x01, 0xcc}, + {0xb0, 0x03, 0x19, 0xcc}, + {0xb0, 0x04, 0x02, 0xcc}, + {0x00, 0x00, 0x30, 0xdd}, + {0xb3, 0x00, 0x64, 0xcc}, + {0xb3, 0x00, 0x67, 0xcc}, + {0xb3, 0x05, 0x01, 0xcc}, + {0xb3, 0x06, 0x01, 0xcc}, + {0xb3, 0x08, 0x01, 0xcc}, + {0xb3, 0x09, 0x0c, 0xcc}, + {0xb3, 0x34, 0x02, 0xcc}, + {0xb3, 0x35, 0xc8, 0xcc}, + {0xb3, 0x02, 0x00, 0xcc}, + {0xb3, 0x03, 0x0a, 0xcc}, + {0xb3, 0x04, 0x05, 0xcc}, + {0xb3, 0x20, 0x00, 0xcc}, + {0xb3, 0x21, 0x00, 0xcc}, + {0xb3, 0x22, 0x01, 0xcc}, + {0xb3, 0x23, 0xe0, 0xcc}, + {0xb3, 0x14, 0x00, 0xcc}, + {0xb3, 0x15, 0x00, 0xcc}, + {0xb3, 0x16, 0x02, 0xcc}, + {0xb3, 0x17, 0x7f, 0xcc}, + {0xb3, 0x00, 0x67, 0xcc}, + {0xb8, 0x00, 0x00, 0xcc}, + {0xbc, 0x00, 0xd1, 0xcc}, + {0xbc, 0x01, 0x01, 0xcc}, + {0xb3, 0x5c, 0x01, 0xcc}, + {0xf0, 0x00, 0x02, 0xbb}, + {0x00, 0x00, 0x10, 0xdd}, + {0xc8, 0x00, 0x00, 0xbb}, + {0x00, 0x00, 0x30, 0xdd}, + {0xf0, 0x00, 0x00, 0xbb}, + {0x00, 0x00, 0x10, 0xdd}, + {0x07, 0x00, 0xe0, 0xbb}, + {0x08, 0x00, 0x0b, 0xbb}, + {0x21, 0x00, 0x0c, 0xbb}, + {0x20, 0x01, 0x03, 0xbb}, + {0xb6, 0x00, 0x00, 0xcc}, + {0xb6, 0x03, 0x01, 0xcc}, + {0xb6, 0x02, 0x40, 0xcc}, + {0xb6, 0x05, 0x00, 0xcc}, + {0xb6, 0x04, 0xf0, 0xcc}, + {0xb6, 0x12, 0xf8, 0xcc}, + {0xb6, 0x13, 0x05, 0xcc}, + {0xb6, 0x18, 0x00, 0xcc}, + {0xb6, 0x17, 0x96, 0xcc}, + {0xb6, 0x16, 0x00, 0xcc}, + {0xb6, 0x22, 0x12, 0xcc}, + {0xb6, 0x23, 0x0b, 0xcc}, + {0xbf, 0xc0, 0x39, 0xcc}, + {0xbf, 0xc1, 0x04, 0xcc}, + {0xbf, 0xcc, 0x00, 0xcc}, + {0xbc, 0x02, 0x18, 0xcc}, + {0xbc, 0x03, 0x50, 0xcc}, + {0xbc, 0x04, 0x18, 0xcc}, + {0xbc, 0x05, 0x00, 0xcc}, + {0xbc, 0x06, 0x00, 0xcc}, + {0xbc, 0x08, 0x30, 0xcc}, + {0xbc, 0x09, 0x40, 0xcc}, + {0xbc, 0x0a, 0x10, 0xcc}, + {0xbc, 0x0b, 0x00, 0xcc}, + {0xbc, 0x0c, 0x00, 0xcc}, + {0xb3, 0x01, 0x41, 0xcc}, + {0xf0, 0x00, 0x00, 0xbb}, + {0x05, 0x01, 0x78, 0xbb}, + {0x06, 0x00, 0x11, 0xbb}, + {0x07, 0x01, 0x42, 0xbb}, + {0x08, 0x00, 0x11, 0xbb}, + {0x20, 0x01, 0x03, 0xbb}, + {0x21, 0x80, 0x00, 0xbb}, + {0x22, 0x0d, 0x0f, 0xbb}, + {0x24, 0x80, 0x00, 0xbb}, + {0x59, 0x00, 0xff, 0xbb}, + {0xf0, 0x00, 0x02, 0xbb}, + {0x39, 0x03, 0xca, 0xbb}, + {0x3a, 0x06, 0x80, 0xbb}, + {0x3b, 0x01, 0x52, 0xbb}, + {0x3c, 0x05, 0x40, 0xbb}, + {0x57, 0x01, 0x9c, 0xbb}, + {0x58, 0x01, 0xee, 0xbb}, + {0x59, 0x00, 0xf0, 0xbb}, + {0x5a, 0x01, 0x20, 0xbb}, + {0x5c, 0x1d, 0x17, 0xbb}, + {0x5d, 0x22, 0x1c, 0xbb}, + {0x64, 0x1e, 0x1c, 0xbb}, + {0x5b, 0x00, 0x00, 0xbb}, + {0xf0, 0x00, 0x02, 0xbb}, + {0x22, 0xa0, 0x78, 0xbb}, + {0x23, 0xa0, 0x78, 0xbb}, + {0x24, 0x7f, 0x00, 0xbb}, + {0x28, 0xea, 0x02, 0xbb}, + {0x29, 0x86, 0x7a, 0xbb}, + {0x5e, 0x52, 0x4c, 0xbb}, + {0x5f, 0x20, 0x24, 0xbb}, + {0x60, 0x00, 0x02, 0xbb}, + {0x02, 0x00, 0xee, 0xbb}, + {0x03, 0x39, 0x23, 0xbb}, + {0x04, 0x07, 0x24, 0xbb}, + {0x09, 0x00, 0xc0, 0xbb}, + {0x0a, 0x00, 0x79, 0xbb}, + {0x0b, 0x00, 0x04, 0xbb}, + {0x0c, 0x00, 0x5c, 0xbb}, + {0x0d, 0x00, 0xd9, 0xbb}, + {0x0e, 0x00, 0x53, 0xbb}, + {0x0f, 0x00, 0x21, 0xbb}, + {0x10, 0x00, 0xa4, 0xbb}, + {0x11, 0x00, 0xe5, 0xbb}, + {0x15, 0x00, 0x00, 0xbb}, + {0x16, 0x00, 0x00, 0xbb}, + {0x17, 0x00, 0x00, 0xbb}, + {0x18, 0x00, 0x00, 0xbb}, + {0x19, 0x00, 0x00, 0xbb}, + {0x1a, 0x00, 0x00, 0xbb}, + {0x1b, 0x00, 0x00, 0xbb}, + {0x1c, 0x00, 0x00, 0xbb}, + {0x1d, 0x00, 0x00, 0xbb}, + {0x1e, 0x00, 0x00, 0xbb}, + {0xf0, 0x00, 0x01, 0xbb}, + {0x06, 0xe0, 0x0e, 0xbb}, + {0x06, 0x60, 0x0e, 0xbb}, + {0xb3, 0x5c, 0x01, 0xcc}, + {} +}; +static const u8 mi1320_soc_InitSXGA_JPG[][4] = { + {0xb3, 0x01, 0x01, 0xcc}, + {0xb0, 0x03, 0x19, 0xcc}, + {0xb0, 0x04, 0x02, 0xcc}, + {0x00, 0x00, 0x33, 0xdd}, + {0xb3, 0x00, 0x64, 0xcc}, + {0xb3, 0x00, 0x67, 0xcc}, + {0xb3, 0x05, 0x00, 0xcc}, + {0xb3, 0x06, 0x00, 0xcc}, + {0xb3, 0x08, 0x01, 0xcc}, + {0xb3, 0x09, 0x0c, 0xcc}, + {0xb3, 0x34, 0x02, 0xcc}, + {0xb3, 0x35, 0xc8, 0xcc}, + {0xb3, 0x02, 0x00, 0xcc}, + {0xb3, 0x03, 0x0a, 0xcc}, + {0xb3, 0x04, 0x05, 0xcc}, + {0xb3, 0x20, 0x00, 0xcc}, + {0xb3, 0x21, 0x00, 0xcc}, + {0xb3, 0x22, 0x04, 0xcc}, + {0xb3, 0x23, 0x00, 0xcc}, + {0xb3, 0x14, 0x00, 0xcc}, + {0xb3, 0x15, 0x00, 0xcc}, + {0xb3, 0x16, 0x04, 0xcc}, + {0xb3, 0x17, 0xff, 0xcc}, + {0xb3, 0x00, 0x67, 0xcc}, + {0xbc, 0x00, 0x71, 0xcc}, + {0xbc, 0x01, 0x01, 0xcc}, + {0xf0, 0x00, 0x02, 0xbb}, + {0x00, 0x00, 0x30, 0xdd}, + {0xc8, 0x9f, 0x0b, 0xbb}, + {0x00, 0x00, 0x20, 0xdd}, + {0x5b, 0x00, 0x01, 0xbb}, + {0x00, 0x00, 0x20, 0xdd}, + {0xf0, 0x00, 0x00, 0xbb}, + {0x00, 0x00, 0x30, 0xdd}, + {0x20, 0x01, 0x03, 0xbb}, + {0x00, 0x00, 0x20, 0xdd}, + {0xb6, 0x00, 0x00, 0xcc}, + {0xb6, 0x03, 0x05, 0xcc}, + {0xb6, 0x02, 0x00, 0xcc}, + {0xb6, 0x05, 0x04, 0xcc}, + {0xb6, 0x04, 0x00, 0xcc}, + {0xb6, 0x12, 0xf8, 0xcc}, + {0xb6, 0x13, 0x29, 0xcc}, + {0xb6, 0x18, 0x0a, 0xcc}, + {0xb6, 0x17, 0x00, 0xcc}, + {0xb6, 0x16, 0x00, 0xcc}, + {0xb6, 0x22, 0x12, 0xcc}, + {0xb6, 0x23, 0x0b, 0xcc}, + {0xbf, 0xc0, 0x39, 0xcc}, + {0xbf, 0xc1, 0x04, 0xcc}, + {0xbf, 0xcc, 0x00, 0xcc}, + {0xb3, 0x5c, 0x01, 0xcc}, + {0xb3, 0x01, 0x41, 0xcc}, + {0xf0, 0x00, 0x00, 0xbb}, + {0x05, 0x01, 0x78, 0xbb}, + {0x06, 0x00, 0x11, 0xbb}, + {0x07, 0x01, 0x42, 0xbb}, + {0x08, 0x00, 0x11, 0xbb}, + {0x20, 0x01, 0x03, 0xbb}, + {0x21, 0x80, 0x00, 0xbb}, + {0x22, 0x0d, 0x0f, 0xbb}, + {0x24, 0x80, 0x00, 0xbb}, + {0x59, 0x00, 0xff, 0xbb}, + {0xf0, 0x00, 0x02, 0xbb}, + {0x39, 0x03, 0xca, 0xbb}, + {0x3a, 0x06, 0x80, 0xbb}, + {0x3b, 0x01, 0x52, 0xbb}, + {0x3c, 0x05, 0x40, 0xbb}, + {0x57, 0x01, 0x9c, 0xbb}, + {0x58, 0x01, 0xee, 0xbb}, + {0x59, 0x00, 0xf0, 0xbb}, + {0x5a, 0x01, 0x20, 0xbb}, + {0x5c, 0x1d, 0x17, 0xbb}, + {0x5d, 0x22, 0x1c, 0xbb}, + {0x64, 0x1e, 0x1c, 0xbb}, + {0x5b, 0x00, 0x00, 0xbb}, + {0xf0, 0x00, 0x02, 0xbb}, + {0x22, 0xa0, 0x78, 0xbb}, + {0x23, 0xa0, 0x78, 0xbb}, + {0x24, 0x7f, 0x00, 0xbb}, + {0x28, 0xea, 0x02, 0xbb}, + {0x29, 0x86, 0x7a, 0xbb}, + {0x5e, 0x52, 0x4c, 0xbb}, + {0x5f, 0x20, 0x24, 0xbb}, + {0x60, 0x00, 0x02, 0xbb}, + {0x02, 0x00, 0xee, 0xbb}, + {0x03, 0x39, 0x23, 0xbb}, + {0x04, 0x07, 0x24, 0xbb}, + {0x09, 0x00, 0xc0, 0xbb}, + {0x0a, 0x00, 0x79, 0xbb}, + {0x0b, 0x00, 0x04, 0xbb}, + {0x0c, 0x00, 0x5c, 0xbb}, + {0x0d, 0x00, 0xd9, 0xbb}, + {0x0e, 0x00, 0x53, 0xbb}, + {0x0f, 0x00, 0x21, 0xbb}, + {0x10, 0x00, 0xa4, 0xbb}, + {0x11, 0x00, 0xe5, 0xbb}, + {0x15, 0x00, 0x00, 0xbb}, + {0x16, 0x00, 0x00, 0xbb}, + {0x17, 0x00, 0x00, 0xbb}, + {0x18, 0x00, 0x00, 0xbb}, + {0x19, 0x00, 0x00, 0xbb}, + {0x1a, 0x00, 0x00, 0xbb}, + {0x1b, 0x00, 0x00, 0xbb}, + {0x1c, 0x00, 0x00, 0xbb}, + {0x1d, 0x00, 0x00, 0xbb}, + {0x1e, 0x00, 0x00, 0xbb}, + {0xf0, 0x00, 0x01, 0xbb}, + {0x06, 0xe0, 0x0e, 0xbb}, + {0x06, 0x60, 0x0e, 0xbb}, + {0xb3, 0x5c, 0x01, 0xcc}, + {0xf0, 0x00, 0x00, 0xbb}, + {0x05, 0x01, 0x13, 0xbb}, + {0x06, 0x00, 0x11, 0xbb}, + {0x07, 0x00, 0x85, 0xbb}, + {0x08, 0x00, 0x27, 0xbb}, + {0x20, 0x01, 0x03, 0xbb}, + {0x21, 0x80, 0x00, 0xbb}, + {0x22, 0x0d, 0x0f, 0xbb}, + {0x24, 0x80, 0x00, 0xbb}, + {0x59, 0x00, 0xff, 0xbb}, + {0xf0, 0x00, 0x02, 0xbb}, + {0x39, 0x03, 0x0d, 0xbb}, + {0x3a, 0x06, 0x1b, 0xbb}, + {0x3b, 0x00, 0x95, 0xbb}, + {0x3c, 0x04, 0xdb, 0xbb}, + {0x57, 0x02, 0x00, 0xbb}, + {0x58, 0x02, 0x66, 0xbb}, + {0x59, 0x00, 0xff, 0xbb}, + {0x5a, 0x01, 0x33, 0xbb}, + {0x5c, 0x12, 0x0d, 0xbb}, + {0x5d, 0x16, 0x11, 0xbb}, + {0x64, 0x5e, 0x1c, 0xbb}, + {0x2f, 0x90, 0x00, 0xbb}, + {} +}; static const __u8 po3130_gamma[17] = { 0x00, 0x13, 0x38, 0x59, 0x79, 0x92, 0xa7, 0xb9, 0xc8, 0xd4, 0xdf, 0xe7, 0xee, 0xf4, 0xf9, 0xfc, 0xff @@ -1936,9 +2314,10 @@ static const struct sensor_info sensor_info_data[] = { {-1, 0x80 | 0x2d, 0x00, 0x0000, 0x65, 0x67, 0x01}, {-1, 0x80 | 0x6e, 0x00, 0x0000, 0x24, 0x25, 0x01}, {-1, 0x80 | 0x56, 0x01, 0x0000, 0x64, 0x67, 0x01}, - {-1, 0x80 | 0x48, 0x00, 0x0000, 0x64, 0x67, 0x01}, -/*fixme: not in the ms-win probe - may be found before?*/ + {SENSOR_MI1320_SOC, 0x80 | 0x48, 0x00, 0x148c, 0x64, 0x67, 0x01}, +/*fixme: previously detected?*/ {SENSOR_MI1320, 0x80 | 0x48, 0x00, 0x148c, 0x64, 0x65, 0x01}, +/*fixme: not in the ms-win probe - may be found before?*/ {SENSOR_OV7670, 0x80 | 0x21, 0x0a, 0x7673, 0x66, 0x67, 0x05}, #else {SENSOR_HV7131R, 0x80 | 0x11, 0x00, 0x0209, 0x24, 0x25, 0x01}, @@ -2180,6 +2559,9 @@ static int sd_config(struct gspca_dev *gspca_dev, case SENSOR_MI1320: PDEBUG(D_PROBE, "Find Sensor MI1320"); break; + case SENSOR_MI1320_SOC: + PDEBUG(D_PROBE, "Find Sensor MI1320_SOC"); + break; case SENSOR_OV7660: PDEBUG(D_PROBE, "Find Sensor OV7660"); break; @@ -2201,10 +2583,15 @@ static int sd_config(struct gspca_dev *gspca_dev, } else { if (sensor != SENSOR_PO1200) { cam->cam_mode = vc0323_mode; - if (sd->sensor != SENSOR_MI1310_SOC) + switch (sensor) { + case SENSOR_MI1310_SOC: + case SENSOR_MI1320_SOC: cam->nmodes = ARRAY_SIZE(vc0323_mode); - else /* no SXGA */ + break; + default: /* no SXGA */ cam->nmodes = ARRAY_SIZE(vc0323_mode) - 1; + break; + } } else { cam->cam_mode = svga_mode; cam->nmodes = ARRAY_SIZE(svga_mode); @@ -2364,7 +2751,7 @@ static int sd_start(struct gspca_dev *gspca_dev) init = mi1310_socinitVGA_JPG; /* 640x480 */ break; default: - init = mi1310_soc_InitSXGA_JPG; /* 1280xq024 */ + init = mi1310_soc_InitSXGA_JPG; /* 1280x1024 */ break; } break; @@ -2376,6 +2763,21 @@ static int sd_start(struct gspca_dev *gspca_dev) else init = mi1320_initVGA_data; /* 640x480 */ break; + case SENSOR_MI1320_SOC: + GammaT = mi1320_gamma; + MatrixT = mi1320_matrix; + switch (mode) { + case 1: + init = mi1320_soc_InitQVGA_JPG; /* 320x240 */ + break; + case 0: + init = mi1320_soc_InitVGA_JPG; /* 640x480 */ + break; + default: + init = mi1320_soc_InitSXGA_JPG; /* 1280x1024 */ + break; + } + break; case SENSOR_PO3130NC: GammaT = po3130_gamma; MatrixT = po3130_matrix; @@ -2584,6 +2986,7 @@ static const __devinitdata struct usb_device_id device_table[] = { {USB_DEVICE(0x0ac8, 0x0328), .driver_info = BRIDGE_VC0321}, {USB_DEVICE(0x0ac8, 0xc001), .driver_info = BRIDGE_VC0321}, {USB_DEVICE(0x0ac8, 0xc002), .driver_info = BRIDGE_VC0321}, + {USB_DEVICE(0x15b8, 0x6001), .driver_info = BRIDGE_VC0323}, {USB_DEVICE(0x15b8, 0x6002), .driver_info = BRIDGE_VC0323}, {USB_DEVICE(0x17ef, 0x4802), .driver_info = BRIDGE_VC0323}, {} -- cgit v1.2.3 From 4c868936aa339cd33061a3b0da82023c95f4aa7e Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 23 Mar 2009 19:00:18 +0100 Subject: ov7670: add missing delay.h include. From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/ov7670.c | 1 + 1 file changed, 1 insertion(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/ov7670.c b/linux/drivers/media/video/ov7670.c index 263f20669..7c97449fd 100644 --- a/linux/drivers/media/video/ov7670.c +++ b/linux/drivers/media/video/ov7670.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include -- cgit v1.2.3 From 160a63ae7b94800a275bb2b0d5f78b2be4d91b16 Mon Sep 17 00:00:00 2001 From: Janne Grunau Date: Mon, 23 Mar 2009 22:18:54 +0100 Subject: hdpvr: Fix build with Config_I2C not set From: Janne Grunau Priority: normal Signed-off-by: Janne Grunau --- linux/drivers/media/video/hdpvr/Makefile | 4 +++- linux/drivers/media/video/hdpvr/hdpvr-core.c | 9 ++++++--- 2 files changed, 9 insertions(+), 4 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/hdpvr/Makefile b/linux/drivers/media/video/hdpvr/Makefile index 79ad2e16c..e0230fcb2 100644 --- a/linux/drivers/media/video/hdpvr/Makefile +++ b/linux/drivers/media/video/hdpvr/Makefile @@ -1,4 +1,6 @@ -hdpvr-objs := hdpvr-control.o hdpvr-core.o hdpvr-i2c.o hdpvr-video.o +hdpvr-objs := hdpvr-control.o hdpvr-core.o hdpvr-video.o + +hdpvr-$(CONFIG_I2C) += hdpvr-i2c.o obj-$(CONFIG_VIDEO_HDPVR) += hdpvr.o diff --git a/linux/drivers/media/video/hdpvr/hdpvr-core.c b/linux/drivers/media/video/hdpvr/hdpvr-core.c index 4a2bbb72b..e96aed42d 100644 --- a/linux/drivers/media/video/hdpvr/hdpvr-core.c +++ b/linux/drivers/media/video/hdpvr/hdpvr-core.c @@ -348,13 +348,14 @@ static int hdpvr_probe(struct usb_interface *interface, goto error; } -#if 0 /* until i2c is working properly */ - retval = hdpvr_register_i2c_adapter(dev); +#ifdef CONFIG_I2C + /* until i2c is working properly */ + retval = 0; /* hdpvr_register_i2c_adapter(dev); */ if (retval < 0) { err("registering i2c adapter failed"); goto error; } -#endif +#endif /* CONFIG_I2C */ /* save our data pointer in this interface device */ usb_set_intfdata(interface, dev); @@ -396,12 +397,14 @@ static void hdpvr_disconnect(struct usb_interface *interface) mutex_unlock(&dev->io_mutex); /* deregister I2C adapter */ +#ifdef CONFIG_I2C mutex_lock(&dev->i2c_mutex); if (dev->i2c_adapter) i2c_del_adapter(dev->i2c_adapter); kfree(dev->i2c_adapter); dev->i2c_adapter = NULL; mutex_unlock(&dev->i2c_mutex); +#endif /* CONFIG_I2C */ atomic_dec(&dev_nr); -- cgit v1.2.3 From a69b6e2b1b07aa24a584f25b078452518aec72a9 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Tue, 24 Mar 2009 22:30:45 -0500 Subject: pvrusb2: Use v4l2_device_disconnect() From: Mike Isely Priority: normal Signed-off-by: Mike Isely --- linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c index 2e21181c3..bea17cd64 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -2694,10 +2694,7 @@ static void pvr2_hdw_remove_usb_stuff(struct pvr2_hdw *hdw) /* If we don't do this, then there will be a dangling struct device reference to our disappearing device persisting inside the V4L core... */ - if (hdw->v4l2_dev.dev) { - dev_set_drvdata(hdw->v4l2_dev.dev, NULL); - hdw->v4l2_dev.dev = NULL; - } + v4l2_device_disconnect(&hdw->v4l2_dev); hdw->usb_dev = NULL; hdw->usb_intf = NULL; pvr2_hdw_render_useless(hdw); -- cgit v1.2.3 From 996d759054f3a54df2a397c7e993f4e06e61d3dd Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Wed, 25 Mar 2009 11:04:11 +0100 Subject: gspca - vc032x: Simplify the i2c write function. From: Jean-Francois Moine Priority: normal Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/vc032x.c | 24 +++++------------------- 1 file changed, 5 insertions(+), 19 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/vc032x.c b/linux/drivers/media/video/gspca/vc032x.c index 81d2054b5..fbe89c7d1 100644 --- a/linux/drivers/media/video/gspca/vc032x.c +++ b/linux/drivers/media/video/gspca/vc032x.c @@ -2438,33 +2438,19 @@ static int vc032x_probe_sensor(struct gspca_dev *gspca_dev) } static void i2c_write(struct gspca_dev *gspca_dev, - __u8 reg, const __u8 *val, __u8 size) + u8 reg, const u8 *val, + u8 size) /* 1 or 2 */ { struct usb_device *dev = gspca_dev->dev; int retry; -#ifdef GSPCA_DEBUG - if (size > 3 || size < 1) - return; -#endif reg_r(gspca_dev, 0xa1, 0xb33f, 1); +/*fixme:should check if (!(gspca_dev->usb_buf[0] & 0x02)) error*/ reg_w(dev, 0xa0, size, 0xb334); reg_w(dev, 0xa0, reg, 0xb33a); - switch (size) { - case 1: - reg_w(dev, 0xa0, val[0], 0xb336); - break; - case 2: - reg_w(dev, 0xa0, val[0], 0xb336); - reg_w(dev, 0xa0, val[1], 0xb337); - break; - default: -/* case 3: */ - reg_w(dev, 0xa0, val[0], 0xb336); + reg_w(dev, 0xa0, val[0], 0xb336); + if (size > 1) reg_w(dev, 0xa0, val[1], 0xb337); - reg_w(dev, 0xa0, val[2], 0xb338); - break; - } reg_w(dev, 0xa0, 0x01, 0xb339); retry = 4; do { -- cgit v1.2.3 From b0e1c914cc6f72511a2c08f337329d20323ce11b Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Wed, 25 Mar 2009 11:06:29 +0100 Subject: gspca - vc032x: Use YVYU format for sensor mi1320_soc. From: Jean-Francois Moine Priority: normal Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/vc032x.c | 442 ++++++++++++++++++++++++++++--- 1 file changed, 412 insertions(+), 30 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/vc032x.c b/linux/drivers/media/video/gspca/vc032x.c index fbe89c7d1..772d18e70 100644 --- a/linux/drivers/media/video/gspca/vc032x.c +++ b/linux/drivers/media/video/gspca/vc032x.c @@ -37,6 +37,8 @@ struct sd { __u8 lightfreq; __u8 sharpness; + u8 image_offset; + char bridge; #define BRIDGE_VC0321 0 #define BRIDGE_VC0323 1 @@ -156,7 +158,44 @@ static const struct v4l2_pix_format vc0323_mode[] = { .colorspace = V4L2_COLORSPACE_JPEG, .priv = 2}, }; - +static const struct v4l2_pix_format bi_mode[] = { +/*fixme: jeg does not work + {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, + .bytesperline = 320, + .sizeimage = 320 * 240 * 3 / 8 + 590, + .colorspace = V4L2_COLORSPACE_JPEG, + .priv = 5}, +*/ + {320, 240, V4L2_PIX_FMT_YVYU, V4L2_FIELD_NONE, + .bytesperline = 320, + .sizeimage = 320 * 240 * 2, + .colorspace = V4L2_COLORSPACE_SRGB, + .priv = 4}, +/* + {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, + .bytesperline = 640, + .sizeimage = 640 * 480 * 3 / 8 + 590, + .colorspace = V4L2_COLORSPACE_JPEG, + .priv = 3}, +*/ + {640, 480, V4L2_PIX_FMT_YVYU, V4L2_FIELD_NONE, + .bytesperline = 640, + .sizeimage = 640 * 480 * 2, + .colorspace = V4L2_COLORSPACE_SRGB, + .priv = 2}, +/* + {1280, 1024, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, + .bytesperline = 1280, + .sizeimage = 1280 * 1024 * 1 / 4 + 590, + .colorspace = V4L2_COLORSPACE_JPEG, + .priv = 1}, +*/ + {1280, 1024, V4L2_PIX_FMT_YVYU, V4L2_FIELD_NONE, + .bytesperline = 1280, + .sizeimage = 1280 * 1024 * 2, + .colorspace = V4L2_COLORSPACE_SRGB, + .priv = 0}, +}; static const struct v4l2_pix_format svga_mode[] = { {800, 600, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, .bytesperline = 800, @@ -892,6 +931,109 @@ static const __u8 mi1320_initQVGA_data[][4] = { {} }; +static const u8 mi1320_soc_InitVGA[][4] = { + {0xb3, 0x01, 0x01, 0xcc}, + {0xb0, 0x03, 0x19, 0xcc}, + {0xb0, 0x04, 0x02, 0xcc}, + {0x00, 0x00, 0x30, 0xdd}, + {0xb3, 0x00, 0x64, 0xcc}, + {0xb3, 0x00, 0x67, 0xcc}, + {0xb3, 0x05, 0x01, 0xcc}, + {0xb3, 0x06, 0x01, 0xcc}, + {0xb3, 0x08, 0x01, 0xcc}, + {0xb3, 0x09, 0x0c, 0xcc}, + {0xb3, 0x34, 0x02, 0xcc}, + {0xb3, 0x35, 0xc8, 0xcc}, + {0xb3, 0x02, 0x00, 0xcc}, + {0xb3, 0x03, 0x0a, 0xcc}, + {0xb3, 0x04, 0x05, 0xcc}, + {0xb3, 0x20, 0x00, 0xcc}, + {0xb3, 0x21, 0x00, 0xcc}, + {0xb3, 0x22, 0x01, 0xcc}, + {0xb3, 0x23, 0xe0, 0xcc}, + {0xb3, 0x14, 0x00, 0xcc}, + {0xb3, 0x15, 0x00, 0xcc}, + {0xb3, 0x16, 0x02, 0xcc}, + {0xb3, 0x17, 0x7f, 0xcc}, + {0xb3, 0x00, 0x67, 0xcc}, + {0xb8, 0x00, 0x00, 0xcc}, + {0xbc, 0x00, 0x71, 0xcc}, + {0xbc, 0x01, 0x01, 0xcc}, + {0xb3, 0x5c, 0x01, 0xcc}, + {0xf0, 0x00, 0x02, 0xbb}, + {0x00, 0x00, 0x10, 0xdd}, + {0xc8, 0x00, 0x00, 0xbb}, + {0x00, 0x00, 0x30, 0xdd}, + {0xf0, 0x00, 0x00, 0xbb}, + {0x00, 0x00, 0x10, 0xdd}, + {0x07, 0x00, 0xe0, 0xbb}, + {0x08, 0x00, 0x0b, 0xbb}, + {0x21, 0x00, 0x0c, 0xbb}, + {0x20, 0x01, 0x03, 0xbb}, + {0xbf, 0xc0, 0x26, 0xcc}, + {0xbf, 0xc1, 0x02, 0xcc}, + {0xbf, 0xcc, 0x04, 0xcc}, + {0xb3, 0x01, 0x41, 0xcc}, + {0xf0, 0x00, 0x00, 0xbb}, + {0x05, 0x01, 0x78, 0xbb}, + {0x06, 0x00, 0x11, 0xbb}, + {0x07, 0x01, 0x42, 0xbb}, + {0x08, 0x00, 0x11, 0xbb}, + {0x20, 0x01, 0x03, 0xbb}, + {0x21, 0x80, 0x00, 0xbb}, + {0x22, 0x0d, 0x0f, 0xbb}, + {0x24, 0x80, 0x00, 0xbb}, + {0x59, 0x00, 0xff, 0xbb}, + {0xf0, 0x00, 0x02, 0xbb}, + {0x39, 0x03, 0xca, 0xbb}, + {0x3a, 0x06, 0x80, 0xbb}, + {0x3b, 0x01, 0x52, 0xbb}, + {0x3c, 0x05, 0x40, 0xbb}, + {0x57, 0x01, 0x9c, 0xbb}, + {0x58, 0x01, 0xee, 0xbb}, + {0x59, 0x00, 0xf0, 0xbb}, + {0x5a, 0x01, 0x20, 0xbb}, + {0x5c, 0x1d, 0x17, 0xbb}, + {0x5d, 0x22, 0x1c, 0xbb}, + {0x64, 0x1e, 0x1c, 0xbb}, + {0x5b, 0x00, 0x00, 0xbb}, + {0xf0, 0x00, 0x02, 0xbb}, + {0x22, 0xa0, 0x78, 0xbb}, + {0x23, 0xa0, 0x78, 0xbb}, + {0x24, 0x7f, 0x00, 0xbb}, + {0x28, 0xea, 0x02, 0xbb}, + {0x29, 0x86, 0x7a, 0xbb}, + {0x5e, 0x52, 0x4c, 0xbb}, + {0x5f, 0x20, 0x24, 0xbb}, + {0x60, 0x00, 0x02, 0xbb}, + {0x02, 0x00, 0xee, 0xbb}, + {0x03, 0x39, 0x23, 0xbb}, + {0x04, 0x07, 0x24, 0xbb}, + {0x09, 0x00, 0xc0, 0xbb}, + {0x0a, 0x00, 0x79, 0xbb}, + {0x0b, 0x00, 0x04, 0xbb}, + {0x0c, 0x00, 0x5c, 0xbb}, + {0x0d, 0x00, 0xd9, 0xbb}, + {0x0e, 0x00, 0x53, 0xbb}, + {0x0f, 0x00, 0x21, 0xbb}, + {0x10, 0x00, 0xa4, 0xbb}, + {0x11, 0x00, 0xe5, 0xbb}, + {0x15, 0x00, 0x00, 0xbb}, + {0x16, 0x00, 0x00, 0xbb}, + {0x17, 0x00, 0x00, 0xbb}, + {0x18, 0x00, 0x00, 0xbb}, + {0x19, 0x00, 0x00, 0xbb}, + {0x1a, 0x00, 0x00, 0xbb}, + {0x1b, 0x00, 0x00, 0xbb}, + {0x1c, 0x00, 0x00, 0xbb}, + {0x1d, 0x00, 0x00, 0xbb}, + {0x1e, 0x00, 0x00, 0xbb}, + {0xf0, 0x00, 0x01, 0xbb}, + {0x06, 0xe0, 0x0e, 0xbb}, + {0x06, 0x60, 0x0e, 0xbb}, + {0xb3, 0x5c, 0x01, 0xcc}, + {} +}; static const u8 mi1320_soc_InitVGA_JPG[][4] = { {0xb3, 0x01, 0x01, 0xcc}, {0xb0, 0x03, 0x19, 0xcc}, @@ -1007,6 +1149,119 @@ static const u8 mi1320_soc_InitVGA_JPG[][4] = { {0xb3, 0x5c, 0x01, 0xcc}, {} }; +static const u8 mi1320_soc_InitQVGA[][4] = { + {0xb3, 0x01, 0x01, 0xcc}, + {0xb0, 0x03, 0x19, 0xcc}, + {0xb0, 0x04, 0x02, 0xcc}, + {0x00, 0x00, 0x30, 0xdd}, + {0xb3, 0x00, 0x64, 0xcc}, + {0xb3, 0x00, 0x67, 0xcc}, + {0xb3, 0x05, 0x01, 0xcc}, + {0xb3, 0x06, 0x01, 0xcc}, + {0xb3, 0x08, 0x01, 0xcc}, + {0xb3, 0x09, 0x0c, 0xcc}, + {0xb3, 0x34, 0x02, 0xcc}, + {0xb3, 0x35, 0xc8, 0xcc}, + {0xb3, 0x02, 0x00, 0xcc}, + {0xb3, 0x03, 0x0a, 0xcc}, + {0xb3, 0x04, 0x05, 0xcc}, + {0xb3, 0x20, 0x00, 0xcc}, + {0xb3, 0x21, 0x00, 0xcc}, + {0xb3, 0x22, 0x01, 0xcc}, + {0xb3, 0x23, 0xe0, 0xcc}, + {0xb3, 0x14, 0x00, 0xcc}, + {0xb3, 0x15, 0x00, 0xcc}, + {0xb3, 0x16, 0x02, 0xcc}, + {0xb3, 0x17, 0x7f, 0xcc}, + {0xb3, 0x00, 0x67, 0xcc}, + {0xb8, 0x00, 0x00, 0xcc}, + {0xbc, 0x00, 0xd1, 0xcc}, + {0xbc, 0x01, 0x01, 0xcc}, + {0xb3, 0x5c, 0x01, 0xcc}, + {0xf0, 0x00, 0x02, 0xbb}, + {0x00, 0x00, 0x10, 0xdd}, + {0xc8, 0x00, 0x00, 0xbb}, + {0x00, 0x00, 0x30, 0xdd}, + {0xf0, 0x00, 0x00, 0xbb}, + {0x00, 0x00, 0x10, 0xdd}, + {0x07, 0x00, 0xe0, 0xbb}, + {0x08, 0x00, 0x0b, 0xbb}, + {0x21, 0x00, 0x0c, 0xbb}, + {0x20, 0x01, 0x03, 0xbb}, + {0xbf, 0xc0, 0x26, 0xcc}, + {0xbf, 0xc1, 0x02, 0xcc}, + {0xbf, 0xcc, 0x04, 0xcc}, + {0xbc, 0x02, 0x18, 0xcc}, + {0xbc, 0x03, 0x50, 0xcc}, + {0xbc, 0x04, 0x18, 0xcc}, + {0xbc, 0x05, 0x00, 0xcc}, + {0xbc, 0x06, 0x00, 0xcc}, + {0xbc, 0x08, 0x30, 0xcc}, + {0xbc, 0x09, 0x40, 0xcc}, + {0xbc, 0x0a, 0x10, 0xcc}, + {0xbc, 0x0b, 0x00, 0xcc}, + {0xbc, 0x0c, 0x00, 0xcc}, + {0xb3, 0x01, 0x41, 0xcc}, + {0xf0, 0x00, 0x00, 0xbb}, + {0x05, 0x01, 0x78, 0xbb}, + {0x06, 0x00, 0x11, 0xbb}, + {0x07, 0x01, 0x42, 0xbb}, + {0x08, 0x00, 0x11, 0xbb}, + {0x20, 0x01, 0x03, 0xbb}, + {0x21, 0x80, 0x00, 0xbb}, + {0x22, 0x0d, 0x0f, 0xbb}, + {0x24, 0x80, 0x00, 0xbb}, + {0x59, 0x00, 0xff, 0xbb}, + {0xf0, 0x00, 0x02, 0xbb}, + {0x39, 0x03, 0xca, 0xbb}, + {0x3a, 0x06, 0x80, 0xbb}, + {0x3b, 0x01, 0x52, 0xbb}, + {0x3c, 0x05, 0x40, 0xbb}, + {0x57, 0x01, 0x9c, 0xbb}, + {0x58, 0x01, 0xee, 0xbb}, + {0x59, 0x00, 0xf0, 0xbb}, + {0x5a, 0x01, 0x20, 0xbb}, + {0x5c, 0x1d, 0x17, 0xbb}, + {0x5d, 0x22, 0x1c, 0xbb}, + {0x64, 0x1e, 0x1c, 0xbb}, + {0x5b, 0x00, 0x00, 0xbb}, + {0xf0, 0x00, 0x02, 0xbb}, + {0x22, 0xa0, 0x78, 0xbb}, + {0x23, 0xa0, 0x78, 0xbb}, + {0x24, 0x7f, 0x00, 0xbb}, + {0x28, 0xea, 0x02, 0xbb}, + {0x29, 0x86, 0x7a, 0xbb}, + {0x5e, 0x52, 0x4c, 0xbb}, + {0x5f, 0x20, 0x24, 0xbb}, + {0x60, 0x00, 0x02, 0xbb}, + {0x02, 0x00, 0xee, 0xbb}, + {0x03, 0x39, 0x23, 0xbb}, + {0x04, 0x07, 0x24, 0xbb}, + {0x09, 0x00, 0xc0, 0xbb}, + {0x0a, 0x00, 0x79, 0xbb}, + {0x0b, 0x00, 0x04, 0xbb}, + {0x0c, 0x00, 0x5c, 0xbb}, + {0x0d, 0x00, 0xd9, 0xbb}, + {0x0e, 0x00, 0x53, 0xbb}, + {0x0f, 0x00, 0x21, 0xbb}, + {0x10, 0x00, 0xa4, 0xbb}, + {0x11, 0x00, 0xe5, 0xbb}, + {0x15, 0x00, 0x00, 0xbb}, + {0x16, 0x00, 0x00, 0xbb}, + {0x17, 0x00, 0x00, 0xbb}, + {0x18, 0x00, 0x00, 0xbb}, + {0x19, 0x00, 0x00, 0xbb}, + {0x1a, 0x00, 0x00, 0xbb}, + {0x1b, 0x00, 0x00, 0xbb}, + {0x1c, 0x00, 0x00, 0xbb}, + {0x1d, 0x00, 0x00, 0xbb}, + {0x1e, 0x00, 0x00, 0xbb}, + {0xf0, 0x00, 0x01, 0xbb}, + {0x06, 0xe0, 0x0e, 0xbb}, + {0x06, 0x60, 0x0e, 0xbb}, + {0xb3, 0x5c, 0x01, 0xcc}, + {} +}; static const u8 mi1320_soc_InitQVGA_JPG[][4] = { {0xb3, 0x01, 0x01, 0xcc}, {0xb0, 0x03, 0x19, 0xcc}, @@ -1269,6 +1524,129 @@ static const u8 mi1320_soc_InitSXGA_JPG[][4] = { {0x2f, 0x90, 0x00, 0xbb}, {} }; +static const u8 mi1320_soc_InitSXGA[][4] = { + {0xb3, 0x01, 0x01, 0xcc}, + {0xb0, 0x03, 0x19, 0xcc}, + {0x00, 0x00, 0x30, 0xdd}, + {0xb3, 0x00, 0x64, 0xcc}, + {0xb3, 0x00, 0x67, 0xcc}, + {0xb3, 0x05, 0x01, 0xcc}, + {0xb3, 0x06, 0x01, 0xcc}, + {0xb3, 0x08, 0x01, 0xcc}, + {0xb3, 0x09, 0x0c, 0xcc}, + {0xb3, 0x34, 0x02, 0xcc}, + {0xb3, 0x35, 0xc8, 0xcc}, + {0xb3, 0x02, 0x00, 0xcc}, + {0xb3, 0x03, 0x0a, 0xcc}, + {0xb3, 0x04, 0x05, 0xcc}, + {0xb3, 0x20, 0x00, 0xcc}, + {0xb3, 0x21, 0x00, 0xcc}, + {0xb3, 0x22, 0x04, 0xcc}, + {0xb3, 0x23, 0x00, 0xcc}, + {0xb3, 0x14, 0x00, 0xcc}, + {0xb3, 0x15, 0x00, 0xcc}, + {0xb3, 0x16, 0x04, 0xcc}, + {0xb3, 0x17, 0xff, 0xcc}, + {0xb3, 0x00, 0x67, 0xcc}, + {0xbc, 0x00, 0x71, 0xcc}, + {0xbc, 0x01, 0x01, 0xcc}, + {0xb3, 0x5c, 0x01, 0xcc}, + {0xf0, 0x00, 0x02, 0xbb}, + {0x00, 0x00, 0x30, 0xdd}, + {0xc8, 0x9f, 0x0b, 0xbb}, + {0x00, 0x00, 0x20, 0xdd}, + {0x5b, 0x00, 0x01, 0xbb}, + {0x00, 0x00, 0x20, 0xdd}, + {0xf0, 0x00, 0x00, 0xbb}, + {0x00, 0x00, 0x30, 0xdd}, + {0x20, 0x01, 0x03, 0xbb}, + {0x00, 0x00, 0x20, 0xdd}, + {0xbf, 0xc0, 0x26, 0xcc}, + {0xbf, 0xc1, 0x02, 0xcc}, + {0xbf, 0xcc, 0x04, 0xcc}, + {0xb3, 0x01, 0x41, 0xcc}, + {0xf0, 0x00, 0x00, 0xbb}, + {0x05, 0x01, 0x78, 0xbb}, + {0x06, 0x00, 0x11, 0xbb}, + {0x07, 0x01, 0x42, 0xbb}, + {0x08, 0x00, 0x11, 0xbb}, + {0x20, 0x01, 0x03, 0xbb}, + {0x21, 0x80, 0x00, 0xbb}, + {0x22, 0x0d, 0x0f, 0xbb}, + {0x24, 0x80, 0x00, 0xbb}, + {0x59, 0x00, 0xff, 0xbb}, + {0xf0, 0x00, 0x02, 0xbb}, + {0x39, 0x03, 0xca, 0xbb}, + {0x3a, 0x06, 0x80, 0xbb}, + {0x3b, 0x01, 0x52, 0xbb}, + {0x3c, 0x05, 0x40, 0xbb}, + {0x57, 0x01, 0x9c, 0xbb}, + {0x58, 0x01, 0xee, 0xbb}, + {0x59, 0x00, 0xf0, 0xbb}, + {0x5a, 0x01, 0x20, 0xbb}, + {0x5c, 0x1d, 0x17, 0xbb}, + {0x5d, 0x22, 0x1c, 0xbb}, + {0x64, 0x1e, 0x1c, 0xbb}, + {0x5b, 0x00, 0x00, 0xbb}, + {0xf0, 0x00, 0x02, 0xbb}, + {0x22, 0xa0, 0x78, 0xbb}, + {0x23, 0xa0, 0x78, 0xbb}, + {0x24, 0x7f, 0x00, 0xbb}, + {0x28, 0xea, 0x02, 0xbb}, + {0x29, 0x86, 0x7a, 0xbb}, + {0x5e, 0x52, 0x4c, 0xbb}, + {0x5f, 0x20, 0x24, 0xbb}, + {0x60, 0x00, 0x02, 0xbb}, + {0x02, 0x00, 0xee, 0xbb}, + {0x03, 0x39, 0x23, 0xbb}, + {0x04, 0x07, 0x24, 0xbb}, + {0x09, 0x00, 0xc0, 0xbb}, + {0x0a, 0x00, 0x79, 0xbb}, + {0x0b, 0x00, 0x04, 0xbb}, + {0x0c, 0x00, 0x5c, 0xbb}, + {0x0d, 0x00, 0xd9, 0xbb}, + {0x0e, 0x00, 0x53, 0xbb}, + {0x0f, 0x00, 0x21, 0xbb}, + {0x10, 0x00, 0xa4, 0xbb}, + {0x11, 0x00, 0xe5, 0xbb}, + {0x15, 0x00, 0x00, 0xbb}, + {0x16, 0x00, 0x00, 0xbb}, + {0x17, 0x00, 0x00, 0xbb}, + {0x18, 0x00, 0x00, 0xbb}, + {0x19, 0x00, 0x00, 0xbb}, + {0x1a, 0x00, 0x00, 0xbb}, + {0x1b, 0x00, 0x00, 0xbb}, + {0x1c, 0x00, 0x00, 0xbb}, + {0x1d, 0x00, 0x00, 0xbb}, + {0x1e, 0x00, 0x00, 0xbb}, + {0xf0, 0x00, 0x01, 0xbb}, + {0x06, 0xe0, 0x0e, 0xbb}, + {0x06, 0x60, 0x0e, 0xbb}, + {0xb3, 0x5c, 0x01, 0xcc}, + {0xf0, 0x00, 0x00, 0xbb}, + {0x05, 0x01, 0x13, 0xbb}, + {0x06, 0x00, 0x11, 0xbb}, + {0x07, 0x00, 0x85, 0xbb}, + {0x08, 0x00, 0x27, 0xbb}, + {0x20, 0x01, 0x03, 0xbb}, + {0x21, 0x80, 0x00, 0xbb}, + {0x22, 0x0d, 0x0f, 0xbb}, + {0x24, 0x80, 0x00, 0xbb}, + {0x59, 0x00, 0xff, 0xbb}, + {0xf0, 0x00, 0x02, 0xbb}, + {0x39, 0x03, 0x0d, 0xbb}, + {0x3a, 0x06, 0x1b, 0xbb}, + {0x3b, 0x00, 0x95, 0xbb}, + {0x3c, 0x04, 0xdb, 0xbb}, + {0x57, 0x02, 0x00, 0xbb}, + {0x58, 0x02, 0x66, 0xbb}, + {0x59, 0x00, 0xff, 0xbb}, + {0x5a, 0x01, 0x33, 0xbb}, + {0x5c, 0x12, 0x0d, 0xbb}, + {0x5d, 0x16, 0x11, 0xbb}, + {0x64, 0x5e, 0x1c, 0xbb}, + {} +}; static const __u8 po3130_gamma[17] = { 0x00, 0x13, 0x38, 0x59, 0x79, 0x92, 0xa7, 0xb9, 0xc8, 0xd4, 0xdf, 0xe7, 0xee, 0xf4, 0xf9, 0xfc, 0xff @@ -2567,20 +2945,23 @@ static int sd_config(struct gspca_dev *gspca_dev, cam->cam_mode = vc0321_mode; cam->nmodes = ARRAY_SIZE(vc0321_mode); } else { - if (sensor != SENSOR_PO1200) { - cam->cam_mode = vc0323_mode; - switch (sensor) { - case SENSOR_MI1310_SOC: - case SENSOR_MI1320_SOC: - cam->nmodes = ARRAY_SIZE(vc0323_mode); - break; - default: /* no SXGA */ - cam->nmodes = ARRAY_SIZE(vc0323_mode) - 1; - break; - } - } else { + switch (sensor) { + case SENSOR_PO1200: cam->cam_mode = svga_mode; cam->nmodes = ARRAY_SIZE(svga_mode); + break; + case SENSOR_MI1310_SOC: + cam->cam_mode = vc0323_mode; + cam->nmodes = ARRAY_SIZE(vc0323_mode); + break; + case SENSOR_MI1320_SOC: + cam->cam_mode = bi_mode; + cam->nmodes = ARRAY_SIZE(bi_mode); + break; + default: + cam->cam_mode = vc0323_mode; + cam->nmodes = ARRAY_SIZE(vc0323_mode) - 1; + break; } } @@ -2683,6 +3064,14 @@ static int sd_start(struct gspca_dev *gspca_dev) const __u8 *GammaT = NULL; const __u8 *MatrixT = NULL; int mode; + static const u8 (*mi1320_soc_init[])[4] = { + mi1320_soc_InitSXGA, + mi1320_soc_InitSXGA_JPG, + mi1320_soc_InitVGA, + mi1320_soc_InitVGA_JPG, + mi1320_soc_InitQVGA, + mi1320_soc_InitQVGA_JPG + }; /* Assume start use the good resolution from gspca_dev->mode */ if (sd->bridge == BRIDGE_VC0321) { @@ -2690,6 +3079,13 @@ static int sd_start(struct gspca_dev *gspca_dev) reg_w(gspca_dev->dev, 0xa0, 0xff, 0xbfed); reg_w(gspca_dev->dev, 0xa0, 0xff, 0xbfee); reg_w(gspca_dev->dev, 0xa0, 0xff, 0xbfef); + sd->image_offset = 46; + } else { + if (gspca_dev->cam.cam_mode[gspca_dev->curr_mode].pixelformat + == V4L2_PIX_FMT_JPEG) + sd->image_offset = 0; + else + sd->image_offset = 32; } mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv; @@ -2752,17 +3148,7 @@ static int sd_start(struct gspca_dev *gspca_dev) case SENSOR_MI1320_SOC: GammaT = mi1320_gamma; MatrixT = mi1320_matrix; - switch (mode) { - case 1: - init = mi1320_soc_InitQVGA_JPG; /* 320x240 */ - break; - case 0: - init = mi1320_soc_InitVGA_JPG; /* 640x480 */ - break; - default: - init = mi1320_soc_InitSXGA_JPG; /* 1280x1024 */ - break; - } + init = mi1320_soc_init[mode]; break; case SENSOR_PO3130NC: GammaT = po3130_gamma; @@ -2834,12 +3220,8 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, "vc032x header packet found len %d", len); frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame, data, 0); - if (sd->bridge == BRIDGE_VC0321) { -#define VCHDRSZ 46 - data += VCHDRSZ; - len -= VCHDRSZ; -#undef VCHDRSZ - } + data += sd->image_offset; + len -= sd->image_offset; gspca_frame_add(gspca_dev, FIRST_PACKET, frame, data, len); return; -- cgit v1.2.3 From 0d7ff0a431799d2d65e5252e8f074897607d5df0 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Wed, 25 Mar 2009 11:13:13 +0100 Subject: gspca - sq905c: New subdriver. From: Theodore Kilgore The code in the new sq905c.c is based upon the structure of the code in gspca/sq905.c, and upon the code in libgphoto2/camlibs/digigr8, which supports the same set of cameras in stillcam mode. I am a co-author of gspca/sq905.c and I am the sole author of libgphoto2/camlibs/digigr8, which is licensed under the LGPL. I hereby give myself permission to use my own code from libgphoto2 in gspca/sq905c.c. Priority: normal Signed-off-by: Theodore Kilgore Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/Kconfig | 9 + linux/drivers/media/video/gspca/Makefile | 2 + linux/drivers/media/video/gspca/sq905c.c | 328 +++++++++++++++++++++++++++++++ 3 files changed, 339 insertions(+) create mode 100644 linux/drivers/media/video/gspca/sq905c.c (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/Kconfig b/linux/drivers/media/video/gspca/Kconfig index a0f05ef5c..578dc4ffc 100644 --- a/linux/drivers/media/video/gspca/Kconfig +++ b/linux/drivers/media/video/gspca/Kconfig @@ -185,6 +185,15 @@ config USB_GSPCA_SQ905 To compile this driver as a module, choose M here: the module will be called gspca_sq905. +config USB_GSPCA_SQ905C + tristate "SQ Technologies SQ905C based USB Camera Driver" + depends on VIDEO_V4L2 && USB_GSPCA + help + Say Y here if you want support for cameras based on the SQ905C chip. + + To compile this driver as a module, choose M here: the + module will be called gspca_sq905c. + config USB_GSPCA_STK014 tristate "Syntek DV4000 (STK014) USB Camera Driver" depends on VIDEO_V4L2 && USB_GSPCA diff --git a/linux/drivers/media/video/gspca/Makefile b/linux/drivers/media/video/gspca/Makefile index b6ec61185..8a6643e8e 100644 --- a/linux/drivers/media/video/gspca/Makefile +++ b/linux/drivers/media/video/gspca/Makefile @@ -17,6 +17,7 @@ obj-$(CONFIG_USB_GSPCA_SPCA506) += gspca_spca506.o obj-$(CONFIG_USB_GSPCA_SPCA508) += gspca_spca508.o obj-$(CONFIG_USB_GSPCA_SPCA561) += gspca_spca561.o obj-$(CONFIG_USB_GSPCA_SQ905) += gspca_sq905.o +obj-$(CONFIG_USB_GSPCA_SQ905C) += gspca_sq905c.o obj-$(CONFIG_USB_GSPCA_SUNPLUS) += gspca_sunplus.o obj-$(CONFIG_USB_GSPCA_STK014) += gspca_stk014.o obj-$(CONFIG_USB_GSPCA_T613) += gspca_t613.o @@ -43,6 +44,7 @@ gspca_spca506-objs := spca506.o gspca_spca508-objs := spca508.o gspca_spca561-objs := spca561.o gspca_sq905-objs := sq905.o +gspca_sq905c-objs := sq905c.o gspca_stk014-objs := stk014.o gspca_sunplus-objs := sunplus.o gspca_t613-objs := t613.o diff --git a/linux/drivers/media/video/gspca/sq905c.c b/linux/drivers/media/video/gspca/sq905c.c new file mode 100644 index 000000000..0bcb74a1b --- /dev/null +++ b/linux/drivers/media/video/gspca/sq905c.c @@ -0,0 +1,328 @@ +/* + * SQ905C subdriver + * + * Copyright (C) 2009 Theodore Kilgore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + * + * This driver uses work done in + * libgphoto2/camlibs/digigr8, Copyright (C) Theodore Kilgore. + * + * This driver has also used as a base the sq905c driver + * and may contain code fragments from it. + */ + +#define MODULE_NAME "sq905c" + +#include +#include "gspca.h" + +MODULE_AUTHOR("Theodore Kilgore "); +MODULE_DESCRIPTION("GSPCA/SQ905C USB Camera Driver"); +MODULE_LICENSE("GPL"); + +/* Default timeouts, in ms */ +#define SQ905C_CMD_TIMEOUT 500 +#define SQ905C_DATA_TIMEOUT 1000 + +/* Maximum transfer size to use. */ +#define SQ905C_MAX_TRANSFER 0x8000 + +#define FRAME_HEADER_LEN 0x50 + +/* Commands. These go in the "value" slot. */ +#define SQ905C_CLEAR 0xa0 /* clear everything */ +#define SQ905C_CAPTURE_LOW 0xa040 /* Starts capture at 160x120 */ +#define SQ905C_CAPTURE_MED 0x1440 /* Starts capture at 320x240 */ +#define SQ905C_CAPTURE_HI 0x2840 /* Starts capture at 320x240 */ + +/* For capture, this must go in the "index" slot. */ +#define SQ905C_CAPTURE_INDEX 0x110f + +/* Structure to hold all of our device specific stuff */ +struct sd { + struct gspca_dev gspca_dev; /* !! must be the first item */ + const struct v4l2_pix_format *cap_mode; + /* Driver stuff */ + struct work_struct work_struct; + struct workqueue_struct *work_thread; +}; + +/* + * Most of these cameras will do 640x480 and 320x240. 160x120 works + * in theory but gives very poor output. Therefore, not supported. + * The 0x2770:0x9050 cameras have max resolution of 320x240. + */ +static struct v4l2_pix_format sq905c_mode[] = { + { 320, 240, V4L2_PIX_FMT_SQ905C, V4L2_FIELD_NONE, + .bytesperline = 320, + .sizeimage = 320 * 240, + .colorspace = V4L2_COLORSPACE_SRGB, + .priv = 0}, + { 640, 480, V4L2_PIX_FMT_SQ905C, V4L2_FIELD_NONE, + .bytesperline = 640, + .sizeimage = 640 * 480, + .colorspace = V4L2_COLORSPACE_SRGB, + .priv = 0} +}; + +/* Send a command to the camera. */ +static int sq905c_command(struct gspca_dev *gspca_dev, u16 command, u16 index) +{ + int ret; + + ret = usb_control_msg(gspca_dev->dev, + usb_sndctrlpipe(gspca_dev->dev, 0), + USB_REQ_SYNCH_FRAME, /* request */ + USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, + command, index, NULL, 0, + SQ905C_CMD_TIMEOUT); + if (ret < 0) { + PDEBUG(D_ERR, "%s: usb_control_msg failed (%d)", + __func__, ret); + return ret; + } + + return 0; +} + +/* This function is called as a workqueue function and runs whenever the camera + * is streaming data. Because it is a workqueue function it is allowed to sleep + * so we can use synchronous USB calls. To avoid possible collisions with other + * threads attempting to use the camera's USB interface the gspca usb_lock is + * used when performing the one USB control operation inside the workqueue, + * which tells the camera to close the stream. In practice the only thing + * which needs to be protected against is the usb_set_interface call that + * gspca makes during stream_off. Otherwise the camera doesn't provide any + * controls that the user could try to change. + */ +static void sq905c_dostream(struct work_struct *work) +{ + struct sd *dev = container_of(work, struct sd, work_struct); + struct gspca_dev *gspca_dev = &dev->gspca_dev; + struct gspca_frame *frame; + int bytes_left; /* bytes remaining in current frame. */ + int data_len; /* size to use for the next read. */ + int act_len; + int discarding = 0; /* true if we failed to get space for frame. */ + int packet_type; + int ret; + u8 *buffer; + + buffer = kmalloc(SQ905C_MAX_TRANSFER, GFP_KERNEL | GFP_DMA); + if (!buffer) { + PDEBUG(D_ERR, "Couldn't allocate USB buffer"); + goto quit_stream; + } + + while (gspca_dev->present && gspca_dev->streaming) { + if (!gspca_dev->present) + goto quit_stream; + /* Request the header, which tells the size to download */ + ret = usb_bulk_msg(gspca_dev->dev, + usb_rcvbulkpipe(gspca_dev->dev, 0x81), + buffer, FRAME_HEADER_LEN, &act_len, + SQ905C_DATA_TIMEOUT); + PDEBUG(D_STREAM, + "Got %d bytes out of %d for header", + act_len, FRAME_HEADER_LEN); + if (ret < 0 || act_len < FRAME_HEADER_LEN) + goto quit_stream; + /* size is read from 4 bytes starting 0x40, little endian */ + bytes_left = buffer[0x40]|(buffer[0x41]<<8)|(buffer[0x42]<<16) + |(buffer[0x43]<<24); + PDEBUG(D_STREAM, "bytes_left = 0x%x", bytes_left); + /* We keep the header. It has other information, too. */ + packet_type = FIRST_PACKET; + frame = gspca_get_i_frame(gspca_dev); + if (frame && !discarding) { + gspca_frame_add(gspca_dev, packet_type, + frame, buffer, FRAME_HEADER_LEN); + } else + discarding = 1; + while (bytes_left > 0) { + data_len = bytes_left > SQ905C_MAX_TRANSFER ? + SQ905C_MAX_TRANSFER : bytes_left; + if (!gspca_dev->present) + goto quit_stream; + ret = usb_bulk_msg(gspca_dev->dev, + usb_rcvbulkpipe(gspca_dev->dev, 0x81), + buffer, data_len, &act_len, + SQ905C_DATA_TIMEOUT); + if (ret < 0 || act_len < data_len) + goto quit_stream; + PDEBUG(D_STREAM, + "Got %d bytes out of %d for frame", + data_len, bytes_left); + bytes_left -= data_len; + if (bytes_left == 0) + packet_type = LAST_PACKET; + else + packet_type = INTER_PACKET; + frame = gspca_get_i_frame(gspca_dev); + if (frame && !discarding) + gspca_frame_add(gspca_dev, packet_type, + frame, buffer, data_len); + else + discarding = 1; + } + } +quit_stream: + mutex_lock(&gspca_dev->usb_lock); + if (gspca_dev->present) + sq905c_command(gspca_dev, SQ905C_CLEAR, 0); + mutex_unlock(&gspca_dev->usb_lock); + kfree(buffer); +} + +/* This function is called at probe time just before sd_init */ +static int sd_config(struct gspca_dev *gspca_dev, + const struct usb_device_id *id) +{ + struct cam *cam = &gspca_dev->cam; + struct sd *dev = (struct sd *) gspca_dev; + + PDEBUG(D_PROBE, + "SQ9050 camera detected" + " (vid/pid 0x%04X:0x%04X)", id->idVendor, id->idProduct); + cam->cam_mode = sq905c_mode; + cam->nmodes = 2; + if (id->idProduct == 0x9050) + cam->nmodes = 1; + /* We don't use the buffer gspca allocates so make it small. */ + cam->bulk_size = 32; + INIT_WORK(&dev->work_struct, sq905c_dostream); + return 0; +} + +/* called on streamoff with alt==0 and on disconnect */ +/* the usb_lock is held at entry - restore on exit */ +static void sd_stop0(struct gspca_dev *gspca_dev) +{ + struct sd *dev = (struct sd *) gspca_dev; + + /* wait for the work queue to terminate */ + mutex_unlock(&gspca_dev->usb_lock); + /* This waits for sq905c_dostream to finish */ + destroy_workqueue(dev->work_thread); + dev->work_thread = NULL; + mutex_lock(&gspca_dev->usb_lock); +} + +/* this function is called at probe and resume time */ +static int sd_init(struct gspca_dev *gspca_dev) +{ + int ret; + + /* connect to the camera and reset it. */ + ret = sq905c_command(gspca_dev, SQ905C_CLEAR, 0); + return ret; +} + +/* Set up for getting frames. */ +static int sd_start(struct gspca_dev *gspca_dev) +{ + struct sd *dev = (struct sd *) gspca_dev; + int ret; + + dev->cap_mode = gspca_dev->cam.cam_mode; + /* "Open the shutter" and set size, to start capture */ + switch (gspca_dev->width) { + case 640: + PDEBUG(D_STREAM, "Start streaming at high resolution"); + dev->cap_mode++; + ret = sq905c_command(gspca_dev, SQ905C_CAPTURE_HI, + SQ905C_CAPTURE_INDEX); + break; + default: /* 320 */ + PDEBUG(D_STREAM, "Start streaming at medium resolution"); + ret = sq905c_command(gspca_dev, SQ905C_CAPTURE_MED, + SQ905C_CAPTURE_INDEX); + } + + if (ret < 0) { + PDEBUG(D_ERR, "Start streaming command failed"); + return ret; + } + /* Start the workqueue function to do the streaming */ + dev->work_thread = create_singlethread_workqueue(MODULE_NAME); + queue_work(dev->work_thread, &dev->work_struct); + + return 0; +} + +/* Table of supported USB devices */ +static const __devinitdata struct usb_device_id device_table[] = { + {USB_DEVICE(0x2770, 0x905c)}, + {USB_DEVICE(0x2770, 0x9050)}, + {USB_DEVICE(0x2770, 0x913d)}, + {} +}; + +MODULE_DEVICE_TABLE(usb, device_table); + +/* sub-driver description */ +static const struct sd_desc sd_desc = { + .name = MODULE_NAME, + .config = sd_config, + .init = sd_init, + .start = sd_start, + .stop0 = sd_stop0, +}; + +/* -- device connect -- */ +static int sd_probe(struct usb_interface *intf, + const struct usb_device_id *id) +{ + return gspca_dev_probe(intf, id, + &sd_desc, + sizeof(struct sd), + THIS_MODULE); +} + +static struct usb_driver sd_driver = { + .name = MODULE_NAME, + .id_table = device_table, + .probe = sd_probe, + .disconnect = gspca_disconnect, +#ifdef CONFIG_PM + .suspend = gspca_suspend, + .resume = gspca_resume, +#endif +}; + +/* -- module insert / remove -- */ +static int __init sd_mod_init(void) +{ + int ret; + + ret = usb_register(&sd_driver); + if (ret < 0) + return ret; + PDEBUG(D_PROBE, "registered"); + return 0; +} + +static void __exit sd_mod_exit(void) +{ + usb_deregister(&sd_driver); + PDEBUG(D_PROBE, "deregistered"); +} + +module_init(sd_mod_init); +module_exit(sd_mod_exit); -- cgit v1.2.3 From a3bb275ba5d574b4c3aa8a7437548afdfd2d974c Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Wed, 25 Mar 2009 21:48:15 +0200 Subject: zl10353: add support for Intel CE6230 and Intel CE6231 From: Antti Palosaari Add chip IDs and configuration registers needed for Intel CE6230 and Intel CE6231. Priority: normal Signed-off-by: Antti Palosaari --- linux/drivers/media/dvb/frontends/zl10353.c | 8 +++++++- linux/drivers/media/dvb/frontends/zl10353.h | 4 ++++ linux/drivers/media/dvb/frontends/zl10353_priv.h | 8 +++++++- 3 files changed, 18 insertions(+), 2 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/frontends/zl10353.c b/linux/drivers/media/dvb/frontends/zl10353.c index 96ccc1720..6b58bf961 100644 --- a/linux/drivers/media/dvb/frontends/zl10353.c +++ b/linux/drivers/media/dvb/frontends/zl10353.c @@ -581,6 +581,10 @@ static int zl10353_init(struct dvb_frontend *fe) #endif if (state->config.parallel_ts) zl10353_reset_attach[2] &= ~0x20; + if (state->config.clock_ctl_1) + zl10353_reset_attach[3] = state->config.clock_ctl_1; + if (state->config.pll_0) + zl10353_reset_attach[4] = state->config.pll_0; /* Do a "hard" reset if not already done */ if (zl10353_read_register(state, 0x50) != zl10353_reset_attach[1] || @@ -625,6 +629,7 @@ struct dvb_frontend *zl10353_attach(const struct zl10353_config *config, struct i2c_adapter *i2c) { struct zl10353_state *state = NULL; + int id; /* allocate memory for the internal state */ state = kzalloc(sizeof(struct zl10353_state), GFP_KERNEL); @@ -636,7 +641,8 @@ struct dvb_frontend *zl10353_attach(const struct zl10353_config *config, memcpy(&state->config, config, sizeof(struct zl10353_config)); /* check if the demod is there */ - if (zl10353_read_register(state, CHIP_ID) != ID_ZL10353) + id = zl10353_read_register(state, CHIP_ID); + if ((id != ID_ZL10353) && (id != ID_CE6230) && (id != ID_CE6231)) goto error; /* create dvb_frontend */ diff --git a/linux/drivers/media/dvb/frontends/zl10353.h b/linux/drivers/media/dvb/frontends/zl10353.h index 2287bac46..6e3ca9eed 100644 --- a/linux/drivers/media/dvb/frontends/zl10353.h +++ b/linux/drivers/media/dvb/frontends/zl10353.h @@ -41,6 +41,10 @@ struct zl10353_config /* set if i2c_gate_ctrl disable is required */ u8 disable_i2c_gate_ctrl:1; + + /* clock control registers (0x51-0x54) */ + u8 clock_ctl_1; /* default: 0x46 */ + u8 pll_0; /* default: 0x15 */ }; #if defined(CONFIG_DVB_ZL10353) || (defined(CONFIG_DVB_ZL10353_MODULE) && defined(MODULE)) diff --git a/linux/drivers/media/dvb/frontends/zl10353_priv.h b/linux/drivers/media/dvb/frontends/zl10353_priv.h index 055ff1f7e..e0dd1d3e0 100644 --- a/linux/drivers/media/dvb/frontends/zl10353_priv.h +++ b/linux/drivers/media/dvb/frontends/zl10353_priv.h @@ -22,7 +22,9 @@ #ifndef _ZL10353_PRIV_ #define _ZL10353_PRIV_ -#define ID_ZL10353 0x14 +#define ID_ZL10353 0x14 /* Zarlink ZL10353 */ +#define ID_CE6230 0x18 /* Intel CE6230 */ +#define ID_CE6231 0x19 /* Intel CE6231 */ #define msb(x) (((x) >> 8) & 0xff) #define lsb(x) ((x) & 0xff) @@ -50,6 +52,10 @@ enum zl10353_reg_addr { TPS_RECEIVED_0 = 0x1E, TPS_CURRENT_1 = 0x1F, TPS_CURRENT_0 = 0x20, + CLOCK_CTL_0 = 0x51, + CLOCK_CTL_1 = 0x52, + PLL_0 = 0x53, + PLL_1 = 0x54, RESET = 0x55, AGC_TARGET = 0x56, MCLK_RATIO = 0x5C, -- cgit v1.2.3 From 271ff892e19406f748d58d75cb6bb9d5b2ad7076 Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Wed, 25 Mar 2009 21:59:45 +0200 Subject: Add driver for Intel CE6230 DVB-T USB2.0 From: Antti Palosaari Add driver for Intel CE6230 DVB-T USB 2.0 COFDM demodulator Priority: normal Signed-off-by: Antti Palosaari --- linux/drivers/media/dvb/dvb-usb/Kconfig | 8 + linux/drivers/media/dvb/dvb-usb/Makefile | 2 + linux/drivers/media/dvb/dvb-usb/ce6230.c | 331 ++++++++++++++++++++++++++ linux/drivers/media/dvb/dvb-usb/ce6230.h | 69 ++++++ linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h | 2 + 5 files changed, 412 insertions(+) create mode 100644 linux/drivers/media/dvb/dvb-usb/ce6230.c create mode 100644 linux/drivers/media/dvb/dvb-usb/ce6230.h (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/dvb-usb/Kconfig b/linux/drivers/media/dvb/dvb-usb/Kconfig index 5b0c8cc25..6103caad1 100644 --- a/linux/drivers/media/dvb/dvb-usb/Kconfig +++ b/linux/drivers/media/dvb/dvb-usb/Kconfig @@ -304,3 +304,11 @@ config DVB_USB_AF9015 select MEDIA_TUNER_MC44S803 if !MEDIA_TUNER_CUSTOMISE help Say Y here to support the Afatech AF9015 based DVB-T USB2.0 receiver + +config DVB_USB_CE6230 + tristate "Intel CE6230 DVB-T USB2.0 support" + depends on DVB_USB && EXPERIMENTAL + select DVB_ZL10353 + select MEDIA_TUNER_MXL5005S if !MEDIA_TUNER_CUSTOMIZE + help + Say Y here to support the Intel CE6230 DVB-T USB2.0 receiver diff --git a/linux/drivers/media/dvb/dvb-usb/Makefile b/linux/drivers/media/dvb/dvb-usb/Makefile index 3122b7cc2..f92734ed7 100644 --- a/linux/drivers/media/dvb/dvb-usb/Makefile +++ b/linux/drivers/media/dvb/dvb-usb/Makefile @@ -76,6 +76,8 @@ obj-$(CONFIG_DVB_USB_AF9015) += dvb-usb-af9015.o dvb-usb-cinergyT2-objs = cinergyT2-core.o cinergyT2-fe.o obj-$(CONFIG_DVB_USB_CINERGY_T2) += dvb-usb-cinergyT2.o +dvb-usb-ce6230-objs = ce6230.o +obj-$(CONFIG_DVB_USB_CE6230) += dvb-usb-ce6230.o EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/ # due to tuner-xc3028 diff --git a/linux/drivers/media/dvb/dvb-usb/ce6230.c b/linux/drivers/media/dvb/dvb-usb/ce6230.c new file mode 100644 index 000000000..2a959c4bd --- /dev/null +++ b/linux/drivers/media/dvb/dvb-usb/ce6230.c @@ -0,0 +1,331 @@ +/* + * DVB USB Linux driver for Intel CE6230 DVB-T USB2.0 receiver + * + * Copyright (C) 2009 Antti Palosaari + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include "ce6230.h" +#include "zl10353.h" +#include "mxl5005s.h" + +/* debug */ +static int dvb_usb_ce6230_debug; +module_param_named(debug, dvb_usb_ce6230_debug, int, 0644); +MODULE_PARM_DESC(debug, "set debugging level" DVB_USB_DEBUG_STATUS); +DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); + +static struct zl10353_config ce6230_zl10353_config; + +static int ce6230_rw_udev(struct usb_device *udev, struct req_t *req) +{ + int ret; + unsigned int pipe; + u8 request; + u8 requesttype; + u16 value; + u16 index; + u8 buf[req->data_len]; + + request = req->cmd; + value = req->value; + index = req->index; + + switch (req->cmd) { + case I2C_READ: + case DEMOD_READ: + case REG_READ: + requesttype = (USB_TYPE_VENDOR | USB_DIR_IN); + break; + case I2C_WRITE: + case DEMOD_WRITE: + case REG_WRITE: + requesttype = (USB_TYPE_VENDOR | USB_DIR_OUT); + break; + default: + err("unknown command:%02x", req->cmd); + ret = -EPERM; + goto error; + } + + if (requesttype == (USB_TYPE_VENDOR | USB_DIR_OUT)) { + /* write */ + memcpy(buf, req->data, req->data_len); + pipe = usb_sndctrlpipe(udev, 0); + } else { + /* read */ + pipe = usb_rcvctrlpipe(udev, 0); + } + + msleep(1); /* avoid I2C errors */ + + ret = usb_control_msg(udev, pipe, request, requesttype, value, index, + buf, sizeof(buf), CE6230_USB_TIMEOUT); + + ce6230_debug_dump(request, requesttype, value, index, buf, + req->data_len, deb_xfer); + + if (ret < 0) + deb_info("%s: usb_control_msg failed:%d\n", __func__, ret); + else + ret = 0; + + /* read request, copy returned data to return buf */ + if (!ret && requesttype == (USB_TYPE_VENDOR | USB_DIR_IN)) + memcpy(req->data, buf, req->data_len); + +error: + return ret; +} + +static int ce6230_ctrl_msg(struct dvb_usb_device *d, struct req_t *req) +{ + return ce6230_rw_udev(d->udev, req); +} + +/* I2C */ +static int ce6230_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], + int num) +{ + struct dvb_usb_device *d = i2c_get_adapdata(adap); + int i = 0; + struct req_t req; + int ret; + memset(&req, 0, sizeof(&req)); + + if (num > 2) + return -EINVAL; + + if (mutex_lock_interruptible(&d->i2c_mutex) < 0) + return -EAGAIN; + + while (i < num) { + if (num > i + 1 && (msg[i+1].flags & I2C_M_RD)) { + if (msg[i].addr == + ce6230_zl10353_config.demod_address) { + req.cmd = DEMOD_READ; + req.value = msg[i].addr >> 1; + req.index = msg[i].buf[0]; + req.data_len = msg[i+1].len; + req.data = &msg[i+1].buf[0]; + ret = ce6230_ctrl_msg(d, &req); + } else { + err("i2c read not implemented"); + ret = -EPERM; + } + i += 2; + } else { + if (msg[i].addr == + ce6230_zl10353_config.demod_address) { + req.cmd = DEMOD_WRITE; + req.value = msg[i].addr >> 1; + req.index = msg[i].buf[0]; + req.data_len = msg[i].len-1; + req.data = &msg[i].buf[1]; + ret = ce6230_ctrl_msg(d, &req); + } else { + req.cmd = I2C_WRITE; + req.value = 0x2000 + (msg[i].addr >> 1); + req.index = 0x0000; + req.data_len = msg[i].len; + req.data = &msg[i].buf[0]; + ret = ce6230_ctrl_msg(d, &req); + } + i += 1; + } + if (ret) + break; + } + + mutex_unlock(&d->i2c_mutex); + return ret ? ret : i; +} + +static u32 ce6230_i2c_func(struct i2c_adapter *adapter) +{ + return I2C_FUNC_I2C; +} + +static struct i2c_algorithm ce6230_i2c_algo = { + .master_xfer = ce6230_i2c_xfer, + .functionality = ce6230_i2c_func, +#ifdef NEED_ALGO_CONTROL + .algo_control = dummy_algo_control, +#endif +}; + +/* Callbacks for DVB USB */ +static struct zl10353_config ce6230_zl10353_config = { + .demod_address = 0x1e, + .adc_clock = 450000, + .if2 = 45700, + .no_tuner = 1, + .parallel_ts = 1, + .clock_ctl_1 = 0x34, + .pll_0 = 0x0e, +}; + +static int ce6230_zl10353_frontend_attach(struct dvb_usb_adapter *adap) +{ + deb_info("%s:\n", __func__); + adap->fe = dvb_attach(zl10353_attach, &ce6230_zl10353_config, + &adap->dev->i2c_adap); + if (adap->fe == NULL) + return -ENODEV; + return 0; +} + +static struct mxl5005s_config ce6230_mxl5003s_config = { + .i2c_address = 0xc6, + .if_freq = IF_FREQ_4570000HZ, + .xtal_freq = CRYSTAL_FREQ_16000000HZ, + .agc_mode = MXL_SINGLE_AGC, + .tracking_filter = MXL_TF_DEFAULT, + .rssi_enable = MXL_RSSI_ENABLE, + .cap_select = MXL_CAP_SEL_ENABLE, + .div_out = MXL_DIV_OUT_4, + .clock_out = MXL_CLOCK_OUT_DISABLE, + .output_load = MXL5005S_IF_OUTPUT_LOAD_200_OHM, + .top = MXL5005S_TOP_25P2, + .mod_mode = MXL_DIGITAL_MODE, + .if_mode = MXL_ZERO_IF, + .AgcMasterByte = 0x00, +}; + +static int ce6230_mxl5003s_tuner_attach(struct dvb_usb_adapter *adap) +{ + int ret; + deb_info("%s:\n", __func__); + ret = dvb_attach(mxl5005s_attach, adap->fe, &adap->dev->i2c_adap, + &ce6230_mxl5003s_config) == NULL ? -ENODEV : 0; + return ret; +} + +static int ce6230_power_ctrl(struct dvb_usb_device *d, int onoff) +{ + int ret; + deb_info("%s: onoff:%d\n", __func__, onoff); + + /* InterfaceNumber 1 / AlternateSetting 0 idle + InterfaceNumber 1 / AlternateSetting 1 streaming */ + ret = usb_set_interface(d->udev, 1, onoff); + if (ret) + err("usb_set_interface failed with error:%d", ret); + + return ret; +} + +/* DVB USB Driver stuff */ +static struct dvb_usb_device_properties ce6230_properties; + +static int ce6230_probe(struct usb_interface *intf, + const struct usb_device_id *id) +{ + int ret = 0; + struct dvb_usb_device *d = NULL; + + deb_info("%s: interface:%d\n", __func__, + intf->cur_altsetting->desc.bInterfaceNumber); + + if (intf->cur_altsetting->desc.bInterfaceNumber == 1) { + ret = dvb_usb_device_init(intf, &ce6230_properties, THIS_MODULE, + &d, adapter_nr); + if (ret) + err("init failed with error:%d\n", ret); + } + + return ret; +} + +static struct usb_device_id ce6230_table[] = { + { USB_DEVICE(USB_VID_INTEL, USB_PID_INTEL_CE9500) }, + { } /* Terminating entry */ +}; +MODULE_DEVICE_TABLE(usb, ce6230_table); + +static struct dvb_usb_device_properties ce6230_properties = { + .caps = DVB_USB_IS_AN_I2C_ADAPTER, + + .usb_ctrl = DEVICE_SPECIFIC, + .no_reconnect = 1, + + .size_of_priv = 0, + + .num_adapters = 1, + .adapter = { + { + .frontend_attach = ce6230_zl10353_frontend_attach, + .tuner_attach = ce6230_mxl5003s_tuner_attach, + .stream = { + .type = USB_BULK, + .count = 6, + .endpoint = 0x82, + .u = { + .bulk = { + .buffersize = 512, + } + } + }, + } + }, + + .power_ctrl = ce6230_power_ctrl, + + .i2c_algo = &ce6230_i2c_algo, + + .num_device_descs = 1, + .devices = { + { + .name = "Intel CE9500 reference design", + .cold_ids = {NULL}, + .warm_ids = {&ce6230_table[0], NULL}, + }, + } +}; + +static struct usb_driver ce6230_driver = { + .name = "dvb_usb_ce6230", + .probe = ce6230_probe, + .disconnect = dvb_usb_device_exit, + .id_table = ce6230_table, +}; + +/* module stuff */ +static int __init ce6230_module_init(void) +{ + int ret; + deb_info("%s:\n", __func__); + ret = usb_register(&ce6230_driver); + if (ret) + err("usb_register failed with error:%d", ret); + + return ret; +} + +static void __exit ce6230_module_exit(void) +{ + deb_info("%s:\n", __func__); + /* deregister this driver from the USB subsystem */ + usb_deregister(&ce6230_driver); +} + +module_init(ce6230_module_init); +module_exit(ce6230_module_exit); + +MODULE_AUTHOR("Antti Palosaari "); +MODULE_DESCRIPTION("Driver for Intel CE6230 DVB-T USB2.0"); +MODULE_LICENSE("GPL"); diff --git a/linux/drivers/media/dvb/dvb-usb/ce6230.h b/linux/drivers/media/dvb/dvb-usb/ce6230.h new file mode 100644 index 000000000..97c42482c --- /dev/null +++ b/linux/drivers/media/dvb/dvb-usb/ce6230.h @@ -0,0 +1,69 @@ +/* + * DVB USB Linux driver for Intel CE6230 DVB-T USB2.0 receiver + * + * Copyright (C) 2009 Antti Palosaari + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifndef _DVB_USB_CE6230_H_ +#define _DVB_USB_CE6230_H_ + +#define DVB_USB_LOG_PREFIX "ce6230" +#include "dvb-usb.h" + +#define deb_info(args...) dprintk(dvb_usb_ce6230_debug, 0x01, args) +#define deb_rc(args...) dprintk(dvb_usb_ce6230_debug, 0x02, args) +#define deb_xfer(args...) dprintk(dvb_usb_ce6230_debug, 0x04, args) +#define deb_reg(args...) dprintk(dvb_usb_ce6230_debug, 0x08, args) +#define deb_i2c(args...) dprintk(dvb_usb_ce6230_debug, 0x10, args) +#define deb_fw(args...) dprintk(dvb_usb_ce6230_debug, 0x20, args) + +#define ce6230_debug_dump(r, t, v, i, b, l, func) { \ + int loop_; \ + func("%02x %02x %02x %02x %02x %02x %02x %02x", \ + t, r, v & 0xff, v >> 8, i & 0xff, i >> 8, l & 0xff, l >> 8); \ + if (t == (USB_TYPE_VENDOR | USB_DIR_OUT)) \ + func(" >>> "); \ + else \ + func(" <<< "); \ + for (loop_ = 0; loop_ < l; loop_++) \ + func("%02x ", b[loop_]); \ + func("\n");\ +} + +#define CE6230_USB_TIMEOUT 1000 + +struct req_t { + u8 cmd; /* [1] */ + u16 value; /* [2|3] */ + u16 index; /* [4|5] */ + u16 data_len; /* [6|7] */ + u8 *data; +}; + +enum ce6230_cmd { + CONFIG_READ = 0xd0, /* rd 0 (unclear) */ + UNKNOWN_WRITE = 0xc7, /* wr 7 (unclear) */ + I2C_READ = 0xd9, /* rd 9 (unclear) */ + I2C_WRITE = 0xca, /* wr a */ + DEMOD_READ = 0xdb, /* rd b */ + DEMOD_WRITE = 0xcc, /* wr c */ + REG_READ = 0xde, /* rd e */ + REG_WRITE = 0xcf, /* wr f */ +}; + +#endif 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 3dfb27174..0f239c668 100644 --- a/linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h +++ b/linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h @@ -33,6 +33,7 @@ #define USB_VID_HANFTEK 0x15f4 #define USB_VID_HAUPPAUGE 0x2040 #define USB_VID_HYPER_PALTEK 0x1025 +#define USB_VID_INTEL 0x8086 #define USB_VID_KWORLD 0xeb2a #define USB_VID_KWORLD_2 0x1b80 #define USB_VID_KYE 0x0458 @@ -96,6 +97,7 @@ #define USB_PID_UNIWILL_STK7700P 0x6003 #define USB_PID_GRANDTEC_DVBT_USB_COLD 0x0fa0 #define USB_PID_GRANDTEC_DVBT_USB_WARM 0x0fa1 +#define USB_PID_INTEL_CE9500 0x9500 #define USB_PID_KWORLD_399U 0xe399 #define USB_PID_KWORLD_395U 0xe396 #define USB_PID_KWORLD_395U_2 0xe39b -- cgit v1.2.3 From 61d85f6f6deaf3d0a860e7010667ebc82d97f925 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Thu, 26 Mar 2009 09:01:48 +0100 Subject: gspca - sq905: Update the frame pointer after adding the last packet. From: Jean-Francois Moine Priority: normal Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/sq905.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/sq905.c b/linux/drivers/media/video/gspca/sq905.c index da60eea51..b1d377e49 100644 --- a/linux/drivers/media/video/gspca/sq905.c +++ b/linux/drivers/media/video/gspca/sq905.c @@ -270,13 +270,14 @@ static void sq905_dostream(struct work_struct *work) } frame = gspca_get_i_frame(gspca_dev); if (frame && !discarding) { - gspca_frame_add(gspca_dev, packet_type, + frame = gspca_frame_add(gspca_dev, packet_type, frame, data, data_len); /* If entire frame fits in one packet we still need to add a LAST_PACKET */ - if ((packet_type == FIRST_PACKET) && - (bytes_left == 0)) - gspca_frame_add(gspca_dev, LAST_PACKET, + if (packet_type == FIRST_PACKET && + bytes_left == 0) + frame = gspca_frame_add(gspca_dev, + LAST_PACKET, frame, data, 0); } else { discarding = 1; -- cgit v1.2.3 From 5579608166061512743e41a0b097aa0e5a30a7ce Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Thu, 26 Mar 2009 09:03:13 +0100 Subject: gspca - sq905: Optimize the resolution setting. From: Jean-Francois Moine Priority: normal Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/sq905.c | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/sq905.c b/linux/drivers/media/video/gspca/sq905.c index b1d377e49..04e3ae57a 100644 --- a/linux/drivers/media/video/gspca/sq905.c +++ b/linux/drivers/media/video/gspca/sq905.c @@ -82,8 +82,6 @@ MODULE_LICENSE("GPL"); struct sd { struct gspca_dev gspca_dev; /* !! must be the first item */ - const struct v4l2_pix_format *cap_mode; - /* * Driver stuff */ @@ -218,6 +216,7 @@ static void sq905_dostream(struct work_struct *work) int header_read; /* true if we have already read the frame header. */ int discarding; /* true if we failed to get space for frame. */ int packet_type; + int frame_sz; int ret; u8 *data; u8 *buffer; @@ -229,6 +228,9 @@ static void sq905_dostream(struct work_struct *work) goto quit_stream; } + frame_sz = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].sizeimage + + FRAME_HEADER_LEN; + while (gspca_dev->present && gspca_dev->streaming) { /* Need a short delay to ensure streaming flag was set by * gspca and to make sure gspca can grab the mutex. */ @@ -237,7 +239,7 @@ static void sq905_dostream(struct work_struct *work) /* request some data and then read it until we have * a complete frame. */ - bytes_left = dev->cap_mode->sizeimage + FRAME_HEADER_LEN; + bytes_left = frame_sz; header_read = 0; discarding = 0; @@ -367,21 +369,18 @@ static int sd_start(struct gspca_dev *gspca_dev) struct sd *dev = (struct sd *) gspca_dev; int ret; - /* Set capture mode based on selected resolution. */ - dev->cap_mode = gspca_dev->cam.cam_mode; /* "Open the shutter" and set size, to start capture */ - switch (gspca_dev->width) { - case 640: + switch (gspca_dev->curr_mode) { + default: +/* case 2: */ PDEBUG(D_STREAM, "Start streaming at high resolution"); - dev->cap_mode += 2; ret = sq905_command(&dev->gspca_dev, SQ905_CAPTURE_HIGH); break; - case 320: + case 1: PDEBUG(D_STREAM, "Start streaming at medium resolution"); - dev->cap_mode++; ret = sq905_command(&dev->gspca_dev, SQ905_CAPTURE_MED); break; - default: + case 0: PDEBUG(D_STREAM, "Start streaming at low resolution"); ret = sq905_command(&dev->gspca_dev, SQ905_CAPTURE_LOW); } -- cgit v1.2.3 From 832e43c35739a168c151088d05efa2f9a24aaea1 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Thu, 26 Mar 2009 09:06:50 +0100 Subject: gspca - finepix: Use a workqueue for streaming. From: Jean-Francois Moine Priority: normal Tested-by: Frank Zago Acked-by: Frank Zago Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/finepix.c | 421 ++++++++++-------------------- 1 file changed, 134 insertions(+), 287 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/finepix.c b/linux/drivers/media/video/gspca/finepix.c index dc65c363a..00e6863ed 100644 --- a/linux/drivers/media/video/gspca/finepix.c +++ b/linux/drivers/media/video/gspca/finepix.c @@ -27,7 +27,7 @@ MODULE_DESCRIPTION("Fujifilm FinePix USB V4L2 driver"); MODULE_LICENSE("GPL"); /* Default timeout, in ms */ -#define FPIX_TIMEOUT (HZ / 10) +#define FPIX_TIMEOUT 250 /* Maximum transfer size to use. The windows driver reads by chunks of * 0x2000 bytes, so do the same. Note: reading more seems to work @@ -38,38 +38,15 @@ MODULE_LICENSE("GPL"); struct usb_fpix { struct gspca_dev gspca_dev; /* !! must be the first item */ - /* - * USB stuff - */ - struct usb_ctrlrequest ctrlreq; - struct urb *control_urb; - struct timer_list bulk_timer; - - enum { - FPIX_NOP, /* inactive, else streaming */ - FPIX_RESET, /* must reset */ - FPIX_REQ_FRAME, /* requesting a frame */ - FPIX_READ_FRAME, /* reading frame */ - } state; - - /* - * Driver stuff - */ - struct delayed_work wqe; - struct completion can_close; - int streaming; + struct work_struct work_struct; + struct workqueue_struct *work_thread; }; /* Delay after which claim the next frame. If the delay is too small, * the camera will return old frames. On the 4800Z, 20ms is bad, 25ms - * will fail every 4 or 5 frames, but 30ms is perfect. */ -#define NEXT_FRAME_DELAY (((HZ * 30) + 999) / 1000) - -#define dev_new_state(new_state) { \ - PDEBUG(D_STREAM, "new state from %d to %d at %s:%d", \ - dev->state, new_state, __func__, __LINE__); \ - dev->state = new_state; \ -} + * will fail every 4 or 5 frames, but 30ms is perfect. On the A210, + * 30ms is bad while 35ms is perfect. */ +#define NEXT_FRAME_DELAY 35 /* These cameras only support 320x200. */ static const struct v4l2_pix_format fpix_mode[1] = { @@ -80,314 +57,183 @@ static const struct v4l2_pix_format fpix_mode[1] = { .priv = 0} }; -/* Reads part of a frame */ -static void read_frame_part(struct usb_fpix *dev) +/* send a command to the webcam */ +static int command(struct gspca_dev *gspca_dev, + int order) /* 0: reset, 1: frame request */ { - int ret; + static u8 order_values[2][12] = { + {0xc6, 0, 0, 0, 0, 0, 0, 0, 0x20, 0, 0, 0}, /* reset */ + {0xd3, 0, 0, 0, 0, 0, 0, 0x01, 0, 0, 0, 0}, /* fr req */ + }; - PDEBUG(D_STREAM, "read_frame_part"); - - /* Reads part of a frame */ - ret = usb_submit_urb(dev->gspca_dev.urb[0], GFP_ATOMIC); - if (ret) { - dev_new_state(FPIX_RESET); - schedule_delayed_work(&dev->wqe, 1); - PDEBUG(D_STREAM, "usb_submit_urb failed with %d", - ret); - } else { - /* Sometimes we never get a callback, so use a timer. - * Is this masking a bug somewhere else? */ - dev->bulk_timer.expires = jiffies + msecs_to_jiffies(150); - add_timer(&dev->bulk_timer); - } + memcpy(gspca_dev->usb_buf, order_values[order], 12); + return usb_control_msg(gspca_dev->dev, + usb_sndctrlpipe(gspca_dev->dev, 0), + USB_REQ_GET_STATUS, + USB_DIR_OUT | USB_TYPE_CLASS | + USB_RECIP_INTERFACE, 0, 0, gspca_dev->usb_buf, + 12, FPIX_TIMEOUT); } -/* Callback for URBs. */ -static void urb_callback(struct urb *urb) +/* workqueue */ +static void dostream(struct work_struct *work) { - struct gspca_dev *gspca_dev = urb->context; - struct usb_fpix *dev = (struct usb_fpix *) gspca_dev; - - PDEBUG(D_PACK, - "enter urb_callback - status=%d, length=%d", - urb->status, urb->actual_length); - - if (dev->state == FPIX_READ_FRAME) - del_timer(&dev->bulk_timer); - - if (urb->status != 0) { - /* We kill a stuck urb every 50 frames on average, so don't - * display a log message for that. */ - if (urb->status != -ECONNRESET) - PDEBUG(D_STREAM, "bad URB status %d", urb->status); - dev_new_state(FPIX_RESET); - schedule_delayed_work(&dev->wqe, 1); - } - - switch (dev->state) { - case FPIX_REQ_FRAME: - dev_new_state(FPIX_READ_FRAME); - read_frame_part(dev); - break; - - case FPIX_READ_FRAME: { - unsigned char *data = urb->transfer_buffer; - struct gspca_frame *frame; - - frame = gspca_get_i_frame(&dev->gspca_dev); - if (frame == NULL) - gspca_dev->last_packet_type = DISCARD_PACKET; - if (urb->actual_length < FPIX_MAX_TRANSFER || - (data[urb->actual_length-2] == 0xff && - data[urb->actual_length-1] == 0xd9)) { - - /* If the result is less than what was asked - * for, then it's the end of the - * frame. Sometime the jpeg is not complete, - * but there's nothing we can do. We also end - * here if the the jpeg ends right at the end - * of the frame. */ - if (frame) - gspca_frame_add(gspca_dev, LAST_PACKET, - frame, - data, urb->actual_length); - dev_new_state(FPIX_REQ_FRAME); - schedule_delayed_work(&dev->wqe, NEXT_FRAME_DELAY); - } else { + struct usb_fpix *dev = container_of(work, struct usb_fpix, work_struct); + struct gspca_dev *gspca_dev = &dev->gspca_dev; + struct urb *urb = gspca_dev->urb[0]; + u8 *data = urb->transfer_buffer; + struct gspca_frame *frame; + int ret = 0; + int len; + + /* synchronize with the main driver */ + mutex_lock(&gspca_dev->usb_lock); + mutex_unlock(&gspca_dev->usb_lock); + PDEBUG(D_STREAM, "dostream started"); + + /* loop reading a frame */ +again: + while (gspca_dev->present && gspca_dev->streaming) { + + /* request a frame */ + mutex_lock(&gspca_dev->usb_lock); + ret = command(gspca_dev, 1); + mutex_unlock(&gspca_dev->usb_lock); + if (ret < 0) + break; + if (!gspca_dev->present || !gspca_dev->streaming) + break; + + /* the frame comes in parts */ + for (;;) { + ret = usb_bulk_msg(gspca_dev->dev, + urb->pipe, + data, + FPIX_MAX_TRANSFER, + &len, FPIX_TIMEOUT); + if (ret < 0) { + /* Most of the time we get a timeout + * error. Just restart. */ + goto again; + } + if (!gspca_dev->present || !gspca_dev->streaming) + goto out; + frame = gspca_get_i_frame(&dev->gspca_dev); + if (frame == NULL) + gspca_dev->last_packet_type = DISCARD_PACKET; + + if (len < FPIX_MAX_TRANSFER || + (data[len - 2] == 0xff && + data[len - 1] == 0xd9)) { + + /* If the result is less than what was asked + * for, then it's the end of the + * frame. Sometimes the jpeg is not complete, + * but there's nothing we can do. We also end + * here if the the jpeg ends right at the end + * of the frame. */ + if (frame) + frame = gspca_frame_add(gspca_dev, + LAST_PACKET, + frame, + data, len); + break; + } /* got a partial image */ if (frame) gspca_frame_add(gspca_dev, gspca_dev->last_packet_type - == LAST_PACKET + == LAST_PACKET ? FIRST_PACKET : INTER_PACKET, - frame, - data, urb->actual_length); - read_frame_part(dev); + frame, data, len); } - break; - } - - case FPIX_NOP: - case FPIX_RESET: - PDEBUG(D_STREAM, "invalid state %d", dev->state); - break; - } -} - -/* Request a new frame */ -static void request_frame(struct usb_fpix *dev) -{ - int ret; - struct gspca_dev *gspca_dev = &dev->gspca_dev; - /* Setup command packet */ - memset(gspca_dev->usb_buf, 0, 12); - gspca_dev->usb_buf[0] = 0xd3; - gspca_dev->usb_buf[7] = 0x01; - - /* Request a frame */ - dev->ctrlreq.bRequestType = - USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE; - dev->ctrlreq.bRequest = USB_REQ_GET_STATUS; - dev->ctrlreq.wValue = 0; - dev->ctrlreq.wIndex = 0; - dev->ctrlreq.wLength = cpu_to_le16(12); - - usb_fill_control_urb(dev->control_urb, - gspca_dev->dev, - usb_sndctrlpipe(gspca_dev->dev, 0), - (unsigned char *) &dev->ctrlreq, - gspca_dev->usb_buf, - 12, urb_callback, gspca_dev); - - ret = usb_submit_urb(dev->control_urb, GFP_ATOMIC); - if (ret) { - dev_new_state(FPIX_RESET); - schedule_delayed_work(&dev->wqe, 1); - PDEBUG(D_STREAM, "usb_submit_urb failed with %d", ret); + /* We must wait before trying reading the next + * frame. If we don't, or if the delay is too short, + * the camera will disconnect. */ + msleep(NEXT_FRAME_DELAY); } -} - -/*--------------------------------------------------------------------------*/ -/* State machine. */ -static void fpix_sm(struct work_struct *work) -{ - struct usb_fpix *dev = container_of(work, struct usb_fpix, wqe.work); - - PDEBUG(D_STREAM, "fpix_sm state %d", dev->state); - - /* verify that the device wasn't unplugged */ - if (!dev->gspca_dev.present) { - PDEBUG(D_STREAM, "device is gone"); - dev_new_state(FPIX_NOP); - complete(&dev->can_close); - return; - } - - if (!dev->streaming) { - PDEBUG(D_STREAM, "stopping state machine"); - dev_new_state(FPIX_NOP); - complete(&dev->can_close); - return; - } - - switch (dev->state) { - case FPIX_RESET: - dev_new_state(FPIX_REQ_FRAME); - schedule_delayed_work(&dev->wqe, HZ / 10); - break; - - case FPIX_REQ_FRAME: - /* get an image */ - request_frame(dev); - break; - - case FPIX_NOP: - case FPIX_READ_FRAME: - PDEBUG(D_STREAM, "invalid state %d", dev->state); - break; - } +out: + PDEBUG(D_STREAM, "dostream stopped"); } /* this function is called at probe time */ static int sd_config(struct gspca_dev *gspca_dev, const struct usb_device_id *id) { + struct usb_fpix *dev = (struct usb_fpix *) gspca_dev; struct cam *cam = &gspca_dev->cam; cam->cam_mode = fpix_mode; cam->nmodes = 1; cam->bulk_size = FPIX_MAX_TRANSFER; -/* gspca_dev->nbalt = 1; * use bulk transfer */ - return 0; -} - -/* Stop streaming and free the ressources allocated by sd_start. */ -static void sd_stopN(struct gspca_dev *gspca_dev) -{ - struct usb_fpix *dev = (struct usb_fpix *) gspca_dev; + INIT_WORK(&dev->work_struct, dostream); - dev->streaming = 0; - - /* Stop the state machine */ - if (dev->state != FPIX_NOP) - wait_for_completion(&dev->can_close); -} - -/* called on streamoff with alt 0 and disconnect */ -static void sd_stop0(struct gspca_dev *gspca_dev) -{ - struct usb_fpix *dev = (struct usb_fpix *) gspca_dev; - - usb_free_urb(dev->control_urb); - dev->control_urb = NULL; -} - -/* Kill an URB that hasn't completed. */ -static void timeout_kill(unsigned long data) -{ - struct urb *urb = (struct urb *) data; - - usb_unlink_urb(urb); + return 0; } /* this function is called at probe and resume time */ static int sd_init(struct gspca_dev *gspca_dev) { - struct usb_fpix *dev = (struct usb_fpix *) gspca_dev; - - INIT_DELAYED_WORK(&dev->wqe, fpix_sm); - - init_timer(&dev->bulk_timer); - dev->bulk_timer.function = timeout_kill; - return 0; } +/* start the camera */ static int sd_start(struct gspca_dev *gspca_dev) { struct usb_fpix *dev = (struct usb_fpix *) gspca_dev; - int ret; - int size_ret; + int ret, len; /* Init the device */ - memset(gspca_dev->usb_buf, 0, 12); - gspca_dev->usb_buf[0] = 0xc6; - gspca_dev->usb_buf[8] = 0x20; - - ret = usb_control_msg(gspca_dev->dev, - usb_sndctrlpipe(gspca_dev->dev, 0), - USB_REQ_GET_STATUS, - USB_DIR_OUT | USB_TYPE_CLASS | - USB_RECIP_INTERFACE, 0, 0, gspca_dev->usb_buf, - 12, FPIX_TIMEOUT); - - if (ret != 12) { - PDEBUG(D_STREAM, "usb_control_msg failed (%d)", ret); - ret = -EIO; - goto error; + ret = command(gspca_dev, 0); + if (ret < 0) { + PDEBUG(D_STREAM, "init failed %d", ret); + return ret; } /* Read the result of the command. Ignore the result, for it * varies with the device. */ ret = usb_bulk_msg(gspca_dev->dev, gspca_dev->urb[0]->pipe, - gspca_dev->usb_buf, FPIX_MAX_TRANSFER, &size_ret, + gspca_dev->urb[0]->transfer_buffer, + FPIX_MAX_TRANSFER, &len, FPIX_TIMEOUT); - if (ret != 0) { - PDEBUG(D_STREAM, "usb_bulk_msg failed (%d)", ret); - ret = -EIO; - goto error; + if (ret < 0) { + PDEBUG(D_STREAM, "usb_bulk_msg failed %d", ret); + return ret; } /* Request a frame, but don't read it */ - memset(gspca_dev->usb_buf, 0, 12); - gspca_dev->usb_buf[0] = 0xd3; - gspca_dev->usb_buf[7] = 0x01; - - ret = usb_control_msg(gspca_dev->dev, - usb_sndctrlpipe(gspca_dev->dev, 0), - USB_REQ_GET_STATUS, - USB_DIR_OUT | USB_TYPE_CLASS | - USB_RECIP_INTERFACE, 0, 0, gspca_dev->usb_buf, - 12, FPIX_TIMEOUT); - if (ret != 12) { - PDEBUG(D_STREAM, "usb_control_msg failed (%d)", ret); - ret = -EIO; - goto error; + ret = command(gspca_dev, 1); + if (ret < 0) { + PDEBUG(D_STREAM, "frame request failed %d", ret); + return ret; } /* Again, reset bulk in endpoint */ usb_clear_halt(gspca_dev->dev, gspca_dev->urb[0]->pipe); - /* Allocate a control URB */ - dev->control_urb = usb_alloc_urb(0, GFP_KERNEL); - if (!dev->control_urb) { - PDEBUG(D_STREAM, "No free urbs available"); - ret = -EIO; - goto error; - } - - /* Various initializations. */ - init_completion(&dev->can_close); - dev->bulk_timer.data = (unsigned long)dev->gspca_dev.urb[0]; - dev->gspca_dev.urb[0]->complete = urb_callback; - dev->streaming = 1; - - /* Schedule a frame request. */ - dev_new_state(FPIX_REQ_FRAME); - schedule_delayed_work(&dev->wqe, 1); + /* Start the workqueue function to do the streaming */ + dev->work_thread = create_singlethread_workqueue(MODULE_NAME); + queue_work(dev->work_thread, &dev->work_struct); return 0; +} + +/* called on streamoff with alt==0 and on disconnect */ +/* the usb_lock is held at entry - restore on exit */ +static void sd_stop0(struct gspca_dev *gspca_dev) +{ + struct usb_fpix *dev = (struct usb_fpix *) gspca_dev; -error: - /* Free the ressources */ - sd_stopN(gspca_dev); - sd_stop0(gspca_dev); - return ret; + /* wait for the work queue to terminate */ + mutex_unlock(&gspca_dev->usb_lock); + destroy_workqueue(dev->work_thread); + mutex_lock(&gspca_dev->usb_lock); + dev->work_thread = NULL; } /* Table of supported USB devices */ @@ -422,12 +268,11 @@ MODULE_DEVICE_TABLE(usb, device_table); /* sub-driver description */ static const struct sd_desc sd_desc = { - .name = MODULE_NAME, + .name = MODULE_NAME, .config = sd_config, - .init = sd_init, - .start = sd_start, - .stopN = sd_stopN, - .stop0 = sd_stop0, + .init = sd_init, + .start = sd_start, + .stop0 = sd_stop0, }; /* -- device connect -- */ @@ -441,13 +286,13 @@ static int sd_probe(struct usb_interface *intf, } static struct usb_driver sd_driver = { - .name = MODULE_NAME, - .id_table = device_table, - .probe = sd_probe, + .name = MODULE_NAME, + .id_table = device_table, + .probe = sd_probe, .disconnect = gspca_disconnect, #ifdef CONFIG_PM .suspend = gspca_suspend, - .resume = gspca_resume, + .resume = gspca_resume, #endif }; @@ -455,12 +300,14 @@ static struct usb_driver sd_driver = { static int __init sd_mod_init(void) { int ret; + ret = usb_register(&sd_driver); if (ret < 0) return ret; PDEBUG(D_PROBE, "registered"); return 0; } + static void __exit sd_mod_exit(void) { usb_deregister(&sd_driver); -- cgit v1.2.3 From d53231f6982970f97db75399f6d6f8b9c9bfc9b5 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Thu, 26 Mar 2009 09:08:48 +0100 Subject: gspca - sonixj: Prefer sonixj instead of sn9c102 for 0471:0327. From: Hans de Goede Prefer the gspca sonixj driver for the Philips SPC600NC webcam instead of the sn9c102 driver. As we've got userreports that it works with the gspca driver, whereas it fails with the sn9c102 driver, see: https://bugzilla.redhat.com/show_bug.cgi?id=477111 Priority: normal Signed-off-by: Hans de Goede Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/sonixj.c | 2 -- linux/drivers/media/video/sn9c102/sn9c102_devtable.h | 2 -- 2 files changed, 4 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/sonixj.c b/linux/drivers/media/video/gspca/sonixj.c index a7fcc169d..c3959f00a 100644 --- a/linux/drivers/media/video/gspca/sonixj.c +++ b/linux/drivers/media/video/gspca/sonixj.c @@ -2228,9 +2228,7 @@ static const __devinitdata struct usb_device_id device_table[] = { #endif {USB_DEVICE(0x045e, 0x00f5), BSI(SN9C105, OV7660, 0x21)}, {USB_DEVICE(0x045e, 0x00f7), BSI(SN9C105, OV7660, 0x21)}, -#if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE {USB_DEVICE(0x0471, 0x0327), BSI(SN9C105, MI0360, 0x5d)}, -#endif {USB_DEVICE(0x0471, 0x0328), BSI(SN9C105, MI0360, 0x5d)}, {USB_DEVICE(0x0471, 0x0330), BSI(SN9C105, MI0360, 0x5d)}, {USB_DEVICE(0x06f8, 0x3004), BSI(SN9C105, OV7660, 0x21)}, diff --git a/linux/drivers/media/video/sn9c102/sn9c102_devtable.h b/linux/drivers/media/video/sn9c102/sn9c102_devtable.h index 41dfb60f4..38a716020 100644 --- a/linux/drivers/media/video/sn9c102/sn9c102_devtable.h +++ b/linux/drivers/media/video/sn9c102/sn9c102_devtable.h @@ -96,9 +96,7 @@ static const struct usb_device_id sn9c102_id_table[] = { #if !defined CONFIG_USB_GSPCA && !defined CONFIG_USB_GSPCA_MODULE { SN9C102_USB_DEVICE(0x045e, 0x00f5, BRIDGE_SN9C105), }, { SN9C102_USB_DEVICE(0x045e, 0x00f7, BRIDGE_SN9C105), }, -#endif { SN9C102_USB_DEVICE(0x0471, 0x0327, BRIDGE_SN9C105), }, -#if !defined CONFIG_USB_GSPCA && !defined CONFIG_USB_GSPCA_MODULE { SN9C102_USB_DEVICE(0x0471, 0x0328, BRIDGE_SN9C105), }, #endif { SN9C102_USB_DEVICE(0x0c45, 0x60c0, BRIDGE_SN9C105), }, -- cgit v1.2.3 From eb1a26eff5dd520a2e8e260b6cf33c071641122a Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Thu, 26 Mar 2009 09:10:55 +0100 Subject: gspca - zc3xx: The webcam DLink DSB - C320 has the sensor pas106. From: Douglas Schilling Landgraf Reported-by: Bruna Griebeler Priority: normal Tested-by: Bruna Griebeler Signed-off-by: Douglas Schilling Landgraf Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/zc3xx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/zc3xx.c b/linux/drivers/media/video/gspca/zc3xx.c index e2ab9c2eb..a90b3b0d4 100644 --- a/linux/drivers/media/video/gspca/zc3xx.c +++ b/linux/drivers/media/video/gspca/zc3xx.c @@ -7662,7 +7662,7 @@ static const __devinitdata struct usb_device_id device_table[] = { {USB_DEVICE(0x055f, 0xd004)}, {USB_DEVICE(0x0698, 0x2003)}, {USB_DEVICE(0x0ac8, 0x0301), .driver_info = SENSOR_PAS106}, - {USB_DEVICE(0x0ac8, 0x0302)}, + {USB_DEVICE(0x0ac8, 0x0302), .driver_info = SENSOR_PAS106}, {USB_DEVICE(0x0ac8, 0x301b)}, {USB_DEVICE(0x0ac8, 0x303b)}, {USB_DEVICE(0x0ac8, 0x305b), .driver_info = SENSOR_TAS5130C_VF0250}, -- cgit v1.2.3 From e1b327c44494755c635ee8cd086c1cd070a4f20b Mon Sep 17 00:00:00 2001 From: Janne Grunau Date: Sat, 28 Mar 2009 00:01:40 +0100 Subject: hdpvr: add struct v4l2_device From: Janne Grunau Priority: normal Signed-off-by: Janne Grunau --- linux/drivers/media/video/hdpvr/hdpvr-core.c | 9 +++++++++ linux/drivers/media/video/hdpvr/hdpvr.h | 4 ++++ 2 files changed, 13 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/hdpvr/hdpvr-core.c b/linux/drivers/media/video/hdpvr/hdpvr-core.c index 547833eb6..3b19a259d 100644 --- a/linux/drivers/media/video/hdpvr/hdpvr-core.c +++ b/linux/drivers/media/video/hdpvr/hdpvr-core.c @@ -278,6 +278,13 @@ static int hdpvr_probe(struct usb_interface *interface, err("Out of memory"); goto error; } + + /* register v4l2_device early so it can be used for printks */ + if (v4l2_device_register(&interface->dev, &dev->v4l2_dev)) { + err("v4l2_device_register failed"); + goto error; + } + mutex_init(&dev->io_mutex); mutex_init(&dev->i2c_mutex); mutex_init(&dev->usbc_mutex); @@ -387,6 +394,7 @@ static void hdpvr_disconnect(struct usb_interface *interface) /* prevent more I/O from starting and stop any ongoing */ mutex_lock(&dev->io_mutex); dev->status = STATUS_DISCONNECTED; + v4l2_device_disconnect(&dev->v4l2_dev); video_unregister_device(dev->video_dev); wake_up_interruptible(&dev->wait_data); wake_up_interruptible(&dev->wait_buffer); @@ -413,6 +421,7 @@ static void hdpvr_disconnect(struct usb_interface *interface) printk(KERN_INFO "Hauppauge HD PVR: device /dev/video%d disconnected\n", minor); + v4l2_device_unregister(&dev->v4l2_dev); kfree(dev->usbc_buf); kfree(dev); } diff --git a/linux/drivers/media/video/hdpvr/hdpvr.h b/linux/drivers/media/video/hdpvr/hdpvr.h index 3af415d81..1edd87591 100644 --- a/linux/drivers/media/video/hdpvr/hdpvr.h +++ b/linux/drivers/media/video/hdpvr/hdpvr.h @@ -15,6 +15,8 @@ #include #include +#include + #define HDPVR_MAJOR_VERSION 0 #define HDPVR_MINOR_VERSION 2 #define HDPVR_RELEASE 0 @@ -65,6 +67,8 @@ struct hdpvr_device { struct video_device *video_dev; /* the usb device for this device */ struct usb_device *udev; + /* v4l2-device unused */ + struct v4l2_device v4l2_dev; /* the max packet size of the bulk endpoint */ size_t bulk_in_size; -- cgit v1.2.3 From 9cd596ebf1895fbde84391135359f7d7cc401fe4 Mon Sep 17 00:00:00 2001 From: Janne Grunau Date: Sat, 28 Mar 2009 00:09:40 +0100 Subject: hdpvr: convert printing macros to v4l2_* with struct v4l2_device From: Janne Grunau it gives us a nice and unique prefix per device Priority: normal Signed-off-by: Janne Grunau --- linux/drivers/media/video/hdpvr/hdpvr-control.c | 22 ++++----- linux/drivers/media/video/hdpvr/hdpvr-core.c | 56 +++++++++++++---------- linux/drivers/media/video/hdpvr/hdpvr-video.c | 61 +++++++++++++------------ 3 files changed, 75 insertions(+), 64 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/hdpvr/hdpvr-control.c b/linux/drivers/media/video/hdpvr/hdpvr-control.c index 51de74aeb..06791749d 100644 --- a/linux/drivers/media/video/hdpvr/hdpvr-control.c +++ b/linux/drivers/media/video/hdpvr/hdpvr-control.c @@ -40,9 +40,9 @@ int hdpvr_config_call(struct hdpvr_device *dev, uint value, u8 valbuf) dev->usbc_buf, 1, 10000); mutex_unlock(&dev->usbc_mutex); - dev_dbg(&dev->udev->dev, - "config call request for value 0x%x returned %d\n", value, - ret); + v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev, + "config call request for value 0x%x returned %d\n", value, + ret); return ret < 0 ? ret : 0; } @@ -57,7 +57,7 @@ struct hdpvr_video_info *get_video_info(struct hdpvr_device *dev) vidinf = kzalloc(sizeof(struct hdpvr_video_info), GFP_KERNEL); if (!vidinf) { - dev_err(&dev->udev->dev, "out of memory"); + v4l2_err(&dev->v4l2_dev, "out of memory\n"); goto err; } @@ -78,8 +78,8 @@ struct hdpvr_video_info *get_video_info(struct hdpvr_device *dev) if (hdpvr_debug & MSG_INFO) { hex_dump_to_buffer(dev->usbc_buf, 5, 16, 1, print_buf, sizeof(print_buf), 0); - dev_dbg(&dev->udev->dev, "get video info returned: %d, %s\n", - ret, print_buf); + v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev, + "get video info returned: %d, %s\n", ret, print_buf); } #endif mutex_unlock(&dev->usbc_mutex); @@ -111,9 +111,9 @@ int get_input_lines_info(struct hdpvr_device *dev) if (hdpvr_debug & MSG_INFO) { hex_dump_to_buffer(dev->usbc_buf, 3, 16, 1, print_buf, sizeof(print_buf), 0); - dev_dbg(&dev->udev->dev, - "get input lines info returned: %d, %s\n", ret, - print_buf); + v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev, + "get input lines info returned: %d, %s\n", ret, + print_buf); } #endif lines = dev->usbc_buf[1] << 8 | dev->usbc_buf[0]; @@ -155,8 +155,8 @@ int hdpvr_set_audio(struct hdpvr_device *dev, u8 input, dev->usbc_buf[1] = 1; else { mutex_unlock(&dev->usbc_mutex); - dev_err(&dev->udev->dev, "invalid audio codec %d\n", - codec); + v4l2_err(&dev->v4l2_dev, "invalid audio codec %d\n", + codec); ret = -EINVAL; goto error; } diff --git a/linux/drivers/media/video/hdpvr/hdpvr-core.c b/linux/drivers/media/video/hdpvr/hdpvr-core.c index 3b19a259d..188bd5aea 100644 --- a/linux/drivers/media/video/hdpvr/hdpvr-core.c +++ b/linux/drivers/media/video/hdpvr/hdpvr-core.c @@ -125,7 +125,7 @@ static int device_authorization(struct hdpvr_device *dev) size_t buf_size = 46; char *print_buf = kzalloc(5*buf_size+1, GFP_KERNEL); if (!print_buf) { - dev_err(&dev->udev->dev, "Out of memory"); + v4l2_err(&dev->v4l2_dev, "Out of memory\n"); goto error; } #endif @@ -138,17 +138,17 @@ static int device_authorization(struct hdpvr_device *dev) dev->usbc_buf, 46, 10000); if (ret != 46) { - dev_err(&dev->udev->dev, - "unexpected answer of status request, len %d", ret); + v4l2_err(&dev->v4l2_dev, + "unexpected answer of status request, len %d\n", ret); goto error; } #ifdef HDPVR_DEBUG else { hex_dump_to_buffer(dev->usbc_buf, 46, 16, 1, print_buf, sizeof(print_buf), 0); - dev_dbg(&dev->udev->dev, - "Status request returned, len %d: %s\n", - ret, print_buf); + v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev, + "Status request returned, len %d: %s\n", + ret, print_buf); } #endif if (dev->usbc_buf[1] == HDPVR_FIRMWARE_VERSION) { @@ -156,11 +156,11 @@ static int device_authorization(struct hdpvr_device *dev) } else if (dev->usbc_buf[1] == HDPVR_FIRMWARE_VERSION_AC3) { dev->flags |= HDPVR_FLAG_AC3_CAP; } else if (dev->usbc_buf[1] > HDPVR_FIRMWARE_VERSION_AC3) { - dev_notice(&dev->udev->dev, "untested firmware version 0x%x, " - "the driver might not work\n", dev->usbc_buf[1]); + v4l2_info(&dev->v4l2_dev, "untested firmware version 0x%x, " + "the driver might not work\n", dev->usbc_buf[1]); dev->flags |= HDPVR_FLAG_AC3_CAP; } else { - dev_err(&dev->udev->dev, "unknown firmware version 0x%x\n", + v4l2_err(&dev->v4l2_dev, "unknown firmware version 0x%x\n", dev->usbc_buf[1]); ret = -EINVAL; goto error; @@ -169,12 +169,14 @@ static int device_authorization(struct hdpvr_device *dev) response = dev->usbc_buf+38; #ifdef HDPVR_DEBUG hex_dump_to_buffer(response, 8, 16, 1, print_buf, sizeof(print_buf), 0); - dev_dbg(&dev->udev->dev, "challenge: %s\n", print_buf); + v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev, "challenge: %s\n", + print_buf); #endif challenge(response); #ifdef HDPVR_DEBUG hex_dump_to_buffer(response, 8, 16, 1, print_buf, sizeof(print_buf), 0); - dev_dbg(&dev->udev->dev, " response: %s\n", print_buf); + v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev, " response: %s\n", + print_buf); #endif msleep(100); @@ -184,7 +186,8 @@ static int device_authorization(struct hdpvr_device *dev) 0x0000, 0x0000, response, 8, 10000); - dev_dbg(&dev->udev->dev, "magic request returned %d\n", ret); + v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev, + "magic request returned %d\n", ret); mutex_unlock(&dev->usbc_mutex); retval = ret != 8; @@ -214,12 +217,13 @@ static int hdpvr_device_init(struct hdpvr_device *dev) CTRL_LOW_PASS_FILTER_VALUE, CTRL_DEFAULT_INDEX, buf, 4, 1000); - dev_dbg(&dev->udev->dev, "control request returned %d\n", ret); + v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev, + "control request returned %d\n", ret); mutex_unlock(&dev->usbc_mutex); vidinf = get_video_info(dev); if (!vidinf) - dev_dbg(&dev->udev->dev, + v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev, "no valid video signal or device init failed\n"); else kfree(vidinf); @@ -231,7 +235,8 @@ static int hdpvr_device_init(struct hdpvr_device *dev) usb_sndctrlpipe(dev->udev, 0), 0xd4, 0x38, 0, 0, buf, 1, 1000); - dev_dbg(&dev->udev->dev, "control request returned %d\n", ret); + v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev, + "control request returned %d\n", ret); /* boost analog audio */ buf[0] = boost_audio; @@ -239,7 +244,8 @@ static int hdpvr_device_init(struct hdpvr_device *dev) usb_sndctrlpipe(dev->udev, 0), 0xd5, 0x38, 0, 0, buf, 1, 1000); - dev_dbg(&dev->udev->dev, "control request returned %d\n", ret); + v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev, + "control request returned %d\n", ret); mutex_unlock(&dev->usbc_mutex); dev->status = STATUS_IDLE; @@ -290,7 +296,7 @@ static int hdpvr_probe(struct usb_interface *interface, mutex_init(&dev->usbc_mutex); dev->usbc_buf = kmalloc(64, GFP_KERNEL); if (!dev->usbc_buf) { - dev_err(&dev->udev->dev, "Out of memory"); + v4l2_err(&dev->v4l2_dev, "Out of memory\n"); goto error; } @@ -332,26 +338,27 @@ static int hdpvr_probe(struct usb_interface *interface, } if (!dev->bulk_in_endpointAddr) { - err("Could not find bulk-in endpoint"); + v4l2_err(&dev->v4l2_dev, "Could not find bulk-in endpoint\n"); goto error; } /* init the device */ if (hdpvr_device_init(dev)) { - err("device init failed"); + v4l2_err(&dev->v4l2_dev, "device init failed\n"); goto error; } mutex_lock(&dev->io_mutex); if (hdpvr_alloc_buffers(dev, NUM_BUFFERS)) { - err("allocating transfer buffers failed"); + v4l2_err(&dev->v4l2_dev, + "allocating transfer buffers failed\n"); goto error; } mutex_unlock(&dev->io_mutex); if (hdpvr_register_videodev(dev, &interface->dev, video_nr[atomic_inc_return(&dev_nr)])) { - err("registering videodev failed"); + v4l2_err(&dev->v4l2_dev, "registering videodev failed\n"); goto error; } @@ -359,7 +366,7 @@ static int hdpvr_probe(struct usb_interface *interface, /* until i2c is working properly */ retval = 0; /* hdpvr_register_i2c_adapter(dev); */ if (retval < 0) { - err("registering i2c adapter failed"); + v4l2_err(&dev->v4l2_dev, "registering i2c adapter failed\n"); goto error; } #endif /* CONFIG_I2C */ @@ -368,7 +375,7 @@ static int hdpvr_probe(struct usb_interface *interface, usb_set_intfdata(interface, dev); /* let the user know what node this device is now attached to */ - v4l2_info(dev->video_dev, "device now attached to /dev/video%d\n", + v4l2_info(&dev->v4l2_dev, "device now attached to /dev/video%d\n", dev->video_dev->minor); return 0; @@ -418,8 +425,7 @@ static void hdpvr_disconnect(struct usb_interface *interface) atomic_dec(&dev_nr); - printk(KERN_INFO "Hauppauge HD PVR: device /dev/video%d disconnected\n", - minor); + v4l2_info(&dev->v4l2_dev, "device /dev/video%d disconnected\n", minor); v4l2_device_unregister(&dev->v4l2_dev); kfree(dev->usbc_buf); diff --git a/linux/drivers/media/video/hdpvr/hdpvr-video.c b/linux/drivers/media/video/hdpvr/hdpvr-video.c index 2fe57303c..f6e1bcefd 100644 --- a/linux/drivers/media/video/hdpvr/hdpvr-video.c +++ b/linux/drivers/media/video/hdpvr/hdpvr-video.c @@ -28,11 +28,12 @@ #define BULK_URB_TIMEOUT 1250 /* 1.25 seconds */ -#define print_buffer_status() v4l2_dbg(MSG_BUFFER, hdpvr_debug, dev->video_dev,\ - "%s:%d buffer stat: %d free, %d proc\n",\ - __func__, __LINE__, \ - list_size(&dev->free_buff_list), \ - list_size(&dev->rec_buff_list)) +#define print_buffer_status() { \ + v4l2_dbg(MSG_BUFFER, hdpvr_debug, &dev->v4l2_dev, \ + "%s:%d buffer stat: %d free, %d proc\n", \ + __func__, __LINE__, \ + list_size(&dev->free_buff_list), \ + list_size(&dev->rec_buff_list)); } struct hdpvr_fh { struct hdpvr_device *dev; @@ -123,21 +124,21 @@ int hdpvr_alloc_buffers(struct hdpvr_device *dev, uint count) struct hdpvr_buffer *buf; struct urb *urb; - v4l2_dbg(MSG_INFO, hdpvr_debug, dev->video_dev, + v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev, "allocating %u buffers\n", count); for (i = 0; i < count; i++) { buf = kzalloc(sizeof(struct hdpvr_buffer), GFP_KERNEL); if (!buf) { - err("cannot allocate buffer"); + v4l2_err(&dev->v4l2_dev, "cannot allocate buffer\n"); goto exit; } buf->dev = dev; urb = usb_alloc_urb(0, GFP_KERNEL); if (!urb) { - err("cannot allocate urb"); + v4l2_err(&dev->v4l2_dev, "cannot allocate urb\n"); goto exit; } buf->urb = urb; @@ -145,7 +146,8 @@ int hdpvr_alloc_buffers(struct hdpvr_device *dev, uint count) mem = usb_buffer_alloc(dev->udev, dev->bulk_in_size, GFP_KERNEL, &urb->transfer_dma); if (!mem) { - err("cannot allocate usb transfer buffer"); + v4l2_err(&dev->v4l2_dev, + "cannot allocate usb transfer buffer\n"); goto exit; } @@ -178,7 +180,8 @@ static int hdpvr_submit_buffers(struct hdpvr_device *dev) buf = list_entry(dev->free_buff_list.next, struct hdpvr_buffer, buff_list); if (buf->status != BUFSTAT_AVAILABLE) { - err("buffer not marked as availbale"); + v4l2_err(&dev->v4l2_dev, + "buffer not marked as availbale\n"); ret = -EFAULT; goto err; } @@ -188,7 +191,9 @@ static int hdpvr_submit_buffers(struct hdpvr_device *dev) urb->actual_length = 0; ret = usb_submit_urb(urb, GFP_KERNEL); if (ret) { - err("usb_submit_urb in %s returned %d", __func__, ret); + v4l2_err(&dev->v4l2_dev, + "usb_submit_urb in %s returned %d\n", + __func__, ret); if (++err_count > 2) break; continue; @@ -228,7 +233,7 @@ static void hdpvr_transmit_buffers(struct work_struct *work) while (dev->status == STATUS_STREAMING) { if (hdpvr_submit_buffers(dev)) { - v4l2_err(dev->video_dev, "couldn't submit buffers\n"); + v4l2_err(&dev->v4l2_dev, "couldn't submit buffers\n"); goto error; } if (wait_event_interruptible(dev->wait_buffer, @@ -237,11 +242,11 @@ static void hdpvr_transmit_buffers(struct work_struct *work) goto error; } - v4l2_dbg(MSG_INFO, hdpvr_debug, dev->video_dev, + v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev, "transmit worker exited\n"); return; error: - v4l2_dbg(MSG_INFO, hdpvr_debug, dev->video_dev, + v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev, "transmit buffers errored\n"); dev->status = STATUS_ERROR; } @@ -260,7 +265,7 @@ static int hdpvr_start_streaming(struct hdpvr_device *dev) vidinf = get_video_info(dev); if (vidinf) { - v4l2_dbg(MSG_BUFFER, hdpvr_debug, dev->video_dev, + v4l2_dbg(MSG_BUFFER, hdpvr_debug, &dev->v4l2_dev, "video signal: %dx%d@%dhz\n", vidinf->width, vidinf->height, vidinf->fps); kfree(vidinf); @@ -269,7 +274,7 @@ static int hdpvr_start_streaming(struct hdpvr_device *dev) ret = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0), 0xb8, 0x38, 0x1, 0, NULL, 0, 8000); - v4l2_dbg(MSG_BUFFER, hdpvr_debug, dev->video_dev, + v4l2_dbg(MSG_BUFFER, hdpvr_debug, &dev->v4l2_dev, "encoder start control request returned %d\n", ret); hdpvr_config_call(dev, CTRL_START_STREAMING_VALUE, 0x00); @@ -277,14 +282,14 @@ static int hdpvr_start_streaming(struct hdpvr_device *dev) INIT_WORK(&dev->worker, hdpvr_transmit_buffers); queue_work(dev->workqueue, &dev->worker); - v4l2_dbg(MSG_BUFFER, hdpvr_debug, dev->video_dev, + v4l2_dbg(MSG_BUFFER, hdpvr_debug, &dev->v4l2_dev, "streaming started\n"); dev->status = STATUS_STREAMING; return 0; } msleep(250); - v4l2_dbg(MSG_INFO, hdpvr_debug, dev->video_dev, + v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev, "no video signal at input %d\n", dev->options.video_input); return -EAGAIN; } @@ -330,14 +335,14 @@ static int hdpvr_open(struct file *file) dev = (struct hdpvr_device *)video_get_drvdata(video_devdata(file)); if (!dev) { - err("open failing with with ENODEV"); + v4l2_err(&dev->v4l2_dev, "open failing with with ENODEV\n"); retval = -ENODEV; goto err; } fh = kzalloc(sizeof(struct hdpvr_fh), GFP_KERNEL); if (!fh) { - err("Out of memory?"); + v4l2_err(&dev->v4l2_dev, "Out of memory\n"); goto err; } /* lock the device to allow correctly handling errors @@ -396,8 +401,8 @@ static ssize_t hdpvr_read(struct file *file, char __user *buffer, size_t count, mutex_lock(&dev->io_mutex); if (dev->status == STATUS_IDLE) { if (hdpvr_start_streaming(dev)) { - v4l2_dbg(MSG_INFO, hdpvr_debug, dev->video_dev, - "start_streaming failed"); + v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev, + "start_streaming failed\n"); ret = -EIO; msleep(200); dev->status = STATUS_IDLE; @@ -445,7 +450,7 @@ static ssize_t hdpvr_read(struct file *file, char __user *buffer, size_t count, if (copy_to_user(buffer, urb->transfer_buffer + buf->pos, cnt)) { - err("read: copy_to_user failed"); + v4l2_err(&dev->v4l2_dev, "read: copy_to_user failed\n"); if (!ret) ret = -EFAULT; goto err; @@ -493,8 +498,8 @@ static unsigned int hdpvr_poll(struct file *filp, poll_table *wait) if (dev->status == STATUS_IDLE) { if (hdpvr_start_streaming(dev)) { - v4l2_dbg(MSG_BUFFER, hdpvr_debug, dev->video_dev, - "start_streaming failed"); + v4l2_dbg(MSG_BUFFER, hdpvr_debug, &dev->v4l2_dev, + "start_streaming failed\n"); dev->status = STATUS_IDLE; } @@ -1130,7 +1135,7 @@ static int vidioc_encoder_cmd(struct file *filp, void *priv, res = hdpvr_stop_streaming(dev); break; default: - v4l2_dbg(MSG_INFO, hdpvr_debug, dev->video_dev, + v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev, "Unsupported encoder cmd %d\n", a->cmd); res = -EINVAL; } @@ -1197,7 +1202,7 @@ int hdpvr_register_videodev(struct hdpvr_device *dev, struct device *parent, /* setup and register video device */ dev->video_dev = video_device_alloc(); if (!dev->video_dev) { - err("video_device_alloc() failed"); + v4l2_err(&dev->v4l2_dev, "video_device_alloc() failed\n"); goto error; } @@ -1207,7 +1212,7 @@ int hdpvr_register_videodev(struct hdpvr_device *dev, struct device *parent, video_set_drvdata(dev->video_dev, dev); if (video_register_device(dev->video_dev, VFL_TYPE_GRABBER, devnum)) { - err("V4L2 device registration failed"); + v4l2_err(&dev->v4l2_dev, "video_device registration failed\n"); goto error; } -- cgit v1.2.3 From 1fcaa2a07d4c815b9f8a8bfdd738b22a46760ede Mon Sep 17 00:00:00 2001 From: Janne Grunau Date: Sat, 28 Mar 2009 00:21:17 +0100 Subject: hdpvr: empty internal device buffer after stopping streaming From: Janne Grunau Makes the next capturing starting faster and more reliable. Priority: normal Signed-off-by: Janne Grunau --- linux/drivers/media/video/hdpvr/hdpvr-video.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/hdpvr/hdpvr-video.c b/linux/drivers/media/video/hdpvr/hdpvr-video.c index f6e1bcefd..3e6ffee8d 100644 --- a/linux/drivers/media/video/hdpvr/hdpvr-video.c +++ b/linux/drivers/media/video/hdpvr/hdpvr-video.c @@ -298,11 +298,20 @@ static int hdpvr_start_streaming(struct hdpvr_device *dev) /* function expects dev->io_mutex to be hold by caller */ static int hdpvr_stop_streaming(struct hdpvr_device *dev) { + uint actual_length, c = 0; + u8 *buf; + if (dev->status == STATUS_IDLE) return 0; else if (dev->status != STATUS_STREAMING) return -EAGAIN; + buf = kmalloc(dev->bulk_in_size, GFP_KERNEL); + if (!buf) + v4l2_err(&dev->v4l2_dev, "failed to allocate temporary buffer " + "for emptying the internal device buffer. " + "Next capture start will be slow\n"); + dev->status = STATUS_SHUTTING_DOWN; hdpvr_config_call(dev, CTRL_STOP_STREAMING_VALUE, 0x00); mutex_unlock(&dev->io_mutex); @@ -316,6 +325,23 @@ static int hdpvr_stop_streaming(struct hdpvr_device *dev) /* kill the still outstanding urbs */ hdpvr_cancel_queue(dev); + /* emptying the device buffer beforeshutting it down */ + while (buf && ++c < 500 && + !usb_bulk_msg(dev->udev, + usb_rcvbulkpipe(dev->udev, + dev->bulk_in_endpointAddr), + buf, dev->bulk_in_size, &actual_length, + BULK_URB_TIMEOUT)) { + /* wait */ + msleep(5); + v4l2_dbg(MSG_BUFFER, hdpvr_debug, &dev->v4l2_dev, + "%2d: got %d bytes\n", c, actual_length); + } + kfree(buf); + v4l2_dbg(MSG_BUFFER, hdpvr_debug, &dev->v4l2_dev, + "used %d urbs to empty device buffers\n", c-1); + msleep(10); + dev->status = STATUS_IDLE; return 0; -- cgit v1.2.3 From b02ab8e4ddec4578f3d68e296e76032accdd378b Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 26 Mar 2009 09:45:53 +0000 Subject: Remove debug output from stb6100_cfg.h From: Artem Makhutov This patch removes the debug output from stb6100_cfg.h as it is flooding the syslog with tuning data during normal operation. Signed-off-by: Artem Makhutov Acked-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/frontends/stb6100_cfg.h | 4 ---- 1 file changed, 4 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/frontends/stb6100_cfg.h b/linux/drivers/media/dvb/frontends/stb6100_cfg.h index d3133405d..6314d18c7 100644 --- a/linux/drivers/media/dvb/frontends/stb6100_cfg.h +++ b/linux/drivers/media/dvb/frontends/stb6100_cfg.h @@ -36,7 +36,6 @@ static int stb6100_get_frequency(struct dvb_frontend *fe, u32 *frequency) return err; } *frequency = t_state.frequency; - printk("%s: Frequency=%d\n", __func__, t_state.frequency); } return 0; } @@ -59,7 +58,6 @@ static int stb6100_set_frequency(struct dvb_frontend *fe, u32 frequency) return err; } } - printk("%s: Frequency=%d\n", __func__, t_state.frequency); return 0; } @@ -81,7 +79,6 @@ static int stb6100_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth) } *bandwidth = t_state.bandwidth; } - printk("%s: Bandwidth=%d\n", __func__, t_state.bandwidth); return 0; } @@ -103,6 +100,5 @@ static int stb6100_set_bandwidth(struct dvb_frontend *fe, u32 bandwidth) return err; } } - printk("%s: Bandwidth=%d\n", __func__, t_state.bandwidth); return 0; } -- cgit v1.2.3 From 39f77adb32b2939a0c5ffd2cbbe0600a0a83e00b Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 26 Mar 2009 14:31:08 +0000 Subject: allow v4l2 drivers to provide a get_unmapped_area handler MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: Daniel Glöckner Shared memory mappings on nommu machines require a get_unmapped_area file operation that suggests an address for the mapping. This patch adds a way for v4l2 drivers to provide this callback. Signed-off-by: Daniel Glöckner Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/v4l2-dev.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/v4l2-dev.c b/linux/drivers/media/video/v4l2-dev.c index 5e9b46c21..2c4d38979 100644 --- a/linux/drivers/media/video/v4l2-dev.c +++ b/linux/drivers/media/video/v4l2-dev.c @@ -236,6 +236,23 @@ static long v4l2_unlocked_ioctl(struct file *filp, return vdev->fops->unlocked_ioctl(filp, cmd, arg); } +#ifdef CONFIG_MMU +#define v4l2_get_unmapped_area NULL +#else +static unsigned long v4l2_get_unmapped_area(struct file *filp, + unsigned long addr, unsigned long len, unsigned long pgoff, + unsigned long flags) +{ + struct video_device *vdev = video_devdata(filp); + + if (!vdev->fops->get_unmapped_area) + return -ENOSYS; + if (video_is_unregistered(vdev)) + return -ENODEV; + return vdev->fops->get_unmapped_area(filp, addr, len, pgoff, flags); +} +#endif + static int v4l2_mmap(struct file *filp, struct vm_area_struct *vm) { struct video_device *vdev = video_devdata(filp); @@ -288,6 +305,7 @@ static const struct file_operations v4l2_unlocked_fops = { .read = v4l2_read, .write = v4l2_write, .open = v4l2_open, + .get_unmapped_area = v4l2_get_unmapped_area, .mmap = v4l2_mmap, .unlocked_ioctl = v4l2_unlocked_ioctl, #ifdef CONFIG_COMPAT @@ -303,6 +321,7 @@ static const struct file_operations v4l2_fops = { .read = v4l2_read, .write = v4l2_write, .open = v4l2_open, + .get_unmapped_area = v4l2_get_unmapped_area, .mmap = v4l2_mmap, .ioctl = v4l2_ioctl, #ifdef CONFIG_COMPAT -- cgit v1.2.3 From 83e8e34fdce5fd6d2092b12a4a0d3b95833635b3 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 26 Mar 2009 20:44:38 +0000 Subject: [PATCH] cx88: Missing failure checks From: Alan Cox The ioremap one was reported in October 2007 (Bug 9146), the kmalloc one was blindingly obvious while looking at the ioremap one The bug suggests some other configuration for lots of I/O memory (32MB per device is ioremapped) but I'll leave that to the real maintainers Signed-off-by: Alan Cox Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/cx88/cx88-cards.c | 7 +++++++ 1 file changed, 7 insertions(+) (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 719315d02..2f30d34be 100644 --- a/linux/drivers/media/video/cx88/cx88-cards.c +++ b/linux/drivers/media/video/cx88/cx88-cards.c @@ -3160,6 +3160,8 @@ struct cx88_core *cx88_core_create(struct pci_dev *pci, int nr) int i; core = kzalloc(sizeof(*core), GFP_KERNEL); + if (core == NULL) + return NULL; atomic_inc(&core->refcount); core->pci_bus = pci->bus->number; @@ -3190,6 +3192,11 @@ struct cx88_core *cx88_core_create(struct pci_dev *pci, int nr) pci_resource_len(pci, 0)); core->bmmio = (u8 __iomem *)core->lmmio; + if (core->lmmio == NULL) { + kfree(core); + return NULL; + } + /* board config */ core->boardnr = UNSET; if (card[core->nr] < ARRAY_SIZE(cx88_boards)) -- cgit v1.2.3 From 03ddd50e8bf14d07eacd58ead6b8fd9236ef0982 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 26 Mar 2009 20:47:48 +0000 Subject: [PATCH] pluto2: silence spew of card hung up messages From: Alan Cox If the card is ejected on some systems you get a spew of messages as other shared IRQ devices interrupt between the card eject and the card IRQ disable. We don't need to spew them all out Closes #7472 Signed-off-by: Alan Cox Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/pluto2/pluto2.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/pluto2/pluto2.c b/linux/drivers/media/dvb/pluto2/pluto2.c index 8522757a5..b27073216 100644 --- a/linux/drivers/media/dvb/pluto2/pluto2.c +++ b/linux/drivers/media/dvb/pluto2/pluto2.c @@ -116,6 +116,7 @@ struct pluto { /* irq */ unsigned int overflow; + unsigned int dead; /* dma */ dma_addr_t dma_addr; @@ -344,8 +345,10 @@ static irqreturn_t pluto_irq(int irq, void *dev_id) return IRQ_NONE; if (tscr == 0xffffffff) { - // FIXME: maybe recover somehow - dev_err(&pluto->pdev->dev, "card hung up :(\n"); + if (pluto->dead == 0) + dev_err(&pluto->pdev->dev, "card has hung or been ejected.\n"); + /* It's dead Jim */ + pluto->dead = 1; return IRQ_HANDLED; } -- cgit v1.2.3 From 5512312e53f2dcc8c53a6a48363e5b4647be9152 Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Fri, 27 Mar 2009 01:27:10 +0200 Subject: af9015: remove experimental From: Antti Palosaari Remove experimental from DVB USB AF9015 device. Priority: normal Signed-off-by: Antti Palosaari --- linux/drivers/media/dvb/dvb-usb/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/dvb-usb/Kconfig b/linux/drivers/media/dvb/dvb-usb/Kconfig index 6103caad1..53a4a4732 100644 --- a/linux/drivers/media/dvb/dvb-usb/Kconfig +++ b/linux/drivers/media/dvb/dvb-usb/Kconfig @@ -294,7 +294,7 @@ config DVB_USB_DTV5100 config DVB_USB_AF9015 tristate "Afatech AF9015 DVB-T USB2.0 support" - depends on DVB_USB && EXPERIMENTAL + depends on DVB_USB select DVB_AF9013 select DVB_PLL if !DVB_FE_CUSTOMISE select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMISE -- cgit v1.2.3 From 670efc5efe630fe0ea45bfb66d10c69f857e7930 Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Fri, 27 Mar 2009 01:41:05 +0200 Subject: af9015: add new USB ID for KWorld USB DVB-T TV Stick II (VS-DVB-T 395U) From: Antti Palosaari Add new USB ID (1b80:e395) for KWorld USB DVB-T TV Stick II (VS-DVB-T 395U). Thanks to Julian Aron Prenner for reporting this. Priority: normal Signed-off-by: Antti Palosaari --- linux/drivers/media/dvb/dvb-usb/af9015.c | 4 +++- linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/dvb-usb/af9015.c b/linux/drivers/media/dvb/dvb-usb/af9015.c index ca7609583..d998d7b59 100644 --- a/linux/drivers/media/dvb/dvb-usb/af9015.c +++ b/linux/drivers/media/dvb/dvb-usb/af9015.c @@ -1240,6 +1240,7 @@ static struct usb_device_id af9015_usb_table[] = { /* 15 */{USB_DEVICE(USB_VID_MSI_2, USB_PID_MSI_DIGI_VOX_MINI_III)}, {USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_395U)}, {USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_395U_2)}, + {USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_395U_3)}, {0}, }; MODULE_DEVICE_TABLE(usb, af9015_usb_table); @@ -1440,7 +1441,8 @@ static struct dvb_usb_device_properties af9015_properties[] = { .name = "KWorld USB DVB-T TV Stick II " \ "(VS-DVB-T 395U)", .cold_ids = {&af9015_usb_table[16], - &af9015_usb_table[17], NULL}, + &af9015_usb_table[17], + &af9015_usb_table[18], NULL}, .warm_ids = {NULL}, }, } 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 0f239c668..ba4115d1a 100644 --- a/linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h +++ b/linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h @@ -101,6 +101,7 @@ #define USB_PID_KWORLD_399U 0xe399 #define USB_PID_KWORLD_395U 0xe396 #define USB_PID_KWORLD_395U_2 0xe39b +#define USB_PID_KWORLD_395U_3 0xe395 #define USB_PID_KWORLD_PC160_2T 0xc160 #define USB_PID_KWORLD_VSTREAM_COLD 0x17de #define USB_PID_KWORLD_VSTREAM_WARM 0x17df -- cgit v1.2.3 From 01e907edffbde4b2f45bd79bc59db7a2107b419e Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Fri, 27 Mar 2009 02:07:18 +0200 Subject: af9015: add support for TrekStor DVB-T USB Stick From: Marc Schneider Add USB ID (15a4:901b) and remote for TrekStor DVB-T USB Stick. Priority: normal Signed-off-by: Marc Schneider Signed-off-by: Antti Palosaari --- linux/drivers/media/dvb/dvb-usb/af9015.c | 18 ++++++- linux/drivers/media/dvb/dvb-usb/af9015.h | 67 ++++++++++++++++++++++++++- linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h | 1 + 3 files changed, 83 insertions(+), 3 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/dvb-usb/af9015.c b/linux/drivers/media/dvb/dvb-usb/af9015.c index d998d7b59..e7a8f61da 100644 --- a/linux/drivers/media/dvb/dvb-usb/af9015.c +++ b/linux/drivers/media/dvb/dvb-usb/af9015.c @@ -836,6 +836,16 @@ static int af9015_read_config(struct usb_device *udev) af9015_ir_table_msi; af9015_config.ir_table_size = ARRAY_SIZE(af9015_ir_table_msi); + } else if (udev->descriptor.idProduct == + cpu_to_le16(USB_PID_TREKSTOR_DVBT)) { + af9015_properties[i].rc_key_map = + af9015_rc_keys_trekstor; + af9015_properties[i].rc_key_map_size = + ARRAY_SIZE(af9015_rc_keys_trekstor); + af9015_config.ir_table = + af9015_ir_table_trekstor; + af9015_config.ir_table_size = + ARRAY_SIZE(af9015_ir_table_trekstor); } break; case USB_VID_AVERMEDIA: @@ -1241,6 +1251,7 @@ static struct usb_device_id af9015_usb_table[] = { {USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_395U)}, {USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_395U_2)}, {USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_395U_3)}, + {USB_DEVICE(USB_VID_AFATECH, USB_PID_TREKSTOR_DVBT)}, {0}, }; MODULE_DEVICE_TABLE(usb, af9015_usb_table); @@ -1405,7 +1416,7 @@ static struct dvb_usb_device_properties af9015_properties[] = { .i2c_algo = &af9015_i2c_algo, - .num_device_descs = 7, + .num_device_descs = 8, .devices = { { .name = "Xtensions XD-380", @@ -1445,6 +1456,11 @@ static struct dvb_usb_device_properties af9015_properties[] = { &af9015_usb_table[18], NULL}, .warm_ids = {NULL}, }, + { + .name = "TrekStor DVB-T USB Stick", + .cold_ids = {&af9015_usb_table[19], NULL}, + .warm_ids = {NULL}, + }, } } }; diff --git a/linux/drivers/media/dvb/dvb-usb/af9015.h b/linux/drivers/media/dvb/dvb-usb/af9015.h index 00e257146..5c44bad28 100644 --- a/linux/drivers/media/dvb/dvb-usb/af9015.h +++ b/linux/drivers/media/dvb/dvb-usb/af9015.h @@ -120,11 +120,11 @@ struct af9015_config { enum af9015_remote { AF9015_REMOTE_NONE = 0, - AF9015_REMOTE_A_LINK_DTU_M, +/* 1 */ AF9015_REMOTE_A_LINK_DTU_M, AF9015_REMOTE_MSI_DIGIVOX_MINI_II_V3, AF9015_REMOTE_MYGICTV_U718, AF9015_REMOTE_DIGITTRADE_DVB_T, - AF9015_REMOTE_AVERMEDIA_KS, +/* 5 */ AF9015_REMOTE_AVERMEDIA_KS, }; /* Leadtek WinFast DTV Dongle Gold */ @@ -691,4 +691,67 @@ static u8 af9015_ir_table_digittrade[] = { 0x00, 0xff, 0x1d, 0xe2, 0x40, 0x00, 0x00, }; +/* TREKSTOR DVB-T USB Stick */ +static struct dvb_usb_rc_key af9015_rc_keys_trekstor[] = { + { 0x07, 0x04, KEY_AGAIN }, /* Home */ + { 0x07, 0x05, KEY_MUTE }, /* Mute */ + { 0x07, 0x06, KEY_UP }, /* Up */ + { 0x07, 0x07, KEY_DOWN }, /* Down */ + { 0x07, 0x09, KEY_RIGHT }, /* Right */ + { 0x07, 0x0a, KEY_ENTER }, /* OK */ + { 0x07, 0x0b, KEY_FASTFORWARD }, /* Fast forward */ + { 0x07, 0x0c, KEY_REWIND }, /* Rewind */ + { 0x07, 0x0d, KEY_PLAY }, /* Play/Pause */ + { 0x07, 0x0e, KEY_VOLUMEUP }, /* Volume + */ + { 0x07, 0x0f, KEY_VOLUMEDOWN }, /* Volume - */ + { 0x07, 0x10, KEY_RECORD }, /* Record */ + { 0x07, 0x11, KEY_STOP }, /* Stop */ + { 0x07, 0x12, KEY_ZOOM }, /* TV */ + { 0x07, 0x13, KEY_EPG }, /* Info/EPG */ + { 0x07, 0x14, KEY_CHANNELDOWN }, /* Channel - */ + { 0x07, 0x15, KEY_CHANNELUP }, /* Channel + */ + { 0x07, 0x1e, KEY_1 }, + { 0x07, 0x1f, KEY_2 }, + { 0x07, 0x20, KEY_3 }, + { 0x07, 0x21, KEY_4 }, + { 0x07, 0x22, KEY_5 }, + { 0x07, 0x23, KEY_6 }, + { 0x07, 0x24, KEY_7 }, + { 0x07, 0x25, KEY_8 }, + { 0x07, 0x26, KEY_9 }, + { 0x07, 0x08, KEY_LEFT }, /* LEFT */ + { 0x07, 0x27, KEY_0 }, +}; + +static u8 af9015_ir_table_trekstor[] = { + 0x00, 0xff, 0x86, 0x79, 0x04, 0x07, 0x00, + 0x00, 0xff, 0x85, 0x7a, 0x05, 0x07, 0x00, + 0x00, 0xff, 0x87, 0x78, 0x06, 0x07, 0x00, + 0x00, 0xff, 0x8c, 0x73, 0x07, 0x07, 0x00, + 0x00, 0xff, 0x89, 0x76, 0x09, 0x07, 0x00, + 0x00, 0xff, 0x88, 0x77, 0x0a, 0x07, 0x00, + 0x00, 0xff, 0x8a, 0x75, 0x0b, 0x07, 0x00, + 0x00, 0xff, 0x9e, 0x61, 0x0c, 0x07, 0x00, + 0x00, 0xff, 0x8d, 0x72, 0x0d, 0x07, 0x00, + 0x00, 0xff, 0x8b, 0x74, 0x0e, 0x07, 0x00, + 0x00, 0xff, 0x9b, 0x64, 0x0f, 0x07, 0x00, + 0x00, 0xff, 0x9d, 0x62, 0x10, 0x07, 0x00, + 0x00, 0xff, 0x8e, 0x71, 0x11, 0x07, 0x00, + 0x00, 0xff, 0x9c, 0x63, 0x12, 0x07, 0x00, + 0x00, 0xff, 0x8f, 0x70, 0x13, 0x07, 0x00, + 0x00, 0xff, 0x93, 0x6c, 0x14, 0x07, 0x00, + 0x00, 0xff, 0x97, 0x68, 0x15, 0x07, 0x00, + 0x00, 0xff, 0x92, 0x6d, 0x1e, 0x07, 0x00, + 0x00, 0xff, 0x96, 0x69, 0x1f, 0x07, 0x00, + 0x00, 0xff, 0x9a, 0x65, 0x20, 0x07, 0x00, + 0x00, 0xff, 0x91, 0x6e, 0x21, 0x07, 0x00, + 0x00, 0xff, 0x95, 0x6a, 0x22, 0x07, 0x00, + 0x00, 0xff, 0x99, 0x66, 0x23, 0x07, 0x00, + 0x00, 0xff, 0x90, 0x6f, 0x24, 0x07, 0x00, + 0x00, 0xff, 0x94, 0x6b, 0x25, 0x07, 0x00, + 0x00, 0xff, 0x98, 0x67, 0x26, 0x07, 0x00, + 0x00, 0xff, 0x9f, 0x60, 0x08, 0x07, 0x00, + 0x00, 0xff, 0x84, 0x7b, 0x27, 0x07, 0x00, +}; + #endif 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 ba4115d1a..cd22d6dde 100644 --- a/linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h +++ b/linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h @@ -64,6 +64,7 @@ #define USB_PID_AFATECH_AF9005 0x9020 #define USB_PID_AFATECH_AF9015_9015 0x9015 #define USB_PID_AFATECH_AF9015_9016 0x9016 +#define USB_PID_TREKSTOR_DVBT 0x901b #define USB_VID_ALINK_DTU 0xf170 #define USB_PID_ANSONIC_DVBT_USB 0x6000 #define USB_PID_ANYSEE 0x861f -- cgit v1.2.3 From e416fe5e6675ac077a2f4af8751e1f29c1e64422 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Fri, 27 Mar 2009 14:46:49 +0100 Subject: uvcvideo: Add support for Syntek cameras found in JAOtech Smart Terminals Signed-off-by: Laurent Pinchart --- linux/drivers/media/video/uvc/uvc_driver.c | 9 +++++++++ 1 file changed, 9 insertions(+) (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 0d2d87198..31d60647d 100644 --- a/linux/drivers/media/video/uvc/uvc_driver.c +++ b/linux/drivers/media/video/uvc/uvc_driver.c @@ -1917,6 +1917,15 @@ static struct usb_device_id uvc_ids[] = { .bInterfaceSubClass = 1, .bInterfaceProtocol = 0, .driver_info = UVC_QUIRK_STREAM_NO_FID }, + /* Syntek (JAOtech Smart Terminal) */ + { .match_flags = USB_DEVICE_ID_MATCH_DEVICE + | USB_DEVICE_ID_MATCH_INT_INFO, + .idVendor = 0x174f, + .idProduct = 0x8a34, + .bInterfaceClass = USB_CLASS_VIDEO, + .bInterfaceSubClass = 1, + .bInterfaceProtocol = 0, + .driver_info = UVC_QUIRK_STREAM_NO_FID }, /* Lenovo Thinkpad SL500 */ { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO, -- cgit v1.2.3 From d4144041518b63e88d1635667f742b292ef03a70 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Fri, 27 Mar 2009 15:13:57 +0100 Subject: uvcvideo: Add zero fill for VIDIOC_ENUM_FMT MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: Márton Németh When enumerating formats with VIDIOC_ENUM_FMT the uvcvideo driver does not fill the reserved fields of the struct v4l2_fmtdesc with zeros as required by V4L2 API revision 0.24 [1]. Add the missing initializations. The patch was tested with v4l-test 0.10 [2] with CNF7129 webcam found on EeePC 901. References: [1] V4L2 API specification, revision 0.24 http://v4l2spec.bytesex.org/spec/r8367.htm [2] v4l-test: Test environment for Video For Linux Two API http://v4l-test.sourceforge.net/ Priority: normal Signed-off-by: Márton Németh Signed-off-by: Laurent Pinchart --- linux/drivers/media/video/uvc/uvc_v4l2.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/uvc/uvc_v4l2.c b/linux/drivers/media/video/uvc/uvc_v4l2.c index 0baa59f61..aa7949d95 100644 --- a/linux/drivers/media/video/uvc/uvc_v4l2.c +++ b/linux/drivers/media/video/uvc/uvc_v4l2.c @@ -679,11 +679,17 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) { struct v4l2_fmtdesc *fmt = arg; struct uvc_format *format; + enum v4l2_buf_type type = fmt->type; + __u32 index = fmt->index; if (fmt->type != video->streaming->type || fmt->index >= video->streaming->nformats) return -EINVAL; + memset(fmt, 0, sizeof(*fmt)); + fmt->index = index; + fmt->type = type; + format = &video->streaming->format[fmt->index]; fmt->flags = 0; if (format->flags & UVC_FMT_FLAG_COMPRESSED) -- cgit v1.2.3 From 2cc0abb17583ba0769357943dee38920a8cd757e Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 28 Mar 2009 06:55:35 -0300 Subject: cx231xx: Fix Kconfig help items From: Mauro Carvalho Chehab Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/cx231xx/Kconfig | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/cx231xx/Kconfig b/linux/drivers/media/video/cx231xx/Kconfig index aba05d3bd..477d4ab5e 100644 --- a/linux/drivers/media/video/cx231xx/Kconfig +++ b/linux/drivers/media/video/cx231xx/Kconfig @@ -7,11 +7,11 @@ config VIDEO_CX231XX select VIDEOBUF_VMALLOC select VIDEO_CX25840 - ---help--- - This is a video4linux driver for Conexant 231xx USB based TV cards. + ---help--- + This is a video4linux driver for Conexant 231xx USB based TV cards. - To compile this driver as a module, choose M here: the - module will be called cx231xx + To compile this driver as a module, choose M here: the + module will be called cx231xx config VIDEO_CX231XX_ALSA tristate "Conexant Cx231xx ALSA audio module" -- cgit v1.2.3 From 6ab3f9154f1ea73d99c5f46a15f3fad0d10b99b6 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 28 Mar 2009 12:29:00 +0100 Subject: bttv: convert to v4l2_subdev since i2c autoprobing will disappear. From: Hans Verkuil Since i2c autoprobing will disappear bttv needs to be converted to use v4l2_subdev instead. Without autoprobing the autoload module option has become obsolete. A warning is generated if it is set, but it is otherwise ignored. Since the bttv card definitions are of questionable value a new option was introduced to allow the user to control which audio module is selected: msp3400, tda7432 or tvaudio (or none at all). By default bttv will use the card definitions and fallback on tvaudio as the last resort. If no audio device was found a warning is printed. The saa6588 RDS device is now also explicitly probed since it is no longer possible to autoprobe it. A new saa6588 module option was added to override the card definition since I suspect more cards have this device than one would guess from the card definitions. Note that the probe addresses of the i2c modules are hardcoded in this driver. Once all v4l drivers are converted to v4l2_subdev this will be cleaned up. Such data belongs in an i2c driver header. Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/bt8xx/bttv-cards.c | 179 ++++++++++++++++++++++---- linux/drivers/media/video/bt8xx/bttv-driver.c | 41 +++--- linux/drivers/media/video/bt8xx/bttv-i2c.c | 52 +------- linux/drivers/media/video/bt8xx/bttv.h | 7 +- linux/drivers/media/video/bt8xx/bttvp.h | 5 +- 5 files changed, 184 insertions(+), 100 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/bt8xx/bttv-cards.c b/linux/drivers/media/video/bt8xx/bttv-cards.c index d2136141e..1c13dbfec 100644 --- a/linux/drivers/media/video/bt8xx/bttv-cards.c +++ b/linux/drivers/media/video/bt8xx/bttv-cards.c @@ -97,12 +97,10 @@ static unsigned int pll[BTTV_MAX] = { [ 0 ... (BTTV_MAX-1) ] = UNSET }; static unsigned int tuner[BTTV_MAX] = { [ 0 ... (BTTV_MAX-1) ] = UNSET }; static unsigned int svhs[BTTV_MAX] = { [ 0 ... (BTTV_MAX-1) ] = UNSET }; static unsigned int remote[BTTV_MAX] = { [ 0 ... (BTTV_MAX-1) ] = UNSET }; +static unsigned int audiodev[BTTV_MAX]; +static unsigned int saa6588[BTTV_MAX]; static struct bttv *master[BTTV_MAX] = { [ 0 ... (BTTV_MAX-1) ] = NULL }; -#ifdef MODULE -static unsigned int autoload = 1; -#else -static unsigned int autoload; -#endif +static unsigned int autoload = UNSET; static unsigned int gpiomask = UNSET; static unsigned int audioall = UNSET; static unsigned int audiomux[5] = { [ 0 ... 4 ] = UNSET }; @@ -121,6 +119,7 @@ module_param_array(pll, int, NULL, 0444); module_param_array(tuner, int, NULL, 0444); module_param_array(svhs, int, NULL, 0444); module_param_array(remote, int, NULL, 0444); +module_param_array(audiodev, int, NULL, 0444); module_param_array(audiomux, int, NULL, 0444); MODULE_PARM_DESC(triton1,"set ETBF pci config bit " @@ -131,7 +130,14 @@ MODULE_PARM_DESC(latency,"pci latency timer"); MODULE_PARM_DESC(card,"specify TV/grabber card model, see CARDLIST file for a list"); MODULE_PARM_DESC(pll,"specify installed crystal (0=none, 28=28 MHz, 35=35 MHz)"); MODULE_PARM_DESC(tuner,"specify installed tuner type"); -MODULE_PARM_DESC(autoload,"automatically load i2c modules like tuner.o, default is 1 (yes)"); +MODULE_PARM_DESC(autoload, "obsolete option, please do not use anymore"); +MODULE_PARM_DESC(audiodev, "specify audio device:\n" + "\t\t-1 = no audio\n" + "\t\t 0 = autodetect (default)\n" + "\t\t 1 = msp3400\n" + "\t\t 2 = tda7432\n" + "\t\t 3 = tvaudio"); +MODULE_PARM_DESC(saa6588, "if 1, then load the saa6588 RDS module, default (0) is to use the card definition."); MODULE_PARM_DESC(no_overlay,"allow override overlay default (0 disables, 1 enables)" " [some VIA/SIS chipsets are known to have problem with overlay]"); @@ -3356,6 +3362,17 @@ void __devinit bttv_init_card1(struct bttv *btv) /* initialization part two -- after registering i2c bus */ void __devinit bttv_init_card2(struct bttv *btv) { + static const unsigned short tvaudio_addrs[] = { + I2C_ADDR_TDA8425 >> 1, + I2C_ADDR_TEA6300 >> 1, + I2C_ADDR_TEA6420 >> 1, + I2C_ADDR_TDA9840 >> 1, + I2C_ADDR_TDA985x_L >> 1, + I2C_ADDR_TDA985x_H >> 1, + I2C_ADDR_TDA9874 >> 1, + I2C_ADDR_PIC16C54 >> 1, + I2C_CLIENT_END + }; int addr=ADDR_UNSET; btv->tuner_type = UNSET; @@ -3519,6 +3536,12 @@ void __devinit bttv_init_card2(struct bttv *btv) printk(KERN_INFO "bttv%d: tuner type=%d\n", btv->c.nr, btv->tuner_type); + if (autoload != UNSET) { + printk(KERN_WARNING "bttv%d: the autoload option is obsolete.\n", btv->c.nr); + printk(KERN_WARNING "bttv%d: use option msp3400, tda7432 or tvaudio to\n", btv->c.nr); + printk(KERN_WARNING "bttv%d: override which audio module should be used.\n", btv->c.nr); + } + if (UNSET == btv->tuner_type) btv->tuner_type = TUNER_ABSENT; @@ -3526,8 +3549,13 @@ void __devinit bttv_init_card2(struct bttv *btv) struct tuner_setup tun_setup; /* Load tuner module before issuing tuner config call! */ - if (autoload) - request_module("tuner"); + if (bttv_tvcards[btv->c.type].has_radio) + v4l2_i2c_new_probed_subdev(&btv->c.i2c_adap, + "tuner", "tuner", v4l2_i2c_tuner_addrs(ADDRS_RADIO)); + v4l2_i2c_new_probed_subdev(&btv->c.i2c_adap, "tuner", + "tuner", v4l2_i2c_tuner_addrs(ADDRS_DEMOD)); + v4l2_i2c_new_probed_subdev(&btv->c.i2c_adap, "tuner", + "tuner", v4l2_i2c_tuner_addrs(ADDRS_TV_WITH_DEMOD)); tun_setup.mode_mask = T_ANALOG_TV | T_DIGITAL_TV; tun_setup.type = btv->tuner_type; @@ -3536,7 +3564,7 @@ void __devinit bttv_init_card2(struct bttv *btv) if (bttv_tvcards[btv->c.type].has_radio) tun_setup.mode_mask |= T_RADIO; - bttv_call_i2c_clients(btv, TUNER_SET_TYPE_ADDR, &tun_setup); + bttv_call_all(btv, tuner, s_type_addr, &tun_setup); } if (btv->tda9887_conf) { @@ -3545,7 +3573,7 @@ void __devinit bttv_init_card2(struct bttv *btv) tda9887_cfg.tuner = TUNER_TDA9887; tda9887_cfg.priv = &btv->tda9887_conf; - bttv_call_i2c_clients(btv, TUNER_SET_CONFIG, &tda9887_cfg); + bttv_call_all(btv, tuner, s_config, &tda9887_cfg); } btv->dig = bttv_tvcards[btv->c.type].has_dig_in ? @@ -3568,31 +3596,127 @@ void __devinit bttv_init_card2(struct bttv *btv) if (bttv_tvcards[btv->c.type].audio_mode_gpio) btv->audio_mode_gpio=bttv_tvcards[btv->c.type].audio_mode_gpio; - if (!autoload) - return; - if (btv->tuner_type == TUNER_ABSENT) return; /* no tuner or related drivers to load */ + if (btv->has_saa6588 || saa6588[btv->c.nr]) { + /* Probe for RDS receiver chip */ + static const unsigned short addrs[] = { + 0x20 >> 1, + 0x22 >> 1, + I2C_CLIENT_END + }; + struct v4l2_subdev *sd; + + sd = v4l2_i2c_new_probed_subdev(&btv->c.i2c_adap, + "saa6588", "saa6588", addrs); + btv->has_saa6588 = (sd != NULL); + } + /* try to detect audio/fader chips */ - if (!bttv_tvcards[btv->c.type].no_msp34xx && - bttv_I2CRead(btv, I2C_ADDR_MSP3400, "MSP34xx") >=0) - request_module("msp3400"); - if (bttv_tvcards[btv->c.type].msp34xx_alt && - bttv_I2CRead(btv, I2C_ADDR_MSP3400_ALT, "MSP34xx (alternate address)") >=0) - request_module("msp3400"); + /* First check if the user specified the audio chip via a module + option. */ + + switch (audiodev[btv->c.nr]) { + case -1: + return; /* do not load any audio module */ - if (!bttv_tvcards[btv->c.type].no_tda9875 && - bttv_I2CRead(btv, I2C_ADDR_TDA9875, "TDA9875") >=0) - request_module("tda9875"); + case 0: /* autodetect */ + break; - if (!bttv_tvcards[btv->c.type].no_tda7432 && - bttv_I2CRead(btv, I2C_ADDR_TDA7432, "TDA7432") >=0) - request_module("tda7432"); + case 1: { + /* The user specified that we should probe for msp3400 */ + static const unsigned short addrs[] = { + I2C_ADDR_MSP3400 >> 1, + I2C_ADDR_MSP3400_ALT >> 1, + I2C_CLIENT_END + }; + + btv->sd_msp34xx = v4l2_i2c_new_probed_subdev(&btv->c.i2c_adap, + "msp3400", "msp3400", addrs); + if (btv->sd_msp34xx) + return; + goto no_audio; + } + + case 2: { + /* The user specified that we should probe for tda7432 */ + static const unsigned short addrs[] = { + I2C_ADDR_TDA7432 >> 1, + I2C_CLIENT_END + }; + + if (v4l2_i2c_new_probed_subdev(&btv->c.i2c_adap, + "tda7432", "tda7432", addrs)) + return; + goto no_audio; + } + + case 3: { + /* The user specified that we should probe for tvaudio */ + btv->sd_tvaudio = v4l2_i2c_new_probed_subdev(&btv->c.i2c_adap, + "tvaudio", "tvaudio", tvaudio_addrs); + if (btv->sd_tvaudio) + return; + goto no_audio; + } + + default: + printk(KERN_WARNING "bttv%d: unknown audiodev value!\n", + btv->c.nr); + return; + } + + /* There were no overrides, so now we try to discover this through the + card definition */ + + /* probe for msp3400 first: this driver can detect whether or not + it really is a msp3400, so it will return NULL when the device + found is really something else (e.g. a tea6300). */ + if (!bttv_tvcards[btv->c.type].no_msp34xx) { + static const unsigned short addrs[] = { + I2C_ADDR_MSP3400 >> 1, + I2C_CLIENT_END + }; + + btv->sd_msp34xx = v4l2_i2c_new_probed_subdev(&btv->c.i2c_adap, + "msp3400", "msp3400", addrs); + } else if (bttv_tvcards[btv->c.type].msp34xx_alt) { + static const unsigned short addrs[] = { + I2C_ADDR_MSP3400_ALT >> 1, + I2C_CLIENT_END + }; + + btv->sd_msp34xx = v4l2_i2c_new_probed_subdev(&btv->c.i2c_adap, + "msp3400", "msp3400", addrs); + } + + /* If we found a msp34xx, then we're done. */ + if (btv->sd_msp34xx) + return; + + /* it might also be a tda7432. */ + if (!bttv_tvcards[btv->c.type].no_tda7432) { + static const unsigned short addrs[] = { + I2C_ADDR_TDA7432 >> 1, + I2C_CLIENT_END + }; + + if (v4l2_i2c_new_probed_subdev(&btv->c.i2c_adap, + "tda7432", "tda7432", addrs)) + return; + } + + /* Now see if we can find one of the tvaudio devices. */ + btv->sd_tvaudio = v4l2_i2c_new_probed_subdev(&btv->c.i2c_adap, + "tvaudio", "tvaudio", tvaudio_addrs); + if (btv->sd_tvaudio) + return; - if (bttv_tvcards[btv->c.type].needs_tvaudio) - request_module("tvaudio"); +no_audio: + printk(KERN_WARNING "bttv%d: audio absent, no audio device found!\n", + btv->c.nr); } @@ -3664,6 +3788,7 @@ static int terratec_active_radio_upgrade(struct bttv *btv) printk("bttv%d: Terratec Active Radio Upgrade found.\n", btv->c.nr); btv->has_radio = 1; + btv->has_saa6588 = 1; btv->has_matchbox = 1; } else { btv->has_radio = 0; diff --git a/linux/drivers/media/video/bt8xx/bttv-driver.c b/linux/drivers/media/video/bt8xx/bttv-driver.c index acb7b5e3d..0609db138 100644 --- a/linux/drivers/media/video/bt8xx/bttv-driver.c +++ b/linux/drivers/media/video/bt8xx/bttv-driver.c @@ -1181,7 +1181,6 @@ audio_mux(struct bttv *btv, int input, int mute) { int gpio_val, signal; struct v4l2_control ctrl; - struct i2c_client *c; gpio_inout(bttv_tvcards[btv->c.type].gpiomask, bttv_tvcards[btv->c.type].gpiomask); @@ -1220,9 +1219,8 @@ audio_mux(struct bttv *btv, int input, int mute) ctrl.id = V4L2_CID_AUDIO_MUTE; ctrl.value = btv->mute; - bttv_call_i2c_clients(btv, VIDIOC_S_CTRL, &ctrl); - c = btv->i2c_msp34xx_client; - if (c) { + bttv_call_all(btv, core, s_ctrl, &ctrl); + if (btv->sd_msp34xx) { struct v4l2_routing route; /* Note: the inputs tuner/radio/extern/intern are translated @@ -1261,15 +1259,14 @@ audio_mux(struct bttv *btv, int input, int mute) break; } route.output = MSP_OUTPUT_DEFAULT; - c->driver->command(c, VIDIOC_INT_S_AUDIO_ROUTING, &route); + v4l2_subdev_call(btv->sd_msp34xx, audio, s_routing, &route); } - c = btv->i2c_tvaudio_client; - if (c) { + if (btv->sd_tvaudio) { struct v4l2_routing route; route.input = input; route.output = 0; - c->driver->command(c, VIDIOC_INT_S_AUDIO_ROUTING, &route); + v4l2_subdev_call(btv->sd_tvaudio, audio, s_routing, &route); } return 0; } @@ -1360,7 +1357,7 @@ set_tvnorm(struct bttv *btv, unsigned int norm) #endif } id = tvnorm->v4l2_id; - bttv_call_i2c_clients(btv, VIDIOC_S_STD, &id); + bttv_call_all(btv, tuner, s_std, id); return 0; } @@ -1504,7 +1501,7 @@ static int bttv_g_ctrl(struct file *file, void *priv, case V4L2_CID_AUDIO_BALANCE: case V4L2_CID_AUDIO_BASS: case V4L2_CID_AUDIO_TREBLE: - bttv_call_i2c_clients(btv, VIDIOC_G_CTRL, c); + bttv_call_all(btv, core, g_ctrl, c); break; case V4L2_CID_PRIVATE_CHROMA_AGC: @@ -1578,12 +1575,12 @@ static int bttv_s_ctrl(struct file *file, void *f, if (btv->volume_gpio) btv->volume_gpio(btv, c->value); - bttv_call_i2c_clients(btv, VIDIOC_S_CTRL, c); + bttv_call_all(btv, core, s_ctrl, c); break; case V4L2_CID_AUDIO_BALANCE: case V4L2_CID_AUDIO_BASS: case V4L2_CID_AUDIO_TREBLE: - bttv_call_i2c_clients(btv, VIDIOC_S_CTRL, c); + bttv_call_all(btv, core, s_ctrl, c); break; case V4L2_CID_PRIVATE_CHROMA_AGC: @@ -2001,7 +1998,7 @@ static int bttv_s_tuner(struct file *file, void *priv, return -EINVAL; mutex_lock(&btv->lock); - bttv_call_i2c_clients(btv, VIDIOC_S_TUNER, t); + bttv_call_all(btv, tuner, s_tuner, t); if (btv->audio_mode_gpio) btv->audio_mode_gpio(btv, t, 1); @@ -2046,7 +2043,7 @@ static int bttv_s_frequency(struct file *file, void *priv, return -EINVAL; mutex_lock(&btv->lock); btv->freq = f->frequency; - bttv_call_i2c_clients(btv, VIDIOC_S_FREQUENCY, f); + bttv_call_all(btv, tuner, s_frequency, f); if (btv->has_matchbox && btv->radio_user) tea5757_set_freq(btv, btv->freq); mutex_unlock(&btv->lock); @@ -2060,7 +2057,7 @@ static int bttv_log_status(struct file *file, void *f) printk(KERN_INFO "bttv%d: ======== START STATUS CARD #%d ========\n", btv->c.nr, btv->c.nr); - bttv_call_i2c_clients(btv, VIDIOC_LOG_STATUS, NULL); + bttv_call_all(btv, core, log_status); printk(KERN_INFO "bttv%d: ======== END STATUS CARD #%d ========\n", btv->c.nr, btv->c.nr); return 0; @@ -2976,7 +2973,7 @@ static int bttv_g_tuner(struct file *file, void *priv, mutex_lock(&btv->lock); t->rxsubchans = V4L2_TUNER_SUB_MONO; - bttv_call_i2c_clients(btv, VIDIOC_G_TUNER, t); + bttv_call_all(btv, tuner, g_tuner, t); strcpy(t->name, "Television"); t->capability = V4L2_TUNER_CAP_NORM; t->type = V4L2_TUNER_ANALOG_TV; @@ -3467,7 +3464,7 @@ static int radio_open(struct file *file) btv->radio_user++; - bttv_call_i2c_clients(btv,AUDC_SET_RADIO,NULL); + bttv_call_all(btv, tuner, s_radio); audio_input(btv,TVAUDIO_INPUT_RADIO); mutex_unlock(&btv->lock); @@ -3487,7 +3484,7 @@ static int radio_release(struct file *file) btv->radio_user--; - bttv_call_i2c_clients(btv, RDS_CMD_CLOSE, &cmd); + bttv_call_all(btv, core, ioctl, RDS_CMD_CLOSE, &cmd); return 0; } @@ -3520,7 +3517,7 @@ static int radio_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t) strcpy(t->name, "Radio"); t->type = V4L2_TUNER_RADIO; - bttv_call_i2c_clients(btv, VIDIOC_G_TUNER, t); + bttv_call_all(btv, tuner, g_tuner, t); if (btv->audio_mode_gpio) btv->audio_mode_gpio(btv, t, 0); @@ -3562,7 +3559,7 @@ static int radio_s_tuner(struct file *file, void *priv, if (0 != t->index) return -EINVAL; - bttv_call_i2c_clients(btv, VIDIOC_G_TUNER, t); + bttv_call_all(btv, tuner, g_tuner, t); return 0; } @@ -3623,7 +3620,7 @@ static ssize_t radio_read(struct file *file, char __user *data, cmd.instance = file; cmd.result = -ENODEV; - bttv_call_i2c_clients(btv, RDS_CMD_READ, &cmd); + bttv_call_all(btv, core, ioctl, RDS_CMD_READ, &cmd); return cmd.result; } @@ -3636,7 +3633,7 @@ static unsigned int radio_poll(struct file *file, poll_table *wait) cmd.instance = file; cmd.event_list = wait; cmd.result = -ENODEV; - bttv_call_i2c_clients(btv, RDS_CMD_POLL, &cmd); + bttv_call_all(btv, core, ioctl, RDS_CMD_POLL, &cmd); return cmd.result; } diff --git a/linux/drivers/media/video/bt8xx/bttv-i2c.c b/linux/drivers/media/video/bt8xx/bttv-i2c.c index c35f09cf4..dbb21f77b 100644 --- a/linux/drivers/media/video/bt8xx/bttv-i2c.c +++ b/linux/drivers/media/video/bt8xx/bttv-i2c.c @@ -36,8 +36,6 @@ #include #include -static int attach_inform(struct i2c_client *client); - static int i2c_debug; static int i2c_hw; static int i2c_scan; @@ -269,51 +267,6 @@ static const struct i2c_algorithm bttv_algo = { /* ----------------------------------------------------------------------- */ /* I2C functions - common stuff */ -static int attach_inform(struct i2c_client *client) -{ - struct v4l2_device *v4l2_dev = i2c_get_adapdata(client->adapter); - struct bttv *btv = to_bttv(v4l2_dev); - int addr=ADDR_UNSET; - - - if (ADDR_UNSET != bttv_tvcards[btv->c.type].tuner_addr) - addr = bttv_tvcards[btv->c.type].tuner_addr; - - - if (bttv_debug) - printk(KERN_DEBUG "bttv%d: %s i2c attach [addr=0x%x,client=%s]\n", - btv->c.nr, client->driver->driver.name, client->addr, - client->name); - if (!client->driver->command) - return 0; - - if (client->driver->id == I2C_DRIVERID_MSP3400) - btv->i2c_msp34xx_client = client; - if (client->driver->id == I2C_DRIVERID_TVAUDIO) - btv->i2c_tvaudio_client = client; - if (btv->tuner_type != TUNER_ABSENT) { - struct tuner_setup tun_setup; - - if (addr == ADDR_UNSET || addr == client->addr) { - tun_setup.mode_mask = T_ANALOG_TV | T_DIGITAL_TV | T_RADIO; - tun_setup.type = btv->tuner_type; - tun_setup.addr = addr; - bttv_call_i2c_clients(btv, TUNER_SET_TYPE_ADDR, &tun_setup); - } - - } - - return 0; -} - -void bttv_call_i2c_clients(struct bttv *btv, unsigned int cmd, void *arg) -{ - if (0 != btv->i2c_rc) - return; - i2c_clients_command(&btv->c.i2c_adap, cmd, arg); -} - - /* read I2C */ int bttv_I2CRead(struct bttv *btv, unsigned char addr, char *probe_for) { @@ -424,8 +377,9 @@ int __devinit init_bttv_i2c(struct bttv *btv) btv->c.i2c_adap.algo_data = &btv->i2c_algo; } btv->c.i2c_adap.owner = THIS_MODULE; +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22) btv->c.i2c_adap.class = I2C_CLASS_TV_ANALOG; - btv->c.i2c_adap.client_register = attach_inform; +#endif btv->c.i2c_adap.dev.parent = &btv->c.pci->dev; snprintf(btv->c.i2c_adap.name, sizeof(btv->c.i2c_adap.name), @@ -435,10 +389,12 @@ int __devinit init_bttv_i2c(struct bttv *btv) i2c_set_adapdata(&btv->c.i2c_adap, &btv->c.v4l2_dev); btv->i2c_client.adapter = &btv->c.i2c_adap; +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22) if (bttv_tvcards[btv->c.type].no_video) btv->c.i2c_adap.class &= ~I2C_CLASS_TV_ANALOG; if (bttv_tvcards[btv->c.type].has_dvb) btv->c.i2c_adap.class |= I2C_CLASS_TV_DIGITAL; +#endif if (btv->use_i2c_hw) { btv->i2c_rc = i2c_add_adapter(&btv->c.i2c_adap); diff --git a/linux/drivers/media/video/bt8xx/bttv.h b/linux/drivers/media/video/bt8xx/bttv.h index 947f6e51a..6b7b62bd4 100644 --- a/linux/drivers/media/video/bt8xx/bttv.h +++ b/linux/drivers/media/video/bt8xx/bttv.h @@ -241,6 +241,9 @@ struct tvcard { unsigned int no_tda7432:1; unsigned int needs_tvaudio:1; unsigned int msp34xx_alt:1; + /* Note: currently no card definition needs to mark the presence + of a RDS saa6588 chip. If this is ever needed, then add a new + 'has_saa6588' bit here. */ unsigned int no_video:1; /* video pci function is unused */ unsigned int has_dvb:1; @@ -358,7 +361,9 @@ void bttv_gpio_bits(struct bttv_core *core, u32 mask, u32 bits); /* ---------------------------------------------------------- */ /* i2c */ -extern void bttv_call_i2c_clients(struct bttv *btv, unsigned int cmd, void *arg); +#define bttv_call_all(btv, o, f, args...) \ + v4l2_device_call_all(&btv->c.v4l2_dev, 0, o, f, ##args) + extern int bttv_I2CRead(struct bttv *btv, unsigned char addr, char *probe_for); extern int bttv_I2CWrite(struct bttv *btv, unsigned char addr, unsigned char b1, unsigned char b2, int both); diff --git a/linux/drivers/media/video/bt8xx/bttvp.h b/linux/drivers/media/video/bt8xx/bttvp.h index 5915c261e..65a8c1df1 100644 --- a/linux/drivers/media/video/bt8xx/bttvp.h +++ b/linux/drivers/media/video/bt8xx/bttvp.h @@ -331,6 +331,7 @@ struct bttv { unsigned int tuner_type; /* tuner chip type */ unsigned int tda9887_conf; unsigned int svhs, dig; + unsigned int has_saa6588:1; struct bttv_pll_info pll; int triton1; int gpioirq; @@ -354,8 +355,8 @@ struct bttv { int i2c_state, i2c_rc; int i2c_done; wait_queue_head_t i2c_queue; - struct i2c_client *i2c_msp34xx_client; - struct i2c_client *i2c_tvaudio_client; + struct v4l2_subdev *sd_msp34xx; + struct v4l2_subdev *sd_tvaudio; /* video4linux (1) */ struct video_device *video_dev; -- cgit v1.2.3 From c1320d2c77e66cf93a7b899cf3764a556c5bc3f9 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 28 Mar 2009 12:55:11 +0100 Subject: bttv: tda9875 is no longer used by bttv, so remove from bt8xx/Kconfig. From: Hans Verkuil Since tda9875 support was merged into tvaudio the bttv driver no longer needs tda9875 as helper driver. Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/bt8xx/Kconfig | 1 - 1 file changed, 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/bt8xx/Kconfig b/linux/drivers/media/video/bt8xx/Kconfig index ce71e8e7b..94c9df8b1 100644 --- a/linux/drivers/media/video/bt8xx/Kconfig +++ b/linux/drivers/media/video/bt8xx/Kconfig @@ -10,7 +10,6 @@ config VIDEO_BT848 select VIDEO_MSP3400 if VIDEO_HELPER_CHIPS_AUTO select VIDEO_TVAUDIO if VIDEO_HELPER_CHIPS_AUTO select VIDEO_TDA7432 if VIDEO_HELPER_CHIPS_AUTO - select VIDEO_TDA9875 if VIDEO_HELPER_CHIPS_AUTO ---help--- Support for BT848 based frame grabber/overlay boards. This includes the Miro, Hauppauge and STB boards. Please read the material in -- cgit v1.2.3 From f2c06347a895cd758222da92cf86e2377ba65fbc Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 28 Mar 2009 13:27:02 +0100 Subject: saa7134: fix RTD Embedded Technologies VFG7350 support. From: Hans Verkuil This card has the saa6752hs on 7-bit address 0x21 instead of 0x20. Add support in the card definition struct to select which address to use and update the definitions accordingly. Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/saa7134/saa6752hs.c | 2 +- linux/drivers/media/video/saa7134/saa7134-cards.c | 8 ++++++++ linux/drivers/media/video/saa7134/saa7134-core.c | 5 +++-- linux/drivers/media/video/saa7134/saa7134-empress.c | 3 +-- linux/drivers/media/video/saa7134/saa7134.h | 1 + 5 files changed, 14 insertions(+), 5 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/saa7134/saa6752hs.c b/linux/drivers/media/video/saa7134/saa6752hs.c index 3af36d929..2b82466d4 100644 --- a/linux/drivers/media/video/saa7134/saa6752hs.c +++ b/linux/drivers/media/video/saa7134/saa6752hs.c @@ -48,7 +48,7 @@ #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22) /* Addresses to scan */ -static unsigned short normal_i2c[] = {0x20, I2C_CLIENT_END}; +static unsigned short normal_i2c[] = {0x20, 0x21, I2C_CLIENT_END}; I2C_CLIENT_INSMOD; #endif diff --git a/linux/drivers/media/video/saa7134/saa7134-cards.c b/linux/drivers/media/video/saa7134/saa7134-cards.c index e8efc883c..50d2868ce 100644 --- a/linux/drivers/media/video/saa7134/saa7134-cards.c +++ b/linux/drivers/media/video/saa7134/saa7134-cards.c @@ -273,6 +273,7 @@ struct saa7134_board saa7134_boards[] = { .radio_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, + .empress_addr = 0x20, .inputs = {{ .name = name_comp1, @@ -409,6 +410,7 @@ struct saa7134_board saa7134_boards[] = { .radio_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, + .empress_addr = 0x20, .tda9887_conf = TDA9887_PRESENT, .gpiomask = 0x820000, .inputs = {{ @@ -819,6 +821,7 @@ struct saa7134_board saa7134_boards[] = { .radio_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, + .empress_addr = 0x20, .inputs = {{ .name = name_comp1, .vmux = 4, @@ -978,6 +981,7 @@ struct saa7134_board saa7134_boards[] = { .radio_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, + .empress_addr = 0x20, .inputs = {{ .name = name_comp1, .vmux = 1, @@ -2365,6 +2369,7 @@ struct saa7134_board saa7134_boards[] = { .radio_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, + .empress_addr = 0x21, .inputs = {{ .name = "Composite 0", .vmux = 0, @@ -4172,6 +4177,7 @@ struct saa7134_board saa7134_boards[] = { .radio_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, + .empress_addr = 0x20, .tda9887_conf = TDA9887_PRESENT, .inputs = { { .name = name_tv, @@ -4208,6 +4214,7 @@ struct saa7134_board saa7134_boards[] = { .radio_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, + .empress_addr = 0x20, .tda9887_conf = TDA9887_PRESENT, .inputs = { { .name = name_tv, @@ -4245,6 +4252,7 @@ struct saa7134_board saa7134_boards[] = { .radio_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, + .empress_addr = 0x20, .tda9887_conf = TDA9887_PRESENT, .inputs = { { .name = name_tv, diff --git a/linux/drivers/media/video/saa7134/saa7134-core.c b/linux/drivers/media/video/saa7134/saa7134-core.c index b99b1ed1c..71142b53e 100644 --- a/linux/drivers/media/video/saa7134/saa7134-core.c +++ b/linux/drivers/media/video/saa7134/saa7134-core.c @@ -1043,8 +1043,9 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev, /* load i2c helpers */ if (card_is_empress(dev)) { struct v4l2_subdev *sd = - v4l2_i2c_new_subdev(&dev->i2c_adap, "saa6752hs", - "saa6752hs", 0x20); + v4l2_i2c_new_subdev(&dev->i2c_adap, + "saa6752hs", "saa6752hs", + saa7134_boards[dev->board].empress_addr); if (sd) sd->grp_id = GRP_EMPRESS; diff --git a/linux/drivers/media/video/saa7134/saa7134-empress.c b/linux/drivers/media/video/saa7134/saa7134-empress.c index 609342128..bab6b56c8 100644 --- a/linux/drivers/media/video/saa7134/saa7134-empress.c +++ b/linux/drivers/media/video/saa7134/saa7134-empress.c @@ -416,8 +416,7 @@ static int empress_g_chip_ident(struct file *file, void *fh, if (chip->match.type == V4L2_CHIP_MATCH_I2C_DRIVER && !strcmp(chip->match.name, "saa6752hs")) return saa_call_empress(dev, core, g_chip_ident, chip); - if (chip->match.type == V4L2_CHIP_MATCH_I2C_ADDR && - chip->match.addr == 0x20) + if (chip->match.type == V4L2_CHIP_MATCH_I2C_ADDR) return saa_call_empress(dev, core, g_chip_ident, chip); return -EINVAL; } diff --git a/linux/drivers/media/video/saa7134/saa7134.h b/linux/drivers/media/video/saa7134/saa7134.h index d2b29ed9e..2e9c7ed3d 100644 --- a/linux/drivers/media/video/saa7134/saa7134.h +++ b/linux/drivers/media/video/saa7134/saa7134.h @@ -333,6 +333,7 @@ struct saa7134_board { unsigned int radio_type; unsigned char tuner_addr; unsigned char radio_addr; + unsigned char empress_addr; unsigned int tda9887_conf; unsigned int tuner_config; -- cgit v1.2.3 From 3305a86bb709837ebcd4aa345c53d6b02c8566c6 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 28 Mar 2009 13:32:42 +0100 Subject: cs53l32a: remove legacy support. From: Hans Verkuil All drivers that use this device have been converted to v4l2_subdev, so there is no more need to support autoprobing on kernels >= 2.6.22. Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/cs53l32a.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/cs53l32a.c b/linux/drivers/media/video/cs53l32a.c index c8b5fa157..4745fd21c 100644 --- a/linux/drivers/media/video/cs53l32a.c +++ b/linux/drivers/media/video/cs53l32a.c @@ -29,7 +29,7 @@ #include #include #include -#include +#include #include "compat.h" MODULE_DESCRIPTION("i2c device driver for cs53l32a Audio ADC"); @@ -42,9 +42,11 @@ module_param(debug, bool, 0644); MODULE_PARM_DESC(debug, "Debugging messages, 0=Off (default), 1=On"); +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22) static unsigned short normal_i2c[] = { 0x22 >> 1, I2C_CLIENT_END }; I2C_CLIENT_INSMOD; +#endif /* ----------------------------------------------------------------------- */ @@ -123,11 +125,6 @@ static int cs53l32a_log_status(struct v4l2_subdev *sd) return 0; } -static int cs53l32a_command(struct i2c_client *client, unsigned cmd, void *arg) -{ - return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg); -} - /* ----------------------------------------------------------------------- */ static const struct v4l2_subdev_core_ops cs53l32a_core_ops = { @@ -225,7 +222,6 @@ MODULE_DEVICE_TABLE(i2c, cs53l32a_id); #endif static struct v4l2_i2c_driver_data v4l2_i2c_data = { .name = "cs53l32a", - .command = cs53l32a_command, .remove = cs53l32a_remove, .probe = cs53l32a_probe, #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) -- cgit v1.2.3 From 7c6ce73528aae8f96ce13949569a1776d67adb6d Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 28 Mar 2009 13:35:40 +0100 Subject: dst_ca: fix compile warning. From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/dvb/bt8xx/dst_ca.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/bt8xx/dst_ca.c b/linux/drivers/media/dvb/bt8xx/dst_ca.c index e71c269c1..bdc22a467 100644 --- a/linux/drivers/media/dvb/bt8xx/dst_ca.c +++ b/linux/drivers/media/dvb/bt8xx/dst_ca.c @@ -650,16 +650,17 @@ free_mem_and_exit: static long dst_ca_ioctl(struct file *file, unsigned int cmd, unsigned long ioctl_arg) { - lock_kernel(); - - struct dvb_device* dvbdev = (struct dvb_device*) file->private_data; - struct dst_state* state = (struct dst_state*) dvbdev->priv; + struct dvb_device *dvbdev; + struct dst_state *state; struct ca_slot_info *p_ca_slot_info; struct ca_caps *p_ca_caps; struct ca_msg *p_ca_message; void __user *arg = (void __user *)ioctl_arg; int result = 0; + lock_kernel(); + dvbdev = (struct dvb_device *)file->private_data; + state = (struct dst_state *)dvbdev->priv; p_ca_message = kmalloc(sizeof (struct ca_msg), GFP_KERNEL); p_ca_slot_info = kmalloc(sizeof (struct ca_slot_info), GFP_KERNEL); p_ca_caps = kmalloc(sizeof (struct ca_caps), GFP_KERNEL); -- cgit v1.2.3 From 6c900804fcc80fe718b9da33501e0a34252a312c Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 28 Mar 2009 13:38:29 +0100 Subject: dabusb: fix compile warning. From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/dabusb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/dabusb.c b/linux/drivers/media/video/dabusb.c index 5585f46dd..9e9cba431 100644 --- a/linux/drivers/media/video/dabusb.c +++ b/linux/drivers/media/video/dabusb.c @@ -736,7 +736,6 @@ static int dabusb_release (struct inode *inode, struct file *file) static long dabusb_ioctl (struct file *file, unsigned int cmd, unsigned long arg) { - lock_kernel(); pdabusb_t s = (pdabusb_t) file->private_data; pbulk_transfer_t pbulk; int ret = 0; @@ -744,6 +743,7 @@ static long dabusb_ioctl (struct file *file, unsigned int cmd, unsigned long arg dbg("dabusb_ioctl"); + lock_kernel(); if (s->remove_pending) { unlock_kernel(); return -EIO; -- cgit v1.2.3 From bcdb0c1f2b2cffa2d507eed6352080933d40793d Mon Sep 17 00:00:00 2001 From: Steven Toth Date: Sat, 28 Mar 2009 12:58:28 -0400 Subject: cx23885: bugfix error message if firmware is not found From: Steven Toth If the firmware failed to be found the error message indicated the incorrect filename. Priority: normal Signed-off-by: Steven Toth --- linux/drivers/media/video/cx23885/cx23885-417.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/cx23885/cx23885-417.c b/linux/drivers/media/video/cx23885/cx23885-417.c index 7e7e75237..adfb79799 100644 --- a/linux/drivers/media/video/cx23885/cx23885-417.c +++ b/linux/drivers/media/video/cx23885/cx23885-417.c @@ -896,7 +896,7 @@ static int cx23885_load_firmware(struct cx23885_dev *dev) if (retval != 0) { printk(KERN_ERR "ERROR: Hotplug firmware request failed (%s).\n", - CX2341X_FIRM_ENC_FILENAME); + CX23885_FIRM_IMAGE_NAME); printk(KERN_ERR "Please fix your hotplug setup, the board will " "not work without firmware loaded!\n"); return -1; -- cgit v1.2.3 From a15ebb515bfbdf0db2cd56d20f28ffa286a03618 Mon Sep 17 00:00:00 2001 From: Steven Toth Date: Mon, 20 Apr 2009 21:42:00 -0400 Subject: cx23885: Frontend wasn't locking on HVR-1500 From: Steven Toth The boards control struct wasn't updated when (presumably) all of the other drivers migrated from using scode_table to specifying the demod. Priority: normal Signed-off-by: Steven Toth --- linux/drivers/media/video/cx23885/cx23885-dvb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/cx23885/cx23885-dvb.c b/linux/drivers/media/video/cx23885/cx23885-dvb.c index 119907f29..a45e80573 100644 --- a/linux/drivers/media/video/cx23885/cx23885-dvb.c +++ b/linux/drivers/media/video/cx23885/cx23885-dvb.c @@ -473,7 +473,7 @@ static int dvb_register(struct cx23885_tsport *port) static struct xc2028_ctrl ctl = { .fname = XC2028_DEFAULT_FIRMWARE, .max_len = 64, - .scode_table = XC3028_FE_OREN538, + .demod = XC3028_FE_OREN538, }; fe = dvb_attach(xc2028_attach, -- cgit v1.2.3 From 2223f3be8a747246fc0a5956421bdbabfe8cdbcc Mon Sep 17 00:00:00 2001 From: Steven Toth Date: Sat, 28 Mar 2009 13:22:21 -0400 Subject: cx88: Add support for the Hauppauge IROnly board. From: Steven Toth cx88: Add support for the Hauppauge IROnly board. Priority: normal Signed-off-by: Steven Toth --- linux/drivers/media/video/cx88/cx88-cards.c | 13 +++++++++++++ linux/drivers/media/video/cx88/cx88-input.c | 2 ++ linux/drivers/media/video/cx88/cx88.h | 1 + 3 files changed, 16 insertions(+) (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 a4d49fbf7..c9bfa835e 100644 --- a/linux/drivers/media/video/cx88/cx88-cards.c +++ b/linux/drivers/media/video/cx88/cx88-cards.c @@ -2002,6 +2002,13 @@ static const struct cx88_board cx88_boards[] = { }, .mpeg = CX88_MPEG_DVB, }, + [CX88_BOARD_HAUPPAUGE_IRONLY] = { + .name = "Hauppauge WinTV-IR Only", + .tuner_type = UNSET, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + }, }; /* ------------------------------------------------------------------ */ @@ -2415,6 +2422,10 @@ static const struct cx88_subid cx88_subids[] = { .subvendor = 0x153b, .subdevice = 0x1177, .card = CX88_BOARD_TERRATEC_CINERGY_HT_PCI_MKII, + }, { + .subvendor = 0x0070, + .subdevice = 0x9290, + .card = CX88_BOARD_HAUPPAUGE_IRONLY, }, }; @@ -2481,6 +2492,7 @@ static void hauppauge_eeprom(struct cx88_core *core, u8 *eeprom_data) case 90500: /* Nova-T-PCI (oem) */ case 90501: /* Nova-T-PCI (oem/IR) */ case 92000: /* Nova-SE2 (OEM, No Video or IR) */ + case 92900: /* WinTV-IROnly (No analog or digital Video inputs) */ case 94009: /* WinTV-HVR1100 (Video and IR Retail) */ case 94501: /* WinTV-HVR1100 (Video and IR OEM) */ case 96009: /* WinTV-HVR1300 (PAL Video, MPEG Video and IR RX) */ @@ -2940,6 +2952,7 @@ static void cx88_card_setup(struct cx88_core *core) case CX88_BOARD_HAUPPAUGE_HVR1300: case CX88_BOARD_HAUPPAUGE_HVR4000: case CX88_BOARD_HAUPPAUGE_HVR4000LITE: + case CX88_BOARD_HAUPPAUGE_IRONLY: if (0 == core->i2c_rc) hauppauge_eeprom(core, eeprom); break; diff --git a/linux/drivers/media/video/cx88/cx88-input.c b/linux/drivers/media/video/cx88/cx88-input.c index 8a2e631b7..facb2e800 100644 --- a/linux/drivers/media/video/cx88/cx88-input.c +++ b/linux/drivers/media/video/cx88/cx88-input.c @@ -230,6 +230,7 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) case CX88_BOARD_HAUPPAUGE_HVR4000LITE: case CX88_BOARD_PCHDTV_HD3000: case CX88_BOARD_PCHDTV_HD5500: + case CX88_BOARD_HAUPPAUGE_IRONLY: ir_codes = ir_codes_hauppauge_new; ir_type = IR_TYPE_RC5; ir->sampling = 1; @@ -476,6 +477,7 @@ void cx88_ir_irq(struct cx88_core *core) case CX88_BOARD_HAUPPAUGE_HVR4000LITE: case CX88_BOARD_PCHDTV_HD3000: case CX88_BOARD_PCHDTV_HD5500: + case CX88_BOARD_HAUPPAUGE_IRONLY: ircode = ir_decode_biphase(ir->samples, ir->scount, 5, 7); ir_dprintk("biphase decoded: %x\n", ircode); /* diff --git a/linux/drivers/media/video/cx88/cx88.h b/linux/drivers/media/video/cx88/cx88.h index 1cf6900e0..0c00c34bc 100644 --- a/linux/drivers/media/video/cx88/cx88.h +++ b/linux/drivers/media/video/cx88/cx88.h @@ -236,6 +236,7 @@ extern struct sram_channel cx88_sram_channels[]; #define CX88_BOARD_TBS_8910 77 #define CX88_BOARD_PROF_6200 78 #define CX88_BOARD_TERRATEC_CINERGY_HT_PCI_MKII 79 +#define CX88_BOARD_HAUPPAUGE_IRONLY 80 enum cx88_itype { CX88_VMUX_COMPOSITE1 = 1, -- cgit v1.2.3 From 01a9b73d338c6ac427e752fbc56c85d1ab5259b9 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Sat, 28 Mar 2009 14:35:26 -0400 Subject: tuner: prevent invalid initialization of t->config in set_type From: Michael Krufky Drivers that don't set "config" directly in the set_type function will end up with an invalid configuration value. Check that the value is sane, otherwise initialize to 0. Thanks to James Edward Geiger & Steven Toth for reporting this bug. Priority: high Signed-off-by: Michael Krufky Cc: Steven Toth Cc: James Edward Geiger --- linux/drivers/media/video/tuner-core.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/tuner-core.c b/linux/drivers/media/video/tuner-core.c index 0188d87ea..a0cbd71e8 100644 --- a/linux/drivers/media/video/tuner-core.c +++ b/linux/drivers/media/video/tuner-core.c @@ -365,7 +365,8 @@ static void set_type(struct i2c_client *c, unsigned int type, } t->type = type; - t->config = new_config; + /* prevent invalid config values */ + t->config = ((new_config >= 0) && (new_config < 256)) ? new_config : 0; if (tuner_callback != NULL) { tuner_dbg("defining GPIO callback\n"); t->fe.callback = tuner_callback; -- cgit v1.2.3 From c6a7ca4c96fd867b70c72a7fdb08866a592dd844 Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Sat, 28 Mar 2009 18:25:35 -0700 Subject: v4l2-ioctl: Check format for S_PARM and G_PARM From: Trent Piepho Return EINVAL if VIDIOC_S/G_PARM is called for a buffer type that the driver doesn't define a ->vidioc_try_fmt_XXX() method for. Several other ioctls, like QUERYBUF, QBUF, and DQBUF, etc. do this too. It saves each driver from having to check if the buffer type is one that it supports. Priority: normal Signed-off-by: Trent Piepho --- linux/drivers/media/video/v4l2-ioctl.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/v4l2-ioctl.c b/linux/drivers/media/video/v4l2-ioctl.c index 5cf729c9d..c16ef96ee 100644 --- a/linux/drivers/media/video/v4l2-ioctl.c +++ b/linux/drivers/media/video/v4l2-ioctl.c @@ -1552,6 +1552,9 @@ static long __video_do_ioctl(struct file *file, struct v4l2_streamparm *p = arg; if (ops->vidioc_g_parm) { + ret = check_fmt(ops, p->type); + if (ret) + break; ret = ops->vidioc_g_parm(file, fh, p); } else { if (p->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) @@ -1571,6 +1574,10 @@ static long __video_do_ioctl(struct file *file, if (!ops->vidioc_s_parm) break; + ret = check_fmt(ops, p->type); + if (ret) + break; + dbgarg(cmd, "type=%d\n", p->type); ret = ops->vidioc_s_parm(file, fh, p); break; -- cgit v1.2.3 From 4e02f28e367a1129eabbf9c8a94c1514d4fc7a8b Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Sat, 28 Mar 2009 18:25:35 -0700 Subject: saa7146: Remove buffer type check from vidioc_g_parm From: Trent Piepho The v4l2-ioctl core now only allows buffer types for which the corresponding ->vidioc_try_fmt_xxx() methods are defined to be used with vidioc_(g|s)_parm. The driver was only allowing VIDEO_CAPTURE buffers for g_parm, but since the driver defines ->vidioc_try_fmt_vid_overlay() it will now allow VIDEO_OVERLAY buffers as well. This should be fine as the fields the driver fills in, readbuffers and frame rate, aren't wrong for VIDEO_OVERLAY buffers. Priority: normal Signed-off-by: Trent Piepho --- linux/drivers/media/common/saa7146_video.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/common/saa7146_video.c b/linux/drivers/media/common/saa7146_video.c index ace925134..46c59da56 100644 --- a/linux/drivers/media/common/saa7146_video.c +++ b/linux/drivers/media/common/saa7146_video.c @@ -724,8 +724,6 @@ static int vidioc_g_parm(struct file *file, void *fh, struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev; struct saa7146_vv *vv = dev->vv_data; - if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; parm->parm.capture.readbuffers = 1; v4l2_video_std_frame_period(vv->standard->id, &parm->parm.capture.timeperframe); -- cgit v1.2.3 From 5d25c814ad864544eb0e58593cadc604618a852c Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Sat, 28 Mar 2009 18:25:35 -0700 Subject: bttv: Remove buffer type check from vidioc_g_parm From: Trent Piepho The v4l2-ioctl core only allows buffer types for which the corresponding ->vidioc_try_fmt_xxx() methods are defined to be used with vidioc_(q|dq|query)bufs(), vidioc_reqbufs() and now vidioc_(s|g)_parm. The driver was only allowing VIDEO_CAPTURE buffers for g_parm, but since the driver defines ->vidioc_try_fmt_vid_overlay() and ->vidioc_try_fmt_vbi_cap() it will now allow VIDEO_OVERLAY and VBI_CAPTURE buffers as well. This should be fine as the driver only fills in the frame rate field, which is just as valid for video overlay and vbi capture as it is for video capture. Priority: normal Signed-off-by: Trent Piepho --- linux/drivers/media/video/bt8xx/bttv-driver.c | 2 -- 1 file changed, 2 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 acb7b5e3d..d91062d97 100644 --- a/linux/drivers/media/video/bt8xx/bttv-driver.c +++ b/linux/drivers/media/video/bt8xx/bttv-driver.c @@ -2956,8 +2956,6 @@ static int bttv_g_parm(struct file *file, void *f, struct bttv_fh *fh = f; struct bttv *btv = fh->btv; - if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; v4l2_video_std_frame_period(bttv_tvnorms[btv->tvnorm].v4l2_id, &parm->parm.capture.timeperframe); return 0; -- cgit v1.2.3 From 57f3110ab60dcf436b20b31c6e7764f0024040ca Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Sat, 28 Mar 2009 18:25:35 -0700 Subject: gspca: Stop setting buffer type, and avoid memset in querycap From: Trent Piepho The v4l2-ioctl core checks the buffer type now by only allowing buffer types for which the corresponding ->vidioc_try_fmt_xxx() methods are defined. This driver only defines ->vidioc_try_fmt_vid_cap() so only VIDEO_CAPTURE buffers are allowed to be used with vidioc_g_parm. Also, ->vidioc_enum_fmt_vid_cap() is only called for VIDEO_CAPTURE buffers. There is no need to set the buffer type since it must already be the correct value. The struct which ->vidioc_querycap() is supposed to fill in is already zeroed so it's not necessary to call memset on it. Priority: normal Signed-off-by: Trent Piepho CC: Jean-Francois Moine --- linux/drivers/media/video/gspca/gspca.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/gspca.c b/linux/drivers/media/video/gspca/gspca.c index 88de8b865..93c35d083 100644 --- a/linux/drivers/media/video/gspca/gspca.c +++ b/linux/drivers/media/video/gspca/gspca.c @@ -777,7 +777,6 @@ static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, fmtdesc->pixelformat = fmt_tb[index]; if (gspca_is_compressed(fmt_tb[index])) fmtdesc->flags = V4L2_FMT_FLAG_COMPRESSED; - fmtdesc->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; fmtdesc->description[0] = fmtdesc->pixelformat & 0xff; fmtdesc->description[1] = (fmtdesc->pixelformat >> 8) & 0xff; fmtdesc->description[2] = (fmtdesc->pixelformat >> 16) & 0xff; @@ -974,8 +973,6 @@ static int vidioc_querycap(struct file *file, void *priv, struct gspca_dev *gspca_dev = priv; int ret; - memset(cap, 0, sizeof *cap); - /* protect the access to the usb device */ if (mutex_lock_interruptible(&gspca_dev->usb_lock)) return -ERESTARTSYS; @@ -1353,7 +1350,6 @@ static int vidioc_g_parm(struct file *filp, void *priv, { struct gspca_dev *gspca_dev = priv; - parm->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; parm->parm.capture.readbuffers = gspca_dev->nbufread; if (gspca_dev->sd_desc->get_streamparm) { -- cgit v1.2.3 From 3a35050c66a731aa86d6cb3a7578e19036879be1 Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Sat, 28 Mar 2009 18:25:36 -0700 Subject: omap24xxcam: Remove buffer type check from vidioc_s/g_parm From: Trent Piepho The v4l2-ioctl core now only allows buffer types for which the corresponding ->vidioc_try_fmt_xxx() methods are defined to be used in vidioc_(g|s)_parm. This driver only defines ->vidioc_try_fmt_vid_cap() so only VIDEO_CAPTURE buffers are allowed to be used with vidioc_s_parm() and vidioc_g_parm(). Priority: normal Signed-off-by: Trent Piepho CC: Sakari Ailus --- linux/drivers/media/video/omap24xxcam.c | 6 ------ 1 file changed, 6 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/omap24xxcam.c b/linux/drivers/media/video/omap24xxcam.c index 61f3c83db..d828597ba 100644 --- a/linux/drivers/media/video/omap24xxcam.c +++ b/linux/drivers/media/video/omap24xxcam.c @@ -1285,9 +1285,6 @@ static int vidioc_g_parm(struct file *file, void *fh, struct omap24xxcam_device *cam = ofh->cam; int rval; - if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - mutex_lock(&cam->mutex); rval = vidioc_int_g_parm(cam->sdev, a); mutex_unlock(&cam->mutex); @@ -1303,9 +1300,6 @@ static int vidioc_s_parm(struct file *file, void *fh, struct v4l2_streamparm old_streamparm; int rval; - if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - mutex_lock(&cam->mutex); if (cam->streaming) { rval = -EBUSY; -- cgit v1.2.3 From 08340d0b0c4b007c6ea1f300e3281b012da7f21b Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Sat, 28 Mar 2009 18:25:36 -0700 Subject: stkwebcam: Remove buffer type check from g_parm and q/dq/reqbufs From: Trent Piepho The v4l2-ioctl core only allows buffer types for which the corresponding ->vidioc_try_fmt_xxx() methods are defined to be used with vidioc_(q|dq|query)bufs(), vidioc_reqbufs() and now vidioc_(s|g)_parm. This driver only defines ->vidioc_try_fmt_vid_cap() so only VIDEO_CAPTURE buffers are allowed to be used with vidioc_g_parm(), vidioc_qbuf(), vidioc_dqbuf(), and vidioc_reqbufs(). Priority: normal Signed-off-by: Trent Piepho CC: Jaime Velasco Juan --- linux/drivers/media/video/stk-webcam.c | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/stk-webcam.c b/linux/drivers/media/video/stk-webcam.c index 54efa2cc0..7cbc4f736 100644 --- a/linux/drivers/media/video/stk-webcam.c +++ b/linux/drivers/media/video/stk-webcam.c @@ -1113,8 +1113,6 @@ static int stk_vidioc_reqbufs(struct file *filp, if (dev == NULL) return -ENODEV; - if (rb->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; if (rb->memory != V4L2_MEMORY_MMAP) return -EINVAL; if (is_streaming(dev) @@ -1153,8 +1151,6 @@ static int stk_vidioc_qbuf(struct file *filp, struct stk_camera *dev = priv; struct stk_sio_buffer *sbuf; unsigned long flags; - if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; if (buf->memory != V4L2_MEMORY_MMAP) return -EINVAL; @@ -1181,8 +1177,7 @@ static int stk_vidioc_dqbuf(struct file *filp, unsigned long flags; int ret; - if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE - || !is_streaming(dev)) + if (!is_streaming(dev)) return -EINVAL; if (filp->f_flags & O_NONBLOCK && list_empty(&dev->sio_full)) @@ -1241,9 +1236,6 @@ static int stk_vidioc_streamoff(struct file *filp, static int stk_vidioc_g_parm(struct file *filp, void *priv, struct v4l2_streamparm *sp) { - if (sp->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - /*FIXME This is not correct */ sp->parm.capture.timeperframe.numerator = 1; sp->parm.capture.timeperframe.denominator = 30; -- cgit v1.2.3 From 3826b3c7a2e11305ae0a51156426920fc03cc21e Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Sat, 28 Mar 2009 18:25:36 -0700 Subject: vino: Remove code for things already done by video_ioctl2 From: Trent Piepho The v4l2-ioctl core only allows buffer types for which the corresponding ->vidioc_try_fmt_xxx() methods are defined to be used in vidioc_(g|s)_parm, vidioc_(q|dq|query)buf, and vidioc_reqbufs. Remove buffer type checking from vino_g_parm(), vino_s_parm(), vino_reqbufs(), vino_querybuf(), vino_qbuf(), and vino_dqbuf(). This reduced the indent level of the code so a few lines can be wrapped better. Also fixed the C++ type comments. The v4l2-ioctl core also provides structs that have been pre-zeroed for all fields that driver is supposed to fill in, so remove zeroing code from vino_enum_fmt_vid_cap(). Also, the format index is unsigned so it's not necessary to check if it's less than zero. Priority: normal Signed-off-by: Trent Piepho --- linux/drivers/media/video/vino.c | 290 +++++++++++++++------------------------ 1 file changed, 114 insertions(+), 176 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/vino.c b/linux/drivers/media/video/vino.c index ba4e8b97d..274b99b56 100644 --- a/linux/drivers/media/video/vino.c +++ b/linux/drivers/media/video/vino.c @@ -3106,22 +3106,14 @@ out: static int vino_enum_fmt_vid_cap(struct file *file, void *__fh, struct v4l2_fmtdesc *fd) { - enum v4l2_buf_type type = fd->type; - int index = fd->index; + dprintk("format index = %d\n", fd->index); - dprintk("format index = %d\n", index); - - if ((fd->index < 0) || - (fd->index >= VINO_DATA_FMT_COUNT)) + if (fd->index >= VINO_DATA_FMT_COUNT) return -EINVAL; - dprintk("format name = %s\n", - vino_data_formats[index].description); - - memset(fd, 0, sizeof(struct v4l2_fmtdesc)); - fd->index = index; - fd->type = type; - fd->pixelformat = vino_data_formats[index].pixelformat; - strcpy(fd->description, vino_data_formats[index].description); + dprintk("format name = %s\n", vino_data_formats[fd->index].description); + + fd->pixelformat = vino_data_formats[fd->index].pixelformat; + strcpy(fd->description, vino_data_formats[fd->index].description); return 0; } @@ -3331,28 +3323,18 @@ static int vino_g_parm(struct file *file, void *__fh, { struct vino_channel_settings *vcs = video_drvdata(file); unsigned long flags; + struct v4l2_captureparm *cp = &sp->parm.capture; - switch (sp->type) { - case V4L2_BUF_TYPE_VIDEO_CAPTURE: { - struct v4l2_captureparm *cp = &sp->parm.capture; - memset(cp, 0, sizeof(struct v4l2_captureparm)); + cp->capability = V4L2_CAP_TIMEPERFRAME; + cp->timeperframe.numerator = 1; - cp->capability = V4L2_CAP_TIMEPERFRAME; - cp->timeperframe.numerator = 1; + spin_lock_irqsave(&vino_drvdata->input_lock, flags); - spin_lock_irqsave(&vino_drvdata->input_lock, flags); + cp->timeperframe.denominator = vcs->fps; - cp->timeperframe.denominator = vcs->fps; + spin_unlock_irqrestore(&vino_drvdata->input_lock, flags); - spin_unlock_irqrestore(&vino_drvdata->input_lock, flags); - - // TODO: cp->readbuffers = xxx; - break; - } - case V4L2_BUF_TYPE_VIDEO_OVERLAY: - default: - return -EINVAL; - } + /* TODO: cp->readbuffers = xxx; */ return 0; } @@ -3362,32 +3344,21 @@ static int vino_s_parm(struct file *file, void *__fh, { struct vino_channel_settings *vcs = video_drvdata(file); unsigned long flags; + struct v4l2_captureparm *cp = &sp->parm.capture; - switch (sp->type) { - case V4L2_BUF_TYPE_VIDEO_CAPTURE: { - struct v4l2_captureparm *cp = &sp->parm.capture; - - spin_lock_irqsave(&vino_drvdata->input_lock, flags); - - if ((cp->timeperframe.numerator == 0) || - (cp->timeperframe.denominator == 0)) { - /* reset framerate */ - vino_set_default_framerate(vcs); - } else { - vino_set_framerate(vcs, cp->timeperframe.denominator / - cp->timeperframe.numerator); - } - - spin_unlock_irqrestore(&vino_drvdata->input_lock, flags); + spin_lock_irqsave(&vino_drvdata->input_lock, flags); - // TODO: set buffers according to cp->readbuffers - break; - } - case V4L2_BUF_TYPE_VIDEO_OVERLAY: - default: - return -EINVAL; + if ((cp->timeperframe.numerator == 0) || + (cp->timeperframe.denominator == 0)) { + /* reset framerate */ + vino_set_default_framerate(vcs); + } else { + vino_set_framerate(vcs, cp->timeperframe.denominator / + cp->timeperframe.numerator); } + spin_unlock_irqrestore(&vino_drvdata->input_lock, flags); + return 0; } @@ -3395,42 +3366,35 @@ static int vino_reqbufs(struct file *file, void *__fh, struct v4l2_requestbuffers *rb) { struct vino_channel_settings *vcs = video_drvdata(file); + if (vcs->reading) return -EBUSY; - switch (rb->type) { - case V4L2_BUF_TYPE_VIDEO_CAPTURE: { - // TODO: check queue type - if (rb->memory != V4L2_MEMORY_MMAP) { - dprintk("type not mmap\n"); - return -EINVAL; - } + /* TODO: check queue type */ + if (rb->memory != V4L2_MEMORY_MMAP) { + dprintk("type not mmap\n"); + return -EINVAL; + } - dprintk("count = %d\n", rb->count); - if (rb->count > 0) { - if (vino_is_capturing(vcs)) { - dprintk("busy, capturing\n"); - return -EBUSY; - } + dprintk("count = %d\n", rb->count); + if (rb->count > 0) { + if (vino_is_capturing(vcs)) { + dprintk("busy, capturing\n"); + return -EBUSY; + } - if (vino_queue_has_mapped_buffers(&vcs->fb_queue)) { - dprintk("busy, buffers still mapped\n"); - return -EBUSY; - } else { - vcs->streaming = 0; - vino_queue_free(&vcs->fb_queue); - vino_queue_init(&vcs->fb_queue, &rb->count); - } + if (vino_queue_has_mapped_buffers(&vcs->fb_queue)) { + dprintk("busy, buffers still mapped\n"); + return -EBUSY; } else { vcs->streaming = 0; - vino_capture_stop(vcs); vino_queue_free(&vcs->fb_queue); + vino_queue_init(&vcs->fb_queue, &rb->count); } - break; - } - case V4L2_BUF_TYPE_VIDEO_OVERLAY: - default: - return -EINVAL; + } else { + vcs->streaming = 0; + vino_capture_stop(vcs); + vino_queue_free(&vcs->fb_queue); } return 0; @@ -3478,35 +3442,27 @@ static int vino_querybuf(struct file *file, void *__fh, struct v4l2_buffer *b) { struct vino_channel_settings *vcs = video_drvdata(file); + struct vino_framebuffer *fb; + if (vcs->reading) return -EBUSY; - switch (b->type) { - case V4L2_BUF_TYPE_VIDEO_CAPTURE: { - struct vino_framebuffer *fb; - - // TODO: check queue type - if (b->index >= vino_queue_get_length(&vcs->fb_queue)) { - dprintk("invalid index = %d\n", - b->index); - return -EINVAL; - } - - fb = vino_queue_get_buffer(&vcs->fb_queue, - b->index); - if (fb == NULL) { - dprintk("vino_queue_get_buffer() failed"); - return -EINVAL; - } - - vino_v4l2_get_buffer_status(vcs, fb, b); - break; + /* TODO: check queue type */ + if (b->index >= vino_queue_get_length(&vcs->fb_queue)) { + dprintk("invalid index = %d\n", + b->index); + return -EINVAL; } - case V4L2_BUF_TYPE_VIDEO_OVERLAY: - default: + + fb = vino_queue_get_buffer(&vcs->fb_queue, + b->index); + if (fb == NULL) { + dprintk("vino_queue_get_buffer() failed"); return -EINVAL; } + vino_v4l2_get_buffer_status(vcs, fb, b); + return 0; } @@ -3514,36 +3470,28 @@ static int vino_qbuf(struct file *file, void *__fh, struct v4l2_buffer *b) { struct vino_channel_settings *vcs = video_drvdata(file); + struct vino_framebuffer *fb; + int ret; + if (vcs->reading) return -EBUSY; - switch (b->type) { - case V4L2_BUF_TYPE_VIDEO_CAPTURE: { - struct vino_framebuffer *fb; - int ret; - - // TODO: check queue type - if (b->memory != V4L2_MEMORY_MMAP) { - dprintk("type not mmap\n"); - return -EINVAL; - } + /* TODO: check queue type */ + if (b->memory != V4L2_MEMORY_MMAP) { + dprintk("type not mmap\n"); + return -EINVAL; + } - fb = vino_capture_enqueue(vcs, b->index); - if (fb == NULL) - return -EINVAL; + fb = vino_capture_enqueue(vcs, b->index); + if (fb == NULL) + return -EINVAL; - vino_v4l2_get_buffer_status(vcs, fb, b); + vino_v4l2_get_buffer_status(vcs, fb, b); - if (vcs->streaming) { - ret = vino_capture_next(vcs, 1); - if (ret) - return ret; - } - break; - } - case V4L2_BUF_TYPE_VIDEO_OVERLAY: - default: - return -EINVAL; + if (vcs->streaming) { + ret = vino_capture_next(vcs, 1); + if (ret) + return ret; } return 0; @@ -3554,73 +3502,63 @@ static int vino_dqbuf(struct file *file, void *__fh, { struct vino_channel_settings *vcs = video_drvdata(file); unsigned int nonblocking = file->f_flags & O_NONBLOCK; + struct vino_framebuffer *fb; + unsigned int incoming, outgoing; + int err; + if (vcs->reading) return -EBUSY; - switch (b->type) { - case V4L2_BUF_TYPE_VIDEO_CAPTURE: { - struct vino_framebuffer *fb; - unsigned int incoming, outgoing; - int err; + /* TODO: check queue type */ + + err = vino_queue_get_incoming(&vcs->fb_queue, &incoming); + if (err) { + dprintk("vino_queue_get_incoming() failed\n"); + return -EINVAL; + } + err = vino_queue_get_outgoing(&vcs->fb_queue, &outgoing); + if (err) { + dprintk("vino_queue_get_outgoing() failed\n"); + return -EINVAL; + } - // TODO: check queue type + dprintk("incoming = %d, outgoing = %d\n", incoming, outgoing); - err = vino_queue_get_incoming(&vcs->fb_queue, &incoming); - if (err) { - dprintk("vino_queue_get_incoming() failed\n"); + if (outgoing == 0) { + if (incoming == 0) { + dprintk("no incoming or outgoing buffers\n"); return -EINVAL; } - err = vino_queue_get_outgoing(&vcs->fb_queue, &outgoing); - if (err) { - dprintk("vino_queue_get_outgoing() failed\n"); - return -EINVAL; + if (nonblocking) { + dprintk("non-blocking I/O was selected and " + "there are no buffers to dequeue\n"); + return -EAGAIN; } - dprintk("incoming = %d, outgoing = %d\n", incoming, outgoing); - - if (outgoing == 0) { - if (incoming == 0) { - dprintk("no incoming or outgoing buffers\n"); - return -EINVAL; - } - if (nonblocking) { - dprintk("non-blocking I/O was selected and " - "there are no buffers to dequeue\n"); - return -EAGAIN; - } - + err = vino_wait_for_frame(vcs); + if (err) { err = vino_wait_for_frame(vcs); if (err) { - err = vino_wait_for_frame(vcs); - if (err) { - /* interrupted or - * no frames captured because - * of frame skipping */ - // vino_capture_failed(vcs); - return -EIO; - } + /* interrupted or no frames captured because of + * frame skipping */ + /* vino_capture_failed(vcs); */ + return -EIO; } } + } - fb = vino_queue_remove(&vcs->fb_queue, &b->index); - if (fb == NULL) { - dprintk("vino_queue_remove() failed\n"); - return -EINVAL; - } - - err = vino_check_buffer(vcs, fb); + fb = vino_queue_remove(&vcs->fb_queue, &b->index); + if (fb == NULL) { + dprintk("vino_queue_remove() failed\n"); + return -EINVAL; + } - vino_v4l2_get_buffer_status(vcs, fb, b); + err = vino_check_buffer(vcs, fb); - if (err) - return -EIO; + vino_v4l2_get_buffer_status(vcs, fb, b); - break; - } - case V4L2_BUF_TYPE_VIDEO_OVERLAY: - default: - return -EINVAL; - } + if (err) + return -EIO; return 0; } -- cgit v1.2.3 From 4ee6e80d40bf32b32e2911094e3146d727b0a007 Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Sat, 28 Mar 2009 18:25:36 -0700 Subject: cafe_ccic: Remove buffer type check from XXXbuf From: Trent Piepho The v4l2-ioctl core only allows buffer types for which the corresponding ->vidioc_try_fmt_xxx() methods are defined to be used with vidioc_(q|dq|query)bufs() and vidioc_reqbufs(). This driver only defines ->vidioc_try_fmt_vid_cap() so only VIDEO_CAPTURE buffers are allowed to be used with cafe_vidioc_reqbufs(), cafe_vidioc_querybuf(), cafe_vidioc_qbuf(), and cafe_vidioc_dqbuf(). The ->vidioc_(s|g|try|enum)_fmt_vid_cap() methods are only called on VIDEO_CAPTURE buffers. Thus, there is no need to check or set the buffer's 'type' field since it must already be set to VIDEO_CAPTURE. So the check in cafe_vidioc_enum_fmt_vid_cap() can be removed. The 'index' field of v4l2_buffer is unsigned so the checks for it being less than zero can be removed too. Priority: normal Signed-off-by: Trent Piepho --- linux/drivers/media/video/cafe_ccic.c | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/cafe_ccic.c b/linux/drivers/media/video/cafe_ccic.c index 2619d77ef..2516e80ed 100644 --- a/linux/drivers/media/video/cafe_ccic.c +++ b/linux/drivers/media/video/cafe_ccic.c @@ -1152,8 +1152,6 @@ static int cafe_vidioc_reqbufs(struct file *filp, void *priv, * Make sure it's something we can do. User pointers could be * implemented without great pain, but that's not been done yet. */ - if (req->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; if (req->memory != V4L2_MEMORY_MMAP) return -EINVAL; /* @@ -1217,9 +1215,7 @@ static int cafe_vidioc_querybuf(struct file *filp, void *priv, int ret = -EINVAL; mutex_lock(&cam->s_mutex); - if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - goto out; - if (buf->index < 0 || buf->index >= cam->n_sbufs) + if (buf->index >= cam->n_sbufs) goto out; *buf = cam->sb_bufs[buf->index].v4lbuf; ret = 0; @@ -1237,9 +1233,7 @@ static int cafe_vidioc_qbuf(struct file *filp, void *priv, unsigned long flags; mutex_lock(&cam->s_mutex); - if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - goto out; - if (buf->index < 0 || buf->index >= cam->n_sbufs) + if (buf->index >= cam->n_sbufs) goto out; sbuf = cam->sb_bufs + buf->index; if (sbuf->v4lbuf.flags & V4L2_BUF_FLAG_QUEUED) { @@ -1270,8 +1264,6 @@ static int cafe_vidioc_dqbuf(struct file *filp, void *priv, unsigned long flags; mutex_lock(&cam->s_mutex); - if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - goto out_unlock; if (cam->state != S_STREAMING) goto out_unlock; if (list_empty(&cam->sb_full) && filp->f_flags & O_NONBLOCK) { @@ -1504,8 +1496,6 @@ static int cafe_vidioc_enum_fmt_vid_cap(struct file *filp, struct cafe_camera *cam = priv; int ret; - if (fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; mutex_lock(&cam->s_mutex); ret = sensor_call(cam, video, enum_fmt, fmt); mutex_unlock(&cam->s_mutex); -- cgit v1.2.3 From 12b11ffa41a0e6082845fda66e358b6df19ec1a4 Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Sat, 28 Mar 2009 18:25:36 -0700 Subject: cx23885-417: Don't need to zero ioctl parameter fields From: Trent Piepho The v4l2 core code in v4l2_ioctl will zero out the structure the driver is supposed to fill in for read-only ioctls. For read/write ioctls, all the fields which aren't supplied from userspace will be zeroed out. Zeroing code is removed from enum_input, g_tuner, g_frequency, querycap, enum_fmt_vid_cap, g_fmt_vid_cap, and try_fmt_vid_cap. The ->vidioc_(s|g|try|enum)_fmt_vid_cap() methods are only called on VIDEO_CAPTURE buffers. Thus, there is no need to check or set the buffer's 'type' field since it must already be set to VIDEO_CAPTURE. There also appeared to be a copy and paste error in vidioc_try_fmt_vid_cap() that would set f->fmt.pix.sizeimage to zero. Note that the s_fmt_vid_cap method doesn't appear to actually do anything. Whatever parameters were requested are just silently ignored. Was this intentional? Who knows, as the commit log entry for the driver just says, "Add generic cx23417 hardware encoder support." There are no docs. A comment like "this driver totally ignores the v4l2 spec w.r.t. VIDIOC_S_FMT because ..." would have gone a long way. Priority: normal Signed-off-by: Trent Piepho CC: Steven Toth --- linux/drivers/media/video/cx23885/cx23885-417.c | 27 ++++--------------------- 1 file changed, 4 insertions(+), 23 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/cx23885/cx23885-417.c b/linux/drivers/media/video/cx23885/cx23885-417.c index 0766a97a0..7e7e75237 100644 --- a/linux/drivers/media/video/cx23885/cx23885-417.c +++ b/linux/drivers/media/video/cx23885/cx23885-417.c @@ -1206,21 +1206,16 @@ static int vidioc_enum_input(struct file *file, void *priv, struct cx23885_fh *fh = file->private_data; struct cx23885_dev *dev = fh->dev; struct cx23885_input *input; - unsigned int n; + int n; - n = i->index; - - if (n >= 4) + if (i->index >= 4) return -EINVAL; - input = &cx23885_boards[dev->board].input[n]; + input = &cx23885_boards[dev->board].input[i->index]; if (input->type == 0) return -EINVAL; - memset(i, 0, sizeof(*i)); - i->index = n; - /* FIXME * strcpy(i->name, input->name); */ strcpy(i->name, "unset"); @@ -1263,7 +1258,6 @@ static int vidioc_g_tuner(struct file *file, void *priv, return -EINVAL; if (0 != t->index) return -EINVAL; - memset(t, 0, sizeof(*t)); strcpy(t->name, "Television"); cx23885_call_i2c_clients(&dev->i2c_bus[2], VIDIOC_G_TUNER, t); cx23885_call_i2c_clients(&dev->i2c_bus[1], VIDIOC_G_TUNER, t); @@ -1294,7 +1288,6 @@ static int vidioc_g_frequency(struct file *file, void *priv, struct cx23885_fh *fh = file->private_data; struct cx23885_dev *dev = fh->dev; - memset(f, 0, sizeof(*f)); if (UNSET == dev->tuner_type) return -EINVAL; f->type = V4L2_TUNER_ANALOG_TV; @@ -1354,7 +1347,6 @@ static int vidioc_querycap(struct file *file, void *priv, struct cx23885_dev *dev = fh->dev; struct cx23885_tsport *tsport = &dev->ts1; - memset(cap, 0, sizeof(*cap)); strcpy(cap->driver, dev->name); strlcpy(cap->card, cx23885_boards[tsport->dev->board].name, sizeof(cap->card)); @@ -1374,16 +1366,10 @@ static int vidioc_querycap(struct file *file, void *priv, static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, struct v4l2_fmtdesc *f) { - int index; - - index = f->index; - if (index != 0) + if (f->index != 0) return -EINVAL; - memset(f, 0, sizeof(*f)); - f->index = index; strlcpy(f->description, "MPEG", sizeof(f->description)); - f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; f->pixelformat = V4L2_PIX_FMT_MPEG; return 0; @@ -1395,8 +1381,6 @@ static int vidioc_g_fmt_vid_cap(struct file *file, void *priv, struct cx23885_fh *fh = file->private_data; struct cx23885_dev *dev = fh->dev; - memset(f, 0, sizeof(*f)); - f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG; f->fmt.pix.bytesperline = 0; f->fmt.pix.sizeimage = @@ -1416,12 +1400,10 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, struct cx23885_fh *fh = file->private_data; struct cx23885_dev *dev = fh->dev; - f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG; f->fmt.pix.bytesperline = 0; f->fmt.pix.sizeimage = dev->ts1.ts_packet_size * dev->ts1.ts_packet_count; - f->fmt.pix.sizeimage = f->fmt.pix.colorspace = 0; dprintk(1, "VIDIOC_TRY_FMT: w: %d, h: %d, f: %d\n", dev->ts1.width, dev->ts1.height, fh->mpegq.field); @@ -1434,7 +1416,6 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, struct cx23885_fh *fh = file->private_data; struct cx23885_dev *dev = fh->dev; - f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG; f->fmt.pix.bytesperline = 0; f->fmt.pix.sizeimage = -- cgit v1.2.3 From 32bcd85629429ddf84d6e4eb8a49ccb98ccc73ad Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Sat, 28 Mar 2009 18:25:36 -0700 Subject: cx88-blackbird: Stop setting buffer type in XXX_fmt_vid_cap From: Trent Piepho The ->vidioc_(s|g|try|enum)_fmt_vid_cap() methods are only called on VIDEO_CAPTURE buffers. Thus, there is no need to check or set the 'type' field since it must already be set to VIDEO_CAPTURE. Priority: normal Signed-off-by: Trent Piepho --- linux/drivers/media/video/cx88/cx88-blackbird.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/cx88/cx88-blackbird.c b/linux/drivers/media/video/cx88/cx88-blackbird.c index 46e009403..f1a6f6984 100644 --- a/linux/drivers/media/video/cx88/cx88-blackbird.c +++ b/linux/drivers/media/video/cx88/cx88-blackbird.c @@ -761,7 +761,6 @@ static int vidioc_enum_fmt_vid_cap (struct file *file, void *priv, return -EINVAL; strlcpy(f->description, "MPEG", sizeof(f->description)); - f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; f->pixelformat = V4L2_PIX_FMT_MPEG; return 0; } @@ -772,7 +771,6 @@ static int vidioc_g_fmt_vid_cap (struct file *file, void *priv, struct cx8802_fh *fh = priv; struct cx8802_dev *dev = fh->dev; - f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG; f->fmt.pix.bytesperline = 0; f->fmt.pix.sizeimage = dev->ts_packet_size * dev->ts_packet_count; /* 188 * 4 * 1024; */ @@ -791,7 +789,6 @@ static int vidioc_try_fmt_vid_cap (struct file *file, void *priv, struct cx8802_fh *fh = priv; struct cx8802_dev *dev = fh->dev; - f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG; f->fmt.pix.bytesperline = 0; f->fmt.pix.sizeimage = dev->ts_packet_size * dev->ts_packet_count; /* 188 * 4 * 1024; */; @@ -808,7 +805,6 @@ static int vidioc_s_fmt_vid_cap (struct file *file, void *priv, struct cx8802_dev *dev = fh->dev; struct cx88_core *core = dev->core; - f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG; f->fmt.pix.bytesperline = 0; f->fmt.pix.sizeimage = dev->ts_packet_size * dev->ts_packet_count; /* 188 * 4 * 1024; */; -- cgit v1.2.3 From 794cc66f2e6bbda775e319221697bb7f02fecd30 Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Sat, 28 Mar 2009 18:25:36 -0700 Subject: meye: Remove buffer type checks from XXX_fmt_vid_cap, XXXbuf From: Trent Piepho The ->vidioc_(s|g|try|enum)_fmt_vid_cap() methods are only called on VIDEO_CAPTURE buffers. Thus, there is no need to check or set the buffer's 'type' field since it must already be set to VIDEO_CAPTURE. The v4l2-ioctl core only allows buffer types for which the corresponding ->vidioc_try_fmt_xxx() methods are defined to be used with vidioc_(q|dq|query)bufs() and vidioc_reqbufs(). Since this driver only defines ->vidioc_try_fmt_vid_cap() the checks can be removed from vidioc_reqbufs(), vidioc_querybuf(), vidioc_qbuf(), and vidioc_dqbuf(). Also, the buffer index is unsigned so it's not necessary to check if it is less than zero. Priority: normal Signed-off-by: Trent Piepho --- linux/drivers/media/video/meye.c | 29 +++-------------------------- 1 file changed, 3 insertions(+), 26 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/meye.c b/linux/drivers/media/video/meye.c index 85b2cff1a..11f0b5e0d 100644 --- a/linux/drivers/media/video/meye.c +++ b/linux/drivers/media/video/meye.c @@ -1261,18 +1261,13 @@ static int vidioc_enum_fmt_vid_cap(struct file *file, void *fh, if (f->index > 1) return -EINVAL; - if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - if (f->index == 0) { /* standard YUV 422 capture */ - f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; f->flags = 0; strcpy(f->description, "YUV422"); f->pixelformat = V4L2_PIX_FMT_YUYV; } else { /* compressed MJPEG capture */ - f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; f->flags = V4L2_FMT_FLAG_COMPRESSED; strcpy(f->description, "MJPEG"); f->pixelformat = V4L2_PIX_FMT_MJPEG; @@ -1284,9 +1279,6 @@ static int vidioc_enum_fmt_vid_cap(struct file *file, void *fh, static int vidioc_try_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *f) { - if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - if (f->fmt.pix.pixelformat != V4L2_PIX_FMT_YUYV && f->fmt.pix.pixelformat != V4L2_PIX_FMT_MJPEG) return -EINVAL; @@ -1317,9 +1309,6 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *fh, static int vidioc_g_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *f) { - if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - switch (meye.mchip_mode) { case MCHIP_HIC_MODE_CONT_OUT: default: @@ -1343,9 +1332,6 @@ static int vidioc_g_fmt_vid_cap(struct file *file, void *fh, static int vidioc_s_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *f) { - if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - if (f->fmt.pix.pixelformat != V4L2_PIX_FMT_YUYV && f->fmt.pix.pixelformat != V4L2_PIX_FMT_MJPEG) return -EINVAL; @@ -1391,9 +1377,6 @@ static int vidioc_reqbufs(struct file *file, void *fh, { int i; - if (req->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - if (req->memory != V4L2_MEMORY_MMAP) return -EINVAL; @@ -1434,9 +1417,9 @@ static int vidioc_reqbufs(struct file *file, void *fh, static int vidioc_querybuf(struct file *file, void *fh, struct v4l2_buffer *buf) { - int index = buf->index; + unsigned int index = buf->index; - if (index < 0 || index >= gbuffers) + if (index >= gbuffers) return -EINVAL; buf->bytesused = meye.grab_buffer[index].size; @@ -1460,13 +1443,10 @@ static int vidioc_querybuf(struct file *file, void *fh, struct v4l2_buffer *buf) static int vidioc_qbuf(struct file *file, void *fh, struct v4l2_buffer *buf) { - if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - if (buf->memory != V4L2_MEMORY_MMAP) return -EINVAL; - if (buf->index < 0 || buf->index >= gbuffers) + if (buf->index >= gbuffers) return -EINVAL; if (meye.grab_buffer[buf->index].state != MEYE_BUF_UNUSED) @@ -1486,9 +1466,6 @@ static int vidioc_dqbuf(struct file *file, void *fh, struct v4l2_buffer *buf) { int reqnr; - if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - if (buf->memory != V4L2_MEMORY_MMAP) return -EINVAL; -- cgit v1.2.3 From 552402f4297b8ba2fb1631079e66d1755b181796 Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Sat, 28 Mar 2009 18:25:36 -0700 Subject: usbvision: Remove buffer type checks from enum_fmt_vid_cap, XXXbuf From: Trent Piepho The v4l2-ioctl core only allows buffer types for which the corresponding ->vidioc_try_fmt_xxx() methods are defined to be used with vidioc_(q|dq|query)buf() and vidioc_reqbufs(). Since this driver only defines ->vidioc_try_fmt_vid_cap() the checks can be removed from vidioc_reqbufs(), vidioc_qbuf(), and vidioc_dqbuf(). The ->vidioc_(s|g|try|enum)_fmt_vid_cap() methods are only called on VIDEO_CAPTURE buffers. Thus, there is no need to check or set the buffer's 'type' field since it must already be set to VIDEO_CAPTURE. So setting the buffer type in vidioc_enum_fmt_vid_cap() can be removed. Priority: normal Signed-off-by: Trent Piepho --- linux/drivers/media/video/usbvision/usbvision-video.c | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/usbvision/usbvision-video.c b/linux/drivers/media/video/usbvision/usbvision-video.c index 74a7652de..fa62a2fd7 100644 --- a/linux/drivers/media/video/usbvision/usbvision-video.c +++ b/linux/drivers/media/video/usbvision/usbvision-video.c @@ -757,8 +757,7 @@ static int vidioc_reqbufs (struct file *file, /* Check input validity: the user must do a VIDEO CAPTURE and MMAP method. */ - if((vr->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) || - (vr->memory != V4L2_MEMORY_MMAP)) + if (vr->memory != V4L2_MEMORY_MMAP) return -EINVAL; if(usbvision->streaming == Stream_On) { @@ -816,9 +815,6 @@ static int vidioc_qbuf (struct file *file, void *priv, struct v4l2_buffer *vb) unsigned long lock_flags; /* FIXME : works only on VIDEO_CAPTURE MODE, MMAP. */ - if(vb->type != V4L2_CAP_VIDEO_CAPTURE) { - return -EINVAL; - } if(vb->index>=usbvision->num_frames) { return -EINVAL; } @@ -853,9 +849,6 @@ static int vidioc_dqbuf (struct file *file, void *priv, struct v4l2_buffer *vb) struct usbvision_frame *f; unsigned long lock_flags; - if (vb->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - if (list_empty(&(usbvision->outqueue))) { if (usbvision->streaming == Stream_Idle) return -EINVAL; @@ -921,7 +914,6 @@ static int vidioc_enum_fmt_vid_cap (struct file *file, void *priv, if(vfd->index>=USBVISION_SUPPORTED_PALETTES-1) { return -EINVAL; } - vfd->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; strcpy(vfd->description,usbvision_v4l2_format[vfd->index].desc); vfd->pixelformat = usbvision_v4l2_format[vfd->index].format; return 0; -- cgit v1.2.3 From d52037715e9e029fa316efb4a5a445c339b170cb Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Sat, 28 Mar 2009 18:25:36 -0700 Subject: zr364xx: Remove code for things already done by video_ioctl2 From: Trent Piepho The ->vidioc_(s|g|try|enum)_fmt_vid_cap() methods are only called on VIDEO_CAPTURE buffers. Thus, there is no need to check or set the buffer's 'type' field since it must already be set to VIDEO_CAPTURE. Checking the buffer type can be removed from zr364xx_vidioc_(s|g|try|enum)_fmt_vid_cap(). The v4l2 core code in v4l2_ioctl will zero out the structure the driver is supposed to fill in for read-only ioctls. For read/write ioctls, all the fields which aren't supplied from userspace will be zeroed out. Zeroing code can be removed from zr364xx_vidioc_querycap(), zr364xx_vidioc_enum_input(), zr364xx_vidioc_enum_fmt_vid_cap(), and zr364xx_vidioc_g_fmt_vid_cap(). Priority: normal Signed-off-by: Trent Piepho CC: Antoine Jacquet --- linux/drivers/media/video/zr364xx.c | 16 ---------------- 1 file changed, 16 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/zr364xx.c b/linux/drivers/media/video/zr364xx.c index 698b7b9ba..2e4d8147b 100644 --- a/linux/drivers/media/video/zr364xx.c +++ b/linux/drivers/media/video/zr364xx.c @@ -427,7 +427,6 @@ static ssize_t zr364xx_read(struct file *file, char __user *buf, size_t cnt, static int zr364xx_vidioc_querycap(struct file *file, void *priv, struct v4l2_capability *cap) { - memset(cap, 0, sizeof(*cap)); strcpy(cap->driver, DRIVER_DESC); cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE; return 0; @@ -438,8 +437,6 @@ static int zr364xx_vidioc_enum_input(struct file *file, void *priv, { if (i->index != 0) return -EINVAL; - memset(i, 0, sizeof(*i)); - i->index = 0; strcpy(i->name, DRIVER_DESC " Camera"); i->type = V4L2_INPUT_TYPE_CAMERA; return 0; @@ -531,11 +528,6 @@ static int zr364xx_vidioc_enum_fmt_vid_cap(struct file *file, { if (f->index > 0) return -EINVAL; - if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - memset(f, 0, sizeof(*f)); - f->index = 0; - f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; f->flags = V4L2_FMT_FLAG_COMPRESSED; strcpy(f->description, "JPEG"); f->pixelformat = V4L2_PIX_FMT_JPEG; @@ -552,8 +544,6 @@ static int zr364xx_vidioc_try_fmt_vid_cap(struct file *file, void *priv, return -ENODEV; cam = video_get_drvdata(vdev); - if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; if (f->fmt.pix.pixelformat != V4L2_PIX_FMT_JPEG) return -EINVAL; if (f->fmt.pix.field != V4L2_FIELD_ANY && @@ -579,10 +569,6 @@ static int zr364xx_vidioc_g_fmt_vid_cap(struct file *file, void *priv, return -ENODEV; cam = video_get_drvdata(vdev); - if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - memset(&f->fmt.pix, 0, sizeof(struct v4l2_pix_format)); - f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; f->fmt.pix.pixelformat = V4L2_PIX_FMT_JPEG; f->fmt.pix.field = V4L2_FIELD_NONE; f->fmt.pix.width = cam->width; @@ -604,8 +590,6 @@ static int zr364xx_vidioc_s_fmt_vid_cap(struct file *file, void *priv, return -ENODEV; cam = video_get_drvdata(vdev); - if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; if (f->fmt.pix.pixelformat != V4L2_PIX_FMT_JPEG) return -EINVAL; if (f->fmt.pix.field != V4L2_FIELD_ANY && -- cgit v1.2.3 From 79e38b2e91236313fe56aa090ed33a0719763e97 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 29 Mar 2009 02:36:18 +0000 Subject: Add AVerMedia A310 USB IDs to CE6230 driver. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: Juan Jesús García de Soria Lucena The CE6230 DVB USB driver works correctly for the AVerMedia A310 USB2.0 DVB-T tuner. Add the required USB ID's and hardware names so that the driver will handle it. Priority: normal Signed-off-by: Juan Jesús García de Soria Lucena Acked-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/dvb-usb/ce6230.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/ce6230.c b/linux/drivers/media/dvb/dvb-usb/ce6230.c index 1682af62f..3ae3bde45 100644 --- a/linux/drivers/media/dvb/dvb-usb/ce6230.c +++ b/linux/drivers/media/dvb/dvb-usb/ce6230.c @@ -253,6 +253,7 @@ static int ce6230_probe(struct usb_interface *intf, static struct usb_device_id ce6230_table[] = { { USB_DEVICE(USB_VID_INTEL, USB_PID_INTEL_CE9500) }, + { USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A310) }, { } /* Terminating entry */ }; MODULE_DEVICE_TABLE(usb, ce6230_table); @@ -287,13 +288,18 @@ static struct dvb_usb_device_properties ce6230_properties = { .i2c_algo = &ce6230_i2c_algo, - .num_device_descs = 1, + .num_device_descs = 2, .devices = { { .name = "Intel CE9500 reference design", .cold_ids = {NULL}, .warm_ids = {&ce6230_table[0], NULL}, }, + { + .name = "AVerMedia A310 USB 2.0 DVB-T tuner", + .cold_ids = {NULL}, + .warm_ids = {&ce6230_table[1], NULL}, + }, } }; 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 dc7ea21cd..ffe2a7335 100644 --- a/linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h +++ b/linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h @@ -167,6 +167,7 @@ #define USB_PID_AVERMEDIA_VOLAR_X 0xa815 #define USB_PID_AVERMEDIA_VOLAR_X_2 0x8150 #define USB_PID_AVERMEDIA_A309 0xa309 +#define USB_PID_AVERMEDIA_A310 0xa310 #define USB_PID_TECHNOTREND_CONNECT_S2400 0x3006 #define USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY 0x005a #define USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY_2 0x0081 -- cgit v1.2.3 From ad5c269e6d4f6c38a8d85b8894a16650e62f77d0 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sun, 29 Mar 2009 11:17:31 +0200 Subject: bttv: move saa6588 config to the helper chip config From: Hans Verkuil saa6588 can also be used by other drivers than just bttv. Move it to a new RDS decoders category and add it as helper chip to bttv. Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/Kconfig | 26 ++++++++++++++------------ linux/drivers/media/video/bt8xx/Kconfig | 1 + 2 files changed, 15 insertions(+), 12 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/Kconfig b/linux/drivers/media/video/Kconfig index 114bf04a6..58abbe374 100644 --- a/linux/drivers/media/video/Kconfig +++ b/linux/drivers/media/video/Kconfig @@ -249,6 +249,20 @@ config VIDEO_VP27SMPX To compile this driver as a module, choose M here: the module will be called vp27smpx. +comment "RDS decoders" + +config VIDEO_SAA6588 + tristate "SAA6588 Radio Chip RDS decoder support" + depends on VIDEO_V4L2 && I2C + + help + Support for this Radio Data System (RDS) decoder. This allows + seeing radio station identification transmitted using this + standard. + + To compile this driver as a module, choose M here: the + module will be called saa6588. + comment "Video decoders" config VIDEO_BT819 @@ -467,18 +481,6 @@ config VIDEO_VIVI source "drivers/media/video/bt8xx/Kconfig" -config VIDEO_SAA6588 - tristate "SAA6588 Radio Chip RDS decoder support on BT848 cards" - depends on I2C && VIDEO_BT848 - - help - Support for Radio Data System (RDS) decoder. This allows seeing - radio station identification transmitted using this standard. - Currently, it works only with bt8x8 chips. - - To compile this driver as a module, choose M here: the - module will be called saa6588. - config VIDEO_PMS tristate "Mediavision Pro Movie Studio Video For Linux" depends on ISA && VIDEO_V4L1 diff --git a/linux/drivers/media/video/bt8xx/Kconfig b/linux/drivers/media/video/bt8xx/Kconfig index 94c9df8b1..3077c4501 100644 --- a/linux/drivers/media/video/bt8xx/Kconfig +++ b/linux/drivers/media/video/bt8xx/Kconfig @@ -10,6 +10,7 @@ config VIDEO_BT848 select VIDEO_MSP3400 if VIDEO_HELPER_CHIPS_AUTO select VIDEO_TVAUDIO if VIDEO_HELPER_CHIPS_AUTO select VIDEO_TDA7432 if VIDEO_HELPER_CHIPS_AUTO + select VIDEO_SAA6588 if VIDEO_HELPER_CHIPS_AUTO ---help--- Support for BT848 based frame grabber/overlay boards. This includes the Miro, Hauppauge and STB boards. Please read the material in -- cgit v1.2.3 From 989c0baab5309fcdfa58455819f9cdd4e2d84070 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sun, 29 Mar 2009 11:26:27 +0200 Subject: saa7134: add RDS support. From: Hans Verkuil The Terratec Cinergy 600 TV MK3 supports the RDS decoder saa6588. Add support to saa7134 for such devices. Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/saa7134/Kconfig | 1 + linux/drivers/media/video/saa7134/saa7134-cards.c | 1 + linux/drivers/media/video/saa7134/saa7134-core.c | 11 +++++++ linux/drivers/media/video/saa7134/saa7134-video.c | 37 +++++++++++++++++++++++ linux/drivers/media/video/saa7134/saa7134.h | 1 + 5 files changed, 51 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/saa7134/Kconfig b/linux/drivers/media/video/saa7134/Kconfig index a2089acb0..0ba68987b 100644 --- a/linux/drivers/media/video/saa7134/Kconfig +++ b/linux/drivers/media/video/saa7134/Kconfig @@ -6,6 +6,7 @@ config VIDEO_SAA7134 select VIDEO_TUNER select VIDEO_TVEEPROM select CRC32 + select VIDEO_SAA6588 if VIDEO_HELPER_CHIPS_AUTO ---help--- This is a video4linux driver for Philips SAA713x based TV cards. diff --git a/linux/drivers/media/video/saa7134/saa7134-cards.c b/linux/drivers/media/video/saa7134/saa7134-cards.c index 50d2868ce..cb94daeda 100644 --- a/linux/drivers/media/video/saa7134/saa7134-cards.c +++ b/linux/drivers/media/video/saa7134/saa7134-cards.c @@ -1704,6 +1704,7 @@ struct saa7134_board saa7134_boards[] = { .radio_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, + .rds_addr = 0x10, .tda9887_conf = TDA9887_PRESENT, .inputs = {{ .name = name_tv, diff --git a/linux/drivers/media/video/saa7134/saa7134-core.c b/linux/drivers/media/video/saa7134/saa7134-core.c index 71142b53e..1bf7c3a1b 100644 --- a/linux/drivers/media/video/saa7134/saa7134-core.c +++ b/linux/drivers/media/video/saa7134/saa7134-core.c @@ -1051,6 +1051,17 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev, sd->grp_id = GRP_EMPRESS; } + if (saa7134_boards[dev->board].rds_addr) { + unsigned short addrs[2] = { 0, I2C_CLIENT_END }; + struct v4l2_subdev *sd; + + addrs[0] = saa7134_boards[dev->board].rds_addr; + sd = v4l2_i2c_new_probed_subdev(&dev->i2c_adap, "saa6588", + "saa6588", addrs); + if (sd) + printk(KERN_INFO "%s: found RDS decoder\n", dev->name); + } + request_submodules(dev); v4l2_prio_init(&dev->prio); diff --git a/linux/drivers/media/video/saa7134/saa7134-video.c b/linux/drivers/media/video/saa7134/saa7134-video.c index d188aae14..8ad0c72d0 100644 --- a/linux/drivers/media/video/saa7134/saa7134-video.c +++ b/linux/drivers/media/video/saa7134/saa7134-video.c @@ -30,6 +30,7 @@ #include "saa7134-reg.h" #include "saa7134.h" #include +#include /* ------------------------------------------------------------------ */ @@ -1462,6 +1463,7 @@ static int video_release(struct file *file) { struct saa7134_fh *fh = file->private_data; struct saa7134_dev *dev = fh->dev; + struct rds_command cmd; unsigned long flags; /* turn off overlay */ @@ -1495,6 +1497,8 @@ static int video_release(struct file *file) saa_andorb(SAA7134_OFMT_DATA_B, 0x1f, 0); saa_call_all(dev, core, s_standby, 0); + if (fh->radio) + saa_call_all(dev, core, ioctl, RDS_CMD_CLOSE, &cmd); /* free stuff */ videobuf_mmap_free(&fh->cap); @@ -1515,6 +1519,37 @@ static int video_mmap(struct file *file, struct vm_area_struct * vma) return videobuf_mmap_mapper(saa7134_queue(fh), vma); } +static ssize_t radio_read(struct file *file, char __user *data, + size_t count, loff_t *ppos) +{ + struct saa7134_fh *fh = file->private_data; + struct saa7134_dev *dev = fh->dev; + struct rds_command cmd; + + cmd.block_count = count/3; + cmd.buffer = data; + cmd.instance = file; + cmd.result = -ENODEV; + + saa_call_all(dev, core, ioctl, RDS_CMD_READ, &cmd); + + return cmd.result; +} + +static unsigned int radio_poll(struct file *file, poll_table *wait) +{ + struct saa7134_fh *fh = file->private_data; + struct saa7134_dev *dev = fh->dev; + struct rds_command cmd; + + cmd.instance = file; + cmd.event_list = wait; + cmd.result = -ENODEV; + saa_call_all(dev, core, ioctl, RDS_CMD_POLL, &cmd); + + return cmd.result; +} + /* ------------------------------------------------------------------ */ static int saa7134_try_get_set_fmt_vbi_cap(struct file *file, void *priv, @@ -2446,8 +2481,10 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = { static const struct v4l2_file_operations radio_fops = { .owner = THIS_MODULE, .open = video_open, + .read = radio_read, .release = video_release, .ioctl = video_ioctl2, + .poll = radio_poll, }; static const struct v4l2_ioctl_ops radio_ioctl_ops = { diff --git a/linux/drivers/media/video/saa7134/saa7134.h b/linux/drivers/media/video/saa7134/saa7134.h index 2e9c7ed3d..85a1dfd19 100644 --- a/linux/drivers/media/video/saa7134/saa7134.h +++ b/linux/drivers/media/video/saa7134/saa7134.h @@ -334,6 +334,7 @@ struct saa7134_board { unsigned char tuner_addr; unsigned char radio_addr; unsigned char empress_addr; + unsigned char rds_addr; unsigned int tda9887_conf; unsigned int tuner_config; -- cgit v1.2.3 From a776331c1eba7665601b6c16c091f98e96885e16 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sun, 29 Mar 2009 11:29:30 +0200 Subject: saa6588: remove legacy code. From: Hans Verkuil saa6588 is now only used through v4l2_subdev, so we can remove the old legacy code. Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/saa6588.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/saa6588.c b/linux/drivers/media/video/saa6588.c index d89d70892..60934e0a9 100644 --- a/linux/drivers/media/video/saa6588.c +++ b/linux/drivers/media/video/saa6588.c @@ -34,9 +34,10 @@ #include #include #include -#include +#include #include "compat.h" +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22) /* Addresses to scan */ static unsigned short normal_i2c[] = { 0x20 >> 1, @@ -45,6 +46,7 @@ static unsigned short normal_i2c[] = { }; I2C_CLIENT_INSMOD; +#endif /* insmod options */ static unsigned int debug; @@ -440,11 +442,6 @@ static int saa6588_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ide return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_SAA6588, 0); } -static int saa6588_command(struct i2c_client *client, unsigned cmd, void *arg) -{ - return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg); -} - /* ----------------------------------------------------------------------- */ static const struct v4l2_subdev_core_ops saa6588_core_ops = { @@ -526,7 +523,6 @@ MODULE_DEVICE_TABLE(i2c, saa6588_id); #endif static struct v4l2_i2c_driver_data v4l2_i2c_data = { .name = "saa6588", - .command = saa6588_command, .probe = saa6588_probe, .remove = saa6588_remove, #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) -- cgit v1.2.3 From 18a4d91ee3e9c2e8eb6d7945a2a817115ee11546 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sun, 29 Mar 2009 11:53:29 +0200 Subject: cx23885: convert to v4l2_subdev. From: Hans Verkuil Convert this driver to v4l2_subdev. Note that currently the only card with analog support in this driver is the HVR-1800. The analog tuner support in this driver is limited to what is needed for this board. When analog support is added for other cards, then the tuner load code will probably have to be expanded to take care of those boards. For example, there is currently no support for either radio tuners or tda9887 demods. I'd like to thank Steven Toth for testing this on his HVR-1800. Priority: normal Signed-off-by: Hans Verkuil Tested-by: Steven Toth --- linux/drivers/media/video/cx23885/cx23885-417.c | 23 ++---- linux/drivers/media/video/cx23885/cx23885-cards.c | 4 +- linux/drivers/media/video/cx23885/cx23885-core.c | 2 +- linux/drivers/media/video/cx23885/cx23885-dvb.c | 2 +- linux/drivers/media/video/cx23885/cx23885-i2c.c | 86 ++--------------------- linux/drivers/media/video/cx23885/cx23885-video.c | 62 +++++++++------- linux/drivers/media/video/cx23885/cx23885.h | 6 +- 7 files changed, 58 insertions(+), 127 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/cx23885/cx23885-417.c b/linux/drivers/media/video/cx23885/cx23885-417.c index adfb79799..aeef889fd 100644 --- a/linux/drivers/media/video/cx23885/cx23885-417.c +++ b/linux/drivers/media/video/cx23885/cx23885-417.c @@ -1194,8 +1194,7 @@ static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *id) * This will likely need to be enabled for non NTSC * formats. */ - cx23885_call_i2c_clients(&dev->i2c_bus[0], VIDIOC_S_STD, id); - cx23885_call_i2c_clients(&dev->i2c_bus[1], VIDIOC_S_STD, id); + call_all(dev, tuner, s_std, id); #endif return 0; } @@ -1259,8 +1258,7 @@ static int vidioc_g_tuner(struct file *file, void *priv, if (0 != t->index) return -EINVAL; strcpy(t->name, "Television"); - cx23885_call_i2c_clients(&dev->i2c_bus[2], VIDIOC_G_TUNER, t); - cx23885_call_i2c_clients(&dev->i2c_bus[1], VIDIOC_G_TUNER, t); + call_all(dev, tuner, g_tuner, t); dprintk(1, "VIDIOC_G_TUNER: tuner type %d\n", t->type); @@ -1277,7 +1275,7 @@ static int vidioc_s_tuner(struct file *file, void *priv, return -EINVAL; /* Update the A/V core */ - cx23885_call_i2c_clients(&dev->i2c_bus[2], VIDIOC_S_TUNER, t); + call_all(dev, tuner, s_tuner, t); return 0; } @@ -1293,8 +1291,7 @@ static int vidioc_g_frequency(struct file *file, void *priv, f->type = V4L2_TUNER_ANALOG_TV; f->frequency = dev->freq; - /* Assumption that tuner is always on bus 1 */ - cx23885_call_i2c_clients(&dev->i2c_bus[1], VIDIOC_G_FREQUENCY, f); + call_all(dev, tuner, g_frequency, f); return 0; } @@ -1321,8 +1318,7 @@ static int vidioc_s_frequency(struct file *file, void *priv, return -EINVAL; dev->freq = f->frequency; - /* Assumption that tuner is always on bus 1 */ - cx23885_call_i2c_clients(&dev->i2c_bus[1], VIDIOC_S_FREQUENCY, f); + call_all(dev, tuner, s_frequency, f); cx23885_initialize_codec(dev); @@ -1336,7 +1332,7 @@ static int vidioc_s_ctrl(struct file *file, void *priv, struct cx23885_dev *dev = fh->dev; /* Update the A/V core */ - cx23885_call_i2c_clients(&dev->i2c_bus[2], VIDIOC_S_CTRL, ctl); + call_all(dev, core, s_ctrl, ctl); return 0; } @@ -1532,12 +1528,7 @@ static int vidioc_log_status(struct file *file, void *priv) printk(KERN_INFO "%s/2: ============ START LOG STATUS ============\n", dev->name); - cx23885_call_i2c_clients(&dev->i2c_bus[0], VIDIOC_LOG_STATUS, - NULL); - cx23885_call_i2c_clients(&dev->i2c_bus[1], VIDIOC_LOG_STATUS, - NULL); - cx23885_call_i2c_clients(&dev->i2c_bus[2], VIDIOC_LOG_STATUS, - NULL); + call_all(dev, core, log_status); cx2341x_log_status(&dev->mpeg_params, name); printk(KERN_INFO "%s/2: ============= END LOG STATUS =============\n", diff --git a/linux/drivers/media/video/cx23885/cx23885-cards.c b/linux/drivers/media/video/cx23885/cx23885-cards.c index e6db78f8b..493551ec0 100644 --- a/linux/drivers/media/video/cx23885/cx23885-cards.c +++ b/linux/drivers/media/video/cx23885/cx23885-cards.c @@ -740,7 +740,9 @@ void cx23885_card_setup(struct cx23885_dev *dev) case CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H: case CX23885_BOARD_COMPRO_VIDEOMATE_E650F: case CX23885_BOARD_NETUP_DUAL_DVBS2_CI: - request_module("cx25840"); + dev->sd_cx25840 = v4l2_i2c_new_subdev(&dev->i2c_bus[2].i2c_adap, + "cx25840", "cx25840", 0x88 >> 1); + v4l2_subdev_call(dev->sd_cx25840, core, init, 0); break; } diff --git a/linux/drivers/media/video/cx23885/cx23885-core.c b/linux/drivers/media/video/cx23885/cx23885-core.c index eea0bc650..2bffcbc48 100644 --- a/linux/drivers/media/video/cx23885/cx23885-core.c +++ b/linux/drivers/media/video/cx23885/cx23885-core.c @@ -876,7 +876,7 @@ static int cx23885_dev_setup(struct cx23885_dev *dev) cx23885_i2c_register(&dev->i2c_bus[1]); cx23885_i2c_register(&dev->i2c_bus[2]); cx23885_card_setup(dev); - cx23885_call_i2c_clients(&dev->i2c_bus[0], TUNER_SET_STANDBY, NULL); + call_all(dev, core, s_standby, 0); cx23885_ir_init(dev); if (cx23885_boards[dev->board].porta == CX23885_ANALOG_VIDEO) { diff --git a/linux/drivers/media/video/cx23885/cx23885-dvb.c b/linux/drivers/media/video/cx23885/cx23885-dvb.c index 364543987..dfb16b91e 100644 --- a/linux/drivers/media/video/cx23885/cx23885-dvb.c +++ b/linux/drivers/media/video/cx23885/cx23885-dvb.c @@ -674,7 +674,7 @@ static int dvb_register(struct cx23885_tsport *port) fe0->dvb.frontend->callback = cx23885_tuner_callback; /* Put the analog decoder in standby to keep it quiet */ - cx23885_call_i2c_clients(i2c_bus, TUNER_SET_STANDBY, NULL); + call_all(dev, core, s_standby, 0); if (fe0->dvb.frontend->ops.analog_ops.standby) fe0->dvb.frontend->ops.analog_ops.standby(fe0->dvb.frontend); diff --git a/linux/drivers/media/video/cx23885/cx23885-i2c.c b/linux/drivers/media/video/cx23885/cx23885-i2c.c index 86493da33..3b0b9d3e3 100644 --- a/linux/drivers/media/video/cx23885/cx23885-i2c.c +++ b/linux/drivers/media/video/cx23885/cx23885-i2c.c @@ -269,83 +269,6 @@ static int i2c_xfer(struct i2c_adapter *i2c_adap, return retval; } -static int attach_inform(struct i2c_client *client) -{ - struct v4l2_device *v4l2_dev = i2c_get_adapdata(client->adapter); - struct cx23885_dev *dev = to_cx23885(v4l2_dev); - struct tuner_setup tun_setup; - - dprintk(1, "%s i2c attach [addr=0x%x,client=%s]\n", - client->driver->driver.name, client->addr, client->name); - - if (!client->driver->command) - return 0; -#if 0 - if (dev->radio_type != UNSET) { - - dprintk(1, "%s (radio) i2c attach [addr=0x%x,client=%s]\n", - client->driver->driver.name, client->addr, - client->name); - - if ((dev->radio_addr == ADDR_UNSET) || - (dev->radio_addr == client->addr)) { - tun_setup.mode_mask = T_RADIO; - tun_setup.type = dev->radio_type; - tun_setup.addr = dev->radio_addr; - - client->driver->command(client, TUNER_SET_TYPE_ADDR, - &tun_setup); - } - } -#endif - - if (dev->tuner_type != UNSET) { - - dprintk(1, "%s (tuner) i2c attach [addr=0x%x,client=%s]\n", - client->driver->driver.name, client->addr, - client->name); - - if ((dev->tuner_addr == ADDR_UNSET) || - (dev->tuner_addr == client->addr)) { - - dprintk(1, "%s (tuner || addr UNSET)\n", - client->driver->driver.name); - - dprintk(1, "%s i2c attach [addr=0x%x,client=%s]\n", - client->driver->driver.name, - client->addr, client->name); - - tun_setup.mode_mask = T_ANALOG_TV; - tun_setup.type = dev->tuner_type; - tun_setup.addr = dev->tuner_addr; - - client->driver->command(client, TUNER_SET_TYPE_ADDR, - &tun_setup); - } - } - - return 0; -} - -static int detach_inform(struct i2c_client *client) -{ - struct v4l2_device *v4l2_dev = i2c_get_adapdata(client->adapter); - struct cx23885_dev *dev = to_cx23885(v4l2_dev); - - dprintk(1, "i2c detach [client=%s]\n", client->name); - - return 0; -} - -void cx23885_call_i2c_clients(struct cx23885_i2c *bus, - unsigned int cmd, void *arg) -{ - if (bus->i2c_rc != 0) - return; - - i2c_clients_command(&bus->i2c_adap, cmd, arg); -} - static u32 cx23885_functionality(struct i2c_adapter *adap) { return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_I2C; @@ -366,9 +289,9 @@ static struct i2c_adapter cx23885_i2c_adap_template = { .owner = THIS_MODULE, .id = I2C_HW_B_CX23885, .algo = &cx23885_i2c_algo_template, +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22) .class = I2C_CLASS_TV_ANALOG, - .client_register = attach_inform, - .client_unregister = detach_inform, +#endif }; static struct i2c_client cx23885_i2c_client_template = { @@ -432,8 +355,11 @@ int cx23885_i2c_register(struct cx23885_i2c *bus) if (0 == bus->i2c_rc) { dprintk(1, "%s: i2c bus %d registered\n", dev->name, bus->nr); - if (i2c_scan) + if (i2c_scan) { + printk(KERN_INFO "%s: scan bus %d:\n", + dev->name, bus->nr); do_i2c_scan(dev->name, &bus->i2c_client); + } } else printk(KERN_WARNING "%s: i2c bus %d register FAILED\n", dev->name, bus->nr); diff --git a/linux/drivers/media/video/cx23885/cx23885-video.c b/linux/drivers/media/video/cx23885/cx23885-video.c index dd6e1f70e..a45bd3b77 100644 --- a/linux/drivers/media/video/cx23885/cx23885-video.c +++ b/linux/drivers/media/video/cx23885/cx23885-video.c @@ -334,11 +334,7 @@ static int cx23885_set_tvnorm(struct cx23885_dev *dev, v4l2_std_id norm) dev->tvnorm = norm; - /* Tell the analog tuner/demods */ - cx23885_call_i2c_clients(&dev->i2c_bus[1], VIDIOC_S_STD, &norm); - - /* Tell the internal A/V decoder */ - cx23885_call_i2c_clients(&dev->i2c_bus[2], VIDIOC_S_STD, &norm); + call_all(dev, tuner, s_std, norm); return 0; } @@ -445,12 +441,10 @@ static int cx23885_video_mux(struct cx23885_dev *dev, unsigned int input) route.input = INPUT(input)->vmux; /* Tell the internal A/V decoder */ - cx23885_call_i2c_clients(&dev->i2c_bus[2], - VIDIOC_INT_S_VIDEO_ROUTING, &route); + v4l2_subdev_call(dev->sd_cx25840, video, s_routing, &route); #if 0 route.input = 0; /* Let the AVCore default */ - cx23885_call_i2c_clients(&dev->i2c_bus[2], - VIDIOC_INT_S_AUDIO_ROUTING, &route); + v4l2_subdev_call(dev->sd_cx25840, audio, s_routing, &route); #endif return 0; @@ -840,8 +834,7 @@ static int video_open(struct file *file) dev->tvaudio = WW_FM; cx23885_set_tvaudio(dev); cx23885_set_stereo(dev, V4L2_TUNER_MODE_STEREO, 1); - cx23885_call_i2c_clients(&dev->i2c_bus[1], - AUDC_SET_RADIO, NULL); + call_all(dev, tuner, s_radio); } #endif unlock_kernel(); @@ -944,7 +937,7 @@ static int video_release(struct file *file) * tuner video. Closing this will result in no video to the encoder. */ #if 0 - cx23885_call_i2c_clients(&dev->i2c_bus[1], TUNER_SET_STANDBY, NULL); + call_all(dev, tuner, s_standby); #endif return 0; @@ -964,7 +957,7 @@ static int cx23885_get_control(struct cx23885_dev *dev, struct v4l2_control *ctl) { dprintk(1, "%s() calling cx25840(VIDIOC_G_CTRL)\n", __func__); - cx23885_call_i2c_clients(&dev->i2c_bus[2], VIDIOC_G_CTRL, ctl); + call_all(dev, core, g_ctrl, ctl); return 0; } @@ -974,7 +967,7 @@ static int cx23885_set_control(struct cx23885_dev *dev, dprintk(1, "%s() calling cx25840(VIDIOC_S_CTRL)" " (disabled - no action)\n", __func__); #if 0 - cx23885_call_i2c_clients(&dev->i2c_bus[2], VIDIOC_S_CTRL, ctl); + call_all(dev, core, s_ctrl, ctl); #endif return 0; } @@ -1081,7 +1074,7 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, fh->vidq.field = f->fmt.pix.field; dprintk(2, "%s() width=%d height=%d field=%d\n", __func__, fh->width, fh->height, fh->vidq.field); - cx23885_call_i2c_clients(&dev->i2c_bus[2], VIDIOC_S_FMT, f); + call_all(dev, video, s_fmt, f); return 0; } @@ -1370,7 +1363,7 @@ static int vidioc_g_frequency(struct file *file, void *priv, f->type = fh->radio ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV; f->frequency = dev->freq; - cx23885_call_i2c_clients(&dev->i2c_bus[1], VIDIOC_G_FREQUENCY, f); + call_all(dev, tuner, g_frequency, f); return 0; } @@ -1385,7 +1378,7 @@ static int cx23885_set_freq(struct cx23885_dev *dev, struct v4l2_frequency *f) mutex_lock(&dev->lock); dev->freq = f->frequency; - cx23885_call_i2c_clients(&dev->i2c_bus[1], VIDIOC_S_FREQUENCY, f); + call_all(dev, tuner, s_frequency, f); /* When changing channels it is required to reset TVAUDIO */ msleep(10); @@ -1419,7 +1412,7 @@ static int vidioc_g_register(struct file *file, void *fh, if (!v4l2_chip_match_host(®->match)) return -EINVAL; - cx23885_call_i2c_clients(&dev->i2c_bus[2], VIDIOC_DBG_G_REGISTER, reg); + call_all(dev, core, g_register, reg); return 0; } @@ -1432,7 +1425,7 @@ static int vidioc_s_register(struct file *file, void *fh, if (!v4l2_chip_match_host(®->match)) return -EINVAL; - cx23885_call_i2c_clients(&dev->i2c_bus[2], VIDIOC_DBG_S_REGISTER, reg); + call_all(dev, core, s_register, reg); return 0; } @@ -1468,7 +1461,7 @@ static int radio_g_tuner(struct file *file, void *priv, strcpy(t->name, "Radio"); t->type = V4L2_TUNER_RADIO; - cx23885_call_i2c_clients(&dev->i2c_bus[1], VIDIOC_G_TUNER, t); + call_all(dev, tuner, g_tuner, t); return 0; } @@ -1503,7 +1496,7 @@ static int radio_s_tuner(struct file *file, void *priv, if (0 != t->index) return -EINVAL; - cx23885_call_i2c_clients(&dev->i2c_bus[1], VIDIOC_S_TUNER, t); + call_all(dev, tuner, s_tuner, t); return 0; } @@ -1782,13 +1775,30 @@ int cx23885_video_register(struct cx23885_dev *dev) #endif cx_set(PCI_INT_MSK, 1); -#if 0 - /* FIXME: These should be correctly defined */ - /* load and configure helper modules */ - if (TUNER_ABSENT != core->tuner_type) - request_module("tuner"); + if (TUNER_ABSENT != dev->tuner_type) { + struct v4l2_subdev *sd = NULL; + + if (dev->tuner_addr) + sd = v4l2_i2c_new_subdev(&dev->i2c_bus[1].i2c_adap, + "tuner", "tuner", dev->tuner_addr); + else + sd = v4l2_i2c_new_probed_subdev(&dev->i2c_bus[1].i2c_adap, + "tuner", "tuner", v4l2_i2c_tuner_addrs(ADDRS_TV)); + if (sd) { + struct tuner_setup tun_setup; + tun_setup.mode_mask = T_ANALOG_TV; + tun_setup.type = dev->tuner_type; + tun_setup.addr = v4l2_i2c_subdev_addr(sd); + + v4l2_subdev_call(sd, tuner, s_type_addr, &tun_setup); + } + } + +#if 0 if (cx23885_boards[dev->board].audio_chip == V4L2_IDENT_WM8775) + /* Must use v4l2_i2c_new_subdev instead of request_module + once this is implemented for real. */ request_module("wm8775"); #endif diff --git a/linux/drivers/media/video/cx23885/cx23885.h b/linux/drivers/media/video/cx23885/cx23885.h index 80031ddfa..c090a7df9 100644 --- a/linux/drivers/media/video/cx23885/cx23885.h +++ b/linux/drivers/media/video/cx23885/cx23885.h @@ -324,6 +324,7 @@ struct cx23885_dev { unsigned int radio_type; unsigned char radio_addr; unsigned int has_radio; + struct v4l2_subdev *sd_cx25840; /* V4l */ u32 freq; @@ -349,6 +350,9 @@ static inline struct cx23885_dev *to_cx23885(struct v4l2_device *v4l2_dev) return container_of(v4l2_dev, struct cx23885_dev, v4l2_dev); } +#define call_all(dev, o, f, args...) \ + v4l2_device_call_all(&dev->v4l2_dev, 0, o, f, ##args) + extern struct list_head cx23885_devlist; #define SRAM_CH01 0 /* Video A */ @@ -465,8 +469,6 @@ extern struct videobuf_queue_ops cx23885_vbi_qops; /* cx23885-i2c.c */ extern int cx23885_i2c_register(struct cx23885_i2c *bus); extern int cx23885_i2c_unregister(struct cx23885_i2c *bus); -extern void cx23885_call_i2c_clients(struct cx23885_i2c *bus, unsigned int cmd, - void *arg); extern void cx23885_av_clk(struct cx23885_dev *dev, int enable); /* ----------------------------------------------------------- */ -- cgit v1.2.3 From ed2a80c674f393482227987d6aeed8c60328cca4 Mon Sep 17 00:00:00 2001 From: Patrick Boettcher Date: Sun, 29 Mar 2009 12:46:58 +0200 Subject: Code cleanup (passes checkpatch now) of the b2c2-flexcop-drivers 1/2 From: Uwe Bugla This patch cleans up the source code of the b2c2 flexcop-driver. It is the first of a total of two. The code is now passing the checkpatch-script. Priority: normal Signed-off-by: Uwe Bugla Signed-off-by: Patrick Boettcher --- linux/drivers/media/dvb/b2c2/Makefile | 1 - linux/drivers/media/dvb/b2c2/flexcop-common.h | 64 ++++---- linux/drivers/media/dvb/b2c2/flexcop-dma.c | 27 ++-- linux/drivers/media/dvb/b2c2/flexcop-eeprom.c | 47 +++--- linux/drivers/media/dvb/b2c2/flexcop-fe-tuner.c | 6 +- linux/drivers/media/dvb/b2c2/flexcop-hw-filter.c | 171 ++++++++++++--------- linux/drivers/media/dvb/b2c2/flexcop-i2c.c | 49 +++--- linux/drivers/media/dvb/b2c2/flexcop-misc.c | 68 ++++---- linux/drivers/media/dvb/b2c2/flexcop-reg.h | 21 ++- linux/drivers/media/dvb/b2c2/flexcop-sram.c | 112 +++++--------- linux/drivers/media/dvb/b2c2/flexcop-usb.h | 62 ++++---- linux/drivers/media/dvb/b2c2/flexcop.c | 85 +++++----- linux/drivers/media/dvb/b2c2/flexcop.h | 20 ++- .../drivers/media/dvb/b2c2/flexcop_ibi_value_be.h | 7 +- .../drivers/media/dvb/b2c2/flexcop_ibi_value_le.h | 7 +- 15 files changed, 353 insertions(+), 394 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/b2c2/Makefile b/linux/drivers/media/dvb/b2c2/Makefile index d9db066f9..b97cf7208 100644 --- a/linux/drivers/media/dvb/b2c2/Makefile +++ b/linux/drivers/media/dvb/b2c2/Makefile @@ -2,7 +2,6 @@ b2c2-flexcop-objs = flexcop.o flexcop-fe-tuner.o flexcop-i2c.o \ flexcop-sram.o flexcop-eeprom.o flexcop-misc.o flexcop-hw-filter.o obj-$(CONFIG_DVB_B2C2_FLEXCOP) += b2c2-flexcop.o - ifneq ($(CONFIG_DVB_B2C2_FLEXCOP_PCI),) b2c2-flexcop-objs += flexcop-dma.o endif diff --git a/linux/drivers/media/dvb/b2c2/flexcop-common.h b/linux/drivers/media/dvb/b2c2/flexcop-common.h index 166f0fb09..cee2956cb 100644 --- a/linux/drivers/media/dvb/b2c2/flexcop-common.h +++ b/linux/drivers/media/dvb/b2c2/flexcop-common.h @@ -29,11 +29,14 @@ /* Steal from usb.h */ #undef err -#define err(format, arg...) printk(KERN_ERR FC_LOG_PREFIX ": " format "\n" , ## arg) +#define err(format, arg...) \ + printk(KERN_ERR FC_LOG_PREFIX ": " format "\n" , ## arg) #undef info -#define info(format, arg...) printk(KERN_INFO FC_LOG_PREFIX ": " format "\n" , ## arg) +#define info(format, arg...) \ + printk(KERN_INFO FC_LOG_PREFIX ": " format "\n" , ## arg) #undef warn -#define warn(format, arg...) printk(KERN_WARNING FC_LOG_PREFIX ": " format "\n" , ## arg) +#define warn(format, arg...) \ + printk(KERN_WARNING FC_LOG_PREFIX ": " format "\n" , ## arg) struct flexcop_dma { struct pci_dev *pdev; @@ -92,16 +95,14 @@ struct flexcop_device { int fullts_streaming_state; /* bus specific callbacks */ - flexcop_ibi_value (*read_ibi_reg) (struct flexcop_device *, flexcop_ibi_register); - int (*write_ibi_reg) (struct flexcop_device *, flexcop_ibi_register, flexcop_ibi_value); - - - int (*i2c_request) (struct flexcop_i2c_adapter*, + flexcop_ibi_value(*read_ibi_reg) (struct flexcop_device *, + flexcop_ibi_register); + int (*write_ibi_reg) (struct flexcop_device *, + flexcop_ibi_register, flexcop_ibi_value); + int (*i2c_request) (struct flexcop_i2c_adapter *, flexcop_access_op_t, u8 chipaddr, u8 addr, u8 *buf, u16 len); - int (*stream_control) (struct flexcop_device*, int); - + int (*stream_control) (struct flexcop_device *, int); int (*get_mac_addr) (struct flexcop_device *fc, int extended); - void *bus_specific; }; @@ -112,22 +113,28 @@ void flexcop_pass_dmx_data(struct flexcop_device *fc, u8 *buf, u32 len); void flexcop_pass_dmx_packets(struct flexcop_device *fc, u8 *buf, u32 no); struct flexcop_device *flexcop_device_kmalloc(size_t bus_specific_len); -void flexcop_device_kfree(struct flexcop_device*); +void flexcop_device_kfree(struct flexcop_device *); -int flexcop_device_initialize(struct flexcop_device*); +int flexcop_device_initialize(struct flexcop_device *); void flexcop_device_exit(struct flexcop_device *fc); - void flexcop_reset_block_300(struct flexcop_device *fc); /* from flexcop-dma.c */ -int flexcop_dma_allocate(struct pci_dev *pdev, struct flexcop_dma *dma, u32 size); +int flexcop_dma_allocate(struct pci_dev *pdev, + struct flexcop_dma *dma, u32 size); void flexcop_dma_free(struct flexcop_dma *dma); -int flexcop_dma_control_timer_irq(struct flexcop_device *fc, flexcop_dma_index_t no, int onoff); -int flexcop_dma_control_size_irq(struct flexcop_device *fc, flexcop_dma_index_t no, int onoff); -int flexcop_dma_config(struct flexcop_device *fc, struct flexcop_dma *dma, flexcop_dma_index_t dma_idx); -int flexcop_dma_xfer_control(struct flexcop_device *fc, flexcop_dma_index_t dma_idx, flexcop_dma_addr_index_t index, int onoff); -int flexcop_dma_config_timer(struct flexcop_device *fc, flexcop_dma_index_t dma_idx, u8 cycles); +int flexcop_dma_control_timer_irq(struct flexcop_device *fc, + flexcop_dma_index_t no, int onoff); +int flexcop_dma_control_size_irq(struct flexcop_device *fc, + flexcop_dma_index_t no, int onoff); +int flexcop_dma_config(struct flexcop_device *fc, struct flexcop_dma *dma, + flexcop_dma_index_t dma_idx); +int flexcop_dma_xfer_control(struct flexcop_device *fc, + flexcop_dma_index_t dma_idx, flexcop_dma_addr_index_t index, + int onoff); +int flexcop_dma_config_timer(struct flexcop_device *fc, + flexcop_dma_index_t dma_idx, u8 cycles); /* from flexcop-eeprom.c */ /* the PCI part uses this call to get the MAC address, the USB part has its own */ @@ -142,13 +149,15 @@ int flexcop_i2c_request(struct flexcop_i2c_adapter*, flexcop_access_op_t, u8 chipaddr, u8 addr, u8 *buf, u16 len); /* from flexcop-sram.c */ -int flexcop_sram_set_dest(struct flexcop_device *fc, flexcop_sram_dest_t dest, flexcop_sram_dest_target_t target); +int flexcop_sram_set_dest(struct flexcop_device *fc, flexcop_sram_dest_t dest, + flexcop_sram_dest_target_t target); void flexcop_wan_set_speed(struct flexcop_device *fc, flexcop_wan_speed_t s); -void flexcop_sram_ctrl(struct flexcop_device *fc, int usb_wan, int sramdma, int maximumfill); +void flexcop_sram_ctrl(struct flexcop_device *fc, + int usb_wan, int sramdma, int maximumfill); /* global prototypes for the flexcop-chip */ /* from flexcop-fe-tuner.c */ -int flexcop_frontend_init(struct flexcop_device *card); +int flexcop_frontend_init(struct flexcop_device *fc); void flexcop_frontend_exit(struct flexcop_device *fc); /* from flexcop-i2c.c */ @@ -160,11 +169,14 @@ int flexcop_sram_init(struct flexcop_device *fc); /* from flexcop-misc.c */ void flexcop_determine_revision(struct flexcop_device *fc); -void flexcop_device_name(struct flexcop_device *fc,const char *prefix,const char *suffix); -void flexcop_dump_reg(struct flexcop_device *fc, flexcop_ibi_register reg, int num); +void flexcop_device_name(struct flexcop_device *fc, + const char *prefix, const char *suffix); +void flexcop_dump_reg(struct flexcop_device *fc, + flexcop_ibi_register reg, int num); /* from flexcop-hw-filter.c */ -int flexcop_pid_feed_control(struct flexcop_device *fc, struct dvb_demux_feed *dvbdmxfeed, int onoff); +int flexcop_pid_feed_control(struct flexcop_device *fc, + struct dvb_demux_feed *dvbdmxfeed, int onoff); void flexcop_hw_filter_init(struct flexcop_device *fc); void flexcop_smc_ctrl(struct flexcop_device *fc, int onoff); diff --git a/linux/drivers/media/dvb/b2c2/flexcop-dma.c b/linux/drivers/media/dvb/b2c2/flexcop-dma.c index 02a0f07a1..2c0eab398 100644 --- a/linux/drivers/media/dvb/b2c2/flexcop-dma.c +++ b/linux/drivers/media/dvb/b2c2/flexcop-dma.c @@ -1,13 +1,12 @@ /* - * This file is part of linux driver the digital TV devices equipped with B2C2 FlexcopII(b)/III - * - * flexcop-dma.c - methods for configuring and controlling the DMA of the FlexCop. - * - * see flexcop.c for copyright information. + * Linux driver for digital TV devices equipped with B2C2 FlexcopII(b)/III + * flexcop-dma.c - configuring and controlling the DMA of the FlexCop + * see flexcop.c for copyright information */ #include "flexcop.h" -int flexcop_dma_allocate(struct pci_dev *pdev, struct flexcop_dma *dma, u32 size) +int flexcop_dma_allocate(struct pci_dev *pdev, + struct flexcop_dma *dma, u32 size) { u8 *tcpu; dma_addr_t tdma = 0; @@ -32,7 +31,8 @@ EXPORT_SYMBOL(flexcop_dma_allocate); void flexcop_dma_free(struct flexcop_dma *dma) { - pci_free_consistent(dma->pdev, dma->size*2,dma->cpu_addr0, dma->dma_addr0); + pci_free_consistent(dma->pdev, dma->size*2, + dma->cpu_addr0, dma->dma_addr0); memset(dma,0,sizeof(struct flexcop_dma)); } EXPORT_SYMBOL(flexcop_dma_free); @@ -44,8 +44,8 @@ int flexcop_dma_config(struct flexcop_device *fc, flexcop_ibi_value v0x0,v0x4,v0xc; v0x0.raw = v0x4.raw = v0xc.raw = 0; - v0x0.dma_0x0.dma_address0 = dma->dma_addr0 >> 2; - v0xc.dma_0xc.dma_address1 = dma->dma_addr1 >> 2; + v0x0.dma_0x0.dma_address0 = dma->dma_addr0 >> 2; + v0xc.dma_0xc.dma_address1 = dma->dma_addr1 >> 2; v0x4.dma_0x4_write.dma_addr_size = dma->size / 4; if ((dma_idx & FC_DMA_1) == dma_idx) { @@ -57,7 +57,8 @@ int flexcop_dma_config(struct flexcop_device *fc, fc->write_ibi_reg(fc,dma2_014,v0x4); fc->write_ibi_reg(fc,dma2_01c,v0xc); } else { - err("either DMA1 or DMA2 can be configured at the within one flexcop_dma_config call."); + err("either DMA1 or DMA2 can be configured within one " + "flexcop_dma_config call."); return -EINVAL; } @@ -81,7 +82,8 @@ int flexcop_dma_xfer_control(struct flexcop_device *fc, r0x0 = dma2_010; r0xc = dma2_01c; } else { - err("either transfer DMA1 or DMA2 can be started within one flexcop_dma_xfer_control call."); + err("either transfer DMA1 or DMA2 can be started within one " + "flexcop_dma_xfer_control call."); return -EINVAL; } @@ -154,8 +156,7 @@ EXPORT_SYMBOL(flexcop_dma_control_timer_irq); /* 1 cycles = 1.97 msec */ int flexcop_dma_config_timer(struct flexcop_device *fc, - flexcop_dma_index_t dma_idx, - u8 cycles) + flexcop_dma_index_t dma_idx, u8 cycles) { flexcop_ibi_register r = (dma_idx & FC_DMA_1) ? dma1_004 : dma2_014; flexcop_ibi_value v = fc->read_ibi_reg(fc,r); diff --git a/linux/drivers/media/dvb/b2c2/flexcop-eeprom.c b/linux/drivers/media/dvb/b2c2/flexcop-eeprom.c index 5d563fbc7..4f42efa26 100644 --- a/linux/drivers/media/dvb/b2c2/flexcop-eeprom.c +++ b/linux/drivers/media/dvb/b2c2/flexcop-eeprom.c @@ -1,9 +1,7 @@ /* - * This file is part of linux driver the digital TV devices equipped with B2C2 FlexcopII(b)/III - * - * flexcop-eeprom.c - eeprom access methods (currently only MAC address reading is used) - * - * see flexcop.c for copyright information. + * Linux driver for digital TV devices equipped with B2C2 FlexcopII(b)/III + * flexcop-eeprom.c - eeprom access methods (currently only MAC address reading) + * see flexcop.c for copyright information */ #include "flexcop.h" @@ -14,17 +12,17 @@ static int eeprom_write(struct adapter *adapter, u16 addr, u8 *buf, u16 len) return flex_i2c_write(adapter, 0x20000000, 0x50, addr, buf, len); } -static int eeprom_lrc_write(struct adapter *adapter, u32 addr, u32 len, u8 *wbuf, u8 *rbuf, int retries) +static int eeprom_lrc_write(struct adapter *adapter, u32 addr, + u32 len, u8 *wbuf, u8 *rbuf, int retries) { - int i; +int i; - for (i = 0; i < retries; i++) { - if (eeprom_write(adapter, addr, wbuf, len) == len) { - if (eeprom_lrc_read(adapter, addr, len, rbuf, retries) == 1) - return 1; +for (i = 0; i < retries; i++) { + if (eeprom_write(adapter, addr, wbuf, len) == len) { + if (eeprom_lrc_read(adapter, addr, len, rbuf, retries) == 1) + return 1; } } - return 0; } @@ -39,12 +37,10 @@ static int eeprom_writeKey(struct adapter *adapter, u8 *key, u32 len) return 0; memcpy(wbuf, key, len); - wbuf[16] = 0; wbuf[17] = 0; wbuf[18] = 0; wbuf[19] = calc_lrc(wbuf, 19); - return eeprom_lrc_write(adapter, 0x3e4, 20, wbuf, rbuf, 4); } @@ -59,7 +55,6 @@ static int eeprom_readKey(struct adapter *adapter, u8 *key, u32 len) return 0; memcpy(key, buf, len); - return 1; } @@ -74,9 +69,7 @@ static char eeprom_set_mac_addr(struct adapter *adapter, char type, u8 *mac) tmp[3] = mac[5]; tmp[4] = mac[6]; tmp[5] = mac[7]; - } else { - tmp[0] = mac[0]; tmp[1] = mac[1]; tmp[2] = mac[2]; @@ -90,11 +83,11 @@ static char eeprom_set_mac_addr(struct adapter *adapter, char type, u8 *mac) if (eeprom_write(adapter, 0x3f8, tmp, 8) == 8) return 1; - return 0; } -static int flexcop_eeprom_read(struct flexcop_device *fc, u16 addr, u8 *buf, u16 len) +static int flexcop_eeprom_read(struct flexcop_device *fc, + u16 addr, u8 *buf, u16 len) { return fc->i2c_request(fc,FC_READ,FC_I2C_PORT_EEPROM,0x50,addr,buf,len); } @@ -110,7 +103,8 @@ static u8 calc_lrc(u8 *buf, int len) return sum; } -static int flexcop_eeprom_request(struct flexcop_device *fc, flexcop_access_op_t op, u16 addr, u8 *buf, u16 len, int retries) +static int flexcop_eeprom_request(struct flexcop_device *fc, + flexcop_access_op_t op, u16 addr, u8 *buf, u16 len, int retries) { int i,ret = 0; u8 chipaddr = 0x50 | ((addr >> 8) & 3); @@ -123,7 +117,8 @@ static int flexcop_eeprom_request(struct flexcop_device *fc, flexcop_access_op_t return ret; } -static int flexcop_eeprom_lrc_read(struct flexcop_device *fc, u16 addr, u8 *buf, u16 len, int retries) +static int flexcop_eeprom_lrc_read(struct flexcop_device *fc, u16 addr, + u8 *buf, u16 len, int retries) { int ret = flexcop_eeprom_request(fc, FC_READ, addr, buf, len, retries); if (ret == 0) @@ -133,8 +128,7 @@ static int flexcop_eeprom_lrc_read(struct flexcop_device *fc, u16 addr, u8 *buf, } /* JJ's comment about extended == 1: it is not presently used anywhere but was - * added to the low-level functions for possible support of EUI64 - */ + * added to the low-level functions for possible support of EUI64 */ int flexcop_eeprom_check_mac_addr(struct flexcop_device *fc, int extended) { u8 buf[8]; @@ -142,12 +136,9 @@ int flexcop_eeprom_check_mac_addr(struct flexcop_device *fc, int extended) if ((ret = flexcop_eeprom_lrc_read(fc,0x3f8,buf,8,4)) == 0) { if (extended != 0) { - err("TODO: extended (EUI64) MAC addresses aren't completely supported yet"); + err("TODO: extended (EUI64) MAC addresses aren't " + "completely supported yet"); ret = -EINVAL; -/* memcpy(fc->dvb_adapter.proposed_mac,buf,3); - mac[3] = 0xfe; - mac[4] = 0xff; - memcpy(&fc->dvb_adapter.proposed_mac[3],&buf[5],3); */ } else memcpy(fc->dvb_adapter.proposed_mac,buf,6); } diff --git a/linux/drivers/media/dvb/b2c2/flexcop-fe-tuner.c b/linux/drivers/media/dvb/b2c2/flexcop-fe-tuner.c index 5cded3708..f7afab594 100644 --- a/linux/drivers/media/dvb/b2c2/flexcop-fe-tuner.c +++ b/linux/drivers/media/dvb/b2c2/flexcop-fe-tuner.c @@ -592,14 +592,14 @@ int flexcop_frontend_init(struct flexcop_device *fc) fc->fe_sleep = ops->sleep; ops->sleep = flexcop_sleep; - fc->dev_type = FC_SKY; + 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_DVB; + fc->dev_type = FC_AIR_DVBT; fc->fe->ops.tuner_ops.calc_regs = samsung_tdtc9251dh0_calc_regs; goto fe_found; } @@ -653,7 +653,7 @@ int flexcop_frontend_init(struct flexcop_device *fc) fc->fe_sleep = ops->sleep; ops->sleep = flexcop_sleep; - fc->dev_type = FC_SKY_OLD; + fc->dev_type = FC_SKY_REV23; goto fe_found; } diff --git a/linux/drivers/media/dvb/b2c2/flexcop-hw-filter.c b/linux/drivers/media/dvb/b2c2/flexcop-hw-filter.c index 451974ba3..77e45475f 100644 --- a/linux/drivers/media/dvb/b2c2/flexcop-hw-filter.c +++ b/linux/drivers/media/dvb/b2c2/flexcop-hw-filter.c @@ -1,33 +1,30 @@ /* - * This file is part of linux driver the digital TV devices equipped with B2C2 FlexcopII(b)/III - * - * flexcop-hw-filter.c - pid and mac address filtering and corresponding control functions. - * - * see flexcop.c for copyright information. + * Linux driver for digital TV devices equipped with B2C2 FlexcopII(b)/III + * flexcop-hw-filter.c - pid and mac address filtering and control functions + * see flexcop.c for copyright information */ #include "flexcop.h" static void flexcop_rcv_data_ctrl(struct flexcop_device *fc, int onoff) { - flexcop_set_ibi_value(ctrl_208,Rcv_Data_sig,onoff); - - deb_ts("rcv_data is now: '%s'\n",onoff ? "on" : "off"); + flexcop_set_ibi_value(ctrl_208, Rcv_Data_sig, onoff); + deb_ts("rcv_data is now: '%s'\n", onoff ? "on" : "off"); } void flexcop_smc_ctrl(struct flexcop_device *fc, int onoff) { - flexcop_set_ibi_value(ctrl_208,SMC_Enable_sig,onoff); + flexcop_set_ibi_value(ctrl_208, SMC_Enable_sig, onoff); } static void flexcop_null_filter_ctrl(struct flexcop_device *fc, int onoff) { - flexcop_set_ibi_value(ctrl_208,Null_filter_sig,onoff); + flexcop_set_ibi_value(ctrl_208, Null_filter_sig, onoff); } void flexcop_set_mac_filter(struct flexcop_device *fc, u8 mac[6]) { - flexcop_ibi_value v418,v41c; - v41c = fc->read_ibi_reg(fc,mac_address_41c); + flexcop_ibi_value v418, v41c; + v41c = fc->read_ibi_reg(fc, mac_address_41c); v418.mac_address_418.MAC1 = mac[0]; v418.mac_address_418.MAC2 = mac[1]; @@ -36,27 +33,28 @@ void flexcop_set_mac_filter(struct flexcop_device *fc, u8 mac[6]) v41c.mac_address_41c.MAC7 = mac[4]; v41c.mac_address_41c.MAC8 = mac[5]; - fc->write_ibi_reg(fc,mac_address_418,v418); - fc->write_ibi_reg(fc,mac_address_41c,v41c); + fc->write_ibi_reg(fc, mac_address_418, v418); + fc->write_ibi_reg(fc, mac_address_41c, v41c); } void flexcop_mac_filter_ctrl(struct flexcop_device *fc, int onoff) { - flexcop_set_ibi_value(ctrl_208,MAC_filter_Mode_sig,onoff); + flexcop_set_ibi_value(ctrl_208, MAC_filter_Mode_sig, onoff); } -static void flexcop_pid_group_filter(struct flexcop_device *fc, u16 pid, u16 mask) +static void flexcop_pid_group_filter(struct flexcop_device *fc, + u16 pid, u16 mask) { /* index_reg_310.extra_index_reg need to 0 or 7 to work */ flexcop_ibi_value v30c; v30c.pid_filter_30c_ext_ind_0_7.Group_PID = pid; v30c.pid_filter_30c_ext_ind_0_7.Group_mask = mask; - fc->write_ibi_reg(fc,pid_filter_30c,v30c); + fc->write_ibi_reg(fc, pid_filter_30c, v30c); } static void flexcop_pid_group_filter_ctrl(struct flexcop_device *fc, int onoff) { - flexcop_set_ibi_value(ctrl_208,Mask_filter_sig,onoff); + flexcop_set_ibi_value(ctrl_208, Mask_filter_sig, onoff); } /* this fancy define reduces the code size of the quite similar PID controlling of @@ -65,91 +63,112 @@ static void flexcop_pid_group_filter_ctrl(struct flexcop_device *fc, int onoff) #define pid_ctrl(vregname,field,enablefield,trans_field,transval) \ flexcop_ibi_value vpid = fc->read_ibi_reg(fc, vregname), \ - v208 = fc->read_ibi_reg(fc, ctrl_208); \ -\ - vpid.vregname.field = onoff ? pid : 0x1fff; \ - vpid.vregname.trans_field = transval; \ - v208.ctrl_208.enablefield = onoff; \ -\ - fc->write_ibi_reg(fc,vregname,vpid); \ - fc->write_ibi_reg(fc,ctrl_208,v208); +v208 = fc->read_ibi_reg(fc, ctrl_208); \ +vpid.vregname.field = onoff ? pid : 0x1fff; \ +vpid.vregname.trans_field = transval; \ +v208.ctrl_208.enablefield = onoff; \ +fc->write_ibi_reg(fc, vregname, vpid); \ +fc->write_ibi_reg(fc, ctrl_208, v208); -static void flexcop_pid_Stream1_PID_ctrl(struct flexcop_device *fc, u16 pid, int onoff) +static void flexcop_pid_Stream1_PID_ctrl(struct flexcop_device *fc, + u16 pid, int onoff) { - pid_ctrl(pid_filter_300,Stream1_PID,Stream1_filter_sig,Stream1_trans,0); + pid_ctrl(pid_filter_300, Stream1_PID, Stream1_filter_sig, + Stream1_trans, 0); } -static void flexcop_pid_Stream2_PID_ctrl(struct flexcop_device *fc, u16 pid, int onoff) +static void flexcop_pid_Stream2_PID_ctrl(struct flexcop_device *fc, + u16 pid, int onoff) { - pid_ctrl(pid_filter_300,Stream2_PID,Stream2_filter_sig,Stream2_trans,0); + pid_ctrl(pid_filter_300, Stream2_PID, Stream2_filter_sig, + Stream2_trans, 0); } -static void flexcop_pid_PCR_PID_ctrl(struct flexcop_device *fc, u16 pid, int onoff) +static void flexcop_pid_PCR_PID_ctrl(struct flexcop_device *fc, + u16 pid, int onoff) { - pid_ctrl(pid_filter_304,PCR_PID,PCR_filter_sig,PCR_trans,0); + pid_ctrl(pid_filter_304, PCR_PID, PCR_filter_sig, PCR_trans, 0); } -static void flexcop_pid_PMT_PID_ctrl(struct flexcop_device *fc, u16 pid, int onoff) +static void flexcop_pid_PMT_PID_ctrl(struct flexcop_device *fc, + u16 pid, int onoff) { - pid_ctrl(pid_filter_304,PMT_PID,PMT_filter_sig,PMT_trans,0); + pid_ctrl(pid_filter_304, PMT_PID, PMT_filter_sig, PMT_trans, 0); } -static void flexcop_pid_EMM_PID_ctrl(struct flexcop_device *fc, u16 pid, int onoff) +static void flexcop_pid_EMM_PID_ctrl(struct flexcop_device *fc, + u16 pid, int onoff) { - pid_ctrl(pid_filter_308,EMM_PID,EMM_filter_sig,EMM_trans,0); + pid_ctrl(pid_filter_308, EMM_PID, EMM_filter_sig, EMM_trans, 0); } -static void flexcop_pid_ECM_PID_ctrl(struct flexcop_device *fc, u16 pid, int onoff) +static void flexcop_pid_ECM_PID_ctrl(struct flexcop_device *fc, + u16 pid, int onoff) { - pid_ctrl(pid_filter_308,ECM_PID,ECM_filter_sig,ECM_trans,0); + pid_ctrl(pid_filter_308, ECM_PID, ECM_filter_sig, ECM_trans, 0); } -static void flexcop_pid_control(struct flexcop_device *fc, int index, u16 pid,int onoff) +static void flexcop_pid_control(struct flexcop_device *fc, + int index, u16 pid, int onoff) { if (pid == 0x2000) return; - deb_ts("setting pid: %5d %04x at index %d '%s'\n",pid,pid,index,onoff ? "on" : "off"); + deb_ts("setting pid: %5d %04x at index %d '%s'\n", + pid, pid, index, onoff ? "on" : "off"); /* We could use bit magic here to reduce source code size. * I decided against it, but to use the real register names */ switch (index) { - case 0: flexcop_pid_Stream1_PID_ctrl(fc,pid,onoff); break; - case 1: flexcop_pid_Stream2_PID_ctrl(fc,pid,onoff); break; - case 2: flexcop_pid_PCR_PID_ctrl(fc,pid,onoff); break; - case 3: flexcop_pid_PMT_PID_ctrl(fc,pid,onoff); break; - case 4: flexcop_pid_EMM_PID_ctrl(fc,pid,onoff); break; - case 5: flexcop_pid_ECM_PID_ctrl(fc,pid,onoff); break; - default: - if (fc->has_32_hw_pid_filter && index < 38) { - flexcop_ibi_value vpid,vid; - - /* set the index */ - vid = fc->read_ibi_reg(fc,index_reg_310); - vid.index_reg_310.index_reg = index - 6; - fc->write_ibi_reg(fc,index_reg_310, vid); - - vpid = fc->read_ibi_reg(fc,pid_n_reg_314); - vpid.pid_n_reg_314.PID = onoff ? pid : 0x1fff; - vpid.pid_n_reg_314.PID_enable_bit = onoff; - fc->write_ibi_reg(fc,pid_n_reg_314, vpid); - } - break; + case 0: + flexcop_pid_Stream1_PID_ctrl(fc, pid, onoff); + break; + case 1: + flexcop_pid_Stream2_PID_ctrl(fc, pid, onoff); + break; + case 2: + flexcop_pid_PCR_PID_ctrl(fc, pid, onoff); + break; + case 3: + flexcop_pid_PMT_PID_ctrl(fc, pid, onoff); + break; + case 4: + flexcop_pid_EMM_PID_ctrl(fc, pid, onoff); + break; + case 5: + flexcop_pid_ECM_PID_ctrl(fc, pid, onoff); + break; + default: + if (fc->has_32_hw_pid_filter && index < 38) { + flexcop_ibi_value vpid, vid; + + /* set the index */ + vid = fc->read_ibi_reg(fc, index_reg_310); + vid.index_reg_310.index_reg = index - 6; + fc->write_ibi_reg(fc, index_reg_310, vid); + + vpid = fc->read_ibi_reg(fc, pid_n_reg_314); + vpid.pid_n_reg_314.PID = onoff ? pid : 0x1fff; + vpid.pid_n_reg_314.PID_enable_bit = onoff; + fc->write_ibi_reg(fc, pid_n_reg_314, vpid); + } + break; } } -static int flexcop_toggle_fullts_streaming(struct flexcop_device *fc,int onoff) +static int flexcop_toggle_fullts_streaming(struct flexcop_device *fc, int onoff) { if (fc->fullts_streaming_state != onoff) { deb_ts("%s full TS transfer\n",onoff ? "enabling" : "disabling"); flexcop_pid_group_filter(fc, 0, 0x1fe0 * (!onoff)); - flexcop_pid_group_filter_ctrl(fc,onoff); + flexcop_pid_group_filter_ctrl(fc, onoff); fc->fullts_streaming_state = onoff; } return 0; } -int flexcop_pid_feed_control(struct flexcop_device *fc, struct dvb_demux_feed *dvbdmxfeed, int onoff) +int flexcop_pid_feed_control(struct flexcop_device *fc, + struct dvb_demux_feed *dvbdmxfeed, int onoff) { int max_pid_filter = 6 + fc->has_32_hw_pid_filter*32; @@ -164,24 +183,25 @@ int flexcop_pid_feed_control(struct flexcop_device *fc, struct dvb_demux_feed *d * - or the requested pid is 0x2000 */ if (!fc->pid_filtering && fc->feedcount == onoff) - flexcop_toggle_fullts_streaming(fc,onoff); + flexcop_toggle_fullts_streaming(fc, onoff); if (fc->pid_filtering) { - flexcop_pid_control(fc,dvbdmxfeed->index,dvbdmxfeed->pid,onoff); + flexcop_pid_control \ + (fc, dvbdmxfeed->index, dvbdmxfeed->pid, onoff); if (fc->extra_feedcount > 0) - flexcop_toggle_fullts_streaming(fc,1); + flexcop_toggle_fullts_streaming(fc, 1); else if (dvbdmxfeed->pid == 0x2000) - flexcop_toggle_fullts_streaming(fc,onoff); + flexcop_toggle_fullts_streaming(fc, onoff); else - flexcop_toggle_fullts_streaming(fc,0); + flexcop_toggle_fullts_streaming(fc, 0); } /* if it was the first or last feed request change the stream-status */ if (fc->feedcount == onoff) { - flexcop_rcv_data_ctrl(fc,onoff); + flexcop_rcv_data_ctrl(fc, onoff); if (fc->stream_control) /* device specific stream control */ - fc->stream_control(fc,onoff); + fc->stream_control(fc, onoff); /* feeding stopped -> reset the flexcop filter*/ if (onoff == 0) { @@ -189,7 +209,6 @@ int flexcop_pid_feed_control(struct flexcop_device *fc, struct dvb_demux_feed *d flexcop_hw_filter_init(fc); } } - return 0; } EXPORT_SYMBOL(flexcop_pid_feed_control); @@ -199,15 +218,15 @@ void flexcop_hw_filter_init(struct flexcop_device *fc) int i; flexcop_ibi_value v; for (i = 0; i < 6 + 32*fc->has_32_hw_pid_filter; i++) - flexcop_pid_control(fc,i,0x1fff,0); + flexcop_pid_control(fc, i, 0x1fff, 0); flexcop_pid_group_filter(fc, 0, 0x1fe0); - flexcop_pid_group_filter_ctrl(fc,0); + flexcop_pid_group_filter_ctrl(fc, 0); - v = fc->read_ibi_reg(fc,pid_filter_308); + v = fc->read_ibi_reg(fc, pid_filter_308); v.pid_filter_308.EMM_filter_4 = 1; v.pid_filter_308.EMM_filter_6 = 0; - fc->write_ibi_reg(fc,pid_filter_308,v); + fc->write_ibi_reg(fc, pid_filter_308, v); flexcop_null_filter_ctrl(fc, 1); } diff --git a/linux/drivers/media/dvb/b2c2/flexcop-i2c.c b/linux/drivers/media/dvb/b2c2/flexcop-i2c.c index 1c07eeafc..06a90f67e 100644 --- a/linux/drivers/media/dvb/b2c2/flexcop-i2c.c +++ b/linux/drivers/media/dvb/b2c2/flexcop-i2c.c @@ -1,17 +1,14 @@ /* - * This file is part of linux driver the digital TV devices equipped with B2C2 FlexcopII(b)/III - * + * Linux driver for digital TV devices equipped with B2C2 FlexcopII(b)/III * flexcop-i2c.c - flexcop internal 2Wire bus (I2C) and dvb i2c initialization - * - * see flexcop.c for copyright information. + * see flexcop.c for copyright information */ #include "flexcop.h" #define FC_MAX_I2C_RETRIES 100000 -/* #define DUMP_I2C_MESSAGES */ - -static int flexcop_i2c_operation(struct flexcop_device *fc, flexcop_ibi_value *r100) +static int flexcop_i2c_operation(struct flexcop_device *fc, + flexcop_ibi_value *r100) { int i; flexcop_ibi_value r; @@ -26,7 +23,7 @@ static int flexcop_i2c_operation(struct flexcop_device *fc, flexcop_ibi_value *r r = fc->read_ibi_reg(fc, tw_sm_c_100); if (!r.tw_sm_c_100.no_base_addr_ack_error) { - if (r.tw_sm_c_100.st_done) { /* && !r.tw_sm_c_100.working_start */ + if (r.tw_sm_c_100.st_done) { *r100 = r; deb_i2c("i2c success\n"); return 0; @@ -36,15 +33,17 @@ static int flexcop_i2c_operation(struct flexcop_device *fc, flexcop_ibi_value *r return -EREMOTEIO; } } - deb_i2c("tried %d times i2c operation, never finished or too many ack errors.\n",i); + deb_i2c("tried %d times i2c operation, " + "never finished or too many ack errors.\n", i); return -EREMOTEIO; } static int flexcop_i2c_read4(struct flexcop_i2c_adapter *i2c, - flexcop_ibi_value r100, u8 *buf) + flexcop_ibi_value r100, u8 *buf) { flexcop_ibi_value r104; - int len = r100.tw_sm_c_100.total_bytes, /* remember total_bytes is buflen-1 */ + int len = r100.tw_sm_c_100.total_bytes, + /* remember total_bytes is buflen-1 */ ret; /* work-around to have CableStar2 and SkyStar2 rev 2.7 work @@ -81,11 +80,11 @@ static int flexcop_i2c_read4(struct flexcop_i2c_adapter *i2c, if (len > 1) buf[2] = r104.tw_sm_c_104.data3_reg; if (len > 2) buf[3] = r104.tw_sm_c_104.data4_reg; } - return 0; } -static int flexcop_i2c_write4(struct flexcop_device *fc, flexcop_ibi_value r100, u8 *buf) +static int flexcop_i2c_write4(struct flexcop_device *fc, + flexcop_ibi_value r100, u8 *buf) { flexcop_ibi_value r104; int len = r100.tw_sm_c_100.total_bytes; /* remember total_bytes is buflen-1 */ @@ -93,7 +92,6 @@ static int flexcop_i2c_write4(struct flexcop_device *fc, flexcop_ibi_value r100, /* there is at least one byte, otherwise we wouldn't be here */ r100.tw_sm_c_100.data1_reg = buf[0]; - r104.tw_sm_c_104.data2_reg = len > 0 ? buf[1] : 0; r104.tw_sm_c_104.data3_reg = len > 1 ? buf[2] : 0; r104.tw_sm_c_104.data4_reg = len > 2 ? buf[3] : 0; @@ -106,7 +104,7 @@ static int flexcop_i2c_write4(struct flexcop_device *fc, flexcop_ibi_value r100, } int flexcop_i2c_request(struct flexcop_i2c_adapter *i2c, - flexcop_access_op_t op, u8 chipaddr, u8 addr, u8 *buf, u16 len) + flexcop_access_op_t op, u8 chipaddr, u8 addr, u8 *buf, u16 len) { int ret; @@ -129,7 +127,6 @@ int flexcop_i2c_request(struct flexcop_i2c_adapter *i2c, printk("rd("); else printk("wr("); - printk("%02x): %02x ", chipaddr, addr); #endif @@ -175,7 +172,8 @@ int flexcop_i2c_request(struct flexcop_i2c_adapter *i2c, EXPORT_SYMBOL(flexcop_i2c_request); /* master xfer callback for demodulator */ -static int flexcop_master_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msgs[], int num) +static int flexcop_master_xfer(struct i2c_adapter *i2c_adap, + struct i2c_msg msgs[], int num) { struct flexcop_i2c_adapter *i2c = i2c_get_adapdata(i2c_adap); int i, ret = 0; @@ -194,12 +192,13 @@ static int flexcop_master_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msgs /* reading */ if (i+1 < num && (msgs[i+1].flags == I2C_M_RD)) { ret = i2c->fc->i2c_request(i2c, FC_READ, msgs[i].addr, - msgs[i].buf[0], msgs[i+1].buf, msgs[i+1].len); + msgs[i].buf[0], msgs[i+1].buf, + msgs[i+1].len); i++; /* skip the following message */ } else /* writing */ ret = i2c->fc->i2c_request(i2c, FC_WRITE, msgs[i].addr, - msgs[i].buf[0], &msgs[i].buf[1], - msgs[i].len - 1); + msgs[i].buf[0], &msgs[i].buf[1], + msgs[i].len - 1); if (ret < 0) { err("i2c master_xfer failed"); break; @@ -229,23 +228,21 @@ static struct i2c_algorithm flexcop_algo = { int flexcop_i2c_init(struct flexcop_device *fc) { int ret; - mutex_init(&fc->i2c_mutex); fc->fc_i2c_adap[0].fc = fc; fc->fc_i2c_adap[1].fc = fc; fc->fc_i2c_adap[2].fc = fc; - fc->fc_i2c_adap[0].port = FC_I2C_PORT_DEMOD; fc->fc_i2c_adap[1].port = FC_I2C_PORT_EEPROM; fc->fc_i2c_adap[2].port = FC_I2C_PORT_TUNER; strlcpy(fc->fc_i2c_adap[0].i2c_adap.name, "B2C2 FlexCop I2C to demod", - sizeof(fc->fc_i2c_adap[0].i2c_adap.name)); + sizeof(fc->fc_i2c_adap[0].i2c_adap.name)); strlcpy(fc->fc_i2c_adap[1].i2c_adap.name, "B2C2 FlexCop I2C to eeprom", - sizeof(fc->fc_i2c_adap[1].i2c_adap.name)); + sizeof(fc->fc_i2c_adap[1].i2c_adap.name)); strlcpy(fc->fc_i2c_adap[2].i2c_adap.name, "B2C2 FlexCop I2C to tuner", - sizeof(fc->fc_i2c_adap[2].i2c_adap.name)); + sizeof(fc->fc_i2c_adap[2].i2c_adap.name)); i2c_set_adapdata(&fc->fc_i2c_adap[0].i2c_adap, &fc->fc_i2c_adap[0]); i2c_set_adapdata(&fc->fc_i2c_adap[1].i2c_adap, &fc->fc_i2c_adap[1]); @@ -283,7 +280,6 @@ adap_2_failed: i2c_del_adapter(&fc->fc_i2c_adap[1].i2c_adap); adap_1_failed: i2c_del_adapter(&fc->fc_i2c_adap[0].i2c_adap); - return ret; } @@ -294,6 +290,5 @@ void flexcop_i2c_exit(struct flexcop_device *fc) i2c_del_adapter(&fc->fc_i2c_adap[1].i2c_adap); i2c_del_adapter(&fc->fc_i2c_adap[0].i2c_adap); } - fc->init_state &= ~FC_STATE_I2C_INIT; } diff --git a/linux/drivers/media/dvb/b2c2/flexcop-misc.c b/linux/drivers/media/dvb/b2c2/flexcop-misc.c index 93d20e56f..e56627d2f 100644 --- a/linux/drivers/media/dvb/b2c2/flexcop-misc.c +++ b/linux/drivers/media/dvb/b2c2/flexcop-misc.c @@ -1,9 +1,7 @@ /* - * This file is part of linux driver the digital TV devices equipped with B2C2 FlexcopII(b)/III - * - * flexcop-misc.c - miscellaneous functions. - * - * see flexcop.c for copyright information. + * Linux driver for digital TV devices equipped with B2C2 FlexcopII(b)/III + * flexcop-misc.c - miscellaneous functions + * see flexcop.c for copyright information */ #include "flexcop.h" @@ -12,39 +10,43 @@ void flexcop_determine_revision(struct flexcop_device *fc) flexcop_ibi_value v = fc->read_ibi_reg(fc,misc_204); switch (v.misc_204.Rev_N_sig_revision_hi) { - case 0x2: - deb_info("found a FlexCopII.\n"); - fc->rev = FLEXCOP_II; - break; - case 0x3: - deb_info("found a FlexCopIIb.\n"); - fc->rev = FLEXCOP_IIB; - break; - case 0x0: - deb_info("found a FlexCopIII.\n"); - fc->rev = FLEXCOP_III; - break; - default: - err("unkown FlexCop Revision: %x. Please report the linux-dvb@linuxtv.org.",v.misc_204.Rev_N_sig_revision_hi); - break; + case 0x2: + deb_info("found a FlexCopII.\n"); + fc->rev = FLEXCOP_II; + break; + case 0x3: + deb_info("found a FlexCopIIb.\n"); + fc->rev = FLEXCOP_IIB; + break; + case 0x0: + deb_info("found a FlexCopIII.\n"); + fc->rev = FLEXCOP_III; + break; + default: + err("unknown FlexCop Revision: %x. Please report this to " + "linux-dvb@linuxtv.org.", + v.misc_204.Rev_N_sig_revision_hi); + break; } if ((fc->has_32_hw_pid_filter = v.misc_204.Rev_N_sig_caps)) - deb_info("this FlexCop has the additional 32 hardware pid filter.\n"); + deb_info("this FlexCop has " + "the additional 32 hardware pid filter.\n"); else - deb_info("this FlexCop has only the 6 basic main hardware pid filter.\n"); + deb_info("this FlexCop has " + "the 6 basic main hardware pid filter.\n"); /* bus parts have to decide if hw pid filtering is used or not. */ } static const char *flexcop_revision_names[] = { - "Unkown chip", + "Unknown chip", "FlexCopII", "FlexCopIIb", "FlexCopIII", }; static const char *flexcop_device_names[] = { - "Unkown device", + "Unknown device", "Air2PC/AirStar 2 DVB-T", "Air2PC/AirStar 2 ATSC 1st generation", "Air2PC/AirStar 2 ATSC 2nd generation", @@ -61,21 +63,23 @@ static const char *flexcop_bus_names[] = { "PCI", }; -void flexcop_device_name(struct flexcop_device *fc,const char *prefix,const - char *suffix) +void flexcop_device_name(struct flexcop_device *fc, + const char *prefix, const char *suffix) { - info("%s '%s' at the '%s' bus controlled by a '%s' %s",prefix, - flexcop_device_names[fc->dev_type],flexcop_bus_names[fc->bus_type], - flexcop_revision_names[fc->rev],suffix); + info("%s '%s' at the '%s' bus controlled by a '%s' %s", + prefix, flexcop_device_names[fc->dev_type], + flexcop_bus_names[fc->bus_type], + flexcop_revision_names[fc->rev], suffix); } -void flexcop_dump_reg(struct flexcop_device *fc, flexcop_ibi_register reg, int num) +void flexcop_dump_reg(struct flexcop_device *fc, + flexcop_ibi_register reg, int num) { flexcop_ibi_value v; int i; for (i = 0; i < num; i++) { - v = fc->read_ibi_reg(fc,reg+4*i); - deb_rdump("0x%03x: %08x, ",reg+4*i, v.raw); + v = fc->read_ibi_reg(fc, reg+4*i); + deb_rdump("0x%03x: %08x, ", reg+4*i, v.raw); } deb_rdump("\n"); } diff --git a/linux/drivers/media/dvb/b2c2/flexcop-reg.h b/linux/drivers/media/dvb/b2c2/flexcop-reg.h index 7599fccc1..dc4528dcb 100644 --- a/linux/drivers/media/dvb/b2c2/flexcop-reg.h +++ b/linux/drivers/media/dvb/b2c2/flexcop-reg.h @@ -1,14 +1,11 @@ /* - * This file is part of linux driver the digital TV devices equipped with B2C2 FlexcopII(b)/III - * + * Linux driver for digital TV devices equipped with B2C2 FlexcopII(b)/III * flexcop-reg.h - register abstraction for FlexCopII, FlexCopIIb and FlexCopIII - * - * see flexcop.c for copyright information. + * see flexcop.c for copyright information */ #ifndef __FLEXCOP_REG_H__ #define __FLEXCOP_REG_H__ - typedef enum { FLEXCOP_UNK = 0, FLEXCOP_II, @@ -18,13 +15,13 @@ typedef enum { typedef enum { FC_UNK = 0, - FC_AIR_DVB, + FC_CABLE, + FC_AIR_DVBT, FC_AIR_ATSC1, FC_AIR_ATSC2, - FC_SKY, - FC_SKY_OLD, - FC_CABLE, FC_AIR_ATSC3, + FC_SKY_REV23, + FC_SKY_REV26, FC_SKY_REV27, FC_SKY_REV28, } flexcop_device_type_t; @@ -36,12 +33,12 @@ typedef enum { /* FlexCop IBI Registers */ #if defined(__LITTLE_ENDIAN) - #include "flexcop_ibi_value_le.h" +#include "flexcop_ibi_value_le.h" #else #if defined(__BIG_ENDIAN) - #include "flexcop_ibi_value_be.h" +#include "flexcop_ibi_value_be.h" #else - #error no endian defined +#error no endian defined #endif #endif diff --git a/linux/drivers/media/dvb/b2c2/flexcop-sram.c b/linux/drivers/media/dvb/b2c2/flexcop-sram.c index cfb196ef7..d0e82a360 100644 --- a/linux/drivers/media/dvb/b2c2/flexcop-sram.c +++ b/linux/drivers/media/dvb/b2c2/flexcop-sram.c @@ -1,45 +1,43 @@ /* - * This file is part of linux driver the digital TV devices equipped with B2C2 FlexcopII(b)/III - * - * flexcop-sram.c - functions for controlling the SRAM. - * - * see flexcop.c for copyright information. + * Linux driver for digital TV devices equipped with B2C2 FlexcopII(b)/III + * flexcop-sram.c - functions for controlling the SRAM + * see flexcop.c for copyright information */ #include "flexcop.h" -static void flexcop_sram_set_chip (struct flexcop_device *fc, flexcop_sram_type_t type) +static void flexcop_sram_set_chip(struct flexcop_device *fc, + flexcop_sram_type_t type) { - flexcop_set_ibi_value(wan_ctrl_reg_71c,sram_chip,type); + flexcop_set_ibi_value(wan_ctrl_reg_71c, sram_chip, type); } int flexcop_sram_init(struct flexcop_device *fc) { switch (fc->rev) { - case FLEXCOP_II: - case FLEXCOP_IIB: - flexcop_sram_set_chip(fc,FC_SRAM_1_32KB); - break; - case FLEXCOP_III: - flexcop_sram_set_chip(fc,FC_SRAM_1_48KB); - break; - default: - return -EINVAL; + case FLEXCOP_II: + case FLEXCOP_IIB: + flexcop_sram_set_chip(fc, FC_SRAM_1_32KB); + break; + case FLEXCOP_III: + flexcop_sram_set_chip(fc, FC_SRAM_1_48KB); + break; + default: + return -EINVAL; } return 0; } -int flexcop_sram_set_dest(struct flexcop_device *fc, flexcop_sram_dest_t dest, flexcop_sram_dest_target_t target) +int flexcop_sram_set_dest(struct flexcop_device *fc, flexcop_sram_dest_t dest, + flexcop_sram_dest_target_t target) { flexcop_ibi_value v; - - v = fc->read_ibi_reg(fc,sram_dest_reg_714); + v = fc->read_ibi_reg(fc, sram_dest_reg_714); if (fc->rev != FLEXCOP_III && target == FC_SRAM_DEST_TARGET_FC3_CA) { err("SRAM destination target to available on FlexCopII(b)\n"); return -EINVAL; } - - deb_sram("sram dest: %x target: %x\n",dest, target); + deb_sram("sram dest: %x target: %x\n", dest, target); if (dest & FC_SRAM_DEST_NET) v.sram_dest_reg_714.NET_Dest = target; @@ -154,14 +152,12 @@ static void sram_write_chunk(struct adapter *adapter, u32 addr, u8 *buf, u16 len else bank = 0x10000000; } - flex_sram_write(adapter, bank, addr & 0x7fff, buf, len); } static void sram_read_chunk(struct adapter *adapter, u32 addr, u8 *buf, u16 len) { u32 bank; - bank = 0; if (adapter->dw_sram_type == 0x20000) { @@ -174,26 +170,22 @@ static void sram_read_chunk(struct adapter *adapter, u32 addr, u8 *buf, u16 len) else bank = 0x10000000; } - flex_sram_read(adapter, bank, addr & 0x7fff, buf, len); } static void sram_read(struct adapter *adapter, u32 addr, u8 *buf, u32 len) { u32 length; - while (len != 0) { length = len; - - // check if the address range belongs to the same - // 32K memory chip. If not, the data is read from - // one chip at a time. + /* check if the address range belongs to the same + * 32K memory chip. If not, the data is read + * from one chip at a time */ if ((addr >> 0x0f) != ((addr + len - 1) >> 0x0f)) { length = (((addr >> 0x0f) + 1) << 0x0f) - addr; } sram_read_chunk(adapter, addr, buf, length); - addr = addr + length; buf = buf + length; len = len - length; @@ -203,19 +195,17 @@ static void sram_read(struct adapter *adapter, u32 addr, u8 *buf, u32 len) static void sram_write(struct adapter *adapter, u32 addr, u8 *buf, u32 len) { u32 length; - while (len != 0) { length = len; - // check if the address range belongs to the same - // 32K memory chip. If not, the data is written to - // one chip at a time. + /* check if the address range belongs to the same + * 32K memory chip. If not, the data is + * written to one chip at a time */ if ((addr >> 0x0f) != ((addr + len - 1) >> 0x0f)) { length = (((addr >> 0x0f) + 1) << 0x0f) - addr; } sram_write_chunk(adapter, addr, buf, length); - addr = addr + length; buf = buf + length; len = len - length; @@ -224,39 +214,29 @@ static void sram_write(struct adapter *adapter, u32 addr, u8 *buf, u32 len) static void sram_set_size(struct adapter *adapter, u32 mask) { - write_reg_dw(adapter, 0x71c, (mask | (~0x30000 & read_reg_dw(adapter, 0x71c)))); + write_reg_dw(adapter, 0x71c, + (mask | (~0x30000 & read_reg_dw(adapter, 0x71c)))); } static void sram_init(struct adapter *adapter) { u32 tmp; - tmp = read_reg_dw(adapter, 0x71c); - write_reg_dw(adapter, 0x71c, 1); if (read_reg_dw(adapter, 0x71c) != 0) { write_reg_dw(adapter, 0x71c, tmp); - adapter->dw_sram_type = tmp & 0x30000; - ddprintk("%s: dw_sram_type = %x\n", __func__, adapter->dw_sram_type); - } else { - adapter->dw_sram_type = 0x10000; - ddprintk("%s: dw_sram_type = %x\n", __func__, adapter->dw_sram_type); } - - /* return value is never used? */ -/* return adapter->dw_sram_type; */ } static int sram_test_location(struct adapter *adapter, u32 mask, u32 addr) { u8 tmp1, tmp2; - dprintk("%s: mask = %x, addr = %x\n", __func__, mask, addr); sram_set_size(adapter, mask); @@ -269,7 +249,6 @@ static int sram_test_location(struct adapter *adapter, u32 mask, u32 addr) sram_write(adapter, addr + 4, &tmp1, 1); tmp2 = 0; - mdelay(20); sram_read(adapter, addr, &tmp2, 1); @@ -287,7 +266,6 @@ static int sram_test_location(struct adapter *adapter, u32 mask, u32 addr) sram_write(adapter, addr + 4, &tmp1, 1); tmp2 = 0; - mdelay(20); sram_read(adapter, addr, &tmp2, 1); @@ -297,26 +275,24 @@ static int sram_test_location(struct adapter *adapter, u32 mask, u32 addr) if (tmp2 != 0x5a) return 0; - return 1; } static u32 sram_length(struct adapter *adapter) { if (adapter->dw_sram_type == 0x10000) - return 32768; // 32K + return 32768; /* 32K */ if (adapter->dw_sram_type == 0x00000) - return 65536; // 64K + return 65536; /* 64K */ if (adapter->dw_sram_type == 0x20000) - return 131072; // 128K - - return 32768; // 32K + return 131072; /* 128K */ + return 32768; /* 32K */ } /* FlexcopII can work with 32K, 64K or 128K of external SRAM memory. - - for 128K there are 4x32K chips at bank 0,1,2,3. - - for 64K there are 2x32K chips at bank 1,2. - - for 32K there is one 32K chip at bank 0. + - for 128K there are 4x32K chips at bank 0,1,2,3. + - for 64K there are 2x32K chips at bank 1,2. + - for 32K there is one 32K chip at bank 0. FlexCop works only with one bank at a time. The bank is selected by bits 28-29 of the 0x700 register. @@ -324,24 +300,18 @@ static u32 sram_length(struct adapter *adapter) bank 0 covers addresses 0x00000-0x07fff bank 1 covers addresses 0x08000-0x0ffff bank 2 covers addresses 0x10000-0x17fff - bank 3 covers addresses 0x18000-0x1ffff -*/ + bank 3 covers addresses 0x18000-0x1ffff */ static int flexcop_sram_detect(struct flexcop_device *fc) { - flexcop_ibi_value r208,r71c_0,vr71c_1; - + flexcop_ibi_value r208, r71c_0, vr71c_1; r208 = fc->read_ibi_reg(fc, ctrl_208); fc->write_ibi_reg(fc, ctrl_208, ibi_zero); r71c_0 = fc->read_ibi_reg(fc, wan_ctrl_reg_71c); - write_reg_dw(adapter, 0x71c, 1); - tmp3 = read_reg_dw(adapter, 0x71c); - dprintk("%s: tmp3 = %x\n", __func__, tmp3); - write_reg_dw(adapter, 0x71c, tmp2); // check for internal SRAM ??? @@ -350,9 +320,7 @@ static int flexcop_sram_detect(struct flexcop_device *fc) sram_set_size(adapter, 0x10000); sram_init(adapter); write_reg_dw(adapter, 0x208, tmp); - dprintk("%s: sram size = 32K\n", __func__); - return 32; } @@ -360,9 +328,7 @@ static int flexcop_sram_detect(struct flexcop_device *fc) sram_set_size(adapter, 0x20000); sram_init(adapter); write_reg_dw(adapter, 0x208, tmp); - dprintk("%s: sram size = 128K\n", __func__); - return 128; } @@ -370,9 +336,7 @@ static int flexcop_sram_detect(struct flexcop_device *fc) sram_set_size(adapter, 0x00000); sram_init(adapter); write_reg_dw(adapter, 0x208, tmp); - dprintk("%s: sram size = 64K\n", __func__); - return 64; } @@ -380,18 +344,14 @@ static int flexcop_sram_detect(struct flexcop_device *fc) sram_set_size(adapter, 0x10000); sram_init(adapter); write_reg_dw(adapter, 0x208, tmp); - dprintk("%s: sram size = 32K\n", __func__); - return 32; } sram_set_size(adapter, 0x10000); sram_init(adapter); write_reg_dw(adapter, 0x208, tmp); - dprintk("%s: SRAM detection failed. Set to 32K \n", __func__); - return 0; } diff --git a/linux/drivers/media/dvb/b2c2/flexcop-usb.h b/linux/drivers/media/dvb/b2c2/flexcop-usb.h index 0e31b9881..5fa250e33 100644 --- a/linux/drivers/media/dvb/b2c2/flexcop-usb.h +++ b/linux/drivers/media/dvb/b2c2/flexcop-usb.h @@ -1,15 +1,20 @@ +/* + * Linux driver for digital TV devices equipped with B2C2 FlexcopII(b)/III + * flexcop-usb.h - header file for the USB part + * see flexcop.c for copyright information + */ #ifndef __FLEXCOP_USB_H_INCLUDED__ #define __FLEXCOP_USB_H_INCLUDED__ #include /* transfer parameters */ -#define B2C2_USB_FRAMES_PER_ISO 4 -#define B2C2_USB_NUM_ISO_URB 4 +#define B2C2_USB_FRAMES_PER_ISO 4 +#define B2C2_USB_NUM_ISO_URB 4 -#define B2C2_USB_CTRL_PIPE_IN usb_rcvctrlpipe(fc_usb->udev,0) -#define B2C2_USB_CTRL_PIPE_OUT usb_sndctrlpipe(fc_usb->udev,0) -#define B2C2_USB_DATA_PIPE usb_rcvisocpipe(fc_usb->udev,0x81) +#define B2C2_USB_CTRL_PIPE_IN usb_rcvctrlpipe(fc_usb->udev, 0) +#define B2C2_USB_CTRL_PIPE_OUT usb_sndctrlpipe(fc_usb->udev, 0) +#define B2C2_USB_DATA_PIPE usb_rcvisocpipe(fc_usb->udev, 0x81) struct flexcop_usb { struct usb_device *udev; @@ -18,8 +23,8 @@ struct flexcop_usb { u8 *iso_buffer; int buffer_size; dma_addr_t dma_addr; - struct urb *iso_urb[B2C2_USB_NUM_ISO_URB]; + struct urb *iso_urb[B2C2_USB_NUM_ISO_URB]; struct flexcop_device *fc_dev; u8 tmp_buffer[1023+190]; @@ -30,14 +35,6 @@ struct flexcop_usb { /* request types TODO What is its use?*/ typedef enum { -/* something is wrong with this part - RTYPE_READ_DW = (1 << 6), - RTYPE_WRITE_DW_1 = (3 << 6), - RTYPE_READ_V8_MEMORY = (6 << 6), - RTYPE_WRITE_V8_MEMORY = (7 << 6), - RTYPE_WRITE_V8_FLASH = (8 << 6), - RTYPE_GENERIC = (9 << 6), -*/ } flexcop_usb_request_type_t; #endif @@ -47,7 +44,6 @@ typedef enum { B2C2_USB_READ_V8_MEM = 0x05, B2C2_USB_READ_REG = 0x08, B2C2_USB_WRITE_REG = 0x0A, -/* B2C2_USB_WRITEREGLO = 0x0A, */ B2C2_USB_WRITEREGHI = 0x0B, B2C2_USB_FLASH_BLOCK = 0x10, B2C2_USB_I2C_REQUEST = 0x11, @@ -62,15 +58,13 @@ typedef enum { USB_FUNC_I2C_REPEATWRITE = 0x04, USB_FUNC_GET_DESCRIPTOR = 0x05, USB_FUNC_I2C_REPEATREAD = 0x06, -/* DKT 020208 - add this to support special case of DiSEqC */ + /* DKT 020208 - add this to support special case of DiSEqC */ USB_FUNC_I2C_CHECKWRITE = 0x07, USB_FUNC_I2C_CHECKRESULT = 0x08, } flexcop_usb_i2c_function_t; -/* - * function definition for UTILITY request 0x12 - * DKT 020304 - new utility function - */ +/* function definition for UTILITY request 0x12 + * DKT 020304 - new utility function */ typedef enum { UTILITY_SET_FILTER = 0x01, UTILITY_DATA_ENABLE = 0x02, @@ -84,7 +78,7 @@ typedef enum { UTILITY_DATA_RESET = 0x0A, UTILITY_GET_DATA_STATUS = 0x10, UTILITY_GET_V8_REG = 0x11, -/* DKT 020326 - add function for v1.14 */ + /* DKT 020326 - add function for v1.14 */ UTILITY_SRAM_WRITE = 0x12, UTILITY_SRAM_READ = 0x13, UTILITY_SRAM_TESTFILL = 0x14, @@ -92,13 +86,13 @@ typedef enum { UTILITY_SRAM_TESTVERIFY = 0x16, } flexcop_usb_utility_function_t; -#define B2C2_WAIT_FOR_OPERATION_RW 1*HZ /* 1 s */ -#define B2C2_WAIT_FOR_OPERATION_RDW 3*HZ /* 3 s */ -#define B2C2_WAIT_FOR_OPERATION_WDW 1*HZ /* 1 s */ +#define B2C2_WAIT_FOR_OPERATION_RW (1*HZ) +#define B2C2_WAIT_FOR_OPERATION_RDW (3*HZ) +#define B2C2_WAIT_FOR_OPERATION_WDW (1*HZ) -#define B2C2_WAIT_FOR_OPERATION_V8READ 3*HZ /* 3 s */ -#define B2C2_WAIT_FOR_OPERATION_V8WRITE 3*HZ /* 3 s */ -#define B2C2_WAIT_FOR_OPERATION_V8FLASH 3*HZ /* 3 s */ +#define B2C2_WAIT_FOR_OPERATION_V8READ (3*HZ) +#define B2C2_WAIT_FOR_OPERATION_V8WRITE (3*HZ) +#define B2C2_WAIT_FOR_OPERATION_V8FLASH (3*HZ) typedef enum { V8_MEMORY_PAGE_DVB_CI = 0x20, @@ -107,13 +101,11 @@ typedef enum { V8_MEMORY_PAGE_FLASH = 0x80 } flexcop_usb_mem_page_t; -#define V8_MEMORY_EXTENDED (1 << 15) - -#define USB_MEM_READ_MAX 32 -#define USB_MEM_WRITE_MAX 1 -#define USB_FLASH_MAX 8 - -#define V8_MEMORY_PAGE_SIZE 0x8000 // 32K -#define V8_MEMORY_PAGE_MASK 0x7FFF +#define V8_MEMORY_EXTENDED (1 << 15) +#define USB_MEM_READ_MAX 32 +#define USB_MEM_WRITE_MAX 1 +#define USB_FLASH_MAX 8 +#define V8_MEMORY_PAGE_SIZE 0x8000 /* 32K */ +#define V8_MEMORY_PAGE_MASK 0x7FFF #endif diff --git a/linux/drivers/media/dvb/b2c2/flexcop.c b/linux/drivers/media/dvb/b2c2/flexcop.c index e836caece..2df1b0214 100644 --- a/linux/drivers/media/dvb/b2c2/flexcop.c +++ b/linux/drivers/media/dvb/b2c2/flexcop.c @@ -1,22 +1,20 @@ /* - * flexcop.c - driver for digital TV devices equipped with B2C2 FlexcopII(b)/III - * - * Copyright (C) 2004-5 Patrick Boettcher - * - * based on the skystar2-driver - * Copyright (C) 2003 Vadim Catana, skystar@moldova.cc + * Linux driver for digital TV devices equipped with B2C2 FlexcopII(b)/III + * flexcop.c - main module part + * Copyright (C) 2004-9 Patrick Boettcher + * based on skystar2-driver Copyright (C) 2003 Vadim Catana, skystar@moldova.cc * * Acknowledgements: - * John Jurrius from BBTI, Inc. for extensive support with - * code examples and data books - * - * Bjarne Steinsbo, bjarne at steinsbo.com (some ideas for rewriting) + * John Jurrius from BBTI, Inc. for extensive support + * with code examples and data books + * Bjarne Steinsbo, bjarne at steinsbo.com (some ideas for rewriting) * * Contributions to the skystar2-driver have been done by - * Vincenzo Di Massa, hawk.it at tiscalinet.it (several DiSEqC fixes) - * Roberto Ragusa, r.ragusa at libero.it (polishing, restyling the code) - * Niklas Peinecke, peinecke at gdv.uni-hannover.de (hardware pid/mac filtering) - * + * Vincenzo Di Massa, hawk.it at tiscalinet.it (several DiSEqC fixes) + * Roberto Ragusa, r.ragusa at libero.it (polishing, restyling the code) + * Uwe Bugla, uwe.bugla at gmx.de (doing tests, restyling code, writing docu) + * Niklas Peinecke, peinecke at gdv.uni-hannover.de (hardware pid/mac + * filtering) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License @@ -46,7 +44,10 @@ int b2c2_flexcop_debug; module_param_named(debug, b2c2_flexcop_debug, int, 0644); -MODULE_PARM_DESC(debug, "set debug level (1=info,2=tuner,4=i2c,8=ts,16=sram,32=reg (|-able))." DEBSTATUS); +MODULE_PARM_DESC(debug, + "set debug level (1=info,2=tuner,4=i2c,8=ts," + "16=sram,32=reg (|-able))." + DEBSTATUS); #undef DEBSTATUS DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); @@ -57,37 +58,36 @@ flexcop_ibi_value ibi_zero; static int flexcop_dvb_start_feed(struct dvb_demux_feed *dvbdmxfeed) { struct flexcop_device *fc = dvbdmxfeed->demux->priv; - return flexcop_pid_feed_control(fc,dvbdmxfeed,1); + return flexcop_pid_feed_control(fc, dvbdmxfeed, 1); } static int flexcop_dvb_stop_feed(struct dvb_demux_feed *dvbdmxfeed) { struct flexcop_device *fc = dvbdmxfeed->demux->priv; - return flexcop_pid_feed_control(fc,dvbdmxfeed,0); + return flexcop_pid_feed_control(fc, dvbdmxfeed, 0); } static int flexcop_dvb_init(struct flexcop_device *fc) { int ret = dvb_register_adapter(&fc->dvb_adapter, - "FlexCop Digital TV device", fc->owner, - fc->dev, adapter_nr); + "FlexCop Digital TV device", fc->owner, + fc->dev, adapter_nr); if (ret < 0) { err("error registering DVB adapter"); return ret; } fc->dvb_adapter.priv = fc; - fc->demux.dmx.capabilities = (DMX_TS_FILTERING | DMX_SECTION_FILTERING | DMX_MEMORY_BASED_FILTERING); + fc->demux.dmx.capabilities = (DMX_TS_FILTERING | DMX_SECTION_FILTERING + | DMX_MEMORY_BASED_FILTERING); fc->demux.priv = fc; - fc->demux.filternum = fc->demux.feednum = FC_MAX_FEED; - fc->demux.start_feed = flexcop_dvb_start_feed; fc->demux.stop_feed = flexcop_dvb_stop_feed; fc->demux.write_to_decoder = NULL; if ((ret = dvb_dmx_init(&fc->demux)) < 0) { - err("dvb_dmx failed: error %d",ret); + err("dvb_dmx failed: error %d", ret); goto err_dmx; } @@ -97,23 +97,23 @@ static int flexcop_dvb_init(struct flexcop_device *fc) fc->dmxdev.demux = &fc->demux.dmx; fc->dmxdev.capabilities = 0; if ((ret = dvb_dmxdev_init(&fc->dmxdev, &fc->dvb_adapter)) < 0) { - err("dvb_dmxdev_init failed: error %d",ret); + err("dvb_dmxdev_init failed: error %d", ret); goto err_dmx_dev; } if ((ret = fc->demux.dmx.add_frontend(&fc->demux.dmx, &fc->hw_frontend)) < 0) { - err("adding hw_frontend to dmx failed: error %d",ret); + err("adding hw_frontend to dmx failed: error %d", ret); goto err_dmx_add_hw_frontend; } fc->mem_frontend.source = DMX_MEMORY_FE; if ((ret = fc->demux.dmx.add_frontend(&fc->demux.dmx, &fc->mem_frontend)) < 0) { - err("adding mem_frontend to dmx failed: error %d",ret); + err("adding mem_frontend to dmx failed: error %d", ret); goto err_dmx_add_mem_frontend; } if ((ret = fc->demux.dmx.connect_frontend(&fc->demux.dmx, &fc->hw_frontend)) < 0) { - err("connect frontend failed: error %d",ret); + err("connect frontend failed: error %d", ret); goto err_connect_frontend; } @@ -123,9 +123,9 @@ static int flexcop_dvb_init(struct flexcop_device *fc) return 0; err_connect_frontend: - fc->demux.dmx.remove_frontend(&fc->demux.dmx,&fc->mem_frontend); + fc->demux.dmx.remove_frontend(&fc->demux.dmx, &fc->mem_frontend); err_dmx_add_mem_frontend: - fc->demux.dmx.remove_frontend(&fc->demux.dmx,&fc->hw_frontend); + fc->demux.dmx.remove_frontend(&fc->demux.dmx, &fc->hw_frontend); err_dmx_add_hw_frontend: dvb_dmxdev_release(&fc->dmxdev); err_dmx_dev: @@ -141,12 +141,13 @@ static void flexcop_dvb_exit(struct flexcop_device *fc) dvb_net_release(&fc->dvbnet); fc->demux.dmx.close(&fc->demux.dmx); - fc->demux.dmx.remove_frontend(&fc->demux.dmx,&fc->mem_frontend); - fc->demux.dmx.remove_frontend(&fc->demux.dmx,&fc->hw_frontend); + fc->demux.dmx.remove_frontend(&fc->demux.dmx, + &fc->mem_frontend); + fc->demux.dmx.remove_frontend(&fc->demux.dmx, + &fc->hw_frontend); dvb_dmxdev_release(&fc->dmxdev); dvb_dmx_release(&fc->demux); dvb_unregister_adapter(&fc->dvb_adapter); - deb_info("deinitialized dvb stuff\n"); } fc->init_state &= ~FC_STATE_DVB_INIT; @@ -168,9 +169,9 @@ EXPORT_SYMBOL(flexcop_pass_dmx_packets); static void flexcop_reset(struct flexcop_device *fc) { - flexcop_ibi_value v210,v204; + flexcop_ibi_value v210, v204; -/* reset the flexcop itself */ + /* reset the flexcop itself */ fc->write_ibi_reg(fc,ctrl_208,ibi_zero); v210.raw = 0; @@ -183,13 +184,11 @@ static void flexcop_reset(struct flexcop_device *fc) v210.sw_reset_210.reset_block_600 = 1; v210.sw_reset_210.reset_block_700 = 1; v210.sw_reset_210.Block_reset_enable = 0xb2; - v210.sw_reset_210.Special_controls = 0xc259; - fc->write_ibi_reg(fc,sw_reset_210,v210); msleep(1); -/* reset the periphical devices */ + /* reset the periphical devices */ v204 = fc->read_ibi_reg(fc,misc_204); v204.misc_204.Per_reset_sig = 0; @@ -201,11 +200,10 @@ static void flexcop_reset(struct flexcop_device *fc) void flexcop_reset_block_300(struct flexcop_device *fc) { - flexcop_ibi_value v208_save = fc->read_ibi_reg(fc,ctrl_208), - v210 = fc->read_ibi_reg(fc,sw_reset_210); - - deb_rdump("208: %08x, 210: %08x\n",v208_save.raw,v210.raw); + flexcop_ibi_value v208_save = fc->read_ibi_reg(fc, ctrl_208), + v210 = fc->read_ibi_reg(fc, sw_reset_210); + deb_rdump("208: %08x, 210: %08x\n", v208_save.raw, v210.raw); fc->write_ibi_reg(fc,ctrl_208,ibi_zero); v210.sw_reset_210.reset_block_300 = 1; @@ -218,7 +216,8 @@ void flexcop_reset_block_300(struct flexcop_device *fc) struct flexcop_device *flexcop_device_kmalloc(size_t bus_specific_len) { void *bus; - struct flexcop_device *fc = kzalloc(sizeof(struct flexcop_device), GFP_KERNEL); + struct flexcop_device *fc = kzalloc(sizeof(struct flexcop_device), + GFP_KERNEL); if (!fc) { err("no memory"); return NULL; @@ -253,7 +252,6 @@ int flexcop_device_initialize(struct flexcop_device *fc) flexcop_determine_revision(fc); flexcop_sram_init(fc); flexcop_hw_filter_init(fc); - flexcop_smc_ctrl(fc, 0); if ((ret = flexcop_dvb_init(fc))) @@ -278,7 +276,6 @@ int flexcop_device_initialize(struct flexcop_device *fc) goto error; flexcop_device_name(fc,"initialization of","complete"); - return 0; error: diff --git a/linux/drivers/media/dvb/b2c2/flexcop.h b/linux/drivers/media/dvb/b2c2/flexcop.h index 0cebe1d92..897b10c85 100644 --- a/linux/drivers/media/dvb/b2c2/flexcop.h +++ b/linux/drivers/media/dvb/b2c2/flexcop.h @@ -1,9 +1,7 @@ /* - * This file is part of linux driver the digital TV devices equipped with B2C2 FlexcopII(b)/III - * - * flexcop.h - private header file for all flexcop-chip-source files. - * - * see flexcop.c for copyright information. + * Linux driver for digital TV devices equipped with B2C2 FlexcopII(b)/III + * flexcop.h - private header file for all flexcop-chip-source files + * see flexcop.c for copyright information */ #ifndef __FLEXCOP_H__ #define __FLEXCOP_H___ @@ -21,11 +19,11 @@ extern int b2c2_flexcop_debug; #define dprintk(level,args...) #endif -#define deb_info(args...) dprintk(0x01,args) -#define deb_tuner(args...) dprintk(0x02,args) -#define deb_i2c(args...) dprintk(0x04,args) -#define deb_ts(args...) dprintk(0x08,args) -#define deb_sram(args...) dprintk(0x10,args) -#define deb_rdump(args...) dprintk(0x20,args) +#define deb_info(args...) dprintk(0x01, args) +#define deb_tuner(args...) dprintk(0x02, args) +#define deb_i2c(args...) dprintk(0x04, args) +#define deb_ts(args...) dprintk(0x08, args) +#define deb_sram(args...) dprintk(0x10, args) +#define deb_rdump(args...) dprintk(0x20, args) #endif diff --git a/linux/drivers/media/dvb/b2c2/flexcop_ibi_value_be.h b/linux/drivers/media/dvb/b2c2/flexcop_ibi_value_be.h index ed9a6756b..8f64bdbd7 100644 --- a/linux/drivers/media/dvb/b2c2/flexcop_ibi_value_be.h +++ b/linux/drivers/media/dvb/b2c2/flexcop_ibi_value_be.h @@ -1,10 +1,7 @@ -/* This file is part of linux driver for digital TV devices equipped with B2C2 FlexcopII(b)/III - * +/* Linux driver for digital TV devices equipped with B2C2 FlexcopII(b)/III * register descriptions - * - * see flexcop.c for copyright information. + * see flexcop.c for copyright information */ - /* This file is automatically generated, do not edit things here. */ #ifndef __FLEXCOP_IBI_VALUE_INCLUDED__ #define __FLEXCOP_IBI_VALUE_INCLUDED__ diff --git a/linux/drivers/media/dvb/b2c2/flexcop_ibi_value_le.h b/linux/drivers/media/dvb/b2c2/flexcop_ibi_value_le.h index 49f2315b6..c75830d7d 100644 --- a/linux/drivers/media/dvb/b2c2/flexcop_ibi_value_le.h +++ b/linux/drivers/media/dvb/b2c2/flexcop_ibi_value_le.h @@ -1,10 +1,7 @@ -/* This file is part of linux driver for digital TV devices equipped with B2C2 FlexcopII(b)/III - * +/* Linux driver for digital TV devices equipped with B2C2 FlexcopII(b)/III * register descriptions - * - * see flexcop.c for copyright information. + * see flexcop.c for copyright information */ - /* This file is automatically generated, do not edit things here. */ #ifndef __FLEXCOP_IBI_VALUE_INCLUDED__ #define __FLEXCOP_IBI_VALUE_INCLUDED__ -- cgit v1.2.3 From 1e76fd570a040e49cab39af526d399c79d44ad01 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 29 Mar 2009 11:12:27 +0000 Subject: Fix buglets in v4l1 compatibility layer From: Russell King The following patch fixes a few bugs I've noticed in the V4L1 compatibility layer: - VIDEO_MODE_AUTO for get/set input ioctls was not being handled - wrong V4L2 ioctl being used in v4l1_compat_select_tuner Signed-off-by: Russell King Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/v4l1-compat.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/v4l1-compat.c b/linux/drivers/media/video/v4l1-compat.c index 4a4cb4c57..ee3991f2f 100644 --- a/linux/drivers/media/video/v4l1-compat.c +++ b/linux/drivers/media/video/v4l1-compat.c @@ -576,6 +576,8 @@ static noinline long v4l1_compat_get_input_info( chan->norm = VIDEO_MODE_NTSC; if (sid & V4L2_STD_SECAM) chan->norm = VIDEO_MODE_SECAM; + if (sid == V4L2_STD_ALL) + chan->norm = VIDEO_MODE_AUTO; } done: return err; @@ -602,6 +604,9 @@ static noinline long v4l1_compat_set_input( case VIDEO_MODE_SECAM: sid = V4L2_STD_SECAM; break; + case VIDEO_MODE_AUTO: + sid = V4L2_STD_ALL; + break; } if (0 != sid) { err = drv(file, VIDIOC_S_STD, &sid); @@ -805,9 +810,9 @@ static noinline long v4l1_compat_select_tuner( t.index = tun->tuner; - err = drv(file, VIDIOC_S_INPUT, &t); + err = drv(file, VIDIOC_S_TUNER, &t); if (err < 0) - dprintk("VIDIOCSTUNER / VIDIOC_S_INPUT: %ld\n", err); + dprintk("VIDIOCSTUNER / VIDIOC_S_TUNER: %ld\n", err); return err; } -- cgit v1.2.3 From a4a53ca9c540139e89446d304d7f83c79bd96b84 Mon Sep 17 00:00:00 2001 From: Patrick Boettcher Date: Sun, 29 Mar 2009 13:13:01 +0200 Subject: Code cleanup (passes checkpatch now) of the b2c2-flexcop-drivers 2/2 From: Uwe Bugla This is the second part of the code cleanup changing the usb and pci-driver cores. Priority: normal Signed-off-by: Uwe Bugla Signed-off-by: Patrick Boettcher --- linux/drivers/media/dvb/b2c2/flexcop-pci.c | 180 +++++++------- linux/drivers/media/dvb/b2c2/flexcop-usb.c | 368 ++++++++++++++++------------- 2 files changed, 289 insertions(+), 259 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/b2c2/flexcop-pci.c b/linux/drivers/media/dvb/b2c2/flexcop-pci.c index 72710fee2..e3ee05d98 100644 --- a/linux/drivers/media/dvb/b2c2/flexcop-pci.c +++ b/linux/drivers/media/dvb/b2c2/flexcop-pci.c @@ -1,9 +1,7 @@ /* - * This file is part of linux driver the digital TV devices equipped with B2C2 FlexcopII(b)/III - * - * flexcop-pci.c - covers the PCI part including DMA transfers. - * - * see flexcop.c for copyright information. + * Linux driver the digital TV devices equipped with B2C2 FlexcopII(b)/III + * flexcop-pci.c - covers the PCI part including DMA transfers + * see flexcop.c for copyright information */ #define FC_LOG_PREFIX "flexcop-pci" @@ -11,7 +9,8 @@ static int enable_pid_filtering = 1; module_param(enable_pid_filtering, int, 0444); -MODULE_PARM_DESC(enable_pid_filtering, "enable hardware pid filtering: supported values: 0 (fullts), 1"); +MODULE_PARM_DESC(enable_pid_filtering, + "enable hardware pid filtering: supported values: 0 (fullts), 1"); static int irq_chk_intv = 100; module_param(irq_chk_intv, int, 0644); @@ -26,17 +25,17 @@ MODULE_PARM_DESC(irq_chk_intv, "set the interval for IRQ streaming watchdog."); #define DEBSTATUS " (debugging is not enabled)" #endif -#define deb_info(args...) dprintk(0x01,args) -#define deb_reg(args...) dprintk(0x02,args) -#define deb_ts(args...) dprintk(0x04,args) -#define deb_irq(args...) dprintk(0x08,args) -#define deb_chk(args...) dprintk(0x10,args) +#define deb_info(args...) dprintk(0x01, args) +#define deb_reg(args...) dprintk(0x02, args) +#define deb_ts(args...) dprintk(0x04, args) +#define deb_irq(args...) dprintk(0x08, args) +#define deb_chk(args...) dprintk(0x10, args) static int debug; module_param(debug, int, 0644); MODULE_PARM_DESC(debug, "set debug level (1=info,2=regs,4=TS,8=irqdma,16=check (|-able))." - DEBSTATUS); + DEBSTATUS); #define DRIVER_VERSION "0.1" #define DRIVER_NAME "Technisat/B2C2 FlexCop II/IIb/III Digital TV PCI Driver" @@ -51,30 +50,30 @@ struct flexcop_pci { void __iomem *io_mem; u32 irq; -/* buffersize (at least for DMA1, need to be % 188 == 0, - * this logic is required */ + /* buffersize (at least for DMA1, need to be % 188 == 0, + * this logic is required */ #define FC_DEFAULT_DMA1_BUFSIZE (1280 * 188) #define FC_DEFAULT_DMA2_BUFSIZE (10 * 188) struct flexcop_dma dma[2]; int active_dma1_addr; /* 0 = addr0 of dma1; 1 = addr1 of dma1 */ - u32 last_dma1_cur_pos; /* position of the pointer last time the timer/packet irq occured */ + u32 last_dma1_cur_pos; + /* position of the pointer last time the timer/packet irq occured */ int count; int count_prev; int stream_problem; spinlock_t irq_lock; - unsigned long last_irq; struct delayed_work irq_check_work; - struct flexcop_device *fc_dev; }; -static int lastwreg,lastwval,lastrreg,lastrval; +static int lastwreg, lastwval, lastrreg, lastrval; -static flexcop_ibi_value flexcop_pci_read_ibi_reg (struct flexcop_device *fc, flexcop_ibi_register r) +static flexcop_ibi_value flexcop_pci_read_ibi_reg(struct flexcop_device *fc, + flexcop_ibi_register r) { struct flexcop_pci *fc_pci = fc->bus_specific; flexcop_ibi_value v; @@ -82,19 +81,20 @@ static flexcop_ibi_value flexcop_pci_read_ibi_reg (struct flexcop_device *fc, fl if (lastrreg != r || lastrval != v.raw) { lastrreg = r; lastrval = v.raw; - deb_reg("new rd: %3x: %08x\n",r,v.raw); + deb_reg("new rd: %3x: %08x\n", r, v.raw); } return v; } -static int flexcop_pci_write_ibi_reg(struct flexcop_device *fc, flexcop_ibi_register r, flexcop_ibi_value v) +static int flexcop_pci_write_ibi_reg(struct flexcop_device *fc, + flexcop_ibi_register r, flexcop_ibi_value v) { struct flexcop_pci *fc_pci = fc->bus_specific; if (lastwreg != r || lastwval != v.raw) { lastwreg = r; lastwval = v.raw; - deb_reg("new wr: %3x: %08x\n",r,v.raw); + deb_reg("new wr: %3x: %08x\n", r, v.raw); } writel(v.raw, fc_pci->io_mem + r); @@ -119,14 +119,14 @@ static void flexcop_pci_irq_check_work(struct work_struct *work) #if 0 flexcop_ibi_value v = fc->read_ibi_reg(fc, sram_dest_reg_714); deb_chk("net_ovflow_error: %d, media_ovflow_error: %d," - "cai_ovflow_error: %d, cao_ovflow_error: %d, " - "sram_dma: %d, maximumfill: %d\n", - v.sram_dest_reg_714.net_ovflow_error, - v.sram_dest_reg_714.media_ovflow_error, - v.sram_dest_reg_714.cai_ovflow_error, - v.sram_dest_reg_714.cao_ovflow_error, - v.sram_dest_reg_714.ctrl_sramdma, - v.sram_dest_reg_714.ctrl_maximumfill); + "cai_ovflow_error: %d, cao_ovflow_error: %d, " + "sram_dma: %d, maximumfill: %d\n", + v.sram_dest_reg_714.net_ovflow_error, + v.sram_dest_reg_714.media_ovflow_error, + v.sram_dest_reg_714.cai_ovflow_error, + v.sram_dest_reg_714.cao_ovflow_error, + v.sram_dest_reg_714.ctrl_sramdma, + v.sram_dest_reg_714.ctrl_maximumfill); #endif if (fc_pci->count == fc_pci->count_prev) { @@ -137,12 +137,12 @@ static void flexcop_pci_irq_check_work(struct work_struct *work) spin_lock_irq(&fc->demux.lock); list_for_each_entry(feed, &fc->demux.feed_list, - list_head) { + list_head) { flexcop_pid_feed_control(fc, feed, 0); } list_for_each_entry(feed, &fc->demux.feed_list, - list_head) { + list_head) { flexcop_pid_feed_control(fc, feed, 1); } spin_unlock_irq(&fc->demux.lock); @@ -174,11 +174,10 @@ static irqreturn_t flexcop_pci_isr(int irq, void *dev_id) flexcop_ibi_value v; irqreturn_t ret = IRQ_HANDLED; - spin_lock_irqsave(&fc_pci->irq_lock,flags); - - v = fc->read_ibi_reg(fc,irq_20c); + spin_lock_irqsave(&fc_pci->irq_lock, flags); + v = fc->read_ibi_reg(fc, irq_20c); - /* errors */ + /* errors */ if (v.irq_20c.Data_receiver_error) deb_chk("data receiver error\n"); if (v.irq_20c.Continuity_error_flag) @@ -189,24 +188,29 @@ static irqreturn_t flexcop_pci_isr(int irq, void *dev_id) deb_chk("Transport error\n"); if ((fc_pci->count % 1000) == 0) - deb_chk("%d valid irq took place so far\n",fc_pci->count); + deb_chk("%d valid irq took place so far\n", fc_pci->count); if (v.irq_20c.DMA1_IRQ_Status == 1) { if (fc_pci->active_dma1_addr == 0) - flexcop_pass_dmx_packets(fc_pci->fc_dev,fc_pci->dma[0].cpu_addr0,fc_pci->dma[0].size / 188); + flexcop_pass_dmx_packets(fc_pci->fc_dev, + fc_pci->dma[0].cpu_addr0, + fc_pci->dma[0].size / 188); else - flexcop_pass_dmx_packets(fc_pci->fc_dev,fc_pci->dma[0].cpu_addr1,fc_pci->dma[0].size / 188); + flexcop_pass_dmx_packets(fc_pci->fc_dev, + fc_pci->dma[0].cpu_addr1, + fc_pci->dma[0].size / 188); deb_irq("page change to page: %d\n",!fc_pci->active_dma1_addr); fc_pci->active_dma1_addr = !fc_pci->active_dma1_addr; - } else if (v.irq_20c.DMA1_Timer_Status == 1) { /* for the timer IRQ we only can use buffer dmx feeding, because we don't have * complete TS packets when reading from the DMA memory */ + } else if (v.irq_20c.DMA1_Timer_Status == 1) { dma_addr_t cur_addr = fc->read_ibi_reg(fc,dma1_008).dma_0x8.dma_cur_addr << 2; u32 cur_pos = cur_addr - fc_pci->dma[0].dma_addr0; - deb_irq("%u irq: %08x cur_addr: %llx: cur_pos: %08x, last_cur_pos: %08x ", + deb_irq("%u irq: %08x cur_addr: %llx: cur_pos: %08x, " + "last_cur_pos: %08x ", jiffies_to_usecs(jiffies - fc_pci->last_irq), v.raw, (unsigned long long)cur_addr, cur_pos, fc_pci->last_dma1_cur_pos); @@ -216,30 +220,36 @@ static irqreturn_t flexcop_pci_isr(int irq, void *dev_id) * pass the data from last_cur_pos to the buffer end to the demux */ if (cur_pos < fc_pci->last_dma1_cur_pos) { - deb_irq(" end was reached: passing %d bytes ",(fc_pci->dma[0].size*2 - 1) - fc_pci->last_dma1_cur_pos); + deb_irq(" end was reached: passing %d bytes ", + (fc_pci->dma[0].size*2 - 1) - + fc_pci->last_dma1_cur_pos); flexcop_pass_dmx_data(fc_pci->fc_dev, - fc_pci->dma[0].cpu_addr0 + fc_pci->last_dma1_cur_pos, - (fc_pci->dma[0].size*2) - fc_pci->last_dma1_cur_pos); + fc_pci->dma[0].cpu_addr0 + + fc_pci->last_dma1_cur_pos, + (fc_pci->dma[0].size*2) - + fc_pci->last_dma1_cur_pos); fc_pci->last_dma1_cur_pos = 0; } if (cur_pos > fc_pci->last_dma1_cur_pos) { - deb_irq(" passing %d bytes ",cur_pos - fc_pci->last_dma1_cur_pos); + deb_irq(" passing %d bytes ", + cur_pos - fc_pci->last_dma1_cur_pos); flexcop_pass_dmx_data(fc_pci->fc_dev, - fc_pci->dma[0].cpu_addr0 + fc_pci->last_dma1_cur_pos, - cur_pos - fc_pci->last_dma1_cur_pos); + fc_pci->dma[0].cpu_addr0 + + fc_pci->last_dma1_cur_pos, + cur_pos - fc_pci->last_dma1_cur_pos); } deb_irq("\n"); fc_pci->last_dma1_cur_pos = cur_pos; fc_pci->count++; } else { - deb_irq("isr for flexcop called, apparently without reason (%08x)\n",v.raw); + deb_irq("isr for flexcop called, " + "apparently without reason (%08x)\n", v.raw); ret = IRQ_NONE; } - spin_unlock_irqrestore(&fc_pci->irq_lock,flags); - + spin_unlock_irqrestore(&fc_pci->irq_lock, flags); return ret; } @@ -247,52 +257,48 @@ static int flexcop_pci_stream_control(struct flexcop_device *fc, int onoff) { struct flexcop_pci *fc_pci = fc->bus_specific; if (onoff) { - flexcop_dma_config(fc,&fc_pci->dma[0],FC_DMA_1); - flexcop_dma_config(fc,&fc_pci->dma[1],FC_DMA_2); - - flexcop_dma_config_timer(fc,FC_DMA_1,0); - - flexcop_dma_xfer_control(fc,FC_DMA_1,FC_DMA_SUBADDR_0 | FC_DMA_SUBADDR_1,1); + flexcop_dma_config(fc, &fc_pci->dma[0], FC_DMA_1); + flexcop_dma_config(fc, &fc_pci->dma[1], FC_DMA_2); + flexcop_dma_config_timer(fc, FC_DMA_1, 0); + flexcop_dma_xfer_control(fc, FC_DMA_1, + FC_DMA_SUBADDR_0 | FC_DMA_SUBADDR_1, 1); deb_irq("DMA xfer enabled\n"); fc_pci->last_dma1_cur_pos = 0; - flexcop_dma_control_timer_irq(fc,FC_DMA_1,1); + flexcop_dma_control_timer_irq(fc, FC_DMA_1, 1); deb_irq("IRQ enabled\n"); - fc_pci->count_prev = fc_pci->count; - -// fc_pci->active_dma1_addr = 0; -// flexcop_dma_control_size_irq(fc,FC_DMA_1,1); - } else { - flexcop_dma_control_timer_irq(fc,FC_DMA_1,0); + flexcop_dma_control_timer_irq(fc, FC_DMA_1, 0); deb_irq("IRQ disabled\n"); -// flexcop_dma_control_size_irq(fc,FC_DMA_1,0); - - flexcop_dma_xfer_control(fc,FC_DMA_1,FC_DMA_SUBADDR_0 | FC_DMA_SUBADDR_1,0); + flexcop_dma_xfer_control(fc, FC_DMA_1, + FC_DMA_SUBADDR_0 | FC_DMA_SUBADDR_1, 0); deb_irq("DMA xfer disabled\n"); } - return 0; } static int flexcop_pci_dma_init(struct flexcop_pci *fc_pci) { int ret; - if ((ret = flexcop_dma_allocate(fc_pci->pdev,&fc_pci->dma[0],FC_DEFAULT_DMA1_BUFSIZE)) != 0) + ret = flexcop_dma_allocate(fc_pci->pdev, &fc_pci->dma[0], + FC_DEFAULT_DMA1_BUFSIZE); + if (ret != 0) return ret; - if ((ret = flexcop_dma_allocate(fc_pci->pdev,&fc_pci->dma[1],FC_DEFAULT_DMA2_BUFSIZE)) != 0) { + ret = flexcop_dma_allocate(fc_pci->pdev, &fc_pci->dma[1], + FC_DEFAULT_DMA2_BUFSIZE); + if (ret != 0) { flexcop_dma_free(&fc_pci->dma[0]); return ret; } - flexcop_sram_set_dest(fc_pci->fc_dev,FC_SRAM_DEST_MEDIA | FC_SRAM_DEST_NET, FC_SRAM_DEST_TARGET_DMA1); - flexcop_sram_set_dest(fc_pci->fc_dev,FC_SRAM_DEST_CAO | FC_SRAM_DEST_CAI, FC_SRAM_DEST_TARGET_DMA2); - + flexcop_sram_set_dest(fc_pci->fc_dev, FC_SRAM_DEST_MEDIA | + FC_SRAM_DEST_NET, FC_SRAM_DEST_TARGET_DMA1); + flexcop_sram_set_dest(fc_pci->fc_dev, FC_SRAM_DEST_CAO | + FC_SRAM_DEST_CAI, FC_SRAM_DEST_TARGET_DMA2); fc_pci->init_state |= FC_PCI_DMA_INIT; - return ret; } @@ -315,12 +321,8 @@ static int flexcop_pci_init(struct flexcop_pci *fc_pci) if ((ret = pci_enable_device(fc_pci->pdev)) != 0) return ret; - pci_set_master(fc_pci->pdev); - /* enable interrupts */ - // pci_write_config_dword(pdev, 0x6c, 0x8000); - if ((ret = pci_request_regions(fc_pci->pdev, DRIVER_NAME)) != 0) goto err_pci_disable_device; @@ -363,8 +365,8 @@ static void flexcop_pci_exit(struct flexcop_pci *fc_pci) fc_pci->init_state &= ~FC_PCI_INIT; } - -static int flexcop_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) +static int flexcop_pci_probe(struct pci_dev *pdev, + const struct pci_device_id *ent) { struct flexcop_device *fc; struct flexcop_pci *fc_pci; @@ -375,7 +377,7 @@ static int flexcop_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e return -ENOMEM; } -/* general flexcop init */ + /* general flexcop init */ fc_pci = fc->bus_specific; fc_pci->fc_dev = fc; @@ -383,7 +385,6 @@ static int flexcop_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e fc->write_ibi_reg = flexcop_pci_write_ibi_reg; fc->i2c_request = flexcop_i2c_request; fc->get_mac_addr = flexcop_eeprom_check_mac_addr; - fc->stream_control = flexcop_pci_stream_control; if (enable_pid_filtering) @@ -393,20 +394,19 @@ static int flexcop_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e fc->pid_filtering = enable_pid_filtering; fc->bus_type = FC_PCI; - fc->dev = &pdev->dev; fc->owner = THIS_MODULE; -/* bus specific part */ + /* bus specific part */ fc_pci->pdev = pdev; if ((ret = flexcop_pci_init(fc_pci)) != 0) goto err_kfree; -/* init flexcop */ + /* init flexcop */ if ((ret = flexcop_device_initialize(fc)) != 0) goto err_pci_exit; -/* init dma */ + /* init dma */ if ((ret = flexcop_pci_dma_init(fc_pci)) != 0) goto err_fc_exit; @@ -416,10 +416,11 @@ static int flexcop_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e INIT_DELAYED_WORK(&fc_pci->irq_check_work, flexcop_pci_irq_check_work); #endif - if (irq_chk_intv > 0) - schedule_delayed_work(&fc_pci->irq_check_work, - msecs_to_jiffies(irq_chk_intv < 100 ? 100 : irq_chk_intv)); - + if (irq_chk_intv > 0) + schedule_delayed_work(&fc_pci->irq_check_work, + msecs_to_jiffies(irq_chk_intv < 100 ? + 100 : + irq_chk_intv)); return ret; err_fc_exit: @@ -449,7 +450,6 @@ static void flexcop_pci_remove(struct pci_dev *pdev) static struct pci_device_id flexcop_pci_tbl[] = { { PCI_DEVICE(0x13d0, 0x2103) }, -/* { PCI_DEVICE(0x13d0, 0x2200) }, ? */ { }, }; diff --git a/linux/drivers/media/dvb/b2c2/flexcop-usb.c b/linux/drivers/media/dvb/b2c2/flexcop-usb.c index 4be298e90..65206b656 100644 --- a/linux/drivers/media/dvb/b2c2/flexcop-usb.c +++ b/linux/drivers/media/dvb/b2c2/flexcop-usb.c @@ -1,11 +1,8 @@ /* - * This file is part of linux driver the digital TV devices equipped with B2C2 FlexcopII(b)/III - * - * flexcop-usb.c - covers the USB part. - * - * see flexcop.c for copyright information. + * Linux driver for digital TV devices equipped with B2C2 FlexcopII(b)/III + * flexcop-usb.c - covers the USB part + * see flexcop.c for copyright information */ - #define FC_LOG_PREFIX "flexcop_usb" #include "flexcop-usb.h" #include "flexcop-common.h" @@ -18,42 +15,47 @@ /* debug */ #ifdef CONFIG_DVB_B2C2_FLEXCOP_DEBUG #define dprintk(level,args...) \ - do { if ((debug & level)) { printk(args); } } while (0) -#define debug_dump(b,l,method) {\ + do { if ((debug & level)) printk(args); } while (0) + +#define debug_dump(b, l, method) do {\ int i; \ - for (i = 0; i < l; i++) method("%02x ", b[i]); \ - method("\n");\ -} + for (i = 0; i < l; i++) \ + method("%02x ", b[i]); \ + method("\n"); \ +} while (0) #define DEBSTATUS "" #else -#define dprintk(level,args...) -#define debug_dump(b,l,method) +#define dprintk(level, args...) +#define debug_dump(b, l, method) #define DEBSTATUS " (debugging is not enabled)" #endif static int debug; module_param(debug, int, 0644); -MODULE_PARM_DESC(debug, "set debugging level (1=info,ts=2,ctrl=4,i2c=8,v8mem=16 (or-able))." DEBSTATUS); +MODULE_PARM_DESC(debug, "set debugging level (1=info,ts=2," + "ctrl=4,i2c=8,v8mem=16 (or-able))." DEBSTATUS); #undef DEBSTATUS -#define deb_info(args...) dprintk(0x01,args) -#define deb_ts(args...) dprintk(0x02,args) -#define deb_ctrl(args...) dprintk(0x04,args) -#define deb_i2c(args...) dprintk(0x08,args) -#define deb_v8(args...) dprintk(0x10,args) +#define deb_info(args...) dprintk(0x01, args) +#define deb_ts(args...) dprintk(0x02, args) +#define deb_ctrl(args...) dprintk(0x04, args) +#define deb_i2c(args...) dprintk(0x08, args) +#define deb_v8(args...) dprintk(0x10, args) /* JLP 111700: we will include the 1 bit gap between the upper and lower 3 bits * in the IBI address, to make the V8 code simpler. - * PCI ADDRESS FORMAT: 0x71C -> 0000 0111 0001 1100 (these are the six bits used) + * PCI ADDRESS FORMAT: 0x71C -> 0000 0111 0001 1100 (the six bits used) * in general: 0000 0HHH 000L LL00 * IBI ADDRESS FORMAT: RHHH BLLL * * where R is the read(1)/write(0) bit, B is the busy bit * and HHH and LLL are the two sets of three bits from the PCI address. */ -#define B2C2_FLEX_PCIOFFSET_TO_INTERNALADDR(usPCI) (u8) (((usPCI >> 2) & 0x07) + ((usPCI >> 4) & 0x70)) -#define B2C2_FLEX_INTERNALADDR_TO_PCIOFFSET(ucAddr) (u16) (((ucAddr & 0x07) << 2) + ((ucAddr & 0x70) << 4)) +#define B2C2_FLEX_PCIOFFSET_TO_INTERNALADDR(usPCI) (u8) \ + (((usPCI >> 2) & 0x07) + ((usPCI >> 4) & 0x70)) +#define B2C2_FLEX_INTERNALADDR_TO_PCIOFFSET(ucAddr) (u16) \ + (((ucAddr & 0x07) << 2) + ((ucAddr & 0x70) << 4)) /* * DKT 020228 @@ -69,12 +71,13 @@ static int flexcop_usb_readwrite_dw(struct flexcop_device *fc, u16 wRegOffsPCI, struct flexcop_usb *fc_usb = fc->bus_specific; u8 request = read ? B2C2_USB_READ_REG : B2C2_USB_WRITE_REG; u8 request_type = (read ? USB_DIR_IN : USB_DIR_OUT) | USB_TYPE_VENDOR; - u8 wAddress = B2C2_FLEX_PCIOFFSET_TO_INTERNALADDR(wRegOffsPCI) | (read ? 0x80 : 0); + u8 wAddress = B2C2_FLEX_PCIOFFSET_TO_INTERNALADDR(wRegOffsPCI) | + (read ? 0x80 : 0); int len = usb_control_msg(fc_usb->udev, read ? B2C2_USB_CTRL_PIPE_IN : B2C2_USB_CTRL_PIPE_OUT, request, - request_type, /* 0xc0 read or 0x40 write*/ + request_type, /* 0xc0 read or 0x40 write */ wAddress, 0, val, @@ -82,55 +85,49 @@ static int flexcop_usb_readwrite_dw(struct flexcop_device *fc, u16 wRegOffsPCI, B2C2_WAIT_FOR_OPERATION_RDW * HZ); if (len != sizeof(u32)) { - err("error while %s dword from %d (%d).",read ? "reading" : "writing", - wAddress,wRegOffsPCI); + err("error while %s dword from %d (%d).", read ? "reading" : + "writing", wAddress, wRegOffsPCI); return -EIO; } return 0; } - /* * DKT 010817 - add support for V8 memory read/write and flash update */ static int flexcop_usb_v8_memory_req(struct flexcop_usb *fc_usb, flexcop_usb_request_t req, u8 page, u16 wAddress, - u8 *pbBuffer,u32 buflen) + u8 *pbBuffer, u32 buflen) { -// u8 dwRequestType; u8 request_type = USB_TYPE_VENDOR; u16 wIndex; - int nWaitTime,pipe,len; - + int nWaitTime, pipe, len; wIndex = page << 8; switch (req) { - case B2C2_USB_READ_V8_MEM: - nWaitTime = B2C2_WAIT_FOR_OPERATION_V8READ; - request_type |= USB_DIR_IN; -// dwRequestType = (u8) RTYPE_READ_V8_MEMORY; - pipe = B2C2_USB_CTRL_PIPE_IN; + case B2C2_USB_READ_V8_MEM: + nWaitTime = B2C2_WAIT_FOR_OPERATION_V8READ; + request_type |= USB_DIR_IN; + pipe = B2C2_USB_CTRL_PIPE_IN; break; - case B2C2_USB_WRITE_V8_MEM: - wIndex |= pbBuffer[0]; - request_type |= USB_DIR_OUT; - nWaitTime = B2C2_WAIT_FOR_OPERATION_V8WRITE; -// dwRequestType = (u8) RTYPE_WRITE_V8_MEMORY; - pipe = B2C2_USB_CTRL_PIPE_OUT; + case B2C2_USB_WRITE_V8_MEM: + wIndex |= pbBuffer[0]; + request_type |= USB_DIR_OUT; + nWaitTime = B2C2_WAIT_FOR_OPERATION_V8WRITE; + pipe = B2C2_USB_CTRL_PIPE_OUT; break; - case B2C2_USB_FLASH_BLOCK: - request_type |= USB_DIR_OUT; - nWaitTime = B2C2_WAIT_FOR_OPERATION_V8FLASH; -// dwRequestType = (u8) RTYPE_WRITE_V8_FLASH; - pipe = B2C2_USB_CTRL_PIPE_OUT; + case B2C2_USB_FLASH_BLOCK: + request_type |= USB_DIR_OUT; + nWaitTime = B2C2_WAIT_FOR_OPERATION_V8FLASH; + pipe = B2C2_USB_CTRL_PIPE_OUT; break; - default: - deb_info("unsupported request for v8_mem_req %x.\n",req); + default: + deb_info("unsupported request for v8_mem_req %x.\n", req); return -EINVAL; } - deb_v8("v8mem: %02x %02x %04x %04x, len: %d\n",request_type,req, - wAddress,wIndex,buflen); + deb_v8("v8mem: %02x %02x %04x %04x, len: %d\n", request_type, req, + wAddress, wIndex, buflen); - len = usb_control_msg(fc_usb->udev,pipe, + len = usb_control_msg(fc_usb->udev, pipe, req, request_type, wAddress, @@ -139,39 +136,53 @@ static int flexcop_usb_v8_memory_req(struct flexcop_usb *fc_usb, buflen, nWaitTime * HZ); - debug_dump(pbBuffer,len,deb_v8); - + debug_dump(pbBuffer, len, deb_v8); return len == buflen ? 0 : -EIO; } #define bytes_left_to_read_on_page(paddr,buflen) \ - ((V8_MEMORY_PAGE_SIZE - (paddr & V8_MEMORY_PAGE_MASK)) > buflen \ - ? buflen : (V8_MEMORY_PAGE_SIZE - (paddr & V8_MEMORY_PAGE_MASK))) + ((V8_MEMORY_PAGE_SIZE - (paddr & V8_MEMORY_PAGE_MASK)) > buflen \ + ? buflen : (V8_MEMORY_PAGE_SIZE - (paddr & V8_MEMORY_PAGE_MASK))) -static int flexcop_usb_memory_req(struct flexcop_usb *fc_usb,flexcop_usb_request_t req, - flexcop_usb_mem_page_t page_start, u32 addr, int extended, u8 *buf, u32 len) +static int flexcop_usb_memory_req(struct flexcop_usb *fc_usb, + flexcop_usb_request_t req, flexcop_usb_mem_page_t page_start, + u32 addr, int extended, u8 *buf, u32 len) { int i,ret = 0; u16 wMax; u32 pagechunk = 0; switch(req) { - case B2C2_USB_READ_V8_MEM: wMax = USB_MEM_READ_MAX; break; - case B2C2_USB_WRITE_V8_MEM: wMax = USB_MEM_WRITE_MAX; break; - case B2C2_USB_FLASH_BLOCK: wMax = USB_FLASH_MAX; break; - default: - return -EINVAL; + case B2C2_USB_READ_V8_MEM: + wMax = USB_MEM_READ_MAX; + break; + case B2C2_USB_WRITE_V8_MEM: + wMax = USB_MEM_WRITE_MAX; + break; + case B2C2_USB_FLASH_BLOCK: + wMax = USB_FLASH_MAX; + break; + default: + return -EINVAL; break; } for (i = 0; i < len;) { - pagechunk = wMax < bytes_left_to_read_on_page(addr,len) ? wMax : bytes_left_to_read_on_page(addr,len); - deb_info("%x\n",(addr & V8_MEMORY_PAGE_MASK) | (V8_MEMORY_EXTENDED*extended)); - if ((ret = flexcop_usb_v8_memory_req(fc_usb,req, - page_start + (addr / V8_MEMORY_PAGE_SIZE), /* actual page */ - (addr & V8_MEMORY_PAGE_MASK) | (V8_MEMORY_EXTENDED*extended), - &buf[i],pagechunk)) < 0) + pagechunk = + wMax < bytes_left_to_read_on_page(addr, len) ? + wMax : + bytes_left_to_read_on_page(addr, len); + deb_info("%x\n", + (addr & V8_MEMORY_PAGE_MASK) | + (V8_MEMORY_EXTENDED*extended)); + + ret = flexcop_usb_v8_memory_req(fc_usb, req, + page_start + (addr / V8_MEMORY_PAGE_SIZE), + (addr & V8_MEMORY_PAGE_MASK) | + (V8_MEMORY_EXTENDED*extended), + &buf[i], pagechunk); + + if (ret < 0) return ret; - addr += pagechunk; len -= pagechunk; } @@ -180,8 +191,9 @@ static int flexcop_usb_memory_req(struct flexcop_usb *fc_usb,flexcop_usb_request static int flexcop_usb_get_mac_addr(struct flexcop_device *fc, int extended) { - return flexcop_usb_memory_req(fc->bus_specific,B2C2_USB_READ_V8_MEM, - V8_MEMORY_PAGE_FLASH,0x1f010,1,fc->dvb_adapter.proposed_mac,6); + return flexcop_usb_memory_req(fc->bus_specific, B2C2_USB_READ_V8_MEM, + V8_MEMORY_PAGE_FLASH, 0x1f010, 1, + fc->dvb_adapter.proposed_mac, 6); } #if 0 /* keep */ @@ -191,11 +203,8 @@ static int flexcop_usb_utility_req(struct flexcop_usb *fc_usb, int set, { u16 wValue; u8 request_type = (set ? USB_DIR_OUT : USB_DIR_IN) | USB_TYPE_VENDOR; -// u8 dwRequestType = (u8) RTYPE_GENERIC, int nWaitTime = 2, - pipe = set ? B2C2_USB_CTRL_PIPE_OUT : B2C2_USB_CTRL_PIPE_IN, - len; - + pipe = set ? B2C2_USB_CTRL_PIPE_OUT : B2C2_USB_CTRL_PIPE_IN, len; wValue = (func << 8) | extra; len = usb_control_msg(fc_usb->udev,pipe, @@ -218,36 +227,35 @@ static int flexcop_usb_i2c_req(struct flexcop_i2c_adapter *i2c, struct flexcop_usb *fc_usb = i2c->fc->bus_specific; u16 wValue, wIndex; int nWaitTime,pipe,len; -// u8 dwRequestType; u8 request_type = USB_TYPE_VENDOR; switch (func) { - case USB_FUNC_I2C_WRITE: - case USB_FUNC_I2C_MULTIWRITE: - case USB_FUNC_I2C_REPEATWRITE: + case USB_FUNC_I2C_WRITE: + case USB_FUNC_I2C_MULTIWRITE: + case USB_FUNC_I2C_REPEATWRITE: /* DKT 020208 - add this to support special case of DiSEqC */ - case USB_FUNC_I2C_CHECKWRITE: - pipe = B2C2_USB_CTRL_PIPE_OUT; - nWaitTime = 2; -// dwRequestType = (u8) RTYPE_GENERIC; - request_type |= USB_DIR_OUT; + case USB_FUNC_I2C_CHECKWRITE: + pipe = B2C2_USB_CTRL_PIPE_OUT; + nWaitTime = 2; + request_type |= USB_DIR_OUT; break; - case USB_FUNC_I2C_READ: - case USB_FUNC_I2C_REPEATREAD: - pipe = B2C2_USB_CTRL_PIPE_IN; - nWaitTime = 2; -// dwRequestType = (u8) RTYPE_GENERIC; - request_type |= USB_DIR_IN; + case USB_FUNC_I2C_READ: + case USB_FUNC_I2C_REPEATREAD: + pipe = B2C2_USB_CTRL_PIPE_IN; + nWaitTime = 2; + request_type |= USB_DIR_IN; break; - default: - deb_info("unsupported function for i2c_req %x\n",func); - return -EINVAL; + default: + deb_info("unsupported function for i2c_req %x\n", func); + return -EINVAL; } wValue = (func << 8) | (i2c->port << 4); wIndex = (chipaddr << 8 ) | addr; - deb_i2c("i2c %2d: %02x %02x %02x %02x %02x %02x\n",func,request_type,req, - wValue & 0xff, wValue >> 8, wIndex & 0xff, wIndex >> 8); + deb_i2c("i2c %2d: %02x %02x %02x %02x %02x %02x\n", + func, request_type, req, + wValue & 0xff, wValue >> 8, + wIndex & 0xff, wIndex >> 8); len = usb_control_msg(fc_usb->udev,pipe, req, @@ -257,44 +265,49 @@ static int flexcop_usb_i2c_req(struct flexcop_i2c_adapter *i2c, buf, buflen, nWaitTime * HZ); - return len == buflen ? 0 : -EREMOTEIO; } -/* actual bus specific access functions, make sure prototype are/will be equal to pci */ -static flexcop_ibi_value flexcop_usb_read_ibi_reg(struct flexcop_device *fc, flexcop_ibi_register reg) +/* actual bus specific access functions, + make sure prototype are/will be equal to pci */ +static flexcop_ibi_value flexcop_usb_read_ibi_reg(struct flexcop_device *fc, + flexcop_ibi_register reg) { flexcop_ibi_value val; val.raw = 0; - flexcop_usb_readwrite_dw(fc,reg, &val.raw, 1); + flexcop_usb_readwrite_dw(fc, reg, &val.raw, 1); return val; } -static int flexcop_usb_write_ibi_reg(struct flexcop_device *fc, flexcop_ibi_register reg, flexcop_ibi_value val) +static int flexcop_usb_write_ibi_reg(struct flexcop_device *fc, + flexcop_ibi_register reg, flexcop_ibi_value val) { - return flexcop_usb_readwrite_dw(fc,reg, &val.raw, 0); + return flexcop_usb_readwrite_dw(fc, reg, &val.raw, 0); } static int flexcop_usb_i2c_request(struct flexcop_i2c_adapter *i2c, - flexcop_access_op_t op, u8 chipaddr, u8 addr, u8 *buf, u16 len) + flexcop_access_op_t op, u8 chipaddr, u8 addr, u8 *buf, u16 len) { if (op == FC_READ) return flexcop_usb_i2c_req(i2c, B2C2_USB_I2C_REQUEST, - USB_FUNC_I2C_READ, chipaddr, addr, buf, len); + USB_FUNC_I2C_READ, chipaddr, addr, buf, len); else return flexcop_usb_i2c_req(i2c, B2C2_USB_I2C_REQUEST, - USB_FUNC_I2C_WRITE, chipaddr, addr, buf, len); + USB_FUNC_I2C_WRITE, chipaddr, addr, buf, len); } -static void flexcop_usb_process_frame(struct flexcop_usb *fc_usb, u8 *buffer, int buffer_length) +static void flexcop_usb_process_frame(struct flexcop_usb *fc_usb, + u8 *buffer, int buffer_length) { u8 *b; int l; - deb_ts("tmp_buffer_length=%d, buffer_length=%d\n", fc_usb->tmp_buffer_length, buffer_length); + deb_ts("tmp_buffer_length=%d, buffer_length=%d\n", + fc_usb->tmp_buffer_length, buffer_length); if (fc_usb->tmp_buffer_length > 0) { - memcpy(fc_usb->tmp_buffer+fc_usb->tmp_buffer_length, buffer, buffer_length); + memcpy(fc_usb->tmp_buffer+fc_usb->tmp_buffer_length, buffer, + buffer_length); fc_usb->tmp_buffer_length += buffer_length; b = fc_usb->tmp_buffer; l = fc_usb->tmp_buffer_length; @@ -304,23 +317,26 @@ static void flexcop_usb_process_frame(struct flexcop_usb *fc_usb, u8 *buffer, in } while (l >= 190) { - if (*b == 0xff) + if (*b == 0xff) { switch (*(b+1) & 0x03) { - case 0x01: /* media packet */ - if ( *(b+2) == 0x47 ) - flexcop_pass_dmx_packets(fc_usb->fc_dev, b+2, 1); - else - deb_ts("not ts packet %02x %02x %02x %02x \n", *(b+2), *(b+3), *(b+4), *(b+5) ); - - b += 190; - l -= 190; + case 0x01: /* media packet */ + if (*(b+2) == 0x47) + flexcop_pass_dmx_packets( + fc_usb->fc_dev, b+2, 1); + else + deb_ts( + "not ts packet %02x %02x %02x %02x \n", + *(b+2), *(b+3), + *(b+4), *(b+5)); + b += 190; + l -= 190; break; - default: - deb_ts("wrong packet type\n"); - l = 0; + default: + deb_ts("wrong packet type\n"); + l = 0; break; } - else { + } else { deb_ts("wrong header\n"); l = 0; } @@ -341,23 +357,26 @@ static void flexcop_usb_urb_complete(struct urb *urb) int i; if (urb->actual_length > 0) - deb_ts("urb completed, bufsize: %d actlen; %d\n",urb->transfer_buffer_length, urb->actual_length); + deb_ts("urb completed, bufsize: %d actlen; %d\n", + urb->transfer_buffer_length, urb->actual_length); for (i = 0; i < urb->number_of_packets; i++) { if (urb->iso_frame_desc[i].status < 0) { - err("iso frame descriptor %d has an error: %d\n",i,urb->iso_frame_desc[i].status); + err("iso frame descriptor %d has an error: %d\n", i, + urb->iso_frame_desc[i].status); } else if (urb->iso_frame_desc[i].actual_length > 0) { - deb_ts("passed %d bytes to the demux\n",urb->iso_frame_desc[i].actual_length); + deb_ts("passed %d bytes to the demux\n", + urb->iso_frame_desc[i].actual_length); flexcop_usb_process_frame(fc_usb, - urb->transfer_buffer + urb->iso_frame_desc[i].offset, + urb->transfer_buffer + + urb->iso_frame_desc[i].offset, urb->iso_frame_desc[i].actual_length); - } + } urb->iso_frame_desc[i].status = 0; urb->iso_frame_desc[i].actual_length = 0; } - usb_submit_urb(urb,GFP_ATOMIC); } @@ -378,35 +397,47 @@ static void flexcop_usb_transfer_exit(struct flexcop_usb *fc_usb) } if (fc_usb->iso_buffer != NULL) - pci_free_consistent(NULL,fc_usb->buffer_size, fc_usb->iso_buffer, fc_usb->dma_addr); + pci_free_consistent(NULL, + fc_usb->buffer_size, fc_usb->iso_buffer, + fc_usb->dma_addr); } static int flexcop_usb_transfer_init(struct flexcop_usb *fc_usb) { - u16 frame_size = le16_to_cpu(fc_usb->uintf->cur_altsetting->endpoint[0].desc.wMaxPacketSize); - int bufsize = B2C2_USB_NUM_ISO_URB * B2C2_USB_FRAMES_PER_ISO * frame_size,i,j,ret; + u16 frame_size = le16_to_cpu( + fc_usb->uintf->cur_altsetting->endpoint[0].desc.wMaxPacketSize); + int bufsize = B2C2_USB_NUM_ISO_URB * B2C2_USB_FRAMES_PER_ISO * + frame_size, i, j, ret; int buffer_offset = 0; - deb_ts("creating %d iso-urbs with %d frames each of %d bytes size = %d.\n", - B2C2_USB_NUM_ISO_URB, B2C2_USB_FRAMES_PER_ISO, frame_size,bufsize); + deb_ts("creating %d iso-urbs with %d frames " + "each of %d bytes size = %d.\n", B2C2_USB_NUM_ISO_URB, + B2C2_USB_FRAMES_PER_ISO, frame_size, bufsize); - fc_usb->iso_buffer = pci_alloc_consistent(NULL,bufsize,&fc_usb->dma_addr); + fc_usb->iso_buffer = pci_alloc_consistent(NULL, + bufsize, &fc_usb->dma_addr); if (fc_usb->iso_buffer == NULL) return -ENOMEM; + memset(fc_usb->iso_buffer, 0, bufsize); fc_usb->buffer_size = bufsize; /* creating iso urbs */ - for (i = 0; i < B2C2_USB_NUM_ISO_URB; i++) - if (!(fc_usb->iso_urb[i] = usb_alloc_urb(B2C2_USB_FRAMES_PER_ISO,GFP_ATOMIC))) { + for (i = 0; i < B2C2_USB_NUM_ISO_URB; i++) { + fc_usb->iso_urb[i] = usb_alloc_urb(B2C2_USB_FRAMES_PER_ISO, + GFP_ATOMIC); + if (fc_usb->iso_urb[i] == NULL) { ret = -ENOMEM; goto urb_error; } + } + /* initialising and submitting iso urbs */ for (i = 0; i < B2C2_USB_NUM_ISO_URB; i++) { int frame_offset = 0; struct urb *urb = fc_usb->iso_urb[i]; - deb_ts("initializing and submitting urb no. %d (buf_offset: %d).\n",i,buffer_offset); + deb_ts("initializing and submitting urb no. %d " + "(buf_offset: %d).\n", i, buffer_offset); urb->dev = fc_usb->udev; urb->context = fc_usb; @@ -420,26 +451,26 @@ static int flexcop_usb_transfer_init(struct flexcop_usb *fc_usb) buffer_offset += frame_size * B2C2_USB_FRAMES_PER_ISO; for (j = 0; j < B2C2_USB_FRAMES_PER_ISO; j++) { - deb_ts("urb no: %d, frame: %d, frame_offset: %d\n",i,j,frame_offset); + deb_ts("urb no: %d, frame: %d, frame_offset: %d\n", + i, j, frame_offset); urb->iso_frame_desc[j].offset = frame_offset; urb->iso_frame_desc[j].length = frame_size; frame_offset += frame_size; } if ((ret = usb_submit_urb(fc_usb->iso_urb[i],GFP_ATOMIC))) { - err("submitting urb %d failed with %d.",i,ret); + err("submitting urb %d failed with %d.", i, ret); goto urb_error; } deb_ts("submitted urb no. %d.\n",i); } -/* SRAM */ - - flexcop_sram_set_dest(fc_usb->fc_dev,FC_SRAM_DEST_MEDIA | FC_SRAM_DEST_NET | - FC_SRAM_DEST_CAO | FC_SRAM_DEST_CAI, FC_SRAM_DEST_TARGET_WAN_USB); - flexcop_wan_set_speed(fc_usb->fc_dev,FC_WAN_SPEED_8MBITS); - flexcop_sram_ctrl(fc_usb->fc_dev,1,1,1); - + /* SRAM */ + flexcop_sram_set_dest(fc_usb->fc_dev, FC_SRAM_DEST_MEDIA | + FC_SRAM_DEST_NET | FC_SRAM_DEST_CAO | FC_SRAM_DEST_CAI, + FC_SRAM_DEST_TARGET_WAN_USB); + flexcop_wan_set_speed(fc_usb->fc_dev, FC_WAN_SPEED_8MBITS); + flexcop_sram_ctrl(fc_usb->fc_dev, 1, 1, 1); return 0; urb_error: @@ -452,20 +483,20 @@ static int flexcop_usb_init(struct flexcop_usb *fc_usb) /* use the alternate setting with the larges buffer */ usb_set_interface(fc_usb->udev,0,1); switch (fc_usb->udev->speed) { - case USB_SPEED_LOW: - err("cannot handle USB speed because it is to sLOW."); - return -ENODEV; - break; - case USB_SPEED_FULL: - info("running at FULL speed."); - break; - case USB_SPEED_HIGH: - info("running at HIGH speed."); - break; - case USB_SPEED_UNKNOWN: /* fall through */ - default: - err("cannot handle USB speed because it is unkown."); - return -ENODEV; + case USB_SPEED_LOW: + err("cannot handle USB speed because it is too slow."); + return -ENODEV; + break; + case USB_SPEED_FULL: + info("running at FULL speed."); + break; + case USB_SPEED_HIGH: + info("running at HIGH speed."); + break; + case USB_SPEED_UNKNOWN: /* fall through */ + default: + err("cannot handle USB speed because it is unknown."); + return -ENODEV; } usb_set_intfdata(fc_usb->uintf, fc_usb); return 0; @@ -489,7 +520,7 @@ static int flexcop_usb_probe(struct usb_interface *intf, return -ENOMEM; } -/* general flexcop init */ + /* general flexcop init */ fc_usb = fc->bus_specific; fc_usb->fc_dev = fc; @@ -506,21 +537,21 @@ static int flexcop_usb_probe(struct usb_interface *intf, fc->dev = &udev->dev; fc->owner = THIS_MODULE; -/* bus specific part */ + /* bus specific part */ fc_usb->udev = udev; fc_usb->uintf = intf; if ((ret = flexcop_usb_init(fc_usb)) != 0) goto err_kfree; -/* init flexcop */ + /* init flexcop */ if ((ret = flexcop_device_initialize(fc)) != 0) goto err_usb_exit; -/* xfer init */ + /* xfer init */ if ((ret = flexcop_usb_transfer_init(fc_usb)) != 0) goto err_fc_exit; - info("%s successfully initialized and connected.",DRIVER_NAME); + info("%s successfully initialized and connected.", DRIVER_NAME); return 0; err_fc_exit: @@ -539,12 +570,12 @@ static void flexcop_usb_disconnect(struct usb_interface *intf) flexcop_device_exit(fc_usb->fc_dev); flexcop_usb_exit(fc_usb); flexcop_device_kfree(fc_usb->fc_dev); - info("%s successfully deinitialized and disconnected.",DRIVER_NAME); + info("%s successfully deinitialized and disconnected.", DRIVER_NAME); } static struct usb_device_id flexcop_usb_table [] = { - { USB_DEVICE(0x0af7, 0x0101) }, - { } + { USB_DEVICE(0x0af7, 0x0101) }, + { } }; MODULE_DEVICE_TABLE (usb, flexcop_usb_table); @@ -561,10 +592,9 @@ static int __init flexcop_usb_module_init(void) { int result; if ((result = usb_register(&flexcop_usb_driver))) { - err("usb_register failed. (%d)",result); + err("usb_register failed. (%d)", result); return result; } - return 0; } -- cgit v1.2.3 From 5f7c983b7de8897ab2f928e0a8183e9c5cf0ad6c Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sun, 29 Mar 2009 13:26:01 +0200 Subject: cx88: convert to v4l2_subdev. From: Hans Verkuil Convert cx88 to use v4l2_subdev since the old i2c autoprobing mechanism will be removed. Added code to explicitly load tvaudio where needed. Also fix the rtc-isl1208 support: since that driver no longer supports autoprobing it has to be loaded using the new i2c API. Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/cx88/cx88-blackbird.c | 4 +-- linux/drivers/media/video/cx88/cx88-cards.c | 40 +++++++++++++++++----- linux/drivers/media/video/cx88/cx88-core.c | 7 ++-- linux/drivers/media/video/cx88/cx88-dvb.c | 2 +- linux/drivers/media/video/cx88/cx88-i2c.c | 39 ++-------------------- linux/drivers/media/video/cx88/cx88-video.c | 44 ++++++++++++++++++------- linux/drivers/media/video/cx88/cx88.h | 14 ++++++-- 7 files changed, 86 insertions(+), 64 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/cx88/cx88-blackbird.c b/linux/drivers/media/video/cx88/cx88-blackbird.c index f1a6f6984..b62eadc71 100644 --- a/linux/drivers/media/video/cx88/cx88-blackbird.c +++ b/linux/drivers/media/video/cx88/cx88-blackbird.c @@ -934,7 +934,7 @@ static int vidioc_log_status (struct file *file, void *priv) snprintf(name, sizeof(name), "%s/2", core->name); printk("%s/2: ============ START LOG STATUS ============\n", core->name); - cx88_call_i2c_clients(core, VIDIOC_LOG_STATUS, NULL); + call_all(core, core, log_status); cx2341x_log_status(&dev->params, name); printk("%s/2: ============= END LOG STATUS =============\n", core->name); @@ -989,7 +989,7 @@ static int vidioc_g_frequency (struct file *file, void *priv, f->type = V4L2_TUNER_ANALOG_TV; f->frequency = core->freq; - cx88_call_i2c_clients(core,VIDIOC_G_FREQUENCY,f); + call_all(core, tuner, g_frequency, f); return 0; } diff --git a/linux/drivers/media/video/cx88/cx88-cards.c b/linux/drivers/media/video/cx88/cx88-cards.c index 2f30d34be..df9e99a3b 100644 --- a/linux/drivers/media/video/cx88/cx88-cards.c +++ b/linux/drivers/media/video/cx88/cx88-cards.c @@ -733,6 +733,8 @@ static const struct cx88_board cx88_boards[] = { .radio_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, + /* Some variants use a tda9874 and so need the tvaudio module. */ + .audio_chip = V4L2_IDENT_TVAUDIO, .input = {{ .type = CX88_VMUX_TELEVISION, .vmux = 0, @@ -3018,7 +3020,7 @@ static void cx88_card_setup(struct cx88_core *core) tea5767_cfg.tuner = TUNER_TEA5767; tea5767_cfg.priv = &ctl; - cx88_call_i2c_clients(core, TUNER_SET_CONFIG, &tea5767_cfg); + call_all(core, tuner, s_config, &tea5767_cfg); break; } case CX88_BOARD_TEVII_S420: @@ -3043,7 +3045,7 @@ static void cx88_card_setup(struct cx88_core *core) tun_setup.type = core->board.radio_type; tun_setup.addr = core->board.radio_addr; tun_setup.tuner_callback = cx88_tuner_callback; - cx88_call_i2c_clients(core, TUNER_SET_TYPE_ADDR, &tun_setup); + call_all(core, tuner, s_type_addr, &tun_setup); mode_mask &= ~T_RADIO; } @@ -3053,7 +3055,7 @@ static void cx88_card_setup(struct cx88_core *core) tun_setup.addr = core->board.tuner_addr; tun_setup.tuner_callback = cx88_tuner_callback; - cx88_call_i2c_clients(core, TUNER_SET_TYPE_ADDR, &tun_setup); + call_all(core, tuner, s_type_addr, &tun_setup); } if (core->board.tda9887_conf) { @@ -3062,7 +3064,7 @@ static void cx88_card_setup(struct cx88_core *core) tda9887_cfg.tuner = TUNER_TDA9887; tda9887_cfg.priv = &core->board.tda9887_conf; - cx88_call_i2c_clients(core, TUNER_SET_CONFIG, &tda9887_cfg); + call_all(core, tuner, s_config, &tda9887_cfg); } if (core->board.tuner_type == TUNER_XC2028) { @@ -3078,9 +3080,9 @@ static void cx88_card_setup(struct cx88_core *core) xc2028_cfg.priv = &ctl; info_printk(core, "Asking xc2028/3028 to load firmware %s\n", ctl.fname); - cx88_call_i2c_clients(core, TUNER_SET_CONFIG, &xc2028_cfg); + call_all(core, tuner, s_config, &xc2028_cfg); } - cx88_call_i2c_clients (core, TUNER_SET_STANDBY, NULL); + call_all(core, core, s_standby, 0); } /* ------------------------------------------------------------------ */ @@ -3235,8 +3237,30 @@ struct cx88_core *cx88_core_create(struct pci_dev *pci, int nr) cx88_i2c_init(core, pci); /* load tuner module, if needed */ - if (TUNER_ABSENT != core->board.tuner_type) - request_module("tuner"); + if (TUNER_ABSENT != core->board.tuner_type) { + int has_demod = (core->board.tda9887_conf & TDA9887_PRESENT); + + /* I don't trust the radio_type as is stored in the card + definitions, so we just probe for it. + The radio_type is sometimes missing, or set to UNSET but + later code configures a tea5767. + */ + v4l2_i2c_new_probed_subdev(&core->i2c_adap, "tuner", "tuner", + v4l2_i2c_tuner_addrs(ADDRS_RADIO)); + if (has_demod) + v4l2_i2c_new_probed_subdev(&core->i2c_adap, "tuner", + "tuner", v4l2_i2c_tuner_addrs(ADDRS_DEMOD)); + if (core->board.tuner_addr == ADDR_UNSET) { + enum v4l2_i2c_tuner_type type = + has_demod ? ADDRS_TV_WITH_DEMOD : ADDRS_TV; + + v4l2_i2c_new_probed_subdev(&core->i2c_adap, "tuner", + "tuner", v4l2_i2c_tuner_addrs(type)); + } else { + v4l2_i2c_new_subdev(&core->i2c_adap, + "tuner", "tuner", core->board.tuner_addr); + } + } cx88_card_setup(core); cx88_ir_init(core, pci); diff --git a/linux/drivers/media/video/cx88/cx88-core.c b/linux/drivers/media/video/cx88/cx88-core.c index ca36a48fa..ceaedf352 100644 --- a/linux/drivers/media/video/cx88/cx88-core.c +++ b/linux/drivers/media/video/cx88/cx88-core.c @@ -1020,7 +1020,7 @@ int cx88_set_tvnorm(struct cx88_core *core, v4l2_std_id norm) set_tvaudio(core); // tell i2c chips - cx88_call_i2c_clients(core,VIDIOC_S_STD,&norm); + call_all(core, tuner, s_std, norm); // done return 0; @@ -1088,8 +1088,11 @@ void cx88_core_put(struct cx88_core *core, struct pci_dev *pci) mutex_lock(&devlist); cx88_ir_fini(core); - if (0 == core->i2c_rc) + if (0 == core->i2c_rc) { + if (core->i2c_rtc) + i2c_unregister_device(core->i2c_rtc); i2c_del_adapter(&core->i2c_adap); + } list_del(&core->devlist); iounmap(core->lmmio); cx88_devcount--; diff --git a/linux/drivers/media/video/cx88/cx88-dvb.c b/linux/drivers/media/video/cx88/cx88-dvb.c index 10cf470ce..3de497312 100644 --- a/linux/drivers/media/video/cx88/cx88-dvb.c +++ b/linux/drivers/media/video/cx88/cx88-dvb.c @@ -1175,7 +1175,7 @@ static int dvb_register(struct cx8802_dev *dev) fe1->dvb.frontend->ops.ts_bus_ctrl = cx88_dvb_bus_ctrl; /* Put the analog decoder in standby to keep it quiet */ - cx88_call_i2c_clients(core, TUNER_SET_STANDBY, NULL); + call_all(core, core, s_standby, 0); /* register everything */ return videobuf_dvb_register_bus(&dev->frontends, THIS_MODULE, dev, diff --git a/linux/drivers/media/video/cx88/cx88-i2c.c b/linux/drivers/media/video/cx88/cx88-i2c.c index 4a17a7579..718f1ce69 100644 --- a/linux/drivers/media/video/cx88/cx88-i2c.c +++ b/linux/drivers/media/video/cx88/cx88-i2c.c @@ -97,39 +97,6 @@ static int cx8800_bit_getsda(void *data) /* ----------------------------------------------------------------------- */ -static int attach_inform(struct i2c_client *client) -{ - struct v4l2_device *v4l2_dev = i2c_get_adapdata(client->adapter); - struct cx88_core *core = to_core(v4l2_dev); - - dprintk(1, "%s i2c attach [addr=0x%x,client=%s]\n", - client->driver->driver.name, client->addr, client->name); - return 0; -} - -static int detach_inform(struct i2c_client *client) -{ - struct v4l2_device *v4l2_dev = i2c_get_adapdata(client->adapter); - struct cx88_core *core = to_core(v4l2_dev); - - dprintk(1, "i2c detach [client=%s]\n", client->name); - return 0; -} - -void cx88_call_i2c_clients(struct cx88_core *core, unsigned int cmd, void *arg) -{ - if (0 != core->i2c_rc) - return; - - if (core->gate_ctrl) - core->gate_ctrl(core, 1); - - i2c_clients_command(&core->i2c_adap, cmd, arg); - - if (core->gate_ctrl) - core->gate_ctrl(core, 0); -} - static const struct i2c_algo_bit_data cx8800_i2c_algo_template = { .setsda = cx8800_bit_setsda, .setscl = cx8800_bit_setscl, @@ -175,17 +142,17 @@ int cx88_i2c_init(struct cx88_core *core, struct pci_dev *pci) memcpy(&core->i2c_algo, &cx8800_i2c_algo_template, sizeof(core->i2c_algo)); +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22) if (core->board.tuner_type != TUNER_ABSENT) core->i2c_adap.class |= I2C_CLASS_TV_ANALOG; if (core->board.mpeg & CX88_MPEG_DVB) core->i2c_adap.class |= I2C_CLASS_TV_DIGITAL; +#endif core->i2c_adap.dev.parent = &pci->dev; strlcpy(core->i2c_adap.name,core->name,sizeof(core->i2c_adap.name)); core->i2c_adap.owner = THIS_MODULE; core->i2c_adap.id = I2C_HW_B_CX2388x; - core->i2c_adap.client_register = attach_inform; - core->i2c_adap.client_unregister = detach_inform; core->i2c_algo.udelay = i2c_udelay; core->i2c_algo.data = core; i2c_set_adapdata(&core->i2c_adap, &core->v4l2_dev); @@ -224,8 +191,6 @@ int cx88_i2c_init(struct cx88_core *core, struct pci_dev *pci) /* ----------------------------------------------------------------------- */ -EXPORT_SYMBOL(cx88_call_i2c_clients); - /* * Local variables: * c-basic-offset: 8 diff --git a/linux/drivers/media/video/cx88/cx88-video.c b/linux/drivers/media/video/cx88/cx88-video.c index 827168d67..ea3920c8a 100644 --- a/linux/drivers/media/video/cx88/cx88-video.c +++ b/linux/drivers/media/video/cx88/cx88-video.c @@ -432,8 +432,7 @@ int cx88_video_mux(struct cx88_core *core, unsigned int input) struct v4l2_routing route; route.input = INPUT(input).audioroute; - cx88_call_i2c_clients(core, - VIDIOC_INT_S_AUDIO_ROUTING, &route); + call_all(core, audio, s_routing, &route); } /* cx2388's C-ADC is connected to the tuner only. When used with S-Video, that ADC is busy dealing with @@ -1053,8 +1052,7 @@ static int video_open(struct file *file) struct v4l2_routing route; route.input = core->board.radio.audioroute; - cx88_call_i2c_clients(core, - VIDIOC_INT_S_AUDIO_ROUTING, &route); + call_all(core, audio, s_routing, &route); } /* "I2S ADC mode" */ core->tvaudio = WW_I2SADC; @@ -1065,7 +1063,7 @@ static int video_open(struct file *file) cx88_set_tvaudio(core); cx88_set_stereo(core,V4L2_TUNER_MODE_STEREO,1); } - cx88_call_i2c_clients(core,AUDC_SET_RADIO,NULL); + call_all(core, tuner, s_radio); } unlock_kernel(); @@ -1159,7 +1157,7 @@ static int video_release(struct file *file) kfree(fh); if(atomic_dec_and_test(&dev->core->users)) - cx88_call_i2c_clients (dev->core, TUNER_SET_STANDBY, NULL); + call_all(dev->core, core, s_standby, 0); return 0; } @@ -1661,7 +1659,7 @@ static int vidioc_g_frequency (struct file *file, void *priv, f->type = fh->radio ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV; f->frequency = core->freq; - cx88_call_i2c_clients(core,VIDIOC_G_FREQUENCY,f); + call_all(core, tuner, g_frequency, f); return 0; } @@ -1677,7 +1675,7 @@ int cx88_set_freq (struct cx88_core *core, mutex_lock(&core->lock); core->freq = f->frequency; cx88_newstation(core); - cx88_call_i2c_clients(core,VIDIOC_S_FREQUENCY,f); + call_all(core, tuner, s_frequency, f); /* When changing channels it is required to reset TVAUDIO */ msleep (10); @@ -1759,7 +1757,7 @@ static int radio_g_tuner (struct file *file, void *priv, strcpy(t->name, "Radio"); t->type = V4L2_TUNER_RADIO; - cx88_call_i2c_clients(core,VIDIOC_G_TUNER,t); + call_all(core, tuner, g_tuner, t); return 0; } @@ -1793,7 +1791,7 @@ static int radio_s_tuner (struct file *file, void *priv, if (0 != t->index) return -EINVAL; - cx88_call_i2c_clients(core,VIDIOC_S_TUNER,t); + call_all(core, tuner, s_tuner, t); return 0; } @@ -2158,12 +2156,34 @@ static int __devinit cx8800_initdev(struct pci_dev *pci_dev, /* load and configure helper modules */ if (core->board.audio_chip == V4L2_IDENT_WM8775) - request_module("wm8775"); + v4l2_i2c_new_subdev(&core->i2c_adap, + "wm8775", "wm8775", 0x36 >> 1); + + if (core->board.audio_chip == V4L2_IDENT_TVAUDIO) { + /* This probes for a tda9874 as is used on some + Pixelview Ultra boards. */ + static const unsigned short i2c_addr[] = { + 0xb0 >> 1, I2C_CLIENT_END + }; + + v4l2_i2c_new_probed_subdev(&core->i2c_adap, + "tvaudio", "tvaudio", i2c_addr); + } switch (core->boardnr) { case CX88_BOARD_DVICO_FUSIONHDTV_5_GOLD: - case CX88_BOARD_DVICO_FUSIONHDTV_7_GOLD: + case CX88_BOARD_DVICO_FUSIONHDTV_7_GOLD: { +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 22) + static struct i2c_board_info rtc_info = { + I2C_BOARD_INFO("isl1208", 0x6f) + }; + request_module("rtc-isl1208"); + core->i2c_rtc = i2c_new_device(&core->i2c_adap, &rtc_info); +#else + request_module("rtc-isl1208"); +#endif + } /* break intentionally omitted */ case CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO: request_module("ir-kbd-i2c"); diff --git a/linux/drivers/media/video/cx88/cx88.h b/linux/drivers/media/video/cx88/cx88.h index d70e26000..e7fbe8aea 100644 --- a/linux/drivers/media/video/cx88/cx88.h +++ b/linux/drivers/media/video/cx88/cx88.h @@ -332,6 +332,7 @@ struct cx88_core { /* config info -- analog */ struct v4l2_device v4l2_dev; + struct i2c_client *i2c_rtc; unsigned int boardnr; struct cx88_board board; @@ -375,6 +376,17 @@ static inline struct cx88_core *to_core(struct v4l2_device *v4l2_dev) return container_of(v4l2_dev, struct cx88_core, v4l2_dev); } +#define call_all(core, o, f, args...) \ + do { \ + if (!core->i2c_rc) { \ + if (core->gate_ctrl) \ + core->gate_ctrl(core, 1); \ + v4l2_device_call_all(&core->v4l2_dev, 0, o, f, ##args); \ + if (core->gate_ctrl) \ + core->gate_ctrl(core, 0); \ + } \ + } while (0) + struct cx8800_dev; struct cx8802_dev; @@ -637,8 +649,6 @@ extern struct videobuf_queue_ops cx8800_vbi_qops; /* cx88-i2c.c */ extern int cx88_i2c_init(struct cx88_core *core, struct pci_dev *pci); -extern void cx88_call_i2c_clients(struct cx88_core *core, - unsigned int cmd, void *arg); /* ----------------------------------------------------------- */ -- cgit v1.2.3 From ad5e78a7b1caf2e54f4ca0f3009152c4aaa03837 Mon Sep 17 00:00:00 2001 From: Patrick Boettcher Date: Sun, 29 Mar 2009 13:43:36 +0200 Subject: Patch for Yuan MC770 DVB-T (1164:0871) From: Xoan Loureiro This patch adds support for the Yuan MC770 DVB-T (1164:0871). Thanks to Xoan Loureiro. Priority: normal Signed-off-by: Xoan Loureiro Signed-off-by: Patrick Boettcher --- linux/drivers/media/dvb/dvb-usb/dib0700_devices.c | 7 ++++++- linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h | 1 + 2 files changed, 7 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 d8901f7a8..f0f98529d 100644 --- a/linux/drivers/media/dvb/dvb-usb/dib0700_devices.c +++ b/linux/drivers/media/dvb/dvb-usb/dib0700_devices.c @@ -1495,6 +1495,7 @@ struct usb_device_id dib0700_usb_id_table[] = { /* 45 */{ USB_DEVICE(USB_VID_YUAN, USB_PID_YUAN_PD378S) }, { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_TIGER_ATSC) }, { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_TIGER_ATSC_B210) }, + { USB_DEVICE(USB_VID_YUAN, USB_PID_YUAN_MC770) }, { 0 } /* Terminating entry */ }; MODULE_DEVICE_TABLE(usb, dib0700_usb_id_table); @@ -1810,7 +1811,7 @@ struct dvb_usb_device_properties dib0700_devices[] = { }, }, - .num_device_descs = 5, + .num_device_descs = 7, .devices = { { "Terratec Cinergy HT USB XE", { &dib0700_usb_id_table[27], NULL }, @@ -1836,6 +1837,10 @@ struct dvb_usb_device_properties dib0700_devices[] = { { &dib0700_usb_id_table[39], NULL }, { NULL }, }, + { "YUAN High-Tech MC770", + { &dib0700_usb_id_table[48], 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 0f239c668..138ce1b5c 100644 --- a/linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h +++ b/linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h @@ -239,6 +239,7 @@ #define USB_PID_YUAN_EC372S 0x1edc #define USB_PID_YUAN_STK7700PH 0x1f08 #define USB_PID_YUAN_PD378S 0x2edc +#define USB_PID_YUAN_MC770 0x0871 #define USB_PID_DW2102 0x2102 #define USB_PID_XTENSIONS_XD_380 0x0381 #define USB_PID_TELESTAR_STARSTICK_2 0x8000 -- cgit v1.2.3 From a69ef6ced83ca94674cf71a79f21116066a10562 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sun, 29 Mar 2009 13:50:31 +0200 Subject: wm8775: remove legacy code for old-style i2c API From: Hans Verkuil All drivers that use wm8775 are now converted to v4l2_subdev, so I can remove the support for the old-style i2c API. Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/wm8775.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/wm8775.c b/linux/drivers/media/video/wm8775.c index 3140c1313..bd4729d13 100644 --- a/linux/drivers/media/video/wm8775.c +++ b/linux/drivers/media/video/wm8775.c @@ -34,16 +34,18 @@ #include #include #include -#include +#include #include "compat.h" MODULE_DESCRIPTION("wm8775 driver"); MODULE_AUTHOR("Ulf Eklund, Hans Verkuil"); MODULE_LICENSE("GPL"); +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22) static unsigned short normal_i2c[] = { 0x36 >> 1, I2C_CLIENT_END }; I2C_CLIENT_INSMOD; +#endif /* ----------------------------------------------------------------------- */ @@ -162,11 +164,6 @@ static int wm8775_s_frequency(struct v4l2_subdev *sd, struct v4l2_frequency *fre return 0; } -static int wm8775_command(struct i2c_client *client, unsigned cmd, void *arg) -{ - return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg); -} - /* ----------------------------------------------------------------------- */ static const struct v4l2_subdev_core_ops wm8775_core_ops = { @@ -271,8 +268,6 @@ MODULE_DEVICE_TABLE(i2c, wm8775_id); #endif static struct v4l2_i2c_driver_data v4l2_i2c_data = { .name = "wm8775", - .driverid = I2C_DRIVERID_WM8775, - .command = wm8775_command, .probe = wm8775_probe, .remove = wm8775_remove, #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) -- cgit v1.2.3 From 341276db860080bc5939fe2554bf9fd3f8a81969 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sun, 29 Mar 2009 13:55:46 +0200 Subject: cx25840: remove legacy code for old-style i2c API From: Hans Verkuil All drivers that use cx25840 are now converted to v4l2_subdev, so I can remove the support for the old-style i2c API. Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/cx25840/cx25840-core.c | 23 +++++------------------ 1 file changed, 5 insertions(+), 18 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/cx25840/cx25840-core.c b/linux/drivers/media/video/cx25840/cx25840-core.c index 5387a846f..6b55cd94b 100644 --- a/linux/drivers/media/video/cx25840/cx25840-core.c +++ b/linux/drivers/media/video/cx25840/cx25840-core.c @@ -39,7 +39,7 @@ #include #include #include -#include +#include #include #include "compat.h" @@ -49,15 +49,17 @@ MODULE_DESCRIPTION("Conexant CX25840 audio/video decoder driver"); MODULE_AUTHOR("Ulf Eklund, Chris Kennedy, Hans Verkuil, Tyler Trafford"); MODULE_LICENSE("GPL"); -static unsigned short normal_i2c[] = { 0x88 >> 1, I2C_CLIENT_END }; - static int cx25840_debug; module_param_named(debug,cx25840_debug, int, 0644); MODULE_PARM_DESC(debug, "Debugging messages [0=Off (default) 1=On]"); +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22) +static unsigned short normal_i2c[] = { 0x88 >> 1, I2C_CLIENT_END }; + I2C_CLIENT_INSMOD; +#endif /* ----------------------------------------------------------------------- */ @@ -1510,19 +1512,6 @@ static int cx25840_log_status(struct v4l2_subdev *sd) return 0; } -static int cx25840_command(struct i2c_client *client, unsigned cmd, void *arg) -{ - /* ignore this command */ - if (cmd == TUNER_SET_TYPE_ADDR || cmd == TUNER_SET_CONFIG) - return 0; - - /* Old-style drivers rely on initialization on first use, so - call the init whenever a command is issued to this driver. - New-style drivers using v4l2_subdev should call init explicitly. */ - cx25840_init(i2c_get_clientdata(client), 0); - return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg); -} - /* ----------------------------------------------------------------------- */ static const struct v4l2_subdev_core_ops cx25840_core_ops = { @@ -1663,8 +1652,6 @@ MODULE_DEVICE_TABLE(i2c, cx25840_id); #endif static struct v4l2_i2c_driver_data v4l2_i2c_data = { .name = "cx25840", - .driverid = I2C_DRIVERID_CX25840, - .command = cx25840_command, .probe = cx25840_probe, .remove = cx25840_remove, #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) -- cgit v1.2.3 From adfc39503d204c842da3fd2768ab84d524b7ef31 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sun, 29 Mar 2009 14:04:29 +0200 Subject: tda9875: remove legacy code for old-style i2c API From: Hans Verkuil tda9875 is no longer used with the old-style i2c API, so I can remove the support for that. Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/tda9875.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/tda9875.c b/linux/drivers/media/video/tda9875.c index 938bafbbd..0351b13db 100644 --- a/linux/drivers/media/video/tda9875.c +++ b/linux/drivers/media/video/tda9875.c @@ -28,7 +28,7 @@ #include #include #include -#include +#include #include #include "compat.h" @@ -36,6 +36,7 @@ static int debug; /* insmod parameter */ module_param(debug, int, S_IRUGO | S_IWUSR); MODULE_LICENSE("GPL"); +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22) /* Addresses to scan */ static unsigned short normal_i2c[] = { I2C_ADDR_TDA9875 >> 1, @@ -43,6 +44,7 @@ static unsigned short normal_i2c[] = { }; I2C_CLIENT_INSMOD; +#endif /* This is a superset of the TDA9875 */ struct tda9875 { @@ -335,11 +337,6 @@ static int tda9875_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc) return -EINVAL; } -static int tda9875_command(struct i2c_client *client, unsigned cmd, void *arg) -{ - return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg); -} - /* ----------------------------------------------------------------------- */ static const struct v4l2_subdev_core_ops tda9875_core_ops = { @@ -418,7 +415,6 @@ MODULE_DEVICE_TABLE(i2c, tda9875_id); #endif static struct v4l2_i2c_driver_data v4l2_i2c_data = { .name = "tda9875", - .command = tda9875_command, .probe = tda9875_probe, .remove = tda9875_remove, #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) -- cgit v1.2.3 From 9e598e510ff2438c06c4c60c910becea4838294b Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sun, 29 Mar 2009 14:06:00 +0200 Subject: tda7432: remove legacy code for old-style i2c API From: Hans Verkuil tda7432 is no longer used with the old-style i2c API, so I can remove the support for that. Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/tda7432.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/tda7432.c b/linux/drivers/media/video/tda7432.c index 104fc4246..07c21a6d7 100644 --- a/linux/drivers/media/video/tda7432.c +++ b/linux/drivers/media/video/tda7432.c @@ -50,7 +50,7 @@ #include #include #include -#include +#include #include "compat.h" #ifndef VIDEO_AUDIO_BALANCE @@ -70,6 +70,7 @@ MODULE_PARM_DESC(maxvol,"Set maximium volume to +20db (0), default is 0db(1)"); module_param(maxvol, int, S_IRUGO | S_IWUSR); +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22) /* Address to scan (I2C address of this chip) */ static unsigned short normal_i2c[] = { I2C_ADDR_TDA7432 >> 1, @@ -77,6 +78,7 @@ static unsigned short normal_i2c[] = { }; I2C_CLIENT_INSMOD; +#endif /* Structure of address and subaddresses for the tda7432 */ @@ -434,11 +436,6 @@ static int tda7432_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc) return -EINVAL; } -static int tda7432_command(struct i2c_client *client, unsigned cmd, void *arg) -{ - return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg); -} - /* ----------------------------------------------------------------------- */ static const struct v4l2_subdev_core_ops tda7432_core_ops = { @@ -503,7 +500,6 @@ MODULE_DEVICE_TABLE(i2c, tda7432_id); #endif static struct v4l2_i2c_driver_data v4l2_i2c_data = { .name = "tda7432", - .command = tda7432_command, .probe = tda7432_probe, .remove = tda7432_remove, #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) -- cgit v1.2.3 From df3d6b341372341ba57dc1ea30ef6059bc24d088 Mon Sep 17 00:00:00 2001 From: Patrick Boettcher Date: Sun, 29 Mar 2009 14:12:06 +0200 Subject: Add Elgato EyeTV DTT to dibcom driver From: Klaus Flittner This patch introduces support for DVB-T for the following dibcom based card: Elgato EyeTV DTT (USB-ID: 0fd9:0021) Priority: normal Signed-off-by: Klaus Flittner Signed-off-by: Patrick Boettcher --- linux/drivers/media/dvb/dvb-usb/dib0700_devices.c | 7 ++++++- linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h | 4 +++- linux/drivers/media/dvb/dvb-usb/dvb-usb.h | 2 +- 3 files changed, 10 insertions(+), 3 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 f0f98529d..31fe6e10a 100644 --- a/linux/drivers/media/dvb/dvb-usb/dib0700_devices.c +++ b/linux/drivers/media/dvb/dvb-usb/dib0700_devices.c @@ -1496,6 +1496,7 @@ struct usb_device_id dib0700_usb_id_table[] = { { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_TIGER_ATSC) }, { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_TIGER_ATSC_B210) }, { USB_DEVICE(USB_VID_YUAN, USB_PID_YUAN_MC770) }, + { USB_DEVICE(USB_VID_ELGATO, USB_PID_ELGATO_EYETV_DTT) }, { 0 } /* Terminating entry */ }; MODULE_DEVICE_TABLE(usb, dib0700_usb_id_table); @@ -1695,7 +1696,7 @@ struct dvb_usb_device_properties dib0700_devices[] = { }, }, - .num_device_descs = 10, + .num_device_descs = 11, .devices = { { "DiBcom STK7070P reference design", { &dib0700_usb_id_table[15], NULL }, @@ -1733,6 +1734,10 @@ struct dvb_usb_device_properties dib0700_devices[] = { { &dib0700_usb_id_table[33], NULL }, { NULL }, }, + { "Elgato EyeTV DTT", + { &dib0700_usb_id_table[49], NULL }, + { NULL }, + }, { "Yuan PD378S", { &dib0700_usb_id_table[45], NULL }, { NULL }, 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 138ce1b5c..dc7ea21cd 100644 --- a/linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h +++ b/linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h @@ -27,6 +27,7 @@ #define USB_VID_DIBCOM 0x10b8 #define USB_VID_DPOSH 0x1498 #define USB_VID_DVICO 0x0fe9 +#define USB_VID_ELGATO 0x0fd9 #define USB_VID_EMPIA 0xeb1a #define USB_VID_GENPIX 0x09c0 #define USB_VID_GRANDTEC 0x5032 @@ -49,6 +50,7 @@ #define USB_VID_TERRATEC 0x0ccd #define USB_VID_TELESTAR 0x10b9 #define USB_VID_VISIONPLUS 0x13d3 +#define USB_VID_SONY 0x1415 #define USB_VID_TWINHAN 0x1822 #define USB_VID_ULTIMA_ELECTRONIC 0x05d8 #define USB_VID_UNIWILL 0x1584 @@ -56,7 +58,6 @@ #define USB_VID_GIGABYTE 0x1044 #define USB_VID_YUAN 0x1164 #define USB_VID_XTENSIONS 0x1ae7 -#define USB_VID_SONY 0x1415 /* Product IDs */ #define USB_PID_ADSTECH_USB2_COLD 0xa333 @@ -245,5 +246,6 @@ #define USB_PID_TELESTAR_STARSTICK_2 0x8000 #define USB_PID_MSI_DIGI_VOX_MINI_III 0x8807 #define USB_PID_SONY_PLAYTV 0x0003 +#define USB_PID_ELGATO_EYETV_DTT 0x0021 #endif diff --git a/linux/drivers/media/dvb/dvb-usb/dvb-usb.h b/linux/drivers/media/dvb/dvb-usb/dvb-usb.h index 081550761..fd64daa06 100644 --- a/linux/drivers/media/dvb/dvb-usb/dvb-usb.h +++ b/linux/drivers/media/dvb/dvb-usb/dvb-usb.h @@ -224,7 +224,7 @@ struct dvb_usb_device_properties { int generic_bulk_ctrl_endpoint; int num_device_descs; - struct dvb_usb_device_description devices[10]; + struct dvb_usb_device_description devices[11]; }; /** -- cgit v1.2.3 From fbb7db73536826892676fe88068fa7f508744923 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sun, 29 Mar 2009 14:19:09 +0200 Subject: v4l2: remove v4l2_subdev_command calls where they are no longer needed. From: Hans Verkuil Several i2c drivers still used v4l2_subdev_command, even though they were converted to v4l2_subdev. Remove those unused .command callbacks. Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/cs5345.c | 7 ------- linux/drivers/media/video/m52790.c | 6 ------ linux/drivers/media/video/ovcamchip/ovcamchip_core.c | 6 ------ linux/drivers/media/video/saa717x.c | 7 ------- linux/drivers/media/video/tlv320aic23b.c | 6 ------ linux/drivers/media/video/upd64031a.c | 6 ------ linux/drivers/media/video/upd64083.c | 6 ------ linux/drivers/media/video/vp27smpx.c | 6 ------ linux/drivers/media/video/wm8739.c | 6 ------ 9 files changed, 56 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/cs5345.c b/linux/drivers/media/video/cs5345.c index 31d6c4aa4..3e018b558 100644 --- a/linux/drivers/media/video/cs5345.c +++ b/linux/drivers/media/video/cs5345.c @@ -147,11 +147,6 @@ static int cs5345_log_status(struct v4l2_subdev *sd) return 0; } -static int cs5345_command(struct i2c_client *client, unsigned cmd, void *arg) -{ - return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg); -} - /* ----------------------------------------------------------------------- */ static const struct v4l2_subdev_core_ops cs5345_core_ops = { @@ -222,8 +217,6 @@ MODULE_DEVICE_TABLE(i2c, cs5345_id); #endif static struct v4l2_i2c_driver_data v4l2_i2c_data = { .name = "cs5345", - .driverid = I2C_DRIVERID_CS5345, - .command = cs5345_command, .probe = cs5345_probe, .remove = cs5345_remove, #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) diff --git a/linux/drivers/media/video/m52790.c b/linux/drivers/media/video/m52790.c index 982ab4268..203a60348 100644 --- a/linux/drivers/media/video/m52790.c +++ b/linux/drivers/media/video/m52790.c @@ -138,11 +138,6 @@ static int m52790_log_status(struct v4l2_subdev *sd) return 0; } -static int m52790_command(struct i2c_client *client, unsigned cmd, void *arg) -{ - return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg); -} - /* ----------------------------------------------------------------------- */ static const struct v4l2_subdev_core_ops m52790_core_ops = { @@ -222,7 +217,6 @@ MODULE_DEVICE_TABLE(i2c, m52790_id); #endif static struct v4l2_i2c_driver_data v4l2_i2c_data = { .name = "m52790", - .command = m52790_command, .probe = m52790_probe, .remove = m52790_remove, #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) diff --git a/linux/drivers/media/video/ovcamchip/ovcamchip_core.c b/linux/drivers/media/video/ovcamchip/ovcamchip_core.c index 63303b70f..8de129b41 100644 --- a/linux/drivers/media/video/ovcamchip/ovcamchip_core.c +++ b/linux/drivers/media/video/ovcamchip/ovcamchip_core.c @@ -335,11 +335,6 @@ static long ovcamchip_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) } } -static int ovcamchip_command(struct i2c_client *client, unsigned cmd, void *arg) -{ - return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg); -} - /* ----------------------------------------------------------------------- */ static const struct v4l2_subdev_core_ops ovcamchip_core_ops = { @@ -409,7 +404,6 @@ MODULE_DEVICE_TABLE(i2c, ovcamchip_id); #endif static struct v4l2_i2c_driver_data v4l2_i2c_data = { .name = "ovcamchip", - .command = ovcamchip_command, .probe = ovcamchip_probe, .remove = ovcamchip_remove, #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) diff --git a/linux/drivers/media/video/saa717x.c b/linux/drivers/media/video/saa717x.c index 3ad43f6b3..ae8fcde9d 100644 --- a/linux/drivers/media/video/saa717x.c +++ b/linux/drivers/media/video/saa717x.c @@ -1386,11 +1386,6 @@ static int saa717x_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt) return 0; } -static int saa717x_command(struct i2c_client *client, unsigned cmd, void *arg) -{ - return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg); -} - /* ----------------------------------------------------------------------- */ static const struct v4l2_subdev_core_ops saa717x_core_ops = { @@ -1539,10 +1534,8 @@ MODULE_DEVICE_TABLE(i2c, saa717x_id); #endif static struct v4l2_i2c_driver_data v4l2_i2c_data = { .name = "saa717x", - .command = saa717x_command, .probe = saa717x_probe, .remove = saa717x_remove, - .legacy_class = I2C_CLASS_TV_ANALOG | I2C_CLASS_TV_DIGITAL, #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) .id_table = saa717x_id, #endif diff --git a/linux/drivers/media/video/tlv320aic23b.c b/linux/drivers/media/video/tlv320aic23b.c index 1eac4f7e7..bfba9ac0d 100644 --- a/linux/drivers/media/video/tlv320aic23b.c +++ b/linux/drivers/media/video/tlv320aic23b.c @@ -124,11 +124,6 @@ static int tlv320aic23b_log_status(struct v4l2_subdev *sd) return 0; } -static int tlv320aic23b_command(struct i2c_client *client, unsigned cmd, void *arg) -{ - return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg); -} - /* ----------------------------------------------------------------------- */ static const struct v4l2_subdev_core_ops tlv320aic23b_core_ops = { @@ -213,7 +208,6 @@ MODULE_DEVICE_TABLE(i2c, tlv320aic23b_id); static struct v4l2_i2c_driver_data v4l2_i2c_data = { .name = "tlv320aic23b", - .command = tlv320aic23b_command, .probe = tlv320aic23b_probe, .remove = tlv320aic23b_remove, #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) diff --git a/linux/drivers/media/video/upd64031a.c b/linux/drivers/media/video/upd64031a.c index 0fd1c9312..0d7f37a9e 100644 --- a/linux/drivers/media/video/upd64031a.c +++ b/linux/drivers/media/video/upd64031a.c @@ -193,11 +193,6 @@ static int upd64031a_s_register(struct v4l2_subdev *sd, struct v4l2_dbg_register } #endif -static int upd64031a_command(struct i2c_client *client, unsigned cmd, void *arg) -{ - return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg); -} - /* ----------------------------------------------------------------------- */ static const struct v4l2_subdev_core_ops upd64031a_core_ops = { @@ -275,7 +270,6 @@ MODULE_DEVICE_TABLE(i2c, upd64031a_id); static struct v4l2_i2c_driver_data v4l2_i2c_data = { .name = "upd64031a", - .command = upd64031a_command, .probe = upd64031a_probe, .remove = upd64031a_remove, #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) diff --git a/linux/drivers/media/video/upd64083.c b/linux/drivers/media/video/upd64083.c index aed167493..fdedc41ef 100644 --- a/linux/drivers/media/video/upd64083.c +++ b/linux/drivers/media/video/upd64083.c @@ -170,11 +170,6 @@ static int upd64083_log_status(struct v4l2_subdev *sd) return 0; } -static int upd64083_command(struct i2c_client *client, unsigned cmd, void *arg) -{ - return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg); -} - /* ----------------------------------------------------------------------- */ static const struct v4l2_subdev_core_ops upd64083_core_ops = { @@ -247,7 +242,6 @@ MODULE_DEVICE_TABLE(i2c, upd64083_id); static struct v4l2_i2c_driver_data v4l2_i2c_data = { .name = "upd64083", - .command = upd64083_command, .probe = upd64083_probe, .remove = upd64083_remove, #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) diff --git a/linux/drivers/media/video/vp27smpx.c b/linux/drivers/media/video/vp27smpx.c index 3104d0e1f..be046e961 100644 --- a/linux/drivers/media/video/vp27smpx.c +++ b/linux/drivers/media/video/vp27smpx.c @@ -135,11 +135,6 @@ static int vp27smpx_log_status(struct v4l2_subdev *sd) return 0; } -static int vp27smpx_command(struct i2c_client *client, unsigned cmd, void *arg) -{ - return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg); -} - /* ----------------------------------------------------------------------- */ static const struct v4l2_subdev_core_ops vp27smpx_core_ops = { @@ -217,7 +212,6 @@ MODULE_DEVICE_TABLE(i2c, vp27smpx_id); static struct v4l2_i2c_driver_data v4l2_i2c_data = { .name = "vp27smpx", - .command = vp27smpx_command, .probe = vp27smpx_probe, .remove = vp27smpx_remove, #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) diff --git a/linux/drivers/media/video/wm8739.c b/linux/drivers/media/video/wm8739.c index df7d6a094..619782737 100644 --- a/linux/drivers/media/video/wm8739.c +++ b/linux/drivers/media/video/wm8739.c @@ -258,11 +258,6 @@ static int wm8739_log_status(struct v4l2_subdev *sd) return 0; } -static int wm8739_command(struct i2c_client *client, unsigned cmd, void *arg) -{ - return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg); -} - /* ----------------------------------------------------------------------- */ static const struct v4l2_subdev_core_ops wm8739_core_ops = { @@ -351,7 +346,6 @@ MODULE_DEVICE_TABLE(i2c, wm8739_id); static struct v4l2_i2c_driver_data v4l2_i2c_data = { .name = "wm8739", - .command = wm8739_command, .probe = wm8739_probe, .remove = wm8739_remove, #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) -- cgit v1.2.3 From 6126d94ddc3aa2d314338c11109c97a1be4b22f0 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sun, 29 Mar 2009 22:30:34 +0200 Subject: msp3400: remove i2c legacy code From: Hans Verkuil All drivers that use msp3400 now use v4l2_subdev, so we can remove the legacy code from msp3400. Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/msp3400-driver.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/msp3400-driver.c b/linux/drivers/media/video/msp3400-driver.c index fbe69a62d..d89531433 100644 --- a/linux/drivers/media/video/msp3400-driver.c +++ b/linux/drivers/media/video/msp3400-driver.c @@ -60,7 +60,7 @@ #include #include #include -#include +#include #include #include #include "compat.h" @@ -113,10 +113,12 @@ MODULE_PARM_DESC(dolby, "Activates Dolby processsing"); /* DSP unit subaddress */ #define I2C_MSP_DSP 0x12 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22) /* Addresses to scan */ static unsigned short normal_i2c[] = { 0x80 >> 1, 0x88 >> 1, I2C_CLIENT_END }; I2C_CLIENT_INSMOD; +#endif /* ----------------------------------------------------------------------- */ /* functions for talking to the MSP3400C Sound processor */ @@ -701,11 +703,6 @@ static int msp_resume(struct i2c_client *client) return 0; } -static int msp_command(struct i2c_client *client, unsigned cmd, void *arg) -{ - return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg); -} - /* ----------------------------------------------------------------------- */ static const struct v4l2_subdev_core_ops msp_core_ops = { @@ -945,8 +942,6 @@ MODULE_DEVICE_TABLE(i2c, msp_id); #endif static struct v4l2_i2c_driver_data v4l2_i2c_data = { .name = "msp3400", - .driverid = I2C_DRIVERID_MSP3400, - .command = msp_command, .probe = msp_probe, .remove = msp_remove, .suspend = msp_suspend, -- cgit v1.2.3 From 20f6e4bc070bb70c5bf336281b7a80d531bfc3f8 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sun, 29 Mar 2009 22:32:35 +0200 Subject: saa7115: remove i2c legacy code From: Hans Verkuil All drivers that use saa7115 now use v4l2_subdev, so we can remove the legacy code from saa7115. Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/saa7115.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/saa7115.c b/linux/drivers/media/video/saa7115.c index 0719b5f13..448d51b58 100644 --- a/linux/drivers/media/video/saa7115.c +++ b/linux/drivers/media/video/saa7115.c @@ -46,7 +46,7 @@ #include #include #include -#include +#include #include #include #include "compat.h" @@ -63,12 +63,14 @@ module_param(debug, bool, 0644); MODULE_PARM_DESC(debug, "Debug level (0-1)"); +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22) static unsigned short normal_i2c[] = { 0x4a >> 1, 0x48 >> 1, /* SAA7111, SAA7111A and SAA7113 */ 0x42 >> 1, 0x40 >> 1, /* SAA7114, SAA7115 and SAA7118 */ I2C_CLIENT_END }; I2C_CLIENT_INSMOD; +#endif struct saa711x_state { struct v4l2_subdev sd; @@ -1499,11 +1501,6 @@ static int saa711x_log_status(struct v4l2_subdev *sd) return 0; } -static int saa711x_command(struct i2c_client *client, unsigned cmd, void *arg) -{ - return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg); -} - /* ----------------------------------------------------------------------- */ static const struct v4l2_subdev_core_ops saa711x_core_ops = { @@ -1687,8 +1684,6 @@ MODULE_DEVICE_TABLE(i2c, saa7115_id); #endif static struct v4l2_i2c_driver_data v4l2_i2c_data = { .name = "saa7115", - .driverid = I2C_DRIVERID_SAA711X, - .command = saa711x_command, .probe = saa711x_probe, .remove = saa711x_remove, .legacy_class = I2C_CLASS_TV_ANALOG | I2C_CLASS_TV_DIGITAL, -- cgit v1.2.3 From 781dcf110fb80cdf01c81c5b28fc65a8a4f130da Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sun, 29 Mar 2009 22:34:31 +0200 Subject: tvp5150: remove i2c legacy code. From: Hans Verkuil All drivers that use tvp5150 now use v4l2_subdev, so we can remove the legacy code from tvp5150. Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/tvp5150.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/tvp5150.c b/linux/drivers/media/video/tvp5150.c index 67c18f280..3b1eab033 100644 --- a/linux/drivers/media/video/tvp5150.c +++ b/linux/drivers/media/video/tvp5150.c @@ -11,7 +11,7 @@ #include #include #include -#include +#include #include #include "tvp5150_reg.h" @@ -20,6 +20,7 @@ MODULE_DESCRIPTION("Texas Instruments TVP5150A video decoder driver"); MODULE_AUTHOR("Mauro Carvalho Chehab"); MODULE_LICENSE("GPL"); +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22) /* standard i2c insmod options */ static unsigned short normal_i2c[] = { 0xb8 >> 1, @@ -28,6 +29,7 @@ static unsigned short normal_i2c[] = { }; I2C_CLIENT_INSMOD; +#endif static int debug; module_param(debug, int, 0); @@ -1093,11 +1095,6 @@ static int tvp5150_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc) return -EINVAL; } -static int tvp5150_command(struct i2c_client *client, unsigned cmd, void *arg) -{ - return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg); -} - /* ----------------------------------------------------------------------- */ static const struct v4l2_subdev_core_ops tvp5150_core_ops = { @@ -1194,10 +1191,11 @@ MODULE_DEVICE_TABLE(i2c, tvp5150_id); #endif static struct v4l2_i2c_driver_data v4l2_i2c_data = { .name = "tvp5150", - .command = tvp5150_command, .probe = tvp5150_probe, .remove = tvp5150_remove, +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22) .legacy_class = I2C_CLASS_TV_ANALOG | I2C_CLASS_TV_DIGITAL, +#endif #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) .id_table = tvp5150_id, #endif -- cgit v1.2.3 From 960b146f6788947695ab1ffb6965617263399f5f Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 1 Apr 2009 08:32:22 +0200 Subject: tuner: remove i2c legacy code. From: Hans Verkuil All drivers that use the tuner module now use v4l2_subdev, so we can remove the legacy code from this module. Note that TUNER_SET_CONFIG is still called by tuner-simple.c, so we have to handle it via a .command callback. There must be a better way to do this, but for now this will work. Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/tuner-core.c | 32 +++++++++++++++++++++++--------- 1 file changed, 23 insertions(+), 9 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/tuner-core.c b/linux/drivers/media/video/tuner-core.c index 0ac702201..dda992109 100644 --- a/linux/drivers/media/video/tuner-core.c +++ b/linux/drivers/media/video/tuner-core.c @@ -16,12 +16,12 @@ #include #include #include "compat.h" -#include +#include #include #include #include #include -#include +#include #include "mt20xx.h" #include "tda8290.h" #include "tea5761.h" @@ -102,6 +102,7 @@ static inline struct tuner *to_tuner(struct v4l2_subdev *sd) return container_of(sd, struct tuner, sd); } +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22) /* standard i2c insmod options */ static unsigned short normal_i2c[] = { #if defined(CONFIG_MEDIA_TUNER_TEA5761) || (defined(CONFIG_MEDIA_TUNER_TEA5761_MODULE) && defined(MODULE)) @@ -114,6 +115,7 @@ static unsigned short normal_i2c[] = { }; I2C_CLIENT_INSMOD; +#endif /* insmod options used at init time => read/only */ static unsigned int addr; @@ -961,11 +963,6 @@ static int tuner_log_status(struct v4l2_subdev *sd) return 0; } -static int tuner_command(struct i2c_client *client, unsigned cmd, void *arg) -{ - return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg); -} - static int tuner_suspend(struct i2c_client *c, pm_message_t state) { struct tuner *t = to_tuner(i2c_get_clientdata(c)); @@ -990,6 +987,20 @@ static int tuner_resume(struct i2c_client *c) return 0; } +static int tuner_command(struct i2c_client *client, unsigned cmd, void *arg) +{ + struct v4l2_subdev *sd = i2c_get_clientdata(client); + + /* TUNER_SET_CONFIG is still called by tuner-simple.c, so we have + to handle it here. + There must be a better way of doing this... */ + switch (cmd) { + case TUNER_SET_CONFIG: + return tuner_s_config(sd, arg); + } + return -ENOIOCTLCMD; +} + /* ----------------------------------------------------------------------- */ static const struct v4l2_subdev_core_ops tuner_core_ops = { @@ -1177,6 +1188,7 @@ register_client: return 0; } +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22) static int tuner_legacy_probe(struct i2c_adapter *adap) { if (0 != addr) { @@ -1210,6 +1222,7 @@ static int tuner_legacy_probe(struct i2c_adapter *adap) } return 1; } +#endif static int tuner_remove(struct i2c_client *client) { @@ -1239,13 +1252,14 @@ MODULE_DEVICE_TABLE(i2c, tuner_id); static struct v4l2_i2c_driver_data v4l2_i2c_data = { .name = "tuner", - .driverid = I2C_DRIVERID_TUNER, - .command = tuner_command, .probe = tuner_probe, .remove = tuner_remove, + .command = tuner_command, .suspend = tuner_suspend, .resume = tuner_resume, +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22) .legacy_probe = tuner_legacy_probe, +#endif #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) .id_table = tuner_id, #endif -- cgit v1.2.3 From 0c9940b6b68e95f4f47eed6ff21d3508051645fc Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sun, 29 Mar 2009 22:56:18 +0200 Subject: tvaudio: remove i2c legacy code From: Hans Verkuil All drivers that use tvaudio now use v4l2_subdev, so we can remove the legacy code from tvaudio. Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/tvaudio.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/tvaudio.c b/linux/drivers/media/video/tvaudio.c index 39d796908..28caf6ef3 100644 --- a/linux/drivers/media/video/tvaudio.c +++ b/linux/drivers/media/video/tvaudio.c @@ -38,7 +38,7 @@ #include #include #include -#include +#include #include @@ -139,6 +139,7 @@ static inline struct CHIPSTATE *to_state(struct v4l2_subdev *sd) return container_of(sd, struct CHIPSTATE, sd); } +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22) /* ---------------------------------------------------------------------- */ /* i2c addresses */ @@ -153,6 +154,7 @@ static unsigned short normal_i2c[] = { I2C_ADDR_PIC16C54 >> 1, I2C_CLIENT_END }; I2C_CLIENT_INSMOD; +#endif /* ---------------------------------------------------------------------- */ /* i2c I/O functions */ @@ -1926,11 +1928,6 @@ static int tvaudio_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ide return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_TVAUDIO, 0); } -static int tvaudio_command(struct i2c_client *client, unsigned cmd, void *arg) -{ - return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg); -} - /* ----------------------------------------------------------------------- */ static const struct v4l2_subdev_core_ops tvaudio_core_ops = { @@ -2100,6 +2097,7 @@ static int tvaudio_remove(struct i2c_client *client) return 0; } +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22) static int tvaudio_legacy_probe(struct i2c_adapter *adap) { /* don't attach on saa7146 based cards, @@ -2110,6 +2108,7 @@ static int tvaudio_legacy_probe(struct i2c_adapter *adap) return 1; return 0; } +#endif #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) /* This driver supports many devices and the idea is to let the driver @@ -2124,11 +2123,11 @@ MODULE_DEVICE_TABLE(i2c, tvaudio_id); static struct v4l2_i2c_driver_data v4l2_i2c_data = { .name = "tvaudio", - .driverid = I2C_DRIVERID_TVAUDIO, - .command = tvaudio_command, .probe = tvaudio_probe, .remove = tvaudio_remove, +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22) .legacy_probe = tvaudio_legacy_probe, +#endif #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) .id_table = tvaudio_id, #endif -- cgit v1.2.3 From 2da0185910448adfcfc41ac3c7749cd9f8f8344c Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sun, 29 Mar 2009 23:00:07 +0200 Subject: v4l: remove obsolete header and source From: Hans Verkuil v4l2-subdev.c and v4l2-i2c-drv-legacy.h were used to support the old i2c API. All v4l drivers are now converted to v4l2_subdev, so these two files can be removed. Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/Makefile | 2 +- linux/drivers/media/video/v4l2-subdev.c | 128 -------------------------------- 2 files changed, 1 insertion(+), 129 deletions(-) delete mode 100644 linux/drivers/media/video/v4l2-subdev.c (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/Makefile b/linux/drivers/media/video/Makefile index 08765d874..731d97cd8 100644 --- a/linux/drivers/media/video/Makefile +++ b/linux/drivers/media/video/Makefile @@ -10,7 +10,7 @@ stkwebcam-objs := stk-webcam.o stk-sensor.o omap2cam-objs := omap24xxcam.o omap24xxcam-dma.o -videodev-objs := v4l2-dev.o v4l2-ioctl.o v4l2-device.o v4l2-subdev.o +videodev-objs := v4l2-dev.o v4l2-ioctl.o v4l2-device.o obj-$(CONFIG_VIDEO_DEV) += videodev.o v4l2-int-device.o ifeq ($(CONFIG_COMPAT),y) diff --git a/linux/drivers/media/video/v4l2-subdev.c b/linux/drivers/media/video/v4l2-subdev.c deleted file mode 100644 index dc881671d..000000000 --- a/linux/drivers/media/video/v4l2-subdev.c +++ /dev/null @@ -1,128 +0,0 @@ -/* - V4L2 sub-device support. - - Copyright (C) 2008 Hans Verkuil - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include -#include -#include -#include -#include - -int v4l2_subdev_command(struct v4l2_subdev *sd, unsigned cmd, void *arg) -{ - switch (cmd) { - case VIDIOC_QUERYCTRL: - return v4l2_subdev_call(sd, core, queryctrl, arg); - case VIDIOC_G_CTRL: - return v4l2_subdev_call(sd, core, g_ctrl, arg); - case VIDIOC_S_CTRL: - return v4l2_subdev_call(sd, core, s_ctrl, arg); - case VIDIOC_G_EXT_CTRLS: - return v4l2_subdev_call(sd, core, g_ext_ctrls, arg); - case VIDIOC_S_EXT_CTRLS: - return v4l2_subdev_call(sd, core, s_ext_ctrls, arg); - case VIDIOC_TRY_EXT_CTRLS: - return v4l2_subdev_call(sd, core, try_ext_ctrls, arg); - case VIDIOC_QUERYMENU: - return v4l2_subdev_call(sd, core, querymenu, arg); - case VIDIOC_LOG_STATUS: - return v4l2_subdev_call(sd, core, log_status); - case VIDIOC_DBG_G_CHIP_IDENT: - return v4l2_subdev_call(sd, core, g_chip_ident, arg); - case VIDIOC_INT_S_STANDBY: - return v4l2_subdev_call(sd, core, s_standby, arg ? (*(u32 *)arg) : 0); - case VIDIOC_INT_RESET: - return v4l2_subdev_call(sd, core, reset, arg ? (*(u32 *)arg) : 0); - case VIDIOC_INT_S_GPIO: - return v4l2_subdev_call(sd, core, s_gpio, arg ? (*(u32 *)arg) : 0); - case VIDIOC_INT_INIT: - return v4l2_subdev_call(sd, core, init, arg ? (*(u32 *)arg) : 0); -#ifdef CONFIG_VIDEO_ADV_DEBUG - case VIDIOC_DBG_G_REGISTER: - return v4l2_subdev_call(sd, core, g_register, arg); - case VIDIOC_DBG_S_REGISTER: - return v4l2_subdev_call(sd, core, s_register, arg); -#endif - - case VIDIOC_INT_S_TUNER_MODE: - return v4l2_subdev_call(sd, tuner, s_mode, *(enum v4l2_tuner_type *)arg); - case AUDC_SET_RADIO: - return v4l2_subdev_call(sd, tuner, s_radio); - case VIDIOC_S_TUNER: - return v4l2_subdev_call(sd, tuner, s_tuner, arg); - case VIDIOC_G_TUNER: - return v4l2_subdev_call(sd, tuner, g_tuner, arg); - case VIDIOC_S_STD: - return v4l2_subdev_call(sd, tuner, s_std, *(v4l2_std_id *)arg); - case VIDIOC_S_FREQUENCY: - return v4l2_subdev_call(sd, tuner, s_frequency, arg); - case VIDIOC_G_FREQUENCY: - return v4l2_subdev_call(sd, tuner, g_frequency, arg); - case TUNER_SET_TYPE_ADDR: - return v4l2_subdev_call(sd, tuner, s_type_addr, arg); - case TUNER_SET_CONFIG: - return v4l2_subdev_call(sd, tuner, s_config, arg); - - case VIDIOC_INT_AUDIO_CLOCK_FREQ: - return v4l2_subdev_call(sd, audio, s_clock_freq, *(u32 *)arg); - case VIDIOC_INT_S_AUDIO_ROUTING: - return v4l2_subdev_call(sd, audio, s_routing, arg); - case VIDIOC_INT_I2S_CLOCK_FREQ: - return v4l2_subdev_call(sd, audio, s_i2s_clock_freq, *(u32 *)arg); - - case VIDIOC_INT_S_VIDEO_ROUTING: - return v4l2_subdev_call(sd, video, s_routing, arg); - case VIDIOC_INT_S_CRYSTAL_FREQ: - return v4l2_subdev_call(sd, video, s_crystal_freq, arg); - case VIDIOC_INT_DECODE_VBI_LINE: - return v4l2_subdev_call(sd, video, decode_vbi_line, arg); - case VIDIOC_INT_S_VBI_DATA: - return v4l2_subdev_call(sd, video, s_vbi_data, arg); - case VIDIOC_INT_G_VBI_DATA: - return v4l2_subdev_call(sd, video, g_vbi_data, arg); - case VIDIOC_G_SLICED_VBI_CAP: - return v4l2_subdev_call(sd, video, g_sliced_vbi_cap, arg); - case VIDIOC_ENUM_FMT: - return v4l2_subdev_call(sd, video, enum_fmt, arg); - case VIDIOC_TRY_FMT: - return v4l2_subdev_call(sd, video, try_fmt, arg); - case VIDIOC_S_FMT: - return v4l2_subdev_call(sd, video, s_fmt, arg); - case VIDIOC_G_FMT: - return v4l2_subdev_call(sd, video, g_fmt, arg); - case VIDIOC_INT_S_STD_OUTPUT: - return v4l2_subdev_call(sd, video, s_std_output, *(v4l2_std_id *)arg); - case VIDIOC_QUERYSTD: - return v4l2_subdev_call(sd, video, querystd, arg); - case VIDIOC_INT_G_INPUT_STATUS: - return v4l2_subdev_call(sd, video, g_input_status, arg); - case VIDIOC_STREAMON: - return v4l2_subdev_call(sd, video, s_stream, 1); - case VIDIOC_STREAMOFF: - return v4l2_subdev_call(sd, video, s_stream, 0); - case VIDIOC_S_PARM: - return v4l2_subdev_call(sd, video, s_parm, arg); - case VIDIOC_G_PARM: - return v4l2_subdev_call(sd, video, g_parm, arg); - - default: - return v4l2_subdev_call(sd, core, ioctl, cmd, arg); - } -} -EXPORT_SYMBOL_GPL(v4l2_subdev_command); -- cgit v1.2.3 From a022c34c8938f0c3a97840b5b3ceffa0ef41f775 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 1 Apr 2009 08:41:09 +0200 Subject: v4l2-common: remove legacy code From: Hans Verkuil Now that all drivers are converted to v4l2_subdev we can remove legacy code in v4l2-common. Also move the documentation of the internal API to v4l2-subdev.h where it really belongs. Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/v4l2-common.c | 4 +++- linux/drivers/media/video/v4l2-ioctl.c | 34 ++------------------------------- 2 files changed, 5 insertions(+), 33 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/v4l2-common.c b/linux/drivers/media/video/v4l2-common.c index b153575fb..912859bf1 100644 --- a/linux/drivers/media/video/v4l2-common.c +++ b/linux/drivers/media/video/v4l2-common.c @@ -740,8 +740,9 @@ EXPORT_SYMBOL(v4l2_chip_ident_i2c_client); /* ----------------------------------------------------------------- */ -/* Helper function for I2C legacy drivers */ +/* I2C Helper functions */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22) int v4l2_i2c_attach(struct i2c_adapter *adapter, int address, struct i2c_driver *driver, const char *name, int (*probe)(struct i2c_client *, const struct i2c_device_id *)) @@ -767,6 +768,7 @@ int v4l2_i2c_attach(struct i2c_adapter *adapter, int address, struct i2c_driver return err != -ENOMEM ? 0 : err; } EXPORT_SYMBOL(v4l2_i2c_attach); +#endif void v4l2_i2c_subdev_init(struct v4l2_subdev *sd, struct i2c_client *client, const struct v4l2_subdev_ops *ops) diff --git a/linux/drivers/media/video/v4l2-ioctl.c b/linux/drivers/media/video/v4l2-ioctl.c index c16ef96ee..885e6f557 100644 --- a/linux/drivers/media/video/v4l2-ioctl.c +++ b/linux/drivers/media/video/v4l2-ioctl.c @@ -276,32 +276,6 @@ static const char *v4l2_ioctls[] = { }; #define V4L2_IOCTLS ARRAY_SIZE(v4l2_ioctls) -static const char *v4l2_int_ioctls[] = { - [_IOC_NR(AUDC_SET_RADIO)] = "AUDC_SET_RADIO", - - [_IOC_NR(TUNER_SET_TYPE_ADDR)] = "TUNER_SET_TYPE_ADDR", - [_IOC_NR(TUNER_SET_STANDBY)] = "TUNER_SET_STANDBY", - [_IOC_NR(TUNER_SET_CONFIG)] = "TUNER_SET_CONFIG", - - [_IOC_NR(VIDIOC_INT_S_TUNER_MODE)] = "VIDIOC_INT_S_TUNER_MODE", - [_IOC_NR(VIDIOC_INT_RESET)] = "VIDIOC_INT_RESET", - [_IOC_NR(VIDIOC_INT_AUDIO_CLOCK_FREQ)] = "VIDIOC_INT_AUDIO_CLOCK_FREQ", - [_IOC_NR(VIDIOC_INT_DECODE_VBI_LINE)] = "VIDIOC_INT_DECODE_VBI_LINE", - [_IOC_NR(VIDIOC_INT_S_VBI_DATA)] = "VIDIOC_INT_S_VBI_DATA", - [_IOC_NR(VIDIOC_INT_G_VBI_DATA)] = "VIDIOC_INT_G_VBI_DATA", - [_IOC_NR(VIDIOC_INT_I2S_CLOCK_FREQ)] = "VIDIOC_INT_I2S_CLOCK_FREQ", - [_IOC_NR(VIDIOC_INT_S_STANDBY)] = "VIDIOC_INT_S_STANDBY", - [_IOC_NR(VIDIOC_INT_S_AUDIO_ROUTING)] = "VIDIOC_INT_S_AUDIO_ROUTING", - [_IOC_NR(VIDIOC_INT_G_AUDIO_ROUTING)] = "VIDIOC_INT_G_AUDIO_ROUTING", - [_IOC_NR(VIDIOC_INT_S_VIDEO_ROUTING)] = "VIDIOC_INT_S_VIDEO_ROUTING", - [_IOC_NR(VIDIOC_INT_G_VIDEO_ROUTING)] = "VIDIOC_INT_G_VIDEO_ROUTING", - [_IOC_NR(VIDIOC_INT_S_CRYSTAL_FREQ)] = "VIDIOC_INT_S_CRYSTAL_FREQ", - [_IOC_NR(VIDIOC_INT_INIT)] = "VIDIOC_INT_INIT", - [_IOC_NR(VIDIOC_INT_G_STD_OUTPUT)] = "VIDIOC_INT_G_STD_OUTPUT", - [_IOC_NR(VIDIOC_INT_S_STD_OUTPUT)] = "VIDIOC_INT_S_STD_OUTPUT", -}; -#define V4L2_INT_IOCTLS ARRAY_SIZE(v4l2_int_ioctls) - /* Common ioctl debug function. This function can be used by external ioctl messages as well as internal V4L ioctl */ void v4l_printk_ioctl(unsigned int cmd) @@ -310,12 +284,8 @@ void v4l_printk_ioctl(unsigned int cmd) switch (_IOC_TYPE(cmd)) { case 'd': - if (_IOC_NR(cmd) >= V4L2_INT_IOCTLS) { - type = "v4l2_int"; - break; - } - printk("%s", v4l2_int_ioctls[_IOC_NR(cmd)]); - return; + type = "v4l2_int"; + break; #ifdef CONFIG_VIDEO_V4L1_COMPAT case 'v': if (_IOC_NR(cmd) >= V4L1_IOCTLS) { -- cgit v1.2.3 From c7f462c7cd345d35a4d2e493c82f589c6e5d1d2d Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 1 Apr 2009 08:49:59 +0200 Subject: v4l2-subdev: move s_standby from core to tuner. From: Hans Verkuil s_standby is only used to put the tuner in powersaving mode, so move it from core to tuner. Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/cx231xx/cx231xx-video.c | 2 +- linux/drivers/media/video/cx23885/cx23885-core.c | 2 +- linux/drivers/media/video/cx23885/cx23885-dvb.c | 2 +- linux/drivers/media/video/cx88/cx88-cards.c | 2 +- linux/drivers/media/video/cx88/cx88-dvb.c | 2 +- linux/drivers/media/video/cx88/cx88-video.c | 2 +- linux/drivers/media/video/em28xx/em28xx-cards.c | 2 +- linux/drivers/media/video/em28xx/em28xx-video.c | 2 +- linux/drivers/media/video/saa7134/saa7134-core.c | 2 +- linux/drivers/media/video/saa7134/saa7134-video.c | 2 +- linux/drivers/media/video/tuner-core.c | 4 ++-- 11 files changed, 12 insertions(+), 12 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/cx231xx/cx231xx-video.c b/linux/drivers/media/video/cx231xx/cx231xx-video.c index d53ddcb6a..c33921038 100644 --- a/linux/drivers/media/video/cx231xx/cx231xx-video.c +++ b/linux/drivers/media/video/cx231xx/cx231xx-video.c @@ -2125,7 +2125,7 @@ static int cx231xx_v4l2_close(struct file *filp) } /* Save some power by putting tuner to sleep */ - call_all(dev, core, s_standby, 0); + call_all(dev, tuner, s_standby); /* do this before setting alternate! */ cx231xx_uninit_isoc(dev); diff --git a/linux/drivers/media/video/cx23885/cx23885-core.c b/linux/drivers/media/video/cx23885/cx23885-core.c index 2bffcbc48..81fa577a6 100644 --- a/linux/drivers/media/video/cx23885/cx23885-core.c +++ b/linux/drivers/media/video/cx23885/cx23885-core.c @@ -876,7 +876,7 @@ static int cx23885_dev_setup(struct cx23885_dev *dev) cx23885_i2c_register(&dev->i2c_bus[1]); cx23885_i2c_register(&dev->i2c_bus[2]); cx23885_card_setup(dev); - call_all(dev, core, s_standby, 0); + call_all(dev, tuner, s_standby); cx23885_ir_init(dev); if (cx23885_boards[dev->board].porta == CX23885_ANALOG_VIDEO) { diff --git a/linux/drivers/media/video/cx23885/cx23885-dvb.c b/linux/drivers/media/video/cx23885/cx23885-dvb.c index dfb16b91e..c4c1d396c 100644 --- a/linux/drivers/media/video/cx23885/cx23885-dvb.c +++ b/linux/drivers/media/video/cx23885/cx23885-dvb.c @@ -674,7 +674,7 @@ static int dvb_register(struct cx23885_tsport *port) fe0->dvb.frontend->callback = cx23885_tuner_callback; /* Put the analog decoder in standby to keep it quiet */ - call_all(dev, core, s_standby, 0); + call_all(dev, tuner, s_standby); if (fe0->dvb.frontend->ops.analog_ops.standby) fe0->dvb.frontend->ops.analog_ops.standby(fe0->dvb.frontend); diff --git a/linux/drivers/media/video/cx88/cx88-cards.c b/linux/drivers/media/video/cx88/cx88-cards.c index a170dedbf..34327b62a 100644 --- a/linux/drivers/media/video/cx88/cx88-cards.c +++ b/linux/drivers/media/video/cx88/cx88-cards.c @@ -3082,7 +3082,7 @@ static void cx88_card_setup(struct cx88_core *core) ctl.fname); call_all(core, tuner, s_config, &xc2028_cfg); } - call_all(core, core, s_standby, 0); + call_all(core, tuner, s_standby); } /* ------------------------------------------------------------------ */ diff --git a/linux/drivers/media/video/cx88/cx88-dvb.c b/linux/drivers/media/video/cx88/cx88-dvb.c index 3de497312..f32cece95 100644 --- a/linux/drivers/media/video/cx88/cx88-dvb.c +++ b/linux/drivers/media/video/cx88/cx88-dvb.c @@ -1175,7 +1175,7 @@ static int dvb_register(struct cx8802_dev *dev) fe1->dvb.frontend->ops.ts_bus_ctrl = cx88_dvb_bus_ctrl; /* Put the analog decoder in standby to keep it quiet */ - call_all(core, core, s_standby, 0); + call_all(core, tuner, s_standby); /* register everything */ return videobuf_dvb_register_bus(&dev->frontends, THIS_MODULE, dev, diff --git a/linux/drivers/media/video/cx88/cx88-video.c b/linux/drivers/media/video/cx88/cx88-video.c index ea3920c8a..a3fd7f643 100644 --- a/linux/drivers/media/video/cx88/cx88-video.c +++ b/linux/drivers/media/video/cx88/cx88-video.c @@ -1157,7 +1157,7 @@ static int video_release(struct file *file) kfree(fh); if(atomic_dec_and_test(&dev->core->users)) - call_all(dev->core, core, s_standby, 0); + call_all(dev->core, tuner, s_standby); return 0; } diff --git a/linux/drivers/media/video/em28xx/em28xx-cards.c b/linux/drivers/media/video/em28xx/em28xx-cards.c index 56c27b745..035fc8eaf 100644 --- a/linux/drivers/media/video/em28xx/em28xx-cards.c +++ b/linux/drivers/media/video/em28xx/em28xx-cards.c @@ -2244,7 +2244,7 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, em28xx_init_extension(dev); /* Save some power by putting tuner to sleep */ - v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_standby, 0); + v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_standby); return 0; diff --git a/linux/drivers/media/video/em28xx/em28xx-video.c b/linux/drivers/media/video/em28xx/em28xx-video.c index f5ca05aab..5d8fe3fe9 100644 --- a/linux/drivers/media/video/em28xx/em28xx-video.c +++ b/linux/drivers/media/video/em28xx/em28xx-video.c @@ -1799,7 +1799,7 @@ static int em28xx_v4l2_close(struct file *filp) } /* Save some power by putting tuner to sleep */ - v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_standby, 0); + v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_standby); /* do this before setting alternate! */ em28xx_uninit_isoc(dev); diff --git a/linux/drivers/media/video/saa7134/saa7134-core.c b/linux/drivers/media/video/saa7134/saa7134-core.c index 1bf7c3a1b..fbe741865 100644 --- a/linux/drivers/media/video/saa7134/saa7134-core.c +++ b/linux/drivers/media/video/saa7134/saa7134-core.c @@ -1076,7 +1076,7 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev, saa7134_irq_video_signalchange(dev); if (TUNER_ABSENT != dev->tuner_type) - saa_call_all(dev, core, s_standby, 0); + saa_call_all(dev, tuner, s_standby); /* register v4l devices */ if (saa7134_no_overlay > 0) diff --git a/linux/drivers/media/video/saa7134/saa7134-video.c b/linux/drivers/media/video/saa7134/saa7134-video.c index 8ad0c72d0..d7117b935 100644 --- a/linux/drivers/media/video/saa7134/saa7134-video.c +++ b/linux/drivers/media/video/saa7134/saa7134-video.c @@ -1496,7 +1496,7 @@ static int video_release(struct file *file) saa_andorb(SAA7134_OFMT_DATA_A, 0x1f, 0); saa_andorb(SAA7134_OFMT_DATA_B, 0x1f, 0); - saa_call_all(dev, core, s_standby, 0); + saa_call_all(dev, tuner, s_standby); if (fh->radio) saa_call_all(dev, core, ioctl, RDS_CMD_CLOSE, &cmd); diff --git a/linux/drivers/media/video/tuner-core.c b/linux/drivers/media/video/tuner-core.c index dda992109..4b68c5394 100644 --- a/linux/drivers/media/video/tuner-core.c +++ b/linux/drivers/media/video/tuner-core.c @@ -797,7 +797,7 @@ static int tuner_s_radio(struct v4l2_subdev *sd) return 0; } -static int tuner_s_standby(struct v4l2_subdev *sd, u32 standby) +static int tuner_s_standby(struct v4l2_subdev *sd) { struct tuner *t = to_tuner(sd); struct analog_demod_ops *analog_ops = &t->fe.ops.analog_ops; @@ -1005,7 +1005,6 @@ static int tuner_command(struct i2c_client *client, unsigned cmd, void *arg) static const struct v4l2_subdev_core_ops tuner_core_ops = { .log_status = tuner_log_status, - .s_standby = tuner_s_standby, }; static const struct v4l2_subdev_tuner_ops tuner_tuner_ops = { @@ -1017,6 +1016,7 @@ static const struct v4l2_subdev_tuner_ops tuner_tuner_ops = { .g_frequency = tuner_g_frequency, .s_type_addr = tuner_s_type_addr, .s_config = tuner_s_config, + .s_standby = tuner_s_standby, }; static const struct v4l2_subdev_ops tuner_ops = { -- cgit v1.2.3 From 6584af2799555f05b6545f667d94f780cbb24a1c Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 30 Mar 2009 00:20:26 +0200 Subject: v4l2-subdev: add load_fw and use that instead of abusing core->init. From: Hans Verkuil The init callback was used in several places to load firmware. Make a separate load_fw callback for that. This makes the code a lot more understandable. Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/cx18/cx18-av-core.c | 60 +++++++++++------------ linux/drivers/media/video/cx18/cx18-av-core.h | 5 -- linux/drivers/media/video/cx18/cx18-driver.c | 4 +- linux/drivers/media/video/cx231xx/cx231xx-cards.c | 2 +- linux/drivers/media/video/cx23885/cx23885-cards.c | 2 +- linux/drivers/media/video/cx25840/cx25840-core.c | 8 +-- linux/drivers/media/video/ivtv/ivtv-driver.c | 2 +- linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c | 2 +- 8 files changed, 40 insertions(+), 45 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/cx18/cx18-av-core.c b/linux/drivers/media/video/cx18/cx18-av-core.c index f4dd9d78e..0c58e55fd 100644 --- a/linux/drivers/media/video/cx18/cx18-av-core.c +++ b/linux/drivers/media/video/cx18/cx18-av-core.c @@ -203,43 +203,42 @@ static int cx18_av_reset(struct v4l2_subdev *sd, u32 val) static int cx18_av_init(struct v4l2_subdev *sd, u32 val) { - struct cx18_av_state *state = to_cx18_av_state(sd); struct cx18 *cx = v4l2_get_subdevdata(sd); - switch (val) { - case CX18_AV_INIT_PLLS: - /* - * The crystal freq used in calculations in this driver will be - * 28.636360 MHz. - * Aim to run the PLLs' VCOs near 400 MHz to minimze errors. - */ + /* + * The crystal freq used in calculations in this driver will be + * 28.636360 MHz. + * Aim to run the PLLs' VCOs near 400 MHz to minimze errors. + */ - /* - * VDCLK Integer = 0x0f, Post Divider = 0x04 - * AIMCLK Integer = 0x0e, Post Divider = 0x16 - */ - cx18_av_write4(cx, CXADEC_PLL_CTRL1, 0x160e040f); + /* + * VDCLK Integer = 0x0f, Post Divider = 0x04 + * AIMCLK Integer = 0x0e, Post Divider = 0x16 + */ + cx18_av_write4(cx, CXADEC_PLL_CTRL1, 0x160e040f); - /* VDCLK Fraction = 0x2be2fe */ - /* xtal * 0xf.15f17f0/4 = 108 MHz: 432 MHz before post divide */ - cx18_av_write4(cx, CXADEC_VID_PLL_FRAC, 0x002be2fe); + /* VDCLK Fraction = 0x2be2fe */ + /* xtal * 0xf.15f17f0/4 = 108 MHz: 432 MHz before post divide */ + cx18_av_write4(cx, CXADEC_VID_PLL_FRAC, 0x002be2fe); - /* AIMCLK Fraction = 0x05227ad */ - /* xtal * 0xe.2913d68/0x16 = 48000 * 384: 406 MHz pre post-div*/ - cx18_av_write4(cx, CXADEC_AUX_PLL_FRAC, 0x005227ad); + /* AIMCLK Fraction = 0x05227ad */ + /* xtal * 0xe.2913d68/0x16 = 48000 * 384: 406 MHz pre post-div*/ + cx18_av_write4(cx, CXADEC_AUX_PLL_FRAC, 0x005227ad); - /* SA_MCLK_SEL=1, SA_MCLK_DIV=0x16 */ - cx18_av_write(cx, CXADEC_I2S_MCLK, 0x56); - break; + /* SA_MCLK_SEL=1, SA_MCLK_DIV=0x16 */ + cx18_av_write(cx, CXADEC_I2S_MCLK, 0x56); + return 0; +} - case CX18_AV_INIT_NORMAL: - default: - if (!state->is_initialized) { - /* initialize on first use */ - state->is_initialized = 1; - cx18_av_initialize(cx); - } - break; +static int cx18_av_load_fw(struct v4l2_subdev *sd) +{ + struct cx18_av_state *state = to_cx18_av_state(sd); + struct cx18 *cx = v4l2_get_subdevdata(sd); + + if (!state->is_initialized) { + /* initialize on first use */ + state->is_initialized = 1; + cx18_av_initialize(cx); } return 0; } @@ -1185,6 +1184,7 @@ static const struct v4l2_subdev_core_ops cx18_av_general_ops = { .g_chip_ident = cx18_av_g_chip_ident, .log_status = cx18_av_log_status, .init = cx18_av_init, + .load_fw = cx18_av_load_fw, .reset = cx18_av_reset, .queryctrl = cx18_av_queryctrl, .g_ctrl = cx18_av_g_ctrl, diff --git a/linux/drivers/media/video/cx18/cx18-av-core.h b/linux/drivers/media/video/cx18/cx18-av-core.h index c458120e8..9b84a0c58 100644 --- a/linux/drivers/media/video/cx18/cx18-av-core.h +++ b/linux/drivers/media/video/cx18/cx18-av-core.h @@ -328,11 +328,6 @@ static inline struct cx18_av_state *to_cx18_av_state(struct v4l2_subdev *sd) return container_of(sd, struct cx18_av_state, sd); } -enum cx18_av_subdev_init_arg { - CX18_AV_INIT_NORMAL = 0, - CX18_AV_INIT_PLLS = 1, -}; - /* ----------------------------------------------------------------------- */ /* cx18_av-core.c */ int cx18_av_write(struct cx18 *cx, u16 addr, u8 value); diff --git a/linux/drivers/media/video/cx18/cx18-driver.c b/linux/drivers/media/video/cx18/cx18-driver.c index f688ec7db..062129fb5 100644 --- a/linux/drivers/media/video/cx18/cx18-driver.c +++ b/linux/drivers/media/video/cx18/cx18-driver.c @@ -815,7 +815,7 @@ static int __devinit cx18_probe(struct pci_dev *pci_dev, CX18_ERR("Could not register A/V decoder subdevice\n"); goto free_map; } - cx18_call_hw(cx, CX18_HW_418_AV, core, init, (u32) CX18_AV_INIT_PLLS); + cx18_call_hw(cx, CX18_HW_418_AV, core, init, 0); /* Initialize GPIO Reset Controller to do chip resets during i2c init */ if (cx->card->hw_all & CX18_HW_GPIO_RESET_CTRL) { @@ -1033,7 +1033,7 @@ int cx18_init_on_first_open(struct cx18 *cx) cx18_vapi(cx, CX18_APU_STOP, 1, CX18_APU_ENCODING_METHOD_MPEG); /* Init the A/V decoder, if it hasn't been already */ - v4l2_subdev_call(cx->sd_av, core, init, (u32) CX18_AV_INIT_NORMAL); + v4l2_subdev_call(cx->sd_av, core, load_fw); vf.tuner = 0; vf.type = V4L2_TUNER_ANALOG_TV; diff --git a/linux/drivers/media/video/cx231xx/cx231xx-cards.c b/linux/drivers/media/video/cx231xx/cx231xx-cards.c index d1872988a..8d445775e 100644 --- a/linux/drivers/media/video/cx231xx/cx231xx-cards.c +++ b/linux/drivers/media/video/cx231xx/cx231xx-cards.c @@ -317,7 +317,7 @@ void cx231xx_card_setup(struct cx231xx *dev) "cx25840", "cx25840", 0x88 >> 1); if (dev->sd_cx25840 == NULL) cx231xx_info("cx25840 subdev registration failure\n"); - cx25840_call(dev, core, init, 0); + cx25840_call(dev, core, load_fw); } diff --git a/linux/drivers/media/video/cx23885/cx23885-cards.c b/linux/drivers/media/video/cx23885/cx23885-cards.c index 493551ec0..c85678464 100644 --- a/linux/drivers/media/video/cx23885/cx23885-cards.c +++ b/linux/drivers/media/video/cx23885/cx23885-cards.c @@ -742,7 +742,7 @@ void cx23885_card_setup(struct cx23885_dev *dev) case CX23885_BOARD_NETUP_DUAL_DVBS2_CI: dev->sd_cx25840 = v4l2_i2c_new_subdev(&dev->i2c_bus[2].i2c_adap, "cx25840", "cx25840", 0x88 >> 1); - v4l2_subdev_call(dev->sd_cx25840, core, init, 0); + v4l2_subdev_call(dev->sd_cx25840, core, load_fw); break; } diff --git a/linux/drivers/media/video/cx25840/cx25840-core.c b/linux/drivers/media/video/cx25840/cx25840-core.c index 67971cc3c..1af7dbfbc 100644 --- a/linux/drivers/media/video/cx25840/cx25840-core.c +++ b/linux/drivers/media/video/cx25840/cx25840-core.c @@ -1214,7 +1214,7 @@ static void log_audio_status(struct i2c_client *client) /* ----------------------------------------------------------------------- */ -/* This init operation must be called to load the driver's firmware. +/* This load_fw operation must be called to load the driver's firmware. Without this the audio standard detection will fail and you will only get mono. @@ -1224,13 +1224,13 @@ static void log_audio_status(struct i2c_client *client) postponing it is that loading this firmware takes a long time (seconds) due to the slow i2c bus speed. So it will speed up the boot process if you can avoid loading the fw as long as the video device isn't used. */ -static int cx25840_init(struct v4l2_subdev *sd, u32 val) +static int cx25840_load_fw(struct v4l2_subdev *sd) { struct cx25840_state *state = to_state(sd); struct i2c_client *client = v4l2_get_subdevdata(sd); if (!state->is_initialized) { - /* initialize on first use */ + /* initialize and load firmware */ state->is_initialized = 1; if (state->is_cx25836) cx25836_initialize(client); @@ -1505,7 +1505,7 @@ static const struct v4l2_subdev_core_ops cx25840_core_ops = { .s_ctrl = cx25840_s_ctrl, .queryctrl = cx25840_queryctrl, .reset = cx25840_reset, - .init = cx25840_init, + .load_fw = cx25840_load_fw, #ifdef CONFIG_VIDEO_ADV_DEBUG .g_register = cx25840_g_register, .s_register = cx25840_s_register, diff --git a/linux/drivers/media/video/ivtv/ivtv-driver.c b/linux/drivers/media/video/ivtv/ivtv-driver.c index 5e90897a2..4549fd525 100644 --- a/linux/drivers/media/video/ivtv/ivtv-driver.c +++ b/linux/drivers/media/video/ivtv/ivtv-driver.c @@ -1238,7 +1238,7 @@ int ivtv_init_on_first_open(struct ivtv *itv) if (itv->card->hw_all & IVTV_HW_CX25840) { struct v4l2_control ctrl; - v4l2_subdev_call(itv->sd_video, core, init, 0); + v4l2_subdev_call(itv->sd_video, core, load_fw); /* CX25840_CID_ENABLE_PVR150_WORKAROUND */ ctrl.id = V4L2_CID_PRIVATE_BASE; ctrl.value = itv->pvr150_workaround; diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c index bea17cd64..c7740866c 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -2202,7 +2202,7 @@ static void pvr2_hdw_setup_low(struct pvr2_hdw *hdw) pvr2_hdw_load_modules(hdw); if (!pvr2_hdw_dev_ok(hdw)) return; - v4l2_device_call_all(&hdw->v4l2_dev, 0, core, init, 0); + v4l2_device_call_all(&hdw->v4l2_dev, 0, core, load_fw); for (idx = 0; idx < CTRLDEF_COUNT; idx++) { cptr = hdw->controls + idx; -- cgit v1.2.3 From 0811e7462ce5c70637faa77e010016680c1e971a Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 1 Apr 2009 08:52:39 +0200 Subject: v4l2-subdev: move s_std from tuner to core. From: Hans Verkuil s_std didn't belong in the tuner ops. Stricly speaking it should be part of the video ops, but it is used by audio and tuner devices as well, so it is more efficient to make it part of the core ops. Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/au0828/au0828-video.c | 2 +- linux/drivers/media/video/bt819.c | 4 ---- linux/drivers/media/video/bt8xx/bttv-driver.c | 2 +- linux/drivers/media/video/cx18/cx18-av-core.c | 2 +- linux/drivers/media/video/cx18/cx18-fileops.c | 2 +- linux/drivers/media/video/cx18/cx18-gpio.c | 2 +- linux/drivers/media/video/cx18/cx18-ioctl.c | 2 +- linux/drivers/media/video/cx231xx/cx231xx-video.c | 2 +- linux/drivers/media/video/cx23885/cx23885-417.c | 2 +- linux/drivers/media/video/cx23885/cx23885-video.c | 2 +- linux/drivers/media/video/cx25840/cx25840-core.c | 2 +- linux/drivers/media/video/cx88/cx88-core.c | 2 +- linux/drivers/media/video/em28xx/em28xx-video.c | 2 +- linux/drivers/media/video/ivtv/ivtv-fileops.c | 2 +- linux/drivers/media/video/ivtv/ivtv-gpio.c | 2 +- linux/drivers/media/video/ivtv/ivtv-ioctl.c | 2 +- linux/drivers/media/video/ks0127.c | 4 ---- linux/drivers/media/video/msp3400-driver.c | 2 +- linux/drivers/media/video/mxb.c | 8 ++++---- linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c | 2 +- linux/drivers/media/video/saa7110.c | 4 ---- linux/drivers/media/video/saa7115.c | 2 +- linux/drivers/media/video/saa7134/saa6752hs.c | 4 ---- linux/drivers/media/video/saa7134/saa7134-video.c | 4 ++-- linux/drivers/media/video/saa717x.c | 2 +- linux/drivers/media/video/saa7191.c | 4 ---- linux/drivers/media/video/tuner-core.c | 2 +- linux/drivers/media/video/tvaudio.c | 2 +- linux/drivers/media/video/tvp5150.c | 2 +- linux/drivers/media/video/usbvision/usbvision-video.c | 2 +- linux/drivers/media/video/vino.c | 6 +++--- linux/drivers/media/video/vp27smpx.c | 2 +- linux/drivers/media/video/vpx3220.c | 4 ---- linux/drivers/media/video/zoran/zoran_device.c | 2 +- linux/drivers/media/video/zoran/zoran_driver.c | 6 +++--- 35 files changed, 37 insertions(+), 61 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 5eac5cde5..f40259e74 100644 --- a/linux/drivers/media/video/au0828/au0828-video.c +++ b/linux/drivers/media/video/au0828/au0828-video.c @@ -1106,7 +1106,7 @@ static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id * norm) have to make the au0828 bridge adjust the size of its capture buffer, which is currently hardcoded at 720x480 */ - v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_std, *norm); + v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_std, *norm); return 0; } diff --git a/linux/drivers/media/video/bt819.c b/linux/drivers/media/video/bt819.c index b8c084acf..5929e05ff 100644 --- a/linux/drivers/media/video/bt819.c +++ b/linux/drivers/media/video/bt819.c @@ -450,9 +450,6 @@ static const struct v4l2_subdev_core_ops bt819_core_ops = { .g_ctrl = bt819_g_ctrl, .s_ctrl = bt819_s_ctrl, .queryctrl = bt819_queryctrl, -}; - -static const struct v4l2_subdev_tuner_ops bt819_tuner_ops = { .s_std = bt819_s_std, }; @@ -465,7 +462,6 @@ static const struct v4l2_subdev_video_ops bt819_video_ops = { static const struct v4l2_subdev_ops bt819_ops = { .core = &bt819_core_ops, - .tuner = &bt819_tuner_ops, .video = &bt819_video_ops, }; diff --git a/linux/drivers/media/video/bt8xx/bttv-driver.c b/linux/drivers/media/video/bt8xx/bttv-driver.c index f40eb10fd..054cd2f38 100644 --- a/linux/drivers/media/video/bt8xx/bttv-driver.c +++ b/linux/drivers/media/video/bt8xx/bttv-driver.c @@ -1357,7 +1357,7 @@ set_tvnorm(struct bttv *btv, unsigned int norm) #endif } id = tvnorm->v4l2_id; - bttv_call_all(btv, tuner, s_std, id); + bttv_call_all(btv, core, s_std, id); return 0; } diff --git a/linux/drivers/media/video/cx18/cx18-av-core.c b/linux/drivers/media/video/cx18/cx18-av-core.c index 0c58e55fd..9b3e574dd 100644 --- a/linux/drivers/media/video/cx18/cx18-av-core.c +++ b/linux/drivers/media/video/cx18/cx18-av-core.c @@ -1189,6 +1189,7 @@ static const struct v4l2_subdev_core_ops cx18_av_general_ops = { .queryctrl = cx18_av_queryctrl, .g_ctrl = cx18_av_g_ctrl, .s_ctrl = cx18_av_s_ctrl, + .s_std = cx18_av_s_std, #ifdef CONFIG_VIDEO_ADV_DEBUG .g_register = cx18_av_g_register, .s_register = cx18_av_s_register, @@ -1200,7 +1201,6 @@ static const struct v4l2_subdev_tuner_ops cx18_av_tuner_ops = { .s_frequency = cx18_av_s_frequency, .g_tuner = cx18_av_g_tuner, .s_tuner = cx18_av_s_tuner, - .s_std = cx18_av_s_std, }; static const struct v4l2_subdev_audio_ops cx18_av_audio_ops = { diff --git a/linux/drivers/media/video/cx18/cx18-fileops.c b/linux/drivers/media/video/cx18/cx18-fileops.c index 7d82c8fb3..d20ac818f 100644 --- a/linux/drivers/media/video/cx18/cx18-fileops.c +++ b/linux/drivers/media/video/cx18/cx18-fileops.c @@ -644,7 +644,7 @@ int cx18_v4l2_close(struct file *filp) /* Mark that the radio is no longer in use */ clear_bit(CX18_F_I_RADIO_USER, &cx->i_flags); /* Switch tuner to TV */ - cx18_call_all(cx, tuner, s_std, cx->std); + cx18_call_all(cx, core, s_std, cx->std); /* Select correct audio input (i.e. TV tuner or Line in) */ cx18_audio_set_io(cx); if (atomic_read(&cx->ana_capturing) > 0) { diff --git a/linux/drivers/media/video/cx18/cx18-gpio.c b/linux/drivers/media/video/cx18/cx18-gpio.c index 5518d1424..ae2460e68 100644 --- a/linux/drivers/media/video/cx18/cx18-gpio.c +++ b/linux/drivers/media/video/cx18/cx18-gpio.c @@ -180,10 +180,10 @@ static int gpiomux_s_audio_routing(struct v4l2_subdev *sd, static const struct v4l2_subdev_core_ops gpiomux_core_ops = { .log_status = gpiomux_log_status, + .s_std = gpiomux_s_std, }; static const struct v4l2_subdev_tuner_ops gpiomux_tuner_ops = { - .s_std = gpiomux_s_std, .s_radio = gpiomux_s_radio, }; diff --git a/linux/drivers/media/video/cx18/cx18-ioctl.c b/linux/drivers/media/video/cx18/cx18-ioctl.c index c7e85f879..810c39f85 100644 --- a/linux/drivers/media/video/cx18/cx18-ioctl.c +++ b/linux/drivers/media/video/cx18/cx18-ioctl.c @@ -713,7 +713,7 @@ int cx18_s_std(struct file *file, void *fh, v4l2_std_id *std) (unsigned long long) cx->std); /* Tuner */ - cx18_call_all(cx, tuner, s_std, cx->std); + cx18_call_all(cx, core, s_std, cx->std); return 0; } diff --git a/linux/drivers/media/video/cx231xx/cx231xx-video.c b/linux/drivers/media/video/cx231xx/cx231xx-video.c index c33921038..37703f02b 100644 --- a/linux/drivers/media/video/cx231xx/cx231xx-video.c +++ b/linux/drivers/media/video/cx231xx/cx231xx-video.c @@ -1089,7 +1089,7 @@ static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *norm) dev->height = f.fmt.pix.height; get_scale(dev, dev->width, dev->height, &dev->hscale, &dev->vscale); - call_all(dev, tuner, s_std, dev->norm); + call_all(dev, core, s_std, dev->norm); mutex_unlock(&dev->lock); diff --git a/linux/drivers/media/video/cx23885/cx23885-417.c b/linux/drivers/media/video/cx23885/cx23885-417.c index aeef889fd..574cdb385 100644 --- a/linux/drivers/media/video/cx23885/cx23885-417.c +++ b/linux/drivers/media/video/cx23885/cx23885-417.c @@ -1194,7 +1194,7 @@ static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *id) * This will likely need to be enabled for non NTSC * formats. */ - call_all(dev, tuner, s_std, id); + call_all(dev, core, s_std, id); #endif return 0; } diff --git a/linux/drivers/media/video/cx23885/cx23885-video.c b/linux/drivers/media/video/cx23885/cx23885-video.c index a45bd3b77..c5467ec46 100644 --- a/linux/drivers/media/video/cx23885/cx23885-video.c +++ b/linux/drivers/media/video/cx23885/cx23885-video.c @@ -334,7 +334,7 @@ static int cx23885_set_tvnorm(struct cx23885_dev *dev, v4l2_std_id norm) dev->tvnorm = norm; - call_all(dev, tuner, s_std, norm); + call_all(dev, core, s_std, norm); return 0; } diff --git a/linux/drivers/media/video/cx25840/cx25840-core.c b/linux/drivers/media/video/cx25840/cx25840-core.c index 1af7dbfbc..e5bf756e5 100644 --- a/linux/drivers/media/video/cx25840/cx25840-core.c +++ b/linux/drivers/media/video/cx25840/cx25840-core.c @@ -1504,6 +1504,7 @@ static const struct v4l2_subdev_core_ops cx25840_core_ops = { .g_ctrl = cx25840_g_ctrl, .s_ctrl = cx25840_s_ctrl, .queryctrl = cx25840_queryctrl, + .s_std = cx25840_s_std, .reset = cx25840_reset, .load_fw = cx25840_load_fw, #ifdef CONFIG_VIDEO_ADV_DEBUG @@ -1514,7 +1515,6 @@ static const struct v4l2_subdev_core_ops cx25840_core_ops = { static const struct v4l2_subdev_tuner_ops cx25840_tuner_ops = { .s_frequency = cx25840_s_frequency, - .s_std = cx25840_s_std, .s_radio = cx25840_s_radio, .g_tuner = cx25840_g_tuner, .s_tuner = cx25840_s_tuner, diff --git a/linux/drivers/media/video/cx88/cx88-core.c b/linux/drivers/media/video/cx88/cx88-core.c index faee9d885..71dccf6af 100644 --- a/linux/drivers/media/video/cx88/cx88-core.c +++ b/linux/drivers/media/video/cx88/cx88-core.c @@ -1020,7 +1020,7 @@ int cx88_set_tvnorm(struct cx88_core *core, v4l2_std_id norm) set_tvaudio(core); // tell i2c chips - call_all(core, tuner, s_std, norm); + call_all(core, core, s_std, norm); // done return 0; diff --git a/linux/drivers/media/video/em28xx/em28xx-video.c b/linux/drivers/media/video/em28xx/em28xx-video.c index 5d8fe3fe9..212444179 100644 --- a/linux/drivers/media/video/em28xx/em28xx-video.c +++ b/linux/drivers/media/video/em28xx/em28xx-video.c @@ -833,7 +833,7 @@ static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *norm) get_scale(dev, dev->width, dev->height, &dev->hscale, &dev->vscale); em28xx_resolution_set(dev); - v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_std, dev->norm); + v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_std, dev->norm); mutex_unlock(&dev->lock); return 0; diff --git a/linux/drivers/media/video/ivtv/ivtv-fileops.c b/linux/drivers/media/video/ivtv/ivtv-fileops.c index cfaacf609..e212337c6 100644 --- a/linux/drivers/media/video/ivtv/ivtv-fileops.c +++ b/linux/drivers/media/video/ivtv/ivtv-fileops.c @@ -857,7 +857,7 @@ int ivtv_v4l2_close(struct file *filp) /* Mark that the radio is no longer in use */ clear_bit(IVTV_F_I_RADIO_USER, &itv->i_flags); /* Switch tuner to TV */ - ivtv_call_all(itv, tuner, s_std, itv->std); + ivtv_call_all(itv, core, s_std, itv->std); /* Select correct audio input (i.e. TV tuner or Line in) */ ivtv_audio_set_io(itv); if (itv->hw_flags & IVTV_HW_SAA711X) diff --git a/linux/drivers/media/video/ivtv/ivtv-gpio.c b/linux/drivers/media/video/ivtv/ivtv-gpio.c index 3321983d8..0dd5f53b7 100644 --- a/linux/drivers/media/video/ivtv/ivtv-gpio.c +++ b/linux/drivers/media/video/ivtv/ivtv-gpio.c @@ -342,10 +342,10 @@ static const struct v4l2_subdev_core_ops subdev_core_ops = { .g_ctrl = subdev_g_ctrl, .s_ctrl = subdev_s_ctrl, .queryctrl = subdev_queryctrl, + .s_std = subdev_s_std, }; static const struct v4l2_subdev_tuner_ops subdev_tuner_ops = { - .s_std = subdev_s_std, .s_radio = subdev_s_radio, .g_tuner = subdev_g_tuner, .s_tuner = subdev_s_tuner, diff --git a/linux/drivers/media/video/ivtv/ivtv-ioctl.c b/linux/drivers/media/video/ivtv/ivtv-ioctl.c index 9a0424298..052fbe9cd 100644 --- a/linux/drivers/media/video/ivtv/ivtv-ioctl.c +++ b/linux/drivers/media/video/ivtv/ivtv-ioctl.c @@ -1121,7 +1121,7 @@ int ivtv_s_std(struct file *file, void *fh, v4l2_std_id *std) IVTV_DEBUG_INFO("Switching standard to %llx.\n", (unsigned long long)itv->std); /* Tuner */ - ivtv_call_all(itv, tuner, s_std, itv->std); + ivtv_call_all(itv, core, s_std, itv->std); if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT) { /* set display standard */ diff --git a/linux/drivers/media/video/ks0127.c b/linux/drivers/media/video/ks0127.c index a1b12557a..198971b75 100644 --- a/linux/drivers/media/video/ks0127.c +++ b/linux/drivers/media/video/ks0127.c @@ -658,9 +658,6 @@ static int ks0127_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_iden static const struct v4l2_subdev_core_ops ks0127_core_ops = { .g_chip_ident = ks0127_g_chip_ident, -}; - -static const struct v4l2_subdev_tuner_ops ks0127_tuner_ops = { .s_std = ks0127_s_std, }; @@ -673,7 +670,6 @@ static const struct v4l2_subdev_video_ops ks0127_video_ops = { static const struct v4l2_subdev_ops ks0127_ops = { .core = &ks0127_core_ops, - .tuner = &ks0127_tuner_ops, .video = &ks0127_video_ops, }; diff --git a/linux/drivers/media/video/msp3400-driver.c b/linux/drivers/media/video/msp3400-driver.c index d89531433..5b63af6f8 100644 --- a/linux/drivers/media/video/msp3400-driver.c +++ b/linux/drivers/media/video/msp3400-driver.c @@ -711,6 +711,7 @@ static const struct v4l2_subdev_core_ops msp_core_ops = { .g_ctrl = msp_g_ctrl, .s_ctrl = msp_s_ctrl, .queryctrl = msp_queryctrl, + .s_std = msp_s_std, }; static const struct v4l2_subdev_tuner_ops msp_tuner_ops = { @@ -718,7 +719,6 @@ static const struct v4l2_subdev_tuner_ops msp_tuner_ops = { .g_tuner = msp_g_tuner, .s_tuner = msp_s_tuner, .s_radio = msp_s_radio, - .s_std = msp_s_std, }; static const struct v4l2_subdev_audio_ops msp_audio_ops = { diff --git a/linux/drivers/media/video/mxb.c b/linux/drivers/media/video/mxb.c index c85cfd27e..93209d160 100644 --- a/linux/drivers/media/video/mxb.c +++ b/linux/drivers/media/video/mxb.c @@ -270,7 +270,7 @@ static int mxb_init_done(struct saa7146_dev* dev) int i = 0, err = 0; /* select video mode in saa7111a */ - saa7111a_call(mxb, tuner, s_std, std); + saa7111a_call(mxb, core, s_std, std); /* select tuner-output on saa7111a */ i = 0; @@ -290,7 +290,7 @@ static int mxb_init_done(struct saa7146_dev* dev) tuner_call(mxb, tuner, s_frequency, &mxb->cur_freq); /* set a default video standard */ - tuner_call(mxb, tuner, s_std, std); + tuner_call(mxb, core, s_std, std); /* mute audio on tea6420s */ tea6420_1_call(mxb, audio, s_routing, &TEA6420_line[6][0]); @@ -792,7 +792,7 @@ static int std_callback(struct saa7146_dev *dev, struct saa7146_standard *standa saa7146_write(dev, GPIO_CTRL, 0x00404050); /* unset the 7111 gpio register -- I don't know what this does exactly */ saa7111a_call(mxb, core, s_gpio, 0); - tuner_call(mxb, tuner, s_std, std); + tuner_call(mxb, core, s_std, std); } else { v4l2_std_id std = V4L2_STD_PAL_BG; @@ -801,7 +801,7 @@ static int std_callback(struct saa7146_dev *dev, struct saa7146_standard *standa saa7146_write(dev, GPIO_CTRL, 0x00404050); /* set the 7111 gpio register -- I don't know what this does exactly */ saa7111a_call(mxb, core, s_gpio, 1); - tuner_call(mxb, tuner, s_std, std); + tuner_call(mxb, core, s_std, std); } return 0; } diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c index c7740866c..1c2f8286b 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -2965,7 +2965,7 @@ static void pvr2_subdev_update(struct pvr2_hdw *hdw) v4l2_std_id vs; vs = hdw->std_mask_cur; v4l2_device_call_all(&hdw->v4l2_dev, 0, - tuner, s_std, vs); + core, s_std, vs); } hdw->tuner_signal_stale = !0; hdw->cropcap_stale = !0; diff --git a/linux/drivers/media/video/saa7110.c b/linux/drivers/media/video/saa7110.c index bb58477e5..d26737735 100644 --- a/linux/drivers/media/video/saa7110.c +++ b/linux/drivers/media/video/saa7110.c @@ -420,9 +420,6 @@ static const struct v4l2_subdev_core_ops saa7110_core_ops = { .g_ctrl = saa7110_g_ctrl, .s_ctrl = saa7110_s_ctrl, .queryctrl = saa7110_queryctrl, -}; - -static const struct v4l2_subdev_tuner_ops saa7110_tuner_ops = { .s_std = saa7110_s_std, }; @@ -435,7 +432,6 @@ static const struct v4l2_subdev_video_ops saa7110_video_ops = { static const struct v4l2_subdev_ops saa7110_ops = { .core = &saa7110_core_ops, - .tuner = &saa7110_tuner_ops, .video = &saa7110_video_ops, }; diff --git a/linux/drivers/media/video/saa7115.c b/linux/drivers/media/video/saa7115.c index 448d51b58..f4f624583 100644 --- a/linux/drivers/media/video/saa7115.c +++ b/linux/drivers/media/video/saa7115.c @@ -1509,6 +1509,7 @@ static const struct v4l2_subdev_core_ops saa711x_core_ops = { .g_ctrl = saa711x_g_ctrl, .s_ctrl = saa711x_s_ctrl, .queryctrl = saa711x_queryctrl, + .s_std = saa711x_s_std, .reset = saa711x_reset, .s_gpio = saa711x_s_gpio, #ifdef CONFIG_VIDEO_ADV_DEBUG @@ -1518,7 +1519,6 @@ static const struct v4l2_subdev_core_ops saa711x_core_ops = { }; static const struct v4l2_subdev_tuner_ops saa711x_tuner_ops = { - .s_std = saa711x_s_std, .s_radio = saa711x_s_radio, .g_tuner = saa711x_g_tuner, }; diff --git a/linux/drivers/media/video/saa7134/saa6752hs.c b/linux/drivers/media/video/saa7134/saa6752hs.c index 2b82466d4..a96e0bb1f 100644 --- a/linux/drivers/media/video/saa7134/saa6752hs.c +++ b/linux/drivers/media/video/saa7134/saa6752hs.c @@ -935,9 +935,6 @@ static const struct v4l2_subdev_core_ops saa6752hs_core_ops = { .g_ext_ctrls = saa6752hs_g_ext_ctrls, .s_ext_ctrls = saa6752hs_s_ext_ctrls, .try_ext_ctrls = saa6752hs_try_ext_ctrls, -}; - -static const struct v4l2_subdev_tuner_ops saa6752hs_tuner_ops = { .s_std = saa6752hs_s_std, }; @@ -948,7 +945,6 @@ static const struct v4l2_subdev_video_ops saa6752hs_video_ops = { static const struct v4l2_subdev_ops saa6752hs_ops = { .core = &saa6752hs_core_ops, - .tuner = &saa6752hs_tuner_ops, .video = &saa6752hs_video_ops, }; diff --git a/linux/drivers/media/video/saa7134/saa7134-video.c b/linux/drivers/media/video/saa7134/saa7134-video.c index d7117b935..5f68bed54 100644 --- a/linux/drivers/media/video/saa7134/saa7134-video.c +++ b/linux/drivers/media/video/saa7134/saa7134-video.c @@ -625,10 +625,10 @@ void saa7134_set_tvnorm_hw(struct saa7134_dev *dev) saa7134_set_decoder(dev); if (card_in(dev, dev->ctl_input).tv) - saa_call_all(dev, tuner, s_std, dev->tvnorm->id); + saa_call_all(dev, core, s_std, dev->tvnorm->id); /* Set the correct norm for the saa6752hs. This function does nothing if there is no saa6752hs. */ - saa_call_empress(dev, tuner, s_std, dev->tvnorm->id); + saa_call_empress(dev, core, s_std, dev->tvnorm->id); } static void set_h_prescale(struct saa7134_dev *dev, int task, int prescale) diff --git a/linux/drivers/media/video/saa717x.c b/linux/drivers/media/video/saa717x.c index ae8fcde9d..1274adeeb 100644 --- a/linux/drivers/media/video/saa717x.c +++ b/linux/drivers/media/video/saa717x.c @@ -1396,12 +1396,12 @@ static const struct v4l2_subdev_core_ops saa717x_core_ops = { .queryctrl = saa717x_queryctrl, .g_ctrl = saa717x_g_ctrl, .s_ctrl = saa717x_s_ctrl, + .s_std = saa717x_s_std, }; static const struct v4l2_subdev_tuner_ops saa717x_tuner_ops = { .g_tuner = saa717x_g_tuner, .s_tuner = saa717x_s_tuner, - .s_std = saa717x_s_std, .s_radio = saa717x_s_radio, }; diff --git a/linux/drivers/media/video/saa7191.c b/linux/drivers/media/video/saa7191.c index 0a14ab6db..d78fa294a 100644 --- a/linux/drivers/media/video/saa7191.c +++ b/linux/drivers/media/video/saa7191.c @@ -588,9 +588,6 @@ static const struct v4l2_subdev_core_ops saa7191_core_ops = { .g_chip_ident = saa7191_g_chip_ident, .g_ctrl = saa7191_g_ctrl, .s_ctrl = saa7191_s_ctrl, -}; - -static const struct v4l2_subdev_tuner_ops saa7191_tuner_ops = { .s_std = saa7191_s_std, }; @@ -603,7 +600,6 @@ static const struct v4l2_subdev_video_ops saa7191_video_ops = { static const struct v4l2_subdev_ops saa7191_ops = { .core = &saa7191_core_ops, .video = &saa7191_video_ops, - .tuner = &saa7191_tuner_ops, }; static int saa7191_probe(struct i2c_client *client, diff --git a/linux/drivers/media/video/tuner-core.c b/linux/drivers/media/video/tuner-core.c index 4b68c5394..ab1eb58ea 100644 --- a/linux/drivers/media/video/tuner-core.c +++ b/linux/drivers/media/video/tuner-core.c @@ -1005,10 +1005,10 @@ static int tuner_command(struct i2c_client *client, unsigned cmd, void *arg) static const struct v4l2_subdev_core_ops tuner_core_ops = { .log_status = tuner_log_status, + .s_std = tuner_s_std, }; static const struct v4l2_subdev_tuner_ops tuner_tuner_ops = { - .s_std = tuner_s_std, .s_radio = tuner_s_radio, .g_tuner = tuner_g_tuner, .s_tuner = tuner_s_tuner, diff --git a/linux/drivers/media/video/tvaudio.c b/linux/drivers/media/video/tvaudio.c index 28caf6ef3..8e396af46 100644 --- a/linux/drivers/media/video/tvaudio.c +++ b/linux/drivers/media/video/tvaudio.c @@ -1935,12 +1935,12 @@ static const struct v4l2_subdev_core_ops tvaudio_core_ops = { .queryctrl = tvaudio_queryctrl, .g_ctrl = tvaudio_g_ctrl, .s_ctrl = tvaudio_s_ctrl, + .s_std = tvaudio_s_std, }; static const struct v4l2_subdev_tuner_ops tvaudio_tuner_ops = { .s_radio = tvaudio_s_radio, .s_frequency = tvaudio_s_frequency, - .s_std = tvaudio_s_std, .s_tuner = tvaudio_s_tuner, .s_tuner = tvaudio_g_tuner, }; diff --git a/linux/drivers/media/video/tvp5150.c b/linux/drivers/media/video/tvp5150.c index 3b1eab033..80fd240d1 100644 --- a/linux/drivers/media/video/tvp5150.c +++ b/linux/drivers/media/video/tvp5150.c @@ -1102,6 +1102,7 @@ static const struct v4l2_subdev_core_ops tvp5150_core_ops = { .g_ctrl = tvp5150_g_ctrl, .s_ctrl = tvp5150_s_ctrl, .queryctrl = tvp5150_queryctrl, + .s_std = tvp5150_s_std, .reset = tvp5150_reset, .g_chip_ident = tvp5150_g_chip_ident, #ifdef CONFIG_VIDEO_ADV_DEBUG @@ -1111,7 +1112,6 @@ static const struct v4l2_subdev_core_ops tvp5150_core_ops = { }; static const struct v4l2_subdev_tuner_ops tvp5150_tuner_ops = { - .s_std = tvp5150_s_std, .g_tuner = tvp5150_g_tuner, }; diff --git a/linux/drivers/media/video/usbvision/usbvision-video.c b/linux/drivers/media/video/usbvision/usbvision-video.c index fa62a2fd7..af06eb2f8 100644 --- a/linux/drivers/media/video/usbvision/usbvision-video.c +++ b/linux/drivers/media/video/usbvision/usbvision-video.c @@ -621,7 +621,7 @@ static int vidioc_s_std (struct file *file, void *priv, v4l2_std_id *id) usbvision->tvnormId=*id; mutex_lock(&usbvision->lock); - call_all(usbvision, tuner, s_std, usbvision->tvnormId); + call_all(usbvision, core, s_std, usbvision->tvnormId); mutex_unlock(&usbvision->lock); /* propagate the change to the decoder */ usbvision_muxsel(usbvision, usbvision->ctl_input); diff --git a/linux/drivers/media/video/vino.c b/linux/drivers/media/video/vino.c index 274b99b56..7b22043b3 100644 --- a/linux/drivers/media/video/vino.c +++ b/linux/drivers/media/video/vino.c @@ -2593,7 +2593,7 @@ static int vino_acquire_input(struct vino_channel_settings *vcs) } if (data_norm == 3) data_norm = VINO_DATA_NORM_PAL; - ret = decoder_call(tuner, s_std, norm); + ret = decoder_call(core, s_std, norm); } spin_lock_irqsave(&vino_drvdata->input_lock, flags); @@ -2683,7 +2683,7 @@ static int vino_set_input(struct vino_channel_settings *vcs, int input) } if (data_norm == 3) data_norm = VINO_DATA_NORM_PAL; - ret = decoder_call(tuner, s_std, norm); + ret = decoder_call(core, s_std, norm); } spin_lock_irqsave(&vino_drvdata->input_lock, flags); @@ -2817,7 +2817,7 @@ static int vino_set_data_norm(struct vino_channel_settings *vcs, * as it may take a while... */ norm = vino_data_norms[data_norm].std; - err = decoder_call(tuner, s_std, norm); + err = decoder_call(core, s_std, norm); spin_lock_irqsave(&vino_drvdata->input_lock, *flags); diff --git a/linux/drivers/media/video/vp27smpx.c b/linux/drivers/media/video/vp27smpx.c index be046e961..710c3aeca 100644 --- a/linux/drivers/media/video/vp27smpx.c +++ b/linux/drivers/media/video/vp27smpx.c @@ -140,11 +140,11 @@ static int vp27smpx_log_status(struct v4l2_subdev *sd) static const struct v4l2_subdev_core_ops vp27smpx_core_ops = { .log_status = vp27smpx_log_status, .g_chip_ident = vp27smpx_g_chip_ident, + .s_std = vp27smpx_s_std, }; static const struct v4l2_subdev_tuner_ops vp27smpx_tuner_ops = { .s_radio = vp27smpx_s_radio, - .s_std = vp27smpx_s_std, .s_tuner = vp27smpx_s_tuner, .g_tuner = vp27smpx_g_tuner, }; diff --git a/linux/drivers/media/video/vpx3220.c b/linux/drivers/media/video/vpx3220.c index 224c899d1..962e9d539 100644 --- a/linux/drivers/media/video/vpx3220.c +++ b/linux/drivers/media/video/vpx3220.c @@ -536,9 +536,6 @@ static const struct v4l2_subdev_core_ops vpx3220_core_ops = { .g_ctrl = vpx3220_g_ctrl, .s_ctrl = vpx3220_s_ctrl, .queryctrl = vpx3220_queryctrl, -}; - -static const struct v4l2_subdev_tuner_ops vpx3220_tuner_ops = { .s_std = vpx3220_s_std, }; @@ -551,7 +548,6 @@ static const struct v4l2_subdev_video_ops vpx3220_video_ops = { static const struct v4l2_subdev_ops vpx3220_ops = { .core = &vpx3220_core_ops, - .tuner = &vpx3220_tuner_ops, .video = &vpx3220_video_ops, }; diff --git a/linux/drivers/media/video/zoran/zoran_device.c b/linux/drivers/media/video/zoran/zoran_device.c index 54a04ea5c..b2880095c 100644 --- a/linux/drivers/media/video/zoran/zoran_device.c +++ b/linux/drivers/media/video/zoran/zoran_device.c @@ -1590,7 +1590,7 @@ zoran_init_hardware (struct zoran *zr) route.input = zr->card.input[zr->input].muxsel; decoder_call(zr, core, init, 0); - decoder_call(zr, tuner, s_std, zr->norm); + decoder_call(zr, core, s_std, zr->norm); decoder_call(zr, video, s_routing, &route); encoder_call(zr, core, init, 0); diff --git a/linux/drivers/media/video/zoran/zoran_driver.c b/linux/drivers/media/video/zoran/zoran_driver.c index c702ea0fe..b965a316c 100644 --- a/linux/drivers/media/video/zoran/zoran_driver.c +++ b/linux/drivers/media/video/zoran/zoran_driver.c @@ -1457,7 +1457,7 @@ zoran_set_norm (struct zoran *zr, v4l2_std_id std = 0; decoder_call(zr, video, querystd, &std); - decoder_call(zr, tuner, s_std, std); + decoder_call(zr, core, s_std, std); /* let changes come into effect */ ssleep(2); @@ -1469,7 +1469,7 @@ zoran_set_norm (struct zoran *zr, "%s: %s - no norm detected\n", ZR_DEVNAME(zr), __func__); /* reset norm */ - decoder_call(zr, tuner, s_std, zr->norm); + decoder_call(zr, core, s_std, zr->norm); return -EIO; } @@ -1488,7 +1488,7 @@ zoran_set_norm (struct zoran *zr, if (on) zr36057_overlay(zr, 0); - decoder_call(zr, tuner, s_std, norm); + decoder_call(zr, core, s_std, norm); encoder_call(zr, video, s_std_output, norm); if (on) -- cgit v1.2.3 From 221b2e5d87ca670a9b764323c59445f1b6e3df27 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 30 Mar 2009 00:40:01 +0200 Subject: v4l2: remove legacy fields in v4l2-i2c-drv.h. From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/saa7115.c | 2 ++ linux/drivers/media/video/tuner-core.c | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/saa7115.c b/linux/drivers/media/video/saa7115.c index f4f624583..a5ae39f35 100644 --- a/linux/drivers/media/video/saa7115.c +++ b/linux/drivers/media/video/saa7115.c @@ -1686,7 +1686,9 @@ static struct v4l2_i2c_driver_data v4l2_i2c_data = { .name = "saa7115", .probe = saa711x_probe, .remove = saa711x_remove, +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22) .legacy_class = I2C_CLASS_TV_ANALOG | I2C_CLASS_TV_DIGITAL, +#endif #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) .id_table = saa7115_id, #endif diff --git a/linux/drivers/media/video/tuner-core.c b/linux/drivers/media/video/tuner-core.c index ab1eb58ea..6e7ea623b 100644 --- a/linux/drivers/media/video/tuner-core.c +++ b/linux/drivers/media/video/tuner-core.c @@ -1044,7 +1044,7 @@ static void tuner_lookup(struct i2c_adapter *adap, int mode_mask; if (pos->i2c->adapter != adap || - pos->i2c->driver->id != I2C_DRIVERID_TUNER) + strcmp(pos->i2c->driver->driver.name, "tuner")) continue; mode_mask = pos->mode_mask & ~T_STANDBY; -- cgit v1.2.3 From 1784ea5527ed756f946958f45f74d1f15797c366 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 30 Mar 2009 01:04:44 +0200 Subject: v4l2: use old-style i2c API for kernels < 2.6.26 instead of < 2.6.22 From: Hans Verkuil Originally the intention was to switch to the new style i2c API starting with the introduction of the API in 2.6.22. However, the i2c_new_probed_device() function has a lethal bug that wasn't fixed until 2.6.25. Or more accurately, it was only fixed in the stable series of 2.6.25 and 2.6.26. Given the fact that the new i2c API also changed starting with 2.6.26 (the addition of i2c_device_id), it is easiest to switch APIs starting with 2.6.26. This patch updates all the legacy code accordingly. Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/common/saa7146_i2c.c | 4 +- linux/drivers/media/dvb/frontends/au8522_decoder.c | 2 +- linux/drivers/media/video/adv7170.c | 2 +- linux/drivers/media/video/adv7175.c | 2 +- linux/drivers/media/video/bt819.c | 2 +- linux/drivers/media/video/bt856.c | 2 +- linux/drivers/media/video/bt866.c | 2 +- linux/drivers/media/video/bt8xx/bttv-i2c.c | 4 +- linux/drivers/media/video/cs5345.c | 2 +- linux/drivers/media/video/cs53l32a.c | 2 +- linux/drivers/media/video/cx18/cx18-i2c.c | 2 +- linux/drivers/media/video/cx23885/cx23885-i2c.c | 2 +- linux/drivers/media/video/cx25840/cx25840-core.c | 2 +- linux/drivers/media/video/cx88/cx88-i2c.c | 2 +- linux/drivers/media/video/cx88/cx88-video.c | 2 +- linux/drivers/media/video/indycam.c | 2 +- linux/drivers/media/video/ivtv/ivtv-i2c.c | 4 +- linux/drivers/media/video/ks0127.c | 2 +- linux/drivers/media/video/m52790.c | 2 +- linux/drivers/media/video/msp3400-driver.c | 2 +- linux/drivers/media/video/mxb.c | 2 +- .../drivers/media/video/ovcamchip/ovcamchip_core.c | 2 +- linux/drivers/media/video/saa5246a.c | 2 +- linux/drivers/media/video/saa5249.c | 2 +- linux/drivers/media/video/saa6588.c | 2 +- linux/drivers/media/video/saa7110.c | 2 +- linux/drivers/media/video/saa7115.c | 7 ++-- linux/drivers/media/video/saa7127.c | 2 +- linux/drivers/media/video/saa7134/saa6752hs.c | 2 +- linux/drivers/media/video/saa7134/saa7134-i2c.c | 2 +- linux/drivers/media/video/saa717x.c | 2 +- linux/drivers/media/video/saa7185.c | 2 +- linux/drivers/media/video/saa7191.c | 2 +- linux/drivers/media/video/tda7432.c | 2 +- linux/drivers/media/video/tda9840.c | 13 +++---- linux/drivers/media/video/tda9875.c | 2 +- linux/drivers/media/video/tea6415c.c | 13 +++---- linux/drivers/media/video/tea6420.c | 13 +++---- linux/drivers/media/video/tlv320aic23b.c | 2 +- linux/drivers/media/video/tuner-core.c | 43 ++++++++++------------ linux/drivers/media/video/tvaudio.c | 13 +++---- linux/drivers/media/video/tvp5150.c | 7 ++-- linux/drivers/media/video/upd64031a.c | 2 +- linux/drivers/media/video/upd64083.c | 2 +- linux/drivers/media/video/v4l2-common.c | 24 ++++-------- linux/drivers/media/video/vp27smpx.c | 2 +- linux/drivers/media/video/vpx3220.c | 2 +- linux/drivers/media/video/w9968cf.c | 2 +- linux/drivers/media/video/wm8739.c | 2 +- linux/drivers/media/video/wm8775.c | 2 +- 50 files changed, 99 insertions(+), 124 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/common/saa7146_i2c.c b/linux/drivers/media/common/saa7146_i2c.c index fa9d4f90a..fc2c95a16 100644 --- a/linux/drivers/media/common/saa7146_i2c.c +++ b/linux/drivers/media/common/saa7146_i2c.c @@ -414,8 +414,8 @@ int saa7146_i2c_adapter_prepare(struct saa7146_dev *dev, struct i2c_adapter *i2c saa7146_i2c_reset(dev); if (i2c_adapter) { -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22) - /* For kernels > 2.6.22 it can actually be NULL +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26) + /* For kernels > 2.6.26 it can actually be NULL when v4l2_subdev is used. */ BUG_ON(!i2c_adapter->class); #endif diff --git a/linux/drivers/media/dvb/frontends/au8522_decoder.c b/linux/drivers/media/dvb/frontends/au8522_decoder.c index 326f94d1e..81d517765 100644 --- a/linux/drivers/media/dvb/frontends/au8522_decoder.c +++ b/linux/drivers/media/dvb/frontends/au8522_decoder.c @@ -48,7 +48,7 @@ MODULE_LICENSE("GPL"); static int au8522_analog_debug; -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22) +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26) static unsigned short normal_i2c[] = { 0x8e >> 1, I2C_CLIENT_END }; I2C_CLIENT_INSMOD; diff --git a/linux/drivers/media/video/adv7170.c b/linux/drivers/media/video/adv7170.c index 04e6125f2..0ce6007bb 100644 --- a/linux/drivers/media/video/adv7170.c +++ b/linux/drivers/media/video/adv7170.c @@ -44,7 +44,7 @@ MODULE_DESCRIPTION("Analog Devices ADV7170 video encoder driver"); MODULE_AUTHOR("Maxim Yevtyushkin"); MODULE_LICENSE("GPL"); -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22) +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26) static unsigned short normal_i2c[] = { 0xd4 >> 1, 0xd6 >> 1, /* adv7170 IDs */ 0x54 >> 1, 0x56 >> 1, /* adv7171 IDs */ diff --git a/linux/drivers/media/video/adv7175.c b/linux/drivers/media/video/adv7175.c index c38f648f8..ffbfb7140 100644 --- a/linux/drivers/media/video/adv7175.c +++ b/linux/drivers/media/video/adv7175.c @@ -43,7 +43,7 @@ MODULE_LICENSE("GPL"); #define I2C_ADV7175 0xd4 #define I2C_ADV7176 0x54 -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22) +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26) static unsigned short normal_i2c[] = { I2C_ADV7175 >> 1, (I2C_ADV7175 >> 1) + 1, I2C_ADV7176 >> 1, (I2C_ADV7176 >> 1) + 1, diff --git a/linux/drivers/media/video/bt819.c b/linux/drivers/media/video/bt819.c index 5929e05ff..df4fe8d9a 100644 --- a/linux/drivers/media/video/bt819.c +++ b/linux/drivers/media/video/bt819.c @@ -49,7 +49,7 @@ static int debug; module_param(debug, int, 0); MODULE_PARM_DESC(debug, "Debug level (0-1)"); -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22) +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26) static unsigned short normal_i2c[] = { 0x8a >> 1, I2C_CLIENT_END }; I2C_CLIENT_INSMOD; diff --git a/linux/drivers/media/video/bt856.c b/linux/drivers/media/video/bt856.c index ab56d7d6e..ef9c3d1c7 100644 --- a/linux/drivers/media/video/bt856.c +++ b/linux/drivers/media/video/bt856.c @@ -48,7 +48,7 @@ static int debug; module_param(debug, int, 0); MODULE_PARM_DESC(debug, "Debug level (0-1)"); -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22) +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26) static unsigned short normal_i2c[] = { 0x88 >> 1, I2C_CLIENT_END }; I2C_CLIENT_INSMOD; diff --git a/linux/drivers/media/video/bt866.c b/linux/drivers/media/video/bt866.c index 5ea31375e..87845f34c 100644 --- a/linux/drivers/media/video/bt866.c +++ b/linux/drivers/media/video/bt866.c @@ -48,7 +48,7 @@ static int debug; module_param(debug, int, 0); MODULE_PARM_DESC(debug, "Debug level (0-1)"); -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22) +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26) static unsigned short normal_i2c[] = { 0x88 >> 1, I2C_CLIENT_END }; I2C_CLIENT_INSMOD; diff --git a/linux/drivers/media/video/bt8xx/bttv-i2c.c b/linux/drivers/media/video/bt8xx/bttv-i2c.c index dbb21f77b..bf94551c3 100644 --- a/linux/drivers/media/video/bt8xx/bttv-i2c.c +++ b/linux/drivers/media/video/bt8xx/bttv-i2c.c @@ -377,7 +377,7 @@ int __devinit init_bttv_i2c(struct bttv *btv) btv->c.i2c_adap.algo_data = &btv->i2c_algo; } btv->c.i2c_adap.owner = THIS_MODULE; -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22) +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26) btv->c.i2c_adap.class = I2C_CLASS_TV_ANALOG; #endif @@ -389,7 +389,7 @@ int __devinit init_bttv_i2c(struct bttv *btv) i2c_set_adapdata(&btv->c.i2c_adap, &btv->c.v4l2_dev); btv->i2c_client.adapter = &btv->c.i2c_adap; -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22) +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26) if (bttv_tvcards[btv->c.type].no_video) btv->c.i2c_adap.class &= ~I2C_CLASS_TV_ANALOG; if (bttv_tvcards[btv->c.type].has_dvb) diff --git a/linux/drivers/media/video/cs5345.c b/linux/drivers/media/video/cs5345.c index 3e018b558..bc98ec17a 100644 --- a/linux/drivers/media/video/cs5345.c +++ b/linux/drivers/media/video/cs5345.c @@ -37,7 +37,7 @@ module_param(debug, bool, 0644); MODULE_PARM_DESC(debug, "Debugging messages, 0=Off (default), 1=On"); -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22) +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26) static unsigned short normal_i2c[] = { 0x98 >> 1, I2C_CLIENT_END }; I2C_CLIENT_INSMOD; diff --git a/linux/drivers/media/video/cs53l32a.c b/linux/drivers/media/video/cs53l32a.c index 4745fd21c..a2e1f677d 100644 --- a/linux/drivers/media/video/cs53l32a.c +++ b/linux/drivers/media/video/cs53l32a.c @@ -42,7 +42,7 @@ module_param(debug, bool, 0644); MODULE_PARM_DESC(debug, "Debugging messages, 0=Off (default), 1=On"); -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22) +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26) static unsigned short normal_i2c[] = { 0x22 >> 1, I2C_CLIENT_END }; I2C_CLIENT_INSMOD; diff --git a/linux/drivers/media/video/cx18/cx18-i2c.c b/linux/drivers/media/video/cx18/cx18-i2c.c index bf15b648d..6c3c0449c 100644 --- a/linux/drivers/media/video/cx18/cx18-i2c.c +++ b/linux/drivers/media/video/cx18/cx18-i2c.c @@ -194,7 +194,7 @@ static struct i2c_adapter cx18_i2c_adap_template = { .algo = NULL, /* set by i2c-algo-bit */ .algo_data = NULL, /* filled from template */ .owner = THIS_MODULE, -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22) +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26) .class = I2C_CLASS_TV_ANALOG, #endif }; diff --git a/linux/drivers/media/video/cx23885/cx23885-i2c.c b/linux/drivers/media/video/cx23885/cx23885-i2c.c index 3b0b9d3e3..a5d9f7530 100644 --- a/linux/drivers/media/video/cx23885/cx23885-i2c.c +++ b/linux/drivers/media/video/cx23885/cx23885-i2c.c @@ -289,7 +289,7 @@ static struct i2c_adapter cx23885_i2c_adap_template = { .owner = THIS_MODULE, .id = I2C_HW_B_CX23885, .algo = &cx23885_i2c_algo_template, -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22) +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26) .class = I2C_CLASS_TV_ANALOG, #endif }; diff --git a/linux/drivers/media/video/cx25840/cx25840-core.c b/linux/drivers/media/video/cx25840/cx25840-core.c index e5bf756e5..11f5ddce4 100644 --- a/linux/drivers/media/video/cx25840/cx25840-core.c +++ b/linux/drivers/media/video/cx25840/cx25840-core.c @@ -55,7 +55,7 @@ module_param_named(debug,cx25840_debug, int, 0644); MODULE_PARM_DESC(debug, "Debugging messages [0=Off (default) 1=On]"); -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22) +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26) static unsigned short normal_i2c[] = { 0x88 >> 1, I2C_CLIENT_END }; I2C_CLIENT_INSMOD; diff --git a/linux/drivers/media/video/cx88/cx88-i2c.c b/linux/drivers/media/video/cx88/cx88-i2c.c index 718f1ce69..680a8c889 100644 --- a/linux/drivers/media/video/cx88/cx88-i2c.c +++ b/linux/drivers/media/video/cx88/cx88-i2c.c @@ -142,7 +142,7 @@ int cx88_i2c_init(struct cx88_core *core, struct pci_dev *pci) memcpy(&core->i2c_algo, &cx8800_i2c_algo_template, sizeof(core->i2c_algo)); -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22) +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26) if (core->board.tuner_type != TUNER_ABSENT) core->i2c_adap.class |= I2C_CLASS_TV_ANALOG; if (core->board.mpeg & CX88_MPEG_DVB) diff --git a/linux/drivers/media/video/cx88/cx88-video.c b/linux/drivers/media/video/cx88/cx88-video.c index a3fd7f643..7e642b6f3 100644 --- a/linux/drivers/media/video/cx88/cx88-video.c +++ b/linux/drivers/media/video/cx88/cx88-video.c @@ -2173,7 +2173,7 @@ static int __devinit cx8800_initdev(struct pci_dev *pci_dev, switch (core->boardnr) { case CX88_BOARD_DVICO_FUSIONHDTV_5_GOLD: case CX88_BOARD_DVICO_FUSIONHDTV_7_GOLD: { -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 22) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) static struct i2c_board_info rtc_info = { I2C_BOARD_INFO("isl1208", 0x6f) }; diff --git a/linux/drivers/media/video/indycam.c b/linux/drivers/media/video/indycam.c index f2da0550b..e1aa39bd5 100644 --- a/linux/drivers/media/video/indycam.c +++ b/linux/drivers/media/video/indycam.c @@ -35,7 +35,7 @@ MODULE_VERSION(INDYCAM_MODULE_VERSION); MODULE_AUTHOR("Mikael Nousiainen "); MODULE_LICENSE("GPL"); -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22) +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26) static unsigned short normal_i2c[] = { 0x56 >> 1, I2C_CLIENT_END }; I2C_CLIENT_INSMOD; diff --git a/linux/drivers/media/video/ivtv/ivtv-i2c.c b/linux/drivers/media/video/ivtv/ivtv-i2c.c index 682377c1a..3f4552469 100644 --- a/linux/drivers/media/video/ivtv/ivtv-i2c.c +++ b/linux/drivers/media/video/ivtv/ivtv-i2c.c @@ -517,7 +517,7 @@ static struct i2c_adapter ivtv_i2c_adap_hw_template = { .algo = &ivtv_algo, .algo_data = NULL, /* filled from template */ .owner = THIS_MODULE, -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22) +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26) .class = I2C_CLASS_TV_ANALOG, #endif }; @@ -571,7 +571,7 @@ static struct i2c_adapter ivtv_i2c_adap_template = { .algo = NULL, /* set by i2c-algo-bit */ .algo_data = NULL, /* filled from template */ .owner = THIS_MODULE, -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22) +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26) .class = I2C_CLASS_TV_ANALOG, #endif }; diff --git a/linux/drivers/media/video/ks0127.c b/linux/drivers/media/video/ks0127.c index 198971b75..c413a1d9b 100644 --- a/linux/drivers/media/video/ks0127.c +++ b/linux/drivers/media/video/ks0127.c @@ -54,7 +54,7 @@ MODULE_LICENSE("GPL"); #define I2C_KS0127_ADDON 0xD8 #define I2C_KS0127_ONBOARD 0xDA -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22) +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26) static unsigned short normal_i2c[] = { I2C_KS0127_ADDON >> 1, I2C_KS0127_ONBOARD >> 1, diff --git a/linux/drivers/media/video/m52790.c b/linux/drivers/media/video/m52790.c index 203a60348..40bdf8857 100644 --- a/linux/drivers/media/video/m52790.c +++ b/linux/drivers/media/video/m52790.c @@ -37,7 +37,7 @@ MODULE_DESCRIPTION("i2c device driver for m52790 A/V switch"); MODULE_AUTHOR("Hans Verkuil"); MODULE_LICENSE("GPL"); -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22) +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26) static unsigned short normal_i2c[] = { 0x90 >> 1, I2C_CLIENT_END }; I2C_CLIENT_INSMOD; diff --git a/linux/drivers/media/video/msp3400-driver.c b/linux/drivers/media/video/msp3400-driver.c index 5b63af6f8..7a2b87621 100644 --- a/linux/drivers/media/video/msp3400-driver.c +++ b/linux/drivers/media/video/msp3400-driver.c @@ -113,7 +113,7 @@ MODULE_PARM_DESC(dolby, "Activates Dolby processsing"); /* DSP unit subaddress */ #define I2C_MSP_DSP 0x12 -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22) +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26) /* Addresses to scan */ static unsigned short normal_i2c[] = { 0x80 >> 1, 0x88 >> 1, I2C_CLIENT_END }; diff --git a/linux/drivers/media/video/mxb.c b/linux/drivers/media/video/mxb.c index 93209d160..af08a3df3 100644 --- a/linux/drivers/media/video/mxb.c +++ b/linux/drivers/media/video/mxb.c @@ -160,7 +160,7 @@ static int mxb_probe(struct saa7146_dev *dev) return -ENOMEM; } -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22) +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26) mxb->i2c_adapter.class = I2C_CLASS_TV_ANALOG; #endif snprintf(mxb->i2c_adapter.name, sizeof(mxb->i2c_adapter.name), "mxb%d", mxb_num); diff --git a/linux/drivers/media/video/ovcamchip/ovcamchip_core.c b/linux/drivers/media/video/ovcamchip/ovcamchip_core.c index 8de129b41..cfeb62645 100644 --- a/linux/drivers/media/video/ovcamchip/ovcamchip_core.c +++ b/linux/drivers/media/video/ovcamchip/ovcamchip_core.c @@ -47,7 +47,7 @@ MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22) +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26) static unsigned short normal_i2c[] = { /* ov7xxx */ 0x42 >> 1, 0x46 >> 1, 0x4a >> 1, 0x4e >> 1, diff --git a/linux/drivers/media/video/saa5246a.c b/linux/drivers/media/video/saa5246a.c index d7faf20bc..a5e9a8c2e 100644 --- a/linux/drivers/media/video/saa5246a.c +++ b/linux/drivers/media/video/saa5246a.c @@ -387,7 +387,7 @@ MODULE_LICENSE("GPL"); #define MINUTE_MAX 0x59 #define PAGE_MAX 0x8FF -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22) +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26) static unsigned short normal_i2c[] = { 0x11, I2C_CLIENT_END }; I2C_CLIENT_INSMOD; diff --git a/linux/drivers/media/video/saa5249.c b/linux/drivers/media/video/saa5249.c index 12f48ebd3..e5643b2b6 100644 --- a/linux/drivers/media/video/saa5249.c +++ b/linux/drivers/media/video/saa5249.c @@ -61,7 +61,7 @@ MODULE_AUTHOR("Michael Geng "); MODULE_DESCRIPTION("Philips SAA5249 Teletext decoder driver"); MODULE_LICENSE("GPL"); -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22) +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26) static unsigned short normal_i2c[] = { 0x11, I2C_CLIENT_END }; I2C_CLIENT_INSMOD; diff --git a/linux/drivers/media/video/saa6588.c b/linux/drivers/media/video/saa6588.c index 60934e0a9..58aff8305 100644 --- a/linux/drivers/media/video/saa6588.c +++ b/linux/drivers/media/video/saa6588.c @@ -37,7 +37,7 @@ #include #include "compat.h" -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22) +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26) /* Addresses to scan */ static unsigned short normal_i2c[] = { 0x20 >> 1, diff --git a/linux/drivers/media/video/saa7110.c b/linux/drivers/media/video/saa7110.c index d26737735..0eeae294f 100644 --- a/linux/drivers/media/video/saa7110.c +++ b/linux/drivers/media/video/saa7110.c @@ -43,7 +43,7 @@ MODULE_DESCRIPTION("Philips SAA7110 video decoder driver"); MODULE_AUTHOR("Pauline Middelink"); MODULE_LICENSE("GPL"); -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22) +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26) static unsigned short normal_i2c[] = { 0x9c >> 1, 0x9e >> 1, I2C_CLIENT_END }; I2C_CLIENT_INSMOD; diff --git a/linux/drivers/media/video/saa7115.c b/linux/drivers/media/video/saa7115.c index a5ae39f35..ea23b7cb1 100644 --- a/linux/drivers/media/video/saa7115.c +++ b/linux/drivers/media/video/saa7115.c @@ -63,7 +63,7 @@ module_param(debug, bool, 0644); MODULE_PARM_DESC(debug, "Debug level (0-1)"); -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22) +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26) static unsigned short normal_i2c[] = { 0x4a >> 1, 0x48 >> 1, /* SAA7111, SAA7111A and SAA7113 */ 0x42 >> 1, 0x40 >> 1, /* SAA7114, SAA7115 and SAA7118 */ @@ -1686,10 +1686,9 @@ static struct v4l2_i2c_driver_data v4l2_i2c_data = { .name = "saa7115", .probe = saa711x_probe, .remove = saa711x_remove, -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22) +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26) .legacy_class = I2C_CLASS_TV_ANALOG | I2C_CLASS_TV_DIGITAL, -#endif -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) +#else .id_table = saa7115_id, #endif }; diff --git a/linux/drivers/media/video/saa7127.c b/linux/drivers/media/video/saa7127.c index 9beef8886..56bd3dc4d 100644 --- a/linux/drivers/media/video/saa7127.c +++ b/linux/drivers/media/video/saa7127.c @@ -70,7 +70,7 @@ module_param(test_image, int, 0644); MODULE_PARM_DESC(debug, "debug level (0-2)"); MODULE_PARM_DESC(test_image, "test_image (0-1)"); -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22) +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26) static unsigned short normal_i2c[] = { 0x88 >> 1, I2C_CLIENT_END }; I2C_CLIENT_INSMOD; diff --git a/linux/drivers/media/video/saa7134/saa6752hs.c b/linux/drivers/media/video/saa7134/saa6752hs.c index a96e0bb1f..860f271dd 100644 --- a/linux/drivers/media/video/saa7134/saa6752hs.c +++ b/linux/drivers/media/video/saa7134/saa6752hs.c @@ -46,7 +46,7 @@ #define MPEG_TOTAL_TARGET_BITRATE_MAX 27000 #define MPEG_PID_MAX ((1 << 14) - 1) -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22) +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26) /* Addresses to scan */ static unsigned short normal_i2c[] = {0x20, 0x21, I2C_CLIENT_END}; diff --git a/linux/drivers/media/video/saa7134/saa7134-i2c.c b/linux/drivers/media/video/saa7134/saa7134-i2c.c index b77ccb5a0..3eb60aabe 100644 --- a/linux/drivers/media/video/saa7134/saa7134-i2c.c +++ b/linux/drivers/media/video/saa7134/saa7134-i2c.c @@ -363,7 +363,7 @@ static struct i2c_algorithm saa7134_algo = { static struct i2c_adapter saa7134_adap_template = { .owner = THIS_MODULE, -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22) +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26) .class = I2C_CLASS_TV_ANALOG, #endif .name = "saa7134", diff --git a/linux/drivers/media/video/saa717x.c b/linux/drivers/media/video/saa717x.c index 1274adeeb..15a44d2ce 100644 --- a/linux/drivers/media/video/saa717x.c +++ b/linux/drivers/media/video/saa717x.c @@ -52,7 +52,7 @@ MODULE_PARM_DESC(debug, "Debug level (0-1)"); * Generic i2c probe * concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1' */ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22) +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26) static unsigned short normal_i2c[] = { 0x42 >> 1, I2C_CLIENT_END }; I2C_CLIENT_INSMOD; diff --git a/linux/drivers/media/video/saa7185.c b/linux/drivers/media/video/saa7185.c index 290299451..bb3e49006 100644 --- a/linux/drivers/media/video/saa7185.c +++ b/linux/drivers/media/video/saa7185.c @@ -44,7 +44,7 @@ static int debug; module_param(debug, int, 0); MODULE_PARM_DESC(debug, "Debug level (0-1)"); -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22) +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26) static unsigned short normal_i2c[] = { 0x88 >> 1, I2C_CLIENT_END }; I2C_CLIENT_INSMOD; diff --git a/linux/drivers/media/video/saa7191.c b/linux/drivers/media/video/saa7191.c index d78fa294a..f6a6b80b6 100644 --- a/linux/drivers/media/video/saa7191.c +++ b/linux/drivers/media/video/saa7191.c @@ -35,7 +35,7 @@ MODULE_VERSION(SAA7191_MODULE_VERSION); MODULE_AUTHOR("Mikael Nousiainen "); MODULE_LICENSE("GPL"); -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22) +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26) static unsigned short normal_i2c[] = { 0x8a >> 1, 0x8e >> 1, I2C_CLIENT_END }; I2C_CLIENT_INSMOD; diff --git a/linux/drivers/media/video/tda7432.c b/linux/drivers/media/video/tda7432.c index 07c21a6d7..749539cb8 100644 --- a/linux/drivers/media/video/tda7432.c +++ b/linux/drivers/media/video/tda7432.c @@ -70,7 +70,7 @@ MODULE_PARM_DESC(maxvol,"Set maximium volume to +20db (0), default is 0db(1)"); module_param(maxvol, int, S_IRUGO | S_IWUSR); -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22) +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26) /* Address to scan (I2C address of this chip) */ static unsigned short normal_i2c[] = { I2C_ADDR_TDA7432 >> 1, diff --git a/linux/drivers/media/video/tda9840.c b/linux/drivers/media/video/tda9840.c index f6d27d581..b1fde87f3 100644 --- a/linux/drivers/media/video/tda9840.c +++ b/linux/drivers/media/video/tda9840.c @@ -57,7 +57,7 @@ MODULE_PARM_DESC(debug, "Debug level (0-1)"); #define TDA9840_SET_BOTH_R 0x16 #define TDA9840_SET_EXTERNAL 0x7a -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22) +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26) static unsigned short normal_i2c[] = { 0x42, I2C_CLIENT_END }; I2C_CLIENT_INSMOD; @@ -198,16 +198,14 @@ static int tda9840_remove(struct i2c_client *client) return 0; } -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22) +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26) static int tda9840_legacy_probe(struct i2c_adapter *adapter) { /* Let's see whether this is a known adapter we can attach to. Prevents conflicts with tvaudio.c. */ return adapter->id == I2C_HW_SAA7146; } -#endif - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) +#else static const struct i2c_device_id tda9840_id[] = { { "tda9840", 0 }, { } @@ -219,10 +217,9 @@ static struct v4l2_i2c_driver_data v4l2_i2c_data = { .name = "tda9840", .probe = tda9840_probe, .remove = tda9840_remove, -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22) +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26) .legacy_probe = tda9840_legacy_probe, -#endif -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) +#else .id_table = tda9840_id, #endif }; diff --git a/linux/drivers/media/video/tda9875.c b/linux/drivers/media/video/tda9875.c index 0351b13db..550c8b348 100644 --- a/linux/drivers/media/video/tda9875.c +++ b/linux/drivers/media/video/tda9875.c @@ -36,7 +36,7 @@ static int debug; /* insmod parameter */ module_param(debug, int, S_IRUGO | S_IWUSR); MODULE_LICENSE("GPL"); -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22) +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26) /* Addresses to scan */ static unsigned short normal_i2c[] = { I2C_ADDR_TDA9875 >> 1, diff --git a/linux/drivers/media/video/tea6415c.c b/linux/drivers/media/video/tea6415c.c index eaf29bd90..3a942d17d 100644 --- a/linux/drivers/media/video/tea6415c.c +++ b/linux/drivers/media/video/tea6415c.c @@ -46,7 +46,7 @@ module_param(debug, int, 0644); MODULE_PARM_DESC(debug, "Debug level (0-1)"); -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22) +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26) static unsigned short normal_i2c[] = { 0x03, 0x43, I2C_CLIENT_END }; I2C_CLIENT_INSMOD; @@ -176,16 +176,14 @@ static int tea6415c_remove(struct i2c_client *client) return 0; } -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22) +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26) static int tea6415c_legacy_probe(struct i2c_adapter *adapter) { /* Let's see whether this is a known adapter we can attach to. Prevents conflicts with tvaudio.c. */ return adapter->id == I2C_HW_SAA7146; } -#endif - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) +#else static const struct i2c_device_id tea6415c_id[] = { { "tea6415c", 0 }, { } @@ -197,10 +195,9 @@ static struct v4l2_i2c_driver_data v4l2_i2c_data = { .name = "tea6415c", .probe = tea6415c_probe, .remove = tea6415c_remove, -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22) +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26) .legacy_probe = tea6415c_legacy_probe, -#endif -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) +#else .id_table = tea6415c_id, #endif }; diff --git a/linux/drivers/media/video/tea6420.c b/linux/drivers/media/video/tea6420.c index 8bddef6d9..5b25c3596 100644 --- a/linux/drivers/media/video/tea6420.c +++ b/linux/drivers/media/video/tea6420.c @@ -46,7 +46,7 @@ module_param(debug, int, 0644); MODULE_PARM_DESC(debug, "Debug level (0-1)"); -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22) +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26) static unsigned short normal_i2c[] = { 0x4c, 0x4d, I2C_CLIENT_END }; I2C_CLIENT_INSMOD; @@ -162,16 +162,14 @@ static int tea6420_remove(struct i2c_client *client) return 0; } -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22) +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26) static int tea6420_legacy_probe(struct i2c_adapter *adapter) { /* Let's see whether this is a known adapter we can attach to. Prevents conflicts with tvaudio.c. */ return adapter->id == I2C_HW_SAA7146; } -#endif - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) +#else static const struct i2c_device_id tea6420_id[] = { { "tea6420", 0 }, { } @@ -183,10 +181,9 @@ static struct v4l2_i2c_driver_data v4l2_i2c_data = { .name = "tea6420", .probe = tea6420_probe, .remove = tea6420_remove, -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22) +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26) .legacy_probe = tea6420_legacy_probe, -#endif -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) +#else .id_table = tea6420_id, #endif }; diff --git a/linux/drivers/media/video/tlv320aic23b.c b/linux/drivers/media/video/tlv320aic23b.c index bfba9ac0d..4173d0eb9 100644 --- a/linux/drivers/media/video/tlv320aic23b.c +++ b/linux/drivers/media/video/tlv320aic23b.c @@ -38,7 +38,7 @@ MODULE_DESCRIPTION("tlv320aic23b driver"); MODULE_AUTHOR("Scott Alfter, Ulf Eklund, Hans Verkuil"); MODULE_LICENSE("GPL"); -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22) +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26) static unsigned short normal_i2c[] = { 0x34 >> 1, I2C_CLIENT_END }; I2C_CLIENT_INSMOD; diff --git a/linux/drivers/media/video/tuner-core.c b/linux/drivers/media/video/tuner-core.c index 6e7ea623b..9f763535e 100644 --- a/linux/drivers/media/video/tuner-core.c +++ b/linux/drivers/media/video/tuner-core.c @@ -102,7 +102,7 @@ static inline struct tuner *to_tuner(struct v4l2_subdev *sd) return container_of(sd, struct tuner, sd); } -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22) +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26) /* standard i2c insmod options */ static unsigned short normal_i2c[] = { #if defined(CONFIG_MEDIA_TUNER_TEA5761) || (defined(CONFIG_MEDIA_TUNER_TEA5761_MODULE) && defined(MODULE)) @@ -1188,7 +1188,22 @@ register_client: return 0; } -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22) +static int tuner_remove(struct i2c_client *client) +{ + struct tuner *t = to_tuner(i2c_get_clientdata(client)); + + v4l2_device_unregister_subdev(&t->sd); + tuner_detach(&t->fe); + t->fe.analog_demod_priv = NULL; + + list_del(&t->list); + kfree(t); + return 0; +} + +/* ----------------------------------------------------------------------- */ + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26) static int tuner_legacy_probe(struct i2c_adapter *adap) { if (0 != addr) { @@ -1222,24 +1237,7 @@ static int tuner_legacy_probe(struct i2c_adapter *adap) } return 1; } -#endif - -static int tuner_remove(struct i2c_client *client) -{ - struct tuner *t = to_tuner(i2c_get_clientdata(client)); - - v4l2_device_unregister_subdev(&t->sd); - tuner_detach(&t->fe); - t->fe.analog_demod_priv = NULL; - - list_del(&t->list); - kfree(t); - return 0; -} - -/* ----------------------------------------------------------------------- */ - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) +#else /* This driver supports many devices and the idea is to let the driver detect which device is present. So rather than listing all supported devices here, we pretend to support a single, fake device type. */ @@ -1257,10 +1255,9 @@ static struct v4l2_i2c_driver_data v4l2_i2c_data = { .command = tuner_command, .suspend = tuner_suspend, .resume = tuner_resume, -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22) +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26) .legacy_probe = tuner_legacy_probe, -#endif -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) +#else .id_table = tuner_id, #endif }; diff --git a/linux/drivers/media/video/tvaudio.c b/linux/drivers/media/video/tvaudio.c index 8e396af46..17bb81e9a 100644 --- a/linux/drivers/media/video/tvaudio.c +++ b/linux/drivers/media/video/tvaudio.c @@ -139,7 +139,7 @@ static inline struct CHIPSTATE *to_state(struct v4l2_subdev *sd) return container_of(sd, struct CHIPSTATE, sd); } -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22) +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26) /* ---------------------------------------------------------------------- */ /* i2c addresses */ @@ -2097,7 +2097,7 @@ static int tvaudio_remove(struct i2c_client *client) return 0; } -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22) +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26) static int tvaudio_legacy_probe(struct i2c_adapter *adap) { /* don't attach on saa7146 based cards, @@ -2108,9 +2108,7 @@ static int tvaudio_legacy_probe(struct i2c_adapter *adap) return 1; return 0; } -#endif - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) +#else /* This driver supports many devices and the idea is to let the driver detect which device is present. So rather than listing all supported devices here, we pretend to support a single, fake device type. */ @@ -2125,10 +2123,9 @@ static struct v4l2_i2c_driver_data v4l2_i2c_data = { .name = "tvaudio", .probe = tvaudio_probe, .remove = tvaudio_remove, -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22) +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26) .legacy_probe = tvaudio_legacy_probe, -#endif -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) +#else .id_table = tvaudio_id, #endif }; diff --git a/linux/drivers/media/video/tvp5150.c b/linux/drivers/media/video/tvp5150.c index 80fd240d1..490e2f2d1 100644 --- a/linux/drivers/media/video/tvp5150.c +++ b/linux/drivers/media/video/tvp5150.c @@ -20,7 +20,7 @@ MODULE_DESCRIPTION("Texas Instruments TVP5150A video decoder driver"); MODULE_AUTHOR("Mauro Carvalho Chehab"); MODULE_LICENSE("GPL"); -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22) +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26) /* standard i2c insmod options */ static unsigned short normal_i2c[] = { 0xb8 >> 1, @@ -1193,10 +1193,9 @@ static struct v4l2_i2c_driver_data v4l2_i2c_data = { .name = "tvp5150", .probe = tvp5150_probe, .remove = tvp5150_remove, -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22) +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26) .legacy_class = I2C_CLASS_TV_ANALOG | I2C_CLASS_TV_DIGITAL, -#endif -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) +#else .id_table = tvp5150_id, #endif }; diff --git a/linux/drivers/media/video/upd64031a.c b/linux/drivers/media/video/upd64031a.c index 0d7f37a9e..990405335 100644 --- a/linux/drivers/media/video/upd64031a.c +++ b/linux/drivers/media/video/upd64031a.c @@ -49,7 +49,7 @@ module_param(debug, int, 0644); MODULE_PARM_DESC(debug, "Debug level (0-1)"); -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22) +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26) static unsigned short normal_i2c[] = { 0x24 >> 1, 0x26 >> 1, I2C_CLIENT_END }; I2C_CLIENT_INSMOD; diff --git a/linux/drivers/media/video/upd64083.c b/linux/drivers/media/video/upd64083.c index fdedc41ef..89f51835b 100644 --- a/linux/drivers/media/video/upd64083.c +++ b/linux/drivers/media/video/upd64083.c @@ -40,7 +40,7 @@ module_param(debug, bool, 0644); MODULE_PARM_DESC(debug, "Debug level (0-1)"); -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22) +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26) static unsigned short normal_i2c[] = { 0xb8 >> 1, 0xba >> 1, I2C_CLIENT_END }; I2C_CLIENT_INSMOD; diff --git a/linux/drivers/media/video/v4l2-common.c b/linux/drivers/media/video/v4l2-common.c index 912859bf1..60a8f299c 100644 --- a/linux/drivers/media/video/v4l2-common.c +++ b/linux/drivers/media/video/v4l2-common.c @@ -742,7 +742,7 @@ EXPORT_SYMBOL(v4l2_chip_ident_i2c_client); /* I2C Helper functions */ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22) +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26) int v4l2_i2c_attach(struct i2c_adapter *adapter, int address, struct i2c_driver *driver, const char *name, int (*probe)(struct i2c_client *, const struct i2c_device_id *)) @@ -786,7 +786,7 @@ void v4l2_i2c_subdev_init(struct v4l2_subdev *sd, struct i2c_client *client, } EXPORT_SYMBOL_GPL(v4l2_i2c_subdev_init); -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22) +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26) /* Supporting function to find a client on a specific address on the given adapter. Used for legacy i2c drivers. */ static struct i2c_client *v4l2_i2c_legacy_find_client(struct i2c_adapter *adap, u8 addr) @@ -826,7 +826,7 @@ struct v4l2_subdev *v4l2_i2c_new_subdev(struct i2c_adapter *adapter, struct v4l2_device *dev = i2c_get_adapdata(adapter); struct v4l2_subdev *sd = NULL; struct i2c_client *client; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 22) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) struct i2c_board_info info; #endif @@ -835,15 +835,11 @@ struct v4l2_subdev *v4l2_i2c_new_subdev(struct i2c_adapter *adapter, if (module_name) request_module(module_name); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 22) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) /* Setup the i2c board info with the device type and the device address. */ memset(&info, 0, sizeof(info)); -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26) - strlcpy(info.driver_name, client_type, sizeof(info.driver_name)); -#else strlcpy(info.type, client_type, sizeof(info.type)); -#endif info.addr = addr; /* Create the i2c client */ @@ -874,7 +870,7 @@ struct v4l2_subdev *v4l2_i2c_new_subdev(struct i2c_adapter *adapter, module_put(client->driver->driver.owner); error: -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 22) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) /* If we have a client but no subdev, then something went wrong and we must unregister the client. */ if (client && sd == NULL) @@ -894,7 +890,7 @@ struct v4l2_subdev *v4l2_i2c_new_probed_subdev(struct i2c_adapter *adapter, struct v4l2_device *dev = i2c_get_adapdata(adapter); struct v4l2_subdev *sd = NULL; struct i2c_client *client = NULL; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 22) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) struct i2c_board_info info; #endif @@ -903,15 +899,11 @@ struct v4l2_subdev *v4l2_i2c_new_probed_subdev(struct i2c_adapter *adapter, if (module_name) request_module(module_name); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 22) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) /* Setup the i2c board info with the device type and the device address. */ memset(&info, 0, sizeof(info)); -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26) - strlcpy(info.driver_name, client_type, sizeof(info.driver_name)); -#else strlcpy(info.type, client_type, sizeof(info.type)); -#endif /* Probe and create the i2c client */ client = i2c_new_probed_device(adapter, &info, addrs); @@ -943,7 +935,7 @@ struct v4l2_subdev *v4l2_i2c_new_probed_subdev(struct i2c_adapter *adapter, module_put(client->driver->driver.owner); error: -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 22) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) /* If we have a client but no subdev, then something went wrong and we must unregister the client. */ if (client && sd == NULL) diff --git a/linux/drivers/media/video/vp27smpx.c b/linux/drivers/media/video/vp27smpx.c index 710c3aeca..544e6ff56 100644 --- a/linux/drivers/media/video/vp27smpx.c +++ b/linux/drivers/media/video/vp27smpx.c @@ -37,7 +37,7 @@ MODULE_DESCRIPTION("vp27smpx driver"); MODULE_AUTHOR("Hans Verkuil"); MODULE_LICENSE("GPL"); -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22) +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26) static unsigned short normal_i2c[] = { 0xb6 >> 1, I2C_CLIENT_END }; I2C_CLIENT_INSMOD; diff --git a/linux/drivers/media/video/vpx3220.c b/linux/drivers/media/video/vpx3220.c index 962e9d539..8193e6277 100644 --- a/linux/drivers/media/video/vpx3220.c +++ b/linux/drivers/media/video/vpx3220.c @@ -38,7 +38,7 @@ static int debug; module_param(debug, int, 0); MODULE_PARM_DESC(debug, "Debug level (0-1)"); -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22) +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26) static unsigned short normal_i2c[] = { 0x86 >> 1, 0x8e >> 1, I2C_CLIENT_END }; I2C_CLIENT_INSMOD; diff --git a/linux/drivers/media/video/w9968cf.c b/linux/drivers/media/video/w9968cf.c index cf8548a7f..8eed1b6fe 100644 --- a/linux/drivers/media/video/w9968cf.c +++ b/linux/drivers/media/video/w9968cf.c @@ -1510,7 +1510,7 @@ static int w9968cf_i2c_init(struct w9968cf_device* cam) static struct i2c_adapter adap = { .id = I2C_HW_SMBUS_W9968CF, .owner = THIS_MODULE, -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22) +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26) .class = I2C_CLASS_TV_ANALOG, #endif .algo = &algo, diff --git a/linux/drivers/media/video/wm8739.c b/linux/drivers/media/video/wm8739.c index 619782737..16e3950c8 100644 --- a/linux/drivers/media/video/wm8739.c +++ b/linux/drivers/media/video/wm8739.c @@ -43,7 +43,7 @@ module_param(debug, int, 0644); MODULE_PARM_DESC(debug, "Debug level (0-1)"); -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22) +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26) static unsigned short normal_i2c[] = { 0x34 >> 1, 0x36 >> 1, I2C_CLIENT_END }; I2C_CLIENT_INSMOD; diff --git a/linux/drivers/media/video/wm8775.c b/linux/drivers/media/video/wm8775.c index bd4729d13..e22497ad4 100644 --- a/linux/drivers/media/video/wm8775.c +++ b/linux/drivers/media/video/wm8775.c @@ -41,7 +41,7 @@ MODULE_DESCRIPTION("wm8775 driver"); MODULE_AUTHOR("Ulf Eklund, Hans Verkuil"); MODULE_LICENSE("GPL"); -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22) +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26) static unsigned short normal_i2c[] = { 0x36 >> 1, I2C_CLIENT_END }; I2C_CLIENT_INSMOD; -- cgit v1.2.3 From f0312f1d7b8dd5cde4035eef2a5b0fe7effdd838 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 1 Apr 2009 08:57:53 +0200 Subject: v4l2-common: add explicit v4l2_device pointer as first arg to new_(probed)_subdev From: Hans Verkuil The functions v4l2_i2c_new_subdev and v4l2_i2c_new_probed_subdev relied on i2c_get_adapdata to return the v4l2_device. However, this is not always possible on embedded platforms. So modify the API to pass the v4l2_device pointer explicitly. Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/au0828/au0828-cards.c | 8 ++-- linux/drivers/media/video/bt8xx/bttv-cards.c | 47 ++++++++++++---------- linux/drivers/media/video/cafe_ccic.c | 2 +- linux/drivers/media/video/cx18/cx18-i2c.c | 14 +++---- linux/drivers/media/video/cx231xx/cx231xx-cards.c | 8 ++-- linux/drivers/media/video/cx23885/cx23885-cards.c | 3 +- linux/drivers/media/video/cx23885/cx23885-video.c | 6 ++- linux/drivers/media/video/cx88/cx88-cards.c | 15 ++++--- linux/drivers/media/video/cx88/cx88-video.c | 4 +- linux/drivers/media/video/em28xx/em28xx-cards.c | 34 ++++++++-------- linux/drivers/media/video/ivtv/ivtv-i2c.c | 15 ++++--- linux/drivers/media/video/mxb.c | 21 ++++++---- linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c | 4 +- linux/drivers/media/video/saa7134/saa7134-cards.c | 20 +++++---- linux/drivers/media/video/saa7134/saa7134-core.c | 6 +-- .../drivers/media/video/usbvision/usbvision-i2c.c | 9 +++-- linux/drivers/media/video/v4l2-common.c | 24 +++++------ linux/drivers/media/video/vino.c | 10 +++-- linux/drivers/media/video/w9968cf.c | 3 +- linux/drivers/media/video/zoran/zoran_card.c | 8 ++-- 20 files changed, 146 insertions(+), 115 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 1aabaa7e5..ec358eec1 100644 --- a/linux/drivers/media/video/au0828/au0828-cards.c +++ b/linux/drivers/media/video/au0828/au0828-cards.c @@ -200,8 +200,8 @@ void au0828_card_setup(struct au0828_dev *dev) /* Load the analog demodulator driver (note this would need to be abstracted out if we ever need to support a different demod) */ - sd = v4l2_i2c_new_subdev(&dev->i2c_adap, "au8522", "au8522", - 0x8e >> 1); + sd = v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap, + "au8522", "au8522", 0x8e >> 1); if (sd == NULL) printk(KERN_ERR "analog subdev registration failed\n"); } @@ -209,8 +209,8 @@ void au0828_card_setup(struct au0828_dev *dev) /* Setup tuners */ if (dev->board.tuner_type != TUNER_ABSENT) { /* Load the tuner module, which does the attach */ - sd = v4l2_i2c_new_subdev(&dev->i2c_adap, "tuner", "tuner", - dev->board.tuner_addr); + sd = v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap, + "tuner", "tuner", dev->board.tuner_addr); if (sd == NULL) printk(KERN_ERR "tuner subdev registration fail\n"); diff --git a/linux/drivers/media/video/bt8xx/bttv-cards.c b/linux/drivers/media/video/bt8xx/bttv-cards.c index 1c13dbfec..24e5c1d9e 100644 --- a/linux/drivers/media/video/bt8xx/bttv-cards.c +++ b/linux/drivers/media/video/bt8xx/bttv-cards.c @@ -3550,12 +3550,15 @@ void __devinit bttv_init_card2(struct bttv *btv) /* Load tuner module before issuing tuner config call! */ if (bttv_tvcards[btv->c.type].has_radio) - v4l2_i2c_new_probed_subdev(&btv->c.i2c_adap, - "tuner", "tuner", v4l2_i2c_tuner_addrs(ADDRS_RADIO)); - v4l2_i2c_new_probed_subdev(&btv->c.i2c_adap, "tuner", - "tuner", v4l2_i2c_tuner_addrs(ADDRS_DEMOD)); - v4l2_i2c_new_probed_subdev(&btv->c.i2c_adap, "tuner", - "tuner", v4l2_i2c_tuner_addrs(ADDRS_TV_WITH_DEMOD)); + v4l2_i2c_new_probed_subdev(&btv->c.v4l2_dev, + &btv->c.i2c_adap, "tuner", "tuner", + v4l2_i2c_tuner_addrs(ADDRS_RADIO)); + v4l2_i2c_new_probed_subdev(&btv->c.v4l2_dev, + &btv->c.i2c_adap, "tuner", "tuner", + v4l2_i2c_tuner_addrs(ADDRS_DEMOD)); + v4l2_i2c_new_probed_subdev(&btv->c.v4l2_dev, + &btv->c.i2c_adap, "tuner", "tuner", + v4l2_i2c_tuner_addrs(ADDRS_TV_WITH_DEMOD)); tun_setup.mode_mask = T_ANALOG_TV | T_DIGITAL_TV; tun_setup.type = btv->tuner_type; @@ -3608,8 +3611,8 @@ void __devinit bttv_init_card2(struct bttv *btv) }; struct v4l2_subdev *sd; - sd = v4l2_i2c_new_probed_subdev(&btv->c.i2c_adap, - "saa6588", "saa6588", addrs); + sd = v4l2_i2c_new_probed_subdev(&btv->c.v4l2_dev, + &btv->c.i2c_adap, "saa6588", "saa6588", addrs); btv->has_saa6588 = (sd != NULL); } @@ -3633,8 +3636,8 @@ void __devinit bttv_init_card2(struct bttv *btv) I2C_CLIENT_END }; - btv->sd_msp34xx = v4l2_i2c_new_probed_subdev(&btv->c.i2c_adap, - "msp3400", "msp3400", addrs); + btv->sd_msp34xx = v4l2_i2c_new_probed_subdev(&btv->c.v4l2_dev, + &btv->c.i2c_adap, "msp3400", "msp3400", addrs); if (btv->sd_msp34xx) return; goto no_audio; @@ -3647,16 +3650,16 @@ void __devinit bttv_init_card2(struct bttv *btv) I2C_CLIENT_END }; - if (v4l2_i2c_new_probed_subdev(&btv->c.i2c_adap, - "tda7432", "tda7432", addrs)) + if (v4l2_i2c_new_probed_subdev(&btv->c.v4l2_dev, + &btv->c.i2c_adap, "tda7432", "tda7432", addrs)) return; goto no_audio; } case 3: { /* The user specified that we should probe for tvaudio */ - btv->sd_tvaudio = v4l2_i2c_new_probed_subdev(&btv->c.i2c_adap, - "tvaudio", "tvaudio", tvaudio_addrs); + btv->sd_tvaudio = v4l2_i2c_new_probed_subdev(&btv->c.v4l2_dev, + &btv->c.i2c_adap, "tvaudio", "tvaudio", tvaudio_addrs); if (btv->sd_tvaudio) return; goto no_audio; @@ -3680,16 +3683,16 @@ void __devinit bttv_init_card2(struct bttv *btv) I2C_CLIENT_END }; - btv->sd_msp34xx = v4l2_i2c_new_probed_subdev(&btv->c.i2c_adap, - "msp3400", "msp3400", addrs); + btv->sd_msp34xx = v4l2_i2c_new_probed_subdev(&btv->c.v4l2_dev, + &btv->c.i2c_adap, "msp3400", "msp3400", addrs); } else if (bttv_tvcards[btv->c.type].msp34xx_alt) { static const unsigned short addrs[] = { I2C_ADDR_MSP3400_ALT >> 1, I2C_CLIENT_END }; - btv->sd_msp34xx = v4l2_i2c_new_probed_subdev(&btv->c.i2c_adap, - "msp3400", "msp3400", addrs); + btv->sd_msp34xx = v4l2_i2c_new_probed_subdev(&btv->c.v4l2_dev, + &btv->c.i2c_adap, "msp3400", "msp3400", addrs); } /* If we found a msp34xx, then we're done. */ @@ -3703,14 +3706,14 @@ void __devinit bttv_init_card2(struct bttv *btv) I2C_CLIENT_END }; - if (v4l2_i2c_new_probed_subdev(&btv->c.i2c_adap, - "tda7432", "tda7432", addrs)) + if (v4l2_i2c_new_probed_subdev(&btv->c.v4l2_dev, + &btv->c.i2c_adap, "tda7432", "tda7432", addrs)) return; } /* Now see if we can find one of the tvaudio devices. */ - btv->sd_tvaudio = v4l2_i2c_new_probed_subdev(&btv->c.i2c_adap, - "tvaudio", "tvaudio", tvaudio_addrs); + btv->sd_tvaudio = v4l2_i2c_new_probed_subdev(&btv->c.v4l2_dev, + &btv->c.i2c_adap, "tvaudio", "tvaudio", tvaudio_addrs); if (btv->sd_tvaudio) return; diff --git a/linux/drivers/media/video/cafe_ccic.c b/linux/drivers/media/video/cafe_ccic.c index 2516e80ed..40eb073fb 100644 --- a/linux/drivers/media/video/cafe_ccic.c +++ b/linux/drivers/media/video/cafe_ccic.c @@ -1955,7 +1955,7 @@ static int cafe_pci_probe(struct pci_dev *pdev, goto out_freeirq; cam->sensor_addr = 0x42; - cam->sensor = v4l2_i2c_new_subdev(&cam->i2c_adapter, + cam->sensor = v4l2_i2c_new_subdev(&cam->v4l2_dev, &cam->i2c_adapter, "ov7670", "ov7670", cam->sensor_addr); if (cam->sensor == NULL) { ret = -ENODEV; diff --git a/linux/drivers/media/video/cx18/cx18-i2c.c b/linux/drivers/media/video/cx18/cx18-i2c.c index 6c3c0449c..4bf737849 100644 --- a/linux/drivers/media/video/cx18/cx18-i2c.c +++ b/linux/drivers/media/video/cx18/cx18-i2c.c @@ -100,16 +100,16 @@ int cx18_i2c_register(struct cx18 *cx, unsigned idx) if (hw == CX18_HW_TUNER) { /* special tuner group handling */ - sd = v4l2_i2c_new_probed_subdev(adap, mod, type, - cx->card_i2c->radio); + sd = v4l2_i2c_new_probed_subdev(&cx->v4l2_dev, + adap, mod, type, cx->card_i2c->radio); if (sd != NULL) sd->grp_id = hw; - sd = v4l2_i2c_new_probed_subdev(adap, mod, type, - cx->card_i2c->demod); + sd = v4l2_i2c_new_probed_subdev(&cx->v4l2_dev, + adap, mod, type, cx->card_i2c->demod); if (sd != NULL) sd->grp_id = hw; - sd = v4l2_i2c_new_probed_subdev(adap, mod, type, - cx->card_i2c->tv); + sd = v4l2_i2c_new_probed_subdev(&cx->v4l2_dev, + adap, mod, type, cx->card_i2c->tv); if (sd != NULL) sd->grp_id = hw; return sd != NULL ? 0 : -1; @@ -120,7 +120,7 @@ int cx18_i2c_register(struct cx18 *cx, unsigned idx) return -1; /* It's an I2C device other than an analog tuner */ - sd = v4l2_i2c_new_subdev(adap, mod, type, hw_addrs[idx]); + sd = v4l2_i2c_new_subdev(&cx->v4l2_dev, adap, mod, type, hw_addrs[idx]); if (sd != NULL) sd->grp_id = hw; return sd != NULL ? 0 : -1; diff --git a/linux/drivers/media/video/cx231xx/cx231xx-cards.c b/linux/drivers/media/video/cx231xx/cx231xx-cards.c index 8d445775e..653899db8 100644 --- a/linux/drivers/media/video/cx231xx/cx231xx-cards.c +++ b/linux/drivers/media/video/cx231xx/cx231xx-cards.c @@ -312,8 +312,8 @@ void cx231xx_card_setup(struct cx231xx *dev) /* request some modules */ if (dev->board.decoder == CX231XX_AVDECODER) { - dev->sd_cx25840 = - v4l2_i2c_new_subdev(&dev->i2c_bus[0].i2c_adap, + dev->sd_cx25840 = v4l2_i2c_new_subdev(&dev->v4l2_dev, + &dev->i2c_bus[0].i2c_adap, "cx25840", "cx25840", 0x88 >> 1); if (dev->sd_cx25840 == NULL) cx231xx_info("cx25840 subdev registration failure\n"); @@ -322,8 +322,8 @@ void cx231xx_card_setup(struct cx231xx *dev) } if (dev->board.tuner_type != TUNER_ABSENT) { - dev->sd_tuner = - v4l2_i2c_new_subdev(&dev->i2c_bus[1].i2c_adap, + dev->sd_tuner = v4l2_i2c_new_subdev(&dev->v4l2_dev, + &dev->i2c_bus[1].i2c_adap, "tuner", "tuner", 0xc2 >> 1); if (dev->sd_tuner == NULL) cx231xx_info("tuner subdev registration failure\n"); diff --git a/linux/drivers/media/video/cx23885/cx23885-cards.c b/linux/drivers/media/video/cx23885/cx23885-cards.c index c85678464..454470ffc 100644 --- a/linux/drivers/media/video/cx23885/cx23885-cards.c +++ b/linux/drivers/media/video/cx23885/cx23885-cards.c @@ -740,7 +740,8 @@ void cx23885_card_setup(struct cx23885_dev *dev) case CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H: case CX23885_BOARD_COMPRO_VIDEOMATE_E650F: case CX23885_BOARD_NETUP_DUAL_DVBS2_CI: - dev->sd_cx25840 = v4l2_i2c_new_subdev(&dev->i2c_bus[2].i2c_adap, + dev->sd_cx25840 = v4l2_i2c_new_subdev(&dev->v4l2_dev, + &dev->i2c_bus[2].i2c_adap, "cx25840", "cx25840", 0x88 >> 1); v4l2_subdev_call(dev->sd_cx25840, core, load_fw); break; diff --git a/linux/drivers/media/video/cx23885/cx23885-video.c b/linux/drivers/media/video/cx23885/cx23885-video.c index c5467ec46..35469c3f9 100644 --- a/linux/drivers/media/video/cx23885/cx23885-video.c +++ b/linux/drivers/media/video/cx23885/cx23885-video.c @@ -1779,10 +1779,12 @@ int cx23885_video_register(struct cx23885_dev *dev) struct v4l2_subdev *sd = NULL; if (dev->tuner_addr) - sd = v4l2_i2c_new_subdev(&dev->i2c_bus[1].i2c_adap, + sd = v4l2_i2c_new_subdev(&dev->v4l2_dev, + &dev->i2c_bus[1].i2c_adap, "tuner", "tuner", dev->tuner_addr); else - sd = v4l2_i2c_new_probed_subdev(&dev->i2c_bus[1].i2c_adap, + sd = v4l2_i2c_new_probed_subdev(&dev->v4l2_dev, + &dev->i2c_bus[1].i2c_adap, "tuner", "tuner", v4l2_i2c_tuner_addrs(ADDRS_TV)); if (sd) { struct tuner_setup tun_setup; diff --git a/linux/drivers/media/video/cx88/cx88-cards.c b/linux/drivers/media/video/cx88/cx88-cards.c index 34327b62a..a4d49fbf7 100644 --- a/linux/drivers/media/video/cx88/cx88-cards.c +++ b/linux/drivers/media/video/cx88/cx88-cards.c @@ -3254,16 +3254,19 @@ struct cx88_core *cx88_core_create(struct pci_dev *pci, int nr) The radio_type is sometimes missing, or set to UNSET but later code configures a tea5767. */ - v4l2_i2c_new_probed_subdev(&core->i2c_adap, "tuner", "tuner", + v4l2_i2c_new_probed_subdev(&core->v4l2_dev, &core->i2c_adap, + "tuner", "tuner", v4l2_i2c_tuner_addrs(ADDRS_RADIO)); if (has_demod) - v4l2_i2c_new_probed_subdev(&core->i2c_adap, "tuner", - "tuner", v4l2_i2c_tuner_addrs(ADDRS_DEMOD)); + v4l2_i2c_new_probed_subdev(&core->v4l2_dev, + &core->i2c_adap, "tuner", "tuner", + v4l2_i2c_tuner_addrs(ADDRS_DEMOD)); if (core->board.tuner_addr == ADDR_UNSET) { - v4l2_i2c_new_probed_subdev(&core->i2c_adap, "tuner", - "tuner", has_demod ? tv_addrs + 4 : tv_addrs); + v4l2_i2c_new_probed_subdev(&core->v4l2_dev, + &core->i2c_adap, "tuner", "tuner", + has_demod ? tv_addrs + 4 : tv_addrs); } else { - v4l2_i2c_new_subdev(&core->i2c_adap, + v4l2_i2c_new_subdev(&core->v4l2_dev, &core->i2c_adap, "tuner", "tuner", core->board.tuner_addr); } } diff --git a/linux/drivers/media/video/cx88/cx88-video.c b/linux/drivers/media/video/cx88/cx88-video.c index 7e642b6f3..8f0e1e616 100644 --- a/linux/drivers/media/video/cx88/cx88-video.c +++ b/linux/drivers/media/video/cx88/cx88-video.c @@ -2156,7 +2156,7 @@ static int __devinit cx8800_initdev(struct pci_dev *pci_dev, /* load and configure helper modules */ if (core->board.audio_chip == V4L2_IDENT_WM8775) - v4l2_i2c_new_subdev(&core->i2c_adap, + v4l2_i2c_new_subdev(&core->v4l2_dev, &core->i2c_adap, "wm8775", "wm8775", 0x36 >> 1); if (core->board.audio_chip == V4L2_IDENT_TVAUDIO) { @@ -2166,7 +2166,7 @@ static int __devinit cx8800_initdev(struct pci_dev *pci_dev, 0xb0 >> 1, I2C_CLIENT_END }; - v4l2_i2c_new_probed_subdev(&core->i2c_adap, + v4l2_i2c_new_probed_subdev(&core->v4l2_dev, &core->i2c_adap, "tvaudio", "tvaudio", i2c_addr); } diff --git a/linux/drivers/media/video/em28xx/em28xx-cards.c b/linux/drivers/media/video/em28xx/em28xx-cards.c index 035fc8eaf..a1c837a7f 100644 --- a/linux/drivers/media/video/em28xx/em28xx-cards.c +++ b/linux/drivers/media/video/em28xx/em28xx-cards.c @@ -2027,44 +2027,46 @@ void em28xx_card_setup(struct em28xx *dev) /* request some modules */ if (dev->board.has_msp34xx) - v4l2_i2c_new_probed_subdev(&dev->i2c_adap, "msp3400", - "msp3400", msp3400_addrs); + v4l2_i2c_new_probed_subdev(&dev->v4l2_dev, &dev->i2c_adap, + "msp3400", "msp3400", msp3400_addrs); if (dev->board.decoder == EM28XX_SAA711X) - v4l2_i2c_new_probed_subdev(&dev->i2c_adap, "saa7115", - "saa7115_auto", saa711x_addrs); + v4l2_i2c_new_probed_subdev(&dev->v4l2_dev, &dev->i2c_adap, + "saa7115", "saa7115_auto", saa711x_addrs); if (dev->board.decoder == EM28XX_TVP5150) - v4l2_i2c_new_probed_subdev(&dev->i2c_adap, "tvp5150", - "tvp5150", tvp5150_addrs); + v4l2_i2c_new_probed_subdev(&dev->v4l2_dev, &dev->i2c_adap, + "tvp5150", "tvp5150", tvp5150_addrs); if (dev->board.adecoder == EM28XX_TVAUDIO) - v4l2_i2c_new_subdev(&dev->i2c_adap, "tvaudio", - "tvaudio", dev->board.tvaudio_addr); + v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap, + "tvaudio", "tvaudio", dev->board.tvaudio_addr); if (dev->board.tuner_type != TUNER_ABSENT) { int has_demod = (dev->tda9887_conf & TDA9887_PRESENT); if (dev->board.radio.type) - v4l2_i2c_new_subdev(&dev->i2c_adap, "tuner", "tuner", - dev->board.radio_addr); + v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap, + "tuner", "tuner", dev->board.radio_addr); if (has_demod) - v4l2_i2c_new_probed_subdev(&dev->i2c_adap, "tuner", - "tuner", v4l2_i2c_tuner_addrs(ADDRS_DEMOD)); + v4l2_i2c_new_probed_subdev(&dev->v4l2_dev, + &dev->i2c_adap, "tuner", "tuner", + v4l2_i2c_tuner_addrs(ADDRS_DEMOD)); if (dev->tuner_addr == 0) { enum v4l2_i2c_tuner_type type = has_demod ? ADDRS_TV_WITH_DEMOD : ADDRS_TV; struct v4l2_subdev *sd; - sd = v4l2_i2c_new_probed_subdev(&dev->i2c_adap, "tuner", - "tuner", v4l2_i2c_tuner_addrs(type)); + sd = v4l2_i2c_new_probed_subdev(&dev->v4l2_dev, + &dev->i2c_adap, "tuner", "tuner", + v4l2_i2c_tuner_addrs(type)); if (sd) dev->tuner_addr = v4l2_i2c_subdev_addr(sd); } else { - v4l2_i2c_new_subdev(&dev->i2c_adap, "tuner", - "tuner", dev->tuner_addr); + v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap, + "tuner", "tuner", dev->tuner_addr); } } diff --git a/linux/drivers/media/video/ivtv/ivtv-i2c.c b/linux/drivers/media/video/ivtv/ivtv-i2c.c index 3f4552469..1262b6908 100644 --- a/linux/drivers/media/video/ivtv/ivtv-i2c.c +++ b/linux/drivers/media/video/ivtv/ivtv-i2c.c @@ -165,15 +165,18 @@ int ivtv_i2c_register(struct ivtv *itv, unsigned idx) return -1; if (hw == IVTV_HW_TUNER) { /* special tuner handling */ - sd = v4l2_i2c_new_probed_subdev(adap, mod, type, + sd = v4l2_i2c_new_probed_subdev(&itv->v4l2_dev, + adap, mod, type, itv->card_i2c->radio); if (sd) sd->grp_id = 1 << idx; - sd = v4l2_i2c_new_probed_subdev(adap, mod, type, + sd = v4l2_i2c_new_probed_subdev(&itv->v4l2_dev, + adap, mod, type, itv->card_i2c->demod); if (sd) sd->grp_id = 1 << idx; - sd = v4l2_i2c_new_probed_subdev(adap, mod, type, + sd = v4l2_i2c_new_probed_subdev(&itv->v4l2_dev, + adap, mod, type, itv->card_i2c->tv); if (sd) sd->grp_id = 1 << idx; @@ -184,9 +187,11 @@ int ivtv_i2c_register(struct ivtv *itv, unsigned idx) if (hw == IVTV_HW_UPD64031A || hw == IVTV_HW_UPD6408X) { unsigned short addrs[2] = { hw_addrs[idx], I2C_CLIENT_END }; - sd = v4l2_i2c_new_probed_subdev(adap, mod, type, addrs); + sd = v4l2_i2c_new_probed_subdev(&itv->v4l2_dev, + adap, mod, type, addrs); } else { - sd = v4l2_i2c_new_subdev(adap, mod, type, hw_addrs[idx]); + sd = v4l2_i2c_new_subdev(&itv->v4l2_dev, + adap, mod, type, hw_addrs[idx]); } if (sd) sd->grp_id = 1 << idx; diff --git a/linux/drivers/media/video/mxb.c b/linux/drivers/media/video/mxb.c index af08a3df3..14fb1afff 100644 --- a/linux/drivers/media/video/mxb.c +++ b/linux/drivers/media/video/mxb.c @@ -172,13 +172,20 @@ static int mxb_probe(struct saa7146_dev *dev) return -EFAULT; } - mxb->saa7111a = v4l2_i2c_new_subdev(&mxb->i2c_adapter, "saa7115", "saa7111", I2C_SAA7111A); - mxb->tea6420_1 = v4l2_i2c_new_subdev(&mxb->i2c_adapter, "tea6420", "tea6420", I2C_TEA6420_1); - mxb->tea6420_2 = v4l2_i2c_new_subdev(&mxb->i2c_adapter, "tea6420", "tea6420", I2C_TEA6420_2); - mxb->tea6415c = v4l2_i2c_new_subdev(&mxb->i2c_adapter, "tea6415c", "tea6415c", I2C_TEA6415C); - mxb->tda9840 = v4l2_i2c_new_subdev(&mxb->i2c_adapter, "tda9840", "tda9840", I2C_TDA9840); - mxb->tuner = v4l2_i2c_new_subdev(&mxb->i2c_adapter, "tuner", "tuner", I2C_TUNER); - if (v4l2_i2c_new_subdev(&mxb->i2c_adapter, "saa5246a", "saa5246a", I2C_SAA5246A)) { + mxb->saa7111a = v4l2_i2c_new_subdev(&dev->v4l2_dev, &mxb->i2c_adapter, + "saa7115", "saa7111", I2C_SAA7111A); + mxb->tea6420_1 = v4l2_i2c_new_subdev(&dev->v4l2_dev, &mxb->i2c_adapter, + "tea6420", "tea6420", I2C_TEA6420_1); + mxb->tea6420_2 = v4l2_i2c_new_subdev(&dev->v4l2_dev, &mxb->i2c_adapter, + "tea6420", "tea6420", I2C_TEA6420_2); + mxb->tea6415c = v4l2_i2c_new_subdev(&dev->v4l2_dev, &mxb->i2c_adapter, + "tea6415c", "tea6415c", I2C_TEA6415C); + mxb->tda9840 = v4l2_i2c_new_subdev(&dev->v4l2_dev, &mxb->i2c_adapter, + "tda9840", "tda9840", I2C_TDA9840); + mxb->tuner = v4l2_i2c_new_subdev(&dev->v4l2_dev, &mxb->i2c_adapter, + "tuner", "tuner", I2C_TUNER); + if (v4l2_i2c_new_subdev(&dev->v4l2_dev, &mxb->i2c_adapter, + "saa5246a", "saa5246a", I2C_SAA5246A)) { printk(KERN_INFO "mxb: found teletext decoder\n"); } diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c index 1c2f8286b..3fa3bf16d 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -2056,7 +2056,7 @@ static int pvr2_hdw_load_subdev(struct pvr2_hdw *hdw, "Module ID %u:" " Setting up with specified i2c address 0x%x", mid, i2caddr[0]); - sd = v4l2_i2c_new_subdev(&hdw->i2c_adap, + sd = v4l2_i2c_new_subdev(&hdw->v4l2_dev, &hdw->i2c_adap, fname, fname, i2caddr[0]); } else { @@ -2064,7 +2064,7 @@ static int pvr2_hdw_load_subdev(struct pvr2_hdw *hdw, "Module ID %u:" " Setting up with address probe list", mid); - sd = v4l2_i2c_new_probed_subdev(&hdw->i2c_adap, + sd = v4l2_i2c_new_probed_subdev(&hdw->v4l2_dev, &hdw->i2c_adap, fname, fname, i2caddr); } diff --git a/linux/drivers/media/video/saa7134/saa7134-cards.c b/linux/drivers/media/video/saa7134/saa7134-cards.c index cb94daeda..39015dfe0 100644 --- a/linux/drivers/media/video/saa7134/saa7134-cards.c +++ b/linux/drivers/media/video/saa7134/saa7134-cards.c @@ -6702,20 +6702,24 @@ int saa7134_board_init2(struct saa7134_dev *dev) /* Note: radio tuner address is always filled in, so we do not need to probe for a radio tuner device. */ if (dev->radio_type != UNSET) - v4l2_i2c_new_subdev(&dev->i2c_adap, - "tuner", "tuner", dev->radio_addr); + v4l2_i2c_new_subdev(&dev->v4l2_dev, + &dev->i2c_adap, "tuner", "tuner", + dev->radio_addr); if (has_demod) - v4l2_i2c_new_probed_subdev(&dev->i2c_adap, "tuner", - "tuner", v4l2_i2c_tuner_addrs(ADDRS_DEMOD)); + v4l2_i2c_new_probed_subdev(&dev->v4l2_dev, + &dev->i2c_adap, "tuner", "tuner", + v4l2_i2c_tuner_addrs(ADDRS_DEMOD)); if (dev->tuner_addr == ADDR_UNSET) { enum v4l2_i2c_tuner_type type = has_demod ? ADDRS_TV_WITH_DEMOD : ADDRS_TV; - v4l2_i2c_new_probed_subdev(&dev->i2c_adap, "tuner", - "tuner", v4l2_i2c_tuner_addrs(type)); + v4l2_i2c_new_probed_subdev(&dev->v4l2_dev, + &dev->i2c_adap, "tuner", "tuner", + v4l2_i2c_tuner_addrs(type)); } else { - v4l2_i2c_new_subdev(&dev->i2c_adap, - "tuner", "tuner", dev->tuner_addr); + v4l2_i2c_new_subdev(&dev->v4l2_dev, + &dev->i2c_adap, "tuner", "tuner", + dev->tuner_addr); } } diff --git a/linux/drivers/media/video/saa7134/saa7134-core.c b/linux/drivers/media/video/saa7134/saa7134-core.c index fbe741865..8ad6e352a 100644 --- a/linux/drivers/media/video/saa7134/saa7134-core.c +++ b/linux/drivers/media/video/saa7134/saa7134-core.c @@ -1043,7 +1043,7 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev, /* load i2c helpers */ if (card_is_empress(dev)) { struct v4l2_subdev *sd = - v4l2_i2c_new_subdev(&dev->i2c_adap, + v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap, "saa6752hs", "saa6752hs", saa7134_boards[dev->board].empress_addr); @@ -1056,8 +1056,8 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev, struct v4l2_subdev *sd; addrs[0] = saa7134_boards[dev->board].rds_addr; - sd = v4l2_i2c_new_probed_subdev(&dev->i2c_adap, "saa6588", - "saa6588", addrs); + sd = v4l2_i2c_new_probed_subdev(&dev->v4l2_dev, &dev->i2c_adap, + "saa6588", "saa6588", addrs); if (sd) printk(KERN_INFO "%s: found RDS decoder\n", dev->name); } diff --git a/linux/drivers/media/video/usbvision/usbvision-i2c.c b/linux/drivers/media/video/usbvision/usbvision-i2c.c index addc1716e..3a315f89b 100644 --- a/linux/drivers/media/video/usbvision/usbvision-i2c.c +++ b/linux/drivers/media/video/usbvision/usbvision-i2c.c @@ -251,7 +251,8 @@ int usbvision_i2c_register(struct usb_usbvision *usbvision) switch (usbvision_device_data[usbvision->DevModel].Codec) { case CODEC_SAA7113: case CODEC_SAA7111: - v4l2_i2c_new_probed_subdev(&usbvision->i2c_adap, "saa7115", + v4l2_i2c_new_probed_subdev(&usbvision->v4l2_dev, + &usbvision->i2c_adap, "saa7115", "saa7115_auto", saa711x_addrs); break; } @@ -260,13 +261,15 @@ int usbvision_i2c_register(struct usb_usbvision *usbvision) enum v4l2_i2c_tuner_type type; struct tuner_setup tun_setup; - sd = v4l2_i2c_new_probed_subdev(&usbvision->i2c_adap, "tuner", + sd = v4l2_i2c_new_probed_subdev(&usbvision->v4l2_dev, + &usbvision->i2c_adap, "tuner", "tuner", v4l2_i2c_tuner_addrs(ADDRS_DEMOD)); /* depending on whether we found a demod or not, select the tuner type. */ type = sd ? ADDRS_TV_WITH_DEMOD : ADDRS_TV; - sd = v4l2_i2c_new_probed_subdev(&usbvision->i2c_adap, "tuner", + sd = v4l2_i2c_new_probed_subdev(&usbvision->v4l2_dev, + &usbvision->i2c_adap, "tuner", "tuner", v4l2_i2c_tuner_addrs(type)); if (usbvision->tuner_type != -1) { diff --git a/linux/drivers/media/video/v4l2-common.c b/linux/drivers/media/video/v4l2-common.c index 60a8f299c..d6f41f8af 100644 --- a/linux/drivers/media/video/v4l2-common.c +++ b/linux/drivers/media/video/v4l2-common.c @@ -817,20 +817,18 @@ static struct i2c_client *v4l2_i2c_legacy_find_client(struct i2c_adapter *adap, #endif -/* Load an i2c sub-device. It assumes that i2c_get_adapdata(adapter) - returns the v4l2_device and that i2c_get_clientdata(client) - returns the v4l2_subdev. */ -struct v4l2_subdev *v4l2_i2c_new_subdev(struct i2c_adapter *adapter, +/* Load an i2c sub-device. */ +struct v4l2_subdev *v4l2_i2c_new_subdev(struct v4l2_device *v4l2_dev, + struct i2c_adapter *adapter, const char *module_name, const char *client_type, u8 addr) { - struct v4l2_device *dev = i2c_get_adapdata(adapter); struct v4l2_subdev *sd = NULL; struct i2c_client *client; #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) struct i2c_board_info info; #endif - BUG_ON(!dev); + BUG_ON(!v4l2_dev); if (module_name) request_module(module_name); @@ -864,7 +862,7 @@ struct v4l2_subdev *v4l2_i2c_new_subdev(struct i2c_adapter *adapter, /* Register with the v4l2_device which increases the module's use count as well. */ - if (v4l2_device_register_subdev(dev, sd)) + if (v4l2_device_register_subdev(v4l2_dev, sd)) sd = NULL; /* Decrease the module use count to match the first try_module_get. */ module_put(client->driver->driver.owner); @@ -880,21 +878,19 @@ error: } EXPORT_SYMBOL_GPL(v4l2_i2c_new_subdev); -/* Probe and load an i2c sub-device. It assumes that i2c_get_adapdata(adapter) - returns the v4l2_device and that i2c_get_clientdata(client) - returns the v4l2_subdev. */ -struct v4l2_subdev *v4l2_i2c_new_probed_subdev(struct i2c_adapter *adapter, +/* Probe and load an i2c sub-device. */ +struct v4l2_subdev *v4l2_i2c_new_probed_subdev(struct v4l2_device *v4l2_dev, + struct i2c_adapter *adapter, const char *module_name, const char *client_type, const unsigned short *addrs) { - struct v4l2_device *dev = i2c_get_adapdata(adapter); struct v4l2_subdev *sd = NULL; struct i2c_client *client = NULL; #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) struct i2c_board_info info; #endif - BUG_ON(!dev); + BUG_ON(!v4l2_dev); if (module_name) request_module(module_name); @@ -929,7 +925,7 @@ struct v4l2_subdev *v4l2_i2c_new_probed_subdev(struct i2c_adapter *adapter, /* Register with the v4l2_device which increases the module's use count as well. */ - if (v4l2_device_register_subdev(dev, sd)) + if (v4l2_device_register_subdev(v4l2_dev, sd)) sd = NULL; /* Decrease the module use count to match the first try_module_get. */ module_put(client->driver->driver.owner); diff --git a/linux/drivers/media/video/vino.c b/linux/drivers/media/video/vino.c index 7b22043b3..093772741 100644 --- a/linux/drivers/media/video/vino.c +++ b/linux/drivers/media/video/vino.c @@ -4341,11 +4341,13 @@ static int __init vino_module_init(void) vino_init_stage++; addr[0] = 0x45; - vino_drvdata->decoder = v4l2_i2c_new_probed_subdev(&vino_i2c_adapter, - "saa7191", "saa7191", addr); + vino_drvdata->decoder = + v4l2_i2c_new_probed_subdev(&vino_drvdata->v4l2_dev, + &vino_i2c_adapter, "saa7191", "saa7191", addr); addr[0] = 0x2b; - vino_drvdata->camera = v4l2_i2c_new_probed_subdev(&vino_i2c_adapter, - "indycam", "indycam", addr); + vino_drvdata->camera = + v4l2_i2c_new_probed_subdev(&vino_drvdata->v4l2_dev, + &vino_i2c_adapter, "indycam", "indycam", addr); dprintk("init complete!\n"); diff --git a/linux/drivers/media/video/w9968cf.c b/linux/drivers/media/video/w9968cf.c index 8eed1b6fe..ed232cbb6 100644 --- a/linux/drivers/media/video/w9968cf.c +++ b/linux/drivers/media/video/w9968cf.c @@ -3537,7 +3537,8 @@ w9968cf_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) w9968cf_turn_on_led(cam); w9968cf_i2c_init(cam); - cam->sensor_sd = v4l2_i2c_new_probed_subdev(&cam->i2c_adapter, + cam->sensor_sd = v4l2_i2c_new_probed_subdev(&cam->v4l2_dev, + &cam->i2c_adapter, "ovcamchip", "ovcamchip", addrs); usb_set_intfdata(intf, cam); diff --git a/linux/drivers/media/video/zoran/zoran_card.c b/linux/drivers/media/video/zoran/zoran_card.c index b7dea2b8a..1ab916e16 100644 --- a/linux/drivers/media/video/zoran/zoran_card.c +++ b/linux/drivers/media/video/zoran/zoran_card.c @@ -1361,11 +1361,13 @@ static int __devinit zoran_probe(struct pci_dev *pdev, goto zr_free_irq; } - zr->decoder = v4l2_i2c_new_probed_subdev(&zr->i2c_adapter, - zr->card.mod_decoder, zr->card.i2c_decoder, zr->card.addrs_decoder); + zr->decoder = v4l2_i2c_new_probed_subdev(&zr->v4l2_dev, + &zr->i2c_adapter, zr->card.mod_decoder, zr->card.i2c_decoder, + zr->card.addrs_decoder); if (zr->card.mod_encoder) - zr->encoder = v4l2_i2c_new_probed_subdev(&zr->i2c_adapter, + zr->encoder = v4l2_i2c_new_probed_subdev(&zr->v4l2_dev, + &zr->i2c_adapter, zr->card.mod_encoder, zr->card.i2c_encoder, zr->card.addrs_encoder); -- cgit v1.2.3 From 402941a820682bd6f89f6705bbe643e6808facc5 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 30 Mar 2009 16:40:54 +0200 Subject: v4l2-common: add v4l2_i2c_new_probed_subdev_addr From: Hans Verkuil Add utility function to probe for a single address, rather than a list of addresses. Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/v4l2-common.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/v4l2-common.c b/linux/drivers/media/video/v4l2-common.c index d6f41f8af..d75d89c88 100644 --- a/linux/drivers/media/video/v4l2-common.c +++ b/linux/drivers/media/video/v4l2-common.c @@ -941,6 +941,17 @@ error: } EXPORT_SYMBOL_GPL(v4l2_i2c_new_probed_subdev); +struct v4l2_subdev *v4l2_i2c_new_probed_subdev_addr(struct v4l2_device *v4l2_dev, + struct i2c_adapter *adapter, + const char *module_name, const char *client_type, u8 addr) +{ + unsigned short addrs[2] = { addr, I2C_CLIENT_END }; + + return v4l2_i2c_new_probed_subdev(v4l2_dev, adapter, + module_name, client_type, addrs); +} +EXPORT_SYMBOL_GPL(v4l2_i2c_new_probed_subdev_addr); + /* Return i2c client address of v4l2_subdev. */ unsigned short v4l2_i2c_subdev_addr(struct v4l2_subdev *sd) { -- cgit v1.2.3 From 454b45e613a5791dadb93e81721b978cb9845625 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 30 Mar 2009 16:47:55 +0200 Subject: v4l2: use v4l2_i2c_new_probed_subdev_addr where appropriate. From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/bt8xx/bttv-cards.c | 20 ++++++-------------- linux/drivers/media/video/cx88/cx88-video.c | 9 +++------ linux/drivers/media/video/ivtv/ivtv-i2c.c | 6 ++---- linux/drivers/media/video/saa7134/saa7134-core.c | 7 +++---- linux/drivers/media/video/vino.c | 11 ++++------- 5 files changed, 18 insertions(+), 35 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/bt8xx/bttv-cards.c b/linux/drivers/media/video/bt8xx/bttv-cards.c index 24e5c1d9e..5adb9eda7 100644 --- a/linux/drivers/media/video/bt8xx/bttv-cards.c +++ b/linux/drivers/media/video/bt8xx/bttv-cards.c @@ -3678,21 +3678,13 @@ void __devinit bttv_init_card2(struct bttv *btv) it really is a msp3400, so it will return NULL when the device found is really something else (e.g. a tea6300). */ if (!bttv_tvcards[btv->c.type].no_msp34xx) { - static const unsigned short addrs[] = { - I2C_ADDR_MSP3400 >> 1, - I2C_CLIENT_END - }; - - btv->sd_msp34xx = v4l2_i2c_new_probed_subdev(&btv->c.v4l2_dev, - &btv->c.i2c_adap, "msp3400", "msp3400", addrs); + btv->sd_msp34xx = v4l2_i2c_new_probed_subdev_addr(&btv->c.v4l2_dev, + &btv->c.i2c_adap, "msp3400", "msp3400", + I2C_ADDR_MSP3400 >> 1); } else if (bttv_tvcards[btv->c.type].msp34xx_alt) { - static const unsigned short addrs[] = { - I2C_ADDR_MSP3400_ALT >> 1, - I2C_CLIENT_END - }; - - btv->sd_msp34xx = v4l2_i2c_new_probed_subdev(&btv->c.v4l2_dev, - &btv->c.i2c_adap, "msp3400", "msp3400", addrs); + btv->sd_msp34xx = v4l2_i2c_new_probed_subdev_addr(&btv->c.v4l2_dev, + &btv->c.i2c_adap, "msp3400", "msp3400", + I2C_ADDR_MSP3400_ALT >> 1); } /* If we found a msp34xx, then we're done. */ diff --git a/linux/drivers/media/video/cx88/cx88-video.c b/linux/drivers/media/video/cx88/cx88-video.c index 8f0e1e616..15bbfb27a 100644 --- a/linux/drivers/media/video/cx88/cx88-video.c +++ b/linux/drivers/media/video/cx88/cx88-video.c @@ -2162,12 +2162,9 @@ static int __devinit cx8800_initdev(struct pci_dev *pci_dev, if (core->board.audio_chip == V4L2_IDENT_TVAUDIO) { /* This probes for a tda9874 as is used on some Pixelview Ultra boards. */ - static const unsigned short i2c_addr[] = { - 0xb0 >> 1, I2C_CLIENT_END - }; - - v4l2_i2c_new_probed_subdev(&core->v4l2_dev, &core->i2c_adap, - "tvaudio", "tvaudio", i2c_addr); + v4l2_i2c_new_probed_subdev_addr(&core->v4l2_dev, + &core->i2c_adap, + "tvaudio", "tvaudio", 0xb0 >> 1); } switch (core->boardnr) { diff --git a/linux/drivers/media/video/ivtv/ivtv-i2c.c b/linux/drivers/media/video/ivtv/ivtv-i2c.c index 1262b6908..984c73b5e 100644 --- a/linux/drivers/media/video/ivtv/ivtv-i2c.c +++ b/linux/drivers/media/video/ivtv/ivtv-i2c.c @@ -185,10 +185,8 @@ int ivtv_i2c_register(struct ivtv *itv, unsigned idx) if (!hw_addrs[idx]) return -1; if (hw == IVTV_HW_UPD64031A || hw == IVTV_HW_UPD6408X) { - unsigned short addrs[2] = { hw_addrs[idx], I2C_CLIENT_END }; - - sd = v4l2_i2c_new_probed_subdev(&itv->v4l2_dev, - adap, mod, type, addrs); + sd = v4l2_i2c_new_probed_subdev_addr(&itv->v4l2_dev, + adap, mod, type, hw_addrs[idx]); } else { sd = v4l2_i2c_new_subdev(&itv->v4l2_dev, adap, mod, type, hw_addrs[idx]); diff --git a/linux/drivers/media/video/saa7134/saa7134-core.c b/linux/drivers/media/video/saa7134/saa7134-core.c index 8ad6e352a..d6ab4c47c 100644 --- a/linux/drivers/media/video/saa7134/saa7134-core.c +++ b/linux/drivers/media/video/saa7134/saa7134-core.c @@ -1052,12 +1052,11 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev, } if (saa7134_boards[dev->board].rds_addr) { - unsigned short addrs[2] = { 0, I2C_CLIENT_END }; struct v4l2_subdev *sd; - addrs[0] = saa7134_boards[dev->board].rds_addr; - sd = v4l2_i2c_new_probed_subdev(&dev->v4l2_dev, &dev->i2c_adap, - "saa6588", "saa6588", addrs); + sd = v4l2_i2c_new_probed_subdev_addr(&dev->v4l2_dev, + &dev->i2c_adap, "saa6588", "saa6588", + saa7134_boards[dev->board].rds_addr); if (sd) printk(KERN_INFO "%s: found RDS decoder\n", dev->name); } diff --git a/linux/drivers/media/video/vino.c b/linux/drivers/media/video/vino.c index 093772741..11b723c0a 100644 --- a/linux/drivers/media/video/vino.c +++ b/linux/drivers/media/video/vino.c @@ -4270,7 +4270,6 @@ static int vino_init_channel_settings(struct vino_channel_settings *vcs, static int __init vino_module_init(void) { - unsigned short addr[] = { 0, I2C_CLIENT_END }; int ret; printk(KERN_INFO "SGI VINO driver version %s\n", @@ -4340,14 +4339,12 @@ static int __init vino_module_init(void) } vino_init_stage++; - addr[0] = 0x45; vino_drvdata->decoder = - v4l2_i2c_new_probed_subdev(&vino_drvdata->v4l2_dev, - &vino_i2c_adapter, "saa7191", "saa7191", addr); - addr[0] = 0x2b; + v4l2_i2c_new_probed_subdev_addr(&vino_drvdata->v4l2_dev, + &vino_i2c_adapter, "saa7191", "saa7191", 0x45); vino_drvdata->camera = - v4l2_i2c_new_probed_subdev(&vino_drvdata->v4l2_dev, - &vino_i2c_adapter, "indycam", "indycam", addr); + v4l2_i2c_new_probed_subdev_addr(&vino_drvdata->v4l2_dev, + &vino_i2c_adapter, "indycam", "indycam", 0x2b); dprintk("init complete!\n"); -- cgit v1.2.3 From ecd19781802e003ad47bd21071a1739f3e622ef4 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 1 Apr 2009 09:00:30 +0200 Subject: tvaudio.h: add static inline to retrieve the list of possible i2c addrs. From: Hans Verkuil Rather than duplicating this list everywhere, just put it in tvaudio.h. Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/bt8xx/bttv-cards.c | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/bt8xx/bttv-cards.c b/linux/drivers/media/video/bt8xx/bttv-cards.c index 5adb9eda7..38b238f0f 100644 --- a/linux/drivers/media/video/bt8xx/bttv-cards.c +++ b/linux/drivers/media/video/bt8xx/bttv-cards.c @@ -3362,17 +3362,6 @@ void __devinit bttv_init_card1(struct bttv *btv) /* initialization part two -- after registering i2c bus */ void __devinit bttv_init_card2(struct bttv *btv) { - static const unsigned short tvaudio_addrs[] = { - I2C_ADDR_TDA8425 >> 1, - I2C_ADDR_TEA6300 >> 1, - I2C_ADDR_TEA6420 >> 1, - I2C_ADDR_TDA9840 >> 1, - I2C_ADDR_TDA985x_L >> 1, - I2C_ADDR_TDA985x_H >> 1, - I2C_ADDR_TDA9874 >> 1, - I2C_ADDR_PIC16C54 >> 1, - I2C_CLIENT_END - }; int addr=ADDR_UNSET; btv->tuner_type = UNSET; @@ -3659,7 +3648,7 @@ void __devinit bttv_init_card2(struct bttv *btv) case 3: { /* The user specified that we should probe for tvaudio */ btv->sd_tvaudio = v4l2_i2c_new_probed_subdev(&btv->c.v4l2_dev, - &btv->c.i2c_adap, "tvaudio", "tvaudio", tvaudio_addrs); + &btv->c.i2c_adap, "tvaudio", "tvaudio", tvaudio_addrs()); if (btv->sd_tvaudio) return; goto no_audio; @@ -3705,7 +3694,7 @@ void __devinit bttv_init_card2(struct bttv *btv) /* Now see if we can find one of the tvaudio devices. */ btv->sd_tvaudio = v4l2_i2c_new_probed_subdev(&btv->c.v4l2_dev, - &btv->c.i2c_adap, "tvaudio", "tvaudio", tvaudio_addrs); + &btv->c.i2c_adap, "tvaudio", "tvaudio", tvaudio_addrs()); if (btv->sd_tvaudio) return; -- cgit v1.2.3 From f18a7c9190ee5b3b6583f3fed9481510833605e8 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 1 Apr 2009 08:15:52 +0200 Subject: v4l: increase version numbers of drivers converted to v4l2_subdev. From: Hans Verkuil With all the v4l2_subdev changes that were made to these drivers it is a good idea to increase the version number of each driver. It's just the patch level that is increased, except for the zoran and saa7146 drivers where the minor number was increased due to the more substantial changes that were made to those two drivers. Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/bt8xx/bttvp.h | 2 +- linux/drivers/media/video/cx23885/cx23885.h | 2 +- linux/drivers/media/video/cx88/cx88.h | 2 +- linux/drivers/media/video/saa7134/saa7134.h | 2 +- linux/drivers/media/video/usbvision/usbvision-video.c | 4 ++-- linux/drivers/media/video/vino.c | 4 ++-- linux/drivers/media/video/w9968cf.h | 2 +- linux/drivers/media/video/zoran/zoran.h | 4 ++-- 8 files changed, 11 insertions(+), 11 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/bt8xx/bttvp.h b/linux/drivers/media/video/bt8xx/bttvp.h index 65a8c1df1..d9243f6d9 100644 --- a/linux/drivers/media/video/bt8xx/bttvp.h +++ b/linux/drivers/media/video/bt8xx/bttvp.h @@ -26,7 +26,7 @@ #define _BTTVP_H_ #include -#define BTTV_VERSION_CODE KERNEL_VERSION(0,9,17) +#define BTTV_VERSION_CODE KERNEL_VERSION(0,9,18) #include #include diff --git a/linux/drivers/media/video/cx23885/cx23885.h b/linux/drivers/media/video/cx23885/cx23885.h index c090a7df9..92828c9ce 100644 --- a/linux/drivers/media/video/cx23885/cx23885.h +++ b/linux/drivers/media/video/cx23885/cx23885.h @@ -38,7 +38,7 @@ #include #include -#define CX23885_VERSION_CODE KERNEL_VERSION(0, 0, 1) +#define CX23885_VERSION_CODE KERNEL_VERSION(0, 0, 2) #define UNSET (-1U) diff --git a/linux/drivers/media/video/cx88/cx88.h b/linux/drivers/media/video/cx88/cx88.h index e7fbe8aea..a34f6ee0c 100644 --- a/linux/drivers/media/video/cx88/cx88.h +++ b/linux/drivers/media/video/cx88/cx88.h @@ -42,7 +42,7 @@ #include #include -#define CX88_VERSION_CODE KERNEL_VERSION(0,0,6) +#define CX88_VERSION_CODE KERNEL_VERSION(0,0,7) #define UNSET (-1U) diff --git a/linux/drivers/media/video/saa7134/saa7134.h b/linux/drivers/media/video/saa7134/saa7134.h index 85a1dfd19..c19ec15f4 100644 --- a/linux/drivers/media/video/saa7134/saa7134.h +++ b/linux/drivers/media/video/saa7134/saa7134.h @@ -20,7 +20,7 @@ */ #include -#define SAA7134_VERSION_CODE KERNEL_VERSION(0,2,14) +#define SAA7134_VERSION_CODE KERNEL_VERSION(0,2,15) #include #include diff --git a/linux/drivers/media/video/usbvision/usbvision-video.c b/linux/drivers/media/video/usbvision/usbvision-video.c index af06eb2f8..21abebfa1 100644 --- a/linux/drivers/media/video/usbvision/usbvision-video.c +++ b/linux/drivers/media/video/usbvision/usbvision-video.c @@ -1,5 +1,5 @@ /* - * USB USBVISION Video device driver 0.9.9 + * USB USBVISION Video device driver 0.9.10 * * * @@ -79,7 +79,7 @@ #define DRIVER_LICENSE "GPL" #define USBVISION_DRIVER_VERSION_MAJOR 0 #define USBVISION_DRIVER_VERSION_MINOR 9 -#define USBVISION_DRIVER_VERSION_PATCHLEVEL 9 +#define USBVISION_DRIVER_VERSION_PATCHLEVEL 10 #define USBVISION_DRIVER_VERSION KERNEL_VERSION(USBVISION_DRIVER_VERSION_MAJOR,\ USBVISION_DRIVER_VERSION_MINOR,\ USBVISION_DRIVER_VERSION_PATCHLEVEL) diff --git a/linux/drivers/media/video/vino.c b/linux/drivers/media/video/vino.c index 11b723c0a..a142da23b 100644 --- a/linux/drivers/media/video/vino.c +++ b/linux/drivers/media/video/vino.c @@ -60,8 +60,8 @@ // #define VINO_DEBUG // #define VINO_DEBUG_INT -#define VINO_MODULE_VERSION "0.0.5" -#define VINO_VERSION_CODE KERNEL_VERSION(0, 0, 5) +#define VINO_MODULE_VERSION "0.0.6" +#define VINO_VERSION_CODE KERNEL_VERSION(0, 0, 6) MODULE_DESCRIPTION("SGI VINO Video4Linux2 driver"); MODULE_VERSION(VINO_MODULE_VERSION); diff --git a/linux/drivers/media/video/w9968cf.h b/linux/drivers/media/video/w9968cf.h index 989d414d6..320222176 100644 --- a/linux/drivers/media/video/w9968cf.h +++ b/linux/drivers/media/video/w9968cf.h @@ -135,7 +135,7 @@ static const struct w9968cf_format w9968cf_formatlist[] = { #define W9968CF_MODULE_NAME "V4L driver for W996[87]CF JPEG USB " \ "Dual Mode Camera Chip" -#define W9968CF_MODULE_VERSION "1:1.33-basic" +#define W9968CF_MODULE_VERSION "1:1.34-basic" #define W9968CF_MODULE_AUTHOR "(C) 2002-2004 Luca Risolia" #define W9968CF_AUTHOR_EMAIL "" #define W9968CF_MODULE_LICENSE "GPL" diff --git a/linux/drivers/media/video/zoran/zoran.h b/linux/drivers/media/video/zoran/zoran.h index afecf32f1..d439c76b2 100644 --- a/linux/drivers/media/video/zoran/zoran.h +++ b/linux/drivers/media/video/zoran/zoran.h @@ -143,8 +143,8 @@ Private IOCTL to set up for displaying MJPEG #ifdef __KERNEL__ #define MAJOR_VERSION 0 /* driver major version */ -#define MINOR_VERSION 9 /* driver minor version */ -#define RELEASE_VERSION 5 /* release version */ +#define MINOR_VERSION 10 /* driver minor version */ +#define RELEASE_VERSION 0 /* release version */ #define ZORAN_NAME "ZORAN" /* name of the device */ -- cgit v1.2.3 From 7d77b86dffee54dd3ca7ffde1588269026e4f8d9 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 1 Apr 2009 10:27:29 +0200 Subject: v4l2-subdev: change prototype of s_crystal_freq. From: Hans Verkuil Remove intermediate v4l2_crystal_freq struct. This is no longer needed with the v4l2_subdev API. Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/ivtv/ivtv-driver.c | 7 ++----- linux/drivers/media/video/ivtv/ivtv-fileops.c | 15 +++++---------- linux/drivers/media/video/saa7115.c | 13 ++++++------- 3 files changed, 13 insertions(+), 22 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/ivtv/ivtv-driver.c b/linux/drivers/media/video/ivtv/ivtv-driver.c index 4549fd525..4ddeb165d 100644 --- a/linux/drivers/media/video/ivtv/ivtv-driver.c +++ b/linux/drivers/media/video/ivtv/ivtv-driver.c @@ -888,12 +888,9 @@ static void ivtv_load_and_init_modules(struct ivtv *itv) } else if (itv->card->type == IVTV_CARD_GV_MVPRX || itv->card->type == IVTV_CARD_GV_MVPRX2E) { - struct v4l2_crystal_freq crystal_freq; - /* The crystal frequency of GVMVPRX is 24.576MHz */ - crystal_freq.freq = SAA7115_FREQ_24_576_MHZ; - crystal_freq.flags = SAA7115_FREQ_FL_UCGC; - v4l2_subdev_call(itv->sd_video, video, s_crystal_freq, &crystal_freq); + v4l2_subdev_call(itv->sd_video, video, s_crystal_freq, + SAA7115_FREQ_24_576_MHZ, SAA7115_FREQ_FL_UCGC); } if (hw & IVTV_HW_CX25840) { diff --git a/linux/drivers/media/video/ivtv/ivtv-fileops.c b/linux/drivers/media/video/ivtv/ivtv-fileops.c index e212337c6..e707ef308 100644 --- a/linux/drivers/media/video/ivtv/ivtv-fileops.c +++ b/linux/drivers/media/video/ivtv/ivtv-fileops.c @@ -860,12 +860,9 @@ int ivtv_v4l2_close(struct file *filp) ivtv_call_all(itv, core, s_std, itv->std); /* Select correct audio input (i.e. TV tuner or Line in) */ ivtv_audio_set_io(itv); - if (itv->hw_flags & IVTV_HW_SAA711X) - { - struct v4l2_crystal_freq crystal_freq; - crystal_freq.freq = SAA7115_FREQ_32_11_MHZ; - crystal_freq.flags = 0; - ivtv_call_hw(itv, IVTV_HW_SAA711X, video, s_crystal_freq, &crystal_freq); + if (itv->hw_flags & IVTV_HW_SAA711X) { + ivtv_call_hw(itv, IVTV_HW_SAA711X, video, s_crystal_freq, + SAA7115_FREQ_32_11_MHZ, 0); } if (atomic_read(&itv->capturing) > 0) { /* Undo video mute */ @@ -956,10 +953,8 @@ static int ivtv_serialized_open(struct ivtv_stream *s, struct file *filp) /* Select the correct audio input (i.e. radio tuner) */ ivtv_audio_set_io(itv); if (itv->hw_flags & IVTV_HW_SAA711X) { - struct v4l2_crystal_freq crystal_freq; - crystal_freq.freq = SAA7115_FREQ_32_11_MHZ; - crystal_freq.flags = SAA7115_FREQ_FL_APLL; - ivtv_call_hw(itv, IVTV_HW_SAA711X, video, s_crystal_freq, &crystal_freq); + ivtv_call_hw(itv, IVTV_HW_SAA711X, video, s_crystal_freq, + SAA7115_FREQ_32_11_MHZ, SAA7115_FREQ_FL_APLL); } /* Done! Unmute and continue. */ ivtv_unmute(itv); diff --git a/linux/drivers/media/video/saa7115.c b/linux/drivers/media/video/saa7115.c index ea23b7cb1..7d445bac7 100644 --- a/linux/drivers/media/video/saa7115.c +++ b/linux/drivers/media/video/saa7115.c @@ -1322,17 +1322,16 @@ static int saa711x_s_stream(struct v4l2_subdev *sd, int enable) return 0; } -static int saa711x_s_crystal_freq(struct v4l2_subdev *sd, struct v4l2_crystal_freq *freq) +static int saa711x_s_crystal_freq(struct v4l2_subdev *sd, u32 freq, u32 flags) { struct saa711x_state *state = to_state(sd); - if (freq->freq != SAA7115_FREQ_32_11_MHZ && - freq->freq != SAA7115_FREQ_24_576_MHZ) + if (freq != SAA7115_FREQ_32_11_MHZ && freq != SAA7115_FREQ_24_576_MHZ) return -EINVAL; - state->crystal_freq = freq->freq; - state->cgcdiv = (freq->flags & SAA7115_FREQ_FL_CGCDIV) ? 3 : 4; - state->ucgc = (freq->flags & SAA7115_FREQ_FL_UCGC) ? 1 : 0; - state->apll = (freq->flags & SAA7115_FREQ_FL_APLL) ? 1 : 0; + state->crystal_freq = freq; + state->cgcdiv = (flags & SAA7115_FREQ_FL_CGCDIV) ? 3 : 4; + state->ucgc = (flags & SAA7115_FREQ_FL_UCGC) ? 1 : 0; + state->apll = (flags & SAA7115_FREQ_FL_APLL) ? 1 : 0; saa711x_s_clock_freq(sd, state->audclk_freq); return 0; } -- cgit v1.2.3 From d0b11e4e4cdf69b5d04acf91e630747b4fde4f8f Mon Sep 17 00:00:00 2001 From: Janne Grunau Date: Wed, 1 Apr 2009 13:39:29 +0200 Subject: cx231xx: use usb_interface.dev for v4l2_device_register From: Janne Grunau Priority: normal Signed-off-by: Janne Grunau --- linux/drivers/media/video/cx231xx/cx231xx-cards.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (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 d1872988a..0574782c1 100644 --- a/linux/drivers/media/video/cx231xx/cx231xx-cards.c +++ b/linux/drivers/media/video/cx231xx/cx231xx-cards.c @@ -685,7 +685,7 @@ static int cx231xx_usb_probe(struct usb_interface *interface, /* Create v4l2 device */ snprintf(dev->v4l2_dev.name, sizeof(dev->v4l2_dev.name), "%s-%03d", "cx231xx", nr); - retval = v4l2_device_register(&udev->dev, &dev->v4l2_dev); + retval = v4l2_device_register(&interface->dev, &dev->v4l2_dev); if (retval) { cx231xx_errdev("v4l2_device_register failed\n"); cx231xx_devused &= ~(1 << nr); -- cgit v1.2.3 From 4ad3ea8b9d538ad4a929c87979fd4118ec0c0508 Mon Sep 17 00:00:00 2001 From: Janne Grunau Date: Wed, 1 Apr 2009 13:41:13 +0200 Subject: cx231xx: remove explicitly set v4l2_device.name From: Janne Grunau Priority: normal Signed-off-by: Janne Grunau --- linux/drivers/media/video/cx231xx/cx231xx-cards.c | 2 -- 1 file changed, 2 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 0574782c1..245c49e9d 100644 --- a/linux/drivers/media/video/cx231xx/cx231xx-cards.c +++ b/linux/drivers/media/video/cx231xx/cx231xx-cards.c @@ -683,8 +683,6 @@ static int cx231xx_usb_probe(struct usb_interface *interface, */ /* Create v4l2 device */ - snprintf(dev->v4l2_dev.name, sizeof(dev->v4l2_dev.name), - "%s-%03d", "cx231xx", nr); retval = v4l2_device_register(&interface->dev, &dev->v4l2_dev); if (retval) { cx231xx_errdev("v4l2_device_register failed\n"); -- cgit v1.2.3 From e39683bbff5c82187cc7d0894f859d875b1b62de Mon Sep 17 00:00:00 2001 From: Janne Grunau Date: Wed, 1 Apr 2009 13:46:00 +0200 Subject: usbvision: use usb_interface.dev for v4l2_device_register From: Janne Grunau Priority: normal Signed-off-by: Janne Grunau Acked-by: Thierry Merle --- linux/drivers/media/video/usbvision/usbvision-video.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/usbvision/usbvision-video.c b/linux/drivers/media/video/usbvision/usbvision-video.c index fa62a2fd7..7db493ca8 100644 --- a/linux/drivers/media/video/usbvision/usbvision-video.c +++ b/linux/drivers/media/video/usbvision/usbvision-video.c @@ -1522,7 +1522,8 @@ static int __devinit usbvision_register_video(struct usb_usbvision *usbvision) * Returns NULL on error, a pointer to usb_usbvision else. * */ -static struct usb_usbvision *usbvision_alloc(struct usb_device *dev) +static struct usb_usbvision *usbvision_alloc(struct usb_device *dev, + struct usb_interface *intf) { struct usb_usbvision *usbvision; @@ -1531,7 +1532,7 @@ static struct usb_usbvision *usbvision_alloc(struct usb_device *dev) return NULL; usbvision->dev = dev; - if (v4l2_device_register(&dev->dev, &usbvision->v4l2_dev)) + if (v4l2_device_register(&intf->dev, &usbvision->v4l2_dev)) goto err_free; mutex_init(&usbvision->lock); /* available */ @@ -1669,7 +1670,8 @@ static int __devinit usbvision_probe(struct usb_interface *intf, return -ENODEV; } - if ((usbvision = usbvision_alloc(dev)) == NULL) { + usbvision = usbvision_alloc(dev, intf); + if (usbvision == NULL) { dev_err(&intf->dev, "%s: couldn't allocate USBVision struct\n", __func__); return -ENOMEM; } -- cgit v1.2.3 From 88626c2344574c18dfd599888714f60dbf91c865 Mon Sep 17 00:00:00 2001 From: Janne Grunau Date: Wed, 1 Apr 2009 13:46:50 +0200 Subject: pvrusb2: use usb_interface.dev for v4l2_device_register From: Janne Grunau Priority: normal Signed-off-by: Janne Grunau Acked-by: Mike Isely --- linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c index def29ddb3..c1fd23e1f 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -2591,7 +2591,7 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf, hdw->ctl_read_urb = usb_alloc_urb(0,GFP_KERNEL); if (!hdw->ctl_read_urb) goto fail; - if (v4l2_device_register(&usb_dev->dev, &hdw->v4l2_dev) != 0) { + if (v4l2_device_register(&intf->dev, &hdw->v4l2_dev) != 0) { pvr2_trace(PVR2_TRACE_ERROR_LEGS, "Error registering with v4l core, giving up"); goto fail; -- cgit v1.2.3 From 0af132238ae56eccd482fc735f4e5cec7a8a3892 Mon Sep 17 00:00:00 2001 From: Janne Grunau Date: Wed, 1 Apr 2009 13:47:35 +0200 Subject: au0828: use usb_interface.dev for v4l2_device_register From: Janne Grunau Priority: normal Signed-off-by: Janne Grunau Acked-by: Devin Heitmueller --- linux/drivers/media/video/au0828/au0828-core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/au0828/au0828-core.c b/linux/drivers/media/video/au0828/au0828-core.c index ffe1bf019..bc913f8b6 100644 --- a/linux/drivers/media/video/au0828/au0828-core.c +++ b/linux/drivers/media/video/au0828/au0828-core.c @@ -201,7 +201,7 @@ static int au0828_usb_probe(struct usb_interface *interface, i = atomic_inc_return(&au0828_instance) - 1; snprintf(dev->v4l2_dev.name, sizeof(dev->v4l2_dev.name), "%s-%03d", "au0828", i); - retval = v4l2_device_register(&dev->usbdev->dev, &dev->v4l2_dev); + retval = v4l2_device_register(&interface->dev, &dev->v4l2_dev); if (retval) { printk(KERN_ERR "%s() v4l2_device_register failed\n", __func__); -- cgit v1.2.3 From 5ec5e0418fa9bc68e66e2043e72aba023cc828f4 Mon Sep 17 00:00:00 2001 From: Janne Grunau Date: Wed, 1 Apr 2009 13:48:29 +0200 Subject: au0828: remove explicitly set v4l2_device.name and unused au0828_instance From: Janne Grunau Priority: normal Signed-off-by: Janne Grunau Acked-by: Devin Heitmueller --- linux/drivers/media/video/au0828/au0828-core.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/au0828/au0828-core.c b/linux/drivers/media/video/au0828/au0828-core.c index bc913f8b6..ab25af430 100644 --- a/linux/drivers/media/video/au0828/au0828-core.c +++ b/linux/drivers/media/video/au0828/au0828-core.c @@ -37,8 +37,6 @@ int au0828_debug; module_param_named(debug, au0828_debug, int, 0644); MODULE_PARM_DESC(debug, "enable debug messages"); -static atomic_t au0828_instance = ATOMIC_INIT(0); - #define _AU0828_BULKPIPE 0x03 #define _BULKPIPESIZE 0xffff @@ -170,7 +168,7 @@ static void au0828_usb_disconnect(struct usb_interface *interface) static int au0828_usb_probe(struct usb_interface *interface, const struct usb_device_id *id) { - int ifnum, retval, i; + int ifnum, retval; struct au0828_dev *dev; struct usb_device *usbdev = interface_to_usbdev(interface); @@ -198,9 +196,6 @@ static int au0828_usb_probe(struct usb_interface *interface, usb_set_intfdata(interface, dev); /* Create the v4l2_device */ - i = atomic_inc_return(&au0828_instance) - 1; - snprintf(dev->v4l2_dev.name, sizeof(dev->v4l2_dev.name), "%s-%03d", - "au0828", i); retval = v4l2_device_register(&interface->dev, &dev->v4l2_dev); if (retval) { printk(KERN_ERR "%s() v4l2_device_register failed\n", -- cgit v1.2.3 From 81fd2420e39ed720ba99ea0278b6daac6d65d200 Mon Sep 17 00:00:00 2001 From: Janne Grunau Date: Wed, 1 Apr 2009 13:49:16 +0200 Subject: w9968cf: use usb_interface.dev for v4l2_device_register From: Janne Grunau Priority: normal Signed-off-by: Janne Grunau --- linux/drivers/media/video/w9968cf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/w9968cf.c b/linux/drivers/media/video/w9968cf.c index cf8548a7f..63658bfd2 100644 --- a/linux/drivers/media/video/w9968cf.c +++ b/linux/drivers/media/video/w9968cf.c @@ -3454,7 +3454,7 @@ w9968cf_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) if (!cam) return -ENOMEM; - err = v4l2_device_register(&udev->dev, &cam->v4l2_dev); + err = v4l2_device_register(&intf->dev, &cam->v4l2_dev); if (err) goto fail0; -- cgit v1.2.3 From 696781508adb89f4ff88ecc99c83092cc031dd7b Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Thu, 2 Apr 2009 01:22:26 +0200 Subject: mxb: fix copy-and-paste bug in mute. From: Hans Verkuil The line-in was muted twice instead of the line-in and the cd-in. Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/mxb.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/mxb.c b/linux/drivers/media/video/mxb.c index 14fb1afff..d593fec1c 100644 --- a/linux/drivers/media/video/mxb.c +++ b/linux/drivers/media/video/mxb.c @@ -302,8 +302,8 @@ static int mxb_init_done(struct saa7146_dev* dev) /* mute audio on tea6420s */ tea6420_1_call(mxb, audio, s_routing, &TEA6420_line[6][0]); tea6420_2_call(mxb, audio, s_routing, &TEA6420_line[6][1]); - tea6420_1_call(mxb, audio, s_routing, &TEA6420_line[6][0]); - tea6420_2_call(mxb, audio, s_routing, &TEA6420_line[6][1]); + tea6420_1_call(mxb, audio, s_routing, &TEA6420_cd[6][0]); + tea6420_2_call(mxb, audio, s_routing, &TEA6420_cd[6][1]); /* switch to tuner-channel on tea6415c */ route.input = 3; -- cgit v1.2.3 From b4d23428b3c4456414ad8bf5e974757fd354a66f Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Thu, 2 Apr 2009 16:26:22 +0200 Subject: v4l2-subdev: change s_routing prototype From: Hans Verkuil It is no longer needed to use a struct pointer as argument, since v4l2_subdev doesn't require that ioctl-like approach anymore. Instead just pass the input, output and config (new!) arguments directly. Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/dvb/frontends/au8522_decoder.c | 12 +-- linux/drivers/media/video/adv7170.c | 19 ++-- linux/drivers/media/video/adv7175.c | 17 +-- linux/drivers/media/video/au0828/au0828-video.c | 10 +- linux/drivers/media/video/bt819.c | 11 +- linux/drivers/media/video/bt856.c | 11 +- linux/drivers/media/video/bt866.c | 11 +- linux/drivers/media/video/bt8xx/bttv-driver.c | 23 ++--- linux/drivers/media/video/cs5345.c | 11 +- linux/drivers/media/video/cs53l32a.c | 9 +- linux/drivers/media/video/cx18/cx18-audio.c | 9 +- linux/drivers/media/video/cx18/cx18-av-core.c | 8 +- linux/drivers/media/video/cx18/cx18-gpio.c | 4 +- linux/drivers/media/video/cx18/cx18-ioctl.c | 2 +- linux/drivers/media/video/cx18/cx18-video.c | 16 +-- linux/drivers/media/video/cx231xx/cx231xx-cards.c | 5 +- linux/drivers/media/video/cx231xx/cx231xx-video.c | 7 +- linux/drivers/media/video/cx23885/cx23885-video.c | 12 +-- linux/drivers/media/video/cx25840/cx25840-core.c | 10 +- linux/drivers/media/video/cx88/cx88-video.c | 12 +-- linux/drivers/media/video/em28xx/em28xx-core.c | 11 +- linux/drivers/media/video/em28xx/em28xx-video.c | 19 ++-- linux/drivers/media/video/ivtv/ivtv-gpio.c | 16 +-- linux/drivers/media/video/ivtv/ivtv-ioctl.c | 10 +- linux/drivers/media/video/ivtv/ivtv-routing.c | 66 ++++++------ linux/drivers/media/video/ks0127.c | 17 +-- linux/drivers/media/video/m52790.c | 7 +- linux/drivers/media/video/msp3400-driver.c | 25 ++--- linux/drivers/media/video/msp3400-driver.h | 3 +- linux/drivers/media/video/msp3400-kthreads.c | 6 +- linux/drivers/media/video/mxb.c | 115 ++++++++------------- linux/drivers/media/video/pvrusb2/pvrusb2-audio.c | 8 +- .../drivers/media/video/pvrusb2/pvrusb2-cs53l32a.c | 7 +- .../media/video/pvrusb2/pvrusb2-cx2584x-v4l.c | 9 +- .../media/video/pvrusb2/pvrusb2-video-v4l.c | 8 +- linux/drivers/media/video/pvrusb2/pvrusb2-wm8775.c | 12 +-- linux/drivers/media/video/saa7110.c | 13 +-- linux/drivers/media/video/saa7115.c | 30 +++--- linux/drivers/media/video/saa7127.c | 11 +- linux/drivers/media/video/saa717x.c | 23 +++-- linux/drivers/media/video/saa7185.c | 9 +- linux/drivers/media/video/saa7191.c | 6 +- linux/drivers/media/video/tea6415c.c | 5 +- linux/drivers/media/video/tea6420.c | 17 ++- linux/drivers/media/video/tvaudio.c | 7 +- linux/drivers/media/video/tvp5150.c | 21 ++-- linux/drivers/media/video/upd64031a.c | 11 +- linux/drivers/media/video/upd64083.c | 9 +- .../drivers/media/video/usbvision/usbvision-core.c | 5 +- linux/drivers/media/video/vino.c | 10 +- linux/drivers/media/video/vpx3220.c | 19 ++-- linux/drivers/media/video/wm8775.c | 9 +- linux/drivers/media/video/zoran/zoran_card.c | 4 +- linux/drivers/media/video/zoran/zoran_device.c | 20 ++-- linux/drivers/media/video/zoran/zoran_driver.c | 20 ++-- 55 files changed, 366 insertions(+), 441 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/frontends/au8522_decoder.c b/linux/drivers/media/dvb/frontends/au8522_decoder.c index 81d517765..0d449ce23 100644 --- a/linux/drivers/media/dvb/frontends/au8522_decoder.c +++ b/linux/drivers/media/dvb/frontends/au8522_decoder.c @@ -658,7 +658,7 @@ static int au8522_reset(struct v4l2_subdev *sd, u32 val) } static int au8522_s_video_routing(struct v4l2_subdev *sd, - const struct v4l2_routing *route) + u32 input, u32 output, u32 config) { struct au8522_state *state = to_state(sd); @@ -669,11 +669,11 @@ static int au8522_s_video_routing(struct v4l2_subdev *sd, closed), and then came back to analog mode */ au8522_writereg(state, 0x106, 1); - if (route->input == AU8522_COMPOSITE_CH1) { + if (input == AU8522_COMPOSITE_CH1) { au8522_setup_cvbs_mode(state); - } else if (route->input == AU8522_SVIDEO_CH13) { + } else if (input == AU8522_SVIDEO_CH13) { au8522_setup_svideo_mode(state); - } else if (route->input == AU8522_COMPOSITE_CH4_SIF) { + } else if (input == AU8522_COMPOSITE_CH4_SIF) { au8522_setup_cvbs_tuner_mode(state); } else { printk(KERN_ERR "au8522 mode not currently supported\n"); @@ -683,10 +683,10 @@ static int au8522_s_video_routing(struct v4l2_subdev *sd, } static int au8522_s_audio_routing(struct v4l2_subdev *sd, - const struct v4l2_routing *route) + u32 input, u32 output, u32 config) { struct au8522_state *state = to_state(sd); - set_audio_input(state, route->input); + set_audio_input(state, input); return 0; } diff --git a/linux/drivers/media/video/adv7170.c b/linux/drivers/media/video/adv7170.c index 0ce6007bb..c153cf81c 100644 --- a/linux/drivers/media/video/adv7170.c +++ b/linux/drivers/media/video/adv7170.c @@ -229,18 +229,19 @@ static int adv7170_s_std_output(struct v4l2_subdev *sd, v4l2_std_id std) return 0; } -static int adv7170_s_routing(struct v4l2_subdev *sd, const struct v4l2_routing *route) +static int adv7170_s_routing(struct v4l2_subdev *sd, + u32 input, u32 output, u32 config) { struct adv7170 *encoder = to_adv7170(sd); - /* RJ: route->input = 0: input is from decoder - route->input = 1: input is from ZR36060 - route->input = 2: color bar */ + /* RJ: input = 0: input is from decoder + input = 1: input is from ZR36060 + input = 2: color bar */ v4l2_dbg(1, debug, sd, "set input from %s\n", - route->input == 0 ? "decoder" : "ZR36060"); + input == 0 ? "decoder" : "ZR36060"); - switch (route->input) { + switch (input) { case 0: adv7170_write(sd, 0x01, 0x20); adv7170_write(sd, 0x08, TR1CAPT); /* TR1 */ @@ -260,11 +261,11 @@ static int adv7170_s_routing(struct v4l2_subdev *sd, const struct v4l2_routing * break; default: - v4l2_dbg(1, debug, sd, "illegal input: %d\n", route->input); + v4l2_dbg(1, debug, sd, "illegal input: %d\n", input); return -EINVAL; } - v4l2_dbg(1, debug, sd, "switched to %s\n", inputs[route->input]); - encoder->input = route->input; + v4l2_dbg(1, debug, sd, "switched to %s\n", inputs[input]); + encoder->input = input; return 0; } diff --git a/linux/drivers/media/video/adv7175.c b/linux/drivers/media/video/adv7175.c index ffbfb7140..4589236e2 100644 --- a/linux/drivers/media/video/adv7175.c +++ b/linux/drivers/media/video/adv7175.c @@ -247,15 +247,16 @@ static int adv7175_s_std_output(struct v4l2_subdev *sd, v4l2_std_id std) return 0; } -static int adv7175_s_routing(struct v4l2_subdev *sd, const struct v4l2_routing *route) +static int adv7175_s_routing(struct v4l2_subdev *sd, + u32 input, u32 output, u32 config) { struct adv7175 *encoder = to_adv7175(sd); - /* RJ: route->input = 0: input is from decoder - route->input = 1: input is from ZR36060 - route->input = 2: color bar */ + /* RJ: input = 0: input is from decoder + input = 1: input is from ZR36060 + input = 2: color bar */ - switch (route->input) { + switch (input) { case 0: adv7175_write(sd, 0x01, 0x00); @@ -298,11 +299,11 @@ static int adv7175_s_routing(struct v4l2_subdev *sd, const struct v4l2_routing * break; default: - v4l2_dbg(1, debug, sd, "illegal input: %d\n", route->input); + v4l2_dbg(1, debug, sd, "illegal input: %d\n", input); return -EINVAL; } - v4l2_dbg(1, debug, sd, "switched to %s\n", inputs[route->input]); - encoder->input = route->input; + v4l2_dbg(1, debug, sd, "switched to %s\n", inputs[input]); + encoder->input = input; return 0; } diff --git a/linux/drivers/media/video/au0828/au0828-video.c b/linux/drivers/media/video/au0828/au0828-video.c index f40259e74..a19d7ba10 100644 --- a/linux/drivers/media/video/au0828/au0828-video.c +++ b/linux/drivers/media/video/au0828/au0828-video.c @@ -1160,7 +1160,6 @@ static int vidioc_s_input(struct file *file, void *priv, unsigned int index) struct au0828_fh *fh = priv; struct au0828_dev *dev = fh->dev; int i; - struct v4l2_routing route; dprintk(1, "VIDIOC_S_INPUT in function %s, input=%d\n", __func__, index); @@ -1186,9 +1185,8 @@ static int vidioc_s_input(struct file *file, void *priv, unsigned int index) break; } - route.input = AUVI_INPUT(index).vmux; - route.output = 0; - v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_routing, &route); + v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_routing, + AUVI_INPUT(index).vmux, 0, 0); for (i = 0; i < AU0828_MAX_INPUT; i++) { int enable = 0; @@ -1211,8 +1209,8 @@ static int vidioc_s_input(struct file *file, void *priv, unsigned int index) } } - route.input = AUVI_INPUT(index).amux; - v4l2_device_call_all(&dev->v4l2_dev, 0, audio, s_routing, &route); + v4l2_device_call_all(&dev->v4l2_dev, 0, audio, s_routing, + AUVI_INPUT(index).amux, 0, 0); return 0; } diff --git a/linux/drivers/media/video/bt819.c b/linux/drivers/media/video/bt819.c index df4fe8d9a..102a833ab 100644 --- a/linux/drivers/media/video/bt819.c +++ b/linux/drivers/media/video/bt819.c @@ -298,21 +298,22 @@ static int bt819_s_std(struct v4l2_subdev *sd, v4l2_std_id std) return 0; } -static int bt819_s_routing(struct v4l2_subdev *sd, const struct v4l2_routing *route) +static int bt819_s_routing(struct v4l2_subdev *sd, + u32 input, u32 output, u32 config) { struct bt819 *decoder = to_bt819(sd); - v4l2_dbg(1, debug, sd, "set input %x\n", route->input); + v4l2_dbg(1, debug, sd, "set input %x\n", input); - if (route->input < 0 || route->input > 7) + if (input < 0 || input > 7) return -EINVAL; if (sd->v4l2_dev == NULL || sd->v4l2_dev->notify == NULL) v4l2_err(sd, "no notify found!\n"); - if (decoder->input != route->input) { + if (decoder->input != input) { v4l2_subdev_notify(sd, BT819_FIFO_RESET_LOW, 0); - decoder->input = route->input; + decoder->input = input; /* select mode */ if (decoder->input == 0) { bt819_setbit(decoder, 0x0b, 6, 0); diff --git a/linux/drivers/media/video/bt856.c b/linux/drivers/media/video/bt856.c index ef9c3d1c7..9f960cbf6 100644 --- a/linux/drivers/media/video/bt856.c +++ b/linux/drivers/media/video/bt856.c @@ -148,16 +148,17 @@ static int bt856_s_std_output(struct v4l2_subdev *sd, v4l2_std_id std) return 0; } -static int bt856_s_routing(struct v4l2_subdev *sd, const struct v4l2_routing *route) +static int bt856_s_routing(struct v4l2_subdev *sd, + u32 input, u32 output, u32 config) { struct bt856 *encoder = to_bt856(sd); - v4l2_dbg(1, debug, sd, "set input %d\n", route->input); + v4l2_dbg(1, debug, sd, "set input %d\n", input); /* We only have video bus. - * route->input= 0: input is from bt819 - * route->input= 1: input is from ZR36060 */ - switch (route->input) { + * input= 0: input is from bt819 + * input= 1: input is from ZR36060 */ + switch (input) { case 0: bt856_setbit(encoder, 0xde, 4, 0); bt856_setbit(encoder, 0xde, 3, 1); diff --git a/linux/drivers/media/video/bt866.c b/linux/drivers/media/video/bt866.c index 87845f34c..0221912d7 100644 --- a/linux/drivers/media/video/bt866.c +++ b/linux/drivers/media/video/bt866.c @@ -105,7 +105,8 @@ static int bt866_s_std_output(struct v4l2_subdev *sd, v4l2_std_id std) return 0; } -static int bt866_s_routing(struct v4l2_subdev *sd, const struct v4l2_routing *route) +static int bt866_s_routing(struct v4l2_subdev *sd, + u32 input, u32 output, u32 config) { static const __u8 init[] = { 0xc8, 0xcc, /* CRSCALE */ @@ -143,7 +144,7 @@ static int bt866_s_routing(struct v4l2_subdev *sd, const struct v4l2_routing *ro val = encoder->reg[0xdc]; - if (route->input == 0) + if (input == 0) val |= 0x40; /* CBSWAP */ else val &= ~0x40; /* !CBSWAP */ @@ -151,15 +152,15 @@ static int bt866_s_routing(struct v4l2_subdev *sd, const struct v4l2_routing *ro bt866_write(encoder, 0xdc, val); val = encoder->reg[0xcc]; - if (route->input == 2) + if (input == 2) val |= 0x01; /* OSDBAR */ else val &= ~0x01; /* !OSDBAR */ bt866_write(encoder, 0xcc, val); - v4l2_dbg(1, debug, sd, "set input %d\n", route->input); + v4l2_dbg(1, debug, sd, "set input %d\n", input); - switch (route->input) { + switch (input) { case 0: case 1: case 2: diff --git a/linux/drivers/media/video/bt8xx/bttv-driver.c b/linux/drivers/media/video/bt8xx/bttv-driver.c index 054cd2f38..958bbd428 100644 --- a/linux/drivers/media/video/bt8xx/bttv-driver.c +++ b/linux/drivers/media/video/bt8xx/bttv-driver.c @@ -1221,7 +1221,7 @@ audio_mux(struct bttv *btv, int input, int mute) ctrl.value = btv->mute; bttv_call_all(btv, core, s_ctrl, &ctrl); if (btv->sd_msp34xx) { - struct v4l2_routing route; + u32 in; /* Note: the inputs tuner/radio/extern/intern are translated to msp routings. This assumes common behavior for all msp3400 @@ -1230,11 +1230,11 @@ audio_mux(struct bttv *btv, int input, int mute) For now this is sufficient. */ switch (input) { case TVAUDIO_INPUT_RADIO: - route.input = MSP_INPUT(MSP_IN_SCART2, MSP_IN_TUNER1, + in = MSP_INPUT(MSP_IN_SCART2, MSP_IN_TUNER1, MSP_DSP_IN_SCART, MSP_DSP_IN_SCART); break; case TVAUDIO_INPUT_EXTERN: - route.input = MSP_INPUT(MSP_IN_SCART1, MSP_IN_TUNER1, + in = MSP_INPUT(MSP_IN_SCART1, MSP_IN_TUNER1, MSP_DSP_IN_SCART, MSP_DSP_IN_SCART); break; case TVAUDIO_INPUT_INTERN: @@ -1243,7 +1243,7 @@ audio_mux(struct bttv *btv, int input, int mute) input is the BTTV_BOARD_AVERMEDIA98. I wonder how that was tested. My guess is that the whole INTERN input does not work. */ - route.input = MSP_INPUT(MSP_IN_SCART2, MSP_IN_TUNER1, + in = MSP_INPUT(MSP_IN_SCART2, MSP_IN_TUNER1, MSP_DSP_IN_SCART, MSP_DSP_IN_SCART); break; case TVAUDIO_INPUT_TUNER: @@ -1252,21 +1252,18 @@ audio_mux(struct bttv *btv, int input, int mute) is the only difference between the VOODOOTV_FM and VOODOOTV_200 */ if (btv->c.type == BTTV_BOARD_VOODOOTV_200) - route.input = MSP_INPUT(MSP_IN_SCART1, MSP_IN_TUNER2, \ + in = MSP_INPUT(MSP_IN_SCART1, MSP_IN_TUNER2, \ MSP_DSP_IN_TUNER, MSP_DSP_IN_TUNER); else - route.input = MSP_INPUT_DEFAULT; + in = MSP_INPUT_DEFAULT; break; } - route.output = MSP_OUTPUT_DEFAULT; - v4l2_subdev_call(btv->sd_msp34xx, audio, s_routing, &route); + v4l2_subdev_call(btv->sd_msp34xx, audio, s_routing, + in, MSP_OUTPUT_DEFAULT, 0); } if (btv->sd_tvaudio) { - struct v4l2_routing route; - - route.input = input; - route.output = 0; - v4l2_subdev_call(btv->sd_tvaudio, audio, s_routing, &route); + v4l2_subdev_call(btv->sd_tvaudio, audio, s_routing, + input, 0, 0); } return 0; } diff --git a/linux/drivers/media/video/cs5345.c b/linux/drivers/media/video/cs5345.c index bc98ec17a..84e7cb967 100644 --- a/linux/drivers/media/video/cs5345.c +++ b/linux/drivers/media/video/cs5345.c @@ -59,14 +59,15 @@ static inline int cs5345_read(struct v4l2_subdev *sd, u8 reg) return i2c_smbus_read_byte_data(client, reg); } -static int cs5345_s_routing(struct v4l2_subdev *sd, const struct v4l2_routing *route) +static int cs5345_s_routing(struct v4l2_subdev *sd, + u32 input, u32 output, u32 config) { - if ((route->input & 0xf) > 6) { - v4l2_err(sd, "Invalid input %d.\n", route->input); + if ((input & 0xf) > 6) { + v4l2_err(sd, "Invalid input %d.\n", input); return -EINVAL; } - cs5345_write(sd, 0x09, route->input & 0xf); - cs5345_write(sd, 0x05, route->input & 0xf0); + cs5345_write(sd, 0x09, input & 0xf); + cs5345_write(sd, 0x05, input & 0xf0); return 0; } diff --git a/linux/drivers/media/video/cs53l32a.c b/linux/drivers/media/video/cs53l32a.c index a2e1f677d..af2e92099 100644 --- a/linux/drivers/media/video/cs53l32a.c +++ b/linux/drivers/media/video/cs53l32a.c @@ -64,17 +64,18 @@ static int cs53l32a_read(struct v4l2_subdev *sd, u8 reg) return i2c_smbus_read_byte_data(client, reg); } -static int cs53l32a_s_routing(struct v4l2_subdev *sd, const struct v4l2_routing *route) +static int cs53l32a_s_routing(struct v4l2_subdev *sd, + u32 input, u32 output, u32 config) { /* There are 2 physical inputs, but the second input can be placed in two modes, the first mode bypasses the PGA (gain), the second goes through the PGA. Hence there are three possible inputs to choose from. */ - if (route->input > 2) { - v4l2_err(sd, "Invalid input %d.\n", route->input); + if (input > 2) { + v4l2_err(sd, "Invalid input %d.\n", input); return -EINVAL; } - cs53l32a_write(sd, 0x01, 0x01 + (route->input << 4)); + cs53l32a_write(sd, 0x01, 0x01 + (input << 4)); return 0; } diff --git a/linux/drivers/media/video/cx18/cx18-audio.c b/linux/drivers/media/video/cx18/cx18-audio.c index bb5c5165d..1519e91c6 100644 --- a/linux/drivers/media/video/cx18/cx18-audio.c +++ b/linux/drivers/media/video/cx18/cx18-audio.c @@ -33,7 +33,6 @@ int cx18_audio_set_io(struct cx18 *cx) { const struct cx18_card_audio_input *in; - struct v4l2_routing route; u32 val; int err; @@ -44,13 +43,11 @@ int cx18_audio_set_io(struct cx18 *cx) in = &cx->card->audio_inputs[cx->audio_input]; /* handle muxer chips */ - route.input = in->muxer_input; - route.output = 0; - v4l2_subdev_call(cx->sd_extmux, audio, s_routing, &route); + v4l2_subdev_call(cx->sd_extmux, audio, s_routing, + in->audio_input, 0, 0); - route.input = in->audio_input; err = cx18_call_hw_err(cx, cx->card->hw_audio_ctrl, - audio, s_routing, &route); + audio, s_routing, in->audio_input, 0, 0); if (err) return err; diff --git a/linux/drivers/media/video/cx18/cx18-av-core.c b/linux/drivers/media/video/cx18/cx18-av-core.c index 9b3e574dd..cf2bd888a 100644 --- a/linux/drivers/media/video/cx18/cx18-av-core.c +++ b/linux/drivers/media/video/cx18/cx18-av-core.c @@ -547,19 +547,19 @@ static int set_input(struct cx18 *cx, enum cx18_av_video_input vid_input, } static int cx18_av_s_video_routing(struct v4l2_subdev *sd, - const struct v4l2_routing *route) + u32 input, u32 output, u32 config) { struct cx18_av_state *state = to_cx18_av_state(sd); struct cx18 *cx = v4l2_get_subdevdata(sd); - return set_input(cx, route->input, state->aud_input); + return set_input(cx, input, state->aud_input); } static int cx18_av_s_audio_routing(struct v4l2_subdev *sd, - const struct v4l2_routing *route) + u32 input, u32 output, u32 config) { struct cx18_av_state *state = to_cx18_av_state(sd); struct cx18 *cx = v4l2_get_subdevdata(sd); - return set_input(cx, state->vid_input, route->input); + return set_input(cx, state->vid_input, input); } static int cx18_av_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt) diff --git a/linux/drivers/media/video/cx18/cx18-gpio.c b/linux/drivers/media/video/cx18/cx18-gpio.c index ae2460e68..86a204b54 100644 --- a/linux/drivers/media/video/cx18/cx18-gpio.c +++ b/linux/drivers/media/video/cx18/cx18-gpio.c @@ -156,12 +156,12 @@ static int gpiomux_s_std(struct v4l2_subdev *sd, v4l2_std_id norm) } static int gpiomux_s_audio_routing(struct v4l2_subdev *sd, - const struct v4l2_routing *route) + u32 input, u32 output, u32 config) { struct cx18 *cx = v4l2_get_subdevdata(sd); u32 data; - switch (route->input) { + switch (input) { case 0: data = cx->card->gpio_audio_input.tuner; break; diff --git a/linux/drivers/media/video/cx18/cx18-ioctl.c b/linux/drivers/media/video/cx18/cx18-ioctl.c index 810c39f85..b2ebd81be 100644 --- a/linux/drivers/media/video/cx18/cx18-ioctl.c +++ b/linux/drivers/media/video/cx18/cx18-ioctl.c @@ -957,7 +957,7 @@ static long cx18_default(struct file *file, void *fh, int cmd, void *arg) CX18_DEBUG_IOCTL("VIDIOC_INT_S_AUDIO_ROUTING(%d, %d)\n", route->input, route->output); cx18_call_hw(cx, cx->card->hw_audio_ctrl, audio, s_routing, - route); + route->input, route->output, 0); break; } diff --git a/linux/drivers/media/video/cx18/cx18-video.c b/linux/drivers/media/video/cx18/cx18-video.c index 6fdadedf1..6dc84aac8 100644 --- a/linux/drivers/media/video/cx18/cx18-video.c +++ b/linux/drivers/media/video/cx18/cx18-video.c @@ -25,20 +25,8 @@ void cx18_video_set_io(struct cx18 *cx) { - struct v4l2_routing route; int inp = cx->active_input; - u32 type; - route.input = cx->card->video_inputs[inp].video_input; - route.output = 0; - v4l2_subdev_call(cx->sd_av, video, s_routing, &route); - - type = cx->card->video_inputs[inp].video_type; - - if (type == CX18_CARD_INPUT_VID_TUNER) - route.input = 0; /* Tuner */ - else if (type < CX18_CARD_INPUT_COMPOSITE1) - route.input = 2; /* S-Video */ - else - route.input = 1; /* Composite */ + v4l2_subdev_call(cx->sd_av, video, s_routing, + cx->card->video_inputs[inp].video_input, 0, 0); } diff --git a/linux/drivers/media/video/cx231xx/cx231xx-cards.c b/linux/drivers/media/video/cx231xx/cx231xx-cards.c index 653899db8..2758958f9 100644 --- a/linux/drivers/media/video/cx231xx/cx231xx-cards.c +++ b/linux/drivers/media/video/cx231xx/cx231xx-cards.c @@ -358,10 +358,7 @@ int cx231xx_config(struct cx231xx *dev) */ void cx231xx_config_i2c(struct cx231xx *dev) { - struct v4l2_routing route; - - route.input = INPUT(dev->video_input)->vmux; - route.output = 0; + /* u32 input = INPUT(dev->video_input)->vmux; */ call_all(dev, video, s_stream, 1); } diff --git a/linux/drivers/media/video/cx231xx/cx231xx-video.c b/linux/drivers/media/video/cx231xx/cx231xx-video.c index 37703f02b..638a8d3e4 100644 --- a/linux/drivers/media/video/cx231xx/cx231xx-video.c +++ b/linux/drivers/media/video/cx231xx/cx231xx-video.c @@ -820,17 +820,12 @@ static struct videobuf_queue_ops cx231xx_video_qops = { void video_mux(struct cx231xx *dev, int index) { - - struct v4l2_routing route; - - route.input = INPUT(index)->vmux; - route.output = 0; dev->video_input = index; dev->ctl_ainput = INPUT(index)->amux; cx231xx_set_video_input_mux(dev, index); - cx25840_call(dev, video, s_routing, &route); + cx25840_call(dev, video, s_routing, INPUT(index)->vmux, 0, 0); cx231xx_set_audio_input(dev, dev->ctl_ainput); diff --git a/linux/drivers/media/video/cx23885/cx23885-video.c b/linux/drivers/media/video/cx23885/cx23885-video.c index 35469c3f9..2855a49b5 100644 --- a/linux/drivers/media/video/cx23885/cx23885-video.c +++ b/linux/drivers/media/video/cx23885/cx23885-video.c @@ -428,9 +428,6 @@ static void res_free(struct cx23885_dev *dev, struct cx23885_fh *fh, static int cx23885_video_mux(struct cx23885_dev *dev, unsigned int input) { - struct v4l2_routing route; - memset(&route, 0, sizeof(route)); - dprintk(1, "%s() video_mux: %d [vmux=%d, gpio=0x%x,0x%x,0x%x,0x%x]\n", __func__, input, INPUT(input)->vmux, @@ -438,13 +435,12 @@ static int cx23885_video_mux(struct cx23885_dev *dev, unsigned int input) INPUT(input)->gpio2, INPUT(input)->gpio3); dev->input = input; - route.input = INPUT(input)->vmux; - /* Tell the internal A/V decoder */ - v4l2_subdev_call(dev->sd_cx25840, video, s_routing, &route); + v4l2_subdev_call(dev->sd_cx25840, video, s_routing, + INPUT(input)->vmux, 0, 0); #if 0 - route.input = 0; /* Let the AVCore default */ - v4l2_subdev_call(dev->sd_cx25840, audio, s_routing, &route); + /* Let the AVCore default */ + v4l2_subdev_call(dev->sd_cx25840, audio, s_routing, 0, 0, 0); #endif return 0; diff --git a/linux/drivers/media/video/cx25840/cx25840-core.c b/linux/drivers/media/video/cx25840/cx25840-core.c index 11f5ddce4..2929bf3b7 100644 --- a/linux/drivers/media/video/cx25840/cx25840-core.c +++ b/linux/drivers/media/video/cx25840/cx25840-core.c @@ -1354,22 +1354,24 @@ static int cx25840_s_radio(struct v4l2_subdev *sd) return 0; } -static int cx25840_s_video_routing(struct v4l2_subdev *sd, const struct v4l2_routing *route) +static int cx25840_s_video_routing(struct v4l2_subdev *sd, + u32 input, u32 output, u32 config) { struct cx25840_state *state = to_state(sd); struct i2c_client *client = v4l2_get_subdevdata(sd); - return set_input(client, route->input, state->aud_input); + return set_input(client, input, state->aud_input); } -static int cx25840_s_audio_routing(struct v4l2_subdev *sd, const struct v4l2_routing *route) +static int cx25840_s_audio_routing(struct v4l2_subdev *sd, + u32 input, u32 output, u32 config) { struct cx25840_state *state = to_state(sd); struct i2c_client *client = v4l2_get_subdevdata(sd); if (state->is_cx25836) return -EINVAL; - return set_input(client, state->vid_input, route->input); + return set_input(client, state->vid_input, input); } static int cx25840_s_frequency(struct v4l2_subdev *sd, struct v4l2_frequency *freq) diff --git a/linux/drivers/media/video/cx88/cx88-video.c b/linux/drivers/media/video/cx88/cx88-video.c index 15bbfb27a..76b16038c 100644 --- a/linux/drivers/media/video/cx88/cx88-video.c +++ b/linux/drivers/media/video/cx88/cx88-video.c @@ -429,10 +429,8 @@ int cx88_video_mux(struct cx88_core *core, unsigned int input) routes for different inputs. HVR-1300 surely does */ if (core->board.audio_chip && core->board.audio_chip == V4L2_IDENT_WM8775) { - struct v4l2_routing route; - - route.input = INPUT(input).audioroute; - call_all(core, audio, s_routing, &route); + call_all(core, audio, s_routing, + INPUT(input).audioroute, 0, 0); } /* cx2388's C-ADC is connected to the tuner only. When used with S-Video, that ADC is busy dealing with @@ -1049,10 +1047,8 @@ static int video_open(struct file *file) if (core->board.radio.audioroute) { if(core->board.audio_chip && core->board.audio_chip == V4L2_IDENT_WM8775) { - struct v4l2_routing route; - - route.input = core->board.radio.audioroute; - call_all(core, audio, s_routing, &route); + call_all(core, audio, s_routing, + core->board.radio.audioroute, 0, 0); } /* "I2S ADC mode" */ core->tvaudio = WW_I2SADC; diff --git a/linux/drivers/media/video/em28xx/em28xx-core.c b/linux/drivers/media/video/em28xx/em28xx-core.c index 08eb11e72..c05f52048 100644 --- a/linux/drivers/media/video/em28xx/em28xx-core.c +++ b/linux/drivers/media/video/em28xx/em28xx-core.c @@ -1027,14 +1027,9 @@ EXPORT_SYMBOL_GPL(em28xx_init_isoc); */ void em28xx_wake_i2c(struct em28xx *dev) { - struct v4l2_routing route; - int zero = 0; - - route.input = INPUT(dev->ctl_input)->vmux; - route.output = 0; - - v4l2_device_call_all(&dev->v4l2_dev, 0, core, reset, zero); - v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_routing, &route); + v4l2_device_call_all(&dev->v4l2_dev, 0, core, reset, 0); + v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_routing, + INPUT(dev->ctl_input)->vmux, 0, 0); v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_stream, 0); } diff --git a/linux/drivers/media/video/em28xx/em28xx-video.c b/linux/drivers/media/video/em28xx/em28xx-video.c index 212444179..1614e5fc4 100644 --- a/linux/drivers/media/video/em28xx/em28xx-video.c +++ b/linux/drivers/media/video/em28xx/em28xx-video.c @@ -519,10 +519,6 @@ static struct videobuf_queue_ops em28xx_video_qops = { static void video_mux(struct em28xx *dev, int index) { - struct v4l2_routing route; - - route.input = INPUT(index)->vmux; - route.output = 0; dev->ctl_input = index; dev->ctl_ainput = INPUT(index)->amux; dev->ctl_aoutput = INPUT(index)->aout; @@ -530,25 +526,22 @@ static void video_mux(struct em28xx *dev, int index) if (!dev->ctl_aoutput) dev->ctl_aoutput = EM28XX_AOUT_MASTER; - v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_routing, &route); + v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_routing, + INPUT(index)->vmux, 0, 0); if (dev->board.has_msp34xx) { if (dev->i2s_speed) { v4l2_device_call_all(&dev->v4l2_dev, 0, audio, s_i2s_clock_freq, dev->i2s_speed); } - route.input = dev->ctl_ainput; - route.output = MSP_OUTPUT(MSP_SC_IN_DSP_SCART1); - /* Note: this is msp3400 specific */ - v4l2_device_call_all(&dev->v4l2_dev, 0, audio, s_routing, &route); + v4l2_device_call_all(&dev->v4l2_dev, 0, audio, s_routing, + dev->ctl_ainput, MSP_OUTPUT(MSP_SC_IN_DSP_SCART1), 0); } if (dev->board.adecoder != EM28XX_NOADECODER) { - route.input = dev->ctl_ainput; - route.output = dev->ctl_aoutput; - - v4l2_device_call_all(&dev->v4l2_dev, 0, audio, s_routing, &route); + v4l2_device_call_all(&dev->v4l2_dev, 0, audio, s_routing, + dev->ctl_ainput, dev->ctl_aoutput, 0); } em28xx_audio_analog_set(dev); diff --git a/linux/drivers/media/video/ivtv/ivtv-gpio.c b/linux/drivers/media/video/ivtv/ivtv-gpio.c index 0dd5f53b7..ceb05bdca 100644 --- a/linux/drivers/media/video/ivtv/ivtv-gpio.c +++ b/linux/drivers/media/video/ivtv/ivtv-gpio.c @@ -248,15 +248,16 @@ static int subdev_s_std(struct v4l2_subdev *sd, v4l2_std_id std) return 0; } -static int subdev_s_audio_routing(struct v4l2_subdev *sd, const struct v4l2_routing *route) +static int subdev_s_audio_routing(struct v4l2_subdev *sd, + u32 input, u32 output, u32 config) { struct ivtv *itv = sd_to_ivtv(sd); u16 mask, data; - if (route->input > 2) + if (input > 2) return -EINVAL; mask = itv->card->gpio_audio_input.mask; - switch (route->input) { + switch (input) { case 0: data = itv->card->gpio_audio_input.tuner; break; @@ -318,17 +319,18 @@ static int subdev_log_status(struct v4l2_subdev *sd) return 0; } -static int subdev_s_video_routing(struct v4l2_subdev *sd, const struct v4l2_routing *route) +static int subdev_s_video_routing(struct v4l2_subdev *sd, + u32 input, u32 output, u32 config) { struct ivtv *itv = sd_to_ivtv(sd); u16 mask, data; - if (route->input > 2) /* 0:Tuner 1:Composite 2:S-Video */ + if (input > 2) /* 0:Tuner 1:Composite 2:S-Video */ return -EINVAL; mask = itv->card->gpio_video_input.mask; - if (route->input == 0) + if (input == 0) data = itv->card->gpio_video_input.tuner; - else if (route->input == 1) + else if (input == 1) data = itv->card->gpio_video_input.composite; else data = itv->card->gpio_video_input.svideo; diff --git a/linux/drivers/media/video/ivtv/ivtv-ioctl.c b/linux/drivers/media/video/ivtv/ivtv-ioctl.c index 052fbe9cd..cf48b6ab9 100644 --- a/linux/drivers/media/video/ivtv/ivtv-ioctl.c +++ b/linux/drivers/media/video/ivtv/ivtv-ioctl.c @@ -1033,7 +1033,6 @@ static int ivtv_g_output(struct file *file, void *fh, unsigned int *i) static int ivtv_s_output(struct file *file, void *fh, unsigned int outp) { struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv; - struct v4l2_routing route; if (outp >= itv->card->nof_outputs) return -EINVAL; @@ -1046,9 +1045,9 @@ static int ivtv_s_output(struct file *file, void *fh, unsigned int outp) itv->active_output, outp); itv->active_output = outp; - route.input = SAA7127_INPUT_TYPE_NORMAL; - route.output = itv->card->video_outputs[outp].video_output; - ivtv_call_hw(itv, IVTV_HW_SAA7127, video, s_routing, &route); + ivtv_call_hw(itv, IVTV_HW_SAA7127, video, s_routing, + SAA7127_INPUT_TYPE_NORMAL, + itv->card->video_outputs[outp].video_output, 0); return 0; } @@ -1738,7 +1737,8 @@ static long ivtv_default(struct file *file, void *fh, int cmd, void *arg) case VIDIOC_INT_S_AUDIO_ROUTING: { struct v4l2_routing *route = arg; - ivtv_call_hw(itv, itv->card->hw_audio, audio, s_routing, route); + ivtv_call_hw(itv, itv->card->hw_audio, audio, s_routing, + route->input, route->output, 0); break; } diff --git a/linux/drivers/media/video/ivtv/ivtv-routing.c b/linux/drivers/media/video/ivtv/ivtv-routing.c index 3fd302294..8898c569a 100644 --- a/linux/drivers/media/video/ivtv/ivtv-routing.c +++ b/linux/drivers/media/video/ivtv/ivtv-routing.c @@ -34,7 +34,7 @@ void ivtv_audio_set_io(struct ivtv *itv) { const struct ivtv_card_audio_input *in; - struct v4l2_routing route; + u32 input, output = 0; /* Determine which input to use */ if (test_bit(IVTV_F_I_RADIO_USER, &itv->i_flags)) @@ -43,73 +43,77 @@ void ivtv_audio_set_io(struct ivtv *itv) in = &itv->card->audio_inputs[itv->audio_input]; /* handle muxer chips */ - route.input = in->muxer_input; - route.output = 0; + input = in->muxer_input; if (itv->card->hw_muxer & IVTV_HW_M52790) - route.output = M52790_OUT_STEREO; - v4l2_subdev_call(itv->sd_muxer, audio, s_routing, &route); + output = M52790_OUT_STEREO; + v4l2_subdev_call(itv->sd_muxer, audio, s_routing, + input, output, 0); - route.input = in->audio_input; - route.output = 0; + input = in->audio_input; + output = 0; if (itv->card->hw_audio & IVTV_HW_MSP34XX) - route.output = MSP_OUTPUT(MSP_SC_IN_DSP_SCART1); - ivtv_call_hw(itv, itv->card->hw_audio, audio, s_routing, &route); + output = MSP_OUTPUT(MSP_SC_IN_DSP_SCART1); + ivtv_call_hw(itv, itv->card->hw_audio, audio, s_routing, + input, output, 0); } /* Selects the video input and output according to the current settings. */ void ivtv_video_set_io(struct ivtv *itv) { - struct v4l2_routing route; int inp = itv->active_input; + u32 input; u32 type; - route.input = itv->card->video_inputs[inp].video_input; - route.output = 0; - v4l2_subdev_call(itv->sd_video, video, s_routing, &route); + v4l2_subdev_call(itv->sd_video, video, s_routing, + itv->card->video_inputs[inp].video_input, 0, 0); type = itv->card->video_inputs[inp].video_type; if (type == IVTV_CARD_INPUT_VID_TUNER) { - route.input = 0; /* Tuner */ + input = 0; /* Tuner */ } else if (type < IVTV_CARD_INPUT_COMPOSITE1) { - route.input = 2; /* S-Video */ + input = 2; /* S-Video */ } else { - route.input = 1; /* Composite */ + input = 1; /* Composite */ } if (itv->card->hw_video & IVTV_HW_GPIO) - ivtv_call_hw(itv, IVTV_HW_GPIO, video, s_routing, &route); + ivtv_call_hw(itv, IVTV_HW_GPIO, video, s_routing, + input, 0, 0); if (itv->card->hw_video & IVTV_HW_UPD64031A) { if (type == IVTV_CARD_INPUT_VID_TUNER || type >= IVTV_CARD_INPUT_COMPOSITE1) { /* Composite: GR on, connect to 3DYCS */ - route.input = UPD64031A_GR_ON | UPD64031A_3DYCS_COMPOSITE; + input = UPD64031A_GR_ON | UPD64031A_3DYCS_COMPOSITE; } else { /* S-Video: GR bypassed, turn it off */ - route.input = UPD64031A_GR_OFF | UPD64031A_3DYCS_DISABLE; + input = UPD64031A_GR_OFF | UPD64031A_3DYCS_DISABLE; } - route.input |= itv->card->gr_config; + input |= itv->card->gr_config; - ivtv_call_hw(itv, IVTV_HW_UPD64031A, video, s_routing, &route); + ivtv_call_hw(itv, IVTV_HW_UPD64031A, video, s_routing, + input, 0, 0); } if (itv->card->hw_video & IVTV_HW_UPD6408X) { - route.input = UPD64083_YCS_MODE; + input = UPD64083_YCS_MODE; if (type > IVTV_CARD_INPUT_VID_TUNER && type < IVTV_CARD_INPUT_COMPOSITE1) { - /* S-Video uses YCNR mode and internal Y-ADC, the upd64031a - is not used. */ - route.input |= UPD64083_YCNR_MODE; + /* S-Video uses YCNR mode and internal Y-ADC, the + upd64031a is not used. */ + input |= UPD64083_YCNR_MODE; } else if (itv->card->hw_video & IVTV_HW_UPD64031A) { - /* Use upd64031a output for tuner and composite(CX23416GYC only) inputs */ - if ((type == IVTV_CARD_INPUT_VID_TUNER)|| - (itv->card->type == IVTV_CARD_CX23416GYC)) { - route.input |= UPD64083_EXT_Y_ADC; - } + /* Use upd64031a output for tuner and + composite(CX23416GYC only) inputs */ + if (type == IVTV_CARD_INPUT_VID_TUNER || + itv->card->type == IVTV_CARD_CX23416GYC) { + input |= UPD64083_EXT_Y_ADC; + } } - ivtv_call_hw(itv, IVTV_HW_UPD6408X, video, s_routing, &route); + ivtv_call_hw(itv, IVTV_HW_UPD6408X, video, s_routing, + input, 0, 0); } } diff --git a/linux/drivers/media/video/ks0127.c b/linux/drivers/media/video/ks0127.c index c413a1d9b..2b70b3e7d 100644 --- a/linux/drivers/media/video/ks0127.c +++ b/linux/drivers/media/video/ks0127.c @@ -419,11 +419,12 @@ static void ks0127_init(struct v4l2_subdev *sd) } } -static int ks0127_s_routing(struct v4l2_subdev *sd, const struct v4l2_routing *route) +static int ks0127_s_routing(struct v4l2_subdev *sd, + u32 input, u32 output, u32 config) { struct ks0127 *ks = to_ks0127(sd); - switch (route->input) { + switch (input) { case KS_INPUT_COMPOSITE_1: case KS_INPUT_COMPOSITE_2: case KS_INPUT_COMPOSITE_3: @@ -431,13 +432,13 @@ static int ks0127_s_routing(struct v4l2_subdev *sd, const struct v4l2_routing *r case KS_INPUT_COMPOSITE_5: case KS_INPUT_COMPOSITE_6: v4l2_dbg(1, debug, sd, - "s_routing %d: Composite\n", route->input); + "s_routing %d: Composite\n", input); /* autodetect 50/60 Hz */ ks0127_and_or(sd, KS_CMDA, 0xfc, 0x00); /* VSE=0 */ ks0127_and_or(sd, KS_CMDA, ~0x40, 0x00); /* set input line */ - ks0127_and_or(sd, KS_CMDB, 0xb0, route->input); + ks0127_and_or(sd, KS_CMDB, 0xb0, input); /* non-freerunning mode */ ks0127_and_or(sd, KS_CMDC, 0x70, 0x0a); /* analog input */ @@ -465,13 +466,13 @@ static int ks0127_s_routing(struct v4l2_subdev *sd, const struct v4l2_routing *r case KS_INPUT_SVIDEO_2: case KS_INPUT_SVIDEO_3: v4l2_dbg(1, debug, sd, - "s_routing %d: S-Video\n", route->input); + "s_routing %d: S-Video\n", input); /* autodetect 50/60 Hz */ ks0127_and_or(sd, KS_CMDA, 0xfc, 0x00); /* VSE=0 */ ks0127_and_or(sd, KS_CMDA, ~0x40, 0x00); /* set input line */ - ks0127_and_or(sd, KS_CMDB, 0xb0, route->input); + ks0127_and_or(sd, KS_CMDB, 0xb0, input); /* non-freerunning mode */ ks0127_and_or(sd, KS_CMDC, 0x70, 0x0a); /* analog input */ @@ -506,7 +507,7 @@ static int ks0127_s_routing(struct v4l2_subdev *sd, const struct v4l2_routing *r ks0127_and_or(sd, KS_CMDA, 0xff, 0x40); /* VSE=1 */ /* set input line and VALIGN */ - ks0127_and_or(sd, KS_CMDB, 0xb0, (route->input | 0x40)); + ks0127_and_or(sd, KS_CMDB, 0xb0, (input | 0x40)); /* freerunning mode, */ /* TSTGEN = 1 TSTGFR=11 TSTGPH=0 TSTGPK=0 VMEM=1*/ ks0127_and_or(sd, KS_CMDC, 0x70, 0x87); @@ -541,7 +542,7 @@ static int ks0127_s_routing(struct v4l2_subdev *sd, const struct v4l2_routing *r default: v4l2_dbg(1, debug, sd, - "s_routing: Unknown input %d\n", route->input); + "s_routing: Unknown input %d\n", input); break; } diff --git a/linux/drivers/media/video/m52790.c b/linux/drivers/media/video/m52790.c index 40bdf8857..e6139e7e6 100644 --- a/linux/drivers/media/video/m52790.c +++ b/linux/drivers/media/video/m52790.c @@ -75,12 +75,13 @@ static int m52790_write(struct v4l2_subdev *sd) part of the audio output routing. The normal case is that another chip takes care of the actual muting so making it part of the output routing seems to be the right thing to do for now. */ -static int m52790_s_routing(struct v4l2_subdev *sd, const struct v4l2_routing *route) +static int m52790_s_routing(struct v4l2_subdev *sd, + u32 input, u32 output, u32 config) { struct m52790_state *state = to_state(sd); - state->input = route->input; - state->output = route->output; + state->input = input; + state->output = output; m52790_write(sd); return 0; } diff --git a/linux/drivers/media/video/msp3400-driver.c b/linux/drivers/media/video/msp3400-driver.c index 7a2b87621..bbcc43a49 100644 --- a/linux/drivers/media/video/msp3400-driver.c +++ b/linux/drivers/media/video/msp3400-driver.c @@ -516,25 +516,26 @@ static int msp_s_std(struct v4l2_subdev *sd, v4l2_std_id id) return 0; } -static int msp_s_routing(struct v4l2_subdev *sd, const struct v4l2_routing *rt) +static int msp_s_routing(struct v4l2_subdev *sd, + u32 input, u32 output, u32 config) { struct msp_state *state = to_state(sd); struct i2c_client *client = v4l2_get_subdevdata(sd); - int tuner = (rt->input >> 3) & 1; - int sc_in = rt->input & 0x7; - int sc1_out = rt->output & 0xf; - int sc2_out = (rt->output >> 4) & 0xf; + int tuner = (input >> 3) & 1; + int sc_in = input & 0x7; + int sc1_out = output & 0xf; + int sc2_out = (output >> 4) & 0xf; u16 val, reg; int i; int extern_input = 1; - if (state->routing.input == rt->input && - state->routing.output == rt->output) + if (state->route_in == input && state->route_out == output) return 0; - state->routing = *rt; + state->route_in = input; + state->route_out = output; /* check if the tuner input is used */ for (i = 0; i < 5; i++) { - if (((rt->input >> (4 + i * 4)) & 0xf) == 0) + if (((input >> (4 + i * 4)) & 0xf) == 0) extern_input = 0; } state->mode = extern_input ? MSP_MODE_EXTERN : MSP_MODE_AM_DETECT; @@ -684,7 +685,7 @@ static int msp_log_status(struct v4l2_subdev *sd) } v4l_info(client, "Audmode: 0x%04x\n", state->audmode); v4l_info(client, "Routing: 0x%08x (input) 0x%08x (output)\n", - state->routing.input, state->routing.output); + state->route_in, state->route_out); v4l_info(client, "ACB: 0x%04x\n", state->acb); return 0; } @@ -776,8 +777,8 @@ static int msp_probe(struct i2c_client *client, const struct i2c_device_id *id) state->i2s_mode = 0; init_waitqueue_head(&state->wq); /* These are the reset input/output positions */ - state->routing.input = MSP_INPUT_DEFAULT; - state->routing.output = MSP_OUTPUT_DEFAULT; + state->route_in = MSP_INPUT_DEFAULT; + state->route_out = MSP_OUTPUT_DEFAULT; state->rev1 = msp_read_dsp(client, 0x1e); if (state->rev1 != -1) diff --git a/linux/drivers/media/video/msp3400-driver.h b/linux/drivers/media/video/msp3400-driver.h index 3fe1c1b10..d6b3e6d0e 100644 --- a/linux/drivers/media/video/msp3400-driver.h +++ b/linux/drivers/media/video/msp3400-driver.h @@ -80,7 +80,8 @@ struct msp_state { int i2s_mode; int main, second; /* sound carrier */ int input; - struct v4l2_routing routing; + u32 route_in; + u32 route_out; /* v4l2 */ int audmode; diff --git a/linux/drivers/media/video/msp3400-kthreads.c b/linux/drivers/media/video/msp3400-kthreads.c index ccba71d9f..80e372f43 100644 --- a/linux/drivers/media/video/msp3400-kthreads.c +++ b/linux/drivers/media/video/msp3400-kthreads.c @@ -191,7 +191,7 @@ void msp3400c_set_mode(struct i2c_client *client, int mode) { struct msp_state *state = to_state(i2c_get_clientdata(client)); struct msp3400c_init_data_dem *data = &msp3400c_init_data[mode]; - int tuner = (state->routing.input >> 3) & 1; + int tuner = (state->route_in >> 3) & 1; int i; v4l_dbg(1, msp_debug, client, "set_mode: %d\n", mode); @@ -899,7 +899,7 @@ static void msp34xxg_set_source(struct i2c_client *client, u16 reg, int in) static void msp34xxg_set_sources(struct i2c_client *client) { struct msp_state *state = to_state(i2c_get_clientdata(client)); - u32 in = state->routing.input; + u32 in = state->route_in; msp34xxg_set_source(client, 0x0008, (in >> 4) & 0xf); /* quasi-peak detector is set to same input as the loudspeaker (MAIN) */ @@ -915,7 +915,7 @@ static void msp34xxg_set_sources(struct i2c_client *client) static void msp34xxg_reset(struct i2c_client *client) { struct msp_state *state = to_state(i2c_get_clientdata(client)); - int tuner = (state->routing.input >> 3) & 1; + int tuner = (state->route_in >> 3) & 1; int modus; /* initialize std to 1 (autodetect) to signal that no standard is diff --git a/linux/drivers/media/video/mxb.c b/linux/drivers/media/video/mxb.c index d593fec1c..4a50c0e95 100644 --- a/linux/drivers/media/video/mxb.c +++ b/linux/drivers/media/video/mxb.c @@ -84,9 +84,14 @@ static struct { static int video_audio_connect[MXB_INPUTS] = { 0, 1, 3, 3 }; +struct mxb_routing { + u32 input; + u32 output; +}; + /* These are the necessary input-output-pins for bringing one audio source (see above) to the CD-output. Note that gain is set to 0 in this table. */ -static struct v4l2_routing TEA6420_cd[MXB_AUDIOS + 1][2] = { +static struct mxb_routing TEA6420_cd[MXB_AUDIOS + 1][2] = { { { 1, 1 }, { 1, 1 } }, /* Tuner */ { { 5, 1 }, { 6, 1 } }, /* AUX 1 */ { { 4, 1 }, { 6, 1 } }, /* AUX 2 */ @@ -98,7 +103,7 @@ static struct v4l2_routing TEA6420_cd[MXB_AUDIOS + 1][2] = { /* These are the necessary input-output-pins for bringing one audio source (see above) to the line-output. Note that gain is set to 0 in this table. */ -static struct v4l2_routing TEA6420_line[MXB_AUDIOS + 1][2] = { +static struct mxb_routing TEA6420_line[MXB_AUDIOS + 1][2] = { { { 2, 3 }, { 1, 2 } }, { { 5, 3 }, { 6, 2 } }, { { 4, 3 }, { 6, 2 } }, @@ -135,10 +140,6 @@ struct mxb #define saa7111a_call(mxb, o, f, args...) \ v4l2_subdev_call(mxb->saa7111a, o, f, ##args) -#define tea6420_1_call(mxb, o, f, args...) \ - v4l2_subdev_call(mxb->tea6420_1, o, f, ##args) -#define tea6420_2_call(mxb, o, f, args...) \ - v4l2_subdev_call(mxb->tea6420_2, o, f, ##args) #define tda9840_call(mxb, o, f, args...) \ v4l2_subdev_call(mxb->tda9840, o, f, ##args) #define tea6415c_call(mxb, o, f, args...) \ @@ -148,6 +149,22 @@ struct mxb #define call_all(dev, o, f, args...) \ v4l2_device_call_until_err(&dev->v4l2_dev, 0, o, f, ##args) +static inline void tea6420_route_cd(struct mxb *mxb, int idx) +{ + v4l2_subdev_call(mxb->tea6420_1, audio, s_routing, + TEA6420_cd[idx][0].input, TEA6420_cd[idx][0].output, 0); + v4l2_subdev_call(mxb->tea6420_2, audio, s_routing, + TEA6420_cd[idx][1].input, TEA6420_cd[idx][1].output, 0); +} + +static inline void tea6420_route_line(struct mxb *mxb, int idx) +{ + v4l2_subdev_call(mxb->tea6420_1, audio, s_routing, + TEA6420_line[idx][0].input, TEA6420_line[idx][0].output, 0); + v4l2_subdev_call(mxb->tea6420_2, audio, s_routing, + TEA6420_line[idx][1].input, TEA6420_line[idx][1].output, 0); +} + static struct saa7146_extension extension; static int mxb_probe(struct saa7146_dev *dev) @@ -272,7 +289,6 @@ static int mxb_init_done(struct saa7146_dev* dev) struct i2c_msg msg; struct tuner_setup tun_setup; v4l2_std_id std = V4L2_STD_PAL_BG; - struct v4l2_routing route; int i = 0, err = 0; @@ -281,9 +297,8 @@ static int mxb_init_done(struct saa7146_dev* dev) /* select tuner-output on saa7111a */ i = 0; - route.input = SAA7115_COMPOSITE0; - route.output = SAA7111_FMT_CCIR | SAA7111_VBI_BYPASS; - saa7111a_call(mxb, video, s_routing, &route); + saa7111a_call(mxb, video, s_routing, SAA7115_COMPOSITE0, + SAA7111_FMT_CCIR | SAA7111_VBI_BYPASS, 0); /* select a tuner type */ tun_setup.mode_mask = T_ANALOG_TV; @@ -300,20 +315,14 @@ static int mxb_init_done(struct saa7146_dev* dev) tuner_call(mxb, core, s_std, std); /* mute audio on tea6420s */ - tea6420_1_call(mxb, audio, s_routing, &TEA6420_line[6][0]); - tea6420_2_call(mxb, audio, s_routing, &TEA6420_line[6][1]); - tea6420_1_call(mxb, audio, s_routing, &TEA6420_cd[6][0]); - tea6420_2_call(mxb, audio, s_routing, &TEA6420_cd[6][1]); + tea6420_route_line(mxb, 6); + tea6420_route_cd(mxb, 6); /* switch to tuner-channel on tea6415c */ - route.input = 3; - route.output = 17; - tea6415c_call(mxb, video, s_routing, &route); + tea6415c_call(mxb, video, s_routing, 3, 17, 0); /* select tuner-output on multicable on tea6415c */ - route.input = 3; - route.output = 13; - tea6415c_call(mxb, video, s_routing, &route); + tea6415c_call(mxb, video, s_routing, 3, 13, 0); /* the rest for mxb */ mxb->cur_input = 0; @@ -437,18 +446,9 @@ static int vidioc_s_ctrl(struct file *file, void *fh, struct v4l2_control *vc) if (vc->id == V4L2_CID_AUDIO_MUTE) { mxb->cur_mute = vc->value; - if (!vc->value) { - /* switch the audio-source */ - tea6420_1_call(mxb, audio, s_routing, - &TEA6420_line[video_audio_connect[mxb->cur_input]][0]); - tea6420_2_call(mxb, audio, s_routing, - &TEA6420_line[video_audio_connect[mxb->cur_input]][1]); - } else { - tea6420_1_call(mxb, audio, s_routing, - &TEA6420_line[6][0]); - tea6420_2_call(mxb, audio, s_routing, - &TEA6420_line[6][1]); - } + /* switch the audio-source */ + tea6420_route_line(mxb, vc->value ? 6 : + video_audio_connect[mxb->cur_input]); DEB_EE(("VIDIOC_S_CTRL, V4L2_CID_AUDIO_MUTE: %d.\n", vc->value)); } return 0; @@ -477,7 +477,7 @@ static int vidioc_s_input(struct file *file, void *fh, unsigned int input) { struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev; struct mxb *mxb = (struct mxb *)dev->ext_priv; - struct v4l2_routing route; + int err = 0; int i = 0; DEB_EE(("VIDIOC_S_INPUT %d.\n", input)); @@ -495,16 +495,12 @@ static int vidioc_s_input(struct file *file, void *fh, unsigned int input) switch (input) { case TUNER: i = SAA7115_COMPOSITE0; - route.input = 3; - route.output = 17; - if (tea6415c_call(mxb, video, s_routing, &route)) { - printk(KERN_ERR "VIDIOC_S_INPUT: could not address tea6415c #1\n"); - return -EFAULT; - } + err = tea6415c_call(mxb, video, s_routing, 3, 17, 0); + /* connect tuner-output always to multicable */ - route.input = 3; - route.output = 13; + if (!err) + err = tea6415c_call(mxb, video, s_routing, 3, 13, 0); break; case AUX3_YC: /* nothing to be done here. aux3_yc is @@ -518,37 +514,20 @@ static int vidioc_s_input(struct file *file, void *fh, unsigned int input) break; case AUX1: i = SAA7115_COMPOSITE0; - route.input = 1; - route.output = 17; + err = tea6415c_call(mxb, video, s_routing, 1, 17, 0); break; } - /* switch video in tea6415c only if necessary */ - switch (input) { - case TUNER: - case AUX1: - if (tea6415c_call(mxb, video, s_routing, &route)) { - printk(KERN_ERR "VIDIOC_S_INPUT: could not address tea6415c #3\n"); - return -EFAULT; - } - break; - default: - break; - } + if (err) + return err; /* switch video in saa7111a */ - route.input = i; - route.output = 0; - if (saa7111a_call(mxb, video, s_routing, &route)) + if (saa7111a_call(mxb, video, s_routing, i, 0, 0)) printk(KERN_ERR "VIDIOC_S_INPUT: could not address saa7111a #1.\n"); /* switch the audio-source only if necessary */ - if (0 == mxb->cur_mute) { - tea6420_1_call(mxb, audio, s_routing, - &TEA6420_line[video_audio_connect[input]][0]); - tea6420_2_call(mxb, audio, s_routing, - &TEA6420_line[video_audio_connect[input]][1]); - } + if (0 == mxb->cur_mute) + tea6420_route_line(mxb, video_audio_connect[input]); return 0; } @@ -690,9 +669,7 @@ static long vidioc_default(struct file *file, void *fh, int cmd, void *arg) DEB_EE(("MXB_S_AUDIO_CD: i:%d.\n", i)); - tea6420_1_call(mxb, audio, s_routing, &TEA6420_cd[i][0]); - tea6420_2_call(mxb, audio, s_routing, &TEA6420_cd[i][1]); - + tea6420_route_cd(mxb, i); return 0; } case MXB_S_AUDIO_LINE: @@ -705,9 +682,7 @@ static long vidioc_default(struct file *file, void *fh, int cmd, void *arg) } DEB_EE(("MXB_S_AUDIO_LINE: i:%d.\n", i)); - tea6420_1_call(mxb, audio, s_routing, &TEA6420_line[i][0]); - tea6420_2_call(mxb, audio, s_routing, &TEA6420_line[i][1]); - + tea6420_route_line(mxb, i); return 0; } default: diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-audio.c b/linux/drivers/media/video/pvrusb2/pvrusb2-audio.c index 61cc80ef2..86049f412 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-audio.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-audio.c @@ -59,9 +59,9 @@ static const struct routing_scheme routing_schemes[] = { void pvr2_msp3400_subdev_update(struct pvr2_hdw *hdw, struct v4l2_subdev *sd) { if (hdw->input_dirty || hdw->force_dirty) { - struct v4l2_routing route; const struct routing_scheme *sp; unsigned int sid = hdw->hdw_desc->signal_routing_scheme; + u32 input; pvr2_trace(PVR2_TRACE_CHIPS, "subdev msp3400 v4l2 set_stereo"); @@ -69,7 +69,7 @@ void pvr2_msp3400_subdev_update(struct pvr2_hdw *hdw, struct v4l2_subdev *sd) ((sp = routing_schemes + sid) != NULL) && (hdw->input_val >= 0) && (hdw->input_val < sp->cnt)) { - route.input = sp->def[hdw->input_val]; + input = sp->def[hdw->input_val]; } else { pvr2_trace(PVR2_TRACE_ERROR_LEGS, "*** WARNING *** subdev msp3400 set_input:" @@ -78,8 +78,8 @@ void pvr2_msp3400_subdev_update(struct pvr2_hdw *hdw, struct v4l2_subdev *sd) sid, hdw->input_val); return; } - route.output = MSP_OUTPUT(MSP_SC_IN_DSP_SCART1); - sd->ops->audio->s_routing(sd, &route); + sd->ops->audio->s_routing(sd, input, + MSP_OUTPUT(MSP_SC_IN_DSP_SCART1), 0); } } diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-cs53l32a.c b/linux/drivers/media/video/pvrusb2/pvrusb2-cs53l32a.c index 932943bd7..f99b77c92 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-cs53l32a.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-cs53l32a.c @@ -61,16 +61,16 @@ static const struct routing_scheme routing_schemes[] = { void pvr2_cs53l32a_subdev_update(struct pvr2_hdw *hdw, struct v4l2_subdev *sd) { if (hdw->input_dirty || hdw->force_dirty) { - struct v4l2_routing route; const struct routing_scheme *sp; unsigned int sid = hdw->hdw_desc->signal_routing_scheme; + u32 input; pvr2_trace(PVR2_TRACE_CHIPS, "subdev v4l2 set_input(%d)", hdw->input_val); if ((sid < ARRAY_SIZE(routing_schemes)) && ((sp = routing_schemes + sid) != NULL) && (hdw->input_val >= 0) && (hdw->input_val < sp->cnt)) { - route.input = sp->def[hdw->input_val]; + input = sp->def[hdw->input_val]; } else { pvr2_trace(PVR2_TRACE_ERROR_LEGS, "*** WARNING *** subdev v4l2 set_input:" @@ -79,8 +79,7 @@ void pvr2_cs53l32a_subdev_update(struct pvr2_hdw *hdw, struct v4l2_subdev *sd) sid, hdw->input_val); return; } - route.output = 0; - sd->ops->audio->s_routing(sd, &route); + sd->ops->audio->s_routing(sd, input, 0, 0); } } diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c b/linux/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c index e0a6de5ae..ef47c3874 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c @@ -106,14 +106,11 @@ void pvr2_cx25840_subdev_update(struct pvr2_hdw *hdw, struct v4l2_subdev *sd) { pvr2_trace(PVR2_TRACE_CHIPS, "subdev cx2584x update..."); if (hdw->input_dirty || hdw->force_dirty) { - struct v4l2_routing route; enum cx25840_video_input vid_input; enum cx25840_audio_input aud_input; const struct routing_scheme *sp; unsigned int sid = hdw->hdw_desc->signal_routing_scheme; - memset(&route, 0, sizeof(route)); - if ((sid < ARRAY_SIZE(routing_schemes)) && ((sp = routing_schemes + sid) != NULL) && (hdw->input_val >= 0) && @@ -132,10 +129,8 @@ void pvr2_cx25840_subdev_update(struct pvr2_hdw *hdw, struct v4l2_subdev *sd) pvr2_trace(PVR2_TRACE_CHIPS, "subdev cx2584x set_input vid=0x%x aud=0x%x", vid_input, aud_input); - route.input = (u32)vid_input; - sd->ops->video->s_routing(sd, &route); - route.input = (u32)aud_input; - sd->ops->audio->s_routing(sd, &route); + sd->ops->video->s_routing(sd, (u32)vid_input, 0, 0); + sd->ops->audio->s_routing(sd, (u32)aud_input, 0, 0); } } diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-video-v4l.c b/linux/drivers/media/video/pvrusb2/pvrusb2-video-v4l.c index b29a42ef5..d240331a6 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-video-v4l.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-video-v4l.c @@ -76,16 +76,17 @@ static const struct routing_scheme routing_schemes[] = { void pvr2_saa7115_subdev_update(struct pvr2_hdw *hdw, struct v4l2_subdev *sd) { if (hdw->input_dirty || hdw->force_dirty) { - struct v4l2_routing route; const struct routing_scheme *sp; unsigned int sid = hdw->hdw_desc->signal_routing_scheme; + u32 input; + pvr2_trace(PVR2_TRACE_CHIPS, "subdev v4l2 set_input(%d)", hdw->input_val); if ((sid < ARRAY_SIZE(routing_schemes)) && ((sp = routing_schemes + sid) != NULL) && (hdw->input_val >= 0) && (hdw->input_val < sp->cnt)) { - route.input = sp->def[hdw->input_val]; + input = sp->def[hdw->input_val]; } else { pvr2_trace(PVR2_TRACE_ERROR_LEGS, "*** WARNING *** subdev v4l2 set_input:" @@ -94,8 +95,7 @@ void pvr2_saa7115_subdev_update(struct pvr2_hdw *hdw, struct v4l2_subdev *sd) sid, hdw->input_val); return; } - route.output = 0; - sd->ops->video->s_routing(sd, &route); + sd->ops->video->s_routing(sd, input, 0, 0); } } diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-wm8775.c b/linux/drivers/media/video/pvrusb2/pvrusb2-wm8775.c index 6364434a5..766e76372 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-wm8775.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-wm8775.c @@ -40,24 +40,22 @@ void pvr2_wm8775_subdev_update(struct pvr2_hdw *hdw, struct v4l2_subdev *sd) { if (hdw->input_dirty || hdw->force_dirty) { - struct v4l2_routing route; - - memset(&route, 0, sizeof(route)); + u32 input; switch (hdw->input_val) { case PVR2_CVAL_INPUT_RADIO: - route.input = 1; + input = 1; break; default: /* All other cases just use the second input */ - route.input = 2; + input = 2; break; } pvr2_trace(PVR2_TRACE_CHIPS, "subdev wm8775" " set_input(val=%d route=0x%x)", - hdw->input_val, route.input); + hdw->input_val, input); - sd->ops->audio->s_routing(sd, &route); + sd->ops->audio->s_routing(sd, input, 0, 0); } } diff --git a/linux/drivers/media/video/saa7110.c b/linux/drivers/media/video/saa7110.c index 0eeae294f..c1f13d334 100644 --- a/linux/drivers/media/video/saa7110.c +++ b/linux/drivers/media/video/saa7110.c @@ -305,17 +305,18 @@ static int saa7110_s_std(struct v4l2_subdev *sd, v4l2_std_id std) return 0; } -static int saa7110_s_routing(struct v4l2_subdev *sd, const struct v4l2_routing *route) +static int saa7110_s_routing(struct v4l2_subdev *sd, + u32 input, u32 output, u32 config) { struct saa7110 *decoder = to_saa7110(sd); - if (route->input < 0 || route->input >= SAA7110_MAX_INPUT) { - v4l2_dbg(1, debug, sd, "input=%d not available\n", route->input); + if (input < 0 || input >= SAA7110_MAX_INPUT) { + v4l2_dbg(1, debug, sd, "input=%d not available\n", input); return -EINVAL; } - if (decoder->input != route->input) { - saa7110_selmux(sd, route->input); - v4l2_dbg(1, debug, sd, "switched to input=%d\n", route->input); + if (decoder->input != input) { + saa7110_selmux(sd, input); + v4l2_dbg(1, debug, sd, "switched to input=%d\n", input); } return 0; } diff --git a/linux/drivers/media/video/saa7115.c b/linux/drivers/media/video/saa7115.c index 7d445bac7..f6ad6f256 100644 --- a/linux/drivers/media/video/saa7115.c +++ b/linux/drivers/media/video/saa7115.c @@ -1237,30 +1237,32 @@ static int saa711x_s_radio(struct v4l2_subdev *sd) return 0; } -static int saa711x_s_routing(struct v4l2_subdev *sd, const struct v4l2_routing *route) +static int saa711x_s_routing(struct v4l2_subdev *sd, + u32 input, u32 output, u32 config) { struct saa711x_state *state = to_state(sd); - u32 input = route->input; u8 mask = (state->ident == V4L2_IDENT_SAA7111) ? 0xf8 : 0xf0; - v4l2_dbg(1, debug, sd, "decoder set input %d output %d\n", route->input, route->output); + v4l2_dbg(1, debug, sd, "decoder set input %d output %d\n", + input, output); + /* saa7111/3 does not have these inputs */ if ((state->ident == V4L2_IDENT_SAA7113 || state->ident == V4L2_IDENT_SAA7111) && - (route->input == SAA7115_COMPOSITE4 || - route->input == SAA7115_COMPOSITE5)) { + (input == SAA7115_COMPOSITE4 || + input == SAA7115_COMPOSITE5)) { return -EINVAL; } - if (route->input > SAA7115_SVIDEO3) + if (input > SAA7115_SVIDEO3) return -EINVAL; - if (route->output > SAA7115_IPORT_ON) + if (output > SAA7115_IPORT_ON) return -EINVAL; - if (state->input == route->input && state->output == route->output) + if (state->input == input && state->output == output) return 0; v4l2_dbg(1, debug, sd, "now setting %s input %s output\n", - (route->input >= SAA7115_SVIDEO0) ? "S-Video" : "Composite", - (route->output == SAA7115_IPORT_ON) ? "iport on" : "iport off"); - state->input = route->input; + (input >= SAA7115_SVIDEO0) ? "S-Video" : "Composite", + (output == SAA7115_IPORT_ON) ? "iport on" : "iport off"); + state->input = input; /* saa7111 has slightly different input numbering */ if (state->ident == V4L2_IDENT_SAA7111) { @@ -1269,10 +1271,10 @@ static int saa711x_s_routing(struct v4l2_subdev *sd, const struct v4l2_routing * /* saa7111 specific */ saa711x_write(sd, R_10_CHROMA_CNTL_2, (saa711x_read(sd, R_10_CHROMA_CNTL_2) & 0x3f) | - ((route->output & 0xc0) ^ 0x40)); + ((output & 0xc0) ^ 0x40)); saa711x_write(sd, R_13_RT_X_PORT_OUT_CNTL, (saa711x_read(sd, R_13_RT_X_PORT_OUT_CNTL) & 0xf0) | - ((route->output & 2) ? 0x0a : 0)); + ((output & 2) ? 0x0a : 0)); } /* select mode */ @@ -1285,7 +1287,7 @@ static int saa711x_s_routing(struct v4l2_subdev *sd, const struct v4l2_routing * (saa711x_read(sd, R_09_LUMA_CNTL) & 0x7f) | (state->input >= SAA7115_SVIDEO0 ? 0x80 : 0x0)); - state->output = route->output; + state->output = output; if (state->ident == V4L2_IDENT_SAA7114 || state->ident == V4L2_IDENT_SAA7115) { saa711x_write(sd, R_83_X_PORT_I_O_ENA_AND_OUT_CLK, diff --git a/linux/drivers/media/video/saa7127.c b/linux/drivers/media/video/saa7127.c index 56bd3dc4d..72dd555a4 100644 --- a/linux/drivers/media/video/saa7127.c +++ b/linux/drivers/media/video/saa7127.c @@ -576,15 +576,16 @@ static int saa7127_s_std_output(struct v4l2_subdev *sd, v4l2_std_id std) return saa7127_set_std(sd, std); } -static int saa7127_s_routing(struct v4l2_subdev *sd, const struct v4l2_routing *route) +static int saa7127_s_routing(struct v4l2_subdev *sd, + u32 input, u32 output, u32 config) { struct saa7127_state *state = to_state(sd); int rc = 0; - if (state->input_type != route->input) - rc = saa7127_set_input_type(sd, route->input); - if (rc == 0 && state->output_type != route->output) - rc = saa7127_set_output_type(sd, route->output); + if (state->input_type != input) + rc = saa7127_set_input_type(sd, input); + if (rc == 0 && state->output_type != output) + rc = saa7127_set_output_type(sd, output); return rc; } diff --git a/linux/drivers/media/video/saa717x.c b/linux/drivers/media/video/saa717x.c index 15a44d2ce..1803e1186 100644 --- a/linux/drivers/media/video/saa717x.c +++ b/linux/drivers/media/video/saa717x.c @@ -1110,22 +1110,22 @@ static struct v4l2_queryctrl saa717x_qctrl[] = { }, }; -static int saa717x_s_video_routing(struct v4l2_subdev *sd, const struct v4l2_routing *route) +static int saa717x_s_video_routing(struct v4l2_subdev *sd, + u32 input, u32 output, u32 config) { struct saa717x_state *decoder = to_state(sd); - int inp = route->input; - int is_tuner = inp & 0x80; /* tuner input flag */ + int is_tuner = input & 0x80; /* tuner input flag */ - inp &= 0x7f; + input &= 0x7f; - v4l2_dbg(1, debug, sd, "decoder set input (%d)\n", inp); + v4l2_dbg(1, debug, sd, "decoder set input (%d)\n", input); /* inputs from 0-9 are available*/ /* saa717x have mode0-mode9 but mode5 is reserved. */ - if (inp < 0 || inp > 9 || inp == 5) + if (input < 0 || input > 9 || input == 5) return -EINVAL; - if (decoder->input != inp) { - int input_line = inp; + if (decoder->input != input) { + int input_line = input; decoder->input = input_line; v4l2_dbg(1, debug, sd, "now setting %s input %d\n", @@ -1282,12 +1282,13 @@ static int saa717x_s_std(struct v4l2_subdev *sd, v4l2_std_id std) return 0; } -static int saa717x_s_audio_routing(struct v4l2_subdev *sd, const struct v4l2_routing *route) +static int saa717x_s_audio_routing(struct v4l2_subdev *sd, + u32 input, u32 output, u32 config) { struct saa717x_state *decoder = to_state(sd); - if (route->input < 3) { /* FIXME! --tadachi */ - decoder->audio_input = route->input; + if (input < 3) { /* FIXME! --tadachi */ + decoder->audio_input = input; v4l2_dbg(1, debug, sd, "set decoder audio input to %d\n", decoder->audio_input); diff --git a/linux/drivers/media/video/saa7185.c b/linux/drivers/media/video/saa7185.c index bb3e49006..459a814d4 100644 --- a/linux/drivers/media/video/saa7185.c +++ b/linux/drivers/media/video/saa7185.c @@ -251,14 +251,15 @@ static int saa7185_s_std_output(struct v4l2_subdev *sd, v4l2_std_id std) return 0; } -static int saa7185_s_routing(struct v4l2_subdev *sd, const struct v4l2_routing *route) +static int saa7185_s_routing(struct v4l2_subdev *sd, + u32 input, u32 output, u32 config) { struct saa7185 *encoder = to_saa7185(sd); - /* RJ: route->input = 0: input is from SA7111 - route->input = 1: input is from ZR36060 */ + /* RJ: input = 0: input is from SA7111 + input = 1: input is from ZR36060 */ - switch (route->input) { + switch (input) { case 0: /* turn off colorbar */ saa7185_write(sd, 0x3a, 0x0f); diff --git a/linux/drivers/media/video/saa7191.c b/linux/drivers/media/video/saa7191.c index f6a6b80b6..aa59776e1 100644 --- a/linux/drivers/media/video/saa7191.c +++ b/linux/drivers/media/video/saa7191.c @@ -166,14 +166,14 @@ static int saa7191_write_block(struct v4l2_subdev *sd, /* Helper functions */ static int saa7191_s_routing(struct v4l2_subdev *sd, - const struct v4l2_routing *route) + u32 input, u32 output, u32 config) { struct saa7191 *decoder = to_saa7191(sd); u8 luma = saa7191_read_reg(sd, SAA7191_REG_LUMA); u8 iock = saa7191_read_reg(sd, SAA7191_REG_IOCK); int err; - switch (route->input) { + switch (input) { case SAA7191_INPUT_COMPOSITE: /* Set Composite input */ iock &= ~(SAA7191_IOCK_CHRS | SAA7191_IOCK_GPSW1 | SAA7191_IOCK_GPSW2); @@ -196,7 +196,7 @@ static int saa7191_s_routing(struct v4l2_subdev *sd, if (err) return -EIO; - decoder->input = route->input; + decoder->input = input; return 0; } diff --git a/linux/drivers/media/video/tea6415c.c b/linux/drivers/media/video/tea6415c.c index 3a942d17d..de866798b 100644 --- a/linux/drivers/media/video/tea6415c.c +++ b/linux/drivers/media/video/tea6415c.c @@ -53,12 +53,11 @@ I2C_CLIENT_INSMOD; #endif /* makes a connection between the input-pin 'i' and the output-pin 'o' */ -static int tea6415c_s_routing(struct v4l2_subdev *sd, const struct v4l2_routing *route) +static int tea6415c_s_routing(struct v4l2_subdev *sd, + u32 i, u32 o, u32 config) { struct i2c_client *client = v4l2_get_subdevdata(sd); u8 byte = 0; - u32 i = route->input; - u32 o = route->output; int ret; v4l2_dbg(1, debug, sd, "i=%d, o=%d\n", i, o); diff --git a/linux/drivers/media/video/tea6420.c b/linux/drivers/media/video/tea6420.c index 5b25c3596..90054dfbe 100644 --- a/linux/drivers/media/video/tea6420.c +++ b/linux/drivers/media/video/tea6420.c @@ -54,15 +54,15 @@ I2C_CLIENT_INSMOD; /* make a connection between the input 'i' and the output 'o' with gain 'g' (note: i = 6 means 'mute') */ -static int tea6420_s_routing(struct v4l2_subdev *sd, const struct v4l2_routing *route) +static int tea6420_s_routing(struct v4l2_subdev *sd, + u32 i, u32 o, u32 config) { struct i2c_client *client = v4l2_get_subdevdata(sd); - int i = route->input; - int o = route->output & 0xf; - int g = (route->output >> 4) & 0xf; + int g = (o >> 4) & 0xf; u8 byte; int ret; + o &= 0xf; v4l2_dbg(1, debug, sd, "i=%d, o=%d, g=%d\n", i, o, g); /* check if the parameters are valid */ @@ -139,13 +139,8 @@ static int tea6420_probe(struct i2c_client *client, /* set initial values: set "mute"-input to all outputs at gain 0 */ err = 0; - for (i = 1; i < 5; i++) { - struct v4l2_routing route; - - route.input = 6; - route.output = i; - err += tea6420_s_routing(sd, &route); - } + for (i = 1; i < 5; i++) + err += tea6420_s_routing(sd, 6, i, 0); if (err) { v4l_dbg(1, debug, client, "could not initialize tea6420\n"); return -ENODEV; diff --git a/linux/drivers/media/video/tvaudio.c b/linux/drivers/media/video/tvaudio.c index 17bb81e9a..d89b68e9b 100644 --- a/linux/drivers/media/video/tvaudio.c +++ b/linux/drivers/media/video/tvaudio.c @@ -1805,17 +1805,18 @@ static int tvaudio_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc) return -EINVAL; } -static int tvaudio_s_routing(struct v4l2_subdev *sd, const struct v4l2_routing *rt) +static int tvaudio_s_routing(struct v4l2_subdev *sd, + u32 input, u32 output, u32 config) { struct CHIPSTATE *chip = to_state(sd); struct CHIPDESC *desc = chip->desc; if (!(desc->flags & CHIP_HAS_INPUTSEL)) return 0; - if (rt->input >= 4) + if (input >= 4) return -EINVAL; /* There are four inputs: tuner, radio, extern and intern. */ - chip->input = rt->input; + chip->input = input; if (chip->muted) return 0; chip_write_masked(chip, desc->inputreg, diff --git a/linux/drivers/media/video/tvp5150.c b/linux/drivers/media/video/tvp5150.c index 490e2f2d1..be7885172 100644 --- a/linux/drivers/media/video/tvp5150.c +++ b/linux/drivers/media/video/tvp5150.c @@ -80,7 +80,8 @@ struct tvp5150 { struct v4l2_subdev sd; v4l2_std_id norm; /* Current set standard */ - struct v4l2_routing route; + u32 input; + u32 output; int enable; int bright; int contrast; @@ -295,10 +296,10 @@ static inline void tvp5150_selmux(struct v4l2_subdev *sd) int input = 0; unsigned char val; - if ((decoder->route.output & TVP5150_BLACK_SCREEN) || !decoder->enable) + if ((decoder->output & TVP5150_BLACK_SCREEN) || !decoder->enable) input = 8; - switch (decoder->route.input) { + switch (decoder->input) { case TVP5150_COMPOSITE1: input |= 2; /* fall through */ @@ -314,8 +315,8 @@ static inline void tvp5150_selmux(struct v4l2_subdev *sd) v4l2_dbg(1, debug, sd, "Selecting video route: route input=%i, output=%i " "=> tvp5150 input=%i, opmode=%i\n", - decoder->route.input,decoder->route.output, - input, opmode ); + decoder->input, decoder->output, + input, opmode); tvp5150_write(sd, TVP5150_OP_MODE_CTL, opmode); tvp5150_write(sd, TVP5150_VD_IN_SRC_SEL_1, input); @@ -324,7 +325,7 @@ static inline void tvp5150_selmux(struct v4l2_subdev *sd) * For Composite and TV, it should be the reverse */ val = tvp5150_read(sd, TVP5150_MISC_CTL); - if (decoder->route.input == TVP5150_SVIDEO) + if (decoder->input == TVP5150_SVIDEO) val = (val & ~0x40) | 0x10; else val = (val & ~0x10) | 0x40; @@ -900,11 +901,13 @@ static int tvp5150_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) I2C Command ****************************************************************************/ -static int tvp5150_s_routing(struct v4l2_subdev *sd, const struct v4l2_routing *route) +static int tvp5150_s_routing(struct v4l2_subdev *sd, + u32 input, u32 output, u32 config) { struct tvp5150 *decoder = to_tvp5150(sd); - decoder->route = *route; + decoder->input = input; + decoder->output = output; tvp5150_selmux(sd); return 0; } @@ -1154,7 +1157,7 @@ static int tvp5150_probe(struct i2c_client *c, c->addr << 1, c->adapter->name); core->norm = V4L2_STD_ALL; /* Default is autodetect */ - core->route.input = TVP5150_COMPOSITE1; + core->input = TVP5150_COMPOSITE1; core->enable = 1; core->bright = 128; core->contrast = 128; diff --git a/linux/drivers/media/video/upd64031a.c b/linux/drivers/media/video/upd64031a.c index 990405335..7da860712 100644 --- a/linux/drivers/media/video/upd64031a.c +++ b/linux/drivers/media/video/upd64031a.c @@ -130,17 +130,18 @@ static int upd64031a_s_frequency(struct v4l2_subdev *sd, struct v4l2_frequency * /* ------------------------------------------------------------------------ */ -static int upd64031a_s_routing(struct v4l2_subdev *sd, const struct v4l2_routing *route) +static int upd64031a_s_routing(struct v4l2_subdev *sd, + u32 input, u32 output, u32 config) { struct upd64031a_state *state = to_state(sd); u8 r00, r05, r08; - state->gr_mode = (route->input & 3) << 6; - state->direct_3dycs_connect = (route->input & 0xc) << 4; + state->gr_mode = (input & 3) << 6; + state->direct_3dycs_connect = (input & 0xc) << 4; state->ext_comp_sync = - (route->input & UPD64031A_COMPOSITE_EXTERNAL) << 1; + (input & UPD64031A_COMPOSITE_EXTERNAL) << 1; state->ext_vert_sync = - (route->input & UPD64031A_VERTICAL_EXTERNAL) << 2; + (input & UPD64031A_VERTICAL_EXTERNAL) << 2; r00 = (state->regs[R00] & ~GR_MODE_MASK) | state->gr_mode; r05 = (state->regs[R00] & ~SYNC_CIRCUIT_MASK) | state->ext_comp_sync | state->ext_vert_sync; diff --git a/linux/drivers/media/video/upd64083.c b/linux/drivers/media/video/upd64083.c index 89f51835b..0dae4876e 100644 --- a/linux/drivers/media/video/upd64083.c +++ b/linux/drivers/media/video/upd64083.c @@ -108,15 +108,16 @@ static u8 upd64083_read(struct v4l2_subdev *sd, u8 reg) /* ------------------------------------------------------------------------ */ -static int upd64083_s_routing(struct v4l2_subdev *sd, const struct v4l2_routing *route) +static int upd64083_s_routing(struct v4l2_subdev *sd, + u32 input, u32 output, u32 config) { struct upd64083_state *state = to_state(sd); u8 r00, r02; - if (route->input > 7 || (route->input & 6) == 6) + if (input > 7 || (input & 6) == 6) return -EINVAL; - state->mode = (route->input & 3) << 6; - state->ext_y_adc = (route->input & UPD64083_EXT_Y_ADC) << 3; + state->mode = (input & 3) << 6; + state->ext_y_adc = (input & UPD64083_EXT_Y_ADC) << 3; r00 = (state->regs[R00] & ~(3 << 6)) | state->mode; r02 = (state->regs[R02] & ~(1 << 5)) | state->ext_y_adc; upd64083_write(sd, R00, r00); diff --git a/linux/drivers/media/video/usbvision/usbvision-core.c b/linux/drivers/media/video/usbvision/usbvision-core.c index 734df263f..9253ec6dd 100644 --- a/linux/drivers/media/video/usbvision/usbvision-core.c +++ b/linux/drivers/media/video/usbvision/usbvision-core.c @@ -2618,7 +2618,6 @@ int usbvision_muxsel(struct usb_usbvision *usbvision, int channel) /* inputs #1 and #2 are variable for SAA7111 and SAA7113 */ int mode[4]= {SAA7115_COMPOSITE0, 0, 0, SAA7115_COMPOSITE3}; int audio[]= {1, 0, 0, 0}; - struct v4l2_routing route; //channel 0 is TV with audiochannel 1 (tuner mono) //channel 1 is Composite with audio channel 0 (line in) //channel 2 is S-Video with audio channel 0 (line in) @@ -2651,9 +2650,7 @@ int usbvision_muxsel(struct usb_usbvision *usbvision, int channel) mode[2] = SAA7115_SVIDEO1; break; } - route.input = mode[channel]; - route.output = 0; - call_all(usbvision, video, s_routing, &route); + call_all(usbvision, video, s_routing, mode[channel], 0, 0); usbvision_set_audio(usbvision, audio[channel]); return 0; } diff --git a/linux/drivers/media/video/vino.c b/linux/drivers/media/video/vino.c index a142da23b..808d9434d 100644 --- a/linux/drivers/media/video/vino.c +++ b/linux/drivers/media/video/vino.c @@ -2569,12 +2569,11 @@ static int vino_acquire_input(struct vino_channel_settings *vcs) int input; int data_norm; v4l2_std_id norm; - struct v4l2_routing route = { 0, 0 }; input = VINO_INPUT_COMPOSITE; - route.input = vino_get_saa7191_input(input); - ret = decoder_call(video, s_routing, &route); + ret = decoder_call(video, s_routing, + vino_get_saa7191_input(input), 0, 0); if (ret) { ret = -EINVAL; goto out; @@ -2660,10 +2659,9 @@ static int vino_set_input(struct vino_channel_settings *vcs, int input) if (vino_drvdata->decoder_owner == vcs->channel) { int data_norm; v4l2_std_id norm; - struct v4l2_routing route = { 0, 0 }; - route.input = vino_get_saa7191_input(input); - ret = decoder_call(video, s_routing, &route); + ret = decoder_call(video, s_routing, + vino_get_saa7191_input(input), 0, 0); if (ret) { vino_drvdata->decoder_owner = VINO_NO_CHANNEL; ret = -EINVAL; diff --git a/linux/drivers/media/video/vpx3220.c b/linux/drivers/media/video/vpx3220.c index 8193e6277..ad141a1f8 100644 --- a/linux/drivers/media/video/vpx3220.c +++ b/linux/drivers/media/video/vpx3220.c @@ -396,33 +396,34 @@ static int vpx3220_s_std(struct v4l2_subdev *sd, v4l2_std_id std) return 0; } -static int vpx3220_s_routing(struct v4l2_subdev *sd, const struct v4l2_routing *route) +static int vpx3220_s_routing(struct v4l2_subdev *sd, + u32 input, u32 output, u32 config) { int data; - /* RJ: route->input = 0: ST8 (PCTV) input - route->input = 1: COMPOSITE input - route->input = 2: SVHS input */ + /* RJ: input = 0: ST8 (PCTV) input + input = 1: COMPOSITE input + input = 2: SVHS input */ - const int input[3][2] = { + const int input_vals[3][2] = { {0x0c, 0}, {0x0d, 0}, {0x0e, 1} }; - if (route->input < 0 || route->input > 2) + if (input < 0 || input > 2) return -EINVAL; - v4l2_dbg(1, debug, sd, "input switched to %s\n", inputs[route->input]); + v4l2_dbg(1, debug, sd, "input switched to %s\n", inputs[input]); - vpx3220_write(sd, 0x33, input[route->input][0]); + vpx3220_write(sd, 0x33, input_vals[input][0]); data = vpx3220_fp_read(sd, 0xf2) & ~(0x0020); if (data < 0) return data; /* 0x0010 is required to latch the setting */ vpx3220_fp_write(sd, 0xf2, - data | (input[route->input][1] << 5) | 0x0010); + data | (input_vals[input][1] << 5) | 0x0010); udelay(10); return 0; diff --git a/linux/drivers/media/video/wm8775.c b/linux/drivers/media/video/wm8775.c index e22497ad4..b07de0c7c 100644 --- a/linux/drivers/media/video/wm8775.c +++ b/linux/drivers/media/video/wm8775.c @@ -85,7 +85,8 @@ static int wm8775_write(struct v4l2_subdev *sd, int reg, u16 val) return -1; } -static int wm8775_s_routing(struct v4l2_subdev *sd, const struct v4l2_routing *route) +static int wm8775_s_routing(struct v4l2_subdev *sd, + u32 input, u32 output, u32 config) { struct wm8775_state *state = to_state(sd); @@ -94,11 +95,11 @@ static int wm8775_s_routing(struct v4l2_subdev *sd, const struct v4l2_routing *r 16 combinations. If only one input is active (the normal case) then the input values 1, 2, 4 or 8 should be used. */ - if (route->input > 15) { - v4l2_err(sd, "Invalid input %d.\n", route->input); + if (input > 15) { + v4l2_err(sd, "Invalid input %d.\n", input); return -EINVAL; } - state->input = route->input; + state->input = input; if (state->muted) return 0; wm8775_write(sd, R21, 0x0c0); diff --git a/linux/drivers/media/video/zoran/zoran_card.c b/linux/drivers/media/video/zoran/zoran_card.c index 1ab916e16..733db7690 100644 --- a/linux/drivers/media/video/zoran/zoran_card.c +++ b/linux/drivers/media/video/zoran/zoran_card.c @@ -1088,10 +1088,8 @@ zr36057_init (struct zoran *zr) detect_guest_activity(zr); test_interrupts(zr); if (!pass_through) { - struct v4l2_routing route = { 2, 0 }; - decoder_call(zr, video, s_stream, 0); - encoder_call(zr, video, s_routing, &route); + encoder_call(zr, video, s_routing, 2, 0, 0); } zr->zoran_proc = NULL; diff --git a/linux/drivers/media/video/zoran/zoran_device.c b/linux/drivers/media/video/zoran/zoran_device.c index b2880095c..4f656f682 100644 --- a/linux/drivers/media/video/zoran/zoran_device.c +++ b/linux/drivers/media/video/zoran/zoran_device.c @@ -972,7 +972,6 @@ zr36057_enable_jpg (struct zoran *zr, struct vfe_settings cap; int field_size = zr->jpg_buffers.buffer_size / zr->jpg_settings.field_per_buff; - struct v4l2_routing route = { 0, 0 }; zr->codec_mode = mode; @@ -995,8 +994,7 @@ zr36057_enable_jpg (struct zoran *zr, */ set_videobus_dir(zr, 0); decoder_call(zr, video, s_stream, 1); - route.input = 0; - encoder_call(zr, video, s_routing, &route); + encoder_call(zr, video, s_routing, 0, 0, 0); /* Take the JPEG codec and the VFE out of sleep */ jpeg_codec_sleep(zr, 0); @@ -1044,8 +1042,7 @@ zr36057_enable_jpg (struct zoran *zr, */ decoder_call(zr, video, s_stream, 0); set_videobus_dir(zr, 1); - route.input = 1; - encoder_call(zr, video, s_routing, &route); + encoder_call(zr, video, s_routing, 1, 0, 0); /* Take the JPEG codec and the VFE out of sleep */ jpeg_codec_sleep(zr, 0); @@ -1090,8 +1087,7 @@ zr36057_enable_jpg (struct zoran *zr, zr36057_adjust_vfe(zr, mode); decoder_call(zr, video, s_stream, 1); - route.input = 0; - encoder_call(zr, video, s_routing, &route); + encoder_call(zr, video, s_routing, 0, 0, 0); dprintk(2, KERN_INFO "%s: enable_jpg(IDLE)\n", ZR_DEVNAME(zr)); break; @@ -1577,8 +1573,6 @@ zoran_set_pci_master (struct zoran *zr, void zoran_init_hardware (struct zoran *zr) { - struct v4l2_routing route = { 0, 0 }; - /* Enable bus-mastering */ zoran_set_pci_master(zr, 1); @@ -1587,16 +1581,14 @@ zoran_init_hardware (struct zoran *zr) zr->card.init(zr); } - route.input = zr->card.input[zr->input].muxsel; - decoder_call(zr, core, init, 0); decoder_call(zr, core, s_std, zr->norm); - decoder_call(zr, video, s_routing, &route); + decoder_call(zr, video, s_routing, + zr->card.input[zr->input].muxsel, 0, 0); encoder_call(zr, core, init, 0); encoder_call(zr, video, s_std_output, zr->norm); - route.input = 0; - encoder_call(zr, video, s_routing, &route); + encoder_call(zr, video, s_routing, 0, 0, 0); /* toggle JPEG codec sleep to sync PLL */ jpeg_codec_sleep(zr, 1); diff --git a/linux/drivers/media/video/zoran/zoran_driver.c b/linux/drivers/media/video/zoran/zoran_driver.c index b965a316c..047902eb0 100644 --- a/linux/drivers/media/video/zoran/zoran_driver.c +++ b/linux/drivers/media/video/zoran/zoran_driver.c @@ -1019,10 +1019,8 @@ zoran_close(struct file *file) zoran_set_pci_master(zr, 0); if (!pass_through) { /* Switch to color bar */ - struct v4l2_routing route = { 2, 0 }; - decoder_call(zr, video, s_stream, 0); - encoder_call(zr, video, s_routing, &route); + encoder_call(zr, video, s_routing, 2, 0, 0); } } @@ -1504,8 +1502,6 @@ static int zoran_set_input (struct zoran *zr, int input) { - struct v4l2_routing route = { 0, 0 }; - if (input == zr->input) { return 0; } @@ -1527,10 +1523,10 @@ zoran_set_input (struct zoran *zr, return -EINVAL; } - route.input = zr->card.input[input].muxsel; zr->input = input; - decoder_call(zr, video, s_routing, &route); + decoder_call(zr, video, s_routing, + zr->card.input[input].muxsel, 0, 0); return 0; } @@ -1756,7 +1752,6 @@ jpgreqbuf_unlock_and_return: case BUZIOC_G_STATUS: { struct zoran_status *bstat = arg; - struct v4l2_routing route = { 0, 0 }; int status = 0, res = 0; v4l2_std_id norm; @@ -1770,8 +1765,6 @@ jpgreqbuf_unlock_and_return: return -EINVAL; } - route.input = zr->card.input[bstat->input].muxsel; - mutex_lock(&zr->resource_lock); if (zr->codec_mode != BUZ_MODE_IDLE) { @@ -1783,7 +1776,8 @@ jpgreqbuf_unlock_and_return: goto gstat_unlock_and_return; } - decoder_call(zr, video, s_routing, &route); + decoder_call(zr, video, s_routing, + zr->card.input[bstat->input].muxsel, 0, 0); /* sleep 1 second */ ssleep(1); @@ -1793,8 +1787,8 @@ jpgreqbuf_unlock_and_return: decoder_call(zr, video, g_input_status, &status); /* restore previous input and norm */ - route.input = zr->card.input[zr->input].muxsel; - decoder_call(zr, video, s_routing, &route); + decoder_call(zr, video, s_routing, + zr->card.input[zr->input].muxsel, 0, 0); gstat_unlock_and_return: mutex_unlock(&zr->resource_lock); -- cgit v1.2.3 From 446c315b251802b7948fbf9a07ccfac45bee2ab3 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Thu, 2 Apr 2009 16:37:41 +0200 Subject: ivtv/cx18: remove VIDIOC_INT_S_AUDIO_ROUTING debug support. From: Hans Verkuil Remove support for the debug call VIDIOC_INT_S_AUDIO_ROUTING from cx18 and ivtv. These internal ioctls shouldn't be exposed. These were only used through the cx18-ctl and ivtv-ctl utilities, and only when testing a new card variant. This cleanup allows the removal of this ioctl from v4l2-common.h. Priority: normal Signed-off-by: Hans Verkuil CC: Andy Walls --- linux/drivers/media/video/cx18/cx18-ioctl.c | 10 ---------- linux/drivers/media/video/ivtv/ivtv-ioctl.c | 8 -------- 2 files changed, 18 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/cx18/cx18-ioctl.c b/linux/drivers/media/video/cx18/cx18-ioctl.c index b2ebd81be..65e2ef425 100644 --- a/linux/drivers/media/video/cx18/cx18-ioctl.c +++ b/linux/drivers/media/video/cx18/cx18-ioctl.c @@ -951,16 +951,6 @@ static long cx18_default(struct file *file, void *fh, int cmd, void *arg) struct cx18 *cx = ((struct cx18_open_id *)fh)->cx; switch (cmd) { - case VIDIOC_INT_S_AUDIO_ROUTING: { - struct v4l2_routing *route = arg; - - CX18_DEBUG_IOCTL("VIDIOC_INT_S_AUDIO_ROUTING(%d, %d)\n", - route->input, route->output); - cx18_call_hw(cx, cx->card->hw_audio_ctrl, audio, s_routing, - route->input, route->output, 0); - break; - } - case VIDIOC_INT_RESET: { u32 val = *(u32 *)arg; diff --git a/linux/drivers/media/video/ivtv/ivtv-ioctl.c b/linux/drivers/media/video/ivtv/ivtv-ioctl.c index cf48b6ab9..4a2d464f0 100644 --- a/linux/drivers/media/video/ivtv/ivtv-ioctl.c +++ b/linux/drivers/media/video/ivtv/ivtv-ioctl.c @@ -1734,14 +1734,6 @@ static long ivtv_default(struct file *file, void *fh, int cmd, void *arg) struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv; switch (cmd) { - case VIDIOC_INT_S_AUDIO_ROUTING: { - struct v4l2_routing *route = arg; - - ivtv_call_hw(itv, itv->card->hw_audio, audio, s_routing, - route->input, route->output, 0); - break; - } - case VIDIOC_INT_RESET: { u32 val = *(u32 *)arg; -- cgit v1.2.3 From a094d5bae41248bc239d58e5f454b6d702726dcb Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Thu, 2 Apr 2009 16:54:15 +0200 Subject: saa7146: fix incorrect comment. From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/common/saa7146_i2c.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/common/saa7146_i2c.c b/linux/drivers/media/common/saa7146_i2c.c index fc2c95a16..ce4f102ad 100644 --- a/linux/drivers/media/common/saa7146_i2c.c +++ b/linux/drivers/media/common/saa7146_i2c.c @@ -415,8 +415,8 @@ int saa7146_i2c_adapter_prepare(struct saa7146_dev *dev, struct i2c_adapter *i2c if (i2c_adapter) { #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26) - /* For kernels > 2.6.26 it can actually be NULL - when v4l2_subdev is used. */ + /* For kernels >= 2.6.26 the class field is actually + always 0, so only do this test for older kernels. */ BUG_ON(!i2c_adapter->class); #endif i2c_set_adapdata(i2c_adapter, &dev->v4l2_dev); -- cgit v1.2.3 From 13a03d748ee008767d82696fe3a61593c19d37bc Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Fri, 3 Apr 2009 15:14:02 +0200 Subject: mt9t031: use platform power hook From: Guennadi Liakhovetski Use platform power hook to turn the camera on and off. Signed-off-by: Guennadi Liakhovetski --- drivers/media/video/mt9t031.c | 21 +++++++++++++++++++++ 1 files changed, 21 insertions(+), 0 deletions(-) --- linux/drivers/media/video/mt9t031.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/mt9t031.c b/linux/drivers/media/video/mt9t031.c index 8a9ca0b27..f4e597e6c 100644 --- a/linux/drivers/media/video/mt9t031.c +++ b/linux/drivers/media/video/mt9t031.c @@ -141,8 +141,19 @@ static int get_shutter(struct soc_camera_device *icd, u32 *data) static int mt9t031_init(struct soc_camera_device *icd) { + struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd); + struct soc_camera_link *icl = mt9t031->client->dev.platform_data; int ret; + if (icl->power) { + ret = icl->power(&mt9t031->client->dev, 1); + if (ret < 0) { + dev_err(icd->vdev->parent, + "Platform failed to power-on the camera.\n"); + return ret; + } + } + /* Disable chip output, synchronous option update */ ret = reg_write(icd, MT9T031_RESET, 1); if (ret >= 0) @@ -150,13 +161,23 @@ static int mt9t031_init(struct soc_camera_device *icd) if (ret >= 0) ret = reg_clear(icd, MT9T031_OUTPUT_CONTROL, 2); + if (ret < 0 && icl->power) + icl->power(&mt9t031->client->dev, 0); + return ret >= 0 ? 0 : -EIO; } static int mt9t031_release(struct soc_camera_device *icd) { + struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd); + struct soc_camera_link *icl = mt9t031->client->dev.platform_data; + /* Disable the chip */ reg_clear(icd, MT9T031_OUTPUT_CONTROL, 2); + + if (icl->power) + icl->power(&mt9t031->client->dev, 0); + return 0; } -- cgit v1.2.3 From 88c3b5d5fa67f017ba19a29c6ef2a28cbc492b90 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Fri, 3 Apr 2009 15:34:02 +0200 Subject: mx3-camera: adapt the clock definition and the driver to the new clock naming From: Guennadi Liakhovetski With the i.MX31 transition to clkdev clock names have changed, but mistakenly the "mx3-camera.0" has been registered with a non-NULL connection ID, which is not necessary, since this is the only clock, used by the capture interface driver. Fix the clock definition and the driver to use NULL as a connection ID. Signed-off-by: Guennadi Liakhovetski Acked-by: Sascha Hauer --- arch/arm/mach-mx3/clock.c | 2 +- drivers/media/video/mx3_camera.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) --- linux/drivers/media/video/mx3_camera.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/mx3_camera.c b/linux/drivers/media/video/mx3_camera.c index 70629e172..c462b811e 100644 --- a/linux/drivers/media/video/mx3_camera.c +++ b/linux/drivers/media/video/mx3_camera.c @@ -1100,7 +1100,7 @@ static int mx3_camera_probe(struct platform_device *pdev) } memset(mx3_cam, 0, sizeof(*mx3_cam)); - mx3_cam->clk = clk_get(&pdev->dev, "csi_clk"); + mx3_cam->clk = clk_get(&pdev->dev, NULL); if (IS_ERR(mx3_cam->clk)) { err = PTR_ERR(mx3_cam->clk); goto eclkget; -- cgit v1.2.3 From 71bde24b27b74e98e8c4a4b253994b5e05ca42bf Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Fri, 3 Apr 2009 15:34:05 +0200 Subject: Add camera (CSI) driver for MX1 From: Paulius Zaleckas Add support for CMOS Sensor Interface on i.MX1 and i.MXL SoCs. Signed-off-by: Paulius Zaleckas Signed-off-by: Darius Augulis Acked-by: Sascha Hauer Signed-off-by: Guennadi Liakhovetski --- arch/arm/mach-mx1/Makefile | 5 +- arch/arm/mach-mx1/devices.c | 2 +- arch/arm/mach-mx1/ksym_mx1.c | 18 + arch/arm/mach-mx1/mx1_camera_fiq.S | 35 ++ arch/arm/plat-mxc/include/mach/memory.h | 8 + arch/arm/plat-mxc/include/mach/mx1_camera.h | 35 ++ drivers/media/video/Kconfig | 13 +- drivers/media/video/Makefile | 1 + drivers/media/video/mx1_camera.c | 827 +++++++++++++++++++++++++++ 9 files changed, 941 insertions(+), 3 deletions(-) create mode 100644 arch/arm/mach-mx1/ksym_mx1.c create mode 100644 arch/arm/mach-mx1/mx1_camera_fiq.S create mode 100644 arch/arm/plat-mxc/include/mach/mx1_camera.h create mode 100644 drivers/media/video/mx1_camera.c --- linux/drivers/media/video/Kconfig | 13 +- linux/drivers/media/video/Makefile | 1 + linux/drivers/media/video/mx1_camera.c | 827 +++++++++++++++++++++++++++++++++ 3 files changed, 840 insertions(+), 1 deletion(-) create mode 100644 linux/drivers/media/video/mx1_camera.c (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/Kconfig b/linux/drivers/media/video/Kconfig index 58abbe374..9d48da2fb 100644 --- a/linux/drivers/media/video/Kconfig +++ b/linux/drivers/media/video/Kconfig @@ -746,6 +746,18 @@ config SOC_CAMERA_OV772X help This is a ov772x camera driver +config MX1_VIDEO + bool + +config VIDEO_MX1 + tristate "i.MX1/i.MXL CMOS Sensor Interface driver" + depends on VIDEO_DEV && ARCH_MX1 && SOC_CAMERA + select FIQ + select VIDEOBUF_DMA_CONTIG + select MX1_VIDEO + ---help--- + This is a v4l2 driver for the i.MX1/i.MXL CMOS Sensor Interface + config VIDEO_MX3 tristate "i.MX3x Camera Sensor Interface driver" depends on VIDEO_DEV && MX3_IPU && SOC_CAMERA @@ -906,5 +918,4 @@ config USB_S2255 This driver can be compiled as a module, called s2255drv. endif # V4L_USB_DRIVERS - endif # VIDEO_CAPTURE_DRIVERS diff --git a/linux/drivers/media/video/Makefile b/linux/drivers/media/video/Makefile index 08765d874..7c0bd6e78 100644 --- a/linux/drivers/media/video/Makefile +++ b/linux/drivers/media/video/Makefile @@ -134,6 +134,7 @@ obj-$(CONFIG_VIDEO_CX18) += cx18/ obj-$(CONFIG_VIDEO_VIVI) += vivi.o obj-$(CONFIG_VIDEO_CX23885) += cx23885/ +obj-$(CONFIG_VIDEO_MX1) += mx1_camera.o obj-$(CONFIG_VIDEO_MX3) += mx3_camera.o obj-$(CONFIG_VIDEO_PXA27x) += pxa_camera.o obj-$(CONFIG_VIDEO_SH_MOBILE_CEU) += sh_mobile_ceu_camera.o diff --git a/linux/drivers/media/video/mx1_camera.c b/linux/drivers/media/video/mx1_camera.c new file mode 100644 index 000000000..86fab56c5 --- /dev/null +++ b/linux/drivers/media/video/mx1_camera.c @@ -0,0 +1,827 @@ +/* + * V4L2 Driver for i.MXL/i.MXL camera (CSI) host + * + * Copyright (C) 2008, Paulius Zaleckas + * Copyright (C) 2009, Darius Augulis + * + * Based on PXA SoC camera driver + * Copyright (C) 2006, Sascha Hauer, Pengutronix + * Copyright (C) 2008, Guennadi Liakhovetski + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +/* + * CSI registers + */ +#define DMA_CCR(x) (0x8c + ((x) << 6)) /* Control Registers */ +#define DMA_DIMR 0x08 /* Interrupt mask Register */ +#define CSICR1 0x00 /* CSI Control Register 1 */ +#define CSISR 0x08 /* CSI Status Register */ +#define CSIRXR 0x10 /* CSI RxFIFO Register */ + +#define CSICR1_RXFF_LEVEL(x) (((x) & 0x3) << 19) +#define CSICR1_SOF_POL (1 << 17) +#define CSICR1_SOF_INTEN (1 << 16) +#define CSICR1_MCLKDIV(x) (((x) & 0xf) << 12) +#define CSICR1_MCLKEN (1 << 9) +#define CSICR1_FCC (1 << 8) +#define CSICR1_BIG_ENDIAN (1 << 7) +#define CSICR1_CLR_RXFIFO (1 << 5) +#define CSICR1_GCLK_MODE (1 << 4) +#define CSICR1_DATA_POL (1 << 2) +#define CSICR1_REDGE (1 << 1) +#define CSICR1_EN (1 << 0) + +#define CSISR_SFF_OR_INT (1 << 25) +#define CSISR_RFF_OR_INT (1 << 24) +#define CSISR_STATFF_INT (1 << 21) +#define CSISR_RXFF_INT (1 << 18) +#define CSISR_SOF_INT (1 << 16) +#define CSISR_DRDY (1 << 0) + +#define VERSION_CODE KERNEL_VERSION(0, 0, 1) +#define DRIVER_NAME "mx1-camera" + +#define CSI_IRQ_MASK (CSISR_SFF_OR_INT | CSISR_RFF_OR_INT | \ + CSISR_STATFF_INT | CSISR_RXFF_INT | CSISR_SOF_INT) + +#define CSI_BUS_FLAGS (SOCAM_MASTER | SOCAM_HSYNC_ACTIVE_HIGH | \ + SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_VSYNC_ACTIVE_LOW | \ + SOCAM_PCLK_SAMPLE_RISING | SOCAM_PCLK_SAMPLE_FALLING | \ + SOCAM_DATA_ACTIVE_HIGH | SOCAM_DATA_ACTIVE_LOW | \ + SOCAM_DATAWIDTH_8) + +#define MAX_VIDEO_MEM 16 /* Video memory limit in megabytes */ + +/* + * Structures + */ + +/* buffer for one video frame */ +struct mx1_buffer { + /* common v4l buffer stuff -- must be first */ + struct videobuf_buffer vb; + const struct soc_camera_data_format *fmt; + int inwork; +}; + +/* i.MX1/i.MXL is only supposed to handle one camera on its Camera Sensor + * Interface. If anyone ever builds hardware to enable more than + * one camera, they will have to modify this driver too */ +struct mx1_camera_dev { + struct soc_camera_device *icd; + struct mx1_camera_pdata *pdata; + struct mx1_buffer *active; + struct device *dev; + struct resource *res; + struct clk *clk; + struct list_head capture; + + void __iomem *base; + int dma_chan; + unsigned int irq; + unsigned long mclk; + + spinlock_t lock; +}; + +/* + * Videobuf operations + */ +static int mx1_videobuf_setup(struct videobuf_queue *vq, unsigned int *count, + unsigned int *size) +{ + struct soc_camera_device *icd = vq->priv_data; + + *size = icd->width * icd->height * + ((icd->current_fmt->depth + 7) >> 3); + + if (!*count) + *count = 32; + + while (*size * *count > MAX_VIDEO_MEM * 1024 * 1024) + (*count)--; + + dev_dbg(&icd->dev, "count=%d, size=%d\n", *count, *size); + + return 0; +} + +static void free_buffer(struct videobuf_queue *vq, struct mx1_buffer *buf) +{ + struct soc_camera_device *icd = vq->priv_data; + struct videobuf_buffer *vb = &buf->vb; + + BUG_ON(in_interrupt()); + + dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__, + vb, vb->baddr, vb->bsize); + + /* This waits until this buffer is out of danger, i.e., until it is no + * longer in STATE_QUEUED or STATE_ACTIVE */ + videobuf_waiton(vb, 0, 0); + videobuf_dma_contig_free(vq, vb); + + vb->state = VIDEOBUF_NEEDS_INIT; +} + +static int mx1_videobuf_prepare(struct videobuf_queue *vq, + struct videobuf_buffer *vb, enum v4l2_field field) +{ + struct soc_camera_device *icd = vq->priv_data; + struct mx1_buffer *buf = container_of(vb, struct mx1_buffer, vb); + int ret; + + dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__, + vb, vb->baddr, vb->bsize); + + /* Added list head initialization on alloc */ + WARN_ON(!list_empty(&vb->queue)); + + BUG_ON(NULL == icd->current_fmt); + + /* I think, in buf_prepare you only have to protect global data, + * the actual buffer is yours */ + buf->inwork = 1; + + if (buf->fmt != icd->current_fmt || + vb->width != icd->width || + vb->height != icd->height || + vb->field != field) { + buf->fmt = icd->current_fmt; + vb->width = icd->width; + vb->height = icd->height; + vb->field = field; + vb->state = VIDEOBUF_NEEDS_INIT; + } + + vb->size = vb->width * vb->height * ((buf->fmt->depth + 7) >> 3); + if (0 != vb->baddr && vb->bsize < vb->size) { + ret = -EINVAL; + goto out; + } + + if (vb->state == VIDEOBUF_NEEDS_INIT) { + ret = videobuf_iolock(vq, vb, NULL); + if (ret) + goto fail; + + vb->state = VIDEOBUF_PREPARED; + } + + buf->inwork = 0; + + return 0; + +fail: + free_buffer(vq, buf); +out: + buf->inwork = 0; + return ret; +} + +static int mx1_camera_setup_dma(struct mx1_camera_dev *pcdev) +{ + struct videobuf_buffer *vbuf = &pcdev->active->vb; + int ret; + + if (unlikely(!pcdev->active)) { + dev_err(pcdev->dev, "DMA End IRQ with no active buffer\n"); + return -EFAULT; + } + + /* setup sg list for future DMA */ + ret = imx_dma_setup_single(pcdev->dma_chan, + videobuf_to_dma_contig(vbuf), + vbuf->size, pcdev->res->start + + CSIRXR, DMA_MODE_READ); + if (unlikely(ret)) + dev_err(pcdev->dev, "Failed to setup DMA sg list\n"); + + return ret; +} + +static void mx1_videobuf_queue(struct videobuf_queue *vq, + struct videobuf_buffer *vb) +{ + struct soc_camera_device *icd = vq->priv_data; + struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); + struct mx1_camera_dev *pcdev = ici->priv; + struct mx1_buffer *buf = container_of(vb, struct mx1_buffer, vb); + unsigned long flags; + + dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__, + vb, vb->baddr, vb->bsize); + + spin_lock_irqsave(&pcdev->lock, flags); + + list_add_tail(&vb->queue, &pcdev->capture); + + vb->state = VIDEOBUF_ACTIVE; + + if (!pcdev->active) { + pcdev->active = buf; + + /* setup sg list for future DMA */ + if (!mx1_camera_setup_dma(pcdev)) { + unsigned int temp; + /* enable SOF irq */ + temp = __raw_readl(pcdev->base + CSICR1) | + CSICR1_SOF_INTEN; + __raw_writel(temp, pcdev->base + CSICR1); + } + } + + spin_unlock_irqrestore(&pcdev->lock, flags); +} + +static void mx1_videobuf_release(struct videobuf_queue *vq, + struct videobuf_buffer *vb) +{ + struct mx1_buffer *buf = container_of(vb, struct mx1_buffer, vb); +#ifdef DEBUG + struct soc_camera_device *icd = vq->priv_data; + + dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__, + vb, vb->baddr, vb->bsize); + + switch (vb->state) { + case VIDEOBUF_ACTIVE: + dev_dbg(&icd->dev, "%s (active)\n", __func__); + break; + case VIDEOBUF_QUEUED: + dev_dbg(&icd->dev, "%s (queued)\n", __func__); + break; + case VIDEOBUF_PREPARED: + dev_dbg(&icd->dev, "%s (prepared)\n", __func__); + break; + default: + dev_dbg(&icd->dev, "%s (unknown)\n", __func__); + break; + } +#endif + + free_buffer(vq, buf); +} + +static void mx1_camera_wakeup(struct mx1_camera_dev *pcdev, + struct videobuf_buffer *vb, + struct mx1_buffer *buf) +{ + /* _init is used to debug races, see comment in mx1_camera_reqbufs() */ + list_del_init(&vb->queue); + vb->state = VIDEOBUF_DONE; + do_gettimeofday(&vb->ts); + vb->field_count++; + wake_up(&vb->done); + + if (list_empty(&pcdev->capture)) { + pcdev->active = NULL; + return; + } + + pcdev->active = list_entry(pcdev->capture.next, + struct mx1_buffer, vb.queue); + + /* setup sg list for future DMA */ + if (likely(!mx1_camera_setup_dma(pcdev))) { + unsigned int temp; + + /* enable SOF irq */ + temp = __raw_readl(pcdev->base + CSICR1) | CSICR1_SOF_INTEN; + __raw_writel(temp, pcdev->base + CSICR1); + } +} + +static void mx1_camera_dma_irq(int channel, void *data) +{ + struct mx1_camera_dev *pcdev = data; + struct mx1_buffer *buf; + struct videobuf_buffer *vb; + unsigned long flags; + + spin_lock_irqsave(&pcdev->lock, flags); + + imx_dma_disable(channel); + + if (unlikely(!pcdev->active)) { + dev_err(pcdev->dev, "DMA End IRQ with no active buffer\n"); + goto out; + } + + vb = &pcdev->active->vb; + buf = container_of(vb, struct mx1_buffer, vb); + WARN_ON(buf->inwork || list_empty(&vb->queue)); + dev_dbg(pcdev->dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__, + vb, vb->baddr, vb->bsize); + + mx1_camera_wakeup(pcdev, vb, buf); +out: + spin_unlock_irqrestore(&pcdev->lock, flags); +} + +static struct videobuf_queue_ops mx1_videobuf_ops = { + .buf_setup = mx1_videobuf_setup, + .buf_prepare = mx1_videobuf_prepare, + .buf_queue = mx1_videobuf_queue, + .buf_release = mx1_videobuf_release, +}; + +static void mx1_camera_init_videobuf(struct videobuf_queue *q, + struct soc_camera_device *icd) +{ + struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); + struct mx1_camera_dev *pcdev = ici->priv; + + videobuf_queue_dma_contig_init(q, &mx1_videobuf_ops, pcdev->dev, + &pcdev->lock, + V4L2_BUF_TYPE_VIDEO_CAPTURE, + V4L2_FIELD_NONE, + sizeof(struct mx1_buffer), icd); +} + +static int mclk_get_divisor(struct mx1_camera_dev *pcdev) +{ + unsigned int mclk = pcdev->mclk; + unsigned long div; + unsigned long lcdclk; + + lcdclk = clk_get_rate(pcdev->clk); + + /* We verify platform_mclk_10khz != 0, so if anyone breaks it, here + * they get a nice Oops */ + div = (lcdclk + 2 * mclk - 1) / (2 * mclk) - 1; + + dev_dbg(pcdev->dev, "System clock %lukHz, target freq %dkHz, " + "divisor %lu\n", lcdclk / 1000, mclk / 1000, div); + + return div; +} + +static void mx1_camera_activate(struct mx1_camera_dev *pcdev) +{ + unsigned int csicr1 = CSICR1_EN; + + dev_dbg(pcdev->dev, "Activate device\n"); + + clk_enable(pcdev->clk); + + /* enable CSI before doing anything else */ + __raw_writel(csicr1, pcdev->base + CSICR1); + + csicr1 |= CSICR1_MCLKEN | CSICR1_FCC | CSICR1_GCLK_MODE; + csicr1 |= CSICR1_MCLKDIV(mclk_get_divisor(pcdev)); + csicr1 |= CSICR1_RXFF_LEVEL(2); /* 16 words */ + + __raw_writel(csicr1, pcdev->base + CSICR1); +} + +static void mx1_camera_deactivate(struct mx1_camera_dev *pcdev) +{ + dev_dbg(pcdev->dev, "Deactivate device\n"); + + /* Disable all CSI interface */ + __raw_writel(0x00, pcdev->base + CSICR1); + + clk_disable(pcdev->clk); +} + +/* The following two functions absolutely depend on the fact, that + * there can be only one camera on i.MX1/i.MXL camera sensor interface */ +static int mx1_camera_add_device(struct soc_camera_device *icd) +{ + struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); + struct mx1_camera_dev *pcdev = ici->priv; + int ret; + + if (pcdev->icd) { + ret = -EBUSY; + goto ebusy; + } + + dev_info(&icd->dev, "MX1 Camera driver attached to camera %d\n", + icd->devnum); + + mx1_camera_activate(pcdev); + ret = icd->ops->init(icd); + + if (!ret) + pcdev->icd = icd; + +ebusy: + return ret; +} + +static void mx1_camera_remove_device(struct soc_camera_device *icd) +{ + struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); + struct mx1_camera_dev *pcdev = ici->priv; + unsigned int csicr1; + + BUG_ON(icd != pcdev->icd); + + /* disable interrupts */ + csicr1 = __raw_readl(pcdev->base + CSICR1) & ~CSI_IRQ_MASK; + __raw_writel(csicr1, pcdev->base + CSICR1); + + /* Stop DMA engine */ + imx_dma_disable(pcdev->dma_chan); + + dev_info(&icd->dev, "MX1 Camera driver detached from camera %d\n", + icd->devnum); + + icd->ops->release(icd); + + mx1_camera_deactivate(pcdev); + + pcdev->icd = NULL; +} + +static int mx1_camera_set_crop(struct soc_camera_device *icd, + struct v4l2_rect *rect) +{ + return icd->ops->set_crop(icd, rect); +} + +static int mx1_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt) +{ + struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); + struct mx1_camera_dev *pcdev = ici->priv; + unsigned long camera_flags, common_flags; + unsigned int csicr1; + int ret; + + camera_flags = icd->ops->query_bus_param(icd); + + /* MX1 supports only 8bit buswidth */ + common_flags = soc_camera_bus_param_compatible(camera_flags, + CSI_BUS_FLAGS); + if (!common_flags) + return -EINVAL; + + icd->buswidth = 8; + + /* Make choises, based on platform choice */ + if ((common_flags & SOCAM_VSYNC_ACTIVE_HIGH) && + (common_flags & SOCAM_VSYNC_ACTIVE_LOW)) { + if (!pcdev->pdata || + pcdev->pdata->flags & MX1_CAMERA_VSYNC_HIGH) + common_flags &= ~SOCAM_VSYNC_ACTIVE_LOW; + else + common_flags &= ~SOCAM_VSYNC_ACTIVE_HIGH; + } + + if ((common_flags & SOCAM_PCLK_SAMPLE_RISING) && + (common_flags & SOCAM_PCLK_SAMPLE_FALLING)) { + if (!pcdev->pdata || + pcdev->pdata->flags & MX1_CAMERA_PCLK_RISING) + common_flags &= ~SOCAM_PCLK_SAMPLE_FALLING; + else + common_flags &= ~SOCAM_PCLK_SAMPLE_RISING; + } + + if ((common_flags & SOCAM_DATA_ACTIVE_HIGH) && + (common_flags & SOCAM_DATA_ACTIVE_LOW)) { + if (!pcdev->pdata || + pcdev->pdata->flags & MX1_CAMERA_DATA_HIGH) + common_flags &= ~SOCAM_DATA_ACTIVE_LOW; + else + common_flags &= ~SOCAM_DATA_ACTIVE_HIGH; + } + + ret = icd->ops->set_bus_param(icd, common_flags); + if (ret < 0) + return ret; + + csicr1 = __raw_readl(pcdev->base + CSICR1); + + if (common_flags & SOCAM_PCLK_SAMPLE_RISING) + csicr1 |= CSICR1_REDGE; + if (common_flags & SOCAM_VSYNC_ACTIVE_HIGH) + csicr1 |= CSICR1_SOF_POL; + if (common_flags & SOCAM_DATA_ACTIVE_LOW) + csicr1 |= CSICR1_DATA_POL; + + __raw_writel(csicr1, pcdev->base + CSICR1); + + return 0; +} + +static int mx1_camera_set_fmt(struct soc_camera_device *icd, + struct v4l2_format *f) +{ + struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); + const struct soc_camera_format_xlate *xlate; + struct v4l2_pix_format *pix = &f->fmt.pix; + int ret; + + xlate = soc_camera_xlate_by_fourcc(icd, pix->pixelformat); + if (!xlate) { + dev_warn(&ici->dev, "Format %x not found\n", pix->pixelformat); + return -EINVAL; + } + + ret = icd->ops->set_fmt(icd, f); + if (!ret) { + icd->buswidth = xlate->buswidth; + icd->current_fmt = xlate->host_fmt; + } + + return ret; +} + +static int mx1_camera_try_fmt(struct soc_camera_device *icd, + struct v4l2_format *f) +{ + /* TODO: limit to mx1 hardware capabilities */ + + /* limit to sensor capabilities */ + return icd->ops->try_fmt(icd, f); +} + +static int mx1_camera_reqbufs(struct soc_camera_file *icf, + struct v4l2_requestbuffers *p) +{ + int i; + + /* This is for locking debugging only. I removed spinlocks and now I + * check whether .prepare is ever called on a linked buffer, or whether + * a dma IRQ can occur for an in-work or unlinked buffer. Until now + * it hadn't triggered */ + for (i = 0; i < p->count; i++) { + struct mx1_buffer *buf = container_of(icf->vb_vidq.bufs[i], + struct mx1_buffer, vb); + buf->inwork = 0; + INIT_LIST_HEAD(&buf->vb.queue); + } + + return 0; +} + +static unsigned int mx1_camera_poll(struct file *file, poll_table *pt) +{ + struct soc_camera_file *icf = file->private_data; + struct mx1_buffer *buf; + + buf = list_entry(icf->vb_vidq.stream.next, struct mx1_buffer, + vb.stream); + + poll_wait(file, &buf->vb.done, pt); + + if (buf->vb.state == VIDEOBUF_DONE || + buf->vb.state == VIDEOBUF_ERROR) + return POLLIN | POLLRDNORM; + + return 0; +} + +static int mx1_camera_querycap(struct soc_camera_host *ici, + struct v4l2_capability *cap) +{ + /* cap->name is set by the friendly caller:-> */ + strlcpy(cap->card, "i.MX1/i.MXL Camera", sizeof(cap->card)); + cap->version = VERSION_CODE; + cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING; + + return 0; +} + +static struct soc_camera_host_ops mx1_soc_camera_host_ops = { + .owner = THIS_MODULE, + .add = mx1_camera_add_device, + .remove = mx1_camera_remove_device, + .set_bus_param = mx1_camera_set_bus_param, + .set_crop = mx1_camera_set_crop, + .set_fmt = mx1_camera_set_fmt, + .try_fmt = mx1_camera_try_fmt, + .init_videobuf = mx1_camera_init_videobuf, + .reqbufs = mx1_camera_reqbufs, + .poll = mx1_camera_poll, + .querycap = mx1_camera_querycap, +}; + +/* Should be allocated dynamically too, but we have only one. */ +static struct soc_camera_host mx1_soc_camera_host = { + .drv_name = DRIVER_NAME, + .ops = &mx1_soc_camera_host_ops, +}; + +static struct fiq_handler fh = { + .name = "csi_sof" +}; + +static int __init mx1_camera_probe(struct platform_device *pdev) +{ + struct mx1_camera_dev *pcdev; + struct resource *res; + struct pt_regs regs; + struct clk *clk; + void __iomem *base; + unsigned int irq; + int err = 0; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + irq = platform_get_irq(pdev, 0); + if (!res || !irq) { + err = -ENODEV; + goto exit; + } + + clk = clk_get(&pdev->dev, "csi_clk"); + if (IS_ERR(clk)) { + err = PTR_ERR(clk); + goto exit; + } + + pcdev = kzalloc(sizeof(*pcdev), GFP_KERNEL); + if (!pcdev) { + dev_err(&pdev->dev, "Could not allocate pcdev\n"); + err = -ENOMEM; + goto exit_put_clk; + } + + dev_set_drvdata(&pdev->dev, pcdev); + pcdev->res = res; + pcdev->clk = clk; + + pcdev->pdata = pdev->dev.platform_data; + + if (pcdev->pdata) + pcdev->mclk = pcdev->pdata->mclk_10khz * 10000; + + if (!pcdev->mclk) { + dev_warn(&pdev->dev, + "mclk_10khz == 0! Please, fix your platform data. " + "Using default 20MHz\n"); + pcdev->mclk = 20000000; + } + + INIT_LIST_HEAD(&pcdev->capture); + spin_lock_init(&pcdev->lock); + + /* + * Request the regions. + */ + if (!request_mem_region(res->start, resource_size(res), DRIVER_NAME)) { + err = -EBUSY; + goto exit_kfree; + } + + base = ioremap(res->start, resource_size(res)); + if (!base) { + err = -ENOMEM; + goto exit_release; + } + pcdev->irq = irq; + pcdev->base = base; + pcdev->dev = &pdev->dev; + + /* request dma */ + pcdev->dma_chan = imx_dma_request_by_prio(DRIVER_NAME, DMA_PRIO_HIGH); + if (pcdev->dma_chan < 0) { + dev_err(pcdev->dev, "Can't request DMA for MX1 CSI\n"); + err = -EBUSY; + goto exit_iounmap; + } + dev_dbg(pcdev->dev, "got DMA channel %d\n", pcdev->dma_chan); + + imx_dma_setup_handlers(pcdev->dma_chan, mx1_camera_dma_irq, NULL, + pcdev); + + imx_dma_config_channel(pcdev->dma_chan, IMX_DMA_TYPE_FIFO, + IMX_DMA_MEMSIZE_32, DMA_REQ_CSI_R, 0); + /* burst length : 16 words = 64 bytes */ + imx_dma_config_burstlen(pcdev->dma_chan, 0); + + /* request irq */ + err = claim_fiq(&fh); + if (err) { + dev_err(pcdev->dev, "Camera interrupt register failed \n"); + goto exit_free_dma; + } + + set_fiq_handler(&mx1_camera_sof_fiq_start, &mx1_camera_sof_fiq_end - + &mx1_camera_sof_fiq_start); + + regs.ARM_r8 = DMA_BASE + DMA_DIMR; + regs.ARM_r9 = DMA_BASE + DMA_CCR(pcdev->dma_chan); + regs.ARM_r10 = (long)pcdev->base + CSICR1; + regs.ARM_fp = (long)pcdev->base + CSISR; + regs.ARM_sp = 1 << pcdev->dma_chan; + set_fiq_regs(®s); + + mxc_set_irq_fiq(irq, 1); + enable_fiq(irq); + + mx1_soc_camera_host.priv = pcdev; + mx1_soc_camera_host.dev.parent = &pdev->dev; + mx1_soc_camera_host.nr = pdev->id; + err = soc_camera_host_register(&mx1_soc_camera_host); + if (err) + goto exit_free_irq; + + dev_info(&pdev->dev, "MX1 Camera driver loaded\n"); + + return 0; + +exit_free_irq: + disable_fiq(irq); + mxc_set_irq_fiq(irq, 0); + release_fiq(&fh); +exit_free_dma: + imx_dma_free(pcdev->dma_chan); +exit_iounmap: + iounmap(base); +exit_release: + release_mem_region(res->start, resource_size(res)); +exit_kfree: + kfree(pcdev); +exit_put_clk: + clk_put(clk); +exit: + return err; +} + +static int __exit mx1_camera_remove(struct platform_device *pdev) +{ + struct mx1_camera_dev *pcdev = platform_get_drvdata(pdev); + struct resource *res; + + imx_dma_free(pcdev->dma_chan); + disable_fiq(pcdev->irq); + mxc_set_irq_fiq(pcdev->irq, 0); + release_fiq(&fh); + + clk_put(pcdev->clk); + + soc_camera_host_unregister(&mx1_soc_camera_host); + + iounmap(pcdev->base); + + res = pcdev->res; + release_mem_region(res->start, resource_size(res)); + + kfree(pcdev); + + dev_info(&pdev->dev, "MX1 Camera driver unloaded\n"); + + return 0; +} + +static struct platform_driver mx1_camera_driver = { + .driver = { + .name = DRIVER_NAME, + }, + .remove = __exit_p(mx1_camera_remove), +}; + +static int __init mx1_camera_init(void) +{ + return platform_driver_probe(&mx1_camera_driver, mx1_camera_probe); +} + +static void __exit mx1_camera_exit(void) +{ + return platform_driver_unregister(&mx1_camera_driver); +} + +module_init(mx1_camera_init); +module_exit(mx1_camera_exit); + +MODULE_DESCRIPTION("i.MX1/i.MXL SoC Camera Host driver"); +MODULE_AUTHOR("Paulius Zaleckas "); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:" DRIVER_NAME); -- cgit v1.2.3 From 4ebd0d44965effc239d92927a43fcfc37e786d87 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 5 Apr 2009 08:02:15 -0300 Subject: em28xx: use usb_interface.dev for v4l2_device_register From: Mauro Carvalho Chehab Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/em28xx/em28xx-cards.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (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 56c27b745..55b5cd724 100644 --- a/linux/drivers/media/video/em28xx/em28xx-cards.c +++ b/linux/drivers/media/video/em28xx/em28xx-cards.c @@ -2142,6 +2142,7 @@ void em28xx_release_resources(struct em28xx *dev) * allocates and inits the device structs, registers i2c bus and v4l device */ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, + struct usb_interface *interface, int minor) { struct em28xx *dev = *devhandle; @@ -2175,7 +2176,7 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, } } - retval = v4l2_device_register(&dev->udev->dev, &dev->v4l2_dev); + retval = v4l2_device_register(&interface->dev, &dev->v4l2_dev); if (retval < 0) { em28xx_errdev("Call to v4l2_device_register() failed!\n"); return retval; @@ -2416,7 +2417,7 @@ static int em28xx_usb_probe(struct usb_interface *interface, /* allocate device struct */ mutex_init(&dev->lock); mutex_lock(&dev->lock); - retval = em28xx_init_dev(&dev, udev, nr); + retval = em28xx_init_dev(&dev, udev, interface, nr); if (retval) { em28xx_devused &= ~(1<devno); kfree(dev); -- cgit v1.2.3 From 43dca0776fdb9e71778253c95a60177a2ab6a52e Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 29 Mar 2009 19:36:02 +0000 Subject: saa7134: Add analog RF tuner support for Avermedia A700 DVB-S Hybrid+FM card From: Matthias Schwarzott Thanks to panagonov for requesting support and testing patches. Signed-off-by: Matthias Schwarzott Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/saa7134/saa7134-cards.c | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/saa7134/saa7134-cards.c b/linux/drivers/media/video/saa7134/saa7134-cards.c index 39015dfe0..af2da365b 100644 --- a/linux/drivers/media/video/saa7134/saa7134-cards.c +++ b/linux/drivers/media/video/saa7134/saa7134-cards.c @@ -4547,12 +4547,17 @@ struct saa7134_board saa7134_boards[] = { /* Matthias Schwarzott */ .name = "Avermedia DVB-S Hybrid+FM A700", .audio_clock = 0x00187de7, - .tuner_type = TUNER_ABSENT, /* TUNER_XC2028 */ + .tuner_type = TUNER_XC2028, .radio_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .mpeg = SAA7134_MPEG_DVB, .inputs = { { + .name = name_tv, + .vmux = 4, + .amux = TV, + .tv = 1, + }, { .name = name_comp, .vmux = 1, .amux = LINE1, @@ -4561,6 +4566,10 @@ struct saa7134_board saa7134_boards[] = { .vmux = 6, .amux = LINE1, } }, + .radio = { + .name = name_radio, + .amux = TV, + }, }, [SAA7134_BOARD_BEHOLD_H6] = { /* Igor Kuznetsov */ @@ -5990,6 +5999,11 @@ static int saa7134_xc2028_callback(struct saa7134_dev *dev, msleep(10); saa7134_set_gpio(dev, 21, 1); break; + case SAA7134_BOARD_AVERMEDIA_A700_HYBRID: + saa7134_set_gpio(dev, 18, 0); + msleep(10); + saa7134_set_gpio(dev, 18, 1); + break; } return 0; } @@ -6362,10 +6376,6 @@ int saa7134_board_init1(struct saa7134_dev *dev) saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x0c0007cd, 0x0c0007cd); break; case SAA7134_BOARD_AVERMEDIA_A700_HYBRID: - printk("%s: %s: hybrid analog/dvb card\n" - "%s: Sorry, of the analog inputs, only analog s-video and composite " - "are supported for now.\n", - dev->name, card(dev).name, dev->name); case SAA7134_BOARD_AVERMEDIA_A700_PRO: /* write windows gpio values */ saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, 0x80040100, 0x80040100); @@ -6429,6 +6439,7 @@ static void saa7134_tuner_setup(struct saa7134_dev *dev) case SAA7134_BOARD_AVERMEDIA_A16D: case SAA7134_BOARD_AVERMEDIA_CARDBUS_506: case SAA7134_BOARD_AVERMEDIA_M103: + case SAA7134_BOARD_AVERMEDIA_A700_HYBRID: ctl.demod = XC3028_FE_ZARLINK456; break; default: -- cgit v1.2.3 From 90fe2a4ea4edbd255bdf8074fbb402d454682e94 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sun, 29 Mar 2009 22:47:30 +0200 Subject: cx88: prevent probing rtc and ir devices From: Hans Verkuil tuner-core.c contains a hack for cx88 board to prevent probing of certain addresses: /* HACK: Ignore 0x6b and 0x6f on cx88 boards. * FusionHDTV5 RT Gold has an ir receiver at 0x6b * and an RTC at 0x6f which can get corrupted if probed. */ With the new i2c API this hack no longer works. So instead change the list of tuner probe addresses in the cx88 driver itself, which is much more clean. Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/cx88/cx88-cards.c | 14 ++++++++++---- 1 file changed, 10 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 df9e99a3b..a170dedbf 100644 --- a/linux/drivers/media/video/cx88/cx88-cards.c +++ b/linux/drivers/media/video/cx88/cx88-cards.c @@ -3238,6 +3238,15 @@ struct cx88_core *cx88_core_create(struct pci_dev *pci, int nr) /* load tuner module, if needed */ if (TUNER_ABSENT != core->board.tuner_type) { + /* Ignore 0x6b and 0x6f on cx88 boards. + * FusionHDTV5 RT Gold has an ir receiver at 0x6b + * and an RTC at 0x6f which can get corrupted if probed. */ + static const unsigned short tv_addrs[] = { + 0x42, 0x43, 0x4a, 0x4b, /* tda8290 */ + 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, + 0x68, 0x69, 0x6a, 0x6c, 0x6d, 0x6e, + I2C_CLIENT_END + }; int has_demod = (core->board.tda9887_conf & TDA9887_PRESENT); /* I don't trust the radio_type as is stored in the card @@ -3251,11 +3260,8 @@ struct cx88_core *cx88_core_create(struct pci_dev *pci, int nr) v4l2_i2c_new_probed_subdev(&core->i2c_adap, "tuner", "tuner", v4l2_i2c_tuner_addrs(ADDRS_DEMOD)); if (core->board.tuner_addr == ADDR_UNSET) { - enum v4l2_i2c_tuner_type type = - has_demod ? ADDRS_TV_WITH_DEMOD : ADDRS_TV; - v4l2_i2c_new_probed_subdev(&core->i2c_adap, "tuner", - "tuner", v4l2_i2c_tuner_addrs(type)); + "tuner", has_demod ? tv_addrs + 4 : tv_addrs); } else { v4l2_i2c_new_subdev(&core->i2c_adap, "tuner", "tuner", core->board.tuner_addr); -- cgit v1.2.3 From 623a87e654939d74358a2b8256042acbca1bce7c Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 29 Mar 2009 22:17:10 +0000 Subject: Sensor orientation reporting From: Adam Baker Add support to the SQ-905 driver to pass back to user space the sensor orientation information obtained from the camera during init. Modifies gspca and the videodev2.h header to create the necessary API. Signed-off-by: Adam Baker [mchehab@redhat.com: Changed "Output is" to "Frames are" at the comments, as suggested at LMML] Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/gspca/gspca.c | 1 + linux/drivers/media/video/gspca/gspca.h | 1 + linux/drivers/media/video/gspca/sq905.c | 6 ++++++ 3 files changed, 8 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/gspca.c b/linux/drivers/media/video/gspca/gspca.c index 93c35d083..cfd27161b 100644 --- a/linux/drivers/media/video/gspca/gspca.c +++ b/linux/drivers/media/video/gspca/gspca.c @@ -1144,6 +1144,7 @@ static int vidioc_enum_input(struct file *file, void *priv, if (input->index != 0) return -EINVAL; input->type = V4L2_INPUT_TYPE_CAMERA; + input->status = gspca_dev->cam.input_flags; strncpy(input->name, gspca_dev->sd_desc->name, sizeof input->name); return 0; diff --git a/linux/drivers/media/video/gspca/gspca.h b/linux/drivers/media/video/gspca/gspca.h index e4d4cf6ce..58e8ff021 100644 --- a/linux/drivers/media/video/gspca/gspca.h +++ b/linux/drivers/media/video/gspca/gspca.h @@ -56,6 +56,7 @@ struct cam { * - cannot be > MAX_NURBS * - when 0 and bulk_size != 0 means * 1 URB and submit done by subdriver */ + u32 input_flags; /* value for ENUM_INPUT status flags */ }; struct gspca_dev; diff --git a/linux/drivers/media/video/gspca/sq905.c b/linux/drivers/media/video/gspca/sq905.c index 04e3ae57a..2e1cdf068 100644 --- a/linux/drivers/media/video/gspca/sq905.c +++ b/linux/drivers/media/video/gspca/sq905.c @@ -360,6 +360,12 @@ static int sd_init(struct gspca_dev *gspca_dev) gspca_dev->cam.nmodes = ARRAY_SIZE(sq905_mode); if (!(ident & SQ905_HIRES_MASK)) gspca_dev->cam.nmodes--; + + if (ident & SQ905_ORIENTATION_MASK) + gspca_dev->cam.input_flags = V4L2_IN_ST_VFLIP; + else + gspca_dev->cam.input_flags = V4L2_IN_ST_VFLIP | + V4L2_IN_ST_HFLIP; return 0; } -- cgit v1.2.3 From 7dca8ee1c6f6848fb5a1acedf2972e004c20d0d2 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 30 Mar 2009 11:26:40 +0200 Subject: cx25840: cleanup: remove intermediate 'ioctl' step From: Hans Verkuil The audio and vbi functions where still called through an ioctl-like interface, even though this is no longer needed with v4l2-subdev. Just change each 'case' into a proper function and call that directly. Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/cx25840/cx25840-audio.c | 121 +++++---- linux/drivers/media/video/cx25840/cx25840-core.c | 24 +- linux/drivers/media/video/cx25840/cx25840-core.h | 8 +- linux/drivers/media/video/cx25840/cx25840-vbi.c | 314 ++++++++++------------ 4 files changed, 219 insertions(+), 248 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/cx25840/cx25840-audio.c b/linux/drivers/media/video/cx25840/cx25840-audio.c index 9dcdef03e..f0a91f981 100644 --- a/linux/drivers/media/video/cx25840/cx25840-audio.c +++ b/linux/drivers/media/video/cx25840/cx25840-audio.c @@ -378,75 +378,74 @@ static void set_mute(struct i2c_client *client, int mute) } } -int cx25840_audio(struct i2c_client *client, unsigned int cmd, void *arg) +int cx25840_s_clock_freq(struct v4l2_subdev *sd, u32 freq) { - struct cx25840_state *state = to_state(i2c_get_clientdata(client)); - struct v4l2_control *ctrl = arg; + struct i2c_client *client = v4l2_get_subdevdata(sd); + struct cx25840_state *state = to_state(sd); int retval; - switch (cmd) { - case VIDIOC_INT_AUDIO_CLOCK_FREQ: - if (!state->is_cx25836) - cx25840_and_or(client, 0x810, ~0x1, 1); - if (state->aud_input != CX25840_AUDIO_SERIAL) { - cx25840_and_or(client, 0x803, ~0x10, 0); - cx25840_write(client, 0x8d3, 0x1f); - } - retval = set_audclk_freq(client, *(u32 *)arg); - if (state->aud_input != CX25840_AUDIO_SERIAL) { - cx25840_and_or(client, 0x803, ~0x10, 0x10); - } - if (!state->is_cx25836) - cx25840_and_or(client, 0x810, ~0x1, 0); - return retval; - - case VIDIOC_G_CTRL: - switch (ctrl->id) { - case V4L2_CID_AUDIO_VOLUME: - ctrl->value = get_volume(client); - break; - case V4L2_CID_AUDIO_BASS: - ctrl->value = get_bass(client); - break; - case V4L2_CID_AUDIO_TREBLE: - ctrl->value = get_treble(client); - break; - case V4L2_CID_AUDIO_BALANCE: - ctrl->value = get_balance(client); - break; - case V4L2_CID_AUDIO_MUTE: - ctrl->value = get_mute(client); - break; - default: - return -EINVAL; - } - break; + if (!state->is_cx25836) + cx25840_and_or(client, 0x810, ~0x1, 1); + if (state->aud_input != CX25840_AUDIO_SERIAL) { + cx25840_and_or(client, 0x803, ~0x10, 0); + cx25840_write(client, 0x8d3, 0x1f); + } + retval = set_audclk_freq(client, freq); + if (state->aud_input != CX25840_AUDIO_SERIAL) + cx25840_and_or(client, 0x803, ~0x10, 0x10); + if (!state->is_cx25836) + cx25840_and_or(client, 0x810, ~0x1, 0); + return retval; +} - case VIDIOC_S_CTRL: - switch (ctrl->id) { - case V4L2_CID_AUDIO_VOLUME: - set_volume(client, ctrl->value); - break; - case V4L2_CID_AUDIO_BASS: - set_bass(client, ctrl->value); - break; - case V4L2_CID_AUDIO_TREBLE: - set_treble(client, ctrl->value); - break; - case V4L2_CID_AUDIO_BALANCE: - set_balance(client, ctrl->value); - break; - case V4L2_CID_AUDIO_MUTE: - set_mute(client, ctrl->value); - break; - default: - return -EINVAL; - } - break; +int cx25840_audio_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + switch (ctrl->id) { + case V4L2_CID_AUDIO_VOLUME: + ctrl->value = get_volume(client); + break; + case V4L2_CID_AUDIO_BASS: + ctrl->value = get_bass(client); + break; + case V4L2_CID_AUDIO_TREBLE: + ctrl->value = get_treble(client); + break; + case V4L2_CID_AUDIO_BALANCE: + ctrl->value = get_balance(client); + break; + case V4L2_CID_AUDIO_MUTE: + ctrl->value = get_mute(client); + break; default: return -EINVAL; } + return 0; +} +int cx25840_audio_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + + switch (ctrl->id) { + case V4L2_CID_AUDIO_VOLUME: + set_volume(client, ctrl->value); + break; + case V4L2_CID_AUDIO_BASS: + set_bass(client, ctrl->value); + break; + case V4L2_CID_AUDIO_TREBLE: + set_treble(client, ctrl->value); + break; + case V4L2_CID_AUDIO_BALANCE: + set_balance(client, ctrl->value); + break; + case V4L2_CID_AUDIO_MUTE: + set_mute(client, ctrl->value); + break; + default: + return -EINVAL; + } return 0; } diff --git a/linux/drivers/media/video/cx25840/cx25840-core.c b/linux/drivers/media/video/cx25840/cx25840-core.c index 6b55cd94b..be270ea5b 100644 --- a/linux/drivers/media/video/cx25840/cx25840-core.c +++ b/linux/drivers/media/video/cx25840/cx25840-core.c @@ -893,7 +893,7 @@ static int cx25840_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) case V4L2_CID_AUDIO_MUTE: if (state->is_cx25836) return -EINVAL; - return cx25840_audio(client, VIDIOC_S_CTRL, ctrl); + return cx25840_audio_s_ctrl(sd, ctrl); default: return -EINVAL; @@ -930,7 +930,7 @@ static int cx25840_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) case V4L2_CID_AUDIO_MUTE: if (state->is_cx25836) return -EINVAL; - return cx25840_audio(client, VIDIOC_G_CTRL, ctrl); + return cx25840_audio_g_ctrl(sd, ctrl); default: return -EINVAL; } @@ -946,7 +946,7 @@ static int cx25840_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) switch (fmt->type) { case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: - return cx25840_vbi(client, VIDIOC_G_FMT, fmt); + return cx25840_vbi_g_fmt(sd, fmt); default: return -EINVAL; } @@ -1008,10 +1008,10 @@ static int cx25840_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) break; case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: - return cx25840_vbi(client, VIDIOC_S_FMT, fmt); + return cx25840_vbi_s_fmt(sd, fmt); case V4L2_BUF_TYPE_VBI_CAPTURE: - return cx25840_vbi(client, VIDIOC_S_FMT, fmt); + return cx25840_vbi_s_fmt(sd, fmt); default: return -EINVAL; @@ -1273,20 +1273,6 @@ static int cx25840_s_register(struct v4l2_subdev *sd, struct v4l2_dbg_register * } #endif -static int cx25840_decode_vbi_line(struct v4l2_subdev *sd, struct v4l2_decode_vbi_line *vbi) -{ - struct i2c_client *client = v4l2_get_subdevdata(sd); - - return cx25840_vbi(client, VIDIOC_INT_DECODE_VBI_LINE, vbi); -} - -static int cx25840_s_clock_freq(struct v4l2_subdev *sd, u32 freq) -{ - struct i2c_client *client = v4l2_get_subdevdata(sd); - - return cx25840_audio(client, VIDIOC_INT_AUDIO_CLOCK_FREQ, &freq); -} - static int cx25840_s_stream(struct v4l2_subdev *sd, int enable) { struct cx25840_state *state = to_state(sd); diff --git a/linux/drivers/media/video/cx25840/cx25840-core.h b/linux/drivers/media/video/cx25840/cx25840-core.h index 422c63752..580c320da 100644 --- a/linux/drivers/media/video/cx25840/cx25840-core.h +++ b/linux/drivers/media/video/cx25840/cx25840-core.h @@ -77,11 +77,15 @@ int cx25840_loadfw(struct i2c_client *client); /* ----------------------------------------------------------------------- */ /* cx25850-audio.c */ -int cx25840_audio(struct i2c_client *client, unsigned int cmd, void *arg); void cx25840_audio_set_path(struct i2c_client *client); +int cx25840_s_clock_freq(struct v4l2_subdev *sd, u32 freq); +int cx25840_audio_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl); +int cx25840_audio_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl); /* ----------------------------------------------------------------------- */ /* cx25850-vbi.c */ -int cx25840_vbi(struct i2c_client *client, unsigned int cmd, void *arg); +int cx25840_vbi_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt); +int cx25840_vbi_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt); +int cx25840_decode_vbi_line(struct v4l2_subdev *sd, struct v4l2_decode_vbi_line *vbi); #endif diff --git a/linux/drivers/media/video/cx25840/cx25840-vbi.c b/linux/drivers/media/video/cx25840/cx25840-vbi.c index 7790afd5b..011987326 100644 --- a/linux/drivers/media/video/cx25840/cx25840-vbi.c +++ b/linux/drivers/media/video/cx25840/cx25840-vbi.c @@ -83,199 +83,181 @@ static int decode_vps(u8 * dst, u8 * p) return err & 0xf0; } -int cx25840_vbi(struct i2c_client *client, unsigned int cmd, void *arg) +int cx25840_vbi_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) { - struct cx25840_state *state = to_state(i2c_get_clientdata(client)); - struct v4l2_format *fmt; + struct i2c_client *client = v4l2_get_subdevdata(sd); + struct cx25840_state *state = to_state(sd); struct v4l2_sliced_vbi_format *svbi; + static const u16 lcr2vbi[] = { + 0, V4L2_SLICED_TELETEXT_B, 0, /* 1 */ + 0, V4L2_SLICED_WSS_625, 0, /* 4 */ + V4L2_SLICED_CAPTION_525, /* 6 */ + 0, 0, V4L2_SLICED_VPS, 0, 0, /* 9 */ + 0, 0, 0, 0 + }; + int is_pal = !(state->std & V4L2_STD_525_60); + int i; - switch (cmd) { - case VIDIOC_G_FMT: - { - static u16 lcr2vbi[] = { - 0, V4L2_SLICED_TELETEXT_B, 0, /* 1 */ - 0, V4L2_SLICED_WSS_625, 0, /* 4 */ - V4L2_SLICED_CAPTION_525, /* 6 */ - 0, 0, V4L2_SLICED_VPS, 0, 0, /* 9 */ - 0, 0, 0, 0 - }; - int is_pal = !(state->std & V4L2_STD_525_60); - int i; - - fmt = arg; - if (fmt->type != V4L2_BUF_TYPE_SLICED_VBI_CAPTURE) - return -EINVAL; - svbi = &fmt->fmt.sliced; - memset(svbi, 0, sizeof(*svbi)); - /* we're done if raw VBI is active */ - if ((cx25840_read(client, 0x404) & 0x10) == 0) - break; + if (fmt->type != V4L2_BUF_TYPE_SLICED_VBI_CAPTURE) + return -EINVAL; + svbi = &fmt->fmt.sliced; + memset(svbi, 0, sizeof(*svbi)); + /* we're done if raw VBI is active */ + if ((cx25840_read(client, 0x404) & 0x10) == 0) + return 0; - if (is_pal) { - for (i = 7; i <= 23; i++) { - u8 v = cx25840_read(client, 0x424 + i - 7); + if (is_pal) { + for (i = 7; i <= 23; i++) { + u8 v = cx25840_read(client, 0x424 + i - 7); - svbi->service_lines[0][i] = lcr2vbi[v >> 4]; - svbi->service_lines[1][i] = lcr2vbi[v & 0xf]; - svbi->service_set |= - svbi->service_lines[0][i] | svbi->service_lines[1][i]; - } + svbi->service_lines[0][i] = lcr2vbi[v >> 4]; + svbi->service_lines[1][i] = lcr2vbi[v & 0xf]; + svbi->service_set |= svbi->service_lines[0][i] | + svbi->service_lines[1][i]; } - else { - for (i = 10; i <= 21; i++) { - u8 v = cx25840_read(client, 0x424 + i - 10); - - svbi->service_lines[0][i] = lcr2vbi[v >> 4]; - svbi->service_lines[1][i] = lcr2vbi[v & 0xf]; - svbi->service_set |= - svbi->service_lines[0][i] | svbi->service_lines[1][i]; - } + } else { + for (i = 10; i <= 21; i++) { + u8 v = cx25840_read(client, 0x424 + i - 10); + + svbi->service_lines[0][i] = lcr2vbi[v >> 4]; + svbi->service_lines[1][i] = lcr2vbi[v & 0xf]; + svbi->service_set |= svbi->service_lines[0][i] | + svbi->service_lines[1][i]; } - break; } + return 0; +} - case VIDIOC_S_FMT: - { - int is_pal = !(state->std & V4L2_STD_525_60); - int vbi_offset = is_pal ? 1 : 0; - int i, x; - u8 lcr[24]; - - fmt = arg; - if (fmt->type != V4L2_BUF_TYPE_SLICED_VBI_CAPTURE && - fmt->type != V4L2_BUF_TYPE_VBI_CAPTURE) - return -EINVAL; - svbi = &fmt->fmt.sliced; - if (fmt->type == V4L2_BUF_TYPE_VBI_CAPTURE) { - /* raw VBI */ - memset(svbi, 0, sizeof(*svbi)); - - /* Setup standard */ - cx25840_std_setup(client); - - /* VBI Offset */ - cx25840_write(client, 0x47f, vbi_offset); - cx25840_write(client, 0x404, 0x2e); - break; - } - - for (x = 0; x <= 23; x++) - lcr[x] = 0x00; +int cx25840_vbi_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + struct cx25840_state *state = to_state(sd); + struct v4l2_sliced_vbi_format *svbi; + int is_pal = !(state->std & V4L2_STD_525_60); + int vbi_offset = is_pal ? 1 : 0; + int i, x; + u8 lcr[24]; + + if (fmt->type != V4L2_BUF_TYPE_SLICED_VBI_CAPTURE && + fmt->type != V4L2_BUF_TYPE_VBI_CAPTURE) + return -EINVAL; + svbi = &fmt->fmt.sliced; + if (fmt->type == V4L2_BUF_TYPE_VBI_CAPTURE) { + /* raw VBI */ + memset(svbi, 0, sizeof(*svbi)); /* Setup standard */ cx25840_std_setup(client); - /* Sliced VBI */ - cx25840_write(client, 0x404, 0x32); /* Ancillary data */ - cx25840_write(client, 0x406, 0x13); + /* VBI Offset */ cx25840_write(client, 0x47f, vbi_offset); + cx25840_write(client, 0x404, 0x2e); + return 0; + } - if (is_pal) { - for (i = 0; i <= 6; i++) - svbi->service_lines[0][i] = - svbi->service_lines[1][i] = 0; - } else { - for (i = 0; i <= 9; i++) - svbi->service_lines[0][i] = - svbi->service_lines[1][i] = 0; - - for (i = 22; i <= 23; i++) - svbi->service_lines[0][i] = - svbi->service_lines[1][i] = 0; - } - - for (i = 7; i <= 23; i++) { - for (x = 0; x <= 1; x++) { - switch (svbi->service_lines[1-x][i]) { - case V4L2_SLICED_TELETEXT_B: - lcr[i] |= 1 << (4 * x); - break; - case V4L2_SLICED_WSS_625: - lcr[i] |= 4 << (4 * x); - break; - case V4L2_SLICED_CAPTION_525: - lcr[i] |= 6 << (4 * x); - break; - case V4L2_SLICED_VPS: - lcr[i] |= 9 << (4 * x); - break; - } - } - } + for (x = 0; x <= 23; x++) + lcr[x] = 0x00; + + /* Setup standard */ + cx25840_std_setup(client); + + /* Sliced VBI */ + cx25840_write(client, 0x404, 0x32); /* Ancillary data */ + cx25840_write(client, 0x406, 0x13); + cx25840_write(client, 0x47f, vbi_offset); + + if (is_pal) { + for (i = 0; i <= 6; i++) + svbi->service_lines[0][i] = + svbi->service_lines[1][i] = 0; + } else { + for (i = 0; i <= 9; i++) + svbi->service_lines[0][i] = + svbi->service_lines[1][i] = 0; + + for (i = 22; i <= 23; i++) + svbi->service_lines[0][i] = + svbi->service_lines[1][i] = 0; + } - if (is_pal) { - for (x = 1, i = 0x424; i <= 0x434; i++, x++) { - cx25840_write(client, i, lcr[6 + x]); - } - } - else { - for (x = 1, i = 0x424; i <= 0x430; i++, x++) { - cx25840_write(client, i, lcr[9 + x]); - } - for (i = 0x431; i <= 0x434; i++) { - cx25840_write(client, i, 0); + for (i = 7; i <= 23; i++) { + for (x = 0; x <= 1; x++) { + switch (svbi->service_lines[1-x][i]) { + case V4L2_SLICED_TELETEXT_B: + lcr[i] |= 1 << (4 * x); + break; + case V4L2_SLICED_WSS_625: + lcr[i] |= 4 << (4 * x); + break; + case V4L2_SLICED_CAPTION_525: + lcr[i] |= 6 << (4 * x); + break; + case V4L2_SLICED_VPS: + lcr[i] |= 9 << (4 * x); + break; } } + } - cx25840_write(client, 0x43c, 0x16); - - if (is_pal) { - cx25840_write(client, 0x474, 0x2a); - } else { - cx25840_write(client, 0x474, 0x22); - } - break; + if (is_pal) { + for (x = 1, i = 0x424; i <= 0x434; i++, x++) + cx25840_write(client, i, lcr[6 + x]); + } else { + for (x = 1, i = 0x424; i <= 0x430; i++, x++) + cx25840_write(client, i, lcr[9 + x]); + for (i = 0x431; i <= 0x434; i++) + cx25840_write(client, i, 0); } - case VIDIOC_INT_DECODE_VBI_LINE: - { - struct v4l2_decode_vbi_line *vbi = arg; - u8 *p = vbi->p; - int id1, id2, l, err = 0; + cx25840_write(client, 0x43c, 0x16); + cx25840_write(client, 0x474, is_pal ? 0x2a : 0x22); + return 0; +} - if (p[0] || p[1] != 0xff || p[2] != 0xff || - (p[3] != 0x55 && p[3] != 0x91)) { - vbi->line = vbi->type = 0; - break; - } +int cx25840_decode_vbi_line(struct v4l2_subdev *sd, struct v4l2_decode_vbi_line *vbi) +{ + struct cx25840_state *state = to_state(sd); + u8 *p = vbi->p; + int id1, id2, l, err = 0; + + if (p[0] || p[1] != 0xff || p[2] != 0xff || + (p[3] != 0x55 && p[3] != 0x91)) { + vbi->line = vbi->type = 0; + return 0; + } - p += 4; - id1 = p[-1]; - id2 = p[0] & 0xf; - l = p[2] & 0x3f; - l += state->vbi_line_offset; - p += 4; + p += 4; + id1 = p[-1]; + id2 = p[0] & 0xf; + l = p[2] & 0x3f; + l += state->vbi_line_offset; + p += 4; - switch (id2) { - case 1: - id2 = V4L2_SLICED_TELETEXT_B; - break; - case 4: - id2 = V4L2_SLICED_WSS_625; - break; - case 6: - id2 = V4L2_SLICED_CAPTION_525; - err = !odd_parity(p[0]) || !odd_parity(p[1]); - break; - case 9: - id2 = V4L2_SLICED_VPS; - if (decode_vps(p, p) != 0) { - err = 1; - } - break; - default: - id2 = 0; + switch (id2) { + case 1: + id2 = V4L2_SLICED_TELETEXT_B; + break; + case 4: + id2 = V4L2_SLICED_WSS_625; + break; + case 6: + id2 = V4L2_SLICED_CAPTION_525; + err = !odd_parity(p[0]) || !odd_parity(p[1]); + break; + case 9: + id2 = V4L2_SLICED_VPS; + if (decode_vps(p, p) != 0) err = 1; - break; - } - - vbi->type = err ? 0 : id2; - vbi->line = err ? 0 : l; - vbi->is_second_field = err ? 0 : (id1 == 0x55); - vbi->p = p; break; - } + default: + id2 = 0; + err = 1; + break; } + vbi->type = err ? 0 : id2; + vbi->line = err ? 0 : l; + vbi->is_second_field = err ? 0 : (id1 == 0x55); + vbi->p = p; return 0; } -- cgit v1.2.3 From 37ae05fdcadbf6763df0ff4d0f66ffdbdbdf2903 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 30 Mar 2009 11:43:13 +0200 Subject: cx18: remove intermediate 'ioctl' step From: Hans Verkuil The audio and vbi parts still used an 'ioctl'-like interface. Replace this with normal functions. Priority: normal Signed-off-by: Hans Verkuil CC: Andy Walls --- linux/drivers/media/video/cx18/cx18-av-audio.c | 120 +++++---- linux/drivers/media/video/cx18/cx18-av-core.c | 29 +-- linux/drivers/media/video/cx18/cx18-av-core.h | 9 +- linux/drivers/media/video/cx18/cx18-av-vbi.c | 325 ++++++++++++------------- 4 files changed, 228 insertions(+), 255 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/cx18/cx18-av-audio.c b/linux/drivers/media/video/cx18/cx18-av-audio.c index a2f0ad570..9e30983f2 100644 --- a/linux/drivers/media/video/cx18/cx18-av-audio.c +++ b/linux/drivers/media/video/cx18/cx18-av-audio.c @@ -464,82 +464,76 @@ static void set_mute(struct cx18 *cx, int mute) } } -int cx18_av_audio(struct cx18 *cx, unsigned int cmd, void *arg) +int cx18_av_s_clock_freq(struct v4l2_subdev *sd, u32 freq) { + struct cx18 *cx = v4l2_get_subdevdata(sd); struct cx18_av_state *state = &cx->av_state; - struct v4l2_control *ctrl = arg; int retval; + u8 v; - switch (cmd) { - case VIDIOC_INT_AUDIO_CLOCK_FREQ: - { - u8 v; - if (state->aud_input > CX18_AV_AUDIO_SERIAL2) { - v = cx18_av_read(cx, 0x803) & ~0x10; - cx18_av_write_expect(cx, 0x803, v, v, 0x1f); - cx18_av_write(cx, 0x8d3, 0x1f); - } - v = cx18_av_read(cx, 0x810) | 0x1; - cx18_av_write_expect(cx, 0x810, v, v, 0x0f); + if (state->aud_input > CX18_AV_AUDIO_SERIAL2) { + v = cx18_av_read(cx, 0x803) & ~0x10; + cx18_av_write_expect(cx, 0x803, v, v, 0x1f); + cx18_av_write(cx, 0x8d3, 0x1f); + } + v = cx18_av_read(cx, 0x810) | 0x1; + cx18_av_write_expect(cx, 0x810, v, v, 0x0f); - retval = set_audclk_freq(cx, *(u32 *)arg); + retval = set_audclk_freq(cx, freq); - v = cx18_av_read(cx, 0x810) & ~0x1; - cx18_av_write_expect(cx, 0x810, v, v, 0x0f); - if (state->aud_input > CX18_AV_AUDIO_SERIAL2) { - v = cx18_av_read(cx, 0x803) | 0x10; - cx18_av_write_expect(cx, 0x803, v, v, 0x1f); - } - return retval; + v = cx18_av_read(cx, 0x810) & ~0x1; + cx18_av_write_expect(cx, 0x810, v, v, 0x0f); + if (state->aud_input > CX18_AV_AUDIO_SERIAL2) { + v = cx18_av_read(cx, 0x803) | 0x10; + cx18_av_write_expect(cx, 0x803, v, v, 0x1f); } + return retval; +} - case VIDIOC_G_CTRL: - switch (ctrl->id) { - case V4L2_CID_AUDIO_VOLUME: - ctrl->value = get_volume(cx); - break; - case V4L2_CID_AUDIO_BASS: - ctrl->value = get_bass(cx); - break; - case V4L2_CID_AUDIO_TREBLE: - ctrl->value = get_treble(cx); - break; - case V4L2_CID_AUDIO_BALANCE: - ctrl->value = get_balance(cx); - break; - case V4L2_CID_AUDIO_MUTE: - ctrl->value = get_mute(cx); - break; - default: - return -EINVAL; - } +int cx18_av_audio_g_ctrl(struct cx18 *cx, struct v4l2_control *ctrl) +{ + switch (ctrl->id) { + case V4L2_CID_AUDIO_VOLUME: + ctrl->value = get_volume(cx); break; - - case VIDIOC_S_CTRL: - switch (ctrl->id) { - case V4L2_CID_AUDIO_VOLUME: - set_volume(cx, ctrl->value); - break; - case V4L2_CID_AUDIO_BASS: - set_bass(cx, ctrl->value); - break; - case V4L2_CID_AUDIO_TREBLE: - set_treble(cx, ctrl->value); - break; - case V4L2_CID_AUDIO_BALANCE: - set_balance(cx, ctrl->value); - break; - case V4L2_CID_AUDIO_MUTE: - set_mute(cx, ctrl->value); - break; - default: - return -EINVAL; - } + case V4L2_CID_AUDIO_BASS: + ctrl->value = get_bass(cx); + break; + case V4L2_CID_AUDIO_TREBLE: + ctrl->value = get_treble(cx); + break; + case V4L2_CID_AUDIO_BALANCE: + ctrl->value = get_balance(cx); + break; + case V4L2_CID_AUDIO_MUTE: + ctrl->value = get_mute(cx); break; - default: return -EINVAL; } + return 0; +} +int cx18_av_audio_s_ctrl(struct cx18 *cx, struct v4l2_control *ctrl) +{ + switch (ctrl->id) { + case V4L2_CID_AUDIO_VOLUME: + set_volume(cx, ctrl->value); + break; + case V4L2_CID_AUDIO_BASS: + set_bass(cx, ctrl->value); + break; + case V4L2_CID_AUDIO_TREBLE: + set_treble(cx, ctrl->value); + break; + case V4L2_CID_AUDIO_BALANCE: + set_balance(cx, ctrl->value); + break; + case V4L2_CID_AUDIO_MUTE: + set_mute(cx, ctrl->value); + break; + default: + return -EINVAL; + } return 0; } diff --git a/linux/drivers/media/video/cx18/cx18-av-core.c b/linux/drivers/media/video/cx18/cx18-av-core.c index 21f4be839..f4dd9d78e 100644 --- a/linux/drivers/media/video/cx18/cx18-av-core.c +++ b/linux/drivers/media/video/cx18/cx18-av-core.c @@ -413,19 +413,6 @@ void cx18_av_std_setup(struct cx18 *cx) cx18_av_write(cx, 0x47f, state->slicer_line_delay); } -static int cx18_av_decode_vbi_line(struct v4l2_subdev *sd, - struct v4l2_decode_vbi_line *vbi_line) -{ - struct cx18 *cx = v4l2_get_subdevdata(sd); - return cx18_av_vbi(cx, VIDIOC_INT_DECODE_VBI_LINE, vbi_line); -} - -static int cx18_av_s_clock_freq(struct v4l2_subdev *sd, u32 freq) -{ - struct cx18 *cx = v4l2_get_subdevdata(sd); - return cx18_av_audio(cx, VIDIOC_INT_AUDIO_CLOCK_FREQ, &freq); -} - static void input_change(struct cx18 *cx) { struct cx18_av_state *state = &cx->av_state; @@ -772,7 +759,7 @@ static int cx18_av_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) case V4L2_CID_AUDIO_TREBLE: case V4L2_CID_AUDIO_BALANCE: case V4L2_CID_AUDIO_MUTE: - return cx18_av_audio(cx, VIDIOC_S_CTRL, ctrl); + return cx18_av_audio_s_ctrl(cx, ctrl); default: return -EINVAL; @@ -802,7 +789,7 @@ static int cx18_av_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) case V4L2_CID_AUDIO_TREBLE: case V4L2_CID_AUDIO_BALANCE: case V4L2_CID_AUDIO_MUTE: - return cx18_av_audio(cx, VIDIOC_G_CTRL, ctrl); + return cx18_av_audio_g_ctrl(cx, ctrl); default: return -EINVAL; } @@ -845,13 +832,7 @@ static int cx18_av_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) { struct cx18 *cx = v4l2_get_subdevdata(sd); - switch (fmt->type) { - case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: - return cx18_av_vbi(cx, VIDIOC_G_FMT, fmt); - default: - return -EINVAL; - } - return 0; + return cx18_av_vbi_g_fmt(cx, fmt); } static int cx18_av_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) @@ -925,10 +906,10 @@ static int cx18_av_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) break; case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: - return cx18_av_vbi(cx, VIDIOC_S_FMT, fmt); + return cx18_av_vbi_s_fmt(cx, fmt); case V4L2_BUF_TYPE_VBI_CAPTURE: - return cx18_av_vbi(cx, VIDIOC_S_FMT, fmt); + return cx18_av_vbi_s_fmt(cx, fmt); default: return -EINVAL; diff --git a/linux/drivers/media/video/cx18/cx18-av-core.h b/linux/drivers/media/video/cx18/cx18-av-core.h index 2687a2c91..c458120e8 100644 --- a/linux/drivers/media/video/cx18/cx18-av-core.h +++ b/linux/drivers/media/video/cx18/cx18-av-core.h @@ -355,11 +355,16 @@ int cx18_av_loadfw(struct cx18 *cx); /* ----------------------------------------------------------------------- */ /* cx18_av-audio.c */ -int cx18_av_audio(struct cx18 *cx, unsigned int cmd, void *arg); +int cx18_av_audio_g_ctrl(struct cx18 *cx, struct v4l2_control *ctrl); +int cx18_av_audio_s_ctrl(struct cx18 *cx, struct v4l2_control *ctrl); +int cx18_av_s_clock_freq(struct v4l2_subdev *sd, u32 freq); void cx18_av_audio_set_path(struct cx18 *cx); /* ----------------------------------------------------------------------- */ /* cx18_av-vbi.c */ -int cx18_av_vbi(struct cx18 *cx, unsigned int cmd, void *arg); +int cx18_av_decode_vbi_line(struct v4l2_subdev *sd, + struct v4l2_decode_vbi_line *vbi); +int cx18_av_vbi_g_fmt(struct cx18 *cx, struct v4l2_format *fmt); +int cx18_av_vbi_s_fmt(struct cx18 *cx, struct v4l2_format *fmt); #endif diff --git a/linux/drivers/media/video/cx18/cx18-av-vbi.c b/linux/drivers/media/video/cx18/cx18-av-vbi.c index 27699839b..23b31670b 100644 --- a/linux/drivers/media/video/cx18/cx18-av-vbi.c +++ b/linux/drivers/media/video/cx18/cx18-av-vbi.c @@ -129,196 +129,189 @@ static int decode_vps(u8 *dst, u8 *p) return err & 0xf0; } -int cx18_av_vbi(struct cx18 *cx, unsigned int cmd, void *arg) +int cx18_av_vbi_g_fmt(struct cx18 *cx, struct v4l2_format *fmt) { struct cx18_av_state *state = &cx->av_state; - struct v4l2_format *fmt; struct v4l2_sliced_vbi_format *svbi; + static const u16 lcr2vbi[] = { + 0, V4L2_SLICED_TELETEXT_B, 0, /* 1 */ + 0, V4L2_SLICED_WSS_625, 0, /* 4 */ + V4L2_SLICED_CAPTION_525, /* 6 */ + 0, 0, V4L2_SLICED_VPS, 0, 0, /* 9 */ + 0, 0, 0, 0 + }; + int is_pal = !(state->std & V4L2_STD_525_60); + int i; - switch (cmd) { - case VIDIOC_G_FMT: - { - static u16 lcr2vbi[] = { - 0, V4L2_SLICED_TELETEXT_B, 0, /* 1 */ - 0, V4L2_SLICED_WSS_625, 0, /* 4 */ - V4L2_SLICED_CAPTION_525, /* 6 */ - 0, 0, V4L2_SLICED_VPS, 0, 0, /* 9 */ - 0, 0, 0, 0 - }; - int is_pal = !(state->std & V4L2_STD_525_60); - int i; - - fmt = arg; - if (fmt->type != V4L2_BUF_TYPE_SLICED_VBI_CAPTURE) - return -EINVAL; - svbi = &fmt->fmt.sliced; - memset(svbi, 0, sizeof(*svbi)); - /* we're done if raw VBI is active */ - if ((cx18_av_read(cx, 0x404) & 0x10) == 0) - break; - - if (is_pal) { - for (i = 7; i <= 23; i++) { - u8 v = cx18_av_read(cx, 0x424 + i - 7); - - svbi->service_lines[0][i] = lcr2vbi[v >> 4]; - svbi->service_lines[1][i] = lcr2vbi[v & 0xf]; - svbi->service_set |= svbi->service_lines[0][i] | - svbi->service_lines[1][i]; - } - } else { - for (i = 10; i <= 21; i++) { - u8 v = cx18_av_read(cx, 0x424 + i - 10); - - svbi->service_lines[0][i] = lcr2vbi[v >> 4]; - svbi->service_lines[1][i] = lcr2vbi[v & 0xf]; - svbi->service_set |= svbi->service_lines[0][i] | - svbi->service_lines[1][i]; - } - } - break; - } + if (fmt->type != V4L2_BUF_TYPE_SLICED_VBI_CAPTURE) + return -EINVAL; + svbi = &fmt->fmt.sliced; + memset(svbi, 0, sizeof(*svbi)); + /* we're done if raw VBI is active */ + if ((cx18_av_read(cx, 0x404) & 0x10) == 0) + return 0; + + if (is_pal) { + for (i = 7; i <= 23; i++) { + u8 v = cx18_av_read(cx, 0x424 + i - 7); - case VIDIOC_S_FMT: - { - int is_pal = !(state->std & V4L2_STD_525_60); - int i, x; - u8 lcr[24]; - - fmt = arg; - if (fmt->type != V4L2_BUF_TYPE_SLICED_VBI_CAPTURE && - fmt->type != V4L2_BUF_TYPE_VBI_CAPTURE) - return -EINVAL; - svbi = &fmt->fmt.sliced; - if (fmt->type == V4L2_BUF_TYPE_VBI_CAPTURE) { - /* raw VBI */ - memset(svbi, 0, sizeof(*svbi)); - - /* Setup standard */ - cx18_av_std_setup(cx); - - /* VBI Offset */ - cx18_av_write(cx, 0x47f, state->slicer_line_delay); - cx18_av_write(cx, 0x404, 0x2e); - break; + svbi->service_lines[0][i] = lcr2vbi[v >> 4]; + svbi->service_lines[1][i] = lcr2vbi[v & 0xf]; + svbi->service_set |= svbi->service_lines[0][i] | + svbi->service_lines[1][i]; } + } else { + for (i = 10; i <= 21; i++) { + u8 v = cx18_av_read(cx, 0x424 + i - 10); + + svbi->service_lines[0][i] = lcr2vbi[v >> 4]; + svbi->service_lines[1][i] = lcr2vbi[v & 0xf]; + svbi->service_set |= svbi->service_lines[0][i] | + svbi->service_lines[1][i]; + } + } + return 0; +} - for (x = 0; x <= 23; x++) - lcr[x] = 0x00; +int cx18_av_vbi_s_fmt(struct cx18 *cx, struct v4l2_format *fmt) +{ + struct cx18_av_state *state = &cx->av_state; + struct v4l2_sliced_vbi_format *svbi; + int is_pal = !(state->std & V4L2_STD_525_60); + int i, x; + u8 lcr[24]; + + if (fmt->type != V4L2_BUF_TYPE_SLICED_VBI_CAPTURE && + fmt->type != V4L2_BUF_TYPE_VBI_CAPTURE) + return -EINVAL; + svbi = &fmt->fmt.sliced; + if (fmt->type == V4L2_BUF_TYPE_VBI_CAPTURE) { + /* raw VBI */ + memset(svbi, 0, sizeof(*svbi)); /* Setup standard */ cx18_av_std_setup(cx); - /* Sliced VBI */ - cx18_av_write(cx, 0x404, 0x32); /* Ancillary data */ - cx18_av_write(cx, 0x406, 0x13); + /* VBI Offset */ cx18_av_write(cx, 0x47f, state->slicer_line_delay); + cx18_av_write(cx, 0x404, 0x2e); + return 0; + } - /* Force impossible lines to 0 */ - if (is_pal) { - for (i = 0; i <= 6; i++) - svbi->service_lines[0][i] = - svbi->service_lines[1][i] = 0; - } else { - for (i = 0; i <= 9; i++) - svbi->service_lines[0][i] = - svbi->service_lines[1][i] = 0; - - for (i = 22; i <= 23; i++) - svbi->service_lines[0][i] = - svbi->service_lines[1][i] = 0; - } + for (x = 0; x <= 23; x++) + lcr[x] = 0x00; + + /* Setup standard */ + cx18_av_std_setup(cx); + + /* Sliced VBI */ + cx18_av_write(cx, 0x404, 0x32); /* Ancillary data */ + cx18_av_write(cx, 0x406, 0x13); + cx18_av_write(cx, 0x47f, state->slicer_line_delay); + + /* Force impossible lines to 0 */ + if (is_pal) { + for (i = 0; i <= 6; i++) + svbi->service_lines[0][i] = + svbi->service_lines[1][i] = 0; + } else { + for (i = 0; i <= 9; i++) + svbi->service_lines[0][i] = + svbi->service_lines[1][i] = 0; + + for (i = 22; i <= 23; i++) + svbi->service_lines[0][i] = + svbi->service_lines[1][i] = 0; + } - /* Build register values for requested service lines */ - for (i = 7; i <= 23; i++) { - for (x = 0; x <= 1; x++) { - switch (svbi->service_lines[1-x][i]) { - case V4L2_SLICED_TELETEXT_B: - lcr[i] |= 1 << (4 * x); - break; - case V4L2_SLICED_WSS_625: - lcr[i] |= 4 << (4 * x); - break; - case V4L2_SLICED_CAPTION_525: - lcr[i] |= 6 << (4 * x); - break; - case V4L2_SLICED_VPS: - lcr[i] |= 9 << (4 * x); - break; - } + /* Build register values for requested service lines */ + for (i = 7; i <= 23; i++) { + for (x = 0; x <= 1; x++) { + switch (svbi->service_lines[1-x][i]) { + case V4L2_SLICED_TELETEXT_B: + lcr[i] |= 1 << (4 * x); + break; + case V4L2_SLICED_WSS_625: + lcr[i] |= 4 << (4 * x); + break; + case V4L2_SLICED_CAPTION_525: + lcr[i] |= 6 << (4 * x); + break; + case V4L2_SLICED_VPS: + lcr[i] |= 9 << (4 * x); + break; } } + } - if (is_pal) { - for (x = 1, i = 0x424; i <= 0x434; i++, x++) - cx18_av_write(cx, i, lcr[6 + x]); - } else { - for (x = 1, i = 0x424; i <= 0x430; i++, x++) - cx18_av_write(cx, i, lcr[9 + x]); - for (i = 0x431; i <= 0x434; i++) - cx18_av_write(cx, i, 0); - } + if (is_pal) { + for (x = 1, i = 0x424; i <= 0x434; i++, x++) + cx18_av_write(cx, i, lcr[6 + x]); + } else { + for (x = 1, i = 0x424; i <= 0x430; i++, x++) + cx18_av_write(cx, i, lcr[9 + x]); + for (i = 0x431; i <= 0x434; i++) + cx18_av_write(cx, i, 0); + } - cx18_av_write(cx, 0x43c, 0x16); - /* FIXME - should match vblank set in cx18_av_std_setup() */ - cx18_av_write(cx, 0x474, is_pal ? 0x2a : 26); - break; + cx18_av_write(cx, 0x43c, 0x16); + /* FIXME - should match vblank set in cx18_av_std_setup() */ + cx18_av_write(cx, 0x474, is_pal ? 0x2a : 26); + return 0; +} + +int cx18_av_decode_vbi_line(struct v4l2_subdev *sd, + struct v4l2_decode_vbi_line *vbi) +{ + struct cx18 *cx = v4l2_get_subdevdata(sd); + struct cx18_av_state *state = &cx->av_state; + struct vbi_anc_data *anc = (struct vbi_anc_data *)vbi->p; + u8 *p; + int did, sdid, l, err = 0; + + /* + * Check for the ancillary data header for sliced VBI + */ + if (anc->preamble[0] || + anc->preamble[1] != 0xff || anc->preamble[2] != 0xff || + (anc->did != sliced_vbi_did[0] && + anc->did != sliced_vbi_did[1])) { + vbi->line = vbi->type = 0; + return 0; } - case VIDIOC_INT_DECODE_VBI_LINE: - { - struct v4l2_decode_vbi_line *vbi = arg; - u8 *p; - struct vbi_anc_data *anc = (struct vbi_anc_data *) vbi->p; - int did, sdid, l, err = 0; - - /* - * Check for the ancillary data header for sliced VBI - */ - if (anc->preamble[0] || - anc->preamble[1] != 0xff || anc->preamble[2] != 0xff || - (anc->did != sliced_vbi_did[0] && - anc->did != sliced_vbi_did[1])) { - vbi->line = vbi->type = 0; - break; - } + did = anc->did; + sdid = anc->sdid & 0xf; + l = anc->idid[0] & 0x3f; + l += state->slicer_line_offset; + p = anc->payload; - did = anc->did; - sdid = anc->sdid & 0xf; - l = anc->idid[0] & 0x3f; - l += state->slicer_line_offset; - p = anc->payload; - - /* Decode the SDID set by the slicer */ - switch (sdid) { - case 1: - sdid = V4L2_SLICED_TELETEXT_B; - break; - case 4: - sdid = V4L2_SLICED_WSS_625; - break; - case 6: - sdid = V4L2_SLICED_CAPTION_525; - err = !odd_parity(p[0]) || !odd_parity(p[1]); - break; - case 9: - sdid = V4L2_SLICED_VPS; - if (decode_vps(p, p) != 0) - err = 1; - break; - default: - sdid = 0; + /* Decode the SDID set by the slicer */ + switch (sdid) { + case 1: + sdid = V4L2_SLICED_TELETEXT_B; + break; + case 4: + sdid = V4L2_SLICED_WSS_625; + break; + case 6: + sdid = V4L2_SLICED_CAPTION_525; + err = !odd_parity(p[0]) || !odd_parity(p[1]); + break; + case 9: + sdid = V4L2_SLICED_VPS; + if (decode_vps(p, p) != 0) err = 1; - break; - } - - vbi->type = err ? 0 : sdid; - vbi->line = err ? 0 : l; - vbi->is_second_field = err ? 0 : (did == sliced_vbi_did[1]); - vbi->p = p; break; - } + default: + sdid = 0; + err = 1; + break; } + vbi->type = err ? 0 : sdid; + vbi->line = err ? 0 : l; + vbi->is_second_field = err ? 0 : (did == sliced_vbi_did[1]); + vbi->p = p; return 0; } -- cgit v1.2.3 From 7724463d3ee67a522ea96970857035232affe184 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 30 Mar 2009 11:55:27 +0200 Subject: v4l: replace 'ioctl' references in v4l i2c drivers From: Hans Verkuil Replace 'VIDIOC_' references in v4l i2c drivers by their new v4l2_subdev callback names. Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/ks0127.c | 23 ++++++++++++----------- linux/drivers/media/video/saa7115.c | 4 ++-- linux/drivers/media/video/tuner-core.c | 17 +++++++---------- linux/drivers/media/video/tvp5150.c | 8 ++++---- linux/drivers/media/video/vpx3220.c | 8 ++++---- 5 files changed, 29 insertions(+), 31 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/ks0127.c b/linux/drivers/media/video/ks0127.c index 3dbda6e92..a1b12557a 100644 --- a/linux/drivers/media/video/ks0127.c +++ b/linux/drivers/media/video/ks0127.c @@ -431,7 +431,7 @@ static int ks0127_s_routing(struct v4l2_subdev *sd, const struct v4l2_routing *r case KS_INPUT_COMPOSITE_5: case KS_INPUT_COMPOSITE_6: v4l2_dbg(1, debug, sd, - "VIDIOC_S_INPUT %d: Composite\n", route->input); + "s_routing %d: Composite\n", route->input); /* autodetect 50/60 Hz */ ks0127_and_or(sd, KS_CMDA, 0xfc, 0x00); /* VSE=0 */ @@ -465,7 +465,7 @@ static int ks0127_s_routing(struct v4l2_subdev *sd, const struct v4l2_routing *r case KS_INPUT_SVIDEO_2: case KS_INPUT_SVIDEO_3: v4l2_dbg(1, debug, sd, - "VIDIOC_S_INPUT %d: S-Video\n", route->input); + "s_routing %d: S-Video\n", route->input); /* autodetect 50/60 Hz */ ks0127_and_or(sd, KS_CMDA, 0xfc, 0x00); /* VSE=0 */ @@ -496,7 +496,7 @@ static int ks0127_s_routing(struct v4l2_subdev *sd, const struct v4l2_routing *r break; case KS_INPUT_YUV656: - v4l2_dbg(1, debug, sd, "VIDIOC_S_INPUT 15: YUV656\n"); + v4l2_dbg(1, debug, sd, "s_routing 15: YUV656\n"); if (ks->norm & V4L2_STD_525_60) /* force 60 Hz */ ks0127_and_or(sd, KS_CMDA, 0xfc, 0x03); @@ -541,7 +541,7 @@ static int ks0127_s_routing(struct v4l2_subdev *sd, const struct v4l2_routing *r default: v4l2_dbg(1, debug, sd, - "VIDIOC_INT_S_VIDEO_ROUTING: Unknown input %d\n", route->input); + "s_routing: Unknown input %d\n", route->input); break; } @@ -561,23 +561,23 @@ static int ks0127_s_std(struct v4l2_subdev *sd, v4l2_std_id std) ks->norm = std; if (std & V4L2_STD_NTSC) { v4l2_dbg(1, debug, sd, - "VIDIOC_S_STD: NTSC_M\n"); + "s_std: NTSC_M\n"); ks0127_and_or(sd, KS_CHROMA, 0x9f, 0x20); } else if (std & V4L2_STD_PAL_N) { v4l2_dbg(1, debug, sd, - "KS0127_SET_NORM: NTSC_N (fixme)\n"); + "s_std: NTSC_N (fixme)\n"); ks0127_and_or(sd, KS_CHROMA, 0x9f, 0x40); } else if (std & V4L2_STD_PAL) { v4l2_dbg(1, debug, sd, - "VIDIOC_S_STD: PAL_N\n"); + "s_std: PAL_N\n"); ks0127_and_or(sd, KS_CHROMA, 0x9f, 0x20); } else if (std & V4L2_STD_PAL_M) { v4l2_dbg(1, debug, sd, - "KS0127_SET_NORM: PAL_M (fixme)\n"); + "s_std: PAL_M (fixme)\n"); ks0127_and_or(sd, KS_CHROMA, 0x9f, 0x40); } else if (std & V4L2_STD_SECAM) { v4l2_dbg(1, debug, sd, - "KS0127_SET_NORM: SECAM\n"); + "s_std: SECAM\n"); /* set to secam autodetection */ ks0127_and_or(sd, KS_CHROMA, 0xdf, 0x20); @@ -589,7 +589,7 @@ static int ks0127_s_std(struct v4l2_subdev *sd, v4l2_std_id std) /* force to secam mode */ ks0127_and_or(sd, KS_DEMOD, 0xf0, 0x0f); } else { - v4l2_dbg(1, debug, sd, "VIDIOC_S_STD: Unknown norm %llx\n", + v4l2_dbg(1, debug, sd, "s_std: Unknown norm %llx\n", (unsigned long long)std); } return 0; @@ -618,7 +618,6 @@ static int ks0127_status(struct v4l2_subdev *sd, u32 *pstatus, v4l2_std_id *pstd u8 status; v4l2_std_id std = V4L2_STD_ALL; - v4l2_dbg(1, debug, sd, "VIDIOC_QUERYSTD/VIDIOC_INT_G_INPUT_STATUS\n"); status = ks0127_read(sd, KS_STAT); if (!(status & 0x20)) /* NOVID not set */ stat = 0; @@ -637,11 +636,13 @@ static int ks0127_status(struct v4l2_subdev *sd, u32 *pstatus, v4l2_std_id *pstd static int ks0127_querystd(struct v4l2_subdev *sd, v4l2_std_id *std) { + v4l2_dbg(1, debug, sd, "querystd\n"); return ks0127_status(sd, NULL, std); } static int ks0127_g_input_status(struct v4l2_subdev *sd, u32 *status) { + v4l2_dbg(1, debug, sd, "g_input_status\n"); return ks0127_status(sd, status, NULL); } diff --git a/linux/drivers/media/video/saa7115.c b/linux/drivers/media/video/saa7115.c index 2570ebf89..0719b5f13 100644 --- a/linux/drivers/media/video/saa7115.c +++ b/linux/drivers/media/video/saa7115.c @@ -932,8 +932,8 @@ static void saa711x_set_v4lstd(struct v4l2_subdev *sd, v4l2_std_id std) /* Prevent unnecessary standard changes. During a standard change the I-Port is temporarily disabled. Any devices reading from that port can get confused. - Note that VIDIOC_S_STD is also used to switch from - radio to TV mode, so if a VIDIOC_S_STD is broadcast to + Note that s_std is also used to switch from + radio to TV mode, so if a s_std is broadcast to all I2C devices then you do not want to have an unwanted side-effect here. */ if (std == state->std) diff --git a/linux/drivers/media/video/tuner-core.c b/linux/drivers/media/video/tuner-core.c index 9960fb357..c73a0841b 100644 --- a/linux/drivers/media/video/tuner-core.c +++ b/linux/drivers/media/video/tuner-core.c @@ -788,8 +788,7 @@ static int tuner_s_radio(struct v4l2_subdev *sd) struct tuner *t = to_tuner(sd); struct i2c_client *client = v4l2_get_subdevdata(sd); - if (set_mode(client, t, V4L2_TUNER_RADIO, "AUDC_SET_RADIO") - == -EINVAL) + if (set_mode(client, t, V4L2_TUNER_RADIO, "s_radio") == -EINVAL) return 0; if (t->radio_freq) set_freq(client, t->radio_freq); @@ -803,7 +802,7 @@ static int tuner_s_standby(struct v4l2_subdev *sd, u32 standby) tuner_dbg("Putting tuner to sleep\n"); - if (check_mode(t, "TUNER_SET_STANDBY") == -EINVAL) + if (check_mode(t, "s_standby") == -EINVAL) return 0; t->mode = T_STANDBY; if (analog_ops->standby) @@ -962,8 +961,7 @@ static int tuner_s_std(struct v4l2_subdev *sd, v4l2_std_id std) struct tuner *t = to_tuner(sd); struct i2c_client *client = v4l2_get_subdevdata(sd); - if (set_mode(client, t, V4L2_TUNER_ANALOG_TV, "VIDIOC_S_STD") - == -EINVAL) + if (set_mode(client, t, V4L2_TUNER_ANALOG_TV, "s_std") == -EINVAL) return 0; switch_v4l2(); @@ -980,8 +978,7 @@ static int tuner_s_frequency(struct v4l2_subdev *sd, struct v4l2_frequency *f) struct tuner *t = to_tuner(sd); struct i2c_client *client = v4l2_get_subdevdata(sd); - if (set_mode(client, t, f->type, "VIDIOC_S_FREQUENCY") - == -EINVAL) + if (set_mode(client, t, f->type, "s_frequency") == -EINVAL) return 0; switch_v4l2(); set_freq(client, f->frequency); @@ -994,7 +991,7 @@ static int tuner_g_frequency(struct v4l2_subdev *sd, struct v4l2_frequency *f) struct tuner *t = to_tuner(sd); struct dvb_tuner_ops *fe_tuner_ops = &t->fe.ops.tuner_ops; - if (check_mode(t, "VIDIOC_G_FREQUENCY") == -EINVAL) + if (check_mode(t, "g_frequency") == -EINVAL) return 0; switch_v4l2(); f->type = t->mode; @@ -1018,7 +1015,7 @@ static int tuner_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt) struct analog_demod_ops *analog_ops = &t->fe.ops.analog_ops; struct dvb_tuner_ops *fe_tuner_ops = &t->fe.ops.tuner_ops; - if (check_mode(t, "VIDIOC_G_TUNER") == -EINVAL) + if (check_mode(t, "g_tuner") == -EINVAL) return 0; switch_v4l2(); @@ -1067,7 +1064,7 @@ static int tuner_s_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt) struct tuner *t = to_tuner(sd); struct i2c_client *client = v4l2_get_subdevdata(sd); - if (check_mode(t, "VIDIOC_S_TUNER") == -EINVAL) + if (check_mode(t, "s_tuner") == -EINVAL) return 0; switch_v4l2(); diff --git a/linux/drivers/media/video/tvp5150.c b/linux/drivers/media/video/tvp5150.c index 9ae372246..67c18f280 100644 --- a/linux/drivers/media/video/tvp5150.c +++ b/linux/drivers/media/video/tvp5150.c @@ -643,7 +643,7 @@ static int tvp5150_g_sliced_vbi_cap(struct v4l2_subdev *sd, const struct i2c_vbi_ram_value *regs = vbi_ram_default; int line; - v4l2_dbg(1, debug, sd, "VIDIOC_G_SLICED_VBI_CAP\n"); + v4l2_dbg(1, debug, sd, "g_sliced_vbi_cap\n"); memset(cap, 0, sizeof *cap); while (regs->reg != (u16)-1 ) { @@ -842,7 +842,7 @@ static int tvp5150_reset(struct v4l2_subdev *sd, u32 val) static int tvp5150_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) { - v4l2_dbg(1, debug, sd, "VIDIOC_G_CTRL called\n"); + v4l2_dbg(1, debug, sd, "g_ctrl called\n"); switch (ctrl->id) { case V4L2_CID_BRIGHTNESS: @@ -872,7 +872,7 @@ static int tvp5150_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) if (ctrl->value < tvp5150_qctrl[i].minimum || ctrl->value > tvp5150_qctrl[i].maximum) return -ERANGE; - v4l2_dbg(1, debug, sd, "VIDIOC_S_CTRL: id=%d, value=%d\n", + v4l2_dbg(1, debug, sd, "s_ctrl: id=%d, value=%d\n", ctrl->id, ctrl->value); break; } @@ -1081,7 +1081,7 @@ static int tvp5150_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc) { int i; - v4l2_dbg(1, debug, sd, "VIDIOC_QUERYCTRL called\n"); + v4l2_dbg(1, debug, sd, "queryctrl called\n"); for (i = 0; i < ARRAY_SIZE(tvp5150_qctrl); i++) if (qc->id && qc->id == tvp5150_qctrl[i].id) { diff --git a/linux/drivers/media/video/vpx3220.c b/linux/drivers/media/video/vpx3220.c index ee6c74176..224c899d1 100644 --- a/linux/drivers/media/video/vpx3220.c +++ b/linux/drivers/media/video/vpx3220.c @@ -316,8 +316,6 @@ static int vpx3220_status(struct v4l2_subdev *sd, u32 *pstatus, v4l2_std_id *pst int res = V4L2_IN_ST_NO_SIGNAL, status; v4l2_std_id std = 0; - v4l2_dbg(1, debug, sd, "VIDIOC_QUERYSTD/VIDIOC_INT_G_INPUT_STATUS\n"); - status = vpx3220_fp_read(sd, 0x0f3); v4l2_dbg(1, debug, sd, "status: 0x%04x\n", status); @@ -356,11 +354,13 @@ static int vpx3220_status(struct v4l2_subdev *sd, u32 *pstatus, v4l2_std_id *pst static int vpx3220_querystd(struct v4l2_subdev *sd, v4l2_std_id *std) { + v4l2_dbg(1, debug, sd, "querystd\n"); return vpx3220_status(sd, NULL, std); } static int vpx3220_g_input_status(struct v4l2_subdev *sd, u32 *status) { + v4l2_dbg(1, debug, sd, "g_input_status\n"); return vpx3220_status(sd, status, NULL); } @@ -374,7 +374,7 @@ static int vpx3220_s_std(struct v4l2_subdev *sd, v4l2_std_id std) choosen video norm */ temp_input = vpx3220_fp_read(sd, 0xf2); - v4l2_dbg(1, debug, sd, "VIDIOC_S_STD %llx\n", (unsigned long long)std); + v4l2_dbg(1, debug, sd, "s_std %llx\n", (unsigned long long)std); if (std & V4L2_STD_NTSC) { vpx3220_write_fp_block(sd, init_ntsc, sizeof(init_ntsc) >> 1); v4l2_dbg(1, debug, sd, "norm switched to NTSC\n"); @@ -430,7 +430,7 @@ static int vpx3220_s_routing(struct v4l2_subdev *sd, const struct v4l2_routing * static int vpx3220_s_stream(struct v4l2_subdev *sd, int enable) { - v4l2_dbg(1, debug, sd, "VIDIOC_STREAM%s\n", enable ? "ON" : "OFF"); + v4l2_dbg(1, debug, sd, "s_stream %s\n", enable ? "on" : "off"); vpx3220_write(sd, 0xf2, (enable ? 0x1b : 0x00)); return 0; -- cgit v1.2.3 From 73f3821cc1c4a112f3fcc4eb834fa26f4a587146 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 30 Mar 2009 12:04:07 +0200 Subject: tuner: remove V4L1 code from this driver. From: Hans Verkuil No i2c modules are called with the V4L1 API anymore, so this can be removed. Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/tuner-core.c | 129 --------------------------------- 1 file changed, 129 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/tuner-core.c b/linux/drivers/media/video/tuner-core.c index c73a0841b..0ac702201 100644 --- a/linux/drivers/media/video/tuner-core.c +++ b/linux/drivers/media/video/tuner-core.c @@ -810,132 +810,6 @@ static int tuner_s_standby(struct v4l2_subdev *sd, u32 standby) return 0; } -#ifdef CONFIG_VIDEO_ALLOW_V4L1 -static long tuner_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) -{ - struct tuner *t = to_tuner(sd); - struct i2c_client *client = v4l2_get_subdevdata(sd); - struct analog_demod_ops *analog_ops = &t->fe.ops.analog_ops; - struct dvb_tuner_ops *fe_tuner_ops = &t->fe.ops.tuner_ops; - - switch (cmd) { - case VIDIOCSAUDIO: - if (check_mode(t, "VIDIOCSAUDIO") == -EINVAL) - return 0; - if (check_v4l2(t) == -EINVAL) - return 0; - - /* Should be implemented, since bttv calls it */ - tuner_dbg("VIDIOCSAUDIO not implemented.\n"); - break; - case VIDIOCSCHAN: - { - static const v4l2_std_id map[] = { - [VIDEO_MODE_PAL] = V4L2_STD_PAL, - [VIDEO_MODE_NTSC] = V4L2_STD_NTSC_M, - [VIDEO_MODE_SECAM] = V4L2_STD_SECAM, - [4 /* bttv */ ] = V4L2_STD_PAL_M, - [5 /* bttv */ ] = V4L2_STD_PAL_N, - [6 /* bttv */ ] = V4L2_STD_NTSC_M_JP, - }; - struct video_channel *vc = arg; - - if (check_v4l2(t) == -EINVAL) - return 0; - - if (set_mode(client,t,V4L2_TUNER_ANALOG_TV, "VIDIOCSCHAN")==-EINVAL) - return 0; - - if (vc->norm < ARRAY_SIZE(map)) - t->std = map[vc->norm]; - tuner_fixup_std(t); - if (t->tv_freq) - set_tv_freq(client, t->tv_freq); - return 0; - } - case VIDIOCSFREQ: - { - unsigned long *v = arg; - - if (check_mode(t, "VIDIOCSFREQ") == -EINVAL) - return 0; - if (check_v4l2(t) == -EINVAL) - return 0; - - set_freq(client, *v); - return 0; - } - case VIDIOCGTUNER: - { - struct video_tuner *vt = arg; - - if (check_mode(t, "VIDIOCGTUNER") == -EINVAL) - return 0; - if (check_v4l2(t) == -EINVAL) - return 0; - - if (V4L2_TUNER_RADIO == t->mode) { - if (fe_tuner_ops->get_status) { - u32 tuner_status; - - fe_tuner_ops->get_status(&t->fe, &tuner_status); - if (tuner_status & TUNER_STATUS_STEREO) - vt->flags |= VIDEO_TUNER_STEREO_ON; - else - vt->flags &= ~VIDEO_TUNER_STEREO_ON; - } else { - if (analog_ops->is_stereo) { - if (analog_ops->is_stereo(&t->fe)) - vt->flags |= - VIDEO_TUNER_STEREO_ON; - else - vt->flags &= - ~VIDEO_TUNER_STEREO_ON; - } - } - if (analog_ops->has_signal) - vt->signal = - analog_ops->has_signal(&t->fe); - - vt->flags |= VIDEO_TUNER_LOW; /* Allow freqs at 62.5 Hz */ - - vt->rangelow = radio_range[0] * 16000; - vt->rangehigh = radio_range[1] * 16000; - - } else { - vt->rangelow = tv_range[0] * 16; - vt->rangehigh = tv_range[1] * 16; - } - - return 0; - } - case VIDIOCGAUDIO: - { - struct video_audio *va = arg; - - if (check_mode(t, "VIDIOCGAUDIO") == -EINVAL) - return 0; - if (check_v4l2(t) == -EINVAL) - return 0; - - if (V4L2_TUNER_RADIO == t->mode) { - if (fe_tuner_ops->get_status) { - u32 tuner_status; - - fe_tuner_ops->get_status(&t->fe, &tuner_status); - va->mode = (tuner_status & TUNER_STATUS_STEREO) - ? VIDEO_SOUND_STEREO : VIDEO_SOUND_MONO; - } else if (analog_ops->is_stereo) - va->mode = analog_ops->is_stereo(&t->fe) - ? VIDEO_SOUND_STEREO : VIDEO_SOUND_MONO; - } - return 0; - } - } - return -ENOIOCTLCMD; -} -#endif - static int tuner_s_config(struct v4l2_subdev *sd, const struct v4l2_priv_tun_config *cfg) { struct tuner *t = to_tuner(sd); @@ -1121,9 +995,6 @@ static int tuner_resume(struct i2c_client *c) static const struct v4l2_subdev_core_ops tuner_core_ops = { .log_status = tuner_log_status, .s_standby = tuner_s_standby, -#ifdef CONFIG_VIDEO_ALLOW_V4L1 - .ioctl = tuner_ioctl, -#endif }; static const struct v4l2_subdev_tuner_ops tuner_tuner_ops = { -- cgit v1.2.3 From ed518b0f12ebcaed430a8d60da4ff0b09269bd10 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 29 Mar 2009 23:19:38 +0000 Subject: 2-dev.c: return 0 for NULL open and release callbacks From: Hans Verkuil Patch allows v4l2_open and v4l2_release functions return 0 if open and release driver callbacks set to NULL. This will be used in radio drivers. -- Priority: normal Signed-off-by: Hans Verkuil Signed-off-by: Alexey Klimov Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/v4l2-dev.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/v4l2-dev.c b/linux/drivers/media/video/v4l2-dev.c index 2c4d38979..f7e128729 100644 --- a/linux/drivers/media/video/v4l2-dev.c +++ b/linux/drivers/media/video/v4l2-dev.c @@ -267,7 +267,7 @@ static int v4l2_mmap(struct file *filp, struct vm_area_struct *vm) static int v4l2_open(struct inode *inode, struct file *filp) { struct video_device *vdev; - int ret; + int ret = 0; /* Check if the video device is available */ mutex_lock(&videodev_lock); @@ -281,7 +281,9 @@ static int v4l2_open(struct inode *inode, struct file *filp) /* and increase the device refcount */ video_get(vdev); mutex_unlock(&videodev_lock); - ret = vdev->fops->open(filp); + if (vdev->fops->open) + ret = vdev->fops->open(filp); + /* decrease the refcount in case of an error */ if (ret) video_put(vdev); @@ -292,7 +294,10 @@ static int v4l2_open(struct inode *inode, struct file *filp) static int v4l2_release(struct inode *inode, struct file *filp) { struct video_device *vdev = video_devdata(filp); - int ret = vdev->fops->release(filp); + int ret = 0; + + if (vdev->fops->release) + vdev->fops->release(filp); /* decrease the refcount unconditionally since the release() return value is ignored. */ -- cgit v1.2.3 From fd7aa03c43fa93b538f714c99c98f4d6976840b1 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 29 Mar 2009 23:19:54 +0000 Subject: pci-isa radios: remove open and release functions From: Alexey Klimov Patch removes empty open and release functions in pci and isa radio drivers, setting them to NULL. V4L module doesn't call for them due to previous patch. Priority: normal Signed-off-by: Alexey Klimov Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/radio/radio-aimslab.c | 12 ------------ linux/drivers/media/radio/radio-aztech.c | 12 ------------ linux/drivers/media/radio/radio-gemtek-pci.c | 12 ------------ linux/drivers/media/radio/radio-gemtek.c | 11 ----------- linux/drivers/media/radio/radio-maestro.c | 12 ------------ linux/drivers/media/radio/radio-maxiradio.c | 12 ------------ linux/drivers/media/radio/radio-rtrack2.c | 12 ------------ linux/drivers/media/radio/radio-sf16fmi.c | 12 ------------ linux/drivers/media/radio/radio-sf16fmr2.c | 12 ------------ linux/drivers/media/radio/radio-terratec.c | 12 ------------ linux/drivers/media/radio/radio-trust.c | 12 ------------ linux/drivers/media/radio/radio-typhoon.c | 12 ------------ linux/drivers/media/radio/radio-zoltrix.c | 12 ------------ 13 files changed, 155 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/radio/radio-aimslab.c b/linux/drivers/media/radio/radio-aimslab.c index 29834df05..0089e38b1 100644 --- a/linux/drivers/media/radio/radio-aimslab.c +++ b/linux/drivers/media/radio/radio-aimslab.c @@ -356,20 +356,8 @@ static int vidioc_s_audio(struct file *file, void *priv, return a->index ? -EINVAL : 0; } -static int rtrack_open(struct file *file) -{ - return 0; -} - -static int rtrack_release(struct file *file) -{ - return 0; -} - static const struct v4l2_file_operations rtrack_fops = { .owner = THIS_MODULE, - .open = rtrack_open, - .release = rtrack_release, .ioctl = video_ioctl2, }; diff --git a/linux/drivers/media/radio/radio-aztech.c b/linux/drivers/media/radio/radio-aztech.c index 6b4081a51..1ca64a92f 100644 --- a/linux/drivers/media/radio/radio-aztech.c +++ b/linux/drivers/media/radio/radio-aztech.c @@ -319,20 +319,8 @@ static int vidioc_s_ctrl(struct file *file, void *priv, return -EINVAL; } -static int aztech_open(struct file *file) -{ - return 0; -} - -static int aztech_release(struct file *file) -{ - return 0; -} - static const struct v4l2_file_operations aztech_fops = { .owner = THIS_MODULE, - .open = aztech_open, - .release = aztech_release, .ioctl = video_ioctl2, }; diff --git a/linux/drivers/media/radio/radio-gemtek-pci.c b/linux/drivers/media/radio/radio-gemtek-pci.c index 13972c431..64859e9b2 100644 --- a/linux/drivers/media/radio/radio-gemtek-pci.c +++ b/linux/drivers/media/radio/radio-gemtek-pci.c @@ -357,20 +357,8 @@ static struct pci_device_id gemtek_pci_id[] = MODULE_DEVICE_TABLE(pci, gemtek_pci_id); -static int gemtek_pci_open(struct file *file) -{ - return 0; -} - -static int gemtek_pci_release(struct file *file) -{ - return 0; -} - static const struct v4l2_file_operations gemtek_pci_fops = { .owner = THIS_MODULE, - .open = gemtek_pci_open, - .release = gemtek_pci_release, .ioctl = video_ioctl2, }; diff --git a/linux/drivers/media/radio/radio-gemtek.c b/linux/drivers/media/radio/radio-gemtek.c index d991476e8..bc58ce7e2 100644 --- a/linux/drivers/media/radio/radio-gemtek.c +++ b/linux/drivers/media/radio/radio-gemtek.c @@ -376,20 +376,9 @@ static int gemtek_probe(struct gemtek *gt) /* * Video 4 Linux stuff. */ -static int gemtek_open(struct file *file) -{ - return 0; -} - -static int gemtek_release(struct file *file) -{ - return 0; -} static const struct v4l2_file_operations gemtek_fops = { .owner = THIS_MODULE, - .open = gemtek_open, - .release = gemtek_release, .ioctl = video_ioctl2, }; diff --git a/linux/drivers/media/radio/radio-maestro.c b/linux/drivers/media/radio/radio-maestro.c index 387bf416b..603e629e1 100644 --- a/linux/drivers/media/radio/radio-maestro.c +++ b/linux/drivers/media/radio/radio-maestro.c @@ -293,20 +293,8 @@ static int vidioc_s_audio(struct file *file, void *priv, return a->index ? -EINVAL : 0; } -static int maestro_open(struct file *file) -{ - return 0; -} - -static int maestro_release(struct file *file) -{ - return 0; -} - static const struct v4l2_file_operations maestro_fops = { .owner = THIS_MODULE, - .open = maestro_open, - .release = maestro_release, .ioctl = video_ioctl2, }; diff --git a/linux/drivers/media/radio/radio-maxiradio.c b/linux/drivers/media/radio/radio-maxiradio.c index a31ea2f5e..da86c058c 100644 --- a/linux/drivers/media/radio/radio-maxiradio.c +++ b/linux/drivers/media/radio/radio-maxiradio.c @@ -340,20 +340,8 @@ static int vidioc_s_ctrl(struct file *file, void *priv, return -EINVAL; } -static int maxiradio_open(struct file *file) -{ - return 0; -} - -static int maxiradio_release(struct file *file) -{ - return 0; -} - static const struct v4l2_file_operations maxiradio_fops = { .owner = THIS_MODULE, - .open = maxiradio_open, - .release = maxiradio_release, .ioctl = video_ioctl2, }; diff --git a/linux/drivers/media/radio/radio-rtrack2.c b/linux/drivers/media/radio/radio-rtrack2.c index 20153db92..6b02c69f2 100644 --- a/linux/drivers/media/radio/radio-rtrack2.c +++ b/linux/drivers/media/radio/radio-rtrack2.c @@ -261,20 +261,8 @@ static int vidioc_s_audio(struct file *file, void *priv, return a->index ? -EINVAL : 0; } -static int rtrack2_open(struct file *file) -{ - return 0; -} - -static int rtrack2_release(struct file *file) -{ - return 0; -} - static const struct v4l2_file_operations rtrack2_fops = { .owner = THIS_MODULE, - .open = rtrack2_open, - .release = rtrack2_release, .ioctl = video_ioctl2, }; diff --git a/linux/drivers/media/radio/radio-sf16fmi.c b/linux/drivers/media/radio/radio-sf16fmi.c index b517b3671..ae2b3e6a1 100644 --- a/linux/drivers/media/radio/radio-sf16fmi.c +++ b/linux/drivers/media/radio/radio-sf16fmi.c @@ -261,20 +261,8 @@ static int vidioc_s_audio(struct file *file, void *priv, return a->index ? -EINVAL : 0; } -static int fmi_open(struct file *file) -{ - return 0; -} - -static int fmi_release(struct file *file) -{ - return 0; -} - static const struct v4l2_file_operations fmi_fops = { .owner = THIS_MODULE, - .open = fmi_open, - .release = fmi_release, .ioctl = video_ioctl2, }; diff --git a/linux/drivers/media/radio/radio-sf16fmr2.c b/linux/drivers/media/radio/radio-sf16fmr2.c index 65e303dba..bb92b329c 100644 --- a/linux/drivers/media/radio/radio-sf16fmr2.c +++ b/linux/drivers/media/radio/radio-sf16fmr2.c @@ -378,20 +378,8 @@ static int vidioc_s_audio(struct file *file, void *priv, return a->index ? -EINVAL : 0; } -static int fmr2_open(struct file *file) -{ - return 0; -} - -static int fmr2_release(struct file *file) -{ - return 0; -} - static const struct v4l2_file_operations fmr2_fops = { .owner = THIS_MODULE, - .open = fmr2_open, - .release = fmr2_release, .ioctl = video_ioctl2, }; diff --git a/linux/drivers/media/radio/radio-terratec.c b/linux/drivers/media/radio/radio-terratec.c index 0bec5f7e2..3e5436faf 100644 --- a/linux/drivers/media/radio/radio-terratec.c +++ b/linux/drivers/media/radio/radio-terratec.c @@ -333,20 +333,8 @@ static int vidioc_s_audio(struct file *file, void *priv, return a->index ? -EINVAL : 0; } -static int terratec_open(struct file *file) -{ - return 0; -} - -static int terratec_release(struct file *file) -{ - return 0; -} - static const struct v4l2_file_operations terratec_fops = { .owner = THIS_MODULE, - .open = terratec_open, - .release = terratec_release, .ioctl = video_ioctl2, }; diff --git a/linux/drivers/media/radio/radio-trust.c b/linux/drivers/media/radio/radio-trust.c index 8b925adb5..67a462d66 100644 --- a/linux/drivers/media/radio/radio-trust.c +++ b/linux/drivers/media/radio/radio-trust.c @@ -339,20 +339,8 @@ static int vidioc_s_audio(struct file *file, void *priv, return a->index ? -EINVAL : 0; } -static int trust_open(struct file *file) -{ - return 0; -} - -static int trust_release(struct file *file) -{ - return 0; -} - static const struct v4l2_file_operations trust_fops = { .owner = THIS_MODULE, - .open = trust_open, - .release = trust_release, .ioctl = video_ioctl2, }; diff --git a/linux/drivers/media/radio/radio-typhoon.c b/linux/drivers/media/radio/radio-typhoon.c index 98e4ce142..23dece5e4 100644 --- a/linux/drivers/media/radio/radio-typhoon.c +++ b/linux/drivers/media/radio/radio-typhoon.c @@ -315,20 +315,8 @@ static int vidioc_log_status(struct file *file, void *priv) return 0; } -static int typhoon_open(struct file *file) -{ - return 0; -} - -static int typhoon_release(struct file *file) -{ - return 0; -} - static const struct v4l2_file_operations typhoon_fops = { .owner = THIS_MODULE, - .open = typhoon_open, - .release = typhoon_release, .ioctl = video_ioctl2, }; diff --git a/linux/drivers/media/radio/radio-zoltrix.c b/linux/drivers/media/radio/radio-zoltrix.c index 0ae5f0d19..c06fbb4fc 100644 --- a/linux/drivers/media/radio/radio-zoltrix.c +++ b/linux/drivers/media/radio/radio-zoltrix.c @@ -371,21 +371,9 @@ static int vidioc_s_audio(struct file *file, void *priv, return a->index ? -EINVAL : 0; } -static int zoltrix_open(struct file *file) -{ - return 0; -} - -static int zoltrix_release(struct file *file) -{ - return 0; -} - static const struct v4l2_file_operations zoltrix_fops = { .owner = THIS_MODULE, - .open = zoltrix_open, - .release = zoltrix_release, .ioctl = video_ioctl2, }; -- cgit v1.2.3 From d1daa96b2ee8d633ec40e440c2a97c6719cd8b7a Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 30 Mar 2009 12:08:30 +0200 Subject: au8522: remove unused I2C_DRIVERID From: Hans Verkuil I2C_DRIVERIDs are no longer needed with v4l2_subdev and will be removed from the kernel soon. Priority: normal Signed-off-by: Hans Verkuil CC: Devin Heitmueller --- linux/drivers/media/dvb/frontends/au8522_decoder.c | 1 - 1 file changed, 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/frontends/au8522_decoder.c b/linux/drivers/media/dvb/frontends/au8522_decoder.c index 70af9cda7..326f94d1e 100644 --- a/linux/drivers/media/dvb/frontends/au8522_decoder.c +++ b/linux/drivers/media/dvb/frontends/au8522_decoder.c @@ -837,7 +837,6 @@ MODULE_DEVICE_TABLE(i2c, au8522_id); #endif static struct v4l2_i2c_driver_data v4l2_i2c_data = { .name = "au8522", - .driverid = I2C_DRIVERID_AU8522, .probe = au8522_probe, .remove = au8522_remove, #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) -- cgit v1.2.3 From 6f7ed0b73229342a0abbeb7764f97f565ba1e188 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 30 Mar 2009 12:16:08 +0200 Subject: cx25840: fix 'unused variable' warning. From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/cx25840/cx25840-core.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/cx25840/cx25840-core.c b/linux/drivers/media/video/cx25840/cx25840-core.c index be270ea5b..67971cc3c 100644 --- a/linux/drivers/media/video/cx25840/cx25840-core.c +++ b/linux/drivers/media/video/cx25840/cx25840-core.c @@ -942,8 +942,6 @@ static int cx25840_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) static int cx25840_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) { - struct i2c_client *client = v4l2_get_subdevdata(sd); - switch (fmt->type) { case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: return cx25840_vbi_g_fmt(sd, fmt); -- cgit v1.2.3 From 430e534136bd77613cd4c8dcb8e318b64b4ffaf6 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 30 Mar 2009 13:03:02 +0200 Subject: saa7191: tuner ops wasn't set. From: Hans Verkuil The tuner ops pointer wasn't set, so s_std never worked here. Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/saa7191.c | 1 + 1 file changed, 1 insertion(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/saa7191.c b/linux/drivers/media/video/saa7191.c index 9df505e0f..0a14ab6db 100644 --- a/linux/drivers/media/video/saa7191.c +++ b/linux/drivers/media/video/saa7191.c @@ -603,6 +603,7 @@ static const struct v4l2_subdev_video_ops saa7191_video_ops = { static const struct v4l2_subdev_ops saa7191_ops = { .core = &saa7191_core_ops, .video = &saa7191_video_ops, + .tuner = &saa7191_tuner_ops, }; static int saa7191_probe(struct i2c_client *client, -- cgit v1.2.3 From ba50529dc5eb313e2709f555b9d29ec90e11e40f Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 30 Mar 2009 08:17:03 -0300 Subject: cx88: Fix compilation breakage for kernels older than 2.6.22 From: Mauro Carvalho Chehab Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/cx88/cx88-core.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/cx88/cx88-core.c b/linux/drivers/media/video/cx88/cx88-core.c index ceaedf352..faee9d885 100644 --- a/linux/drivers/media/video/cx88/cx88-core.c +++ b/linux/drivers/media/video/cx88/cx88-core.c @@ -1088,11 +1088,13 @@ void cx88_core_put(struct cx88_core *core, struct pci_dev *pci) mutex_lock(&devlist); cx88_ir_fini(core); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 22) if (0 == core->i2c_rc) { if (core->i2c_rtc) i2c_unregister_device(core->i2c_rtc); i2c_del_adapter(&core->i2c_adap); } +#endif list_del(&core->devlist); iounmap(core->lmmio); cx88_devcount--; -- cgit v1.2.3 From 19e35224611a4b1aaf8f5d121233d3c81d920d44 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 30 Mar 2009 08:18:10 -0300 Subject: msp3400: use the V4L2 header since no V4L1 code is there From: Mauro Carvalho Chehab Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/msp3400-driver.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/msp3400-driver.c b/linux/drivers/media/video/msp3400-driver.c index fdcc1c1c5..fbe69a62d 100644 --- a/linux/drivers/media/video/msp3400-driver.c +++ b/linux/drivers/media/video/msp3400-driver.c @@ -57,7 +57,7 @@ #else #include #endif -#include +#include #include #include #include -- cgit v1.2.3 From 8dd3ceb79cec4a833fbc9fd654b7e71e9548d331 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 30 Mar 2009 07:59:56 -0700 Subject: patch: s2255drv driver removal problem fixed From: Dean Anderson This patch fixes kfree problem on driver removal, fixes streamoff problem and removes unnecessary videobuf_waiton from free_buffer function. Signed-off-by: Dean Anderson Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/s2255drv.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/s2255drv.c b/linux/drivers/media/video/s2255drv.c index edfac2f9e..c13aa2cc8 100644 --- a/linux/drivers/media/video/s2255drv.c +++ b/linux/drivers/media/video/s2255drv.c @@ -723,7 +723,6 @@ static void free_buffer(struct videobuf_queue *vq, struct s2255_buffer *buf) { dprintk(4, "%s\n", __func__); - videobuf_waiton(&buf->vb, 0, 0); videobuf_vmalloc_free(&buf->vb); buf->vb.state = VIDEOBUF_NEEDS_INIT; } @@ -1325,7 +1324,6 @@ static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) { - int res; struct s2255_fh *fh = priv; struct s2255_dev *dev = fh->dev; @@ -1339,9 +1337,7 @@ static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) return -EINVAL; } s2255_stop_acquire(dev, fh->channel); - res = videobuf_streamoff(&fh->vb_vidq); - if (res < 0) - return res; + videobuf_streamoff(&fh->vb_vidq); res_free(dev, fh); return 0; } @@ -1708,13 +1704,13 @@ static void s2255_destroy(struct kref *kref) kfree(dev->fw_data); usb_put_dev(dev->udev); dprintk(1, "%s", __func__); - kfree(dev); while (!list_empty(&s2255_devlist)) { list = s2255_devlist.next; list_del(list); } mutex_unlock(&dev->open_lock); + kfree(dev); } static int s2255_close(struct file *file) -- cgit v1.2.3 From 65c8976997f4e297c5d082a1c80ffc80d67bfda5 Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Mon, 30 Mar 2009 23:57:51 +0300 Subject: af9015: remove wrong definitions From: Antti Palosaari Remove wrong GPIO definitions. GPIOs used by AF9015 are property of the AF9013 demodulator and are coming from there. Priority: normal Signed-off-by: Antti Palosaari --- linux/drivers/media/dvb/dvb-usb/af9015.h | 8 -------- 1 file changed, 8 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/dvb-usb/af9015.h b/linux/drivers/media/dvb/dvb-usb/af9015.h index 5c44bad28..8d81a17c1 100644 --- a/linux/drivers/media/dvb/dvb-usb/af9015.h +++ b/linux/drivers/media/dvb/dvb-usb/af9015.h @@ -64,14 +64,6 @@ #define AF9015_EEPROM_OFFSET (AF9015_EEPROM_SAW_BW2 - AF9015_EEPROM_SAW_BW1) -#define AF9015_GPIO_ON (1 << 0) -#define AF9015_GPIO_EN (1 << 1) -#define AF9015_GPIO_O (1 << 2) -#define AF9015_GPIO_I (1 << 3) - -#define AF9015_GPIO_TUNER_ON (AF9015_GPIO_ON|AF9015_GPIO_EN) -#define AF9015_GPIO_TUNER_OFF (AF9015_GPIO_ON|AF9015_GPIO_EN|AF9015_GPIO_O) - struct req_t { u8 cmd; /* [0] */ /* seq */ /* [1] */ -- cgit v1.2.3 From 868c60ab580a0b1d3939600a6b9522886982528b Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 30 Mar 2009 21:36:19 -0400 Subject: fix misspelling of kconfig option From: Kyle McMartin CUSTOMISE appears to be the one actually defined... Signed-off-by: Kyle McMartin Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/dvb-usb/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/dvb-usb/Kconfig b/linux/drivers/media/dvb/dvb-usb/Kconfig index 6103caad1..089ba4513 100644 --- a/linux/drivers/media/dvb/dvb-usb/Kconfig +++ b/linux/drivers/media/dvb/dvb-usb/Kconfig @@ -309,6 +309,6 @@ config DVB_USB_CE6230 tristate "Intel CE6230 DVB-T USB2.0 support" depends on DVB_USB && EXPERIMENTAL select DVB_ZL10353 - select MEDIA_TUNER_MXL5005S if !MEDIA_TUNER_CUSTOMIZE + select MEDIA_TUNER_MXL5005S if !MEDIA_TUNER_CUSTOMISE help Say Y here to support the Intel CE6230 DVB-T USB2.0 receiver -- cgit v1.2.3 From 6392c3238a48546c25590608a5a96a48e387e0d3 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Tue, 31 Mar 2009 08:44:21 +0200 Subject: pxa_camera: Enforce YUV422P frame sizes to be 16 multiples From: Robert Jarzmik Due to DMA constraints, the DMA chain always transfers bytes from the QCI fifos to memory in 8 bytes units. In planar formats, that could mean 0 padding between Y and U plane (and between U and V plane), which is against YUV422P standard. Therefore, a frame size is required to be a multiple of 16 (so U plane size is a multiple of 8). It is enforced in try_fmt() and set_fmt() primitives, be aligning height then width on 4 multiples as need be, to reach a 16 multiple. Signed-off-by: Robert Jarzmik Signed-off-by: Guennadi Liakhovetski --- drivers/media/video/pxa_camera.c | 32 +++++++++++++++++++++----------- 1 files changed, 21 insertions(+), 11 deletions(-) --- linux/drivers/media/video/pxa_camera.c | 32 +++++++++++++++++++++----------- 1 file changed, 21 insertions(+), 11 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/pxa_camera.c b/linux/drivers/media/video/pxa_camera.c index d1aa540ba..5e60c3c31 100644 --- a/linux/drivers/media/video/pxa_camera.c +++ b/linux/drivers/media/video/pxa_camera.c @@ -172,6 +172,13 @@ CICR0_PERRM | CICR0_QDM | CICR0_CDM | CICR0_SOFM | \ CICR0_EOFM | CICR0_FOM) +/* + * YUV422P picture size should be a multiple of 16, so the heuristic aligns + * height, width on 4 byte boundaries to reach the 16 multiple for the size. + */ +#define YUV422P_X_Y_ALIGN 4 +#define YUV422P_SIZE_ALIGN YUV422P_X_Y_ALIGN * YUV422P_X_Y_ALIGN + /* * Structures */ @@ -246,20 +253,11 @@ static int pxa_videobuf_setup(struct videobuf_queue *vq, unsigned int *count, unsigned int *size) { struct soc_camera_device *icd = vq->priv_data; - struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); - struct pxa_camera_dev *pcdev = ici->priv; dev_dbg(&icd->dev, "count=%d, size=%d\n", *count, *size); - /* planar capture requires Y, U and V buffers to be page aligned */ - if (pcdev->channels == 3) { - *size = PAGE_ALIGN(icd->width * icd->height); /* Y pages */ - *size += PAGE_ALIGN(icd->width * icd->height / 2); /* U pages */ - *size += PAGE_ALIGN(icd->width * icd->height / 2); /* V pages */ - } else { - *size = icd->width * icd->height * - ((icd->current_fmt->depth + 7) >> 3); - } + *size = roundup(icd->width * icd->height * + ((icd->current_fmt->depth + 7) >> 3), 8); if (0 == *count) *count = 32; @@ -1275,6 +1273,18 @@ static int pxa_camera_try_fmt(struct soc_camera_device *icd, pix->width = 2048; pix->width &= ~0x01; + /* + * YUV422P planar format requires images size to be a 16 bytes + * multiple. If not, zeros will be inserted between Y and U planes, and + * U and V planes, and YUV422P standard would be violated. + */ + if (xlate->host_fmt->fourcc == V4L2_PIX_FMT_YUV422P) { + if (!IS_ALIGNED(pix->width * pix->height, YUV422P_SIZE_ALIGN)) + pix->height = ALIGN(pix->height, YUV422P_X_Y_ALIGN); + if (!IS_ALIGNED(pix->width * pix->height, YUV422P_SIZE_ALIGN)) + pix->width = ALIGN(pix->width, YUV422P_X_Y_ALIGN); + } + pix->bytesperline = pix->width * DIV_ROUND_UP(xlate->host_fmt->depth, 8); pix->sizeimage = pix->height * pix->bytesperline; -- cgit v1.2.3 From 953d03eaa6a48726291126a512da56846b71f3ec Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Tue, 31 Mar 2009 08:44:21 +0200 Subject: pxa_camera: Remove YUV planar formats hole From: Robert Jarzmik All planes were PAGE aligned (ie. 4096 bytes aligned). This is not consistent with YUV422 format, which requires Y, U and V planes glued together. The new implementation forces the alignement on 8 bytes (DMA requirement), which is almost always the case (granted by width x height being a multiple of 8). The test cases include tests in both YUV422 and RGB565 : - a picture of size 111 x 111 (cross RAM pages example) - a picture of size 1023 x 4 in (under 1 RAM page) - a picture of size 1024 x 4 in (exactly 1 RAM page) - a picture of size 1025 x 4 in (over 1 RAM page) - a picture of size 1280 x 1024 (many RAM pages) Signed-off-by: Robert Jarzmik Signed-off-by: Guennadi Liakhovetski --- drivers/media/video/pxa_camera.c | 145 +++++++++++++++++++++++++++---------- 1 files changed, 106 insertions(+), 39 deletions(-) --- linux/drivers/media/video/pxa_camera.c | 143 ++++++++++++++++++++++++--------- 1 file changed, 105 insertions(+), 38 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/pxa_camera.c b/linux/drivers/media/video/pxa_camera.c index 5e60c3c31..e8ad3c08d 100644 --- a/linux/drivers/media/video/pxa_camera.c +++ b/linux/drivers/media/video/pxa_camera.c @@ -297,19 +297,63 @@ static void free_buffer(struct videobuf_queue *vq, struct pxa_buffer *buf) buf->vb.state = VIDEOBUF_NEEDS_INIT; } +static int calculate_dma_sglen(struct scatterlist *sglist, int sglen, + int sg_first_ofs, int size) +{ + int i, offset, dma_len, xfer_len; + struct scatterlist *sg; + + offset = sg_first_ofs; + for_each_sg(sglist, sg, sglen, i) { + dma_len = sg_dma_len(sg); + + /* PXA27x Developer's Manual 27.4.4.1: round up to 8 bytes */ + xfer_len = roundup(min(dma_len - offset, size), 8); + + size = max(0, size - xfer_len); + offset = 0; + if (size == 0) + break; + } + + BUG_ON(size != 0); + return i + 1; +} + +/** + * pxa_init_dma_channel - init dma descriptors + * @pcdev: pxa camera device + * @buf: pxa buffer to find pxa dma channel + * @dma: dma video buffer + * @channel: dma channel (0 => 'Y', 1 => 'U', 2 => 'V') + * @cibr: camera Receive Buffer Register + * @size: bytes to transfer + * @sg_first: first element of sg_list + * @sg_first_ofs: offset in first element of sg_list + * + * Prepares the pxa dma descriptors to transfer one camera channel. + * Beware sg_first and sg_first_ofs are both input and output parameters. + * + * Returns 0 or -ENOMEM if no coherent memory is available + */ static int pxa_init_dma_channel(struct pxa_camera_dev *pcdev, struct pxa_buffer *buf, struct videobuf_dmabuf *dma, int channel, - int sglen, int sg_start, int cibr, - unsigned int size) + int cibr, int size, + struct scatterlist **sg_first, int *sg_first_ofs) { struct pxa_cam_dma *pxa_dma = &buf->dmas[channel]; - int i; + struct scatterlist *sg; + int i, offset, sglen; + int dma_len = 0, xfer_len = 0; if (pxa_dma->sg_cpu) dma_free_coherent(pcdev->dev, pxa_dma->sg_size, pxa_dma->sg_cpu, pxa_dma->sg_dma); + sglen = calculate_dma_sglen(*sg_first, dma->sglen, + *sg_first_ofs, size); + pxa_dma->sg_size = (sglen + 1) * sizeof(struct pxa_dma_desc); pxa_dma->sg_cpu = dma_alloc_coherent(pcdev->dev, pxa_dma->sg_size, &pxa_dma->sg_dma, GFP_KERNEL); @@ -317,28 +361,54 @@ static int pxa_init_dma_channel(struct pxa_camera_dev *pcdev, return -ENOMEM; pxa_dma->sglen = sglen; + offset = *sg_first_ofs; - for (i = 0; i < sglen; i++) { - int sg_i = sg_start + i; - struct scatterlist *sg = dma->sglist; - unsigned int dma_len = sg_dma_len(&sg[sg_i]), xfer_len; + dev_dbg(pcdev->dev, "DMA: sg_first=%p, sglen=%d, ofs=%d, dma.desc=%x\n", + *sg_first, sglen, *sg_first_ofs, pxa_dma->sg_dma); - pxa_dma->sg_cpu[i].dsadr = pcdev->res->start + cibr; - pxa_dma->sg_cpu[i].dtadr = sg_dma_address(&sg[sg_i]); + + for_each_sg(*sg_first, sg, sglen, i) { + dma_len = sg_dma_len(sg); /* PXA27x Developer's Manual 27.4.4.1: round up to 8 bytes */ - xfer_len = (min(dma_len, size) + 7) & ~7; + xfer_len = roundup(min(dma_len - offset, size), 8); + size = max(0, size - xfer_len); + + pxa_dma->sg_cpu[i].dsadr = pcdev->res->start + cibr; + pxa_dma->sg_cpu[i].dtadr = sg_dma_address(sg) + offset; pxa_dma->sg_cpu[i].dcmd = DCMD_FLOWSRC | DCMD_BURST8 | DCMD_INCTRGADDR | xfer_len; - size -= dma_len; pxa_dma->sg_cpu[i].ddadr = pxa_dma->sg_dma + (i + 1) * sizeof(struct pxa_dma_desc); + + dev_vdbg(pcdev->dev, "DMA: desc.%08x->@phys=0x%08x, len=%d\n", + pxa_dma->sg_dma + i * sizeof(struct pxa_dma_desc), + sg_dma_address(sg) + offset, xfer_len); + offset = 0; + + if (size == 0) + break; } pxa_dma->sg_cpu[sglen - 1].ddadr = DDADR_STOP; pxa_dma->sg_cpu[sglen - 1].dcmd |= DCMD_ENDIRQEN; + /* + * Handle 1 special case : + * - in 3 planes (YUV422P format), we might finish with xfer_len equal + * to dma_len (end on PAGE boundary). In this case, the sg element + * for next plane should be the next after the last used to store the + * last scatter gather RAM page + */ + if (xfer_len >= dma_len) { + *sg_first_ofs = xfer_len - dma_len; + *sg_first = sg_next(sg); + } else { + *sg_first_ofs = xfer_len; + *sg_first = sg; + } + return 0; } @@ -350,7 +420,6 @@ static int pxa_videobuf_prepare(struct videobuf_queue *vq, struct pxa_camera_dev *pcdev = ici->priv; struct pxa_buffer *buf = container_of(vb, struct pxa_buffer, vb); int ret; - int sglen_y, sglen_yu = 0, sglen_u = 0, sglen_v = 0; int size_y, size_u = 0, size_v = 0; dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__, @@ -389,53 +458,51 @@ static int pxa_videobuf_prepare(struct videobuf_queue *vq, } if (vb->state == VIDEOBUF_NEEDS_INIT) { - unsigned int size = vb->size; + int size = vb->size; + int next_ofs = 0; struct videobuf_dmabuf *dma = videobuf_to_dma(vb); + struct scatterlist *sg; ret = videobuf_iolock(vq, vb, NULL); if (ret) goto fail; if (pcdev->channels == 3) { - /* FIXME the calculations should be more precise */ - sglen_y = dma->sglen / 2; - sglen_u = sglen_v = dma->sglen / 4 + 1; - sglen_yu = sglen_y + sglen_u; size_y = size / 2; size_u = size_v = size / 4; } else { - sglen_y = dma->sglen; size_y = size; } - /* init DMA for Y channel */ - ret = pxa_init_dma_channel(pcdev, buf, dma, 0, sglen_y, - 0, 0x28, size_y); + sg = dma->sglist; + /* init DMA for Y channel */ + ret = pxa_init_dma_channel(pcdev, buf, dma, 0, CIBR0, size_y, + &sg, &next_ofs); if (ret) { dev_err(pcdev->dev, "DMA initialization for Y/RGB failed\n"); goto fail; } - if (pcdev->channels == 3) { - /* init DMA for U channel */ - ret = pxa_init_dma_channel(pcdev, buf, dma, 1, sglen_u, - sglen_y, 0x30, size_u); - if (ret) { - dev_err(pcdev->dev, - "DMA initialization for U failed\n"); - goto fail_u; - } + /* init DMA for U channel */ + if (size_u) + ret = pxa_init_dma_channel(pcdev, buf, dma, 1, CIBR1, + size_u, &sg, &next_ofs); + if (ret) { + dev_err(pcdev->dev, + "DMA initialization for U failed\n"); + goto fail_u; + } - /* init DMA for V channel */ - ret = pxa_init_dma_channel(pcdev, buf, dma, 2, sglen_v, - sglen_yu, 0x38, size_v); - if (ret) { - dev_err(pcdev->dev, - "DMA initialization for V failed\n"); - goto fail_v; - } + /* init DMA for V channel */ + if (size_v) + ret = pxa_init_dma_channel(pcdev, buf, dma, 2, CIBR2, + size_v, &sg, &next_ofs); + if (ret) { + dev_err(pcdev->dev, + "DMA initialization for V failed\n"); + goto fail_v; } vb->state = VIDEOBUF_PREPARED; -- cgit v1.2.3 From 25c1a20a39b9a75aaef1dc3b2bcbf3276856d915 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Tue, 31 Mar 2009 08:44:21 +0200 Subject: pxa_camera: Redesign DMA handling From: Robert Jarzmik The DMA transfers in pxa_camera showed some weaknesses in multiple queued buffers context : - poll/select problem The bug shows up with capture_example tool from v4l2 hg tree. The process just "stalls" on a "select timeout". - multiple buffers DMA starting When multiple buffers were queued, the DMA channels were always started right away. This is not optimal, as a special case appears when the first EOF was not yet reached, and the DMA channels were prematurely started. - Maintainability DMA code was a bit obfuscated. Rationalize the code to be easily maintainable by anyone. - DMA hot chaining DMA is not stopped anymore to queue a buffer, the buffer is queued with DMA running. As a tribute, a corner case exists where chaining happens while DMA finishes the chain, and the capture is restarted to deal with the missed link buffer. This patch attemps to address these issues / improvements. Signed-off-by: Robert Jarzmik Signed-off-by: Guennadi Liakhovetski --- Documentation/video4linux/pxa_camera.txt | 125 ++++++++++++ drivers/media/video/pxa_camera.c | 319 ++++++++++++++++++------------ 2 files changed, 316 insertions(+), 128 deletions(-) create mode 100644 Documentation/video4linux/pxa_camera.txt --- linux/drivers/media/video/pxa_camera.c | 319 ++++++++++++++++++++------------- 1 file changed, 191 insertions(+), 128 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/pxa_camera.c b/linux/drivers/media/video/pxa_camera.c index e8ad3c08d..03a9dc69a 100644 --- a/linux/drivers/media/video/pxa_camera.c +++ b/linux/drivers/media/video/pxa_camera.c @@ -379,6 +379,10 @@ static int pxa_init_dma_channel(struct pxa_camera_dev *pcdev, pxa_dma->sg_cpu[i].dtadr = sg_dma_address(sg) + offset; pxa_dma->sg_cpu[i].dcmd = DCMD_FLOWSRC | DCMD_BURST8 | DCMD_INCTRGADDR | xfer_len; +#ifdef DEBUG + if (!i) + pxa_dma->sg_cpu[i].dcmd |= DCMD_STARTIRQEN; +#endif pxa_dma->sg_cpu[i].ddadr = pxa_dma->sg_dma + (i + 1) * sizeof(struct pxa_dma_desc); @@ -391,8 +395,8 @@ static int pxa_init_dma_channel(struct pxa_camera_dev *pcdev, break; } - pxa_dma->sg_cpu[sglen - 1].ddadr = DDADR_STOP; - pxa_dma->sg_cpu[sglen - 1].dcmd |= DCMD_ENDIRQEN; + pxa_dma->sg_cpu[sglen].ddadr = DDADR_STOP; + pxa_dma->sg_cpu[sglen].dcmd = DCMD_FLOWSRC | DCMD_BURST8 | DCMD_ENDIRQEN; /* * Handle 1 special case : @@ -412,6 +416,20 @@ static int pxa_init_dma_channel(struct pxa_camera_dev *pcdev, return 0; } +static void pxa_videobuf_set_actdma(struct pxa_camera_dev *pcdev, + struct pxa_buffer *buf) +{ + buf->active_dma = DMA_Y; + if (pcdev->channels == 3) + buf->active_dma |= DMA_U | DMA_V; +} + +/* + * Please check the DMA prepared buffer structure in : + * Documentation/video4linux/pxa_camera.txt + * Please check also in pxa_camera_check_link_miss() to understand why DMA chain + * modification while DMA chain is running will work anyway. + */ static int pxa_videobuf_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb, enum v4l2_field field) { @@ -509,9 +527,7 @@ static int pxa_videobuf_prepare(struct videobuf_queue *vq, } buf->inwork = 0; - buf->active_dma = DMA_Y; - if (pcdev->channels == 3) - buf->active_dma |= DMA_U | DMA_V; + pxa_videobuf_set_actdma(pcdev, buf); return 0; @@ -528,6 +544,99 @@ out: return ret; } +/** + * pxa_dma_start_channels - start DMA channel for active buffer + * @pcdev: pxa camera device + * + * Initialize DMA channels to the beginning of the active video buffer, and + * start these channels. + */ +static void pxa_dma_start_channels(struct pxa_camera_dev *pcdev) +{ + int i; + struct pxa_buffer *active; + + active = pcdev->active; + + for (i = 0; i < pcdev->channels; i++) { + dev_dbg(pcdev->dev, "%s (channel=%d) ddadr=%08x\n", __func__, + i, active->dmas[i].sg_dma); + DDADR(pcdev->dma_chans[i]) = active->dmas[i].sg_dma; + DCSR(pcdev->dma_chans[i]) = DCSR_RUN; + } +} + +static void pxa_dma_stop_channels(struct pxa_camera_dev *pcdev) +{ + int i; + + for (i = 0; i < pcdev->channels; i++) { + dev_dbg(pcdev->dev, "%s (channel=%d)\n", __func__, i); + DCSR(pcdev->dma_chans[i]) = 0; + } +} + +static void pxa_dma_update_sg_tail(struct pxa_camera_dev *pcdev, + struct pxa_buffer *buf) +{ + int i; + + for (i = 0; i < pcdev->channels; i++) + pcdev->sg_tail[i] = buf->dmas[i].sg_cpu + buf->dmas[i].sglen; +} + +static void pxa_dma_add_tail_buf(struct pxa_camera_dev *pcdev, + struct pxa_buffer *buf) +{ + int i; + struct pxa_dma_desc *buf_last_desc; + + for (i = 0; i < pcdev->channels; i++) { + buf_last_desc = buf->dmas[i].sg_cpu + buf->dmas[i].sglen; + buf_last_desc->ddadr = DDADR_STOP; + + if (!pcdev->sg_tail[i]) + continue; + pcdev->sg_tail[i]->ddadr = buf->dmas[i].sg_dma; + } + + pxa_dma_update_sg_tail(pcdev, buf); +} + +/** + * pxa_camera_start_capture - start video capturing + * @pcdev: camera device + * + * Launch capturing. DMA channels should not be active yet. They should get + * activated at the end of frame interrupt, to capture only whole frames, and + * never begin the capture of a partial frame. + */ +static void pxa_camera_start_capture(struct pxa_camera_dev *pcdev) +{ + unsigned long cicr0, cifr; + + dev_dbg(pcdev->dev, "%s\n", __func__); + /* Reset the FIFOs */ + cifr = __raw_readl(pcdev->base + CIFR) | CIFR_RESET_F; + __raw_writel(cifr, pcdev->base + CIFR); + /* Enable End-Of-Frame Interrupt */ + cicr0 = __raw_readl(pcdev->base + CICR0) | CICR0_ENB; + cicr0 &= ~CICR0_EOFM; + __raw_writel(cicr0, pcdev->base + CICR0); +} + +static void pxa_camera_stop_capture(struct pxa_camera_dev *pcdev) +{ + unsigned long cicr0; + + pxa_dma_stop_channels(pcdev); + + cicr0 = __raw_readl(pcdev->base + CICR0) & ~CICR0_ENB; + __raw_writel(cicr0, pcdev->base + CICR0); + + dev_dbg(pcdev->dev, "%s\n", __func__); +} + static void pxa_videobuf_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) { @@ -535,81 +644,20 @@ static void pxa_videobuf_queue(struct videobuf_queue *vq, struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); struct pxa_camera_dev *pcdev = ici->priv; struct pxa_buffer *buf = container_of(vb, struct pxa_buffer, vb); - struct pxa_buffer *active; unsigned long flags; - int i; - dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__, - vb, vb->baddr, vb->bsize); + dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %d active=%p\n", __func__, + vb, vb->baddr, vb->bsize, pcdev->active); + spin_lock_irqsave(&pcdev->lock, flags); list_add_tail(&vb->queue, &pcdev->capture); vb->state = VIDEOBUF_ACTIVE; - active = pcdev->active; + pxa_dma_add_tail_buf(pcdev, buf); - if (!active) { - unsigned long cifr, cicr0; - - cifr = __raw_readl(pcdev->base + CIFR) | CIFR_RESET_F; - __raw_writel(cifr, pcdev->base + CIFR); - - for (i = 0; i < pcdev->channels; i++) { - DDADR(pcdev->dma_chans[i]) = buf->dmas[i].sg_dma; - DCSR(pcdev->dma_chans[i]) = DCSR_RUN; - pcdev->sg_tail[i] = buf->dmas[i].sg_cpu + buf->dmas[i].sglen - 1; - } - - pcdev->active = buf; - - cicr0 = __raw_readl(pcdev->base + CICR0) | CICR0_ENB; - __raw_writel(cicr0, pcdev->base + CICR0); - } else { - struct pxa_cam_dma *buf_dma; - struct pxa_cam_dma *act_dma; - int nents; - - for (i = 0; i < pcdev->channels; i++) { - buf_dma = &buf->dmas[i]; - act_dma = &active->dmas[i]; - nents = buf_dma->sglen; - - /* Stop DMA engine */ - DCSR(pcdev->dma_chans[i]) = 0; - - /* Add the descriptors we just initialized to - the currently running chain */ - pcdev->sg_tail[i]->ddadr = buf_dma->sg_dma; - pcdev->sg_tail[i] = buf_dma->sg_cpu + buf_dma->sglen - 1; - - /* Setup a dummy descriptor with the DMA engines current - * state - */ - buf_dma->sg_cpu[nents].dsadr = - pcdev->res->start + 0x28 + i*8; /* CIBRx */ - buf_dma->sg_cpu[nents].dtadr = - DTADR(pcdev->dma_chans[i]); - buf_dma->sg_cpu[nents].dcmd = - DCMD(pcdev->dma_chans[i]); - - if (DDADR(pcdev->dma_chans[i]) == DDADR_STOP) { - /* The DMA engine is on the last - descriptor, set the next descriptors - address to the descriptors we just - initialized */ - buf_dma->sg_cpu[nents].ddadr = buf_dma->sg_dma; - } else { - buf_dma->sg_cpu[nents].ddadr = - DDADR(pcdev->dma_chans[i]); - } - - /* The next descriptor is the dummy descriptor */ - DDADR(pcdev->dma_chans[i]) = buf_dma->sg_dma + nents * - sizeof(struct pxa_dma_desc); - - DCSR(pcdev->dma_chans[i]) = DCSR_RUN; - } - } + if (!pcdev->active) + pxa_camera_start_capture(pcdev); spin_unlock_irqrestore(&pcdev->lock, flags); } @@ -647,7 +695,7 @@ static void pxa_camera_wakeup(struct pxa_camera_dev *pcdev, struct videobuf_buffer *vb, struct pxa_buffer *buf) { - unsigned long cicr0; + int i; /* _init is used to debug races, see comment in pxa_camera_reqbufs() */ list_del_init(&vb->queue); @@ -655,15 +703,13 @@ static void pxa_camera_wakeup(struct pxa_camera_dev *pcdev, do_gettimeofday(&vb->ts); vb->field_count++; wake_up(&vb->done); + dev_dbg(pcdev->dev, "%s dequeud buffer (vb=0x%p)\n", __func__, vb); if (list_empty(&pcdev->capture)) { + pxa_camera_stop_capture(pcdev); pcdev->active = NULL; - DCSR(pcdev->dma_chans[0]) = 0; - DCSR(pcdev->dma_chans[1]) = 0; - DCSR(pcdev->dma_chans[2]) = 0; - - cicr0 = __raw_readl(pcdev->base + CICR0) & ~CICR0_ENB; - __raw_writel(cicr0, pcdev->base + CICR0); + for (i = 0; i < pcdev->channels; i++) + pcdev->sg_tail[i] = NULL; return; } @@ -671,6 +717,35 @@ static void pxa_camera_wakeup(struct pxa_camera_dev *pcdev, struct pxa_buffer, vb.queue); } +/** + * pxa_camera_check_link_miss - check missed DMA linking + * @pcdev: camera device + * + * The DMA chaining is done with DMA running. This means a tiny temporal window + * remains, where a buffer is queued on the chain, while the chain is already + * stopped. This means the tailed buffer would never be transfered by DMA. + * This function restarts the capture for this corner case, where : + * - DADR() == DADDR_STOP + * - a videobuffer is queued on the pcdev->capture list + * + * Please check the "DMA hot chaining timeslice issue" in + * Documentation/video4linux/pxa_camera.txt + * + * Context: should only be called within the dma irq handler + */ +static void pxa_camera_check_link_miss(struct pxa_camera_dev *pcdev) +{ + int i, is_dma_stopped = 1; + + for (i = 0; i < pcdev->channels; i++) + if (DDADR(pcdev->dma_chans[i]) != DDADR_STOP) + is_dma_stopped = 0; + dev_dbg(pcdev->dev, "%s : top queued buffer=%p, dma_stopped=%d\n", + __func__, pcdev->active, is_dma_stopped); + if (pcdev->active && is_dma_stopped) + pxa_camera_start_capture(pcdev); +} + static void pxa_camera_dma_irq(int channel, struct pxa_camera_dev *pcdev, enum pxa_camera_active_dma act_dma) { @@ -678,19 +753,23 @@ static void pxa_camera_dma_irq(int channel, struct pxa_camera_dev *pcdev, unsigned long flags; u32 status, camera_status, overrun; struct videobuf_buffer *vb; - unsigned long cifr, cicr0; spin_lock_irqsave(&pcdev->lock, flags); status = DCSR(channel); - DCSR(channel) = status | DCSR_ENDINTR; + DCSR(channel) = status; + + camera_status = __raw_readl(pcdev->base + CISR); + overrun = CISR_IFO_0; + if (pcdev->channels == 3) + overrun |= CISR_IFO_1 | CISR_IFO_2; if (status & DCSR_BUSERR) { dev_err(pcdev->dev, "DMA Bus Error IRQ!\n"); goto out; } - if (!(status & DCSR_ENDINTR)) { + if (!(status & (DCSR_ENDINTR | DCSR_STARTINTR))) { dev_err(pcdev->dev, "Unknown DMA IRQ source, " "status: 0x%08x\n", status); goto out; @@ -701,38 +780,28 @@ static void pxa_camera_dma_irq(int channel, struct pxa_camera_dev *pcdev, goto out; } - camera_status = __raw_readl(pcdev->base + CISR); - overrun = CISR_IFO_0; - if (pcdev->channels == 3) - overrun |= CISR_IFO_1 | CISR_IFO_2; - if (camera_status & overrun) { - dev_dbg(pcdev->dev, "FIFO overrun! CISR: %x\n", camera_status); - /* Stop the Capture Interface */ - cicr0 = __raw_readl(pcdev->base + CICR0) & ~CICR0_ENB; - __raw_writel(cicr0, pcdev->base + CICR0); - - /* Stop DMA */ - DCSR(channel) = 0; - /* Reset the FIFOs */ - cifr = __raw_readl(pcdev->base + CIFR) | CIFR_RESET_F; - __raw_writel(cifr, pcdev->base + CIFR); - /* Enable End-Of-Frame Interrupt */ - cicr0 &= ~CICR0_EOFM; - __raw_writel(cicr0, pcdev->base + CICR0); - /* Restart the Capture Interface */ - __raw_writel(cicr0 | CICR0_ENB, pcdev->base + CICR0); - goto out; - } - vb = &pcdev->active->vb; buf = container_of(vb, struct pxa_buffer, vb); WARN_ON(buf->inwork || list_empty(&vb->queue)); - dev_dbg(pcdev->dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__, - vb, vb->baddr, vb->bsize); - buf->active_dma &= ~act_dma; - if (!buf->active_dma) - pxa_camera_wakeup(pcdev, vb, buf); + dev_dbg(pcdev->dev, "%s channel=%d %s%s(vb=0x%p) dma.desc=%x\n", + __func__, channel, status & DCSR_STARTINTR ? "SOF " : "", + status & DCSR_ENDINTR ? "EOF " : "", vb, DDADR(channel)); + + if (status & DCSR_ENDINTR) { + if (camera_status & overrun) { + dev_dbg(pcdev->dev, "FIFO overrun! CISR: %x\n", + camera_status); + pxa_camera_stop_capture(pcdev); + pxa_camera_start_capture(pcdev); + goto out; + } + buf->active_dma &= ~act_dma; + if (!buf->active_dma) { + pxa_camera_wakeup(pcdev, vb, buf); + pxa_camera_check_link_miss(pcdev); + } + } out: spin_unlock_irqrestore(&pcdev->lock, flags); @@ -861,6 +930,8 @@ static irqreturn_t pxa_camera_irq(int irq, void *data) { struct pxa_camera_dev *pcdev = data; unsigned long status, cicr0; + struct pxa_buffer *buf; + struct videobuf_buffer *vb; status = __raw_readl(pcdev->base + CISR); dev_dbg(pcdev->dev, "Camera interrupt status 0x%lx\n", status); @@ -871,12 +942,14 @@ static irqreturn_t pxa_camera_irq(int irq, void *data) __raw_writel(status, pcdev->base + CISR); if (status & CISR_EOF) { - int i; - for (i = 0; i < pcdev->channels; i++) { - DDADR(pcdev->dma_chans[i]) = - pcdev->active->dmas[i].sg_dma; - DCSR(pcdev->dma_chans[i]) = DCSR_RUN; - } + pcdev->active = list_first_entry(&pcdev->capture, + struct pxa_buffer, vb.queue); + vb = &pcdev->active->vb; + buf = container_of(vb, struct pxa_buffer, vb); + pxa_videobuf_set_actdma(pcdev, buf); + + pxa_dma_start_channels(pcdev); + cicr0 = __raw_readl(pcdev->base + CICR0) | CICR0_EOFM; __raw_writel(cicr0, pcdev->base + CICR0); } @@ -1459,18 +1532,8 @@ static int pxa_camera_resume(struct soc_camera_device *icd) ret = pcdev->icd->ops->resume(pcdev->icd); /* Restart frame capture if active buffer exists */ - if (!ret && pcdev->active) { - unsigned long cifr, cicr0; - - /* Reset the FIFOs */ - cifr = __raw_readl(pcdev->base + CIFR) | CIFR_RESET_F; - __raw_writel(cifr, pcdev->base + CIFR); - - cicr0 = __raw_readl(pcdev->base + CICR0); - cicr0 &= ~CICR0_EOFM; /* Enable End-Of-Frame Interrupt */ - cicr0 |= CICR0_ENB; /* Restart the Capture Interface */ - __raw_writel(cicr0, pcdev->base + CICR0); - } + if (!ret && pcdev->active) + pxa_camera_start_capture(pcdev); return ret; } -- cgit v1.2.3 From 760482414d848730ddfb7bbf28d43c7e829f3eac Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Tue, 31 Mar 2009 08:44:22 +0200 Subject: pxa_camera: Fix overrun condition on last buffer From: Robert Jarzmik The last buffer queued will often overrun, as the DMA chain is finished, and the time the dma irq handler is activated, the QCI fifos are filled by the sensor. The fix is to ignore the overrun condition on the last queued buffer, and restart the capture only on intermediate buffers of the chain. Moreover, a fix was added to the very unlikely condition where in YUV422P mode, one channel overruns while another completes at the very same time. The capture is restarted after the overrun as before, but the other channel completion is now ignored. Signed-off-by: Robert Jarzmik Signed-off-by: Guennadi Liakhovetski --- drivers/media/video/pxa_camera.c | 25 ++++++++++++++++++++----- 1 files changed, 20 insertions(+), 5 deletions(-) --- linux/drivers/media/video/pxa_camera.c | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/pxa_camera.c b/linux/drivers/media/video/pxa_camera.c index 03a9dc69a..318d5f61b 100644 --- a/linux/drivers/media/video/pxa_camera.c +++ b/linux/drivers/media/video/pxa_camera.c @@ -634,6 +634,7 @@ static void pxa_camera_stop_capture(struct pxa_camera_dev *pcdev) cicr0 = __raw_readl(pcdev->base + CICR0) & ~CICR0_ENB; __raw_writel(cicr0, pcdev->base + CICR0); + pcdev->active = NULL; dev_dbg(pcdev->dev, "%s\n", __func__); } @@ -707,7 +708,6 @@ static void pxa_camera_wakeup(struct pxa_camera_dev *pcdev, if (list_empty(&pcdev->capture)) { pxa_camera_stop_capture(pcdev); - pcdev->active = NULL; for (i = 0; i < pcdev->channels; i++) pcdev->sg_tail[i] = NULL; return; @@ -775,10 +775,20 @@ static void pxa_camera_dma_irq(int channel, struct pxa_camera_dev *pcdev, goto out; } - if (!pcdev->active) { - dev_err(pcdev->dev, "DMA End IRQ with no active buffer!\n"); + /* + * pcdev->active should not be NULL in DMA irq handler. + * + * But there is one corner case : if capture was stopped due to an + * overrun of channel 1, and at that same channel 2 was completed. + * + * When handling the overrun in DMA irq for channel 1, we'll stop the + * capture and restart it (and thus set pcdev->active to NULL). But the + * DMA irq handler will already be pending for channel 2. So on entering + * the DMA irq handler for channel 2 there will be no active buffer, yet + * that is normal. + */ + if (!pcdev->active) goto out; - } vb = &pcdev->active->vb; buf = container_of(vb, struct pxa_buffer, vb); @@ -789,7 +799,12 @@ static void pxa_camera_dma_irq(int channel, struct pxa_camera_dev *pcdev, status & DCSR_ENDINTR ? "EOF " : "", vb, DDADR(channel)); if (status & DCSR_ENDINTR) { - if (camera_status & overrun) { + /* + * It's normal if the last frame creates an overrun, as there + * are no more DMA descriptors to fetch from QCI fifos + */ + if (camera_status & overrun && + !list_is_last(pcdev->capture.next, &pcdev->capture)) { dev_dbg(pcdev->dev, "FIFO overrun! CISR: %x\n", camera_status); pxa_camera_stop_capture(pcdev); -- cgit v1.2.3 From 16606c768bcdfd4d0ce36f8263a81aac8324732f Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Tue, 31 Mar 2009 08:44:22 +0200 Subject: pxa-camera: simplify the .buf_queue path by merging two loops From: Guennadi Liakhovetski pxa_dma_update_sg_tail() is called only once, runs exactly the same loop as the caller and has to recalculate the last element in an sg-list, that the caller has already calculated. Eliminate redundancy by merging the two loops and re-using the calculated pointer. This also saves a bit of performance which is always good during video-capture. Signed-off-by: Guennadi Liakhovetski Acked-by: Robert Jarzmik --- drivers/media/video/pxa_camera.c | 20 ++++++-------------- 1 files changed, 6 insertions(+), 14 deletions(-) --- linux/drivers/media/video/pxa_camera.c | 20 ++++++-------------- 1 file changed, 6 insertions(+), 14 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/pxa_camera.c b/linux/drivers/media/video/pxa_camera.c index 318d5f61b..98825d631 100644 --- a/linux/drivers/media/video/pxa_camera.c +++ b/linux/drivers/media/video/pxa_camera.c @@ -576,15 +576,6 @@ static void pxa_dma_stop_channels(struct pxa_camera_dev *pcdev) } } -static void pxa_dma_update_sg_tail(struct pxa_camera_dev *pcdev, - struct pxa_buffer *buf) -{ - int i; - - for (i = 0; i < pcdev->channels; i++) - pcdev->sg_tail[i] = buf->dmas[i].sg_cpu + buf->dmas[i].sglen; -} - static void pxa_dma_add_tail_buf(struct pxa_camera_dev *pcdev, struct pxa_buffer *buf) { @@ -595,12 +586,13 @@ static void pxa_dma_add_tail_buf(struct pxa_camera_dev *pcdev, buf_last_desc = buf->dmas[i].sg_cpu + buf->dmas[i].sglen; buf_last_desc->ddadr = DDADR_STOP; - if (!pcdev->sg_tail[i]) - continue; - pcdev->sg_tail[i]->ddadr = buf->dmas[i].sg_dma; - } + if (pcdev->sg_tail[i]) + /* Link the new buffer to the old tail */ + pcdev->sg_tail[i]->ddadr = buf->dmas[i].sg_dma; - pxa_dma_update_sg_tail(pcdev, buf); + /* Update the channel tail */ + pcdev->sg_tail[i] = buf_last_desc; + } } /** -- cgit v1.2.3 From 2adb7ebfe8e864f77d3f58a65523a9766f86137a Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Tue, 31 Mar 2009 08:44:22 +0200 Subject: ov772x: wrong pointer for soc_camera_link is modified From: Kuninori Morimoto priv->client->dev.platrom_data mean ov772x_camera_info in ov772x driver. So, struct soc_camera_link doesn't exist there. This patch modify this bug. Signed-off-by: Kuninori Morimoto Signed-off-by: Guennadi Liakhovetski --- drivers/media/video/ov772x.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) --- linux/drivers/media/video/ov772x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/ov772x.c b/linux/drivers/media/video/ov772x.c index cde3a1019..d3e0bd30e 100644 --- a/linux/drivers/media/video/ov772x.c +++ b/linux/drivers/media/video/ov772x.c @@ -670,7 +670,7 @@ static int ov772x_set_bus_param(struct soc_camera_device *icd, static unsigned long ov772x_query_bus_param(struct soc_camera_device *icd) { struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd); - struct soc_camera_link *icl = priv->client->dev.platform_data; + struct soc_camera_link *icl = &priv->info->link; unsigned long flags = SOCAM_PCLK_SAMPLE_RISING | SOCAM_MASTER | SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_DATA_ACTIVE_HIGH | priv->info->buswidth; -- cgit v1.2.3 From 894ef336d9eaaf5528b4e796e4d2c86b45c59b9b Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Tue, 31 Mar 2009 08:44:22 +0200 Subject: soc-camera: fix breakage caused by 1fa5ae857bb14f6046205171d98506d8112dd74e From: Guennadi Liakhovetski soc-camera re-uses struct devices multiple times in calls to device_register(), therefore it has to reset the embedded struct kobject to avoid the "tried to init an initialized object" error, which then also erases its name. Now with the transition to kobject's name for device names, we have to re-initialise the name before each call to device_register(). Signed-off-by: Guennadi Liakhovetski --- drivers/media/video/soc_camera.c | 6 ++++-- 1 files changed, 4 insertions(+), 2 deletions(-) --- linux/drivers/media/video/soc_camera.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/soc_camera.c b/linux/drivers/media/video/soc_camera.c index da6d224eb..9e432d390 100644 --- a/linux/drivers/media/video/soc_camera.c +++ b/linux/drivers/media/video/soc_camera.c @@ -765,7 +765,10 @@ static int soc_camera_s_register(struct file *file, void *fh, static int device_register_link(struct soc_camera_device *icd) { - int ret = device_register(&icd->dev); + int ret = dev_set_name(&icd->dev, "%u-%u", icd->iface, icd->devnum); + + if (!ret) + ret = device_register(&icd->dev); if (ret < 0) { /* Prevent calling device_unregister() */ @@ -1061,7 +1064,6 @@ int soc_camera_device_register(struct soc_camera_device *icd) icd->devnum = num; icd->dev.bus = &soc_camera_bus_type; - dev_set_name(&icd->dev, "%u-%u", icd->iface, icd->devnum); icd->dev.release = dummy_release; icd->use_count = 0; -- cgit v1.2.3 From 0cd492de264ff13ccca9ebe6722775938c387392 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Tue, 31 Mar 2009 08:44:22 +0200 Subject: mt9m001: fix advertised pixel clock polarity From: Guennadi Liakhovetski MT9M001 datasheet says, that the data is ready on the falling edge of the pixel clock, but the driver wrongly sets the SOCAM_PCLK_SAMPLE_RISING flag. Changing this doesn't seem to produce any visible difference, still, it is better to comply to the datasheet. Reported-by: Sascha Oppermann Signed-off-by: Guennadi Liakhovetski --- drivers/media/video/mt9m001.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) --- linux/drivers/media/video/mt9m001.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/mt9m001.c b/linux/drivers/media/video/mt9m001.c index e3dab2119..83f3cae47 100644 --- a/linux/drivers/media/video/mt9m001.c +++ b/linux/drivers/media/video/mt9m001.c @@ -207,7 +207,7 @@ static unsigned long mt9m001_query_bus_param(struct soc_camera_device *icd) struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd); struct soc_camera_link *icl = mt9m001->client->dev.platform_data; /* MT9M001 has all capture_format parameters fixed */ - unsigned long flags = SOCAM_PCLK_SAMPLE_RISING | + unsigned long flags = SOCAM_PCLK_SAMPLE_FALLING | SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_DATA_ACTIVE_HIGH | SOCAM_MASTER; -- cgit v1.2.3 From 5e8385995e4d6c1811a1b8e5e819094658cdb77c Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Tue, 31 Mar 2009 08:44:22 +0200 Subject: ov772x: add edge contrl support From: Kuninori Morimoto Signed-off-by: Kuninori Morimoto Signed-off-by: Guennadi Liakhovetski --- drivers/media/video/ov772x.c | 63 +++++++++++++++++++++++++++++++++++++++-- include/media/ov772x.h | 35 +++++++++++++++++++++++ 2 files changed, 94 insertions(+), 4 deletions(-) --- linux/drivers/media/video/ov772x.c | 63 +++++++++++++++++++++++++++++++++++--- 1 file changed, 59 insertions(+), 4 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/ov772x.c b/linux/drivers/media/video/ov772x.c index d3e0bd30e..b17a7400d 100644 --- a/linux/drivers/media/video/ov772x.c +++ b/linux/drivers/media/video/ov772x.c @@ -169,11 +169,11 @@ #define GAM15 0x8C /* Gamma Curve 15th segment input end point */ #define SLOP 0x8D /* Gamma curve highest segment slope */ #define DNSTH 0x8E /* De-noise threshold */ -#define EDGE0 0x8F /* Edge enhancement control 0 */ -#define EDGE1 0x90 /* Edge enhancement control 1 */ +#define EDGE_STRNGT 0x8F /* Edge strength control when manual mode */ +#define EDGE_TRSHLD 0x90 /* Edge threshold control when manual mode */ #define DNSOFF 0x91 /* Auto De-noise threshold control */ -#define EDGE2 0x92 /* Edge enhancement strength low point control */ -#define EDGE3 0x93 /* Edge enhancement strength high point control */ +#define EDGE_UPPER 0x92 /* Edge strength upper limit when Auto mode */ +#define EDGE_LOWER 0x93 /* Edge strength lower limit when Auto mode */ #define MTX1 0x94 /* Matrix coefficient 1 */ #define MTX2 0x95 /* Matrix coefficient 2 */ #define MTX3 0x96 /* Matrix coefficient 3 */ @@ -358,6 +358,14 @@ #define VOSZ_VGA 0xF0 #define VOSZ_QVGA 0x78 +/* DSPAUTO (DSP Auto Function ON/OFF Control) */ +#define AWB_ACTRL 0x80 /* AWB auto threshold control */ +#define DENOISE_ACTRL 0x40 /* De-noise auto threshold control */ +#define EDGE_ACTRL 0x20 /* Edge enhancement auto strength control */ +#define UV_ACTRL 0x10 /* UV adjust auto slope control */ +#define SCAL0_ACTRL 0x08 /* Auto scaling factor control */ +#define SCAL1_2_ACTRL 0x04 /* Auto scaling factor control */ + /* * ID */ @@ -815,6 +823,53 @@ static int ov772x_set_params(struct ov772x_priv *priv, u32 width, u32 height, */ ov772x_reset(priv->client); + /* + * Edge Ctrl + */ + if (priv->info->edgectrl.strength & OV772X_MANUAL_EDGE_CTRL) { + + /* + * Manual Edge Control Mode + * + * Edge auto strength bit is set by default. + * Remove it when manual mode. + */ + + ret = ov772x_mask_set(priv->client, DSPAUTO, EDGE_ACTRL, 0x00); + if (ret < 0) + goto ov772x_set_fmt_error; + + ret = ov772x_mask_set(priv->client, + EDGE_TRSHLD, EDGE_THRESHOLD_MASK, + priv->info->edgectrl.threshold); + if (ret < 0) + goto ov772x_set_fmt_error; + + ret = ov772x_mask_set(priv->client, + EDGE_STRNGT, EDGE_STRENGTH_MASK, + priv->info->edgectrl.strength); + if (ret < 0) + goto ov772x_set_fmt_error; + + } else if (priv->info->edgectrl.upper > priv->info->edgectrl.lower) { + /* + * Auto Edge Control Mode + * + * set upper and lower limit + */ + ret = ov772x_mask_set(priv->client, + EDGE_UPPER, EDGE_UPPER_MASK, + priv->info->edgectrl.upper); + if (ret < 0) + goto ov772x_set_fmt_error; + + ret = ov772x_mask_set(priv->client, + EDGE_LOWER, EDGE_LOWER_MASK, + priv->info->edgectrl.lower); + if (ret < 0) + goto ov772x_set_fmt_error; + } + /* * set size format */ -- cgit v1.2.3 From fdab553be22b01acd8124650ed75da649169596f Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Tue, 31 Mar 2009 23:01:02 +0300 Subject: af9015: add support for AverMedia AVerTV Volar Black HD (A850) From: Antti Palosaari Add USB ID (07ca:850a) and configuration hack for AverMedia AVerTV Volar Black HD (A850) DVB-T USB stick. Priority: normal Signed-off-by: Antti Palosaari Tested-by: Olivier MENUEL Tested-by: Thomas Renard --- linux/drivers/media/dvb/dvb-usb/af9015.c | 24 +++++++++++++++++++++++- linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h | 1 + 2 files changed, 24 insertions(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/dvb-usb/af9015.c b/linux/drivers/media/dvb/dvb-usb/af9015.c index e7a8f61da..5feed970a 100644 --- a/linux/drivers/media/dvb/dvb-usb/af9015.c +++ b/linux/drivers/media/dvb/dvb-usb/af9015.c @@ -994,6 +994,21 @@ error: if (ret) err("eeprom read failed:%d", ret); + /* AverMedia AVerTV Volar Black HD (A850) device have bad EEPROM + content :-( Override some wrong values here. */ + if (le16_to_cpu(udev->descriptor.idVendor) == USB_VID_AVERMEDIA && + le16_to_cpu(udev->descriptor.idProduct) == USB_PID_AVERMEDIA_A850) { + deb_info("%s: AverMedia A850: overriding config\n", __func__); + /* disable dual mode */ + af9015_config.dual_mode = 0; + /* disable 2nd adapter */ + for (i = 0; i < af9015_properties_count; i++) + af9015_properties[i].num_adapters = 1; + + /* set correct IF */ + af9015_af9013_config[0].tuner_if = 4570; + } + return ret; } @@ -1252,6 +1267,7 @@ static struct usb_device_id af9015_usb_table[] = { {USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_395U_2)}, {USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_395U_3)}, {USB_DEVICE(USB_VID_AFATECH, USB_PID_TREKSTOR_DVBT)}, + {USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A850)}, {0}, }; MODULE_DEVICE_TABLE(usb, af9015_usb_table); @@ -1416,7 +1432,7 @@ static struct dvb_usb_device_properties af9015_properties[] = { .i2c_algo = &af9015_i2c_algo, - .num_device_descs = 8, + .num_device_descs = 9, .devices = { { .name = "Xtensions XD-380", @@ -1461,6 +1477,12 @@ static struct dvb_usb_device_properties af9015_properties[] = { .cold_ids = {&af9015_usb_table[19], NULL}, .warm_ids = {NULL}, }, + { + .name = "AverMedia AVerTV Volar Black HD " \ + "(A850)", + .cold_ids = {&af9015_usb_table[20], NULL}, + .warm_ids = {NULL}, + }, } } }; 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 cd22d6dde..7031bafe6 100644 --- a/linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h +++ b/linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h @@ -168,6 +168,7 @@ #define USB_PID_AVERMEDIA_VOLAR_X 0xa815 #define USB_PID_AVERMEDIA_VOLAR_X_2 0x8150 #define USB_PID_AVERMEDIA_A309 0xa309 +#define USB_PID_AVERMEDIA_A850 0x850a #define USB_PID_TECHNOTREND_CONNECT_S2400 0x3006 #define USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY 0x005a #define USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY_2 0x0081 -- cgit v1.2.3 From 5a77a70cc69ef5dc3da63db495a588ec1f3934bc Mon Sep 17 00:00:00 2001 From: Douglas Schilling Landgraf Date: Tue, 31 Mar 2009 17:10:58 -0300 Subject: em28xx: convert to v4l2_subdev From: Douglas Schilling Landgraf Converted em28xx driver to v4l2_subdev. Thanks to Hans Verkuil for helping this conversion. Priority: normal Signed-off-by: Douglas Schilling Landgraf Signed-off-by: Hans Verkuil --- linux/drivers/media/video/em28xx/em28xx-cards.c | 145 +++++++++++++++++++----- linux/drivers/media/video/em28xx/em28xx-core.c | 9 +- linux/drivers/media/video/em28xx/em28xx-i2c.c | 72 +----------- linux/drivers/media/video/em28xx/em28xx-video.c | 78 ++++++------- linux/drivers/media/video/em28xx/em28xx.h | 10 +- 5 files changed, 174 insertions(+), 140 deletions(-) (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 6b4a204a9..56c27b745 100644 --- a/linux/drivers/media/video/em28xx/em28xx-cards.c +++ b/linux/drivers/media/video/em28xx/em28xx-cards.c @@ -32,6 +32,8 @@ #include #include #include +#include +#include #include #include #include @@ -1305,6 +1307,7 @@ struct em28xx_board em28xx_boards[] = { [EM2820_BOARD_COMPRO_VIDEOMATE_FORYOU] = { .name = "Compro VideoMate ForYou/Stereo", .tuner_type = TUNER_LG_PAL_NEW_TAPC, + .tvaudio_addr = 0xb0, .tda9887_conf = TDA9887_PRESENT, .decoder = EM28XX_TVP5150, .adecoder = EM28XX_TVAUDIO, @@ -1513,6 +1516,24 @@ static struct em28xx_hash_table em28xx_i2c_hash[] = { {0xc51200e3, EM2820_BOARD_GADMEI_TVR200, TUNER_LG_PAL_NEW_TAPC}, }; +/* I2C possible address to saa7115, tvp5150, msp3400, tvaudio */ +static unsigned short saa711x_addrs[] = { + 0x4a >> 1, 0x48 >> 1, /* SAA7111, SAA7111A and SAA7113 */ + 0x42 >> 1, 0x40 >> 1, /* SAA7114, SAA7115 and SAA7118 */ + I2C_CLIENT_END }; + +static unsigned short tvp5150_addrs[] = { + 0xb8 >> 1, + 0xba >> 1, + I2C_CLIENT_END +}; + +static unsigned short msp3400_addrs[] = { + 0x80 >> 1, + 0x88 >> 1, + I2C_CLIENT_END +}; + int em28xx_tuner_callback(void *ptr, int component, int command, int arg) { int rc = 0; @@ -1741,31 +1762,55 @@ static void em28xx_setup_xc3028(struct em28xx *dev, struct xc2028_ctrl *ctl) } } -static void em28xx_config_tuner(struct em28xx *dev) +static void em28xx_tuner_setup(struct em28xx *dev) { - struct v4l2_priv_tun_config xc2028_cfg; struct tuner_setup tun_setup; struct v4l2_frequency f; if (dev->tuner_type == TUNER_ABSENT) return; + memset(&tun_setup, 0, sizeof(tun_setup)); + tun_setup.mode_mask = T_ANALOG_TV | T_RADIO; - tun_setup.type = dev->tuner_type; - tun_setup.addr = dev->tuner_addr; tun_setup.tuner_callback = em28xx_tuner_callback; - em28xx_i2c_call_clients(dev, TUNER_SET_TYPE_ADDR, &tun_setup); + if (dev->board.radio.type) { + tun_setup.type = dev->board.radio.type; + tun_setup.addr = dev->board.radio_addr; + + v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_type_addr, &tun_setup); + } + + if ((dev->tuner_type != TUNER_ABSENT) && (dev->tuner_type)) { + tun_setup.type = dev->tuner_type; + tun_setup.addr = dev->tuner_addr; + + v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_type_addr, &tun_setup); + } + + if (dev->tda9887_conf) { + struct v4l2_priv_tun_config tda9887_cfg; + + tda9887_cfg.tuner = TUNER_TDA9887; + tda9887_cfg.priv = &dev->tda9887_conf; + + v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_config, &tda9887_cfg); + } if (dev->tuner_type == TUNER_XC2028) { + struct v4l2_priv_tun_config xc2028_cfg; struct xc2028_ctrl ctl; + memset(&xc2028_cfg, 0, sizeof(xc2028_cfg)); + memset(&ctl, 0, sizeof(ctl)); + em28xx_setup_xc3028(dev, &ctl); xc2028_cfg.tuner = TUNER_XC2028; xc2028_cfg.priv = &ctl; - em28xx_i2c_call_clients(dev, TUNER_SET_CONFIG, &xc2028_cfg); + v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_config, &xc2028_cfg); } /* configure tuner */ @@ -1773,7 +1818,7 @@ static void em28xx_config_tuner(struct em28xx *dev) f.type = V4L2_TUNER_ANALOG_TV; f.frequency = 9076; /* just a magic number */ dev->ctl_freq = f.frequency; - em28xx_i2c_call_clients(dev, VIDIOC_S_FREQUENCY, &f); + v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_frequency, &f); } static int em28xx_hint_board(struct em28xx *dev) @@ -1980,22 +2025,50 @@ void em28xx_card_setup(struct em28xx *dev) if (tuner >= 0) dev->tuner_type = tuner; -#ifdef CONFIG_MODULES /* request some modules */ if (dev->board.has_msp34xx) - request_module("msp3400"); + v4l2_i2c_new_probed_subdev(&dev->i2c_adap, "msp3400", + "msp3400", msp3400_addrs); + if (dev->board.decoder == EM28XX_SAA711X) - request_module("saa7115"); + v4l2_i2c_new_probed_subdev(&dev->i2c_adap, "saa7115", + "saa7115_auto", saa711x_addrs); + if (dev->board.decoder == EM28XX_TVP5150) - request_module("tvp5150"); - if (dev->board.tuner_type != TUNER_ABSENT) - request_module("tuner"); - if (dev->board.adecoder == EM28XX_TVAUDIO) - request_module("tvaudio"); -#endif + v4l2_i2c_new_probed_subdev(&dev->i2c_adap, "tvp5150", + "tvp5150", tvp5150_addrs); - em28xx_config_tuner(dev); + if (dev->board.adecoder == EM28XX_TVAUDIO) + v4l2_i2c_new_subdev(&dev->i2c_adap, "tvaudio", + "tvaudio", dev->board.tvaudio_addr); + + if (dev->board.tuner_type != TUNER_ABSENT) { + int has_demod = (dev->tda9887_conf & TDA9887_PRESENT); + + if (dev->board.radio.type) + v4l2_i2c_new_subdev(&dev->i2c_adap, "tuner", "tuner", + dev->board.radio_addr); + + if (has_demod) + v4l2_i2c_new_probed_subdev(&dev->i2c_adap, "tuner", + "tuner", v4l2_i2c_tuner_addrs(ADDRS_DEMOD)); + if (dev->tuner_addr == 0) { + enum v4l2_i2c_tuner_type type = + has_demod ? ADDRS_TV_WITH_DEMOD : ADDRS_TV; + struct v4l2_subdev *sd; + + sd = v4l2_i2c_new_probed_subdev(&dev->i2c_adap, "tuner", + "tuner", v4l2_i2c_tuner_addrs(type)); + + if (sd) + dev->tuner_addr = v4l2_i2c_subdev_addr(sd); + } else { + v4l2_i2c_new_subdev(&dev->i2c_adap, "tuner", + "tuner", dev->tuner_addr); + } + } + em28xx_tuner_setup(dev); em28xx_ir_init(dev); } @@ -2055,6 +2128,9 @@ void em28xx_release_resources(struct em28xx *dev) em28xx_remove_from_devlist(dev); em28xx_i2c_unregister(dev); + + v4l2_device_unregister(&dev->v4l2_dev); + usb_put_dev(dev->udev); /* Mark device as unused */ @@ -2099,9 +2175,16 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, } } + retval = v4l2_device_register(&dev->udev->dev, &dev->v4l2_dev); + if (retval < 0) { + em28xx_errdev("Call to v4l2_device_register() failed!\n"); + return retval; + } + /* register i2c bus */ errCode = em28xx_i2c_register(dev); if (errCode < 0) { + v4l2_device_unregister(&dev->v4l2_dev); em28xx_errdev("%s: em28xx_i2c_register - errCode [%d]!\n", __func__, errCode); return errCode; @@ -2113,6 +2196,7 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, /* Configure audio */ errCode = em28xx_audio_setup(dev); if (errCode < 0) { + v4l2_device_unregister(&dev->v4l2_dev); em28xx_errdev("%s: Error while setting audio - errCode [%d]!\n", __func__, errCode); } @@ -2160,7 +2244,7 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, em28xx_init_extension(dev); /* Save some power by putting tuner to sleep */ - em28xx_i2c_call_clients(dev, TUNER_SET_STANDBY, NULL); + v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_standby, 0); return 0; @@ -2179,7 +2263,7 @@ static int em28xx_usb_probe(struct usb_interface *interface, struct usb_device *udev; struct usb_interface *uif; struct em28xx *dev = NULL; - int retval = -ENODEV; + int retval; int i, nr, ifnum, isoc_pipe; char *speed; char descr[255] = ""; @@ -2201,7 +2285,8 @@ static int em28xx_usb_probe(struct usb_interface *interface, interface->altsetting[0].desc.bInterfaceClass); em28xx_devused &= ~(1<cur_altsetting->endpoint[0].desc; @@ -2234,7 +2319,8 @@ static int em28xx_usb_probe(struct usb_interface *interface, "interface not used by the driver\n"); em28xx_devused &= ~(1<name, 29, "em28xx #%d", nr); @@ -2312,7 +2400,8 @@ static int em28xx_usb_probe(struct usb_interface *interface, em28xx_errdev("out of memory!\n"); em28xx_devused &= ~(1<num_alt ; i++) { @@ -2331,8 +2420,7 @@ static int em28xx_usb_probe(struct usb_interface *interface, if (retval) { em28xx_devused &= ~(1<devno); kfree(dev); - - return retval; + goto err; } /* save our data pointer in this interface device */ @@ -2346,6 +2434,9 @@ static int em28xx_usb_probe(struct usb_interface *interface, mutex_unlock(&dev->lock); return 0; + +err: + return retval; } /* @@ -2371,6 +2462,8 @@ static void em28xx_usb_disconnect(struct usb_interface *interface) wake_up_interruptible_all(&dev->open); + v4l2_device_disconnect(&dev->v4l2_dev); + if (dev->users) { em28xx_warn ("device /dev/video%d is open! Deregistration and memory " diff --git a/linux/drivers/media/video/em28xx/em28xx-core.c b/linux/drivers/media/video/em28xx/em28xx-core.c index 4edd3870e..08eb11e72 100644 --- a/linux/drivers/media/video/em28xx/em28xx-core.c +++ b/linux/drivers/media/video/em28xx/em28xx-core.c @@ -1030,11 +1030,12 @@ void em28xx_wake_i2c(struct em28xx *dev) struct v4l2_routing route; int zero = 0; - route.input = INPUT(dev->ctl_input)->vmux; + route.input = INPUT(dev->ctl_input)->vmux; route.output = 0; - em28xx_i2c_call_clients(dev, VIDIOC_INT_RESET, &zero); - em28xx_i2c_call_clients(dev, VIDIOC_INT_S_VIDEO_ROUTING, &route); - em28xx_i2c_call_clients(dev, VIDIOC_STREAMON, NULL); + + v4l2_device_call_all(&dev->v4l2_dev, 0, core, reset, zero); + v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_routing, &route); + v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_stream, 0); } /* diff --git a/linux/drivers/media/video/em28xx/em28xx-i2c.c b/linux/drivers/media/video/em28xx/em28xx-i2c.c index e9abb2769..24456cebd 100644 --- a/linux/drivers/media/video/em28xx/em28xx-i2c.c +++ b/linux/drivers/media/video/em28xx/em28xx-i2c.c @@ -459,70 +459,15 @@ static u32 functionality(struct i2c_adapter *adap) 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 0x86: - case 0x84: - case 0x96: - case 0x94: - { - struct v4l2_priv_tun_config tda9887_cfg; - - struct tuner_setup tun_setup; - - tun_setup.mode_mask = T_ANALOG_TV | T_RADIO; - tun_setup.type = TUNER_TDA9887; - tun_setup.addr = client->addr; - - em28xx_i2c_call_clients(dev, TUNER_SET_TYPE_ADDR, - &tun_setup); - - tda9887_cfg.tuner = TUNER_TDA9887; - tda9887_cfg.priv = &dev->tda9887_conf; - em28xx_i2c_call_clients(dev, TUNER_SET_CONFIG, - &tda9887_cfg); - break; - } - case 0x42: - dprintk1(1, "attach_inform: saa7114 detected.\n"); - break; - case 0x4a: - dprintk1(1, "attach_inform: saa7113 detected.\n"); - break; - case 0xa0: - dprintk1(1, "attach_inform: eeprom detected.\n"); - break; case 0x60: case 0x8e: - { - struct IR_i2c *ir = i2c_get_clientdata(client); - dprintk1(1, "attach_inform: IR detected (%s).\n", - ir->phys); + dprintk1(1, "attach_inform: IR detected (%s).\n", ir->phys); em28xx_set_ir(dev, ir); break; } - case 0x80: - case 0x88: - dprintk1(1, "attach_inform: msp34xx detected.\n"); - break; - case 0xb8: - case 0xba: - dprintk1(1, "attach_inform: tvp5150 detected.\n"); - break; - - case 0xb0: - dprintk1(1, "attach_inform: tda9874 detected\n"); - break; - - default: - if (!dev->tuner_addr) - dev->tuner_addr = client->addr; - - dprintk1(1, "attach inform: detected I2C address %x\n", - client->addr << 1); - dprintk1(1, "driver id %d\n", client->driver->id); - - } return 0; } @@ -537,7 +482,9 @@ static struct i2c_algorithm em28xx_algo = { static struct i2c_adapter em28xx_adap_template = { .owner = THIS_MODULE, +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22) .class = I2C_CLASS_TV_ANALOG, +#endif .name = "em28xx", .id = I2C_HW_B_EM28XX, .algo = &em28xx_algo, @@ -597,16 +544,6 @@ void em28xx_do_i2c_scan(struct em28xx *dev) ARRAY_SIZE(i2c_devicelist), 32); } -/* - * em28xx_i2c_call_clients() - * send commands to all attached i2c devices - */ -void em28xx_i2c_call_clients(struct em28xx *dev, unsigned int cmd, void *arg) -{ - BUG_ON(NULL == dev->i2c_adap.algo_data); - i2c_clients_command(&dev->i2c_adap, cmd, arg); -} - /* * em28xx_i2c_register() * register i2c bus @@ -621,6 +558,7 @@ int em28xx_i2c_register(struct em28xx *dev) dev->i2c_adap.dev.parent = &dev->udev->dev; strcpy(dev->i2c_adap.name, dev->name); dev->i2c_adap.algo_data = dev; + i2c_set_adapdata(&dev->i2c_adap, &dev->v4l2_dev); retval = i2c_add_adapter(&dev->i2c_adap); if (retval < 0) { diff --git a/linux/drivers/media/video/em28xx/em28xx-video.c b/linux/drivers/media/video/em28xx/em28xx-video.c index ef02999ec..f5ca05aab 100644 --- a/linux/drivers/media/video/em28xx/em28xx-video.c +++ b/linux/drivers/media/video/em28xx/em28xx-video.c @@ -49,7 +49,7 @@ "Sascha Sommer " #define DRIVER_DESC "Empia em28xx based USB video device driver" -#define EM28XX_VERSION_CODE KERNEL_VERSION(0, 1, 1) +#define EM28XX_VERSION_CODE KERNEL_VERSION(0, 1, 2) #define em28xx_videodbg(fmt, arg...) do {\ if (video_debug) \ @@ -404,7 +404,7 @@ buffer_setup(struct videobuf_queue *vq, unsigned int *count, unsigned int *size) f.frequency = dev->ctl_freq; f.type = fh->radio ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV; - em28xx_i2c_call_clients(dev, VIDIOC_S_FREQUENCY, &f); + v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_frequency, &f); return 0; } @@ -530,25 +530,25 @@ static void video_mux(struct em28xx *dev, int index) if (!dev->ctl_aoutput) dev->ctl_aoutput = EM28XX_AOUT_MASTER; - em28xx_i2c_call_clients(dev, VIDIOC_INT_S_VIDEO_ROUTING, &route); + v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_routing, &route); if (dev->board.has_msp34xx) { if (dev->i2s_speed) { - em28xx_i2c_call_clients(dev, VIDIOC_INT_I2S_CLOCK_FREQ, - &dev->i2s_speed); + v4l2_device_call_all(&dev->v4l2_dev, 0, audio, + s_i2s_clock_freq, dev->i2s_speed); } - route.input = dev->ctl_ainput; + route.input = dev->ctl_ainput; route.output = MSP_OUTPUT(MSP_SC_IN_DSP_SCART1); + /* Note: this is msp3400 specific */ - em28xx_i2c_call_clients(dev, VIDIOC_INT_S_AUDIO_ROUTING, - &route); + v4l2_device_call_all(&dev->v4l2_dev, 0, audio, s_routing, &route); } if (dev->board.adecoder != EM28XX_NOADECODER) { - route.input = dev->ctl_ainput; + route.input = dev->ctl_ainput; route.output = dev->ctl_aoutput; - em28xx_i2c_call_clients(dev, VIDIOC_INT_S_AUDIO_ROUTING, - &route); + + v4l2_device_call_all(&dev->v4l2_dev, 0, audio, s_routing, &route); } em28xx_audio_analog_set(dev); @@ -833,7 +833,7 @@ static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *norm) get_scale(dev, dev->width, dev->height, &dev->hscale, &dev->vscale); em28xx_resolution_set(dev); - em28xx_i2c_call_clients(dev, VIDIOC_S_STD, &dev->norm); + v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_std, dev->norm); mutex_unlock(&dev->lock); return 0; @@ -1005,8 +1005,9 @@ static int vidioc_queryctrl(struct file *file, void *priv, } } } + mutex_lock(&dev->lock); - em28xx_i2c_call_clients(dev, VIDIOC_QUERYCTRL, qc); + v4l2_device_call_all(&dev->v4l2_dev, 0, core, queryctrl, qc); mutex_unlock(&dev->lock); if (qc->type) @@ -1030,11 +1031,11 @@ static int vidioc_g_ctrl(struct file *file, void *priv, mutex_lock(&dev->lock); if (dev->board.has_msp34xx) - em28xx_i2c_call_clients(dev, VIDIOC_G_CTRL, ctrl); + v4l2_device_call_all(&dev->v4l2_dev, 0, core, g_ctrl, ctrl); else { rc = em28xx_get_ctrl(dev, ctrl); if (rc < 0) { - em28xx_i2c_call_clients(dev, VIDIOC_G_CTRL, ctrl); + v4l2_device_call_all(&dev->v4l2_dev, 0, core, g_ctrl, ctrl); rc = 0; } } @@ -1058,7 +1059,7 @@ static int vidioc_s_ctrl(struct file *file, void *priv, mutex_lock(&dev->lock); if (dev->board.has_msp34xx) - em28xx_i2c_call_clients(dev, VIDIOC_S_CTRL, ctrl); + v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_ctrl, ctrl); else { rc = 1; for (i = 0; i < ARRAY_SIZE(em28xx_qctrl); i++) { @@ -1077,7 +1078,7 @@ static int vidioc_s_ctrl(struct file *file, void *priv, /* Control not found - try to send it to the attached devices */ if (rc == 1) { - em28xx_i2c_call_clients(dev, VIDIOC_S_CTRL, ctrl); + v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_ctrl, ctrl); rc = 0; } @@ -1102,10 +1103,9 @@ static int vidioc_g_tuner(struct file *file, void *priv, strcpy(t->name, "Tuner"); mutex_lock(&dev->lock); - - em28xx_i2c_call_clients(dev, VIDIOC_G_TUNER, t); - + v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, g_tuner, t); mutex_unlock(&dev->lock); + return 0; } @@ -1124,10 +1124,9 @@ static int vidioc_s_tuner(struct file *file, void *priv, return -EINVAL; mutex_lock(&dev->lock); - - em28xx_i2c_call_clients(dev, VIDIOC_S_TUNER, t); - + v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_tuner, t); mutex_unlock(&dev->lock); + return 0; } @@ -1167,7 +1166,7 @@ static int vidioc_s_frequency(struct file *file, void *priv, mutex_lock(&dev->lock); dev->ctl_freq = f->frequency; - em28xx_i2c_call_clients(dev, VIDIOC_S_FREQUENCY, f); + v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_frequency, f); mutex_unlock(&dev->lock); @@ -1196,7 +1195,7 @@ static int vidioc_g_chip_ident(struct file *file, void *priv, chip->ident = V4L2_IDENT_NONE; chip->revision = 0; - em28xx_i2c_call_clients(dev, VIDIOC_DBG_G_CHIP_IDENT, chip); + v4l2_device_call_all(&dev->v4l2_dev, 0, core, g_chip_ident, chip); return 0; } @@ -1221,7 +1220,7 @@ static int vidioc_g_register(struct file *file, void *priv, reg->size = 1; return 0; case V4L2_CHIP_MATCH_I2C_DRIVER: - em28xx_i2c_call_clients(dev, VIDIOC_DBG_G_REGISTER, reg); + v4l2_device_call_all(&dev->v4l2_dev, 0, core, g_register, reg); return 0; case V4L2_CHIP_MATCH_I2C_ADDR: /* Not supported yet */ @@ -1273,7 +1272,7 @@ static int vidioc_s_register(struct file *file, void *priv, return rc; case V4L2_CHIP_MATCH_I2C_DRIVER: - em28xx_i2c_call_clients(dev, VIDIOC_DBG_S_REGISTER, reg); + v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_register, reg); return 0; case V4L2_CHIP_MATCH_I2C_ADDR: /* Not supported yet */ @@ -1419,13 +1418,13 @@ static int vidioc_g_fmt_sliced_vbi_cap(struct file *file, void *priv, mutex_lock(&dev->lock); f->fmt.sliced.service_set = 0; - - em28xx_i2c_call_clients(dev, VIDIOC_G_FMT, f); + v4l2_device_call_all(&dev->v4l2_dev, 0, video, g_fmt, f); if (f->fmt.sliced.service_set == 0) rc = -EINVAL; mutex_unlock(&dev->lock); + return rc; } @@ -1441,7 +1440,7 @@ static int vidioc_try_set_sliced_vbi_cap(struct file *file, void *priv, return rc; mutex_lock(&dev->lock); - em28xx_i2c_call_clients(dev, VIDIOC_G_FMT, f); + v4l2_device_call_all(&dev->v4l2_dev, 0, video, g_fmt, f); mutex_unlock(&dev->lock); if (f->fmt.sliced.service_set == 0) @@ -1579,7 +1578,7 @@ static int radio_g_tuner(struct file *file, void *priv, t->type = V4L2_TUNER_RADIO; mutex_lock(&dev->lock); - em28xx_i2c_call_clients(dev, VIDIOC_G_TUNER, t); + v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, g_tuner, t); mutex_unlock(&dev->lock); return 0; @@ -1614,7 +1613,7 @@ static int radio_s_tuner(struct file *file, void *priv, return -EINVAL; mutex_lock(&dev->lock); - em28xx_i2c_call_clients(dev, VIDIOC_S_TUNER, t); + v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_tuner, t); mutex_unlock(&dev->lock); return 0; @@ -1717,7 +1716,7 @@ static int em28xx_v4l2_open(struct file *filp) #if 0 em28xx_start_radio(dev); #endif - em28xx_i2c_call_clients(dev, AUDC_SET_RADIO, NULL); + v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_radio); } dev->users++; @@ -1800,7 +1799,7 @@ static int em28xx_v4l2_close(struct file *filp) } /* Save some power by putting tuner to sleep */ - em28xx_i2c_call_clients(dev, TUNER_SET_STANDBY, NULL); + v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_standby, 0); /* do this before setting alternate! */ em28xx_uninit_isoc(dev); @@ -2026,11 +2025,12 @@ static struct video_device *em28xx_vdev_init(struct em28xx *dev, vfd = video_device_alloc(); if (NULL == vfd) return NULL; - *vfd = *template; - vfd->minor = -1; - vfd->parent = &dev->udev->dev; - vfd->release = video_device_release; - vfd->debug = video_debug; + + *vfd = *template; + vfd->minor = -1; + vfd->v4l2_dev = &dev->v4l2_dev; + vfd->release = video_device_release; + vfd->debug = video_debug; snprintf(vfd->name, sizeof(vfd->name), "%s %s", dev->name, type_name); diff --git a/linux/drivers/media/video/em28xx/em28xx.h b/linux/drivers/media/video/em28xx/em28xx.h index c9be33aba..a9d0a865f 100644 --- a/linux/drivers/media/video/em28xx/em28xx.h +++ b/linux/drivers/media/video/em28xx/em28xx.h @@ -28,6 +28,7 @@ #include "compat.h" #include #include +#include #include #include @@ -386,6 +387,8 @@ struct em28xx_board { unsigned int valid:1; unsigned char xclk, i2c_speed; + unsigned char radio_addr; + unsigned short tvaudio_addr; enum em28xx_decoder decoder; enum em28xx_adecoder adecoder; @@ -469,6 +472,7 @@ struct em28xx { int devno; /* marks the number of this device */ enum em28xx_chip_id chip_id; + struct v4l2_device v4l2_dev; struct em28xx_board board; unsigned int stream_on:1; /* Locks streams */ @@ -586,11 +590,9 @@ struct em28xx_ops { }; /* Provided by em28xx-i2c.c */ - -void em28xx_i2c_call_clients(struct em28xx *dev, unsigned int cmd, void *arg); void em28xx_do_i2c_scan(struct em28xx *dev); -int em28xx_i2c_register(struct em28xx *dev); -int em28xx_i2c_unregister(struct em28xx *dev); +int em28xx_i2c_register(struct em28xx *dev); +int em28xx_i2c_unregister(struct em28xx *dev); /* Provided by em28xx-core.c */ -- cgit v1.2.3 From a1e46dd7960d90441d7adeb6109ca7426c2e728e Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 1 Apr 2009 00:01:04 +0000 Subject: radio-si470x: fix possible bug with freeing memory order From: Alexey Klimov Patch fixes cleanup procedure in si470x_usb_driver_probe. Add new label err_video and change order of freeing memory. Signed-off-by: Alexey Klimov Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/radio/radio-si470x.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/radio/radio-si470x.c b/linux/drivers/media/radio/radio-si470x.c index 599fc0dcf..b4d6641b4 100644 --- a/linux/drivers/media/radio/radio-si470x.c +++ b/linux/drivers/media/radio/radio-si470x.c @@ -1687,7 +1687,7 @@ static int si470x_usb_driver_probe(struct usb_interface *intf, /* show some infos about the specific si470x device */ if (si470x_get_all_registers(radio) < 0) { retval = -EIO; - goto err_all; + goto err_video; } printk(KERN_INFO DRIVER_NAME ": DeviceID=0x%4.4hx ChipID=0x%4.4hx\n", radio->registers[DEVICEID], radio->registers[CHIPID]); @@ -1695,7 +1695,7 @@ static int si470x_usb_driver_probe(struct usb_interface *intf, /* get software and hardware versions */ if (si470x_get_scratch_page_versions(radio) < 0) { retval = -EIO; - goto err_all; + goto err_video; } printk(KERN_INFO DRIVER_NAME ": software version %d, hardware version %d\n", @@ -1728,7 +1728,7 @@ static int si470x_usb_driver_probe(struct usb_interface *intf, radio->buffer = kmalloc(radio->buf_size, GFP_KERNEL); if (!radio->buffer) { retval = -EIO; - goto err_all; + goto err_video; } /* rds buffer configuration */ @@ -1750,8 +1750,9 @@ static int si470x_usb_driver_probe(struct usb_interface *intf, return 0; err_all: - video_device_release(radio->videodev); kfree(radio->buffer); +err_video: + video_device_release(radio->videodev); err_radio: kfree(radio); err_initial: -- cgit v1.2.3 From cc563328c3991caed024da39ebb98e68f9b64dde Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 31 Mar 2009 22:01:51 +0000 Subject: cx88: Add support for stereo and sap detection for A2 From: Marton Balint The patch implements reliable stereo and sap detection for the A2 sound standard. This is achieved by processing the samples of the audio RDS fifo of the cx2388x chip. A2M, EIAJ and BTSC stereo/sap detection is also possible with this new approach, but it's not implemented yet. Stereo detection when alsa handles the sound also does not work yet. Priority: normal Signed-off-by: Marton Balint Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/cx88/Makefile | 2 +- linux/drivers/media/video/cx88/cx88-core.c | 26 ++++++++-- linux/drivers/media/video/cx88/cx88-tvaudio.c | 75 ++++++++++++++++----------- linux/drivers/media/video/cx88/cx88.h | 10 ++++ 4 files changed, 77 insertions(+), 36 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/cx88/Makefile b/linux/drivers/media/video/cx88/Makefile index b06b1275a..5b7e26761 100644 --- a/linux/drivers/media/video/cx88/Makefile +++ b/linux/drivers/media/video/cx88/Makefile @@ -1,5 +1,5 @@ cx88xx-objs := cx88-cards.o cx88-core.o cx88-i2c.o cx88-tvaudio.o \ - cx88-input.o + cx88-dsp.o cx88-input.o cx8800-objs := cx88-video.o cx88-vbi.o cx8802-objs := cx88-mpeg.o diff --git a/linux/drivers/media/video/cx88/cx88-core.c b/linux/drivers/media/video/cx88/cx88-core.c index 71dccf6af..39cbd152a 100644 --- a/linux/drivers/media/video/cx88/cx88-core.c +++ b/linux/drivers/media/video/cx88/cx88-core.c @@ -232,7 +232,7 @@ cx88_free_buffer(struct videobuf_queue *q, struct cx88_buffer *buf) * can use the whole SDRAM for the DMA fifos. To simplify things, we * use a static memory layout. That surely will waste memory in case * we don't use all DMA channels at the same time (which will be the - * case most of the time). But that still gives us enougth FIFO space + * case most of the time). But that still gives us enough FIFO space * to be able to deal with insane long pci latencies ... * * FIFO space allocations: @@ -242,6 +242,7 @@ cx88_free_buffer(struct videobuf_queue *q, struct cx88_buffer *buf) * channel 24 (vbi) - 4.0k * channels 25+26 (audio) - 4.0k * channel 28 (mpeg) - 4.0k + * channel 27 (audio rds)- 3.0k * TOTAL = 29.0k * * Every channel has 160 bytes control data (64 bytes instruction @@ -338,6 +339,18 @@ struct sram_channel cx88_sram_channels[] = { .cnt1_reg = MO_DMA28_CNT1, .cnt2_reg = MO_DMA28_CNT2, }, + [SRAM_CH27] = { + .name = "audio rds", + .cmds_start = 0x1801C0, + .ctrl_start = 0x180860, + .cdt = 0x180860 + 64, + .fifo_start = 0x187400, + .fifo_size = 0x000C00, + .ptr1_reg = MO_DMA27_PTR1, + .ptr2_reg = MO_DMA27_PTR2, + .cnt1_reg = MO_DMA27_CNT1, + .cnt2_reg = MO_DMA27_CNT2, + }, }; int cx88_sram_channel_setup(struct cx88_core *core, @@ -623,6 +636,7 @@ int cx88_reset(struct cx88_core *core) cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH25], 128, 0); cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH26], 128, 0); cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH28], 188*4, 0); + cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH27], 128, 0); /* misc init ... */ cx_write(MO_INPUT_FORMAT, ((1 << 13) | // agc enable @@ -821,6 +835,8 @@ int cx88_start_audio_dma(struct cx88_core *core) /* constant 128 made buzz in analog Nicam-stereo for bigger fifo_size */ int bpl = cx88_sram_channels[SRAM_CH25].fifo_size/4; + int rds_bpl = cx88_sram_channels[SRAM_CH27].fifo_size/AUD_RDS_LINES; + /* If downstream RISC is enabled, bail out; ALSA is managing DMA */ if (cx_read(MO_AUD_DMACNTRL) & 0x10) return 0; @@ -828,12 +844,14 @@ int cx88_start_audio_dma(struct cx88_core *core) /* setup fifo + format */ cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH25], bpl, 0); cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH26], bpl, 0); + cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH27], + rds_bpl, 0); cx_write(MO_AUDD_LNGTH, bpl); /* fifo bpl size */ - cx_write(MO_AUDR_LNGTH, bpl); /* fifo bpl size */ + cx_write(MO_AUDR_LNGTH, rds_bpl); /* fifo bpl size */ - /* start dma */ - cx_write(MO_AUD_DMACNTRL, 0x0003); /* Up and Down fifo enable */ + /* enable Up, Down and Audio RDS fifo */ + cx_write(MO_AUD_DMACNTRL, 0x0007); return 0; } diff --git a/linux/drivers/media/video/cx88/cx88-tvaudio.c b/linux/drivers/media/video/cx88/cx88-tvaudio.c index 0039354cf..71a127dce 100644 --- a/linux/drivers/media/video/cx88/cx88-tvaudio.c +++ b/linux/drivers/media/video/cx88/cx88-tvaudio.c @@ -167,6 +167,8 @@ static void set_audio_finish(struct cx88_core *core, u32 ctl) /* unmute */ volume = cx_sread(SHADOW_AUD_VOL_CTL); cx_swrite(SHADOW_AUD_VOL_CTL, AUD_VOL_CTL, volume); + + core->last_change = jiffies; } /* ----------------------------------------------------------- */ @@ -749,6 +751,7 @@ void cx88_set_tvaudio(struct cx88_core *core) break; case WW_BG: case WW_DK: + case WW_M: case WW_I: case WW_L: /* prepare all dsp registers */ @@ -760,6 +763,7 @@ void cx88_set_tvaudio(struct cx88_core *core) if (0 == cx88_detect_nicam(core)) { /* fall back to fm / am mono */ set_audio_standard_A2(core, EN_A2_FORCE_MONO1); + core->audiomode_current = V4L2_TUNER_MODE_MONO; core->use_nicam = 0; } else { core->use_nicam = 1; @@ -791,6 +795,7 @@ void cx88_set_tvaudio(struct cx88_core *core) void cx88_newstation(struct cx88_core *core) { core->audiomode_manual = UNSET; + core->last_change = jiffies; } void cx88_get_stereo(struct cx88_core *core, struct v4l2_tuner *t) @@ -809,44 +814,42 @@ void cx88_get_stereo(struct cx88_core *core, struct v4l2_tuner *t) aud_ctl_names[cx_read(AUD_CTL) & 63]); core->astat = reg; -/* TODO - Reading from AUD_STATUS is not enough - for auto-detecting sap/dual-fm/nicam. - Add some code here later. -*/ - -# if 0 t->capability = V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_SAP | V4L2_TUNER_CAP_LANG1 | V4L2_TUNER_CAP_LANG2; - t->rxsubchans = V4L2_TUNER_SUB_MONO; + t->rxsubchans = UNSET; t->audmode = V4L2_TUNER_MODE_MONO; + switch (mode) { + case 0: + t->audmode = V4L2_TUNER_MODE_STEREO; + break; + case 1: + t->audmode = V4L2_TUNER_MODE_LANG2; + break; + case 2: + t->audmode = V4L2_TUNER_MODE_MONO; + break; + case 3: + t->audmode = V4L2_TUNER_MODE_SAP; + break; + } + switch (core->tvaudio) { case WW_BTSC: - t->capability = V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_SAP; - t->rxsubchans = V4L2_TUNER_SUB_STEREO; - if (1 == pilot) { - /* SAP */ - t->rxsubchans |= V4L2_TUNER_SUB_SAP; - } - break; - case WW_A2_BG: - case WW_A2_DK: - case WW_A2_M: - if (1 == pilot) { - /* stereo */ - t->rxsubchans = - V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO; - if (0 == mode) - t->audmode = V4L2_TUNER_MODE_STEREO; - } - if (2 == pilot) { - /* dual language -- FIXME */ - t->rxsubchans = - V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2; - t->audmode = V4L2_TUNER_MODE_LANG1; + case WW_BG: + case WW_DK: + case WW_M: + case WW_EIAJ: + if (!core->use_nicam) { + t->rxsubchans = cx88_dsp_detect_stereo_sap(core); + break; } break; +# if 0 + /* TODO + Reading from AUD_STATUS is not enough + for auto-detecting sap/dual-fm/nicam. + */ case WW_NICAM_BGDKL: if (0 == mode) { t->audmode = V4L2_TUNER_MODE_STEREO; @@ -859,11 +862,20 @@ void cx88_get_stereo(struct cx88_core *core, struct v4l2_tuner *t) t->rxsubchans |= V4L2_TUNER_SUB_STEREO; } break; +# endif default: /* nothing */ break; } -# endif + + /* If software stereo detection is not supported... */ + if (UNSET == t->rxsubchans) { + t->rxsubchans = V4L2_TUNER_SUB_MONO; + /* If the hardware itself detected stereo, also return + stereo as an available subchannel */ + if (V4L2_TUNER_MODE_STEREO == t->audmode) + t->rxsubchans |= V4L2_TUNER_SUB_STEREO; + } return; } @@ -900,6 +912,7 @@ void cx88_set_stereo(struct cx88_core *core, u32 mode, int manual) break; case WW_BG: case WW_DK: + case WW_M: case WW_I: case WW_L: if (1 == core->use_nicam) { diff --git a/linux/drivers/media/video/cx88/cx88.h b/linux/drivers/media/video/cx88/cx88.h index a34f6ee0c..1cf6900e0 100644 --- a/linux/drivers/media/video/cx88/cx88.h +++ b/linux/drivers/media/video/cx88/cx88.h @@ -66,6 +66,8 @@ #define VBI_LINE_COUNT 17 #define VBI_LINE_LENGTH 2048 +#define AUD_RDS_LINES 4 + /* need "shadow" registers for some write-only ones ... */ #define SHADOW_AUD_VOL_CTL 1 #define SHADOW_AUD_BAL_CTL 2 @@ -133,6 +135,7 @@ struct cx88_ctrl { #define SRAM_CH25 4 /* audio */ #define SRAM_CH26 5 #define SRAM_CH28 6 /* mpeg */ +#define SRAM_CH27 7 /* audio rds */ /* more */ struct sram_channel { @@ -354,6 +357,7 @@ struct cx88_core { u32 input; u32 astat; u32 use_nicam; + unsigned long last_change; /* IR remote control state */ struct cx88_IR *ir; @@ -673,6 +677,7 @@ extern void cx88_setup_xc3028(struct cx88_core *core, struct xc2028_ctrl *ctl); #define WW_I2SPT 8 #define WW_FM 9 #define WW_I2SADC 10 +#define WW_M 11 void cx88_set_tvaudio(struct cx88_core *core); void cx88_newstation(struct cx88_core *core); @@ -685,6 +690,11 @@ int cx8802_unregister_driver(struct cx8802_driver *drv); struct cx8802_dev *cx8802_get_device(int minor); struct cx8802_driver * cx8802_get_driver(struct cx8802_dev *dev, enum cx88_board_type btype); +/* ----------------------------------------------------------- */ +/* cx88-dsp.c */ + +s32 cx88_dsp_detect_stereo_sap(struct cx88_core *core); + /* ----------------------------------------------------------- */ /* cx88-input.c */ -- cgit v1.2.3 From 9eded14b2cc5dfbe4c50e5b31bff3bea4c177a28 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 31 Mar 2009 22:01:52 +0000 Subject: cx88: audio thread: if stereo detection is hw supported don't do it manually From: Marton Balint The sole purpose of the audio thread is to detect if stereo transmission is available, and if it is, then switch to stereo mode (and switch back, if it's no longer available). This manual autodetection is useful for some audio standards (e.g. A2) where cx88_get_stereo CAN detect stereo sound, but the cx2388x chip CANNOT auto-detect stereo sound. However, for other audio standards, the cx2388x chip CAN auto-detect the stereo sound, so the manual autodetection in the audio thread is not needed. In fact, it can cause serious problems because for some of these audio standards, cx88_get_stereo CANNOT detect the presence of stereo sound. Besides that, if the hardware automatically detects stereo/mono sound, you cannot set core->audiomode_current to the real current audio mode on channel change. With this patch, the manual autodetection is only used if audiomode_current is known after a channel change (because of the initial mono mode), and hardware-based stereo autodetecion is not applicable for the current audio standard. Priority: normal Signed-off-by: Marton Balint Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/cx88/cx88-tvaudio.c | 51 +++++++++++++++++---------- 1 file changed, 33 insertions(+), 18 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/cx88/cx88-tvaudio.c b/linux/drivers/media/video/cx88/cx88-tvaudio.c index 71a127dce..4a8b6bba5 100644 --- a/linux/drivers/media/video/cx88/cx88-tvaudio.c +++ b/linux/drivers/media/video/cx88/cx88-tvaudio.c @@ -998,24 +998,39 @@ int cx88_audio_thread(void *data) break; try_to_freeze(); - /* just monitor the audio status for now ... */ - memset(&t, 0, sizeof(t)); - cx88_get_stereo(core, &t); - - if (UNSET != core->audiomode_manual) - /* manually set, don't do anything. */ - continue; - - /* monitor signal */ - if (t.rxsubchans & V4L2_TUNER_SUB_STEREO) - mode = V4L2_TUNER_MODE_STEREO; - else - mode = V4L2_TUNER_MODE_MONO; - if (mode == core->audiomode_current) - continue; - - /* automatically switch to best available mode */ - cx88_set_stereo(core, mode, 0); + switch (core->tvaudio) { + case WW_BG: + case WW_DK: + case WW_M: + case WW_I: + case WW_L: + if (core->use_nicam) + goto hw_autodetect; + + /* just monitor the audio status for now ... */ + memset(&t, 0, sizeof(t)); + cx88_get_stereo(core, &t); + + if (UNSET != core->audiomode_manual) + /* manually set, don't do anything. */ + continue; + + /* monitor signal and set stereo if available */ + if (t.rxsubchans & V4L2_TUNER_SUB_STEREO) + mode = V4L2_TUNER_MODE_STEREO; + else + mode = V4L2_TUNER_MODE_MONO; + if (mode == core->audiomode_current) + continue; + /* automatically switch to best available mode */ + cx88_set_stereo(core, mode, 0); + break; + default: +hw_autodetect: + /* stereo autodetection is supported by hardware so + we don't need to do it manually. Do nothing. */ + break; + } } dprintk("cx88: tvaudio thread exiting\n"); -- cgit v1.2.3 From 45c26066f501ed98fc14f3614ff37ddc4f480894 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 31 Mar 2009 22:01:53 +0000 Subject: cx88: avoid reprogramming every audio register on A2 stereo/mono change From: Marton Balint This patch changes cx88_set_stereo to avoid resetting all of the audio registers on stereo/mono change if the audio standard is A2, and set only the AUD_CTL register. The benefit of this method is that it eliminates the annoying clicking noise on setting the audio mode to stereo or mono. The driver had used the same method 1.5 years ago (and for FM radio it still does), but a pretty big cleanup commit changed it to the "complete audio reset" method, although the reason for this move was not clear. (If somebody knows why it was necessary, please let me know!) The original commit: http://linuxtv.org/hg/v4l-dvb/rev/ffe313541d7d Priority: normal Signed-off-by: Marton Balint Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/cx88/cx88-tvaudio.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/cx88/cx88-tvaudio.c b/linux/drivers/media/video/cx88/cx88-tvaudio.c index 4a8b6bba5..76d42b3d8 100644 --- a/linux/drivers/media/video/cx88/cx88-tvaudio.c +++ b/linux/drivers/media/video/cx88/cx88-tvaudio.c @@ -938,20 +938,18 @@ void cx88_set_stereo(struct cx88_core *core, u32 mode, int manual) set_audio_standard_A2(core, EN_A2_FORCE_MONO1); } else { /* TODO: Add A2 autodection */ + mask = 0x3f; switch (mode) { case V4L2_TUNER_MODE_MONO: case V4L2_TUNER_MODE_LANG1: - set_audio_standard_A2(core, - EN_A2_FORCE_MONO1); + ctl = EN_A2_FORCE_MONO1; break; case V4L2_TUNER_MODE_LANG2: - set_audio_standard_A2(core, - EN_A2_FORCE_MONO2); + ctl = EN_A2_FORCE_MONO2; break; case V4L2_TUNER_MODE_STEREO: case V4L2_TUNER_MODE_LANG1_LANG2: - set_audio_standard_A2(core, - EN_A2_FORCE_STEREO); + ctl = EN_A2_FORCE_STEREO; break; } } -- cgit v1.2.3 From cd550662abdf0912f05b5925adaba97ae022b504 Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Tue, 31 Mar 2009 22:58:49 -0400 Subject: au0828: better document i2c registers From: Devin Heitmueller Change the #define entries for the i2c registers to be more meaningful, and document the valid values for the registers. Note that this changeset makes *no* functional changes to the code. Priority: normal Signed-off-by: Devin Heitmueller --- linux/drivers/media/video/au0828/au0828-i2c.c | 62 ++++++++++++++++++--------- linux/drivers/media/video/au0828/au0828-reg.h | 35 ++++++++++++--- 2 files changed, 69 insertions(+), 28 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/au0828/au0828-i2c.c b/linux/drivers/media/video/au0828/au0828-i2c.c index eb63166f6..a0298fb84 100644 --- a/linux/drivers/media/video/au0828/au0828-i2c.c +++ b/linux/drivers/media/video/au0828/au0828-i2c.c @@ -40,13 +40,15 @@ MODULE_PARM_DESC(i2c_scan, "scan i2c bus at insmod time"); static inline int i2c_slave_did_write_ack(struct i2c_adapter *i2c_adap) { struct au0828_dev *dev = i2c_adap->algo_data; - return au0828_read(dev, REG_201) & 0x08 ? 0 : 1; + return au0828_read(dev, AU0828_I2C_STATUS_201) & + AU0828_I2C_STATUS_NO_WRITE_ACK ? 0 : 1; } static inline int i2c_slave_did_read_ack(struct i2c_adapter *i2c_adap) { struct au0828_dev *dev = i2c_adap->algo_data; - return au0828_read(dev, REG_201) & 0x02 ? 0 : 1; + return au0828_read(dev, AU0828_I2C_STATUS_201) & + AU0828_I2C_STATUS_NO_READ_ACK ? 0 : 1; } static int i2c_wait_read_ack(struct i2c_adapter *i2c_adap) @@ -68,7 +70,8 @@ static int i2c_wait_read_ack(struct i2c_adapter *i2c_adap) static inline int i2c_is_read_busy(struct i2c_adapter *i2c_adap) { struct au0828_dev *dev = i2c_adap->algo_data; - return au0828_read(dev, REG_201) & 0x01 ? 0 : 1; + return au0828_read(dev, AU0828_I2C_STATUS_201) & + AU0828_I2C_STATUS_READ_DONE ? 0 : 1; } static int i2c_wait_read_done(struct i2c_adapter *i2c_adap) @@ -90,7 +93,8 @@ static int i2c_wait_read_done(struct i2c_adapter *i2c_adap) static inline int i2c_is_write_done(struct i2c_adapter *i2c_adap) { struct au0828_dev *dev = i2c_adap->algo_data; - return au0828_read(dev, REG_201) & 0x04 ? 1 : 0; + return au0828_read(dev, AU0828_I2C_STATUS_201) & + AU0828_I2C_STATUS_WRITE_DONE ? 1 : 0; } static int i2c_wait_write_done(struct i2c_adapter *i2c_adap) @@ -112,7 +116,8 @@ static int i2c_wait_write_done(struct i2c_adapter *i2c_adap) static inline int i2c_is_busy(struct i2c_adapter *i2c_adap) { struct au0828_dev *dev = i2c_adap->algo_data; - return au0828_read(dev, REG_201) & 0x10 ? 1 : 0; + return au0828_read(dev, AU0828_I2C_STATUS_201) & + AU0828_I2C_STATUS_BUSY ? 1 : 0; } static int i2c_wait_done(struct i2c_adapter *i2c_adap) @@ -140,19 +145,21 @@ static int i2c_sendbytes(struct i2c_adapter *i2c_adap, dprintk(4, "%s()\n", __func__); - au0828_write(dev, REG_2FF, 0x01); + au0828_write(dev, AU0828_I2C_MULTIBYTE_MODE_2FF, 0x01); /* FIXME: There is a problem with i2c communications with xc5000 that requires us to slow down the i2c clock until we have a better strategy (such as using the secondary i2c bus to do firmware loading */ if ((msg->addr << 1) == 0xc2) - au0828_write(dev, REG_202, 0x40); + au0828_write(dev, AU0828_I2C_CLK_DIVIDER_202, + AU0828_I2C_CLK_30KHZ); else - au0828_write(dev, REG_202, 0x07); + au0828_write(dev, AU0828_I2C_CLK_DIVIDER_202, + AU0828_I2C_CLK_250KHZ); /* Hardware needs 8 bit addresses */ - au0828_write(dev, REG_203, msg->addr << 1); + au0828_write(dev, AU0828_I2C_DEST_ADDR_203, msg->addr << 1); dprintk(4, "SEND: %02x\n", msg->addr); @@ -164,7 +171,9 @@ static int i2c_sendbytes(struct i2c_adapter *i2c_adap, actual bytes to the bus, just do a read check. This is consistent with how I saw i2c device checking done in the USB trace of the Windows driver */ - au0828_write(dev, REG_200, 0x20); + au0828_write(dev, AU0828_I2C_TRIGGER_200, + AU0828_I2C_TRIGGER_READ); + if (!i2c_wait_done(i2c_adap)) return -EIO; @@ -178,7 +187,7 @@ static int i2c_sendbytes(struct i2c_adapter *i2c_adap, dprintk(4, " %02x\n", msg->buf[i]); - au0828_write(dev, REG_205, msg->buf[i]); + au0828_write(dev, AU0828_I2C_WRITE_FIFO_205, msg->buf[i]); strobe++; i++; @@ -187,9 +196,12 @@ static int i2c_sendbytes(struct i2c_adapter *i2c_adap, /* Strobe the byte into the bus */ if (i < msg->len) - au0828_write(dev, REG_200, 0x41); + au0828_write(dev, AU0828_I2C_TRIGGER_200, + AU0828_I2C_TRIGGER_WRITE | + AU0828_I2C_TRIGGER_HOLD); else - au0828_write(dev, REG_200, 0x01); + au0828_write(dev, AU0828_I2C_TRIGGER_200, + AU0828_I2C_TRIGGER_WRITE); /* Reset strobe trigger */ strobe = 0; @@ -217,25 +229,29 @@ static int i2c_readbytes(struct i2c_adapter *i2c_adap, dprintk(4, "%s()\n", __func__); - au0828_write(dev, REG_2FF, 0x01); + au0828_write(dev, AU0828_I2C_MULTIBYTE_MODE_2FF, 0x01); /* FIXME: There is a problem with i2c communications with xc5000 that requires us to slow down the i2c clock until we have a better strategy (such as using the secondary i2c bus to do firmware loading */ if ((msg->addr << 1) == 0xc2) - au0828_write(dev, REG_202, 0x40); + au0828_write(dev, AU0828_I2C_CLK_DIVIDER_202, + AU0828_I2C_CLK_30KHZ); else - au0828_write(dev, REG_202, 0x07); + au0828_write(dev, AU0828_I2C_CLK_DIVIDER_202, + AU0828_I2C_CLK_250KHZ); /* Hardware needs 8 bit addresses */ - au0828_write(dev, REG_203, msg->addr << 1); + au0828_write(dev, AU0828_I2C_DEST_ADDR_203, msg->addr << 1); dprintk(4, " RECV:\n"); /* Deal with i2c_scan */ if (msg->len == 0) { - au0828_write(dev, REG_200, 0x20); + au0828_write(dev, AU0828_I2C_TRIGGER_200, + AU0828_I2C_TRIGGER_READ); + if (i2c_wait_read_ack(i2c_adap)) return -EIO; return 0; @@ -246,14 +262,18 @@ static int i2c_readbytes(struct i2c_adapter *i2c_adap, i++; if (i < msg->len) - au0828_write(dev, REG_200, 0x60); + au0828_write(dev, AU0828_I2C_TRIGGER_200, + AU0828_I2C_TRIGGER_READ | + AU0828_I2C_TRIGGER_HOLD); else - au0828_write(dev, REG_200, 0x20); + au0828_write(dev, AU0828_I2C_TRIGGER_200, + AU0828_I2C_TRIGGER_READ); if (!i2c_wait_read_done(i2c_adap)) return -EIO; - msg->buf[i-1] = au0828_read(dev, REG_209) & 0xff; + msg->buf[i-1] = au0828_read(dev, AU0828_I2C_READ_FIFO_209) & + 0xff; dprintk(4, " %02x\n", msg->buf[i-1]); } diff --git a/linux/drivers/media/video/au0828/au0828-reg.h b/linux/drivers/media/video/au0828/au0828-reg.h index b15e4a3b6..c39f3d2b7 100644 --- a/linux/drivers/media/video/au0828/au0828-reg.h +++ b/linux/drivers/media/video/au0828/au0828-reg.h @@ -30,15 +30,36 @@ #define AU0828_SENSORCTRL_100 0x100 #define AU0828_SENSORCTRL_VBI_103 0x103 -#define REG_200 0x200 -#define REG_201 0x201 -#define REG_202 0x202 -#define REG_203 0x203 -#define REG_205 0x205 -#define REG_209 0x209 -#define REG_2FF 0x2ff +/* I2C registers */ +#define AU0828_I2C_TRIGGER_200 0x200 +#define AU0828_I2C_STATUS_201 0x201 +#define AU0828_I2C_CLK_DIVIDER_202 0x202 +#define AU0828_I2C_DEST_ADDR_203 0x203 +#define AU0828_I2C_WRITE_FIFO_205 0x205 +#define AU0828_I2C_READ_FIFO_209 0x209 +#define AU0828_I2C_MULTIBYTE_MODE_2FF 0x2ff /* Audio registers */ #define AU0828_AUDIOCTRL_50C 0x50C #define REG_600 0x600 + +/*********************************************************************/ +/* Here are constants for values associated with the above registers */ + +/* I2C Trigger (Reg 0x200) */ +#define AU0828_I2C_TRIGGER_WRITE 0x01 +#define AU0828_I2C_TRIGGER_READ 0x20 +#define AU0828_I2C_TRIGGER_HOLD 0x40 + +/* I2C Status (Reg 0x201) */ +#define AU0828_I2C_STATUS_READ_DONE 0x01 +#define AU0828_I2C_STATUS_NO_READ_ACK 0x02 +#define AU0828_I2C_STATUS_WRITE_DONE 0x04 +#define AU0828_I2C_STATUS_NO_WRITE_ACK 0x08 +#define AU0828_I2C_STATUS_BUSY 0x10 + +/* I2C Clock Divider (Reg 0x202) */ +#define AU0828_I2C_CLK_250KHZ 0x07 +#define AU0828_I2C_CLK_100KHZ 0x14 +#define AU0828_I2C_CLK_30KHZ 0x40 -- cgit v1.2.3 From 41a918183d70414e601306083d030ed58b5b8bd7 Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Tue, 31 Mar 2009 23:11:31 -0400 Subject: au0828: make i2c clock speed per-board configurable From: Devin Heitmueller Setup the i2c clock speed to be definable on a per-board basis. This allows us to explicitly set the clock speed to 30 KHz on the 950q, and also gets rid of code which sets it on a basis of what chip the i2c master is talking to at any given time (which could have caused issues because i2c slaves should never receive commands at a clock higher than their supported clock speed). Priority: normal Signed-off-by: Devin Heitmueller --- linux/drivers/media/video/au0828/au0828-cards.c | 11 +++++++++++ linux/drivers/media/video/au0828/au0828-i2c.c | 26 ++++++------------------- linux/drivers/media/video/au0828/au0828.h | 1 + 3 files changed, 18 insertions(+), 20 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 1aabaa7e5..abba48b15 100644 --- a/linux/drivers/media/video/au0828/au0828-cards.c +++ b/linux/drivers/media/video/au0828/au0828-cards.c @@ -46,6 +46,7 @@ struct au0828_board au0828_boards[] = { .name = "Hauppauge HVR850", .tuner_type = TUNER_XC5000, .tuner_addr = 0x61, + .i2c_clk_divider = AU0828_I2C_CLK_30KHZ, .input = { { .type = AU0828_VMUX_TELEVISION, @@ -70,6 +71,13 @@ struct au0828_board au0828_boards[] = { .name = "Hauppauge HVR950Q", .tuner_type = TUNER_XC5000, .tuner_addr = 0x61, + /* The au0828 hardware i2c implementation does not properly + support the xc5000's i2c clock stretching. So we need to + lower the clock frequency enough where the 15us clock + stretch fits inside of a normal clock cycle, or else the + au0828 fails to set the STOP bit. A 30 KHz clock puts the + clock pulse width at 18us */ + .i2c_clk_divider = AU0828_I2C_CLK_30KHZ, .input = { { .type = AU0828_VMUX_TELEVISION, @@ -94,16 +102,19 @@ struct au0828_board au0828_boards[] = { .name = "Hauppauge HVR950Q rev xxF8", .tuner_type = UNSET, .tuner_addr = ADDR_UNSET, + .i2c_clk_divider = AU0828_I2C_CLK_250KHZ, }, [AU0828_BOARD_DVICO_FUSIONHDTV7] = { .name = "DViCO FusionHDTV USB", .tuner_type = UNSET, .tuner_addr = ADDR_UNSET, + .i2c_clk_divider = AU0828_I2C_CLK_250KHZ, }, [AU0828_BOARD_HAUPPAUGE_WOODBURY] = { .name = "Hauppauge Woodbury", .tuner_type = UNSET, .tuner_addr = ADDR_UNSET, + .i2c_clk_divider = AU0828_I2C_CLK_250KHZ, }, }; diff --git a/linux/drivers/media/video/au0828/au0828-i2c.c b/linux/drivers/media/video/au0828/au0828-i2c.c index a0298fb84..a589d2ccb 100644 --- a/linux/drivers/media/video/au0828/au0828-i2c.c +++ b/linux/drivers/media/video/au0828/au0828-i2c.c @@ -147,16 +147,9 @@ static int i2c_sendbytes(struct i2c_adapter *i2c_adap, au0828_write(dev, AU0828_I2C_MULTIBYTE_MODE_2FF, 0x01); - /* FIXME: There is a problem with i2c communications with xc5000 that - requires us to slow down the i2c clock until we have a better - strategy (such as using the secondary i2c bus to do firmware - loading */ - if ((msg->addr << 1) == 0xc2) - au0828_write(dev, AU0828_I2C_CLK_DIVIDER_202, - AU0828_I2C_CLK_30KHZ); - else - au0828_write(dev, AU0828_I2C_CLK_DIVIDER_202, - AU0828_I2C_CLK_250KHZ); + /* Set the I2C clock */ + au0828_write(dev, AU0828_I2C_CLK_DIVIDER_202, + dev->board.i2c_clk_divider); /* Hardware needs 8 bit addresses */ au0828_write(dev, AU0828_I2C_DEST_ADDR_203, msg->addr << 1); @@ -231,16 +224,9 @@ static int i2c_readbytes(struct i2c_adapter *i2c_adap, au0828_write(dev, AU0828_I2C_MULTIBYTE_MODE_2FF, 0x01); - /* FIXME: There is a problem with i2c communications with xc5000 that - requires us to slow down the i2c clock until we have a better - strategy (such as using the secondary i2c bus to do firmware - loading */ - if ((msg->addr << 1) == 0xc2) - au0828_write(dev, AU0828_I2C_CLK_DIVIDER_202, - AU0828_I2C_CLK_30KHZ); - else - au0828_write(dev, AU0828_I2C_CLK_DIVIDER_202, - AU0828_I2C_CLK_250KHZ); + /* Set the I2C clock */ + au0828_write(dev, AU0828_I2C_CLK_DIVIDER_202, + dev->board.i2c_clk_divider); /* Hardware needs 8 bit addresses */ au0828_write(dev, AU0828_I2C_DEST_ADDR_203, msg->addr << 1); diff --git a/linux/drivers/media/video/au0828/au0828.h b/linux/drivers/media/video/au0828/au0828.h index 6ed1a6129..b977915ef 100644 --- a/linux/drivers/media/video/au0828/au0828.h +++ b/linux/drivers/media/video/au0828/au0828.h @@ -81,6 +81,7 @@ struct au0828_board { char *name; unsigned int tuner_type; unsigned char tuner_addr; + unsigned char i2c_clk_divider; struct au0828_input input[AU0828_MAX_INPUT]; }; -- cgit v1.2.3 From 103979f7c3e7b514b671dc8853ddd47f033c6add Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Tue, 31 Mar 2009 23:49:57 -0500 Subject: pvrusb2: Fix incorrect reporting of default value for non-integer controls From: Mike Isely Priority: high Signed-off-by: Mike Isely --- linux/drivers/media/video/pvrusb2/pvrusb2-ctrl.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-ctrl.c b/linux/drivers/media/video/pvrusb2/pvrusb2-ctrl.c index 5fa8af50b..77360a385 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-ctrl.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-ctrl.c @@ -138,14 +138,12 @@ int pvr2_ctrl_get_min(struct pvr2_ctrl *cptr) int pvr2_ctrl_get_def(struct pvr2_ctrl *cptr, int *valptr) { int ret = 0; - if (!cptr) return 0; + if (!cptr) return -EINVAL; LOCK_TAKE(cptr->hdw->big_lock); do { - if (cptr->info->type == pvr2_ctl_int) { - if (cptr->info->get_def_value) { - ret = cptr->info->get_def_value(cptr, valptr); - } else { - *valptr = cptr->info->default_value; - } + if (cptr->info->get_def_value) { + ret = cptr->info->get_def_value(cptr, valptr); + } else { + *valptr = cptr->info->default_value; } } while(0); LOCK_GIVE(cptr->hdw->big_lock); return ret; -- cgit v1.2.3 From 3082c825708d174b83fbcf67482d6e8acbb03d23 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Tue, 31 Mar 2009 23:51:53 -0500 Subject: pvrusb2: Report def_val items in sysfs symbolically, consistent with cur_val From: Mike Isely Priority: normal Signed-off-by: Mike Isely --- linux/drivers/media/video/pvrusb2/pvrusb2-sysfs.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-sysfs.c b/linux/drivers/media/video/pvrusb2/pvrusb2-sysfs.c index 84379d6e0..7ed3b8453 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-sysfs.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-sysfs.c @@ -154,14 +154,16 @@ static ssize_t show_def(struct device *class_dev, struct pvr2_sysfs_ctl_item *cip; int val; int ret; + unsigned int cnt = 0; cip = container_of(attr, struct pvr2_sysfs_ctl_item, attr_def); ret = pvr2_ctrl_get_def(cip->cptr, &val); - pvr2_sysfs_trace("pvr2_sysfs(%p) show_def(cid=%d) is %d, stat=%d", - cip->chptr, cip->ctl_id, val, ret); - if (ret < 0) { - return ret; - } - return scnprintf(buf, PAGE_SIZE, "%d\n", val); + if (ret < 0) return ret; + ret = pvr2_ctrl_value_to_sym(cip->cptr, ~0, val, + buf, PAGE_SIZE - 1, &cnt); + pvr2_sysfs_trace("pvr2_sysfs(%p) show_def(cid=%d) is %.*s (%d)", + cip->chptr, cip->ctl_id, cnt, buf, val); + buf[cnt] = '\n'; + return cnt + 1; } static ssize_t show_val_norm(struct device *class_dev, -- cgit v1.2.3 From f76de4701fca53bec40b9819de8de434a07716b6 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Tue, 31 Mar 2009 23:55:26 -0500 Subject: pvrusb2: Fix uninitialized tuner_setup field(s) From: Mike Isely Any time a struct (especially one not defined by this driver) is allocated, we MUST zero its underlying storage. This makes our usage of the struct predictable and robust against future changes where fields might be added that we don't know about. Failing to do this with tuner_setup left the config field uninitialized which then caused trouble with the tuner type used for HVR-1950 devices. Priority: high Signed-off-by: Mike Isely --- linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c | 1 + 1 file changed, 1 insertion(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c index bea17cd64..def29ddb3 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -2948,6 +2948,7 @@ static void pvr2_subdev_update(struct pvr2_hdw *hdw) pvr2_trace(PVR2_TRACE_CHIPS, "subdev tuner set_type(%d)", hdw->tuner_type); if (((int)(hdw->tuner_type)) >= 0) { + memset(&setup, 0, sizeof(setup)); setup.addr = ADDR_UNSET; setup.type = hdw->tuner_type; setup.mode_mask = T_RADIO | T_ANALOG_TV; -- cgit v1.2.3 From 7311d91726777ee42703fdf54cc73f851fb2e184 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 6 Apr 2009 09:26:24 -0300 Subject: Add a missing cx88-dsp file From: Mauro Carvalho Chehab This file were supposed to be included on changeset 11394:0eba67ef42ba. However, it weren't. Sorry for the mess. I'll merge this one with the original changeset at -git. This is the original description that also applies to this file: - cx88: Add support for stereo and sap detection for A2 - From: Marton Balint The patch implements reliable stereo and sap detection for the A2 sound standard. This is achieved by processing the samples of the audio RDS fifo of the cx2388x chip. A2M, EIAJ and BTSC stereo/sap detection is also possible with this new approach, but it's not implemented yet. Stereo detection when alsa handles the sound also does not work yet. Priority: normal Signed-off-by: Marton Balint Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/cx88/cx88-dsp.c | 304 ++++++++++++++++++++++++++++++ 1 file changed, 304 insertions(+) create mode 100644 linux/drivers/media/video/cx88/cx88-dsp.c (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/cx88/cx88-dsp.c b/linux/drivers/media/video/cx88/cx88-dsp.c new file mode 100644 index 000000000..da2b306c0 --- /dev/null +++ b/linux/drivers/media/video/cx88/cx88-dsp.c @@ -0,0 +1,304 @@ +/* + * + * Stereo and SAP detection for cx88 + * + * Copyright (c) 2009 Marton Balint + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include + +#include "cx88.h" +#include "cx88-reg.h" + +#define INT_PI ((s32)(3.141592653589 * 32768.0)) + +#define compat_remainder(a, b) \ + ((float)(((s32)((a)*100))%((s32)((b)*100)))/100.0) + +#define baseband_freq(carrier, srate, tone) ((s32)( \ + (compat_remainder(carrier + tone, srate)) / srate * 2 * INT_PI)) + +/* We calculate the baseband frequencies of the carrier and the pilot tones + * based on the the sampling rate of the audio rds fifo. */ + +#define FREQ_A2_CARRIER baseband_freq(54687.5, 2689.36, 0.0) +#define FREQ_A2_DUAL baseband_freq(54687.5, 2689.36, 274.1) +#define FREQ_A2_STEREO baseband_freq(54687.5, 2689.36, 117.5) + +/* The frequencies below are from the reference driver. They probably need + * further adjustments, because they are not tested at all. You may even need + * to play a bit with the registers of the chip to select the proper signal + * for the input of the audio rds fifo, and measure it's sampling rate to + * calculate the proper baseband frequencies... */ + +#define FREQ_A2M_CARRIER ((s32)(2.114516 * 32768.0)) +#define FREQ_A2M_DUAL ((s32)(2.754916 * 32768.0)) +#define FREQ_A2M_STEREO ((s32)(2.462326 * 32768.0)) + +#define FREQ_EIAJ_CARRIER ((s32)(1.963495 * 32768.0)) /* 5pi/8 */ +#define FREQ_EIAJ_DUAL ((s32)(2.562118 * 32768.0)) +#define FREQ_EIAJ_STEREO ((s32)(2.601053 * 32768.0)) + +#define FREQ_BTSC_DUAL ((s32)(1.963495 * 32768.0)) /* 5pi/8 */ +#define FREQ_BTSC_DUAL_REF ((s32)(1.374446 * 32768.0)) /* 7pi/16 */ + +#define FREQ_BTSC_SAP ((s32)(2.471532 * 32768.0)) +#define FREQ_BTSC_SAP_REF ((s32)(1.730072 * 32768.0)) + +/* The spectrum of the signal should be empty between these frequencies. */ +#define FREQ_NOISE_START ((s32)(0.100000 * 32768.0)) +#define FREQ_NOISE_END ((s32)(1.200000 * 32768.0)) + +static unsigned int dsp_debug; +module_param(dsp_debug, int, 0644); +MODULE_PARM_DESC(dsp_debug, "enable audio dsp debug messages"); + +#define dprintk(level, fmt, arg...) if (dsp_debug >= level) \ + printk(KERN_DEBUG "%s/0: " fmt, core->name , ## arg) + +static s32 int_cos(u32 x) +{ + u32 t2, t4, t6, t8; + s32 ret; + u16 period = x / INT_PI; + if (period % 2) + return -int_cos(x - INT_PI); + x = x % INT_PI; + if (x > INT_PI/2) + return -int_cos(INT_PI/2 - (x % (INT_PI/2))); + /* Now x is between 0 and INT_PI/2. + * To calculate cos(x) we use it's Taylor polinom. */ + t2 = x*x/32768/2; + t4 = t2*x/32768*x/32768/3/4; + t6 = t4*x/32768*x/32768/5/6; + t8 = t6*x/32768*x/32768/7/8; + ret = 32768-t2+t4-t6+t8; + return ret; +} + +static u32 int_goertzel(s16 x[], u32 N, u32 freq) +{ + /* We use the Goertzel algorithm to determine the power of the + * given frequency in the signal */ + s32 s_prev = 0; + s32 s_prev2 = 0; + s32 coeff = 2*int_cos(freq); + u32 i; + for (i = 0; i < N; i++) { + s32 s = x[i] + ((s64)coeff*s_prev/32768) - s_prev2; + s_prev2 = s_prev; + s_prev = s; + } + return (u32)(((s64)s_prev2*s_prev2 + (s64)s_prev*s_prev - + (s64)coeff*s_prev2*s_prev/32768)/N/N); +} + +static u32 freq_magnitude(s16 x[], u32 N, u32 freq) +{ + u32 sum = int_goertzel(x, N, freq); + return (u32)int_sqrt(sum); +} + +static u32 noise_magnitude(s16 x[], u32 N, u32 freq_start, u32 freq_end) +{ + int i; + u32 sum = 0; + u32 freq_step; + int samples = 5; + + if (N > 192) { + /* The last 192 samples are enough for noise detection */ + x += (N-192); + N = 192; + } + + freq_step = (freq_end - freq_start) / (samples - 1); + + for (i = 0; i < samples; i++) { + sum += int_goertzel(x, N, freq_start); + freq_start += freq_step; + } + + return (u32)int_sqrt(sum / samples); +} + +static s32 detect_a2_a2m_eiaj(struct cx88_core *core, s16 x[], u32 N) +{ + s32 carrier, stereo, dual, noise; + s32 carrier_freq, stereo_freq, dual_freq; + s32 ret; + + switch (core->tvaudio) { + case WW_BG: + case WW_DK: + carrier_freq = FREQ_A2_CARRIER; + stereo_freq = FREQ_A2_STEREO; + dual_freq = FREQ_A2_DUAL; + break; + case WW_M: + carrier_freq = FREQ_A2M_CARRIER; + stereo_freq = FREQ_A2M_STEREO; + dual_freq = FREQ_A2M_DUAL; + break; + case WW_EIAJ: + carrier_freq = FREQ_EIAJ_CARRIER; + stereo_freq = FREQ_EIAJ_STEREO; + dual_freq = FREQ_EIAJ_DUAL; + break; + default: + printk(KERN_WARNING "%s/0: unsupported audio mode %d for %s\n", + core->name, core->tvaudio, __func__); + return UNSET; + } + + carrier = freq_magnitude(x, N, carrier_freq); + stereo = freq_magnitude(x, N, stereo_freq); + dual = freq_magnitude(x, N, dual_freq); + noise = noise_magnitude(x, N, FREQ_NOISE_START, FREQ_NOISE_END); + + dprintk(1, "detect a2/a2m/eiaj: carrier=%d, stereo=%d, dual=%d, " + "noise=%d\n", carrier, stereo, dual, noise); + + if (stereo > dual) + ret = V4L2_TUNER_SUB_STEREO; + else + ret = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2; + + if (core->tvaudio == WW_EIAJ) { + /* EIAJ checks may need adjustments */ + if ((carrier > max(stereo, dual)*2) && + (carrier < max(stereo, dual)*6) && + (carrier > 20 && carrier < 200) && + (max(stereo, dual) > min(stereo, dual))) { + /* For EIAJ the carrier is always present, + so we probably don't need noise detection */ + return ret; + } + } else { + if ((carrier > max(stereo, dual)*2) && + (carrier < max(stereo, dual)*8) && + (carrier > 20 && carrier < 200) && + (noise < 10) && + (max(stereo, dual) > min(stereo, dual)*2)) { + return ret; + } + } + return V4L2_TUNER_SUB_MONO; +} + +static s32 detect_btsc(struct cx88_core *core, s16 x[], u32 N) +{ + s32 sap_ref = freq_magnitude(x, N, FREQ_BTSC_SAP_REF); + s32 sap = freq_magnitude(x, N, FREQ_BTSC_SAP); + s32 dual_ref = freq_magnitude(x, N, FREQ_BTSC_DUAL_REF); + s32 dual = freq_magnitude(x, N, FREQ_BTSC_DUAL); + dprintk(1, "detect btsc: dual_ref=%d, dual=%d, sap_ref=%d, sap=%d" + "\n", dual_ref, dual, sap_ref, sap); + /* FIXME: Currently not supported */ + return UNSET; +} + +static s16 *read_rds_samples(struct cx88_core *core, u32 *N) +{ + struct sram_channel *srch = &cx88_sram_channels[SRAM_CH27]; + s16 *samples; + + unsigned int i; + unsigned int bpl = srch->fifo_size/AUD_RDS_LINES; + unsigned int spl = bpl/4; + unsigned int sample_count = spl*(AUD_RDS_LINES-1); + + u32 current_address = cx_read(srch->ptr1_reg); + u32 offset = (current_address - srch->fifo_start + bpl); + + dprintk(1, "read RDS samples: current_address=%08x (offset=%08x), " + "sample_count=%d, aud_intstat=%08x\n", current_address, + current_address - srch->fifo_start, sample_count, + cx_read(MO_AUD_INTSTAT)); + + samples = kmalloc(sizeof(s16)*sample_count, GFP_KERNEL); + if (!samples) + return NULL; + + *N = sample_count; + + for (i = 0; i < sample_count; i++) { + offset = offset % (AUD_RDS_LINES*bpl); + samples[i] = cx_read(srch->fifo_start + offset); + offset += 4; + } + + if (dsp_debug >= 2) { + dprintk(2, "RDS samples dump: "); + for (i = 0; i < sample_count; i++) + printk("%hd ", samples[i]); + printk(".\n"); + } + + return samples; +} + +s32 cx88_dsp_detect_stereo_sap(struct cx88_core *core) +{ + s16 *samples; + u32 N = 0; + s32 ret = UNSET; + + /* If audio RDS fifo is disabled, we can't read the samples */ + if (!(cx_read(MO_AUD_DMACNTRL) & 0x04)) + return ret; + if (!(cx_read(AUD_CTL) & EN_FMRADIO_EN_RDS)) + return ret; + + /* Wait at least 500 ms after an audio standard change */ + if (time_before(jiffies, core->last_change + msecs_to_jiffies(500))) + return ret; + + samples = read_rds_samples(core, &N); + + if (!samples) + return ret; + + switch (core->tvaudio) { + case WW_BG: + case WW_DK: +#if 0 + /* We should not detect these, until they are properly tested... */ + case WW_EIAJ: + case WW_M: +#endif + ret = detect_a2_a2m_eiaj(core, samples, N); + break; + case WW_BTSC: + ret = detect_btsc(core, samples, N); + break; + } + + kfree(samples); + + if (UNSET != ret) + dprintk(1, "stereo/sap detection result:%s%s%s\n", + (ret & V4L2_TUNER_SUB_MONO) ? " mono" : "", + (ret & V4L2_TUNER_SUB_STEREO) ? " stereo" : "", + (ret & V4L2_TUNER_SUB_LANG2) ? " dual" : ""); + + return ret; +} +EXPORT_SYMBOL(cx88_dsp_detect_stereo_sap); + -- cgit v1.2.3 From f59d306e416b8bfd707417c9a8c1d77e2e87f173 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 1 Apr 2009 07:35:10 +0000 Subject: Support for Legend Silicon LGS8913/LGS8GL5/LGS8GXX China DMB-TH digital demodulator From: David Wong This patch contains the unified driver for Legend Silicon LGS8913 and LGS8GL5. It should replace lgs8gl5.c in media/dvb/frontends in the future. Signed-off-by: David T.L. Wong Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/frontends/Kconfig | 7 + linux/drivers/media/dvb/frontends/Makefile | 1 + linux/drivers/media/dvb/frontends/lgs8gxx.c | 859 +++++++++++++++++++++++ linux/drivers/media/dvb/frontends/lgs8gxx.h | 90 +++ linux/drivers/media/dvb/frontends/lgs8gxx_priv.h | 70 ++ 5 files changed, 1027 insertions(+) create mode 100644 linux/drivers/media/dvb/frontends/lgs8gxx.c create mode 100644 linux/drivers/media/dvb/frontends/lgs8gxx.h create mode 100644 linux/drivers/media/dvb/frontends/lgs8gxx_priv.h (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/frontends/Kconfig b/linux/drivers/media/dvb/frontends/Kconfig index a206cee23..578b834bf 100644 --- a/linux/drivers/media/dvb/frontends/Kconfig +++ b/linux/drivers/media/dvb/frontends/Kconfig @@ -513,6 +513,13 @@ config DVB_LGS8GL5 help A DMB-TH tuner module. Say Y when you want to support this frontend. +config DVB_LGS8GXX + tristate "Legend Silicon LGS8913/LGS8GL5/LGS8GXX DMB-TH demodulator" + depends on DVB_CORE && I2C + default m if DVB_FE_CUSTOMISE + help + A DMB-TH tuner module. Say Y when you want to support this frontend. + comment "Tools to develop new frontends" config DVB_DUMMY_FE diff --git a/linux/drivers/media/dvb/frontends/Makefile b/linux/drivers/media/dvb/frontends/Makefile index 65a336aa1..bc2b00abd 100644 --- a/linux/drivers/media/dvb/frontends/Makefile +++ b/linux/drivers/media/dvb/frontends/Makefile @@ -61,6 +61,7 @@ obj-$(CONFIG_DVB_TDA10048) += tda10048.o obj-$(CONFIG_DVB_TUNER_CX24113) += cx24113.o obj-$(CONFIG_DVB_S5H1411) += s5h1411.o obj-$(CONFIG_DVB_LGS8GL5) += lgs8gl5.o +obj-$(CONFIG_DVB_LGS8GXX) += lgs8gxx.o obj-$(CONFIG_DVB_DUMMY_FE) += dvb_dummy_fe.o obj-$(CONFIG_DVB_AF9013) += af9013.o obj-$(CONFIG_DVB_CX24116) += cx24116.o diff --git a/linux/drivers/media/dvb/frontends/lgs8gxx.c b/linux/drivers/media/dvb/frontends/lgs8gxx.c new file mode 100644 index 000000000..1395f3b5b --- /dev/null +++ b/linux/drivers/media/dvb/frontends/lgs8gxx.c @@ -0,0 +1,859 @@ +/* + * Support for Legend Silicon DMB-TH demodulator + * LGS8913, LGS8GL5 + * experimental support LGS8G42, LGS8G52 + * + * Copyright (C) 2007,2008 David T.L. Wong + * Copyright (C) 2008 Sirius International (Hong Kong) Limited + * Timothy Lee (for initial work on LGS8GL5) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include + +#include "dvb_frontend.h" + +#include "lgs8gxx.h" +#include "lgs8gxx_priv.h" + +#define dprintk(args...) \ + do { \ + if (debug) \ + printk(KERN_DEBUG "lgs8gxx: " args); \ + } while (0) + +static int debug; +static int fake_signal_str; + +module_param(debug, int, 0644); +MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off)."); + +module_param(fake_signal_str, int, 0644); +MODULE_PARM_DESC(fake_signal_str, "fake signal strength for LGS8913." +"Signal strength calculation is slow.(default:off)."); + +/* LGS8GXX internal helper functions */ + +static int lgs8gxx_write_reg(struct lgs8gxx_state *priv, u8 reg, u8 data) +{ + int ret; + u8 buf[] = { reg, data }; + struct i2c_msg msg = { .flags = 0, .buf = buf, .len = 2 }; + + msg.addr = priv->config->demod_address; + if (reg >= 0xC0) + msg.addr += 0x02; + + if (debug >= 2) + printk(KERN_DEBUG "%s: reg=0x%02X, data=0x%02X\n", + __func__, reg, data); + + ret = i2c_transfer(priv->i2c, &msg, 1); + + if (ret != 1) + dprintk(KERN_DEBUG "%s: error reg=0x%x, data=0x%x, ret=%i\n", + __func__, reg, data, ret); + + return (ret != 1) ? -1 : 0; +} + +static int lgs8gxx_read_reg(struct lgs8gxx_state *priv, u8 reg, u8 *p_data) +{ + int ret; + u8 dev_addr; + + u8 b0[] = { reg }; + u8 b1[] = { 0 }; + struct i2c_msg msg[] = { + { .flags = 0, .buf = b0, .len = 1 }, + { .flags = I2C_M_RD, .buf = b1, .len = 1 }, + }; + + dev_addr = priv->config->demod_address; + if (reg >= 0xC0) + dev_addr += 0x02; + msg[1].addr = msg[0].addr = dev_addr; + + ret = i2c_transfer(priv->i2c, msg, 2); + if (ret != 2) { + dprintk(KERN_DEBUG "%s: error reg=0x%x, ret=%i\n", + __func__, reg, ret); + return -1; + } + + *p_data = b1[0]; + if (debug >= 2) + printk(KERN_DEBUG "%s: reg=0x%02X, data=0x%02X\n", + __func__, reg, b1[0]); + return 0; +} + +static int lgs8gxx_soft_reset(struct lgs8gxx_state *priv) +{ + lgs8gxx_write_reg(priv, 0x02, 0x00); + msleep(1); + lgs8gxx_write_reg(priv, 0x02, 0x01); + msleep(100); + + return 0; +} + +static int lgs8gxx_set_ad_mode(struct lgs8gxx_state *priv) +{ + const struct lgs8gxx_config *config = priv->config; + u8 if_conf; + + if_conf = 0x10; /* AGC output on; */ + + if_conf |= + ((config->ext_adc) ? 0x80 : 0x00) | + ((config->if_neg_center) ? 0x04 : 0x00) | + ((config->if_freq == 0) ? 0x08 : 0x00) | /* Baseband */ + ((config->ext_adc && config->adc_signed) ? 0x02 : 0x00) | + ((config->ext_adc && config->if_neg_edge) ? 0x01 : 0x00); + + if (config->ext_adc && + (config->prod == LGS8GXX_PROD_LGS8G52)) { + lgs8gxx_write_reg(priv, 0xBA, 0x40); + } + + lgs8gxx_write_reg(priv, 0x07, if_conf); + + return 0; +} + +static int lgs8gxx_set_if_freq(struct lgs8gxx_state *priv, u32 freq /*in kHz*/) +{ + u64 val; + u32 v32; + u32 if_clk; + + if_clk = priv->config->if_clk_freq; + + val = freq; + if (freq != 0) { + val *= (u64)1 << 32; + if (if_clk != 0) + do_div(val, if_clk); + v32 = val & 0xFFFFFFFF; + dprintk("Set IF Freq to %dkHz\n", freq); + } else { + v32 = 0; + dprintk("Set IF Freq to baseband\n"); + } + dprintk("AFC_INIT_FREQ = 0x%08X\n", v32); + + lgs8gxx_write_reg(priv, 0x09, 0xFF & (v32)); + lgs8gxx_write_reg(priv, 0x0A, 0xFF & (v32 >> 8)); + lgs8gxx_write_reg(priv, 0x0B, 0xFF & (v32 >> 16)); + lgs8gxx_write_reg(priv, 0x0C, 0xFF & (v32 >> 24)); + + return 0; +} + +static int lgs8gxx_set_mode_auto(struct lgs8gxx_state *priv) +{ + u8 t; + + if (priv->config->prod == LGS8GXX_PROD_LGS8913) + lgs8gxx_write_reg(priv, 0xC6, 0x01); + + lgs8gxx_read_reg(priv, 0x7E, &t); + lgs8gxx_write_reg(priv, 0x7E, t | 0x01); + + /* clear FEC self reset */ + lgs8gxx_read_reg(priv, 0xC5, &t); + lgs8gxx_write_reg(priv, 0xC5, t & 0xE0); + + if (priv->config->prod == LGS8GXX_PROD_LGS8913) { + /* FEC auto detect */ + lgs8gxx_write_reg(priv, 0xC1, 0x03); + + lgs8gxx_read_reg(priv, 0x7C, &t); + t = (t & 0x8C) | 0x03; + lgs8gxx_write_reg(priv, 0x7C, t); + } + + + if (priv->config->prod == LGS8GXX_PROD_LGS8913) { + /* BER test mode */ + lgs8gxx_read_reg(priv, 0xC3, &t); + t = (t & 0xEF) | 0x10; + lgs8gxx_write_reg(priv, 0xC3, t); + } + + if (priv->config->prod == LGS8GXX_PROD_LGS8G52) + lgs8gxx_write_reg(priv, 0xD9, 0x40); + + return 0; +} + +static int lgs8gxx_set_mode_manual(struct lgs8gxx_state *priv) +{ + int ret = 0; + u8 t; + + /* turn off auto-detect; manual settings */ + lgs8gxx_write_reg(priv, 0x7E, 0); + if (priv->config->prod == LGS8GXX_PROD_LGS8913) + lgs8gxx_write_reg(priv, 0xC1, 0); + + ret = lgs8gxx_read_reg(priv, 0xC5, &t); + t = (t & 0xE0) | 0x06; + lgs8gxx_write_reg(priv, 0xC5, t); + + lgs8gxx_soft_reset(priv); + + return 0; +} + +static int lgs8gxx_is_locked(struct lgs8gxx_state *priv, u8 *locked) +{ + int ret = 0; + u8 t; + + ret = lgs8gxx_read_reg(priv, 0x4B, &t); + if (ret != 0) + return ret; + + *locked = ((t & 0xC0) == 0xC0) ? 1 : 0; + return 0; +} + +static int lgs8gxx_is_autodetect_finished(struct lgs8gxx_state *priv, + u8 *finished) +{ + int ret = 0; + u8 t; + + ret = lgs8gxx_read_reg(priv, 0xA4, &t); + if (ret != 0) + return ret; + + *finished = ((t & 0x3) == 0x1) ? 1 : 0; + + return 0; +} + +static int lgs8gxx_autolock_gi(struct lgs8gxx_state *priv, u8 gi, u8 *locked) +{ + int err; + u8 ad_fini = 0; + + if (gi == GI_945) + dprintk("try GI 945\n"); + else if (gi == GI_595) + dprintk("try GI 595\n"); + else if (gi == GI_420) + dprintk("try GI 420\n"); + lgs8gxx_write_reg(priv, 0x04, gi); + lgs8gxx_soft_reset(priv); + msleep(50); + err = lgs8gxx_is_autodetect_finished(priv, &ad_fini); + if (err != 0) + return err; + if (ad_fini) { + err = lgs8gxx_is_locked(priv, locked); + if (err != 0) + return err; + } + + return 0; +} + +static int lgs8gxx_auto_detect(struct lgs8gxx_state *priv, + u8 *detected_param, u8 *gi) +{ + int i, j; + int err = 0; + u8 locked = 0, tmp_gi; + + dprintk("%s\n", __func__); + + lgs8gxx_set_mode_auto(priv); + /* Guard Interval */ + lgs8gxx_write_reg(priv, 0x03, 00); + + for (i = 0; i < 2; i++) { + for (j = 0; j < 2; j++) { + tmp_gi = GI_945; + err = lgs8gxx_autolock_gi(priv, GI_945, &locked); + if (err) + goto out; + if (locked) + goto locked; + } + for (j = 0; j < 2; j++) { + tmp_gi = GI_420; + err = lgs8gxx_autolock_gi(priv, GI_420, &locked); + if (err) + goto out; + if (locked) + goto locked; + } + tmp_gi = GI_595; + err = lgs8gxx_autolock_gi(priv, GI_595, &locked); + if (err) + goto out; + if (locked) + goto locked; + } + +locked: + if ((err == 0) && (locked == 1)) { + u8 t; + + lgs8gxx_read_reg(priv, 0xA2, &t); + *detected_param = t; + + if (tmp_gi == GI_945) + dprintk("GI 945 locked\n"); + else if (tmp_gi == GI_595) + dprintk("GI 595 locked\n"); + else if (tmp_gi == GI_420) + dprintk("GI 420 locked\n"); + *gi = tmp_gi; + } + if (!locked) + err = -1; + +out: + return err; +} + +static void lgs8gxx_auto_lock(struct lgs8gxx_state *priv) +{ + s8 err; + u8 gi = 0x2; + u8 detected_param = 0; + + err = lgs8gxx_auto_detect(priv, &detected_param, &gi); + + if (err != 0) { +#if 0 + /* Set auto guardinterval detection */ + lgs8gxx_write_reg(priv, 0x03, 0x01); +#endif + dprintk("lgs8gxx_auto_detect failed\n"); + } + + /* Apply detected parameters */ + if (priv->config->prod == LGS8GXX_PROD_LGS8913) { + u8 inter_leave_len = detected_param & TIM_MASK ; + inter_leave_len = (inter_leave_len == TIM_LONG) ? 0x60 : 0x40; + detected_param &= CF_MASK | SC_MASK | LGS_FEC_MASK; + detected_param |= inter_leave_len; + } + lgs8gxx_write_reg(priv, 0x7D, detected_param); + if (priv->config->prod == LGS8GXX_PROD_LGS8913) + lgs8gxx_write_reg(priv, 0xC0, detected_param); + /* lgs8gxx_soft_reset(priv); */ + + /* Enter manual mode */ + lgs8gxx_set_mode_manual(priv); + + switch (gi) { + case GI_945: + priv->curr_gi = 945; break; + case GI_595: + priv->curr_gi = 595; break; + case GI_420: + priv->curr_gi = 420; break; + default: + priv->curr_gi = 945; break; + } +} + +static int lgs8gxx_set_mpeg_mode(struct lgs8gxx_state *priv, + u8 serial, u8 clk_pol, u8 clk_gated) +{ + int ret = 0; + u8 t; + + ret = lgs8gxx_read_reg(priv, 0xC2, &t); + if (ret != 0) + return ret; + + t &= 0xF8; + t |= serial ? TS_SERIAL : TS_PARALLEL; + t |= clk_pol ? TS_CLK_INVERTED : TS_CLK_NORMAL; + t |= clk_gated ? TS_CLK_GATED : TS_CLK_FREERUN; + + ret = lgs8gxx_write_reg(priv, 0xC2, t); + if (ret != 0) + return ret; + + return 0; +} + + +/* LGS8913 demod frontend functions */ + +static int lgs8913_init(struct lgs8gxx_state *priv) +{ + u8 t; + + /* LGS8913 specific */ + lgs8gxx_write_reg(priv, 0xc1, 0x3); + + lgs8gxx_read_reg(priv, 0x7c, &t); + lgs8gxx_write_reg(priv, 0x7c, (t&0x8c) | 0x3); + + /* LGS8913 specific */ + lgs8gxx_read_reg(priv, 0xc3, &t); + lgs8gxx_write_reg(priv, 0xc3, t&0x10); + +#if 0 + /* set AGC ref */ + /* TODO better set from configuration per hardware */ + lgs8gxx_write_reg(priv, 0x2C, 0); + lgs8gxx_write_reg(priv, 0x2D, 0x18); + lgs8gxx_write_reg(priv, 0x2E, 0xA2); +#endif + + return 0; +} + +static int lgs8gxx_init(struct dvb_frontend *fe) +{ + struct lgs8gxx_state *priv = + (struct lgs8gxx_state *)fe->demodulator_priv; + const struct lgs8gxx_config *config = priv->config; + u8 data = 0; + s8 err; + dprintk("%s\n", __func__); + + lgs8gxx_read_reg(priv, 0, &data); + dprintk("reg 0 = 0x%02X\n", data); + + /* Setup MPEG output format */ + err = lgs8gxx_set_mpeg_mode(priv, config->serial_ts, + config->ts_clk_pol, + config->ts_clk_gated); + if (err != 0) + return -EIO; + + if (config->prod == LGS8GXX_PROD_LGS8913) + lgs8913_init(priv); + lgs8gxx_set_if_freq(priv, priv->config->if_freq); + if (config->prod != LGS8GXX_PROD_LGS8913) + lgs8gxx_set_ad_mode(priv); + + return 0; +} + +static void lgs8gxx_release(struct dvb_frontend *fe) +{ + struct lgs8gxx_state *state = fe->demodulator_priv; + dprintk("%s\n", __func__); + + kfree(state); +} + +#if 0 +static int lgs8gxx_sleep(struct dvb_frontend *fe) +{ + dprintk("%s\n", __func__); + + return 0; +} +#endif + +static int lgs8gxx_write(struct dvb_frontend *fe, u8 *buf, int len) +{ + struct lgs8gxx_state *priv = fe->demodulator_priv; + + if (len != 2) + return -EINVAL; + + return lgs8gxx_write_reg(priv, buf[0], buf[1]); +} + +static int lgs8gxx_set_fe(struct dvb_frontend *fe, + struct dvb_frontend_parameters *fe_params) +{ + struct lgs8gxx_state *priv = fe->demodulator_priv; + + dprintk("%s\n", __func__); + + /* set frequency */ + if (fe->ops.tuner_ops.set_params) { + fe->ops.tuner_ops.set_params(fe, fe_params); + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 0); + } + + /* start auto lock */ + lgs8gxx_auto_lock(priv); + + msleep(10); + + return 0; +} + +static int lgs8gxx_get_fe(struct dvb_frontend *fe, + struct dvb_frontend_parameters *fe_params) +{ + struct lgs8gxx_state *priv = fe->demodulator_priv; + u8 t; +#if 0 + int translated_fec = FEC_1_2; +#endif + + dprintk("%s\n", __func__); + + /* TODO: get real readings from device */ + /* inversion status */ + fe_params->inversion = INVERSION_OFF; + + /* bandwidth */ + fe_params->u.ofdm.bandwidth = BANDWIDTH_8_MHZ; + + + lgs8gxx_read_reg(priv, 0x7D, &t); +#if 0 + /* FEC. No exact match for DMB-TH, pick approx. value */ + switch (t & LGS_FEC_MASK) { + case LGS_FEC_0_4: /* FEC 0.4 */ + translated_fec = FEC_1_2; + break; + case LGS_FEC_0_6: /* FEC 0.6 */ + translated_fec = FEC_2_3; + break; + case LGS_FEC_0_8: /* FEC 0.8 */ + translated_fec = FEC_5_6; + break; + default: + translated_fec = FEC_1_2; + } + fe_params->u.ofdm.code_rate_HP = translated_fec; + fe_params->u.ofdm.code_rate_LP = translated_fec; +#endif + fe_params->u.ofdm.code_rate_HP = FEC_AUTO; + fe_params->u.ofdm.code_rate_LP = FEC_AUTO; + + /* constellation */ + switch (t & SC_MASK) { + case SC_QAM64: + fe_params->u.ofdm.constellation = QAM_64; + break; + case SC_QAM32: + fe_params->u.ofdm.constellation = QAM_32; + break; + case SC_QAM16: + fe_params->u.ofdm.constellation = QAM_16; + break; + case SC_QAM4: + case SC_QAM4NR: + fe_params->u.ofdm.constellation = QPSK; + break; + default: + fe_params->u.ofdm.constellation = QAM_64; + } + + /* transmission mode */ + fe_params->u.ofdm.transmission_mode = TRANSMISSION_MODE_AUTO; + + /* guard interval */ + fe_params->u.ofdm.guard_interval = GUARD_INTERVAL_AUTO; + + /* hierarchy */ + fe_params->u.ofdm.hierarchy_information = HIERARCHY_NONE; + + return 0; +} + +static +int lgs8gxx_get_tune_settings(struct dvb_frontend *fe, + struct dvb_frontend_tune_settings *fesettings) +{ + /* FIXME: copy from tda1004x.c */ + fesettings->min_delay_ms = 800; + fesettings->step_size = 0; + fesettings->max_drift = 0; + return 0; +} + +static int lgs8gxx_read_status(struct dvb_frontend *fe, fe_status_t *fe_status) +{ + struct lgs8gxx_state *priv = fe->demodulator_priv; + s8 ret; + u8 t; + + dprintk("%s\n", __func__); + + ret = lgs8gxx_read_reg(priv, 0x4B, &t); + if (ret != 0) + return -EIO; + + dprintk("Reg 0x4B: 0x%02X\n", t); + + *fe_status = 0; + if (priv->config->prod == LGS8GXX_PROD_LGS8913) { + if ((t & 0x40) == 0x40) + *fe_status |= FE_HAS_SIGNAL | FE_HAS_CARRIER; + if ((t & 0x80) == 0x80) + *fe_status |= FE_HAS_VITERBI | FE_HAS_SYNC | + FE_HAS_LOCK; + } else { + if ((t & 0x80) == 0x80) + *fe_status |= FE_HAS_SIGNAL | FE_HAS_CARRIER | + FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK; + } + + /* success */ + dprintk("%s: fe_status=0x%x\n", __func__, *fe_status); + return 0; +} + +static int lgs8gxx_read_signal_agc(struct lgs8gxx_state *priv, u16 *signal) +{ + u16 v; + u8 agc_lvl[2], cat; + + dprintk("%s()\n", __func__); + lgs8gxx_read_reg(priv, 0x3F, &agc_lvl[0]); + lgs8gxx_read_reg(priv, 0x3E, &agc_lvl[1]); + + v = agc_lvl[0]; + v <<= 8; + v |= agc_lvl[1]; + + dprintk("agc_lvl: 0x%04X\n", v); + + if (v < 0x100) + cat = 0; + else if (v < 0x190) + cat = 5; + else if (v < 0x2A8) + cat = 4; + else if (v < 0x381) + cat = 3; + else if (v < 0x400) + cat = 2; + else if (v == 0x400) + cat = 1; + else + cat = 0; + + *signal = cat; + + return 0; +} + +static int lgs8913_read_signal_strength(struct lgs8gxx_state *priv, u16 *signal) +{ + u8 t; s8 ret; + s16 max_strength = 0; + u8 str; + u16 i, gi = priv->curr_gi; + + dprintk("%s\n", __func__); + + ret = lgs8gxx_read_reg(priv, 0x4B, &t); + if (ret != 0) + return -EIO; + + if (fake_signal_str) { + if ((t & 0xC0) == 0xC0) { + dprintk("Fake signal strength as 50\n"); + *signal = 0x32; + } else + *signal = 0; + return 0; + } + + dprintk("gi = %d\n", gi); + for (i = 0; i < gi; i++) { + + if ((i & 0xFF) == 0) + lgs8gxx_write_reg(priv, 0x84, 0x03 & (i >> 8)); + lgs8gxx_write_reg(priv, 0x83, i & 0xFF); + + lgs8gxx_read_reg(priv, 0x94, &str); + if (max_strength < str) + max_strength = str; + } + + *signal = max_strength; + dprintk("%s: signal=0x%02X\n", __func__, *signal); + + lgs8gxx_read_reg(priv, 0x95, &t); + dprintk("%s: AVG Noise=0x%02X\n", __func__, t); + + return 0; +} + +static int lgs8gxx_read_signal_strength(struct dvb_frontend *fe, u16 *signal) +{ + struct lgs8gxx_state *priv = fe->demodulator_priv; + + if (priv->config->prod == LGS8GXX_PROD_LGS8913) + return lgs8913_read_signal_strength(priv, signal); + else + return lgs8gxx_read_signal_agc(priv, signal); +} + +static int lgs8gxx_read_snr(struct dvb_frontend *fe, u16 *snr) +{ + struct lgs8gxx_state *priv = fe->demodulator_priv; + u8 t; + *snr = 0; + + lgs8gxx_read_reg(priv, 0x95, &t); + dprintk("AVG Noise=0x%02X\n", t); + *snr = 256 - t; + *snr <<= 8; + dprintk("snr=0x%x\n", *snr); + + return 0; +} + +static int lgs8gxx_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) +{ + *ucblocks = 0; + dprintk("%s: ucblocks=0x%x\n", __func__, *ucblocks); + return 0; +} + +static int lgs8gxx_read_ber(struct dvb_frontend *fe, u32 *ber) +{ + struct lgs8gxx_state *priv = fe->demodulator_priv; + u8 r0, r1, r2, r3; + u32 total_cnt, err_cnt; + + dprintk("%s\n", __func__); + + lgs8gxx_write_reg(priv, 0xc6, 0x01); + lgs8gxx_write_reg(priv, 0xc6, 0x41); + lgs8gxx_write_reg(priv, 0xc6, 0x01); + + msleep(200); + + lgs8gxx_write_reg(priv, 0xc6, 0x81); + lgs8gxx_read_reg(priv, 0xd0, &r0); + lgs8gxx_read_reg(priv, 0xd1, &r1); + lgs8gxx_read_reg(priv, 0xd2, &r2); + lgs8gxx_read_reg(priv, 0xd3, &r3); + total_cnt = (r3 << 24) | (r2 << 16) | (r1 << 8) | (r0); + lgs8gxx_read_reg(priv, 0xd4, &r0); + lgs8gxx_read_reg(priv, 0xd5, &r1); + lgs8gxx_read_reg(priv, 0xd6, &r2); + lgs8gxx_read_reg(priv, 0xd7, &r3); + err_cnt = (r3 << 24) | (r2 << 16) | (r1 << 8) | (r0); + dprintk("error=%d total=%d\n", err_cnt, total_cnt); + + if (total_cnt == 0) + *ber = 0; + else + *ber = err_cnt * 100 / total_cnt; + + dprintk("%s: ber=0x%x\n", __func__, *ber); + return 0; +} + +static int lgs8gxx_i2c_gate_ctrl(struct dvb_frontend *fe, int enable) +{ + struct lgs8gxx_state *priv = fe->demodulator_priv; + + if (priv->config->tuner_address == 0) + return 0; + if (enable) { + u8 v = 0x80 | priv->config->tuner_address; + return lgs8gxx_write_reg(priv, 0x01, v); + } + return lgs8gxx_write_reg(priv, 0x01, 0); +} + +static struct dvb_frontend_ops lgs8gxx_ops = { + .info = { + .name = "Legend Silicon LGS8913/LGS8GXX DMB-TH", + .type = FE_OFDM, + .frequency_min = 474000000, + .frequency_max = 858000000, + .frequency_stepsize = 10000, + .caps = + FE_CAN_FEC_AUTO | + FE_CAN_QAM_AUTO | + FE_CAN_TRANSMISSION_MODE_AUTO | + FE_CAN_GUARD_INTERVAL_AUTO + }, + + .release = lgs8gxx_release, + + .init = lgs8gxx_init, +#if 0 + .sleep = lgs8gxx_sleep, +#endif + .write = lgs8gxx_write, + .i2c_gate_ctrl = lgs8gxx_i2c_gate_ctrl, + + .set_frontend = lgs8gxx_set_fe, + .get_frontend = lgs8gxx_get_fe, + .get_tune_settings = lgs8gxx_get_tune_settings, + + .read_status = lgs8gxx_read_status, + .read_ber = lgs8gxx_read_ber, + .read_signal_strength = lgs8gxx_read_signal_strength, + .read_snr = lgs8gxx_read_snr, + .read_ucblocks = lgs8gxx_read_ucblocks, +}; + +struct dvb_frontend *lgs8gxx_attach(const struct lgs8gxx_config *config, + struct i2c_adapter *i2c) +{ + struct lgs8gxx_state *priv = NULL; + u8 data = 0; + + dprintk("%s()\n", __func__); + + if (config == NULL || i2c == NULL) + return NULL; + + priv = kzalloc(sizeof(struct lgs8gxx_state), GFP_KERNEL); + if (priv == NULL) + goto error_out; + + priv->config = config; + priv->i2c = i2c; + + /* check if the demod is there */ + if (lgs8gxx_read_reg(priv, 0, &data) != 0) { + dprintk("%s lgs8gxx not found at i2c addr 0x%02X\n", + __func__, priv->config->demod_address); + goto error_out; + } + + lgs8gxx_read_reg(priv, 1, &data); + + memcpy(&priv->frontend.ops, &lgs8gxx_ops, + sizeof(struct dvb_frontend_ops)); + priv->frontend.demodulator_priv = priv; + + return &priv->frontend; + +error_out: + dprintk("%s() error_out\n", __func__); + kfree(priv); + return NULL; + +} +EXPORT_SYMBOL(lgs8gxx_attach); + +MODULE_DESCRIPTION("Legend Silicon LGS8913/LGS8GXX DMB-TH demodulator driver"); +MODULE_AUTHOR("David T. L. Wong "); +MODULE_LICENSE("GPL"); diff --git a/linux/drivers/media/dvb/frontends/lgs8gxx.h b/linux/drivers/media/dvb/frontends/lgs8gxx.h new file mode 100644 index 000000000..321d366a8 --- /dev/null +++ b/linux/drivers/media/dvb/frontends/lgs8gxx.h @@ -0,0 +1,90 @@ +/* + * Support for Legend Silicon DMB-TH demodulator + * LGS8913, LGS8GL5 + * experimental support LGS8G42, LGS8G52 + * + * Copyright (C) 2007,2008 David T.L. Wong + * Copyright (C) 2008 Sirius International (Hong Kong) Limited + * Timothy Lee (for initial work on LGS8GL5) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifndef __LGS8GXX_H__ +#define __LGS8GXX_H__ + +#include +#include + +#define LGS8GXX_PROD_LGS8913 0 +#define LGS8GXX_PROD_LGS8GL5 1 +#define LGS8GXX_PROD_LGS8G42 3 +#define LGS8GXX_PROD_LGS8G52 4 +#define LGS8GXX_PROD_LGS8G54 5 + +struct lgs8gxx_config { + + /* product type */ + u8 prod; + + /* the demodulator's i2c address */ + u8 demod_address; + + /* parallel or serial transport stream */ + u8 serial_ts; + + /* transport stream polarity*/ + u8 ts_clk_pol; + + /* transport stream clock gated by ts_valid */ + u8 ts_clk_gated; + + /* A/D Clock frequency */ + u32 if_clk_freq; /* in kHz */ + + /* IF frequency */ + u32 if_freq; /* in kHz */ + + /*Use External ADC*/ + u8 ext_adc; + + /*External ADC output two's complement*/ + u8 adc_signed; + + /*Sample IF data at falling edge of IF_CLK*/ + u8 if_neg_edge; + + /*IF use Negative center frequency*/ + u8 if_neg_center; + + /* slave address and configuration of the tuner */ + u8 tuner_address; +}; + +#if defined(CONFIG_DVB_LGS8GXX) || \ + (defined(CONFIG_DVB_LGS8GXX_MODULE) && defined(MODULE)) +extern struct dvb_frontend *lgs8gxx_attach(const struct lgs8gxx_config *config, + struct i2c_adapter *i2c); +#else +static inline +struct dvb_frontend *lgs8gxx_attach(const struct lgs8gxx_config *config, + struct i2c_adapter *i2c) { + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); + return NULL; +} +#endif /* CONFIG_DVB_LGS8GXX */ + +#endif /* __LGS8GXX_H__ */ diff --git a/linux/drivers/media/dvb/frontends/lgs8gxx_priv.h b/linux/drivers/media/dvb/frontends/lgs8gxx_priv.h new file mode 100644 index 000000000..9776d3068 --- /dev/null +++ b/linux/drivers/media/dvb/frontends/lgs8gxx_priv.h @@ -0,0 +1,70 @@ +/* + * Support for Legend Silicon DMB-TH demodulator + * LGS8913, LGS8GL5 + * experimental support LGS8G42, LGS8G52 + * + * Copyright (C) 2007,2008 David T.L. Wong + * Copyright (C) 2008 Sirius International (Hong Kong) Limited + * Timothy Lee (for initial work on LGS8GL5) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifndef LGS8913_PRIV_H +#define LGS8913_PRIV_H + +struct lgs8gxx_state { + struct i2c_adapter *i2c; + /* configuration settings */ + const struct lgs8gxx_config *config; + struct dvb_frontend frontend; + u16 curr_gi; /* current guard interval */ +}; + +#define SC_MASK 0x1C /* Sub-Carrier Modulation Mask */ +#define SC_QAM64 0x10 /* 64QAM modulation */ +#define SC_QAM32 0x0C /* 32QAM modulation */ +#define SC_QAM16 0x08 /* 16QAM modulation */ +#define SC_QAM4NR 0x04 /* 4QAM modulation */ +#define SC_QAM4 0x00 /* 4QAM modulation */ + +#define LGS_FEC_MASK 0x03 /* FEC Rate Mask */ +#define LGS_FEC_0_4 0x00 /* FEC Rate 0.4 */ +#define LGS_FEC_0_6 0x01 /* FEC Rate 0.6 */ +#define LGS_FEC_0_8 0x02 /* FEC Rate 0.8 */ + +#define TIM_MASK 0x20 /* Time Interleave Length Mask */ +#define TIM_LONG 0x00 /* Time Interleave Length = 720 */ +#define TIM_MIDDLE 0x20 /* Time Interleave Length = 240 */ + +#define CF_MASK 0x80 /* Control Frame Mask */ +#define CF_EN 0x80 /* Control Frame On */ + +#define GI_MASK 0x03 /* Guard Interval Mask */ +#define GI_420 0x00 /* 1/9 Guard Interval */ +#define GI_595 0x01 /* */ +#define GI_945 0x02 /* 1/4 Guard Interval */ + + +#define TS_PARALLEL 0x00 /* Parallel TS Output a.k.a. SPI */ +#define TS_SERIAL 0x01 /* Serial TS Output a.k.a. SSI */ +#define TS_CLK_NORMAL 0x00 /* MPEG Clock Normal */ +#define TS_CLK_INVERTED 0x02 /* MPEG Clock Inverted */ +#define TS_CLK_GATED 0x00 /* MPEG clock gated */ +#define TS_CLK_FREERUN 0x04 /* MPEG clock free running*/ + + +#endif -- cgit v1.2.3 From 5d077a339744b7da7c3a5611c5d433ecdac55ecf Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 1 Apr 2009 20:25:00 +0000 Subject: Revert "V4L/DVB (10962): fired-avc: fix printk formatting warning." From: Stefan Richter Commit 34aecd2851bba5c2b7dae2f0dbe8e629b1c5e4ac was made obsolete and invalid by commit 40cf65d149053889c8876c6c2b4ce204fde55baa. Signed-off-by: Stefan Richter Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/firewire/firedtv-avc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/firewire/firedtv-avc.c b/linux/drivers/media/dvb/firewire/firedtv-avc.c index d8dae2599..79fab477c 100644 --- a/linux/drivers/media/dvb/firewire/firedtv-avc.c +++ b/linux/drivers/media/dvb/firewire/firedtv-avc.c @@ -150,7 +150,7 @@ static void debug_fcp(const u8 *data, size_t length) subunit_type = data[1] >> 3; subunit_id = data[1] & 7; op = subunit_type == 0x1e || subunit_id == 5 ? ~0 : data[2]; - printk(KERN_INFO "%ssu=%x.%x l=%zu: %-8s - %s\n", + printk(KERN_INFO "%ssu=%x.%x l=%d: %-8s - %s\n", prefix, subunit_type, subunit_id, length, debug_fcp_ctype(data[0]), debug_fcp_opcode(op, data, length)); -- cgit v1.2.3 From 42628535c1ee2b9d89e7fe0d4d430df926a2368c Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Thu, 2 Apr 2009 11:25:09 +0300 Subject: af9015: support for DigitalNow TinyTwin remote From: Stuart Hall Patch to provide basic support for DigitalNow TinyTwin Remote. It uses same remote as TwinHan AzureWave AD-TU700(704J). Priority: normal Signed-off-by: Stuart Hall Signed-off-by: Antti Palosaari --- linux/drivers/media/dvb/dvb-usb/af9015.c | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/dvb-usb/af9015.c b/linux/drivers/media/dvb/dvb-usb/af9015.c index 5feed970a..ceea6676b 100644 --- a/linux/drivers/media/dvb/dvb-usb/af9015.c +++ b/linux/drivers/media/dvb/dvb-usb/af9015.c @@ -785,17 +785,14 @@ static int af9015_read_config(struct usb_device *udev) ARRAY_SIZE(af9015_ir_table_leadtek); break; case USB_VID_VISIONPLUS: - if (udev->descriptor.idProduct == - cpu_to_le16(USB_PID_AZUREWAVE_AD_TU700)) { - af9015_properties[i].rc_key_map = - af9015_rc_keys_twinhan; - af9015_properties[i].rc_key_map_size = - ARRAY_SIZE(af9015_rc_keys_twinhan); - af9015_config.ir_table = - af9015_ir_table_twinhan; - af9015_config.ir_table_size = - ARRAY_SIZE(af9015_ir_table_twinhan); - } + af9015_properties[i].rc_key_map = + af9015_rc_keys_twinhan; + af9015_properties[i].rc_key_map_size = + ARRAY_SIZE(af9015_rc_keys_twinhan); + af9015_config.ir_table = + af9015_ir_table_twinhan; + af9015_config.ir_table_size = + ARRAY_SIZE(af9015_ir_table_twinhan); break; case USB_VID_KWORLD_2: /* TODO: use correct rc keys */ -- cgit v1.2.3 From 8e9910b286e583c460848c806cb7c0f6376acce4 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 2 Apr 2009 15:30:19 +0000 Subject: V4L/DVB: usbvision: remove unused #include From: Huang Weiyi Remove unused #include in drivers/media/video/usbvision/usbvision-i2c.c. Signed-off-by: Huang Weiyi Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/usbvision/usbvision-i2c.c | 1 - 1 file changed, 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/usbvision/usbvision-i2c.c b/linux/drivers/media/video/usbvision/usbvision-i2c.c index 3a315f89b..b74ada0c6 100644 --- a/linux/drivers/media/video/usbvision/usbvision-i2c.c +++ b/linux/drivers/media/video/usbvision/usbvision-i2c.c @@ -28,7 +28,6 @@ #include #include #include -#include #include #include #include -- cgit v1.2.3 From e6755c4d9f71332ff051c1b38fe17d48ebace5c6 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 2 Apr 2009 15:30:26 +0000 Subject: V4L/DVB: zr364xx: remove unused #include From: Huang Weiyi Remove unused #include in drivers/media/video/zr364xx.c. Signed-off-by: Huang Weiyi Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/zr364xx.c | 1 - 1 file changed, 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/zr364xx.c b/linux/drivers/media/video/zr364xx.c index 2e4d8147b..b8f47acab 100644 --- a/linux/drivers/media/video/zr364xx.c +++ b/linux/drivers/media/video/zr364xx.c @@ -26,7 +26,6 @@ */ -#include #include #include #include -- 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 d42082dc735f5ce9f74e24f05f118677d36bec4d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20Andr=C3=A9n?= Date: Sun, 3 May 2009 20:31:55 +0200 Subject: gspca - m5602: Checkpatch.pl fixes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: Erik Andrén Priority: normal Signed-off-by: Erik Andrén --- linux/drivers/media/video/gspca/m5602/m5602_core.c | 4 +++- linux/drivers/media/video/gspca/m5602/m5602_mt9m111.c | 6 ++++-- linux/drivers/media/video/gspca/m5602/m5602_s5k83a.c | 3 ++- 3 files changed, 9 insertions(+), 4 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/m5602/m5602_core.c b/linux/drivers/media/video/gspca/m5602/m5602_core.c index dd1024325..8a5bba16f 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_core.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_core.c @@ -113,7 +113,9 @@ int m5602_read_sensor(struct sd *sd, const u8 address, if (err < 0) return err; - /* Sensors with registers that only are one byte width are differently read */ + /* Sensors with registers that are of only + one byte width are differently read */ + /* FIXME: This works with the ov9650, but has issues with the po1030 */ if (sd->sensor->i2c_regW == 1) { err = m5602_write_bridge(sd, M5602_XB_I2C_CTRL, 1); diff --git a/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.c b/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.c index a9780dfc7..8c6d2a229 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.c @@ -350,7 +350,8 @@ int mt9m111_start(struct sd *sd) (sensor_settings[VFLIP_IDX] << 0) | (sensor_settings[HFLIP_IDX] << 1); - err = m5602_write_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B, data, 2); + err = m5602_write_sensor(sd, + MT9M111_SC_R_MODE_CONTEXT_B, data, 2); break; case 320: @@ -360,7 +361,8 @@ int mt9m111_start(struct sd *sd) MT9M111_RMB_COLUMN_SKIP_4X | (sensor_settings[VFLIP_IDX] << 0) | (sensor_settings[HFLIP_IDX] << 1); - err = m5602_write_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B, data, 2); + err = m5602_write_sensor(sd, + MT9M111_SC_R_MODE_CONTEXT_B, data, 2); break; } return err; diff --git a/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.c b/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.c index df21ad19a..7127321ac 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.c @@ -280,7 +280,8 @@ static int rotation_thread_function(void *data) vflip = !vflip; hflip = !hflip; } - s5k83a_set_flip_real((struct gspca_dev *) sd, vflip, hflip); + s5k83a_set_flip_real((struct gspca_dev *) sd, + vflip, hflip); } mutex_unlock(&sd->gspca_dev.usb_lock); -- cgit v1.2.3 From 97c5c3546fe066caa96e733f5ad03a4cb3a15e79 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20Andr=C3=A9n?= Date: Sun, 3 May 2009 20:45:48 +0200 Subject: gspca - stv06xx-vv6410: Add exposure ctrl MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: Erik Andrén Add the possibility to control the exposure on the vv6410 sensor Priority: normal Signed-off-by: Erik Andrén --- .../media/video/gspca/stv06xx/stv06xx_vv6410.c | 69 +++++++++++++++++++++- .../media/video/gspca/stv06xx/stv06xx_vv6410.h | 4 ++ 2 files changed, 72 insertions(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.c b/linux/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.c index 69c77c932..f6603a9de 100644 --- a/linux/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.c +++ b/linux/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.c @@ -84,8 +84,22 @@ static const struct ctrl vv6410_ctrl[] = { }, .set = vv6410_set_analog_gain, .get = vv6410_get_analog_gain + }, +#define EXPOSURE_IDX 3 + { + { + .id = V4L2_CID_EXPOSURE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "exposure", + .minimum = 0, + .maximum = 32768, + .step = 1, + .default_value = 20000 + }, + .set = vv6410_set_exposure, + .get = vv6410_get_exposure } -}; + }; static int vv6410_probe(struct sd *sd) { @@ -121,6 +135,7 @@ static int vv6410_probe(struct sd *sd) static int vv6410_init(struct sd *sd) { int err = 0, i; + s32 *sensor_settings = sd->sensor_priv; for (i = 0; i < ARRAY_SIZE(stv_bridge_init); i++) { /* if NULL then len contains single value */ @@ -142,6 +157,11 @@ static int vv6410_init(struct sd *sd) err = stv06xx_write_sensor_bytes(sd, (u8 *) vv6410_sensor_init, ARRAY_SIZE(vv6410_sensor_init)); + if (err < 0) + return err; + + err = vv6410_set_exposure(&sd->gspca_dev, + sensor_settings[EXPOSURE_IDX]); return (err < 0) ? err : 0; } @@ -318,3 +338,50 @@ static int vv6410_set_analog_gain(struct gspca_dev *gspca_dev, __s32 val) return (err < 0) ? err : 0; } + +static int vv6410_get_exposure(struct gspca_dev *gspca_dev, __s32 *val) +{ + struct sd *sd = (struct sd *) gspca_dev; + s32 *sensor_settings = sd->sensor_priv; + + *val = sensor_settings[EXPOSURE_IDX]; + + PDEBUG(D_V4L2, "Read exposure %d", *val); + + return 0; +} + +static int vv6410_set_exposure(struct gspca_dev *gspca_dev, __s32 val) +{ + int err; + struct sd *sd = (struct sd *) gspca_dev; + s32 *sensor_settings = sd->sensor_priv; + unsigned int fine, coarse; + + sensor_settings[EXPOSURE_IDX] = val; + + val = (val * val >> 14) + val / 4; + + fine = val % VV6410_CIF_LINELENGTH; + coarse = min(512, val / VV6410_CIF_LINELENGTH); + + PDEBUG(D_V4L2, "Set coarse exposure to %d, fine expsure to %d", + coarse, fine); + + err = stv06xx_write_sensor(sd, VV6410_FINEH, fine >> 8); + if (err < 0) + goto out; + + err = stv06xx_write_sensor(sd, VV6410_FINEL, fine & 0xff); + if (err < 0) + goto out; + + err = stv06xx_write_sensor(sd, VV6410_COARSEH, coarse >> 8); + if (err < 0) + goto out; + + err = stv06xx_write_sensor(sd, VV6410_COARSEL, coarse & 0xff); + +out: + return err; +} diff --git a/linux/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.h b/linux/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.h index 95ac55891..809f92264 100644 --- a/linux/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.h +++ b/linux/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.h @@ -173,6 +173,8 @@ #define VV6410_SUBSAMPLE 0x01 #define VV6410_CROP_TO_QVGA 0x02 +#define VV6410_CIF_LINELENGTH 415 + static int vv6410_probe(struct sd *sd); static int vv6410_start(struct sd *sd); static int vv6410_init(struct sd *sd); @@ -187,6 +189,8 @@ static int vv6410_get_vflip(struct gspca_dev *gspca_dev, __s32 *val); static int vv6410_set_vflip(struct gspca_dev *gspca_dev, __s32 val); static int vv6410_get_analog_gain(struct gspca_dev *gspca_dev, __s32 *val); static int vv6410_set_analog_gain(struct gspca_dev *gspca_dev, __s32 val); +static int vv6410_get_exposure(struct gspca_dev *gspca_dev, __s32 *val); +static int vv6410_set_exposure(struct gspca_dev *gspca_dev, __s32 val); const struct stv06xx_sensor stv06xx_sensor_vv6410 = { .name = "ST VV6410", -- cgit v1.2.3 From 310b6441c9746001ed44a26aa4167b198fa69cff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20Andr=C3=A9n?= Date: Fri, 3 Apr 2009 22:16:42 +0200 Subject: gspca - stv06xx-vv6410: No need to double set gain and exposure MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: Erik Andrén Priority: normal Signed-off-by: Erik Andrén --- linux/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.h | 6 ------ 1 file changed, 6 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.h b/linux/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.h index 809f92264..487d40555 100644 --- a/linux/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.h +++ b/linux/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.h @@ -246,12 +246,6 @@ static const u8 vv6410_sensor_init[][2] = { /* Pre-clock generator divide off */ {VV6410_DATAFORMAT, BIT(7) | BIT(0)}, - /* Exposure registers */ - {VV6410_FINEH, VV6410_FINE_EXPOSURE >> 8}, - {VV6410_FINEL, VV6410_FINE_EXPOSURE & 0xff}, - {VV6410_COARSEH, VV6410_COARSE_EXPOSURE >> 8}, - {VV6410_COARSEL, VV6410_COARSE_EXPOSURE & 0xff}, - {VV6410_ANALOGGAIN, 0xf0 | VV6410_DEFAULT_GAIN}, {VV6410_CLKDIV, VV6410_CLK_DIV_2}, /* System registers */ -- cgit v1.2.3 From 552e9393c3f36654b397349c63cbe94bfde4916e Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 3 Apr 2009 21:45:17 +0000 Subject: dsbr100 radio: convert to to v4l2_device From: Alexey Klimov dsbr100: convert to v4l2_device. Signed-off-by: Alexey Klimov Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/radio/dsbr100.c | 88 +++++++++++++++---------------------- 1 file changed, 36 insertions(+), 52 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/radio/dsbr100.c b/linux/drivers/media/radio/dsbr100.c index 155a75341..bd13bef85 100644 --- a/linux/drivers/media/radio/dsbr100.c +++ b/linux/drivers/media/radio/dsbr100.c @@ -33,6 +33,9 @@ History: + Version 0.45: + Converted to v4l2_device. + Version 0.44: Add suspend/resume functions, fix unplug of device, a lot of cleanups and fixes by Alexey Klimov @@ -88,7 +91,7 @@ #include #include #include -#include +#include #include #include #include "compat.h" @@ -98,39 +101,8 @@ */ #include /* for KERNEL_VERSION MACRO */ -#define DRIVER_VERSION "v0.44" -#define RADIO_VERSION KERNEL_VERSION(0, 4, 4) - -static struct v4l2_queryctrl radio_qctrl[] = { - { - .id = V4L2_CID_AUDIO_MUTE, - .name = "Mute", - .minimum = 0, - .maximum = 1, - .default_value = 1, - .type = V4L2_CTRL_TYPE_BOOLEAN, - }, -/* HINT: the disabled controls are only here to satify kradio and such apps */ - { .id = V4L2_CID_AUDIO_VOLUME, - .flags = V4L2_CTRL_FLAG_DISABLED, - }, - { - .id = V4L2_CID_AUDIO_BALANCE, - .flags = V4L2_CTRL_FLAG_DISABLED, - }, - { - .id = V4L2_CID_AUDIO_BASS, - .flags = V4L2_CTRL_FLAG_DISABLED, - }, - { - .id = V4L2_CID_AUDIO_TREBLE, - .flags = V4L2_CTRL_FLAG_DISABLED, - }, - { - .id = V4L2_CID_AUDIO_LOUDNESS, - .flags = V4L2_CTRL_FLAG_DISABLED, - }, -}; +#define DRIVER_VERSION "v0.45" +#define RADIO_VERSION KERNEL_VERSION(0, 4, 5) #define DRIVER_AUTHOR "Markus Demleitner " #define DRIVER_DESC "D-Link DSB-R100 USB FM radio driver" @@ -168,6 +140,8 @@ module_param(radio_nr, int, 0); struct dsbr100_device { struct usb_device *usbdev; struct video_device videodev; + struct v4l2_device v4l2_dev; + u8 *transfer_buffer; struct mutex lock; /* buffer locking */ int curfreq; @@ -387,6 +361,7 @@ static void usb_dsbr100_disconnect(struct usb_interface *intf) mutex_unlock(&radio->lock); video_unregister_device(&radio->videodev); + v4l2_device_disconnect(&radio->v4l2_dev); } @@ -482,14 +457,11 @@ static int vidioc_g_frequency(struct file *file, void *priv, static int vidioc_queryctrl(struct file *file, void *priv, struct v4l2_queryctrl *qc) { - int i; - - for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) { - if (qc->id && qc->id == radio_qctrl[i].id) { - memcpy(qc, &(radio_qctrl[i]), sizeof(*qc)); - return 0; - } + switch (qc->id) { + case V4L2_CID_AUDIO_MUTE: + return v4l2_ctrl_query_fill(qc, 0, 1, 1, 1); } + return -EINVAL; } @@ -659,6 +631,7 @@ static void usb_dsbr100_video_device_release(struct video_device *videodev) { struct dsbr100_device *radio = videodev_to_radio(videodev); + v4l2_device_unregister(&radio->v4l2_dev); kfree(radio->transfer_buffer); kfree(radio); } @@ -686,22 +659,15 @@ static const struct v4l2_ioctl_ops usb_dsbr100_ioctl_ops = { .vidioc_s_input = vidioc_s_input, }; -/* V4L2 interface */ -static struct video_device dsbr100_videodev_data = { - .name = "D-Link DSB-R 100", - .fops = &usb_dsbr100_fops, - .ioctl_ops = &usb_dsbr100_ioctl_ops, - .release = usb_dsbr100_video_device_release, -}; - /* check if the device is present and register with v4l and usb if it is */ static int usb_dsbr100_probe(struct usb_interface *intf, const struct usb_device_id *id) { struct dsbr100_device *radio; + struct v4l2_device *v4l2_dev; int retval; - radio = kmalloc(sizeof(struct dsbr100_device), GFP_KERNEL); + radio = kzalloc(sizeof(struct dsbr100_device), GFP_KERNEL); if (!radio) return -ENOMEM; @@ -713,17 +679,35 @@ static int usb_dsbr100_probe(struct usb_interface *intf, return -ENOMEM; } + v4l2_dev = &radio->v4l2_dev; + + retval = v4l2_device_register(&intf->dev, v4l2_dev); + if (retval < 0) { + v4l2_err(v4l2_dev, "couldn't register v4l2_device\n"); + kfree(radio->transfer_buffer); + kfree(radio); + return retval; + } + + strlcpy(radio->videodev.name, v4l2_dev->name, sizeof(radio->videodev.name)); + radio->videodev.v4l2_dev = v4l2_dev; + radio->videodev.fops = &usb_dsbr100_fops; + radio->videodev.ioctl_ops = &usb_dsbr100_ioctl_ops; + radio->videodev.release = usb_dsbr100_video_device_release; + mutex_init(&radio->lock); - radio->videodev = dsbr100_videodev_data; radio->removed = 0; radio->users = 0; radio->usbdev = interface_to_usbdev(intf); radio->curfreq = FREQ_MIN * FREQ_MUL; + video_set_drvdata(&radio->videodev, radio); + retval = video_register_device(&radio->videodev, VFL_TYPE_RADIO, radio_nr); if (retval < 0) { - dev_err(&intf->dev, "couldn't register video device\n"); + v4l2_err(v4l2_dev, "couldn't register video device\n"); + v4l2_device_unregister(v4l2_dev); kfree(radio->transfer_buffer); kfree(radio); return -EIO; -- cgit v1.2.3 From d8c90a34d26e8cef97a9eb86154d887b086ed42b Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 3 Apr 2009 21:45:27 +0000 Subject: radio-mr800: convert to to v4l2_device From: Alexey Klimov radio-mr800: convert to to v4l2_device. Signed-off-by: Alexey Klimov Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/radio/radio-mr800.c | 85 ++++++++++++--------------------- 1 file changed, 31 insertions(+), 54 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/radio/radio-mr800.c b/linux/drivers/media/radio/radio-mr800.c index c04c8887e..93d5a7aa6 100644 --- a/linux/drivers/media/radio/radio-mr800.c +++ b/linux/drivers/media/radio/radio-mr800.c @@ -43,6 +43,7 @@ * Douglas Schilling Landgraf and * David Ellingsworth * for discussion, help and support. + * Version 0.11: Converted to v4l2_device. * * Many things to do: * - Correct power managment of device (suspend & resume) @@ -59,7 +60,7 @@ #include #include #include -#include +#include #include #include #include /* for KERNEL_VERSION MACRO */ @@ -68,8 +69,8 @@ /* driver and module definitions */ #define DRIVER_AUTHOR "Alexey Klimov " #define DRIVER_DESC "AverMedia MR 800 USB FM radio driver" -#define DRIVER_VERSION "0.10" -#define RADIO_VERSION KERNEL_VERSION(0, 1, 0) +#define DRIVER_VERSION "0.11" +#define RADIO_VERSION KERNEL_VERSION(0, 1, 1) MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); @@ -114,38 +115,6 @@ static int radio_nr = -1; module_param(radio_nr, int, 0); MODULE_PARM_DESC(radio_nr, "Radio Nr"); -static struct v4l2_queryctrl radio_qctrl[] = { - { - .id = V4L2_CID_AUDIO_MUTE, - .name = "Mute", - .minimum = 0, - .maximum = 1, - .step = 1, - .default_value = 1, - .type = V4L2_CTRL_TYPE_BOOLEAN, - }, -/* HINT: the disabled controls are only here to satify kradio and such apps */ - { .id = V4L2_CID_AUDIO_VOLUME, - .flags = V4L2_CTRL_FLAG_DISABLED, - }, - { - .id = V4L2_CID_AUDIO_BALANCE, - .flags = V4L2_CTRL_FLAG_DISABLED, - }, - { - .id = V4L2_CID_AUDIO_BASS, - .flags = V4L2_CTRL_FLAG_DISABLED, - }, - { - .id = V4L2_CID_AUDIO_TREBLE, - .flags = V4L2_CTRL_FLAG_DISABLED, - }, - { - .id = V4L2_CID_AUDIO_LOUDNESS, - .flags = V4L2_CTRL_FLAG_DISABLED, - }, -}; - static int usb_amradio_probe(struct usb_interface *intf, const struct usb_device_id *id); static void usb_amradio_disconnect(struct usb_interface *intf); @@ -160,6 +129,7 @@ struct amradio_device { /* reference to USB and video device */ struct usb_device *usbdev; struct video_device *videodev; + struct v4l2_device v4l2_dev; unsigned char *buffer; struct mutex lock; /* buffer locking */ @@ -332,6 +302,7 @@ static void usb_amradio_disconnect(struct usb_interface *intf) usb_set_intfdata(intf, NULL); video_unregister_device(radio->videodev); + v4l2_device_disconnect(&radio->v4l2_dev); } /* vidioc_querycap - query device capabilities */ @@ -466,14 +437,11 @@ static int vidioc_g_frequency(struct file *file, void *priv, static int vidioc_queryctrl(struct file *file, void *priv, struct v4l2_queryctrl *qc) { - int i; - - for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) { - if (qc->id && qc->id == radio_qctrl[i].id) { - memcpy(qc, &(radio_qctrl[i]), sizeof(*qc)); - return 0; - } + switch (qc->id) { + case V4L2_CID_AUDIO_MUTE: + return v4l2_ctrl_query_fill(qc, 0, 1, 1, 1); } + return -EINVAL; } @@ -674,34 +642,29 @@ static const struct v4l2_ioctl_ops usb_amradio_ioctl_ops = { .vidioc_s_input = vidioc_s_input, }; -static void usb_amradio_device_release(struct video_device *videodev) +static void usb_amradio_video_device_release(struct video_device *videodev) { struct amradio_device *radio = video_get_drvdata(videodev); /* we call v4l to free radio->videodev */ video_device_release(videodev); + v4l2_device_unregister(&radio->v4l2_dev); + /* free rest memory */ kfree(radio->buffer); kfree(radio); } -/* V4L2 interface */ -static struct video_device amradio_videodev_template = { - .name = "AverMedia MR 800 USB FM Radio", - .fops = &usb_amradio_fops, - .ioctl_ops = &usb_amradio_ioctl_ops, - .release = usb_amradio_device_release, -}; - /* check if the device is present and register with v4l and usb if it is */ static int usb_amradio_probe(struct usb_interface *intf, const struct usb_device_id *id) { struct amradio_device *radio; + struct v4l2_device *v4l2_dev; int retval; - radio = kmalloc(sizeof(struct amradio_device), GFP_KERNEL); + radio = kzalloc(sizeof(struct amradio_device), GFP_KERNEL); if (!radio) { dev_err(&intf->dev, "kmalloc for amradio_device failed\n"); @@ -716,6 +679,15 @@ static int usb_amradio_probe(struct usb_interface *intf, return -ENOMEM; } + v4l2_dev = &radio->v4l2_dev; + retval = v4l2_device_register(&intf->dev, v4l2_dev); + if (retval < 0) { + dev_err(&intf->dev, "couldn't register v4l2_device\n"); + kfree(radio->buffer); + kfree(radio); + return retval; + } + radio->videodev = video_device_alloc(); if (!radio->videodev) { @@ -725,8 +697,11 @@ static int usb_amradio_probe(struct usb_interface *intf, return -ENOMEM; } - memcpy(radio->videodev, &amradio_videodev_template, - sizeof(amradio_videodev_template)); + strlcpy(radio->videodev->name, v4l2_dev->name, sizeof(radio->videodev->name)); + radio->videodev->v4l2_dev = v4l2_dev; + radio->videodev->fops = &usb_amradio_fops; + radio->videodev->ioctl_ops = &usb_amradio_ioctl_ops; + radio->videodev->release = usb_amradio_video_device_release; radio->removed = 0; radio->users = 0; @@ -737,10 +712,12 @@ static int usb_amradio_probe(struct usb_interface *intf, mutex_init(&radio->lock); video_set_drvdata(radio->videodev, radio); + retval = video_register_device(radio->videodev, VFL_TYPE_RADIO, radio_nr); if (retval < 0) { dev_err(&intf->dev, "could not register video device\n"); video_device_release(radio->videodev); + v4l2_device_unregister(v4l2_dev); kfree(radio->buffer); kfree(radio); return -EIO; -- cgit v1.2.3 From f538ed735dbd437ed99b9a22368c2c70f5cf0db2 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 4 Apr 2009 21:13:33 +0000 Subject: pvrusb2: Drop client_register/unregister stubs From: Jean Delvare The client_register and client_unregister methods are optional so there is no point in defining stub ones. Especially when these methods are likely to be removed soon. Signed-off-by: Jean Delvare Acked-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c | 12 ------------ 1 file changed, 12 deletions(-) (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 fde4d3bd1..919a4f4e1 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c @@ -595,16 +595,6 @@ static u32 pvr2_i2c_functionality(struct i2c_adapter *adap) return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_I2C; } -static int pvr2_i2c_attach_inform(struct i2c_client *client) -{ - return 0; -} - -static int pvr2_i2c_detach_inform(struct i2c_client *client) -{ - return 0; -} - static struct i2c_algorithm pvr2_i2c_algo_template = { .master_xfer = pvr2_i2c_xfer, .functionality = pvr2_i2c_functionality, @@ -617,8 +607,6 @@ static struct i2c_adapter pvr2_i2c_adap_template = { .owner = THIS_MODULE, .class = 0, .id = I2C_HW_B_BT848, - .client_register = pvr2_i2c_attach_inform, - .client_unregister = pvr2_i2c_detach_inform, }; -- cgit v1.2.3 From f5ea7eb5503fdf00a99adcd6ef0d43271f6cecda Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 20 Apr 2009 11:35:06 -0300 Subject: Siano: SDIO interface driver - remove two redundant lines From: Uri Shkolnik Remove two redundant lines, based on Klimov Alexey code review. Priority: normal Signed-off-by: Uri Shkolnik Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/siano/smssdio.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/siano/smssdio.c b/linux/drivers/media/dvb/siano/smssdio.c index 31ba8c5af..4f8fa59a9 100644 --- a/linux/drivers/media/dvb/siano/smssdio.c +++ b/linux/drivers/media/dvb/siano/smssdio.c @@ -96,8 +96,6 @@ static int smssdio_sendrequest(void *context, void *buffer, size_t size) if (size) { ret = sdio_write_bytes(smsdev->func, SMSSDIO_DATA, buffer, size); - if (ret) - goto out; } out: -- cgit v1.2.3 From 82c030337cbead2e29d30808dcab8e558c4dfa89 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 5 Apr 2009 08:12:51 +0000 Subject: Siano: core header - add definitions and structures From: Uri Shkolnik [PATCH] [0904_2] Siano: core header - add definitions and structures Add new definitions (of Siano's protocol messages), and protocol structures (for future commits usage) Priority: normal Signed-off-by: Uri Shkolnik Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/siano/smscoreapi.h | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/siano/smscoreapi.h b/linux/drivers/media/dvb/siano/smscoreapi.h index 85da09f86..cac8fe2be 100644 --- a/linux/drivers/media/dvb/siano/smscoreapi.h +++ b/linux/drivers/media/dvb/siano/smscoreapi.h @@ -47,6 +47,7 @@ #define min(a, b) (((a) < (b)) ? (a) : (b)) #endif +#define SMS_PROTOCOL_MAX_RAOUNDTRIP_MS (10000) #define SMS_ALLOC_ALIGNMENT 128 #define SMS_DMA_ALIGNMENT 16 #define SMS_ALIGN_ADDRESS(addr) \ @@ -162,6 +163,7 @@ struct smsclient_params_t { #define MSG_SMS_GET_PID_FILTER_LIST_RES 609 #define MSG_SMS_GET_STATISTICS_REQ 615 #define MSG_SMS_GET_STATISTICS_RES 616 +#define MSG_SMS_HO_PER_SLICES_IND 630 #define MSG_SMS_SET_ANTENNA_CONFIG_REQ 651 #define MSG_SMS_SET_ANTENNA_CONFIG_RES 652 #define MSG_SMS_GET_STATISTICS_EX_REQ 653 @@ -191,6 +193,13 @@ struct smsclient_params_t { #define MSG_SMS_GPIO_CONFIG_EX_RES 713 #define MSG_SMS_ISDBT_TUNE_REQ 776 #define MSG_SMS_ISDBT_TUNE_RES 777 +#define MSG_SMS_TRANSMISSION_IND 782 +#define MSG_SMS_START_IR_REQ 800 +#define MSG_SMS_START_IR_RES 801 +#define MSG_SMS_IR_SAMPLES_IND 802 +#define MSG_SMS_SIGNAL_DETECTED_IND 827 +#define MSG_SMS_NO_SIGNAL_IND 828 + #define SMS_INIT_MSG_EX(ptr, type, src, dst, len) do { \ (ptr)->msgType = type; (ptr)->msgSrcId = src; (ptr)->msgDstId = dst; \ @@ -198,6 +207,15 @@ struct smsclient_params_t { } while (0) #define SMS_INIT_MSG(ptr, type, len) \ SMS_INIT_MSG_EX(ptr, type, 0, HIF_TASK, len) +enum SMS_DVB3_EVENTS { + DVB3_EVENT_INIT = 0, + DVB3_EVENT_SLEEP, + DVB3_EVENT_HOTPLUG, + DVB3_EVENT_FE_LOCK, + DVB3_EVENT_FE_UNLOCK, + DVB3_EVENT_UNC_OK, + DVB3_EVENT_UNC_ERR +}; enum SMS_DEVICE_MODE { DEVICE_MODE_NONE = -1, @@ -222,8 +240,13 @@ struct SmsMsgHdr_ST { }; struct SmsMsgData_ST { - struct SmsMsgHdr_ST xMsgHeader; - u32 msgData[1]; + struct SmsMsgHdr_ST xMsgHeader; + u32 msgData[1]; +}; + +struct SmsMsgData_ST2 { + struct SmsMsgHdr_ST xMsgHeader; + u32 msgData[2]; }; struct SmsDataDownload_ST { -- cgit v1.2.3 From 4c25b22d66ac58fedf280b2d59dcc38ebc17dbed Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 5 Apr 2009 08:21:23 +0000 Subject: [PATCH] [0904_3] Siano: core - move and update the main core structure declaration From: Uri Shkolnik smscoreapi - move the main core structure declaration to the header, in order to enable other components (such as IR) to use it. Priority: normal Signed-off-by: Uri Shkolnik Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/siano/smscoreapi.c | 36 -------------------- linux/drivers/media/dvb/siano/smscoreapi.h | 54 ++++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+), 36 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/siano/smscoreapi.c b/linux/drivers/media/dvb/siano/smscoreapi.c index 8c37a060b..9a9db2588 100644 --- a/linux/drivers/media/dvb/siano/smscoreapi.c +++ b/linux/drivers/media/dvb/siano/smscoreapi.c @@ -58,42 +58,6 @@ struct smscore_client_t { onremove_t onremove_handler; }; -struct smscore_device_t { - struct list_head entry; - - struct list_head clients; - struct list_head subclients; - spinlock_t clientslock; - - struct list_head buffers; - spinlock_t bufferslock; - int num_buffers; - - void *common_buffer; - int common_buffer_size; - dma_addr_t common_buffer_phys; - - void *context; - struct device *device; - - char devpath[32]; - unsigned long device_flags; - - setmode_t setmode_handler; - detectmode_t detectmode_handler; - sendrequest_t sendrequest_handler; - preload_t preload_handler; - postload_t postload_handler; - - int mode, modes_supported; - - struct completion version_ex_done, data_download_done, trigger_done; - struct completion init_device_done, reload_start_done, resume_done; - - int board_id; - int led_state; -}; - void smscore_set_board_id(struct smscore_device_t *core, int id) { core->board_id = id; diff --git a/linux/drivers/media/dvb/siano/smscoreapi.h b/linux/drivers/media/dvb/siano/smscoreapi.h index cac8fe2be..54264b5d3 100644 --- a/linux/drivers/media/dvb/siano/smscoreapi.h +++ b/linux/drivers/media/dvb/siano/smscoreapi.h @@ -122,6 +122,60 @@ struct smsclient_params_t { void *context; }; +struct smscore_device_t { + struct list_head entry; + + struct list_head clients; + struct list_head subclients; + spinlock_t clientslock; + + struct list_head buffers; + spinlock_t bufferslock; + int num_buffers; + + void *common_buffer; + int common_buffer_size; + dma_addr_t common_buffer_phys; + + void *context; + struct device *device; + + char devpath[32]; + unsigned long device_flags; + + setmode_t setmode_handler; + detectmode_t detectmode_handler; + sendrequest_t sendrequest_handler; + preload_t preload_handler; + postload_t postload_handler; + + int mode, modes_supported; + + /* host <--> device messages */ + struct completion version_ex_done, data_download_done, trigger_done; + struct completion init_device_done, reload_start_done, resume_done; + struct completion gpio_configuration_done, gpio_set_level_done; + struct completion gpio_get_level_done, ir_init_done; + + /* Buffer management */ + wait_queue_head_t buffer_mng_waitq; + + /* GPIO */ + int gpio_get_res; + + /* Target hardware board */ + int board_id; + + /* Firmware */ + u8 *fw_buf; + u32 fw_buf_size; + + /* Infrared (IR) */ + /* struct ir_t ir; */ + + int led_state; +}; + /* GPIO definitions for antenna frequency domain control (SMS8021) */ #define SMS_ANTENNA_GPIO_0 1 #define SMS_ANTENNA_GPIO_1 0 -- cgit v1.2.3 From 8e8624523d0528593547570641d323fb709775b5 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 5 Apr 2009 08:26:50 +0000 Subject: [PATCH] [0904_5] Siano: core header - indentation From: Uri Shkolnik Some more indentation for the smscoreapi.h There are no implementation changes in this patch. Priority: normal Signed-off-by: Uri Shkolnik Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/siano/smscoreapi.h | 42 ++++++++++++++++-------------- 1 file changed, 23 insertions(+), 19 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/siano/smscoreapi.h b/linux/drivers/media/dvb/siano/smscoreapi.h index 54264b5d3..83e0e55f7 100644 --- a/linux/drivers/media/dvb/siano/smscoreapi.h +++ b/linux/drivers/media/dvb/siano/smscoreapi.h @@ -47,14 +47,14 @@ #define min(a, b) (((a) < (b)) ? (a) : (b)) #endif -#define SMS_PROTOCOL_MAX_RAOUNDTRIP_MS (10000) -#define SMS_ALLOC_ALIGNMENT 128 -#define SMS_DMA_ALIGNMENT 16 +#define SMS_PROTOCOL_MAX_RAOUNDTRIP_MS (10000) +#define SMS_ALLOC_ALIGNMENT 128 +#define SMS_DMA_ALIGNMENT 16 #define SMS_ALIGN_ADDRESS(addr) \ ((((uintptr_t)(addr)) + (SMS_DMA_ALIGNMENT-1)) & ~(SMS_DMA_ALIGNMENT-1)) -#define SMS_DEVICE_FAMILY2 1 -#define SMS_ROM_NO_RESPONSE 2 +#define SMS_DEVICE_FAMILY2 1 +#define SMS_ROM_NO_RESPONSE 2 #define SMS_DEVICE_NOT_READY 0x8000000 enum sms_device_type_st { @@ -85,13 +85,13 @@ typedef void (*onremove_t)(void *context); struct smscore_buffer_t { /* public members, once passed to clients can be changed freely */ struct list_head entry; - int size; - int offset; + int size; + int offset; /* private members, read-only for clients */ - void *p; - dma_addr_t phys; - unsigned long offset_in_common; + void *p; + dma_addr_t phys; + unsigned long offset_in_common; }; struct smsdevice_params_t { @@ -118,7 +118,6 @@ struct smsclient_params_t { int data_type; onresponse_t onresponse_handler; onremove_t onremove_handler; - void *context; }; @@ -254,13 +253,14 @@ struct smscore_device_t { #define MSG_SMS_SIGNAL_DETECTED_IND 827 #define MSG_SMS_NO_SIGNAL_IND 828 - #define SMS_INIT_MSG_EX(ptr, type, src, dst, len) do { \ (ptr)->msgType = type; (ptr)->msgSrcId = src; (ptr)->msgDstId = dst; \ (ptr)->msgLength = len; (ptr)->msgFlags = 0; \ } while (0) + #define SMS_INIT_MSG(ptr, type, len) \ SMS_INIT_MSG_EX(ptr, type, 0, HIF_TASK, len) + enum SMS_DVB3_EVENTS { DVB3_EVENT_INIT = 0, DVB3_EVENT_SLEEP, @@ -316,11 +316,12 @@ struct SmsVersionRes_ST { u8 Step; /* 0 - Step A */ u8 MetalFix; /* 0 - Metal 0 */ - u8 FirmwareId; /* 0xFF � ROM, otherwise the - * value indicated by - * SMSHOSTLIB_DEVICE_MODES_E */ - u8 SupportedProtocols; /* Bitwise OR combination of + /* FirmwareId 0xFF if ROM, otherwise the + * value indicated by SMSHOSTLIB_DEVICE_MODES_E */ + u8 FirmwareId; + /* SupportedProtocols Bitwise OR combination of * supported protocols */ + u8 SupportedProtocols; u8 VersionMajor; u8 VersionMinor; @@ -354,10 +355,12 @@ struct SMSHOSTLIB_STATISTICS_ST { s32 SNR; /* dB */ u32 BER; /* Post Viterbi BER [1E-5] */ u32 FIB_CRC; /* CRC errors percentage, valid only for DAB */ - u32 TS_PER; /* Transport stream PER, 0xFFFFFFFF indicate N/A, + /* Transport stream PER, 0xFFFFFFFF indicate N/A, * valid only for DVB-T/H */ - u32 MFER; /* DVB-H frame error rate in percentage, + u32 TS_PER; + /* DVB-H frame error rate in percentage, * 0xFFFFFFFF indicate N/A, valid only for DVB-H */ + u32 MFER; s32 RSSI; /* dBm */ s32 InBandPwr; /* In band power in dBM */ s32 CarrierOffset; /* Carrier Offset in bin/1024 */ @@ -365,8 +368,9 @@ struct SMSHOSTLIB_STATISTICS_ST { /* Transmission parameters, valid only for DVB-T/H */ u32 Frequency; /* Frequency in Hz */ u32 Bandwidth; /* Bandwidth in MHz */ - u32 TransmissionMode; /* Transmission Mode, for DAB modes 1-4, + /* Transmission Mode, for DAB modes 1-4, * for DVB-T/H FFT mode carriers in Kilos */ + u32 TransmissionMode; u32 ModemState; /* from SMS_DvbModemState_ET */ u32 GuardInterval; /* Guard Interval, 1 divided by value */ u32 CodeRate; /* Code Rate from SMS_DvbModemState_ET */ -- cgit v1.2.3 From ddf57e9054c6d575bd185bcfe58cca2214ae330e Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 5 Apr 2009 09:01:37 +0000 Subject: [PATCH] [0904_9] Siano: add support for infra-red (IR) controllers From: Uri Shkolnik This patch add support for IR (infra-red) remote controllers. Further commits are needed in order to enable the activation of the IR components. Priority: normal Signed-off-by: Uri Shkolnik Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/siano/smsir.c | 301 ++++++++++++++++++++++++++++++++++ linux/drivers/media/dvb/siano/smsir.h | 93 +++++++++++ 2 files changed, 394 insertions(+) create mode 100644 linux/drivers/media/dvb/siano/smsir.c create mode 100644 linux/drivers/media/dvb/siano/smsir.h (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/siano/smsir.c b/linux/drivers/media/dvb/siano/smsir.c new file mode 100644 index 000000000..a5f302c58 --- /dev/null +++ b/linux/drivers/media/dvb/siano/smsir.c @@ -0,0 +1,301 @@ +/**************************************************************** + + Siano Mobile Silicon, Inc. + MDTV receiver kernel modules. + Copyright (C) 2006-2009, Uri Shkolnik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + + ****************************************************************/ + + +#include +#include + +#include "smscoreapi.h" +#include "smsir.h" +#include "sms-cards.h" + +/* In order to add new IR remote control - + * 1) Add it to the @ smsir,h, + * 2) Add its map to keyboard_layout_maps below + * 3) Set your board (sms-cards sub-module) to use it + */ + +static struct keyboard_layout_map_t keyboard_layout_maps[] = { + [SMS_IR_KB_DEFAULT_TV] = { + .ir_protocol = IR_RC5, + .rc5_kbd_address = KEYBOARD_ADDRESS_TV1, + .keyboard_layout_map = { + KEY_0, KEY_1, KEY_2, + KEY_3, KEY_4, KEY_5, + KEY_6, KEY_7, KEY_8, + KEY_9, 0, 0, KEY_POWER, + KEY_MUTE, 0, 0, + KEY_VOLUMEUP, KEY_VOLUMEDOWN, + KEY_BRIGHTNESSUP, + KEY_BRIGHTNESSDOWN, KEY_CHANNELUP, + KEY_CHANNELDOWN, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + } + }, + [SMS_IR_KB_HCW_SILVER] = { + .ir_protocol = IR_RC5, + .rc5_kbd_address = KEYBOARD_ADDRESS_LIGHTING1, + .keyboard_layout_map = { + KEY_0, KEY_1, KEY_2, + KEY_3, KEY_4, KEY_5, + KEY_6, KEY_7, KEY_8, + KEY_9, KEY_TEXT, KEY_RED, + KEY_RADIO, KEY_MENU, + KEY_SUBTITLE, + KEY_MUTE, KEY_VOLUMEUP, + KEY_VOLUMEDOWN, KEY_PREVIOUS, 0, + KEY_UP, KEY_DOWN, KEY_LEFT, + KEY_RIGHT, KEY_VIDEO, KEY_AUDIO, + KEY_MHP, KEY_EPG, KEY_TV, + 0, KEY_NEXTSONG, KEY_EXIT, + KEY_CHANNELUP, KEY_CHANNELDOWN, + KEY_CHANNEL, 0, + KEY_PREVIOUSSONG, KEY_ENTER, + KEY_SLEEP, 0, 0, KEY_BLUE, + 0, 0, 0, 0, KEY_GREEN, 0, + KEY_PAUSE, 0, KEY_REWIND, + 0, KEY_FASTFORWARD, KEY_PLAY, + KEY_STOP, KEY_RECORD, + KEY_YELLOW, 0, 0, KEY_SELECT, + KEY_ZOOM, KEY_POWER, 0, 0 + } + }, + { } /* Terminating entry */ +}; + +u32 ir_pos; +u32 ir_word; +u32 ir_toggle; + +#define RC5_PUSH_BIT(dst, bit, pos) \ + { dst <<= 1; dst |= bit; pos++; } + + +static void sms_ir_rc5_event(struct smscore_device_t *coredev, + u32 toggle, u32 addr, u32 cmd) +{ + bool toggle_changed; + u16 keycode; + + sms_info("IR RC5 word: address %d, command %d, toggle %d", + addr, cmd, toggle); + + toggle_changed = ir_toggle != toggle; + /* keep toggle */ + ir_toggle = toggle; + + if (addr != + keyboard_layout_maps[coredev->ir.ir_kb_type].rc5_kbd_address) + return; /* Check for valid address */ + + keycode = + keyboard_layout_maps + [coredev->ir.ir_kb_type].keyboard_layout_map[cmd]; + + if (!toggle_changed && + (keycode != KEY_VOLUMEUP && keycode != KEY_VOLUMEDOWN)) + return; /* accept only repeated volume, reject other keys */ + + sms_info("kernel input keycode (from ir) %d", keycode); + input_report_key(coredev->ir.input_dev, keycode, 1); + input_sync(coredev->ir.input_dev); + +} + +/* decode raw bit pattern to RC5 code */ +/* taken from ir-functions.c */ +static u32 ir_rc5_decode(unsigned int code) +{ +/* unsigned int org_code = code;*/ + unsigned int pair; + unsigned int rc5 = 0; + int i; + + for (i = 0; i < 14; ++i) { + pair = code & 0x3; + code >>= 2; + + rc5 <<= 1; + switch (pair) { + case 0: + case 2: + break; + case 1: + rc5 |= 1; + break; + case 3: +/* dprintk(1, "ir-common: ir_rc5_decode(%x) bad code\n", org_code);*/ + sms_info("bad code"); + return 0; + } + } +/* + dprintk(1, "ir-common: code=%x, rc5=%x, start=%x, + toggle=%x, address=%x, " + "instr=%x\n", rc5, org_code, RC5_START(rc5), + RC5_TOGGLE(rc5), RC5_ADDR(rc5), RC5_INSTR(rc5)); +*/ + return rc5; +} + +static void sms_rc5_parse_word(struct smscore_device_t *coredev) +{ + #define RC5_START(x) (((x)>>12)&3) + #define RC5_TOGGLE(x) (((x)>>11)&1) + #define RC5_ADDR(x) (((x)>>6)&0x1F) + #define RC5_INSTR(x) ((x)&0x3F) + + int i, j; + u32 rc5_word = 0; + + /* Reverse the IR word direction */ + for (i = 0 ; i < 28 ; i++) + 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_ir_rc5_event(coredev, + RC5_TOGGLE(rc5_word), + RC5_ADDR(rc5_word), + RC5_INSTR(rc5_word)); +} + + +static void sms_rc5_accumulate_bits(struct smscore_device_t *coredev, + s32 ir_sample) +{ + #define RC5_TIME_GRANULARITY 200 + #define RC5_DEF_BIT_TIME 889 + #define RC5_MAX_SAME_BIT_CONT 4 + #define RC5_WORD_LEN 27 /* 28 bit */ + + u32 i, j; + s32 delta_time; + u32 time = (ir_sample > 0) ? ir_sample : (0-ir_sample); + u32 level = (ir_sample < 0) ? 0 : 1; + + for (i = RC5_MAX_SAME_BIT_CONT; i > 0; i--) { + delta_time = time - (i*RC5_DEF_BIT_TIME) + RC5_TIME_GRANULARITY; + if (delta_time < 0) + continue; /* not so many consecutive bits */ + if (delta_time > (2 * RC5_TIME_GRANULARITY)) { + /* timeout */ + if (ir_pos == (RC5_WORD_LEN-1)) + /* complete last bit */ + RC5_PUSH_BIT(ir_word, level, ir_pos) + + 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"); + + ir_pos = 0; + ir_word = 0; + /* sms_info("timeout %d", time); */ + break; + } + /* The time is within the range of this number of bits */ + for (j = 0 ; j < i ; j++) + RC5_PUSH_BIT(ir_word, level, ir_pos) + + break; + } +} + +void sms_ir_event(struct smscore_device_t *coredev, const char *buf, int len) +{ + #define IR_DATA_RECEIVE_MAX_LEN 520 /* 128*4 + 4 + 4 */ + u32 i; + enum ir_protocol ir_protocol = + keyboard_layout_maps[coredev->ir.ir_kb_type] + .ir_protocol; + s32 *samples; + int count = len>>2; + + samples = (s32 *)buf; +/* sms_info("IR buffer received, length = %d", count);*/ + + for (i = 0; i < count; i++) + if (ir_protocol == IR_RC5) + sms_rc5_accumulate_bits(coredev, samples[i]); + /* IR_RCMM not implemented */ +} + +int sms_ir_init(struct smscore_device_t *coredev) +{ + struct input_dev *input_dev; + + sms_info("Allocating input device"); + input_dev = input_allocate_device(); + if (!input_dev) { + sms_err("Not enough memory"); + return -ENOMEM; + } + + coredev->ir.input_dev = input_dev; + coredev->ir.ir_kb_type = + sms_get_board(smscore_get_board_id(coredev))->ir_kb_type; + 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); + + coredev->ir.controller = 0; /* Todo: vega/nova SPI number */ + coredev->ir.timeout = IR_DEFAULT_TIMEOUT; + sms_info("IR port %d, timeout %d ms", + coredev->ir.controller, coredev->ir.timeout); + + snprintf(coredev->ir.name, + IR_DEV_NAME_MAX_LEN, + "SMS IR w/kbd type %d", + coredev->ir.ir_kb_type); + input_dev->name = coredev->ir.name; + input_dev->phys = coredev->ir.name; + input_dev->dev.parent = coredev->device; + + /* Key press events only */ + 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); + + if (input_register_device(input_dev)) { + sms_err("Failed to register device"); + input_free_device(input_dev); + return -EACCES; + } + + return 0; +} + +void sms_ir_exit(struct smscore_device_t *coredev) +{ + if (coredev->ir.input_dev) + input_unregister_device(coredev->ir.input_dev); + + sms_info(""); +} + diff --git a/linux/drivers/media/dvb/siano/smsir.h b/linux/drivers/media/dvb/siano/smsir.h new file mode 100644 index 000000000..b7d703e2d --- /dev/null +++ b/linux/drivers/media/dvb/siano/smsir.h @@ -0,0 +1,93 @@ +/**************************************************************** + +Siano Mobile Silicon, Inc. +MDTV receiver kernel modules. +Copyright (C) 2006-2009, Uri Shkolnik + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 of the License, or +(at your option) any later version. + + This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . + +****************************************************************/ + +#ifndef __SMS_IR_H__ +#define __SMS_IR_H__ + +#include + +#define IR_DEV_NAME_MAX_LEN 23 /* "SMS IR kbd type nn\0" */ +#define IR_KEYBOARD_LAYOUT_SIZE 64 +#define IR_DEFAULT_TIMEOUT 100 + +enum ir_kb_type { + SMS_IR_KB_DEFAULT_TV, + SMS_IR_KB_HCW_SILVER +}; + +enum rc5_keyboard_address { + KEYBOARD_ADDRESS_TV1 = 0, + KEYBOARD_ADDRESS_TV2 = 1, + KEYBOARD_ADDRESS_TELETEXT = 2, + KEYBOARD_ADDRESS_VIDEO = 3, + KEYBOARD_ADDRESS_LV1 = 4, + KEYBOARD_ADDRESS_VCR1 = 5, + KEYBOARD_ADDRESS_VCR2 = 6, + KEYBOARD_ADDRESS_EXPERIMENTAL = 7, + KEYBOARD_ADDRESS_SAT1 = 8, + KEYBOARD_ADDRESS_CAMERA = 9, + KEYBOARD_ADDRESS_SAT2 = 10, + KEYBOARD_ADDRESS_CDV = 12, + KEYBOARD_ADDRESS_CAMCORDER = 13, + KEYBOARD_ADDRESS_PRE_AMP = 16, + KEYBOARD_ADDRESS_TUNER = 17, + KEYBOARD_ADDRESS_RECORDER1 = 18, + KEYBOARD_ADDRESS_PRE_AMP1 = 19, + KEYBOARD_ADDRESS_CD_PLAYER = 20, + KEYBOARD_ADDRESS_PHONO = 21, + KEYBOARD_ADDRESS_SATA = 22, + KEYBOARD_ADDRESS_RECORDER2 = 23, + KEYBOARD_ADDRESS_CDR = 26, + KEYBOARD_ADDRESS_LIGHTING = 29, + KEYBOARD_ADDRESS_LIGHTING1 = 30, /* KEYBOARD_ADDRESS_HCW_SILVER */ + KEYBOARD_ADDRESS_PHONE = 31, + KEYBOARD_ADDRESS_NOT_RC5 = 0xFFFF +}; + +enum ir_protocol { + IR_RC5, + IR_RCMM +}; + +struct keyboard_layout_map_t { + enum ir_protocol ir_protocol; + enum rc5_keyboard_address rc5_kbd_address; + u16 keyboard_layout_map[IR_KEYBOARD_LAYOUT_SIZE]; +}; + +struct smscore_device_t; + +struct ir_t { + struct input_dev *input_dev; + enum ir_kb_type ir_kb_type; + char name[IR_DEV_NAME_MAX_LEN+1]; + u16 *keyboard_layout_map; + u32 timeout; + u32 controller; +}; + +int sms_ir_init(struct smscore_device_t *coredev); +void sms_ir_exit(struct smscore_device_t *coredev); +void sms_ir_event(struct smscore_device_t *coredev, + const char *buf, int len); + +#endif /* __SMS_IR_H__ */ + -- cgit v1.2.3 From 56e85790c8d7256d555de35a62fa0e13535f62fd Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 20 Apr 2009 13:00:52 -0300 Subject: Siano: add messages handling for big-endian target From: Uri Shkolnik Add code that modify the content of Siano's protocol messages when running with big-endian target. Priority: normal Signed-off-by: Uri Shkolnik Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/siano/smsendian.c | 100 ++++++++++++++++++++++++++++++ linux/drivers/media/dvb/siano/smsendian.h | 32 ++++++++++ 2 files changed, 132 insertions(+) create mode 100644 linux/drivers/media/dvb/siano/smsendian.c create mode 100644 linux/drivers/media/dvb/siano/smsendian.h (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/siano/smsendian.c b/linux/drivers/media/dvb/siano/smsendian.c new file mode 100644 index 000000000..d79aa0512 --- /dev/null +++ b/linux/drivers/media/dvb/siano/smsendian.c @@ -0,0 +1,100 @@ +/**************************************************************** + + Siano Mobile Silicon, Inc. + MDTV receiver kernel modules. + Copyright (C) 2006-2009, Uri Shkolnik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + + ****************************************************************/ + +#include + +#include "smsendian.h" +#include "smscoreapi.h" + +void smsendian_handle_tx_message(void *buffer) +{ +#ifdef __BIG_ENDIAN + struct SmsMsgData_ST *msg = (struct SmsMsgData_ST *)buffer; + int i; + int msgWords; + + switch (msg->xMsgHeader.msgType) { + case MSG_SMS_DATA_DOWNLOAD_REQ: + { + msg->msgData[0] = le32_to_cpu(msg->msgData[0]); + break; + } + + default: + msgWords = (msg->xMsgHeader.msgLength - + sizeof(struct SmsMsgHdr_ST))/4; + + for (i = 0; i < msgWords; i++) + msg->msgData[i] = le32_to_cpu(msg->msgData[i]); + + break; + } +#endif /* __BIG_ENDIAN */ +} + +void smsendian_handle_rx_message(void *buffer) +{ +#ifdef __BIG_ENDIAN + struct SmsMsgData_ST *msg = (struct SmsMsgData_ST *)buffer; + int i; + int msgWords; + + switch (msg->xMsgHeader.msgType) { + case MSG_SMS_GET_VERSION_EX_RES: + { + struct SmsVersionRes_ST *ver = + (struct SmsVersionRes_ST *) msg; + ver->ChipModel = le16_to_cpu(ver->ChipModel); + break; + } + + case MSG_SMS_DVBT_BDA_DATA: + case MSG_SMS_DAB_CHANNEL: + case MSG_SMS_DATA_MSG: + { + break; + } + + default: + { + msgWords = (msg->xMsgHeader.msgLength - + sizeof(struct SmsMsgHdr_ST))/4; + + for (i = 0; i < msgWords; i++) + msg->msgData[i] = le32_to_cpu(msg->msgData[i]); + + break; + } + } +#endif /* __BIG_ENDIAN */ +} + +void smsendian_handle_message_header(void *msg) +{ +#ifdef __BIG_ENDIAN + struct SmsMsgHdr_ST *phdr = (struct SmsMsgHdr_ST *)msg; + + phdr->msgType = le16_to_cpu(phdr->msgType); + phdr->msgLength = le16_to_cpu(phdr->msgLength); + phdr->msgFlags = le16_to_cpu(phdr->msgFlags); +#endif /* __BIG_ENDIAN */ +} + diff --git a/linux/drivers/media/dvb/siano/smsendian.h b/linux/drivers/media/dvb/siano/smsendian.h new file mode 100644 index 000000000..7fbedc6a6 --- /dev/null +++ b/linux/drivers/media/dvb/siano/smsendian.h @@ -0,0 +1,32 @@ +/**************************************************************** + +Siano Mobile Silicon, Inc. +MDTV receiver kernel modules. +Copyright (C) 2006-2009, Uri Shkolnik + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 of the License, or +(at your option) any later version. + + This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . + +****************************************************************/ + +#ifndef __SMS_ENDIAN_H__ +#define __SMS_ENDIAN_H__ + +#include + +void smsendian_handle_tx_message(void *buffer); +void smsendian_handle_rx_message(void *buffer); +void smsendian_handle_message_header(void *msg); + +#endif /* __SMS_ENDIAN_H__ */ + -- cgit v1.2.3 From b16003f763962973b1ec89b94f4f1f063b25e957 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 5 Apr 2009 10:25:06 +0000 Subject: Siano: unified the debug filter module parameter (dvb and core) From: Uri Shkolnik The sms_debug module parameter sets the debug filter for the smsmdtv module. It has been moved to the core component, and replace the smsdvb's. Priority: normal Signed-off-by: Uri Shkolnik Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/siano/smscoreapi.c | 4 ++-- linux/drivers/media/dvb/siano/smscoreapi.h | 3 ++- linux/drivers/media/dvb/siano/smsdvb.c | 3 --- 3 files changed, 4 insertions(+), 6 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/siano/smscoreapi.c b/linux/drivers/media/dvb/siano/smscoreapi.c index 9a9db2588..5cf5bb5d9 100644 --- a/linux/drivers/media/dvb/siano/smscoreapi.c +++ b/linux/drivers/media/dvb/siano/smscoreapi.c @@ -34,8 +34,8 @@ #include "smscoreapi.h" #include "sms-cards.h" -static int sms_dbg; -module_param_named(debug, sms_dbg, int, 0644); +int sms_debug; +module_param_named(debug, sms_debug, int, 0644); MODULE_PARM_DESC(debug, "set debug level (info=1, adv=2 (or-able))"); struct smscore_device_notifyee_t { diff --git a/linux/drivers/media/dvb/siano/smscoreapi.h b/linux/drivers/media/dvb/siano/smscoreapi.h index 83e0e55f7..875cbe6c7 100644 --- a/linux/drivers/media/dvb/siano/smscoreapi.h +++ b/linux/drivers/media/dvb/siano/smscoreapi.h @@ -658,6 +658,7 @@ int smscore_led_state(struct smscore_device_t *core, int led); /* ------------------------------------------------------------------------ */ +extern int sms_debug; #define DBG_INFO 1 #define DBG_ADV 2 @@ -666,7 +667,7 @@ int smscore_led_state(struct smscore_device_t *core, int led); printk(kern "%s: " fmt "\n", __func__, ##arg) #define dprintk(kern, lvl, fmt, arg...) do {\ - if (sms_dbg & lvl) \ + if (sms_debug & lvl) \ sms_printk(kern, fmt, ##arg); } while (0) #define sms_log(fmt, arg...) sms_printk(KERN_INFO, fmt, ##arg) diff --git a/linux/drivers/media/dvb/siano/smsdvb.c b/linux/drivers/media/dvb/siano/smsdvb.c index 035bd52c9..329cbce07 100644 --- a/linux/drivers/media/dvb/siano/smsdvb.c +++ b/linux/drivers/media/dvb/siano/smsdvb.c @@ -50,9 +50,6 @@ struct smsdvb_client_t { static struct list_head g_smsdvb_clients; static struct mutex g_smsdvb_clientslock; -static int sms_dbg; -module_param_named(debug, sms_dbg, int, 0644); -MODULE_PARM_DESC(debug, "set debug level (info=1, adv=2 (or-able))"); static int smsdvb_onresponse(void *context, struct smscore_buffer_t *cb) { -- cgit v1.2.3 From 5b5b3ec90de6979247cb25370a466355482e26d2 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 6 Apr 2009 02:14:43 +0000 Subject: au0828: fix Kconfig dependance From: Alexander Beregalov Fix this build error: ERROR: "videobuf_queue_vmalloc_init" [drivers/media/video/au0828/au0828.ko] undefined! ERROR: "videobuf_vmalloc_free" [drivers/media/video/au0828/au0828.ko] undefined! ERROR: "videobuf_to_vmalloc" [drivers/media/video/au0828/au0828.ko] undefined! Signed-off-by: Alexander Beregalov Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/au0828/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/au0828/Kconfig b/linux/drivers/media/video/au0828/Kconfig index 05cdf494d..0c3a5ba0e 100644 --- a/linux/drivers/media/video/au0828/Kconfig +++ b/linux/drivers/media/video/au0828/Kconfig @@ -4,6 +4,7 @@ config VIDEO_AU0828 depends on I2C && INPUT && DVB_CORE && USB && VIDEO_V4L2 select I2C_ALGOBIT select VIDEO_TVEEPROM + select VIDEOBUF_VMALLOC select DVB_AU8522 if !DVB_FE_CUSTOMISE select MEDIA_TUNER_XC5000 if !MEDIA_TUNER_CUSTOMISE select MEDIA_TUNER_MXL5007T if !MEDIA_TUNER_CUSTOMISE -- cgit v1.2.3 From 7b7dbf06c3c16bf46bd2954ad07325f6b43fb367 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Sun, 5 Apr 2009 23:51:38 -0500 Subject: pvrusb2: Select, track, and report IR scheme in use with the device From: Mike Isely This change defines all possible "IR schemes" related to the pvrusb2 driver, on a per-device basis. That information is then set according to the hardware in use. The idea here is to make possible a more intelligent future decision on which, if any, IR receiver driver might be loaded during initialization. Priority: normal Signed-off-by: Mike Isely --- .../drivers/media/video/pvrusb2/pvrusb2-devattr.c | 1 + .../drivers/media/video/pvrusb2/pvrusb2-devattr.h | 22 +++++++--------------- .../media/video/pvrusb2/pvrusb2-hdw-internal.h | 3 +++ linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c | 18 +++++++++++++++++- .../drivers/media/video/pvrusb2/pvrusb2-i2c-core.c | 12 ++++++++++-- 5 files changed, 38 insertions(+), 18 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-devattr.c b/linux/drivers/media/video/pvrusb2/pvrusb2-devattr.c index 129de13da..341af4355 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-devattr.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-devattr.c @@ -71,6 +71,7 @@ static const struct pvr2_device_desc pvr2_device_29xxx = { .flag_has_svideo = !0, .signal_routing_scheme = PVR2_ROUTING_SCHEME_HAUPPAUGE, .led_scheme = PVR2_LED_SCHEME_HAUPPAUGE, + .ir_scheme = PVR2_IR_SCHEME_29XXX, }; diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-devattr.h b/linux/drivers/media/video/pvrusb2/pvrusb2-devattr.h index 3e553389c..73e0e0ba0 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-devattr.h +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-devattr.h @@ -78,8 +78,10 @@ struct pvr2_string_table { #define PVR2_LED_SCHEME_HAUPPAUGE 1 #define PVR2_IR_SCHEME_NONE 0 -#define PVR2_IR_SCHEME_24XXX 1 -#define PVR2_IR_SCHEME_ZILOG 2 +#define PVR2_IR_SCHEME_24XXX 1 /* FX2-controlled IR */ +#define PVR2_IR_SCHEME_ZILOG 2 /* HVR-1950 style (must be taken out of reset) */ +#define PVR2_IR_SCHEME_24XXX_MCE 3 /* 24xxx MCE device */ +#define PVR2_IR_SCHEME_29XXX 4 /* Original 29xxx device */ /* This describes a particular hardware type (except for the USB device ID which must live in a separate structure due to environmental @@ -162,19 +164,9 @@ struct pvr2_device_desc { ensure that it is found. */ unsigned int flag_has_wm8775:1; - /* Indicate any specialized IR scheme that might need to be - supported by this driver. If not set, then it is assumed that - IR can work without help from the driver (which is frequently - the case). This is otherwise set to one of - PVR2_IR_SCHEME_xxxx. For "xxxx", the value "24XXX" indicates a - Hauppauge 24xxx class device which has an FPGA-hosted IR - receiver that can only be reached via FX2 command codes. In - that case the pvrusb2 driver will emulate the behavior of the - older 29xxx device's IR receiver (a "virtual" I2C chip) in terms - of those command codes. For the value "ZILOG", we're dealing - with an IR chip that must be taken out of reset via another FX2 - command code (which is the case for HVR-1950 devices). */ - unsigned int ir_scheme:2; + /* Indicate IR scheme of hardware. If not set, then it is assumed + that IR can work without any help from the driver. */ + unsigned int ir_scheme:3; /* These bits define which kinds of sources the device can handle. Note: Digital tuner presence is inferred by the diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h index 5d75eb521..5b152ff20 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h @@ -200,6 +200,9 @@ struct pvr2_hdw { int i2c_cx25840_hack_state; int i2c_linked; + /* IR related */ + unsigned int ir_scheme_active; /* IR scheme as seen from the outside */ + /* Frequency table */ unsigned int freqTable[FREQTABLE_SIZE]; unsigned int freqProgSlot; diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c index c0e1e2cc9..b07daea8c 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -143,6 +143,15 @@ static const unsigned char *module_i2c_addresses[] = { }; +static const char *ir_scheme_names[] = { + [PVR2_IR_SCHEME_NONE] = "none", + [PVR2_IR_SCHEME_29XXX] = "29xxx", + [PVR2_IR_SCHEME_24XXX] = "24xxx (29xxx emulation)", + [PVR2_IR_SCHEME_24XXX_MCE] = "24xxx (MCE device)", + [PVR2_IR_SCHEME_ZILOG] = "Zilog", +}; + + /* Define the list of additional controls we'll dynamically construct based on query of the cx2341x module. */ struct pvr2_mpeg_ids { @@ -2187,7 +2196,7 @@ static void pvr2_hdw_setup_low(struct pvr2_hdw *hdw) } /* Take the IR chip out of reset, if appropriate */ - if (hdw->hdw_desc->ir_scheme == PVR2_IR_SCHEME_ZILOG) { + if (hdw->ir_scheme_active == PVR2_IR_SCHEME_ZILOG) { pvr2_issue_simple_cmd(hdw, FX2CMD_HCW_ZILOG_RESET | (1 << 8) | @@ -2468,6 +2477,7 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf, GFP_KERNEL); if (!hdw->controls) goto fail; hdw->hdw_desc = hdw_desc; + hdw->ir_scheme_active = hdw->hdw_desc->ir_scheme; for (idx = 0; idx < hdw->control_cnt; idx++) { cptr = hdw->controls + idx; cptr->hdw = hdw; @@ -4903,6 +4913,12 @@ static unsigned int pvr2_hdw_report_unlocked(struct pvr2_hdw *hdw,int which, stats.buffers_processed, stats.buffers_failed); } + case 6: { + unsigned int id = hdw->ir_scheme_active; + return scnprintf(buf, acnt, "ir scheme: id=%d %s", id, + (id >= ARRAY_SIZE(ir_scheme_names) ? + "?" : ir_scheme_names[id])); + } default: break; } return 0; diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c b/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c index 919a4f4e1..4c761161f 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c @@ -652,7 +652,9 @@ void pvr2_i2c_core_init(struct pvr2_hdw *hdw) printk(KERN_INFO "%s: IR disabled\n",hdw->name); hdw->i2c_func[0x18] = i2c_black_hole; } else if (ir_mode[hdw->unit_number] == 1) { - if (hdw->hdw_desc->ir_scheme == PVR2_IR_SCHEME_24XXX) { + if (hdw->ir_scheme_active == PVR2_IR_SCHEME_24XXX) { + /* Set up translation so that our IR looks like a + 29xxx device */ hdw->i2c_func[0x18] = i2c_24xxx_ir; } } @@ -675,12 +677,18 @@ void pvr2_i2c_core_init(struct pvr2_hdw *hdw) i2c_add_adapter(&hdw->i2c_adap); if (hdw->i2c_func[0x18] == i2c_24xxx_ir) { /* Probe for a different type of IR receiver on this - device. If present, disable the emulated IR receiver. */ + device. This is really the only way to differentiate + older 24xxx devices from 24xxx variants that include an + IR blaster. If the IR blaster is present, the IR + receiver is part of that chip and thus we must disable + the emulated IR receiver. */ if (do_i2c_probe(hdw, 0x71)) { pvr2_trace(PVR2_TRACE_INFO, "Device has newer IR hardware;" " disabling unneeded virtual IR device"); hdw->i2c_func[0x18] = NULL; + /* Remember that this is a different device... */ + hdw->ir_scheme_active = PVR2_IR_SCHEME_24XXX_MCE; } } if (i2c_scan) do_i2c_scan(hdw); -- cgit v1.2.3 From 045548622863911d1e32b2264efbf076d970ece4 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Mon, 6 Apr 2009 22:45:20 +0400 Subject: Initial go at TT S2-1600 From: Manu Abraham Signed-off-by: Manu Abraham --- linux/drivers/media/dvb/frontends/Kconfig | 22 + linux/drivers/media/dvb/frontends/Makefile | 4 +- linux/drivers/media/dvb/frontends/isl6423.c | 293 ++ linux/drivers/media/dvb/frontends/isl6423.h | 63 + linux/drivers/media/dvb/frontends/stv090x.c | 4797 +++++++++++++++++++++ linux/drivers/media/dvb/frontends/stv090x.h | 109 + linux/drivers/media/dvb/frontends/stv090x_priv.h | 274 ++ linux/drivers/media/dvb/frontends/stv090x_reg.h | 2300 ++++++++++ linux/drivers/media/dvb/frontends/stv6110x.c | 442 ++ linux/drivers/media/dvb/frontends/stv6110x.h | 71 + linux/drivers/media/dvb/frontends/stv6110x_priv.h | 77 + linux/drivers/media/dvb/frontends/stv6110x_reg.h | 82 + linux/drivers/media/dvb/ttpci/budget-ci.c | 83 + 13 files changed, 8616 insertions(+), 1 deletion(-) create mode 100644 linux/drivers/media/dvb/frontends/isl6423.c create mode 100644 linux/drivers/media/dvb/frontends/isl6423.h create mode 100644 linux/drivers/media/dvb/frontends/stv090x.c create mode 100644 linux/drivers/media/dvb/frontends/stv090x.h create mode 100644 linux/drivers/media/dvb/frontends/stv090x_priv.h create mode 100644 linux/drivers/media/dvb/frontends/stv090x_reg.h create mode 100644 linux/drivers/media/dvb/frontends/stv6110x.c create mode 100644 linux/drivers/media/dvb/frontends/stv6110x.h create mode 100644 linux/drivers/media/dvb/frontends/stv6110x_priv.h create mode 100644 linux/drivers/media/dvb/frontends/stv6110x_reg.h (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/frontends/Kconfig b/linux/drivers/media/dvb/frontends/Kconfig index a206cee23..29276960d 100644 --- a/linux/drivers/media/dvb/frontends/Kconfig +++ b/linux/drivers/media/dvb/frontends/Kconfig @@ -35,6 +35,21 @@ config DVB_STB6100 A Silicon tuner from ST used in conjunction with the STB0899 demodulator. Say Y when you want to support this tuner. +config DVB_STV090x + tristate "STV0900/STV0903(A/B) based" + depends on DVB_CORE && I2C + default m if DVB_FE_CUSTOMISE + help + DVB-S/S2/DSS Multistandard Professional/Broadcast demodulators. + Say Y when you want to support these frontends. + +config DVB_STV6110x + tristate "STV6110/(A) based tuners" + depends on DVB_CORE && I2C + default m if DVB_FE_CUSTOMISE + help + A Silicon tuner that supports DVB-S and DVB-S2 modes + comment "DVB-S (satellite) frontends" depends on DVB_CORE @@ -506,6 +521,13 @@ config DVB_ISL6421 help An SEC control chip. +config DVB_ISL6423 + tristate "ISL6423 SEC controller" + depends on DVB_CORE && I2C + default m if DVB_FE_CUSTOMISE + help + A SEC controller chip from Intersil + config DVB_LGS8GL5 tristate "Silicon Legend LGS-8GL5 demodulator (OFDM)" depends on DVB_CORE && I2C diff --git a/linux/drivers/media/dvb/frontends/Makefile b/linux/drivers/media/dvb/frontends/Makefile index 65a336aa1..83f7c7e7e 100644 --- a/linux/drivers/media/dvb/frontends/Makefile +++ b/linux/drivers/media/dvb/frontends/Makefile @@ -70,4 +70,6 @@ obj-$(CONFIG_DVB_STB6000) += stb6000.o obj-$(CONFIG_DVB_S921) += s921.o obj-$(CONFIG_DVB_STV6110) += stv6110.o obj-$(CONFIG_DVB_STV0900) += stv0900.o - +obj-$(CONFIG_DVB_STV090x) += stv090x.o +obj-$(CONFIG_DVB_STV6110x) += stv6110x.o +obj-$(CONFIG_DVB_ISL6423) += isl6423.o diff --git a/linux/drivers/media/dvb/frontends/isl6423.c b/linux/drivers/media/dvb/frontends/isl6423.c new file mode 100644 index 000000000..c1943dcb8 --- /dev/null +++ b/linux/drivers/media/dvb/frontends/isl6423.c @@ -0,0 +1,293 @@ +/* + Intersil ISL6423 SEC and LNB Power supply controller + + Copyright (C) Manu Abraham + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include +#include +#include +#include +#include +#include +#include + +#include "dvb_frontend.h" +#include "isl6423.h" + +static unsigned int verbose; +module_param(verbose, int, 0644); +MODULE_PARM_DESC(verbose, "Set Verbosity level"); + +#define FE_ERROR 0 +#define FE_NOTICE 1 +#define FE_INFO 2 +#define FE_DEBUG 3 +#define FE_DEBUGREG 4 + +#define dprintk(__y, __z, format, arg...) do { \ + if (__z) { \ + if ((verbose > FE_ERROR) && (verbose > __y)) \ + printk(KERN_ERR "%s: " format "\n", __func__ , ##arg); \ + else if ((verbose > FE_NOTICE) && (verbose > __y)) \ + printk(KERN_NOTICE "%s: " format "\n", __func__ , ##arg); \ + else if ((verbose > FE_INFO) && (verbose > __y)) \ + printk(KERN_INFO "%s: " format "\n", __func__ , ##arg); \ + else if ((verbose > FE_DEBUG) && (verbose > __y)) \ + printk(KERN_DEBUG "%s: " format "\n", __func__ , ##arg); \ + } else { \ + if (verbose > __y) \ + printk(format, ##arg); \ + } \ +} while (0) + +struct isl6423_dev { + const struct isl6423_config *config; + struct i2c_adapter *i2c; + + u8 reg_3; + u8 reg_4; + + unsigned int verbose; +}; + +static int isl6423_write(struct isl6423_dev *isl6423, u8 reg) +{ + struct i2c_adapter *i2c = isl6423->i2c; + u8 addr = isl6423->config->addr; + int err = 0; + + struct i2c_msg msg = { .addr = addr, .flags = 0, .buf = ®, .len = 1 }; + + err = i2c_transfer(i2c, &msg, 1); + if (err < 0) + goto exit; + return 0; + +exit: + dprintk(FE_ERROR, 1, "I/O error <%d>", err); + return err; +} + +static int isl6423_set_modulation(struct dvb_frontend *fe) +{ + struct isl6423_dev *isl6423 = (struct isl6423_dev *) fe->sec_priv; + const struct isl6423_config *config = isl6423->config; + int err = 0; + u8 reg_2 = 0; + + reg_2 = 0x01 << 5; + + if (config->mod_extern) + reg_2 |= (1 << 3); + else + reg_2 |= (1 << 4); + + err = isl6423_write(isl6423, reg_2); + if (err < 0) + goto exit; + return 0; + +exit: + dprintk(FE_ERROR, 1, "I/O error <%d>", err); + return err; +} + +static int isl6423_voltage_boost(struct dvb_frontend *fe, long arg) +{ + struct isl6423_dev *isl6423 = (struct isl6423_dev *) fe->sec_priv; + u8 reg_3 = isl6423->reg_3; + u8 reg_4 = isl6423->reg_4; + int err = 0; + + if (arg) { + /* EN = 1, VSPEN = 1, VBOT = 1 */ + reg_4 |= (1 << 4); + reg_4 |= 0x1; + reg_3 |= (1 << 3); + } else { + /* EN = 1, VSPEN = 1, VBOT = 0 */ + reg_4 |= (1 << 4); + reg_4 &= ~0x1; + reg_3 |= (1 << 3); + } + err = isl6423_write(isl6423, reg_3); + if (err < 0) + goto exit; + + err = isl6423_write(isl6423, reg_4); + if (err < 0) + goto exit; + + return 0; +exit: + dprintk(FE_ERROR, 1, "I/O error <%d>", err); + return err; +} + + +static int isl6423_set_voltage(struct dvb_frontend *fe, + enum fe_sec_voltage voltage) +{ + struct isl6423_dev *isl6423 = (struct isl6423_dev *) fe->sec_priv; + u8 reg_4 = isl6423->reg_4; + int err = 0; + + /* SR4H = 0, SR4M = 1, SR4L = 1 */ + reg_4 = 0x03 << 5; + + switch (voltage) { + case SEC_VOLTAGE_OFF: + /* EN = 0 */ + reg_4 &= ~(1 << 4); + break; + + case SEC_VOLTAGE_13: + /* EN = 1, VSPEN = 1, VTOP = 0, VBOT = 0 */ + reg_4 |= (1 << 4); + reg_4 &= ~0x3; + break; + + case SEC_VOLTAGE_18: + /* EN = 1, VSPEN = 1, VTOP = 1, VBOT = 0 */ + reg_4 |= (1 << 4); + reg_4 |= 0x2; + reg_4 &= ~0x1; + break; + + default: + break; + } + err = isl6423_write(isl6423, reg_4); + if (err < 0) + goto exit; + + return 0; +exit: + dprintk(FE_ERROR, 1, "I/O error <%d>", err); + return err; +} + +static int isl6423_set_current(struct dvb_frontend *fe) +{ + struct isl6423_dev *isl6423 = (struct isl6423_dev *) fe->sec_priv; + u8 reg_3 = isl6423->reg_3; + const struct isl6423_config *config = isl6423->config; + int err = 0; + + /* SR3H = 0, SR3M = 1, SR3L = 0 */ + reg_3 = 0x02 << 5; + + switch (config->current_max) { + case SEC_CURRENT_275m: + /* 275mA */ + /* ISELH = 0, ISELL = 0 */ + reg_3 &= ~0x3; + break; + + case SEC_CURRENT_515m: + /* 515mA */ + /* ISELH = 0, ISELL = 1 */ + reg_3 &= ~0x2; + reg_3 |= 0x1; + break; + + case SEC_CURRENT_635m: + /* 635mA */ + /* ISELH = 1, ISELL = 0 */ + reg_3 &= ~0x1; + reg_3 |= 0x2; + break; + + case SEC_CURRENT_800m: + /* 800mA */ + /* ISELH = 1, ISELL = 1 */ + reg_3 |= 0x3; + break; + } + + err = isl6423_write(isl6423, reg_3); + if (err < 0) + goto exit; + + switch (config->curlim) { + case SEC_CURRENT_LIM_ON: + /* DCL = 1 */ + reg_3 |= 0x10; + break; + + case SEC_CURRENT_LIM_OFF: + /* DCL = 0 */ + reg_3 &= ~0x10; + break; + } + + err = isl6423_write(isl6423, reg_3); + if (err < 0) + goto exit; + + return 0; +exit: + dprintk(FE_ERROR, 1, "I/O error <%d>", err); + return err; +} + +static void isl6423_release(struct dvb_frontend *fe) +{ + isl6423_set_voltage(fe, SEC_VOLTAGE_OFF); + + kfree(fe->sec_priv); + fe->sec_priv = NULL; +} + +struct dvb_frontend *isl6423_attach(struct dvb_frontend *fe, + struct i2c_adapter *i2c, + const struct isl6423_config *config) +{ + struct isl6423_dev *isl6423; + + isl6423 = kzalloc(sizeof(struct isl6423_dev), GFP_KERNEL); + if (!isl6423) + return NULL; + + isl6423->config = config; + isl6423->i2c = i2c; + fe->sec_priv = isl6423; + + if (isl6423_set_current(fe)) + goto exit; + + if (isl6423_set_modulation(fe)) + goto exit; + + fe->ops.release_sec = isl6423_release; + fe->ops.set_voltage = isl6423_set_voltage; + fe->ops.enable_high_lnb_voltage = isl6423_voltage_boost; + isl6423->verbose = verbose; + + return fe; + +exit: + kfree(isl6423); + fe->sec_priv = NULL; + return NULL; +} +EXPORT_SYMBOL(isl6423_attach); + +MODULE_DESCRIPTION("ISL6423 SEC"); +MODULE_AUTHOR("Manu Abraham"); +MODULE_LICENSE("GPL"); diff --git a/linux/drivers/media/dvb/frontends/isl6423.h b/linux/drivers/media/dvb/frontends/isl6423.h new file mode 100644 index 000000000..e1a37fba0 --- /dev/null +++ b/linux/drivers/media/dvb/frontends/isl6423.h @@ -0,0 +1,63 @@ +/* + Intersil ISL6423 SEC and LNB Power supply controller + + Copyright (C) Manu Abraham + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __ISL_6423_H +#define __ISL_6423_H + +#include + +enum isl6423_current { + SEC_CURRENT_275m = 0, + SEC_CURRENT_515m, + SEC_CURRENT_635m, + SEC_CURRENT_800m, +}; + +enum isl6423_curlim { + SEC_CURRENT_LIM_ON = 1, + SEC_CURRENT_LIM_OFF +}; + +struct isl6423_config { + enum isl6423_current current_max; + enum isl6423_curlim curlim; + u8 addr; + u8 mod_extern; +}; + +#if defined(CONFIG_DVB_ISL6423) || (defined(CONFIG_DVB_ISL6423_MODULE) && defined(MODULE)) + + +extern struct dvb_frontend *isl6423_attach(struct dvb_frontend *fe, + struct i2c_adapter *i2c, + const struct isl6423_config *config); + +#else +static inline struct dvb_frontend *isl6423_attach(struct dvb_frontend *fe, + struct i2c_adapter *i2c, + const struct isl6423_config *config) +{ + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); + return NULL; +} + +#endif /* CONFIG_DVB_ISL6423 */ + +#endif /* __ISL_6423_H */ diff --git a/linux/drivers/media/dvb/frontends/stv090x.c b/linux/drivers/media/dvb/frontends/stv090x.c new file mode 100644 index 000000000..fc0781961 --- /dev/null +++ b/linux/drivers/media/dvb/frontends/stv090x.c @@ -0,0 +1,4797 @@ +/* + STV0900/0903 Multistandard Broadcast Frontend driver + Copyright (C) Manu Abraham + + Copyright (C) ST Microelectronics + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include +#include +#include +#include +#include + +#include +#include "dvb_frontend.h" + +#include "stv6110x.h" /* for demodulator internal modes */ + +#include "stv090x_reg.h" +#include "stv090x.h" +#include "stv090x_priv.h" + +static unsigned int verbose; +module_param(verbose, int, 0644); + +struct mutex demod_lock; + +/* DVBS1 and DSS C/N Lookup table */ +static const struct stv090x_tab stv090x_s1cn_tab[] = { + { 0, 8917 }, /* 0.0dB */ + { 5, 8801 }, /* 0.5dB */ + { 10, 8667 }, /* 1.0dB */ + { 15, 8522 }, /* 1.5dB */ + { 20, 8355 }, /* 2.0dB */ + { 25, 8175 }, /* 2.5dB */ + { 30, 7979 }, /* 3.0dB */ + { 35, 7763 }, /* 3.5dB */ + { 40, 7530 }, /* 4.0dB */ + { 45, 7282 }, /* 4.5dB */ + { 50, 7026 }, /* 5.0dB */ + { 55, 6781 }, /* 5.5dB */ + { 60, 6514 }, /* 6.0dB */ + { 65, 6241 }, /* 6.5dB */ + { 70, 5965 }, /* 7.0dB */ + { 75, 5690 }, /* 7.5dB */ + { 80, 5424 }, /* 8.0dB */ + { 85, 5161 }, /* 8.5dB */ + { 90, 4902 }, /* 9.0dB */ + { 95, 4654 }, /* 9.5dB */ + { 100, 4417 }, /* 10.0dB */ + { 105, 4186 }, /* 10.5dB */ + { 110, 3968 }, /* 11.0dB */ + { 115, 3757 }, /* 11.5dB */ + { 120, 3558 }, /* 12.0dB */ + { 125, 3366 }, /* 12.5dB */ + { 130, 3185 }, /* 13.0dB */ + { 135, 3012 }, /* 13.5dB */ + { 140, 2850 }, /* 14.0dB */ + { 145, 2698 }, /* 14.5dB */ + { 150, 2550 }, /* 15.0dB */ + { 160, 2283 }, /* 16.0dB */ + { 170, 2042 }, /* 17.0dB */ + { 180, 1827 }, /* 18.0dB */ + { 190, 1636 }, /* 19.0dB */ + { 200, 1466 }, /* 20.0dB */ + { 210, 1315 }, /* 21.0dB */ + { 220, 1181 }, /* 22.0dB */ + { 230, 1064 }, /* 23.0dB */ + { 240, 960 }, /* 24.0dB */ + { 250, 869 }, /* 25.0dB */ + { 260, 792 }, /* 26.0dB */ + { 270, 724 }, /* 27.0dB */ + { 280, 665 }, /* 28.0dB */ + { 290, 616 }, /* 29.0dB */ + { 300, 573 }, /* 30.0dB */ + { 310, 537 }, /* 31.0dB */ + { 320, 507 }, /* 32.0dB */ + { 330, 483 }, /* 33.0dB */ + { 400, 398 }, /* 40.0dB */ + { 450, 381 }, /* 45.0dB */ + { 500, 377 } /* 50.0dB */ +}; + +/* DVBS2 C/N Lookup table */ +static const struct stv090x_tab stv090x_s2cn_tab[] = { + { -30, 13348 }, /* -3.0dB */ + { -20, 12640 }, /* -2d.0B */ + { -10, 11883 }, /* -1.0dB */ + { 0, 11101 }, /* -0.0dB */ + { 5, 10718 }, /* 0.5dB */ + { 10, 10339 }, /* 1.0dB */ + { 15, 9947 }, /* 1.5dB */ + { 20, 9552 }, /* 2.0dB */ + { 25, 9183 }, /* 2.5dB */ + { 30, 8799 }, /* 3.0dB */ + { 35, 8422 }, /* 3.5dB */ + { 40, 8062 }, /* 4.0dB */ + { 45, 7707 }, /* 4.5dB */ + { 50, 7353 }, /* 5.0dB */ + { 55, 7025 }, /* 5.5dB */ + { 60, 6684 }, /* 6.0dB */ + { 65, 6331 }, /* 6.5dB */ + { 70, 6036 }, /* 7.0dB */ + { 75, 5727 }, /* 7.5dB */ + { 80, 5437 }, /* 8.0dB */ + { 85, 5164 }, /* 8.5dB */ + { 90, 4902 }, /* 9.0dB */ + { 95, 4653 }, /* 9.5dB */ + { 100, 4408 }, /* 10.0dB */ + { 105, 4187 }, /* 10.5dB */ + { 110, 3961 }, /* 11.0dB */ + { 115, 3751 }, /* 11.5dB */ + { 120, 3558 }, /* 12.0dB */ + { 125, 3368 }, /* 12.5dB */ + { 130, 3191 }, /* 13.0dB */ + { 135, 3017 }, /* 13.5dB */ + { 140, 2862 }, /* 14.0dB */ + { 145, 2710 }, /* 14.5dB */ + { 150, 2565 }, /* 15.0dB */ + { 160, 2300 }, /* 16.0dB */ + { 170, 2058 }, /* 17.0dB */ + { 180, 1849 }, /* 18.0dB */ + { 190, 1663 }, /* 19.0dB */ + { 200, 1495 }, /* 20.0dB */ + { 210, 1349 }, /* 21.0dB */ + { 220, 1222 }, /* 22.0dB */ + { 230, 1110 }, /* 23.0dB */ + { 240, 1011 }, /* 24.0dB */ + { 250, 925 }, /* 25.0dB */ + { 260, 853 }, /* 26.0dB */ + { 270, 789 }, /* 27.0dB */ + { 280, 734 }, /* 28.0dB */ + { 290, 690 }, /* 29.0dB */ + { 300, 650 }, /* 30.0dB */ + { 310, 619 }, /* 31.0dB */ + { 320, 593 }, /* 32.0dB */ + { 330, 571 }, /* 33.0dB */ + { 400, 498 }, /* 40.0dB */ + { 450, 484 }, /* 45.0dB */ + { 500, 481 } /* 50.0dB */ +}; + +/* RF level C/N lookup table */ +static const struct stv090x_tab stv090x_rf_tab[] = { + { -5, 0xcaa1 }, /* -5dBm */ + { -10, 0xc229 }, /* -10dBm */ + { -15, 0xbb08 }, /* -15dBm */ + { -20, 0xb4bc }, /* -20dBm */ + { -25, 0xad5a }, /* -25dBm */ + { -30, 0xa298 }, /* -30dBm */ + { -35, 0x98a8 }, /* -35dBm */ + { -40, 0x8389 }, /* -40dBm */ + { -45, 0x59be }, /* -45dBm */ + { -50, 0x3a14 }, /* -50dBm */ + { -55, 0x2d11 }, /* -55dBm */ + { -60, 0x210d }, /* -60dBm */ + { -65, 0xa14f }, /* -65dBm */ + { -70, 0x07aa } /* -70dBm */ +}; + +#if 0 +static struct stv090x_reg stv090x_defval[] = { + + { STV090x_MID, 0x20 }, /* MID */ + { STV090x_DACR1, 0x00 }, /* DACR1 */ + { STV090x_DACR2, 0x00 }, /* DACR2 */ + { STV090x_OUTCFG, 0x00 }, /* OUTCFG */ +#if 0 + { STV090x_MODECFG, 0xff }, /* MODECFG */ +#endif + { STV090x_IRQSTATUS3, 0x00 }, /* IRQSTATUS3 */ + { STV090x_IRQSTATUS2, 0x00 }, /* IRQSTATUS2 */ + { STV090x_IRQSTATUS1, 0x00 }, /* IRQSTATUS1 */ + { STV090x_IRQSTATUS0, 0x00 }, /* IRQSTATUS0 */ + { STV090x_IRQMASK3, 0x3f }, /* IRQMASK3 */ + { STV090x_IRQMASK2, 0xff }, /* IRQMASK2 */ + { STV090x_IRQMASK1, 0xff }, /* IRQMASK1 */ + { STV090x_IRQMASK0, 0xff }, /* IRQMASK0 */ + { STV090x_I2CCFG, 0x08 }, /* I2CCFG */ + { STV090x_P1_I2CRPT, 0x44 }, /* P1_I2CRPT */ + { STV090x_P2_I2CRPT, 0x44 }, /* P2_I2CRPT */ + { STV090x_CLKI2CFG, 0x82 }, /* CLKI2CFG */ + { STV090x_GPIO1CFG, 0x82 }, /* GPIO1CFG */ + { STV090x_GPIO2CFG, 0x82 }, /* GPIO2CFG */ + { STV090x_GPIO3CFG, 0x82 }, /* GPIO3CFG */ + { STV090x_GPIO4CFG, 0x82 }, /* GPIO4CFG */ + { STV090x_GPIO5CFG, 0x82 }, /* GPIO5CFG */ + { STV090x_GPIO6CFG, 0x82 }, /* GPIO6CFG */ + { STV090x_GPIO7CFG, 0x82 }, /* GPIO7CFG */ + { STV090x_GPIO8CFG, 0x82 }, /* GPIO8CFG */ + { STV090x_GPIO9CFG, 0x82 }, /* GPIO9CFG */ + { STV090x_GPIO10CFG, 0x82 }, /* GPIO10CFG */ + { STV090x_GPIO11CFG, 0x82 }, /* GPIO11CFG */ + { STV090x_GPIO12CFG, 0x82 }, /* GPIO12CFG */ + { STV090x_GPIO13CFG, 0x82 }, /* GPIO13CFG */ + { STV090x_CS0CFG, 0x82 }, /* CS0CFG */ + { STV090x_CS1CFG, 0x82 }, /* CS1CFG */ + { STV090x_STDBYCFG, 0x82 }, /* STDBYCFG */ + { STV090x_DIRCLKCFG, 0x82 }, /* DIRCLKCFG */ + { STV090x_AGCRF1CFG, 0x11 }, /* AGCRF1CFG */ + { STV090x_SDAT1CFG, 0xb0 }, /* SDAT1CFG */ + { STV090x_SCLT1CFG, 0xb2 }, /* SCLT1CFG */ + { STV090x_DISEQCO1CFG, 0x14 }, /* DISEQCO1CFG */ + { STV090x_AGCRF2CFG, 0x13 }, /* AGCRF2CFG */ + { STV090x_SDAT2CFG, 0xb4 }, /* SDAT2CFG */ + { STV090x_SCLT2CFG, 0xb6 }, /* SCLT2CFG */ + { STV090x_DISEQCO2CFG, 0x16 }, /* DISEQCO2CFG */ + { STV090x_CLKOUT27CFG, 0x7e }, /* ERROR1CFG */ + { STV090x_DPN1CFG, 0xc0 }, /* DPN1CFG */ + { STV090x_STROUT1CFG, 0xc2 }, /* STROUT1CFG */ + { STV090x_CLKOUT1CFG, 0xc6 }, /* CLKOUT1CFG */ + { STV090x_DATA71CFG, 0xc8 }, /* DATA71CFG */ + { STV090x_ERROR2CFG, 0xce }, /* ERROR2CFG */ + { STV090x_DPN2CFG, 0xca }, /* DPN2CFG */ + { STV090x_STROUT2CFG, 0xcc }, /* STROUT2CFG */ + { STV090x_CLKOUT2CFG, 0xd0 }, /* CLKOUT2CFG */ + { STV090x_DATA72CFG, 0xd2 }, /* DATA72CFG */ + { STV090x_ERROR3CFG, 0xd8 }, /* ERROR3CFG */ + { STV090x_DPN3CFG, 0xd4 }, /* DPN3CFG */ + { STV090x_STROUT3CFG, 0xd6 }, /* STROUT3CFG */ + { STV090x_CLKOUT3CFG, 0xda }, /* CLKOUT3CFG */ + { STV090x_DATA73CFG, 0xdc }, /* DATA73CFG */ + { STV090x_FSKTFC2, 0x8c }, /* FSKTFC2 */ + { STV090x_FSKTFC1, 0x75 }, /* FSKTFC1 */ + { STV090x_FSKTFC0, 0xc2 }, /* FSKTFC0 */ + { STV090x_FSKTDELTAF1, 0x02 }, /* FSKTDELTAF1 */ + { STV090x_FSKTDELTAF0, 0x0c }, /* FSKTDELTAF0 */ + { STV090x_FSKTCTRL, 0x04 }, /* FSKTCTRL */ + { STV090x_FSKRFC2, 0x10 }, /* FSKRFC2 */ + { STV090x_FSKRFC1, 0x75 }, /* FSKRFC1 */ + { STV090x_FSKRFC0, 0xc2 }, /* FSKRFC0 */ + { STV090x_FSKRK1, 0x3a }, /* FSKRK1 */ + { STV090x_FSKRK2, 0x74 }, /* FSKRK2 */ + { STV090x_FSKRAGCR, 0x28 }, /* FSKRAGCR */ + { STV090x_FSKRAGC, 0xff }, /* FSKRAGC */ + { STV090x_FSKRALPHA, 0x17 }, /* FSKRALPHA */ + { STV090x_FSKRPLTH1, 0x80 }, /* FSKRPLTH1 */ + { STV090x_FSKRPLTH0, 0x00 }, /* FSKRPLTH0 */ + { STV090x_FSKRDF1, 0x80 }, /* FSKRDF1 */ + { STV090x_FSKRDF0, 0x00 }, /* FSKRDF0 */ + { STV090x_FSKRSTEPP, 0x30 }, /* FSKRSTEPP */ + { STV090x_FSKRSTEPM, 0x70 }, /* FSKRSTEPM */ + { STV090x_FSKRDET1, 0x00 }, /* FSKRDET1 */ + { STV090x_FSKRDET0, 0x00 }, /* FSKRDET0 */ + { STV090x_FSKRDTH1, 0x11 }, /* FSKRDTH1 */ + { STV090x_FSKRDTH0, 0x89 }, /* FSKRDTH0 */ + { STV090x_FSKRLOSS, 0x06 }, /* FSKRLOSS */ + { STV090x_P2_DISTXCTL, 0x22 }, /* P2_DISTXCTL */ + { STV090x_P2_DISRXCTL, 0x80 }, /* P2_DISRXCTL */ + { STV090x_P2_DISRX_ST0, 0x04 }, /* P2_DISRX_ST0 */ + { STV090x_P2_DISRX_ST1, 0x00 }, /* P2_DISRX_ST1 */ + { STV090x_P2_DISRXDATA, 0x00 }, /* P2_DISRXDATA */ + { STV090x_P2_DISTXDATA, 0x00 }, /* P2_DISTXDATA */ + { STV090x_P2_DISTXSTATUS, 0x20 }, /* P2_DISTXSTATUS */ + { STV090x_P2_F22TX, 0xc0 }, /* P2_F22TX */ + { STV090x_P2_F22RX, 0xc0 }, /* P2_F22RX */ + { STV090x_P2_ACRPRESC, 0x01 }, /* P2_ACRPRESC */ + { STV090x_P2_ACRDIV, 0x14 }, /* P2_ACRDIV */ + { STV090x_P1_DISTXCTL, 0x22 }, /* P1_DISTXCTL */ + { STV090x_P1_DISRXCTL, 0x80 }, /* P1_DISRXCTL */ + { STV090x_P1_DISRX_ST0, 0x14 }, /* P1_DISRX_ST0 */ + { STV090x_P1_DISRX_ST1, 0x80 }, /* P1_DISRX_ST1 */ + { STV090x_P1_DISRXDATA, 0x00 }, /* P1_DISRXDATA */ + { STV090x_P1_DISTXDATA, 0x00 }, /* P1_DISTXDATA */ + { STV090x_P1_DISTXSTATUS, 0x20 }, /* P1_DISTXSTATUS */ + { STV090x_P1_F22TX, 0xc0 }, /* P1_F22TX */ + { STV090x_P1_F22RX, 0xc0 }, /* P1_F22RX */ + { STV090x_P1_ACRPRESC, 0x01 }, /* P1_ACRPRESC */ + { STV090x_P1_ACRDIV, 0x14 }, /* P1_ACRDIV */ + { STV090x_NCOARSE, 0x13 }, /* NCOARSE */ + { STV090x_SYNTCTRL, 0x22 }, /* SYNTCTRL (default CLKI) */ + { STV090x_FILTCTRL, 0x01 }, /* FILTCTRL */ + { STV090x_PLLSTAT, 0xc0 }, /* PLLSTAT */ + { STV090x_STOPCLK1, 0x00 }, /* STOPCLK1 */ + { STV090x_STOPCLK2, 0x00 }, /* STOPCLK2 */ + { STV090x_TSTTNR0, 0x04 }, /* TSTTNR0 */ + { STV090x_TSTTNR1, 0x27 }, /* TSTTNR1 */ + { STV090x_TSTTNR2, 0x21 }, /* TSTTNR2 */ + { STV090x_TSTTNR3, 0x27 }, /* TSTTNR3 */ + { STV090x_TSTTNR4, 0x21 }, /* TSTTNR4 */ + { STV090x_P2_IQCONST, 0x00 }, /* P2_IQCONST */ + { STV090x_P2_NOSCFG, 0x1c }, /* P2_NOSCFG */ + { STV090x_P2_ISYMB, 0x27 }, /* P2_ISYMB */ + { STV090x_P2_QSYMB, 0x2a }, /* P2_QSYMB */ + { STV090x_P2_AGC1CFG, 0x54 }, /* P2_AGC1CFG */ + { STV090x_P2_AGC1CN, 0xd9 }, /* P2_AGC1CN */ + { STV090x_P2_AGC1REF, 0x58 }, /* P2_AGC1REF */ + { STV090x_P2_IDCCOMP, 0x00 }, /* P2_IDCCOMP */ + { STV090x_P2_QDCCOMP, 0xfd }, /* P2_QDCCOMP */ + { STV090x_P2_POWERI, 0x0e }, /* P2_POWERI */ + { STV090x_P2_POWERQ, 0x0c }, /* P2_POWERQ */ + { STV090x_P2_AGC1AMM, 0x19 }, /* P2_AGC1AMM */ + { STV090x_P2_AGC1QUAD, 0xf9 }, /* P2_AGC1QUAD */ + { STV090x_P2_AGCIQIN1, 0x00 }, /* P2_AGCIQIN1 */ + { STV090x_P2_AGCIQIN0, 0x00 }, /* P2_AGCIQIN0 */ + { STV090x_P2_DEMOD, 0x08 }, /* P2_DEMOD */ + { STV090x_P2_DMDMODCOD, 0x10 }, /* P2_DMDMODCOD */ + { STV090x_P2_DSTATUS, 0x10 }, /* P2_DSTATUS */ + { STV090x_P2_DSTATUS2, 0x88 }, /* P2_DSTATUS2 */ + { STV090x_P2_DMDCFGMD, 0xf9 }, /* P2_DMDCFGMD */ + { STV090x_P2_DMDCFG2, 0x3b }, /* P2_DMDCFG2 */ + { STV090x_P2_DMDISTATE, 0x5c }, /* P2_DMDISTATE */ +#if 0 + { STV090x_P2_DMDT0M, 0x20 }, /* P2_DMDT0M */ +#endif + { STV090x_P2_DMDSTATE, 0x1c }, /* P2_DMDSTATE */ + { STV090x_P2_DMDFLYW, 0x00 }, /* P2_DMDFLYW */ + { STV090x_P2_DSTATUS3, 0x00 }, /* P2_DSTATUS3 */ + { STV090x_P2_DMDCFG3, 0x68 }, /* P2_DMDCFG3 */ +#if 0 + { STV090x_P2_DMDCFG4, 0x10 }, /* P2_DMDCFG4 */ +#endif + { STV090x_P2_CORRELMANT, 0x70 }, /* P2_CORRELMANT */ + { STV090x_P2_CORRELABS, 0x88 }, /* P2_CORRELABS */ + { STV090x_P2_CORRELEXP, 0xaa }, /* P2_CORRELEXP */ + { STV090x_P2_PLHMODCOD, 0x42 }, /* P2_PLHMODCOD */ +#if 0 + { STV090x_P2_AGCK32, 0x00 }, /* P2_AGCK32 */ + { STV090x_P2_AGC2O, 0x5b }, /* P2_AGC2O */ +#endif + { STV090x_P2_AGC2REF, 0x38 }, /* P2_AGC2REF */ + { STV090x_P2_AGC1ADJ, 0x58 }, /* P2_AGC1ADJ */ + { STV090x_P2_AGC2I1, 0x00 }, /* P2_AGC2I1 */ + { STV090x_P2_AGC2I0, 0x60 }, /* P2_AGC2I0 */ + { STV090x_P2_CARCFG, 0xe4 }, /* P2_CARCFG */ + { STV090x_P2_ACLC, 0x1a }, /* P2_ACLC */ + { STV090x_P2_BCLC, 0x09 }, /* P2_BCLC */ + { STV090x_P2_CARFREQ, 0x38 }, /* P2_CARFREQ */ + { STV090x_P2_CARHDR, 0x20 }, /* P2_CARHDR */ + { STV090x_P2_LDT, 0xd0 }, /* P2_LDT */ + { STV090x_P2_LDT2, 0xb0 }, /* P2_LDT2 */ + { STV090x_P2_CFRICFG, 0xf8 }, /* P2_CFRICFG */ + { STV090x_P2_CFRUP1, 0x3f }, /* P2_CFRUP1 */ + { STV090x_P2_CFRUP0, 0xff }, /* P2_CFRUP0 */ + { STV090x_P2_CFRLOW1, 0xc0 }, /* P2_CFRLOW1 */ + { STV090x_P2_CFRLOW0, 0x01 }, /* P2_CFRLOW0 */ + { STV090x_P2_CFRINIT1, 0xfc }, /* P2_CFRINIT1 */ + { STV090x_P2_CFRINIT0, 0xff }, /* P2_CFRINIT0 */ + { STV090x_P2_CFRINC1, 0x03 }, /* P2_CFRINC1 */ + { STV090x_P2_CFRINC0, 0x00 }, /* P2_CFRINC0 */ + { STV090x_P2_CFR2, 0xfc }, /* P2_CFR2 */ + { STV090x_P2_CFR1, 0xff }, /* P2_CFR1 */ + { STV090x_P2_CFR0, 0x00 }, /* P2_CFR0 */ + { STV090x_P2_LDI, 0x80 }, /* P2_LDI */ + { STV090x_P2_TMGCFG, 0xd2 }, /* P2_TMGCFG */ + { STV090x_P2_RTC, 0x88 }, /* P2_RTC */ + { STV090x_P2_RTCS2, 0x66 }, /* P2_RTCS2 */ + { STV090x_P2_TMGTHRISE, 0x20 }, /* P2_TMGTHRISE */ + { STV090x_P2_TMGTHFALL, 0x00 }, /* P2_TMGTHFALL */ + { STV090x_P2_SFRUPRATIO, 0xf0 }, /* P2_SFRUPRATIO */ + { STV090x_P2_SFRLOWRATIO, 0x70 }, /* P2_SFRLOWRATIO */ + { STV090x_P2_KREFTMG, 0x31 }, /* P2_KREFTMG */ + { STV090x_P2_SFRSTEP, 0x58 }, /* P2_SFRSTEP */ + { STV090x_P2_TMGCFG2, 0x01 }, /* P2_TMGCFG2 */ + { STV090x_P2_SFRINIT1, 0x03 }, /* P2_SFRINIT1 */ + { STV090x_P2_SFRINIT0, 0x01 }, /* P2_SFRINIT0 */ + { STV090x_P2_SFRUP1, 0x83 }, /* P2_SFRUP1 */ + { STV090x_P2_SFRUP0, 0xc0 }, /* P2_SFRUP0 */ + { STV090x_P2_SFRLOW1, 0x82 }, /* P2_SFRLOW1 */ + { STV090x_P2_SFRLOW0, 0xa0 }, /* P2_SFRLOW0 */ + { STV090x_P2_SFR3, 0x03 }, /* P2_SFR3 */ + { STV090x_P2_SFR2, 0x01 }, /* P2_SFR2 */ + { STV090x_P2_SFR1, 0x00 }, /* P2_SFR1 */ + { STV090x_P2_SFR0, 0x00 }, /* P2_SFR0 */ + { STV090x_P2_TMGREG2, 0x00 }, /* P2_TMGREG2 */ + { STV090x_P2_TMGREG1, 0x00 }, /* P2_TMGREG1 */ + { STV090x_P2_TMGREG0, 0x00 }, /* P2_TMGREG0 */ + { STV090x_P2_TMGLOCK1, 0x00 }, /* P2_TMGLOCK1 */ + { STV090x_P2_TMGLOCK0, 0x00 }, /* P2_TMGLOCK0 */ + { STV090x_P2_TMGOBS, 0x10 }, /* P2_TMGOBS */ + { STV090x_P2_EQUALCFG, 0x41 }, /* P2_EQUALCFG */ + { STV090x_P2_EQUAI1, 0xf0 }, /* P2_EQUAI1 */ + { STV090x_P2_EQUAQ1, 0x00 }, /* P2_EQUAQ1 */ + { STV090x_P2_EQUAI2, 0xf0 }, /* P2_EQUAI2 */ + { STV090x_P2_EQUAQ2, 0x00 }, /* P2_EQUAQ2 */ + { STV090x_P2_EQUAI3, 0xf0 }, /* P2_EQUAI3 */ + { STV090x_P2_EQUAQ3, 0x00 }, /* P2_EQUAQ3 */ + { STV090x_P2_EQUAI4, 0xf0 }, /* P2_EQUAI4 */ + { STV090x_P2_EQUAQ4, 0x00 }, /* P2_EQUAQ4 */ + { STV090x_P2_EQUAI5, 0xf0 }, /* P2_EQUAI5 */ + { STV090x_P2_EQUAQ5, 0x00 }, /* P2_EQUAQ5 */ + { STV090x_P2_EQUAI6, 0xf0 }, /* P2_EQUAI6 */ + { STV090x_P2_EQUAQ6, 0x00 }, /* P2_EQUAQ6 */ + { STV090x_P2_EQUAI7, 0xf0 }, /* P2_EQUAI7 */ + { STV090x_P2_EQUAQ7, 0x00 }, /* P2_EQUAQ7 */ + { STV090x_P2_EQUAI8, 0xf0 }, /* P2_EQUAI8 */ + { STV090x_P2_EQUAQ8, 0x00 }, /* P2_EQUAQ8 */ + { STV090x_P2_NNOSDATAT1, 0x01 }, /* P2_NNOSDATAT1 */ + { STV090x_P2_NNOSDATAT0, 0x65 }, /* P2_NNOSDATAT0 */ + { STV090x_P2_NNOSDATA1, 0x00 }, /* P2_NNOSDATA1 */ + { STV090x_P2_NNOSDATA0, 0x0d }, /* P2_NNOSDATA0 */ + { STV090x_P2_NNOSPLHT1, 0x4d }, /* P2_NNOSPLHT1 */ + { STV090x_P2_NNOSPLHT0, 0x6a }, /* P2_NNOSPLHT0 */ + { STV090x_P2_NNOSPLH1, 0x57 }, /* P2_NNOSPLH1 */ + { STV090x_P2_NNOSPLH0, 0x52 }, /* P2_NNOSPLH0 */ + { STV090x_P2_NOSDATAT1, 0x01 }, /* P2_NOSDATAT1 */ + { STV090x_P2_NOSDATAT0, 0x39 }, /* P2_NOSDATAT0 */ + { STV090x_P2_NOSDATA1, 0x00 }, /* P2_NOSDATA1 */ + { STV090x_P2_NOSDATA0, 0x0a }, /* P2_NOSDATA0 */ + { STV090x_P2_NOSPLHT1, 0x43 }, /* P2_NOSPLHT1 */ + { STV090x_P2_NOSPLHT0, 0xbd }, /* P2_NOSPLHT0 */ + { STV090x_P2_NNOSPLH1, 0x42 }, /* P2_NOSPLH1 */ + { STV090x_P2_NNOSPLH0, 0xdb }, /* P2_NOSPLH0 */ + { STV090x_P2_CAR2CFG, 0x26 }, /* P2_CAR2CFG */ + { STV090x_P2_ACLC2, 0x28 }, /* P2_ACLC2 */ + { STV090x_P2_BCLC2, 0x25 }, /* P2_BCLC2 */ +#if 0 + { STV090x_P2_CFR22, 0x00 }, /* P2_CFR22 */ + { STV090x_P2_CFR21, 0x00 }, /* P2_CFR21 */ + { STV090x_P2_CFR20, 0x00 }, /* P2_CFR20 */ +#endif + { STV090x_P2_ACLC2S2Q, 0x6a }, /* P2_ACLC2S2Q */ + { STV090x_P2_ACLC2S28, 0x58 }, /* P2_ACLC2S28 */ + { STV090x_P2_ACLC2S216A, 0x68 }, /* P2_ACLC2S216A */ + { STV090x_P2_ACLC2S232A, 0x68 }, /* P2_ACLC2S232A */ + + { STV090x_P2_BCLC2S2Q, 0x86 }, /* P2_BCLC2S2Q */ + { STV090x_P2_BCLC2S28, 0x86 }, /* P2_BCLC2S28 */ + { STV090x_P2_BCLC2S216A, 0xa5 }, /* P2_BCLC2S216A */ + { STV090x_P2_BCLC2S232A, 0xa5 }, /* P2_BCLC2S232A */ + + { STV090x_P2_PLROOT2, 0x00 }, /* P2_PLROOT2 */ + { STV090x_P2_FECM, 0x10 }, /* P2_FECM */ + { STV090x_P2_PLROOT1, 0x00 }, /* P2_PLROOT1 */ + { STV090x_P2_PLROOT0, 0x01 }, /* P2_PLROOT0 */ + { STV090x_P2_MODCODLST0, 0xff }, /* P2_MODCODLST0 */ + { STV090x_P2_MODCODLST1, 0xff }, /* P2_MODCODLST1 */ + { STV090x_P2_MODCODLST2, 0xff }, /* P2_MODCODLST2 */ + { STV090x_P2_MODCODLST3, 0xff }, /* P2_MODCODLST3 */ + { STV090x_P2_MODCODLST4, 0xff }, /* P2_MODCODLST4 */ + { STV090x_P2_MODCODLST5, 0xff }, /* P2_MODCODLST5 */ + { STV090x_P2_MODCODLST6, 0xff }, /* P2_MODCODLST6 */ + { STV090x_P2_MODCODLST7, 0xcc }, /* P2_MODCODLST7 */ + { STV090x_P2_MODCODLST8, 0xcc }, /* P2_MODCODLST8 */ + { STV090x_P2_MODCODLST9, 0xcc }, /* P2_MODCODLST9 */ + { STV090x_P2_MODCODLSTA, 0xcc }, /* P2_MODCODLSTA */ + { STV090x_P2_MODCODLSTB, 0xcc }, /* P2_MODCODLSTB */ + { STV090x_P2_MODCODLSTC, 0xcc }, /* P2_MODCODLSTC */ + { STV090x_P2_MODCODLSTD, 0xcc }, /* P2_MODCODLSTD */ + { STV090x_P2_MODCODLSTE, 0xcc }, /* P2_MODCODLSTE */ + { STV090x_P2_MODCODLSTF, 0xcf }, /* P2_MODCODLSTF */ + { STV090x_P2_DMDRESCFG, 0x29 }, /* P2_DMDRESCFG */ + { STV090x_P2_DMDRESADR, 0x11 }, /* P2_DMDRESADR */ + { STV090x_P2_DMDRESDATA7, 0x47 }, /* P2_DMDRESDATA7 */ + { STV090x_P2_DMDRESDATA6, 0x82 }, /* P2_DMDRESDATA6 */ + { STV090x_P2_DMDRESDATA5, 0x00 }, /* P2_DMDRESDATA5 */ + { STV090x_P2_DMDRESDATA4, 0x00 }, /* P2_DMDRESDATA4 */ + { STV090x_P2_DMDRESDATA3, 0x92 }, /* P2_DMDRESDATA3 */ + { STV090x_P2_DMDRESDATA2, 0x4c }, /* P2_DMDRESDATA2 */ + { STV090x_P2_DMDRESDATA1, 0x00 }, /* P2_DMDRESDATA1 */ + { STV090x_P2_DMDRESDATA0, 0x07 }, /* P2_DMDRESDATA0 */ + { STV090x_P2_FFEI1, 0x00 }, /* P2_FFEI1 */ + { STV090x_P2_FFEQ1, 0x00 }, /* P2_FFEQ1 */ + { STV090x_P2_FFEI2, 0x00 }, /* P2_FFEI2 */ + { STV090x_P2_FFEQ2, 0x00 }, /* P2_FFEQ2 */ + { STV090x_P2_FFEI3, 0x00 }, /* P2_FFEI3 */ + { STV090x_P2_FFEQ3, 0x00 }, /* P2_FFEQ3 */ + { STV090x_P2_FFEI4, 0x00 }, /* P2_FFEI4 */ + { STV090x_P2_FFEQ4, 0x00 }, /* P2_FFEQ4 */ + { STV090x_P2_FFECFG, 0x31 }, /* P2_FFECFG */ +#if 0 + { STV090x_P2_TNRCFG, 0xef }, /* P2_TNRCFG */ + { STV090x_P2_TNRCFG2, 0x02 }, /* P2_TNRCFG2 */ + { STV090x_P2_TNRXTAL, 0x1b }, /* P2_TNRXTAL */ + { STV090x_P2_TNRSTEPS, 0x87 }, /* P2_TNRSTEPS */ + { STV090x_P2_TNRGAIN, 0x09 }, /* P2_TNRGAIN */ + { STV090x_P2_TNRRF1, 0x47 }, /* P2_TNRRF1 */ + { STV090x_P2_TNRRF0, 0x82 }, /* P2_TNRRF0 */ + { STV090x_P2_TNRBW, 0x24 }, /* P2_TNRBW */ + { STV090x_P2_TNRADJ, 0x1f }, /* P2_TNRADJ */ + { STV090x_P2_TNRCTL2, 0x37 }, /* P2_TNRCTL2 */ + { STV090x_P2_TNRCFG3, 0x02 }, /* P2_TNRCFG3 */ + { STV090x_P2_TNRLAUNCH, 0x00 }, /* P2_TNRLAUNCH */ + { STV090x_P2_TNRLD, 0x00 }, /* P2_TNRLD */ + { STV090x_P2_TNROBSL, 0x50 }, /* P2_TNROBSL */ + { STV090x_P2_TNRRESTE, 0x00 }, /* P2_TNRRESTE */ +#endif + { STV090x_P2_SMAPCOEF7, 0x06 }, /* P2_SMAPCOEF7 */ + { STV090x_P2_SMAPCOEF6, 0x00 }, /* P2_SMAPCOEF6 */ + { STV090x_P2_SMAPCOEF5, 0x04 }, /* P2_SMAPCOEF5 */ + { STV090x_P2_DMDPLHSTAT, 0x00 }, /* P2_DMDPLHSTAT */ + { STV090x_P2_LOCKTIME3, 0xff }, /* P2_LOCKTIME3 */ + { STV090x_P2_LOCKTIME2, 0xf0 }, /* P2_LOCKTIME2 */ + { STV090x_P2_LOCKTIME1, 0x5a }, /* P2_LOCKTIME1 */ + { STV090x_P2_LOCKTIME0, 0x86 }, /* P2_LOCKTIME0 */ + { STV090x_P2_VITSCALE, 0x00 }, /* P2_VITSCALE */ + { STV090x_P2_FECM, 0x10 }, /* P2_FECM */ + { STV090x_P2_VTH12, 0xd0 }, /* P2_VTH12 */ + { STV090x_P2_VTH23, 0x7d }, /* P2_VTH23 */ + { STV090x_P2_VTH34, 0x53 }, /* P2_VTH34 */ + { STV090x_P2_VTH56, 0x2f }, /* P2_VTH56 */ + { STV090x_P2_VTH67, 0x24 }, /* P2_VTH67 */ + { STV090x_P2_VTH78, 0x1f }, /* P2_VTH78 */ + { STV090x_P2_VITCURPUN, 0x0d }, /* P2_VITCURPUN */ + { STV090x_P2_VERROR, 0xff }, /* P2_VERROR */ + { STV090x_P2_PRVIT, 0x3f }, /* P2_PRVIT */ + { STV090x_P2_VAVSRVIT, 0x00 }, /* P2_VAVSRVIT */ + { STV090x_P2_VSTATUSVIT, 0xa7 }, /* P2_VSTATUSVIT */ + { STV090x_P2_VTHINUSE, 0x01 }, /* P2_VTHINUSE */ + { STV090x_P2_KDIV12, 0x27 }, /* P2_KDIV12 */ + { STV090x_P2_KDIV23, 0x32 }, /* P2_KDIV23 */ + { STV090x_P2_KDIV34, 0x32 }, /* P2_KDIV34 */ + { STV090x_P2_KDIV56, 0x32 }, /* P2_KDIV56 */ + { STV090x_P2_KDIV67, 0x32 }, /* P2_KDIV67 */ + { STV090x_P2_KDIV78, 0x50 }, /* P2_KDIV78 */ + { STV090x_P2_PDELCTRL1, 0x00 }, /* P2_PDELCTRL1 */ + { STV090x_P2_PDELCTRL2, 0x20 }, /* P2_PDELCTRL2 */ + { STV090x_P2_HYSTTHRESH, 0x41 }, /* P2_HYSTTHRESH */ + { STV090x_P2_ISIENTRY, 0x00 }, /* P2_ISIENTRY */ + { STV090x_P2_ISIBITENA, 0x00 }, /* P2_ISIBITENA */ + { STV090x_P2_MATSTR1, 0xf0 }, /* P2_MATSTR1 */ + { STV090x_P2_MATSTR0, 0x00 }, /* P2_MATSTR0 */ + { STV090x_P2_UPLSTR1, 0x05 }, /* P2_UPLSTR1 */ + { STV090x_P2_UPLSTR0, 0xe0 }, /* P2_UPLSTR0 */ + { STV090x_P2_DFLSTR1, 0x7d }, /* P2_DFLSTR1 */ + { STV090x_P2_DFLSTR0, 0x80 }, /* P2_DFLSTR0 */ + { STV090x_P2_SYNCSTR, 0x47 }, /* P2_SYNCSTR */ + { STV090x_P2_SYNCDSTR1, 0x00 }, /* P2_SYNCDSTR1 */ + { STV090x_P2_SYNCDSTR0, 0x00 }, /* P2_SYNCDSTR0 */ + { STV090x_P2_PDELSTATUS1, 0x94 }, /* P2_PDELSTATUS1 */ + { STV090x_P2_PDELSTATUS2, 0x90 }, /* P2_PDELSTATUS2 */ + { STV090x_P2_BBFCRCKO1, 0x00 }, /* P2_BBFCRCKO1 */ + { STV090x_P2_BBFCRCKO0, 0x00 }, /* P2_BBFCRCKO0 */ + { STV090x_P2_UPCRCKO1, 0x00 }, /* P2_UPCRCKO1 */ + { STV090x_P2_UPCRCKO0, 0x00 }, /* P2_UPCRCKO0 */ + { STV090x_P2_TSSTATEM, 0xb0 }, /* P2_TSSTATEM */ + { STV090x_P2_TSCFGH, 0x40 }, /* P2_TSCFGH */ + { STV090x_P2_TSCFGM, 0x00 }, /* P2_TSCFGM */ + { STV090x_P2_TSCFGL, 0x20 }, /* P2_TSCFGL */ + { STV090x_P2_TSINSDELH, 0x00 }, /* P2_TSINSDELH */ + { STV090x_P2_TSSPEED, 0xff }, /* P2_TSSPEED */ + { STV090x_P2_TSSTATUS, 0x52 }, /* P2_TSSTATUS */ + { STV090x_P2_TSSTATUS2, 0xea }, /* P2_TSSTATUS2 */ + { STV090x_P2_TSBITRATE1, 0x00 }, /* P2_TSBITRATE1 */ + { STV090x_P2_TSBITRATE0, 0x00 }, /* P2_TSBITRATE0 */ + { STV090x_P2_ERRCTRL1, 0x35 }, /* P2_ERRCTRL1 */ + { STV090x_P2_ERRCNT12, 0x80 }, /* P2_ERRCNT12 */ + { STV090x_P2_ERRCNT11, 0x00 }, /* P2_ERRCNT11 */ + { STV090x_P2_ERRCNT10, 0x00 }, /* P2_ERRCNT10 */ + { STV090x_P2_ERRCTRL2, 0xc1 }, /* P2_ERRCTRL2 */ + { STV090x_P2_ERRCNT22, 0x00 }, /* P2_ERRCNT22 */ + { STV090x_P2_ERRCNT21, 0x00 }, /* P2_ERRCNT21 */ + { STV090x_P2_ERRCNT20, 0x00 }, /* P2_ERRCNT20 */ + { STV090x_P2_FECSPY, 0xa8 }, /* P2_FECSPY */ + { STV090x_P2_FSPYCFG, 0x2c }, /* P2_FSPYCFG */ + { STV090x_P2_FSPYDATA, 0x3a }, /* P2_FSPYDATA */ + { STV090x_P2_FSPYOUT, 0x07 }, /* P2_FSPYOUT */ + { STV090x_P2_FSTATUS, 0x00 }, /* P2_FSTATUS */ + { STV090x_P2_FBERCPT4, 0x00 }, /* P2_FBERCPT4 */ + { STV090x_P2_FBERCPT3, 0x00 }, /* P2_FBERCPT3 */ + { STV090x_P2_FBERCPT2, 0x00 }, /* P2_FBERCPT2 */ + { STV090x_P2_FBERCPT1, 0x00 }, /* P2_FBERCPT1 */ + { STV090x_P2_FBERCPT0, 0x00 }, /* P2_FBERCPT0 */ + { STV090x_P2_FBERERR2, 0x00 }, /* P2_FBERERR2 */ + { STV090x_P2_FBERERR1, 0x00 }, /* P2_FBERERR1 */ + { STV090x_P2_FBERERR0, 0x00 }, /* P2_FBERERR0 */ + { STV090x_P2_FSPYBER, 0x10 }, /* P2_FSPYBER */ + { STV090x_P1_IQCONST, 0x00 }, /* P1_IQCONST */ + { STV090x_P1_NOSCFG, 0x1c }, /* P1_NOSCFG */ + { STV090x_P1_ISYMB, 0x29 }, /* P1_ISYMB */ + { STV090x_P1_QSYMB, 0x29 }, /* P1_QSYMB */ + { STV090x_P1_AGC1CFG, 0x54 }, /* P1_AGC1CFG */ + { STV090x_P1_AGC1CN, 0x99 }, /* P1_AGC1CN */ + { STV090x_P1_AGC1REF, 0x58 }, /* P1_AGC1REF */ + { STV090x_P1_IDCCOMP, 0x03 }, /* P1_IDCCOMP */ + { STV090x_P1_QDCCOMP, 0xfe }, /* P1_QDCCOMP */ + { STV090x_P1_POWERI, 0x91 }, /* P1_POWERI */ + { STV090x_P1_POWERQ, 0x86 }, /* P1_POWERQ */ + { STV090x_P1_AGC1AMM, 0x08 }, /* P1_AGC1AMM */ + { STV090x_P1_AGC1QUAD, 0x02 }, /* P1_AGC1QUAD */ + { STV090x_P1_AGCIQIN1, 0x68 }, /* P1_AGCIQIN1 */ + { STV090x_P1_AGCIQIN0, 0x20 }, /* P1_AGCIQIN0 */ + { STV090x_P1_DEMOD, 0x08 }, /* P1_DEMOD */ + { STV090x_P1_DMDMODCOD, 0x10 }, /* P1_DMDMODCOD */ + { STV090x_P1_DSTATUS, 0x10 }, /* P1_DSTATUS */ + { STV090x_P1_DSTATUS2, 0x80 }, /* P1_DSTATUS2 */ + { STV090x_P1_DMDCFGMD, 0xf9 }, /* P1_DMDCFGMD */ + { STV090x_P1_DMDCFG2, 0x3b }, /* P1_DMDCFG2 */ + { STV090x_P1_DMDISTATE, 0x5c }, /* P1_DMDISTATE */ +#if 0 + { STV090x_P1_DMDT0M, 0x20 }, /* P1_DMDT0M */ +#endif + { STV090x_P1_DMDSTATE, 0x1c }, /* P1_DMDSTATE */ + { STV090x_P1_DMDFLYW, 0x00 }, /* P1_DMDFLYW */ + { STV090x_P1_DSTATUS3, 0x00 }, /* P1_DSTATUS3 */ + { STV090x_P1_DMDCFG3, 0x68 }, /* P1_DMDCFG3 */ +#if 0 + { STV090x_P1_DMDCFG4, 0x10 }, /* P1_DMDCFG4 */ +#endif + { STV090x_P1_CORRELMANT, 0x70 }, /* P1_CORRELMANT */ + { STV090x_P1_CORRELABS, 0x88 }, /* P1_CORRELABS */ + { STV090x_P1_CORRELEXP, 0xaa }, /* P1_CORRELEXP */ + { STV090x_P1_PLHMODCOD, 0x42 }, /* P1_PLHMODCOD */ +#if 0 + { STV090x_P1_AGCK32, 0x00 }, /* P1_AGCK32 */ + { STV090x_P1_AGC2O, 0x5b }, /* P1_AGC2O */ +#endif + { STV090x_P1_AGC2REF, 0x38 }, /* P1_AGC2REF */ + { STV090x_P1_AGC1ADJ, 0x58 }, /* P1_AGC1ADJ */ + { STV090x_P1_AGC2I1, 0x00 }, /* P1_AGC2I1 */ + { STV090x_P1_AGC2I0, 0x60 }, /* P1_AGC2I0 */ + { STV090x_P1_CARCFG, 0xe4 }, /* P1_CARCFG */ + { STV090x_P2_AGC2REF, 0x38 }, + { STV090x_P1_ACLC, 0x1a }, /* P1_ACLC */ + { STV090x_P1_BCLC, 0x09 }, /* P1_BCLC */ + { STV090x_P1_CARFREQ, 0x38 }, /* P1_CARFREQ */ + { STV090x_P1_CARHDR, 0x20 }, /* P1_CARHDR */ + { STV090x_P1_LDT, 0xd0 }, /* P1_LDT */ + { STV090x_P1_LDT2, 0xb0 }, /* P1_LDT2 */ + { STV090x_P1_CFRICFG, 0xf8 }, /* P1_CFRICFG */ + { STV090x_P1_CFRUP1, 0x3f }, /* P1_CFRUP1 */ + { STV090x_P1_CFRUP0, 0xff }, /* P1_CFRUP0 */ + { STV090x_P1_CFRLOW1, 0xc0 }, /* P1_CFRLOW1 */ + { STV090x_P1_CFRLOW0, 0x01 }, /* P1_CFRLOW0 */ + { STV090x_P1_CFRINIT1, 0x03 }, /* P1_CFRINIT1 */ + { STV090x_P1_CFRINIT0, 0x00 }, /* P1_CFRINIT0 */ + { STV090x_P1_CFRINC1, 0x03 }, /* P1_CFRINC1 */ + { STV090x_P1_CFRINC0, 0x00 }, /* P1_CFRINC0 */ + { STV090x_P1_CFR2, 0x03 }, /* P1_CFR2 */ + { STV090x_P1_CFR1, 0x00 }, /* P1_CFR1 */ + { STV090x_P1_CFR0, 0x00 }, /* P1_CFR0 */ + { STV090x_P1_LDI, 0x80 }, /* P1_LDI */ + { STV090x_P1_TMGCFG, 0xd3 }, /* P1_TMGCFG */ + { STV090x_P1_RTC, 0x88 }, /* P1_RTC */ + { STV090x_P1_RTCS2, 0x66 }, /* P1_RTCS2 */ + { STV090x_P1_TMGTHRISE, 0x20 }, /* P1_TMGTHRISE */ + { STV090x_P1_TMGTHFALL, 0x00 }, /* P1_TMGTHFALL */ + { STV090x_P1_SFRUPRATIO, 0xf0 }, /* P1_SFRUPRATIO */ + { STV090x_P1_SFRLOWRATIO, 0x70 }, /* P1_SFRLOWRATIO */ + { STV090x_P1_KREFTMG, 0x31 }, /* P1_KREFTMG */ + { STV090x_P1_SFRSTEP, 0x58 }, /* P1_SFRSTEP */ + { STV090x_P1_TMGCFG2, 0x01 }, /* P1_TMGCFG2 */ + { STV090x_P1_SFRINIT1, 0x03 }, /* P1_SFRINIT1 */ + { STV090x_P1_SFRINIT0, 0x01 }, /* P1_SFRINIT0 */ + { STV090x_P1_SFRUP1, 0x83 }, /* P1_SFRUP1 */ + { STV090x_P1_SFRUP0, 0xc0 }, /* P1_SFRUP0 */ + { STV090x_P2_AGC2REF, 0x38 }, + { STV090x_P1_SFRLOW1, 0x82 }, /* P1_SFRLOW1 */ + { STV090x_P1_SFRLOW0, 0xa0 }, /* P1_SFRLOW0 */ + { STV090x_P1_SFR3, 0x03 }, /* P1_SFR3 */ + { STV090x_P1_SFR2, 0x01 }, /* P1_SFR2 */ + { STV090x_P1_SFR1, 0x00 }, /* P1_SFR1 */ + { STV090x_P1_SFR0, 0x00 }, /* P1_SFR0 */ + { STV090x_P1_TMGREG2, 0x00 }, /* P1_TMGREG2 */ + { STV090x_P1_TMGREG1, 0x00 }, /* P1_TMGREG1 */ + { STV090x_P1_TMGREG0, 0x00 }, /* P1_TMGREG0 */ + { STV090x_P1_TMGLOCK1, 0x00 }, /* P1_TMGLOCK1 */ + { STV090x_P1_TMGLOCK0, 0x00 }, /* P1_TMGLOCK0 */ + { STV090x_P1_TMGOBS, 0x10 }, /* P1_TMGOBS */ + { STV090x_P1_EQUALCFG, 0x41 }, /* P1_EQUALCFG */ + { STV090x_P1_EQUAI1, 0xf1 }, /* P1_EQUAI1 */ + { STV090x_P1_EQUAQ1, 0x00 }, /* P1_EQUAQ1 */ + { STV090x_P1_EQUAI2, 0xf1 }, /* P1_EQUAI2 */ + { STV090x_P1_EQUAQ2, 0x00 }, /* P1_EQUAQ2 */ + { STV090x_P1_EQUAI3, 0xf1 }, /* P1_EQUAI3 */ + { STV090x_P1_EQUAQ3, 0x00 }, /* P1_EQUAQ3 */ + { STV090x_P1_EQUAI4, 0xf1 }, /* P1_EQUAI4 */ + { STV090x_P1_EQUAQ4, 0x00 }, /* P1_EQUAQ4 */ + { STV090x_P1_EQUAI5, 0xf1 }, /* P1_EQUAI5 */ + { STV090x_P1_EQUAQ5, 0x00 }, /* P1_EQUAQ5 */ + { STV090x_P1_EQUAI6, 0xf1 }, /* P1_EQUAI6 */ + { STV090x_P1_EQUAQ6, 0x00 }, /* P1_EQUAQ6 */ + { STV090x_P1_EQUAI7, 0xf1 }, /* P1_EQUAI7 */ + { STV090x_P1_EQUAQ7, 0x00 }, /* P1_EQUAQ7 */ + { STV090x_P1_EQUAI8, 0xf1 }, /* P1_EQUAI8 */ + { STV090x_P1_EQUAQ8, 0x00 }, /* P1_EQUAQ8 */ + { STV090x_P1_NNOSDATAT1, 0x01 }, /* P1_NNOSDATAT1 */ + { STV090x_P1_NNOSDATAT0, 0xab }, /* P1_NNOSDATAT0 */ + { STV090x_P1_NNOSDATA1, 0x00 }, /* P1_NNOSDATA1 */ + { STV090x_P1_NNOSDATA0, 0x12 }, /* P1_NNOSDATA0 */ + { STV090x_P1_NNOSPLHT1, 0x4d }, /* P1_NNOSPLHT1 */ + { STV090x_P1_NNOSPLHT0, 0x7b }, /* P1_NNOSPLHT0 */ + { STV090x_P1_NNOSPLH1, 0x57 }, /* P1_NNOSPLH1 */ + { STV090x_P1_NNOSPLH0, 0x52 }, /* P1_NNOSPLH0 */ + { STV090x_P1_NOSDATAT1, 0x01 }, /* P1_NOSDATAT1 */ + { STV090x_P1_NOSDATAT0, 0x76 }, /* P1_NOSDATAT0 */ + { STV090x_P1_NOSDATA1, 0x00 }, /* P1_NOSDATA1 */ + { STV090x_P1_NOSDATA0, 0x0e }, /* P1_NOSDATA0 */ + { STV090x_P1_NOSPLHT1, 0x43 }, /* P1_NOSPLHT1 */ + { STV090x_P1_NOSPLHT0, 0xcc }, /* P1_NOSPLHT0 */ + { STV090x_P1_NNOSPLH1, 0x42 }, /* P1_NOSPLH1 */ + { STV090x_P1_NNOSPLH0, 0xdb }, /* P1_NOSPLH0 */ + { STV090x_P1_CAR2CFG, 0x26 }, /* P1_CAR2CFG */ + { STV090x_P1_ACLC2, 0x28 }, /* P1_ACLC2 */ + { STV090x_P1_BCLC2, 0x25 }, /* P1_BCLC2 */ +#if 0 + { STV090x_P1_CFR22, 0x00 }, /* P2_CFR22 */ + { STV090x_P1_CFR21, 0x00 }, /* P2_CFR21 */ + { STV090x_P1_CFR20, 0x00 }, /* P2_CFR20 */ +#endif + { STV090x_P1_ACLC2S2Q, 0x6a }, /* P1_ACLC2S2Q */ + { STV090x_P1_ACLC2S28, 0x58 }, /* P1_ACLC2S28 */ + { STV090x_P1_ACLC2S216A, 0x68 }, /* P2_ACLC2S216A */ + { STV090x_P1_ACLC2S232A, 0x68 }, /* P2_ACLC2S232A */ + { STV090x_P1_BCLC2S2Q, 0x86 }, /* P1_BCLC2S2Q */ + { STV090x_P1_BCLC2S28, 0x86 }, /* P1_BCLC2S28 */ + { STV090x_P1_BCLC2S216A, 0xa5 }, /* P2_BCLC2S216A */ + { STV090x_P1_BCLC2S232A, 0xa5 }, /* P2_BCLC2S232A */ + + { STV090x_P1_PLROOT2, 0x00 }, /* P1_PLROOT2 */ + { STV090x_P1_PLROOT1, 0x00 }, /* P1_PLROOT1 */ + { STV090x_P1_PLROOT0, 0x01 }, /* P1_PLROOT0 */ + { STV090x_P1_MODCODLST0, 0xff }, /* P1_MODCODLST0 */ + { STV090x_P1_MODCODLST1, 0xff }, /* P1_MODCODLST1 */ + { STV090x_P1_MODCODLST2, 0xff }, /* P1_MODCODLST2 */ + { STV090x_P1_MODCODLST3, 0xff }, /* P1_MODCODLST3 */ + { STV090x_P1_MODCODLST4, 0xff }, /* P1_MODCODLST4 */ + { STV090x_P1_MODCODLST5, 0xff }, /* P1_MODCODLST5 */ + { STV090x_P1_MODCODLST6, 0xff }, /* P1_MODCODLST6 */ + { STV090x_P1_MODCODLST7, 0xcc }, /* P1_MODCODLST7 */ + { STV090x_P1_MODCODLST8, 0xcc }, /* P1_MODCODLST8 */ + { STV090x_P1_MODCODLST9, 0xcc }, /* P1_MODCODLST9 */ + { STV090x_P1_MODCODLSTA, 0xcc }, /* P1_MODCODLSTA */ + { STV090x_P1_MODCODLSTB, 0xcc }, /* P1_MODCODLSTB */ + { STV090x_P1_MODCODLSTC, 0xcc }, /* P1_MODCODLSTC */ + { STV090x_P1_MODCODLSTD, 0xcc }, /* P1_MODCODLSTD */ + { STV090x_P1_MODCODLSTE, 0xcc }, /* P1_MODCODLSTE */ + { STV090x_P1_MODCODLSTF, 0xcf }, /* P1_MODCODLSTF */ + { STV090x_P1_DMDRESCFG, 0x29 }, /* P1_DMDRESCFG */ + { STV090x_P1_DMDRESADR, 0x11 }, /* P1_DMDRESADR */ + { STV090x_P1_DMDRESDATA7, 0x4e }, /* P1_DMDRESDATA7 */ + { STV090x_P1_DMDRESDATA6, 0x7f }, /* P1_DMDRESDATA6 */ + { STV090x_P1_DMDRESDATA5, 0x00 }, /* P1_DMDRESDATA5 */ + { STV090x_P1_DMDRESDATA4, 0x04 }, /* P1_DMDRESDATA4 */ + { STV090x_P1_DMDRESDATA3, 0x92 }, /* P1_DMDRESDATA3 */ + { STV090x_P1_DMDRESDATA2, 0xcc }, /* P1_DMDRESDATA2 */ + { STV090x_P1_DMDRESDATA1, 0x0a }, /* P1_DMDRESDATA1 */ + { STV090x_P1_DMDRESDATA0, 0x07 }, /* P1_DMDRESDATA0 */ + { STV090x_P1_FFEI1, 0x00 }, /* P1_FFEI1 */ + { STV090x_P1_FFEQ1, 0x00 }, /* P1_FFEQ1 */ + { STV090x_P1_FFEI2, 0x00 }, /* P1_FFEI2 */ + { STV090x_P1_FFEQ2, 0x00 }, /* P1_FFEQ2 */ + { STV090x_P1_FFEI3, 0x00 }, /* P1_FFEI3 */ + { STV090x_P1_FFEQ3, 0x00 }, /* P1_FFEQ3 */ + { STV090x_P1_FFEI4, 0x00 }, /* P1_FFEI4 */ + { STV090x_P1_FFEQ4, 0x00 }, /* P1_FFEQ4 */ + { STV090x_P1_FFECFG, 0x31 }, /* P1_FFECFG */ +#if 0 + { STV090x_P1_TNRCFG, 0xec }, /* P1_TNRCFG */ + { STV090x_P1_TNRCFG2, 0x82 }, /* P1_TNRCFG2 */ + { STV090x_P1_TNRXTAL, 0x1b }, /* P1_TNRXTAL */ + { STV090x_P1_TNRSTEPS, 0x87 }, /* P1_TNRSTEPS */ + { STV090x_P1_TNRGAIN, 0x09 }, /* P1_TNRGAIN */ + { STV090x_P1_TNRRF1, 0x4e }, /* P1_TNRRF1 */ + { STV090x_P1_TNRRF0, 0x7f }, /* P1_TNRRF0 */ + { STV090x_P1_TNRBW, 0x64 }, /* P1_TNRBW */ + { STV090x_P1_TNRADJ, 0x1f }, /* P1_TNRADJ */ + { STV090x_P1_TNRCTL2, 0x37 }, /* P1_TNRCTL2 */ + { STV090x_P1_TNRCFG3, 0x02 }, /* P1_TNRCFG3 */ + { STV090x_P1_TNRLAUNCH, 0x00 }, /* P1_TNRLAUNCH */ + { STV090x_P1_TNRLD, 0x00 }, /* P1_TNRLD */ + { STV090x_P1_TNROBSL, 0x50 }, /* P1_TNROBSL */ + { STV090x_P1_TNRRESTE, 0x40 }, /* P1_TNRRESTE */ +#endif + { STV090x_P1_SMAPCOEF7, 0x06 }, /* P1_SMAPCOEF7 */ + { STV090x_P1_SMAPCOEF6, 0x00 }, /* P1_SMAPCOEF6 */ + { STV090x_P1_SMAPCOEF5, 0x04 }, /* P1_SMAPCOEF5 */ + { STV090x_P1_DMDPLHSTAT, 0x00 }, /* P1_DMDPLHSTAT */ + { STV090x_P1_LOCKTIME3, 0xff }, /* P1_LOCKTIME3 */ + { STV090x_P1_LOCKTIME2, 0xf0 }, /* P1_LOCKTIME2 */ + { STV090x_P1_LOCKTIME1, 0x73 }, /* P1_LOCKTIME1 */ + { STV090x_P1_LOCKTIME0, 0x27 }, /* P1_LOCKTIME0 */ + { STV090x_P1_VITSCALE, 0x00 }, /* P1_VITSCALE */ + { STV090x_P1_FECM, 0x10 }, /* P1_FECM */ + { STV090x_P1_VTH12, 0xd0 }, /* P1_VTH12 */ + { STV090x_P1_VTH23, 0x7d }, /* P1_VTH23 */ + { STV090x_P1_VTH34, 0x53 }, /* P1_VTH34 */ + { STV090x_P1_VTH56, 0x2f }, /* P1_VTH56 */ + { STV090x_P1_VTH67, 0x24 }, /* P1_VTH67 */ + { STV090x_P1_VTH78, 0x1f }, /* P1_VTH78 */ + { STV090x_P1_VITCURPUN, 0x0d }, /* P1_VITCURPUN */ + { STV090x_P1_VERROR, 0xff }, /* P1_VERROR */ + { STV090x_P1_PRVIT, 0x3f }, /* P1_PRVIT */ + { STV090x_P1_VAVSRVIT, 0x00 }, /* P1_VAVSRVIT */ + { STV090x_P1_VSTATUSVIT, 0xa5 }, /* P1_VSTATUSVIT */ + { STV090x_P1_VTHINUSE, 0x01 }, /* P1_VTHINUSE */ + { STV090x_P1_KDIV12, 0x27 }, /* P1_KDIV12 */ + { STV090x_P1_KDIV23, 0x32 }, /* P1_KDIV23 */ + { STV090x_P1_KDIV34, 0x32 }, /* P1_KDIV34 */ + { STV090x_P2_AGC2REF, 0x38 }, + { STV090x_P1_KDIV56, 0x32 }, /* P1_KDIV56 */ + { STV090x_P1_KDIV67, 0x32 }, /* P1_KDIV67 */ + { STV090x_P1_KDIV78, 0x50 }, /* P1_KDIV78 */ + { STV090x_P1_PDELCTRL1, 0x00 }, /* P1_PDELCTRL1 */ + { STV090x_P1_PDELCTRL2, 0x00 }, /* P1_PDELCTRL2 */ + { STV090x_P1_HYSTTHRESH, 0x41 }, /* P1_HYSTTHRESH */ + { STV090x_P1_ISIENTRY, 0x00 }, /* P1_ISIENTRY */ + { STV090x_P1_ISIBITENA, 0x00 }, /* P1_ISIBITENA */ + { STV090x_P1_MATSTR1, 0xf0 }, /* P1_MATSTR1 */ + { STV090x_P1_MATSTR0, 0x00 }, /* P1_MATSTR0 */ + { STV090x_P1_UPLSTR1, 0x05 }, /* P1_UPLSTR1 */ + { STV090x_P1_UPLSTR0, 0xe0 }, /* P1_UPLSTR0 */ + { STV090x_P1_DFLSTR1, 0x7d }, /* P1_DFLSTR1 */ + { STV090x_P1_DFLSTR0, 0x80 }, /* P1_DFLSTR0 */ + { STV090x_P1_SYNCSTR, 0x47 }, /* P1_SYNCSTR */ + { STV090x_P1_SYNCDSTR1, 0x00 }, /* P1_SYNCDSTR1 */ + { STV090x_P1_SYNCDSTR0, 0x00 }, /* P1_SYNCDSTR0 */ + { STV090x_P1_PDELSTATUS1, 0x94 }, /* P1_PDELSTATUS1 */ + { STV090x_P1_PDELSTATUS2, 0x10 }, /* P1_PDELSTATUS2 */ + { STV090x_P1_BBFCRCKO1, 0x00 }, /* P1_BBFCRCKO1 */ + { STV090x_P1_BBFCRCKO0, 0x00 }, /* P1_BBFCRCKO0 */ + { STV090x_P1_UPCRCKO1, 0x00 }, /* P1_UPCRCKO1 */ + { STV090x_P1_UPCRCKO0, 0x00 }, /* P1_UPCRCKO0 */ + { STV090x_P1_TSSTATEM, 0xb0 }, /* P1_TSSTATEM */ + { STV090x_P1_TSCFGH, 0x40 }, /* P1_TSCFGH */ + { STV090x_P1_TSCFGM, 0x00 }, /* P1_TSCFGM */ + { STV090x_P1_TSCFGL, 0x20 }, /* P1_TSCFGL */ + { STV090x_P1_TSINSDELH, 0x00 }, /* P1_TSINSDELH */ + { STV090x_P1_TSSPEED, 0xff }, /* P1_TSSPEED */ + { STV090x_P1_TSSTATUS, 0x52 }, /* P1_TSSTATUS */ + { STV090x_P1_TSSTATUS2, 0x6a }, /* P1_TSSTATUS2 */ + { STV090x_P1_TSBITRATE1, 0x00 }, /* P1_TSBITRATE1 */ + { STV090x_P1_TSBITRATE0, 0x00 }, /* P1_TSBITRATE0 */ + { STV090x_P1_ERRCTRL1, 0x35 }, /* P1_ERRCTRL1 */ + { STV090x_P1_ERRCNT12, 0x80 }, /* P1_ERRCNT12 */ + { STV090x_P1_ERRCNT11, 0x00 }, /* P1_ERRCNT11 */ + { STV090x_P1_ERRCNT10, 0x00 }, /* P1_ERRCNT10 */ + { STV090x_P1_ERRCTRL2, 0xc1 }, /* P1_ERRCTRL2 */ + { STV090x_P1_ERRCNT22, 0x00 }, /* P1_ERRCNT22 */ + { STV090x_P1_ERRCNT21, 0x00 }, /* P1_ERRCNT21 */ + { STV090x_P1_ERRCNT20, 0x00 }, /* P1_ERRCNT20 */ + { STV090x_P1_FECSPY, 0xa8 }, /* P1_FECSPY */ + { STV090x_P1_FSPYCFG, 0x2c }, /* P1_FSPYCFG */ + { STV090x_P1_FSPYDATA, 0x3a }, /* P1_FSPYDATA */ + { STV090x_P1_FSPYOUT, 0x07 }, /* P1_FSPYOUT */ + { STV090x_P2_AGC2REF, 0x38 }, + { STV090x_P1_FSTATUS, 0x00 }, /* P1_FSTATUS */ + { STV090x_P1_FBERCPT4, 0x00 }, /* P1_FBERCPT4 */ + { STV090x_P1_FBERCPT3, 0x00 }, /* P1_FBERCPT3 */ + { STV090x_P1_FBERCPT2, 0x00 }, /* P1_FBERCPT2 */ + { STV090x_P1_FBERCPT1, 0x00 }, /* P1_FBERCPT1 */ + { STV090x_P1_FBERCPT0, 0x00 }, /* P1_FBERCPT0 */ + { STV090x_P1_FBERERR2, 0x00 }, /* P1_FBERERR2 */ + { STV090x_P1_FBERERR1, 0x00 }, /* P1_FBERERR1 */ + { STV090x_P1_FBERERR0, 0x00 }, /* P1_FBERERR0 */ + { STV090x_P1_FSPYBER, 0x10 }, /* P1_FSPYBER */ +#if 0 + { STV090x_RCCFGH, 0x20 }, /* RCCFGH */ +#endif + { STV090x_TSGENERAL, 0x14 }, /* TSGENERAL */ +#if 0 + { STV090x_TSGENERAL1X, 0x00 }, /* TSGENERAL1X */ +#endif + { STV090x_NBITER_NF4, 0x37 }, /* NBITER_NF4 */ + { STV090x_AGCRF2CFG, 0x13 }, + + { STV090x_NBITER_NF5, 0x29 }, /* NBITER_NF5 */ + { STV090x_NBITER_NF6, 0x37 }, /* NBITER_NF6 */ + { STV090x_NBITER_NF7, 0x33 }, /* NBITER_NF7 */ + { STV090x_NBITER_NF8, 0x31 }, /* NBITER_NF8 */ + { STV090x_NBITER_NF9, 0x2f }, /* NBITER_NF9 */ + { STV090x_NBITER_NF10, 0x39 }, /* NBITER_NF10 */ + { STV090x_NBITER_NF11, 0x3a }, /* NBITER_NF11 */ + { STV090x_NBITER_NF12, 0x29 }, /* NBITER_NF12 */ + { STV090x_NBITER_NF13, 0x37 }, /* NBITER_NF13 */ + { STV090x_P2_AGC2REF, 0x38 }, + { STV090x_NBITER_NF14, 0x33 }, /* NBITER_NF14 */ + { STV090x_NBITER_NF15, 0x2f }, /* NBITER_NF15 */ + { STV090x_NBITER_NF16, 0x39 }, /* NBITER_NF16 */ + { STV090x_NBITER_NF17, 0x3a }, /* NBITER_NF17 */ + { STV090x_NBITERNOERR, 0x04 }, /* NBITERNOERR */ + { STV090x_GAINLLR_NF4, 0x21 }, /* GAINLLR_NF4 */ + { STV090x_GAINLLR_NF5, 0x21 }, /* GAINLLR_NF5 */ + { STV090x_GAINLLR_NF6, 0x20 }, /* GAINLLR_NF6 */ + { STV090x_GAINLLR_NF7, 0x1f }, /* GAINLLR_NF7 */ + { STV090x_GAINLLR_NF8, 0x1e }, /* GAINLLR_NF8 */ + { STV090x_GAINLLR_NF9, 0x1e }, /* GAINLLR_NF9 */ + { STV090x_GAINLLR_NF10, 0x1d }, /* GAINLLR_NF10 */ + { STV090x_GAINLLR_NF11, 0x1b }, /* GAINLLR_NF11 */ + { STV090x_GAINLLR_NF12, 0x20 }, /* GAINLLR_NF12 */ + { STV090x_GAINLLR_NF13, 0x20 }, /* GAINLLR_NF13 */ + { STV090x_GAINLLR_NF14, 0x20 }, /* GAINLLR_NF14 */ + { STV090x_GAINLLR_NF15, 0x20 }, /* GAINLLR_NF15 */ + { STV090x_GAINLLR_NF16, 0x20 }, /* GAINLLR_NF16 */ + { STV090x_GAINLLR_NF17, 0x21 }, /* GAINLLR_NF17 */ +#if 0 + { STV090x_CFGEXT, 0x01 }, /* CFGEXT */ +#endif + { STV090x_GENCFG, 0x1d }, /* GENCFG */ + { STV090x_P2_AGC2REF, 0x38 }, + { STV090x_LDPCERR1, 0x00 }, /* LDPCERR1 */ + { STV090x_LDPCERR0, 0x00 }, /* LDPCERR0 */ + { STV090x_BCHERR, 0x00 }, /* BCHERR */ + { STV090x_TSTRES0, 0x00 }, /* TSTRES0 */ + { STV090x_P2_TSTDISRX, 0x00 }, /* P2_TSTDISRX */ + { STV090x_P1_TSTDISRX, 0x00 }, /* P1_TSTDISRX */ +}; +#endif + +static struct stv090x_reg stv0900_initval[] = { + + { STV090x_OUTCFG, 0x00 }, +#if 0 + { STV090x_MODECFG, 0xff }, +#endif + { STV090x_AGCRF1CFG, 0x11 }, + { STV090x_AGCRF2CFG, 0x13 }, +#if 0 + { STV090x_TSGENERAL1X, 0x14 }, +#endif + { STV090x_TSTTNR2, 0x21 }, + { STV090x_TSTTNR4, 0x21 }, + { STV090x_P2_DISTXCTL, 0x22 }, + { STV090x_P2_F22TX, 0xc0 }, + { STV090x_P2_F22RX, 0xc0 }, + { STV090x_P2_DISRXCTL, 0x00 }, +#if 0 + { STV090x_P2_TNRSTEPS, 0x87 }, + { STV090x_P2_TNRGAIN, 0x09 }, +#endif + { STV090x_P2_DMDCFGMD, 0xF9 }, + { STV090x_P2_DEMOD, 0x08 }, + { STV090x_P2_DMDCFG3, 0xc4 }, + { STV090x_P2_CARFREQ, 0xed }, +#if 0 + { STV090x_P2_TNRCFG2, 0x02 }, + { STV090x_P2_TNRCFG3, 0x02 }, +#endif + { STV090x_P2_LDT, 0xd0 }, + { STV090x_P2_LDT2, 0xb8 }, + { STV090x_P2_TMGCFG, 0xd2 }, + { STV090x_P2_TMGTHRISE, 0x20 }, + { STV090x_P1_TMGCFG, 0xd2 }, + + { STV090x_P2_TMGTHFALL, 0x00 }, + { STV090x_P2_FECSPY, 0x88 }, + { STV090x_P2_FSPYDATA, 0x3a }, + { STV090x_P2_FBERCPT4, 0x00 }, + { STV090x_P2_FSPYBER, 0x10 }, + { STV090x_P2_ERRCTRL1, 0x35 }, + { STV090x_P2_ERRCTRL2, 0xc1 }, + { STV090x_P2_CFRICFG, 0xf8 }, + { STV090x_P2_NOSCFG, 0x1c }, +#if 0 + { STV090x_P2_DMDT0M, 0x20 }, +#endif + { STV090x_P2_CORRELMANT, 0x70 }, + { STV090x_P2_CORRELABS, 0x88 }, +#if 0 + { STV090x_P2_AGC2O, 0x5b }, +#endif + { STV090x_P2_AGC2REF, 0x38 }, + { STV090x_P2_CARCFG, 0xe4 }, + { STV090x_P2_ACLC, 0x1A }, + { STV090x_P2_BCLC, 0x09 }, + { STV090x_P2_CARHDR, 0x08 }, + { STV090x_P2_KREFTMG, 0xc1 }, + { STV090x_P2_SFRUPRATIO, 0xf0 }, + { STV090x_P2_SFRLOWRATIO, 0x70 }, + { STV090x_P2_SFRSTEP, 0x58 }, + { STV090x_P2_TMGCFG2, 0x01 }, + { STV090x_P2_CAR2CFG, 0x26 }, + { STV090x_P2_BCLC2S2Q, 0x86 }, + { STV090x_P2_BCLC2S28, 0x86 }, + { STV090x_P2_SMAPCOEF7, 0x77 }, + { STV090x_P2_SMAPCOEF6, 0x85 }, + { STV090x_P2_SMAPCOEF5, 0x77 }, + { STV090x_P2_TSCFGL, 0x20 }, + { STV090x_P2_DMDCFG2, 0x3b }, + { STV090x_P2_MODCODLST0, 0xff }, + { STV090x_P2_MODCODLST1, 0xff }, + { STV090x_P2_MODCODLST2, 0xff }, + { STV090x_P2_MODCODLST3, 0xff }, + { STV090x_P2_MODCODLST4, 0xff }, + { STV090x_P2_MODCODLST5, 0xff }, + { STV090x_P2_MODCODLST6, 0xff }, + { STV090x_P2_MODCODLST7, 0xcc }, + { STV090x_P2_MODCODLST8, 0xcc }, + { STV090x_P2_MODCODLST9, 0xcc }, + { STV090x_P2_MODCODLSTA, 0xcc }, + { STV090x_P2_MODCODLSTB, 0xcc }, + { STV090x_P2_MODCODLSTC, 0xcc }, + { STV090x_P2_MODCODLSTD, 0xcc }, + { STV090x_P2_MODCODLSTE, 0xcc }, + { STV090x_P2_MODCODLSTF, 0xcf }, + { STV090x_P1_DISTXCTL, 0x22 }, + { STV090x_P1_F22TX, 0xc0 }, + { STV090x_P1_F22RX, 0xc0 }, + { STV090x_P1_DISRXCTL, 0x00 }, +#if 0 + { STV090x_P1_TNRSTEPS, 0x87 }, + { STV090x_P1_TNRGAIN, 0x09 }, +#endif + { STV090x_P1_DMDCFGMD, 0xf9 }, + { STV090x_P1_DEMOD, 0x08 }, + { STV090x_P1_DMDCFG3, 0xc4 }, +#if 0 + { STV090x_P1_DMDT0M, 0x20 }, +#endif + { STV090x_P1_CARFREQ, 0xed }, +#if 0 + { STV090x_P1_TNRCFG2, 0x82 }, + { STV090x_P1_TNRCFG3, 0x02 }, +#endif + { STV090x_P1_LDT, 0xd0 }, + { STV090x_P1_LDT2, 0xb8 }, + { STV090x_P1_TMGCFG, 0xd2 }, + { STV090x_P1_TMGTHRISE, 0x20 }, + { STV090x_P1_TMGTHFALL, 0x00 }, + { STV090x_P1_SFRUPRATIO, 0xf0 }, + { STV090x_P1_SFRLOWRATIO, 0x70 }, + { STV090x_P1_TSCFGL, 0x20 }, + { STV090x_P1_FECSPY, 0x88 }, + { STV090x_P1_FSPYDATA, 0x3a }, + { STV090x_P1_FBERCPT4, 0x00 }, + { STV090x_P1_FSPYBER, 0x10 }, + { STV090x_P1_ERRCTRL1, 0x35 }, + { STV090x_P1_ERRCTRL2, 0xc1 }, + { STV090x_P1_CFRICFG, 0xf8 }, + { STV090x_P1_NOSCFG, 0x1c }, + { STV090x_P1_CORRELMANT, 0x70 }, + { STV090x_P1_CORRELABS, 0x88 }, +#if 0 + { STV090x_P1_AGC2O, 0x5b }, +#endif + { STV090x_P1_AGC2REF, 0x38 }, + { STV090x_P1_CARCFG, 0xe4 }, + { STV090x_P1_ACLC, 0x1A }, + { STV090x_P1_BCLC, 0x09 }, + { STV090x_P1_CARHDR, 0x08 }, + { STV090x_P1_KREFTMG, 0xc1 }, + { STV090x_P1_SFRSTEP, 0x58 }, + { STV090x_P1_TMGCFG2, 0x01 }, + { STV090x_P1_CAR2CFG, 0x26 }, + { STV090x_P1_BCLC2S2Q, 0x86 }, + { STV090x_P1_BCLC2S28, 0x86 }, + { STV090x_P1_SMAPCOEF7, 0x77 }, + { STV090x_P1_SMAPCOEF6, 0x85 }, + { STV090x_P1_SMAPCOEF5, 0x77 }, + { STV090x_P1_DMDCFG2, 0x3b }, + { STV090x_P1_MODCODLST0, 0xff }, + { STV090x_P1_MODCODLST1, 0xff }, + { STV090x_P1_MODCODLST2, 0xff }, + { STV090x_P1_MODCODLST3, 0xff }, + { STV090x_P1_MODCODLST4, 0xff }, + { STV090x_P1_MODCODLST5, 0xff }, + { STV090x_P1_MODCODLST6, 0xff }, + { STV090x_P1_MODCODLST7, 0xcc }, + { STV090x_P1_MODCODLST8, 0xcc }, + { STV090x_P1_MODCODLST9, 0xcc }, + { STV090x_P1_MODCODLSTA, 0xcc }, + { STV090x_P1_MODCODLSTB, 0xcc }, + { STV090x_P1_MODCODLSTC, 0xcc }, + { STV090x_P1_MODCODLSTD, 0xcc }, + { STV090x_P1_MODCODLSTE, 0xcc }, + { STV090x_P1_MODCODLSTF, 0xcf }, + { STV090x_GENCFG, 0x1d }, + { STV090x_NBITER_NF4, 0x37 }, + { STV090x_NBITER_NF5, 0x29 }, + { STV090x_NBITER_NF6, 0x37 }, + { STV090x_NBITER_NF7, 0x33 }, + { STV090x_NBITER_NF8, 0x31 }, + { STV090x_NBITER_NF9, 0x2f }, + { STV090x_NBITER_NF10, 0x39 }, + { STV090x_NBITER_NF11, 0x3a }, + { STV090x_NBITER_NF12, 0x29 }, + { STV090x_NBITER_NF13, 0x37 }, + { STV090x_NBITER_NF14, 0x33 }, + { STV090x_NBITER_NF15, 0x2f }, + { STV090x_NBITER_NF16, 0x39 }, + { STV090x_NBITER_NF17, 0x3a }, + { STV090x_NBITERNOERR, 0x04 }, + { STV090x_GAINLLR_NF4, 0x0C }, + { STV090x_GAINLLR_NF5, 0x0F }, + { STV090x_GAINLLR_NF6, 0x11 }, + { STV090x_GAINLLR_NF7, 0x14 }, + { STV090x_GAINLLR_NF8, 0x17 }, + { STV090x_GAINLLR_NF9, 0x19 }, + { STV090x_GAINLLR_NF10, 0x20 }, + { STV090x_GAINLLR_NF11, 0x21 }, + { STV090x_GAINLLR_NF12, 0x0D }, + { STV090x_GAINLLR_NF13, 0x0F }, + { STV090x_GAINLLR_NF14, 0x13 }, + { STV090x_GAINLLR_NF15, 0x1A }, + { STV090x_GAINLLR_NF16, 0x1F }, + { STV090x_GAINLLR_NF17, 0x21 }, +#if 0 + { STV090x_RCCFGH, 0x20 }, +#endif + { STV090x_P1_FECM, 0x01 }, /* disable DSS modes */ + { STV090x_P2_FECM, 0x01 }, /* disable DSS modes */ + { STV090x_P1_PRVIT, 0x2F }, /* disable PR 6/7 */ + { STV090x_P2_PRVIT, 0x2F }, /* disable PR 6/7 */ +}; + +static struct stv090x_reg stv0903_initval[] = { + { STV090x_OUTCFG, 0x00 }, + { STV090x_AGCRF1CFG, 0x11 }, + { STV090x_STOPCLK1, 0x48 }, + { STV090x_STOPCLK2, 0x14 }, + { STV090x_TSTTNR1, 0x27 }, + { STV090x_TSTTNR2, 0x21 }, + { STV090x_P1_DISTXCTL, 0x22 }, + { STV090x_P1_F22TX, 0xc0 }, + { STV090x_P1_F22RX, 0xc0 }, + { STV090x_P1_DISRXCTL, 0x00 }, +#if 0 + { STV090x_TNRSTEPS, 0x87 }, + { STV090x_TNRGAIN, 0x09 }, +#endif + { STV090x_P1_DMDCFGMD, 0xF9 }, + { STV090x_P1_DEMOD, 0x08 }, + { STV090x_P1_DMDCFG3, 0xc4 }, + { STV090x_P1_CARFREQ, 0xed }, + { STV090x_P1_TNRCFG2, 0x82 }, +#if 0 + { STV090x_P1_TNRCFG3, 0x03 }, +#endif + { STV090x_P1_LDT, 0xd0 }, + { STV090x_P1_LDT2, 0xb8 }, + { STV090x_P1_TMGCFG, 0xd2 }, + { STV090x_P1_TMGTHRISE, 0x20 }, + { STV090x_P1_TMGTHFALL, 0x00 }, + { STV090x_P1_SFRUPRATIO, 0xf0 }, + { STV090x_P1_SFRLOWRATIO, 0x70 }, + { STV090x_P1_TSCFGL, 0x20 }, + { STV090x_P1_FECSPY, 0x88 }, + { STV090x_P1_FSPYDATA, 0x3a }, + { STV090x_P1_FBERCPT4, 0x00 }, + { STV090x_P1_FSPYBER, 0x10 }, + { STV090x_P1_ERRCTRL1, 0x35 }, + { STV090x_P1_ERRCTRL2, 0xc1 }, + { STV090x_P1_CFRICFG, 0xf8 }, + { STV090x_P1_NOSCFG, 0x1c }, +#if 0 + { STV090x_P1_DMDT0M, 0x20 }, +#endif + { STV090x_P1_CORRELMANT, 0x70 }, + { STV090x_P1_CORRELABS, 0x88 }, +#if 0 + { STV090x_P1_AGC2O, 0x5b }, +#endif + { STV090x_P1_AGC2REF, 0x38 } , + { STV090x_P1_CARCFG, 0xe4 }, + { STV090x_P1_ACLC, 0x1A }, + { STV090x_P1_BCLC, 0x09 } , + { STV090x_P1_CARHDR, 0x08 }, + { STV090x_P1_KREFTMG, 0xc1 }, + { STV090x_P1_SFRSTEP, 0x58 }, + { STV090x_P1_TMGCFG2, 0x01 }, + { STV090x_P1_CAR2CFG, 0x26 }, + { STV090x_P1_BCLC2S2Q, 0x86 }, + { STV090x_P1_BCLC2S28, 0x86 }, + { STV090x_P1_SMAPCOEF7, 0x77 }, + { STV090x_P1_SMAPCOEF6, 0x85 }, + { STV090x_P1_SMAPCOEF5, 0x77 }, + { STV090x_P1_DMDCFG2, 0x3b }, + { STV090x_P1_MODCODLST0, 0xff }, + { STV090x_P1_MODCODLST1, 0xff }, + { STV090x_P1_MODCODLST2, 0xff }, + { STV090x_P1_MODCODLST3, 0xff }, + { STV090x_P1_MODCODLST4, 0xff }, + { STV090x_P1_MODCODLST5, 0xff }, + { STV090x_P1_MODCODLST6, 0xff }, + { STV090x_P1_MODCODLST7, 0xcc }, + { STV090x_P1_MODCODLST8, 0xcc }, + { STV090x_P1_MODCODLST9, 0xcc }, + { STV090x_P1_MODCODLSTA, 0xcc }, + { STV090x_P1_MODCODLSTB, 0xcc }, + { STV090x_P1_MODCODLSTC, 0xcc }, + { STV090x_P1_MODCODLSTD, 0xcc }, + { STV090x_P1_MODCODLSTE, 0xcc }, + { STV090x_P1_MODCODLSTF, 0xcf }, + { STV090x_GENCFG, 0x1c }, + { STV090x_NBITER_NF4, 0x37 }, + { STV090x_NBITER_NF5, 0x29 }, + { STV090x_NBITER_NF6, 0x37 }, + { STV090x_NBITER_NF7, 0x33 }, + { STV090x_NBITER_NF8, 0x31 }, + { STV090x_NBITER_NF9, 0x2f }, + { STV090x_NBITER_NF10, 0x39 }, + { STV090x_NBITER_NF11, 0x3a }, + { STV090x_NBITER_NF12, 0x29 }, + { STV090x_NBITER_NF13, 0x37 }, + { STV090x_NBITER_NF14, 0x33 }, + { STV090x_NBITER_NF15, 0x2f }, + { STV090x_NBITER_NF16, 0x39 }, + { STV090x_NBITER_NF17, 0x3a }, + { STV090x_NBITERNOERR, 0x04 }, + { STV090x_GAINLLR_NF4, 0x0C }, + { STV090x_GAINLLR_NF5, 0x0F }, + { STV090x_GAINLLR_NF6, 0x11 }, + { STV090x_GAINLLR_NF7, 0x14 }, + { STV090x_GAINLLR_NF8, 0x17 }, + { STV090x_GAINLLR_NF9, 0x19 }, + { STV090x_GAINLLR_NF10, 0x20 }, + { STV090x_GAINLLR_NF11, 0x21 }, + { STV090x_GAINLLR_NF12, 0x0D }, + { STV090x_GAINLLR_NF13, 0x0F }, + { STV090x_GAINLLR_NF14, 0x13 }, + { STV090x_GAINLLR_NF15, 0x1A }, + { STV090x_GAINLLR_NF16, 0x1F }, + { STV090x_GAINLLR_NF17, 0x21 }, +#if 0 + { STV090x_RCCFGH, 0x20 }, +#endif + { STV090x_P1_FECM, 0x01 }, /*disable the DSS mode */ + { STV090x_P1_PRVIT, 0x2f } /*disable puncture rate 6/7*/ +}; + +static struct stv090x_reg stv0900_cut20_val[] = { + + { STV090x_P2_DMDCFG3, 0xe8 }, +#if 0 + { STV090x_P2_DMDCFG4, 0x10 }, +#endif + { STV090x_P2_CARFREQ, 0x38 }, + { STV090x_P2_CARHDR, 0x20 }, + { STV090x_P2_KREFTMG, 0x5a }, + { STV090x_P2_SMAPCOEF7, 0x06 }, + { STV090x_P2_SMAPCOEF6, 0x00 }, + { STV090x_P2_SMAPCOEF5, 0x04 }, + { STV090x_P2_NOSCFG, 0x0c }, + { STV090x_P1_DMDCFG3, 0xe8 }, +#if 0 + { STV090x_P1_DMDCFG4, 0x10 }, +#endif + { STV090x_P1_CARFREQ, 0x38 }, + { STV090x_P1_CARHDR, 0x20 }, + { STV090x_P1_KREFTMG, 0x5a }, + { STV090x_P1_SMAPCOEF7, 0x06 }, + { STV090x_P1_SMAPCOEF6, 0x00 }, + { STV090x_P1_SMAPCOEF5, 0x04 }, + { STV090x_P1_NOSCFG, 0x0c }, + { STV090x_GAINLLR_NF4, 0x21 }, + { STV090x_GAINLLR_NF5, 0x21 }, + { STV090x_GAINLLR_NF6, 0x20 }, + { STV090x_GAINLLR_NF7, 0x1F }, + { STV090x_GAINLLR_NF8, 0x1E }, + { STV090x_GAINLLR_NF9, 0x1E }, + { STV090x_GAINLLR_NF10, 0x1D }, + { STV090x_GAINLLR_NF11, 0x1B }, + { STV090x_GAINLLR_NF12, 0x20 }, + { STV090x_GAINLLR_NF13, 0x20 }, + { STV090x_GAINLLR_NF14, 0x20 }, + { STV090x_GAINLLR_NF15, 0x20 }, + { STV090x_GAINLLR_NF16, 0x20 }, + { STV090x_GAINLLR_NF17, 0x21 }, +}; + +static struct stv090x_reg stv0903_cut20_val[] = { + { STV090x_P1_DMDCFG3, 0xe8 }, +#if 0 + { STV090x_P1_DMDCFG4, 0x10 }, +#endif + { STV090x_P1_CARFREQ, 0x38 }, + { STV090x_P1_CARHDR, 0x20 }, + { STV090x_P1_KREFTMG, 0x5a }, + { STV090x_P1_SMAPCOEF7, 0x06 }, + { STV090x_P1_SMAPCOEF6, 0x00 }, + { STV090x_P1_SMAPCOEF5, 0x04 }, + { STV090x_P1_NOSCFG, 0x0c }, + { STV090x_GAINLLR_NF4, 0x21 }, + { STV090x_GAINLLR_NF5, 0x21 }, + { STV090x_GAINLLR_NF6, 0x20 }, + { STV090x_GAINLLR_NF7, 0x1F }, + { STV090x_GAINLLR_NF8, 0x1E }, + { STV090x_GAINLLR_NF9, 0x1E }, + { STV090x_GAINLLR_NF10, 0x1D }, + { STV090x_GAINLLR_NF11, 0x1B }, + { STV090x_GAINLLR_NF12, 0x20 }, + { STV090x_GAINLLR_NF13, 0x20 }, + { STV090x_GAINLLR_NF14, 0x20 }, + { STV090x_GAINLLR_NF15, 0x20 }, + { STV090x_GAINLLR_NF16, 0x20 }, + { STV090x_GAINLLR_NF17, 0x21 } +}; + +/* Cut 1.x Long Frame Tracking CR loop */ +static struct stv090x_long_frame_crloop stv090x_s2_crl[] = { + /* MODCOD 2MPon 2MPoff 5MPon 5MPoff 10MPon 10MPoff 20MPon 20MPoff 30MPon 30MPoff */ + { STV090x_QPSK_12, 0x1c, 0x0d, 0x1b, 0x2c, 0x3a, 0x1c, 0x2a, 0x3b, 0x2a, 0x1b }, + { STV090x_QPSK_35, 0x2c, 0x0d, 0x2b, 0x2c, 0x3a, 0x0c, 0x3a, 0x2b, 0x2a, 0x0b }, + { STV090x_QPSK_23, 0x2c, 0x0d, 0x2b, 0x2c, 0x0b, 0x0c, 0x3a, 0x1b, 0x2a, 0x3a }, + { STV090x_QPSK_34, 0x3c, 0x0d, 0x3b, 0x1c, 0x0b, 0x3b, 0x3a, 0x0b, 0x2a, 0x3a }, + { STV090x_QPSK_45, 0x3c, 0x0d, 0x3b, 0x1c, 0x0b, 0x3b, 0x3a, 0x0b, 0x2a, 0x3a }, + { STV090x_QPSK_56, 0x0d, 0x0d, 0x3b, 0x1c, 0x0b, 0x3b, 0x3a, 0x0b, 0x2a, 0x3a }, + { STV090x_QPSK_89, 0x0d, 0x0d, 0x3b, 0x1c, 0x1b, 0x3b, 0x3a, 0x0b, 0x2a, 0x3a }, + { STV090x_QPSK_910, 0x1d, 0x0d, 0x3b, 0x1c, 0x1b, 0x3b, 0x3a, 0x0b, 0x2a, 0x3a }, + { STV090x_8PSK_35, 0x29, 0x3b, 0x09, 0x2b, 0x38, 0x0b, 0x18, 0x1a, 0x08, 0x0a }, + { STV090x_8PSK_23, 0x0a, 0x3b, 0x29, 0x2b, 0x19, 0x0b, 0x38, 0x1a, 0x18, 0x0a }, + { STV090x_8PSK_34, 0x3a, 0x3b, 0x2a, 0x2b, 0x39, 0x0b, 0x19, 0x1a, 0x38, 0x0a }, + { STV090x_8PSK_56, 0x1b, 0x3b, 0x0b, 0x2b, 0x1a, 0x0b, 0x39, 0x1a, 0x19, 0x0a }, + { STV090x_8PSK_89, 0x3b, 0x3b, 0x0b, 0x2b, 0x2a, 0x0b, 0x39, 0x1a, 0x29, 0x39 }, + { STV090x_8PSK_910, 0x3b, 0x3b, 0x0b, 0x2b, 0x2a, 0x0b, 0x39, 0x1a, 0x29, 0x39 } +}; + +/* Cut 2.0 Long Frame Tracking CR loop */ +static struct stv090x_long_frame_crloop stv090x_s2_crl_cut20[] = { + /* MODCOD 2MPon 2MPoff 5MPon 5MPoff 10MPon 10MPoff 20MPon 20MPoff 30MPon 30MPoff */ + { STV090x_QPSK_12, 0x1f, 0x3f, 0x1e, 0x3f, 0x3d, 0x1f, 0x3d, 0x3e, 0x3d, 0x1e }, + { STV090x_QPSK_35, 0x2f, 0x3f, 0x2e, 0x2f, 0x3d, 0x0f, 0x0e, 0x2e, 0x3d, 0x0e }, + { STV090x_QPSK_23, 0x2f, 0x3f, 0x2e, 0x2f, 0x0e, 0x0f, 0x0e, 0x1e, 0x3d, 0x3d }, + { STV090x_QPSK_34, 0x3f, 0x3f, 0x3e, 0x1f, 0x0e, 0x3e, 0x0e, 0x1e, 0x3d, 0x3d }, + { STV090x_QPSK_45, 0x3f, 0x3f, 0x3e, 0x1f, 0x0e, 0x3e, 0x0e, 0x1e, 0x3d, 0x3d }, + { STV090x_QPSK_56, 0x3f, 0x3f, 0x3e, 0x1f, 0x0e, 0x3e, 0x0e, 0x1e, 0x3d, 0x3d }, + { STV090x_QPSK_89, 0x3f, 0x3f, 0x3e, 0x1f, 0x1e, 0x3e, 0x0e, 0x1e, 0x3d, 0x3d }, + { STV090x_QPSK_910, 0x3f, 0x3f, 0x3e, 0x1f, 0x1e, 0x3e, 0x0e, 0x1e, 0x3d, 0x3d }, + { STV090x_8PSK_35, 0x3c, 0x3e, 0x1c, 0x2e, 0x0c, 0x1e, 0x2b, 0x2d, 0x1b, 0x1d }, + { STV090x_8PSK_23, 0x1d, 0x3e, 0x3c, 0x2e, 0x2c, 0x1e, 0x0c, 0x2d, 0x2b, 0x1d }, + { STV090x_8PSK_34, 0x0e, 0x3e, 0x3d, 0x2e, 0x0d, 0x1e, 0x2c, 0x2d, 0x0c, 0x1d }, + { STV090x_8PSK_56, 0x2e, 0x3e, 0x1e, 0x2e, 0x2d, 0x1e, 0x3c, 0x2d, 0x2c, 0x1d }, + { STV090x_8PSK_89, 0x3e, 0x3e, 0x1e, 0x2e, 0x3d, 0x1e, 0x0d, 0x2d, 0x3c, 0x1d }, + { STV090x_8PSK_910, 0x3e, 0x3e, 0x1e, 0x2e, 0x3d, 0x1e, 0x1d, 0x2d, 0x0d, 0x1d } +}; + +#if 0 +/* Cut 3.0 Long Frame Tracking CR loop */ +static struct stv090x_long_frame_crloop stv090x_s2_crl_cut30[] = { + /* MODCOD 2MPon 2MPoff 5MPon 5MPoff 10MPon 10MPoff 20MPon 20MPoff 30MPon 30MPoff */ + { STV090x_QPSK_12, 0x3c, 0x2c, 0x0c, 0x2c, 0x1b, 0x2c, 0x1b, 0x1c, 0x0b, 0x3b }, + { STV090x_QPSK_35, 0x0d, 0x0d, 0x0c, 0x0d, 0x1b, 0x3c, 0x1b, 0x1c, 0x0b, 0x3b }, + { STV090x_QPSK_23, 0x1d, 0x0d, 0x0c, 0x1d, 0x2b, 0x3c, 0x1b, 0x1c, 0x0b, 0x3b }, + { STV090x_QPSK_34, 0x1d, 0x1d, 0x0c, 0x1d, 0x2b, 0x3c, 0x1b, 0x1c, 0x0b, 0x3b }, + { STV090x_QPSK_45, 0x2d, 0x1d, 0x1c, 0x1d, 0x2b, 0x3c, 0x2b, 0x0c, 0x1b, 0x3b }, + { STV090x_QPSK_56, 0x2d, 0x1d, 0x1c, 0x1d, 0x2b, 0x3c, 0x2b, 0x0c, 0x1b, 0x3b }, + { STV090x_QPSK_89, 0x3d, 0x2d, 0x1c, 0x1d, 0x3b, 0x3c, 0x2b, 0x0c, 0x1b, 0x3b }, + { STV090x_QPSK_910, 0x3d, 0x2d, 0x1c, 0x1d, 0x3b, 0x3c, 0x2b, 0x0c, 0x1b, 0x3b }, + { STV090x_8PSK_35, 0x39, 0x29, 0x39, 0x19, 0x19, 0x19, 0x19, 0x19, 0x09, 0x19 }, + { STV090x_8PSK_23, 0x2a, 0x39, 0x1a, 0x0a, 0x39, 0x0a, 0x29, 0x39, 0x29, 0x0a }, + { STV090x_8PSK_34, 0x2b, 0x3a, 0x1b, 0x1b, 0x3a, 0x1b, 0x1a, 0x0b, 0x1a, 0x3a }, + { STV090x_8PSK_56, 0x0c, 0x1b, 0x3b, 0x3b, 0x1b, 0x3b, 0x3a, 0x3b, 0x3a, 0x1b }, + { STV090x_8PSK_89, 0x0d, 0x3c, 0x2c, 0x2c, 0x2b, 0x0c, 0x0b, 0x3b, 0x0b, 0x1b }, + { STV090x_8PSK_910, 0x0d, 0x0d, 0x2c, 0x3c, 0x3b, 0x1c, 0x0b, 0x3b, 0x0b, 0x1b } +}; +#endif + +/* Cut 2.0 Long Frame Tracking CR Loop */ +static struct stv090x_long_frame_crloop stv090x_s2_apsk_crl_cut20[] = { + /* MODCOD 2MPon 2MPoff 5MPon 5MPoff 10MPon 10MPoff 20MPon 20MPoff 30MPon 30MPoff */ + { STV090x_16APSK_23, 0x0c, 0x0c, 0x0c, 0x0c, 0x1d, 0x0c, 0x3c, 0x0c, 0x2c, 0x0c }, + { STV090x_16APSK_34, 0x0c, 0x0c, 0x0c, 0x0c, 0x0e, 0x0c, 0x2d, 0x0c, 0x1d, 0x0c }, + { STV090x_16APSK_45, 0x0c, 0x0c, 0x0c, 0x0c, 0x1e, 0x0c, 0x3d, 0x0c, 0x2d, 0x0c }, + { STV090x_16APSK_56, 0x0c, 0x0c, 0x0c, 0x0c, 0x1e, 0x0c, 0x3d, 0x0c, 0x2d, 0x0c }, + { STV090x_16APSK_89, 0x0c, 0x0c, 0x0c, 0x0c, 0x2e, 0x0c, 0x0e, 0x0c, 0x3d, 0x0c }, + { STV090x_16APSK_910, 0x0c, 0x0c, 0x0c, 0x0c, 0x2e, 0x0c, 0x0e, 0x0c, 0x3d, 0x0c }, + { STV090x_32APSK_34, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c }, + { STV090x_32APSK_45, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c }, + { STV090x_32APSK_56, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c }, + { STV090x_32APSK_89, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c }, + { STV090x_32APSK_910, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c } +}; + +#if 0 +/* Cut 3.0 Long Frame Tracking CR Loop */ +static struct stv090x_long_frame_crloop stv090x_s2_apsk_crl_cut30[] = { + /* MODCOD 2MPon 2MPoff 5MPon 5MPoff 10MPon 10MPoff 20MPon 20MPoff 30MPon 30MPoff */ + { STV090x_16APSK_23, 0x0a, 0x0a, 0x0a, 0x0a, 0x1a, 0x0a, 0x3a, 0x0a, 0x2a, 0x0a }, + { STV090x_16APSK_34, 0x0a, 0x0a, 0x0a, 0x0a, 0x0b, 0x0a, 0x3b, 0x0a, 0x1b, 0x0a }, + { STV090x_16APSK_45, 0x0a, 0x0a, 0x0a, 0x0a, 0x1b, 0x0a, 0x3b, 0x0a, 0x2b, 0x0a }, + { STV090x_16APSK_56, 0x0a, 0x0a, 0x0a, 0x0a, 0x1b, 0x0a, 0x3b, 0x0a, 0x2b, 0x0a }, + { STV090x_16APSK_89, 0x0a, 0x0a, 0x0a, 0x0a, 0x2b, 0x0a, 0x0c, 0x0a, 0x3b, 0x0a }, + { STV090x_16APSK_910, 0x0a, 0x0a, 0x0a, 0x0a, 0x2b, 0x0a, 0x0c, 0x0a, 0x3b, 0x0a }, + { STV090x_32APSK_34, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a }, + { STV090x_32APSK_45, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a }, + { STV090x_32APSK_56, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a }, + { STV090x_32APSK_89, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a }, + { STV090x_32APSK_910, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a } +}; +#endif + +static struct stv090x_long_frame_crloop stv090x_s2_lowqpsk_crl_cut20[] = { + /* MODCOD 2MPon 2MPoff 5MPon 5MPoff 10MPon 10MPoff 20MPon 20MPoff 30MPon 30MPoff */ + { STV090x_QPSK_14, 0x0f, 0x3f, 0x0e, 0x3f, 0x2d, 0x2f, 0x2d, 0x1f, 0x3d, 0x3e }, + { STV090x_QPSK_13, 0x0f, 0x3f, 0x0e, 0x3f, 0x2d, 0x2f, 0x3d, 0x0f, 0x3d, 0x2e }, + { STV090x_QPSK_25, 0x1f, 0x3f, 0x1e, 0x3f, 0x3d, 0x1f, 0x3d, 0x3e, 0x3d, 0x2e } +}; + +#if 0 +static struct stv090x_long_frame_crloop stv090x_s2_lowqpsk_crl_cut30[] = { + /* MODCOD 2MPon 2MPoff 5MPon 5MPoff 10MPon 10MPoff 20MPon 20MPoff 30MPon 30MPoff */ + { STV090x_QPSK_14, 0x0c, 0x3c, 0x0b, 0x3c, 0x2a, 0x2c, 0x2a, 0x1c, 0x3a, 0x3b }, + { STV090x_QPSK_13, 0x0c, 0x3c, 0x0b, 0x3c, 0x2a, 0x2c, 0x3a, 0x0c, 0x3a, 0x2b }, + { STV090x_QPSK_25, 0x1c, 0x3c, 0x1b, 0x3c, 0x3a, 0x1c, 0x3a, 0x3b, 0x3a, 0x2b } +}; +#endif + +/* Cut 1.2 & 2.0 Short Frame Tracking CR Loop */ +static struct stv090x_short_frame_crloop stv090x_s2_short_crl[] = { + /* MODCOD 2M_cut1.2 2M_cut2.0 5M_cut1.2 5M_cut2.0 10M_cut1.2 10M_cut2.0 20M_cut1.2 20M_cut2.0 30M_cut1.2 30M_cut2.0 */ + { STV090x_QPSK, 0x3c, 0x2f, 0x2b, 0x2e, 0x0b, 0x0e, 0x3a, 0x0e, 0x2a, 0x3d }, + { STV090x_8PSK, 0x0b, 0x3e, 0x2a, 0x0e, 0x0a, 0x2d, 0x19, 0x0d, 0x09, 0x3c }, + { STV090x_16APSK, 0x1b, 0x1e, 0x1b, 0x1e, 0x1b, 0x1e, 0x3a, 0x3d, 0x2a, 0x2d }, + { STV090x_32APSK, 0x1b, 0x1e, 0x1b, 0x1e, 0x1b, 0x1e, 0x3a, 0x3d, 0x2a, 0x2d } +}; + +#if 0 +static struct stv090x_short_frame_vsmod_crloop stv090x_s2_short_crl_cut30[] = { + /* MODCOD 2M 5M 10M 20M 30M */ + { STV090x_QPSK, 0x2C, 0x2B, 0x0B, 0x0B, 0x3A }, + { STV090x_8PSK, 0x3B, 0x0B, 0x2A, 0x0A, 0x39 }, + { STV090x_16APSK, 0x1B, 0x1B, 0x1B, 0x3A, 0x2A }, + { STV090x_32APSK, 0x1B, 0x1B, 0x1B, 0x3A, 0x2A } +}; +#endif + +static inline s32 comp2(s32 __x, s32 __width) +{ + if (__width == 32) + return __x; + else + return (__x >= (1 << (__width - 1))) ? (__x - (1 << __width)) : __x; +} + +static int stv090x_read_reg(struct stv090x_state *state, unsigned int reg) +{ + const struct stv090x_config *config = state->config; + int ret; + + u8 b0[] = { reg >> 8, reg & 0xff }; + u8 buf; + + struct i2c_msg msg[] = { + { .addr = config->address, .flags = 0, .buf = b0, .len = 2 }, + { .addr = config->address, .flags = I2C_M_RD, .buf = &buf, .len = 1 } + }; + + ret = i2c_transfer(state->i2c, msg, 2); + if (ret != 2) { + if (ret != -ERESTARTSYS) + dprintk(FE_ERROR, 1, + "Read error, Reg=[0x%02x], Status=%d", + reg, ret); + + return ret < 0 ? ret : -EREMOTEIO; + } + if (unlikely(*state->verbose >= FE_DEBUGREG)) + dprintk(FE_ERROR, 1, "Reg=[0x%02x], data=%02x", + reg, buf); + + return (unsigned int) buf; +} + +static int stv090x_write_regs(struct stv090x_state *state, unsigned int reg, u8 *data, u32 count) +{ + const struct stv090x_config *config = state->config; + int ret; + u8 buf[2 + count]; + struct i2c_msg i2c_msg = { .addr = config->address, .flags = 0, .buf = buf, .len = 2 + count }; + + buf[0] = reg >> 8; + buf[1] = reg & 0xff; + memcpy(&buf[2], data, count); + + if (unlikely(*state->verbose >= FE_DEBUGREG)) { + int i; + + printk(KERN_DEBUG "%s [0x%04x]:", __func__, reg); + for (i = 0; i < count; i++) + printk(" %02x", data[i]); + printk("\n"); + } + + ret = i2c_transfer(state->i2c, &i2c_msg, 1); + if (ret != 1) { + if (ret != -ERESTARTSYS) + dprintk(FE_ERROR, 1, "Reg=[0x%04x], Data=[0x%02x ...], Count=%u, Status=%d", + reg, data[0], count, ret); + return ret < 0 ? ret : -EREMOTEIO; + } + + return 0; +} + +static int stv090x_write_reg(struct stv090x_state *state, unsigned int reg, u8 data) +{ + return stv090x_write_regs(state, reg, &data, 1); +} + +static int stv090x_i2c_gate_ctrl(struct dvb_frontend *fe, int enable) +{ + struct stv090x_state *state = fe->demodulator_priv; + u32 reg; + + reg = STV090x_READ_DEMOD(state, I2CRPT); + + if (enable) { + STV090x_SETFIELD_Px(reg, I2CT_ON_FIELD, 1); + if (STV090x_WRITE_DEMOD(state, I2CRPT, reg) < 0) + goto err; + + } else { + STV090x_SETFIELD_Px(reg, I2CT_ON_FIELD, 0); + if ((STV090x_WRITE_DEMOD(state, I2CRPT, reg)) < 0) + goto err; + } + return 0; +err: + dprintk(FE_ERROR, 1, "I/O error"); + return -1; +} + +static void stv090x_get_lock_tmg(struct stv090x_state *state) +{ + switch (state->algo) { + case STV090x_BLIND_SEARCH: + dprintk(FE_DEBUG, 1, "Blind Search"); + if (state->srate <= 1500000) { /*10Msps< SR <=15Msps*/ + state->DemodTimeout = 1500; + state->FecTimeout = 400; + } else if (state->srate <= 5000000) { /*10Msps< SR <=15Msps*/ + state->DemodTimeout = 1000; + state->FecTimeout = 300; + } else { /*SR >20Msps*/ + state->DemodTimeout = 700; + state->FecTimeout = 100; + } + break; + + case STV090x_COLD_SEARCH: + case STV090x_WARM_SEARCH: + default: + dprintk(FE_DEBUG, 1, "Normal Search"); + if (state->srate <= 1000000) { /*SR <=1Msps*/ + state->DemodTimeout = 4500; + state->FecTimeout = 1700; + } else if (state->srate <= 2000000) { /*1Msps < SR <= 2Msps */ + state->DemodTimeout = 2500; + state->FecTimeout = 1100; + } else if (state->srate <= 5000000) { /*2Msps < SR <= 5Msps */ + state->DemodTimeout = 1000; + state->FecTimeout = 550; + } else if (state->srate <= 10000000) { /*5Msps < SR <= 10Msps */ + state->DemodTimeout = 700; + state->FecTimeout = 250; + } else if (state->srate <= 20000000) { /*10Msps < SR <= 20Msps */ + state->DemodTimeout = 400; + state->FecTimeout = 130; + } else { /*SR >20Msps*/ + state->DemodTimeout = 300; + state->FecTimeout = 100; + } + break; + } + + if (state->algo == STV090x_WARM_SEARCH) + state->DemodTimeout /= 2; +} + +static int stv090x_set_srate(struct stv090x_state *state, u32 srate) +{ + u32 sym; + + if (srate > 6000000) { + sym = (srate / 1000) * 65536; + sym /= (state->mclk / 1000); + } else { + sym = (srate / 100) * 65536; + sym /= (state->mclk / 100); + } + + if (STV090x_WRITE_DEMOD(state, SFRINIT1, (sym >> 8) & 0xff) < 0) /* MSB */ + goto err; + if (STV090x_WRITE_DEMOD(state, SFRINIT0, (sym & 0xff)) < 0) /* LSB */ + goto err; + return 0; +err: + dprintk(FE_ERROR, 1, "I/O error"); + return -1; +} + +static int stv090x_set_max_srate(struct stv090x_state *state, u32 clk, u32 srate) +{ + u32 sym; + + srate = 105 * (srate / 100); + if (srate > 6000000) { + sym = (srate / 1000) * 65536; + sym /= (clk / 1000); + } else { + sym = (srate / 100) * 65536; + sym /= (clk / 100); + } + if (STV090x_WRITE_DEMOD(state, SFRUP1, (sym >> 8) & 0x7f) < 0) /* MSB */ + goto err; + if (STV090x_WRITE_DEMOD(state, SFRUP0, sym & 0xff) < 0) /* LSB */ + goto err; + return 0; +err: + dprintk(FE_ERROR, 1, "I/O error"); + return -1; +} + +static int stv090x_set_min_srate(struct stv090x_state *state, u32 clk, u32 srate) +{ + u32 sym; + + srate = 95 * (srate / 100); + if (srate > 6000000) { + sym = (srate / 1000) * 65536; + sym /= (clk / 1000); + } else { + sym = (srate / 100) * 65536; + sym /= (clk / 100); + } + if (STV090x_WRITE_DEMOD(state, SFRLOW1, ((sym >> 8) & 0xff)) < 0) /* MSB */ + goto err; + if (STV090x_WRITE_DEMOD(state, SFRLOW0, (sym & 0xff)) < 0) /* LSB */ + goto err; + return 0; +err: + dprintk(FE_ERROR, 1, "I/O error"); + return -1; +} + +static u32 stv090x_car_width(u32 srate, u32 rolloff) +{ + return srate + (srate * rolloff) / 100; +} + +static int stv090x_set_vit_thacq(struct stv090x_state *state) +{ + if (STV090x_WRITE_DEMOD(state, VTH12, 0x96) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, VTH23, 0x64) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, VTH34, 0x36) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, VTH56, 0x23) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, VTH67, 0x1e) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, VTH78, 0x19) < 0) + goto err; + return 0; +err: + dprintk(FE_ERROR, 1, "I/O error"); + return -1; +} + +static int stv090x_set_vit_thtracq(struct stv090x_state *state) +{ + if (STV090x_WRITE_DEMOD(state, VTH12, 0xd0) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, VTH23, 0x7d) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, VTH34, 0x53) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, VTH56, 0x2f) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, VTH67, 0x24) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, VTH78, 0x1f) < 0) + goto err; + return 0; +err: + dprintk(FE_ERROR, 1, "I/O error"); + return -1; +} + +static int stv090x_set_viterbi(struct stv090x_state *state) +{ + switch (state->search_mode) { + case STV090x_SEARCH_AUTO: + if (STV090x_WRITE_DEMOD(state, FECM, 0x10) < 0) /* DVB-S and DVB-S2 */ + goto err; + if (STV090x_WRITE_DEMOD(state, PRVIT, 0x3f) < 0) /* all puncture rate */ + goto err; + break; + case STV090x_SEARCH_DVBS1: + if (STV090x_WRITE_DEMOD(state, FECM, 0x00) < 0) /* disable DSS */ + goto err; + switch (state->fec) { + case STV090x_PR12: + if (STV090x_WRITE_DEMOD(state, PRVIT, 0x01) < 0) + goto err; + break; + + case STV090x_PR23: + if (STV090x_WRITE_DEMOD(state, PRVIT, 0x02) < 0) + goto err; + break; + + case STV090x_PR34: + if (STV090x_WRITE_DEMOD(state, PRVIT, 0x04) < 0) + goto err; + break; + + case STV090x_PR56: + if (STV090x_WRITE_DEMOD(state, PRVIT, 0x08) < 0) + goto err; + break; + + case STV090x_PR78: + if (STV090x_WRITE_DEMOD(state, PRVIT, 0x20) < 0) + goto err; + break; + + default: + if (STV090x_WRITE_DEMOD(state, PRVIT, 0x2f) < 0) /* all */ + goto err; + break; + } + break; + case STV090x_SEARCH_DSS: + if (STV090x_WRITE_DEMOD(state, FECM, 0x80) < 0) + goto err; + switch (state->fec) { + case STV090x_PR12: + if (STV090x_WRITE_DEMOD(state, PRVIT, 0x01) < 0) + goto err; + break; + + case STV090x_PR23: + if (STV090x_WRITE_DEMOD(state, PRVIT, 0x02) < 0) + goto err; + break; + + case STV090x_PR67: + if (STV090x_WRITE_DEMOD(state, PRVIT, 0x10) < 0) + goto err; + break; + + default: + if (STV090x_WRITE_DEMOD(state, PRVIT, 0x13) < 0) /* 1/2, 2/3, 6/7 */ + goto err; + break; + } + break; + default: + break; + } + return 0; +err: + dprintk(FE_ERROR, 1, "I/O error"); + return -1; +} + +static int stv090x_stop_modcod(struct stv090x_state *state) +{ + if (STV090x_WRITE_DEMOD(state, MODCODLST0, 0xff) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, MODCODLST1, 0xff) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, MODCODLST2, 0xff) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, MODCODLST3, 0xff) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, MODCODLST4, 0xff) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, MODCODLST5, 0xff) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, MODCODLST6, 0xff) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, MODCODLST7, 0xff) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, MODCODLST8, 0xff) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, MODCODLST9, 0xff) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, MODCODLSTA, 0xff) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, MODCODLSTB, 0xff) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, MODCODLSTC, 0xff) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, MODCODLSTD, 0xff) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, MODCODLSTE, 0xff) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, MODCODLSTF, 0xff) < 0) + goto err; + return 0; +err: + dprintk(FE_ERROR, 1, "I/O error"); + return -1; +} + +static int stv090x_activate_modcod(struct stv090x_state *state) +{ + u32 matype, modcod, f_mod, index; + + if (state->dev_ver <= 0x11) { + msleep(5); + modcod = STV090x_READ_DEMOD(state, PLHMODCOD); + matype = modcod & 0x03; + modcod = (modcod & 0x7f) >> 2; + index = STV090x_ADDR_OFFST(state, MODCODLSTF) - (modcod / 2); + + switch (matype) { + default: + case 0: + f_mod = 14; + break; + case 1: + f_mod = 13; + break; + case 2: + f_mod = 11; + break; + case 3: + f_mod = 7; + break; + } + if (matype <= 1) { + if (modcod % 2) { + if (stv090x_write_reg(state, index, 0xf0 | f_mod) < 0) + goto err; + } else { + if (stv090x_write_reg(state, index, (f_mod << 4) | 0x0f) < 0) + goto err; + } + } + } else if (state->dev_ver >= 0x12) { + if (STV090x_WRITE_DEMOD(state, MODCODLST0, 0xff) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, MODCODLST1, 0xfc) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, MODCODLST2, 0xcc) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, MODCODLST3, 0xcc) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, MODCODLST4, 0xcc) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, MODCODLST5, 0xcc) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, MODCODLST6, 0xcc) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, MODCODLST7, 0xcc) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, MODCODLST8, 0xcc) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, MODCODLST9, 0xcc) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, MODCODLSTA, 0xcc) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, MODCODLSTB, 0xcc) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, MODCODLSTC, 0xcc) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, MODCODLSTD, 0xcc) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, MODCODLSTE, 0xcc) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, MODCODLSTF, 0xcf) < 0) + goto err; + } + return 0; +err: + dprintk(FE_ERROR, 1, "I/O error"); + return -1; +} + +static int stv090x_vitclk_ctl(struct stv090x_state *state, int enable) +{ + u32 reg; + + switch (state->demod) { + case STV090x_DEMODULATOR_0: + mutex_lock(&demod_lock); + reg = stv090x_read_reg(state, STV090x_STOPCLK2); + STV090x_SETFIELD(reg, STOP_CLKVIT1_FIELD, enable); + if (stv090x_write_reg(state, STV090x_STOPCLK2, reg) < 0) + goto err; + mutex_unlock(&demod_lock); + break; + + case STV090x_DEMODULATOR_1: + mutex_lock(&demod_lock); + reg = stv090x_read_reg(state, STV090x_STOPCLK2); + STV090x_SETFIELD(reg, STOP_CLKVIT2_FIELD, enable); + if (stv090x_write_reg(state, STV090x_STOPCLK2, reg) < 0) + goto err; + mutex_unlock(&demod_lock); + break; + + default: + dprintk(FE_ERROR, 1, "Wrong demodulator!"); + break; + } + return 0; +err: + mutex_unlock(&demod_lock); + dprintk(FE_ERROR, 1, "I/O error"); + return -1; +} + +static int stv090x_delivery_search(struct stv090x_state *state) +{ + u32 reg; + + switch (state->search_mode) { + case STV090x_SEARCH_DVBS1: + case STV090x_SEARCH_DSS: + reg = STV090x_READ_DEMOD(state, DMDCFGMD); + STV090x_SETFIELD_Px(reg, DVBS1_ENABLE_FIELD, 1); + STV090x_SETFIELD_Px(reg, DVBS2_ENABLE_FIELD, 0); + if (STV090x_WRITE_DEMOD(state, DMDCFGMD, reg) < 0) + goto err; + + /* Activate Viterbi decoder in legacy search, do not use FRESVIT1, might impact VITERBI2 */ + if (stv090x_vitclk_ctl(state, 0) < 0) + goto err; + + if (STV090x_WRITE_DEMOD(state, ACLC, 0x1a) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, BCLC, 0x09) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, CAR2CFG, 0x22) < 0) /* disable DVB-S2 */ + goto err; + + stv090x_set_vit_thacq(state); + stv090x_set_viterbi(state); + break; + + case STV090x_SEARCH_DVBS2: + reg = STV090x_READ_DEMOD(state, DMDCFGMD); + STV090x_SETFIELD_Px(reg, DVBS1_ENABLE_FIELD, 0); + STV090x_SETFIELD_Px(reg, DVBS2_ENABLE_FIELD, 0); + if (STV090x_WRITE_DEMOD(state, DMDCFGMD, reg) < 0) + goto err; + STV090x_SETFIELD_Px(reg, DVBS1_ENABLE_FIELD, 1); + STV090x_SETFIELD_Px(reg, DVBS2_ENABLE_FIELD, 1); + if (STV090x_WRITE_DEMOD(state, DMDCFGMD, reg) < 0) + goto err; + + if (stv090x_vitclk_ctl(state, 1) < 0) + goto err; + + if (STV090x_WRITE_DEMOD(state, ACLC, 0x1a) < 0) /* stop DVB-S CR loop */ + goto err; + if (STV090x_WRITE_DEMOD(state, BCLC, 0x09) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, CAR2CFG, 0x26) < 0) + goto err; + + if (state->demod_mode != STV090x_SINGLE) { + if (state->dev_ver <= 0x11) /* 900 in dual TS mode */ + stv090x_stop_modcod(state); + else + stv090x_activate_modcod(state); + } + break; + + case STV090x_SEARCH_AUTO: + default: + reg = STV090x_READ_DEMOD(state, DMDCFGMD); + STV090x_SETFIELD_Px(reg, DVBS1_ENABLE_FIELD, 0); + STV090x_SETFIELD_Px(reg, DVBS2_ENABLE_FIELD, 0); + if (STV090x_WRITE_DEMOD(state, DMDCFGMD, reg) < 0) + goto err; + STV090x_SETFIELD_Px(reg, DVBS1_ENABLE_FIELD, 1); + STV090x_SETFIELD_Px(reg, DVBS2_ENABLE_FIELD, 1); + if (STV090x_WRITE_DEMOD(state, DMDCFGMD, reg) < 0) + goto err; + + if (stv090x_vitclk_ctl(state, 1) < 0) + goto err; + + if (STV090x_WRITE_DEMOD(state, ACLC, 0x1a) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, ACLC, 0x09) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, CAR2CFG, 0x26) < 0) + goto err; + + if (state->demod_mode != STV090x_SINGLE) { + if (state->dev_ver <= 0x11) /* 900 in dual TS mode */ + stv090x_stop_modcod(state); + else + stv090x_activate_modcod(state); + } + stv090x_set_vit_thacq(state); + stv090x_set_viterbi(state); + break; + } + return 0; +err: + dprintk(FE_ERROR, 1, "I/O error"); + return -1; +} + +static int stv090x_start_search(struct stv090x_state *state) +{ + u32 reg; + + reg = STV090x_READ_DEMOD(state, DMDISTATE); + STV090x_SETFIELD_Px(reg, I2C_DEMOD_MODE_FIELD, 0x1f); + if (STV090x_WRITE_DEMOD(state, DMDISTATE, reg) < 0) + goto err; + + if (state->dev_ver == 0x10) { + if (STV090x_WRITE_DEMOD(state, CORRELEXP, 0xaa) < 0) + goto err; + } + if (state->dev_ver < 0x20) { + if (STV090x_WRITE_DEMOD(state, CARHDR, 0x55) < 0) + goto err; + } + if (state->srate <= 5000000) { + if (STV090x_WRITE_DEMOD(state, CARCFG, 0x44) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, CFRUP1, 0x0f) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, CFRUP1, 0xff) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, CFRLOW1, 0xf0) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, CFRLOW0, 0x00) < 0) + goto err; + + /*enlarge the timing bandwith for Low SR*/ + if (STV090x_WRITE_DEMOD(state, RTCS2, 0x68) < 0) + goto err; + } else { + /* If the symbol rate is >5 Msps + Set The carrier search up and low to auto mode */ + if (STV090x_WRITE_DEMOD(state, CARCFG, 0xc4) < 0) + goto err; + /*reduce the timing bandwith for high SR*/ + if (STV090x_WRITE_DEMOD(state, RTCS2, 0x44) < 0) + goto err; + } + if (STV090x_WRITE_DEMOD(state, CFRINIT1, 0) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, CFRINIT0, 0) < 0) + goto err; + + if (state->dev_ver >= 0x20) { + if (STV090x_WRITE_DEMOD(state, EQUALCFG, 0x41) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, FFECFG, 0x41) < 0) + goto err; + + if ((state->search_mode == STV090x_DVBS1) || + (state->search_mode == STV090x_DSS) || + (state->search_mode == STV090x_SEARCH_AUTO)) { + + if (STV090x_WRITE_DEMOD(state, VITSCALE, 0x82) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, VAVSRVIT, 0x00) < 0) + goto err; + } + } + + if (STV090x_WRITE_DEMOD(state, SFRSTEP, 0x00) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, TMGTHRISE, 0xe0) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, TMGTHFALL, 0xc0) < 0) + goto err; + + reg = STV090x_READ_DEMOD(state, DMDCFGMD); + STV090x_SETFIELD_Px(reg, SCAN_ENABLE_FIELD, 0); + STV090x_SETFIELD_Px(reg, CFR_AUTOSCAN_FIELD, 0); + if (STV090x_WRITE_DEMOD(state, DMDCFGMD, reg) < 0) + goto err; + reg = STV090x_READ_DEMOD(state, DMDCFG2); + STV090x_SETFIELD_Px(reg, S1S2_SEQUENTIAL_FIELD, 0x0); + if (STV090x_WRITE_DEMOD(state, DMDCFG2, reg) < 0) + goto err; + + if (state->dev_ver >= 0x20) { /*Frequency offset detector setting*/ + if (state->srate < 10000000) { + if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x4c) < 0) + goto err; + } else { + if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x4b) < 0) + goto err; + } + } else { + if (state->srate < 10000000) { + if (STV090x_WRITE_DEMOD(state, CARFREQ, 0xef) < 0) + goto err; + } else { + if (STV090x_WRITE_DEMOD(state, CARFREQ, 0xed) < 0) + goto err; + } + } + + switch (state->algo) { + case STV090x_WARM_SEARCH:/*The symbol rate and the exact carrier Frequency are known */ + if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x1f) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x18) < 0) + goto err; + break; + + case STV090x_COLD_SEARCH:/*The symbol rate is known*/ + if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x1f) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x15) < 0) + goto err; + break; + + default: + break; + } + return 0; +err: + dprintk(FE_ERROR, 1, "I/O error"); + return -1; +} + +static int stv090x_get_agc2_min_level(struct stv090x_state *state) +{ + u32 agc2_min = 0, agc2 = 0, freq_init, freq_step, reg; + s32 i, j, steps, dir; + + if (STV090x_WRITE_DEMOD(state, AGC2REF, 0x38) < 0) + goto err; + reg = STV090x_READ_DEMOD(state, DMDCFGMD); + STV090x_SETFIELD_Px(reg, SCAN_ENABLE_FIELD, 1); + STV090x_SETFIELD_Px(reg, CFR_AUTOSCAN_FIELD, 1); + if (STV090x_WRITE_DEMOD(state, DMDCFGMD, reg) < 0) + goto err; + + if (STV090x_WRITE_DEMOD(state, SFRUP1, 0x83) < 0) /* SR = 65 Msps Max */ + goto err; + if (STV090x_WRITE_DEMOD(state, SFRUP0, 0xc0) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, SFRLOW1, 0x82) < 0) /* SR= 400 ksps Min */ + goto err; + if (STV090x_WRITE_DEMOD(state, SFRLOW0, 0xa0) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, DMDTOM, 0x00) < 0) /* stop acq @ coarse carrier state */ + goto err; + stv090x_set_srate(state, 1000000); + + steps = -1 + state->search_range / 1000000; + steps /= 2; + steps = (2 * steps) + 1; + if (steps < 0) + steps = 1; + + dir = 1; + freq_step = (1000000 * 256) / (state->mclk / 256); + freq_init = 0; + + for (i = 0; i < steps; i++) { + if (dir > 0) + freq_init = freq_init + (freq_step * i); + else + freq_init = freq_init - (freq_step * i); + + dir = -1; + + if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x5c) < 0) /* Demod RESET */ + goto err; + if (STV090x_WRITE_DEMOD(state, CFRINIT1, (freq_init >> 8) & 0xff) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, CFRINIT0, freq_init & 0xff) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x58) < 0) /* Demod RESET */ + goto err; + msleep(10); + for (j = 0; j < 10; j++) { + agc2 += STV090x_READ_DEMOD(state, AGC2I1) << 8; + agc2 |= STV090x_READ_DEMOD(state, AGC2I0); + } + agc2 /= 10; + agc2_min = 0xffff; + if (agc2 < 0xffff) + agc2_min = agc2; + } + + return agc2_min; +err: + dprintk(FE_ERROR, 1, "I/O error"); + return -1; +} + +static u32 stv090x_get_srate(struct stv090x_state *state, u32 clk) +{ + u8 r3, r2, r1, r0; + s32 srate, int_1, int_2, tmp_1, tmp_2; + u32 pow2; + + r3 = STV090x_READ_DEMOD(state, SFR3); + r2 = STV090x_READ_DEMOD(state, SFR2); + r1 = STV090x_READ_DEMOD(state, SFR1); + r0 = STV090x_READ_DEMOD(state, SFR0); + + srate = ((r3 << 24) | (r2 << 16) | (r1 << 8) | r0); + + pow2 = 1 << 16; + int_1 = clk / pow2; + int_2 = srate / pow2; + + tmp_1 = clk % pow2; + tmp_2 = srate % pow2; + + srate = (int_1 * int_2) + + ((int_1 * tmp_2) / pow2) + + ((int_2 * tmp_1) / pow2); + + return srate; +} + +static u32 stv090x_srate_srch_coarse(struct stv090x_state *state) +{ + struct dvb_frontend *fe = &state->frontend; + + int tmg_lock = 0, i; + s32 tmg_cpt = 0, dir = 1, steps, cur_step = 0, freq; + u32 srate_coarse = 0, agc2 = 0, car_step = 1200, reg; + + reg = STV090x_READ_DEMOD(state, DMDISTATE); + STV090x_SETFIELD_Px(reg, I2C_DEMOD_MODE_FIELD, 0x1f); /* Demod RESET */ + if (STV090x_WRITE_DEMOD(state, DMDISTATE, reg) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, TMGCFG, 0x12) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, TMGTHRISE, 0xf0) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, TMGTHFALL, 0xe0) < 0) + goto err; + reg = STV090x_READ_DEMOD(state, DMDCFGMD); + STV090x_SETFIELD_Px(reg, SCAN_ENABLE_FIELD, 1); + STV090x_SETFIELD_Px(reg, CFR_AUTOSCAN_FIELD, 1); + if (STV090x_WRITE_DEMOD(state, DMDCFGMD, reg) < 0) + goto err; + + if (STV090x_WRITE_DEMOD(state, SFRUP1, 0x83) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, SFRUP0, 0xc0) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, SFRLOW1, 0x82) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, SFRLOW0, 0xa0) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, DMDTOM, 0x00) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, AGC2REF, 0x60) < 0) + goto err; + + if (state->dev_ver >= 0x20) { + if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x6a) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, SFRSTEP, 0x95) < 0) + goto err; + } else { + if (STV090x_WRITE_DEMOD(state, CARFREQ, 0xed) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, SFRSTEP, 0x73) < 0) + goto err; + } + + if (state->srate <= 2000000) + car_step = 1000; + else if (state->srate <= 5000000) + car_step = 2000; + else if (state->srate <= 12000000) + car_step = 3000; + else + car_step = 5000; + + steps = -1 + ((state->search_range / 1000) / car_step); + steps /= 2; + steps = (2 * steps) + 1; + if (steps < 0) + steps = 1; + else if (steps > 10) { + steps = 11; + car_step = (state->search_range / 1000) / 10; + } + cur_step = 0; + dir = 1; + freq = state->frequency; + + while ((!tmg_lock) && (cur_step < steps)) { + if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x5f) < 0) /* Demod RESET */ + goto err; + reg = STV090x_READ_DEMOD(state, DMDISTATE); + STV090x_SETFIELD_Px(reg, I2C_DEMOD_MODE_FIELD, 0x00); /* trigger acquisition */ + if (STV090x_WRITE_DEMOD(state, DMDISTATE, reg) < 0) + goto err; + msleep(50); + for (i = 0; i < 10; i++) { + reg = STV090x_READ_DEMOD(state, DSTATUS); + if (STV090x_GETFIELD_Px(reg, TMGLOCK_QUALITY_FIELD) >= 2) + tmg_cpt++; + agc2 += STV090x_READ_DEMOD(state, AGC2I1) << 8; + agc2 |= STV090x_READ_DEMOD(state, AGC2I0); + } + agc2 /= 10; + srate_coarse = stv090x_get_srate(state, state->mclk); + cur_step++; + dir *= -1; + if ((tmg_cpt >= 5) && (agc2 < 0x1f00) && (srate_coarse < 55000000) && (srate_coarse > 850000)) + tmg_lock = 1; + else if (cur_step < steps) { + if (dir > 0) + freq += cur_step * car_step; + else + freq -= cur_step * car_step; + + /* Setup tuner */ + stv090x_i2c_gate_ctrl(fe, 1); + + if (state->config->tuner_set_frequency) + state->config->tuner_set_frequency(fe, state->frequency); + + if (state->config->tuner_set_bandwidth) + state->config->tuner_set_bandwidth(fe, state->tuner_bw); + + stv090x_i2c_gate_ctrl(fe, 0); + msleep(50); + stv090x_i2c_gate_ctrl(fe, 1); + + if (state->config->tuner_get_status) + state->config->tuner_get_status(fe, ®); + + if (reg) + dprintk(FE_DEBUG, 1, "Tuner phase locked"); + else + dprintk(FE_DEBUG, 1, "Tuner unlocked"); + + stv090x_i2c_gate_ctrl(fe, 0); + + } + } + if (!tmg_lock) + srate_coarse = 0; + else + srate_coarse = stv090x_get_srate(state, state->mclk); + + return srate_coarse; +err: + dprintk(FE_ERROR, 1, "I/O error"); + return -1; +} + +static u32 stv090x_srate_srch_fine(struct stv090x_state *state) +{ + u32 srate_coarse, freq_coarse, sym, reg; + + srate_coarse = stv090x_get_srate(state, state->mclk); + freq_coarse = STV090x_READ_DEMOD(state, CFR2) << 8; + freq_coarse |= STV090x_READ_DEMOD(state, CFR1); + sym = 13 * (srate_coarse / 10); /* SFRUP = SFR + 30% */ + + if (sym < state->srate) + srate_coarse = 0; + else { + if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x1f) < 0) /* Demod RESET */ + goto err; + if (STV090x_WRITE_DEMOD(state, TMGCFG2, 0x01) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, TMGTHRISE, 0x20) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, TMGTHFALL, 0x00) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, TMGCFG, 0xd2) < 0) + goto err; + reg = STV090x_READ_DEMOD(state, DMDCFGMD); + STV090x_SETFIELD_Px(reg, CFR_AUTOSCAN_FIELD, 0x00); + if (STV090x_WRITE_DEMOD(state, DMDCFGMD, reg) < 0) + goto err; + + if (state->dev_ver >= 0x20) { + if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x49) < 0) + goto err; + } else { + if (STV090x_WRITE_DEMOD(state, CARFREQ, 0xed) < 0) + goto err; + } + + if (srate_coarse > 3000000) { + sym = 13 * (srate_coarse / 10); /* SFRUP = SFR + 30% */ + sym = (sym / 1000) * 65536; + sym /= (state->mclk / 1000); + if (STV090x_WRITE_DEMOD(state, SFRUP1, (sym >> 8) & 0x7f) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, SFRUP0, sym & 0xff) < 0) + goto err; + sym = 10 * (srate_coarse / 13); /* SFRLOW = SFR - 30% */ + sym = (sym / 1000) * 65536; + sym /= (state->mclk / 1000); + if (STV090x_WRITE_DEMOD(state, SFRLOW1, (sym >> 8) & 0x7f) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, SFRLOW0, sym & 0xff) < 0) + goto err; + sym = (srate_coarse / 1000) * 65536; + sym /= (state->mclk / 1000); + if (STV090x_WRITE_DEMOD(state, SFRINIT1, (sym >> 8) & 0xff) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, SFRINIT0, sym & 0xff) < 0) + goto err; + } else { + sym = 13 * (srate_coarse / 10); /* SFRUP = SFR + 30% */ + sym = (sym / 100) * 65536; + sym /= (state->mclk / 100); + if (STV090x_WRITE_DEMOD(state, SFRUP1, (sym >> 8) & 0x7f) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, SFRUP0, sym & 0xff) < 0) + goto err; + sym = 10 * (srate_coarse / 14); /* SFRLOW = SFR - 30% */ + sym = (sym / 100) * 65536; + sym /= (state->mclk / 100); + if (STV090x_WRITE_DEMOD(state, SFRLOW1, (sym >> 8) & 0x7f) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, SFRLOW0, sym & 0xff) < 0) + goto err; + sym = (srate_coarse / 100) * 65536; + sym /= (state->mclk / 100); + if (STV090x_WRITE_DEMOD(state, SFRINIT1, (sym >> 8) & 0xff) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, SFRINIT0, sym & 0xff) < 0) + goto err; + } + if (STV090x_WRITE_DEMOD(state, DMDTOM, 0x20) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, CFRINIT1, (freq_coarse >> 8) & 0xff) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, CFRINIT0, freq_coarse & 0xff) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x15) < 0) /* trigger acquisition */ + goto err; + } + + return srate_coarse; + +err: + dprintk(FE_ERROR, 1, "I/O error"); + return -1; +} + +static int stv090x_get_dmdlock(struct stv090x_state *state, s32 timeout) +{ + s32 timer = 0, lock = 0; + u32 reg; + u8 stat; + + while ((timer < timeout) && (!lock)) { + reg = STV090x_READ_DEMOD(state, DMDSTATE); + stat = STV090x_GETFIELD_Px(reg, HEADER_MODE_FIELD); + + switch (stat) { + case 0: /* searching */ + case 1: /* first PLH detected */ + default: + dprintk(FE_DEBUG, 1, "Demodulator searching .."); + lock = 0; + break; + case 2: /* DVB-S2 mode */ + case 3: /* DVB-S1/legacy mode */ + reg = STV090x_READ_DEMOD(state, DSTATUS); + lock = STV090x_GETFIELD_Px(reg, LOCK_DEFINITIF_FIELD); + break; + } + + if (!lock) + msleep(10); + else + dprintk(FE_DEBUG, 1, "Demodulator acquired LOCK"); + + timer += 10; + } + return lock; +} + +static int stv090x_blind_search(struct stv090x_state *state) +{ + u32 agc2, reg, srate_coarse; + s32 timeout_dmd = 500, cpt_fail, agc2_ovflw, i; + u8 k_ref, k_max, k_min; + int coarse_fail, lock; + + if (state->dev_ver < 0x20) { + k_max = 233; + k_min = 143; + } else { + k_max = 120; + k_min = 30; + } + + agc2 = stv090x_get_agc2_min_level(state); + + if (agc2 > STV090x_SEARCH_AGC2_TH) { + lock = 0; + } else { + if (state->dev_ver == 0x10) { + if (STV090x_WRITE_DEMOD(state, CORRELEXP, 0xaa) < 0) + goto err; + } + if (state->dev_ver < 0x20) { + if (STV090x_WRITE_DEMOD(state, CARHDR, 0x55) < 0) + goto err; + } + + if (STV090x_WRITE_DEMOD(state, CARCFG, 0xc4) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, RTCS2, 0x44) < 0) + goto err; + if (state->dev_ver >= 0x20) { + if (STV090x_WRITE_DEMOD(state, EQUALCFG, 0x41) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, FFECFG, 0x41) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, VITSCALE, 0x82) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, VAVSRVIT, 0x00) < 0) /* set viterbi hysteresis */ + goto err; + } + + k_ref = k_max; + do { + if (STV090x_WRITE_DEMOD(state, KREFTMG, k_ref) < 0) + goto err; + if (stv090x_srate_srch_coarse(state) != 0) { + srate_coarse = stv090x_srate_srch_fine(state); + if (srate_coarse != 0) { + stv090x_get_lock_tmg(state); + lock = stv090x_get_dmdlock(state, timeout_dmd); + } else { + lock = 0; + } + } else { + cpt_fail = 0; + agc2_ovflw = 0; + for (i = 0; i < 10; i++) { + agc2 = STV090x_READ_DEMOD(state, AGC2I1) << 8; + agc2 |= STV090x_READ_DEMOD(state, AGC2I0); + if (agc2 >= 0xff00) + agc2_ovflw++; + reg = STV090x_READ_DEMOD(state, DSTATUS2); + if ((STV090x_GETFIELD_Px(reg, CFR_OVERFLOW_FIELD) == 0x01) && + (STV090x_GETFIELD_Px(reg, DEMOD_DELOCK_FIELD) == 0x01)) + + cpt_fail++; + } + if ((cpt_fail > 7) || (agc2_ovflw > 7)) + coarse_fail = 1; + + lock = 0; + } + k_ref -= 30; + } while ((k_ref >= k_min) && (!lock) && (!coarse_fail)); + } + + return lock; + +err: + dprintk(FE_ERROR, 1, "I/O error"); + return -1; +} + +static int stv090x_chk_tmg(struct stv090x_state *state) +{ + u32 reg; + s32 tmg_cpt, i; + u8 freq, tmg_thh, tmg_thl; + int tmg_lock; + + freq = STV090x_READ_DEMOD(state, CARFREQ); + tmg_thh = STV090x_READ_DEMOD(state, TMGTHRISE); + tmg_thl = STV090x_READ_DEMOD(state, TMGTHFALL); + if (STV090x_WRITE_DEMOD(state, TMGTHRISE, 0x20) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, TMGTHFALL, 0x00) < 0) + goto err; + + reg = STV090x_READ_DEMOD(state, DMDCFGMD); + STV090x_SETFIELD_Px(reg, CFR_AUTOSCAN_FIELD, 0x00); /* stop carrier offset search */ + if (STV090x_WRITE_DEMOD(state, DMDCFGMD, reg) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, RTC, 0x80) < 0) + goto err; + + if (STV090x_WRITE_DEMOD(state, RTCS2, 0x40) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x00) < 0) + goto err; + + if (STV090x_WRITE_DEMOD(state, CFRINIT1, 0x00) < 0) /* set car ofset to 0 */ + goto err; + if (STV090x_WRITE_DEMOD(state, CFRINIT0, 0x00) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, AGC2REF, 0x65) < 0) + goto err; + + if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x18) < 0) /* trigger acquisition */ + goto err; + msleep(10); + + for (i = 0; i < 10; i++) { + reg = STV090x_READ_DEMOD(state, DSTATUS); + if (STV090x_GETFIELD_Px(reg, TMGLOCK_QUALITY_FIELD) >= 2) + tmg_cpt++; + msleep(1); + } + if (tmg_cpt >= 3) + tmg_lock = 1; + + if (STV090x_WRITE_DEMOD(state, AGC2REF, 0x38) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, RTC, 0x88) < 0) /* DVB-S1 timing */ + goto err; + if (STV090x_WRITE_DEMOD(state, RTCS2, 0x68) < 0) /* DVB-S2 timing */ + goto err; + + if (STV090x_WRITE_DEMOD(state, CARFREQ, freq) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, TMGTHRISE, tmg_thh) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, TMGTHFALL, tmg_thl) < 0) + goto err; + + return tmg_lock; + +err: + dprintk(FE_ERROR, 1, "I/O error"); + return -1; +} + +static int stv090x_get_coldlock(struct stv090x_state *state, s32 timeout_dmd) +{ + struct dvb_frontend *fe = &state->frontend; + + u32 reg; + s32 car_step, steps, cur_step, dir, freq, timeout_lock; + int lock = 0; + + if (state->srate >= 10000000) + timeout_lock = timeout_dmd / 3; + else + timeout_lock = timeout_dmd / 2; + + lock = stv090x_get_dmdlock(state, timeout_lock); /* cold start wait */ + if (!lock) { + if (state->srate >= 10000000) { + if (stv090x_chk_tmg(state)) { + if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x1f) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x15) < 0) + goto err; + lock = stv090x_get_dmdlock(state, timeout_dmd); + } else { + lock = 0; + } + } else { + if (state->srate <= 4000000) + car_step = 1000; + else if (state->srate <= 7000000) + car_step = 2000; + else if (state->srate <= 10000000) + car_step = 3000; + else + car_step = 5000; + + steps = (state->search_range / 1000) / car_step; + steps /= 2; + steps = 2 * (steps + 1); + if (steps < 0) + steps = 2; + else if (steps > 12) + steps = 12; + + cur_step = 1; + dir = 1; + + if (!lock) { + freq = state->frequency; + state->tuner_bw = stv090x_car_width(state->srate, state->rolloff) + state->srate; + while ((cur_step <= steps) && (!lock)) { + if (dir > 0) + freq += cur_step * car_step; + else + freq -= cur_step * car_step; + + /* Setup tuner */ + stv090x_i2c_gate_ctrl(fe, 1); + + if (state->config->tuner_set_frequency) + state->config->tuner_set_frequency(fe, state->frequency); + + if (state->config->tuner_set_bandwidth) + state->config->tuner_set_bandwidth(fe, state->tuner_bw); + + stv090x_i2c_gate_ctrl(fe, 0); + + msleep(50); + + stv090x_i2c_gate_ctrl(fe, 1); + + if (state->config->tuner_get_status) + state->config->tuner_get_status(fe, ®); + + if (reg) + dprintk(FE_DEBUG, 1, "Tuner phase locked"); + else + dprintk(FE_DEBUG, 1, "Tuner unlocked"); + + stv090x_i2c_gate_ctrl(fe, 0); + + STV090x_WRITE_DEMOD(state, DMDISTATE, 0x1c); + if (state->delsys == STV090x_DVBS2) { + reg = STV090x_READ_DEMOD(state, DMDCFGMD); + STV090x_SETFIELD_Px(reg, DVBS1_ENABLE_FIELD, 0); + STV090x_SETFIELD_Px(reg, DVBS2_ENABLE_FIELD, 0); + if (STV090x_WRITE_DEMOD(state, DMDCFGMD, reg) < 0) + goto err; + STV090x_SETFIELD_Px(reg, DVBS1_ENABLE_FIELD, 1); + STV090x_SETFIELD_Px(reg, DVBS2_ENABLE_FIELD, 1); + if (STV090x_WRITE_DEMOD(state, DMDCFGMD, reg) < 0) + goto err; + } + if (STV090x_WRITE_DEMOD(state, CFRINIT1, 0x00) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, CFRINIT0, 0x00) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x1f) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x15) < 0) + goto err; + lock = stv090x_get_dmdlock(state, (timeout_dmd / 3)); + + dir *= -1; + cur_step++; + } + } + } + } + + return lock; + +err: + dprintk(FE_ERROR, 1, "I/O error"); + return -1; +} + +static int stv090x_get_loop_params(struct stv090x_state *state, s32 *freq_inc, s32 *timeout_sw, s32 *steps) +{ + s32 timeout, inc, steps_max, srate, car_max; + + srate = state->srate; + car_max = state->search_range / 1000; + car_max = 65536 * (car_max / 2); + car_max /= (state->mclk / 1000); + + if (car_max > 0x4000) + car_max = 0x4000 ; /* maxcarrier should be<= +-1/4 Mclk */ + + inc = srate; + inc /= state->mclk / 1000; + inc *= 256; + inc *= 256; + inc /= 1000; + + switch (state->algo) { + case STV090x_SEARCH_DVBS1: + case STV090x_SEARCH_DSS: + inc *= 3; /* freq step = 3% of srate */ + timeout = 20; + break; + + case STV090x_SEARCH_DVBS2: + inc *= 4; + timeout = 25; + break; + + case STV090x_SEARCH_AUTO: + default: + inc *= 3; + timeout = 25; + break; + } + inc /= 100; + if ((inc > car_max) || (inc < 0)) + inc = car_max / 2; /* increment <= 1/8 Mclk */ + + timeout *= 27500; /* 27.5 Msps reference */ + if (srate > 0) + timeout /= (srate / 1000); + + if ((timeout > 100) || (timeout < 0)) + timeout = 100; + + steps_max = (car_max / inc) + 1; /* min steps = 3 */ + if ((steps_max > 100) || (steps_max < 0)) { + steps_max = 100; /* max steps <= 100 */ + inc = car_max / steps_max; + } + *freq_inc = inc; + *timeout_sw = timeout; + *steps = steps_max; + + return 0; +} + +static int stv090x_chk_signal(struct stv090x_state *state) +{ + s32 offst_car, agc2, car_max; + int no_signal; + + offst_car = STV090x_READ_DEMOD(state, CFR2) << 8; + offst_car |= STV090x_READ_DEMOD(state, CFR1); + + agc2 = STV090x_READ_DEMOD(state, AGC2I1) << 8; + agc2 |= STV090x_READ_DEMOD(state, AGC2I0); + car_max = state->search_range / 1000; + + car_max += (car_max / 10); /* 10% margin */ + car_max = (65536 * car_max / 2); + car_max /= state->mclk / 1000; + + if (car_max > 0x4000) + car_max = 0x4000; + + if ((agc2 > 0x2000) || (offst_car > 2 * car_max) || (offst_car < -2 * car_max)) { + no_signal = 1; + dprintk(FE_DEBUG, 1, "No Signal"); + } else { + no_signal = 0; + dprintk(FE_DEBUG, 1, "Found Signal"); + } + + return no_signal; +} + +static int stv090x_search_car_loop(struct stv090x_state *state, s32 inc, s32 timeout, int zigzag, s32 steps_max) +{ + int no_signal, lock = 0; + s32 cpt_step, offst_freq, car_max; + u32 reg; + + car_max = state->search_range / 1000; + car_max += (car_max / 10); + car_max = (65536 * car_max / 2); + car_max /= (state->mclk / 1000); + if (car_max > 0x4000) + car_max = 0x4000; + + if (zigzag) + offst_freq = 0; + else + offst_freq = -car_max + inc; + + cpt_step = 0; + do { + if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x1c) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, CFRINIT1, ((offst_freq / 256) & 0xff)) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, CFRINIT0, offst_freq & 0xff) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x18) < 0) + goto err; + + reg = STV090x_READ_DEMOD(state, PDELCTRL1); + STV090x_SETFIELD_Px(reg, ALGOSWRST_FIELD, 0x1); /* stop DVB-S2 packet delin */ + if (STV090x_WRITE_DEMOD(state, PDELCTRL1, reg) < 0) + goto err; + + if (state->dev_ver == 0x12) { + reg = STV090x_READ_DEMOD(state, TSCFGH); + STV090x_SETFIELD_Px(reg, RST_HWARE_FIELD, 0x1); + if (STV090x_WRITE_DEMOD(state, TSCFGH, reg) < 0) + goto err; + } + + if (zigzag) { + if (offst_freq >= 0) + offst_freq = -offst_freq - 2 * inc; + else + offst_freq = -offst_freq; + } else { + offst_freq += 2 * inc; + } + + lock = stv090x_get_dmdlock(state, timeout); + no_signal = stv090x_chk_signal(state); + + } while ((!lock) && + (!no_signal) && + ((offst_freq - inc) < car_max) && + ((offst_freq + inc) > -car_max) && + (cpt_step < steps_max)); + + reg = STV090x_READ_DEMOD(state, PDELCTRL1); + STV090x_SETFIELD_Px(reg, ALGOSWRST_FIELD, 0); + if (STV090x_WRITE_DEMOD(state, PDELCTRL1, reg) < 0) + goto err; + + return lock; +err: + dprintk(FE_ERROR, 1, "I/O error"); + return -1; +} + +static int stv090x_sw_algo(struct stv090x_state *state) +{ + int no_signal, zigzag, lock = 0; + u32 reg; + + s32 dvbs2_fly_wheel; + s32 inc, timeout_step, trials, steps_max; + + stv090x_get_loop_params(state, &inc, &timeout_step, &steps_max); /* get params */ + + switch (state->algo) { + case STV090x_SEARCH_DVBS1: + case STV090x_SEARCH_DSS: + /* accelerate the frequency detector */ + if (state->dev_ver >= 0x20) { + if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x3B) < 0) + goto err; + } else { + if (STV090x_WRITE_DEMOD(state, CARFREQ, 0xef) < 0) + goto err; + } + if (STV090x_WRITE_DEMOD(state, DMDCFGMD, 0x49) < 0) + goto err; + zigzag = 0; + break; + + case STV090x_SEARCH_DVBS2: + if (state->dev_ver >= 0x20) { + if (STV090x_WRITE_DEMOD(state, CORRELABS, 0x79) < 0) + goto err; + } else { + if (STV090x_WRITE_DEMOD(state, CORRELABS, 0x68) < 0) + goto err; + } + if (STV090x_WRITE_DEMOD(state, DMDCFGMD, 0x89) < 0) + goto err; + zigzag = 1; + break; + + case STV090x_SEARCH_AUTO: + default: + /* accelerate the frequency detector */ + if (state->dev_ver >= 0x20) { + if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x3b) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, CORRELABS, 0x79) < 0) + goto err; + } else { + if (STV090x_WRITE_DEMOD(state, CARFREQ, 0xef) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, CORRELABS, 0x68) < 0) + goto err; + } + if (STV090x_WRITE_DEMOD(state, DMDCFGMD, 0x69) < 0) + goto err; + zigzag = 0; + break; + } + + trials = 0; + do { + lock = stv090x_search_car_loop(state, inc, timeout_step, zigzag, steps_max); + no_signal = stv090x_chk_signal(state); + trials++; + + /*run the SW search 2 times maximum*/ + if (lock || no_signal || (trials == 2)) { + /*Check if the demod is not losing lock in DVBS2*/ + if (state->dev_ver >= 0x20) { + if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x49) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, CORRELABS, 0x9e) < 0) + goto err; + } else { + if (STV090x_WRITE_DEMOD(state, CARFREQ, 0xed) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, CORRELABS, 0x88) < 0) + goto err; + } + + reg = STV090x_READ_DEMOD(state, DMDSTATE); + if ((lock) && (STV090x_GETFIELD_Px(reg, HEADER_MODE_FIELD) == STV090x_DVBS2)) { + /*Check if the demod is not losing lock in DVBS2*/ + msleep(timeout_step); + reg = STV090x_READ_DEMOD(state, DMDFLYW); + dvbs2_fly_wheel = STV090x_GETFIELD_Px(reg, FLYWHEEL_CPT_FIELD); + if (dvbs2_fly_wheel < 0xd) { /*if correct frames is decrementing */ + msleep(timeout_step); + reg = STV090x_READ_DEMOD(state, DMDFLYW); + dvbs2_fly_wheel = STV090x_GETFIELD_Px(reg, FLYWHEEL_CPT_FIELD); + } + if (dvbs2_fly_wheel < 0xd) { + /*FALSE lock, The demod is loosing lock */ + lock = 0; + if (trials < 2) { + if (state->dev_ver >= 0x20) { + if (STV090x_WRITE_DEMOD(state, CORRELABS, 0x79) < 0) + goto err; + } else { + if (STV090x_WRITE_DEMOD(state, CORRELABS, 0x68) < 0) + goto err; + } + if (STV090x_WRITE_DEMOD(state, DMDCFGMD, 0x89) < 0) + goto err; + } + } + } + } + } while ((!lock) && (trials < 2) && (!no_signal)); + + return lock; +err: + dprintk(FE_ERROR, 1, "I/O error"); + return -1; +} + +static enum stv090x_delsys stv090x_get_std(struct stv090x_state *state) +{ + u32 reg; + enum stv090x_delsys delsys; + + reg = STV090x_READ_DEMOD(state, DMDSTATE); + if (STV090x_GETFIELD_Px(reg, HEADER_MODE_FIELD) == 2) + delsys = STV090x_DVBS2; + else if (STV090x_GETFIELD_Px(reg, HEADER_MODE_FIELD) == 3) { + reg = STV090x_READ_DEMOD(state, FECM); + if (STV090x_GETFIELD_Px(reg, DSS_DVB_FIELD) == 1) + delsys = STV090x_DSS; + else + delsys = STV090x_DVBS1; + } else { + delsys = STV090x_ERROR; + } + + return delsys; +} + +/* in Hz */ +static s32 stv090x_get_car_freq(struct stv090x_state *state, u32 mclk) +{ + s32 derot, int_1, int_2, tmp_1, tmp_2; + u32 pow2; + + derot = STV090x_READ_DEMOD(state, CFR2) << 16; + derot |= STV090x_READ_DEMOD(state, CFR1) << 8; + derot |= STV090x_READ_DEMOD(state, CFR0); + + derot = comp2(derot, 24); + pow2 = 1 << 12; + int_1 = state->mclk / pow2; + int_2 = derot / pow2; + + tmp_1 = state->mclk % pow2; + tmp_2 = derot % pow2; + + derot = (int_1 * int_2) + + ((int_1 * tmp_2) / pow2) + + ((int_1 * tmp_1) / pow2); + + return derot; +} + +static int stv090x_get_viterbi(struct stv090x_state *state) +{ + u32 reg, rate; + + reg = STV090x_READ_DEMOD(state, VITCURPUN); + rate = STV090x_GETFIELD_Px(reg, VIT_CURPUN_FIELD); + + switch (rate) { + case 13: + state->fec = STV090x_PR12; + break; + + case 18: + state->fec = STV090x_PR23; + break; + + case 21: + state->fec = STV090x_PR34; + break; + + case 24: + state->fec = STV090x_PR56; + break; + + case 25: + state->fec = STV090x_PR67; + break; + + case 26: + state->fec = STV090x_PR78; + break; + + default: + state->fec = STV090x_PRERR; + break; + } + + return 0; +} + +static enum stv090x_signal_state stv090x_get_sig_params(struct stv090x_state *state) +{ + struct dvb_frontend *fe = &state->frontend; + + u8 tmg; + u32 reg; + s32 i = 0, offst_freq; + + msleep(5); + + if (state->algo == STV090x_BLIND_SEARCH) { + tmg = STV090x_READ_DEMOD(state, TMGREG2); + STV090x_WRITE_DEMOD(state, SFRSTEP, 0x5c); + while ((i <= 50) && (!tmg) && (tmg != 0xff)) { + tmg = STV090x_READ_DEMOD(state, TMGREG2); + msleep(5); + i += 5; + } + } + state->delsys = stv090x_get_std(state); + + stv090x_i2c_gate_ctrl(fe, 1); + + if (state->config->tuner_get_frequency) + state->config->tuner_get_frequency(fe, &state->frequency); + + stv090x_i2c_gate_ctrl(fe, 0); + + offst_freq = stv090x_get_car_freq(state, state->mclk) / 1000; + state->frequency += offst_freq; + stv090x_get_viterbi(state); + reg = STV090x_READ_DEMOD(state, DMDMODCOD); + state->modcod = STV090x_GETFIELD_Px(reg, DEMOD_MODCOD_FIELD); + state->pilots = STV090x_GETFIELD_Px(reg, DEMOD_TYPE_FIELD) & 0x01; + state->frame_len = STV090x_GETFIELD_Px(reg, DEMOD_TYPE_FIELD) >> 1; + reg = STV090x_READ_DEMOD(state, TMGOBS); + state->rolloff = STV090x_GETFIELD_Px(reg, ROLLOFF_STATUS_FIELD); + reg = STV090x_READ_DEMOD(state, FECM); + state->inversion = STV090x_GETFIELD_Px(reg, IQINV_FIELD); + + if ((state->algo == STV090x_BLIND_SEARCH) || (state->srate < 10000000)) { + + stv090x_i2c_gate_ctrl(fe, 1); + + if (state->config->tuner_get_frequency) + state->config->tuner_get_frequency(fe, &state->frequency); + + stv090x_i2c_gate_ctrl(fe, 0); + + if (abs(offst_freq) <= ((state->search_range / 2000) + 500)) + return STV090x_RANGEOK; + else if (abs(offst_freq) <= (stv090x_car_width(state->srate, state->rolloff) / 2000)) + return STV090x_RANGEOK; + else + return STV090x_OUTOFRANGE; /* Out of Range */ + } else { + if (abs(offst_freq) <= ((state->search_range / 2000) + 500)) + return STV090x_RANGEOK; + else + return STV090x_OUTOFRANGE; + } + + return STV090x_OUTOFRANGE; +} + +static u32 stv090x_get_tmgoffst(struct stv090x_state *state, u32 srate) +{ + s32 offst_tmg; + s32 pow2; + + offst_tmg = STV090x_READ_DEMOD(state, TMGREG2) << 16; + offst_tmg |= STV090x_READ_DEMOD(state, TMGREG1) << 8; + offst_tmg |= STV090x_READ_DEMOD(state, TMGREG0); + + pow2 = 1 << 24; + + offst_tmg = comp2(offst_tmg, 24); /* 2's complement */ + if (!offst_tmg) + offst_tmg = 1; + + offst_tmg = ((s32) srate * 10) / (pow2 / offst_tmg); + offst_tmg /= 320; + + return offst_tmg; +} + +static u8 stv090x_optimize_carloop(struct stv090x_state *state, enum stv090x_modcod modcod, s32 pilots) +{ + u8 aclc = 0x29; + s32 i; + struct stv090x_long_frame_crloop *car_loop; + + if (state->dev_ver <= 0x12) + car_loop = stv090x_s2_crl; + else if (state->dev_ver == 0x20) + car_loop = stv090x_s2_crl_cut20; + else + car_loop = stv090x_s2_crl; + + + if (modcod < STV090x_QPSK_12) { + i = 0; + while ((i < 3) && (modcod != stv090x_s2_lowqpsk_crl_cut20[i].modcod)) + i++; + + if (i >= 3) + i = 2; + + } else { + i = 0; + while ((i < 14) && (modcod != car_loop[i].modcod)) + i++; + + if (i >= 14) { + i = 0; + while ((i < 11) && (modcod != stv090x_s2_lowqpsk_crl_cut20[i].modcod)) + i++; + + if (i >= 11) + i = 10; + } + } + + if (modcod <= STV090x_QPSK_25) { + if (pilots) { + if (state->srate <= 3000000) + aclc = stv090x_s2_lowqpsk_crl_cut20[i].crl_pilots_on_2; + else if (state->srate <= 7000000) + aclc = stv090x_s2_lowqpsk_crl_cut20[i].crl_pilots_on_5; + else if (state->srate <= 15000000) + aclc = stv090x_s2_lowqpsk_crl_cut20[i].crl_pilots_on_10; + else if (state->srate <= 25000000) + aclc = stv090x_s2_lowqpsk_crl_cut20[i].crl_pilots_on_20; + else + aclc = stv090x_s2_lowqpsk_crl_cut20[i].crl_pilots_on_30; + } else { + if (state->srate <= 3000000) + aclc = stv090x_s2_lowqpsk_crl_cut20[i].crl_pilots_off_2; + else if (state->srate <= 7000000) + aclc = stv090x_s2_lowqpsk_crl_cut20[i].crl_pilots_off_5; + else if (state->srate <= 15000000) + aclc = stv090x_s2_lowqpsk_crl_cut20[i].crl_pilots_off_10; + else if (state->srate <= 25000000) + aclc = stv090x_s2_lowqpsk_crl_cut20[i].crl_pilots_off_20; + else + aclc = stv090x_s2_lowqpsk_crl_cut20[i].crl_pilots_off_30; + } + + } else if (modcod <= STV090x_8PSK_910) { + if (pilots) { + if (state->srate <= 3000000) + aclc = car_loop[i].crl_pilots_on_2; + else if (state->srate <= 7000000) + aclc = car_loop[i].crl_pilots_on_5; + else if (state->srate <= 15000000) + aclc = car_loop[i].crl_pilots_on_10; + else if (state->srate <= 25000000) + aclc = car_loop[i].crl_pilots_on_20; + else + aclc = car_loop[i].crl_pilots_on_30; + } else { + if (state->srate <= 3000000) + aclc = car_loop[i].crl_pilots_off_2; + else if (state->srate <= 7000000) + aclc = car_loop[i].crl_pilots_off_5; + else if (state->srate <= 15000000) + aclc = car_loop[i].crl_pilots_off_10; + else if (state->srate <= 25000000) + aclc = car_loop[i].crl_pilots_off_20; + else + aclc = car_loop[i].crl_pilots_off_30; + } + } else { /* 16APSK and 32APSK */ + if (state->srate <= 3000000) + aclc = stv090x_s2_apsk_crl_cut20[i].crl_pilots_on_2; + else if (state->srate <= 7000000) + aclc = stv090x_s2_apsk_crl_cut20[i].crl_pilots_on_5; + else if (state->srate <= 15000000) + aclc = stv090x_s2_apsk_crl_cut20[i].crl_pilots_on_10; + else if (state->srate <= 25000000) + aclc = stv090x_s2_apsk_crl_cut20[i].crl_pilots_on_20; + else + aclc = stv090x_s2_apsk_crl_cut20[i].crl_pilots_on_30; + } + + return aclc; +} + +static u8 stv090x_optimize_carloop_short(struct stv090x_state *state) +{ + s32 index = 0; + u8 aclc = 0x0b; + + switch (state->modulation) { + case STV090x_QPSK: + default: + index = 0; + break; + case STV090x_8PSK: + index = 1; + break; + case STV090x_16APSK: + index = 2; + break; + case STV090x_32APSK: + index = 3; + break; + } + + switch (state->dev_ver) { + case 0x20: + if (state->srate <= 3000000) + aclc = stv090x_s2_short_crl[index].crl_cut20_2; + else if (state->srate <= 7000000) + aclc = stv090x_s2_short_crl[index].crl_cut20_5; + else if (state->srate <= 15000000) + aclc = stv090x_s2_short_crl[index].crl_cut20_10; + else if (state->srate <= 25000000) + aclc = stv090x_s2_short_crl[index].crl_cut20_20; + else + aclc = stv090x_s2_short_crl[index].crl_cut20_30; + break; + + case 0x12: + default: + if (state->srate <= 3000000) + aclc = stv090x_s2_short_crl[index].crl_cut12_2; + else if (state->srate <= 7000000) + aclc = stv090x_s2_short_crl[index].crl_cut12_5; + else if (state->srate <= 15000000) + aclc = stv090x_s2_short_crl[index].crl_cut12_10; + else if (state->srate <= 25000000) + aclc = stv090x_s2_short_crl[index].crl_cut12_20; + else + aclc = stv090x_s2_short_crl[index].crl_cut12_30; + break; + } + + return aclc; +} + +static int stv090x_optimize_track(struct stv090x_state *state) +{ + struct dvb_frontend *fe = &state->frontend; + + enum stv090x_rolloff rolloff; + enum stv090x_modcod modcod; + + s32 srate, pilots, aclc, f_1, f_0, i = 0, blind_tune = 0; + u32 reg; + + srate = stv090x_get_srate(state, state->mclk); + srate += stv090x_get_tmgoffst(state, srate); + + switch (state->delsys) { + case STV090x_DVBS1: + case STV090x_DSS: + if (state->algo == STV090x_SEARCH_AUTO) { + reg = STV090x_READ_DEMOD(state, DMDCFGMD); + STV090x_SETFIELD_Px(reg, DVBS1_ENABLE_FIELD, 1); + STV090x_SETFIELD_Px(reg, DVBS2_ENABLE_FIELD, 0); + if (STV090x_WRITE_DEMOD(state, DMDCFGMD, reg) < 0) + goto err; + } + reg = STV090x_READ_DEMOD(state, DEMOD); + STV090x_SETFIELD_Px(reg, ROLLOFF_CONTROL_FIELD, state->rolloff); + STV090x_SETFIELD_Px(reg, MANUAL_ROLLOFF_FIELD, 0x01); + if (STV090x_WRITE_DEMOD(state, DEMOD, reg) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, ERRCTRL1, 0x75) < 0) + goto err; + break; + + case STV090x_DVBS2: + reg = STV090x_READ_DEMOD(state, DMDCFGMD); + STV090x_SETFIELD_Px(reg, DVBS1_ENABLE_FIELD, 1); + STV090x_SETFIELD_Px(reg, DVBS2_ENABLE_FIELD, 0); + if (STV090x_WRITE_DEMOD(state, DMDCFGMD, reg) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, ACLC, 0) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, BCLC, 0) < 0) + goto err; + if (state->frame_len == STV090x_LONG_FRAME) { + reg = STV090x_READ_DEMOD(state, DMDMODCOD); + modcod = STV090x_GETFIELD_Px(reg, DEMOD_MODCOD_FIELD); + pilots = STV090x_GETFIELD_Px(reg, DEMOD_TYPE_FIELD) & 0x01; + aclc = stv090x_optimize_carloop(state, modcod, pilots); + if (modcod <= STV090x_QPSK_910) { + STV090x_WRITE_DEMOD(state, ACLC2S2Q, aclc); + } else if (modcod <= STV090x_8PSK_910) { + if (STV090x_WRITE_DEMOD(state, ACLC2S2Q, 0x2a) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, ACLC2S28, aclc) < 0) + goto err; + } + if ((state->demod_mode == STV090x_SINGLE) && (modcod > STV090x_8PSK_910)) { + if (modcod <= STV090x_16APSK_910) { + if (STV090x_WRITE_DEMOD(state, ACLC2S2Q, 0x2a) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, ACLC2S216A, aclc) < 0) + goto err; + } else { + if (STV090x_WRITE_DEMOD(state, ACLC2S2Q, 0x2a) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, ACLC2S232A, aclc) < 0) + goto err; + } + } + } else { + /*Carrier loop setting for short frame*/ + aclc = stv090x_optimize_carloop_short(state); + if (state->modulation == STV090x_QPSK) { + if (STV090x_WRITE_DEMOD(state, ACLC2S2Q, aclc) < 0) + goto err; + } else if (state->modulation == STV090x_8PSK) { + if (STV090x_WRITE_DEMOD(state, ACLC2S2Q, 0x2a) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, ACLC2S28, aclc) < 0) + goto err; + } else if (state->modulation == STV090x_16APSK) { + if (STV090x_WRITE_DEMOD(state, ACLC2S2Q, 0x2a) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, ACLC2S216A, aclc) < 0) + goto err; + } else if (state->modulation == STV090x_32APSK) { + if (STV090x_WRITE_DEMOD(state, ACLC2S2Q, 0x2a) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, ACLC2S232A, aclc) < 0) + goto err; + } + } + if (state->dev_ver <= 0x11) { + if (state->demod_mode != STV090x_SINGLE) + stv090x_activate_modcod(state); /* link to LDPC after demod LOCK */ + } + STV090x_WRITE_DEMOD(state, ERRCTRL1, 0x67); /* PER */ + break; + + case STV090x_UNKNOWN: + default: + reg = STV090x_READ_DEMOD(state, DMDCFGMD); + STV090x_SETFIELD_Px(reg, DVBS1_ENABLE_FIELD, 1); + STV090x_SETFIELD_Px(reg, DVBS2_ENABLE_FIELD, 1); + if (STV090x_WRITE_DEMOD(state, DMDCFGMD, reg) < 0) + goto err; + break; + } + + f_1 = STV090x_READ_DEMOD(state, CFR2); + f_0 = STV090x_READ_DEMOD(state, CFR1); + reg = STV090x_READ_DEMOD(state, TMGOBS); + rolloff = STV090x_GETFIELD_Px(reg, ROLLOFF_STATUS_FIELD); + + if (state->algo == STV090x_BLIND_SEARCH) { + STV090x_WRITE_DEMOD(state, SFRSTEP, 0x00); + reg = STV090x_READ_DEMOD(state, DMDCFGMD); + STV090x_SETFIELD_Px(reg, SCAN_ENABLE_FIELD, 0x00); + STV090x_SETFIELD_Px(reg, CFR_AUTOSCAN_FIELD, 0x00); + if (STV090x_WRITE_DEMOD(state, DMDCFGMD, reg) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, TMGCFG2, 0x01) < 0) + goto err; + stv090x_set_srate(state, srate); + stv090x_set_max_srate(state, state->mclk, srate); + stv090x_set_min_srate(state, state->mclk, srate); + blind_tune = 1; + } + + if (state->dev_ver >= 0x20) { + if ((state->search_mode == STV090x_SEARCH_DVBS1) || + (state->search_mode == STV090x_SEARCH_DSS) || + (state->search_mode == STV090x_SEARCH_AUTO)) { + + if (STV090x_WRITE_DEMOD(state, VAVSRVIT, 0x0a) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, VITSCALE, 0x00) < 0) + goto err; + } + } + + if (state->dev_ver < 0x20) { + if (STV090x_WRITE_DEMOD(state, CARHDR, 0x08) < 0) + goto err; + } + if (state->dev_ver == 0x10) { + if (STV090x_WRITE_DEMOD(state, CORRELEXP, 0x0a) < 0) + goto err; + } + + if (STV090x_WRITE_DEMOD(state, AGC2REF, 0x38) < 0) + goto err; + + if ((state->dev_ver >= 0x20) || (blind_tune == 1) || (state->srate < 10000000)) { + + if (STV090x_WRITE_DEMOD(state, CFRINIT1, f_1) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, CFRINIT0, f_0) < 0) + goto err; + state->tuner_bw = stv090x_car_width(srate, state->rolloff) + 10000000; + + if ((state->dev_ver >= 0x20) || (blind_tune == 1)) { + + if (state->algo != STV090x_WARM_SEARCH) { + + stv090x_i2c_gate_ctrl(fe, 1); + + if (state->config->tuner_set_bandwidth) + state->config->tuner_set_bandwidth(fe, state->tuner_bw); + + stv090x_i2c_gate_ctrl(fe, 0); + + } + } + if ((state->algo == STV090x_BLIND_SEARCH) || (state->srate < 10000000)) + msleep(50); /* blind search: wait 50ms for SR stabilization */ + else + msleep(5); + + stv090x_get_lock_tmg(state); + + if (!(stv090x_get_dmdlock(state, (state->DemodTimeout / 2)))) { + if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x1f) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, CFRINIT1, f_1) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, CFRINIT0, f_0) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x18) < 0) + goto err; + + i = 0; + + while ((!(stv090x_get_dmdlock(state, (state->DemodTimeout / 2)))) && (i <= 2)) { + + if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x1f) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, CFRINIT1, f_1) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, CFRINIT0, f_0) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x18) < 0) + goto err; + i++; + } + } + + } + + if (state->dev_ver >= 0x20) { + if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x49) < 0) + goto err; + } + if ((state->delsys == STV090x_DVBS1) || (state->delsys == STV090x_DSS)) + stv090x_set_vit_thtracq(state); + + return 0; +err: + dprintk(FE_ERROR, 1, "I/O error"); + return -1; +} + +static int stv090x_get_feclock(struct stv090x_state *state, s32 timeout) +{ + s32 timer = 0, lock = 0, stat; + u32 reg; + + while ((timer < timeout) && (!lock)) { + reg = STV090x_READ_DEMOD(state, DMDSTATE); + stat = STV090x_GETFIELD_Px(reg, HEADER_MODE_FIELD); + + switch (stat) { + case 0: /* searching */ + case 1: /* first PLH detected */ + default: + lock = 0; + break; + + case 2: /* DVB-S2 mode */ + reg = STV090x_READ_DEMOD(state, PDELSTATUS1); + lock = STV090x_GETFIELD_Px(reg, PKTDELIN_LOCK_FIELD); + break; + + case 3: /* DVB-S1/legacy mode */ + reg = STV090x_READ_DEMOD(state, VSTATUSVIT); + lock = STV090x_GETFIELD_Px(reg, LOCKEDVIT_FIELD); + break; + } + if (!lock) { + msleep(10); + timer += 10; + } + } + return lock; +} + +static int stv090x_get_lock(struct stv090x_state *state, s32 timeout_dmd, s32 timeout_fec) +{ + u32 reg; + s32 timer = 0; + int lock; + + lock = stv090x_get_dmdlock(state, timeout_dmd); + if (lock) + lock = stv090x_get_feclock(state, timeout_fec); + + if (lock) { + lock = 0; + + while ((timer < timeout_fec) && (!lock)) { + reg = STV090x_READ_DEMOD(state, TSSTATUS); + lock = STV090x_GETFIELD_Px(reg, TSFIFO_LINEOK_FIELD); + msleep(1); + timer++; + } + } + + return lock; +} + +static int stv090x_set_s2rolloff(struct stv090x_state *state) +{ + s32 rolloff; + u32 reg; + + if (state->dev_ver == 0x10) { + reg = STV090x_READ_DEMOD(state, DEMOD); + STV090x_SETFIELD_Px(reg, MANUAL_ROLLOFF_FIELD, 0x01); + if (STV090x_WRITE_DEMOD(state, DEMOD, reg) < 0) + goto err; + rolloff = STV090x_READ_DEMOD(state, MATSTR1) & 0x03; + reg = STV090x_READ_DEMOD(state, DEMOD); + STV090x_SETFIELD_Px(reg, ROLLOFF_CONTROL_FIELD, reg); + if (STV090x_WRITE_DEMOD(state, DEMOD, reg) < 0) + goto err; + } else { + reg = STV090x_READ_DEMOD(state, DEMOD); + STV090x_SETFIELD_Px(reg, MANUAL_ROLLOFF_FIELD, 0x00); + if (STV090x_WRITE_DEMOD(state, DEMOD, reg) < 0) + goto err; + } + return 0; +err: + dprintk(FE_ERROR, 1, "I/O error"); + return -1; +} + +static enum stv090x_signal_state stv090x_acq_fixs1(struct stv090x_state *state) +{ + s32 srate, f_1, f_2; + enum stv090x_signal_state signal_state = STV090x_NODATA; + u32 reg; + int lock; + + reg = STV090x_READ_DEMOD(state, DMDSTATE); + if (STV090x_GETFIELD_Px(reg, HEADER_MODE_FIELD) == 3) { /* DVB-S mode */ + srate = stv090x_get_srate(state, state->mclk); + srate += stv090x_get_tmgoffst(state, state->srate); + + if (state->algo == STV090x_BLIND_SEARCH) + stv090x_set_srate(state, state->srate); + + stv090x_get_lock_tmg(state); + + f_1 = STV090x_READ_DEMOD(state, CFR2); + f_2 = STV090x_READ_DEMOD(state, CFR1); + + reg = STV090x_READ_DEMOD(state, DMDCFGMD); + STV090x_SETFIELD_Px(reg, CFR_AUTOSCAN_FIELD, 0); + if (STV090x_WRITE_DEMOD(state, DMDCFGMD, reg) < 0) + goto err; + + reg = STV090x_READ_DEMOD(state, DEMOD); + STV090x_SETFIELD_Px(reg, SPECINV_CONTROL_FIELD, STV090x_IQ_SWAP); + if (STV090x_WRITE_DEMOD(state, DEMOD, reg) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x1c) < 0) /* stop demod */ + goto err; + if (STV090x_WRITE_DEMOD(state, CFRINIT1, f_1) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, CFRINIT0, f_2) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x18) < 0) /* warm start trigger */ + goto err; + + if (stv090x_get_lock(state, state->DemodTimeout, state->FecTimeout)) { + lock = 1; + stv090x_get_sig_params(state); + stv090x_optimize_track(state); + } else { + reg = STV090x_READ_DEMOD(state, DEMOD); + STV090x_SETFIELD_Px(reg, SPECINV_CONTROL_FIELD, STV090x_IQ_NORMAL); + if (STV090x_WRITE_DEMOD(state, DEMOD, reg) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x1c) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, CFRINIT1, f_1) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, CFRINIT0, f_2) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x18) < 0) /* warm start trigger */ + goto err; + if (stv090x_get_lock(state, state->DemodTimeout, state->FecTimeout)) { + lock = 1; + signal_state = stv090x_get_sig_params(state); + stv090x_optimize_track(state); + } + } + } else { + lock = 0; + } + + return signal_state; + +err: + dprintk(FE_ERROR, 1, "I/O error"); + return -1; +} + +static enum stv090x_signal_state stv090x_algo(struct stv090x_state *state) +{ + struct dvb_frontend *fe = &state->frontend; + enum stv090x_signal_state signal_state = STV090x_NOCARRIER; + u32 reg; + s32 timeout_dmd = 500, timeout_fec = 50; + int lock = 0, low_sr, no_signal = 0; + + reg = STV090x_READ_DEMOD(state, TSCFGH); + STV090x_SETFIELD_Px(reg, RST_HWARE_FIELD, 1); /* Stop path 1 stream merger */ + if (STV090x_WRITE_DEMOD(state, TSCFGH, reg) < 0) + goto err; + + if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x5c) < 0) /* Demod stop */ + goto err; + + if (state->dev_ver >= 0x20) { + if (STV090x_WRITE_DEMOD(state, CORRELABS, 0x9e) < 0) /* cut 2.0 */ + goto err; + } else { + if (STV090x_WRITE_DEMOD(state, CORRELABS, 0x88) < 0) /* cut 1.x */ + goto err; + } + + stv090x_get_lock_tmg(state); + + if (state->algo == STV090x_BLIND_SEARCH) { + state->tuner_bw = 2 * 36000000; /* wide bw for unknown srate */ + if (STV090x_WRITE_DEMOD(state, TMGCFG2, 0x00) < 0) /* wider srate scan */ + goto err; + stv090x_set_srate(state, 1000000); /* inital srate = 1Msps */ + } else { + /* known srate */ + if (STV090x_WRITE_DEMOD(state, DMDTOM, 0x20) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, TMGCFG, 0xd2) < 0) + goto err; + + if (state->srate >= 10000000) { + if (STV090x_WRITE_DEMOD(state, AGC2REF, 0x38) < 0) /* High SR */ + goto err; + } else { + if (STV090x_WRITE_DEMOD(state, AGC2REF, 0x60) < 0) /* Low SR */ + goto err; + } + + if (state->dev_ver >= 0x20) { + if (STV090x_WRITE_DEMOD(state, KREFTMG, 0x5a) < 0) + goto err; + if (state->algo == STV090x_COLD_SEARCH) + state->tuner_bw = (15 * (stv090x_car_width(state->srate, state->rolloff) + 1000000)) / 10; + else if (state->algo == STV090x_WARM_SEARCH) + state->tuner_bw = stv090x_car_width(state->srate, state->rolloff) + 10000000; + } else { + if (STV090x_WRITE_DEMOD(state, KREFTMG, 0xc1) < 0) + goto err; + state->tuner_bw = (15 * (stv090x_car_width(state->srate, state->rolloff) + 10000000)) / 10; + } + if (STV090x_WRITE_DEMOD(state, TMGCFG2, 0x01) < 0) /* narrow srate scan */ + goto err; + stv090x_set_srate(state, state->srate); + stv090x_set_max_srate(state, state->mclk, state->srate); + stv090x_set_min_srate(state, state->mclk, state->srate); + + if (state->srate >= 10000000) + low_sr = 1; + } + + /* Setup tuner */ + stv090x_i2c_gate_ctrl(fe, 1); + + if (state->config->tuner_set_bbgain) + state->config->tuner_set_bbgain(fe, 10); /* 10dB */ + + if (state->config->tuner_set_frequency) + state->config->tuner_set_frequency(fe, state->frequency); + + if (state->config->tuner_set_bandwidth) + state->config->tuner_set_bandwidth(fe, state->tuner_bw); + + stv090x_i2c_gate_ctrl(fe, 0); + + msleep(50); + + stv090x_i2c_gate_ctrl(fe, 1); + + if (state->config->tuner_get_status) + state->config->tuner_get_status(fe, ®); + + if (reg) + dprintk(FE_DEBUG, 1, "Tuner phase locked"); + else + dprintk(FE_DEBUG, 1, "Tuner unlocked"); + + stv090x_i2c_gate_ctrl(fe, 0); + + reg = STV090x_READ_DEMOD(state, DEMOD); + STV090x_SETFIELD_Px(reg, SPECINV_CONTROL_FIELD, state->inversion); + STV090x_SETFIELD_Px(reg, MANUAL_ROLLOFF_FIELD, 1); + if (STV090x_WRITE_DEMOD(state, DEMOD, reg) < 0) + goto err; + stv090x_delivery_search(state); + if (state->algo == STV090x_BLIND_SEARCH) + stv090x_start_search(state); + + if (state->dev_ver == 0x12) { + reg = STV090x_READ_DEMOD(state, TSCFGH); + STV090x_SETFIELD_Px(reg, RST_HWARE_FIELD, 0); /* release merger reset */ + if (STV090x_WRITE_DEMOD(state, TSCFGH, reg) < 0) + goto err; + msleep(3); + STV090x_SETFIELD_Px(reg, RST_HWARE_FIELD, 1); /* merger reset */ + if (STV090x_WRITE_DEMOD(state, TSCFGH, reg) < 0) + goto err; + STV090x_SETFIELD_Px(reg, RST_HWARE_FIELD, 0); /* release merger reset */ + if (STV090x_WRITE_DEMOD(state, TSCFGH, reg) < 0) + goto err; + } + + if (state->algo == STV090x_BLIND_SEARCH) + lock = stv090x_blind_search(state); + else if (state->algo == STV090x_COLD_SEARCH) + lock = stv090x_get_coldlock(state, timeout_dmd); + else if (state->algo == STV090x_WARM_SEARCH) + lock = stv090x_get_dmdlock(state, timeout_dmd); + + if ((!lock) && (state->algo == STV090x_COLD_SEARCH)) { + if (!low_sr) { + if (stv090x_chk_tmg(state)) + lock = stv090x_sw_algo(state); + } + } + + if (lock) + signal_state = stv090x_get_sig_params(state); + + if ((lock) && (signal_state == STV090x_RANGEOK)) { /* signal within Range */ + stv090x_optimize_track(state); + if (state->dev_ver <= 0x11) { /*workaround for dual DVBS1 cut 1.1 and 1.0 only*/ + if (stv090x_get_std(state) == STV090x_DVBS1) { + msleep(20); + reg = STV090x_READ_DEMOD(state, TSCFGH); + STV090x_SETFIELD_Px(reg, RST_HWARE_FIELD, 0); /* release merger reset */ + if (STV090x_WRITE_DEMOD(state, TSCFGH, reg) < 0) + goto err; + } else { + reg = STV090x_READ_DEMOD(state, TSCFGH); + STV090x_SETFIELD_Px(reg, RST_HWARE_FIELD, 0); /* release merger reset */ + if (STV090x_WRITE_DEMOD(state, TSCFGH, reg) < 0) + goto err; + msleep(3); + STV090x_SETFIELD_Px(reg, RST_HWARE_FIELD, 1); /* merger reset */ + if (STV090x_WRITE_DEMOD(state, TSCFGH, reg) < 0) + goto err; + STV090x_SETFIELD_Px(reg, RST_HWARE_FIELD, 0); /* release merger reset */ + if (STV090x_WRITE_DEMOD(state, TSCFGH, reg) < 0) + goto err; + } + } else if (state->dev_ver == 0x20) { /*cut 2.0 :release TS reset after demod lock and TrackingOptimization*/ + reg = STV090x_READ_DEMOD(state, TSCFGH); + STV090x_SETFIELD_Px(reg, RST_HWARE_FIELD, 0); /* release merger reset */ + if (STV090x_WRITE_DEMOD(state, TSCFGH, reg) < 0) + goto err; + msleep(3); + STV090x_SETFIELD_Px(reg, RST_HWARE_FIELD, 1); /* merger reset */ + if (STV090x_WRITE_DEMOD(state, TSCFGH, reg) < 0) + goto err; + + STV090x_SETFIELD_Px(reg, RST_HWARE_FIELD, 0); /* release merger reset */ + if (STV090x_WRITE_DEMOD(state, TSCFGH, reg) < 0) + goto err; + } + + if (stv090x_get_lock(state, timeout_fec, timeout_fec)) { + lock = 1; + if (state->delsys == STV090x_DVBS2) { + stv090x_set_s2rolloff(state); + if (STV090x_WRITE_DEMOD(state, PDELCTRL2, 0x40) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, PDELCTRL2, 0x00) < 0) /* RESET counter */ + goto err; + if (STV090x_WRITE_DEMOD(state, ERRCTRL1, 0x67) < 0) /* PER */ + goto err; + } else { + if (STV090x_WRITE_DEMOD(state, ERRCTRL1, 0x75) < 0) + goto err; + } + if (STV090x_WRITE_DEMOD(state, FBERCPT4, 0x00) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, ERRCTRL2, 0xc1) < 0) + goto err; + } else { + lock = 0; + signal_state = STV090x_NODATA; + no_signal = stv090x_chk_signal(state); + } + } + if ((signal_state == STV090x_NODATA) && (!no_signal)) { + if (state->dev_ver <= 0x11) { + reg = STV090x_READ_DEMOD(state, DMDSTATE); + if (((STV090x_GETFIELD_Px(reg, HEADER_MODE_FIELD)) == STV090x_DVBS2) && (state->inversion == INVERSION_AUTO)) + signal_state = stv090x_acq_fixs1(state); + } + } + return signal_state; + +err: + dprintk(FE_ERROR, 1, "I/O error"); + return -1; +} + +static enum dvbfe_search stv090x_search(struct dvb_frontend *fe, struct dvb_frontend_parameters *p) +{ + struct stv090x_state *state = fe->demodulator_priv; + struct dtv_frontend_properties *props = &fe->dtv_property_cache; + + state->delsys = props->delivery_system; + state->frequency = p->frequency; + state->srate = p->u.qpsk.symbol_rate; + + if (!stv090x_algo(state)) { + dprintk(FE_DEBUG, 1, "Search success!"); + return DVBFE_ALGO_SEARCH_SUCCESS; + } else { + dprintk(FE_DEBUG, 1, "Search failed!"); + return DVBFE_ALGO_SEARCH_FAILED; + } + + return DVBFE_ALGO_SEARCH_ERROR; +} + +/* FIXME! */ +static int stv090x_read_status(struct dvb_frontend *fe, enum fe_status *status) +{ + struct stv090x_state *state = fe->demodulator_priv; + u32 reg; + u8 search_state; + int locked = 0; + + reg = STV090x_READ_DEMOD(state, DMDSTATE); + search_state = STV090x_GETFIELD_Px(reg, HEADER_MODE_FIELD); + + switch (search_state) { + case 0: /* searching */ + case 1: /* first PLH detected */ + default: + dprintk(FE_DEBUG, 1, "Status: Unlocked (Searching ..)"); + locked = 0; + break; + + case 2: /* DVB-S2 mode */ + dprintk(FE_DEBUG, 1, "Delivery system: DVB-S2"); + reg = STV090x_READ_DEMOD(state, DSTATUS); + if (STV090x_GETFIELD_Px(reg, LOCK_DEFINITIF_FIELD)) { + reg = STV090x_READ_DEMOD(state, TSSTATUS); + if (STV090x_GETFIELD_Px(reg, TSFIFO_LINEOK_FIELD)) { + locked = 1; + *status = FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK; + } + } + break; + + case 3: /* DVB-S1/legacy mode */ + dprintk(FE_DEBUG, 1, "Delivery system: DVB-S"); + reg = STV090x_READ_DEMOD(state, DSTATUS); + if (STV090x_GETFIELD_Px(reg, LOCK_DEFINITIF_FIELD)) { + reg = STV090x_READ_DEMOD(state, VSTATUSVIT); + if (STV090x_GETFIELD_Px(reg, LOCKEDVIT_FIELD)) { + reg = STV090x_READ_DEMOD(state, TSSTATUS); + if (STV090x_GETFIELD_Px(reg, TSFIFO_LINEOK_FIELD)) { + locked = 1; + *status = FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK; + } + } + } + break; + } + + return locked; +} + +static int stv090x_read_per(struct dvb_frontend *fe, u32 *per) +{ + struct stv090x_state *state = fe->demodulator_priv; + + s32 count_4, count_3, count_2, count_1, count_0, count; + u32 reg, h, m, l; + enum fe_status status; + + if (!stv090x_read_status(fe, &status)) { + *per = 1 << 23; /* Max PER */ + } else { + /* Counter 2 */ + reg = STV090x_READ_DEMOD(state, ERRCNT22); + h = STV090x_GETFIELD_Px(reg, ERR_CNT2_FIELD); + + reg = STV090x_READ_DEMOD(state, ERRCNT21); + m = STV090x_GETFIELD_Px(reg, ERR_CNT21_FIELD); + + reg = STV090x_READ_DEMOD(state, ERRCNT20); + l = STV090x_GETFIELD_Px(reg, ERR_CNT20_FIELD); + + *per = ((h << 16) | (m << 8) | l); + + count_4 = STV090x_READ_DEMOD(state, FBERCPT4); + count_3 = STV090x_READ_DEMOD(state, FBERCPT3); + count_2 = STV090x_READ_DEMOD(state, FBERCPT2); + count_1 = STV090x_READ_DEMOD(state, FBERCPT1); + count_0 = STV090x_READ_DEMOD(state, FBERCPT0); + + if ((!count_4) && (!count_3)) { + count = (count_2 & 0xff) << 16; + count |= (count_1 & 0xff) << 8; + count |= count_0 & 0xff; + } else { + count = 1 << 24; + } + if (count == 0) + *per = 1; + } + if (STV090x_WRITE_DEMOD(state, FBERCPT4, 0) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, ERRCTRL2, 0xc1) < 0) + goto err; + + return 0; +err: + dprintk(FE_ERROR, 1, "I/O error"); + return -1; +} + +static int stv090x_table_lookup(const struct stv090x_tab *tab, int max, int val) +{ + int res = 0; + int min = 0, med; + + if (val < tab[min].read) + res = tab[min].real; + else if (val >= tab[max].read) + res = tab[max].real; + else { + while ((max - min) > 1) { + med = (max + min) / 2; + if (val >= tab[min].read && val < tab[med].read) + max = med; + else + min = med; + } + res = ((val - tab[min].read) * + (tab[max].real - tab[min].real) / + (tab[max].read - tab[min].read)) + + tab[min].real; + } + + return res; +} + +static int stv090x_read_signal_strength(struct dvb_frontend *fe, u16 *strength) +{ + struct stv090x_state *state = fe->demodulator_priv; + u32 reg; + s32 agc; + + reg = STV090x_READ_DEMOD(state, AGCIQIN1); + agc = STV090x_GETFIELD_Px(reg, AGCIQ_VALUE_FIELD); + + *strength = stv090x_table_lookup(stv090x_rf_tab, ARRAY_SIZE(stv090x_rf_tab) - 1, agc); + if (agc > stv090x_rf_tab[0].read) + *strength = 5; + else if (agc < stv090x_rf_tab[ARRAY_SIZE(stv090x_rf_tab) - 1].read) + *strength = -100; + + return 0; +} + +static int stv090x_read_cnr(struct dvb_frontend *fe, u16 *cnr) +{ + struct stv090x_state *state = fe->demodulator_priv; + u32 reg_0, reg_1, reg, i; + s32 val_0, val_1, val = 0; + u8 lock_f; + + switch (state->delsys) { + case STV090x_DVBS2: + reg = STV090x_READ_DEMOD(state, DSTATUS); + lock_f = STV090x_GETFIELD_Px(reg, LOCK_DEFINITIF_FIELD); + if (lock_f) { + msleep(5); + for (i = 0; i < 16; i++) { + reg_1 = STV090x_READ_DEMOD(state, NNOSPLHT1); + val_1 = STV090x_GETFIELD_Px(reg_1, NOSPLHT_NORMED_FIELD); + reg_0 = STV090x_READ_DEMOD(state, NNOSPLHT0); + val_0 = STV090x_GETFIELD_Px(reg_1, NOSPLHT_NORMED_FIELD); + val += MAKEWORD16(val_1, val_0); + msleep(1); + } + val /= 16; + *cnr = stv090x_table_lookup(stv090x_s2cn_tab, ARRAY_SIZE(stv090x_s2cn_tab) - 1, val); + if (val < stv090x_s2cn_tab[ARRAY_SIZE(stv090x_s2cn_tab) - 1].read) + *cnr = 1000; + } + break; + + case STV090x_DVBS1: + case STV090x_DSS: + reg = STV090x_READ_DEMOD(state, DSTATUS); + lock_f = STV090x_GETFIELD_Px(reg, LOCK_DEFINITIF_FIELD); + if (lock_f) { + msleep(5); + for (i = 0; i < 16; i++) { + reg_1 = STV090x_READ_DEMOD(state, NOSDATAT1); + val_1 = STV090x_GETFIELD_Px(reg_1, NOSDATAT_UNNORMED_FIELD); + reg_0 = STV090x_READ_DEMOD(state, NOSDATAT0); + val_0 = STV090x_GETFIELD_Px(reg_1, NOSDATAT_UNNORMED_FIELD); + val += MAKEWORD16(val_1, val_0); + msleep(1); + } + val /= 16; + *cnr = stv090x_table_lookup(stv090x_s1cn_tab, ARRAY_SIZE(stv090x_s1cn_tab) - 1, val); + if (val < stv090x_s2cn_tab[ARRAY_SIZE(stv090x_s1cn_tab) - 1].read) + *cnr = 1000; + } + break; + default: + break; + } + + return 0; +} + +static int stv090x_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone) +{ + struct stv090x_state *state = fe->demodulator_priv; + u32 reg; + + reg = STV090x_READ_DEMOD(state, DISTXCTL); + switch (tone) { + case SEC_TONE_ON: + STV090x_SETFIELD_Px(reg, DISTX_MODE_FIELD, 0); + STV090x_SETFIELD_Px(reg, DISEQC_RESET_FIELD, 1); + if (STV090x_WRITE_DEMOD(state, DISTXCTL, reg) < 0) + goto err; + STV090x_SETFIELD_Px(reg, DISEQC_RESET_FIELD, 0); + if (STV090x_WRITE_DEMOD(state, DISTXCTL, reg) < 0) + goto err; + break; + + case SEC_TONE_OFF: + STV090x_SETFIELD_Px(reg, DISTX_MODE_FIELD, 0); + STV090x_SETFIELD_Px(reg, DISEQC_RESET_FIELD, 1); + if (STV090x_WRITE_DEMOD(state, DISTXCTL, reg) < 0) + goto err; + break; + default: + return -EINVAL; + } + + return 0; +err: + dprintk(FE_ERROR, 1, "I/O error"); + return -1; +} + + +static enum dvbfe_algo stv090x_frontend_algo(struct dvb_frontend *fe) +{ + return DVBFE_ALGO_CUSTOM; +} + +static int stv090x_send_diseqc_msg(struct dvb_frontend *fe, struct dvb_diseqc_master_cmd *cmd) +{ + struct stv090x_state *state = fe->demodulator_priv; + u32 reg, idle = 0, fifo_full = 1; + int i; + + reg = STV090x_READ_DEMOD(state, DISTXCTL); + STV090x_SETFIELD_Px(reg, DIS_PRECHARGE_FIELD, 1); + if (STV090x_WRITE_DEMOD(state, DISTXCTL, reg) < 0) + goto err; + + for (i = 0; i < cmd->msg_len; i++) { + + while (fifo_full) { + reg = STV090x_READ_DEMOD(state, DISTXSTATUS); + fifo_full = STV090x_GETFIELD_Px(reg, FIFO_FULL_FIELD); + } + + if (STV090x_WRITE_DEMOD(state, DISTXDATA, cmd->msg[i]) < 0) + goto err; + i++; + } + reg = STV090x_READ_DEMOD(state, DISTXCTL); + STV090x_SETFIELD_Px(reg, DIS_PRECHARGE_FIELD, 0); + if (STV090x_WRITE_DEMOD(state, DISTXCTL, reg) < 0) + goto err; + + i = 0; + + while ((!idle) && (i < 10)) { + reg = STV090x_READ_DEMOD(state, DISTXSTATUS); + idle = STV090x_GETFIELD_Px(reg, TX_IDLE_FIELD); + msleep(10); + i++; + } + + return 0; +err: + dprintk(FE_ERROR, 1, "I/O error"); + return -1; +} + +static int stv090x_recv_slave_reply(struct dvb_frontend *fe, struct dvb_diseqc_slave_reply *reply) +{ + struct stv090x_state *state = fe->demodulator_priv; + u32 reg = 0, i = 0, rx_end = 0; + + while ((rx_end != 1) && (i < 10)) { + msleep(10); + i++; + reg = STV090x_READ_DEMOD(state, DISRX_ST0); + rx_end = STV090x_GETFIELD_Px(reg, RX_END_FIELD); + } + + if (rx_end) { + reply->msg_len = STV090x_GETFIELD_Px(reg, FIFO_BYTENBR_FIELD); + for (i = 0; i < reply->msg_len; i++) + reply->msg[i] = STV090x_READ_DEMOD(state, DISRXDATA); + } + + return 0; +} + +static int stv090x_sleep(struct dvb_frontend *fe) +{ + struct stv090x_state *state = fe->demodulator_priv; + u32 reg; + + dprintk(FE_DEBUG, 1, "Set %s to sleep", + state->device == STV0900 ? "STV0900" : "STV0903"); + + reg = stv090x_read_reg(state, STV090x_SYNTCTRL); + STV090x_SETFIELD(reg, STANDBY_FIELD, 0x01); + if (stv090x_write_reg(state, STV090x_SYNTCTRL, reg) < 0) + goto err; + + return 0; +err: + dprintk(FE_ERROR, 1, "I/O error"); + return -1; +} + +static int stv090x_wakeup(struct dvb_frontend *fe) +{ + struct stv090x_state *state = fe->demodulator_priv; + u32 reg; + + dprintk(FE_DEBUG, 1, "Wake %s from standby", + state->device == STV0900 ? "STV0900" : "STV0903"); + + reg = stv090x_read_reg(state, STV090x_SYNTCTRL); + STV090x_SETFIELD(reg, STANDBY_FIELD, 0x00); + if (stv090x_write_reg(state, STV090x_SYNTCTRL, reg) < 0) + goto err; + + return 0; +err: + dprintk(FE_ERROR, 1, "I/O error"); + return -1; +} + +static void stv090x_release(struct dvb_frontend *fe) +{ + struct stv090x_state *state = fe->demodulator_priv; + + kfree(state); +} + +static int stv090x_ldpc_mode(struct stv090x_state *state, enum stv090x_mode ldpc_mode) +{ + u32 reg; + + switch (ldpc_mode) { + case STV090x_DUAL: + default: + reg = stv090x_read_reg(state, STV090x_GENCFG); + if ((state->demod_mode != STV090x_DUAL) || (STV090x_GETFIELD(reg, DDEMOD_FIELD) != 1)) { + /* follow LDPC default state */ + if (stv090x_write_reg(state, STV090x_GENCFG, reg) < 0) + goto err; + state->demod_mode = STV090x_DUAL; + reg = stv090x_read_reg(state, STV090x_TSTRES0); + STV090x_SETFIELD(reg, FRESFEC_FIELD, 0x1); + if (stv090x_write_reg(state, STV090x_TSTRES0, reg) < 0) + goto err; + STV090x_SETFIELD(reg, FRESFEC_FIELD, 0x0); + if (stv090x_write_reg(state, STV090x_TSTRES0, reg) < 0) + goto err; + } + break; + + case STV090x_SINGLE: + if (state->demod == STV090x_DEMODULATOR_1) { + if (stv090x_write_reg(state, STV090x_GENCFG, 0x06) < 0) /* path 2 */ + goto err; + } else { + if (stv090x_write_reg(state, STV090x_GENCFG, 0x04) < 0) /* path 1 */ + goto err; + } + + reg = stv090x_read_reg(state, STV090x_TSTRES0); + STV090x_SETFIELD(reg, FRESFEC_FIELD, 0x1); + if (stv090x_write_reg(state, STV090x_TSTRES0, reg) < 0) + goto err; + STV090x_SETFIELD(reg, FRESFEC_FIELD, 0x0); + if (stv090x_write_reg(state, STV090x_TSTRES0, reg) < 0) + goto err; + + reg = STV090x_READ_DEMOD(state, PDELCTRL1); + STV090x_SETFIELD_Px(reg, ALGOSWRST_FIELD, 0x01); + if (STV090x_WRITE_DEMOD(state, PDELCTRL1, reg) < 0) + goto err; + STV090x_SETFIELD_Px(reg, ALGOSWRST_FIELD, 0x00); + if (STV090x_WRITE_DEMOD(state, PDELCTRL1, reg) < 0) + goto err; + break; + } + + return 0; +err: + dprintk(FE_ERROR, 1, "I/O error"); + return -1; +} + +/* return (Hz), clk in Hz*/ +static u32 stv090x_get_mclk(struct stv090x_state *state) +{ + const struct stv090x_config *config = state->config; + u32 div, reg; + u8 ratio; + + div = stv090x_read_reg(state, STV090x_NCOARSE); + reg = stv090x_read_reg(state, STV090x_SYNTCTRL); + ratio = STV090x_GETFIELD(reg, SELX1RATIO_FIELD) ? 4 : 6; + + return (div + 1) * config->xtal / ratio; /* kHz */ +} + +static int stv090x_set_mclk(struct stv090x_state *state, u32 mclk, u32 clk) +{ + const struct stv090x_config *config = state->config; + u32 reg, div, clk_sel; + + reg = stv090x_read_reg(state, STV090x_SYNTCTRL); + clk_sel = ((STV090x_GETFIELD(reg, SELX1RATIO_FIELD) == 1) ? 4 : 6); + + div = ((clk_sel * mclk) / config->xtal) - 1; + + reg = stv090x_read_reg(state, STV090x_NCOARSE); + STV090x_SETFIELD(reg, M_DIV_FIELD, div); + if (stv090x_write_reg(state, STV090x_NCOARSE, reg) < 0) + goto err; + + state->mclk = stv090x_get_mclk(state); + + return 0; +err: + dprintk(FE_ERROR, 1, "I/O error"); + return -1; +} + +static int stv090x_set_tspath(struct stv090x_state *state) +{ + u32 reg; + + if (state->dev_ver >= 0x20) { + switch (state->config->ts1_mode) { + case STV090x_TSMODE_PARALLEL_PUNCTURED: + case STV090x_TSMODE_DVBCI: + switch (state->config->ts2_mode) { + case STV090x_TSMODE_SERIAL_PUNCTURED: + case STV090x_TSMODE_SERIAL_CONTINUOUS: + default: + stv090x_write_reg(state, STV090x_TSGENERAL, 0x00); + break; + + case STV090x_TSMODE_PARALLEL_PUNCTURED: + case STV090x_TSMODE_DVBCI: + if (stv090x_write_reg(state, STV090x_TSGENERAL, 0x06) < 0) /* Mux'd stream mode */ + goto err; + reg = stv090x_read_reg(state, STV090x_P1_TSCFGM); + STV090x_SETFIELD_Px(reg, TSFIFO_MANSPEED_FIELD, 3); + if (stv090x_write_reg(state, STV090x_P1_TSCFGM, reg) < 0) + goto err; + reg = stv090x_read_reg(state, STV090x_P2_TSCFGM); + STV090x_SETFIELD_Px(reg, TSFIFO_MANSPEED_FIELD, 3); + if (stv090x_write_reg(state, STV090x_P2_TSCFGM, reg) < 0) + goto err; + if (stv090x_write_reg(state, STV090x_P1_TSSPEED, 0x14) < 0) + goto err; + if (stv090x_write_reg(state, STV090x_P2_TSSPEED, 0x28) < 0) + goto err; + break; + } + break; + + case STV090x_TSMODE_SERIAL_PUNCTURED: + case STV090x_TSMODE_SERIAL_CONTINUOUS: + default: + switch (state->config->ts2_mode) { + case STV090x_TSMODE_SERIAL_PUNCTURED: + case STV090x_TSMODE_SERIAL_CONTINUOUS: + default: + if (stv090x_write_reg(state, STV090x_TSGENERAL, 0x0c) < 0) + goto err; + break; + + case STV090x_TSMODE_PARALLEL_PUNCTURED: + case STV090x_TSMODE_DVBCI: + if (stv090x_write_reg(state, STV090x_TSGENERAL, 0x0a) < 0) + goto err; + break; + } + break; + } + } else { + switch (state->config->ts1_mode) { + case STV090x_TSMODE_PARALLEL_PUNCTURED: + case STV090x_TSMODE_DVBCI: + switch (state->config->ts2_mode) { + case STV090x_TSMODE_SERIAL_PUNCTURED: + case STV090x_TSMODE_SERIAL_CONTINUOUS: + default: +#if 0 + stv090x_write_reg(state, STV090x_TSGENERAL1X, 0x10); +#endif + break; + + case STV090x_TSMODE_PARALLEL_PUNCTURED: + case STV090x_TSMODE_DVBCI: +#if 0 + stv090x_write_reg(state, STV090x_TSGENERAL1X, 0x16); +#endif + reg = stv090x_read_reg(state, STV090x_P1_TSCFGM); + STV090x_SETFIELD_Px(reg, TSFIFO_MANSPEED_FIELD, 3); + if (stv090x_write_reg(state, STV090x_P1_TSCFGM, reg) < 0) + goto err; + reg = stv090x_read_reg(state, STV090x_P1_TSCFGM); + STV090x_SETFIELD_Px(reg, TSFIFO_MANSPEED_FIELD, 0); + if (stv090x_write_reg(state, STV090x_P1_TSCFGM, reg) < 0) + goto err; + if (stv090x_write_reg(state, STV090x_P1_TSSPEED, 0x14) < 0) + goto err; + if (stv090x_write_reg(state, STV090x_P2_TSSPEED, 0x28) < 0) + goto err; + break; + } + break; + + case STV090x_TSMODE_SERIAL_PUNCTURED: + case STV090x_TSMODE_SERIAL_CONTINUOUS: + default: + switch (state->config->ts2_mode) { + case STV090x_TSMODE_SERIAL_PUNCTURED: + case STV090x_TSMODE_SERIAL_CONTINUOUS: + default: +#if 0 + stv090x_write_reg(state, STV090x_TSGENERAL1X, 0x14); +#endif + break; + + case STV090x_TSMODE_PARALLEL_PUNCTURED: + case STV090x_TSMODE_DVBCI: +#if 0 + stv090x_write_reg(state, STV090x_TSGENERAL1X, 0x12); +#endif + break; + } + break; + } + } + + switch (state->config->ts1_mode) { + case STV090x_TSMODE_PARALLEL_PUNCTURED: + reg = stv090x_read_reg(state, STV090x_P1_TSCFGH); + STV090x_SETFIELD_Px(reg, TSFIFO_SERIAL_FIELD, 0x00); + STV090x_SETFIELD_Px(reg, TSFIFO_DVBCI_FIELD, 0x00); + if (stv090x_write_reg(state, STV090x_P1_TSCFGH, reg) < 0) + goto err; + break; + + case STV090x_TSMODE_DVBCI: + reg = stv090x_read_reg(state, STV090x_P1_TSCFGH); + STV090x_SETFIELD_Px(reg, TSFIFO_SERIAL_FIELD, 0x00); + STV090x_SETFIELD_Px(reg, TSFIFO_DVBCI_FIELD, 0x01); + if (stv090x_write_reg(state, STV090x_P1_TSCFGH, reg) < 0) + goto err; + break; + + case STV090x_TSMODE_SERIAL_PUNCTURED: + reg = stv090x_read_reg(state, STV090x_P1_TSCFGH); + STV090x_SETFIELD_Px(reg, TSFIFO_SERIAL_FIELD, 0x01); + STV090x_SETFIELD_Px(reg, TSFIFO_DVBCI_FIELD, 0x00); + if (stv090x_write_reg(state, STV090x_P1_TSCFGH, reg) < 0) + goto err; + break; + + case STV090x_TSMODE_SERIAL_CONTINUOUS: + reg = stv090x_read_reg(state, STV090x_P1_TSCFGH); + STV090x_SETFIELD_Px(reg, TSFIFO_SERIAL_FIELD, 0x01); + STV090x_SETFIELD_Px(reg, TSFIFO_DVBCI_FIELD, 0x01); + if (stv090x_write_reg(state, STV090x_P1_TSCFGH, reg) < 0) + goto err; + break; + + default: + break; + } + + switch (state->config->ts2_mode) { + case STV090x_TSMODE_PARALLEL_PUNCTURED: + reg = stv090x_read_reg(state, STV090x_P1_TSCFGH); + STV090x_SETFIELD_Px(reg, TSFIFO_SERIAL_FIELD, 0x00); + STV090x_SETFIELD_Px(reg, TSFIFO_DVBCI_FIELD, 0x00); + if (stv090x_write_reg(state, STV090x_P1_TSCFGH, reg) < 0) + goto err; + break; + + case STV090x_TSMODE_DVBCI: + reg = stv090x_read_reg(state, STV090x_P1_TSCFGH); + STV090x_SETFIELD_Px(reg, TSFIFO_SERIAL_FIELD, 0x00); + STV090x_SETFIELD_Px(reg, TSFIFO_DVBCI_FIELD, 0x01); + if (stv090x_write_reg(state, STV090x_P1_TSCFGH, reg) < 0) + goto err; + break; + + case STV090x_TSMODE_SERIAL_PUNCTURED: + reg = stv090x_read_reg(state, STV090x_P1_TSCFGH); + STV090x_SETFIELD_Px(reg, TSFIFO_SERIAL_FIELD, 0x01); + STV090x_SETFIELD_Px(reg, TSFIFO_DVBCI_FIELD, 0x00); + if (stv090x_write_reg(state, STV090x_P1_TSCFGH, reg) < 0) + goto err; + break; + + case STV090x_TSMODE_SERIAL_CONTINUOUS: + reg = stv090x_read_reg(state, STV090x_P1_TSCFGH); + STV090x_SETFIELD_Px(reg, TSFIFO_SERIAL_FIELD, 0x01); + STV090x_SETFIELD_Px(reg, TSFIFO_DVBCI_FIELD, 0x01); + if (stv090x_write_reg(state, STV090x_P1_TSCFGH, reg) < 0) + goto err; + break; + + default: + break; + } + reg = stv090x_read_reg(state, STV090x_P2_TSCFGH); + STV090x_SETFIELD_Px(reg, RST_HWARE_FIELD, 0x01); + if (stv090x_write_reg(state, STV090x_P2_TSCFGH, reg) < 0) + goto err; + STV090x_SETFIELD_Px(reg, RST_HWARE_FIELD, 0x00); + if (stv090x_write_reg(state, STV090x_P2_TSCFGH, reg) < 0) + goto err; + + reg = stv090x_read_reg(state, STV090x_P1_TSCFGH); + STV090x_SETFIELD_Px(reg, RST_HWARE_FIELD, 0x01); + if (stv090x_write_reg(state, STV090x_P1_TSCFGH, reg) < 0) + goto err; + STV090x_SETFIELD_Px(reg, RST_HWARE_FIELD, 0x00); + if (stv090x_write_reg(state, STV090x_P1_TSCFGH, reg) < 0) + goto err; + + return 0; +err: + dprintk(FE_ERROR, 1, "I/O error"); + return -1; +} + +static int stv090x_init(struct dvb_frontend *fe) +{ + struct stv090x_state *state = fe->demodulator_priv; + const struct stv090x_config *config = state->config; + u32 reg; + + stv090x_ldpc_mode(state, state->demod_mode); + + reg = STV090x_READ_DEMOD(state, TNRCFG2); + STV090x_SETFIELD_Px(reg, TUN_IQSWAP_FIELD, state->inversion); + if (STV090x_WRITE_DEMOD(state, TNRCFG2, reg) < 0) + goto err; + reg = STV090x_READ_DEMOD(state, DEMOD); + STV090x_SETFIELD_Px(reg, ROLLOFF_CONTROL_FIELD, state->rolloff); + if (STV090x_WRITE_DEMOD(state, DEMOD, reg) < 0) + goto err; + + stv090x_i2c_gate_ctrl(fe, 1); + + if (config->tuner_init) + config->tuner_init(fe); + + stv090x_i2c_gate_ctrl(fe, 0); + + stv090x_set_tspath(state); + + return 0; +err: + dprintk(FE_ERROR, 1, "I/O error"); + return -1; +} + +static int stv090x_setup(struct dvb_frontend *fe) +{ + struct stv090x_state *state = fe->demodulator_priv; + const struct stv090x_config *config = state->config; + const struct stv090x_reg *stv090x_initval = NULL; + const struct stv090x_reg *stv090x_cut20_val = NULL; + unsigned long t1_size = 0, t2_size = 0; + + int i; + + if (state->device == STV0900) { + dprintk(FE_DEBUG, 1, "Initializing STV0900"); + stv090x_initval = stv0900_initval; + t1_size = ARRAY_SIZE(stv0900_initval); + stv090x_cut20_val = stv0900_cut20_val; + t2_size = ARRAY_SIZE(stv0900_cut20_val); + } else if (state->device == STV0903) { + dprintk(FE_DEBUG, 1, "Initializing STV0903"); + stv090x_initval = stv0903_initval; + t1_size = ARRAY_SIZE(stv0903_initval); + stv090x_cut20_val = stv0903_cut20_val; + t2_size = ARRAY_SIZE(stv0903_cut20_val); + } +#if 0 + /* write defval to image map */ + for (i = 0; i < (ARRAY_SIZE(stv090x_defval)); i++) { + dprintk(FE_DEBUG, 1, "Setting up defaults"); + if (stv090x_write_reg(state, stv090x_defval[i].addr, stv090x_defval[i].data) < 0) + goto err; + } + /* check register fields */ + + reg = STV090x_READ_DEMOD(state, TNRCFG); + STV090x_SETFIELD_Px(reg, TUN_TYPE, 6); + STV090x_WRITE_DEMOD(state, TNRCFG, reg); +#endif + + /* STV090x init */ + if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x5c) < 0) /* Stop Demod */ + goto err; + + msleep(5); + + if (STV090x_WRITE_DEMOD(state, TNRCFG, 0x6c) < 0) /* check register ! (No Tuner Mode) */ + goto err; + + if (STV090x_WRITE_DEMOD(state, I2CRPT, 0x00) < 0) /* repeater OFF */ + goto err; + + if (stv090x_write_reg(state, STV090x_NCOARSE, 0x13) < 0) /* set PLL divider */ + goto err; + msleep(5); + if (stv090x_write_reg(state, STV090x_I2CCFG, 0x08) < 0) /* 1/41 oversampling */ + goto err; + if (stv090x_write_reg(state, STV090x_SYNTCTRL, 0x20 | config->clk_mode) < 0) /* enable PLL */ + goto err; + msleep(5); + + /* write initval */ + for (i = 0; i < t1_size; i++) { + dprintk(FE_DEBUG, 1, "Setting up initial values"); + if (stv090x_write_reg(state, stv090x_initval[i].addr, stv090x_initval[i].data) < 0) + goto err; + } + + if (state->dev_ver >= 0x20) { + if (stv090x_write_reg(state, STV090x_TSGENERAL, 0x0c) < 0) + goto err; + + /* write cut20_val*/ + dprintk(FE_DEBUG, 1, "Setting up Cut 2.0 initial values"); + for (i = 0; i < t2_size; i++) { + if (stv090x_write_reg(state, stv090x_cut20_val[i].addr, stv090x_cut20_val[i].data) < 0) + goto err; + } + } + + if (stv090x_write_reg(state, STV090x_TSTRES0, 0x80) < 0) + goto err; + if (stv090x_write_reg(state, STV090x_TSTRES0, 0x00) < 0) + goto err; + + stv090x_set_mclk(state, 135000000, config->xtal); /* 135 Mhz */ + msleep(5); + if (stv090x_write_reg(state, STV090x_SYNTCTRL, 0x20 | config->clk_mode) < 0) + goto err; + stv090x_get_mclk(state); + + return 0; +err: + dprintk(FE_ERROR, 1, "I/O error"); + return -1; +} + +static struct dvb_frontend_ops stv090x_ops = { + + .info = { + .name = "STV090x Multistandard", + }, + + .release = stv090x_release, + .init = stv090x_init, + + .sleep = stv090x_sleep, + .get_frontend_algo = stv090x_frontend_algo, + + .i2c_gate_ctrl = stv090x_i2c_gate_ctrl, + + .diseqc_send_master_cmd = stv090x_send_diseqc_msg, + .diseqc_recv_slave_reply = stv090x_recv_slave_reply, + .set_tone = stv090x_set_tone, + + .search = stv090x_search, + .read_status = stv090x_read_status, + .read_ber = stv090x_read_per, + .read_signal_strength = stv090x_read_signal_strength, + .read_snr = stv090x_read_cnr +}; + + +struct dvb_frontend *stv090x_attach(const struct stv090x_config *config, + struct i2c_adapter *i2c, + enum stv090x_demodulator demod) +{ + struct stv090x_state *state = NULL; + + state = kzalloc(sizeof (struct stv090x_state), GFP_KERNEL); + if (state == NULL) + goto error; + + state->verbose = &verbose; + state->config = config; + state->i2c = i2c; + state->frontend.ops = stv090x_ops; + state->frontend.demodulator_priv = state; + state->demod_mode = config->demod_mode; /* Single or Dual mode */ + state->device = config->device; + state->rolloff = 35; /* default */ + + if (state->demod == STV090x_DEMODULATOR_0) + mutex_init(&demod_lock); + + if (stv090x_sleep(&state->frontend) < 0) { + dprintk(FE_ERROR, 1, "Error putting device to sleep"); + goto error; + } + + if (stv090x_setup(&state->frontend) < 0) { + dprintk(FE_ERROR, 1, "Error setting up device"); + goto error; + } + if (stv090x_wakeup(&state->frontend) < 0) { + dprintk(FE_ERROR, 1, "Error waking device"); + goto error; + } + state->dev_ver = stv090x_read_reg(state, STV090x_MID); + + dprintk(FE_ERROR, 1, "Attaching %s demodulator(%d) Cut=0x%02x\n", + state->device == STV0900 ? "STV0900" : "STV0903", + demod, + state->dev_ver); + + return &state->frontend; + +error: + kfree(state); + return NULL; +} +EXPORT_SYMBOL(stv090x_attach); +MODULE_PARM_DESC(verbose, "Set Verbosity level"); +MODULE_AUTHOR("Manu Abraham"); +MODULE_DESCRIPTION("STV090x Multi-Std Broadcast frontend"); +MODULE_LICENSE("GPL"); diff --git a/linux/drivers/media/dvb/frontends/stv090x.h b/linux/drivers/media/dvb/frontends/stv090x.h new file mode 100644 index 000000000..d1cc36985 --- /dev/null +++ b/linux/drivers/media/dvb/frontends/stv090x.h @@ -0,0 +1,109 @@ +/* + STV0900/0903 Multistandard Broadcast Frontend driver + Copyright (C) Manu Abraham + + Copyright (C) ST Microelectronics + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __STV090x_H +#define __STV090x_H + +enum stv090x_demodulator { + STV090x_DEMODULATOR_0 = 1, + STV090x_DEMODULATOR_1 +}; + +enum stv090x_device { + STV0903 = 0, + STV0900, +}; + +enum stv090x_mode { + STV090x_DUAL = 0, + STV090x_SINGLE +}; + +enum stv090x_tsmode { + STV090x_TSMODE_SERIAL_PUNCTURED = 1, + STV090x_TSMODE_SERIAL_CONTINUOUS, + STV090x_TSMODE_PARALLEL_PUNCTURED, + STV090x_TSMODE_DVBCI +}; + +enum stv090x_clkmode { + STV090x_CLK_INT = 0, /* Clk i/p = CLKI */ + STV090x_CLK_EXT = 2 /* Clk i/p = XTALI */ +}; + +struct stv090x_config { + enum stv090x_device device; + enum stv090x_mode demod_mode; + enum stv090x_clkmode clk_mode; + + u32 xtal; /* default: 8000000 */ + u8 address; /* default: 0x68 */ + + u32 ref_clk; /* default: 16000000 FIXME to tuner config */ + + u8 ts1_mode; + u8 ts2_mode; +#if 0 + int (*tuner_init) (struct dvb_frontend *fe); + int (*tuner_set_frequency) (struct dvb_frontend *fe, u32 frequency); + int (*tuner_get_frequency) (struct dvb_frontend *fe, u32 *frequency); + int (*tuner_set_bandwidth) (struct dvb_frontend *fe, u32 bandwidth); + int (*tuner_get_bandwidth) (struct dvb_frontend *fe, u32 *bandwidth); + int (*tuner_set_refclock) (struct dvb_frontend *fe, u32 refclk); +#endif + + int (*tuner_init) (struct dvb_frontend *fe); + int (*tuner_set_mode) (struct dvb_frontend *fe, enum tuner_mode mode); + int (*tuner_set_frequency) (struct dvb_frontend *fe, u32 frequency); + int (*tuner_get_frequency) (struct dvb_frontend *fe, u32 *frequency); + int (*tuner_set_bandwidth) (struct dvb_frontend *fe, u32 bandwidth); + int (*tuner_get_bandwidth) (struct dvb_frontend *fe, u32 *bandwidth); + int (*tuner_set_bbgain) (struct dvb_frontend *fe, u32 gain); + int (*tuner_get_bbgain) (struct dvb_frontend *fe, u32 *gain); + int (*tuner_set_refclk) (struct dvb_frontend *fe, u32 refclk); + int (*tuner_get_status) (struct dvb_frontend *fe, u32 *status); +}; + +#if defined(CONFIG_DVB_STV090x) || (defined(CONFIG_DVB_STV090x_MODULE) && defined(MODULE)) + +extern struct dvb_frontend *stv090x_attach(const struct stv090x_config *config, + struct i2c_adapter *i2c, + enum stv090x_demodulator demod); +#else + +static inline struct dvb_frontend *stv090x_attach(const struct stv090x_config *config, + struct i2c_adapter *i2c, + enum stv090x_demodulator demod) +{ + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); + return NULL; +} + +static inline struct dvb_frontend *stv090x_attach(const struct stv090x_config* config, + struct i2c_adapter *i2c, + enum stv090x_demodulator demod) +{ + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); + return NULL; +} +#endif /* CONFIG_DVB_STV090x */ + +#endif /* __STV090x_H */ diff --git a/linux/drivers/media/dvb/frontends/stv090x_priv.h b/linux/drivers/media/dvb/frontends/stv090x_priv.h new file mode 100644 index 000000000..9d536226e --- /dev/null +++ b/linux/drivers/media/dvb/frontends/stv090x_priv.h @@ -0,0 +1,274 @@ +/* + STV0900/0903 Multistandard Broadcast Frontend driver + Copyright (C) Manu Abraham + + Copyright (C) ST Microelectronics + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __STV090x_PRIV_H +#define __STV090x_PRIV_H + +#include "dvb_frontend.h" + +#define FE_ERROR 0 +#define FE_NOTICE 1 +#define FE_INFO 2 +#define FE_DEBUG 3 +#define FE_DEBUGREG 4 + +#define dprintk(__y, __z, format, arg...) do { \ + if (__z) { \ + if ((verbose > FE_ERROR) && (verbose > __y)) \ + printk(KERN_ERR "%s: " format "\n", __func__ , ##arg); \ + else if ((verbose > FE_NOTICE) && (verbose > __y)) \ + printk(KERN_NOTICE "%s: " format "\n", __func__ , ##arg); \ + else if ((verbose > FE_INFO) && (verbose > __y)) \ + printk(KERN_INFO "%s: " format "\n", __func__ , ##arg); \ + else if ((verbose > FE_DEBUG) && (verbose > __y)) \ + printk(KERN_DEBUG "%s: " format "\n", __func__ , ##arg); \ + } else { \ + if (verbose > __y) \ + printk(format, ##arg); \ + } \ +} while (0) + +#define STV090x_READ_DEMOD(__state, __reg) (( \ + (__state)->demod == STV090x_DEMODULATOR_1) ? \ + stv090x_read_reg(__state, STV090x_P2_##__reg) : \ + stv090x_read_reg(__state, STV090x_P1_##__reg)) + +#define STV090x_WRITE_DEMOD(__state, __reg, __data) (( \ + (__state)->demod == STV090x_DEMODULATOR_1) ? \ + stv090x_write_reg(__state, STV090x_P2_##__reg, __data) :\ + stv090x_write_reg(__state, STV090x_P1_##__reg, __data)) + +#define STV090x_ADDR_OFFST(__state, __x) (( \ + (__state->demod) == STV090x_DEMODULATOR_1) ? \ + STV090x_P1_##__x : \ + STV090x_P2_##__x) + + +#define STV090x_SETFIELD(mask, bitf, val) (mask = (mask & (~(((1 << STV090x_WIDTH_##bitf) - 1) <<\ + STV090x_OFFST_##bitf))) | \ + (val << STV090x_OFFST_##bitf)) + +#define STV090x_GETFIELD(val, bitf) ((val >> STV090x_OFFST_##bitf) & ((1 << STV090x_WIDTH_##bitf) - 1)) + + +#define STV090x_SETFIELD_Px(mask, bitf, val) (mask = (mask & (~(((1 << STV090x_WIDTH_Px_##bitf) - 1) <<\ + STV090x_OFFST_Px_##bitf))) | \ + (val << STV090x_OFFST_Px_##bitf)) + +#define STV090x_GETFIELD_Px(val, bitf) ((val >> STV090x_OFFST_Px_##bitf) & ((1 << STV090x_WIDTH_Px_##bitf) - 1)) + +#define MAKEWORD16(__a, __b) (((__a) << 8) | (__b)) + +#define STV090x_SEARCH_AGC2_TH 700 + +enum stv090x_signal_state { + STV090x_NOCARRIER, + STV090x_NODATA, + STV090x_DATAOK, + STV090x_RANGEOK, + STV090x_OUTOFRANGE +}; + +enum stv090x_fec { + STV090x_PR12 = 0, + STV090x_PR23, + STV090x_PR34, + STV090x_PR45, + STV090x_PR56, + STV090x_PR67, + STV090x_PR78, + STV090x_PR89, + STV090x_PR910, + STV090x_PRERR +}; + +enum stv090x_modulation { + STV090x_QPSK, + STV090x_8PSK, + STV090x_16APSK, + STV090x_32APSK, + STV090x_UNKNOWN +}; + +enum stv090x_frame { + STV090x_LONG_FRAME, + STV090x_SHORT_FRAME +}; + +enum stv090x_pilot { + STV090x_PILOTS_OFF, + STV090x_PILOTS_ON +}; + +enum stv090x_rolloff { + STV090x_RO_35, + STV090x_RO_25, + STV090x_RO_20 +}; + +enum stv090x_inversion { + STV090x_IQ_AUTO, + STV090x_IQ_NORMAL, + STV090x_IQ_SWAP +}; + +enum stv090x_modcod { + STV090x_DUMMY_PLF = 0, + STV090x_QPSK_14, + STV090x_QPSK_13, + STV090x_QPSK_25, + STV090x_QPSK_12, + STV090x_QPSK_35, + STV090x_QPSK_23, + STV090x_QPSK_34, + STV090x_QPSK_45, + STV090x_QPSK_56, + STV090x_QPSK_89, + STV090x_QPSK_910, + STV090x_8PSK_35, + STV090x_8PSK_23, + STV090x_8PSK_34, + STV090x_8PSK_56, + STV090x_8PSK_89, + STV090x_8PSK_910, + STV090x_16APSK_23, + STV090x_16APSK_34, + STV090x_16APSK_45, + STV090x_16APSK_56, + STV090x_16APSK_89, + STV090x_16APSK_910, + STV090x_32APSK_34, + STV090x_32APSK_45, + STV090x_32APSK_56, + STV090x_32APSK_89, + STV090x_32APSK_910, + STV090x_MODCODE_UNKNOWN +}; + +enum stv090x_search { + STV090x_SEARCH_DSS = 0, + STV090x_SEARCH_DVBS1, + STV090x_SEARCH_DVBS2, + STV090x_SEARCH_AUTO +}; + +enum stv090x_algo { + STV090x_BLIND_SEARCH, + STV090x_COLD_SEARCH, + STV090x_WARM_SEARCH +}; + +enum stv090x_delsys { + STV090x_ERROR = 0, + STV090x_DVBS1 = 1, + STV090x_DVBS2, + STV090x_DSS +}; + +struct stv090x_long_frame_crloop { + enum stv090x_modcod modcod; + + u8 crl_pilots_on_2; + u8 crl_pilots_off_2; + u8 crl_pilots_on_5; + u8 crl_pilots_off_5; + u8 crl_pilots_on_10; + u8 crl_pilots_off_10; + u8 crl_pilots_on_20; + u8 crl_pilots_off_20; + u8 crl_pilots_on_30; + u8 crl_pilots_off_30; +}; + +struct stv090x_short_frame_crloop { + enum stv090x_modulation modulation; + + u8 crl_cut12_2; /* Cut 1.2, SR <= 3M */ + u8 crl_cut20_2; /* Cut 2.0, SR < 3M */ + u8 crl_cut12_5; /* Cut 1.2, 3 < SR <= 7M */ + u8 crl_cut20_5; /* Cut 2.0, 3 < SR <= 7M */ + u8 crl_cut12_10; /* Cut 1.2, 7 < SR <= 15M */ + u8 crl_cut20_10; /* Cut 2.0, 7 < SR <= 15M */ + u8 crl_cut12_20; /* Cut 1.2, 10 < SR <= 25M */ + u8 crl_cut20_20; /* Cut 2.0, 10 < SR <= 25M */ + u8 crl_cut12_30; /* Cut 1.2, 25 < SR <= 45M */ + u8 crl_cut20_30; /* Cut 2.0, 10 < SR <= 45M */ +}; + + +struct stv090x_short_frame_vsmod_crloop { + enum stv090x_modulation modulation; + + u8 crl_2; /* < 3M */ + u8 crl_5; /* 3 < SR <= 7M */ + u8 crl_10; /* 7 < SR <= 15M */ + u8 crl_20; /* 10 < SR <= 25M */ + u8 crl_30; /* 10 < SR <= 45M */ +}; + +struct stv090x_reg { + u16 addr; + u8 data; +}; + +struct stv090x_tab { + s32 real; + s32 read; +}; + +struct stv090x_state { + enum stv090x_device device; + enum stv090x_demodulator demod; + enum stv090x_mode demod_mode; + u32 dev_ver; + + struct i2c_adapter *i2c; + const struct stv090x_config *config; + struct dvb_frontend frontend; + + u32 *verbose; /* Cached module verbosity */ + + enum stv090x_delsys delsys; + enum stv090x_fec fec; + enum stv090x_modulation modulation; + enum stv090x_modcod modcod; + enum stv090x_search search_mode; + enum stv090x_frame frame_len; + enum stv090x_pilot pilots; + enum stv090x_rolloff rolloff; + enum stv090x_inversion inversion; + enum stv090x_algo algo; + + u32 frequency; + u32 srate; + + s32 mclk; /* Masterclock Divider factor */ + s32 tuner_bw; + + u32 tuner_refclk; + + s32 search_range; + + s32 DemodTimeout; + s32 FecTimeout; +}; + +#endif /* __STV090x_PRIV_H */ diff --git a/linux/drivers/media/dvb/frontends/stv090x_reg.h b/linux/drivers/media/dvb/frontends/stv090x_reg.h new file mode 100644 index 000000000..b59eca953 --- /dev/null +++ b/linux/drivers/media/dvb/frontends/stv090x_reg.h @@ -0,0 +1,2300 @@ +/* + STV0900/0903 Multistandard Broadcast Frontend driver + Copyright (C) Manu Abraham + + Copyright (C) ST Microelectronics + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __STV090x_REG_H +#define __STV090x_REG_H + +#define STV090x_MID 0xf100 +#define STV090x_OFFST_MCHIP_IDENT_FIELD 4 +#define STV090x_WIDTH_MCHIP_IDENT_FIELD 4 +#define STV090x_OFFST_MRELEASE_FIELD 0 +#define STV090x_WIDTH_MRELEASE_FIELD 4 + +#define STV090x_DACR1 0xf113 +#define STV090x_OFFST_DACR1_MODE_FIELD 5 +#define STV090x_WIDTH_DACR1_MODE_FIELD 3 +#define STV090x_OFFST_DACR1_VALUE_FIELD 0 +#define STV090x_WIDTH_DACR1_VALUE_FIELD 4 + +#define STV090x_DACR2 0xf114 +#define STV090x_OFFST_DACR2_VALUE_FIELD 0 +#define STV090x_WIDTH_DACR2_VALUE_FIELD 8 + +#define STV090x_OUTCFG 0xf11c +#define STV090x_OFFST_OUTSERRS1_HZ_FIELD 6 +#define STV090x_WIDTH_OUTSERRS1_HZ_FIELD 1 +#define STV090x_OFFST_OUTSERRS2_HZ_FIELD 5 +#define STV090x_WIDTH_OUTSERRS2_HZ_FIELD 1 +#define STV090x_OFFST_OUTSERRS3_HZ_FIELD 4 +#define STV090x_WIDTH_OUTPARRS3_HZ_FIELD 1 +#define STV090x_OFFST_OUTPARRS3_HZ_FIELD 3 +#define STV090x_WIDTH_OUTPARRS3_HZ_FIELD 1 + +#define STV090x_IRQSTATUS3 0xf120 +#define STV090x_OFFST_SPLL_LOCK_FIELD 5 +#define STV090x_WIDTH_SPLL_LOCK_FIELD 1 +#define STV090x_OFFST_SSTREAM_LCK_3_FIELD 4 +#define STV090x_WIDTH_SSTREAM_LCK_3_FIELD 1 +#define STV090x_OFFST_SSTREAM_LCK_2_FIELD 3 +#define STV090x_WIDTH_SSTREAM_LCK_2_FIELD 1 +#define STV090x_OFFST_SSTREAM_LCK_1_FIELD 2 +#define STV090x_WIDTH_SSTREAM_LCK_1_FIELD 1 +#define STV090x_OFFST_SDVBS1_PRF_2_FIELD 1 +#define STV090x_WIDTH_SDVBS1_PRF_2_FIELD 1 +#define STV090x_OFFST_SDVBS1_PRF_1_FIELD 0 +#define STV090x_WIDTH_SDVBS1_PRF_1_FIELD 1 + +#define STV090x_IRQSTATUS2 0xf121 +#define STV090x_OFFST_SSPY_ENDSIM_3_FIELD 7 +#define STV090x_WIDTH_SSPY_ENDSIM_3_FIELD 1 +#define STV090x_OFFST_SSPY_ENDSIM_2_FIELD 6 +#define STV090x_WIDTH_SSPY_ENDSIM_2_FIELD 1 +#define STV090x_OFFST_SSPY_ENDSIM_1_FIELD 5 +#define STV090x_WIDTH_SSPY_ENDSIM_1_FIELD 1 +#define STV090x_OFFST_SPKTDEL_ERROR_2_FIELD 4 +#define STV090x_WIDTH_SPKTDEL_ERROR_2_FIELD 1 +#define STV090x_OFFST_SPKTDEL_LOCKB_2_FIELD 3 +#define STV090x_WIDTH_SPKTDEL_LOCKB_2_FIELD 1 +#define STV090x_OFFST_SPKTDEL_LOCK_2_FIELD 2 +#define STV090x_WIDTH_SPKTDEL_LOCK_2_FIELD 1 +#define STV090x_OFFST_SPKTDEL_ERROR_1_FIELD 1 +#define STV090x_WIDTH_SPKTDEL_ERROR_1_FIELD 1 +#define STV090x_OFFST_SPKTDEL_LOCKB_1_FIELD 0 +#define STV090x_WIDTH_SPKTDEL_LOCKB_1_FIELD 1 + +#define STV090x_IRQSTATUS1 0xf122 +#define STV090x_OFFST_SPKTDEL_LOCK_1_FIELD 7 +#define STV090x_WIDTH_SPKTDEL_LOCK_1_FIELD 1 +#define STV090x_OFFST_SDEMOD_LOCKB_2_FIELD 2 +#define STV090x_WIDTH_SDEMOD_LOCKB_2_FIELD 1 +#define STV090x_OFFST_SDEMOD_LOCK_2_FIELD 1 +#define STV090x_WIDTH_SDEMOD_LOCK_2_FIELD 1 +#define STV090x_OFFST_SDEMOD_IRQ_2_FIELD 0 +#define STV090x_WIDTH_SDEMOD_IRQ_2_FIELD 1 + +#define STV090x_IRQSTATUS0 0xf123 +#define STV090x_OFFST_SDEMOD_LOCKB_1_FIELD 7 +#define STV090x_WIDTH_SDEMOD_LOCKB_1_FIELD 1 +#define STV090x_OFFST_SDEMOD_LOCK_1_FIELD 6 +#define STV090x_WIDTH_SDEMOD_LOCK_1_FIELD 1 +#define STV090x_OFFST_SDEMOD_IRQ_1_FIELD 5 +#define STV090x_WIDTH_SDEMOD_IRQ_1_FIELD 1 +#define STV090x_OFFST_SBCH_ERRFLAG_FIELD 4 +#define STV090x_WIDTH_SBCH_ERRFLAG_FIELD 1 +#define STV090x_OFFST_SDISEQC2RX_IRQ_FIELD 3 +#define STV090x_WIDTH_SDISEQC2RX_IRQ_FIELD 1 +#define STV090x_OFFST_SDISEQC2TX_IRQ_FIELD 2 +#define STV090x_WIDTH_SDISEQC2TX_IRQ_FIELD 1 +#define STV090x_OFFST_SDISEQC1RX_IRQ_FIELD 1 +#define STV090x_WIDTH_SDISEQC1RX_IRQ_FIELD 1 +#define STV090x_OFFST_SDISEQC1TX_IRQ_FIELD 0 +#define STV090x_WIDTH_SDISEQC1TX_IRQ_FIELD 1 + +#define STV090x_IRQMASK3 0xf124 +#define STV090x_OFFST_MPLL_LOCK_FIELD 5 +#define STV090x_WIDTH_MPLL_LOCK_FIELD 1 +#define STV090x_OFFST_MSTREAM_LCK_3_FIELD 2 +#define STV090x_WIDTH_MSTREAM_LCK_3_FIELD 3 +#define STV090x_OFFST_MSTREAM_LCK_2_FIELD 2 +#define STV090x_WIDTH_MSTREAM_LCK_2_FIELD 3 +#define STV090x_OFFST_MSTREAM_LCK_1_FIELD 2 +#define STV090x_WIDTH_MSTREAM_LCK_1_FIELD 3 +#define STV090x_OFFST_MDVBS1_PRF_2_FIELD 1 +#define STV090x_WIDTH_MDVBS1_PRF_2_FIELD 1 +#define STV090x_OFFST_MDVBS1_PRF_1_FIELD 0 +#define STV090x_WIDTH_MDVBS1_PRF_1_FIELD 1 + +#define STV090x_IRQMASK2 0xf125 +#define STV090x_OFFST_MSPY_ENDSIM_3_FIELD 5 +#define STV090x_WIDTH_MSPY_ENDSIM_3_FIELD 3 +#define STV090x_OFFST_MSPY_ENDSIM_2_FIELD 5 +#define STV090x_WIDTH_MSPY_ENDSIM_2_FIELD 3 +#define STV090x_OFFST_MSPY_ENDSIM_1_FIELD 5 +#define STV090x_WIDTH_MSPY_ENDSIM_1_FIELD 3 +#define STV090x_OFFST_MPKTDEL_ERROR_2_FIELD 4 +#define STV090x_WIDTH_MPKTDEL_ERROR_2_FIELD 1 +#define STV090x_OFFST_MPKTDEL_LOCKB_2_FIELD 3 +#define STV090x_WIDTH_MPKTDEL_LOCKB_2_FIELD 1 +#define STV090x_OFFST_MPKTDEL_LOCK_2_FIELD 2 +#define STV090x_WIDTH_MPKTDEL_LOCK_2_FIELD 1 +#define STV090x_OFFST_MPKTDEL_ERROR_1_FIELD 1 +#define STV090x_WIDTH_MPKTDEL_ERROR_1_FIELD 1 +#define STV090x_OFFST_MPKTDEL_LOCKB_1_FIELD 0 +#define STV090x_WIDTH_MPKTDEL_LOCKB_1_FIELD 1 + +#define STV090x_IRQMASK1 0xf126 +#define STV090x_OFFST_MPKTDEL_LOCK_1_FIELD 7 +#define STV090x_WIDTH_MPKTDEL_LOCK_1_FIELD 1 +#define STV090x_OFFST_MEXTPINB2_FIELD 6 +#define STV090x_WIDTH_MEXTPINB2_FIELD 1 +#define STV090x_OFFST_MEXTPIN2_FIELD 5 +#define STV090x_WIDTH_MEXTPIN2_FIELD 1 +#define STV090x_OFFST_MEXTPINB1_FIELD 4 +#define STV090x_WIDTH_MEXTPINB1_FIELD 1 +#define STV090x_OFFST_MEXTPIN1_FIELD 3 +#define STV090x_WIDTH_MEXTPIN1_FIELD 1 +#define STV090x_OFFST_MDEMOD_LOCKB_2_FIELD 2 +#define STV090x_WIDTH_MDEMOD_LOCKB_2_FIELD 1 +#define STV090x_OFFST_MDEMOD_LOCK_2_FIELD 1 +#define STV090x_WIDTH_MDEMOD_LOCK_2_FIELD 1 +#define STV090x_OFFST_MDEMOD_IRQ_2_FIELD 0 +#define STV090x_WIDTH_MDEMOD_IRQ_2_FIELD 1 + +#define STV090x_IRQMASK0 0xf127 +#define STV090x_OFFST_MDEMOD_LOCKB_1_FIELD 7 +#define STV090x_WIDTH_MDEMOD_LOCKB_1_FIELD 1 +#define STV090x_OFFST_MDEMOD_LOCK_1_FIELD 6 +#define STV090x_WIDTH_MDEMOD_LOCK_1_FIELD 1 +#define STV090x_OFFST_MDEMOD_IRQ_1_FIELD 5 +#define STV090x_WIDTH_MDEMOD_IRQ_1_FIELD 1 +#define STV090x_OFFST_MBCH_ERRFLAG_FIELD 4 +#define STV090x_WIDTH_MBCH_ERRFLAG_FIELD 1 +#define STV090x_OFFST_MDISEQC2RX_IRQ_FIELD 3 +#define STV090x_WIDTH_MDISEQC2RX_IRQ_FIELD 1 +#define STV090x_OFFST_MDISEQC2TX_IRQ_FIELD 2 +#define STV090x_WIDTH_MDISEQC2TX_IRQ_FIELD 1 +#define STV090x_OFFST_MDISEQC1RX_IRQ_FIELD 1 +#define STV090x_WIDTH_MDISEQC1RX_IRQ_FIELD 1 +#define STV090x_OFFST_MDISEQC1TX_IRQ_FIELD 0 +#define STV090x_WIDTH_MDISEQC1TX_IRQ_FIELD 1 + +#define STV090x_I2CCFG 0xf129 +#define STV090x_OFFST_12C_FASTMODE_FIELD 3 +#define STV090x_WIDTH_12C_FASTMODE_FIELD 1 +#define STV090x_OFFST_12CADDR_INC_FIELD 0 +#define STV090x_WIDTH_12CADDR_INC_FIELD 2 + +#define STV090x_Px_I2CRPT(__x) (0xf12a + (__x - 1) * 0x1) +#define STV090x_P1_I2CRPT STV090x_Px_I2CRPT(1) +#define STV090x_P2_I2CRPT STV090x_Px_I2CRPT(2) +#define STV090x_OFFST_Px_I2CT_ON_FIELD 7 +#define STV090x_WIDTH_Px_I2CT_ON_FIELD 1 +#define STV090x_OFFST_Px_ENARPT_LEVEL_FIELD 4 +#define STV090x_WIDTH_Px_ENARPT_LEVEL_FIELD 3 +#define STV090x_OFFST_Px_SCLT_DELAY_FIELD 3 +#define STV090x_WIDTH_Px_SCLT_DELAY_FIELD 1 +#define STV090x_OFFST_Px_STOP_ENABLE_FIELD 2 +#define STV090x_WIDTH_Px_STOP_ENABLE_FIELD 1 +#define STV090x_OFFST_Px_STOP_SDAT2SDA_FIELD 1 +#define STV090x_WIDTH_Px_STOP_SDAT2SDA_FIELD 1 + +#define STV090x_CLKI2CFG 0xf140 +#define STV090x_OFFST_CLKI2_OPD_FIELD 7 +#define STV090x_WIDTH_CLKI2_OPD_FIELD 1 +#define STV090x_OFFST_CLKI2_CONFIG_FIELD 1 +#define STV090x_WIDTH_CLKI2_CONFIG_FIELD 6 +#define STV090x_OFFST_CLKI2_XOR_FIELD 0 +#define STV090x_WIDTH_CLKI2_XOR_FIELD 1 + +#define STV090x_GPIOxCFG(__x) (0xf141 + (__x - 1)) +#define STV090x_GPIO1CFG STV090x_GPIOxCFG(1) +#define STV090x_GPIO2CFG STV090x_GPIOxCFG(2) +#define STV090x_GPIO3CFG STV090x_GPIOxCFG(3) +#define STV090x_GPIO4CFG STV090x_GPIOxCFG(4) +#define STV090x_GPIO5CFG STV090x_GPIOxCFG(5) +#define STV090x_GPIO6CFG STV090x_GPIOxCFG(6) +#define STV090x_GPIO7CFG STV090x_GPIOxCFG(7) +#define STV090x_GPIO8CFG STV090x_GPIOxCFG(8) +#define STV090x_GPIO9CFG STV090x_GPIOxCFG(9) +#define STV090x_GPIO10CFG STV090x_GPIOxCFG(10) +#define STV090x_GPIO11CFG STV090x_GPIOxCFG(11) +#define STV090x_GPIO12CFG STV090x_GPIOxCFG(12) +#define STV090x_GPIO13CFG STV090x_GPIOxCFG(13) +#define STV090x_OFFST_GPIOx_OPD_FIELD 7 +#define STV090x_WIDTH_GPIOx_OPD_FIELD 1 +#define STV090x_OFFST_GPIOx_CONFIG_FIELD 1 +#define STV090x_WIDTH_GPIOx_CONFIG_FIELD 6 +#define STV090x_OFFST_GPIOx_XOR_FIELD 0 +#define STV090x_WIDTH_GPIOx_XOR_FIELD 1 + +#define STV090x_CSxCFG(__x) (0xf14e + __x * 0x1) +#define STV090x_CS0CFG STV090x_CSxCFG(0) +#define STV090x_CS1CFG STV090x_CSxCFG(1) +#define STV090x_OFFST_CSX_OPD_FIELD 7 +#define STV090x_WIDTH_CSX_OPD_FIELD 1 +#define STV090x_OFFST_CSX_CONFIG_FIELD 1 +#define STV090x_WIDTH_CSX_CONFIG_FIELD 6 +#define STV090x_OFFST_CSX_XOR_FIELD 0 +#define STV090x_WIDTH_CSX_XOR_FIELD 1 + + +#define STV090x_STDBYCFG 0xf150 +#define STV090x_OFFST_STDBY_OPD_FIELD 7 +#define STV090x_WIDTH_STDBY_OPD_FIELD 1 +#define STV090x_OFFST_STDBY_CONFIG_FIELD 1 +#define STV090x_WIDTH_STDBY_CONFIG_FIELD 6 +#define STV090x_OFFST_STDBY_XOR_FIELD 0 +#define STV090x_WIDTH_STDBY_XOR_FIELD 1 + +#define STV090x_DIRCLKCFG 0xf151 +#define STV090x_OFFST_DIRCLK_OPD_FIELD 7 +#define STV090x_WIDTH_DIRCLK_OPD_FIELD 1 +#define STV090x_OFFST_DIRCLK_CONFIG_FIELD 1 +#define STV090x_WIDTH_DIRCLK_CONFIG_FIELD 6 +#define STV090x_OFFST_DIRCLK_XOR_FIELD 0 +#define STV090x_WIDTH_DIRCLK_XOR_FIELD 1 + + +#define STV090x_AGCRFxCFG(__x) (0xf152 + (__x - 1) * 0x4) +#define STV090x_AGCRF1CFG STV090x_AGCRFxCFG(1) +#define STV090x_AGCRF2CFG STV090x_AGCRFxCFG(2) +#define STV090x_OFFST_AGCRFx_OPD_FIELD 7 +#define STV090x_WIDTH_AGCRFx_OPD_FIELD 1 +#define STV090x_OFFST_AGCRFx_CONFIG_FIELD 1 +#define STV090x_WIDTH_AGCRFx_CONFIG_FIELD 6 +#define STV090x_OFFST_AGCRFx_XOR_FIELD 0 +#define STV090x_WIDTH_AGCRFx_XOR_FIELD 1 + +#define STV090x_SDATxCFG(__x) (0xf153 + (__x - 1) * 0x4) +#define STV090x_SDAT1CFG STV090x_SDATxCFG(1) +#define STV090x_SDAT2CFG STV090x_SDATxCFG(2) +#define STV090x_OFFST_SDATx_OPD_FIELD 7 +#define STV090x_WIDTH_SDATx_OPD_FIELD 1 +#define STV090x_OFFST_SDATx_CONFIG_FIELD 1 +#define STV090x_WIDTH_SDATx_CONFIG_FIELD 6 +#define STV090x_OFFST_SDATx_XOR_FIELD 0 +#define STV090x_WIDTH_SDATx_XOR_FIELD 1 + +#define STV090x_SCLTxCFG(__x) (0xf154 + (__x - 1) * 0x4) +#define STV090x_SCLT1CFG STV090x_SCLTxCFG(1) +#define STV090x_SCLT2CFG STV090x_SCLTxCFG(2) +#define STV090x_OFFST_SCLTx_OPD_FIELD 7 +#define STV090x_WIDTH_SCLTx_OPD_FIELD 1 +#define STV090x_OFFST_SCLTx_CONFIG_FIELD 1 +#define STV090x_WIDTH_SCLTx_CONFIG_FIELD 6 +#define STV090x_OFFST_SCLTx_XOR_FIELD 0 +#define STV090x_WIDTH_SCLTx_XOR_FIELD 1 + +#define STV090x_DISEQCOxCFG(__x) (0xf155 + (__x - 1) * 0x4) +#define STV090x_DISEQCO1CFG STV090x_DISEQCOxCFG(1) +#define STV090x_DISEQCO2CFG STV090x_DISEQCOxCFG(2) +#define STV090x_OFFST_DISEQCOx_OPD_FIELD 7 +#define STV090x_WIDTH_DISEQCOx_OPD_FIELD 1 +#define STV090x_OFFST_DISEQCOx_CONFIG_FIELD 1 +#define STV090x_WIDTH_DISEQCOx_CONFIG_FIELD 6 +#define STV090x_OFFST_DISEQCOx_XOR_FIELD 0 +#define STV090x_WIDTH_DISEQCOx_XOR_FIELD 1 + +#define STV090x_CLKOUT27CFG 0xf15a +#define STV090x_OFFST_CLKOUT27_OPD_FIELD 7 +#define STV090x_WIDTH_CLKOUT27_OPD_FIELD 1 +#define STV090x_OFFST_CLKOUT27_CONFIG_FIELD 1 +#define STV090x_WIDTH_CLKOUT27_CONFIG_FIELD 6 +#define STV090x_OFFST_CLKOUT27_XOR_FIELD 0 +#define STV090x_WIDTH_CLKOUT27_XOR_FIELD 1 + +#define STV090x_ERRORxCFG(__x) (0xf15b + (__x - 1) * 0x5) +#define STV090x_ERROR1CFG STV090x_ERRORxCFG(1) +#define STV090x_ERROR2CFG STV090x_ERRORxCFG(2) +#define STV090x_ERROR3CFG STV090x_ERRORxCFG(3) +#define STV090x_OFFST_ERRORx_OPD_FIELD 7 +#define STV090x_WIDTH_ERRORx_OPD_FIELD 1 +#define STV090x_OFFST_ERRORx_CONFIG_FIELD 1 +#define STV090x_WIDTH_ERRORx_CONFIG_FIELD 6 +#define STV090x_OFFST_ERRORx_XOR_FIELD 0 +#define STV090x_WIDTH_ERRORx_XOR_FIELD 1 + +#define STV090x_DPNxCFG(__x) (0xf15c + (__x - 1) * 0x5) +#define STV090x_DPN1CFG STV090x_DPNxCFG(1) +#define STV090x_DPN2CFG STV090x_DPNxCFG(2) +#define STV090x_DPN3CFG STV090x_DPNxCFG(3) +#define STV090x_OFFST_DPNx_OPD_FIELD 7 +#define STV090x_WIDTH_DPNx_OPD_FIELD 1 +#define STV090x_OFFST_DPNx_CONFIG_FIELD 1 +#define STV090x_WIDTH_DPNx_CONFIG_FIELD 6 +#define STV090x_OFFST_DPNx_XOR_FIELD 0 +#define STV090x_WIDTH_DPNx_XOR_FIELD 1 + +#define STV090x_STROUTxCFG(__x) (0xf15d + (__x - 1) * 0x5) +#define STV090x_STROUT1CFG STV090x_STROUTxCFG(1) +#define STV090x_STROUT2CFG STV090x_STROUTxCFG(2) +#define STV090x_STROUT3CFG STV090x_STROUTxCFG(3) +#define STV090x_OFFST_STROUTx_OPD_FIELD 7 +#define STV090x_WIDTH_STROUTx_OPD_FIELD 1 +#define STV090x_OFFST_STROUTx_CONFIG_FIELD 1 +#define STV090x_WIDTH_STROUTx_CONFIG_FIELD 6 +#define STV090x_OFFST_STROUTx_XOR_FIELD 0 +#define STV090x_WIDTH_STROUTx_XOR_FIELD 1 + +#define STV090x_CLKOUTxCFG(__x) (0xf15e + (__x - 1) * 0x5) +#define STV090x_CLKOUT1CFG STV090x_CLKOUTxCFG(1) +#define STV090x_CLKOUT2CFG STV090x_CLKOUTxCFG(2) +#define STV090x_CLKOUT3CFG STV090x_CLKOUTxCFG(3) +#define STV090x_OFFST_CLKOUTx_OPD_FIELD 7 +#define STV090x_WIDTH_CLKOUTx_OPD_FIELD 1 +#define STV090x_OFFST_CLKOUTx_CONFIG_FIELD 1 +#define STV090x_WIDTH_CLKOUTx_CONFIG_FIELD 6 +#define STV090x_OFFST_CLKOUTx_XOR_FIELD 0 +#define STV090x_WIDTH_CLKOUTx_XOR_FIELD 1 + +#define STV090x_DATAxCFG(__x) (0xf15f + (__x - 71) * 0x5) +#define STV090x_DATA71CFG STV090x_DATAxCFG(71) +#define STV090x_DATA72CFG STV090x_DATAxCFG(72) +#define STV090x_DATA73CFG STV090x_DATAxCFG(73) +#define STV090x_OFFST_DATAx_OPD_FIELD 7 +#define STV090x_WIDTH_DATAx_OPD_FIELD 1 +#define STV090x_OFFST_DATAx_CONFIG_FIELD 1 +#define STV090x_WIDTH_DATAx_CONFIG_FIELD 6 +#define STV090x_OFFST_DATAx_XOR_FIELD 0 +#define STV090x_WIDTH_DATAx_XOR_FIELD 1 + +#define STV090x_NCOARSE 0xf1b3 +#define STV090x_OFFST_M_DIV_FIELD 0 +#define STV090x_WIDTH_M_DIV_FIELD 8 + +#define STV090x_SYNTCTRL 0xf1b6 +#define STV090x_OFFST_STANDBY_FIELD 7 +#define STV090x_WIDTH_STANDBY_FIELD 1 +#define STV090x_OFFST_BYPASSPLLCORE_FIELD 6 +#define STV090x_WIDTH_BYPASSPLLCORE_FIELD 1 +#define STV090x_OFFST_SELX1RATIO_FIELD 5 +#define STV090x_WIDTH_SELX1RATIO_FIELD 1 +#define STV090x_OFFST_STOP_PLL_FIELD 3 +#define STV090x_WIDTH_SELX1RATIO_FIELD 1 +#define STV090x_OFFST_BYPASSPLLFSK_FIELD 2 +#define STV090x_WIDTH_BYPASSPLLFSK_FIELD 1 +#define STV090x_OFFST_SELOSCI_FIELD 1 +#define STV090x_WIDTH_SELOSCI_FIELD 1 +#define STV090x_OFFST_BYPASSPLLADC_FIELD 0 +#define STV090x_WIDTH_BYPASSPLLADC_FIELD 1 + +#define STV090x_FILTCTRL 0xf1b7 +#define STV090x_OFFST_INV_CLK135_FIELD 7 +#define STV090x_WIDTH_INV_CLK135_FIELD 1 +#define STV090x_OFFST_SEL_FSKCKDIV_FIELD 2 +#define STV090x_WIDTH_SEL_FSKCKDIV_FIELD 1 +#define STV090x_OFFST_INV_CLKFSK_FIELD 1 +#define STV090x_WIDTH_INV_CLKFSK_FIELD 1 +#define STV090x_OFFST_BYPASS_APPLI_FIELD 0 +#define STV090x_WIDTH_BYPASS_APPLI_FIELD 1 + +#define STV090x_PLLSTAT 0xf1b8 +#define STV090x_OFFST_PLLLOCK_FIELD 0 +#define STV090x_WIDTH_PLLLOCK_FIELD 1 + +#define STV090x_STOPCLK1 0xf1c2 +#define STV090x_OFFST_STOP_CLKPKDT2_FIELD 6 +#define STV090x_WIDTH_STOP_CLKPKDT2_FIELD 1 +#define STV090x_OFFST_STOP_CLKPKDT1_FIELD 5 +#define STV090x_WIDTH_STOP_CLKPKDT1_FIELD 1 +#define STV090x_OFFST_STOP_CLKFEC_FIELD 4 +#define STV090x_WIDTH_STOP_CLKFEC_FIELD 1 +#define STV090x_OFFST_STOP_CLKADCI2_FIELD 3 +#define STV090x_WIDTH_STOP_CLKADCI2_FIELD 1 +#define STV090x_OFFST_INV_CLKADCI2_FIELD 2 +#define STV090x_WIDTH_INV_CLKADCI2_FIELD 1 +#define STV090x_OFFST_STOP_CLKADCI1_FIELD 1 +#define STV090x_WIDTH_STOP_CLKADCI1_FIELD 1 +#define STV090x_OFFST_INV_CLKADCI1_FIELD 0 +#define STV090x_WIDTH_INV_CLKADCI1_FIELD 1 + +#define STV090x_STOPCLK2 0xf1c3 +#define STV090x_OFFST_STOP_CLKSAMP2_FIELD 4 +#define STV090x_WIDTH_STOP_CLKSAMP2_FIELD 1 +#define STV090x_OFFST_STOP_CLKSAMP1_FIELD 3 +#define STV090x_WIDTH_STOP_CLKSAMP1_FIELD 1 +#define STV090x_OFFST_STOP_CLKVIT2_FIELD 2 +#define STV090x_WIDTH_STOP_CLKVIT2_FIELD 1 +#define STV090x_OFFST_STOP_CLKVIT1_FIELD 1 +#define STV090x_WIDTH_STOP_CLKVIT1_FIELD 1 +#define STV090x_OFFST_STOP_CLKTS_FIELD 0 +#define STV090x_WIDTH_STOP_CLKTS_FIELD 1 + +#define STV090x_TSTTNR0 0xf1df +#define STV090x_OFFST_SEL_FSK_FIELD 7 +#define STV090x_WIDTH_SEL_FSK_FIELD 1 +#define STV090x_OFFST_FSK_PON_FIELD 2 +#define STV090x_WIDTH_FSK_PON_FIELD 1 + +#define STV090x_TSTTNR1 0xf1e0 +#define STV090x_OFFST_ADC1_PON_FIELD 1 +#define STV090x_WIDTH_ADC1_PON_FIELD 1 +#define STV090x_OFFST_ADC1_INMODE_FIELD 0 +#define STV090x_WIDTH_ADC1_INMODE_FIELD 1 + +#define STV090x_TSTTNR2 0xf1e1 +#define STV090x_OFFST_DISEQC1_PON_FIELD 5 +#define STV090x_WIDTH_DISEQC1_PON_FIELD 1 + +#define STV090x_TSTTNR3 0xf1e2 +#define STV090x_OFFST_ADC2_PON_FIELD 1 +#define STV090x_WIDTH_ADC2_PON_FIELD 1 +#define STV090x_OFFST_ADC2_INMODE_FIELD 0 +#define STV090x_WIDTH_ADC2_INMODE_FIELD 1 + +#define STV090x_TSTTNR4 0xf1e3 +#define STV090x_OFFST_DISEQC2_PON_FIELD 5 +#define STV090x_WIDTH_DISEQC2_PON_FIELD 1 + +#define STV090x_FSKTFC2 0xf170 +#define STV090x_OFFST_FSKT_KMOD_FIELD 2 +#define STV090x_WIDTH_FSKT_KMOD_FIELD 6 +#define STV090x_OFFST_FSKT_CAR_FIELD 0 +#define STV090x_WIDTH_FSKT_CAR_FIELD 2 + +#define STV090x_FSKTFC1 0xf171 +#define STV090x_OFFST_FSKTC1_CAR_FIELD 0 +#define STV090x_WIDTH_FSKTC1_CAR_FIELD 8 + +#define STV090x_FSKTFC0 0xf172 +#define STV090x_OFFST_FSKTC0_CAR_FIELD 0 +#define STV090x_WIDTH_FSKTC0_CAR_FIELD 8 + +#define STV090x_FSKTDELTAF1 0xf173 +#define STV090x_OFFST_FSKTF1_DELTAF_FIELD 0 +#define STV090x_WIDTH_FSKTF1_DELTAF_FIELD 4 + +#define STV090x_FSKTDELTAF0 0xf174 +#define STV090x_OFFST_FSKTF0_DELTAF_FIELD 0 +#define STV090x_WIDTH_FSKTF0_DELTAF_FIELD 8 + +#define STV090x_FSKTCTRL 0xf175 +#define STV090x_OFFST_FSKT_EN_SGN_FIELD 6 +#define STV090x_WIDTH_FSKT_EN_SGN__FIELD 1 +#define STV090x_OFFST_FSKT_MOD_SGN_FIELD 5 +#define STV090x_WIDTH_FSKT_MOD_SGN_FIELD 1 +#define STV090x_OFFST_FSKT_MOD_EN_FIELD 2 +#define STV090x_WIDTH_FSKT_MOD_EN_FIELD 3 +#define STV090x_OFFST_FSKT_DACMODE_FIELD 0 +#define STV090x_WIDTH_FSKT_DACMODE_FIELD 2 + +#define STV090x_FSKRFC2 0xf176 +#define STV090x_OFFST_FSKRC2_DETSGN_FIELD 6 +#define STV090x_WIDTH_FSKRC2_DETSGN_FIELD 1 +#define STV090x_OFFST_FSKRC2_OUTSGN_FIELD 5 +#define STV090x_WIDTH_FSKRC2_OUTSGN_FIELD 1 +#define STV090x_OFFST_FSKRC2_KAGC_FIELD 2 +#define STV090x_WIDTH_FSKRC2_KAGC_FIELD 3 +#define STV090x_OFFST_FSKRC2_CAR_FIELD 0 +#define STV090x_WIDTH_FSKRC2_CAR_FIELD 2 + +#define STV090x_FSKRFC1 0xf177 +#define STV090x_OFFST_FSKRC1_CAR_FIELD 0 +#define STV090x_WIDTH_FSKRC1_CAR_FIELD 8 + +#define STV090x_FSKRFC0 0xf178 +#define STV090x_OFFST_FSKRC0_CAR_FIELD 0 +#define STV090x_WIDTH_FSKRC0_CAR_FIELD 8 + +#define STV090x_FSKRK1 0xf179 +#define STV090x_OFFST_FSKR_K1_EXP_FIELD 5 +#define STV090x_WIDTH_FSKR_K1_EXP_FIELD 3 +#define STV090x_OFFST_FSKR_K1_MANT_FIELD 0 +#define STV090x_WIDTH_FSKR_K1_MANT_FIELD 5 + +#define STV090x_FSKRK2 0xf17a +#define STV090x_OFFST_FSKR_K2_EXP_FIELD 5 +#define STV090x_WIDTH_FSKR_K2_EXP_FIELD 3 +#define STV090x_OFFST_FSKR_K2_MANT_FIELD 0 +#define STV090x_WIDTH_FSKR_K2_MANT_FIELD 5 + +#define STV090x_FSKRAGCR 0xf17b +#define STV090x_OFFST_FSKR_OUTCTL_FIELD 6 +#define STV090x_WIDTH_FSKR_OUTCTL_FIELD 2 +#define STV090x_OFFST_FSKR_AGC_REF_FIELD 0 +#define STV090x_WIDTH_FSKR_AGC_REF_FIELD 6 + +#define STV090x_FSKRAGC 0xf17c +#define STV090x_OFFST_FSKR_AGC_ACCU_FIELD 0 +#define STV090x_WIDTH_FSKR_AGC_ACCU_FIELD 8 + +#define STV090x_FSKRALPHA 0xf17d +#define STV090x_OFFST_FSKR_ALPHA_EXP_FIELD 2 +#define STV090x_WIDTH_FSKR_ALPHA_EXP_FIELD 3 +#define STV090x_OFFST_FSKR_ALPHA_M_FIELD 0 +#define STV090x_WIDTH_FSKR_ALPHA_M_FIELD 2 + +#define STV090x_FSKRPLTH1 0xf17e +#define STV090x_OFFST_FSKR_BETA_FIELD 4 +#define STV090x_WIDTH_FSKR_BETA_FIELD 4 +#define STV090x_OFFST_FSKR_PLL_TRESH1_FIELD 0 +#define STV090x_WIDTH_FSKR_PLL_TRESH1_FIELD 4 + +#define STV090x_FSKRPLTH0 0xf17f +#define STV090x_OFFST_FSKR_PLL_TRESH0_FIELD 0 +#define STV090x_WIDTH_FSKR_PLL_TRESH0_FIELD 8 + +#define STV090x_FSKRDF1 0xf180 +#define STV090x_OFFST_FSKR_DELTAF1_FIELD 0 +#define STV090x_WIDTH_FSKR_DELTAF1_FIELD 5 + +#define STV090x_FSKRDF0 0xf181 +#define STV090x_OFFST_FSKR_DELTAF0_FIELD 0 +#define STV090x_WIDTH_FSKR_DELTAF0_FIELD 8 + +#define STV090x_FSKRSTEPP 0xf182 +#define STV090x_OFFST_FSKR_STEP_PLUS_FIELD 0 +#define STV090x_WIDTH_FSKR_STEP_PLUS_FIELD 8 + +#define STV090x_FSKRSTEPM 0xf183 +#define STV090x_OFFST_FSKR_STEP_MINUS_FIELD 0 +#define STV090x_WIDTH_FSKR_STEP_MINUS_FIELD 8 + +#define STV090x_FSKRDET1 0xf184 +#define STV090x_OFFST_FSKR_CARDET1_ACCU_FIELD 0 +#define STV090x_WIDTH_FSKR_CARDET1_ACCU_FIELD 4 + +#define STV090x_FSKRDET0 0xf185 +#define STV090x_OFFST_FSKR_CARDET0_ACCU_FIELD 0 +#define STV090x_WIDTH_FSKR_CARDET0_ACCU_FIELD 8 + +#define STV090x_FSKRDTH1 0xf186 +#define STV090x_OFFST_FSKR_CARLOSS_THRESH1_FIELD 4 +#define STV090x_WIDTH_FSKR_CARLOSS_THRESH1_FIELD 4 +#define STV090x_OFFST_FSKR_CARDET_THRESH1_FIELD 0 +#define STV090x_WIDTH_FSKR_CARDET_THRESH1_FIELD 4 + +#define STV090x_FSKRDTH0 0xf187 +#define STV090x_OFFST_FSKR_CARDET_THRESH0_FIELD 0 +#define STV090x_WIDTH_FSKR_CARDET_THRESH0_FIELD 8 + +#define STV090x_FSKRLOSS 0xf188 +#define STV090x_OFFST_FSKR_CARLOSS_THRESH_FIELD 0 +#define STV090x_WIDTH_FSKR_CARLOSS_THRESH_FIELD 8 + +#define STV090x_Px_DISTXCTL(__x) (0xF1A0 - (__x - 1) * 0x10) +#define STV090x_P1_DISTXCTL (1) +#define STV090x_P2_DISTXCTL (2) +#define STV090x_OFFST_Px_TIM_OFF_FIELD 7 +#define STV090x_WIDTH_Px_TIM_OFF_FIELD 1 +#define STV090x_OFFST_Px_DISEQC_RESET_FIELD 6 +#define STV090x_WIDTH_Px_DISEQC_RESET_FIELD 1 +#define STV090x_OFFST_Px_TIM_CMD_FIELD 4 +#define STV090x_WIDTH_Px_TIM_CMD_FIELD 2 +#define STV090x_OFFST_Px_DIS_PRECHARGE_FIELD 3 +#define STV090x_WIDTH_Px_DIS_PRECHARGE_FIELD 1 +#define STV090x_OFFST_Px_DISTX_MODE_FIELD 0 +#define STV090x_WIDTH_Px_DISTX_MODE_FIELD 3 + +#define STV090x_Px_DISRXCTL(__x) (0xf1a1 - (__x - 1) * 0x10) +#define STV090x_P1_DISRXCTL (1) +#define STV090x_P2_DISRXCTL (2) +#define STV090x_OFFST_Px_RECEIVER_ON_FIELD 7 +#define STV090x_WIDTH_Px_RECEIVER_ON_FIELD 1 +#define STV090x_OFFST_Px_IGNO_SHORT22K_FIELD 6 +#define STV090x_WIDTH_Px_IGNO_SHORT22K_FIELD 1 +#define STV090x_OFFST_Px_ONECHIP_TRX_FIELD 5 +#define STV090x_WIDTH_Px_ONECHIP_TRX_FIELD 1 +#define STV090x_OFFST_Px_EXT_ENVELOP_FIELD 4 +#define STV090x_WIDTH_Px_EXT_ENVELOP_FIELD 1 +#define STV090x_OFFST_Px_PIN_SELECT_FIELD 2 +#define STV090x_WIDTH_Px_PIN_SELECT_FIELD 2 +#define STV090x_OFFST_Px_IRQ_RXEND_FIELD 1 +#define STV090x_WIDTH_Px_IRQ_RXEND_FIELD 1 +#define STV090x_OFFST_Px_IRQ_4NBYTES_FIELD 0 +#define STV090x_WIDTH_Px_IRQ_4NBYTES_FIELD 1 + +#define STV090x_Px_DISRX_ST0(__x) (0xf1a4 - (__x - 1) * 0x10) +#define STV090x_P1_DISRX_ST0 (1) +#define STV090x_P2_DISRX_ST0 (2) +#define STV090x_OFFST_Px_RX_END_FIELD 7 +#define STV090x_WIDTH_Px_RX_END_FIELD 1 +#define STV090x_OFFST_Px_RX_ACTIVE_FIELD 6 +#define STV090x_WIDTH_Px_RX_ACTIVE_FIELD 1 +#define STV090x_OFFST_Px_SHORT_22KHZ_FIELD 5 +#define STV090x_WIDTH_Px_SHORT_22KHZ_FIELD 1 +#define STV090x_OFFST_Px_CONT_TONE_FIELD 4 +#define STV090x_WIDTH_Px_CONT_TONE_FIELD 1 +#define STV090x_OFFST_Px_FIFO_4BREADY_FIELD 3 +#define STV090x_WIDTH_Px_FIFO_4BREADYFIELD 2 +#define STV090x_OFFST_Px_FIFO_EMPTY_FIELD 2 +#define STV090x_WIDTH_Px_FIFO_EMPTY_FIELD 1 +#define STV090x_OFFST_Px_ABORT_DISRX_FIELD 0 +#define STV090x_WIDTH_Px_ABORT_DISRX_FIELD 1 + +#define STV090x_Px_DISRX_ST1(__x) (0xf1a5 - (__x - 1) * 0x10) +#define STV090x_P1_DISRX_ST1 (1) +#define STV090x_P2_DISRX_ST1 (2) +#define STV090x_OFFST_Px_RX_FAIL_FIELD 7 +#define STV090x_WIDTH_Px_RX_FAIL_FIELD 1 +#define STV090x_OFFST_Px_FIFO_PARITYFAIL_FIELD 6 +#define STV090x_WIDTH_Px_FIFO_PARITYFAIL_FIELD 1 +#define STV090x_OFFST_Px_RX_NONBYTE_FIELD 5 +#define STV090x_WIDTH_Px_RX_NONBYTE_FIELD 1 +#define STV090x_OFFST_Px_FIFO_OVERFLOW_FIELD 4 +#define STV090x_WIDTH_Px_FIFO_OVERFLOW_FIELD 1 +#define STV090x_OFFST_Px_FIFO_BYTENBR_FIELD 0 +#define STV090x_WIDTH_Px_FIFO_BYTENBR_FIELD 4 + +#define STV090x_Px_DISRXDATA(__x) (0xf1a6 - (__x - 1) * 0x10) +#define STV090x_P1_DISRXDATA (1) +#define STV090x_P2_DISRXDATA (2) +#define STV090x_OFFST_Px_DISRX_DATA_FIELD 0 +#define STV090x_WIDTH_Px_DISRX_DATA_FIELD 8 + +#define STV090x_Px_DISTXDATA(__x) (0xf1a7 - (__x - 1) * 0x10) +#define STV090x_P1_DISTXDATA (1) +#define STV090x_P2_DISTXDATA (2) +#define STV090x_OFFST_Px_DISEQC_FIFO_FIELD 0 +#define STV090x_WIDTH_Px_DISEQC_FIFO_FIELD 8 + +#define STV090x_Px_DISTXSTATUS(__x) (0xf1a8 - (__x - 1) * 0x10) +#define STV090x_P1_DISTXSTATUS (1) +#define STV090x_P2_DISTXSTATUS (2) +#define STV090x_OFFST_Px_TX_FAIL_FIELD 7 +#define STV090x_WIDTH_Px_TX_FAIL_FIELD 1 +#define STV090x_OFFST_Px_FIFO_FULL_FIELD 6 +#define STV090x_WIDTH_Px_FIFO_FULL_FIELD 1 +#define STV090x_OFFST_Px_TX_IDLE_FIELD 5 +#define STV090x_WIDTH_Px_TX_IDLE_FIELD 1 +#define STV090x_OFFST_Px_GAP_BURST_FIELD 4 +#define STV090x_WIDTH_Px_GAP_BURST_FIELD 1 +#define STV090x_OFFST_Px_TXFIFO_BYTES_FIELD 0 +#define STV090x_WIDTH_Px_TXFIFO_BYTES_FIELD 4 + +#define STV090x_Px_F22TX(__x) (0xf1a9 - (__x - 1) * 0x10) +#define STV090x_P1_F22TX (1) +#define STV090x_P2_F22TX (2) +#define STV090x_OFFST_Px_F22_REG_FIELD 0 +#define STV090x_WIDTH_Px_F22_REG_FIELD 8 + +#define STV090x_Px_F22RX(__x) (0xf1aa - (__x - 1) * 0x10) +#define STV090x_P1_F22RX (1) +#define STV090x_P2_F22RX (2) +#define STV090x_OFFST_Px_F22RX_REG_FIELD 0 +#define STV090x_WIDTH_Px_F22RX_REG_FIELD 8 + +#define STV090x_Px_ACRPRESC(__x) (0xf1ac - (__x - 1) * 0x10) +#define STV090x_P1_ACRPRESC (1) +#define STV090x_P2_ACRPRESC (2) +#define STV090x_OFFST_Px_ACR_PRESC_FIELD 0 +#define STV090x_WIDTH_Px_ACR_PRESC_FIELD 3 + +#define STV090x_Px_ACRDIV(__x) (0xf1ad - (__x - 1) * 0x10) +#define STV090x_P1_ACRDIV (1) +#define STV090x_P2_ACRDIV (2) +#define STV090x_OFFST_Px_ACR_DIV_FIELD 0 +#define STV090x_WIDTH_Px_ACR_DIV_FIELD 8 + +#define STV090x_Px_IQCONST(__x) (0xF400 - (__x - 1) * 0x200) +#define STV090x_P1_IQCONST STV090x_Px_IQCONST(1) +#define STV090x_P2_IQCONST STV090x_Px_IQCONST(2) +#define STV090x_OFFST_Px_CONSTEL_SELECT_FIELD 5 +#define STV090x_WIDTH_Px_CONSTEL_SELECT_FIELD 2 + +#define STV090x_Px_NOSCFG(__x) (0xF401 - (__x - 1) * 0x200) +#define STV090x_P1_NOSCFG STV090x_Px_NOSCFG(1) +#define STV090x_P2_NOSCFG STV090x_Px_NOSCFG(2) +#define STV090x_OFFST_Px_NOSPLH_BETA_FIELD 3 +#define STV090x_WIDTH_Px_NOSPLH_BETA_FIELD 2 +#define STV090x_OFFST_Px_NOSDATA_BETA_FIELD 0 +#define STV090x_WIDTH_Px_NOSDATA_BETA_FIELD 3 + +#define STV090x_Px_ISYMB(__x) (0xF402 - (__x - 1) * 0x200) +#define STV090x_P1_ISYMB STV090x_Px_ISYMB(1) +#define STV090x_P2_ISYMB STV090x_Px_ISYMB(2) +#define STV090x_OFFST_Px_I_SYMBOL_FIELD 0 +#define STV090x_WIDTH_Px_I_SYMBOL_FIELD 8 + +#define STV090x_Px_QSYMB(__x) (0xF403 - (__x - 1) * 0x200) +#define STV090x_P1_QSYMB STV090x_Px_QSYMB(1) +#define STV090x_P2_QSYMB STV090x_Px_QSYMB(2) +#define STV090x_OFFST_Px_Q_SYMBOL_FIELD 0 +#define STV090x_WIDTH_Px_Q_SYMBOL_FIELD 8 + +#define STV090x_Px_AGC1CFG(__x) (0xF404 - (__x - 1) * 0x200) +#define STV090x_P1_AGC1CFG STV090x_Px_AGC1CFG(1) +#define STV090x_P2_AGC1CFG STV090x_Px_AGC1CFG(2) +#define STV090x_OFFST_Px_DC_FROZEN_FIELD 7 +#define STV090x_WIDTH_Px_DC_FROZEN_FIELD 1 +#define STV090x_OFFST_Px_DC_CORRECT_FIELD 6 +#define STV090x_WIDTH_Px_DC_CORRECT_FIELD 1 +#define STV090x_OFFST_Px_AMM_FROZEN_FIELD 5 +#define STV090x_WIDTH_Px_AMM_FROZEN_FIELD 1 +#define STV090x_OFFST_Px_AMM_CORRECT_FIELD 4 +#define STV090x_WIDTH_Px_AMM_CORRECT_FIELD 1 +#define STV090x_OFFST_Px_QUAD_FROZEN_FIELD 3 +#define STV090x_WIDTH_Px_QUAD_FROZEN_FIELD 1 +#define STV090x_OFFST_Px_QUAD_CORRECT_FIELD 2 +#define STV090x_WIDTH_Px_QUAD_CORRECT_FIELD 1 + +#define STV090x_Px_AGC1CN(__x) (0xF406 - (__x - 1) * 0x200) +#define STV090x_P1_AGC1CN STV090x_Px_AGC1CN(1) +#define STV090x_P2_AGC1CN STV090x_Px_AGC1CN(2) +#define STV090x_WIDTH_Px_AGC1_LOCKED_FIELD 7 +#define STV090x_OFFST_Px_AGC1_LOCKED_FIELD 1 +#define STV090x_OFFST_Px_AGC1_MINPOWER_FIELD 4 +#define STV090x_WIDTH_Px_AGC1_MINPOWER_FIELD 1 +#define STV090x_OFFST_Px_AGCOUT_FAST_FIELD 3 +#define STV090x_WIDTH_Px_AGCOUT_FAST_FIELD 1 +#define STV090x_OFFST_Px_AGCIQ_BETA_FIELD 0 +#define STV090x_WIDTH_Px_AGCIQ_BETA_FIELD 3 + +#define STV090x_Px_AGC1REF(__x) (0xF407 - (__x - 1) * 0x200) +#define STV090x_P1_AGC1REF STV090x_Px_AGC1REF(1) +#define STV090x_P2_AGC1REF STV090x_Px_AGC1REF(2) +#define STV090x_OFFST_Px_AGCIQ_REF_FIELD 0 +#define STV090x_WIDTH_Px_AGCIQ_REF_FIELD 8 + +#define STV090x_Px_IDCCOMP(__x) (0xF408 - (__x - 1) * 0x200) +#define STV090x_P1_IDCCOMP STV090x_Px_IDCCOMP(1) +#define STV090x_P2_IDCCOMP STV090x_Px_IDCCOMP(2) +#define STV090x_OFFST_Px_IAVERAGE_ADJ_FIELD 0 +#define STV090x_WIDTH_Px_IAVERAGE_ADJ_FIELD 8 + +#define STV090x_Px_QDCCOMP(__x) (0xF409 - (__x - 1) * 0x200) +#define STV090x_P1_QDCCOMP STV090x_Px_QDCCOMP(1) +#define STV090x_P2_QDCCOMP STV090x_Px_QDCCOMP(2) +#define STV090x_OFFST_Px_QAVERAGE_ADJ_FIELD 0 +#define STV090x_WIDTH_Px_QAVERAGE_ADJ_FIELD 8 + +#define STV090x_Px_POWERI(__x) (0xF40A - (__x - 1) * 0x200) +#define STV090x_P1_POWERI STV090x_Px_POWERI(1) +#define STV090x_P2_POWERI STV090x_Px_POWERI(2) +#define STV090x_OFFST_Px_POWER_I_FIELD 0 +#define STV090x_WIDTH_Px_POWER_I_FIELD 8 + +#define STV090x_Px_POWERQ(__x) (0xF40B - (__x - 1) * 0x200) +#define STV090x_P1_POWERQ STV090x_Px_POWERQ(1) +#define STV090x_P2_POWERQ STV090x_Px_POWERQ(2) +#define STV090x_OFFST_Px_POWER_Q_FIELD 0 +#define STV090x_WIDTH_Px_POWER_Q_FIELD 8 + +#define STV090x_Px_AGC1AMM(__x) (0xF40C - (__x - 1) * 0x200) +#define STV090x_P1_AGC1AMM STV090x_Px_AGC1AMM(1) +#define STV090x_P2_AGC1AMM STV090x_Px_AGC1AMM(2) +#define STV090x_OFFST_Px_AMM_VALUE_FIELD 0 +#define STV090x_WIDTH_Px_AMM_VALUE_FIELD 8 + +#define STV090x_Px_AGC1QUAD(__x) (0xF40D - (__x - 1) * 0x200) +#define STV090x_P1_AGC1QUAD STV090x_Px_AGC1QUAD(1) +#define STV090x_P2_AGC1QUAD STV090x_Px_AGC1QUAD(2) +#define STV090x_OFFST_Px_QUAD_VALUE_FIELD 0 +#define STV090x_WIDTH_Px_QUAD_VALUE_FIELD 8 + +#define STV090x_Px_AGCIQINy(__x, __y) (0xF40F - (__x-1) * 0x200 - __y * 0x1) +#define STV090x_P1_AGCIQIN0 STV090x_Px_AGCIQINy(1, 0) +#define STV090x_P1_AGCIQIN1 STV090x_Px_AGCIQINy(1, 1) +#define STV090x_P2_AGCIQIN0 STV090x_Px_AGCIQINy(2, 0) +#define STV090x_P2_AGCIQIN1 STV090x_Px_AGCIQINy(2, 1) +#define STV090x_OFFST_Px_AGCIQ_VALUE_FIELD 0 +#define STV090x_WIDTH_Px_AGCIQ_VALUE_FIELD 8 + +#define STV090x_Px_DEMOD(__x) (0xF410 - (__x - 1) * 0x200) +#define STV090x_P1_DEMOD STV090x_Px_DEMOD(1) +#define STV090x_P2_DEMOD STV090x_Px_DEMOD(2) +#define STV090x_OFFST_Px_SPECINV_CONTROL_FIELD 4 +#define STV090x_WIDTH_Px_SPECINV_CONTROL_FIELD 2 +#define STV090x_OFFST_Px_MANUAL_ROLLOFF_FIELD 2 +#define STV090x_WIDTH_Px_MANUAL_ROLLOFF_FIELD 1 +#define STV090x_OFFST_Px_ROLLOFF_CONTROL_FIELD 0 +#define STV090x_WIDTH_Px_ROLLOFF_CONTROL_FIELD 2 + +#define STV090x_Px_DMDMODCOD(__x) (0xF411 - (__x - 1) * 0x200) +#define STV090x_P1_DMDMODCOD STV090x_Px_DMDMODCOD(1) +#define STV090x_P2_DMDMODCOD STV090x_Px_DMDMODCOD(2) +#define STV090x_OFFST_Px_MANUAL_MODCOD_FIELD 7 +#define STV090x_WIDTH_Px_MANUAL_MODCOD_FIELD 1 +#define STV090x_OFFST_Px_DEMOD_MODCOD_FIELD 2 +#define STV090x_WIDTH_Px_DEMOD_MODCOD_FIELD 5 +#define STV090x_OFFST_Px_DEMOD_TYPE_FIELD 0 +#define STV090x_WIDTH_Px_DEMOD_TYPE_FIELD 2 + +#define STV090x_Px_DSTATUS(__x) (0xF412 - (__x - 1) * 0x200) +#define STV090x_P1_DSTATUS STV090x_Px_DSTATUS(1) +#define STV090x_P2_DSTATUS STV090x_Px_DSTATUS(2) +#define STV090x_OFFST_Px_CAR_LOCK_FIELD 7 +#define STV090x_WIDTH_Px_CAR_LOCK_FIELD 1 +#define STV090x_OFFST_Px_TMGLOCK_QUALITY_FIELD 5 +#define STV090x_WIDTH_Px_TMGLOCK_QUALITY_FIELD 2 +#define STV090x_OFFST_Px_LOCK_DEFINITIF_FIELD 3 +#define STV090x_WIDTH_Px_LOCK_DEFINITIF_FIELD 1 + +#define STV090x_Px_DSTATUS2(__x) (0xF413 - (__x - 1) * 0x200) +#define STV090x_P1_DSTATUS2 STV090x_Px_DSTATUS2(1) +#define STV090x_P2_DSTATUS2 STV090x_Px_DSTATUS2(2) +#define STV090x_OFFST_Px_DEMOD_DELOCK_FIELD 7 +#define STV090x_WIDTH_Px_DEMOD_DELOCK_FIELD 1 +#define STV090x_OFFST_Px_AGC1_NOSIGNALACK_FIELD 3 +#define STV090x_WIDTH_Px_AGC1_NOSIGNALACK_FIELD 1 +#define STV090x_OFFST_Px_AGC2_OVERFLOW_FIELD 2 +#define STV090x_WIDTH_Px_AGC2_OVERFLOW_FIELD 1 +#define STV090x_OFFST_Px_CFR_OVERFLOW_FIELD 1 +#define STV090x_WIDTH_Px_CFR_OVERFLOW_FIELD 1 +#define STV090x_OFFST_Px_GAMMA_OVERUNDER_FIELD 0 +#define STV090x_WIDTH_Px_GAMMA_OVERUNDER_FIELD 1 + +#define STV090x_Px_DMDCFGMD(__x) (0xF414 - (__x - 1) * 0x200) +#define STV090x_P1_DMDCFGMD STV090x_Px_DMDCFGMD(1) +#define STV090x_P2_DMDCFGMD STV090x_Px_DMDCFGMD(2) +#define STV090x_OFFST_Px_DVBS2_ENABLE_FIELD 7 +#define STV090x_WIDTH_Px_DVBS2_ENABLE_FIELD 1 +#define STV090x_OFFST_Px_DVBS1_ENABLE_FIELD 6 +#define STV090x_WIDTH_Px_DVBS1_ENABLE_FIELD 1 +#define STV090x_OFFST_Px_CFR_AUTOSCAN_FIELD 5 /* check */ +#define STV090x_WIDTH_Px_CFR_AUTOSCAN_FIELD 1 +#define STV090x_OFFST_Px_SCAN_ENABLE_FIELD 4 /* check */ +#define STV090x_WIDTH_Px_SCAN_ENABLE_FIELD 1 +#define STV090x_OFFST_Px_TUN_AUTOSCAN_FIELD 3 +#define STV090x_WIDTH_Px_TUN_AUTOSCAN_FIELD 1 +#define STV090x_OFFST_Px_NOFORCE_RELOCK_FIELD 2 +#define STV090x_WIDTH_Px_NOFORCE_RELOCK_FIELD 1 +#define STV090x_OFFST_Px_TUN_RNG_FIELD 0 +#define STV090x_WIDTH_Px_TUN_RNG_FIELD 2 + +#define STV090x_Px_DMDCFG2(__x) (0xF415 - (__x - 1) * 0x200) +#define STV090x_P1_DMDCFG2 STV090x_Px_DMDCFG2(1) +#define STV090x_P2_DMDCFG2 STV090x_Px_DMDCFG2(2) +#define STV090x_OFFST_Px_S1S2_SEQUENTIAL_FIELD 6 +#define STV090x_WIDTH_Px_S1S2_SEQUENTIAL_FIELD 1 + +#define STV090x_Px_DMDISTATE(__x) (0xF416 - (__x - 1) * 0x200) +#define STV090x_P1_DMDISTATE STV090x_Px_DMDISTATE(1) +#define STV090x_P2_DMDISTATE STV090x_Px_DMDISTATE(2) +#define STV090x_OFFST_Px_I2C_DEMOD_MODE_FIELD 0 +#define STV090x_WIDTH_Px_I2C_DEMOD_MODE_FIELD 5 + +#define STV090x_Px_DMDTOM(__x) (0xF417 - (__x - 1) * 0x200) /* check */ +#define STV090x_P1_DMDTOM STV090x_Px_DMDTOM(1) +#define STV090x_P2_DMDTOM STV090x_Px_DMDTOM(2) + +#define STV090x_Px_DMDSTATE(__x) (0xF41B - (__x - 1) * 0x200) +#define STV090x_P1_DMDSTATE STV090x_Px_DMDSTATE(1) +#define STV090x_P2_DMDSTATE STV090x_Px_DMDSTATE(2) +#define STV090x_OFFST_Px_HEADER_MODE_FIELD 5 +#define STV090x_WIDTH_Px_HEADER_MODE_FIELD 2 + +#define STV090x_Px_DMDFLYW(__x) (0xF41C - (__x - 1) * 0x200) +#define STV090x_P1_DMDFLYW STV090x_Px_DMDFLYW(1) +#define STV090x_P2_DMDFLYW STV090x_Px_DMDFLYW(2) +#define STV090x_OFFST_Px_I2C_IRQVAL_FIELD 4 +#define STV090x_WIDTH_Px_I2C_IRQVAL_FIELD 4 +#define STV090x_OFFST_Px_FLYWHEEL_CPT_FIELD 0 /* check */ +#define STV090x_WIDTH_Px_FLYWHEEL_CPT_FIELD 4 + +#define STV090x_Px_DSTATUS3(__x) (0xF41D - (__x - 1) * 0x200) +#define STV090x_P1_DSTATUS3 STV090x_Px_DSTATUS3(1) +#define STV090x_P2_DSTATUS3 STV090x_Px_DSTATUS3(2) +#define STV090x_OFFST_Px_DEMOD_CFGMODE_FIELD 5 +#define STV090x_WIDTH_Px_DEMOD_CFGMODE_FIELD 2 + +#define STV090x_Px_DMDCFG3(__x) (0xF41E - (__x - 1) * 0x200) +#define STV090x_P1_DMDCFG3 STV090x_Px_DMDCFG3(1) +#define STV090x_P2_DMDCFG3 STV090x_Px_DMDCFG3(2) +#define STV090x_OFFST_Px_NOSTOP_FIFOFULL_FIELD 3 +#define STV090x_WIDTH_Px_NOSTOP_FIFOFULL_FIELD 1 + +#define STV090x_Px_CORRELMANT(__x) (0xF420 - (__x - 1) * 0x200) +#define STV090x_P1_CORRELMANT STV090x_Px_CORRELMANT(1) +#define STV090x_P2_CORRELMANT STV090x_Px_CORRELMANT(2) +#define STV090x_OFFST_Px_CORREL_MANT_FIELD 0 +#define STV090x_WIDTH_Px_CORREL_MANT_FIELD 8 + +#define STV090x_Px_CORRELABS(__x) (0xF421 - (__x - 1) * 0x200) +#define STV090x_P1_CORRELABS STV090x_Px_CORRELABS(1) +#define STV090x_P2_CORRELABS STV090x_Px_CORRELABS(2) +#define STV090x_OFFST_Px_CORREL_ABS_FIELD 0 +#define STV090x_WIDTH_Px_CORREL_ABS_FIELD 8 + +#define STV090x_Px_CORRELEXP(__x) (0xF422 - (__x - 1) * 0x200) +#define STV090x_P1_CORRELEXP STV090x_Px_CORRELEXP(1) +#define STV090x_P2_CORRELEXP STV090x_Px_CORRELEXP(2) +#define STV090x_OFFST_Px_CORREL_ABSEXP_FIELD 4 +#define STV090x_WIDTH_Px_CORREL_ABSEXP_FIELD 4 +#define STV090x_OFFST_Px_CORREL_EXP_FIELD 0 +#define STV090x_WIDTH_Px_CORREL_EXP_FIELD 4 + +#define STV090x_Px_PLHMODCOD(__x) (0xF424 - (__x - 1) * 0x200) +#define STV090x_P1_PLHMODCOD STV090x_Px_PLHMODCOD(1) +#define STV090x_P2_PLHMODCOD STV090x_Px_PLHMODCOD(2) +#define STV090x_OFFST_Px_SPECINV_DEMOD_FIELD 7 +#define STV090x_WIDTH_Px_SPECINV_DEMOD_FIELD 1 +#define STV090x_OFFST_Px_PLH_MODCOD_FIELD 2 +#define STV090x_WIDTH_Px_PLH_MODCOD_FIELD 5 +#define STV090x_OFFST_Px_PLH_TYPE_FIELD 0 +#define STV090x_WIDTH_Px_PLH_TYPE_FIELD 2 + +#define STV090x_Px_AGC2REF(__x) (0xF42D - (__x - 1) * 0x200) +#define STV090x_P1_AGC2REF STV090x_Px_AGC2REF(1) +#define STV090x_P2_AGC2REF STV090x_Px_AGC2REF(2) +#define STV090x_OFFST_Px_AGC2_REF_FIELD 0 +#define STV090x_WIDTH_Px_AGC2_REF_FIELD 8 + +#define STV090x_Px_AGC1ADJ(__x) (0xF42E - (__x - 1) * 0x200) +#define STV090x_P1_AGC1ADJ STV090x_Px_AGC1ADJ(1) +#define STV090x_P2_AGC1ADJ STV090x_Px_AGC1ADJ(2) +#define STV090x_OFFST_Px_AGC1_ADJUSTED_FIELD 0 +#define STV090x_WIDTH_Px_AGC1_ADJUSTED_FIELD 7 + +#define STV090x_Px_AGC2Iy(__x, __y) (0xF437 - (__x - 1) * 0x200 - __y * 0x1) +#define STV090x_P1_AGC2I0 STV090x_Px_AGC2Iy(1, 0) +#define STV090x_P1_AGC2I1 STV090x_Px_AGC2Iy(1, 1) +#define STV090x_P2_AGC2I0 STV090x_Px_AGC2Iy(2, 0) +#define STV090x_P2_AGC2I1 STV090x_Px_AGC2Iy(2, 1) +#define STV090x_OFFST_Px_AGC2_INTEGRATOR_FIELD 0 +#define STV090x_WIDTH_Px_AGC2_INTEGRATOR_FIELD 8 + +#define STV090x_Px_CARCFG(__x) (0xF438 - (__x - 1) * 0x200) +#define STV090x_P1_CARCFG STV090x_Px_CARCFG(1) +#define STV090x_P2_CARCFG STV090x_Px_CARCFG(2) +#define STV090x_OFFST_Px_EN_CAR2CENTER_FIELD 5 +#define STV090x_WIDTH_Px_EN_CAR2CENTER_FIELD 1 +#define STV090x_OFFST_Px_ROTATON_FIELD 2 +#define STV090x_WIDTH_Px_ROTATON_FIELD 1 +#define STV090x_OFFST_Px_PH_DET_ALGO_FIELD 0 +#define STV090x_WIDTH_Px_PH_DET_ALGO_FIELD 2 + +#define STV090x_Px_ACLC(__x) (0xF439 - (__x - 1) * 0x200) +#define STV090x_P1_ACLC STV090x_Px_ACLC(1) +#define STV090x_P2_ACLC STV090x_Px_ACLC(2) +#define STV090x_OFFST_Px_CAR_ALPHA_MANT_FIELD 4 +#define STV090x_WIDTH_Px_CAR_ALPHA_MANT_FIELD 2 +#define STV090x_OFFST_Px_CAR_ALPHA_EXP_FIELD 0 +#define STV090x_WIDTH_Px_CAR_ALPHA_EXP_FIELD 4 + +#define STV090x_Px_BCLC(__x) (0xF43A - (__x - 1) * 0x200) +#define STV090x_P1_BCLC STV090x_Px_BCLC(1) +#define STV090x_P2_BCLC STV090x_Px_BCLC(2) +#define STV090x_OFFST_Px_CAR_BETA_MANT_FIELD 4 +#define STV090x_WIDTH_Px_CAR_BETA_MANT_FIELD 2 +#define STV090x_OFFST_Px_CAR_BETA_EXP_FIELD 0 +#define STV090x_WIDTH_Px_CAR_BETA_EXP_FIELD 4 + +#define STV090x_Px_CARFREQ(__x) (0xF43D - (__x - 1) * 0x200) +#define STV090x_P1_CARFREQ STV090x_Px_CARFREQ(1) +#define STV090x_P2_CARFREQ STV090x_Px_CARFREQ(2) +#define STV090x_OFFST_Px_KC_COARSE_EXP_FIELD 4 +#define STV090x_WIDTH_Px_KC_COARSE_EXP_FIELD 4 +#define STV090x_OFFST_Px_BETA_FREQ_FIELD 0 +#define STV090x_WIDTH_Px_BETA_FREQ_FIELD 4 + +#define STV090x_Px_CARHDR(__x) (0xF43E - (__x - 1) * 0x200) +#define STV090x_P1_CARHDR STV090x_Px_CARHDR(1) +#define STV090x_P2_CARHDR STV090x_Px_CARHDR(2) +#define STV090x_OFFST_Px_FREQ_HDR_FIELD 0 +#define STV090x_WIDTH_Px_FREQ_HDR_FIELD 8 + +#define STV090x_Px_LDT(__x) (0xF43F - (__x - 1) * 0x200) +#define STV090x_P1_LDT STV090x_Px_LDT(1) +#define STV090x_P2_LDT STV090x_Px_LDT(2) +#define STV090x_OFFST_Px_CARLOCK_THRES_FIELD 0 +#define STV090x_WIDTH_Px_CARLOCK_THRES_FIELD 8 + +#define STV090x_Px_LDT2(__x) (0xF440 - (__x - 1) * 0x200) +#define STV090x_P1_LDT2 STV090x_Px_LDT2(1) +#define STV090x_P2_LDT2 STV090x_Px_LDT2(2) +#define STV090x_OFFST_Px_CARLOCK_THRES2_FIELD 0 +#define STV090x_WIDTH_Px_CARLOCK_THRES2_FIELD 8 + +#define STV090x_Px_CFRICFG(__x) (0xF441 - (__x - 1) * 0x200) +#define STV090x_P1_CFRICFG STV090x_Px_CFRICFG(1) +#define STV090x_P2_CFRICFG STV090x_Px_CFRICFG(2) +#define STV090x_OFFST_Px_NEG_CFRSTEP_FIELD 0 +#define STV090x_WIDTH_Px_NEG_CFRSTEP_FIELD 1 + +#define STV090x_Pn_CFRUPy(__x, __y) (0xF443 - (__x - 1) * 0x200 - __y * 0x1) +#define STV090x_P1_CFRUP0 STV090x_Pn_CFRUPy(1, 0) +#define STV090x_P1_CFRUP1 STV090x_Pn_CFRUPy(1, 1) +#define STV090x_P2_CFRUP0 STV090x_Pn_CFRUPy(2, 0) +#define STV090x_P2_CFRUP1 STV090x_Pn_CFRUPy(2, 1) +#define STV090x_OFFST_Px_CFR_UP_FIELD 0 +#define STV090x_WIDTH_Px_CFR_UP_FIELD 8 + +#define STV090x_Pn_CFRLOWy(__x, __y) (0xF447 - (__x - 1) * 0x200 - __y * 0x1) +#define STV090x_P1_CFRLOW0 STV090x_Pn_CFRLOWy(1, 0) +#define STV090x_P1_CFRLOW1 STV090x_Pn_CFRLOWy(1, 1) +#define STV090x_P2_CFRLOW0 STV090x_Pn_CFRLOWy(2, 0) +#define STV090x_P2_CFRLOW1 STV090x_Pn_CFRLOWy(2, 1) +#define STV090x_OFFST_Px_CFR_LOW_FIELD 0 +#define STV090x_WIDTH_Px_CFR_LOW_FIELD 8 + +#define STV090x_Pn_CFRINITy(__x, __y) (0xF449 - (__x - 1) * 0x200 - __y * 0x1) +#define STV090x_P1_CFRINIT0 STV090x_Pn_CFRINITy(1, 0) +#define STV090x_P1_CFRINIT1 STV090x_Pn_CFRINITy(1, 1) +#define STV090x_P2_CFRINIT0 STV090x_Pn_CFRINITy(2, 0) +#define STV090x_P2_CFRINIT1 STV090x_Pn_CFRINITy(2, 1) +#define STV090x_OFFST_Px_CFR_INIT_FIELD 0 +#define STV090x_WIDTH_Px_CFR_INIT_FIELD 8 + +#define STV090x_Px_CFRINC1(__x) (0xF44A - (__x - 1) * 0x200) +#define STV090x_P1_CFRINC1 STV090x_Px_CFRINC1(1) +#define STV090x_P2_CFRINC1 STV090x_Px_CFRINC1(2) +#define STV090x_OFFST_Px_CFR_INC1_FIELD 0 +#define STV090x_WIDTH_Px_CFR_INC1_FIELD 7 + +#define STV090x_Px_CFRINC0(__x) (0xF44B - (__x - 1) * 0x200) +#define STV090x_P1_CFRINC0 STV090x_Px_CFRINC0(1) +#define STV090x_P2_CFRINC0 STV090x_Px_CFRINC0(2) +#define STV090x_OFFST_Px_CFR_INC0_FIELD 4 +#define STV090x_WIDTH_Px_CFR_INC0_FIELD 4 + +#define STV090x_Pn_CFRy(__x, __y) (0xF44E - (__x - 1) * 0x200 - __y * 0x1) +#define STV090x_P1_CFR0 STV090x_Pn_CFRy(1, 0) +#define STV090x_P1_CFR1 STV090x_Pn_CFRy(1, 1) +#define STV090x_P1_CFR2 STV090x_Pn_CFRy(1, 2) +#define STV090x_P2_CFR0 STV090x_Pn_CFRy(2, 0) +#define STV090x_P2_CFR1 STV090x_Pn_CFRy(2, 1) +#define STV090x_P2_CFR2 STV090x_Pn_CFRy(2, 2) +#define STV090x_OFFST_Px_CAR_FREQ_FIELD 0 +#define STV090x_WIDTH_Px_CAR_FREQ_FIELD 8 + +#define STV090x_Px_LDI(__x) (0xF44F - (__x - 1) * 0x200) +#define STV090x_P1_LDI STV090x_Px_LDI(1) +#define STV090x_P2_LDI STV090x_Px_LDI(2) +#define STV090x_OFFST_Px_LOCK_DET_INTEGR_FIELD 0 +#define STV090x_WIDTH_Px_LOCK_DET_INTEGR_FIELD 8 + +#define STV090x_Px_TMGCFG(__x) (0xF450 - (__x - 1) * 0x200) +#define STV090x_P1_TMGCFG STV090x_Px_TMGCFG(1) +#define STV090x_P2_TMGCFG STV090x_Px_TMGCFG(2) +#define STV090x_OFFST_Px_TMGLOCK_BETA_FIELD 6 +#define STV090x_WIDTH_Px_TMGLOCK_BETA_FIELD 2 +#define STV090x_OFFST_Px_DO_TIMING_FIELD 4 +#define STV090x_WIDTH_Px_DO_TIMING_FIELD 1 +#define STV090x_OFFST_Px_TMG_MINFREQ_FIELD 0 +#define STV090x_WIDTH_Px_TMG_MINFREQ_FIELD 2 + +#define STV090x_Px_RTC(__x) (0xF451 - (__x - 1) * 0x200) +#define STV090x_P1_RTC STV090x_Px_RTC(1) +#define STV090x_P2_RTC STV090x_Px_RTC(2) +#define STV090x_OFFST_Px_TMGALPHA_EXP_FIELD 4 +#define STV090x_WIDTH_Px_TMGALPHA_EXP_FIELD 4 +#define STV090x_OFFST_Px_TMGBETA_EXP_FIELD 0 +#define STV090x_WIDTH_Px_TMGBETA_EXP_FIELD 4 + +#define STV090x_Px_RTCS2(__x) (0xF452 - (__x - 1) * 0x200) +#define STV090x_P1_RTCS2 STV090x_Px_RTCS2(1) +#define STV090x_P2_RTCS2 STV090x_Px_RTCS2(2) +#define STV090x_OFFST_Px_TMGALPHAS2_EXP_FIELD 4 +#define STV090x_WIDTH_Px_TMGALPHAS2_EXP_FIELD 4 +#define STV090x_OFFST_Px_TMGBETAS2_EXP_FIELD 0 +#define STV090x_WIDTH_Px_TMGBETAS2_EXP_FIELD 4 + +#define STV090x_Px_TMGTHRISE(__x) (0xF453 - (__x - 1) * 0x200) +#define STV090x_P1_TMGTHRISE STV090x_Px_TMGTHRISE(1) +#define STV090x_P2_TMGTHRISE STV090x_Px_TMGTHRISE(2) +#define STV090x_OFFST_Px_TMGLOCK_THRISE_FIELD 0 +#define STV090x_WIDTH_Px_TMGLOCK_THRISE_FIELD 8 + +#define STV090x_Px_TMGTHFALL(__x) (0xF454 - (__x - 1) * 0x200) +#define STV090x_P1_TMGTHFALL STV090x_Px_TMGTHFALL(1) +#define STV090x_P2_TMGTHFALL STV090x_Px_TMGTHFALL(2) +#define STV090x_OFFST_Px_TMGLOCK_THFALL_FIELD 0 +#define STV090x_WIDTH_Px_TMGLOCK_THFALL_FIELD 8 + +#define STV090x_Px_SFRUPRATIO(__x) (0xF455 - (__x - 1) * 0x200) +#define STV090x_P1_SFRUPRATIO STV090x_Px_SFRUPRATIO(1) +#define STV090x_P2_SFRUPRATIO STV090x_Px_SFRUPRATIO(2) +#define STV090x_OFFST_Px_SFR_UPRATIO_FIELD 0 +#define STV090x_WIDTH_Px_SFR_UPRATIO_FIELD 8 + +#define STV090x_Px_SFRLOWRATIO(__x) (0xF456 - (__x - 1) * 0x200) +#define STV090x_P1_SFRLOWRATIO STV090x_Px_SFRLOWRATIO(1) +#define STV090x_P2_SFRLOWRATIO STV090x_Px_SFRLOWRATIO(2) +#define STV090x_OFFST_Px_SFR_LOWRATIO_FIELD 0 +#define STV090x_WIDTH_Px_SFR_LOWRATIO_FIELD 8 + +#define STV090x_Px_KREFTMG(__x) (0xF458 - (__x - 1) * 0x200) +#define STV090x_P1_KREFTMG STV090x_Px_KREFTMG(1) +#define STV090x_P2_KREFTMG STV090x_Px_KREFTMG(2) +#define STV090x_OFFST_Px_KREF_TMG_FIELD 0 +#define STV090x_WIDTH_Px_KREF_TMG_FIELD 8 + +#define STV090x_Px_SFRSTEP(__x) (0xF459 - (__x - 1) * 0x200) +#define STV090x_P1_SFRSTEP STV090x_Px_SFRSTEP(1) +#define STV090x_P2_SFRSTEP STV090x_Px_SFRSTEP(2) +#define STV090x_OFFST_Px_SFR_SCANSTEP_FIELD 4 +#define STV090x_WIDTH_Px_SFR_SCANSTEP_FIELD 4 +#define STV090x_OFFST_Px_SFR_CENTERSTEP_FIELD 0 +#define STV090x_WIDTH_Px_SFR_CENTERSTEP_FIELD 4 + +#define STV090x_Px_TMGCFG2(__x) (0xF45A - (__x - 1) * 0x200) +#define STV090x_P1_TMGCFG2 STV090x_Px_TMGCFG2(1) +#define STV090x_P2_TMGCFG2 STV090x_Px_TMGCFG2(2) +#define STV090x_OFFST_Px_SFRRATIO_FINE_FIELD 0 +#define STV090x_WIDTH_Px_SFRRATIO_FINE_FIELD 1 + +#define STV090x_Px_SFRINIT1(__x) (0xF45E - (__x - 1) * 0x200) +#define STV090x_P1_SFRINIT1 STV090x_Px_SFRINIT1(1) +#define STV090x_P2_SFRINIT1 STV090x_Px_SFRINIT1(2) +#define STV090x_OFFST_Px_SFR_INIT_FIELD 0 +#define STV090x_WIDTH_Px_SFR_INIT_FIELD 8 + +#define STV090x_Px_SFRINIT0(__x) (0xF45F - (__x - 1) * 0x200) +#define STV090x_P1_SFRINIT0 STV090x_Px_SFRINIT0(1) +#define STV090x_P2_SFRINIT0 STV090x_Px_SFRINIT0(2) +#define STV090x_OFFST_Px_SFR_INIT_FIELD 0 +#define STV090x_WIDTH_Px_SFR_INIT_FIELD 8 + +#define STV090x_Px_SFRUP1(__x) (0xF460 - (__x - 1) * 0x200) +#define STV090x_P1_SFRUP1 STV090x_Px_SFRUP1(1) +#define STV090x_P2_SFRUP1 STV090x_Px_SFRUP1(2) +#define STV090x_OFFST_Px_SYMB_FREQ_UP1_FIELD 0 +#define STV090x_WIDTH_Px_SYMB_FREQ_UP1_FIELD 7 + +#define STV090x_Px_SFRUP0(__x) (0xF461 - (__x - 1) * 0x200) +#define STV090x_P1_SFRUP0 STV090x_Px_SFRUP0(1) +#define STV090x_P2_SFRUP0 STV090x_Px_SFRUP0(2) +#define STV090x_OFFST_Px_SYMB_FREQ_UP0_FIELD 0 +#define STV090x_WIDTH_Px_SYMB_FREQ_UP0_FIELD 8 + +#define STV090x_Px_SFRLOW1(__x) (0xF462 - (__x - 1) * 0x200) +#define STV090x_P1_SFRLOW1 STV090x_Px_SFRLOW1(1) +#define STV090x_P2_SFRLOW1 STV090x_Px_SFRLOW1(2) +#define STV090x_OFFST_Px_SYMB_FREQ_LOW1_FIELD 0 +#define STV090x_WIDTH_Px_SYMB_FREQ_LOW1_FIELD 7 + +#define STV090x_Px_SFRLOW0(__x) (0xF463 - (__x - 1) * 0x200) +#define STV090x_P1_SFRLOW0 STV090x_Px_SFRLOW0(1) +#define STV090x_P2_SFRLOW0 STV090x_Px_SFRLOW0(2) +#define STV090x_OFFST_Px_SYMB_FREQ_LOW0_FIELD 0 +#define STV090x_WIDTH_Px_SYMB_FREQ_LOW0_FIELD 8 + +#define STV090x_Px_SFRy(__x, __y) (0xF464 - (__x-1) * 0x200 + (3 - __y)) +#define STV090x_P1_SFR0 STV090x_Px_SFRy(1, 0) +#define STV090x_P1_SFR1 STV090x_Px_SFRy(1, 1) +#define STV090x_P1_SFR2 STV090x_Px_SFRy(1, 2) +#define STV090x_P1_SFR3 STV090x_Px_SFRy(1, 3) +#define STV090x_P2_SFR0 STV090x_Px_SFRy(2, 0) +#define STV090x_P2_SFR1 STV090x_Px_SFRy(2, 1) +#define STV090x_P2_SFR2 STV090x_Px_SFRy(2, 2) +#define STV090x_P2_SFR3 STV090x_Px_SFRy(2, 3) +#define STV090x_OFFST_Px_SYMB_FREQ_FIELD 0 +#define STV090x_WIDTH_Px_SYMB_FREQ_FIELD 32 + +#define STV090x_Px_TMGREG2(__x) (0xF468 - (__x - 1) * 0x200) +#define STV090x_P1_TMGREG2 STV090x_Px_TMGREG2(1) +#define STV090x_P2_TMGREG2 STV090x_Px_TMGREG2(2) +#define STV090x_OFFST_Px_TMGREG_FIELD 0 +#define STV090x_WIDTH_Px_TMGREG_FIELD 8 + +#define STV090x_Px_TMGREG1(__x) (0xF469 - (__x - 1) * 0x200) +#define STV090x_P1_TMGREG1 STV090x_Px_TMGREG1(1) +#define STV090x_P2_TMGREG1 STV090x_Px_TMGREG1(2) +#define STV090x_OFFST_Px_TMGREG_FIELD 0 +#define STV090x_WIDTH_Px_TMGREG_FIELD 8 + +#define STV090x_Px_TMGREG0(__x) (0xF46A - (__x - 1) * 0x200) +#define STV090x_P1_TMGREG0 STV090x_Px_TMGREG0(1) +#define STV090x_P2_TMGREG0 STV090x_Px_TMGREG0(2) +#define STV090x_OFFST_Px_TMGREG_FIELD 0 +#define STV090x_WIDTH_Px_TMGREG_FIELD 8 + +#define STV090x_Px_TMGLOCKy(__x, __y) (0xF46C - (__x - 1) * 0x200 - __y * 0x1) +#define STV090x_P1_TMGLOCK0 STV090x_Px_TMGLOCKy(1, 0) +#define STV090x_P1_TMGLOCK1 STV090x_Px_TMGLOCKy(1, 1) +#define STV090x_P2_TMGLOCK0 STV090x_Px_TMGLOCKy(2, 0) +#define STV090x_P2_TMGLOCK1 STV090x_Px_TMGLOCKy(2, 1) +#define STV090x_OFFST_Px_TMGLOCK_LEVEL_FIELD 0 +#define STV090x_WIDTH_Px_TMGLOCK_LEVEL_FIELD 8 + +#define STV090x_Px_TMGOBS(__x) (0xF46D - (__x - 1) * 0x200) +#define STV090x_P1_TMGOBS STV090x_Px_TMGOBS(1) +#define STV090x_P2_TMGOBS STV090x_Px_TMGOBS(2) +#define STV090x_OFFST_Px_ROLLOFF_STATUS_FIELD 6 +#define STV090x_WIDTH_Px_ROLLOFF_STATUS_FIELD 2 + +#define STV090x_Px_EQUALCFG(__x) (0xF46F - (__x - 1) * 0x200) +#define STV090x_P1_EQUALCFG STV090x_Px_EQUALCFG(1) +#define STV090x_P2_EQUALCFG STV090x_Px_EQUALCFG(2) +#define STV090x_OFFST_Px_EQUAL_ON_FIELD 6 +#define STV090x_WIDTH_Px_EQUAL_ON_FIELD 1 +#define STV090x_OFFST_Px_MU_EQUALDFE_FIELD 0 +#define STV090x_WIDTH_Px_MU_EQUALDFE_FIELD 3 + +#define STV090x_Px_EQUAIy(__x, __y) (0xf470 - (__x - 1) * 0x200 + (__y - 1)) +#define STV090x_P1_EQUAI1 STV090x_Px_EQUAIy(1, 1) +#define STV090x_P1_EQUAI2 STV090x_Px_EQUAIy(1, 2) +#define STV090x_P1_EQUAI3 STV090x_Px_EQUAIy(1, 3) +#define STV090x_P1_EQUAI4 STV090x_Px_EQUAIy(1, 4) +#define STV090x_P1_EQUAI5 STV090x_Px_EQUAIy(1, 5) +#define STV090x_P1_EQUAI6 STV090x_Px_EQUAIy(1, 6) +#define STV090x_P1_EQUAI7 STV090x_Px_EQUAIy(1, 7) +#define STV090x_P1_EQUAI8 STV090x_Px_EQUAIy(1, 8) + +#define STV090x_P2_EQUAI1 STV090x_Px_EQUAIy(2, 1) +#define STV090x_P2_EQUAI2 STV090x_Px_EQUAIy(2, 2) +#define STV090x_P2_EQUAI3 STV090x_Px_EQUAIy(2, 3) +#define STV090x_P2_EQUAI4 STV090x_Px_EQUAIy(2, 4) +#define STV090x_P2_EQUAI5 STV090x_Px_EQUAIy(2, 5) +#define STV090x_P2_EQUAI6 STV090x_Px_EQUAIy(2, 6) +#define STV090x_P2_EQUAI7 STV090x_Px_EQUAIy(2, 7) +#define STV090x_P2_EQUAI8 STV090x_Px_EQUAIy(2, 8) +#define STV090x_OFFST_Px_EQUA_ACCIy_FIELD 0 +#define STV090x_WIDTH_Px_EQUA_ACCIy_FIELD 8 + +#define STV090x_Px_EQUAQy(__x, __y) (0xf471 - (__x - 1) * 0x200 + (__y - 1)) +#define STV090x_P1_EQUAQ1 STV090x_Px_EQUAQy(1, 1) +#define STV090x_P1_EQUAQ2 STV090x_Px_EQUAQy(1, 2) +#define STV090x_P1_EQUAQ3 STV090x_Px_EQUAQy(1, 3) +#define STV090x_P1_EQUAQ4 STV090x_Px_EQUAQy(1, 4) +#define STV090x_P1_EQUAQ5 STV090x_Px_EQUAQy(1, 5) +#define STV090x_P1_EQUAQ6 STV090x_Px_EQUAQy(1, 6) +#define STV090x_P1_EQUAQ7 STV090x_Px_EQUAQy(1, 7) +#define STV090x_P1_EQUAQ8 STV090x_Px_EQUAQy(1, 8) + +#define STV090x_P2_EQUAQ1 STV090x_Px_EQUAQy(2, 1) +#define STV090x_P2_EQUAQ2 STV090x_Px_EQUAQy(2, 2) +#define STV090x_P2_EQUAQ3 STV090x_Px_EQUAQy(2, 3) +#define STV090x_P2_EQUAQ4 STV090x_Px_EQUAQy(2, 4) +#define STV090x_P2_EQUAQ5 STV090x_Px_EQUAQy(2, 5) +#define STV090x_P2_EQUAQ6 STV090x_Px_EQUAQy(2, 6) +#define STV090x_P2_EQUAQ7 STV090x_Px_EQUAQy(2, 7) +#define STV090x_P2_EQUAQ8 STV090x_Px_EQUAQy(2, 8) +#define STV090x_OFFST_Px_EQUA_ACCQy_FIELD 0 +#define STV090x_WIDTH_Px_EQUA_ACCQy_FIELD 8 + +#define STV090x_Px_NNOSDATATy(__x, __y) (0xf481 - (__x - 1) * 0x200 - __y * 0x1) +#define STV090x_P1_NNOSDATAT0 STV090x_Px_NNOSDATATy(1, 0) +#define STV090x_P1_NNOSDATAT1 STV090x_Px_NNOSDATATy(1, 1) +#define STV090x_P2_NNOSDATAT0 STV090x_Px_NNOSDATATy(2, 0) +#define STV090x_P2_NNOSDATAT1 STV090x_Px_NNOSDATATy(2, 1) +#define STV090x_OFFST_Px_NOSDATAT_NORMED_FIELD 0 +#define STV090x_WIDTH_Px_NOSDATAT_NORMED_FIELD 8 + +#define STV090x_Px_NNOSDATAy(__x, __y) (0xf483 - (__x - 1) * 0x200 - __y * 0x1) +#define STV090x_P1_NNOSDATA0 STV090x_Px_NNOSDATAy(1, 0) +#define STV090x_P1_NNOSDATA1 STV090x_Px_NNOSDATAy(1, 1) +#define STV090x_P2_NNOSDATA0 STV090x_Px_NNOSDATAy(2, 0) +#define STV090x_P2_NNOSDATA1 STV090x_Px_NNOSDATAy(2, 1) +#define STV090x_OFFST_Px_NOSDATA_NORMED_FIELD 0 +#define STV090x_WIDTH_Px_NOSDATA_NORMED_FIELD 8 + +#define STV090x_Px_NNOSPLHTy(__x, __y) (0xf485 - (__x - 1) * 0x200 - __y * 0x1) +#define STV090x_P1_NNOSPLHT0 STV090x_Px_NNOSPLHTy(1, 0) +#define STV090x_P1_NNOSPLHT1 STV090x_Px_NNOSPLHTy(1, 1) +#define STV090x_P2_NNOSPLHT0 STV090x_Px_NNOSPLHTy(2, 0) +#define STV090x_P2_NNOSPLHT1 STV090x_Px_NNOSPLHTy(2, 1) +#define STV090x_OFFST_Px_NOSPLHT_NORMED_FIELD 0 +#define STV090x_WIDTH_Px_NOSPLHT_NORMED_FIELD 8 + +#define STV090x_Px_NNOSPLHy(__x, __y) (0xf487 - (__x - 1) * 0x200 - __y * 0x1) +#define STV090x_P1_NNOSPLH0 STV090x_Px_NNOSPLHy(1, 0) +#define STV090x_P1_NNOSPLH1 STV090x_Px_NNOSPLHy(1, 1) +#define STV090x_P2_NNOSPLH0 STV090x_Px_NNOSPLHy(2, 0) +#define STV090x_P2_NNOSPLH1 STV090x_Px_NNOSPLHy(2, 1) +#define STV090x_OFFST_Px_NOSPLH_NORMED_FIELD 0 +#define STV090x_WIDTH_Px_NOSPLH_NORMED_FIELD 8 + +#define STV090x_Px_NOSDATATy(__x, __y) (0xf489 - (__x - 1) * 0x200 - __y * 0x1) +#define STV090x_P1_NOSDATAT0 STV090x_Px_NOSDATATy(1, 0) +#define STV090x_P1_NOSDATAT1 STV090x_Px_NOSDATATy(1, 1) +#define STV090x_P2_NOSDATAT0 STV090x_Px_NOSDATATy(2, 0) +#define STV090x_P2_NOSDATAT1 STV090x_Px_NOSDATATy(2, 1) +#define STV090x_OFFST_Px_NOSDATAT_UNNORMED_FIELD 0 +#define STV090x_WIDTH_Px_NOSDATAT_UNNORMED_FIELD 8 + +#define STV090x_Px_NOSDATAy(__x, __y) (0xf48b - (__x - 1) * 0x200 - __y * 0x1) +#define STV090x_P1_NOSDATA0 STV090x_Px_NOSDATAy(1, 0) +#define STV090x_P1_NOSDATA1 STV090x_Px_NOSDATAy(1, 1) +#define STV090x_P2_NOSDATA0 STV090x_Px_NOSDATAy(2, 0) +#define STV090x_P2_NOSDATA1 STV090x_Px_NOSDATAy(2, 1) +#define STV090x_OFFST_Px_NOSDATA_UNNORMED_FIELD 0 +#define STV090x_WIDTH_Px_NOSDATA_UNNORMED_FIELD 8 + +#define STV090x_Px_NOSPLHTy(__x, __y) (0xf48d - (__x - 1) * 0x200 - __y * 0x1) +#define STV090x_P1_NOSPLHT0 STV090x_Px_NOSPLHTy(1, 0) +#define STV090x_P1_NOSPLHT1 STV090x_Px_NOSPLHTy(1, 1) +#define STV090x_P2_NOSPLHT0 STV090x_Px_NOSPLHTy(2, 0) +#define STV090x_P2_NOSPLHT1 STV090x_Px_NOSPLHTy(2, 1) +#define STV090x_OFFST_Px_NOSPLHT_UNNORMED_FIELD 0 +#define STV090x_WIDTH_Px_NOSPLHT_UNNORMED_FIELD 8 + +#define STV090x_Px_NOSPLHy(__x, __y) (0xf48f - (__x - 1) * 0x200 - __y * 0x1) +#define STv090x_P1_NOSPLH0 STV090x_Px_NOSPLHy(1, 0) +#define STv090x_P1_NOSPLH1 STV090x_Px_NOSPLHy(1, 1) +#define STv090x_P2_NOSPLH0 STV090x_Px_NOSPLHy(2, 0) +#define STv090x_P2_NOSPLH1 STV090x_Px_NOSPLHy(2, 1) +#define STV090x_OFFST_Px_NOSPLH_UNNORMED_FIELD 0 +#define STV090x_WIDTH_Px_NOSPLH_UNNORMED_FIELD 8 + +#define STV090x_Px_CAR2CFG(__x) (0xf490 - (__x - 1) * 0x200) +#define STV090x_P1_CAR2CFG STV090x_Px_CAR2CFG(1) +#define STV090x_P2_CAR2CFG STV090x_Px_CAR2CFG(2) +#define STV090x_OFFST_Px_PN4_SELECT_FIELD 6 +#define STV090x_WIDTH_Px_PN4_SELECT_FIELD 1 +#define STV090x_OFFST_Px_CFR2_STOPDVBS1_FIELD 5 +#define STV090x_WIDTH_Px_CFR2_STOPDVBS1_FIELD 1 +#define STV090x_OFFST_Px_ROTA2ON_FIELD 2 +#define STV090x_WIDTH_Px_ROTA2ON_FIELD 1 +#define STV090x_OFFST_Px_PH_DET_ALGO2_FIELD 0 +#define STV090x_WIDTH_Px_PH_DET_ALGO2_FIELD 2 + +#define STV090x_Px_ACLC2(__x) (0xf491 - (__x - 1) * 0x200) +#define STV090x_P1_ACLC2 STV090x_Px_ACLC2(1) +#define STV090x_P2_ACLC2 STV090x_Px_ACLC2(2) +#define STV090x_OFFST_Px_CAR2_ALPHA_MANT_FIELD 4 +#define STV090x_WIDTH_Px_CAR2_ALPHA_MANT_FIELD 2 +#define STV090x_OFFST_Px_CAR2_ALPHA_EXP_FIELD 0 +#define STV090x_WIDTH_Px_CAR2_ALPHA_EXP_FIELD 4 + +#define STV090x_Px_BCLC2(__x) (0xf492 - (__x - 1) * 0x200) +#define STV090x_P1_BCLC2 STV090x_Px_BCLC2(1) +#define STV090x_P2_BCLC2 STV090x_Px_BCLC2(2) +#define STV090x_OFFST_Px_CAR2_BETA_MANT_FIELD 4 +#define STV090x_WIDTH_Px_CAR2_BETA_MANT_FIELD 2 +#define STV090x_OFFST_Px_CAR2_BETA_EXP_FIELD 0 +#define STV090x_WIDTH_Px_CAR2_BETA_EXP_FIELD 4 + +#define STV090x_Px_ACLC2S2Q(__x) (0xf497 - (__x - 1) * 0x200) +#define STV090x_P1_ACLC2S2Q STV090x_Px_ACLC2S2Q(1) +#define STV090x_P2_ACLC2S2Q STV090x_Px_ACLC2S2Q(2) +#define STV090x_OFFST_Px_ENAB_SPSKSYMB_FIELD 7 +#define STV090x_WIDTH_Px_ENAB_SPSKSYMB_FIELD 1 +#define STV090x_OFFST_Px_CAR2S2_Q_ALPH_M_FIELD 4 +#define STV090x_WIDTH_Px_CAR2S2_Q_ALPH_M_FIELD 2 +#define STV090x_OFFST_Px_CAR2S2_Q_ALPH_E_FIELD 0 +#define STV090x_WIDTH_Px_CAR2S2_Q_ALPH_E_FIELD 4 + +#define STV090x_Px_ACLC2S28(__x) (0xf498 - (__x - 1) * 0x200) +#define STV090x_P1_ACLC2S28 STV090x_Px_ACLC2S28(1) +#define STV090x_P2_ACLC2S28 STV090x_Px_ACLC2S28(2) +#define STV090x_OFFST_Px_CAR2S2_8_ALPH_M_FIELD 4 +#define STV090x_WIDTH_Px_CAR2S2_8_ALPH_M_FIELD 2 +#define STV090x_OFFST_Px_CAR2S2_8_ALPH_E_FIELD 0 +#define STV090x_WIDTH_Px_CAR2S2_8_ALPH_E_FIELD 4 + +#define STV090x_Px_ACLC2S216A(__x) (0xf499 - (__x - 1) * 0x200) +#define STV090x_P1_ACLC2S216A STV090x_Px_ACLC2S216A(1) +#define STV090x_P2_ACLC2S216A STV090x_Px_ACLC2S216A(2) +#define STV090x_OFFST_Px_CAR2S2_16A_ALPH_M_FIELD 4 +#define STV090x_WIDTH_Px_CAR2S2_16A_ALPH_M_FIELD 2 +#define STV090x_OFFST_Px_CAR2S2_16A_ALPH_E_FIELD 0 +#define STV090x_WIDTH_Px_CAR2S2_16A_ALPH_E_FIELD 4 + +#define STV090x_Px_ACLC2S232A(__x) (0xf499 - (__x - 1) * 0x200) +#define STV090x_P1_ACLC2S232A STV090x_Px_ACLC2S216A(1) +#define STV090x_P2_ACLC2S232A STV090x_Px_ACLC2S216A(2) +#define STV090x_OFFST_Px_CAR2S2_32A_ALPH_M_FIELD 4 +#define STV090x_WIDTH_Px_CAR2S2_32A_ALPH_M_FIELD 2 +#define STV090x_OFFST_Px_CAR2S2_32A_ALPH_E_FIELD 0 +#define STV090x_WIDTH_Px_CAR2S2_32A_ALPH_E_FIELD 4 + +#define STV090x_Px_BCLC2S2Q(__x) (0xf49c - (__x - 1) * 0x200) +#define STV090x_P1_BCLC2S2Q STV090x_Px_BCLC2S2Q(1) +#define STV090x_P2_BCLC2S2Q STV090x_Px_BCLC2S2Q(2) +#define STV090x_OFFST_Px_CAR2S2_Q_BETA_M_FIELD 4 +#define STV090x_WIDTH_Px_CAR2S2_Q_BETA_M_FIELD 2 +#define STV090x_OFFST_Px_CAR2S2_Q_BETA_E_FIELD 0 +#define STV090x_WIDTH_Px_CAR2S2_Q_BETA_E_FIELD 4 + +#define STV090x_Px_BCLC2S28(__x) (0xf49d - (__x - 1) * 0x200) +#define STV090x_P1_BCLC2S28 STV090x_Px_BCLC2S28(1) +#define STV090x_P2_BCLC2S28 STV090x_Px_BCLC2S28(1) +#define STV090x_OFFST_Px_CAR2S2_8_BETA_M_FIELD 4 +#define STV090x_WIDTH_Px_CAR2S2_8_BETA_M_FIELD 2 +#define STV090x_OFFST_Px_CAR2S2_8_BETA_E_FIELD 0 +#define STV090x_WIDTH_Px_CAR2S2_8_BETA_E_FIELD 4 + +#define STV090x_Px_BCLC2S216A(__x) (0xf49d - (__x - 1) * 0x200) +#define STV090x_P1_BCLC2S216A STV090x_Px_BCLC2S216A(1) +#define STV090x_P2_BCLC2S216A STV090x_Px_BCLC2S216A(1) +#define STV090x_OFFST_Px_CAR2S2_16A_BETA_M_FIELD 4 +#define STV090x_WIDTH_Px_CAR2S2_16A_BETA_M_FIELD 2 +#define STV090x_OFFST_Px_CAR2S2_16A_BETA_E_FIELD 0 +#define STV090x_WIDTH_Px_CAR2S2_16A_BETA_E_FIELD 4 + +#define STV090x_Px_BCLC2S232A(__x) (0xf49d - (__x - 1) * 0x200) +#define STV090x_P1_BCLC2S232A STV090x_Px_BCLC2S232A(1) +#define STV090x_P2_BCLC2S232A STV090x_Px_BCLC2S232A(1) +#define STV090x_OFFST_Px_CAR2S2_32A_BETA_M_FIELD 4 +#define STV090x_WIDTH_Px_CAR2S2_32A_BETA_M_FIELD 2 +#define STV090x_OFFST_Px_CAR2S2_32A_BETA_E_FIELD 0 +#define STV090x_WIDTH_Px_CAR2S2_32A_BETA_E_FIELD 4 + +#define STV090x_Px_PLROOT2(__x) (0xf4ac - (__x - 1) * 0x200) +#define STV090x_P1_PLROOT2 STV090x_Px_PLROOT2(1) +#define STV090x_P2_PLROOT2 STV090x_Px_PLROOT2(2) +#define STV090x_OFFST_Px_PLSCRAMB_MODE_FIELD 2 +#define STV090x_WIDTH_Px_PLSCRAMB_MODE_FIELD 2 +#define STV090x_OFFST_Px_PLSCRAMB_ROOT_FIELD 0 +#define STV090x_WIDTH_Px_PLSCRAMB_ROOT_FIELD 2 + +#define STV090x_Px_PLROOT1(__x) (0xf4ad - (__x - 1) * 0x200) +#define STV090x_P1_PLROOT1 STV090x_Px_PLROOT1(1) +#define STV090x_P2_PLROOT1 STV090x_Px_PLROOT1(2) +#define STV090x_OFFST_Px_PLSCRAMB_ROOT1_FIELD 0 +#define STV090x_WIDTH_Px_PLSCRAMB_ROOT1_FIELD 8 + +#define STV090x_Px_PLROOT0(__x) (0xf4ae - (__x - 1) * 0x200) +#define STV090x_P1_PLROOT0 STV090x_Px_PLROOT0(1) +#define STV090x_P2_PLROOT0 STV090x_Px_PLROOT0(2) +#define STV090x_OFFST_Px_PLSCRAMB_ROOT0_FIELD 0 +#define STV090x_WIDTH_Px_PLSCRAMB_ROOT0_FIELD 8 + +#define STV090x_Px_MODCODLST0(__x) (0xf4b0 - (__x - 1) * 0x200) /* check */ +#define STV090x_P1_MODCODLST0 STV090x_Px_MODCODLST0(1) +#define STV090x_P2_MODCODLST0 STV090x_Px_MODCODLST0(2) + +#define STV090x_Px_MODCODLST1(__x) (0xf4b1 - (__x - 1) * 0x200) +#define STV090x_P1_MODCODLST1 STV090x_Px_MODCODLST1(1) +#define STV090x_P2_MODCODLST1 STV090x_Px_MODCODLST1(2) +#define STV090x_OFFST_Px_DIS_MODCOD29_FIELD 4 +#define STV090x_WIDTH_Px_DIS_MODCOD29T_FIELD 4 +#define STV090x_OFFST_Px_DIS_32PSK_9_10_FIELD 0 +#define STV090x_WIDTH_Px_DIS_32PSK_9_10_FIELD 4 + +#define STV090x_Px_MODCODLST2(__x) (0xf4b2 - (__x - 1) * 0x200) +#define STV090x_P1_MODCODLST2 STV090x_Px_MODCODLST2(1) +#define STV090x_P2_MODCODLST2 STV090x_Px_MODCODLST2(2) +#define STV090x_OFFST_Px_DIS_32PSK_8_9_FIELD 4 +#define STV090x_WIDTH_Px_DIS_32PSK_8_9_FIELD 4 +#define STV090x_OFFST_Px_DIS_32PSK_5_6_FIELD 0 +#define STV090x_WIDTH_Px_DIS_32PSK_5_6_FIELD 4 + +#define STV090x_Px_MODCODLST3(__x) (0xf4b3 - (__x - 1) * 0x200) +#define STV090x_P1_MODCODLST3 STV090x_Px_MODCODLST3(1) +#define STV090x_P2_MODCODLST3 STV090x_Px_MODCODLST3(2) +#define STV090x_OFFST_Px_DIS_32PSK_4_5_FIELD 4 +#define STV090x_WIDTH_Px_DIS_32PSK_4_5_FIELD 4 +#define STV090x_OFFST_Px_DIS_32PSK_3_4_FIELD 0 +#define STV090x_WIDTH_Px_DIS_32PSK_3_4_FIELD 4 + +#define STV090x_Px_MODCODLST4(__x) (0xf4b4 - (__x - 1) * 0x200) +#define STV090x_P1_MODCODLST4 STV090x_Px_MODCODLST4(1) +#define STV090x_P2_MODCODLST4 STV090x_Px_MODCODLST4(2) +#define STV090x_OFFST_Px_DIS_16PSK_9_10_FIELD 4 +#define STV090x_WIDTH_Px_DIS_16PSK_9_10_FIELD 4 +#define STV090x_OFFST_Px_DIS_16PSK_8_9_FIELD 0 +#define STV090x_WIDTH_Px_DIS_16PSK_8_9_FIELD 4 + +#define STV090x_Px_MODCODLST5(__x) (0xf4b5 - (__x - 1) * 0x200) +#define STV090x_P1_MODCODLST5 STV090x_Px_MODCODLST5(1) +#define STV090x_P2_MODCODLST5 STV090x_Px_MODCODLST5(2) +#define STV090x_OFFST_Px_DIS_16PSK_5_6_FIELD 4 +#define STV090x_WIDTH_Px_DIS_16PSK_5_6_FIELD 4 +#define STV090x_OFFST_Px_DIS_16PSK_4_5_FIELD 0 +#define STV090x_WIDTH_Px_DIS_16PSK_4_5_FIELD 4 + +#define STV090x_Px_MODCODLST6(__x) (0xf4b6 - (__x - 1) * 0x200) +#define STV090x_P1_MODCODLST6 STV090x_Px_MODCODLST6(1) +#define STV090x_P2_MODCODLST6 STV090x_Px_MODCODLST6(2) +#define STV090x_OFFST_Px_DIS_16PSK_3_4_FIELD 4 +#define STV090x_WIDTH_Px_DIS_16PSK_3_4_FIELD 4 +#define STV090x_OFFST_Px_DIS_16PSK_2_3_FIELD 0 +#define STV090x_WIDTH_Px_DIS_16PSK_2_3_FIELD 4 + +#define STV090x_Px_MODCODLST7(__x) (0xf4b7 - (__x - 1) * 0x200) +#define STV090x_P1_MODCODLST7 STV090x_Px_MODCODLST7(1) +#define STV090x_P2_MODCODLST7 STV090x_Px_MODCODLST7(2) +#define STV090x_OFFST_Px_DIS_8P_9_10_FIELD 4 +#define STV090x_WIDTH_Px_DIS_8P_9_10_FIELD 4 +#define STV090x_OFFST_Px_DIS_8P_8_9_FIELD 0 +#define STV090x_WIDTH_Px_DIS_8P_8_9_FIELD 4 + +#define STV090x_Px_MODCODLST8(__x) (0xf4b8 - (__x - 1) * 0x200) +#define STV090x_P1_MODCODLST8 STV090x_Px_MODCODLST8(1) +#define STV090x_P2_MODCODLST8 STV090x_Px_MODCODLST8(2) +#define STV090x_OFFST_Px_DIS_8P_5_6_FIELD 4 +#define STV090x_WIDTH_Px_DIS_8P_5_6_FIELD 4 +#define STV090x_OFFST_Px_DIS_8P_3_4_FIELD 0 +#define STV090x_WIDTH_Px_DIS_8P_3_4_FIELD 4 + +#define STV090x_Px_MODCODLST9(__x) (0xf4b9 - (__x - 1) * 0x200) +#define STV090x_P1_MODCODLST9 STV090x_Px_MODCODLST9(1) +#define STV090x_P2_MODCODLST9 STV090x_Px_MODCODLST9(2) +#define STV090x_OFFST_Px_DIS_8P_2_3_FIELD 4 +#define STV090x_WIDTH_Px_DIS_8P_2_3_FIELD 4 +#define STV090x_OFFST_Px_DIS_8P_3_5_FIELD 0 +#define STV090x_WIDTH_Px_DIS_8P_3_5_FIELD 4 + +#define STV090x_Px_MODCODLSTA(__x) (0xf4ba - (__x - 1) * 0x200) +#define STV090x_P1_MODCODLSTA STV090x_Px_MODCODLSTA(1) +#define STV090x_P2_MODCODLSTA STV090x_Px_MODCODLSTA(2) +#define STV090x_OFFST_Px_DIS_QP_9_10_FIELD 4 +#define STV090x_WIDTH_Px_DIS_QP_9_10_FIELD 4 +#define STV090x_OFFST_Px_DIS_QP_8_9_FIELD 0 +#define STV090x_WIDTH_Px_DIS_QP_8_9_FIELD 4 + +#define STV090x_Px_MODCODLSTB(__x) (0xf4bb - (__x - 1) * 0x200) +#define STV090x_P1_MODCODLSTB STV090x_Px_MODCODLSTB(1) +#define STV090x_P2_MODCODLSTB STV090x_Px_MODCODLSTB(2) +#define STV090x_OFFST_Px_DIS_QP_5_6_FIELD 4 +#define STV090x_WIDTH_Px_DIS_QP_5_6_FIELD 4 +#define STV090x_OFFST_Px_DIS_QP_4_5_FIELD 0 +#define STV090x_WIDTH_Px_DIS_QP_4_5_FIELD 4 + +#define STV090x_Px_MODCODLSTC(__x) (0xf4bc - (__x - 1) * 0x200) +#define STV090x_P1_MODCODLSTC STV090x_Px_MODCODLSTC(1) +#define STV090x_P2_MODCODLSTC STV090x_Px_MODCODLSTC(2) +#define STV090x_OFFST_Px_DIS_QP_3_4_FIELD 4 +#define STV090x_WIDTH_Px_DIS_QP_3_4_FIELD 4 +#define STV090x_OFFST_Px_DIS_QP_2_3_FIELD 0 +#define STV090x_WIDTH_Px_DIS_QP_2_3_FIELD 4 + +#define STV090x_Px_MODCODLSTD(__x) (0xf4bd - (__x - 1) * 0x200) +#define STV090x_P1_MODCODLSTD STV090x_Px_MODCODLSTD(1) +#define STV090x_P2_MODCODLSTD STV090x_Px_MODCODLSTD(2) +#define STV090x_OFFST_Px_DIS_QP_3_5_FIELD 4 +#define STV090x_WIDTH_Px_DIS_QP_3_5_FIELD 4 +#define STV090x_OFFST_Px_DIS_QP_1_2_FIELD 0 +#define STV090x_WIDTH_Px_DIS_QP_1_2_FIELD 4 + +#define STV090x_Px_MODCODLSTE(__x) (0xf4be - (__x - 1) * 0x200) +#define STV090x_P1_MODCODLSTE STV090x_Px_MODCODLSTE(1) +#define STV090x_P2_MODCODLSTE STV090x_Px_MODCODLSTE(2) +#define STV090x_OFFST_Px_DIS_QP_2_5_FIELD 4 +#define STV090x_WIDTH_Px_DIS_QP_2_5_FIELD 4 +#define STV090x_OFFST_Px_DIS_QP_1_3_FIELD 0 +#define STV090x_WIDTH_Px_DIS_QP_1_3_FIELD 4 + +#define STV090x_Px_MODCODLSTF(__x) (0xf4bf - (__x - 1) * 0x200) +#define STV090x_P1_MODCODLSTF STV090x_Px_MODCODLSTF(1) +#define STV090x_P2_MODCODLSTF STV090x_Px_MODCODLSTF(2) +#define STV090x_OFFST_Px_DIS_QP_1_4_FIELD 4 +#define STV090x_WIDTH_Px_DIS_QP_1_4_FIELD 4 + +#define STV090x_Px_DMDRESCFG(__x) (0xF4C6 - (__x - 1) * 0x200) +#define STV090x_P1_DMDRESCFG STV090x_Px_DMDRESCFG(1) +#define STV090x_P2_DMDRESCFG STV090x_Px_DMDRESCFG(2) +#define STV090x_OFFST_Px_DMDRES_RESET_FIELD 7 +#define STV090x_WIDTH_Px_DMDRES_RESET_FIELD 1 + +#define STV090x_Px_DMDRESADR(__x) (0xF4C7 - (__x - 1) * 0x200) +#define STV090x_P1_DMDRESADR STV090x_Px_DMDRESADR(1) +#define STV090x_P2_DMDRESADR STV090x_Px_DMDRESADR(2) +#define STV090x_OFFST_Px_DMDRES_RESNBR_FIELD 0 +#define STV090x_WIDTH_Px_DMDRES_RESNBR_FIELD 4 + +#define STV090x_Px_DMDRESDATAy(__x, __y) (0xF4C8 - (__x - 1) * 0x200 + (7 - __y)) +#define STV090x_P1_DMDRESDATA0 STV090x_Px_DMDRESDATAy(1, 0) +#define STV090x_P1_DMDRESDATA1 STV090x_Px_DMDRESDATAy(1, 1) +#define STV090x_P1_DMDRESDATA2 STV090x_Px_DMDRESDATAy(1, 2) +#define STV090x_P1_DMDRESDATA3 STV090x_Px_DMDRESDATAy(1, 3) +#define STV090x_P1_DMDRESDATA4 STV090x_Px_DMDRESDATAy(1, 4) +#define STV090x_P1_DMDRESDATA5 STV090x_Px_DMDRESDATAy(1, 5) +#define STV090x_P1_DMDRESDATA6 STV090x_Px_DMDRESDATAy(1, 6) +#define STV090x_P1_DMDRESDATA7 STV090x_Px_DMDRESDATAy(1, 7) +#define STV090x_P2_DMDRESDATA0 STV090x_Px_DMDRESDATAy(2, 0) +#define STV090x_P2_DMDRESDATA1 STV090x_Px_DMDRESDATAy(2, 1) +#define STV090x_P2_DMDRESDATA2 STV090x_Px_DMDRESDATAy(2, 2) +#define STV090x_P2_DMDRESDATA3 STV090x_Px_DMDRESDATAy(2, 3) +#define STV090x_P2_DMDRESDATA4 STV090x_Px_DMDRESDATAy(2, 4) +#define STV090x_P2_DMDRESDATA5 STV090x_Px_DMDRESDATAy(2, 5) +#define STV090x_P2_DMDRESDATA6 STV090x_Px_DMDRESDATAy(2, 6) +#define STV090x_P2_DMDRESDATA7 STV090x_Px_DMDRESDATAy(2, 7) +#define STV090x_OFFST_Px_DMDRES_DATA_FIELD 0 +#define STV090x_WIDTH_Px_DMDRES_DATA_FIELD 8 + +#define STV090x_Px_FFEIy(__x, __y) (0xf4d0 - (__x - 1) * 0x200 + 0x2 * (__y - 1)) +#define STV090x_P1_FFEI1 STV090x_Px_FFEIy(1, 1) +#define STV090x_P1_FFEI2 STV090x_Px_FFEIy(1, 2) +#define STV090x_P1_FFEI3 STV090x_Px_FFEIy(1, 3) +#define STV090x_P1_FFEI4 STV090x_Px_FFEIy(1, 4) +#define STV090x_P2_FFEI1 STV090x_Px_FFEIy(2, 1) +#define STV090x_P2_FFEI2 STV090x_Px_FFEIy(2, 2) +#define STV090x_P2_FFEI3 STV090x_Px_FFEIy(2, 3) +#define STV090x_P2_FFEI4 STV090x_Px_FFEIy(2, 4) +#define STV090x_OFFST_Px_FFE_ACCIy_FIELD 0 +#define STV090x_WIDTH_Px_FFE_ACCIy_FIELD 8 + +#define STV090x_Px_FFEQy(__x, __y) (0xf4d1 - (__x - 1) * 0x200 + 0x2 * (__y - 1)) +#define STV090x_P1_FFEQ1 STV090x_Px_FFEQy(1, 1) +#define STV090x_P1_FFEQ2 STV090x_Px_FFEQy(1, 2) +#define STV090x_P1_FFEQ3 STV090x_Px_FFEQy(1, 3) +#define STV090x_P1_FFEQ4 STV090x_Px_FFEQy(1, 4) +#define STV090x_P2_FFEQ1 STV090x_Px_FFEQy(2, 1) +#define STV090x_P2_FFEQ2 STV090x_Px_FFEQy(2, 2) +#define STV090x_P2_FFEQ3 STV090x_Px_FFEQy(2, 3) +#define STV090x_P2_FFEQ4 STV090x_Px_FFEQy(2, 4) +#define STV090x_OFFST_Px_FFE_ACCQy_FIELD 0 +#define STV090x_WIDTH_Px_FFE_ACCQy_FIELD 8 + +#define STV090x_Px_FFECFG(__x) (0xf4d8 - (__x - 1) * 0x200) +#define STV090x_P1_FFECFG STV090x_Px_FFECFG(1) +#define STV090x_P2_FFECFG STV090x_Px_FFECFG(2) +#define STV090x_OFFST_Px_EQUALFFE_ON_FIELD 6 +#define STV090x_WIDTH_Px_EQUALFFE_ON_FIELD 1 + +#define STV090x_Px_SMAPCOEF7(__x) (0xf500 - (__x - 1) * 0x200) +#define STV090x_P1_SMAPCOEF7 STV090x_Px_SMAPCOEF7(1) +#define STV090x_P2_SMAPCOEF7 STV090x_Px_SMAPCOEF7(2) +#define STV090x_OFFST_Px_DIS_QSCALE_FIELD 7 +#define STV090x_WIDTH_Px_DIS_QSCALE_FIELD 1 +#define STV090x_OFFST_Px_SMAPCOEF_Q_LLR12_FIELD 0 +#define STV090x_WIDTH_Px_SMAPCOEF_Q_LLR12_FIELD 7 + +#define STV090x_Px_SMAPCOEF6(__x) (0xf501 - (__x - 1) * 0x200) +#define STV090x_P1_SMAPCOEF6 STV090x_Px_SMAPCOEF6(1) +#define STV090x_P2_SMAPCOEF6 STV090x_Px_SMAPCOEF6(2) +#define STV090x_OFFST_Px_ADJ_8PSKLLR1_FIELD 2 +#define STV090x_WIDTH_Px_ADJ_8PSKLLR1_FIELD 1 +#define STV090x_OFFST_Px_OLD_8PSKLLR1_FIELD 1 +#define STV090x_WIDTH_Px_OLD_8PSKLLR1_FIELD 1 +#define STV090x_OFFST_Px_DIS_AB8PSK_FIELD 0 +#define STV090x_WIDTH_Px_DIS_AB8PSK_FIELD 1 + +#define STV090x_Px_SMAPCOEF5(__x) (0xf502 - (__x - 1) * 0x200) +#define STV090x_P1_SMAPCOEF5 STV090x_Px_SMAPCOEF5(1) +#define STV090x_P2_SMAPCOEF5 STV090x_Px_SMAPCOEF5(2) +#define STV090x_OFFST_Px_DIS_8SCALE_FIELD 7 +#define STV090x_WIDTH_Px_DIS_8SCALE_FIELD 1 +#define STV090x_OFFST_Px_SMAPCOEF_8P_LLR23_FIELD 0 +#define STV090x_WIDTH_Px_SMAPCOEF_8P_LLR23_FIELD 7 + +#define STV090x_Px_DMDPLHSTAT(__x) (0xF520 - (__x - 1) * 0x200) +#define STV090x_P1_DMDPLHSTAT STV090x_Px_DMDPLHSTAT(1) +#define STV090x_P2_DMDPLHSTAT STV090x_Px_DMDPLHSTAT(2) +#define STV090x_OFFST_Px_PLH_STATISTIC_FIELD 0 +#define STV090x_WIDTH_Px_PLH_STATISTIC_FIELD 8 + +#define STV090x_Px_LOCKTIMEy(__x, __y) (0xF525 - (__x - 1) * 0x200 - __y * 0x1) +#define STV090x_P1_LOCKTIME0 STV090x_Px_LOCKTIMEy(1, 0) +#define STV090x_P1_LOCKTIME1 STV090x_Px_LOCKTIMEy(1, 1) +#define STV090x_P1_LOCKTIME2 STV090x_Px_LOCKTIMEy(1, 2) +#define STV090x_P1_LOCKTIME3 STV090x_Px_LOCKTIMEy(1, 3) +#define STV090x_P2_LOCKTIME0 STV090x_Px_LOCKTIMEy(2, 0) +#define STV090x_P2_LOCKTIME1 STV090x_Px_LOCKTIMEy(2, 1) +#define STV090x_P2_LOCKTIME2 STV090x_Px_LOCKTIMEy(2, 2) +#define STV090x_P2_LOCKTIME3 STV090x_Px_LOCKTIMEy(2, 3) +#define STV090x_OFFST_Px_DEMOD_LOCKTIME_FIELD 0 +#define STV090x_WIDTH_Px_DEMOD_LOCKTIME_FIELD 8 + +#define STV090x_Px_TNRCFG(__x) (0xf4e0 - (__x - 1) * 0x200) /* check */ +#define STV090x_P1_TNRCFG STV090x_Px_TNRCFG(1) +#define STV090x_P2_TNRCFG STV090x_Px_TNRCFG(2) + +#define STV090x_Px_TNRCFG2(__x) (0xf4e1 - (__x - 1) * 0x200) +#define STV090x_P1_TNRCFG2 STV090x_Px_TNRCFG2(1) +#define STV090x_P2_TNRCFG2 STV090x_Px_TNRCFG2(2) +#define STV090x_OFFST_Px_TUN_IQSWAP_FIELD 7 +#define STV090x_WIDTH_Px_TUN_IQSWAP_FIELD 1 + +#define STV090x_Px_VITSCALE(__x) (0xf532 - (__x - 1) * 0x200) +#define STV090x_P1_VITSCALE STV090x_Px_VITSCALE(1) +#define STV090x_P2_VITSCALE STV090x_Px_VITSCALE(2) +#define STV090x_OFFST_Px_NVTH_NOSRANGE_FIELD 7 +#define STV090x_WIDTH_Px_NVTH_NOSRANGE_FIELD 1 +#define STV090x_OFFST_Px_VERROR_MAXMODE_FIELD 6 +#define STV090x_WIDTH_Px_VERROR_MAXMODE_FIELD 1 +#define STV090x_OFFST_Px_NSLOWSN_LOCKED_FIELD 3 +#define STV090x_WIDTH_Px_NSLOWSN_LOCKED_FIELD 1 +#define STV090x_OFFST_Px_DIS_RSFLOCK_FIELD 1 +#define STV090x_WIDTH_Px_DIS_RSFLOCK_FIELD 1 + +#define STV090x_Px_FECM(__x) (0xf533 - (__x - 1) * 0x200) +#define STV090x_P1_FECM STV090x_Px_FECM(1) +#define STV090x_P2_FECM STV090x_Px_FECM(2) +#define STV090x_OFFST_Px_DSS_DVB_FIELD 7 +#define STV090x_WIDTH_Px_DSS_DVB_FIELD 1 +#define STV090x_OFFST_Px_DSS_SRCH_FIELD 4 +#define STV090x_WIDTH_Px_DSS_SRCH_FIELD 1 +#define STV090x_OFFST_Px_SYNCVIT_FIELD 1 +#define STV090x_WIDTH_Px_SYNCVIT_FIELD 1 +#define STV090x_OFFST_Px_IQINV_FIELD 0 +#define STV090x_WIDTH_Px_IQINV_FIELD 1 + +#define STV090x_Px_VTH12(__x) (0xf534 - (__x - 1) * 0x200) +#define STV090x_P1_VTH12 STV090x_Px_VTH12(1) +#define STV090x_P2_VTH12 STV090x_Px_VTH12(2) +#define STV090x_OFFST_Px_VTH12_FIELD 0 +#define STV090x_WIDTH_Px_VTH12_FIELD 8 + +#define STV090x_Px_VTH23(__x) (0xf535 - (__x - 1) * 0x200) +#define STV090x_P1_VTH23 STV090x_Px_VTH23(1) +#define STV090x_P2_VTH23 STV090x_Px_VTH23(2) +#define STV090x_OFFST_Px_VTH23_FIELD 0 +#define STV090x_WIDTH_Px_VTH23_FIELD 8 + +#define STV090x_Px_VTH34(__x) (0xf536 - (__x - 1) * 0x200) +#define STV090x_P1_VTH34 STV090x_Px_VTH34(1) + #define STV090x_P2_VTH34 STV090x_Px_VTH34(2) +#define STV090x_OFFST_Px_VTH34_FIELD 0 +#define STV090x_WIDTH_Px_VTH34_FIELD 8 + +#define STV090x_Px_VTH56(__x) (0xf537 - (__x - 1) * 0x200) +#define STV090x_P1_VTH56 STV090x_Px_VTH56(1) +#define STV090x_P2_VTH56 STV090x_Px_VTH56(2) +#define STV090x_OFFST_Px_VTH56_FIELD 0 +#define STV090x_WIDTH_Px_VTH56_FIELD 8 + +#define STV090x_Px_VTH67(__x) (0xf538 - (__x - 1) * 0x200) +#define STV090x_P1_VTH67 STV090x_Px_VTH67(1) +#define STV090x_P2_VTH67 STV090x_Px_VTH67(2) +#define STV090x_OFFST_Px_VTH67_FIELD 0 +#define STV090x_WIDTH_Px_VTH67_FIELD 8 + +#define STV090x_Px_VTH78(__x) (0xf539 - (__x - 1) * 0x200) +#define STV090x_P1_VTH78 STV090x_Px_VTH78(1) +#define STV090x_P2_VTH78 STV090x_Px_VTH78(2) +#define STV090x_OFFST_Px_VTH78_FIELD 0 +#define STV090x_WIDTH_Px_VTH78_FIELD 8 + +#define STV090x_Px_VITCURPUN(__x) (0xf53a - (__x - 1) * 0x200) +#define STV090x_P1_VITCURPUN STV090x_Px_VITCURPUN(1) +#define STV090x_P2_VITCURPUN STV090x_Px_VITCURPUN(2) +#define STV090x_OFFST_Px_VIT_CURPUN_FIELD 0 +#define STV090x_WIDTH_Px_VIT_CURPUN_FIELD 5 + +#define STV090x_Px_VERROR(__x) (0xf53b - (__x - 1) * 0x200) +#define STV090x_P1_VERROR STV090x_Px_VERROR(1) +#define STV090x_P2_VERROR STV090x_Px_VERROR(2) +#define STV090x_OFFST_Px_REGERR_VIT_FIELD 0 +#define STV090x_WIDTH_Px_REGERR_VIT_FIELD 8 + +#define STV090x_Px_PRVIT(__x) (0xf53c - (__x - 1) * 0x200) +#define STV090x_P1_PRVIT STV090x_Px_PRVIT(1) +#define STV090x_P2_PRVIT STV090x_Px_PRVIT(2) +#define STV090x_OFFST_Px_DIS_VTHLOCK_FIELD 6 +#define STV090x_WIDTH_Px_DIS_VTHLOCK_FIELD 1 +#define STV090x_OFFST_Px_E7_8VIT_FIELD 5 +#define STV090x_WIDTH_Px_E7_8VIT_FIELD 1 +#define STV090x_OFFST_Px_E6_7VIT_FIELD 4 +#define STV090x_WIDTH_Px_E6_7VIT_FIELD 1 +#define STV090x_OFFST_Px_E5_6VIT_FIELD_ 3 +#define STV090x_WIDTH_Px_E5_6VIT_FIELD 1 +#define STV090x_OFFST_Px_E3_4VIT_FIELD 2 +#define STV090x_WIDTH_Px_E3_4VIT_FIELD 1 +#define STV090x_OFFST_Px_E2_3VIT_FIELD 1 +#define STV090x_WIDTH_Px_E2_3VIT_FIELD 1 +#define STV090x_OFFST_Px_E1_2VIT_FIELD 0 +#define STV090x_WIDTH_Px_E1_2VIT_FIELD 1 + +#define STV090x_Px_VAVSRVIT(__x) (0xf53d - (__x - 1) * 0x200) +#define STV090x_P1_VAVSRVIT STV090x_Px_VAVSRVIT(1) +#define STV090x_P2_VAVSRVIT STV090x_Px_VAVSRVIT(2) +#define STV090x_OFFST_Px_SNVIT_FIELD 4 +#define STV090x_WIDTH_Px_SNVIT_FIELD 2 +#define STV090x_OFFST_Px_TOVVIT_FIELD 2 +#define STV090x_WIDTH_Px_TOVVIT_FIELD 2 +#define STV090x_OFFST_Px_HYPVIT_FIELD 0 +#define STV090x_WIDTH_Px_HYPVIT_FIELD 2 + +#define STV090x_Px_VSTATUSVIT(__x) (0xf53e - (__x - 1) * 0x200) +#define STV090x_P1_VSTATUSVIT STV090x_Px_VSTATUSVIT(1) +#define STV090x_P2_VSTATUSVIT STV090x_Px_VSTATUSVIT(2) +#define STV090x_OFFST_Px_PRFVIT_FIELD 4 +#define STV090x_WIDTH_Px_PRFVIT_FIELD 1 +#define STV090x_OFFST_Px_LOCKEDVIT_FIELD 3 +#define STV090x_WIDTH_Px_LOCKEDVIT_FIELD 1 + +#define STV090x_Px_VTHINUSE(__x) (0xf53f - (__x - 1) * 0x200) +#define STV090x_P1_VTHINUSE STV090x_Px_VTHINUSE(1) +#define STV090x_P2_VTHINUSE STV090x_Px_VTHINUSE(2) +#define STV090x_OFFST_Px_VIT_INUSE_FIELD 0 +#define STV090x_WIDTH_Px_VIT_INUSE_FIELD 8 + +#define STV090x_Px_KDIV12(__x) (0xf540 - (__x - 1) * 0x200) +#define STV090x_P1_KDIV12 STV090x_Px_KDIV12(1) +#define STV090x_P2_KDIV12 STV090x_Px_KDIV12(2) +#define STV090x_OFFST_Px_K_DIVIDER_12_FIELD 0 +#define STV090x_WIDTH_Px_K_DIVIDER_12_FIELD 7 + +#define STV090x_Px_KDIV23(__x) (0xf541 - (__x - 1) * 0x200) +#define STV090x_P1_KDIV23 STV090x_Px_KDIV23(1) +#define STV090x_P2_KDIV23 STV090x_Px_KDIV23(2) +#define STV090x_OFFST_Px_K_DIVIDER_23_FIELD 0 +#define STV090x_WIDTH_Px_K_DIVIDER_23_FIELD 7 + +#define STV090x_Px_KDIV34(__x) (0xf542 - (__x - 1) * 0x200) +#define STV090x_P1_KDIV34 STV090x_Px_KDIV34(1) +#define STV090x_P2_KDIV34 STV090x_Px_KDIV34(2) +#define STV090x_OFFST_Px_K_DIVIDER_34_FIELD 0 +#define STV090x_WIDTH_Px_K_DIVIDER_34_FIELD 7 + +#define STV090x_Px_KDIV56(__x) (0xf543 - (__x - 1) * 0x200) +#define STV090x_P1_KDIV56 STV090x_Px_KDIV56(1) +#define STV090x_P2_KDIV56 STV090x_Px_KDIV56(2) +#define STV090x_OFFST_Px_K_DIVIDER_56_FIELD 0 +#define STV090x_WIDTH_Px_K_DIVIDER_56_FIELD 7 + +#define STV090x_Px_KDIV67(__x) (0xf544 - (__x - 1) * 0x200) +#define STV090x_P1_KDIV67 STV090x_Px_KDIV67(1) +#define STV090x_P2_KDIV67 STV090x_Px_KDIV67(2) +#define STV090x_OFFST_Px_K_DIVIDER_67_FIELD 0 +#define STV090x_WIDTH_Px_K_DIVIDER_67_FIELD 7 + +#define STV090x_Px_KDIV78(__x) (0xf545 - (__x - 1) * 0x200) +#define STV090x_P1_KDIV78 STV090x_Px_KDIV78(1) +#define STV090x_P2_KDIV78 STV090x_Px_KDIV78(2) +#define STV090x_OFFST_Px_K_DIVIDER_78_FIELD 0 +#define STV090x_WIDTH_Px_K_DIVIDER_78_FIELD 7 + +#define STV090x_Px_PDELCTRL1(__x) (0xf550 - (__x - 1) * 0x200) +#define STV090x_P1_PDELCTRL1 STV090x_Px_PDELCTRL1(1) +#define STV090x_P2_PDELCTRL1 STV090x_Px_PDELCTRL1(2) +#define STV090x_OFFST_Px_INV_MISMASK_FIELD 7 +#define STV090x_WIDTH_Px_INV_MISMASK_FIELD 1 +#define STV090x_OFFST_Px_FILTER_EN_FIELD 5 +#define STV090x_WIDTH_Px_FILTER_EN_FIELD 1 +#define STV090x_OFFST_Px_EN_MIS00_FIELD 1 +#define STV090x_WIDTH_Px_EN_MIS00_FIELD 1 +#define STV090x_OFFST_Px_ALGOSWRST_FIELD 0 +#define STV090x_WIDTH_Px_ALGOSWRST_FIELD 1 + +#define STV090x_Px_PDELCTRL2(__x) (0xf551 - (__x - 1) * 0x200) +#define STV090x_P1_PDELCTRL2 STV090x_Px_PDELCTRL2(1) +#define STV090x_P2_PDELCTRL2 STV090x_Px_PDELCTRL2(2) +#define STV090x_OFFST_Px_FRAME_MODE_FIELD 1 +#define STV090x_WIDTH_Px_FRAME_MODE_FIELD 1 + +#define STV090x_Px_HYSTTHRESH(__x) (0xf554 - (__x - 1) * 0x200) +#define STV090x_P1_HYSTTHRESH STV090x_Px_HYSTTHRESH(1) +#define STV090x_P2_HYSTTHRESH STV090x_Px_HYSTTHRESH(2) +#define STV090x_OFFST_Px_UNLCK_THRESH_FIELD 4 +#define STV090x_WIDTH_Px_UNLCK_THRESH_FIELD 4 +#define STV090x_OFFST_Px_DELIN_LCK_THRESH_FIELD 0 +#define STV090x_WIDTH_Px_DELIN_LCK_THRESH__FIELD 4 + +#define STV090x_Px_ISIENTRY(__x) (0xf55e - (__x - 1) * 0x200) +#define STV090x_P1_ISIENTRY STV090x_Px_ISIENTRY(1) +#define STV090x_P2_ISIENTRY STV090x_Px_ISIENTRY(2) +#define STV090x_OFFST_Px_ISI_ENTRY_FIELD 0 +#define STV090x_WIDTH_Px_ISI_ENTRY__FIELD 8 + +#define STV090x_Px_ISIBITENA(__x) (0xf55f - (__x - 1) * 0x200) +#define STV090x_P1_ISIBITENA STV090x_Px_ISIBITENA(1) +#define STV090x_P2_ISIBITENA STV090x_Px_ISIBITENA(2) +#define STV090x_OFFST_Px_ISI_BIT_EN_FIELD 0 +#define STV090x_WIDTH_Px_ISI_BIT_EN_FIELD 8 + +#define STV090x_Px_MATSTRy(__x, __y) (0xf561 - (__x - 1) * 0x200 - __y * 0x1) +#define STV090x_P1_MATSTR0 STV090x_Px_MATSTRy(1, 0) +#define STV090x_P1_MATSTR1 STV090x_Px_MATSTRy(1, 1) +#define STV090x_P2_MATSTR0 STV090x_Px_MATSTRy(2, 0) +#define STV090x_P2_MATSTR1 STV090x_Px_MATSTRy(2, 1) +#define STV090x_OFFST_Px_MATYPE_CURRENT_FIELD 0 +#define STV090x_WIDTH_Px_MATYPE_CURRENT_FIELD 8 + +#define STV090x_Px_UPLSTRy(__x, __y) (0xf563 - (__x - 1) * 0x200 - __y * 0x1) +#define STV090x_P1_UPLSTR0 STV090x_Px_UPLSTRy(1, 0) +#define STV090x_P1_UPLSTR1 STV090x_Px_UPLSTRy(1, 1) +#define STV090x_P2_UPLSTR0 STV090x_Px_UPLSTRy(2, 0) +#define STV090x_P2_UPLSTR1 STV090x_Px_UPLSTRy(2, 1) +#define STV090x_OFFST_Px_UPL_CURRENT_FIELD 0 +#define STV090x_WIDTH_Px_UPL_CURRENT_FIELD 8 + +#define STV090x_Px_DFLSTRy(__x, __y) (0xf565 - (__x - 1) * 0x200 - __y * 0x1) +#define STV090x_P1_DFLSTR0 STV090x_Px_DFLSTRy(1, 0) +#define STV090x_P1_DFLSTR1 STV090x_Px_DFLSTRy(1, 1) +#define STV090x_P2_DFLSTR0 STV090x_Px_DFLSTRy(2, 0) +#define STV090x_P2_DFLSTR1 STV090x_Px_DFLSTRy(2, 1) +#define STV090x_OFFST_Px_DFL_CURRENT_FIELD 0 +#define STV090x_WIDTH_Px_DFL_CURRENT_FIELD 8 + +#define STV090x_Px_SYNCSTR(__x) (0xf566 - (__x - 1) * 0x200) +#define STV090x_P1_SYNCSTR STV090x_Px_SYNCSTR(1) +#define STV090x_P2_SYNCSTR STV090x_Px_SYNCSTR(2) +#define STV090x_OFFST_Px_SYNC_CURRENT_FIELD 0 +#define STV090x_WIDTH_Px_SYNC_CURRENT_FIELD 8 + +#define STV090x_Px_SYNCDSTRy(__x, __y) (0xf568 - (__x - 1) * 0x200 - __y * 0x1) +#define STV090x_P1_SYNCDSTR0 STV090x_Px_SYNCDSTRy(1, 0) +#define STV090x_P1_SYNCDSTR1 STV090x_Px_SYNCDSTRy(1, 1) +#define STV090x_P2_SYNCDSTR0 STV090x_Px_SYNCDSTRy(2, 0) +#define STV090x_P2_SYNCDSTR1 STV090x_Px_SYNCDSTRy(2, 1) +#define STV090x_OFFST_Px_SYNCD_CURRENT_FIELD 0 +#define STV090x_WIDTH_Px_SYNCD_CURRENT_FIELD 8 + +#define STV090x_Px_PDELSTATUS1(__x) (0xf569 - (__x - 1) * 0x200) +#define STV090x_P1_PDELSTATUS1 STV090x_Px_PDELSTATUS1(1) +#define STV090x_P2_PDELSTATUS1 STV090x_Px_PDELSTATUS1(2) +#define STV090x_OFFST_Px_PKTDELIN_LOCK_FIELD 1 +#define STV090x_WIDTH_Px_PKTDELIN_LOCK_FIELD 1 +#define STV090x_OFFST_Px_FIRST_LOCK_FIELD 0 +#define STV090x_WIDTH_Px_FIRST_LOCK_FIELD 1 + +#define STV090x_Px_PDELSTATUS2(__x) (0xf56a - (__x - 1) * 0x200) +#define STV090x_P1_PDELSTATUS2 STV090x_Px_PDELSTATUS2(1) +#define STV090x_P2_PDELSTATUS2 STV090x_Px_PDELSTATUS2(2) +#define STV090x_OFFST_Px_FRAME_MODCOD_FIELD 2 +#define STV090x_WIDTH_Px_FRAME_MODCOD_FIELD 5 +#define STV090x_OFFST_Px_FRAME_TYPE_FIELD 0 +#define STV090x_WIDTH_Px_FRAME_TYPE_FIELD 2 + +#define STV090x_Px_BBFCRCKO1(__x) (0xf56b - (__x - 1) * 0x200) +#define STV090x_P1_BBFCRCKO1 STV090x_Px_BBFCRCKO1(1) +#define STV090x_P2_BBFCRCKO1 STV090x_Px_BBFCRCKO1(2) +#define STV090x_OFFST_Px_BBHCRC_KOCNT_FIELD 0 +#define STV090x_WIDTH_Px_BBHCRC_KOCNT_FIELD 8 + +#define STV090x_Px_BBFCRCKO0(__x) (0xf56c - (__x - 1) * 0x200) +#define STV090x_P1_BBFCRCKO0 STV090x_Px_BBFCRCKO0(1) +#define STV090x_P2_BBFCRCKO0 STV090x_Px_BBFCRCKO0(2) +#define STV090x_OFFST_Px_BBHCRC_KOCNT_FIELD 0 +#define STV090x_WIDTH_Px_BBHCRC_KOCNT_FIELD 8 + +#define STV090x_Px_UPCRCKO1(__x) (0xf56d - (__x - 1) * 0x200) +#define STV090x_P1_UPCRCKO1 STV090x_Px_UPCRCKO1(1) +#define STV090x_P2_UPCRCKO1 STV090x_Px_UPCRCKO1(2) +#define STV090x_OFFST_Px_PKTCRC_KOCNT_FIELD 0 +#define STV090x_WIDTH_Px_PKTCRC_KOCNT_FIELD 8 + +#define STV090x_Px_UPCRCKO0(__x) (0xf56e - (__x - 1) * 0x200) +#define STV090x_P1_UPCRCKO0 STV090x_Px_UPCRCKO0(1) +#define STV090x_P2_UPCRCKO0 STV090x_Px_UPCRCKO0(2) +#define STV090x_OFFST_Px_PKTCRC_KOCNT_FIELD 0 +#define STV090x_WIDTH_Px_PKTCRC_KOCNT_FIELD 8 + +#define STV090x_NBITER_NFx(__x) (0xFA03 + (__x - 4) * 0x1) +#define STV090x_NBITER_NF4 STV090x_NBITER_NFx(4) +#define STV090x_NBITER_NF5 STV090x_NBITER_NFx(5) +#define STV090x_NBITER_NF6 STV090x_NBITER_NFx(6) +#define STV090x_NBITER_NF7 STV090x_NBITER_NFx(7) +#define STV090x_NBITER_NF8 STV090x_NBITER_NFx(8) +#define STV090x_NBITER_NF9 STV090x_NBITER_NFx(9) +#define STV090x_NBITER_NF10 STV090x_NBITER_NFx(10) +#define STV090x_NBITER_NF11 STV090x_NBITER_NFx(11) +#define STV090x_NBITER_NF12 STV090x_NBITER_NFx(12) +#define STV090x_NBITER_NF13 STV090x_NBITER_NFx(13) +#define STV090x_NBITER_NF14 STV090x_NBITER_NFx(14) +#define STV090x_NBITER_NF15 STV090x_NBITER_NFx(15) +#define STV090x_NBITER_NF16 STV090x_NBITER_NFx(16) +#define STV090x_NBITER_NF17 STV090x_NBITER_NFx(17) + +#define STV090x_NBITERNOERR 0xFA3F +#define STV090x_OFFST_NBITER_STOP_CRIT_FIELD 0 +#define STV090x_WIDTH_NBITER_STOP_CRIT_FIELD 4 + +#define STV090x_GAINLLR_NFx(__x) (0xFA43 + (__x - 4) * 0x1) +#define STV090x_GAINLLR_NF4 STV090x_GAINLLR_NFx(4) +#define STV090x_OFFST_GAINLLR_NF_QP_1_2_FIELD 0 +#define STV090x_WIDTH_GAINLLR_NF_QP_1_2_FIELD 7 + +#define STV090x_GAINLLR_NF5 STV090x_GAINLLR_NFx(5) +#define STV090x_OFFST_GAINLLR_NF_QP_3_5_FIELD 0 +#define STV090x_WIDTH_GAINLLR_NF_QP_3_5_FIELD 7 + +#define STV090x_GAINLLR_NF6 STV090x_GAINLLR_NFx(6) +#define STV090x_OFFST_GAINLLR_NF_QP_2_3_FIELD 0 +#define STV090x_WIDTH_GAINLLR_NF_QP_2_3_FIELD 7 + +#define STV090x_GAINLLR_NF7 STV090x_GAINLLR_NFx(7) +#define STV090x_OFFST_GAINLLR_NF_QP_3_4_FIELD 0 +#define STV090x_WIDTH_GAINLLR_NF_QP_3_4_FIELD 7 + +#define STV090x_GAINLLR_NF8 STV090x_GAINLLR_NFx(8) +#define STV090x_OFFST_GAINLLR_NF_QP_4_5_FIELD 0 +#define STV090x_WIDTH_GAINLLR_NF_QP_4_5_FIELD 7 + +#define STV090x_GAINLLR_NF9 STV090x_GAINLLR_NFx(9) +#define STV090x_OFFST_GAINLLR_NF_QP_5_6_FIELD 0 +#define STV090x_WIDTH_GAINLLR_NF_QP_5_6_FIELD 7 + +#define STV090x_GAINLLR_NF10 STV090x_GAINLLR_NFx(10) +#define STV090x_OFFST_GAINLLR_NF_QP_8_9_FIELD 0 +#define STV090x_WIDTH_GAINLLR_NF_QP_8_9_FIELD 7 + +#define STV090x_GAINLLR_NF11 STV090x_GAINLLR_NFx(11) +#define STV090x_OFFST_GAINLLR_NF_QP_9_10_FIELD 0 +#define STV090x_WIDTH_GAINLLR_NF_QP_9_10IELD 7 + +#define STV090x_GAINLLR_NF12 STV090x_GAINLLR_NFx(12) +#define STV090x_OFFST_GAINLLR_NF_8P_3_5_FIELD 0 +#define STV090x_WIDTH_GAINLLR_NF_8P_3_5_FIELD 7 + +#define STV090x_GAINLLR_NF13 STV090x_GAINLLR_NFx(13) +#define STV090x_OFFST_GAINLLR_NF_8P_2_3_FIELD 0 +#define STV090x_WIDTH_GAINLLR_NF_8P_2_3_FIELD 7 + +#define STV090x_GAINLLR_NF14 STV090x_GAINLLR_NFx(14) +#define STV090x_OFFST_GAINLLR_NF_8P_3_4_FIELD 0 +#define STV090x_WIDTH_GAINLLR_NF_8P_3_4_FIELD 7 + +#define STV090x_GAINLLR_NF15 STV090x_GAINLLR_NFx(15) +#define STV090x_OFFST_GAINLLR_NF_8P_5_6_FIELD 0 +#define STV090x_WIDTH_GAINLLR_NF_8P_5_6_FIELD 7 + +#define STV090x_GAINLLR_NF16 STV090x_GAINLLR_NFx(16) +#define STV090x_OFFST_GAINLLR_NF_8P_8_9_FIELD 0 +#define STV090x_WIDTH_GAINLLR_NF_8P_8_9_FIELD 7 + +#define STV090x_GAINLLR_NF17 STV090x_GAINLLR_NFx(17) +#define STV090x_OFFST_GAINLLR_NF_8P_9_10_FIELD 0 +#define STV090x_WIDTH_GAINLLR_NF_8P_9_10_FIELD 7 + +#define STV090x_GENCFG 0xFA86 +#define STV090x_OFFST_BROADCAST_FIELD 4 +#define STV090x_WIDTH_BROADCAST_FIELD 1 +#define STV090x_OFFST_PRIORITY_FIELD 1 +#define STV090x_WIDTH_PRIORITY_FIELD 1 +#define STV090x_OFFST_DDEMOD_FIELD 0 +#define STV090x_WIDTH_DDEMOD_FIELD 1 + +#define STV090x_LDPCERRx(__x) (0xFA97 - (__x * 0x1)) +#define STV090x_LDPCERR0 STV090x_LDPCERRx(0) +#define STV090x_LDPCERR1 STV090x_LDPCERRx(1) +#define STV090x_OFFST_Px_LDPC_ERRORS_COUNTER_FIELD 0 +#define STV090x_WIDTH_Px_LDPC_ERRORS_COUNTER_FIELD 8 + +#define STV090x_BCHERR 0xFA98 +#define STV090x_OFFST_Px_ERRORFLAG_FIELD 4 +#define STV090x_WIDTH_Px_ERRORFLAG_FIELD 1 +#define STV090x_OFFST_Px_BCH_ERRORS_COUNTER_FIELD 0 +#define STV090x_WIDTH_Px_BCH_ERRORS_COUNTER_FIELD 4 + +#define STV090x_Px_TSSTATEM(__x) (0xF570 - (__x - 1) * 0x200) +#define STV090x_P1_TSSTATEM STV090x_Px_TSSTATEM(1) +#define STV090x_P2_TSSTATEM STV090x_Px_TSSTATEM(2) +#define STV090x_OFFST_Px_TSDIL_ON_FIELD 7 +#define STV090x_WIDTH_Px_TSDIL_ON_FIELD 1 +#define STV090x_OFFST_Px_TSRS_ON_FIELD 5 +#define STV090x_WIDTH_Px_TSRS_ON_FIELD 1 + +#define STV090x_Px_TSCFGH(__x) (0xF572 - (__x - 1) * 0x200) +#define STV090x_P1_TSCFGH STV090x_Px_TSCFGH(1) +#define STV090x_P2_TSCFGH STV090x_Px_TSCFGH(2) +#define STV090x_OFFST_Px_TSFIFO_DVBCI_FIELD 7 +#define STV090x_WIDTH_Px_TSFIFO_DVBCI_FIELD 1 +#define STV090x_OFFST_Px_TSFIFO_SERIAL_FIELD 6 +#define STV090x_WIDTH_Px_TSFIFO_SERIAL_FIELD 1 +#define STV090x_OFFST_Px_TSFIFO_TEIUPDATE_FIELD 5 +#define STV090x_WIDTH_Px_TSFIFO_TEIUPDATE_FIELD 1 +#define STV090x_OFFST_Px_TSFIFO_DUTY50_FIELD 4 +#define STV090x_WIDTH_Px_TSFIFO_DUTY50_FIELD 1 +#define STV090x_OFFST_Px_TSFIFO_HSGNLOUT_FIELD 3 +#define STV090x_WIDTH_Px_TSFIFO_HSGNLOUT_FIELD 1 +#define STV090x_OFFST_Px_TSFIFO_ERRORMODE_FIELD 1 +#define STV090x_WIDTH_Px_TSFIFO_ERRORMODE_FIELD 2 +#define STV090x_OFFST_Px_RST_HWARE_FIELD 0 +#define STV090x_WIDTH_Px_RST_HWARE_FIELD 1 + +#define STV090x_Px_TSCFGM(__x) (0xF573 - (__x - 1) * 0x200) +#define STV090x_P1_TSCFGM STV090x_Px_TSCFGM(1) +#define STV090x_P2_TSCFGM STV090x_Px_TSCFGM(2) +#define STV090x_OFFST_Px_TSFIFO_MANSPEED_FIELD 6 +#define STV090x_WIDTH_Px_TSFIFO_MANSPEED_FIELD 2 +#define STV090x_OFFST_Px_TSFIFO_PERMDATA_FIELD 5 +#define STV090x_WIDTH_Px_TSFIFO_PERMDATA_FIELD 1 +#define STV090x_OFFST_Px_TSFIFO_INVDATA_FIELD 0 +#define STV090x_WIDTH_Px_TSFIFO_INVDATA__FIELD 1 + +#define STV090x_Px_TSCFGL(__x) (0xF574 - (__x - 1) * 0x200) +#define STV090x_P1_TSCFGL STV090x_Px_TSCFGL(1) +#define STV090x_P2_TSCFGL STV090x_Px_TSCFGL(2) +#define STV090x_OFFST_Px_TSFIFO_BCLKDEL1CK_FIELD 6 +#define STV090x_WIDTH_Px_TSFIFO_BCLKDEL1CK_FIELD 2 +#define STV090x_OFFST_Px_BCHERROR_MODE_FIELD 4 +#define STV090x_WIDTH_Px_BCHERROR_MODE_FIELD 2 +#define STV090x_OFFST_Px_TSFIFO_NSGNL2DATA_FIELD 3 +#define STV090x_WIDTH_Px_TSFIFO_NSGNL2DATA__FIELD 1 +#define STV090x_OFFST_Px_TSFIFO_EMBINDVB_FIELD 2 +#define STV090x_WIDTH_Px_TSFIFO_EMBINDVB_FIELD 1 +#define STV090x_OFFST_Px_TSFIFO_DPUNACT_FIELD 1 +#define STV090x_WIDTH_Px_TSFIFO_DPUNACT_FIELD 1 + +#define STV090x_Px_TSINSDELH(__x) (0xF576 - (__x - 1) * 0x200) +#define STV090x_P1_TSINSDELH STV090x_Px_TSINSDELH(1) +#define STV090x_P2_TSINSDELH STV090x_Px_TSINSDELH(2) +#define STV090x_OFFST_Px_TSDEL_SYNCBYTE_FIELD 7 +#define STV090x_WIDTH_Px_TSDEL_SYNCBYTE_FIELD 1 +#define STV090x_OFFST_Px_TSDEL_XXHEADER_FIELD 6 +#define STV090x_WIDTH_Px_TSDEL_XXHEADER_FIELD 1 + +#define STV090x_Px_TSSPEED(__x) (0xF580 - (__x - 1) * 0x200) +#define STV090x_P1_TSSPEED STV090x_Px_TSSPEED(1) +#define STV090x_P2_TSSPEED STV090x_Px_TSSPEED(2) +#define STV090x_OFFST_Px_TSFIFO_OUTSPEED_FIELD 0 +#define STV090x_WIDTH_Px_TSFIFO_OUTSPEED_FIELD 8 + +#define STV090x_Px_TSSTATUS(__x) (0xF581 - (__x - 1) * 0x200) +#define STV090x_P1_TSSTATUS STV090x_Px_TSSTATUS(1) +#define STV090x_P2_TSSTATUS STV090x_Px_TSSTATUS(2) +#define STV090x_OFFST_Px_TSFIFO_LINEOK_FIELD 7 +#define STV090x_WIDTH_Px_TSFIFO_LINEOK_FIELD 1 +#define STV090x_OFFST_Px_TSFIFO_ERROR_FIELD 6 +#define STV090x_WIDTH_Px_TSFIFO_ERROR_FIELD 1 + +#define STV090x_Px_TSSTATUS2(__x) (0xF582 - (__x - 1) * 0x200) +#define STV090x_P1_TSSTATUS2 STV090x_Px_TSSTATUS2(1) +#define STV090x_P2_TSSTATUS2 STV090x_Px_TSSTATUS2(2) +#define STV090x_OFFST_Px_TSFIFO_DEMODSEL_FIELD 7 +#define STV090x_WIDTH_Px_TSFIFO_DEMODSEL_FIELD 1 +#define STV090x_OFFST_Px_TSFIFOSPEED_STORE_FIELD 6 +#define STV090x_WIDTH_Px_TSFIFOSPEED_STORE_FIELD 1 +#define STV090x_OFFST_Px_DILXX_RESET_FIELD 5 +#define STV090x_WIDTH_Px_DILXX_RESET_FIELD 1 +#define STV090x_OFFST_Px_TSSERIAL_IMPOS_FIELD 5 +#define STV090x_WIDTH_Px_TSSERIAL_IMPOS_FIELD 1 +#define STV090x_OFFST_Px_SCRAMBDETECT_FIELD 1 +#define STV090x_WIDTH_Px_SCRAMBDETECT_FIELD 1 + +#define STV090x_Px_TSBITRATEy(__x, __y) (0xF584 - (__x - 1) * 0x200 - __y * 0x1) +#define STV090x_P1_TSBITRATE0 STV090x_Px_TSBITRATEy(1, 0) +#define STV090x_P1_TSBITRATE1 STV090x_Px_TSBITRATEy(1, 1) +#define STV090x_P2_TSBITRATE0 STV090x_Px_TSBITRATEy(2, 0) +#define STV090x_P2_TSBITRATE1 STV090x_Px_TSBITRATEy(2, 1) +#define STV090x_OFFST_Px_TSFIFO_BITRATE_FIELD 7 +#define STV090x_WIDTH_Px_TSFIFO_BITRATE_FIELD 8 + +#define STV090x_Px_ERRCTRL1(__x) (0xF598 - (__x - 1) * 0x200) +#define STV090x_P1_ERRCTRL1 STV090x_Px_ERRCTRL1(1) +#define STV090x_P2_ERRCTRL1 STV090x_Px_ERRCTRL1(2) +#define STV090x_OFFST_Px_ERR_SOURCE_FIELD 4 +#define STV090x_WIDTH_Px_ERR_SOURCE_FIELD 4 +#define STV090x_OFFST_Px_NUM_EVENT_FIELD 0 +#define STV090x_WIDTH_Px_NUM_EVENT_FIELD 3 + +#define STV090x_Px_ERRCNT12(__x) (0xF599 - (__x - 1) * 0x200) +#define STV090x_P1_ERRCNT12 STV090x_Px_ERRCNT12(1) +#define STV090x_P2_ERRCNT12 STV090x_Px_ERRCNT12(2) +#define STV090x_OFFST_Px_ERRCNT1_OLDVALUE__FIELD 7 +#define STV090x_WIDTH_Px_ERRCNT1_OLDVALUE_FIELD 1 +#define STV090x_OFFST_Px_ERR_CNT12_FIELD 0 +#define STV090x_WIDTH_Px_ERR_CNT12_FIELD 7 + +#define STV090x_Px_ERRCNT11(__x) (0xF59A - (__x - 1) * 0x200) +#define STV090x_P1_ERRCNT11 STV090x_Px_ERRCNT11(1) +#define STV090x_P2_ERRCNT11 STV090x_Px_ERRCNT11(2) +#define STV090x_OFFST_Px_ERR_CNT11_FIELD 0 +#define STV090x_WIDTH_Px_ERR_CNT11_FIELD 8 + +#define STV090x_Px_ERRCNT10(__x) (0xF59B - (__x - 1) * 0x200) +#define STV090x_P1_ERRCNT10 STV090x_Px_ERRCNT10(1) +#define STV090x_P2_ERRCNT10 STV090x_Px_ERRCNT10(2) +#define STV090x_OFFST_Px_ERR_CNT10_FIELD 0 +#define STV090x_WIDTH_Px_ERR_CNT10_FIELD 8 + +#define STV090x_Px_ERRCTRL2(__x) (0xF59C - (__x - 1) * 0x200) +#define STV090x_P1_ERRCTRL2 STV090x_Px_ERRCTRL2(1) +#define STV090x_P2_ERRCTRL2 STV090x_Px_ERRCTRL2(2) +#define STV090x_OFFST_Px_ERR_SOURCE2_FIELD 4 +#define STV090x_WIDTH_Px_ERR_SOURCE2_FIELD 4 +#define STV090x_OFFST_Px_NUM_EVENT2_FIELD 0 +#define STV090x_WIDTH_Px_NUM_EVENT2_FIELD 3 + +#define STV090x_Px_ERRCNT22(__x) (0xF59D - (__x - 1) * 0x200) +#define STV090x_P1_ERRCNT22 STV090x_Px_ERRCNT22(1) +#define STV090x_P2_ERRCNT22 STV090x_Px_ERRCNT22(2) +#define STV090x_OFFST_Px_ERRCNT2_OLDVALUE_FIELD 7 +#define STV090x_WIDTH_Px_ERRCNT2_OLDVALUE_FIELD 1 +#define STV090x_OFFST_Px_ERR_CNT2_FIELD 0 +#define STV090x_WIDTH_Px_ERR_CNT2_FIELD 7 + +#define STV090x_Px_ERRCNT21(__x) (0xF59E - (__x - 1) * 0x200) +#define STV090x_P1_ERRCNT21 STV090x_Px_ERRCNT21(1) +#define STV090x_P2_ERRCNT21 STV090x_Px_ERRCNT21(2) +#define STV090x_OFFST_Px_ERR_CNT21_FIELD 0 +#define STV090x_WIDTH_Px_ERR_CNT21_FIELD 8 + +#define STV090x_Px_ERRCNT20(__x) (0xF59F - (__x - 1) * 0x200) +#define STV090x_P1_ERRCNT20 STV090x_Px_ERRCNT20(1) +#define STV090x_P2_ERRCNT20 STV090x_Px_ERRCNT20(2) +#define STV090x_OFFST_Px_ERR_CNT20_FIELD 0 +#define STV090x_WIDTH_Px_ERR_CNT20_FIELD 8 + +#define STV090x_Px_FECSPY(__x) (0xF5A0 - (__x - 1) * 0x200) +#define STV090x_P1_FECSPY STV090x_Px_FECSPY(1) +#define STV090x_P2_FECSPY STV090x_Px_FECSPY(2) +#define STV090x_OFFST_Px_SPY_ENABLE_FIELD 7 +#define STV090x_WIDTH_Px_SPY_ENABLE_FIELD 1 +#define STV090x_OFFST_Px_BERMETER_DATAMAODE_FIELD 2 +#define STV090x_WIDTH_Px_BERMETER_DATAMAODE_FIELD 2 + +#define STV090x_Px_FSPYCFG(__x) (0xF5A1 - (__x - 1) * 0x200) +#define STV090x_P1_FSPYCFG STV090x_Px_FSPYCFG(1) +#define STV090x_P2_FSPYCFG STV090x_Px_FSPYCFG(2) +#define STV090x_OFFST_Px_RST_ON_ERROR_FIELD 5 +#define STV090x_WIDTH_Px_RST_ON_ERROR_FIELD 1 +#define STV090x_OFFST_Px_ONE_SHOT_FIELD 4 +#define STV090x_WIDTH_Px_ONE_SHOT_FIELD 1 +#define STV090x_OFFST_Px_I2C_MODE_FIELD 2 +#define STV090x_WIDTH_Px_I2C_MODE_FIELD 2 + +#define STV090x_Px_FSPYDATA(__x) (0xF5A2 - (__x - 1) * 0x200) +#define STV090x_P1_FSPYDATA STV090x_Px_FSPYDATA(1) +#define STV090x_P2_FSPYDATA STV090x_Px_FSPYDATA(2) +#define STV090x_OFFST_Px_SPY_STUFFING_FIELD 7 +#define STV090x_WIDTH_Px_SPY_STUFFING_FIELD 1 +#define STV090x_OFFST_Px_SPY_CNULLPKT_FIELD 5 +#define STV090x_WIDTH_Px_SPY_CNULLPKT_FIELD 1 +#define STV090x_OFFST_Px_SPY_OUTDATA_MODE_FIELD 0 +#define STV090x_WIDTH_Px_SPY_OUTDATA_MODE_FIELD 5 + +#define STV090x_Px_FSPYOUT(__x) (0xF5A3 - (__x - 1) * 0x200) +#define STV090x_P1_FSPYOUT STV090x_Px_FSPYOUT(1) +#define STV090x_P2_FSPYOUT STV090x_Px_FSPYOUT(2) +#define STV090x_OFFST_Px_FSPY_DIRECT_FIELD 7 +#define STV090x_WIDTH_Px_FSPY_DIRECT_FIELD 1 +#define STV090x_OFFST_Px_STUFF_MODE_FIELD 0 +#define STV090x_WIDTH_Px_STUFF_MODE_FIELD 3 + +#define STV090x_Px_FSTATUS(__x) (0xF5A4 - (__x - 1) * 0x200) +#define STV090x_P1_FSTATUS STV090x_Px_FSTATUS(1) +#define STV090x_P2_FSTATUS STV090x_Px_FSTATUS(2) +#define STV090x_OFFST_Px_SPY_ENDSIM_FIELD 7 +#define STV090x_WIDTH_Px_SPY_ENDSIM_FIELD 1 +#define STV090x_OFFST_Px_VALID_SIM_FIELD 6 +#define STV090x_WIDTH_Px_VALID_SIM_FIELD 1 +#define STV090x_OFFST_Px_FOUND_SIGNAL_FIELD 5 +#define STV090x_WIDTH_Px_FOUND_SIGNAL_FIELD 1 +#define STV090x_OFFST_Px_DSS_SYNCBYTE_FIELD 4 +#define STV090x_WIDTH_Px_DSS_SYNCBYTE_FIELD 1 +#define STV090x_OFFST_Px_RESULT_STATE_FIELD 0 +#define STV090x_WIDTH_Px_RESULT_STATE_FIELD 4 + +#define STV090x_Px_FBERCPT4(__x) (0xF5A8 - (__x - 1) * 0x200) +#define STV090x_P1_FBERCPT4 STV090x_Px_FBERCPT4(1) +#define STV090x_P2_FBERCPT4 STV090x_Px_FBERCPT4(2) +#define STV090x_OFFST_Px_FBERMETER_CPT_FIELD 0 +#define STV090x_WIDTH_Px_BERMETER_CPT_FIELD 8 + +#define STV090x_Px_FBERCPT3(__x) (0xF5A9 - (__x - 1) * 0x200) +#define STV090x_P1_FBERCPT3 STV090x_Px_FBERCPT3(1) +#define STV090x_P2_FBERCPT3 STV090x_Px_FBERCPT3(2) +#define STV090x_OFFST_Px_FBERMETER_CPT_FIELD 0 +#define STV090x_WIDTH_Px_FBERMETER_CPT_FIELD 8 + +#define STV090x_Px_FBERCPT2(__x) (0xF5AA - (__x - 1) * 0x200) +#define STV090x_P1_FBERCPT2 STV090x_Px_FBERCPT2(1) +#define STV090x_P2_FBERCPT2 STV090x_Px_FBERCPT2(2) +#define STV090x_OFFST_Px_FBERMETER_CPT_FIELD 0 +#define STV090x_WIDTH_Px_FBERMETER_CPT_FIELD 8 + +#define STV090x_Px_FBERCPT1(__x) (0xF5AB - (__x - 1) * 0x200) +#define STV090x_P1_FBERCPT1 STV090x_Px_FBERCPT1(1) +#define STV090x_P2_FBERCPT1 STV090x_Px_FBERCPT1(2) +#define STV090x_OFFST_Px_FBERMETER_CPT_FIELD 0 +#define STV090x_WIDTH_Px_FBERMETER_CPT_FIELD 8 + +#define STV090x_Px_FBERCPT0(__x) (0xF5AC - (__x - 1) * 0x200) +#define STV090x_P1_FBERCPT0 STV090x_Px_FBERCPT0(1) +#define STV090x_P2_FBERCPT0 STV090x_Px_FBERCPT0(2) +#define STV090x_OFFST_Px_FBERMETER_CPT_FIELD 0 +#define STV090x_WIDTH_Px_FBERMETER_CPT_FIELD 8 + +#define STV090x_Px_FBERERRy(__x, __y) (0xF5AF - (__x - 1) * 0x200 - __y * 0x1) +#define STV090x_P1_FBERERR0 STV090x_Px_FBERERRy(1, 0) +#define STV090x_P1_FBERERR1 STV090x_Px_FBERERRy(1, 1) +#define STV090x_P1_FBERERR2 STV090x_Px_FBERERRy(1, 2) +#define STV090x_P2_FBERERR0 STV090x_Px_FBERERRy(2, 0) +#define STV090x_P2_FBERERR1 STV090x_Px_FBERERRy(2, 1) +#define STV090x_P2_FBERERR2 STV090x_Px_FBERERRy(2, 2) +#define STV090x_OFFST_Px_FBERMETER_CPT_ERR_FIELD 0 +#define STV090x_WIDTH_Px_FBERMETER_CPT_ERR_FIELD 8 + +#define STV090x_Px_FSPYBER(__x) (0xF5B2 - (__x - 1) * 0x200) +#define STV090x_P1_FSPYBER STV090x_Px_FSPYBER(1) +#define STV090x_P2_FSPYBER STV090x_Px_FSPYBER(2) +#define STV090x_OFFST_Px_FSPYBER_SYNCBYTE_FIELD 4 +#define STV090x_WIDTH_Px_FSPYBER_SYNCBYTE_FIELD 1 +#define STV090x_OFFST_Px_FSPYBER_UNSYNC_FIELD 3 +#define STV090x_WIDTH_Px_FSPYBER_UNSYNC_FIELD 1 +#define STV090x_OFFST_Px_FSPYBER_CTIME_FIELD 0 +#define STV090x_WIDTH_Px_FSPYBER_CTIME_FIELD 3 + +#define STV090x_TSGENERAL 0xF630 +#define STV090x_OFFST_Px_MUXSTREAM_OUT_FIELD 3 +#define STV090x_WIDTH_Px_MUXSTREAM_OUT_FIELD 1 +#define STV090x_OFFST_Px_TSFIFO_PERMPARAL_FIELD 1 +#define STV090x_WIDTH_Px_TSFIFO_PERMPARAL_FIELD 2 + +#define STV090x_TSTRES0 0xFF11 +#define STV090x_OFFST_FRESFEC_FIELD 7 +#define STV090x_WIDTH_FRESFEC_FIELD 1 + +#define STV090x_Px_TSTDISRX(__x) (0xFF67 - (__x - 1) * 0x2) +#define STV090x_P1_TSTDISRX STV090x_Px_TSTDISRX(1) +#define STV090x_P2_TSTDISRX STV090x_Px_TSTDISRX(2) +#define STV090x_OFFST_Px_TSTDISRX_SELECT_FIELD 3 +#define STV090x_WIDTH_Px_TSTDISRX_SELECT_FIELD 1 + +#endif /* __STV090x_REG_H */ diff --git a/linux/drivers/media/dvb/frontends/stv6110x.c b/linux/drivers/media/dvb/frontends/stv6110x.c new file mode 100644 index 000000000..c818e21f4 --- /dev/null +++ b/linux/drivers/media/dvb/frontends/stv6110x.c @@ -0,0 +1,442 @@ +/* + STV6110(A) Silicon tuner driver + + Copyright (C) Manu Abraham + + Copyright (C) ST Microelectronics + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include +#include +#include +#include + +#include "dvb_frontend.h" + +#include "stv6110x_reg.h" +#include "stv6110x.h" +#include "stv6110x_priv.h" + +static unsigned int verbose; +module_param(verbose, int, 0644); +MODULE_PARM_DESC(verbose, "Set Verbosity level"); + +static u8 stv6110x_regs[] = {0x07, 0x11, 0xdc, 0x85, 0x17, 0x01, 0xe6, 0x1e}; + +static int stv6110x_read_reg(struct stv6110x_state *stv6110x, u8 reg, u8 *data) +{ + int ret; + const struct stv6110x_config *config = stv6110x->config; + u8 b0[] = { reg }; + u8 b1[] = { 0 }; + struct i2c_msg msg[] = { + { .addr = config->addr, .flags = 0, .buf = b0, .len = 1 }, + { .addr = config->addr, .flags = I2C_M_RD, .buf = b1, .len = 1 } + }; + + ret = i2c_transfer(stv6110x->i2c, msg, 2); + if (ret != 2) { + dprintk(FE_ERROR, 1, "I/O Error"); + return -EREMOTEIO; + } + + return 0; +} + +static int stv6110x_write_reg(struct stv6110x_state *stv6110x, u8 reg, u8 data) +{ + int ret; + const struct stv6110x_config *config = stv6110x->config; + u8 buf[] = { reg, data }; + struct i2c_msg msg = { .addr = config->addr, .flags = 0, . buf = buf, .len = 2 }; + + ret = i2c_transfer(stv6110x->i2c, &msg, 1); + if (ret != 1) { + dprintk(FE_ERROR, 1, "I/O Error"); + return -EREMOTEIO; + } + + return 0; +} + +static int stv6110x_init(struct dvb_frontend *fe) +{ + struct stv6110x_state *stv6110x = fe->tuner_priv; + int ret; + u8 i; + + for (i = 0; i < ARRAY_SIZE(stv6110x_regs); i++) { + ret = stv6110x_write_reg(stv6110x, i, stv6110x_regs[i]); + if (ret < 0) { + dprintk(FE_ERROR, 1, "Initialization failed"); + return -1; + } + } + + return 0; +} + +static int stv6110x_set_frequency(struct dvb_frontend *fe, u32 frequency) +{ + struct stv6110x_state *stv6110x = fe->tuner_priv; + u32 rDiv, divider; + s32 pVal, pCalc, rDivOpt = 0; + u8 i; + + STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL1], CTRL1_K, (REFCLOCK_MHz - 16)); + + if (frequency <= 1023000) { + STV6110x_SETFIELD(stv6110x_regs[STV6110x_TNG1], TNG1_DIV4SEL, 1); + STV6110x_SETFIELD(stv6110x_regs[STV6110x_TNG1], TNG1_PRESC32_ON, 0); + pVal = 40; + } else if (frequency <= 1300000) { + STV6110x_SETFIELD(stv6110x_regs[STV6110x_TNG1], TNG1_DIV4SEL, 1); + STV6110x_SETFIELD(stv6110x_regs[STV6110x_TNG1], TNG1_PRESC32_ON, 1); + pVal = 40; + } else if (frequency <= 2046000) { + STV6110x_SETFIELD(stv6110x_regs[STV6110x_TNG1], TNG1_DIV4SEL, 0); + STV6110x_SETFIELD(stv6110x_regs[STV6110x_TNG1], TNG1_PRESC32_ON, 0); + pVal = 20; + } else { + STV6110x_SETFIELD(stv6110x_regs[STV6110x_TNG1], TNG1_DIV4SEL, 0); + STV6110x_SETFIELD(stv6110x_regs[STV6110x_TNG1], TNG1_PRESC32_ON, 1); + pVal = 20; + } + + for (rDiv = 0; rDiv <= 3; rDiv++) { + pCalc = (REFCLOCK_kHz / 100) / R_DIV(rDiv); + + if ((abs((s32)(pCalc - pVal))) < (abs((s32)(1000 - pVal)))) + rDivOpt = rDiv; + } + + divider = (frequency * R_DIV(rDivOpt) * pVal) / REFCLOCK_kHz; + divider = (divider + 5) / 10; + + STV6110x_SETFIELD(stv6110x_regs[STV6110x_TNG1], TNG1_R_DIV, rDivOpt); + STV6110x_SETFIELD(stv6110x_regs[STV6110x_TNG1], TNG1_N_DIV_11_8, MSB(divider)); + STV6110x_SETFIELD(stv6110x_regs[STV6110x_TNG0], TNG0_N_DIV_7_0, LSB(divider)); + + /* VCO Auto calibration */ + STV6110x_SETFIELD(stv6110x_regs[STV6110x_STAT1], STAT1_CALVCO_STRT, 1); + + stv6110x_write_reg(stv6110x, STV6110x_CTRL1, stv6110x_regs[STV6110x_CTRL1]); + stv6110x_write_reg(stv6110x, STV6110x_TNG1, stv6110x_regs[STV6110x_TNG1]); + stv6110x_write_reg(stv6110x, STV6110x_TNG0, stv6110x_regs[STV6110x_TNG0]); + stv6110x_write_reg(stv6110x, STV6110x_STAT1, stv6110x_regs[STV6110x_STAT1]); + + for (i = 0; i < TRIALS; i++) { + stv6110x_read_reg(stv6110x, STV6110x_STAT1, &stv6110x_regs[STV6110x_STAT1]); + if (!STV6110x_GETFIELD(STAT1_CALVCO_STRT, stv6110x_regs[STV6110x_STAT1])) + break; + msleep(1); + } + + return 0; +} + +static int stv6110x_get_frequency(struct dvb_frontend *fe, u32 *frequency) +{ + struct stv6110x_state *stv6110x = fe->tuner_priv; + + stv6110x_read_reg(stv6110x, STV6110x_TNG1, &stv6110x_regs[STV6110x_TNG1]); + stv6110x_read_reg(stv6110x, STV6110x_TNG0, &stv6110x_regs[STV6110x_TNG0]); + + *frequency = (MAKEWORD16(STV6110x_GETFIELD(TNG1_N_DIV_11_8, stv6110x_regs[STV6110x_TNG1]), + STV6110x_GETFIELD(TNG0_N_DIV_7_0, stv6110x_regs[STV6110x_TNG0]))) * REFCLOCK_kHz; + + *frequency /= (1 << (STV6110x_GETFIELD(TNG1_R_DIV, stv6110x_regs[STV6110x_TNG1]) + + STV6110x_GETFIELD(TNG1_DIV4SEL, stv6110x_regs[STV6110x_TNG1]))); + + *frequency >>= 2; + + return 0; +} + +static int stv6110x_set_bandwidth(struct dvb_frontend *fe, u32 bandwidth) +{ + struct stv6110x_state *stv6110x = fe->tuner_priv; + u32 halfbw; + u8 i; + + halfbw = bandwidth >> 1; + + if (halfbw > 36000000) + STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL3], CTRL3_CF, 31); /* LPF */ + else if (halfbw < 5000000) + STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL3], CTRL3_CF, 0); /* LPF */ + else + STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL3], CTRL3_CF, ((halfbw / 1000000) - 5)); /* LPF */ + + + STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL3], CTRL3_RCCLK_OFF, 0x0); /* cal. clk activated */ + STV6110x_SETFIELD(stv6110x_regs[STV6110x_STAT1], STAT1_CALRC_STRT, 0x1); /* LPF auto cal */ + + stv6110x_write_reg(stv6110x, STV6110x_CTRL3, stv6110x_regs[STV6110x_CTRL3]); + stv6110x_write_reg(stv6110x, STV6110x_STAT1, stv6110x_regs[STV6110x_STAT1]); + + for (i = 0; i < TRIALS; i++) { + stv6110x_read_reg(stv6110x, STV6110x_STAT1, &stv6110x_regs[STV6110x_STAT1]); + if (!STV6110x_GETFIELD(STAT1_CALRC_STRT, stv6110x_regs[STV6110x_STAT1])) + break; + msleep(1); + } + STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL3], CTRL3_RCCLK_OFF, 0x1); /* cal. done */ + stv6110x_write_reg(stv6110x, STV6110x_CTRL3, stv6110x_regs[STV6110x_CTRL3]); + + return 0; +} + +static int stv6110x_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth) +{ + struct stv6110x_state *stv6110x = fe->tuner_priv; + + stv6110x_read_reg(stv6110x, STV6110x_CTRL3, &stv6110x_regs[STV6110x_CTRL3]); + *bandwidth = (STV6110x_GETFIELD(CTRL3_CF, stv6110x_regs[STV6110x_CTRL3]) + 5) * 2000000; + + return 0; +} + +static int stv6110x_set_refclock(struct dvb_frontend *fe, u32 refclock) +{ + struct stv6110x_state *stv6110x = fe->tuner_priv; + + /* setup divider */ + switch (refclock) { + default: + case 1: + STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL2], CTRL2_CO_DIV, 0); + break; + case 2: + STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL2], CTRL2_CO_DIV, 1); + break; + case 4: + STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL2], CTRL2_CO_DIV, 2); + break; + case 8: + case 0: + STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL2], CTRL2_CO_DIV, 3); + break; + } + stv6110x_write_reg(stv6110x, STV6110x_CTRL2, stv6110x_regs[STV6110x_CTRL2]); + + return 0; +} + +static int stv6110x_get_bbgain(struct dvb_frontend *fe, u32 *gain) +{ + struct stv6110x_state *stv6110x = fe->tuner_priv; + + stv6110x_read_reg(stv6110x, STV6110x_CTRL2, &stv6110x_regs[STV6110x_CTRL2]); + *gain = 2 * STV6110x_GETFIELD(CTRL2_BBGAIN, stv6110x_regs[STV6110x_CTRL2]); + + return 0; +} + +static int stv6110x_set_bbgain(struct dvb_frontend *fe, u32 gain) +{ + struct stv6110x_state *stv6110x = fe->tuner_priv; + + STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL2], CTRL2_BBGAIN, gain / 2); + stv6110x_write_reg(stv6110x, STV6110x_CTRL2, stv6110x_regs[STV6110x_CTRL2]); + + return 0; +} + +static int stv6110x_set_mode(struct dvb_frontend *fe, enum tuner_mode mode) +{ + struct stv6110x_state *stv6110x = fe->tuner_priv; + int ret; + + switch (mode) { + case TUNER_SLEEP: + STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL1], CTRL1_SYN, 0); + STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL1], CTRL1_RX, 0); + STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL1], CTRL1_LPT, 0); + break; + + case TUNER_WAKE: + STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL1], CTRL1_SYN, 1); + STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL1], CTRL1_RX, 1); + STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL1], CTRL1_LPT, 1); + break; + } + + ret = stv6110x_write_reg(stv6110x, STV6110x_CTRL1, stv6110x_regs[STV6110x_CTRL1]); + if (ret < 0) { + dprintk(FE_ERROR, 1, "I/O Error"); + return -EIO; + } + + return 0; +} + +static int stv6110x_sleep(struct dvb_frontend *fe) +{ + return stv6110x_set_mode(fe, TUNER_SLEEP); +} + +static int stv6110x_get_status(struct dvb_frontend *fe, u32 *status) +{ + struct stv6110x_state *stv6110x = fe->tuner_priv; + + stv6110x_read_reg(stv6110x, STV6110x_STAT1, &stv6110x_regs[STV6110x_STAT1]); + + if (STV6110x_GETFIELD(STAT1_LOCK, stv6110x_regs[STV6110x_STAT1])) + *status = TUNER_PHASELOCKED; + else + *status = 0; + + return 0; +} + +#if 0 +static int stv6110x_get_state(struct dvb_frontend *fe, + enum tuner_param param, + struct tuner_state *state) +{ + switch (param) { + case DVBFE_TUNER_FREQUENCY: + stv6110x_get_frequency(fe, &state->frequency); + break; + + case DVBFE_TUNER_TUNERSTEP: + break; + + case DVBFE_TUNER_IFFREQ: + break; + + case DVBFE_TUNER_BANDWIDTH: + stv6110x_get_bandwidth(fe, &state->bandwidth); + break; + + case DVBFE_TUNER_REFCLOCK: + break; + + default: + break; + } + + return 0; +} + +static int stv6110x_set_state(struct dvb_frontend *fe, + enum tuner_param param, + struct tuner_state *tstate) +{ + struct stv6110x_state *stv6110x = fe->tuner_priv; + + switch (param) { + case DVBFE_TUNER_FREQUENCY: + stv6110x_set_frequency(fe, stv6110x->frequency); + tstate->frequency = stv6110x->frequency; + break; + + case DVBFE_TUNER_TUNERSTEP: + break; + + case DVBFE_TUNER_IFFREQ: + break; + + case DVBFE_TUNER_BANDWIDTH: + stv6110x_set_bandwidth(fe, stv6110x->bandwidth); + tstate->bandwidth = stv6110x->bandwidth; + break; + + case DVBFE_TUNER_REFCLOCK: + stv6110x_set_refclock(fe, stv6110x->reference); + tstate->refclock = stv6110x->reference; + break; + + default: + break; + } + + return 0; +} +#endif + +static int stv6110x_release(struct dvb_frontend *fe) +{ + struct stv6110x_state *stv6110x = fe->tuner_priv; + + fe->tuner_priv = NULL; + kfree(stv6110x); + + return 0; +} + +static struct dvb_tuner_ops stv6110x_ops = { + .info = { + .name = "STV6110(A) Silicon Tuner", + .frequency_min = 950000, + .frequency_max = 2150000, + .frequency_step = 0, + }, + + .init = stv6110x_init, + .sleep = stv6110x_sleep, +#if 0 + .get_status = stv6110x_get_status, + .get_state = stv6110x_get_state, + .set_state = stv6110x_set_state, +#endif + .release = stv6110x_release +}; + +static struct stv6110x_devctl stv6110x_ctl = { + .tuner_init = stv6110x_init, + .tuner_set_mode = stv6110x_set_mode, + .tuner_set_frequency = stv6110x_set_frequency, + .tuner_get_frequency = stv6110x_get_frequency, + .tuner_set_bandwidth = stv6110x_set_bandwidth, + .tuner_get_bandwidth = stv6110x_get_bandwidth, + .tuner_set_bbgain = stv6110x_set_bbgain, + .tuner_get_bbgain = stv6110x_get_bbgain, + .tuner_set_refclk = stv6110x_set_refclock, + .tuner_get_status = stv6110x_get_status, +}; + +struct stv6110x_devctl *stv6110x_attach(struct dvb_frontend *fe, + const struct stv6110x_config *config, + struct i2c_adapter *i2c) +{ + struct stv6110x_state *stv6110x; + + stv6110x = kzalloc(sizeof (struct stv6110x_state), GFP_KERNEL); + if (stv6110x == NULL) + goto error; + + stv6110x->i2c = i2c; + stv6110x->config = config; + stv6110x->devctl = &stv6110x_ctl; + + fe->tuner_priv = stv6110x; + fe->ops.tuner_ops = stv6110x_ops; + + printk("%s: Attaching STV6110x \n", __func__); + return stv6110x->devctl; + +error: + kfree(stv6110x); + return NULL; +} +EXPORT_SYMBOL(stv6110x_attach); + +MODULE_AUTHOR("Manu Abraham"); +MODULE_DESCRIPTION("STV6110x Silicon tuner"); +MODULE_LICENSE("GPL"); diff --git a/linux/drivers/media/dvb/frontends/stv6110x.h b/linux/drivers/media/dvb/frontends/stv6110x.h new file mode 100644 index 000000000..6d43c294e --- /dev/null +++ b/linux/drivers/media/dvb/frontends/stv6110x.h @@ -0,0 +1,71 @@ +/* + STV6110(A) Silicon tuner driver + + Copyright (C) Manu Abraham + + Copyright (C) ST Microelectronics + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __STV6110x_H +#define __STV6110x_H + +struct stv6110x_config { + u8 addr; + u32 refclk; +}; + +enum tuner_mode { + TUNER_SLEEP = 1, + TUNER_WAKE, +}; + +enum tuner_status { + TUNER_PHASELOCKED = 1, +}; + +struct stv6110x_devctl { + int (*tuner_init) (struct dvb_frontend *fe); + int (*tuner_set_mode) (struct dvb_frontend *fe, enum tuner_mode mode); + int (*tuner_set_frequency) (struct dvb_frontend *fe, u32 frequency); + int (*tuner_get_frequency) (struct dvb_frontend *fe, u32 *frequency); + int (*tuner_set_bandwidth) (struct dvb_frontend *fe, u32 bandwidth); + int (*tuner_get_bandwidth) (struct dvb_frontend *fe, u32 *bandwidth); + int (*tuner_set_bbgain) (struct dvb_frontend *fe, u32 gain); + int (*tuner_get_bbgain) (struct dvb_frontend *fe, u32 *gain); + int (*tuner_set_refclk) (struct dvb_frontend *fe, u32 refclk); + int (*tuner_get_status) (struct dvb_frontend *fe, u32 *status); +}; + + +#if defined(CONFIG_DVB_STV6110x) || (defined(CONFIG_DVB_STV6110x_MODULE) && defined(MODULE)) + +extern struct stv6110x_devctl *stv6110x_attach(struct dvb_frontend *fe, + const struct stv6110x_config *config, + struct i2c_adapter *i2c); + +#else +static inline struct stv6110x_devctl *stv6110x_attach(struct dvb_frontend *fe, + const struct stv6110x_config *config, + struct i2c_adapter *i2c); +{ + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); + return NULL; +} + +#endif /* CONFIG_DVB_STV6110x */ + +#endif /* __STV6110x_H */ diff --git a/linux/drivers/media/dvb/frontends/stv6110x_priv.h b/linux/drivers/media/dvb/frontends/stv6110x_priv.h new file mode 100644 index 000000000..1295272fc --- /dev/null +++ b/linux/drivers/media/dvb/frontends/stv6110x_priv.h @@ -0,0 +1,77 @@ +/* + STV6110(A) Silicon tuner driver + + Copyright (C) Manu Abraham + + Copyright (C) ST Microelectronics + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __STV6110x_PRIV_H +#define __STV6110x_PRIV_H + +#define FE_ERROR 0 +#define FE_NOTICE 1 +#define FE_INFO 2 +#define FE_DEBUG 3 +#define FE_DEBUGREG 4 + +#define dprintk(__y, __z, format, arg...) do { \ + if (__z) { \ + if ((verbose > FE_ERROR) && (verbose > __y)) \ + printk(KERN_ERR "%s: " format "\n", __func__ , ##arg); \ + else if ((verbose > FE_NOTICE) && (verbose > __y)) \ + printk(KERN_NOTICE "%s: " format "\n", __func__ , ##arg); \ + else if ((verbose > FE_INFO) && (verbose > __y)) \ + printk(KERN_INFO "%s: " format "\n", __func__ , ##arg); \ + else if ((verbose > FE_DEBUG) && (verbose > __y)) \ + printk(KERN_DEBUG "%s: " format "\n", __func__ , ##arg); \ + } else { \ + if (verbose > __y) \ + printk(format, ##arg); \ + } \ +} while (0) + + +#define STV6110x_SETFIELD(mask, bitf, val) \ + (mask = (mask & (~(((1 << STV6110x_WIDTH_##bitf) - 1) << \ + STV6110x_OFFST_##bitf))) | \ + (val << STV6110x_OFFST_##bitf)) + +#define STV6110x_GETFIELD(bitf, val) \ + ((val >> STV6110x_OFFST_##bitf) & \ + ((1 << STV6110x_WIDTH_##bitf) - 1)) + +#define MAKEWORD16(a, b) (((a) << 8) | (b)) + +#define LSB(x) ((x & 0xff)) +#define MSB(y) ((y >> 8) & 0xff) + +#define TRIALS 10 +#define R_DIV(__div) (1 << (__div + 1)) +#define REFCLOCK_kHz (stv6110x->reference / 1000) +#define REFCLOCK_MHz (stv6110x->reference / 1000000) + +struct stv6110x_state { + struct i2c_adapter *i2c; + const struct stv6110x_config *config; + + struct stv6110x_devctl *devctl; + + u32 reference; +}; + +#endif /* __STV6110x_PRIV_H */ diff --git a/linux/drivers/media/dvb/frontends/stv6110x_reg.h b/linux/drivers/media/dvb/frontends/stv6110x_reg.h new file mode 100644 index 000000000..93e5c70e5 --- /dev/null +++ b/linux/drivers/media/dvb/frontends/stv6110x_reg.h @@ -0,0 +1,82 @@ +/* + STV6110(A) Silicon tuner driver + + Copyright (C) Manu Abraham + + Copyright (C) ST Microelectronics + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __STV6110x_REG_H +#define __STV6110x_REG_H + +#define STV6110x_CTRL1 0x00 +#define STV6110x_OFFST_CTRL1_K 3 +#define STV6110x_WIDTH_CTRL1_K 5 +#define STV6110x_OFFST_CTRL1_LPT 2 +#define STV6110x_WIDTH_CTRL1_LPT 1 +#define STV6110x_OFFST_CTRL1_RX 1 +#define STV6110x_WIDTH_CTRL1_RX 1 +#define STV6110x_OFFST_CTRL1_SYN 0 +#define STV6110x_WIDTH_CTRL1_SYN 1 + +#define STV6110x_CTRL2 0x01 +#define STV6110x_OFFST_CTRL2_CO_DIV 6 +#define STV6110x_WIDTH_CTRL2_CO_DIV 2 +#define STV6110x_OFFST_CTRL2_RSVD 5 +#define STV6110x_WIDTH_CTRL2_RSVD 1 +#define STV6110x_OFFST_CTRL2_REFOUT_SEL 4 +#define STV6110x_WIDTH_CTRL2_REFOUT_SEL 1 +#define STV6110x_OFFST_CTRL2_BBGAIN 0 +#define STV6110x_WIDTH_CTRL2_BBGAIN 4 + +#define STV6110x_TNG0 0x02 +#define STV6110x_OFFST_TNG0_N_DIV_7_0 0 +#define STV6110x_WIDTH_TNG0_N_DIV_7_0 8 + +#define STV6110x_TNG1 0x03 +#define STV6110x_OFFST_TNG1_R_DIV 6 +#define STV6110x_WIDTH_TNG1_R_DIV 2 +#define STV6110x_OFFST_TNG1_PRESC32_ON 5 +#define STV6110x_WIDTH_TNG1_PRESC32_ON 1 +#define STV6110x_OFFST_TNG1_DIV4SEL 4 +#define STV6110x_WIDTH_TNG1_DIV4SEL 1 +#define STV6110x_OFFST_TNG1_N_DIV_11_8 0 +#define STV6110x_WIDTH_TNG1_N_DIV_11_8 4 + + +#define STV6110x_CTRL3 0x04 +#define STV6110x_OFFST_CTRL3_DCLOOP_OFF 7 +#define STV6110x_WIDTH_CTRL3_DCLOOP_OFF 1 +#define STV6110x_OFFST_CTRL3_RCCLK_OFF 6 +#define STV6110x_WIDTH_CTRL3_RCCLK_OFF 1 +#define STV6110x_OFFST_CTRL3_ICP 5 +#define STV6110x_WIDTH_CTRL3_ICP 1 +#define STV6110x_OFFST_CTRL3_CF 0 +#define STV6110x_WIDTH_CTRL3_CF 5 + +#define STV6110x_STAT1 0x05 +#define STV6110x_OFFST_STAT1_CALVCO_STRT 2 +#define STV6110x_WIDTH_STAT1_CALVCO_STRT 1 +#define STV6110x_OFFST_STAT1_CALRC_STRT 1 +#define STV6110x_WIDTH_STAT1_CALRC_STRT 1 +#define STV6110x_OFFST_STAT1_LOCK 0 +#define STV6110x_WIDTH_STAT1_LOCK 1 + +#define STV6110x_STAT2 0x06 +#define STV6110x_STAT3 0x07 + +#endif /* __STV6110x_REG_H */ diff --git a/linux/drivers/media/dvb/ttpci/budget-ci.c b/linux/drivers/media/dvb/ttpci/budget-ci.c index 1b564eb79..bab8a041c 100644 --- a/linux/drivers/media/dvb/ttpci/budget-ci.c +++ b/linux/drivers/media/dvb/ttpci/budget-ci.c @@ -57,6 +57,9 @@ #include "bsru6.h" #include "tda1002x.h" #include "tda827x.h" +#include "stv6110x.h" +#include "stv090x.h" +#include "isl6423.h" /* * Regarding DEBIADDR_IR: @@ -1354,6 +1357,41 @@ static struct stb6100_config tt3200_stb6100_config = { .refclock = 27000000, }; +static struct stv090x_config tt1600_stv090x_config = { + .device = STV0903, + .demod_mode = STV090x_SINGLE, + .clk_mode = STV090x_CLK_INT, + + .xtal = 8000000, + .address = 0x68, + .ref_clk = 16000000, + + .ts1_mode = STV090x_TSMODE_DVBCI, + .ts2_mode = STV090x_TSMODE_DVBCI, + + .tuner_init = NULL, + .tuner_set_mode = NULL, + .tuner_set_frequency = NULL, + .tuner_get_frequency = NULL, + .tuner_set_bandwidth = NULL, + .tuner_get_bandwidth = NULL, + .tuner_set_bbgain = NULL, + .tuner_get_bbgain = NULL, + .tuner_set_refclk = NULL, + .tuner_get_status = NULL, +}; + +static struct stv6110x_config tt1600_stv6110x_config = { + .addr = 0x60, + .refclk = 16000000, +}; + +static struct isl6423_config tt1600_isl6423_config = { + .current_max = SEC_CURRENT_800m, + .curlim = SEC_CURRENT_LIM_ON, + .addr = 0x08, +}; + static void frontend_init(struct budget_ci *budget_ci) { switch (budget_ci->budget.dev->pci->subsystem_device) { @@ -1473,6 +1511,49 @@ static void frontend_init(struct budget_ci *budget_ci) } break; + case 0x101c: { /* TT S2-1600 */ + struct stv6110x_devctl *ctl; + /* TODO! must verify with Andreas */ + saa7146_setgpio(budget_ci->budget.dev, 2, SAA7146_GPIO_OUTLO); + msleep(50); + saa7146_setgpio(budget_ci->budget.dev, 2, SAA7146_GPIO_OUTHI); + msleep(250); + + budget_ci->budget.dvb_frontend = dvb_attach(stv090x_attach, + &tt1600_stv090x_config, + &budget_ci->budget.i2c_adap, + STV090x_DEMODULATOR_0); + + if (budget_ci->budget.dvb_frontend) { + + ctl = dvb_attach(stv6110x_attach, + budget_ci->budget.dvb_frontend, + &tt1600_stv6110x_config, + &budget_ci->budget.i2c_adap); + + tt1600_stv090x_config.tuner_init = ctl->tuner_init; + tt1600_stv090x_config.tuner_set_mode = ctl->tuner_set_mode; + tt1600_stv090x_config.tuner_set_frequency = ctl->tuner_set_frequency; + tt1600_stv090x_config.tuner_get_frequency = ctl->tuner_get_frequency; + tt1600_stv090x_config.tuner_set_bandwidth = ctl->tuner_set_bandwidth; + tt1600_stv090x_config.tuner_get_bandwidth = ctl->tuner_get_bandwidth; + tt1600_stv090x_config.tuner_set_bbgain = ctl->tuner_set_bbgain; + tt1600_stv090x_config.tuner_get_bbgain = ctl->tuner_get_bbgain; + tt1600_stv090x_config.tuner_set_refclk = ctl->tuner_set_refclk; + tt1600_stv090x_config.tuner_get_status = ctl->tuner_get_status; + + dvb_attach(isl6423_attach, + budget_ci->budget.dvb_frontend, + &budget_ci->budget.i2c_adap, + &tt1600_isl6423_config); + + } else { + dvb_frontend_detach(budget_ci->budget.dvb_frontend); + budget_ci->budget.dvb_frontend = NULL; + } + } + break; + } if (budget_ci->budget.dvb_frontend == NULL) { @@ -1564,6 +1645,7 @@ MAKE_BUDGET_INFO(ttbtci, "TT-Budget-T-CI PCI", BUDGET_TT); MAKE_BUDGET_INFO(ttbcci, "TT-Budget-C-CI PCI", BUDGET_TT); MAKE_BUDGET_INFO(ttc1501, "TT-Budget C-1501 PCI", BUDGET_TT); MAKE_BUDGET_INFO(tt3200, "TT-Budget S2-3200 PCI", BUDGET_TT); +MAKE_BUDGET_INFO(tt1600, "TT-Budget S2-1600 PCI", BUDGET_TT); static struct pci_device_id pci_tbl[] = { MAKE_EXTENSION_PCI(ttbci, 0x13c2, 0x100c), @@ -1574,6 +1656,7 @@ static struct pci_device_id pci_tbl[] = { MAKE_EXTENSION_PCI(ttbs2, 0x13c2, 0x1017), MAKE_EXTENSION_PCI(ttc1501, 0x13c2, 0x101a), MAKE_EXTENSION_PCI(tt3200, 0x13c2, 0x1019), + MAKE_EXTENSION_PCI(tt1600, 0x13c2, 0x101c), { .vendor = 0, } -- cgit v1.2.3 From bd6cdb0ea9b6db322a484ad00da53cdd7307fc43 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Mon, 6 Apr 2009 22:46:50 +0400 Subject: Fix incorrect default CLOCK setup From: Andreas Regel Signed-off-by: Andreas Regel Signed-off-by: MAnu Abraham --- linux/drivers/media/dvb/ttpci/budget-ci.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/ttpci/budget-ci.c b/linux/drivers/media/dvb/ttpci/budget-ci.c index bab8a041c..2e05479dc 100644 --- a/linux/drivers/media/dvb/ttpci/budget-ci.c +++ b/linux/drivers/media/dvb/ttpci/budget-ci.c @@ -1360,11 +1360,11 @@ static struct stb6100_config tt3200_stb6100_config = { static struct stv090x_config tt1600_stv090x_config = { .device = STV0903, .demod_mode = STV090x_SINGLE, - .clk_mode = STV090x_CLK_INT, + .clk_mode = STV090x_CLK_EXT, - .xtal = 8000000, + .xtal = 27000000, .address = 0x68, - .ref_clk = 16000000, + .ref_clk = 27000000, .ts1_mode = STV090x_TSMODE_DVBCI, .ts2_mode = STV090x_TSMODE_DVBCI, @@ -1383,11 +1383,11 @@ static struct stv090x_config tt1600_stv090x_config = { static struct stv6110x_config tt1600_stv6110x_config = { .addr = 0x60, - .refclk = 16000000, + .refclk = 27000000, }; static struct isl6423_config tt1600_isl6423_config = { - .current_max = SEC_CURRENT_800m, + .current_max = SEC_CURRENT_515m, .curlim = SEC_CURRENT_LIM_ON, .addr = 0x08, }; -- cgit v1.2.3 From b64197b551660377c1e6985c549258ab7b392187 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 6 Apr 2009 14:57:55 -0700 Subject: UVC: uvc_status_cleanup(): undefined reference to `input_unregister_device' From: Randy Dunlap Fix build errors when USB_VIDEO_CLASS=y and INPUT=m. Fixes kernel bugzilla #12671. Signed-off-by: Randy Dunlap Acked-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/uvc/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/uvc/Kconfig b/linux/drivers/media/video/uvc/Kconfig index c2d9760de..2956a7637 100644 --- a/linux/drivers/media/video/uvc/Kconfig +++ b/linux/drivers/media/video/uvc/Kconfig @@ -9,7 +9,7 @@ config USB_VIDEO_CLASS config USB_VIDEO_CLASS_INPUT_EVDEV bool "UVC input events device support" default y - depends on USB_VIDEO_CLASS && INPUT + depends on USB_VIDEO_CLASS=INPUT || INPUT=y ---help--- This option makes USB Video Class devices register an input device to report button events. -- cgit v1.2.3 From 40905aba779ffd9e3c84a2214d4fcaedc9baed7f Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 6 Apr 2009 14:59:31 -0700 Subject: PWC: fix build error when CONFIG_INPUT=m From: Randy Dunlap Fix build errors when USB_PWC=y and INPUT=m. Signed-off-by: Randy Dunlap Acked-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/pwc/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/pwc/Kconfig b/linux/drivers/media/video/pwc/Kconfig index 8b9f0aa84..340f954ab 100644 --- a/linux/drivers/media/video/pwc/Kconfig +++ b/linux/drivers/media/video/pwc/Kconfig @@ -39,7 +39,7 @@ config USB_PWC_DEBUG config USB_PWC_INPUT_EVDEV bool "USB Philips Cameras input events device support" default y - depends on USB_PWC && INPUT + depends on USB_PWC=INPUT || INPUT=y ---help--- This option makes USB Philips cameras register the snapshot button as an input device to report button events. -- cgit v1.2.3 From 644f5d383ba294f1f1b80c77a57ae0f3190813e3 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 6 Apr 2009 23:07:04 +0000 Subject: cx88-dsp: fixing 64bit math From: Miroslav Sustek cx88-dsp: fixing 64bit math on 32bit kernels Some gcc versions report the missing of __divdi3 Signed-off-by: Miroslav Sustek Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/cx88/cx88-dsp.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/cx88/cx88-dsp.c b/linux/drivers/media/video/cx88/cx88-dsp.c index da2b306c0..262bda9ec 100644 --- a/linux/drivers/media/video/cx88/cx88-dsp.c +++ b/linux/drivers/media/video/cx88/cx88-dsp.c @@ -100,13 +100,22 @@ static u32 int_goertzel(s16 x[], u32 N, u32 freq) s32 s_prev2 = 0; s32 coeff = 2*int_cos(freq); u32 i; + + s64 tmp; + u32 remainder; + for (i = 0; i < N; i++) { s32 s = x[i] + ((s64)coeff*s_prev/32768) - s_prev2; s_prev2 = s_prev; s_prev = s; } - return (u32)(((s64)s_prev2*s_prev2 + (s64)s_prev*s_prev - - (s64)coeff*s_prev2*s_prev/32768)/N/N); + + tmp = (s64)s_prev2*s_prev2 + (s64)s_prev*s_prev - + (s64)coeff*s_prev2*s_prev/32768; + + /* XXX: N must be low enough so that N*N fits in s32. + * Else we need two divisions. */ + return (u32) div_s64_rem(tmp, N*N, &remainder); } static u32 freq_magnitude(s16 x[], u32 N, u32 freq) -- cgit v1.2.3 From 028d9a0c9dfc2039314063233c47fef4905d9071 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Tue, 7 Apr 2009 12:19:54 +0400 Subject: * Reference clock was unused * Fix missing repeater level setup From: Manu Abraham Signed-off-by: Manu Abraham --- linux/drivers/media/dvb/frontends/stv090x.c | 9 +++++++-- linux/drivers/media/dvb/frontends/stv090x.h | 13 +++++++++++++ linux/drivers/media/dvb/frontends/stv6110x_priv.h | 6 ++---- linux/drivers/media/dvb/ttpci/budget-ci.c | 2 ++ 4 files changed, 24 insertions(+), 6 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/frontends/stv090x.c b/linux/drivers/media/dvb/frontends/stv090x.c index fc0781961..7d6cb0600 100644 --- a/linux/drivers/media/dvb/frontends/stv090x.c +++ b/linux/drivers/media/dvb/frontends/stv090x.c @@ -1484,16 +1484,19 @@ static int stv090x_write_reg(struct stv090x_state *state, unsigned int reg, u8 d static int stv090x_i2c_gate_ctrl(struct dvb_frontend *fe, int enable) { struct stv090x_state *state = fe->demodulator_priv; + const struct stv090x_config *config = state->config; u32 reg; reg = STV090x_READ_DEMOD(state, I2CRPT); - +// STV090x_SETFIELD_Px(reg, ENARPT_LEVEL_FIELD, config->repeater_level); if (enable) { + dprintk(FE_DEBUG, 1, "Enable Gate"); STV090x_SETFIELD_Px(reg, I2CT_ON_FIELD, 1); if (STV090x_WRITE_DEMOD(state, I2CRPT, reg) < 0) goto err; } else { + dprintk(FE_DEBUG, 1, "Disable Gate"); STV090x_SETFIELD_Px(reg, I2CT_ON_FIELD, 0); if ((STV090x_WRITE_DEMOD(state, I2CRPT, reg)) < 0) goto err; @@ -4629,6 +4632,7 @@ static int stv090x_setup(struct dvb_frontend *fe) const struct stv090x_reg *stv090x_initval = NULL; const struct stv090x_reg *stv090x_cut20_val = NULL; unsigned long t1_size = 0, t2_size = 0; + u32 reg = 0; int i; @@ -4668,7 +4672,8 @@ static int stv090x_setup(struct dvb_frontend *fe) if (STV090x_WRITE_DEMOD(state, TNRCFG, 0x6c) < 0) /* check register ! (No Tuner Mode) */ goto err; - if (STV090x_WRITE_DEMOD(state, I2CRPT, 0x00) < 0) /* repeater OFF */ + STV090x_SETFIELD_Px(reg, ENARPT_LEVEL_FIELD, config->repeater_level); + if (STV090x_WRITE_DEMOD(state, I2CRPT, reg) < 0) /* repeater OFF */ goto err; if (stv090x_write_reg(state, STV090x_NCOARSE, 0x13) < 0) /* set PLL divider */ diff --git a/linux/drivers/media/dvb/frontends/stv090x.h b/linux/drivers/media/dvb/frontends/stv090x.h index d1cc36985..b75a66baf 100644 --- a/linux/drivers/media/dvb/frontends/stv090x.h +++ b/linux/drivers/media/dvb/frontends/stv090x.h @@ -49,6 +49,17 @@ enum stv090x_clkmode { STV090x_CLK_EXT = 2 /* Clk i/p = XTALI */ }; +enum stv090x_i2crpt { + STV090x_RPTLEVEL_256 = 0, + STV090x_RPTLEVEL_128 = 1, + STV090x_RPTLEVEL_64 = 2, + STV090x_RPTLEVEL_32 = 3, + STV090x_RPTLEVEL_16 = 4, + STV090x_RPTLEVEL_8 = 5, + STV090x_RPTLEVEL_4 = 6, + STV090x_RPTLEVEL_2 = 7, +}; + struct stv090x_config { enum stv090x_device device; enum stv090x_mode demod_mode; @@ -61,6 +72,8 @@ struct stv090x_config { u8 ts1_mode; u8 ts2_mode; + + enum stv090x_i2crpt repeater_level; #if 0 int (*tuner_init) (struct dvb_frontend *fe); int (*tuner_set_frequency) (struct dvb_frontend *fe, u32 frequency); diff --git a/linux/drivers/media/dvb/frontends/stv6110x_priv.h b/linux/drivers/media/dvb/frontends/stv6110x_priv.h index 1295272fc..7260da633 100644 --- a/linux/drivers/media/dvb/frontends/stv6110x_priv.h +++ b/linux/drivers/media/dvb/frontends/stv6110x_priv.h @@ -62,16 +62,14 @@ #define TRIALS 10 #define R_DIV(__div) (1 << (__div + 1)) -#define REFCLOCK_kHz (stv6110x->reference / 1000) -#define REFCLOCK_MHz (stv6110x->reference / 1000000) +#define REFCLOCK_kHz (stv6110x->config->refclk / 1000) +#define REFCLOCK_MHz (stv6110x->config->refclk / 1000000) struct stv6110x_state { struct i2c_adapter *i2c; const struct stv6110x_config *config; struct stv6110x_devctl *devctl; - - u32 reference; }; #endif /* __STV6110x_PRIV_H */ diff --git a/linux/drivers/media/dvb/ttpci/budget-ci.c b/linux/drivers/media/dvb/ttpci/budget-ci.c index 2e05479dc..74ae43592 100644 --- a/linux/drivers/media/dvb/ttpci/budget-ci.c +++ b/linux/drivers/media/dvb/ttpci/budget-ci.c @@ -1369,6 +1369,8 @@ static struct stv090x_config tt1600_stv090x_config = { .ts1_mode = STV090x_TSMODE_DVBCI, .ts2_mode = STV090x_TSMODE_DVBCI, + .repeater_level = STV090x_RPTLEVEL_16, + .tuner_init = NULL, .tuner_set_mode = NULL, .tuner_set_frequency = NULL, -- cgit v1.2.3 From c3f5b411bcdd2ddc8633e2586be30fb34526ae04 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Tue, 21 Apr 2009 09:17:59 +0200 Subject: gspca - main: Version change. From: Jean-Francois Moine Priority: normal Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/gspca.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/gspca.c b/linux/drivers/media/video/gspca/gspca.c index b12974d5e..c018f162a 100644 --- a/linux/drivers/media/video/gspca/gspca.c +++ b/linux/drivers/media/video/gspca/gspca.c @@ -1,7 +1,7 @@ /* * Main USB camera driver * - * V4L2 by Jean-Francois Moine + * Copyright (C) 2008-2009 Jean-Francois Moine (http://moinejf.free.fr) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -51,7 +51,7 @@ MODULE_AUTHOR("Jean-Francois Moine "); MODULE_DESCRIPTION("GSPCA USB Camera Driver"); MODULE_LICENSE("GPL"); -#define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 5, 0) +#define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 6, 0) #ifdef GSPCA_DEBUG int gspca_debug = D_ERR | D_PROBE; -- cgit v1.2.3 From 33e07d82c88624e750f132b924afa1a891e5069a Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Tue, 7 Apr 2009 10:30:31 +0200 Subject: gspca - zc3xx: Bad debug level in i2c_read. From: Jean-Francois Moine Priority: normal Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/zc3xx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/zc3xx.c b/linux/drivers/media/video/gspca/zc3xx.c index 18a7ca2b6..2855ebf90 100644 --- a/linux/drivers/media/video/gspca/zc3xx.c +++ b/linux/drivers/media/video/gspca/zc3xx.c @@ -6336,7 +6336,7 @@ static __u16 i2c_read(struct gspca_dev *gspca_dev, retbyte = reg_r_i(gspca_dev, 0x0091); /* read status */ retval = reg_r_i(gspca_dev, 0x0095); /* read Lowbyte */ retval |= reg_r_i(gspca_dev, 0x0096) << 8; /* read Hightbyte */ - PDEBUG(D_USBO, "i2c r [%02x] -> %04x (%02x)", + PDEBUG(D_USBI, "i2c r [%02x] -> %04x (%02x)", reg, retval, retbyte); return retval; } -- cgit v1.2.3 From 3bf2471fdfa0240ad65a9212340e146abf623235 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 7 Apr 2009 15:55:17 +0000 Subject: tda7432: Delete old driver history From: Jean Delvare The history of changes does belong to git. In general I wouldn't care too much but it happens that this specific comment triggers a false positive in one of my scripts, so I'd rather get rid of it. Signed-off-by: Jean Delvare Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/tda7432.c | 14 -------------- 1 file changed, 14 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/tda7432.c b/linux/drivers/media/video/tda7432.c index 749539cb8..a1416084b 100644 --- a/linux/drivers/media/video/tda7432.c +++ b/linux/drivers/media/video/tda7432.c @@ -20,20 +20,6 @@ * loudness - set between 0 and 15 for varying degrees of loudness effect * * maxvol - set maximium volume to +20db (1), default is 0db(0) - * - * - * Revision: 0.7 - maxvol module parm to set maximium volume 0db or +20db - * store if muted so we can return it - * change balance only if flaged to - * Revision: 0.6 - added tone controls - * Revision: 0.5 - Fixed odd balance problem - * Revision: 0.4 - added muting - * Revision: 0.3 - Fixed silly reversed volume controls. :) - * Revision: 0.2 - Cleaned up #defines - * fixed volume control - * Added I2C_DRIVERID_TDA7432 - * added loudness insmod control - * Revision: 0.1 - initial version */ #include -- cgit v1.2.3 From f9a56ea326e7bf2efc796a2a7bbbc376a332fa25 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Tue, 7 Apr 2009 23:08:26 +0400 Subject: Fix Undocumented Registers From: Manu Abraham Signed-off-by: Manu Abraham --- linux/drivers/media/dvb/frontends/stv090x.c | 71 +++---------------------- linux/drivers/media/dvb/frontends/stv090x_reg.h | 69 +++++++++++++++--------- 2 files changed, 52 insertions(+), 88 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/frontends/stv090x.c b/linux/drivers/media/dvb/frontends/stv090x.c index 7d6cb0600..7267e21a4 100644 --- a/linux/drivers/media/dvb/frontends/stv090x.c +++ b/linux/drivers/media/dvb/frontends/stv090x.c @@ -179,9 +179,7 @@ static struct stv090x_reg stv090x_defval[] = { { STV090x_DACR1, 0x00 }, /* DACR1 */ { STV090x_DACR2, 0x00 }, /* DACR2 */ { STV090x_OUTCFG, 0x00 }, /* OUTCFG */ -#if 0 { STV090x_MODECFG, 0xff }, /* MODECFG */ -#endif { STV090x_IRQSTATUS3, 0x00 }, /* IRQSTATUS3 */ { STV090x_IRQSTATUS2, 0x00 }, /* IRQSTATUS2 */ { STV090x_IRQSTATUS1, 0x00 }, /* IRQSTATUS1 */ @@ -314,24 +312,18 @@ static struct stv090x_reg stv090x_defval[] = { { STV090x_P2_DMDCFGMD, 0xf9 }, /* P2_DMDCFGMD */ { STV090x_P2_DMDCFG2, 0x3b }, /* P2_DMDCFG2 */ { STV090x_P2_DMDISTATE, 0x5c }, /* P2_DMDISTATE */ -#if 0 - { STV090x_P2_DMDT0M, 0x20 }, /* P2_DMDT0M */ -#endif + { STV090x_P2_DMDTOM, 0x20 }, /* P2_DMDT0M */ { STV090x_P2_DMDSTATE, 0x1c }, /* P2_DMDSTATE */ { STV090x_P2_DMDFLYW, 0x00 }, /* P2_DMDFLYW */ { STV090x_P2_DSTATUS3, 0x00 }, /* P2_DSTATUS3 */ { STV090x_P2_DMDCFG3, 0x68 }, /* P2_DMDCFG3 */ -#if 0 { STV090x_P2_DMDCFG4, 0x10 }, /* P2_DMDCFG4 */ -#endif { STV090x_P2_CORRELMANT, 0x70 }, /* P2_CORRELMANT */ { STV090x_P2_CORRELABS, 0x88 }, /* P2_CORRELABS */ { STV090x_P2_CORRELEXP, 0xaa }, /* P2_CORRELEXP */ { STV090x_P2_PLHMODCOD, 0x42 }, /* P2_PLHMODCOD */ -#if 0 { STV090x_P2_AGCK32, 0x00 }, /* P2_AGCK32 */ { STV090x_P2_AGC2O, 0x5b }, /* P2_AGC2O */ -#endif { STV090x_P2_AGC2REF, 0x38 }, /* P2_AGC2REF */ { STV090x_P2_AGC1ADJ, 0x58 }, /* P2_AGC1ADJ */ { STV090x_P2_AGC2I1, 0x00 }, /* P2_AGC2I1 */ @@ -591,24 +583,18 @@ static struct stv090x_reg stv090x_defval[] = { { STV090x_P1_DMDCFGMD, 0xf9 }, /* P1_DMDCFGMD */ { STV090x_P1_DMDCFG2, 0x3b }, /* P1_DMDCFG2 */ { STV090x_P1_DMDISTATE, 0x5c }, /* P1_DMDISTATE */ -#if 0 - { STV090x_P1_DMDT0M, 0x20 }, /* P1_DMDT0M */ -#endif + { STV090x_P1_DMDTOM, 0x20 }, /* P1_DMDT0M */ { STV090x_P1_DMDSTATE, 0x1c }, /* P1_DMDSTATE */ { STV090x_P1_DMDFLYW, 0x00 }, /* P1_DMDFLYW */ { STV090x_P1_DSTATUS3, 0x00 }, /* P1_DSTATUS3 */ { STV090x_P1_DMDCFG3, 0x68 }, /* P1_DMDCFG3 */ -#if 0 { STV090x_P1_DMDCFG4, 0x10 }, /* P1_DMDCFG4 */ -#endif { STV090x_P1_CORRELMANT, 0x70 }, /* P1_CORRELMANT */ { STV090x_P1_CORRELABS, 0x88 }, /* P1_CORRELABS */ { STV090x_P1_CORRELEXP, 0xaa }, /* P1_CORRELEXP */ { STV090x_P1_PLHMODCOD, 0x42 }, /* P1_PLHMODCOD */ -#if 0 { STV090x_P1_AGCK32, 0x00 }, /* P1_AGCK32 */ { STV090x_P1_AGC2O, 0x5b }, /* P1_AGC2O */ -#endif { STV090x_P1_AGC2REF, 0x38 }, /* P1_AGC2REF */ { STV090x_P1_AGC1ADJ, 0x58 }, /* P1_AGC1ADJ */ { STV090x_P1_AGC2I1, 0x00 }, /* P1_AGC2I1 */ @@ -848,13 +834,9 @@ static struct stv090x_reg stv090x_defval[] = { { STV090x_P1_FBERERR1, 0x00 }, /* P1_FBERERR1 */ { STV090x_P1_FBERERR0, 0x00 }, /* P1_FBERERR0 */ { STV090x_P1_FSPYBER, 0x10 }, /* P1_FSPYBER */ -#if 0 { STV090x_RCCFGH, 0x20 }, /* RCCFGH */ -#endif { STV090x_TSGENERAL, 0x14 }, /* TSGENERAL */ -#if 0 { STV090x_TSGENERAL1X, 0x00 }, /* TSGENERAL1X */ -#endif { STV090x_NBITER_NF4, 0x37 }, /* NBITER_NF4 */ { STV090x_AGCRF2CFG, 0x13 }, @@ -887,9 +869,7 @@ static struct stv090x_reg stv090x_defval[] = { { STV090x_GAINLLR_NF15, 0x20 }, /* GAINLLR_NF15 */ { STV090x_GAINLLR_NF16, 0x20 }, /* GAINLLR_NF16 */ { STV090x_GAINLLR_NF17, 0x21 }, /* GAINLLR_NF17 */ -#if 0 { STV090x_CFGEXT, 0x01 }, /* CFGEXT */ -#endif { STV090x_GENCFG, 0x1d }, /* GENCFG */ { STV090x_P2_AGC2REF, 0x38 }, { STV090x_LDPCERR1, 0x00 }, /* LDPCERR1 */ @@ -904,14 +884,10 @@ static struct stv090x_reg stv090x_defval[] = { static struct stv090x_reg stv0900_initval[] = { { STV090x_OUTCFG, 0x00 }, -#if 0 { STV090x_MODECFG, 0xff }, -#endif { STV090x_AGCRF1CFG, 0x11 }, { STV090x_AGCRF2CFG, 0x13 }, -#if 0 { STV090x_TSGENERAL1X, 0x14 }, -#endif { STV090x_TSTTNR2, 0x21 }, { STV090x_TSTTNR4, 0x21 }, { STV090x_P2_DISTXCTL, 0x22 }, @@ -945,14 +921,10 @@ static struct stv090x_reg stv0900_initval[] = { { STV090x_P2_ERRCTRL2, 0xc1 }, { STV090x_P2_CFRICFG, 0xf8 }, { STV090x_P2_NOSCFG, 0x1c }, -#if 0 - { STV090x_P2_DMDT0M, 0x20 }, -#endif + { STV090x_P2_DMDTOM, 0x20 }, { STV090x_P2_CORRELMANT, 0x70 }, { STV090x_P2_CORRELABS, 0x88 }, -#if 0 { STV090x_P2_AGC2O, 0x5b }, -#endif { STV090x_P2_AGC2REF, 0x38 }, { STV090x_P2_CARCFG, 0xe4 }, { STV090x_P2_ACLC, 0x1A }, @@ -998,9 +970,7 @@ static struct stv090x_reg stv0900_initval[] = { { STV090x_P1_DMDCFGMD, 0xf9 }, { STV090x_P1_DEMOD, 0x08 }, { STV090x_P1_DMDCFG3, 0xc4 }, -#if 0 - { STV090x_P1_DMDT0M, 0x20 }, -#endif + { STV090x_P1_DMDTOM, 0x20 }, { STV090x_P1_CARFREQ, 0xed }, #if 0 { STV090x_P1_TNRCFG2, 0x82 }, @@ -1024,9 +994,7 @@ static struct stv090x_reg stv0900_initval[] = { { STV090x_P1_NOSCFG, 0x1c }, { STV090x_P1_CORRELMANT, 0x70 }, { STV090x_P1_CORRELABS, 0x88 }, -#if 0 { STV090x_P1_AGC2O, 0x5b }, -#endif { STV090x_P1_AGC2REF, 0x38 }, { STV090x_P1_CARCFG, 0xe4 }, { STV090x_P1_ACLC, 0x1A }, @@ -1088,9 +1056,7 @@ static struct stv090x_reg stv0900_initval[] = { { STV090x_GAINLLR_NF15, 0x1A }, { STV090x_GAINLLR_NF16, 0x1F }, { STV090x_GAINLLR_NF17, 0x21 }, -#if 0 { STV090x_RCCFGH, 0x20 }, -#endif { STV090x_P1_FECM, 0x01 }, /* disable DSS modes */ { STV090x_P2_FECM, 0x01 }, /* disable DSS modes */ { STV090x_P1_PRVIT, 0x2F }, /* disable PR 6/7 */ @@ -1136,18 +1102,14 @@ static struct stv090x_reg stv0903_initval[] = { { STV090x_P1_ERRCTRL2, 0xc1 }, { STV090x_P1_CFRICFG, 0xf8 }, { STV090x_P1_NOSCFG, 0x1c }, -#if 0 - { STV090x_P1_DMDT0M, 0x20 }, -#endif + { STV090x_P1_DMDTOM, 0x20 }, { STV090x_P1_CORRELMANT, 0x70 }, { STV090x_P1_CORRELABS, 0x88 }, -#if 0 { STV090x_P1_AGC2O, 0x5b }, -#endif - { STV090x_P1_AGC2REF, 0x38 } , + { STV090x_P1_AGC2REF, 0x38 }, { STV090x_P1_CARCFG, 0xe4 }, { STV090x_P1_ACLC, 0x1A }, - { STV090x_P1_BCLC, 0x09 } , + { STV090x_P1_BCLC, 0x09 }, { STV090x_P1_CARHDR, 0x08 }, { STV090x_P1_KREFTMG, 0xc1 }, { STV090x_P1_SFRSTEP, 0x58 }, @@ -1205,9 +1167,7 @@ static struct stv090x_reg stv0903_initval[] = { { STV090x_GAINLLR_NF15, 0x1A }, { STV090x_GAINLLR_NF16, 0x1F }, { STV090x_GAINLLR_NF17, 0x21 }, -#if 0 { STV090x_RCCFGH, 0x20 }, -#endif { STV090x_P1_FECM, 0x01 }, /*disable the DSS mode */ { STV090x_P1_PRVIT, 0x2f } /*disable puncture rate 6/7*/ }; @@ -1215,9 +1175,7 @@ static struct stv090x_reg stv0903_initval[] = { static struct stv090x_reg stv0900_cut20_val[] = { { STV090x_P2_DMDCFG3, 0xe8 }, -#if 0 { STV090x_P2_DMDCFG4, 0x10 }, -#endif { STV090x_P2_CARFREQ, 0x38 }, { STV090x_P2_CARHDR, 0x20 }, { STV090x_P2_KREFTMG, 0x5a }, @@ -1226,9 +1184,7 @@ static struct stv090x_reg stv0900_cut20_val[] = { { STV090x_P2_SMAPCOEF5, 0x04 }, { STV090x_P2_NOSCFG, 0x0c }, { STV090x_P1_DMDCFG3, 0xe8 }, -#if 0 { STV090x_P1_DMDCFG4, 0x10 }, -#endif { STV090x_P1_CARFREQ, 0x38 }, { STV090x_P1_CARHDR, 0x20 }, { STV090x_P1_KREFTMG, 0x5a }, @@ -1254,9 +1210,7 @@ static struct stv090x_reg stv0900_cut20_val[] = { static struct stv090x_reg stv0903_cut20_val[] = { { STV090x_P1_DMDCFG3, 0xe8 }, -#if 0 { STV090x_P1_DMDCFG4, 0x10 }, -#endif { STV090x_P1_CARFREQ, 0x38 }, { STV090x_P1_CARHDR, 0x20 }, { STV090x_P1_KREFTMG, 0x5a }, @@ -1484,11 +1438,9 @@ static int stv090x_write_reg(struct stv090x_state *state, unsigned int reg, u8 d static int stv090x_i2c_gate_ctrl(struct dvb_frontend *fe, int enable) { struct stv090x_state *state = fe->demodulator_priv; - const struct stv090x_config *config = state->config; u32 reg; reg = STV090x_READ_DEMOD(state, I2CRPT); -// STV090x_SETFIELD_Px(reg, ENARPT_LEVEL_FIELD, config->repeater_level); if (enable) { dprintk(FE_DEBUG, 1, "Enable Gate"); STV090x_SETFIELD_Px(reg, I2CT_ON_FIELD, 1); @@ -4449,16 +4401,12 @@ static int stv090x_set_tspath(struct stv090x_state *state) case STV090x_TSMODE_SERIAL_PUNCTURED: case STV090x_TSMODE_SERIAL_CONTINUOUS: default: -#if 0 stv090x_write_reg(state, STV090x_TSGENERAL1X, 0x10); -#endif break; case STV090x_TSMODE_PARALLEL_PUNCTURED: case STV090x_TSMODE_DVBCI: -#if 0 stv090x_write_reg(state, STV090x_TSGENERAL1X, 0x16); -#endif reg = stv090x_read_reg(state, STV090x_P1_TSCFGM); STV090x_SETFIELD_Px(reg, TSFIFO_MANSPEED_FIELD, 3); if (stv090x_write_reg(state, STV090x_P1_TSCFGM, reg) < 0) @@ -4482,16 +4430,12 @@ static int stv090x_set_tspath(struct stv090x_state *state) case STV090x_TSMODE_SERIAL_PUNCTURED: case STV090x_TSMODE_SERIAL_CONTINUOUS: default: -#if 0 stv090x_write_reg(state, STV090x_TSGENERAL1X, 0x14); -#endif break; case STV090x_TSMODE_PARALLEL_PUNCTURED: case STV090x_TSMODE_DVBCI: -#if 0 stv090x_write_reg(state, STV090x_TSGENERAL1X, 0x12); -#endif break; } break; @@ -4762,6 +4706,7 @@ struct dvb_frontend *stv090x_attach(const struct stv090x_config *config, state->i2c = i2c; state->frontend.ops = stv090x_ops; state->frontend.demodulator_priv = state; + state->demod = demod; state->demod_mode = config->demod_mode; /* Single or Dual mode */ state->device = config->device; state->rolloff = 35; /* default */ diff --git a/linux/drivers/media/dvb/frontends/stv090x_reg.h b/linux/drivers/media/dvb/frontends/stv090x_reg.h index b59eca953..0dff56d4e 100644 --- a/linux/drivers/media/dvb/frontends/stv090x_reg.h +++ b/linux/drivers/media/dvb/frontends/stv090x_reg.h @@ -48,6 +48,8 @@ #define STV090x_OFFST_OUTPARRS3_HZ_FIELD 3 #define STV090x_WIDTH_OUTPARRS3_HZ_FIELD 1 +#define STV090x_MODECFG 0xf11d + #define STV090x_IRQSTATUS3 0xf120 #define STV090x_OFFST_SPLL_LOCK_FIELD 5 #define STV090x_WIDTH_SPLL_LOCK_FIELD 1 @@ -312,9 +314,9 @@ #define STV090x_OFFST_ERRORx_XOR_FIELD 0 #define STV090x_WIDTH_ERRORx_XOR_FIELD 1 -#define STV090x_DPNxCFG(__x) (0xf15c + (__x - 1) * 0x5) +#define STV090x_DPNxCFG(__x) (0xf15c + (__x - 1) * 0x5) #define STV090x_DPN1CFG STV090x_DPNxCFG(1) -#define STV090x_DPN2CFG STV090x_DPNxCFG(2) +#define STV090x_DPN2CFG STV090x_DPNxCFG(2) #define STV090x_DPN3CFG STV090x_DPNxCFG(3) #define STV090x_OFFST_DPNx_OPD_FIELD 7 #define STV090x_WIDTH_DPNx_OPD_FIELD 1 @@ -571,8 +573,8 @@ #define STV090x_WIDTH_FSKR_CARLOSS_THRESH_FIELD 8 #define STV090x_Px_DISTXCTL(__x) (0xF1A0 - (__x - 1) * 0x10) -#define STV090x_P1_DISTXCTL (1) -#define STV090x_P2_DISTXCTL (2) +#define STV090x_P1_DISTXCTL STV090x_Px_DISTXCTL(1) +#define STV090x_P2_DISTXCTL STV090x_Px_DISTXCTL(2) #define STV090x_OFFST_Px_TIM_OFF_FIELD 7 #define STV090x_WIDTH_Px_TIM_OFF_FIELD 1 #define STV090x_OFFST_Px_DISEQC_RESET_FIELD 6 @@ -585,8 +587,8 @@ #define STV090x_WIDTH_Px_DISTX_MODE_FIELD 3 #define STV090x_Px_DISRXCTL(__x) (0xf1a1 - (__x - 1) * 0x10) -#define STV090x_P1_DISRXCTL (1) -#define STV090x_P2_DISRXCTL (2) +#define STV090x_P1_DISRXCTL STV090x_Px_DISRXCTL(1) +#define STV090x_P2_DISRXCTL STV090x_Px_DISRXCTL(2) #define STV090x_OFFST_Px_RECEIVER_ON_FIELD 7 #define STV090x_WIDTH_Px_RECEIVER_ON_FIELD 1 #define STV090x_OFFST_Px_IGNO_SHORT22K_FIELD 6 @@ -603,8 +605,8 @@ #define STV090x_WIDTH_Px_IRQ_4NBYTES_FIELD 1 #define STV090x_Px_DISRX_ST0(__x) (0xf1a4 - (__x - 1) * 0x10) -#define STV090x_P1_DISRX_ST0 (1) -#define STV090x_P2_DISRX_ST0 (2) +#define STV090x_P1_DISRX_ST0 STV090x_Px_DISRX_ST0(1) +#define STV090x_P2_DISRX_ST0 STV090x_Px_DISRX_ST0(2) #define STV090x_OFFST_Px_RX_END_FIELD 7 #define STV090x_WIDTH_Px_RX_END_FIELD 1 #define STV090x_OFFST_Px_RX_ACTIVE_FIELD 6 @@ -621,8 +623,8 @@ #define STV090x_WIDTH_Px_ABORT_DISRX_FIELD 1 #define STV090x_Px_DISRX_ST1(__x) (0xf1a5 - (__x - 1) * 0x10) -#define STV090x_P1_DISRX_ST1 (1) -#define STV090x_P2_DISRX_ST1 (2) +#define STV090x_P1_DISRX_ST1 STV090x_Px_DISRX_ST1(1) +#define STV090x_P2_DISRX_ST1 STV090x_Px_DISRX_ST1(2) #define STV090x_OFFST_Px_RX_FAIL_FIELD 7 #define STV090x_WIDTH_Px_RX_FAIL_FIELD 1 #define STV090x_OFFST_Px_FIFO_PARITYFAIL_FIELD 6 @@ -635,20 +637,20 @@ #define STV090x_WIDTH_Px_FIFO_BYTENBR_FIELD 4 #define STV090x_Px_DISRXDATA(__x) (0xf1a6 - (__x - 1) * 0x10) -#define STV090x_P1_DISRXDATA (1) -#define STV090x_P2_DISRXDATA (2) +#define STV090x_P1_DISRXDATA STV090x_Px_DISRXDATA(1) +#define STV090x_P2_DISRXDATA STV090x_Px_DISRXDATA(2) #define STV090x_OFFST_Px_DISRX_DATA_FIELD 0 #define STV090x_WIDTH_Px_DISRX_DATA_FIELD 8 #define STV090x_Px_DISTXDATA(__x) (0xf1a7 - (__x - 1) * 0x10) -#define STV090x_P1_DISTXDATA (1) -#define STV090x_P2_DISTXDATA (2) +#define STV090x_P1_DISTXDATA STV090x_Px_DISTXDATA(1) +#define STV090x_P2_DISTXDATA STV090x_Px_DISTXDATA(2) #define STV090x_OFFST_Px_DISEQC_FIFO_FIELD 0 #define STV090x_WIDTH_Px_DISEQC_FIFO_FIELD 8 #define STV090x_Px_DISTXSTATUS(__x) (0xf1a8 - (__x - 1) * 0x10) -#define STV090x_P1_DISTXSTATUS (1) -#define STV090x_P2_DISTXSTATUS (2) +#define STV090x_P1_DISTXSTATUS STV090x_Px_DISTXSTATUS(1) +#define STV090x_P2_DISTXSTATUS STV090x_Px_DISTXSTATUS(2) #define STV090x_OFFST_Px_TX_FAIL_FIELD 7 #define STV090x_WIDTH_Px_TX_FAIL_FIELD 1 #define STV090x_OFFST_Px_FIFO_FULL_FIELD 6 @@ -661,26 +663,26 @@ #define STV090x_WIDTH_Px_TXFIFO_BYTES_FIELD 4 #define STV090x_Px_F22TX(__x) (0xf1a9 - (__x - 1) * 0x10) -#define STV090x_P1_F22TX (1) -#define STV090x_P2_F22TX (2) +#define STV090x_P1_F22TX STV090x_Px_F22TX(1) +#define STV090x_P2_F22TX STV090x_Px_F22TX(2) #define STV090x_OFFST_Px_F22_REG_FIELD 0 #define STV090x_WIDTH_Px_F22_REG_FIELD 8 #define STV090x_Px_F22RX(__x) (0xf1aa - (__x - 1) * 0x10) -#define STV090x_P1_F22RX (1) -#define STV090x_P2_F22RX (2) +#define STV090x_P1_F22RX STV090x_Px_F22RX(1) +#define STV090x_P2_F22RX STV090x_Px_F22RX(2) #define STV090x_OFFST_Px_F22RX_REG_FIELD 0 #define STV090x_WIDTH_Px_F22RX_REG_FIELD 8 #define STV090x_Px_ACRPRESC(__x) (0xf1ac - (__x - 1) * 0x10) -#define STV090x_P1_ACRPRESC (1) -#define STV090x_P2_ACRPRESC (2) +#define STV090x_P1_ACRPRESC STV090x_Px_ACRPRESC(1) +#define STV090x_P2_ACRPRESC STV090x_Px_ACRPRESC(2) #define STV090x_OFFST_Px_ACR_PRESC_FIELD 0 #define STV090x_WIDTH_Px_ACR_PRESC_FIELD 3 #define STV090x_Px_ACRDIV(__x) (0xf1ad - (__x - 1) * 0x10) -#define STV090x_P1_ACRDIV (1) -#define STV090x_P2_ACRDIV (2) +#define STV090x_P1_ACRDIV STV090x_Px_ACRDIV(1) +#define STV090x_P2_ACRDIV STV090x_Px_ACRDIV(2) #define STV090x_OFFST_Px_ACR_DIV_FIELD 0 #define STV090x_WIDTH_Px_ACR_DIV_FIELD 8 @@ -892,6 +894,10 @@ #define STV090x_OFFST_Px_NOSTOP_FIFOFULL_FIELD 3 #define STV090x_WIDTH_Px_NOSTOP_FIFOFULL_FIELD 1 +#define STV090x_Px_DMDCFG4(__x) (0xf41f - (__x - 1) * 0x200) +#define STV090x_P1_DMDCFG4 STV090x_Px_DMDCFG4(1) +#define STV090x_P2_DMDCFG4 STV090x_Px_DMDCFG4(2) + #define STV090x_Px_CORRELMANT(__x) (0xF420 - (__x - 1) * 0x200) #define STV090x_P1_CORRELMANT STV090x_Px_CORRELMANT(1) #define STV090x_P2_CORRELMANT STV090x_Px_CORRELMANT(2) @@ -922,6 +928,14 @@ #define STV090x_OFFST_Px_PLH_TYPE_FIELD 0 #define STV090x_WIDTH_Px_PLH_TYPE_FIELD 2 +#define STV090x_Px_AGCK32(__x) (0xf42b - (__x - 1) * 0x200) +#define STV090x_P1_AGCK32 STV090x_Px_AGCK32(1) +#define STV090x_P2_AGCK32 STV090x_Px_AGCK32(2) + +#define STV090x_Px_AGC2O(__x) (0xF42C - (__x - 1) * 0x200) +#define STV090x_P1_AGC2O STV090x_Px_AGC2O(1) +#define STV090x_P2_AGC2O STV090x_Px_AGC2O(2) + #define STV090x_Px_AGC2REF(__x) (0xF42D - (__x - 1) * 0x200) #define STV090x_P1_AGC2REF STV090x_Px_AGC2REF(1) #define STV090x_P2_AGC2REF STV090x_Px_AGC2REF(2) @@ -1640,7 +1654,7 @@ #define STV090x_OFFST_Px_SMAPCOEF_8P_LLR23_FIELD 0 #define STV090x_WIDTH_Px_SMAPCOEF_8P_LLR23_FIELD 7 -#define STV090x_Px_DMDPLHSTAT(__x) (0xF520 - (__x - 1) * 0x200) +#define STV090x_Px_DMDPLHSTAT(__x) (0xF520 - (__x - 1) * 0x200) #define STV090x_P1_DMDPLHSTAT STV090x_Px_DMDPLHSTAT(1) #define STV090x_P2_DMDPLHSTAT STV090x_Px_DMDPLHSTAT(2) #define STV090x_OFFST_Px_PLH_STATISTIC_FIELD 0 @@ -2281,12 +2295,17 @@ #define STV090x_OFFST_Px_FSPYBER_CTIME_FIELD 0 #define STV090x_WIDTH_Px_FSPYBER_CTIME_FIELD 3 +#define STV090x_RCCFGH 0xf600 + #define STV090x_TSGENERAL 0xF630 #define STV090x_OFFST_Px_MUXSTREAM_OUT_FIELD 3 #define STV090x_WIDTH_Px_MUXSTREAM_OUT_FIELD 1 #define STV090x_OFFST_Px_TSFIFO_PERMPARAL_FIELD 1 #define STV090x_WIDTH_Px_TSFIFO_PERMPARAL_FIELD 2 +#define STV090x_TSGENERAL1X 0xf670 +#define STV090x_CFGEXT 0xfa80 + #define STV090x_TSTRES0 0xFF11 #define STV090x_OFFST_FRESFEC_FIELD 7 #define STV090x_WIDTH_FRESFEC_FIELD 1 -- cgit v1.2.3 From ea62326fb834d265d25c6d2bf8b9335e601969ed Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Tue, 7 Apr 2009 23:09:52 +0400 Subject: Various ISL64231 fixes Use external modulation From: Andreas Regel Signed-off-by: Andreas Regel Signed-off-by: Manu Abraham --- linux/drivers/media/dvb/frontends/isl6423.c | 35 ++++++++++++++++++++--------- linux/drivers/media/dvb/ttpci/budget-ci.c | 1 + 2 files changed, 26 insertions(+), 10 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/frontends/isl6423.c b/linux/drivers/media/dvb/frontends/isl6423.c index c1943dcb8..dca5bebfe 100644 --- a/linux/drivers/media/dvb/frontends/isl6423.c +++ b/linux/drivers/media/dvb/frontends/isl6423.c @@ -73,6 +73,7 @@ static int isl6423_write(struct isl6423_dev *isl6423, u8 reg) struct i2c_msg msg = { .addr = addr, .flags = 0, .buf = ®, .len = 1 }; + dprintk(FE_DEBUG, 1, "write reg %02X", reg); err = i2c_transfer(i2c, &msg, 1); if (err < 0) goto exit; @@ -133,6 +134,9 @@ static int isl6423_voltage_boost(struct dvb_frontend *fe, long arg) if (err < 0) goto exit; + isl6423->reg_3 = reg_3; + isl6423->reg_4 = reg_4; + return 0; exit: dprintk(FE_ERROR, 1, "I/O error <%d>", err); @@ -144,12 +148,10 @@ static int isl6423_set_voltage(struct dvb_frontend *fe, enum fe_sec_voltage voltage) { struct isl6423_dev *isl6423 = (struct isl6423_dev *) fe->sec_priv; + u8 reg_3 = isl6423->reg_3; u8 reg_4 = isl6423->reg_4; int err = 0; - /* SR4H = 0, SR4M = 1, SR4L = 1 */ - reg_4 = 0x03 << 5; - switch (voltage) { case SEC_VOLTAGE_OFF: /* EN = 0 */ @@ -160,6 +162,7 @@ static int isl6423_set_voltage(struct dvb_frontend *fe, /* EN = 1, VSPEN = 1, VTOP = 0, VBOT = 0 */ reg_4 |= (1 << 4); reg_4 &= ~0x3; + reg_3 |= (1 << 3); break; case SEC_VOLTAGE_18: @@ -167,15 +170,23 @@ static int isl6423_set_voltage(struct dvb_frontend *fe, reg_4 |= (1 << 4); reg_4 |= 0x2; reg_4 &= ~0x1; + reg_3 |= (1 << 3); break; default: break; } + err = isl6423_write(isl6423, reg_3); + if (err < 0) + goto exit; + err = isl6423_write(isl6423, reg_4); if (err < 0) goto exit; + isl6423->reg_3 = reg_3; + isl6423->reg_4 = reg_4; + return 0; exit: dprintk(FE_ERROR, 1, "I/O error <%d>", err); @@ -189,9 +200,6 @@ static int isl6423_set_current(struct dvb_frontend *fe) const struct isl6423_config *config = isl6423->config; int err = 0; - /* SR3H = 0, SR3M = 1, SR3L = 0 */ - reg_3 = 0x02 << 5; - switch (config->current_max) { case SEC_CURRENT_275m: /* 275mA */ @@ -226,13 +234,13 @@ static int isl6423_set_current(struct dvb_frontend *fe) switch (config->curlim) { case SEC_CURRENT_LIM_ON: - /* DCL = 1 */ - reg_3 |= 0x10; + /* DCL = 0 */ + reg_3 &= ~0x10; break; case SEC_CURRENT_LIM_OFF: - /* DCL = 0 */ - reg_3 &= ~0x10; + /* DCL = 1 */ + reg_3 |= 0x10; break; } @@ -240,6 +248,8 @@ static int isl6423_set_current(struct dvb_frontend *fe) if (err < 0) goto exit; + isl6423->reg_3 = reg_3; + return 0; exit: dprintk(FE_ERROR, 1, "I/O error <%d>", err); @@ -268,6 +278,11 @@ struct dvb_frontend *isl6423_attach(struct dvb_frontend *fe, isl6423->i2c = i2c; fe->sec_priv = isl6423; + /* SR3H = 0, SR3M = 1, SR3L = 0 */ + isl6423->reg_3 = 0x02 << 5; + /* SR4H = 0, SR4M = 1, SR4L = 1 */ + isl6423->reg_4 = 0x03 << 5; + if (isl6423_set_current(fe)) goto exit; diff --git a/linux/drivers/media/dvb/ttpci/budget-ci.c b/linux/drivers/media/dvb/ttpci/budget-ci.c index 74ae43592..b1d189ccc 100644 --- a/linux/drivers/media/dvb/ttpci/budget-ci.c +++ b/linux/drivers/media/dvb/ttpci/budget-ci.c @@ -1391,6 +1391,7 @@ static struct stv6110x_config tt1600_stv6110x_config = { static struct isl6423_config tt1600_isl6423_config = { .current_max = SEC_CURRENT_515m, .curlim = SEC_CURRENT_LIM_ON, + .mod_extern = 1, .addr = 0x08, }; -- cgit v1.2.3 From a3ec55c8056a094d349074f26b9f855010a94ef3 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 7 Apr 2009 22:49:46 +0000 Subject: V4L/DVB: cx231xx: remove unused #include 's From: Huang Weiyi Remove unused #include 's in drivers/media/video/cx231xx/cx231xx-avcore.c drivers/media/video/cx231xx/cx231xx-vbi.c Signed-off-by: Huang Weiyi Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/cx231xx/cx231xx-avcore.c | 1 - linux/drivers/media/video/cx231xx/cx231xx-vbi.c | 1 - 2 files changed, 2 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/cx231xx/cx231xx-avcore.c b/linux/drivers/media/video/cx231xx/cx231xx-avcore.c index 1be3881be..6a9464079 100644 --- a/linux/drivers/media/video/cx231xx/cx231xx-avcore.c +++ b/linux/drivers/media/video/cx231xx/cx231xx-avcore.c @@ -29,7 +29,6 @@ #include #include #include -#include #include #include diff --git a/linux/drivers/media/video/cx231xx/cx231xx-vbi.c b/linux/drivers/media/video/cx231xx/cx231xx-vbi.c index 020aa13b8..d9c8e1c58 100644 --- a/linux/drivers/media/video/cx231xx/cx231xx-vbi.c +++ b/linux/drivers/media/video/cx231xx/cx231xx-vbi.c @@ -26,7 +26,6 @@ #include #include #include -#include #include #include -- cgit v1.2.3 From e8f43bdccb27fa9f829fc5c0123514b0fda2c841 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 8 Apr 2009 14:01:19 -0300 Subject: saa7134: BZ#7524: Add AVerTV Studio 507UA support From: Andy Shevchenko Priority: normal [mchehab@redhat.com: Fix merge conflicts and CodingStyle issues] Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/saa7134/saa7134-cards.c | 44 +++++++++++++++++++++++ linux/drivers/media/video/saa7134/saa7134-input.c | 1 + linux/drivers/media/video/saa7134/saa7134.h | 1 + 3 files changed, 46 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/saa7134/saa7134-cards.c b/linux/drivers/media/video/saa7134/saa7134-cards.c index af2da365b..2849b7f54 100644 --- a/linux/drivers/media/video/saa7134/saa7134-cards.c +++ b/linux/drivers/media/video/saa7134/saa7134-cards.c @@ -4792,6 +4792,44 @@ struct saa7134_board saa7134_boards[] = { .gpio = 0x01, }, }, + [SAA7134_BOARD_AVERMEDIA_STUDIO_507UA] = { + /* Andy Shevchenko */ + .name = "Avermedia AVerTV Studio 507UA", + .audio_clock = 0x00187de7, + .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, /* Should be MK5 */ + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .tda9887_conf = TDA9887_PRESENT, + .gpiomask = 0x03, + .inputs = { { + .name = name_tv, + .vmux = 1, + .amux = TV, + .tv = 1, + .gpio = 0x00, + }, { + .name = name_comp1, + .vmux = 3, + .amux = LINE1, + .gpio = 0x00, + }, { + .name = name_svideo, + .vmux = 8, + .amux = LINE1, + .gpio = 0x00, + } }, + .radio = { + .name = name_radio, + .amux = LINE2, + .gpio = 0x01, + }, + .mute = { + .name = name_mute, + .amux = LINE1, + .gpio = 0x00, + }, + }, }; const unsigned int saa7134_bcount = ARRAY_SIZE(saa7134_boards); @@ -5479,6 +5517,12 @@ struct pci_device_id saa7134_pci_tbl[] = { .subdevice = 0x9715, .driver_data = SAA7134_BOARD_AVERMEDIA_STUDIO_507, },{ + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7134, + .subvendor = 0x1461, /* Avermedia Technologies Inc */ + .subdevice = 0xa11b, + .driver_data = SAA7134_BOARD_AVERMEDIA_STUDIO_507UA, + }, { .vendor = PCI_VENDOR_ID_PHILIPS, .device = PCI_DEVICE_ID_PHILIPS_SAA7133, .subvendor = 0x1043, diff --git a/linux/drivers/media/video/saa7134/saa7134-input.c b/linux/drivers/media/video/saa7134/saa7134-input.c index 3c55ca44a..87dc1b9bb 100644 --- a/linux/drivers/media/video/saa7134/saa7134-input.c +++ b/linux/drivers/media/video/saa7134/saa7134-input.c @@ -447,6 +447,7 @@ int saa7134_input_init1(struct saa7134_dev *dev) case SAA7134_BOARD_AVERMEDIA_STUDIO_305: case SAA7134_BOARD_AVERMEDIA_STUDIO_307: case SAA7134_BOARD_AVERMEDIA_STUDIO_507: + case SAA7134_BOARD_AVERMEDIA_STUDIO_507UA: case SAA7134_BOARD_AVERMEDIA_GO_007_FM: case SAA7134_BOARD_AVERMEDIA_M102: case SAA7134_BOARD_AVERMEDIA_GO_007_FM_PLUS: diff --git a/linux/drivers/media/video/saa7134/saa7134.h b/linux/drivers/media/video/saa7134/saa7134.h index c19ec15f4..46d12fc27 100644 --- a/linux/drivers/media/video/saa7134/saa7134.h +++ b/linux/drivers/media/video/saa7134/saa7134.h @@ -281,6 +281,7 @@ struct saa7134_format { #define SAA7134_BOARD_AVERMEDIA_GO_007_FM_PLUS 154 #define SAA7134_BOARD_HAUPPAUGE_HVR1120 155 #define SAA7134_BOARD_HAUPPAUGE_HVR1110R3 156 +#define SAA7134_BOARD_AVERMEDIA_STUDIO_507UA 157 #define SAA7134_MAXBOARDS 32 #define SAA7134_INPUT_MAX 8 -- cgit v1.2.3 From e9b59da1542294b667400c0aa2340368e3dc4a80 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Thu, 9 Apr 2009 00:27:51 +0400 Subject: Add tone burst control From: Andreas Regel Signed-off-by: Andreas Regel Signed-off-by: Manu Abraham --- linux/drivers/media/dvb/frontends/stv090x.c | 66 +++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/frontends/stv090x.c b/linux/drivers/media/dvb/frontends/stv090x.c index 7267e21a4..19e5d4961 100644 --- a/linux/drivers/media/dvb/frontends/stv090x.c +++ b/linux/drivers/media/dvb/frontends/stv090x.c @@ -4145,6 +4145,15 @@ static int stv090x_send_diseqc_msg(struct dvb_frontend *fe, struct dvb_diseqc_ma int i; reg = STV090x_READ_DEMOD(state, DISTXCTL); + + STV090x_SETFIELD_Px(reg, DISTX_MODE_FIELD, 2); + STV090x_SETFIELD_Px(reg, DISEQC_RESET_FIELD, 1); + if (STV090x_WRITE_DEMOD(state, DISTXCTL, reg) < 0) + goto err; + STV090x_SETFIELD_Px(reg, DISEQC_RESET_FIELD, 0); + if (STV090x_WRITE_DEMOD(state, DISTXCTL, reg) < 0) + goto err; + STV090x_SETFIELD_Px(reg, DIS_PRECHARGE_FIELD, 1); if (STV090x_WRITE_DEMOD(state, DISTXCTL, reg) < 0) goto err; @@ -4158,8 +4167,64 @@ static int stv090x_send_diseqc_msg(struct dvb_frontend *fe, struct dvb_diseqc_ma if (STV090x_WRITE_DEMOD(state, DISTXDATA, cmd->msg[i]) < 0) goto err; + } + reg = STV090x_READ_DEMOD(state, DISTXCTL); + STV090x_SETFIELD_Px(reg, DIS_PRECHARGE_FIELD, 0); + if (STV090x_WRITE_DEMOD(state, DISTXCTL, reg) < 0) + goto err; + + i = 0; + + while ((!idle) && (i < 10)) { + reg = STV090x_READ_DEMOD(state, DISTXSTATUS); + idle = STV090x_GETFIELD_Px(reg, TX_IDLE_FIELD); + msleep(10); i++; } + + return 0; +err: + dprintk(FE_ERROR, 1, "I/O error"); + return -1; +} + +static int stv090x_send_diseqc_burst(struct dvb_frontend *fe, fe_sec_mini_cmd_t burst) +{ + struct stv090x_state *state = fe->demodulator_priv; + u32 reg, idle = 0, fifo_full = 1; + u8 mode, value; + int i; + + reg = STV090x_READ_DEMOD(state, DISTXCTL); + + if (burst == SEC_MINI_A) { + mode = 3; + value = 0x00; + } else { + mode = 2; + value = 0xFF; + } + + STV090x_SETFIELD_Px(reg, DISTX_MODE_FIELD, mode); + STV090x_SETFIELD_Px(reg, DISEQC_RESET_FIELD, 1); + if (STV090x_WRITE_DEMOD(state, DISTXCTL, reg) < 0) + goto err; + STV090x_SETFIELD_Px(reg, DISEQC_RESET_FIELD, 0); + if (STV090x_WRITE_DEMOD(state, DISTXCTL, reg) < 0) + goto err; + + STV090x_SETFIELD_Px(reg, DIS_PRECHARGE_FIELD, 1); + if (STV090x_WRITE_DEMOD(state, DISTXCTL, reg) < 0) + goto err; + + while (fifo_full) { + reg = STV090x_READ_DEMOD(state, DISTXSTATUS); + fifo_full = STV090x_GETFIELD_Px(reg, FIFO_FULL_FIELD); + } + + if (STV090x_WRITE_DEMOD(state, DISTXDATA, value) < 0) + goto err; + reg = STV090x_READ_DEMOD(state, DISTXCTL); STV090x_SETFIELD_Px(reg, DIS_PRECHARGE_FIELD, 0); if (STV090x_WRITE_DEMOD(state, DISTXCTL, reg) < 0) @@ -4680,6 +4745,7 @@ static struct dvb_frontend_ops stv090x_ops = { .i2c_gate_ctrl = stv090x_i2c_gate_ctrl, .diseqc_send_master_cmd = stv090x_send_diseqc_msg, + .diseqc_send_burst = stv090x_send_diseqc_burst, .diseqc_recv_slave_reply = stv090x_recv_slave_reply, .set_tone = stv090x_set_tone, -- cgit v1.2.3 From fa0f1c1e69e4c7711855792ff509c438034fddfc Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Thu, 9 Apr 2009 00:28:41 +0400 Subject: Fix incorrectly used mode From: Andreas Regel Signed-off-by: Andreas Regel Signed-off-by: Manu Abraham --- linux/drivers/media/dvb/frontends/stv090x.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/frontends/stv090x.c b/linux/drivers/media/dvb/frontends/stv090x.c index 19e5d4961..011ef160a 100644 --- a/linux/drivers/media/dvb/frontends/stv090x.c +++ b/linux/drivers/media/dvb/frontends/stv090x.c @@ -2707,7 +2707,7 @@ static int stv090x_get_loop_params(struct stv090x_state *state, s32 *freq_inc, s inc *= 256; inc /= 1000; - switch (state->algo) { + switch (state->search_mode) { case STV090x_SEARCH_DVBS1: case STV090x_SEARCH_DSS: inc *= 3; /* freq step = 3% of srate */ @@ -2858,7 +2858,7 @@ static int stv090x_sw_algo(struct stv090x_state *state) stv090x_get_loop_params(state, &inc, &timeout_step, &steps_max); /* get params */ - switch (state->algo) { + switch (state->search_mode) { case STV090x_SEARCH_DVBS1: case STV090x_SEARCH_DSS: /* accelerate the frequency detector */ -- cgit v1.2.3 From e380ca95f7765ba08766f2a412d74c67f77a269a Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Thu, 9 Apr 2009 01:27:10 +0400 Subject: Switch i/p ADC as well during Power management From: Manu Abraham Signed-off-by: Manu Abraham --- linux/drivers/media/dvb/frontends/stv090x.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/frontends/stv090x.c b/linux/drivers/media/dvb/frontends/stv090x.c index 011ef160a..6071b3aab 100644 --- a/linux/drivers/media/dvb/frontends/stv090x.c +++ b/linux/drivers/media/dvb/frontends/stv090x.c @@ -4279,6 +4279,11 @@ static int stv090x_sleep(struct dvb_frontend *fe) if (stv090x_write_reg(state, STV090x_SYNTCTRL, reg) < 0) goto err; + reg = stv090x_read_reg(state, STV090x_TSTTNR1); + STV090x_SETFIELD(reg, ADC1_PON_FIELD, 0); + if (stv090x_write_reg(state, STV090x_TSTTNR1, reg) < 0) + goto err; + return 0; err: dprintk(FE_ERROR, 1, "I/O error"); @@ -4298,6 +4303,11 @@ static int stv090x_wakeup(struct dvb_frontend *fe) if (stv090x_write_reg(state, STV090x_SYNTCTRL, reg) < 0) goto err; + reg = stv090x_read_reg(state, STV090x_TSTTNR1); + STV090x_SETFIELD(reg, ADC1_PON_FIELD, 1); + if (stv090x_write_reg(state, STV090x_TSTTNR1, reg) < 0) + goto err; + return 0; err: dprintk(FE_ERROR, 1, "I/O error"); -- cgit v1.2.3 From 5fa5b751c79a00c20a2717b642094fab5945c1b3 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Thu, 9 Apr 2009 02:45:43 +0400 Subject: Set DiSEqC frequency to 22kHz From: Manu Abraham Signed-off-by: Manu Abraham --- linux/drivers/media/dvb/frontends/stv090x.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/frontends/stv090x.c b/linux/drivers/media/dvb/frontends/stv090x.c index 6071b3aab..219b10d0c 100644 --- a/linux/drivers/media/dvb/frontends/stv090x.c +++ b/linux/drivers/media/dvb/frontends/stv090x.c @@ -4408,6 +4408,13 @@ static int stv090x_set_mclk(struct stv090x_state *state, u32 mclk, u32 clk) state->mclk = stv090x_get_mclk(state); + /*Set the DiseqC frequency to 22KHz */ + div = state->mclk / 704000; + if (STV090x_WRITE_DEMOD(state, F22TX, div) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, F22RX, div) < 0) + goto err; + return 0; err: dprintk(FE_ERROR, 1, "I/O error"); -- cgit v1.2.3 From f0275699c613cb8cbe3aebf02b8db03c68ba28f1 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Thu, 9 Apr 2009 03:14:00 +0400 Subject: Support > 60MSPS, simplify Srate calculation From: Manu Abraham Signed-off-by: Manu Abraham --- linux/drivers/media/dvb/frontends/stv090x.c | 60 +++++++++++++++++++---------- 1 file changed, 40 insertions(+), 20 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/frontends/stv090x.c b/linux/drivers/media/dvb/frontends/stv090x.c index 219b10d0c..3a98731f0 100644 --- a/linux/drivers/media/dvb/frontends/stv090x.c +++ b/linux/drivers/media/dvb/frontends/stv090x.c @@ -1510,18 +1510,22 @@ static int stv090x_set_srate(struct stv090x_state *state, u32 srate) { u32 sym; - if (srate > 6000000) { - sym = (srate / 1000) * 65536; - sym /= (state->mclk / 1000); + if (srate > 60000000) { + sym = (srate << 4); /* SR * 2^16 / master_clk */ + sym /= (state->mclk >> 12); + } else if (srate > 6000000) { + sym = (srate << 6); + sym /= (state->mclk >> 10); } else { - sym = (srate / 100) * 65536; - sym /= (state->mclk / 100); + sym = (srate << 9); + sym /= (state->mclk >> 7); } - if (STV090x_WRITE_DEMOD(state, SFRINIT1, (sym >> 8) & 0xff) < 0) /* MSB */ + if (STV090x_WRITE_DEMOD(state, SFRINIT1, (sym >> 8) & 0x7f) < 0) /* MSB */ goto err; if (STV090x_WRITE_DEMOD(state, SFRINIT0, (sym & 0xff)) < 0) /* LSB */ goto err; + return 0; err: dprintk(FE_ERROR, 1, "I/O error"); @@ -1533,17 +1537,29 @@ static int stv090x_set_max_srate(struct stv090x_state *state, u32 clk, u32 srate u32 sym; srate = 105 * (srate / 100); - if (srate > 6000000) { - sym = (srate / 1000) * 65536; - sym /= (clk / 1000); + if (srate > 60000000) { + sym = (srate << 4); /* SR * 2^16 / master_clk */ + sym /= (state->mclk >> 12); + } else if (srate > 6000000) { + sym = (srate << 6); + sym /= (state->mclk >> 10); } else { - sym = (srate / 100) * 65536; - sym /= (clk / 100); + sym = (srate << 9); + sym /= (state->mclk >> 7); } - if (STV090x_WRITE_DEMOD(state, SFRUP1, (sym >> 8) & 0x7f) < 0) /* MSB */ - goto err; - if (STV090x_WRITE_DEMOD(state, SFRUP0, sym & 0xff) < 0) /* LSB */ - goto err; + + if (sym < 0x7fff) { + if (STV090x_WRITE_DEMOD(state, SFRUP1, (sym >> 8) & 0x7f) < 0) /* MSB */ + goto err; + if (STV090x_WRITE_DEMOD(state, SFRUP0, sym & 0xff) < 0) /* LSB */ + goto err; + } else { + if (STV090x_WRITE_DEMOD(state, SFRUP1, 0x7f) < 0) /* MSB */ + goto err; + if (STV090x_WRITE_DEMOD(state, SFRUP0, 0xff) < 0) /* LSB */ + goto err; + } + return 0; err: dprintk(FE_ERROR, 1, "I/O error"); @@ -1555,13 +1571,17 @@ static int stv090x_set_min_srate(struct stv090x_state *state, u32 clk, u32 srate u32 sym; srate = 95 * (srate / 100); - if (srate > 6000000) { - sym = (srate / 1000) * 65536; - sym /= (clk / 1000); + if (srate > 60000000) { + sym = (srate << 4); /* SR * 2^16 / master_clk */ + sym /= (state->mclk >> 12); + } else if (srate > 6000000) { + sym = (srate << 6); + sym /= (state->mclk >> 10); } else { - sym = (srate / 100) * 65536; - sym /= (clk / 100); + sym = (srate << 9); + sym /= (state->mclk >> 7); } + if (STV090x_WRITE_DEMOD(state, SFRLOW1, ((sym >> 8) & 0xff)) < 0) /* MSB */ goto err; if (STV090x_WRITE_DEMOD(state, SFRLOW0, (sym & 0xff)) < 0) /* LSB */ -- cgit v1.2.3 From d933db51bba0b9f9419ac7046cbd6df20c10b960 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 8 Apr 2009 23:18:24 +0000 Subject: cx88-dsp: fixing 64bit math on 32bit kernels From: Miroslav Sustek Signed-off-by: Miroslav Sustek Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/cx88/cx88-dsp.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/cx88/cx88-dsp.c b/linux/drivers/media/video/cx88/cx88-dsp.c index 262bda9ec..4699055f2 100644 --- a/linux/drivers/media/video/cx88/cx88-dsp.c +++ b/linux/drivers/media/video/cx88/cx88-dsp.c @@ -22,6 +22,7 @@ #include #include #include +#include #include "cx88.h" #include "cx88-reg.h" @@ -101,8 +102,8 @@ static u32 int_goertzel(s16 x[], u32 N, u32 freq) s32 coeff = 2*int_cos(freq); u32 i; - s64 tmp; - u32 remainder; + u64 tmp; + u32 divisor; for (i = 0; i < N; i++) { s32 s = x[i] + ((s64)coeff*s_prev/32768) - s_prev2; @@ -115,7 +116,10 @@ static u32 int_goertzel(s16 x[], u32 N, u32 freq) /* XXX: N must be low enough so that N*N fits in s32. * Else we need two divisions. */ - return (u32) div_s64_rem(tmp, N*N, &remainder); + divisor = N * N; + do_div(tmp, divisor); + + return (u32) tmp; } static u32 freq_magnitude(s16 x[], u32 N, u32 freq) -- cgit v1.2.3 From c3403e5da51196983e3245ef276ee773ed2e9877 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Thu, 9 Apr 2009 03:18:50 +0400 Subject: Code simplification From: Manu Abraham Signed-off-by: Manu Abraham --- linux/drivers/media/dvb/frontends/stv090x.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/frontends/stv090x.c b/linux/drivers/media/dvb/frontends/stv090x.c index 3a98731f0..17f8d7e41 100644 --- a/linux/drivers/media/dvb/frontends/stv090x.c +++ b/linux/drivers/media/dvb/frontends/stv090x.c @@ -2153,7 +2153,6 @@ static u32 stv090x_get_srate(struct stv090x_state *state, u32 clk) { u8 r3, r2, r1, r0; s32 srate, int_1, int_2, tmp_1, tmp_2; - u32 pow2; r3 = STV090x_READ_DEMOD(state, SFR3); r2 = STV090x_READ_DEMOD(state, SFR2); @@ -2162,16 +2161,15 @@ static u32 stv090x_get_srate(struct stv090x_state *state, u32 clk) srate = ((r3 << 24) | (r2 << 16) | (r1 << 8) | r0); - pow2 = 1 << 16; - int_1 = clk / pow2; - int_2 = srate / pow2; + int_1 = clk >> 16; + int_2 = srate >> 16; - tmp_1 = clk % pow2; - tmp_2 = srate % pow2; + tmp_1 = clk % 0x10000; + tmp_2 = srate % 0x10000; srate = (int_1 * int_2) + - ((int_1 * tmp_2) / pow2) + - ((int_2 * tmp_1) / pow2); + ((int_1 * tmp_2) >> 16) + + ((int_2 * tmp_1) >> 16); return srate; } -- cgit v1.2.3 From a4d648b94c25506bd0bfa3665c4481d1be4924bd Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Thu, 9 Apr 2009 03:24:53 +0400 Subject: Code simplification From: Manu Abraham Signed-off-by: Manu Abraham --- linux/drivers/media/dvb/frontends/stv090x.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/frontends/stv090x.c b/linux/drivers/media/dvb/frontends/stv090x.c index 17f8d7e41..2044288a3 100644 --- a/linux/drivers/media/dvb/frontends/stv090x.c +++ b/linux/drivers/media/dvb/frontends/stv090x.c @@ -3136,19 +3136,16 @@ static enum stv090x_signal_state stv090x_get_sig_params(struct stv090x_state *st static u32 stv090x_get_tmgoffst(struct stv090x_state *state, u32 srate) { s32 offst_tmg; - s32 pow2; offst_tmg = STV090x_READ_DEMOD(state, TMGREG2) << 16; offst_tmg |= STV090x_READ_DEMOD(state, TMGREG1) << 8; offst_tmg |= STV090x_READ_DEMOD(state, TMGREG0); - pow2 = 1 << 24; - offst_tmg = comp2(offst_tmg, 24); /* 2's complement */ if (!offst_tmg) offst_tmg = 1; - offst_tmg = ((s32) srate * 10) / (pow2 / offst_tmg); + offst_tmg = ((s32) srate * 10) / ((s32) 0x1000000 / offst_tmg); offst_tmg /= 320; return offst_tmg; -- cgit v1.2.3 From 0d047c69b6b735f6fc53dcbc268fe5a106e9efde Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Thu, 9 Apr 2009 03:30:29 +0400 Subject: Code Simplification From: Manu Abraham Signed-off-by: Manu Abraham --- linux/drivers/media/dvb/frontends/stv090x.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/frontends/stv090x.c b/linux/drivers/media/dvb/frontends/stv090x.c index 2044288a3..2c7b5e6e3 100644 --- a/linux/drivers/media/dvb/frontends/stv090x.c +++ b/linux/drivers/media/dvb/frontends/stv090x.c @@ -3007,23 +3007,22 @@ static enum stv090x_delsys stv090x_get_std(struct stv090x_state *state) static s32 stv090x_get_car_freq(struct stv090x_state *state, u32 mclk) { s32 derot, int_1, int_2, tmp_1, tmp_2; - u32 pow2; derot = STV090x_READ_DEMOD(state, CFR2) << 16; derot |= STV090x_READ_DEMOD(state, CFR1) << 8; derot |= STV090x_READ_DEMOD(state, CFR0); derot = comp2(derot, 24); - pow2 = 1 << 12; - int_1 = state->mclk / pow2; - int_2 = derot / pow2; + int_1 = state->mclk >> 12; + int_2 = derot >> 12; - tmp_1 = state->mclk % pow2; - tmp_2 = derot % pow2; + /* carrier_frequency = MasterClock * Reg / 2^24 */ + tmp_1 = state->mclk % 0x1000; + tmp_2 = derot % 0x1000; derot = (int_1 * int_2) + - ((int_1 * tmp_2) / pow2) + - ((int_1 * tmp_1) / pow2); + ((int_1 * tmp_2) >> 12) + + ((int_1 * tmp_1) >> 12); return derot; } -- cgit v1.2.3 From ea7c6424150b7c03840e34b1a38a42c05c4a0489 Mon Sep 17 00:00:00 2001 From: Oliver Endriss Date: Fri, 10 Apr 2009 15:20:00 +0200 Subject: dvb-ttpci: Add TS replay capability From: Oliver Endriss Implemented TS replay capability. audio/video devices are able to process PES and TS data now. Priority: normal Signed-off-by: Oliver Endriss --- linux/drivers/media/dvb/ttpci/av7110_av.c | 95 +++++++++++++++++++++++++------ 1 file changed, 78 insertions(+), 17 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/ttpci/av7110_av.c b/linux/drivers/media/dvb/ttpci/av7110_av.c index e4d0900d5..2fc90e9a8 100644 --- a/linux/drivers/media/dvb/ttpci/av7110_av.c +++ b/linux/drivers/media/dvb/ttpci/av7110_av.c @@ -89,6 +89,7 @@ static void p_to_t(u8 const *buf, long int length, u16 pid, u8 *counter, struct dvb_demux_feed *feed); +static int write_ts_to_decoder(struct av7110 *av7110, int type, const u8 *buf, size_t len); int av7110_record_cb(struct dvb_filter_pes2ts *p2t, u8 *buf, size_t len) @@ -437,6 +438,45 @@ static void play_audio_cb(u8 *buf, int count, void *priv) aux_ring_buffer_write(&av7110->aout, buf, count); } + +#define FREE_COND_TS (dvb_ringbuffer_free(rb) >= 4096) + +static ssize_t ts_play(struct av7110 *av7110, const char __user *buf, + unsigned long count, int nonblock, int type) +{ + struct dvb_ringbuffer *rb; + u8 *kb; + unsigned long todo = count; + + dprintk(2, "%s: type %d cnt %lu\n", __func__, type, count); + + rb = (type) ? &av7110->avout : &av7110->aout; + kb = av7110->kbuf[type]; + + if (!kb) + return -ENOBUFS; + + if (nonblock && !FREE_COND_TS) + return -EWOULDBLOCK; + + while (todo >= TS_SIZE) { + if (!FREE_COND_TS) { + if (nonblock) + return count - todo; + if (wait_event_interruptible(rb->queue, FREE_COND_TS)) + return count - todo; + } + if (copy_from_user(kb, buf, TS_SIZE)) + return -EFAULT; + write_ts_to_decoder(av7110, type, kb, TS_SIZE); + todo -= TS_SIZE; + buf += TS_SIZE; + } + + return count - todo; +} + + #define FREE_COND (dvb_ringbuffer_free(&av7110->avout) >= 20 * 1024 && \ dvb_ringbuffer_free(&av7110->aout) >= 20 * 1024) @@ -780,11 +820,32 @@ static void p_to_t(u8 const *buf, long int length, u16 pid, u8 *counter, } +static int write_ts_to_decoder(struct av7110 *av7110, int type, const u8 *buf, size_t len) +{ + struct ipack *ipack = &av7110->ipack[type]; + + if (!(buf[3] & PAYLOAD)) + return -1; + + if (buf[1] & PAY_START) + av7110_ipack_flush(ipack); + + if (buf[3] & ADAPT_FIELD) { + len -= buf[4] + 1; + buf += buf[4] + 1; + if (!len) + return 0; + } + + av7110_ipack_instant_repack(buf + 4, len - 4, ipack); + return 0; +} + + int av7110_write_to_decoder(struct dvb_demux_feed *feed, const u8 *buf, size_t len) { struct dvb_demux *demux = feed->demux; struct av7110 *av7110 = (struct av7110 *) demux->priv; - struct ipack *ipack = &av7110->ipack[feed->pes_type]; dprintk(2, "av7110:%p, \n", av7110); @@ -804,20 +865,7 @@ int av7110_write_to_decoder(struct dvb_demux_feed *feed, const u8 *buf, size_t l return -1; } - if (!(buf[3] & 0x10)) /* no payload? */ - return -1; - if (buf[1] & 0x40) - av7110_ipack_flush(ipack); - - if (buf[3] & 0x20) { /* adaptation field? */ - len -= buf[4] + 1; - buf += buf[4] + 1; - if (!len) - return 0; - } - - av7110_ipack_instant_repack(buf + 4, len - 4, &av7110->ipack[feed->pes_type]); - return 0; + return write_ts_to_decoder(av7110, feed->pes_type, buf, len); } @@ -916,6 +964,7 @@ static ssize_t dvb_video_write(struct file *file, const char __user *buf, { struct dvb_device *dvbdev = file->private_data; struct av7110 *av7110 = dvbdev->priv; + unsigned char c; dprintk(2, "av7110:%p, \n", av7110); @@ -925,7 +974,12 @@ static ssize_t dvb_video_write(struct file *file, const char __user *buf, if (av7110->videostate.stream_source != VIDEO_SOURCE_MEMORY) return -EPERM; - return dvb_play(av7110, buf, count, file->f_flags & O_NONBLOCK, 1); + if (get_user(c, buf)) + return -EFAULT; + if (c == 0x47 && count % TS_SIZE == 0) + return ts_play(av7110, buf, count, file->f_flags & O_NONBLOCK, 1); + else + return dvb_play(av7110, buf, count, file->f_flags & O_NONBLOCK, 1); } static unsigned int dvb_audio_poll(struct file *file, poll_table *wait) @@ -952,6 +1006,7 @@ static ssize_t dvb_audio_write(struct file *file, const char __user *buf, { struct dvb_device *dvbdev = file->private_data; struct av7110 *av7110 = dvbdev->priv; + unsigned char c; dprintk(2, "av7110:%p, \n", av7110); @@ -959,7 +1014,13 @@ static ssize_t dvb_audio_write(struct file *file, const char __user *buf, printk(KERN_ERR "not audio source memory\n"); return -EPERM; } - return dvb_aplay(av7110, buf, count, file->f_flags & O_NONBLOCK, 0); + + if (get_user(c, buf)) + return -EFAULT; + if (c == 0x47 && count % TS_SIZE == 0) + return ts_play(av7110, buf, count, file->f_flags & O_NONBLOCK, 0); + else + return dvb_aplay(av7110, buf, count, file->f_flags & O_NONBLOCK, 0); } static u8 iframe_header[] = { 0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x80, 0x00, 0x00 }; -- cgit v1.2.3 From f05ceff50bdfc30402afc53b669c3e2c130c931f Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 12 Apr 2009 19:58:52 +0000 Subject: remove broken macro from dvb stv0900_priv.h From: Mariusz Kozlowski It both has unbalanced parentheses and == is not = and it's not used anywhere anyway. Signed-off-by: Mariusz Kozlowski Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/frontends/stv0900_priv.h | 2 -- 1 file changed, 2 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/frontends/stv0900_priv.h b/linux/drivers/media/dvb/frontends/stv0900_priv.h index 762d5af62..67dc8ec63 100644 --- a/linux/drivers/media/dvb/frontends/stv0900_priv.h +++ b/linux/drivers/media/dvb/frontends/stv0900_priv.h @@ -60,8 +60,6 @@ } \ } while (0) -#define dmd_choose(a, b) (demod = STV0900_DEMOD_2 ? b : a)) - static int stvdebug; #define dprintk(args...) \ -- cgit v1.2.3 From dc85976d603c70ff9a78f6a02c1c412b87fd50d6 Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Mon, 13 Apr 2009 21:22:40 -0400 Subject: cx18: Rename the work queue to "in_work_queue" From: Andy Walls Rename the work queue to "in_work_queue" to indicate it is handling incoming mailbox commands. This is preparation for adding a work queue for handling deferrable outgoing mailbox commands. Priority: normal Signed-off-by: Andy Walls --- linux/drivers/media/video/cx18/cx18-driver.c | 34 +++++++++++---------- linux/drivers/media/video/cx18/cx18-driver.h | 9 +++--- linux/drivers/media/video/cx18/cx18-mailbox.c | 44 +++++++++++++-------------- linux/drivers/media/video/cx18/cx18-mailbox.h | 4 +-- 4 files changed, 47 insertions(+), 44 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/cx18/cx18-driver.c b/linux/drivers/media/video/cx18/cx18-driver.c index 062129fb5..ca6f1b555 100644 --- a/linux/drivers/media/video/cx18/cx18-driver.c +++ b/linux/drivers/media/video/cx18/cx18-driver.c @@ -562,20 +562,22 @@ static int __devinit cx18_init_struct1(struct cx18 *cx) mutex_init(&cx->epu2apu_mb_lock); mutex_init(&cx->epu2cpu_mb_lock); - cx->work_queue = create_singlethread_workqueue(cx->v4l2_dev.name); - if (cx->work_queue == NULL) { - CX18_ERR("Unable to create work hander thread\n"); + snprintf(cx->in_workq_name, sizeof(cx->in_workq_name), "%s-in", + cx->v4l2_dev.name); + cx->in_work_queue = create_singlethread_workqueue(cx->in_workq_name); + if (cx->in_work_queue == NULL) { + CX18_ERR("Unable to create incoming mailbox handler thread\n"); return -ENOMEM; } - for (i = 0; i < CX18_MAX_EPU_WORK_ORDERS; i++) { - cx->epu_work_order[i].cx = cx; - cx->epu_work_order[i].str = cx->epu_debug_str; + for (i = 0; i < CX18_MAX_IN_WORK_ORDERS; i++) { + cx->in_work_order[i].cx = cx; + cx->in_work_order[i].str = cx->epu_debug_str; #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 20) - INIT_WORK(&cx->epu_work_order[i].work, cx18_epu_work_handler); + INIT_WORK(&cx->in_work_order[i].work, cx18_in_work_handler); #else - INIT_WORK(&cx->epu_work_order[i].work, cx18_epu_work_handler, - &cx->epu_work_order[i].work); + INIT_WORK(&cx->in_work_order[i].work, cx18_in_work_handler, + &cx->in_work_order[i].work); #endif } @@ -949,7 +951,7 @@ free_map: free_mem: release_mem_region(cx->base_addr, CX18_MEM_SIZE); free_workqueue: - destroy_workqueue(cx->work_queue); + destroy_workqueue(cx->in_work_queue); err: if (retval == 0) retval = -ENODEV; @@ -1059,11 +1061,11 @@ int cx18_init_on_first_open(struct cx18 *cx) } #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 22) -static void cx18_cancel_epu_work_orders(struct cx18 *cx) +static void cx18_cancel_in_work_orders(struct cx18 *cx) { int i; - for (i = 0; i < CX18_MAX_EPU_WORK_ORDERS; i++) - cancel_work_sync(&cx->epu_work_order[i].work); + for (i = 0; i < CX18_MAX_IN_WORK_ORDERS; i++) + cancel_work_sync(&cx->in_work_order[i].work); } #endif @@ -1087,17 +1089,17 @@ static void cx18_remove(struct pci_dev *pci_dev) cx18_halt_firmware(cx); - cx18_cancel_epu_work_orders(cx); + cx18_cancel_in_work_orders(cx); #else - flush_workqueue(cx->work_queue); + flush_workqueue(cx->in_work_queue); cx18_sw2_irq_disable(cx, IRQ_CPU_TO_EPU_ACK | IRQ_APU_TO_EPU_ACK); cx18_halt_firmware(cx); #endif - destroy_workqueue(cx->work_queue); + destroy_workqueue(cx->in_work_queue); cx18_streams_cleanup(cx, 1); diff --git a/linux/drivers/media/video/cx18/cx18-driver.h b/linux/drivers/media/video/cx18/cx18-driver.h index ece4f281e..e6f42d0cb 100644 --- a/linux/drivers/media/video/cx18/cx18-driver.h +++ b/linux/drivers/media/video/cx18/cx18-driver.h @@ -305,7 +305,7 @@ struct cx18_scb; /* forward reference */ #define CX18_MAX_MDL_ACKS 2 -#define CX18_MAX_EPU_WORK_ORDERS (CX18_MAX_FW_MDLS_PER_STREAM + 7) +#define CX18_MAX_IN_WORK_ORDERS (CX18_MAX_FW_MDLS_PER_STREAM + 7) /* CPU_DE_RELEASE_MDL can burst CX18_MAX_FW_MDLS_PER_STREAM orders in a group */ #define CX18_F_EWO_MB_STALE_UPON_RECEIPT 0x1 @@ -313,7 +313,7 @@ struct cx18_scb; /* forward reference */ #define CX18_F_EWO_MB_STALE \ (CX18_F_EWO_MB_STALE_UPON_RECEIPT | CX18_F_EWO_MB_STALE_WHILE_PROC) -struct cx18_epu_work_order { +struct cx18_in_work_order { struct work_struct work; atomic_t pending; struct cx18 *cx; @@ -568,8 +568,9 @@ struct cx18 { u32 sw2_irq_mask; u32 hw2_irq_mask; - struct workqueue_struct *work_queue; - struct cx18_epu_work_order epu_work_order[CX18_MAX_EPU_WORK_ORDERS]; + struct workqueue_struct *in_work_queue; + char in_workq_name[11]; /* "cx18-NN-in" */ + struct cx18_in_work_order in_work_order[CX18_MAX_IN_WORK_ORDERS]; char epu_debug_str[256]; /* CX18_EPU_DEBUG is rare: use shared space */ /* i2c */ diff --git a/linux/drivers/media/video/cx18/cx18-mailbox.c b/linux/drivers/media/video/cx18/cx18-mailbox.c index 66964722f..1f643b9e6 100644 --- a/linux/drivers/media/video/cx18/cx18-mailbox.c +++ b/linux/drivers/media/video/cx18/cx18-mailbox.c @@ -131,7 +131,7 @@ static void dump_mb(struct cx18 *cx, struct cx18_mailbox *mb, char *name) * Functions that run in a work_queue work handling context */ -static void epu_dma_done(struct cx18 *cx, struct cx18_epu_work_order *order) +static void epu_dma_done(struct cx18 *cx, struct cx18_in_work_order *order) { u32 handle, mdl_ack_count, id; struct cx18_mailbox *mb; @@ -213,7 +213,7 @@ static void epu_dma_done(struct cx18 *cx, struct cx18_epu_work_order *order) wake_up(&s->waitq); } -static void epu_debug(struct cx18 *cx, struct cx18_epu_work_order *order) +static void epu_debug(struct cx18 *cx, struct cx18_in_work_order *order) { char *p; char *str = order->str; @@ -224,7 +224,7 @@ static void epu_debug(struct cx18 *cx, struct cx18_epu_work_order *order) CX18_INFO("FW version: %s\n", p - 1); } -static void epu_cmd(struct cx18 *cx, struct cx18_epu_work_order *order) +static void epu_cmd(struct cx18 *cx, struct cx18_in_work_order *order) { switch (order->rpu) { case CPU: @@ -253,24 +253,24 @@ static void epu_cmd(struct cx18 *cx, struct cx18_epu_work_order *order) } static -void free_epu_work_order(struct cx18 *cx, struct cx18_epu_work_order *order) +void free_in_work_order(struct cx18 *cx, struct cx18_in_work_order *order) { atomic_set(&order->pending, 0); } #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 20) -void cx18_epu_work_handler(struct work_struct *work) +void cx18_in_work_handler(struct work_struct *work) { - struct cx18_epu_work_order *order = - container_of(work, struct cx18_epu_work_order, work); + struct cx18_in_work_order *order = + container_of(work, struct cx18_in_work_order, work); #else -void cx18_epu_work_handler(void *arg) +void cx18_in_work_handler(void *arg) { - struct cx18_epu_work_order *order = arg; + struct cx18_in_work_order *order = arg; #endif struct cx18 *cx = order->cx; epu_cmd(cx, order); - free_epu_work_order(cx, order); + free_in_work_order(cx, order); } @@ -278,7 +278,7 @@ void cx18_epu_work_handler(void *arg) * Functions that run in an interrupt handling context */ -static void mb_ack_irq(struct cx18 *cx, struct cx18_epu_work_order *order) +static void mb_ack_irq(struct cx18 *cx, struct cx18_in_work_order *order) { struct cx18_mailbox __iomem *ack_mb; u32 ack_irq, req; @@ -314,7 +314,7 @@ static void mb_ack_irq(struct cx18 *cx, struct cx18_epu_work_order *order) return; } -static int epu_dma_done_irq(struct cx18 *cx, struct cx18_epu_work_order *order) +static int epu_dma_done_irq(struct cx18 *cx, struct cx18_in_work_order *order) { u32 handle, mdl_ack_offset, mdl_ack_count; struct cx18_mailbox *mb; @@ -340,7 +340,7 @@ static int epu_dma_done_irq(struct cx18 *cx, struct cx18_epu_work_order *order) } static -int epu_debug_irq(struct cx18 *cx, struct cx18_epu_work_order *order) +int epu_debug_irq(struct cx18 *cx, struct cx18_in_work_order *order) { u32 str_offset; char *str = order->str; @@ -361,7 +361,7 @@ int epu_debug_irq(struct cx18 *cx, struct cx18_epu_work_order *order) } static inline -int epu_cmd_irq(struct cx18 *cx, struct cx18_epu_work_order *order) +int epu_cmd_irq(struct cx18 *cx, struct cx18_in_work_order *order) { int ret = -1; @@ -393,12 +393,12 @@ int epu_cmd_irq(struct cx18 *cx, struct cx18_epu_work_order *order) } static inline -struct cx18_epu_work_order *alloc_epu_work_order_irq(struct cx18 *cx) +struct cx18_in_work_order *alloc_in_work_order_irq(struct cx18 *cx) { int i; - struct cx18_epu_work_order *order = NULL; + struct cx18_in_work_order *order = NULL; - for (i = 0; i < CX18_MAX_EPU_WORK_ORDERS; i++) { + for (i = 0; i < CX18_MAX_IN_WORK_ORDERS; i++) { /* * We only need "pending" atomic to inspect its contents, * and need not do a check and set because: @@ -407,8 +407,8 @@ struct cx18_epu_work_order *alloc_epu_work_order_irq(struct cx18 *cx) * 2. "pending" is only set here, and we're serialized because * we're called in an IRQ handler context. */ - if (atomic_read(&cx->epu_work_order[i].pending) == 0) { - order = &cx->epu_work_order[i]; + if (atomic_read(&cx->in_work_order[i].pending) == 0) { + order = &cx->in_work_order[i]; atomic_set(&order->pending, 1); break; } @@ -420,7 +420,7 @@ void cx18_api_epu_cmd_irq(struct cx18 *cx, int rpu) { struct cx18_mailbox __iomem *mb; struct cx18_mailbox *order_mb; - struct cx18_epu_work_order *order; + struct cx18_in_work_order *order; int submit; switch (rpu) { @@ -434,7 +434,7 @@ void cx18_api_epu_cmd_irq(struct cx18 *cx, int rpu) return; } - order = alloc_epu_work_order_irq(cx); + order = alloc_in_work_order_irq(cx); if (order == NULL) { CX18_WARN("Unable to find blank work order form to schedule " "incoming mailbox command processing\n"); @@ -467,7 +467,7 @@ void cx18_api_epu_cmd_irq(struct cx18 *cx, int rpu) */ submit = epu_cmd_irq(cx, order); if (submit > 0) { - queue_work(cx->work_queue, &order->work); + queue_work(cx->in_work_queue, &order->work); } } diff --git a/linux/drivers/media/video/cx18/cx18-mailbox.h b/linux/drivers/media/video/cx18/cx18-mailbox.h index a667f1ae4..4bd0ba57f 100644 --- a/linux/drivers/media/video/cx18/cx18-mailbox.h +++ b/linux/drivers/media/video/cx18/cx18-mailbox.h @@ -96,9 +96,9 @@ int cx18_api_func(void *priv, u32 cmd, int in, int out, void cx18_api_epu_cmd_irq(struct cx18 *cx, int rpu); #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 20) -void cx18_epu_work_handler(struct work_struct *work); +void cx18_in_work_handler(struct work_struct *work); #else -void cx18_epu_work_handler(void *arg); +void cx18_in_work_handler(void *arg); #endif #endif -- cgit v1.2.3 From 30acb038b4822df9ff73cd379a9144314a194d94 Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Mon, 13 Apr 2009 21:42:43 -0400 Subject: cx18: Add a work queue for deferring empty buffer handoffs to the firmware From: Andy Walls This change defers sending all CX18_CPU_DE_SET_MDL commands, for a stream with an ongoing capture, by adding a work queue to handle sending such commands when needed. This prevents any sleeps, caused by notifying the firmware of new usable buffers, when a V4L2 application read() is being satisfied or when an incoming buffer is processed by the cx18-NN-in work queue thread. Priority: normal Signed-off-by: Andy Walls --- linux/drivers/media/video/cx18/cx18-driver.c | 106 +++++++++++++++++++------- linux/drivers/media/video/cx18/cx18-driver.h | 32 ++++++++ linux/drivers/media/video/cx18/cx18-streams.c | 105 +++++++++++++++++++++++-- linux/drivers/media/video/cx18/cx18-streams.h | 9 ++- 4 files changed, 219 insertions(+), 33 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/cx18/cx18-driver.c b/linux/drivers/media/video/cx18/cx18-driver.c index ca6f1b555..db226f412 100644 --- a/linux/drivers/media/video/cx18/cx18-driver.c +++ b/linux/drivers/media/video/cx18/cx18-driver.c @@ -546,22 +546,8 @@ done: cx->card_i2c = cx->card->i2c; } -/* Precondition: the cx18 structure has been memset to 0. Only - the dev and instance fields have been filled in. - No assumptions on the card type may be made here (see cx18_init_struct2 - for that). - */ -static int __devinit cx18_init_struct1(struct cx18 *cx) +static int __devinit cx18_create_in_workq(struct cx18 *cx) { - int i; - - cx->base_addr = pci_resource_start(cx->pci_dev, 0); - - mutex_init(&cx->serialize_lock); - mutex_init(&cx->gpio_lock); - mutex_init(&cx->epu2apu_mb_lock); - mutex_init(&cx->epu2cpu_mb_lock); - snprintf(cx->in_workq_name, sizeof(cx->in_workq_name), "%s-in", cx->v4l2_dev.name); cx->in_work_queue = create_singlethread_workqueue(cx->in_workq_name); @@ -569,7 +555,24 @@ static int __devinit cx18_init_struct1(struct cx18 *cx) CX18_ERR("Unable to create incoming mailbox handler thread\n"); return -ENOMEM; } + return 0; +} + +static int __devinit cx18_create_out_workq(struct cx18 *cx) +{ + snprintf(cx->out_workq_name, sizeof(cx->out_workq_name), "%s-out", + cx->v4l2_dev.name); + cx->out_work_queue = create_workqueue(cx->out_workq_name); + if (cx->out_work_queue == NULL) { + CX18_ERR("Unable to create outgoing mailbox handler threads\n"); + return -ENOMEM; + } + return 0; +} +static void __devinit cx18_init_in_work_orders(struct cx18 *cx) +{ + int i; for (i = 0; i < CX18_MAX_IN_WORK_ORDERS; i++) { cx->in_work_order[i].cx = cx; cx->in_work_order[i].str = cx->epu_debug_str; @@ -580,6 +583,48 @@ static int __devinit cx18_init_struct1(struct cx18 *cx) &cx->in_work_order[i].work); #endif } +} + +static void __devinit cx18_init_out_work_orders(struct cx18 *cx) +{ + int i; + for (i = 0; i < CX18_MAX_OUT_WORK_ORDERS; i++) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 20) + INIT_WORK(&cx->out_work_order[i].work, cx18_out_work_handler); +#else + INIT_WORK(&cx->out_work_order[i].work, cx18_out_work_handler, + &cx->out_work_order[i].work); +#endif +} + +/* Precondition: the cx18 structure has been memset to 0. Only + the dev and instance fields have been filled in. + No assumptions on the card type may be made here (see cx18_init_struct2 + for that). + */ +static int __devinit cx18_init_struct1(struct cx18 *cx) +{ + int ret; + + cx->base_addr = pci_resource_start(cx->pci_dev, 0); + + mutex_init(&cx->serialize_lock); + mutex_init(&cx->gpio_lock); + mutex_init(&cx->epu2apu_mb_lock); + mutex_init(&cx->epu2cpu_mb_lock); + + ret = cx18_create_out_workq(cx); + if (ret) + return ret; + + ret = cx18_create_in_workq(cx); + if (ret) { + destroy_workqueue(cx->out_work_queue); + return ret; + } + + cx18_init_out_work_orders(cx); + cx18_init_in_work_orders(cx); /* start counting open_id at 1 */ cx->open_id = 1; @@ -766,17 +811,17 @@ static int __devinit cx18_probe(struct pci_dev *pci_dev, retval = -ENODEV; goto err; } - if (cx18_init_struct1(cx)) { - retval = -ENOMEM; + + retval = cx18_init_struct1(cx); + if (retval) goto err; - } CX18_DEBUG_INFO("base addr: 0x%08x\n", cx->base_addr); /* PCI Device Setup */ retval = cx18_setup_pci(cx, pci_dev, pci_id); if (retval != 0) - goto free_workqueue; + goto free_workqueues; /* map io memory */ CX18_DEBUG_INFO("attempting ioremap at 0x%08x len 0x%08x\n", @@ -950,8 +995,9 @@ free_map: cx18_iounmap(cx); free_mem: release_mem_region(cx->base_addr, CX18_MEM_SIZE); -free_workqueue: +free_workqueues: destroy_workqueue(cx->in_work_queue); + destroy_workqueue(cx->out_work_queue); err: if (retval == 0) retval = -ENODEV; @@ -1082,24 +1128,30 @@ static void cx18_remove(struct pci_dev *pci_dev) if (atomic_read(&cx->tot_capturing) > 0) cx18_stop_all_captures(cx); - /* Interrupts */ + /* Stop interrupts that cause incoming work to be queued */ cx18_sw1_irq_disable(cx, IRQ_CPU_TO_EPU | IRQ_APU_TO_EPU); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 22) - cx18_sw2_irq_disable(cx, IRQ_CPU_TO_EPU_ACK | IRQ_APU_TO_EPU_ACK); - - cx18_halt_firmware(cx); + /* Incoming work can cause outgoing work, so clean up incoming first */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 22) cx18_cancel_in_work_orders(cx); #else - flush_workqueue(cx->in_work_queue); +#endif + /* + * An outgoing work order can have the only pointer to a dynamically + * allocated buffer, so we need to flush outgoing work and not just + * cancel it, so we don't lose the pointer and leak memory. + */ + flush_workqueue(cx->out_work_queue); + + /* Stop ack interrupts that may have been needed for work to finish */ cx18_sw2_irq_disable(cx, IRQ_CPU_TO_EPU_ACK | IRQ_APU_TO_EPU_ACK); cx18_halt_firmware(cx); -#endif destroy_workqueue(cx->in_work_queue); + destroy_workqueue(cx->out_work_queue); cx18_streams_cleanup(cx, 1); diff --git a/linux/drivers/media/video/cx18/cx18-driver.h b/linux/drivers/media/video/cx18/cx18-driver.h index e6f42d0cb..62dca432f 100644 --- a/linux/drivers/media/video/cx18/cx18-driver.h +++ b/linux/drivers/media/video/cx18/cx18-driver.h @@ -254,6 +254,7 @@ struct cx18_options { #define CX18_F_S_INTERNAL_USE 5 /* this stream is used internally (sliced VBI processing) */ #define CX18_F_S_STREAMOFF 7 /* signal end of stream EOS */ #define CX18_F_S_APPL_IO 8 /* this stream is used read/written by an application */ +#define CX18_F_S_STOPPING 9 /* telling the fw to stop capturing */ /* per-cx18, i_flags */ #define CX18_F_I_LOADED_FW 0 /* Loaded firmware 1st time */ @@ -324,6 +325,33 @@ struct cx18_in_work_order { char *str; }; +/* + * There are 2 types of deferrable tasks that send messages out to the firmware: + * 1. Sending individual buffers back to the firmware + * 2. Sending as many free buffers for a stream from q_free as we can to the fw + * + * The worst case scenario for multiple simultaneous streams is + * TS, YUV, PCM, VBI, MPEG, and IDX all going at once. + * + * We try to load the firmware queue with as many free buffers as possible, + * whenever we get a buffer back for a stream. For the TS we return the single + * buffer to the firmware at that time as well. For all other streams, we + * return single buffers to the firmware as the application drains them. + * + * 6 streams * 2 sets of orders * (1 single buf + 1 load fw from q_free) + * = 24 work orders should cover our needs, provided the applications read + * at a fairly steady rate. If apps don't, we fall back to non-deferred + * operation, when no cx18_out_work_orders are available for use. + */ +#define CX18_MAX_OUT_WORK_ORDERS (24) + +struct cx18_out_work_order { + struct work_struct work; + atomic_t pending; + struct cx18_stream *s; + struct cx18_buffer *buf; /* buf == NULL, means load fw from q_free */ +}; + #define CX18_INVALID_TASK_HANDLE 0xffffffff struct cx18_stream { @@ -573,6 +601,10 @@ struct cx18 { struct cx18_in_work_order in_work_order[CX18_MAX_IN_WORK_ORDERS]; char epu_debug_str[256]; /* CX18_EPU_DEBUG is rare: use shared space */ + struct workqueue_struct *out_work_queue; + char out_workq_name[12]; /* "cx18-NN-out" */ + struct cx18_out_work_order out_work_order[CX18_MAX_OUT_WORK_ORDERS]; + /* i2c */ struct i2c_adapter i2c_adap[2]; struct i2c_algo_bit_data i2c_algo[2]; diff --git a/linux/drivers/media/video/cx18/cx18-streams.c b/linux/drivers/media/video/cx18/cx18-streams.c index 7c1db9c18..64d80855b 100644 --- a/linux/drivers/media/video/cx18/cx18-streams.c +++ b/linux/drivers/media/video/cx18/cx18-streams.c @@ -431,14 +431,16 @@ static void cx18_vbi_setup(struct cx18_stream *s) cx18_api(cx, CX18_CPU_SET_RAW_VBI_PARAM, 6, data); } -struct cx18_queue *cx18_stream_put_buf_fw(struct cx18_stream *s, - struct cx18_buffer *buf) +static +struct cx18_queue *_cx18_stream_put_buf_fw(struct cx18_stream *s, + struct cx18_buffer *buf) { struct cx18 *cx = s->cx; struct cx18_queue *q; /* Don't give it to the firmware, if we're not running a capture */ if (s->handle == CX18_INVALID_TASK_HANDLE || + test_bit(CX18_F_S_STOPPING, &s->s_flags) || !test_bit(CX18_F_S_STREAMING, &s->s_flags)) return cx18_enqueue(s, buf, &s->q_free); @@ -453,7 +455,8 @@ struct cx18_queue *cx18_stream_put_buf_fw(struct cx18_stream *s, return q; } -void cx18_stream_load_fw_queue(struct cx18_stream *s) +static +void _cx18_stream_load_fw_queue(struct cx18_stream *s) { struct cx18_queue *q; struct cx18_buffer *buf; @@ -467,11 +470,99 @@ void cx18_stream_load_fw_queue(struct cx18_stream *s) buf = cx18_dequeue(s, &s->q_free); if (buf == NULL) break; - q = cx18_stream_put_buf_fw(s, buf); + q = _cx18_stream_put_buf_fw(s, buf); } while (atomic_read(&s->q_busy.buffers) < CX18_MAX_FW_MDLS_PER_STREAM && q == &s->q_busy); } +static inline +void free_out_work_order(struct cx18_out_work_order *order) +{ + atomic_set(&order->pending, 0); +} + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 20) +void cx18_out_work_handler(struct work_struct *work) +{ + struct cx18_out_work_order *order = + container_of(work, struct cx18_out_work_order, work); +#else +void cx18_out_work_handler(void *arg) +{ + struct cx18_out_work_order *order = arg; +#endif + struct cx18_stream *s = order->s; + struct cx18_buffer *buf = order->buf; + + free_out_work_order(order); + + if (buf == NULL) + _cx18_stream_load_fw_queue(s); + else + _cx18_stream_put_buf_fw(s, buf); +} + +static +struct cx18_out_work_order *alloc_out_work_order(struct cx18 *cx) +{ + int i; + struct cx18_out_work_order *order = NULL; + + for (i = 0; i < CX18_MAX_OUT_WORK_ORDERS; i++) { + /* + * We need "pending" to be atomic to inspect & set its contents + * 1. "pending" is only set to 1 here, but needs multiple access + * protection + * 2. work handler threads only clear "pending" and only + * on one, particular work order at a time, per handler thread. + */ + if (atomic_add_unless(&cx->out_work_order[i].pending, 1, 1)) { + order = &cx->out_work_order[i]; + break; + } + } + return order; +} + +struct cx18_queue *cx18_stream_put_buf_fw(struct cx18_stream *s, + struct cx18_buffer *buf) +{ + struct cx18 *cx = s->cx; + struct cx18_out_work_order *order; + + order = alloc_out_work_order(cx); + if (order == NULL) { + CX18_DEBUG_WARN("No blank, outgoing-mailbox, deferred-work, " + "order forms available; sending buffer %u back " + "to the firmware immediately for stream %s\n", + buf->id, s->name); + return _cx18_stream_put_buf_fw(s, buf); + } + order->s = s; + order->buf = buf; + queue_work(cx->out_work_queue, &order->work); + return NULL; +} + +void cx18_stream_load_fw_queue(struct cx18_stream *s) +{ + struct cx18 *cx = s->cx; + struct cx18_out_work_order *order; + + order = alloc_out_work_order(cx); + if (order == NULL) { + CX18_DEBUG_WARN("No blank, outgoing-mailbox, deferred-work, " + "order forms available; filling the firmware " + "buffer queue immediately for stream %s\n", + s->name); + _cx18_stream_load_fw_queue(s); + return; + } + order->s = s; + order->buf = NULL; /* Indicates to load the fw queue */ + queue_work(cx->out_work_queue, &order->work); +} + int cx18_start_v4l2_encode_stream(struct cx18_stream *s) { u32 data[MAX_MB_ARGUMENTS]; @@ -607,12 +698,13 @@ int cx18_start_v4l2_encode_stream(struct cx18_stream *s) cx18_writel(cx, s->buf_size, &cx->scb->cpu_mdl[buf->id].length); } mutex_unlock(&s->qlock); - cx18_stream_load_fw_queue(s); + _cx18_stream_load_fw_queue(s); /* begin_capture */ if (cx18_vapi(cx, CX18_CPU_CAPTURE_START, 1, s->handle)) { CX18_DEBUG_WARN("Error starting capture!\n"); /* Ensure we're really not capturing before releasing MDLs */ + set_bit(CX18_F_S_STOPPING, &s->s_flags); if (s->type == CX18_ENC_STREAM_TYPE_MPG) cx18_vapi(cx, CX18_CPU_CAPTURE_STOP, 2, s->handle, 1); else @@ -622,6 +714,7 @@ int cx18_start_v4l2_encode_stream(struct cx18_stream *s) cx18_vapi(cx, CX18_CPU_DE_RELEASE_MDL, 1, s->handle); cx18_vapi(cx, CX18_DESTROY_TASK, 1, s->handle); s->handle = CX18_INVALID_TASK_HANDLE; + clear_bit(CX18_F_S_STOPPING, &s->s_flags); if (atomic_read(&cx->tot_capturing) == 0) { set_bit(CX18_F_I_EOS, &cx->i_flags); cx18_write_reg(cx, 5, CX18_DSP0_INTERRUPT_MASK); @@ -666,6 +759,7 @@ int cx18_stop_v4l2_encode_stream(struct cx18_stream *s, int gop_end) if (atomic_read(&cx->tot_capturing) == 0) return 0; + set_bit(CX18_F_S_STOPPING, &s->s_flags); if (s->type == CX18_ENC_STREAM_TYPE_MPG) cx18_vapi(cx, CX18_CPU_CAPTURE_STOP, 2, s->handle, !gop_end); else @@ -716,6 +810,7 @@ int cx18_stop_v4l2_encode_stream(struct cx18_stream *s, int gop_end) cx18_vapi(cx, CX18_DESTROY_TASK, 1, s->handle); s->handle = CX18_INVALID_TASK_HANDLE; + clear_bit(CX18_F_S_STOPPING, &s->s_flags); if (atomic_read(&cx->tot_capturing) > 0) return 0; diff --git a/linux/drivers/media/video/cx18/cx18-streams.h b/linux/drivers/media/video/cx18/cx18-streams.h index 420e0a172..c0801d51d 100644 --- a/linux/drivers/media/video/cx18/cx18-streams.h +++ b/linux/drivers/media/video/cx18/cx18-streams.h @@ -28,10 +28,17 @@ int cx18_streams_setup(struct cx18 *cx); int cx18_streams_register(struct cx18 *cx); void cx18_streams_cleanup(struct cx18 *cx, int unregister); -/* Capture related */ +/* Related to submission of buffers to firmware */ void cx18_stream_load_fw_queue(struct cx18_stream *s); struct cx18_queue *cx18_stream_put_buf_fw(struct cx18_stream *s, struct cx18_buffer *buf); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 20) +void cx18_out_work_handler(struct work_struct *work); +#else +void cx18_out_work_handler(void *arg); +#endif + +/* Capture related */ int cx18_start_v4l2_encode_stream(struct cx18_stream *s); int cx18_stop_v4l2_encode_stream(struct cx18_stream *s, int gop_end); -- cgit v1.2.3 From b475f6c79d531e93935cba748b4dd3a0c572597b Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Mon, 13 Apr 2009 21:53:09 -0400 Subject: cx18: Set up to wait for a one-shot response before sending a firmware cmd From: Andy Walls When sending an outgoing firmware command, prepare to wait before we raise the interrupt, so we don't miss the wake_up() on the acknowledgment. When waiting for the acknowledgement, there is no need to loop around schedule(), as there will only be one interrupt, and hence one wake_up(), issued. Priority: normal Signed-off-by: Andy Walls --- linux/drivers/media/video/cx18/cx18-mailbox.c | 49 ++++++++++++++++++++------- 1 file changed, 37 insertions(+), 12 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/cx18/cx18-mailbox.c b/linux/drivers/media/video/cx18/cx18-mailbox.c index 1f643b9e6..58b5d0229 100644 --- a/linux/drivers/media/video/cx18/cx18-mailbox.c +++ b/linux/drivers/media/video/cx18/cx18-mailbox.c @@ -484,9 +484,10 @@ static int cx18_api_call(struct cx18 *cx, u32 cmd, int args, u32 data[]) u32 __iomem *xpu_state; wait_queue_head_t *waitq; struct mutex *mb_lock; - long int timeout, ret; + unsigned long int t0, timeout, ret; int i; char argstr[MAX_MB_ARGUMENTS*11+1]; + DEFINE_WAIT(w); if (info == NULL) { CX18_WARN("unknown cmd %x\n", cmd); @@ -568,25 +569,49 @@ static int cx18_api_call(struct cx18 *cx, u32 cmd, int args, u32 data[]) CX18_DEBUG_HI_IRQ("sending interrupt SW1: %x to send %s\n", irq, info->name); + + /* So we don't miss the wakeup, prepare to wait before notifying fw */ + prepare_to_wait(waitq, &w, TASK_UNINTERRUPTIBLE); cx18_write_reg_expect(cx, irq, SW1_INT_SET, irq, irq); - ret = wait_event_timeout( - *waitq, - cx18_readl(cx, &mb->ack) == cx18_readl(cx, &mb->request), - timeout); + t0 = jiffies; + ack = cx18_readl(cx, &mb->ack); + if (ack != req) { + schedule_timeout(timeout); + ret = jiffies - t0; + ack = cx18_readl(cx, &mb->ack); + } else { + ret = jiffies - t0; + } + + finish_wait(waitq, &w); - if (ret == 0) { - /* Timed out */ + if (req != ack) { mutex_unlock(mb_lock); - CX18_DEBUG_WARN("sending %s timed out waiting %d msecs for RPU " - "acknowledgement\n", - info->name, jiffies_to_msecs(timeout)); + if (ret >= timeout) { + /* Timed out */ + CX18_DEBUG_WARN("sending %s timed out waiting %d msecs " + "for RPU acknowledgement\n", + info->name, jiffies_to_msecs(ret)); + } else { + CX18_DEBUG_WARN("woken up before mailbox ack was ready " + "after submitting %s to RPU. only " + "waited %d msecs on req %u but awakened" + " with unmatched ack %u\n", + info->name, + jiffies_to_msecs(ret), + req, ack); + } return -EINVAL; } - if (ret != timeout) + if (ret >= timeout) + CX18_DEBUG_WARN("failed to be awakened upon RPU acknowledgment " + "sending %s; timed out waiting %d msecs\n", + info->name, jiffies_to_msecs(ret)); + else CX18_DEBUG_HI_API("waited %u msecs for %s to be acked\n", - jiffies_to_msecs(timeout-ret), info->name); + jiffies_to_msecs(ret), info->name); /* Collect data returned by the XPU */ for (i = 0; i < MAX_MB_ARGUMENTS; i++) -- cgit v1.2.3 From 4898ebd32abf45917d84356171f9b18e52d58697 Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Mon, 13 Apr 2009 22:08:00 -0400 Subject: cx18: Convert per stream mutex locks to per queue spin locks From: Andy Walls To avoid sleeps in providing buffers to user space and in handling incoming buffers from the capture unit, converted the per stream mutex for locking queues to 3 spin locks. There is now a spin lock per queue to increase concurrency when moving buffers around. Also simplified queue manipulations and buffer handling of incoming buffers of data from the capture unit. Priority: normal Signed-off-by: Andy Walls --- linux/drivers/media/video/cx18/cx18-driver.h | 2 +- linux/drivers/media/video/cx18/cx18-mailbox.c | 25 ++++---- linux/drivers/media/video/cx18/cx18-queue.c | 83 ++++++++++++++++----------- linux/drivers/media/video/cx18/cx18-streams.c | 8 ++- 4 files changed, 69 insertions(+), 49 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/cx18/cx18-driver.h b/linux/drivers/media/video/cx18/cx18-driver.h index 62dca432f..35a6758a7 100644 --- a/linux/drivers/media/video/cx18/cx18-driver.h +++ b/linux/drivers/media/video/cx18/cx18-driver.h @@ -286,6 +286,7 @@ struct cx18_queue { struct list_head list; atomic_t buffers; u32 bytesused; + spinlock_t lock; }; struct cx18_dvb { @@ -365,7 +366,6 @@ struct cx18_stream { unsigned mdl_offset; u32 id; - struct mutex qlock; /* locks access to the queues */ unsigned long s_flags; /* status flags, see above */ int dma; /* can be PCI_DMA_TODEVICE, PCI_DMA_FROMDEVICE or diff --git a/linux/drivers/media/video/cx18/cx18-mailbox.c b/linux/drivers/media/video/cx18/cx18-mailbox.c index 58b5d0229..36f4d3dd7 100644 --- a/linux/drivers/media/video/cx18/cx18-mailbox.c +++ b/linux/drivers/media/video/cx18/cx18-mailbox.c @@ -191,23 +191,24 @@ static void epu_dma_done(struct cx18 *cx, struct cx18_in_work_order *order) if (buf == NULL) { CX18_WARN("Could not find buf %d for stream %s\n", id, s->name); - /* Put as many buffers as possible back into fw use */ - cx18_stream_load_fw_queue(s); continue; } - if (s->type == CX18_ENC_STREAM_TYPE_TS && s->dvb.enabled) { - CX18_DEBUG_HI_DMA("TS recv bytesused = %d\n", - buf->bytesused); - dvb_dmx_swfilter(&s->dvb.demux, buf->buf, - buf->bytesused); + CX18_DEBUG_HI_DMA("%s recv bytesused = %d\n", + s->name, buf->bytesused); + + if (s->type != CX18_ENC_STREAM_TYPE_TS) + cx18_enqueue(s, buf, &s->q_full); + else { + if (s->dvb.enabled) + dvb_dmx_swfilter(&s->dvb.demux, buf->buf, + buf->bytesused); + cx18_enqueue(s, buf, &s->q_free); } - /* Put as many buffers as possible back into fw use */ - cx18_stream_load_fw_queue(s); - /* Put back TS buffer, since it was removed from all queues */ - if (s->type == CX18_ENC_STREAM_TYPE_TS) - cx18_stream_put_buf_fw(s, buf); } + /* Put as many buffers as possible back into fw use */ + cx18_stream_load_fw_queue(s); + wake_up(&cx->dma_waitq); if (s->id != -1) wake_up(&s->waitq); diff --git a/linux/drivers/media/video/cx18/cx18-queue.c b/linux/drivers/media/video/cx18/cx18-queue.c index 3046b8e74..693a745b0 100644 --- a/linux/drivers/media/video/cx18/cx18-queue.c +++ b/linux/drivers/media/video/cx18/cx18-queue.c @@ -53,13 +53,13 @@ struct cx18_queue *_cx18_enqueue(struct cx18_stream *s, struct cx18_buffer *buf, buf->skipped = 0; } - mutex_lock(&s->qlock); - /* q_busy is restricted to a max buffer count imposed by firmware */ if (q == &s->q_busy && atomic_read(&q->buffers) >= CX18_MAX_FW_MDLS_PER_STREAM) q = &s->q_free; + spin_lock(&q->lock); + if (to_front) list_add(&buf->list, &q->list); /* LIFO */ else @@ -67,7 +67,7 @@ struct cx18_queue *_cx18_enqueue(struct cx18_stream *s, struct cx18_buffer *buf, q->bytesused += buf->bytesused - buf->readpos; atomic_inc(&q->buffers); - mutex_unlock(&s->qlock); + spin_unlock(&q->lock); return q; } @@ -75,7 +75,7 @@ struct cx18_buffer *cx18_dequeue(struct cx18_stream *s, struct cx18_queue *q) { struct cx18_buffer *buf = NULL; - mutex_lock(&s->qlock); + spin_lock(&q->lock); if (!list_empty(&q->list)) { buf = list_first_entry(&q->list, struct cx18_buffer, list); list_del_init(&buf->list); @@ -83,7 +83,7 @@ struct cx18_buffer *cx18_dequeue(struct cx18_stream *s, struct cx18_queue *q) buf->skipped = 0; atomic_dec(&q->buffers); } - mutex_unlock(&s->qlock); + spin_unlock(&q->lock); return buf; } @@ -94,9 +94,23 @@ struct cx18_buffer *cx18_queue_get_buf(struct cx18_stream *s, u32 id, struct cx18_buffer *buf; struct cx18_buffer *tmp; struct cx18_buffer *ret = NULL; - - mutex_lock(&s->qlock); + LIST_HEAD(sweep_up); + + /* + * We don't have to acquire multiple q locks here, because we are + * serialized by the single threaded work handler. + * Buffers from the firmware will thus remain in order as + * they are moved from q_busy to q_full or to the dvb ring buffer. + */ + spin_lock(&s->q_busy.lock); list_for_each_entry_safe(buf, tmp, &s->q_busy.list, list) { + /* + * We should find what the firmware told us is done, + * right at the front of the queue. If we don't, we likely have + * missed a buffer done message from the firmware. + * Once we skip a buffer repeatedly, relative to the size of + * q_busy, we have high confidence we've missed it. + */ if (buf->id != id) { buf->skipped++; if (buf->skipped >= atomic_read(&s->q_busy.buffers)-1) { @@ -105,38 +119,41 @@ struct cx18_buffer *cx18_queue_get_buf(struct cx18_stream *s, u32 id, "times - it must have dropped out of " "rotation\n", s->name, buf->id, buf->skipped); - /* move it to q_free */ - list_move_tail(&buf->list, &s->q_free.list); - buf->bytesused = buf->readpos = buf->b_flags = - buf->skipped = 0; + /* Sweep it up to put it back into rotation */ + list_move_tail(&buf->list, &sweep_up); atomic_dec(&s->q_busy.buffers); - atomic_inc(&s->q_free.buffers); } continue; } - - buf->bytesused = bytesused; - /* Sync the buffer before we release the qlock */ - cx18_buf_sync_for_cpu(s, buf); - if (s->type == CX18_ENC_STREAM_TYPE_TS) { - /* - * TS doesn't use q_full. As we pull the buffer off of - * the queue here, the caller will have to put it back. - */ - list_del_init(&buf->list); - } else { - /* Move buffer from q_busy to q_full */ - list_move_tail(&buf->list, &s->q_full.list); - set_bit(CX18_F_B_NEED_BUF_SWAP, &buf->b_flags); - s->q_full.bytesused += buf->bytesused; - atomic_inc(&s->q_full.buffers); - } + /* + * We pull the desired buffer off of the queue here. Something + * will have to put it back on a queue later. + */ + list_del_init(&buf->list); atomic_dec(&s->q_busy.buffers); - ret = buf; break; } - mutex_unlock(&s->qlock); + spin_unlock(&s->q_busy.lock); + + /* + * We found the buffer for which we were looking. Get it ready for + * the caller to put on q_full or in the dvb ring buffer. + */ + if (ret != NULL) { + ret->bytesused = bytesused; + ret->skipped = 0; + /* readpos and b_flags were 0'ed when the buf went on q_busy */ + cx18_buf_sync_for_cpu(s, ret); + if (s->type != CX18_ENC_STREAM_TYPE_TS) + set_bit(CX18_F_B_NEED_BUF_SWAP, &ret->b_flags); + } + + /* Put any buffers the firmware is ignoring back into normal rotation */ + list_for_each_entry_safe(buf, tmp, &sweep_up, list) { + list_del_init(&buf->list); + cx18_enqueue(s, buf, &s->q_free); + } return ret; } @@ -148,7 +165,7 @@ static void cx18_queue_flush(struct cx18_stream *s, struct cx18_queue *q) if (q == &s->q_free) return; - mutex_lock(&s->qlock); + spin_lock(&q->lock); while (!list_empty(&q->list)) { buf = list_first_entry(&q->list, struct cx18_buffer, list); list_move_tail(&buf->list, &s->q_free.list); @@ -156,7 +173,7 @@ static void cx18_queue_flush(struct cx18_stream *s, struct cx18_queue *q) atomic_inc(&s->q_free.buffers); } cx18_queue_init(q); - mutex_unlock(&s->qlock); + spin_unlock(&q->lock); } void cx18_flush_queues(struct cx18_stream *s) diff --git a/linux/drivers/media/video/cx18/cx18-streams.c b/linux/drivers/media/video/cx18/cx18-streams.c index 64d80855b..5cd6f1e51 100644 --- a/linux/drivers/media/video/cx18/cx18-streams.c +++ b/linux/drivers/media/video/cx18/cx18-streams.c @@ -116,11 +116,13 @@ static void cx18_stream_init(struct cx18 *cx, int type) s->buffers = cx->stream_buffers[type]; s->buf_size = cx->stream_buf_size[type]; - mutex_init(&s->qlock); init_waitqueue_head(&s->waitq); s->id = -1; + spin_lock_init(&s->q_free.lock); cx18_queue_init(&s->q_free); + spin_lock_init(&s->q_busy.lock); cx18_queue_init(&s->q_busy); + spin_lock_init(&s->q_full.lock); cx18_queue_init(&s->q_full); } @@ -691,13 +693,13 @@ int cx18_start_v4l2_encode_stream(struct cx18_stream *s) /* Init all the cpu_mdls for this stream */ cx18_flush_queues(s); - mutex_lock(&s->qlock); + spin_lock(&s->q_free.lock); list_for_each_entry(buf, &s->q_free.list, list) { cx18_writel(cx, buf->dma_handle, &cx->scb->cpu_mdl[buf->id].paddr); cx18_writel(cx, s->buf_size, &cx->scb->cpu_mdl[buf->id].length); } - mutex_unlock(&s->qlock); + spin_unlock(&s->q_free.lock); _cx18_stream_load_fw_queue(s); /* begin_capture */ -- cgit v1.2.3 From c9b0e0161de09a846b048792fd53557bc316c5d4 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 14 Apr 2009 18:47:17 +0000 Subject: Added support for AVerMedia Cardbus Plus MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: Oldřich Jedlička Here comes the full support for AVerMedia Cardbus Plus (E501R) - including remote control. TV, Composite and FM radio tested, I don't have S-Video to test. I've figured out that the radio works only with xtal frequency 13MHz. Now without word-wrapping. [mchehab@redhat.com: CodingStyle fixes] Signed-off-by: Oldřich Jedlička Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/saa7134/saa7134-cards.c | 51 +++++++++++++++++++++++ linux/drivers/media/video/saa7134/saa7134.h | 1 + 2 files changed, 52 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/saa7134/saa7134-cards.c b/linux/drivers/media/video/saa7134/saa7134-cards.c index 2849b7f54..eca83a3e0 100644 --- a/linux/drivers/media/video/saa7134/saa7134-cards.c +++ b/linux/drivers/media/video/saa7134/saa7134-cards.c @@ -1669,6 +1669,39 @@ struct saa7134_board saa7134_boards[] = { .amux = LINE1, }, }, + [SAA7134_BOARD_AVERMEDIA_CARDBUS_501] = { + /* Oldrich Jedlicka */ + .name = "AVerMedia Cardbus TV/Radio (E501R)", + .audio_clock = 0x187de7, + .tuner_type = TUNER_ALPS_TSBE5_PAL, + .radio_type = TUNER_TEA5767, + .tuner_addr = 0x61, + .radio_addr = 0x60, + .tda9887_conf = TDA9887_PRESENT, + .gpiomask = 0x08000000, + .inputs = { { + .name = name_tv, + .vmux = 1, + .amux = TV, + .tv = 1, + .gpio = 0x08000000, + }, { + .name = name_comp1, + .vmux = 3, + .amux = LINE1, + .gpio = 0x08000000, + }, { + .name = name_svideo, + .vmux = 8, + .amux = LINE1, + .gpio = 0x08000000, + } }, + .radio = { + .name = name_radio, + .amux = LINE2, + .gpio = 0x00000000, + }, + }, [SAA7134_BOARD_CINERGY400_CARDBUS] = { .name = "Terratec Cinergy 400 mobile", .audio_clock = 0x187de7, @@ -5104,6 +5137,13 @@ struct pci_device_id saa7134_pci_tbl[] = { .subdevice = 0xd6ee, .driver_data = SAA7134_BOARD_AVERMEDIA_CARDBUS, },{ + /* AVerMedia CardBus */ + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7134, + .subvendor = 0x1461, /* Avermedia Technologies Inc */ + .subdevice = 0xb7e9, + .driver_data = SAA7134_BOARD_AVERMEDIA_CARDBUS_501, + }, { /* TransGear 3000TV */ .vendor = PCI_VENDOR_ID_PHILIPS, .device = PCI_DEVICE_ID_PHILIPS_SAA7130, @@ -6341,6 +6381,16 @@ int saa7134_board_init1(struct saa7134_dev *dev) saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0xffffffff, 0xffffffff); msleep(10); break; + case SAA7134_BOARD_AVERMEDIA_CARDBUS_501: + /* power-down tuner chip */ + saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, 0x08400000, 0x08400000); + saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x08400000, 0); + msleep(10); + saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, 0x08400000, 0x08400000); + saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x08400000, 0x08400000); + msleep(10); + dev->has_remote = SAA7134_REMOTE_I2C; + break; case SAA7134_BOARD_AVERMEDIA_CARDBUS_506: saa7134_set_gpio(dev, 23, 0); msleep(10); @@ -6782,6 +6832,7 @@ int saa7134_board_init2(struct saa7134_dev *dev) switch (dev->board) { case SAA7134_BOARD_BEHOLD_COLUMBUS_TVFM: + case SAA7134_BOARD_AVERMEDIA_CARDBUS_501: { struct v4l2_priv_tun_config tea5767_cfg; struct tea5767_ctrl ctl; diff --git a/linux/drivers/media/video/saa7134/saa7134.h b/linux/drivers/media/video/saa7134/saa7134.h index 46d12fc27..bac170935 100644 --- a/linux/drivers/media/video/saa7134/saa7134.h +++ b/linux/drivers/media/video/saa7134/saa7134.h @@ -282,6 +282,7 @@ struct saa7134_format { #define SAA7134_BOARD_HAUPPAUGE_HVR1120 155 #define SAA7134_BOARD_HAUPPAUGE_HVR1110R3 156 #define SAA7134_BOARD_AVERMEDIA_STUDIO_507UA 157 +#define SAA7134_BOARD_AVERMEDIA_CARDBUS_501 158 #define SAA7134_MAXBOARDS 32 #define SAA7134_INPUT_MAX 8 -- cgit v1.2.3 From 27ff4755ec3de948d144d09307b5d9ffb74dc7e2 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 20 Apr 2009 14:52:21 -0300 Subject: revert changeset 11562:fd645c976997 From: Mauro Carvalho Chehab The changeset created breakage on both modules: WARNING: "sms_debug" [/home/v4l/master/v4l/smsusb.ko] undefined! WARNING: "sms_debug" [/home/v4l/master/v4l/smsdvb.ko] undefined! Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/siano/smscoreapi.c | 4 ++-- linux/drivers/media/dvb/siano/smscoreapi.h | 3 +-- linux/drivers/media/dvb/siano/smsdvb.c | 3 +++ 3 files changed, 6 insertions(+), 4 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/siano/smscoreapi.c b/linux/drivers/media/dvb/siano/smscoreapi.c index 5cf5bb5d9..9a9db2588 100644 --- a/linux/drivers/media/dvb/siano/smscoreapi.c +++ b/linux/drivers/media/dvb/siano/smscoreapi.c @@ -34,8 +34,8 @@ #include "smscoreapi.h" #include "sms-cards.h" -int sms_debug; -module_param_named(debug, sms_debug, int, 0644); +static int sms_dbg; +module_param_named(debug, sms_dbg, int, 0644); MODULE_PARM_DESC(debug, "set debug level (info=1, adv=2 (or-able))"); struct smscore_device_notifyee_t { diff --git a/linux/drivers/media/dvb/siano/smscoreapi.h b/linux/drivers/media/dvb/siano/smscoreapi.h index 875cbe6c7..83e0e55f7 100644 --- a/linux/drivers/media/dvb/siano/smscoreapi.h +++ b/linux/drivers/media/dvb/siano/smscoreapi.h @@ -658,7 +658,6 @@ int smscore_led_state(struct smscore_device_t *core, int led); /* ------------------------------------------------------------------------ */ -extern int sms_debug; #define DBG_INFO 1 #define DBG_ADV 2 @@ -667,7 +666,7 @@ extern int sms_debug; printk(kern "%s: " fmt "\n", __func__, ##arg) #define dprintk(kern, lvl, fmt, arg...) do {\ - if (sms_debug & lvl) \ + if (sms_dbg & lvl) \ sms_printk(kern, fmt, ##arg); } while (0) #define sms_log(fmt, arg...) sms_printk(KERN_INFO, fmt, ##arg) diff --git a/linux/drivers/media/dvb/siano/smsdvb.c b/linux/drivers/media/dvb/siano/smsdvb.c index 329cbce07..035bd52c9 100644 --- a/linux/drivers/media/dvb/siano/smsdvb.c +++ b/linux/drivers/media/dvb/siano/smsdvb.c @@ -50,6 +50,9 @@ struct smsdvb_client_t { static struct list_head g_smsdvb_clients; static struct mutex g_smsdvb_clientslock; +static int sms_dbg; +module_param_named(debug, sms_dbg, int, 0644); +MODULE_PARM_DESC(debug, "set debug level (info=1, adv=2 (or-able))"); static int smsdvb_onresponse(void *context, struct smscore_buffer_t *cb) { -- cgit v1.2.3 From d4b7ca589b79b68daaa259887670edeef1ca37d4 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 15 Apr 2009 14:01:58 +0200 Subject: uvcvideo: Prevent invormation loss with removing implicit casting MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: Márton Németh The uvcvideo driver supports only one input, which is input 0. For all other input index the return value shall be EINVAL. This patch fixes the problem when the value 0x80000000 was incorrectly casted and treated as a zero value. The patch was tested with v4l-test 0.10 [2] with CNF7129 webcam found on EeePC 901. References: [1] V4L2 API specification, revision 0.24 http://v4l2spec.bytesex.org/spec/r11217.htm [2] v4l-test: Test environment for Video For Linux Two API http://v4l-test.sourceforge.net/ [Modified by Laurent Pinchart] Invalid input value (u32)-1 would be accepted due to integer overflow. Make sure the driver rejects it and returns -EINVAL. Priority: normal Signed-off-by: Márton Németh Signed-off-by: Andrew Morton Signed-off-by: Laurent Pinchart --- linux/drivers/media/video/uvc/uvc_v4l2.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/uvc/uvc_v4l2.c b/linux/drivers/media/video/uvc/uvc_v4l2.c index aa7949d95..e03419afe 100644 --- a/linux/drivers/media/video/uvc/uvc_v4l2.c +++ b/linux/drivers/media/video/uvc/uvc_v4l2.c @@ -654,7 +654,7 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) case VIDIOC_S_INPUT: { - u8 input = *(u32 *)arg + 1; + u32 input = *(u32 *)arg + 1; if ((ret = uvc_acquire_privileges(handle)) < 0) return ret; @@ -666,7 +666,7 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) break; } - if (input > video->selector->selector.bNrInPins) + if (input == 0 || input > video->selector->selector.bNrInPins) return -EINVAL; return uvc_query_ctrl(video->dev, SET_CUR, video->selector->id, -- cgit v1.2.3 From aa8de0afdd1a794bcd8f80c83ca7710c0050894a Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Wed, 15 Apr 2009 19:45:10 -0400 Subject: cx18: Simplify the work handler for outgoing mailbox commands From: Andy Walls Simplify the way outgoing work handler gets scheduled to send empty buffers back to the firmware for use. Also reduced the memory required for scheduling this outgoing work, by using a single, per stream work object. Priority: normal Signed-off-by: Andy Walls --- linux/drivers/media/video/cx18/cx18-driver.c | 31 ++++------ linux/drivers/media/video/cx18/cx18-driver.h | 30 +-------- linux/drivers/media/video/cx18/cx18-dvb.c | 1 + linux/drivers/media/video/cx18/cx18-queue.c | 2 +- linux/drivers/media/video/cx18/cx18-streams.c | 89 ++++----------------------- linux/drivers/media/video/cx18/cx18-streams.h | 17 ++++- 6 files changed, 40 insertions(+), 130 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/cx18/cx18-driver.c b/linux/drivers/media/video/cx18/cx18-driver.c index db226f412..41997dd18 100644 --- a/linux/drivers/media/video/cx18/cx18-driver.c +++ b/linux/drivers/media/video/cx18/cx18-driver.c @@ -30,6 +30,7 @@ #include "cx18-irq.h" #include "cx18-gpio.h" #include "cx18-firmware.h" +#include "cx18-queue.h" #include "cx18-streams.h" #include "cx18-av-core.h" #include "cx18-scb.h" @@ -585,18 +586,6 @@ static void __devinit cx18_init_in_work_orders(struct cx18 *cx) } } -static void __devinit cx18_init_out_work_orders(struct cx18 *cx) -{ - int i; - for (i = 0; i < CX18_MAX_OUT_WORK_ORDERS; i++) -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 20) - INIT_WORK(&cx->out_work_order[i].work, cx18_out_work_handler); -#else - INIT_WORK(&cx->out_work_order[i].work, cx18_out_work_handler, - &cx->out_work_order[i].work); -#endif -} - /* Precondition: the cx18 structure has been memset to 0. Only the dev and instance fields have been filled in. No assumptions on the card type may be made here (see cx18_init_struct2 @@ -623,7 +612,6 @@ static int __devinit cx18_init_struct1(struct cx18 *cx) return ret; } - cx18_init_out_work_orders(cx); cx18_init_in_work_orders(cx); /* start counting open_id at 1 */ @@ -1114,6 +1102,14 @@ static void cx18_cancel_in_work_orders(struct cx18 *cx) cancel_work_sync(&cx->in_work_order[i].work); } +static void cx18_cancel_out_work_orders(struct cx18 *cx) +{ + int i; + for (i = 0; i < CX18_MAX_STREAMS; i++) + if (&cx->streams[i].video_dev != NULL) + cancel_work_sync(&cx->streams[i].out_work_order); +} + #endif static void cx18_remove(struct pci_dev *pci_dev) { @@ -1134,16 +1130,11 @@ static void cx18_remove(struct pci_dev *pci_dev) /* Incoming work can cause outgoing work, so clean up incoming first */ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 22) cx18_cancel_in_work_orders(cx); + cx18_cancel_out_work_orders(cx); #else flush_workqueue(cx->in_work_queue); -#endif - - /* - * An outgoing work order can have the only pointer to a dynamically - * allocated buffer, so we need to flush outgoing work and not just - * cancel it, so we don't lose the pointer and leak memory. - */ flush_workqueue(cx->out_work_queue); +#endif /* Stop ack interrupts that may have been needed for work to finish */ cx18_sw2_irq_disable(cx, IRQ_CPU_TO_EPU_ACK | IRQ_APU_TO_EPU_ACK); diff --git a/linux/drivers/media/video/cx18/cx18-driver.h b/linux/drivers/media/video/cx18/cx18-driver.h index 35a6758a7..f89b82367 100644 --- a/linux/drivers/media/video/cx18/cx18-driver.h +++ b/linux/drivers/media/video/cx18/cx18-driver.h @@ -326,33 +326,6 @@ struct cx18_in_work_order { char *str; }; -/* - * There are 2 types of deferrable tasks that send messages out to the firmware: - * 1. Sending individual buffers back to the firmware - * 2. Sending as many free buffers for a stream from q_free as we can to the fw - * - * The worst case scenario for multiple simultaneous streams is - * TS, YUV, PCM, VBI, MPEG, and IDX all going at once. - * - * We try to load the firmware queue with as many free buffers as possible, - * whenever we get a buffer back for a stream. For the TS we return the single - * buffer to the firmware at that time as well. For all other streams, we - * return single buffers to the firmware as the application drains them. - * - * 6 streams * 2 sets of orders * (1 single buf + 1 load fw from q_free) - * = 24 work orders should cover our needs, provided the applications read - * at a fairly steady rate. If apps don't, we fall back to non-deferred - * operation, when no cx18_out_work_orders are available for use. - */ -#define CX18_MAX_OUT_WORK_ORDERS (24) - -struct cx18_out_work_order { - struct work_struct work; - atomic_t pending; - struct cx18_stream *s; - struct cx18_buffer *buf; /* buf == NULL, means load fw from q_free */ -}; - #define CX18_INVALID_TASK_HANDLE 0xffffffff struct cx18_stream { @@ -381,6 +354,8 @@ struct cx18_stream { struct cx18_queue q_busy; /* busy buffers - in use by firmware */ struct cx18_queue q_full; /* full buffers - data for user apps */ + struct work_struct out_work_order; + /* DVB / Digital Transport */ struct cx18_dvb dvb; }; @@ -603,7 +578,6 @@ struct cx18 { struct workqueue_struct *out_work_queue; char out_workq_name[12]; /* "cx18-NN-out" */ - struct cx18_out_work_order out_work_order[CX18_MAX_OUT_WORK_ORDERS]; /* i2c */ struct i2c_adapter i2c_adap[2]; diff --git a/linux/drivers/media/video/cx18/cx18-dvb.c b/linux/drivers/media/video/cx18/cx18-dvb.c index 3b86f57cd..e7285a109 100644 --- a/linux/drivers/media/video/cx18/cx18-dvb.c +++ b/linux/drivers/media/video/cx18/cx18-dvb.c @@ -23,6 +23,7 @@ #include "cx18-version.h" #include "cx18-dvb.h" #include "cx18-io.h" +#include "cx18-queue.h" #include "cx18-streams.h" #include "cx18-cards.h" #include "s5h1409.h" diff --git a/linux/drivers/media/video/cx18/cx18-queue.c b/linux/drivers/media/video/cx18/cx18-queue.c index 693a745b0..fa1ed7897 100644 --- a/linux/drivers/media/video/cx18/cx18-queue.c +++ b/linux/drivers/media/video/cx18/cx18-queue.c @@ -23,8 +23,8 @@ */ #include "cx18-driver.h" -#include "cx18-streams.h" #include "cx18-queue.h" +#include "cx18-streams.h" #include "cx18-scb.h" void cx18_buf_swap(struct cx18_buffer *buf) diff --git a/linux/drivers/media/video/cx18/cx18-streams.c b/linux/drivers/media/video/cx18/cx18-streams.c index 5cd6f1e51..142302ba5 100644 --- a/linux/drivers/media/video/cx18/cx18-streams.c +++ b/linux/drivers/media/video/cx18/cx18-streams.c @@ -124,6 +124,13 @@ static void cx18_stream_init(struct cx18 *cx, int type) cx18_queue_init(&s->q_busy); spin_lock_init(&s->q_full.lock); cx18_queue_init(&s->q_full); + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 20) + INIT_WORK(&s->out_work_order, cx18_out_work_handler); +#else + INIT_WORK(&s->out_work_order, cx18_out_work_handler, + &s->out_work_order); +#endif } static int cx18_prep_dev(struct cx18 *cx, int type) @@ -477,92 +484,18 @@ void _cx18_stream_load_fw_queue(struct cx18_stream *s) && q == &s->q_busy); } -static inline -void free_out_work_order(struct cx18_out_work_order *order) -{ - atomic_set(&order->pending, 0); -} - #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 20) void cx18_out_work_handler(struct work_struct *work) { - struct cx18_out_work_order *order = - container_of(work, struct cx18_out_work_order, work); #else void cx18_out_work_handler(void *arg) { - struct cx18_out_work_order *order = arg; + struct work_struct *work = arg; #endif - struct cx18_stream *s = order->s; - struct cx18_buffer *buf = order->buf; - - free_out_work_order(order); - - if (buf == NULL) - _cx18_stream_load_fw_queue(s); - else - _cx18_stream_put_buf_fw(s, buf); -} + struct cx18_stream *s = + container_of(work, struct cx18_stream, out_work_order); -static -struct cx18_out_work_order *alloc_out_work_order(struct cx18 *cx) -{ - int i; - struct cx18_out_work_order *order = NULL; - - for (i = 0; i < CX18_MAX_OUT_WORK_ORDERS; i++) { - /* - * We need "pending" to be atomic to inspect & set its contents - * 1. "pending" is only set to 1 here, but needs multiple access - * protection - * 2. work handler threads only clear "pending" and only - * on one, particular work order at a time, per handler thread. - */ - if (atomic_add_unless(&cx->out_work_order[i].pending, 1, 1)) { - order = &cx->out_work_order[i]; - break; - } - } - return order; -} - -struct cx18_queue *cx18_stream_put_buf_fw(struct cx18_stream *s, - struct cx18_buffer *buf) -{ - struct cx18 *cx = s->cx; - struct cx18_out_work_order *order; - - order = alloc_out_work_order(cx); - if (order == NULL) { - CX18_DEBUG_WARN("No blank, outgoing-mailbox, deferred-work, " - "order forms available; sending buffer %u back " - "to the firmware immediately for stream %s\n", - buf->id, s->name); - return _cx18_stream_put_buf_fw(s, buf); - } - order->s = s; - order->buf = buf; - queue_work(cx->out_work_queue, &order->work); - return NULL; -} - -void cx18_stream_load_fw_queue(struct cx18_stream *s) -{ - struct cx18 *cx = s->cx; - struct cx18_out_work_order *order; - - order = alloc_out_work_order(cx); - if (order == NULL) { - CX18_DEBUG_WARN("No blank, outgoing-mailbox, deferred-work, " - "order forms available; filling the firmware " - "buffer queue immediately for stream %s\n", - s->name); - _cx18_stream_load_fw_queue(s); - return; - } - order->s = s; - order->buf = NULL; /* Indicates to load the fw queue */ - queue_work(cx->out_work_queue, &order->work); + _cx18_stream_load_fw_queue(s); } int cx18_start_v4l2_encode_stream(struct cx18_stream *s) diff --git a/linux/drivers/media/video/cx18/cx18-streams.h b/linux/drivers/media/video/cx18/cx18-streams.h index c0801d51d..b51a014b5 100644 --- a/linux/drivers/media/video/cx18/cx18-streams.h +++ b/linux/drivers/media/video/cx18/cx18-streams.h @@ -29,9 +29,20 @@ int cx18_streams_register(struct cx18 *cx); void cx18_streams_cleanup(struct cx18 *cx, int unregister); /* Related to submission of buffers to firmware */ -void cx18_stream_load_fw_queue(struct cx18_stream *s); -struct cx18_queue *cx18_stream_put_buf_fw(struct cx18_stream *s, - struct cx18_buffer *buf); +static inline void cx18_stream_load_fw_queue(struct cx18_stream *s) +{ + struct cx18 *cx = s->cx; + queue_work(cx->out_work_queue, &s->out_work_order); +} + +static inline void cx18_stream_put_buf_fw(struct cx18_stream *s, + struct cx18_buffer *buf) +{ + /* Put buf on q_free; the out work handler will move buf(s) to q_busy */ + cx18_enqueue(s, buf, &s->q_free); + cx18_stream_load_fw_queue(s); +} + #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 20) void cx18_out_work_handler(struct work_struct *work); #else -- cgit v1.2.3 From b9c9223867f6cc234603d878addfbe6526fba480 Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Wed, 15 Apr 2009 19:49:19 -0400 Subject: cx18: Increment version due to significant buffer handling changes From: Andy Walls Version bump from 1.1.0 to 1.2.0 Priority: normal Signed-off-by: Andy Walls --- linux/drivers/media/video/cx18/cx18-version.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/cx18/cx18-version.h b/linux/drivers/media/video/cx18/cx18-version.h index bd9bd44da..45494b094 100644 --- a/linux/drivers/media/video/cx18/cx18-version.h +++ b/linux/drivers/media/video/cx18/cx18-version.h @@ -24,7 +24,7 @@ #define CX18_DRIVER_NAME "cx18" #define CX18_DRIVER_VERSION_MAJOR 1 -#define CX18_DRIVER_VERSION_MINOR 1 +#define CX18_DRIVER_VERSION_MINOR 2 #define CX18_DRIVER_VERSION_PATCHLEVEL 0 #define CX18_VERSION __stringify(CX18_DRIVER_VERSION_MAJOR) "." __stringify(CX18_DRIVER_VERSION_MINOR) "." __stringify(CX18_DRIVER_VERSION_PATCHLEVEL) -- cgit v1.2.3 From 9cb965cb8b28ed6832410d2b6b5f709f08bb3a47 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Thu, 16 Apr 2009 15:38:46 +0400 Subject: Fix read bug in STV6110x From: Andreas Regel Signed-off-by: Andreas Regel Signed-off-by: Manu Abraham --- linux/drivers/media/dvb/frontends/stv6110x.c | 1 + 1 file changed, 1 insertion(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/frontends/stv6110x.c b/linux/drivers/media/dvb/frontends/stv6110x.c index c818e21f4..cca32f3d6 100644 --- a/linux/drivers/media/dvb/frontends/stv6110x.c +++ b/linux/drivers/media/dvb/frontends/stv6110x.c @@ -53,6 +53,7 @@ static int stv6110x_read_reg(struct stv6110x_state *stv6110x, u8 reg, u8 *data) dprintk(FE_ERROR, 1, "I/O Error"); return -EREMOTEIO; } + *data = b1[0]; return 0; } -- cgit v1.2.3 From d69148350fa7fb334ad5ab1fc2e972a74de82970 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Thu, 16 Apr 2009 15:40:36 +0400 Subject: Fix Rolloff From: Andreas Regel Signed-off-by: Andreas Regel Signed-off-by: Manu Abraham --- linux/drivers/media/dvb/frontends/stv090x.c | 37 ++++++++++++++++++++++------- 1 file changed, 29 insertions(+), 8 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/frontends/stv090x.c b/linux/drivers/media/dvb/frontends/stv090x.c index 2c7b5e6e3..b28bb081d 100644 --- a/linux/drivers/media/dvb/frontends/stv090x.c +++ b/linux/drivers/media/dvb/frontends/stv090x.c @@ -1592,9 +1592,24 @@ err: return -1; } -static u32 stv090x_car_width(u32 srate, u32 rolloff) +static u32 stv090x_car_width(u32 srate, enum stv090x_rolloff rolloff) { - return srate + (srate * rolloff) / 100; + u32 ro; + + switch (rolloff) { + case STV090x_RO_20: + ro = 20; + break; + case STV090x_RO_25: + ro = 25; + break; + case STV090x_RO_35: + default: + ro = 35; + break; + } + + return srate + (srate * ro) / 100; } static int stv090x_set_vit_thacq(struct stv090x_state *state) @@ -1933,12 +1948,12 @@ static int stv090x_delivery_search(struct stv090x_state *state) if (STV090x_WRITE_DEMOD(state, DMDCFGMD, reg) < 0) goto err; - if (stv090x_vitclk_ctl(state, 1) < 0) + if (stv090x_vitclk_ctl(state, 0) < 0) goto err; if (STV090x_WRITE_DEMOD(state, ACLC, 0x1a) < 0) goto err; - if (STV090x_WRITE_DEMOD(state, ACLC, 0x09) < 0) + if (STV090x_WRITE_DEMOD(state, BCLC, 0x09) < 0) goto err; if (STV090x_WRITE_DEMOD(state, CAR2CFG, 0x26) < 0) goto err; @@ -3689,7 +3704,7 @@ static enum stv090x_signal_state stv090x_algo(struct stv090x_state *state) enum stv090x_signal_state signal_state = STV090x_NOCARRIER; u32 reg; s32 timeout_dmd = 500, timeout_fec = 50; - int lock = 0, low_sr, no_signal = 0; + int lock = 0, low_sr = 0, no_signal = 0; reg = STV090x_READ_DEMOD(state, TSCFGH); STV090x_SETFIELD_Px(reg, RST_HWARE_FIELD, 1); /* Stop path 1 stream merger */ @@ -3733,7 +3748,7 @@ static enum stv090x_signal_state stv090x_algo(struct stv090x_state *state) if (STV090x_WRITE_DEMOD(state, KREFTMG, 0x5a) < 0) goto err; if (state->algo == STV090x_COLD_SEARCH) - state->tuner_bw = (15 * (stv090x_car_width(state->srate, state->rolloff) + 1000000)) / 10; + state->tuner_bw = (15 * (stv090x_car_width(state->srate, state->rolloff) + 10000000)) / 10; else if (state->algo == STV090x_WARM_SEARCH) state->tuner_bw = stv090x_car_width(state->srate, state->rolloff) + 10000000; } else { @@ -3748,6 +3763,8 @@ static enum stv090x_signal_state stv090x_algo(struct stv090x_state *state) stv090x_set_min_srate(state, state->mclk, state->srate); if (state->srate >= 10000000) + low_sr = 0; + else low_sr = 1; } @@ -3785,7 +3802,7 @@ static enum stv090x_signal_state stv090x_algo(struct stv090x_state *state) if (STV090x_WRITE_DEMOD(state, DEMOD, reg) < 0) goto err; stv090x_delivery_search(state); - if (state->algo == STV090x_BLIND_SEARCH) + if (state->algo != STV090x_BLIND_SEARCH) stv090x_start_search(state); if (state->dev_ver == 0x12) { @@ -3902,6 +3919,10 @@ static enum dvbfe_search stv090x_search(struct dvb_frontend *fe, struct dvb_fron state->delsys = props->delivery_system; state->frequency = p->frequency; state->srate = p->u.qpsk.symbol_rate; + state->search_mode = STV090x_SEARCH_AUTO; + state->algo = STV090x_COLD_SEARCH; + state->fec = STV090x_PRERR; + state->search_range = 2000000; if (!stv090x_algo(state)) { dprintk(FE_DEBUG, 1, "Search success!"); @@ -4806,7 +4827,7 @@ struct dvb_frontend *stv090x_attach(const struct stv090x_config *config, state->demod = demod; state->demod_mode = config->demod_mode; /* Single or Dual mode */ state->device = config->device; - state->rolloff = 35; /* default */ + state->rolloff = STV090x_RO_35; /* default */ if (state->demod == STV090x_DEMODULATOR_0) mutex_init(&demod_lock); -- cgit v1.2.3 From 6b2cbdf49bd9c16272aabd0e4323ca5cec5c2103 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Thu, 16 Apr 2009 15:43:41 +0400 Subject: Fix incorrect TSMODE usage From: Andreas Regel Signed-off-by: Andreas Regel Signed-off-by: Manu Abraham --- linux/drivers/media/dvb/frontends/stv090x.c | 16 ++++++++-------- linux/drivers/media/dvb/ttpci/budget-ci.c | 4 ++-- 2 files changed, 10 insertions(+), 10 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/frontends/stv090x.c b/linux/drivers/media/dvb/frontends/stv090x.c index b28bb081d..4637f9890 100644 --- a/linux/drivers/media/dvb/frontends/stv090x.c +++ b/linux/drivers/media/dvb/frontends/stv090x.c @@ -4598,34 +4598,34 @@ static int stv090x_set_tspath(struct stv090x_state *state) switch (state->config->ts2_mode) { case STV090x_TSMODE_PARALLEL_PUNCTURED: - reg = stv090x_read_reg(state, STV090x_P1_TSCFGH); + reg = stv090x_read_reg(state, STV090x_P2_TSCFGH); STV090x_SETFIELD_Px(reg, TSFIFO_SERIAL_FIELD, 0x00); STV090x_SETFIELD_Px(reg, TSFIFO_DVBCI_FIELD, 0x00); - if (stv090x_write_reg(state, STV090x_P1_TSCFGH, reg) < 0) + if (stv090x_write_reg(state, STV090x_P2_TSCFGH, reg) < 0) goto err; break; case STV090x_TSMODE_DVBCI: - reg = stv090x_read_reg(state, STV090x_P1_TSCFGH); + reg = stv090x_read_reg(state, STV090x_P2_TSCFGH); STV090x_SETFIELD_Px(reg, TSFIFO_SERIAL_FIELD, 0x00); STV090x_SETFIELD_Px(reg, TSFIFO_DVBCI_FIELD, 0x01); - if (stv090x_write_reg(state, STV090x_P1_TSCFGH, reg) < 0) + if (stv090x_write_reg(state, STV090x_P2_TSCFGH, reg) < 0) goto err; break; case STV090x_TSMODE_SERIAL_PUNCTURED: - reg = stv090x_read_reg(state, STV090x_P1_TSCFGH); + reg = stv090x_read_reg(state, STV090x_P2_TSCFGH); STV090x_SETFIELD_Px(reg, TSFIFO_SERIAL_FIELD, 0x01); STV090x_SETFIELD_Px(reg, TSFIFO_DVBCI_FIELD, 0x00); - if (stv090x_write_reg(state, STV090x_P1_TSCFGH, reg) < 0) + if (stv090x_write_reg(state, STV090x_P2_TSCFGH, reg) < 0) goto err; break; case STV090x_TSMODE_SERIAL_CONTINUOUS: - reg = stv090x_read_reg(state, STV090x_P1_TSCFGH); + reg = stv090x_read_reg(state, STV090x_P2_TSCFGH); STV090x_SETFIELD_Px(reg, TSFIFO_SERIAL_FIELD, 0x01); STV090x_SETFIELD_Px(reg, TSFIFO_DVBCI_FIELD, 0x01); - if (stv090x_write_reg(state, STV090x_P1_TSCFGH, reg) < 0) + if (stv090x_write_reg(state, STV090x_P2_TSCFGH, reg) < 0) goto err; break; diff --git a/linux/drivers/media/dvb/ttpci/budget-ci.c b/linux/drivers/media/dvb/ttpci/budget-ci.c index b1d189ccc..07fec975a 100644 --- a/linux/drivers/media/dvb/ttpci/budget-ci.c +++ b/linux/drivers/media/dvb/ttpci/budget-ci.c @@ -1366,8 +1366,8 @@ static struct stv090x_config tt1600_stv090x_config = { .address = 0x68, .ref_clk = 27000000, - .ts1_mode = STV090x_TSMODE_DVBCI, - .ts2_mode = STV090x_TSMODE_DVBCI, + .ts1_mode = STV090x_TSMODE_PARALLEL_PUNCTURED, + .ts2_mode = STV090x_TSMODE_SERIAL_PUNCTURED, .repeater_level = STV090x_RPTLEVEL_16, -- cgit v1.2.3 From d11015309b20086d70d49ef788bc935f0225144a Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 17 Apr 2009 13:56:51 +0000 Subject: cx18: Fix the handling of i2c bus registration error From: Jean Delvare * Return actual error values as returned by the i2c subsystem, rather than 0 or 1. * If the registration of the second bus fails, unregister the first one before exiting, otherwise we are leaking resources. Signed-off-by: Jean Delvare Acked-by: Andy Walls Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/cx18/cx18-i2c.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/cx18/cx18-i2c.c b/linux/drivers/media/video/cx18/cx18-i2c.c index 4bf737849..3c76a1e27 100644 --- a/linux/drivers/media/video/cx18/cx18-i2c.c +++ b/linux/drivers/media/video/cx18/cx18-i2c.c @@ -214,7 +214,7 @@ static struct i2c_algo_bit_data cx18_i2c_algo_template = { /* init + register i2c algo-bit adapter */ int init_cx18_i2c(struct cx18 *cx) { - int i; + int i, err; CX18_DEBUG_I2C("i2c init\n"); for (i = 0; i < 2; i++) { @@ -273,8 +273,18 @@ int init_cx18_i2c(struct cx18 *cx) cx18_call_hw(cx, CX18_HW_GPIO_RESET_CTRL, core, reset, (u32) CX18_GPIO_RESET_I2C); - return i2c_bit_add_bus(&cx->i2c_adap[0]) || - i2c_bit_add_bus(&cx->i2c_adap[1]); + err = i2c_bit_add_bus(&cx->i2c_adap[0]); + if (err) + goto err; + err = i2c_bit_add_bus(&cx->i2c_adap[1]); + if (err) + goto err_del_bus_0; + return 0; + + err_del_bus_0: + i2c_del_adapter(&cx->i2c_adap[0]); + err: + return err; } void exit_cx18_i2c(struct cx18 *cx) -- cgit v1.2.3 From 8650091f79531c84de3ffa46f0b0d7655d610a1a Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Mon, 20 Apr 2009 19:51:49 +0200 Subject: uvcvideo: fill reserved fields with zero of VIDIOC_QUERYMENU MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: Márton Németh When querying menu items with VIDIOC_QUERYMENU the reserved field is not set to zero as required by V4L2 API revision 0.24 [1]. Add this fill. The patch was tested with v4l-test 0.11 [2] with CNF7129 webcam found on EeePC 901. References: [1] V4L2 API specification, revision 0.24 http://v4l2spec.bytesex.org/spec/r13317.htm#V4L2-QUERYMENU [2] v4l-test: Test environment for Video For Linux Two API http://v4l-test.sourceforge.net/ [Modified by Laurent Pinchart] Use u32 instead of __u32 in non-exported kernel code. Priority: normal Signed-off-by: Márton Németh Signed-off-by: Laurent Pinchart --- linux/drivers/media/video/uvc/uvc_v4l2.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/uvc/uvc_v4l2.c b/linux/drivers/media/video/uvc/uvc_v4l2.c index e03419afe..bc13dbf05 100644 --- a/linux/drivers/media/video/uvc/uvc_v4l2.c +++ b/linux/drivers/media/video/uvc/uvc_v4l2.c @@ -46,6 +46,8 @@ static int uvc_v4l2_query_menu(struct uvc_video_device *video, struct uvc_menu_info *menu_info; struct uvc_control_mapping *mapping; struct uvc_control *ctrl; + u32 index = query_menu->index; + u32 id = query_menu->id; ctrl = uvc_find_control(video, query_menu->id, &mapping); if (ctrl == NULL || mapping->v4l2_type != V4L2_CTRL_TYPE_MENU) @@ -54,6 +56,10 @@ static int uvc_v4l2_query_menu(struct uvc_video_device *video, if (query_menu->index >= mapping->menu_count) return -EINVAL; + memset(query_menu, 0, sizeof(*query_menu)); + query_menu->id = id; + query_menu->index = index; + menu_info = &mapping->menu_info[query_menu->index]; strlcpy(query_menu->name, menu_info->name, sizeof query_menu->name); return 0; -- cgit v1.2.3 From 990ddd211286de0b58e67483c758ce029715c97e Mon Sep 17 00:00:00 2001 From: "tom.leiming@gmail.com" Date: Sat, 18 Apr 2009 01:50:30 +0200 Subject: uvcvideo: fix uvc resume failed From: Ming Lei Now urb buffers is not freed before suspend, so uvc_alloc_urb_buffers should return packet counts allocated originally during uvc resume, instead of zero. This version uses round down to return packet counts on Linus' suggestions, or else may lead to buffer destructed if packet size is changed before calling uvc_alloc_urb_buffers() in this kind of case. Priority: normal Signed-off-by: Ming Lei Acked-by: Laurent Pinchart --- linux/drivers/media/video/uvc/uvc_video.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) --- linux/drivers/media/video/uvc/uvc_video.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/uvc/uvc_video.c b/linux/drivers/media/video/uvc/uvc_video.c index 82a9999b6..c5df33de9 100644 --- a/linux/drivers/media/video/uvc/uvc_video.c +++ b/linux/drivers/media/video/uvc/uvc_video.c @@ -746,7 +746,7 @@ static int uvc_alloc_urb_buffers(struct uvc_video_device *video, /* Buffers are already allocated, bail out. */ if (video->urb_size) - return 0; + return video->urb_size / psize; /* Compute the number of packets. Bulk endpoints might transfer UVC * payloads accross multiple URBs. -- cgit v1.2.3 From 64653d7d79b02fcce49f6b56e8b12d7ead4201f1 Mon Sep 17 00:00:00 2001 From: Oliver Endriss Date: Sun, 19 Apr 2009 19:47:01 +0200 Subject: dvb-ttpci: Check transport error indicator flag From: Oliver Endriss Discard PES packet if transport error indicator flag is set. Priority: normal Signed-off-by: Oliver Endriss --- linux/drivers/media/dvb/ttpci/av7110_av.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/ttpci/av7110_av.c b/linux/drivers/media/dvb/ttpci/av7110_av.c index 2fc90e9a8..2adcaeff3 100644 --- a/linux/drivers/media/dvb/ttpci/av7110_av.c +++ b/linux/drivers/media/dvb/ttpci/av7110_av.c @@ -824,6 +824,11 @@ static int write_ts_to_decoder(struct av7110 *av7110, int type, const u8 *buf, s { struct ipack *ipack = &av7110->ipack[type]; + if (buf[1] & TRANS_ERROR) { + av7110_ipack_reset(ipack); + return -1; + } + if (!(buf[3] & PAYLOAD)) return -1; -- cgit v1.2.3 From 91ebcf14b8f1d729a2b5c28f23aa2165ccaf2ee1 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 19 Apr 2009 20:21:03 +0000 Subject: av7110_hw: fix compile warning From: Alexey Klimov Signed-off-by: Alexey Klimov Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/ttpci/av7110_hw.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/ttpci/av7110_hw.c b/linux/drivers/media/dvb/ttpci/av7110_hw.c index 276be4056..9c91e3b88 100644 --- a/linux/drivers/media/dvb/ttpci/av7110_hw.c +++ b/linux/drivers/media/dvb/ttpci/av7110_hw.c @@ -1089,7 +1089,7 @@ int av7110_osd_cmd(struct av7110 *av7110, osd_cmd_t *dc) else { int i, len = dc->x0-dc->color+1; u8 __user *colors = (u8 __user *)dc->data; - u8 r, g, b, blend; + u8 r, g = 0, b = 0, blend = 0; ret = 0; for (i = 0; i Date: Mon, 20 Apr 2009 16:57:49 +0200 Subject: Add Elgato EyeTV DTT deluxe to dibcom driver From: Armin Schenker This patch introduces support for DVB-T for the following dibcom based card: Elgato EyeTV DTT deluxe (USB-ID: 0fd9:0020) Priority: normal Signed-off-by: Armin Schenker Signed-off-by: Patrick Boettcher --- linux/drivers/media/dvb/dvb-usb/dib0700_devices.c | 7 ++++++- linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h | 1 + linux/drivers/media/dvb/dvb-usb/dvb-usb.h | 2 +- 3 files changed, 8 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 31fe6e10a..e39993df0 100644 --- a/linux/drivers/media/dvb/dvb-usb/dib0700_devices.c +++ b/linux/drivers/media/dvb/dvb-usb/dib0700_devices.c @@ -1497,6 +1497,7 @@ struct usb_device_id dib0700_usb_id_table[] = { { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_TIGER_ATSC_B210) }, { 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) }, { 0 } /* Terminating entry */ }; MODULE_DEVICE_TABLE(usb, dib0700_usb_id_table); @@ -1696,7 +1697,7 @@ struct dvb_usb_device_properties dib0700_devices[] = { }, }, - .num_device_descs = 11, + .num_device_descs = 12, .devices = { { "DiBcom STK7070P reference design", { &dib0700_usb_id_table[15], NULL }, @@ -1742,6 +1743,10 @@ struct dvb_usb_device_properties dib0700_devices[] = { { &dib0700_usb_id_table[45], NULL }, { NULL }, }, + { "Elgato EyeTV Dtt Dlx PD378S", + { &dib0700_usb_id_table[50], NULL }, + { NULL }, + }, }, .rc_interval = DEFAULT_RC_INTERVAL, 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 ca0051272..6a4062d5d 100644 --- a/linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h +++ b/linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h @@ -253,5 +253,6 @@ #define USB_PID_MSI_DIGI_VOX_MINI_III 0x8807 #define USB_PID_SONY_PLAYTV 0x0003 #define USB_PID_ELGATO_EYETV_DTT 0x0021 +#define USB_PID_ELGATO_EYETV_DTT_Dlx 0x0020 #endif diff --git a/linux/drivers/media/dvb/dvb-usb/dvb-usb.h b/linux/drivers/media/dvb/dvb-usb/dvb-usb.h index fd64daa06..8874221c1 100644 --- a/linux/drivers/media/dvb/dvb-usb/dvb-usb.h +++ b/linux/drivers/media/dvb/dvb-usb/dvb-usb.h @@ -224,7 +224,7 @@ struct dvb_usb_device_properties { int generic_bulk_ctrl_endpoint; int num_device_descs; - struct dvb_usb_device_description devices[11]; + struct dvb_usb_device_description devices[12]; }; /** -- cgit v1.2.3 From 914624bd0e787219ab55bf33d1ac7c7412a8459c Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 20 Apr 2009 22:07:44 +0000 Subject: patch: s2255drv: fix race condition on set mode From: Dean Anderson set_modeready flag must be set before command sent to USB in s2255_write_config. Signed-off-by: Dean Anderson Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/s2255drv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/s2255drv.c b/linux/drivers/media/video/s2255drv.c index c13aa2cc8..0fac6af08 100644 --- a/linux/drivers/media/video/s2255drv.c +++ b/linux/drivers/media/video/s2255drv.c @@ -1238,6 +1238,7 @@ static int s2255_set_mode(struct s2255_dev *dev, unsigned long chn, buffer[1] = (u32) chn_rev; buffer[2] = CMD_SET_MODE; memcpy(&buffer[3], &dev->mode[chn], sizeof(struct s2255_mode)); + dev->setmode_ready[chn] = 0; res = s2255_write_config(dev->udev, (unsigned char *)buffer, 512); if (debug) dump_verify_mode(dev, mode); @@ -1246,7 +1247,6 @@ static int s2255_set_mode(struct s2255_dev *dev, unsigned long chn, /* wait at least 3 frames before continuing */ if (mode->restart) { - dev->setmode_ready[chn] = 0; wait_event_timeout(dev->wait_setmode[chn], (dev->setmode_ready[chn] != 0), msecs_to_jiffies(S2255_SETMODE_TIMEOUT)); -- cgit v1.2.3 From 175b0d841f2019dc6f8383d83db6664adff68fa4 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Tue, 21 Apr 2009 18:45:56 +0200 Subject: gspca - main: Webcams cannot do both isoc and bulk image transfers. From: Jean-Francois Moine Let the subdrivers to set the 'image transfer by bulk' flag. Priority: normal Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/finepix.c | 1 + linux/drivers/media/video/gspca/gspca.c | 31 +++++++++++-------------------- linux/drivers/media/video/gspca/gspca.h | 2 +- linux/drivers/media/video/gspca/ov534.c | 7 +++++-- linux/drivers/media/video/gspca/sq905.c | 1 + linux/drivers/media/video/gspca/sq905c.c | 1 + 6 files changed, 20 insertions(+), 23 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/finepix.c b/linux/drivers/media/video/gspca/finepix.c index 00e6863ed..480ec5c87 100644 --- a/linux/drivers/media/video/gspca/finepix.c +++ b/linux/drivers/media/video/gspca/finepix.c @@ -168,6 +168,7 @@ static int sd_config(struct gspca_dev *gspca_dev, cam->cam_mode = fpix_mode; cam->nmodes = 1; + cam->bulk = 1; cam->bulk_size = FPIX_MAX_TRANSFER; INIT_WORK(&dev->work_struct, dostream); diff --git a/linux/drivers/media/video/gspca/gspca.c b/linux/drivers/media/video/gspca/gspca.c index c018f162a..10ee2c66f 100644 --- a/linux/drivers/media/video/gspca/gspca.c +++ b/linux/drivers/media/video/gspca/gspca.c @@ -453,7 +453,7 @@ static void destroy_urbs(struct gspca_dev *gspca_dev) * look for an input transfer endpoint in an alternate setting */ static struct usb_host_endpoint *alt_xfer(struct usb_host_interface *alt, - __u8 xfer) + int xfer) { struct usb_host_endpoint *ep; int i, attr; @@ -479,37 +479,28 @@ static struct usb_host_endpoint *get_ep(struct gspca_dev *gspca_dev) { struct usb_interface *intf; struct usb_host_endpoint *ep; - int i, ret; + int xfer, i, ret; intf = usb_ifnum_to_if(gspca_dev->dev, gspca_dev->iface); ep = NULL; + xfer = gspca_dev->cam.bulk ? USB_ENDPOINT_XFER_BULK + : USB_ENDPOINT_XFER_ISOC; i = gspca_dev->alt; /* previous alt setting */ - - /* try isoc */ while (--i >= 0) { - ep = alt_xfer(&intf->altsetting[i], - USB_ENDPOINT_XFER_ISOC); + ep = alt_xfer(&intf->altsetting[i], xfer); if (ep) break; } - - /* if no isoc, try bulk (alt 0 only) */ if (ep == NULL) { - ep = alt_xfer(&intf->altsetting[0], - USB_ENDPOINT_XFER_BULK); - if (ep == NULL) { - err("no transfer endpoint found"); - return NULL; - } - i = 0; - gspca_dev->bulk = 1; + err("no transfer endpoint found"); + return NULL; } PDEBUG(D_STREAM, "use alt %d ep 0x%02x", i, ep->desc.bEndpointAddress); if (i > 0) { ret = usb_set_interface(gspca_dev->dev, gspca_dev->iface, i); if (ret < 0) { - err("set interface err %d", ret); + err("set alt %d err %d", i, ret); return NULL; } } @@ -529,7 +520,7 @@ static int create_urbs(struct gspca_dev *gspca_dev, /* calculate the packet size and the number of packets */ psize = le16_to_cpu(ep->desc.wMaxPacketSize); - if (!gspca_dev->bulk) { /* isoc */ + if (!gspca_dev->cam.bulk) { /* isoc */ /* See paragraph 5.9 / table 5-11 of the usb 2.0 spec. */ psize = (psize & 0x07ff) * (1 + ((psize >> 11) & 3)); @@ -629,7 +620,7 @@ static int gspca_init_transfer(struct gspca_dev *gspca_dev) goto out; /* clear the bulk endpoint */ - if (gspca_dev->bulk) + if (gspca_dev->cam.bulk) usb_clear_halt(gspca_dev->dev, gspca_dev->urb[0]->pipe); @@ -642,7 +633,7 @@ static int gspca_init_transfer(struct gspca_dev *gspca_dev) gspca_dev->streaming = 1; /* some bulk transfers are started by the subdriver */ - if (gspca_dev->bulk && gspca_dev->cam.bulk_nurbs == 0) + if (gspca_dev->cam.bulk && gspca_dev->cam.bulk_nurbs == 0) break; /* submit the URBs */ diff --git a/linux/drivers/media/video/gspca/gspca.h b/linux/drivers/media/video/gspca/gspca.h index 58e8ff021..85bb0fedd 100644 --- a/linux/drivers/media/video/gspca/gspca.h +++ b/linux/drivers/media/video/gspca/gspca.h @@ -56,6 +56,7 @@ struct cam { * - cannot be > MAX_NURBS * - when 0 and bulk_size != 0 means * 1 URB and submit done by subdriver */ + u8 bulk; /* image transfer by 0:isoc / 1:bulk */ u32 input_flags; /* value for ENUM_INPUT status flags */ }; @@ -168,7 +169,6 @@ struct gspca_dev { __u8 iface; /* USB interface number */ __u8 alt; /* USB alternate setting */ __u8 nbalt; /* number of USB alternate settings */ - u8 bulk; /* image transfer by 0:isoc / 1:bulk */ }; int gspca_dev_probe(struct usb_interface *intf, diff --git a/linux/drivers/media/video/gspca/ov534.c b/linux/drivers/media/video/gspca/ov534.c index 0f5ec9317..abb8ea3db 100644 --- a/linux/drivers/media/video/gspca/ov534.c +++ b/linux/drivers/media/video/gspca/ov534.c @@ -727,8 +727,11 @@ static int sd_config(struct gspca_dev *gspca_dev, cam->cam_mode = vga_mode; cam->nmodes = ARRAY_SIZE(vga_mode); - cam->bulk_size = 16384; - cam->bulk_nurbs = 2; + if (sd->sensor == SENSOR_OV772X) { + cam->bulk = 1; + cam->bulk_size = 16384; + cam->bulk_nurbs = 2; + } return 0; } diff --git a/linux/drivers/media/video/gspca/sq905.c b/linux/drivers/media/video/gspca/sq905.c index 2e1cdf068..715a68f01 100644 --- a/linux/drivers/media/video/gspca/sq905.c +++ b/linux/drivers/media/video/gspca/sq905.c @@ -309,6 +309,7 @@ static int sd_config(struct gspca_dev *gspca_dev, struct sd *dev = (struct sd *) gspca_dev; /* We don't use the buffer gspca allocates so make it small. */ + cam->bulk = 1; cam->bulk_size = 64; INIT_WORK(&dev->work_struct, sq905_dostream); diff --git a/linux/drivers/media/video/gspca/sq905c.c b/linux/drivers/media/video/gspca/sq905c.c index 0bcb74a1b..916892505 100644 --- a/linux/drivers/media/video/gspca/sq905c.c +++ b/linux/drivers/media/video/gspca/sq905c.c @@ -206,6 +206,7 @@ static int sd_config(struct gspca_dev *gspca_dev, cam->nmodes = 1; /* We don't use the buffer gspca allocates so make it small. */ cam->bulk_size = 32; + cam->bulk = 1; INIT_WORK(&dev->work_struct, sq905c_dostream); return 0; } -- cgit v1.2.3 From c1c75c6d10a30d067a92060e5061488642663341 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Tue, 21 Apr 2009 18:57:31 +0200 Subject: gspca - main: Fix a crash when no bandwidth available. From: Jean-Francois Moine When the bandwidth is not wide enough, the transfer endpoint may be set to the one of the alternate setting 0. This one may be null and this causes a divide by 0 oops. Reported-by: Hans de Goede Priority: normal Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/gspca.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/gspca.c b/linux/drivers/media/video/gspca/gspca.c index 10ee2c66f..cbdfd7552 100644 --- a/linux/drivers/media/video/gspca/gspca.c +++ b/linux/drivers/media/video/gspca/gspca.c @@ -461,7 +461,8 @@ static struct usb_host_endpoint *alt_xfer(struct usb_host_interface *alt, for (i = 0; i < alt->desc.bNumEndpoints; i++) { ep = &alt->endpoint[i]; attr = ep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK; - if (attr == xfer) + if (attr == xfer + && ep->desc.wMaxPacketSize != 0) return ep; } return NULL; -- cgit v1.2.3 From 27fcff0ad226c68320c8b72afff4a431d25d4462 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Tue, 21 Apr 2009 19:05:44 +0200 Subject: gspca - main: Set the current alternate setting only when needed. From: Jean-Francois Moine Priority: normal Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/gspca.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/gspca.c b/linux/drivers/media/video/gspca/gspca.c index cbdfd7552..e7f9e37d4 100644 --- a/linux/drivers/media/video/gspca/gspca.c +++ b/linux/drivers/media/video/gspca/gspca.c @@ -498,7 +498,7 @@ static struct usb_host_endpoint *get_ep(struct gspca_dev *gspca_dev) } PDEBUG(D_STREAM, "use alt %d ep 0x%02x", i, ep->desc.bEndpointAddress); - if (i > 0) { + if (gspca_dev->nbalt > 1) { ret = usb_set_interface(gspca_dev->dev, gspca_dev->iface, i); if (ret < 0) { err("set alt %d err %d", i, ret); @@ -665,6 +665,8 @@ static int gspca_set_alt0(struct gspca_dev *gspca_dev) { int ret; + if (gspca_dev->alt == 0) + return 0; ret = usb_set_interface(gspca_dev->dev, gspca_dev->iface, 0); if (ret < 0) PDEBUG(D_ERR|D_STREAM, "set alt 0 err %d", ret); -- cgit v1.2.3 From 023647a67a1b61656f768f562ec79dd516c97535 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 23 Apr 2009 05:32:49 +0000 Subject: saa7134: split Behold`s card entries to properly identify the model From: Dmitri Belimov Split Beholdr`s cards to correct models. Signed-off-by: Beholder Intl. Ltd. Dmitry Belimov Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/saa7134/saa7134-cards.c | 341 ++++++++++++++++++++-- linux/drivers/media/video/saa7134/saa7134-input.c | 12 +- linux/drivers/media/video/saa7134/saa7134.h | 12 +- 3 files changed, 339 insertions(+), 26 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/saa7134/saa7134-cards.c b/linux/drivers/media/video/saa7134/saa7134-cards.c index eca83a3e0..582a56c07 100644 --- a/linux/drivers/media/video/saa7134/saa7134-cards.c +++ b/linux/drivers/media/video/saa7134/saa7134-cards.c @@ -4078,7 +4078,7 @@ struct saa7134_board saa7134_boards[] = { [SAA7134_BOARD_BEHOLD_505FM] = { /* Beholder Intl. Ltd. 2008 */ /*Dmitry Belimov */ - .name = "Beholder BeholdTV 505 FM/RDS", + .name = "Beholder BeholdTV 505 FM", .audio_clock = 0x00200000, .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, .radio_type = UNSET, @@ -4086,6 +4086,40 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = ADDR_UNSET, .tda9887_conf = TDA9887_PRESENT, .gpiomask = 0x00008000, + .inputs = {{ + .name = name_tv, + .vmux = 3, + .amux = LINE2, + .tv = 1, + }, { + .name = name_comp1, + .vmux = 1, + .amux = LINE1, + }, { + .name = name_svideo, + .vmux = 8, + .amux = LINE1, + } }, + .mute = { + .name = name_mute, + .amux = LINE1, + }, + .radio = { + .name = name_radio, + .amux = LINE2, + }, + }, + [SAA7134_BOARD_BEHOLD_505RDS] = { + /* Beholder Intl. Ltd. 2008 */ + /*Dmitry Belimov */ + .name = "Beholder BeholdTV 505 RDS", + .audio_clock = 0x00200000, + .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, /* FIXME to MK5 */ + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .tda9887_conf = TDA9887_PRESENT, + .gpiomask = 0x00008000, .inputs = {{ .name = name_tv, .vmux = 3, @@ -4112,7 +4146,7 @@ struct saa7134_board saa7134_boards[] = { [SAA7134_BOARD_BEHOLD_507_9FM] = { /* Beholder Intl. Ltd. 2008 */ /*Dmitry Belimov */ - .name = "Beholder BeholdTV 507 FM/RDS / BeholdTV 509 FM", + .name = "Beholder BeholdTV 507 FM / BeholdTV 509 FM", .audio_clock = 0x00187de7, .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, .radio_type = UNSET, @@ -4139,6 +4173,66 @@ struct saa7134_board saa7134_boards[] = { .amux = LINE2, }, }, + [SAA7134_BOARD_BEHOLD_507RDS_MK5] = { + /* Beholder Intl. Ltd. 2008 */ + /*Dmitry Belimov */ + .name = "Beholder BeholdTV 507 RDS", + .audio_clock = 0x00187de7, + .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, /* FIXME to MK5 */ + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .tda9887_conf = TDA9887_PRESENT, + .gpiomask = 0x00008000, + .inputs = {{ + .name = name_tv, + .vmux = 3, + .amux = TV, + .tv = 1, + }, { + .name = name_comp1, + .vmux = 1, + .amux = LINE1, + }, { + .name = name_svideo, + .vmux = 8, + .amux = LINE1, + } }, + .radio = { + .name = name_radio, + .amux = LINE2, + }, + }, + [SAA7134_BOARD_BEHOLD_507RDS_MK3] = { + /* Beholder Intl. Ltd. 2008 */ + /*Dmitry Belimov */ + .name = "Beholder BeholdTV 507 RDS", + .audio_clock = 0x00187de7, + .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .tda9887_conf = TDA9887_PRESENT, + .gpiomask = 0x00008000, + .inputs = {{ + .name = name_tv, + .vmux = 3, + .amux = TV, + .tv = 1, + }, { + .name = name_comp1, + .vmux = 1, + .amux = LINE1, + }, { + .name = name_svideo, + .vmux = 8, + .amux = LINE1, + } }, + .radio = { + .name = name_radio, + .amux = LINE2, + }, + }, [SAA7134_BOARD_BEHOLD_COLUMBUS_TVFM] = { /* Beholder Intl. Ltd. 2008 */ /*Dmitry Belimov */ @@ -4173,15 +4267,211 @@ struct saa7134_board saa7134_boards[] = { .gpio = 0x000A8000, }, }, - [SAA7134_BOARD_BEHOLD_607_9FM] = { + [SAA7134_BOARD_BEHOLD_607FM_MK3] = { + /* Andrey Melnikoff */ + .name = "Beholder BeholdTV 607 FM", + .audio_clock = 0x00187de7, + .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .tda9887_conf = TDA9887_PRESENT, + .inputs = {{ + .name = name_tv, + .vmux = 3, + .amux = TV, + .tv = 1, + }, { + .name = name_comp1, + .vmux = 1, + .amux = LINE1, + }, { + .name = name_svideo, + .vmux = 8, + .amux = LINE1, + } }, + .radio = { + .name = name_radio, + .amux = LINE2, + }, + }, + [SAA7134_BOARD_BEHOLD_609FM_MK3] = { /* Andrey Melnikoff */ - .name = "Beholder BeholdTV 607 / BeholdTV 609", + .name = "Beholder BeholdTV 609 FM", .audio_clock = 0x00187de7, .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, .radio_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .tda9887_conf = TDA9887_PRESENT, + .inputs = {{ + .name = name_tv, + .vmux = 3, + .amux = TV, + .tv = 1, + }, { + .name = name_comp1, + .vmux = 1, + .amux = LINE1, + }, { + .name = name_svideo, + .vmux = 8, + .amux = LINE1, + } }, + .radio = { + .name = name_radio, + .amux = LINE2, + }, + }, + [SAA7134_BOARD_BEHOLD_607FM_MK5] = { + /* Andrey Melnikoff */ + .name = "Beholder BeholdTV 607 FM", + .audio_clock = 0x00187de7, + .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, /* FIXME to MK5 */ + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .tda9887_conf = TDA9887_PRESENT, + .inputs = {{ + .name = name_tv, + .vmux = 3, + .amux = TV, + .tv = 1, + }, { + .name = name_comp1, + .vmux = 1, + .amux = LINE1, + }, { + .name = name_svideo, + .vmux = 8, + .amux = LINE1, + } }, + .radio = { + .name = name_radio, + .amux = LINE2, + }, + }, + [SAA7134_BOARD_BEHOLD_609FM_MK5] = { + /* Andrey Melnikoff */ + .name = "Beholder BeholdTV 609 FM", + .audio_clock = 0x00187de7, + .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, /* FIXME to MK5 */ + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .tda9887_conf = TDA9887_PRESENT, + .inputs = {{ + .name = name_tv, + .vmux = 3, + .amux = TV, + .tv = 1, + }, { + .name = name_comp1, + .vmux = 1, + .amux = LINE1, + }, { + .name = name_svideo, + .vmux = 8, + .amux = LINE1, + } }, + .radio = { + .name = name_radio, + .amux = LINE2, + }, + }, + [SAA7134_BOARD_BEHOLD_607RDS_MK3] = { + /* Andrey Melnikoff */ + .name = "Beholder BeholdTV 607 RDS", + .audio_clock = 0x00187de7, + .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .tda9887_conf = TDA9887_PRESENT, + .inputs = {{ + .name = name_tv, + .vmux = 3, + .amux = TV, + .tv = 1, + }, { + .name = name_comp1, + .vmux = 1, + .amux = LINE1, + }, { + .name = name_svideo, + .vmux = 8, + .amux = LINE1, + } }, + .radio = { + .name = name_radio, + .amux = LINE2, + }, + }, + [SAA7134_BOARD_BEHOLD_609RDS_MK3] = { + /* Andrey Melnikoff */ + .name = "Beholder BeholdTV 609 RDS", + .audio_clock = 0x00187de7, + .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .tda9887_conf = TDA9887_PRESENT, + .inputs = {{ + .name = name_tv, + .vmux = 3, + .amux = TV, + .tv = 1, + }, { + .name = name_comp1, + .vmux = 1, + .amux = LINE1, + }, { + .name = name_svideo, + .vmux = 8, + .amux = LINE1, + } }, + .radio = { + .name = name_radio, + .amux = LINE2, + }, + }, + [SAA7134_BOARD_BEHOLD_607RDS_MK5] = { + /* Andrey Melnikoff */ + .name = "Beholder BeholdTV 607 RDS", + .audio_clock = 0x00187de7, + .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, /* FIXME to MK5 */ + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .tda9887_conf = TDA9887_PRESENT, + .inputs = {{ + .name = name_tv, + .vmux = 3, + .amux = TV, + .tv = 1, + }, { + .name = name_comp1, + .vmux = 1, + .amux = LINE1, + }, { + .name = name_svideo, + .vmux = 8, + .amux = LINE1, + } }, + .radio = { + .name = name_radio, + .amux = LINE2, + }, + }, + [SAA7134_BOARD_BEHOLD_609RDS_MK5] = { + /* Andrey Melnikoff */ + .name = "Beholder BeholdTV 609 RDS", + .audio_clock = 0x00187de7, + .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, /* FIXME to MK5 */ + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .tda9887_conf = TDA9887_PRESENT, .inputs = {{ .name = name_tv, .vmux = 3, @@ -4281,8 +4571,7 @@ struct saa7134_board saa7134_boards[] = { /* Beholder Intl. Ltd. Dmitry Belimov */ .name = "Beholder BeholdTV M6 Extra", .audio_clock = 0x00187de7, - /* FIXME: Must be PHILIPS_FM1216ME_MK5*/ - .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, + .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, /* FIXME to MK5 */ .radio_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, @@ -5766,18 +6055,12 @@ struct pci_device_id saa7134_pci_tbl[] = { .subvendor = 0x0000, .subdevice = 0x4090, .driver_data = SAA7134_BOARD_BEHOLD_409, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7130, - .subvendor = 0x0000, - .subdevice = 0x5051, - .driver_data = SAA7134_BOARD_BEHOLD_505FM, },{ .vendor = PCI_VENDOR_ID_PHILIPS, .device = PCI_DEVICE_ID_PHILIPS_SAA7130, .subvendor = 0x0000, .subdevice = 0x505B, - .driver_data = SAA7134_BOARD_BEHOLD_505FM, + .driver_data = SAA7134_BOARD_BEHOLD_505RDS, },{ .vendor = PCI_VENDOR_ID_PHILIPS, .device = PCI_DEVICE_ID_PHILIPS_SAA7130, @@ -5789,13 +6072,13 @@ struct pci_device_id saa7134_pci_tbl[] = { .device = PCI_DEVICE_ID_PHILIPS_SAA7133, .subvendor = 0x0000, .subdevice = 0x5071, - .driver_data = SAA7134_BOARD_BEHOLD_507_9FM, + .driver_data = SAA7134_BOARD_BEHOLD_507RDS_MK3, },{ .vendor = PCI_VENDOR_ID_PHILIPS, .device = PCI_DEVICE_ID_PHILIPS_SAA7133, .subvendor = 0x0000, .subdevice = 0x507B, - .driver_data = SAA7134_BOARD_BEHOLD_507_9FM, + .driver_data = SAA7134_BOARD_BEHOLD_507RDS_MK5, },{ .vendor = PCI_VENDOR_ID_PHILIPS, .device = PCI_DEVICE_ID_PHILIPS_SAA7134, @@ -5819,49 +6102,49 @@ struct pci_device_id saa7134_pci_tbl[] = { .device = PCI_DEVICE_ID_PHILIPS_SAA7134, .subvendor = 0x5ace, .subdevice = 0x6070, - .driver_data = SAA7134_BOARD_BEHOLD_607_9FM, + .driver_data = SAA7134_BOARD_BEHOLD_607FM_MK3, },{ .vendor = PCI_VENDOR_ID_PHILIPS, .device = PCI_DEVICE_ID_PHILIPS_SAA7134, .subvendor = 0x5ace, .subdevice = 0x6071, - .driver_data = SAA7134_BOARD_BEHOLD_607_9FM, + .driver_data = SAA7134_BOARD_BEHOLD_607FM_MK5, },{ .vendor = PCI_VENDOR_ID_PHILIPS, .device = PCI_DEVICE_ID_PHILIPS_SAA7134, .subvendor = 0x5ace, .subdevice = 0x6072, - .driver_data = SAA7134_BOARD_BEHOLD_607_9FM, + .driver_data = SAA7134_BOARD_BEHOLD_607RDS_MK3, },{ .vendor = PCI_VENDOR_ID_PHILIPS, .device = PCI_DEVICE_ID_PHILIPS_SAA7134, .subvendor = 0x5ace, .subdevice = 0x6073, - .driver_data = SAA7134_BOARD_BEHOLD_607_9FM, + .driver_data = SAA7134_BOARD_BEHOLD_607RDS_MK5, },{ .vendor = PCI_VENDOR_ID_PHILIPS, .device = PCI_DEVICE_ID_PHILIPS_SAA7133, .subvendor = 0x5ace, .subdevice = 0x6090, - .driver_data = SAA7134_BOARD_BEHOLD_607_9FM, + .driver_data = SAA7134_BOARD_BEHOLD_609FM_MK3, },{ .vendor = PCI_VENDOR_ID_PHILIPS, .device = PCI_DEVICE_ID_PHILIPS_SAA7133, .subvendor = 0x5ace, .subdevice = 0x6091, - .driver_data = SAA7134_BOARD_BEHOLD_607_9FM, + .driver_data = SAA7134_BOARD_BEHOLD_609FM_MK5, },{ .vendor = PCI_VENDOR_ID_PHILIPS, .device = PCI_DEVICE_ID_PHILIPS_SAA7133, .subvendor = 0x5ace, .subdevice = 0x6092, - .driver_data = SAA7134_BOARD_BEHOLD_607_9FM, + .driver_data = SAA7134_BOARD_BEHOLD_609RDS_MK3, },{ .vendor = PCI_VENDOR_ID_PHILIPS, .device = PCI_DEVICE_ID_PHILIPS_SAA7133, .subvendor = 0x5ace, .subdevice = 0x6093, - .driver_data = SAA7134_BOARD_BEHOLD_607_9FM, + .driver_data = SAA7134_BOARD_BEHOLD_609RDS_MK5, },{ .vendor = PCI_VENDOR_ID_PHILIPS, .device = PCI_DEVICE_ID_PHILIPS_SAA7133, @@ -6325,7 +6608,10 @@ int saa7134_board_init1(struct saa7134_dev *dev) case SAA7134_BOARD_BEHOLD_407FM: case SAA7134_BOARD_BEHOLD_409: case SAA7134_BOARD_BEHOLD_505FM: + case SAA7134_BOARD_BEHOLD_505RDS: case SAA7134_BOARD_BEHOLD_507_9FM: + case SAA7134_BOARD_BEHOLD_507RDS_MK3: + case SAA7134_BOARD_BEHOLD_507RDS_MK5: case SAA7134_BOARD_GENIUS_TVGO_A11MCE: case SAA7134_BOARD_REAL_ANGEL_220: case SAA7134_BOARD_KWORLD_PLUS_TV_ANALOG: @@ -6450,7 +6736,14 @@ int saa7134_board_init1(struct saa7134_dev *dev) case SAA7134_BOARD_UPMOST_PURPLE_TV: case SAA7134_BOARD_MSI_TVATANYWHERE_PLUS: case SAA7134_BOARD_HAUPPAUGE_HVR1110: - case SAA7134_BOARD_BEHOLD_607_9FM: + case SAA7134_BOARD_BEHOLD_607FM_MK3: + case SAA7134_BOARD_BEHOLD_607FM_MK5: + case SAA7134_BOARD_BEHOLD_609FM_MK3: + case SAA7134_BOARD_BEHOLD_609FM_MK5: + case SAA7134_BOARD_BEHOLD_607RDS_MK3: + case SAA7134_BOARD_BEHOLD_607RDS_MK5: + case SAA7134_BOARD_BEHOLD_609RDS_MK3: + case SAA7134_BOARD_BEHOLD_609RDS_MK5: case SAA7134_BOARD_BEHOLD_M6: case SAA7134_BOARD_BEHOLD_M63: case SAA7134_BOARD_BEHOLD_M6_EXTRA: diff --git a/linux/drivers/media/video/saa7134/saa7134-input.c b/linux/drivers/media/video/saa7134/saa7134-input.c index 87dc1b9bb..80a4cc23d 100644 --- a/linux/drivers/media/video/saa7134/saa7134-input.c +++ b/linux/drivers/media/video/saa7134/saa7134-input.c @@ -507,7 +507,10 @@ int saa7134_input_init1(struct saa7134_dev *dev) case SAA7134_BOARD_BEHOLD_407FM: case SAA7134_BOARD_BEHOLD_409: case SAA7134_BOARD_BEHOLD_505FM: + case SAA7134_BOARD_BEHOLD_505RDS: case SAA7134_BOARD_BEHOLD_507_9FM: + case SAA7134_BOARD_BEHOLD_507RDS_MK3: + case SAA7134_BOARD_BEHOLD_507RDS_MK5: ir_codes = ir_codes_manli; mask_keycode = 0x003f00; mask_keyup = 0x004000; @@ -718,7 +721,14 @@ void saa7134_set_i2c_ir(struct saa7134_dev *dev, struct IR_i2c *ir) ir->get_key = get_key_hvr1110; ir->ir_codes = ir_codes_hauppauge_new; break; - case SAA7134_BOARD_BEHOLD_607_9FM: + case SAA7134_BOARD_BEHOLD_607FM_MK3: + case SAA7134_BOARD_BEHOLD_607FM_MK5: + case SAA7134_BOARD_BEHOLD_609FM_MK3: + case SAA7134_BOARD_BEHOLD_609FM_MK5: + case SAA7134_BOARD_BEHOLD_607RDS_MK3: + case SAA7134_BOARD_BEHOLD_607RDS_MK5: + case SAA7134_BOARD_BEHOLD_609RDS_MK3: + case SAA7134_BOARD_BEHOLD_609RDS_MK5: case SAA7134_BOARD_BEHOLD_M6: case SAA7134_BOARD_BEHOLD_M63: case SAA7134_BOARD_BEHOLD_M6_EXTRA: diff --git a/linux/drivers/media/video/saa7134/saa7134.h b/linux/drivers/media/video/saa7134/saa7134.h index bac170935..d961e0861 100644 --- a/linux/drivers/media/video/saa7134/saa7134.h +++ b/linux/drivers/media/video/saa7134/saa7134.h @@ -253,7 +253,7 @@ struct saa7134_format { #define SAA7134_BOARD_BEHOLD_505FM 126 #define SAA7134_BOARD_BEHOLD_507_9FM 127 #define SAA7134_BOARD_BEHOLD_COLUMBUS_TVFM 128 -#define SAA7134_BOARD_BEHOLD_607_9FM 129 +#define SAA7134_BOARD_BEHOLD_607FM_MK3 129 #define SAA7134_BOARD_BEHOLD_M6 130 #define SAA7134_BOARD_TWINHAN_DTV_DVB_3056 131 #define SAA7134_BOARD_GENIUS_TVGO_A11MCE 132 @@ -283,6 +283,16 @@ struct saa7134_format { #define SAA7134_BOARD_HAUPPAUGE_HVR1110R3 156 #define SAA7134_BOARD_AVERMEDIA_STUDIO_507UA 157 #define SAA7134_BOARD_AVERMEDIA_CARDBUS_501 158 +#define SAA7134_BOARD_BEHOLD_505RDS 159 +#define SAA7134_BOARD_BEHOLD_507RDS_MK3 160 +#define SAA7134_BOARD_BEHOLD_507RDS_MK5 161 +#define SAA7134_BOARD_BEHOLD_607FM_MK5 162 +#define SAA7134_BOARD_BEHOLD_609FM_MK3 163 +#define SAA7134_BOARD_BEHOLD_609FM_MK5 164 +#define SAA7134_BOARD_BEHOLD_607RDS_MK3 165 +#define SAA7134_BOARD_BEHOLD_607RDS_MK5 166 +#define SAA7134_BOARD_BEHOLD_609RDS_MK3 167 +#define SAA7134_BOARD_BEHOLD_609RDS_MK5 168 #define SAA7134_MAXBOARDS 32 #define SAA7134_INPUT_MAX 8 -- cgit v1.2.3 From 44d5135c991fe67dafe83b30bbadddd586a63fe4 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Thu, 23 Apr 2009 18:52:27 +0200 Subject: gspca - ov534: Don't discard the images when no UVC EOF. From: Jean-Francois Moine A new image may start without any UVC EOF in the last packet of the previous image. Priority: normal Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/ov534.c | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/ov534.c b/linux/drivers/media/video/gspca/ov534.c index abb8ea3db..1e00e46b1 100644 --- a/linux/drivers/media/video/gspca/ov534.c +++ b/linux/drivers/media/video/gspca/ov534.c @@ -890,18 +890,16 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, struct gspca_frame *frame, /* If PTS or FID has changed, start a new frame. */ if (this_pts != sd->last_pts || this_fid != sd->last_fid) { - gspca_frame_add(gspca_dev, FIRST_PACKET, frame, - NULL, 0); + if (gspca_dev->last_packet_type == INTER_PACKET) + frame = gspca_frame_add(gspca_dev, + LAST_PACKET, frame, + NULL, 0); sd->last_pts = this_pts; sd->last_fid = this_fid; - } - - /* Add the data from this payload */ - gspca_frame_add(gspca_dev, INTER_PACKET, frame, + gspca_frame_add(gspca_dev, FIRST_PACKET, frame, data + 12, len - 12); - /* If this packet is marked as EOF, end the frame */ - if (data[1] & UVC_STREAM_EOF) { + } else if (data[1] & UVC_STREAM_EOF) { sd->last_pts = 0; if (frame->data_end - frame->data != @@ -909,11 +907,16 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, struct gspca_frame *frame, PDEBUG(D_PACK, "short frame"); goto discard; } - frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame, - NULL, 0); + data + 12, len - 12); + } else { + + /* Add the data from this payload */ + gspca_frame_add(gspca_dev, INTER_PACKET, frame, + data + 12, len - 12); } + /* Done this payload */ goto scan_next; -- cgit v1.2.3 From b82ff2ac55f0e0ab4af0426465514aced6c5db24 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Thu, 23 Apr 2009 19:33:00 +0200 Subject: gspca - spca500 and sunplus: Change the 0x00 insertion mechanism. From: Jean-Francois Moine The new mechanism does not use any temporary buffer. Priority: normal Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/spca500.c | 33 ++++++++++++------------------- linux/drivers/media/video/gspca/sunplus.c | 33 ++++++++++++------------------- 2 files changed, 26 insertions(+), 40 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/spca500.c b/linux/drivers/media/video/gspca/spca500.c index 8cfb7cad9..9717da6af 100644 --- a/linux/drivers/media/video/gspca/spca500.c +++ b/linux/drivers/media/video/gspca/spca500.c @@ -32,9 +32,6 @@ MODULE_LICENSE("GPL"); struct sd { struct gspca_dev gspca_dev; /* !! must be the first item */ - __u8 packet[ISO_MAX_SIZE + 128]; - /* !! no more than 128 ff in an ISO packet */ - unsigned char brightness; unsigned char contrast; unsigned char colors; @@ -923,7 +920,6 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, { struct sd *sd = (struct sd *) gspca_dev; int i; - __u8 *s, *d; static __u8 ffd9[] = {0xff, 0xd9}; /* frames are jpeg 4.1.1 without 0xff escape */ @@ -947,22 +943,19 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, } /* add 0x00 after 0xff */ - for (i = len; --i >= 0; ) - if (data[i] == 0xff) - break; - if (i < 0) { /* no 0xff */ - gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len); - return; - } - s = data; - d = sd->packet; - for (i = 0; i < len; i++) { - *d++ = *s++; - if (s[-1] == 0xff) - *d++ = 0x00; - } - gspca_frame_add(gspca_dev, INTER_PACKET, frame, - sd->packet, d - sd->packet); + i = 0; + do { + if (data[i] == 0xff) { + gspca_frame_add(gspca_dev, INTER_PACKET, frame, + data, i + 1); + len -= i; + data += i; + *data = 0x00; + i = 0; + } + i++; + } while (i < len); + gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len); } static void setbrightness(struct gspca_dev *gspca_dev) diff --git a/linux/drivers/media/video/gspca/sunplus.c b/linux/drivers/media/video/gspca/sunplus.c index 428b1e2b7..16bc65dc7 100644 --- a/linux/drivers/media/video/gspca/sunplus.c +++ b/linux/drivers/media/video/gspca/sunplus.c @@ -32,9 +32,6 @@ MODULE_LICENSE("GPL"); struct sd { struct gspca_dev gspca_dev; /* !! must be the first item */ - __u8 packet[ISO_MAX_SIZE + 128]; - /* !! no more than 128 ff in an ISO packet */ - unsigned char brightness; unsigned char contrast; unsigned char colors; @@ -1134,7 +1131,6 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, { struct sd *sd = (struct sd *) gspca_dev; int i, sof = 0; - unsigned char *s, *d; static unsigned char ffd9[] = {0xff, 0xd9}; /* frames are jpeg 4.1.1 without 0xff escape */ @@ -1208,22 +1204,19 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, } /* add 0x00 after 0xff */ - for (i = len; --i >= 0; ) - if (data[i] == 0xff) - break; - if (i < 0) { /* no 0xff */ - gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len); - return; - } - s = data; - d = sd->packet; - for (i = 0; i < len; i++) { - *d++ = *s++; - if (s[-1] == 0xff) - *d++ = 0x00; - } - gspca_frame_add(gspca_dev, INTER_PACKET, frame, - sd->packet, d - sd->packet); + i = 0; + do { + if (data[i] == 0xff) { + gspca_frame_add(gspca_dev, INTER_PACKET, frame, + data, i + 1); + len -= i; + data += i; + *data = 0x00; + i = 0; + } + i++; + } while (i < len); + gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len); } static void setbrightness(struct gspca_dev *gspca_dev) -- cgit v1.2.3 From a904ed23d4d6c515b5a18868ed34e021e23e7a0a Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Thu, 23 Apr 2009 21:56:41 +0400 Subject: Fixes: * Cut revision was read too late * Missing increment * wrong return value * mismatched entries From: Andreas Regel Signed-off-by: Andreas Regel Signed-off-by: Manu Abraham --- linux/drivers/media/dvb/frontends/stv090x.c | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/frontends/stv090x.c b/linux/drivers/media/dvb/frontends/stv090x.c index 4637f9890..20efaf685 100644 --- a/linux/drivers/media/dvb/frontends/stv090x.c +++ b/linux/drivers/media/dvb/frontends/stv090x.c @@ -2728,6 +2728,7 @@ static int stv090x_get_loop_params(struct stv090x_state *state, s32 *freq_inc, s srate = state->srate; car_max = state->search_range / 1000; + car_max += car_max / 10; car_max = 65536 * (car_max / 2); car_max /= (state->mclk / 1000); @@ -2788,6 +2789,7 @@ static int stv090x_chk_signal(struct stv090x_state *state) offst_car = STV090x_READ_DEMOD(state, CFR2) << 8; offst_car |= STV090x_READ_DEMOD(state, CFR1); + offst_car = comp2(offst_car, 16); agc2 = STV090x_READ_DEMOD(state, AGC2I1) << 8; agc2 |= STV090x_READ_DEMOD(state, AGC2I0); @@ -2850,6 +2852,9 @@ static int stv090x_search_car_loop(struct stv090x_state *state, s32 inc, s32 tim STV090x_SETFIELD_Px(reg, RST_HWARE_FIELD, 0x1); if (STV090x_WRITE_DEMOD(state, TSCFGH, reg) < 0) goto err; + STV090x_SETFIELD_Px(reg, RST_HWARE_FIELD, 0x0); + if (STV090x_WRITE_DEMOD(state, TSCFGH, reg) < 0) + goto err; } if (zigzag) { @@ -2861,6 +2866,8 @@ static int stv090x_search_car_loop(struct stv090x_state *state, s32 inc, s32 tim offst_freq += 2 * inc; } + cpt_step++; + lock = stv090x_get_dmdlock(state, timeout); no_signal = stv090x_chk_signal(state); @@ -2934,7 +2941,7 @@ static int stv090x_sw_algo(struct stv090x_state *state) if (STV090x_WRITE_DEMOD(state, CORRELABS, 0x68) < 0) goto err; } - if (STV090x_WRITE_DEMOD(state, DMDCFGMD, 0x69) < 0) + if (STV090x_WRITE_DEMOD(state, DMDCFGMD, 0xc9) < 0) goto err; zigzag = 0; break; @@ -3095,7 +3102,7 @@ static enum stv090x_signal_state stv090x_get_sig_params(struct stv090x_state *st if (state->algo == STV090x_BLIND_SEARCH) { tmg = STV090x_READ_DEMOD(state, TMGREG2); STV090x_WRITE_DEMOD(state, SFRSTEP, 0x5c); - while ((i <= 50) && (!tmg) && (tmg != 0xff)) { + while ((i <= 50) && (tmg != 0) && (tmg != 0xff)) { tmg = STV090x_READ_DEMOD(state, TMGREG2); msleep(5); i += 5; @@ -3132,7 +3139,7 @@ static enum stv090x_signal_state stv090x_get_sig_params(struct stv090x_state *st stv090x_i2c_gate_ctrl(fe, 0); if (abs(offst_freq) <= ((state->search_range / 2000) + 500)) - return STV090x_RANGEOK; + return STV090x_RANGEOK; else if (abs(offst_freq) <= (stv090x_car_width(state->srate, state->rolloff) / 2000)) return STV090x_RANGEOK; else @@ -3354,8 +3361,8 @@ static int stv090x_optimize_track(struct stv090x_state *state) case STV090x_DVBS2: reg = STV090x_READ_DEMOD(state, DMDCFGMD); - STV090x_SETFIELD_Px(reg, DVBS1_ENABLE_FIELD, 1); - STV090x_SETFIELD_Px(reg, DVBS2_ENABLE_FIELD, 0); + STV090x_SETFIELD_Px(reg, DVBS1_ENABLE_FIELD, 0); + STV090x_SETFIELD_Px(reg, DVBS2_ENABLE_FIELD, 1); if (STV090x_WRITE_DEMOD(state, DMDCFGMD, reg) < 0) goto err; if (STV090x_WRITE_DEMOD(state, ACLC, 0) < 0) @@ -3900,7 +3907,7 @@ static enum stv090x_signal_state stv090x_algo(struct stv090x_state *state) if ((signal_state == STV090x_NODATA) && (!no_signal)) { if (state->dev_ver <= 0x11) { reg = STV090x_READ_DEMOD(state, DMDSTATE); - if (((STV090x_GETFIELD_Px(reg, HEADER_MODE_FIELD)) == STV090x_DVBS2) && (state->inversion == INVERSION_AUTO)) + if (((STV090x_GETFIELD_Px(reg, HEADER_MODE_FIELD)) == STV090x_DVBS1) && (state->inversion == INVERSION_AUTO)) signal_state = stv090x_acq_fixs1(state); } } @@ -3924,7 +3931,7 @@ static enum dvbfe_search stv090x_search(struct dvb_frontend *fe, struct dvb_fron state->fec = STV090x_PRERR; state->search_range = 2000000; - if (!stv090x_algo(state)) { + if (stv090x_algo(state) == STV090x_RANGEOK) { dprintk(FE_DEBUG, 1, "Search success!"); return DVBFE_ALGO_SEARCH_SUCCESS; } else { @@ -4747,12 +4754,13 @@ static int stv090x_setup(struct dvb_frontend *fe) msleep(5); /* write initval */ + dprintk(FE_DEBUG, 1, "Setting up initial values"); for (i = 0; i < t1_size; i++) { - dprintk(FE_DEBUG, 1, "Setting up initial values"); if (stv090x_write_reg(state, stv090x_initval[i].addr, stv090x_initval[i].data) < 0) goto err; } + state->dev_ver = stv090x_read_reg(state, STV090x_MID); if (state->dev_ver >= 0x20) { if (stv090x_write_reg(state, STV090x_TSGENERAL, 0x0c) < 0) goto err; @@ -4845,7 +4853,6 @@ struct dvb_frontend *stv090x_attach(const struct stv090x_config *config, dprintk(FE_ERROR, 1, "Error waking device"); goto error; } - state->dev_ver = stv090x_read_reg(state, STV090x_MID); dprintk(FE_ERROR, 1, "Attaching %s demodulator(%d) Cut=0x%02x\n", state->device == STV0900 ? "STV0900" : "STV0903", -- cgit v1.2.3 From 646f510d1100149a70483eadcda550da9c8fa551 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Thu, 23 Apr 2009 21:57:24 +0400 Subject: Fixes Some register definitions From: Andreas Regel Signed-off-by: Andreas Regel Signed-off-by: Manu Abraham --- linux/drivers/media/dvb/frontends/stv090x_reg.h | 28 ++++++++++++------------- 1 file changed, 14 insertions(+), 14 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/frontends/stv090x_reg.h b/linux/drivers/media/dvb/frontends/stv090x_reg.h index 0dff56d4e..55737074e 100644 --- a/linux/drivers/media/dvb/frontends/stv090x_reg.h +++ b/linux/drivers/media/dvb/frontends/stv090x_reg.h @@ -470,7 +470,7 @@ #define STV090x_FSKTCTRL 0xf175 #define STV090x_OFFST_FSKT_EN_SGN_FIELD 6 -#define STV090x_WIDTH_FSKT_EN_SGN__FIELD 1 +#define STV090x_WIDTH_FSKT_EN_SGN_FIELD 1 #define STV090x_OFFST_FSKT_MOD_SGN_FIELD 5 #define STV090x_WIDTH_FSKT_MOD_SGN_FIELD 1 #define STV090x_OFFST_FSKT_MOD_EN_FIELD 2 @@ -616,7 +616,7 @@ #define STV090x_OFFST_Px_CONT_TONE_FIELD 4 #define STV090x_WIDTH_Px_CONT_TONE_FIELD 1 #define STV090x_OFFST_Px_FIFO_4BREADY_FIELD 3 -#define STV090x_WIDTH_Px_FIFO_4BREADYFIELD 2 +#define STV090x_WIDTH_Px_FIFO_4BREADY_FIELD 2 #define STV090x_OFFST_Px_FIFO_EMPTY_FIELD 2 #define STV090x_WIDTH_Px_FIFO_EMPTY_FIELD 1 #define STV090x_OFFST_Px_ABORT_DISRX_FIELD 0 @@ -1385,8 +1385,8 @@ #define STV090x_WIDTH_Px_CAR2S2_16A_ALPH_E_FIELD 4 #define STV090x_Px_ACLC2S232A(__x) (0xf499 - (__x - 1) * 0x200) -#define STV090x_P1_ACLC2S232A STV090x_Px_ACLC2S216A(1) -#define STV090x_P2_ACLC2S232A STV090x_Px_ACLC2S216A(2) +#define STV090x_P1_ACLC2S232A STV090x_Px_ACLC2S232A(1) +#define STV090x_P2_ACLC2S232A STV090x_Px_ACLC2S232A(2) #define STV090x_OFFST_Px_CAR2S2_32A_ALPH_M_FIELD 4 #define STV090x_WIDTH_Px_CAR2S2_32A_ALPH_M_FIELD 2 #define STV090x_OFFST_Px_CAR2S2_32A_ALPH_E_FIELD 0 @@ -1720,7 +1720,7 @@ #define STV090x_Px_VTH34(__x) (0xf536 - (__x - 1) * 0x200) #define STV090x_P1_VTH34 STV090x_Px_VTH34(1) - #define STV090x_P2_VTH34 STV090x_Px_VTH34(2) +#define STV090x_P2_VTH34 STV090x_Px_VTH34(2) #define STV090x_OFFST_Px_VTH34_FIELD 0 #define STV090x_WIDTH_Px_VTH34_FIELD 8 @@ -1763,7 +1763,7 @@ #define STV090x_WIDTH_Px_E7_8VIT_FIELD 1 #define STV090x_OFFST_Px_E6_7VIT_FIELD 4 #define STV090x_WIDTH_Px_E6_7VIT_FIELD 1 -#define STV090x_OFFST_Px_E5_6VIT_FIELD_ 3 +#define STV090x_OFFST_Px_E5_6VIT_FIELD 3 #define STV090x_WIDTH_Px_E5_6VIT_FIELD 1 #define STV090x_OFFST_Px_E3_4VIT_FIELD 2 #define STV090x_WIDTH_Px_E3_4VIT_FIELD 1 @@ -1856,13 +1856,13 @@ #define STV090x_OFFST_Px_UNLCK_THRESH_FIELD 4 #define STV090x_WIDTH_Px_UNLCK_THRESH_FIELD 4 #define STV090x_OFFST_Px_DELIN_LCK_THRESH_FIELD 0 -#define STV090x_WIDTH_Px_DELIN_LCK_THRESH__FIELD 4 +#define STV090x_WIDTH_Px_DELIN_LCK_THRESH_FIELD 4 #define STV090x_Px_ISIENTRY(__x) (0xf55e - (__x - 1) * 0x200) #define STV090x_P1_ISIENTRY STV090x_Px_ISIENTRY(1) #define STV090x_P2_ISIENTRY STV090x_Px_ISIENTRY(2) #define STV090x_OFFST_Px_ISI_ENTRY_FIELD 0 -#define STV090x_WIDTH_Px_ISI_ENTRY__FIELD 8 +#define STV090x_WIDTH_Px_ISI_ENTRY_FIELD 8 #define STV090x_Px_ISIBITENA(__x) (0xf55f - (__x - 1) * 0x200) #define STV090x_P1_ISIBITENA STV090x_Px_ISIBITENA(1) @@ -1968,7 +1968,7 @@ #define STV090x_OFFST_NBITER_STOP_CRIT_FIELD 0 #define STV090x_WIDTH_NBITER_STOP_CRIT_FIELD 4 -#define STV090x_GAINLLR_NFx(__x) (0xFA43 + (__x - 4) * 0x1) +#define STV090x_GAINLLR_NFx(__x) (0xFA43 + (__x - 4) * 0x1) #define STV090x_GAINLLR_NF4 STV090x_GAINLLR_NFx(4) #define STV090x_OFFST_GAINLLR_NF_QP_1_2_FIELD 0 #define STV090x_WIDTH_GAINLLR_NF_QP_1_2_FIELD 7 @@ -1999,7 +1999,7 @@ #define STV090x_GAINLLR_NF11 STV090x_GAINLLR_NFx(11) #define STV090x_OFFST_GAINLLR_NF_QP_9_10_FIELD 0 -#define STV090x_WIDTH_GAINLLR_NF_QP_9_10IELD 7 +#define STV090x_WIDTH_GAINLLR_NF_QP_9_10_FIELD 7 #define STV090x_GAINLLR_NF12 STV090x_GAINLLR_NFx(12) #define STV090x_OFFST_GAINLLR_NF_8P_3_5_FIELD 0 @@ -2079,7 +2079,7 @@ #define STV090x_OFFST_Px_TSFIFO_PERMDATA_FIELD 5 #define STV090x_WIDTH_Px_TSFIFO_PERMDATA_FIELD 1 #define STV090x_OFFST_Px_TSFIFO_INVDATA_FIELD 0 -#define STV090x_WIDTH_Px_TSFIFO_INVDATA__FIELD 1 +#define STV090x_WIDTH_Px_TSFIFO_INVDATA_FIELD 1 #define STV090x_Px_TSCFGL(__x) (0xF574 - (__x - 1) * 0x200) #define STV090x_P1_TSCFGL STV090x_Px_TSCFGL(1) @@ -2089,7 +2089,7 @@ #define STV090x_OFFST_Px_BCHERROR_MODE_FIELD 4 #define STV090x_WIDTH_Px_BCHERROR_MODE_FIELD 2 #define STV090x_OFFST_Px_TSFIFO_NSGNL2DATA_FIELD 3 -#define STV090x_WIDTH_Px_TSFIFO_NSGNL2DATA__FIELD 1 +#define STV090x_WIDTH_Px_TSFIFO_NSGNL2DATA_FIELD 1 #define STV090x_OFFST_Px_TSFIFO_EMBINDVB_FIELD 2 #define STV090x_WIDTH_Px_TSFIFO_EMBINDVB_FIELD 1 #define STV090x_OFFST_Px_TSFIFO_DPUNACT_FIELD 1 @@ -2150,7 +2150,7 @@ #define STV090x_Px_ERRCNT12(__x) (0xF599 - (__x - 1) * 0x200) #define STV090x_P1_ERRCNT12 STV090x_Px_ERRCNT12(1) #define STV090x_P2_ERRCNT12 STV090x_Px_ERRCNT12(2) -#define STV090x_OFFST_Px_ERRCNT1_OLDVALUE__FIELD 7 +#define STV090x_OFFST_Px_ERRCNT1_OLDVALUE_FIELD 7 #define STV090x_WIDTH_Px_ERRCNT1_OLDVALUE_FIELD 1 #define STV090x_OFFST_Px_ERR_CNT12_FIELD 0 #define STV090x_WIDTH_Px_ERR_CNT12_FIELD 7 @@ -2249,7 +2249,7 @@ #define STV090x_P1_FBERCPT4 STV090x_Px_FBERCPT4(1) #define STV090x_P2_FBERCPT4 STV090x_Px_FBERCPT4(2) #define STV090x_OFFST_Px_FBERMETER_CPT_FIELD 0 -#define STV090x_WIDTH_Px_BERMETER_CPT_FIELD 8 +#define STV090x_WIDTH_Px_FBERMETER_CPT_FIELD 8 #define STV090x_Px_FBERCPT3(__x) (0xF5A9 - (__x - 1) * 0x200) #define STV090x_P1_FBERCPT3 STV090x_Px_FBERCPT3(1) -- cgit v1.2.3 From fefe9f0c6dc0858fd05f26da9230beb27aba3663 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Thu, 23 Apr 2009 21:58:36 +0400 Subject: Fixes read_status to return 0 in case of no error From: Andreas Regel Signed-off-by: Andreas Regel Signed-off-by: Manu Abraham --- linux/drivers/media/dvb/frontends/stv090x.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/frontends/stv090x.c b/linux/drivers/media/dvb/frontends/stv090x.c index 20efaf685..0635f3355 100644 --- a/linux/drivers/media/dvb/frontends/stv090x.c +++ b/linux/drivers/media/dvb/frontends/stv090x.c @@ -3948,7 +3948,6 @@ static int stv090x_read_status(struct dvb_frontend *fe, enum fe_status *status) struct stv090x_state *state = fe->demodulator_priv; u32 reg; u8 search_state; - int locked = 0; reg = STV090x_READ_DEMOD(state, DMDSTATE); search_state = STV090x_GETFIELD_Px(reg, HEADER_MODE_FIELD); @@ -3958,7 +3957,7 @@ static int stv090x_read_status(struct dvb_frontend *fe, enum fe_status *status) case 1: /* first PLH detected */ default: dprintk(FE_DEBUG, 1, "Status: Unlocked (Searching ..)"); - locked = 0; + *status = 0; break; case 2: /* DVB-S2 mode */ @@ -3967,7 +3966,6 @@ static int stv090x_read_status(struct dvb_frontend *fe, enum fe_status *status) if (STV090x_GETFIELD_Px(reg, LOCK_DEFINITIF_FIELD)) { reg = STV090x_READ_DEMOD(state, TSSTATUS); if (STV090x_GETFIELD_Px(reg, TSFIFO_LINEOK_FIELD)) { - locked = 1; *status = FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK; } } @@ -3981,7 +3979,6 @@ static int stv090x_read_status(struct dvb_frontend *fe, enum fe_status *status) if (STV090x_GETFIELD_Px(reg, LOCKEDVIT_FIELD)) { reg = STV090x_READ_DEMOD(state, TSSTATUS); if (STV090x_GETFIELD_Px(reg, TSFIFO_LINEOK_FIELD)) { - locked = 1; *status = FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK; } } @@ -3989,7 +3986,7 @@ static int stv090x_read_status(struct dvb_frontend *fe, enum fe_status *status) break; } - return locked; + return 0; } static int stv090x_read_per(struct dvb_frontend *fe, u32 *per) @@ -4000,7 +3997,8 @@ static int stv090x_read_per(struct dvb_frontend *fe, u32 *per) u32 reg, h, m, l; enum fe_status status; - if (!stv090x_read_status(fe, &status)) { + stv090x_read_status(fe, &status); + if (!(status & FE_HAS_LOCK)) { *per = 1 << 23; /* Max PER */ } else { /* Counter 2 */ -- cgit v1.2.3 From ebd9024f2b351ec4874da20b73bbb6ea601b0702 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Thu, 23 Apr 2009 21:59:03 +0400 Subject: Fix missing wakeup in init From: Andreas Regel Signed-off-by: Andreas Regel Signed-off-by: Manu Abraham --- linux/drivers/media/dvb/frontends/stv090x.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/frontends/stv090x.c b/linux/drivers/media/dvb/frontends/stv090x.c index 0635f3355..28ab19c22 100644 --- a/linux/drivers/media/dvb/frontends/stv090x.c +++ b/linux/drivers/media/dvb/frontends/stv090x.c @@ -4665,6 +4665,11 @@ static int stv090x_init(struct dvb_frontend *fe) const struct stv090x_config *config = state->config; u32 reg; + if (stv090x_wakeup(fe) < 0) { + dprintk(FE_ERROR, 1, "Error waking device"); + goto err; + } + stv090x_ldpc_mode(state, state->demod_mode); reg = STV090x_READ_DEMOD(state, TNRCFG2); @@ -4678,6 +4683,8 @@ static int stv090x_init(struct dvb_frontend *fe) stv090x_i2c_gate_ctrl(fe, 1); + if (config->tuner_set_mode) + config->tuner_set_mode(fe, TUNER_WAKE); if (config->tuner_init) config->tuner_init(fe); -- cgit v1.2.3 From 23076fb0253b331e86009049488311da2fd762a7 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Thu, 23 Apr 2009 21:59:36 +0400 Subject: Use budget driver instead From: Andreas Regel Signed-off-by: Andreas Regel Signed-off-by: Manu Abraham --- linux/drivers/media/dvb/ttpci/budget-ci.c | 86 ------------------------------- linux/drivers/media/dvb/ttpci/budget.c | 85 ++++++++++++++++++++++++++++++ 2 files changed, 85 insertions(+), 86 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/ttpci/budget-ci.c b/linux/drivers/media/dvb/ttpci/budget-ci.c index 07fec975a..1b564eb79 100644 --- a/linux/drivers/media/dvb/ttpci/budget-ci.c +++ b/linux/drivers/media/dvb/ttpci/budget-ci.c @@ -57,9 +57,6 @@ #include "bsru6.h" #include "tda1002x.h" #include "tda827x.h" -#include "stv6110x.h" -#include "stv090x.h" -#include "isl6423.h" /* * Regarding DEBIADDR_IR: @@ -1357,44 +1354,6 @@ static struct stb6100_config tt3200_stb6100_config = { .refclock = 27000000, }; -static struct stv090x_config tt1600_stv090x_config = { - .device = STV0903, - .demod_mode = STV090x_SINGLE, - .clk_mode = STV090x_CLK_EXT, - - .xtal = 27000000, - .address = 0x68, - .ref_clk = 27000000, - - .ts1_mode = STV090x_TSMODE_PARALLEL_PUNCTURED, - .ts2_mode = STV090x_TSMODE_SERIAL_PUNCTURED, - - .repeater_level = STV090x_RPTLEVEL_16, - - .tuner_init = NULL, - .tuner_set_mode = NULL, - .tuner_set_frequency = NULL, - .tuner_get_frequency = NULL, - .tuner_set_bandwidth = NULL, - .tuner_get_bandwidth = NULL, - .tuner_set_bbgain = NULL, - .tuner_get_bbgain = NULL, - .tuner_set_refclk = NULL, - .tuner_get_status = NULL, -}; - -static struct stv6110x_config tt1600_stv6110x_config = { - .addr = 0x60, - .refclk = 27000000, -}; - -static struct isl6423_config tt1600_isl6423_config = { - .current_max = SEC_CURRENT_515m, - .curlim = SEC_CURRENT_LIM_ON, - .mod_extern = 1, - .addr = 0x08, -}; - static void frontend_init(struct budget_ci *budget_ci) { switch (budget_ci->budget.dev->pci->subsystem_device) { @@ -1514,49 +1473,6 @@ static void frontend_init(struct budget_ci *budget_ci) } break; - case 0x101c: { /* TT S2-1600 */ - struct stv6110x_devctl *ctl; - /* TODO! must verify with Andreas */ - saa7146_setgpio(budget_ci->budget.dev, 2, SAA7146_GPIO_OUTLO); - msleep(50); - saa7146_setgpio(budget_ci->budget.dev, 2, SAA7146_GPIO_OUTHI); - msleep(250); - - budget_ci->budget.dvb_frontend = dvb_attach(stv090x_attach, - &tt1600_stv090x_config, - &budget_ci->budget.i2c_adap, - STV090x_DEMODULATOR_0); - - if (budget_ci->budget.dvb_frontend) { - - ctl = dvb_attach(stv6110x_attach, - budget_ci->budget.dvb_frontend, - &tt1600_stv6110x_config, - &budget_ci->budget.i2c_adap); - - tt1600_stv090x_config.tuner_init = ctl->tuner_init; - tt1600_stv090x_config.tuner_set_mode = ctl->tuner_set_mode; - tt1600_stv090x_config.tuner_set_frequency = ctl->tuner_set_frequency; - tt1600_stv090x_config.tuner_get_frequency = ctl->tuner_get_frequency; - tt1600_stv090x_config.tuner_set_bandwidth = ctl->tuner_set_bandwidth; - tt1600_stv090x_config.tuner_get_bandwidth = ctl->tuner_get_bandwidth; - tt1600_stv090x_config.tuner_set_bbgain = ctl->tuner_set_bbgain; - tt1600_stv090x_config.tuner_get_bbgain = ctl->tuner_get_bbgain; - tt1600_stv090x_config.tuner_set_refclk = ctl->tuner_set_refclk; - tt1600_stv090x_config.tuner_get_status = ctl->tuner_get_status; - - dvb_attach(isl6423_attach, - budget_ci->budget.dvb_frontend, - &budget_ci->budget.i2c_adap, - &tt1600_isl6423_config); - - } else { - dvb_frontend_detach(budget_ci->budget.dvb_frontend); - budget_ci->budget.dvb_frontend = NULL; - } - } - break; - } if (budget_ci->budget.dvb_frontend == NULL) { @@ -1648,7 +1564,6 @@ MAKE_BUDGET_INFO(ttbtci, "TT-Budget-T-CI PCI", BUDGET_TT); MAKE_BUDGET_INFO(ttbcci, "TT-Budget-C-CI PCI", BUDGET_TT); MAKE_BUDGET_INFO(ttc1501, "TT-Budget C-1501 PCI", BUDGET_TT); MAKE_BUDGET_INFO(tt3200, "TT-Budget S2-3200 PCI", BUDGET_TT); -MAKE_BUDGET_INFO(tt1600, "TT-Budget S2-1600 PCI", BUDGET_TT); static struct pci_device_id pci_tbl[] = { MAKE_EXTENSION_PCI(ttbci, 0x13c2, 0x100c), @@ -1659,7 +1574,6 @@ static struct pci_device_id pci_tbl[] = { MAKE_EXTENSION_PCI(ttbs2, 0x13c2, 0x1017), MAKE_EXTENSION_PCI(ttc1501, 0x13c2, 0x101a), MAKE_EXTENSION_PCI(tt3200, 0x13c2, 0x1019), - MAKE_EXTENSION_PCI(tt1600, 0x13c2, 0x101c), { .vendor = 0, } diff --git a/linux/drivers/media/dvb/ttpci/budget.c b/linux/drivers/media/dvb/ttpci/budget.c index 83e9e7750..07dced4e7 100644 --- a/linux/drivers/media/dvb/ttpci/budget.c +++ b/linux/drivers/media/dvb/ttpci/budget.c @@ -47,6 +47,9 @@ #include "bsru6.h" #include "bsbe1.h" #include "tdhd1.h" +#include "stv6110x.h" +#include "stv090x.h" +#include "isl6423.h" static int diseqc_method; module_param(diseqc_method, int, 0444); @@ -425,6 +428,44 @@ static u8 read_pwm(struct budget* budget) return pwm; } +static struct stv090x_config tt1600_stv090x_config = { + .device = STV0903, + .demod_mode = STV090x_SINGLE, + .clk_mode = STV090x_CLK_EXT, + + .xtal = 27000000, + .address = 0x68, + .ref_clk = 27000000, + + .ts1_mode = STV090x_TSMODE_PARALLEL_PUNCTURED, + .ts2_mode = STV090x_TSMODE_SERIAL_PUNCTURED, + + .repeater_level = STV090x_RPTLEVEL_16, + + .tuner_init = NULL, + .tuner_set_mode = NULL, + .tuner_set_frequency = NULL, + .tuner_get_frequency = NULL, + .tuner_set_bandwidth = NULL, + .tuner_get_bandwidth = NULL, + .tuner_set_bbgain = NULL, + .tuner_get_bbgain = NULL, + .tuner_set_refclk = NULL, + .tuner_get_status = NULL, +}; + +static struct stv6110x_config tt1600_stv6110x_config = { + .addr = 0x60, + .refclk = 27000000, +}; + +static struct isl6423_config tt1600_isl6423_config = { + .current_max = SEC_CURRENT_515m, + .curlim = SEC_CURRENT_LIM_ON, + .mod_extern = 1, + .addr = 0x08, +}; + static void frontend_init(struct budget *budget) { (void)alps_bsbe1_config; /* avoid warning */ @@ -566,6 +607,48 @@ static void frontend_init(struct budget *budget) } break; } + + case 0x101c: { /* TT S2-1600 */ + struct stv6110x_devctl *ctl; + saa7146_setgpio(budget->dev, 2, SAA7146_GPIO_OUTLO); + msleep(50); + saa7146_setgpio(budget->dev, 2, SAA7146_GPIO_OUTHI); + msleep(250); + + budget->dvb_frontend = dvb_attach(stv090x_attach, + &tt1600_stv090x_config, + &budget->i2c_adap, + STV090x_DEMODULATOR_0); + + if (budget->dvb_frontend) { + + ctl = dvb_attach(stv6110x_attach, + budget->dvb_frontend, + &tt1600_stv6110x_config, + &budget->i2c_adap); + + tt1600_stv090x_config.tuner_init = ctl->tuner_init; + tt1600_stv090x_config.tuner_set_mode = ctl->tuner_set_mode; + tt1600_stv090x_config.tuner_set_frequency = ctl->tuner_set_frequency; + tt1600_stv090x_config.tuner_get_frequency = ctl->tuner_get_frequency; + tt1600_stv090x_config.tuner_set_bandwidth = ctl->tuner_set_bandwidth; + tt1600_stv090x_config.tuner_get_bandwidth = ctl->tuner_get_bandwidth; + tt1600_stv090x_config.tuner_set_bbgain = ctl->tuner_set_bbgain; + tt1600_stv090x_config.tuner_get_bbgain = ctl->tuner_get_bbgain; + tt1600_stv090x_config.tuner_set_refclk = ctl->tuner_set_refclk; + tt1600_stv090x_config.tuner_get_status = ctl->tuner_get_status; + + dvb_attach(isl6423_attach, + budget->dvb_frontend, + &budget->i2c_adap, + &tt1600_isl6423_config); + + } else { + dvb_frontend_detach(budget->dvb_frontend); + budget->dvb_frontend = NULL; + } + } + break; } if (budget->dvb_frontend == NULL) { @@ -641,6 +724,7 @@ MAKE_BUDGET_INFO(ttbc, "TT-Budget/WinTV-NOVA-C PCI", BUDGET_TT); MAKE_BUDGET_INFO(ttbt, "TT-Budget/WinTV-NOVA-T PCI", BUDGET_TT); MAKE_BUDGET_INFO(satel, "SATELCO Multimedia PCI", BUDGET_TT_HW_DISEQC); MAKE_BUDGET_INFO(ttbs1401, "TT-Budget-S-1401 PCI", BUDGET_TT); +MAKE_BUDGET_INFO(tt1600, "TT-Budget S2-1600 PCI", BUDGET_TT); MAKE_BUDGET_INFO(fsacs0, "Fujitsu Siemens Activy Budget-S PCI (rev GR/grundig frontend)", BUDGET_FS_ACTIVY); MAKE_BUDGET_INFO(fsacs1, "Fujitsu Siemens Activy Budget-S PCI (rev AL/alps frontend)", BUDGET_FS_ACTIVY); MAKE_BUDGET_INFO(fsact, "Fujitsu Siemens Activy Budget-T PCI (rev GR/Grundig frontend)", BUDGET_FS_ACTIVY); @@ -653,6 +737,7 @@ static struct pci_device_id pci_tbl[] = { MAKE_EXTENSION_PCI(satel, 0x13c2, 0x1013), MAKE_EXTENSION_PCI(ttbs, 0x13c2, 0x1016), MAKE_EXTENSION_PCI(ttbs1401, 0x13c2, 0x1018), + MAKE_EXTENSION_PCI(tt1600, 0x13c2, 0x101c), MAKE_EXTENSION_PCI(fsacs1,0x1131, 0x4f60), MAKE_EXTENSION_PCI(fsacs0,0x1131, 0x4f61), MAKE_EXTENSION_PCI(fsact1, 0x1131, 0x5f60), -- cgit v1.2.3 From 6de40f28605c851a07f13922c906bc6b89b3bca0 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Thu, 23 Apr 2009 22:00:04 +0400 Subject: Use Continuous clock From: Andreas Regel Signed-off-by: Andreas Regel Signed-off-by: Manu Abraham --- linux/drivers/media/dvb/ttpci/budget.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/ttpci/budget.c b/linux/drivers/media/dvb/ttpci/budget.c index 07dced4e7..e48380c48 100644 --- a/linux/drivers/media/dvb/ttpci/budget.c +++ b/linux/drivers/media/dvb/ttpci/budget.c @@ -437,8 +437,8 @@ static struct stv090x_config tt1600_stv090x_config = { .address = 0x68, .ref_clk = 27000000, - .ts1_mode = STV090x_TSMODE_PARALLEL_PUNCTURED, - .ts2_mode = STV090x_TSMODE_SERIAL_PUNCTURED, + .ts1_mode = STV090x_TSMODE_DVBCI, + .ts2_mode = STV090x_TSMODE_SERIAL_CONTINUOUS, .repeater_level = STV090x_RPTLEVEL_16, -- cgit v1.2.3 From 59964b28e0205cdf0a4465194f40867b7c7f5aa6 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Thu, 23 Apr 2009 22:00:40 +0400 Subject: Update demodulator capabilities From: Andreas Regel Signed-off-by: Andreas Regel Signed-off-by: Manu Abraham --- linux/drivers/media/dvb/frontends/stv090x.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/frontends/stv090x.c b/linux/drivers/media/dvb/frontends/stv090x.c index 28ab19c22..39909fefc 100644 --- a/linux/drivers/media/dvb/frontends/stv090x.c +++ b/linux/drivers/media/dvb/frontends/stv090x.c @@ -4799,6 +4799,17 @@ static struct dvb_frontend_ops stv090x_ops = { .info = { .name = "STV090x Multistandard", + .type = FE_QPSK, + .frequency_min = 950000, + .frequency_max = 2150000, + .frequency_stepsize = 0, + .frequency_tolerance = 0, + .symbol_rate_min = 1000000, + .symbol_rate_max = 45000000, + .caps = FE_CAN_INVERSION_AUTO | + FE_CAN_FEC_AUTO | + FE_CAN_QPSK | + FE_CAN_2G_MODULATION }, .release = stv090x_release, -- cgit v1.2.3 From db70e703e55d87b3659e6fb511b201b6d725e737 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 23 Apr 2009 19:04:41 +0000 Subject: patch: s2255drv: code cleanup From: Dean Anderson This patch does: - remove unused structure items. - define Response values; - change Driver revision printk. Signed-off-by: Dean Anderson Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/s2255drv.c | 47 +++++++++++++++++------------------- 1 file changed, 22 insertions(+), 25 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/s2255drv.c b/linux/drivers/media/video/s2255drv.c index 0fac6af08..12ced841e 100644 --- a/linux/drivers/media/video/s2255drv.c +++ b/linux/drivers/media/video/s2255drv.c @@ -78,6 +78,8 @@ #define MAX_CHANNELS 4 #define S2255_MARKER_FRAME 0x2255DA4AL #define S2255_MARKER_RESPONSE 0x2255ACACL +#define S2255_RESPONSE_SETMODE 0x01 +#define S2255_RESPONSE_FW 0x10 #define S2255_USB_XFER_SIZE (16 * 1024) #define MAX_CHANNELS 4 #define MAX_PIPE_BUFFERS 1 @@ -179,9 +181,6 @@ struct s2255_bufferi { struct s2255_dmaqueue { struct list_head active; - /* thread for acquisition */ - struct task_struct *kthread; - int frame; struct s2255_dev *dev; int channel; }; @@ -211,16 +210,11 @@ struct s2255_pipeinfo { u32 max_transfer_size; u32 cur_transfer_size; u8 *transfer_buffer; - u32 transfer_flags;; u32 state; - u32 prev_state; - u32 urb_size; void *stream_urb; void *dev; /* back pointer to s2255_dev struct*/ u32 err_count; - u32 buf_index; u32 idx; - u32 priority_set; }; struct s2255_fmt; /*forward declaration */ @@ -240,8 +234,6 @@ struct s2255_dev { struct list_head s2255_devlist; struct timer_list timer; struct s2255_fw *fw_data; - int board_num; - int is_open; struct s2255_pipeinfo pipes[MAX_PIPE_BUFFERS]; struct s2255_bufferi buffer[MAX_CHANNELS]; struct s2255_mode mode[MAX_CHANNELS]; @@ -298,9 +290,10 @@ struct s2255_fh { int resources[MAX_CHANNELS]; }; -#define CUR_USB_FWVER 774 /* current cypress EEPROM firmware version */ +/* current cypress EEPROM firmware version */ +#define S2255_CUR_USB_FWVER ((3 << 8) | 6) #define S2255_MAJOR_VERSION 1 -#define S2255_MINOR_VERSION 13 +#define S2255_MINOR_VERSION 14 #define S2255_RELEASE 0 #define S2255_VERSION KERNEL_VERSION(S2255_MAJOR_VERSION, \ S2255_MINOR_VERSION, \ @@ -1819,7 +1812,6 @@ static int s2255_probe_v4l(struct s2255_dev *dev) INIT_LIST_HEAD(&dev->vidq[i].active); dev->vidq[i].dev = dev; dev->vidq[i].channel = i; - dev->vidq[i].kthread = NULL; /* register 4 video devices */ dev->vdev[i] = video_device_alloc(); memcpy(dev->vdev[i], &template, sizeof(struct video_device)); @@ -1840,7 +1832,9 @@ static int s2255_probe_v4l(struct s2255_dev *dev) return ret; } } - printk(KERN_INFO "Sensoray 2255 V4L driver\n"); + printk(KERN_INFO "Sensoray 2255 V4L driver Revision: %d.%d\n", + S2255_MAJOR_VERSION, + S2255_MINOR_VERSION); return ret; } @@ -1930,14 +1924,14 @@ static int save_frame(struct s2255_dev *dev, struct s2255_pipeinfo *pipe_info) if (!(cc >= 0 && cc < MAX_CHANNELS)) break; switch (pdword[2]) { - case 0x01: + case S2255_RESPONSE_SETMODE: /* check if channel valid */ /* set mode ready */ dev->setmode_ready[cc] = 1; wake_up(&dev->wait_setmode[cc]); dprintk(5, "setmode ready %d\n", cc); break; - case 0x10: + case S2255_RESPONSE_FW: dev->chn_ready |= (1 << cc); if ((dev->chn_ready & 0x0f) != 0x0f) @@ -2173,10 +2167,15 @@ static int s2255_board_init(struct s2255_dev *dev) /* query the firmware */ fw_ver = s2255_get_fx2fw(dev); - printk(KERN_INFO "2255 usb firmware version %d \n", fw_ver); - if (fw_ver < CUR_USB_FWVER) + printk(KERN_INFO "2255 usb firmware version %d.%d\n", + (fw_ver >> 8) & 0xff, + fw_ver & 0xff); + + if (fw_ver < S2255_CUR_USB_FWVER) dev_err(&dev->udev->dev, - "usb firmware not up to date %d\n", fw_ver); + "usb firmware not up to date %d.%d\n", + (fw_ver >> 8) & 0xff, + fw_ver & 0xff); for (j = 0; j < MAX_CHANNELS; j++) { dev->b_acquire[j] = 0; @@ -2284,8 +2283,7 @@ static int s2255_start_readpipe(struct s2255_dev *dev) for (i = 0; i < MAX_PIPE_BUFFERS; i++) { pipe_info->state = 1; - pipe_info->buf_index = (u32) i; - pipe_info->priority_set = 0; + pipe_info->err_count = 0; pipe_info->stream_urb = usb_alloc_urb(0, GFP_KERNEL); if (!pipe_info->stream_urb) { dev_err(&dev->udev->dev, @@ -2299,7 +2297,6 @@ static int s2255_start_readpipe(struct s2255_dev *dev) pipe_info->cur_transfer_size, read_pipe_completion, pipe_info); - pipe_info->urb_size = sizeof(pipe_info->stream_urb); dprintk(4, "submitting URB %p\n", pipe_info->stream_urb); retval = usb_submit_urb(pipe_info->stream_urb, GFP_KERNEL); if (retval) { @@ -2404,8 +2401,6 @@ static void s2255_stop_readpipe(struct s2255_dev *dev) if (pipe_info->state == 0) continue; pipe_info->state = 0; - pipe_info->prev_state = 1; - } } @@ -2543,7 +2538,9 @@ static int s2255_probe(struct usb_interface *interface, s2255_probe_v4l(dev); usb_reset_device(dev->udev); /* load 2255 board specific */ - s2255_board_init(dev); + retval = s2255_board_init(dev); + if (retval) + goto error; dprintk(4, "before probe done %p\n", dev); spin_lock_init(&dev->slock); -- cgit v1.2.3 From 3abdad521cc36eefdd131acfd578c08838fe4aa0 Mon Sep 17 00:00:00 2001 From: Oliver Endriss Date: Fri, 24 Apr 2009 04:24:33 +0200 Subject: dvb-ttpci: Fixed VIDEO_SLOWMOTION ioctl From: Oliver Endriss Fixed VIDEO_SLOWMOTION ioctl. Priority: normal Signed-off-by: Oliver Endriss --- linux/drivers/media/dvb/ttpci/av7110_av.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/ttpci/av7110_av.c b/linux/drivers/media/dvb/ttpci/av7110_av.c index 2adcaeff3..7b93ab9dc 100644 --- a/linux/drivers/media/dvb/ttpci/av7110_av.c +++ b/linux/drivers/media/dvb/ttpci/av7110_av.c @@ -1249,7 +1249,8 @@ static int dvb_video_ioctl(struct inode *inode, struct file *file, case VIDEO_SLOWMOTION: if (av7110->playing&RP_VIDEO) { - ret = av7110_fw_cmd(av7110, COMTYPE_REC_PLAY, __Slow, 2, 0, 0); + if (av7110->trickmode != TRICK_SLOW) + ret = av7110_fw_cmd(av7110, COMTYPE_REC_PLAY, __Slow, 2, 0, 0); if (!ret) ret = vidcom(av7110, AV_VIDEO_CMD_SLOW, arg); } else { -- cgit v1.2.3 From 34efc2efeab79b43139454c4daeef94ff1b69f2c Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 24 Apr 2009 01:46:41 -0300 Subject: stv090x.h and stv6110x.h: Fix two trivial compilation breakage errors From: Mauro Carvalho Chehab /home/v4l/master/v4l/stv6110x.h:64: error: expected identifier or '(' before '{' token In file included from /home/v4l/master/v4l/budget.c:52: /home/v4l/master/v4l/stv090x.h:116: error: redefinition of 'stv090x_attach' /home/v4l/master/v4l/stv090x.h:108: error: previous definition of 'stv090x_attach' was here The first pne were due to an extra ';', and the other is due to a duplicated inline function declaration. This patch will need to be merged with the one that added those two headers at -git, to avoid breaking git bisect. CC: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/frontends/stv090x.h | 8 -------- linux/drivers/media/dvb/frontends/stv6110x.h | 2 +- 2 files changed, 1 insertion(+), 9 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/frontends/stv090x.h b/linux/drivers/media/dvb/frontends/stv090x.h index b75a66baf..5a567b3b4 100644 --- a/linux/drivers/media/dvb/frontends/stv090x.h +++ b/linux/drivers/media/dvb/frontends/stv090x.h @@ -109,14 +109,6 @@ static inline struct dvb_frontend *stv090x_attach(const struct stv090x_config *c printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); return NULL; } - -static inline struct dvb_frontend *stv090x_attach(const struct stv090x_config* config, - struct i2c_adapter *i2c, - enum stv090x_demodulator demod) -{ - printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); - return NULL; -} #endif /* CONFIG_DVB_STV090x */ #endif /* __STV090x_H */ diff --git a/linux/drivers/media/dvb/frontends/stv6110x.h b/linux/drivers/media/dvb/frontends/stv6110x.h index 6d43c294e..a38257080 100644 --- a/linux/drivers/media/dvb/frontends/stv6110x.h +++ b/linux/drivers/media/dvb/frontends/stv6110x.h @@ -60,7 +60,7 @@ extern struct stv6110x_devctl *stv6110x_attach(struct dvb_frontend *fe, #else static inline struct stv6110x_devctl *stv6110x_attach(struct dvb_frontend *fe, const struct stv6110x_config *config, - struct i2c_adapter *i2c); + struct i2c_adapter *i2c) { printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); return NULL; -- cgit v1.2.3 From 4958205a8529a672cec383a02fa7d7c53c12ff0d Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Fri, 24 Apr 2009 17:53:51 +0200 Subject: soc-camera: add a free_bus method to struct soc_camera_link From: Guennadi Liakhovetski Currently pcm990 camera bus-width management functions request a GPIO and never free it again. With this approach the GPIO extender driver cannot be unloaded once camera drivers have been loaded, also unloading theb i2c-pxa bus driver produces errors, because the GPIO extender driver cannot unregister properly. Another problem is, that if camera drivers are once loaded before the GPIO extender driver, the platform code marks the GPIO unavailable and only a reboot helps to recover. Adding an explicit free_bus method and using it in mt9m001 and mt9v022 drivers fixes these problems. Signed-off-by: Guennadi Liakhovetski Acked-by: Eric Miao --- arch/arm/mach-pxa/pcm990-baseboard.c | 23 ++++++++++++++++------- drivers/media/video/mt9m001.c | 3 +++ drivers/media/video/mt9v022.c | 3 +++ include/media/soc_camera.h | 1 + 4 files changed, 23 insertions(+), 7 deletions(-) --- linux/drivers/media/video/mt9m001.c | 3 +++ linux/drivers/media/video/mt9v022.c | 3 +++ 2 files changed, 6 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/mt9m001.c b/linux/drivers/media/video/mt9m001.c index 83f3cae47..959edc760 100644 --- a/linux/drivers/media/video/mt9m001.c +++ b/linux/drivers/media/video/mt9m001.c @@ -604,10 +604,13 @@ ei2c: static void mt9m001_video_remove(struct soc_camera_device *icd) { struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd); + struct soc_camera_link *icl = mt9m001->client->dev.platform_data; dev_dbg(&icd->dev, "Video %x removed: %p, %p\n", mt9m001->client->addr, icd->dev.parent, icd->vdev); soc_camera_video_stop(icd); + if (icl->free_bus) + icl->free_bus(icl); } #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) diff --git a/linux/drivers/media/video/mt9v022.c b/linux/drivers/media/video/mt9v022.c index 3bee30caa..07ffd967e 100644 --- a/linux/drivers/media/video/mt9v022.c +++ b/linux/drivers/media/video/mt9v022.c @@ -735,10 +735,13 @@ ei2c: static void mt9v022_video_remove(struct soc_camera_device *icd) { struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd); + struct soc_camera_link *icl = mt9v022->client->dev.platform_data; dev_dbg(&icd->dev, "Video %x removed: %p, %p\n", mt9v022->client->addr, icd->dev.parent, icd->vdev); soc_camera_video_stop(icd); + if (icl->free_bus) + icl->free_bus(icl); } #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) -- cgit v1.2.3 From 217174ee3676b072ebdb35e23c59dea90d1894dd Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Fri, 24 Apr 2009 17:55:18 +0200 Subject: soc-camera: host-driver cleanup From: Guennadi Liakhovetski Embed struct soc_camera_host in platform-specific per host instance objects instead of allocating them statically in drivers, use platform_[gs]et_drvdata consistently, use resource_size(). Signed-off-by: Guennadi Liakhovetski --- drivers/media/video/mx1_camera.c | 21 ++++++++----------- drivers/media/video/mx3_camera.c | 2 +- drivers/media/video/pxa_camera.c | 29 ++++++++++++--------------- drivers/media/video/sh_mobile_ceu_camera.c | 6 ++-- 4 files changed, 26 insertions(+), 32 deletions(-) --- linux/drivers/media/video/mx1_camera.c | 21 ++++++++--------- linux/drivers/media/video/mx3_camera.c | 2 +- linux/drivers/media/video/pxa_camera.c | 29 +++++++++++------------- linux/drivers/media/video/sh_mobile_ceu_camera.c | 6 ++--- 4 files changed, 26 insertions(+), 32 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/mx1_camera.c b/linux/drivers/media/video/mx1_camera.c index 86fab56c5..48dd984da 100644 --- a/linux/drivers/media/video/mx1_camera.c +++ b/linux/drivers/media/video/mx1_camera.c @@ -102,6 +102,7 @@ struct mx1_buffer { * Interface. If anyone ever builds hardware to enable more than * one camera, they will have to modify this driver too */ struct mx1_camera_dev { + struct soc_camera_host soc_host; struct soc_camera_device *icd; struct mx1_camera_pdata *pdata; struct mx1_buffer *active; @@ -633,12 +634,6 @@ static struct soc_camera_host_ops mx1_soc_camera_host_ops = { .querycap = mx1_camera_querycap, }; -/* Should be allocated dynamically too, but we have only one. */ -static struct soc_camera_host mx1_soc_camera_host = { - .drv_name = DRIVER_NAME, - .ops = &mx1_soc_camera_host_ops, -}; - static struct fiq_handler fh = { .name = "csi_sof" }; @@ -673,7 +668,7 @@ static int __init mx1_camera_probe(struct platform_device *pdev) goto exit_put_clk; } - dev_set_drvdata(&pdev->dev, pcdev); + platform_set_drvdata(pdev, pcdev); pcdev->res = res; pcdev->clk = clk; @@ -746,10 +741,12 @@ static int __init mx1_camera_probe(struct platform_device *pdev) mxc_set_irq_fiq(irq, 1); enable_fiq(irq); - mx1_soc_camera_host.priv = pcdev; - mx1_soc_camera_host.dev.parent = &pdev->dev; - mx1_soc_camera_host.nr = pdev->id; - err = soc_camera_host_register(&mx1_soc_camera_host); + pcdev->soc_host.drv_name = DRIVER_NAME; + pcdev->soc_host.ops = &mx1_soc_camera_host_ops; + pcdev->soc_host.priv = pcdev; + pcdev->soc_host.dev.parent = &pdev->dev; + pcdev->soc_host.nr = pdev->id; + err = soc_camera_host_register(&pcdev->soc_host); if (err) goto exit_free_irq; @@ -787,7 +784,7 @@ static int __exit mx1_camera_remove(struct platform_device *pdev) clk_put(pcdev->clk); - soc_camera_host_unregister(&mx1_soc_camera_host); + soc_camera_host_unregister(&pcdev->soc_host); iounmap(pcdev->base); diff --git a/linux/drivers/media/video/mx3_camera.c b/linux/drivers/media/video/mx3_camera.c index c462b811e..22c58dcc8 100644 --- a/linux/drivers/media/video/mx3_camera.c +++ b/linux/drivers/media/video/mx3_camera.c @@ -1106,7 +1106,7 @@ static int mx3_camera_probe(struct platform_device *pdev) goto eclkget; } - dev_set_drvdata(&pdev->dev, mx3_cam); + platform_set_drvdata(pdev, mx3_cam); mx3_cam->pdata = pdev->dev.platform_data; mx3_cam->platform_flags = mx3_cam->pdata->flags; diff --git a/linux/drivers/media/video/pxa_camera.c b/linux/drivers/media/video/pxa_camera.c index cb4491338..682e66d95 100644 --- a/linux/drivers/media/video/pxa_camera.c +++ b/linux/drivers/media/video/pxa_camera.c @@ -214,6 +214,7 @@ struct pxa_buffer { }; struct pxa_camera_dev { + struct soc_camera_host soc_host; struct device *dev; /* PXA27x is only supposed to handle one camera on its Quick Capture * interface. If anyone ever builds hardware to enable more than @@ -1564,12 +1565,6 @@ static struct soc_camera_host_ops pxa_soc_camera_host_ops = { .set_bus_param = pxa_camera_set_bus_param, }; -/* Should be allocated dynamically too, but we have only one. */ -static struct soc_camera_host pxa_soc_camera_host = { - .drv_name = PXA_CAM_DRV_NAME, - .ops = &pxa_soc_camera_host_ops, -}; - static int pxa_camera_probe(struct platform_device *pdev) { struct pxa_camera_dev *pcdev; @@ -1598,7 +1593,7 @@ static int pxa_camera_probe(struct platform_device *pdev) goto exit_kfree; } - dev_set_drvdata(&pdev->dev, pcdev); + platform_set_drvdata(pdev, pcdev); pcdev->res = res; pcdev->pdata = pdev->dev.platform_data; @@ -1628,13 +1623,13 @@ static int pxa_camera_probe(struct platform_device *pdev) /* * Request the regions. */ - if (!request_mem_region(res->start, res->end - res->start + 1, + if (!request_mem_region(res->start, resource_size(res), PXA_CAM_DRV_NAME)) { err = -EBUSY; goto exit_clk; } - base = ioremap(res->start, res->end - res->start + 1); + base = ioremap(res->start, resource_size(res)); if (!base) { err = -ENOMEM; goto exit_release; @@ -1682,10 +1677,12 @@ static int pxa_camera_probe(struct platform_device *pdev) goto exit_free_dma; } - pxa_soc_camera_host.priv = pcdev; - pxa_soc_camera_host.dev.parent = &pdev->dev; - pxa_soc_camera_host.nr = pdev->id; - err = soc_camera_host_register(&pxa_soc_camera_host); + pcdev->soc_host.drv_name = PXA_CAM_DRV_NAME; + pcdev->soc_host.ops = &pxa_soc_camera_host_ops; + pcdev->soc_host.priv = pcdev; + pcdev->soc_host.dev.parent = &pdev->dev; + pcdev->soc_host.nr = pdev->id; + err = soc_camera_host_register(&pcdev->soc_host); if (err) goto exit_free_irq; @@ -1702,7 +1699,7 @@ exit_free_dma_y: exit_iounmap: iounmap(base); exit_release: - release_mem_region(res->start, res->end - res->start + 1); + release_mem_region(res->start, resource_size(res)); exit_clk: clk_put(pcdev->clk); exit_kfree: @@ -1723,12 +1720,12 @@ static int __devexit pxa_camera_remove(struct platform_device *pdev) pxa_free_dma(pcdev->dma_chans[2]); free_irq(pcdev->irq, pcdev); - soc_camera_host_unregister(&pxa_soc_camera_host); + soc_camera_host_unregister(&pcdev->soc_host); iounmap(pcdev->base); res = pcdev->res; - release_mem_region(res->start, res->end - res->start + 1); + release_mem_region(res->start, resource_size(res)); kfree(pcdev); diff --git a/linux/drivers/media/video/sh_mobile_ceu_camera.c b/linux/drivers/media/video/sh_mobile_ceu_camera.c index cd796b33f..0647f3724 100644 --- a/linux/drivers/media/video/sh_mobile_ceu_camera.c +++ b/linux/drivers/media/video/sh_mobile_ceu_camera.c @@ -841,7 +841,7 @@ static int sh_mobile_ceu_probe(struct platform_device *pdev) goto exit_kfree; } - base = ioremap_nocache(res->start, res->end - res->start + 1); + base = ioremap_nocache(res->start, resource_size(res)); if (!base) { err = -ENXIO; dev_err(&pdev->dev, "Unable to ioremap CEU registers.\n"); @@ -857,7 +857,7 @@ static int sh_mobile_ceu_probe(struct platform_device *pdev) if (res) { err = dma_declare_coherent_memory(&pdev->dev, res->start, res->start, - (res->end - res->start) + 1, + resource_size(res), DMA_MEMORY_MAP | DMA_MEMORY_EXCLUSIVE); if (!err) { @@ -866,7 +866,7 @@ static int sh_mobile_ceu_probe(struct platform_device *pdev) goto exit_iounmap; } - pcdev->video_limit = (res->end - res->start) + 1; + pcdev->video_limit = resource_size(res); } /* request irq */ -- cgit v1.2.3 From 0d6bf4267e7a2b8a78e1e92da9a4545bc82d29c5 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Fri, 24 Apr 2009 17:55:48 +0200 Subject: soc-camera: remove an extra device generation from struct soc_camera_host From: Guennadi Liakhovetski Make camera devices direct children of host platform devices, move the inheritance management into the soc_camera.c core driver. Signed-off-by: Guennadi Liakhovetski --- drivers/media/video/mx1_camera.c | 35 +++++----- drivers/media/video/mx3_camera.c | 40 ++++++------ drivers/media/video/pxa_camera.c | 97 ++++++++++++++-------------- drivers/media/video/sh_mobile_ceu_camera.c | 21 +++--- drivers/media/video/soc_camera.c | 35 +++------- include/media/soc_camera.h | 4 +- 6 files changed, 107 insertions(+), 125 deletions(-) --- linux/drivers/media/video/mx1_camera.c | 35 +++++---- linux/drivers/media/video/mx3_camera.c | 40 +++++----- linux/drivers/media/video/pxa_camera.c | 97 ++++++++++++------------ linux/drivers/media/video/sh_mobile_ceu_camera.c | 21 +++-- linux/drivers/media/video/soc_camera.c | 35 +++------ 5 files changed, 105 insertions(+), 123 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/mx1_camera.c b/linux/drivers/media/video/mx1_camera.c index 48dd984da..2d075205b 100644 --- a/linux/drivers/media/video/mx1_camera.c +++ b/linux/drivers/media/video/mx1_camera.c @@ -106,7 +106,6 @@ struct mx1_camera_dev { struct soc_camera_device *icd; struct mx1_camera_pdata *pdata; struct mx1_buffer *active; - struct device *dev; struct resource *res; struct clk *clk; struct list_head capture; @@ -220,7 +219,7 @@ static int mx1_camera_setup_dma(struct mx1_camera_dev *pcdev) int ret; if (unlikely(!pcdev->active)) { - dev_err(pcdev->dev, "DMA End IRQ with no active buffer\n"); + dev_err(pcdev->soc_host.dev, "DMA End IRQ with no active buffer\n"); return -EFAULT; } @@ -230,7 +229,7 @@ static int mx1_camera_setup_dma(struct mx1_camera_dev *pcdev) vbuf->size, pcdev->res->start + CSIRXR, DMA_MODE_READ); if (unlikely(ret)) - dev_err(pcdev->dev, "Failed to setup DMA sg list\n"); + dev_err(pcdev->soc_host.dev, "Failed to setup DMA sg list\n"); return ret; } @@ -339,14 +338,14 @@ static void mx1_camera_dma_irq(int channel, void *data) imx_dma_disable(channel); if (unlikely(!pcdev->active)) { - dev_err(pcdev->dev, "DMA End IRQ with no active buffer\n"); + dev_err(pcdev->soc_host.dev, "DMA End IRQ with no active buffer\n"); goto out; } vb = &pcdev->active->vb; buf = container_of(vb, struct mx1_buffer, vb); WARN_ON(buf->inwork || list_empty(&vb->queue)); - dev_dbg(pcdev->dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__, + dev_dbg(pcdev->soc_host.dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__, vb, vb->baddr, vb->bsize); mx1_camera_wakeup(pcdev, vb, buf); @@ -367,7 +366,7 @@ static void mx1_camera_init_videobuf(struct videobuf_queue *q, struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); struct mx1_camera_dev *pcdev = ici->priv; - videobuf_queue_dma_contig_init(q, &mx1_videobuf_ops, pcdev->dev, + videobuf_queue_dma_contig_init(q, &mx1_videobuf_ops, ici->dev, &pcdev->lock, V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_NONE, @@ -386,7 +385,7 @@ static int mclk_get_divisor(struct mx1_camera_dev *pcdev) * they get a nice Oops */ div = (lcdclk + 2 * mclk - 1) / (2 * mclk) - 1; - dev_dbg(pcdev->dev, "System clock %lukHz, target freq %dkHz, " + dev_dbg(pcdev->soc_host.dev, "System clock %lukHz, target freq %dkHz, " "divisor %lu\n", lcdclk / 1000, mclk / 1000, div); return div; @@ -396,7 +395,7 @@ static void mx1_camera_activate(struct mx1_camera_dev *pcdev) { unsigned int csicr1 = CSICR1_EN; - dev_dbg(pcdev->dev, "Activate device\n"); + dev_dbg(pcdev->soc_host.dev, "Activate device\n"); clk_enable(pcdev->clk); @@ -412,7 +411,7 @@ static void mx1_camera_activate(struct mx1_camera_dev *pcdev) static void mx1_camera_deactivate(struct mx1_camera_dev *pcdev) { - dev_dbg(pcdev->dev, "Deactivate device\n"); + dev_dbg(pcdev->soc_host.dev, "Deactivate device\n"); /* Disable all CSI interface */ __raw_writel(0x00, pcdev->base + CSICR1); @@ -551,7 +550,7 @@ static int mx1_camera_set_fmt(struct soc_camera_device *icd, xlate = soc_camera_xlate_by_fourcc(icd, pix->pixelformat); if (!xlate) { - dev_warn(&ici->dev, "Format %x not found\n", pix->pixelformat); + dev_warn(ici->dev, "Format %x not found\n", pix->pixelformat); return -EINVAL; } @@ -668,7 +667,6 @@ static int __init mx1_camera_probe(struct platform_device *pdev) goto exit_put_clk; } - platform_set_drvdata(pdev, pcdev); pcdev->res = res; pcdev->clk = clk; @@ -702,16 +700,15 @@ static int __init mx1_camera_probe(struct platform_device *pdev) } pcdev->irq = irq; pcdev->base = base; - pcdev->dev = &pdev->dev; /* request dma */ pcdev->dma_chan = imx_dma_request_by_prio(DRIVER_NAME, DMA_PRIO_HIGH); if (pcdev->dma_chan < 0) { - dev_err(pcdev->dev, "Can't request DMA for MX1 CSI\n"); + dev_err(&pdev->dev, "Can't request DMA for MX1 CSI\n"); err = -EBUSY; goto exit_iounmap; } - dev_dbg(pcdev->dev, "got DMA channel %d\n", pcdev->dma_chan); + dev_dbg(&pdev->dev, "got DMA channel %d\n", pcdev->dma_chan); imx_dma_setup_handlers(pcdev->dma_chan, mx1_camera_dma_irq, NULL, pcdev); @@ -724,7 +721,7 @@ static int __init mx1_camera_probe(struct platform_device *pdev) /* request irq */ err = claim_fiq(&fh); if (err) { - dev_err(pcdev->dev, "Camera interrupt register failed \n"); + dev_err(&pdev->dev, "Camera interrupt register failed \n"); goto exit_free_dma; } @@ -744,7 +741,7 @@ static int __init mx1_camera_probe(struct platform_device *pdev) pcdev->soc_host.drv_name = DRIVER_NAME; pcdev->soc_host.ops = &mx1_soc_camera_host_ops; pcdev->soc_host.priv = pcdev; - pcdev->soc_host.dev.parent = &pdev->dev; + pcdev->soc_host.dev = &pdev->dev; pcdev->soc_host.nr = pdev->id; err = soc_camera_host_register(&pcdev->soc_host); if (err) @@ -774,7 +771,9 @@ exit: static int __exit mx1_camera_remove(struct platform_device *pdev) { - struct mx1_camera_dev *pcdev = platform_get_drvdata(pdev); + struct soc_camera_host *soc_host = to_soc_camera_host(&pdev->dev); + struct mx1_camera_dev *pcdev = container_of(soc_host, + struct mx1_camera_dev, soc_host); struct resource *res; imx_dma_free(pcdev->dma_chan); @@ -784,7 +783,7 @@ static int __exit mx1_camera_remove(struct platform_device *pdev) clk_put(pcdev->clk); - soc_camera_host_unregister(&pcdev->soc_host); + soc_camera_host_unregister(soc_host); iounmap(pcdev->base); diff --git a/linux/drivers/media/video/mx3_camera.c b/linux/drivers/media/video/mx3_camera.c index 22c58dcc8..cb13faa2e 100644 --- a/linux/drivers/media/video/mx3_camera.c +++ b/linux/drivers/media/video/mx3_camera.c @@ -87,7 +87,6 @@ struct mx3_camera_buffer { * @soc_host: embedded soc_host object */ struct mx3_camera_dev { - struct device *dev; /* * i.MX3x is only supposed to handle one camera on its Camera Sensor * Interface. If anyone ever builds hardware to enable more than one @@ -431,7 +430,7 @@ static void mx3_camera_init_videobuf(struct videobuf_queue *q, struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); struct mx3_camera_dev *mx3_cam = ici->priv; - videobuf_queue_dma_contig_init(q, &mx3_videobuf_ops, mx3_cam->dev, + videobuf_queue_dma_contig_init(q, &mx3_videobuf_ops, ici->dev, &mx3_cam->lock, V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_NONE, @@ -599,7 +598,8 @@ static int test_platform_param(struct mx3_camera_dev *mx3_cam, *flags |= SOCAM_DATAWIDTH_4; break; default: - dev_info(mx3_cam->dev, "Unsupported bus width %d\n", buswidth); + dev_info(mx3_cam->soc_host.dev, "Unsupported bus width %d\n", + buswidth); return -EINVAL; } @@ -614,7 +614,7 @@ static int mx3_camera_try_bus_param(struct soc_camera_device *icd, unsigned long bus_flags, camera_flags; int ret = test_platform_param(mx3_cam, depth, &bus_flags); - dev_dbg(&ici->dev, "requested bus width %d bit: %d\n", depth, ret); + dev_dbg(ici->dev, "requested bus width %d bit: %d\n", depth, ret); if (ret < 0) return ret; @@ -637,7 +637,7 @@ static bool chan_filter(struct dma_chan *chan, void *arg) if (!rq) return false; - pdata = rq->mx3_cam->dev->platform_data; + pdata = rq->mx3_cam->soc_host.dev->platform_data; return rq->id == chan->chan_id && pdata->dma_dev == chan->device->dev; @@ -697,7 +697,7 @@ static int mx3_camera_get_formats(struct soc_camera_device *icd, int idx, xlate->cam_fmt = icd->formats + idx; xlate->buswidth = buswidth; xlate++; - dev_dbg(&ici->dev, "Providing format %s using %s\n", + dev_dbg(ici->dev, "Providing format %s using %s\n", mx3_camera_formats[0].name, icd->formats[idx].name); } @@ -709,7 +709,7 @@ static int mx3_camera_get_formats(struct soc_camera_device *icd, int idx, xlate->cam_fmt = icd->formats + idx; xlate->buswidth = buswidth; xlate++; - dev_dbg(&ici->dev, "Providing format %s using %s\n", + dev_dbg(ici->dev, "Providing format %s using %s\n", mx3_camera_formats[0].name, icd->formats[idx].name); } @@ -722,7 +722,7 @@ passthrough: xlate->cam_fmt = icd->formats + idx; xlate->buswidth = buswidth; xlate++; - dev_dbg(&ici->dev, + dev_dbg(ici->dev, "Providing format %s in pass-through mode\n", icd->formats[idx].name); } @@ -829,7 +829,7 @@ static int mx3_camera_set_fmt(struct soc_camera_device *icd, xlate = soc_camera_xlate_by_fourcc(icd, pix->pixelformat); if (!xlate) { - dev_warn(&ici->dev, "Format %x not found\n", pix->pixelformat); + dev_warn(ici->dev, "Format %x not found\n", pix->pixelformat); return -EINVAL; } @@ -866,7 +866,7 @@ static int mx3_camera_try_fmt(struct soc_camera_device *icd, xlate = soc_camera_xlate_by_fourcc(icd, pixfmt); if (pixfmt && !xlate) { - dev_warn(&ici->dev, "Format %x not found\n", pixfmt); + dev_warn(ici->dev, "Format %x not found\n", pixfmt); return -EINVAL; } @@ -933,11 +933,11 @@ static int mx3_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt) xlate = soc_camera_xlate_by_fourcc(icd, pixfmt); if (!xlate) { - dev_warn(&ici->dev, "Format %x not found\n", pixfmt); + dev_warn(ici->dev, "Format %x not found\n", pixfmt); return -EINVAL; } - dev_dbg(&ici->dev, "requested bus width %d bit: %d\n", + dev_dbg(ici->dev, "requested bus width %d bit: %d\n", icd->buswidth, ret); if (ret < 0) @@ -947,7 +947,7 @@ static int mx3_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt) common_flags = soc_camera_bus_param_compatible(camera_flags, bus_flags); if (!common_flags) { - dev_dbg(&ici->dev, "no common flags: camera %lx, host %lx\n", + dev_dbg(ici->dev, "no common flags: camera %lx, host %lx\n", camera_flags, bus_flags); return -EINVAL; } @@ -1054,7 +1054,7 @@ static int mx3_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt) csi_reg_write(mx3_cam, sens_conf | dw, CSI_SENS_CONF); - dev_dbg(&ici->dev, "Set SENS_CONF to %x\n", sens_conf | dw); + dev_dbg(ici->dev, "Set SENS_CONF to %x\n", sens_conf | dw); return 0; } @@ -1106,8 +1106,6 @@ static int mx3_camera_probe(struct platform_device *pdev) goto eclkget; } - platform_set_drvdata(pdev, mx3_cam); - mx3_cam->pdata = pdev->dev.platform_data; mx3_cam->platform_flags = mx3_cam->pdata->flags; if (!(mx3_cam->platform_flags & (MX3_CAMERA_DATAWIDTH_4 | @@ -1139,14 +1137,14 @@ static int mx3_camera_probe(struct platform_device *pdev) } mx3_cam->base = base; - mx3_cam->dev = &pdev->dev; soc_host = &mx3_cam->soc_host; soc_host->drv_name = MX3_CAM_DRV_NAME; soc_host->ops = &mx3_soc_camera_host_ops; soc_host->priv = mx3_cam; - soc_host->dev.parent = &pdev->dev; + soc_host->dev = &pdev->dev; soc_host->nr = pdev->id; + err = soc_camera_host_register(soc_host); if (err) goto ecamhostreg; @@ -1169,11 +1167,13 @@ egetres: static int __devexit mx3_camera_remove(struct platform_device *pdev) { - struct mx3_camera_dev *mx3_cam = platform_get_drvdata(pdev); + struct soc_camera_host *soc_host = to_soc_camera_host(&pdev->dev); + struct mx3_camera_dev *mx3_cam = container_of(soc_host, + struct mx3_camera_dev, soc_host); clk_put(mx3_cam->clk); - soc_camera_host_unregister(&mx3_cam->soc_host); + soc_camera_host_unregister(soc_host); iounmap(mx3_cam->base); diff --git a/linux/drivers/media/video/pxa_camera.c b/linux/drivers/media/video/pxa_camera.c index 682e66d95..35642c430 100644 --- a/linux/drivers/media/video/pxa_camera.c +++ b/linux/drivers/media/video/pxa_camera.c @@ -215,7 +215,6 @@ struct pxa_buffer { struct pxa_camera_dev { struct soc_camera_host soc_host; - struct device *dev; /* PXA27x is only supposed to handle one camera on its Quick Capture * interface. If anyone ever builds hardware to enable more than * one camera, they will have to modify this driver too */ @@ -274,7 +273,6 @@ static void free_buffer(struct videobuf_queue *vq, struct pxa_buffer *buf) { struct soc_camera_device *icd = vq->priv_data; struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); - struct pxa_camera_dev *pcdev = ici->priv; struct videobuf_dmabuf *dma = videobuf_to_dma(&buf->vb); int i; @@ -291,7 +289,7 @@ static void free_buffer(struct videobuf_queue *vq, struct pxa_buffer *buf) for (i = 0; i < ARRAY_SIZE(buf->dmas); i++) { if (buf->dmas[i].sg_cpu) - dma_free_coherent(pcdev->dev, buf->dmas[i].sg_size, + dma_free_coherent(ici->dev, buf->dmas[i].sg_size, buf->dmas[i].sg_cpu, buf->dmas[i].sg_dma); buf->dmas[i].sg_cpu = NULL; @@ -351,14 +349,14 @@ static int pxa_init_dma_channel(struct pxa_camera_dev *pcdev, int dma_len = 0, xfer_len = 0; if (pxa_dma->sg_cpu) - dma_free_coherent(pcdev->dev, pxa_dma->sg_size, + dma_free_coherent(pcdev->soc_host.dev, pxa_dma->sg_size, pxa_dma->sg_cpu, pxa_dma->sg_dma); sglen = calculate_dma_sglen(*sg_first, dma->sglen, *sg_first_ofs, size); pxa_dma->sg_size = (sglen + 1) * sizeof(struct pxa_dma_desc); - pxa_dma->sg_cpu = dma_alloc_coherent(pcdev->dev, pxa_dma->sg_size, + pxa_dma->sg_cpu = dma_alloc_coherent(pcdev->soc_host.dev, pxa_dma->sg_size, &pxa_dma->sg_dma, GFP_KERNEL); if (!pxa_dma->sg_cpu) return -ENOMEM; @@ -366,7 +364,7 @@ static int pxa_init_dma_channel(struct pxa_camera_dev *pcdev, pxa_dma->sglen = sglen; offset = *sg_first_ofs; - dev_dbg(pcdev->dev, "DMA: sg_first=%p, sglen=%d, ofs=%d, dma.desc=%x\n", + dev_dbg(pcdev->soc_host.dev, "DMA: sg_first=%p, sglen=%d, ofs=%d, dma.desc=%x\n", *sg_first, sglen, *sg_first_ofs, pxa_dma->sg_dma); @@ -389,7 +387,7 @@ static int pxa_init_dma_channel(struct pxa_camera_dev *pcdev, pxa_dma->sg_cpu[i].ddadr = pxa_dma->sg_dma + (i + 1) * sizeof(struct pxa_dma_desc); - dev_vdbg(pcdev->dev, "DMA: desc.%08x->@phys=0x%08x, len=%d\n", + dev_vdbg(pcdev->soc_host.dev, "DMA: desc.%08x->@phys=0x%08x, len=%d\n", pxa_dma->sg_dma + i * sizeof(struct pxa_dma_desc), sg_dma_address(sg) + offset, xfer_len); offset = 0; @@ -501,7 +499,7 @@ static int pxa_videobuf_prepare(struct videobuf_queue *vq, ret = pxa_init_dma_channel(pcdev, buf, dma, 0, CIBR0, size_y, &sg, &next_ofs); if (ret) { - dev_err(pcdev->dev, + dev_err(pcdev->soc_host.dev, "DMA initialization for Y/RGB failed\n"); goto fail; } @@ -511,7 +509,7 @@ static int pxa_videobuf_prepare(struct videobuf_queue *vq, ret = pxa_init_dma_channel(pcdev, buf, dma, 1, CIBR1, size_u, &sg, &next_ofs); if (ret) { - dev_err(pcdev->dev, + dev_err(pcdev->soc_host.dev, "DMA initialization for U failed\n"); goto fail_u; } @@ -521,7 +519,7 @@ static int pxa_videobuf_prepare(struct videobuf_queue *vq, ret = pxa_init_dma_channel(pcdev, buf, dma, 2, CIBR2, size_v, &sg, &next_ofs); if (ret) { - dev_err(pcdev->dev, + dev_err(pcdev->soc_host.dev, "DMA initialization for V failed\n"); goto fail_v; } @@ -535,10 +533,10 @@ static int pxa_videobuf_prepare(struct videobuf_queue *vq, return 0; fail_v: - dma_free_coherent(pcdev->dev, buf->dmas[1].sg_size, + dma_free_coherent(pcdev->soc_host.dev, buf->dmas[1].sg_size, buf->dmas[1].sg_cpu, buf->dmas[1].sg_dma); fail_u: - dma_free_coherent(pcdev->dev, buf->dmas[0].sg_size, + dma_free_coherent(pcdev->soc_host.dev, buf->dmas[0].sg_size, buf->dmas[0].sg_cpu, buf->dmas[0].sg_dma); fail: free_buffer(vq, buf); @@ -562,7 +560,7 @@ static void pxa_dma_start_channels(struct pxa_camera_dev *pcdev) active = pcdev->active; for (i = 0; i < pcdev->channels; i++) { - dev_dbg(pcdev->dev, "%s (channel=%d) ddadr=%08x\n", __func__, + dev_dbg(pcdev->soc_host.dev, "%s (channel=%d) ddadr=%08x\n", __func__, i, active->dmas[i].sg_dma); DDADR(pcdev->dma_chans[i]) = active->dmas[i].sg_dma; DCSR(pcdev->dma_chans[i]) = DCSR_RUN; @@ -574,7 +572,7 @@ static void pxa_dma_stop_channels(struct pxa_camera_dev *pcdev) int i; for (i = 0; i < pcdev->channels; i++) { - dev_dbg(pcdev->dev, "%s (channel=%d)\n", __func__, i); + dev_dbg(pcdev->soc_host.dev, "%s (channel=%d)\n", __func__, i); DCSR(pcdev->dma_chans[i]) = 0; } } @@ -610,7 +608,7 @@ static void pxa_camera_start_capture(struct pxa_camera_dev *pcdev) { unsigned long cicr0, cifr; - dev_dbg(pcdev->dev, "%s\n", __func__); + dev_dbg(pcdev->soc_host.dev, "%s\n", __func__); /* Reset the FIFOs */ cifr = __raw_readl(pcdev->base + CIFR) | CIFR_RESET_F; __raw_writel(cifr, pcdev->base + CIFR); @@ -630,7 +628,7 @@ static void pxa_camera_stop_capture(struct pxa_camera_dev *pcdev) __raw_writel(cicr0, pcdev->base + CICR0); pcdev->active = NULL; - dev_dbg(pcdev->dev, "%s\n", __func__); + dev_dbg(pcdev->soc_host.dev, "%s\n", __func__); } static void pxa_videobuf_queue(struct videobuf_queue *vq, @@ -699,7 +697,7 @@ static void pxa_camera_wakeup(struct pxa_camera_dev *pcdev, do_gettimeofday(&vb->ts); vb->field_count++; wake_up(&vb->done); - dev_dbg(pcdev->dev, "%s dequeud buffer (vb=0x%p)\n", __func__, vb); + dev_dbg(pcdev->soc_host.dev, "%s dequeud buffer (vb=0x%p)\n", __func__, vb); if (list_empty(&pcdev->capture)) { pxa_camera_stop_capture(pcdev); @@ -735,7 +733,7 @@ static void pxa_camera_check_link_miss(struct pxa_camera_dev *pcdev) for (i = 0; i < pcdev->channels; i++) if (DDADR(pcdev->dma_chans[i]) != DDADR_STOP) is_dma_stopped = 0; - dev_dbg(pcdev->dev, "%s : top queued buffer=%p, dma_stopped=%d\n", + dev_dbg(pcdev->soc_host.dev, "%s : top queued buffer=%p, dma_stopped=%d\n", __func__, pcdev->active, is_dma_stopped); if (pcdev->active && is_dma_stopped) pxa_camera_start_capture(pcdev); @@ -760,12 +758,12 @@ static void pxa_camera_dma_irq(int channel, struct pxa_camera_dev *pcdev, overrun |= CISR_IFO_1 | CISR_IFO_2; if (status & DCSR_BUSERR) { - dev_err(pcdev->dev, "DMA Bus Error IRQ!\n"); + dev_err(pcdev->soc_host.dev, "DMA Bus Error IRQ!\n"); goto out; } if (!(status & (DCSR_ENDINTR | DCSR_STARTINTR))) { - dev_err(pcdev->dev, "Unknown DMA IRQ source, " + dev_err(pcdev->soc_host.dev, "Unknown DMA IRQ source, " "status: 0x%08x\n", status); goto out; } @@ -789,7 +787,7 @@ static void pxa_camera_dma_irq(int channel, struct pxa_camera_dev *pcdev, buf = container_of(vb, struct pxa_buffer, vb); WARN_ON(buf->inwork || list_empty(&vb->queue)); - dev_dbg(pcdev->dev, "%s channel=%d %s%s(vb=0x%p) dma.desc=%x\n", + dev_dbg(pcdev->soc_host.dev, "%s channel=%d %s%s(vb=0x%p) dma.desc=%x\n", __func__, channel, status & DCSR_STARTINTR ? "SOF " : "", status & DCSR_ENDINTR ? "EOF " : "", vb, DDADR(channel)); @@ -800,7 +798,7 @@ static void pxa_camera_dma_irq(int channel, struct pxa_camera_dev *pcdev, */ if (camera_status & overrun && !list_is_last(pcdev->capture.next, &pcdev->capture)) { - dev_dbg(pcdev->dev, "FIFO overrun! CISR: %x\n", + dev_dbg(pcdev->soc_host.dev, "FIFO overrun! CISR: %x\n", camera_status); pxa_camera_stop_capture(pcdev); pxa_camera_start_capture(pcdev); @@ -867,7 +865,7 @@ static u32 mclk_get_divisor(struct pxa_camera_dev *pcdev) /* mclk <= ciclk / 4 (27.4.2) */ if (mclk > lcdclk / 4) { mclk = lcdclk / 4; - dev_warn(pcdev->dev, "Limiting master clock to %lu\n", mclk); + dev_warn(pcdev->soc_host.dev, "Limiting master clock to %lu\n", mclk); } /* We verify mclk != 0, so if anyone breaks it, here comes their Oops */ @@ -877,7 +875,7 @@ static u32 mclk_get_divisor(struct pxa_camera_dev *pcdev) if (pcdev->platform_flags & PXA_CAMERA_MCLK_EN) pcdev->mclk = lcdclk / (2 * (div + 1)); - dev_dbg(pcdev->dev, "LCD clock %luHz, target freq %luHz, " + dev_dbg(pcdev->soc_host.dev, "LCD clock %luHz, target freq %luHz, " "divisor %u\n", lcdclk, mclk, div); return div; @@ -897,12 +895,12 @@ static void pxa_camera_activate(struct pxa_camera_dev *pcdev) struct pxacamera_platform_data *pdata = pcdev->pdata; u32 cicr4 = 0; - dev_dbg(pcdev->dev, "Registered platform device at %p data %p\n", + dev_dbg(pcdev->soc_host.dev, "Registered platform device at %p data %p\n", pcdev, pdata); if (pdata && pdata->init) { - dev_dbg(pcdev->dev, "%s: Init gpios\n", __func__); - pdata->init(pcdev->dev); + dev_dbg(pcdev->soc_host.dev, "%s: Init gpios\n", __func__); + pdata->init(pcdev->soc_host.dev); } /* disable all interrupts */ @@ -944,7 +942,7 @@ static irqreturn_t pxa_camera_irq(int irq, void *data) struct videobuf_buffer *vb; status = __raw_readl(pcdev->base + CISR); - dev_dbg(pcdev->dev, "Camera interrupt status 0x%lx\n", status); + dev_dbg(pcdev->soc_host.dev, "Camera interrupt status 0x%lx\n", status); if (!status) return IRQ_NONE; @@ -1272,7 +1270,7 @@ static int pxa_camera_get_formats(struct soc_camera_device *icd, int idx, xlate->cam_fmt = icd->formats + idx; xlate->buswidth = buswidth; xlate++; - dev_dbg(&ici->dev, "Providing format %s using %s\n", + dev_dbg(ici->dev, "Providing format %s using %s\n", pxa_camera_formats[0].name, icd->formats[idx].name); } @@ -1287,7 +1285,7 @@ static int pxa_camera_get_formats(struct soc_camera_device *icd, int idx, xlate->cam_fmt = icd->formats + idx; xlate->buswidth = buswidth; xlate++; - dev_dbg(&ici->dev, "Providing format %s packed\n", + dev_dbg(ici->dev, "Providing format %s packed\n", icd->formats[idx].name); } break; @@ -1299,7 +1297,7 @@ static int pxa_camera_get_formats(struct soc_camera_device *icd, int idx, xlate->cam_fmt = icd->formats + idx; xlate->buswidth = icd->formats[idx].depth; xlate++; - dev_dbg(&ici->dev, + dev_dbg(ici->dev, "Providing format %s in pass-through mode\n", icd->formats[idx].name); } @@ -1328,11 +1326,11 @@ static int pxa_camera_set_crop(struct soc_camera_device *icd, icd->sense = NULL; if (ret < 0) { - dev_warn(&ici->dev, "Failed to crop to %ux%u@%u:%u\n", + dev_warn(ici->dev, "Failed to crop to %ux%u@%u:%u\n", rect->width, rect->height, rect->left, rect->top); } else if (sense.flags & SOCAM_SENSE_PCLK_CHANGED) { if (sense.pixel_clock > sense.pixel_clock_max) { - dev_err(&ici->dev, + dev_err(ici->dev, "pixel clock %lu set by the camera too high!", sense.pixel_clock); return -EIO; @@ -1360,7 +1358,7 @@ static int pxa_camera_set_fmt(struct soc_camera_device *icd, xlate = soc_camera_xlate_by_fourcc(icd, pix->pixelformat); if (!xlate) { - dev_warn(&ici->dev, "Format %x not found\n", pix->pixelformat); + dev_warn(ici->dev, "Format %x not found\n", pix->pixelformat); return -EINVAL; } @@ -1376,11 +1374,11 @@ static int pxa_camera_set_fmt(struct soc_camera_device *icd, icd->sense = NULL; if (ret < 0) { - dev_warn(&ici->dev, "Failed to configure for format %x\n", + dev_warn(ici->dev, "Failed to configure for format %x\n", pix->pixelformat); } else if (sense.flags & SOCAM_SENSE_PCLK_CHANGED) { if (sense.pixel_clock > sense.pixel_clock_max) { - dev_err(&ici->dev, + dev_err(ici->dev, "pixel clock %lu set by the camera too high!", sense.pixel_clock); return -EIO; @@ -1408,7 +1406,7 @@ static int pxa_camera_try_fmt(struct soc_camera_device *icd, xlate = soc_camera_xlate_by_fourcc(icd, pixfmt); if (!xlate) { - dev_warn(&ici->dev, "Format %x not found\n", pixfmt); + dev_warn(ici->dev, "Format %x not found\n", pixfmt); return -EINVAL; } @@ -1593,7 +1591,6 @@ static int pxa_camera_probe(struct platform_device *pdev) goto exit_kfree; } - platform_set_drvdata(pdev, pcdev); pcdev->res = res; pcdev->pdata = pdev->dev.platform_data; @@ -1614,7 +1611,6 @@ static int pxa_camera_probe(struct platform_device *pdev) pcdev->mclk = 20000000; } - pcdev->dev = &pdev->dev; pcdev->mclk_divisor = mclk_get_divisor(pcdev); INIT_LIST_HEAD(&pcdev->capture); @@ -1641,29 +1637,29 @@ static int pxa_camera_probe(struct platform_device *pdev) err = pxa_request_dma("CI_Y", DMA_PRIO_HIGH, pxa_camera_dma_irq_y, pcdev); if (err < 0) { - dev_err(pcdev->dev, "Can't request DMA for Y\n"); + dev_err(&pdev->dev, "Can't request DMA for Y\n"); goto exit_iounmap; } pcdev->dma_chans[0] = err; - dev_dbg(pcdev->dev, "got DMA channel %d\n", pcdev->dma_chans[0]); + dev_dbg(&pdev->dev, "got DMA channel %d\n", pcdev->dma_chans[0]); err = pxa_request_dma("CI_U", DMA_PRIO_HIGH, pxa_camera_dma_irq_u, pcdev); if (err < 0) { - dev_err(pcdev->dev, "Can't request DMA for U\n"); + dev_err(&pdev->dev, "Can't request DMA for U\n"); goto exit_free_dma_y; } pcdev->dma_chans[1] = err; - dev_dbg(pcdev->dev, "got DMA channel (U) %d\n", pcdev->dma_chans[1]); + dev_dbg(&pdev->dev, "got DMA channel (U) %d\n", pcdev->dma_chans[1]); err = pxa_request_dma("CI_V", DMA_PRIO_HIGH, pxa_camera_dma_irq_v, pcdev); if (err < 0) { - dev_err(pcdev->dev, "Can't request DMA for V\n"); + dev_err(&pdev->dev, "Can't request DMA for V\n"); goto exit_free_dma_u; } pcdev->dma_chans[2] = err; - dev_dbg(pcdev->dev, "got DMA channel (V) %d\n", pcdev->dma_chans[2]); + dev_dbg(&pdev->dev, "got DMA channel (V) %d\n", pcdev->dma_chans[2]); DRCMR(68) = pcdev->dma_chans[0] | DRCMR_MAPVLD; DRCMR(69) = pcdev->dma_chans[1] | DRCMR_MAPVLD; @@ -1673,15 +1669,16 @@ static int pxa_camera_probe(struct platform_device *pdev) err = request_irq(pcdev->irq, pxa_camera_irq, 0, PXA_CAM_DRV_NAME, pcdev); if (err) { - dev_err(pcdev->dev, "Camera interrupt register failed \n"); + dev_err(&pdev->dev, "Camera interrupt register failed \n"); goto exit_free_dma; } pcdev->soc_host.drv_name = PXA_CAM_DRV_NAME; pcdev->soc_host.ops = &pxa_soc_camera_host_ops; pcdev->soc_host.priv = pcdev; - pcdev->soc_host.dev.parent = &pdev->dev; + pcdev->soc_host.dev = &pdev->dev; pcdev->soc_host.nr = pdev->id; + err = soc_camera_host_register(&pcdev->soc_host); if (err) goto exit_free_irq; @@ -1710,7 +1707,9 @@ exit: static int __devexit pxa_camera_remove(struct platform_device *pdev) { - struct pxa_camera_dev *pcdev = platform_get_drvdata(pdev); + struct soc_camera_host *soc_host = to_soc_camera_host(&pdev->dev); + struct pxa_camera_dev *pcdev = container_of(soc_host, + struct pxa_camera_dev, soc_host); struct resource *res; clk_put(pcdev->clk); @@ -1720,7 +1719,7 @@ static int __devexit pxa_camera_remove(struct platform_device *pdev) pxa_free_dma(pcdev->dma_chans[2]); free_irq(pcdev->irq, pcdev); - soc_camera_host_unregister(&pcdev->soc_host); + soc_camera_host_unregister(soc_host); iounmap(pcdev->base); diff --git a/linux/drivers/media/video/sh_mobile_ceu_camera.c b/linux/drivers/media/video/sh_mobile_ceu_camera.c index 0647f3724..bf0b176f9 100644 --- a/linux/drivers/media/video/sh_mobile_ceu_camera.c +++ b/linux/drivers/media/video/sh_mobile_ceu_camera.c @@ -82,7 +82,6 @@ struct sh_mobile_ceu_buffer { }; struct sh_mobile_ceu_dev { - struct device *dev; struct soc_camera_host ici; struct soc_camera_device *icd; @@ -618,7 +617,7 @@ static int sh_mobile_ceu_get_formats(struct soc_camera_device *icd, int idx, xlate->cam_fmt = icd->formats + idx; xlate->buswidth = icd->formats[idx].depth; xlate++; - dev_dbg(&ici->dev, "Providing format %s using %s\n", + dev_dbg(ici->dev, "Providing format %s using %s\n", sh_mobile_ceu_formats[k].name, icd->formats[idx].name); } @@ -631,7 +630,7 @@ add_single_format: xlate->cam_fmt = icd->formats + idx; xlate->buswidth = icd->formats[idx].depth; xlate++; - dev_dbg(&ici->dev, + dev_dbg(ici->dev, "Providing format %s in pass-through mode\n", icd->formats[idx].name); } @@ -658,7 +657,7 @@ static int sh_mobile_ceu_set_fmt(struct soc_camera_device *icd, xlate = soc_camera_xlate_by_fourcc(icd, pixfmt); if (!xlate) { - dev_warn(&ici->dev, "Format %x not found\n", pixfmt); + dev_warn(ici->dev, "Format %x not found\n", pixfmt); return -EINVAL; } @@ -685,7 +684,7 @@ static int sh_mobile_ceu_try_fmt(struct soc_camera_device *icd, xlate = soc_camera_xlate_by_fourcc(icd, pixfmt); if (!xlate) { - dev_warn(&ici->dev, "Format %x not found\n", pixfmt); + dev_warn(ici->dev, "Format %x not found\n", pixfmt); return -EINVAL; } @@ -783,7 +782,7 @@ static void sh_mobile_ceu_init_videobuf(struct videobuf_queue *q, videobuf_queue_dma_contig_init(q, &sh_mobile_ceu_videobuf_ops, - &ici->dev, &pcdev->lock, + ici->dev, &pcdev->lock, V4L2_BUF_TYPE_VIDEO_CAPTURE, pcdev->is_interlaced ? V4L2_FIELD_INTERLACED : V4L2_FIELD_NONE, @@ -830,7 +829,6 @@ static int sh_mobile_ceu_probe(struct platform_device *pdev) goto exit; } - platform_set_drvdata(pdev, pcdev); INIT_LIST_HEAD(&pcdev->capture); spin_lock_init(&pcdev->lock); @@ -851,7 +849,6 @@ static int sh_mobile_ceu_probe(struct platform_device *pdev) pcdev->irq = irq; pcdev->base = base; pcdev->video_limit = 0; /* only enabled if second resource exists */ - pcdev->dev = &pdev->dev; res = platform_get_resource(pdev, IORESOURCE_MEM, 1); if (res) { @@ -886,7 +883,7 @@ static int sh_mobile_ceu_probe(struct platform_device *pdev) } pcdev->ici.priv = pcdev; - pcdev->ici.dev.parent = &pdev->dev; + pcdev->ici.dev = &pdev->dev; pcdev->ici.nr = pdev->id; pcdev->ici.drv_name = dev_name(&pdev->dev); pcdev->ici.ops = &sh_mobile_ceu_host_ops; @@ -914,9 +911,11 @@ exit: static int sh_mobile_ceu_remove(struct platform_device *pdev) { - struct sh_mobile_ceu_dev *pcdev = platform_get_drvdata(pdev); + struct soc_camera_host *soc_host = to_soc_camera_host(&pdev->dev); + struct sh_mobile_ceu_dev *pcdev = container_of(soc_host, + struct sh_mobile_ceu_dev, ici); - soc_camera_host_unregister(&pcdev->ici); + soc_camera_host_unregister(soc_host); clk_put(pcdev->clk); free_irq(pcdev->irq, pcdev); if (platform_get_resource(pdev, IORESOURCE_MEM, 1)) diff --git a/linux/drivers/media/video/soc_camera.c b/linux/drivers/media/video/soc_camera.c index 9e432d390..9dca8f470 100644 --- a/linux/drivers/media/video/soc_camera.c +++ b/linux/drivers/media/video/soc_camera.c @@ -280,7 +280,7 @@ static int soc_camera_set_fmt(struct soc_camera_file *icf, return ret; } else if (!icd->current_fmt || icd->current_fmt->fourcc != pix->pixelformat) { - dev_err(&ici->dev, + dev_err(ici->dev, "Host driver hasn't set up current format correctly!\n"); return -EINVAL; } @@ -795,7 +795,7 @@ static void scan_add_host(struct soc_camera_host *ici) list_for_each_entry(icd, &devices, list) { if (icd->iface == ici->nr) { - icd->dev.parent = &ici->dev; + icd->dev.parent = ici->dev; device_register_link(icd); } } @@ -819,7 +819,7 @@ static int scan_add_device(struct soc_camera_device *icd) list_for_each_entry(ici, &hosts, list) { if (icd->iface == ici->nr) { ret = 1; - icd->dev.parent = &ici->dev; + icd->dev.parent = ici->dev; break; } } @@ -953,7 +953,6 @@ static void dummy_release(struct device *dev) int soc_camera_host_register(struct soc_camera_host *ici) { - int ret; struct soc_camera_host *ix; if (!ici || !ici->ops || @@ -966,12 +965,10 @@ int soc_camera_host_register(struct soc_camera_host *ici) !ici->ops->reqbufs || !ici->ops->add || !ici->ops->remove || - !ici->ops->poll) + !ici->ops->poll || + !ici->dev) return -EINVAL; - /* Number might be equal to the platform device ID */ - dev_set_name(&ici->dev, "camera_host%d", ici->nr); - mutex_lock(&list_lock); list_for_each_entry(ix, &hosts, list) { if (ix->nr == ici->nr) { @@ -980,26 +977,14 @@ int soc_camera_host_register(struct soc_camera_host *ici) } } + dev_set_drvdata(ici->dev, ici); + list_add_tail(&ici->list, &hosts); mutex_unlock(&list_lock); - ici->dev.release = dummy_release; - - ret = device_register(&ici->dev); - - if (ret) - goto edevr; - scan_add_host(ici); return 0; - -edevr: - mutex_lock(&list_lock); - list_del(&ici->list); - mutex_unlock(&list_lock); - - return ret; } EXPORT_SYMBOL(soc_camera_host_register); @@ -1013,7 +998,7 @@ void soc_camera_host_unregister(struct soc_camera_host *ici) list_del(&ici->list); list_for_each_entry(icd, &devices, list) { - if (icd->dev.parent == &ici->dev) { + if (icd->dev.parent == ici->dev) { device_unregister(&icd->dev); /* Not before device_unregister(), .remove * needs parent to call ici->ops->remove() */ @@ -1024,7 +1009,7 @@ void soc_camera_host_unregister(struct soc_camera_host *ici) mutex_unlock(&list_lock); - device_unregister(&ici->dev); + dev_set_drvdata(ici->dev, NULL); } EXPORT_SYMBOL(soc_camera_host_unregister); @@ -1131,7 +1116,7 @@ int soc_camera_video_start(struct soc_camera_device *icd) vdev = video_device_alloc(); if (!vdev) goto evidallocd; - dev_dbg(&ici->dev, "Allocated video_device %p\n", vdev); + dev_dbg(ici->dev, "Allocated video_device %p\n", vdev); strlcpy(vdev->name, ici->drv_name, sizeof(vdev->name)); -- cgit v1.2.3 From 8cef54b05d22c813f03e2df886dbd50c5a135085 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Fri, 24 Apr 2009 17:57:01 +0200 Subject: soc-camera: simplify register access routines in multiple sensor drivers From: Guennadi Liakhovetski Register access routines only need the I2C client, not the soc-camera device context. Signed-off-by: Guennadi Liakhovetski --- drivers/media/video/mt9m001.c | 105 +++++++++++++++++--------------- drivers/media/video/mt9m111.c | 73 ++++++++++++---------- drivers/media/video/mt9t031.c | 135 +++++++++++++++++++++------------------- drivers/media/video/mt9v022.c | 135 +++++++++++++++++++++-------------------- 4 files changed, 236 insertions(+), 212 deletions(-) --- linux/drivers/media/video/mt9m001.c | 105 +++++++++++++++------------- linux/drivers/media/video/mt9m111.c | 73 ++++++++++--------- linux/drivers/media/video/mt9t031.c | 135 +++++++++++++++++++----------------- linux/drivers/media/video/mt9v022.c | 135 +++++++++++++++++++----------------- 4 files changed, 236 insertions(+), 212 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/mt9m001.c b/linux/drivers/media/video/mt9m001.c index 959edc760..8d61ad30a 100644 --- a/linux/drivers/media/video/mt9m001.c +++ b/linux/drivers/media/video/mt9m001.c @@ -75,53 +75,50 @@ struct mt9m001 { unsigned char autoexposure; }; -static int reg_read(struct soc_camera_device *icd, const u8 reg) +static int reg_read(struct i2c_client *client, const u8 reg) { - struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd); - struct i2c_client *client = mt9m001->client; s32 data = i2c_smbus_read_word_data(client, reg); return data < 0 ? data : swab16(data); } -static int reg_write(struct soc_camera_device *icd, const u8 reg, +static int reg_write(struct i2c_client *client, const u8 reg, const u16 data) { - struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd); - return i2c_smbus_write_word_data(mt9m001->client, reg, swab16(data)); + return i2c_smbus_write_word_data(client, reg, swab16(data)); } -static int reg_set(struct soc_camera_device *icd, const u8 reg, +static int reg_set(struct i2c_client *client, const u8 reg, const u16 data) { int ret; - ret = reg_read(icd, reg); + ret = reg_read(client, reg); if (ret < 0) return ret; - return reg_write(icd, reg, ret | data); + return reg_write(client, reg, ret | data); } -static int reg_clear(struct soc_camera_device *icd, const u8 reg, +static int reg_clear(struct i2c_client *client, const u8 reg, const u16 data) { int ret; - ret = reg_read(icd, reg); + ret = reg_read(client, reg); if (ret < 0) return ret; - return reg_write(icd, reg, ret & ~data); + return reg_write(client, reg, ret & ~data); } static int mt9m001_init(struct soc_camera_device *icd) { - struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd); - struct soc_camera_link *icl = mt9m001->client->dev.platform_data; + struct i2c_client *client = to_i2c_client(icd->control); + struct soc_camera_link *icl = client->dev.platform_data; int ret; dev_dbg(icd->vdev->parent, "%s\n", __func__); if (icl->power) { - ret = icl->power(&mt9m001->client->dev, 1); + ret = icl->power(&client->dev, 1); if (ret < 0) { dev_err(icd->vdev->parent, "Platform failed to power-on the camera.\n"); @@ -131,49 +128,53 @@ static int mt9m001_init(struct soc_camera_device *icd) /* The camera could have been already on, we reset it additionally */ if (icl->reset) - ret = icl->reset(&mt9m001->client->dev); + ret = icl->reset(&client->dev); else ret = -ENODEV; if (ret < 0) { /* Either no platform reset, or platform reset failed */ - ret = reg_write(icd, MT9M001_RESET, 1); + ret = reg_write(client, MT9M001_RESET, 1); if (!ret) - ret = reg_write(icd, MT9M001_RESET, 0); + ret = reg_write(client, MT9M001_RESET, 0); } /* Disable chip, synchronous option update */ if (!ret) - ret = reg_write(icd, MT9M001_OUTPUT_CONTROL, 0); + ret = reg_write(client, MT9M001_OUTPUT_CONTROL, 0); return ret; } static int mt9m001_release(struct soc_camera_device *icd) { - struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd); - struct soc_camera_link *icl = mt9m001->client->dev.platform_data; + struct i2c_client *client = to_i2c_client(icd->control); + struct soc_camera_link *icl = client->dev.platform_data; /* Disable the chip */ - reg_write(icd, MT9M001_OUTPUT_CONTROL, 0); + reg_write(client, MT9M001_OUTPUT_CONTROL, 0); if (icl->power) - icl->power(&mt9m001->client->dev, 0); + icl->power(&client->dev, 0); return 0; } static int mt9m001_start_capture(struct soc_camera_device *icd) { + struct i2c_client *client = to_i2c_client(icd->control); + /* Switch to master "normal" mode */ - if (reg_write(icd, MT9M001_OUTPUT_CONTROL, 2) < 0) + if (reg_write(client, MT9M001_OUTPUT_CONTROL, 2) < 0) return -EIO; return 0; } static int mt9m001_stop_capture(struct soc_camera_device *icd) { + struct i2c_client *client = to_i2c_client(icd->control); + /* Stop sensor readout */ - if (reg_write(icd, MT9M001_OUTPUT_CONTROL, 0) < 0) + if (reg_write(client, MT9M001_OUTPUT_CONTROL, 0) < 0) return -EIO; return 0; } @@ -222,28 +223,29 @@ static unsigned long mt9m001_query_bus_param(struct soc_camera_device *icd) static int mt9m001_set_crop(struct soc_camera_device *icd, struct v4l2_rect *rect) { + struct i2c_client *client = to_i2c_client(icd->control); struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd); int ret; const u16 hblank = 9, vblank = 25; /* Blanking and start values - default... */ - ret = reg_write(icd, MT9M001_HORIZONTAL_BLANKING, hblank); + ret = reg_write(client, MT9M001_HORIZONTAL_BLANKING, hblank); if (!ret) - ret = reg_write(icd, MT9M001_VERTICAL_BLANKING, vblank); + ret = reg_write(client, MT9M001_VERTICAL_BLANKING, vblank); /* The caller provides a supported format, as verified per * call to icd->try_fmt() */ if (!ret) - ret = reg_write(icd, MT9M001_COLUMN_START, rect->left); + ret = reg_write(client, MT9M001_COLUMN_START, rect->left); if (!ret) - ret = reg_write(icd, MT9M001_ROW_START, rect->top); + ret = reg_write(client, MT9M001_ROW_START, rect->top); if (!ret) - ret = reg_write(icd, MT9M001_WINDOW_WIDTH, rect->width - 1); + ret = reg_write(client, MT9M001_WINDOW_WIDTH, rect->width - 1); if (!ret) - ret = reg_write(icd, MT9M001_WINDOW_HEIGHT, + ret = reg_write(client, MT9M001_WINDOW_HEIGHT, rect->height + icd->y_skip_top - 1); if (!ret && mt9m001->autoexposure) { - ret = reg_write(icd, MT9M001_SHUTTER_WIDTH, + ret = reg_write(client, MT9M001_SHUTTER_WIDTH, rect->height + icd->y_skip_top + vblank); if (!ret) { const struct v4l2_queryctrl *qctrl = @@ -312,16 +314,16 @@ static int mt9m001_get_chip_id(struct soc_camera_device *icd, static int mt9m001_get_register(struct soc_camera_device *icd, struct v4l2_dbg_register *reg) { - struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd); + struct i2c_client *client = to_i2c_client(icd->control); if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff) return -EINVAL; - if (reg->match.addr != mt9m001->client->addr) + if (reg->match.addr != client->addr) return -ENODEV; reg->size = 2; - reg->val = reg_read(icd, reg->reg); + reg->val = reg_read(client, reg->reg); if (reg->val > 0xffff) return -EIO; @@ -332,15 +334,15 @@ static int mt9m001_get_register(struct soc_camera_device *icd, static int mt9m001_set_register(struct soc_camera_device *icd, struct v4l2_dbg_register *reg) { - struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd); + struct i2c_client *client = to_i2c_client(icd->control); if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff) return -EINVAL; - if (reg->match.addr != mt9m001->client->addr) + if (reg->match.addr != client->addr) return -ENODEV; - if (reg_write(icd, reg->reg, reg->val) < 0) + if (reg_write(client, reg->reg, reg->val) < 0) return -EIO; return 0; @@ -416,12 +418,13 @@ static struct soc_camera_ops mt9m001_ops = { static int mt9m001_get_control(struct soc_camera_device *icd, struct v4l2_control *ctrl) { + struct i2c_client *client = to_i2c_client(icd->control); struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd); int data; switch (ctrl->id) { case V4L2_CID_VFLIP: - data = reg_read(icd, MT9M001_READ_OPTIONS2); + data = reg_read(client, MT9M001_READ_OPTIONS2); if (data < 0) return -EIO; ctrl->value = !!(data & 0x8000); @@ -435,6 +438,7 @@ static int mt9m001_get_control(struct soc_camera_device *icd, struct v4l2_contro static int mt9m001_set_control(struct soc_camera_device *icd, struct v4l2_control *ctrl) { + struct i2c_client *client = to_i2c_client(icd->control); struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd); const struct v4l2_queryctrl *qctrl; int data; @@ -447,9 +451,9 @@ static int mt9m001_set_control(struct soc_camera_device *icd, struct v4l2_contro switch (ctrl->id) { case V4L2_CID_VFLIP: if (ctrl->value) - data = reg_set(icd, MT9M001_READ_OPTIONS2, 0x8000); + data = reg_set(client, MT9M001_READ_OPTIONS2, 0x8000); else - data = reg_clear(icd, MT9M001_READ_OPTIONS2, 0x8000); + data = reg_clear(client, MT9M001_READ_OPTIONS2, 0x8000); if (data < 0) return -EIO; break; @@ -463,7 +467,7 @@ static int mt9m001_set_control(struct soc_camera_device *icd, struct v4l2_contro data = ((ctrl->value - qctrl->minimum) * 8 + range / 2) / range; dev_dbg(&icd->dev, "Setting gain %d\n", data); - data = reg_write(icd, MT9M001_GLOBAL_GAIN, data); + data = reg_write(client, MT9M001_GLOBAL_GAIN, data); if (data < 0) return -EIO; } else { @@ -481,8 +485,8 @@ static int mt9m001_set_control(struct soc_camera_device *icd, struct v4l2_contro data = ((gain - 64) * 7 + 28) / 56 + 96; dev_dbg(&icd->dev, "Setting gain from %d to %d\n", - reg_read(icd, MT9M001_GLOBAL_GAIN), data); - data = reg_write(icd, MT9M001_GLOBAL_GAIN, data); + reg_read(client, MT9M001_GLOBAL_GAIN), data); + data = reg_write(client, MT9M001_GLOBAL_GAIN, data); if (data < 0) return -EIO; } @@ -500,8 +504,8 @@ static int mt9m001_set_control(struct soc_camera_device *icd, struct v4l2_contro range / 2) / range + 1; dev_dbg(&icd->dev, "Setting shutter width from %d to %lu\n", - reg_read(icd, MT9M001_SHUTTER_WIDTH), shutter); - if (reg_write(icd, MT9M001_SHUTTER_WIDTH, shutter) < 0) + reg_read(client, MT9M001_SHUTTER_WIDTH), shutter); + if (reg_write(client, MT9M001_SHUTTER_WIDTH, shutter) < 0) return -EIO; icd->exposure = ctrl->value; mt9m001->autoexposure = 0; @@ -510,7 +514,7 @@ static int mt9m001_set_control(struct soc_camera_device *icd, struct v4l2_contro case V4L2_CID_EXPOSURE_AUTO: if (ctrl->value) { const u16 vblank = 25; - if (reg_write(icd, MT9M001_SHUTTER_WIDTH, icd->height + + if (reg_write(client, MT9M001_SHUTTER_WIDTH, icd->height + icd->y_skip_top + vblank) < 0) return -EIO; qctrl = soc_camera_find_qctrl(icd->ops, V4L2_CID_EXPOSURE); @@ -529,8 +533,9 @@ static int mt9m001_set_control(struct soc_camera_device *icd, struct v4l2_contro * this wasn't our capture interface, so, we wait for the right one */ static int mt9m001_video_probe(struct soc_camera_device *icd) { + struct i2c_client *client = to_i2c_client(icd->control); struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd); - struct soc_camera_link *icl = mt9m001->client->dev.platform_data; + struct soc_camera_link *icl = client->dev.platform_data; s32 data; int ret; unsigned long flags; @@ -542,11 +547,11 @@ static int mt9m001_video_probe(struct soc_camera_device *icd) return -ENODEV; /* Enable the chip */ - data = reg_write(icd, MT9M001_CHIP_ENABLE, 1); + data = reg_write(client, MT9M001_CHIP_ENABLE, 1); dev_dbg(&icd->dev, "write: %d\n", data); /* Read out the chip version register */ - data = reg_read(icd, MT9M001_CHIP_VERSION); + data = reg_read(client, MT9M001_CHIP_VERSION); /* must be 0x8411 or 0x8421 for colour sensor and 8431 for bw */ switch (data) { diff --git a/linux/drivers/media/video/mt9m111.c b/linux/drivers/media/video/mt9m111.c index 69498d519..77639ae5c 100644 --- a/linux/drivers/media/video/mt9m111.c +++ b/linux/drivers/media/video/mt9m111.c @@ -113,10 +113,10 @@ * mt9m111: Camera control register addresses (0x200..0x2ff not implemented) */ -#define reg_read(reg) mt9m111_reg_read(icd, MT9M111_##reg) -#define reg_write(reg, val) mt9m111_reg_write(icd, MT9M111_##reg, (val)) -#define reg_set(reg, val) mt9m111_reg_set(icd, MT9M111_##reg, (val)) -#define reg_clear(reg, val) mt9m111_reg_clear(icd, MT9M111_##reg, (val)) +#define reg_read(reg) mt9m111_reg_read(client, MT9M111_##reg) +#define reg_write(reg, val) mt9m111_reg_write(client, MT9M111_##reg, (val)) +#define reg_set(reg, val) mt9m111_reg_set(client, MT9M111_##reg, (val)) +#define reg_clear(reg, val) mt9m111_reg_clear(client, MT9M111_##reg, (val)) #define MT9M111_MIN_DARK_ROWS 8 #define MT9M111_MIN_DARK_COLS 24 @@ -184,58 +184,55 @@ static int reg_page_map_set(struct i2c_client *client, const u16 reg) return ret; } -static int mt9m111_reg_read(struct soc_camera_device *icd, const u16 reg) +static int mt9m111_reg_read(struct i2c_client *client, const u16 reg) { - struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); - struct i2c_client *client = mt9m111->client; int ret; ret = reg_page_map_set(client, reg); if (!ret) ret = swab16(i2c_smbus_read_word_data(client, (reg & 0xff))); - dev_dbg(&icd->dev, "read reg.%03x -> %04x\n", reg, ret); + dev_dbg(&client->dev, "read reg.%03x -> %04x\n", reg, ret); return ret; } -static int mt9m111_reg_write(struct soc_camera_device *icd, const u16 reg, +static int mt9m111_reg_write(struct i2c_client *client, const u16 reg, const u16 data) { - struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); - struct i2c_client *client = mt9m111->client; int ret; ret = reg_page_map_set(client, reg); if (!ret) - ret = i2c_smbus_write_word_data(mt9m111->client, (reg & 0xff), + ret = i2c_smbus_write_word_data(client, (reg & 0xff), swab16(data)); - dev_dbg(&icd->dev, "write reg.%03x = %04x -> %d\n", reg, data, ret); + dev_dbg(&client->dev, "write reg.%03x = %04x -> %d\n", reg, data, ret); return ret; } -static int mt9m111_reg_set(struct soc_camera_device *icd, const u16 reg, +static int mt9m111_reg_set(struct i2c_client *client, const u16 reg, const u16 data) { int ret; - ret = mt9m111_reg_read(icd, reg); + ret = mt9m111_reg_read(client, reg); if (ret >= 0) - ret = mt9m111_reg_write(icd, reg, ret | data); + ret = mt9m111_reg_write(client, reg, ret | data); return ret; } -static int mt9m111_reg_clear(struct soc_camera_device *icd, const u16 reg, +static int mt9m111_reg_clear(struct i2c_client *client, const u16 reg, const u16 data) { int ret; - ret = mt9m111_reg_read(icd, reg); - return mt9m111_reg_write(icd, reg, ret & ~data); + ret = mt9m111_reg_read(client, reg); + return mt9m111_reg_write(client, reg, ret & ~data); } static int mt9m111_set_context(struct soc_camera_device *icd, enum mt9m111_context ctxt) { + struct i2c_client *client = to_i2c_client(icd->control); int valB = MT9M111_CTXT_CTRL_RESTART | MT9M111_CTXT_CTRL_DEFECTCOR_B | MT9M111_CTXT_CTRL_RESIZE_B | MT9M111_CTXT_CTRL_CTRL2_B | MT9M111_CTXT_CTRL_GAMMA_B | MT9M111_CTXT_CTRL_READ_MODE_B @@ -252,6 +249,7 @@ static int mt9m111_set_context(struct soc_camera_device *icd, static int mt9m111_setup_rect(struct soc_camera_device *icd, struct v4l2_rect *rect) { + struct i2c_client *client = to_i2c_client(icd->control); struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); int ret, is_raw_format; int width = rect->width; @@ -296,6 +294,7 @@ static int mt9m111_setup_rect(struct soc_camera_device *icd, static int mt9m111_setup_pixfmt(struct soc_camera_device *icd, u16 outfmt) { + struct i2c_client *client = to_i2c_client(icd->control); int ret; ret = reg_write(OUTPUT_FORMAT_CTRL2_A, outfmt); @@ -357,12 +356,13 @@ static int mt9m111_setfmt_yuv(struct soc_camera_device *icd) static int mt9m111_enable(struct soc_camera_device *icd) { + struct i2c_client *client = to_i2c_client(icd->control); struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); - struct soc_camera_link *icl = mt9m111->client->dev.platform_data; + struct soc_camera_link *icl = client->dev.platform_data; int ret; if (icl->power) { - ret = icl->power(&mt9m111->client->dev, 1); + ret = icl->power(&client->dev, 1); if (ret < 0) { dev_err(icd->vdev->parent, "Platform failed to power-on the camera.\n"); @@ -378,8 +378,9 @@ static int mt9m111_enable(struct soc_camera_device *icd) static int mt9m111_disable(struct soc_camera_device *icd) { + struct i2c_client *client = to_i2c_client(icd->control); struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); - struct soc_camera_link *icl = mt9m111->client->dev.platform_data; + struct soc_camera_link *icl = client->dev.platform_data; int ret; ret = reg_clear(RESET, MT9M111_RESET_CHIP_ENABLE); @@ -387,15 +388,15 @@ static int mt9m111_disable(struct soc_camera_device *icd) mt9m111->powered = 0; if (icl->power) - icl->power(&mt9m111->client->dev, 0); + icl->power(&client->dev, 0); return ret; } static int mt9m111_reset(struct soc_camera_device *icd) { - struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); - struct soc_camera_link *icl = mt9m111->client->dev.platform_data; + struct i2c_client *client = to_i2c_client(icd->control); + struct soc_camera_link *icl = client->dev.platform_data; int ret; ret = reg_set(RESET, MT9M111_RESET_RESET_MODE); @@ -406,7 +407,7 @@ static int mt9m111_reset(struct soc_camera_device *icd) | MT9M111_RESET_RESET_SOC); if (icl->reset) - icl->reset(&mt9m111->client->dev); + icl->reset(&client->dev); return ret; } @@ -562,15 +563,14 @@ static int mt9m111_get_register(struct soc_camera_device *icd, struct v4l2_dbg_register *reg) { int val; - - struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); + struct i2c_client *client = to_i2c_client(icd->control); if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0x2ff) return -EINVAL; - if (reg->match.addr != mt9m111->client->addr) + if (reg->match.addr != client->addr) return -ENODEV; - val = mt9m111_reg_read(icd, reg->reg); + val = mt9m111_reg_read(client, reg->reg); reg->size = 2; reg->val = (u64)val; @@ -583,15 +583,15 @@ static int mt9m111_get_register(struct soc_camera_device *icd, static int mt9m111_set_register(struct soc_camera_device *icd, struct v4l2_dbg_register *reg) { - struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); + struct i2c_client *client = to_i2c_client(icd->control); if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0x2ff) return -EINVAL; - if (reg->match.addr != mt9m111->client->addr) + if (reg->match.addr != client->addr) return -ENODEV; - if (mt9m111_reg_write(icd, reg->reg, reg->val) < 0) + if (mt9m111_reg_write(client, reg->reg, reg->val) < 0) return -EIO; return 0; @@ -672,6 +672,7 @@ static struct soc_camera_ops mt9m111_ops = { static int mt9m111_set_flip(struct soc_camera_device *icd, int flip, int mask) { + struct i2c_client *client = to_i2c_client(icd->control); struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); int ret; @@ -692,6 +693,7 @@ static int mt9m111_set_flip(struct soc_camera_device *icd, int flip, int mask) static int mt9m111_get_global_gain(struct soc_camera_device *icd) { + struct i2c_client *client = to_i2c_client(icd->control); int data; data = reg_read(GLOBAL_GAIN); @@ -703,6 +705,7 @@ static int mt9m111_get_global_gain(struct soc_camera_device *icd) static int mt9m111_set_global_gain(struct soc_camera_device *icd, int gain) { + struct i2c_client *client = to_i2c_client(icd->control); u16 val; if (gain > 63 * 2 * 2) @@ -721,6 +724,7 @@ static int mt9m111_set_global_gain(struct soc_camera_device *icd, int gain) static int mt9m111_set_autoexposure(struct soc_camera_device *icd, int on) { + struct i2c_client *client = to_i2c_client(icd->control); struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); int ret; @@ -737,6 +741,7 @@ static int mt9m111_set_autoexposure(struct soc_camera_device *icd, int on) static int mt9m111_set_autowhitebalance(struct soc_camera_device *icd, int on) { + struct i2c_client *client = to_i2c_client(icd->control); struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); int ret; @@ -754,6 +759,7 @@ static int mt9m111_set_autowhitebalance(struct soc_camera_device *icd, int on) static int mt9m111_get_control(struct soc_camera_device *icd, struct v4l2_control *ctrl) { + struct i2c_client *client = to_i2c_client(icd->control); struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); int data; @@ -898,6 +904,7 @@ static int mt9m111_release(struct soc_camera_device *icd) */ static int mt9m111_video_probe(struct soc_camera_device *icd) { + struct i2c_client *client = to_i2c_client(icd->control); struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); s32 data; int ret; diff --git a/linux/drivers/media/video/mt9t031.c b/linux/drivers/media/video/mt9t031.c index f4e597e6c..381dd0fbe 100644 --- a/linux/drivers/media/video/mt9t031.c +++ b/linux/drivers/media/video/mt9t031.c @@ -76,64 +76,61 @@ struct mt9t031 { u16 yskip; }; -static int reg_read(struct soc_camera_device *icd, const u8 reg) +static int reg_read(struct i2c_client *client, const u8 reg) { - struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd); - struct i2c_client *client = mt9t031->client; s32 data = i2c_smbus_read_word_data(client, reg); return data < 0 ? data : swab16(data); } -static int reg_write(struct soc_camera_device *icd, const u8 reg, +static int reg_write(struct i2c_client *client, const u8 reg, const u16 data) { - struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd); - return i2c_smbus_write_word_data(mt9t031->client, reg, swab16(data)); + return i2c_smbus_write_word_data(client, reg, swab16(data)); } -static int reg_set(struct soc_camera_device *icd, const u8 reg, +static int reg_set(struct i2c_client *client, const u8 reg, const u16 data) { int ret; - ret = reg_read(icd, reg); + ret = reg_read(client, reg); if (ret < 0) return ret; - return reg_write(icd, reg, ret | data); + return reg_write(client, reg, ret | data); } -static int reg_clear(struct soc_camera_device *icd, const u8 reg, +static int reg_clear(struct i2c_client *client, const u8 reg, const u16 data) { int ret; - ret = reg_read(icd, reg); + ret = reg_read(client, reg); if (ret < 0) return ret; - return reg_write(icd, reg, ret & ~data); + return reg_write(client, reg, ret & ~data); } -static int set_shutter(struct soc_camera_device *icd, const u32 data) +static int set_shutter(struct i2c_client *client, const u32 data) { int ret; - ret = reg_write(icd, MT9T031_SHUTTER_WIDTH_UPPER, data >> 16); + ret = reg_write(client, MT9T031_SHUTTER_WIDTH_UPPER, data >> 16); if (ret >= 0) - ret = reg_write(icd, MT9T031_SHUTTER_WIDTH, data & 0xffff); + ret = reg_write(client, MT9T031_SHUTTER_WIDTH, data & 0xffff); return ret; } -static int get_shutter(struct soc_camera_device *icd, u32 *data) +static int get_shutter(struct i2c_client *client, u32 *data) { int ret; - ret = reg_read(icd, MT9T031_SHUTTER_WIDTH_UPPER); + ret = reg_read(client, MT9T031_SHUTTER_WIDTH_UPPER); *data = ret << 16; if (ret >= 0) - ret = reg_read(icd, MT9T031_SHUTTER_WIDTH); + ret = reg_read(client, MT9T031_SHUTTER_WIDTH); *data |= ret & 0xffff; return ret < 0 ? ret : 0; @@ -141,12 +138,12 @@ static int get_shutter(struct soc_camera_device *icd, u32 *data) static int mt9t031_init(struct soc_camera_device *icd) { - struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd); - struct soc_camera_link *icl = mt9t031->client->dev.platform_data; + struct i2c_client *client = to_i2c_client(icd->control); + struct soc_camera_link *icl = client->dev.platform_data; int ret; if (icl->power) { - ret = icl->power(&mt9t031->client->dev, 1); + ret = icl->power(&client->dev, 1); if (ret < 0) { dev_err(icd->vdev->parent, "Platform failed to power-on the camera.\n"); @@ -155,44 +152,48 @@ static int mt9t031_init(struct soc_camera_device *icd) } /* Disable chip output, synchronous option update */ - ret = reg_write(icd, MT9T031_RESET, 1); + ret = reg_write(client, MT9T031_RESET, 1); if (ret >= 0) - ret = reg_write(icd, MT9T031_RESET, 0); + ret = reg_write(client, MT9T031_RESET, 0); if (ret >= 0) - ret = reg_clear(icd, MT9T031_OUTPUT_CONTROL, 2); + ret = reg_clear(client, MT9T031_OUTPUT_CONTROL, 2); if (ret < 0 && icl->power) - icl->power(&mt9t031->client->dev, 0); + icl->power(&client->dev, 0); return ret >= 0 ? 0 : -EIO; } static int mt9t031_release(struct soc_camera_device *icd) { - struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd); - struct soc_camera_link *icl = mt9t031->client->dev.platform_data; + struct i2c_client *client = to_i2c_client(icd->control); + struct soc_camera_link *icl = client->dev.platform_data; /* Disable the chip */ - reg_clear(icd, MT9T031_OUTPUT_CONTROL, 2); + reg_clear(client, MT9T031_OUTPUT_CONTROL, 2); if (icl->power) - icl->power(&mt9t031->client->dev, 0); + icl->power(&client->dev, 0); return 0; } static int mt9t031_start_capture(struct soc_camera_device *icd) { + struct i2c_client *client = to_i2c_client(icd->control); + /* Switch to master "normal" mode */ - if (reg_set(icd, MT9T031_OUTPUT_CONTROL, 2) < 0) + if (reg_set(client, MT9T031_OUTPUT_CONTROL, 2) < 0) return -EIO; return 0; } static int mt9t031_stop_capture(struct soc_camera_device *icd) { + struct i2c_client *client = to_i2c_client(icd->control); + /* Stop sensor readout */ - if (reg_clear(icd, MT9T031_OUTPUT_CONTROL, 2) < 0) + if (reg_clear(client, MT9T031_OUTPUT_CONTROL, 2) < 0) return -EIO; return 0; } @@ -200,14 +201,16 @@ static int mt9t031_stop_capture(struct soc_camera_device *icd) static int mt9t031_set_bus_param(struct soc_camera_device *icd, unsigned long flags) { + struct i2c_client *client = to_i2c_client(icd->control); + /* The caller should have queried our parameters, check anyway */ if (flags & ~MT9T031_BUS_PARAM) return -EINVAL; if (flags & SOCAM_PCLK_SAMPLE_FALLING) - reg_clear(icd, MT9T031_PIXEL_CLOCK_CONTROL, 0x8000); + reg_clear(client, MT9T031_PIXEL_CLOCK_CONTROL, 0x8000); else - reg_set(icd, MT9T031_PIXEL_CLOCK_CONTROL, 0x8000); + reg_set(client, MT9T031_PIXEL_CLOCK_CONTROL, 0x8000); return 0; } @@ -235,6 +238,7 @@ static void recalculate_limits(struct soc_camera_device *icd, static int mt9t031_set_params(struct soc_camera_device *icd, struct v4l2_rect *rect, u16 xskip, u16 yskip) { + struct i2c_client *client = to_i2c_client(icd->control); struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd); int ret; u16 xbin, ybin, width, height, left, top; @@ -277,22 +281,22 @@ static int mt9t031_set_params(struct soc_camera_device *icd, } /* Disable register update, reconfigure atomically */ - ret = reg_set(icd, MT9T031_OUTPUT_CONTROL, 1); + ret = reg_set(client, MT9T031_OUTPUT_CONTROL, 1); if (ret < 0) return ret; /* Blanking and start values - default... */ - ret = reg_write(icd, MT9T031_HORIZONTAL_BLANKING, hblank); + ret = reg_write(client, MT9T031_HORIZONTAL_BLANKING, hblank); if (ret >= 0) - ret = reg_write(icd, MT9T031_VERTICAL_BLANKING, vblank); + ret = reg_write(client, MT9T031_VERTICAL_BLANKING, vblank); if (yskip != mt9t031->yskip || xskip != mt9t031->xskip) { /* Binning, skipping */ if (ret >= 0) - ret = reg_write(icd, MT9T031_COLUMN_ADDRESS_MODE, + ret = reg_write(client, MT9T031_COLUMN_ADDRESS_MODE, ((xbin - 1) << 4) | (xskip - 1)); if (ret >= 0) - ret = reg_write(icd, MT9T031_ROW_ADDRESS_MODE, + ret = reg_write(client, MT9T031_ROW_ADDRESS_MODE, ((ybin - 1) << 4) | (yskip - 1)); } dev_dbg(&icd->dev, "new physical left %u, top %u\n", left, top); @@ -300,16 +304,16 @@ static int mt9t031_set_params(struct soc_camera_device *icd, /* The caller provides a supported format, as guaranteed by * icd->try_fmt_cap(), soc_camera_s_crop() and soc_camera_cropcap() */ if (ret >= 0) - ret = reg_write(icd, MT9T031_COLUMN_START, left); + ret = reg_write(client, MT9T031_COLUMN_START, left); if (ret >= 0) - ret = reg_write(icd, MT9T031_ROW_START, top); + ret = reg_write(client, MT9T031_ROW_START, top); if (ret >= 0) - ret = reg_write(icd, MT9T031_WINDOW_WIDTH, width - 1); + ret = reg_write(client, MT9T031_WINDOW_WIDTH, width - 1); if (ret >= 0) - ret = reg_write(icd, MT9T031_WINDOW_HEIGHT, + ret = reg_write(client, MT9T031_WINDOW_HEIGHT, height + icd->y_skip_top - 1); if (ret >= 0 && mt9t031->autoexposure) { - ret = set_shutter(icd, height + icd->y_skip_top + vblank); + ret = set_shutter(client, height + icd->y_skip_top + vblank); if (ret >= 0) { const u32 shutter_max = MT9T031_MAX_HEIGHT + vblank; const struct v4l2_queryctrl *qctrl = @@ -324,7 +328,7 @@ static int mt9t031_set_params(struct soc_camera_device *icd, /* Re-enable register update, commit all changes */ if (ret >= 0) - ret = reg_clear(icd, MT9T031_OUTPUT_CONTROL, 1); + ret = reg_clear(client, MT9T031_OUTPUT_CONTROL, 1); return ret < 0 ? ret : 0; } @@ -417,15 +421,15 @@ static int mt9t031_get_chip_id(struct soc_camera_device *icd, static int mt9t031_get_register(struct soc_camera_device *icd, struct v4l2_dbg_register *reg) { - struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd); + struct i2c_client *client = to_i2c_client(icd->control); if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff) return -EINVAL; - if (reg->match.addr != mt9t031->client->addr) + if (reg->match.addr != client->addr) return -ENODEV; - reg->val = reg_read(icd, reg->reg); + reg->val = reg_read(client, reg->reg); if (reg->val > 0xffff) return -EIO; @@ -436,15 +440,15 @@ static int mt9t031_get_register(struct soc_camera_device *icd, static int mt9t031_set_register(struct soc_camera_device *icd, struct v4l2_dbg_register *reg) { - struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd); + struct i2c_client *client = to_i2c_client(icd->control); if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff) return -EINVAL; - if (reg->match.addr != mt9t031->client->addr) + if (reg->match.addr != client->addr) return -ENODEV; - if (reg_write(icd, reg->reg, reg->val) < 0) + if (reg_write(client, reg->reg, reg->val) < 0) return -EIO; return 0; @@ -528,18 +532,19 @@ static struct soc_camera_ops mt9t031_ops = { static int mt9t031_get_control(struct soc_camera_device *icd, struct v4l2_control *ctrl) { + struct i2c_client *client = to_i2c_client(icd->control); struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd); int data; switch (ctrl->id) { case V4L2_CID_VFLIP: - data = reg_read(icd, MT9T031_READ_MODE_2); + data = reg_read(client, MT9T031_READ_MODE_2); if (data < 0) return -EIO; ctrl->value = !!(data & 0x8000); break; case V4L2_CID_HFLIP: - data = reg_read(icd, MT9T031_READ_MODE_2); + data = reg_read(client, MT9T031_READ_MODE_2); if (data < 0) return -EIO; ctrl->value = !!(data & 0x4000); @@ -553,6 +558,7 @@ static int mt9t031_get_control(struct soc_camera_device *icd, struct v4l2_contro static int mt9t031_set_control(struct soc_camera_device *icd, struct v4l2_control *ctrl) { + struct i2c_client *client = to_i2c_client(icd->control); struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd); const struct v4l2_queryctrl *qctrl; int data; @@ -565,17 +571,17 @@ static int mt9t031_set_control(struct soc_camera_device *icd, struct v4l2_contro switch (ctrl->id) { case V4L2_CID_VFLIP: if (ctrl->value) - data = reg_set(icd, MT9T031_READ_MODE_2, 0x8000); + data = reg_set(client, MT9T031_READ_MODE_2, 0x8000); else - data = reg_clear(icd, MT9T031_READ_MODE_2, 0x8000); + data = reg_clear(client, MT9T031_READ_MODE_2, 0x8000); if (data < 0) return -EIO; break; case V4L2_CID_HFLIP: if (ctrl->value) - data = reg_set(icd, MT9T031_READ_MODE_2, 0x4000); + data = reg_set(client, MT9T031_READ_MODE_2, 0x4000); else - data = reg_clear(icd, MT9T031_READ_MODE_2, 0x4000); + data = reg_clear(client, MT9T031_READ_MODE_2, 0x4000); if (data < 0) return -EIO; break; @@ -589,7 +595,7 @@ static int mt9t031_set_control(struct soc_camera_device *icd, struct v4l2_contro data = ((ctrl->value - qctrl->minimum) * 8 + range / 2) / range; dev_dbg(&icd->dev, "Setting gain %d\n", data); - data = reg_write(icd, MT9T031_GLOBAL_GAIN, data); + data = reg_write(client, MT9T031_GLOBAL_GAIN, data); if (data < 0) return -EIO; } else { @@ -609,8 +615,8 @@ static int mt9t031_set_control(struct soc_camera_device *icd, struct v4l2_contro data = (((gain - 64 + 7) * 32) & 0xff00) | 0x60; dev_dbg(&icd->dev, "Setting gain from 0x%x to 0x%x\n", - reg_read(icd, MT9T031_GLOBAL_GAIN), data); - data = reg_write(icd, MT9T031_GLOBAL_GAIN, data); + reg_read(client, MT9T031_GLOBAL_GAIN), data); + data = reg_write(client, MT9T031_GLOBAL_GAIN, data); if (data < 0) return -EIO; } @@ -628,10 +634,10 @@ static int mt9t031_set_control(struct soc_camera_device *icd, struct v4l2_contro range / 2) / range + 1; u32 old; - get_shutter(icd, &old); + get_shutter(client, &old); dev_dbg(&icd->dev, "Setting shutter width from %u to %u\n", old, shutter); - if (set_shutter(icd, shutter) < 0) + if (set_shutter(client, shutter) < 0) return -EIO; icd->exposure = ctrl->value; mt9t031->autoexposure = 0; @@ -641,7 +647,7 @@ static int mt9t031_set_control(struct soc_camera_device *icd, struct v4l2_contro if (ctrl->value) { const u16 vblank = MT9T031_VERTICAL_BLANK; const u32 shutter_max = MT9T031_MAX_HEIGHT + vblank; - if (set_shutter(icd, icd->height + + if (set_shutter(client, icd->height + icd->y_skip_top + vblank) < 0) return -EIO; qctrl = soc_camera_find_qctrl(icd->ops, V4L2_CID_EXPOSURE); @@ -661,6 +667,7 @@ static int mt9t031_set_control(struct soc_camera_device *icd, struct v4l2_contro * this wasn't our capture interface, so, we wait for the right one */ static int mt9t031_video_probe(struct soc_camera_device *icd) { + struct i2c_client *client = to_i2c_client(icd->control); struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd); s32 data; int ret; @@ -672,11 +679,11 @@ static int mt9t031_video_probe(struct soc_camera_device *icd) return -ENODEV; /* Enable the chip */ - data = reg_write(icd, MT9T031_CHIP_ENABLE, 1); + data = reg_write(client, MT9T031_CHIP_ENABLE, 1); dev_dbg(&icd->dev, "write: %d\n", data); /* Read out the chip version register */ - data = reg_read(icd, MT9T031_CHIP_VERSION); + data = reg_read(client, MT9T031_CHIP_VERSION); switch (data) { case 0x1621: diff --git a/linux/drivers/media/video/mt9v022.c b/linux/drivers/media/video/mt9v022.c index 07ffd967e..016bcdfcf 100644 --- a/linux/drivers/media/video/mt9v022.c +++ b/linux/drivers/media/video/mt9v022.c @@ -91,51 +91,49 @@ struct mt9v022 { u16 chip_control; }; -static int reg_read(struct soc_camera_device *icd, const u8 reg) +static int reg_read(struct i2c_client *client, const u8 reg) { - struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd); - struct i2c_client *client = mt9v022->client; s32 data = i2c_smbus_read_word_data(client, reg); return data < 0 ? data : swab16(data); } -static int reg_write(struct soc_camera_device *icd, const u8 reg, +static int reg_write(struct i2c_client *client, const u8 reg, const u16 data) { - struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd); - return i2c_smbus_write_word_data(mt9v022->client, reg, swab16(data)); + return i2c_smbus_write_word_data(client, reg, swab16(data)); } -static int reg_set(struct soc_camera_device *icd, const u8 reg, +static int reg_set(struct i2c_client *client, const u8 reg, const u16 data) { int ret; - ret = reg_read(icd, reg); + ret = reg_read(client, reg); if (ret < 0) return ret; - return reg_write(icd, reg, ret | data); + return reg_write(client, reg, ret | data); } -static int reg_clear(struct soc_camera_device *icd, const u8 reg, +static int reg_clear(struct i2c_client *client, const u8 reg, const u16 data) { int ret; - ret = reg_read(icd, reg); + ret = reg_read(client, reg); if (ret < 0) return ret; - return reg_write(icd, reg, ret & ~data); + return reg_write(client, reg, ret & ~data); } static int mt9v022_init(struct soc_camera_device *icd) { + struct i2c_client *client = to_i2c_client(icd->control); struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd); - struct soc_camera_link *icl = mt9v022->client->dev.platform_data; + struct soc_camera_link *icl = client->dev.platform_data; int ret; if (icl->power) { - ret = icl->power(&mt9v022->client->dev, 1); + ret = icl->power(&client->dev, 1); if (ret < 0) { dev_err(icd->vdev->parent, "Platform failed to power-on the camera.\n"); @@ -148,27 +146,27 @@ static int mt9v022_init(struct soc_camera_device *icd) * if available. Soft reset is done in video_probe(). */ if (icl->reset) - icl->reset(&mt9v022->client->dev); + icl->reset(&client->dev); /* Almost the default mode: master, parallel, simultaneous, and an * undocumented bit 0x200, which is present in table 7, but not in 8, * plus snapshot mode to disable scan for now */ mt9v022->chip_control |= 0x10; - ret = reg_write(icd, MT9V022_CHIP_CONTROL, mt9v022->chip_control); + ret = reg_write(client, MT9V022_CHIP_CONTROL, mt9v022->chip_control); if (!ret) - ret = reg_write(icd, MT9V022_READ_MODE, 0x300); + ret = reg_write(client, MT9V022_READ_MODE, 0x300); /* All defaults */ if (!ret) /* AEC, AGC on */ - ret = reg_set(icd, MT9V022_AEC_AGC_ENABLE, 0x3); + ret = reg_set(client, MT9V022_AEC_AGC_ENABLE, 0x3); if (!ret) - ret = reg_write(icd, MT9V022_MAX_TOTAL_SHUTTER_WIDTH, 480); + ret = reg_write(client, MT9V022_MAX_TOTAL_SHUTTER_WIDTH, 480); if (!ret) /* default - auto */ - ret = reg_clear(icd, MT9V022_BLACK_LEVEL_CALIB_CTRL, 1); + ret = reg_clear(client, MT9V022_BLACK_LEVEL_CALIB_CTRL, 1); if (!ret) - ret = reg_write(icd, MT9V022_DIGITAL_TEST_PATTERN, 0); + ret = reg_write(client, MT9V022_DIGITAL_TEST_PATTERN, 0); return ret; } @@ -186,10 +184,11 @@ static int mt9v022_release(struct soc_camera_device *icd) static int mt9v022_start_capture(struct soc_camera_device *icd) { + struct i2c_client *client = to_i2c_client(icd->control); struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd); /* Switch to master "normal" mode */ mt9v022->chip_control &= ~0x10; - if (reg_write(icd, MT9V022_CHIP_CONTROL, + if (reg_write(client, MT9V022_CHIP_CONTROL, mt9v022->chip_control) < 0) return -EIO; return 0; @@ -197,10 +196,11 @@ static int mt9v022_start_capture(struct soc_camera_device *icd) static int mt9v022_stop_capture(struct soc_camera_device *icd) { + struct i2c_client *client = to_i2c_client(icd->control); struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd); /* Switch to snapshot mode */ mt9v022->chip_control |= 0x10; - if (reg_write(icd, MT9V022_CHIP_CONTROL, + if (reg_write(client, MT9V022_CHIP_CONTROL, mt9v022->chip_control) < 0) return -EIO; return 0; @@ -209,8 +209,9 @@ static int mt9v022_stop_capture(struct soc_camera_device *icd) static int mt9v022_set_bus_param(struct soc_camera_device *icd, unsigned long flags) { + struct i2c_client *client = to_i2c_client(icd->control); struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd); - struct soc_camera_link *icl = mt9v022->client->dev.platform_data; + struct soc_camera_link *icl = client->dev.platform_data; unsigned int width_flag = flags & SOCAM_DATAWIDTH_MASK; int ret; u16 pixclk = 0; @@ -243,14 +244,14 @@ static int mt9v022_set_bus_param(struct soc_camera_device *icd, if (!(flags & SOCAM_VSYNC_ACTIVE_HIGH)) pixclk |= 0x2; - ret = reg_write(icd, MT9V022_PIXCLK_FV_LV, pixclk); + ret = reg_write(client, MT9V022_PIXCLK_FV_LV, pixclk); if (ret < 0) return ret; if (!(flags & SOCAM_MASTER)) mt9v022->chip_control &= ~0x8; - ret = reg_write(icd, MT9V022_CHIP_CONTROL, mt9v022->chip_control); + ret = reg_write(client, MT9V022_CHIP_CONTROL, mt9v022->chip_control); if (ret < 0) return ret; @@ -282,35 +283,36 @@ static unsigned long mt9v022_query_bus_param(struct soc_camera_device *icd) static int mt9v022_set_crop(struct soc_camera_device *icd, struct v4l2_rect *rect) { + struct i2c_client *client = to_i2c_client(icd->control); int ret; /* Like in example app. Contradicts the datasheet though */ - ret = reg_read(icd, MT9V022_AEC_AGC_ENABLE); + ret = reg_read(client, MT9V022_AEC_AGC_ENABLE); if (ret >= 0) { if (ret & 1) /* Autoexposure */ - ret = reg_write(icd, MT9V022_MAX_TOTAL_SHUTTER_WIDTH, + ret = reg_write(client, MT9V022_MAX_TOTAL_SHUTTER_WIDTH, rect->height + icd->y_skip_top + 43); else - ret = reg_write(icd, MT9V022_TOTAL_SHUTTER_WIDTH, + ret = reg_write(client, MT9V022_TOTAL_SHUTTER_WIDTH, rect->height + icd->y_skip_top + 43); } /* Setup frame format: defaults apart from width and height */ if (!ret) - ret = reg_write(icd, MT9V022_COLUMN_START, rect->left); + ret = reg_write(client, MT9V022_COLUMN_START, rect->left); if (!ret) - ret = reg_write(icd, MT9V022_ROW_START, rect->top); + ret = reg_write(client, MT9V022_ROW_START, rect->top); if (!ret) /* Default 94, Phytec driver says: * "width + horizontal blank >= 660" */ - ret = reg_write(icd, MT9V022_HORIZONTAL_BLANKING, + ret = reg_write(client, MT9V022_HORIZONTAL_BLANKING, rect->width > 660 - 43 ? 43 : 660 - rect->width); if (!ret) - ret = reg_write(icd, MT9V022_VERTICAL_BLANKING, 45); + ret = reg_write(client, MT9V022_VERTICAL_BLANKING, 45); if (!ret) - ret = reg_write(icd, MT9V022_WINDOW_WIDTH, rect->width); + ret = reg_write(client, MT9V022_WINDOW_WIDTH, rect->width); if (!ret) - ret = reg_write(icd, MT9V022_WINDOW_HEIGHT, + ret = reg_write(client, MT9V022_WINDOW_HEIGHT, rect->height + icd->y_skip_top); if (ret < 0) @@ -396,16 +398,16 @@ static int mt9v022_get_chip_id(struct soc_camera_device *icd, static int mt9v022_get_register(struct soc_camera_device *icd, struct v4l2_dbg_register *reg) { - struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd); + struct i2c_client *client = to_i2c_client(icd->control); if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff) return -EINVAL; - if (reg->match.addr != mt9v022->client->addr) + if (reg->match.addr != client->addr) return -ENODEV; reg->size = 2; - reg->val = reg_read(icd, reg->reg); + reg->val = reg_read(client, reg->reg); if (reg->val > 0xffff) return -EIO; @@ -416,15 +418,15 @@ static int mt9v022_get_register(struct soc_camera_device *icd, static int mt9v022_set_register(struct soc_camera_device *icd, struct v4l2_dbg_register *reg) { - struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd); + struct i2c_client *client = to_i2c_client(icd->control); if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff) return -EINVAL; - if (reg->match.addr != mt9v022->client->addr) + if (reg->match.addr != client->addr) return -ENODEV; - if (reg_write(icd, reg->reg, reg->val) < 0) + if (reg_write(client, reg->reg, reg->val) < 0) return -EIO; return 0; @@ -517,29 +519,30 @@ static struct soc_camera_ops mt9v022_ops = { static int mt9v022_get_control(struct soc_camera_device *icd, struct v4l2_control *ctrl) { + struct i2c_client *client = to_i2c_client(icd->control); int data; switch (ctrl->id) { case V4L2_CID_VFLIP: - data = reg_read(icd, MT9V022_READ_MODE); + data = reg_read(client, MT9V022_READ_MODE); if (data < 0) return -EIO; ctrl->value = !!(data & 0x10); break; case V4L2_CID_HFLIP: - data = reg_read(icd, MT9V022_READ_MODE); + data = reg_read(client, MT9V022_READ_MODE); if (data < 0) return -EIO; ctrl->value = !!(data & 0x20); break; case V4L2_CID_EXPOSURE_AUTO: - data = reg_read(icd, MT9V022_AEC_AGC_ENABLE); + data = reg_read(client, MT9V022_AEC_AGC_ENABLE); if (data < 0) return -EIO; ctrl->value = !!(data & 0x1); break; case V4L2_CID_AUTOGAIN: - data = reg_read(icd, MT9V022_AEC_AGC_ENABLE); + data = reg_read(client, MT9V022_AEC_AGC_ENABLE); if (data < 0) return -EIO; ctrl->value = !!(data & 0x2); @@ -552,6 +555,7 @@ static int mt9v022_set_control(struct soc_camera_device *icd, struct v4l2_control *ctrl) { int data; + struct i2c_client *client = to_i2c_client(icd->control); const struct v4l2_queryctrl *qctrl; qctrl = soc_camera_find_qctrl(&mt9v022_ops, ctrl->id); @@ -562,17 +566,17 @@ static int mt9v022_set_control(struct soc_camera_device *icd, switch (ctrl->id) { case V4L2_CID_VFLIP: if (ctrl->value) - data = reg_set(icd, MT9V022_READ_MODE, 0x10); + data = reg_set(client, MT9V022_READ_MODE, 0x10); else - data = reg_clear(icd, MT9V022_READ_MODE, 0x10); + data = reg_clear(client, MT9V022_READ_MODE, 0x10); if (data < 0) return -EIO; break; case V4L2_CID_HFLIP: if (ctrl->value) - data = reg_set(icd, MT9V022_READ_MODE, 0x20); + data = reg_set(client, MT9V022_READ_MODE, 0x20); else - data = reg_clear(icd, MT9V022_READ_MODE, 0x20); + data = reg_clear(client, MT9V022_READ_MODE, 0x20); if (data < 0) return -EIO; break; @@ -593,12 +597,12 @@ static int mt9v022_set_control(struct soc_camera_device *icd, /* The user wants to set gain manually, hope, she * knows, what she's doing... Switch AGC off. */ - if (reg_clear(icd, MT9V022_AEC_AGC_ENABLE, 0x2) < 0) + if (reg_clear(client, MT9V022_AEC_AGC_ENABLE, 0x2) < 0) return -EIO; dev_info(&icd->dev, "Setting gain from %d to %lu\n", - reg_read(icd, MT9V022_ANALOG_GAIN), gain); - if (reg_write(icd, MT9V022_ANALOG_GAIN, gain) < 0) + reg_read(client, MT9V022_ANALOG_GAIN), gain); + if (reg_write(client, MT9V022_ANALOG_GAIN, gain) < 0) return -EIO; icd->gain = ctrl->value; } @@ -614,13 +618,13 @@ static int mt9v022_set_control(struct soc_camera_device *icd, /* The user wants to set shutter width manually, hope, * she knows, what she's doing... Switch AEC off. */ - if (reg_clear(icd, MT9V022_AEC_AGC_ENABLE, 0x1) < 0) + if (reg_clear(client, MT9V022_AEC_AGC_ENABLE, 0x1) < 0) return -EIO; dev_dbg(&icd->dev, "Shutter width from %d to %lu\n", - reg_read(icd, MT9V022_TOTAL_SHUTTER_WIDTH), + reg_read(client, MT9V022_TOTAL_SHUTTER_WIDTH), shutter); - if (reg_write(icd, MT9V022_TOTAL_SHUTTER_WIDTH, + if (reg_write(client, MT9V022_TOTAL_SHUTTER_WIDTH, shutter) < 0) return -EIO; icd->exposure = ctrl->value; @@ -628,17 +632,17 @@ static int mt9v022_set_control(struct soc_camera_device *icd, break; case V4L2_CID_AUTOGAIN: if (ctrl->value) - data = reg_set(icd, MT9V022_AEC_AGC_ENABLE, 0x2); + data = reg_set(client, MT9V022_AEC_AGC_ENABLE, 0x2); else - data = reg_clear(icd, MT9V022_AEC_AGC_ENABLE, 0x2); + data = reg_clear(client, MT9V022_AEC_AGC_ENABLE, 0x2); if (data < 0) return -EIO; break; case V4L2_CID_EXPOSURE_AUTO: if (ctrl->value) - data = reg_set(icd, MT9V022_AEC_AGC_ENABLE, 0x1); + data = reg_set(client, MT9V022_AEC_AGC_ENABLE, 0x1); else - data = reg_clear(icd, MT9V022_AEC_AGC_ENABLE, 0x1); + data = reg_clear(client, MT9V022_AEC_AGC_ENABLE, 0x1); if (data < 0) return -EIO; break; @@ -650,8 +654,9 @@ static int mt9v022_set_control(struct soc_camera_device *icd, * this wasn't our capture interface, so, we wait for the right one */ static int mt9v022_video_probe(struct soc_camera_device *icd) { + struct i2c_client *client = to_i2c_client(icd->control); struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd); - struct soc_camera_link *icl = mt9v022->client->dev.platform_data; + struct soc_camera_link *icl = client->dev.platform_data; s32 data; int ret; unsigned long flags; @@ -661,7 +666,7 @@ static int mt9v022_video_probe(struct soc_camera_device *icd) return -ENODEV; /* Read out the chip version register */ - data = reg_read(icd, MT9V022_CHIP_VERSION); + data = reg_read(client, MT9V022_CHIP_VERSION); /* must be 0x1311 or 0x1313 */ if (data != 0x1311 && data != 0x1313) { @@ -672,12 +677,12 @@ static int mt9v022_video_probe(struct soc_camera_device *icd) } /* Soft reset */ - ret = reg_write(icd, MT9V022_RESET, 1); + ret = reg_write(client, MT9V022_RESET, 1); if (ret < 0) goto ei2c; /* 15 clock cycles */ udelay(200); - if (reg_read(icd, MT9V022_RESET)) { + if (reg_read(client, MT9V022_RESET)) { dev_err(&icd->dev, "Resetting MT9V022 failed!\n"); goto ei2c; } @@ -685,11 +690,11 @@ static int mt9v022_video_probe(struct soc_camera_device *icd) /* Set monochrome or colour sensor type */ if (sensor_type && (!strcmp("colour", sensor_type) || !strcmp("color", sensor_type))) { - ret = reg_write(icd, MT9V022_PIXEL_OPERATION_MODE, 4 | 0x11); + ret = reg_write(client, MT9V022_PIXEL_OPERATION_MODE, 4 | 0x11); mt9v022->model = V4L2_IDENT_MT9V022IX7ATC; icd->formats = mt9v022_colour_formats; } else { - ret = reg_write(icd, MT9V022_PIXEL_OPERATION_MODE, 0x11); + ret = reg_write(client, MT9V022_PIXEL_OPERATION_MODE, 0x11); mt9v022->model = V4L2_IDENT_MT9V022IX7ATM; icd->formats = mt9v022_monochrome_formats; } -- cgit v1.2.3 From 820b1bf8a59407c1b4171306b9d6577c65d3a016 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Fri, 24 Apr 2009 17:57:42 +0200 Subject: soc-camera: link host drivers after clients From: Guennadi Liakhovetski With the transition of soc-camera to become a platform driver and to the v4l2-subdev framework the initialisation order becomes important. In case of a static build clients (i2c) drivers have to be available when host drivers are probed. Moving host drivers down in the Makefile achieves the desired order. Signed-off-by: Guennadi Liakhovetski --- drivers/media/video/Makefile | 9 +++++---- 1 files changed, 5 insertions(+), 4 deletions(-) --- linux/drivers/media/video/Makefile | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/Makefile b/linux/drivers/media/video/Makefile index 3f1a0350a..7aefac643 100644 --- a/linux/drivers/media/video/Makefile +++ b/linux/drivers/media/video/Makefile @@ -134,10 +134,6 @@ obj-$(CONFIG_VIDEO_CX18) += cx18/ obj-$(CONFIG_VIDEO_VIVI) += vivi.o obj-$(CONFIG_VIDEO_CX23885) += cx23885/ -obj-$(CONFIG_VIDEO_MX1) += mx1_camera.o -obj-$(CONFIG_VIDEO_MX3) += mx3_camera.o -obj-$(CONFIG_VIDEO_PXA27x) += pxa_camera.o -obj-$(CONFIG_VIDEO_SH_MOBILE_CEU) += sh_mobile_ceu_camera.o obj-$(CONFIG_VIDEO_OMAP2) += omap2cam.o obj-$(CONFIG_SOC_CAMERA) += soc_camera.o obj-$(CONFIG_SOC_CAMERA_MT9M001) += mt9m001.o @@ -147,6 +143,11 @@ obj-$(CONFIG_SOC_CAMERA_MT9V022) += mt9v022.o obj-$(CONFIG_SOC_CAMERA_OV772X) += ov772x.o obj-$(CONFIG_SOC_CAMERA_PLATFORM) += soc_camera_platform.o obj-$(CONFIG_SOC_CAMERA_TW9910) += tw9910.o +# soc-camera host drivers have to be linked after camera drivers +obj-$(CONFIG_VIDEO_MX1) += mx1_camera.o +obj-$(CONFIG_VIDEO_MX3) += mx3_camera.o +obj-$(CONFIG_VIDEO_PXA27x) += pxa_camera.o +obj-$(CONFIG_VIDEO_SH_MOBILE_CEU) += sh_mobile_ceu_camera.o obj-$(CONFIG_VIDEO_AU0828) += au0828/ -- cgit v1.2.3 From c3cc042608813e24ef6a3510cdae6d0924c1be09 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Fri, 24 Apr 2009 17:58:24 +0200 Subject: mx3_camera: Fix compilation with CONFIG_PM From: Sascha Hauer Signed-off-by: Sascha Hauer Signed-off-by: Guennadi Liakhovetski priority: high --- drivers/media/video/mx3_camera.c | 4 ---- 1 files changed, 0 insertions(+), 4 deletions(-) --- linux/drivers/media/video/mx3_camera.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/mx3_camera.c b/linux/drivers/media/video/mx3_camera.c index cb13faa2e..4d47eeb14 100644 --- a/linux/drivers/media/video/mx3_camera.c +++ b/linux/drivers/media/video/mx3_camera.c @@ -1063,10 +1063,6 @@ static struct soc_camera_host_ops mx3_soc_camera_host_ops = { .owner = THIS_MODULE, .add = mx3_camera_add_device, .remove = mx3_camera_remove_device, -#ifdef CONFIG_PM - .suspend = mx3_camera_suspend, - .resume = mx3_camera_resume, -#endif .set_crop = mx3_camera_set_crop, .set_fmt = mx3_camera_set_fmt, .try_fmt = mx3_camera_try_fmt, -- cgit v1.2.3 From cdc99b1ab6d3e5b15d0837de6dcd1c42211dc18d Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Sat, 25 Apr 2009 18:29:01 +0200 Subject: gspca - main: Set the number of packets per ISOC message. From: Jean-Francois Moine The number of packets per isochronous message may now be set by the subdrivers (default value 32). Priority: normal Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/gspca.c | 6 +++--- linux/drivers/media/video/gspca/gspca.h | 4 ++-- linux/drivers/media/video/gspca/sonixb.c | 2 ++ linux/drivers/media/video/gspca/sonixj.c | 1 + linux/drivers/media/video/gspca/vc032x.c | 14 +++++++++++++- 5 files changed, 21 insertions(+), 6 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/gspca.c b/linux/drivers/media/video/gspca/gspca.c index e7f9e37d4..c3c17faa3 100644 --- a/linux/drivers/media/video/gspca/gspca.c +++ b/linux/drivers/media/video/gspca/gspca.c @@ -525,9 +525,9 @@ static int create_urbs(struct gspca_dev *gspca_dev, /* See paragraph 5.9 / table 5-11 of the usb 2.0 spec. */ psize = (psize & 0x07ff) * (1 + ((psize >> 11) & 3)); - npkt = ISO_MAX_SIZE / psize; - if (npkt > ISO_MAX_PKT) - npkt = ISO_MAX_PKT; + npkt = gspca_dev->cam.npkt; + if (npkt == 0) + npkt = 32; /* default value */ bsize = psize * npkt; PDEBUG(D_STREAM, "isoc %d pkts size %d = bsize:%d", diff --git a/linux/drivers/media/video/gspca/gspca.h b/linux/drivers/media/video/gspca/gspca.h index 85bb0fedd..bd1faff88 100644 --- a/linux/drivers/media/video/gspca/gspca.h +++ b/linux/drivers/media/video/gspca/gspca.h @@ -44,8 +44,6 @@ extern int gspca_debug; #define GSPCA_MAX_FRAMES 16 /* maximum number of video frame buffers */ /* image transfers */ #define MAX_NURBS 4 /* max number of URBs */ -#define ISO_MAX_PKT 32 /* max number of packets in an ISOC transfer */ -#define ISO_MAX_SIZE 0x8000 /* max size of one URB buffer (32 Kb) */ /* device information - set at probe time */ struct cam { @@ -57,6 +55,8 @@ struct cam { * - when 0 and bulk_size != 0 means * 1 URB and submit done by subdriver */ u8 bulk; /* image transfer by 0:isoc / 1:bulk */ + u8 npkt; /* number of packets in an ISOC message + * 0 is the default value: 32 packets */ u32 input_flags; /* value for ENUM_INPUT status flags */ }; diff --git a/linux/drivers/media/video/gspca/sonixb.c b/linux/drivers/media/video/gspca/sonixb.c index edb2bfa85..4141cf494 100644 --- a/linux/drivers/media/video/gspca/sonixb.c +++ b/linux/drivers/media/video/gspca/sonixb.c @@ -907,6 +907,8 @@ static int sd_config(struct gspca_dev *gspca_dev, cam->cam_mode = sif_mode; cam->nmodes = ARRAY_SIZE(sif_mode); } + cam->npkt = 36; /* 36 packets per ISOC message */ + sd->brightness = BRIGHTNESS_DEF; sd->gain = GAIN_DEF; sd->exposure = EXPOSURE_DEF; diff --git a/linux/drivers/media/video/gspca/sonixj.c b/linux/drivers/media/video/gspca/sonixj.c index c3959f00a..b3418f868 100644 --- a/linux/drivers/media/video/gspca/sonixj.c +++ b/linux/drivers/media/video/gspca/sonixj.c @@ -1296,6 +1296,7 @@ static int sd_config(struct gspca_dev *gspca_dev, cam = &gspca_dev->cam; cam->cam_mode = vga_mode; cam->nmodes = ARRAY_SIZE(vga_mode); + cam->npkt = 24; /* 24 packets per ISOC message */ sd->bridge = id->driver_info >> 16; sd->sensor = id->driver_info >> 8; diff --git a/linux/drivers/media/video/gspca/vc032x.c b/linux/drivers/media/video/gspca/vc032x.c index b5026a2d1..e994439fa 100644 --- a/linux/drivers/media/video/gspca/vc032x.c +++ b/linux/drivers/media/video/gspca/vc032x.c @@ -42,7 +42,7 @@ struct sd { char bridge; #define BRIDGE_VC0321 0 #define BRIDGE_VC0323 1 - char sensor; + u8 sensor; #define SENSOR_HV7131R 0 #define SENSOR_MI0360 1 #define SENSOR_MI1310_SOC 2 @@ -2905,6 +2905,17 @@ static int sd_config(struct gspca_dev *gspca_dev, struct usb_device *dev = gspca_dev->dev; struct cam *cam; int sensor; + static u8 npkt[] = { /* number of packets per ISOC message */ + 64, /* HV7131R 0 */ + 32, /* MI0360 1 */ + 32, /* MI1310_SOC 2 */ + 64, /* MI1320 3 */ + 128, /* MI1320_SOC 4 */ + 32, /* OV7660 5 */ + 64, /* OV7670 6 */ + 128, /* PO1200 7 */ + 128, /* PO3130NC 8 */ + }; cam = &gspca_dev->cam; sd->bridge = id->driver_info; @@ -2970,6 +2981,7 @@ static int sd_config(struct gspca_dev *gspca_dev, break; } } + cam->npkt = npkt[sd->sensor]; sd->hflip = HFLIP_DEF; sd->vflip = VFLIP_DEF; -- cgit v1.2.3 From 3a5029e47ebbbb4707dce75ad6beebe667224ba5 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 9 May 2009 21:45:37 +0200 Subject: soc-camera: Fix section mismatch warning From: Guennadi Liakhovetski modpost needs a __refdata marker in driver structs to ensure references to .probe and .remove functions from .devinit.text and .devexit.text sections respectively are valid. Add __refdata to soc_camera_pdrv platform driver. Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/soc_camera.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/soc_camera.c b/linux/drivers/media/video/soc_camera.c index f792ab2e5..822052b25 100644 --- a/linux/drivers/media/video/soc_camera.c +++ b/linux/drivers/media/video/soc_camera.c @@ -1204,7 +1204,7 @@ static int __devexit soc_camera_pdrv_remove(struct platform_device *pdev) return 0; } -static struct platform_driver soc_camera_pdrv = { +static struct platform_driver __refdata soc_camera_pdrv = { .probe = soc_camera_pdrv_probe, .remove = __exit_p(soc_camera_pdrv_remove), .driver = { -- cgit v1.2.3 From 8336aa0dd9ebd561d8bd2bd866b37071d0d0c79a Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 26 Apr 2009 08:43:59 +0000 Subject: Link firmware to physical device From: Jean Delvare Use the physical device rather than the i2c adapter as the reference device when loading firmwares. This will prevent the sysfs name collision with i2c-dev that has been reported many times. I may have missed other drivers which need the same fix. Signed-off-by: Jean Delvare Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/common/tuners/tuner-xc2028.c | 2 +- linux/drivers/media/common/tuners/xc5000.c | 2 +- linux/drivers/media/dvb/frontends/af9013.c | 2 +- linux/drivers/media/dvb/frontends/cx24116.c | 2 +- linux/drivers/media/dvb/frontends/drx397xD.c | 4 ++-- linux/drivers/media/dvb/frontends/nxt200x.c | 6 ++++-- linux/drivers/media/dvb/frontends/or51132.c | 2 +- linux/drivers/media/dvb/frontends/tda10048.c | 2 +- 8 files changed, 12 insertions(+), 10 deletions(-) (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 bd010379b..3f03dfa2c 100644 --- a/linux/drivers/media/common/tuners/tuner-xc2028.c +++ b/linux/drivers/media/common/tuners/tuner-xc2028.c @@ -276,7 +276,7 @@ static int load_all_firmwares(struct dvb_frontend *fe) fname = firmware_name; tuner_dbg("Reading firmware %s\n", fname); - rc = request_firmware(&fw, fname, &priv->i2c_props.adap->dev); + rc = request_firmware(&fw, fname, priv->i2c_props.adap->dev.parent); if (rc < 0) { if (rc == -ENOENT) tuner_err("Error: firmware %s not found.\n", diff --git a/linux/drivers/media/common/tuners/xc5000.c b/linux/drivers/media/common/tuners/xc5000.c index 39c415df0..e38433ec6 100644 --- a/linux/drivers/media/common/tuners/xc5000.c +++ b/linux/drivers/media/common/tuners/xc5000.c @@ -594,7 +594,7 @@ static int xc5000_fwupload(struct dvb_frontend *fe) XC5000_DEFAULT_FIRMWARE); ret = request_firmware(&fw, XC5000_DEFAULT_FIRMWARE, - &priv->i2c_props.adap->dev); + priv->i2c_props.adap->dev.parent); if (ret) { printk(KERN_ERR "xc5000: Upload failed. (file not found?)\n"); ret = XC_RESULT_RESET_FAILURE; diff --git a/linux/drivers/media/dvb/frontends/af9013.c b/linux/drivers/media/dvb/frontends/af9013.c index 937715a96..d12d99802 100644 --- a/linux/drivers/media/dvb/frontends/af9013.c +++ b/linux/drivers/media/dvb/frontends/af9013.c @@ -1456,7 +1456,7 @@ static int af9013_download_firmware(struct af9013_state *state) af9013_ops.info.name); /* request the firmware, this will block and timeout */ - ret = request_firmware(&fw, fw_file, &state->i2c->dev); + ret = request_firmware(&fw, fw_file, state->i2c->dev.parent); if (ret) { err("did not find the firmware file. (%s) " "Please see linux/Documentation/dvb/ for more details" \ diff --git a/linux/drivers/media/dvb/frontends/cx24116.c b/linux/drivers/media/dvb/frontends/cx24116.c index b5ff0b6a8..fddd27bd1 100644 --- a/linux/drivers/media/dvb/frontends/cx24116.c +++ b/linux/drivers/media/dvb/frontends/cx24116.c @@ -492,7 +492,7 @@ static int cx24116_firmware_ondemand(struct dvb_frontend *fe) printk(KERN_INFO "%s: Waiting for firmware upload (%s)...\n", __func__, CX24116_DEFAULT_FIRMWARE); ret = request_firmware(&fw, CX24116_DEFAULT_FIRMWARE, - &state->i2c->dev); + state->i2c->dev.parent); printk(KERN_INFO "%s: Waiting for firmware upload(2)...\n", __func__); if (ret) { diff --git a/linux/drivers/media/dvb/frontends/drx397xD.c b/linux/drivers/media/dvb/frontends/drx397xD.c index 0bdb933d0..95eff4a81 100644 --- a/linux/drivers/media/dvb/frontends/drx397xD.c +++ b/linux/drivers/media/dvb/frontends/drx397xD.c @@ -124,10 +124,10 @@ static int drx_load_fw(struct drx397xD_state *s, enum fw_ix ix) } memset(&fw[ix].data[0], 0, sizeof(fw[0].data)); - if (request_firmware(&fw[ix].file, fw[ix].name, &s->i2c->dev) != 0) { + rc = request_firmware(&fw[ix].file, fw[ix].name, s->i2c->dev.parent); + if (rc != 0) { printk(KERN_ERR "%s: Firmware \"%s\" not available\n", mod_name, fw[ix].name); - rc = -ENOENT; goto exit_err; } diff --git a/linux/drivers/media/dvb/frontends/nxt200x.c b/linux/drivers/media/dvb/frontends/nxt200x.c index 846350bc4..748f95b22 100644 --- a/linux/drivers/media/dvb/frontends/nxt200x.c +++ b/linux/drivers/media/dvb/frontends/nxt200x.c @@ -880,7 +880,8 @@ static int nxt2002_init(struct dvb_frontend* fe) /* request the firmware, this will block until someone uploads it */ printk("nxt2002: Waiting for firmware upload (%s)...\n", NXT2002_DEFAULT_FIRMWARE); - ret = request_firmware(&fw, NXT2002_DEFAULT_FIRMWARE, &state->i2c->dev); + ret = request_firmware(&fw, NXT2002_DEFAULT_FIRMWARE, + state->i2c->dev.parent); printk("nxt2002: Waiting for firmware upload(2)...\n"); if (ret) { printk("nxt2002: No firmware uploaded (timeout or file not found?)\n"); @@ -944,7 +945,8 @@ static int nxt2004_init(struct dvb_frontend* fe) /* request the firmware, this will block until someone uploads it */ printk("nxt2004: Waiting for firmware upload (%s)...\n", NXT2004_DEFAULT_FIRMWARE); - ret = request_firmware(&fw, NXT2004_DEFAULT_FIRMWARE, &state->i2c->dev); + ret = request_firmware(&fw, NXT2004_DEFAULT_FIRMWARE, + state->i2c->dev.parent); printk("nxt2004: Waiting for firmware upload(2)...\n"); if (ret) { printk("nxt2004: No firmware uploaded (timeout or file not found?)\n"); diff --git a/linux/drivers/media/dvb/frontends/or51132.c b/linux/drivers/media/dvb/frontends/or51132.c index 5ed32544d..8133ea3cd 100644 --- a/linux/drivers/media/dvb/frontends/or51132.c +++ b/linux/drivers/media/dvb/frontends/or51132.c @@ -340,7 +340,7 @@ static int or51132_set_parameters(struct dvb_frontend* fe, } printk("or51132: Waiting for firmware upload(%s)...\n", fwname); - ret = request_firmware(&fw, fwname, &state->i2c->dev); + ret = request_firmware(&fw, fwname, state->i2c->dev.parent); if (ret) { printk(KERN_WARNING "or51132: No firmware up" "loaded(timeout or file not found?)\n"); diff --git a/linux/drivers/media/dvb/frontends/tda10048.c b/linux/drivers/media/dvb/frontends/tda10048.c index 3163aad5b..a223e617f 100644 --- a/linux/drivers/media/dvb/frontends/tda10048.c +++ b/linux/drivers/media/dvb/frontends/tda10048.c @@ -492,7 +492,7 @@ static int tda10048_firmware_upload(struct dvb_frontend *fe) TDA10048_DEFAULT_FIRMWARE); ret = request_firmware(&fw, TDA10048_DEFAULT_FIRMWARE, - &state->i2c->dev); + state->i2c->dev.parent); if (ret) { printk(KERN_ERR "%s: Upload failed. (file not found?)\n", __func__); -- cgit v1.2.3 From f839a7e32846bf9f12045aec9371b228c0e6dcbf Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Sun, 26 Apr 2009 15:34:36 -0400 Subject: cx18: Allow IVTV format VBI insertion in MPEG-2 SVCD and DVD streams From: Andy Walls Both the MPEG-2 SVCD stream format and the MPEG-2 DVD stream format should use an MPEG-2 PS container. This makes it safe to stuff IVTV Private Stream 1 VBI packets in these stream types using the existing cx18 driver routines. Reported-by: Helen Buus Priority: normal Signed-off-by: Andy Walls --- linux/drivers/media/video/cx18/cx18-controls.c | 6 ++++-- linux/drivers/media/video/cx18/cx18-fileops.c | 7 ++++++- 2 files changed, 10 insertions(+), 3 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/cx18/cx18-controls.c b/linux/drivers/media/video/cx18/cx18-controls.c index 82fc2f9d4..8e35c3aed 100644 --- a/linux/drivers/media/video/cx18/cx18-controls.c +++ b/linux/drivers/media/video/cx18/cx18-controls.c @@ -176,8 +176,10 @@ static int cx18_setup_vbi_fmt(struct cx18 *cx, return -EBUSY; if (fmt != V4L2_MPEG_STREAM_VBI_FMT_IVTV || - type != V4L2_MPEG_STREAM_TYPE_MPEG2_PS) { - /* We don't do VBI insertion aside from IVTV format in a PS */ + !(type == V4L2_MPEG_STREAM_TYPE_MPEG2_PS || + type == V4L2_MPEG_STREAM_TYPE_MPEG2_DVD || + type == V4L2_MPEG_STREAM_TYPE_MPEG2_SVCD)) { + /* Only IVTV fmt VBI insertion & only MPEG-2 PS type streams */ cx->vbi.insert_mpeg = V4L2_MPEG_STREAM_VBI_FMT_NONE; CX18_DEBUG_INFO("disabled insertion of sliced VBI data into " "the MPEG stream\n"); diff --git a/linux/drivers/media/video/cx18/cx18-fileops.c b/linux/drivers/media/video/cx18/cx18-fileops.c index d20ac818f..817bb9263 100644 --- a/linux/drivers/media/video/cx18/cx18-fileops.c +++ b/linux/drivers/media/video/cx18/cx18-fileops.c @@ -301,8 +301,13 @@ static size_t cx18_copy_buf_to_user(struct cx18_stream *s, * an MPEG-2 Program Pack start code, and provide only * up to that point to the user, so it's easy to insert VBI data * the next time around. + * + * This will not work for an MPEG-2 TS and has only been + * verified by analysis to work for an MPEG-2 PS. Helen Buus + * pointed out this works for the CX23416 MPEG-2 DVD compatible + * stream, and research indicates both the MPEG 2 SVCD and DVD + * stream types use an MPEG-2 PS container. */ - /* FIXME - This only works for an MPEG-2 PS, not a TS */ /* * An MPEG-2 Program Stream (PS) is a series of * MPEG-2 Program Packs terminated by an -- cgit v1.2.3 From fea8fb6f1e235d4db4337c3a5f08bbc1de6b3af9 Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Sun, 26 Apr 2009 16:02:25 -0400 Subject: cx18: Verify cx18-av-core digitizer firmware loads correctly From: Andy Walls Add code to verify the cx18-av-core digitizer firmware loads correctly. The verification function reads back and compares the firmware bytes loaded into the A/V core. The result of the verification is only used to log a message in the system log. This change was prompted by users with multiple card setups that have problems with broadcast audio decoding the first time the cx18 module is loaded. Priority: normal Signed-off-by: Andy Walls --- linux/drivers/media/video/cx18/cx18-av-firmware.c | 50 ++++++++++++++++++++++- 1 file changed, 48 insertions(+), 2 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/cx18/cx18-av-firmware.c b/linux/drivers/media/video/cx18/cx18-av-firmware.c index 49a55cc8d..ab99030dc 100644 --- a/linux/drivers/media/video/cx18/cx18-av-firmware.c +++ b/linux/drivers/media/video/cx18/cx18-av-firmware.c @@ -27,6 +27,48 @@ #define CX18_AUDIO_ENABLE 0xc72014 #define FWFILE "v4l-cx23418-dig.fw" +static int cx18_av_verifyfw(struct cx18 *cx, const struct firmware *fw) +{ + struct v4l2_subdev *sd = &cx->av_state.sd; + int ret = 0; + const u8 *data; + u32 size; + int addr; + u32 expected, dl_control; + + /* Ensure we put the 8051 in reset and enable firmware upload mode */ + dl_control = cx18_av_read4(cx, CXADEC_DL_CTL); + do { + dl_control &= 0x00ffffff; + dl_control |= 0x0f000000; + cx18_av_write4_noretry(cx, CXADEC_DL_CTL, dl_control); + dl_control = cx18_av_read4(cx, CXADEC_DL_CTL); + } while ((dl_control & 0xff000000) != 0x0f000000); + + /* Read and auto increment until at address 0x0000 */ + while (dl_control & 0x3fff) + dl_control = cx18_av_read4(cx, CXADEC_DL_CTL); + + data = fw->data; + size = fw->size; + for (addr = 0; addr < size; addr++) { + dl_control &= 0xffff3fff; /* ignore top 2 bits of address */ + expected = 0x0f000000 | ((u32)data[addr] << 16) | addr; + if (expected != dl_control) { + CX18_ERR_DEV(sd, "verification of %s firmware load " + "failed: expected %#010x got %#010x\n", + FWFILE, expected, dl_control); + ret = -EIO; + break; + } + dl_control = cx18_av_read4(cx, CXADEC_DL_CTL); + } + if (ret == 0) + CX18_INFO_DEV(sd, "verified load of %s firmware (%d bytes)\n", + FWFILE, size); + return ret; +} + int cx18_av_loadfw(struct cx18 *cx) { struct v4l2_subdev *sd = &cx->av_state.sd; @@ -95,6 +137,12 @@ int cx18_av_loadfw(struct cx18 *cx) } cx18_av_write4_expect(cx, CXADEC_DL_CTL, + 0x03000000 | fw->size, 0x03000000, 0x13000000); + + CX18_INFO_DEV(sd, "loaded %s firmware (%d bytes)\n", FWFILE, size); + + if (cx18_av_verifyfw(cx, fw) == 0) + cx18_av_write4_expect(cx, CXADEC_DL_CTL, 0x13000000 | fw->size, 0x13000000, 0x13000000); /* Output to the 416 */ @@ -143,7 +191,5 @@ int cx18_av_loadfw(struct cx18 *cx) cx18_av_write4_expect(cx, CXADEC_STD_DET_CTL, v, v, 0x3F00FFFF); release_firmware(fw); - - CX18_INFO_DEV(sd, "loaded %s firmware (%d bytes)\n", FWFILE, size); return 0; } -- cgit v1.2.3 From 65877f260b6716f91d4cd687d28c1d1a3f21b470 Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Sun, 26 Apr 2009 17:46:14 -0400 Subject: cx18: Toggle the AI1 mux when changing the CX18_AUDIO_ENABLE register From: Andy Walls Toggle the AI1 mux when changing the CX18_AUDIO_ENABLE register. It's hard to reliably tell when we have written to this register successfully unless we change some bits we know we can read back. The AI mux bits always read back what we wrote to them, so force them to toggle whenever we have to write to the register, so we can tell we wrote to the register successfully. This change was prompted by users experiencing broadcast audio decoding problems after the cx18 module loads for the first time. Priority: normal Signed-off-by: Andy Walls --- linux/drivers/media/video/cx18/cx18-audio.c | 44 +++++++++++++++++++---- linux/drivers/media/video/cx18/cx18-av-firmware.c | 32 +++++++++++++++-- 2 files changed, 68 insertions(+), 8 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/cx18/cx18-audio.c b/linux/drivers/media/video/cx18/cx18-audio.c index 7a8ad5963..352689239 100644 --- a/linux/drivers/media/video/cx18/cx18-audio.c +++ b/linux/drivers/media/video/cx18/cx18-audio.c @@ -26,14 +26,18 @@ #include "cx18-cards.h" #include "cx18-audio.h" -#define CX18_AUDIO_ENABLE 0xc72014 +#define CX18_AUDIO_ENABLE 0xc72014 +#define CX18_AI1_MUX_MASK 0x30 +#define CX18_AI1_MUX_I2S1 0x00 +#define CX18_AI1_MUX_I2S2 0x10 +#define CX18_AI1_MUX_843_I2S 0x20 /* Selects the audio input and output according to the current settings. */ int cx18_audio_set_io(struct cx18 *cx) { const struct cx18_card_audio_input *in; - u32 val; + u32 u, v; int err; /* Determine which input to use */ @@ -52,9 +56,37 @@ int cx18_audio_set_io(struct cx18 *cx) return err; /* FIXME - this internal mux should be abstracted to a subdev */ - val = cx18_read_reg(cx, CX18_AUDIO_ENABLE) & ~0x30; - val |= (in->audio_input > CX18_AV_AUDIO_SERIAL2) ? 0x20 : - (in->audio_input << 4); - cx18_write_reg_expect(cx, val | 0xb00, CX18_AUDIO_ENABLE, val, 0x30); + u = cx18_read_reg(cx, CX18_AUDIO_ENABLE); + v = u & ~CX18_AI1_MUX_MASK; + switch (in->audio_input) { + case CX18_AV_AUDIO_SERIAL1: + v |= CX18_AI1_MUX_I2S1; + break; + case CX18_AV_AUDIO_SERIAL2: + v |= CX18_AI1_MUX_I2S2; + break; + default: + v |= CX18_AI1_MUX_843_I2S; + break; + } + if (v == u) { + /* force a toggle of some AI1 MUX control bits */ + u &= ~CX18_AI1_MUX_MASK; + switch (in->audio_input) { + case CX18_AV_AUDIO_SERIAL1: + u |= CX18_AI1_MUX_843_I2S; + break; + case CX18_AV_AUDIO_SERIAL2: + u |= CX18_AI1_MUX_843_I2S; + break; + default: + u |= CX18_AI1_MUX_I2S1; + break; + } + cx18_write_reg_expect(cx, u | 0xb00, CX18_AUDIO_ENABLE, + u, CX18_AI1_MUX_MASK); + } + cx18_write_reg_expect(cx, v | 0xb00, CX18_AUDIO_ENABLE, + v, CX18_AI1_MUX_MASK); return 0; } diff --git a/linux/drivers/media/video/cx18/cx18-av-firmware.c b/linux/drivers/media/video/cx18/cx18-av-firmware.c index ab99030dc..b9e8cc5d2 100644 --- a/linux/drivers/media/video/cx18/cx18-av-firmware.c +++ b/linux/drivers/media/video/cx18/cx18-av-firmware.c @@ -24,7 +24,13 @@ #include "cx18-io.h" #include -#define CX18_AUDIO_ENABLE 0xc72014 +#define CX18_AUDIO_ENABLE 0xc72014 +#define CX18_AI1_MUX_MASK 0x30 +#define CX18_AI1_MUX_I2S1 0x00 +#define CX18_AI1_MUX_I2S2 0x10 +#define CX18_AI1_MUX_843_I2S 0x20 +#define CX18_AI1_MUX_INVALID 0x30 + #define FWFILE "v4l-cx23418-dig.fw" static int cx18_av_verifyfw(struct cx18 *cx, const struct firmware *fw) @@ -74,7 +80,7 @@ int cx18_av_loadfw(struct cx18 *cx) struct v4l2_subdev *sd = &cx->av_state.sd; const struct firmware *fw = NULL; u32 size; - u32 v; + u32 u, v; const u8 *ptr; int i; int retries1 = 0; @@ -183,6 +189,28 @@ int cx18_av_loadfw(struct cx18 *cx) cx18_write_reg_expect(cx, v & 0xFFFFFBFF, CX18_AUDIO_ENABLE, 0, 0x400); + /* Toggle the AI1 MUX */ + v = cx18_read_reg(cx, CX18_AUDIO_ENABLE); + u = v & CX18_AI1_MUX_MASK; + v &= ~CX18_AI1_MUX_MASK; + if (u == CX18_AI1_MUX_843_I2S || u == CX18_AI1_MUX_INVALID) { + /* Switch to I2S1 */ + v |= CX18_AI1_MUX_I2S1; + cx18_write_reg_expect(cx, v | 0xb00, CX18_AUDIO_ENABLE, + v, CX18_AI1_MUX_MASK); + /* Switch back to the A/V decoder core I2S output */ + v = (v & ~CX18_AI1_MUX_MASK) | CX18_AI1_MUX_843_I2S; + } else { + /* Switch to the A/V decoder core I2S output */ + v |= CX18_AI1_MUX_843_I2S; + cx18_write_reg_expect(cx, v | 0xb00, CX18_AUDIO_ENABLE, + v, CX18_AI1_MUX_MASK); + /* Switch back to I2S1 or I2S2 */ + v = (v & ~CX18_AI1_MUX_MASK) | u; + } + cx18_write_reg_expect(cx, v | 0xb00, CX18_AUDIO_ENABLE, + v, CX18_AI1_MUX_MASK); + /* Enable WW auto audio standard detection */ v = cx18_av_read4(cx, CXADEC_STD_DET_CTL); v |= 0xFF; /* Auto by default */ -- cgit v1.2.3 From 931c58dd0134b10194c570d8e5d47f774dd6fb5d Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Mon, 27 Apr 2009 10:27:04 -0400 Subject: cx23885: Two fixes for DViCO FusionHDTV DVB-T Dual Express From: Christopher Pascoe Two fixes for DViCO FusionHDTV DVB-T Dual Express: * Reset correct tuner when reinitializing xc3028. * Disable the I2C gate control to avoid locking up the I2C bus. Priority: high Signed-off-by: Christopher Pascoe Signed-off-by: Devin Heitmueller Tested-by: John Knops Reviewed-By: Steven Toth --- linux/drivers/media/video/cx23885/cx23885-cards.c | 4 ++-- linux/drivers/media/video/cx23885/cx23885-dvb.c | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/cx23885/cx23885-cards.c b/linux/drivers/media/video/cx23885/cx23885-cards.c index 454470ffc..28f305dfd 100644 --- a/linux/drivers/media/video/cx23885/cx23885-cards.c +++ b/linux/drivers/media/video/cx23885/cx23885-cards.c @@ -442,9 +442,9 @@ int cx23885_tuner_callback(void *priv, int component, int command, int arg) case CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP: /* Two identical tuners on two different i2c buses, * we need to reset the correct gpio. */ - if (port->nr == 0) + if (port->nr == 1) bitmask = 0x01; - else if (port->nr == 1) + else if (port->nr == 2) bitmask = 0x04; break; } diff --git a/linux/drivers/media/video/cx23885/cx23885-dvb.c b/linux/drivers/media/video/cx23885/cx23885-dvb.c index c4c1d396c..119907f29 100644 --- a/linux/drivers/media/video/cx23885/cx23885-dvb.c +++ b/linux/drivers/media/video/cx23885/cx23885-dvb.c @@ -315,6 +315,7 @@ static struct zl10353_config dvico_fusionhdtv_xc3028 = { .demod_address = 0x0f, .if2 = 45600, .no_tuner = 1, + .disable_i2c_gate_ctrl = 1, }; static struct stv0900_config netup_stv0900_config = { -- cgit v1.2.3 From 2af675418bb28b6297dfe4d592589fcd7a9410f6 Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Tue, 28 Apr 2009 12:14:07 -0400 Subject: au0828: fix kernel oops regression on USB disconnect. From: Devin Heitmueller A regression was introduced in hg changeset 33810c734a0d, which resulted in a kernel panic whenever the device was disconnected from USB. The call to 4l2_device_register() was overwriting the pointer for usb_set_intfdata(), so when au0828_usb_disconnect() was called, the usb_get_intfdata() returned a pointer to the v4l2_device instead of the au0828_dev structure. Priority: high Signed-off-by: Devin Heitmueller --- linux/drivers/media/video/au0828/au0828-core.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/au0828/au0828-core.c b/linux/drivers/media/video/au0828/au0828-core.c index ab25af430..4da5b7909 100644 --- a/linux/drivers/media/video/au0828/au0828-core.c +++ b/linux/drivers/media/video/au0828/au0828-core.c @@ -193,8 +193,6 @@ static int au0828_usb_probe(struct usb_interface *interface, dev->usbdev = usbdev; dev->boardnr = id->driver_info; - usb_set_intfdata(interface, dev); - /* Create the v4l2_device */ retval = v4l2_device_register(&interface->dev, &dev->v4l2_dev); if (retval) { @@ -223,6 +221,10 @@ static int au0828_usb_probe(struct usb_interface *interface, /* Digital TV */ au0828_dvb_register(dev); + /* Store the pointer to the au0828_dev so it can be accessed in + au0828_usb_disconnect */ + usb_set_intfdata(interface, dev); + printk(KERN_INFO "Registered device AU0828 [%s]\n", dev->board.name == NULL ? "Unset" : dev->board.name); -- cgit v1.2.3 From 60b4d74dcde3331a1fe9844599ac1c7380f290b3 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 26 Apr 2009 12:30:18 +0000 Subject: gspca - m5602: Storage class should be before const qualifier MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: Tobias Klauser The C99 specification states in section 6.11.5: The placement of a storage-class specifier other than at the beginning of the declaration specifiers in a declaration is an obsolescent feature. [mchehab@redhat.com: Fix a trivial merge conflict] Signed-off-by: Tobias Klauser CC: Erik Andrén Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h | 2 +- linux/drivers/media/video/gspca/m5602/m5602_ov9650.c | 2 +- linux/drivers/media/video/gspca/m5602/m5602_ov9650.h | 2 +- linux/drivers/media/video/gspca/m5602/m5602_po1030.c | 2 +- linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c | 2 +- linux/drivers/media/video/gspca/m5602/m5602_s5k83a.c | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h b/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h index e71ddb786..b3de77823 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h @@ -113,7 +113,7 @@ int mt9m111_init(struct sd *sd); int mt9m111_start(struct sd *sd); void mt9m111_disconnect(struct sd *sd); -const static struct m5602_sensor mt9m111 = { +static const struct m5602_sensor mt9m111 = { .name = "MT9M111", .i2c_slave_id = 0xba, diff --git a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c index fcaf207c4..83fdff268 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c @@ -99,7 +99,7 @@ static {} }; -const static struct ctrl ov9650_ctrls[] = { +static const struct ctrl ov9650_ctrls[] = { #define EXPOSURE_IDX 0 { { diff --git a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.h b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.h index 27fe54204..c98c40d69 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.h @@ -143,7 +143,7 @@ int ov9650_start(struct sd *sd); int ov9650_stop(struct sd *sd); void ov9650_disconnect(struct sd *sd); -const static struct m5602_sensor ov9650 = { +static const struct m5602_sensor ov9650 = { .name = "OV9650", .i2c_slave_id = 0x60, .i2c_regW = 1, diff --git a/linux/drivers/media/video/gspca/m5602/m5602_po1030.c b/linux/drivers/media/video/gspca/m5602/m5602_po1030.c index 7706bd29f..633636365 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_po1030.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_po1030.c @@ -66,7 +66,7 @@ static struct v4l2_pix_format po1030_modes[] = { } }; -const static struct ctrl po1030_ctrls[] = { +static const struct ctrl po1030_ctrls[] = { #define GAIN_IDX 0 { { diff --git a/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c b/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c index 3ec22ebd2..2c0940bff 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c @@ -79,7 +79,7 @@ static struct v4l2_pix_format s5k4aa_modes[] = { } }; -const static struct ctrl s5k4aa_ctrls[] = { +static const struct ctrl s5k4aa_ctrls[] = { #define VFLIP_IDX 0 { { diff --git a/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.c b/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.c index 942030fd0..df21ad19a 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.c @@ -44,7 +44,7 @@ static struct v4l2_pix_format s5k83a_modes[] = { } }; -const static struct ctrl s5k83a_ctrls[] = { +static const struct ctrl s5k83a_ctrls[] = { #define GAIN_IDX 0 { { -- cgit v1.2.3 From 174bab7f1cc3bfa7b54978080cbe82002b94adbf Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 26 Apr 2009 13:03:29 +0000 Subject: firedtv: Storage class should be before const qualifier From: Tobias Klauser The C99 specification states in section 6.11.5: The placement of a storage-class specifier other than at the beginning of the declaration specifiers in a declaration is an obsolescent feature. Signed-off-by: Tobias Klauser Acked-by: Stefan Richter Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/firewire/firedtv-rc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/firewire/firedtv-rc.c b/linux/drivers/media/dvb/firewire/firedtv-rc.c index 46a6324d7..27bca2e28 100644 --- a/linux/drivers/media/dvb/firewire/firedtv-rc.c +++ b/linux/drivers/media/dvb/firewire/firedtv-rc.c @@ -18,7 +18,7 @@ #include "firedtv.h" /* fixed table with older keycodes, geared towards MythTV */ -const static u16 oldtable[] = { +static const u16 oldtable[] = { /* code from device: 0x4501...0x451f */ @@ -62,7 +62,7 @@ const static u16 oldtable[] = { }; /* user-modifiable table for a remote as sold in 2008 */ -const static u16 keytable[] = { +static const u16 keytable[] = { /* code from device: 0x0300...0x031f */ -- cgit v1.2.3 From 4c50c14ed35b0df615ad59f74cadbbaf52b0c657 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 26 Apr 2009 15:31:26 +0000 Subject: V4L/DVB: cx23885/cymax2: binary/logical &/&& typo From: Roel Kluin Signed-off-by: Roel Kluin Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/cx23885/cimax2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/cx23885/cimax2.c b/linux/drivers/media/video/cx23885/cimax2.c index 0e29f97f3..fed6d9f9f 100644 --- a/linux/drivers/media/video/cx23885/cimax2.c +++ b/linux/drivers/media/video/cx23885/cimax2.c @@ -320,7 +320,7 @@ static void netup_read_ci_status(struct work_struct *work) "TS config = %02x\n", __func__, state->ci_i2c_addr, 0, buf[0], buf[32]); - if (buf[0] && 1) + if (buf[0] & 1) state->status = DVB_CA_EN50221_POLL_CAM_PRESENT | DVB_CA_EN50221_POLL_CAM_READY; else -- cgit v1.2.3 From 2202d0517ac0f2864868e84b832cf979586568b8 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Sun, 26 Apr 2009 19:46:12 +0200 Subject: gspca - sonixj: Adjust some exchanges according to traces. From: Jean-Francois Moine Priority: normal Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/sonixj.c | 69 +++++++++++++++----------------- 1 file changed, 32 insertions(+), 37 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/sonixj.c b/linux/drivers/media/video/gspca/sonixj.c index b3418f868..c01f4e1c9 100644 --- a/linux/drivers/media/video/gspca/sonixj.c +++ b/linux/drivers/media/video/gspca/sonixj.c @@ -62,7 +62,6 @@ struct sd { #define BRIDGE_SN9C105 1 #define BRIDGE_SN9C110 2 #define BRIDGE_SN9C120 3 -#define BRIDGE_SN9C325 4 u8 sensor; /* Type of image sensor chip */ #define SENSOR_HV7131R 0 #define SENSOR_MI0360 1 @@ -358,9 +357,9 @@ static const u8 sn_ov7648[0x1c] = { static const u8 sn_ov7660[0x1c] = { /* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */ - 0x00, 0x61, 0x40, 0x00, 0x1a, 0x20, 0x20, 0x20, + 0x00, 0x61, 0x40, 0x00, 0x1a, 0x00, 0x00, 0x00, /* reg8 reg9 rega regb regc regd rege regf */ - 0x81, 0x21, 0x07, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x81, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */ 0x03, 0x00, 0x01, 0x01, 0x08, 0x28, 0x1e, 0x20, /* reg18 reg19 reg1a reg1b */ @@ -765,6 +764,7 @@ static const u8 ov7660_sensor_init[][8] = { {0xc1, 0x21, 0x88, 0xaf, 0xc7, 0xdf, 0x00, 0x10}, /* gamma curve */ {0xc1, 0x21, 0x8b, 0x99, 0x99, 0xcf, 0x00, 0x10}, /* reserved */ {0xb1, 0x21, 0x92, 0x00, 0x00, 0x00, 0x00, 0x10}, /* DM_LNL/H */ + {0xb1, 0x21, 0xa1, 0x00, 0x00, 0x00, 0x00, 0x10}, /****** (some exchanges in the win trace) ******/ {0xa1, 0x21, 0x1e, 0x01, 0x00, 0x00, 0x00, 0x10}, /* MVFP */ /* bits[3..0]reserved */ @@ -1073,9 +1073,13 @@ static int configure_gpio(struct gspca_dev *gspca_dev, struct sd *sd = (struct sd *) gspca_dev; const u8 *reg9a; static const u8 reg9a_def[] = - {0x08, 0x40, 0x20, 0x10, 0x00, 0x04}; - static const u8 reg9a_sn9c325[] = - {0x0a, 0x40, 0x38, 0x30, 0x00, 0x20}; +#if 1 + {0x00, 0x40, 0x20, 0x00, 0x00, 0x00}; +#else + {0x00, 0x40, 0x20, 0x10, 0x00, 0x04}; +#endif + static const u8 reg9a_spec[] = + {0x00, 0x40, 0x38, 0x30, 0x00, 0x20}; static const u8 regd4[] = {0x60, 0x00, 0x00}; reg_w1(gspca_dev, 0xf1, 0x00); @@ -1089,9 +1093,10 @@ static int configure_gpio(struct gspca_dev *gspca_dev, reg_w(gspca_dev, 0x01, &sn9c1xx[1], 2); reg_w(gspca_dev, 0x08, &sn9c1xx[8], 2); reg_w(gspca_dev, 0x17, &sn9c1xx[0x17], 5); /* jfm len was 3 */ - switch (sd->bridge) { - case BRIDGE_SN9C325: - reg9a = reg9a_sn9c325; + switch (sd->sensor) { + case SENSOR_OV7660: + case SENSOR_SP80708: + reg9a = reg9a_spec; break; default: reg9a = reg9a_def; @@ -1116,32 +1121,24 @@ static int configure_gpio(struct gspca_dev *gspca_dev, reg_w1(gspca_dev, 0x17, 0x64); reg_w1(gspca_dev, 0x01, 0x42); break; -#if 1 -/*jfm: from win trace */ case SENSOR_OV7630: reg_w1(gspca_dev, 0x01, 0x61); reg_w1(gspca_dev, 0x17, 0xe2); reg_w1(gspca_dev, 0x01, 0x60); reg_w1(gspca_dev, 0x01, 0x40); break; -#endif case SENSOR_OV7648: reg_w1(gspca_dev, 0x01, 0x63); reg_w1(gspca_dev, 0x17, 0x20); + reg_w1(gspca_dev, 0x01, 0x62); reg_w1(gspca_dev, 0x01, 0x42); break; -#if 1 -/*jfm: from win trace */ case SENSOR_OV7660: - if (sd->bridge == BRIDGE_SN9C120) { - reg_w1(gspca_dev, 0x01, 0x61); - reg_w1(gspca_dev, 0x17, 0x20); - reg_w1(gspca_dev, 0x01, 0x60); - reg_w1(gspca_dev, 0x01, 0x40); - break; - } - /* fall thru */ -#endif + reg_w1(gspca_dev, 0x01, 0x61); + reg_w1(gspca_dev, 0x17, 0x20); + reg_w1(gspca_dev, 0x01, 0x60); + reg_w1(gspca_dev, 0x01, 0x40); + break; case SENSOR_SP80708: reg_w1(gspca_dev, 0x01, 0x63); reg_w1(gspca_dev, 0x17, 0x20); @@ -1150,6 +1147,9 @@ static int configure_gpio(struct gspca_dev *gspca_dev, mdelay(100); reg_w1(gspca_dev, 0x02, 0x62); break; +/* case SENSOR_HV7131R: */ +/* case SENSOR_MI0360: */ +/* case SENSOR_MO4000: */ default: reg_w1(gspca_dev, 0x01, 0x43); reg_w1(gspca_dev, 0x17, 0x61); @@ -1716,15 +1716,9 @@ static int sd_start(struct gspca_dev *gspca_dev) case SENSOR_OV7648: reg17 = 0x20; break; -#if 1 -/*jfm: from win trace */ case SENSOR_OV7660: - if (sd->bridge == BRIDGE_SN9C120) { - reg17 = 0xa0; - break; - } - /* fall thru */ -#endif + reg17 = 0xa0; + break; default: reg17 = 0x60; break; @@ -1749,16 +1743,17 @@ static int sd_start(struct gspca_dev *gspca_dev) reg_w1(gspca_dev, 0x9a, 0x0a); reg_w1(gspca_dev, 0x99, 0x60); break; + case SENSOR_OV7660: + reg_w1(gspca_dev, 0x9a, 0x05); + if (sd->bridge == BRIDGE_SN9C105) + reg_w1(gspca_dev, 0x99, 0xff); + else + reg_w1(gspca_dev, 0x99, 0x5b); + break; case SENSOR_SP80708: reg_w1(gspca_dev, 0x9a, 0x05); reg_w1(gspca_dev, 0x99, 0x59); break; - case SENSOR_OV7660: - if (sd->bridge == BRIDGE_SN9C120) { - reg_w1(gspca_dev, 0x9a, 0x05); - break; - } - /* fall thru */ default: reg_w1(gspca_dev, 0x9a, 0x08); reg_w1(gspca_dev, 0x99, 0x59); -- cgit v1.2.3 From 413c17d0bd1060bf7ebfb0c216cee97a130085df Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 27 Apr 2009 10:50:42 +0000 Subject: Modify the file license to match all other Siano's files From: Uri Shkolnik Modify the file license to match all other Siano's files Priority: normal Signed-off-by: Uri Shkolnik Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/siano/smscoreapi.h | 48 +++++++++++++++--------------- 1 file changed, 24 insertions(+), 24 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/siano/smscoreapi.h b/linux/drivers/media/dvb/siano/smscoreapi.h index 83e0e55f7..1aa27f836 100644 --- a/linux/drivers/media/dvb/siano/smscoreapi.h +++ b/linux/drivers/media/dvb/siano/smscoreapi.h @@ -1,26 +1,26 @@ -/* - * Driver for the Siano SMS1xxx USB dongle - * - * author: Anatoly Greenblat - * - * Copyright (c), 2005-2008 Siano Mobile Silicon, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation; - * - * Software distributed under the License is distributed on an "AS IS" - * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. - * - * See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#ifndef __smscoreapi_h__ -#define __smscoreapi_h__ +/**************************************************************** + +Siano Mobile Silicon, Inc. +MDTV receiver kernel modules. +Copyright (C) 2006-2008, Uri Shkolnik, Anatoly Greenblat + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 of the License, or +(at your option) any later version. + + This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . + +****************************************************************/ + +#ifndef __SMS_CORE_API_H__ +#define __SMS_CORE_API_H__ #include #include @@ -679,4 +679,4 @@ int smscore_led_state(struct smscore_device_t *core, int led); dprintk(KERN_DEBUG, DBG_ADV, fmt, ##arg) -#endif /* __smscoreapi_h__ */ +#endif /* __SMS_CORE_API_H__ */ -- cgit v1.2.3 From 9ba5733875ddcf79e88cb46977a70a9919932a4b Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 11 May 2009 06:36:27 -0300 Subject: Siano: core header - update include files From: Uri Shkolnik Re-order the include files list Re-order the include files list, put the DVB-API v3 within its own section, within a define container. Priority: normal Signed-off-by: Uri Shkolnik Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/siano/smscoreapi.h | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/siano/smscoreapi.h b/linux/drivers/media/dvb/siano/smscoreapi.h index 1aa27f836..72e385c05 100644 --- a/linux/drivers/media/dvb/siano/smscoreapi.h +++ b/linux/drivers/media/dvb/siano/smscoreapi.h @@ -28,15 +28,20 @@ along with this program. If not, see . #include #include #include -#include #include +#include +#include + +#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_) -- cgit v1.2.3 From 19e333202f72c13f3d78fcdb935ed454d402e779 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 27 Apr 2009 12:09:47 +0000 Subject: Siano: smsdvb - modify license From: Uri Shkolnik Siano: smsdvb - Fix license to match all other Siano's files Priority: normal Signed-off-by: Uri Shkolnik Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/siano/smsdvb.c | 40 +++++++++++++++++----------------- 1 file changed, 20 insertions(+), 20 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/siano/smsdvb.c b/linux/drivers/media/dvb/siano/smsdvb.c index 035bd52c9..3991883b7 100644 --- a/linux/drivers/media/dvb/siano/smsdvb.c +++ b/linux/drivers/media/dvb/siano/smsdvb.c @@ -1,23 +1,23 @@ -/* - * Driver for the Siano SMS1xxx USB dongle - * - * Author: Uri Shkolni - * - * Copyright (c), 2005-2008 Siano Mobile Silicon, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation; - * - * Software distributed under the License is distributed on an "AS IS" - * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. - * - * See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ +/**************************************************************** + +Siano Mobile Silicon, Inc. +MDTV receiver kernel modules. +Copyright (C) 2006-2008, Uri Shkolnik + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 of the License, or +(at your option) any later version. + + This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . + +****************************************************************/ #include #include -- cgit v1.2.3 From df5e4d6882589cee518247400d785abbfb470240 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 27 Apr 2009 12:12:37 +0000 Subject: Siano: smsdvb - remove redundent complete instruction From: Uri Shkolnik Remove redundant complete instruction from smsdvb, in the past this was used by the statistics state machine, but no longer. Priority: normal Signed-off-by: Uri Shkolnik Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/siano/smsdvb.c | 1 - 1 file changed, 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/siano/smsdvb.c b/linux/drivers/media/dvb/siano/smsdvb.c index 3991883b7..255ee5719 100644 --- a/linux/drivers/media/dvb/siano/smsdvb.c +++ b/linux/drivers/media/dvb/siano/smsdvb.c @@ -488,7 +488,6 @@ static int smsdvb_hotplug(struct smscore_device_t *coredev, client->coredev = coredev; init_completion(&client->tune_done); - init_completion(&client->stat_done); kmutex_lock(&g_smsdvb_clientslock); -- cgit v1.2.3 From 2031afeba8b04f69eaec2813c11809fc5b3b0a99 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 28 Apr 2009 04:11:22 +0000 Subject: af9015: support for KWorld MC810 From: Wen-chien Jesse Sung Add USB ID (1b80:c810) for Kworld MC810. Priority: normal Signed-off-by: Wen-chien Jesse Sung Acked-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/dvb-usb/af9015.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/af9015.c b/linux/drivers/media/dvb/dvb-usb/af9015.c index 57c678892..5d9aacd0a 100644 --- a/linux/drivers/media/dvb/dvb-usb/af9015.c +++ b/linux/drivers/media/dvb/dvb-usb/af9015.c @@ -1267,6 +1267,7 @@ static struct usb_device_id af9015_usb_table[] = { /* 20 */{USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A850)}, {USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A805)}, {USB_DEVICE(USB_VID_KWORLD_2, USB_PID_CONCEPTRONIC_CTVDIGRCU)}, + {USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_MC810)}, {0}, }; MODULE_DEVICE_TABLE(usb, af9015_usb_table); @@ -1537,7 +1538,7 @@ static struct dvb_usb_device_properties af9015_properties[] = { .i2c_algo = &af9015_i2c_algo, - .num_device_descs = 2, /* max 9 */ + .num_device_descs = 3, /* max 9 */ .devices = { { .name = "AverMedia AVerTV Volar GPS 805 (A805)", @@ -1550,6 +1551,11 @@ static struct dvb_usb_device_properties af9015_properties[] = { .cold_ids = {&af9015_usb_table[22], NULL}, .warm_ids = {NULL}, }, + { + .name = "KWorld Digial MC-810", + .cold_ids = {&af9015_usb_table[23], NULL}, + .warm_ids = {NULL}, + }, } }, }; 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 6a4062d5d..1b5e65f1d 100644 --- a/linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h +++ b/linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h @@ -105,6 +105,7 @@ #define USB_PID_KWORLD_395U 0xe396 #define USB_PID_KWORLD_395U_2 0xe39b #define USB_PID_KWORLD_395U_3 0xe395 +#define USB_PID_KWORLD_MC810 0xc810 #define USB_PID_KWORLD_PC160_2T 0xc160 #define USB_PID_KWORLD_VSTREAM_COLD 0x17de #define USB_PID_KWORLD_VSTREAM_WARM 0x17df -- cgit v1.2.3 From b6e7822b8f96c2e514b0ec863de373928a2e14e2 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 28 Apr 2009 08:45:39 +0000 Subject: buf-dma-contig: remove sync operation From: Magnus Damm Remove the videobuf-dma-contig sync operation. Sync is only needed for noncoherent buffers, and since videobuf-dma-contig is built on coherent memory allocators the memory is by definition always in sync. Reported-by: Matthieu CASTET Signed-off-by: Magnus Damm Reviewed-by: Paul Mundt Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/videobuf-dma-contig.c | 14 -------------- 1 file changed, 14 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/videobuf-dma-contig.c b/linux/drivers/media/video/videobuf-dma-contig.c index 6db1398fd..633a124cf 100644 --- a/linux/drivers/media/video/videobuf-dma-contig.c +++ b/linux/drivers/media/video/videobuf-dma-contig.c @@ -183,19 +183,6 @@ static int __videobuf_iolock(struct videobuf_queue *q, return 0; } -static int __videobuf_sync(struct videobuf_queue *q, - struct videobuf_buffer *buf) -{ - struct videobuf_dma_contig_memory *mem = buf->priv; - - BUG_ON(!mem); - MAGIC_CHECK(mem->magic, MAGIC_DC_MEM); - - dma_sync_single_for_cpu(q->dev, mem->dma_handle, mem->size, - DMA_FROM_DEVICE); - return 0; -} - static int __videobuf_mmap_free(struct videobuf_queue *q) { unsigned int i; @@ -357,7 +344,6 @@ static struct videobuf_qtype_ops qops = { .alloc = __videobuf_alloc, .iolock = __videobuf_iolock, - .sync = __videobuf_sync, .mmap_free = __videobuf_mmap_free, .mmap_mapper = __videobuf_mmap_mapper, .video_copy_to_user = __videobuf_copy_to_user, -- cgit v1.2.3 From bcd4645cb019d22f5addac33a51fc424a3cf042d Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 28 Apr 2009 22:44:05 +0000 Subject: saa7134: disable not yet existing IR and DVB support on the Compro T750 From: hermann pitton The Compro VideoMate T750 has no support for IR and DVB-T yet. Disable both to avoid fall through and confusing printouts. Signed-off-by: Hermann Pitton Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/saa7134/saa7134-cards.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/saa7134/saa7134-cards.c b/linux/drivers/media/video/saa7134/saa7134-cards.c index 582a56c07..a4e3deac2 100644 --- a/linux/drivers/media/video/saa7134/saa7134-cards.c +++ b/linux/drivers/media/video/saa7134/saa7134-cards.c @@ -4826,7 +4826,6 @@ struct saa7134_board saa7134_boards[] = { .radio_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, - .mpeg = SAA7134_MPEG_DVB, .inputs = {{ .name = name_tv, .vmux = 3, @@ -6580,7 +6579,6 @@ int saa7134_board_init1(struct saa7134_dev *dev) case SAA7134_BOARD_VIDEOMATE_DVBT_300: case SAA7134_BOARD_VIDEOMATE_DVBT_200: case SAA7134_BOARD_VIDEOMATE_DVBT_200A: - case SAA7134_BOARD_VIDEOMATE_T750: case SAA7134_BOARD_MANLI_MTV001: case SAA7134_BOARD_MANLI_MTV002: case SAA7134_BOARD_BEHOLD_409FM: -- cgit v1.2.3 From 42a150036e0f0f58c5882319cec52b76a401471c Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 28 Apr 2009 09:41:08 +0000 Subject: increase MPEG encoder timout From: Dmitri Belimov Hi All. If video has a lot of changes in frame, MPEG encoder need more time for coding process. Add new bigger timeout for encoder. This is patch from our customer. I checked this. Signed-off-by: Alexey Osipov Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/saa7134/saa7134-ts.c | 2 +- linux/drivers/media/video/saa7134/saa7134.h | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/saa7134/saa7134-ts.c b/linux/drivers/media/video/saa7134/saa7134-ts.c index cc8b923af..b8ff459d0 100644 --- a/linux/drivers/media/video/saa7134/saa7134-ts.c +++ b/linux/drivers/media/video/saa7134/saa7134-ts.c @@ -65,7 +65,7 @@ static int buffer_activate(struct saa7134_dev *dev, /* start DMA */ saa7134_set_dmabits(dev); - mod_timer(&dev->ts_q.timeout, jiffies+BUFFER_TIMEOUT); + mod_timer(&dev->ts_q.timeout, jiffies+TS_BUFFER_TIMEOUT); if (dev->ts_state == SAA7134_TS_BUFF_DONE) { /* Clear TS cache */ diff --git a/linux/drivers/media/video/saa7134/saa7134.h b/linux/drivers/media/video/saa7134/saa7134.h index d961e0861..ae7ba8923 100644 --- a/linux/drivers/media/video/saa7134/saa7134.h +++ b/linux/drivers/media/video/saa7134/saa7134.h @@ -377,6 +377,7 @@ struct saa7134_board { #define INTERLACE_OFF 2 #define BUFFER_TIMEOUT msecs_to_jiffies(500) /* 0.5 seconds */ +#define TS_BUFFER_TIMEOUT msecs_to_jiffies(1000) /* 1 second */ struct saa7134_dev; struct saa7134_dma; -- cgit v1.2.3 From ed9027e5c1c8f80d44d34d80514e48469bc61c0f Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 28 Apr 2009 09:46:15 +0000 Subject: remove hw reset of MPEG encoder when lost/found seq. From: Dmitri Belimov When we capture signal from composite input offen lost and found syncro sequence. In this case the MPEG coder hardware reset after each lost/found event. The image has a lot of artefactes. This patch remove hardware reset of MPEG encoder. This is patch from our customer. I checked this. With my best regards, Dmitry. Signed-off-by: Alexey Osipov Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/saa7134/saa7134-empress.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/saa7134/saa7134-empress.c b/linux/drivers/media/video/saa7134/saa7134-empress.c index bab6b56c8..dd22a5215 100644 --- a/linux/drivers/media/video/saa7134/saa7134-empress.c +++ b/linux/drivers/media/video/saa7134/saa7134-empress.c @@ -499,11 +499,8 @@ static void empress_signal_update(struct work_struct *work) if (dev->nosignal) { dprintk("no video signal\n"); - ts_reset_encoder(dev); } else { dprintk("video signal acquired\n"); - if (atomic_read(&dev->empress_users)) - ts_init_encoder(dev); } } -- 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 a7015afafe5781e175338757b833679614e4c252 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 29 Apr 2009 06:55:31 +0000 Subject: Enabling of the Winfast TV2000 XP Global TV capture card remote control From: Pieter Van Schaik This patch is for supporting the remote control of the Winfast TV2000 XP Global TV capture card. A case statement was added in order to initialize the GPIO data structures as well as a case statement for handling the keys correctly when pressed. Thanks to Hermann and Mauro for all the help Signed-off-by: Pieter C van Schaik Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/cx88/cx88-input.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/cx88/cx88-input.c b/linux/drivers/media/video/cx88/cx88-input.c index facb2e800..dad809335 100644 --- a/linux/drivers/media/video/cx88/cx88-input.c +++ b/linux/drivers/media/video/cx88/cx88-input.c @@ -92,6 +92,7 @@ static void cx88_ir_handle_key(struct cx88_IR *ir) gpio=(gpio & 0x7fd) + (auxgpio & 0xef); break; case CX88_BOARD_WINFAST_DTV1000: + case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL: gpio = (gpio & 0x6ff) | ((cx_read(MO_GP1_IO) << 8) & 0x900); auxgpio = gpio; break; @@ -244,6 +245,7 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) break; case CX88_BOARD_WINFAST2000XP_EXPERT: case CX88_BOARD_WINFAST_DTV1000: + case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL: ir_codes = ir_codes_winfast; ir->gpio_addr = MO_GP0_IO; ir->mask_keycode = 0x8f8; -- cgit v1.2.3 From 244c2bb5a4cd825df18e2ce0ed52675943888af1 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 29 Apr 2009 18:57:24 +0000 Subject: 2: modify return value of VIDIOC_REQBUFS ioctl MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: Németh Márton The V4L2 ioctls usually return 0 when the operation was successful and -1 in case of error. Currently VIDIOC_REQBUFS returns the number of buffers which is redundant because this information is available in count field of struct v4l2_requestbuffers. The V4L2 API specification, revision 0.24 [1] explicitly specifies for VIDIOC_REQBUFS that the return value shall be 0 on success. The patch was tested with v4l-test 0.13 [2] with vivi driver. References: [1] V4L2 API specification, revision 0.24 http://v4l2spec.bytesex.org/spec/r13696.htm [2] v4l-test: Test environment for Video For Linux Two API http://v4l-test.sourceforge.net/ Signed-off-by: Márton Németh Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/videobuf-core.c | 1 + 1 file changed, 1 insertion(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/videobuf-core.c b/linux/drivers/media/video/videobuf-core.c index b104cd593..972f09836 100644 --- a/linux/drivers/media/video/videobuf-core.c +++ b/linux/drivers/media/video/videobuf-core.c @@ -440,6 +440,7 @@ int videobuf_reqbufs(struct videobuf_queue *q, } req->count = retval; + retval = 0; done: mutex_unlock(&q->vb_lock); -- cgit v1.2.3 From f9276b4928a4076ff0e5478e1e5687a77d95db7d Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 29 Apr 2009 16:34:27 -0300 Subject: backport commit ec5f5bf80501abfe2da2897cfcde8452b545aacb From: Mauro Carvalho Chehab kernel-sync: Author: Alan Cox Date: Wed Apr 22 15:03:15 2009 +0100 radio_si470x: Fix free memory corruption The release path for a disconnected device frees the object then unlocks the mutex in the freed object... Found by Dan Carpenter using Smatch Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/radio/radio-si470x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/radio/radio-si470x.c b/linux/drivers/media/radio/radio-si470x.c index b4d6641b4..f78a9cdea 100644 --- a/linux/drivers/media/radio/radio-si470x.c +++ b/linux/drivers/media/radio/radio-si470x.c @@ -1201,7 +1201,7 @@ static int si470x_fops_release(struct file *file) video_unregister_device(radio->videodev); kfree(radio->buffer); kfree(radio); - goto unlock; + goto done; } /* stop rds reception */ -- cgit v1.2.3 From bb4f5714918805dca1debaf31b897d4c4dda715a Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 29 Apr 2009 17:25:36 -0300 Subject: backport commit 6b35ca0d3d586b8ecb8396821af21186e20afaf0 From: Mauro Carvalho Chehab kernel-sync: Author: Martin Fuzzey Date: Tue Apr 21 21:48:09 2009 +0200 USB: pwc : do not pass stack allocated buffers to USB core. This is causes problems on platforms that have alignment requirements for DMA transfers. Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/pwc/pwc-ctrl.c | 238 +++++++++++++++++++++---------- 1 file changed, 164 insertions(+), 74 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/pwc/pwc-ctrl.c b/linux/drivers/media/video/pwc/pwc-ctrl.c index f9fbe02e0..50b415e07 100644 --- a/linux/drivers/media/video/pwc/pwc-ctrl.c +++ b/linux/drivers/media/video/pwc/pwc-ctrl.c @@ -159,35 +159,67 @@ static void pwc_set_image_buffer_size(struct pwc_device *pdev); /****************************************************************************/ +static int _send_control_msg(struct pwc_device *pdev, + u8 request, u16 value, int index, void *buf, int buflen, int timeout) +{ + int rc; + void *kbuf = NULL; + + if (buflen) { + kbuf = kmalloc(buflen, GFP_KERNEL); /* not allowed on stack */ + if (kbuf == NULL) + return -ENOMEM; + memcpy(kbuf, buf, buflen); + } -#define SendControlMsg(request, value, buflen) \ - usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0), \ - request, \ - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, \ - value, \ - pdev->vcinterface, \ - &buf, buflen, 500) + rc = usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0), + request, + USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, + value, + index, + kbuf, buflen, timeout); -#define RecvControlMsg(request, value, buflen) \ - usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0), \ - request, \ - USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, \ - value, \ - pdev->vcinterface, \ - &buf, buflen, 500) + kfree(kbuf); + return rc; +} +static int recv_control_msg(struct pwc_device *pdev, + u8 request, u16 value, void *buf, int buflen) +{ + int rc; + void *kbuf = kmalloc(buflen, GFP_KERNEL); /* not allowed on stack */ + + if (kbuf == NULL) + return -ENOMEM; + + rc = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0), + request, + USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, + value, + pdev->vcinterface, + kbuf, buflen, 500); + memcpy(buf, kbuf, buflen); + kfree(kbuf); + return rc; +} -static int send_video_command(struct usb_device *udev, int index, void *buf, int buflen) +static inline int send_video_command(struct pwc_device *pdev, + int index, void *buf, int buflen) { - return usb_control_msg(udev, - usb_sndctrlpipe(udev, 0), + return _send_control_msg(pdev, SET_EP_STREAM_CTL, - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, VIDEO_OUTPUT_CONTROL_FORMATTER, index, buf, buflen, 1000); } +static inline int send_control_msg(struct pwc_device *pdev, + u8 request, u16 value, void *buf, int buflen) +{ + return _send_control_msg(pdev, + request, value, pdev->vcinterface, buf, buflen, 500); +} + static int set_video_mode_Nala(struct pwc_device *pdev, int size, int frames) @@ -224,7 +256,7 @@ static int set_video_mode_Nala(struct pwc_device *pdev, int size, int frames) return -EINVAL; memcpy(buf, pEntry->mode, 3); - ret = send_video_command(pdev->udev, pdev->vendpoint, buf, 3); + ret = send_video_command(pdev, pdev->vendpoint, buf, 3); if (ret < 0) { PWC_DEBUG_MODULE("Failed to send video command... %d\n", ret); return ret; @@ -285,7 +317,7 @@ static int set_video_mode_Timon(struct pwc_device *pdev, int size, int frames, i memcpy(buf, pChoose->mode, 13); if (snapshot) buf[0] |= 0x80; - ret = send_video_command(pdev->udev, pdev->vendpoint, buf, 13); + ret = send_video_command(pdev, pdev->vendpoint, buf, 13); if (ret < 0) return ret; @@ -358,7 +390,7 @@ static int set_video_mode_Kiara(struct pwc_device *pdev, int size, int frames, i buf[0] |= 0x80; /* Firmware bug: video endpoint is 5, but commands are sent to endpoint 4 */ - ret = send_video_command(pdev->udev, 4 /* pdev->vendpoint */, buf, 12); + ret = send_video_command(pdev, 4 /* pdev->vendpoint */, buf, 12); if (ret < 0) return ret; @@ -530,7 +562,8 @@ int pwc_get_brightness(struct pwc_device *pdev) char buf; int ret; - ret = RecvControlMsg(GET_LUM_CTL, BRIGHTNESS_FORMATTER, 1); + ret = recv_control_msg(pdev, + GET_LUM_CTL, BRIGHTNESS_FORMATTER, &buf, sizeof(buf)); if (ret < 0) return ret; return buf; @@ -545,7 +578,8 @@ int pwc_set_brightness(struct pwc_device *pdev, int value) if (value > 0xffff) value = 0xffff; buf = (value >> 9) & 0x7f; - return SendControlMsg(SET_LUM_CTL, BRIGHTNESS_FORMATTER, 1); + return send_control_msg(pdev, + SET_LUM_CTL, BRIGHTNESS_FORMATTER, &buf, sizeof(buf)); } /* CONTRAST */ @@ -555,7 +589,8 @@ int pwc_get_contrast(struct pwc_device *pdev) char buf; int ret; - ret = RecvControlMsg(GET_LUM_CTL, CONTRAST_FORMATTER, 1); + ret = recv_control_msg(pdev, + GET_LUM_CTL, CONTRAST_FORMATTER, &buf, sizeof(buf)); if (ret < 0) return ret; return buf; @@ -570,7 +605,8 @@ int pwc_set_contrast(struct pwc_device *pdev, int value) if (value > 0xffff) value = 0xffff; buf = (value >> 10) & 0x3f; - return SendControlMsg(SET_LUM_CTL, CONTRAST_FORMATTER, 1); + return send_control_msg(pdev, + SET_LUM_CTL, CONTRAST_FORMATTER, &buf, sizeof(buf)); } /* GAMMA */ @@ -580,7 +616,8 @@ int pwc_get_gamma(struct pwc_device *pdev) char buf; int ret; - ret = RecvControlMsg(GET_LUM_CTL, GAMMA_FORMATTER, 1); + ret = recv_control_msg(pdev, + GET_LUM_CTL, GAMMA_FORMATTER, &buf, sizeof(buf)); if (ret < 0) return ret; return buf; @@ -595,7 +632,8 @@ int pwc_set_gamma(struct pwc_device *pdev, int value) if (value > 0xffff) value = 0xffff; buf = (value >> 11) & 0x1f; - return SendControlMsg(SET_LUM_CTL, GAMMA_FORMATTER, 1); + return send_control_msg(pdev, + SET_LUM_CTL, GAMMA_FORMATTER, &buf, sizeof(buf)); } @@ -613,7 +651,8 @@ int pwc_get_saturation(struct pwc_device *pdev, int *value) saturation_register = SATURATION_MODE_FORMATTER2; else saturation_register = SATURATION_MODE_FORMATTER1; - ret = RecvControlMsg(GET_CHROM_CTL, saturation_register, 1); + ret = recv_control_msg(pdev, + GET_CHROM_CTL, saturation_register, &buf, sizeof(buf)); if (ret < 0) return ret; *value = (signed)buf; @@ -636,7 +675,8 @@ int pwc_set_saturation(struct pwc_device *pdev, int value) saturation_register = SATURATION_MODE_FORMATTER2; else saturation_register = SATURATION_MODE_FORMATTER1; - return SendControlMsg(SET_CHROM_CTL, saturation_register, 1); + return send_control_msg(pdev, + SET_CHROM_CTL, saturation_register, &buf, sizeof(buf)); } /* AGC */ @@ -651,7 +691,8 @@ int pwc_set_agc(struct pwc_device *pdev, int mode, int value) else buf = 0xff; /* fixed */ - ret = SendControlMsg(SET_LUM_CTL, AGC_MODE_FORMATTER, 1); + ret = send_control_msg(pdev, + SET_LUM_CTL, AGC_MODE_FORMATTER, &buf, sizeof(buf)); if (!mode && ret >= 0) { if (value < 0) @@ -659,7 +700,8 @@ int pwc_set_agc(struct pwc_device *pdev, int mode, int value) if (value > 0xffff) value = 0xffff; buf = (value >> 10) & 0x3F; - ret = SendControlMsg(SET_LUM_CTL, PRESET_AGC_FORMATTER, 1); + ret = send_control_msg(pdev, + SET_LUM_CTL, PRESET_AGC_FORMATTER, &buf, sizeof(buf)); } if (ret < 0) return ret; @@ -671,12 +713,14 @@ int pwc_get_agc(struct pwc_device *pdev, int *value) unsigned char buf; int ret; - ret = RecvControlMsg(GET_LUM_CTL, AGC_MODE_FORMATTER, 1); + ret = recv_control_msg(pdev, + GET_LUM_CTL, AGC_MODE_FORMATTER, &buf, sizeof(buf)); if (ret < 0) return ret; if (buf != 0) { /* fixed */ - ret = RecvControlMsg(GET_LUM_CTL, PRESET_AGC_FORMATTER, 1); + ret = recv_control_msg(pdev, + GET_LUM_CTL, PRESET_AGC_FORMATTER, &buf, sizeof(buf)); if (ret < 0) return ret; if (buf > 0x3F) @@ -684,7 +728,8 @@ int pwc_get_agc(struct pwc_device *pdev, int *value) *value = (buf << 10); } else { /* auto */ - ret = RecvControlMsg(GET_STATUS_CTL, READ_AGC_FORMATTER, 1); + ret = recv_control_msg(pdev, + GET_STATUS_CTL, READ_AGC_FORMATTER, &buf, sizeof(buf)); if (ret < 0) return ret; /* Gah... this value ranges from 0x00 ... 0x9F */ @@ -707,7 +752,8 @@ int pwc_set_shutter_speed(struct pwc_device *pdev, int mode, int value) else buf[0] = 0xff; /* fixed */ - ret = SendControlMsg(SET_LUM_CTL, SHUTTER_MODE_FORMATTER, 1); + ret = send_control_msg(pdev, + SET_LUM_CTL, SHUTTER_MODE_FORMATTER, &buf, sizeof(buf)); if (!mode && ret >= 0) { if (value < 0) @@ -726,7 +772,9 @@ int pwc_set_shutter_speed(struct pwc_device *pdev, int mode, int value) buf[0] = value >> 8; } - ret = SendControlMsg(SET_LUM_CTL, PRESET_SHUTTER_FORMATTER, 2); + ret = send_control_msg(pdev, + SET_LUM_CTL, PRESET_SHUTTER_FORMATTER, + &buf, sizeof(buf)); } return ret; } @@ -737,7 +785,8 @@ int pwc_get_shutter_speed(struct pwc_device *pdev, int *value) unsigned char buf[2]; int ret; - ret = RecvControlMsg(GET_STATUS_CTL, READ_SHUTTER_FORMATTER, 2); + ret = recv_control_msg(pdev, + GET_STATUS_CTL, READ_SHUTTER_FORMATTER, &buf, sizeof(buf)); if (ret < 0) return ret; *value = buf[0] + (buf[1] << 8); @@ -764,7 +813,9 @@ int pwc_camera_power(struct pwc_device *pdev, int power) buf = 0x00; /* active */ else buf = 0xFF; /* power save */ - return SendControlMsg(SET_STATUS_CTL, SET_POWER_SAVE_MODE_FORMATTER, 1); + return send_control_msg(pdev, + SET_STATUS_CTL, SET_POWER_SAVE_MODE_FORMATTER, + &buf, sizeof(buf)); } @@ -773,20 +824,20 @@ int pwc_camera_power(struct pwc_device *pdev, int power) int pwc_restore_user(struct pwc_device *pdev) { - char buf; /* dummy */ - return SendControlMsg(SET_STATUS_CTL, RESTORE_USER_DEFAULTS_FORMATTER, 0); + return send_control_msg(pdev, + SET_STATUS_CTL, RESTORE_USER_DEFAULTS_FORMATTER, NULL, 0); } int pwc_save_user(struct pwc_device *pdev) { - char buf; /* dummy */ - return SendControlMsg(SET_STATUS_CTL, SAVE_USER_DEFAULTS_FORMATTER, 0); + return send_control_msg(pdev, + SET_STATUS_CTL, SAVE_USER_DEFAULTS_FORMATTER, NULL, 0); } int pwc_restore_factory(struct pwc_device *pdev) { - char buf; /* dummy */ - return SendControlMsg(SET_STATUS_CTL, RESTORE_FACTORY_DEFAULTS_FORMATTER, 0); + return send_control_msg(pdev, + SET_STATUS_CTL, RESTORE_FACTORY_DEFAULTS_FORMATTER, NULL, 0); } /* ************************************************* */ @@ -814,7 +865,8 @@ int pwc_set_awb(struct pwc_device *pdev, int mode) buf = mode & 0x07; /* just the lowest three bits */ - ret = SendControlMsg(SET_CHROM_CTL, WB_MODE_FORMATTER, 1); + ret = send_control_msg(pdev, + SET_CHROM_CTL, WB_MODE_FORMATTER, &buf, sizeof(buf)); if (ret < 0) return ret; @@ -826,7 +878,8 @@ int pwc_get_awb(struct pwc_device *pdev) unsigned char buf; int ret; - ret = RecvControlMsg(GET_CHROM_CTL, WB_MODE_FORMATTER, 1); + ret = recv_control_msg(pdev, + GET_CHROM_CTL, WB_MODE_FORMATTER, &buf, sizeof(buf)); if (ret < 0) return ret; @@ -843,7 +896,9 @@ int pwc_set_red_gain(struct pwc_device *pdev, int value) value = 0xffff; /* only the msb is considered */ buf = value >> 8; - return SendControlMsg(SET_CHROM_CTL, PRESET_MANUAL_RED_GAIN_FORMATTER, 1); + return send_control_msg(pdev, + SET_CHROM_CTL, PRESET_MANUAL_RED_GAIN_FORMATTER, + &buf, sizeof(buf)); } int pwc_get_red_gain(struct pwc_device *pdev, int *value) @@ -851,7 +906,9 @@ int pwc_get_red_gain(struct pwc_device *pdev, int *value) unsigned char buf; int ret; - ret = RecvControlMsg(GET_CHROM_CTL, PRESET_MANUAL_RED_GAIN_FORMATTER, 1); + ret = recv_control_msg(pdev, + GET_CHROM_CTL, PRESET_MANUAL_RED_GAIN_FORMATTER, + &buf, sizeof(buf)); if (ret < 0) return ret; *value = buf << 8; @@ -869,7 +926,9 @@ int pwc_set_blue_gain(struct pwc_device *pdev, int value) value = 0xffff; /* only the msb is considered */ buf = value >> 8; - return SendControlMsg(SET_CHROM_CTL, PRESET_MANUAL_BLUE_GAIN_FORMATTER, 1); + return send_control_msg(pdev, + SET_CHROM_CTL, PRESET_MANUAL_BLUE_GAIN_FORMATTER, + &buf, sizeof(buf)); } int pwc_get_blue_gain(struct pwc_device *pdev, int *value) @@ -877,7 +936,9 @@ int pwc_get_blue_gain(struct pwc_device *pdev, int *value) unsigned char buf; int ret; - ret = RecvControlMsg(GET_CHROM_CTL, PRESET_MANUAL_BLUE_GAIN_FORMATTER, 1); + ret = recv_control_msg(pdev, + GET_CHROM_CTL, PRESET_MANUAL_BLUE_GAIN_FORMATTER, + &buf, sizeof(buf)); if (ret < 0) return ret; *value = buf << 8; @@ -894,7 +955,8 @@ static int pwc_read_red_gain(struct pwc_device *pdev, int *value) unsigned char buf; int ret; - ret = RecvControlMsg(GET_STATUS_CTL, READ_RED_GAIN_FORMATTER, 1); + ret = recv_control_msg(pdev, + GET_STATUS_CTL, READ_RED_GAIN_FORMATTER, &buf, sizeof(buf)); if (ret < 0) return ret; *value = buf << 8; @@ -906,7 +968,8 @@ static int pwc_read_blue_gain(struct pwc_device *pdev, int *value) unsigned char buf; int ret; - ret = RecvControlMsg(GET_STATUS_CTL, READ_BLUE_GAIN_FORMATTER, 1); + ret = recv_control_msg(pdev, + GET_STATUS_CTL, READ_BLUE_GAIN_FORMATTER, &buf, sizeof(buf)); if (ret < 0) return ret; *value = buf << 8; @@ -920,7 +983,8 @@ static int pwc_set_wb_speed(struct pwc_device *pdev, int speed) /* useful range is 0x01..0x20 */ buf = speed / 0x7f0; - return SendControlMsg(SET_CHROM_CTL, AWB_CONTROL_SPEED_FORMATTER, 1); + return send_control_msg(pdev, + SET_CHROM_CTL, AWB_CONTROL_SPEED_FORMATTER, &buf, sizeof(buf)); } static int pwc_get_wb_speed(struct pwc_device *pdev, int *value) @@ -928,7 +992,8 @@ static int pwc_get_wb_speed(struct pwc_device *pdev, int *value) unsigned char buf; int ret; - ret = RecvControlMsg(GET_CHROM_CTL, AWB_CONTROL_SPEED_FORMATTER, 1); + ret = recv_control_msg(pdev, + GET_CHROM_CTL, AWB_CONTROL_SPEED_FORMATTER, &buf, sizeof(buf)); if (ret < 0) return ret; *value = buf * 0x7f0; @@ -942,7 +1007,8 @@ static int pwc_set_wb_delay(struct pwc_device *pdev, int delay) /* useful range is 0x01..0x3F */ buf = (delay >> 10); - return SendControlMsg(SET_CHROM_CTL, AWB_CONTROL_DELAY_FORMATTER, 1); + return send_control_msg(pdev, + SET_CHROM_CTL, AWB_CONTROL_DELAY_FORMATTER, &buf, sizeof(buf)); } static int pwc_get_wb_delay(struct pwc_device *pdev, int *value) @@ -950,7 +1016,8 @@ static int pwc_get_wb_delay(struct pwc_device *pdev, int *value) unsigned char buf; int ret; - ret = RecvControlMsg(GET_CHROM_CTL, AWB_CONTROL_DELAY_FORMATTER, 1); + ret = recv_control_msg(pdev, + GET_CHROM_CTL, AWB_CONTROL_DELAY_FORMATTER, &buf, sizeof(buf)); if (ret < 0) return ret; *value = buf << 10; @@ -978,7 +1045,8 @@ int pwc_set_leds(struct pwc_device *pdev, int on_value, int off_value) buf[0] = on_value; buf[1] = off_value; - return SendControlMsg(SET_STATUS_CTL, LED_FORMATTER, 2); + return send_control_msg(pdev, + SET_STATUS_CTL, LED_FORMATTER, &buf, sizeof(buf)); } static int pwc_get_leds(struct pwc_device *pdev, int *on_value, int *off_value) @@ -992,7 +1060,8 @@ static int pwc_get_leds(struct pwc_device *pdev, int *on_value, int *off_value) return 0; } - ret = RecvControlMsg(GET_STATUS_CTL, LED_FORMATTER, 2); + ret = recv_control_msg(pdev, + GET_STATUS_CTL, LED_FORMATTER, &buf, sizeof(buf)); if (ret < 0) return ret; *on_value = buf[0] * 100; @@ -1009,7 +1078,8 @@ int pwc_set_contour(struct pwc_device *pdev, int contour) buf = 0xff; /* auto contour on */ else buf = 0x0; /* auto contour off */ - ret = SendControlMsg(SET_LUM_CTL, AUTO_CONTOUR_FORMATTER, 1); + ret = send_control_msg(pdev, + SET_LUM_CTL, AUTO_CONTOUR_FORMATTER, &buf, sizeof(buf)); if (ret < 0) return ret; @@ -1019,7 +1089,8 @@ int pwc_set_contour(struct pwc_device *pdev, int contour) contour = 0xffff; buf = (contour >> 10); /* contour preset is [0..3f] */ - ret = SendControlMsg(SET_LUM_CTL, PRESET_CONTOUR_FORMATTER, 1); + ret = send_control_msg(pdev, + SET_LUM_CTL, PRESET_CONTOUR_FORMATTER, &buf, sizeof(buf)); if (ret < 0) return ret; return 0; @@ -1030,13 +1101,16 @@ int pwc_get_contour(struct pwc_device *pdev, int *contour) unsigned char buf; int ret; - ret = RecvControlMsg(GET_LUM_CTL, AUTO_CONTOUR_FORMATTER, 1); + ret = recv_control_msg(pdev, + GET_LUM_CTL, AUTO_CONTOUR_FORMATTER, &buf, sizeof(buf)); if (ret < 0) return ret; if (buf == 0) { /* auto mode off, query current preset value */ - ret = RecvControlMsg(GET_LUM_CTL, PRESET_CONTOUR_FORMATTER, 1); + ret = recv_control_msg(pdev, + GET_LUM_CTL, PRESET_CONTOUR_FORMATTER, + &buf, sizeof(buf)); if (ret < 0) return ret; *contour = buf << 10; @@ -1055,7 +1129,9 @@ int pwc_set_backlight(struct pwc_device *pdev, int backlight) buf = 0xff; else buf = 0x0; - return SendControlMsg(SET_LUM_CTL, BACK_LIGHT_COMPENSATION_FORMATTER, 1); + return send_control_msg(pdev, + SET_LUM_CTL, BACK_LIGHT_COMPENSATION_FORMATTER, + &buf, sizeof(buf)); } int pwc_get_backlight(struct pwc_device *pdev, int *backlight) @@ -1063,7 +1139,9 @@ int pwc_get_backlight(struct pwc_device *pdev, int *backlight) int ret; unsigned char buf; - ret = RecvControlMsg(GET_LUM_CTL, BACK_LIGHT_COMPENSATION_FORMATTER, 1); + ret = recv_control_msg(pdev, + GET_LUM_CTL, BACK_LIGHT_COMPENSATION_FORMATTER, + &buf, sizeof(buf)); if (ret < 0) return ret; *backlight = !!buf; @@ -1078,7 +1156,8 @@ int pwc_set_colour_mode(struct pwc_device *pdev, int colour) buf = 0xff; else buf = 0x0; - return SendControlMsg(SET_CHROM_CTL, COLOUR_MODE_FORMATTER, 1); + return send_control_msg(pdev, + SET_CHROM_CTL, COLOUR_MODE_FORMATTER, &buf, sizeof(buf)); } int pwc_get_colour_mode(struct pwc_device *pdev, int *colour) @@ -1086,7 +1165,8 @@ int pwc_get_colour_mode(struct pwc_device *pdev, int *colour) int ret; unsigned char buf; - ret = RecvControlMsg(GET_CHROM_CTL, COLOUR_MODE_FORMATTER, 1); + ret = recv_control_msg(pdev, + GET_CHROM_CTL, COLOUR_MODE_FORMATTER, &buf, sizeof(buf)); if (ret < 0) return ret; *colour = !!buf; @@ -1102,7 +1182,8 @@ int pwc_set_flicker(struct pwc_device *pdev, int flicker) buf = 0xff; else buf = 0x0; - return SendControlMsg(SET_LUM_CTL, FLICKERLESS_MODE_FORMATTER, 1); + return send_control_msg(pdev, + SET_LUM_CTL, FLICKERLESS_MODE_FORMATTER, &buf, sizeof(buf)); } int pwc_get_flicker(struct pwc_device *pdev, int *flicker) @@ -1110,7 +1191,8 @@ int pwc_get_flicker(struct pwc_device *pdev, int *flicker) int ret; unsigned char buf; - ret = RecvControlMsg(GET_LUM_CTL, FLICKERLESS_MODE_FORMATTER, 1); + ret = recv_control_msg(pdev, + GET_LUM_CTL, FLICKERLESS_MODE_FORMATTER, &buf, sizeof(buf)); if (ret < 0) return ret; *flicker = !!buf; @@ -1126,7 +1208,9 @@ int pwc_set_dynamic_noise(struct pwc_device *pdev, int noise) if (noise > 3) noise = 3; buf = noise; - return SendControlMsg(SET_LUM_CTL, DYNAMIC_NOISE_CONTROL_FORMATTER, 1); + return send_control_msg(pdev, + SET_LUM_CTL, DYNAMIC_NOISE_CONTROL_FORMATTER, + &buf, sizeof(buf)); } int pwc_get_dynamic_noise(struct pwc_device *pdev, int *noise) @@ -1134,7 +1218,9 @@ int pwc_get_dynamic_noise(struct pwc_device *pdev, int *noise) int ret; unsigned char buf; - ret = RecvControlMsg(GET_LUM_CTL, DYNAMIC_NOISE_CONTROL_FORMATTER, 1); + ret = recv_control_msg(pdev, + GET_LUM_CTL, DYNAMIC_NOISE_CONTROL_FORMATTER, + &buf, sizeof(buf)); if (ret < 0) return ret; *noise = buf; @@ -1146,7 +1232,8 @@ static int _pwc_mpt_reset(struct pwc_device *pdev, int flags) unsigned char buf; buf = flags & 0x03; // only lower two bits are currently used - return SendControlMsg(SET_MPT_CTL, PT_RESET_CONTROL_FORMATTER, 1); + return send_control_msg(pdev, + SET_MPT_CTL, PT_RESET_CONTROL_FORMATTER, &buf, sizeof(buf)); } int pwc_mpt_reset(struct pwc_device *pdev, int flags) @@ -1175,7 +1262,8 @@ static int _pwc_mpt_set_angle(struct pwc_device *pdev, int pan, int tilt) buf[1] = (pan >> 8) & 0xFF; buf[2] = tilt & 0xFF; buf[3] = (tilt >> 8) & 0xFF; - return SendControlMsg(SET_MPT_CTL, PT_RELATIVE_CONTROL_FORMATTER, 4); + return send_control_msg(pdev, + SET_MPT_CTL, PT_RELATIVE_CONTROL_FORMATTER, &buf, sizeof(buf)); } int pwc_mpt_set_angle(struct pwc_device *pdev, int pan, int tilt) @@ -1211,7 +1299,8 @@ static int pwc_mpt_get_status(struct pwc_device *pdev, struct pwc_mpt_status *st int ret; unsigned char buf[5]; - ret = RecvControlMsg(GET_MPT_CTL, PT_STATUS_FORMATTER, 5); + ret = recv_control_msg(pdev, + GET_MPT_CTL, PT_STATUS_FORMATTER, &buf, sizeof(buf)); if (ret < 0) return ret; status->status = buf[0] & 0x7; // 3 bits are used for reporting @@ -1233,7 +1322,8 @@ int pwc_get_cmos_sensor(struct pwc_device *pdev, int *sensor) else request = SENSOR_TYPE_FORMATTER2; - ret = RecvControlMsg(GET_STATUS_CTL, request, 1); + ret = recv_control_msg(pdev, + GET_STATUS_CTL, request, &buf, sizeof(buf)); if (ret < 0) return ret; if (pdev->type < 675) -- cgit v1.2.3 From 072a6b98300f11462d16d85cbf83239a6957cd91 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 29 Apr 2009 18:01:48 -0300 Subject: backport commit 3444b26afa145148951112534f298bdc554ec789 From: Mauro Carvalho Chehab kernel-sync: Author: David Vrabel Date: Wed Apr 8 17:36:28 2009 +0000 USB: add reset endpoint operations Wireless USB endpoint state has a sequence number and a current window and not just a single toggle bit. So allow HCDs to provide a endpoint_reset method and call this or clear the software toggles as required (after a clear halt, set configuration etc.). usb_settoggle() and friends are then HCD internal and are moved into core/hcd.h and all device drivers call usb_reset_endpoint() instead. If the device endpoint state has been reset (with a clear halt) but the host endpoint state has not then subsequent data transfers will not complete. The device will only work again after it is reset or disconnected. CC: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c | 1 - 1 file changed, 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c index f3d9db69e..c0e1e2cc9 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -1471,7 +1471,6 @@ static int pvr2_upload_firmware1(struct pvr2_hdw *hdw) return ret; } - usb_settoggle(hdw->usb_dev, 0 & 0xf, !(0 & USB_DIR_IN), 0); usb_clear_halt(hdw->usb_dev, usb_sndbulkpipe(hdw->usb_dev, 0 & 0x7f)); pipe = usb_sndctrlpipe(hdw->usb_dev, 0); -- cgit v1.2.3 From 792254c7ef1bcee499b53704869d84cc8c2b280d Mon Sep 17 00:00:00 2001 From: Steven Toth Date: Wed, 29 Apr 2009 19:49:12 -0400 Subject: cx23885: Don't assume GPIO interrupts are cam related. From: Steven Toth cx23885: Don't assume GPIO interrupts are cam related. Priority: normal Signed-off-by: Steven Toth --- linux/drivers/media/video/cx23885/cx23885-core.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/cx23885/cx23885-core.c b/linux/drivers/media/video/cx23885/cx23885-core.c index 81fa577a6..48f777b99 100644 --- a/linux/drivers/media/video/cx23885/cx23885-core.c +++ b/linux/drivers/media/video/cx23885/cx23885-core.c @@ -1711,9 +1711,13 @@ static irqreturn_t cx23885_irq(int irq, void *dev_id) } if (cx23885_boards[dev->board].cimax > 0 && - ((pci_status & PCI_MSK_GPIO0) || (pci_status & PCI_MSK_GPIO1))) - /* handled += cx23885_irq_gpio(dev, pci_status); */ - handled += netup_ci_slot_status(dev, pci_status); + ((pci_status & PCI_MSK_GPIO0) || + (pci_status & PCI_MSK_GPIO1))) { + + if (cx23885_boards[dev->board].cimax > 0) + handled += netup_ci_slot_status(dev, pci_status); + + } if (ts1_status) { if (cx23885_boards[dev->board].portb == CX23885_MPEG_DVB) -- cgit v1.2.3 From c43f103d41c7e4f9c6763b53c83327d6c2a49253 Mon Sep 17 00:00:00 2001 From: Oliver Endriss Date: Thu, 30 Apr 2009 04:09:44 +0200 Subject: dvb-ttpci: Fixed return code of av7110_av_start_play From: Oliver Endriss av7110_av_start_play() should return 0 on success. Priority: normal Signed-off-by: Oliver Endriss --- linux/drivers/media/dvb/ttpci/av7110_av.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/ttpci/av7110_av.c b/linux/drivers/media/dvb/ttpci/av7110_av.c index 7b93ab9dc..a5ad9b0be 100644 --- a/linux/drivers/media/dvb/ttpci/av7110_av.c +++ b/linux/drivers/media/dvb/ttpci/av7110_av.c @@ -193,8 +193,6 @@ int av7110_av_start_play(struct av7110 *av7110, int av) ret = av7110_fw_cmd(av7110, COMTYPE_REC_PLAY, __Play, 2, AV_PES, 0); break; } - if (!ret) - ret = av7110->playing; return ret; } -- cgit v1.2.3 From 3d88b8ea62d861b60775b3b1437124a9809be4a8 Mon Sep 17 00:00:00 2001 From: Oliver Endriss Date: Thu, 30 Apr 2009 04:25:07 +0200 Subject: dvb-ttpci: Some whitespace adjustments From: Oliver Endriss Some whitespace adjustments. Priority: normal Signed-off-by: Oliver Endriss --- linux/drivers/media/dvb/ttpci/av7110_av.c | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/ttpci/av7110_av.c b/linux/drivers/media/dvb/ttpci/av7110_av.c index a5ad9b0be..538848141 100644 --- a/linux/drivers/media/dvb/ttpci/av7110_av.c +++ b/linux/drivers/media/dvb/ttpci/av7110_av.c @@ -1126,7 +1126,6 @@ static int dvb_video_ioctl(struct inode *inode, struct file *file, if (ret) break; } - if (av7110->videostate.stream_source == VIDEO_SOURCE_MEMORY) { if (av7110->playing == RP_AV) { ret = av7110_fw_cmd(av7110, COMTYPE_REC_PLAY, __Stop, 0); @@ -1186,20 +1185,16 @@ static int dvb_video_ioctl(struct inode *inode, struct file *file, case VIDEO_SET_DISPLAY_FORMAT: { video_displayformat_t format = (video_displayformat_t) arg; - switch (format) { case VIDEO_PAN_SCAN: av7110->display_panscan = VID_PAN_SCAN_PREF; break; - case VIDEO_LETTER_BOX: av7110->display_panscan = VID_VC_AND_PS_PREF; break; - case VIDEO_CENTER_CUT_OUT: av7110->display_panscan = VID_CENTRE_CUT_PREF; break; - default: ret = -EINVAL; } @@ -1272,7 +1267,6 @@ static int dvb_video_ioctl(struct inode *inode, struct file *file, case VIDEO_CLEAR_BUFFER: dvb_ringbuffer_flush_spinlock_wakeup(&av7110->avout); av7110_ipack_reset(&av7110->ipack[1]); - if (av7110->playing == RP_AV) { ret = av7110_fw_cmd(av7110, COMTYPE_REC_PLAY, __Play, 2, AV_PES, 0); @@ -1293,13 +1287,13 @@ static int dvb_video_ioctl(struct inode *inode, struct file *file, break; case VIDEO_SET_STREAMTYPE: - break; default: ret = -ENOIOCTLCMD; break; } + return ret; } @@ -1374,7 +1368,6 @@ static int dvb_audio_ioctl(struct inode *inode, struct file *file, case AUDIO_CHANNEL_SELECT: av7110->audiostate.channel_select = (audio_channel_select_t) arg; - switch(av7110->audiostate.channel_select) { case AUDIO_STEREO: ret = audcom(av7110, AUDIO_CMD_STEREO); @@ -1385,7 +1378,6 @@ static int dvb_audio_ioctl(struct inode *inode, struct file *file, msp_writereg(av7110, MSP_WR_DSP, 0x0008, 0x0220); } break; - case AUDIO_MONO_LEFT: ret = audcom(av7110, AUDIO_CMD_MONO_L); if (!ret) { @@ -1395,7 +1387,6 @@ static int dvb_audio_ioctl(struct inode *inode, struct file *file, msp_writereg(av7110, MSP_WR_DSP, 0x0008, 0x0200); } break; - case AUDIO_MONO_RIGHT: ret = audcom(av7110, AUDIO_CMD_MONO_R); if (!ret) { @@ -1405,7 +1396,6 @@ static int dvb_audio_ioctl(struct inode *inode, struct file *file, msp_writereg(av7110, MSP_WR_DSP, 0x0008, 0x0210); } break; - default: ret = -EINVAL; break; @@ -1431,21 +1421,24 @@ static int dvb_audio_ioctl(struct inode *inode, struct file *file, ret = av7110_fw_cmd(av7110, COMTYPE_REC_PLAY, __Play, 2, AV_PES, 0); break; - case AUDIO_SET_ID: + case AUDIO_SET_ID: break; + case AUDIO_SET_MIXER: { struct audio_mixer *amix = (struct audio_mixer *)parg; - ret = av7110_set_volume(av7110, amix->volume_left, amix->volume_right); break; } + case AUDIO_SET_STREAMTYPE: break; + default: ret = -ENOIOCTLCMD; } + return ret; } -- cgit v1.2.3 From a2d7371dbe37dfa05b77b635e401e96be28796a2 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 30 Apr 2009 08:40:07 +0000 Subject: Drop stray references to i2c_probe From: Jean Delvare The new i2c binding model doesn't use i2c_probe. Signed-off-by: Jean Delvare Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/tea6415c.c | 1 - linux/drivers/media/video/tea6420.c | 1 - 2 files changed, 2 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/tea6415c.c b/linux/drivers/media/video/tea6415c.c index de866798b..910e156f4 100644 --- a/linux/drivers/media/video/tea6415c.c +++ b/linux/drivers/media/video/tea6415c.c @@ -147,7 +147,6 @@ static const struct v4l2_subdev_ops tea6415c_ops = { .video = &tea6415c_video_ops, }; -/* this function is called by i2c_probe */ static int tea6415c_probe(struct i2c_client *client, const struct i2c_device_id *id) { diff --git a/linux/drivers/media/video/tea6420.c b/linux/drivers/media/video/tea6420.c index 90054dfbe..0e7bb8d6a 100644 --- a/linux/drivers/media/video/tea6420.c +++ b/linux/drivers/media/video/tea6420.c @@ -118,7 +118,6 @@ static const struct v4l2_subdev_ops tea6420_ops = { .audio = &tea6420_audio_ops, }; -/* this function is called by i2c_probe */ static int tea6420_probe(struct i2c_client *client, const struct i2c_device_id *id) { -- cgit v1.2.3 From 761fb9dc928dfb9fa78fe3ed6e9269c1fdcbc9b1 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 30 Apr 2009 15:29:38 +0000 Subject: patch: s2255drv: urb completion routine fixes From: Dean Anderson Error count in read pipe completion corrected. URB not resubmitted if shutting down. URB not freed in completion routine if new urb_submit_fails. (URB is freed on shutdown). Priority: high Signed-off-by: Dean Anderson Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/s2255drv.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/s2255drv.c b/linux/drivers/media/video/s2255drv.c index 12ced841e..8a939387a 100644 --- a/linux/drivers/media/video/s2255drv.c +++ b/linux/drivers/media/video/s2255drv.c @@ -2240,8 +2240,10 @@ static void read_pipe_completion(struct urb *purb) return; } status = purb->status; - if (status != 0) { - dprintk(2, "read_pipe_completion: err\n"); + /* if shutting down, do not resubmit, exit immediately */ + if (status == -ESHUTDOWN) { + dprintk(2, "read_pipe_completion: err shutdown\n"); + pipe_info->err_count++; return; } @@ -2250,9 +2252,13 @@ static void read_pipe_completion(struct urb *purb) return; } - s2255_read_video_callback(dev, pipe_info); + if (status == 0) + s2255_read_video_callback(dev, pipe_info); + else { + pipe_info->err_count++; + dprintk(1, "s2255drv: failed URB %d\n", status); + } - pipe_info->err_count = 0; pipe = usb_rcvbulkpipe(dev->udev, dev->read_endpoint); /* reuse urb */ usb_fill_bulk_urb(pipe_info->stream_urb, dev->udev, @@ -2264,7 +2270,6 @@ static void read_pipe_completion(struct urb *purb) if (pipe_info->state != 0) { if (usb_submit_urb(pipe_info->stream_urb, GFP_KERNEL)) { dev_err(&dev->udev->dev, "error submitting urb\n"); - usb_free_urb(pipe_info->stream_urb); } } else { dprintk(2, "read pipe complete state 0\n"); -- cgit v1.2.3 From 0ea260891398ca8c39e7b6a524839125c0894ad9 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 30 Apr 2009 22:18:08 +0000 Subject: remove driver_data direct access of struct device From: Greg Kroah-Hartman In the near future, the driver core is going to not allow direct access to the driver_data pointer in struct device. Instead, the functions dev_get_drvdata() and dev_set_drvdata() should be used. These functions have been around since the beginning, so are backwards compatible with all older kernel versions. Signed-off-by: Greg Kroah-Hartman Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/firewire/firedtv-1394.c | 4 ++-- linux/drivers/media/dvb/firewire/firedtv-dvb.c | 2 +- linux/drivers/media/video/pvrusb2/pvrusb2-sysfs.c | 22 +++++++++++----------- 3 files changed, 14 insertions(+), 14 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/firewire/firedtv-1394.c b/linux/drivers/media/dvb/firewire/firedtv-1394.c index 4e207658c..2b6eeeab5 100644 --- a/linux/drivers/media/dvb/firewire/firedtv-1394.c +++ b/linux/drivers/media/dvb/firewire/firedtv-1394.c @@ -225,7 +225,7 @@ fail_free: static int node_remove(struct device *dev) { - struct firedtv *fdtv = dev->driver_data; + struct firedtv *fdtv = dev_get_drvdata(dev); fdtv_dvb_unregister(fdtv); @@ -242,7 +242,7 @@ static int node_remove(struct device *dev) static int node_update(struct unit_directory *ud) { - struct firedtv *fdtv = ud->device.driver_data; + struct firedtv *fdtv = dev_get_drvdata(&ud->device); if (fdtv->isochannel >= 0) cmp_establish_pp_connection(fdtv, fdtv->subunit, diff --git a/linux/drivers/media/dvb/firewire/firedtv-dvb.c b/linux/drivers/media/dvb/firewire/firedtv-dvb.c index 9d308dd32..5742fde79 100644 --- a/linux/drivers/media/dvb/firewire/firedtv-dvb.c +++ b/linux/drivers/media/dvb/firewire/firedtv-dvb.c @@ -268,7 +268,7 @@ struct firedtv *fdtv_alloc(struct device *dev, if (!fdtv) return NULL; - dev->driver_data = fdtv; + dev_set_drvdata(dev, fdtv); fdtv->device = dev; fdtv->isochannel = -1; fdtv->voltage = 0xff; diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-sysfs.c b/linux/drivers/media/video/pvrusb2/pvrusb2-sysfs.c index 7ed3b8453..d8ad83df3 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-sysfs.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-sysfs.c @@ -548,7 +548,7 @@ static void class_dev_destroy(struct pvr2_sysfs *sfp) &sfp->attr_unit_number); } pvr2_sysfs_trace("Destroying class_dev id=%p",sfp->class_dev); - sfp->class_dev->driver_data = NULL; + dev_set_drvdata(sfp->class_dev, NULL); device_unregister(sfp->class_dev); sfp->class_dev = NULL; } @@ -558,7 +558,7 @@ static ssize_t v4l_minor_number_show(struct device *class_dev, struct device_attribute *attr, char *buf) { struct pvr2_sysfs *sfp; - sfp = (struct pvr2_sysfs *)class_dev->driver_data; + sfp = dev_get_drvdata(class_dev); if (!sfp) return -EINVAL; return scnprintf(buf,PAGE_SIZE,"%d\n", pvr2_hdw_v4l_get_minor_number(sfp->channel.hdw, @@ -570,7 +570,7 @@ static ssize_t bus_info_show(struct device *class_dev, struct device_attribute *attr, char *buf) { struct pvr2_sysfs *sfp; - sfp = (struct pvr2_sysfs *)class_dev->driver_data; + sfp = dev_get_drvdata(class_dev); if (!sfp) return -EINVAL; return scnprintf(buf,PAGE_SIZE,"%s\n", pvr2_hdw_get_bus_info(sfp->channel.hdw)); @@ -581,7 +581,7 @@ static ssize_t hdw_name_show(struct device *class_dev, struct device_attribute *attr, char *buf) { struct pvr2_sysfs *sfp; - sfp = (struct pvr2_sysfs *)class_dev->driver_data; + sfp = dev_get_drvdata(class_dev); if (!sfp) return -EINVAL; return scnprintf(buf,PAGE_SIZE,"%s\n", pvr2_hdw_get_type(sfp->channel.hdw)); @@ -592,7 +592,7 @@ static ssize_t hdw_desc_show(struct device *class_dev, struct device_attribute *attr, char *buf) { struct pvr2_sysfs *sfp; - sfp = (struct pvr2_sysfs *)class_dev->driver_data; + sfp = dev_get_drvdata(class_dev); if (!sfp) return -EINVAL; return scnprintf(buf,PAGE_SIZE,"%s\n", pvr2_hdw_get_desc(sfp->channel.hdw)); @@ -604,7 +604,7 @@ static ssize_t v4l_radio_minor_number_show(struct device *class_dev, char *buf) { struct pvr2_sysfs *sfp; - sfp = (struct pvr2_sysfs *)class_dev->driver_data; + sfp = dev_get_drvdata(class_dev); if (!sfp) return -EINVAL; return scnprintf(buf,PAGE_SIZE,"%d\n", pvr2_hdw_v4l_get_minor_number(sfp->channel.hdw, @@ -616,7 +616,7 @@ static ssize_t unit_number_show(struct device *class_dev, struct device_attribute *attr, char *buf) { struct pvr2_sysfs *sfp; - sfp = (struct pvr2_sysfs *)class_dev->driver_data; + sfp = dev_get_drvdata(class_dev); if (!sfp) return -EINVAL; return scnprintf(buf,PAGE_SIZE,"%d\n", pvr2_hdw_get_unit_number(sfp->channel.hdw)); @@ -644,7 +644,7 @@ static void class_dev_create(struct pvr2_sysfs *sfp, class_dev->parent = &usb_dev->dev; sfp->class_dev = class_dev; - class_dev->driver_data = sfp; + dev_set_drvdata(class_dev, sfp); ret = device_register(class_dev); if (ret) { pvr2_trace(PVR2_TRACE_ERROR_LEGS, @@ -817,7 +817,7 @@ static ssize_t debuginfo_show(struct device *class_dev, struct device_attribute *attr, char *buf) { struct pvr2_sysfs *sfp; - sfp = (struct pvr2_sysfs *)class_dev->driver_data; + sfp = dev_get_drvdata(class_dev); if (!sfp) return -EINVAL; pvr2_hdw_trigger_module_log(sfp->channel.hdw); return pvr2_debugifc_print_info(sfp->channel.hdw,buf,PAGE_SIZE); @@ -828,7 +828,7 @@ static ssize_t debugcmd_show(struct device *class_dev, struct device_attribute *attr, char *buf) { struct pvr2_sysfs *sfp; - sfp = (struct pvr2_sysfs *)class_dev->driver_data; + sfp = dev_get_drvdata(class_dev); if (!sfp) return -EINVAL; return pvr2_debugifc_print_status(sfp->channel.hdw,buf,PAGE_SIZE); } @@ -841,7 +841,7 @@ static ssize_t debugcmd_store(struct device *class_dev, struct pvr2_sysfs *sfp; int ret; - sfp = (struct pvr2_sysfs *)class_dev->driver_data; + sfp = dev_get_drvdata(class_dev); if (!sfp) return -EINVAL; ret = pvr2_debugifc_docmd(sfp->channel.hdw,buf,count); -- cgit v1.2.3 From e7a66d6a4c0fbf91c8105ef68c07327a235d06af Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Thu, 30 Apr 2009 17:03:34 -0700 Subject: zoran: fix bug when enumerating format -1 From: Trent Piepho If someone requests a format at fmt->index == (unsigned)-1 and the first format in the array doesn't have the requested type then num will still be -1 when it's compared to fmt->index and there will appear to be a match. Restructure the loop so this can't happen. It's simpler this way too. The unnecessary check for (unsigned)fmt->index < 0 found by Roel Kluin is removed this way too. Priority: normal Signed-off-by: Trent Piepho --- linux/drivers/media/video/zoran/zoran_driver.c | 28 ++++++++++++-------------- 1 file changed, 13 insertions(+), 15 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/zoran/zoran_driver.c b/linux/drivers/media/video/zoran/zoran_driver.c index 047902eb0..793395074 100644 --- a/linux/drivers/media/video/zoran/zoran_driver.c +++ b/linux/drivers/media/video/zoran/zoran_driver.c @@ -1871,22 +1871,20 @@ static int zoran_querycap(struct file *file, void *__fh, struct v4l2_capability static int zoran_enum_fmt(struct zoran *zr, struct v4l2_fmtdesc *fmt, int flag) { - int num = -1, i; - - for (i = 0; i < NUM_FORMATS; i++) { - if (zoran_formats[i].flags & flag) - num++; - if (num == fmt->index) - break; + unsigned int num, i; + + for (num = i = 0; i < NUM_FORMATS; i++) { + if (zoran_formats[i].flags & flag && num++ == fmt->index) { + strncpy(fmt->description, zoran_formats[i].name, + sizeof(fmt->description) - 1); + /* fmt struct pre-zeroed, so adding '\0' not neeed */ + fmt->pixelformat = zoran_formats[i].fourcc; + if (zoran_formats[i].flags & ZORAN_FORMAT_COMPRESSED) + fmt->flags |= V4L2_FMT_FLAG_COMPRESSED; + return 0; + } } - if (fmt->index < 0 /* late, but not too late */ || i == NUM_FORMATS) - return -EINVAL; - - strncpy(fmt->description, zoran_formats[i].name, sizeof(fmt->description)-1); - fmt->pixelformat = zoran_formats[i].fourcc; - if (zoran_formats[i].flags & ZORAN_FORMAT_COMPRESSED) - fmt->flags |= V4L2_FMT_FLAG_COMPRESSED; - return 0; + return -EINVAL; } static int zoran_enum_fmt_vid_cap(struct file *file, void *__fh, -- cgit v1.2.3 From 574b057f4500a8ad93c3d36a72e7ba6568d15e8b Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Thu, 30 Apr 2009 17:03:34 -0700 Subject: v4l2-ioctl: Check buffer types using g_fmt instead of try_fmt From: Trent Piepho For a number of different ioctls, the v4l2-ioctl code checks that the passed buffer type is supported by the driver. It did this by checking that the driver defined a method for the try_fmt handler for that buffer type. However, try_fmt is optional and a driver might not provide it even though it does support that type. So use g_fmt instead, since that isn't optional. This should fix a problem with VBI capture with saa7146. Priority: normal Signed-off-by: Trent Piepho --- linux/drivers/media/video/v4l2-ioctl.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/v4l2-ioctl.c b/linux/drivers/media/video/v4l2-ioctl.c index 885e6f557..e3eea7c71 100644 --- a/linux/drivers/media/video/v4l2-ioctl.c +++ b/linux/drivers/media/video/v4l2-ioctl.c @@ -545,39 +545,39 @@ static int check_fmt(const struct v4l2_ioctl_ops *ops, enum v4l2_buf_type type) switch (type) { case V4L2_BUF_TYPE_VIDEO_CAPTURE: - if (ops->vidioc_try_fmt_vid_cap) + if (ops->vidioc_g_fmt_vid_cap) return 0; break; case V4L2_BUF_TYPE_VIDEO_OVERLAY: - if (ops->vidioc_try_fmt_vid_overlay) + if (ops->vidioc_g_fmt_vid_overlay) return 0; break; case V4L2_BUF_TYPE_VIDEO_OUTPUT: - if (ops->vidioc_try_fmt_vid_out) + if (ops->vidioc_g_fmt_vid_out) return 0; break; case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY: - if (ops->vidioc_try_fmt_vid_out_overlay) + if (ops->vidioc_g_fmt_vid_out_overlay) return 0; break; case V4L2_BUF_TYPE_VBI_CAPTURE: - if (ops->vidioc_try_fmt_vbi_cap) + if (ops->vidioc_g_fmt_vbi_cap) return 0; break; case V4L2_BUF_TYPE_VBI_OUTPUT: - if (ops->vidioc_try_fmt_vbi_out) + if (ops->vidioc_g_fmt_vbi_out) return 0; break; case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: - if (ops->vidioc_try_fmt_sliced_vbi_cap) + if (ops->vidioc_g_fmt_sliced_vbi_cap) return 0; break; case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT: - if (ops->vidioc_try_fmt_sliced_vbi_out) + if (ops->vidioc_g_fmt_sliced_vbi_out) return 0; break; case V4L2_BUF_TYPE_PRIVATE: - if (ops->vidioc_try_fmt_type_private) + if (ops->vidioc_g_fmt_type_private) return 0; break; } -- cgit v1.2.3 From 5b50b456410eb7eaf50e12abe21730cc65a49078 Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Thu, 30 Apr 2009 17:03:34 -0700 Subject: v4l2-ioctl: Clear buffer type specific trailing fields/padding MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: Trent Piepho Some ioctls have structs that are a different size depending on what type of buffer is being used. If the buffer type leaves a field unused or has padding space at the end, this space should be zeroed out. The problems with S_FMT and REQBUFS were original identified and patched by Márton Németh . Priority: normal Signed-off-by: Trent Piepho --- linux/drivers/media/video/v4l2-ioctl.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/v4l2-ioctl.c b/linux/drivers/media/video/v4l2-ioctl.c index e3eea7c71..22b380dfd 100644 --- a/linux/drivers/media/video/v4l2-ioctl.c +++ b/linux/drivers/media/video/v4l2-ioctl.c @@ -43,6 +43,12 @@ printk(KERN_DEBUG "%s: " fmt, vfd->name, ## arg);\ } while (0) +/* Zero out the end of the struct pointed to by p. Everthing after, but + * not including, the specified field is cleared. */ +#define CLEAR_AFTER_FIELD(p, field) \ + memset((u8 *)(p) + offsetof(typeof(*(p)), field) + sizeof((p)->field), \ + 0, sizeof(*(p)) - offsetof(typeof(*(p)), field) - sizeof((p)->field)) + struct std_descr { v4l2_std_id std; const char *descr; @@ -783,44 +789,53 @@ static long __video_do_ioctl(struct file *file, switch (f->type) { case V4L2_BUF_TYPE_VIDEO_CAPTURE: + CLEAR_AFTER_FIELD(f, fmt.pix); v4l_print_pix_fmt(vfd, &f->fmt.pix); if (ops->vidioc_s_fmt_vid_cap) ret = ops->vidioc_s_fmt_vid_cap(file, fh, f); break; case V4L2_BUF_TYPE_VIDEO_OVERLAY: + CLEAR_AFTER_FIELD(f, fmt.win); if (ops->vidioc_s_fmt_vid_overlay) ret = ops->vidioc_s_fmt_vid_overlay(file, fh, f); break; case V4L2_BUF_TYPE_VIDEO_OUTPUT: + CLEAR_AFTER_FIELD(f, fmt.pix); v4l_print_pix_fmt(vfd, &f->fmt.pix); if (ops->vidioc_s_fmt_vid_out) ret = ops->vidioc_s_fmt_vid_out(file, fh, f); break; case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY: + CLEAR_AFTER_FIELD(f, fmt.win); if (ops->vidioc_s_fmt_vid_out_overlay) ret = ops->vidioc_s_fmt_vid_out_overlay(file, fh, f); break; case V4L2_BUF_TYPE_VBI_CAPTURE: + CLEAR_AFTER_FIELD(f, fmt.vbi); if (ops->vidioc_s_fmt_vbi_cap) ret = ops->vidioc_s_fmt_vbi_cap(file, fh, f); break; case V4L2_BUF_TYPE_VBI_OUTPUT: + CLEAR_AFTER_FIELD(f, fmt.vbi); if (ops->vidioc_s_fmt_vbi_out) ret = ops->vidioc_s_fmt_vbi_out(file, fh, f); break; case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: + CLEAR_AFTER_FIELD(f, fmt.sliced); if (ops->vidioc_s_fmt_sliced_vbi_cap) ret = ops->vidioc_s_fmt_sliced_vbi_cap(file, fh, f); break; case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT: + CLEAR_AFTER_FIELD(f, fmt.sliced); if (ops->vidioc_s_fmt_sliced_vbi_out) ret = ops->vidioc_s_fmt_sliced_vbi_out(file, fh, f); break; case V4L2_BUF_TYPE_PRIVATE: + /* CLEAR_AFTER_FIELD(f, fmt.raw_data); <- does nothing */ if (ops->vidioc_s_fmt_type_private) ret = ops->vidioc_s_fmt_type_private(file, fh, f); @@ -837,46 +852,55 @@ static long __video_do_ioctl(struct file *file, v4l2_type_names)); switch (f->type) { case V4L2_BUF_TYPE_VIDEO_CAPTURE: + CLEAR_AFTER_FIELD(f, fmt.pix); if (ops->vidioc_try_fmt_vid_cap) ret = ops->vidioc_try_fmt_vid_cap(file, fh, f); if (!ret) v4l_print_pix_fmt(vfd, &f->fmt.pix); break; case V4L2_BUF_TYPE_VIDEO_OVERLAY: + CLEAR_AFTER_FIELD(f, fmt.win); if (ops->vidioc_try_fmt_vid_overlay) ret = ops->vidioc_try_fmt_vid_overlay(file, fh, f); break; case V4L2_BUF_TYPE_VIDEO_OUTPUT: + CLEAR_AFTER_FIELD(f, fmt.pix); if (ops->vidioc_try_fmt_vid_out) ret = ops->vidioc_try_fmt_vid_out(file, fh, f); if (!ret) v4l_print_pix_fmt(vfd, &f->fmt.pix); break; case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY: + CLEAR_AFTER_FIELD(f, fmt.win); if (ops->vidioc_try_fmt_vid_out_overlay) ret = ops->vidioc_try_fmt_vid_out_overlay(file, fh, f); break; case V4L2_BUF_TYPE_VBI_CAPTURE: + CLEAR_AFTER_FIELD(f, fmt.vbi); if (ops->vidioc_try_fmt_vbi_cap) ret = ops->vidioc_try_fmt_vbi_cap(file, fh, f); break; case V4L2_BUF_TYPE_VBI_OUTPUT: + CLEAR_AFTER_FIELD(f, fmt.vbi); if (ops->vidioc_try_fmt_vbi_out) ret = ops->vidioc_try_fmt_vbi_out(file, fh, f); break; case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: + CLEAR_AFTER_FIELD(f, fmt.sliced); if (ops->vidioc_try_fmt_sliced_vbi_cap) ret = ops->vidioc_try_fmt_sliced_vbi_cap(file, fh, f); break; case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT: + CLEAR_AFTER_FIELD(f, fmt.sliced); if (ops->vidioc_try_fmt_sliced_vbi_out) ret = ops->vidioc_try_fmt_sliced_vbi_out(file, fh, f); break; case V4L2_BUF_TYPE_PRIVATE: + /* CLEAR_AFTER_FIELD(f, fmt.raw_data); <- does nothing */ if (ops->vidioc_try_fmt_type_private) ret = ops->vidioc_try_fmt_type_private(file, fh, f); @@ -899,6 +923,9 @@ static long __video_do_ioctl(struct file *file, if (ret) break; + if (p->type < V4L2_BUF_TYPE_PRIVATE) + CLEAR_AFTER_FIELD(p, memory); + ret = ops->vidioc_reqbufs(file, fh, p); dbgarg(cmd, "count=%d, type=%s, memory=%s\n", p->count, -- cgit v1.2.3 From e12bd28a677612320a63eca215a0b260ab897ffb Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Fri, 1 May 2009 20:23:39 -0500 Subject: pvrusb2: Update to work with upcoming ir_video changes in v4l-dvb core From: Mike Isely The ir-kbd-i2c module is about to be updated to match the new style i2c binding model. These pvrusb2 changes maintain compatibility with that change. Note that this does not actually break anything even without the expected ir-kbd-i2c changes yet because previously the pvrusb2 didn't autoload ir-kbd-i2c anyway. Priority: normal Signed-off-by: Mike Isely --- .../drivers/media/video/pvrusb2/pvrusb2-i2c-core.c | 39 ++++++++++++++++++++++ 1 file changed, 39 insertions(+) (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 4c761161f..694e51f58 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c @@ -43,6 +43,18 @@ 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; +module_param_named(disable_autoload_ir_video, pvr2_disable_ir_video, + int, S_IRUGO|S_IWUSR); +MODULE_PARM_DESC(disable_autoload_ir_video, + "1=do not try to autoload ir_video IR receiver"); + +/* Mapping of IR schemes to known I2C addresses - if any */ +static const unsigned char ir_video_addresses[] = { + [PVR2_IR_SCHEME_29XXX] = 0x18, + [PVR2_IR_SCHEME_24XXX] = 0x18, +}; + static int pvr2_i2c_write(struct pvr2_hdw *hdw, /* Context */ u8 i2c_addr, /* I2C address we're talking to */ u8 *data, /* Data to write */ @@ -637,6 +649,31 @@ static void do_i2c_scan(struct pvr2_hdw *hdw) printk(KERN_INFO "%s: i2c scan done.\n", hdw->name); } +static void pvr2_i2c_register_ir(struct pvr2_hdw *hdw) +{ + struct i2c_board_info info; + unsigned char addr = 0; + if (pvr2_disable_ir_video) { + pvr2_trace(PVR2_TRACE_INFO, + "Automatic binding of ir_video has been disabled."); + return; + } + if (hdw->ir_scheme_active < ARRAY_SIZE(ir_video_addresses)) { + addr = ir_video_addresses[hdw->ir_scheme_active]; + } + if (!addr) { + /* The device either doesn't support I2C-based IR or we + don't know (yet) how to operate IR on the device. */ + return; + } + pvr2_trace(PVR2_TRACE_INFO, + "Binding ir_video to i2c address 0x%02x.", addr); + memset(&info, 0, sizeof(struct i2c_board_info)); + strlcpy(info.type, "ir_video", I2C_NAME_SIZE); + info.addr = addr; + i2c_new_device(&hdw->i2c_adap, &info); +} + void pvr2_i2c_core_init(struct pvr2_hdw *hdw) { unsigned int idx; @@ -692,6 +729,8 @@ void pvr2_i2c_core_init(struct pvr2_hdw *hdw) } } if (i2c_scan) do_i2c_scan(hdw); + + pvr2_i2c_register_ir(hdw); } void pvr2_i2c_core_done(struct pvr2_hdw *hdw) -- cgit v1.2.3 From 961b6d8d20c76a4c210516ce2c9baa4df6d43527 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Fri, 1 May 2009 20:33:16 -0500 Subject: pvrusb2: Set ir_video autoloading to default disabled From: Mike Isely This sets the disable_autoload_ir_video module option to being set, which disables any attempt by the driver to autoload IR support. This changes preserves previous behavior, for now. This change can be set back concurrent with other changes that finally update i2c-kbd-i2c to use the new i2c binding model. Priority: normal Signed-off-by: Mike Isely --- 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 694e51f58..28463489a 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; +static int pvr2_disable_ir_video = 1; 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 2a1a9acb2d85130c9e1b9f7dc7812e8846142bcc Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Fri, 1 May 2009 22:04:35 -0500 Subject: pvrusb2: Bump up version advertised through v4l interface From: Mike Isely Kick up the pvrusb2 version number advertised through the v4l interface. This value really has almost no meaning because I don't make a serious attempt to version the driver in this manner (otherwise this one line becomes a nasty hotspot of changes and merge conflicts). The value that is here is really a historical thing. However Hans Verkuil thought it might be a good idea to bump up the number anyway right now since the driver's mechanism for communicating with the v4l core has pretty much completely changed. Sending out a different version number can be useful for later debugging in case a problem arises. Priority: normal Signed-off-by: Mike Isely --- linux/drivers/media/video/pvrusb2/pvrusb2-v4l2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-v4l2.c b/linux/drivers/media/video/pvrusb2/pvrusb2-v4l2.c index c7fc605f8..adccf1cc8 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-v4l2.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-v4l2.c @@ -91,7 +91,7 @@ static struct v4l2_capability pvr_capability ={ .driver = "pvrusb2", .card = "Hauppauge WinTV pvr-usb2", .bus_info = "usb", - .version = KERNEL_VERSION(0,8,0), + .version = KERNEL_VERSION(0, 9, 0), .capabilities = (V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_TUNER | V4L2_CAP_AUDIO | V4L2_CAP_RADIO | V4L2_CAP_READWRITE), -- cgit v1.2.3 From 5fc20d3a3b9f5a7aed0f0e17174524ff7caf6f72 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Fri, 1 May 2009 22:22:27 -0500 Subject: pvrusb2: Don't use the internal i2c client list From: Jean Delvare The i2c core used to maintain a list of client for each adapter. This is a duplication of what the driver core already does, so this list will be removed as part of a future cleanup. Anyone using this list must stop doing so. For pvrusb2, I propose the following change, which should lead to an equally informative output. The only difference is that i2c clients which are not a v4l2 subdev won't show up, but I guess this case is not supposed to happen anyway. Priority: normal Signed-off-by: Jean Delvare Signed-off-by: Mike Isely --- linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c | 56 ++++++------------------- 1 file changed, 13 insertions(+), 43 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c index b07daea8c..3411cb36a 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -4935,65 +4935,35 @@ static unsigned int pvr2_hdw_report_clients(struct pvr2_hdw *hdw, unsigned int tcnt = 0; unsigned int ccnt; struct i2c_client *client; - struct list_head *item; - void *cd; const char *p; unsigned int id; - ccnt = scnprintf(buf, acnt, "Associated v4l2-subdev drivers:"); + ccnt = scnprintf(buf, acnt, "Associated v4l2-subdev drivers and I2C clients:\n"); tcnt += ccnt; v4l2_device_for_each_subdev(sd, &hdw->v4l2_dev) { id = sd->grp_id; p = NULL; if (id < ARRAY_SIZE(module_names)) p = module_names[id]; if (p) { - ccnt = scnprintf(buf + tcnt, acnt - tcnt, " %s", p); + ccnt = scnprintf(buf + tcnt, acnt - tcnt, " %s:", p); tcnt += ccnt; } else { ccnt = scnprintf(buf + tcnt, acnt - tcnt, - " (unknown id=%u)", id); + " (unknown id=%u):", id); tcnt += ccnt; } - } - ccnt = scnprintf(buf + tcnt, acnt - tcnt, "\n"); - tcnt += ccnt; - - ccnt = scnprintf(buf + tcnt, acnt - tcnt, "I2C clients:\n"); - tcnt += ccnt; - - mutex_lock(&hdw->i2c_adap.clist_lock); - list_for_each(item, &hdw->i2c_adap.clients) { - client = list_entry(item, struct i2c_client, list); - ccnt = scnprintf(buf + tcnt, acnt - tcnt, - " %s: i2c=%02x", client->name, client->addr); - tcnt += ccnt; - cd = i2c_get_clientdata(client); - v4l2_device_for_each_subdev(sd, &hdw->v4l2_dev) { - if (cd == sd) { - id = sd->grp_id; - p = NULL; - if (id < ARRAY_SIZE(module_names)) { - p = module_names[id]; - } - if (p) { - ccnt = scnprintf(buf + tcnt, - acnt - tcnt, - " subdev=%s", p); - tcnt += ccnt; - } else { - ccnt = scnprintf(buf + tcnt, - acnt - tcnt, - " subdev= id %u)", - id); - tcnt += ccnt; - } - break; - } + client = v4l2_get_subdevdata(sd); + if (client) { + ccnt = scnprintf(buf + tcnt, acnt - tcnt, + " %s @ %02x\n", client->name, + client->addr); + tcnt += ccnt; + } else { + ccnt = scnprintf(buf + tcnt, acnt - tcnt, + " no i2c client\n"); + tcnt += ccnt; } - ccnt = scnprintf(buf + tcnt, acnt - tcnt, "\n"); - tcnt += ccnt; } - mutex_unlock(&hdw->i2c_adap.clist_lock); return tcnt; } -- cgit v1.2.3 From bd5e7a9e095c77ae571573079f9f87181f73f0a5 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Fri, 1 May 2009 22:36:33 -0500 Subject: pvrusb2: remove driver_data direct access of struct device From: Greg Kroah-Hartman In the near future, the driver core is going to not allow direct access to the driver_data pointer in struct device. Instead, the functions dev_get_drvdata() and dev_set_drvdata() should be used. These functions have been around since the beginning, so are backwards compatible with all older kernel versions. Priority: normal Cc: Mauro Carvalho Chehab Cc: linux-media@vger.kernel.org Signed-off-by: Greg Kroah-Hartman Signed-off-by: Mike Isely --- linux/drivers/media/video/pvrusb2/pvrusb2-sysfs.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-sysfs.c b/linux/drivers/media/video/pvrusb2/pvrusb2-sysfs.c index 7ed3b8453..d8ad83df3 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-sysfs.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-sysfs.c @@ -548,7 +548,7 @@ static void class_dev_destroy(struct pvr2_sysfs *sfp) &sfp->attr_unit_number); } pvr2_sysfs_trace("Destroying class_dev id=%p",sfp->class_dev); - sfp->class_dev->driver_data = NULL; + dev_set_drvdata(sfp->class_dev, NULL); device_unregister(sfp->class_dev); sfp->class_dev = NULL; } @@ -558,7 +558,7 @@ static ssize_t v4l_minor_number_show(struct device *class_dev, struct device_attribute *attr, char *buf) { struct pvr2_sysfs *sfp; - sfp = (struct pvr2_sysfs *)class_dev->driver_data; + sfp = dev_get_drvdata(class_dev); if (!sfp) return -EINVAL; return scnprintf(buf,PAGE_SIZE,"%d\n", pvr2_hdw_v4l_get_minor_number(sfp->channel.hdw, @@ -570,7 +570,7 @@ static ssize_t bus_info_show(struct device *class_dev, struct device_attribute *attr, char *buf) { struct pvr2_sysfs *sfp; - sfp = (struct pvr2_sysfs *)class_dev->driver_data; + sfp = dev_get_drvdata(class_dev); if (!sfp) return -EINVAL; return scnprintf(buf,PAGE_SIZE,"%s\n", pvr2_hdw_get_bus_info(sfp->channel.hdw)); @@ -581,7 +581,7 @@ static ssize_t hdw_name_show(struct device *class_dev, struct device_attribute *attr, char *buf) { struct pvr2_sysfs *sfp; - sfp = (struct pvr2_sysfs *)class_dev->driver_data; + sfp = dev_get_drvdata(class_dev); if (!sfp) return -EINVAL; return scnprintf(buf,PAGE_SIZE,"%s\n", pvr2_hdw_get_type(sfp->channel.hdw)); @@ -592,7 +592,7 @@ static ssize_t hdw_desc_show(struct device *class_dev, struct device_attribute *attr, char *buf) { struct pvr2_sysfs *sfp; - sfp = (struct pvr2_sysfs *)class_dev->driver_data; + sfp = dev_get_drvdata(class_dev); if (!sfp) return -EINVAL; return scnprintf(buf,PAGE_SIZE,"%s\n", pvr2_hdw_get_desc(sfp->channel.hdw)); @@ -604,7 +604,7 @@ static ssize_t v4l_radio_minor_number_show(struct device *class_dev, char *buf) { struct pvr2_sysfs *sfp; - sfp = (struct pvr2_sysfs *)class_dev->driver_data; + sfp = dev_get_drvdata(class_dev); if (!sfp) return -EINVAL; return scnprintf(buf,PAGE_SIZE,"%d\n", pvr2_hdw_v4l_get_minor_number(sfp->channel.hdw, @@ -616,7 +616,7 @@ static ssize_t unit_number_show(struct device *class_dev, struct device_attribute *attr, char *buf) { struct pvr2_sysfs *sfp; - sfp = (struct pvr2_sysfs *)class_dev->driver_data; + sfp = dev_get_drvdata(class_dev); if (!sfp) return -EINVAL; return scnprintf(buf,PAGE_SIZE,"%d\n", pvr2_hdw_get_unit_number(sfp->channel.hdw)); @@ -644,7 +644,7 @@ static void class_dev_create(struct pvr2_sysfs *sfp, class_dev->parent = &usb_dev->dev; sfp->class_dev = class_dev; - class_dev->driver_data = sfp; + dev_set_drvdata(class_dev, sfp); ret = device_register(class_dev); if (ret) { pvr2_trace(PVR2_TRACE_ERROR_LEGS, @@ -817,7 +817,7 @@ static ssize_t debuginfo_show(struct device *class_dev, struct device_attribute *attr, char *buf) { struct pvr2_sysfs *sfp; - sfp = (struct pvr2_sysfs *)class_dev->driver_data; + sfp = dev_get_drvdata(class_dev); if (!sfp) return -EINVAL; pvr2_hdw_trigger_module_log(sfp->channel.hdw); return pvr2_debugifc_print_info(sfp->channel.hdw,buf,PAGE_SIZE); @@ -828,7 +828,7 @@ static ssize_t debugcmd_show(struct device *class_dev, struct device_attribute *attr, char *buf) { struct pvr2_sysfs *sfp; - sfp = (struct pvr2_sysfs *)class_dev->driver_data; + sfp = dev_get_drvdata(class_dev); if (!sfp) return -EINVAL; return pvr2_debugifc_print_status(sfp->channel.hdw,buf,PAGE_SIZE); } @@ -841,7 +841,7 @@ static ssize_t debugcmd_store(struct device *class_dev, struct pvr2_sysfs *sfp; int ret; - sfp = (struct pvr2_sysfs *)class_dev->driver_data; + sfp = dev_get_drvdata(class_dev); if (!sfp) return -EINVAL; ret = pvr2_debugifc_docmd(sfp->channel.hdw,buf,count); -- cgit v1.2.3 From 1cf5bef87d4d6a9e00381996efdf37b91801c38c Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 5 May 2009 06:39:21 -0300 Subject: Fix a warning introduced by git commit ec5f5bf80501abfe2da2897cfcde8452b545aacb From: Mauro Carvalho Chehab /home/v4l/master/v4l/radio-si470x.c: In function 'si470x_fops_release': /home/v4l/master/v4l/radio-si470x.c:1218: warning: label 'unlock' defined but not used Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/radio/radio-si470x.c | 1 - 1 file changed, 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/radio/radio-si470x.c b/linux/drivers/media/radio/radio-si470x.c index f78a9cdea..101ede1cf 100644 --- a/linux/drivers/media/radio/radio-si470x.c +++ b/linux/drivers/media/radio/radio-si470x.c @@ -1215,7 +1215,6 @@ static int si470x_fops_release(struct file *file) usb_autopm_put_interface(radio->intf); } -unlock: mutex_unlock(&radio->disconnect_lock); done: -- cgit v1.2.3 From ce05681eb1dbee65c3110182492f84519f264326 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 2 May 2009 12:56:46 +0200 Subject: ivtv: fix compiler warning. From: Hans Verkuil Priority: high Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/ivtv/ivtv-driver.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/ivtv/ivtv-driver.c b/linux/drivers/media/video/ivtv/ivtv-driver.c index 4ddeb165d..d5bdcd372 100644 --- a/linux/drivers/media/video/ivtv/ivtv-driver.c +++ b/linux/drivers/media/video/ivtv/ivtv-driver.c @@ -305,14 +305,17 @@ int ivtv_waitq(wait_queue_head_t *waitq) /* Generic utility functions */ int ivtv_msleep_timeout(unsigned int msecs, int intr) { - int ret; int timeout = msecs_to_jiffies(msecs); do { set_current_state(intr ? TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE); timeout = schedule_timeout(timeout); - if (intr && (ret = signal_pending(current))) - return ret; + if (intr) { + int ret = signal_pending(current); + + if (ret) + return ret; + } } while (timeout); return 0; } -- cgit v1.2.3 From be0bb8202ad078bfd0e8c669849aed9983b94bea Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 2 May 2009 13:12:36 +0200 Subject: uvc: fix compile warning From: Hans Verkuil The 2.6.30 kernel generates this warning: uvc_driver.c:1729: warning: 'ret' may be used uninitialized in this function I guess some new warning flag must have been turned on since this warning didn't appear with older kernels (gcc version 4.3.1). It's also a bogus warning, but since this code didn't comply to the coding standard anyway I've modified it to 1) remove the warning and 2) conform to the coding standard. Priority: high Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/uvc/uvc_driver.c | 9 ++++++--- 1 file changed, 6 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 31d60647d..4a69a3af6 100644 --- a/linux/drivers/media/video/uvc/uvc_driver.c +++ b/linux/drivers/media/video/uvc/uvc_driver.c @@ -1726,14 +1726,17 @@ static int uvc_suspend(struct usb_interface *intf, pm_message_t message) static int __uvc_resume(struct usb_interface *intf, int reset) { struct uvc_device *dev = usb_get_intfdata(intf); - int ret; uvc_trace(UVC_TRACE_SUSPEND, "Resuming interface %u\n", intf->cur_altsetting->desc.bInterfaceNumber); if (intf->cur_altsetting->desc.bInterfaceSubClass == SC_VIDEOCONTROL) { - if (reset && (ret = uvc_ctrl_resume_device(dev)) < 0) - return ret; + if (reset) { + int ret = uvc_ctrl_resume_device(dev); + + if (ret < 0) + return ret; + } return uvc_status_resume(dev); } -- cgit v1.2.3 From 83d87c0c4e7849713db298cea21c964f85313f3b Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 2 May 2009 14:42:57 +0200 Subject: tuner: remove tuner_i2c_address_check From: Hans Verkuil Support for tuners with i2c addresses >= 0x65 is dropped since no tuners with addresses in the range 0x65-0x6f have been found. This patch removes addresses 0x65-0x6f from the list of tuner probe addresses, it removes the kernel warning that warned if addresses in this range appeared, and it removed a hack for the cx88 that is no longer needed now that the tuner address range is reduced. Priority: normal Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/tuner-core.c | 52 +-------------------------------- linux/drivers/media/video/v4l2-common.c | 3 +- 2 files changed, 2 insertions(+), 53 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/tuner-core.c b/linux/drivers/media/video/tuner-core.c index 9f763535e..bb60c910e 100644 --- a/linux/drivers/media/video/tuner-core.c +++ b/linux/drivers/media/video/tuner-core.c @@ -109,8 +109,7 @@ static unsigned short normal_i2c[] = { 0x10, #endif 0x42, 0x43, 0x4a, 0x4b, /* tda8290 */ - 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, - 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, + 0x60, 0x61, 0x62, 0x63, 0x64, I2C_CLIENT_END }; @@ -324,32 +323,6 @@ static void set_freq(struct i2c_client *c, unsigned long freq) } } -static void tuner_i2c_address_check(struct tuner *t) -{ - if ((t->type == UNSET || t->type == TUNER_ABSENT) || - ((t->i2c->addr < 0x64) || (t->i2c->addr > 0x6f))) - return; - - /* We already know that the XC5000 can only be located at - * i2c address 0x61, 0x62, 0x63 or 0x64 */ - if ((t->type == TUNER_XC5000) && - ((t->i2c->addr <= 0x64)) && (t->i2c->addr >= 0x61)) - return; - - tuner_warn("====================== WARNING! ======================\n"); - tuner_warn("Support for tuners in i2c address range 0x64 thru 0x6f\n"); - tuner_warn("will soon be dropped. This message indicates that your\n"); - tuner_warn("hardware has a %s tuner at i2c address 0x%02x.\n", - t->name, t->i2c->addr); - tuner_warn("To ensure continued support for your device, please\n"); - tuner_warn("send a copy of this message, along with full dmesg\n"); - tuner_warn("output to v4l-dvb-maintainer@linuxtv.org\n"); - tuner_warn("Please use subject line: \"obsolete tuner i2c address.\"\n"); - tuner_warn("driver: %s, addr: 0x%02x, type: %d (%s)\n", - t->i2c->adapter->name, t->i2c->addr, t->type, t->name); - tuner_warn("====================== WARNING! ======================\n"); -} - static struct xc5000_config xc5000_cfg; static void set_type(struct i2c_client *c, unsigned int type, @@ -505,7 +478,6 @@ static void set_type(struct i2c_client *c, unsigned int type, tuner_dbg("%s %s I2C addr 0x%02x with type %d used for 0x%02x\n", c->adapter->name, c->driver->driver.name, c->addr << 1, type, t->mode_mask); - tuner_i2c_address_check(t); return; attach_failed: @@ -1213,28 +1185,6 @@ static int tuner_legacy_probe(struct i2c_adapter *adap) if ((adap->class & I2C_CLASS_TV_ANALOG) == 0) return 0; - - /* HACK: Ignore 0x6b and 0x6f on cx88 boards. - * FusionHDTV5 RT Gold has an ir receiver at 0x6b - * and an RTC at 0x6f which can get corrupted if probed. - */ - if ((adap->id == I2C_HW_B_CX2388x) || - (adap->id == I2C_HW_B_CX23885)) { - unsigned int i = 0; - - while (i < I2C_CLIENT_MAX_OPTS && ignore[i] != I2C_CLIENT_END) - i += 2; - if (i + 4 < I2C_CLIENT_MAX_OPTS) { - ignore[i+0] = adap->nr; - ignore[i+1] = 0x6b; - ignore[i+2] = adap->nr; - ignore[i+3] = 0x6f; - ignore[i+4] = I2C_CLIENT_END; - } else - printk(KERN_WARNING "tuner: " - "too many options specified " - "in i2c probe ignore list!\n"); - } return 1; } #else diff --git a/linux/drivers/media/video/v4l2-common.c b/linux/drivers/media/video/v4l2-common.c index d75d89c88..0301974dc 100644 --- a/linux/drivers/media/video/v4l2-common.c +++ b/linux/drivers/media/video/v4l2-common.c @@ -978,8 +978,7 @@ const unsigned short *v4l2_i2c_tuner_addrs(enum v4l2_i2c_tuner_type type) }; static const unsigned short tv_addrs[] = { 0x42, 0x43, 0x4a, 0x4b, /* tda8290 */ - 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, - 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, + 0x60, 0x61, 0x62, 0x63, 0x64, I2C_CLIENT_END }; -- cgit v1.2.3 From 79d2addf97397ee580b80f71343cf72b03da65a2 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 2 May 2009 15:12:50 +0200 Subject: v4l2: add v4l2_device_set_name() From: Hans Verkuil Add a utility function that can be used to setup the v4l2_device's name field in a standard manner. Priority: normal Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/v4l2-device.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/v4l2-device.c b/linux/drivers/media/video/v4l2-device.c index 2cb81c210..143f69614 100644 --- a/linux/drivers/media/video/v4l2-device.c +++ b/linux/drivers/media/video/v4l2-device.c @@ -50,6 +50,22 @@ int v4l2_device_register(struct device *dev, struct v4l2_device *v4l2_dev) } EXPORT_SYMBOL_GPL(v4l2_device_register); +int v4l2_device_set_name(struct v4l2_device *v4l2_dev, const char *basename, + atomic_t *instance) +{ + int num = atomic_inc_return(instance) - 1; + int len = strlen(basename); + + if (basename[len - 1] >= '0' && basename[len - 1] <= '9') + snprintf(v4l2_dev->name, sizeof(v4l2_dev->name), + "%s-%d", basename, num); + else + snprintf(v4l2_dev->name, sizeof(v4l2_dev->name), + "%s%d", basename, num); + return num; +} +EXPORT_SYMBOL_GPL(v4l2_device_set_name); + void v4l2_device_disconnect(struct v4l2_device *v4l2_dev) { if (v4l2_dev->dev) { -- cgit v1.2.3 From 82be7998cf669df0155ca75ef1876c750cccbff9 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 2 May 2009 15:15:17 +0200 Subject: ivtv: use v4l2_device_set_name. From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/ivtv/ivtv-driver.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/ivtv/ivtv-driver.c b/linux/drivers/media/video/ivtv/ivtv-driver.c index d5bdcd372..edb81a948 100644 --- a/linux/drivers/media/video/ivtv/ivtv-driver.c +++ b/linux/drivers/media/video/ivtv/ivtv-driver.c @@ -950,17 +950,14 @@ static int __devinit ivtv_probe(struct pci_dev *pdev, if (itv == NULL) return -ENOMEM; itv->pdev = pdev; - itv->instance = atomic_inc_return(&ivtv_instance) - 1; + itv->instance = v4l2_device_set_name(&itv->v4l2_dev, "ivtv", + &ivtv_instance); retval = v4l2_device_register(&pdev->dev, &itv->v4l2_dev); if (retval) { kfree(itv); return retval; } - /* "ivtv + PCI ID" is a bit of a mouthful, so use - "ivtv + instance" instead. */ - snprintf(itv->v4l2_dev.name, sizeof(itv->v4l2_dev.name), - "ivtv%d", itv->instance); IVTV_INFO("Initializing card %d\n", itv->instance); ivtv_process_options(itv); -- cgit v1.2.3 From 486b64428b6255dc6cf7aa8759648f9a9bca1dbd Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 2 May 2009 15:58:51 +0200 Subject: v4l2-device: unregister i2c_clients when unregistering the v4l2_device. From: Hans Verkuil Until now I relied on i2c_del_adapter to unregister the i2c_clients for me, however, if the i2c bus is a platform bus then it is never deleted. So instead I need to unregister i2c clients when unregistering the v4l2_device. Priority: normal Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/v4l2-common.c | 1 + linux/drivers/media/video/v4l2-device.c | 13 ++++++++++++- 2 files changed, 13 insertions(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/v4l2-common.c b/linux/drivers/media/video/v4l2-common.c index 0301974dc..8f2db1250 100644 --- a/linux/drivers/media/video/v4l2-common.c +++ b/linux/drivers/media/video/v4l2-common.c @@ -774,6 +774,7 @@ void v4l2_i2c_subdev_init(struct v4l2_subdev *sd, struct i2c_client *client, const struct v4l2_subdev_ops *ops) { v4l2_subdev_init(sd, ops); + sd->flags |= V4L2_SUBDEV_FL_IS_I2C; /* the owner is the same as the i2c_client's driver owner */ sd->owner = client->driver->driver.owner; /* i2c_client and v4l2_subdev point to one another */ diff --git a/linux/drivers/media/video/v4l2-device.c b/linux/drivers/media/video/v4l2-device.c index 143f69614..c76f83840 100644 --- a/linux/drivers/media/video/v4l2-device.c +++ b/linux/drivers/media/video/v4l2-device.c @@ -84,8 +84,19 @@ void v4l2_device_unregister(struct v4l2_device *v4l2_dev) v4l2_device_disconnect(v4l2_dev); /* Unregister subdevs */ - list_for_each_entry_safe(sd, next, &v4l2_dev->subdevs, list) + list_for_each_entry_safe(sd, next, &v4l2_dev->subdevs, list) { v4l2_device_unregister_subdev(sd); + if (sd->flags & V4L2_SUBDEV_FL_IS_I2C) { + struct i2c_client *client = v4l2_get_subdevdata(sd); + + /* We need to unregister the i2c client explicitly. + We cannot rely on i2c_del_adapter to always + unregister clients for us, since if the i2c bus + is a platform bus, then it is never deleted. */ + if (client) + i2c_unregister_device(client); + } + } } EXPORT_SYMBOL_GPL(v4l2_device_unregister); -- cgit v1.2.3 From 77ac583a25bcae37eff2c535fc7b3fe6a26d937e Mon Sep 17 00:00:00 2001 From: Steven Toth Date: Sat, 2 May 2009 10:07:29 -0400 Subject: tda10048: Add ability to select I/F at attach time. From: Steven Toth tda10048: Add ability to select I/F at attach time. Priority: normal Signed-off-by: Steven Toth --- linux/drivers/media/dvb/frontends/tda10048.c | 219 ++++++++++++++++++++++++++- linux/drivers/media/dvb/frontends/tda10048.h | 14 ++ 2 files changed, 232 insertions(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/frontends/tda10048.c b/linux/drivers/media/dvb/frontends/tda10048.c index cb5b1efd8..2233e649e 100644 --- a/linux/drivers/media/dvb/frontends/tda10048.c +++ b/linux/drivers/media/dvb/frontends/tda10048.c @@ -25,6 +25,7 @@ #include #include #include +#include #include "dvb_frontend.h" #include "dvb_math.h" #include "tda10048.h" @@ -143,6 +144,15 @@ struct tda10048_state { struct dvb_frontend frontend; int fwloaded; + + u32 freq_if_hz; + u32 xtal_hz; + u32 pll_mfactor; + u32 pll_nfactor; + u32 pll_pfactor; + u32 sample_freq; + + enum fe_bandwidth bandwidth; }; static struct init_tab { @@ -271,6 +281,199 @@ error: return ret; } +static int tda10048_set_phy2(struct dvb_frontend *fe, u32 sample_freq_hz, + u32 if_hz) +{ + struct tda10048_state *state = fe->demodulator_priv; + u64 t; + + dprintk(1, "%s()\n", __func__); + + if (sample_freq_hz == 0) + return -EINVAL; + + if (if_hz < (sample_freq_hz / 2)) { + /* PHY2 = (if2/fs) * 2^15 */ + t = if_hz; + t *= 10; + t *= 32768; + do_div(t, sample_freq_hz); + t += 5; + do_div(t, 10); + } else { + /* PHY2 = ((IF1-fs)/fs) * 2^15 */ + t = sample_freq_hz - if_hz; + t *= 10; + t *= 32768; + do_div(t, sample_freq_hz); + t += 5; + do_div(t, 10); + t = ~t + 1; + } + + tda10048_writereg(state, TDA10048_FREQ_PHY2_LSB, (u8)t); + tda10048_writereg(state, TDA10048_FREQ_PHY2_MSB, (u8)(t >> 8)); + + return 0; +} + +static int tda10048_set_wref(struct dvb_frontend *fe, u32 sample_freq_hz, + u32 bw) +{ + struct tda10048_state *state = fe->demodulator_priv; + u64 t, z; + u32 b = 8000000; + + dprintk(1, "%s()\n", __func__); + + if (sample_freq_hz == 0) + return -EINVAL; + + if (bw == BANDWIDTH_6_MHZ) + b = 6000000; + else + if (bw == BANDWIDTH_7_MHZ) + b = 7000000; + + /* WREF = (B / (7 * fs)) * 2^31 */ + t = b * 10; + /* avoid warning: this decimal constant is unsigned only in ISO C90 */ + /* t *= 2147483648 on 32bit platforms */ + t *= (2048 * 1024); + t *= 1024; + z = 7 * sample_freq_hz; + do_div(t, z); + t += 5; + do_div(t, 10); + + tda10048_writereg(state, TDA10048_TIME_WREF_LSB, (u8)t); + tda10048_writereg(state, TDA10048_TIME_WREF_MID1, (u8)(t >> 8)); + tda10048_writereg(state, TDA10048_TIME_WREF_MID2, (u8)(t >> 16)); + tda10048_writereg(state, TDA10048_TIME_WREF_MSB, (u8)(t >> 24)); + + return 0; +} + +static int tda10048_set_invwref(struct dvb_frontend *fe, u32 sample_freq_hz, + u32 bw) +{ + struct tda10048_state *state = fe->demodulator_priv; + u64 t; + u32 b = 8000000; + + dprintk(1, "%s()\n", __func__); + + if (sample_freq_hz == 0) + return -EINVAL; + + if (bw == BANDWIDTH_6_MHZ) + b = 6000000; + else + if (bw == BANDWIDTH_7_MHZ) + b = 7000000; + + /* INVWREF = ((7 * fs) / B) * 2^5 */ + t = sample_freq_hz; + t *= 7; + t *= 32; + t *= 10; + do_div(t, b); + t += 5; + do_div(t, 10); + + tda10048_writereg(state, TDA10048_TIME_INVWREF_LSB, (u8)t); + tda10048_writereg(state, TDA10048_TIME_INVWREF_MSB, (u8)(t >> 8)); + + return 0; +} + +static int tda10048_set_bandwidth(struct dvb_frontend *fe, + enum fe_bandwidth bw) +{ + struct tda10048_state *state = fe->demodulator_priv; + dprintk(1, "%s(bw=%d)\n", __func__, bw); + + /* Bandwidth setting may need to be adjusted */ + switch (bw) { + case BANDWIDTH_6_MHZ: + case BANDWIDTH_7_MHZ: + case BANDWIDTH_8_MHZ: + tda10048_set_wref(fe, state->sample_freq, bw); + tda10048_set_invwref(fe, state->sample_freq, bw); + break; + default: + printk(KERN_ERR "%s() invalid bandwidth\n", __func__); + return -EINVAL; + } + + state->bandwidth = bw; + + return 0; +} + +static int tda10048_set_pll(struct dvb_frontend *fe) +{ + struct tda10048_state *state = fe->demodulator_priv; + int ret = 0; + + dprintk(1, "%s()\n", __func__); + + if ((state->config->clk_freq_khz == TDA10048_CLK_4000) && + (state->config->if_freq_khz == TDA10048_IF_36130)) { + state->freq_if_hz = TDA10048_IF_36130 * 1000; + state->xtal_hz = TDA10048_CLK_4000 * 1000; + state->pll_mfactor = 10; + state->pll_nfactor = 0; + state->pll_pfactor = 0; + } else + if ((state->config->clk_freq_khz == TDA10048_CLK_16000) && + (state->config->if_freq_khz == TDA10048_IF_4300)) { + state->freq_if_hz = TDA10048_IF_4300 * 1000; + state->xtal_hz = TDA10048_CLK_16000 * 1000; + state->pll_mfactor = 10; + state->pll_nfactor = 3; + state->pll_pfactor = 0; + } else + if ((state->config->clk_freq_khz == TDA10048_CLK_16000) && + (state->config->if_freq_khz == TDA10048_IF_4000)) { + state->freq_if_hz = TDA10048_IF_4000 * 1000; + state->xtal_hz = TDA10048_CLK_16000 * 1000; + state->pll_mfactor = 10; + state->pll_nfactor = 3; + state->pll_pfactor = 0; + } else + if ((state->config->clk_freq_khz == TDA10048_CLK_16000) && + (state->config->if_freq_khz == TDA10048_IF_36130)) { + state->freq_if_hz = TDA10048_IF_36130 * 1000; + state->xtal_hz = TDA10048_CLK_16000 * 1000; + state->pll_mfactor = 10; + state->pll_nfactor = 3; + state->pll_pfactor = 0; + } else { + printk(KERN_ERR "%s() Incorrect attach settings\n", __func__); + ret = -EINVAL; + } + + dprintk(1, "- freq_if_hz = %d\n", state->freq_if_hz); + dprintk(1, "- xtal_hz = %d\n", state->xtal_hz); + dprintk(1, "- pll_mfactor = %d\n", state->pll_mfactor); + dprintk(1, "- pll_nfactor = %d\n", state->pll_nfactor); + dprintk(1, "- pll_pfactor = %d\n", state->pll_pfactor); + + /* Calculate the sample frequency */ + state->sample_freq = state->xtal_hz * (state->pll_mfactor + 45); + state->sample_freq /= (state->pll_nfactor + 1); + state->sample_freq /= (state->pll_pfactor + 4); + dprintk(1, "- sample_freq = %d\n", state->sample_freq); + + tda10048_set_phy2(fe, state->sample_freq, + state->config->if_freq_khz * 1000); + tda10048_set_wref(fe, state->sample_freq, state->bandwidth); + tda10048_set_invwref(fe, state->sample_freq, state->bandwidth); + + return ret; +} + static int tda10048_firmware_upload(struct dvb_frontend *fe) { struct tda10048_state *state = fe->demodulator_priv; @@ -523,6 +726,9 @@ static int tda10048_set_frontend(struct dvb_frontend *fe, dprintk(1, "%s(frequency=%d)\n", __func__, p->frequency); + if (p->u.ofdm.bandwidth != state->bandwidth) + tda10048_set_bandwidth(fe, p->u.ofdm.bandwidth); + if (fe->ops.tuner_ops.set_params) { if (fe->ops.i2c_gate_ctrl) @@ -558,9 +764,15 @@ static int tda10048_init(struct dvb_frontend *fe) /* Set either serial or parallel */ tda10048_output_mode(fe, state->config->output_mode); - /* set inversion */ + /* Set inversion */ tda10048_set_inversion(fe, state->config->inversion); + /* Establish default PLL values */ + tda10048_set_pll(fe); + + /* Establish default bandwidth */ + tda10048_set_bandwidth(fe, BANDWIDTH_8_MHZ); + /* Ensure we leave the gate closed */ tda10048_i2c_gate_ctrl(fe, 0); @@ -835,6 +1047,7 @@ struct dvb_frontend *tda10048_attach(const struct tda10048_config *config, state->config = config; state->i2c = i2c; state->fwloaded = 0; + state->bandwidth = BANDWIDTH_8_MHZ; /* check if the demod is present */ if (tda10048_readreg(state, TDA10048_IDENTITY) != 0x048) @@ -845,6 +1058,10 @@ struct dvb_frontend *tda10048_attach(const struct tda10048_config *config, sizeof(struct dvb_frontend_ops)); state->frontend.demodulator_priv = state; + /* Set the xtal and freq defaults */ + if (tda10048_set_pll(&state->frontend) != 0) + goto error; + /* Leave the gate closed */ tda10048_i2c_gate_ctrl(&state->frontend, 0); diff --git a/linux/drivers/media/dvb/frontends/tda10048.h b/linux/drivers/media/dvb/frontends/tda10048.h index 0457b2460..ab9cf5bd4 100644 --- a/linux/drivers/media/dvb/frontends/tda10048.h +++ b/linux/drivers/media/dvb/frontends/tda10048.h @@ -43,6 +43,20 @@ struct tda10048_config { #define TDA10048_INVERSION_OFF 0 #define TDA10048_INVERSION_ON 1 u8 inversion; + +#define TDA10048_IF_3300 3300 +#define TDA10048_IF_3500 3500 +#define TDA10048_IF_3800 3800 +#define TDA10048_IF_4000 4000 +#define TDA10048_IF_4300 4300 +#define TDA10048_IF_4500 4500 +#define TDA10048_IF_4750 4750 +#define TDA10048_IF_36130 36130 + u16 if_freq_khz; + +#define TDA10048_CLK_4000 4000 +#define TDA10048_CLK_16000 16000 + u16 clk_freq_khz; }; #if defined(CONFIG_DVB_TDA10048) || \ -- cgit v1.2.3 From 92374741385c325820e860ceeec329bab96c40e7 Mon Sep 17 00:00:00 2001 From: Steven Toth Date: Sat, 2 May 2009 10:08:23 -0400 Subject: cx23885: For tda10048 boards ensure we specify the I/F From: Steven Toth cx23885: For tda10048 boards ensure we specify the I/F Priority: normal Signed-off-by: Steven Toth --- linux/drivers/media/video/cx23885/cx23885-dvb.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/cx23885/cx23885-dvb.c b/linux/drivers/media/video/cx23885/cx23885-dvb.c index 119907f29..bad7430f1 100644 --- a/linux/drivers/media/video/cx23885/cx23885-dvb.c +++ b/linux/drivers/media/video/cx23885/cx23885-dvb.c @@ -123,7 +123,9 @@ static struct tda10048_config hauppauge_hvr1200_config = { .demod_address = 0x10 >> 1, .output_mode = TDA10048_SERIAL_OUTPUT, .fwbulkwritelen = TDA10048_BULKWRITE_200, - .inversion = TDA10048_INVERSION_ON + .inversion = TDA10048_INVERSION_ON, + .if_freq_khz = TDA10048_IF_4300, + .clk_freq_khz = TDA10048_CLK_16000, }; static struct s5h1409_config hauppauge_ezqam_config = { -- cgit v1.2.3 From 3e9d856b917d4d6e8f237885b014d299b73e6718 Mon Sep 17 00:00:00 2001 From: Steven Toth Date: Sat, 2 May 2009 10:09:08 -0400 Subject: pvrusb2: Ensure we specify the I/F at attach time. From: Steven Toth pvrusb2: Ensure we specify the I/F at attach time. Priority: normal Signed-off-by: Steven Toth --- linux/drivers/media/video/pvrusb2/pvrusb2-devattr.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-devattr.c b/linux/drivers/media/video/pvrusb2/pvrusb2-devattr.c index 1cb6a260e..76d42d92e 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-devattr.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-devattr.c @@ -284,6 +284,8 @@ static struct tda10048_config hauppauge_tda10048_config = { .output_mode = TDA10048_PARALLEL_OUTPUT, .fwbulkwritelen = TDA10048_BULKWRITE_50, .inversion = TDA10048_INVERSION_ON, + .if_freq_khz = TDA10048_IF_4300, + .clk_freq_khz = TDA10048_CLK_16000, }; static struct tda829x_config tda829x_no_probe = { -- cgit v1.2.3 From f0cdb3f5eacee30176d1371d6fde1522c69ebb5e Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 2 May 2009 16:10:23 +0200 Subject: ivtv: fix incorrect bit tests From: Hans Verkuil Found the coccinelle tool. Priority: high Signed-off-by: Hans Verkuil Thanks-to: Julia Lawall Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/ivtv/ivtv-ioctl.c | 5 +++-- linux/drivers/media/video/ivtv/ivtv-irq.c | 2 +- linux/drivers/media/video/ivtv/ivtv-yuv.c | 3 ++- linux/drivers/media/video/ivtv/ivtvfb.c | 3 ++- 4 files changed, 8 insertions(+), 5 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/ivtv/ivtv-ioctl.c b/linux/drivers/media/video/ivtv/ivtv-ioctl.c index 4a2d464f0..c342a9fe9 100644 --- a/linux/drivers/media/video/ivtv/ivtv-ioctl.c +++ b/linux/drivers/media/video/ivtv/ivtv-ioctl.c @@ -180,7 +180,7 @@ int ivtv_set_speed(struct ivtv *itv, int speed) /* Wait for any DMA to finish */ prepare_to_wait(&itv->dma_waitq, &wait, TASK_INTERRUPTIBLE); - while (itv->i_flags & IVTV_F_I_DMA) { + while (test_bit(IVTV_F_I_DMA, &itv->i_flags)) { got_sig = signal_pending(current); if (got_sig) break; @@ -1710,7 +1710,8 @@ static int ivtv_decoder_ioctls(struct file *filp, unsigned int cmd, void *arg) we are waiting unlock first and later lock again. */ mutex_unlock(&itv->serialize_lock); prepare_to_wait(&itv->event_waitq, &wait, TASK_INTERRUPTIBLE); - if ((itv->i_flags & (IVTV_F_I_EV_DEC_STOPPED|IVTV_F_I_EV_VSYNC)) == 0) + if (!test_bit(IVTV_F_I_EV_DEC_STOPPED, &itv->i_flags) && + !test_bit(IVTV_F_I_EV_VSYNC, &itv->i_flags)) schedule(); finish_wait(&itv->event_waitq, &wait); mutex_lock(&itv->serialize_lock); diff --git a/linux/drivers/media/video/ivtv/ivtv-irq.c b/linux/drivers/media/video/ivtv/ivtv-irq.c index 6dda1dd03..981171915 100644 --- a/linux/drivers/media/video/ivtv/ivtv-irq.c +++ b/linux/drivers/media/video/ivtv/ivtv-irq.c @@ -202,7 +202,7 @@ static int stream_enc_dma_append(struct ivtv_stream *s, u32 data[CX2341X_MBOX_MA bytes_needed, s->name); return -1; } - if (rc && !s->buffers_stolen && (s->s_flags & IVTV_F_S_APPL_IO)) { + if (rc && !s->buffers_stolen && test_bit(IVTV_F_S_APPL_IO, &s->s_flags)) { IVTV_WARN("All %s stream buffers are full. Dropping data.\n", s->name); IVTV_WARN("Cause: the application is not reading fast enough.\n"); } diff --git a/linux/drivers/media/video/ivtv/ivtv-yuv.c b/linux/drivers/media/video/ivtv/ivtv-yuv.c index 7912ed6b7..c0875378a 100644 --- a/linux/drivers/media/video/ivtv/ivtv-yuv.c +++ b/linux/drivers/media/video/ivtv/ivtv-yuv.c @@ -1063,7 +1063,8 @@ static int ivtv_yuv_udma_frame(struct ivtv *itv, struct ivtv_dma_frame *args) prepare_to_wait(&itv->dma_waitq, &wait, TASK_INTERRUPTIBLE); /* if no UDMA is pending and no UDMA is in progress, then the DMA is finished */ - while (itv->i_flags & (IVTV_F_I_UDMA_PENDING | IVTV_F_I_UDMA)) { + while (test_bit(IVTV_F_I_UDMA_PENDING, &itv->i_flags) || + test_bit(IVTV_F_I_UDMA, &itv->i_flags)) { /* don't interrupt if the DMA is in progress but break off a still pending DMA. */ got_sig = signal_pending(current); diff --git a/linux/drivers/media/video/ivtv/ivtvfb.c b/linux/drivers/media/video/ivtv/ivtvfb.c index a48fe216b..caa72fa4c 100644 --- a/linux/drivers/media/video/ivtv/ivtvfb.c +++ b/linux/drivers/media/video/ivtv/ivtvfb.c @@ -298,7 +298,8 @@ static int ivtvfb_prep_dec_dma_to_device(struct ivtv *itv, prepare_to_wait(&itv->dma_waitq, &wait, TASK_INTERRUPTIBLE); /* if no UDMA is pending and no UDMA is in progress, then the DMA is finished */ - while (itv->i_flags & (IVTV_F_I_UDMA_PENDING | IVTV_F_I_UDMA)) { + while (test_bit(IVTV_F_I_UDMA_PENDING, &itv->i_flags) || + test_bit(IVTV_F_I_UDMA, &itv->i_flags)) { /* don't interrupt if the DMA is in progress but break off a still pending DMA. */ got_sig = signal_pending(current); -- cgit v1.2.3 From 36600a08afc4d3e85ae44cf92fb494933b003bb9 Mon Sep 17 00:00:00 2001 From: Steven Toth Date: Sat, 2 May 2009 10:29:50 -0400 Subject: cx23885: Add generic functions for driving GPIO's From: Steven Toth The GPIO's on the product can be in one of three places. To date we've mainly used the GPIO's on the bridge itself, and once on the encoder. Rather than having the complexity of multiple GPIO writes/reads from isolated placed in the driver we'll route them through this function, so we can make intelligent decisions about 1) Where the GPIO lives and 2) Whether it conflicts (based on board) with some other function to avoid bugs. Priority: normal Signed-off-by: Steven Toth Signed-off-by: Michael Krufky --- linux/drivers/media/video/cx23885/cx23885-core.c | 82 ++++++++++++++++++++++++ linux/drivers/media/video/cx23885/cx23885.h | 16 +++++ 2 files changed, 98 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/cx23885/cx23885-core.c b/linux/drivers/media/video/cx23885/cx23885-core.c index 48f777b99..7ae527a6b 100644 --- a/linux/drivers/media/video/cx23885/cx23885-core.c +++ b/linux/drivers/media/video/cx23885/cx23885-core.c @@ -1744,6 +1744,88 @@ out: return IRQ_RETVAL(handled); } +int encoder_on_portb(struct cx23885_dev *dev) +{ + return cx23885_boards[dev->board].portb == CX23885_MPEG_ENCODER; +} + +int encoder_on_portc(struct cx23885_dev *dev) +{ + return cx23885_boards[dev->board].portc == CX23885_MPEG_ENCODER; +} + +/* Mask represents 32 different GPIOs, GPIO's are split into multiple + * registers depending on the board configuration (and whether the + * 417 encoder (wi it's own GPIO's) are present. Each GPIO bit will + * be pushed into the correct hardware register, regardless of the + * physical location. Certain registers are shared so we sanity check + * and report errors if we think we're tampering with a GPIo that might + * be assigned to the encoder (and used for the host bus). + * + * GPIO 2 thru 0 - On the cx23885 bridge + * GPIO 18 thru 3 - On the cx23417 host bus interface + * GPIO 23 thru 19 - On the cx25840 a/v core + */ +void cx23885_gpio_set(struct cx23885_dev *dev, u32 mask) +{ + if (mask & 0x7) + cx_set(GP0_IO, mask & 0x7); + + if (mask & 0x0007fff8) { + if (encoder_on_portb(dev) || encoder_on_portc(dev)) + printk(KERN_ERR + "%s: Setting GPIO on encoder ports\n", + dev->name); + cx_set(MC417_RWD, (mask & 0x0007fff8) >> 3); + } + + /* TODO: 23-19 */ + if (mask & 0x00f80000) + printk(KERN_INFO "%s: Unsupported\n", dev->name); +} + +void cx23885_gpio_clear(struct cx23885_dev *dev, u32 mask) +{ + if (mask & 0x00000007) + cx_clear(GP0_IO, mask & 0x7); + + if (mask & 0x0007fff8) { + if (encoder_on_portb(dev) || encoder_on_portc(dev)) + printk(KERN_ERR + "%s: Clearing GPIO moving on encoder ports\n", + dev->name); + cx_clear(MC417_RWD, (mask & 0x7fff8) >> 3); + } + + /* TODO: 23-19 */ + if (mask & 0x00f80000) + printk(KERN_INFO "%s: Unsupported\n", dev->name); +} + +void cx23885_gpio_enable(struct cx23885_dev *dev, u32 mask, int asoutput) +{ + if ((mask & 0x00000007) && asoutput) + cx_set(GP0_IO, (mask & 0x7) << 16); + else if ((mask & 0x00000007) && !asoutput) + cx_clear(GP0_IO, (mask & 0x7) << 16); + + if (mask & 0x0007fff8) { + if (encoder_on_portb(dev) || encoder_on_portc(dev)) + printk(KERN_ERR + "%s: Enabling GPIO on encoder ports\n", + dev->name); + } + + /* MC417_OEN is active low for output, write 1 for an input */ + if ((mask & 0x0007fff8) && asoutput) + cx_clear(MC417_OEN, (mask & 0x7fff8) >> 3); + + else if ((mask & 0x0007fff8) && !asoutput) + cx_set(MC417_OEN, (mask & 0x7fff8) >> 3); + + /* TODO: 23-19 */ +} + static int __devinit cx23885_initdev(struct pci_dev *pci_dev, const struct pci_device_id *pci_id) { diff --git a/linux/drivers/media/video/cx23885/cx23885.h b/linux/drivers/media/video/cx23885/cx23885.h index 92828c9ce..4bc38d47d 100644 --- a/linux/drivers/media/video/cx23885/cx23885.h +++ b/linux/drivers/media/video/cx23885/cx23885.h @@ -73,6 +73,17 @@ #define CX23885_BOARD_DVBWORLD_2005 16 #define CX23885_BOARD_NETUP_DUAL_DVBS2_CI 17 +#define GPIO_0 0x00000001 +#define GPIO_1 0x00000002 +#define GPIO_2 0x00000004 +#define GPIO_3 0x00000008 +#define GPIO_4 0x00000010 +#define GPIO_5 0x00000020 +#define GPIO_6 0x00000040 +#define GPIO_7 0x00000080 +#define GPIO_8 0x00000100 +#define GPIO_9 0x00000200 + /* Currently unsupported by the driver: PAL/H, NTSC/Kr, SECAM B/G/H/LC */ #define CX23885_NORMS (\ V4L2_STD_NTSC_M | V4L2_STD_NTSC_M_JP | V4L2_STD_NTSC_443 | \ @@ -423,6 +434,11 @@ extern int cx23885_restart_queue(struct cx23885_tsport *port, extern void cx23885_wakeup(struct cx23885_tsport *port, struct cx23885_dmaqueue *q, u32 count); +extern void cx23885_gpio_set(struct cx23885_dev *dev, u32 mask); +extern void cx23885_gpio_clear(struct cx23885_dev *dev, u32 mask); +extern void cx23885_gpio_enable(struct cx23885_dev *dev, u32 mask, + int asoutput); + /* ----------------------------------------------------------- */ /* cx23885-cards.c */ -- cgit v1.2.3 From 38b8ac708c45ac944c7a69638d9b4afe73717849 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Mon, 11 May 2009 12:37:26 -0400 Subject: cx23885: mark functions encoder_on_port[bc] as static inline From: Michael Krufky Priority: normal Signed-off-by: Michael Krufky --- linux/drivers/media/video/cx23885/cx23885-core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/cx23885/cx23885-core.c b/linux/drivers/media/video/cx23885/cx23885-core.c index 7ae527a6b..6988361c9 100644 --- a/linux/drivers/media/video/cx23885/cx23885-core.c +++ b/linux/drivers/media/video/cx23885/cx23885-core.c @@ -1744,12 +1744,12 @@ out: return IRQ_RETVAL(handled); } -int encoder_on_portb(struct cx23885_dev *dev) +static inline int encoder_on_portb(struct cx23885_dev *dev) { return cx23885_boards[dev->board].portb == CX23885_MPEG_ENCODER; } -int encoder_on_portc(struct cx23885_dev *dev) +static inline int encoder_on_portc(struct cx23885_dev *dev) { return cx23885_boards[dev->board].portc == CX23885_MPEG_ENCODER; } -- cgit v1.2.3 From d72082806f7688e66f823051fe7bc4f62acca533 Mon Sep 17 00:00:00 2001 From: Steven Toth Date: Sat, 2 May 2009 10:39:46 -0400 Subject: cx23885: Add preliminary support for the HVR1270 From: Steven Toth The patch means the board will be recognised, and the parts brought out of reset correctly. This patches depends on the centralized GPIO patch to be merged. What's missing before the HVR-1270 will function for DTV? The model# needs to be added to avoid 'unknown model' output and the LG3305/Tuner need to be attached in cx23885-dvb.c Priority: normal Signed-off-by: Steven Toth Signed-off-by: Michael Krufky --- linux/drivers/media/video/cx23885/cx23885-cards.c | 21 +++++++++++++++++++++ linux/drivers/media/video/cx23885/cx23885.h | 1 + 2 files changed, 22 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/cx23885/cx23885-cards.c b/linux/drivers/media/video/cx23885/cx23885-cards.c index 28f305dfd..bd608b4a0 100644 --- a/linux/drivers/media/video/cx23885/cx23885-cards.c +++ b/linux/drivers/media/video/cx23885/cx23885-cards.c @@ -182,6 +182,9 @@ struct cx23885_board cx23885_boards[] = { .portb = CX23885_MPEG_DVB, .portc = CX23885_MPEG_DVB, }, + [CX23885_BOARD_HAUPPAUGE_HVR1270] = { + .name = "Hauppauge WinTV-HVR1270", + }, }; const unsigned int cx23885_bcount = ARRAY_SIZE(cx23885_boards); @@ -281,6 +284,10 @@ struct cx23885_subid cx23885_subids[] = { .subvendor = 0x1b55, .subdevice = 0x2a2c, .card = CX23885_BOARD_NETUP_DUAL_DVBS2_CI, + }, { + .subvendor = 0x0070, + .subdevice = 0x2211, + .card = CX23885_BOARD_HAUPPAUGE_HVR1270, }, }; const unsigned int cx23885_idcount = ARRAY_SIZE(cx23885_subids); @@ -620,6 +627,17 @@ void cx23885_gpio_setup(struct cx23885_dev *dev) /* enable irq */ cx_write(GPIO_ISM, 0x00000000);/* INTERRUPTS active low*/ break; + case CX23885_BOARD_HAUPPAUGE_HVR1270: + /* GPIO-6 I2C Gate which can isolate the 3305 from the bus */ + /* GPIO-9 LG3305 reset */ + + /* Put the parts into reset and back */ + cx23885_gpio_enable(dev, GPIO_9 | GPIO_6, 1); + cx23885_gpio_set(dev, GPIO_9 | GPIO_6); + cx23885_gpio_clear(dev, GPIO_9); + mdelay(20); + cx23885_gpio_set(dev, GPIO_9); + break; } } @@ -632,6 +650,7 @@ int cx23885_ir_init(struct cx23885_dev *dev) case CX23885_BOARD_HAUPPAUGE_HVR1800: case CX23885_BOARD_HAUPPAUGE_HVR1200: case CX23885_BOARD_HAUPPAUGE_HVR1400: + case CX23885_BOARD_HAUPPAUGE_HVR1270: /* FIXME: Implement me */ break; case CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP: @@ -667,6 +686,7 @@ void cx23885_card_setup(struct cx23885_dev *dev) case CX23885_BOARD_HAUPPAUGE_HVR1800lp: case CX23885_BOARD_HAUPPAUGE_HVR1200: case CX23885_BOARD_HAUPPAUGE_HVR1700: + case CX23885_BOARD_HAUPPAUGE_HVR1270: if (dev->i2c_bus[0].i2c_rc == 0) hauppauge_eeprom(dev, eeprom+0xc0); break; @@ -724,6 +744,7 @@ void cx23885_card_setup(struct cx23885_dev *dev) case CX23885_BOARD_HAUPPAUGE_HVR1400: case CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H: case CX23885_BOARD_COMPRO_VIDEOMATE_E650F: + case CX23885_BOARD_HAUPPAUGE_HVR1270: default: ts2->gen_ctrl_val = 0xc; /* Serial bus + punctured clock */ ts2->ts_clk_en_val = 0x1; /* Enable TS_CLK */ diff --git a/linux/drivers/media/video/cx23885/cx23885.h b/linux/drivers/media/video/cx23885/cx23885.h index 4bc38d47d..21d886212 100644 --- a/linux/drivers/media/video/cx23885/cx23885.h +++ b/linux/drivers/media/video/cx23885/cx23885.h @@ -72,6 +72,7 @@ #define CX23885_BOARD_TEVII_S470 15 #define CX23885_BOARD_DVBWORLD_2005 16 #define CX23885_BOARD_NETUP_DUAL_DVBS2_CI 17 +#define CX23885_BOARD_HAUPPAUGE_HVR1270 18 #define GPIO_0 0x00000001 #define GPIO_1 0x00000002 -- cgit v1.2.3 From 9bea37bb76e87851bed1ecdc99f6d3f0e51dc50b Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 2 May 2009 16:52:35 +0200 Subject: ivtv/radio: fix V4L2_TUNER_MODE/V4L2_TUNER_SUB confusion From: Hans Verkuil V4L2_TUNER_MODE_ was used in a few places where V4L2_TUNER_SUB_ should have been used. Priority: high Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/radio/radio-sf16fmi.c | 2 +- linux/drivers/media/radio/radio-sf16fmr2.c | 2 +- linux/drivers/media/video/ivtv/ivtv-gpio.c | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/radio/radio-sf16fmi.c b/linux/drivers/media/radio/radio-sf16fmi.c index ae2b3e6a1..f84d332c7 100644 --- a/linux/drivers/media/radio/radio-sf16fmi.c +++ b/linux/drivers/media/radio/radio-sf16fmi.c @@ -154,7 +154,7 @@ static int vidioc_g_tuner(struct file *file, void *priv, mult = (fmi->flags & V4L2_TUNER_CAP_LOW) ? 1 : 1000; v->rangelow = RSF16_MINFREQ / mult; v->rangehigh = RSF16_MAXFREQ / mult; - v->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_MODE_STEREO; + v->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO; v->capability = fmi->flags & V4L2_TUNER_CAP_LOW; v->audmode = V4L2_TUNER_MODE_STEREO; v->signal = fmi_getsigstr(fmi); diff --git a/linux/drivers/media/radio/radio-sf16fmr2.c b/linux/drivers/media/radio/radio-sf16fmr2.c index bb92b329c..85cafe401 100644 --- a/linux/drivers/media/radio/radio-sf16fmr2.c +++ b/linux/drivers/media/radio/radio-sf16fmr2.c @@ -234,7 +234,7 @@ static int vidioc_g_tuner(struct file *file, void *priv, mult = (fmr2->flags & V4L2_TUNER_CAP_LOW) ? 1 : 1000; v->rangelow = RSF16_MINFREQ / mult; v->rangehigh = RSF16_MAXFREQ / mult; - v->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_MODE_STEREO; + v->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO; v->capability = fmr2->flags&V4L2_TUNER_CAP_LOW; v->audmode = fmr2->stereo ? V4L2_TUNER_MODE_STEREO: V4L2_TUNER_MODE_MONO; diff --git a/linux/drivers/media/video/ivtv/ivtv-gpio.c b/linux/drivers/media/video/ivtv/ivtv-gpio.c index ceb05bdca..85ac70722 100644 --- a/linux/drivers/media/video/ivtv/ivtv-gpio.c +++ b/linux/drivers/media/video/ivtv/ivtv-gpio.c @@ -190,8 +190,8 @@ static int subdev_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt) mask = itv->card->gpio_audio_detect.mask; if (mask == 0 || (read_reg(IVTV_REG_GPIO_IN) & mask)) - vt->rxsubchans = V4L2_TUNER_MODE_STEREO | - V4L2_TUNER_MODE_LANG1 | V4L2_TUNER_MODE_LANG2; + vt->rxsubchans = V4L2_TUNER_SUB_STEREO | + V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2; else vt->rxsubchans = V4L2_TUNER_SUB_MONO; return 0; -- cgit v1.2.3 From 404ec5697df745366ea8fb28146e2737b31d2059 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 2 May 2009 17:04:13 +0200 Subject: radio-fm16: cleanups From: Hans Verkuil Remove bogus flags field Priority: normal Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/radio/radio-sf16fmi.c | 16 ++++------------ linux/drivers/media/radio/radio-sf16fmr2.c | 16 ++++------------ 2 files changed, 8 insertions(+), 24 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/radio/radio-sf16fmi.c b/linux/drivers/media/radio/radio-sf16fmi.c index f84d332c7..fc406103b 100644 --- a/linux/drivers/media/radio/radio-sf16fmi.c +++ b/linux/drivers/media/radio/radio-sf16fmi.c @@ -50,7 +50,6 @@ struct fmi int io; int curvol; /* 1 or 0 */ unsigned long curfreq; /* freq in kHz */ - __u32 flags; struct mutex lock; }; @@ -58,7 +57,7 @@ static struct fmi fmi_card; static struct pnp_dev *dev; /* freq is in 1/16 kHz to internal number, hw precision is 50 kHz */ -/* It is only useful to give freq in intervall of 800 (=0.05Mhz), +/* It is only useful to give freq in interval of 800 (=0.05Mhz), * other bits will be truncated, e.g 92.7400016 -> 92.7, but * 92.7400017 -> 92.75 */ @@ -143,7 +142,6 @@ static int vidioc_querycap(struct file *file, void *priv, static int vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *v) { - int mult; struct fmi *fmi = video_drvdata(file); if (v->index > 0) @@ -151,11 +149,10 @@ static int vidioc_g_tuner(struct file *file, void *priv, strlcpy(v->name, "FM", sizeof(v->name)); v->type = V4L2_TUNER_RADIO; - mult = (fmi->flags & V4L2_TUNER_CAP_LOW) ? 1 : 1000; - v->rangelow = RSF16_MINFREQ / mult; - v->rangehigh = RSF16_MAXFREQ / mult; + v->rangelow = RSF16_MINFREQ; + v->rangehigh = RSF16_MAXFREQ; v->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO; - v->capability = fmi->flags & V4L2_TUNER_CAP_LOW; + v->capability = V4L2_TUNER_CAP_LOW; v->audmode = V4L2_TUNER_MODE_STEREO; v->signal = fmi_getsigstr(fmi); return 0; @@ -172,8 +169,6 @@ static int vidioc_s_frequency(struct file *file, void *priv, { struct fmi *fmi = video_drvdata(file); - if (!(fmi->flags & V4L2_TUNER_CAP_LOW)) - f->frequency *= 1000; if (f->frequency < RSF16_MINFREQ || f->frequency > RSF16_MAXFREQ) return -EINVAL; @@ -190,8 +185,6 @@ static int vidioc_g_frequency(struct file *file, void *priv, f->type = V4L2_TUNER_RADIO; f->frequency = fmi->curfreq; - if (!(fmi->flags & V4L2_TUNER_CAP_LOW)) - f->frequency /= 1000; return 0; } @@ -348,7 +341,6 @@ static int __init fmi_init(void) return res; } - fmi->flags = V4L2_TUNER_CAP_LOW; strlcpy(fmi->vdev.name, v4l2_dev->name, sizeof(fmi->vdev.name)); fmi->vdev.v4l2_dev = v4l2_dev; fmi->vdev.fops = &fmi_fops; diff --git a/linux/drivers/media/radio/radio-sf16fmr2.c b/linux/drivers/media/radio/radio-sf16fmr2.c index 85cafe401..3a10f718a 100644 --- a/linux/drivers/media/radio/radio-sf16fmr2.c +++ b/linux/drivers/media/radio/radio-sf16fmr2.c @@ -62,13 +62,12 @@ struct fmr2 int stereo; /* card is producing stereo audio */ unsigned long curfreq; /* freq in kHz */ int card_type; - u32 flags; }; static struct fmr2 fmr2_card; /* hw precision is 12.5 kHz - * It is only useful to give freq in intervall of 200 (=0.0125Mhz), + * It is only useful to give freq in interval of 200 (=0.0125Mhz), * other bits will be truncated */ #define RSF16_ENCODE(x) ((x) / 200 + 856) @@ -222,7 +221,6 @@ static int vidioc_querycap(struct file *file, void *priv, static int vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *v) { - int mult; struct fmr2 *fmr2 = video_drvdata(file); if (v->index > 0) @@ -231,11 +229,10 @@ static int vidioc_g_tuner(struct file *file, void *priv, strlcpy(v->name, "FM", sizeof(v->name)); v->type = V4L2_TUNER_RADIO; - mult = (fmr2->flags & V4L2_TUNER_CAP_LOW) ? 1 : 1000; - v->rangelow = RSF16_MINFREQ / mult; - v->rangehigh = RSF16_MAXFREQ / mult; + v->rangelow = RSF16_MINFREQ; + v->rangehigh = RSF16_MAXFREQ; v->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO; - v->capability = fmr2->flags&V4L2_TUNER_CAP_LOW; + v->capability = V4L2_TUNER_CAP_LOW; v->audmode = fmr2->stereo ? V4L2_TUNER_MODE_STEREO: V4L2_TUNER_MODE_MONO; mutex_lock(&fmr2->lock); @@ -255,8 +252,6 @@ static int vidioc_s_frequency(struct file *file, void *priv, { struct fmr2 *fmr2 = video_drvdata(file); - if (!(fmr2->flags & V4L2_TUNER_CAP_LOW)) - f->frequency *= 1000; if (f->frequency < RSF16_MINFREQ || f->frequency > RSF16_MAXFREQ) return -EINVAL; @@ -280,8 +275,6 @@ static int vidioc_g_frequency(struct file *file, void *priv, f->type = V4L2_TUNER_RADIO; f->frequency = fmr2->curfreq; - if (!(fmr2->flags & V4L2_TUNER_CAP_LOW)) - f->frequency /= 1000; return 0; } @@ -407,7 +400,6 @@ static int __init fmr2_init(void) strlcpy(v4l2_dev->name, "sf16fmr2", sizeof(v4l2_dev->name)); fmr2->io = io; fmr2->stereo = 1; - fmr2->flags = V4L2_TUNER_CAP_LOW; mutex_init(&fmr2->lock); if (!request_region(fmr2->io, 2, "sf16fmr2")) { -- cgit v1.2.3 From 3c03639d1d631911524bd4be8500155de4809b20 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 2 May 2009 17:06:15 +0200 Subject: radio-fm16: fix g_tuner. From: Hans Verkuil g_tuner handled capability, audmode and rxsubchans incorrectly. Priority: normal Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/radio/radio-sf16fmi.c | 2 +- linux/drivers/media/radio/radio-sf16fmr2.c | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/radio/radio-sf16fmi.c b/linux/drivers/media/radio/radio-sf16fmi.c index fc406103b..891617ee1 100644 --- a/linux/drivers/media/radio/radio-sf16fmi.c +++ b/linux/drivers/media/radio/radio-sf16fmi.c @@ -152,7 +152,7 @@ static int vidioc_g_tuner(struct file *file, void *priv, v->rangelow = RSF16_MINFREQ; v->rangehigh = RSF16_MAXFREQ; v->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO; - v->capability = V4L2_TUNER_CAP_LOW; + v->capability = V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_LOW; v->audmode = V4L2_TUNER_MODE_STEREO; v->signal = fmi_getsigstr(fmi); return 0; diff --git a/linux/drivers/media/radio/radio-sf16fmr2.c b/linux/drivers/media/radio/radio-sf16fmr2.c index 3a10f718a..df8c10a50 100644 --- a/linux/drivers/media/radio/radio-sf16fmr2.c +++ b/linux/drivers/media/radio/radio-sf16fmr2.c @@ -231,10 +231,10 @@ static int vidioc_g_tuner(struct file *file, void *priv, v->rangelow = RSF16_MINFREQ; v->rangehigh = RSF16_MAXFREQ; - v->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO; - v->capability = V4L2_TUNER_CAP_LOW; - v->audmode = fmr2->stereo ? V4L2_TUNER_MODE_STEREO: - V4L2_TUNER_MODE_MONO; + v->rxsubchans = fmr2->stereo ? V4L2_TUNER_SUB_STEREO : + V4L2_TUNER_SUB_MONO; + v->capability = V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_LOW; + v->audmode = V4L2_TUNER_MODE_STEREO; mutex_lock(&fmr2->lock); v->signal = fmr2_getsigstr(fmr2); mutex_unlock(&fmr2->lock); -- cgit v1.2.3 From b6846f8378e51e39a605b395c560986011bde203 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 2 May 2009 19:38:47 +0000 Subject: V4L/DVB: cleanup redundant tests on unsigned From: Roel Kluin Remove redundant tests on unsigned. Signed-off-by: Roel Kluin Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/ttpci/av7110_v4l.c | 2 +- linux/drivers/media/dvb/ttpci/budget-av.c | 2 +- linux/drivers/media/video/cpia2/cpia2_v4l.c | 6 +++--- linux/drivers/media/video/hexium_gemini.c | 2 +- linux/drivers/media/video/hexium_orion.c | 2 +- linux/drivers/media/video/ivtv/ivtv-ioctl.c | 2 +- linux/drivers/media/video/mxb.c | 4 ++-- linux/drivers/media/video/pvrusb2/pvrusb2-v4l2.c | 4 ++-- linux/drivers/media/video/pwc/pwc-v4l.c | 2 +- linux/drivers/media/video/stk-webcam.c | 4 ++-- linux/drivers/media/video/usbvision/usbvision-video.c | 2 +- linux/drivers/media/video/videobuf-core.c | 4 ++-- 12 files changed, 18 insertions(+), 18 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/ttpci/av7110_v4l.c b/linux/drivers/media/dvb/ttpci/av7110_v4l.c index 2210cff73..ce64c6214 100644 --- a/linux/drivers/media/dvb/ttpci/av7110_v4l.c +++ b/linux/drivers/media/dvb/ttpci/av7110_v4l.c @@ -458,7 +458,7 @@ static int vidioc_enum_input(struct file *file, void *fh, struct v4l2_input *i) dprintk(2, "VIDIOC_ENUMINPUT: %d\n", i->index); if (av7110->analog_tuner_flags) { - if (i->index < 0 || i->index >= 4) + if (i->index >= 4) return -EINVAL; } else { if (i->index != 0) diff --git a/linux/drivers/media/dvb/ttpci/budget-av.c b/linux/drivers/media/dvb/ttpci/budget-av.c index 855fe74b6..8ea915227 100644 --- a/linux/drivers/media/dvb/ttpci/budget-av.c +++ b/linux/drivers/media/dvb/ttpci/budget-av.c @@ -1413,7 +1413,7 @@ static struct v4l2_input knc1_inputs[KNC1_INPUTS] = { static int vidioc_enum_input(struct file *file, void *fh, struct v4l2_input *i) { dprintk(1, "VIDIOC_ENUMINPUT %d.\n", i->index); - if (i->index < 0 || i->index >= KNC1_INPUTS) + if (i->index >= KNC1_INPUTS) return -EINVAL; memcpy(i, &knc1_inputs[i->index], sizeof(struct v4l2_input)); return 0; diff --git a/linux/drivers/media/video/cpia2/cpia2_v4l.c b/linux/drivers/media/video/cpia2/cpia2_v4l.c index d4099f531..0b4a8f309 100644 --- a/linux/drivers/media/video/cpia2/cpia2_v4l.c +++ b/linux/drivers/media/video/cpia2/cpia2_v4l.c @@ -1064,7 +1064,7 @@ static int ioctl_querymenu(void *arg,struct camera_data *cam) switch(m->id) { case CPIA2_CID_FLICKER_MODE: - if(m->index < 0 || m->index >= NUM_FLICKER_CONTROLS) + if (m->index >= NUM_FLICKER_CONTROLS) return -EINVAL; strcpy(m->name, flicker_controls[m->index].name); @@ -1082,14 +1082,14 @@ static int ioctl_querymenu(void *arg,struct camera_data *cam) maximum = i; } } - if(m->index < 0 || m->index > maximum) + if (m->index > maximum) return -EINVAL; strcpy(m->name, framerate_controls[m->index].name); break; } case CPIA2_CID_LIGHTS: - if(m->index < 0 || m->index >= NUM_LIGHTS_CONTROLS) + if (m->index >= NUM_LIGHTS_CONTROLS) return -EINVAL; strcpy(m->name, lights_controls[m->index].name); diff --git a/linux/drivers/media/video/hexium_gemini.c b/linux/drivers/media/video/hexium_gemini.c index bcd8144c5..e7dc0aa61 100644 --- a/linux/drivers/media/video/hexium_gemini.c +++ b/linux/drivers/media/video/hexium_gemini.c @@ -225,7 +225,7 @@ static int vidioc_enum_input(struct file *file, void *fh, struct v4l2_input *i) { DEB_EE(("VIDIOC_ENUMINPUT %d.\n", i->index)); - if (i->index < 0 || i->index >= HEXIUM_INPUTS) + if (i->index >= HEXIUM_INPUTS) return -EINVAL; memcpy(i, &hexium_inputs[i->index], sizeof(struct v4l2_input)); diff --git a/linux/drivers/media/video/hexium_orion.c b/linux/drivers/media/video/hexium_orion.c index 4178edcc2..d559c0e0c 100644 --- a/linux/drivers/media/video/hexium_orion.c +++ b/linux/drivers/media/video/hexium_orion.c @@ -326,7 +326,7 @@ static int vidioc_enum_input(struct file *file, void *fh, struct v4l2_input *i) { DEB_EE(("VIDIOC_ENUMINPUT %d.\n", i->index)); - if (i->index < 0 || i->index >= HEXIUM_INPUTS) + if (i->index >= HEXIUM_INPUTS) return -EINVAL; memcpy(i, &hexium_inputs[i->index], sizeof(struct v4l2_input)); diff --git a/linux/drivers/media/video/ivtv/ivtv-ioctl.c b/linux/drivers/media/video/ivtv/ivtv-ioctl.c index c342a9fe9..99f3c39a1 100644 --- a/linux/drivers/media/video/ivtv/ivtv-ioctl.c +++ b/linux/drivers/media/video/ivtv/ivtv-ioctl.c @@ -709,7 +709,7 @@ static int ivtv_itvc(struct ivtv *itv, unsigned int cmd, void *arg) else if (itv->has_cx23415 && regs->reg >= IVTV_DECODER_OFFSET && regs->reg < IVTV_DECODER_OFFSET + IVTV_DECODER_SIZE) reg_start = itv->dec_mem - IVTV_DECODER_OFFSET; - else if (regs->reg >= 0 && regs->reg < IVTV_ENCODER_SIZE) + else if (regs->reg < IVTV_ENCODER_SIZE) reg_start = itv->enc_mem; else return -EINVAL; diff --git a/linux/drivers/media/video/mxb.c b/linux/drivers/media/video/mxb.c index 4a50c0e95..411efcd34 100644 --- a/linux/drivers/media/video/mxb.c +++ b/linux/drivers/media/video/mxb.c @@ -457,7 +457,7 @@ static int vidioc_s_ctrl(struct file *file, void *fh, struct v4l2_control *vc) static int vidioc_enum_input(struct file *file, void *fh, struct v4l2_input *i) { DEB_EE(("VIDIOC_ENUMINPUT %d.\n", i->index)); - if (i->index < 0 || i->index >= MXB_INPUTS) + if (i->index >= MXB_INPUTS) return -EINVAL; memcpy(i, &mxb_inputs[i->index], sizeof(struct v4l2_input)); return 0; @@ -620,7 +620,7 @@ static int vidioc_g_audio(struct file *file, void *fh, struct v4l2_audio *a) struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev; struct mxb *mxb = (struct mxb *)dev->ext_priv; - if (a->index < 0 || a->index > MXB_INPUTS) { + if (a->index > MXB_INPUTS) { DEB_D(("VIDIOC_G_AUDIO %d out of range.\n", a->index)); return -EINVAL; } diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-v4l2.c b/linux/drivers/media/video/pvrusb2/pvrusb2-v4l2.c index c7fc605f8..11deb1ae1 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-v4l2.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-v4l2.c @@ -268,7 +268,7 @@ static long pvr2_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) memset(&tmp,0,sizeof(tmp)); tmp.index = vi->index; ret = 0; - if ((vi->index < 0) || (vi->index >= fh->input_cnt)) { + if (vi->index >= fh->input_cnt) { ret = -EINVAL; break; } @@ -332,7 +332,7 @@ static long pvr2_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) case VIDIOC_S_INPUT: { struct v4l2_input *vi = (struct v4l2_input *)arg; - if ((vi->index < 0) || (vi->index >= fh->input_cnt)) { + if (vi->index >= fh->input_cnt) { ret = -ERANGE; break; } diff --git a/linux/drivers/media/video/pwc/pwc-v4l.c b/linux/drivers/media/video/pwc/pwc-v4l.c index bc0a46429..2876ce084 100644 --- a/linux/drivers/media/video/pwc/pwc-v4l.c +++ b/linux/drivers/media/video/pwc/pwc-v4l.c @@ -1107,7 +1107,7 @@ long pwc_video_do_ioctl(struct file *file, unsigned int cmd, void *arg) return -EINVAL; if (buf->memory != V4L2_MEMORY_MMAP) return -EINVAL; - if (buf->index < 0 || buf->index >= pwc_mbufs) + if (buf->index >= pwc_mbufs) return -EINVAL; buf->flags |= V4L2_BUF_FLAG_QUEUED; diff --git a/linux/drivers/media/video/stk-webcam.c b/linux/drivers/media/video/stk-webcam.c index 7cbc4f736..886caf736 100644 --- a/linux/drivers/media/video/stk-webcam.c +++ b/linux/drivers/media/video/stk-webcam.c @@ -1138,7 +1138,7 @@ static int stk_vidioc_querybuf(struct file *filp, struct stk_camera *dev = priv; struct stk_sio_buffer *sbuf; - if (buf->index < 0 || buf->index >= dev->n_sbufs) + if (buf->index >= dev->n_sbufs) return -EINVAL; sbuf = dev->sio_bufs + buf->index; *buf = sbuf->v4lbuf; @@ -1155,7 +1155,7 @@ static int stk_vidioc_qbuf(struct file *filp, if (buf->memory != V4L2_MEMORY_MMAP) return -EINVAL; - if (buf->index < 0 || buf->index >= dev->n_sbufs) + if (buf->index >= dev->n_sbufs) return -EINVAL; sbuf = dev->sio_bufs + buf->index; if (sbuf->v4lbuf.flags & V4L2_BUF_FLAG_QUEUED) diff --git a/linux/drivers/media/video/usbvision/usbvision-video.c b/linux/drivers/media/video/usbvision/usbvision-video.c index d7056a5b7..d03e5922d 100644 --- a/linux/drivers/media/video/usbvision/usbvision-video.c +++ b/linux/drivers/media/video/usbvision/usbvision-video.c @@ -541,7 +541,7 @@ static int vidioc_enum_input (struct file *file, void *priv, struct usb_usbvision *usbvision = video_drvdata(file); int chan; - if ((vi->index >= usbvision->video_inputs) || (vi->index < 0) ) + if (vi->index >= usbvision->video_inputs) return -EINVAL; if (usbvision->have_tuner) { chan = vi->index; diff --git a/linux/drivers/media/video/videobuf-core.c b/linux/drivers/media/video/videobuf-core.c index 972f09836..e9696385d 100644 --- a/linux/drivers/media/video/videobuf-core.c +++ b/linux/drivers/media/video/videobuf-core.c @@ -456,7 +456,7 @@ int videobuf_querybuf(struct videobuf_queue *q, struct v4l2_buffer *b) dprintk(1, "querybuf: Wrong type.\n"); goto done; } - if (unlikely(b->index < 0 || b->index >= VIDEO_MAX_FRAME)) { + if (unlikely(b->index >= VIDEO_MAX_FRAME)) { dprintk(1, "querybuf: index out of range.\n"); goto done; } @@ -497,7 +497,7 @@ int videobuf_qbuf(struct videobuf_queue *q, dprintk(1, "qbuf: Wrong type.\n"); goto done; } - if (b->index < 0 || b->index >= VIDEO_MAX_FRAME) { + if (b->index >= VIDEO_MAX_FRAME) { dprintk(1, "qbuf: index out of range.\n"); goto done; } -- cgit v1.2.3 From 92d86489f12a97b91898eaffecc71667b5c1c58f Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 2 May 2009 20:52:52 +0000 Subject: zoran: Fix &&/|| typo From: Roel Kluin Fix &&/|| typo Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/zoran/zoran_card.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/zoran/zoran_card.c b/linux/drivers/media/video/zoran/zoran_card.c index 733db7690..67ab10878 100644 --- a/linux/drivers/media/video/zoran/zoran_card.c +++ b/linux/drivers/media/video/zoran/zoran_card.c @@ -1023,7 +1023,7 @@ zr36057_init (struct zoran *zr) zr->vbuf_bytesperline = 0; /* Avoid nonsense settings from user for default input/norm */ - if (default_norm < 0 && default_norm > 2) + if (default_norm < 0 || default_norm > 2) default_norm = 0; if (default_norm == 0) { zr->norm = V4L2_STD_PAL; -- cgit v1.2.3 From 3d2b4c935e8804f2ed232614079f41ab6360aad2 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Sun, 3 May 2009 01:26:58 +0400 Subject: STV0900/STV0903: 1. Support Silicon Cut >= 3.0 2. Remove support for obsolete cuts: 1.0. 1.1. 1.2 3. Try to catch more error cases Driver doesn't now attach to obsolete silcon cuts, It just simply quits. Results in code simplification, with removal of the obsolete cuts. From: Manu Abraham Signed-off-by: Manu Abraham --- linux/drivers/media/dvb/frontends/stv090x.c | 1076 +++++++++++++--------- linux/drivers/media/dvb/frontends/stv090x.h | 8 - linux/drivers/media/dvb/frontends/stv090x_priv.h | 33 +- linux/drivers/media/dvb/frontends/stv090x_reg.h | 72 +- 4 files changed, 733 insertions(+), 456 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/frontends/stv090x.c b/linux/drivers/media/dvb/frontends/stv090x.c index 39909fefc..62078400f 100644 --- a/linux/drivers/media/dvb/frontends/stv090x.c +++ b/linux/drivers/media/dvb/frontends/stv090x.c @@ -1234,25 +1234,6 @@ static struct stv090x_reg stv0903_cut20_val[] = { { STV090x_GAINLLR_NF17, 0x21 } }; -/* Cut 1.x Long Frame Tracking CR loop */ -static struct stv090x_long_frame_crloop stv090x_s2_crl[] = { - /* MODCOD 2MPon 2MPoff 5MPon 5MPoff 10MPon 10MPoff 20MPon 20MPoff 30MPon 30MPoff */ - { STV090x_QPSK_12, 0x1c, 0x0d, 0x1b, 0x2c, 0x3a, 0x1c, 0x2a, 0x3b, 0x2a, 0x1b }, - { STV090x_QPSK_35, 0x2c, 0x0d, 0x2b, 0x2c, 0x3a, 0x0c, 0x3a, 0x2b, 0x2a, 0x0b }, - { STV090x_QPSK_23, 0x2c, 0x0d, 0x2b, 0x2c, 0x0b, 0x0c, 0x3a, 0x1b, 0x2a, 0x3a }, - { STV090x_QPSK_34, 0x3c, 0x0d, 0x3b, 0x1c, 0x0b, 0x3b, 0x3a, 0x0b, 0x2a, 0x3a }, - { STV090x_QPSK_45, 0x3c, 0x0d, 0x3b, 0x1c, 0x0b, 0x3b, 0x3a, 0x0b, 0x2a, 0x3a }, - { STV090x_QPSK_56, 0x0d, 0x0d, 0x3b, 0x1c, 0x0b, 0x3b, 0x3a, 0x0b, 0x2a, 0x3a }, - { STV090x_QPSK_89, 0x0d, 0x0d, 0x3b, 0x1c, 0x1b, 0x3b, 0x3a, 0x0b, 0x2a, 0x3a }, - { STV090x_QPSK_910, 0x1d, 0x0d, 0x3b, 0x1c, 0x1b, 0x3b, 0x3a, 0x0b, 0x2a, 0x3a }, - { STV090x_8PSK_35, 0x29, 0x3b, 0x09, 0x2b, 0x38, 0x0b, 0x18, 0x1a, 0x08, 0x0a }, - { STV090x_8PSK_23, 0x0a, 0x3b, 0x29, 0x2b, 0x19, 0x0b, 0x38, 0x1a, 0x18, 0x0a }, - { STV090x_8PSK_34, 0x3a, 0x3b, 0x2a, 0x2b, 0x39, 0x0b, 0x19, 0x1a, 0x38, 0x0a }, - { STV090x_8PSK_56, 0x1b, 0x3b, 0x0b, 0x2b, 0x1a, 0x0b, 0x39, 0x1a, 0x19, 0x0a }, - { STV090x_8PSK_89, 0x3b, 0x3b, 0x0b, 0x2b, 0x2a, 0x0b, 0x39, 0x1a, 0x29, 0x39 }, - { STV090x_8PSK_910, 0x3b, 0x3b, 0x0b, 0x2b, 0x2a, 0x0b, 0x39, 0x1a, 0x29, 0x39 } -}; - /* Cut 2.0 Long Frame Tracking CR loop */ static struct stv090x_long_frame_crloop stv090x_s2_crl_cut20[] = { /* MODCOD 2MPon 2MPoff 5MPon 5MPoff 10MPon 10MPoff 20MPon 20MPoff 30MPon 30MPoff */ @@ -1272,7 +1253,6 @@ static struct stv090x_long_frame_crloop stv090x_s2_crl_cut20[] = { { STV090x_8PSK_910, 0x3e, 0x3e, 0x1e, 0x2e, 0x3d, 0x1e, 0x1d, 0x2d, 0x0d, 0x1d } }; -#if 0 /* Cut 3.0 Long Frame Tracking CR loop */ static struct stv090x_long_frame_crloop stv090x_s2_crl_cut30[] = { /* MODCOD 2MPon 2MPoff 5MPon 5MPoff 10MPon 10MPoff 20MPon 20MPoff 30MPon 30MPoff */ @@ -1291,7 +1271,6 @@ static struct stv090x_long_frame_crloop stv090x_s2_crl_cut30[] = { { STV090x_8PSK_89, 0x0d, 0x3c, 0x2c, 0x2c, 0x2b, 0x0c, 0x0b, 0x3b, 0x0b, 0x1b }, { STV090x_8PSK_910, 0x0d, 0x0d, 0x2c, 0x3c, 0x3b, 0x1c, 0x0b, 0x3b, 0x0b, 0x1b } }; -#endif /* Cut 2.0 Long Frame Tracking CR Loop */ static struct stv090x_long_frame_crloop stv090x_s2_apsk_crl_cut20[] = { @@ -1309,7 +1288,6 @@ static struct stv090x_long_frame_crloop stv090x_s2_apsk_crl_cut20[] = { { STV090x_32APSK_910, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c } }; -#if 0 /* Cut 3.0 Long Frame Tracking CR Loop */ static struct stv090x_long_frame_crloop stv090x_s2_apsk_crl_cut30[] = { /* MODCOD 2MPon 2MPoff 5MPon 5MPoff 10MPon 10MPoff 20MPon 20MPoff 30MPon 30MPoff */ @@ -1325,7 +1303,6 @@ static struct stv090x_long_frame_crloop stv090x_s2_apsk_crl_cut30[] = { { STV090x_32APSK_89, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a }, { STV090x_32APSK_910, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a } }; -#endif static struct stv090x_long_frame_crloop stv090x_s2_lowqpsk_crl_cut20[] = { /* MODCOD 2MPon 2MPoff 5MPon 5MPoff 10MPon 10MPoff 20MPon 20MPoff 30MPon 30MPoff */ @@ -1334,33 +1311,30 @@ static struct stv090x_long_frame_crloop stv090x_s2_lowqpsk_crl_cut20[] = { { STV090x_QPSK_25, 0x1f, 0x3f, 0x1e, 0x3f, 0x3d, 0x1f, 0x3d, 0x3e, 0x3d, 0x2e } }; -#if 0 static struct stv090x_long_frame_crloop stv090x_s2_lowqpsk_crl_cut30[] = { /* MODCOD 2MPon 2MPoff 5MPon 5MPoff 10MPon 10MPoff 20MPon 20MPoff 30MPon 30MPoff */ { STV090x_QPSK_14, 0x0c, 0x3c, 0x0b, 0x3c, 0x2a, 0x2c, 0x2a, 0x1c, 0x3a, 0x3b }, { STV090x_QPSK_13, 0x0c, 0x3c, 0x0b, 0x3c, 0x2a, 0x2c, 0x3a, 0x0c, 0x3a, 0x2b }, { STV090x_QPSK_25, 0x1c, 0x3c, 0x1b, 0x3c, 0x3a, 0x1c, 0x3a, 0x3b, 0x3a, 0x2b } }; -#endif -/* Cut 1.2 & 2.0 Short Frame Tracking CR Loop */ -static struct stv090x_short_frame_crloop stv090x_s2_short_crl[] = { - /* MODCOD 2M_cut1.2 2M_cut2.0 5M_cut1.2 5M_cut2.0 10M_cut1.2 10M_cut2.0 20M_cut1.2 20M_cut2.0 30M_cut1.2 30M_cut2.0 */ - { STV090x_QPSK, 0x3c, 0x2f, 0x2b, 0x2e, 0x0b, 0x0e, 0x3a, 0x0e, 0x2a, 0x3d }, - { STV090x_8PSK, 0x0b, 0x3e, 0x2a, 0x0e, 0x0a, 0x2d, 0x19, 0x0d, 0x09, 0x3c }, - { STV090x_16APSK, 0x1b, 0x1e, 0x1b, 0x1e, 0x1b, 0x1e, 0x3a, 0x3d, 0x2a, 0x2d }, - { STV090x_32APSK, 0x1b, 0x1e, 0x1b, 0x1e, 0x1b, 0x1e, 0x3a, 0x3d, 0x2a, 0x2d } +/* Cut 2.0 Short Frame Tracking CR Loop */ +static struct stv090x_short_frame_crloop stv090x_s2_short_crl_cut20[] = { + /* MODCOD 2M 5M 10M 20M 30M */ + { STV090x_QPSK, 0x2f, 0x2e, 0x0e, 0x0e, 0x3d }, + { STV090x_8PSK, 0x3e, 0x0e, 0x2d, 0x0d, 0x3c }, + { STV090x_16APSK, 0x1e, 0x1e, 0x1e, 0x3d, 0x2d }, + { STV090x_32APSK, 0x1e, 0x1e, 0x1e, 0x3d, 0x2d } }; -#if 0 -static struct stv090x_short_frame_vsmod_crloop stv090x_s2_short_crl_cut30[] = { +/* Cut 3.0 Short Frame Tracking CR Loop */ +static struct stv090x_short_frame_crloop stv090x_s2_short_crl_cut30[] = { /* MODCOD 2M 5M 10M 20M 30M */ { STV090x_QPSK, 0x2C, 0x2B, 0x0B, 0x0B, 0x3A }, { STV090x_8PSK, 0x3B, 0x0B, 0x2A, 0x0A, 0x39 }, { STV090x_16APSK, 0x1B, 0x1B, 0x1B, 0x3A, 0x2A }, { STV090x_32APSK, 0x1B, 0x1B, 0x1B, 0x3A, 0x2A } }; -#endif static inline s32 comp2(s32 __x, s32 __width) { @@ -1772,74 +1746,83 @@ err: static int stv090x_activate_modcod(struct stv090x_state *state) { - u32 matype, modcod, f_mod, index; + if (STV090x_WRITE_DEMOD(state, MODCODLST0, 0xff) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, MODCODLST1, 0xfc) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, MODCODLST2, 0xcc) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, MODCODLST3, 0xcc) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, MODCODLST4, 0xcc) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, MODCODLST5, 0xcc) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, MODCODLST6, 0xcc) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, MODCODLST7, 0xcc) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, MODCODLST8, 0xcc) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, MODCODLST9, 0xcc) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, MODCODLSTA, 0xcc) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, MODCODLSTB, 0xcc) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, MODCODLSTC, 0xcc) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, MODCODLSTD, 0xcc) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, MODCODLSTE, 0xcc) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, MODCODLSTF, 0xcf) < 0) + goto err; - if (state->dev_ver <= 0x11) { - msleep(5); - modcod = STV090x_READ_DEMOD(state, PLHMODCOD); - matype = modcod & 0x03; - modcod = (modcod & 0x7f) >> 2; - index = STV090x_ADDR_OFFST(state, MODCODLSTF) - (modcod / 2); + return 0; +err: + dprintk(FE_ERROR, 1, "I/O error"); + return -1; +} + +static int stv090x_activate_modcod_single(struct stv090x_state *state) +{ + + if (STV090x_WRITE_DEMOD(state, MODCODLST0, 0xff) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, MODCODLST1, 0xf0) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, MODCODLST2, 0x00) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, MODCODLST3, 0x00) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, MODCODLST4, 0x00) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, MODCODLST5, 0x00) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, MODCODLST6, 0x00) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, MODCODLST7, 0x00) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, MODCODLST8, 0x00) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, MODCODLST9, 0x00) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, MODCODLSTA, 0x00) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, MODCODLSTB, 0x00) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, MODCODLSTC, 0x00) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, MODCODLSTD, 0x00) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, MODCODLSTE, 0x00) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, MODCODLSTF, 0x0f) < 0) + goto err; - switch (matype) { - default: - case 0: - f_mod = 14; - break; - case 1: - f_mod = 13; - break; - case 2: - f_mod = 11; - break; - case 3: - f_mod = 7; - break; - } - if (matype <= 1) { - if (modcod % 2) { - if (stv090x_write_reg(state, index, 0xf0 | f_mod) < 0) - goto err; - } else { - if (stv090x_write_reg(state, index, (f_mod << 4) | 0x0f) < 0) - goto err; - } - } - } else if (state->dev_ver >= 0x12) { - if (STV090x_WRITE_DEMOD(state, MODCODLST0, 0xff) < 0) - goto err; - if (STV090x_WRITE_DEMOD(state, MODCODLST1, 0xfc) < 0) - goto err; - if (STV090x_WRITE_DEMOD(state, MODCODLST2, 0xcc) < 0) - goto err; - if (STV090x_WRITE_DEMOD(state, MODCODLST3, 0xcc) < 0) - goto err; - if (STV090x_WRITE_DEMOD(state, MODCODLST4, 0xcc) < 0) - goto err; - if (STV090x_WRITE_DEMOD(state, MODCODLST5, 0xcc) < 0) - goto err; - if (STV090x_WRITE_DEMOD(state, MODCODLST6, 0xcc) < 0) - goto err; - if (STV090x_WRITE_DEMOD(state, MODCODLST7, 0xcc) < 0) - goto err; - if (STV090x_WRITE_DEMOD(state, MODCODLST8, 0xcc) < 0) - goto err; - if (STV090x_WRITE_DEMOD(state, MODCODLST9, 0xcc) < 0) - goto err; - if (STV090x_WRITE_DEMOD(state, MODCODLSTA, 0xcc) < 0) - goto err; - if (STV090x_WRITE_DEMOD(state, MODCODLSTB, 0xcc) < 0) - goto err; - if (STV090x_WRITE_DEMOD(state, MODCODLSTC, 0xcc) < 0) - goto err; - if (STV090x_WRITE_DEMOD(state, MODCODLSTD, 0xcc) < 0) - goto err; - if (STV090x_WRITE_DEMOD(state, MODCODLSTE, 0xcc) < 0) - goto err; - if (STV090x_WRITE_DEMOD(state, MODCODLSTF, 0xcf) < 0) - goto err; - } return 0; + err: dprintk(FE_ERROR, 1, "I/O error"); return -1; @@ -1879,6 +1862,40 @@ err: return -1; } +static int stv090x_dvbs_track_crl(struct stv090x_state *state) +{ + if (state->dev_ver >= 0x30) { + /* Set ACLC BCLC optimised value vs SR */ + if (state->srate >= 15000000) { + if (STV090x_WRITE_DEMOD(state, ACLC, 0x2b) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, BCLC, 0x1a) < 0) + goto err; + } else if ((state->srate >= 7000000) && (15000000 > state->srate)) { + if (STV090x_WRITE_DEMOD(state, ACLC, 0x0c) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, BCLC, 0x1b) < 0) + goto err; + } else if (state->srate < 7000000) { + if (STV090x_WRITE_DEMOD(state, ACLC, 0x2c) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, BCLC, 0x1c) < 0) + goto err; + } + + } else { + /* Cut 2.0 */ + if (STV090x_WRITE_DEMOD(state, ACLC, 0x1a) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, BCLC, 0x09) < 0) + goto err; + } + return 0; +err: + dprintk(FE_ERROR, 1, "I/O error"); + return -1; +} + static int stv090x_delivery_search(struct stv090x_state *state) { u32 reg; @@ -1892,19 +1909,22 @@ static int stv090x_delivery_search(struct stv090x_state *state) if (STV090x_WRITE_DEMOD(state, DMDCFGMD, reg) < 0) goto err; - /* Activate Viterbi decoder in legacy search, do not use FRESVIT1, might impact VITERBI2 */ + /* Activate Viterbi decoder in legacy search, + * do not use FRESVIT1, might impact VITERBI2 + */ if (stv090x_vitclk_ctl(state, 0) < 0) goto err; - if (STV090x_WRITE_DEMOD(state, ACLC, 0x1a) < 0) - goto err; - if (STV090x_WRITE_DEMOD(state, BCLC, 0x09) < 0) + if (stv090x_dvbs_track_crl(state) < 0) goto err; + if (STV090x_WRITE_DEMOD(state, CAR2CFG, 0x22) < 0) /* disable DVB-S2 */ goto err; - stv090x_set_vit_thacq(state); - stv090x_set_viterbi(state); + if (stv090x_set_vit_thacq(state) < 0) + goto err; + if (stv090x_set_viterbi(state) < 0) + goto err; break; case STV090x_SEARCH_DVBS2: @@ -1925,24 +1945,36 @@ static int stv090x_delivery_search(struct stv090x_state *state) goto err; if (STV090x_WRITE_DEMOD(state, BCLC, 0x09) < 0) goto err; - if (STV090x_WRITE_DEMOD(state, CAR2CFG, 0x26) < 0) - goto err; + + if (state->dev_ver <= 0x20) { + /* enable S2 carrier loop */ + if (STV090x_WRITE_DEMOD(state, CAR2CFG, 0x26) < 0) + goto err; + } else { + /* > Cut 3: Stop carrier 3 */ + if (STV090x_WRITE_DEMOD(state, CAR2CFG, 0x66) < 0) + goto err; + } if (state->demod_mode != STV090x_SINGLE) { - if (state->dev_ver <= 0x11) /* 900 in dual TS mode */ - stv090x_stop_modcod(state); - else - stv090x_activate_modcod(state); + /* Cut 2: enable link during search */ + if (stv090x_activate_modcod(state) < 0) + goto err; + } else { + /* Single demodulator + * Authorize SHORT and LONG frames, + * QPSK, 8PSK, 16APSK and 32APSK + */ + if (stv090x_activate_modcod_single(state) < 0) + goto err; } + break; case STV090x_SEARCH_AUTO: default: + /* enable DVB-S2 and DVB-S2 in Auto MODE */ reg = STV090x_READ_DEMOD(state, DMDCFGMD); - STV090x_SETFIELD_Px(reg, DVBS1_ENABLE_FIELD, 0); - STV090x_SETFIELD_Px(reg, DVBS2_ENABLE_FIELD, 0); - if (STV090x_WRITE_DEMOD(state, DMDCFGMD, reg) < 0) - goto err; STV090x_SETFIELD_Px(reg, DVBS1_ENABLE_FIELD, 1); STV090x_SETFIELD_Px(reg, DVBS2_ENABLE_FIELD, 1); if (STV090x_WRITE_DEMOD(state, DMDCFGMD, reg) < 0) @@ -1951,21 +1983,46 @@ static int stv090x_delivery_search(struct stv090x_state *state) if (stv090x_vitclk_ctl(state, 0) < 0) goto err; - if (STV090x_WRITE_DEMOD(state, ACLC, 0x1a) < 0) - goto err; - if (STV090x_WRITE_DEMOD(state, BCLC, 0x09) < 0) - goto err; - if (STV090x_WRITE_DEMOD(state, CAR2CFG, 0x26) < 0) + if (stv090x_dvbs_track_crl(state) < 0) goto err; + if (state->dev_ver <= 0x20) { + /* enable S2 carrier loop */ + if (STV090x_WRITE_DEMOD(state, CAR2CFG, 0x26) < 0) + goto err; + } else { + /* > Cut 3: Stop carrier 3 */ + if (STV090x_WRITE_DEMOD(state, CAR2CFG, 0x66) < 0) + goto err; + } + if (state->demod_mode != STV090x_SINGLE) { - if (state->dev_ver <= 0x11) /* 900 in dual TS mode */ - stv090x_stop_modcod(state); - else - stv090x_activate_modcod(state); + /* Cut 2: enable link during search */ + if (stv090x_activate_modcod(state) < 0) + goto err; + } else { + /* Single demodulator + * Authorize SHORT and LONG frames, + * QPSK, 8PSK, 16APSK and 32APSK + */ + if (stv090x_activate_modcod_single(state) < 0) + goto err; + } + + if (state->srate >= 2000000) { + /* Srate >= 2MSPS, Viterbi threshold to acquire */ + if (stv090x_set_vit_thacq(state) < 0) + goto err; + } else { + /* Srate < 2MSPS, Reset Viterbi thresholdto track + * and then re-acquire + */ + if (stv090x_set_vit_thtracq(state) < 0) + goto err; } - stv090x_set_vit_thacq(state); - stv090x_set_viterbi(state); + + if (stv090x_set_viterbi(state) < 0) + goto err; break; } return 0; @@ -1976,45 +2033,87 @@ err: static int stv090x_start_search(struct stv090x_state *state) { - u32 reg; + u32 reg, freq_abs; + s16 freq; + /* Reset demodulator */ reg = STV090x_READ_DEMOD(state, DMDISTATE); STV090x_SETFIELD_Px(reg, I2C_DEMOD_MODE_FIELD, 0x1f); if (STV090x_WRITE_DEMOD(state, DMDISTATE, reg) < 0) goto err; - if (state->dev_ver == 0x10) { - if (STV090x_WRITE_DEMOD(state, CORRELEXP, 0xaa) < 0) - goto err; - } - if (state->dev_ver < 0x20) { - if (STV090x_WRITE_DEMOD(state, CARHDR, 0x55) < 0) - goto err; - } - if (state->srate <= 5000000) { - if (STV090x_WRITE_DEMOD(state, CARCFG, 0x44) < 0) - goto err; - if (STV090x_WRITE_DEMOD(state, CFRUP1, 0x0f) < 0) - goto err; - if (STV090x_WRITE_DEMOD(state, CFRUP1, 0xff) < 0) - goto err; - if (STV090x_WRITE_DEMOD(state, CFRLOW1, 0xf0) < 0) + if (state->dev_ver <= 0x20) { + if (state->srate <= 5000000) { + if (STV090x_WRITE_DEMOD(state, CARCFG, 0x44) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, CFRUP1, 0x0f) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, CFRUP1, 0xff) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, CFRLOW1, 0xf0) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, CFRLOW0, 0x00) < 0) + goto err; + + /*enlarge the timing bandwith for Low SR*/ + if (STV090x_WRITE_DEMOD(state, RTCS2, 0x68) < 0) + goto err; + } else { + /* If the symbol rate is >5 Msps + Set The carrier search up and low to auto mode */ + if (STV090x_WRITE_DEMOD(state, CARCFG, 0xc4) < 0) + goto err; + /*reduce the timing bandwith for high SR*/ + if (STV090x_WRITE_DEMOD(state, RTCS2, 0x44) < 0) + goto err; + } + } else { + /* >= Cut 3 */ + if (state->srate <= 5000000) { + /* enlarge the timing bandwith for Low SR */ + STV090x_WRITE_DEMOD(state, RTCS2, 0x68); + } else { + /* reduce timing bandwith for high SR */ + STV090x_WRITE_DEMOD(state, RTCS2, 0x44); + } + + /* Set CFR min and max to manual mode */ + STV090x_WRITE_DEMOD(state, CARCFG, 0x46); + + if (state->algo == STV090x_WARM_SEARCH) { + /* WARM Start + * CFR min = -1MHz, + * CFR max = +1MHz + */ + freq_abs = 1000 << 16; + freq_abs /= (state->mclk / 1000); + freq = (s16) freq_abs; + } else { + /* COLD Start + * CFR min =- (SearchRange / 2 + 600KHz) + * CFR max = +(SearchRange / 2 + 600KHz) + * (600KHz for the tuner step size) + */ + freq_abs = (state->search_range / 2000) + 600; + freq_abs = freq_abs << 16; + freq_abs /= (state->mclk / 1000); + freq = (s16) freq_abs; + } + + if (STV090x_WRITE_DEMOD(state, CFRUP1, MSB(freq)) < 0) goto err; - if (STV090x_WRITE_DEMOD(state, CFRLOW0, 0x00) < 0) + if (STV090x_WRITE_DEMOD(state, CFRUP1, LSB(freq)) < 0) goto err; - /*enlarge the timing bandwith for Low SR*/ - if (STV090x_WRITE_DEMOD(state, RTCS2, 0x68) < 0) - goto err; - } else { - /* If the symbol rate is >5 Msps - Set The carrier search up and low to auto mode */ - if (STV090x_WRITE_DEMOD(state, CARCFG, 0xc4) < 0) + freq *= -1; + + if (STV090x_WRITE_DEMOD(state, CFRLOW1, MSB(freq)) < 0) goto err; - /*reduce the timing bandwith for high SR*/ - if (STV090x_WRITE_DEMOD(state, RTCS2, 0x44) < 0) + if (STV090x_WRITE_DEMOD(state, CFRLOW0, LSB(freq)) < 0) goto err; + } + if (STV090x_WRITE_DEMOD(state, CFRINIT1, 0) < 0) goto err; if (STV090x_WRITE_DEMOD(state, CFRINIT0, 0) < 0) @@ -2054,7 +2153,22 @@ static int stv090x_start_search(struct stv090x_state *state) if (STV090x_WRITE_DEMOD(state, DMDCFG2, reg) < 0) goto err; - if (state->dev_ver >= 0x20) { /*Frequency offset detector setting*/ + if (state->dev_ver >= 0x20) { + /*Frequency offset detector setting*/ + if (state->srate < 2000000) { + if (state->dev_ver <= 0x20) { + /* Cut 2 */ + if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x39) < 0) + goto err; + } else { + /* Cut 2 */ + if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x89) < 0) + goto err; + } + if (STV090x_WRITE_DEMOD(state, CARHDR, 0x40) < 0) + goto err; + } + if (state->srate < 10000000) { if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x4c) < 0) goto err; @@ -2073,14 +2187,18 @@ static int stv090x_start_search(struct stv090x_state *state) } switch (state->algo) { - case STV090x_WARM_SEARCH:/*The symbol rate and the exact carrier Frequency are known */ + case STV090x_WARM_SEARCH: + /* The symbol rate and the exact + * carrier Frequency are known + */ if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x1f) < 0) goto err; if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x18) < 0) goto err; break; - case STV090x_COLD_SEARCH:/*The symbol rate is known*/ + case STV090x_COLD_SEARCH: + /* The symbol rate is known */ if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x1f) < 0) goto err; if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x15) < 0) @@ -2119,7 +2237,8 @@ static int stv090x_get_agc2_min_level(struct stv090x_state *state) goto err; if (STV090x_WRITE_DEMOD(state, DMDTOM, 0x00) < 0) /* stop acq @ coarse carrier state */ goto err; - stv090x_set_srate(state, 1000000); + if (stv090x_set_srate(state, 1000000) < 0) + goto err; steps = -1 + state->search_range / 1000000; steps /= 2; @@ -2226,15 +2345,16 @@ static u32 stv090x_srate_srch_coarse(struct stv090x_state *state) if (STV090x_WRITE_DEMOD(state, AGC2REF, 0x60) < 0) goto err; - if (state->dev_ver >= 0x20) { - if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x6a) < 0) + if (state->dev_ver >= 0x30) { + if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x99) < 0) goto err; if (STV090x_WRITE_DEMOD(state, SFRSTEP, 0x95) < 0) goto err; - } else { - if (STV090x_WRITE_DEMOD(state, CARFREQ, 0xed) < 0) + + } else if (state->dev_ver >= 0x20) { + if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x6a) < 0) goto err; - if (STV090x_WRITE_DEMOD(state, SFRSTEP, 0x73) < 0) + if (STV090x_WRITE_DEMOD(state, SFRSTEP, 0x95) < 0) goto err; } @@ -2288,27 +2408,39 @@ static u32 stv090x_srate_srch_coarse(struct stv090x_state *state) freq -= cur_step * car_step; /* Setup tuner */ - stv090x_i2c_gate_ctrl(fe, 1); + if (stv090x_i2c_gate_ctrl(fe, 1) < 0) + goto err; + + if (state->config->tuner_set_frequency) { + if (state->config->tuner_set_frequency(fe, state->frequency) < 0) + goto err; + } - if (state->config->tuner_set_frequency) - state->config->tuner_set_frequency(fe, state->frequency); + if (state->config->tuner_set_bandwidth) { + if (state->config->tuner_set_bandwidth(fe, state->tuner_bw) < 0) + goto err; + } - if (state->config->tuner_set_bandwidth) - state->config->tuner_set_bandwidth(fe, state->tuner_bw); + if (stv090x_i2c_gate_ctrl(fe, 0) < 0) + goto err; - stv090x_i2c_gate_ctrl(fe, 0); msleep(50); - stv090x_i2c_gate_ctrl(fe, 1); - if (state->config->tuner_get_status) - state->config->tuner_get_status(fe, ®); + if (stv090x_i2c_gate_ctrl(fe, 1) < 0) + goto err; + + if (state->config->tuner_get_status) { + if (state->config->tuner_get_status(fe, ®) < 0) + goto err; + } if (reg) dprintk(FE_DEBUG, 1, "Tuner phase locked"); else dprintk(FE_DEBUG, 1, "Tuner unlocked"); - stv090x_i2c_gate_ctrl(fe, 0); + if (stv090x_i2c_gate_ctrl(fe, 0) < 0) + goto err; } } @@ -2350,11 +2482,11 @@ static u32 stv090x_srate_srch_fine(struct stv090x_state *state) if (STV090x_WRITE_DEMOD(state, DMDCFGMD, reg) < 0) goto err; - if (state->dev_ver >= 0x20) { - if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x49) < 0) + if (state->dev_ver >= 0x30) { + if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x79) < 0) goto err; - } else { - if (STV090x_WRITE_DEMOD(state, CARFREQ, 0xed) < 0) + } else if (state->dev_ver >= 0x20) { + if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x49) < 0) goto err; } @@ -2459,32 +2591,27 @@ static int stv090x_blind_search(struct stv090x_state *state) u8 k_ref, k_max, k_min; int coarse_fail, lock; - if (state->dev_ver < 0x20) { - k_max = 233; - k_min = 143; - } else { - k_max = 120; - k_min = 30; - } + k_max = 120; + k_min = 30; agc2 = stv090x_get_agc2_min_level(state); - if (agc2 > STV090x_SEARCH_AGC2_TH) { + if (agc2 > STV090x_SEARCH_AGC2_TH(state->dev_ver)) { lock = 0; } else { - if (state->dev_ver == 0x10) { - if (STV090x_WRITE_DEMOD(state, CORRELEXP, 0xaa) < 0) + + if (state->dev_ver <= 0x20) { + if (STV090x_WRITE_DEMOD(state, CARCFG, 0xc4) < 0) goto err; - } - if (state->dev_ver < 0x20) { - if (STV090x_WRITE_DEMOD(state, CARHDR, 0x55) < 0) + } else { + /* > Cut 3 */ + if (STV090x_WRITE_DEMOD(state, CARCFG, 0x06) < 0) goto err; } - if (STV090x_WRITE_DEMOD(state, CARCFG, 0xc4) < 0) - goto err; if (STV090x_WRITE_DEMOD(state, RTCS2, 0x44) < 0) goto err; + if (state->dev_ver >= 0x20) { if (STV090x_WRITE_DEMOD(state, EQUALCFG, 0x41) < 0) goto err; @@ -2541,7 +2668,7 @@ err: static int stv090x_chk_tmg(struct stv090x_state *state) { u32 reg; - s32 tmg_cpt, i; + s32 tmg_cpt = 0, i; u8 freq, tmg_thh, tmg_thl; int tmg_lock; @@ -2662,29 +2789,39 @@ static int stv090x_get_coldlock(struct stv090x_state *state, s32 timeout_dmd) freq -= cur_step * car_step; /* Setup tuner */ - stv090x_i2c_gate_ctrl(fe, 1); + if (stv090x_i2c_gate_ctrl(fe, 1) < 0) + goto err; - if (state->config->tuner_set_frequency) - state->config->tuner_set_frequency(fe, state->frequency); + if (state->config->tuner_set_frequency) { + if (state->config->tuner_set_frequency(fe, state->frequency) < 0) + goto err; + } - if (state->config->tuner_set_bandwidth) - state->config->tuner_set_bandwidth(fe, state->tuner_bw); + if (state->config->tuner_set_bandwidth) { + if (state->config->tuner_set_bandwidth(fe, state->tuner_bw) < 0) + goto err; + } - stv090x_i2c_gate_ctrl(fe, 0); + if (stv090x_i2c_gate_ctrl(fe, 0) < 0) + goto err; msleep(50); - stv090x_i2c_gate_ctrl(fe, 1); + if (stv090x_i2c_gate_ctrl(fe, 1) < 0) + goto err; - if (state->config->tuner_get_status) - state->config->tuner_get_status(fe, ®); + if (state->config->tuner_get_status) { + if (state->config->tuner_get_status(fe, ®) < 0) + goto err; + } if (reg) dprintk(FE_DEBUG, 1, "Tuner phase locked"); else dprintk(FE_DEBUG, 1, "Tuner unlocked"); - stv090x_i2c_gate_ctrl(fe, 0); + if (stv090x_i2c_gate_ctrl(fe, 0) < 0) + goto err; STV090x_WRITE_DEMOD(state, DMDISTATE, 0x1c); if (state->delsys == STV090x_DVBS2) { @@ -2816,7 +2953,7 @@ static int stv090x_chk_signal(struct stv090x_state *state) static int stv090x_search_car_loop(struct stv090x_state *state, s32 inc, s32 timeout, int zigzag, s32 steps_max) { int no_signal, lock = 0; - s32 cpt_step, offst_freq, car_max; + s32 cpt_step = 0, offst_freq, car_max; u32 reg; car_max = state->search_range / 1000; @@ -2831,7 +2968,6 @@ static int stv090x_search_car_loop(struct stv090x_state *state, s32 inc, s32 tim else offst_freq = -car_max + inc; - cpt_step = 0; do { if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x1c) < 0) goto err; @@ -2847,16 +2983,6 @@ static int stv090x_search_car_loop(struct stv090x_state *state, s32 inc, s32 tim if (STV090x_WRITE_DEMOD(state, PDELCTRL1, reg) < 0) goto err; - if (state->dev_ver == 0x12) { - reg = STV090x_READ_DEMOD(state, TSCFGH); - STV090x_SETFIELD_Px(reg, RST_HWARE_FIELD, 0x1); - if (STV090x_WRITE_DEMOD(state, TSCFGH, reg) < 0) - goto err; - STV090x_SETFIELD_Px(reg, RST_HWARE_FIELD, 0x0); - if (STV090x_WRITE_DEMOD(state, TSCFGH, reg) < 0) - goto err; - } - if (zigzag) { if (offst_freq >= 0) offst_freq = -offst_freq - 2 * inc; @@ -2896,7 +3022,8 @@ static int stv090x_sw_algo(struct stv090x_state *state) s32 dvbs2_fly_wheel; s32 inc, timeout_step, trials, steps_max; - stv090x_get_loop_params(state, &inc, &timeout_step, &steps_max); /* get params */ + /* get params */ + stv090x_get_loop_params(state, &inc, &timeout_step, &steps_max); switch (state->search_mode) { case STV090x_SEARCH_DVBS1: @@ -2905,10 +3032,8 @@ static int stv090x_sw_algo(struct stv090x_state *state) if (state->dev_ver >= 0x20) { if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x3B) < 0) goto err; - } else { - if (STV090x_WRITE_DEMOD(state, CARFREQ, 0xef) < 0) - goto err; } + if (STV090x_WRITE_DEMOD(state, DMDCFGMD, 0x49) < 0) goto err; zigzag = 0; @@ -2918,10 +3043,8 @@ static int stv090x_sw_algo(struct stv090x_state *state) if (state->dev_ver >= 0x20) { if (STV090x_WRITE_DEMOD(state, CORRELABS, 0x79) < 0) goto err; - } else { - if (STV090x_WRITE_DEMOD(state, CORRELABS, 0x68) < 0) - goto err; } + if (STV090x_WRITE_DEMOD(state, DMDCFGMD, 0x89) < 0) goto err; zigzag = 1; @@ -2935,12 +3058,8 @@ static int stv090x_sw_algo(struct stv090x_state *state) goto err; if (STV090x_WRITE_DEMOD(state, CORRELABS, 0x79) < 0) goto err; - } else { - if (STV090x_WRITE_DEMOD(state, CARFREQ, 0xef) < 0) - goto err; - if (STV090x_WRITE_DEMOD(state, CORRELABS, 0x68) < 0) - goto err; } + if (STV090x_WRITE_DEMOD(state, DMDCFGMD, 0xc9) < 0) goto err; zigzag = 0; @@ -2961,11 +3080,6 @@ static int stv090x_sw_algo(struct stv090x_state *state) goto err; if (STV090x_WRITE_DEMOD(state, CORRELABS, 0x9e) < 0) goto err; - } else { - if (STV090x_WRITE_DEMOD(state, CARFREQ, 0xed) < 0) - goto err; - if (STV090x_WRITE_DEMOD(state, CORRELABS, 0x88) < 0) - goto err; } reg = STV090x_READ_DEMOD(state, DMDSTATE); @@ -2986,10 +3100,8 @@ static int stv090x_sw_algo(struct stv090x_state *state) if (state->dev_ver >= 0x20) { if (STV090x_WRITE_DEMOD(state, CORRELABS, 0x79) < 0) goto err; - } else { - if (STV090x_WRITE_DEMOD(state, CORRELABS, 0x68) < 0) - goto err; } + if (STV090x_WRITE_DEMOD(state, DMDCFGMD, 0x89) < 0) goto err; } @@ -3110,16 +3222,23 @@ static enum stv090x_signal_state stv090x_get_sig_params(struct stv090x_state *st } state->delsys = stv090x_get_std(state); - stv090x_i2c_gate_ctrl(fe, 1); + if (stv090x_i2c_gate_ctrl(fe, 1) < 0) + goto err; - if (state->config->tuner_get_frequency) - state->config->tuner_get_frequency(fe, &state->frequency); + if (state->config->tuner_get_frequency) { + if (state->config->tuner_get_frequency(fe, &state->frequency) < 0) + goto err; + } - stv090x_i2c_gate_ctrl(fe, 0); + if (stv090x_i2c_gate_ctrl(fe, 0) < 0) + goto err; offst_freq = stv090x_get_car_freq(state, state->mclk) / 1000; state->frequency += offst_freq; - stv090x_get_viterbi(state); + + if (stv090x_get_viterbi(state) < 0) + goto err; + reg = STV090x_READ_DEMOD(state, DMDMODCOD); state->modcod = STV090x_GETFIELD_Px(reg, DEMOD_MODCOD_FIELD); state->pilots = STV090x_GETFIELD_Px(reg, DEMOD_TYPE_FIELD) & 0x01; @@ -3131,12 +3250,16 @@ static enum stv090x_signal_state stv090x_get_sig_params(struct stv090x_state *st if ((state->algo == STV090x_BLIND_SEARCH) || (state->srate < 10000000)) { - stv090x_i2c_gate_ctrl(fe, 1); + if (stv090x_i2c_gate_ctrl(fe, 1) < 0) + goto err; - if (state->config->tuner_get_frequency) - state->config->tuner_get_frequency(fe, &state->frequency); + if (state->config->tuner_get_frequency) { + if (state->config->tuner_get_frequency(fe, &state->frequency) < 0) + goto err; + } - stv090x_i2c_gate_ctrl(fe, 0); + if (stv090x_i2c_gate_ctrl(fe, 0) < 0) + goto err; if (abs(offst_freq) <= ((state->search_range / 2000) + 500)) return STV090x_RANGEOK; @@ -3152,6 +3275,9 @@ static enum stv090x_signal_state stv090x_get_sig_params(struct stv090x_state *st } return STV090x_OUTOFRANGE; +err: + dprintk(FE_ERROR, 1, "I/O error"); + return -1; } static u32 stv090x_get_tmgoffst(struct stv090x_state *state, u32 srate) @@ -3176,19 +3302,22 @@ static u8 stv090x_optimize_carloop(struct stv090x_state *state, enum stv090x_mod { u8 aclc = 0x29; s32 i; - struct stv090x_long_frame_crloop *car_loop; - - if (state->dev_ver <= 0x12) - car_loop = stv090x_s2_crl; - else if (state->dev_ver == 0x20) - car_loop = stv090x_s2_crl_cut20; - else - car_loop = stv090x_s2_crl; + struct stv090x_long_frame_crloop *car_loop, *car_loop_qpsk_low, *car_loop_apsk_low; + if (state->dev_ver == 0x20) { + car_loop = stv090x_s2_crl_cut20; + car_loop_qpsk_low = stv090x_s2_lowqpsk_crl_cut20; + car_loop_apsk_low = stv090x_s2_apsk_crl_cut20; + } else { + /* >= Cut 3 */ + car_loop = stv090x_s2_crl_cut30; + car_loop_qpsk_low = stv090x_s2_lowqpsk_crl_cut30; + car_loop_apsk_low = stv090x_s2_apsk_crl_cut30; + } if (modcod < STV090x_QPSK_12) { i = 0; - while ((i < 3) && (modcod != stv090x_s2_lowqpsk_crl_cut20[i].modcod)) + while ((i < 3) && (modcod != car_loop_qpsk_low[i].modcod)) i++; if (i >= 3) @@ -3201,7 +3330,7 @@ static u8 stv090x_optimize_carloop(struct stv090x_state *state, enum stv090x_mod if (i >= 14) { i = 0; - while ((i < 11) && (modcod != stv090x_s2_lowqpsk_crl_cut20[i].modcod)) + while ((i < 11) && (modcod != car_loop_apsk_low[i].modcod)) i++; if (i >= 11) @@ -3212,26 +3341,26 @@ static u8 stv090x_optimize_carloop(struct stv090x_state *state, enum stv090x_mod if (modcod <= STV090x_QPSK_25) { if (pilots) { if (state->srate <= 3000000) - aclc = stv090x_s2_lowqpsk_crl_cut20[i].crl_pilots_on_2; + aclc = car_loop_qpsk_low[i].crl_pilots_on_2; else if (state->srate <= 7000000) - aclc = stv090x_s2_lowqpsk_crl_cut20[i].crl_pilots_on_5; + aclc = car_loop_qpsk_low[i].crl_pilots_on_5; else if (state->srate <= 15000000) - aclc = stv090x_s2_lowqpsk_crl_cut20[i].crl_pilots_on_10; + aclc = car_loop_qpsk_low[i].crl_pilots_on_10; else if (state->srate <= 25000000) - aclc = stv090x_s2_lowqpsk_crl_cut20[i].crl_pilots_on_20; + aclc = car_loop_qpsk_low[i].crl_pilots_on_20; else - aclc = stv090x_s2_lowqpsk_crl_cut20[i].crl_pilots_on_30; + aclc = car_loop_qpsk_low[i].crl_pilots_on_30; } else { if (state->srate <= 3000000) - aclc = stv090x_s2_lowqpsk_crl_cut20[i].crl_pilots_off_2; + aclc = car_loop_qpsk_low[i].crl_pilots_off_2; else if (state->srate <= 7000000) - aclc = stv090x_s2_lowqpsk_crl_cut20[i].crl_pilots_off_5; + aclc = car_loop_qpsk_low[i].crl_pilots_off_5; else if (state->srate <= 15000000) - aclc = stv090x_s2_lowqpsk_crl_cut20[i].crl_pilots_off_10; + aclc = car_loop_qpsk_low[i].crl_pilots_off_10; else if (state->srate <= 25000000) - aclc = stv090x_s2_lowqpsk_crl_cut20[i].crl_pilots_off_20; + aclc = car_loop_qpsk_low[i].crl_pilots_off_20; else - aclc = stv090x_s2_lowqpsk_crl_cut20[i].crl_pilots_off_30; + aclc = car_loop_qpsk_low[i].crl_pilots_off_30; } } else if (modcod <= STV090x_8PSK_910) { @@ -3260,15 +3389,15 @@ static u8 stv090x_optimize_carloop(struct stv090x_state *state, enum stv090x_mod } } else { /* 16APSK and 32APSK */ if (state->srate <= 3000000) - aclc = stv090x_s2_apsk_crl_cut20[i].crl_pilots_on_2; + aclc = car_loop_apsk_low[i].crl_pilots_on_2; else if (state->srate <= 7000000) - aclc = stv090x_s2_apsk_crl_cut20[i].crl_pilots_on_5; + aclc = car_loop_apsk_low[i].crl_pilots_on_5; else if (state->srate <= 15000000) - aclc = stv090x_s2_apsk_crl_cut20[i].crl_pilots_on_10; + aclc = car_loop_apsk_low[i].crl_pilots_on_10; else if (state->srate <= 25000000) - aclc = stv090x_s2_apsk_crl_cut20[i].crl_pilots_on_20; + aclc = car_loop_apsk_low[i].crl_pilots_on_20; else - aclc = stv090x_s2_apsk_crl_cut20[i].crl_pilots_on_30; + aclc = car_loop_apsk_low[i].crl_pilots_on_30; } return aclc; @@ -3276,6 +3405,7 @@ static u8 stv090x_optimize_carloop(struct stv090x_state *state, enum stv090x_mod static u8 stv090x_optimize_carloop_short(struct stv090x_state *state) { + struct stv090x_short_frame_crloop *short_crl; s32 index = 0; u8 aclc = 0x0b; @@ -3295,34 +3425,21 @@ static u8 stv090x_optimize_carloop_short(struct stv090x_state *state) break; } - switch (state->dev_ver) { - case 0x20: - if (state->srate <= 3000000) - aclc = stv090x_s2_short_crl[index].crl_cut20_2; - else if (state->srate <= 7000000) - aclc = stv090x_s2_short_crl[index].crl_cut20_5; - else if (state->srate <= 15000000) - aclc = stv090x_s2_short_crl[index].crl_cut20_10; - else if (state->srate <= 25000000) - aclc = stv090x_s2_short_crl[index].crl_cut20_20; - else - aclc = stv090x_s2_short_crl[index].crl_cut20_30; - break; - - case 0x12: - default: - if (state->srate <= 3000000) - aclc = stv090x_s2_short_crl[index].crl_cut12_2; - else if (state->srate <= 7000000) - aclc = stv090x_s2_short_crl[index].crl_cut12_5; - else if (state->srate <= 15000000) - aclc = stv090x_s2_short_crl[index].crl_cut12_10; - else if (state->srate <= 25000000) - aclc = stv090x_s2_short_crl[index].crl_cut12_20; - else - aclc = stv090x_s2_short_crl[index].crl_cut12_30; - break; - } + if (state->dev_ver >= 0x30) + short_crl = stv090x_s2_short_crl_cut20; + else if (state->dev_ver >= 0x20) + short_crl = stv090x_s2_short_crl_cut30; + + if (state->srate <= 3000000) + aclc = short_crl[index].crl_2; + else if (state->srate <= 7000000) + aclc = short_crl[index].crl_5; + else if (state->srate <= 15000000) + aclc = short_crl[index].crl_10; + else if (state->srate <= 25000000) + aclc = short_crl[index].crl_20; + else + aclc = short_crl[index].crl_30; return aclc; } @@ -3352,9 +3469,27 @@ static int stv090x_optimize_track(struct stv090x_state *state) } reg = STV090x_READ_DEMOD(state, DEMOD); STV090x_SETFIELD_Px(reg, ROLLOFF_CONTROL_FIELD, state->rolloff); - STV090x_SETFIELD_Px(reg, MANUAL_ROLLOFF_FIELD, 0x01); + STV090x_SETFIELD_Px(reg, MANUAL_SXROLLOFF_FIELD, 0x01); if (STV090x_WRITE_DEMOD(state, DEMOD, reg) < 0) goto err; + + if (state->dev_ver >= 0x30) { + if (stv090x_get_viterbi(state) < 0) + goto err; + + if (state->fec == STV090x_PR12) { + if (STV090x_WRITE_DEMOD(state, GAUSSR0, 0x98) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, CCIR0, 0x18) < 0) + goto err; + } else { + if (STV090x_WRITE_DEMOD(state, GAUSSR0, 0x18) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, CCIR0, 0x18) < 0) + goto err; + } + } + if (STV090x_WRITE_DEMOD(state, ERRCTRL1, 0x75) < 0) goto err; break; @@ -3418,10 +3553,7 @@ static int stv090x_optimize_track(struct stv090x_state *state) goto err; } } - if (state->dev_ver <= 0x11) { - if (state->demod_mode != STV090x_SINGLE) - stv090x_activate_modcod(state); /* link to LDPC after demod LOCK */ - } + STV090x_WRITE_DEMOD(state, ERRCTRL1, 0x67); /* PER */ break; @@ -3447,11 +3579,17 @@ static int stv090x_optimize_track(struct stv090x_state *state) STV090x_SETFIELD_Px(reg, CFR_AUTOSCAN_FIELD, 0x00); if (STV090x_WRITE_DEMOD(state, DMDCFGMD, reg) < 0) goto err; - if (STV090x_WRITE_DEMOD(state, TMGCFG2, 0x01) < 0) + if (STV090x_WRITE_DEMOD(state, TMGCFG2, 0xc1) < 0) + goto err; + + if (stv090x_set_srate(state, srate) < 0) + goto err; +#if 0 + if (stv090x_set_max_srate(state, state->mclk, srate) < 0) + goto err; + if (stv090x_set_min_srate(state, state->mclk, srate) < 0) goto err; - stv090x_set_srate(state, srate); - stv090x_set_max_srate(state, state->mclk, srate); - stv090x_set_min_srate(state, state->mclk, srate); +#endif blind_tune = 1; } @@ -3467,20 +3605,18 @@ static int stv090x_optimize_track(struct stv090x_state *state) } } - if (state->dev_ver < 0x20) { - if (STV090x_WRITE_DEMOD(state, CARHDR, 0x08) < 0) - goto err; - } - if (state->dev_ver == 0x10) { - if (STV090x_WRITE_DEMOD(state, CORRELEXP, 0x0a) < 0) - goto err; - } - if (STV090x_WRITE_DEMOD(state, AGC2REF, 0x38) < 0) goto err; - if ((state->dev_ver >= 0x20) || (blind_tune == 1) || (state->srate < 10000000)) { + /* AUTO tracking MODE */ + if (STV090x_WRITE_DEMOD(state, SFRUP1, 0x80) < 0) + goto err; + /* AUTO tracking MODE */ + if (STV090x_WRITE_DEMOD(state, SFRLOW1, 0x80) < 0) + goto err; + if ((state->dev_ver >= 0x20) || (blind_tune == 1) || (state->srate < 10000000)) { + /* update initial carrier freq with the found freq offset */ if (STV090x_WRITE_DEMOD(state, CFRINIT1, f_1) < 0) goto err; if (STV090x_WRITE_DEMOD(state, CFRINIT0, f_0) < 0) @@ -3491,12 +3627,16 @@ static int stv090x_optimize_track(struct stv090x_state *state) if (state->algo != STV090x_WARM_SEARCH) { - stv090x_i2c_gate_ctrl(fe, 1); + if (stv090x_i2c_gate_ctrl(fe, 1) < 0) + goto err; - if (state->config->tuner_set_bandwidth) - state->config->tuner_set_bandwidth(fe, state->tuner_bw); + if (state->config->tuner_set_bandwidth) { + if (state->config->tuner_set_bandwidth(fe, state->tuner_bw) < 0) + goto err; + } - stv090x_i2c_gate_ctrl(fe, 0); + if (stv090x_i2c_gate_ctrl(fe, 0) < 0) + goto err; } } @@ -3539,6 +3679,7 @@ static int stv090x_optimize_track(struct stv090x_state *state) if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x49) < 0) goto err; } + if ((state->delsys == STV090x_DVBS1) || (state->delsys == STV090x_DSS)) stv090x_set_vit_thtracq(state); @@ -3608,22 +3749,18 @@ static int stv090x_get_lock(struct stv090x_state *state, s32 timeout_dmd, s32 ti static int stv090x_set_s2rolloff(struct stv090x_state *state) { - s32 rolloff; u32 reg; - if (state->dev_ver == 0x10) { - reg = STV090x_READ_DEMOD(state, DEMOD); - STV090x_SETFIELD_Px(reg, MANUAL_ROLLOFF_FIELD, 0x01); - if (STV090x_WRITE_DEMOD(state, DEMOD, reg) < 0) - goto err; - rolloff = STV090x_READ_DEMOD(state, MATSTR1) & 0x03; + if (state->dev_ver <= 0x20) { + /* rolloff to auto mode if DVBS2 */ reg = STV090x_READ_DEMOD(state, DEMOD); - STV090x_SETFIELD_Px(reg, ROLLOFF_CONTROL_FIELD, reg); + STV090x_SETFIELD_Px(reg, MANUAL_SXROLLOFF_FIELD, 0x00); if (STV090x_WRITE_DEMOD(state, DEMOD, reg) < 0) goto err; } else { + /* DVB-S2 rolloff to auto mode if DVBS2 */ reg = STV090x_READ_DEMOD(state, DEMOD); - STV090x_SETFIELD_Px(reg, MANUAL_ROLLOFF_FIELD, 0x00); + STV090x_SETFIELD_Px(reg, MANUAL_S2ROLLOFF_FIELD, 0x00); if (STV090x_WRITE_DEMOD(state, DEMOD, reg) < 0) goto err; } @@ -3633,6 +3770,7 @@ err: return -1; } +#if 0 static enum stv090x_signal_state stv090x_acq_fixs1(struct stv090x_state *state) { s32 srate, f_1, f_2; @@ -3645,8 +3783,10 @@ static enum stv090x_signal_state stv090x_acq_fixs1(struct stv090x_state *state) srate = stv090x_get_srate(state, state->mclk); srate += stv090x_get_tmgoffst(state, state->srate); - if (state->algo == STV090x_BLIND_SEARCH) - stv090x_set_srate(state, state->srate); + if (state->algo == STV090x_BLIND_SEARCH) { + if (stv090x_set_srate(state, state->srate) < 0) + goto err; + } stv090x_get_lock_tmg(state); @@ -3704,13 +3844,14 @@ err: dprintk(FE_ERROR, 1, "I/O error"); return -1; } +#endif static enum stv090x_signal_state stv090x_algo(struct stv090x_state *state) { struct dvb_frontend *fe = &state->frontend; enum stv090x_signal_state signal_state = STV090x_NOCARRIER; u32 reg; - s32 timeout_dmd = 500, timeout_fec = 50; + s32 timeout_dmd = 500, timeout_fec = 50, agc1_power, power_iq = 0, i; int lock = 0, low_sr = 0, no_signal = 0; reg = STV090x_READ_DEMOD(state, TSCFGH); @@ -3724,18 +3865,18 @@ static enum stv090x_signal_state stv090x_algo(struct stv090x_state *state) if (state->dev_ver >= 0x20) { if (STV090x_WRITE_DEMOD(state, CORRELABS, 0x9e) < 0) /* cut 2.0 */ goto err; - } else { - if (STV090x_WRITE_DEMOD(state, CORRELABS, 0x88) < 0) /* cut 1.x */ - goto err; } stv090x_get_lock_tmg(state); if (state->algo == STV090x_BLIND_SEARCH) { state->tuner_bw = 2 * 36000000; /* wide bw for unknown srate */ - if (STV090x_WRITE_DEMOD(state, TMGCFG2, 0x00) < 0) /* wider srate scan */ + if (STV090x_WRITE_DEMOD(state, TMGCFG2, 0xc0) < 0) /* wider srate scan */ + goto err; + if (STV090x_WRITE_DEMOD(state, CORRELMANT, 0x70) < 0) + goto err; + if (stv090x_set_srate(state, 1000000) < 0) /* inital srate = 1Msps */ goto err; - stv090x_set_srate(state, 1000000); /* inital srate = 1Msps */ } else { /* known srate */ if (STV090x_WRITE_DEMOD(state, DMDTOM, 0x20) < 0) @@ -3743,14 +3884,19 @@ static enum stv090x_signal_state stv090x_algo(struct stv090x_state *state) if (STV090x_WRITE_DEMOD(state, TMGCFG, 0xd2) < 0) goto err; - if (state->srate >= 10000000) { - if (STV090x_WRITE_DEMOD(state, AGC2REF, 0x38) < 0) /* High SR */ + if (state->srate < 2000000) { + /* SR < 2MSPS */ + if (STV090x_WRITE_DEMOD(state, CORRELMANT, 0x63) < 0) goto err; } else { - if (STV090x_WRITE_DEMOD(state, AGC2REF, 0x60) < 0) /* Low SR */ + /* SR >= 2Msps */ + if (STV090x_WRITE_DEMOD(state, CORRELMANT, 0x70) < 0) goto err; } + if (STV090x_WRITE_DEMOD(state, AGC2REF, 0x38) < 0) + goto err; + if (state->dev_ver >= 0x20) { if (STV090x_WRITE_DEMOD(state, KREFTMG, 0x5a) < 0) goto err; @@ -3758,16 +3904,21 @@ static enum stv090x_signal_state stv090x_algo(struct stv090x_state *state) state->tuner_bw = (15 * (stv090x_car_width(state->srate, state->rolloff) + 10000000)) / 10; else if (state->algo == STV090x_WARM_SEARCH) state->tuner_bw = stv090x_car_width(state->srate, state->rolloff) + 10000000; - } else { - if (STV090x_WRITE_DEMOD(state, KREFTMG, 0xc1) < 0) - goto err; - state->tuner_bw = (15 * (stv090x_car_width(state->srate, state->rolloff) + 10000000)) / 10; } - if (STV090x_WRITE_DEMOD(state, TMGCFG2, 0x01) < 0) /* narrow srate scan */ + + /* if cold start or warm (Symbolrate is known) + * use a Narrow symbol rate scan range + */ + if (STV090x_WRITE_DEMOD(state, TMGCFG2, 0xc1) < 0) /* narrow srate scan */ + goto err; + + if (stv090x_set_srate(state, state->srate) < 0) + goto err; + + if (stv090x_set_max_srate(state, state->mclk, state->srate) < 0) + goto err; + if (stv090x_set_min_srate(state, state->mclk, state->srate) < 0) goto err; - stv090x_set_srate(state, state->srate); - stv090x_set_max_srate(state, state->mclk, state->srate); - stv090x_set_min_srate(state, state->mclk, state->srate); if (state->srate >= 10000000) low_sr = 0; @@ -3776,60 +3927,97 @@ static enum stv090x_signal_state stv090x_algo(struct stv090x_state *state) } /* Setup tuner */ - stv090x_i2c_gate_ctrl(fe, 1); + if (stv090x_i2c_gate_ctrl(fe, 1) < 0) + goto err; - if (state->config->tuner_set_bbgain) - state->config->tuner_set_bbgain(fe, 10); /* 10dB */ + if (state->config->tuner_set_bbgain) { + if (state->config->tuner_set_bbgain(fe, 10) < 0) /* 10dB */ + goto err; + } - if (state->config->tuner_set_frequency) - state->config->tuner_set_frequency(fe, state->frequency); + if (state->config->tuner_set_frequency) { + if (state->config->tuner_set_frequency(fe, state->frequency) < 0) + goto err; + } - if (state->config->tuner_set_bandwidth) - state->config->tuner_set_bandwidth(fe, state->tuner_bw); + if (state->config->tuner_set_bandwidth) { + if (state->config->tuner_set_bandwidth(fe, state->tuner_bw) < 0) + goto err; + } - stv090x_i2c_gate_ctrl(fe, 0); + if (stv090x_i2c_gate_ctrl(fe, 0) < 0) + goto err; msleep(50); - stv090x_i2c_gate_ctrl(fe, 1); + if (stv090x_i2c_gate_ctrl(fe, 1) < 0) + goto err; - if (state->config->tuner_get_status) - state->config->tuner_get_status(fe, ®); + if (state->config->tuner_get_status) { + if (state->config->tuner_get_status(fe, ®) < 0) + goto err; + } if (reg) dprintk(FE_DEBUG, 1, "Tuner phase locked"); else dprintk(FE_DEBUG, 1, "Tuner unlocked"); - stv090x_i2c_gate_ctrl(fe, 0); - - reg = STV090x_READ_DEMOD(state, DEMOD); - STV090x_SETFIELD_Px(reg, SPECINV_CONTROL_FIELD, state->inversion); - STV090x_SETFIELD_Px(reg, MANUAL_ROLLOFF_FIELD, 1); - if (STV090x_WRITE_DEMOD(state, DEMOD, reg) < 0) + if (stv090x_i2c_gate_ctrl(fe, 0) < 0) goto err; - stv090x_delivery_search(state); - if (state->algo != STV090x_BLIND_SEARCH) - stv090x_start_search(state); - if (state->dev_ver == 0x12) { - reg = STV090x_READ_DEMOD(state, TSCFGH); - STV090x_SETFIELD_Px(reg, RST_HWARE_FIELD, 0); /* release merger reset */ - if (STV090x_WRITE_DEMOD(state, TSCFGH, reg) < 0) - goto err; - msleep(3); - STV090x_SETFIELD_Px(reg, RST_HWARE_FIELD, 1); /* merger reset */ - if (STV090x_WRITE_DEMOD(state, TSCFGH, reg) < 0) + msleep(10); + agc1_power = MAKEWORD16(STV090x_READ_DEMOD(state, AGCIQIN1), + STV090x_READ_DEMOD(state, AGCIQIN0)); + + if (agc1_power == 0) { + /* If AGC1 integrator value is 0 + * then read POWERI, POWERQ + */ + for (i = 0; i < 5; i++) { + power_iq += (STV090x_READ_DEMOD(state, POWERI) + + STV090x_READ_DEMOD(state, POWERQ)) >> 1; + } + power_iq /= 5; + } + + if ((agc1_power == 0) && (power_iq < STV090x_IQPOWER_THRESHOLD)) { + dprintk(FE_ERROR, 1, "No Signal: POWER_IQ=0x%02x", power_iq); + lock = 0; + + } else { + reg = STV090x_READ_DEMOD(state, DEMOD); + STV090x_SETFIELD_Px(reg, SPECINV_CONTROL_FIELD, state->inversion); + + if (state->dev_ver <= 0x20) { + /* rolloff to auto mode if DVBS2 */ + STV090x_SETFIELD_Px(reg, MANUAL_SXROLLOFF_FIELD, 1); + } else { + /* DVB-S2 rolloff to auto mode if DVBS2 */ + STV090x_SETFIELD_Px(reg, MANUAL_S2ROLLOFF_FIELD, 1); + } + if (STV090x_WRITE_DEMOD(state, DEMOD, reg) < 0) goto err; - STV090x_SETFIELD_Px(reg, RST_HWARE_FIELD, 0); /* release merger reset */ - if (STV090x_WRITE_DEMOD(state, TSCFGH, reg) < 0) + + if (stv090x_delivery_search(state) < 0) goto err; + + if (state->algo != STV090x_BLIND_SEARCH) { + if (stv090x_start_search(state) < 0) + goto err; + } } + /* need to check for AGC1 state */ + + + if (state->algo == STV090x_BLIND_SEARCH) lock = stv090x_blind_search(state); + else if (state->algo == STV090x_COLD_SEARCH) lock = stv090x_get_coldlock(state, timeout_dmd); + else if (state->algo == STV090x_WARM_SEARCH) lock = stv090x_get_dmdlock(state, timeout_dmd); @@ -3845,32 +4033,18 @@ static enum stv090x_signal_state stv090x_algo(struct stv090x_state *state) if ((lock) && (signal_state == STV090x_RANGEOK)) { /* signal within Range */ stv090x_optimize_track(state); - if (state->dev_ver <= 0x11) { /*workaround for dual DVBS1 cut 1.1 and 1.0 only*/ - if (stv090x_get_std(state) == STV090x_DVBS1) { - msleep(20); - reg = STV090x_READ_DEMOD(state, TSCFGH); - STV090x_SETFIELD_Px(reg, RST_HWARE_FIELD, 0); /* release merger reset */ - if (STV090x_WRITE_DEMOD(state, TSCFGH, reg) < 0) - goto err; - } else { - reg = STV090x_READ_DEMOD(state, TSCFGH); - STV090x_SETFIELD_Px(reg, RST_HWARE_FIELD, 0); /* release merger reset */ - if (STV090x_WRITE_DEMOD(state, TSCFGH, reg) < 0) - goto err; - msleep(3); - STV090x_SETFIELD_Px(reg, RST_HWARE_FIELD, 1); /* merger reset */ - if (STV090x_WRITE_DEMOD(state, TSCFGH, reg) < 0) - goto err; - STV090x_SETFIELD_Px(reg, RST_HWARE_FIELD, 0); /* release merger reset */ - if (STV090x_WRITE_DEMOD(state, TSCFGH, reg) < 0) - goto err; - } - } else if (state->dev_ver == 0x20) { /*cut 2.0 :release TS reset after demod lock and TrackingOptimization*/ + + if (state->dev_ver >= 0x20) { + /* >= Cut 2.0 :release TS reset after + * demod lock and optimized Tracking + */ reg = STV090x_READ_DEMOD(state, TSCFGH); STV090x_SETFIELD_Px(reg, RST_HWARE_FIELD, 0); /* release merger reset */ if (STV090x_WRITE_DEMOD(state, TSCFGH, reg) < 0) goto err; + msleep(3); + STV090x_SETFIELD_Px(reg, RST_HWARE_FIELD, 1); /* merger reset */ if (STV090x_WRITE_DEMOD(state, TSCFGH, reg) < 0) goto err; @@ -3884,18 +4058,27 @@ static enum stv090x_signal_state stv090x_algo(struct stv090x_state *state) lock = 1; if (state->delsys == STV090x_DVBS2) { stv090x_set_s2rolloff(state); - if (STV090x_WRITE_DEMOD(state, PDELCTRL2, 0x40) < 0) + + reg = STV090x_READ_DEMOD(state, PDELCTRL2); + STV090x_SETFIELD_Px(reg, RESET_UPKO_COUNT, 1); + if (STV090x_WRITE_DEMOD(state, PDELCTRL2, reg) < 0) goto err; - if (STV090x_WRITE_DEMOD(state, PDELCTRL2, 0x00) < 0) /* RESET counter */ + /* Reset DVBS2 packet delinator error counter */ + reg = STV090x_READ_DEMOD(state, PDELCTRL2); + STV090x_SETFIELD_Px(reg, RESET_UPKO_COUNT, 0); + if (STV090x_WRITE_DEMOD(state, PDELCTRL2, reg) < 0) goto err; + if (STV090x_WRITE_DEMOD(state, ERRCTRL1, 0x67) < 0) /* PER */ goto err; } else { if (STV090x_WRITE_DEMOD(state, ERRCTRL1, 0x75) < 0) goto err; } + /* Reset the Total packet counter */ if (STV090x_WRITE_DEMOD(state, FBERCPT4, 0x00) < 0) goto err; + /* Reset the packet Error counter2 */ if (STV090x_WRITE_DEMOD(state, ERRCTRL2, 0xc1) < 0) goto err; } else { @@ -3904,13 +4087,6 @@ static enum stv090x_signal_state stv090x_algo(struct stv090x_state *state) no_signal = stv090x_chk_signal(state); } } - if ((signal_state == STV090x_NODATA) && (!no_signal)) { - if (state->dev_ver <= 0x11) { - reg = STV090x_READ_DEMOD(state, DMDSTATE); - if (((STV090x_GETFIELD_Px(reg, HEADER_MODE_FIELD)) == STV090x_DVBS1) && (state->inversion == INVERSION_AUTO)) - signal_state = stv090x_acq_fixs1(state); - } - } return signal_state; err: @@ -4363,17 +4539,18 @@ static void stv090x_release(struct dvb_frontend *fe) static int stv090x_ldpc_mode(struct stv090x_state *state, enum stv090x_mode ldpc_mode) { - u32 reg; + u32 reg = 0; switch (ldpc_mode) { case STV090x_DUAL: default: - reg = stv090x_read_reg(state, STV090x_GENCFG); if ((state->demod_mode != STV090x_DUAL) || (STV090x_GETFIELD(reg, DDEMOD_FIELD) != 1)) { - /* follow LDPC default state */ - if (stv090x_write_reg(state, STV090x_GENCFG, reg) < 0) + /* set LDPC to dual mode */ + if (stv090x_write_reg(state, STV090x_GENCFG, 0x1d) < 0) goto err; + state->demod_mode = STV090x_DUAL; + reg = stv090x_read_reg(state, STV090x_TSTRES0); STV090x_SETFIELD(reg, FRESFEC_FIELD, 0x1); if (stv090x_write_reg(state, STV090x_TSTRES0, reg) < 0) @@ -4381,10 +4558,50 @@ static int stv090x_ldpc_mode(struct stv090x_state *state, enum stv090x_mode ldpc STV090x_SETFIELD(reg, FRESFEC_FIELD, 0x0); if (stv090x_write_reg(state, STV090x_TSTRES0, reg) < 0) goto err; + + if (STV090x_WRITE_DEMOD(state, MODCODLST0, 0xff) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, MODCODLST1, 0xff) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, MODCODLST2, 0xff) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, MODCODLST3, 0xff) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, MODCODLST4, 0xff) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, MODCODLST5, 0xff) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, MODCODLST6, 0xff) < 0) + goto err; + + if (STV090x_WRITE_DEMOD(state, MODCODLST7, 0xcc) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, MODCODLST8, 0xcc) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, MODCODLST9, 0xcc) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, MODCODLSTA, 0xcc) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, MODCODLSTB, 0xcc) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, MODCODLSTC, 0xcc) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, MODCODLSTD, 0xcc) < 0) + goto err; + + if (STV090x_WRITE_DEMOD(state, MODCODLSTE, 0xff) < 0) + goto err; + if (STV090x_WRITE_DEMOD(state, MODCODLSTF, 0xcf) < 0) + goto err; } break; case STV090x_SINGLE: + if (stv090x_stop_modcod(state) < 0) + goto err; + if (stv090x_activate_modcod_single(state) < 0) + goto err; + if (state->demod == STV090x_DEMODULATOR_1) { if (stv090x_write_reg(state, STV090x_GENCFG, 0x06) < 0) /* path 2 */ goto err; @@ -4670,7 +4887,8 @@ static int stv090x_init(struct dvb_frontend *fe) goto err; } - stv090x_ldpc_mode(state, state->demod_mode); + if (stv090x_ldpc_mode(state, state->demod_mode) < 0) + goto err; reg = STV090x_READ_DEMOD(state, TNRCFG2); STV090x_SETFIELD_Px(reg, TUN_IQSWAP_FIELD, state->inversion); @@ -4681,16 +4899,24 @@ static int stv090x_init(struct dvb_frontend *fe) if (STV090x_WRITE_DEMOD(state, DEMOD, reg) < 0) goto err; - stv090x_i2c_gate_ctrl(fe, 1); + if (stv090x_i2c_gate_ctrl(fe, 1) < 0) + goto err; - if (config->tuner_set_mode) - config->tuner_set_mode(fe, TUNER_WAKE); - if (config->tuner_init) - config->tuner_init(fe); + if (config->tuner_set_mode) { + if (config->tuner_set_mode(fe, TUNER_WAKE) < 0) + goto err; + } - stv090x_i2c_gate_ctrl(fe, 0); + if (config->tuner_init) { + if (config->tuner_init(fe) < 0) + goto err; + } - stv090x_set_tspath(state); + if (stv090x_i2c_gate_ctrl(fe, 0) < 0) + goto err; + + if (stv090x_set_tspath(state) < 0) + goto err; return 0; err: @@ -4776,6 +5002,16 @@ static int stv090x_setup(struct dvb_frontend *fe) if (stv090x_write_reg(state, stv090x_cut20_val[i].addr, stv090x_cut20_val[i].data) < 0) goto err; } + + } else if (state->dev_ver < 0x20) { + dprintk(FE_ERROR, 1, "ERROR: Unsupported Cut: 0x%02x!", + state->dev_ver); + + goto err; + } else if (state->dev_ver > 0x30) { + /* we shouldn't bail out from here */ + dprintk(FE_ERROR, 1, "INFO: Cut: 0x%02x probably incomplete support!", + state->dev_ver); } if (stv090x_write_reg(state, STV090x_TSTRES0, 0x80) < 0) diff --git a/linux/drivers/media/dvb/frontends/stv090x.h b/linux/drivers/media/dvb/frontends/stv090x.h index 5a567b3b4..e968c98bb 100644 --- a/linux/drivers/media/dvb/frontends/stv090x.h +++ b/linux/drivers/media/dvb/frontends/stv090x.h @@ -74,14 +74,6 @@ struct stv090x_config { u8 ts2_mode; enum stv090x_i2crpt repeater_level; -#if 0 - int (*tuner_init) (struct dvb_frontend *fe); - int (*tuner_set_frequency) (struct dvb_frontend *fe, u32 frequency); - int (*tuner_get_frequency) (struct dvb_frontend *fe, u32 *frequency); - int (*tuner_set_bandwidth) (struct dvb_frontend *fe, u32 bandwidth); - int (*tuner_get_bandwidth) (struct dvb_frontend *fe, u32 *bandwidth); - int (*tuner_set_refclock) (struct dvb_frontend *fe, u32 refclk); -#endif int (*tuner_init) (struct dvb_frontend *fe); int (*tuner_set_mode) (struct dvb_frontend *fe, enum tuner_mode mode); diff --git a/linux/drivers/media/dvb/frontends/stv090x_priv.h b/linux/drivers/media/dvb/frontends/stv090x_priv.h index 9d536226e..5a4a01740 100644 --- a/linux/drivers/media/dvb/frontends/stv090x_priv.h +++ b/linux/drivers/media/dvb/frontends/stv090x_priv.h @@ -77,7 +77,18 @@ #define MAKEWORD16(__a, __b) (((__a) << 8) | (__b)) -#define STV090x_SEARCH_AGC2_TH 700 +#define MSB(__x) ((__x >> 8) & 0xff) +#define LSB(__x) (__x & 0xff) + + +#define STV090x_IQPOWER_THRESHOLD 30 +#define STV090x_SEARCH_AGC2_TH_CUT20 700 +#define STV090x_SEARCH_AGC2_TH_CUT30 1200 + +#define STV090x_SEARCH_AGC2_TH(__ver) \ + ((__ver <= 0x20) ? \ + STV090x_SEARCH_AGC2_TH_CUT20 : \ + STV090x_SEARCH_AGC2_TH_CUT30) enum stv090x_signal_state { STV090x_NOCARRIER, @@ -201,24 +212,8 @@ struct stv090x_long_frame_crloop { struct stv090x_short_frame_crloop { enum stv090x_modulation modulation; - u8 crl_cut12_2; /* Cut 1.2, SR <= 3M */ - u8 crl_cut20_2; /* Cut 2.0, SR < 3M */ - u8 crl_cut12_5; /* Cut 1.2, 3 < SR <= 7M */ - u8 crl_cut20_5; /* Cut 2.0, 3 < SR <= 7M */ - u8 crl_cut12_10; /* Cut 1.2, 7 < SR <= 15M */ - u8 crl_cut20_10; /* Cut 2.0, 7 < SR <= 15M */ - u8 crl_cut12_20; /* Cut 1.2, 10 < SR <= 25M */ - u8 crl_cut20_20; /* Cut 2.0, 10 < SR <= 25M */ - u8 crl_cut12_30; /* Cut 1.2, 25 < SR <= 45M */ - u8 crl_cut20_30; /* Cut 2.0, 10 < SR <= 45M */ -}; - - -struct stv090x_short_frame_vsmod_crloop { - enum stv090x_modulation modulation; - - u8 crl_2; /* < 3M */ - u8 crl_5; /* 3 < SR <= 7M */ + u8 crl_2; /* SR < 3M */ + u8 crl_5; /* 3 < SR <= 7M */ u8 crl_10; /* 7 < SR <= 15M */ u8 crl_20; /* 10 < SR <= 25M */ u8 crl_30; /* 10 < SR <= 45M */ diff --git a/linux/drivers/media/dvb/frontends/stv090x_reg.h b/linux/drivers/media/dvb/frontends/stv090x_reg.h index 55737074e..57b6abbbd 100644 --- a/linux/drivers/media/dvb/frontends/stv090x_reg.h +++ b/linux/drivers/media/dvb/frontends/stv090x_reg.h @@ -793,10 +793,16 @@ #define STV090x_Px_DEMOD(__x) (0xF410 - (__x - 1) * 0x200) #define STV090x_P1_DEMOD STV090x_Px_DEMOD(1) #define STV090x_P2_DEMOD STV090x_Px_DEMOD(2) +#define STV090x_OFFST_Px_MANUAL_S2ROLLOFF_FIELD 7 +#define STV090x_WIDTH_Px_MANUAL_S2ROLLOFF_FIELD 1 +#define STV090x_OFFST_Px_DEMOD_STOP_FIELD 6 +#define STV090x_WIDTH_Px_DEMOD_STOP_FIELD 1 #define STV090x_OFFST_Px_SPECINV_CONTROL_FIELD 4 #define STV090x_WIDTH_Px_SPECINV_CONTROL_FIELD 2 -#define STV090x_OFFST_Px_MANUAL_ROLLOFF_FIELD 2 -#define STV090x_WIDTH_Px_MANUAL_ROLLOFF_FIELD 1 +#define STV090x_OFFST_Px_FORCE_ENASAMP_FIELD 3 +#define STV090x_WIDTH_Px_FORCE_ENASAMP_FIELD 1 +#define STV090x_OFFST_Px_MANUAL_SXROLLOFF_FIELD 2 +#define STV090x_WIDTH_Px_MANUAL_SXROLLOFF_FIELD 1 #define STV090x_OFFST_Px_ROLLOFF_CONTROL_FIELD 0 #define STV090x_WIDTH_Px_ROLLOFF_CONTROL_FIELD 2 @@ -1566,6 +1572,42 @@ #define STV090x_OFFST_Px_DIS_QP_1_4_FIELD 4 #define STV090x_WIDTH_Px_DIS_QP_1_4_FIELD 4 +#define STV090x_Px_GAUSSR0(__x) (0xf4c0 - (__x - 1) * 0x200) +#define STV090x_P1_GAUSSR0 STV090x_Px_GAUSSR0(1) +#define STV090x_P2_GAUSSR0 STV090x_Px_GAUSSR0(2) +#define STV090x_OFFST_Px_EN_CCIMODE_FIELD 7 +#define STV090x_WIDTH_Px_EN_CCIMODE_FIELD 1 +#define STV090x_OFFST_Px_R0_GAUSSIEN_FIELD 0 +#define STV090x_WIDTH_Px_R0_GAUSSIEN_FIELD 7 + +#define STV090x_Px_CCIR0(__x) (0xf4c1 - (__x - 1) * 0x200) +#define STV090x_P1_CCIR0 STV090x_Px_CCIR0(1) +#define STV090x_P2_CCIR0 STV090x_Px_CCIR0(2) +#define STV090x_OFFST_Px_CCIDETECT_PLH_FIELD 7 +#define STV090x_WIDTH_Px_CCIDETECT_PLH_FIELD 1 +#define STV090x_OFFST_Px_R0_CCI_FIELD 0 +#define STV090x_WIDTH_Px_R0_CCI_FIELD 7 + +#define STV090x_Px_CCIQUANT(__x) (0xf4c2 - (__x - 1) * 0x200) +#define STV090x_P1_CCIQUANT STV090x_Px_CCIQUANT(1) +#define STV090x_P2_CCIQUANT STV090x_Px_CCIQUANT(2) +#define STV090x_OFFST_Px_CCI_BETA_FIELD 5 +#define STV090x_WIDTH_Px_CCI_BETA_FIELD 3 +#define STV090x_OFFST_Px_CCI_QUANT_FIELD 0 +#define STV090x_WIDTH_Px_CCI_QUANT_FIELD 5 + +#define STV090x_Px_CCITHRESH(__x) (0xf4c3 - (__x - 1) * 0x200) +#define STV090x_P1_CCITHRESH STV090x_Px_CCITHRESH(1) +#define STV090x_P2_CCITHRESH STV090x_Px_CCITHRESH(2) +#define STV090x_OFFST_Px_CCI_THRESHOLD_FIELD 0 +#define STV090x_WIDTH_Px_CCI_THRESHOLD_FIELD 8 + +#define STV090x_Px_CCIACC(__x) (0xf4c4 - (__x - 1) * 0x200) +#define STV090x_P1_CCIACC STV090x_Px_CCIACC(1) +#define STV090x_P2_CCIACC STV090x_Px_CCIACC(1) +#define STV090x_OFFST_Px_CCI_VALUE_FIELD 0 +#define STV090x_WIDTH_Px_CCI_VALUE_FIELD 8 + #define STV090x_Px_DMDRESCFG(__x) (0xF4C6 - (__x - 1) * 0x200) #define STV090x_P1_DMDRESCFG STV090x_Px_DMDRESCFG(1) #define STV090x_P2_DMDRESCFG STV090x_Px_DMDRESCFG(2) @@ -1847,16 +1889,28 @@ #define STV090x_Px_PDELCTRL2(__x) (0xf551 - (__x - 1) * 0x200) #define STV090x_P1_PDELCTRL2 STV090x_Px_PDELCTRL2(1) #define STV090x_P2_PDELCTRL2 STV090x_Px_PDELCTRL2(2) +#define STV090x_OFFST_Px_FORCE_CONTINUOUS 7 +#define STV090x_WIDTH_Px_FORCE_CONTINUOUS 1 +#define STV090x_OFFST_Px_RESET_UPKO_COUNT 6 +#define STV090x_WIDTH_Px_RESET_UPKO_COUNT 1 +#define STV090x_OFFST_Px_USER_PKTDELIN_NB 5 +#define STV090x_WIDTH_Px_USER_PKTDELIN_NB 1 +#define STV090x_OFFST_Px_FORCE_LOCKED 4 +#define STV090x_WIDTH_Px_FORCE_LOCKED 1 +#define STV090x_OFFST_Px_DATA_UNBBSCRAM 3 +#define STV090x_WIDTH_Px_DATA_UNBBSCRAM 1 +#define STV090x_OFFST_Px_FORCE_LONGPACKET 2 +#define STV090x_WIDTH_Px_FORCE_LONGPACKET 1 #define STV090x_OFFST_Px_FRAME_MODE_FIELD 1 #define STV090x_WIDTH_Px_FRAME_MODE_FIELD 1 -#define STV090x_Px_HYSTTHRESH(__x) (0xf554 - (__x - 1) * 0x200) -#define STV090x_P1_HYSTTHRESH STV090x_Px_HYSTTHRESH(1) -#define STV090x_P2_HYSTTHRESH STV090x_Px_HYSTTHRESH(2) -#define STV090x_OFFST_Px_UNLCK_THRESH_FIELD 4 -#define STV090x_WIDTH_Px_UNLCK_THRESH_FIELD 4 -#define STV090x_OFFST_Px_DELIN_LCK_THRESH_FIELD 0 -#define STV090x_WIDTH_Px_DELIN_LCK_THRESH_FIELD 4 +#define STV090x_Px_HYSTTHRESH(__x) (0xf554 - (__x - 1) * 0x200) +#define STV090x_P1_HYSTTHRESH STV090x_Px_HYSTTHRESH(1) +#define STV090x_P2_HYSTTHRESH STV090x_Px_HYSTTHRESH(2) +#define STV090x_OFFST_Px_UNLCK_THRESH_FIELD 4 +#define STV090x_WIDTH_Px_UNLCK_THRESH_FIELD 4 +#define STV090x_OFFST_Px_DELIN_LCK_THRESH_FIELD 0 +#define STV090x_WIDTH_Px_DELIN_LCK_THRESH_FIELD 4 #define STV090x_Px_ISIENTRY(__x) (0xf55e - (__x - 1) * 0x200) #define STV090x_P1_ISIENTRY STV090x_Px_ISIENTRY(1) -- cgit v1.2.3 From 6ec0c26a8ed7aac236c5269763cb2e98b3930688 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 3 May 2009 09:58:04 +0200 Subject: cafe_ccic: fix sensor detection From: Hans Verkuil Due to an uninitialized chip.ident field the chip identification failed. Priority: high Signed-off-by: Hans Verkuil Thanks-to: saeed bishara Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/cafe_ccic.c | 1 + 1 file changed, 1 insertion(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/cafe_ccic.c b/linux/drivers/media/video/cafe_ccic.c index 40eb073fb..f1119efe6 100644 --- a/linux/drivers/media/video/cafe_ccic.c +++ b/linux/drivers/media/video/cafe_ccic.c @@ -775,6 +775,7 @@ static int cafe_cam_init(struct cafe_camera *cam) ret = __cafe_cam_reset(cam); if (ret) goto out; + chip.ident == V4L2_IDENT_NONE; chip.match.type = V4L2_CHIP_MATCH_I2C_ADDR; chip.match.addr = cam->sensor_addr; ret = sensor_call(cam, core, g_chip_ident, &chip); -- cgit v1.2.3 From 5a57ca61d1316da19d76ac86ef8bf76b2f9b3746 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20Andr=C3=A9n?= Date: Sun, 3 May 2009 20:51:36 +0200 Subject: gspca - stv06xx-vv6410: Set analog gain at init MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: Erik Andrén Set the analog gain at sensor init. Also set a sensible default value. Priority: normal Signed-off-by: Erik Andrén --- linux/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.c b/linux/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.c index f6603a9de..11a0c002f 100644 --- a/linux/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.c +++ b/linux/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.c @@ -80,7 +80,7 @@ static const struct ctrl vv6410_ctrl[] = { .minimum = 0, .maximum = 15, .step = 1, - .default_value = 0 + .default_value = 10 }, .set = vv6410_set_analog_gain, .get = vv6410_get_analog_gain @@ -162,6 +162,11 @@ static int vv6410_init(struct sd *sd) err = vv6410_set_exposure(&sd->gspca_dev, sensor_settings[EXPOSURE_IDX]); + if (err < 0) + return err; + + err = vv6410_set_analog_gain(&sd->gspca_dev, + sensor_settings[GAIN_IDX]); return (err < 0) ? err : 0; } -- cgit v1.2.3 From 2814226386886b18a319856de6512d5cf0297629 Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Sun, 3 May 2009 17:01:57 -0400 Subject: cx18: Have audio decoder drive SIF gain control, and rework AFE config From: Andy Walls Ensure the variable gain amplifier gain for SIF is driven by the audio deocder and not the video decoder. This forced rework of the analog front end (AFE) configuration to not rely on autoconfiguration, but instead set up the AFE mux, AFE parameters, and ADC1 & ADC2 configurations explicitly. Reported-by: Helen Buus Priority: normal Signed-off-by: Andy Walls --- linux/drivers/media/video/cx18/cx18-av-core.c | 234 ++++++++++++++++++-------- 1 file changed, 165 insertions(+), 69 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/cx18/cx18-av-core.c b/linux/drivers/media/video/cx18/cx18-av-core.c index cf2bd888a..2b07b1563 100644 --- a/linux/drivers/media/video/cx18/cx18-av-core.c +++ b/linux/drivers/media/video/cx18/cx18-av-core.c @@ -99,9 +99,39 @@ int cx18_av_and_or4(struct cx18 *cx, u16 addr, u32 and_mask, or_value); } -static void cx18_av_initialize(struct cx18 *cx) +static int cx18_av_init(struct v4l2_subdev *sd, u32 val) { - struct cx18_av_state *state = &cx->av_state; + struct cx18 *cx = v4l2_get_subdevdata(sd); + + /* + * The crystal freq used in calculations in this driver will be + * 28.636360 MHz. + * Aim to run the PLLs' VCOs near 400 MHz to minimze errors. + */ + + /* + * VDCLK Integer = 0x0f, Post Divider = 0x04 + * AIMCLK Integer = 0x0e, Post Divider = 0x16 + */ + cx18_av_write4(cx, CXADEC_PLL_CTRL1, 0x160e040f); + + /* VDCLK Fraction = 0x2be2fe */ + /* xtal * 0xf.15f17f0/4 = 108 MHz: 432 MHz before post divide */ + cx18_av_write4(cx, CXADEC_VID_PLL_FRAC, 0x002be2fe); + + /* AIMCLK Fraction = 0x05227ad */ + /* xtal * 0xe.2913d68/0x16 = 48000 * 384: 406 MHz pre post-div*/ + cx18_av_write4(cx, CXADEC_AUX_PLL_FRAC, 0x005227ad); + + /* SA_MCLK_SEL=1, SA_MCLK_DIV=0x16 */ + cx18_av_write(cx, CXADEC_I2S_MCLK, 0x56); + return 0; +} + +static void cx18_av_initialize(struct v4l2_subdev *sd) +{ + struct cx18_av_state *state = to_cx18_av_state(sd); + struct cx18 *cx = v4l2_get_subdevdata(sd); u32 v; cx18_av_loadfw(cx); @@ -150,6 +180,26 @@ static void cx18_av_initialize(struct cx18 *cx) cx18_av_write4(cx, CXADEC_SOFT_RST_CTRL, 0x8000); cx18_av_write4(cx, CXADEC_SOFT_RST_CTRL, 0); + /* + * Disable Video Auto-config of the Analog Front End and Video PLL. + * + * Since we only use BT.656 pixel mode, which works for both 525 and 625 + * line systems, it's just easier for us to set registers + * 0x102 (CXADEC_CHIP_CTRL), 0x104-0x106 (CXADEC_AFE_CTRL), + * 0x108-0x109 (CXADEC_PLL_CTRL1), and 0x10c-0x10f (CXADEC_VID_PLL_FRAC) + * ourselves, than to run around cleaning up after the auto-config. + * + * (Note: my CX23418 chip doesn't seem to let the ACFG_DIS bit + * get set to 1, but OTOH, it doesn't seem to do AFE and VID PLL + * autoconfig either.) + * + * As a default, also turn off Dual mode for ADC2 and set ADC2 to CH3. + */ + cx18_av_and_or4(cx, CXADEC_CHIP_CTRL, 0xFFFBFFFF, 0x00120000); + + /* Setup the Video and and Aux/Audio PLLs */ + cx18_av_init(sd, 0); + /* set video to auto-detect */ /* Clear bits 11-12 to enable slow locking mode. Set autodetect mode */ /* set the comb notch = 1 */ @@ -176,12 +226,23 @@ static void cx18_av_initialize(struct cx18 *cx) /* EncSetSignalStd(dwDevNum, pEnc->dwSigStd); */ /* EncSetVideoInput(dwDevNum, pEnc->VidIndSelection); */ - v = cx18_av_read4(cx, CXADEC_AFE_CTRL); - v &= 0xFFFBFFFF; /* turn OFF bit 18 for droop_comp_ch1 */ - v &= 0xFFFF7FFF; /* turn OFF bit 9 for clamp_sel_ch1 */ - v &= 0xFFFFFFFE; /* turn OFF bit 0 for 12db_ch1 */ - /* v |= 0x00000001;*/ /* turn ON bit 0 for 12db_ch1 */ - cx18_av_write4(cx, CXADEC_AFE_CTRL, v); + /* + * Analog Front End (AFE) + * Default to luma on ch1/ADC1, chroma on ch2/ADC2, SIF on ch3/ADC2 + * bypass_ch[1-3] use filter + * droop_comp_ch[1-3] disable + * clamp_en_ch[1-3] disable + * aud_in_sel ADC2 + * luma_in_sel ADC1 + * chroma_in_sel ADC2 + * clamp_sel_ch[2-3] midcode + * clamp_sel_ch1 video decoder + * vga_sel_ch3 audio decoder + * vga_sel_ch[1-2] video decoder + * half_bw_ch[1-3] disable + * +12db_ch[1-3] disable + */ + cx18_av_and_or4(cx, CXADEC_AFE_CTRL, 0xFF000000, 0x00005D00); /* if(dwEnable && dw3DCombAvailable) { */ /* CxDevWrReg(CXADEC_SRC_COMB_CFG, 0x7728021F); */ @@ -195,50 +256,18 @@ static void cx18_av_initialize(struct cx18 *cx) static int cx18_av_reset(struct v4l2_subdev *sd, u32 val) { - struct cx18 *cx = v4l2_get_subdevdata(sd); - - cx18_av_initialize(cx); - return 0; -} - -static int cx18_av_init(struct v4l2_subdev *sd, u32 val) -{ - struct cx18 *cx = v4l2_get_subdevdata(sd); - - /* - * The crystal freq used in calculations in this driver will be - * 28.636360 MHz. - * Aim to run the PLLs' VCOs near 400 MHz to minimze errors. - */ - - /* - * VDCLK Integer = 0x0f, Post Divider = 0x04 - * AIMCLK Integer = 0x0e, Post Divider = 0x16 - */ - cx18_av_write4(cx, CXADEC_PLL_CTRL1, 0x160e040f); - - /* VDCLK Fraction = 0x2be2fe */ - /* xtal * 0xf.15f17f0/4 = 108 MHz: 432 MHz before post divide */ - cx18_av_write4(cx, CXADEC_VID_PLL_FRAC, 0x002be2fe); - - /* AIMCLK Fraction = 0x05227ad */ - /* xtal * 0xe.2913d68/0x16 = 48000 * 384: 406 MHz pre post-div*/ - cx18_av_write4(cx, CXADEC_AUX_PLL_FRAC, 0x005227ad); - - /* SA_MCLK_SEL=1, SA_MCLK_DIV=0x16 */ - cx18_av_write(cx, CXADEC_I2S_MCLK, 0x56); + cx18_av_initialize(sd); return 0; } static int cx18_av_load_fw(struct v4l2_subdev *sd) { struct cx18_av_state *state = to_cx18_av_state(sd); - struct cx18 *cx = v4l2_get_subdevdata(sd); if (!state->is_initialized) { /* initialize on first use */ state->is_initialized = 1; - cx18_av_initialize(cx); + cx18_av_initialize(sd); } return 0; } @@ -470,16 +499,23 @@ static int set_input(struct cx18 *cx, enum cx18_av_video_input vid_input, { struct cx18_av_state *state = &cx->av_state; struct v4l2_subdev *sd = &state->sd; - u8 is_composite = (vid_input >= CX18_AV_COMPOSITE1 && - vid_input <= CX18_AV_COMPOSITE8); - u8 reg; - u8 v; + + enum analog_signal_type { + NONE, CVBS, Y, C, SIF, Pb, Pr + } ch[3] = {NONE, NONE, NONE}; + + u8 afe_mux_cfg; + u8 adc2_cfg; + u32 afe_cfg; + int i; CX18_DEBUG_INFO_DEV(sd, "decoder set video input %d, audio input %d\n", vid_input, aud_input); - if (is_composite) { - reg = 0xf0 + (vid_input - CX18_AV_COMPOSITE1); + if (vid_input >= CX18_AV_COMPOSITE1 && + vid_input <= CX18_AV_COMPOSITE8) { + afe_mux_cfg = 0xf0 + (vid_input - CX18_AV_COMPOSITE1); + ch[0] = CVBS; } else { int luma = vid_input & 0xf0; int chroma = vid_input & 0xf00; @@ -493,26 +529,45 @@ static int set_input(struct cx18 *cx, enum cx18_av_video_input vid_input, vid_input); return -EINVAL; } - reg = 0xf0 + ((luma - CX18_AV_SVIDEO_LUMA1) >> 4); + afe_mux_cfg = 0xf0 + ((luma - CX18_AV_SVIDEO_LUMA1) >> 4); + ch[0] = Y; if (chroma >= CX18_AV_SVIDEO_CHROMA7) { - reg &= 0x3f; - reg |= (chroma - CX18_AV_SVIDEO_CHROMA7) >> 2; + afe_mux_cfg &= 0x3f; + afe_mux_cfg |= (chroma - CX18_AV_SVIDEO_CHROMA7) >> 2; + ch[2] = C; } else { - reg &= 0xcf; - reg |= (chroma - CX18_AV_SVIDEO_CHROMA4) >> 4; + afe_mux_cfg &= 0xcf; + afe_mux_cfg |= (chroma - CX18_AV_SVIDEO_CHROMA4) >> 4; + ch[1] = C; } } + /* TODO: LeadTek WinFast DVR3100 H & WinFast PVR2100 can do Y/Pb/Pr */ switch (aud_input) { case CX18_AV_AUDIO_SERIAL1: case CX18_AV_AUDIO_SERIAL2: /* do nothing, use serial audio input */ break; - case CX18_AV_AUDIO4: reg &= ~0x30; break; - case CX18_AV_AUDIO5: reg &= ~0x30; reg |= 0x10; break; - case CX18_AV_AUDIO6: reg &= ~0x30; reg |= 0x20; break; - case CX18_AV_AUDIO7: reg &= ~0xc0; break; - case CX18_AV_AUDIO8: reg &= ~0xc0; reg |= 0x40; break; + case CX18_AV_AUDIO4: + afe_mux_cfg &= ~0x30; + ch[1] = SIF; + break; + case CX18_AV_AUDIO5: + afe_mux_cfg = (afe_mux_cfg & ~0x30) | 0x10; + ch[1] = SIF; + break; + case CX18_AV_AUDIO6: + afe_mux_cfg = (afe_mux_cfg & ~0x30) | 0x20; + ch[1] = SIF; + break; + case CX18_AV_AUDIO7: + afe_mux_cfg &= ~0xc0; + ch[2] = SIF; + break; + case CX18_AV_AUDIO8: + afe_mux_cfg = (afe_mux_cfg & ~0xc0) | 0x40; + ch[2] = SIF; + break; default: CX18_ERR_DEV(sd, "0x%04x is not a valid audio input!\n", @@ -520,24 +575,65 @@ static int set_input(struct cx18 *cx, enum cx18_av_video_input vid_input, return -EINVAL; } - cx18_av_write_expect(cx, 0x103, reg, reg, 0xf7); + /* Set up analog front end multiplexers */ + cx18_av_write_expect(cx, 0x103, afe_mux_cfg, afe_mux_cfg, 0xf7); /* Set INPUT_MODE to Composite (0) or S-Video (1) */ - cx18_av_and_or(cx, 0x401, ~0x6, is_composite ? 0 : 0x02); + cx18_av_and_or(cx, 0x401, ~0x6, ch[0] == CVBS ? 0 : 0x02); /* Set CH_SEL_ADC2 to 1 if input comes from CH3 */ - v = cx18_av_read(cx, 0x102); - if (reg & 0x80) - v &= ~0x2; + adc2_cfg = cx18_av_read(cx, 0x102); + if (ch[2] == NONE) + adc2_cfg &= ~0x2; /* No sig on CH3, set ADC2 to CH2 for input */ else - v |= 0x2; + adc2_cfg |= 0x2; /* Signal on CH3, set ADC2 to CH3 for input */ + /* Set DUAL_MODE_ADC2 to 1 if input comes from both CH2 and CH3 */ - if ((reg & 0xc0) != 0xc0 && (reg & 0x30) != 0x30) - v |= 0x4; + if (ch[1] != NONE && ch[2] != NONE) + adc2_cfg |= 0x4; /* Set dual mode */ else - v &= ~0x4; - cx18_av_write_expect(cx, 0x102, v, v, 0x17); + adc2_cfg &= ~0x4; /* Clear dual mode */ + cx18_av_write_expect(cx, 0x102, adc2_cfg, adc2_cfg, 0x17); + + /* Configure the analog front end */ + afe_cfg = cx18_av_read4(cx, CXADEC_AFE_CTRL); + afe_cfg &= 0xff000000; + afe_cfg |= 0x00005000; /* CHROMA_IN, AUD_IN: ADC2; LUMA_IN: ADC1 */ + if (ch[1] != NONE && ch[2] != NONE) + afe_cfg |= 0x00000030; /* half_bw_ch[2-3] since in dual mode */ + + for (i = 0; i < 3; i++) { + switch (ch[i]) { + default: + case NONE: + /* CLAMP_SEL = Fixed to midcode clamp level */ + afe_cfg |= (0x00000200 << i); + break; + case CVBS: + case Y: + if (i > 0) + afe_cfg |= 0x00002000; /* LUMA_IN_SEL: ADC2 */ + break; + case C: + case Pb: + case Pr: + /* CLAMP_SEL = Fixed to midcode clamp level */ + afe_cfg |= (0x00000200 << i); + if (i == 0 && ch[i] == C) + afe_cfg &= ~0x00001000; /* CHROMA_IN_SEL ADC1 */ + break; + case SIF: + /* + * VGA_GAIN_SEL = Audio Decoder + * CLAMP_SEL = Fixed to midcode clamp level + */ + afe_cfg |= (0x00000240 << i); + if (i == 0) + afe_cfg &= ~0x00004000; /* AUD_IN_SEL ADC1 */ + break; + } + } - /*cx18_av_and_or4(cx, 0x104, ~0x001b4180, 0x00004180);*/ + cx18_av_write4(cx, CXADEC_AFE_CTRL, afe_cfg); state->vid_input = vid_input; state->aud_input = aud_input; -- cgit v1.2.3 From add6db3f5ca3f7cf4e3a0fd1f2c347319537e10a Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Sun, 3 May 2009 22:27:02 -0400 Subject: cx23885: add ATSC/QAM tuning support for Hauppauge WinTV-HVR1270 From: Michael Krufky Priority: normal Signed-off-by: Michael Krufky --- linux/drivers/media/video/cx23885/cx23885-cards.c | 1 + linux/drivers/media/video/cx23885/cx23885-dvb.c | 34 +++++++++++++++++++++++ 2 files changed, 35 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/cx23885/cx23885-cards.c b/linux/drivers/media/video/cx23885/cx23885-cards.c index bd608b4a0..299182227 100644 --- a/linux/drivers/media/video/cx23885/cx23885-cards.c +++ b/linux/drivers/media/video/cx23885/cx23885-cards.c @@ -184,6 +184,7 @@ struct cx23885_board cx23885_boards[] = { }, [CX23885_BOARD_HAUPPAUGE_HVR1270] = { .name = "Hauppauge WinTV-HVR1270", + .portc = CX23885_MPEG_DVB, }, }; const unsigned int cx23885_bcount = ARRAY_SIZE(cx23885_boards); diff --git a/linux/drivers/media/video/cx23885/cx23885-dvb.c b/linux/drivers/media/video/cx23885/cx23885-dvb.c index eb3293789..b60f68a6d 100644 --- a/linux/drivers/media/video/cx23885/cx23885-dvb.c +++ b/linux/drivers/media/video/cx23885/cx23885-dvb.c @@ -52,6 +52,7 @@ #include "cimax2.h" #include "netup-eeprom.h" #include "netup-init.h" +#include "lgdt3305.h" static unsigned int debug; @@ -227,6 +228,28 @@ static struct tda18271_config hauppauge_hvr1200_tuner_config = { .gate = TDA18271_GATE_ANALOG, }; +static struct tda18271_std_map hcw_lgdt3305_tda18271_std_map = { + .atsc_6 = { .if_freq = 3250, .agc_mode = 3, .std = 4, + .if_lvl = 1, .rfagc_top = 0x58 }, + .qam_6 = { .if_freq = 4000, .agc_mode = 3, .std = 5, + .if_lvl = 1, .rfagc_top = 0x58 }, +}; + +static struct tda18271_config hcw_lgdt3305_tda18271_config = { + .std_map = &hcw_lgdt3305_tda18271_std_map, +}; + +static struct lgdt3305_config hcw_lgdt3305_config = { + .i2c_addr = 0x0e, + .mpeg_mode = LGDT3305_MPEG_SERIAL, + .tpclk_edge = LGDT3305_TPCLK_FALLING_EDGE, + .tpvalid_polarity = LGDT3305_TP_VALID_HIGH, + .deny_i2c_rptr = 1, + .spectral_inversion = 1, + .qam_if_khz = 4000, + .vsb_if_khz = 3250, +}; + static struct dibx000_agc_config xc3028_agc_config = { BAND_VHF | BAND_UHF, /* band_caps */ @@ -399,6 +422,17 @@ static int dvb_register(struct cx23885_tsport *port) &hauppauge_generic_tunerconfig, 0); } break; + case CX23885_BOARD_HAUPPAUGE_HVR1270: + i2c_bus = &dev->i2c_bus[0]; + fe0->dvb.frontend = dvb_attach(lgdt3305_attach, + &hcw_lgdt3305_config, + &i2c_bus->i2c_adap); + if (fe0->dvb.frontend != NULL) { + dvb_attach(tda18271_attach, fe0->dvb.frontend, + 0x60, &dev->i2c_bus[1].i2c_adap, + &hcw_lgdt3305_tda18271_config); + } + break; case CX23885_BOARD_HAUPPAUGE_HVR1800: i2c_bus = &dev->i2c_bus[0]; switch (alt_tuner) { -- 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 6ed58e999798b11865df38e6b6ef8895c29eeed6 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Sat, 9 May 2009 11:21:35 +0200 Subject: gspca - sonixj: Webcams with bridge sn9c128 added. From: Jean-Francois Moine Priority: normal Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/sonixj.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/sonixj.c b/linux/drivers/media/video/gspca/sonixj.c index c01f4e1c9..d7a42ae44 100644 --- a/linux/drivers/media/video/gspca/sonixj.c +++ b/linux/drivers/media/video/gspca/sonixj.c @@ -2246,7 +2246,12 @@ static const __devinitdata struct usb_device_id device_table[] = { #if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE {USB_DEVICE(0x0c45, 0x60fe), BSI(SN9C105, OV7630, 0x21)}, #endif + {USB_DEVICE(0x0c45, 0x6100), BSI(SN9C120, MI0360, 0x5d)}, /*sn9c128*/ /* {USB_DEVICE(0x0c45, 0x6108), BSI(SN9C120, OM6801, 0x??)}, */ + {USB_DEVICE(0x0c45, 0x610a), BSI(SN9C120, OV7648, 0x21)}, /*sn9c128*/ + {USB_DEVICE(0x0c45, 0x610b), BSI(SN9C120, OV7660, 0x21)}, /*sn9c128*/ + {USB_DEVICE(0x0c45, 0x610c), BSI(SN9C120, HV7131R, 0x11)}, /*sn9c128*/ + {USB_DEVICE(0x0c45, 0x610e), BSI(SN9C120, OV7630, 0x21)}, /*sn9c128*/ /* {USB_DEVICE(0x0c45, 0x6122), BSI(SN9C110, ICM105C, 0x??)}, */ /* {USB_DEVICE(0x0c45, 0x6123), BSI(SN9C110, SanyoCCD, 0x??)}, */ {USB_DEVICE(0x0c45, 0x6128), BSI(SN9C110, OM6802, 0x21)}, /*sn9c325?*/ -- cgit v1.2.3 From 0262f12fd25b3da034766687d9bb33774f6a70b0 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Tue, 5 May 2009 09:59:45 +0200 Subject: gspca - vc032x: Bad pixelformat for mi1320_soc. From: Jean-Francois Moine Priority: normal Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/vc032x.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/vc032x.c b/linux/drivers/media/video/gspca/vc032x.c index e994439fa..e69f63770 100644 --- a/linux/drivers/media/video/gspca/vc032x.c +++ b/linux/drivers/media/video/gspca/vc032x.c @@ -166,7 +166,7 @@ static const struct v4l2_pix_format bi_mode[] = { .colorspace = V4L2_COLORSPACE_JPEG, .priv = 5}, #endif - {320, 240, V4L2_PIX_FMT_YVYU, V4L2_FIELD_NONE, + {320, 240, V4L2_PIX_FMT_YUYV, V4L2_FIELD_NONE, .bytesperline = 320, .sizeimage = 320 * 240 * 2, .colorspace = V4L2_COLORSPACE_SRGB, @@ -178,7 +178,7 @@ static const struct v4l2_pix_format bi_mode[] = { .colorspace = V4L2_COLORSPACE_JPEG, .priv = 4}, #endif - {640, 480, V4L2_PIX_FMT_YVYU, V4L2_FIELD_NONE, + {640, 480, V4L2_PIX_FMT_YUYV, V4L2_FIELD_NONE, .bytesperline = 640, .sizeimage = 640 * 480 * 2, .colorspace = V4L2_COLORSPACE_SRGB, @@ -190,7 +190,7 @@ static const struct v4l2_pix_format bi_mode[] = { .colorspace = V4L2_COLORSPACE_JPEG, .priv = 3}, #endif - {1280, 1024, V4L2_PIX_FMT_YVYU, V4L2_FIELD_NONE, + {1280, 1024, V4L2_PIX_FMT_YUYV, V4L2_FIELD_NONE, .bytesperline = 1280, .sizeimage = 1280 * 1024 * 2, .colorspace = V4L2_COLORSPACE_SRGB, -- cgit v1.2.3 From 7e76cabe80ded958fe3848900080e669ce5feb3e Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Tue, 5 May 2009 10:01:11 +0200 Subject: gspca - vc032x: mi1320_soc images are upside-down. From: Jean-Francois Moine Priority: normal Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/vc032x.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/vc032x.c b/linux/drivers/media/video/gspca/vc032x.c index e69f63770..a29c85cac 100644 --- a/linux/drivers/media/video/gspca/vc032x.c +++ b/linux/drivers/media/video/gspca/vc032x.c @@ -2974,6 +2974,8 @@ static int sd_config(struct gspca_dev *gspca_dev, case SENSOR_MI1320_SOC: cam->cam_mode = bi_mode; cam->nmodes = ARRAY_SIZE(bi_mode); + cam->input_flags = V4L2_IN_ST_VFLIP | + V4L2_IN_ST_HFLIP; break; default: cam->cam_mode = vc0323_mode; -- cgit v1.2.3 From e3350f8a84515b83479cd25f1b8c885c0a124c51 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 5 May 2009 08:08:38 -0300 Subject: cafe_ccic: use = instead of == for setting a value at a var From: Mauro Carvalho Chehab /home/v4l/master/v4l/cafe_ccic.c: In function 'cafe_cam_init': /home/v4l/master/v4l/cafe_ccic.c:778: warning: statement with no effect Priority: high CC: Hans Verkuil CC: saeed bishara Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/cafe_ccic.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/cafe_ccic.c b/linux/drivers/media/video/cafe_ccic.c index f1119efe6..4b8ecad1b 100644 --- a/linux/drivers/media/video/cafe_ccic.c +++ b/linux/drivers/media/video/cafe_ccic.c @@ -775,7 +775,7 @@ static int cafe_cam_init(struct cafe_camera *cam) ret = __cafe_cam_reset(cam); if (ret) goto out; - chip.ident == V4L2_IDENT_NONE; + chip.ident = V4L2_IDENT_NONE; chip.match.type = V4L2_CHIP_MATCH_I2C_ADDR; chip.match.addr = cam->sensor_addr; ret = sensor_call(cam, core, g_chip_ident, &chip); -- cgit v1.2.3 From ae3601f13c4816b10e34a719b5f04ebcdc924879 Mon Sep 17 00:00:00 2001 From: Steven Toth Date: Tue, 5 May 2009 18:30:27 -0400 Subject: tda10048: Added option to block i2c gate control from other drivers. From: Steven Toth Currently, DVB-T is broken and this fixes it. The PVRUSB2 has an odd I2C bus configuration where opening the i2c gate on the digital and analog demod causes the tuner to fail. This needs to be protected against for the PVRUSB2. Priority: high Signed-off-by: Steven Toth Signed-off-by: Michael Krufky --- linux/drivers/media/dvb/frontends/tda10048.c | 3 +++ linux/drivers/media/dvb/frontends/tda10048.h | 3 +++ 2 files changed, 6 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/frontends/tda10048.c b/linux/drivers/media/dvb/frontends/tda10048.c index 2233e649e..3163aad5b 100644 --- a/linux/drivers/media/dvb/frontends/tda10048.c +++ b/linux/drivers/media/dvb/frontends/tda10048.c @@ -689,6 +689,9 @@ static int tda10048_i2c_gate_ctrl(struct dvb_frontend *fe, int enable) struct tda10048_state *state = fe->demodulator_priv; dprintk(1, "%s(%d)\n", __func__, enable); + if (state->config->disable_gate_access) + return 0; + if (enable) return tda10048_writereg(state, TDA10048_CONF_C4_1, tda10048_readreg(state, TDA10048_CONF_C4_1) | 0x02); diff --git a/linux/drivers/media/dvb/frontends/tda10048.h b/linux/drivers/media/dvb/frontends/tda10048.h index ab9cf5bd4..ee07b50e9 100644 --- a/linux/drivers/media/dvb/frontends/tda10048.h +++ b/linux/drivers/media/dvb/frontends/tda10048.h @@ -57,6 +57,9 @@ struct tda10048_config { #define TDA10048_CLK_4000 4000 #define TDA10048_CLK_16000 16000 u16 clk_freq_khz; + + /* Disable I2C gate access */ + u8 disable_gate_access; }; #if defined(CONFIG_DVB_TDA10048) || \ -- cgit v1.2.3 From 8b727693b8af14cfee6510a7eccbf4777fa133bc Mon Sep 17 00:00:00 2001 From: Steven Toth Date: Tue, 5 May 2009 18:31:42 -0400 Subject: pvrusb2: Ensure the PVRUSB2 disabled the i2c gate on the tda10048. From: Steven Toth ... else DVB-T tuning will not work. Priority: high Signed-off-by: Steven Toth Signed-off-by: Michael Krufky --- linux/drivers/media/video/pvrusb2/pvrusb2-devattr.c | 1 + 1 file changed, 1 insertion(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-devattr.c b/linux/drivers/media/video/pvrusb2/pvrusb2-devattr.c index 76d42d92e..129de13da 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-devattr.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-devattr.c @@ -286,6 +286,7 @@ static struct tda10048_config hauppauge_tda10048_config = { .inversion = TDA10048_INVERSION_ON, .if_freq_khz = TDA10048_IF_4300, .clk_freq_khz = TDA10048_CLK_16000, + .disable_gate_access = 1, }; static struct tda829x_config tda829x_no_probe = { -- 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 4775def6207228a81a0a99a2ed0b18f95ac56bac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20Andr=C3=A9n?= Date: Wed, 6 May 2009 22:44:45 +0200 Subject: gspca - m5602-s5k4aa: Add vflip quirk for the Lenovo Y300 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: Erik Andrén The Lenovo Y300 has its sensor upside down. Quirk it to gain normal functionality. Priority: normal Signed-off-by: Erik Andrén --- linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c b/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c index 81f24d413..4a105cb38 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c @@ -67,6 +67,12 @@ static DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International"), DMI_MATCH(DMI_PRODUCT_NAME, "MS-1717X") } + }, { + .ident = "Lenovo Y300", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "L3000 Y300"), + DMI_MATCH(DMI_PRODUCT_NAME, "Y300") + } }, { } }; -- 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 fd22f9f82432e1d80c92bd020d5a9374c13125e3 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Thu, 7 May 2009 08:32:27 +0200 Subject: gspca - sonixj: Webcam 06f8:3008 added. From: Jani Monoses Priority: normal Signed-off-by: Jani Monoses Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/sonixj.c | 1 + 1 file changed, 1 insertion(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/sonixj.c b/linux/drivers/media/video/gspca/sonixj.c index d7a42ae44..a4c935d69 100644 --- a/linux/drivers/media/video/gspca/sonixj.c +++ b/linux/drivers/media/video/gspca/sonixj.c @@ -2228,6 +2228,7 @@ static const __devinitdata struct usb_device_id device_table[] = { {USB_DEVICE(0x0471, 0x0328), BSI(SN9C105, MI0360, 0x5d)}, {USB_DEVICE(0x0471, 0x0330), BSI(SN9C105, MI0360, 0x5d)}, {USB_DEVICE(0x06f8, 0x3004), BSI(SN9C105, OV7660, 0x21)}, + {USB_DEVICE(0x06f8, 0x3008), BSI(SN9C105, OV7660, 0x21)}, {USB_DEVICE(0x0c45, 0x6040), BSI(SN9C102P, HV7131R, 0x11)}, /* bw600.inf: {USB_DEVICE(0x0c45, 0x6040), BSI(SN9C102P, MI0360, 0x5d)}, */ -- cgit v1.2.3 From e35d2b660b1c4e14bbf10d6158278f39444635ac Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 7 May 2009 12:29:25 +0000 Subject: TI THS7303 video amplifier driver code From: Chaithrika U S This patch adds driver for TI THS7303 video amplifier. This driver is implemented as a v4l2 sub device. Tested on TI DM646x EVM. This version has updates based on review comments by Mauro Chehab. Signed-off-by: Chaithrika U S Reviewed-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/Kconfig | 9 +++ linux/drivers/media/video/Makefile | 1 + linux/drivers/media/video/ths7303.c | 151 ++++++++++++++++++++++++++++++++++++ 3 files changed, 161 insertions(+) create mode 100644 linux/drivers/media/video/ths7303.c (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/Kconfig b/linux/drivers/media/video/Kconfig index 9d48da2fb..f99348cc3 100644 --- a/linux/drivers/media/video/Kconfig +++ b/linux/drivers/media/video/Kconfig @@ -440,6 +440,15 @@ config VIDEO_ADV7175 To compile this driver as a module, choose M here: the module will be called adv7175. +config VIDEO_THS7303 + tristate "THS7303 Video Amplifier" + depends on I2C + help + Support for TI THS7303 video amplifier + + To compile this driver as a module, choose M here: the + module will be called ths7303. + comment "Video improvement chips" config VIDEO_UPD64031A diff --git a/linux/drivers/media/video/Makefile b/linux/drivers/media/video/Makefile index 7aefac643..352dd6d32 100644 --- a/linux/drivers/media/video/Makefile +++ b/linux/drivers/media/video/Makefile @@ -54,6 +54,7 @@ obj-$(CONFIG_VIDEO_BT819) += bt819.o obj-$(CONFIG_VIDEO_BT856) += bt856.o obj-$(CONFIG_VIDEO_BT866) += bt866.o obj-$(CONFIG_VIDEO_KS0127) += ks0127.o +obj-$(CONFIG_VIDEO_THS7303) += ths7303.o obj-$(CONFIG_VIDEO_ZORAN) += zoran/ diff --git a/linux/drivers/media/video/ths7303.c b/linux/drivers/media/video/ths7303.c new file mode 100644 index 000000000..21781f8a0 --- /dev/null +++ b/linux/drivers/media/video/ths7303.c @@ -0,0 +1,151 @@ +/* + * ths7303- THS7303 Video Amplifier driver + * + * Copyright (C) 2009 Texas Instruments Incorporated - http://www.ti.com/ + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation version 2. + * + * This program is distributed .as is. WITHOUT ANY WARRANTY of any + * kind, whether express or implied; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +MODULE_DESCRIPTION("TI THS7303 video amplifier driver"); +MODULE_AUTHOR("Chaithrika U S"); +MODULE_LICENSE("GPL"); + +static int debug; +module_param(debug, int, 0644); +MODULE_PARM_DESC(debug, "Debug level 0-1"); + +/* following function is used to set ths7303 */ +static int ths7303_setvalue(struct v4l2_subdev *sd, v4l2_std_id std) +{ + int err = 0; + u8 val; + struct i2c_client *client; + + client = v4l2_get_subdevdata(sd); + + if (std & (V4L2_STD_ALL & ~V4L2_STD_SECAM)) { + val = 0x02; + v4l2_dbg(1, debug, sd, "setting value for SDTV format\n"); + } else { + val = 0x00; + v4l2_dbg(1, debug, sd, "disabling all channels\n"); + } + + err |= i2c_smbus_write_byte_data(client, 0x01, val); + err |= i2c_smbus_write_byte_data(client, 0x02, val); + err |= i2c_smbus_write_byte_data(client, 0x03, val); + + if (err) + v4l2_err(sd, "write failed\n"); + + return err; +} + +static int ths7303_s_std_output(struct v4l2_subdev *sd, v4l2_std_id norm) +{ + return ths7303_setvalue(sd, norm); +} + +static int ths7303_g_chip_ident(struct v4l2_subdev *sd, + struct v4l2_dbg_chip_ident *chip) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + + return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_THS7303, 0); +} + +static const struct v4l2_subdev_video_ops ths7303_video_ops = { + .s_std_output = ths7303_s_std_output, +}; + +static const struct v4l2_subdev_core_ops ths7303_core_ops = { + .g_chip_ident = ths7303_g_chip_ident, +}; + +static const struct v4l2_subdev_ops ths7303_ops = { + .core = &ths7303_core_ops, + .video = &ths7303_video_ops, +}; + +static int ths7303_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct v4l2_subdev *sd; + v4l2_std_id std_id = V4L2_STD_NTSC; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) + return -ENODEV; + + v4l_info(client, "chip found @ 0x%x (%s)\n", + client->addr << 1, client->adapter->name); + + sd = kzalloc(sizeof(struct v4l2_subdev), GFP_KERNEL); + if (sd == NULL) + return -ENOMEM; + + v4l2_i2c_subdev_init(sd, client, &ths7303_ops); + + return ths7303_setvalue(sd, std_id); +} + +static int ths7303_remove(struct i2c_client *client) +{ + struct v4l2_subdev *sd = i2c_get_clientdata(client); + + v4l2_device_unregister_subdev(sd); + kfree(sd); + + return 0; +} + +static const struct i2c_device_id ths7303_id[] = { + {"ths7303", 0}, + {}, +}; + +MODULE_DEVICE_TABLE(i2c, ths7303_id); + +static struct i2c_driver ths7303_driver = { + .driver = { + .owner = THIS_MODULE, + .name = "ths7303", + }, + .probe = ths7303_probe, + .remove = ths7303_remove, + .id_table = ths7303_id, +}; + +static int __init ths7303_init(void) +{ + return i2c_add_driver(&ths7303_driver); +} + +static void __exit ths7303_exit(void) +{ + i2c_del_driver(&ths7303_driver); +} + +module_init(ths7303_init); +module_exit(ths7303_exit); + -- cgit v1.2.3 From 3349bdfa71ab601e2ad2fe785485cb8fe455248b Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 7 May 2009 12:30:01 +0000 Subject: Analog Devices ADV7343 video encoder driver From: Chaithrika U S Add ADV7343 I2C based video encoder driver. This follows the v4l2-subdev framework. This driver has been tested on TI DM646x EVM. It has been tested for Composite and Component outputs. Updates as per review by Mauro Chehab, added support for more standards supported by the encoder. Also adding the missed out signed-offs.Tested only NTSC and PAL standards. Signed-off-by: Manjunath Hadli Signed-off-by: Brijesh Jadav Signed-off-by: Chaithrika U S [hverkuil@xs4all.nl: s_routing API changed, updated driver to use new API] Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/Kconfig | 9 + linux/drivers/media/video/Makefile | 1 + linux/drivers/media/video/adv7343.c | 534 +++++++++++++++++++++++++++++++ linux/drivers/media/video/adv7343_regs.h | 185 +++++++++++ 4 files changed, 729 insertions(+) create mode 100644 linux/drivers/media/video/adv7343.c create mode 100644 linux/drivers/media/video/adv7343_regs.h (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/Kconfig b/linux/drivers/media/video/Kconfig index f99348cc3..7a1f43d17 100644 --- a/linux/drivers/media/video/Kconfig +++ b/linux/drivers/media/video/Kconfig @@ -449,6 +449,15 @@ config VIDEO_THS7303 To compile this driver as a module, choose M here: the module will be called ths7303. +config VIDEO_ADV7343 + tristate "ADV7343 video encoder" + depends on I2C + help + Support for Analog Devices I2C bus based ADV7343 encoder. + + To compile this driver as a module, choose M here: the + module will be called adv7343. + comment "Video improvement chips" config VIDEO_UPD64031A diff --git a/linux/drivers/media/video/Makefile b/linux/drivers/media/video/Makefile index 352dd6d32..f7d9a4c6f 100644 --- a/linux/drivers/media/video/Makefile +++ b/linux/drivers/media/video/Makefile @@ -49,6 +49,7 @@ obj-$(CONFIG_VIDEO_SAA7185) += saa7185.o obj-$(CONFIG_VIDEO_SAA7191) += saa7191.o obj-$(CONFIG_VIDEO_ADV7170) += adv7170.o obj-$(CONFIG_VIDEO_ADV7175) += adv7175.o +obj-$(CONFIG_VIDEO_ADV7343) += adv7343.o obj-$(CONFIG_VIDEO_VPX3220) += vpx3220.o obj-$(CONFIG_VIDEO_BT819) += bt819.o obj-$(CONFIG_VIDEO_BT856) += bt856.o diff --git a/linux/drivers/media/video/adv7343.c b/linux/drivers/media/video/adv7343.c new file mode 100644 index 000000000..30f5caf5d --- /dev/null +++ b/linux/drivers/media/video/adv7343.c @@ -0,0 +1,534 @@ +/* + * adv7343 - ADV7343 Video Encoder Driver + * + * The encoder hardware does not support SECAM. + * + * Copyright (C) 2009 Texas Instruments Incorporated - http://www.ti.com/ + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation version 2. + * + * This program is distributed .as is. WITHOUT ANY WARRANTY of any + * kind, whether express or implied; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "adv7343_regs.h" + +MODULE_DESCRIPTION("ADV7343 video encoder driver"); +MODULE_LICENSE("GPL"); + +static int debug; +module_param(debug, int, 0644); +MODULE_PARM_DESC(debug, "Debug level 0-1"); + +struct adv7343_state { + struct v4l2_subdev sd; + u8 reg00; + u8 reg01; + u8 reg02; + u8 reg35; + u8 reg80; + u8 reg82; + int bright; + int hue; + int gain; + u32 output; + v4l2_std_id std; +}; + +static inline struct adv7343_state *to_state(struct v4l2_subdev *sd) +{ + return container_of(sd, struct adv7343_state, sd); +} + +static inline int adv7343_write(struct v4l2_subdev *sd, u8 reg, u8 value) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + + return i2c_smbus_write_byte_data(client, reg, value); +} + +static const u8 adv7343_init_reg_val[] = { + ADV7343_SOFT_RESET, ADV7343_SOFT_RESET_DEFAULT, + ADV7343_POWER_MODE_REG, ADV7343_POWER_MODE_REG_DEFAULT, + + ADV7343_HD_MODE_REG1, ADV7343_HD_MODE_REG1_DEFAULT, + ADV7343_HD_MODE_REG2, ADV7343_HD_MODE_REG2_DEFAULT, + ADV7343_HD_MODE_REG3, ADV7343_HD_MODE_REG3_DEFAULT, + ADV7343_HD_MODE_REG4, ADV7343_HD_MODE_REG4_DEFAULT, + ADV7343_HD_MODE_REG5, ADV7343_HD_MODE_REG5_DEFAULT, + ADV7343_HD_MODE_REG6, ADV7343_HD_MODE_REG6_DEFAULT, + ADV7343_HD_MODE_REG7, ADV7343_HD_MODE_REG7_DEFAULT, + + ADV7343_SD_MODE_REG1, ADV7343_SD_MODE_REG1_DEFAULT, + ADV7343_SD_MODE_REG2, ADV7343_SD_MODE_REG2_DEFAULT, + ADV7343_SD_MODE_REG3, ADV7343_SD_MODE_REG3_DEFAULT, + ADV7343_SD_MODE_REG4, ADV7343_SD_MODE_REG4_DEFAULT, + ADV7343_SD_MODE_REG5, ADV7343_SD_MODE_REG5_DEFAULT, + ADV7343_SD_MODE_REG6, ADV7343_SD_MODE_REG6_DEFAULT, + ADV7343_SD_MODE_REG7, ADV7343_SD_MODE_REG7_DEFAULT, + ADV7343_SD_MODE_REG8, ADV7343_SD_MODE_REG8_DEFAULT, + + ADV7343_SD_HUE_REG, ADV7343_SD_HUE_REG_DEFAULT, + ADV7343_SD_CGMS_WSS0, ADV7343_SD_CGMS_WSS0_DEFAULT, + ADV7343_SD_BRIGHTNESS_WSS, ADV7343_SD_BRIGHTNESS_WSS_DEFAULT, +}; + +/* + * 2^32 + * FSC(reg) = FSC (HZ) * -------- + * 27000000 + */ +static const struct adv7343_std_info stdinfo[] = { + { + /* FSC(Hz) = 3,579,545.45 Hz */ + SD_STD_NTSC, 569408542, V4L2_STD_NTSC, + }, { + /* FSC(Hz) = 3,575,611.00 Hz */ + SD_STD_PAL_M, 568782678, V4L2_STD_PAL_M, + }, { + /* FSC(Hz) = 3,582,056.00 */ + SD_STD_PAL_N, 569807903, V4L2_STD_PAL_Nc, + }, { + /* FSC(Hz) = 4,433,618.75 Hz */ + SD_STD_PAL_N, 705268427, V4L2_STD_PAL_N, + }, { + /* FSC(Hz) = 4,433,618.75 Hz */ + SD_STD_PAL_BDGHI, 705268427, V4L2_STD_PAL, + }, { + /* FSC(Hz) = 4,433,618.75 Hz */ + SD_STD_NTSC, 705268427, V4L2_STD_NTSC_443, + }, { + /* FSC(Hz) = 4,433,618.75 Hz */ + SD_STD_PAL_M, 705268427, V4L2_STD_PAL_60, + }, +}; + +static int adv7343_setstd(struct v4l2_subdev *sd, v4l2_std_id std) +{ + struct adv7343_state *state = to_state(sd); + struct adv7343_std_info *std_info; + int output_idx, num_std; + char *fsc_ptr; + u8 reg, val; + int err = 0; + int i = 0; + + output_idx = state->output; + + std_info = (struct adv7343_std_info *)stdinfo; + num_std = ARRAY_SIZE(stdinfo); + + for (i = 0; i < num_std; i++) { + if (std_info[i].stdid & std) + break; + } + + if (i == num_std) { + v4l2_dbg(1, debug, sd, + "Invalid std or std is not supported: %llx\n", + (unsigned long long)std); + return -EINVAL; + } + + /* Set the standard */ + val = state->reg80 & (~(SD_STD_MASK)); + val |= std_info[i].standard_val3; + err = adv7343_write(sd, ADV7343_SD_MODE_REG1, val); + if (err < 0) + goto setstd_exit; + + state->reg80 = val; + + /* Configure the input mode register */ + val = state->reg01 & (~((u8) INPUT_MODE_MASK)); + val |= SD_INPUT_MODE; + err = adv7343_write(sd, ADV7343_MODE_SELECT_REG, val); + if (err < 0) + goto setstd_exit; + + state->reg01 = val; + + /* Program the sub carrier frequency registers */ + fsc_ptr = (unsigned char *)&std_info[i].fsc_val; + reg = ADV7343_FSC_REG0; + for (i = 0; i < 4; i++, reg++, fsc_ptr++) { + err = adv7343_write(sd, reg, *fsc_ptr); + if (err < 0) + goto setstd_exit; + } + + val = state->reg80; + + /* Filter settings */ + if (std & (V4L2_STD_NTSC | V4L2_STD_NTSC_443)) + val &= 0x03; + else if (std & ~V4L2_STD_SECAM) + val |= 0x04; + + err = adv7343_write(sd, ADV7343_SD_MODE_REG1, val); + if (err < 0) + goto setstd_exit; + + state->reg80 = val; + +setstd_exit: + if (err != 0) + v4l2_err(sd, "Error setting std, write failed\n"); + + return err; +} + +static int adv7343_setoutput(struct v4l2_subdev *sd, u32 output_type) +{ + struct adv7343_state *state = to_state(sd); + unsigned char val; + int err = 0; + + if (output_type > ADV7343_SVIDEO_ID) { + v4l2_dbg(1, debug, sd, + "Invalid output type or output type not supported:%d\n", + output_type); + return -EINVAL; + } + + /* Enable Appropriate DAC */ + val = state->reg00 & 0x03; + + if (output_type == ADV7343_COMPOSITE_ID) + val |= ADV7343_COMPOSITE_POWER_VALUE; + else if (output_type == ADV7343_COMPONENT_ID) + val |= ADV7343_COMPONENT_POWER_VALUE; + else + val |= ADV7343_SVIDEO_POWER_VALUE; + + err = adv7343_write(sd, ADV7343_POWER_MODE_REG, val); + if (err < 0) + goto setoutput_exit; + + state->reg00 = val; + + /* Enable YUV output */ + val = state->reg02 | YUV_OUTPUT_SELECT; + err = adv7343_write(sd, ADV7343_MODE_REG0, val); + if (err < 0) + goto setoutput_exit; + + state->reg02 = val; + + /* configure SD DAC Output 2 and SD DAC Output 1 bit to zero */ + val = state->reg82 & (SD_DAC_1_DI & SD_DAC_2_DI); + err = adv7343_write(sd, ADV7343_SD_MODE_REG2, val); + if (err < 0) + goto setoutput_exit; + + state->reg82 = val; + + /* configure ED/HD Color DAC Swap and ED/HD RGB Input Enable bit to + * zero */ + val = state->reg35 & (HD_RGB_INPUT_DI & HD_DAC_SWAP_DI); + err = adv7343_write(sd, ADV7343_HD_MODE_REG6, val); + if (err < 0) + goto setoutput_exit; + + state->reg35 = val; + +setoutput_exit: + if (err != 0) + v4l2_err(sd, "Error setting output, write failed\n"); + + return err; +} + +static int adv7343_log_status(struct v4l2_subdev *sd) +{ + struct adv7343_state *state = to_state(sd); + + v4l2_info(sd, "Standard: %llx\n", (unsigned long long)state->std); + v4l2_info(sd, "Output: %s\n", (state->output == 0) ? "Composite" : + ((state->output == 1) ? "Component" : "S-Video")); + return 0; +} + +static int adv7343_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc) +{ + switch (qc->id) { + case V4L2_CID_BRIGHTNESS: + return v4l2_ctrl_query_fill(qc, ADV7343_BRIGHTNESS_MIN, + ADV7343_BRIGHTNESS_MAX, 1, + ADV7343_BRIGHTNESS_DEF); + case V4L2_CID_HUE: + return v4l2_ctrl_query_fill(qc, ADV7343_HUE_MIN, + ADV7343_HUE_MAX, 1 , + ADV7343_HUE_DEF); + case V4L2_CID_GAIN: + return v4l2_ctrl_query_fill(qc, ADV7343_GAIN_MIN, + ADV7343_GAIN_MAX, 1, + ADV7343_GAIN_DEF); + default: + break; + } + + return 0; +} + +static int adv7343_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) +{ + struct adv7343_state *state = to_state(sd); + int err = 0; + + switch (ctrl->id) { + case V4L2_CID_BRIGHTNESS: + if (ctrl->value < ADV7343_BRIGHTNESS_MIN || + ctrl->value > ADV7343_BRIGHTNESS_MAX) { + v4l2_dbg(1, debug, sd, + "invalid brightness settings %d\n", + ctrl->value); + return -ERANGE; + } + + state->bright = ctrl->value; + err = adv7343_write(sd, ADV7343_SD_BRIGHTNESS_WSS, + state->bright); + break; + + case V4L2_CID_HUE: + if (ctrl->value < ADV7343_HUE_MIN || + ctrl->value > ADV7343_HUE_MAX) { + v4l2_dbg(1, debug, sd, "invalid hue settings %d\n", + ctrl->value); + return -ERANGE; + } + + state->hue = ctrl->value; + err = adv7343_write(sd, ADV7343_SD_HUE_REG, state->hue); + break; + + case V4L2_CID_GAIN: + if (ctrl->value < ADV7343_GAIN_MIN || + ctrl->value > ADV7343_GAIN_MAX) { + v4l2_dbg(1, debug, sd, "invalid gain settings %d\n", + ctrl->value); + return -ERANGE; + } + + if ((ctrl->value > POSITIVE_GAIN_MAX) && + (ctrl->value < NEGATIVE_GAIN_MIN)) { + v4l2_dbg(1, debug, sd, + "gain settings not within the specified range\n"); + return -ERANGE; + } + + state->gain = ctrl->value; + err = adv7343_write(sd, ADV7343_DAC2_OUTPUT_LEVEL, state->gain); + break; + + default: + return -EINVAL; + } + + if (err < 0) + v4l2_err(sd, "Failed to set the encoder controls\n"); + + return err; +} + +static int adv7343_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) +{ + struct adv7343_state *state = to_state(sd); + + switch (ctrl->id) { + case V4L2_CID_BRIGHTNESS: + ctrl->value = state->bright; + break; + + case V4L2_CID_HUE: + ctrl->value = state->hue; + break; + + case V4L2_CID_GAIN: + ctrl->value = state->gain; + break; + + default: + return -EINVAL; + } + + return 0; +} + +static int adv7343_g_chip_ident(struct v4l2_subdev *sd, + struct v4l2_dbg_chip_ident *chip) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + + return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_ADV7343, 0); +} + +static const struct v4l2_subdev_core_ops adv7343_core_ops = { + .log_status = adv7343_log_status, + .g_chip_ident = adv7343_g_chip_ident, + .g_ctrl = adv7343_g_ctrl, + .s_ctrl = adv7343_s_ctrl, + .queryctrl = adv7343_queryctrl, +}; + +static int adv7343_s_std_output(struct v4l2_subdev *sd, v4l2_std_id std) +{ + struct adv7343_state *state = to_state(sd); + int err = 0; + + if (state->std == std) + return 0; + + err = adv7343_setstd(sd, std); + if (!err) + state->std = std; + + return err; +} + +static int adv7343_s_routing(struct v4l2_subdev *sd, + u32 input, u32 output, u32 config) +{ + struct adv7343_state *state = to_state(sd); + int err = 0; + + if (state->output == output) + return 0; + + err = adv7343_setoutput(sd, output); + if (!err) + state->output = output; + + return err; +} + +static const struct v4l2_subdev_video_ops adv7343_video_ops = { + .s_std_output = adv7343_s_std_output, + .s_routing = adv7343_s_routing, +}; + +static const struct v4l2_subdev_ops adv7343_ops = { + .core = &adv7343_core_ops, + .video = &adv7343_video_ops, +}; + +static int adv7343_initialize(struct v4l2_subdev *sd) +{ + struct adv7343_state *state = to_state(sd); + int err = 0; + int i; + + for (i = 0; i < ARRAY_SIZE(adv7343_init_reg_val); i += 2) { + + err = adv7343_write(sd, adv7343_init_reg_val[i], + adv7343_init_reg_val[i+1]); + if (err) { + v4l2_err(sd, "Error initializing\n"); + return err; + } + } + + /* Configure for default video standard */ + err = adv7343_setoutput(sd, state->output); + if (err < 0) { + v4l2_err(sd, "Error setting output during init\n"); + return -EINVAL; + } + + err = adv7343_setstd(sd, state->std); + if (err < 0) { + v4l2_err(sd, "Error setting std during init\n"); + return -EINVAL; + } + + return err; +} + +static int adv7343_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct adv7343_state *state; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) + return -ENODEV; + + v4l_info(client, "chip found @ 0x%x (%s)\n", + client->addr << 1, client->adapter->name); + + state = kzalloc(sizeof(struct adv7343_state), GFP_KERNEL); + if (state == NULL) + return -ENOMEM; + + state->reg00 = 0x80; + state->reg01 = 0x00; + state->reg02 = 0x20; + state->reg35 = 0x00; + state->reg80 = ADV7343_SD_MODE_REG1_DEFAULT; + state->reg82 = ADV7343_SD_MODE_REG2_DEFAULT; + + state->output = ADV7343_COMPOSITE_ID; + state->std = V4L2_STD_NTSC; + + v4l2_i2c_subdev_init(&state->sd, client, &adv7343_ops); + return adv7343_initialize(&state->sd); +} + +static int adv7343_remove(struct i2c_client *client) +{ + struct v4l2_subdev *sd = i2c_get_clientdata(client); + + v4l2_device_unregister_subdev(sd); + kfree(to_state(sd)); + + return 0; +} + +static const struct i2c_device_id adv7343_id[] = { + {"adv7343", 0}, + {}, +}; + +MODULE_DEVICE_TABLE(i2c, adv7343_id); + +static struct i2c_driver adv7343_driver = { + .driver = { + .owner = THIS_MODULE, + .name = "adv7343", + }, + .probe = adv7343_probe, + .remove = adv7343_remove, + .id_table = adv7343_id, +}; + +static __init int init_adv7343(void) +{ + return i2c_add_driver(&adv7343_driver); +} + +static __exit void exit_adv7343(void) +{ + i2c_del_driver(&adv7343_driver); +} + +module_init(init_adv7343); +module_exit(exit_adv7343); diff --git a/linux/drivers/media/video/adv7343_regs.h b/linux/drivers/media/video/adv7343_regs.h new file mode 100644 index 000000000..3431045b3 --- /dev/null +++ b/linux/drivers/media/video/adv7343_regs.h @@ -0,0 +1,185 @@ +/* + * ADV7343 encoder related structure and register definitions + * + * Copyright (C) 2009 Texas Instruments Incorporated - http://www.ti.com/ + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation version 2. + * + * This program is distributed .as is. WITHOUT ANY WARRANTY of any + * kind, whether express or implied; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef ADV7343_REG_H +#define ADV7343_REGS_H + +struct adv7343_std_info { + u32 standard_val3; + u32 fsc_val; + v4l2_std_id stdid; +}; + +/* Register offset macros */ +#define ADV7343_POWER_MODE_REG (0x00) +#define ADV7343_MODE_SELECT_REG (0x01) +#define ADV7343_MODE_REG0 (0x02) + +#define ADV7343_DAC2_OUTPUT_LEVEL (0x0b) + +#define ADV7343_SOFT_RESET (0x17) + +#define ADV7343_HD_MODE_REG1 (0x30) +#define ADV7343_HD_MODE_REG2 (0x31) +#define ADV7343_HD_MODE_REG3 (0x32) +#define ADV7343_HD_MODE_REG4 (0x33) +#define ADV7343_HD_MODE_REG5 (0x34) +#define ADV7343_HD_MODE_REG6 (0x35) + +#define ADV7343_HD_MODE_REG7 (0x39) + +#define ADV7343_SD_MODE_REG1 (0x80) +#define ADV7343_SD_MODE_REG2 (0x82) +#define ADV7343_SD_MODE_REG3 (0x83) +#define ADV7343_SD_MODE_REG4 (0x84) +#define ADV7343_SD_MODE_REG5 (0x86) +#define ADV7343_SD_MODE_REG6 (0x87) +#define ADV7343_SD_MODE_REG7 (0x88) +#define ADV7343_SD_MODE_REG8 (0x89) + +#define ADV7343_FSC_REG0 (0x8C) +#define ADV7343_FSC_REG1 (0x8D) +#define ADV7343_FSC_REG2 (0x8E) +#define ADV7343_FSC_REG3 (0x8F) + +#define ADV7343_SD_CGMS_WSS0 (0x99) + +#define ADV7343_SD_HUE_REG (0xA0) +#define ADV7343_SD_BRIGHTNESS_WSS (0xA1) + +/* Default values for the registers */ +#define ADV7343_POWER_MODE_REG_DEFAULT (0x10) +#define ADV7343_HD_MODE_REG1_DEFAULT (0x3C) /* Changed Default + 720p EAVSAV code*/ +#define ADV7343_HD_MODE_REG2_DEFAULT (0x01) /* Changed Pixel data + valid */ +#define ADV7343_HD_MODE_REG3_DEFAULT (0x00) /* Color delay 0 clks */ +#define ADV7343_HD_MODE_REG4_DEFAULT (0xE8) /* Changed */ +#define ADV7343_HD_MODE_REG5_DEFAULT (0x08) +#define ADV7343_HD_MODE_REG6_DEFAULT (0x00) +#define ADV7343_HD_MODE_REG7_DEFAULT (0x00) +#define ADV7343_SD_MODE_REG8_DEFAULT (0x00) +#define ADV7343_SOFT_RESET_DEFAULT (0x02) +#define ADV7343_COMPOSITE_POWER_VALUE (0x80) +#define ADV7343_COMPONENT_POWER_VALUE (0x1C) +#define ADV7343_SVIDEO_POWER_VALUE (0x60) +#define ADV7343_SD_HUE_REG_DEFAULT (127) +#define ADV7343_SD_BRIGHTNESS_WSS_DEFAULT (0x03) + +#define ADV7343_SD_CGMS_WSS0_DEFAULT (0x10) + +#define ADV7343_SD_MODE_REG1_DEFAULT (0x00) +#define ADV7343_SD_MODE_REG2_DEFAULT (0xC9) +#define ADV7343_SD_MODE_REG3_DEFAULT (0x10) +#define ADV7343_SD_MODE_REG4_DEFAULT (0x01) +#define ADV7343_SD_MODE_REG5_DEFAULT (0x02) +#define ADV7343_SD_MODE_REG6_DEFAULT (0x0C) +#define ADV7343_SD_MODE_REG7_DEFAULT (0x04) +#define ADV7343_SD_MODE_REG8_DEFAULT (0x00) + +/* Bit masks for Mode Select Register */ +#define INPUT_MODE_MASK (0x70) +#define SD_INPUT_MODE (0x00) +#define HD_720P_INPUT_MODE (0x10) +#define HD_1080I_INPUT_MODE (0x10) + +/* Bit masks for Mode Register 0 */ +#define TEST_PATTERN_BLACK_BAR_EN (0x04) +#define YUV_OUTPUT_SELECT (0x20) +#define RGB_OUTPUT_SELECT (0xDF) + +/* Bit masks for DAC output levels */ +#define DAC_OUTPUT_LEVEL_MASK (0xFF) +#define POSITIVE_GAIN_MAX (0x40) +#define POSITIVE_GAIN_MIN (0x00) +#define NEGATIVE_GAIN_MAX (0xFF) +#define NEGATIVE_GAIN_MIN (0xC0) + +/* Bit masks for soft reset register */ +#define SOFT_RESET (0x02) + +/* Bit masks for HD Mode Register 1 */ +#define OUTPUT_STD_MASK (0x03) +#define OUTPUT_STD_SHIFT (0) +#define OUTPUT_STD_EIA0_2 (0x00) +#define OUTPUT_STD_EIA0_1 (0x01) +#define OUTPUT_STD_FULL (0x02) +#define EMBEDDED_SYNC (0x04) +#define EXTERNAL_SYNC (0xFB) +#define STD_MODE_SHIFT (3) +#define STD_MODE_MASK (0x1F) +#define STD_MODE_720P (0x05) +#define STD_MODE_720P_25 (0x08) +#define STD_MODE_720P_30 (0x07) +#define STD_MODE_720P_50 (0x06) +#define STD_MODE_1080I (0x0D) +#define STD_MODE_1080I_25fps (0x0E) +#define STD_MODE_1080P_24 (0x12) +#define STD_MODE_1080P_25 (0x10) +#define STD_MODE_1080P_30 (0x0F) +#define STD_MODE_525P (0x00) +#define STD_MODE_625P (0x03) + +/* Bit masks for SD Mode Register 1 */ +#define SD_STD_MASK (0x03) +#define SD_STD_NTSC (0x00) +#define SD_STD_PAL_BDGHI (0x01) +#define SD_STD_PAL_M (0x02) +#define SD_STD_PAL_N (0x03) +#define SD_LUMA_FLTR_MASK (0x7) +#define SD_LUMA_FLTR_SHIFT (0x2) +#define SD_CHROMA_FLTR_MASK (0x7) +#define SD_CHROMA_FLTR_SHIFT (0x5) + +/* Bit masks for SD Mode Register 2 */ +#define SD_PBPR_SSAF_EN (0x01) +#define SD_PBPR_SSAF_DI (0xFE) +#define SD_DAC_1_DI (0xFD) +#define SD_DAC_2_DI (0xFB) +#define SD_PEDESTAL_EN (0x08) +#define SD_PEDESTAL_DI (0xF7) +#define SD_SQUARE_PIXEL_EN (0x10) +#define SD_SQUARE_PIXEL_DI (0xEF) +#define SD_PIXEL_DATA_VALID (0x40) +#define SD_ACTIVE_EDGE_EN (0x80) +#define SD_ACTIVE_EDGE_DI (0x7F) + +/* Bit masks for HD Mode Register 6 */ +#define HD_RGB_INPUT_EN (0x02) +#define HD_RGB_INPUT_DI (0xFD) +#define HD_PBPR_SYNC_EN (0x04) +#define HD_PBPR_SYNC_DI (0xFB) +#define HD_DAC_SWAP_EN (0x08) +#define HD_DAC_SWAP_DI (0xF7) +#define HD_GAMMA_CURVE_A (0xEF) +#define HD_GAMMA_CURVE_B (0x10) +#define HD_GAMMA_EN (0x20) +#define HD_GAMMA_DI (0xDF) +#define HD_ADPT_FLTR_MODEB (0x40) +#define HD_ADPT_FLTR_MODEA (0xBF) +#define HD_ADPT_FLTR_EN (0x80) +#define HD_ADPT_FLTR_DI (0x7F) + +#define ADV7343_BRIGHTNESS_MAX (127) +#define ADV7343_BRIGHTNESS_MIN (0) +#define ADV7343_BRIGHTNESS_DEF (3) +#define ADV7343_HUE_MAX (255) +#define ADV7343_HUE_MIN (0) +#define ADV7343_HUE_DEF (127) +#define ADV7343_GAIN_MAX (255) +#define ADV7343_GAIN_MIN (0) +#define ADV7343_GAIN_DEF (0) + +#endif -- cgit v1.2.3 From ee56997de9033d06c740726754437b09ddebb039 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Thu, 7 May 2009 18:25:32 +0200 Subject: soc-camera: prepare for the platform driver conversion Add a platform driver to soc_camera.c. This way we preserve backwards compatibility with existing platforms and can start converting them one by one to the new platform-device soc-camera interface. Signed-off-by: Guennadi Liakhovetski --- linux/drivers/media/video/soc_camera.c | 71 +++++++++++++++++++++++++++++++--- 1 file changed, 66 insertions(+), 5 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/soc_camera.c b/linux/drivers/media/video/soc_camera.c index 9dca8f470..f792ab2e5 100644 --- a/linux/drivers/media/video/soc_camera.c +++ b/linux/drivers/media/video/soc_camera.c @@ -16,19 +16,21 @@ * published by the Free Software Foundation. */ -#include -#include #include -#include #include +#include +#include +#include +#include #include +#include #include +#include #include -#include #include +#include #include -#include #include "compat.h" /* Default to VGA resolution */ @@ -1160,6 +1162,57 @@ void soc_camera_video_stop(struct soc_camera_device *icd) } EXPORT_SYMBOL(soc_camera_video_stop); +static int __devinit soc_camera_pdrv_probe(struct platform_device *pdev) +{ + struct soc_camera_link *icl = pdev->dev.platform_data; + struct i2c_adapter *adap; + struct i2c_client *client; + + if (!icl) + return -EINVAL; + + adap = i2c_get_adapter(icl->i2c_adapter_id); + if (!adap) { + dev_warn(&pdev->dev, "Cannot get adapter #%d. No driver?\n", + icl->i2c_adapter_id); + /* -ENODEV and -ENXIO do not produce an error on probe()... */ + return -ENOENT; + } + + icl->board_info->platform_data = icl; + client = i2c_new_device(adap, icl->board_info); + if (!client) { + i2c_put_adapter(adap); + return -ENOMEM; + } + + platform_set_drvdata(pdev, client); + + return 0; +} + +static int __devexit soc_camera_pdrv_remove(struct platform_device *pdev) +{ + struct i2c_client *client = platform_get_drvdata(pdev); + + if (!client) + return -ENODEV; + + i2c_unregister_device(client); + i2c_put_adapter(client->adapter); + + return 0; +} + +static struct platform_driver soc_camera_pdrv = { + .probe = soc_camera_pdrv_probe, + .remove = __exit_p(soc_camera_pdrv_remove), + .driver = { + .name = "soc-camera-pdrv", + .owner = THIS_MODULE, + }, +}; + static int __init soc_camera_init(void) { int ret = bus_register(&soc_camera_bus_type); @@ -1169,8 +1222,14 @@ static int __init soc_camera_init(void) if (ret) goto edrvr; + ret = platform_driver_register(&soc_camera_pdrv); + if (ret) + goto epdr; + return 0; +epdr: + driver_unregister(&ic_drv); edrvr: bus_unregister(&soc_camera_bus_type); return ret; @@ -1178,6 +1237,7 @@ edrvr: static void __exit soc_camera_exit(void) { + platform_driver_unregister(&soc_camera_pdrv); driver_unregister(&ic_drv); bus_unregister(&soc_camera_bus_type); } @@ -1188,3 +1248,4 @@ module_exit(soc_camera_exit); MODULE_DESCRIPTION("Image capture bus driver"); MODULE_AUTHOR("Guennadi Liakhovetski "); MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:soc-camera-pdrv"); -- cgit v1.2.3 From 14614b91f8762ceb2d9ee7e76e424442a72f2483 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Fri, 29 May 2009 09:46:12 +0200 Subject: gspca - spca505: Reinitialize the webcam at resume time. From: Jean-Francois Moine Priority: normal Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/spca505.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/spca505.c b/linux/drivers/media/video/gspca/spca505.c index 2acec58b1..ea8c9fe2e 100644 --- a/linux/drivers/media/video/gspca/spca505.c +++ b/linux/drivers/media/video/gspca/spca505.c @@ -637,19 +637,19 @@ static int sd_config(struct gspca_dev *gspca_dev, cam->nmodes = ARRAY_SIZE(vga_mode) - 1; sd->brightness = BRIGHTNESS_DEF; - if (sd->subtype == Nxultra) { - if (write_vector(gspca_dev, spca505b_init_data)) - return -EIO; - } else { - if (write_vector(gspca_dev, spca505_init_data)) - return -EIO; - } return 0; } /* this function is called at probe and resume time */ static int sd_init(struct gspca_dev *gspca_dev) { + struct sd *sd = (struct sd *) gspca_dev; + + if (write_vector(gspca_dev, + sd->subtype == Nxultra + ? spca505b_init_data + : spca505_init_data)) + return -EIO; return 0; } -- cgit v1.2.3 From dd007d4908b20070d6ea01c800ad017e26d6aa1b Mon Sep 17 00:00:00 2001 From: Douglas Schilling Landgraf Date: Sat, 6 Jun 2009 16:34:01 -0300 Subject: em28xx: set up tda9887_conf in em28xx_card_setup() From: Franklin Meng Added tda9887_conf set up into em28xx_card_setup() Priority: normal Signed-off-by: Franklin Meng Signed-off-by: Douglas Schilling Landgraf --- linux/drivers/media/video/em28xx/em28xx-cards.c | 3 +++ 1 file changed, 3 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 5b89c1821..b9b8a4e01 100644 --- a/linux/drivers/media/video/em28xx/em28xx-cards.c +++ b/linux/drivers/media/video/em28xx/em28xx-cards.c @@ -2081,6 +2081,9 @@ void em28xx_card_setup(struct em28xx *dev) if (em28xx_boards[dev->model].tuner_addr) dev->tuner_addr = em28xx_boards[dev->model].tuner_addr; + if (em28xx_boards[dev->model].tda9887_conf) + dev->tda9887_conf = em28xx_boards[dev->model].tda9887_conf; + /* request some modules */ switch (dev->model) { case EM2820_BOARD_HAUPPAUGE_WINTV_USB_2: -- cgit v1.2.3 From 0a6e7fde238f94e6a9d873258e77baa775942b81 Mon Sep 17 00:00:00 2001 From: Douglas Schilling Landgraf Date: Sat, 6 Jun 2009 17:05:02 -0300 Subject: em28xx: Add Kworld 315 entry From: Franklin Meng Added an entry for Kworld 315 (for while, dvb only) Priority: normal Signed-off-by: Franklin Meng Signed-off-by: Douglas Schilling Landgraf --- linux/drivers/media/video/em28xx/em28xx-cards.c | 69 +++++++++++++++++++++++++ linux/drivers/media/video/em28xx/em28xx-dvb.c | 14 +++++ linux/drivers/media/video/em28xx/em28xx.h | 1 + 3 files changed, 84 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 b9b8a4e01..16093680b 100644 --- a/linux/drivers/media/video/em28xx/em28xx-cards.c +++ b/linux/drivers/media/video/em28xx/em28xx-cards.c @@ -122,6 +122,24 @@ static struct em28xx_reg_seq em2870_kworld_355u_digital[] = { }; #endif +/* Board - EM2882 Kworld 315U digital */ +static struct em28xx_reg_seq em2882_kworld_315u_digital[] = { + {EM28XX_R08_GPIO, 0xff, 0xff, 10}, + {EM28XX_R08_GPIO, 0xfe, 0xff, 10}, + {EM2880_R04_GPO, 0x04, 0xff, 10}, + {EM2880_R04_GPO, 0x0c, 0xff, 10}, + {EM28XX_R08_GPIO, 0x7e, 0xff, 10}, + { -1, -1, -1, -1}, +}; + +static struct em28xx_reg_seq em2882_kworld_315u_tuner_gpio[] = { + {EM2880_R04_GPO, 0x08, 0xff, 10}, + {EM2880_R04_GPO, 0x0c, 0xff, 10}, + {EM2880_R04_GPO, 0x08, 0xff, 10}, + {EM2880_R04_GPO, 0x0c, 0xff, 10}, + { -1, -1, -1, -1}, +}; + static struct em28xx_reg_seq kworld_330u_analog[] = { {EM28XX_R08_GPIO, 0x6d, ~EM_GPIO_4, 10}, {EM2880_R04_GPO, 0x00, 0xff, 10}, @@ -1160,6 +1178,38 @@ struct em28xx_board em28xx_boards[] = { .gpio = default_analog, } }, }, + [EM2882_BOARD_KWORLD_ATSC_315U] = { + .name = "KWorld ATSC 315U HDTV TV Box", + .valid = EM28XX_BOARD_NOT_VALIDATED, + .tuner_type = TUNER_THOMSON_DTT761X, + .tuner_gpio = em2882_kworld_315u_tuner_gpio, + .tda9887_conf = TDA9887_PRESENT, + .decoder = EM28XX_SAA711X, + .has_dvb = 1, + .dvb_gpio = em2882_kworld_315u_digital, + .xclk = EM28XX_XCLK_FREQUENCY_12MHZ, + .i2c_speed = EM28XX_I2C_CLK_WAIT_ENABLE, + /* Analog mode - still not ready */ + /*.input = { { + .type = EM28XX_VMUX_TELEVISION, + .vmux = SAA7115_COMPOSITE2, + .amux = EM28XX_AMUX_VIDEO, + .gpio = em2882_kworld_315u_analog, + .aout = EM28XX_AOUT_PCM_IN | EM28XX_AOUT_PCM_STEREO, + }, { + .type = EM28XX_VMUX_COMPOSITE1, + .vmux = SAA7115_COMPOSITE0, + .amux = EM28XX_AMUX_LINE_IN, + .gpio = em2882_kworld_315u_analog1, + .aout = EM28XX_AOUT_PCM_IN | EM28XX_AOUT_PCM_STEREO, + }, { + .type = EM28XX_VMUX_SVIDEO, + .vmux = SAA7115_SVIDEO3, + .amux = EM28XX_AMUX_LINE_IN, + .gpio = em2882_kworld_315u_analog1, + .aout = EM28XX_AOUT_PCM_IN | EM28XX_AOUT_PCM_STEREO, + } }, */ + }, [EM2880_BOARD_EMPIRE_DUAL_TV] = { .name = "Empire dual TV", .tuner_type = TUNER_XC2028, @@ -1501,6 +1551,8 @@ struct usb_device_id em28xx_id_table[] = { { USB_DEVICE(0xeb1a, 0xe310), .driver_info = EM2880_BOARD_KWORLD_DVB_310U }, #endif + { USB_DEVICE(0xeb1a, 0xa313), + .driver_info = EM2882_BOARD_KWORLD_ATSC_315U }, { USB_DEVICE(0xeb1a, 0xa316), .driver_info = EM2883_BOARD_KWORLD_HYBRID_330U }, { USB_DEVICE(0xeb1a, 0xe320), @@ -1770,6 +1822,17 @@ void em28xx_pre_card_setup(struct em28xx *dev) em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xfd); break; + case EM2882_BOARD_KWORLD_ATSC_315U: + em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xff); + msleep(10); + em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xfe); + msleep(10); + em28xx_write_reg(dev, EM2880_R04_GPO, 0x00); + msleep(10); + em28xx_write_reg(dev, EM2880_R04_GPO, 0x08); + msleep(10); + break; + case EM2860_BOARD_KAIOMY_TVNPC_U2: em28xx_write_regs(dev, EM28XX_R0F_XCLK, "\x07", 1); em28xx_write_regs(dev, EM28XX_R06_I2C_CLK, "\x40", 1); @@ -2113,6 +2176,12 @@ void em28xx_card_setup(struct em28xx *dev) #endif break; } + case EM2882_BOARD_KWORLD_ATSC_315U: + em28xx_write_reg(dev, 0x0d, 0x42); + msleep(10); + em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xfd); + msleep(10); + break; case EM2820_BOARD_KWORLD_PVRTV2800RF: /* GPIO enables sound on KWORLD PVR TV 2800RF */ em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xf9); diff --git a/linux/drivers/media/video/em28xx/em28xx-dvb.c b/linux/drivers/media/video/em28xx/em28xx-dvb.c index de919504f..722cc709f 100644 --- a/linux/drivers/media/video/em28xx/em28xx-dvb.c +++ b/linux/drivers/media/video/em28xx/em28xx-dvb.c @@ -26,6 +26,8 @@ #include "em28xx.h" #include #include +#include +#include "tuner-simple.h" #include "lgdt330x.h" #include "zl10353.h" @@ -452,6 +454,18 @@ static int dvb_init(struct em28xx *dev) goto out_free; } break; + case EM2882_BOARD_KWORLD_ATSC_315U: + dvb->frontend = dvb_attach(lgdt330x_attach, + &em2880_lgdt3303_dev, + &dev->i2c_adap); + if (dvb->frontend != NULL) { + if (!dvb_attach(simple_tuner_attach, dvb->frontend, + &dev->i2c_adap, 0x61, TUNER_THOMSON_DTT761X)) { + result = -EINVAL; + goto out_free; + } + } + break; case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900_R2: #ifdef EM28XX_DRX397XD_SUPPORT /* We don't have the config structure properly populated, so diff --git a/linux/drivers/media/video/em28xx/em28xx.h b/linux/drivers/media/video/em28xx/em28xx.h index db07d92f6..aafc4a2d0 100644 --- a/linux/drivers/media/video/em28xx/em28xx.h +++ b/linux/drivers/media/video/em28xx/em28xx.h @@ -106,6 +106,7 @@ #define EM2880_BOARD_EMPIRE_DUAL_TV 66 #define EM2860_BOARD_TERRATEC_GRABBY 67 #define EM2860_BOARD_TERRATEC_AV350 68 +#define EM2882_BOARD_KWORLD_ATSC_315U 69 /* Limits minimum and default number of buffers */ #define EM28XX_MIN_BUF 4 -- cgit v1.2.3 From f4a62b7bf0e900a5a628c46ac8be803c18f5aafb Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Sun, 7 Jun 2009 17:10:39 +0200 Subject: gspca - ov519: Add support for the ov518 bridge. From: Hans de Goede Priority: normal Signed-off-by: Hans de Goede Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/ov519.c | 520 +++++++++++++++++++++++++++++--- 1 file changed, 486 insertions(+), 34 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/ov519.c b/linux/drivers/media/video/gspca/ov519.c index bd70e9adb..2bd42f4e0 100644 --- a/linux/drivers/media/video/gspca/ov519.c +++ b/linux/drivers/media/video/gspca/ov519.c @@ -50,6 +50,13 @@ static int i2c_detect_tries = 10; struct sd { struct gspca_dev gspca_dev; /* !! must be the first item */ + char bridge; +#define BRIDGE_OV511 0 +#define BRIDGE_OV511PLUS 1 +#define BRIDGE_OV518 2 +#define BRIDGE_OV518PLUS 3 +#define BRIDGE_OV519 4 + /* Determined by sensor type */ __u8 sif; @@ -87,6 +94,9 @@ static int sd_sethflip(struct gspca_dev *gspca_dev, __s32 val); static int sd_gethflip(struct gspca_dev *gspca_dev, __s32 *val); static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val); static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val); +static void setbrightness(struct gspca_dev *gspca_dev); +static void setcontrast(struct gspca_dev *gspca_dev); +static void setcolors(struct gspca_dev *gspca_dev); static struct ctrl sd_ctrls[] = { { @@ -164,7 +174,7 @@ static struct ctrl sd_ctrls[] = { }, }; -static const struct v4l2_pix_format vga_mode[] = { +static const struct v4l2_pix_format ov519_vga_mode[] = { {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, .bytesperline = 320, .sizeimage = 320 * 240 * 3 / 8 + 590, @@ -176,7 +186,7 @@ static const struct v4l2_pix_format vga_mode[] = { .colorspace = V4L2_COLORSPACE_JPEG, .priv = 0}, }; -static const struct v4l2_pix_format sif_mode[] = { +static const struct v4l2_pix_format ov519_sif_mode[] = { {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, .bytesperline = 176, .sizeimage = 176 * 144 * 3 / 8 + 590, @@ -189,6 +199,47 @@ static const struct v4l2_pix_format sif_mode[] = { .priv = 0}, }; +static const struct v4l2_pix_format ov518_vga_mode[] = { + {320, 240, V4L2_PIX_FMT_OV518, V4L2_FIELD_NONE, + .bytesperline = 320, + .sizeimage = 320 * 240 * 3 / 8 + 590, + .colorspace = V4L2_COLORSPACE_JPEG, + .priv = 1}, + {640, 480, V4L2_PIX_FMT_OV518, V4L2_FIELD_NONE, + .bytesperline = 640, + .sizeimage = 640 * 480 * 3 / 8 + 590, + .colorspace = V4L2_COLORSPACE_JPEG, + .priv = 0}, +}; +static const struct v4l2_pix_format ov518_sif_mode[] = { + {176, 144, V4L2_PIX_FMT_OV518, V4L2_FIELD_NONE, + .bytesperline = 176, + .sizeimage = 40000, + .colorspace = V4L2_COLORSPACE_JPEG, + .priv = 1}, + {352, 288, V4L2_PIX_FMT_OV518, V4L2_FIELD_NONE, + .bytesperline = 352, + .sizeimage = 352 * 288 * 3 / 8 + 590, + .colorspace = V4L2_COLORSPACE_JPEG, + .priv = 0}, +}; + + +/* Registers common to OV511 / OV518 */ +#define R51x_SYS_RESET 0x50 +#define R51x_SYS_INIT 0x53 +#define R51x_SYS_SNAP 0x52 +#define R51x_SYS_CUST_ID 0x5F +#define R51x_COMP_LUT_BEGIN 0x80 + +/* OV511 Camera interface register numbers */ +#define R511_SYS_LED_CTL 0x55 /* OV511+ only */ +#define OV511_RESET_NOREGS 0x3F /* All but OV511 & regs */ + +/* OV518 Camera interface register numbers */ +#define R518_GPIO_OUT 0x56 /* OV518(+) only */ +#define R518_GPIO_CTL 0x57 /* OV518(+) only */ + /* OV519 Camera interface register numbers */ #define OV519_R10_H_SIZE 0x10 #define OV519_R11_V_SIZE 0x11 @@ -224,6 +275,8 @@ static const struct v4l2_pix_format sif_mode[] = { /* OV7610 registers */ #define OV7610_REG_GAIN 0x00 /* gain setting (5:0) */ +#define OV7610_REG_BLUE 0x01 /* blue channel balance */ +#define OV7610_REG_RED 0x02 /* red channel balance */ #define OV7610_REG_SAT 0x03 /* saturation */ #define OV8610_REG_HUE 0x04 /* 04 reserved */ #define OV7610_REG_CNT 0x05 /* Y contrast */ @@ -846,11 +899,12 @@ static unsigned char ov7670_abs_to_sm(unsigned char v) static int reg_w(struct sd *sd, __u16 index, __u8 value) { int ret; + int req = (sd->bridge <= BRIDGE_OV511PLUS) ? 2 : 1; sd->gspca_dev.usb_buf[0] = value; ret = usb_control_msg(sd->gspca_dev.dev, usb_sndctrlpipe(sd->gspca_dev.dev, 0), - 1, /* REQ_IO (ov518/519) */ + req, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 0, index, sd->gspca_dev.usb_buf, 1, 500); @@ -864,10 +918,11 @@ static int reg_w(struct sd *sd, __u16 index, __u8 value) static int reg_r(struct sd *sd, __u16 index) { int ret; + int req = (sd->bridge <= BRIDGE_OV511PLUS) ? 3 : 1; ret = usb_control_msg(sd->gspca_dev.dev, usb_rcvctrlpipe(sd->gspca_dev.dev, 0), - 1, /* REQ_IO */ + req, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 0, index, sd->gspca_dev.usb_buf, 1, 500); @@ -923,6 +978,28 @@ static int reg_w_mask(struct sd *sd, return reg_w(sd, index, value); } +/* + * Writes multiple (n) byte value to a single register. Only valid with certain + * registers (0x30 and 0xc4 - 0xce). + */ +static int ov518_reg_w32(struct sd *sd, __u16 index, u32 value, int n) +{ + int ret; + + *((u32 *)sd->gspca_dev.usb_buf) = __cpu_to_le32(value); + + ret = usb_control_msg(sd->gspca_dev.dev, + usb_sndctrlpipe(sd->gspca_dev.dev, 0), + 1 /* REG_IO */, + USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, + 0, index, + sd->gspca_dev.usb_buf, n, 500); + if (ret < 0) + PDEBUG(D_ERR, "Write reg32 [%02x] %08x failed", index, value); + return ret; +} + + /* * The OV518 I2C I/O procedure is different, hence, this function. * This is normally only called from i2c_w(). Note that this function @@ -1014,20 +1091,47 @@ static inline int ov51x_stop(struct sd *sd) { PDEBUG(D_STREAM, "stopping"); sd->stopped = 1; - return reg_w(sd, OV519_SYS_RESET1, 0x0f); + switch (sd->bridge) { + case BRIDGE_OV511: + case BRIDGE_OV511PLUS: + return reg_w(sd, R51x_SYS_RESET, 0x3d); + case BRIDGE_OV518: + case BRIDGE_OV518PLUS: + return reg_w_mask(sd, R51x_SYS_RESET, 0x3a, 0x3a); + case BRIDGE_OV519: + return reg_w(sd, OV519_SYS_RESET1, 0x0f); + } + + return 0; } /* Restarts OV511 after ov511_stop() is called. Has no effect if it is not * actually stopped (for performance). */ static inline int ov51x_restart(struct sd *sd) { + int rc; + PDEBUG(D_STREAM, "restarting"); if (!sd->stopped) return 0; sd->stopped = 0; /* Reinitialize the stream */ - return reg_w(sd, OV519_SYS_RESET1, 0x00); + switch (sd->bridge) { + case BRIDGE_OV511: + case BRIDGE_OV511PLUS: + return reg_w(sd, R51x_SYS_RESET, 0x00); + case BRIDGE_OV518: + case BRIDGE_OV518PLUS: + rc = reg_w(sd, 0x2f, 0x80); + if (rc < 0) + return rc; + return reg_w(sd, R51x_SYS_RESET, 0x00); + case BRIDGE_OV519: + return reg_w(sd, OV519_SYS_RESET1, 0x00); + } + + return 0; } /* This does an initial reset of an OmniVision sensor and ensures that I2C @@ -1287,16 +1391,161 @@ static int ov6xx0_configure(struct sd *sd) /* Turns on or off the LED. Only has an effect with OV511+/OV518(+)/OV519 */ static void ov51x_led_control(struct sd *sd, int on) { - reg_w_mask(sd, OV519_GPIO_DATA_OUT0, !on, 1); /* 0 / 1 */ + switch (sd->bridge) { + /* OV511 has no LED control */ + case BRIDGE_OV511PLUS: + reg_w(sd, R511_SYS_LED_CTL, on ? 1 : 0); + break; + case BRIDGE_OV518: + case BRIDGE_OV518PLUS: + reg_w_mask(sd, R518_GPIO_OUT, on ? 0x02 : 0x00, 0x02); + break; + case BRIDGE_OV519: + reg_w_mask(sd, OV519_GPIO_DATA_OUT0, !on, 1); /* 0 / 1 */ + break; + } } -/* this function is called at probe time */ -static int sd_config(struct gspca_dev *gspca_dev, - const struct usb_device_id *id) +/* OV518 quantization tables are 8x4 (instead of 8x8) */ +static int ov518_upload_quan_tables(struct sd *sd) +{ + const unsigned char yQuanTable518[] = { + 5, 4, 5, 6, 6, 7, 7, 7, + 5, 5, 5, 5, 6, 7, 7, 7, + 6, 6, 6, 6, 7, 7, 7, 8, + 7, 7, 6, 7, 7, 7, 8, 8 + }; + + const unsigned char uvQuanTable518[] = { + 6, 6, 6, 7, 7, 7, 7, 7, + 6, 6, 6, 7, 7, 7, 7, 7, + 6, 6, 6, 7, 7, 7, 7, 8, + 7, 7, 7, 7, 7, 7, 8, 8 + }; + + const unsigned char *pYTable = yQuanTable518; + const unsigned char *pUVTable = uvQuanTable518; + unsigned char val0, val1; + int i, rc, reg = R51x_COMP_LUT_BEGIN; + + PDEBUG(D_PROBE, "Uploading quantization tables"); + + for (i = 0; i < 16; i++) { + val0 = *pYTable++; + val1 = *pYTable++; + val0 &= 0x0f; + val1 &= 0x0f; + val0 |= val1 << 4; + rc = reg_w(sd, reg, val0); + if (rc < 0) + return rc; + + val0 = *pUVTable++; + val1 = *pUVTable++; + val0 &= 0x0f; + val1 &= 0x0f; + val0 |= val1 << 4; + rc = reg_w(sd, reg + 16, val0); + if (rc < 0) + return rc; + + reg++; + } + + return 0; +} + +/* This initializes the OV518/OV518+ and the sensor */ +static int ov518_configure(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; - struct cam *cam; + int rc; + + /* For 518 and 518+ */ + static struct ov_regvals init_518[] = { + { R51x_SYS_RESET, 0x40 }, + { R51x_SYS_INIT, 0xe1 }, + { R51x_SYS_RESET, 0x3e }, + { R51x_SYS_INIT, 0xe1 }, + { R51x_SYS_RESET, 0x00 }, + { R51x_SYS_INIT, 0xe1 }, + { 0x46, 0x00 }, + { 0x5d, 0x03 }, + }; + + static struct ov_regvals norm_518[] = { + { R51x_SYS_SNAP, 0x02 }, /* Reset */ + { R51x_SYS_SNAP, 0x01 }, /* Enable */ + { 0x31, 0x0f }, + { 0x5d, 0x03 }, + { 0x24, 0x9f }, + { 0x25, 0x90 }, + { 0x20, 0x00 }, + { 0x51, 0x04 }, + { 0x71, 0x19 }, + { 0x2f, 0x80 }, + }; + + static struct ov_regvals norm_518_p[] = { + { R51x_SYS_SNAP, 0x02 }, /* Reset */ + { R51x_SYS_SNAP, 0x01 }, /* Enable */ + { 0x31, 0x0f }, + { 0x5d, 0x03 }, + { 0x24, 0x9f }, + { 0x25, 0x90 }, + { 0x20, 0x60 }, + { 0x51, 0x02 }, + { 0x71, 0x19 }, + { 0x40, 0xff }, + { 0x41, 0x42 }, + { 0x46, 0x00 }, + { 0x33, 0x04 }, + { 0x21, 0x19 }, + { 0x3f, 0x10 }, + { 0x2f, 0x80 }, + }; + + /* First 5 bits of custom ID reg are a revision ID on OV518 */ + PDEBUG(D_PROBE, "Device revision %d", + 0x1F & reg_r(sd, R51x_SYS_CUST_ID)); + + rc = write_regvals(sd, init_518, ARRAY_SIZE(init_518)); + if (rc < 0) + return rc; + + /* Set LED GPIO pin to output mode */ + rc = reg_w_mask(sd, R518_GPIO_CTL, 0x00, 0x02); + if (rc < 0) + return rc; + switch (sd->bridge) { + case BRIDGE_OV518: + rc = write_regvals(sd, norm_518, ARRAY_SIZE(norm_518)); + if (rc < 0) + return rc; + break; + case BRIDGE_OV518PLUS: + rc = write_regvals(sd, norm_518_p, ARRAY_SIZE(norm_518_p)); + if (rc < 0) + return rc; + break; + } + + rc = ov518_upload_quan_tables(sd); + if (rc < 0) { + PDEBUG(D_ERR, "Error uploading quantization tables"); + return rc; + } + + rc = reg_w(sd, 0x2f, 0x80); + if (rc < 0) + return rc; + + return 0; +} + +static int ov519_configure(struct sd *sd) +{ static const struct ov_regvals init_519[] = { { 0x5a, 0x6d }, /* EnableSystem */ { 0x53, 0x9b }, @@ -1313,8 +1562,32 @@ static int sd_config(struct gspca_dev *gspca_dev, /* windows reads 0x55 at this point*/ }; - if (write_regvals(sd, init_519, ARRAY_SIZE(init_519))) + return write_regvals(sd, init_519, ARRAY_SIZE(init_519)); +} + +/* this function is called at probe time */ +static int sd_config(struct gspca_dev *gspca_dev, + const struct usb_device_id *id) +{ + struct sd *sd = (struct sd *) gspca_dev; + struct cam *cam; + int ret = 0; + + sd->bridge = id->driver_info; + + switch (sd->bridge) { + case BRIDGE_OV518: + case BRIDGE_OV518PLUS: + ret = ov518_configure(gspca_dev); + break; + case BRIDGE_OV519: + ret = ov519_configure(sd); + break; + } + + if (ret) goto error; + ov51x_led_control(sd, 0); /* turn LED off */ /* Test for 76xx */ @@ -1360,12 +1633,26 @@ static int sd_config(struct gspca_dev *gspca_dev, } cam = &gspca_dev->cam; - if (!sd->sif) { - cam->cam_mode = vga_mode; - cam->nmodes = ARRAY_SIZE(vga_mode); - } else { - cam->cam_mode = sif_mode; - cam->nmodes = ARRAY_SIZE(sif_mode); + switch (sd->bridge) { + case BRIDGE_OV518: + case BRIDGE_OV518PLUS: + if (!sd->sif) { + cam->cam_mode = ov518_vga_mode; + cam->nmodes = ARRAY_SIZE(ov518_vga_mode); + } else { + cam->cam_mode = ov518_sif_mode; + cam->nmodes = ARRAY_SIZE(ov518_sif_mode); + } + break; + case BRIDGE_OV519: + if (!sd->sif) { + cam->cam_mode = ov519_vga_mode; + cam->nmodes = ARRAY_SIZE(ov519_vga_mode); + } else { + cam->cam_mode = ov519_sif_mode; + cam->nmodes = ARRAY_SIZE(ov519_sif_mode); + } + break; } sd->brightness = BRIGHTNESS_DEF; sd->contrast = CONTRAST_DEF; @@ -1422,6 +1709,106 @@ static int sd_init(struct gspca_dev *gspca_dev) return 0; } +/* Sets up the OV518/OV518+ with the given image parameters + * + * OV518 needs a completely different approach, until we can figure out what + * the individual registers do. Also, only 15 FPS is supported now. + * + * Do not put any sensor-specific code in here (including I2C I/O functions) + */ +static int ov518_mode_init_regs(struct sd *sd) +{ + int hsegs, vsegs; + + /******** Set the mode ********/ + + reg_w(sd, 0x2b, 0); + reg_w(sd, 0x2c, 0); + reg_w(sd, 0x2d, 0); + reg_w(sd, 0x2e, 0); + reg_w(sd, 0x3b, 0); + reg_w(sd, 0x3c, 0); + reg_w(sd, 0x3d, 0); + reg_w(sd, 0x3e, 0); + + if (sd->bridge == BRIDGE_OV518) { + /* Set 8-bit (YVYU) input format */ + reg_w_mask(sd, 0x20, 0x08, 0x08); + + /* Set 12-bit (4:2:0) output format */ + reg_w_mask(sd, 0x28, 0x80, 0xf0); + reg_w_mask(sd, 0x38, 0x80, 0xf0); + } else { + reg_w(sd, 0x28, 0x80); + reg_w(sd, 0x38, 0x80); + } + + hsegs = sd->gspca_dev.width / 16; + vsegs = sd->gspca_dev.height / 4; + + reg_w(sd, 0x29, hsegs); + reg_w(sd, 0x2a, vsegs); + + reg_w(sd, 0x39, hsegs); + reg_w(sd, 0x3a, vsegs); + + /* Windows driver does this here; who knows why */ + reg_w(sd, 0x2f, 0x80); + + /******** Set the framerate (to 30 FPS) ********/ + if (sd->bridge == BRIDGE_OV518PLUS) + sd->clockdiv = 1; + else + sd->clockdiv = 0; + + /* Mode independent, but framerate dependent, regs */ + reg_w(sd, 0x51, 0x04); /* Clock divider; lower==faster */ + reg_w(sd, 0x22, 0x18); + reg_w(sd, 0x23, 0xff); + + if (sd->bridge == BRIDGE_OV518PLUS) + reg_w(sd, 0x21, 0x19); + else + reg_w(sd, 0x71, 0x17); /* Compression-related? */ + + /* FIXME: Sensor-specific */ + /* Bit 5 is what matters here. Of course, it is "reserved" */ + i2c_w(sd, 0x54, 0x23); + + reg_w(sd, 0x2f, 0x80); + + if (sd->bridge == BRIDGE_OV518PLUS) { + reg_w(sd, 0x24, 0x94); + reg_w(sd, 0x25, 0x90); + ov518_reg_w32(sd, 0xc4, 400, 2); /* 190h */ + ov518_reg_w32(sd, 0xc6, 540, 2); /* 21ch */ + ov518_reg_w32(sd, 0xc7, 540, 2); /* 21ch */ + ov518_reg_w32(sd, 0xc8, 108, 2); /* 6ch */ + ov518_reg_w32(sd, 0xca, 131098, 3); /* 2001ah */ + ov518_reg_w32(sd, 0xcb, 532, 2); /* 214h */ + ov518_reg_w32(sd, 0xcc, 2400, 2); /* 960h */ + ov518_reg_w32(sd, 0xcd, 32, 2); /* 20h */ + ov518_reg_w32(sd, 0xce, 608, 2); /* 260h */ + } else { + reg_w(sd, 0x24, 0x9f); + reg_w(sd, 0x25, 0x90); + ov518_reg_w32(sd, 0xc4, 400, 2); /* 190h */ + ov518_reg_w32(sd, 0xc6, 381, 2); /* 17dh */ + ov518_reg_w32(sd, 0xc7, 381, 2); /* 17dh */ + ov518_reg_w32(sd, 0xc8, 128, 2); /* 80h */ + ov518_reg_w32(sd, 0xca, 183331, 3); /* 2cc23h */ + ov518_reg_w32(sd, 0xcb, 746, 2); /* 2eah */ + ov518_reg_w32(sd, 0xcc, 1750, 2); /* 6d6h */ + ov518_reg_w32(sd, 0xcd, 45, 2); /* 2dh */ + ov518_reg_w32(sd, 0xce, 851, 2); /* 353h */ + } + + reg_w(sd, 0x2f, 0x80); + + return 0; +} + + /* Sets up the OV519 with the given image parameters * * OV519 needs a completely different approach, until we can figure out what @@ -1765,6 +2152,11 @@ static int set_ov_sensor_window(struct sd *sd) hwebase = 0x3a; vwsbase = 0x05; vwebase = 0x06; + if (qvga) { + /* HDG: this fixes U and V getting swapped */ + hwsbase--; + vwsbase--; + } break; case SEN_OV7620: hwsbase = 0x2f; /* From 7620.SET (spec is wrong) */ @@ -1880,15 +2272,28 @@ static int set_ov_sensor_window(struct sd *sd) static int sd_start(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; - int ret; + int ret = 0; - ret = ov519_mode_init_regs(sd); + switch (sd->bridge) { + case BRIDGE_OV518: + case BRIDGE_OV518PLUS: + ret = ov518_mode_init_regs(sd); + break; + case BRIDGE_OV519: + ret = ov519_mode_init_regs(sd); + break; + } if (ret < 0) goto out; + ret = set_ov_sensor_window(sd); if (ret < 0) goto out; + setcontrast(gspca_dev); + setbrightness(gspca_dev); + setcolors(gspca_dev); + ret = ov51x_restart(sd); if (ret < 0) goto out; @@ -1907,7 +2312,30 @@ static void sd_stopN(struct gspca_dev *gspca_dev) ov51x_led_control(sd, 0); } -static void sd_pkt_scan(struct gspca_dev *gspca_dev, +static void ov518_pkt_scan(struct gspca_dev *gspca_dev, + struct gspca_frame *frame, /* target */ + __u8 *data, /* isoc packet */ + int len) /* iso packet length */ +{ + PDEBUG(D_STREAM, "ov518_pkt_scan: %d bytes", len); + + if (len & 7) { + len--; + PDEBUG(D_STREAM, "packet number: %d\n", (int)data[len]); + } + + /* A false positive here is likely, until OVT gives me + * the definitive SOF/EOF format */ + if ((!(data[0] | data[1] | data[2] | data[3] | data[5])) && data[6]) { + gspca_frame_add(gspca_dev, LAST_PACKET, frame, data, 0); + gspca_frame_add(gspca_dev, FIRST_PACKET, frame, data, 0); + } + + /* intermediate packet */ + gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len); +} + +static void ov519_pkt_scan(struct gspca_dev *gspca_dev, struct gspca_frame *frame, /* target */ __u8 *data, /* isoc packet */ int len) /* iso packet length */ @@ -1951,6 +2379,27 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, data, len); } +static void sd_pkt_scan(struct gspca_dev *gspca_dev, + struct gspca_frame *frame, /* target */ + __u8 *data, /* isoc packet */ + int len) /* iso packet length */ +{ + struct sd *sd = (struct sd *) gspca_dev; + + switch (sd->bridge) { + case BRIDGE_OV511: + case BRIDGE_OV511PLUS: + break; + case BRIDGE_OV518: + case BRIDGE_OV518PLUS: + ov518_pkt_scan(gspca_dev, frame, data, len); + break; + case BRIDGE_OV519: + ov519_pkt_scan(gspca_dev, frame, data, len); + break; + } +} + /* -- management routines -- */ static void setbrightness(struct gspca_dev *gspca_dev) @@ -1995,6 +2444,7 @@ static void setcontrast(struct gspca_dev *gspca_dev) break; case SEN_OV6630: i2c_w_mask(sd, OV7610_REG_CNT, val >> 4, 0x0f); + break; case SEN_OV8610: { static const __u8 ctab[] = { 0x03, 0x09, 0x0b, 0x0f, 0x53, 0x6f, 0x35, 0x7f @@ -2161,19 +2611,21 @@ static const struct sd_desc sd_desc = { /* -- module initialisation -- */ static const __devinitdata struct usb_device_id device_table[] = { - {USB_DEVICE(0x041e, 0x4052)}, - {USB_DEVICE(0x041e, 0x405f)}, - {USB_DEVICE(0x041e, 0x4060)}, - {USB_DEVICE(0x041e, 0x4061)}, - {USB_DEVICE(0x041e, 0x4064)}, - {USB_DEVICE(0x041e, 0x4068)}, - {USB_DEVICE(0x045e, 0x028c)}, - {USB_DEVICE(0x054c, 0x0154)}, - {USB_DEVICE(0x054c, 0x0155)}, - {USB_DEVICE(0x05a9, 0x0519)}, - {USB_DEVICE(0x05a9, 0x0530)}, - {USB_DEVICE(0x05a9, 0x4519)}, - {USB_DEVICE(0x05a9, 0x8519)}, + {USB_DEVICE(0x041e, 0x4052), .driver_info = BRIDGE_OV519 }, + {USB_DEVICE(0x041e, 0x405f), .driver_info = BRIDGE_OV519 }, + {USB_DEVICE(0x041e, 0x4060), .driver_info = BRIDGE_OV519 }, + {USB_DEVICE(0x041e, 0x4061), .driver_info = BRIDGE_OV519 }, + {USB_DEVICE(0x041e, 0x4064), .driver_info = BRIDGE_OV519 }, + {USB_DEVICE(0x041e, 0x4068), .driver_info = BRIDGE_OV519 }, + {USB_DEVICE(0x045e, 0x028c), .driver_info = BRIDGE_OV519 }, + {USB_DEVICE(0x054c, 0x0154), .driver_info = BRIDGE_OV519 }, + {USB_DEVICE(0x054c, 0x0155), .driver_info = BRIDGE_OV519 }, + {USB_DEVICE(0x05a9, 0x0518), .driver_info = BRIDGE_OV518 }, + {USB_DEVICE(0x05a9, 0x0519), .driver_info = BRIDGE_OV519 }, + {USB_DEVICE(0x05a9, 0x0530), .driver_info = BRIDGE_OV519 }, + {USB_DEVICE(0x05a9, 0x4519), .driver_info = BRIDGE_OV519 }, + {USB_DEVICE(0x05a9, 0x8519), .driver_info = BRIDGE_OV519 }, + {USB_DEVICE(0x05a9, 0xa518), .driver_info = BRIDGE_OV518PLUS }, {} }; -- cgit v1.2.3 From 6e323483b126ac7589cadb5bad2f666cf4b7eb9d Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Tue, 9 Jun 2009 22:40:39 -0400 Subject: em28xx: don't create audio device if not supported From: Devin Heitmueller In cases where the device does not actually provide a USB audio class *or* vendor audio, do not load the driver that provides vendor audio support (such as the KWorld 2800d). Otherwise, the /dev/audio1 device file gets created and users get confused. Also, reworks the logic a bit so that we don't try to inspect the register content if the register read failed entirely. Priority: normal Signed-off-by: Devin Heitmueller --- linux/drivers/media/video/em28xx/em28xx-core.c | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 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 02e51af9d..2bce72e4f 100644 --- a/linux/drivers/media/video/em28xx/em28xx-core.c +++ b/linux/drivers/media/video/em28xx/em28xx-core.c @@ -500,18 +500,21 @@ int em28xx_audio_setup(struct em28xx *dev) /* See how this device is configured */ cfg = em28xx_read_reg(dev, EM28XX_R00_CHIPCFG); - if (cfg < 0) + em28xx_info("Config register raw data: 0x%02x\n", cfg); + if (cfg < 0) { + /* Register read error? */ cfg = EM28XX_CHIPCFG_AC97; /* Be conservative */ - else - em28xx_info("Config register raw data: 0x%02x\n", cfg); - - if ((cfg & EM28XX_CHIPCFG_AUDIOMASK) == - EM28XX_CHIPCFG_I2S_3_SAMPRATES) { + } else if ((cfg & EM28XX_CHIPCFG_AUDIOMASK) == 0x00) { + /* The device doesn't have vendor audio at all */ + dev->has_alsa_audio = 0; + dev->audio_mode.has_audio = 0; + return 0; + } else if ((cfg & EM28XX_CHIPCFG_AUDIOMASK) == + EM28XX_CHIPCFG_I2S_3_SAMPRATES) { em28xx_info("I2S Audio (3 sample rates)\n"); dev->audio_mode.i2s_3rates = 1; - } - if ((cfg & EM28XX_CHIPCFG_AUDIOMASK) == - EM28XX_CHIPCFG_I2S_5_SAMPRATES) { + } else if ((cfg & EM28XX_CHIPCFG_AUDIOMASK) == + EM28XX_CHIPCFG_I2S_5_SAMPRATES) { em28xx_info("I2S Audio (5 sample rates)\n"); dev->audio_mode.i2s_5rates = 1; } -- cgit v1.2.3 From c38b05097ac62c51b41478fb09ef7225b93fb25b Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Wed, 10 Jun 2009 09:52:18 +0200 Subject: gspca - main: Skip disabled controls. From: Hans de Goede Priority: normal Signed-off-by: Hans de Goede Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/gspca.c | 122 ++++++++++++++++---------------- 1 file changed, 61 insertions(+), 61 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/gspca.c b/linux/drivers/media/video/gspca/gspca.c index 3bf8b4866..e6ab4bb8c 100644 --- a/linux/drivers/media/video/gspca/gspca.c +++ b/linux/drivers/media/video/gspca/gspca.c @@ -1021,43 +1021,54 @@ out: return ret; } +static const struct ctrl *get_ctrl(struct gspca_dev *gspca_dev, + int id) +{ + const struct ctrl *ctrls; + int i; + + for (i = 0, ctrls = gspca_dev->sd_desc->ctrls; + i < gspca_dev->sd_desc->nctrls; + i++, ctrls++) { + if (gspca_dev->ctrl_dis & (1 << i)) + continue; + if (id == ctrls->qctrl.id) + return ctrls; + } + return NULL; +} + static int vidioc_queryctrl(struct file *file, void *priv, struct v4l2_queryctrl *q_ctrl) { struct gspca_dev *gspca_dev = priv; - int i, ix; + const struct ctrl *ctrls; + int i; u32 id; - ix = -1; + ctrls = NULL; id = q_ctrl->id; if (id & V4L2_CTRL_FLAG_NEXT_CTRL) { id &= V4L2_CTRL_ID_MASK; id++; for (i = 0; i < gspca_dev->sd_desc->nctrls; i++) { - if (gspca_dev->sd_desc->ctrls[i].qctrl.id < id) + if (gspca_dev->ctrl_dis & (1 << i)) continue; - if (ix < 0) { - ix = i; + if (ctrls->qctrl.id < id) continue; + if (ctrls != NULL) { + if (gspca_dev->sd_desc->ctrls[i].qctrl.id + > ctrls->qctrl.id) + continue; } - if (gspca_dev->sd_desc->ctrls[i].qctrl.id - > gspca_dev->sd_desc->ctrls[ix].qctrl.id) - continue; - ix = i; - } - } - for (i = 0; i < gspca_dev->sd_desc->nctrls; i++) { - if (id == gspca_dev->sd_desc->ctrls[i].qctrl.id) { - ix = i; - break; + ctrls = &gspca_dev->sd_desc->ctrls[i]; } + } else { + ctrls = get_ctrl(gspca_dev, id); } - if (ix < 0) + if (ctrls == NULL) return -EINVAL; - memcpy(q_ctrl, &gspca_dev->sd_desc->ctrls[ix].qctrl, - sizeof *q_ctrl); - if (gspca_dev->ctrl_dis & (1 << ix)) - q_ctrl->flags |= V4L2_CTRL_FLAG_DISABLED; + memcpy(q_ctrl, ctrls, sizeof *q_ctrl); return 0; } @@ -1066,56 +1077,45 @@ static int vidioc_s_ctrl(struct file *file, void *priv, { struct gspca_dev *gspca_dev = priv; const struct ctrl *ctrls; - int i, ret; + int ret; - for (i = 0, ctrls = gspca_dev->sd_desc->ctrls; - i < gspca_dev->sd_desc->nctrls; - i++, ctrls++) { - if (ctrl->id != ctrls->qctrl.id) - continue; - if (gspca_dev->ctrl_dis & (1 << i)) - return -EINVAL; - if (ctrl->value < ctrls->qctrl.minimum - || ctrl->value > ctrls->qctrl.maximum) - return -ERANGE; - PDEBUG(D_CONF, "set ctrl [%08x] = %d", ctrl->id, ctrl->value); - if (mutex_lock_interruptible(&gspca_dev->usb_lock)) - return -ERESTARTSYS; - if (gspca_dev->present) - ret = ctrls->set(gspca_dev, ctrl->value); - else - ret = -ENODEV; - mutex_unlock(&gspca_dev->usb_lock); - return ret; - } - return -EINVAL; + ctrls = get_ctrl(gspca_dev, ctrl->id); + if (ctrls == NULL) + return -EINVAL; + + if (ctrl->value < ctrls->qctrl.minimum + || ctrl->value > ctrls->qctrl.maximum) + return -ERANGE; + PDEBUG(D_CONF, "set ctrl [%08x] = %d", ctrl->id, ctrl->value); + if (mutex_lock_interruptible(&gspca_dev->usb_lock)) + return -ERESTARTSYS; + if (gspca_dev->present) + ret = ctrls->set(gspca_dev, ctrl->value); + else + ret = -ENODEV; + mutex_unlock(&gspca_dev->usb_lock); + return ret; } static int vidioc_g_ctrl(struct file *file, void *priv, struct v4l2_control *ctrl) { struct gspca_dev *gspca_dev = priv; - const struct ctrl *ctrls; - int i, ret; + int ret; - for (i = 0, ctrls = gspca_dev->sd_desc->ctrls; - i < gspca_dev->sd_desc->nctrls; - i++, ctrls++) { - if (ctrl->id != ctrls->qctrl.id) - continue; - if (gspca_dev->ctrl_dis & (1 << i)) - return -EINVAL; - if (mutex_lock_interruptible(&gspca_dev->usb_lock)) - return -ERESTARTSYS; - if (gspca_dev->present) - ret = ctrls->get(gspca_dev, &ctrl->value); - else - ret = -ENODEV; - mutex_unlock(&gspca_dev->usb_lock); - return ret; - } - return -EINVAL; + ctrls = get_ctrl(gspca_dev, ctrl->id); + if (ctrls == NULL) + return -EINVAL; + + if (mutex_lock_interruptible(&gspca_dev->usb_lock)) + return -ERESTARTSYS; + if (gspca_dev->present) + ret = ctrls->get(gspca_dev, &ctrl->value); + else + ret = -ENODEV; + mutex_unlock(&gspca_dev->usb_lock); + return ret; } /*fixme: have an audio flag in gspca_dev?*/ -- cgit v1.2.3 From 9c6048c72d19fffcc4cb08b2f146858d569d4318 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Fri, 12 Jun 2009 08:20:46 +0200 Subject: gspca - ov534: Do the ov772x work again. From: Jean-Francois Moine The scan of the image packets of the sensor ov772x was broken when the sensor ov965x was added. Priority: normal Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/ov534.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/ov534.c b/linux/drivers/media/video/gspca/ov534.c index 14341b6be..21a9366c7 100644 --- a/linux/drivers/media/video/gspca/ov534.c +++ b/linux/drivers/media/video/gspca/ov534.c @@ -958,9 +958,11 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, struct gspca_frame *frame, __u32 this_pts; u16 this_fid; int remaining_len = len; + int payload_len; + payload_len = gspca_dev->cam.bulk ? 2048 : 2040; do { - len = min(remaining_len, 2040); /*fixme: was 2048*/ + len = min(remaining_len, payload_len); /* Payloads are prefixed with a UVC-style header. We consider a frame to start when the FID toggles, or the PTS -- cgit v1.2.3 From abfb41850a42b51c099c5bab3dd48c9cc6399110 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 12 Jun 2009 08:38:15 +0200 Subject: v4l: i2c modules must be linked before the v4l2 drivers From: Hans Verkuil Since i2c autoprobing is no longer supported by v4l2 we need to make sure that the i2c modules are linked before the v4l2 modules. The v4l2 modules now rely on the presence of the i2c modules, so these must have initialized themselves before the v4l2 modules. The exception is the ir-kbd-i2c module, which is the only one still using autoprobing. This one should be loaded at the end of the v4l2 module. Loading it earlier actually causes problems with tveeprom. Once ir-kbd-i2c is no longer autoprobing, then it has to move up as well. This is only an issue when everything is compiled into the kernel. Thanks to Marcus Swoboda for reporting this and Udo Steinberg for testing this patch. Priority: high Signed-off-by: Hans Verkuil Tested-by: Udo A. Steinberg --- linux/drivers/media/video/Makefile | 70 ++++++++++++++++-------------- linux/drivers/media/video/saa7134/Makefile | 3 +- 2 files changed, 38 insertions(+), 35 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/Makefile b/linux/drivers/media/video/Makefile index f7d9a4c6f..7fb3add1b 100644 --- a/linux/drivers/media/video/Makefile +++ b/linux/drivers/media/video/Makefile @@ -12,6 +12,8 @@ omap2cam-objs := omap24xxcam.o omap24xxcam-dma.o videodev-objs := v4l2-dev.o v4l2-ioctl.o v4l2-device.o +# V4L2 core modules + obj-$(CONFIG_VIDEO_DEV) += videodev.o v4l2-int-device.o ifeq ($(CONFIG_COMPAT),y) obj-$(CONFIG_VIDEO_DEV) += v4l2-compat-ioctl32.o @@ -23,21 +25,15 @@ ifeq ($(CONFIG_VIDEO_V4L1_COMPAT),y) obj-$(CONFIG_VIDEO_DEV) += v4l1-compat.o endif -obj-$(CONFIG_VIDEO_TUNER) += tuner.o +# All i2c modules must come first: -obj-$(CONFIG_VIDEO_BT848) += bt8xx/ -obj-$(CONFIG_VIDEO_IR_I2C) += ir-kbd-i2c.o +obj-$(CONFIG_VIDEO_TUNER) += tuner.o obj-$(CONFIG_VIDEO_TVAUDIO) += tvaudio.o obj-$(CONFIG_VIDEO_TDA7432) += tda7432.o obj-$(CONFIG_VIDEO_TDA9875) += tda9875.o - obj-$(CONFIG_VIDEO_SAA6588) += saa6588.o obj-$(CONFIG_VIDEO_SAA5246A) += saa5246a.o obj-$(CONFIG_VIDEO_SAA5249) += saa5249.o -obj-$(CONFIG_VIDEO_CQCAM) += c-qcam.o -obj-$(CONFIG_VIDEO_BWQCAM) += bw-qcam.o -obj-$(CONFIG_VIDEO_W9966) += w9966.o - obj-$(CONFIG_VIDEO_TDA9840) += tda9840.o obj-$(CONFIG_VIDEO_TEA6415C) += tea6415c.o obj-$(CONFIG_VIDEO_TEA6420) += tea6420.o @@ -56,11 +52,40 @@ obj-$(CONFIG_VIDEO_BT856) += bt856.o obj-$(CONFIG_VIDEO_BT866) += bt866.o obj-$(CONFIG_VIDEO_KS0127) += ks0127.o obj-$(CONFIG_VIDEO_THS7303) += ths7303.o +obj-$(CONFIG_VIDEO_VINO) += indycam.o +obj-$(CONFIG_VIDEO_TVP5150) += tvp5150.o +obj-$(CONFIG_VIDEO_TVP514X) += tvp514x.o +obj-$(CONFIG_VIDEO_MSP3400) += msp3400.o +obj-$(CONFIG_VIDEO_CS5345) += cs5345.o +obj-$(CONFIG_VIDEO_CS53L32A) += cs53l32a.o +obj-$(CONFIG_VIDEO_M52790) += m52790.o +obj-$(CONFIG_VIDEO_TLV320AIC23B) += tlv320aic23b.o +obj-$(CONFIG_VIDEO_WM8775) += wm8775.o +obj-$(CONFIG_VIDEO_WM8739) += wm8739.o +obj-$(CONFIG_VIDEO_VP27SMPX) += vp27smpx.o +obj-$(CONFIG_VIDEO_CX25840) += cx25840/ +obj-$(CONFIG_VIDEO_UPD64031A) += upd64031a.o +obj-$(CONFIG_VIDEO_UPD64083) += upd64083.o +obj-$(CONFIG_VIDEO_OV7670) += ov7670.o +obj-$(CONFIG_VIDEO_TCM825X) += tcm825x.o +obj-$(CONFIG_VIDEO_TVEEPROM) += tveeprom.o -obj-$(CONFIG_VIDEO_ZORAN) += zoran/ +obj-$(CONFIG_SOC_CAMERA_MT9M001) += mt9m001.o +obj-$(CONFIG_SOC_CAMERA_MT9M111) += mt9m111.o +obj-$(CONFIG_SOC_CAMERA_MT9T031) += mt9t031.o +obj-$(CONFIG_SOC_CAMERA_MT9V022) += mt9v022.o +obj-$(CONFIG_SOC_CAMERA_OV772X) += ov772x.o +obj-$(CONFIG_SOC_CAMERA_TW9910) += tw9910.o + +# And now the v4l2 drivers: +obj-$(CONFIG_VIDEO_BT848) += bt8xx/ +obj-$(CONFIG_VIDEO_ZORAN) += zoran/ +obj-$(CONFIG_VIDEO_CQCAM) += c-qcam.o +obj-$(CONFIG_VIDEO_BWQCAM) += bw-qcam.o +obj-$(CONFIG_VIDEO_W9966) += w9966.o obj-$(CONFIG_VIDEO_PMS) += pms.o -obj-$(CONFIG_VIDEO_VINO) += vino.o indycam.o +obj-$(CONFIG_VIDEO_VINO) += vino.o obj-$(CONFIG_VIDEO_STRADIS) += stradis.o obj-$(CONFIG_VIDEO_CPIA) += cpia.o obj-$(CONFIG_VIDEO_CPIA_PP) += cpia_pp.o @@ -71,17 +96,7 @@ obj-$(CONFIG_VIDEO_CX88) += cx88/ obj-$(CONFIG_VIDEO_EM28XX) += em28xx/ obj-$(CONFIG_VIDEO_CX231XX) += cx231xx/ obj-$(CONFIG_VIDEO_USBVISION) += usbvision/ -obj-$(CONFIG_VIDEO_TVP5150) += tvp5150.o -obj-$(CONFIG_VIDEO_TVP514X) += tvp514x.o obj-$(CONFIG_VIDEO_PVRUSB2) += pvrusb2/ -obj-$(CONFIG_VIDEO_MSP3400) += msp3400.o -obj-$(CONFIG_VIDEO_CS5345) += cs5345.o -obj-$(CONFIG_VIDEO_CS53L32A) += cs53l32a.o -obj-$(CONFIG_VIDEO_M52790) += m52790.o -obj-$(CONFIG_VIDEO_TLV320AIC23B) += tlv320aic23b.o -obj-$(CONFIG_VIDEO_WM8775) += wm8775.o -obj-$(CONFIG_VIDEO_WM8739) += wm8739.o -obj-$(CONFIG_VIDEO_VP27SMPX) += vp27smpx.o obj-$(CONFIG_VIDEO_OVCAMCHIP) += ovcamchip/ obj-$(CONFIG_VIDEO_CPIA2) += cpia2/ obj-$(CONFIG_VIDEO_MXB) += mxb.o @@ -94,19 +109,12 @@ obj-$(CONFIG_VIDEOBUF_DMA_CONTIG) += videobuf-dma-contig.o obj-$(CONFIG_VIDEOBUF_VMALLOC) += videobuf-vmalloc.o obj-$(CONFIG_VIDEOBUF_DVB) += videobuf-dvb.o obj-$(CONFIG_VIDEO_BTCX) += btcx-risc.o -obj-$(CONFIG_VIDEO_TVEEPROM) += tveeprom.o obj-$(CONFIG_VIDEO_M32R_AR_M64278) += arv.o -obj-$(CONFIG_VIDEO_CX25840) += cx25840/ -obj-$(CONFIG_VIDEO_UPD64031A) += upd64031a.o -obj-$(CONFIG_VIDEO_UPD64083) += upd64083.o obj-$(CONFIG_VIDEO_CX2341X) += cx2341x.o obj-$(CONFIG_VIDEO_CAFE_CCIC) += cafe_ccic.o -obj-$(CONFIG_VIDEO_OV7670) += ov7670.o - -obj-$(CONFIG_VIDEO_TCM825X) += tcm825x.o obj-$(CONFIG_USB_DABUSB) += dabusb.o obj-$(CONFIG_USB_OV511) += ov511.o @@ -138,13 +146,7 @@ obj-$(CONFIG_VIDEO_CX23885) += cx23885/ obj-$(CONFIG_VIDEO_OMAP2) += omap2cam.o obj-$(CONFIG_SOC_CAMERA) += soc_camera.o -obj-$(CONFIG_SOC_CAMERA_MT9M001) += mt9m001.o -obj-$(CONFIG_SOC_CAMERA_MT9M111) += mt9m111.o -obj-$(CONFIG_SOC_CAMERA_MT9T031) += mt9t031.o -obj-$(CONFIG_SOC_CAMERA_MT9V022) += mt9v022.o -obj-$(CONFIG_SOC_CAMERA_OV772X) += ov772x.o obj-$(CONFIG_SOC_CAMERA_PLATFORM) += soc_camera_platform.o -obj-$(CONFIG_SOC_CAMERA_TW9910) += tw9910.o # soc-camera host drivers have to be linked after camera drivers obj-$(CONFIG_VIDEO_MX1) += mx1_camera.o obj-$(CONFIG_VIDEO_MX3) += mx3_camera.o @@ -155,6 +157,8 @@ obj-$(CONFIG_VIDEO_AU0828) += au0828/ obj-$(CONFIG_USB_VIDEO_CLASS) += uvc/ +obj-$(CONFIG_VIDEO_IR_I2C) += ir-kbd-i2c.o + EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core EXTRA_CFLAGS += -Idrivers/media/dvb/frontends EXTRA_CFLAGS += -Idrivers/media/common/tuners diff --git a/linux/drivers/media/video/saa7134/Makefile b/linux/drivers/media/video/saa7134/Makefile index 3dbaa19a6..604158a8c 100644 --- a/linux/drivers/media/video/saa7134/Makefile +++ b/linux/drivers/media/video/saa7134/Makefile @@ -3,8 +3,7 @@ saa7134-objs := saa7134-cards.o saa7134-core.o saa7134-i2c.o \ saa7134-ts.o saa7134-tvaudio.o saa7134-vbi.o \ saa7134-video.o saa7134-input.o -obj-$(CONFIG_VIDEO_SAA7134) += saa7134.o saa7134-empress.o \ - saa6752hs.o +obj-$(CONFIG_VIDEO_SAA7134) += saa6752hs.o saa7134.o saa7134-empress.o obj-$(CONFIG_VIDEO_SAA7134_ALSA) += saa7134-alsa.o -- cgit v1.2.3 From aa180367f345706e7f042506f21cbab42c6e233a Mon Sep 17 00:00:00 2001 From: "Igor M. Liplianin" Date: Sat, 13 Jun 2009 14:10:24 +0300 Subject: Remote control debugging for dw2102 driver based USB cards From: Igor M. Liplianin Remote control debugging for dw2102 driver based USB cards It includes DVBWorld, TeVii, Terratec and others. Type 'modprobe dvb-usb-dw2102 debug=4', then look at dmesg output. Signed-off-by: Igor M. Liplianin --- linux/drivers/media/dvb/dvb-usb/dw2102.c | 27 ++++++++++++++++++++------- linux/drivers/media/dvb/dvb-usb/dw2102.h | 1 + 2 files changed, 21 insertions(+), 7 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/dvb-usb/dw2102.c b/linux/drivers/media/dvb/dvb-usb/dw2102.c index 2b8ee587b..725d5c00d 100644 --- a/linux/drivers/media/dvb/dvb-usb/dw2102.c +++ b/linux/drivers/media/dvb/dvb-usb/dw2102.c @@ -51,7 +51,9 @@ struct dw210x_rc_keys { /* debug */ static int dvb_usb_dw2102_debug; module_param_named(debug, dvb_usb_dw2102_debug, int, 0644); -MODULE_PARM_DESC(debug, "set debugging level (1=info 2=xfer (or-able))." DVB_USB_DEBUG_STATUS); +MODULE_PARM_DESC(debug, "set debugging level (1=info 2=xfer 4=rc(or-able))." + DVB_USB_DEBUG_STATUS); + DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); @@ -565,26 +567,37 @@ static int dw2102_rc_query(struct dvb_usb_device *d, u32 *event, int *state) { struct dw210x_state *st = d->priv; u8 key[2]; - struct i2c_msg msg[] = { - {.addr = DW2102_RC_QUERY, .flags = I2C_M_RD, .buf = key, - .len = 2}, + struct i2c_msg msg = { + .addr = DW2102_RC_QUERY, + .flags = I2C_M_RD, + .buf = key, + .len = 2 }; int i; *state = REMOTE_NO_KEY_PRESSED; - if (dw2102_i2c_transfer(&d->i2c_adap, msg, 1) == 1) { + if (dw2102_i2c_transfer(&d->i2c_adap, &msg, 1) == 1) { for (i = 0; i < ARRAY_SIZE(dw210x_rc_keys); i++) { - if (dw210x_rc_keys[i].data == msg[0].buf[0]) { + if (dw210x_rc_keys[i].data == msg.buf[0]) { *state = REMOTE_KEY_PRESSED; *event = dw210x_rc_keys[i].event; st->last_key_pressed = dw210x_rc_keys[i].event; break; } + st->last_key_pressed = 0; } + + if ((*state) == REMOTE_KEY_PRESSED) + deb_rc("%s: found rc key: %x, %x, event: %x\n", + __func__, key[0], key[1], (*event)); + else if (key[0] != 0xff) + deb_rc("%s: unknown rc key: %x, %x\n", + __func__, key[0], key[1]); + } - /* info("key: %x %x\n",key[0],key[1]); */ + return 0; } diff --git a/linux/drivers/media/dvb/dvb-usb/dw2102.h b/linux/drivers/media/dvb/dvb-usb/dw2102.h index e3370734e..5cd0b0eb6 100644 --- a/linux/drivers/media/dvb/dvb-usb/dw2102.h +++ b/linux/drivers/media/dvb/dvb-usb/dw2102.h @@ -5,4 +5,5 @@ #include "dvb-usb.h" #define deb_xfer(args...) dprintk(dvb_usb_dw2102_debug, 0x02, args) +#define deb_rc(args...) dprintk(dvb_usb_dw2102_debug, 0x04, args) #endif -- cgit v1.2.3 From 8a7773709ee61adb37f483c166f80d1d9f6ef25b Mon Sep 17 00:00:00 2001 From: "Igor M. Liplianin" Date: Mon, 15 Jun 2009 01:41:22 +0300 Subject: Add keymaps for TeVii and TBS USB DVB-S/S2 cards From: Igor M. Liplianin Add keymaps for TeVii and TBS USB DVB-S/S2 cards Also module parameter named keymap inserted for override default keymap. Signed-off-by: Igor M. Liplianin --- linux/drivers/media/dvb/dvb-usb/dw2102.c | 126 +++++++++++++++++++++++++++---- 1 file changed, 110 insertions(+), 16 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/dvb-usb/dw2102.c b/linux/drivers/media/dvb/dvb-usb/dw2102.c index 725d5c00d..cf1fc5e83 100644 --- a/linux/drivers/media/dvb/dvb-usb/dw2102.c +++ b/linux/drivers/media/dvb/dvb-usb/dw2102.c @@ -40,12 +40,9 @@ #define DW2102_VOLTAGE_CTRL (0x1800) #define DW2102_RC_QUERY (0x1a00) -struct dw210x_state { - u32 last_key_pressed; -}; -struct dw210x_rc_keys { - u32 keycode; - u32 event; +struct dvb_usb_rc_keys_table { + struct dvb_usb_rc_key *rc_keys; + int rc_keys_size; }; /* debug */ @@ -54,6 +51,10 @@ module_param_named(debug, dvb_usb_dw2102_debug, int, 0644); MODULE_PARM_DESC(debug, "set debugging level (1=info 2=xfer 4=rc(or-able))." DVB_USB_DEBUG_STATUS); +/* keymaps */ +static int ir_keymap; +module_param_named(keymap, ir_keymap, int, 0644); +MODULE_PARM_DESC(keymap, "set keymap 0=default 1=dvbworld 2=tevii 3=tbs ..."); DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); @@ -474,6 +475,7 @@ static int dw2104_frontend_attach(struct dvb_usb_adapter *d) } static struct dvb_usb_device_properties dw2102_properties; +static struct dvb_usb_device_properties dw2104_properties; static int dw2102_frontend_attach(struct dvb_usb_adapter *d) { @@ -558,14 +560,103 @@ static struct dvb_usb_rc_key dw210x_rc_keys[] = { { 0xf8, 0x40, KEY_F }, /*full*/ { 0xf8, 0x1e, KEY_W }, /*tvmode*/ { 0xf8, 0x1b, KEY_B }, /*recall*/ +}; +static struct dvb_usb_rc_key tevii_rc_keys[] = { + { 0xf8, 0x0a, KEY_POWER }, + { 0xf8, 0x0c, KEY_MUTE }, + { 0xf8, 0x11, KEY_1 }, + { 0xf8, 0x12, KEY_2 }, + { 0xf8, 0x13, KEY_3 }, + { 0xf8, 0x14, KEY_4 }, + { 0xf8, 0x15, KEY_5 }, + { 0xf8, 0x16, KEY_6 }, + { 0xf8, 0x17, KEY_7 }, + { 0xf8, 0x18, KEY_8 }, + { 0xf8, 0x19, KEY_9 }, + { 0xf8, 0x10, KEY_0 }, + { 0xf8, 0x1c, KEY_MENU }, + { 0xf8, 0x0f, KEY_VOLUMEDOWN }, + { 0xf8, 0x1a, KEY_LAST }, + { 0xf8, 0x0e, KEY_OPEN }, + { 0xf8, 0x04, KEY_RECORD }, + { 0xf8, 0x09, KEY_VOLUMEUP }, + { 0xf8, 0x08, KEY_CHANNELUP }, + { 0xf8, 0x07, KEY_PVR }, + { 0xf8, 0x0b, KEY_TIME }, + { 0xf8, 0x02, KEY_RIGHT }, + { 0xf8, 0x03, KEY_LEFT }, + { 0xf8, 0x00, KEY_UP }, + { 0xf8, 0x1f, KEY_OK }, + { 0xf8, 0x01, KEY_DOWN }, + { 0xf8, 0x05, KEY_TUNER }, + { 0xf8, 0x06, KEY_CHANNELDOWN }, + { 0xf8, 0x40, KEY_PLAYPAUSE }, + { 0xf8, 0x1e, KEY_REWIND }, + { 0xf8, 0x1b, KEY_FAVORITES }, + { 0xf8, 0x1d, KEY_BACK }, + { 0xf8, 0x4d, KEY_FASTFORWARD }, + { 0xf8, 0x44, KEY_EPG }, + { 0xf8, 0x4c, KEY_INFO }, + { 0xf8, 0x41, KEY_AB }, + { 0xf8, 0x43, KEY_AUDIO }, + { 0xf8, 0x45, KEY_SUBTITLE }, + { 0xf8, 0x4a, KEY_LIST }, + { 0xf8, 0x46, KEY_F1 }, + { 0xf8, 0x47, KEY_F2 }, + { 0xf8, 0x5e, KEY_F3 }, + { 0xf8, 0x5c, KEY_F4 }, + { 0xf8, 0x52, KEY_F5 }, + { 0xf8, 0x5a, KEY_F6 }, + { 0xf8, 0x56, KEY_MODE }, + { 0xf8, 0x58, KEY_SWITCHVIDEOMODE }, }; +static struct dvb_usb_rc_key tbs_rc_keys[] = { + { 0xf8, 0x84, KEY_POWER }, + { 0xf8, 0x94, KEY_MUTE }, + { 0xf8, 0x87, KEY_1 }, + { 0xf8, 0x86, KEY_2 }, + { 0xf8, 0x85, KEY_3 }, + { 0xf8, 0x8b, KEY_4 }, + { 0xf8, 0x8a, KEY_5 }, + { 0xf8, 0x89, KEY_6 }, + { 0xf8, 0x8f, KEY_7 }, + { 0xf8, 0x8e, KEY_8 }, + { 0xf8, 0x8d, KEY_9 }, + { 0xf8, 0x92, KEY_0 }, + { 0xf8, 0x96, KEY_CHANNELUP }, + { 0xf8, 0x91, KEY_CHANNELDOWN }, + { 0xf8, 0x93, KEY_VOLUMEUP }, + { 0xf8, 0x8c, KEY_VOLUMEDOWN }, + { 0xf8, 0x83, KEY_RECORD }, + { 0xf8, 0x98, KEY_PAUSE }, + { 0xf8, 0x99, KEY_OK }, + { 0xf8, 0x9a, KEY_SHUFFLE }, + { 0xf8, 0x81, KEY_UP }, + { 0xf8, 0x90, KEY_LEFT }, + { 0xf8, 0x82, KEY_RIGHT }, + { 0xf8, 0x88, KEY_DOWN }, + { 0xf8, 0x95, KEY_FAVORITES }, + { 0xf8, 0x97, KEY_SUBTITLE }, + { 0xf8, 0x9d, KEY_ZOOM }, + { 0xf8, 0x9f, KEY_EXIT }, + { 0xf8, 0x9e, KEY_MENU }, + { 0xf8, 0x9c, KEY_EPG }, + { 0xf8, 0x80, KEY_PREVIOUS }, + { 0xf8, 0x9b, KEY_MODE } +}; +static struct dvb_usb_rc_keys_table keys_tables[] = { + { dw210x_rc_keys, ARRAY_SIZE(dw210x_rc_keys) }, + { tevii_rc_keys, ARRAY_SIZE(tevii_rc_keys) }, + { tbs_rc_keys, ARRAY_SIZE(tbs_rc_keys) }, +}; static int dw2102_rc_query(struct dvb_usb_device *d, u32 *event, int *state) { - struct dw210x_state *st = d->priv; + struct dvb_usb_rc_key *keymap = d->props.rc_key_map; + int keymap_size = d->props.rc_key_map_size; u8 key[2]; struct i2c_msg msg = { .addr = DW2102_RC_QUERY, @@ -574,19 +665,21 @@ static int dw2102_rc_query(struct dvb_usb_device *d, u32 *event, int *state) .len = 2 }; int i; + /* override keymap */ + if ((ir_keymap > 0) && (ir_keymap <= ARRAY_SIZE(keys_tables))) { + keymap = keys_tables[ir_keymap - 1].rc_keys ; + keymap_size = keys_tables[ir_keymap - 1].rc_keys_size; + } *state = REMOTE_NO_KEY_PRESSED; if (dw2102_i2c_transfer(&d->i2c_adap, &msg, 1) == 1) { - for (i = 0; i < ARRAY_SIZE(dw210x_rc_keys); i++) { - if (dw210x_rc_keys[i].data == msg.buf[0]) { + for (i = 0; i < keymap_size ; i++) { + if (keymap[i].data == msg.buf[0]) { *state = REMOTE_KEY_PRESSED; - *event = dw210x_rc_keys[i].event; - st->last_key_pressed = - dw210x_rc_keys[i].event; + *event = keymap[i].event; break; } - st->last_key_pressed = 0; } if ((*state) == REMOTE_KEY_PRESSED) @@ -667,8 +760,11 @@ static int dw2102_load_firmware(struct usb_device *dev, } /* init registers */ switch (dev->descriptor.idProduct) { - case USB_PID_DW2104: case 0xd650: + dw2104_properties.rc_key_map = tevii_rc_keys; + dw2104_properties.rc_key_map_size = + ARRAY_SIZE(tevii_rc_keys); + case USB_PID_DW2104: reset = 1; dw210x_op_rw(dev, 0xc4, 0x0000, 0, &reset, 1, DW210X_WRITE_MSG); @@ -725,7 +821,6 @@ static struct dvb_usb_device_properties dw2102_properties = { .caps = DVB_USB_IS_AN_I2C_ADAPTER, .usb_ctrl = DEVICE_SPECIFIC, .firmware = "dvb-usb-dw2102.fw", - .size_of_priv = sizeof(struct dw210x_state), .no_reconnect = 1, .i2c_algo = &dw2102_serit_i2c_algo, @@ -777,7 +872,6 @@ static struct dvb_usb_device_properties dw2104_properties = { .caps = DVB_USB_IS_AN_I2C_ADAPTER, .usb_ctrl = DEVICE_SPECIFIC, .firmware = "dvb-usb-dw2104.fw", - .size_of_priv = sizeof(struct dw210x_state), .no_reconnect = 1, .i2c_algo = &dw2104_i2c_algo, -- cgit v1.2.3 From f8eb1c250a545b18aadc3d0962b49b33759a13cc Mon Sep 17 00:00:00 2001 From: "Igor M. Liplianin" Date: Mon, 15 Jun 2009 02:51:45 +0300 Subject: Add support for DVBWorld DVB-C USB Cable card. From: Igor M. Liplianin DVBWorld DVB-C USB Cable card contains TUA6034 tuner, TDA10023 demod and Cypress FX-2 controller. http://www.worlddvb.com/product/htm/usbc.htm Signed-off-by: Igor M. Liplianin --- linux/drivers/media/dvb/dvb-usb/dw2102.c | 179 +++++++++++++++++++++++++++++-- 1 file changed, 168 insertions(+), 11 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/dvb-usb/dw2102.c b/linux/drivers/media/dvb/dvb-usb/dw2102.c index cf1fc5e83..0fc9be43a 100644 --- a/linux/drivers/media/dvb/dvb-usb/dw2102.c +++ b/linux/drivers/media/dvb/dvb-usb/dw2102.c @@ -1,7 +1,7 @@ /* DVB USB framework compliant Linux driver for the -* DVBWorld DVB-S 2101, 2102, DVB-S2 2104 Card -* -* Copyright (C) 2008 Igor M. Liplianin (liplianin@me.by) +* DVBWorld DVB-S 2101, 2102, DVB-S2 2104, DVB-C 3101, +* TeVii S600, S650 Cards +* Copyright (C) 2008,2009 Igor M. Liplianin (liplianin@me.by) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -17,6 +17,7 @@ #include "stb6000.h" #include "eds1547.h" #include "cx24116.h" +#include "tda1002x.h" #ifndef USB_PID_DW2102 #define USB_PID_DW2102 0x2102 @@ -26,10 +27,18 @@ #define USB_PID_DW2104 0x2104 #endif +#ifndef USB_PID_DW3101 +#define USB_PID_DW3101 0x3101 +#endif + #ifndef USB_PID_CINERGY_S #define USB_PID_CINERGY_S 0x0064 #endif +#ifndef USB_PID_TEVII_S650 +#define USB_PID_TEVII_S650 0xd650 +#endif + #define DW210X_READ_MSG 0 #define DW210X_WRITE_MSG 1 @@ -82,7 +91,7 @@ static int dw210x_op_rw(struct usb_device *dev, u8 request, u16 value, static int dw2102_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[], int num) { -struct dvb_usb_device *d = i2c_get_adapdata(adap); + struct dvb_usb_device *d = i2c_get_adapdata(adap); int i = 0, ret = 0; u8 buf6[] = {0x2c, 0x05, 0xc0, 0, 0, 0, 0}; u16 value; @@ -208,6 +217,7 @@ static int dw2102_serit_i2c_transfer(struct i2c_adapter *adap, mutex_unlock(&d->i2c_mutex); return num; } + static int dw2102_earda_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[], int num) { struct dvb_usb_device *d = i2c_get_adapdata(adap); @@ -222,7 +232,7 @@ static int dw2102_earda_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg ms case 2: { /* read */ /* first write first register number */ - u8 ibuf [msg[1].len + 2], obuf[3]; + u8 ibuf[msg[1].len + 2], obuf[3]; obuf[0] = 0xd0; obuf[1] = msg[0].len; obuf[2] = msg[0].buf[0]; @@ -296,7 +306,7 @@ static int dw2104_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[], i case 2: { /* read */ /* first write first register number */ - u8 ibuf [msg[1].len + 2], obuf[3]; + u8 ibuf[msg[1].len + 2], obuf[3]; obuf[0] = 0xaa; obuf[1] = msg[0].len; obuf[2] = msg[0].buf[0]; @@ -363,6 +373,69 @@ static int dw2104_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[], i return num; } +static int dw3101_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[], + int num) +{ + struct dvb_usb_device *d = i2c_get_adapdata(adap); + int ret = 0, i; + + if (!d) + return -ENODEV; + if (mutex_lock_interruptible(&d->i2c_mutex) < 0) + return -EAGAIN; + + switch (num) { + case 2: { + /* read */ + /* first write first register number */ + u8 ibuf[msg[1].len + 2], obuf[3]; + obuf[0] = msg[0].addr << 1; + obuf[1] = msg[0].len; + obuf[2] = msg[0].buf[0]; + ret = dw210x_op_rw(d->udev, 0xc2, 0, 0, + obuf, msg[0].len + 2, DW210X_WRITE_MSG); + /* second read registers */ + ret = dw210x_op_rw(d->udev, 0xc3, 0x19 , 0, + ibuf, msg[1].len + 2, DW210X_READ_MSG); + memcpy(msg[1].buf, ibuf + 2, msg[1].len); + + break; + } + case 1: + switch (msg[0].addr) { + case 0x60: + case 0x0c: { + /* write to register */ + u8 obuf[msg[0].len + 2]; + obuf[0] = msg[0].addr << 1; + obuf[1] = msg[0].len; + memcpy(obuf + 2, msg[0].buf, msg[0].len); + ret = dw210x_op_rw(d->udev, 0xc2, 0, 0, + obuf, msg[0].len + 2, DW210X_WRITE_MSG); + break; + } + case(DW2102_RC_QUERY): { + u8 ibuf[2]; + ret = dw210x_op_rw(d->udev, 0xb8, 0, 0, + ibuf, 2, DW210X_READ_MSG); + memcpy(msg[0].buf, ibuf , 2); + break; + } + } + + break; + } + + for (i = 0; i < num; i++) { + deb_xfer("%02x:%02x: %s ", i, msg[i].addr, + msg[i].flags == 0 ? ">>>" : "<<<"); + debug_dump(msg[i].buf, msg[i].len, deb_xfer); + } + + mutex_unlock(&d->i2c_mutex); + return num; +} + static u32 dw210x_i2c_func(struct i2c_adapter *adapter) { return I2C_FUNC_I2C; @@ -400,6 +473,14 @@ static struct i2c_algorithm dw2104_i2c_algo = { #endif }; +static struct i2c_algorithm dw3101_i2c_algo = { + .master_xfer = dw3101_i2c_transfer, + .functionality = dw210x_i2c_func, +#ifdef NEED_ALGO_CONTROL + .algo_control = dummy_algo_control, +#endif +}; + static int dw210x_read_mac_address(struct dvb_usb_device *d, u8 mac[6]) { int i; @@ -419,6 +500,7 @@ static int dw210x_read_mac_address(struct dvb_usb_device *d, u8 mac[6]) debug_dump(eepromline, 16, deb_xfer); } } + memcpy(mac, eeprom + 8, 6); return 0; }; @@ -463,6 +545,11 @@ static struct si21xx_config serit_sp1511lhb_config = { }; +static struct tda10023_config dw3101_tda10023_config = { + .demod_address = 0x0c, + .invert = 1, +}; + static int dw2104_frontend_attach(struct dvb_usb_adapter *d) { if ((d->fe = dvb_attach(cx24116_attach, &dw2104_config, @@ -513,6 +600,17 @@ static int dw2102_frontend_attach(struct dvb_usb_adapter *d) return -EIO; } +static int dw3101_frontend_attach(struct dvb_usb_adapter *d) +{ + d->fe = dvb_attach(tda10023_attach, &dw3101_tda10023_config, + &d->dev->i2c_adap, 0x48); + if (d->fe != NULL) { + info("Attached tda10023!\n"); + return 0; + } + return -EIO; +} + static int dw2102_tuner_attach(struct dvb_usb_adapter *adap) { dvb_attach(dvb_pll_attach, adap->fe, 0x60, @@ -528,6 +626,14 @@ static int dw2102_earda_tuner_attach(struct dvb_usb_adapter *adap) return 0; } +static int dw3101_tuner_attach(struct dvb_usb_adapter *adap) +{ + dvb_attach(dvb_pll_attach, adap->fe, 0x60, + &adap->dev->i2c_adap, DVB_PLL_TUA6034); + + return 0; +} + static struct dvb_usb_rc_key dw210x_rc_keys[] = { { 0xf8, 0x0a, KEY_Q }, /*power*/ { 0xf8, 0x0c, KEY_M }, /*mute*/ @@ -697,9 +803,10 @@ static int dw2102_rc_query(struct dvb_usb_device *d, u32 *event, int *state) static struct usb_device_id dw2102_table[] = { {USB_DEVICE(USB_VID_CYPRESS, USB_PID_DW2102)}, {USB_DEVICE(USB_VID_CYPRESS, 0x2101)}, - {USB_DEVICE(USB_VID_CYPRESS, 0x2104)}, - {USB_DEVICE(0x9022, 0xd650)}, + {USB_DEVICE(USB_VID_CYPRESS, USB_PID_DW2104)}, + {USB_DEVICE(0x9022, USB_PID_TEVII_S650)}, {USB_DEVICE(USB_VID_TERRATEC, USB_PID_CINERGY_S)}, + {USB_DEVICE(USB_VID_CYPRESS, USB_PID_DW3101)}, { } }; @@ -760,7 +867,7 @@ static int dw2102_load_firmware(struct usb_device *dev, } /* init registers */ switch (dev->descriptor.idProduct) { - case 0xd650: + case USB_PID_TEVII_S650: dw2104_properties.rc_key_map = tevii_rc_keys; dw2104_properties.rc_key_map_size = ARRAY_SIZE(tevii_rc_keys); @@ -768,6 +875,8 @@ static int dw2102_load_firmware(struct usb_device *dev, reset = 1; dw210x_op_rw(dev, 0xc4, 0x0000, 0, &reset, 1, DW210X_WRITE_MSG); + /* break omitted intentionally */ + case USB_PID_DW3101: reset = 0; dw210x_op_rw(dev, 0xbf, 0x0040, 0, &reset, 0, DW210X_WRITE_MSG); @@ -811,6 +920,7 @@ static int dw2102_load_firmware(struct usb_device *dev, DW210X_READ_MSG); break; } + msleep(100); kfree(p); } @@ -834,7 +944,7 @@ static struct dvb_usb_device_properties dw2102_properties = { .num_adapters = 1, .download_firmware = dw2102_load_firmware, .read_mac_address = dw210x_read_mac_address, - .adapter = { + .adapter = { { .frontend_attach = dw2102_frontend_attach, .streaming_ctrl = NULL, @@ -915,12 +1025,57 @@ static struct dvb_usb_device_properties dw2104_properties = { } }; +static struct dvb_usb_device_properties dw3101_properties = { + .caps = DVB_USB_IS_AN_I2C_ADAPTER, + .usb_ctrl = DEVICE_SPECIFIC, + .firmware = "dvb-usb-dw3101.fw", + .no_reconnect = 1, + + .i2c_algo = &dw3101_i2c_algo, + .rc_key_map = dw210x_rc_keys, + .rc_key_map_size = ARRAY_SIZE(dw210x_rc_keys), + .rc_interval = 150, + .rc_query = dw2102_rc_query, + + .generic_bulk_ctrl_endpoint = 0x81, + /* parameter for the MPEG2-data transfer */ + .num_adapters = 1, + .download_firmware = dw2102_load_firmware, + .read_mac_address = dw210x_read_mac_address, + .adapter = { + { + .frontend_attach = dw3101_frontend_attach, + .streaming_ctrl = NULL, + .tuner_attach = dw3101_tuner_attach, + .stream = { + .type = USB_BULK, + .count = 8, + .endpoint = 0x82, + .u = { + .bulk = { + .buffersize = 4096, + } + } + }, + } + }, + .num_device_descs = 1, + .devices = { + { "DVBWorld DVB-C 3101 USB2.0", + {&dw2102_table[5], NULL}, + {NULL}, + }, + } +}; + static int dw2102_probe(struct usb_interface *intf, const struct usb_device_id *id) { if (0 == dvb_usb_device_init(intf, &dw2102_properties, THIS_MODULE, NULL, adapter_nr) || 0 == dvb_usb_device_init(intf, &dw2104_properties, + THIS_MODULE, NULL, adapter_nr) || + 0 == dvb_usb_device_init(intf, &dw3101_properties, THIS_MODULE, NULL, adapter_nr)) { return 0; } @@ -952,6 +1107,8 @@ module_init(dw2102_module_init); module_exit(dw2102_module_exit); MODULE_AUTHOR("Igor M. Liplianin (c) liplianin@me.by"); -MODULE_DESCRIPTION("Driver for DVBWorld DVB-S 2101, 2102, DVB-S2 2104 USB2.0 device"); +MODULE_DESCRIPTION("Driver for DVBWorld DVB-S 2101, 2102, DVB-S2 2104," + " DVB-C 3101 USB2.0," + " TeVii S600, S650 USB2.0 devices"); MODULE_VERSION("0.1"); MODULE_LICENSE("GPL"); -- cgit v1.2.3 From 279ab5cb24214bc30fc83bb50f63d418498f00e8 Mon Sep 17 00:00:00 2001 From: "Igor M. Liplianin" Date: Mon, 15 Jun 2009 03:34:12 +0300 Subject: Add support for yet another SDMC DM1105 based DVB-S card. From: Igor M. Liplianin Add support for SDMC DM1105 based DVB-S cards with PCI ID 195d:1105 Also create separate workqueue for demuxing. Signed-off-by: Igor M. Liplianin --- linux/drivers/media/dvb/dm1105/dm1105.c | 121 +++++++++++++++++++++----------- 1 file changed, 80 insertions(+), 41 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/dm1105/dm1105.c b/linux/drivers/media/dvb/dm1105/dm1105.c index ca1048fd4..17edeb66b 100644 --- a/linux/drivers/media/dvb/dm1105/dm1105.c +++ b/linux/drivers/media/dvb/dm1105/dm1105.c @@ -51,6 +51,9 @@ #ifndef PCI_VENDOR_ID_TRIGEM #define PCI_VENDOR_ID_TRIGEM 0x109f #endif +#ifndef PCI_VENDOR_ID_AXESS +#define PCI_VENDOR_ID_AXESS 0x195d +#endif #ifndef PCI_DEVICE_ID_DM1105 #define PCI_DEVICE_ID_DM1105 0x036f #endif @@ -60,6 +63,9 @@ #ifndef PCI_DEVICE_ID_DW2004 #define PCI_DEVICE_ID_DW2004 0x2004 #endif +#ifndef PCI_DEVICE_ID_DM05 +#define PCI_DEVICE_ID_DM05 0x1105 +#endif /* ----------------------------------------------- */ /* sdmc dm1105 registers */ @@ -150,6 +156,11 @@ #define DM1105_LNB_13V 0x00010100 #define DM1105_LNB_18V 0x00000100 +/* GPIO's for LNB power control for Axess DM05 */ +#define DM05_LNB_MASK 0x00000000 +#define DM05_LNB_13V 0x00020000 +#define DM05_LNB_18V 0x00030000 + static int ir_debug; module_param(ir_debug, int, 0644); MODULE_PARM_DESC(ir_debug, "enable debugging information for IR decoding"); @@ -188,6 +199,8 @@ struct dm1105dvb { /* irq */ struct work_struct work; + struct workqueue_struct *wq; + char wqn[16]; /* dma */ dma_addr_t dma_addr; @@ -316,15 +329,25 @@ static inline struct dm1105dvb *frontend_to_dm1105dvb(struct dvb_frontend *fe) static int dm1105dvb_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) { struct dm1105dvb *dm1105dvb = frontend_to_dm1105dvb(fe); + u32 lnb_mask, lnb_13v, lnb_18v; - if (voltage == SEC_VOLTAGE_18) { - outl(DM1105_LNB_MASK, dm_io_mem(DM1105_GPIOCTR)); - outl(DM1105_LNB_18V, dm_io_mem(DM1105_GPIOVAL)); - } else { - /*LNB ON-13V by default!*/ - outl(DM1105_LNB_MASK, dm_io_mem(DM1105_GPIOCTR)); - outl(DM1105_LNB_13V, dm_io_mem(DM1105_GPIOVAL)); - } + switch (dm1105dvb->pdev->subsystem_device) { + case PCI_DEVICE_ID_DM05: + lnb_mask = DM05_LNB_MASK; + lnb_13v = DM05_LNB_13V; + lnb_18v = DM05_LNB_18V; + break; + default: + lnb_mask = DM1105_LNB_MASK; + lnb_13v = DM1105_LNB_13V; + lnb_18v = DM1105_LNB_18V; + } + + outl(lnb_mask, dm_io_mem(DM1105_GPIOCTR)); + if (voltage == SEC_VOLTAGE_18) + outl(lnb_18v , dm_io_mem(DM1105_GPIOVAL)); + else + outl(lnb_13v, dm_io_mem(DM1105_GPIOVAL)); return 0; } @@ -463,7 +486,7 @@ static irqreturn_t dm1105dvb_irq(int irq, void *dev_id) case (INTSTS_TSIRQ | INTSTS_IR): dm1105dvb->nextwrp = inl(dm_io_mem(DM1105_WRP)) - inl(dm_io_mem(DM1105_STADR)); - schedule_work(&dm1105dvb->work); + queue_work(dm1105dvb->wq, &dm1105dvb->work); break; case INTSTS_IR: dm1105dvb->ir.ir_command = inl(dm_io_mem(DM1105_IRCODE)); @@ -599,46 +622,44 @@ static int __devinit frontend_init(struct dm1105dvb *dm1105dvb) int ret; switch (dm1105dvb->pdev->subsystem_device) { - case PCI_DEVICE_ID_DW2002: + case PCI_DEVICE_ID_DW2004: dm1105dvb->fe = dvb_attach( - stv0299_attach, &sharp_z0194a_config, + cx24116_attach, &serit_sp2633_config, &dm1105dvb->i2c_adap); + if (dm1105dvb->fe) + dm1105dvb->fe->ops.set_voltage = dm1105dvb_set_voltage; + break; + default: + dm1105dvb->fe = dvb_attach( + stv0299_attach, &sharp_z0194a_config, + &dm1105dvb->i2c_adap); if (dm1105dvb->fe) { dm1105dvb->fe->ops.set_voltage = dm1105dvb_set_voltage; dvb_attach(dvb_pll_attach, dm1105dvb->fe, 0x60, &dm1105dvb->i2c_adap, DVB_PLL_OPERA1); + break; } - if (!dm1105dvb->fe) { - dm1105dvb->fe = dvb_attach( - stv0288_attach, &earda_config, - &dm1105dvb->i2c_adap); - if (dm1105dvb->fe) { - dm1105dvb->fe->ops.set_voltage = - dm1105dvb_set_voltage; - dvb_attach(stb6000_attach, dm1105dvb->fe, 0x61, - &dm1105dvb->i2c_adap); - } + dm1105dvb->fe = dvb_attach( + stv0288_attach, &earda_config, + &dm1105dvb->i2c_adap); + if (dm1105dvb->fe) { + dm1105dvb->fe->ops.set_voltage = + dm1105dvb_set_voltage; + dvb_attach(stb6000_attach, dm1105dvb->fe, 0x61, + &dm1105dvb->i2c_adap); + break; } - if (!dm1105dvb->fe) { - dm1105dvb->fe = dvb_attach( - si21xx_attach, &serit_config, - &dm1105dvb->i2c_adap); - if (dm1105dvb->fe) - dm1105dvb->fe->ops.set_voltage = - dm1105dvb_set_voltage; - } - break; - case PCI_DEVICE_ID_DW2004: dm1105dvb->fe = dvb_attach( - cx24116_attach, &serit_sp2633_config, + si21xx_attach, &serit_config, &dm1105dvb->i2c_adap); if (dm1105dvb->fe) - dm1105dvb->fe->ops.set_voltage = dm1105dvb_set_voltage; - break; + dm1105dvb->fe->ops.set_voltage = + dm1105dvb_set_voltage; + } if (!dm1105dvb->fe) { @@ -662,10 +683,17 @@ static void __devinit dm1105dvb_read_mac(struct dm1105dvb *dm1105dvb, u8 *mac) static u8 command[1] = { 0x28 }; struct i2c_msg msg[] = { - { .addr = IIC_24C01_addr >> 1, .flags = 0, - .buf = command, .len = 1 }, - { .addr = IIC_24C01_addr >> 1, .flags = I2C_M_RD, - .buf = mac, .len = 6 }, + { + .addr = IIC_24C01_addr >> 1, + .flags = 0, + .buf = command, + .len = 1 + }, { + .addr = IIC_24C01_addr >> 1, + .flags = I2C_M_RD, + .buf = mac, + .len = 6 + }, }; dm1105_i2c_xfer(&dm1105dvb->i2c_adap, msg , 2); @@ -788,14 +816,22 @@ static int __devinit dm1105_probe(struct pci_dev *pdev, #else INIT_WORK(&dm1105dvb->work, dm1105_dmx_buffer); #endif + sprintf(dm1105dvb->wqn, "%s/%d", dvb_adapter->name, dvb_adapter->num); + dm1105dvb->wq = create_singlethread_workqueue(dm1105dvb->wqn); + if (!dm1105dvb->wq) + goto err_dvb_net; ret = request_irq(pdev->irq, dm1105dvb_irq, IRQF_SHARED, DRIVER_NAME, dm1105dvb); if (ret < 0) - goto err_free_irq; + goto err_workqueue; return 0; +err_workqueue: + destroy_workqueue(dm1105dvb->wq); +err_dvb_net: + dvb_net_release(&dm1105dvb->dvbnet); err_disconnect_frontend: dmx->disconnect_frontend(dmx); err_remove_mem_frontend: @@ -812,8 +848,6 @@ err_i2c_del_adapter: i2c_del_adapter(&dm1105dvb->i2c_adap); err_dm1105dvb_hw_exit: dm1105dvb_hw_exit(dm1105dvb); -err_free_irq: - free_irq(pdev->irq, dm1105dvb); err_pci_iounmap: pci_iounmap(pdev, dm1105dvb->io_mem); err_pci_release_regions: @@ -869,6 +903,11 @@ static struct pci_device_id dm1105_id_table[] __devinitdata = { .device = PCI_DEVICE_ID_DM1105, .subvendor = PCI_ANY_ID, .subdevice = PCI_DEVICE_ID_DW2004, + }, { + .vendor = PCI_VENDOR_ID_AXESS, + .device = PCI_DEVICE_ID_DM05, + .subvendor = PCI_VENDOR_ID_AXESS, + .subdevice = PCI_DEVICE_ID_DM05, }, { /* empty */ }, -- cgit v1.2.3 From 6f3d74e1d2c5407251649488848e76a576cfc633 Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Sun, 14 Jun 2009 22:05:20 -0400 Subject: au8522: add support for QAM-64 modulation type From: Frank Dischner Add support for QAM64 modulation type to the au8522 demod driver. Priority: normal Signed-off-by: Frank Dischner Signed-off-by: Devin Heitmueller --- linux/drivers/media/dvb/frontends/au8522_dig.c | 98 ++++++++++++++++++++++++-- 1 file changed, 92 insertions(+), 6 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/frontends/au8522_dig.c b/linux/drivers/media/dvb/frontends/au8522_dig.c index 41aedcc99..9375905ee 100644 --- a/linux/drivers/media/dvb/frontends/au8522_dig.c +++ b/linux/drivers/media/dvb/frontends/au8522_dig.c @@ -367,11 +367,90 @@ static struct { { 0x8231, 0x13 }, }; -/* QAM Modulation table */ +/* QAM64 Modulation table */ static struct { u16 reg; u16 data; -} QAM_mod_tab[] = { +} QAM64_mod_tab[] = { + { 0x00a3, 0x09 }, + { 0x00a4, 0x00 }, + { 0x0081, 0xc4 }, + { 0x00a5, 0x40 }, + { 0x00aa, 0x77 }, + { 0x00ad, 0x77 }, + { 0x00a6, 0x67 }, + { 0x0262, 0x20 }, + { 0x021c, 0x30 }, + { 0x00b8, 0x3e }, + { 0x00b9, 0xf0 }, + { 0x00ba, 0x01 }, + { 0x00bb, 0x18 }, + { 0x00bc, 0x50 }, + { 0x00bd, 0x00 }, + { 0x00be, 0xea }, + { 0x00bf, 0xef }, + { 0x00c0, 0xfc }, + { 0x00c1, 0xbd }, + { 0x00c2, 0x1f }, + { 0x00c3, 0xfc }, + { 0x00c4, 0xdd }, + { 0x00c5, 0xaf }, + { 0x00c6, 0x00 }, + { 0x00c7, 0x38 }, + { 0x00c8, 0x30 }, + { 0x00c9, 0x05 }, + { 0x00ca, 0x4a }, + { 0x00cb, 0xd0 }, + { 0x00cc, 0x01 }, + { 0x00cd, 0xd9 }, + { 0x00ce, 0x6f }, + { 0x00cf, 0xf9 }, + { 0x00d0, 0x70 }, + { 0x00d1, 0xdf }, + { 0x00d2, 0xf7 }, + { 0x00d3, 0xc2 }, + { 0x00d4, 0xdf }, + { 0x00d5, 0x02 }, + { 0x00d6, 0x9a }, + { 0x00d7, 0xd0 }, + { 0x0250, 0x0d }, + { 0x0251, 0xcd }, + { 0x0252, 0xe0 }, + { 0x0253, 0x05 }, + { 0x0254, 0xa7 }, + { 0x0255, 0xff }, + { 0x0256, 0xed }, + { 0x0257, 0x5b }, + { 0x0258, 0xae }, + { 0x0259, 0xe6 }, + { 0x025a, 0x3d }, + { 0x025b, 0x0f }, + { 0x025c, 0x0d }, + { 0x025d, 0xea }, + { 0x025e, 0xf2 }, + { 0x025f, 0x51 }, + { 0x0260, 0xf5 }, + { 0x0261, 0x06 }, + { 0x021a, 0x00 }, + { 0x0546, 0x40 }, + { 0x0210, 0xc7 }, + { 0x0211, 0xaa }, + { 0x0212, 0xab }, + { 0x0213, 0x02 }, + { 0x0502, 0x00 }, + { 0x0121, 0x04 }, + { 0x0122, 0x04 }, + { 0x052e, 0x10 }, + { 0x00a4, 0xca }, + { 0x00a7, 0x40 }, + { 0x0526, 0x01 }, +}; + +/* QAM256 Modulation table */ +static struct { + u16 reg; + u16 data; +} QAM256_mod_tab[] = { { 0x80a3, 0x09 }, { 0x80a4, 0x00 }, { 0x8081, 0xc4 }, @@ -464,12 +543,19 @@ static int au8522_enable_modulation(struct dvb_frontend *fe, au8522_set_if(fe, state->config->vsb_if); break; case QAM_64: + dprintk("%s() QAM 64\n", __func__); + for (i = 0; i < ARRAY_SIZE(QAM64_mod_tab); i++) + au8522_writereg(state, + QAM64_mod_tab[i].reg, + QAM64_mod_tab[i].data); + au8522_set_if(fe, state->config->qam_if); + break; case QAM_256: - dprintk("%s() QAM 64/256\n", __func__); - for (i = 0; i < ARRAY_SIZE(QAM_mod_tab); i++) + dprintk("%s() QAM 256\n", __func__); + for (i = 0; i < ARRAY_SIZE(QAM256_mod_tab); i++) au8522_writereg(state, - QAM_mod_tab[i].reg, - QAM_mod_tab[i].data); + QAM256_mod_tab[i].reg, + QAM256_mod_tab[i].data); au8522_set_if(fe, state->config->qam_if); break; default: -- cgit v1.2.3 From c94ab6cb1dd05db76fdf72b92dc40ffcf3f47d29 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 15 Jun 2009 10:04:00 -0300 Subject: ov511: Fix unit_video parameter behavior From: Mauro Carvalho Chehab Fix a regression caused by changeset 9133:64aed7485a43 - v4l: disconnect kernel number from minor Before the above changeset, ov511_probe used to allow forcing to use a certain specific set of video devices, like: modprobe ov511 unit_video=4,1,3 num_uv=3 So, assuming that you have 5 ov511 devices, and connect they one by one, they'll gain the following device numbers (at the connection order): /dev/video4 /dev/video1 /dev/video3 /dev/video0 /dev/video2 However, this was changed due to this change at video_register_device(): + nr = find_next_zero_bit(video_nums[type], minor_cnt, nr == -1 ? 0 : nr); With the previous behavior, a trial to register on an already allocated mirror would fail, and a loop would get the next requested minor. However, the current behavior is to get the next available minor instead of failing. Due to that, this means that the above modprobe parameter will give, instead: /dev/video5 /dev/video6 /dev/video7 /dev/video8 /dev/video9 In order to restore the original behavior, a static var were added, storing the amount of already registered devices. While there, it also fixes the locking of the probe/disconnect functions. Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/ov511.c | 45 +++++++++++++++++++++++++++------------ linux/drivers/media/video/ov511.h | 3 +++ 2 files changed, 34 insertions(+), 14 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/ov511.c b/linux/drivers/media/video/ov511.c index 12d109eaa..2839546b1 100644 --- a/linux/drivers/media/video/ov511.c +++ b/linux/drivers/media/video/ov511.c @@ -112,6 +112,8 @@ static int framedrop = -1; static int fastset; static int force_palette; static int backlight; +/* Bitmask marking allocated devices from 0 to OV511_MAX_UNIT_VIDEO */ +static unsigned long ov511_devused; static int unit_video[OV511_MAX_UNIT_VIDEO]; static int remove_zeros; static int mirror; @@ -5724,7 +5726,7 @@ ov51x_probe(struct usb_interface *intf, const struct usb_device_id *id) struct usb_device *dev = interface_to_usbdev(intf); struct usb_interface_descriptor *idesc; struct usb_ov511 *ov; - int i; + int i, rc, nr; PDEBUG(1, "probing for device..."); @@ -5849,33 +5851,41 @@ ov51x_probe(struct usb_interface *intf, const struct usb_device_id *id) ov->vdev->parent = &intf->dev; video_set_drvdata(ov->vdev, ov); - for (i = 0; i < OV511_MAX_UNIT_VIDEO; i++) { - /* Minor 0 cannot be specified; assume user wants autodetect */ - if (unit_video[i] == 0) - break; + mutex_lock(&ov->lock); - if (video_register_device(ov->vdev, VFL_TYPE_GRABBER, - unit_video[i]) >= 0) { - break; - } - } + /* Check to see next free device and mark as used */ + nr = find_first_zero_bit(&ov511_devused, OV511_MAX_UNIT_VIDEO); + + /* Registers device */ + if (unit_video[nr] != 0) + rc = video_register_device(ov->vdev, VFL_TYPE_GRABBER, + unit_video[nr]); + else + rc = video_register_device(ov->vdev, VFL_TYPE_GRABBER, -1); - /* Use the next available one */ - if ((ov->vdev->minor == -1) && - video_register_device(ov->vdev, VFL_TYPE_GRABBER, -1) < 0) { + if (rc < 0) { err("video_register_device failed"); + mutex_unlock(&ov->lock); goto error; } + /* Mark device as used */ + ov511_devused |= 1 << nr; + ov->nr = nr; + dev_info(&intf->dev, "Device at %s registered to minor %d\n", ov->usb_path, ov->vdev->minor); usb_set_intfdata(intf, ov); if (ov_create_sysfs(ov->vdev)) { err("ov_create_sysfs failed"); + ov511_devused &= ~(1 << nr); + mutex_unlock(&ov->lock); goto error; } + mutex_lock(&ov->lock); + return 0; error: @@ -5910,10 +5920,16 @@ ov51x_disconnect(struct usb_interface *intf) PDEBUG(3, ""); + mutex_lock(&ov->lock); usb_set_intfdata (intf, NULL); - if (!ov) + if (!ov) { + mutex_unlock(&ov->lock); return; + } + + /* Free device number */ + ov511_devused &= ~(1 << ov->nr); if (ov->vdev) video_unregister_device(ov->vdev); @@ -5931,6 +5947,7 @@ ov51x_disconnect(struct usb_interface *intf) ov->streaming = 0; ov51x_unlink_isoc(ov); + mutex_unlock(&ov->lock); ov->dev = NULL; diff --git a/linux/drivers/media/video/ov511.h b/linux/drivers/media/video/ov511.h index c303ac5a8..c213d944e 100644 --- a/linux/drivers/media/video/ov511.h +++ b/linux/drivers/media/video/ov511.h @@ -495,6 +495,9 @@ struct usb_ov511 { int has_decoder; /* Device has a video decoder */ int pal; /* Device is designed for PAL resolution */ + /* ov511 device number ID */ + int nr; /* Stores a device number */ + /* I2C interface */ struct mutex i2c_lock; /* Protect I2C controller regs */ unsigned char primary_i2c_slave; /* I2C write id of sensor */ -- cgit v1.2.3 From aa387bcec63ca659d9c03f9ad7ff70299d41f527 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 16 Jun 2009 00:46:40 -0300 Subject: dvb-usb/Kconfig: DVBWorld DVB-C USB Cable card needs tda1002x frontend From: Mauro Carvalho Chehab Auto-selects tda1002x if !DVB_FE_CUSTOMISE Priority: normal CC: Igor M. Liplianin Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/dvb-usb/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/dvb-usb/Kconfig b/linux/drivers/media/dvb/dvb-usb/Kconfig index 60955a70d..8a8a1bede 100644 --- a/linux/drivers/media/dvb/dvb-usb/Kconfig +++ b/linux/drivers/media/dvb/dvb-usb/Kconfig @@ -261,6 +261,7 @@ config DVB_USB_DW2102 select DVB_STB6000 if !DVB_FE_CUSTOMISE select DVB_CX24116 if !DVB_FE_CUSTOMISE select DVB_SI21XX if !DVB_FE_CUSTOMISE + select DVB_TDA10021 if !DVB_FE_CUSTOMISE help Say Y here to support the DvbWorld DVB-S/S2 USB2.0 receivers and the TeVii S650. -- cgit v1.2.3 From 6c59e2781795481200d573e3a4ef8b033924987a Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 8 May 2009 02:31:02 +0000 Subject: saa7134-video.c: fix the block bug From: figo.zhang when re-open or re-start (video_streamon), the q->curr would not be NULL in saa7134_buffer_queue(), and all the qbuf will add to q->queue list,no one to do activate to start DMA,and then no interrupt would happened,so it will be block. In VIDEOBUF_NEEDS_INIT state, initialize the curr pointer to be NULL in the buffer_prepare(). Signed-off-by: Figo.zhang Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/saa7134/saa7134-video.c | 1 + 1 file changed, 1 insertion(+) (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 518de9b2c..4212c4ec8 100644 --- a/linux/drivers/media/video/saa7134/saa7134-video.c +++ b/linux/drivers/media/video/saa7134/saa7134-video.c @@ -1057,6 +1057,7 @@ static int buffer_prepare(struct videobuf_queue *q, buf->vb.field = field; buf->fmt = fh->fmt; buf->pt = &fh->pt_cap; + dev->video_q.curr = NULL; err = videobuf_iolock(q,&buf->vb,&dev->ovbuf); if (err) -- cgit v1.2.3 From 8220eb0d3b9e4da0f7f057b1c80fd7e1b15e3151 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Fri, 8 May 2009 21:39:24 -0400 Subject: cx23885: add ATSC/QAM tuning support for Hauppauge WinTV-HVR1275 From: Michael Krufky Priority: normal Signed-off-by: Michael Krufky --- linux/drivers/media/video/cx23885/cx23885-cards.c | 17 +++++++++++++++-- linux/drivers/media/video/cx23885/cx23885-dvb.c | 1 + linux/drivers/media/video/cx23885/cx23885.h | 1 + 3 files changed, 17 insertions(+), 2 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/cx23885/cx23885-cards.c b/linux/drivers/media/video/cx23885/cx23885-cards.c index 299182227..45b2856c9 100644 --- a/linux/drivers/media/video/cx23885/cx23885-cards.c +++ b/linux/drivers/media/video/cx23885/cx23885-cards.c @@ -186,6 +186,10 @@ struct cx23885_board cx23885_boards[] = { .name = "Hauppauge WinTV-HVR1270", .portc = CX23885_MPEG_DVB, }, + [CX23885_BOARD_HAUPPAUGE_HVR1275] = { + .name = "Hauppauge WinTV-HVR1275", + .portc = CX23885_MPEG_DVB, + }, }; const unsigned int cx23885_bcount = ARRAY_SIZE(cx23885_boards); @@ -289,6 +293,10 @@ struct cx23885_subid cx23885_subids[] = { .subvendor = 0x0070, .subdevice = 0x2211, .card = CX23885_BOARD_HAUPPAUGE_HVR1270, + }, { + .subvendor = 0x0070, + .subdevice = 0x2215, + .card = CX23885_BOARD_HAUPPAUGE_HVR1275, }, }; const unsigned int cx23885_idcount = ARRAY_SIZE(cx23885_subids); @@ -629,12 +637,14 @@ void cx23885_gpio_setup(struct cx23885_dev *dev) cx_write(GPIO_ISM, 0x00000000);/* INTERRUPTS active low*/ break; case CX23885_BOARD_HAUPPAUGE_HVR1270: + case CX23885_BOARD_HAUPPAUGE_HVR1275: + /* GPIO-5 RF Control: 0 = RF1 Terrestrial, 1 = RF2 Cable */ /* GPIO-6 I2C Gate which can isolate the 3305 from the bus */ /* GPIO-9 LG3305 reset */ /* Put the parts into reset and back */ - cx23885_gpio_enable(dev, GPIO_9 | GPIO_6, 1); - cx23885_gpio_set(dev, GPIO_9 | GPIO_6); + cx23885_gpio_enable(dev, GPIO_9 | GPIO_6 | GPIO_5, 1); + cx23885_gpio_set(dev, GPIO_9 | GPIO_6 | GPIO_5); cx23885_gpio_clear(dev, GPIO_9); mdelay(20); cx23885_gpio_set(dev, GPIO_9); @@ -652,6 +662,7 @@ int cx23885_ir_init(struct cx23885_dev *dev) case CX23885_BOARD_HAUPPAUGE_HVR1200: case CX23885_BOARD_HAUPPAUGE_HVR1400: case CX23885_BOARD_HAUPPAUGE_HVR1270: + case CX23885_BOARD_HAUPPAUGE_HVR1275: /* FIXME: Implement me */ break; case CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP: @@ -688,6 +699,7 @@ void cx23885_card_setup(struct cx23885_dev *dev) case CX23885_BOARD_HAUPPAUGE_HVR1200: case CX23885_BOARD_HAUPPAUGE_HVR1700: case CX23885_BOARD_HAUPPAUGE_HVR1270: + case CX23885_BOARD_HAUPPAUGE_HVR1275: if (dev->i2c_bus[0].i2c_rc == 0) hauppauge_eeprom(dev, eeprom+0xc0); break; @@ -746,6 +758,7 @@ void cx23885_card_setup(struct cx23885_dev *dev) case CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H: case CX23885_BOARD_COMPRO_VIDEOMATE_E650F: case CX23885_BOARD_HAUPPAUGE_HVR1270: + case CX23885_BOARD_HAUPPAUGE_HVR1275: default: ts2->gen_ctrl_val = 0xc; /* Serial bus + punctured clock */ ts2->ts_clk_en_val = 0x1; /* Enable TS_CLK */ diff --git a/linux/drivers/media/video/cx23885/cx23885-dvb.c b/linux/drivers/media/video/cx23885/cx23885-dvb.c index b60f68a6d..6f9a5f72c 100644 --- a/linux/drivers/media/video/cx23885/cx23885-dvb.c +++ b/linux/drivers/media/video/cx23885/cx23885-dvb.c @@ -423,6 +423,7 @@ static int dvb_register(struct cx23885_tsport *port) } break; case CX23885_BOARD_HAUPPAUGE_HVR1270: + case CX23885_BOARD_HAUPPAUGE_HVR1275: i2c_bus = &dev->i2c_bus[0]; fe0->dvb.frontend = dvb_attach(lgdt3305_attach, &hcw_lgdt3305_config, diff --git a/linux/drivers/media/video/cx23885/cx23885.h b/linux/drivers/media/video/cx23885/cx23885.h index 21d886212..645333922 100644 --- a/linux/drivers/media/video/cx23885/cx23885.h +++ b/linux/drivers/media/video/cx23885/cx23885.h @@ -73,6 +73,7 @@ #define CX23885_BOARD_DVBWORLD_2005 16 #define CX23885_BOARD_NETUP_DUAL_DVBS2_CI 17 #define CX23885_BOARD_HAUPPAUGE_HVR1270 18 +#define CX23885_BOARD_HAUPPAUGE_HVR1275 19 #define GPIO_0 0x00000001 #define GPIO_1 0x00000002 -- cgit v1.2.3 From fa2725b25f78c7b35f5c9c2a5087612a6c009bb9 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Fri, 8 May 2009 15:05:29 -0400 Subject: cx23885: add ATSC/QAM tuning support for Hauppauge WinTV-HVR1255 From: Michael Krufky Priority: normal Signed-off-by: Michael Krufky --- linux/drivers/media/video/cx23885/cx23885-cards.c | 12 ++++++++++++ linux/drivers/media/video/cx23885/cx23885-dvb.c | 21 +++++++++++++++++++++ linux/drivers/media/video/cx23885/cx23885.h | 1 + 3 files changed, 34 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/cx23885/cx23885-cards.c b/linux/drivers/media/video/cx23885/cx23885-cards.c index 45b2856c9..2d398f755 100644 --- a/linux/drivers/media/video/cx23885/cx23885-cards.c +++ b/linux/drivers/media/video/cx23885/cx23885-cards.c @@ -190,6 +190,10 @@ struct cx23885_board cx23885_boards[] = { .name = "Hauppauge WinTV-HVR1275", .portc = CX23885_MPEG_DVB, }, + [CX23885_BOARD_HAUPPAUGE_HVR1255] = { + .name = "Hauppauge WinTV-HVR1255", + .portc = CX23885_MPEG_DVB, + }, }; const unsigned int cx23885_bcount = ARRAY_SIZE(cx23885_boards); @@ -297,6 +301,10 @@ struct cx23885_subid cx23885_subids[] = { .subvendor = 0x0070, .subdevice = 0x2215, .card = CX23885_BOARD_HAUPPAUGE_HVR1275, + }, { + .subvendor = 0x0070, + .subdevice = 0x2251, + .card = CX23885_BOARD_HAUPPAUGE_HVR1255, }, }; const unsigned int cx23885_idcount = ARRAY_SIZE(cx23885_subids); @@ -638,6 +646,7 @@ void cx23885_gpio_setup(struct cx23885_dev *dev) break; case CX23885_BOARD_HAUPPAUGE_HVR1270: case CX23885_BOARD_HAUPPAUGE_HVR1275: + case CX23885_BOARD_HAUPPAUGE_HVR1255: /* GPIO-5 RF Control: 0 = RF1 Terrestrial, 1 = RF2 Cable */ /* GPIO-6 I2C Gate which can isolate the 3305 from the bus */ /* GPIO-9 LG3305 reset */ @@ -663,6 +672,7 @@ int cx23885_ir_init(struct cx23885_dev *dev) case CX23885_BOARD_HAUPPAUGE_HVR1400: case CX23885_BOARD_HAUPPAUGE_HVR1270: case CX23885_BOARD_HAUPPAUGE_HVR1275: + case CX23885_BOARD_HAUPPAUGE_HVR1255: /* FIXME: Implement me */ break; case CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP: @@ -700,6 +710,7 @@ void cx23885_card_setup(struct cx23885_dev *dev) case CX23885_BOARD_HAUPPAUGE_HVR1700: case CX23885_BOARD_HAUPPAUGE_HVR1270: case CX23885_BOARD_HAUPPAUGE_HVR1275: + case CX23885_BOARD_HAUPPAUGE_HVR1255: if (dev->i2c_bus[0].i2c_rc == 0) hauppauge_eeprom(dev, eeprom+0xc0); break; @@ -759,6 +770,7 @@ void cx23885_card_setup(struct cx23885_dev *dev) case CX23885_BOARD_COMPRO_VIDEOMATE_E650F: case CX23885_BOARD_HAUPPAUGE_HVR1270: case CX23885_BOARD_HAUPPAUGE_HVR1275: + case CX23885_BOARD_HAUPPAUGE_HVR1255: default: ts2->gen_ctrl_val = 0xc; /* Serial bus + punctured clock */ ts2->ts_clk_en_val = 0x1; /* Enable TS_CLK */ diff --git a/linux/drivers/media/video/cx23885/cx23885-dvb.c b/linux/drivers/media/video/cx23885/cx23885-dvb.c index 6f9a5f72c..c671d8e46 100644 --- a/linux/drivers/media/video/cx23885/cx23885-dvb.c +++ b/linux/drivers/media/video/cx23885/cx23885-dvb.c @@ -198,6 +198,16 @@ static struct s5h1411_config dvico_s5h1411_config = { .mpeg_timing = S5H1411_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK, }; +static struct s5h1411_config hcw_s5h1411_config = { + .output_mode = S5H1411_SERIAL_OUTPUT, + .gpio = S5H1411_GPIO_OFF, + .vsb_if = S5H1411_IF_44000, + .qam_if = S5H1411_IF_4000, + .inversion = S5H1411_INVERSION_ON, + .status_mode = S5H1411_DEMODLOCKING, + .mpeg_timing = S5H1411_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK, +}; + static struct xc5000_config hauppauge_hvr1500q_tunerconfig = { .i2c_address = 0x61, .if_khz = 5380, @@ -434,6 +444,17 @@ static int dvb_register(struct cx23885_tsport *port) &hcw_lgdt3305_tda18271_config); } break; + case CX23885_BOARD_HAUPPAUGE_HVR1255: + i2c_bus = &dev->i2c_bus[0]; + fe0->dvb.frontend = dvb_attach(s5h1411_attach, + &hcw_s5h1411_config, + &i2c_bus->i2c_adap); + if (fe0->dvb.frontend != NULL) { + dvb_attach(tda18271_attach, fe0->dvb.frontend, + 0x60, &dev->i2c_bus[1].i2c_adap, + &hauppauge_tda18271_config); + } + break; case CX23885_BOARD_HAUPPAUGE_HVR1800: i2c_bus = &dev->i2c_bus[0]; switch (alt_tuner) { diff --git a/linux/drivers/media/video/cx23885/cx23885.h b/linux/drivers/media/video/cx23885/cx23885.h index 645333922..947ade659 100644 --- a/linux/drivers/media/video/cx23885/cx23885.h +++ b/linux/drivers/media/video/cx23885/cx23885.h @@ -74,6 +74,7 @@ #define CX23885_BOARD_NETUP_DUAL_DVBS2_CI 17 #define CX23885_BOARD_HAUPPAUGE_HVR1270 18 #define CX23885_BOARD_HAUPPAUGE_HVR1275 19 +#define CX23885_BOARD_HAUPPAUGE_HVR1255 20 #define GPIO_0 0x00000001 #define GPIO_1 0x00000002 -- cgit v1.2.3 From 010bc93a2744240c769f474f024d8e6e6c385536 Mon Sep 17 00:00:00 2001 From: Tobias Lorenz Date: Sun, 21 Jun 2009 00:00:06 +0200 Subject: Version 1.0.10 Add support for interrupt mode for RDS endpoint, instead of polling. Improves RDS reception significantly Signed-off-by: Edouard Lafargue Acked-by: Tobias Lorenz --- linux/drivers/media/radio/radio-si470x.c | 350 +++++++++++++++++-------------- 1 file changed, 192 insertions(+), 158 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/radio/radio-si470x.c b/linux/drivers/media/radio/radio-si470x.c index 101ede1cf..1358ee2bb 100644 --- a/linux/drivers/media/radio/radio-si470x.c +++ b/linux/drivers/media/radio/radio-si470x.c @@ -106,20 +106,24 @@ * Tobias Lorenz * - add LED status output * - get HW/SW version from scratchpad + * 2009-06-16 Edouard Lafargue + * Version 1.0.10 + * - add support for interrupt mode for RDS endpoint, + * instead of polling. + * Improves RDS reception significantly * * ToDo: * - add firmware download/update support - * - RDS support: interrupt mode, instead of polling */ /* driver definitions */ #define DRIVER_AUTHOR "Tobias Lorenz " #define DRIVER_NAME "radio-si470x" -#define DRIVER_KERNEL_VERSION KERNEL_VERSION(1, 0, 9) +#define DRIVER_KERNEL_VERSION KERNEL_VERSION(1, 0, 10) #define DRIVER_CARD "Silicon Labs Si470x FM Radio Receiver" #define DRIVER_DESC "USB radio driver for Si470x FM Radio Receivers" -#define DRIVER_VERSION "1.0.9" +#define DRIVER_VERSION "1.0.10" /* kernel includes */ @@ -218,16 +222,6 @@ static unsigned short max_rds_errors = 1; module_param(max_rds_errors, ushort, 0644); MODULE_PARM_DESC(max_rds_errors, "RDS maximum block errors: *1*"); -/* RDS poll frequency */ -static unsigned int rds_poll_time = 40; -/* 40 is used by the original USBRadio.exe */ -/* 50 is used by radio-cadet */ -/* 75 should be okay */ -/* 80 is the usual RDS receive interval */ -module_param(rds_poll_time, uint, 0644); -MODULE_PARM_DESC(rds_poll_time, "RDS poll time (ms): *40*"); - - /************************************************************************** * Register Definitions @@ -450,6 +444,12 @@ struct si470x_device { struct usb_interface *intf; struct video_device *videodev; + /* Interrupt endpoint handling */ + char *int_in_buffer; + struct usb_endpoint_descriptor *int_in_endpoint; + struct urb *int_in_urb; + int int_in_running; + /* driver management */ unsigned int users; unsigned char disconnected; @@ -459,7 +459,6 @@ struct si470x_device { unsigned short registers[RADIO_REGISTER_NUM]; /* RDS receive buffer */ - struct delayed_work work; wait_queue_head_t read_queue; struct mutex lock; /* buffer locking */ unsigned char *buffer; /* size is always multiple of three */ @@ -864,43 +863,6 @@ static int si470x_get_all_registers(struct si470x_device *radio) -/************************************************************************** - * General Driver Functions - RDS_REPORT - **************************************************************************/ - -/* - * si470x_get_rds_registers - read rds registers - */ -static int si470x_get_rds_registers(struct si470x_device *radio) -{ - unsigned char buf[RDS_REPORT_SIZE]; - int retval; - int size; - unsigned char regnr; - - buf[0] = RDS_REPORT; - - retval = usb_interrupt_msg(radio->usbdev, - usb_rcvintpipe(radio->usbdev, 1), - (void *) &buf, sizeof(buf), &size, usb_timeout); - if (size != sizeof(buf)) - printk(KERN_WARNING DRIVER_NAME ": si470x_get_rds_registers: " - "return size differs: %d != %zu\n", size, sizeof(buf)); - if (retval < 0) - printk(KERN_WARNING DRIVER_NAME ": si470x_get_rds_registers: " - "usb_interrupt_msg returned %d\n", retval); - - if (retval >= 0) - for (regnr = 0; regnr < RDS_REGISTER_NUM; regnr++) - radio->registers[STATUSRSSI + regnr] = - get_unaligned_be16( - &buf[regnr * RADIO_REGISTER_SIZE + 1]); - - return (retval < 0) ? -EINVAL : 0; -} - - - /************************************************************************** * General Driver Functions - LED_REPORT **************************************************************************/ @@ -959,102 +921,118 @@ static int si470x_get_scratch_page_versions(struct si470x_device *radio) **************************************************************************/ /* - * si470x_rds - rds processing function + * si470x_int_in_callback - rds callback and processing function + * + * TODO: do we need to use mutex locks in some sections? */ -static void si470x_rds(struct si470x_device *radio) +static void si470x_int_in_callback(struct urb *urb) { + struct si470x_device *radio = urb->context; + unsigned char buf[RDS_REPORT_SIZE]; + int retval; + unsigned char regnr; unsigned char blocknum; unsigned short bler; /* rds block errors */ unsigned short rds; unsigned char tmpbuf[3]; - /* get rds blocks */ - if (si470x_get_rds_registers(radio) < 0) - return; - if ((radio->registers[STATUSRSSI] & STATUSRSSI_RDSR) == 0) { - /* No RDS group ready */ - return; - } - if ((radio->registers[STATUSRSSI] & STATUSRSSI_RDSS) == 0) { - /* RDS decoder not synchronized */ - return; - } - - /* copy all four RDS blocks to internal buffer */ - mutex_lock(&radio->lock); - for (blocknum = 0; blocknum < 4; blocknum++) { - switch (blocknum) { - default: - bler = (radio->registers[STATUSRSSI] & - STATUSRSSI_BLERA) >> 9; - rds = radio->registers[RDSA]; - break; - case 1: - bler = (radio->registers[READCHAN] & - READCHAN_BLERB) >> 14; - rds = radio->registers[RDSB]; - break; - case 2: - bler = (radio->registers[READCHAN] & - READCHAN_BLERC) >> 12; - rds = radio->registers[RDSC]; - break; - case 3: - bler = (radio->registers[READCHAN] & - READCHAN_BLERD) >> 10; - rds = radio->registers[RDSD]; - break; - }; - - /* Fill the V4L2 RDS buffer */ - put_unaligned_le16(rds, &tmpbuf); - tmpbuf[2] = blocknum; /* offset name */ - tmpbuf[2] |= blocknum << 3; /* received offset */ - if (bler > max_rds_errors) - tmpbuf[2] |= 0x80; /* uncorrectable errors */ - else if (bler > 0) - tmpbuf[2] |= 0x40; /* corrected error(s) */ - - /* copy RDS block to internal buffer */ - memcpy(&radio->buffer[radio->wr_index], &tmpbuf, 3); - radio->wr_index += 3; - - /* wrap write pointer */ - if (radio->wr_index >= radio->buf_size) - radio->wr_index = 0; - - /* check for overflow */ - if (radio->wr_index == radio->rd_index) { - /* increment and wrap read pointer */ - radio->rd_index += 3; - if (radio->rd_index >= radio->buf_size) - radio->rd_index = 0; + if (urb->status) { + if (urb->status == -ENOENT || + urb->status == -ECONNRESET || + urb->status == -ESHUTDOWN) { + return; + } else { + printk(KERN_WARNING DRIVER_NAME + ": non-zero urb status (%d)\n", urb->status); + goto resubmit; /* Maybe we can recover. */ } } - mutex_unlock(&radio->lock); - - /* wake up read queue */ - if (radio->wr_index != radio->rd_index) - wake_up_interruptible(&radio->read_queue); -} - - -/* - * si470x_work - rds work function - */ -static void si470x_work(struct work_struct *work) -{ - struct si470x_device *radio = container_of(work, struct si470x_device, - work.work); /* safety checks */ if (radio->disconnected) return; if ((radio->registers[SYSCONFIG1] & SYSCONFIG1_RDS) == 0) - return; + goto resubmit; - si470x_rds(radio); - schedule_delayed_work(&radio->work, msecs_to_jiffies(rds_poll_time)); + if (urb->actual_length > 0) { + /* Update RDS registers with URB data */ + buf[0] = RDS_REPORT; + for (regnr = 0; regnr < RDS_REGISTER_NUM; regnr++) + radio->registers[STATUSRSSI + regnr] = + get_unaligned_be16(&radio->int_in_buffer[ + regnr * RADIO_REGISTER_SIZE + 1]); + /* get rds blocks */ + if ((radio->registers[STATUSRSSI] & STATUSRSSI_RDSR) == 0) { + /* No RDS group ready, better luck next time */ + goto resubmit; + } + if ((radio->registers[STATUSRSSI] & STATUSRSSI_RDSS) == 0) { + /* RDS decoder not synchronized */ + goto resubmit; + } + for (blocknum = 0; blocknum < 4; blocknum++) { + switch (blocknum) { + default: + bler = (radio->registers[STATUSRSSI] & + STATUSRSSI_BLERA) >> 9; + rds = radio->registers[RDSA]; + break; + case 1: + bler = (radio->registers[READCHAN] & + READCHAN_BLERB) >> 14; + rds = radio->registers[RDSB]; + break; + case 2: + bler = (radio->registers[READCHAN] & + READCHAN_BLERC) >> 12; + rds = radio->registers[RDSC]; + break; + case 3: + bler = (radio->registers[READCHAN] & + READCHAN_BLERD) >> 10; + rds = radio->registers[RDSD]; + break; + }; + + /* Fill the V4L2 RDS buffer */ + put_unaligned_le16(rds, &tmpbuf); + tmpbuf[2] = blocknum; /* offset name */ + tmpbuf[2] |= blocknum << 3; /* received offset */ + if (bler > max_rds_errors) + tmpbuf[2] |= 0x80; /* uncorrectable errors */ + else if (bler > 0) + tmpbuf[2] |= 0x40; /* corrected error(s) */ + + /* copy RDS block to internal buffer */ + memcpy(&radio->buffer[radio->wr_index], &tmpbuf, 3); + radio->wr_index += 3; + + /* wrap write pointer */ + if (radio->wr_index >= radio->buf_size) + radio->wr_index = 0; + + /* check for overflow */ + if (radio->wr_index == radio->rd_index) { + /* increment and wrap read pointer */ + radio->rd_index += 3; + if (radio->rd_index >= radio->buf_size) + radio->rd_index = 0; + } + } + if (radio->wr_index != radio->rd_index) + wake_up_interruptible(&radio->read_queue); + } + +resubmit: + /* Resubmit if we're still running. */ + if (radio->int_in_running && radio->usbdev) { + retval = usb_submit_urb(radio->int_in_urb, GFP_ATOMIC); + if (retval) { + printk(KERN_WARNING DRIVER_NAME + ": resubmitting urb failed (%d)", retval); + radio->int_in_running = 0; + } + } } @@ -1076,8 +1054,6 @@ static ssize_t si470x_fops_read(struct file *file, char __user *buf, /* switch on rds reception */ if ((radio->registers[SYSCONFIG1] & SYSCONFIG1_RDS) == 0) { si470x_rds_on(radio); - schedule_delayed_work(&radio->work, - msecs_to_jiffies(rds_poll_time)); } /* block if no new data available */ @@ -1136,8 +1112,6 @@ static unsigned int si470x_fops_poll(struct file *file, /* switch on rds reception */ if ((radio->registers[SYSCONFIG1] & SYSCONFIG1_RDS) == 0) { si470x_rds_on(radio); - schedule_delayed_work(&radio->work, - msecs_to_jiffies(rds_poll_time)); } poll_wait(file, &radio->read_queue, pts); @@ -1167,11 +1141,37 @@ static int si470x_fops_open(struct file *file) goto done; } + printk(KERN_INFO DRIVER_NAME + ": Opened radio (users now: %i)\n", radio->users); + if (radio->users == 1) { /* start radio */ retval = si470x_start(radio); - if (retval < 0) + if (retval < 0) { usb_autopm_put_interface(radio->intf); + goto done; + } + /* Initialize interrupt URB. */ + usb_fill_int_urb(radio->int_in_urb, radio->usbdev, + usb_rcvintpipe(radio->usbdev, + radio->int_in_endpoint->bEndpointAddress), + radio->int_in_buffer, + le16_to_cpu(radio->int_in_endpoint->wMaxPacketSize), + si470x_int_in_callback, + radio, + radio->int_in_endpoint->bInterval); + + radio->int_in_running = 1; + mb(); + + retval = usb_submit_urb(radio->int_in_urb, GFP_KERNEL); + if (retval) { + printk(KERN_INFO DRIVER_NAME + ": submitting int urb failed (%d)\n", retval); + radio->int_in_running = 0; + usb_autopm_put_interface(radio->intf); + } + } done: @@ -1196,17 +1196,25 @@ static int si470x_fops_release(struct file *file) mutex_lock(&radio->disconnect_lock); radio->users--; + printk(KERN_INFO DRIVER_NAME + ": Closed radio (remaining users:%i)\n", radio->users); if (radio->users == 0) { + + /* Shutdown Interrupt handler */ + if (radio->int_in_running) { + radio->int_in_running = 0; + if (radio->int_in_urb) + usb_kill_urb(radio->int_in_urb); + } + if (radio->disconnected) { video_unregister_device(radio->videodev); + kfree(radio->int_in_buffer); kfree(radio->buffer); kfree(radio); goto done; } - /* stop rds reception */ - cancel_delayed_work_sync(&radio->work); - /* cancel read processes */ wake_up_interruptible(&radio->read_queue); @@ -1658,7 +1666,9 @@ static int si470x_usb_driver_probe(struct usb_interface *intf, const struct usb_device_id *id) { struct si470x_device *radio; - int retval = 0; + struct usb_host_interface *iface_desc; + struct usb_endpoint_descriptor *endpoint; + int i, int_end_size, retval = 0; /* private data allocation and initialization */ radio = kzalloc(sizeof(struct si470x_device), GFP_KERNEL); @@ -1673,11 +1683,45 @@ static int si470x_usb_driver_probe(struct usb_interface *intf, mutex_init(&radio->disconnect_lock); mutex_init(&radio->lock); + iface_desc = intf->cur_altsetting; + + /* Set up interrupt endpoint information. */ + for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { + endpoint = &iface_desc->endpoint[i].desc; + if (((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == + USB_DIR_IN) && ((endpoint->bmAttributes & + USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT)) + radio->int_in_endpoint = endpoint; + } + if (!radio->int_in_endpoint) { + printk(KERN_INFO DRIVER_NAME + ": could not find interrupt in endpoint\n"); + retval = -EIO; + goto err_radio; + } + + int_end_size = le16_to_cpu(radio->int_in_endpoint->wMaxPacketSize); + + radio->int_in_buffer = kmalloc(int_end_size, GFP_KERNEL); + if (!radio->int_in_buffer) { + printk(KERN_INFO DRIVER_NAME + "could not allocate int_in_buffer"); + retval = -ENOMEM; + goto err_radio; + } + + radio->int_in_urb = usb_alloc_urb(0, GFP_KERNEL); + if (!radio->int_in_urb) { + printk(KERN_INFO DRIVER_NAME "could not allocate int_in_urb"); + retval = -ENOMEM; + goto err_intbuffer; + } + /* video device allocation and initialization */ radio->videodev = video_device_alloc(); if (!radio->videodev) { retval = -ENOMEM; - goto err_radio; + goto err_intbuffer; } memcpy(radio->videodev, &si470x_viddev_template, sizeof(si470x_viddev_template)); @@ -1735,9 +1779,6 @@ static int si470x_usb_driver_probe(struct usb_interface *intf, radio->rd_index = 0; init_waitqueue_head(&radio->read_queue); - /* prepare rds work function */ - INIT_DELAYED_WORK(&radio->work, si470x_work); - /* register video device */ retval = video_register_device(radio->videodev, VFL_TYPE_RADIO, radio_nr); if (retval) { @@ -1752,6 +1793,8 @@ err_all: kfree(radio->buffer); err_video: video_device_release(radio->videodev); +err_intbuffer: + kfree(radio->int_in_buffer); err_radio: kfree(radio); err_initial: @@ -1765,12 +1808,8 @@ err_initial: static int si470x_usb_driver_suspend(struct usb_interface *intf, pm_message_t message) { - struct si470x_device *radio = usb_get_intfdata(intf); - printk(KERN_INFO DRIVER_NAME ": suspending now...\n"); - cancel_delayed_work_sync(&radio->work); - return 0; } @@ -1780,16 +1819,8 @@ static int si470x_usb_driver_suspend(struct usb_interface *intf, */ static int si470x_usb_driver_resume(struct usb_interface *intf) { - struct si470x_device *radio = usb_get_intfdata(intf); - printk(KERN_INFO DRIVER_NAME ": resuming now...\n"); - mutex_lock(&radio->lock); - if (radio->users && radio->registers[SYSCONFIG1] & SYSCONFIG1_RDS) - schedule_delayed_work(&radio->work, - msecs_to_jiffies(rds_poll_time)); - mutex_unlock(&radio->lock); - return 0; } @@ -1803,12 +1834,15 @@ static void si470x_usb_driver_disconnect(struct usb_interface *intf) mutex_lock(&radio->disconnect_lock); radio->disconnected = 1; - cancel_delayed_work_sync(&radio->work); usb_set_intfdata(intf, NULL); if (radio->users == 0) { /* set led to disconnect state */ si470x_set_led_state(radio, BLINK_ORANGE_LED); + /* Free data structures. */ + usb_free_urb(radio->int_in_urb); + + kfree(radio->int_in_buffer); video_unregister_device(radio->videodev); kfree(radio->buffer); kfree(radio); -- cgit v1.2.3 From 98c1432a2113aa0c3aa68dcd754f61527375b7f8 Mon Sep 17 00:00:00 2001 From: Tobias Lorenz Date: Sun, 21 Jun 2009 00:14:50 +0200 Subject: Cleanup - Remove user count log messages - Comments adopted to general style Signed-off-by: Tobias Lorenz --- linux/drivers/media/radio/radio-si470x.c | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/radio/radio-si470x.c b/linux/drivers/media/radio/radio-si470x.c index 1358ee2bb..a40c8f355 100644 --- a/linux/drivers/media/radio/radio-si470x.c +++ b/linux/drivers/media/radio/radio-si470x.c @@ -1141,9 +1141,6 @@ static int si470x_fops_open(struct file *file) goto done; } - printk(KERN_INFO DRIVER_NAME - ": Opened radio (users now: %i)\n", radio->users); - if (radio->users == 1) { /* start radio */ retval = si470x_start(radio); @@ -1151,7 +1148,8 @@ static int si470x_fops_open(struct file *file) usb_autopm_put_interface(radio->intf); goto done; } - /* Initialize interrupt URB. */ + + /* initialize interrupt urb */ usb_fill_int_urb(radio->int_in_urb, radio->usbdev, usb_rcvintpipe(radio->usbdev, radio->int_in_endpoint->bEndpointAddress), @@ -1171,7 +1169,6 @@ static int si470x_fops_open(struct file *file) radio->int_in_running = 0; usb_autopm_put_interface(radio->intf); } - } done: @@ -1196,11 +1193,8 @@ static int si470x_fops_release(struct file *file) mutex_lock(&radio->disconnect_lock); radio->users--; - printk(KERN_INFO DRIVER_NAME - ": Closed radio (remaining users:%i)\n", radio->users); if (radio->users == 0) { - - /* Shutdown Interrupt handler */ + /* shutdown interrupt handler */ if (radio->int_in_running) { radio->int_in_running = 0; if (radio->int_in_urb) -- cgit v1.2.3 From cde1c0fde4222d9ad97877a793a9143f9b4cd850 Mon Sep 17 00:00:00 2001 From: Tobias Lorenz Date: Sun, 21 Jun 2009 00:17:30 +0200 Subject: removed v4l2_queryctrl in favor of v4l2_ctrl_query_fill Signed-off-by: Tobias Lorenz --- linux/drivers/media/radio/radio-si470x.c | 37 +++++--------------------------- 1 file changed, 5 insertions(+), 32 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/radio/radio-si470x.c b/linux/drivers/media/radio/radio-si470x.c index a40c8f355..de4673b3a 100644 --- a/linux/drivers/media/radio/radio-si470x.c +++ b/linux/drivers/media/radio/radio-si470x.c @@ -1242,31 +1242,6 @@ static const struct v4l2_file_operations si470x_fops = { * Video4Linux Interface **************************************************************************/ -/* - * si470x_v4l2_queryctrl - query control - */ -static struct v4l2_queryctrl si470x_v4l2_queryctrl[] = { - { - .id = V4L2_CID_AUDIO_VOLUME, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "Volume", - .minimum = 0, - .maximum = 15, - .step = 1, - .default_value = 15, - }, - { - .id = V4L2_CID_AUDIO_MUTE, - .type = V4L2_CTRL_TYPE_BOOLEAN, - .name = "Mute", - .minimum = 0, - .maximum = 1, - .step = 1, - .default_value = 1, - }, -}; - - /* * si470x_vidioc_querycap - query device capabilities */ @@ -1292,7 +1267,6 @@ static int si470x_vidioc_querycap(struct file *file, void *priv, static int si470x_vidioc_queryctrl(struct file *file, void *priv, struct v4l2_queryctrl *qc) { - unsigned char i = 0; int retval = -EINVAL; /* abort if qc->id is below V4L2_CID_BASE */ @@ -1300,12 +1274,11 @@ static int si470x_vidioc_queryctrl(struct file *file, void *priv, goto done; /* search video control */ - for (i = 0; i < ARRAY_SIZE(si470x_v4l2_queryctrl); i++) { - if (qc->id == si470x_v4l2_queryctrl[i].id) { - memcpy(qc, &(si470x_v4l2_queryctrl[i]), sizeof(*qc)); - retval = 0; /* found */ - break; - } + switch (qc->id) { + case V4L2_CID_AUDIO_VOLUME: + return v4l2_ctrl_query_fill(qc, 0, 15, 1, 15); + case V4L2_CID_AUDIO_MUTE: + return v4l2_ctrl_query_fill(qc, 0, 1, 1, 1); } /* disable unsupported base controls */ -- cgit v1.2.3 From 2e3dbe38af11659dad7ec398a503f64125c2617e Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Mon, 22 Jun 2009 21:32:32 -0400 Subject: em28xx: Fix tuning for Terratec Cinergy T XS USB (zl10353 version) From: Devin Heitmueller Fix the code so that the zl10353 version of the Terratec Cinergy T XS USB starts working again. This includes fixing what must have been a typo in the GPIO definition for the digital side of the board, and setting of the disable_i2c_gate_ctrl property for the zl10353 config, so that the i2c bus doesn't get wedged the first time something tries to close the gate. Also, add a printk() making clear that the mt352 version still isn't supported. This issue is still being actively debugged, but in the meantime at least the dmesg output will show a very clear error... Thanks to Jelle de Jong for providing sample hardware to test with. Thanks to Simon Kenyon for testing various patches and providing SSH access to his environment so I could debug with access to a valid signal source. Priority: high Signed-off-by: Devin Heitmueller Cc: Jelle de Jong Cc: Simon Kenyon --- linux/drivers/media/video/em28xx/em28xx-cards.c | 2 +- linux/drivers/media/video/em28xx/em28xx-dvb.c | 28 ++++++++++++++++++++++++- 2 files changed, 28 insertions(+), 2 deletions(-) (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 b824eed46..46ce91afc 100644 --- a/linux/drivers/media/video/em28xx/em28xx-cards.c +++ b/linux/drivers/media/video/em28xx/em28xx-cards.c @@ -863,7 +863,7 @@ struct em28xx_board em28xx_boards[] = { .tuner_gpio = default_tuner_gpio, .decoder = EM28XX_TVP5150, .has_dvb = 1, - .dvb_gpio = default_analog, + .dvb_gpio = default_digital, .input = { { .type = EM28XX_VMUX_TELEVISION, .vmux = TVP5150_COMPOSITE0, diff --git a/linux/drivers/media/video/em28xx/em28xx-dvb.c b/linux/drivers/media/video/em28xx/em28xx-dvb.c index 85afa0be0..86be58641 100644 --- a/linux/drivers/media/video/em28xx/em28xx-dvb.c +++ b/linux/drivers/media/video/em28xx/em28xx-dvb.c @@ -244,6 +244,14 @@ static struct s5h1409_config em28xx_s5h1409_with_xc3028 = { .mpeg_timing = S5H1409_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK }; +static struct zl10353_config em28xx_terratec_xs_zl10353_xc3028 = { + .demod_address = (0x1e >> 1), + .no_tuner = 1, + .disable_i2c_gate_ctrl = 1, + .parallel_ts = 1, + .if2 = 45600, +}; + #ifdef EM28XX_DRX397XD_SUPPORT /* [TODO] djh - not sure yet what the device config needs to contain */ static struct drx397xD_config em28xx_drx397xD_with_xc3028 = { @@ -434,7 +442,6 @@ static int dvb_init(struct em28xx *dev) } break; case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900: - case EM2880_BOARD_TERRATEC_HYBRID_XS: case EM2880_BOARD_KWORLD_DVB_310U: case EM2880_BOARD_EMPIRE_DUAL_TV: dvb->frontend = dvb_attach(zl10353_attach, @@ -445,6 +452,25 @@ static int dvb_init(struct em28xx *dev) goto out_free; } break; + case EM2880_BOARD_TERRATEC_HYBRID_XS: + dvb->frontend = dvb_attach(zl10353_attach, + &em28xx_terratec_xs_zl10353_xc3028, + &dev->i2c_adap); + if (dvb->frontend == NULL) { + /* This board could have either a zl10353 or a mt352. + If the chip id isn't for zl10353, try mt352 */ + + /* FIXME: make support for mt352 work */ + printk(KERN_ERR "version of this board with mt352 not " + "currently supported\n"); + result = -EINVAL; + goto out_free; + } + if (attach_xc3028(0x61, dev) < 0) { + result = -EINVAL; + goto out_free; + } + break; case EM2883_BOARD_KWORLD_HYBRID_330U: case EM2882_BOARD_EVGA_INDTUBE: dvb->frontend = dvb_attach(s5h1409_attach, -- cgit v1.2.3 From 12ca65f34438319e101f46e652524f0229f5bb74 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Wed, 24 Jun 2009 15:31:25 +0200 Subject: soc_camera: Fix debug output of supported formats count From: Stefan Herbrechtsmeier The supported formats count must be set to 0 after debug output right before the second pass. Signed-off-by: Stefan Herbrechtsmeier Signed-off-by: Guennadi Liakhovetski Priority: high --- drivers/media/video/soc_camera.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) --- linux/drivers/media/video/soc_camera.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/soc_camera.c b/linux/drivers/media/video/soc_camera.c index e4056a9c2..711e14109 100644 --- a/linux/drivers/media/video/soc_camera.c +++ b/linux/drivers/media/video/soc_camera.c @@ -238,11 +238,11 @@ static int soc_camera_init_user_formats(struct soc_camera_device *icd) return -ENOMEM; icd->num_user_formats = fmts; - fmts = 0; dev_dbg(&icd->dev, "Found %d supported formats.\n", fmts); /* Second pass - actually fill data formats */ + fmts = 0; for (i = 0; i < icd->num_formats; i++) if (!ici->ops->get_formats) { icd->user_formats[i].host_fmt = icd->formats + i; -- cgit v1.2.3 From 23fc368d1e39ccddfbbf74673e172d7c3e8391aa Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Wed, 24 Jun 2009 15:31:25 +0200 Subject: soc-camera: fix missing clean up on error path From: Guennadi Liakhovetski If soc_camera_init_user_formats() fails in soc_camera_probe(), we have to call client's .remove() method to unregister the video device. Reported-by: Kuninori Morimoto Signed-off-by: Guennadi Liakhovetski Priority: high --- drivers/media/video/soc_camera.c | 10 +++++++--- 1 files changed, 7 insertions(+), 3 deletions(-) --- linux/drivers/media/video/soc_camera.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/soc_camera.c b/linux/drivers/media/video/soc_camera.c index 711e14109..4f315c1b7 100644 --- a/linux/drivers/media/video/soc_camera.c +++ b/linux/drivers/media/video/soc_camera.c @@ -878,8 +878,11 @@ static int soc_camera_probe(struct device *dev) (unsigned short)~0; ret = soc_camera_init_user_formats(icd); - if (ret < 0) + if (ret < 0) { + if (icd->ops->remove) + icd->ops->remove(icd); goto eiufmt; + } icd->height = DEFAULT_HEIGHT; icd->width = DEFAULT_WIDTH; @@ -903,8 +906,10 @@ static int soc_camera_remove(struct device *dev) { struct soc_camera_device *icd = to_soc_camera_dev(dev); + mutex_lock(&icd->video_lock); if (icd->ops->remove) icd->ops->remove(icd); + mutex_unlock(&icd->video_lock); soc_camera_free_user_formats(icd); @@ -1146,6 +1151,7 @@ evidallocd: } EXPORT_SYMBOL(soc_camera_video_start); +/* Called from client .remove() methods with .video_lock held */ void soc_camera_video_stop(struct soc_camera_device *icd) { struct video_device *vdev = icd->vdev; @@ -1155,10 +1161,8 @@ void soc_camera_video_stop(struct soc_camera_device *icd) if (!icd->dev.parent || !vdev) return; - mutex_lock(&icd->video_lock); video_unregister_device(vdev); icd->vdev = NULL; - mutex_unlock(&icd->video_lock); } EXPORT_SYMBOL(soc_camera_video_stop); -- cgit v1.2.3 From bb4a3773913e20573cc6c6c22db484453612ffe6 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 25 Jun 2009 16:28:23 -0300 Subject: vivi: bug: don't assume that S_STD will be called before streaming From: Mauro Carvalho Chehab precalculate_bars() improved vivi performance. However, it assumed that always before streaming, the driver would call VIDIOC_S_STD. This is not an API requirement, and the testing apps don't do that. Due to that, a regression were caused by the patch that added it. This patch moves the precalculate_bars to the proper place of the code, calling it at buffer_prepare() callback. Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/vivi.c | 99 ++++++++++++++++++++-------------------- 1 file changed, 50 insertions(+), 49 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/vivi.c b/linux/drivers/media/video/vivi.c index fe39b7326..afd8e2a5a 100644 --- a/linux/drivers/media/video/vivi.c +++ b/linux/drivers/media/video/vivi.c @@ -346,6 +346,53 @@ static struct bar_std bars[] = { #define TO_U(r, g, b) \ (((-9714 * r - 19070 * g + 28784 * b + 32768) >> 16) + 128) +/* precalculate color bar values to speed up rendering */ +static void precalculate_bars(struct vivi_fh *fh) +{ + struct vivi_dev *dev = fh->dev; + unsigned char r, g, b; + int k, is_yuv; + + fh->input = dev->input; + + for (k = 0; k < 8; k++) { + r = bars[fh->input].bar[k][0]; + g = bars[fh->input].bar[k][1]; + b = bars[fh->input].bar[k][2]; + is_yuv = 0; + + switch (fh->fmt->fourcc) { + case V4L2_PIX_FMT_YUYV: + case V4L2_PIX_FMT_UYVY: + is_yuv = 1; + break; + case V4L2_PIX_FMT_RGB565: + case V4L2_PIX_FMT_RGB565X: + r >>= 3; + g >>= 2; + b >>= 3; + break; + case V4L2_PIX_FMT_RGB555: + case V4L2_PIX_FMT_RGB555X: + r >>= 3; + g >>= 3; + b >>= 3; + break; + } + + if (is_yuv) { + fh->bars[k][0] = TO_Y(r, g, b); /* Luma */ + fh->bars[k][1] = TO_U(r, g, b); /* Cb */ + fh->bars[k][2] = TO_V(r, g, b); /* Cr */ + } else { + fh->bars[k][0] = r; + fh->bars[k][1] = g; + fh->bars[k][2] = b; + } + } + +} + #define TSTAMP_MIN_Y 24 #define TSTAMP_MAX_Y (TSTAMP_MIN_Y + 15) #define TSTAMP_INPUT_X 10 @@ -758,6 +805,8 @@ buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb, buf->vb.height = fh->height; buf->vb.field = field; + precalculate_bars(fh); + if (VIDEOBUF_NEEDS_INIT == buf->vb.state) { rc = videobuf_iolock(vq, &buf->vb, NULL); if (rc < 0) @@ -896,53 +945,6 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, return 0; } -/* precalculate color bar values to speed up rendering */ -static void precalculate_bars(struct vivi_fh *fh) -{ - struct vivi_dev *dev = fh->dev; - unsigned char r, g, b; - int k, is_yuv; - - fh->input = dev->input; - - for (k = 0; k < 8; k++) { - r = bars[fh->input].bar[k][0]; - g = bars[fh->input].bar[k][1]; - b = bars[fh->input].bar[k][2]; - is_yuv = 0; - - switch (fh->fmt->fourcc) { - case V4L2_PIX_FMT_YUYV: - case V4L2_PIX_FMT_UYVY: - is_yuv = 1; - break; - case V4L2_PIX_FMT_RGB565: - case V4L2_PIX_FMT_RGB565X: - r >>= 3; - g >>= 2; - b >>= 3; - break; - case V4L2_PIX_FMT_RGB555: - case V4L2_PIX_FMT_RGB555X: - r >>= 3; - g >>= 3; - b >>= 3; - break; - } - - if (is_yuv) { - fh->bars[k][0] = TO_Y(r, g, b); /* Luma */ - fh->bars[k][1] = TO_U(r, g, b); /* Cb */ - fh->bars[k][2] = TO_V(r, g, b); /* Cr */ - } else { - fh->bars[k][0] = r; - fh->bars[k][1] = g; - fh->bars[k][2] = b; - } - } - -} - /*FIXME: This seems to be generic enough to be at videodev2 */ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) @@ -968,8 +970,6 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, fh->vb_vidq.field = f->fmt.pix.field; fh->type = f->type; - precalculate_bars(fh); - ret = 0; out: mutex_unlock(&q->vb_lock); @@ -1360,6 +1360,7 @@ static int __init vivi_create_instance(int inst) goto unreg_dev; *vfd = vivi_template; + vfd->debug = debug; ret = video_register_device(vfd, VFL_TYPE_GRABBER, video_nr); if (ret < 0) -- cgit v1.2.3 From f3e605bcc7d54a437e0d179042c0ce2890eee348 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 26 Jun 2009 20:35:04 +0200 Subject: ttpci: config TTPCI_EEPROM depends on I2C From: Hans Verkuil If I2C is not enabled, then we shouldn't build ttpci_eeprom.c. Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/dvb/ttpci/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/ttpci/Kconfig b/linux/drivers/media/dvb/ttpci/Kconfig index 68eb4493f..d8d4214fd 100644 --- a/linux/drivers/media/dvb/ttpci/Kconfig +++ b/linux/drivers/media/dvb/ttpci/Kconfig @@ -1,5 +1,6 @@ config TTPCI_EEPROM tristate + depends on I2C default n config DVB_AV7110 -- cgit v1.2.3 From cec46d3ee957c58f44aa2d013e22cca96b7ea6ee Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 29 Jun 2009 05:41:26 -0300 Subject: Add a driver for mt9v011 sensor From: Mauro Carvalho Chehab Adds driver for mt9v011 based on its datasheet, available at: http://download.micron.com/pdf/datasheets/imaging/MT9V011.pdf The driver was tested with a webcam that will be added on a next patch. Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/Kconfig | 8 + linux/drivers/media/video/Makefile | 1 + linux/drivers/media/video/mt9v011.c | 371 ++++++++++++++++++++++++++++++++++++ linux/drivers/media/video/mt9v011.h | 35 ++++ 4 files changed, 415 insertions(+) create mode 100644 linux/drivers/media/video/mt9v011.c create mode 100644 linux/drivers/media/video/mt9v011.h (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/Kconfig b/linux/drivers/media/video/Kconfig index 061e147f6..84b6fc155 100644 --- a/linux/drivers/media/video/Kconfig +++ b/linux/drivers/media/video/Kconfig @@ -312,6 +312,14 @@ config VIDEO_OV7670 OV7670 VGA camera. It currently only works with the M88ALP01 controller. +config VIDEO_MT9V011 + tristate "Micron mt9v011 sensor support" + depends on I2C && VIDEO_V4L2 + ---help--- + This is a Video4Linux2 sensor-level driver for the Micron + mt0v011 1.3 Mpixel camera. It currently only works with the + em28xx driver. + config VIDEO_TCM825X tristate "TCM825x camera sensor support" depends on I2C && VIDEO_V4L2 diff --git a/linux/drivers/media/video/Makefile b/linux/drivers/media/video/Makefile index 7fb3add1b..9f2e3214a 100644 --- a/linux/drivers/media/video/Makefile +++ b/linux/drivers/media/video/Makefile @@ -69,6 +69,7 @@ obj-$(CONFIG_VIDEO_UPD64083) += upd64083.o obj-$(CONFIG_VIDEO_OV7670) += ov7670.o obj-$(CONFIG_VIDEO_TCM825X) += tcm825x.o obj-$(CONFIG_VIDEO_TVEEPROM) += tveeprom.o +obj-$(CONFIG_VIDEO_MT9V011) += mt9v011.o obj-$(CONFIG_SOC_CAMERA_MT9M001) += mt9m001.o obj-$(CONFIG_SOC_CAMERA_MT9M111) += mt9m111.o diff --git a/linux/drivers/media/video/mt9v011.c b/linux/drivers/media/video/mt9v011.c new file mode 100644 index 000000000..a4fdbed20 --- /dev/null +++ b/linux/drivers/media/video/mt9v011.c @@ -0,0 +1,371 @@ +/* + * mt9v011 -Micron 1/4-Inch VGA Digital Image Sensor + * + * Copyright (c) 2009 Mauro Carvalho Chehab (mchehab@redhat.com) + * This code is placed under the terms of the GNU General Public License v2 + */ + +#include +#include "compat.h" +#include +#include +#include +#include "mt9v011.h" +#include +#include + +MODULE_DESCRIPTION("Micron mt9v011 sensor driver"); +MODULE_AUTHOR("Mauro Carvalho Chehab "); +MODULE_LICENSE("GPL"); + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26) +/* standard i2c insmod options */ +static unsigned short normal_i2c[] = { + 0xba >> 1, + I2C_CLIENT_END +}; + +I2C_CLIENT_INSMOD; +#endif + +static int debug; +module_param(debug, int, 0); +MODULE_PARM_DESC(debug, "Debug level (0-2)"); + +/* supported controls */ +static struct v4l2_queryctrl mt9v011_qctrl[] = { + { + .id = V4L2_CID_GAIN, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Gain", + .minimum = 0, + .maximum = (1 << 10) - 1, + .step = 1, + .default_value = 0x0020, + .flags = 0, + }, { + .id = V4L2_CID_RED_BALANCE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Red Balance", + .minimum = -1 << 9, + .maximum = (1 << 9) - 1, + .step = 1, + .default_value = 0, + .flags = 0, + }, { + .id = V4L2_CID_BLUE_BALANCE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Blue Balance", + .minimum = -1 << 9, + .maximum = (1 << 9) - 1, + .step = 1, + .default_value = 0, + .flags = 0, + }, +}; + +struct mt9v011 { + struct v4l2_subdev sd; + + u16 global_gain, red_bal, blue_bal; +}; + +static inline struct mt9v011 *to_mt9v011(struct v4l2_subdev *sd) +{ + return container_of(sd, struct mt9v011, sd); +} + +static int mt9v011_read(struct v4l2_subdev *sd, unsigned char addr) +{ + struct i2c_client *c = v4l2_get_subdevdata(sd); + __be16 buffer; + int rc, val; + + if (1 != (rc = i2c_master_send(c, &addr, 1))) + v4l2_dbg(0, debug, sd, + "i2c i/o error: rc == %d (should be 1)\n", rc); + + msleep(10); + + if (2 != (rc = i2c_master_recv(c, (char *)&buffer, 2))) + v4l2_dbg(0, debug, sd, + "i2c i/o error: rc == %d (should be 1)\n", rc); + + val = be16_to_cpu(buffer); + + v4l2_dbg(2, debug, sd, "mt9v011: read 0x%02x = 0x%04x\n", addr, val); + + return val; +} + +static void mt9v011_write(struct v4l2_subdev *sd, unsigned char addr, + u16 value) +{ + struct i2c_client *c = v4l2_get_subdevdata(sd); + unsigned char buffer[3]; + int rc; + + buffer[0] = addr; + buffer[1] = value >> 8; + buffer[2] = value & 0xff; + + v4l2_dbg(2, debug, sd, + "mt9v011: writing 0x%02x 0x%04x\n", buffer[0], value); + if (3 != (rc = i2c_master_send(c, buffer, 3))) + v4l2_dbg(0, debug, sd, + "i2c i/o error: rc == %d (should be 3)\n", rc); +} + + +struct i2c_reg_value { + unsigned char reg; + u16 value; +}; + +/* + * Values used at the original driver + * Some values are marked as Reserved at the datasheet + */ +static const struct i2c_reg_value mt9v011_init_default[] = { + /* guessed meaning - as mt9m111 */ + { R0D_MT9V011_RESET, 0x0001 }, + { R0D_MT9V011_RESET, 0x0000 }, + { R01_MT9V011_ROWSTART, 0x0008 }, + { R02_MT9V011_COLSTART, 0x0014 }, + { R03_MT9V011_HEIGHT, 0x01e0 }, + { R04_MT9V011_WIDTH, 0x0280 }, + { R05_MT9V011_HBLANK, 0x0001 }, + { R05_MT9V011_HBLANK, 0x0001 }, + { R0A_MT9V011_CLK_SPEED, 0x0000 }, + { R05_MT9V011_HBLANK, 0x000a }, + { 0x30, 0x0005 }, + { 0x34, 0x0100 }, + { 0x3d, 0x068f }, + { 0x40, 0x01e0 }, + { 0x52, 0x0100 }, + { 0x58, 0x0038 }, /* Datasheet default 0x0078 */ + { 0x59, 0x0723 }, /* Datasheet default 0x0703 */ + { 0x62, 0x041a }, /* Datasheet default 0x0418 */ + { R09_MT9V011_SHUTTER_WIDTH, 0x0418 }, + { R20_MT9V011_READ_MODE, 0x1100 }, +}; + +static void set_balance(struct v4l2_subdev *sd) +{ + struct mt9v011 *core = to_mt9v011(sd); + u16 green1_gain, green2_gain, blue_gain, red_gain; + + green1_gain = core->global_gain; + green2_gain = core->global_gain; + + blue_gain = core->global_gain + + core->global_gain * core->blue_bal / (1 << 9); + + red_gain = core->global_gain + + core->global_gain * core->blue_bal / (1 << 9); + + mt9v011_write(sd, R2B_MT9V011_GREEN_1_GAIN, green1_gain); + mt9v011_write(sd, R2E_MT9V011_GREEN_2_GAIN, green1_gain); + mt9v011_write(sd, R2C_MT9V011_BLUE_GAIN, blue_gain); + mt9v011_write(sd, R2D_MT9V011_RED_GAIN, red_gain); +} + +static int mt9v011_reset(struct v4l2_subdev *sd, u32 val) +{ + u16 version; + int i; + + version = mt9v011_read(sd, R00_MT9V011_CHIP_VERSION); + + if (version != MT9V011_VERSION) { + v4l2_info(sd, "*** unknown micron chip detected (0x%04x.\n", + version); + return -EINVAL; + + } + + for (i = 0; i < ARRAY_SIZE(mt9v011_init_default); i++) + mt9v011_write(sd, mt9v011_init_default[i].reg, + mt9v011_init_default[i].value); + + set_balance(sd); + + return 0; +}; + +static int mt9v011_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) +{ + struct mt9v011 *core = to_mt9v011(sd); + + v4l2_dbg(1, debug, sd, "g_ctrl called\n"); + + switch (ctrl->id) { + case V4L2_CID_GAIN: + ctrl->value = core->global_gain; + return 0; + case V4L2_CID_RED_BALANCE: + ctrl->value = core->red_bal; + return 0; + case V4L2_CID_BLUE_BALANCE: + ctrl->value = core->blue_bal; + return 0; + } + return -EINVAL; +} + +static int mt9v011_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) +{ + struct mt9v011 *core = to_mt9v011(sd); + u8 i, n; + n = ARRAY_SIZE(mt9v011_qctrl); + + for (i = 0; i < n; i++) { + if (ctrl->id != mt9v011_qctrl[i].id) + continue; + if (ctrl->value < mt9v011_qctrl[i].minimum || + ctrl->value > mt9v011_qctrl[i].maximum) + return -ERANGE; + v4l2_dbg(1, debug, sd, "s_ctrl: id=%d, value=%d\n", + ctrl->id, ctrl->value); + break; + } + + switch (ctrl->id) { + case V4L2_CID_GAIN: + core->global_gain = ctrl->value; + break; + case V4L2_CID_RED_BALANCE: + core->red_bal = ctrl->value; + break; + case V4L2_CID_BLUE_BALANCE: + core->blue_bal = ctrl->value; + break; + default: + return -EINVAL; + } + + set_balance(sd); + + return 0; +} + +#ifdef CONFIG_VIDEO_ADV_DEBUG +static int mt9v011_g_register(struct v4l2_subdev *sd, + struct v4l2_dbg_register *reg) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + + if (!v4l2_chip_match_i2c_client(client, ®->match)) + return -EINVAL; + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + + reg->val = mt9v011_read(sd, reg->reg & 0xff); + reg->size = 2; + + return 0; +} + +static int mt9v011_s_register(struct v4l2_subdev *sd, + struct v4l2_dbg_register *reg) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + + if (!v4l2_chip_match_i2c_client(client, ®->match)) + return -EINVAL; + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + + mt9v011_write(sd, reg->reg & 0xff, reg->val & 0xffff); + + return 0; +} +#endif + +static int mt9v011_g_chip_ident(struct v4l2_subdev *sd, + struct v4l2_dbg_chip_ident *chip) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + + return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_MT9V011, + MT9V011_VERSION); +} + +static const struct v4l2_subdev_core_ops mt9v011_core_ops = { + .g_ctrl = mt9v011_g_ctrl, + .s_ctrl = mt9v011_s_ctrl, + .reset = mt9v011_reset, + .g_chip_ident = mt9v011_g_chip_ident, +#ifdef CONFIG_VIDEO_ADV_DEBUG + .g_register = mt9v011_g_register, + .s_register = mt9v011_s_register, +#endif +}; + +static const struct v4l2_subdev_ops mt9v011_ops = { + .core = &mt9v011_core_ops, +}; + + +/**************************************************************************** + I2C Client & Driver + ****************************************************************************/ + +static int mt9v011_probe(struct i2c_client *c, + const struct i2c_device_id *id) +{ + struct mt9v011 *core; + struct v4l2_subdev *sd; + + /* Check if the adapter supports the needed features */ + if (!i2c_check_functionality(c->adapter, + I2C_FUNC_SMBUS_READ_BYTE | I2C_FUNC_SMBUS_WRITE_BYTE_DATA)) + return -EIO; + + core = kzalloc(sizeof(struct mt9v011), GFP_KERNEL); + if (!core) + return -ENOMEM; + + core->global_gain = 0x0024; + + sd = &core->sd; + v4l2_i2c_subdev_init(sd, c, &mt9v011_ops); + v4l_info(c, "chip found @ 0x%02x (%s)\n", + c->addr << 1, c->adapter->name); + + return 0; +} + +static int mt9v011_remove(struct i2c_client *c) +{ + struct v4l2_subdev *sd = i2c_get_clientdata(c); + + v4l2_dbg(1, debug, sd, + "mt9v011.c: removing mt9v011 adapter on address 0x%x\n", + c->addr << 1); + + v4l2_device_unregister_subdev(sd); + kfree(to_mt9v011(sd)); + return 0; +} + +/* ----------------------------------------------------------------------- */ + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) +static const struct i2c_device_id mt9v011_id[] = { + { "mt9v011", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, mt9v011_id); + +#endif +static struct v4l2_i2c_driver_data v4l2_i2c_data = { + .name = "mt9v011", + .probe = mt9v011_probe, + .remove = mt9v011_remove, +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26) + .legacy_class = I2C_CLASS_TV_ANALOG | I2C_CLASS_TV_DIGITAL, +#else + .id_table = mt9v011_id, +#endif +}; diff --git a/linux/drivers/media/video/mt9v011.h b/linux/drivers/media/video/mt9v011.h new file mode 100644 index 000000000..9e443ee30 --- /dev/null +++ b/linux/drivers/media/video/mt9v011.h @@ -0,0 +1,35 @@ +/* + * mt9v011 -Micron 1/4-Inch VGA Digital Image Sensor + * + * Copyright (c) 2009 Mauro Carvalho Chehab (mchehab@redhat.com) + * This code is placed under the terms of the GNU General Public License v2 + */ + +#ifndef MT9V011_H_ +#define MT9V011_H_ + +#define R00_MT9V011_CHIP_VERSION 0x00 +#define R01_MT9V011_ROWSTART 0x01 +#define R02_MT9V011_COLSTART 0x02 +#define R03_MT9V011_HEIGHT 0x03 +#define R04_MT9V011_WIDTH 0x04 +#define R05_MT9V011_HBLANK 0x05 +#define R06_MT9V011_VBLANK 0x06 +#define R07_MT9V011_OUT_CTRL 0x07 +#define R09_MT9V011_SHUTTER_WIDTH 0x09 +#define R0A_MT9V011_CLK_SPEED 0x0a +#define R0B_MT9V011_RESTART 0x0b +#define R0C_MT9V011_SHUTTER_DELAY 0x0c +#define R0D_MT9V011_RESET 0x0d +#define R1E_MT9V011_DIGITAL_ZOOM 0x1e +#define R20_MT9V011_READ_MODE 0x20 +#define R2B_MT9V011_GREEN_1_GAIN 0x2b +#define R2C_MT9V011_BLUE_GAIN 0x2c +#define R2D_MT9V011_RED_GAIN 0x2d +#define R2E_MT9V011_GREEN_2_GAIN 0x2e +#define R35_MT9V011_GLOBAL_GAIN 0x35 +#define RF1_MT9V011_CHIP_ENABLE 0xf1 + +#define MT9V011_VERSION 0x8243 + +#endif -- cgit v1.2.3 From b971cb7ebd14c02cdd2768cb81e96530eca6f5c6 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 29 Jun 2009 11:03:22 -0300 Subject: mt9v011: Some fixes at the register initialization table From: Mauro Carvalho Chehab Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/mt9v011.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/mt9v011.c b/linux/drivers/media/video/mt9v011.c index a4fdbed20..ce64cd728 100644 --- a/linux/drivers/media/video/mt9v011.c +++ b/linux/drivers/media/video/mt9v011.c @@ -127,17 +127,25 @@ struct i2c_reg_value { * Some values are marked as Reserved at the datasheet */ static const struct i2c_reg_value mt9v011_init_default[] = { - /* guessed meaning - as mt9m111 */ { R0D_MT9V011_RESET, 0x0001 }, { R0D_MT9V011_RESET, 0x0000 }, + { R01_MT9V011_ROWSTART, 0x0008 }, { R02_MT9V011_COLSTART, 0x0014 }, { R03_MT9V011_HEIGHT, 0x01e0 }, { R04_MT9V011_WIDTH, 0x0280 }, - { R05_MT9V011_HBLANK, 0x0001 }, - { R05_MT9V011_HBLANK, 0x0001 }, + { R05_MT9V011_HBLANK, 0x007b }, + { R06_MT9V011_VBLANK, 0x001c }, + { R09_MT9V011_SHUTTER_WIDTH, 0x0418 }, { R0A_MT9V011_CLK_SPEED, 0x0000 }, - { R05_MT9V011_HBLANK, 0x000a }, + { R0C_MT9V011_SHUTTER_DELAY, 0x0000 }, + { R1E_MT9V011_DIGITAL_ZOOM, 0x0000 }, + { R20_MT9V011_READ_MODE, 0x1100 }, + + /* + * Those registers are not docummented at the datasheet. + * However, the original driver initializes them + */ { 0x30, 0x0005 }, { 0x34, 0x0100 }, { 0x3d, 0x068f }, @@ -146,8 +154,8 @@ static const struct i2c_reg_value mt9v011_init_default[] = { { 0x58, 0x0038 }, /* Datasheet default 0x0078 */ { 0x59, 0x0723 }, /* Datasheet default 0x0703 */ { 0x62, 0x041a }, /* Datasheet default 0x0418 */ - { R09_MT9V011_SHUTTER_WIDTH, 0x0418 }, - { R20_MT9V011_READ_MODE, 0x1100 }, + + { R07_MT9V011_OUT_CTRL, 0x000a }, /* chip enable */ }; static void set_balance(struct v4l2_subdev *sd) -- cgit v1.2.3 From a1f731e499ffb5e010c3b1d9b28cbfccc5db0028 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 29 Jun 2009 11:12:05 -0300 Subject: mt9v011: CodingStyle fixes From: Mauro Carvalho Chehab Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/mt9v011.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/mt9v011.c b/linux/drivers/media/video/mt9v011.c index ce64cd728..d3f2b4dc5 100644 --- a/linux/drivers/media/video/mt9v011.c +++ b/linux/drivers/media/video/mt9v011.c @@ -81,15 +81,17 @@ static int mt9v011_read(struct v4l2_subdev *sd, unsigned char addr) __be16 buffer; int rc, val; - if (1 != (rc = i2c_master_send(c, &addr, 1))) + rc = i2c_master_send(c, &addr, 1); + if (rc != 1) v4l2_dbg(0, debug, sd, "i2c i/o error: rc == %d (should be 1)\n", rc); msleep(10); - if (2 != (rc = i2c_master_recv(c, (char *)&buffer, 2))) + rc = i2c_master_recv(c, (char *)&buffer, 2); + if (rc != 2) v4l2_dbg(0, debug, sd, - "i2c i/o error: rc == %d (should be 1)\n", rc); + "i2c i/o error: rc == %d (should be 2)\n", rc); val = be16_to_cpu(buffer); @@ -111,7 +113,8 @@ static void mt9v011_write(struct v4l2_subdev *sd, unsigned char addr, v4l2_dbg(2, debug, sd, "mt9v011: writing 0x%02x 0x%04x\n", buffer[0], value); - if (3 != (rc = i2c_master_send(c, buffer, 3))) + rc = i2c_master_send(c, &buffer, 3); + if (rc != 3) v4l2_dbg(0, debug, sd, "i2c i/o error: rc == %d (should be 3)\n", rc); } -- cgit v1.2.3 From 3ba1d8073b90814e553b5a1ca1cd7a7b065c2cd4 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 29 Jun 2009 11:35:05 -0300 Subject: em28xx: add support for Silvercrest Webcam From: Mauro Carvalho Chehab This webcam uses a em2710 chipset, that identifies itself as em2820, plus a mt9v011 sensor, and a DY-301P lens. It needs a few different initializations than a normal em28xx device. Thanks to Hans de Goede and Douglas Landgraf for providing the acces for the webcam during this weekend, I could make a patch for it while returning back from FISL/Fudcom LATAM 2009. Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/em28xx/Kconfig | 2 ++ linux/drivers/media/video/em28xx/em28xx-cards.c | 37 ++++++++++++++++++++++++- linux/drivers/media/video/em28xx/em28xx-core.c | 33 ++++++++++++++++++---- linux/drivers/media/video/em28xx/em28xx.h | 3 ++ 4 files changed, 68 insertions(+), 7 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/em28xx/Kconfig b/linux/drivers/media/video/em28xx/Kconfig index 16a5af30e..6524b493e 100644 --- a/linux/drivers/media/video/em28xx/Kconfig +++ b/linux/drivers/media/video/em28xx/Kconfig @@ -8,6 +8,8 @@ config VIDEO_EM28XX select VIDEO_SAA711X if VIDEO_HELPER_CHIPS_AUTO select VIDEO_TVP5150 if VIDEO_HELPER_CHIPS_AUTO select VIDEO_MSP3400 if VIDEO_HELPER_CHIPS_AUTO + select VIDEO_MT9V011 if VIDEO_HELPER_CHIPS_AUTO + ---help--- This is a video4linux driver for Empia 28xx based TV cards. diff --git a/linux/drivers/media/video/em28xx/em28xx-cards.c b/linux/drivers/media/video/em28xx/em28xx-cards.c index b824eed46..e78424f3a 100644 --- a/linux/drivers/media/video/em28xx/em28xx-cards.c +++ b/linux/drivers/media/video/em28xx/em28xx-cards.c @@ -204,6 +204,13 @@ static struct em28xx_reg_seq terratec_av350_unmute_gpio[] = { {EM28XX_R08_GPIO, 0xff, 0xff, 10}, { -1, -1, -1, -1}, }; + +static struct em28xx_reg_seq silvercrest_reg_seq[] = { + {EM28XX_R08_GPIO, 0xff, 0xff, 10}, + {EM28XX_R08_GPIO, 0x01, 0xf7, 10}, + { -1, -1, -1, -1}, +}; + /* * Board definitions */ @@ -451,6 +458,18 @@ struct em28xx_board em28xx_boards[] = { .amux = EM28XX_AMUX_VIDEO, } }, }, + [EM2820_BOARD_SILVERCREST_WEBCAM] = { + .name = "Silvercrest Webcam 1.3mpix", + .tuner_type = TUNER_ABSENT, + .is_27xx = 1, + .decoder = EM28XX_MT9V011, + .input = { { + .type = EM28XX_VMUX_COMPOSITE1, + .vmux = 0, + .amux = EM28XX_AMUX_VIDEO, + .gpio = silvercrest_reg_seq, + } }, + }, [EM2821_BOARD_SUPERCOMP_USB_2] = { .name = "Supercomp USB 2.0 TV", .valid = EM28XX_BOARD_NOT_VALIDATED, @@ -1708,6 +1727,11 @@ static unsigned short tvp5150_addrs[] = { I2C_CLIENT_END }; +static unsigned short mt9v011_addrs[] = { + 0xba >> 1, + I2C_CLIENT_END +}; + static unsigned short msp3400_addrs[] = { 0x80 >> 1, 0x88 >> 1, @@ -1775,7 +1799,10 @@ void em28xx_pre_card_setup(struct em28xx *dev) em28xx_info("chip ID is em2750\n"); break; case CHIP_ID_EM2820: - em28xx_info("chip ID is em2820\n"); + if (dev->board.is_27xx) + em28xx_info("chip is em2710\n"); + else + em28xx_info("chip ID is em2820\n"); break; case CHIP_ID_EM2840: em28xx_info("chip ID is em2840\n"); @@ -2261,6 +2288,10 @@ void em28xx_card_setup(struct em28xx *dev) before probing the i2c bus. */ em28xx_set_mode(dev, EM28XX_ANALOG_MODE); break; + case EM2820_BOARD_SILVERCREST_WEBCAM: + /* FIXME: need to document the registers bellow */ + em28xx_write_reg(dev, 0x0d, 0x42); + em28xx_write_reg(dev, 0x13, 0x08); } if (dev->board.has_snapshot_button) @@ -2292,6 +2323,10 @@ void em28xx_card_setup(struct em28xx *dev) v4l2_i2c_new_probed_subdev(&dev->v4l2_dev, &dev->i2c_adap, "tvp5150", "tvp5150", tvp5150_addrs); + if (dev->board.decoder == EM28XX_MT9V011) + v4l2_i2c_new_probed_subdev(&dev->v4l2_dev, &dev->i2c_adap, + "mt9v011", "mt9v011", mt9v011_addrs); + if (dev->board.adecoder == EM28XX_TVAUDIO) v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap, "tvaudio", "tvaudio", dev->board.tvaudio_addr); diff --git a/linux/drivers/media/video/em28xx/em28xx-core.c b/linux/drivers/media/video/em28xx/em28xx-core.c index 2bce72e4f..7ad8edff2 100644 --- a/linux/drivers/media/video/em28xx/em28xx-core.c +++ b/linux/drivers/media/video/em28xx/em28xx-core.c @@ -648,17 +648,29 @@ int em28xx_capture_start(struct em28xx *dev, int start) int em28xx_set_outfmt(struct em28xx *dev) { int ret; + int vinmode, vinctl, outfmt; + + outfmt = dev->format->reg; + + if (dev->board.is_27xx) { + vinmode = 0x0d; + vinctl = 0x00; + outfmt = 0x24; + } else { + vinmode = 0x10; + vinctl = 0x11; + } ret = em28xx_write_reg_bits(dev, EM28XX_R27_OUTFMT, - dev->format->reg | 0x20, 0x3f); + outfmt | 0x20, 0xff); if (ret < 0) - return ret; + return ret; - ret = em28xx_write_reg(dev, EM28XX_R10_VINMODE, 0x10); + ret = em28xx_write_reg(dev, EM28XX_R10_VINMODE, vinmode); if (ret < 0) return ret; - return em28xx_write_reg(dev, EM28XX_R11_VINCTRL, 0x11); + return em28xx_write_reg(dev, EM28XX_R11_VINCTRL, vinctl); } static int em28xx_accumulator_set(struct em28xx *dev, u8 xmin, u8 xmax, @@ -695,13 +707,19 @@ static int em28xx_scaler_set(struct em28xx *dev, u16 h, u16 v) { u8 mode; /* the em2800 scaler only supports scaling down to 50% */ - if (dev->board.is_em2800) + + if (dev->board.is_27xx) { + /* FIXME: Don't use the scaler yet */ + mode = 0; + } else if (dev->board.is_em2800) { mode = (v ? 0x20 : 0x00) | (h ? 0x10 : 0x00); - else { + } else { u8 buf[2]; + buf[0] = h; buf[1] = h >> 8; em28xx_write_regs(dev, EM28XX_R30_HSCALELOW, (char *)buf, 2); + buf[0] = v; buf[1] = v >> 8; em28xx_write_regs(dev, EM28XX_R32_VSCALELOW, (char *)buf, 2); @@ -720,8 +738,11 @@ int em28xx_resolution_set(struct em28xx *dev) height = norm_maxh(dev) >> 1; em28xx_set_outfmt(dev); + + em28xx_accumulator_set(dev, 1, (width - 4) >> 2, 1, (height - 4) >> 2); em28xx_capture_area_set(dev, 0, 0, width >> 2, height >> 2); + return em28xx_scaler_set(dev, dev->hscale, dev->vscale); } diff --git a/linux/drivers/media/video/em28xx/em28xx.h b/linux/drivers/media/video/em28xx/em28xx.h index 6fb890efa..2eedfef53 100644 --- a/linux/drivers/media/video/em28xx/em28xx.h +++ b/linux/drivers/media/video/em28xx/em28xx.h @@ -108,6 +108,7 @@ #define EM2860_BOARD_TERRATEC_AV350 68 #define EM2882_BOARD_KWORLD_ATSC_315U 69 #define EM2882_BOARD_EVGA_INDTUBE 70 +#define EM2820_BOARD_SILVERCREST_WEBCAM 71 /* Limits minimum and default number of buffers */ #define EM28XX_MIN_BUF 4 @@ -361,6 +362,7 @@ enum em28xx_decoder { EM28XX_NODECODER, EM28XX_TVP5150, EM28XX_SAA711X, + EM28XX_MT9V011, }; enum em28xx_adecoder { @@ -389,6 +391,7 @@ struct em28xx_board { unsigned int max_range_640_480:1; unsigned int has_dvb:1; unsigned int has_snapshot_button:1; + unsigned int is_27xx:1; unsigned int valid:1; unsigned char xclk, i2c_speed; -- cgit v1.2.3 From 331ffeac0127bface1146240b2b494272452d6bc Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 30 Jun 2009 08:36:17 -0300 Subject: em28xx: add other video formats From: Mauro Carvalho Chehab Add suppport for the teste RGB565 format (16 bits/pixel). Currently, webcam support works only at RGB565, at 640x480. Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/em28xx/em28xx-video.c | 58 ++++++++++++++++++++++++- 1 file changed, 57 insertions(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/em28xx/em28xx-video.c b/linux/drivers/media/video/em28xx/em28xx-video.c index 63d21698c..b4dde89e9 100644 --- a/linux/drivers/media/video/em28xx/em28xx-video.c +++ b/linux/drivers/media/video/em28xx/em28xx-video.c @@ -94,6 +94,49 @@ static struct em28xx_fmt format[] = { .fourcc = V4L2_PIX_FMT_YUYV, .depth = 16, .reg = EM28XX_OUTFMT_YUV422_Y0UY1V, + }, { + .name = "16 bpp RGB, le", + .fourcc = V4L2_PIX_FMT_RGB565, + .depth = 16, + .reg = EM28XX_OUTFMT_YUV211, +#if 0 + /* TODO: need tests and newer definitions */ + }, { + .name = "Y1-U-Y0-V, 16 bpp", + .fourcc = 0, + .depth = 16, + .reg = EM28XX_OUTFMT_YUV422_Y1UY0V + }, { + .name = "YUV211, 8 bpp", + .fourcc = 0, + .depth = 8, + .reg = EM28XX_OUTFMT_YUV211, + }, { + .name = "YUV411, 12 bpp", + .fourcc = 0, + .depth = 12, + .reg = EM28XX_OUTFMT_YUV411, + }, { + .name = "RGB, 8bit RGRG", + .fourcc = 0, + .depth = 8, + .reg = EM28XX_OUTFMT_YUV211, + }, { + .name = "RGB, 8bit GRGR", + .fourcc = 0, + .depth = 8, + .reg = EM28XX_OUTFMT_YUV211, + }, { + .name = "RGB, 8bit GBGB", + .fourcc = 0, + .depth = 8, + .reg = EM28XX_OUTFMT_YUV211, + }, { + .name = "RGB, 8bit BGBG", + .fourcc = 0, + .depth = 8, + .reg = EM28XX_OUTFMT_RGB_8_BGBG, +#endif }, }; @@ -698,6 +741,10 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, unsigned int hscale, vscale; struct em28xx_fmt *fmt; + /* FIXME: This is the only supported fmt */ + if (dev->board.is_27xx) + f->fmt.pix.pixelformat = V4L2_PIX_FMT_RGB565; + fmt = format_by_fourcc(f->fmt.pix.pixelformat); if (!fmt) { em28xx_videodbg("Fourcc format (%08x) invalid.\n", @@ -705,7 +752,12 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, return -EINVAL; } - if (dev->board.is_em2800) { + if (dev->board.is_27xx) { + /* FIXME: This is the only supported fmt */ + width = 640; + height = 480; + V4L2_PIX_FMT_RGB565; + } else if (dev->board.is_em2800) { /* the em2800 can only scale down to 50% */ height = height > (3 * maxh / 4) ? maxh : maxh / 2; width = width > (3 * maxw / 4) ? maxw : maxw / 2; @@ -751,6 +803,10 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, mutex_lock(&dev->lock); + /* FIXME: This is the only supported fmt */ + if (dev->board.is_27xx) + f->fmt.pix.pixelformat = V4L2_PIX_FMT_RGB565; + vidioc_try_fmt_vid_cap(file, priv, f); fmt = format_by_fourcc(f->fmt.pix.pixelformat); -- cgit v1.2.3 From edefe5abbee82017b6f74ca42a1606f273da719d Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 30 Jun 2009 12:45:16 -0300 Subject: Remove a bogus code From: Mauro Carvalho Chehab Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/em28xx/em28xx-video.c | 1 - 1 file changed, 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/em28xx/em28xx-video.c b/linux/drivers/media/video/em28xx/em28xx-video.c index b4dde89e9..3c47acee3 100644 --- a/linux/drivers/media/video/em28xx/em28xx-video.c +++ b/linux/drivers/media/video/em28xx/em28xx-video.c @@ -756,7 +756,6 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, /* FIXME: This is the only supported fmt */ width = 640; height = 480; - V4L2_PIX_FMT_RGB565; } else if (dev->board.is_em2800) { /* the em2800 can only scale down to 50% */ height = height > (3 * maxh / 4) ? maxh : maxh / 2; -- cgit v1.2.3 From 8cd6a59c3237cf9b5d95aeb629f1de468c1771c0 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 30 Jun 2009 12:45:45 -0300 Subject: pwc: remove definitions that are already present at videodev2.h From: Mauro Carvalho Chehab Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/pwc/pwc.h | 6 ------ 1 file changed, 6 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/pwc/pwc.h b/linux/drivers/media/video/pwc/pwc.h index 3a89dca13..7a766eb35 100644 --- a/linux/drivers/media/video/pwc/pwc.h +++ b/linux/drivers/media/video/pwc/pwc.h @@ -137,12 +137,6 @@ #define DEVICE_USE_CODEC3(x) ((x)>=700) #define DEVICE_USE_CODEC23(x) ((x)>=675) - -#ifndef V4L2_PIX_FMT_PWC1 -#define V4L2_PIX_FMT_PWC1 v4l2_fourcc('P','W','C','1') -#define V4L2_PIX_FMT_PWC2 v4l2_fourcc('P','W','C','2') -#endif - /* The following structures were based on cpia.h. Why reinvent the wheel? :-) */ struct pwc_iso_buf { -- cgit v1.2.3 From 0676b34e5c012f7bc63e2cac72401b3aed4c79ea Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 30 Jun 2009 16:07:26 -0300 Subject: move V4L2_PIX_FMT_SGRBG8 to the proper place From: Mauro Carvalho Chehab Instead of defining a new pif format on an internal header, move it to the V4L2 API header. Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/gspca/stv06xx/stv06xx.h | 4 ---- 1 file changed, 4 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/stv06xx/stv06xx.h b/linux/drivers/media/video/gspca/stv06xx/stv06xx.h index bb73c3288..bdea4dae2 100644 --- a/linux/drivers/media/video/gspca/stv06xx/stv06xx.h +++ b/linux/drivers/media/video/gspca/stv06xx/stv06xx.h @@ -37,10 +37,6 @@ #define STV_ISOC_ENDPOINT_ADDR 0x81 -#ifndef V4L2_PIX_FMT_SGRBG8 -#define V4L2_PIX_FMT_SGRBG8 v4l2_fourcc('G', 'R', 'B', 'G') -#endif - #define STV_REG23 0x0423 /* Control registers of the STV0600 ASIC */ -- cgit v1.2.3 From 006bfc72f27dbb1100886dab420c648ab8262e51 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 8 May 2009 21:39:24 -0400 Subject: cx23885: override set_frontend to allow rf input path switching on the HVR1275 From: Michael Krufky Use separate RF input spigots for Antennae and Cable. Priority: normal Reviewed-by: Steven Toth Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/cx23885/cx23885-dvb.c | 29 +++++++++++++++++++++++++ linux/drivers/media/video/cx23885/cx23885.h | 2 ++ 2 files changed, 31 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/cx23885/cx23885-dvb.c b/linux/drivers/media/video/cx23885/cx23885-dvb.c index 71f196ec5..83584535a 100644 --- a/linux/drivers/media/video/cx23885/cx23885-dvb.c +++ b/linux/drivers/media/video/cx23885/cx23885-dvb.c @@ -464,6 +464,30 @@ static struct xc5000_config mygica_x8506_xc5000_config = { .if_khz = 5380, }; +static int cx23885_dvb_set_frontend(struct dvb_frontend *fe, + struct dvb_frontend_parameters *param) +{ + struct cx23885_tsport *port = fe->dvb->priv; + struct cx23885_dev *dev = port->dev; + + switch (dev->board) { + case CX23885_BOARD_HAUPPAUGE_HVR1275: + switch (param->u.vsb.modulation) { + case VSB_8: + cx23885_gpio_clear(dev, GPIO_5); + break; + case QAM_64: + case QAM_256: + default: + cx23885_gpio_set(dev, GPIO_5); + break; + } + break; + } + return (port->set_frontend_save) ? + port->set_frontend_save(fe, param) : -ENODEV; +} + static int dvb_register(struct cx23885_tsport *port) { struct cx23885_dev *dev = port->dev; @@ -503,6 +527,11 @@ static int dvb_register(struct cx23885_tsport *port) 0x60, &dev->i2c_bus[1].i2c_adap, &hauppauge_hvr127x_config); } + + /* define bridge override to set_frontend */ + port->set_frontend_save = fe0->dvb.frontend->ops.set_frontend; + fe0->dvb.frontend->ops.set_frontend = cx23885_dvb_set_frontend; + break; case CX23885_BOARD_HAUPPAUGE_HVR1255: i2c_bus = &dev->i2c_bus[0]; diff --git a/linux/drivers/media/video/cx23885/cx23885.h b/linux/drivers/media/video/cx23885/cx23885.h index 2022ed7de..81af0ede1 100644 --- a/linux/drivers/media/video/cx23885/cx23885.h +++ b/linux/drivers/media/video/cx23885/cx23885.h @@ -289,6 +289,8 @@ struct cx23885_tsport { /* Allow a single tsport to have multiple frontends */ u32 num_frontends; void *port_priv; + int (*set_frontend_save) (struct dvb_frontend *, + struct dvb_frontend_parameters *); }; struct cx23885_dev { -- cgit v1.2.3 From 878e6f5343f5cdf3a658188f4fa94c052e1d7108 Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Fri, 8 May 2009 23:34:31 -0400 Subject: cx18: Add missing newline to tuner detection error message From: Andy Walls Priority: normal Signed-off-by: Andy Walls --- linux/drivers/media/video/cx18/cx18-driver.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/cx18/cx18-driver.c b/linux/drivers/media/video/cx18/cx18-driver.c index 41997dd18..f42a97314 100644 --- a/linux/drivers/media/video/cx18/cx18-driver.c +++ b/linux/drivers/media/video/cx18/cx18-driver.c @@ -313,7 +313,7 @@ static void cx18_process_eeprom(struct cx18 *cx) CX18_INFO("Autodetected %s\n", cx->card_name); if (tv.tuner_type == TUNER_ABSENT) - CX18_ERR("tveeprom cannot autodetect tuner!"); + CX18_ERR("tveeprom cannot autodetect tuner!\n"); if (cx->options.tuner == -1) cx->options.tuner = tv.tuner_type; -- cgit v1.2.3 From 2b01e0e4cd5cd2969d0b64c23608f18da907e20b Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Fri, 8 May 2009 23:43:40 -0400 Subject: tveeprom: Point the TCL MNM05-4 tuner entry to an actual tuner definition From: Andy Walls The TCL MNM05-04 is used on some HVR-1600 models. It appears to be similar to the TCL MFMN05-4 but without FM radio. The TUNER_PHILIPS_FM1236_MK3 tuner definition appears to be the proper existing tuner definition to use for this tuner. Reported-by: Matt Beadon Priority: normal Tested-by: Matt Beadon Signed-off-by: Andy Walls --- linux/drivers/media/video/tveeprom.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/tveeprom.c b/linux/drivers/media/video/tveeprom.c index cdea91aae..7d6459dd2 100644 --- a/linux/drivers/media/video/tveeprom.c +++ b/linux/drivers/media/video/tveeprom.c @@ -211,7 +211,7 @@ hauppauge_tuner[] = { TUNER_TEA5767, "Philips TEA5768HL FM Radio"}, { TUNER_ABSENT, "Panasonic ENV57H12D5"}, { TUNER_PHILIPS_FM1236_MK3, "TCL MFNM05-4"}, - { TUNER_ABSENT, "TCL MNM05-4"}, + { TUNER_PHILIPS_FM1236_MK3, "TCL MNM05-4"}, { TUNER_PHILIPS_FM1216ME_MK3, "TCL MPE05-2"}, { TUNER_ABSENT, "TCL MQNM05-4"}, { TUNER_ABSENT, "LG TAPC-W701D"}, -- cgit v1.2.3 From e45c6d33fbee270c6642910bd7d706d602d72914 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Sat, 9 May 2009 21:40:45 +0200 Subject: soc-camera: Fix section mismatch warning From: Guennadi Liakhovetski modpost needs a __refdata marker in driver structs to ensure references to .probe and .remove functions from .devinit.text and .devexit.text sections respectively are valid. Add __refdata to soc_camera_pdrv platform driver. Signed-off-by: Guennadi Liakhovetski --- drivers/media/video/soc_camera.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) --- linux/drivers/media/video/soc_camera.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/soc_camera.c b/linux/drivers/media/video/soc_camera.c index f792ab2e5..822052b25 100644 --- a/linux/drivers/media/video/soc_camera.c +++ b/linux/drivers/media/video/soc_camera.c @@ -1204,7 +1204,7 @@ static int __devexit soc_camera_pdrv_remove(struct platform_device *pdev) return 0; } -static struct platform_driver soc_camera_pdrv = { +static struct platform_driver __refdata soc_camera_pdrv = { .probe = soc_camera_pdrv_probe, .remove = __exit_p(soc_camera_pdrv_remove), .driver = { -- cgit v1.2.3 From cfff66b2575874f0f9c6677cba1a54bb166c444b Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Sat, 9 May 2009 16:00:23 -0500 Subject: pvrusb2: Allocate a routing ID for future support of Terratec Grabster AV400 From: Mike Isely Priority: normal Signed-off-by: Mike Isely --- linux/drivers/media/video/pvrusb2/pvrusb2-devattr.h | 1 + 1 file changed, 1 insertion(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-devattr.h b/linux/drivers/media/video/pvrusb2/pvrusb2-devattr.h index 73e0e0ba0..ea04ecf8a 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-devattr.h +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-devattr.h @@ -69,6 +69,7 @@ struct pvr2_string_table { #define PVR2_ROUTING_SCHEME_HAUPPAUGE 0 #define PVR2_ROUTING_SCHEME_GOTVIEW 1 #define PVR2_ROUTING_SCHEME_ONAIR 2 +#define PVR2_ROUTING_SCHEME_AV400 3 #define PVR2_DIGITAL_SCHEME_NONE 0 #define PVR2_DIGITAL_SCHEME_HAUPPAUGE 1 -- cgit v1.2.3 From f8bb2c583e80e1d67900051b691b9ef7069d3f6d Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Sun, 10 May 2009 21:14:29 -0400 Subject: cx18: Initial attempt to get sliced VBI working for 625 line systems From: Andy Walls Initial changes to get sliced VBI for 625 line system working. This is patch is untested. Priority: normal Signed-off-by: Andy Walls --- linux/drivers/media/video/cx18/cx18-av-core.c | 59 +++++++++++++++++++++------ linux/drivers/media/video/cx18/cx18-av-vbi.c | 4 +- linux/drivers/media/video/cx18/cx18-streams.c | 8 +++- 3 files changed, 56 insertions(+), 15 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/cx18/cx18-av-core.c b/linux/drivers/media/video/cx18/cx18-av-core.c index 2b07b1563..d98010e0d 100644 --- a/linux/drivers/media/video/cx18/cx18-av-core.c +++ b/linux/drivers/media/video/cx18/cx18-av-core.c @@ -288,17 +288,52 @@ void cx18_av_std_setup(struct cx18 *cx) else cx18_av_write(cx, 0x49f, 0x14); + /* + * Note: At the end of a field, there are 3 sets of half line duration + * (double horizontal rate) pulses: + * + * 5 (625) or 6 (525) half-lines to blank for the vertical retrace + * 5 (625) or 6 (525) vertical sync pulses of half line duration + * 5 (625) or 6 (525) half-lines of equalization pulses + */ if (std & V4L2_STD_625_50) { - /* FIXME - revisit these for Sliced VBI */ + /* + * The following relationships of half line counts should hold: + * 625 = vblank656 + vactive + postvactive + * 10 = vblank656 - vblank = vsync pulses + equalization pulses + * + * vblank656: half lines after line 625/mid-313 of blanked video + * vblank: half lines, after line 5/317, of blanked video + * vactive: half lines of active video + * postvactive: 5 half lines after the end of active video + * + * As far as I can tell: + * vblank656 starts counting from the falling edge of the first + * vsync pulse (start of line 1 or mid-313) + * vblank starts counting from the after the 5 vsync pulses and + * 5 or 4 equalization pulses (start of line 6 or 318) + * + * For 625 line systems the driver will extract VBI information + * from lines 6-23 and lines 318-335 (but the slicer can only + * handle 17 lines, not the 18 in the vblank region). + */ + vblank656 = 46; /* lines 1 - 23 & 313 - 335 */ + vblank = 36; /* lines 6 - 23 & 318 - 335 */ + vactive = 574; /* lines 24 - 310 & 336 - 622 */ + + /* + * For a 13.5 Mpps clock and 15,625 Hz line rate, a line is + * is 864 pixels = 720 active + 144 blanking. ITU-R BT.601 + * specifies 12 luma clock periods or ~ 0.9 * 13.5 Mpps after + * the end of active video to start a horizontal line, so that + * leaves 132 pixels of hblank to ignore. + */ hblank = 132; hactive = 720; - burst = 93; - vblank = 36; - vactive = 580; - vblank656 = 40; - src_decimation = 0x21f; + burst = 93; luma_lpf = 2; + src_decimation = 0x21f; if (std & V4L2_STD_PAL) { uv_lpf = 1; comb = 0x20; @@ -315,13 +350,13 @@ void cx18_av_std_setup(struct cx18 *cx) } else { /* * The following relationships of half line counts should hold: - * 525 = vsync + vactive + vblank656 - * 12 = vblank656 - vblank + * 525 = prevsync + vblank656 + vactive + * 12 = vblank656 - vblank = vsync pulses + equalization pulses * - * vsync: always 6 half-lines of vsync pulses - * vactive: half lines of active video + * prevsync: 6 half-lines before the vsync pulses * vblank656: half lines, after line 3/mid-266, of blanked video * vblank: half lines, after line 9/272, of blanked video + * vactive: half lines of active video * * As far as I can tell: * vblank656 starts counting from the falling edge of the first @@ -954,9 +989,9 @@ static int cx18_av_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) * cx18_av_std_setup(), above standard values: * * 480 + 1 for 60 Hz systems - * 576 + 4 for 50 Hz systems + * 576 - 2 for 50 Hz systems */ - Vlines = pix->height + (is_50Hz ? 4 : 1); + Vlines = pix->height + (is_50Hz ? -2 : 1); /* * Invalid height and width scaling requests are: diff --git a/linux/drivers/media/video/cx18/cx18-av-vbi.c b/linux/drivers/media/video/cx18/cx18-av-vbi.c index 23b31670b..640121448 100644 --- a/linux/drivers/media/video/cx18/cx18-av-vbi.c +++ b/linux/drivers/media/video/cx18/cx18-av-vbi.c @@ -255,8 +255,8 @@ int cx18_av_vbi_s_fmt(struct cx18 *cx, struct v4l2_format *fmt) } cx18_av_write(cx, 0x43c, 0x16); - /* FIXME - should match vblank set in cx18_av_std_setup() */ - cx18_av_write(cx, 0x474, is_pal ? 0x2a : 26); + /* Should match vblank set in cx18_av_std_setup() */ + cx18_av_write(cx, 0x474, is_pal ? 36 : 26); return 0; } diff --git a/linux/drivers/media/video/cx18/cx18-streams.c b/linux/drivers/media/video/cx18/cx18-streams.c index 142302ba5..081efc575 100644 --- a/linux/drivers/media/video/cx18/cx18-streams.c +++ b/linux/drivers/media/video/cx18/cx18-streams.c @@ -376,9 +376,15 @@ static void cx18_vbi_setup(struct cx18_stream *s) * Tell the encoder to capture 21-4+1=18 lines per field, * since we want lines 10 through 21. * + * For 625/50 systems, according to the VIP 2 & BT.656 std: + * The EAV RP code's Field bit toggles on line 1, a few lines + * after the Vertcal Blank bit has already toggled. + * Tell the encoder to capture 23-1+1=23 lines per field, + * since we want lines 6 through 23. + * * FIXME - revisit for 625/50 systems */ - lines = cx->is_60hz ? (21 - 4 + 1) * 2 : 38; + lines = cx->is_60hz ? (21 - 4 + 1) * 2 : (23 - 1 + 1) * 2; } data[0] = s->handle; -- cgit v1.2.3 From 39ae4cb418ef242558b61172ca37807dd184fb70 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Mon, 11 May 2009 19:51:32 +0200 Subject: soc_camera: depends on I2C From: Randy Dunlap soc_camera uses i2c_*() functions and has build errors when CONFIG_I2C=n: ERROR: "i2c_new_device" [drivers/media/video/soc_camera.ko] undefined! ERROR: "i2c_get_adapter" [drivers/media/video/soc_camera.ko] undefined! ERROR: "i2c_put_adapter" [drivers/media/video/soc_camera.ko] undefined! ERROR: "i2c_unregister_device" [drivers/media/video/soc_camera.ko] undefined! Signed-off-by: Randy Dunlap Signed-off-by: Guennadi Liakhovetski --- drivers/media/video/Kconfig | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) --- linux/drivers/media/video/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/Kconfig b/linux/drivers/media/video/Kconfig index 9d48da2fb..f3799cb67 100644 --- a/linux/drivers/media/video/Kconfig +++ b/linux/drivers/media/video/Kconfig @@ -694,7 +694,7 @@ config VIDEO_CAFE_CCIC config SOC_CAMERA tristate "SoC camera support" - depends on VIDEO_V4L2 && HAS_DMA + depends on VIDEO_V4L2 && HAS_DMA && I2C select VIDEOBUF_GEN help SoC Camera is a common API to several cameras, not connecting -- cgit v1.2.3 From e8b29e62cfa708cab8f3f2dc6cb55a433ccfe561 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 11 May 2009 09:37:41 -0700 Subject: 2: handle unregister for non-I2C builds From: Randy Dunlap Build fails when CONFIG_I2C=n, so handle that case in the if block: drivers/built-in.o: In function `v4l2_device_unregister': (.text+0x157821): undefined reference to `i2c_unregister_device' Signed-off-by: Randy Dunlap Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/v4l2-device.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/v4l2-device.c b/linux/drivers/media/video/v4l2-device.c index c76f83840..b962862fe 100644 --- a/linux/drivers/media/video/v4l2-device.c +++ b/linux/drivers/media/video/v4l2-device.c @@ -86,6 +86,7 @@ void v4l2_device_unregister(struct v4l2_device *v4l2_dev) /* Unregister subdevs */ list_for_each_entry_safe(sd, next, &v4l2_dev->subdevs, list) { v4l2_device_unregister_subdev(sd); +#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) if (sd->flags & V4L2_SUBDEV_FL_IS_I2C) { struct i2c_client *client = v4l2_get_subdevdata(sd); @@ -96,6 +97,7 @@ void v4l2_device_unregister(struct v4l2_device *v4l2_dev) if (client) i2c_unregister_device(client); } +#endif } } EXPORT_SYMBOL_GPL(v4l2_device_unregister); -- cgit v1.2.3 From d43f81dbba069842d0b1d0083b6f64e0eb9f9c38 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 12 May 2009 16:32:17 -0400 Subject: cx23885: add DVB-T tuning support for Hauppauge WinTV-HVR1210 From: Michael Krufky Priority: normal Signed-off-by: Michael Krufky --- linux/drivers/media/video/cx23885/cx23885-cards.c | 20 +++++++++++++++++-- linux/drivers/media/video/cx23885/cx23885-dvb.c | 24 +++++++++++++++++++++++ linux/drivers/media/video/cx23885/cx23885.h | 1 + 3 files changed, 43 insertions(+), 2 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/cx23885/cx23885-cards.c b/linux/drivers/media/video/cx23885/cx23885-cards.c index 2d398f755..0e65a2d25 100644 --- a/linux/drivers/media/video/cx23885/cx23885-cards.c +++ b/linux/drivers/media/video/cx23885/cx23885-cards.c @@ -194,6 +194,10 @@ struct cx23885_board cx23885_boards[] = { .name = "Hauppauge WinTV-HVR1255", .portc = CX23885_MPEG_DVB, }, + [CX23885_BOARD_HAUPPAUGE_HVR1210] = { + .name = "Hauppauge WinTV-HVR1210", + .portc = CX23885_MPEG_DVB, + }, }; const unsigned int cx23885_bcount = ARRAY_SIZE(cx23885_boards); @@ -305,6 +309,14 @@ struct cx23885_subid cx23885_subids[] = { .subvendor = 0x0070, .subdevice = 0x2251, .card = CX23885_BOARD_HAUPPAUGE_HVR1255, + }, { + .subvendor = 0x0070, + .subdevice = 0x2291, + .card = CX23885_BOARD_HAUPPAUGE_HVR1210, + }, { + .subvendor = 0x0070, + .subdevice = 0x2295, + .card = CX23885_BOARD_HAUPPAUGE_HVR1210, }, }; const unsigned int cx23885_idcount = ARRAY_SIZE(cx23885_subids); @@ -647,9 +659,10 @@ void cx23885_gpio_setup(struct cx23885_dev *dev) case CX23885_BOARD_HAUPPAUGE_HVR1270: case CX23885_BOARD_HAUPPAUGE_HVR1275: case CX23885_BOARD_HAUPPAUGE_HVR1255: + case CX23885_BOARD_HAUPPAUGE_HVR1210: /* GPIO-5 RF Control: 0 = RF1 Terrestrial, 1 = RF2 Cable */ - /* GPIO-6 I2C Gate which can isolate the 3305 from the bus */ - /* GPIO-9 LG3305 reset */ + /* GPIO-6 I2C Gate which can isolate the demod from the bus */ + /* GPIO-9 Demod reset */ /* Put the parts into reset and back */ cx23885_gpio_enable(dev, GPIO_9 | GPIO_6 | GPIO_5, 1); @@ -673,6 +686,7 @@ int cx23885_ir_init(struct cx23885_dev *dev) case CX23885_BOARD_HAUPPAUGE_HVR1270: case CX23885_BOARD_HAUPPAUGE_HVR1275: case CX23885_BOARD_HAUPPAUGE_HVR1255: + case CX23885_BOARD_HAUPPAUGE_HVR1210: /* FIXME: Implement me */ break; case CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP: @@ -711,6 +725,7 @@ void cx23885_card_setup(struct cx23885_dev *dev) case CX23885_BOARD_HAUPPAUGE_HVR1270: case CX23885_BOARD_HAUPPAUGE_HVR1275: case CX23885_BOARD_HAUPPAUGE_HVR1255: + case CX23885_BOARD_HAUPPAUGE_HVR1210: if (dev->i2c_bus[0].i2c_rc == 0) hauppauge_eeprom(dev, eeprom+0xc0); break; @@ -771,6 +786,7 @@ void cx23885_card_setup(struct cx23885_dev *dev) case CX23885_BOARD_HAUPPAUGE_HVR1270: case CX23885_BOARD_HAUPPAUGE_HVR1275: case CX23885_BOARD_HAUPPAUGE_HVR1255: + case CX23885_BOARD_HAUPPAUGE_HVR1210: default: ts2->gen_ctrl_val = 0xc; /* Serial bus + punctured clock */ ts2->ts_clk_en_val = 0x1; /* Enable TS_CLK */ diff --git a/linux/drivers/media/video/cx23885/cx23885-dvb.c b/linux/drivers/media/video/cx23885/cx23885-dvb.c index c671d8e46..28d7466f5 100644 --- a/linux/drivers/media/video/cx23885/cx23885-dvb.c +++ b/linux/drivers/media/video/cx23885/cx23885-dvb.c @@ -129,6 +129,15 @@ static struct tda10048_config hauppauge_hvr1200_config = { .clk_freq_khz = TDA10048_CLK_16000, }; +static struct tda10048_config hauppauge_hvr1210_config = { + .demod_address = 0x10 >> 1, + .output_mode = TDA10048_SERIAL_OUTPUT, + .fwbulkwritelen = TDA10048_BULKWRITE_200, + .inversion = TDA10048_INVERSION_ON, + .if_freq_khz = TDA10048_IF_4000, + .clk_freq_khz = TDA10048_CLK_16000, +}; + static struct s5h1409_config hauppauge_ezqam_config = { .demod_address = 0x32 >> 1, .output_mode = S5H1409_SERIAL_OUTPUT, @@ -238,6 +247,10 @@ static struct tda18271_config hauppauge_hvr1200_tuner_config = { .gate = TDA18271_GATE_ANALOG, }; +static struct tda18271_config hauppauge_hvr1210_tuner_config = { + .gate = TDA18271_GATE_DIGITAL, +}; + static struct tda18271_std_map hcw_lgdt3305_tda18271_std_map = { .atsc_6 = { .if_freq = 3250, .agc_mode = 3, .std = 4, .if_lvl = 1, .rfagc_top = 0x58 }, @@ -555,6 +568,17 @@ static int dvb_register(struct cx23885_tsport *port) &hauppauge_hvr1200_tuner_config); } break; + case CX23885_BOARD_HAUPPAUGE_HVR1210: + i2c_bus = &dev->i2c_bus[0]; + fe0->dvb.frontend = dvb_attach(tda10048_attach, + &hauppauge_hvr1210_config, + &i2c_bus->i2c_adap); + if (fe0->dvb.frontend != NULL) { + dvb_attach(tda18271_attach, fe0->dvb.frontend, + 0x60, &dev->i2c_bus[1].i2c_adap, + &hauppauge_hvr1210_tuner_config); + } + break; case CX23885_BOARD_HAUPPAUGE_HVR1400: i2c_bus = &dev->i2c_bus[0]; fe0->dvb.frontend = dvb_attach(dib7000p_attach, diff --git a/linux/drivers/media/video/cx23885/cx23885.h b/linux/drivers/media/video/cx23885/cx23885.h index 947ade659..8dba2fdd6 100644 --- a/linux/drivers/media/video/cx23885/cx23885.h +++ b/linux/drivers/media/video/cx23885/cx23885.h @@ -75,6 +75,7 @@ #define CX23885_BOARD_HAUPPAUGE_HVR1270 18 #define CX23885_BOARD_HAUPPAUGE_HVR1275 19 #define CX23885_BOARD_HAUPPAUGE_HVR1255 20 +#define CX23885_BOARD_HAUPPAUGE_HVR1210 21 #define GPIO_0 0x00000001 #define GPIO_1 0x00000002 -- cgit v1.2.3 From e93650ed915f11162ed9004e4cfb2e9e4fd36367 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 12 May 2009 17:37:35 -0400 Subject: cx23885: update model matrix for "k2c2" retail boards From: Michael Krufky Priority: normal Signed-off-by: Michael Krufky --- linux/drivers/media/video/cx23885/cx23885-cards.c | 36 +++++++++++++++++++++++ 1 file changed, 36 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/cx23885/cx23885-cards.c b/linux/drivers/media/video/cx23885/cx23885-cards.c index 0e65a2d25..93176fe4b 100644 --- a/linux/drivers/media/video/cx23885/cx23885-cards.c +++ b/linux/drivers/media/video/cx23885/cx23885-cards.c @@ -358,6 +358,42 @@ static void hauppauge_eeprom(struct cx23885_dev *dev, u8 *eeprom_data) /* Make sure we support the board model */ switch (tv.model) { + case 22001: + /* WinTV-HVR1270 (PCIe, Retail, half height) + * ATSC/QAM and basic analog, IR Blast */ + case 22009: + /* WinTV-HVR1210 (PCIe, Retail, half height) + * DVB-T and basic analog, IR Blast */ + case 22011: + /* WinTV-HVR1270 (PCIe, Retail, half height) + * ATSC/QAM and basic analog, IR Recv */ + case 22019: + /* WinTV-HVR1210 (PCIe, Retail, half height) + * DVB-T and basic analog, IR Recv */ + case 22021: + /* WinTV-HVR1275 (PCIe, Retail, half height) + * ATSC/QAM and basic analog, IR Recv */ + case 22029: + /* WinTV-HVR1210 (PCIe, Retail, half height) + * DVB-T and basic analog, IR Recv */ + case 22101: + /* WinTV-HVR1270 (PCIe, Retail, full height) + * ATSC/QAM and basic analog, IR Blast */ + case 22109: + /* WinTV-HVR1210 (PCIe, Retail, full height) + * DVB-T and basic analog, IR Blast */ + case 22111: + /* WinTV-HVR1270 (PCIe, Retail, full height) + * ATSC/QAM and basic analog, IR Recv */ + case 22119: + /* WinTV-HVR1210 (PCIe, Retail, full height) + * DVB-T and basic analog, IR Recv */ + case 22121: + /* WinTV-HVR1275 (PCIe, Retail, full height) + * ATSC/QAM and basic analog, IR Recv */ + case 22129: + /* WinTV-HVR1210 (PCIe, Retail, full height) + * DVB-T and basic analog, IR Recv */ case 71009: /* WinTV-HVR1200 (PCIe, Retail, full height) * DVB-T and basic analog */ -- cgit v1.2.3 From 7e2fc0b0dd4648fcd4c2ca82093aebcfaed3e863 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 12 May 2009 17:53:47 -0400 Subject: cx23885: clean up struct names for Hauppauge WinTV-HVR127X devices From: Michael Krufky Priority: normal Signed-off-by: Michael Krufky --- linux/drivers/media/video/cx23885/cx23885-dvb.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/cx23885/cx23885-dvb.c b/linux/drivers/media/video/cx23885/cx23885-dvb.c index 28d7466f5..ba120b9cf 100644 --- a/linux/drivers/media/video/cx23885/cx23885-dvb.c +++ b/linux/drivers/media/video/cx23885/cx23885-dvb.c @@ -251,18 +251,18 @@ static struct tda18271_config hauppauge_hvr1210_tuner_config = { .gate = TDA18271_GATE_DIGITAL, }; -static struct tda18271_std_map hcw_lgdt3305_tda18271_std_map = { +static struct tda18271_std_map hauppauge_hvr127x_std_map = { .atsc_6 = { .if_freq = 3250, .agc_mode = 3, .std = 4, .if_lvl = 1, .rfagc_top = 0x58 }, .qam_6 = { .if_freq = 4000, .agc_mode = 3, .std = 5, .if_lvl = 1, .rfagc_top = 0x58 }, }; -static struct tda18271_config hcw_lgdt3305_tda18271_config = { - .std_map = &hcw_lgdt3305_tda18271_std_map, +static struct tda18271_config hauppauge_hvr127x_config = { + .std_map = &hauppauge_hvr127x_std_map, }; -static struct lgdt3305_config hcw_lgdt3305_config = { +static struct lgdt3305_config hauppauge_lgdt3305_config = { .i2c_addr = 0x0e, .mpeg_mode = LGDT3305_MPEG_SERIAL, .tpclk_edge = LGDT3305_TPCLK_FALLING_EDGE, @@ -449,12 +449,12 @@ static int dvb_register(struct cx23885_tsport *port) case CX23885_BOARD_HAUPPAUGE_HVR1275: i2c_bus = &dev->i2c_bus[0]; fe0->dvb.frontend = dvb_attach(lgdt3305_attach, - &hcw_lgdt3305_config, + &hauppauge_lgdt3305_config, &i2c_bus->i2c_adap); if (fe0->dvb.frontend != NULL) { dvb_attach(tda18271_attach, fe0->dvb.frontend, 0x60, &dev->i2c_bus[1].i2c_adap, - &hcw_lgdt3305_tda18271_config); + &hauppauge_hvr127x_config); } break; case CX23885_BOARD_HAUPPAUGE_HVR1255: -- cgit v1.2.3 From fff076374a4aa9a09b3197f4590be83707fe0faa Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 11 May 2009 11:16:06 +0000 Subject: tuner: add support Philips MK5 tuner From: Dmitri Belimov Signed-off-by: Beholder Intl. Ltd. Dmitry Belimov Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/common/tuners/tuner-types.c | 30 +++++++++++++++++++++++++ 1 file changed, 30 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/common/tuners/tuner-types.c b/linux/drivers/media/common/tuners/tuner-types.c index d83df3604..43afd30b0 100644 --- a/linux/drivers/media/common/tuners/tuner-types.c +++ b/linux/drivers/media/common/tuners/tuner-types.c @@ -579,6 +579,31 @@ static struct tuner_params tuner_fm1216me_mk3_params[] = { }, }; +/* ------------ TUNER_PHILIPS_FM1216MK5 - Philips PAL ------------ */ + +static struct tuner_range tuner_fm1216mk5_pal_ranges[] = { + { 16 * 158.00 /*MHz*/, 0xce, 0x01, }, + { 16 * 441.00 /*MHz*/, 0xce, 0x02, }, + { 16 * 864.00 , 0xce, 0x04, }, +}; + +static struct tuner_params tuner_fm1216mk5_params[] = { + { + .type = TUNER_PARAM_TYPE_PAL, + .ranges = tuner_fm1216mk5_pal_ranges, + .count = ARRAY_SIZE(tuner_fm1216mk5_pal_ranges), + .cb_first_if_lower_freq = 1, + .has_tda9887 = 1, + .port1_active = 1, + .port2_active = 1, + .port2_invert_for_secam_lc = 1, + .port1_fm_high_sensitivity = 1, + .default_top_mid = -2, + .default_top_secam_mid = -2, + .default_top_secam_high = -2, + }, +}; + /* ------------ TUNER_LG_NTSC_NEW_TAPC - LGINNOTEK NTSC ------------ */ static struct tuner_params tuner_lg_ntsc_new_tapc_params[] = { @@ -1695,6 +1720,11 @@ struct tunertype tuners[] = { .initdata = tua603x_agc112, .sleepdata = (u8[]){ 4, 0x9c, 0x60, 0x85, 0x54 }, }, + [TUNER_PHILIPS_FM1216MK5] = { /* Philips PAL */ + .name = "Philips PAL/SECAM multi (FM1216 MK5)", + .params = tuner_fm1216mk5_params, + .count = ARRAY_SIZE(tuner_fm1216mk5_params), + }, }; EXPORT_SYMBOL(tuners); -- 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 240e6d86113de5254985ae8f151581df10b65a8f Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 12 May 2009 10:57:54 +0000 Subject: Siano: smsusb - update license From: Uri Shkolnik This patch updates the license of the USB interface driver Priority: normal Signed-off-by: Uri Shkolnik Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/siano/smsusb.c | 40 +++++++++++++++++----------------- 1 file changed, 20 insertions(+), 20 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/siano/smsusb.c b/linux/drivers/media/dvb/siano/smsusb.c index 67be79549..fab73ca39 100644 --- a/linux/drivers/media/dvb/siano/smsusb.c +++ b/linux/drivers/media/dvb/siano/smsusb.c @@ -1,23 +1,23 @@ -/* - * Driver for the Siano SMS1xxx USB dongle - * - * author: Anatoly Greenblat - * - * Copyright (c), 2005-2008 Siano Mobile Silicon, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation; - * - * Software distributed under the License is distributed on an "AS IS" - * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. - * - * See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ +/**************************************************************** + +Siano Mobile Silicon, Inc. +MDTV receiver kernel modules. +Copyright (C) 2005-2009, Uri Shkolnik, Anatoly Greenblat + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 of the License, or +(at your option) any later version. + + This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . + +****************************************************************/ #include #include -- cgit v1.2.3 From 68afa52d9809eae342ae42338b0b004ea71257a2 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 12 May 2009 11:24:07 +0000 Subject: Siano: smsusb - handle byte ordering and big endianity From: Uri Shkolnik This patch adds support for byte ordering and big endianity handling for the USB interface driver Priority: normal Signed-off-by: Uri Shkolnik Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/siano/smsusb.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/siano/smsusb.c b/linux/drivers/media/dvb/siano/smsusb.c index fab73ca39..17332a09a 100644 --- a/linux/drivers/media/dvb/siano/smsusb.c +++ b/linux/drivers/media/dvb/siano/smsusb.c @@ -26,6 +26,7 @@ along with this program. If not, see . #include "smscoreapi.h" #include "sms-cards.h" +#include "smsendian.h" static int sms_dbg; module_param_named(debug, sms_dbg, int, 0644); @@ -180,6 +181,7 @@ static int smsusb_sendrequest(void *context, void *buffer, size_t size) struct smsusb_device_t *dev = (struct smsusb_device_t *) context; int dummy; + smsendian_handle_message_header((struct SmsMsgHdr_ST *)buffer); return usb_bulk_msg(dev->udev, usb_sndbulkpipe(dev->udev, 2), buffer, size, &dummy, 1000); } @@ -337,8 +339,8 @@ static int smsusb_init_device(struct usb_interface *intf, int board_id) case SMS_VEGA: dev->buffer_size = USB2_BUFFER_SIZE; dev->response_alignment = - dev->udev->ep_in[1]->desc.wMaxPacketSize - - sizeof(struct SmsMsgHdr_ST); + le16_to_cpu(dev->udev->ep_in[1]->desc.wMaxPacketSize) - + sizeof(struct SmsMsgHdr_ST); params.flags |= SMS_DEVICE_FAMILY2; break; -- cgit v1.2.3 From df4ef7800b3db4653ab235d8347dc17d876e8f67 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 12 May 2009 14:28:41 +0000 Subject: Siano: smsusb - lost buffers bug fix From: Uri Shkolnik This patch fixes a problem were protocol buffers have been lost during USB disconnect events. Priority: normal Signed-off-by: Uri Shkolnik Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/siano/smsusb.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/siano/smsusb.c b/linux/drivers/media/dvb/siano/smsusb.c index 17332a09a..7f0246fdb 100644 --- a/linux/drivers/media/dvb/siano/smsusb.c +++ b/linux/drivers/media/dvb/siano/smsusb.c @@ -69,14 +69,14 @@ static void smsusb_onresponse(struct urb *urb, struct pt_regs *regs) struct smsusb_urb_t *surb = (struct smsusb_urb_t *) urb->context; struct smsusb_device_t *dev = surb->dev; - if (urb->status < 0) { - sms_err("error, urb status %d, %d bytes", + if (urb->status == -ESHUTDOWN) { + sms_err("error, urb status %d (-ESHUTDOWN), %d bytes", urb->status, urb->actual_length); return; } - if (urb->actual_length > 0) { - struct SmsMsgHdr_ST *phdr = (struct SmsMsgHdr_ST *) surb->cb->p; + if ((urb->actual_length > 0) && (urb->status == 0)) { + struct SmsMsgHdr_ST *phdr = (struct SmsMsgHdr_ST *)surb->cb->p; if (urb->actual_length >= phdr->msgLength) { surb->cb->size = phdr->msgLength; @@ -114,7 +114,10 @@ static void smsusb_onresponse(struct urb *urb, struct pt_regs *regs) "msglen %d actual %d", phdr->msgLength, urb->actual_length); } - } + } else + sms_err("error, urb status %d, %d bytes", + urb->status, urb->actual_length); + exit_and_resubmit: smsusb_submit_urb(dev, surb); -- cgit v1.2.3 From caf7a673bbefc685df483fd4a285c443174fbd24 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 12 May 2009 06:38:58 -0700 Subject: Siano: Makefile - add smsendian to build From: Uri Shkolnik Add smsendian component to the module build Priority: normal Signed-off-by: Uri Shkolnik Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/siano/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/siano/Makefile b/linux/drivers/media/dvb/siano/Makefile index bcf93f482..6354a4718 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 +sms1xxx-objs := smscoreapi.o sms-cards.o smsendian.o obj-$(CONFIG_DVB_SIANO_SMS1XXX) += sms1xxx.o obj-$(CONFIG_DVB_SIANO_SMS1XXX) += smsusb.o -- cgit v1.2.3 From 933b155b80111900885f3b736fb5ec36207cac98 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 14 May 2009 09:35:26 -0300 Subject: Siano: fix compilation error due to the lack of EXTERNAL_SYMBOL Priority: normal CC: Uri Shkolnik Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/siano/smsendian.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/siano/smsendian.c b/linux/drivers/media/dvb/siano/smsendian.c index d79aa0512..457b6d02e 100644 --- a/linux/drivers/media/dvb/siano/smsendian.c +++ b/linux/drivers/media/dvb/siano/smsendian.c @@ -49,6 +49,7 @@ void smsendian_handle_tx_message(void *buffer) } #endif /* __BIG_ENDIAN */ } +EXPORT_SYMBOL_GPL(smsendian_handle_tx_message); void smsendian_handle_rx_message(void *buffer) { @@ -86,6 +87,7 @@ void smsendian_handle_rx_message(void *buffer) } #endif /* __BIG_ENDIAN */ } +EXPORT_SYMBOL_GPL(smsendian_handle_rx_message); void smsendian_handle_message_header(void *msg) { @@ -97,4 +99,4 @@ void smsendian_handle_message_header(void *msg) phdr->msgFlags = le16_to_cpu(phdr->msgFlags); #endif /* __BIG_ENDIAN */ } - +EXPORT_SYMBOL_GPL(smsendian_handle_message_header); -- cgit v1.2.3 From 5970b3d8008b625f502690ea408dc756f45a30e3 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 12 May 2009 14:37:09 +0000 Subject: Siano: smsdvb - add big endian support From: Uri Shkolnik Add support for Siano protocol messages with big endian systems. Priority: normal Signed-off-by: Uri Shkolnik Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/siano/smsdvb.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/siano/smsdvb.c b/linux/drivers/media/dvb/siano/smsdvb.c index 255ee5719..b69bd77cb 100644 --- a/linux/drivers/media/dvb/siano/smsdvb.c +++ b/linux/drivers/media/dvb/siano/smsdvb.c @@ -23,6 +23,7 @@ along with this program. If not, see . #include #include "smscoreapi.h" +#include "smsendian.h" #include "sms-cards.h" DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); @@ -60,6 +61,8 @@ static int smsdvb_onresponse(void *context, struct smscore_buffer_t *cb) struct SmsMsgHdr_ST *phdr = (struct SmsMsgHdr_ST *)(((u8 *) cb->p) + cb->offset); + smsendian_handle_rx_message((struct SmsMsgData_ST *) phdr); + switch (phdr->msgType) { case MSG_SMS_DVBT_BDA_DATA: dvb_dmx_swfilter(&client->demux, (u8 *)(phdr + 1), @@ -149,6 +152,7 @@ static int smsdvb_start_feed(struct dvb_demux_feed *feed) PidMsg.xMsgHeader.msgLength = sizeof(PidMsg); PidMsg.msgData[0] = feed->pid; + smsendian_handle_tx_message((struct SmsMsgHdr_ST *)&PidMsg); return smsclient_sendrequest(client->smsclient, &PidMsg, sizeof(PidMsg)); } @@ -169,6 +173,7 @@ static int smsdvb_stop_feed(struct dvb_demux_feed *feed) PidMsg.xMsgHeader.msgLength = sizeof(PidMsg); PidMsg.msgData[0] = feed->pid; + smsendian_handle_tx_message((struct SmsMsgHdr_ST *)&PidMsg); return smsclient_sendrequest(client->smsclient, &PidMsg, sizeof(PidMsg)); } @@ -177,7 +182,10 @@ static int smsdvb_sendrequest_and_wait(struct smsdvb_client_t *client, void *buffer, size_t size, struct completion *completion) { - int rc = smsclient_sendrequest(client->smsclient, buffer, size); + int rc; + + smsendian_handle_tx_message((struct SmsMsgHdr_ST *)buffer); + rc = smsclient_sendrequest(client->smsclient, buffer, size); if (rc < 0) return rc; -- cgit v1.2.3 From 30c67c0e526d256d94bc1026d021d62a97947ef1 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 12 May 2009 15:28:46 +0000 Subject: Siano: smsdvb - use 'push' status mechanism From: Uri Shkolnik This patch replace the old method of pulling the device status by sending "get_statistics" request, to push mode. This make status update much faster, and reduce various operation time (UHF scan now takes 15s instead of 2m). In order to make the change the following modification have been applied: 1) core header - update statistics headers. 2) dvb adapter - omit the statistics request, add handling of status indications. 3) core 'onresponse' - re-route messages addressed to other adapter to the dvb adapter. Priority: normal Signed-off-by: Uri Shkolnik Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/siano/smscoreapi.c | 23 +- linux/drivers/media/dvb/siano/smscoreapi.h | 377 +++++++++++++---------------- linux/drivers/media/dvb/siano/smsdvb.c | 266 +++++++++++--------- 3 files changed, 343 insertions(+), 323 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/siano/smscoreapi.c b/linux/drivers/media/dvb/siano/smscoreapi.c index 9a9db2588..15272dbb5 100644 --- a/linux/drivers/media/dvb/siano/smscoreapi.c +++ b/linux/drivers/media/dvb/siano/smscoreapi.c @@ -904,15 +904,11 @@ smscore_client_t *smscore_find_client(struct smscore_device_t *coredev, * */ void smscore_onresponse(struct smscore_device_t *coredev, - struct smscore_buffer_t *cb) -{ - struct SmsMsgHdr_ST *phdr = - (struct SmsMsgHdr_ST *)((u8 *) cb->p + cb->offset); - struct smscore_client_t *client = - smscore_find_client(coredev, phdr->msgType, phdr->msgDstId); + struct smscore_buffer_t *cb) { + struct SmsMsgHdr_ST *phdr = (struct SmsMsgHdr_ST *) ((u8 *) cb->p + + cb->offset); + struct smscore_client_t *client; int rc = -EBUSY; - -#if 1 static unsigned long last_sample_time; /* = 0; */ static int data_total; /* = 0; */ unsigned long time_now = jiffies_to_msecs(jiffies); @@ -930,7 +926,16 @@ void smscore_onresponse(struct smscore_device_t *coredev, } data_total += cb->size; -#endif + /* Do we need to re-route? */ + if ((phdr->msgType == MSG_SMS_HO_PER_SLICES_IND) || + (phdr->msgType == MSG_SMS_TRANSMISSION_IND)) { + if (coredev->mode == DEVICE_MODE_DVBT_BDA) + phdr->msgDstId = DVBT_BDA_CONTROL_MSG_ID; + } + + + client = smscore_find_client(coredev, phdr->msgType, phdr->msgDstId); + /* If no client registered for type & id, * check for control client where type is not registered */ if (client) diff --git a/linux/drivers/media/dvb/siano/smscoreapi.h b/linux/drivers/media/dvb/siano/smscoreapi.h index 72e385c05..d98b4a749 100644 --- a/linux/drivers/media/dvb/siano/smscoreapi.h +++ b/linux/drivers/media/dvb/siano/smscoreapi.h @@ -214,19 +214,15 @@ struct smscore_device_t { #define MSG_SMS_INIT_DEVICE_RES 579 #define MSG_SMS_ADD_PID_FILTER_REQ 601 #define MSG_SMS_ADD_PID_FILTER_RES 602 -#define MSG_SMS_REMOVE_PID_FILTER_REQ 603 -#define MSG_SMS_REMOVE_PID_FILTER_RES 604 -#define MSG_SMS_DAB_CHANNEL 607 -#define MSG_SMS_GET_PID_FILTER_LIST_REQ 608 -#define MSG_SMS_GET_PID_FILTER_LIST_RES 609 -#define MSG_SMS_GET_STATISTICS_REQ 615 -#define MSG_SMS_GET_STATISTICS_RES 616 +#define MSG_SMS_REMOVE_PID_FILTER_REQ 603 +#define MSG_SMS_REMOVE_PID_FILTER_RES 604 +#define MSG_SMS_DAB_CHANNEL 607 +#define MSG_SMS_GET_PID_FILTER_LIST_REQ 608 +#define MSG_SMS_GET_PID_FILTER_LIST_RES 609 #define MSG_SMS_HO_PER_SLICES_IND 630 -#define MSG_SMS_SET_ANTENNA_CONFIG_REQ 651 -#define MSG_SMS_SET_ANTENNA_CONFIG_RES 652 -#define MSG_SMS_GET_STATISTICS_EX_REQ 653 -#define MSG_SMS_GET_STATISTICS_EX_RES 654 -#define MSG_SMS_SLEEP_RESUME_COMP_IND 655 +#define MSG_SMS_SET_ANTENNA_CONFIG_REQ 651 +#define MSG_SMS_SET_ANTENNA_CONFIG_RES 652 +#define MSG_SMS_SLEEP_RESUME_COMP_IND 655 #define MSG_SMS_DATA_DOWNLOAD_REQ 660 #define MSG_SMS_DATA_DOWNLOAD_RES 661 #define MSG_SMS_SWDOWNLOAD_TRIGGER_REQ 664 @@ -348,225 +344,202 @@ struct SmsFirmware_ST { u8 Payload[1]; }; -struct SMSHOSTLIB_STATISTICS_ST { - u32 Reserved; /* Reserved */ +/* Statistics information returned as response for + * SmsHostApiGetStatistics_Req */ +struct SMSHOSTLIB_STATISTICS_S { + u32 Reserved; /* Reserved */ /* Common parameters */ - u32 IsRfLocked; /* 0 - not locked, 1 - locked */ - u32 IsDemodLocked; /* 0 - not locked, 1 - locked */ - u32 IsExternalLNAOn; /* 0 - external LNA off, 1 - external LNA on */ + u32 IsRfLocked; /* 0 - not locked, 1 - locked */ + u32 IsDemodLocked; /* 0 - not locked, 1 - locked */ + u32 IsExternalLNAOn; /* 0 - external LNA off, 1 - external LNA on */ /* Reception quality */ - s32 SNR; /* dB */ - u32 BER; /* Post Viterbi BER [1E-5] */ - u32 FIB_CRC; /* CRC errors percentage, valid only for DAB */ - /* Transport stream PER, 0xFFFFFFFF indicate N/A, - * valid only for DVB-T/H */ - u32 TS_PER; - /* DVB-H frame error rate in percentage, - * 0xFFFFFFFF indicate N/A, valid only for DVB-H */ - u32 MFER; - s32 RSSI; /* dBm */ - s32 InBandPwr; /* In band power in dBM */ - s32 CarrierOffset; /* Carrier Offset in bin/1024 */ - - /* Transmission parameters, valid only for DVB-T/H */ - u32 Frequency; /* Frequency in Hz */ - u32 Bandwidth; /* Bandwidth in MHz */ - /* Transmission Mode, for DAB modes 1-4, - * for DVB-T/H FFT mode carriers in Kilos */ - u32 TransmissionMode; - u32 ModemState; /* from SMS_DvbModemState_ET */ - u32 GuardInterval; /* Guard Interval, 1 divided by value */ - u32 CodeRate; /* Code Rate from SMS_DvbModemState_ET */ - u32 LPCodeRate; /* Low Priority Code Rate from SMS_DvbModemState_ET */ - u32 Hierarchy; /* Hierarchy from SMS_Hierarchy_ET */ - u32 Constellation; /* Constellation from SMS_Constellation_ET */ + s32 SNR; /* dB */ + u32 BER; /* Post Viterbi BER [1E-5] */ + u32 FIB_CRC; /* CRC errors percentage, valid only for DAB */ + u32 TS_PER; /* Transport stream PER, + 0xFFFFFFFF indicate N/A, valid only for DVB-T/H */ + u32 MFER; /* DVB-H frame error rate in percentage, + 0xFFFFFFFF indicate N/A, valid only for DVB-H */ + s32 RSSI; /* dBm */ + s32 InBandPwr; /* In band power in dBM */ + s32 CarrierOffset; /* Carrier Offset in bin/1024 */ - /* Burst parameters, valid only for DVB-H */ - u32 BurstSize; /* Current burst size in bytes */ - u32 BurstDuration; /* Current burst duration in mSec */ - u32 BurstCycleTime; /* Current burst cycle time in mSec */ - u32 CalculatedBurstCycleTime; /* Current burst cycle time in mSec, - * as calculated by demodulator */ - u32 NumOfRows; /* Number of rows in MPE table */ - u32 NumOfPaddCols; /* Number of padding columns in MPE table */ - u32 NumOfPunctCols; /* Number of puncturing columns in MPE table */ - /* Burst parameters */ - u32 ErrorTSPackets; /* Number of erroneous transport-stream packets */ - u32 TotalTSPackets; /* Total number of transport-stream packets */ - u32 NumOfValidMpeTlbs; /* Number of MPE tables which do not include - * errors after MPE RS decoding */ - u32 NumOfInvalidMpeTlbs; /* Number of MPE tables which include errors - * after MPE RS decoding */ - u32 NumOfCorrectedMpeTlbs; /* Number of MPE tables which were corrected - * by MPE RS decoding */ + /* Transmission parameters */ + u32 Frequency; /* Frequency in Hz */ + u32 Bandwidth; /* Bandwidth in MHz, valid only for DVB-T/H */ + u32 TransmissionMode; /* Transmission Mode, for DAB modes 1-4, + for DVB-T/H FFT mode carriers in Kilos */ + u32 ModemState; /* from SMSHOSTLIB_DVB_MODEM_STATE_ET, + valid only for DVB-T/H */ + u32 GuardInterval; /* Guard Interval from + SMSHOSTLIB_GUARD_INTERVALS_ET, valid only for DVB-T/H */ + u32 CodeRate; /* Code Rate from SMSHOSTLIB_CODE_RATE_ET, + valid only for DVB-T/H */ + u32 LPCodeRate; /* Low Priority Code Rate from + SMSHOSTLIB_CODE_RATE_ET, valid only for DVB-T/H */ + u32 Hierarchy; /* Hierarchy from SMSHOSTLIB_HIERARCHY_ET, + valid only for DVB-T/H */ + u32 Constellation; /* Constellation from + SMSHOSTLIB_CONSTELLATION_ET, valid only for DVB-T/H */ + /* Burst parameters, valid only for DVB-H */ + u32 BurstSize; /* Current burst size in bytes, + valid only for DVB-H */ + u32 BurstDuration; /* Current burst duration in mSec, + valid only for DVB-H */ + u32 BurstCycleTime; /* Current burst cycle time in mSec, + valid only for DVB-H */ + u32 CalculatedBurstCycleTime;/* Current burst cycle time in mSec, + as calculated by demodulator, valid only for DVB-H */ + u32 NumOfRows; /* Number of rows in MPE table, + valid only for DVB-H */ + u32 NumOfPaddCols; /* Number of padding columns in MPE table, + valid only for DVB-H */ + u32 NumOfPunctCols; /* Number of puncturing columns in MPE table, + valid only for DVB-H */ + u32 ErrorTSPackets; /* Number of erroneous + transport-stream packets */ + u32 TotalTSPackets; /* Total number of transport-stream packets */ + u32 NumOfValidMpeTlbs; /* Number of MPE tables which do not include + errors after MPE RS decoding */ + u32 NumOfInvalidMpeTlbs;/* Number of MPE tables which include errors + after MPE RS decoding */ + u32 NumOfCorrectedMpeTlbs;/* Number of MPE tables which were + corrected by MPE RS decoding */ /* Common params */ - u32 BERErrorCount; /* Number of errornous SYNC bits. */ - u32 BERBitCount; /* Total number of SYNC bits. */ + u32 BERErrorCount; /* Number of errornous SYNC bits. */ + u32 BERBitCount; /* Total number of SYNC bits. */ /* Interface information */ - u32 SmsToHostTxErrors; /* Total number of transmission errors. */ + u32 SmsToHostTxErrors; /* Total number of transmission errors. */ /* DAB/T-DMB */ - u32 PreBER; /* DAB/T-DMB only: Pre Viterbi BER [1E-5] */ + u32 PreBER; /* DAB/T-DMB only: Pre Viterbi BER [1E-5] */ /* DVB-H TPS parameters */ - u32 CellId; /* TPS Cell ID in bits 15..0, bits 31..16 zero; - * if set to 0xFFFFFFFF cell_id not yet recovered */ - -}; - -struct SmsMsgStatisticsInfo_ST { - u32 RequestResult; - - struct SMSHOSTLIB_STATISTICS_ST Stat; + u32 CellId; /* TPS Cell ID in bits 15..0, bits 31..16 zero; + if set to 0xFFFFFFFF cell_id not yet recovered */ + u32 DvbhSrvIndHP; /* DVB-H service indication info, bit 1 - + Time Slicing indicator, bit 0 - MPE-FEC indicator */ + u32 DvbhSrvIndLP; /* DVB-H service indication info, bit 1 - + Time Slicing indicator, bit 0 - MPE-FEC indicator */ - /* Split the calc of the SNR in DAB */ - u32 Signal; /* dB */ - u32 Noise; /* dB */ + u32 NumMPEReceived; /* DVB-H, Num MPE section received */ + u32 ReservedFields[10]; /* Reserved */ }; -#if 0 -struct SMSHOSTLIB_ISDBT_LAYER_STAT_ST { - /* Per-layer information */ - u32 CodeRate; /* Code Rate from SMSHOSTLIB_CODE_RATE_ET, - * 255 means layer does not exist */ - u32 Constellation; /* Constellation from SMSHOSTLIB_CONSTELLATION_ET, - * 255 means layer does not exist */ - u32 BER; /* Post Viterbi BER [1E-5], 0xFFFFFFFF indicate N/A */ - u32 BERErrorCount; /* Post Viterbi Error Bits Count */ - u32 BERBitCount; /* Post Viterbi Total Bits Count */ - u32 PreBER; /* Pre Viterbi BER [1E-5], 0xFFFFFFFF indicate N/A */ - u32 TS_PER; /* Transport stream PER [%], 0xFFFFFFFF indicate N/A */ - u32 ErrorTSPackets; /* Number of erroneous transport-stream packets */ - u32 TotalTSPackets; /* Total number of transport-stream packets */ - u32 TILdepthI; /* Time interleaver depth I parameter, - * 255 means layer does not exist */ - u32 NumberOfSegments; /* Number of segments in layer A, - * 255 means layer does not exist */ - u32 TMCCErrors; /* TMCC errors */ +struct PID_STATISTICS_DATA_S { + struct PID_BURST_S { + u32 size; + u32 padding_cols; + u32 punct_cols; + u32 duration; + u32 cycle; + u32 calc_cycle; + } burst; + + u32 tot_tbl_cnt; + u32 invalid_tbl_cnt; + u32 tot_cor_tbl; }; -struct SMSHOSTLIB_STATISTICS_ISDBT_ST { - u32 StatisticsType; /* Enumerator identifying the type of the - * structure. Values are the same as - * SMSHOSTLIB_DEVICE_MODES_E - * - * This field MUST always be first in any - * statistics structure */ - - u32 FullSize; /* Total size of the structure returned by the modem. - * If the size requested by the host is smaller than - * FullSize, the struct will be truncated */ - - /* Common parameters */ - u32 IsRfLocked; /* 0 - not locked, 1 - locked */ - u32 IsDemodLocked; /* 0 - not locked, 1 - locked */ - u32 IsExternalLNAOn; /* 0 - external LNA off, 1 - external LNA on */ - - /* Reception quality */ - s32 SNR; /* dB */ - s32 RSSI; /* dBm */ - s32 InBandPwr; /* In band power in dBM */ - s32 CarrierOffset; /* Carrier Offset in Hz */ - - /* Transmission parameters */ - u32 Frequency; /* Frequency in Hz */ - u32 Bandwidth; /* Bandwidth in MHz */ - u32 TransmissionMode; /* ISDB-T transmission mode */ - u32 ModemState; /* 0 - Acquisition, 1 - Locked */ - u32 GuardInterval; /* Guard Interval, 1 divided by value */ - u32 SystemType; /* ISDB-T system type (ISDB-T / ISDB-Tsb) */ - u32 PartialReception; /* TRUE - partial reception, FALSE otherwise */ - u32 NumOfLayers; /* Number of ISDB-T layers in the network */ - - /* Per-layer information */ - /* Layers A, B and C */ - struct SMSHOSTLIB_ISDBT_LAYER_STAT_ST LayerInfo[3]; - /* Per-layer statistics, see SMSHOSTLIB_ISDBT_LAYER_STAT_ST */ +struct PID_DATA_S { + u32 pid; + u32 num_rows; + struct PID_STATISTICS_DATA_S pid_statistics; +}; - /* Interface information */ - u32 SmsToHostTxErrors; /* Total number of transmission errors. */ +#define CORRECT_STAT_RSSI(_stat) ((_stat).RSSI *= -1) +#define CORRECT_STAT_BANDWIDTH(_stat) (_stat.Bandwidth = 8 - _stat.Bandwidth) +#define CORRECT_STAT_TRANSMISSON_MODE(_stat) \ + if (_stat.TransmissionMode == 0) \ + _stat.TransmissionMode = 2; \ + else if (_stat.TransmissionMode == 1) \ + _stat.TransmissionMode = 8; \ + else \ + _stat.TransmissionMode = 4; + +struct TRANSMISSION_STATISTICS_S { + u32 Frequency; /* Frequency in Hz */ + u32 Bandwidth; /* Bandwidth in MHz */ + u32 TransmissionMode; /* FFT mode carriers in Kilos */ + u32 GuardInterval; /* Guard Interval from + SMSHOSTLIB_GUARD_INTERVALS_ET */ + u32 CodeRate; /* Code Rate from SMSHOSTLIB_CODE_RATE_ET */ + u32 LPCodeRate; /* Low Priority Code Rate from + SMSHOSTLIB_CODE_RATE_ET */ + u32 Hierarchy; /* Hierarchy from SMSHOSTLIB_HIERARCHY_ET */ + u32 Constellation; /* Constellation from + SMSHOSTLIB_CONSTELLATION_ET */ + /* DVB-H TPS parameters */ + u32 CellId; /* TPS Cell ID in bits 15..0, bits 31..16 zero; + if set to 0xFFFFFFFF cell_id not yet recovered */ + u32 DvbhSrvIndHP; /* DVB-H service indication info, bit 1 - + Time Slicing indicator, bit 0 - MPE-FEC indicator */ + u32 DvbhSrvIndLP; /* DVB-H service indication info, bit 1 - + Time Slicing indicator, bit 0 - MPE-FEC indicator */ + u32 IsDemodLocked; /* 0 - not locked, 1 - locked */ }; -struct SMSHOSTLIB_STATISTICS_DVB_ST { - u32 StatisticsType; /* Enumerator identifying the type of the - * structure. Values are the same as - * SMSHOSTLIB_DEVICE_MODES_E - * This field MUST always first in any - * statistics structure */ +struct RECEPTION_STATISTICS_S { + u32 IsRfLocked; /* 0 - not locked, 1 - locked */ + u32 IsDemodLocked; /* 0 - not locked, 1 - locked */ + u32 IsExternalLNAOn; /* 0 - external LNA off, 1 - external LNA on */ + + u32 ModemState; /* from SMSHOSTLIB_DVB_MODEM_STATE_ET */ + s32 SNR; /* dB */ + u32 BER; /* Post Viterbi BER [1E-5] */ + u32 BERErrorCount; /* Number of erronous SYNC bits. */ + u32 BERBitCount; /* Total number of SYNC bits. */ + u32 TS_PER; /* Transport stream PER, + 0xFFFFFFFF indicate N/A */ + u32 MFER; /* DVB-H frame error rate in percentage, + 0xFFFFFFFF indicate N/A, valid only for DVB-H */ + s32 RSSI; /* dBm */ + s32 InBandPwr; /* In band power in dBM */ + s32 CarrierOffset; /* Carrier Offset in bin/1024 */ + u32 ErrorTSPackets; /* Number of erroneous + transport-stream packets */ + u32 TotalTSPackets; /* Total number of transport-stream packets */ + + s32 MRC_SNR; /* dB */ + s32 MRC_RSSI; /* dBm */ + s32 MRC_InBandPwr; /* In band power in dBM */ +}; - u32 FullSize; /* Total size of the structure returned by the modem. - * If the size requested by the host is smaller than - * FullSize, the struct will be truncated */ - /* Common parameters */ - u32 IsRfLocked; /* 0 - not locked, 1 - locked */ - u32 IsDemodLocked; /* 0 - not locked, 1 - locked */ - u32 IsExternalLNAOn; /* 0 - external LNA off, 1 - external LNA on */ - /* Reception quality */ - s32 SNR; /* dB */ - u32 BER; /* Post Viterbi BER [1E-5] */ - u32 BERErrorCount; /* Number of errornous SYNC bits. */ - u32 BERBitCount; /* Total number of SYNC bits. */ - u32 TS_PER; /* Transport stream PER, 0xFFFFFFFF indicate N/A */ - u32 MFER; /* DVB-H frame error rate in percentage, - * 0xFFFFFFFF indicate N/A, valid only for DVB-H */ - s32 RSSI; /* dBm */ - s32 InBandPwr; /* In band power in dBM */ - s32 CarrierOffset; /* Carrier Offset in bin/1024 */ +/* Statistics information returned as response for + * SmsHostApiGetStatisticsEx_Req for DVB applications, SMS1100 and up */ +struct SMSHOSTLIB_STATISTICS_DVB_S { + /* Reception */ + struct RECEPTION_STATISTICS_S ReceptionData; /* Transmission parameters */ - u32 Frequency; /* Frequency in Hz */ - u32 Bandwidth; /* Bandwidth in MHz */ - u32 ModemState; /* from SMSHOSTLIB_DVB_MODEM_STATE_ET */ - u32 TransmissionMode; /* FFT mode carriers in Kilos */ - u32 GuardInterval; /* Guard Interval, 1 divided by value */ - u32 CodeRate; /* Code Rate from SMSHOSTLIB_CODE_RATE_ET */ - u32 LPCodeRate; /* Low Priority Code Rate from - * SMSHOSTLIB_CODE_RATE_ET */ - u32 Hierarchy; /* Hierarchy from SMSHOSTLIB_HIERARCHY_ET */ - u32 Constellation; /* Constellation from SMSHOSTLIB_CONSTELLATION_ET */ + struct TRANSMISSION_STATISTICS_S TransmissionData; /* Burst parameters, valid only for DVB-H */ - u32 BurstSize; /* Current burst size in bytes */ - u32 BurstDuration; /* Current burst duration in mSec */ - u32 BurstCycleTime; /* Current burst cycle time in mSec */ - u32 CalculatedBurstCycleTime; /* Current burst cycle time in mSec, - * as calculated by demodulator */ - u32 NumOfRows; /* Number of rows in MPE table */ - u32 NumOfPaddCols; /* Number of padding columns in MPE table */ - u32 NumOfPunctCols; /* Number of puncturing columns in MPE table */ - - u32 ErrorTSPackets; /* Number of erroneous transport-stream packets */ - u32 TotalTSPackets; /* Total number of transport-stream packets */ - - u32 NumOfValidMpeTlbs; /* Number of MPE tables which do not include - * errors after MPE RS decoding */ - u32 NumOfInvalidMpeTlbs; /* Number of MPE tables which include - * errors after MPE RS decoding */ - u32 NumOfCorrectedMpeTlbs; /* Number of MPE tables which were - * corrected by MPE RS decoding */ - - u32 NumMPEReceived; /* DVB-H, Num MPE section received */ - - /* DVB-H TPS parameters */ - u32 CellId; /* TPS Cell ID in bits 15..0, bits 31..16 zero; - * if set to 0xFFFFFFFF cell_id not yet recovered */ - u32 DvbhSrvIndHP; /* DVB-H service indication info, - * bit 1 - Time Slicing indicator, - * bit 0 - MPE-FEC indicator */ - u32 DvbhSrvIndLP; /* DVB-H service indication info, - * bit 1 - Time Slicing indicator, - * bit 0 - MPE-FEC indicator */ - - /* Interface information */ - u32 SmsToHostTxErrors; /* Total number of transmission errors. */ +#define SRVM_MAX_PID_FILTERS 8 + struct PID_DATA_S PidData[SRVM_MAX_PID_FILTERS]; +}; +struct SRVM_SIGNAL_STATUS_S { + u32 result; + u32 snr; + u32 tsPackets; + u32 etsPackets; + u32 constellation; + u32 hpCode; + u32 tpsSrvIndLP; + u32 tpsSrvIndHP; + u32 cellId; + u32 reason; + + s32 inBandPower; + u32 requestId; }; struct SMSHOSTLIB_I2C_REQ_ST { @@ -581,7 +554,7 @@ struct SMSHOSTLIB_I2C_RES_ST { u32 ReadCount; /* number of bytes read */ u8 Data[1]; }; -#endif + struct smscore_gpio_config { #define SMS_GPIO_DIRECTION_INPUT 0 diff --git a/linux/drivers/media/dvb/siano/smsdvb.c b/linux/drivers/media/dvb/siano/smsdvb.c index b69bd77cb..f265b148f 100644 --- a/linux/drivers/media/dvb/siano/smsdvb.c +++ b/linux/drivers/media/dvb/siano/smsdvb.c @@ -40,12 +40,15 @@ struct smsdvb_client_t { struct dvb_frontend frontend; fe_status_t fe_status; - int fe_ber, fe_snr, fe_unc, fe_signal_strength; - struct completion tune_done, stat_done; + struct completion tune_done; /* todo: save freq/band instead whole struct */ struct dvb_frontend_parameters fe_params; + + struct SMSHOSTLIB_STATISTICS_DVB_S sms_stat_dvb; + int event_fe_state; + int event_unc_state; }; static struct list_head g_smsdvb_clients; @@ -55,11 +58,19 @@ static int sms_dbg; module_param_named(debug, sms_dbg, int, 0644); MODULE_PARM_DESC(debug, "set debug level (info=1, adv=2 (or-able))"); +/* Events that may come from DVB v3 adapter */ +static void sms_board_dvb3_event(struct smsdvb_client_t *client, + enum SMS_DVB3_EVENTS event) { +} + static int smsdvb_onresponse(void *context, struct smscore_buffer_t *cb) { struct smsdvb_client_t *client = (struct smsdvb_client_t *) context; - struct SmsMsgHdr_ST *phdr = - (struct SmsMsgHdr_ST *)(((u8 *) cb->p) + cb->offset); + struct SmsMsgHdr_ST *phdr = (struct SmsMsgHdr_ST *) (((u8 *) cb->p) + + cb->offset); + u32 *pMsgData = (u32 *) phdr + 1; + /*u32 MsgDataLen = phdr->msgLength - sizeof(struct SmsMsgHdr_ST);*/ + bool is_status_update = false; smsendian_handle_rx_message((struct SmsMsgData_ST *) phdr); @@ -73,43 +84,110 @@ static int smsdvb_onresponse(void *context, struct smscore_buffer_t *cb) complete(&client->tune_done); break; - case MSG_SMS_GET_STATISTICS_RES: - { - struct SmsMsgStatisticsInfo_ST *p = - (struct SmsMsgStatisticsInfo_ST *)(phdr + 1); - - if (p->Stat.IsDemodLocked) { - client->fe_status = FE_HAS_SIGNAL | - FE_HAS_CARRIER | - FE_HAS_VITERBI | - FE_HAS_SYNC | - FE_HAS_LOCK; - - client->fe_snr = p->Stat.SNR; - client->fe_ber = p->Stat.BER; - client->fe_unc = p->Stat.BERErrorCount; - - if (p->Stat.InBandPwr < -95) - client->fe_signal_strength = 0; - else if (p->Stat.InBandPwr > -29) - client->fe_signal_strength = 100; - else - client->fe_signal_strength = - (p->Stat.InBandPwr + 95) * 3 / 2; + case MSG_SMS_SIGNAL_DETECTED_IND: + sms_info("MSG_SMS_SIGNAL_DETECTED_IND"); + client->sms_stat_dvb.TransmissionData.IsDemodLocked = true; + is_status_update = true; + break; + + case MSG_SMS_NO_SIGNAL_IND: + sms_info("MSG_SMS_NO_SIGNAL_IND"); + client->sms_stat_dvb.TransmissionData.IsDemodLocked = false; + is_status_update = true; + break; + + case MSG_SMS_TRANSMISSION_IND: { + sms_info("MSG_SMS_TRANSMISSION_IND"); + + pMsgData++; + memcpy(&client->sms_stat_dvb.TransmissionData, pMsgData, + sizeof(struct TRANSMISSION_STATISTICS_S)); + + /* Mo need to correct guard interval + * (as opposed to old statistics message). + */ + CORRECT_STAT_BANDWIDTH(client->sms_stat_dvb.TransmissionData); + CORRECT_STAT_TRANSMISSON_MODE( + client->sms_stat_dvb.TransmissionData); + is_status_update = true; + break; + } + case MSG_SMS_HO_PER_SLICES_IND: { + struct RECEPTION_STATISTICS_S *pReceptionData = + &client->sms_stat_dvb.ReceptionData; + struct SRVM_SIGNAL_STATUS_S SignalStatusData; + + /*sms_info("MSG_SMS_HO_PER_SLICES_IND");*/ + pMsgData++; + SignalStatusData.result = pMsgData[0]; + SignalStatusData.snr = pMsgData[1]; + SignalStatusData.inBandPower = (s32) pMsgData[2]; + SignalStatusData.tsPackets = pMsgData[3]; + SignalStatusData.etsPackets = pMsgData[4]; + SignalStatusData.constellation = pMsgData[5]; + SignalStatusData.hpCode = pMsgData[6]; + SignalStatusData.tpsSrvIndLP = pMsgData[7] & 0x03; + SignalStatusData.tpsSrvIndHP = pMsgData[8] & 0x03; + SignalStatusData.cellId = pMsgData[9] & 0xFFFF; + SignalStatusData.reason = pMsgData[10]; + SignalStatusData.requestId = pMsgData[11]; + pReceptionData->IsRfLocked = pMsgData[16]; + pReceptionData->IsDemodLocked = pMsgData[17]; + pReceptionData->ModemState = pMsgData[12]; + pReceptionData->SNR = pMsgData[1]; + pReceptionData->BER = pMsgData[13]; + pReceptionData->RSSI = pMsgData[14]; + CORRECT_STAT_RSSI(client->sms_stat_dvb.ReceptionData); + + pReceptionData->InBandPwr = (s32) pMsgData[2]; + pReceptionData->CarrierOffset = (s32) pMsgData[15]; + pReceptionData->TotalTSPackets = pMsgData[3]; + pReceptionData->ErrorTSPackets = pMsgData[4]; + + /* TS PER */ + if ((SignalStatusData.tsPackets + SignalStatusData.etsPackets) + > 0) { + pReceptionData->TS_PER = (SignalStatusData.etsPackets + * 100) / (SignalStatusData.tsPackets + + SignalStatusData.etsPackets); } else { - client->fe_status = 0; - client->fe_snr = - client->fe_ber = - client->fe_unc = - client->fe_signal_strength = 0; + pReceptionData->TS_PER = 0; } - complete(&client->stat_done); - break; - } } + pReceptionData->BERBitCount = pMsgData[18]; + pReceptionData->BERErrorCount = pMsgData[19]; + pReceptionData->MRC_SNR = pMsgData[20]; + pReceptionData->MRC_InBandPwr = pMsgData[21]; + pReceptionData->MRC_RSSI = pMsgData[22]; + + is_status_update = true; + break; + } + } smscore_putbuffer(client->coredev, cb); + if (is_status_update) { + if (client->sms_stat_dvb.ReceptionData.IsDemodLocked) { + client->fe_status = FE_HAS_SIGNAL | FE_HAS_CARRIER + | FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK; + sms_board_dvb3_event(client, DVB3_EVENT_FE_LOCK); + if (client->sms_stat_dvb.ReceptionData.ErrorTSPackets + == 0) + sms_board_dvb3_event(client, DVB3_EVENT_UNC_OK); + else + sms_board_dvb3_event(client, + DVB3_EVENT_UNC_ERR); + + } else { + /*client->fe_status = + (phdr->msgType == MSG_SMS_NO_SIGNAL_IND) ? + 0 : FE_HAS_SIGNAL;*/ + client->fe_status = 0; + sms_board_dvb3_event(client, DVB3_EVENT_FE_UNLOCK); + } + } + return 0; } @@ -194,83 +272,61 @@ static int smsdvb_sendrequest_and_wait(struct smsdvb_client_t *client, 0 : -ETIME; } -static int smsdvb_send_statistics_request(struct smsdvb_client_t *client) -{ - struct SmsMsgHdr_ST Msg = { MSG_SMS_GET_STATISTICS_REQ, - DVBT_BDA_CONTROL_MSG_ID, - HIF_TASK, sizeof(struct SmsMsgHdr_ST), 0 }; - int ret = smsdvb_sendrequest_and_wait(client, &Msg, sizeof(Msg), - &client->stat_done); - if (ret < 0) - return ret; - - if (client->fe_status & FE_HAS_LOCK) - sms_board_led_feedback(client->coredev, - (client->fe_unc == 0) ? - SMS_LED_HI : SMS_LED_LO); - else - sms_board_led_feedback(client->coredev, SMS_LED_OFF); - return ret; -} - static int smsdvb_read_status(struct dvb_frontend *fe, fe_status_t *stat) { - struct smsdvb_client_t *client = - container_of(fe, struct smsdvb_client_t, frontend); - int rc = smsdvb_send_statistics_request(client); + struct smsdvb_client_t *client; + client = container_of(fe, struct smsdvb_client_t, frontend); - if (!rc) - *stat = client->fe_status; + *stat = client->fe_status; - return rc; + return 0; } static int smsdvb_read_ber(struct dvb_frontend *fe, u32 *ber) { - struct smsdvb_client_t *client = - container_of(fe, struct smsdvb_client_t, frontend); - int rc = smsdvb_send_statistics_request(client); + struct smsdvb_client_t *client; + client = container_of(fe, struct smsdvb_client_t, frontend); - if (!rc) - *ber = client->fe_ber; + *ber = client->sms_stat_dvb.ReceptionData.BER; - return rc; + return 0; } static int smsdvb_read_signal_strength(struct dvb_frontend *fe, u16 *strength) { - struct smsdvb_client_t *client = - container_of(fe, struct smsdvb_client_t, frontend); - int rc = smsdvb_send_statistics_request(client); + struct smsdvb_client_t *client; + client = container_of(fe, struct smsdvb_client_t, frontend); - if (!rc) - *strength = client->fe_signal_strength; + if (client->sms_stat_dvb.ReceptionData.InBandPwr < -95) + *strength = 0; + else if (client->sms_stat_dvb.ReceptionData.InBandPwr > -29) + *strength = 100; + else + *strength = + (client->sms_stat_dvb.ReceptionData.InBandPwr + + 95) * 3 / 2; - return rc; + return 0; } static int smsdvb_read_snr(struct dvb_frontend *fe, u16 *snr) { - struct smsdvb_client_t *client = - container_of(fe, struct smsdvb_client_t, frontend); - int rc = smsdvb_send_statistics_request(client); + struct smsdvb_client_t *client; + client = container_of(fe, struct smsdvb_client_t, frontend); - if (!rc) - *snr = client->fe_snr; + *snr = client->sms_stat_dvb.ReceptionData.SNR; - return rc; + return 0; } static int smsdvb_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) { - struct smsdvb_client_t *client = - container_of(fe, struct smsdvb_client_t, frontend); - int rc = smsdvb_send_statistics_request(client); + struct smsdvb_client_t *client; + client = container_of(fe, struct smsdvb_client_t, frontend); - if (!rc) - *ucblocks = client->fe_unc; + *ucblocks = client->sms_stat_dvb.ReceptionData.ErrorTSPackets; - return rc; + return 0; } static int smsdvb_get_tune_settings(struct dvb_frontend *fe, @@ -294,12 +350,15 @@ static int smsdvb_set_frontend(struct dvb_frontend *fe, struct SmsMsgHdr_ST Msg; u32 Data[3]; } Msg; - int ret; - Msg.Msg.msgSrcId = DVBT_BDA_CONTROL_MSG_ID; - Msg.Msg.msgDstId = HIF_TASK; - Msg.Msg.msgFlags = 0; - Msg.Msg.msgType = MSG_SMS_RF_TUNE_REQ; + client->fe_status = FE_HAS_SIGNAL; + client->event_fe_state = -1; + client->event_unc_state = -1; + + Msg.Msg.msgSrcId = DVBT_BDA_CONTROL_MSG_ID; + Msg.Msg.msgDstId = HIF_TASK; + Msg.Msg.msgFlags = 0; + Msg.Msg.msgType = MSG_SMS_RF_TUNE_REQ; Msg.Msg.msgLength = sizeof(Msg); Msg.Data[0] = fep->frequency; Msg.Data[2] = 12000000; @@ -318,24 +377,6 @@ static int smsdvb_set_frontend(struct dvb_frontend *fe, default: return -EINVAL; } - /* Disable LNA, if any. An error is returned if no LNA is present */ - ret = sms_board_lna_control(client->coredev, 0); - if (ret == 0) { - fe_status_t status; - - /* tune with LNA off at first */ - ret = smsdvb_sendrequest_and_wait(client, &Msg, sizeof(Msg), - &client->tune_done); - - smsdvb_read_status(fe, &status); - - if (status & FE_HAS_LOCK) - return ret; - - /* previous tune didnt lock - enable LNA and tune again */ - sms_board_lna_control(client->coredev, 1); - } - return smsdvb_sendrequest_and_wait(client, &Msg, sizeof(Msg), &client->tune_done); } @@ -360,8 +401,7 @@ static int smsdvb_init(struct dvb_frontend *fe) struct smsdvb_client_t *client = container_of(fe, struct smsdvb_client_t, frontend); - sms_board_power(client->coredev, 1); - + sms_board_dvb3_event(client, DVB3_EVENT_INIT); return 0; } @@ -370,8 +410,7 @@ static int smsdvb_sleep(struct dvb_frontend *fe) struct smsdvb_client_t *client = container_of(fe, struct smsdvb_client_t, frontend); - sms_board_led_feedback(client->coredev, SMS_LED_OFF); - sms_board_power(client->coredev, 0); + sms_board_dvb3_event(client, DVB3_EVENT_SLEEP); return 0; } @@ -503,8 +542,11 @@ static int smsdvb_hotplug(struct smscore_device_t *coredev, kmutex_unlock(&g_smsdvb_clientslock); - sms_info("success"); + client->event_fe_state = -1; + client->event_unc_state = -1; + sms_board_dvb3_event(client, DVB3_EVENT_HOTPLUG); + sms_info("success"); sms_board_setup(coredev); return 0; -- cgit v1.2.3 From dac2a57af684d3f1fd146a0b84a559c011d84102 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 12 May 2009 16:13:13 +0000 Subject: Siano: smsdvb - small typo fix ad module author From: Uri Shkolnik Fix type at the module description Priority: normal Signed-off-by: Uri Shkolnik Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/siano/smsdvb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/siano/smsdvb.c b/linux/drivers/media/dvb/siano/smsdvb.c index f265b148f..f43c7f543 100644 --- a/linux/drivers/media/dvb/siano/smsdvb.c +++ b/linux/drivers/media/dvb/siano/smsdvb.c @@ -599,5 +599,5 @@ module_init(smsdvb_module_init); module_exit(smsdvb_module_exit); MODULE_DESCRIPTION("SMS DVB subsystem adaptation module"); -MODULE_AUTHOR("Siano Mobile Silicon, INC. (uris@siano-ms.com)"); +MODULE_AUTHOR("Siano Mobile Silicon, Inc. (uris@siano-ms.com)"); MODULE_LICENSE("GPL"); -- 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 ccc187959eea7ba618103cb5f4c88ef6e2c92889 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Wed, 13 May 2009 19:21:46 +0200 Subject: gspca - spca508: Cleanup source and update copyright. From: Jean-Francois Moine Priority: normal Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/spca508.c | 1901 ++++++++++++++--------------- 1 file changed, 888 insertions(+), 1013 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/spca508.c b/linux/drivers/media/video/gspca/spca508.c index e3afc9e7f..d24d9d4aa 100644 --- a/linux/drivers/media/video/gspca/spca508.c +++ b/linux/drivers/media/video/gspca/spca508.c @@ -1,7 +1,7 @@ /* * SPCA508 chip based cameras subdriver * - * V4L2 by Jean-Francois Moine + * Copyright (C) 2009 Jean-Francois Moine * * 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 @@ -30,9 +30,9 @@ MODULE_LICENSE("GPL"); struct sd { struct gspca_dev gspca_dev; /* !! must be the first item */ - unsigned char brightness; + u8 brightness; - char subtype; + u8 subtype; #define CreativeVista 0 #define HamaUSBSightcam 1 #define HamaUSBSightcam2 2 @@ -86,58 +86,54 @@ static const struct v4l2_pix_format sif_mode[] = { }; /* Frame packet header offsets for the spca508 */ +#if 0 +#define SPCA508_OFFSET_ #define SPCA508_OFFSET_TYPE 1 +#define SPCA508_IMAGE_TYPE_MASK 0x1f +#define SPCA508_SNAPBIT 0x20 +#define SPCA508_SNAPCTRL 0x40 #define SPCA508_OFFSET_COMPRESS 2 #define SPCA508_OFFSET_FRAMSEQ 8 +#define SPCA508_OFFSET_GPIO 9 +#define SPCA508_OFFSET_GLBINF 10 #define SPCA508_OFFSET_WIN1LUM 11 +#define SPCA508_OFFSET_WIN2LUM 12 +#define SPCA508_OFFSET_WIN1RG 13 +#define SPCA508_OFFSET_WIN1BG 14 +#define SPCA508_OFFSET_WIN2RG 15 +#define SPCA508_OFFSET_WIN2BG 16 +#define SPCA508_OFFSET_21 21 +#define SPCA508_GAMMAEN 0x01 +#define SPCA508_EDGEMODE 0x02 +#endif #define SPCA508_OFFSET_DATA 37 -#define SPCA508_SNAPBIT 0x20 -#define SPCA508_SNAPCTRL 0x40 -/*************** I2c ****************/ -#define SPCA508_INDEX_I2C_BASE 0x8800 - /* * Initialization data: this is the first set-up data written to the * device (before the open data). */ static const u16 spca508_init_data[][2] = { - /* line URB value, index */ - /* 44274 1804 */ {0x0000, 0x870b}, - - /* 44299 1805 */ {0x0020, 0x8112}, - /* Video drop enable, ISO streaming disable */ - /* 44324 1806 */ {0x0003, 0x8111}, - /* Reset compression & memory */ - /* 44349 1807 */ {0x0000, 0x8110}, - /* Disable all outputs */ - /* 44372 1808 */ /* READ {0x0000, 0x8114} -> 0000: 00 */ - /* 44398 1809 */ {0x0000, 0x8114}, - /* SW GPIO data */ - /* 44423 1810 */ {0x0008, 0x8110}, - /* Enable charge pump output */ - /* 44527 1811 */ {0x0002, 0x8116}, - /* 200 kHz pump clock */ - /* 44555 1812 */ - /* UNKNOWN DIRECTION (URB_FUNCTION_SELECT_INTERFACE:) */ - /* 44590 1813 */ {0x0003, 0x8111}, - /* Reset compression & memory */ - /* 44615 1814 */ {0x0000, 0x8111}, - /* Normal mode (not reset) */ - /* 44640 1815 */ {0x0098, 0x8110}, - /* Enable charge pump output, sync.serial,external 2x clock */ - /* 44665 1816 */ {0x000d, 0x8114}, - /* SW GPIO data */ - /* 44690 1817 */ {0x0002, 0x8116}, - /* 200 kHz pump clock */ - /* 44715 1818 */ {0x0020, 0x8112}, - /* Video drop enable, ISO streaming disable */ + {0x0000, 0x870b}, + + {0x0020, 0x8112}, /* Video drop enable, ISO streaming disable */ + {0x0003, 0x8111}, /* Reset compression & memory */ + {0x0000, 0x8110}, /* Disable all outputs */ + /* READ {0x0000, 0x8114} -> 0000: 00 */ + {0x0000, 0x8114}, /* SW GPIO data */ + {0x0008, 0x8110}, /* Enable charge pump output */ + {0x0002, 0x8116}, /* 200 kHz pump clock */ + /* UNKNOWN DIRECTION (URB_FUNCTION_SELECT_INTERFACE:) */ + {0x0003, 0x8111}, /* Reset compression & memory */ + {0x0000, 0x8111}, /* Normal mode (not reset) */ + {0x0098, 0x8110}, + /* Enable charge pump output, sync.serial,external 2x clock */ + {0x000d, 0x8114}, /* SW GPIO data */ + {0x0002, 0x8116}, /* 200 kHz pump clock */ + {0x0020, 0x8112}, /* Video drop enable, ISO streaming disable */ /* --------------------------------------- */ - /* 44740 1819 */ {0x000f, 0x8402}, - /* memory bank */ - /* 44765 1820 */ {0x0000, 0x8403}, - /* ... address */ + {0x000f, 0x8402}, /* memory bank */ + {0x0000, 0x8403}, /* ... address */ /* --------------------------------------- */ /* 0x88__ is Synchronous Serial Interface. */ /* TBD: This table could be expressed more compactly */ @@ -145,342 +141,307 @@ static const u16 spca508_init_data[][2] = /* TBD: Should see if the values in spca50x_i2c_data */ /* would work with the VQ110 instead of the values */ /* below. */ - /* 44790 1821 */ {0x00c0, 0x8804}, - /* SSI slave addr */ - /* 44815 1822 */ {0x0008, 0x8802}, - /* 375 Khz SSI clock */ - /* 44838 1823 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */ - /* 44862 1824 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08 */ - /* 44888 1825 */ {0x0008, 0x8802}, - /* 375 Khz SSI clock */ - /* 44913 1826 */ {0x0012, 0x8801}, - /* SSI reg addr */ - /* 44938 1827 */ {0x0080, 0x8800}, - /* SSI data to write */ - /* 44961 1828 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */ - /* 44985 1829 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */ - /* 45009 1830 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08 */ - /* 45035 1831 */ {0x0008, 0x8802}, - /* 375 Khz SSI clock */ - /* 45060 1832 */ {0x0012, 0x8801}, - /* SSI reg addr */ - /* 45085 1833 */ {0x0000, 0x8800}, - /* SSI data to write */ - /* 45108 1834 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */ - /* 45132 1835 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */ - /* 45156 1836 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08 */ - /* 45182 1837 */ {0x0008, 0x8802}, - /* 375 Khz SSI clock */ - /* 45207 1838 */ {0x0011, 0x8801}, - /* SSI reg addr */ - /* 45232 1839 */ {0x0040, 0x8800}, - /* SSI data to write */ - /* 45255 1840 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */ - /* 45279 1841 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */ - /* 45303 1842 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08 */ - /* 45329 1843 */ {0x0008, 0x8802}, - /* 45354 1844 */ {0x0013, 0x8801}, - /* 45379 1845 */ {0x0000, 0x8800}, - /* 45402 1846 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */ - /* 45426 1847 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */ - /* 45450 1848 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08 */ - /* 45476 1849 */ {0x0008, 0x8802}, - /* 45501 1850 */ {0x0014, 0x8801}, - /* 45526 1851 */ {0x0000, 0x8800}, - /* 45549 1852 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */ - /* 45573 1853 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */ - /* 45597 1854 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08 */ - /* 45623 1855 */ {0x0008, 0x8802}, - /* 45648 1856 */ {0x0015, 0x8801}, - /* 45673 1857 */ {0x0001, 0x8800}, - /* 45696 1858 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */ - /* 45720 1859 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */ - /* 45744 1860 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08 */ - /* 45770 1861 */ {0x0008, 0x8802}, - /* 45795 1862 */ {0x0016, 0x8801}, - /* 45820 1863 */ {0x0003, 0x8800}, - /* 45843 1864 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */ - /* 45867 1865 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */ - /* 45891 1866 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08 */ - /* 45917 1867 */ {0x0008, 0x8802}, - /* 45942 1868 */ {0x0017, 0x8801}, - /* 45967 1869 */ {0x0036, 0x8800}, - /* 45990 1870 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */ - /* 46014 1871 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */ - /* 46038 1872 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08 */ - /* 46064 1873 */ {0x0008, 0x8802}, - /* 46089 1874 */ {0x0018, 0x8801}, - /* 46114 1875 */ {0x00ec, 0x8800}, - /* 46137 1876 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */ - /* 46161 1877 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */ - /* 46185 1878 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08 */ - /* 46211 1879 */ {0x0008, 0x8802}, - /* 46236 1880 */ {0x001a, 0x8801}, - /* 46261 1881 */ {0x0094, 0x8800}, - /* 46284 1882 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */ - /* 46308 1883 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */ - /* 46332 1884 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08 */ - /* 46358 1885 */ {0x0008, 0x8802}, - /* 46383 1886 */ {0x001b, 0x8801}, - /* 46408 1887 */ {0x0000, 0x8800}, - /* 46431 1888 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */ - /* 46455 1889 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */ - /* 46479 1890 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08 */ - /* 46505 1891 */ {0x0008, 0x8802}, - /* 46530 1892 */ {0x0027, 0x8801}, - /* 46555 1893 */ {0x00a2, 0x8800}, - /* 46578 1894 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */ - /* 46602 1895 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */ - /* 46626 1896 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08 */ - /* 46652 1897 */ {0x0008, 0x8802}, - /* 46677 1898 */ {0x0028, 0x8801}, - /* 46702 1899 */ {0x0040, 0x8800}, - /* 46725 1900 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */ - /* 46749 1901 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */ - /* 46773 1902 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08 */ - /* 46799 1903 */ {0x0008, 0x8802}, - /* 46824 1904 */ {0x002a, 0x8801}, - /* 46849 1905 */ {0x0084, 0x8800}, - /* 46872 1906 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */ - /* 46896 1907 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */ - /* 46920 1908 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08 */ - /* 46946 1909 */ {0x0008, 0x8802}, - /* 46971 1910 */ {0x002b, 0x8801}, - /* 46996 1911 */ {0x00a8, 0x8800}, - /* 47019 1912 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */ - /* 47043 1913 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */ - /* 47067 1914 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08 */ - /* 47093 1915 */ {0x0008, 0x8802}, - /* 47118 1916 */ {0x002c, 0x8801}, - /* 47143 1917 */ {0x00fe, 0x8800}, - /* 47166 1918 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */ - /* 47190 1919 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */ - /* 47214 1920 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08 */ - /* 47240 1921 */ {0x0008, 0x8802}, - /* 47265 1922 */ {0x002d, 0x8801}, - /* 47290 1923 */ {0x0003, 0x8800}, - /* 47313 1924 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */ - /* 47337 1925 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */ - /* 47361 1926 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08 */ - /* 47387 1927 */ {0x0008, 0x8802}, - /* 47412 1928 */ {0x0038, 0x8801}, - /* 47437 1929 */ {0x0083, 0x8800}, - /* 47460 1930 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */ - /* 47484 1931 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */ - /* 47508 1932 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08 */ - /* 47534 1933 */ {0x0008, 0x8802}, - /* 47559 1934 */ {0x0033, 0x8801}, - /* 47584 1935 */ {0x0081, 0x8800}, - /* 47607 1936 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */ - /* 47631 1937 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */ - /* 47655 1938 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08 */ - /* 47681 1939 */ {0x0008, 0x8802}, - /* 47706 1940 */ {0x0034, 0x8801}, - /* 47731 1941 */ {0x004a, 0x8800}, - /* 47754 1942 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */ - /* 47778 1943 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */ - /* 47802 1944 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08 */ - /* 47828 1945 */ {0x0008, 0x8802}, - /* 47853 1946 */ {0x0039, 0x8801}, - /* 47878 1947 */ {0x0000, 0x8800}, - /* 47901 1948 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */ - /* 47925 1949 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */ - /* 47949 1950 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08 */ - /* 47975 1951 */ {0x0008, 0x8802}, - /* 48000 1952 */ {0x0010, 0x8801}, - /* 48025 1953 */ {0x00a8, 0x8800}, - /* 48048 1954 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */ - /* 48072 1955 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */ - /* 48096 1956 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08 */ - /* 48122 1957 */ {0x0008, 0x8802}, - /* 48147 1958 */ {0x0006, 0x8801}, - /* 48172 1959 */ {0x0058, 0x8800}, - /* 48195 1960 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */ - /* 48219 1961 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */ - /* 48243 1962 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08 */ - /* 48269 1963 */ {0x0008, 0x8802}, - /* 48294 1964 */ {0x0000, 0x8801}, - /* 48319 1965 */ {0x0004, 0x8800}, - /* 48342 1966 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */ - /* 48366 1967 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */ - /* 48390 1968 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08 */ - /* 48416 1969 */ {0x0008, 0x8802}, - /* 48441 1970 */ {0x0040, 0x8801}, - /* 48466 1971 */ {0x0080, 0x8800}, - /* 48489 1972 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */ - /* 48513 1973 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */ - /* 48537 1974 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08 */ - /* 48563 1975 */ {0x0008, 0x8802}, - /* 48588 1976 */ {0x0041, 0x8801}, - /* 48613 1977 */ {0x000c, 0x8800}, - /* 48636 1978 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */ - /* 48660 1979 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */ - /* 48684 1980 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08 */ - /* 48710 1981 */ {0x0008, 0x8802}, - /* 48735 1982 */ {0x0042, 0x8801}, - /* 48760 1983 */ {0x000c, 0x8800}, - /* 48783 1984 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */ - /* 48807 1985 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */ - /* 48831 1986 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08 */ - /* 48857 1987 */ {0x0008, 0x8802}, - /* 48882 1988 */ {0x0043, 0x8801}, - /* 48907 1989 */ {0x0028, 0x8800}, - /* 48930 1990 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */ - /* 48954 1991 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */ - /* 48978 1992 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08 */ - /* 49004 1993 */ {0x0008, 0x8802}, - /* 49029 1994 */ {0x0044, 0x8801}, - /* 49054 1995 */ {0x0080, 0x8800}, - /* 49077 1996 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */ - /* 49101 1997 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */ - /* 49125 1998 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08 */ - /* 49151 1999 */ {0x0008, 0x8802}, - /* 49176 2000 */ {0x0045, 0x8801}, - /* 49201 2001 */ {0x0020, 0x8800}, - /* 49224 2002 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */ - /* 49248 2003 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */ - /* 49272 2004 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08 */ - /* 49298 2005 */ {0x0008, 0x8802}, - /* 49323 2006 */ {0x0046, 0x8801}, - /* 49348 2007 */ {0x0020, 0x8800}, - /* 49371 2008 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */ - /* 49395 2009 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */ - /* 49419 2010 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08 */ - /* 49445 2011 */ {0x0008, 0x8802}, - /* 49470 2012 */ {0x0047, 0x8801}, - /* 49495 2013 */ {0x0080, 0x8800}, - /* 49518 2014 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */ - /* 49542 2015 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */ - /* 49566 2016 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08 */ - /* 49592 2017 */ {0x0008, 0x8802}, - /* 49617 2018 */ {0x0048, 0x8801}, - /* 49642 2019 */ {0x004c, 0x8800}, - /* 49665 2020 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */ - /* 49689 2021 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */ - /* 49713 2022 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08 */ - /* 49739 2023 */ {0x0008, 0x8802}, - /* 49764 2024 */ {0x0049, 0x8801}, - /* 49789 2025 */ {0x0084, 0x8800}, - /* 49812 2026 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */ - /* 49836 2027 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */ - /* 49860 2028 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08 */ - /* 49886 2029 */ {0x0008, 0x8802}, - /* 49911 2030 */ {0x004a, 0x8801}, - /* 49936 2031 */ {0x0084, 0x8800}, - /* 49959 2032 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */ - /* 49983 2033 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */ - /* 50007 2034 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08 */ - /* 50033 2035 */ {0x0008, 0x8802}, - /* 50058 2036 */ {0x004b, 0x8801}, - /* 50083 2037 */ {0x0084, 0x8800}, - /* 50106 2038 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */ + {0x00c0, 0x8804}, /* SSI slave addr */ + {0x0008, 0x8802}, /* 375 Khz SSI clock */ + /* READ { 0x0001, 0x8803 } -> 0000: 00 */ + /* READ { 0x0001, 0x8802 } -> 0000: 08 */ + {0x0008, 0x8802}, /* 375 Khz SSI clock */ + {0x0012, 0x8801}, /* SSI reg addr */ + {0x0080, 0x8800}, /* SSI data to write */ + /* READ { 0x0001, 0x8803 } -> 0000: 00 */ + /* READ { 0x0001, 0x8803 } -> 0000: 00 */ + /* READ { 0x0001, 0x8802 } -> 0000: 08 */ + {0x0008, 0x8802}, /* 375 Khz SSI clock */ + {0x0012, 0x8801}, /* SSI reg addr */ + {0x0000, 0x8800}, /* SSI data to write */ + /* READ { 0x0001, 0x8803 } -> 0000: 00 */ + /* READ { 0x0001, 0x8803 } -> 0000: 00 */ + /* READ { 0x0001, 0x8802 } -> 0000: 08 */ + {0x0008, 0x8802}, /* 375 Khz SSI clock */ + {0x0011, 0x8801}, /* SSI reg addr */ + {0x0040, 0x8800}, /* SSI data to write */ + /* READ { 0x0001, 0x8803 } -> 0000: 00 */ + /* READ { 0x0001, 0x8803 } -> 0000: 00 */ + /* READ { 0x0001, 0x8802 } -> 0000: 08 */ + {0x0008, 0x8802}, + {0x0013, 0x8801}, + {0x0000, 0x8800}, + /* READ { 0x0001, 0x8803 } -> 0000: 00 */ + /* READ { 0x0001, 0x8803 } -> 0000: 00 */ + /* READ { 0x0001, 0x8802 } -> 0000: 08 */ + {0x0008, 0x8802}, + {0x0014, 0x8801}, + {0x0000, 0x8800}, + /* READ { 0x0001, 0x8803 } -> 0000: 00 */ + /* READ { 0x0001, 0x8803 } -> 0000: 00 */ + /* READ { 0x0001, 0x8802 } -> 0000: 08 */ + {0x0008, 0x8802}, + {0x0015, 0x8801}, + {0x0001, 0x8800}, + /* READ { 0x0001, 0x8803 } -> 0000: 00 */ + /* READ { 0x0001, 0x8803 } -> 0000: 00 */ + /* READ { 0x0001, 0x8802 } -> 0000: 08 */ + {0x0008, 0x8802}, + {0x0016, 0x8801}, + {0x0003, 0x8800}, + /* READ { 0x0001, 0x8803 } -> 0000: 00 */ + /* READ { 0x0001, 0x8803 } -> 0000: 00 */ + /* READ { 0x0001, 0x8802 } -> 0000: 08 */ + {0x0008, 0x8802}, + {0x0017, 0x8801}, + {0x0036, 0x8800}, + /* READ { 0x0001, 0x8803 } -> 0000: 00 */ + /* READ { 0x0001, 0x8803 } -> 0000: 00 */ + /* READ { 0x0001, 0x8802 } -> 0000: 08 */ + {0x0008, 0x8802}, + {0x0018, 0x8801}, + {0x00ec, 0x8800}, + /* READ { 0x0001, 0x8803 } -> 0000: 00 */ + /* READ { 0x0001, 0x8803 } -> 0000: 00 */ + /* READ { 0x0001, 0x8802 } -> 0000: 08 */ + {0x0008, 0x8802}, + {0x001a, 0x8801}, + {0x0094, 0x8800}, + /* READ { 0x0001, 0x8803 } -> 0000: 00 */ + /* READ { 0x0001, 0x8803 } -> 0000: 00 */ + /* READ { 0x0001, 0x8802 } -> 0000: 08 */ + {0x0008, 0x8802}, + {0x001b, 0x8801}, + {0x0000, 0x8800}, + /* READ { 0x0001, 0x8803 } -> 0000: 00 */ + /* READ { 0x0001, 0x8803 } -> 0000: 00 */ + /* READ { 0x0001, 0x8802 } -> 0000: 08 */ + {0x0008, 0x8802}, + {0x0027, 0x8801}, + {0x00a2, 0x8800}, + /* READ { 0x0001, 0x8803 } -> 0000: 00 */ + /* READ { 0x0001, 0x8803 } -> 0000: 00 */ + /* READ { 0x0001, 0x8802 } -> 0000: 08 */ + {0x0008, 0x8802}, + {0x0028, 0x8801}, + {0x0040, 0x8800}, + /* READ { 0x0001, 0x8803 } -> 0000: 00 */ + /* READ { 0x0001, 0x8803 } -> 0000: 00 */ + /* READ { 0x0001, 0x8802 } -> 0000: 08 */ + {0x0008, 0x8802}, + {0x002a, 0x8801}, + {0x0084, 0x8800}, + /* READ { 0x0001, 0x8803 } -> 0000: 00 */ + /* READ { 0x0001, 0x8803 } -> 0000: 00 */ + /* READ { 0x0001, 0x8802 } -> 0000: 08 */ + {0x0008, 0x8802}, + {0x002b, 0x8801}, + {0x00a8, 0x8800}, + /* READ { 0x0001, 0x8803 } -> 0000: 00 */ + /* READ { 0x0001, 0x8803 } -> 0000: 00 */ + /* READ { 0x0001, 0x8802 } -> 0000: 08 */ + {0x0008, 0x8802}, + {0x002c, 0x8801}, + {0x00fe, 0x8800}, + /* READ { 0x0001, 0x8803 } -> 0000: 00 */ + /* READ { 0x0001, 0x8803 } -> 0000: 00 */ + /* READ { 0x0001, 0x8802 } -> 0000: 08 */ + {0x0008, 0x8802}, + {0x002d, 0x8801}, + {0x0003, 0x8800}, + /* READ { 0x0001, 0x8803 } -> 0000: 00 */ + /* READ { 0x0001, 0x8803 } -> 0000: 00 */ + /* READ { 0x0001, 0x8802 } -> 0000: 08 */ + {0x0008, 0x8802}, + {0x0038, 0x8801}, + {0x0083, 0x8800}, + /* READ { 0x0001, 0x8803 } -> 0000: 00 */ + /* READ { 0x0001, 0x8803 } -> 0000: 00 */ + /* READ { 0x0001, 0x8802 } -> 0000: 08 */ + {0x0008, 0x8802}, + {0x0033, 0x8801}, + {0x0081, 0x8800}, + /* READ { 0x0001, 0x8803 } -> 0000: 00 */ + /* READ { 0x0001, 0x8803 } -> 0000: 00 */ + /* READ { 0x0001, 0x8802 } -> 0000: 08 */ + {0x0008, 0x8802}, + {0x0034, 0x8801}, + {0x004a, 0x8800}, + /* READ { 0x0001, 0x8803 } -> 0000: 00 */ + /* READ { 0x0001, 0x8803 } -> 0000: 00 */ + /* READ { 0x0001, 0x8802 } -> 0000: 08 */ + {0x0008, 0x8802}, + {0x0039, 0x8801}, + {0x0000, 0x8800}, + /* READ { 0x0001, 0x8803 } -> 0000: 00 */ + /* READ { 0x0001, 0x8803 } -> 0000: 00 */ + /* READ { 0x0001, 0x8802 } -> 0000: 08 */ + {0x0008, 0x8802}, + {0x0010, 0x8801}, + {0x00a8, 0x8800}, + /* READ { 0x0001, 0x8803 } -> 0000: 00 */ + /* READ { 0x0001, 0x8803 } -> 0000: 00 */ + /* READ { 0x0001, 0x8802 } -> 0000: 08 */ + {0x0008, 0x8802}, + {0x0006, 0x8801}, + {0x0058, 0x8800}, + /* READ { 0x0001, 0x8803 } -> 0000: 00 */ + /* READ { 0x0001, 0x8803 } -> 0000: 00 */ + /* READ { 0x0001, 0x8802 } -> 0000: 08 */ + {0x0008, 0x8802}, + {0x0000, 0x8801}, + {0x0004, 0x8800}, + /* READ { 0x0001, 0x8803 } -> 0000: 00 */ + /* READ { 0x0001, 0x8803 } -> 0000: 00 */ + /* READ { 0x0001, 0x8802 } -> 0000: 08 */ + {0x0008, 0x8802}, + {0x0040, 0x8801}, + {0x0080, 0x8800}, + /* READ { 0x0001, 0x8803 } -> 0000: 00 */ + /* READ { 0x0001, 0x8803 } -> 0000: 00 */ + /* READ { 0x0001, 0x8802 } -> 0000: 08 */ + {0x0008, 0x8802}, + {0x0041, 0x8801}, + {0x000c, 0x8800}, + /* READ { 0x0001, 0x8803 } -> 0000: 00 */ + /* READ { 0x0001, 0x8803 } -> 0000: 00 */ + /* READ { 0x0001, 0x8802 } -> 0000: 08 */ + {0x0008, 0x8802}, + {0x0042, 0x8801}, + {0x000c, 0x8800}, + /* READ { 0x0001, 0x8803 } -> 0000: 00 */ + /* READ { 0x0001, 0x8803 } -> 0000: 00 */ + /* READ { 0x0001, 0x8802 } -> 0000: 08 */ + {0x0008, 0x8802}, + {0x0043, 0x8801}, + {0x0028, 0x8800}, + /* READ { 0x0001, 0x8803 } -> 0000: 00 */ + /* READ { 0x0001, 0x8803 } -> 0000: 00 */ + /* READ { 0x0001, 0x8802 } -> 0000: 08 */ + {0x0008, 0x8802}, + {0x0044, 0x8801}, + {0x0080, 0x8800}, + /* READ { 0x0001, 0x8803 } -> 0000: 00 */ + /* READ { 0x0001, 0x8803 } -> 0000: 00 */ + /* READ { 0x0001, 0x8802 } -> 0000: 08 */ + {0x0008, 0x8802}, + {0x0045, 0x8801}, + {0x0020, 0x8800}, + /* READ { 0x0001, 0x8803 } -> 0000: 00 */ + /* READ { 0x0001, 0x8803 } -> 0000: 00 */ + /* READ { 0x0001, 0x8802 } -> 0000: 08 */ + {0x0008, 0x8802}, + {0x0046, 0x8801}, + {0x0020, 0x8800}, + /* READ { 0x0001, 0x8803 } -> 0000: 00 */ + /* READ { 0x0001, 0x8803 } -> 0000: 00 */ + /* READ { 0x0001, 0x8802 } -> 0000: 08 */ + {0x0008, 0x8802}, + {0x0047, 0x8801}, + {0x0080, 0x8800}, + /* READ { 0x0001, 0x8803 } -> 0000: 00 */ + /* READ { 0x0001, 0x8803 } -> 0000: 00 */ + /* READ { 0x0001, 0x8802 } -> 0000: 08 */ + {0x0008, 0x8802}, + {0x0048, 0x8801}, + {0x004c, 0x8800}, + /* READ { 0x0001, 0x8803 } -> 0000: 00 */ + /* READ { 0x0001, 0x8803 } -> 0000: 00 */ + /* READ { 0x0001, 0x8802 } -> 0000: 08 */ + {0x0008, 0x8802}, + {0x0049, 0x8801}, + {0x0084, 0x8800}, + /* READ { 0x0001, 0x8803 } -> 0000: 00 */ + /* READ { 0x0001, 0x8803 } -> 0000: 00 */ + /* READ { 0x0001, 0x8802 } -> 0000: 08 */ + {0x0008, 0x8802}, + {0x004a, 0x8801}, + {0x0084, 0x8800}, + /* READ { 0x0001, 0x8803 } -> 0000: 00 */ + /* READ { 0x0001, 0x8803 } -> 0000: 00 */ + /* READ { 0x0001, 0x8802 } -> 0000: 08 */ + {0x0008, 0x8802}, + {0x004b, 0x8801}, + {0x0084, 0x8800}, + /* READ { 0x0001, 0x8803 } -> 0000: 00 */ /* --------------------------------------- */ - /* 50132 2039 */ {0x0012, 0x8700}, - /* Clock speed 48Mhz/(2+2)/2= 6 Mhz */ - /* 50157 2040 */ {0x0000, 0x8701}, - /* CKx1 clock delay adj */ - /* 50182 2041 */ {0x0000, 0x8701}, - /* CKx1 clock delay adj */ - /* 50207 2042 */ {0x0001, 0x870c}, - /* CKOx2 output */ + {0x0012, 0x8700}, /* Clock speed 48Mhz/(2+2)/2= 6 Mhz */ + {0x0000, 0x8701}, /* CKx1 clock delay adj */ + {0x0000, 0x8701}, /* CKx1 clock delay adj */ + {0x0001, 0x870c}, /* CKOx2 output */ /* --------------------------------------- */ - /* 50232 2043 */ {0x0080, 0x8600}, - /* Line memory read counter (L) */ - /* 50257 2044 */ {0x0001, 0x8606}, - /* reserved */ - /* 50282 2045 */ {0x0064, 0x8607}, - /* Line memory read counter (H) 0x6480=25,728 */ - /* 50307 2046 */ {0x002a, 0x8601}, - /* CDSP sharp interpolation mode, + {0x0080, 0x8600}, /* Line memory read counter (L) */ + {0x0001, 0x8606}, /* reserved */ + {0x0064, 0x8607}, /* Line memory read counter (H) 0x6480=25,728 */ + {0x002a, 0x8601}, /* CDSP sharp interpolation mode, * line sel for color sep, edge enhance enab */ - /* 50332 2047 */ {0x0000, 0x8602}, - /* optical black level for user settng = 0 */ - /* 50357 2048 */ {0x0080, 0x8600}, - /* Line memory read counter (L) */ - /* 50382 2049 */ {0x000a, 0x8603}, - /* optical black level calc mode: auto; optical black offset = 10 */ - /* 50407 2050 */ {0x00df, 0x865b}, - /* Horiz offset for valid pixels (L)=0xdf */ - /* 50432 2051 */ {0x0012, 0x865c}, - /* Vert offset for valid lines (L)=0x12 */ + {0x0000, 0x8602}, /* optical black level for user settng = 0 */ + {0x0080, 0x8600}, /* Line memory read counter (L) */ + {0x000a, 0x8603}, /* optical black level calc mode: + * auto; optical black offset = 10 */ + {0x00df, 0x865b}, /* Horiz offset for valid pixels (L)=0xdf */ + {0x0012, 0x865c}, /* Vert offset for valid lines (L)=0x12 */ /* The following two lines seem to be the "wrong" resolution. */ /* But perhaps these indicate the actual size of the sensor */ /* rather than the size of the current video mode. */ - /* 50457 2052 */ {0x0058, 0x865d}, - /* Horiz valid pixels (*4) (L) = 352 */ - /* 50482 2053 */ {0x0048, 0x865e}, - /* Vert valid lines (*4) (L) = 288 */ - - /* 50507 2054 */ {0x0015, 0x8608}, - /* A11 Coef ... */ - /* 50532 2055 */ {0x0030, 0x8609}, - /* 50557 2056 */ {0x00fb, 0x860a}, - /* 50582 2057 */ {0x003e, 0x860b}, - /* 50607 2058 */ {0x00ce, 0x860c}, - /* 50632 2059 */ {0x00f4, 0x860d}, - /* 50657 2060 */ {0x00eb, 0x860e}, - /* 50682 2061 */ {0x00dc, 0x860f}, - /* 50707 2062 */ {0x0039, 0x8610}, - /* 50732 2063 */ {0x0001, 0x8611}, - /* R offset for white balance ... */ - /* 50757 2064 */ {0x0000, 0x8612}, - /* 50782 2065 */ {0x0001, 0x8613}, - /* 50807 2066 */ {0x0000, 0x8614}, - /* 50832 2067 */ {0x005b, 0x8651}, - /* R gain for white balance ... */ - /* 50857 2068 */ {0x0040, 0x8652}, - /* 50882 2069 */ {0x0060, 0x8653}, - /* 50907 2070 */ {0x0040, 0x8654}, - /* 50932 2071 */ {0x0000, 0x8655}, - /* 50957 2072 */ {0x0001, 0x863f}, - /* Fixed gamma correction enable, USB control, - * lum filter disable, lum noise clip disable */ - /* 50982 2073 */ {0x00a1, 0x8656}, - /* Window1 size 256x256, Windows2 size 64x64, - * gamma look-up disable, new edge enhancement enable */ - /* 51007 2074 */ {0x0018, 0x8657}, - /* Edge gain high thresh */ - /* 51032 2075 */ {0x0020, 0x8658}, - /* Edge gain low thresh */ - /* 51057 2076 */ {0x000a, 0x8659}, - /* Edge bandwidth high threshold */ - /* 51082 2077 */ {0x0005, 0x865a}, - /* Edge bandwidth low threshold */ + {0x0058, 0x865d}, /* Horiz valid pixels (*4) (L) = 352 */ + {0x0048, 0x865e}, /* Vert valid lines (*4) (L) = 288 */ + + {0x0015, 0x8608}, /* A11 Coef ... */ + {0x0030, 0x8609}, + {0x00fb, 0x860a}, + {0x003e, 0x860b}, + {0x00ce, 0x860c}, + {0x00f4, 0x860d}, + {0x00eb, 0x860e}, + {0x00dc, 0x860f}, + {0x0039, 0x8610}, + {0x0001, 0x8611}, /* R offset for white balance ... */ + {0x0000, 0x8612}, + {0x0001, 0x8613}, + {0x0000, 0x8614}, + {0x005b, 0x8651}, /* R gain for white balance ... */ + {0x0040, 0x8652}, + {0x0060, 0x8653}, + {0x0040, 0x8654}, + {0x0000, 0x8655}, + {0x0001, 0x863f}, /* Fixed gamma correction enable, USB control, + * lum filter disable, lum noise clip disable */ + {0x00a1, 0x8656}, /* Window1 size 256x256, Windows2 size 64x64, + * gamma look-up disable, + * new edge enhancement enable */ + {0x0018, 0x8657}, /* Edge gain high thresh */ + {0x0020, 0x8658}, /* Edge gain low thresh */ + {0x000a, 0x8659}, /* Edge bandwidth high threshold */ + {0x0005, 0x865a}, /* Edge bandwidth low threshold */ /* -------------------------------- */ - /* 51107 2078 */ {0x0030, 0x8112}, - /* Video drop enable, ISO streaming enable */ - /* 51130 2079 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */ - /* 51154 2080 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08 */ - /* 51180 2081 */ {0xa908, 0x8802}, - /* 51205 2082 */ {0x0034, 0x8801}, - /* SSI reg addr */ - /* 51230 2083 */ {0x00ca, 0x8800}, + {0x0030, 0x8112}, /* Video drop enable, ISO streaming enable */ + /* READ { 0x0001, 0x8803 } -> 0000: 00 */ + /* READ { 0x0001, 0x8802 } -> 0000: 08 */ + {0xa908, 0x8802}, + {0x0034, 0x8801}, /* SSI reg addr */ + {0x00ca, 0x8800}, /* SSI data to write */ - /* 51253 2084 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */ - /* 51277 2085 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */ - /* 51301 2086 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08 */ - /* 51327 2087 */ {0x1f08, 0x8802}, - /* 51352 2088 */ {0x0006, 0x8801}, - /* 51377 2089 */ {0x0080, 0x8800}, - /* 51400 2090 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */ + /* READ { 0x0001, 0x8803 } -> 0000: 00 */ + /* READ { 0x0001, 0x8803 } -> 0000: 00 */ + /* READ { 0x0001, 0x8802 } -> 0000: 08 */ + {0x1f08, 0x8802}, + {0x0006, 0x8801}, + {0x0080, 0x8800}, + /* READ { 0x0001, 0x8803 } -> 0000: 00 */ /* ----- Read back coefs we wrote earlier. */ - /* 51424 2091 */ /* READ { 0, 0x0000, 0x8608 } -> 0000: 15 */ - /* 51448 2092 */ /* READ { 0, 0x0000, 0x8609 } -> 0000: 30 */ - /* 51472 2093 */ /* READ { 0, 0x0000, 0x860a } -> 0000: fb */ - /* 51496 2094 */ /* READ { 0, 0x0000, 0x860b } -> 0000: 3e */ - /* 51520 2095 */ /* READ { 0, 0x0000, 0x860c } -> 0000: ce */ - /* 51544 2096 */ /* READ { 0, 0x0000, 0x860d } -> 0000: f4 */ - /* 51568 2097 */ /* READ { 0, 0x0000, 0x860e } -> 0000: eb */ - /* 51592 2098 */ /* READ { 0, 0x0000, 0x860f } -> 0000: dc */ - /* 51616 2099 */ /* READ { 0, 0x0000, 0x8610 } -> 0000: 39 */ - /* 51640 2100 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */ - /* 51664 2101 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08 */ - /* 51690 2102 */ {0xb008, 0x8802}, - /* 51715 2103 */ {0x0006, 0x8801}, - /* 51740 2104 */ {0x007d, 0x8800}, - /* 51763 2105 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */ + /* READ { 0x0000, 0x8608 } -> 0000: 15 */ + /* READ { 0x0000, 0x8609 } -> 0000: 30 */ + /* READ { 0x0000, 0x860a } -> 0000: fb */ + /* READ { 0x0000, 0x860b } -> 0000: 3e */ + /* READ { 0x0000, 0x860c } -> 0000: ce */ + /* READ { 0x0000, 0x860d } -> 0000: f4 */ + /* READ { 0x0000, 0x860e } -> 0000: eb */ + /* READ { 0x0000, 0x860f } -> 0000: dc */ + /* READ { 0x0000, 0x8610 } -> 0000: 39 */ + /* READ { 0x0001, 0x8803 } -> 0000: 00 */ + /* READ { 0x0001, 0x8802 } -> 0000: 08 */ + {0xb008, 0x8802}, + {0x0006, 0x8801}, + {0x007d, 0x8800}, + /* READ { 0x0001, 0x8803 } -> 0000: 00 */ #if 0 /* experimental. dark version. */ @@ -504,114 +465,86 @@ static const u16 spca508_init_data[][2] = /* earlier commands (A11 Coef...), but if I disable it, */ /* the image appears too dark. Maybe there was some kind of */ /* reset since the earlier commands, so this is necessary again. */ - /* 51789 2106 */ {0x0015, 0x8608}, - /* 51814 2107 */ {0x0030, 0x8609}, - /* 51839 2108 */ {0xfffb, 0x860a}, - /* 51864 2109 */ {0x003e, 0x860b}, - /* 51889 2110 */ {0xffce, 0x860c}, - /* 51914 2111 */ {0xfff4, 0x860d}, - /* 51939 2112 */ {0xffeb, 0x860e}, - /* 51964 2113 */ {0xffdc, 0x860f}, - /* 51989 2114 */ {0x0039, 0x8610}, - /* 52014 2115 */ {0x0018, 0x8657}, + {0x0015, 0x8608}, + {0x0030, 0x8609}, + {0xfffb, 0x860a}, + {0x003e, 0x860b}, + {0xffce, 0x860c}, + {0xfff4, 0x860d}, + {0xffeb, 0x860e}, + {0xffdc, 0x860f}, + {0x0039, 0x8610}, + {0x0018, 0x8657}, #endif - /* 52039 2116 */ {0x0000, 0x8508}, - /* Disable compression. */ + {0x0000, 0x8508}, /* Disable compression. */ /* Previous line was: - * 52039 2116 * { 0, 0x0021, 0x8508 }, * Enable compression. */ - /* 52064 2117 */ {0x0032, 0x850b}, - /* compression stuff */ - /* 52089 2118 */ {0x0003, 0x8509}, - /* compression stuff */ - /* 52114 2119 */ {0x0011, 0x850a}, - /* compression stuff */ - /* 52139 2120 */ {0x0021, 0x850d}, - /* compression stuff */ - /* 52164 2121 */ {0x0010, 0x850c}, - /* compression stuff */ - /* 52189 2122 */ {0x0003, 0x8500}, - /* *** Video mode: 160x120 */ - /* 52214 2123 */ {0x0001, 0x8501}, - /* Hardware-dominated snap control */ - /* 52239 2124 */ {0x0061, 0x8656}, - /* Window1 size 128x128, Windows2 size 128x128, - * gamma look-up disable, new edge enhancement enable */ - /* 52264 2125 */ {0x0018, 0x8617}, - /* Window1 start X (*2) */ - /* 52289 2126 */ {0x0008, 0x8618}, - /* Window1 start Y (*2) */ - /* 52314 2127 */ {0x0061, 0x8656}, - /* Window1 size 128x128, Windows2 size 128x128, - * gamma look-up disable, new edge enhancement enable */ - /* 52339 2128 */ {0x0058, 0x8619}, - /* Window2 start X (*2) */ - /* 52364 2129 */ {0x0008, 0x861a}, - /* Window2 start Y (*2) */ - /* 52389 2130 */ {0x00ff, 0x8615}, - /* High lum thresh for white balance */ - /* 52414 2131 */ {0x0000, 0x8616}, - /* Low lum thresh for white balance */ - /* 52439 2132 */ {0x0012, 0x8700}, - /* Clock speed 48Mhz/(2+2)/2= 6 Mhz */ - /* 52464 2133 */ {0x0012, 0x8700}, - /* Clock speed 48Mhz/(2+2)/2= 6 Mhz */ - /* 52487 2134 */ /* READ { 0, 0x0000, 0x8656 } -> 0000: 61 */ - /* 52513 2135 */ {0x0028, 0x8802}, - /* 375 Khz SSI clock, SSI r/w sync with VSYNC */ - /* 52536 2136 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */ - /* 52560 2137 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 28 */ - /* 52586 2138 */ {0x1f28, 0x8802}, - /* 375 Khz SSI clock, SSI r/w sync with VSYNC */ - /* 52611 2139 */ {0x0010, 0x8801}, - /* SSI reg addr */ - /* 52636 2140 */ {0x003e, 0x8800}, - /* SSI data to write */ - /* 52659 2141 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */ - /* 52685 2142 */ {0x0028, 0x8802}, - /* 52708 2143 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */ - /* 52732 2144 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 28 */ - /* 52758 2145 */ {0x1f28, 0x8802}, - /* 52783 2146 */ {0x0000, 0x8801}, - /* 52808 2147 */ {0x001f, 0x8800}, - /* 52831 2148 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */ - /* 52857 2149 */ {0x0001, 0x8602}, - /* optical black level for user settning = 1 */ + {0x0021, 0x8508}, * Enable compression. */ + {0x0032, 0x850b}, /* compression stuff */ + {0x0003, 0x8509}, /* compression stuff */ + {0x0011, 0x850a}, /* compression stuff */ + {0x0021, 0x850d}, /* compression stuff */ + {0x0010, 0x850c}, /* compression stuff */ + {0x0003, 0x8500}, /* *** Video mode: 160x120 */ + {0x0001, 0x8501}, /* Hardware-dominated snap control */ + {0x0061, 0x8656}, /* Window1 size 128x128, Windows2 size 128x128, + * gamma look-up disable, + * new edge enhancement enable */ + {0x0018, 0x8617}, /* Window1 start X (*2) */ + {0x0008, 0x8618}, /* Window1 start Y (*2) */ + {0x0061, 0x8656}, /* Window1 size 128x128, Windows2 size 128x128, + * gamma look-up disable, + * new edge enhancement enable */ + {0x0058, 0x8619}, /* Window2 start X (*2) */ + {0x0008, 0x861a}, /* Window2 start Y (*2) */ + {0x00ff, 0x8615}, /* High lum thresh for white balance */ + {0x0000, 0x8616}, /* Low lum thresh for white balance */ + {0x0012, 0x8700}, /* Clock speed 48Mhz/(2+2)/2= 6 Mhz */ + {0x0012, 0x8700}, /* Clock speed 48Mhz/(2+2)/2= 6 Mhz */ + /* READ { 0x0000, 0x8656 } -> 0000: 61 */ + {0x0028, 0x8802}, /* 375 Khz SSI clock, SSI r/w sync with VSYNC */ + /* READ { 0x0001, 0x8803 } -> 0000: 00 */ + /* READ { 0x0001, 0x8802 } -> 0000: 28 */ + {0x1f28, 0x8802}, /* 375 Khz SSI clock, SSI r/w sync with VSYNC */ + {0x0010, 0x8801}, /* SSI reg addr */ + {0x003e, 0x8800}, /* SSI data to write */ + /* READ { 0x0001, 0x8803 } -> 0000: 00 */ + {0x0028, 0x8802}, + /* READ { 0x0001, 0x8803 } -> 0000: 00 */ + /* READ { 0x0001, 0x8802 } -> 0000: 28 */ + {0x1f28, 0x8802}, + {0x0000, 0x8801}, + {0x001f, 0x8800}, + /* READ { 0x0001, 0x8803 } -> 0000: 00 */ + {0x0001, 0x8602}, /* optical black level for user settning = 1 */ #if 0 /* NOTE: Code like this case lets this driver (often) work */ /* in 352x288 resolution, apparently by slowing down the */ /* clock. */ - /* 52464 2133 */ {0x002F, 0x8700}, - /* Clock speed */ + {0x002f, 0x8700}, /* Clock speed */ #else /* Original: */ - /* 52882 2150 */ {0x0023, 0x8700}, - /* Clock speed 48Mhz/(3+2)/4= 2.4 Mhz */ + {0x0023, 0x8700}, /* Clock speed 48Mhz/(3+2)/4= 2.4 Mhz */ #endif - /* 52907 2151 */ {0x000f, 0x8602}, - /* optical black level for user settning = 15 */ - - /* 52932 2152 */ {0x0028, 0x8802}, - /* 52955 2153 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */ - /* 52979 2154 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 28 */ - /* 53005 2155 */ {0x1f28, 0x8802}, - /* 53030 2156 */ {0x0010, 0x8801}, - /* 53055 2157 */ {0x007b, 0x8800}, - /* 53078 2158 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */ - /* 53104 2159 */ {0x002f, 0x8651}, - /* R gain for white balance ... */ - /* 53129 2160 */ {0x0080, 0x8653}, - /* 53152 2161 */ /* READ { 0, 0x0000, 0x8655 } -> 0000: 00 */ - /* 53178 2162 */ {0x0000, 0x8655}, - - /* 53203 2163 */ {0x0030, 0x8112}, - /* Video drop enable, ISO streaming enable */ - /* 53228 2164 */ {0x0020, 0x8112}, - /* Video drop enable, ISO streaming disable */ - /* 53252 2165 */ - /* UNKNOWN DIRECTION (URB_FUNCTION_SELECT_INTERFACE: (ALT=0) ) */ + {0x000f, 0x8602}, /* optical black level for user settning = 15 */ + + {0x0028, 0x8802}, + /* READ { 0x0001, 0x8803 } -> 0000: 00 */ + /* READ { 0x0001, 0x8802 } -> 0000: 28 */ + {0x1f28, 0x8802}, + {0x0010, 0x8801}, + {0x007b, 0x8800}, + /* READ { 0x0001, 0x8803 } -> 0000: 00 */ + {0x002f, 0x8651}, /* R gain for white balance ... */ + {0x0080, 0x8653}, + /* READ { 0x0000, 0x8655 } -> 0000: 00 */ + {0x0000, 0x8655}, + + {0x0030, 0x8112}, /* Video drop enable, ISO streaming enable */ + {0x0020, 0x8112}, /* Video drop enable, ISO streaming disable */ + /* UNKNOWN DIRECTION (URB_FUNCTION_SELECT_INTERFACE: (ALT=0) ) */ {} }; @@ -619,27 +552,27 @@ static const u16 spca508_init_data[][2] = * Initialization data for Intel EasyPC Camera CS110 */ static const u16 spca508cs110_init_data[][2] = { - {0x0000, 0x870b}, /* Reset CTL3 */ - {0x0003, 0x8111}, /* Soft Reset compression, memory, TG & CDSP */ - {0x0000, 0x8111}, /* Normal operation on reset */ + {0x0000, 0x870b}, /* Reset CTL3 */ + {0x0003, 0x8111}, /* Soft Reset compression, memory, TG & CDSP */ + {0x0000, 0x8111}, /* Normal operation on reset */ {0x0090, 0x8110}, /* External Clock 2x & Synchronous Serial Interface Output */ - {0x0020, 0x8112}, /* Video Drop packet enable */ - {0x0000, 0x8114}, /* Software GPIO output data */ + {0x0020, 0x8112}, /* Video Drop packet enable */ + {0x0000, 0x8114}, /* Software GPIO output data */ {0x0001, 0x8114}, {0x0001, 0x8114}, {0x0001, 0x8114}, {0x0003, 0x8114}, /* Initial sequence Synchronous Serial Interface */ - {0x000f, 0x8402}, /* Memory bank Address */ - {0x0000, 0x8403}, /* Memory bank Address */ - {0x00ba, 0x8804}, /* SSI Slave address */ - {0x0010, 0x8802}, /* 93.75kHz SSI Clock Two DataByte */ - {0x0010, 0x8802}, /* 93.75kHz SSI Clock two DataByte */ + {0x000f, 0x8402}, /* Memory bank Address */ + {0x0000, 0x8403}, /* Memory bank Address */ + {0x00ba, 0x8804}, /* SSI Slave address */ + {0x0010, 0x8802}, /* 93.75kHz SSI Clock Two DataByte */ + {0x0010, 0x8802}, /* 93.75kHz SSI Clock two DataByte */ {0x0001, 0x8801}, - {0x000a, 0x8805},/* a - NWG: Dunno what this is about */ + {0x000a, 0x8805}, /* a - NWG: Dunno what this is about */ {0x0000, 0x8800}, {0x0010, 0x8802}, @@ -673,459 +606,459 @@ static const u16 spca508cs110_init_data[][2] = { {0x0000, 0x8800}, {0x0010, 0x8802}, - {0x0002, 0x8704}, /* External input CKIx1 */ - {0x0001, 0x8606}, /* 1 Line memory Read Counter (H) Result: (d)410 */ - {0x009a, 0x8600}, /* Line memory Read Counter (L) */ - {0x0001, 0x865b}, /* 1 Horizontal Offset for Valid Pixel(L) */ - {0x0003, 0x865c}, /* 3 Vertical Offset for Valid Lines(L) */ - {0x0058, 0x865d}, /* 58 Horizontal Valid Pixel Window(L) */ + {0x0002, 0x8704}, /* External input CKIx1 */ + {0x0001, 0x8606}, /* 1 Line memory Read Counter (H) Result: (d)410 */ + {0x009a, 0x8600}, /* Line memory Read Counter (L) */ + {0x0001, 0x865b}, /* 1 Horizontal Offset for Valid Pixel(L) */ + {0x0003, 0x865c}, /* 3 Vertical Offset for Valid Lines(L) */ + {0x0058, 0x865d}, /* 58 Horizontal Valid Pixel Window(L) */ - {0x0006, 0x8660}, /* Nibble data + input order */ + {0x0006, 0x8660}, /* Nibble data + input order */ - {0x000a, 0x8602}, /* Optical black level set to 0x0a */ -/* 1945 */ {0x0000, 0x8603}, /* Optical black level Offset */ + {0x000a, 0x8602}, /* Optical black level set to 0x0a */ + {0x0000, 0x8603}, /* Optical black level Offset */ -/* 1962 * {0, 0x0000, 0x8611}, * 0 R Offset for white Balance */ -/* 1963 * {0, 0x0000, 0x8612}, * 1 Gr Offset for white Balance */ -/* 1964 * {0, 0x0000, 0x8613}, * 1f B Offset for white Balance */ -/* 1965 * {0, 0x0000, 0x8614}, * f0 Gb Offset for white Balance */ +/* {0x0000, 0x8611}, * 0 R Offset for white Balance */ +/* {0x0000, 0x8612}, * 1 Gr Offset for white Balance */ +/* {0x0000, 0x8613}, * 1f B Offset for white Balance */ +/* {0x0000, 0x8614}, * f0 Gb Offset for white Balance */ - {0x0040, 0x8651}, /* 2b BLUE gain for white balance good at all 60 */ - {0x0030, 0x8652}, /* 41 Gr Gain for white Balance (L) */ - {0x0035, 0x8653}, /* 26 RED gain for white balance */ - {0x0035, 0x8654}, /* 40Gb Gain for white Balance (L) */ + {0x0040, 0x8651}, /* 2b BLUE gain for white balance good at all 60 */ + {0x0030, 0x8652}, /* 41 Gr Gain for white Balance (L) */ + {0x0035, 0x8653}, /* 26 RED gain for white balance */ + {0x0035, 0x8654}, /* 40Gb Gain for white Balance (L) */ {0x0041, 0x863f}, /* Fixed Gamma correction enabled (makes colours look better) */ -/* 2422 */ {0x0000, 0x8655}, - /* High bits for white balance*****brightness control*** */ + {0x0000, 0x8655}, + /* High bits for white balance*****brightness control*** */ {} }; static const u16 spca508_sightcam_init_data[][2] = { /* This line seems to setup the frame/canvas */ - /*368 */ {0x000f, 0x8402}, + {0x000f, 0x8402}, /* Theese 6 lines are needed to startup the webcam */ - /*398 */ {0x0090, 0x8110}, - /*399 */ {0x0001, 0x8114}, - /*400 */ {0x0001, 0x8114}, - /*401 */ {0x0001, 0x8114}, - /*402 */ {0x0003, 0x8114}, - /*403 */ {0x0080, 0x8804}, + {0x0090, 0x8110}, + {0x0001, 0x8114}, + {0x0001, 0x8114}, + {0x0001, 0x8114}, + {0x0003, 0x8114}, + {0x0080, 0x8804}, /* This part seems to make the pictures darker? (autobrightness?) */ - /*436 */ {0x0001, 0x8801}, - /*437 */ {0x0004, 0x8800}, - /*439 */ {0x0003, 0x8801}, - /*440 */ {0x00e0, 0x8800}, - /*442 */ {0x0004, 0x8801}, - /*443 */ {0x00b4, 0x8800}, - /*445 */ {0x0005, 0x8801}, - /*446 */ {0x0000, 0x8800}, - - /*448 */ {0x0006, 0x8801}, - /*449 */ {0x00e0, 0x8800}, - /*451 */ {0x0007, 0x8801}, - /*452 */ {0x000c, 0x8800}, + {0x0001, 0x8801}, + {0x0004, 0x8800}, + {0x0003, 0x8801}, + {0x00e0, 0x8800}, + {0x0004, 0x8801}, + {0x00b4, 0x8800}, + {0x0005, 0x8801}, + {0x0000, 0x8800}, + + {0x0006, 0x8801}, + {0x00e0, 0x8800}, + {0x0007, 0x8801}, + {0x000c, 0x8800}, /* This section is just needed, it probably * does something like the previous section, * but the cam won't start if it's not included. */ - /*484 */ {0x0014, 0x8801}, - /*485 */ {0x0008, 0x8800}, - /*487 */ {0x0015, 0x8801}, - /*488 */ {0x0067, 0x8800}, - /*490 */ {0x0016, 0x8801}, - /*491 */ {0x0000, 0x8800}, - /*493 */ {0x0017, 0x8801}, - /*494 */ {0x0020, 0x8800}, - /*496 */ {0x0018, 0x8801}, - /*497 */ {0x0044, 0x8800}, + {0x0014, 0x8801}, + {0x0008, 0x8800}, + {0x0015, 0x8801}, + {0x0067, 0x8800}, + {0x0016, 0x8801}, + {0x0000, 0x8800}, + {0x0017, 0x8801}, + {0x0020, 0x8800}, + {0x0018, 0x8801}, + {0x0044, 0x8800}, /* Makes the picture darker - and the * cam won't start if not included */ - /*505 */ {0x001e, 0x8801}, - /*506 */ {0x00ea, 0x8800}, - /*508 */ {0x001f, 0x8801}, - /*509 */ {0x0001, 0x8800}, - /*511 */ {0x0003, 0x8801}, - /*512 */ {0x00e0, 0x8800}, + {0x001e, 0x8801}, + {0x00ea, 0x8800}, + {0x001f, 0x8801}, + {0x0001, 0x8800}, + {0x0003, 0x8801}, + {0x00e0, 0x8800}, /* seems to place the colors ontop of each other #1 */ - /*517 */ {0x0006, 0x8704}, - /*518 */ {0x0001, 0x870c}, - /*519 */ {0x0016, 0x8600}, - /*520 */ {0x0002, 0x8606}, + {0x0006, 0x8704}, + {0x0001, 0x870c}, + {0x0016, 0x8600}, + {0x0002, 0x8606}, /* if not included the pictures becomes _very_ dark */ - /*521 */ {0x0064, 0x8607}, - /*522 */ {0x003a, 0x8601}, - /*523 */ {0x0000, 0x8602}, + {0x0064, 0x8607}, + {0x003a, 0x8601}, + {0x0000, 0x8602}, /* seems to place the colors ontop of each other #2 */ - /*524 */ {0x0016, 0x8600}, - /*525 */ {0x0018, 0x8617}, - /*526 */ {0x0008, 0x8618}, - /*527 */ {0x00a1, 0x8656}, + {0x0016, 0x8600}, + {0x0018, 0x8617}, + {0x0008, 0x8618}, + {0x00a1, 0x8656}, /* webcam won't start if not included */ - /*528 */ {0x0007, 0x865b}, - /*529 */ {0x0001, 0x865c}, - /*530 */ {0x0058, 0x865d}, - /*531 */ {0x0048, 0x865e}, + {0x0007, 0x865b}, + {0x0001, 0x865c}, + {0x0058, 0x865d}, + {0x0048, 0x865e}, /* adjusts the colors */ - /*541 */ {0x0049, 0x8651}, - /*542 */ {0x0040, 0x8652}, - /*543 */ {0x004c, 0x8653}, - /*544 */ {0x0040, 0x8654}, + {0x0049, 0x8651}, + {0x0040, 0x8652}, + {0x004c, 0x8653}, + {0x0040, 0x8654}, {} }; static const u16 spca508_sightcam2_init_data[][2] = { -/* 35 */ {0x0020, 0x8112}, - -/* 36 */ {0x000f, 0x8402}, -/* 37 */ {0x0000, 0x8403}, - -/* 38 */ {0x0008, 0x8201}, -/* 39 */ {0x0008, 0x8200}, -/* 40 */ {0x0001, 0x8200}, -/* 43 */ {0x0009, 0x8201}, -/* 44 */ {0x0008, 0x8200}, -/* 45 */ {0x0001, 0x8200}, -/* 48 */ {0x000a, 0x8201}, -/* 49 */ {0x0008, 0x8200}, -/* 50 */ {0x0001, 0x8200}, -/* 53 */ {0x000b, 0x8201}, -/* 54 */ {0x0008, 0x8200}, -/* 55 */ {0x0001, 0x8200}, -/* 58 */ {0x000c, 0x8201}, -/* 59 */ {0x0008, 0x8200}, -/* 60 */ {0x0001, 0x8200}, -/* 63 */ {0x000d, 0x8201}, -/* 64 */ {0x0008, 0x8200}, -/* 65 */ {0x0001, 0x8200}, -/* 68 */ {0x000e, 0x8201}, -/* 69 */ {0x0008, 0x8200}, -/* 70 */ {0x0001, 0x8200}, -/* 73 */ {0x0007, 0x8201}, -/* 74 */ {0x0008, 0x8200}, -/* 75 */ {0x0001, 0x8200}, -/* 78 */ {0x000f, 0x8201}, -/* 79 */ {0x0008, 0x8200}, -/* 80 */ {0x0001, 0x8200}, - -/* 84 */ {0x0018, 0x8660}, -/* 85 */ {0x0010, 0x8201}, - -/* 86 */ {0x0008, 0x8200}, -/* 87 */ {0x0001, 0x8200}, -/* 90 */ {0x0011, 0x8201}, -/* 91 */ {0x0008, 0x8200}, -/* 92 */ {0x0001, 0x8200}, - -/* 95 */ {0x0000, 0x86b0}, -/* 96 */ {0x0034, 0x86b1}, -/* 97 */ {0x0000, 0x86b2}, -/* 98 */ {0x0049, 0x86b3}, -/* 99 */ {0x0000, 0x86b4}, -/* 100 */ {0x0000, 0x86b4}, - -/* 101 */ {0x0012, 0x8201}, -/* 102 */ {0x0008, 0x8200}, -/* 103 */ {0x0001, 0x8200}, -/* 106 */ {0x0013, 0x8201}, -/* 107 */ {0x0008, 0x8200}, -/* 108 */ {0x0001, 0x8200}, - -/* 111 */ {0x0001, 0x86b0}, -/* 112 */ {0x00aa, 0x86b1}, -/* 113 */ {0x0000, 0x86b2}, -/* 114 */ {0x00e4, 0x86b3}, -/* 115 */ {0x0000, 0x86b4}, -/* 116 */ {0x0000, 0x86b4}, - -/* 118 */ {0x0018, 0x8660}, - -/* 119 */ {0x0090, 0x8110}, -/* 120 */ {0x0001, 0x8114}, -/* 121 */ {0x0001, 0x8114}, -/* 122 */ {0x0001, 0x8114}, -/* 123 */ {0x0003, 0x8114}, - -/* 124 */ {0x0080, 0x8804}, -/* 157 */ {0x0003, 0x8801}, -/* 158 */ {0x0012, 0x8800}, -/* 160 */ {0x0004, 0x8801}, -/* 161 */ {0x0005, 0x8800}, -/* 163 */ {0x0005, 0x8801}, -/* 164 */ {0x0000, 0x8800}, -/* 166 */ {0x0006, 0x8801}, -/* 167 */ {0x0000, 0x8800}, -/* 169 */ {0x0007, 0x8801}, -/* 170 */ {0x0000, 0x8800}, -/* 172 */ {0x0008, 0x8801}, -/* 173 */ {0x0005, 0x8800}, -/* 175 */ {0x000a, 0x8700}, -/* 176 */ {0x000e, 0x8801}, -/* 177 */ {0x0004, 0x8800}, -/* 179 */ {0x0005, 0x8801}, -/* 180 */ {0x0047, 0x8800}, -/* 182 */ {0x0006, 0x8801}, -/* 183 */ {0x0000, 0x8800}, -/* 185 */ {0x0007, 0x8801}, -/* 186 */ {0x00c0, 0x8800}, -/* 188 */ {0x0008, 0x8801}, -/* 189 */ {0x0003, 0x8800}, -/* 191 */ {0x0013, 0x8801}, -/* 192 */ {0x0001, 0x8800}, -/* 194 */ {0x0009, 0x8801}, -/* 195 */ {0x0000, 0x8800}, -/* 197 */ {0x000a, 0x8801}, -/* 198 */ {0x0000, 0x8800}, -/* 200 */ {0x000b, 0x8801}, -/* 201 */ {0x0000, 0x8800}, -/* 203 */ {0x000c, 0x8801}, -/* 204 */ {0x0000, 0x8800}, -/* 206 */ {0x000e, 0x8801}, -/* 207 */ {0x0004, 0x8800}, -/* 209 */ {0x000f, 0x8801}, -/* 210 */ {0x0000, 0x8800}, -/* 212 */ {0x0010, 0x8801}, -/* 213 */ {0x0006, 0x8800}, -/* 215 */ {0x0011, 0x8801}, -/* 216 */ {0x0006, 0x8800}, -/* 218 */ {0x0012, 0x8801}, -/* 219 */ {0x0000, 0x8800}, -/* 221 */ {0x0013, 0x8801}, -/* 222 */ {0x0001, 0x8800}, - -/* 224 */ {0x000a, 0x8700}, -/* 225 */ {0x0000, 0x8702}, -/* 226 */ {0x0000, 0x8703}, -/* 227 */ {0x00c2, 0x8704}, -/* 228 */ {0x0001, 0x870c}, - -/* 229 */ {0x0044, 0x8600}, -/* 230 */ {0x0002, 0x8606}, -/* 231 */ {0x0064, 0x8607}, -/* 232 */ {0x003a, 0x8601}, -/* 233 */ {0x0008, 0x8602}, -/* 234 */ {0x0044, 0x8600}, -/* 235 */ {0x0018, 0x8617}, -/* 236 */ {0x0008, 0x8618}, -/* 237 */ {0x00a1, 0x8656}, -/* 238 */ {0x0004, 0x865b}, -/* 239 */ {0x0002, 0x865c}, -/* 240 */ {0x0058, 0x865d}, -/* 241 */ {0x0048, 0x865e}, -/* 242 */ {0x0012, 0x8608}, -/* 243 */ {0x002c, 0x8609}, -/* 244 */ {0x0002, 0x860a}, -/* 245 */ {0x002c, 0x860b}, -/* 246 */ {0x00db, 0x860c}, -/* 247 */ {0x00f9, 0x860d}, -/* 248 */ {0x00f1, 0x860e}, -/* 249 */ {0x00e3, 0x860f}, -/* 250 */ {0x002c, 0x8610}, -/* 251 */ {0x006c, 0x8651}, -/* 252 */ {0x0041, 0x8652}, -/* 253 */ {0x0059, 0x8653}, -/* 254 */ {0x0040, 0x8654}, -/* 255 */ {0x00fa, 0x8611}, -/* 256 */ {0x00ff, 0x8612}, -/* 257 */ {0x00f8, 0x8613}, -/* 258 */ {0x0000, 0x8614}, -/* 259 */ {0x0001, 0x863f}, -/* 260 */ {0x0000, 0x8640}, -/* 261 */ {0x0026, 0x8641}, -/* 262 */ {0x0045, 0x8642}, -/* 263 */ {0x0060, 0x8643}, -/* 264 */ {0x0075, 0x8644}, -/* 265 */ {0x0088, 0x8645}, -/* 266 */ {0x009b, 0x8646}, -/* 267 */ {0x00b0, 0x8647}, -/* 268 */ {0x00c5, 0x8648}, -/* 269 */ {0x00d2, 0x8649}, -/* 270 */ {0x00dc, 0x864a}, -/* 271 */ {0x00e5, 0x864b}, -/* 272 */ {0x00eb, 0x864c}, -/* 273 */ {0x00f0, 0x864d}, -/* 274 */ {0x00f6, 0x864e}, -/* 275 */ {0x00fa, 0x864f}, -/* 276 */ {0x00ff, 0x8650}, -/* 277 */ {0x0060, 0x8657}, -/* 278 */ {0x0010, 0x8658}, -/* 279 */ {0x0018, 0x8659}, -/* 280 */ {0x0005, 0x865a}, -/* 281 */ {0x0018, 0x8660}, -/* 282 */ {0x0003, 0x8509}, -/* 283 */ {0x0011, 0x850a}, -/* 284 */ {0x0032, 0x850b}, -/* 285 */ {0x0010, 0x850c}, -/* 286 */ {0x0021, 0x850d}, -/* 287 */ {0x0001, 0x8500}, -/* 288 */ {0x0000, 0x8508}, -/* 289 */ {0x0012, 0x8608}, -/* 290 */ {0x002c, 0x8609}, -/* 291 */ {0x0002, 0x860a}, -/* 292 */ {0x0039, 0x860b}, -/* 293 */ {0x00d0, 0x860c}, -/* 294 */ {0x00f7, 0x860d}, -/* 295 */ {0x00ed, 0x860e}, -/* 296 */ {0x00db, 0x860f}, -/* 297 */ {0x0039, 0x8610}, -/* 298 */ {0x0012, 0x8657}, -/* 299 */ {0x000c, 0x8619}, -/* 300 */ {0x0004, 0x861a}, -/* 301 */ {0x00a1, 0x8656}, -/* 302 */ {0x00c8, 0x8615}, -/* 303 */ {0x0032, 0x8616}, - -/* 306 */ {0x0030, 0x8112}, -/* 313 */ {0x0020, 0x8112}, -/* 314 */ {0x0020, 0x8112}, -/* 315 */ {0x000f, 0x8402}, -/* 316 */ {0x0000, 0x8403}, - -/* 317 */ {0x0090, 0x8110}, -/* 318 */ {0x0001, 0x8114}, -/* 319 */ {0x0001, 0x8114}, -/* 320 */ {0x0001, 0x8114}, -/* 321 */ {0x0003, 0x8114}, -/* 322 */ {0x0080, 0x8804}, - -/* 355 */ {0x0003, 0x8801}, -/* 356 */ {0x0012, 0x8800}, -/* 358 */ {0x0004, 0x8801}, -/* 359 */ {0x0005, 0x8800}, -/* 361 */ {0x0005, 0x8801}, -/* 362 */ {0x0047, 0x8800}, -/* 364 */ {0x0006, 0x8801}, -/* 365 */ {0x0000, 0x8800}, -/* 367 */ {0x0007, 0x8801}, -/* 368 */ {0x00c0, 0x8800}, -/* 370 */ {0x0008, 0x8801}, -/* 371 */ {0x0003, 0x8800}, -/* 373 */ {0x000a, 0x8700}, -/* 374 */ {0x000e, 0x8801}, -/* 375 */ {0x0004, 0x8800}, -/* 377 */ {0x0005, 0x8801}, -/* 378 */ {0x0047, 0x8800}, -/* 380 */ {0x0006, 0x8801}, -/* 381 */ {0x0000, 0x8800}, -/* 383 */ {0x0007, 0x8801}, -/* 384 */ {0x00c0, 0x8800}, -/* 386 */ {0x0008, 0x8801}, -/* 387 */ {0x0003, 0x8800}, -/* 389 */ {0x0013, 0x8801}, -/* 390 */ {0x0001, 0x8800}, -/* 392 */ {0x0009, 0x8801}, -/* 393 */ {0x0000, 0x8800}, -/* 395 */ {0x000a, 0x8801}, -/* 396 */ {0x0000, 0x8800}, -/* 398 */ {0x000b, 0x8801}, -/* 399 */ {0x0000, 0x8800}, -/* 401 */ {0x000c, 0x8801}, -/* 402 */ {0x0000, 0x8800}, -/* 404 */ {0x000e, 0x8801}, -/* 405 */ {0x0004, 0x8800}, -/* 407 */ {0x000f, 0x8801}, -/* 408 */ {0x0000, 0x8800}, -/* 410 */ {0x0010, 0x8801}, -/* 411 */ {0x0006, 0x8800}, -/* 413 */ {0x0011, 0x8801}, -/* 414 */ {0x0006, 0x8800}, -/* 416 */ {0x0012, 0x8801}, -/* 417 */ {0x0000, 0x8800}, -/* 419 */ {0x0013, 0x8801}, -/* 420 */ {0x0001, 0x8800}, -/* 422 */ {0x000a, 0x8700}, -/* 423 */ {0x0000, 0x8702}, -/* 424 */ {0x0000, 0x8703}, -/* 425 */ {0x00c2, 0x8704}, -/* 426 */ {0x0001, 0x870c}, -/* 427 */ {0x0044, 0x8600}, -/* 428 */ {0x0002, 0x8606}, -/* 429 */ {0x0064, 0x8607}, -/* 430 */ {0x003a, 0x8601}, -/* 431 */ {0x0008, 0x8602}, -/* 432 */ {0x0044, 0x8600}, -/* 433 */ {0x0018, 0x8617}, -/* 434 */ {0x0008, 0x8618}, -/* 435 */ {0x00a1, 0x8656}, -/* 436 */ {0x0004, 0x865b}, -/* 437 */ {0x0002, 0x865c}, -/* 438 */ {0x0058, 0x865d}, -/* 439 */ {0x0048, 0x865e}, -/* 440 */ {0x0012, 0x8608}, -/* 441 */ {0x002c, 0x8609}, -/* 442 */ {0x0002, 0x860a}, -/* 443 */ {0x002c, 0x860b}, -/* 444 */ {0x00db, 0x860c}, -/* 445 */ {0x00f9, 0x860d}, -/* 446 */ {0x00f1, 0x860e}, -/* 447 */ {0x00e3, 0x860f}, -/* 448 */ {0x002c, 0x8610}, -/* 449 */ {0x006c, 0x8651}, -/* 450 */ {0x0041, 0x8652}, -/* 451 */ {0x0059, 0x8653}, -/* 452 */ {0x0040, 0x8654}, -/* 453 */ {0x00fa, 0x8611}, -/* 454 */ {0x00ff, 0x8612}, -/* 455 */ {0x00f8, 0x8613}, -/* 456 */ {0x0000, 0x8614}, -/* 457 */ {0x0001, 0x863f}, -/* 458 */ {0x0000, 0x8640}, -/* 459 */ {0x0026, 0x8641}, -/* 460 */ {0x0045, 0x8642}, -/* 461 */ {0x0060, 0x8643}, -/* 462 */ {0x0075, 0x8644}, -/* 463 */ {0x0088, 0x8645}, -/* 464 */ {0x009b, 0x8646}, -/* 465 */ {0x00b0, 0x8647}, -/* 466 */ {0x00c5, 0x8648}, -/* 467 */ {0x00d2, 0x8649}, -/* 468 */ {0x00dc, 0x864a}, -/* 469 */ {0x00e5, 0x864b}, -/* 470 */ {0x00eb, 0x864c}, -/* 471 */ {0x00f0, 0x864d}, -/* 472 */ {0x00f6, 0x864e}, -/* 473 */ {0x00fa, 0x864f}, -/* 474 */ {0x00ff, 0x8650}, -/* 475 */ {0x0060, 0x8657}, -/* 476 */ {0x0010, 0x8658}, -/* 477 */ {0x0018, 0x8659}, -/* 478 */ {0x0005, 0x865a}, -/* 479 */ {0x0018, 0x8660}, -/* 480 */ {0x0003, 0x8509}, -/* 481 */ {0x0011, 0x850a}, -/* 482 */ {0x0032, 0x850b}, -/* 483 */ {0x0010, 0x850c}, -/* 484 */ {0x0021, 0x850d}, -/* 485 */ {0x0001, 0x8500}, -/* 486 */ {0x0000, 0x8508}, - -/* 487 */ {0x0012, 0x8608}, -/* 488 */ {0x002c, 0x8609}, -/* 489 */ {0x0002, 0x860a}, -/* 490 */ {0x0039, 0x860b}, -/* 491 */ {0x00d0, 0x860c}, -/* 492 */ {0x00f7, 0x860d}, -/* 493 */ {0x00ed, 0x860e}, -/* 494 */ {0x00db, 0x860f}, -/* 495 */ {0x0039, 0x8610}, -/* 496 */ {0x0012, 0x8657}, -/* 497 */ {0x0064, 0x8619}, + {0x0020, 0x8112}, + + {0x000f, 0x8402}, + {0x0000, 0x8403}, + + {0x0008, 0x8201}, + {0x0008, 0x8200}, + {0x0001, 0x8200}, + {0x0009, 0x8201}, + {0x0008, 0x8200}, + {0x0001, 0x8200}, + {0x000a, 0x8201}, + {0x0008, 0x8200}, + {0x0001, 0x8200}, + {0x000b, 0x8201}, + {0x0008, 0x8200}, + {0x0001, 0x8200}, + {0x000c, 0x8201}, + {0x0008, 0x8200}, + {0x0001, 0x8200}, + {0x000d, 0x8201}, + {0x0008, 0x8200}, + {0x0001, 0x8200}, + {0x000e, 0x8201}, + {0x0008, 0x8200}, + {0x0001, 0x8200}, + {0x0007, 0x8201}, + {0x0008, 0x8200}, + {0x0001, 0x8200}, + {0x000f, 0x8201}, + {0x0008, 0x8200}, + {0x0001, 0x8200}, + + {0x0018, 0x8660}, + {0x0010, 0x8201}, + + {0x0008, 0x8200}, + {0x0001, 0x8200}, + {0x0011, 0x8201}, + {0x0008, 0x8200}, + {0x0001, 0x8200}, + + {0x0000, 0x86b0}, + {0x0034, 0x86b1}, + {0x0000, 0x86b2}, + {0x0049, 0x86b3}, + {0x0000, 0x86b4}, + {0x0000, 0x86b4}, + + {0x0012, 0x8201}, + {0x0008, 0x8200}, + {0x0001, 0x8200}, + {0x0013, 0x8201}, + {0x0008, 0x8200}, + {0x0001, 0x8200}, + + {0x0001, 0x86b0}, + {0x00aa, 0x86b1}, + {0x0000, 0x86b2}, + {0x00e4, 0x86b3}, + {0x0000, 0x86b4}, + {0x0000, 0x86b4}, + + {0x0018, 0x8660}, + + {0x0090, 0x8110}, + {0x0001, 0x8114}, + {0x0001, 0x8114}, + {0x0001, 0x8114}, + {0x0003, 0x8114}, + + {0x0080, 0x8804}, + {0x0003, 0x8801}, + {0x0012, 0x8800}, + {0x0004, 0x8801}, + {0x0005, 0x8800}, + {0x0005, 0x8801}, + {0x0000, 0x8800}, + {0x0006, 0x8801}, + {0x0000, 0x8800}, + {0x0007, 0x8801}, + {0x0000, 0x8800}, + {0x0008, 0x8801}, + {0x0005, 0x8800}, + {0x000a, 0x8700}, + {0x000e, 0x8801}, + {0x0004, 0x8800}, + {0x0005, 0x8801}, + {0x0047, 0x8800}, + {0x0006, 0x8801}, + {0x0000, 0x8800}, + {0x0007, 0x8801}, + {0x00c0, 0x8800}, + {0x0008, 0x8801}, + {0x0003, 0x8800}, + {0x0013, 0x8801}, + {0x0001, 0x8800}, + {0x0009, 0x8801}, + {0x0000, 0x8800}, + {0x000a, 0x8801}, + {0x0000, 0x8800}, + {0x000b, 0x8801}, + {0x0000, 0x8800}, + {0x000c, 0x8801}, + {0x0000, 0x8800}, + {0x000e, 0x8801}, + {0x0004, 0x8800}, + {0x000f, 0x8801}, + {0x0000, 0x8800}, + {0x0010, 0x8801}, + {0x0006, 0x8800}, + {0x0011, 0x8801}, + {0x0006, 0x8800}, + {0x0012, 0x8801}, + {0x0000, 0x8800}, + {0x0013, 0x8801}, + {0x0001, 0x8800}, + + {0x000a, 0x8700}, + {0x0000, 0x8702}, + {0x0000, 0x8703}, + {0x00c2, 0x8704}, + {0x0001, 0x870c}, + + {0x0044, 0x8600}, + {0x0002, 0x8606}, + {0x0064, 0x8607}, + {0x003a, 0x8601}, + {0x0008, 0x8602}, + {0x0044, 0x8600}, + {0x0018, 0x8617}, + {0x0008, 0x8618}, + {0x00a1, 0x8656}, + {0x0004, 0x865b}, + {0x0002, 0x865c}, + {0x0058, 0x865d}, + {0x0048, 0x865e}, + {0x0012, 0x8608}, + {0x002c, 0x8609}, + {0x0002, 0x860a}, + {0x002c, 0x860b}, + {0x00db, 0x860c}, + {0x00f9, 0x860d}, + {0x00f1, 0x860e}, + {0x00e3, 0x860f}, + {0x002c, 0x8610}, + {0x006c, 0x8651}, + {0x0041, 0x8652}, + {0x0059, 0x8653}, + {0x0040, 0x8654}, + {0x00fa, 0x8611}, + {0x00ff, 0x8612}, + {0x00f8, 0x8613}, + {0x0000, 0x8614}, + {0x0001, 0x863f}, + {0x0000, 0x8640}, + {0x0026, 0x8641}, + {0x0045, 0x8642}, + {0x0060, 0x8643}, + {0x0075, 0x8644}, + {0x0088, 0x8645}, + {0x009b, 0x8646}, + {0x00b0, 0x8647}, + {0x00c5, 0x8648}, + {0x00d2, 0x8649}, + {0x00dc, 0x864a}, + {0x00e5, 0x864b}, + {0x00eb, 0x864c}, + {0x00f0, 0x864d}, + {0x00f6, 0x864e}, + {0x00fa, 0x864f}, + {0x00ff, 0x8650}, + {0x0060, 0x8657}, + {0x0010, 0x8658}, + {0x0018, 0x8659}, + {0x0005, 0x865a}, + {0x0018, 0x8660}, + {0x0003, 0x8509}, + {0x0011, 0x850a}, + {0x0032, 0x850b}, + {0x0010, 0x850c}, + {0x0021, 0x850d}, + {0x0001, 0x8500}, + {0x0000, 0x8508}, + {0x0012, 0x8608}, + {0x002c, 0x8609}, + {0x0002, 0x860a}, + {0x0039, 0x860b}, + {0x00d0, 0x860c}, + {0x00f7, 0x860d}, + {0x00ed, 0x860e}, + {0x00db, 0x860f}, + {0x0039, 0x8610}, + {0x0012, 0x8657}, + {0x000c, 0x8619}, + {0x0004, 0x861a}, + {0x00a1, 0x8656}, + {0x00c8, 0x8615}, + {0x0032, 0x8616}, + + {0x0030, 0x8112}, + {0x0020, 0x8112}, + {0x0020, 0x8112}, + {0x000f, 0x8402}, + {0x0000, 0x8403}, + + {0x0090, 0x8110}, + {0x0001, 0x8114}, + {0x0001, 0x8114}, + {0x0001, 0x8114}, + {0x0003, 0x8114}, + {0x0080, 0x8804}, + + {0x0003, 0x8801}, + {0x0012, 0x8800}, + {0x0004, 0x8801}, + {0x0005, 0x8800}, + {0x0005, 0x8801}, + {0x0047, 0x8800}, + {0x0006, 0x8801}, + {0x0000, 0x8800}, + {0x0007, 0x8801}, + {0x00c0, 0x8800}, + {0x0008, 0x8801}, + {0x0003, 0x8800}, + {0x000a, 0x8700}, + {0x000e, 0x8801}, + {0x0004, 0x8800}, + {0x0005, 0x8801}, + {0x0047, 0x8800}, + {0x0006, 0x8801}, + {0x0000, 0x8800}, + {0x0007, 0x8801}, + {0x00c0, 0x8800}, + {0x0008, 0x8801}, + {0x0003, 0x8800}, + {0x0013, 0x8801}, + {0x0001, 0x8800}, + {0x0009, 0x8801}, + {0x0000, 0x8800}, + {0x000a, 0x8801}, + {0x0000, 0x8800}, + {0x000b, 0x8801}, + {0x0000, 0x8800}, + {0x000c, 0x8801}, + {0x0000, 0x8800}, + {0x000e, 0x8801}, + {0x0004, 0x8800}, + {0x000f, 0x8801}, + {0x0000, 0x8800}, + {0x0010, 0x8801}, + {0x0006, 0x8800}, + {0x0011, 0x8801}, + {0x0006, 0x8800}, + {0x0012, 0x8801}, + {0x0000, 0x8800}, + {0x0013, 0x8801}, + {0x0001, 0x8800}, + {0x000a, 0x8700}, + {0x0000, 0x8702}, + {0x0000, 0x8703}, + {0x00c2, 0x8704}, + {0x0001, 0x870c}, + {0x0044, 0x8600}, + {0x0002, 0x8606}, + {0x0064, 0x8607}, + {0x003a, 0x8601}, + {0x0008, 0x8602}, + {0x0044, 0x8600}, + {0x0018, 0x8617}, + {0x0008, 0x8618}, + {0x00a1, 0x8656}, + {0x0004, 0x865b}, + {0x0002, 0x865c}, + {0x0058, 0x865d}, + {0x0048, 0x865e}, + {0x0012, 0x8608}, + {0x002c, 0x8609}, + {0x0002, 0x860a}, + {0x002c, 0x860b}, + {0x00db, 0x860c}, + {0x00f9, 0x860d}, + {0x00f1, 0x860e}, + {0x00e3, 0x860f}, + {0x002c, 0x8610}, + {0x006c, 0x8651}, + {0x0041, 0x8652}, + {0x0059, 0x8653}, + {0x0040, 0x8654}, + {0x00fa, 0x8611}, + {0x00ff, 0x8612}, + {0x00f8, 0x8613}, + {0x0000, 0x8614}, + {0x0001, 0x863f}, + {0x0000, 0x8640}, + {0x0026, 0x8641}, + {0x0045, 0x8642}, + {0x0060, 0x8643}, + {0x0075, 0x8644}, + {0x0088, 0x8645}, + {0x009b, 0x8646}, + {0x00b0, 0x8647}, + {0x00c5, 0x8648}, + {0x00d2, 0x8649}, + {0x00dc, 0x864a}, + {0x00e5, 0x864b}, + {0x00eb, 0x864c}, + {0x00f0, 0x864d}, + {0x00f6, 0x864e}, + {0x00fa, 0x864f}, + {0x00ff, 0x8650}, + {0x0060, 0x8657}, + {0x0010, 0x8658}, + {0x0018, 0x8659}, + {0x0005, 0x865a}, + {0x0018, 0x8660}, + {0x0003, 0x8509}, + {0x0011, 0x850a}, + {0x0032, 0x850b}, + {0x0010, 0x850c}, + {0x0021, 0x850d}, + {0x0001, 0x8500}, + {0x0000, 0x8508}, + + {0x0012, 0x8608}, + {0x002c, 0x8609}, + {0x0002, 0x860a}, + {0x0039, 0x860b}, + {0x00d0, 0x860c}, + {0x00f7, 0x860d}, + {0x00ed, 0x860e}, + {0x00db, 0x860f}, + {0x0039, 0x8610}, + {0x0012, 0x8657}, + {0x0064, 0x8619}, /* This line starts it all, it is not needed here */ /* since it has been build into the driver */ /* jfm: don't start now */ -/* 590 * {0x0030, 0x8112}, */ +/* {0x0030, 0x8112}, */ {} }; @@ -1136,14 +1069,14 @@ static const u16 spca508_vista_init_data[][2] = { {0x0008, 0x8200}, /* Clear register */ {0x0000, 0x870b}, /* Reset CTL3 */ {0x0020, 0x8112}, /* Video Drop packet enable */ - {0x0003, 0x8111}, /* Soft Reset compression, memory, TG & CDSP */ + {0x0003, 0x8111}, /* Soft Reset compression, memory, TG & CDSP */ {0x0000, 0x8110}, /* Disable everything */ {0x0000, 0x8114}, /* Software GPIO output data */ {0x0000, 0x8114}, {0x0003, 0x8111}, {0x0000, 0x8111}, - {0x0090, 0x8110}, /* Enable: SSI output, External 2X clock output */ + {0x0090, 0x8110}, /* Enable: SSI output, External 2X clock output */ {0x0020, 0x8112}, {0x0000, 0x8114}, {0x0001, 0x8114}, @@ -1156,191 +1089,143 @@ static const u16 spca508_vista_init_data[][2] = { {0x00ba, 0x8804}, /* SSI Slave address */ {0x0010, 0x8802}, /* 93.75kHz SSI Clock Two DataByte */ - /* READ { 0, 0x0001, 0x8803 } -> - 0000: 00 */ - /* READ { 0, 0x0001, 0x8802 } -> - 0000: 10 */ + /* READ { 0x0001, 0x8803 } -> 0000: 00 */ + /* READ { 0x0001, 0x8802 } -> 0000: 10 */ {0x0010, 0x8802}, /* Will write 2 bytes (DATA1+DATA2) */ {0x0020, 0x8801}, /* Register address for SSI read/write */ {0x0044, 0x8805}, /* DATA2 */ {0x0004, 0x8800}, /* DATA1 -> write triggered */ - /* READ { 0, 0x0001, 0x8803 } -> - 0000: 00 */ + /* READ { 0x0001, 0x8803 } -> 0000: 00 */ - /* READ { 0, 0x0001, 0x8803 } -> - 0000: 00 */ - /* READ { 0, 0x0001, 0x8802 } -> - 0000: 10 */ + /* READ { 0x0001, 0x8803 } -> 0000: 00 */ + /* READ { 0x0001, 0x8802 } -> 0000: 10 */ {0x0010, 0x8802}, {0x0009, 0x8801}, {0x0042, 0x8805}, {0x0001, 0x8800}, - /* READ { 0, 0x0001, 0x8803 } -> - 0000: 00 */ + /* READ { 0x0001, 0x8803 } -> 0000: 00 */ - /* READ { 0, 0x0001, 0x8803 } -> - 0000: 00 */ - /* READ { 0, 0x0001, 0x8802 } -> - 0000: 10 */ + /* READ { 0x0001, 0x8803 } -> 0000: 00 */ + /* READ { 0x0001, 0x8802 } -> 0000: 10 */ {0x0010, 0x8802}, {0x003c, 0x8801}, {0x0001, 0x8805}, {0x0000, 0x8800}, - /* READ { 0, 0x0001, 0x8803 } -> - 0000: 00 */ + /* READ { 0x0001, 0x8803 } -> 0000: 00 */ - /* READ { 0, 0x0001, 0x8803 } -> - 0000: 00 */ - /* READ { 0, 0x0001, 0x8802 } -> - 0000: 10 */ + /* READ { 0x0001, 0x8803 } -> 0000: 00 */ + /* READ { 0x0001, 0x8802 } -> 0000: 10 */ {0x0010, 0x8802}, {0x0001, 0x8801}, {0x000a, 0x8805}, {0x0000, 0x8800}, - /* READ { 0, 0x0001, 0x8803 } -> - 0000: 00 */ + /* READ { 0x0001, 0x8803 } -> 0000: 00 */ - /* READ { 0, 0x0001, 0x8803 } -> - 0000: 00 */ - /* READ { 0, 0x0001, 0x8802 } -> - 0000: 10 */ + /* READ { 0x0001, 0x8803 } -> 0000: 00 */ + /* READ { 0x0001, 0x8802 } -> 0000: 10 */ {0x0010, 0x8802}, {0x0002, 0x8801}, {0x0000, 0x8805}, {0x0000, 0x8800}, - /* READ { 0, 0x0001, 0x8803 } -> - 0000: 00 */ + /* READ { 0x0001, 0x8803 } -> 0000: 00 */ - /* READ { 0, 0x0001, 0x8803 } -> - 0000: 00 */ - /* READ { 0, 0x0001, 0x8802 } -> - 0000: 10 */ + /* READ { 0x0001, 0x8803 } -> 0000: 00 */ + /* READ { 0x0001, 0x8802 } -> 0000: 10 */ {0x0010, 0x8802}, {0x0003, 0x8801}, {0x0027, 0x8805}, {0x0001, 0x8800}, - /* READ { 0, 0x0001, 0x8803 } -> - 0000: 00 */ + /* READ { 0x0001, 0x8803 } -> 0000: 00 */ - /* READ { 0, 0x0001, 0x8803 } -> - 0000: 00 */ - /* READ { 0, 0x0001, 0x8802 } -> - 0000: 10 */ + /* READ { 0x0001, 0x8803 } -> 0000: 00 */ + /* READ { 0x0001, 0x8802 } -> 0000: 10 */ {0x0010, 0x8802}, {0x0004, 0x8801}, {0x0065, 0x8805}, {0x0001, 0x8800}, - /* READ { 0, 0x0001, 0x8803 } -> - 0000: 00 */ + /* READ { 0x0001, 0x8803 } -> 0000: 00 */ - /* READ { 0, 0x0001, 0x8803 } -> - 0000: 00 */ - /* READ { 0, 0x0001, 0x8802 } -> - 0000: 10 */ + /* READ { 0x0001, 0x8803 } -> 0000: 00 */ + /* READ { 0x0001, 0x8802 } -> 0000: 10 */ {0x0010, 0x8802}, {0x0005, 0x8801}, {0x0003, 0x8805}, {0x0000, 0x8800}, - /* READ { 0, 0x0001, 0x8803 } -> - 0000: 00 */ + /* READ { 0x0001, 0x8803 } -> 0000: 00 */ - /* READ { 0, 0x0001, 0x8803 } -> - 0000: 00 */ - /* READ { 0, 0x0001, 0x8802 } -> - 0000: 10 */ + /* READ { 0x0001, 0x8803 } -> 0000: 00 */ + /* READ { 0x0001, 0x8802 } -> 0000: 10 */ {0x0010, 0x8802}, {0x0006, 0x8801}, {0x001c, 0x8805}, {0x0000, 0x8800}, - /* READ { 0, 0x0001, 0x8803 } -> - 0000: 00 */ + /* READ { 0x0001, 0x8803 } -> 0000: 00 */ - /* READ { 0, 0x0001, 0x8803 } -> - 0000: 00 */ - /* READ { 0, 0x0001, 0x8802 } -> - 0000: 10 */ + /* READ { 0x0001, 0x8803 } -> 0000: 00 */ + /* READ { 0x0001, 0x8802 } -> 0000: 10 */ {0x0010, 0x8802}, {0x0007, 0x8801}, {0x002a, 0x8805}, {0x0000, 0x8800}, - /* READ { 0, 0x0001, 0x8803 } -> - 0000: 00 */ + /* READ { 0x0001, 0x8803 } -> 0000: 00 */ - /* READ { 0, 0x0001, 0x8803 } -> - 0000: 00 */ - /* READ { 0, 0x0001, 0x8802 } -> - 0000: 10 */ + /* READ { 0x0001, 0x8803 } -> 0000: 00 */ + /* READ { 0x0001, 0x8802 } -> 0000: 10 */ {0x0010, 0x8802}, {0x000e, 0x8801}, {0x0000, 0x8805}, {0x0000, 0x8800}, - /* READ { 0, 0x0001, 0x8803 } -> - 0000: 00 */ + /* READ { 0x0001, 0x8803 } -> 0000: 00 */ - /* READ { 0, 0x0001, 0x8803 } -> - 0000: 00 */ - /* READ { 0, 0x0001, 0x8802 } -> - 0000: 10 */ + /* READ { 0x0001, 0x8803 } -> 0000: 00 */ + /* READ { 0x0001, 0x8802 } -> 0000: 10 */ {0x0010, 0x8802}, {0x0028, 0x8801}, {0x002e, 0x8805}, {0x0000, 0x8800}, - /* READ { 0, 0x0001, 0x8803 } -> - 0000: 00 */ + /* READ { 0x0001, 0x8803 } -> 0000: 00 */ - /* READ { 0, 0x0001, 0x8803 } -> - 0000: 00 */ - /* READ { 0, 0x0001, 0x8802 } -> - 0000: 10 */ + /* READ { 0x0001, 0x8803 } -> 0000: 00 */ + /* READ { 0x0001, 0x8802 } -> 0000: 10 */ {0x0010, 0x8802}, {0x0039, 0x8801}, {0x0013, 0x8805}, {0x0000, 0x8800}, - /* READ { 0, 0x0001, 0x8803 } -> - 0000: 00 */ + /* READ { 0x0001, 0x8803 } -> 0000: 00 */ - /* READ { 0, 0x0001, 0x8803 } -> - 0000: 00 */ - /* READ { 0, 0x0001, 0x8802 } -> - 0000: 10 */ + /* READ { 0x0001, 0x8803 } -> 0000: 00 */ + /* READ { 0x0001, 0x8802 } -> 0000: 10 */ {0x0010, 0x8802}, {0x003b, 0x8801}, {0x000c, 0x8805}, {0x0000, 0x8800}, - /* READ { 0, 0x0001, 0x8803 } -> - 0000: 00 */ + /* READ { 0x0001, 0x8803 } -> 0000: 00 */ - /* READ { 0, 0x0001, 0x8803 } -> - 0000: 00 */ - /* READ { 0, 0x0001, 0x8802 } -> - 0000: 10 */ + /* READ { 0x0001, 0x8803 } -> 0000: 00 */ + /* READ { 0x0001, 0x8802 } -> 0000: 10 */ {0x0010, 0x8802}, {0x0035, 0x8801}, {0x0028, 0x8805}, {0x0000, 0x8800}, - /* READ { 0, 0x0001, 0x8803 } -> - 0000: 00 */ + /* READ { 0x0001, 0x8803 } -> 0000: 00 */ - /* READ { 0, 0x0001, 0x8803 } -> - 0000: 00 */ - /* READ { 0, 0x0001, 0x8802 } -> - 0000: 10 */ + /* READ { 0x0001, 0x8803 } -> 0000: 00 */ + /* READ { 0x0001, 0x8802 } -> 0000: 10 */ {0x0010, 0x8802}, {0x0009, 0x8801}, {0x0042, 0x8805}, {0x0001, 0x8800}, - /* READ { 0, 0x0001, 0x8803 } -> - 0000: 00 */ + /* READ { 0x0001, 0x8803 } -> 0000: 00 */ {0x0050, 0x8703}, {0x0002, 0x8704}, /* External input CKIx1 */ {0x0001, 0x870c}, /* Select CKOx2 output */ {0x009a, 0x8600}, /* Line memory Read Counter (L) */ - {0x0001, 0x8606}, /* 1 Line memory Read Counter (H) Result: (d)410 */ + {0x0001, 0x8606}, /* 1 Line memory Read Counter (H) Result: (d)410 */ {0x0023, 0x8601}, {0x0010, 0x8602}, {0x000a, 0x8603}, - {0x009A, 0x8600}, + {0x009a, 0x8600}, {0x0001, 0x865b}, /* 1 Horizontal Offset for Valid Pixel(L) */ {0x0003, 0x865c}, /* Vertical offset for valid lines (L) */ {0x0058, 0x865d}, /* Horizontal valid pixels window (L) */ @@ -1356,7 +1241,7 @@ static const u16 spca508_vista_init_data[][2] = { {0x0005, 0x860a}, /* ... */ {0x0025, 0x860b}, {0x00e1, 0x860c}, - {0x00fa, 0x860D}, + {0x00fa, 0x860d}, {0x00f4, 0x860e}, {0x00e8, 0x860f}, {0x0025, 0x8610}, /* A33 Coef. */ @@ -1371,11 +1256,12 @@ static const u16 spca508_vista_init_data[][2] = { {0x0040, 0x8654}, /* Gb gain for white balance (L) */ {0x0001, 0x863f}, /* Enable fixed gamma correction */ - {0x00a1, 0x8656}, /* Size - Window1: 256x256, Window2: 128x128 */ - /* UV division: UV no change, Enable New edge enhancement */ + {0x00a1, 0x8656}, /* Size - Window1: 256x256, Window2: 128x128, + * UV division: UV no change, + * Enable New edge enhancement */ {0x0018, 0x8657}, /* Edge gain high threshold */ {0x0020, 0x8658}, /* Edge gain low threshold */ - {0x000A, 0x8659}, /* Edge bandwidth high threshold */ + {0x000a, 0x8659}, /* Edge bandwidth high threshold */ {0x0005, 0x865a}, /* Edge bandwidth low threshold */ {0x0064, 0x8607}, /* UV filter enable */ @@ -1411,29 +1297,20 @@ static const u16 spca508_vista_init_data[][2] = { {0x0000, 0x86b4}, {0x001e, 0x8660}, - /* READ { 0, 0x0000, 0x8608 } -> - 0000: 13 */ - /* READ { 0, 0x0000, 0x8609 } -> - 0000: 28 */ - /* READ { 0, 0x0000, 0x8610 } -> - 0000: 05 */ - /* READ { 0, 0x0000, 0x8611 } -> - 0000: 25 */ - /* READ { 0, 0x0000, 0x8612 } -> - 0000: e1 */ - /* READ { 0, 0x0000, 0x8613 } -> - 0000: fa */ - /* READ { 0, 0x0000, 0x8614 } -> - 0000: f4 */ - /* READ { 0, 0x0000, 0x8615 } -> - 0000: e8 */ - /* READ { 0, 0x0000, 0x8616 } -> - 0000: 25 */ + /* READ { 0x0000, 0x8608 } -> 0000: 13 */ + /* READ { 0x0000, 0x8609 } -> 0000: 28 */ + /* READ { 0x0000, 0x8610 } -> 0000: 05 */ + /* READ { 0x0000, 0x8611 } -> 0000: 25 */ + /* READ { 0x0000, 0x8612 } -> 0000: e1 */ + /* READ { 0x0000, 0x8613 } -> 0000: fa */ + /* READ { 0x0000, 0x8614 } -> 0000: f4 */ + /* READ { 0x0000, 0x8615 } -> 0000: e8 */ + /* READ { 0x0000, 0x8616 } -> 0000: 25 */ {} }; static int reg_write(struct usb_device *dev, - __u16 index, __u16 value) + u16 index, u16 value) { int ret; @@ -1452,7 +1329,7 @@ static int reg_write(struct usb_device *dev, /* read 1 byte */ /* returns: negative is error, pos or zero is data */ static int reg_read(struct gspca_dev *gspca_dev, - __u16 index) /* wIndex */ + u16 index) /* wIndex */ { int ret; @@ -1548,7 +1425,6 @@ static int sd_config(struct gspca_dev *gspca_dev, /* this function is called at probe and resume time */ static int sd_init(struct gspca_dev *gspca_dev) { -/* write_vector(gspca_dev, spca508_open_data); */ return 0; } @@ -1556,7 +1432,7 @@ static int sd_start(struct gspca_dev *gspca_dev) { int mode; - mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv; + mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv; reg_write(gspca_dev->dev, 0x8500, mode); switch (mode) { case 0: @@ -1581,7 +1457,7 @@ static void sd_stopN(struct gspca_dev *gspca_dev) static void sd_pkt_scan(struct gspca_dev *gspca_dev, struct gspca_frame *frame, /* target */ - __u8 *data, /* isoc packet */ + u8 *data, /* isoc packet */ int len) /* iso packet length */ { switch (data[0]) { @@ -1594,7 +1470,6 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, data, len); break; case 0xff: /* drop */ -/* gspca_dev->last_packet_type = DISCARD_PACKET; */ break; default: data += 1; @@ -1608,7 +1483,7 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, static void setbrightness(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; - __u8 brightness = sd->brightness; + u8 brightness = sd->brightness; /* MX seem contrast */ reg_write(gspca_dev->dev, 0x8651, brightness); -- cgit v1.2.3 From df0e501722668b611a6bfc7c4edb54337a5b8d77 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Wed, 13 May 2009 19:25:29 +0200 Subject: gspca - spca508: Optimize code. From: Jean-Francois Moine Priority: normal Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/spca508.c | 46 +++++++++++-------------------- 1 file changed, 16 insertions(+), 30 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/spca508.c b/linux/drivers/media/video/gspca/spca508.c index d24d9d4aa..7fd8079c2 100644 --- a/linux/drivers/media/video/gspca/spca508.c +++ b/linux/drivers/media/video/gspca/spca508.c @@ -1351,16 +1351,16 @@ static int reg_read(struct gspca_dev *gspca_dev, } static int write_vector(struct gspca_dev *gspca_dev, - const u16 data[][2]) + const u16 (*data)[2]) { struct usb_device *dev = gspca_dev->dev; - int ret, i = 0; + int ret; - while (data[i][1] != 0) { - ret = reg_write(dev, data[i][1], data[i][0]); + while ((*data)[1] != 0) { + ret = reg_write(dev, (*data)[1], (*data)[0]); if (ret < 0) return ret; - i++; + data++; } return 0; } @@ -1372,6 +1372,15 @@ static int sd_config(struct gspca_dev *gspca_dev, struct sd *sd = (struct sd *) gspca_dev; struct cam *cam; int data1, data2; + const u16 (*init_data)[2]; + static const u16 (*(init_data_tb[]))[2] = { + spca508_vista_init_data, /* CreativeVista 0 */ + spca508_sightcam_init_data, /* HamaUSBSightcam 1 */ + spca508_sightcam2_init_data, /* HamaUSBSightcam2 2 */ + spca508cs110_init_data, /* IntelEasyPCCamera 3 */ + spca508cs110_init_data, /* MicroInnovationIC200 4 */ + spca508_init_data, /* ViewQuestVQ110 5 */ + }; /* Read from global register the USB product and vendor IDs, just to * prove that we can communicate with the device. This works, which @@ -1395,31 +1404,8 @@ static int sd_config(struct gspca_dev *gspca_dev, sd->subtype = id->driver_info; sd->brightness = BRIGHTNESS_DEF; - switch (sd->subtype) { - case ViewQuestVQ110: - if (write_vector(gspca_dev, spca508_init_data)) - return -1; - break; - default: -/* case MicroInnovationIC200: */ -/* case IntelEasyPCCamera: */ - if (write_vector(gspca_dev, spca508cs110_init_data)) - return -1; - break; - case HamaUSBSightcam: - if (write_vector(gspca_dev, spca508_sightcam_init_data)) - return -1; - break; - case HamaUSBSightcam2: - if (write_vector(gspca_dev, spca508_sightcam2_init_data)) - return -1; - break; - case CreativeVista: - if (write_vector(gspca_dev, spca508_vista_init_data)) - return -1; - break; - } - return 0; /* success */ + init_data = init_data_tb[sd->subtype]; + return write_vector(gspca_dev, init_data); } /* this function is called at probe and resume time */ -- 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 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 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 02f289e848b5b8a9826eb20dd8ea3a100737de16 Mon Sep 17 00:00:00 2001 From: Steven Toth Date: Fri, 15 May 2009 20:01:57 -0400 Subject: TDA10048: Ensure the I/F changes during DVB-T 6/7/8 bandwidth changes. From: Steven Toth TDA10048: Ensure the I/F changes during DVB-T 6/7/8 bandwidth changes. Priority: normal Signed-off-by: Steven Toth --- linux/drivers/media/dvb/frontends/tda10048.c | 184 ++++++++++++++++++--------- linux/drivers/media/dvb/frontends/tda10048.h | 6 +- 2 files changed, 127 insertions(+), 63 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/frontends/tda10048.c b/linux/drivers/media/dvb/frontends/tda10048.c index a223e617f..9bc1ba786 100644 --- a/linux/drivers/media/dvb/frontends/tda10048.c +++ b/linux/drivers/media/dvb/frontends/tda10048.c @@ -1,7 +1,7 @@ /* NXP TDA10048HN DVB OFDM demodulator driver - Copyright (C) 2008 Steven Toth + Copyright (C) 2009 Steven Toth 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 @@ -139,8 +139,8 @@ struct tda10048_state { struct i2c_adapter *i2c; - /* configuration settings */ - const struct tda10048_config *config; + /* We'll cache and update the attach config settings */ + struct tda10048_config config; struct dvb_frontend frontend; int fwloaded; @@ -202,12 +202,24 @@ static struct init_tab { { TDA10048_CONF_C4_2, 0x04 }, }; +static struct pll_tab { + u32 clk_freq_khz; + u32 if_freq_khz; + u8 m, n, p; +} pll_tab[] = { + { TDA10048_CLK_4000, TDA10048_IF_36130, 10, 0, 0 }, + { TDA10048_CLK_16000, TDA10048_IF_4300, 10, 3, 0 }, + { TDA10048_CLK_16000, TDA10048_IF_4000, 10, 3, 0 }, + { TDA10048_CLK_16000, TDA10048_IF_36130, 10, 3, 0 }, +}; + static int tda10048_writereg(struct tda10048_state *state, u8 reg, u8 data) { + struct tda10048_config *config = &state->config; int ret; u8 buf[] = { reg, data }; struct i2c_msg msg = { - .addr = state->config->demod_address, + .addr = config->demod_address, .flags = 0, .buf = buf, .len = 2 }; dprintk(2, "%s(reg = 0x%02x, data = 0x%02x)\n", __func__, reg, data); @@ -222,13 +234,14 @@ static int tda10048_writereg(struct tda10048_state *state, u8 reg, u8 data) static u8 tda10048_readreg(struct tda10048_state *state, u8 reg) { + struct tda10048_config *config = &state->config; int ret; u8 b0[] = { reg }; u8 b1[] = { 0 }; struct i2c_msg msg[] = { - { .addr = state->config->demod_address, + { .addr = config->demod_address, .flags = 0, .buf = b0, .len = 1 }, - { .addr = state->config->demod_address, + { .addr = config->demod_address, .flags = I2C_M_RD, .buf = b1, .len = 1 } }; dprintk(2, "%s(reg = 0x%02x)\n", __func__, reg); @@ -245,6 +258,7 @@ static u8 tda10048_readreg(struct tda10048_state *state, u8 reg) static int tda10048_writeregbulk(struct tda10048_state *state, u8 reg, const u8 *data, u16 len) { + struct tda10048_config *config = &state->config; int ret = -EREMOTEIO; struct i2c_msg msg; u8 *buf; @@ -260,7 +274,7 @@ static int tda10048_writeregbulk(struct tda10048_state *state, u8 reg, *buf = reg; memcpy(buf + 1, data, len); - msg.addr = state->config->demod_address; + msg.addr = config->demod_address; msg.flags = 0; msg.buf = buf; msg.len = len + 1; @@ -411,47 +425,47 @@ static int tda10048_set_bandwidth(struct dvb_frontend *fe, return 0; } -static int tda10048_set_pll(struct dvb_frontend *fe) +static int tda10048_set_if(struct dvb_frontend *fe, enum fe_bandwidth bw) { struct tda10048_state *state = fe->demodulator_priv; - int ret = 0; + struct tda10048_config *config = &state->config; + int i; + u32 if_freq_khz; - dprintk(1, "%s()\n", __func__); + dprintk(1, "%s(bw = %d)\n", __func__, bw); - if ((state->config->clk_freq_khz == TDA10048_CLK_4000) && - (state->config->if_freq_khz == TDA10048_IF_36130)) { - state->freq_if_hz = TDA10048_IF_36130 * 1000; - state->xtal_hz = TDA10048_CLK_4000 * 1000; - state->pll_mfactor = 10; - state->pll_nfactor = 0; - state->pll_pfactor = 0; - } else - if ((state->config->clk_freq_khz == TDA10048_CLK_16000) && - (state->config->if_freq_khz == TDA10048_IF_4300)) { - state->freq_if_hz = TDA10048_IF_4300 * 1000; - state->xtal_hz = TDA10048_CLK_16000 * 1000; - state->pll_mfactor = 10; - state->pll_nfactor = 3; - state->pll_pfactor = 0; - } else - if ((state->config->clk_freq_khz == TDA10048_CLK_16000) && - (state->config->if_freq_khz == TDA10048_IF_4000)) { - state->freq_if_hz = TDA10048_IF_4000 * 1000; - state->xtal_hz = TDA10048_CLK_16000 * 1000; - state->pll_mfactor = 10; - state->pll_nfactor = 3; - state->pll_pfactor = 0; - } else - if ((state->config->clk_freq_khz == TDA10048_CLK_16000) && - (state->config->if_freq_khz == TDA10048_IF_36130)) { - state->freq_if_hz = TDA10048_IF_36130 * 1000; - state->xtal_hz = TDA10048_CLK_16000 * 1000; - state->pll_mfactor = 10; - state->pll_nfactor = 3; - state->pll_pfactor = 0; - } else { - printk(KERN_ERR "%s() Incorrect attach settings\n", __func__); - ret = -EINVAL; + /* based on target bandwidth and clk we calculate pll factors */ + switch (bw) { + case BANDWIDTH_6_MHZ: + if_freq_khz = config->dtv6_if_freq_khz; + break; + case BANDWIDTH_7_MHZ: + if_freq_khz = config->dtv7_if_freq_khz; + break; + case BANDWIDTH_8_MHZ: + if_freq_khz = config->dtv8_if_freq_khz; + break; + default: + printk(KERN_ERR "%s() no default\n", __func__); + return -EINVAL; + } + + for (i = 0; i < ARRAY_SIZE(pll_tab); i++) { + if ((pll_tab[i].clk_freq_khz == config->clk_freq_khz) && + (pll_tab[i].if_freq_khz == if_freq_khz)) { + + state->freq_if_hz = pll_tab[i].if_freq_khz * 1000; + state->xtal_hz = pll_tab[i].clk_freq_khz * 1000; + state->pll_mfactor = pll_tab[i].m; + state->pll_nfactor = pll_tab[i].n; + state->pll_pfactor = pll_tab[i].p; + break; + } + } + if (i == ARRAY_SIZE(pll_tab)) { + printk(KERN_ERR "%s() Incorrect attach settings\n", + __func__); + return -EINVAL; } dprintk(1, "- freq_if_hz = %d\n", state->freq_if_hz); @@ -466,22 +480,21 @@ static int tda10048_set_pll(struct dvb_frontend *fe) state->sample_freq /= (state->pll_pfactor + 4); dprintk(1, "- sample_freq = %d\n", state->sample_freq); - tda10048_set_phy2(fe, state->sample_freq, - state->config->if_freq_khz * 1000); - tda10048_set_wref(fe, state->sample_freq, state->bandwidth); - tda10048_set_invwref(fe, state->sample_freq, state->bandwidth); + /* Update the I/F */ + tda10048_set_phy2(fe, state->sample_freq, state->freq_if_hz); - return ret; + return 0; } static int tda10048_firmware_upload(struct dvb_frontend *fe) { struct tda10048_state *state = fe->demodulator_priv; + struct tda10048_config *config = &state->config; const struct firmware *fw; int ret; int pos = 0; int cnt; - u8 wlen = state->config->fwbulkwritelen; + u8 wlen = config->fwbulkwritelen; if ((wlen != TDA10048_BULKWRITE_200) && (wlen != TDA10048_BULKWRITE_50)) wlen = TDA10048_BULKWRITE_200; @@ -687,9 +700,10 @@ static int tda10048_get_tps(struct tda10048_state *state, static int tda10048_i2c_gate_ctrl(struct dvb_frontend *fe, int enable) { struct tda10048_state *state = fe->demodulator_priv; + struct tda10048_config *config = &state->config; dprintk(1, "%s(%d)\n", __func__, enable); - if (state->config->disable_gate_access) + if (config->disable_gate_access) return 0; if (enable) @@ -729,8 +743,11 @@ static int tda10048_set_frontend(struct dvb_frontend *fe, dprintk(1, "%s(frequency=%d)\n", __func__, p->frequency); - if (p->u.ofdm.bandwidth != state->bandwidth) + /* Update the I/F pll's if the bandwidth changes */ + if (p->u.ofdm.bandwidth != state->bandwidth) { + tda10048_set_if(fe, p->u.ofdm.bandwidth); tda10048_set_bandwidth(fe, p->u.ofdm.bandwidth); + } if (fe->ops.tuner_ops.set_params) { @@ -753,6 +770,7 @@ static int tda10048_set_frontend(struct dvb_frontend *fe, static int tda10048_init(struct dvb_frontend *fe) { struct tda10048_state *state = fe->demodulator_priv; + struct tda10048_config *config = &state->config; int ret = 0, i; dprintk(1, "%s()\n", __func__); @@ -765,15 +783,13 @@ static int tda10048_init(struct dvb_frontend *fe) ret = tda10048_firmware_upload(fe); /* Set either serial or parallel */ - tda10048_output_mode(fe, state->config->output_mode); + tda10048_output_mode(fe, config->output_mode); /* Set inversion */ - tda10048_set_inversion(fe, state->config->inversion); + tda10048_set_inversion(fe, config->inversion); - /* Establish default PLL values */ - tda10048_set_pll(fe); - - /* Establish default bandwidth */ + /* Establish default RF values */ + tda10048_set_if(fe, BANDWIDTH_8_MHZ); tda10048_set_bandwidth(fe, BANDWIDTH_8_MHZ); /* Ensure we leave the gate closed */ @@ -1032,6 +1048,45 @@ static void tda10048_release(struct dvb_frontend *fe) kfree(state); } +static void tda10048_establish_defaults(struct dvb_frontend *fe) +{ + struct tda10048_state *state = fe->demodulator_priv; + struct tda10048_config *config = &state->config; + + /* Validate/default the config */ + if (config->dtv6_if_freq_khz == 0) { + config->dtv6_if_freq_khz = TDA10048_IF_4300; + printk(KERN_WARNING "%s() tda10048_config.dtv6_if_freq_khz " + "is not set (defaulting to %d)\n", + __func__, + config->dtv6_if_freq_khz); + } + + if (config->dtv7_if_freq_khz == 0) { + config->dtv7_if_freq_khz = TDA10048_IF_4300; + printk(KERN_WARNING "%s() tda10048_config.dtv7_if_freq_khz " + "is not set (defaulting to %d)\n", + __func__, + config->dtv7_if_freq_khz); + } + + if (config->dtv8_if_freq_khz == 0) { + config->dtv8_if_freq_khz = TDA10048_IF_4300; + printk(KERN_WARNING "%s() tda10048_config.dtv8_if_freq_khz " + "is not set (defaulting to %d)\n", + __func__, + config->dtv8_if_freq_khz); + } + + if (config->clk_freq_khz == 0) { + config->clk_freq_khz = TDA10048_CLK_16000; + printk(KERN_WARNING "%s() tda10048_config.clk_freq_khz " + "is not set (defaulting to %d)\n", + __func__, + config->clk_freq_khz); + } +} + static struct dvb_frontend_ops tda10048_ops; struct dvb_frontend *tda10048_attach(const struct tda10048_config *config, @@ -1046,8 +1101,8 @@ struct dvb_frontend *tda10048_attach(const struct tda10048_config *config, if (state == NULL) goto error; - /* setup the state */ - state->config = config; + /* setup the state and clone the config */ + memcpy(&state->config, config, sizeof(*config)); state->i2c = i2c; state->fwloaded = 0; state->bandwidth = BANDWIDTH_8_MHZ; @@ -1061,8 +1116,15 @@ struct dvb_frontend *tda10048_attach(const struct tda10048_config *config, sizeof(struct dvb_frontend_ops)); state->frontend.demodulator_priv = state; + /* Establish any defaults the the user didn't pass */ + tda10048_establish_defaults(&state->frontend); + /* Set the xtal and freq defaults */ - if (tda10048_set_pll(&state->frontend) != 0) + if (tda10048_set_if(&state->frontend, BANDWIDTH_8_MHZ) != 0) + goto error; + + /* Default bandwidth */ + if (tda10048_set_bandwidth(&state->frontend, BANDWIDTH_8_MHZ) != 0) goto error; /* Leave the gate closed */ diff --git a/linux/drivers/media/dvb/frontends/tda10048.h b/linux/drivers/media/dvb/frontends/tda10048.h index ee07b50e9..8828ceaf7 100644 --- a/linux/drivers/media/dvb/frontends/tda10048.h +++ b/linux/drivers/media/dvb/frontends/tda10048.h @@ -1,7 +1,7 @@ /* NXP TDA10048HN DVB OFDM demodulator driver - Copyright (C) 2008 Steven Toth + Copyright (C) 2009 Steven Toth 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 @@ -52,7 +52,9 @@ struct tda10048_config { #define TDA10048_IF_4500 4500 #define TDA10048_IF_4750 4750 #define TDA10048_IF_36130 36130 - u16 if_freq_khz; + u16 dtv6_if_freq_khz; + u16 dtv7_if_freq_khz; + u16 dtv8_if_freq_khz; #define TDA10048_CLK_4000 4000 #define TDA10048_CLK_16000 16000 -- cgit v1.2.3 From 9623e5fde7a41395739f4e13f7b218d097d5d93a Mon Sep 17 00:00:00 2001 From: Steven Toth Date: Fri, 15 May 2009 20:04:18 -0400 Subject: cx23885: Ensure we specify I/F's for all bandwidths From: Steven Toth cx23885: Ensure we specify I/F's for all bandwidths Priority: normal Signed-off-by: Steven Toth --- linux/drivers/media/video/cx23885/cx23885-dvb.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/cx23885/cx23885-dvb.c b/linux/drivers/media/video/cx23885/cx23885-dvb.c index ba120b9cf..c0095e818 100644 --- a/linux/drivers/media/video/cx23885/cx23885-dvb.c +++ b/linux/drivers/media/video/cx23885/cx23885-dvb.c @@ -125,7 +125,9 @@ static struct tda10048_config hauppauge_hvr1200_config = { .output_mode = TDA10048_SERIAL_OUTPUT, .fwbulkwritelen = TDA10048_BULKWRITE_200, .inversion = TDA10048_INVERSION_ON, - .if_freq_khz = TDA10048_IF_4300, + .dtv6_if_freq_khz = TDA10048_IF_3300, + .dtv7_if_freq_khz = TDA10048_IF_3800, + .dtv8_if_freq_khz = TDA10048_IF_4300, .clk_freq_khz = TDA10048_CLK_16000, }; -- cgit v1.2.3 From 9b5c764e4dc2cb4ec07a83f17113b7228dba03f6 Mon Sep 17 00:00:00 2001 From: Steven Toth Date: Fri, 15 May 2009 20:04:56 -0400 Subject: pvrusb2: Ensure we specify I/F's for all bandwidths From: Steven Toth pvrusb2: Ensure we specify I/F's for all bandwidths Priority: normal Signed-off-by: Steven Toth --- linux/drivers/media/video/pvrusb2/pvrusb2-devattr.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-devattr.c b/linux/drivers/media/video/pvrusb2/pvrusb2-devattr.c index 341af4355..336a20ede 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-devattr.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-devattr.c @@ -285,7 +285,9 @@ static struct tda10048_config hauppauge_tda10048_config = { .output_mode = TDA10048_PARALLEL_OUTPUT, .fwbulkwritelen = TDA10048_BULKWRITE_50, .inversion = TDA10048_INVERSION_ON, - .if_freq_khz = TDA10048_IF_4300, + .dtv6_if_freq_khz = TDA10048_IF_3300, + .dtv7_if_freq_khz = TDA10048_IF_3800, + .dtv8_if_freq_khz = TDA10048_IF_4300, .clk_freq_khz = TDA10048_CLK_16000, .disable_gate_access = 1, }; -- cgit v1.2.3 From abbf3f268166b272916a7af0e798e10e06394926 Mon Sep 17 00:00:00 2001 From: Steven Toth Date: Sat, 16 May 2009 13:43:51 -0400 Subject: TDA10048: Missing two I/F's / Pll combinations from the PLL table From: Steven Toth This was causing a lock failure in Australia. Priority: normal Signed-off-by: Steven Toth --- linux/drivers/media/dvb/frontends/tda10048.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/frontends/tda10048.c b/linux/drivers/media/dvb/frontends/tda10048.c index 9bc1ba786..04596baa9 100644 --- a/linux/drivers/media/dvb/frontends/tda10048.c +++ b/linux/drivers/media/dvb/frontends/tda10048.c @@ -208,8 +208,10 @@ static struct pll_tab { u8 m, n, p; } pll_tab[] = { { TDA10048_CLK_4000, TDA10048_IF_36130, 10, 0, 0 }, - { TDA10048_CLK_16000, TDA10048_IF_4300, 10, 3, 0 }, + { TDA10048_CLK_16000, TDA10048_IF_3300, 10, 3, 0 }, + { TDA10048_CLK_16000, TDA10048_IF_3500, 10, 3, 0 }, { TDA10048_CLK_16000, TDA10048_IF_4000, 10, 3, 0 }, + { TDA10048_CLK_16000, TDA10048_IF_4300, 10, 3, 0 }, { TDA10048_CLK_16000, TDA10048_IF_36130, 10, 3, 0 }, }; -- cgit v1.2.3 From ff417333f92b9ebf9523167136785d69bb73fab6 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Sat, 16 May 2009 10:00:23 -0400 Subject: cx23885: fix tda10048 IF frequencies for the Hauppauge WinTV-HVR1210 From: Michael Krufky Steve missed the HVR1210 config struct for the TDA10048 in his IF freq patch. Priority: normal Signed-off-by: Michael Krufky --- linux/drivers/media/video/cx23885/cx23885-dvb.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/cx23885/cx23885-dvb.c b/linux/drivers/media/video/cx23885/cx23885-dvb.c index c0095e818..4efc7dee1 100644 --- a/linux/drivers/media/video/cx23885/cx23885-dvb.c +++ b/linux/drivers/media/video/cx23885/cx23885-dvb.c @@ -136,7 +136,9 @@ static struct tda10048_config hauppauge_hvr1210_config = { .output_mode = TDA10048_SERIAL_OUTPUT, .fwbulkwritelen = TDA10048_BULKWRITE_200, .inversion = TDA10048_INVERSION_ON, - .if_freq_khz = TDA10048_IF_4000, + .dtv6_if_freq_khz = TDA10048_IF_3300, + .dtv7_if_freq_khz = TDA10048_IF_3500, + .dtv8_if_freq_khz = TDA10048_IF_4000, .clk_freq_khz = TDA10048_CLK_16000, }; -- cgit v1.2.3 From a4e560bb4630144033a7ab1bc0d30b0a50ed3236 Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Sat, 16 May 2009 20:06:57 -0400 Subject: cx18: Complete support for Sliced and Raw VBI for 625 line systems From: Andy Walls Finish changes for sliced and raw VBI for 625 line systems. Tested with VPS and WSS being emitted by a PVR-350 in field 1 lines 16 and 23. Priority: normal Signed-off-by: Andy Walls --- linux/drivers/media/video/cx18/cx18-av-core.c | 27 +++++++++++++++++++-------- linux/drivers/media/video/cx18/cx18-av-vbi.c | 2 +- linux/drivers/media/video/cx18/cx18-streams.c | 9 ++++----- 3 files changed, 24 insertions(+), 14 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/cx18/cx18-av-core.c b/linux/drivers/media/video/cx18/cx18-av-core.c index d98010e0d..33ec269a0 100644 --- a/linux/drivers/media/video/cx18/cx18-av-core.c +++ b/linux/drivers/media/video/cx18/cx18-av-core.c @@ -299,13 +299,13 @@ void cx18_av_std_setup(struct cx18 *cx) if (std & V4L2_STD_625_50) { /* * The following relationships of half line counts should hold: - * 625 = vblank656 + vactive + postvactive + * 625 = vblank656 + vactive * 10 = vblank656 - vblank = vsync pulses + equalization pulses * * vblank656: half lines after line 625/mid-313 of blanked video * vblank: half lines, after line 5/317, of blanked video - * vactive: half lines of active video - * postvactive: 5 half lines after the end of active video + * vactive: half lines of active video + + * 5 half lines after the end of active video * * As far as I can tell: * vblank656 starts counting from the falling edge of the first @@ -316,10 +316,21 @@ void cx18_av_std_setup(struct cx18 *cx) * For 625 line systems the driver will extract VBI information * from lines 6-23 and lines 318-335 (but the slicer can only * handle 17 lines, not the 18 in the vblank region). + * In addition, we need vblank656 and vblank to be one whole + * line longer, to cover line 24 and 336, so the SAV/EAV RP + * codes get generated such that the encoder can actually + * extract line 23 & 335 (WSS). We'll lose 1 line in each field + * at the top of the screen. + * + * It appears the 5 half lines that happen after active + * video must be included in vactive (579 instead of 574), + * otherwise the colors get badly displayed in various regions + * of the screen. I guess the chroma comb filter gets confused + * without them (at least when a PVR-350 is the PAL source). */ - vblank656 = 46; /* lines 1 - 23 & 313 - 335 */ - vblank = 36; /* lines 6 - 23 & 318 - 335 */ - vactive = 574; /* lines 24 - 310 & 336 - 622 */ + vblank656 = 48; /* lines 1 - 24 & 313 - 336 */ + vblank = 38; /* lines 6 - 24 & 318 - 336 */ + vactive = 579; /* lines 24 - 313 & 337 - 626 */ /* * For a 13.5 Mpps clock and 15,625 Hz line rate, a line is @@ -989,9 +1000,9 @@ static int cx18_av_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) * cx18_av_std_setup(), above standard values: * * 480 + 1 for 60 Hz systems - * 576 - 2 for 50 Hz systems + * 576 + 3 for 50 Hz systems */ - Vlines = pix->height + (is_50Hz ? -2 : 1); + Vlines = pix->height + (is_50Hz ? 3 : 1); /* * Invalid height and width scaling requests are: diff --git a/linux/drivers/media/video/cx18/cx18-av-vbi.c b/linux/drivers/media/video/cx18/cx18-av-vbi.c index 640121448..a51732bcc 100644 --- a/linux/drivers/media/video/cx18/cx18-av-vbi.c +++ b/linux/drivers/media/video/cx18/cx18-av-vbi.c @@ -256,7 +256,7 @@ int cx18_av_vbi_s_fmt(struct cx18 *cx, struct v4l2_format *fmt) cx18_av_write(cx, 0x43c, 0x16); /* Should match vblank set in cx18_av_std_setup() */ - cx18_av_write(cx, 0x474, is_pal ? 36 : 26); + cx18_av_write(cx, 0x474, is_pal ? 38 : 26); return 0; } diff --git a/linux/drivers/media/video/cx18/cx18-streams.c b/linux/drivers/media/video/cx18/cx18-streams.c index 081efc575..c134927b3 100644 --- a/linux/drivers/media/video/cx18/cx18-streams.c +++ b/linux/drivers/media/video/cx18/cx18-streams.c @@ -379,12 +379,11 @@ static void cx18_vbi_setup(struct cx18_stream *s) * For 625/50 systems, according to the VIP 2 & BT.656 std: * The EAV RP code's Field bit toggles on line 1, a few lines * after the Vertcal Blank bit has already toggled. - * Tell the encoder to capture 23-1+1=23 lines per field, - * since we want lines 6 through 23. - * - * FIXME - revisit for 625/50 systems + * (We've actually set the digitizer so that the Field bit + * toggles on line 2.) Tell the encoder to capture 23-2+1=22 + * lines per field, since we want lines 6 through 23. */ - lines = cx->is_60hz ? (21 - 4 + 1) * 2 : (23 - 1 + 1) * 2; + lines = cx->is_60hz ? (21 - 4 + 1) * 2 : (23 - 2 + 1) * 2; } data[0] = s->handle; -- cgit v1.2.3 From fc06889a7cb90e50621ecaaf22f2f575b5ae6a44 Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Sat, 16 May 2009 21:43:43 -0400 Subject: cx18: Tweak color burst gate delay and initial color sub-carrier freq From: Andy Walls Fix the burst gate delays to use a crystal value of 28636360 as assumed by the rest of the driver. Also have the initial color sub-carrier freq paramter use the src decimation ratio per the documentation, instead of the actual crystal/pixel clock ratio. The tracking circuit will find the correct color subcarrier in any case, as long as we're close. Also fix up some debug print statements. Priority: normal Signed-off-by: Andy Walls --- linux/drivers/media/video/cx18/cx18-av-core.c | 69 +++++++++++++++++++-------- 1 file changed, 48 insertions(+), 21 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/cx18/cx18-av-core.c b/linux/drivers/media/video/cx18/cx18-av-core.c index 33ec269a0..0b3d840cc 100644 --- a/linux/drivers/media/video/cx18/cx18-av-core.c +++ b/linux/drivers/media/video/cx18/cx18-av-core.c @@ -277,8 +277,15 @@ void cx18_av_std_setup(struct cx18 *cx) struct cx18_av_state *state = &cx->av_state; struct v4l2_subdev *sd = &state->sd; v4l2_std_id std = state->std; + + /* + * Video ADC crystal clock to pixel clock SRC decimation ratio + * 28.636360 MHz/13.5 Mpps * 256 = 0x21f.07b + */ + const int src_decimation = 0x21f; + int hblank, hactive, burst, vblank, vactive, sc; - int vblank656, src_decimation; + int vblank656; int luma_lpf, uv_lpf, comb; u32 pll_int, pll_frac, pll_post; @@ -342,21 +349,31 @@ void cx18_av_std_setup(struct cx18 *cx) hblank = 132; hactive = 720; + /* + * Burst gate delay (for 625 line systems) + * Hsync leading edge to color burst rise = 5.6 us + * Color burst width = 2.25 us + * Gate width = 4 pixel clocks + * (5.6 us + 2.25/2 us) * 13.5 Mpps + 4/2 clocks = 92.79 clocks + */ burst = 93; luma_lpf = 2; - src_decimation = 0x21f; if (std & V4L2_STD_PAL) { uv_lpf = 1; comb = 0x20; - sc = 688739; + /* sc = 4433618.75 * src_decimation/28636360 * 2^13 */ + sc = 688700; } else if (std == V4L2_STD_PAL_Nc) { uv_lpf = 1; comb = 0x20; - sc = 556453; + /* sc = 3582056.25 * src_decimation/28636360 * 2^13 */ + sc = 556422; } else { /* SECAM */ uv_lpf = 0; comb = 0; - sc = 672351; + /* (fr + fb)/2 = (4406260 + 4250000)/2 = 4328130 */ + /* sc = 4328130 * src_decimation/28636360 * 2^13 */ + sc = 672314; } } else { /* @@ -394,20 +411,30 @@ void cx18_av_std_setup(struct cx18 *cx) luma_lpf = 1; uv_lpf = 1; - src_decimation = 0x21f; + /* + * Burst gate delay (for 525 line systems) + * Hsync leading edge to color burst rise = 5.3 us + * Color burst width = 2.5 us + * Gate width = 4 pixel clocks + * (5.3 us + 2.5/2 us) * 13.5 Mpps + 4/2 clocks = 90.425 clocks + */ if (std == V4L2_STD_PAL_60) { - burst = 0x5b; + burst = 90; luma_lpf = 2; comb = 0x20; - sc = 688739; + /* sc = 4433618.75 * src_decimation/28636360 * 2^13 */ + sc = 688700; } else if (std == V4L2_STD_PAL_M) { - burst = 0x61; + /* The 97 needs to be verified against PAL-M timings */ + burst = 97; comb = 0x20; - sc = 555452; + /* sc = 3575611.49 * src_decimation/28636360 * 2^13 */ + sc = 555421; } else { - burst = 0x5b; + burst = 90; comb = 0x66; - sc = 556063; + /* sc = 3579545.45.. * src_decimation/28636360 * 2^13 */ + sc = 556032; } } @@ -419,23 +446,23 @@ void cx18_av_std_setup(struct cx18 *cx) pll_int, pll_frac, pll_post); if (pll_post) { - int fin, fsc, pll; + int fsc, pll; pll = (28636360L * ((((u64)pll_int) << 25) + pll_frac)) >> 25; pll /= pll_post; - CX18_DEBUG_INFO_DEV(sd, "PLL = %d.%06d MHz\n", + CX18_DEBUG_INFO_DEV(sd, "Video PLL = %d.%06d MHz\n", pll / 1000000, pll % 1000000); - CX18_DEBUG_INFO_DEV(sd, "PLL/8 = %d.%06d MHz\n", + CX18_DEBUG_INFO_DEV(sd, "Pixel rate = %d.%06d Mpixel/sec\n", pll / 8000000, (pll / 8) % 1000000); - fin = ((u64)src_decimation * pll) >> 12; - CX18_DEBUG_INFO_DEV(sd, "ADC Sampling freq = %d.%06d MHz\n", - fin / 1000000, fin % 1000000); + CX18_DEBUG_INFO_DEV(sd, "ADC XTAL/pixel clock decimation ratio " + "= %d.%03d\n", src_decimation / 256, + ((src_decimation % 256) * 1000) / 256); - fsc = (((u64)sc) * pll) >> 24L; + fsc = ((((u64)sc) * 28636360)/src_decimation) >> 13L; CX18_DEBUG_INFO_DEV(sd, - "Chroma sub-carrier freq = %d.%06d MHz\n", - fsc / 1000000, fsc % 1000000); + "Chroma sub-carrier initial freq = %d.%06d " + "MHz\n", fsc / 1000000, fsc % 1000000); CX18_DEBUG_INFO_DEV(sd, "hblank %i, hactive %i, vblank %i, " "vactive %i, vblank656 %i, src_dec %i, " -- 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 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 From 92ff57a2afea5458088efcdff7a40693797483bf Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 31 May 2009 16:47:28 -0300 Subject: Adds support for Leadtek WinFast DTV-1800H From: Miroslav Sustek Enables analog/digital tv, radio and remote control (gpio). Signed-off-by: Miroslav Sustek Tested-by: Marcin Wojcikowski Tested-by: Karel Juhanak Tested-by: Andrew Goff Tested-by: Jan Novak Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/cx88/cx88-cards.c | 75 +++++++++++++++++++++++++++++ linux/drivers/media/video/cx88/cx88-dvb.c | 1 + linux/drivers/media/video/cx88/cx88-input.c | 2 + linux/drivers/media/video/cx88/cx88.h | 1 + 4 files changed, 79 insertions(+) (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 546793c02..825b1f25d 100644 --- a/linux/drivers/media/video/cx88/cx88-cards.c +++ b/linux/drivers/media/video/cx88/cx88-cards.c @@ -2009,6 +2009,47 @@ static const struct cx88_board cx88_boards[] = { .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, }, + [CX88_BOARD_WINFAST_DTV1800H] = { + .name = "Leadtek WinFast DTV1800 Hybrid", + .tuner_type = TUNER_XC2028, + .radio_type = TUNER_XC2028, + .tuner_addr = 0x61, + .radio_addr = 0x61, + /* + * GPIO setting + * + * 2: mute (0=off,1=on) + * 12: tuner reset pin + * 13: audio source (0=tuner audio,1=line in) + * 14: FM (0=on,1=off ???) + */ + .input = {{ + .type = CX88_VMUX_TELEVISION, + .vmux = 0, + .gpio0 = 0x0400, /* pin 2 = 0 */ + .gpio1 = 0x6040, /* pin 13 = 0, pin 14 = 1 */ + .gpio2 = 0x0000, + }, { + .type = CX88_VMUX_COMPOSITE1, + .vmux = 1, + .gpio0 = 0x0400, /* pin 2 = 0 */ + .gpio1 = 0x6060, /* pin 13 = 1, pin 14 = 1 */ + .gpio2 = 0x0000, + }, { + .type = CX88_VMUX_SVIDEO, + .vmux = 2, + .gpio0 = 0x0400, /* pin 2 = 0 */ + .gpio1 = 0x6060, /* pin 13 = 1, pin 14 = 1 */ + .gpio2 = 0x0000, + } }, + .radio = { + .type = CX88_RADIO, + .gpio0 = 0x0400, /* pin 2 = 0 */ + .gpio1 = 0x6000, /* pin 13 = 0, pin 14 = 0 */ + .gpio2 = 0x0000, + }, + .mpeg = CX88_MPEG_DVB, + }, }; /* ------------------------------------------------------------------ */ @@ -2426,6 +2467,10 @@ static const struct cx88_subid cx88_subids[] = { .subvendor = 0x0070, .subdevice = 0x9290, .card = CX88_BOARD_HAUPPAUGE_IRONLY, + }, { + .subvendor = 0x107d, + .subdevice = 0x6654, + .card = CX88_BOARD_WINFAST_DTV1800H, }, }; @@ -2624,6 +2669,23 @@ static int cx88_xc3028_geniatech_tuner_callback(struct cx88_core *core, return -EINVAL; } +static int cx88_xc3028_winfast1800h_callback(struct cx88_core *core, + int command, int arg) +{ + switch (command) { + case XC2028_TUNER_RESET: + /* GPIO 12 (xc3028 tuner reset) */ + cx_set(MO_GP1_IO, 0x1010); + mdelay(50); + cx_clear(MO_GP1_IO, 0x10); + mdelay(50); + cx_set(MO_GP1_IO, 0x10); + mdelay(50); + return 0; + } + return -EINVAL; +} + /* ------------------------------------------------------------------- */ /* some Divco specific stuff */ static int cx88_pv_8000gt_callback(struct cx88_core *core, @@ -2696,6 +2758,8 @@ static int cx88_xc2028_tuner_callback(struct cx88_core *core, case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO: case CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO: return cx88_dvico_xc2028_callback(core, command, arg); + case CX88_BOARD_WINFAST_DTV1800H: + return cx88_xc3028_winfast1800h_callback(core, command, arg); } switch (command) { @@ -2882,6 +2946,16 @@ static void cx88_card_setup_pre_i2c(struct cx88_core *core) cx_set(MO_GP0_IO, 0x00000080); /* 702 out of reset */ udelay(1000); break; + + case CX88_BOARD_WINFAST_DTV1800H: + /* GPIO 12 (xc3028 tuner reset) */ + cx_set(MO_GP1_IO, 0x1010); + mdelay(50); + cx_clear(MO_GP1_IO, 0x10); + mdelay(50); + cx_set(MO_GP1_IO, 0x10); + mdelay(50); + break; } } @@ -2902,6 +2976,7 @@ void cx88_setup_xc3028(struct cx88_core *core, struct xc2028_ctrl *ctl) core->i2c_algo.udelay = 16; break; case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO: + case CX88_BOARD_WINFAST_DTV1800H: ctl->demod = XC3028_FE_ZARLINK456; break; case CX88_BOARD_KWORLD_ATSC_120: diff --git a/linux/drivers/media/video/cx88/cx88-dvb.c b/linux/drivers/media/video/cx88/cx88-dvb.c index f32cece95..36f35f0b5 100644 --- a/linux/drivers/media/video/cx88/cx88-dvb.c +++ b/linux/drivers/media/video/cx88/cx88-dvb.c @@ -1021,6 +1021,7 @@ static int dvb_register(struct cx8802_dev *dev) } break; case CX88_BOARD_PINNACLE_HYBRID_PCTV: + case CX88_BOARD_WINFAST_DTV1800H: fe0->dvb.frontend = dvb_attach(zl10353_attach, &cx88_pinnacle_hybrid_pctv, &core->i2c_adap); diff --git a/linux/drivers/media/video/cx88/cx88-input.c b/linux/drivers/media/video/cx88/cx88-input.c index dad809335..7c5e94916 100644 --- a/linux/drivers/media/video/cx88/cx88-input.c +++ b/linux/drivers/media/video/cx88/cx88-input.c @@ -92,6 +92,7 @@ static void cx88_ir_handle_key(struct cx88_IR *ir) gpio=(gpio & 0x7fd) + (auxgpio & 0xef); break; case CX88_BOARD_WINFAST_DTV1000: + case CX88_BOARD_WINFAST_DTV1800H: case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL: gpio = (gpio & 0x6ff) | ((cx_read(MO_GP1_IO) << 8) & 0x900); auxgpio = gpio; @@ -237,6 +238,7 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) ir->sampling = 1; break; case CX88_BOARD_WINFAST_DTV2000H: + case CX88_BOARD_WINFAST_DTV1800H: ir_codes = ir_codes_winfast; ir->gpio_addr = MO_GP0_IO; ir->mask_keycode = 0x8f8; diff --git a/linux/drivers/media/video/cx88/cx88.h b/linux/drivers/media/video/cx88/cx88.h index 0c00c34bc..59fc01a53 100644 --- a/linux/drivers/media/video/cx88/cx88.h +++ b/linux/drivers/media/video/cx88/cx88.h @@ -237,6 +237,7 @@ extern struct sram_channel cx88_sram_channels[]; #define CX88_BOARD_PROF_6200 78 #define CX88_BOARD_TERRATEC_CINERGY_HT_PCI_MKII 79 #define CX88_BOARD_HAUPPAUGE_IRONLY 80 +#define CX88_BOARD_WINFAST_DTV1800H 81 enum cx88_itype { CX88_VMUX_COMPOSITE1 = 1, -- cgit v1.2.3 From 51a300d3840310ac710404dddda8eb9afe79a840 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 18 May 2009 08:25:49 +0000 Subject: cx23885: support for card Mygica X8506 DMB-TH From: David Wong This patch add cx23885 support for card "Mygica X8506 DMB-TH". It should work on "Magic-Pro ProHDTV Extreme" as well, as they are same hardware with different branding. Sign-off-by: David T.L. Wong Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/cx23885/cx23885-cards.c | 22 ++++++++++++++ linux/drivers/media/video/cx23885/cx23885-dvb.c | 35 ++++++++++++++++++++++- linux/drivers/media/video/cx23885/cx23885.h | 1 + 3 files changed, 57 insertions(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/cx23885/cx23885-cards.c b/linux/drivers/media/video/cx23885/cx23885-cards.c index 93176fe4b..35b2abd6a 100644 --- a/linux/drivers/media/video/cx23885/cx23885-cards.c +++ b/linux/drivers/media/video/cx23885/cx23885-cards.c @@ -198,6 +198,10 @@ struct cx23885_board cx23885_boards[] = { .name = "Hauppauge WinTV-HVR1210", .portc = CX23885_MPEG_DVB, }, + [CX23885_BOARD_MYGICA_X8506] = { + .name = "Mygica X8506 DMB-TH", + .portb = CX23885_MPEG_DVB, + }, }; const unsigned int cx23885_bcount = ARRAY_SIZE(cx23885_boards); @@ -317,6 +321,10 @@ struct cx23885_subid cx23885_subids[] = { .subvendor = 0x0070, .subdevice = 0x2295, .card = CX23885_BOARD_HAUPPAUGE_HVR1210, + }, { + .subvendor = 0x14f1, + .subdevice = 0x8651, + .card = CX23885_BOARD_MYGICA_X8506, }, }; const unsigned int cx23885_idcount = ARRAY_SIZE(cx23885_subids); @@ -707,6 +715,15 @@ void cx23885_gpio_setup(struct cx23885_dev *dev) mdelay(20); cx23885_gpio_set(dev, GPIO_9); break; + case CX23885_BOARD_MYGICA_X8506: + /* GPIO-1 reset XC5000 */ + /* GPIO-2 reset LGS8GL5 */ + cx_set(GP0_IO, 0x00060000); + cx_clear(GP0_IO, 0x00000006); + mdelay(100); + cx_set(GP0_IO, 0x00060006); + mdelay(100); + break; } } @@ -810,6 +827,11 @@ void cx23885_card_setup(struct cx23885_dev *dev) ts2->ts_clk_en_val = 0x1; /* Enable TS_CLK */ ts2->src_sel_val = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO; break; + case CX23885_BOARD_MYGICA_X8506: + ts1->gen_ctrl_val = 0x5; /* Parallel */ + ts1->ts_clk_en_val = 0x1; /* Enable TS_CLK */ + ts1->src_sel_val = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO; + break; case CX23885_BOARD_HAUPPAUGE_HVR1250: case CX23885_BOARD_HAUPPAUGE_HVR1500: case CX23885_BOARD_HAUPPAUGE_HVR1500Q: diff --git a/linux/drivers/media/video/cx23885/cx23885-dvb.c b/linux/drivers/media/video/cx23885/cx23885-dvb.c index 4efc7dee1..9c3259b22 100644 --- a/linux/drivers/media/video/cx23885/cx23885-dvb.c +++ b/linux/drivers/media/video/cx23885/cx23885-dvb.c @@ -50,6 +50,7 @@ #include "lnbh24.h" #include "cx24116.h" #include "cimax2.h" +#include "lgs8gxx.h" #include "netup-eeprom.h" #include "netup-init.h" #include "lgdt3305.h" @@ -421,10 +422,29 @@ static struct cx24116_config dvbworld_cx24116_config = { .demod_address = 0x05, }; +static struct lgs8gxx_config mygica_x8506_lgs8gl5_config = { + .prod = LGS8GXX_PROD_LGS8GL5, + .demod_address = 0x19, + .serial_ts = 0, + .ts_clk_pol = 1, + .ts_clk_gated = 1, + .if_clk_freq = 30400, /* 30.4 MHz */ + .if_freq = 5380, /* 5.38 MHz */ + .if_neg_center = 1, + .ext_adc = 0, + .adc_signed = 0, + .if_neg_edge = 0, +}; + +static struct xc5000_config mygica_x8506_xc5000_config = { + .i2c_address = 0x61, + .if_khz = 5380, +}; + static int dvb_register(struct cx23885_tsport *port) { struct cx23885_dev *dev = port->dev; - struct cx23885_i2c *i2c_bus = NULL; + struct cx23885_i2c *i2c_bus = NULL, *i2c_bus2 = NULL; struct videobuf_dvb_frontend *fe0; int ret; @@ -746,6 +766,19 @@ static int dvb_register(struct cx23885_tsport *port) break; } break; + case CX23885_BOARD_MYGICA_X8506: + i2c_bus = &dev->i2c_bus[0]; + i2c_bus2 = &dev->i2c_bus[1]; + fe0->dvb.frontend = dvb_attach(lgs8gxx_attach, + &mygica_x8506_lgs8gl5_config, + &i2c_bus->i2c_adap); + if (fe0->dvb.frontend != NULL) { + dvb_attach(xc5000_attach, + fe0->dvb.frontend, + &i2c_bus2->i2c_adap, + &mygica_x8506_xc5000_config); + } + break; default: printk(KERN_INFO "%s: The frontend of your DVB/ATSC card " " isn't supported yet\n", diff --git a/linux/drivers/media/video/cx23885/cx23885.h b/linux/drivers/media/video/cx23885/cx23885.h index 8dba2fdd6..2022ed7de 100644 --- a/linux/drivers/media/video/cx23885/cx23885.h +++ b/linux/drivers/media/video/cx23885/cx23885.h @@ -76,6 +76,7 @@ #define CX23885_BOARD_HAUPPAUGE_HVR1275 19 #define CX23885_BOARD_HAUPPAUGE_HVR1255 20 #define CX23885_BOARD_HAUPPAUGE_HVR1210 21 +#define CX23885_BOARD_MYGICA_X8506 22 #define GPIO_0 0x00000001 #define GPIO_1 0x00000002 -- cgit v1.2.3 From f48ec98ff6423bfb2816b716ced5ec8873af6da0 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 19 May 2009 01:00:34 +0000 Subject: one kconfig controls them all From: Randy Dunlap Add a kconfig symbol that allows someone to disable all multimedia config options at one time. Signed-off-by: Randy Dunlap Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/Kconfig | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/Kconfig b/linux/drivers/media/Kconfig index 223c36ede..ba69beeb0 100644 --- a/linux/drivers/media/Kconfig +++ b/linux/drivers/media/Kconfig @@ -2,8 +2,14 @@ # Multimedia device configuration # -menu "Multimedia devices" +menuconfig MEDIA_SUPPORT + tristate "Multimedia support" depends on HAS_IOMEM + help + If you want to use Video for Linux, DVB for Linux, or DAB adapters, + enable this option and other options below. + +if MEDIA_SUPPORT comment "Multimedia core support" @@ -136,4 +142,4 @@ config USB_DABUSB module will be called dabusb. endif # DAB -endmenu +endif # MEDIA_SUPPORT -- cgit v1.2.3 From 7a720bf4019f0daff79779605456a7460b4e2d33 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 31 May 2009 18:05:05 -0300 Subject: saa7134-video.c: Fix poll return condition From: Figo.zhang In v2, when buf == NULL, it will goto err instead of returning "PULLERR" without unlocking. [mchehab@redhat.com: diff patch against v1 and v2 of saa7134-video.c: poll method lose race condition for capture video patch] Signed-off-by: Figo.zhang Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/saa7134/saa7134-video.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (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 26f1727e6..20b66cb8d 100644 --- a/linux/drivers/media/video/saa7134/saa7134-video.c +++ b/linux/drivers/media/video/saa7134/saa7134-video.c @@ -1448,7 +1448,7 @@ video_poll(struct file *file, struct poll_table_struct *wait) } if (!buf) - rc = POLLERR; + goto err; poll_wait(file, &buf->done, wait); if (buf->state == VIDEOBUF_DONE || -- cgit v1.2.3 From a47bd9ff056af0e4adfc7755b121000827d8972f Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 19 May 2009 12:51:41 +0000 Subject: Siano: cards - add two additional (USB) devices From: Uri Shkolnik Add two additional USB targets, add these to the 'cards' modules and to the 'smsusb' module. Priority: normal Signed-off-by: Uri Shkolnik Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/siano/sms-cards.c | 10 ++++++++++ linux/drivers/media/dvb/siano/sms-cards.h | 2 ++ linux/drivers/media/dvb/siano/smsusb.c | 9 +++++++-- 3 files changed, 19 insertions(+), 2 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 fda483f07..1a1890680 100644 --- a/linux/drivers/media/dvb/siano/sms-cards.c +++ b/linux/drivers/media/dvb/siano/sms-cards.c @@ -85,6 +85,16 @@ static struct sms_board sms_boards[] = { .fw[DEVICE_MODE_DVBT_BDA] = "sms1xxx-hcw-55xxx-dvbt-02.fw", .lna_ctrl = -1, }, + [SMS1XXX_BOARD_SIANO_NICE] = { + /* 11 */ + .name = "Siano Nice Digital Receiver", + .type = SMS_NOVA_B0, + }, + [SMS1XXX_BOARD_SIANO_VENICE] = { + /* 12 */ + .name = "Siano Venice Digital Receiver", + .type = SMS_VEGA, + }, }; struct sms_board *sms_get_board(int id) diff --git a/linux/drivers/media/dvb/siano/sms-cards.h b/linux/drivers/media/dvb/siano/sms-cards.h index 447481ab5..e183f946a 100644 --- a/linux/drivers/media/dvb/siano/sms-cards.h +++ b/linux/drivers/media/dvb/siano/sms-cards.h @@ -35,6 +35,8 @@ #define SMS1XXX_BOARD_HAUPPAUGE_WINDHAM 8 #define SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD 9 #define SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD_R2 10 +#define SMS1XXX_BOARD_SIANO_NICE 11 +#define SMS1XXX_BOARD_SIANO_VENICE 12 struct sms_board_gpio_cfg { int lna_vhf_exist; diff --git a/linux/drivers/media/dvb/siano/smsusb.c b/linux/drivers/media/dvb/siano/smsusb.c index 3bbbdb197..a85538b06 100644 --- a/linux/drivers/media/dvb/siano/smsusb.c +++ b/linux/drivers/media/dvb/siano/smsusb.c @@ -531,8 +531,13 @@ struct usb_device_id smsusb_id_table[] = { .driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM }, { USB_DEVICE(0x2040, 0x5590), .driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM }, - { } /* Terminating entry */ -}; + { USB_DEVICE(0x187f, 0x0202), + .driver_info = SMS1XXX_BOARD_SIANO_NICE }, + { USB_DEVICE(0x187f, 0x0301), + .driver_info = SMS1XXX_BOARD_SIANO_VENICE }, + { } /* Terminating entry */ + }; + MODULE_DEVICE_TABLE(usb, smsusb_id_table); static struct usb_driver smsusb_driver = { -- cgit v1.2.3 From f19c04a5b4926e17938cbdd708d40446e806509d Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 19 May 2009 14:15:01 +0000 Subject: Siano: smssdio - revert to stand alone module From: Uri Shkolnik Make the SDIO interface driver a stand alone module. Priority: normal Signed-off-by: Uri Shkolnik Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/siano/smssdio.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/siano/smssdio.c b/linux/drivers/media/dvb/siano/smssdio.c index 4f8fa59a9..dfaa49a53 100644 --- a/linux/drivers/media/dvb/siano/smssdio.c +++ b/linux/drivers/media/dvb/siano/smssdio.c @@ -332,7 +332,7 @@ static struct sdio_driver smssdio_driver = { /* Module functions */ /*******************************************************************/ -int smssdio_register(void) +int smssdio_module_init(void) { int ret = 0; @@ -344,11 +344,14 @@ int smssdio_register(void) return ret; } -void smssdio_unregister(void) +void smssdio_module_exit(void) { sdio_unregister_driver(&smssdio_driver); } +module_init(smssdio_module_init); +module_exit(smssdio_module_exit); + MODULE_DESCRIPTION("Siano SMS1xxx SDIO driver"); MODULE_AUTHOR("Pierre Ossman"); MODULE_LICENSE("GPL"); -- cgit v1.2.3 From b4bb609923f3f62aa6fa3dd8efa9b384ee02d177 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 19 May 2009 14:49:19 +0000 Subject: Siano: Add new GPIO management interface From: Uri Shkolnik Add new GPIO management interface to replace old (buggy) one. Keeping old interface intact for now. Priority: normal Signed-off-by: Uri Shkolnik Acked-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/siano/sms-cards.c | 2 +- linux/drivers/media/dvb/siano/smscoreapi.c | 235 ++++++++++++++++++++++++++++- linux/drivers/media/dvb/siano/smscoreapi.h | 55 ++++++- 3 files changed, 288 insertions(+), 4 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 1a1890680..370cf513a 100644 --- a/linux/drivers/media/dvb/siano/sms-cards.c +++ b/linux/drivers/media/dvb/siano/sms-cards.c @@ -109,7 +109,7 @@ static int sms_set_gpio(struct smscore_device_t *coredev, int pin, int enable) { int lvl, ret; u32 gpio; - struct smscore_gpio_config gpioconfig = { + struct smscore_config_gpio gpioconfig = { .direction = SMS_GPIO_DIRECTION_OUTPUT, .pullupdown = SMS_GPIO_PULLUPDOWN_NONE, .inputcharacteristics = SMS_GPIO_INPUTCHARACTERISTICS_NORMAL, diff --git a/linux/drivers/media/dvb/siano/smscoreapi.c b/linux/drivers/media/dvb/siano/smscoreapi.c index 16917016c..6446e0f6c 100644 --- a/linux/drivers/media/dvb/siano/smscoreapi.c +++ b/linux/drivers/media/dvb/siano/smscoreapi.c @@ -1331,8 +1331,9 @@ static int smscore_map_common_buffer(struct smscore_device_t *coredev, } #endif +/* old GPIO managments implementation */ int smscore_configure_gpio(struct smscore_device_t *coredev, u32 pin, - struct smscore_gpio_config *pinconfig) + struct smscore_config_gpio *pinconfig) { struct { struct SmsMsgHdr_ST hdr; @@ -1401,6 +1402,238 @@ int smscore_set_gpio(struct smscore_device_t *coredev, u32 pin, int level) &msg, sizeof(msg)); } +/* new GPIO managment implementation */ +static int GetGpioPinParams(u32 PinNum, u32 *pTranslatedPinNum, + u32 *pGroupNum, u32 *pGroupCfg) { + + *pGroupCfg = 1; + + if (PinNum >= 0 && PinNum <= 1) { + *pTranslatedPinNum = 0; + *pGroupNum = 9; + *pGroupCfg = 2; + } else if (PinNum >= 2 && PinNum <= 6) { + *pTranslatedPinNum = 2; + *pGroupNum = 0; + *pGroupCfg = 2; + } else if (PinNum >= 7 && PinNum <= 11) { + *pTranslatedPinNum = 7; + *pGroupNum = 1; + } else if (PinNum >= 12 && PinNum <= 15) { + *pTranslatedPinNum = 12; + *pGroupNum = 2; + *pGroupCfg = 3; + } else if (PinNum == 16) { + *pTranslatedPinNum = 16; + *pGroupNum = 23; + } else if (PinNum >= 17 && PinNum <= 24) { + *pTranslatedPinNum = 17; + *pGroupNum = 3; + } else if (PinNum == 25) { + *pTranslatedPinNum = 25; + *pGroupNum = 6; + } else if (PinNum >= 26 && PinNum <= 28) { + *pTranslatedPinNum = 26; + *pGroupNum = 4; + } else if (PinNum == 29) { + *pTranslatedPinNum = 29; + *pGroupNum = 5; + *pGroupCfg = 2; + } else if (PinNum == 30) { + *pTranslatedPinNum = 30; + *pGroupNum = 8; + } else if (PinNum == 31) { + *pTranslatedPinNum = 31; + *pGroupNum = 17; + } else + return -1; + + *pGroupCfg <<= 24; + + return 0; +} + +int smscore_gpio_configure(struct smscore_device_t *coredev, u8 PinNum, + struct smscore_gpio_config *pGpioConfig) { + + u32 totalLen; + u32 TranslatedPinNum; + u32 GroupNum; + u32 ElectricChar; + u32 groupCfg; + void *buffer; + int rc; + + struct SetGpioMsg { + struct SmsMsgHdr_ST xMsgHeader; + u32 msgData[6]; + } *pMsg; + + + if (PinNum > MAX_GPIO_PIN_NUMBER) + return -EINVAL; + + if (pGpioConfig == NULL) + return -EINVAL; + + totalLen = sizeof(struct SmsMsgHdr_ST) + (sizeof(u32) * 6); + + buffer = kmalloc(totalLen + SMS_DMA_ALIGNMENT, + GFP_KERNEL | GFP_DMA); + if (!buffer) + return -ENOMEM; + + pMsg = (struct SetGpioMsg *) SMS_ALIGN_ADDRESS(buffer); + + pMsg->xMsgHeader.msgSrcId = DVBT_BDA_CONTROL_MSG_ID; + pMsg->xMsgHeader.msgDstId = HIF_TASK; + pMsg->xMsgHeader.msgFlags = 0; + pMsg->xMsgHeader.msgLength = (u16) totalLen; + pMsg->msgData[0] = PinNum; + + if (!(coredev->device_flags & SMS_DEVICE_FAMILY2)) { + pMsg->xMsgHeader.msgType = MSG_SMS_GPIO_CONFIG_REQ; + if (GetGpioPinParams(PinNum, &TranslatedPinNum, &GroupNum, + &groupCfg) != 0) + return -EINVAL; + + pMsg->msgData[1] = TranslatedPinNum; + pMsg->msgData[2] = GroupNum; + ElectricChar = (pGpioConfig->PullUpDown) + | (pGpioConfig->InputCharacteristics << 2) + | (pGpioConfig->OutputSlewRate << 3) + | (pGpioConfig->OutputDriving << 4); + pMsg->msgData[3] = ElectricChar; + pMsg->msgData[4] = pGpioConfig->Direction; + pMsg->msgData[5] = groupCfg; + } else { + pMsg->xMsgHeader.msgType = MSG_SMS_GPIO_CONFIG_EX_REQ; + pMsg->msgData[1] = pGpioConfig->PullUpDown; + pMsg->msgData[2] = pGpioConfig->OutputSlewRate; + pMsg->msgData[3] = pGpioConfig->OutputDriving; + pMsg->msgData[4] = pGpioConfig->Direction; + pMsg->msgData[5] = 0; + } + + smsendian_handle_tx_message((struct SmsMsgHdr_ST *)pMsg); + rc = smscore_sendrequest_and_wait(coredev, pMsg, totalLen, + &coredev->gpio_configuration_done); + + if (rc != 0) { + if (rc == -ETIME) + sms_err("smscore_gpio_configure timeout"); + else + sms_err("smscore_gpio_configure error"); + } + kfree(buffer); + + return rc; +} + +int smscore_gpio_set_level(struct smscore_device_t *coredev, u8 PinNum, + u8 NewLevel) { + + u32 totalLen; + int rc; + void *buffer; + + struct SetGpioMsg { + struct SmsMsgHdr_ST xMsgHeader; + u32 msgData[3]; /* keep it 3 ! */ + } *pMsg; + + if ((NewLevel > 1) || (PinNum > MAX_GPIO_PIN_NUMBER) || + (PinNum > MAX_GPIO_PIN_NUMBER)) + return -EINVAL; + + totalLen = sizeof(struct SmsMsgHdr_ST) + + (3 * sizeof(u32)); /* keep it 3 ! */ + + buffer = kmalloc(totalLen + SMS_DMA_ALIGNMENT, + GFP_KERNEL | GFP_DMA); + if (!buffer) + return -ENOMEM; + + pMsg = (struct SetGpioMsg *) SMS_ALIGN_ADDRESS(buffer); + + pMsg->xMsgHeader.msgSrcId = DVBT_BDA_CONTROL_MSG_ID; + pMsg->xMsgHeader.msgDstId = HIF_TASK; + pMsg->xMsgHeader.msgFlags = 0; + pMsg->xMsgHeader.msgType = MSG_SMS_GPIO_SET_LEVEL_REQ; + pMsg->xMsgHeader.msgLength = (u16) totalLen; + pMsg->msgData[0] = PinNum; + pMsg->msgData[1] = NewLevel; + + /* Send message to SMS */ + smsendian_handle_tx_message((struct SmsMsgHdr_ST *)pMsg); + rc = smscore_sendrequest_and_wait(coredev, pMsg, totalLen, + &coredev->gpio_set_level_done); + + if (rc != 0) { + if (rc == -ETIME) + sms_err("smscore_gpio_set_level timeout"); + else + sms_err("smscore_gpio_set_level error"); + } + kfree(buffer); + + return rc; +} + +int smscore_gpio_get_level(struct smscore_device_t *coredev, u8 PinNum, + u8 *level) { + + u32 totalLen; + int rc; + void *buffer; + + struct SetGpioMsg { + struct SmsMsgHdr_ST xMsgHeader; + u32 msgData[2]; + } *pMsg; + + + if (PinNum > MAX_GPIO_PIN_NUMBER) + return -EINVAL; + + totalLen = sizeof(struct SmsMsgHdr_ST) + (2 * sizeof(u32)); + + buffer = kmalloc(totalLen + SMS_DMA_ALIGNMENT, + GFP_KERNEL | GFP_DMA); + if (!buffer) + return -ENOMEM; + + pMsg = (struct SetGpioMsg *) SMS_ALIGN_ADDRESS(buffer); + + pMsg->xMsgHeader.msgSrcId = DVBT_BDA_CONTROL_MSG_ID; + pMsg->xMsgHeader.msgDstId = HIF_TASK; + pMsg->xMsgHeader.msgFlags = 0; + pMsg->xMsgHeader.msgType = MSG_SMS_GPIO_GET_LEVEL_REQ; + pMsg->xMsgHeader.msgLength = (u16) totalLen; + pMsg->msgData[0] = PinNum; + pMsg->msgData[1] = 0; + + /* Send message to SMS */ + smsendian_handle_tx_message((struct SmsMsgHdr_ST *)pMsg); + rc = smscore_sendrequest_and_wait(coredev, pMsg, totalLen, + &coredev->gpio_get_level_done); + + if (rc != 0) { + if (rc == -ETIME) + sms_err("smscore_gpio_get_level timeout"); + else + sms_err("smscore_gpio_get_level error"); + } + kfree(buffer); + + /* Its a race between other gpio_get_level() and the copy of the single + * global 'coredev->gpio_get_res' to the function's variable 'level' + */ + *level = coredev->gpio_get_res; + + return rc; +} + static int __init smscore_module_init(void) { int rc = 0; diff --git a/linux/drivers/media/dvb/siano/smscoreapi.h b/linux/drivers/media/dvb/siano/smscoreapi.h index f4aa406ef..28663315a 100644 --- a/linux/drivers/media/dvb/siano/smscoreapi.h +++ b/linux/drivers/media/dvb/siano/smscoreapi.h @@ -550,7 +550,7 @@ struct SMSHOSTLIB_I2C_RES_ST { }; -struct smscore_gpio_config { +struct smscore_config_gpio { #define SMS_GPIO_DIRECTION_INPUT 0 #define SMS_GPIO_DIRECTION_OUTPUT 1 u8 direction; @@ -576,6 +576,48 @@ struct smscore_gpio_config { u8 outputdriving; }; +struct smscore_gpio_config { +#define SMS_GPIO_DIRECTION_INPUT 0 +#define SMS_GPIO_DIRECTION_OUTPUT 1 + u8 Direction; + +#define SMS_GPIO_PULLUPDOWN_NONE 0 +#define SMS_GPIO_PULLUPDOWN_PULLDOWN 1 +#define SMS_GPIO_PULLUPDOWN_PULLUP 2 +#define SMS_GPIO_PULLUPDOWN_KEEPER 3 + u8 PullUpDown; + +#define SMS_GPIO_INPUT_CHARACTERISTICS_NORMAL 0 +#define SMS_GPIO_INPUT_CHARACTERISTICS_SCHMITT 1 + u8 InputCharacteristics; + +#define SMS_GPIO_OUTPUT_SLEW_RATE_SLOW 1 /* 10xx */ +#define SMS_GPIO_OUTPUT_SLEW_RATE_FAST 0 /* 10xx */ + + +#define SMS_GPIO_OUTPUT_SLEW_RATE_0_45_V_NS 0 /* 11xx */ +#define SMS_GPIO_OUTPUT_SLEW_RATE_0_9_V_NS 1 /* 11xx */ +#define SMS_GPIO_OUTPUT_SLEW_RATE_1_7_V_NS 2 /* 11xx */ +#define SMS_GPIO_OUTPUT_SLEW_RATE_3_3_V_NS 3 /* 11xx */ + u8 OutputSlewRate; + +#define SMS_GPIO_OUTPUT_DRIVING_S_4mA 0 /* 10xx */ +#define SMS_GPIO_OUTPUT_DRIVING_S_8mA 1 /* 10xx */ +#define SMS_GPIO_OUTPUT_DRIVING_S_12mA 2 /* 10xx */ +#define SMS_GPIO_OUTPUT_DRIVING_S_16mA 3 /* 10xx */ + +#define SMS_GPIO_OUTPUT_DRIVING_1_5mA 0 /* 11xx */ +#define SMS_GPIO_OUTPUT_DRIVING_2_8mA 1 /* 11xx */ +#define SMS_GPIO_OUTPUT_DRIVING_4mA 2 /* 11xx */ +#define SMS_GPIO_OUTPUT_DRIVING_7mA 3 /* 11xx */ +#define SMS_GPIO_OUTPUT_DRIVING_10mA 4 /* 11xx */ +#define SMS_GPIO_OUTPUT_DRIVING_11mA 5 /* 11xx */ +#define SMS_GPIO_OUTPUT_DRIVING_14mA 6 /* 11xx */ +#undef SMS_GPIO_OUTPUT_DRIVING_16mA +#define SMS_GPIO_OUTPUT_DRIVING_16mA 7 /* 11xx */ + u8 OutputDriving; +}; + extern void smscore_registry_setmode(char *devpath, int mode); extern int smscore_registry_getmode(char *devpath); @@ -619,10 +661,19 @@ struct smscore_buffer_t *smscore_getbuffer(struct smscore_device_t *coredev); extern void smscore_putbuffer(struct smscore_device_t *coredev, struct smscore_buffer_t *cb); +/* old GPIO managment */ int smscore_configure_gpio(struct smscore_device_t *coredev, u32 pin, - struct smscore_gpio_config *pinconfig); + struct smscore_config_gpio *pinconfig); int smscore_set_gpio(struct smscore_device_t *coredev, u32 pin, int level); +/* new GPIO managment */ +extern int smscore_gpio_configure(struct smscore_device_t *coredev, u8 PinNum, + struct smscore_gpio_config *pGpioConfig); +extern int smscore_gpio_set_level(struct smscore_device_t *coredev, u8 PinNum, + u8 NewLevel); +extern int smscore_gpio_get_level(struct smscore_device_t *coredev, u8 PinNum, + u8 *level); + void smscore_set_board_id(struct smscore_device_t *core, int id); int smscore_get_board_id(struct smscore_device_t *core); -- cgit v1.2.3 From 52057033c8278b7d00e054ea3ea6c5d8e55256a9 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 19 May 2009 15:10:36 +0000 Subject: Siano: smscore - fix some new GPIO definitions names From: Uri Shkolnik Fix some definitions' names, in order to emphasize the names Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/siano/smscoreapi.h | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/siano/smscoreapi.h b/linux/drivers/media/dvb/siano/smscoreapi.h index 28663315a..6fbab351f 100644 --- a/linux/drivers/media/dvb/siano/smscoreapi.h +++ b/linux/drivers/media/dvb/siano/smscoreapi.h @@ -581,10 +581,10 @@ struct smscore_gpio_config { #define SMS_GPIO_DIRECTION_OUTPUT 1 u8 Direction; -#define SMS_GPIO_PULLUPDOWN_NONE 0 -#define SMS_GPIO_PULLUPDOWN_PULLDOWN 1 -#define SMS_GPIO_PULLUPDOWN_PULLUP 2 -#define SMS_GPIO_PULLUPDOWN_KEEPER 3 +#define SMS_GPIO_PULL_UP_DOWN_NONE 0 +#define SMS_GPIO_PULL_UP_DOWN_PULLDOWN 1 +#define SMS_GPIO_PULL_UP_DOWN_PULLUP 2 +#define SMS_GPIO_PULL_UP_DOWN_KEEPER 3 u8 PullUpDown; #define SMS_GPIO_INPUT_CHARACTERISTICS_NORMAL 0 @@ -608,13 +608,12 @@ struct smscore_gpio_config { #define SMS_GPIO_OUTPUT_DRIVING_1_5mA 0 /* 11xx */ #define SMS_GPIO_OUTPUT_DRIVING_2_8mA 1 /* 11xx */ -#define SMS_GPIO_OUTPUT_DRIVING_4mA 2 /* 11xx */ -#define SMS_GPIO_OUTPUT_DRIVING_7mA 3 /* 11xx */ -#define SMS_GPIO_OUTPUT_DRIVING_10mA 4 /* 11xx */ -#define SMS_GPIO_OUTPUT_DRIVING_11mA 5 /* 11xx */ -#define SMS_GPIO_OUTPUT_DRIVING_14mA 6 /* 11xx */ -#undef SMS_GPIO_OUTPUT_DRIVING_16mA -#define SMS_GPIO_OUTPUT_DRIVING_16mA 7 /* 11xx */ +#define SMS_GPIO_OUTPUT_DRIVING_4mA 2 /* 11xx */ +#define SMS_GPIO_OUTPUT_DRIVING_7mA 3 /* 11xx */ +#define SMS_GPIO_OUTPUT_DRIVING_10mA 4 /* 11xx */ +#define SMS_GPIO_OUTPUT_DRIVING_11mA 5 /* 11xx */ +#define SMS_GPIO_OUTPUT_DRIVING_14mA 6 /* 11xx */ +#define SMS_GPIO_OUTPUT_DRIVING_16mA 7 /* 11xx */ u8 OutputDriving; }; -- cgit v1.2.3 From acac54fbcb26b026019f2aed395b998538e3e485 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 19 May 2009 15:18:40 +0000 Subject: Siano: smscards - add board (target) events From: Uri Shkolnik Add events handling for targets. All board-specific (target specific) should reside here. Priority: normal Signed-off-by: Uri Shkolnik Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/siano/sms-cards.c | 167 ++++++++++++++++++++++++++++++ linux/drivers/media/dvb/siano/sms-cards.h | 24 +++++ 2 files changed, 191 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 370cf513a..d8b15d583 100644 --- a/linux/drivers/media/dvb/siano/sms-cards.c +++ b/linux/drivers/media/dvb/siano/sms-cards.c @@ -104,6 +104,173 @@ struct sms_board *sms_get_board(int id) return &sms_boards[id]; } EXPORT_SYMBOL_GPL(sms_get_board); +static inline void sms_gpio_assign_11xx_default_led_config( + struct smscore_gpio_config *pGpioConfig) { + pGpioConfig->Direction = SMS_GPIO_DIRECTION_OUTPUT; + pGpioConfig->InputCharacteristics = + SMS_GPIO_INPUT_CHARACTERISTICS_NORMAL; + pGpioConfig->OutputDriving = SMS_GPIO_OUTPUT_DRIVING_4mA; + pGpioConfig->OutputSlewRate = SMS_GPIO_OUTPUT_SLEW_RATE_0_45_V_NS; + pGpioConfig->PullUpDown = SMS_GPIO_PULL_UP_DOWN_NONE; +} + +int sms_board_event(struct smscore_device_t *coredev, + enum SMS_BOARD_EVENTS gevent) { + int board_id = smscore_get_board_id(coredev); + struct sms_board *board = sms_get_board(board_id); + struct smscore_gpio_config MyGpioConfig; + + sms_gpio_assign_11xx_default_led_config(&MyGpioConfig); + + switch (gevent) { + case BOARD_EVENT_POWER_INIT: /* including hotplug */ + switch (board_id) { + case SMS1XXX_BOARD_HAUPPAUGE_WINDHAM: + /* set I/O and turn off all LEDs */ + smscore_gpio_configure(coredev, + board->board_cfg.leds_power, + &MyGpioConfig); + smscore_gpio_set_level(coredev, + board->board_cfg.leds_power, 0); + smscore_gpio_configure(coredev, board->board_cfg.led0, + &MyGpioConfig); + smscore_gpio_set_level(coredev, + board->board_cfg.led0, 0); + smscore_gpio_configure(coredev, board->board_cfg.led1, + &MyGpioConfig); + smscore_gpio_set_level(coredev, + board->board_cfg.led1, 0); + break; + case SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD_R2: + case SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD: + /* set I/O and turn off LNA */ + smscore_gpio_configure(coredev, + board->board_cfg.foreign_lna0_ctrl, + &MyGpioConfig); + smscore_gpio_set_level(coredev, + board->board_cfg.foreign_lna0_ctrl, + 0); + break; + } + break; /* BOARD_EVENT_BIND */ + + case BOARD_EVENT_POWER_SUSPEND: + switch (board_id) { + case SMS1XXX_BOARD_HAUPPAUGE_WINDHAM: + smscore_gpio_set_level(coredev, + board->board_cfg.leds_power, 0); + smscore_gpio_set_level(coredev, + board->board_cfg.led0, 0); + smscore_gpio_set_level(coredev, + board->board_cfg.led1, 0); + break; + case SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD_R2: + case SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD: + smscore_gpio_set_level(coredev, + board->board_cfg.foreign_lna0_ctrl, + 0); + break; + } + break; /* BOARD_EVENT_POWER_SUSPEND */ + + case BOARD_EVENT_POWER_RESUME: + switch (board_id) { + case SMS1XXX_BOARD_HAUPPAUGE_WINDHAM: + smscore_gpio_set_level(coredev, + board->board_cfg.leds_power, 1); + smscore_gpio_set_level(coredev, + board->board_cfg.led0, 1); + smscore_gpio_set_level(coredev, + board->board_cfg.led1, 0); + break; + case SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD_R2: + case SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD: + smscore_gpio_set_level(coredev, + board->board_cfg.foreign_lna0_ctrl, + 1); + break; + } + break; /* BOARD_EVENT_POWER_RESUME */ + + case BOARD_EVENT_BIND: + switch (board_id) { + case SMS1XXX_BOARD_HAUPPAUGE_WINDHAM: + smscore_gpio_set_level(coredev, + board->board_cfg.leds_power, 1); + smscore_gpio_set_level(coredev, + board->board_cfg.led0, 1); + smscore_gpio_set_level(coredev, + board->board_cfg.led1, 0); + break; + case SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD_R2: + case SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD: + smscore_gpio_set_level(coredev, + board->board_cfg.foreign_lna0_ctrl, + 1); + break; + } + break; /* BOARD_EVENT_BIND */ + + case BOARD_EVENT_SCAN_PROG: + break; /* BOARD_EVENT_SCAN_PROG */ + case BOARD_EVENT_SCAN_COMP: + break; /* BOARD_EVENT_SCAN_COMP */ + case BOARD_EVENT_EMERGENCY_WARNING_SIGNAL: + break; /* BOARD_EVENT_EMERGENCY_WARNING_SIGNAL */ + case BOARD_EVENT_FE_LOCK: + switch (board_id) { + case SMS1XXX_BOARD_HAUPPAUGE_WINDHAM: + smscore_gpio_set_level(coredev, + board->board_cfg.led1, 1); + break; + } + break; /* BOARD_EVENT_FE_LOCK */ + case BOARD_EVENT_FE_UNLOCK: + switch (board_id) { + case SMS1XXX_BOARD_HAUPPAUGE_WINDHAM: + smscore_gpio_set_level(coredev, + board->board_cfg.led1, 0); + break; + } + break; /* BOARD_EVENT_FE_UNLOCK */ + case BOARD_EVENT_DEMOD_LOCK: + break; /* BOARD_EVENT_DEMOD_LOCK */ + case BOARD_EVENT_DEMOD_UNLOCK: + break; /* BOARD_EVENT_DEMOD_UNLOCK */ + case BOARD_EVENT_RECEPTION_MAX_4: + break; /* BOARD_EVENT_RECEPTION_MAX_4 */ + case BOARD_EVENT_RECEPTION_3: + break; /* BOARD_EVENT_RECEPTION_3 */ + case BOARD_EVENT_RECEPTION_2: + break; /* BOARD_EVENT_RECEPTION_2 */ + case BOARD_EVENT_RECEPTION_1: + break; /* BOARD_EVENT_RECEPTION_1 */ + case BOARD_EVENT_RECEPTION_LOST_0: + break; /* BOARD_EVENT_RECEPTION_LOST_0 */ + case BOARD_EVENT_MULTIPLEX_OK: + switch (board_id) { + case SMS1XXX_BOARD_HAUPPAUGE_WINDHAM: + smscore_gpio_set_level(coredev, + board->board_cfg.led1, 1); + break; + } + break; /* BOARD_EVENT_MULTIPLEX_OK */ + case BOARD_EVENT_MULTIPLEX_ERRORS: + switch (board_id) { + case SMS1XXX_BOARD_HAUPPAUGE_WINDHAM: + smscore_gpio_set_level(coredev, + board->board_cfg.led1, 0); + break; + } + break; /* BOARD_EVENT_MULTIPLEX_ERRORS */ + + default: + sms_err("Unknown SMS board event"); + break; + } + return 0; +} +EXPORT_SYMBOL_GPL(sms_board_event); static int sms_set_gpio(struct smscore_device_t *coredev, int pin, int enable) { diff --git a/linux/drivers/media/dvb/siano/sms-cards.h b/linux/drivers/media/dvb/siano/sms-cards.h index e183f946a..38f062f6a 100644 --- a/linux/drivers/media/dvb/siano/sms-cards.h +++ b/linux/drivers/media/dvb/siano/sms-cards.h @@ -85,6 +85,30 @@ struct sms_board *sms_get_board(int id); extern struct smscore_device_t *coredev; +enum SMS_BOARD_EVENTS { + BOARD_EVENT_POWER_INIT, + BOARD_EVENT_POWER_SUSPEND, + BOARD_EVENT_POWER_RESUME, + BOARD_EVENT_BIND, + BOARD_EVENT_SCAN_PROG, + BOARD_EVENT_SCAN_COMP, + BOARD_EVENT_EMERGENCY_WARNING_SIGNAL, + BOARD_EVENT_FE_LOCK, + BOARD_EVENT_FE_UNLOCK, + BOARD_EVENT_DEMOD_LOCK, + BOARD_EVENT_DEMOD_UNLOCK, + BOARD_EVENT_RECEPTION_MAX_4, + BOARD_EVENT_RECEPTION_3, + BOARD_EVENT_RECEPTION_2, + BOARD_EVENT_RECEPTION_1, + BOARD_EVENT_RECEPTION_LOST_0, + BOARD_EVENT_MULTIPLEX_OK, + BOARD_EVENT_MULTIPLEX_ERRORS +}; + +int sms_board_event(struct smscore_device_t *coredev, + enum SMS_BOARD_EVENTS gevent); + int sms_board_setup(struct smscore_device_t *coredev); #define SMS_LED_OFF 0 -- cgit v1.2.3 From 26abee2f5be78d62a6dd302315e71614f93b62bc Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 19 May 2009 15:24:03 +0000 Subject: Siano: smsusb - remove redundant ifdef From: Uri Shkolnik Remove a redundant ifdef Priority: normal Signed-off-by: Uri Shkolnik Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/siano/smsusb.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/siano/smsusb.c b/linux/drivers/media/dvb/siano/smsusb.c index a85538b06..c31a52d3a 100644 --- a/linux/drivers/media/dvb/siano/smsusb.c +++ b/linux/drivers/media/dvb/siano/smsusb.c @@ -489,7 +489,6 @@ static int smsusb_resume(struct usb_interface *intf) } struct usb_device_id smsusb_id_table[] = { -#ifdef CONFIG_DVB_SIANO_SMS1XXX_SMS_IDS { USB_DEVICE(0x187f, 0x0010), .driver_info = SMS1XXX_BOARD_SIANO_STELLAR }, { USB_DEVICE(0x187f, 0x0100), @@ -500,7 +499,6 @@ struct usb_device_id smsusb_id_table[] = { .driver_info = SMS1XXX_BOARD_SIANO_NOVA_B }, { USB_DEVICE(0x187f, 0x0300), .driver_info = SMS1XXX_BOARD_SIANO_VEGA }, -#endif { USB_DEVICE(0x2040, 0x1700), .driver_info = SMS1XXX_BOARD_HAUPPAUGE_CATAMOUNT }, { USB_DEVICE(0x2040, 0x1800), -- cgit v1.2.3 From 0bd1a842c277e4fbd4b78c3af80708135638e820 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 19 May 2009 15:28:02 +0000 Subject: Siano: smsdvb - add DVB v3 events From: Uri Shkolnik Add various DVB-API v3 events, those events will trig target (card) events. Priority: normal Signed-off-by: Uri Shkolnik Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/siano/smsdvb.c | 48 ++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/siano/smsdvb.c b/linux/drivers/media/dvb/siano/smsdvb.c index 39421ee6f..f8856d9c8 100644 --- a/linux/drivers/media/dvb/siano/smsdvb.c +++ b/linux/drivers/media/dvb/siano/smsdvb.c @@ -66,6 +66,54 @@ MODULE_PARM_DESC(debug, "set debug level (info=1, adv=2 (or-able))"); /* Events that may come from DVB v3 adapter */ static void sms_board_dvb3_event(struct smsdvb_client_t *client, enum SMS_DVB3_EVENTS event) { + + struct smscore_device_t *coredev = client->coredev; + switch (event) { + case DVB3_EVENT_INIT: + sms_debug("DVB3_EVENT_INIT"); + sms_board_event(coredev, BOARD_EVENT_BIND); + break; + case DVB3_EVENT_SLEEP: + sms_debug("DVB3_EVENT_SLEEP"); + sms_board_event(coredev, BOARD_EVENT_POWER_SUSPEND); + break; + case DVB3_EVENT_HOTPLUG: + sms_debug("DVB3_EVENT_HOTPLUG"); + sms_board_event(coredev, BOARD_EVENT_POWER_INIT); + break; + case DVB3_EVENT_FE_LOCK: + if (client->event_fe_state != DVB3_EVENT_FE_LOCK) { + client->event_fe_state = DVB3_EVENT_FE_LOCK; + sms_debug("DVB3_EVENT_FE_LOCK"); + sms_board_event(coredev, BOARD_EVENT_FE_LOCK); + } + break; + case DVB3_EVENT_FE_UNLOCK: + if (client->event_fe_state != DVB3_EVENT_FE_UNLOCK) { + client->event_fe_state = DVB3_EVENT_FE_UNLOCK; + sms_debug("DVB3_EVENT_FE_UNLOCK"); + sms_board_event(coredev, BOARD_EVENT_FE_UNLOCK); + } + break; + case DVB3_EVENT_UNC_OK: + if (client->event_unc_state != DVB3_EVENT_UNC_OK) { + client->event_unc_state = DVB3_EVENT_UNC_OK; + sms_debug("DVB3_EVENT_UNC_OK"); + sms_board_event(coredev, BOARD_EVENT_MULTIPLEX_OK); + } + break; + case DVB3_EVENT_UNC_ERR: + if (client->event_unc_state != DVB3_EVENT_UNC_ERR) { + client->event_unc_state = DVB3_EVENT_UNC_ERR; + sms_debug("DVB3_EVENT_UNC_ERR"); + sms_board_event(coredev, BOARD_EVENT_MULTIPLEX_ERRORS); + } + break; + + default: + sms_err("Unknown dvb3 api event"); + break; + } } static int smsdvb_onresponse(void *context, struct smscore_buffer_t *cb) -- cgit v1.2.3 From 3c278aedd50ae75abf8b20630363185eff753f88 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 19 May 2009 15:34:09 +0000 Subject: Siano: smscore - remove redundant code From: Uri Shkolnik remove redundant code, which in the past handled the various components (now independent modules) registrations. Priority: normal Signed-off-by: Uri Shkolnik Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/siano/smscoreapi.c | 88 ------------------------------ 1 file changed, 88 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/siano/smscoreapi.c b/linux/drivers/media/dvb/siano/smscoreapi.c index 6446e0f6c..802d7e6a9 100644 --- a/linux/drivers/media/dvb/siano/smscoreapi.c +++ b/linux/drivers/media/dvb/siano/smscoreapi.c @@ -1645,99 +1645,11 @@ static int __init smscore_module_init(void) INIT_LIST_HEAD(&g_smscore_registry); kmutex_init(&g_smscore_registrylock); -#if 0 /* def SMS_CHAR_CLIENT */ - /* Char interface Register */ - rc = smschar_register(); - if (rc) { - sms_err("Error registering char device client.\n"); - goto smschar_error; - } -#endif - -#if 0 /* def SMS_DVB_CLIENT */ - /* DVB Register */ - rc = smsdvb_register(); - if (rc) { - sms_err("Error registering DVB client.\n"); - goto smsdvb_error; - } -#endif - -#if 0 /* def SMS_NET_CLIENT */ - /* DVB Register */ - rc = smsnet_register(); - if (rc) { - sms_err("Error registering Network client.\n"); - goto smsnet_error; - } -#endif - -#if 0 /* def SMS_USB_BUS_DRV */ - /* USB Register */ - rc = smsusb_register(); - if (rc) { - sms_err("Error registering USB bus driver.\n"); - goto sms_bus_drv_error; - } -#endif - -#if 0 /* def SMS_SPI_BUS_DRV */ - /* USB Register */ - rc = smsspi_register(); - if (rc) { - sms_err("Error registering spi bus driver.\n"); - goto sms_bus_drv_error; - } -#endif - - return rc; -#if 0 -sms_bus_drv_error: -#endif /* 0 */ -#if 0 /* def SMS_NET_CLIENT */ - smsnet_unregister(); -smsnet_error: -#endif -#if 0 /* def SMS_DVB_CLIENT */ - smsdvb_unregister(); -smsdvb_error: -#endif -#if 0 /* def SMS_CHAR_CLIENT */ - smschar_unregister(); -smschar_error: -#endif - sms_debug("rc %d", rc); - return rc; } static void __exit smscore_module_exit(void) { -#if 0 /* def SMS_CHAR_CLIENT */ - /* Char interface UnRegister */ - smschar_unregister(); -#endif - -#if 0 /* def SMS_DVB_CLIENT */ - /* DVB UnRegister */ - smsdvb_unregister(); -#endif - -#if 0 /* def SMS_NET_CLIENT */ - /* NET UnRegister */ - smsnet_unregister(); -#endif - -#if 0 /* def SMS_USB_BUS_DRV */ - /* Unregister USB */ - smsusb_unregister(); -#endif - -#if 0 /* def SMS_SPI_BUS_DRV */ - /* Unregister SPI */ - smsspi_unregister(); -#endif - kmutex_lock(&g_smscore_deviceslock); while (!list_empty(&g_smscore_notifyees)) { struct smscore_device_notifyee_t *notifyee = -- cgit v1.2.3 From 88e23f22d75580ffb879c5fd535d838830dfb7fe Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 19 May 2009 15:52:58 +0000 Subject: Siano: smscore - bind the GPIO SMS protocol From: Uri Shkolnik Bind SMS protocol commands to the GPIO commands Priority: normal Signed-off-by: Uri Shkolnik Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/siano/smscoreapi.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/siano/smscoreapi.c b/linux/drivers/media/dvb/siano/smscoreapi.c index 802d7e6a9..e513408fc 100644 --- a/linux/drivers/media/dvb/siano/smscoreapi.c +++ b/linux/drivers/media/dvb/siano/smscoreapi.c @@ -352,6 +352,9 @@ 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->gpio_configuration_done); + init_completion(&dev->gpio_set_level_done); + init_completion(&dev->gpio_get_level_done); init_completion(&dev->ir_init_done); /* Buffer management */ @@ -1051,6 +1054,23 @@ void smscore_onresponse(struct smscore_device_t *coredev, case MSG_SMS_SLEEP_RESUME_COMP_IND: complete(&coredev->resume_done); break; + case MSG_SMS_GPIO_CONFIG_EX_RES: + sms_debug("MSG_SMS_GPIO_CONFIG_EX_RES"); + complete(&coredev->gpio_configuration_done); + break; + case MSG_SMS_GPIO_SET_LEVEL_RES: + sms_debug("MSG_SMS_GPIO_SET_LEVEL_RES"); + complete(&coredev->gpio_set_level_done); + break; + case MSG_SMS_GPIO_GET_LEVEL_RES: + { + u32 *msgdata = (u32 *) phdr; + coredev->gpio_get_res = msgdata[1]; + sms_debug("MSG_SMS_GPIO_GET_LEVEL_RES gpio level %d", + coredev->gpio_get_res); + complete(&coredev->gpio_get_level_done); + break; + } case MSG_SMS_START_IR_RES: complete(&coredev->ir_init_done); break; -- cgit v1.2.3 From dc637c2382bc5ae4e39c9e07ae657d0eaab6d799 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 19 May 2009 15:56:16 +0000 Subject: Siano: smsendien - declare function as extern From: Uri Shkolnik Declare the object function as 'extern' Priority: normal Signed-off-by: Uri Shkolnik Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/siano/smsendian.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/siano/smsendian.h b/linux/drivers/media/dvb/siano/smsendian.h index 7fbedc6a6..1624d6fd3 100644 --- a/linux/drivers/media/dvb/siano/smsendian.h +++ b/linux/drivers/media/dvb/siano/smsendian.h @@ -24,9 +24,9 @@ along with this program. If not, see . #include -void smsendian_handle_tx_message(void *buffer); -void smsendian_handle_rx_message(void *buffer); -void smsendian_handle_message_header(void *msg); +extern void smsendian_handle_tx_message(void *buffer); +extern void smsendian_handle_rx_message(void *buffer); +extern void smsendian_handle_message_header(void *msg); #endif /* __SMS_ENDIAN_H__ */ -- cgit v1.2.3 From b0ead79496ce5e528b0735acae2d8c0c61803d22 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 19 May 2009 16:00:42 +0000 Subject: Siano: smscore - remove redundant define From: Uri Shkolnik Remove redundant define. Priority: normal Signed-off-by: Uri Shkolnik Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/siano/smscoreapi.h | 2 -- 1 file changed, 2 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/siano/smscoreapi.h b/linux/drivers/media/dvb/siano/smscoreapi.h index 6fbab351f..bc4572de6 100644 --- a/linux/drivers/media/dvb/siano/smscoreapi.h +++ b/linux/drivers/media/dvb/siano/smscoreapi.h @@ -645,7 +645,6 @@ extern int smsclient_sendrequest(struct smscore_client_t *client, extern void smscore_onresponse(struct smscore_device_t *coredev, struct smscore_buffer_t *cb); -#if 1 extern int smscore_get_common_buffer_size(struct smscore_device_t *coredev); extern int smscore_map_common_buffer(struct smscore_device_t *coredev, struct vm_area_struct *vma); @@ -653,7 +652,6 @@ extern int smscore_get_fw_filename(struct smscore_device_t *coredev, int mode, char *filename); extern int smscore_send_fw_file(struct smscore_device_t *coredev, u8 *ufwbuf, int size); -#endif extern struct smscore_buffer_t *smscore_getbuffer(struct smscore_device_t *coredev); -- cgit v1.2.3 From 5f623f9662748ffe9662ee5b0561fe746ef3279d Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Wed, 20 May 2009 22:58:16 -0400 Subject: dvb_frontend: fix case where fepriv->exit not reset From: Devin Heitmueller The fact that we now explicitly set fepriv->exit = 1 when the thread is shutting down exposed an edge case where it was not being reset back to zero once the thread went away in some cases. This resulted in failures in cases where the frontend was closed, and then opened O_RDONLY, since in that case the thread is not being restarted but it was checking the fepriv->exit flag. Thanks to Thierry Lelegard, who and encountered and debugged a large portion of the issue in the same twelve hours that I did (as well as testing my patch). Priority: high Signed-off-by: Devin Heitmueller Cc: Thierry Lelegard --- 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 d359f6841..41166d407 100644 --- a/linux/drivers/media/dvb/dvb-core/dvb_frontend.c +++ b/linux/drivers/media/dvb/dvb-core/dvb_frontend.c @@ -668,6 +668,7 @@ restart: } fepriv->thread = NULL; + fepriv->exit = 0; mb(); dvb_frontend_wakeup(fe); -- cgit v1.2.3 From faf2a349d29687e3f55dbe86d0728c549bd33ff1 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Fri, 19 Jun 2009 15:21:37 -0400 Subject: tda10048: add missing entry to pll_tab for 3.8 MHz IF From: Michael Krufky Thanks for Terry Wu for pointing out the missing entry. Priority: high Cc: Terry Wu Signed-off-by: Michael Krufky --- linux/drivers/media/dvb/frontends/tda10048.c | 1 + 1 file changed, 1 insertion(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/frontends/tda10048.c b/linux/drivers/media/dvb/frontends/tda10048.c index 04596baa9..edf5a19a3 100644 --- a/linux/drivers/media/dvb/frontends/tda10048.c +++ b/linux/drivers/media/dvb/frontends/tda10048.c @@ -210,6 +210,7 @@ static struct pll_tab { { TDA10048_CLK_4000, TDA10048_IF_36130, 10, 0, 0 }, { TDA10048_CLK_16000, TDA10048_IF_3300, 10, 3, 0 }, { TDA10048_CLK_16000, TDA10048_IF_3500, 10, 3, 0 }, + { TDA10048_CLK_16000, TDA10048_IF_3800, 10, 3, 0 }, { TDA10048_CLK_16000, TDA10048_IF_4000, 10, 3, 0 }, { TDA10048_CLK_16000, TDA10048_IF_4300, 10, 3, 0 }, { TDA10048_CLK_16000, TDA10048_IF_36130, 10, 3, 0 }, -- cgit v1.2.3 From 04ef26ec109fff2b6d310da4dabdafc4135ad058 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Thu, 21 May 2009 11:49:28 -0400 Subject: cx23885: ensure correct IF freq is used on HVR1200 & HVR1700 From: Michael Krufky Ensure that we're programming the tda18271 tuner with the correct IF frequencies to match the programming of the TDA10048 DVB-T demod for the HVR1200 and HVR1700 products. Priority: high Signed-off-by: Michael Krufky --- linux/drivers/media/video/cx23885/cx23885-dvb.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/cx23885/cx23885-dvb.c b/linux/drivers/media/video/cx23885/cx23885-dvb.c index 4efc7dee1..499beaf3d 100644 --- a/linux/drivers/media/video/cx23885/cx23885-dvb.c +++ b/linux/drivers/media/video/cx23885/cx23885-dvb.c @@ -242,12 +242,22 @@ static struct tda18271_std_map hauppauge_tda18271_std_map = { .if_lvl = 6, .rfagc_top = 0x37 }, }; +static struct tda18271_std_map hauppauge_hvr1200_tda18271_std_map = { + .dvbt_6 = { .if_freq = 3300, .agc_mode = 3, .std = 4, + .if_lvl = 1, .rfagc_top = 0x37, }, + .dvbt_7 = { .if_freq = 3800, .agc_mode = 3, .std = 5, + .if_lvl = 1, .rfagc_top = 0x37, }, + .dvbt_8 = { .if_freq = 4300, .agc_mode = 3, .std = 6, + .if_lvl = 1, .rfagc_top = 0x37, }, +}; + static struct tda18271_config hauppauge_tda18271_config = { .std_map = &hauppauge_tda18271_std_map, .gate = TDA18271_GATE_ANALOG, }; static struct tda18271_config hauppauge_hvr1200_tuner_config = { + .std_map = &hauppauge_hvr1200_tda18271_std_map, .gate = TDA18271_GATE_ANALOG, }; -- cgit v1.2.3 From 98b4c4078e4d51a889a86cead6c03d1b6c8a5b3d Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Fri, 22 May 2009 09:16:42 +0200 Subject: gspca - ov534: JPEG 320x240 and 640x480 formats for ov965x. From: Jean-Francois Moine The YUYV 640x480 format did not work with ov965x. Priority: normal Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/ov534.c | 244 ++++++++++++++++++++++---------- 1 file changed, 173 insertions(+), 71 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/ov534.c b/linux/drivers/media/video/gspca/ov534.c index 1e00e46b1..14341b6be 100644 --- a/linux/drivers/media/video/gspca/ov534.c +++ b/linux/drivers/media/video/gspca/ov534.c @@ -60,10 +60,23 @@ struct sd { static struct ctrl sd_ctrls[] = { }; -static const struct v4l2_pix_format vga_mode[] = { +static const struct v4l2_pix_format vga_yuyv_mode[] = { {640, 480, V4L2_PIX_FMT_YUYV, V4L2_FIELD_NONE, .bytesperline = 640 * 2, .sizeimage = 640 * 480 * 2, + .colorspace = V4L2_COLORSPACE_SRGB, + .priv = 0}, +}; + +static const struct v4l2_pix_format vga_jpeg_mode[] = { + {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, + .bytesperline = 320, + .sizeimage = 320 * 240 * 3 / 8 + 590, + .colorspace = V4L2_COLORSPACE_JPEG, + .priv = 1}, + {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, + .bytesperline = 640, + .sizeimage = 640 * 480 * 3 / 8 + 590, .colorspace = V4L2_COLORSPACE_JPEG, .priv = 0}, }; @@ -244,7 +257,7 @@ static const u8 bridge_init_ov965x[][2] = { }; static const u8 sensor_init_ov965x[][2] = { - {0x12, 0x80}, /* com7 - reset */ + {0x12, 0x80}, /* com7 - SSCB reset */ {0x00, 0x00}, /* gain */ {0x01, 0x80}, /* blue */ {0x02, 0x80}, /* red */ @@ -254,10 +267,10 @@ static const u8 sensor_init_ov965x[][2] = { {0x0e, 0x61}, /* com5 */ {0x0f, 0x42}, /* com6 */ {0x11, 0x00}, /* clkrc */ - {0x12, 0x02}, /* com7 */ + {0x12, 0x02}, /* com7 - 15fps VGA YUYV */ {0x13, 0xe7}, /* com8 - everything (AGC, AWB and AEC) */ {0x14, 0x28}, /* com9 */ - {0x16, 0x24}, /* rsvd16 */ + {0x16, 0x24}, /* reg16 */ {0x17, 0x1d}, /* hstart*/ {0x18, 0xbd}, /* hstop */ {0x19, 0x01}, /* vstrt */ @@ -269,24 +282,24 @@ static const u8 sensor_init_ov965x[][2] = { {0x27, 0x08}, /* bbias */ {0x28, 0x08}, /* gbbias */ {0x29, 0x15}, /* gr com */ - {0x2a, 0x00}, - {0x2b, 0x00}, + {0x2a, 0x00}, /* exhch */ + {0x2b, 0x00}, /* exhcl */ {0x2c, 0x08}, /* rbias */ {0x32, 0xff}, /* href */ {0x33, 0x00}, /* chlf */ - {0x34, 0x3f}, /* arblm */ - {0x35, 0x00}, /* rsvd35 */ - {0x36, 0xf8}, /* rsvd36 */ - {0x38, 0x72}, /* acom38 */ - {0x39, 0x57}, /* ofon */ - {0x3a, 0x80}, /* tslb */ - {0x3b, 0xc4}, + {0x34, 0x3f}, /* aref1 */ + {0x35, 0x00}, /* aref2 */ + {0x36, 0xf8}, /* aref3 */ + {0x38, 0x72}, /* adc2 */ + {0x39, 0x57}, /* aref4 */ + {0x3a, 0x80}, /* tslb - yuyv */ + {0x3b, 0xc4}, /* com11 - night mode 1/4 frame rate */ {0x3d, 0x99}, /* com13 */ - {0x3f, 0xc1}, + {0x3f, 0xc1}, /* edge */ {0x40, 0xc0}, /* com15 */ {0x41, 0x40}, /* com16 */ - {0x42, 0xc0}, - {0x43, 0x0a}, + {0x42, 0xc0}, /* com17 */ + {0x43, 0x0a}, /* rsvd */ {0x44, 0xf0}, {0x45, 0x46}, {0x46, 0x62}, @@ -297,22 +310,22 @@ static const u8 sensor_init_ov965x[][2] = { {0x4c, 0x7f}, {0x4d, 0x7f}, {0x4e, 0x7f}, - {0x4f, 0x98}, + {0x4f, 0x98}, /* matrix */ {0x50, 0x98}, {0x51, 0x00}, {0x52, 0x28}, {0x53, 0x70}, {0x54, 0x98}, - {0x58, 0x1a}, - {0x59, 0x85}, + {0x58, 0x1a}, /* matrix coef sign */ + {0x59, 0x85}, /* AWB control */ {0x5a, 0xa9}, {0x5b, 0x64}, {0x5c, 0x84}, {0x5d, 0x53}, {0x5e, 0x0e}, - {0x5f, 0xf0}, - {0x60, 0xf0}, - {0x61, 0xf0}, + {0x5f, 0xf0}, /* AWB blue limit */ + {0x60, 0xf0}, /* AWB red limit */ + {0x61, 0xf0}, /* AWB green limit */ {0x62, 0x00}, /* lcc1 */ {0x63, 0x00}, /* lcc2 */ {0x64, 0x02}, /* lcc3 */ @@ -324,15 +337,15 @@ static const u8 sensor_init_ov965x[][2] = { {0x6d, 0x55}, {0x6e, 0x00}, {0x6f, 0x9d}, - {0x70, 0x21}, + {0x70, 0x21}, /* dnsth */ {0x71, 0x78}, - {0x72, 0x00}, - {0x73, 0x01}, - {0x74, 0x3a}, - {0x75, 0x35}, + {0x72, 0x00}, /* poidx */ + {0x73, 0x01}, /* pckdv */ + {0x74, 0x3a}, /* xindx */ + {0x75, 0x35}, /* yindx */ {0x76, 0x01}, {0x77, 0x02}, - {0x7a, 0x12}, + {0x7a, 0x12}, /* gamma curve */ {0x7b, 0x08}, {0x7c, 0x16}, {0x7d, 0x30}, @@ -349,33 +362,33 @@ static const u8 sensor_init_ov965x[][2] = { {0x88, 0xe6}, {0x89, 0xf2}, {0x8a, 0x03}, - {0x8c, 0x89}, + {0x8c, 0x89}, /* com19 */ {0x14, 0x28}, /* com9 */ {0x90, 0x7d}, {0x91, 0x7b}, - {0x9d, 0x03}, - {0x9e, 0x04}, + {0x9d, 0x03}, /* lcc6 */ + {0x9e, 0x04}, /* lcc7 */ {0x9f, 0x7a}, {0xa0, 0x79}, {0xa1, 0x40}, /* aechm */ - {0xa4, 0x50}, + {0xa4, 0x50}, /* com21 */ {0xa5, 0x68}, /* com26 */ - {0xa6, 0x4a}, - {0xa8, 0xc1}, /* acoma8 */ - {0xa9, 0xef}, /* acoma9 */ + {0xa6, 0x4a}, /* AWB green */ + {0xa8, 0xc1}, /* refa8 */ + {0xa9, 0xef}, /* refa9 */ {0xaa, 0x92}, {0xab, 0x04}, - {0xac, 0x80}, + {0xac, 0x80}, /* black level control */ {0xad, 0x80}, {0xae, 0x80}, {0xaf, 0x80}, {0xb2, 0xf2}, {0xb3, 0x20}, - {0xb4, 0x20}, + {0xb4, 0x20}, /* ctrlb4 */ {0xb5, 0x00}, {0xb6, 0xaf}, {0xbb, 0xae}, - {0xbc, 0x7f}, + {0xbc, 0x7f}, /* ADC channel offsets */ {0xdb, 0x7f}, {0xbe, 0x7f}, {0xbf, 0x7f}, @@ -384,7 +397,7 @@ static const u8 sensor_init_ov965x[][2] = { {0xc2, 0x01}, {0xc3, 0x4e}, {0xc6, 0x85}, - {0xc7, 0x80}, + {0xc7, 0x80}, /* com24 */ {0xc9, 0xe0}, {0xca, 0xe8}, {0xcb, 0xf0}, @@ -399,11 +412,11 @@ static const u8 sensor_init_ov965x[][2] = { {0x58, 0x1a}, {0xff, 0x41}, /* read 41, write ff 00 */ {0x41, 0x40}, /* com16 */ - {0xc5, 0x03}, - {0x6a, 0x02}, + {0xc5, 0x03}, /* 60 Hz banding filter */ + {0x6a, 0x02}, /* 50 Hz banding filter */ - {0x12, 0x62}, /* com7 - VGA + CIF */ - {0x36, 0xfa}, /* rsvd36 */ + {0x12, 0x62}, /* com7 - 30fps VGA YUV */ + {0x36, 0xfa}, /* aref3 */ {0x69, 0x0a}, /* hv */ {0x8c, 0x89}, /* com22 */ {0x14, 0x28}, /* com9 */ @@ -442,8 +455,8 @@ static const u8 bridge_init_ov965x_2[][2] = { {0x52, 0x3c}, {0x53, 0x00}, {0x54, 0x00}, - {0x55, 0x00}, - {0x57, 0x00}, + {0x55, 0x00}, /* brightness */ + {0x57, 0x00}, /* contrast 2 */ {0x5c, 0x00}, {0x5a, 0xa0}, {0x5b, 0x78}, @@ -489,8 +502,31 @@ static const u8 sensor_init_ov965x_2[][2] = { {0x13, 0xe7}, /* com8 - everything (AGC, AWB and AEC) */ }; +static const u8 sensor_start_ov965x[][2] = { + {0x12, 0x62}, /* com7 - 30fps VGA YUV */ + {0x36, 0xfa}, /* aref3 */ + {0x69, 0x0a}, /* hv */ + {0x8c, 0x89}, /* com22 */ + {0x14, 0x28}, /* com9 */ + {0x3e, 0x0c}, /* com14 */ + {0x41, 0x40}, /* com16 */ + {0x72, 0x00}, + {0x73, 0x00}, + {0x74, 0x3a}, + {0x75, 0x35}, + {0x76, 0x01}, + {0xc7, 0x80}, /* com24 */ + {0x03, 0x12}, /* vref */ + {0x17, 0x16}, /* hstart */ + {0x18, 0x02}, /* hstop */ + {0x19, 0x01}, /* vstrt */ + {0x1a, 0x3d}, /* vstop */ + {0x32, 0xff}, /* href */ + {0xc0, 0xaa}, + {} +}; + static const u8 bridge_start_ov965x[][2] = { -#if 0 {0x94, 0xaa}, {0xf1, 0x60}, {0xe5, 0x04}, @@ -499,9 +535,33 @@ static const u8 bridge_start_ov965x[][2] = { {0x8c, 0x00}, {0x8d, 0x1c}, {0x34, 0x05}, -#endif + {} +}; + +static const u8 bridge_start_ov965x_vga[][2] = { + {0xc2, 0x0c}, + {0xc3, 0xf9}, + {0xda, 0x01}, + {0x50, 0x00}, + {0x51, 0xa0}, + {0x52, 0x3c}, + {0x53, 0x00}, + {0x54, 0x00}, + {0x55, 0x00}, + {0x57, 0x00}, + {0x5c, 0x00}, + {0x5a, 0xa0}, + {0x5b, 0x78}, + {0x35, 0x02}, + {0xd9, 0x10}, + {0x94, 0x11}, + {} +}; + +static const u8 bridge_start_ov965x_cif[][2] = { {0xc2, 0x4c}, {0xc3, 0xf9}, + {0xda, 0x00}, {0x50, 0x00}, {0x51, 0xa0}, {0x52, 0x78}, @@ -510,39 +570,64 @@ static const u8 bridge_start_ov965x[][2] = { {0x55, 0x00}, {0x57, 0x00}, {0x5c, 0x00}, - {0x5a, 0x28}, - {0x5b, 0x1e}, - {0x35, 0x00}, - {0xd9, 0x21}, + {0x5a, 0x50}, + {0x5b, 0x3c}, + {0x35, 0x02}, + {0xd9, 0x10}, {0x94, 0x11}, + {} }; -static const u8 sensor_start_ov965x[][2] = { - {0x3b, 0xe4}, +static const u8 sensor_start_ov965x_vga[][2] = { + {0x3b, 0xc4}, /* com11 - night mode 1/4 frame rate */ + {0x1e, 0x04}, /* mvfp */ + {0x13, 0xe0}, /* com8 */ + {0x00, 0x00}, + {0x13, 0xe7}, /* com8 - everything (AGC, AWB and AEC) */ + {0x11, 0x03}, /* clkrc */ + {0x6b, 0x5a}, /* dblv */ + {0x6a, 0x05}, /* 50 Hz banding filter */ + {0xc5, 0x07}, /* 60 Hz banding filter */ + {0xa2, 0x4b}, /* bd50 */ + {0xa3, 0x3e}, /* bd60 */ + + {0x2d, 0x00}, /* advfl */ + {} +}; + +static const u8 sensor_start_ov965x_cif[][2] = { + {0x3b, 0xe4}, /* com11 - night mode 1/4 frame rate */ {0x1e, 0x04}, /* mvfp */ {0x13, 0xe0}, /* com8 */ {0x00, 0x00}, {0x13, 0xe7}, /* com8 - everything (AGC, AWB and AEC) */ {0x11, 0x01}, /* clkrc */ {0x6b, 0x5a}, /* dblv */ - {0x6a, 0x02}, - {0xc5, 0x03}, - {0xa2, 0x96}, - {0xa3, 0x7d}, + {0x6a, 0x02}, /* 50 Hz banding filter */ + {0xc5, 0x03}, /* 60 Hz banding filter */ + {0xa2, 0x96}, /* bd50 */ + {0xa3, 0x7d}, /* bd60 */ + {0xff, 0x13}, /* read 13, write ff 00 */ {0x13, 0xe7}, - {0x3a, 0x80}, + {0x3a, 0x80}, /* tslb - yuyv */ + {} +}; + +static const u8 sensor_start_ov965x_2[][2] = { {0xff, 0x42}, /* read 42, write ff 00 */ - {0x42, 0xc1}, + {0x42, 0xc1}, /* com17 - 50 Hz filter */ + {} }; #if 0 -static const u8 sensor_start_ov965x_2[][2] = { +static const u8 sensor_start_ov965x_3[][2] = { {0xff, 0x13}, /* read 13, write ff 00 */ {0x13, 0xe7}, {0x3a, 0x80}, {0xff, 0x42}, /* read 42, write ff 00 */ {0x42, 0xc1}, + {} }; #endif @@ -724,13 +809,16 @@ static int sd_config(struct gspca_dev *gspca_dev, cam = &gspca_dev->cam; - cam->cam_mode = vga_mode; - cam->nmodes = ARRAY_SIZE(vga_mode); - if (sd->sensor == SENSOR_OV772X) { + cam->cam_mode = vga_yuyv_mode; + cam->nmodes = ARRAY_SIZE(vga_yuyv_mode); + cam->bulk = 1; cam->bulk_size = 16384; cam->bulk_nurbs = 2; + } else { /* ov965x */ + cam->cam_mode = vga_jpeg_mode; + cam->nmodes = ARRAY_SIZE(vga_jpeg_mode); } return 0; @@ -800,6 +888,7 @@ static int sd_init(struct gspca_dev *gspca_dev) static int sd_start(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; + int mode; switch (sd->sensor) { case SENSOR_OV772X: @@ -808,17 +897,28 @@ static int sd_start(struct gspca_dev *gspca_dev) break; default: /* case SENSOR_OV965X: */ -#if 0 - sccb_w_array(gspca_dev, sensor_init_ov965x, - ARRAY_SIZE(sensor_init_ov965x)); -#endif - reg_w_array(gspca_dev, bridge_start_ov965x, - ARRAY_SIZE(bridge_start_ov965x)); + sccb_w_array(gspca_dev, sensor_start_ov965x, ARRAY_SIZE(sensor_start_ov965x)); + reg_w_array(gspca_dev, bridge_start_ov965x, + ARRAY_SIZE(bridge_start_ov965x)); + mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv; + if (mode != 0) { /* 320x240 */ + reg_w_array(gspca_dev, bridge_start_ov965x_cif, + ARRAY_SIZE(bridge_start_ov965x_cif)); + sccb_w_array(gspca_dev, sensor_start_ov965x_cif, + ARRAY_SIZE(sensor_start_ov965x_cif)); + } else { /* 640x480 */ + reg_w_array(gspca_dev, bridge_start_ov965x_vga, + ARRAY_SIZE(bridge_start_ov965x_vga)); + sccb_w_array(gspca_dev, sensor_start_ov965x_vga, + ARRAY_SIZE(sensor_start_ov965x_vga)); + } + sccb_w_array(gspca_dev, sensor_start_ov965x_2, + ARRAY_SIZE(sensor_start_ov965x_2)); + ov534_reg_write(gspca_dev, 0xe0, 0x00); ov534_reg_write(gspca_dev, 0xe0, 0x00); ov534_set_led(gspca_dev, 1); -/*fixme: other sensor start omitted*/ } return 0; } @@ -901,12 +1001,14 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, struct gspca_frame *frame, /* If this packet is marked as EOF, end the frame */ } else if (data[1] & UVC_STREAM_EOF) { sd->last_pts = 0; - +#if 0 +/*fixme: check if not jpeg*/ if (frame->data_end - frame->data != gspca_dev->width * gspca_dev->height * 2) { PDEBUG(D_PACK, "short frame"); goto discard; } +#endif frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame, data + 12, len - 12); } else { -- cgit v1.2.3 From 355e218336f85e723e8061e62c292436b0654104 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 22 May 2009 10:19:14 +0000 Subject: flexcop-pci: dmesg visible names broken From: Matthias Schwarzott Changeset 1589a993f074124c3edfff03656e910bb472eeaa broke user visible names of flexcop-pci devices, as it did reorder the enum of card types, but did not adjust the array containing the card names. Reorder the names, and uses [FC_AIR_DVBT] = "Air2PC/AirStar 2 DVB-T" assignment style for more clarity. It also adds the revision Number to the name for SkyStar rev. 2.3 and rev 2.6 as I think it is useful to see in log output. Signed-off-by: Matthias Schwarzott Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/b2c2/flexcop-misc.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/b2c2/flexcop-misc.c b/linux/drivers/media/dvb/b2c2/flexcop-misc.c index e56627d2f..f06f3a907 100644 --- a/linux/drivers/media/dvb/b2c2/flexcop-misc.c +++ b/linux/drivers/media/dvb/b2c2/flexcop-misc.c @@ -46,16 +46,16 @@ static const char *flexcop_revision_names[] = { }; static const char *flexcop_device_names[] = { - "Unknown device", - "Air2PC/AirStar 2 DVB-T", - "Air2PC/AirStar 2 ATSC 1st generation", - "Air2PC/AirStar 2 ATSC 2nd generation", - "Sky2PC/SkyStar 2 DVB-S", - "Sky2PC/SkyStar 2 DVB-S (old version)", - "Cable2PC/CableStar 2 DVB-C", - "Air2PC/AirStar 2 ATSC 3rd generation (HD5000)", - "Sky2PC/SkyStar 2 DVB-S rev 2.7a/u", - "Sky2PC/SkyStar 2 DVB-S rev 2.8", + [FC_UNK] = "Unknown device", + [FC_CABLE] = "Cable2PC/CableStar 2 DVB-C", + [FC_AIR_DVBT] = "Air2PC/AirStar 2 DVB-T", + [FC_AIR_ATSC1] = "Air2PC/AirStar 2 ATSC 1st generation", + [FC_AIR_ATSC2] = "Air2PC/AirStar 2 ATSC 2nd generation", + [FC_AIR_ATSC3] = "Air2PC/AirStar 2 ATSC 3rd generation (HD5000)", + [FC_SKY_REV23] = "Sky2PC/SkyStar 2 DVB-S rev 2.3 (old version)", + [FC_SKY_REV26] = "Sky2PC/SkyStar 2 DVB-S rev 2.6", + [FC_SKY_REV27] = "Sky2PC/SkyStar 2 DVB-S rev 2.7a/u", + [FC_SKY_REV28] = "Sky2PC/SkyStar 2 DVB-S rev 2.8", }; static const char *flexcop_bus_names[] = { -- cgit v1.2.3 From 3beb22a88b25f76e30ddde31f6436ac190b61235 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 22 May 2009 20:07:46 -0400 Subject: lnbp21: Add missing newline From: Andy Walls Reported-by: VDR User Priority: normal Signed-off-by: Andy Walls Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/frontends/lnbp21.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/frontends/lnbp21.c b/linux/drivers/media/dvb/frontends/lnbp21.c index 1dcc56f32..71f607fe8 100644 --- a/linux/drivers/media/dvb/frontends/lnbp21.c +++ b/linux/drivers/media/dvb/frontends/lnbp21.c @@ -133,7 +133,7 @@ static struct dvb_frontend *lnbx2x_attach(struct dvb_frontend *fe, /* override frontend ops */ fe->ops.set_voltage = lnbp21_set_voltage; fe->ops.enable_high_lnb_voltage = lnbp21_enable_high_lnb_voltage; - printk(KERN_INFO "LNBx2x attached on addr=%x", lnbp21->i2c_addr); + printk(KERN_INFO "LNBx2x attached on addr=%x\n", lnbp21->i2c_addr); return fe; } -- cgit v1.2.3 From 47be3ed7254d563ac971323126bfcffc3b712d87 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 22 May 2009 20:12:00 -0400 Subject: ivtv: Add missing newline From: Andy Walls Reported-by: Martin Dauskardt Priority: normal Signed-off-by: Andy Walls Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/ivtv/ivtv-driver.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/ivtv/ivtv-driver.c b/linux/drivers/media/video/ivtv/ivtv-driver.c index edb81a948..9f91838d7 100644 --- a/linux/drivers/media/video/ivtv/ivtv-driver.c +++ b/linux/drivers/media/video/ivtv/ivtv-driver.c @@ -455,7 +455,7 @@ static void ivtv_process_eeprom(struct ivtv *itv) break; } if (tv.tuner_type == TUNER_ABSENT) - IVTV_ERR("tveeprom cannot autodetect tuner!"); + IVTV_ERR("tveeprom cannot autodetect tuner!\n"); if (itv->options.tuner == -1) itv->options.tuner = tv.tuner_type; -- cgit v1.2.3 From 8817e52a9b01c76ac3a33ac34ab4708fe3bf81a4 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 7 Jun 2009 20:39:03 -0400 Subject: tuner-simple, tveeprom: Add Philips FQ1216LME MK3 analog tuner From: Andy Walls Priority: normal Signed-off-by: Andy Walls Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/common/tuners/tuner-simple.c | 51 +++++++++++++----------- linux/drivers/media/common/tuners/tuner-types.c | 29 ++++++++++++++ linux/drivers/media/video/tveeprom.c | 4 +- 3 files changed, 58 insertions(+), 26 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/common/tuners/tuner-simple.c b/linux/drivers/media/common/tuners/tuner-simple.c index 233476df9..ebbc1e045 100644 --- a/linux/drivers/media/common/tuners/tuner-simple.c +++ b/linux/drivers/media/common/tuners/tuner-simple.c @@ -423,6 +423,24 @@ static int simple_std_setup(struct dvb_frontend *fe, return 0; } +static int simple_set_aux_byte(struct dvb_frontend *fe, u8 config, u8 aux) +{ + struct tuner_simple_priv *priv = fe->tuner_priv; + int rc; + u8 buffer[2]; + + buffer[0] = (config & ~0x38) | 0x18; + buffer[1] = aux; + + tuner_dbg("setting aux byte: 0x%02x 0x%02x\n", buffer[0], buffer[1]); + + rc = tuner_i2c_xfer_send(&priv->i2c_props, buffer, 2); + if (2 != rc) + tuner_warn("i2c i/o error: rc == %d (should be 2)\n", rc); + + return rc == 2 ? 0 : rc; +} + static int simple_post_tune(struct dvb_frontend *fe, u8 *buffer, u16 div, u8 config, u8 cb) { @@ -431,30 +449,10 @@ static int simple_post_tune(struct dvb_frontend *fe, u8 *buffer, switch (priv->type) { case TUNER_LG_TDVS_H06XF: - /* Set the Auxiliary Byte. */ -#if 0 - buffer[2] &= ~0x20; - buffer[2] |= 0x18; - buffer[3] = 0x20; - tuner_dbg("tv 0x%02x 0x%02x 0x%02x 0x%02x\n", - buffer[0], buffer[1], buffer[2], buffer[3]); - - rc = tuner_i2c_xfer_send(&priv->i2c_props, buffer, 4); - if (4 != rc) - tuner_warn("i2c i/o error: rc == %d " - "(should be 4)\n", rc); -#else - buffer[0] = buffer[2]; - buffer[0] &= ~0x20; - buffer[0] |= 0x18; - buffer[1] = 0x20; - tuner_dbg("tv 0x%02x 0x%02x\n", buffer[0], buffer[1]); - - rc = tuner_i2c_xfer_send(&priv->i2c_props, buffer, 2); - if (2 != rc) - tuner_warn("i2c i/o error: rc == %d " - "(should be 2)\n", rc); -#endif + simple_set_aux_byte(fe, config, 0x20); + break; + case TUNER_PHILIPS_FQ1216LME_MK3: + simple_set_aux_byte(fe, config, 0x60); /* External AGC */ break; case TUNER_MICROTUNE_4042FI5: { @@ -526,6 +524,11 @@ static int simple_radio_bandswitch(struct dvb_frontend *fe, u8 *buffer) case TUNER_THOMSON_DTT761X: buffer[3] = 0x39; break; + case TUNER_PHILIPS_FQ1216LME_MK3: + tuner_err("This tuner doesn't have FM\n"); + /* Set the low band for sanity, since it covers 88-108 MHz */ + buffer[3] = 0x01; + break; case TUNER_MICROTUNE_4049FM5: default: buffer[3] = 0xa4; diff --git a/linux/drivers/media/common/tuners/tuner-types.c b/linux/drivers/media/common/tuners/tuner-types.c index 43afd30b0..e57d7cb2f 100644 --- a/linux/drivers/media/common/tuners/tuner-types.c +++ b/linux/drivers/media/common/tuners/tuner-types.c @@ -1280,6 +1280,28 @@ static struct tuner_params tuner_tcl_mf02gip_5n_params[] = { }, }; +/* 80-89 */ +/* --------- TUNER_PHILIPS_FQ1216LME_MK3 -- active loopthrough, no FM ------- */ + +static struct tuner_params tuner_fq1216lme_mk3_params[] = { + { + .type = TUNER_PARAM_TYPE_PAL, + .ranges = tuner_fm1216me_mk3_pal_ranges, + .count = ARRAY_SIZE(tuner_fm1216me_mk3_pal_ranges), + .cb_first_if_lower_freq = 1, /* not specified, but safe to do */ + .has_tda9887 = 1, /* TDA9886 */ + .port1_active = 1, + .port2_active = 1, + .port2_invert_for_secam_lc = 1, + .default_top_low = 4, + .default_top_mid = 4, + .default_top_high = 4, + .default_top_secam_low = 4, + .default_top_secam_mid = 4, + .default_top_secam_high = 4, + }, +}; + /* --------------------------------------------------------------------- */ struct tunertype tuners[] = { @@ -1725,6 +1747,13 @@ struct tunertype tuners[] = { .params = tuner_fm1216mk5_params, .count = ARRAY_SIZE(tuner_fm1216mk5_params), }, + + /* 80-89 */ + [TUNER_PHILIPS_FQ1216LME_MK3] = { /* PAL/SECAM, Loop-thru, no FM */ + .name = "Philips FQ1216LME MK3 PAL/SECAM w/active loopthrough", + .params = tuner_fq1216lme_mk3_params, + .count = ARRAY_SIZE(tuner_fq1216lme_mk3_params), + }, }; EXPORT_SYMBOL(tuners); diff --git a/linux/drivers/media/video/tveeprom.c b/linux/drivers/media/video/tveeprom.c index 7d6459dd2..5e3c9f4e2 100644 --- a/linux/drivers/media/video/tveeprom.c +++ b/linux/drivers/media/video/tveeprom.c @@ -185,7 +185,7 @@ hauppauge_tuner[] = { TUNER_ABSENT, "Silicon TDA8275C1 8290 FM"}, { TUNER_ABSENT, "Thompson DTT757"}, /* 80-89 */ - { TUNER_PHILIPS_FM1216ME_MK3, "Philips FQ1216LME MK3"}, + { TUNER_PHILIPS_FQ1216LME_MK3, "Philips FQ1216LME MK3"}, { TUNER_LG_PAL_NEW_TAPC, "LG TAPC G701D"}, { TUNER_LG_NTSC_NEW_TAPC, "LG TAPC H791F"}, { TUNER_LG_PAL_NEW_TAPC, "TCL 2002MB 3"}, @@ -230,7 +230,7 @@ hauppauge_tuner[] = { TUNER_ABSENT, "Samsung THPD5222FG30A"}, /* 120-129 */ { TUNER_XC2028, "Xceive XC3028"}, - { TUNER_ABSENT, "Philips FQ1216LME MK5"}, + { TUNER_PHILIPS_FQ1216LME_MK3, "Philips FQ1216LME MK5"}, { TUNER_ABSENT, "Philips FQD1216LME"}, { TUNER_ABSENT, "Conexant CX24118A"}, { TUNER_ABSENT, "TCL DMF11WIP"}, -- cgit v1.2.3 From 8b4ba9e06fa0f932b664304018ac132019dee4e6 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 25 May 2009 01:22:41 +0000 Subject: Change order for FM tune From: Dmitri Belimov Change order data of buffer in FM simple_tune function. It is usefull for: 1. Set data of tuner with CP bit UP. 0xCE for MK5 or 0xC6 for MK3 2. When call simple_fm_tune, read this byte from config and overwrite this byte in function simple_radio_bandswitch for set CP bit to OFF. Of course it can be usefull for other tuner for overwrite default settings of FM. Signed-off-by: Beholder Intl. Ltd. Dmitry Belimov Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/common/tuners/tuner-simple.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/common/tuners/tuner-simple.c b/linux/drivers/media/common/tuners/tuner-simple.c index ebbc1e045..2ac1c8edb 100644 --- a/linux/drivers/media/common/tuners/tuner-simple.c +++ b/linux/drivers/media/common/tuners/tuner-simple.c @@ -701,12 +701,12 @@ static int simple_set_radio_freq(struct dvb_frontend *fe, return 0; } - /* Bandswitch byte */ - simple_radio_bandswitch(fe, &buffer[0]); - buffer[2] = (t_params->ranges[0].config & ~TUNER_RATIO_MASK) | TUNER_RATIO_SELECT_50; /* 50 kHz step */ + /* Bandswitch byte */ + simple_radio_bandswitch(fe, &buffer[0]); + /* Convert from 1/16 kHz V4L steps to 1/20 MHz (=50 kHz) PLL steps freq * (1 Mhz / 16000 V4L steps) * (20 PLL steps / 1 MHz) = freq * (1/800) */ -- cgit v1.2.3 From a13b9f748066480bddab6794014d6d39217a1ab6 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Mon, 25 May 2009 20:04:22 +0200 Subject: gspca - main: VIDIOC_ENUM_FRAMESIZES ioctl added. From: Hans de Goede Priority: normal Signed-off-by: Hans de Goede Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/gspca.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/gspca.c b/linux/drivers/media/video/gspca/gspca.c index c3c17faa3..3bf8b4866 100644 --- a/linux/drivers/media/video/gspca/gspca.c +++ b/linux/drivers/media/video/gspca/gspca.c @@ -875,6 +875,32 @@ out: return ret; } +static int vidioc_enum_framesizes(struct file *file, void *priv, + struct v4l2_frmsizeenum *fsize) +{ + struct gspca_dev *gspca_dev = priv; + int i; + __u32 index = 0; + + for (i = 0; i < gspca_dev->cam.nmodes; i++) { + if (fsize->pixel_format != + gspca_dev->cam.cam_mode[i].pixelformat) + continue; + + if (fsize->index == index) { + fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE; + fsize->discrete.width = + gspca_dev->cam.cam_mode[i].width; + fsize->discrete.height = + gspca_dev->cam.cam_mode[i].height; + return 0; + } + index++; + } + + return -EINVAL; +} + static void gspca_release(struct video_device *vfd) { struct gspca_dev *gspca_dev = container_of(vfd, struct gspca_dev, vdev); @@ -1870,6 +1896,7 @@ static const struct v4l2_ioctl_ops dev_ioctl_ops = { .vidioc_g_parm = vidioc_g_parm, .vidioc_s_parm = vidioc_s_parm, .vidioc_s_std = vidioc_s_std, + .vidioc_enum_framesizes = vidioc_enum_framesizes, #ifdef CONFIG_VIDEO_V4L1_COMPAT .vidiocgmbuf = vidiocgmbuf, #endif -- cgit v1.2.3 From ba05bd85fc738be7cea87cd0e089c6eff8d34314 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Mon, 25 May 2009 20:20:16 +0200 Subject: gspca - spca561: Change the Rev12a controls. From: Hans de Goede - Extend the gain range - Adjust the exposure - Remove the broken autogain Priority: normal Signed-off-by: Hans de Goede Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/spca561.c | 77 +++++++++++++------------------ 1 file changed, 32 insertions(+), 45 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/spca561.c b/linux/drivers/media/video/gspca/spca561.c index c8dd036a6..047d63d08 100644 --- a/linux/drivers/media/video/gspca/spca561.c +++ b/linux/drivers/media/video/gspca/spca561.c @@ -34,8 +34,8 @@ struct sd { __u16 exposure; /* rev12a only */ #define EXPOSURE_MIN 1 -#define EXPOSURE_DEF 200 -#define EXPOSURE_MAX (4095 - 900) /* see set_exposure */ +#define EXPOSURE_DEF 700 /* == 10 fps */ +#define EXPOSURE_MAX (2047 + 325) /* see setexposure */ __u8 contrast; /* rev72a only */ #define CONTRAST_MIN 0x00 @@ -58,9 +58,9 @@ struct sd { #define AUTOGAIN_MAX 1 __u8 gain; /* rev12a only */ -#define GAIN_MIN 0x0 -#define GAIN_DEF 0x24 -#define GAIN_MAX 0x24 +#define GAIN_MIN 0 +#define GAIN_DEF 63 +#define GAIN_MAX 255 #define EXPO12A_DEF 3 __u8 expo12a; /* expo/gain? for rev 12a */ @@ -580,8 +580,7 @@ static void setcontrast(struct gspca_dev *gspca_dev) static void setexposure(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; - int expo; - int clock_divider; + int i, expo = 0; /* Register 0x8309 controls exposure for the spca561, the basic exposure setting goes from 1-2047, where 1 is completely @@ -595,16 +594,22 @@ static void setexposure(struct gspca_dev *gspca_dev) configure a divider for the base framerate which us used at the exposure setting of 1-300. These bits configure the base framerate according to the following formula: fps = 60 / (value + 2) */ - if (sd->exposure < 2048) { - expo = sd->exposure; - clock_divider = 0; - } else { - /* Add 900 to make the 0 setting of the second part of the - exposure equal to the 2047 setting of the first part. */ - expo = (sd->exposure - 2048) + 900; - clock_divider = 3; + + /* We choose to use the high bits setting the fixed framerate divisor + asap, as setting high basic exposure setting without the fixed + divider in combination with high gains makes the cam stop */ + int table[] = { 0, 450, 550, 625, EXPOSURE_MAX }; + + for (i = 0; i < ARRAY_SIZE(table) - 1; i++) { + if (sd->exposure <= table[i + 1]) { + expo = sd->exposure - table[i]; + if (i) + expo += 300; + expo |= i << 11; + break; + } } - expo |= clock_divider << 11; + gspca_dev->usb_buf[0] = expo; gspca_dev->usb_buf[1] = expo >> 8; reg_w_buf(gspca_dev, 0x8309, 2); @@ -615,7 +620,16 @@ static void setgain(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; - gspca_dev->usb_buf[0] = sd->gain; + /* gain reg low 6 bits 0-63 gain, bit 6 and 7, both double the + sensitivity when set, so 31 + one of them set == 63, and 15 + with both of them set == 63 */ + if (sd->gain < 64) + gspca_dev->usb_buf[0] = sd->gain; + else if (sd->gain < 128) + gspca_dev->usb_buf[0] = (sd->gain / 2) | 0x40; + else + gspca_dev->usb_buf[0] = (sd->gain / 4) | 0xC0; + gspca_dev->usb_buf[1] = 0; reg_w_buf(gspca_dev, 0x8335, 2); } @@ -660,8 +674,7 @@ static int sd_start_12a(struct gspca_dev *gspca_dev) reg_w_buf(gspca_dev, 0x8391, 8); reg_w_buf(gspca_dev, 0x8390, 8); setwhite(gspca_dev); - setautogain(gspca_dev); -/* setgain(gspca_dev); */ + setgain(gspca_dev); setexposure(gspca_dev); return 0; } @@ -793,18 +806,6 @@ static void do_autogain(struct gspca_dev *gspca_dev) i2c_write(gspca_dev, expotimes | pixelclk, 0x09); } break; - case Rev012A: - reg_r(gspca_dev, 0x8330, 2); - if (gspca_dev->usb_buf[1] > 0x08) { - gspca_dev->usb_buf[0] = ++sd->expo12a; - gspca_dev->usb_buf[1] = 0; - reg_w_buf(gspca_dev, 0x8339, 2); - } else if (gspca_dev->usb_buf[1] < 0x02) { - gspca_dev->usb_buf[0] = --sd->expo12a; - gspca_dev->usb_buf[1] = 0; - reg_w_buf(gspca_dev, 0x8339, 2); - } - break; } } @@ -983,19 +984,6 @@ static struct ctrl sd_ctrls_12a[] = { .set = sd_setexposure, .get = sd_getexposure, }, - { - { - .id = V4L2_CID_AUTOGAIN, - .type = V4L2_CTRL_TYPE_BOOLEAN, - .name = "Auto Gain", - .minimum = AUTOGAIN_MIN, - .maximum = AUTOGAIN_MAX, - .step = 1, - .default_value = AUTOGAIN_DEF, - }, - .set = sd_setautogain, - .get = sd_getautogain, - }, { { .id = V4L2_CID_GAIN, @@ -1077,7 +1065,6 @@ static const struct sd_desc sd_desc_12a = { .stopN = sd_stopN, .stop0 = sd_stop0, .pkt_scan = sd_pkt_scan, -/* .dq_callback = do_autogain, * fixme */ }; static const struct sd_desc sd_desc_72a = { .name = MODULE_NAME, -- cgit v1.2.3 From e04d6d72df5f7dfbf9d9355950617c7d3a041ea0 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Mon, 25 May 2009 20:26:59 +0200 Subject: gspca - spca561: Rename the 'White Balance' control to 'Hue'. From: Hans de Goede Priority: normal Signed-off-by: Hans de Goede Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/spca561.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/spca561.c b/linux/drivers/media/video/gspca/spca561.c index 047d63d08..cb3313e19 100644 --- a/linux/drivers/media/video/gspca/spca561.c +++ b/linux/drivers/media/video/gspca/spca561.c @@ -48,9 +48,9 @@ struct sd { #define BRIGHTNESS_MAX 0x3f __u8 white; -#define WHITE_MIN 1 -#define WHITE_DEF 0x40 -#define WHITE_MAX 0x7f +#define HUE_MIN 1 +#define HUE_DEF 0x40 +#define HUE_MAX 0x7f __u8 autogain; #define AUTOGAIN_MIN 0 @@ -492,7 +492,7 @@ static int sd_config(struct gspca_dev *gspca_dev, } sd->brightness = BRIGHTNESS_DEF; sd->contrast = CONTRAST_DEF; - sd->white = WHITE_DEF; + sd->white = HUE_DEF; sd->exposure = EXPOSURE_DEF; sd->autogain = AUTOGAIN_DEF; sd->gain = GAIN_DEF; @@ -960,13 +960,13 @@ static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val) static struct ctrl sd_ctrls_12a[] = { { { - .id = V4L2_CID_DO_WHITE_BALANCE, + .id = V4L2_CID_HUE, .type = V4L2_CTRL_TYPE_INTEGER, - .name = "White Balance", - .minimum = WHITE_MIN, - .maximum = WHITE_MAX, + .name = "Hue", + .minimum = HUE_MIN, + .maximum = HUE_MAX, .step = 1, - .default_value = WHITE_DEF, + .default_value = HUE_DEF, }, .set = sd_setwhite, .get = sd_getwhite, @@ -1002,13 +1002,13 @@ static struct ctrl sd_ctrls_12a[] = { static struct ctrl sd_ctrls_72a[] = { { { - .id = V4L2_CID_DO_WHITE_BALANCE, + .id = V4L2_CID_HUE, .type = V4L2_CTRL_TYPE_INTEGER, - .name = "White Balance", - .minimum = WHITE_MIN, - .maximum = WHITE_MAX, + .name = "Hue", + .minimum = HUE_MIN, + .maximum = HUE_MAX, .step = 1, - .default_value = WHITE_DEF, + .default_value = HUE_DEF, }, .set = sd_setwhite, .get = sd_getwhite, -- cgit v1.2.3 From 9c9fd460173573929daf32f42a502283a9aaae26 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 27 May 2009 15:32:23 -0300 Subject: Building system: Restore compilation with kernels older than 2.6.29 From: Mauro Carvalho Chehab Mostly due to ir-kdb-i2c, but also due to two new drivers, compilation with kernels older than 2.6.29 were broken. This quick and dirty changeset, generated semi-automatically, restaures backport to the subsystem by adding lots of #ifs. It is possible to write a much more small changeset that would restore backport without adding so many ifs, but, due to the lack of time, this will also solve it. Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/siano/smsir.c | 2 + linux/drivers/media/video/bt8xx/bttv-i2c.c | 2 + linux/drivers/media/video/cx231xx/cx231xx-cards.c | 13 ++ linux/drivers/media/video/cx231xx/cx231xx-i2c.c | 2 + linux/drivers/media/video/cx231xx/cx231xx.h | 4 + linux/drivers/media/video/cx23885/cx23885-i2c.c | 2 + linux/drivers/media/video/cx88/cx88-i2c.c | 2 + linux/drivers/media/video/em28xx/em28xx-cards.c | 34 +++ linux/drivers/media/video/em28xx/em28xx-i2c.c | 2 + linux/drivers/media/video/em28xx/em28xx-input.c | 12 ++ linux/drivers/media/video/em28xx/em28xx.h | 2 +- linux/drivers/media/video/ir-kbd-i2c.c | 231 +++++++++++++++++++++ linux/drivers/media/video/ivtv/ivtv-i2c.c | 4 +- .../drivers/media/video/pvrusb2/pvrusb2-i2c-core.c | 2 + linux/drivers/media/video/saa7134/saa7134-i2c.c | 2 + linux/drivers/media/video/saa7134/saa7134-input.c | 99 +++++++++ linux/drivers/media/video/saa7134/saa7134.h | 4 + linux/drivers/media/video/v4l2-device.c | 2 + 18 files changed, 418 insertions(+), 3 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/siano/smsir.c b/linux/drivers/media/dvb/siano/smsir.c index e3d776fee..ac876859c 100644 --- a/linux/drivers/media/dvb/siano/smsir.c +++ b/linux/drivers/media/dvb/siano/smsir.c @@ -274,7 +274,9 @@ int sms_ir_init(struct smscore_device_t *coredev) coredev->ir.ir_kb_type); input_dev->name = coredev->ir.name; input_dev->phys = coredev->ir.name; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 30) input_dev->dev.parent = coredev->device; +#endif /* Key press events only */ input_dev->evbit[0] = BIT_MASK(EV_KEY); diff --git a/linux/drivers/media/video/bt8xx/bttv-i2c.c b/linux/drivers/media/video/bt8xx/bttv-i2c.c index 31f2f07d9..4febaf881 100644 --- a/linux/drivers/media/video/bt8xx/bttv-i2c.c +++ b/linux/drivers/media/video/bt8xx/bttv-i2c.c @@ -405,6 +405,7 @@ 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); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 30) /* Instantiate the IR receiver device, if present */ if (0 == btv->i2c_rc) { @@ -426,6 +427,7 @@ int __devinit init_bttv_i2c(struct bttv *btv) strlcpy(info.type, "ir_video", I2C_NAME_SIZE); i2c_new_probed_device(&btv->c.i2c_adap, &info, addr_list); } +#endif 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 68f92da9e..f388262bd 100644 --- a/linux/drivers/media/video/cx231xx/cx231xx-cards.c +++ b/linux/drivers/media/video/cx231xx/cx231xx-cards.c @@ -282,12 +282,25 @@ static void cx231xx_config_tuner(struct cx231xx *dev) } /* ----------------------------------------------------------------------- */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30) +void cx231xx_set_ir(struct cx231xx *dev, struct IR_i2c *ir) +#else void cx231xx_register_i2c_ir(struct cx231xx *dev) +#endif { +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30) + if (disable_ir) { + ir->get_key = NULL; +#else if (disable_ir) +#endif return; +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30) + } +#else /* REVISIT: instantiate IR device */ +#endif /* 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 e71005c59..4525fab35 100644 --- a/linux/drivers/media/video/cx231xx/cx231xx-i2c.c +++ b/linux/drivers/media/video/cx231xx/cx231xx-i2c.c @@ -511,9 +511,11 @@ int cx231xx_i2c_register(struct cx231xx_i2c *bus) if (0 == bus->i2c_rc) { if (i2c_scan) cx231xx_do_i2c_scan(dev, &bus->i2c_client); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 30) /* Instantiate the IR receiver device, if present */ cx231xx_register_i2c_ir(dev); +#endif } 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 d3c05186e..c436f2b0d 100644 --- a/linux/drivers/media/video/cx231xx/cx231xx.h +++ b/linux/drivers/media/video/cx231xx/cx231xx.h @@ -747,7 +747,11 @@ 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; +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30) +void cx231xx_set_ir(struct cx231xx *dev, struct IR_i2c *ir); +#else void cx231xx_register_i2c_ir(struct cx231xx *dev); +#endif int cx231xx_tuner_callback(void *ptr, int component, int command, int arg); /* Provided by cx231xx-input.c */ diff --git a/linux/drivers/media/video/cx23885/cx23885-i2c.c b/linux/drivers/media/video/cx23885/cx23885-i2c.c index 4369470a3..2e3f3d37c 100644 --- a/linux/drivers/media/video/cx23885/cx23885-i2c.c +++ b/linux/drivers/media/video/cx23885/cx23885-i2c.c @@ -364,6 +364,7 @@ int cx23885_i2c_register(struct cx23885_i2c *bus) printk(KERN_WARNING "%s: i2c bus %d register FAILED\n", dev->name, bus->nr); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 30) /* Instantiate the IR receiver device, if present */ if (0 == bus->i2c_rc) { struct i2c_board_info info; @@ -376,6 +377,7 @@ int cx23885_i2c_register(struct cx23885_i2c *bus) i2c_new_probed_device(&bus->i2c_adap, &info, addr_list); } +#endif 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 dbd629511..b5833aa29 100644 --- a/linux/drivers/media/video/cx88/cx88-i2c.c +++ b/linux/drivers/media/video/cx88/cx88-i2c.c @@ -186,6 +186,7 @@ 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); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 30) /* Instantiate the IR receiver device, if present */ if (0 == core->i2c_rc) { @@ -199,6 +200,7 @@ int cx88_i2c_init(struct cx88_core *core, struct pci_dev *pci) strlcpy(info.type, "ir_video", I2C_NAME_SIZE); i2c_new_probed_device(&core->i2c_adap, &info, addr_list); } +#endif 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 c765d769b..384aead65 100644 --- a/linux/drivers/media/video/em28xx/em28xx-cards.c +++ b/linux/drivers/media/video/em28xx/em28xx-cards.c @@ -1981,8 +1981,18 @@ static int em28xx_hint_board(struct em28xx *dev) } /* ----------------------------------------------------------------------- */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30) +void em28xx_set_ir(struct em28xx *dev, struct IR_i2c *ir) +#else void em28xx_register_i2c_ir(struct em28xx *dev) +#endif { +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30) + if (disable_ir) { + ir->get_key = NULL; + return ; + } +#else struct i2c_board_info info; struct IR_i2c_init_data init_data; const unsigned short addr_list[] = { @@ -1995,6 +2005,7 @@ void em28xx_register_i2c_ir(struct em28xx *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); +#endif /* detect & configure */ switch (dev->model) { @@ -2004,19 +2015,40 @@ void em28xx_register_i2c_ir(struct em28xx *dev) break; case (EM2800_BOARD_TERRATEC_CINERGY_200): case (EM2820_BOARD_TERRATEC_CINERGY_250): +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30) + ir->ir_codes = ir_codes_em_terratec; + ir->get_key = em28xx_get_key_terratec; + snprintf(ir->name, sizeof(ir->name), + "i2c IR (EM28XX Terratec)"); +#else init_data.ir_codes = ir_codes_em_terratec; init_data.get_key = em28xx_get_key_terratec; init_data.name = "i2c IR (EM28XX Terratec)"; +#endif break; case (EM2820_BOARD_PINNACLE_USB_2): +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30) + 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)"); +#else 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)"; +#endif break; case (EM2820_BOARD_HAUPPAUGE_WINTV_USB_2): +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30) + 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)"); +#else init_data.ir_codes = ir_codes_hauppauge_new; init_data.get_key = em28xx_get_key_em_haup; init_data.name = "i2c IR (EM2840 Hauppauge)"; +#endif break; case (EM2820_BOARD_MSI_VOX_USB_2): break; @@ -2027,10 +2059,12 @@ void em28xx_register_i2c_ir(struct em28xx *dev) case (EM2800_BOARD_GRABBEEX_USB2800): break; } +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 30) if (init_data.name) info.platform_data = &init_data; i2c_new_probed_device(&dev->i2c_adap, &info, addr_list); +#endif } 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 fd6be0e2c..1cdd88361 100644 --- a/linux/drivers/media/video/em28xx/em28xx-i2c.c +++ b/linux/drivers/media/video/em28xx/em28xx-i2c.c @@ -559,9 +559,11 @@ int em28xx_i2c_register(struct em28xx *dev) if (i2c_scan) em28xx_do_i2c_scan(dev); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 30) /* Instantiate the IR receiver device, if present */ em28xx_register_i2c_ir(dev); +#endif return 0; } diff --git a/linux/drivers/media/video/em28xx/em28xx-input.c b/linux/drivers/media/video/em28xx/em28xx-input.c index bfe2cb8f6..df58b4c5b 100644 --- a/linux/drivers/media/video/em28xx/em28xx-input.c +++ b/linux/drivers/media/video/em28xx/em28xx-input.c @@ -86,7 +86,11 @@ int em28xx_get_key_terratec(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) unsigned char b; /* poll IR chip */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30) + if (1 != i2c_master_recv(&ir->c, &b, 1)) { +#else if (1 != i2c_master_recv(ir->c, &b, 1)) { +#endif i2cdprintk("read error\n"); return -EIO; } @@ -115,7 +119,11 @@ int em28xx_get_key_em_haup(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) unsigned char code; /* poll IR chip */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30) + if (2 != i2c_master_recv(&ir->c, buf, 2)) +#else if (2 != i2c_master_recv(ir->c, buf, 2)) +#endif return -EIO; /* Does eliminate repeated parity code */ @@ -153,7 +161,11 @@ int em28xx_get_key_pinnacle_usb_grey(struct IR_i2c *ir, u32 *ir_key, /* poll IR chip */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30) + if (3 != i2c_master_recv(&ir->c, buf, 3)) { +#else if (3 != i2c_master_recv(ir->c, buf, 3)) { +#endif 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 e4ddc50c5..1c61b98e6 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 diff --git a/linux/drivers/media/video/ir-kbd-i2c.c b/linux/drivers/media/video/ir-kbd-i2c.c index 0a18d07c7..cdf369129 100644 --- a/linux/drivers/media/video/ir-kbd-i2c.c +++ b/linux/drivers/media/video/ir-kbd-i2c.c @@ -75,7 +75,11 @@ 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 LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30) + if (size != i2c_master_recv(&ir->c,buf,size)) +#else if (size != i2c_master_recv(ir->c, buf, size)) +#endif return -EIO; /* split rc5 data block ... */ @@ -138,7 +142,11 @@ static int get_key_pixelview(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) unsigned char b; /* poll IR chip */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30) + if (1 != i2c_master_recv(&ir->c,&b,1)) { +#else if (1 != i2c_master_recv(ir->c, &b, 1)) { +#endif dprintk(1,"read error\n"); return -EIO; } @@ -152,7 +160,11 @@ static int get_key_pv951(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) unsigned char b; /* poll IR chip */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30) + if (1 != i2c_master_recv(&ir->c,&b,1)) { +#else if (1 != i2c_master_recv(ir->c, &b, 1)) { +#endif dprintk(1,"read error\n"); return -EIO; } @@ -172,7 +184,11 @@ static int get_key_fusionhdtv(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) unsigned char buf[4]; /* poll IR chip */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30) + if (4 != i2c_master_recv(&ir->c,buf,4)) { +#else if (4 != i2c_master_recv(ir->c, buf, 4)) { +#endif dprintk(1,"read error\n"); return -EIO; } @@ -196,7 +212,11 @@ static int get_key_knc1(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) unsigned char b; /* poll IR chip */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30) + if (1 != i2c_master_recv(&ir->c,&b,1)) { +#else if (1 != i2c_master_recv(ir->c, &b, 1)) { +#endif dprintk(1,"read error\n"); return -EIO; } @@ -223,12 +243,24 @@ static int get_key_avermedia_cardbus(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) { unsigned char subaddr, key, keygroup; +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30) + struct i2c_msg msg[] = { { .addr = ir->c.addr, .flags = 0, +#else struct i2c_msg msg[] = { { .addr = ir->c->addr, .flags = 0, +#endif .buf = &subaddr, .len = 1}, +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30) + { .addr = ir->c.addr, .flags = I2C_M_RD, +#else { .addr = ir->c->addr, .flags = I2C_M_RD, +#endif .buf = &key, .len = 1} }; subaddr = 0x0d; +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30) + if (2 != i2c_transfer(ir->c.adapter, msg, 2)) { +#else if (2 != i2c_transfer(ir->c->adapter, msg, 2)) { +#endif dprintk(1, "read error\n"); return -EIO; } @@ -238,7 +270,11 @@ static int get_key_avermedia_cardbus(struct IR_i2c *ir, subaddr = 0x0b; msg[1].buf = &keygroup; +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30) + if (2 != i2c_transfer(ir->c.adapter, msg, 2)) { +#else if (2 != i2c_transfer(ir->c->adapter, msg, 2)) { +#endif dprintk(1, "read error\n"); return -EIO; } @@ -295,7 +331,11 @@ static void ir_work(struct work_struct *work) /* MSI TV@nywhere Plus requires more frequent polling otherwise it will miss some keypresses */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30) + if (ir->c.adapter->id == I2C_HW_SAA7134 && ir->c.addr == 0x30) +#else if (ir->c->adapter->id == I2C_HW_SAA7134 && ir->c->addr == 0x30) +#endif polling_interval = 50; ir_key_poll(ir); @@ -304,15 +344,42 @@ static void ir_work(struct work_struct *work) /* ----------------------------------------------------------------------- */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30) +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 = +{ + .name = "unset", + .driver = &driver + }; + +static int ir_attach(struct i2c_adapter *adap, int addr, + unsigned short flags, int kind) +#else static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) +#endif { IR_KEYTAB_TYPE *ir_codes = NULL; const char *name = NULL; int ir_type; struct IR_i2c *ir; struct input_dev *input_dev; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 30) struct i2c_adapter *adap = client->adapter; unsigned short addr = client->addr; +#endif int err; ir = kzalloc(sizeof(struct IR_i2c),GFP_KERNEL); @@ -324,7 +391,16 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) ir->c = client; ir->input = input_dev; +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30) + + ir->c.adapter = adap; + ir->c.addr = addr; + snprintf(ir->c.name, sizeof(ir->c.name), "ir-kbd"); + + i2c_set_clientdata(&ir->c, ir); +#else i2c_set_clientdata(client, ir); +#endif switch(addr) { case 0x64: @@ -394,6 +470,7 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) goto err_out_free; } +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 30) /* Let the caller override settings */ if (client->dev.platform_data) { const struct IR_i2c_init_data *init_data = @@ -411,14 +488,41 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) err = -ENODEV; goto err_out_free; } +#endif /* Sets name */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30) + snprintf(ir->c.name, sizeof(ir->c.name), "i2c IR (%s)", name); +#else snprintf(ir->name, sizeof(ir->name), "i2c IR (%s)", name); +#endif ir->ir_codes = ir_codes; +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30) + /* 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) */ +#endif snprintf(ir->phys, sizeof(ir->phys), "%s/%s/ir0", +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30) + dev_name(&ir->c.adapter->dev), + dev_name(&ir->c.dev)); +#else dev_name(&adap->dev), dev_name(&client->dev)); +#endif /* init + register input device */ ir_input_init(input_dev, &ir->ir, ir_type, ir->ir_codes); @@ -428,7 +532,11 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) err = input_register_device(ir->input); if (err) +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30) + goto err_out_detach; +#else goto err_out_free; +#endif printk(DEVNAME ": %s detected at %s [%s]\n", ir->input->name, ir->input->phys, adap->name); @@ -443,27 +551,149 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) return 0; +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30) + err_out_detach: + i2c_detach_client(&ir->c); +#endif err_out_free: input_free_device(input_dev); kfree(ir); return err; } +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30) +static int ir_detach(struct i2c_client *client) +#else static int ir_remove(struct i2c_client *client) +#endif { struct IR_i2c *ir = i2c_get_clientdata(client); /* kill outstanding polls */ cancel_delayed_work_sync(&ir->work); +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30) + /* unregister devices */ +#else /* unregister device */ +#endif input_unregister_device(ir->input); +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30) + i2c_detach_client(&ir->c); +#endif /* free memory */ kfree(ir); return 0; } +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30) +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); + } + + return 0; +} +#else static const struct i2c_device_id ir_kbd_id[] = { /* Generic entry for any IR receiver */ { "ir_video", 0 }, @@ -479,6 +709,7 @@ static struct i2c_driver driver = { .remove = ir_remove, .id_table = ir_kbd_id, }; +#endif /* ----------------------------------------------------------------------- */ diff --git a/linux/drivers/media/video/ivtv/ivtv-i2c.c b/linux/drivers/media/video/ivtv/ivtv-i2c.c index 0d18c2220..eed4d2364 100644 --- a/linux/drivers/media/video/ivtv/ivtv-i2c.c +++ b/linux/drivers/media/video/ivtv/ivtv-i2c.c @@ -639,7 +639,7 @@ int init_ivtv_i2c(struct ivtv *itv) retval = i2c_add_adapter(&itv->i2c_adap); else retval = i2c_bit_add_bus(&itv->i2c_adap); - +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 30) /* Instantiate the IR receiver device, if present */ if (retval == 0) { struct i2c_board_info info; @@ -665,7 +665,7 @@ int init_ivtv_i2c(struct ivtv *itv) strlcpy(info.type, "ir_video", I2C_NAME_SIZE); i2c_new_probed_device(&itv->i2c_adap, &info, addr_list); } - +#endif return retval; } diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c b/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c index 694e51f58..24644fc96 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c @@ -651,6 +651,7 @@ static void do_i2c_scan(struct pvr2_hdw *hdw) static void pvr2_i2c_register_ir(struct pvr2_hdw *hdw) { +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 30) struct i2c_board_info info; unsigned char addr = 0; if (pvr2_disable_ir_video) { @@ -672,6 +673,7 @@ static void pvr2_i2c_register_ir(struct pvr2_hdw *hdw) strlcpy(info.type, "ir_video", I2C_NAME_SIZE); info.addr = addr; i2c_new_device(&hdw->i2c_adap, &info); +#endif } void pvr2_i2c_core_init(struct pvr2_hdw *hdw) diff --git a/linux/drivers/media/video/saa7134/saa7134-i2c.c b/linux/drivers/media/video/saa7134/saa7134-i2c.c index a8185693f..f6cf7c1be 100644 --- a/linux/drivers/media/video/saa7134/saa7134-i2c.c +++ b/linux/drivers/media/video/saa7134/saa7134-i2c.c @@ -416,9 +416,11 @@ 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); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 30) /* Instantiate the IR receiver device, if present */ saa7134_probe_i2c_ir(dev); +#endif return 0; } diff --git a/linux/drivers/media/video/saa7134/saa7134-input.c b/linux/drivers/media/video/saa7134/saa7134-input.c index 36913d22b..b54bfd645 100644 --- a/linux/drivers/media/video/saa7134/saa7134-input.c +++ b/linux/drivers/media/video/saa7134/saa7134-input.c @@ -59,8 +59,13 @@ 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) +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30) +#define i2cdprintk(fmt, arg...) if (ir_debug) \ + printk(KERN_DEBUG "%s/ir: " fmt, ir->c.name , ## arg) +#else #define i2cdprintk(fmt, arg...) if (ir_debug) \ printk(KERN_DEBUG "%s/ir: " fmt, ir->name , ## arg) +#endif /* Helper functions for RC5 and NEC decoding at GPIO16 or GPIO18 */ static int saa7134_rc5_irq(struct saa7134_dev *dev); @@ -134,10 +139,18 @@ 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. */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30) + struct saa7134_dev *dev = ir->c.adapter->algo_data; +#else struct saa7134_dev *dev = ir->c->adapter->algo_data; +#endif if (dev == NULL) { dprintk("get_key_msi_tvanywhere_plus: " +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30) + "gir->c.adapter->algo_data is NULL!\n"); +#else "gir->c->adapter->algo_data is NULL!\n"); +#endif return -EIO; } @@ -156,7 +169,11 @@ static int get_key_msi_tvanywhere_plus(struct IR_i2c *ir, u32 *ir_key, /* GPIO says there is a button press. Get it. */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30) + if (1 != i2c_master_recv(&ir->c, &b, 1)) { +#else if (1 != i2c_master_recv(ir->c, &b, 1)) { +#endif i2cdprintk("read error\n"); return -EIO; } @@ -179,7 +196,11 @@ static int get_key_purpletv(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) unsigned char b; /* poll IR chip */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30) + if (1 != i2c_master_recv(&ir->c,&b,1)) { +#else if (1 != i2c_master_recv(ir->c, &b, 1)) { +#endif i2cdprintk("read error\n"); return -EIO; } @@ -202,7 +223,11 @@ 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 LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30) + if (5 != i2c_master_recv(&ir->c,buf,5)) +#else if (5 != i2c_master_recv(ir->c, buf, 5)) +#endif return -EIO; cod4 = buf[4]; @@ -224,7 +249,11 @@ static int get_key_beholdm6xx(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) unsigned char data[12]; u32 gpio; +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30) + struct saa7134_dev *dev = ir->c.adapter->algo_data; +#else struct saa7134_dev *dev = ir->c->adapter->algo_data; +#endif /* rising SAA7134_GPIO_GPRESCAN reads the status */ saa_clearb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN); @@ -235,9 +264,17 @@ static int get_key_beholdm6xx(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) if (0x400000 & ~gpio) return 0; /* No button press */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30) + ir->c.addr = 0x5a >> 1; +#else ir->c->addr = 0x5a >> 1; +#endif +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30) + if (12 != i2c_master_recv(&ir->c, data, 12)) { +#else if (12 != i2c_master_recv(ir->c, data, 12)) { +#endif i2cdprintk("read error\n"); return -EIO; } @@ -267,7 +304,11 @@ 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 LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30) + if (4 != i2c_master_recv(&ir->c, b, 4)) { +#else if (4 != i2c_master_recv(ir->c, b, 4)) { +#endif i2cdprintk("read error\n"); return -EIO; } @@ -686,8 +727,13 @@ void saa7134_input_fini(struct saa7134_dev *dev) dev->remote = NULL; } +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30) +void saa7134_set_i2c_ir(struct saa7134_dev *dev, struct IR_i2c *ir) +#else void saa7134_probe_i2c_ir(struct saa7134_dev *dev) +#endif { +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 30) struct i2c_board_info info; struct IR_i2c_init_data init_data; const unsigned short addr_list[] = { @@ -704,33 +750,66 @@ void saa7134_probe_i2c_ir(struct saa7134_dev *dev) int rc; +#endif if (disable_ir) { +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30) + dprintk("Found supported i2c remote, but IR has been disabled\n"); + ir->get_key=NULL; +#else dprintk("IR has been disabled, not probing for i2c remote\n"); +#endif return; } +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 30) 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); +#endif switch (dev->board) { case SAA7134_BOARD_PINNACLE_PCTV_110i: case SAA7134_BOARD_PINNACLE_PCTV_310i: +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30) + snprintf(ir->c.name, sizeof(ir->c.name), "Pinnacle PCTV"); +#else init_data.name = "Pinnacle PCTV"; +#endif if (pinnacle_remote == 0) { +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30) + ir->get_key = get_key_pinnacle_color; + ir->ir_codes = ir_codes_pinnacle_color; +#else init_data.get_key = get_key_pinnacle_color; init_data.ir_codes = ir_codes_pinnacle_color; +#endif } else { +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30) + ir->get_key = get_key_pinnacle_grey; + ir->ir_codes = ir_codes_pinnacle_grey; +#else init_data.get_key = get_key_pinnacle_grey; init_data.ir_codes = ir_codes_pinnacle_grey; +#endif } break; case SAA7134_BOARD_UPMOST_PURPLE_TV: +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30) + snprintf(ir->c.name, sizeof(ir->c.name), "Purple TV"); + ir->get_key = get_key_purpletv; + ir->ir_codes = ir_codes_purpletv; +#else init_data.name = "Purple TV"; init_data.get_key = get_key_purpletv; init_data.ir_codes = ir_codes_purpletv; +#endif break; case SAA7134_BOARD_MSI_TVATANYWHERE_PLUS: +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30) + snprintf(ir->c.name, sizeof(ir->c.name), "MSI TV@nywhere Plus"); + ir->get_key = get_key_msi_tvanywhere_plus; + ir->ir_codes = ir_codes_msi_tvanywhere_plus; +#else 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; @@ -743,11 +822,18 @@ void saa7134_probe_i2c_ir(struct saa7134_dev *dev) dprintk(KERN_DEBUG "probe 0x%02x @ %s: %s\n", msg_msi.addr, dev->i2c_adap.name, (1 == rc) ? "yes" : "no"); +#endif break; case SAA7134_BOARD_HAUPPAUGE_HVR1110: +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30) + snprintf(ir->c.name, sizeof(ir->c.name), "HVR 1110"); + ir->get_key = get_key_hvr1110; + ir->ir_codes = ir_codes_hauppauge_new; +#else init_data.name = "HVR 1110"; init_data.get_key = get_key_hvr1110; init_data.ir_codes = ir_codes_hauppauge_new; +#endif break; case SAA7134_BOARD_BEHOLD_607FM_MK3: case SAA7134_BOARD_BEHOLD_607FM_MK5: @@ -761,16 +847,28 @@ void saa7134_probe_i2c_ir(struct saa7134_dev *dev) case SAA7134_BOARD_BEHOLD_M63: case SAA7134_BOARD_BEHOLD_M6_EXTRA: case SAA7134_BOARD_BEHOLD_H6: +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30) + snprintf(ir->c.name, sizeof(ir->c.name), "BeholdTV"); + ir->get_key = get_key_beholdm6xx; + ir->ir_codes = ir_codes_behold; +#else init_data.name = "BeholdTV"; init_data.get_key = get_key_beholdm6xx; init_data.ir_codes = ir_codes_behold; +#endif break; +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30) + default: + dprintk("Shouldn't get here: Unknown board %x for I2C IR?\n",dev->board); +#else case SAA7134_BOARD_AVERMEDIA_CARDBUS_501: case SAA7134_BOARD_AVERMEDIA_CARDBUS_506: info.addr = 0x40; +#endif break; } +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 30) if (init_data.name) info.platform_data = &init_data; /* No need to probe if address is known */ @@ -781,6 +879,7 @@ void saa7134_probe_i2c_ir(struct saa7134_dev *dev) /* Address not known, fallback to probing */ i2c_new_probed_device(&dev->i2c_adap, &info, addr_list); +#endif } 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 be6763dde..385bc26bd 100644 --- a/linux/drivers/media/video/saa7134/saa7134.h +++ b/linux/drivers/media/video/saa7134/saa7134.h @@ -804,7 +804,11 @@ 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); +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30) +void saa7134_set_i2c_ir(struct saa7134_dev *dev, struct IR_i2c *ir); +#else void saa7134_probe_i2c_ir(struct saa7134_dev *dev); +#endif void saa7134_ir_start(struct saa7134_dev *dev, struct card_ir *ir); void saa7134_ir_stop(struct saa7134_dev *dev); diff --git a/linux/drivers/media/video/v4l2-device.c b/linux/drivers/media/video/v4l2-device.c index b962862fe..18d404499 100644 --- a/linux/drivers/media/video/v4l2-device.c +++ b/linux/drivers/media/video/v4l2-device.c @@ -87,6 +87,7 @@ void v4l2_device_unregister(struct v4l2_device *v4l2_dev) list_for_each_entry_safe(sd, next, &v4l2_dev->subdevs, list) { v4l2_device_unregister_subdev(sd); #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29) if (sd->flags & V4L2_SUBDEV_FL_IS_I2C) { struct i2c_client *client = v4l2_get_subdevdata(sd); @@ -97,6 +98,7 @@ void v4l2_device_unregister(struct v4l2_device *v4l2_dev) if (client) i2c_unregister_device(client); } +#endif #endif } } -- cgit v1.2.3 From 96768446c3bdd84dffc002636e39a0aa3708d9df Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 10 Jun 2009 11:58:22 -0300 Subject: Fix v4l2-device usage of i2c_unregister_device() From: Randy Dunlap Fix v4l2-device usage of i2c_unregister_device() and handle the case of CONFIG_I2C=m & CONFIG_MEDIA_VIDEO=y. Signed-off-by: Randy Dunlap Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/v4l2-device.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/v4l2-device.c b/linux/drivers/media/video/v4l2-device.c index 18d404499..4fa93189d 100644 --- a/linux/drivers/media/video/v4l2-device.c +++ b/linux/drivers/media/video/v4l2-device.c @@ -86,7 +86,7 @@ void v4l2_device_unregister(struct v4l2_device *v4l2_dev) /* Unregister subdevs */ list_for_each_entry_safe(sd, next, &v4l2_dev->subdevs, list) { v4l2_device_unregister_subdev(sd); -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) +#if defined(CONFIG_I2C) || (defined(CONFIG_I2C_MODULE) && defined(MODULE)) #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29) if (sd->flags & V4L2_SUBDEV_FL_IS_I2C) { struct i2c_client *client = v4l2_get_subdevdata(sd); -- cgit v1.2.3 From 82e50d5ad9d80f0a346a46ec6363a72a9b6d9aa7 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 28 May 2009 01:10:43 +0000 Subject: vino: replace dma_sync_single with dma_sync_single_for_cpu From: FUJITA Tomonori This replaces dma_sync_single() with dma_sync_single_for_cpu() because dma_sync_single() is an obsolete API; include/linux/dma-mapping.h says: /* Backwards compat, remove in 2.7.x */ Signed-off-by: FUJITA Tomonori Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/vino.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/vino.c b/linux/drivers/media/video/vino.c index 808d9434d..7c39b43ee 100644 --- a/linux/drivers/media/video/vino.c +++ b/linux/drivers/media/video/vino.c @@ -868,9 +868,9 @@ static void vino_sync_buffer(struct vino_framebuffer *fb) dprintk("vino_sync_buffer():\n"); for (i = 0; i < fb->desc_table.page_count; i++) - dma_sync_single(NULL, - fb->desc_table.dma_cpu[VINO_PAGE_RATIO * i], - PAGE_SIZE, DMA_FROM_DEVICE); + dma_sync_single_for_cpu(NULL, + fb->desc_table.dma_cpu[VINO_PAGE_RATIO * i], + PAGE_SIZE, DMA_FROM_DEVICE); } /* Framebuffer fifo functions (need to be locked externally) */ -- cgit v1.2.3 From 0ee8ab67793906ca35ec917d37e53f82a68ef59e Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Wed, 27 May 2009 22:23:37 -0400 Subject: em28xx: Don't let device work unless connected to a high speed USB port From: Devin Heitmueller The em28xx basically just doesn't work at 12 Mbps. The isoc pipe needs nearly 200 Mbps for analog support, so users would see garbage video, and on the DVB/ATSC side scanning is likely to work but if the user tried to tune it would certainly appear to have failed. It's better to fail explicity up front and tell the user to plug into a USB 2.0 port, than to let the driver load and the user have weird problems with tuning and garbage video. Priority: normal Signed-off-by: Devin Heitmueller --- linux/drivers/media/video/em28xx/em28xx-cards.c | 14 ++++++++++++++ 1 file changed, 14 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 384aead65..9c092f842 100644 --- a/linux/drivers/media/video/em28xx/em28xx-cards.c +++ b/linux/drivers/media/video/em28xx/em28xx-cards.c @@ -2482,6 +2482,20 @@ static int em28xx_usb_probe(struct usb_interface *interface, ifnum, interface->altsetting->desc.bInterfaceNumber); + /* + * Make sure we have 480 Mbps of bandwidth, otherwise things like + * video stream wouldn't likely work, since 12 Mbps is generally + * not enough even for most Digital TV streams. + */ + if (udev->speed != USB_SPEED_HIGH) { + printk(DRIVER_NAME ": Device initialization failed.\n"); + printk(DRIVER_NAME ": Device must be connected to a high-speed" + " USB 2.0 port.\n"); + em28xx_devused &= ~(1<= EM28XX_MAXBOARDS) { printk(DRIVER_NAME ": Supports only %i em28xx boards.\n", EM28XX_MAXBOARDS); -- cgit v1.2.3 From 7e58cab3858aad1f493903e63dab1b90bdcc9f27 Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Wed, 27 May 2009 22:25:36 -0400 Subject: au0828: Don't let device work unless connected to a high speed USB port From: Devin Heitmueller The au0828 basically just doesn't work at 12 Mbps. The isoc pipe needs nearly 200 Mbps for analog support, so users would see garbage video, and on the DVB/ATSC side scanning is likely to work but if the user tried to tune it would certainly appear to have failed. It's better to fail explicity up front and tell the user to plug into a USB 2.0 port, than to let the driver load and the user have weird problems with tuning and garbage video. Priority: normal Signed-off-by: Devin Heitmueller --- linux/drivers/media/video/au0828/au0828-core.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/au0828/au0828-core.c b/linux/drivers/media/video/au0828/au0828-core.c index 4da5b7909..d52d66bfd 100644 --- a/linux/drivers/media/video/au0828/au0828-core.c +++ b/linux/drivers/media/video/au0828/au0828-core.c @@ -182,6 +182,18 @@ static int au0828_usb_probe(struct usb_interface *interface, le16_to_cpu(usbdev->descriptor.idProduct), ifnum); + /* + * Make sure we have 480 Mbps of bandwidth, otherwise things like + * video stream wouldn't likely work, since 12 Mbps is generally + * not enough even for most Digital TV streams. + */ + if (usbdev->speed != USB_SPEED_HIGH) { + printk(KERN_ERR "au0828: Device initialization failed.\n"); + printk(KERN_ERR "au0828: Device must be connected to a " + "high-speed USB 2.0 port.\n"); + return -ENODEV; + } + dev = kzalloc(sizeof(*dev), GFP_KERNEL); if (dev == NULL) { printk(KERN_ERR "%s() Unable to allocate memory\n", __func__); -- cgit v1.2.3 From 54bb45ac67bf8460b3cf7d6ed232a987b3697dcf Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Wed, 27 May 2009 22:27:26 -0400 Subject: em28xx: Add support for the K-World 2800d From: Devin Heitmueller Make the KWorld 2800d work properly. In this case, that means making the profile more generic so that it works for both the Pointnix Intra-Oral USB camera and the KWorld device. The device provides the audio through a pass-thru cable, so we don't need an actual audio capture profile (neither the K-World device nor the Pointnix have an onboard audio decoder). Thanks to Paul Thomas for providing sample hardware. Priority: normal Signed-off-by: Devin Heitmueller Cc: Paul Thomas --- linux/drivers/media/video/em28xx/em28xx-cards.c | 11 ++++++----- linux/drivers/media/video/em28xx/em28xx.h | 4 ++-- 2 files changed, 8 insertions(+), 7 deletions(-) (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 9c092f842..6db3474c2 100644 --- a/linux/drivers/media/video/em28xx/em28xx-cards.c +++ b/linux/drivers/media/video/em28xx/em28xx-cards.c @@ -1043,16 +1043,17 @@ struct em28xx_board em28xx_boards[] = { .amux = EM28XX_AMUX_LINE_IN, } }, }, - [EM2860_BOARD_POINTNIX_INTRAORAL_CAMERA] = { - .name = "PointNix Intra-Oral Camera", + [EM2860_BOARD_SAA711X_REFERENCE_DESIGN] = { + .name = "EM2860/SAA711X Reference Design", .has_snapshot_button = 1, - .tda9887_conf = TDA9887_PRESENT, .tuner_type = TUNER_ABSENT, .decoder = EM28XX_SAA711X, .input = { { .type = EM28XX_VMUX_SVIDEO, .vmux = SAA7115_SVIDEO3, - .amux = EM28XX_AMUX_VIDEO, + }, { + .type = EM28XX_VMUX_COMPOSITE1, + .vmux = SAA7115_COMPOSITE0, } }, }, [EM2880_BOARD_MSI_DIGIVOX_AD] = { @@ -1588,7 +1589,7 @@ static struct em28xx_hash_table em28xx_eeprom_hash[] = { static struct em28xx_hash_table em28xx_i2c_hash[] = { {0xb06a32c3, EM2800_BOARD_TERRATEC_CINERGY_200, TUNER_LG_PAL_NEW_TAPC}, {0xf51200e3, EM2800_BOARD_VGEAR_POCKETTV, TUNER_LG_PAL_NEW_TAPC}, - {0x1ba50080, EM2860_BOARD_POINTNIX_INTRAORAL_CAMERA, TUNER_ABSENT}, + {0x1ba50080, EM2860_BOARD_SAA711X_REFERENCE_DESIGN, TUNER_ABSENT}, {0xc51200e3, EM2820_BOARD_GADMEI_TVR200, TUNER_LG_PAL_NEW_TAPC}, }; diff --git a/linux/drivers/media/video/em28xx/em28xx.h b/linux/drivers/media/video/em28xx/em28xx.h index 1c61b98e6..db07d92f6 100644 --- a/linux/drivers/media/video/em28xx/em28xx.h +++ b/linux/drivers/media/video/em28xx/em28xx.h @@ -59,7 +59,7 @@ #define EM2883_BOARD_HAUPPAUGE_WINTV_HVR_950 16 #define EM2880_BOARD_PINNACLE_PCTV_HD_PRO 17 #define EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900_R2 18 -#define EM2860_BOARD_POINTNIX_INTRAORAL_CAMERA 19 +#define EM2860_BOARD_SAA711X_REFERENCE_DESIGN 19 #define EM2880_BOARD_AMD_ATI_TV_WONDER_HD_600 20 #define EM2800_BOARD_GRABBEEX_USB2800 21 #define EM2750_BOARD_UNKNOWN 22 @@ -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 -- cgit v1.2.3 From f12529f2224df7595de7e73f6b717ef125124f5e Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Wed, 27 May 2009 22:28:46 -0400 Subject: tuner-core: fix warning introduced when cleaning up xc5000 init routine From: Devin Heitmueller This patch removes some remaining dead code. Warning showed up in Hans Verkuil's daily report after I committed hg changeset 7f2eea75118b. Thanks to Michael Krufky for bringing the warning to my attention. Priority: normal Signed-off-by: Devin Heitmueller Cc: Michael Krufky --- linux/drivers/media/video/tuner-core.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/tuner-core.c b/linux/drivers/media/video/tuner-core.c index cb715f143..85b133df4 100644 --- a/linux/drivers/media/video/tuner-core.c +++ b/linux/drivers/media/video/tuner-core.c @@ -426,8 +426,6 @@ static void set_type(struct i2c_client *c, unsigned int type, break; case TUNER_XC5000: { - struct dvb_tuner_ops *xc_tuner_ops; - xc5000_cfg.i2c_address = t->i2c->addr; /* if_khz will be set when the digital dvb_attach() occurs */ xc5000_cfg.if_khz = 0; -- cgit v1.2.3 From 12c818b1959a2b8e5c0575df85ff2957c01e93df Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Wed, 27 May 2009 22:44:10 -0400 Subject: em28xx: provide module option to disable USB speed check From: Devin Heitmueller Add an em28xx module option that allows a user to override the USB speed check. Intended for advanced users who understand the consequences of trying to use the device with a 12Mbps bus. Priority: normal Signed-off-by: Devin Heitmueller --- linux/drivers/media/video/em28xx/em28xx-cards.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (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 6db3474c2..5b89c1821 100644 --- a/linux/drivers/media/video/em28xx/em28xx-cards.c +++ b/linux/drivers/media/video/em28xx/em28xx-cards.c @@ -50,6 +50,11 @@ static unsigned int disable_ir; module_param(disable_ir, int, 0444); MODULE_PARM_DESC(disable_ir, "disable infrared remote support"); +static unsigned int disable_usb_speed_check; +module_param(disable_usb_speed_check, int, 0444); +MODULE_PARM_DESC(disable_usb_speed_check, + "override min bandwidth requirement of 480M bps"); + static unsigned int card[] = {[0 ... (EM28XX_MAXBOARDS - 1)] = UNSET }; module_param_array(card, int, NULL, 0444); MODULE_PARM_DESC(card, "card type"); @@ -2488,7 +2493,7 @@ static int em28xx_usb_probe(struct usb_interface *interface, * video stream wouldn't likely work, since 12 Mbps is generally * not enough even for most Digital TV streams. */ - if (udev->speed != USB_SPEED_HIGH) { + if (udev->speed != USB_SPEED_HIGH && disable_usb_speed_check == 0) { printk(DRIVER_NAME ": Device initialization failed.\n"); printk(DRIVER_NAME ": Device must be connected to a high-speed" " USB 2.0 port.\n"); -- cgit v1.2.3 From ab62c90c3f2b6debe4c45c66aa08b5a65039e40e Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Wed, 27 May 2009 22:46:17 -0400 Subject: au0828: provide module option to disable USB speed check From: Devin Heitmueller Add an au0828 module option that allows a user to override the USB speed check. Intended for advanced users who understand the consequences of trying to use the device with a 12Mbps bus. Priority: normal Signed-off-by: Devin Heitmueller --- linux/drivers/media/video/au0828/au0828-core.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/au0828/au0828-core.c b/linux/drivers/media/video/au0828/au0828-core.c index d52d66bfd..0e2f0eb1a 100644 --- a/linux/drivers/media/video/au0828/au0828-core.c +++ b/linux/drivers/media/video/au0828/au0828-core.c @@ -37,6 +37,11 @@ int au0828_debug; module_param_named(debug, au0828_debug, int, 0644); MODULE_PARM_DESC(debug, "enable debug messages"); +static unsigned int disable_usb_speed_check; +module_param(disable_usb_speed_check, int, 0444); +MODULE_PARM_DESC(disable_usb_speed_check, + "override min bandwidth requirement of 480M bps"); + #define _AU0828_BULKPIPE 0x03 #define _BULKPIPESIZE 0xffff @@ -187,7 +192,7 @@ static int au0828_usb_probe(struct usb_interface *interface, * video stream wouldn't likely work, since 12 Mbps is generally * not enough even for most Digital TV streams. */ - if (usbdev->speed != USB_SPEED_HIGH) { + if (usbdev->speed != USB_SPEED_HIGH && disable_usb_speed_check == 0) { printk(KERN_ERR "au0828: Device initialization failed.\n"); printk(KERN_ERR "au0828: Device must be connected to a " "high-speed USB 2.0 port.\n"); -- cgit v1.2.3 From 3ae45ce9d9bfb75dec4a17b5ca17f5086e0185e0 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 28 May 2009 04:58:57 +0000 Subject: big rework of TS for saa7134 From: Dmitri Belimov 1. Add start/stop TS function. 2. Move setup DMA of TS to DMA function. 3. Write support cupture via MMAP 4. Rework startup and finish process, remove simple FSM. Signed-off-by: Beholder Intl. Ltd. Dmitry Belimov Signed-off-by: Alexey Osipov Tested-by: Hermann Pitton Tested-by: Beholder Intl. Ltd. Dmitry Belimov Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/saa7134/saa7134-cards.c | 2 + linux/drivers/media/video/saa7134/saa7134-core.c | 17 +++ .../drivers/media/video/saa7134/saa7134-empress.c | 11 ++ linux/drivers/media/video/saa7134/saa7134-ts.c | 120 +++++++++++---------- linux/drivers/media/video/saa7134/saa7134.h | 12 +-- 5 files changed, 100 insertions(+), 62 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/saa7134/saa7134-cards.c b/linux/drivers/media/video/saa7134/saa7134-cards.c index 587209fdd..064fb86bc 100644 --- a/linux/drivers/media/video/saa7134/saa7134-cards.c +++ b/linux/drivers/media/video/saa7134/saa7134-cards.c @@ -4497,6 +4497,7 @@ struct saa7134_board saa7134_boards[] = { /* Igor Kuznetsov */ /* Andrey Melnikoff */ /* Beholder Intl. Ltd. Dmitry Belimov */ + /* Alexey Osipov */ .name = "Beholder BeholdTV M6", .audio_clock = 0x00187de7, .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, @@ -4571,6 +4572,7 @@ struct saa7134_board saa7134_boards[] = { /* Igor Kuznetsov */ /* Andrey Melnikoff */ /* Beholder Intl. Ltd. Dmitry Belimov */ + /* Alexey Osipov */ .name = "Beholder BeholdTV M6 Extra", .audio_clock = 0x00187de7, .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, /* FIXME to MK5 */ diff --git a/linux/drivers/media/video/saa7134/saa7134-core.c b/linux/drivers/media/video/saa7134/saa7134-core.c index dc692d7a7..da73430ad 100644 --- a/linux/drivers/media/video/saa7134/saa7134-core.c +++ b/linux/drivers/media/video/saa7134/saa7134-core.c @@ -380,6 +380,10 @@ void saa7134_buffer_next(struct saa7134_dev *dev, dprintk("buffer_next %p\n",NULL); saa7134_set_dmabits(dev); del_timer(&q->timeout); + + if (card_has_mpeg(dev)) + if (dev->ts_started) + saa7134_ts_stop(dev); } } @@ -465,6 +469,19 @@ int saa7134_set_dmabits(struct saa7134_dev *dev) ctrl |= SAA7134_MAIN_CTRL_TE5; irq |= SAA7134_IRQ1_INTE_RA2_1 | SAA7134_IRQ1_INTE_RA2_0; + + /* dma: setup channel 5 (= TS) */ + + saa_writeb(SAA7134_TS_DMA0, (dev->ts.nr_packets - 1) & 0xff); + saa_writeb(SAA7134_TS_DMA1, + ((dev->ts.nr_packets - 1) >> 8) & 0xff); + /* TSNOPIT=0, TSCOLAP=0 */ + saa_writeb(SAA7134_TS_DMA2, + (((dev->ts.nr_packets - 1) >> 16) & 0x3f) | 0x00); + saa_writel(SAA7134_RS_PITCH(5), TS_PACKET_SIZE); + saa_writel(SAA7134_RS_CONTROL(5), SAA7134_RS_CONTROL_BURST_16 | + SAA7134_RS_CONTROL_ME | + (dev->ts.pt_ts.dma >> 12)); } /* set task conditions + field handling */ diff --git a/linux/drivers/media/video/saa7134/saa7134-empress.c b/linux/drivers/media/video/saa7134/saa7134-empress.c index dd22a5215..96334a20b 100644 --- a/linux/drivers/media/video/saa7134/saa7134-empress.c +++ b/linux/drivers/media/video/saa7134/saa7134-empress.c @@ -255,6 +255,16 @@ static int empress_s_fmt_vid_cap(struct file *file, void *priv, return 0; } +static int empress_try_fmt_vid_cap(struct file *file, void *priv, + struct v4l2_format *f) +{ + struct saa7134_dev *dev = file->private_data; + + f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG; + f->fmt.pix.sizeimage = TS_PACKET_SIZE * dev->ts.nr_packets; + + return 0; +} static int empress_reqbufs(struct file *file, void *priv, struct v4l2_requestbuffers *p) @@ -450,6 +460,7 @@ static const struct v4l2_file_operations ts_fops = static const struct v4l2_ioctl_ops ts_ioctl_ops = { .vidioc_querycap = empress_querycap, .vidioc_enum_fmt_vid_cap = empress_enum_fmt_vid_cap, + .vidioc_try_fmt_vid_cap = empress_try_fmt_vid_cap, .vidioc_s_fmt_vid_cap = empress_s_fmt_vid_cap, .vidioc_g_fmt_vid_cap = empress_g_fmt_vid_cap, .vidioc_reqbufs = empress_reqbufs, diff --git a/linux/drivers/media/video/saa7134/saa7134-ts.c b/linux/drivers/media/video/saa7134/saa7134-ts.c index b8ff459d0..3fa652279 100644 --- a/linux/drivers/media/video/saa7134/saa7134-ts.c +++ b/linux/drivers/media/video/saa7134/saa7134-ts.c @@ -67,33 +67,8 @@ static int buffer_activate(struct saa7134_dev *dev, mod_timer(&dev->ts_q.timeout, jiffies+TS_BUFFER_TIMEOUT); - if (dev->ts_state == SAA7134_TS_BUFF_DONE) { - /* Clear TS cache */ - dev->buff_cnt = 0; - saa_writeb(SAA7134_TS_SERIAL1, 0x00); - saa_writeb(SAA7134_TS_SERIAL1, 0x03); - saa_writeb(SAA7134_TS_SERIAL1, 0x00); - saa_writeb(SAA7134_TS_SERIAL1, 0x01); - - /* TS clock non-inverted */ - saa_writeb(SAA7134_TS_SERIAL1, 0x00); - - /* Start TS stream */ - switch (saa7134_boards[dev->board].ts_type) { - case SAA7134_MPEG_TS_PARALLEL: - saa_writeb(SAA7134_TS_SERIAL0, 0x40); - saa_writeb(SAA7134_TS_PARALLEL, 0xec); - break; - case SAA7134_MPEG_TS_SERIAL: - saa_writeb(SAA7134_TS_SERIAL0, 0xd8); - saa_writeb(SAA7134_TS_PARALLEL, 0x6c); - saa_writeb(SAA7134_TS_PARALLEL_SERIAL, 0xbc); - saa_writeb(SAA7134_TS_SERIAL1, 0x02); - break; - } - - dev->ts_state = SAA7134_TS_STARTED; - } + if (!dev->ts_started) + saa7134_ts_start(dev); return 0; } @@ -104,7 +79,6 @@ static int buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb, struct saa7134_dev *dev = q->priv_data; struct saa7134_buf *buf = container_of(vb,struct saa7134_buf,vb); unsigned int lines, llength, size; - u32 control; int err; dprintk("buffer_prepare [%p,%s]\n",buf,v4l2_field_names[field]); @@ -121,8 +95,11 @@ static int buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb, } if (VIDEOBUF_NEEDS_INIT == buf->vb.state) { + struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb); + dprintk("buffer_prepare: needs_init\n"); + buf->vb.width = llength; buf->vb.height = lines; buf->vb.size = size; @@ -139,23 +116,6 @@ static int buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb, goto oops; } - dev->buff_cnt++; - - if (dev->buff_cnt == dev->ts.nr_bufs) { - dev->ts_state = SAA7134_TS_BUFF_DONE; - /* dma: setup channel 5 (= TS) */ - control = SAA7134_RS_CONTROL_BURST_16 | - SAA7134_RS_CONTROL_ME | - (buf->pt->dma >> 12); - - saa_writeb(SAA7134_TS_DMA0, (lines - 1) & 0xff); - saa_writeb(SAA7134_TS_DMA1, ((lines - 1) >> 8) & 0xff); - /* TSNOPIT=0, TSCOLAP=0 */ - saa_writeb(SAA7134_TS_DMA2, (((lines - 1) >> 16) & 0x3f) | 0x00); - saa_writel(SAA7134_RS_PITCH(5), TS_PACKET_SIZE); - saa_writel(SAA7134_RS_CONTROL(5), control); - } - buf->vb.state = VIDEOBUF_PREPARED; buf->activate = buffer_activate; buf->vb.field = field; @@ -175,8 +135,7 @@ buffer_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *size) if (0 == *count) *count = dev->ts.nr_bufs; *count = saa7134_buffer_count(*size,*count); - dev->buff_cnt = 0; - dev->ts_state = SAA7134_TS_STOPPED; + return 0; } @@ -193,11 +152,9 @@ static void buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb) struct saa7134_buf *buf = container_of(vb,struct saa7134_buf,vb); struct saa7134_dev *dev = q->priv_data; - if (dev->ts_state == SAA7134_TS_STARTED) { - /* Stop TS transport */ - saa_writeb(SAA7134_TS_PARALLEL, 0x6c); - dev->ts_state = SAA7134_TS_STOPPED; - } + if (dev->ts_started) + saa7134_ts_stop(dev); + saa7134_dma_free(q,buf); } @@ -214,7 +171,7 @@ EXPORT_SYMBOL_GPL(saa7134_ts_qops); static unsigned int tsbufs = 8; module_param(tsbufs, int, 0444); -MODULE_PARM_DESC(tsbufs,"number of ts buffers, range 2-32"); +MODULE_PARM_DESC(tsbufs, "number of ts buffers for read/write IO, range 2-32"); static unsigned int ts_nr_packets = 64; module_param(ts_nr_packets, int, 0444); @@ -256,6 +213,7 @@ int saa7134_ts_init1(struct saa7134_dev *dev) dev->ts_q.timeout.data = (unsigned long)(&dev->ts_q); dev->ts_q.dev = dev; dev->ts_q.need_two = 1; + dev->ts_started = 0; saa7134_pgtable_alloc(dev->pci,&dev->ts.pt_ts); /* init TS hw */ @@ -264,13 +222,67 @@ int saa7134_ts_init1(struct saa7134_dev *dev) return 0; } +/* Function for stop TS */ +int saa7134_ts_stop(struct saa7134_dev *dev) +{ + dprintk("TS stop\n"); + + BUG_ON(!dev->ts_started); + + /* Stop TS stream */ + switch (saa7134_boards[dev->board].ts_type) { + case SAA7134_MPEG_TS_PARALLEL: + saa_writeb(SAA7134_TS_PARALLEL, 0x6c); + dev->ts_started = 0; + break; + case SAA7134_MPEG_TS_SERIAL: + saa_writeb(SAA7134_TS_SERIAL0, 0x40); + dev->ts_started = 0; + break; + } + return 0; +} + +/* Function for start TS */ +int saa7134_ts_start(struct saa7134_dev *dev) +{ + dprintk("TS start\n"); + + BUG_ON(dev->ts_started); + + saa_writeb(SAA7134_TS_SERIAL1, 0x00); + saa_writeb(SAA7134_TS_SERIAL1, 0x03); + saa_writeb(SAA7134_TS_SERIAL1, 0x00); + saa_writeb(SAA7134_TS_SERIAL1, 0x01); + + /* TS clock non-inverted */ + saa_writeb(SAA7134_TS_SERIAL1, 0x00); + + /* Start TS stream */ + switch (saa7134_boards[dev->board].ts_type) { + case SAA7134_MPEG_TS_PARALLEL: + saa_writeb(SAA7134_TS_SERIAL0, 0x40); + saa_writeb(SAA7134_TS_PARALLEL, 0xec); + break; + case SAA7134_MPEG_TS_SERIAL: + saa_writeb(SAA7134_TS_SERIAL0, 0xd8); + saa_writeb(SAA7134_TS_PARALLEL, 0x6c); + saa_writeb(SAA7134_TS_PARALLEL_SERIAL, 0xbc); + saa_writeb(SAA7134_TS_SERIAL1, 0x02); + break; + } + + dev->ts_started = 1; + + return 0; +} + int saa7134_ts_fini(struct saa7134_dev *dev) { saa7134_pgtable_free(dev->pci,&dev->ts.pt_ts); return 0; } - void saa7134_irq_ts_done(struct saa7134_dev *dev, unsigned long status) { enum v4l2_field field; diff --git a/linux/drivers/media/video/saa7134/saa7134.h b/linux/drivers/media/video/saa7134/saa7134.h index 385bc26bd..454802e73 100644 --- a/linux/drivers/media/video/saa7134/saa7134.h +++ b/linux/drivers/media/video/saa7134/saa7134.h @@ -498,12 +498,6 @@ struct saa7134_mpeg_ops { void (*signal_change)(struct saa7134_dev *dev); }; -enum saa7134_ts_status { - SAA7134_TS_STOPPED, - SAA7134_TS_BUFF_DONE, - SAA7134_TS_STARTED, -}; - /* global device status */ struct saa7134_dev { struct list_head devlist; @@ -598,8 +592,7 @@ struct saa7134_dev { /* SAA7134_MPEG_* */ struct saa7134_ts ts; struct saa7134_dmaqueue ts_q; - enum saa7134_ts_status ts_state; - unsigned int buff_cnt; + int ts_started; struct saa7134_mpeg_ops *mops; /* SAA7134_MPEG_EMPRESS only */ @@ -757,6 +750,9 @@ void saa7134_ts_unregister(struct saa7134_mpeg_ops *ops); int saa7134_ts_init_hw(struct saa7134_dev *dev); +int saa7134_ts_start(struct saa7134_dev *dev); +int saa7134_ts_stop(struct saa7134_dev *dev); + /* ----------------------------------------------------------- */ /* saa7134-vbi.c */ -- cgit v1.2.3 From 43d08cbe79b56211fb686f8301d2cfcdaaa1548d Mon Sep 17 00:00:00 2001 From: Douglas Schilling Landgraf Date: Thu, 28 May 2009 11:11:53 -0300 Subject: bt8xx: remove always false if From: Filipe Rosset Remove always false if over unsigned int variable Priority: normal Signed-off-by: Filipe Rosset Signed-off-by: Douglas Schilling Landgraf --- linux/drivers/media/video/bt8xx/bttv-driver.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (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 8d2075186..67d06eb6c 100644 --- a/linux/drivers/media/video/bt8xx/bttv-driver.c +++ b/linux/drivers/media/video/bt8xx/bttv-driver.c @@ -4665,7 +4665,7 @@ static int __init bttv_init_module(void) #endif if (gbuffers < 2 || gbuffers > VIDEO_MAX_FRAME) gbuffers = 2; - if (gbufsize < 0 || gbufsize > BTTV_MAX_FBUF) + if (gbufsize > BTTV_MAX_FBUF) gbufsize = BTTV_MAX_FBUF; gbufsize = (gbufsize + PAGE_SIZE - 1) & PAGE_MASK; if (bttv_verbose) -- cgit v1.2.3 From 18f456ba66ff7f265cebbc7c0fa00c6ea2d6ae21 Mon Sep 17 00:00:00 2001 From: Douglas Schilling Landgraf Date: Thu, 28 May 2009 11:16:19 -0300 Subject: em28xx: Fix for Slow Memory Leak From: Robert Krakora Test Code: (Provided by Douglas) v4l-dvb/v4l2-apps/test/stress-buffer.c The audio DMA area was never being freed and would slowly leak over time as the v4l device was opened and closed by an application. Thanks again to Douglas for generating the test code to help locate memory leaks!!! Priority: normal Signed-off-by: Robert Krakora Signed-off-by: Douglas Schilling Landgraf --- linux/drivers/media/video/em28xx/em28xx-audio.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/em28xx/em28xx-audio.c b/linux/drivers/media/video/em28xx/em28xx-audio.c index 089764d42..66aace7cf 100644 --- a/linux/drivers/media/video/em28xx/em28xx-audio.c +++ b/linux/drivers/media/video/em28xx/em28xx-audio.c @@ -385,6 +385,11 @@ static int snd_em28xx_pcm_close(struct snd_pcm_substream *substream) mutex_lock(&dev->lock); dev->adev.users--; em28xx_audio_analog_set(dev); + if (substream->runtime->dma_area) { + dprintk("freeing\n"); + vfree(substream->runtime->dma_area); + substream->runtime->dma_area = NULL; + } mutex_unlock(&dev->lock); return 0; -- cgit v1.2.3 From 0291002e9dcce64956346325ef3c35478c6c95b5 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Thu, 28 May 2009 12:50:36 -0400 Subject: lgdt3305: fix 64bit division in function lgdt3305_set_if From: Michael Krufky Priority: high Signed-off-by: Michael Krufky --- linux/drivers/media/dvb/frontends/lgdt3305.c | 17 +++-------------- 1 file changed, 3 insertions(+), 14 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/frontends/lgdt3305.c b/linux/drivers/media/dvb/frontends/lgdt3305.c index f0c0c8199..b16410c64 100644 --- a/linux/drivers/media/dvb/frontends/lgdt3305.c +++ b/linux/drivers/media/dvb/frontends/lgdt3305.c @@ -19,6 +19,7 @@ * */ +#include #include "compat.h" #include #include "dvb_math.h" @@ -497,27 +498,15 @@ static int lgdt3305_set_if(struct lgdt3305_state *state, nco = if_freq_khz / 10; -#define LGDT3305_64BIT_DIVISION_ENABLED 0 - /* FIXME: 64bit division disabled to avoid linking error: - * WARNING: "__udivdi3" [lgdt3305.ko] undefined! - */ switch (param->u.vsb.modulation) { case VSB_8: -#if LGDT3305_64BIT_DIVISION_ENABLED nco <<= 24; - nco /= 625; -#else - nco *= ((1 << 24) / 625); -#endif + do_div(nco, 625); break; case QAM_64: case QAM_256: -#if LGDT3305_64BIT_DIVISION_ENABLED nco <<= 28; - nco /= 625; -#else - nco *= ((1 << 28) / 625); -#endif + do_div(nco, 625); break; default: return -EINVAL; -- cgit v1.2.3 From 3d5f82276e18a37806603a52b23d18c8b60b5d01 Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Fri, 29 May 2009 19:54:02 -0400 Subject: cx18: Perform 64 bit divide so it works for 32 bit systems From: Andy Walls Thanks to David Ward and Mike Krufky for reporting the problem and debugging this as an unresolved symbol due to a 64 bit divide on a 32 bit system. David Ward provided the content of this patch; Andy Walls only performed some cosmetic edits. Reported-by: David Ward Priority: normal Signed-off-by: David Ward Signed-off-by: Andy Walls --- linux/drivers/media/video/cx18/cx18-av-core.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/cx18/cx18-av-core.c b/linux/drivers/media/video/cx18/cx18-av-core.c index 0b3d840cc..536dedb23 100644 --- a/linux/drivers/media/video/cx18/cx18-av-core.c +++ b/linux/drivers/media/video/cx18/cx18-av-core.c @@ -447,6 +447,7 @@ void cx18_av_std_setup(struct cx18 *cx) if (pll_post) { int fsc, pll; + u64 tmp; pll = (28636360L * ((((u64)pll_int) << 25) + pll_frac)) >> 25; pll /= pll_post; @@ -459,7 +460,9 @@ void cx18_av_std_setup(struct cx18 *cx) "= %d.%03d\n", src_decimation / 256, ((src_decimation % 256) * 1000) / 256); - fsc = ((((u64)sc) * 28636360)/src_decimation) >> 13L; + tmp = 28636360 * (u64) sc; + do_div(tmp, src_decimation); + fsc = tmp >> 13; CX18_DEBUG_INFO_DEV(sd, "Chroma sub-carrier initial freq = %d.%06d " "MHz\n", fsc / 1000000, fsc % 1000000); -- cgit v1.2.3 From 51c04c87bb11afe772c5cf797a12c71c602cff8c Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Sat, 30 May 2009 17:45:46 -0700 Subject: v4l2: Create helper function for bounding and aligning images From: Trent Piepho Most hardware has limits on minimum and maximum image dimensions and also requirements about alignment. For example, image width must be even or a multiple of four. Some hardware has requirements that the total image size (width * height) be a multiple of some power of two. v4l_bound_align_image() will enforce min and max width and height, power of two alignment on width and height, and power of two alignment on total image size. It uses an efficient algorithm that will try to find the "closest" image size that meets the requirements. Priority: normal Signed-off-by: Trent Piepho --- linux/drivers/media/video/v4l2-common.c | 71 +++++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/v4l2-common.c b/linux/drivers/media/video/v4l2-common.c index 8f2db1250..d81bae197 100644 --- a/linux/drivers/media/video/v4l2-common.c +++ b/linux/drivers/media/video/v4l2-common.c @@ -997,4 +997,75 @@ const unsigned short *v4l2_i2c_tuner_addrs(enum v4l2_i2c_tuner_type type) } EXPORT_SYMBOL_GPL(v4l2_i2c_tuner_addrs); +/* Clamp x to be between min and max, aligned to a multiple of 2^align. min + * and max don't have to be aligned, but there must be at least one valid + * value. E.g., min=17,max=31,align=4 is not allowed as there are no multiples + * of 16 between 17 and 31. */ +static unsigned int clamp_align(unsigned int x, unsigned int min, + unsigned int max, unsigned int align) +{ + /* Bits that must be zero to be aligned */ + unsigned int mask = ~((1 << align) - 1); + + /* Round to nearest aligned value */ + if (align) + x = (x + (1 << (align - 1))) & mask; + + /* Clamp to aligned value of min and max */ + if (x < min) + x = (min + ~mask) & mask; + else if (x > max) + x = max & mask; + + return x; +} + +/* Bound an image to have a width between wmin and wmax, and height between + * hmin and hmax, inclusive. Additionally, the width will be a multiple of + * 2^walign, the height will be a multiple of 2^halign, and the overall size + * (width*height) will be a multiple of 2^salign. The image may be shrunk + * or enlarged to fit the alignment constraints. + * + * The width or height maximum must not be smaller than the corresponding + * minimum. The alignments must not be so high there are no possible image + * sizes within the allowed bounds. wmin and hmin must be at least 1 + * (don't use 0). If you don't care about a certain alignment, specify 0, + * as 2^0 is 1 and one byte alignment is equivalent to no alignment. If + * you only want to adjust downward, specify a maximum that's the same as + * the initial value. + */ +void v4l_bound_align_image(u32 *w, unsigned int wmin, unsigned int wmax, + unsigned int walign, + u32 *h, unsigned int hmin, unsigned int hmax, + unsigned int halign, unsigned int salign) +{ + *w = clamp_align(*w, wmin, wmax, walign); + *h = clamp_align(*h, hmin, hmax, halign); + + /* Usually we don't need to align the size and are done now. */ + if (!salign) + return; + + /* How much alignment do we have? */ + walign = __ffs(*w); + halign = __ffs(*h); + /* Enough to satisfy the image alignment? */ + if (walign + halign < salign) { + /* Max walign where there is still a valid width */ + unsigned int wmaxa = __fls(wmax ^ (wmin - 1)); + + /* up the smaller alignment until we have enough */ + do { + if (walign <= halign && walign < wmaxa) { + *w = clamp_align(*w, wmin, wmax, walign + 1); + walign = __ffs(*w); + } else { + *h = clamp_align(*h, hmin, hmax, halign + 1); + halign = __ffs(*h); + } + } while (halign + walign < salign); + } +} +EXPORT_SYMBOL_GPL(v4l_bound_align_image); + #endif -- cgit v1.2.3 From 9b58b19cf0eba5a8a77bbbd58df57194a5688a80 Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Sat, 30 May 2009 17:45:46 -0700 Subject: pxa-camera: Use v4l bounding/alignment function From: Trent Piepho The v4l function has a better algorithm for aligning image size. For instance the old code would change 159x243 into 156x240 to meet the alignment requirements. The new function will use 160x243, which is a lot closer to what was asked for originally. Priority: normal Signed-off-by: Trent Piepho CC: Robert Jarzmik CC: Guennadi Liakhovetski --- linux/drivers/media/video/pxa_camera.c | 36 +++++++--------------------------- 1 file changed, 7 insertions(+), 29 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/pxa_camera.c b/linux/drivers/media/video/pxa_camera.c index 35642c430..2c122ec90 100644 --- a/linux/drivers/media/video/pxa_camera.c +++ b/linux/drivers/media/video/pxa_camera.c @@ -174,13 +174,6 @@ CICR0_PERRM | CICR0_QDM | CICR0_CDM | CICR0_SOFM | \ CICR0_EOFM | CICR0_FOM) -/* - * YUV422P picture size should be a multiple of 16, so the heuristic aligns - * height, width on 4 byte boundaries to reach the 16 multiple for the size. - */ -#define YUV422P_X_Y_ALIGN 4 -#define YUV422P_SIZE_ALIGN YUV422P_X_Y_ALIGN * YUV422P_X_Y_ALIGN - /* * Structures */ @@ -1410,28 +1403,13 @@ static int pxa_camera_try_fmt(struct soc_camera_device *icd, return -EINVAL; } - /* limit to pxa hardware capabilities */ - if (pix->height < 32) - pix->height = 32; - if (pix->height > 2048) - pix->height = 2048; - if (pix->width < 48) - pix->width = 48; - if (pix->width > 2048) - pix->width = 2048; - pix->width &= ~0x01; - - /* - * YUV422P planar format requires images size to be a 16 bytes - * multiple. If not, zeros will be inserted between Y and U planes, and - * U and V planes, and YUV422P standard would be violated. - */ - if (xlate->host_fmt->fourcc == V4L2_PIX_FMT_YUV422P) { - if (!IS_ALIGNED(pix->width * pix->height, YUV422P_SIZE_ALIGN)) - pix->height = ALIGN(pix->height, YUV422P_X_Y_ALIGN); - if (!IS_ALIGNED(pix->width * pix->height, YUV422P_SIZE_ALIGN)) - pix->width = ALIGN(pix->width, YUV422P_X_Y_ALIGN); - } + /* Limit to pxa hardware capabilities. YUV422P planar format requires + * images size to be a multiple of 16 bytes. If not, zeros will be + * inserted between Y and U planes, and U and V planes, which violates + * the YUV422P standard. */ + v4l2_bound_align_image(&pix->width, 48, 2048, 1, + &pix->height, 32, 2048, 0, + xlate->host_fmt->fourcc == V4L2_PIX_FMT_YUV422P ? 4 : 0); pix->bytesperline = pix->width * DIV_ROUND_UP(xlate->host_fmt->depth, 8); -- cgit v1.2.3 From fc32b7aec72765c7ee074348f4bf6f8f920aacc4 Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Sat, 30 May 2009 17:45:46 -0700 Subject: sh_mobile_ceu_camera: Use v4l bounding/alignment function From: Trent Piepho The v4l function has a better algorithm for aligning image size. Priority: normal Signed-off-by: Trent Piepho --- linux/drivers/media/video/sh_mobile_ceu_camera.c | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/sh_mobile_ceu_camera.c b/linux/drivers/media/video/sh_mobile_ceu_camera.c index bf0b176f9..7ea2a0edf 100644 --- a/linux/drivers/media/video/sh_mobile_ceu_camera.c +++ b/linux/drivers/media/video/sh_mobile_ceu_camera.c @@ -690,16 +690,8 @@ static int sh_mobile_ceu_try_fmt(struct soc_camera_device *icd, /* FIXME: calculate using depth and bus width */ - if (f->fmt.pix.height < 4) - f->fmt.pix.height = 4; - if (f->fmt.pix.height > 1920) - f->fmt.pix.height = 1920; - if (f->fmt.pix.width < 2) - f->fmt.pix.width = 2; - if (f->fmt.pix.width > 2560) - f->fmt.pix.width = 2560; - f->fmt.pix.width &= ~0x01; - f->fmt.pix.height &= ~0x03; + v4l_bound_align_image(&f->fmt.pix.width, 2, 2560, 1, + &f->fmt.pix.height, 4, 1920, 2, 0); f->fmt.pix.bytesperline = f->fmt.pix.width * DIV_ROUND_UP(xlate->host_fmt->depth, 8); -- cgit v1.2.3 From 8c986b899b3f035b94b4ee568ce00a8a48c12f45 Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Sat, 30 May 2009 17:45:46 -0700 Subject: zoran: Use v4l bounding/alignment functiob From: Trent Piepho The v4l function has a better algorithm for aligning image size. Priority: normal Signed-off-by: Trent Piepho --- linux/drivers/media/video/zoran/zoran_driver.c | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/zoran/zoran_driver.c b/linux/drivers/media/video/zoran/zoran_driver.c index 793395074..8c17d47b3 100644 --- a/linux/drivers/media/video/zoran/zoran_driver.c +++ b/linux/drivers/media/video/zoran/zoran_driver.c @@ -2096,16 +2096,10 @@ static int zoran_try_fmt_vid_cap(struct file *file, void *__fh, return -EINVAL; } - bpp = (zoran_formats[i].depth + 7) / 8; - fmt->fmt.pix.width &= ~((bpp == 2) ? 1 : 3); - if (fmt->fmt.pix.width > BUZ_MAX_WIDTH) - fmt->fmt.pix.width = BUZ_MAX_WIDTH; - if (fmt->fmt.pix.width < BUZ_MIN_WIDTH) - fmt->fmt.pix.width = BUZ_MIN_WIDTH; - if (fmt->fmt.pix.height > BUZ_MAX_HEIGHT) - fmt->fmt.pix.height = BUZ_MAX_HEIGHT; - if (fmt->fmt.pix.height < BUZ_MIN_HEIGHT) - fmt->fmt.pix.height = BUZ_MIN_HEIGHT; + bpp = DIV_ROUND_UP(zoran_formats[i].depth, 8); + v4l_bound_align_image( + &fmt->fmt.pix.width, BUZ_MIN_WIDTH, BUZ_MAX_WIDTH, bpp == 2 ? 1 : 2, + &fmt->fmt.pix.height, BUZ_MIN_HEIGHT, BUZ_MAX_HEIGHT, 0, 0); mutex_unlock(&zr->resource_lock); return 0; -- cgit v1.2.3 From 1892adfab10cb9deee0fef6c601bf0ed01daa384 Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Sat, 30 May 2009 17:45:46 -0700 Subject: vivi: Use v4l bounding/alignment function From: Trent Piepho The v4l function has a better algorithm for aligning image size. Priority: normal Signed-off-by: Trent Piepho --- linux/drivers/media/video/vivi.c | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/vivi.c b/linux/drivers/media/video/vivi.c index e3bc2b0a3..fe39b7326 100644 --- a/linux/drivers/media/video/vivi.c +++ b/linux/drivers/media/video/vivi.c @@ -886,15 +886,8 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, maxh = norm_maxh(); f->fmt.pix.field = field; - if (f->fmt.pix.height < 32) - f->fmt.pix.height = 32; - if (f->fmt.pix.height > maxh) - f->fmt.pix.height = maxh; - if (f->fmt.pix.width < 48) - f->fmt.pix.width = 48; - if (f->fmt.pix.width > maxw) - f->fmt.pix.width = maxw; - f->fmt.pix.width &= ~0x03; + v4l_bound_align_image(&f->fmt.pix.width, 48, maxw, 2, + &f->fmt.pix.height, 32, maxh, 0, 0); f->fmt.pix.bytesperline = (f->fmt.pix.width * fmt->depth) >> 3; f->fmt.pix.sizeimage = -- cgit v1.2.3 From 6ebc4db113b06e0a7390faa61f891ef23d3a483a Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Sat, 30 May 2009 17:45:46 -0700 Subject: saa7134: Use v4l bounding/alignment function From: Trent Piepho The v4l function has a better algorithm for aligning image size. Priority: normal Signed-off-by: Trent Piepho --- linux/drivers/media/video/saa7134/saa7134-video.c | 11 ++--------- 1 file changed, 2 insertions(+), 9 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 26f1727e6..ddf842a0d 100644 --- a/linux/drivers/media/video/saa7134/saa7134-video.c +++ b/linux/drivers/media/video/saa7134/saa7134-video.c @@ -1646,15 +1646,8 @@ static int saa7134_try_fmt_vid_cap(struct file *file, void *priv, } f->fmt.pix.field = field; - if (f->fmt.pix.width < 48) - f->fmt.pix.width = 48; - if (f->fmt.pix.height < 32) - f->fmt.pix.height = 32; - if (f->fmt.pix.width > maxw) - f->fmt.pix.width = maxw; - if (f->fmt.pix.height > maxh) - f->fmt.pix.height = maxh; - f->fmt.pix.width &= ~0x03; + v4l_bound_align_image(&f->fmt.pix.width, 48, maxw, 2, + &f->fmt.pix.height, 32, maxh, 0, 0); f->fmt.pix.bytesperline = (f->fmt.pix.width * fmt->depth) >> 3; f->fmt.pix.sizeimage = -- cgit v1.2.3 From 6c671f37ed7cd5bbe5c041761851f903361f8687 Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Sat, 30 May 2009 17:45:46 -0700 Subject: cx88: Use v4l bounding/alignment function From: Trent Piepho The v4l function has a better algorithm for aligning image size. Priority: normal Signed-off-by: Trent Piepho --- linux/drivers/media/video/cx88/cx88-video.c | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) (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 2dfa4c9c3..70b086fb7 100644 --- a/linux/drivers/media/video/cx88/cx88-video.c +++ b/linux/drivers/media/video/cx88/cx88-video.c @@ -1339,15 +1339,8 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, } f->fmt.pix.field = field; - if (f->fmt.pix.height < 32) - f->fmt.pix.height = 32; - if (f->fmt.pix.height > maxh) - f->fmt.pix.height = maxh; - if (f->fmt.pix.width < 48) - f->fmt.pix.width = 48; - if (f->fmt.pix.width > maxw) - f->fmt.pix.width = maxw; - f->fmt.pix.width &= ~0x03; + v4l_bound_align_image(&f->fmt.pix.width, 48, maxw, 2, + &f->fmt.pix.height, 32, maxh, 0, 0); f->fmt.pix.bytesperline = (f->fmt.pix.width * fmt->depth) >> 3; f->fmt.pix.sizeimage = -- cgit v1.2.3 From b0fc719e0220c50eb50f77552fc00b0adc11c5d0 Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Sat, 30 May 2009 17:45:46 -0700 Subject: w8968cf: Use v4l bounding/alignment function From: Trent Piepho The v4l function has a better algorithm for aligning image size. The existing code was casting pointers to u32 and to unsigned int into pointers to u16. This could mess up if someone passed in an image size greater than 65,535 and on big-endian platforms it won't work at all. The existing bounding code would shrink an image if it was too big, but returned ERANGE if it was too small. The code will not shrink or expand as necessary. Priority: normal Signed-off-by: Trent Piepho --- linux/drivers/media/video/w9968cf.c | 35 ++++++++++++++--------------------- 1 file changed, 14 insertions(+), 21 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/w9968cf.c b/linux/drivers/media/video/w9968cf.c index d51566ddc..86738d186 100644 --- a/linux/drivers/media/video/w9968cf.c +++ b/linux/drivers/media/video/w9968cf.c @@ -464,7 +464,7 @@ static int w9968cf_set_picture(struct w9968cf_device*, struct video_picture); static int w9968cf_set_window(struct w9968cf_device*, struct video_window); static int w9968cf_postprocess_frame(struct w9968cf_device*, struct w9968cf_frame_t*); -static int w9968cf_adjust_window_size(struct w9968cf_device*, u16* w, u16* h); +static int w9968cf_adjust_window_size(struct w9968cf_device*, u32 *w, u32 *h); static void w9968cf_init_framelist(struct w9968cf_device*); static void w9968cf_push_frame(struct w9968cf_device*, u8 f_num); static void w9968cf_pop_frame(struct w9968cf_device*,struct w9968cf_frame_t**); @@ -1777,8 +1777,7 @@ w9968cf_set_window(struct w9968cf_device* cam, struct video_window win) #define UNSC(x) ((x) >> 10) /* Make sure we are using a supported resolution */ - if ((err = w9968cf_adjust_window_size(cam, (u16*)&win.width, - (u16*)&win.height))) + if ((err = w9968cf_adjust_window_size(cam, &win.width, &win.height))) goto error; /* Scaling factors */ @@ -1928,12 +1927,9 @@ error: Return 0 on success, -1 otherwise. --------------------------------------------------------------------------*/ static int -w9968cf_adjust_window_size(struct w9968cf_device* cam, u16* width, u16* height) +w9968cf_adjust_window_size(struct w9968cf_device *cam, u32 *width, u32 *height) { - u16 maxw, maxh; - - if ((*width < cam->minwidth) || (*height < cam->minheight)) - return -ERANGE; + unsigned int maxw, maxh, align; maxw = cam->upscaling && !(cam->vpp_flag & VPP_DECOMPRESSION) && w9968cf_vpp ? max((u16)W9968CF_MAX_WIDTH, cam->maxwidth) @@ -1941,16 +1937,10 @@ w9968cf_adjust_window_size(struct w9968cf_device* cam, u16* width, u16* height) maxh = cam->upscaling && !(cam->vpp_flag & VPP_DECOMPRESSION) && w9968cf_vpp ? max((u16)W9968CF_MAX_HEIGHT, cam->maxheight) : cam->maxheight; + align = (cam->vpp_flag & VPP_DECOMPRESSION) ? 4 : 0; - if (*width > maxw) - *width = maxw; - if (*height > maxh) - *height = maxh; - - if (cam->vpp_flag & VPP_DECOMPRESSION) { - *width &= ~15L; /* multiple of 16 */ - *height &= ~15L; - } + v4l_bound_align_image(width, cam->minwidth, maxw, align, + height, cam->minheight, maxh, align, 0); PDBGG("Window size adjusted w=%u, h=%u ", *width, *height) @@ -3057,8 +3047,8 @@ static long w9968cf_v4l_ioctl(struct file *filp, if (win.clipcount != 0 || win.flags != 0) return -EINVAL; - if ((err = w9968cf_adjust_window_size(cam, (u16*)&win.width, - (u16*)&win.height))) { + if ((err = w9968cf_adjust_window_size(cam, &win.width, + &win.height))) { DBG(4, "Resolution not supported (%ux%u). " "VIDIOCSWIN failed", win.width, win.height) return err; @@ -3130,6 +3120,7 @@ static long w9968cf_v4l_ioctl(struct file *filp, { struct video_mmap mmap; struct w9968cf_frame_t* fr; + u32 w, h; int err = 0; if (copy_from_user(&mmap, arg, sizeof(mmap))) @@ -3178,8 +3169,10 @@ static long w9968cf_v4l_ioctl(struct file *filp, } } - if ((err = w9968cf_adjust_window_size(cam, (u16*)&mmap.width, - (u16*)&mmap.height))) { + w = mmap.width; h = mmap.height; + err = w9968cf_adjust_window_size(cam, &w, &h); + mmap.width = w; mmap.height = h; + if (err) { DBG(4, "Resolution not supported (%dx%d). " "VIDIOCMCAPTURE failed", mmap.width, mmap.height) -- cgit v1.2.3 From 3b017fe86fc86aebdfb6430c70d4e9f9fb944492 Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Sat, 30 May 2009 17:45:46 -0700 Subject: cx23885: Use v4l bounding/alignment function From: Trent Piepho The v4l function has a better algorithm for aligning image size. Priority: normal Signed-off-by: Trent Piepho --- linux/drivers/media/video/cx23885/cx23885-video.c | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/cx23885/cx23885-video.c b/linux/drivers/media/video/cx23885/cx23885-video.c index 2855a49b5..378943605 100644 --- a/linux/drivers/media/video/cx23885/cx23885-video.c +++ b/linux/drivers/media/video/cx23885/cx23885-video.c @@ -1035,15 +1035,8 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, } f->fmt.pix.field = field; - if (f->fmt.pix.height < 32) - f->fmt.pix.height = 32; - if (f->fmt.pix.height > maxh) - f->fmt.pix.height = maxh; - if (f->fmt.pix.width < 48) - f->fmt.pix.width = 48; - if (f->fmt.pix.width > maxw) - f->fmt.pix.width = maxw; - f->fmt.pix.width &= ~0x03; + v4l_bound_align_image(&f->fmt.pix.width, 48, maxw, 2, + &f->fmt.pix.height, 32, maxh, 0, 0); f->fmt.pix.bytesperline = (f->fmt.pix.width * fmt->depth) >> 3; f->fmt.pix.sizeimage = -- cgit v1.2.3 From 63242b556aeb302ca2feab368b784eb1e8ff2df0 Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Sat, 30 May 2009 17:45:46 -0700 Subject: mt9: Use v4l bounding/alignment function From: Trent Piepho The v4l function has a better algorithm for aligning image size. Priority: normal Signed-off-by: Trent Piepho CC: Guennadi Liakhovetski --- linux/drivers/media/video/mt9m001.c | 12 +++--------- linux/drivers/media/video/mt9t031.c | 14 +++----------- linux/drivers/media/video/mt9v022.c | 12 +++--------- 3 files changed, 9 insertions(+), 29 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/mt9m001.c b/linux/drivers/media/video/mt9m001.c index 8d61ad30a..e609d68c4 100644 --- a/linux/drivers/media/video/mt9m001.c +++ b/linux/drivers/media/video/mt9m001.c @@ -280,15 +280,9 @@ static int mt9m001_try_fmt(struct soc_camera_device *icd, { struct v4l2_pix_format *pix = &f->fmt.pix; - if (pix->height < 32 + icd->y_skip_top) - pix->height = 32 + icd->y_skip_top; - if (pix->height > 1024 + icd->y_skip_top) - pix->height = 1024 + icd->y_skip_top; - if (pix->width < 48) - pix->width = 48; - if (pix->width > 1280) - pix->width = 1280; - pix->width &= ~0x01; /* has to be even, unsure why was ~3 */ + v4l_bound_align_image(&pix->width, 48, 1280, 1, + &pix->height, 32 + icd->y_skip_top, + 1024 + icd->y_skip_top, 0, 0); return 0; } diff --git a/linux/drivers/media/video/mt9t031.c b/linux/drivers/media/video/mt9t031.c index 381dd0fbe..a57051522 100644 --- a/linux/drivers/media/video/mt9t031.c +++ b/linux/drivers/media/video/mt9t031.c @@ -385,17 +385,9 @@ static int mt9t031_try_fmt(struct soc_camera_device *icd, { struct v4l2_pix_format *pix = &f->fmt.pix; - if (pix->height < MT9T031_MIN_HEIGHT) - pix->height = MT9T031_MIN_HEIGHT; - if (pix->height > MT9T031_MAX_HEIGHT) - pix->height = MT9T031_MAX_HEIGHT; - if (pix->width < MT9T031_MIN_WIDTH) - pix->width = MT9T031_MIN_WIDTH; - if (pix->width > MT9T031_MAX_WIDTH) - pix->width = MT9T031_MAX_WIDTH; - - pix->width &= ~0x01; /* has to be even */ - pix->height &= ~0x01; /* has to be even */ + v4l_bound_align_image( + &pix->width, MT9T031_MIN_WIDTH, MT9T031_MAX_WIDTH, 1, + &pix->height, MT9T031_MIN_HEIGHT, MT9T031_MAX_HEIGHT, 1, 0); return 0; } diff --git a/linux/drivers/media/video/mt9v022.c b/linux/drivers/media/video/mt9v022.c index 016bcdfcf..4841e6eea 100644 --- a/linux/drivers/media/video/mt9v022.c +++ b/linux/drivers/media/video/mt9v022.c @@ -364,15 +364,9 @@ static int mt9v022_try_fmt(struct soc_camera_device *icd, { struct v4l2_pix_format *pix = &f->fmt.pix; - if (pix->height < 32 + icd->y_skip_top) - pix->height = 32 + icd->y_skip_top; - if (pix->height > 480 + icd->y_skip_top) - pix->height = 480 + icd->y_skip_top; - if (pix->width < 48) - pix->width = 48; - if (pix->width > 752) - pix->width = 752; - pix->width &= ~0x03; /* ? */ + v4l_bound_align_image(&pix->width, 48, 752, 2 /* ? */, + &pix->height, 32 + icd->y_skip_top, + 480 + icd->y_skip_top, 0, 0); return 0; } -- cgit v1.2.3 From 89238d5360d8f8530addc8728b8681f05921fbb0 Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Sat, 30 May 2009 17:45:46 -0700 Subject: cx231xx: Use v4l bounding/alignment function From: Trent Piepho The v4l function has a better algorithm for aligning image size. Priority: normal Signed-off-by: Trent Piepho CC: Srinivasa Deevi --- linux/drivers/media/video/cx231xx/cx231xx-video.c | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/cx231xx/cx231xx-video.c b/linux/drivers/media/video/cx231xx/cx231xx-video.c index 638a8d3e4..6ed752c22 100644 --- a/linux/drivers/media/video/cx231xx/cx231xx-video.c +++ b/linux/drivers/media/video/cx231xx/cx231xx-video.c @@ -955,8 +955,8 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, { struct cx231xx_fh *fh = priv; struct cx231xx *dev = fh->dev; - int width = f->fmt.pix.width; - int height = f->fmt.pix.height; + unsigned int width = f->fmt.pix.width; + unsigned int height = f->fmt.pix.height; unsigned int maxw = norm_maxw(dev); unsigned int maxh = norm_maxh(dev); unsigned int hscale, vscale; @@ -971,17 +971,7 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, /* width must even because of the YUYV format height must be even because of interlacing */ - height &= 0xfffe; - width &= 0xfffe; - - if (unlikely(height < 32)) - height = 32; - if (unlikely(height > maxh)) - height = maxh; - if (unlikely(width < 48)) - width = 48; - if (unlikely(width > maxw)) - width = maxw; + v4l_bound_align_image(&width, 48, maxw, 1, &height, 32, maxh, 1, 0); get_scale(dev, width, height, &hscale, &vscale); -- cgit v1.2.3 From ed377dd0de1bcd6b8df32c6ad057d9e0fc0def29 Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Sat, 30 May 2009 17:45:46 -0700 Subject: em28xx: Use v4l bounding/alignment function From: Trent Piepho The v4l function has a better algorithm for aligning image size. It appears that the em2800 can only scale by 50% or 100%, i.e. the only heights supported might be 240 and 480. In that case the old code would set any height other than 240 to 480. Request 240 get 240, but request 239 and then you get 480. Change it to round to the nearest supported value. Priority: normal Signed-off-by: Trent Piepho --- linux/drivers/media/video/em28xx/em28xx-video.c | 38 ++++++++----------------- 1 file changed, 12 insertions(+), 26 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/em28xx/em28xx-video.c b/linux/drivers/media/video/em28xx/em28xx-video.c index 1614e5fc4..63d21698c 100644 --- a/linux/drivers/media/video/em28xx/em28xx-video.c +++ b/linux/drivers/media/video/em28xx/em28xx-video.c @@ -691,8 +691,8 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, { struct em28xx_fh *fh = priv; struct em28xx *dev = fh->dev; - int width = f->fmt.pix.width; - int height = f->fmt.pix.height; + unsigned int width = f->fmt.pix.width; + unsigned int height = f->fmt.pix.height; unsigned int maxw = norm_maxw(dev); unsigned int maxh = norm_maxh(dev); unsigned int hscale, vscale; @@ -705,34 +705,20 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, return -EINVAL; } - /* width must even because of the YUYV format - height must be even because of interlacing */ - height &= 0xfffe; - width &= 0xfffe; - - if (unlikely(height < 32)) - height = 32; - if (unlikely(height > maxh)) - height = maxh; - if (unlikely(width < 48)) - width = 48; - if (unlikely(width > maxw)) - width = maxw; - if (dev->board.is_em2800) { /* the em2800 can only scale down to 50% */ - if (height % (maxh / 2)) - height = maxh; - if (width % (maxw / 2)) - width = maxw; - /* according to empiatech support */ - /* the MaxPacketSize is to small to support */ - /* framesizes larger than 640x480 @ 30 fps */ - /* or 640x576 @ 25 fps. As this would cut */ - /* of a part of the image we prefer */ - /* 360x576 or 360x480 for now */ + height = height > (3 * maxh / 4) ? maxh : maxh / 2; + width = width > (3 * maxw / 4) ? maxw : maxw / 2; + /* According to empiatech support the MaxPacketSize is too small + * to support framesizes larger than 640x480 @ 30 fps or 640x576 + * @ 25 fps. As this would cut of a part of the image we prefer + * 360x576 or 360x480 for now */ if (width == maxw && height == maxh) width /= 2; + } else { + /* width must even because of the YUYV format + height must be even because of interlacing */ + v4l_bound_align_image(&width, 48, maxw, 1, &height, 32, maxh, 1, 0); } get_scale(dev, width, height, &hscale, &vscale); -- cgit v1.2.3 From 0b81474a751308c61db74ee4088c8b557b913c3c Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Sat, 30 May 2009 17:45:46 -0700 Subject: cx231xx: TRY_FMT should not actually set anything From: Trent Piepho In the TRY_FMT handler the function get_scale() is called to find what the scaler hardware will produce for a requested size. The problem is that get_scale(struct cx231xx *dev, ..., unsigned int *vscale, unsigned int *hscale) saves the calculated scale values into both the pointer arguments and into dev's hscale and vscale fields. TRY_FMT shouldn't actually change anything in the device state. The code to in get_scale() that writes to dev->[hv]scale can just be deleted. In all cases when dev's fields should be modified, get_scale() was called with get_scale(dev, ..., &dev->hscale, &dev->vscale), so dev was getting updated anyway. This didn't actually cause a problem because nothing ever actually made use of the hscale and vscale fields. I changed cx231xx_resolution_set() to use those fields rather than re-calculate them with a call to get_scale(). Updating [hv]scale in cx231xx_resolution_set() isn't necessary because every call of cx231xx_resolution_set() was already preceded by a call to get_scale() or setting the [hv]scale fields, so they will be always be up-to-date w.r.t. width and height. Removing the call to get_scale() from cx231xx_resolution_set() allowed making get_scale() a static function, which is a good thing for something with such a short name. There is already another function with the same name in the em28xx driver, but that one is static. Priority: normal Signed-off-by: Trent Piepho --- linux/drivers/media/video/cx231xx/cx231xx-avcore.c | 17 ++++------------- linux/drivers/media/video/cx231xx/cx231xx-video.c | 10 +++------- linux/drivers/media/video/cx231xx/cx231xx.h | 3 --- 3 files changed, 7 insertions(+), 23 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/cx231xx/cx231xx-avcore.c b/linux/drivers/media/video/cx231xx/cx231xx-avcore.c index 6a9464079..bbbb3f50e 100644 --- a/linux/drivers/media/video/cx231xx/cx231xx-avcore.c +++ b/linux/drivers/media/video/cx231xx/cx231xx-avcore.c @@ -1052,22 +1052,13 @@ int cx231xx_set_audio_decoder_input(struct cx231xx *dev, /* Set resolution of the video */ int cx231xx_resolution_set(struct cx231xx *dev) { - int width, height; - u32 hscale, vscale; - int status = 0; - - width = dev->width; - height = dev->height; - - get_scale(dev, width, height, &hscale, &vscale); - /* set horzontal scale */ - status = vid_blk_write_word(dev, HSCALE_CTRL, hscale); + int status = vid_blk_write_word(dev, HSCALE_CTRL, dev->hscale); + if (status) + return status; /* set vertical scale */ - status = vid_blk_write_word(dev, VSCALE_CTRL, vscale); - - return status; + return vid_blk_write_word(dev, VSCALE_CTRL, dev->vscale); } /****************************************************************************** diff --git a/linux/drivers/media/video/cx231xx/cx231xx-video.c b/linux/drivers/media/video/cx231xx/cx231xx-video.c index 6ed752c22..e00edd0aa 100644 --- a/linux/drivers/media/video/cx231xx/cx231xx-video.c +++ b/linux/drivers/media/video/cx231xx/cx231xx-video.c @@ -893,9 +893,9 @@ static int check_dev(struct cx231xx *dev) return 0; } -void get_scale(struct cx231xx *dev, - unsigned int width, unsigned int height, - unsigned int *hscale, unsigned int *vscale) +static void get_scale(struct cx231xx *dev, + unsigned int width, unsigned int height, + unsigned int *hscale, unsigned int *vscale) { unsigned int maxw = norm_maxw(dev); unsigned int maxh = norm_maxh(dev); @@ -907,10 +907,6 @@ void get_scale(struct cx231xx *dev, *vscale = (((unsigned long)maxh) << 12) / height - 4096L; if (*vscale >= 0x4000) *vscale = 0x3fff; - - dev->hscale = *hscale; - dev->vscale = *vscale; - } /* ------------------------------------------------------------------ diff --git a/linux/drivers/media/video/cx231xx/cx231xx.h b/linux/drivers/media/video/cx231xx/cx231xx.h index c436f2b0d..051ca21c1 100644 --- a/linux/drivers/media/video/cx231xx/cx231xx.h +++ b/linux/drivers/media/video/cx231xx/cx231xx.h @@ -731,9 +731,6 @@ int cx231xx_set_video_input_mux(struct cx231xx *dev, u8 input); int cx231xx_set_decoder_video_input(struct cx231xx *dev, u8 pin_type, u8 input); int cx231xx_do_mode_ctrl_overrides(struct cx231xx *dev); int cx231xx_set_audio_input(struct cx231xx *dev, u8 input); -void get_scale(struct cx231xx *dev, - unsigned int width, unsigned int height, - unsigned int *hscale, unsigned int *vscale); /* Provided by cx231xx-video.c */ int cx231xx_register_extension(struct cx231xx_ops *dev); -- cgit v1.2.3 From 44b1c5b02d09f608ab17baeed5f5862af30bb32e Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Sun, 31 May 2009 22:05:55 +0200 Subject: uvcvideo: Add generic control blacklist. From: Laurent Pinchart Another device (5986:0241) has been reported to advertise a UVC control it does not support. Rework the control blacklist to match devices by their VID:PID instead of trying to be clever about which controls might not be supported properly. Priority: normal Signed-off-by: Laurent Pinchart --- linux/drivers/media/video/uvc/uvc_ctrl.c | 35 +++++++++++++----------------- linux/drivers/media/video/uvc/uvc_driver.c | 3 +-- linux/drivers/media/video/uvc/uvcvideo.h | 1 - 3 files changed, 16 insertions(+), 23 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/uvc/uvc_ctrl.c b/linux/drivers/media/video/uvc/uvc_ctrl.c index 7774ce6b5..ef55bc35a 100644 --- a/linux/drivers/media/video/uvc/uvc_ctrl.c +++ b/linux/drivers/media/video/uvc/uvc_ctrl.c @@ -1374,21 +1374,19 @@ end: } /* - * Prune an entity of its bogus controls. This currently includes processing - * unit auto controls for which no corresponding manual control is available. - * Such auto controls make little sense if any, and are known to crash at - * least the SiGma Micro webcam. + * Prune an entity of its bogus controls using a blacklist. Bogus controls + * are currently the ones that crash the camera or unconditionally return an + * error when queried. */ static void -uvc_ctrl_prune_entity(struct uvc_entity *entity) +uvc_ctrl_prune_entity(struct uvc_device *dev, struct uvc_entity *entity) { static const struct { - u8 idx_manual; - u8 idx_auto; + struct usb_device_id id; + u8 index; } blacklist[] = { - { 2, 11 }, /* Hue */ - { 6, 12 }, /* White Balance Temperature */ - { 7, 13 }, /* White Balance Component */ + { { USB_DEVICE(0x1c4f, 0x3000) }, 6 }, /* WB Temperature */ + { { USB_DEVICE(0x5986, 0x0241) }, 2 }, /* Hue */ }; u8 *controls; @@ -1402,19 +1400,17 @@ uvc_ctrl_prune_entity(struct uvc_entity *entity) size = entity->processing.bControlSize; for (i = 0; i < ARRAY_SIZE(blacklist); ++i) { - if (blacklist[i].idx_auto >= 8 * size || - blacklist[i].idx_manual >= 8 * size) + if (!usb_match_id(dev->intf, &blacklist[i].id)) continue; - if (!uvc_test_bit(controls, blacklist[i].idx_auto) || - uvc_test_bit(controls, blacklist[i].idx_manual)) + if (blacklist[i].index >= 8 * size || + !uvc_test_bit(controls, blacklist[i].index)) continue; - uvc_trace(UVC_TRACE_CONTROL, "Auto control %u/%u has no " - "matching manual control, removing it.\n", entity->id, - blacklist[i].idx_auto); + uvc_trace(UVC_TRACE_CONTROL, "%u/%u control is black listed, " + "removing it.\n", entity->id, blacklist[i].index); - uvc_clear_bit(controls, blacklist[i].idx_auto); + uvc_clear_bit(controls, blacklist[i].index); } } @@ -1444,8 +1440,7 @@ int uvc_ctrl_init_device(struct uvc_device *dev) bControlSize = entity->camera.bControlSize; } - if (dev->quirks & UVC_QUIRK_PRUNE_CONTROLS) - uvc_ctrl_prune_entity(entity); + uvc_ctrl_prune_entity(dev, entity); for (i = 0; i < bControlSize; ++i) ncontrols += hweight8(bmControls[i]); diff --git a/linux/drivers/media/video/uvc/uvc_driver.c b/linux/drivers/media/video/uvc/uvc_driver.c index 8d193376c..1622bca54 100644 --- a/linux/drivers/media/video/uvc/uvc_driver.c +++ b/linux/drivers/media/video/uvc/uvc_driver.c @@ -1948,8 +1948,7 @@ static struct usb_device_id uvc_ids[] = { .bInterfaceSubClass = 1, .bInterfaceProtocol = 0, .driver_info = UVC_QUIRK_PROBE_MINMAX - | UVC_QUIRK_IGNORE_SELECTOR_UNIT - | UVC_QUIRK_PRUNE_CONTROLS }, + | UVC_QUIRK_IGNORE_SELECTOR_UNIT }, /* Generic USB Video Class */ { USB_INTERFACE_INFO(USB_CLASS_VIDEO, 1, 0) }, {} diff --git a/linux/drivers/media/video/uvc/uvcvideo.h b/linux/drivers/media/video/uvc/uvcvideo.h index 6b254fd39..58789fa22 100644 --- a/linux/drivers/media/video/uvc/uvcvideo.h +++ b/linux/drivers/media/video/uvc/uvcvideo.h @@ -314,7 +314,6 @@ struct uvc_xu_control { #define UVC_QUIRK_BUILTIN_ISIGHT 0x00000008 #define UVC_QUIRK_STREAM_NO_FID 0x00000010 #define UVC_QUIRK_IGNORE_SELECTOR_UNIT 0x00000020 -#define UVC_QUIRK_PRUNE_CONTROLS 0x00000040 #define UVC_QUIRK_FIX_BANDWIDTH 0x00000080 /* Format flags */ -- cgit v1.2.3 From b8991839208bf9058df16c5afdc4abe46aed454d Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Sun, 31 May 2009 23:07:01 +0300 Subject: af9015: support for Genius TVGo DVB-T03 From: Antti Palosaari Add USB ID (0458:4012) for Genius TVGo DVB-T03. Thanks to Petr Vodicka for reporting and testing. Priority: normal Signed-off-by: Antti Palosaari Tested-by: Petr Vodicka --- linux/drivers/media/dvb/dvb-usb/af9015.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/af9015.c b/linux/drivers/media/dvb/dvb-usb/af9015.c index 5d9aacd0a..a50bf34af 100644 --- a/linux/drivers/media/dvb/dvb-usb/af9015.c +++ b/linux/drivers/media/dvb/dvb-usb/af9015.c @@ -1268,6 +1268,7 @@ static struct usb_device_id af9015_usb_table[] = { {USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A805)}, {USB_DEVICE(USB_VID_KWORLD_2, USB_PID_CONCEPTRONIC_CTVDIGRCU)}, {USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_MC810)}, + {USB_DEVICE(USB_VID_KYE, USB_PID_GENIUS_TVGO_DVB_T03)}, {0}, }; MODULE_DEVICE_TABLE(usb, af9015_usb_table); @@ -1538,7 +1539,7 @@ static struct dvb_usb_device_properties af9015_properties[] = { .i2c_algo = &af9015_i2c_algo, - .num_device_descs = 3, /* max 9 */ + .num_device_descs = 4, /* max 9 */ .devices = { { .name = "AverMedia AVerTV Volar GPS 805 (A805)", @@ -1556,6 +1557,11 @@ static struct dvb_usb_device_properties af9015_properties[] = { .cold_ids = {&af9015_usb_table[23], NULL}, .warm_ids = {NULL}, }, + { + .name = "Genius TVGo DVB-T03", + .cold_ids = {&af9015_usb_table[24], NULL}, + .warm_ids = {NULL}, + }, } }, }; 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 7340ef4cd..9593b7289 100644 --- a/linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h +++ b/linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h @@ -98,6 +98,7 @@ #define USB_PID_DPOSH_M9206_COLD 0x9206 #define USB_PID_DPOSH_M9206_WARM 0xa090 #define USB_PID_UNIWILL_STK7700P 0x6003 +#define USB_PID_GENIUS_TVGO_DVB_T03 0x4012 #define USB_PID_GRANDTEC_DVBT_USB_COLD 0x0fa0 #define USB_PID_GRANDTEC_DVBT_USB_WARM 0x0fa1 #define USB_PID_INTEL_CE9500 0x9500 -- cgit v1.2.3 From 12f7442713d7eb82fecd42660ef8714f6e7d6e94 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 1 Jun 2009 11:46:08 -0300 Subject: Fix firmware load for DVB-T @ 6MHz From: Mauro Carvalho Chehab bandwidth for xc3028/xc3028L The only two countries that are known to use 6MHz bandwidth are Taiwan and Uruguay. Both use QAM subcarriers at OFTM. This patch fixes the firmware load for such countries, where the required firmware is the QAM one. This also confirms the previous tests where it was noticed that the 6MHz QAM firmware doesn't work for cable. So, this patch also removes support for DVB-C, instead of just printing a warning. Thanks to Terry Wu for pointing this issue and to Andy Walls for an initial patch for this fix. Priority: normal CC: Terry Wu CC: Andy Walls Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/common/tuners/tuner-xc2028.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) (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 cb5b577fa..10becc3c0 100644 --- a/linux/drivers/media/common/tuners/tuner-xc2028.c +++ b/linux/drivers/media/common/tuners/tuner-xc2028.c @@ -1026,21 +1026,20 @@ static int xc2028_set_params(struct dvb_frontend *fe, switch(fe->ops.info.type) { case FE_OFDM: bw = p->u.ofdm.bandwidth; - break; - case FE_QAM: - tuner_info("WARN: There are some reports that " - "QAM 6 MHz doesn't work.\n" - "If this works for you, please report by " - "e-mail to: v4l-dvb-maintainer@linuxtv.org\n"); - bw = BANDWIDTH_6_MHZ; - type |= QAM; + /* + * The only countries with 6MHz seem to be Taiwan/Uruguay. + * Both seem to require QAM firmware for OFDM decoding + * Tested in Taiwan by Terry Wu + */ + if (bw == BANDWIDTH_6_MHZ) + type |= QAM; break; case FE_ATSC: bw = BANDWIDTH_6_MHZ; /* The only ATSC firmware (at least on v2.7) is D2633 */ type |= ATSC | D2633; break; - /* DVB-S is not supported */ + /* DVB-S and pure QAM (FE_QAM) are not supported */ default: return -EINVAL; } -- cgit v1.2.3 From 3cfc0ea022a646fa73ba82352c3a95af859c20f6 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 1 Jun 2009 12:18:10 -0300 Subject: tuner-xc2028: Fix offset frequencies for DVB @ 6MHz From: Mauro Carvalho Chehab Both ATSC and DVB @ 6MHz bandwidth require the same offset. While we're fixing it, let's cleanup the bandwidth setup to better reflect the fact that it is a function of the bandwidth. Thanks to Terry Wu for pointing this issue and to Andy Walls for an initial patch for this fix. Priority: normal CC: Terry Wu CC: Andy Walls Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/common/tuners/tuner-xc2028.c | 32 ++++++++++++++---------- 1 file changed, 19 insertions(+), 13 deletions(-) (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 10becc3c0..493e8d642 100644 --- a/linux/drivers/media/common/tuners/tuner-xc2028.c +++ b/linux/drivers/media/common/tuners/tuner-xc2028.c @@ -921,22 +921,28 @@ static int generic_set_freq(struct dvb_frontend *fe, u32 freq /* in HZ */, * that xc2028 will be in a safe state. * Maybe this might also be needed for DTV. */ - if (new_mode == T_ANALOG_TV) { + if (new_mode == T_ANALOG_TV) rc = send_seq(priv, {0x00, 0x00}); - } else if (priv->cur_fw.type & ATSC) { - offset = 1750000; - } else { - offset = 2750000; + + /* + * Digital modes require an offset to adjust to the + * proper frequency + */ + if (new_mode != T_ANALOG_TV) { + /* Sets the offset according with firmware */ + if (priv->cur_fw.type & DTV6) + offset = 1750000; + if (priv->cur_fw.type & DTV7) + offset = 2250000; + else /* DTV8 or DTV78 */ + offset = 2750000; + /* - * We must adjust the offset by 500kHz in two cases in order - * to correctly center the IF output: - * 1) When the ZARLINK456 or DIBCOM52 tables were explicitly - * selected and a 7MHz channel is tuned; - * 2) When tuning a VHF channel with DTV78 firmware. + * We must adjust the offset by 500kHz when + * tuning a 7MHz VHF channel with DTV78 firmware + * (used in Australia) */ - if (((priv->cur_fw.type & DTV7) && - (priv->cur_fw.scode_table & (ZARLINK456 | DIBCOM52))) || - ((priv->cur_fw.type & DTV78) && freq < 470000000)) + if ((priv->cur_fw.type & DTV78) && freq < 470000000) offset -= 500000; } -- cgit v1.2.3 From dafdda930b528f67343d34c87492d060919195a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20Andr=C3=A9n?= Date: Mon, 1 Jun 2009 21:22:18 +0200 Subject: gspca - m5602-ov9650: Add vflip quirk for the ASUS A6VA MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: Erik Andrén Add vflip quirk for the ASUS A6VA. Thanks to Salvo Di Rosa for reporting. Priority: normal Signed-off-by: Erik Andrén --- linux/drivers/media/video/gspca/m5602/m5602_ov9650.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c index bbf9935df..bd32fe827 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c @@ -96,6 +96,13 @@ static DMI_MATCH(DMI_PRODUCT_NAME, "A6K") } }, + { + .ident = "ASUS A6VA", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "A6VA") + } + }, { .ident = "Alienware Aurora m9700", .matches = { -- cgit v1.2.3 From b49e742345a086611441cc31b1b0041f1fe7051d Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 1 Jun 2009 22:34:20 -0300 Subject: tuner-xc3028: fix frequency offset From: Mauro Carvalho Chehab The last changeset has an else missing, causing wrong frequencies for DTV6. Thanks to Terry Wu for pointing the issue. Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/common/tuners/tuner-xc2028.c | 2 +- linux/drivers/media/video/cx88/cx88-cards.c | 95 +++++++++++++++++++----- 2 files changed, 77 insertions(+), 20 deletions(-) (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 493e8d642..c98a628e8 100644 --- a/linux/drivers/media/common/tuners/tuner-xc2028.c +++ b/linux/drivers/media/common/tuners/tuner-xc2028.c @@ -932,7 +932,7 @@ static int generic_set_freq(struct dvb_frontend *fe, u32 freq /* in HZ */, /* Sets the offset according with firmware */ if (priv->cur_fw.type & DTV6) offset = 1750000; - if (priv->cur_fw.type & DTV7) + else if (priv->cur_fw.type & DTV7) offset = 2250000; else /* DTV8 or DTV78 */ offset = 2750000; diff --git a/linux/drivers/media/video/cx88/cx88-cards.c b/linux/drivers/media/video/cx88/cx88-cards.c index 825b1f25d..64ee8cac2 100644 --- a/linux/drivers/media/video/cx88/cx88-cards.c +++ b/linux/drivers/media/video/cx88/cx88-cards.c @@ -1557,33 +1557,45 @@ static const struct cx88_board cx88_boards[] = { }, .mpeg = CX88_MPEG_DVB, }, + /* Terry Wu */ + /* TV Audio : set GPIO 2, 18, 19 value to 0, 1, 0 */ + /* FM Audio : set GPIO 2, 18, 19 value to 0, 0, 0 */ + /* Line-in Audio : set GPIO 2, 18, 19 value to 0, 1, 1 */ + /* Mute Audio : set GPIO 2 value to 1 */ [CX88_BOARD_WINFAST_TV2000_XP_GLOBAL] = { - .name = "Winfast TV2000 XP Global", + .name = "Leadtek TV2000 XP Global", .tuner_type = TUNER_XC2028, .tuner_addr = 0x61, + .radio_type = TUNER_XC2028, + .radio_addr = 0x61, .input = { { .type = CX88_VMUX_TELEVISION, .vmux = 0, - .gpio0 = 0x0400, /* pin 2:mute = 0 (off?) */ + .gpio0 = 0x0400, /* pin 2 = 0 */ .gpio1 = 0x0000, - .gpio2 = 0x0800, /* pin 19:audio = 0 (tv) */ - + .gpio2 = 0x0C04, /* pin 18 = 1, pin 19 = 0 */ + .gpio3 = 0x0000, }, { .type = CX88_VMUX_COMPOSITE1, .vmux = 1, - .gpio0 = 0x0400, /* probably? or 0x0404 to turn mute on */ + .gpio0 = 0x0400, /* pin 2 = 0 */ .gpio1 = 0x0000, - .gpio2 = 0x0808, /* pin 19:audio = 1 (line) */ - + .gpio2 = 0x0C0C, /* pin 18 = 1, pin 19 = 1 */ + .gpio3 = 0x0000, }, { .type = CX88_VMUX_SVIDEO, .vmux = 2, + .gpio0 = 0x0400, /* pin 2 = 0 */ + .gpio1 = 0x0000, + .gpio2 = 0x0C0C, /* pin 18 = 1, pin 19 = 1 */ + .gpio3 = 0x0000, } }, .radio = { .type = CX88_RADIO, - .gpio0 = 0x004ff, - .gpio1 = 0x010ff, - .gpio2 = 0x0ff, + .gpio0 = 0x0400, /* pin 2 = 0 */ + .gpio1 = 0x0000, + .gpio2 = 0x0C00, /* pin 18 = 0, pin 19 = 0 */ + .gpio3 = 0x0000, }, }, [CX88_BOARD_POWERCOLOR_REAL_ANGEL] = { @@ -2471,6 +2483,41 @@ static const struct cx88_subid cx88_subids[] = { .subvendor = 0x107d, .subdevice = 0x6654, .card = CX88_BOARD_WINFAST_DTV1800H, + },{ + /* PVR2000 PAL Model [107d:6630] */ + .subvendor = 0x107d, + .subdevice = 0x6630, + .card = CX88_BOARD_LEADTEK_PVR2000, + }, { + /* PVR2000 PAL Model [107d:6638] */ + .subvendor = 0x107d, + .subdevice = 0x6638, + .card = CX88_BOARD_LEADTEK_PVR2000, + }, { + /* PVR2000 NTSC Model [107d:6631] */ + .subvendor = 0x107d, + .subdevice = 0x6631, + .card = CX88_BOARD_LEADTEK_PVR2000, + }, { + /* PVR2000 NTSC Model [107d:6637] */ + .subvendor = 0x107d, + .subdevice = 0x6637, + .card = CX88_BOARD_LEADTEK_PVR2000, + }, { + /* PVR2000 NTSC Model [107d:663d] */ + .subvendor = 0x107d, + .subdevice = 0x663d, + .card = CX88_BOARD_LEADTEK_PVR2000, + }, { + /* DV2000 NTSC Model [107d:6621] */ + .subvendor = 0x107d, + .subdevice = 0x6621, + .card = CX88_BOARD_WINFAST_DV2000, + }, { + /* TV2000 XP Global [107d:6618] */ + .subvendor = 0x107d, + .subdevice = 0x6618, + .card = CX88_BOARD_WINFAST_TV2000_XP_GLOBAL, }, }; @@ -2479,12 +2526,6 @@ static const struct cx88_subid cx88_subids[] = { static void leadtek_eeprom(struct cx88_core *core, u8 *eeprom_data) { - /* This is just for the "Winfast 2000XP Expert" board ATM; I don't have data on - * any others. - * - * Byte 0 is 1 on the NTSC board. - */ - if (eeprom_data[4] != 0x7d || eeprom_data[5] != 0x10 || eeprom_data[7] != 0x66) { @@ -2492,8 +2533,20 @@ static void leadtek_eeprom(struct cx88_core *core, u8 *eeprom_data) return; } - core->board.tuner_type = (eeprom_data[6] == 0x13) ? - TUNER_PHILIPS_FM1236_MK3 : TUNER_PHILIPS_FM1216ME_MK3; + /* Terry Wu */ + switch (eeprom_data[6]) + { + case 0x13: /* SSID 6613 for TV2000 XP Expert NTSC Model */ + case 0x21: /* SSID 6621 for DV2000 NTSC Model */ + case 0x31: /* SSID 6631 for PVR2000 NTSC Model */ + case 0x37: /* SSID 6637 for PVR2000 NTSC Model */ + case 0x3d: /* SSID 6637 for PVR2000 NTSC Model */ + core->board.tuner_type = TUNER_PHILIPS_FM1236_MK3; + break; + default: + core->board.tuner_type = TUNER_PHILIPS_FM1216ME_MK3; + break; + } info_printk(core, "Leadtek Winfast 2000XP Expert config: " "tuner=%d, eeprom[0]=0x%02x\n", @@ -2746,7 +2799,6 @@ static int cx88_xc2028_tuner_callback(struct cx88_core *core, { /* Board-specific callbacks */ switch (core->boardnr) { - case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL: case CX88_BOARD_POWERCOLOR_REAL_ANGEL: case CX88_BOARD_GENIATECH_X8000_MT: case CX88_BOARD_KWORLD_ATSC_120: @@ -2758,6 +2810,7 @@ static int cx88_xc2028_tuner_callback(struct cx88_core *core, case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO: case CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO: return cx88_dvico_xc2028_callback(core, command, arg); + case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL: case CX88_BOARD_WINFAST_DTV1800H: return cx88_xc3028_winfast1800h_callback(core, command, arg); } @@ -2947,6 +3000,7 @@ static void cx88_card_setup_pre_i2c(struct cx88_core *core) udelay(1000); break; + case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL: case CX88_BOARD_WINFAST_DTV1800H: /* GPIO 12 (xc3028 tuner reset) */ cx_set(MO_GP1_IO, 0x1010); @@ -2983,6 +3037,7 @@ void cx88_setup_xc3028(struct cx88_core *core, struct xc2028_ctrl *ctl) case CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO: ctl->demod = XC3028_FE_OREN538; break; + case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL: case CX88_BOARD_PROLINK_PV_GLOBAL_XTREME: case CX88_BOARD_PROLINK_PV_8000GT: /* @@ -3026,6 +3081,8 @@ static void cx88_card_setup(struct cx88_core *core) if (0 == core->i2c_rc) gdi_eeprom(core, eeprom); break; + case CX88_BOARD_LEADTEK_PVR2000: + case CX88_BOARD_WINFAST_DV2000: case CX88_BOARD_WINFAST2000XP_EXPERT: if (0 == core->i2c_rc) leadtek_eeprom(core, eeprom); -- cgit v1.2.3 From edb804f93fd68c190d3c43e606f31c806343d647 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 3 Jun 2009 02:01:04 +0000 Subject: buf-core.c: add pointer check From: Figo.zhang add poiter check for videobuf_queue_core_init(). any guys who write a v4l driver, pass a NULL pointer or a non-inintial pointer to the first parameter such as videobuf_queue_sg_init() , it would be crashed. Signed-off-by: Figo.zhang Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/videobuf-core.c | 1 + 1 file changed, 1 insertion(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/videobuf-core.c b/linux/drivers/media/video/videobuf-core.c index e9696385d..faf912403 100644 --- a/linux/drivers/media/video/videobuf-core.c +++ b/linux/drivers/media/video/videobuf-core.c @@ -119,6 +119,7 @@ void videobuf_queue_core_init(struct videobuf_queue *q, void *priv, struct videobuf_qtype_ops *int_ops) { + BUG_ON(!q); memset(q, 0, sizeof(*q)); q->irqlock = irqlock; q->dev = dev; -- cgit v1.2.3 From 054fa57e4d628733bccc6deff5fb9497c0620d34 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 3 Jun 2009 02:00:43 -0300 Subject: Partially backport changeset 5ec629d784ad From: Mauro Carvalho Chehab By mistake, I've committed a changeset that it is not done yet together with a fix. Revert the broken part of the old changeset. Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/cx88/cx88-cards.c | 95 ++++++----------------------- 1 file changed, 19 insertions(+), 76 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 64ee8cac2..825b1f25d 100644 --- a/linux/drivers/media/video/cx88/cx88-cards.c +++ b/linux/drivers/media/video/cx88/cx88-cards.c @@ -1557,45 +1557,33 @@ static const struct cx88_board cx88_boards[] = { }, .mpeg = CX88_MPEG_DVB, }, - /* Terry Wu */ - /* TV Audio : set GPIO 2, 18, 19 value to 0, 1, 0 */ - /* FM Audio : set GPIO 2, 18, 19 value to 0, 0, 0 */ - /* Line-in Audio : set GPIO 2, 18, 19 value to 0, 1, 1 */ - /* Mute Audio : set GPIO 2 value to 1 */ [CX88_BOARD_WINFAST_TV2000_XP_GLOBAL] = { - .name = "Leadtek TV2000 XP Global", + .name = "Winfast TV2000 XP Global", .tuner_type = TUNER_XC2028, .tuner_addr = 0x61, - .radio_type = TUNER_XC2028, - .radio_addr = 0x61, .input = { { .type = CX88_VMUX_TELEVISION, .vmux = 0, - .gpio0 = 0x0400, /* pin 2 = 0 */ + .gpio0 = 0x0400, /* pin 2:mute = 0 (off?) */ .gpio1 = 0x0000, - .gpio2 = 0x0C04, /* pin 18 = 1, pin 19 = 0 */ - .gpio3 = 0x0000, + .gpio2 = 0x0800, /* pin 19:audio = 0 (tv) */ + }, { .type = CX88_VMUX_COMPOSITE1, .vmux = 1, - .gpio0 = 0x0400, /* pin 2 = 0 */ + .gpio0 = 0x0400, /* probably? or 0x0404 to turn mute on */ .gpio1 = 0x0000, - .gpio2 = 0x0C0C, /* pin 18 = 1, pin 19 = 1 */ - .gpio3 = 0x0000, + .gpio2 = 0x0808, /* pin 19:audio = 1 (line) */ + }, { .type = CX88_VMUX_SVIDEO, .vmux = 2, - .gpio0 = 0x0400, /* pin 2 = 0 */ - .gpio1 = 0x0000, - .gpio2 = 0x0C0C, /* pin 18 = 1, pin 19 = 1 */ - .gpio3 = 0x0000, } }, .radio = { .type = CX88_RADIO, - .gpio0 = 0x0400, /* pin 2 = 0 */ - .gpio1 = 0x0000, - .gpio2 = 0x0C00, /* pin 18 = 0, pin 19 = 0 */ - .gpio3 = 0x0000, + .gpio0 = 0x004ff, + .gpio1 = 0x010ff, + .gpio2 = 0x0ff, }, }, [CX88_BOARD_POWERCOLOR_REAL_ANGEL] = { @@ -2483,41 +2471,6 @@ static const struct cx88_subid cx88_subids[] = { .subvendor = 0x107d, .subdevice = 0x6654, .card = CX88_BOARD_WINFAST_DTV1800H, - },{ - /* PVR2000 PAL Model [107d:6630] */ - .subvendor = 0x107d, - .subdevice = 0x6630, - .card = CX88_BOARD_LEADTEK_PVR2000, - }, { - /* PVR2000 PAL Model [107d:6638] */ - .subvendor = 0x107d, - .subdevice = 0x6638, - .card = CX88_BOARD_LEADTEK_PVR2000, - }, { - /* PVR2000 NTSC Model [107d:6631] */ - .subvendor = 0x107d, - .subdevice = 0x6631, - .card = CX88_BOARD_LEADTEK_PVR2000, - }, { - /* PVR2000 NTSC Model [107d:6637] */ - .subvendor = 0x107d, - .subdevice = 0x6637, - .card = CX88_BOARD_LEADTEK_PVR2000, - }, { - /* PVR2000 NTSC Model [107d:663d] */ - .subvendor = 0x107d, - .subdevice = 0x663d, - .card = CX88_BOARD_LEADTEK_PVR2000, - }, { - /* DV2000 NTSC Model [107d:6621] */ - .subvendor = 0x107d, - .subdevice = 0x6621, - .card = CX88_BOARD_WINFAST_DV2000, - }, { - /* TV2000 XP Global [107d:6618] */ - .subvendor = 0x107d, - .subdevice = 0x6618, - .card = CX88_BOARD_WINFAST_TV2000_XP_GLOBAL, }, }; @@ -2526,6 +2479,12 @@ static const struct cx88_subid cx88_subids[] = { static void leadtek_eeprom(struct cx88_core *core, u8 *eeprom_data) { + /* This is just for the "Winfast 2000XP Expert" board ATM; I don't have data on + * any others. + * + * Byte 0 is 1 on the NTSC board. + */ + if (eeprom_data[4] != 0x7d || eeprom_data[5] != 0x10 || eeprom_data[7] != 0x66) { @@ -2533,20 +2492,8 @@ static void leadtek_eeprom(struct cx88_core *core, u8 *eeprom_data) return; } - /* Terry Wu */ - switch (eeprom_data[6]) - { - case 0x13: /* SSID 6613 for TV2000 XP Expert NTSC Model */ - case 0x21: /* SSID 6621 for DV2000 NTSC Model */ - case 0x31: /* SSID 6631 for PVR2000 NTSC Model */ - case 0x37: /* SSID 6637 for PVR2000 NTSC Model */ - case 0x3d: /* SSID 6637 for PVR2000 NTSC Model */ - core->board.tuner_type = TUNER_PHILIPS_FM1236_MK3; - break; - default: - core->board.tuner_type = TUNER_PHILIPS_FM1216ME_MK3; - break; - } + core->board.tuner_type = (eeprom_data[6] == 0x13) ? + TUNER_PHILIPS_FM1236_MK3 : TUNER_PHILIPS_FM1216ME_MK3; info_printk(core, "Leadtek Winfast 2000XP Expert config: " "tuner=%d, eeprom[0]=0x%02x\n", @@ -2799,6 +2746,7 @@ static int cx88_xc2028_tuner_callback(struct cx88_core *core, { /* Board-specific callbacks */ switch (core->boardnr) { + case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL: case CX88_BOARD_POWERCOLOR_REAL_ANGEL: case CX88_BOARD_GENIATECH_X8000_MT: case CX88_BOARD_KWORLD_ATSC_120: @@ -2810,7 +2758,6 @@ static int cx88_xc2028_tuner_callback(struct cx88_core *core, case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO: case CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO: return cx88_dvico_xc2028_callback(core, command, arg); - case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL: case CX88_BOARD_WINFAST_DTV1800H: return cx88_xc3028_winfast1800h_callback(core, command, arg); } @@ -3000,7 +2947,6 @@ static void cx88_card_setup_pre_i2c(struct cx88_core *core) udelay(1000); break; - case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL: case CX88_BOARD_WINFAST_DTV1800H: /* GPIO 12 (xc3028 tuner reset) */ cx_set(MO_GP1_IO, 0x1010); @@ -3037,7 +2983,6 @@ void cx88_setup_xc3028(struct cx88_core *core, struct xc2028_ctrl *ctl) case CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO: ctl->demod = XC3028_FE_OREN538; break; - case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL: case CX88_BOARD_PROLINK_PV_GLOBAL_XTREME: case CX88_BOARD_PROLINK_PV_8000GT: /* @@ -3081,8 +3026,6 @@ static void cx88_card_setup(struct cx88_core *core) if (0 == core->i2c_rc) gdi_eeprom(core, eeprom); break; - case CX88_BOARD_LEADTEK_PVR2000: - case CX88_BOARD_WINFAST_DV2000: case CX88_BOARD_WINFAST2000XP_EXPERT: if (0 == core->i2c_rc) leadtek_eeprom(core, eeprom); -- cgit v1.2.3 From 2e4dae3dad6d21fbd5ce4b97f4724ab1a830af8c Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 3 Jun 2009 02:27:34 -0300 Subject: tuner-xc2028: Improve comments, based on Andy Walls and Hermann Pitton From: Mauro Carvalho Chehab feedback CC: Andy Walls CC: Hermann Pitton Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/common/tuners/tuner-xc2028.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (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 c98a628e8..083e62723 100644 --- a/linux/drivers/media/common/tuners/tuner-xc2028.c +++ b/linux/drivers/media/common/tuners/tuner-xc2028.c @@ -926,7 +926,8 @@ static int generic_set_freq(struct dvb_frontend *fe, u32 freq /* in HZ */, /* * Digital modes require an offset to adjust to the - * proper frequency + * proper frequency. + * Analog modes require offset = 0 */ if (new_mode != T_ANALOG_TV) { /* Sets the offset according with firmware */ @@ -940,7 +941,7 @@ static int generic_set_freq(struct dvb_frontend *fe, u32 freq /* in HZ */, /* * We must adjust the offset by 500kHz when * tuning a 7MHz VHF channel with DTV78 firmware - * (used in Australia) + * (used in Australia, Italy and Germany) */ if ((priv->cur_fw.type & DTV78) && freq < 470000000) offset -= 500000; -- cgit v1.2.3 From 2534dbc36b3ce8468ed85ed58818d4dcddaec092 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Thu, 4 Jun 2009 14:26:39 +0200 Subject: uvcvideo: Don't accept to change the format when buffers are allocated. From: Laurent Pinchart Setting a new frame format or size will likely change the buffer size required to store a complete video frame. To avoid a buffer overflow, don't allow VIDIOC_S_FMT calls when video buffers are already allocated. Priority: normal Signed-off-by: Laurent Pinchart --- linux/drivers/media/video/uvc/uvc_queue.c | 14 ++++++++++++++ linux/drivers/media/video/uvc/uvc_v4l2.c | 2 +- linux/drivers/media/video/uvc/uvcvideo.h | 1 + 3 files changed, 16 insertions(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/uvc/uvc_queue.c b/linux/drivers/media/video/uvc/uvc_queue.c index 0155752e4..f854698c4 100644 --- a/linux/drivers/media/video/uvc/uvc_queue.c +++ b/linux/drivers/media/video/uvc/uvc_queue.c @@ -172,6 +172,20 @@ int uvc_free_buffers(struct uvc_video_queue *queue) return 0; } +/* + * Check if buffers have been allocated. + */ +int uvc_queue_allocated(struct uvc_video_queue *queue) +{ + int allocated; + + mutex_lock(&queue->mutex); + allocated = queue->count != 0; + mutex_unlock(&queue->mutex); + + return allocated; +} + static void __uvc_query_buffer(struct uvc_buffer *buf, struct v4l2_buffer *v4l2_buf) { diff --git a/linux/drivers/media/video/uvc/uvc_v4l2.c b/linux/drivers/media/video/uvc/uvc_v4l2.c index 160c01314..736d8ae23 100644 --- a/linux/drivers/media/video/uvc/uvc_v4l2.c +++ b/linux/drivers/media/video/uvc/uvc_v4l2.c @@ -251,7 +251,7 @@ static int uvc_v4l2_set_format(struct uvc_video_device *video, if (fmt->type != video->streaming->type) return -EINVAL; - if (uvc_queue_streaming(&video->queue)) + if (uvc_queue_allocated(&video->queue)) return -EBUSY; ret = uvc_v4l2_try_format(video, fmt, &probe, &format, &frame); diff --git a/linux/drivers/media/video/uvc/uvcvideo.h b/linux/drivers/media/video/uvc/uvcvideo.h index 58789fa22..de13c86f2 100644 --- a/linux/drivers/media/video/uvc/uvcvideo.h +++ b/linux/drivers/media/video/uvc/uvcvideo.h @@ -748,6 +748,7 @@ extern struct uvc_buffer *uvc_queue_next_buffer(struct uvc_video_queue *queue, struct uvc_buffer *buf); extern unsigned int uvc_queue_poll(struct uvc_video_queue *queue, struct file *file, poll_table *wait); +extern int uvc_queue_allocated(struct uvc_video_queue *queue); static inline int uvc_queue_streaming(struct uvc_video_queue *queue) { return queue->flags & UVC_QUEUE_STREAMING; -- cgit v1.2.3 From 337800edfc26abd2a7b3a13733836f35244d8ca5 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 4 Jun 2009 14:07:16 +0000 Subject: Add missing __devexit_p() From: Jean Delvare Add missing __devexit_p() to several drivers. Also add a few missing __init, __devinit and __exit markers. These errors could result in build failures depending on the kernel configuration. Signed-off-by: Jean Delvare Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/bt8xx/bt878.c | 8 +------- linux/drivers/media/video/cx88/cx88-alsa.c | 7 +++---- linux/drivers/media/video/mx3_camera.c | 6 +++--- linux/drivers/media/video/pxa_camera.c | 6 +++--- linux/drivers/media/video/soc_camera.c | 2 +- linux/drivers/media/video/usbvision/usbvision-video.c | 2 +- linux/drivers/media/video/zoran/zoran_card.c | 2 +- 7 files changed, 13 insertions(+), 20 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/bt8xx/bt878.c b/linux/drivers/media/dvb/bt8xx/bt878.c index 57f0f84b6..456cd8756 100644 --- a/linux/drivers/media/dvb/bt8xx/bt878.c +++ b/linux/drivers/media/dvb/bt8xx/bt878.c @@ -512,12 +512,6 @@ static int __devinit bt878_probe(struct pci_dev *dev, pci_set_master(dev); pci_set_drvdata(dev, bt); -/* if(init_bt878(btv) < 0) { - bt878_remove(dev); - return -EIO; - } -*/ - if ((result = bt878_mem_alloc(bt))) { printk(KERN_ERR "bt878: failed to allocate memory!\n"); goto fail2; @@ -583,7 +577,7 @@ static struct pci_driver bt878_pci_driver = { .name = "bt878", .id_table = bt878_pci_tbl, .probe = bt878_probe, - .remove = bt878_remove, + .remove = __devexit_p(bt878_remove), }; static int bt878_pci_driver_registered; diff --git a/linux/drivers/media/video/cx88/cx88-alsa.c b/linux/drivers/media/video/cx88/cx88-alsa.c index 077c9f0d7..4b9f1bb22 100644 --- a/linux/drivers/media/video/cx88/cx88-alsa.c +++ b/linux/drivers/media/video/cx88/cx88-alsa.c @@ -939,7 +939,7 @@ static struct pci_driver cx88_audio_pci_driver = { .name = "cx88_audio", .id_table = cx88_audio_pci_tbl, .probe = cx88_audio_initdev, - .remove = cx88_audio_finidev, + .remove = __devexit_p(cx88_audio_finidev), }; /**************************************************************************** @@ -949,7 +949,7 @@ static struct pci_driver cx88_audio_pci_driver = { /* * module init */ -static int cx88_audio_init(void) +static int __init cx88_audio_init(void) { printk(KERN_INFO "cx2388x alsa driver version %d.%d.%d loaded\n", (CX88_VERSION_CODE >> 16) & 0xff, @@ -965,9 +965,8 @@ static int cx88_audio_init(void) /* * module remove */ -static void cx88_audio_fini(void) +static void __exit cx88_audio_fini(void) { - pci_unregister_driver(&cx88_audio_pci_driver); } diff --git a/linux/drivers/media/video/mx3_camera.c b/linux/drivers/media/video/mx3_camera.c index 4d47eeb14..e605c076e 100644 --- a/linux/drivers/media/video/mx3_camera.c +++ b/linux/drivers/media/video/mx3_camera.c @@ -1074,7 +1074,7 @@ static struct soc_camera_host_ops mx3_soc_camera_host_ops = { .set_bus_param = mx3_camera_set_bus_param, }; -static int mx3_camera_probe(struct platform_device *pdev) +static int __devinit mx3_camera_probe(struct platform_device *pdev) { struct mx3_camera_dev *mx3_cam; struct resource *res; @@ -1194,11 +1194,11 @@ static struct platform_driver mx3_camera_driver = { .name = MX3_CAM_DRV_NAME, }, .probe = mx3_camera_probe, - .remove = __exit_p(mx3_camera_remove), + .remove = __devexit_p(mx3_camera_remove), }; -static int __devinit mx3_camera_init(void) +static int __init mx3_camera_init(void) { return platform_driver_register(&mx3_camera_driver); } diff --git a/linux/drivers/media/video/pxa_camera.c b/linux/drivers/media/video/pxa_camera.c index 2c122ec90..7578d0cfe 100644 --- a/linux/drivers/media/video/pxa_camera.c +++ b/linux/drivers/media/video/pxa_camera.c @@ -1541,7 +1541,7 @@ static struct soc_camera_host_ops pxa_soc_camera_host_ops = { .set_bus_param = pxa_camera_set_bus_param, }; -static int pxa_camera_probe(struct platform_device *pdev) +static int __devinit pxa_camera_probe(struct platform_device *pdev) { struct pxa_camera_dev *pcdev; struct resource *res; @@ -1716,11 +1716,11 @@ static struct platform_driver pxa_camera_driver = { .name = PXA_CAM_DRV_NAME, }, .probe = pxa_camera_probe, - .remove = __exit_p(pxa_camera_remove), + .remove = __devexit_p(pxa_camera_remove), }; -static int __devinit pxa_camera_init(void) +static int __init pxa_camera_init(void) { return platform_driver_register(&pxa_camera_driver); } diff --git a/linux/drivers/media/video/soc_camera.c b/linux/drivers/media/video/soc_camera.c index 822052b25..e4056a9c2 100644 --- a/linux/drivers/media/video/soc_camera.c +++ b/linux/drivers/media/video/soc_camera.c @@ -1206,7 +1206,7 @@ static int __devexit soc_camera_pdrv_remove(struct platform_device *pdev) static struct platform_driver __refdata soc_camera_pdrv = { .probe = soc_camera_pdrv_probe, - .remove = __exit_p(soc_camera_pdrv_remove), + .remove = __devexit_p(soc_camera_pdrv_remove), .driver = { .name = "soc-camera-pdrv", .owner = THIS_MODULE, diff --git a/linux/drivers/media/video/usbvision/usbvision-video.c b/linux/drivers/media/video/usbvision/usbvision-video.c index d03e5922d..90b58914f 100644 --- a/linux/drivers/media/video/usbvision/usbvision-video.c +++ b/linux/drivers/media/video/usbvision/usbvision-video.c @@ -1794,7 +1794,7 @@ static struct usb_driver usbvision_driver = { .name = "usbvision", .id_table = usbvision_table, .probe = usbvision_probe, - .disconnect = usbvision_disconnect + .disconnect = __devexit_p(usbvision_disconnect), }; /* diff --git a/linux/drivers/media/video/zoran/zoran_card.c b/linux/drivers/media/video/zoran/zoran_card.c index 67ab10878..85f63116d 100644 --- a/linux/drivers/media/video/zoran/zoran_card.c +++ b/linux/drivers/media/video/zoran/zoran_card.c @@ -1478,7 +1478,7 @@ static struct pci_driver zoran_driver = { .name = "zr36067", .id_table = zr36067_pci_tbl, .probe = zoran_probe, - .remove = zoran_remove, + .remove = __devexit_p(zoran_remove), }; static int __init zoran_init(void) -- cgit v1.2.3 From 4a8ec05c873aa6247954e168931f9937c948a6cc Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 4 Jun 2009 19:18:13 +0000 Subject: V4L/pwc - use usb_interface as parent, not usb_device From: Lennart Poettering The current code creates a sysfs device path where the video4linux device is child of the usb device itself instead of the interface it belongs to. That is evil and confuses udev. This patch does basically the same thing as Kay's similar patch for the ov511 driver: http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commitdiff;h=ce96d0a44a4f8d1bb3dc12b5e98cb688c1bc730d Signed-off-by: Lennart Poettering Acked-by: Hans de Goede Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/pwc/pwc-if.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/pwc/pwc-if.c b/linux/drivers/media/video/pwc/pwc-if.c index eaeea5520..4087612ee 100644 --- a/linux/drivers/media/video/pwc/pwc-if.c +++ b/linux/drivers/media/video/pwc/pwc-if.c @@ -1791,7 +1791,7 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id return -ENOMEM; } memcpy(pdev->vdev, &pwc_template, sizeof(pwc_template)); - pdev->vdev->parent = &(udev->dev); + pdev->vdev->parent = &intf->dev; strcpy(pdev->vdev->name, name); video_set_drvdata(pdev->vdev, pdev); -- cgit v1.2.3 From e3f49481ec12d850c2290cad0d7ebd61b0e8d8e6 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 5 Jun 2009 10:56:18 +0000 Subject: ivtv: Fix PCI direction From: Alan Cox The ivtv stream buffers may be for receive or for send but the attached sg handle is always destined cpu->device. We flush it correctly but the allocation is wrongly done with the same type as the buffers. See bug: http://bugzilla.kernel.org/show_bug.cgi?id=13385 (Note this doesn't close the bug - it fixes the ivtv part and in turn the logging next shows up some rather alarming DMA sg list warnings in libata) Signed-off-by: Alan Cox Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/ivtv/ivtv-queue.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/ivtv/ivtv-queue.c b/linux/drivers/media/video/ivtv/ivtv-queue.c index ff7b7dede..7fde36e6d 100644 --- a/linux/drivers/media/video/ivtv/ivtv-queue.c +++ b/linux/drivers/media/video/ivtv/ivtv-queue.c @@ -230,7 +230,8 @@ int ivtv_stream_alloc(struct ivtv_stream *s) return -ENOMEM; } if (ivtv_might_use_dma(s)) { - s->sg_handle = pci_map_single(itv->pdev, s->sg_dma, sizeof(struct ivtv_sg_element), s->dma); + s->sg_handle = pci_map_single(itv->pdev, s->sg_dma, + sizeof(struct ivtv_sg_element), PCI_DMA_TODEVICE); ivtv_stream_sync_for_cpu(s); } -- cgit v1.2.3 From 66d1ec994cb3e98d73a7847d6cd516aceebd6fdf Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 6 Jun 2009 09:16:21 +0000 Subject: zr364xx.c: vfree does its own NULL check From: Figo.zhang vfree() does it's own NULL checking, no need for explicit check before calling it. Signed-off-by: Figo.zhang Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/zr364xx.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/zr364xx.c b/linux/drivers/media/video/zr364xx.c index b8f47acab..8746f067d 100644 --- a/linux/drivers/media/video/zr364xx.c +++ b/linux/drivers/media/video/zr364xx.c @@ -883,9 +883,11 @@ static void zr364xx_disconnect(struct usb_interface *intf) video_unregister_device(cam->vdev); cam->vdev = NULL; kfree(cam->buffer); - if (cam->framebuf) - vfree(cam->framebuf); + cam->buffer = NULL; + vfree(cam->framebuf); + cam->framebuf = NULL; kfree(cam); + cam = NULL; } -- cgit v1.2.3 From d336dddd42e43b5465cd58b5a4812011805905df Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 6 Jun 2009 08:15:08 -0300 Subject: tuner-xc2028: cleanup: better use tuner typpe defines From: Mauro Carvalho Chehab Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/common/tuners/tuner-xc2028.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (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 083e62723..a7466867c 100644 --- a/linux/drivers/media/common/tuners/tuner-xc2028.c +++ b/linux/drivers/media/common/tuners/tuner-xc2028.c @@ -929,7 +929,7 @@ static int generic_set_freq(struct dvb_frontend *fe, u32 freq /* in HZ */, * proper frequency. * Analog modes require offset = 0 */ - if (new_mode != T_ANALOG_TV) { + if (new_mode == T_DIGITAL_TV) { /* Sets the offset according with firmware */ if (priv->cur_fw.type & DTV6) offset = 1750000; @@ -1002,7 +1002,7 @@ static int xc2028_set_analog_freq(struct dvb_frontend *fe, if (priv->ctrl.input1) type |= INPUT1; return generic_set_freq(fe, (625l * p->frequency) / 10, - T_ANALOG_TV, type, 0, 0); + T_RADIO, type, 0, 0); } /* if std is not defined, choose one */ -- cgit v1.2.3 From 7ef1e386396d4ebc645310511099bf2526e519c4 Mon Sep 17 00:00:00 2001 From: Abylay Ospan Date: Sat, 6 Jun 2009 16:31:34 +0400 Subject: TS continuity check: show error message when discontinuity detected or TEI flag detected in header Signed-off-by: Abylay Ospan --- linux/drivers/media/dvb/dvb-core/dvb_demux.c | 42 ++++++++++++++++++++++++++++ linux/drivers/media/dvb/dvb-core/dvb_demux.h | 4 +++ 2 files changed, 46 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/dvb-core/dvb_demux.c b/linux/drivers/media/dvb/dvb-core/dvb_demux.c index e2eca0b1f..cfe2768d2 100644 --- a/linux/drivers/media/dvb/dvb-core/dvb_demux.c +++ b/linux/drivers/media/dvb/dvb-core/dvb_demux.c @@ -38,6 +38,16 @@ */ // #define DVB_DEMUX_SECTION_LOSS_LOG +static int dvb_demux_tscheck; +module_param(dvb_demux_tscheck, int, 0644); +MODULE_PARM_DESC(dvb_demux_tscheck, + "enable transport stream continuity and TEI check"); + +#define dprintk_tscheck(x...) do { \ + if (dvb_demux_tscheck && printk_ratelimit()) \ + printk(x); \ + } while (0) + /****************************************************************************** * static inlined helper functions ******************************************************************************/ @@ -376,6 +386,36 @@ static void dvb_dmx_swfilter_packet(struct dvb_demux *demux, const u8 *buf) u16 pid = ts_pid(buf); int dvr_done = 0; + if (dvb_demux_tscheck) { + if (!demux->cnt_storage) + demux->cnt_storage = vmalloc(MAX_PID + 1); + + if (!demux->cnt_storage) { + printk(KERN_WARNING "Couldn't allocate memory for TS/TEI check. Disabling it\n"); + dvb_demux_tscheck = 0; + goto no_dvb_demux_tscheck; + } + + /* check pkt counter */ + if (pid < MAX_PID) { + if (buf[1] & 0x80) + dprintk_tscheck("TEI detected. " + "PID=0x%x data1=0x%x\n", + pid, buf[1]); + + if ((buf[3] & 0xf) != demux->cnt_storage[pid]) + dprintk_tscheck("TS packet counter mismatch. " + "PID=0x%x expected 0x%x " + "got 0x%x\n", + pid, demux->cnt_storage[pid], + buf[3] & 0xf); + + demux->cnt_storage[pid] = ((buf[3] & 0xf) + 1)&0xf; + }; + /* end check */ + }; +no_dvb_demux_tscheck: + list_for_each_entry(feed, &demux->feed_list, list_head) { if ((feed->pid != pid) && (feed->pid != 0x2000)) continue; @@ -1160,6 +1200,7 @@ int dvb_dmx_init(struct dvb_demux *dvbdemux) int i; struct dmx_demux *dmx = &dvbdemux->dmx; + dvbdemux->cnt_storage = NULL; dvbdemux->users = 0; dvbdemux->filter = vmalloc(dvbdemux->filternum * sizeof(struct dvb_demux_filter)); @@ -1226,6 +1267,7 @@ EXPORT_SYMBOL(dvb_dmx_init); void dvb_dmx_release(struct dvb_demux *dvbdemux) { + vfree(dvbdemux->cnt_storage); vfree(dvbdemux->filter); vfree(dvbdemux->feed); } diff --git a/linux/drivers/media/dvb/dvb-core/dvb_demux.h b/linux/drivers/media/dvb/dvb-core/dvb_demux.h index 933397c24..1e0ade4ec 100644 --- a/linux/drivers/media/dvb/dvb-core/dvb_demux.h +++ b/linux/drivers/media/dvb/dvb-core/dvb_demux.h @@ -43,6 +43,8 @@ #define DVB_DEMUX_MASK_MAX 18 +#define MAX_PID 0x1fff + struct dvb_demux_filter { struct dmx_section_filter filter; u8 maskandmode[DMX_MAX_FILTER_SIZE]; @@ -128,6 +130,8 @@ struct dvb_demux { struct mutex mutex; spinlock_t lock; + + uint8_t *cnt_storage; /* for TS continuity check */ }; int dvb_dmx_init(struct dvb_demux *dvbdemux); -- cgit v1.2.3 From 404f85e5ea9ee93c2a52e01b98acafa010c4d013 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Tue, 9 Jun 2009 22:12:33 +0200 Subject: v4l2: add new s_config subdev ops and v4l2_i2c_new_subdev_cfg/board calls From: Hans Verkuil Add a new s_config core ops call: this is called with the irq and platform data to be used to initialize the subdev. Added new v4l2_i2c_new_subdev_cfg and v4l2_i2c_new_subdev_board calls that allows you to pass these new arguments. The existing v4l2_i2c_new_subdev functions were modified to also call s_config. In the future the existing v4l2_i2c_new_subdev functions will be replaced by a single v4l2_i2c_new_subdev function similar to v4l2_i2c_new_subdev_cfg but without the irq and platform_data arguments. Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/v4l2-common.c | 166 ++++++++++++++++++++++++++++++++ 1 file changed, 166 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/v4l2-common.c b/linux/drivers/media/video/v4l2-common.c index d81bae197..af1a64969 100644 --- a/linux/drivers/media/video/v4l2-common.c +++ b/linux/drivers/media/video/v4l2-common.c @@ -868,6 +868,17 @@ struct v4l2_subdev *v4l2_i2c_new_subdev(struct v4l2_device *v4l2_dev, /* Decrease the module use count to match the first try_module_get. */ module_put(client->driver->driver.owner); + if (sd) { + /* We return errors from v4l2_subdev_call only if we have the + callback as the .s_config is not mandatory */ + int err = v4l2_subdev_call(sd, core, s_config, 0, NULL); + + if (err && err != -ENOIOCTLCMD) { + v4l2_device_unregister_subdev(sd); + sd = NULL; + } + } + error: #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) /* If we have a client but no subdev, then something went wrong and @@ -931,6 +942,17 @@ struct v4l2_subdev *v4l2_i2c_new_probed_subdev(struct v4l2_device *v4l2_dev, /* Decrease the module use count to match the first try_module_get. */ module_put(client->driver->driver.owner); + if (sd) { + /* We return errors from v4l2_subdev_call only if we have the + callback as the .s_config is not mandatory */ + int err = v4l2_subdev_call(sd, core, s_config, 0, NULL); + + if (err && err != -ENOIOCTLCMD) { + v4l2_device_unregister_subdev(sd); + sd = NULL; + } + } + error: #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) /* If we have a client but no subdev, then something went wrong and @@ -953,6 +975,150 @@ struct v4l2_subdev *v4l2_i2c_new_probed_subdev_addr(struct v4l2_device *v4l2_dev } EXPORT_SYMBOL_GPL(v4l2_i2c_new_probed_subdev_addr); +/* Load an i2c sub-device. */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) +struct v4l2_subdev *v4l2_i2c_new_subdev_board(struct v4l2_device *v4l2_dev, + struct i2c_adapter *adapter, const char *module_name, + struct i2c_board_info *info, const unsigned short *probe_addrs) +{ + struct v4l2_subdev *sd = NULL; + struct i2c_client *client; + + BUG_ON(!v4l2_dev); + + if (module_name) + request_module(module_name); + + /* Create the i2c client */ + if (info->addr == 0 && probe_addrs) + client = i2c_new_probed_device(adapter, info, probe_addrs); + else + client = i2c_new_device(adapter, info); + + /* Note: by loading the module first we are certain that c->driver + will be set if the driver was found. If the module was not loaded + first, then the i2c core tries to delay-load the module for us, + and then c->driver is still NULL until the module is finally + loaded. This delay-load mechanism doesn't work if other drivers + want to use the i2c device, so explicitly loading the module + is the best alternative. */ + if (client == NULL || client->driver == NULL) + goto error; + + /* Lock the module so we can safely get the v4l2_subdev pointer */ + if (!try_module_get(client->driver->driver.owner)) + goto error; + sd = i2c_get_clientdata(client); + + /* Register with the v4l2_device which increases the module's + use count as well. */ + if (v4l2_device_register_subdev(v4l2_dev, sd)) + sd = NULL; + /* Decrease the module use count to match the first try_module_get. */ + module_put(client->driver->driver.owner); + + if (sd) { + /* We return errors from v4l2_subdev_call only if we have the + callback as the .s_config is not mandatory */ + int err = v4l2_subdev_call(sd, core, s_config, + info->irq, info->platform_data); + + if (err && err != -ENOIOCTLCMD) { + v4l2_device_unregister_subdev(sd); + sd = NULL; + } + } + +error: + /* If we have a client but no subdev, then something went wrong and + we must unregister the client. */ + if (client && sd == NULL) + i2c_unregister_device(client); + return sd; +} +EXPORT_SYMBOL_GPL(v4l2_i2c_new_subdev_board); + +struct v4l2_subdev *v4l2_i2c_new_subdev_cfg(struct v4l2_device *v4l2_dev, + struct i2c_adapter *adapter, + const char *module_name, const char *client_type, + int irq, void *platform_data, + u8 addr, const unsigned short *probe_addrs) +{ + struct i2c_board_info info; + + /* Setup the i2c board info with the device type and + the device address. */ + memset(&info, 0, sizeof(info)); + strlcpy(info.type, client_type, sizeof(info.type)); + info.addr = addr; + info.irq = irq; + info.platform_data = platform_data; + + return v4l2_i2c_new_subdev_board(v4l2_dev, adapter, module_name, + &info, probe_addrs); +} +EXPORT_SYMBOL_GPL(v4l2_i2c_new_subdev_cfg); +#else +struct v4l2_subdev *v4l2_i2c_new_subdev_cfg(struct v4l2_device *v4l2_dev, + struct i2c_adapter *adapter, + const char *module_name, const char *client_type, + int irq, void *platform_data, + u8 addr, const unsigned short *probe_addrs) +{ + struct v4l2_subdev *sd = NULL; + struct i2c_client *client; + + BUG_ON(!v4l2_dev); + + if (module_name) + request_module(module_name); + + if (addr == 0 && probe_addrs) { + /* Legacy code: loading the module should automatically + probe and create the i2c_client on the adapter. + Try to find the client by walking the adapter's client list + for each of the possible addresses. */ + while (!client && *probe_addrs != I2C_CLIENT_END) + client = v4l2_i2c_legacy_find_client(adapter, *probe_addrs++); + } else { + /* Legacy code: loading the module automatically probes and + creates the i2c_client on the adapter. Try to find the + client by walking the adapter's client list. */ + client = v4l2_i2c_legacy_find_client(adapter, addr); + } + if (client == NULL || client->driver == NULL) + goto error; + + /* Lock the module so we can safely get the v4l2_subdev pointer */ + if (!try_module_get(client->driver->driver.owner)) + goto error; + sd = i2c_get_clientdata(client); + + /* Register with the v4l2_device which increases the module's + use count as well. */ + if (v4l2_device_register_subdev(v4l2_dev, sd)) + sd = NULL; + /* Decrease the module use count to match the first try_module_get. */ + module_put(client->driver->driver.owner); + + if (sd) { + /* We return errors from v4l2_subdev_call only if we have the + callback as the .s_config is not mandatory */ + int err = v4l2_subdev_call(sd, core, s_config, + irq, platform_data); + + if (err && err != -ENOIOCTLCMD) { + v4l2_device_unregister_subdev(sd); + sd = NULL; + } + } + +error: + return sd; +} +EXPORT_SYMBOL_GPL(v4l2_i2c_new_subdev_cfg); +#endif + /* Return i2c client address of v4l2_subdev. */ unsigned short v4l2_i2c_subdev_addr(struct v4l2_subdev *sd) { -- cgit v1.2.3 From 6f5d1d816e6bda52a698c98b2f96426eb68a42c4 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 6 Jun 2009 18:29:37 +0200 Subject: v4l2-device: fix incorrect kernel check From: Hans Verkuil i2c_unregister_device must be called on kernels >= 2.6.26, not just for kernels >= 2.6.29. Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/v4l2-device.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/v4l2-device.c b/linux/drivers/media/video/v4l2-device.c index 18d404499..655d19cd6 100644 --- a/linux/drivers/media/video/v4l2-device.c +++ b/linux/drivers/media/video/v4l2-device.c @@ -87,7 +87,7 @@ void v4l2_device_unregister(struct v4l2_device *v4l2_dev) list_for_each_entry_safe(sd, next, &v4l2_dev->subdevs, list) { v4l2_device_unregister_subdev(sd); #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) if (sd->flags & V4L2_SUBDEV_FL_IS_I2C) { struct i2c_client *client = v4l2_get_subdevdata(sd); -- cgit v1.2.3 From f0f562fe7ee44a16459f76484a96bc5a822bc2fc Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 7 Jun 2009 13:41:03 +0000 Subject: saa7134: add support for AVerMedia M103 (f736) From: Barry Kitson Add 1461:f736 to the list of identifiers corresponding to the SAA7134_BOARD_AVERMEDIA_M103 board. This patch adds support for a variant of the AVerMedia M103 MiniPCI DVB-T Hybrid card. Signed-off-by: Barry Kitson Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/saa7134/saa7134-cards.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/saa7134/saa7134-cards.c b/linux/drivers/media/video/saa7134/saa7134-cards.c index 064fb86bc..e2d98ff5c 100644 --- a/linux/drivers/media/video/saa7134/saa7134-cards.c +++ b/linux/drivers/media/video/saa7134/saa7134-cards.c @@ -6238,6 +6238,12 @@ struct pci_device_id saa7134_pci_tbl[] = { .subvendor = 0x1461, /* Avermedia Technologies Inc */ .subdevice = 0xf636, .driver_data = SAA7134_BOARD_AVERMEDIA_M103, + }, { + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7133, + .subvendor = 0x1461, /* Avermedia Technologies Inc */ + .subdevice = 0xf736, + .driver_data = SAA7134_BOARD_AVERMEDIA_M103, }, { .vendor = PCI_VENDOR_ID_PHILIPS, .device = PCI_DEVICE_ID_PHILIPS_SAA7133, -- cgit v1.2.3 From 4e89b9e36f8b8a7ad919333c7dcc6cbdd902a5e5 Mon Sep 17 00:00:00 2001 From: "Igor M. Liplianin" Date: Sun, 14 Jun 2009 19:17:15 +0300 Subject: Change lnbh24 configure bits for NetUP card. From: Igor M. Liplianin Signed-off-by: Igor M. Liplianin --- linux/drivers/media/video/cx23885/cx23885-dvb.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/cx23885/cx23885-dvb.c b/linux/drivers/media/video/cx23885/cx23885-dvb.c index 9c3259b22..10bb442b1 100644 --- a/linux/drivers/media/video/cx23885/cx23885-dvb.c +++ b/linux/drivers/media/video/cx23885/cx23885-dvb.c @@ -737,7 +737,8 @@ static int dvb_register(struct cx23885_tsport *port) if (!dvb_attach(lnbh24_attach, fe0->dvb.frontend, &i2c_bus->i2c_adap, - LNBH24_PCL, 0, 0x09)) + LNBH24_PCL, + LNBH24_TTX, 0x09)) printk(KERN_ERR "No LNBH24 found!\n"); @@ -757,7 +758,8 @@ static int dvb_register(struct cx23885_tsport *port) if (!dvb_attach(lnbh24_attach, fe0->dvb.frontend, &i2c_bus->i2c_adap, - LNBH24_PCL, 0, 0x0a)) + LNBH24_PCL, + LNBH24_TTX, 0x0a)) printk(KERN_ERR "No LNBH24 found!\n"); -- cgit v1.2.3 From 0c34c03a8998a601da924c7f2679494992b548e6 Mon Sep 17 00:00:00 2001 From: Abylay Ospan Date: Sun, 14 Jun 2009 20:10:05 +0300 Subject: Bug fix: stv0900 register read must using i2c in one transaction From: Abylay Ospan Signed-off-by: Abylay Ospan --- linux/drivers/media/dvb/frontends/stv0900_core.c | 40 ++++++++++++------------ 1 file changed, 20 insertions(+), 20 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/frontends/stv0900_core.c b/linux/drivers/media/dvb/frontends/stv0900_core.c index 899b1e7ed..156d269f7 100644 --- a/linux/drivers/media/dvb/frontends/stv0900_core.c +++ b/linux/drivers/media/dvb/frontends/stv0900_core.c @@ -149,31 +149,31 @@ void stv0900_write_reg(struct stv0900_internal *i_params, u16 reg_addr, dprintk(KERN_ERR "%s: i2c error %d\n", __func__, ret); } -u8 stv0900_read_reg(struct stv0900_internal *i_params, u16 reg_addr) +u8 stv0900_read_reg(struct stv0900_internal *i_params, u16 reg) { - u8 data[2]; int ret; - struct i2c_msg i2cmsg = { - .addr = i_params->i2c_addr, - .flags = 0, - .len = 2, - .buf = data, + u8 b0[] = { MSB(reg), LSB(reg) }; + u8 buf = 0; + struct i2c_msg msg[] = { + { + .addr = i_params->i2c_addr, + .flags = 0, + .buf = b0, + .len = 2, + }, { + .addr = i_params->i2c_addr, + .flags = I2C_M_RD, + .buf = &buf, + .len = 1, + }, }; - data[0] = MSB(reg_addr); - data[1] = LSB(reg_addr); - - ret = i2c_transfer(i_params->i2c_adap, &i2cmsg, 1); - if (ret != 1) - dprintk(KERN_ERR "%s: i2c error %d\n", __func__, ret); - - i2cmsg.flags = I2C_M_RD; - i2cmsg.len = 1; - ret = i2c_transfer(i_params->i2c_adap, &i2cmsg, 1); - if (ret != 1) - dprintk(KERN_ERR "%s: i2c error %d\n", __func__, ret); + ret = i2c_transfer(i_params->i2c_adap, msg, 2); + if (ret != 2) + dprintk(KERN_ERR "%s: i2c error %d, reg[0x%02x]\n", + __func__, ret, reg); - return data[0]; + return buf; } void extract_mask_pos(u32 label, u8 *mask, u8 *pos) -- cgit v1.2.3 From 3d2ec84da9539d7b413eaa6c2b99373cfc02597e Mon Sep 17 00:00:00 2001 From: Abylay Ospan Date: Mon, 8 Jun 2009 11:31:26 +0400 Subject: Implement reading uncorrected blocks for stv0900 From: Abylay Ospan Signed-off-by: Abylay Ospan --- linux/drivers/media/dvb/frontends/stv0900_core.c | 39 ++++++++++++++++++++++++ 1 file changed, 39 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/frontends/stv0900_core.c b/linux/drivers/media/dvb/frontends/stv0900_core.c index 156d269f7..2e9e5fbbb 100644 --- a/linux/drivers/media/dvb/frontends/stv0900_core.c +++ b/linux/drivers/media/dvb/frontends/stv0900_core.c @@ -716,6 +716,44 @@ static s32 stv0900_carr_get_quality(struct dvb_frontend *fe, return c_n; } +static int stv0900_read_ucblocks(struct dvb_frontend *fe, u32 * ucblocks) +{ + struct stv0900_state *state = fe->demodulator_priv; + struct stv0900_internal *i_params = state->internal; + enum fe_stv0900_demod_num demod = state->demod; + u8 err_val1, err_val0; + s32 err_field1, err_field0; + u32 header_err_val = 0; + + *ucblocks = 0x0; + if (stv0900_get_standard(fe, demod) == STV0900_DVBS2_STANDARD) { + /* DVB-S2 delineator errors count */ + + /* retreiving number for errnous headers */ + dmd_reg(err_field0, R0900_P1_BBFCRCKO0, + R0900_P2_BBFCRCKO0); + dmd_reg(err_field1, R0900_P1_BBFCRCKO1, + R0900_P2_BBFCRCKO1); + + err_val1 = stv0900_read_reg(i_params, err_field1); + err_val0 = stv0900_read_reg(i_params, err_field0); + header_err_val = (err_val1<<8) | err_val0; + + /* retreiving number for errnous packets */ + dmd_reg(err_field0, R0900_P1_UPCRCKO0, + R0900_P2_UPCRCKO0); + dmd_reg(err_field1, R0900_P1_UPCRCKO1, + R0900_P2_UPCRCKO1); + + err_val1 = stv0900_read_reg(i_params, err_field1); + err_val0 = stv0900_read_reg(i_params, err_field0); + *ucblocks = (err_val1<<8) | err_val0; + *ucblocks += header_err_val; + } + + return 0; +} + static int stv0900_read_snr(struct dvb_frontend *fe, u16 *snr) { *snr = stv0900_carr_get_quality(fe, @@ -1897,6 +1935,7 @@ static struct dvb_frontend_ops stv0900_ops = { .read_ber = stv0900_read_ber, .read_signal_strength = stv0900_read_signal_strength, .read_snr = stv0900_read_snr, + .read_ucblocks = stv0900_read_ucblocks, }; struct dvb_frontend *stv0900_attach(const struct stv0900_config *config, -- cgit v1.2.3 From 6bbc9163a42ac2c7a561b470cfffaec1a79e46b8 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Tue, 9 Jun 2009 10:54:02 +0200 Subject: DaVinci: DM646x Video: VPIF driver From: Chaithrika U S Video Port Interface driver Add VPIF driver for DM646x. This code be used by the display and capture drivers. Priority: normal Signed-off-by: Manjunath Hadli Signed-off-by: Brijesh Jadav Signed-off-by: Chaithrika U S Reviewed-by: Hans Verkuil Signed-off-by: Hans Verkuil --- linux/drivers/media/video/davinci/vpif.c | 234 ++++++++++++ linux/drivers/media/video/davinci/vpif.h | 632 +++++++++++++++++++++++++++++++ 2 files changed, 866 insertions(+) create mode 100644 linux/drivers/media/video/davinci/vpif.c create mode 100644 linux/drivers/media/video/davinci/vpif.h (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/davinci/vpif.c b/linux/drivers/media/video/davinci/vpif.c new file mode 100644 index 000000000..aa771268a --- /dev/null +++ b/linux/drivers/media/video/davinci/vpif.c @@ -0,0 +1,234 @@ +/* + * vpif - DM646x Video Port Interface driver + * VPIF is a receiver and transmitter for video data. It has two channels(0, 1) + * that receiveing video byte stream and two channels(2, 3) for video output. + * The hardware supports SDTV, HDTV formats, raw data capture. + * Currently, the driver supports NTSC and PAL standards. + * + * Copyright (C) 2009 Texas Instruments Incorporated - http://www.ti.com/ + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation version 2. + * + * This program is distributed .as is. WITHOUT ANY WARRANTY of any + * kind, whether express or implied; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include + +#include "vpif.h" + +MODULE_DESCRIPTION("TI DaVinci Video Port Interface driver"); +MODULE_LICENSE("GPL"); + +#define VPIF_CH0_MAX_MODES (22) +#define VPIF_CH1_MAX_MODES (02) +#define VPIF_CH2_MAX_MODES (15) +#define VPIF_CH3_MAX_MODES (02) + +static inline void vpif_wr_bit(u32 reg, u32 bit, u32 val) +{ + if (val) + vpif_set_bit(reg, bit); + else + vpif_clr_bit(reg, bit); +} + +/* This structure is used to keep track of VPIF size register's offsets */ +struct vpif_registers { + u32 h_cfg, v_cfg_00, v_cfg_01, v_cfg_02, v_cfg, ch_ctrl; + u32 line_offset, vanc0_strt, vanc0_size, vanc1_strt; + u32 vanc1_size, width_mask, len_mask; + u8 max_modes; +}; + +static const struct vpif_registers vpifregs[VPIF_NUM_CHANNELS] = { + /* Channel0 */ + { + VPIF_CH0_H_CFG, VPIF_CH0_V_CFG_00, VPIF_CH0_V_CFG_01, + VPIF_CH0_V_CFG_02, VPIF_CH0_V_CFG_03, VPIF_CH0_CTRL, + VPIF_CH0_IMG_ADD_OFST, 0, 0, 0, 0, 0x1FFF, 0xFFF, + VPIF_CH0_MAX_MODES, + }, + /* Channel1 */ + { + VPIF_CH1_H_CFG, VPIF_CH1_V_CFG_00, VPIF_CH1_V_CFG_01, + VPIF_CH1_V_CFG_02, VPIF_CH1_V_CFG_03, VPIF_CH1_CTRL, + VPIF_CH1_IMG_ADD_OFST, 0, 0, 0, 0, 0x1FFF, 0xFFF, + VPIF_CH1_MAX_MODES, + }, + /* Channel2 */ + { + VPIF_CH2_H_CFG, VPIF_CH2_V_CFG_00, VPIF_CH2_V_CFG_01, + VPIF_CH2_V_CFG_02, VPIF_CH2_V_CFG_03, VPIF_CH2_CTRL, + VPIF_CH2_IMG_ADD_OFST, VPIF_CH2_VANC0_STRT, VPIF_CH2_VANC0_SIZE, + VPIF_CH2_VANC1_STRT, VPIF_CH2_VANC1_SIZE, 0x7FF, 0x7FF, + VPIF_CH2_MAX_MODES + }, + /* Channel3 */ + { + VPIF_CH3_H_CFG, VPIF_CH3_V_CFG_00, VPIF_CH3_V_CFG_01, + VPIF_CH3_V_CFG_02, VPIF_CH3_V_CFG_03, VPIF_CH3_CTRL, + VPIF_CH3_IMG_ADD_OFST, VPIF_CH3_VANC0_STRT, VPIF_CH3_VANC0_SIZE, + VPIF_CH3_VANC1_STRT, VPIF_CH3_VANC1_SIZE, 0x7FF, 0x7FF, + VPIF_CH3_MAX_MODES + }, +}; + +/* vpif_set_mode_info: + * This function is used to set horizontal and vertical config parameters + * As per the standard in the channel, configure the values of L1, L3, + * L5, L7 L9, L11 in VPIF Register , also write width and height + */ +static void vpif_set_mode_info(const struct vpif_channel_config_params *config, + u8 channel_id, u8 config_channel_id) +{ + u32 value; + + value = (config->eav2sav & vpifregs[config_channel_id].width_mask); + value <<= VPIF_CH_LEN_SHIFT; + value |= (config->sav2eav & vpifregs[config_channel_id].width_mask); + regw(value, vpifregs[channel_id].h_cfg); + + value = (config->l1 & vpifregs[config_channel_id].len_mask); + value <<= VPIF_CH_LEN_SHIFT; + value |= (config->l3 & vpifregs[config_channel_id].len_mask); + regw(value, vpifregs[channel_id].v_cfg_00); + + value = (config->l5 & vpifregs[config_channel_id].len_mask); + value <<= VPIF_CH_LEN_SHIFT; + value |= (config->l7 & vpifregs[config_channel_id].len_mask); + regw(value, vpifregs[channel_id].v_cfg_01); + + value = (config->l9 & vpifregs[config_channel_id].len_mask); + value <<= VPIF_CH_LEN_SHIFT; + value |= (config->l11 & vpifregs[config_channel_id].len_mask); + regw(value, vpifregs[channel_id].v_cfg_02); + + value = (config->vsize & vpifregs[config_channel_id].len_mask); + regw(value, vpifregs[channel_id].v_cfg); +} + +/* config_vpif_params + * Function to set the parameters of a channel + * Mainly modifies the channel ciontrol register + * It sets frame format, yc mux mode + */ +static void config_vpif_params(struct vpif_params *vpifparams, + u8 channel_id, u8 found) +{ + const struct vpif_channel_config_params *config = &vpifparams->std_info; + u32 value, ch_nip, reg; + u8 start, end; + int i; + + start = channel_id; + end = channel_id + found; + + for (i = start; i < end; i++) { + reg = vpifregs[i].ch_ctrl; + if (channel_id < 2) + ch_nip = VPIF_CAPTURE_CH_NIP; + else + ch_nip = VPIF_DISPLAY_CH_NIP; + + vpif_wr_bit(reg, ch_nip, config->frm_fmt); + vpif_wr_bit(reg, VPIF_CH_YC_MUX_BIT, config->ycmux_mode); + vpif_wr_bit(reg, VPIF_CH_INPUT_FIELD_FRAME_BIT, + vpifparams->video_params.storage_mode); + + /* Set raster scanning SDR Format */ + vpif_clr_bit(reg, VPIF_CH_SDR_FMT_BIT); + vpif_wr_bit(reg, VPIF_CH_DATA_MODE_BIT, config->capture_format); + + if (channel_id > 1) /* Set the Pixel enable bit */ + vpif_set_bit(reg, VPIF_DISPLAY_PIX_EN_BIT); + else if (config->capture_format) { + /* Set the polarity of various pins */ + vpif_wr_bit(reg, VPIF_CH_FID_POLARITY_BIT, + vpifparams->params.raw_params.fid_pol); + vpif_wr_bit(reg, VPIF_CH_V_VALID_POLARITY_BIT, + vpifparams->params.raw_params.vd_pol); + vpif_wr_bit(reg, VPIF_CH_H_VALID_POLARITY_BIT, + vpifparams->params.raw_params.hd_pol); + + value = regr(reg); + /* Set data width */ + value &= ((~(unsigned int)(0x3)) << + VPIF_CH_DATA_WIDTH_BIT); + value |= ((vpifparams->params.raw_params.data_sz) << + VPIF_CH_DATA_WIDTH_BIT); + regw(value, reg); + } + + /* Write the pitch in the driver */ + regw((vpifparams->video_params.hpitch), + vpifregs[i].line_offset); + } +} + +/* vpif_set_video_params + * This function is used to set video parameters in VPIF register + */ +int vpif_set_video_params(struct vpif_params *vpifparams, u8 channel_id) +{ + const struct vpif_channel_config_params *config = &vpifparams->std_info; + int found = 1; + + vpif_set_mode_info(config, channel_id, channel_id); + if (!config->ycmux_mode) { + /* YC are on separate channels (HDTV formats) */ + vpif_set_mode_info(config, channel_id + 1, channel_id); + found = 2; + } + + config_vpif_params(vpifparams, channel_id, found); + + regw(0x80, VPIF_REQ_SIZE); + regw(0x01, VPIF_EMULATION_CTRL); + + return found; +} +EXPORT_SYMBOL(vpif_set_video_params); + +void vpif_set_vbi_display_params(struct vpif_vbi_params *vbiparams, + u8 channel_id) +{ + u32 value; + + value = 0x3F8 & (vbiparams->hstart0); + value |= 0x3FFFFFF & ((vbiparams->vstart0) << 16); + regw(value, vpifregs[channel_id].vanc0_strt); + + value = 0x3F8 & (vbiparams->hstart1); + value |= 0x3FFFFFF & ((vbiparams->vstart1) << 16); + regw(value, vpifregs[channel_id].vanc1_strt); + + value = 0x3F8 & (vbiparams->hsize0); + value |= 0x3FFFFFF & ((vbiparams->vsize0) << 16); + regw(value, vpifregs[channel_id].vanc0_size); + + value = 0x3F8 & (vbiparams->hsize1); + value |= 0x3FFFFFF & ((vbiparams->vsize1) << 16); + regw(value, vpifregs[channel_id].vanc1_size); + +} +EXPORT_SYMBOL(vpif_set_vbi_display_params); + +int vpif_channel_getfid(u8 channel_id) +{ + return (regr(vpifregs[channel_id].ch_ctrl) & VPIF_CH_FID_MASK) + >> VPIF_CH_FID_SHIFT; +} +EXPORT_SYMBOL(vpif_channel_getfid); + +void vpif_base_addr_init(void __iomem *base) +{ + vpif_base = base; +} +EXPORT_SYMBOL(vpif_base_addr_init); diff --git a/linux/drivers/media/video/davinci/vpif.h b/linux/drivers/media/video/davinci/vpif.h new file mode 100644 index 000000000..fca26dcb5 --- /dev/null +++ b/linux/drivers/media/video/davinci/vpif.h @@ -0,0 +1,632 @@ +/* + * VPIF header file + * + * Copyright (C) 2009 Texas Instruments Incorporated - http://www.ti.com/ + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation version 2. + * + * This program is distributed .as is. WITHOUT ANY WARRANTY of any + * kind, whether express or implied; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef VPIF_H +#define VPIF_H + +#include +#include +#include + +/* Maximum channel allowed */ +#define VPIF_NUM_CHANNELS (4) +#define VPIF_CAPTURE_NUM_CHANNELS (2) +#define VPIF_DISPLAY_NUM_CHANNELS (2) + +/* Macros to read/write registers */ +static void __iomem *vpif_base; +#define regr(reg) readl((reg) + vpif_base) +#define regw(value, reg) writel(value, (reg + vpif_base)) + +/* Register Addresss Offsets */ +#define VPIF_PID (0x0000) +#define VPIF_CH0_CTRL (0x0004) +#define VPIF_CH1_CTRL (0x0008) +#define VPIF_CH2_CTRL (0x000C) +#define VPIF_CH3_CTRL (0x0010) + +#define VPIF_INTEN (0x0020) +#define VPIF_INTEN_SET (0x0024) +#define VPIF_INTEN_CLR (0x0028) +#define VPIF_STATUS (0x002C) +#define VPIF_STATUS_CLR (0x0030) +#define VPIF_EMULATION_CTRL (0x0034) +#define VPIF_REQ_SIZE (0x0038) + +#define VPIF_CH0_TOP_STRT_ADD_LUMA (0x0040) +#define VPIF_CH0_BTM_STRT_ADD_LUMA (0x0044) +#define VPIF_CH0_TOP_STRT_ADD_CHROMA (0x0048) +#define VPIF_CH0_BTM_STRT_ADD_CHROMA (0x004c) +#define VPIF_CH0_TOP_STRT_ADD_HANC (0x0050) +#define VPIF_CH0_BTM_STRT_ADD_HANC (0x0054) +#define VPIF_CH0_TOP_STRT_ADD_VANC (0x0058) +#define VPIF_CH0_BTM_STRT_ADD_VANC (0x005c) +#define VPIF_CH0_SP_CFG (0x0060) +#define VPIF_CH0_IMG_ADD_OFST (0x0064) +#define VPIF_CH0_HANC_ADD_OFST (0x0068) +#define VPIF_CH0_H_CFG (0x006c) +#define VPIF_CH0_V_CFG_00 (0x0070) +#define VPIF_CH0_V_CFG_01 (0x0074) +#define VPIF_CH0_V_CFG_02 (0x0078) +#define VPIF_CH0_V_CFG_03 (0x007c) + +#define VPIF_CH1_TOP_STRT_ADD_LUMA (0x0080) +#define VPIF_CH1_BTM_STRT_ADD_LUMA (0x0084) +#define VPIF_CH1_TOP_STRT_ADD_CHROMA (0x0088) +#define VPIF_CH1_BTM_STRT_ADD_CHROMA (0x008c) +#define VPIF_CH1_TOP_STRT_ADD_HANC (0x0090) +#define VPIF_CH1_BTM_STRT_ADD_HANC (0x0094) +#define VPIF_CH1_TOP_STRT_ADD_VANC (0x0098) +#define VPIF_CH1_BTM_STRT_ADD_VANC (0x009c) +#define VPIF_CH1_SP_CFG (0x00a0) +#define VPIF_CH1_IMG_ADD_OFST (0x00a4) +#define VPIF_CH1_HANC_ADD_OFST (0x00a8) +#define VPIF_CH1_H_CFG (0x00ac) +#define VPIF_CH1_V_CFG_00 (0x00b0) +#define VPIF_CH1_V_CFG_01 (0x00b4) +#define VPIF_CH1_V_CFG_02 (0x00b8) +#define VPIF_CH1_V_CFG_03 (0x00bc) + +#define VPIF_CH2_TOP_STRT_ADD_LUMA (0x00c0) +#define VPIF_CH2_BTM_STRT_ADD_LUMA (0x00c4) +#define VPIF_CH2_TOP_STRT_ADD_CHROMA (0x00c8) +#define VPIF_CH2_BTM_STRT_ADD_CHROMA (0x00cc) +#define VPIF_CH2_TOP_STRT_ADD_HANC (0x00d0) +#define VPIF_CH2_BTM_STRT_ADD_HANC (0x00d4) +#define VPIF_CH2_TOP_STRT_ADD_VANC (0x00d8) +#define VPIF_CH2_BTM_STRT_ADD_VANC (0x00dc) +#define VPIF_CH2_SP_CFG (0x00e0) +#define VPIF_CH2_IMG_ADD_OFST (0x00e4) +#define VPIF_CH2_HANC_ADD_OFST (0x00e8) +#define VPIF_CH2_H_CFG (0x00ec) +#define VPIF_CH2_V_CFG_00 (0x00f0) +#define VPIF_CH2_V_CFG_01 (0x00f4) +#define VPIF_CH2_V_CFG_02 (0x00f8) +#define VPIF_CH2_V_CFG_03 (0x00fc) +#define VPIF_CH2_HANC0_STRT (0x0100) +#define VPIF_CH2_HANC0_SIZE (0x0104) +#define VPIF_CH2_HANC1_STRT (0x0108) +#define VPIF_CH2_HANC1_SIZE (0x010c) +#define VPIF_CH2_VANC0_STRT (0x0110) +#define VPIF_CH2_VANC0_SIZE (0x0114) +#define VPIF_CH2_VANC1_STRT (0x0118) +#define VPIF_CH2_VANC1_SIZE (0x011c) + +#define VPIF_CH3_TOP_STRT_ADD_LUMA (0x0140) +#define VPIF_CH3_BTM_STRT_ADD_LUMA (0x0144) +#define VPIF_CH3_TOP_STRT_ADD_CHROMA (0x0148) +#define VPIF_CH3_BTM_STRT_ADD_CHROMA (0x014c) +#define VPIF_CH3_TOP_STRT_ADD_HANC (0x0150) +#define VPIF_CH3_BTM_STRT_ADD_HANC (0x0154) +#define VPIF_CH3_TOP_STRT_ADD_VANC (0x0158) +#define VPIF_CH3_BTM_STRT_ADD_VANC (0x015c) +#define VPIF_CH3_SP_CFG (0x0160) +#define VPIF_CH3_IMG_ADD_OFST (0x0164) +#define VPIF_CH3_HANC_ADD_OFST (0x0168) +#define VPIF_CH3_H_CFG (0x016c) +#define VPIF_CH3_V_CFG_00 (0x0170) +#define VPIF_CH3_V_CFG_01 (0x0174) +#define VPIF_CH3_V_CFG_02 (0x0178) +#define VPIF_CH3_V_CFG_03 (0x017c) +#define VPIF_CH3_HANC0_STRT (0x0180) +#define VPIF_CH3_HANC0_SIZE (0x0184) +#define VPIF_CH3_HANC1_STRT (0x0188) +#define VPIF_CH3_HANC1_SIZE (0x018c) +#define VPIF_CH3_VANC0_STRT (0x0190) +#define VPIF_CH3_VANC0_SIZE (0x0194) +#define VPIF_CH3_VANC1_STRT (0x0198) +#define VPIF_CH3_VANC1_SIZE (0x019c) + +#define VPIF_IODFT_CTRL (0x01c0) + +/* Functions for bit Manipulation */ +static inline void vpif_set_bit(u32 reg, u32 bit) +{ + regw((regr(reg)) | (0x01 << bit), reg); +} + +static inline void vpif_clr_bit(u32 reg, u32 bit) +{ + regw(((regr(reg)) & ~(0x01 << bit)), reg); +} + +/* Macro for Generating mask */ +#ifdef GENERATE_MASK +#undef GENERATE_MASK +#endif + +#define GENERATE_MASK(bits, pos) \ + ((((0xFFFFFFFF) << (32 - bits)) >> (32 - bits)) << pos) + +/* Bit positions in the channel control registers */ +#define VPIF_CH_DATA_MODE_BIT (2) +#define VPIF_CH_YC_MUX_BIT (3) +#define VPIF_CH_SDR_FMT_BIT (4) +#define VPIF_CH_HANC_EN_BIT (8) +#define VPIF_CH_VANC_EN_BIT (9) + +#define VPIF_CAPTURE_CH_NIP (10) +#define VPIF_DISPLAY_CH_NIP (11) + +#define VPIF_DISPLAY_PIX_EN_BIT (10) + +#define VPIF_CH_INPUT_FIELD_FRAME_BIT (12) + +#define VPIF_CH_FID_POLARITY_BIT (15) +#define VPIF_CH_V_VALID_POLARITY_BIT (14) +#define VPIF_CH_H_VALID_POLARITY_BIT (13) +#define VPIF_CH_DATA_WIDTH_BIT (28) + +#define VPIF_CH_CLK_EDGE_CTRL_BIT (31) + +/* Mask various length */ +#define VPIF_CH_EAVSAV_MASK GENERATE_MASK(13, 0) +#define VPIF_CH_LEN_MASK GENERATE_MASK(12, 0) +#define VPIF_CH_WIDTH_MASK GENERATE_MASK(13, 0) +#define VPIF_CH_LEN_SHIFT (16) + +/* VPIF masks for registers */ +#define VPIF_REQ_SIZE_MASK (0x1ff) + +/* bit posotion of interrupt vpif_ch_intr register */ +#define VPIF_INTEN_FRAME_CH0 (0x00000001) +#define VPIF_INTEN_FRAME_CH1 (0x00000002) +#define VPIF_INTEN_FRAME_CH2 (0x00000004) +#define VPIF_INTEN_FRAME_CH3 (0x00000008) + +/* bit position of clock and channel enable in vpif_chn_ctrl register */ + +#define VPIF_CH0_CLK_EN (0x00000002) +#define VPIF_CH0_EN (0x00000001) +#define VPIF_CH1_CLK_EN (0x00000002) +#define VPIF_CH1_EN (0x00000001) +#define VPIF_CH2_CLK_EN (0x00000002) +#define VPIF_CH2_EN (0x00000001) +#define VPIF_CH3_CLK_EN (0x00000002) +#define VPIF_CH3_EN (0x00000001) +#define VPIF_CH_CLK_EN (0x00000002) +#define VPIF_CH_EN (0x00000001) + +#define VPIF_INT_TOP (0x00) +#define VPIF_INT_BOTTOM (0x01) +#define VPIF_INT_BOTH (0x02) + +#define VPIF_CH0_INT_CTRL_SHIFT (6) +#define VPIF_CH1_INT_CTRL_SHIFT (6) +#define VPIF_CH2_INT_CTRL_SHIFT (6) +#define VPIF_CH3_INT_CTRL_SHIFT (6) +#define VPIF_CH_INT_CTRL_SHIFT (6) + +/* enabled interrupt on both the fields on vpid_ch0_ctrl register */ +#define channel0_intr_assert() (regw((regr(VPIF_CH0_CTRL)|\ + (VPIF_INT_BOTH << VPIF_CH0_INT_CTRL_SHIFT)), VPIF_CH0_CTRL)) + +/* enabled interrupt on both the fields on vpid_ch1_ctrl register */ +#define channel1_intr_assert() (regw((regr(VPIF_CH1_CTRL)|\ + (VPIF_INT_BOTH << VPIF_CH1_INT_CTRL_SHIFT)), VPIF_CH1_CTRL)) + +/* enabled interrupt on both the fields on vpid_ch0_ctrl register */ +#define channel2_intr_assert() (regw((regr(VPIF_CH2_CTRL)|\ + (VPIF_INT_BOTH << VPIF_CH2_INT_CTRL_SHIFT)), VPIF_CH2_CTRL)) + +/* enabled interrupt on both the fields on vpid_ch1_ctrl register */ +#define channel3_intr_assert() (regw((regr(VPIF_CH3_CTRL)|\ + (VPIF_INT_BOTH << VPIF_CH3_INT_CTRL_SHIFT)), VPIF_CH3_CTRL)) + +#define VPIF_CH_FID_MASK (0x20) +#define VPIF_CH_FID_SHIFT (5) + +#define VPIF_NTSC_VBI_START_FIELD0 (1) +#define VPIF_NTSC_VBI_START_FIELD1 (263) +#define VPIF_PAL_VBI_START_FIELD0 (624) +#define VPIF_PAL_VBI_START_FIELD1 (311) + +#define VPIF_NTSC_HBI_START_FIELD0 (1) +#define VPIF_NTSC_HBI_START_FIELD1 (263) +#define VPIF_PAL_HBI_START_FIELD0 (624) +#define VPIF_PAL_HBI_START_FIELD1 (311) + +#define VPIF_NTSC_VBI_COUNT_FIELD0 (20) +#define VPIF_NTSC_VBI_COUNT_FIELD1 (19) +#define VPIF_PAL_VBI_COUNT_FIELD0 (24) +#define VPIF_PAL_VBI_COUNT_FIELD1 (25) + +#define VPIF_NTSC_HBI_COUNT_FIELD0 (263) +#define VPIF_NTSC_HBI_COUNT_FIELD1 (262) +#define VPIF_PAL_HBI_COUNT_FIELD0 (312) +#define VPIF_PAL_HBI_COUNT_FIELD1 (313) + +#define VPIF_NTSC_VBI_SAMPLES_PER_LINE (720) +#define VPIF_PAL_VBI_SAMPLES_PER_LINE (720) +#define VPIF_NTSC_HBI_SAMPLES_PER_LINE (268) +#define VPIF_PAL_HBI_SAMPLES_PER_LINE (280) + +#define VPIF_CH_VANC_EN (0x20) +#define VPIF_DMA_REQ_SIZE (0x080) +#define VPIF_EMULATION_DISABLE (0x01) + +extern u8 irq_vpif_capture_channel[VPIF_NUM_CHANNELS]; + +/* inline function to enable/disable channel0 */ +static inline void enable_channel0(int enable) +{ + if (enable) + regw((regr(VPIF_CH0_CTRL) | (VPIF_CH0_EN)), VPIF_CH0_CTRL); + else + regw((regr(VPIF_CH0_CTRL) & (~VPIF_CH0_EN)), VPIF_CH0_CTRL); +} + +/* inline function to enable/disable channel1 */ +static inline void enable_channel1(int enable) +{ + if (enable) + regw((regr(VPIF_CH1_CTRL) | (VPIF_CH1_EN)), VPIF_CH1_CTRL); + else + regw((regr(VPIF_CH1_CTRL) & (~VPIF_CH1_EN)), VPIF_CH1_CTRL); +} + +/* inline function to enable interrupt for channel0 */ +static inline void channel0_intr_enable(int enable) +{ + if (enable) { + regw((regr(VPIF_INTEN) | 0x10), VPIF_INTEN); + regw((regr(VPIF_INTEN_SET) | 0x10), VPIF_INTEN_SET); + + regw((regr(VPIF_INTEN) | VPIF_INTEN_FRAME_CH0), VPIF_INTEN); + regw((regr(VPIF_INTEN_SET) | VPIF_INTEN_FRAME_CH0), + VPIF_INTEN_SET); + } else { + regw((regr(VPIF_INTEN) & (~VPIF_INTEN_FRAME_CH0)), VPIF_INTEN); + regw((regr(VPIF_INTEN_SET) | VPIF_INTEN_FRAME_CH0), + VPIF_INTEN_SET); + } +} + +/* inline function to enable interrupt for channel1 */ +static inline void channel1_intr_enable(int enable) +{ + if (enable) { + regw((regr(VPIF_INTEN) | 0x10), VPIF_INTEN); + regw((regr(VPIF_INTEN_SET) | 0x10), VPIF_INTEN_SET); + + regw((regr(VPIF_INTEN) | VPIF_INTEN_FRAME_CH1), VPIF_INTEN); + regw((regr(VPIF_INTEN_SET) | VPIF_INTEN_FRAME_CH1), + VPIF_INTEN_SET); + } else { + regw((regr(VPIF_INTEN) & (~VPIF_INTEN_FRAME_CH1)), VPIF_INTEN); + regw((regr(VPIF_INTEN_SET) | VPIF_INTEN_FRAME_CH1), + VPIF_INTEN_SET); + } +} + +/* inline function to set buffer addresses in case of Y/C non mux mode */ +static inline void ch0_set_videobuf_addr_yc_nmux(unsigned long top_strt_luma, + unsigned long btm_strt_luma, + unsigned long top_strt_chroma, + unsigned long btm_strt_chroma) +{ + regw(top_strt_luma, VPIF_CH0_TOP_STRT_ADD_LUMA); + regw(btm_strt_luma, VPIF_CH0_BTM_STRT_ADD_LUMA); + regw(top_strt_chroma, VPIF_CH1_TOP_STRT_ADD_CHROMA); + regw(btm_strt_chroma, VPIF_CH1_BTM_STRT_ADD_CHROMA); +} + +/* inline function to set buffer addresses in VPIF registers for video data */ +static inline void ch0_set_videobuf_addr(unsigned long top_strt_luma, + unsigned long btm_strt_luma, + unsigned long top_strt_chroma, + unsigned long btm_strt_chroma) +{ + regw(top_strt_luma, VPIF_CH0_TOP_STRT_ADD_LUMA); + regw(btm_strt_luma, VPIF_CH0_BTM_STRT_ADD_LUMA); + regw(top_strt_chroma, VPIF_CH0_TOP_STRT_ADD_CHROMA); + regw(btm_strt_chroma, VPIF_CH0_BTM_STRT_ADD_CHROMA); +} + +static inline void ch1_set_videobuf_addr(unsigned long top_strt_luma, + unsigned long btm_strt_luma, + unsigned long top_strt_chroma, + unsigned long btm_strt_chroma) +{ + + regw(top_strt_luma, VPIF_CH1_TOP_STRT_ADD_LUMA); + regw(btm_strt_luma, VPIF_CH1_BTM_STRT_ADD_LUMA); + regw(top_strt_chroma, VPIF_CH1_TOP_STRT_ADD_CHROMA); + regw(btm_strt_chroma, VPIF_CH1_BTM_STRT_ADD_CHROMA); +} + +static inline void ch0_set_vbi_addr(unsigned long top_vbi, + unsigned long btm_vbi, unsigned long a, unsigned long b) +{ + regw(top_vbi, VPIF_CH0_TOP_STRT_ADD_VANC); + regw(btm_vbi, VPIF_CH0_BTM_STRT_ADD_VANC); +} + +static inline void ch0_set_hbi_addr(unsigned long top_vbi, + unsigned long btm_vbi, unsigned long a, unsigned long b) +{ + regw(top_vbi, VPIF_CH0_TOP_STRT_ADD_HANC); + regw(btm_vbi, VPIF_CH0_BTM_STRT_ADD_HANC); +} + +static inline void ch1_set_vbi_addr(unsigned long top_vbi, + unsigned long btm_vbi, unsigned long a, unsigned long b) +{ + regw(top_vbi, VPIF_CH1_TOP_STRT_ADD_VANC); + regw(btm_vbi, VPIF_CH1_BTM_STRT_ADD_VANC); +} + +static inline void ch1_set_hbi_addr(unsigned long top_vbi, + unsigned long btm_vbi, unsigned long a, unsigned long b) +{ + regw(top_vbi, VPIF_CH1_TOP_STRT_ADD_HANC); + regw(btm_vbi, VPIF_CH1_BTM_STRT_ADD_HANC); +} + +/* Inline function to enable raw vbi in the given channel */ +static inline void disable_raw_feature(u8 channel_id, u8 index) +{ + u32 ctrl_reg; + if (0 == channel_id) + ctrl_reg = VPIF_CH0_CTRL; + else + ctrl_reg = VPIF_CH1_CTRL; + + if (1 == index) + vpif_clr_bit(ctrl_reg, VPIF_CH_VANC_EN_BIT); + else + vpif_clr_bit(ctrl_reg, VPIF_CH_HANC_EN_BIT); +} + +static inline void enable_raw_feature(u8 channel_id, u8 index) +{ + u32 ctrl_reg; + if (0 == channel_id) + ctrl_reg = VPIF_CH0_CTRL; + else + ctrl_reg = VPIF_CH1_CTRL; + + if (1 == index) + vpif_set_bit(ctrl_reg, VPIF_CH_VANC_EN_BIT); + else + vpif_set_bit(ctrl_reg, VPIF_CH_HANC_EN_BIT); +} + +/* inline function to enable/disable channel2 */ +static inline void enable_channel2(int enable) +{ + if (enable) { + regw((regr(VPIF_CH2_CTRL) | (VPIF_CH2_CLK_EN)), VPIF_CH2_CTRL); + regw((regr(VPIF_CH2_CTRL) | (VPIF_CH2_EN)), VPIF_CH2_CTRL); + } else { + regw((regr(VPIF_CH2_CTRL) & (~VPIF_CH2_CLK_EN)), VPIF_CH2_CTRL); + regw((regr(VPIF_CH2_CTRL) & (~VPIF_CH2_EN)), VPIF_CH2_CTRL); + } +} + +/* inline function to enable/disable channel3 */ +static inline void enable_channel3(int enable) +{ + if (enable) { + regw((regr(VPIF_CH3_CTRL) | (VPIF_CH3_CLK_EN)), VPIF_CH3_CTRL); + regw((regr(VPIF_CH3_CTRL) | (VPIF_CH3_EN)), VPIF_CH3_CTRL); + } else { + regw((regr(VPIF_CH3_CTRL) & (~VPIF_CH3_CLK_EN)), VPIF_CH3_CTRL); + regw((regr(VPIF_CH3_CTRL) & (~VPIF_CH3_EN)), VPIF_CH3_CTRL); + } +} + +/* inline function to enable interrupt for channel2 */ +static inline void channel2_intr_enable(int enable) +{ + if (enable) { + regw((regr(VPIF_INTEN) | 0x10), VPIF_INTEN); + regw((regr(VPIF_INTEN_SET) | 0x10), VPIF_INTEN_SET); + regw((regr(VPIF_INTEN) | VPIF_INTEN_FRAME_CH2), VPIF_INTEN); + regw((regr(VPIF_INTEN_SET) | VPIF_INTEN_FRAME_CH2), + VPIF_INTEN_SET); + } else { + regw((regr(VPIF_INTEN) & (~VPIF_INTEN_FRAME_CH2)), VPIF_INTEN); + regw((regr(VPIF_INTEN_SET) | VPIF_INTEN_FRAME_CH2), + VPIF_INTEN_SET); + } +} + +/* inline function to enable interrupt for channel3 */ +static inline void channel3_intr_enable(int enable) +{ + if (enable) { + regw((regr(VPIF_INTEN) | 0x10), VPIF_INTEN); + regw((regr(VPIF_INTEN_SET) | 0x10), VPIF_INTEN_SET); + + regw((regr(VPIF_INTEN) | VPIF_INTEN_FRAME_CH3), VPIF_INTEN); + regw((regr(VPIF_INTEN_SET) | VPIF_INTEN_FRAME_CH3), + VPIF_INTEN_SET); + } else { + regw((regr(VPIF_INTEN) & (~VPIF_INTEN_FRAME_CH3)), VPIF_INTEN); + regw((regr(VPIF_INTEN_SET) | VPIF_INTEN_FRAME_CH3), + VPIF_INTEN_SET); + } +} + +/* inline function to enable raw vbi data for channel2 */ +static inline void channel2_raw_enable(int enable, u8 index) +{ + u32 mask; + + if (1 == index) + mask = VPIF_CH_VANC_EN_BIT; + else + mask = VPIF_CH_HANC_EN_BIT; + + if (enable) + vpif_set_bit(VPIF_CH2_CTRL, mask); + else + vpif_clr_bit(VPIF_CH2_CTRL, mask); +} + +/* inline function to enable raw vbi data for channel3*/ +static inline void channel3_raw_enable(int enable, u8 index) +{ + u32 mask; + + if (1 == index) + mask = VPIF_CH_VANC_EN_BIT; + else + mask = VPIF_CH_HANC_EN_BIT; + + if (enable) + vpif_set_bit(VPIF_CH3_CTRL, mask); + else + vpif_clr_bit(VPIF_CH3_CTRL, mask); +} + +/* inline function to set buffer addresses in case of Y/C non mux mode */ +static inline void ch2_set_videobuf_addr_yc_nmux(unsigned long top_strt_luma, + unsigned long btm_strt_luma, + unsigned long top_strt_chroma, + unsigned long btm_strt_chroma) +{ + regw(top_strt_luma, VPIF_CH2_TOP_STRT_ADD_LUMA); + regw(btm_strt_luma, VPIF_CH2_BTM_STRT_ADD_LUMA); + regw(top_strt_chroma, VPIF_CH3_TOP_STRT_ADD_CHROMA); + regw(btm_strt_chroma, VPIF_CH3_BTM_STRT_ADD_CHROMA); +} + +/* inline function to set buffer addresses in VPIF registers for video data */ +static inline void ch2_set_videobuf_addr(unsigned long top_strt_luma, + unsigned long btm_strt_luma, + unsigned long top_strt_chroma, + unsigned long btm_strt_chroma) +{ + regw(top_strt_luma, VPIF_CH2_TOP_STRT_ADD_LUMA); + regw(btm_strt_luma, VPIF_CH2_BTM_STRT_ADD_LUMA); + regw(top_strt_chroma, VPIF_CH2_TOP_STRT_ADD_CHROMA); + regw(btm_strt_chroma, VPIF_CH2_BTM_STRT_ADD_CHROMA); +} + +static inline void ch3_set_videobuf_addr(unsigned long top_strt_luma, + unsigned long btm_strt_luma, + unsigned long top_strt_chroma, + unsigned long btm_strt_chroma) +{ + regw(top_strt_luma, VPIF_CH3_TOP_STRT_ADD_LUMA); + regw(btm_strt_luma, VPIF_CH3_BTM_STRT_ADD_LUMA); + regw(top_strt_chroma, VPIF_CH3_TOP_STRT_ADD_CHROMA); + regw(btm_strt_chroma, VPIF_CH3_BTM_STRT_ADD_CHROMA); +} + +/* inline function to set buffer addresses in VPIF registers for vbi data */ +static inline void ch2_set_vbi_addr(unsigned long top_strt_luma, + unsigned long btm_strt_luma, + unsigned long top_strt_chroma, + unsigned long btm_strt_chroma) +{ + regw(top_strt_luma, VPIF_CH2_TOP_STRT_ADD_VANC); + regw(btm_strt_luma, VPIF_CH2_BTM_STRT_ADD_VANC); +} + +static inline void ch3_set_vbi_addr(unsigned long top_strt_luma, + unsigned long btm_strt_luma, + unsigned long top_strt_chroma, + unsigned long btm_strt_chroma) +{ + regw(top_strt_luma, VPIF_CH3_TOP_STRT_ADD_VANC); + regw(btm_strt_luma, VPIF_CH3_BTM_STRT_ADD_VANC); +} + +#define VPIF_MAX_NAME (30) + +/* This structure will store size parameters as per the mode selected by user */ +struct vpif_channel_config_params { + char name[VPIF_MAX_NAME]; /* Name of the mode */ + u16 width; /* Indicates width of the image */ + u16 height; /* Indicates height of the image */ + u8 fps; + u8 frm_fmt; /* Indicates whether this is interlaced + * or progressive format */ + u8 ycmux_mode; /* Indicates whether this mode requires + * single or two channels */ + u16 eav2sav; /* length of sav 2 eav */ + u16 sav2eav; /* length of sav 2 eav */ + u16 l1, l3, l5, l7, l9, l11; /* Other parameter configurations */ + u16 vsize; /* Vertical size of the image */ + u8 capture_format; /* Indicates whether capture format + * is in BT or in CCD/CMOS */ + u8 vbi_supported; /* Indicates whether this mode + * supports capturing vbi or not */ + u8 hd_sd; + v4l2_std_id stdid; +}; + +struct vpif_interface; +struct vpif_params; +struct vpif_vbi_params; + +int vpif_set_video_params(struct vpif_params *vpifparams, u8 channel_id); +void vpif_set_vbi_display_params(struct vpif_vbi_params *vbiparams, + u8 channel_id); +int vpif_channel_getfid(u8 channel_id); +void vpif_base_addr_init(void __iomem *base); + +/* Enumerated data types */ +enum vpif_capture_pinpol { + VPIF_CAPTURE_PINPOL_SAME = 0, + VPIF_CAPTURE_PINPOL_INVERT = 1 +}; + +enum data_size { + _8BITS = 0, + _10BITS, + _12BITS, +}; + +struct vpif_capture_params_raw { + enum data_size data_sz; + enum vpif_capture_pinpol fid_pol; + enum vpif_capture_pinpol vd_pol; + enum vpif_capture_pinpol hd_pol; +}; + +/* Structure for vpif parameters for raw vbi data */ +struct vpif_vbi_params { + __u32 hstart0; /* Horizontal start of raw vbi data for first field */ + __u32 vstart0; /* Vertical start of raw vbi data for first field */ + __u32 hsize0; /* Horizontal size of raw vbi data for first field */ + __u32 vsize0; /* Vertical size of raw vbi data for first field */ + __u32 hstart1; /* Horizontal start of raw vbi data for second field */ + __u32 vstart1; /* Vertical start of raw vbi data for second field */ + __u32 hsize1; /* Horizontal size of raw vbi data for second field */ + __u32 vsize1; /* Vertical size of raw vbi data for second field */ +}; + +/* structure for vpif parameters */ +struct vpif_interface { + __u8 storage_mode; /* Indicates field or frame mode */ + unsigned long hpitch; + v4l2_std_id stdid; +}; + +struct vpif_params { + struct vpif_interface video_params; + struct vpif_channel_config_params std_info; + union param { + struct vpif_vbi_params vbi_params; + struct vpif_capture_params_raw raw_params; + } params; +}; + +#endif /* End of #ifndef VPIF_H */ + -- cgit v1.2.3 From a97d14d9276802762e30cd33312dca3cee970e68 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Tue, 9 Jun 2009 10:55:37 +0200 Subject: DaVinci: DM646x Video: Add VPIF display driver From: Chaithrika U S Display driver for VPIF Adds the VPIF display driver and the associated header file. Priority: normal Signed-off-by: Manjunath Hadli Signed-off-by: Brijesh Jadav Signed-off-by: Chaithrika U S Reviewed-by: Hans Verkuil Signed-off-by: Hans Verkuil --- linux/drivers/media/video/davinci/vpif_display.c | 1664 ++++++++++++++++++++++ linux/drivers/media/video/davinci/vpif_display.h | 175 +++ 2 files changed, 1839 insertions(+) create mode 100644 linux/drivers/media/video/davinci/vpif_display.c create mode 100644 linux/drivers/media/video/davinci/vpif_display.h (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/davinci/vpif_display.c b/linux/drivers/media/video/davinci/vpif_display.c new file mode 100644 index 000000000..5e2b86b3f --- /dev/null +++ b/linux/drivers/media/video/davinci/vpif_display.c @@ -0,0 +1,1664 @@ +/* + * vpif-display - VPIF display driver + * Display driver for TI DaVinci VPIF + * + * Copyright (C) 2009 Texas Instruments Incorporated - http://www.ti.com/ + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation version 2. + * + * This program is distributed .as is. WITHOUT ANY WARRANTY of any + * kind, whether express or implied; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + +#include + +#include "vpif_display.h" +#include "vpif.h" + +MODULE_DESCRIPTION("TI DaVinci VPIF Display driver"); +MODULE_LICENSE("GPL"); + +#define DM646X_V4L2_STD (V4L2_STD_525_60 | V4L2_STD_625_50) + +#define vpif_err(fmt, arg...) v4l2_err(&vpif_obj.v4l2_dev, fmt, ## arg) +#define vpif_dbg(level, debug, fmt, arg...) \ + v4l2_dbg(level, debug, &vpif_obj.v4l2_dev, fmt, ## arg) + +static int debug = 1; +static u32 ch2_numbuffers = 3; +static u32 ch3_numbuffers = 3; +static u32 ch2_bufsize = 1920 * 1080 * 2; +static u32 ch3_bufsize = 720 * 576 * 2; + +module_param(debug, int, 0644); +module_param(ch2_numbuffers, uint, S_IRUGO); +module_param(ch3_numbuffers, uint, S_IRUGO); +module_param(ch2_bufsize, uint, S_IRUGO); +module_param(ch3_bufsize, uint, S_IRUGO); + +MODULE_PARM_DESC(debug, "Debug level 0-1"); +MODULE_PARM_DESC(ch2_numbuffers, "Channel2 buffer count (default:3)"); +MODULE_PARM_DESC(ch3_numbuffers, "Channel3 buffer count (default:3)"); +MODULE_PARM_DESC(ch2_bufsize, "Channel2 buffer size (default:1920 x 1080 x 2)"); +MODULE_PARM_DESC(ch3_bufsize, "Channel3 buffer size (default:720 x 576 x 2)"); + +static struct vpif_config_params config_params = { + .min_numbuffers = 3, + .numbuffers[0] = 3, + .numbuffers[1] = 3, + .min_bufsize[0] = 720 * 480 * 2, + .min_bufsize[1] = 720 * 480 * 2, + .channel_bufsize[0] = 1920 * 1080 * 2, + .channel_bufsize[1] = 720 * 576 * 2, +}; + +static struct vpif_device vpif_obj = { {NULL} }; +static struct device *vpif_dev; + +static const struct vpif_channel_config_params ch_params[] = { + { + "NTSC", 720, 480, 30, 0, 1, 268, 1440, 1, 23, 263, 266, + 286, 525, 525, 0, 1, 0, V4L2_STD_525_60, + }, + { + "PAL", 720, 576, 25, 0, 1, 280, 1440, 1, 23, 311, 313, + 336, 624, 625, 0, 1, 0, V4L2_STD_625_50, + }, +}; + +/* + * vpif_uservirt_to_phys: This function is used to convert user + * space virtual address to physical address. + */ +static u32 vpif_uservirt_to_phys(u32 virtp) +{ + struct mm_struct *mm = current->mm; + unsigned long physp = 0; + struct vm_area_struct *vma; + + vma = find_vma(mm, virtp); + + /* For kernel direct-mapped memory, take the easy way */ + if (virtp >= PAGE_OFFSET) { + physp = virt_to_phys((void *)virtp); + } else if (vma && (vma->vm_flags & VM_IO) && (vma->vm_pgoff)) { + /* this will catch, kernel-allocated, mmaped-to-usermode addr */ + physp = (vma->vm_pgoff << PAGE_SHIFT) + (virtp - vma->vm_start); + } else { + /* otherwise, use get_user_pages() for general userland pages */ + int res, nr_pages = 1; + struct page *pages; + down_read(¤t->mm->mmap_sem); + + res = get_user_pages(current, current->mm, + virtp, nr_pages, 1, 0, &pages, NULL); + up_read(¤t->mm->mmap_sem); + + if (res == nr_pages) { + physp = __pa(page_address(&pages[0]) + + (virtp & ~PAGE_MASK)); + } else { + vpif_err("get_user_pages failed\n"); + return 0; + } + } + + return physp; +} + +/* + * buffer_prepare: This is the callback function called from videobuf_qbuf() + * function the buffer is prepared and user space virtual address is converted + * into physical address + */ +static int vpif_buffer_prepare(struct videobuf_queue *q, + struct videobuf_buffer *vb, + enum v4l2_field field) +{ + struct vpif_fh *fh = q->priv_data; + struct common_obj *common; + unsigned long addr; + + common = &fh->channel->common[VPIF_VIDEO_INDEX]; + if (VIDEOBUF_NEEDS_INIT == vb->state) { + vb->width = common->width; + vb->height = common->height; + vb->size = vb->width * vb->height; + vb->field = field; + } + vb->state = VIDEOBUF_PREPARED; + + /* if user pointer memory mechanism is used, get the physical + * address of the buffer */ + if (V4L2_MEMORY_USERPTR == common->memory) { + if (!vb->baddr) { + vpif_err("buffer_address is 0\n"); + return -EINVAL; + } + + vb->boff = vpif_uservirt_to_phys(vb->baddr); + if (!ISALIGNED(vb->boff)) + goto buf_align_exit; + } + + addr = vb->boff; + if (q->streaming && (V4L2_BUF_TYPE_SLICED_VBI_OUTPUT != q->type)) { + if (!ISALIGNED(addr + common->ytop_off) || + !ISALIGNED(addr + common->ybtm_off) || + !ISALIGNED(addr + common->ctop_off) || + !ISALIGNED(addr + common->cbtm_off)) + goto buf_align_exit; + } + return 0; + +buf_align_exit: + vpif_err("buffer offset not aligned to 8 bytes\n"); + return -EINVAL; +} + +/* + * vpif_buffer_setup: This function allocates memory for the buffers + */ +static int vpif_buffer_setup(struct videobuf_queue *q, unsigned int *count, + unsigned int *size) +{ + struct vpif_fh *fh = q->priv_data; + struct channel_obj *ch = fh->channel; + struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; + + if (V4L2_MEMORY_MMAP != common->memory) + return 0; + + *size = config_params.channel_bufsize[ch->channel_id]; + if (*count < config_params.min_numbuffers) + *count = config_params.min_numbuffers; + + return 0; +} + +/* + * vpif_buffer_queue: This function adds the buffer to DMA queue + */ +static void vpif_buffer_queue(struct videobuf_queue *q, + struct videobuf_buffer *vb) +{ + struct vpif_fh *fh = q->priv_data; + struct common_obj *common; + + common = &fh->channel->common[VPIF_VIDEO_INDEX]; + + /* add the buffer to the DMA queue */ + list_add_tail(&vb->queue, &common->dma_queue); + vb->state = VIDEOBUF_QUEUED; +} + +/* + * vpif_buffer_release: This function is called from the videobuf layer to + * free memory allocated to the buffers + */ +static void vpif_buffer_release(struct videobuf_queue *q, + struct videobuf_buffer *vb) +{ + struct vpif_fh *fh = q->priv_data; + struct channel_obj *ch = fh->channel; + struct common_obj *common; + unsigned int buf_size = 0; + + common = &ch->common[VPIF_VIDEO_INDEX]; + + videobuf_dma_contig_free(q, vb); + vb->state = VIDEOBUF_NEEDS_INIT; + + if (V4L2_MEMORY_MMAP != common->memory) + return; + + buf_size = config_params.channel_bufsize[ch->channel_id]; +} + +static struct videobuf_queue_ops video_qops = { + .buf_setup = vpif_buffer_setup, + .buf_prepare = vpif_buffer_prepare, + .buf_queue = vpif_buffer_queue, + .buf_release = vpif_buffer_release, +}; +static u8 channel_first_int[VPIF_NUMOBJECTS][2] = { {1, 1} }; + +static void process_progressive_mode(struct common_obj *common) +{ + unsigned long addr = 0; + + /* Get the next buffer from buffer queue */ + common->next_frm = list_entry(common->dma_queue.next, + struct videobuf_buffer, queue); + /* Remove that buffer from the buffer queue */ + list_del(&common->next_frm->queue); + /* Mark status of the buffer as active */ + common->next_frm->state = VIDEOBUF_ACTIVE; + + /* Set top and bottom field addrs in VPIF registers */ + addr = videobuf_to_dma_contig(common->next_frm); + common->set_addr(addr + common->ytop_off, + addr + common->ybtm_off, + addr + common->ctop_off, + addr + common->cbtm_off); +} + +static void process_interlaced_mode(int fid, struct common_obj *common) +{ + /* device field id and local field id are in sync */ + /* If this is even field */ + if (0 == fid) { + if (common->cur_frm == common->next_frm) + return; + + /* one frame is displayed If next frame is + * available, release cur_frm and move on */ + /* Copy frame display time */ + do_gettimeofday(&common->cur_frm->ts); + /* Change status of the cur_frm */ + common->cur_frm->state = VIDEOBUF_DONE; + /* unlock semaphore on cur_frm */ + wake_up_interruptible(&common->cur_frm->done); + /* Make cur_frm pointing to next_frm */ + common->cur_frm = common->next_frm; + + } else if (1 == fid) { /* odd field */ + if (list_empty(&common->dma_queue) + || (common->cur_frm != common->next_frm)) { + return; + } + /* one field is displayed configure the next + * frame if it is available else hold on current + * frame */ + /* Get next from the buffer queue */ + process_progressive_mode(common); + + } +} + +/* + * vpif_channel_isr: It changes status of the displayed buffer, takes next + * buffer from the queue and sets its address in VPIF registers + */ +static irqreturn_t vpif_channel_isr(int irq, void *dev_id) +{ + struct vpif_device *dev = &vpif_obj; + struct channel_obj *ch; + struct common_obj *common; + enum v4l2_field field; + int fid = -1, i; + int channel_id = 0; + + channel_id = *(int *)(dev_id); + ch = dev->dev[channel_id]; + field = ch->common[VPIF_VIDEO_INDEX].fmt.fmt.pix.field; + for (i = 0; i < VPIF_NUMOBJECTS; i++) { + common = &ch->common[i]; + /* If streaming is started in this channel */ + if (0 == common->started) + continue; + + if (1 == ch->vpifparams.std_info.frm_fmt) { + if (list_empty(&common->dma_queue)) + continue; + + /* Progressive mode */ + if (!channel_first_int[i][channel_id]) { + /* Mark status of the cur_frm to + * done and unlock semaphore on it */ + do_gettimeofday(&common->cur_frm->ts); + common->cur_frm->state = VIDEOBUF_DONE; + wake_up_interruptible(&common->cur_frm->done); + /* Make cur_frm pointing to next_frm */ + common->cur_frm = common->next_frm; + } + + channel_first_int[i][channel_id] = 0; + process_progressive_mode(common); + } else { + /* Interlaced mode */ + /* If it is first interrupt, ignore it */ + + if (channel_first_int[i][channel_id]) { + channel_first_int[i][channel_id] = 0; + continue; + } + + if (0 == i) { + ch->field_id ^= 1; + /* Get field id from VPIF registers */ + fid = vpif_channel_getfid(ch->channel_id + 2); + /* If fid does not match with stored field id */ + if (fid != ch->field_id) { + /* Make them in sync */ + if (0 == fid) + ch->field_id = fid; + + return IRQ_HANDLED; + } + } + process_interlaced_mode(fid, common); + } + } + + return IRQ_HANDLED; +} + +static int vpif_get_std_info(struct channel_obj *ch) +{ + struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; + struct video_obj *vid_ch = &ch->video; + struct vpif_params *vpifparams = &ch->vpifparams; + struct vpif_channel_config_params *std_info = &vpifparams->std_info; + const struct vpif_channel_config_params *config; + + int index; + + std_info->stdid = vid_ch->stdid; + if (!std_info) + return -1; + + for (index = 0; index < ARRAY_SIZE(ch_params); index++) { + config = &ch_params[index]; + if (config->stdid & std_info->stdid) { + memcpy(std_info, config, sizeof(*config)); + break; + } + } + + if (index == ARRAY_SIZE(ch_params)) + return -1; + + common->fmt.fmt.pix.width = std_info->width; + common->fmt.fmt.pix.height = std_info->height; + vpif_dbg(1, debug, "Pixel details: Width = %d,Height = %d\n", + common->fmt.fmt.pix.width, common->fmt.fmt.pix.height); + + /* Set height and width paramateres */ + ch->common[VPIF_VIDEO_INDEX].height = std_info->height; + ch->common[VPIF_VIDEO_INDEX].width = std_info->width; + + return 0; +} + +/* + * vpif_calculate_offsets: This function calculates buffers offset for Y and C + * in the top and bottom field + */ +static void vpif_calculate_offsets(struct channel_obj *ch) +{ + struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; + struct vpif_params *vpifparams = &ch->vpifparams; + enum v4l2_field field = common->fmt.fmt.pix.field; + struct video_obj *vid_ch = &ch->video; + unsigned int hpitch, vpitch, sizeimage; + + if (V4L2_FIELD_ANY == common->fmt.fmt.pix.field) { + if (ch->vpifparams.std_info.frm_fmt) + vid_ch->buf_field = V4L2_FIELD_NONE; + else + vid_ch->buf_field = V4L2_FIELD_INTERLACED; + } else { + vid_ch->buf_field = common->fmt.fmt.pix.field; + } + + if (V4L2_MEMORY_USERPTR == common->memory) + sizeimage = common->fmt.fmt.pix.sizeimage; + else + sizeimage = config_params.channel_bufsize[ch->channel_id]; + + hpitch = common->fmt.fmt.pix.bytesperline; + vpitch = sizeimage / (hpitch * 2); + if ((V4L2_FIELD_NONE == vid_ch->buf_field) || + (V4L2_FIELD_INTERLACED == vid_ch->buf_field)) { + common->ytop_off = 0; + common->ybtm_off = hpitch; + common->ctop_off = sizeimage / 2; + common->cbtm_off = sizeimage / 2 + hpitch; + } else if (V4L2_FIELD_SEQ_TB == vid_ch->buf_field) { + common->ytop_off = 0; + common->ybtm_off = sizeimage / 4; + common->ctop_off = sizeimage / 2; + common->cbtm_off = common->ctop_off + sizeimage / 4; + } else if (V4L2_FIELD_SEQ_BT == vid_ch->buf_field) { + common->ybtm_off = 0; + common->ytop_off = sizeimage / 4; + common->cbtm_off = sizeimage / 2; + common->ctop_off = common->cbtm_off + sizeimage / 4; + } + + if ((V4L2_FIELD_NONE == vid_ch->buf_field) || + (V4L2_FIELD_INTERLACED == vid_ch->buf_field)) { + vpifparams->video_params.storage_mode = 1; + } else { + vpifparams->video_params.storage_mode = 0; + } + + if (ch->vpifparams.std_info.frm_fmt == 1) { + vpifparams->video_params.hpitch = + common->fmt.fmt.pix.bytesperline; + } else { + if ((field == V4L2_FIELD_ANY) || + (field == V4L2_FIELD_INTERLACED)) + vpifparams->video_params.hpitch = + common->fmt.fmt.pix.bytesperline * 2; + else + vpifparams->video_params.hpitch = + common->fmt.fmt.pix.bytesperline; + } + + ch->vpifparams.video_params.stdid = ch->vpifparams.std_info.stdid; +} + +static void vpif_config_format(struct channel_obj *ch) +{ + struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; + + common->fmt.fmt.pix.field = V4L2_FIELD_ANY; + if (config_params.numbuffers[ch->channel_id] == 0) + common->memory = V4L2_MEMORY_USERPTR; + else + common->memory = V4L2_MEMORY_MMAP; + + common->fmt.fmt.pix.sizeimage = + config_params.channel_bufsize[ch->channel_id]; + common->fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUV422P; + common->fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT; +} + +static int vpif_check_format(struct channel_obj *ch, + struct v4l2_pix_format *pixfmt) +{ + struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; + enum v4l2_field field = pixfmt->field; + u32 sizeimage, hpitch, vpitch; + + if (pixfmt->pixelformat != V4L2_PIX_FMT_YUV422P) + goto invalid_fmt_exit; + + if (!(VPIF_VALID_FIELD(field))) + goto invalid_fmt_exit; + + if (pixfmt->bytesperline <= 0) + goto invalid_pitch_exit; + + if (V4L2_MEMORY_USERPTR == common->memory) + sizeimage = pixfmt->sizeimage; + else + sizeimage = config_params.channel_bufsize[ch->channel_id]; + + if (vpif_get_std_info(ch)) { + vpif_err("Error getting the standard info\n"); + return -EINVAL; + } + + hpitch = pixfmt->bytesperline; + vpitch = sizeimage / (hpitch * 2); + + /* Check for valid value of pitch */ + if ((hpitch < ch->vpifparams.std_info.width) || + (vpitch < ch->vpifparams.std_info.height)) + goto invalid_pitch_exit; + + /* Check for 8 byte alignment */ + if (!ISALIGNED(hpitch)) { + vpif_err("invalid pitch alignment\n"); + return -EINVAL; + } + pixfmt->width = common->fmt.fmt.pix.width; + pixfmt->height = common->fmt.fmt.pix.height; + + return 0; + +invalid_fmt_exit: + vpif_err("invalid field format\n"); + return -EINVAL; + +invalid_pitch_exit: + vpif_err("invalid pitch\n"); + return -EINVAL; +} + +static void vpif_config_addr(struct channel_obj *ch, int muxmode) +{ + struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; + + if (VPIF_CHANNEL3_VIDEO == ch->channel_id) { + common->set_addr = ch3_set_videobuf_addr; + } else { + if (2 == muxmode) + common->set_addr = ch2_set_videobuf_addr_yc_nmux; + else + common->set_addr = ch2_set_videobuf_addr; + } +} + +/* + * vpif_mmap: It is used to map kernel space buffers into user spaces + */ +static int vpif_mmap(struct file *filep, struct vm_area_struct *vma) +{ + struct vpif_fh *fh = filep->private_data; + struct common_obj *common = &fh->channel->common[VPIF_VIDEO_INDEX]; + + return videobuf_mmap_mapper(&common->buffer_queue, vma); +} + +/* + * vpif_poll: It is used for select/poll system call + */ +static unsigned int vpif_poll(struct file *filep, poll_table *wait) +{ + struct vpif_fh *fh = filep->private_data; + struct channel_obj *ch = fh->channel; + struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; + + if (common->started) + return videobuf_poll_stream(filep, &common->buffer_queue, wait); + + return 0; +} + +/* + * vpif_open: It creates object of file handle structure and stores it in + * private_data member of filepointer + */ +static int vpif_open(struct file *filep) +{ + struct video_device *vdev = video_devdata(filep); + struct channel_obj *ch = NULL; + struct vpif_fh *fh = NULL; + + ch = video_get_drvdata(vdev); + /* Allocate memory for the file handle object */ + fh = kmalloc(sizeof(struct vpif_fh), GFP_KERNEL); + if (fh == NULL) { + vpif_err("unable to allocate memory for file handle object\n"); + return -ENOMEM; + } + + /* store pointer to fh in private_data member of filep */ + filep->private_data = fh; + fh->channel = ch; + fh->initialized = 0; + if (!ch->initialized) { + fh->initialized = 1; + ch->initialized = 1; + memset(&ch->vpifparams, 0, sizeof(ch->vpifparams)); + } + + /* Increment channel usrs counter */ + atomic_inc(&ch->usrs); + /* Set io_allowed[VPIF_VIDEO_INDEX] member to false */ + fh->io_allowed[VPIF_VIDEO_INDEX] = 0; + /* Initialize priority of this instance to default priority */ + fh->prio = V4L2_PRIORITY_UNSET; + v4l2_prio_open(&ch->prio, &fh->prio); + + return 0; +} + +/* + * vpif_release: This function deletes buffer queue, frees the buffers and + * the vpif file handle + */ +static int vpif_release(struct file *filep) +{ + struct vpif_fh *fh = filep->private_data; + struct channel_obj *ch = fh->channel; + struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; + + mutex_lock_interruptible(&common->lock); + /* if this instance is doing IO */ + if (fh->io_allowed[VPIF_VIDEO_INDEX]) { + /* Reset io_usrs member of channel object */ + common->io_usrs = 0; + /* Disable channel */ + if (VPIF_CHANNEL2_VIDEO == ch->channel_id) { + enable_channel2(0); + channel2_intr_enable(0); + } + if ((VPIF_CHANNEL3_VIDEO == ch->channel_id) || + (2 == common->started)) { + enable_channel3(0); + channel3_intr_enable(0); + } + common->started = 0; + /* Free buffers allocated */ + videobuf_queue_cancel(&common->buffer_queue); + videobuf_mmap_free(&common->buffer_queue); + common->numbuffers = + config_params.numbuffers[ch->channel_id]; + } + + mutex_unlock(&common->lock); + + /* Decrement channel usrs counter */ + atomic_dec(&ch->usrs); + /* If this file handle has initialize encoder device, reset it */ + if (fh->initialized) + ch->initialized = 0; + + /* Close the priority */ + v4l2_prio_close(&ch->prio, &fh->prio); + filep->private_data = NULL; + fh->initialized = 0; + kfree(fh); + + return 0; +} + +/* functions implementing ioctls */ + +static int vpif_querycap(struct file *file, void *priv, + struct v4l2_capability *cap) +{ + struct vpif_config *config = vpif_dev->platform_data; + + cap->version = VPIF_DISPLAY_VERSION_CODE; + cap->capabilities = V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_STREAMING; + strlcpy(cap->driver, "vpif display", sizeof(cap->driver)); + strlcpy(cap->bus_info, "Platform", sizeof(cap->bus_info)); + strlcpy(cap->card, config->card_name, sizeof(cap->card)); + + return 0; +} + +static int vpif_enum_fmt_vid_out(struct file *file, void *priv, + struct v4l2_fmtdesc *fmt) +{ + if (fmt->index != 0) { + vpif_err("Invalid format index\n"); + return -EINVAL; + } + + /* Fill in the information about format */ + fmt->type = V4L2_BUF_TYPE_VIDEO_OUTPUT; + strcpy(fmt->description, "YCbCr4:2:2 YC Planar"); + fmt->pixelformat = V4L2_PIX_FMT_YUV422P; + + return 0; +} + +static int vpif_g_fmt_vid_out(struct file *file, void *priv, + struct v4l2_format *fmt) +{ + struct vpif_fh *fh = priv; + struct channel_obj *ch = fh->channel; + struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; + + /* Check the validity of the buffer type */ + if (common->fmt.type != fmt->type) + return -EINVAL; + + /* Fill in the information about format */ + mutex_lock_interruptible(&common->lock); + if (vpif_get_std_info(ch)) { + vpif_err("Error getting the standard info\n"); + return -EINVAL; + } + + *fmt = common->fmt; + mutex_unlock(&common->lock); + return 0; +} + +static int vpif_s_fmt_vid_out(struct file *file, void *priv, + struct v4l2_format *fmt) +{ + struct vpif_fh *fh = priv; + struct v4l2_pix_format *pixfmt; + struct channel_obj *ch = fh->channel; + struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; + int ret = 0; + + if ((VPIF_CHANNEL2_VIDEO == ch->channel_id) + || (VPIF_CHANNEL3_VIDEO == ch->channel_id)) { + if (!fh->initialized) { + vpif_dbg(1, debug, "Channel Busy\n"); + return -EBUSY; + } + + /* Check for the priority */ + ret = v4l2_prio_check(&ch->prio, &fh->prio); + if (0 != ret) + return ret; + fh->initialized = 1; + } + + if (common->started) { + vpif_dbg(1, debug, "Streaming in progress\n"); + return -EBUSY; + } + + pixfmt = &fmt->fmt.pix; + /* Check for valid field format */ + ret = vpif_check_format(ch, pixfmt); + if (ret) + return ret; + + /* store the pix format in the channel object */ + common->fmt.fmt.pix = *pixfmt; + /* store the format in the channel object */ + mutex_lock_interruptible(&common->lock); + common->fmt = *fmt; + mutex_unlock(&common->lock); + + return 0; +} + +static int vpif_try_fmt_vid_out(struct file *file, void *priv, + struct v4l2_format *fmt) +{ + struct vpif_fh *fh = priv; + struct channel_obj *ch = fh->channel; + struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; + struct v4l2_pix_format *pixfmt = &fmt->fmt.pix; + int ret = 0; + + ret = vpif_check_format(ch, pixfmt); + if (ret) { + *pixfmt = common->fmt.fmt.pix; + pixfmt->sizeimage = pixfmt->width * pixfmt->height * 2; + } + + return ret; +} + +static int vpif_reqbufs(struct file *file, void *priv, + struct v4l2_requestbuffers *reqbuf) +{ + struct vpif_fh *fh = priv; + struct channel_obj *ch = fh->channel; + struct common_obj *common; + enum v4l2_field field; + u8 index = 0; + int ret = 0; + + /* This file handle has not initialized the channel, + It is not allowed to do settings */ + if ((VPIF_CHANNEL2_VIDEO == ch->channel_id) + || (VPIF_CHANNEL3_VIDEO == ch->channel_id)) { + if (!fh->initialized) { + vpif_err("Channel Busy\n"); + return -EBUSY; + } + } + + if (V4L2_BUF_TYPE_VIDEO_OUTPUT != reqbuf->type) + return -EINVAL; + + index = VPIF_VIDEO_INDEX; + + common = &ch->common[index]; + mutex_lock_interruptible(&common->lock); + if (common->fmt.type != reqbuf->type) { + ret = -EINVAL; + goto reqbuf_exit; + } + + if (0 != common->io_usrs) { + ret = -EBUSY; + goto reqbuf_exit; + } + + if (reqbuf->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) { + if (common->fmt.fmt.pix.field == V4L2_FIELD_ANY) + field = V4L2_FIELD_INTERLACED; + else + field = common->fmt.fmt.pix.field; + } else { + field = V4L2_VBI_INTERLACED; + } + + /* Initialize videobuf queue as per the buffer type */ + videobuf_queue_dma_contig_init(&common->buffer_queue, + &video_qops, NULL, + &common->irqlock, + reqbuf->type, field, + sizeof(struct videobuf_buffer), fh); + + /* Set io allowed member of file handle to TRUE */ + fh->io_allowed[index] = 1; + /* Increment io usrs member of channel object to 1 */ + common->io_usrs = 1; + /* Store type of memory requested in channel object */ + common->memory = reqbuf->memory; + INIT_LIST_HEAD(&common->dma_queue); + + /* Allocate buffers */ + ret = videobuf_reqbufs(&common->buffer_queue, reqbuf); + +reqbuf_exit: + mutex_unlock(&common->lock); + return ret; +} + +static int vpif_querybuf(struct file *file, void *priv, + struct v4l2_buffer *tbuf) +{ + struct vpif_fh *fh = priv; + struct channel_obj *ch = fh->channel; + struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; + + if (common->fmt.type != tbuf->type) + return -EINVAL; + + return videobuf_querybuf(&common->buffer_queue, tbuf); +} + +static int vpif_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf) +{ + + struct vpif_fh *fh = priv; + struct channel_obj *ch = fh->channel; + struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; + struct v4l2_buffer tbuf = *buf; + struct videobuf_buffer *buf1; + unsigned long addr = 0; + unsigned long flags; + int ret = 0; + + if (common->fmt.type != tbuf.type) + return -EINVAL; + + if (!fh->io_allowed[VPIF_VIDEO_INDEX]) { + vpif_err("fh->io_allowed\n"); + return -EACCES; + } + + if (!(list_empty(&common->dma_queue)) || + (common->cur_frm != common->next_frm) || + !(common->started) || + (common->started && (0 == ch->field_id))) + return videobuf_qbuf(&common->buffer_queue, buf); + + /* bufferqueue is empty store buffer address in VPIF registers */ + mutex_lock(&common->buffer_queue.vb_lock); + buf1 = common->buffer_queue.bufs[tbuf.index]; + if (buf1->memory != tbuf.memory) { + vpif_err("invalid buffer type\n"); + goto qbuf_exit; + } + + if ((buf1->state == VIDEOBUF_QUEUED) || + (buf1->state == VIDEOBUF_ACTIVE)) { + vpif_err("invalid state\n"); + goto qbuf_exit; + } + + switch (buf1->memory) { + case V4L2_MEMORY_MMAP: + if (buf1->baddr == 0) + goto qbuf_exit; + break; + + case V4L2_MEMORY_USERPTR: + if (tbuf.length < buf1->bsize) + goto qbuf_exit; + + if ((VIDEOBUF_NEEDS_INIT != buf1->state) + && (buf1->baddr != tbuf.m.userptr)) + vpif_buffer_release(&common->buffer_queue, buf1); + buf1->baddr = tbuf.m.userptr; + break; + + default: + goto qbuf_exit; + } + + local_irq_save(flags); + ret = vpif_buffer_prepare(&common->buffer_queue, buf1, + common->buffer_queue.field); + if (ret < 0) { + local_irq_restore(flags); + goto qbuf_exit; + } + + buf1->state = VIDEOBUF_ACTIVE; + addr = buf1->boff; + common->next_frm = buf1; + if (tbuf.type != V4L2_BUF_TYPE_SLICED_VBI_OUTPUT) { + common->set_addr((addr + common->ytop_off), + (addr + common->ybtm_off), + (addr + common->ctop_off), + (addr + common->cbtm_off)); + } + + local_irq_restore(flags); + list_add_tail(&buf1->stream, &common->buffer_queue.stream); + mutex_unlock(&common->buffer_queue.vb_lock); + return 0; + +qbuf_exit: + mutex_unlock(&common->buffer_queue.vb_lock); + return -EINVAL; +} + +static int vpif_s_std(struct file *file, void *priv, v4l2_std_id *std_id) +{ + struct vpif_fh *fh = priv; + struct channel_obj *ch = fh->channel; + struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; + int ret = 0; + + if (!(*std_id & DM646X_V4L2_STD)) + return -EINVAL; + + if (common->started) { + vpif_err("streaming in progress\n"); + return -EBUSY; + } + + /* Call encoder subdevice function to set the standard */ + mutex_lock_interruptible(&common->lock); + + ch->video.stdid = *std_id; + /* Get the information about the standard */ + if (vpif_get_std_info(ch)) { + vpif_err("Error getting the standard info\n"); + return -EINVAL; + } + + if ((ch->vpifparams.std_info.width * + ch->vpifparams.std_info.height * 2) > + config_params.channel_bufsize[ch->channel_id]) { + vpif_err("invalid std for this size\n"); + ret = -EINVAL; + goto s_std_exit; + } + + common->fmt.fmt.pix.bytesperline = common->fmt.fmt.pix.width; + /* Configure the default format information */ + vpif_config_format(ch); + + ret = v4l2_device_call_until_err(&vpif_obj.v4l2_dev, 1, video, + s_std_output, *std_id); + if (ret < 0) { + vpif_err("Failed to set output standard\n"); + goto s_std_exit; + } + + ret = v4l2_device_call_until_err(&vpif_obj.v4l2_dev, 1, core, + s_std, *std_id); + if (ret < 0) + vpif_err("Failed to set standard for sub devices\n"); + +s_std_exit: + mutex_unlock(&common->lock); + return ret; +} + +static int vpif_g_std(struct file *file, void *priv, v4l2_std_id *std) +{ + struct vpif_fh *fh = priv; + struct channel_obj *ch = fh->channel; + + *std = ch->video.stdid; + return 0; +} + +static int vpif_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p) +{ + struct vpif_fh *fh = priv; + struct channel_obj *ch = fh->channel; + struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; + + return videobuf_dqbuf(&common->buffer_queue, p, + (file->f_flags & O_NONBLOCK)); +} + +static int vpif_streamon(struct file *file, void *priv, + enum v4l2_buf_type buftype) +{ + struct vpif_fh *fh = priv; + struct channel_obj *ch = fh->channel; + struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; + struct channel_obj *oth_ch = vpif_obj.dev[!ch->channel_id]; + struct vpif_params *vpif = &ch->vpifparams; + struct vpif_config *vpif_config_data = + vpif_dev->platform_data; + unsigned long addr = 0; + int ret = 0; + + if (buftype != V4L2_BUF_TYPE_VIDEO_OUTPUT) { + vpif_err("buffer type not supported\n"); + return -EINVAL; + } + + if (!fh->io_allowed[VPIF_VIDEO_INDEX]) { + vpif_err("fh->io_allowed\n"); + return -EACCES; + } + + /* If Streaming is already started, return error */ + if (common->started) { + vpif_err("channel->started\n"); + return -EBUSY; + } + + if ((ch->channel_id == VPIF_CHANNEL2_VIDEO + && oth_ch->common[VPIF_VIDEO_INDEX].started && + ch->vpifparams.std_info.ycmux_mode == 0) + || ((ch->channel_id == VPIF_CHANNEL3_VIDEO) + && (2 == oth_ch->common[VPIF_VIDEO_INDEX].started))) { + vpif_err("other channel is using\n"); + return -EBUSY; + } + + ret = vpif_check_format(ch, &common->fmt.fmt.pix); + if (ret < 0) + return ret; + + /* Call videobuf_streamon to start streaming in videobuf */ + ret = videobuf_streamon(&common->buffer_queue); + if (ret < 0) { + vpif_err("videobuf_streamon\n"); + return ret; + } + + mutex_lock_interruptible(&common->lock); + /* If buffer queue is empty, return error */ + if (list_empty(&common->dma_queue)) { + vpif_err("buffer queue is empty\n"); + ret = -EIO; + goto streamon_exit; + } + + /* Get the next frame from the buffer queue */ + common->next_frm = common->cur_frm = + list_entry(common->dma_queue.next, + struct videobuf_buffer, queue); + + list_del(&common->cur_frm->queue); + /* Mark state of the current frame to active */ + common->cur_frm->state = VIDEOBUF_ACTIVE; + + /* Initialize field_id and started member */ + ch->field_id = 0; + common->started = 1; + if (buftype == V4L2_BUF_TYPE_VIDEO_OUTPUT) { + addr = common->cur_frm->boff; + /* Calculate the offset for Y and C data in the buffer */ + vpif_calculate_offsets(ch); + + if ((ch->vpifparams.std_info.frm_fmt && + ((common->fmt.fmt.pix.field != V4L2_FIELD_NONE) + && (common->fmt.fmt.pix.field != V4L2_FIELD_ANY))) + || (!ch->vpifparams.std_info.frm_fmt + && (common->fmt.fmt.pix.field == V4L2_FIELD_NONE))) { + vpif_err("conflict in field format and std format\n"); + ret = -EINVAL; + goto streamon_exit; + } + + /* clock settings */ + ret = + vpif_config_data->set_clock(ch->vpifparams.std_info.ycmux_mode, + ch->vpifparams.std_info.hd_sd); + if (ret < 0) { + vpif_err("can't set clock\n"); + goto streamon_exit; + } + + /* set the parameters and addresses */ + ret = vpif_set_video_params(vpif, ch->channel_id + 2); + if (ret < 0) + goto streamon_exit; + + common->started = ret; + vpif_config_addr(ch, ret); + common->set_addr((addr + common->ytop_off), + (addr + common->ybtm_off), + (addr + common->ctop_off), + (addr + common->cbtm_off)); + + /* Set interrupt for both the fields in VPIF + Register enable channel in VPIF register */ + if (VPIF_CHANNEL2_VIDEO == ch->channel_id) { + channel2_intr_assert(); + channel2_intr_enable(1); + enable_channel2(1); + } + + if ((VPIF_CHANNEL3_VIDEO == ch->channel_id) + || (common->started == 2)) { + channel3_intr_assert(); + channel3_intr_enable(1); + enable_channel3(1); + } + channel_first_int[VPIF_VIDEO_INDEX][ch->channel_id] = 1; + } + +streamon_exit: + mutex_unlock(&common->lock); + return ret; +} + +static int vpif_streamoff(struct file *file, void *priv, + enum v4l2_buf_type buftype) +{ + struct vpif_fh *fh = priv; + struct channel_obj *ch = fh->channel; + struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; + + if (buftype != V4L2_BUF_TYPE_VIDEO_OUTPUT) { + vpif_err("buffer type not supported\n"); + return -EINVAL; + } + + if (!fh->io_allowed[VPIF_VIDEO_INDEX]) { + vpif_err("fh->io_allowed\n"); + return -EACCES; + } + + if (!common->started) { + vpif_err("channel->started\n"); + return -EINVAL; + } + + mutex_lock_interruptible(&common->lock); + if (buftype == V4L2_BUF_TYPE_VIDEO_OUTPUT) { + /* disable channel */ + if (VPIF_CHANNEL2_VIDEO == ch->channel_id) { + enable_channel2(0); + channel2_intr_enable(0); + } + if ((VPIF_CHANNEL3_VIDEO == ch->channel_id) || + (2 == common->started)) { + enable_channel3(0); + channel3_intr_enable(0); + } + } + + common->started = 0; + mutex_unlock(&common->lock); + + return videobuf_streamoff(&common->buffer_queue); +} + +static int vpif_cropcap(struct file *file, void *priv, + struct v4l2_cropcap *crop) +{ + struct vpif_fh *fh = priv; + struct channel_obj *ch = fh->channel; + struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; + if (V4L2_BUF_TYPE_VIDEO_OUTPUT != crop->type) + return -EINVAL; + + crop->bounds.left = crop->bounds.top = 0; + crop->defrect.left = crop->defrect.top = 0; + crop->defrect.height = crop->bounds.height = common->height; + crop->defrect.width = crop->bounds.width = common->width; + + return 0; +} + +static int vpif_enum_output(struct file *file, void *fh, + struct v4l2_output *output) +{ + + struct vpif_config *config = vpif_dev->platform_data; + + if (output->index >= config->output_count) { + vpif_dbg(1, debug, "Invalid output index\n"); + return -EINVAL; + } + + strcpy(output->name, config->output[output->index]); + output->type = V4L2_OUTPUT_TYPE_ANALOG; + output->std = DM646X_V4L2_STD; + + return 0; +} + +static int vpif_s_output(struct file *file, void *priv, unsigned int i) +{ + struct vpif_fh *fh = priv; + struct channel_obj *ch = fh->channel; + struct video_obj *vid_ch = &ch->video; + struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; + int ret = 0; + + mutex_lock_interruptible(&common->lock); + if (common->started) { + vpif_err("Streaming in progress\n"); + ret = -EBUSY; + goto s_output_exit; + } + + ret = v4l2_device_call_until_err(&vpif_obj.v4l2_dev, 1, video, + s_routing, 0, i, 0); + + if (ret < 0) + vpif_err("Failed to set output standard\n"); + + vid_ch->output_id = i; + +s_output_exit: + mutex_unlock(&common->lock); + return ret; +} + +static int vpif_g_output(struct file *file, void *priv, unsigned int *i) +{ + struct vpif_fh *fh = priv; + struct channel_obj *ch = fh->channel; + struct video_obj *vid_ch = &ch->video; + + *i = vid_ch->output_id; + + return 0; +} + +static int vpif_g_priority(struct file *file, void *priv, enum v4l2_priority *p) +{ + struct vpif_fh *fh = priv; + struct channel_obj *ch = fh->channel; + + *p = v4l2_prio_max(&ch->prio); + + return 0; +} + +static int vpif_s_priority(struct file *file, void *priv, enum v4l2_priority p) +{ + struct vpif_fh *fh = priv; + struct channel_obj *ch = fh->channel; + + return v4l2_prio_change(&ch->prio, &fh->prio, p); +} + +/* vpif display ioctl operations */ +static const struct v4l2_ioctl_ops vpif_ioctl_ops = { + .vidioc_querycap = vpif_querycap, + .vidioc_g_priority = vpif_g_priority, + .vidioc_s_priority = vpif_s_priority, + .vidioc_enum_fmt_vid_out = vpif_enum_fmt_vid_out, + .vidioc_g_fmt_vid_out = vpif_g_fmt_vid_out, + .vidioc_s_fmt_vid_out = vpif_s_fmt_vid_out, + .vidioc_try_fmt_vid_out = vpif_try_fmt_vid_out, + .vidioc_reqbufs = vpif_reqbufs, + .vidioc_querybuf = vpif_querybuf, + .vidioc_qbuf = vpif_qbuf, + .vidioc_dqbuf = vpif_dqbuf, + .vidioc_streamon = vpif_streamon, + .vidioc_streamoff = vpif_streamoff, + .vidioc_s_std = vpif_s_std, + .vidioc_g_std = vpif_g_std, + .vidioc_enum_output = vpif_enum_output, + .vidioc_s_output = vpif_s_output, + .vidioc_g_output = vpif_g_output, + .vidioc_cropcap = vpif_cropcap, +}; + +static const struct v4l2_file_operations vpif_fops = { + .owner = THIS_MODULE, + .open = vpif_open, + .release = vpif_release, + .ioctl = video_ioctl2, + .mmap = vpif_mmap, + .poll = vpif_poll +}; + +static struct video_device vpif_video_template = { + .name = "vpif", + .fops = &vpif_fops, + .minor = -1, + .ioctl_ops = &vpif_ioctl_ops, + .tvnorms = DM646X_V4L2_STD, + .current_norm = V4L2_STD_625_50, + +}; + +/*Configure the channels, buffer sizei, request irq */ +static int initialize_vpif(void) +{ + int free_channel_objects_index; + int free_buffer_channel_index; + int free_buffer_index; + int err = 0, i, j; + + /* Default number of buffers should be 3 */ + if ((ch2_numbuffers > 0) && + (ch2_numbuffers < config_params.min_numbuffers)) + ch2_numbuffers = config_params.min_numbuffers; + if ((ch3_numbuffers > 0) && + (ch3_numbuffers < config_params.min_numbuffers)) + ch3_numbuffers = config_params.min_numbuffers; + + /* Set buffer size to min buffers size if invalid buffer size is + * given */ + if (ch2_bufsize < config_params.min_bufsize[VPIF_CHANNEL2_VIDEO]) + ch2_bufsize = + config_params.min_bufsize[VPIF_CHANNEL2_VIDEO]; + if (ch3_bufsize < config_params.min_bufsize[VPIF_CHANNEL3_VIDEO]) + ch3_bufsize = + config_params.min_bufsize[VPIF_CHANNEL3_VIDEO]; + + config_params.numbuffers[VPIF_CHANNEL2_VIDEO] = ch2_numbuffers; + + if (ch2_numbuffers) { + config_params.channel_bufsize[VPIF_CHANNEL2_VIDEO] = + ch2_bufsize; + } + config_params.numbuffers[VPIF_CHANNEL3_VIDEO] = ch3_numbuffers; + + if (ch3_numbuffers) { + config_params.channel_bufsize[VPIF_CHANNEL3_VIDEO] = + ch3_bufsize; + } + + /* Allocate memory for six channel objects */ + for (i = 0; i < VPIF_DISPLAY_MAX_DEVICES; i++) { + vpif_obj.dev[i] = + kmalloc(sizeof(struct channel_obj), GFP_KERNEL); + /* If memory allocation fails, return error */ + if (!vpif_obj.dev[i]) { + free_channel_objects_index = i; + err = -ENOMEM; + goto vpif_init_free_channel_objects; + } + } + + free_channel_objects_index = VPIF_DISPLAY_MAX_DEVICES; + free_buffer_channel_index = VPIF_DISPLAY_NUM_CHANNELS; + free_buffer_index = config_params.numbuffers[i - 1]; + + return 0; + +vpif_init_free_channel_objects: + for (j = 0; j < free_channel_objects_index; j++) + kfree(vpif_obj.dev[j]); + return err; +} + +/* + * vpif_probe: This function creates device entries by register itself to the + * V4L2 driver and initializes fields of each channel objects + */ +static __init int vpif_probe(struct platform_device *pdev) +{ + const struct subdev_info *subdevdata; + int i, j = 0, k, q, m, err = 0; + struct i2c_adapter *i2c_adap; + struct vpif_config *config; + struct common_obj *common; + struct channel_obj *ch; + struct video_device *vfd; + struct resource *res; + int subdev_count; + + vpif_dev = &pdev->dev; + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + v4l2_err(vpif_dev->driver, + "Error getting platform resource\n"); + return -ENOENT; + } + + if (!request_mem_region(res->start, res->end - res->start + 1, + vpif_dev->driver->name)) { + v4l2_err(vpif_dev->driver, "VPIF: failed request_mem_region\n"); + return -ENXIO; + } + + vpif_base = ioremap_nocache(res->start, res->end - res->start + 1); + if (!vpif_base) { + v4l2_err(vpif_dev->driver, "Unable to ioremap VPIF reg\n"); + err = -ENXIO; + goto resource_exit; + } + + vpif_base_addr_init(vpif_base); + + initialize_vpif(); + + err = v4l2_device_register(vpif_dev, &vpif_obj.v4l2_dev); + if (err) { + v4l2_err(vpif_dev->driver, "Error registering v4l2 device\n"); + return err; + } + + k = 0; + while ((res = platform_get_resource(pdev, IORESOURCE_IRQ, k))) { + for (i = res->start; i <= res->end; i++) { + if (request_irq(i, vpif_channel_isr, IRQF_DISABLED, + "DM646x_Display", + (void *)(&vpif_obj.dev[k]->channel_id))) { + err = -EBUSY; + goto vpif_int_err; + } + } + k++; + } + + for (i = 0; i < VPIF_DISPLAY_MAX_DEVICES; i++) { + + /* Get the pointer to the channel object */ + ch = vpif_obj.dev[i]; + + /* Allocate memory for video device */ + vfd = video_device_alloc(); + if (vfd == NULL) { + for (j = 0; j < i; j++) { + ch = vpif_obj.dev[j]; + video_device_release(ch->video_dev); + } + err = -ENOMEM; + goto video_dev_alloc_exit; + } + + /* Initialize field of video device */ + *vfd = vpif_video_template; + vfd->v4l2_dev = &vpif_obj.v4l2_dev; + vfd->release = video_device_release; + snprintf(vfd->name, sizeof(vfd->name), + "DM646x_VPIFDisplay_DRIVER_V%d.%d.%d", + (VPIF_DISPLAY_VERSION_CODE >> 16) & 0xff, + (VPIF_DISPLAY_VERSION_CODE >> 8) & 0xff, + (VPIF_DISPLAY_VERSION_CODE) & 0xff); + + /* Set video_dev to the video device */ + ch->video_dev = vfd; + } + + for (j = 0; j < VPIF_DISPLAY_MAX_DEVICES; j++) { + ch = vpif_obj.dev[j]; + /* Initialize field of the channel objects */ + atomic_set(&ch->usrs, 0); + for (k = 0; k < VPIF_NUMOBJECTS; k++) { + ch->common[k].numbuffers = 0; + common = &ch->common[k]; + common->io_usrs = 0; + common->started = 0; + spin_lock_init(&common->irqlock); + mutex_init(&common->lock); + common->numbuffers = 0; + common->set_addr = NULL; + common->ytop_off = common->ybtm_off = 0; + common->ctop_off = common->cbtm_off = 0; + common->cur_frm = common->next_frm = NULL; + memset(&common->fmt, 0, sizeof(common->fmt)); + common->numbuffers = config_params.numbuffers[k]; + + } + ch->initialized = 0; + ch->channel_id = j; + if (j < 2) + ch->common[VPIF_VIDEO_INDEX].numbuffers = + config_params.numbuffers[ch->channel_id]; + else + ch->common[VPIF_VIDEO_INDEX].numbuffers = 0; + + memset(&ch->vpifparams, 0, sizeof(ch->vpifparams)); + + /* Initialize prio member of channel object */ + v4l2_prio_init(&ch->prio); + ch->common[VPIF_VIDEO_INDEX].fmt.type = + V4L2_BUF_TYPE_VIDEO_OUTPUT; + + /* register video device */ + vpif_dbg(1, debug, "channel=%x,channel->video_dev=%x\n", + (int)ch, (int)&ch->video_dev); + + err = video_register_device(ch->video_dev, + VFL_TYPE_GRABBER, (j ? 3 : 2)); + if (err < 0) + goto probe_out; + + video_set_drvdata(ch->video_dev, ch); + } + + i2c_adap = i2c_get_adapter(1); + config = pdev->dev.platform_data; + subdev_count = config->subdev_count; + subdevdata = config->subdevinfo; + vpif_obj.sd = kmalloc(sizeof(struct v4l2_subdev *) * subdev_count, + GFP_KERNEL); + if (vpif_obj.sd == NULL) { + vpif_err("unable to allocate memory for subdevice pointers\n"); + err = -ENOMEM; + goto probe_out; + } + + for (i = 0; i < subdev_count; i++) { + vpif_obj.sd[i] = v4l2_i2c_new_probed_subdev(&vpif_obj.v4l2_dev, + i2c_adap, subdevdata[i].name, + subdevdata[i].name, + &subdevdata[i].addr); + if (!vpif_obj.sd[i]) { + vpif_err("Error registering v4l2 subdevice\n"); + goto probe_subdev_out; + } + + if (vpif_obj.sd[i]) + vpif_obj.sd[i]->grp_id = 1 << i; + } + + return 0; + +probe_subdev_out: + kfree(vpif_obj.sd); +probe_out: + for (k = 0; k < j; k++) { + ch = vpif_obj.dev[k]; + video_unregister_device(ch->video_dev); + video_device_release(ch->video_dev); + ch->video_dev = NULL; + } +vpif_int_err: + v4l2_device_unregister(&vpif_obj.v4l2_dev); + vpif_err("VPIF IRQ request failed\n"); + for (q = k; k >= 0; k--) { + for (m = i; m >= res->start; m--) + free_irq(m, (void *)(&vpif_obj.dev[k]->channel_id)); + res = platform_get_resource(pdev, IORESOURCE_IRQ, k-1); + m = res->end; + } +video_dev_alloc_exit: + iounmap(vpif_base); +resource_exit: + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + release_mem_region(res->start, res->end - res->start + 1); + + return err; +} + +/* + * vpif_remove: It un-register channels from V4L2 driver + */ +static int vpif_remove(struct platform_device *device) +{ + struct channel_obj *ch; + int i; + + v4l2_device_unregister(&vpif_obj.v4l2_dev); + + /* un-register device */ + for (i = 0; i < VPIF_DISPLAY_MAX_DEVICES; i++) { + /* Get the pointer to the channel object */ + ch = vpif_obj.dev[i]; + /* Unregister video device */ + video_unregister_device(ch->video_dev); + + ch->video_dev = NULL; + } + + return 0; +} + +static struct platform_driver vpif_driver = { + .driver = { + .name = "vpif_display", + .owner = THIS_MODULE, + }, + .probe = vpif_probe, + .remove = vpif_remove, +}; + +static __init int vpif_init(void) +{ + return platform_driver_register(&vpif_driver); +} + +/* + * vpif_cleanup: This function un-registers device and driver to the kernel, + * frees requested irq handler and de-allocates memory allocated for channel + * objects. + */ +static void vpif_cleanup(void) +{ + struct platform_device *pdev; + struct resource *res; + int irq_num; + int i = 0; + + pdev = container_of(vpif_dev, struct platform_device, dev); + + while ((res = platform_get_resource(pdev, IORESOURCE_IRQ, i))) { + for (irq_num = res->start; irq_num <= res->end; irq_num++) + free_irq(irq_num, + (void *)(&vpif_obj.dev[i]->channel_id)); + i++; + } + + iounmap(vpif_base); + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + release_mem_region(res->start, res->end - res->start + 1); + platform_driver_unregister(&vpif_driver); + kfree(vpif_obj.sd); + for (i = 0; i < VPIF_DISPLAY_MAX_DEVICES; i++) + kfree(vpif_obj.dev[i]); +} + +module_init(vpif_init); +module_exit(vpif_cleanup); diff --git a/linux/drivers/media/video/davinci/vpif_display.h b/linux/drivers/media/video/davinci/vpif_display.h new file mode 100644 index 000000000..a2a7cd166 --- /dev/null +++ b/linux/drivers/media/video/davinci/vpif_display.h @@ -0,0 +1,175 @@ +/* + * DM646x display header file + * + * Copyright (C) 2009 Texas Instruments Incorporated - http://www.ti.com/ + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation version 2. + * + * This program is distributed .as is. WITHOUT ANY WARRANTY of any + * kind, whether express or implied; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef DAVINCIHD_DISPLAY_H +#define DAVINCIHD_DISPLAY_H + +/* Header files */ +#include +#include +#include +#include +#include +#include + +#include "vpif.h" + +/* Macros */ +#define VPIF_MAJOR_RELEASE (0) +#define VPIF_MINOR_RELEASE (0) +#define VPIF_BUILD (1) + +#define VPIF_DISPLAY_VERSION_CODE \ + ((VPIF_MAJOR_RELEASE << 16) | (VPIF_MINOR_RELEASE << 8) | VPIF_BUILD) + +#define VPIF_VALID_FIELD(field) \ + (((V4L2_FIELD_ANY == field) || (V4L2_FIELD_NONE == field)) || \ + (((V4L2_FIELD_INTERLACED == field) || (V4L2_FIELD_SEQ_TB == field)) || \ + (V4L2_FIELD_SEQ_BT == field))) + +#define VPIF_DISPLAY_MAX_DEVICES (2) +#define VPIF_SLICED_BUF_SIZE (256) +#define VPIF_SLICED_MAX_SERVICES (3) +#define VPIF_VIDEO_INDEX (0) +#define VPIF_VBI_INDEX (1) +#define VPIF_HBI_INDEX (2) + +/* Setting it to 1 as HBI/VBI support yet to be added , else 3*/ +#define VPIF_NUMOBJECTS (1) + +/* Macros */ +#define ISALIGNED(a) (0 == ((a) & 7)) + +/* enumerated data types */ +/* Enumerated data type to give id to each device per channel */ +enum vpif_channel_id { + VPIF_CHANNEL2_VIDEO = 0, /* Channel2 Video */ + VPIF_CHANNEL3_VIDEO, /* Channel3 Video */ +}; + +/* structures */ + +struct video_obj { + enum v4l2_field buf_field; + u32 latest_only; /* indicate whether to return + * most recent displayed frame only */ + v4l2_std_id stdid; /* Currently selected or default + * standard */ + u32 output_id; /* Current output id */ +}; + +struct vbi_obj { + int num_services; + struct vpif_vbi_params vbiparams; /* vpif parameters for the raw + * vbi data */ +}; + +struct common_obj { + /* Buffer specific parameters */ + u8 *fbuffers[VIDEO_MAX_FRAME]; /* List of buffer pointers for + * storing frames */ + u32 numbuffers; /* number of buffers */ + struct videobuf_buffer *cur_frm; /* Pointer pointing to current + * videobuf_buffer */ + struct videobuf_buffer *next_frm; /* Pointer pointing to next + * videobuf_buffer */ + enum v4l2_memory memory; /* This field keeps track of + * type of buffer exchange + * method user has selected */ + struct v4l2_format fmt; /* Used to store the format */ + struct videobuf_queue buffer_queue; /* Buffer queue used in + * video-buf */ + struct list_head dma_queue; /* Queue of filled frames */ + spinlock_t irqlock; /* Used in video-buf */ + + /* channel specific parameters */ + struct mutex lock; /* lock used to access this + * structure */ + u32 io_usrs; /* number of users performing + * IO */ + u8 started; /* Indicates whether streaming + * started */ + u32 ytop_off; /* offset of Y top from the + * starting of the buffer */ + u32 ybtm_off; /* offset of Y bottom from the + * starting of the buffer */ + u32 ctop_off; /* offset of C top from the + * starting of the buffer */ + u32 cbtm_off; /* offset of C bottom from the + * starting of the buffer */ + /* Function pointer to set the addresses */ + void (*set_addr) (unsigned long, unsigned long, + unsigned long, unsigned long); + u32 height; + u32 width; +}; + +struct channel_obj { + /* V4l2 specific parameters */ + struct video_device *video_dev; /* Identifies video device for + * this channel */ + struct v4l2_prio_state prio; /* Used to keep track of state of + * the priority */ + atomic_t usrs; /* number of open instances of + * the channel */ + u32 field_id; /* Indicates id of the field + * which is being displayed */ + u8 initialized; /* flag to indicate whether + * encoder is initialized */ + + enum vpif_channel_id channel_id;/* Identifies channel */ + struct vpif_params vpifparams; + struct common_obj common[VPIF_NUMOBJECTS]; + struct video_obj video; + struct vbi_obj vbi; +}; + +/* File handle structure */ +struct vpif_fh { + struct channel_obj *channel; /* pointer to channel object for + * opened device */ + u8 io_allowed[VPIF_NUMOBJECTS]; /* Indicates whether this file handle + * is doing IO */ + enum v4l2_priority prio; /* Used to keep track priority of + * this instance */ + u8 initialized; /* Used to keep track of whether this + * file handle has initialized + * channel or not */ +}; + +/* vpif device structure */ +struct vpif_device { + struct v4l2_device v4l2_dev; + struct channel_obj *dev[VPIF_DISPLAY_NUM_CHANNELS]; + struct v4l2_subdev **sd; + +}; + +struct vpif_config_params { + u32 min_bufsize[VPIF_DISPLAY_NUM_CHANNELS]; + u32 channel_bufsize[VPIF_DISPLAY_NUM_CHANNELS]; + u8 numbuffers[VPIF_DISPLAY_NUM_CHANNELS]; + u8 min_numbuffers; +}; + +/* Struct which keeps track of the line numbers for the sliced vbi service */ +struct vpif_service_line { + u16 service_id; + u16 service_line[2]; + u16 enc_service_id; + u8 bytestowrite; +}; + +#endif /* DAVINCIHD_DISPLAY_H */ -- cgit v1.2.3 From 3637f495560909953363d298dde4259e1c8ea46e Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Tue, 9 Jun 2009 11:38:58 +0200 Subject: DaVinci: DM646x Video: Makefile and config files modifications for Display From: Chaithrika U S Makefile and Kconfig changes Modifies and adds the video Makefiles and Kconfig files to support DM646x Video display device Priority: normal Signed-off-by: Manjunath Hadli Signed-off-by: Brijesh Jadav Signed-off-by: Chaithrika U S Reviewed-by: Hans Verkuil Signed-off-by: Hans Verkuil --- linux/drivers/media/video/Kconfig | 22 ++++++++++++++++++++++ linux/drivers/media/video/Makefile | 2 ++ linux/drivers/media/video/davinci/Makefile | 9 +++++++++ 3 files changed, 33 insertions(+) create mode 100644 linux/drivers/media/video/davinci/Makefile (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/Kconfig b/linux/drivers/media/video/Kconfig index 061e147f6..15b4d3ad4 100644 --- a/linux/drivers/media/video/Kconfig +++ b/linux/drivers/media/video/Kconfig @@ -485,6 +485,28 @@ config VIDEO_UPD64083 endmenu # encoder / decoder chips +config DISPLAY_DAVINCI_DM646X_EVM + tristate "DM646x EVM Video Display" + depends on VIDEO_DEV && MACH_DAVINCI_DM6467_EVM + select VIDEOBUF_DMA_CONTIG + select VIDEO_DAVINCI_VPIF + select VIDEO_ADV7343 + select VIDEO_THS7303 + help + Support for DaVinci based display device. + + To compile this driver as a module, choose M here: the + module will be called davincihd_display. + +config VIDEO_DAVINCI_VPIF + tristate "DaVinci VPIF Driver" + depends on DISPLAY_DAVINCI_DM646X_EVM + help + Support for DaVinci VPIF Driver. + + To compile this driver as a module, choose M here: the + module will be called vpif. + config VIDEO_VIVI tristate "Virtual Video Driver" depends on VIDEO_DEV && VIDEO_V4L2 && !SPARC32 && !SPARC64 diff --git a/linux/drivers/media/video/Makefile b/linux/drivers/media/video/Makefile index 7fb3add1b..327138f26 100644 --- a/linux/drivers/media/video/Makefile +++ b/linux/drivers/media/video/Makefile @@ -159,6 +159,8 @@ obj-$(CONFIG_USB_VIDEO_CLASS) += uvc/ obj-$(CONFIG_VIDEO_IR_I2C) += ir-kbd-i2c.o +obj-$(CONFIG_ARCH_DAVINCI) += davinci/ + EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core EXTRA_CFLAGS += -Idrivers/media/dvb/frontends EXTRA_CFLAGS += -Idrivers/media/common/tuners diff --git a/linux/drivers/media/video/davinci/Makefile b/linux/drivers/media/video/davinci/Makefile new file mode 100644 index 000000000..7fe9bce97 --- /dev/null +++ b/linux/drivers/media/video/davinci/Makefile @@ -0,0 +1,9 @@ +# +# Makefile for the davinci video device drivers. +# + +# VPIF +obj-$(CONFIG_VIDEO_DAVINCI_VPIF) += vpif.o + +#DM646x EVM Display driver +obj-$(CONFIG_DISPLAY_DAVINCI_DM646X_EVM) += vpif_display.o -- cgit v1.2.3 From 20235d898f6e1fe04b67efccc344467c0c8c7779 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 9 Jun 2009 10:59:40 +0000 Subject: gspca - stv06xx: remove needless if check and goto MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: Alexey Klimov Patch removes needless if check and goto. Signed-off-by: Alexey Klimov Reviewed-by: Erik Andrén Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/gspca/stv06xx/stv06xx.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/stv06xx/stv06xx.c b/linux/drivers/media/video/gspca/stv06xx/stv06xx.c index 9dff2e65b..e573c3406 100644 --- a/linux/drivers/media/video/gspca/stv06xx/stv06xx.c +++ b/linux/drivers/media/video/gspca/stv06xx/stv06xx.c @@ -293,8 +293,6 @@ static void stv06xx_stopN(struct gspca_dev *gspca_dev) goto out; err = sd->sensor->stop(sd); - if (err < 0) - goto out; out: if (err < 0) -- cgit v1.2.3 From 31968551a3292edae62b6b1a007b0ae361851241 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 9 Jun 2009 13:02:11 +0000 Subject: se401: Fix coding style From: Alan Cox Having fixed the sprintfs I decided a quick clean wouldn't do any harm so it was actually easy to read in future. Priority: normal Signed-off-by: Alan Cox Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/se401.c | 876 +++++++++++++++++++------------------- linux/drivers/media/video/se401.h | 7 +- 2 files changed, 452 insertions(+), 431 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/se401.c b/linux/drivers/media/video/se401.c index 9ba500f8d..1274a5966 100644 --- a/linux/drivers/media/video/se401.c +++ b/linux/drivers/media/video/se401.c @@ -38,7 +38,7 @@ static const char version[] = "0.24"; static int flickerless; static int video_nr = -1; -static struct usb_device_id device_table [] = { +static struct usb_device_id device_table[] = { { USB_DEVICE(0x03e8, 0x0004) },/* Endpoints/Aox SE401 */ { USB_DEVICE(0x0471, 0x030b) },/* Philips PCVC665K */ { USB_DEVICE(0x047d, 0x5001) },/* Kensington 67014 */ @@ -53,7 +53,8 @@ MODULE_AUTHOR("Jeroen Vreeken "); MODULE_DESCRIPTION("SE401 USB Camera Driver"); MODULE_LICENSE("GPL"); module_param(flickerless, int, 0); -MODULE_PARM_DESC(flickerless, "Net frequency to adjust exposure time to (0/50/60)"); +MODULE_PARM_DESC(flickerless, + "Net frequency to adjust exposure time to (0/50/60)"); module_param(video_nr, int, 0); static struct usb_driver se401_driver; @@ -78,8 +79,8 @@ static void *rvmalloc(unsigned long size) adr = (unsigned long) mem; while (size > 0) { SetPageReserved(vmalloc_to_page((void *)adr)); - adr += PAGE_SIZE; - size -= PAGE_SIZE; + adr += PAGE_SIZE; + size -= PAGE_SIZE; } return mem; @@ -95,8 +96,8 @@ static void rvfree(void *mem, unsigned long size) adr = (unsigned long) mem; while ((long) size > 0) { ClearPageReserved(vmalloc_to_page((void *)adr)); - adr += PAGE_SIZE; - size -= PAGE_SIZE; + adr += PAGE_SIZE; + size -= PAGE_SIZE; } vfree(mem); } @@ -112,7 +113,7 @@ static void rvfree(void *mem, unsigned long size) static int se401_sndctrl(int set, struct usb_se401 *se401, unsigned short req, unsigned short value, unsigned char *cp, int size) { - return usb_control_msg ( + return usb_control_msg( se401->dev, set ? usb_sndctrlpipe(se401->dev, 0) : usb_rcvctrlpipe(se401->dev, 0), req, @@ -132,7 +133,7 @@ static int se401_set_feature(struct usb_se401 *se401, unsigned short selector, and the param in index, but in the logs of the windows driver they do this the other way around... */ - return usb_control_msg ( + return usb_control_msg( se401->dev, usb_sndctrlpipe(se401->dev, 0), SE401_REQ_SET_EXT_FEATURE, @@ -152,7 +153,7 @@ static unsigned short se401_get_feature(struct usb_se401 *se401, wrong here to.... */ unsigned char cp[2]; - usb_control_msg ( + usb_control_msg( se401->dev, usb_rcvctrlpipe(se401->dev, 0), SE401_REQ_GET_EXT_FEATURE, @@ -175,46 +176,51 @@ static unsigned short se401_get_feature(struct usb_se401 *se401, static int se401_send_pict(struct usb_se401 *se401) { - se401_set_feature(se401, HV7131_REG_TITL, se401->expose_l);/* integration time low */ - se401_set_feature(se401, HV7131_REG_TITM, se401->expose_m);/* integration time mid */ - se401_set_feature(se401, HV7131_REG_TITU, se401->expose_h);/* integration time mid */ - se401_set_feature(se401, HV7131_REG_ARLV, se401->resetlevel);/* reset level value */ - se401_set_feature(se401, HV7131_REG_ARCG, se401->rgain);/* red color gain */ - se401_set_feature(se401, HV7131_REG_AGCG, se401->ggain);/* green color gain */ - se401_set_feature(se401, HV7131_REG_ABCG, se401->bgain);/* blue color gain */ + /* integration time low */ + se401_set_feature(se401, HV7131_REG_TITL, se401->expose_l); + /* integration time mid */ + se401_set_feature(se401, HV7131_REG_TITM, se401->expose_m); + /* integration time mid */ + se401_set_feature(se401, HV7131_REG_TITU, se401->expose_h); + /* reset level value */ + se401_set_feature(se401, HV7131_REG_ARLV, se401->resetlevel); + /* red color gain */ + se401_set_feature(se401, HV7131_REG_ARCG, se401->rgain); + /* green color gain */ + se401_set_feature(se401, HV7131_REG_AGCG, se401->ggain); + /* blue color gain */ + se401_set_feature(se401, HV7131_REG_ABCG, se401->bgain); return 0; } static void se401_set_exposure(struct usb_se401 *se401, int brightness) { - int integration=brightness<<5; - - if (flickerless==50) { - integration=integration-integration%106667; - } - if (flickerless==60) { - integration=integration-integration%88889; - } - se401->brightness=integration>>5; - se401->expose_h=(integration>>16)&0xff; - se401->expose_m=(integration>>8)&0xff; - se401->expose_l=integration&0xff; + int integration = brightness << 5; + + if (flickerless == 50) + integration = integration-integration % 106667; + if (flickerless == 60) + integration = integration-integration % 88889; + se401->brightness = integration >> 5; + se401->expose_h = (integration >> 16) & 0xff; + se401->expose_m = (integration >> 8) & 0xff; + se401->expose_l = integration & 0xff; } static int se401_get_pict(struct usb_se401 *se401, struct video_picture *p) { - p->brightness=se401->brightness; - if (se401->enhance) { - p->whiteness=32768; - } else { - p->whiteness=0; - } - p->colour=65535; - p->contrast=65535; - p->hue=se401->rgain<<10; - p->palette=se401->palette; - p->depth=3; /* rgb24 */ + p->brightness = se401->brightness; + if (se401->enhance) + p->whiteness = 32768; + else + p->whiteness = 0; + + p->colour = 65535; + p->contrast = 65535; + p->hue = se401->rgain << 10; + p->palette = se401->palette; + p->depth = 3; /* rgb24 */ return 0; } @@ -223,20 +229,19 @@ static int se401_set_pict(struct usb_se401 *se401, struct video_picture *p) { if (p->palette != VIDEO_PALETTE_RGB24) return 1; - se401->palette=p->palette; - if (p->hue!=se401->hue) { - se401->rgain= p->hue>>10; - se401->bgain= 0x40-(p->hue>>10); - se401->hue=p->hue; + se401->palette = p->palette; + if (p->hue != se401->hue) { + se401->rgain = p->hue >> 10; + se401->bgain = 0x40-(p->hue >> 10); + se401->hue = p->hue; } - if (p->brightness!=se401->brightness) { + if (p->brightness != se401->brightness) se401_set_exposure(se401, p->brightness); - } - if (p->whiteness>=32768) { - se401->enhance=1; - } else { - se401->enhance=0; - } + + if (p->whiteness >= 32768) + se401->enhance = 1; + else + se401->enhance = 0; se401_send_pict(se401); se401_send_pict(se401); return 0; @@ -249,7 +254,7 @@ static int se401_set_pict(struct usb_se401 *se401, struct video_picture *p) static void se401_auto_resetlevel(struct usb_se401 *se401) { unsigned int ahrc, alrc; - int oldreset=se401->resetlevel; + int oldreset = se401->resetlevel; /* For some reason this normally read-only register doesn't get reset to zero after reading them just once... @@ -258,24 +263,24 @@ static void se401_auto_resetlevel(struct usb_se401 *se401) se401_get_feature(se401, HV7131_REG_HIREFNOL); se401_get_feature(se401, HV7131_REG_LOREFNOH); se401_get_feature(se401, HV7131_REG_LOREFNOL); - ahrc=256*se401_get_feature(se401, HV7131_REG_HIREFNOH) + + ahrc = 256*se401_get_feature(se401, HV7131_REG_HIREFNOH) + se401_get_feature(se401, HV7131_REG_HIREFNOL); - alrc=256*se401_get_feature(se401, HV7131_REG_LOREFNOH) + + alrc = 256*se401_get_feature(se401, HV7131_REG_LOREFNOH) + se401_get_feature(se401, HV7131_REG_LOREFNOL); /* Not an exact science, but it seems to work pretty well... */ if (alrc > 10) { - while (alrc>=10 && se401->resetlevel < 63) { + while (alrc >= 10 && se401->resetlevel < 63) { se401->resetlevel++; - alrc /=2; + alrc /= 2; } } else if (ahrc > 20) { - while (ahrc>=20 && se401->resetlevel > 0) { + while (ahrc >= 20 && se401->resetlevel > 0) { se401->resetlevel--; - ahrc /=2; + ahrc /= 2; } } - if (se401->resetlevel!=oldreset) + if (se401->resetlevel != oldreset) se401_set_feature(se401, HV7131_REG_ARLV, se401->resetlevel); return; @@ -304,21 +309,22 @@ static void se401_button_irq(struct urb *urb) case -ENOENT: case -ESHUTDOWN: /* this urb is terminated, clean up */ - dbg("%s - urb shutting down with status: %d", __func__, urb->status); + dbg("%s - urb shutting down with status: %d", + __func__, urb->status); return; default: - dbg("%s - nonzero urb status received: %d", __func__, urb->status); + dbg("%s - nonzero urb status received: %d", + __func__, urb->status); goto exit; } - if (urb->actual_length >=2) { + if (urb->actual_length >= 2) if (se401->button) - se401->buttonpressed=1; - } + se401->buttonpressed = 1; exit: - status = usb_submit_urb (urb, GFP_ATOMIC); + status = usb_submit_urb(urb, GFP_ATOMIC); if (status) - err ("%s - usb_submit_urb failed with result %d", + err("%s - usb_submit_urb failed with result %d", __func__, status); } @@ -344,55 +350,52 @@ static void se401_video_irq(struct urb *urb) keeps sending them forever... */ if (length && !urb->status) { - se401->nullpackets=0; - switch(se401->scratch[se401->scratch_next].state) { - case BUFFER_READY: - case BUFFER_BUSY: { - se401->dropped++; - break; - } - case BUFFER_UNUSED: { - memcpy(se401->scratch[se401->scratch_next].data, (unsigned char *)urb->transfer_buffer, length); - se401->scratch[se401->scratch_next].state=BUFFER_READY; - se401->scratch[se401->scratch_next].offset=se401->bayeroffset; - se401->scratch[se401->scratch_next].length=length; - if (waitqueue_active(&se401->wq)) { - wake_up_interruptible(&se401->wq); - } - se401->scratch_overflow=0; - se401->scratch_next++; - if (se401->scratch_next>=SE401_NUMSCRATCH) - se401->scratch_next=0; - break; - } - } - se401->bayeroffset+=length; - if (se401->bayeroffset>=se401->cheight*se401->cwidth) { - se401->bayeroffset=0; + se401->nullpackets = 0; + switch (se401->scratch[se401->scratch_next].state) { + case BUFFER_READY: + case BUFFER_BUSY: + se401->dropped++; + break; + case BUFFER_UNUSED: + memcpy(se401->scratch[se401->scratch_next].data, + (unsigned char *)urb->transfer_buffer, length); + se401->scratch[se401->scratch_next].state + = BUFFER_READY; + se401->scratch[se401->scratch_next].offset + = se401->bayeroffset; + se401->scratch[se401->scratch_next].length = length; + if (waitqueue_active(&se401->wq)) + wake_up_interruptible(&se401->wq); + se401->scratch_overflow = 0; + se401->scratch_next++; + if (se401->scratch_next >= SE401_NUMSCRATCH) + se401->scratch_next = 0; + break; } + se401->bayeroffset += length; + if (se401->bayeroffset >= se401->cheight * se401->cwidth) + se401->bayeroffset = 0; } else { se401->nullpackets++; - if (se401->nullpackets > SE401_MAX_NULLPACKETS) { - if (waitqueue_active(&se401->wq)) { + if (se401->nullpackets > SE401_MAX_NULLPACKETS) + if (waitqueue_active(&se401->wq)) wake_up_interruptible(&se401->wq); - } - } } /* Resubmit urb for new data */ - urb->status=0; - urb->dev=se401->dev; - if(usb_submit_urb(urb, GFP_KERNEL)) + urb->status = 0; + urb->dev = se401->dev; + if (usb_submit_urb(urb, GFP_KERNEL)) dev_info(&urb->dev->dev, "urb burned down\n"); return; } static void se401_send_size(struct usb_se401 *se401, int width, int height) { - int i=0; - int mode=0x03; /* No compression */ - int sendheight=height; - int sendwidth=width; + int i = 0; + int mode = 0x03; /* No compression */ + int sendheight = height; + int sendwidth = width; /* JangGu compression can only be used with the camera supported sizes, but bayer seems to work with any size that fits on the sensor. @@ -400,18 +403,21 @@ static void se401_send_size(struct usb_se401 *se401, int width, int height) 4 or 16 times subcapturing, if not we use uncompressed bayer data but this will result in cutouts of the maximum size.... */ - while (isizes && !(se401->width[i]==width && se401->height[i]==height)) + while (i < se401->sizes && !(se401->width[i] == width && + se401->height[i] == height)) i++; - while (isizes) { - if (se401->width[i]==width*2 && se401->height[i]==height*2) { - sendheight=se401->height[i]; - sendwidth=se401->width[i]; - mode=0x40; + while (i < se401->sizes) { + if (se401->width[i] == width * 2 && + se401->height[i] == height * 2) { + sendheight = se401->height[i]; + sendwidth = se401->width[i]; + mode = 0x40; } - if (se401->width[i]==width*4 && se401->height[i]==height*4) { - sendheight=se401->height[i]; - sendwidth=se401->width[i]; - mode=0x42; + if (se401->width[i] == width * 4 && + se401->height[i] == height * 4) { + sendheight = se401->height[i]; + sendwidth = se401->width[i]; + mode = 0x42; } i++; } @@ -420,13 +426,10 @@ static void se401_send_size(struct usb_se401 *se401, int width, int height) se401_sndctrl(1, se401, SE401_REQ_SET_HEIGHT, sendheight, NULL, 0); se401_set_feature(se401, SE401_OPERATINGMODE, mode); - if (mode==0x03) { - se401->format=FMT_BAYER; - } else { - se401->format=FMT_JANGGU; - } - - return; + if (mode == 0x03) + se401->format = FMT_BAYER; + else + se401->format = FMT_JANGGU; } /* @@ -437,29 +440,31 @@ static void se401_send_size(struct usb_se401 *se401, int width, int height) static int se401_start_stream(struct usb_se401 *se401) { struct urb *urb; - int err=0, i; - se401->streaming=1; + int err = 0, i; + se401->streaming = 1; se401_sndctrl(1, se401, SE401_REQ_CAMERA_POWER, 1, NULL, 0); se401_sndctrl(1, se401, SE401_REQ_LED_CONTROL, 1, NULL, 0); /* Set picture settings */ - se401_set_feature(se401, HV7131_REG_MODE_B, 0x05);/*windowed + pix intg */ + /* windowed + pix intg */ + se401_set_feature(se401, HV7131_REG_MODE_B, 0x05); se401_send_pict(se401); se401_send_size(se401, se401->cwidth, se401->cheight); - se401_sndctrl(1, se401, SE401_REQ_START_CONTINUOUS_CAPTURE, 0, NULL, 0); + se401_sndctrl(1, se401, SE401_REQ_START_CONTINUOUS_CAPTURE, + 0, NULL, 0); /* Do some memory allocation */ - for (i=0; iframe[i].data=se401->fbuf + i * se401->maxframesize; - se401->frame[i].curpix=0; + for (i = 0; i < SE401_NUMFRAMES; i++) { + se401->frame[i].data = se401->fbuf + i * se401->maxframesize; + se401->frame[i].curpix = 0; } - for (i=0; isbuf[i].data=kmalloc(SE401_PACKETSIZE, GFP_KERNEL); + for (i = 0; i < SE401_NUMSBUF; i++) { + se401->sbuf[i].data = kmalloc(SE401_PACKETSIZE, GFP_KERNEL); if (!se401->sbuf[i].data) { - for(i = i - 1; i >= 0; i--) { + for (i = i - 1; i >= 0; i--) { kfree(se401->sbuf[i].data); se401->sbuf[i].data = NULL; } @@ -467,26 +472,26 @@ static int se401_start_stream(struct usb_se401 *se401) } } - se401->bayeroffset=0; - se401->scratch_next=0; - se401->scratch_use=0; - se401->scratch_overflow=0; - for (i=0; iscratch[i].data=kmalloc(SE401_PACKETSIZE, GFP_KERNEL); + se401->bayeroffset = 0; + se401->scratch_next = 0; + se401->scratch_use = 0; + se401->scratch_overflow = 0; + for (i = 0; i < SE401_NUMSCRATCH; i++) { + se401->scratch[i].data = kmalloc(SE401_PACKETSIZE, GFP_KERNEL); if (!se401->scratch[i].data) { - for(i = i - 1; i >= 0; i--) { + for (i = i - 1; i >= 0; i--) { kfree(se401->scratch[i].data); se401->scratch[i].data = NULL; } goto nomem_sbuf; } - se401->scratch[i].state=BUFFER_UNUSED; + se401->scratch[i].state = BUFFER_UNUSED; } - for (i=0; i= 0; i--) { + for (i = 0; i < SE401_NUMSBUF; i++) { + urb = usb_alloc_urb(0, GFP_KERNEL); + if (!urb) { + for (i = i - 1; i >= 0; i--) { usb_kill_urb(se401->urb[i]); usb_free_urb(se401->urb[i]); se401->urb[i] = NULL; @@ -500,24 +505,24 @@ static int se401_start_stream(struct usb_se401 *se401) se401_video_irq, se401); - se401->urb[i]=urb; + se401->urb[i] = urb; - err=usb_submit_urb(se401->urb[i], GFP_KERNEL); - if(err) + err = usb_submit_urb(se401->urb[i], GFP_KERNEL); + if (err) err("urb burned down"); } - se401->framecount=0; + se401->framecount = 0; return 0; nomem_scratch: - for (i=0; iscratch[i].data); se401->scratch[i].data = NULL; } nomem_sbuf: - for (i=0; isbuf[i].data); se401->sbuf[i].data = NULL; } @@ -531,22 +536,23 @@ static int se401_stop_stream(struct usb_se401 *se401) if (!se401->streaming || !se401->dev) return 1; - se401->streaming=0; + se401->streaming = 0; se401_sndctrl(1, se401, SE401_REQ_STOP_CONTINUOUS_CAPTURE, 0, NULL, 0); se401_sndctrl(1, se401, SE401_REQ_LED_CONTROL, 0, NULL, 0); se401_sndctrl(1, se401, SE401_REQ_CAMERA_POWER, 0, NULL, 0); - for (i=0; iurb[i]) { - usb_kill_urb(se401->urb[i]); - usb_free_urb(se401->urb[i]); - se401->urb[i]=NULL; - kfree(se401->sbuf[i].data); - } - for (i=0; iurb[i]) { + usb_kill_urb(se401->urb[i]); + usb_free_urb(se401->urb[i]); + se401->urb[i] = NULL; + kfree(se401->sbuf[i].data); + } + for (i = 0; i < SE401_NUMSCRATCH; i++) { kfree(se401->scratch[i].data); - se401->scratch[i].data=NULL; + se401->scratch[i].data = NULL; } return 0; @@ -554,9 +560,9 @@ static int se401_stop_stream(struct usb_se401 *se401) static int se401_set_size(struct usb_se401 *se401, int width, int height) { - int wasstreaming=se401->streaming; + int wasstreaming = se401->streaming; /* Check to see if we need to change */ - if (se401->cwidth==width && se401->cheight==height) + if (se401->cwidth == width && se401->cheight == height) return 0; /* Check for a valid mode */ @@ -564,16 +570,16 @@ static int se401_set_size(struct usb_se401 *se401, int width, int height) return 1; if ((width & 1) || (height & 1)) return 1; - if (width>se401->width[se401->sizes-1]) + if (width > se401->width[se401->sizes-1]) return 1; - if (height>se401->height[se401->sizes-1]) + if (height > se401->height[se401->sizes-1]) return 1; /* Stop a current stream and start it again at the new size */ if (wasstreaming) se401_stop_stream(se401); - se401->cwidth=width; - se401->cheight=height; + se401->cwidth = width; + se401->cheight = height; if (wasstreaming) se401_start_stream(se401); return 0; @@ -594,68 +600,68 @@ static int se401_set_size(struct usb_se401 *se401, int width, int height) static inline void enhance_picture(unsigned char *frame, int len) { while (len--) { - *frame=(((*frame^255)*(*frame^255))/255)^255; + *frame = (((*frame^255)*(*frame^255))/255)^255; frame++; } } static inline void decode_JangGu_integrate(struct usb_se401 *se401, int data) { - struct se401_frame *frame=&se401->frame[se401->curframe]; - int linelength=se401->cwidth*3; + struct se401_frame *frame = &se401->frame[se401->curframe]; + int linelength = se401->cwidth * 3; if (frame->curlinepix >= linelength) { - frame->curlinepix=0; - frame->curline+=linelength; + frame->curlinepix = 0; + frame->curline += linelength; } /* First three are absolute, all others relative. * Format is rgb from right to left (mirrorred image), * we flip it to get bgr from left to right. */ - if (frame->curlinepix < 3) { - *(frame->curline-frame->curlinepix)=1+data*4; - } else { - *(frame->curline-frame->curlinepix)= - *(frame->curline-frame->curlinepix+3)+data*4; - } + if (frame->curlinepix < 3) + *(frame->curline-frame->curlinepix) = 1 + data * 4; + else + *(frame->curline-frame->curlinepix) = + *(frame->curline-frame->curlinepix + 3) + data * 4; frame->curlinepix++; } -static inline void decode_JangGu_vlc (struct usb_se401 *se401, unsigned char *data, int bit_exp, int packetlength) +static inline void decode_JangGu_vlc(struct usb_se401 *se401, + unsigned char *data, int bit_exp, int packetlength) { - int pos=0; - int vlc_cod=0; - int vlc_size=0; - int vlc_data=0; + int pos = 0; + int vlc_cod = 0; + int vlc_size = 0; + int vlc_data = 0; int bit_cur; int bit; - data+=4; + data += 4; while (pos < packetlength) { - bit_cur=8; + bit_cur = 8; while (bit_cur && bit_exp) { - bit=((*data)>>(bit_cur-1))&1; + bit = ((*data) >> (bit_cur-1))&1; if (!vlc_cod) { if (bit) { vlc_size++; } else { - if (!vlc_size) { + if (!vlc_size) decode_JangGu_integrate(se401, 0); - } else { - vlc_cod=2; - vlc_data=0; + else { + vlc_cod = 2; + vlc_data = 0; } } } else { - if (vlc_cod==2) { + if (vlc_cod == 2) { if (!bit) - vlc_data = -(1<data; - int len=buffer->length; - int bit_exp=0, pix_exp=0, frameinfo=0, packetlength=0, size; - int datapos=0; + unsigned char *data = buffer->data; + int len = buffer->length; + int bit_exp = 0, pix_exp = 0, frameinfo = 0, packetlength = 0, size; + int datapos = 0; /* New image? */ if (!se401->frame[se401->curframe].curpix) { - se401->frame[se401->curframe].curlinepix=0; - se401->frame[se401->curframe].curline= + se401->frame[se401->curframe].curlinepix = 0; + se401->frame[se401->curframe].curline = se401->frame[se401->curframe].data+ - se401->cwidth*3-1; - if (se401->frame[se401->curframe].grabstate==FRAME_READY) - se401->frame[se401->curframe].grabstate=FRAME_GRABBING; - se401->vlcdatapos=0; + se401->cwidth * 3 - 1; + if (se401->frame[se401->curframe].grabstate == FRAME_READY) + se401->frame[se401->curframe].grabstate = FRAME_GRABBING; + se401->vlcdatapos = 0; } while (datapos < len) { - size=1024-se401->vlcdatapos; + size = 1024 - se401->vlcdatapos; if (size+datapos > len) - size=len-datapos; + size = len-datapos; memcpy(se401->vlcdata+se401->vlcdatapos, data+datapos, size); - se401->vlcdatapos+=size; - packetlength=0; + se401->vlcdatapos += size; + packetlength = 0; if (se401->vlcdatapos >= 4) { - bit_exp=se401->vlcdata[3]+(se401->vlcdata[2]<<8); - pix_exp=se401->vlcdata[1]+((se401->vlcdata[0]&0x3f)<<8); - frameinfo=se401->vlcdata[0]&0xc0; - packetlength=((bit_exp+47)>>4)<<1; + bit_exp = se401->vlcdata[3] + (se401->vlcdata[2] << 8); + pix_exp = se401->vlcdata[1] + + ((se401->vlcdata[0] & 0x3f) << 8); + frameinfo = se401->vlcdata[0] & 0xc0; + packetlength = ((bit_exp + 47) >> 4) << 1; if (packetlength > 1024) { - se401->vlcdatapos=0; - datapos=len; - packetlength=0; + se401->vlcdatapos = 0; + datapos = len; + packetlength = 0; se401->error++; - se401->frame[se401->curframe].curpix=0; + se401->frame[se401->curframe].curpix = 0; } } if (packetlength && se401->vlcdatapos >= packetlength) { - decode_JangGu_vlc(se401, se401->vlcdata, bit_exp, packetlength); - se401->frame[se401->curframe].curpix+=pix_exp*3; - datapos+=size-(se401->vlcdatapos-packetlength); - se401->vlcdatapos=0; - if (se401->frame[se401->curframe].curpix>=se401->cwidth*se401->cheight*3) { - if (se401->frame[se401->curframe].curpix==se401->cwidth*se401->cheight*3) { - if (se401->frame[se401->curframe].grabstate==FRAME_GRABBING) { - se401->frame[se401->curframe].grabstate=FRAME_DONE; + decode_JangGu_vlc(se401, se401->vlcdata, bit_exp, + packetlength); + se401->frame[se401->curframe].curpix += pix_exp * 3; + datapos += size-(se401->vlcdatapos-packetlength); + se401->vlcdatapos = 0; + if (se401->frame[se401->curframe].curpix >= se401->cwidth * se401->cheight * 3) { + if (se401->frame[se401->curframe].curpix == se401->cwidth * se401->cheight * 3) { + if (se401->frame[se401->curframe].grabstate == FRAME_GRABBING) { + se401->frame[se401->curframe].grabstate = FRAME_DONE; se401->framecount++; se401->readcount++; } - if (se401->frame[(se401->curframe+1)&(SE401_NUMFRAMES-1)].grabstate==FRAME_READY) { - se401->curframe=(se401->curframe+1) & (SE401_NUMFRAMES-1); - } - } else { + if (se401->frame[(se401->curframe + 1) & (SE401_NUMFRAMES - 1)].grabstate == FRAME_READY) + se401->curframe = (se401->curframe + 1) & (SE401_NUMFRAMES - 1); + } else se401->error++; - } - se401->frame[se401->curframe].curpix=0; - datapos=len; + se401->frame[se401->curframe].curpix = 0; + datapos = len; } - } else { - datapos+=size; - } + } else + datapos += size; } } -static inline void decode_bayer (struct usb_se401 *se401, struct se401_scratch *buffer) +static inline void decode_bayer(struct usb_se401 *se401, + struct se401_scratch *buffer) { - unsigned char *data=buffer->data; - int len=buffer->length; - int offset=buffer->offset; - int datasize=se401->cwidth*se401->cheight; - struct se401_frame *frame=&se401->frame[se401->curframe]; + unsigned char *data = buffer->data; + int len = buffer->length; + int offset = buffer->offset; + int datasize = se401->cwidth * se401->cheight; + struct se401_frame *frame = &se401->frame[se401->curframe]; + unsigned char *framedata = frame->data, *curline, *nextline; + int width = se401->cwidth; + int blineoffset = 0, bline; + int linelength = width * 3, i; - unsigned char *framedata=frame->data, *curline, *nextline; - int width=se401->cwidth; - int blineoffset=0, bline; - int linelength=width*3, i; + if (frame->curpix == 0) { + if (frame->grabstate == FRAME_READY) + frame->grabstate = FRAME_GRABBING; - if (frame->curpix==0) { - if (frame->grabstate==FRAME_READY) { - frame->grabstate=FRAME_GRABBING; - } - frame->curline=framedata+linelength; - frame->curlinepix=0; + frame->curline = framedata + linelength; + frame->curlinepix = 0; } - if (offset!=frame->curpix) { + if (offset != frame->curpix) { /* Regard frame as lost :( */ - frame->curpix=0; + frame->curpix = 0; se401->error++; return; } /* Check if we have to much data */ - if (frame->curpix+len > datasize) { - len=datasize-frame->curpix; - } - if (se401->cheight%4) - blineoffset=1; - bline=frame->curpix/se401->cwidth+blineoffset; - - curline=frame->curline; - nextline=curline+linelength; - if (nextline >= framedata+datasize*3) - nextline=curline; + if (frame->curpix + len > datasize) + len = datasize-frame->curpix; + + if (se401->cheight % 4) + blineoffset = 1; + bline = frame->curpix / se401->cwidth+blineoffset; + + curline = frame->curline; + nextline = curline + linelength; + if (nextline >= framedata+datasize * 3) + nextline = curline; while (len) { - if (frame->curlinepix>=width) { - frame->curlinepix-=width; - bline=frame->curpix/width+blineoffset; - curline+=linelength*2; - nextline+=linelength*2; - if (curline >= framedata+datasize*3) { + if (frame->curlinepix >= width) { + frame->curlinepix -= width; + bline = frame->curpix / width + blineoffset; + curline += linelength*2; + nextline += linelength*2; + if (curline >= framedata+datasize * 3) { frame->curlinepix++; - curline-=3; - nextline-=3; + curline -= 3; + nextline -= 3; len--; data++; frame->curpix++; } if (nextline >= framedata+datasize*3) - nextline=curline; + nextline = curline; } - if ((bline&1)) { - if ((frame->curlinepix&1)) { - *(curline+2)=*data; - *(curline-1)=*data; - *(nextline+2)=*data; - *(nextline-1)=*data; + if (bline & 1) { + if (frame->curlinepix & 1) { + *(curline + 2) = *data; + *(curline - 1) = *data; + *(nextline + 2) = *data; + *(nextline - 1) = *data; } else { - *(curline+1)= - (*(curline+1)+*data)/2; - *(curline-2)= - (*(curline-2)+*data)/2; - *(nextline+1)=*data; - *(nextline-2)=*data; + *(curline + 1) = + (*(curline + 1) + *data) / 2; + *(curline-2) = + (*(curline - 2) + *data) / 2; + *(nextline + 1) = *data; + *(nextline - 2) = *data; } } else { - if ((frame->curlinepix&1)) { - *(curline+1)= - (*(curline+1)+*data)/2; - *(curline-2)= - (*(curline-2)+*data)/2; - *(nextline+1)=*data; - *(nextline-2)=*data; + if (frame->curlinepix & 1) { + *(curline + 1) = + (*(curline + 1) + *data) / 2; + *(curline - 2) = + (*(curline - 2) + *data) / 2; + *(nextline + 1) = *data; + *(nextline - 2) = *data; } else { - *curline=*data; - *(curline-3)=*data; - *nextline=*data; - *(nextline-3)=*data; + *curline = *data; + *(curline - 3) = *data; + *nextline = *data; + *(nextline - 3) = *data; } } frame->curlinepix++; - curline-=3; - nextline-=3; + curline -= 3; + nextline -= 3; len--; data++; frame->curpix++; } - frame->curline=curline; + frame->curline = curline; - if (frame->curpix>=datasize) { + if (frame->curpix >= datasize) { /* Fix the top line */ - framedata+=linelength; - for (i=0; icheight; i++) { - *framedata=*(framedata+3); - *(framedata+1)=*(framedata+4); - *(framedata+2)=*(framedata+5); - framedata+=linelength; + for (i = 0; i < se401->cheight; i++) { + *framedata = *(framedata + 3); + *(framedata + 1) = *(framedata + 4); + *(framedata + 2) = *(framedata + 5); + framedata += linelength; } - frame->curpix=0; - frame->grabstate=FRAME_DONE; + frame->curpix = 0; + frame->grabstate = FRAME_DONE; se401->framecount++; se401->readcount++; - if (se401->frame[(se401->curframe+1)&(SE401_NUMFRAMES-1)].grabstate==FRAME_READY) { - se401->curframe=(se401->curframe+1) & (SE401_NUMFRAMES-1); + if (se401->frame[(se401->curframe + 1) & + (SE401_NUMFRAMES - 1)].grabstate == FRAME_READY) { + se401->curframe = (se401->curframe+1) & + (SE401_NUMFRAMES-1); } } } @@ -853,72 +861,76 @@ static inline void decode_bayer (struct usb_se401 *se401, struct se401_scratch * static int se401_newframe(struct usb_se401 *se401, int framenr) { DECLARE_WAITQUEUE(wait, current); - int errors=0; + int errors = 0; while (se401->streaming && - (se401->frame[framenr].grabstate==FRAME_READY || - se401->frame[framenr].grabstate==FRAME_GRABBING) ) { - if(!se401->frame[framenr].curpix) { + (se401->frame[framenr].grabstate == FRAME_READY || + se401->frame[framenr].grabstate == FRAME_GRABBING)) { + if (!se401->frame[framenr].curpix) errors++; - } + wait_interruptible( - se401->scratch[se401->scratch_use].state!=BUFFER_READY, - &se401->wq, - &wait - ); + se401->scratch[se401->scratch_use].state != BUFFER_READY, + &se401->wq, &wait); if (se401->nullpackets > SE401_MAX_NULLPACKETS) { - se401->nullpackets=0; + se401->nullpackets = 0; dev_info(&se401->dev->dev, - "too many null length packets, restarting capture\n"); + "too many null length packets, restarting capture\n"); se401_stop_stream(se401); se401_start_stream(se401); } else { - if (se401->scratch[se401->scratch_use].state!=BUFFER_READY) { - se401->frame[framenr].grabstate=FRAME_ERROR; + if (se401->scratch[se401->scratch_use].state != + BUFFER_READY) { + se401->frame[framenr].grabstate = FRAME_ERROR; return -EIO; } - se401->scratch[se401->scratch_use].state=BUFFER_BUSY; - if (se401->format==FMT_JANGGU) { - decode_JangGu(se401, &se401->scratch[se401->scratch_use]); - } else { - decode_bayer(se401, &se401->scratch[se401->scratch_use]); - } - se401->scratch[se401->scratch_use].state=BUFFER_UNUSED; + se401->scratch[se401->scratch_use].state = BUFFER_BUSY; + if (se401->format == FMT_JANGGU) + decode_JangGu(se401, + &se401->scratch[se401->scratch_use]); + else + decode_bayer(se401, + &se401->scratch[se401->scratch_use]); + + se401->scratch[se401->scratch_use].state = + BUFFER_UNUSED; se401->scratch_use++; - if (se401->scratch_use>=SE401_NUMSCRATCH) - se401->scratch_use=0; + if (se401->scratch_use >= SE401_NUMSCRATCH) + se401->scratch_use = 0; if (errors > SE401_MAX_ERRORS) { - errors=0; + errors = 0; dev_info(&se401->dev->dev, - "too many errors, restarting capture\n"); + "too many errors, restarting capture\n"); se401_stop_stream(se401); se401_start_stream(se401); } } } - if (se401->frame[framenr].grabstate==FRAME_DONE) + if (se401->frame[framenr].grabstate == FRAME_DONE) if (se401->enhance) - enhance_picture(se401->frame[framenr].data, se401->cheight*se401->cwidth*3); + enhance_picture(se401->frame[framenr].data, + se401->cheight * se401->cwidth * 3); return 0; } -static void usb_se401_remove_disconnected (struct usb_se401 *se401) +static void usb_se401_remove_disconnected(struct usb_se401 *se401) { int i; se401->dev = NULL; - for (i=0; iurb[i]) { usb_kill_urb(se401->urb[i]); usb_free_urb(se401->urb[i]); se401->urb[i] = NULL; kfree(se401->sbuf[i].data); } - for (i=0; iscratch[i].data); - } + if (se401->inturb) { usb_kill_urb(se401->inturb); usb_free_urb(se401->inturb); @@ -973,11 +985,11 @@ static int se401_close(struct file *file) dev_info(&se401->dev->dev, "device unregistered\n"); usb_se401_remove_disconnected(se401); } else { - for (i=0; iframe[i].grabstate=FRAME_UNUSED; + for (i = 0; i < SE401_NUMFRAMES; i++) + se401->frame[i].grabstate = FRAME_UNUSED; if (se401->streaming) se401_stop_stream(se401); - se401->user=0; + se401->user = 0; } file->private_data = NULL; return 0; @@ -1073,7 +1085,7 @@ static long se401_do_ioctl(struct file *file, unsigned int cmd, void *arg) memset(vm, 0, sizeof(*vm)); vm->size = SE401_NUMFRAMES * se401->maxframesize; vm->frames = SE401_NUMFRAMES; - for (i=0; ioffsets[i] = se401->maxframesize * i; return 0; } @@ -1091,16 +1103,16 @@ static long se401_do_ioctl(struct file *file, unsigned int cmd, void *arg) /* Is this according to the v4l spec??? */ if (se401_set_size(se401, vm->width, vm->height)) return -EINVAL; - se401->frame[vm->frame].grabstate=FRAME_READY; + se401->frame[vm->frame].grabstate = FRAME_READY; if (!se401->streaming) se401_start_stream(se401); /* Set the picture properties */ - if (se401->framecount==0) + if (se401->framecount == 0) se401_send_pict(se401); /* Calibrate the reset level after a few frames. */ - if (se401->framecount%20==1) + if (se401->framecount % 20 == 1) se401_auto_resetlevel(se401); return 0; @@ -1108,13 +1120,13 @@ static long se401_do_ioctl(struct file *file, unsigned int cmd, void *arg) case VIDIOCSYNC: { int *frame = arg; - int ret=0; + int ret = 0; - if(*frame <0 || *frame >= SE401_NUMFRAMES) + if (*frame < 0 || *frame >= SE401_NUMFRAMES) return -EINVAL; - ret=se401_newframe(se401, *frame); - se401->frame[*frame].grabstate=FRAME_UNUSED; + ret = se401_newframe(se401, *frame); + se401->frame[*frame].grabstate = FRAME_UNUSED; return ret; } case VIDIOCGFBUF: @@ -1155,36 +1167,36 @@ static long se401_ioctl(struct file *file, static ssize_t se401_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) { - int realcount=count, ret=0; + int realcount = count, ret = 0; struct video_device *dev = file->private_data; struct usb_se401 *se401 = (struct usb_se401 *)dev; - if (se401->dev == NULL) + if (se401->dev == NULL) return -EIO; if (realcount > se401->cwidth*se401->cheight*3) - realcount=se401->cwidth*se401->cheight*3; + realcount = se401->cwidth*se401->cheight*3; /* Shouldn't happen: */ - if (se401->frame[0].grabstate==FRAME_GRABBING) + if (se401->frame[0].grabstate == FRAME_GRABBING) return -EBUSY; - se401->frame[0].grabstate=FRAME_READY; - se401->frame[1].grabstate=FRAME_UNUSED; - se401->curframe=0; + se401->frame[0].grabstate = FRAME_READY; + se401->frame[1].grabstate = FRAME_UNUSED; + se401->curframe = 0; if (!se401->streaming) se401_start_stream(se401); /* Set the picture properties */ - if (se401->framecount==0) + if (se401->framecount == 0) se401_send_pict(se401); /* Calibrate the reset level after a few frames. */ - if (se401->framecount%20==1) + if (se401->framecount%20 == 1) se401_auto_resetlevel(se401); - ret=se401_newframe(se401, 0); + ret = se401_newframe(se401, 0); - se401->frame[0].grabstate=FRAME_UNUSED; + se401->frame[0].grabstate = FRAME_UNUSED; if (ret) return ret; if (copy_to_user(buf, se401->frame[0].data, realcount)) @@ -1203,11 +1215,12 @@ static int se401_mmap(struct file *file, struct vm_area_struct *vma) mutex_lock(&se401->lock); - if (se401->dev == NULL) { + if (se401->dev == NULL) { mutex_unlock(&se401->lock); return -EIO; } - if (size > (((SE401_NUMFRAMES * se401->maxframesize) + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1))) { + if (size > (((SE401_NUMFRAMES * se401->maxframesize) + PAGE_SIZE - 1) + & ~(PAGE_SIZE - 1))) { mutex_unlock(&se401->lock); return -EINVAL; } @@ -1218,10 +1231,10 @@ static int se401_mmap(struct file *file, struct vm_area_struct *vma) mutex_unlock(&se401->lock); return -EAGAIN; } - start += PAGE_SIZE; - pos += PAGE_SIZE; + start += PAGE_SIZE; + pos += PAGE_SIZE; if (size > PAGE_SIZE) - size -= PAGE_SIZE; + size -= PAGE_SIZE; else size = 0; } @@ -1231,7 +1244,7 @@ static int se401_mmap(struct file *file, struct vm_area_struct *vma) } static const struct v4l2_file_operations se401_fops = { - .owner = THIS_MODULE, + .owner = THIS_MODULE, .open = se401_open, .release = se401_close, .read = se401_read, @@ -1249,7 +1262,7 @@ static struct video_device se401_template = { /***************************/ static int se401_init(struct usb_se401 *se401, int button) { - int i=0, rc; + int i = 0, rc; unsigned char cp[0x40]; char temp[200]; int slen; @@ -1258,64 +1271,67 @@ static int se401_init(struct usb_se401 *se401, int button) se401_sndctrl(1, se401, SE401_REQ_LED_CONTROL, 1, NULL, 0); /* get camera descriptor */ - rc=se401_sndctrl(0, se401, SE401_REQ_GET_CAMERA_DESCRIPTOR, 0, cp, sizeof(cp)); + rc = se401_sndctrl(0, se401, SE401_REQ_GET_CAMERA_DESCRIPTOR, 0, + cp, sizeof(cp)); if (cp[1] != 0x41) { err("Wrong descriptor type"); return 1; } slen = snprintf(temp, 200, "ExtraFeatures: %d", cp[3]); - se401->sizes=cp[4]+cp[5]*256; - se401->width=kmalloc(se401->sizes*sizeof(int), GFP_KERNEL); + se401->sizes = cp[4] + cp[5] * 256; + se401->width = kmalloc(se401->sizes*sizeof(int), GFP_KERNEL); if (!se401->width) return 1; - se401->height=kmalloc(se401->sizes*sizeof(int), GFP_KERNEL); + se401->height = kmalloc(se401->sizes*sizeof(int), GFP_KERNEL); if (!se401->height) { kfree(se401->width); return 1; } - for (i=0; isizes; i++) { - se401->width[i]=cp[6+i*4+0]+cp[6+i*4+1]*256; - se401->height[i]=cp[6+i*4+2]+cp[6+i*4+3]*256; + for (i = 0; i < se401->sizes; i++) { + se401->width[i] = cp[6 + i * 4 + 0] + cp[6 + i*4 + 1] * 256; + se401->height[i] = cp[6 + i * 4 + 2] + cp[6 + i * 4 + 3] * 256; } - slen += snprintf (temp + slen, 200 - slen, " Sizes:"); - for (i=0; isizes; i++) { - slen += snprintf(temp + slen, 200 - slen, + slen += snprintf(temp + slen, 200 - slen, " Sizes:"); + for (i = 0; i < se401->sizes; i++) { + slen += snprintf(temp + slen, 200 - slen, " %dx%d", se401->width[i], se401->height[i]); } dev_info(&se401->dev->dev, "%s\n", temp); - se401->maxframesize=se401->width[se401->sizes-1]*se401->height[se401->sizes-1]*3; + se401->maxframesize = se401->width[se401->sizes-1] * + se401->height[se401->sizes - 1] * 3; - rc=se401_sndctrl(0, se401, SE401_REQ_GET_WIDTH, 0, cp, sizeof(cp)); - se401->cwidth=cp[0]+cp[1]*256; - rc=se401_sndctrl(0, se401, SE401_REQ_GET_HEIGHT, 0, cp, sizeof(cp)); - se401->cheight=cp[0]+cp[1]*256; + rc = se401_sndctrl(0, se401, SE401_REQ_GET_WIDTH, 0, cp, sizeof(cp)); + se401->cwidth = cp[0]+cp[1]*256; + rc = se401_sndctrl(0, se401, SE401_REQ_GET_HEIGHT, 0, cp, sizeof(cp)); + se401->cheight = cp[0]+cp[1]*256; if (!(cp[2] & SE401_FORMAT_BAYER)) { err("Bayer format not supported!"); return 1; } /* set output mode (BAYER) */ - se401_sndctrl(1, se401, SE401_REQ_SET_OUTPUT_MODE, SE401_FORMAT_BAYER, NULL, 0); + se401_sndctrl(1, se401, SE401_REQ_SET_OUTPUT_MODE, + SE401_FORMAT_BAYER, NULL, 0); - rc=se401_sndctrl(0, se401, SE401_REQ_GET_BRT, 0, cp, sizeof(cp)); - se401->brightness=cp[0]+cp[1]*256; + rc = se401_sndctrl(0, se401, SE401_REQ_GET_BRT, 0, cp, sizeof(cp)); + se401->brightness = cp[0]+cp[1]*256; /* some default values */ - se401->resetlevel=0x2d; - se401->rgain=0x20; - se401->ggain=0x20; - se401->bgain=0x20; + se401->resetlevel = 0x2d; + se401->rgain = 0x20; + se401->ggain = 0x20; + se401->bgain = 0x20; se401_set_exposure(se401, 20000); - se401->palette=VIDEO_PALETTE_RGB24; - se401->enhance=1; - se401->dropped=0; - se401->error=0; - se401->framecount=0; - se401->readcount=0; + se401->palette = VIDEO_PALETTE_RGB24; + se401->enhance = 1; + se401->dropped = 0; + se401->error = 0; + se401->framecount = 0; + se401->readcount = 0; /* Start interrupt transfers for snapshot button */ if (button) { - se401->inturb=usb_alloc_urb(0, GFP_KERNEL); + se401->inturb = usb_alloc_urb(0, GFP_KERNEL); if (!se401->inturb) { dev_info(&se401->dev->dev, "Allocation of inturb failed\n"); @@ -1333,7 +1349,7 @@ static int se401_init(struct usb_se401 *se401, int button) return 1; } } else - se401->inturb=NULL; + se401->inturb = NULL; /* Flash the led */ se401_sndctrl(1, se401, SE401_REQ_CAMERA_POWER, 1, NULL, 0); @@ -1350,8 +1366,8 @@ static int se401_probe(struct usb_interface *intf, struct usb_device *dev = interface_to_usbdev(intf); struct usb_interface_descriptor *interface; struct usb_se401 *se401; - char *camera_name=NULL; - int button=1; + char *camera_name = NULL; + int button = 1; /* We don't handle multi-config cameras */ if (dev->descriptor.bNumConfigurations != 1) @@ -1360,22 +1376,22 @@ static int se401_probe(struct usb_interface *intf, interface = &intf->cur_altsetting->desc; /* Is it an se401? */ - if (le16_to_cpu(dev->descriptor.idVendor) == 0x03e8 && - le16_to_cpu(dev->descriptor.idProduct) == 0x0004) { - camera_name="Endpoints/Aox SE401"; - } else if (le16_to_cpu(dev->descriptor.idVendor) == 0x0471 && - le16_to_cpu(dev->descriptor.idProduct) == 0x030b) { - camera_name="Philips PCVC665K"; - } else if (le16_to_cpu(dev->descriptor.idVendor) == 0x047d && - le16_to_cpu(dev->descriptor.idProduct) == 0x5001) { - camera_name="Kensington VideoCAM 67014"; - } else if (le16_to_cpu(dev->descriptor.idVendor) == 0x047d && - le16_to_cpu(dev->descriptor.idProduct) == 0x5002) { - camera_name="Kensington VideoCAM 6701(5/7)"; - } else if (le16_to_cpu(dev->descriptor.idVendor) == 0x047d && - le16_to_cpu(dev->descriptor.idProduct) == 0x5003) { - camera_name="Kensington VideoCAM 67016"; - button=0; + if (le16_to_cpu(dev->descriptor.idVendor) == 0x03e8 && + le16_to_cpu(dev->descriptor.idProduct) == 0x0004) { + camera_name = "Endpoints/Aox SE401"; + } else if (le16_to_cpu(dev->descriptor.idVendor) == 0x0471 && + le16_to_cpu(dev->descriptor.idProduct) == 0x030b) { + camera_name = "Philips PCVC665K"; + } else if (le16_to_cpu(dev->descriptor.idVendor) == 0x047d && + le16_to_cpu(dev->descriptor.idProduct) == 0x5001) { + camera_name = "Kensington VideoCAM 67014"; + } else if (le16_to_cpu(dev->descriptor.idVendor) == 0x047d && + le16_to_cpu(dev->descriptor.idProduct) == 0x5002) { + camera_name = "Kensington VideoCAM 6701(5/7)"; + } else if (le16_to_cpu(dev->descriptor.idVendor) == 0x047d && + le16_to_cpu(dev->descriptor.idProduct) == 0x5003) { + camera_name = "Kensington VideoCAM 67016"; + button = 0; } else return -ENODEV; @@ -1388,7 +1404,8 @@ static int se401_probe(struct usb_interface *intf, /* We found one */ dev_info(&intf->dev, "SE401 camera found: %s\n", camera_name); - if ((se401 = kzalloc(sizeof(*se401), GFP_KERNEL)) == NULL) { + se401 = kzalloc(sizeof(*se401), GFP_KERNEL); + if (se401 == NULL) { err("couldn't kmalloc se401 struct"); return -ENOMEM; } @@ -1406,12 +1423,14 @@ static int se401_probe(struct usb_interface *intf, } memcpy(&se401->vdev, &se401_template, sizeof(se401_template)); - memcpy(se401->vdev.name, se401->camera_name, strlen(se401->camera_name)); + memcpy(se401->vdev.name, se401->camera_name, + strlen(se401->camera_name)); init_waitqueue_head(&se401->wq); mutex_init(&se401->lock); wmb(); - if (video_register_device(&se401->vdev, VFL_TYPE_GRABBER, video_nr) < 0) { + if (video_register_device(&se401->vdev, + VFL_TYPE_GRABBER, video_nr) < 0) { kfree(se401); err("video_register_device failed"); return -EIO; @@ -1419,20 +1438,20 @@ static int se401_probe(struct usb_interface *intf, dev_info(&intf->dev, "registered new video device: video%d\n", se401->vdev.num); - usb_set_intfdata (intf, se401); + usb_set_intfdata(intf, se401); return 0; } static void se401_disconnect(struct usb_interface *intf) { - struct usb_se401 *se401 = usb_get_intfdata (intf); + struct usb_se401 *se401 = usb_get_intfdata(intf); - usb_set_intfdata (intf, NULL); + usb_set_intfdata(intf, NULL); if (se401) { video_unregister_device(&se401->vdev); - if (!se401->user){ + if (!se401->user) usb_se401_remove_disconnected(se401); - } else { + else { se401->frame[0].grabstate = FRAME_ERROR; se401->frame[0].grabstate = FRAME_ERROR; @@ -1445,10 +1464,10 @@ static void se401_disconnect(struct usb_interface *intf) } static struct usb_driver se401_driver = { - .name = "se401", - .id_table = device_table, - .probe = se401_probe, - .disconnect = se401_disconnect, + .name = "se401", + .id_table = device_table, + .probe = se401_probe, + .disconnect = se401_disconnect, }; @@ -1461,9 +1480,10 @@ static struct usb_driver se401_driver = { static int __init usb_se401_init(void) { - printk(KERN_INFO "SE401 usb camera driver version %s registering\n", version); + printk(KERN_INFO "SE401 usb camera driver version %s registering\n", + version); if (flickerless) - if (flickerless!=50 && flickerless!=60) { + if (flickerless != 50 && flickerless != 60) { printk(KERN_ERR "Invallid flickerless value, use 0, 50 or 60.\n"); return -1; } diff --git a/linux/drivers/media/video/se401.h b/linux/drivers/media/video/se401.h index 0be02c48b..00f0ddbf4 100644 --- a/linux/drivers/media/video/se401.h +++ b/linux/drivers/media/video/se401.h @@ -2,7 +2,7 @@ #ifndef __LINUX_se401_H #define __LINUX_se401_H -#include +#include #include "compat.h" #include #include @@ -13,9 +13,10 @@ #ifdef se401_DEBUG # define PDEBUG(level, fmt, args...) \ -if (debug >= level) info("[" __PRETTY_FUNCTION__ ":%d] " fmt, __LINE__ , ## args) +if (debug >= level) \ + info("[" __PRETTY_FUNCTION__ ":%d] " fmt, __LINE__ , ## args) #else -# define PDEBUG(level, fmt, args...) do {} while(0) +# define PDEBUG(level, fmt, args...) do {} while (0) #endif /* An almost drop-in replacement for sleep_on_interruptible */ -- cgit v1.2.3 From a49326a6a3bb0c430f83e146348c98fa7f2bea16 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Tue, 9 Jun 2009 17:40:59 +0200 Subject: uvcvideo: Add support for Aveo Technology webcams From: Laurent Pinchart The Aveo Technology USB 2.0 Camera (1871:0306) requires the PROBE_EXTRAFIELDS quirk. Add a corresponding entry in the device IDs list. Priority: normal Signed-off-by: Laurent Pinchart --- linux/drivers/media/video/uvc/uvc_driver.c | 9 +++++++++ 1 file changed, 9 insertions(+) (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 1622bca54..46ab1b5d6 100644 --- a/linux/drivers/media/video/uvc/uvc_driver.c +++ b/linux/drivers/media/video/uvc/uvc_driver.c @@ -1919,6 +1919,15 @@ static struct usb_device_id uvc_ids[] = { .bInterfaceSubClass = 1, .bInterfaceProtocol = 0, .driver_info = UVC_QUIRK_STREAM_NO_FID }, + /* Aveo Technology USB 2.0 Camera */ + { .match_flags = USB_DEVICE_ID_MATCH_DEVICE + | USB_DEVICE_ID_MATCH_INT_INFO, + .idVendor = 0x1871, + .idProduct = 0x0306, + .bInterfaceClass = USB_CLASS_VIDEO, + .bInterfaceSubClass = 1, + .bInterfaceProtocol = 0, + .driver_info = UVC_QUIRK_PROBE_EXTRAFIELDS }, /* Ecamm Pico iMage */ { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO, -- cgit v1.2.3 From fefb311aefd18f36e9a772703a11999fb468eaff Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Tue, 9 Jun 2009 17:46:43 +0200 Subject: uvcvideo: Add support for FSC V30S webcams From: Laurent Pinchart The FSC WebCam V30S (18ec:3288) requires the MINMAX quirk. Add a corresponding entry in the device IDs list. Priority: normal Signed-off-by: Laurent Pinchart --- linux/drivers/media/video/uvc/uvc_driver.c | 9 +++++++++ 1 file changed, 9 insertions(+) (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 46ab1b5d6..c62bc8114 100644 --- a/linux/drivers/media/video/uvc/uvc_driver.c +++ b/linux/drivers/media/video/uvc/uvc_driver.c @@ -1937,6 +1937,15 @@ static struct usb_device_id uvc_ids[] = { .bInterfaceSubClass = 1, .bInterfaceProtocol = 0, .driver_info = UVC_QUIRK_PROBE_EXTRAFIELDS }, + /* FSC WebCam V30S */ + { .match_flags = USB_DEVICE_ID_MATCH_DEVICE + | USB_DEVICE_ID_MATCH_INT_INFO, + .idVendor = 0x18ec, + .idProduct = 0x3288, + .bInterfaceClass = USB_CLASS_VIDEO, + .bInterfaceSubClass = 1, + .bInterfaceProtocol = 0, + .driver_info = UVC_QUIRK_PROBE_MINMAX }, /* Bodelin ProScopeHR */ { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_DEV_HI -- cgit v1.2.3 From 3d4939aa3fd67ca96970740ca759d960c8511437 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Tue, 9 Jun 2009 18:07:44 +0200 Subject: uvcvideo: Ignore non-UVC trailing interface descriptors. From: Laurent Pinchart Herton Ronaldo Krzesinski from Mandriva reported that one Bison Electronics webcam exposes a non-UVC interface descriptor. Instead of failing completely, ignore trailing non-UVC descriptors and move on. Thanks to Herton for reporting the problem and submitting a patch proposal. Priority: normal Signed-off-by: Laurent Pinchart --- linux/drivers/media/video/uvc/uvc_driver.c | 4 ++-- 1 file changed, 2 insertions(+), 2 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 c62bc8114..40df6828f 100644 --- a/linux/drivers/media/video/uvc/uvc_driver.c +++ b/linux/drivers/media/video/uvc/uvc_driver.c @@ -644,7 +644,7 @@ static int uvc_parse_streaming(struct uvc_device *dev, _buflen = buflen; /* Count the format and frame descriptors. */ - while (_buflen > 2) { + while (_buflen > 2 && _buffer[1] == CS_INTERFACE) { switch (_buffer[2]) { case VS_FORMAT_UNCOMPRESSED: case VS_FORMAT_MJPEG: @@ -709,7 +709,7 @@ static int uvc_parse_streaming(struct uvc_device *dev, streaming->nformats = nformats; /* Parse the format descriptors. */ - while (buflen > 2) { + while (buflen > 2 && buffer[1] == CS_INTERFACE) { switch (buffer[2]) { case VS_FORMAT_UNCOMPRESSED: case VS_FORMAT_MJPEG: -- cgit v1.2.3 From ac8cc4d3dda761c04e7d642d0fc1273e1216f081 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 9 Jun 2009 22:31:55 +0000 Subject: af9015: fix stack corruption bug From: Jan Nikitenko This patch fixes stack corruption bug present in af9015_eeprom_dump(): the buffer buf is one byte smaller than required - there is 4 chars for address prefix, 16*3 chars for dump of 16 eeprom bytes per line and 1 byte for zero ending the string required, i.e. 53 bytes, but only 52 are provided. The one byte missing in stack based buffer buf causes following oops on MIPS little endian platform, because i2c_adap pointer in af9015_af9013_frontend_attach() is corrupted by inlined function af9015_eeprom_dump(): CPU 0 Unable to handle kernel paging request at virtual address 00000000, epc == 803a4488, ra == c049a1c8 Oops[#1]: Cpu 0 $ 0 : 00000000 10003c00 00000000 803a4468 $ 4 : 8f17c600 8f067b30 00000002 00000038 $ 8 : 00000001 8faf3e98 11da000d 09010002 $12 : 00000000 00000000 00000000 0000000a $16 : 8f17c600 8f067b68 8faf3c00 8f067c04 $20 : 8f067b9c 00000100 8f067bf0 80104100 $24 : 00000000 2aba9fb0 $28 : 8f066000 8f067af0 802cbc48 c049a1c8 Hi : 00000000 Lo : 00000000 epc : 803a4488 i2c_transfer+0x20/0x104 Not tainted ra : c049a1c8 af9013_read_reg+0x78/0xc4 [af9013] Status: 10003c03 KERNEL EXL IE Cause : 00808008 BadVA : 00000000 PrId : 03030200 (Au1550) Modules linked in: af9013 dvb_usb_af9015(+) dvb_usb dvb_core firmware_class i2c_au1550 au1550_spi Process modprobe (pid: 2757, threadinfo=8f066000, task=8fade098, tls=2aad6470) Stack : c049f5e0 80163090 805ba880 00000100 8f067bf0 0000d733 8f067b68 8faf3c00 8f067c04 c049a1c8 80163bc0 8056a630 8f067b40 80163224 80569fc8 8f0033d7 00000038 80140003 8f067b2c 00010038 c0420001 8f067b28 c049f5e0 00000004 00000004 c049a524 c049d5a8 c049d5a8 00000000 803a6700 00000000 8f17c600 c042a7a4 8f17c600 c042a7a4 c049c924 00000000 00000000 00000002 613a6c00 ... Call Trace: [<803a4488>] i2c_transfer+0x20/0x104 [] af9013_read_reg+0x78/0xc4 [af9013] [] af9013_read_reg_bits+0x2c/0x70 [af9013] [] af9013_attach+0x98/0x65c [af9013] [] af9015_af9013_frontend_attach+0x214/0x67c [dvb_usb_af9015] [] dvb_usb_adapter_frontend_init+0x20/0x12c [dvb_usb] [] dvb_usb_device_init+0x374/0x6b0 [dvb_usb] [] af9015_usb_probe+0x4fc/0xfcc [dvb_usb_af9015] [<80381024>] usb_probe_interface+0xbc/0x218 [<803227fc>] driver_probe_device+0x12c/0x30c [<80322a80>] __driver_attach+0xa4/0xac [<80321ed0>] bus_for_each_dev+0x60/0xd0 [<8032162c>] bus_add_driver+0x1e8/0x2a8 [<80322cdc>] driver_register+0x7c/0x17c [<80380d30>] usb_register_driver+0xa0/0x12c [] af9015_usb_module_init+0x30/0x6c [dvb_usb_af9015] [<8010d2a4>] __kprobes_text_end+0x3c/0x1f4 [<80167150>] sys_init_module+0xb8/0x1cc [<80102370>] stack_done+0x20/0x3c Code: afb10018 7000003f 00808021 <8c430000> 7000003f 1060002d 00c09021 8f830014 3c02efff Signed-off-by: Jan Nikitenko Acked-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/dvb-usb/af9015.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/dvb-usb/af9015.c b/linux/drivers/media/dvb/dvb-usb/af9015.c index a50bf34af..b6fc8ddf3 100644 --- a/linux/drivers/media/dvb/dvb-usb/af9015.c +++ b/linux/drivers/media/dvb/dvb-usb/af9015.c @@ -541,7 +541,7 @@ exit: /* dump eeprom */ static int af9015_eeprom_dump(struct dvb_usb_device *d) { - char buf[52], buf2[4]; + char buf[4+3*16+1], buf2[4]; u8 reg, val; for (reg = 0; ; reg++) { -- cgit v1.2.3 From 15f999634d9b368effd455da5fecf19a9eef04d6 Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Tue, 9 Jun 2009 19:37:24 -0400 Subject: cx18: Split LeadTek PVR2100 and DVR3100 H into 2 separate card entries From: Andy Walls Priority: normal Signed-off-by: Andy Walls --- linux/drivers/media/video/cx18/cx18-cards.c | 61 ++++++++++++++++++++++++++-- linux/drivers/media/video/cx18/cx18-driver.c | 3 +- linux/drivers/media/video/cx18/cx18-driver.h | 5 ++- 3 files changed, 63 insertions(+), 6 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/cx18/cx18-cards.c b/linux/drivers/media/video/cx18/cx18-cards.c index 8c25ca8e3..3a155d7bd 100644 --- a/linux/drivers/media/video/cx18/cx18-cards.c +++ b/linux/drivers/media/video/cx18/cx18-cards.c @@ -351,13 +351,12 @@ static const struct cx18_card cx18_card_toshiba_qosmio_dvbt = { static const struct cx18_card_pci_info cx18_pci_leadtek_pvr2100[] = { { PCI_DEVICE_ID_CX23418, CX18_PCI_ID_LEADTEK, 0x6f27 }, /* PVR2100 */ - { PCI_DEVICE_ID_CX23418, CX18_PCI_ID_LEADTEK, 0x6690 }, /* DVR3100 H */ { 0, 0, 0 } }; static const struct cx18_card cx18_card_leadtek_pvr2100 = { .type = CX18_CARD_LEADTEK_PVR2100, - .name = "Leadtek WinFast PVR2100/DVR3100 H", + .name = "Leadtek WinFast PVR2100", .comment = "Experimenters and photos needed for device to work well.\n" "\tTo help, mail the ivtv-devel list (www.ivtvdriver.org).\n", .v4l2_capabilities = CX18_CAP_ENCODER, @@ -376,7 +375,7 @@ static const struct cx18_card cx18_card_leadtek_pvr2100 = { { CX18_CARD_INPUT_LINE_IN1, CX18_AV_AUDIO_SERIAL1, 1 }, }, .tuners = { - /* XC3028 tuner */ + /* XC2028 tuner */ { .std = V4L2_STD_ALL, .tuner = TUNER_XC2028 }, }, .radio_input = { CX18_CARD_INPUT_AUD_TUNER, CX18_AV_AUDIO5, 2 }, @@ -403,6 +402,61 @@ static const struct cx18_card cx18_card_leadtek_pvr2100 = { /* ------------------------------------------------------------------------- */ +/* Leadtek WinFast DVR3100 H */ + +static const struct cx18_card_pci_info cx18_pci_leadtek_dvr3100h[] = { + { PCI_DEVICE_ID_CX23418, CX18_PCI_ID_LEADTEK, 0x6690 }, /* DVR3100 H */ + { 0, 0, 0 } +}; + +static const struct cx18_card cx18_card_leadtek_dvr3100h = { + .type = CX18_CARD_LEADTEK_DVR3100H, + .name = "Leadtek WinFast DVR3100 H", + .comment = "Experimenters and photos needed for device to work well.\n" + "\tTo help, mail the ivtv-devel list (www.ivtvdriver.org).\n", + .v4l2_capabilities = CX18_CAP_ENCODER, + .hw_audio_ctrl = CX18_HW_418_AV, + .hw_muxer = CX18_HW_GPIO_MUX, + .hw_all = CX18_HW_418_AV | CX18_HW_TUNER | CX18_HW_GPIO_MUX | + CX18_HW_GPIO_RESET_CTRL, + .video_inputs = { + { CX18_CARD_INPUT_VID_TUNER, 0, CX18_AV_COMPOSITE2 }, + { CX18_CARD_INPUT_SVIDEO1, 1, + CX18_AV_SVIDEO_LUMA3 | CX18_AV_SVIDEO_CHROMA4 }, + { CX18_CARD_INPUT_COMPOSITE1, 1, CX18_AV_COMPOSITE7 }, + }, + .audio_inputs = { + { CX18_CARD_INPUT_AUD_TUNER, CX18_AV_AUDIO5, 0 }, + { CX18_CARD_INPUT_LINE_IN1, CX18_AV_AUDIO_SERIAL1, 1 }, + }, + .tuners = { + /* XC3028 tuner */ + { .std = V4L2_STD_ALL, .tuner = TUNER_XC2028 }, + }, + .radio_input = { CX18_CARD_INPUT_AUD_TUNER, CX18_AV_AUDIO5, 2 }, + .ddr = { + /* + * Pointer to proper DDR config values provided by + * Terry Wu + */ + .chip_config = 0x303, + .refresh = 0x3bb, + .timing1 = 0x24220e83, + .timing2 = 0x1f, + .tune_lane = 0, + .initial_emrs = 0x2, + }, + .gpio_init.initial_value = 0x6, + .gpio_init.direction = 0x7, + .gpio_audio_input = { .mask = 0x7, + .tuner = 0x6, .linein = 0x2, .radio = 0x2 }, + .xceive_pin = 15, + .pci_list = cx18_pci_leadtek_dvr3100h, + .i2c = &cx18_i2c_std, +}; + +/* ------------------------------------------------------------------------- */ + static const struct cx18_card *cx18_card_list[] = { &cx18_card_hvr1600_esmt, &cx18_card_hvr1600_samsung, @@ -411,6 +465,7 @@ static const struct cx18_card *cx18_card_list[] = { &cx18_card_cnxt_raptor_pal, &cx18_card_toshiba_qosmio_dvbt, &cx18_card_leadtek_pvr2100, + &cx18_card_leadtek_dvr3100h, }; const struct cx18_card *cx18_get_card(u16 index) diff --git a/linux/drivers/media/video/cx18/cx18-driver.c b/linux/drivers/media/video/cx18/cx18-driver.c index f42a97314..7ffdda49c 100644 --- a/linux/drivers/media/video/cx18/cx18-driver.c +++ b/linux/drivers/media/video/cx18/cx18-driver.c @@ -152,7 +152,8 @@ MODULE_PARM_DESC(cardtype, "\t\t\t 4 = Yuan MPC718\n" "\t\t\t 5 = Conexant Raptor PAL/SECAM\n" "\t\t\t 6 = Toshiba Qosmio DVB-T/Analog\n" - "\t\t\t 7 = Leadtek WinFast PVR2100/DVR3100 H\n" + "\t\t\t 7 = Leadtek WinFast PVR2100\n" + "\t\t\t 8 = Leadtek WinFast DVR3100 H\n" "\t\t\t 0 = Autodetect (default)\n" "\t\t\t-1 = Ignore this card\n\t\t"); MODULE_PARM_DESC(pal, "Set PAL standard: B, G, H, D, K, I, M, N, Nc, 60"); diff --git a/linux/drivers/media/video/cx18/cx18-driver.h b/linux/drivers/media/video/cx18/cx18-driver.h index f89b82367..c6a1e907f 100644 --- a/linux/drivers/media/video/cx18/cx18-driver.h +++ b/linux/drivers/media/video/cx18/cx18-driver.h @@ -80,8 +80,9 @@ #define CX18_CARD_YUAN_MPC718 3 /* Yuan MPC718 */ #define CX18_CARD_CNXT_RAPTOR_PAL 4 /* Conexant Raptor PAL */ #define CX18_CARD_TOSHIBA_QOSMIO_DVBT 5 /* Toshiba Qosmio Interal DVB-T/Analog*/ -#define CX18_CARD_LEADTEK_PVR2100 6 /* Leadtek WinFast PVR2100/DVR3100 H */ -#define CX18_CARD_LAST 6 +#define CX18_CARD_LEADTEK_PVR2100 6 /* Leadtek WinFast PVR2100 */ +#define CX18_CARD_LEADTEK_DVR3100H 7 /* Leadtek WinFast DVR3100 H */ +#define CX18_CARD_LAST 7 #define CX18_ENC_STREAM_TYPE_MPG 0 #define CX18_ENC_STREAM_TYPE_TS 1 -- cgit v1.2.3 From 4b038fe7fa0a646fedf0e49aa2bfba38c814e3ad Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Tue, 9 Jun 2009 19:47:21 -0400 Subject: cx18: Add DVB-T support for the Leadtek WinFast DVR3100 H From: Andy Walls This adds support for DVB-T on the Leadtek DVR3100 H and should also get analog TV capture from the tuner working properly as well. DVB-T 6 MHz and 8 MHz have been tested and verified to work by Terry Wu of Leadtek. DVB-T 7 MHz has also been verified working with a change developed by Terry to the tuner-xc2028.c driver. Special thanks go to Terry Wu of Leadtek who provided the needed information and testing to get digital TV working for the Leadtek DVR3100 H. Reported-by: Terry Wu Priority: normal Tested-by: Terry Wu Signed-off-by: Andy Walls --- linux/drivers/media/video/cx18/cx18-cards.c | 18 ++++------ linux/drivers/media/video/cx18/cx18-dvb.c | 53 +++++++++++++++++++++++++++-- 2 files changed, 57 insertions(+), 14 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/cx18/cx18-cards.c b/linux/drivers/media/video/cx18/cx18-cards.c index 3a155d7bd..fa755a982 100644 --- a/linux/drivers/media/video/cx18/cx18-cards.c +++ b/linux/drivers/media/video/cx18/cx18-cards.c @@ -380,10 +380,7 @@ static const struct cx18_card cx18_card_leadtek_pvr2100 = { }, .radio_input = { CX18_CARD_INPUT_AUD_TUNER, CX18_AV_AUDIO5, 2 }, .ddr = { - /* - * Pointer to proper DDR config values provided by - * Terry Wu - */ + /* Pointer to proper DDR config values provided by Terry Wu */ .chip_config = 0x303, .refresh = 0x3bb, .timing1 = 0x24220e83, @@ -412,13 +409,13 @@ static const struct cx18_card_pci_info cx18_pci_leadtek_dvr3100h[] = { static const struct cx18_card cx18_card_leadtek_dvr3100h = { .type = CX18_CARD_LEADTEK_DVR3100H, .name = "Leadtek WinFast DVR3100 H", - .comment = "Experimenters and photos needed for device to work well.\n" - "\tTo help, mail the ivtv-devel list (www.ivtvdriver.org).\n", + .comment = "Simultaneous DVB-T and Analog capture supported,\n" + "\texcept when capturing Analog from the antenna input.\n", .v4l2_capabilities = CX18_CAP_ENCODER, .hw_audio_ctrl = CX18_HW_418_AV, .hw_muxer = CX18_HW_GPIO_MUX, .hw_all = CX18_HW_418_AV | CX18_HW_TUNER | CX18_HW_GPIO_MUX | - CX18_HW_GPIO_RESET_CTRL, + CX18_HW_DVB | CX18_HW_GPIO_RESET_CTRL, .video_inputs = { { CX18_CARD_INPUT_VID_TUNER, 0, CX18_AV_COMPOSITE2 }, { CX18_CARD_INPUT_SVIDEO1, 1, @@ -435,10 +432,7 @@ static const struct cx18_card cx18_card_leadtek_dvr3100h = { }, .radio_input = { CX18_CARD_INPUT_AUD_TUNER, CX18_AV_AUDIO5, 2 }, .ddr = { - /* - * Pointer to proper DDR config values provided by - * Terry Wu - */ + /* Pointer to proper DDR config values provided by Terry Wu */ .chip_config = 0x303, .refresh = 0x3bb, .timing1 = 0x24220e83, @@ -450,7 +444,7 @@ static const struct cx18_card cx18_card_leadtek_dvr3100h = { .gpio_init.direction = 0x7, .gpio_audio_input = { .mask = 0x7, .tuner = 0x6, .linein = 0x2, .radio = 0x2 }, - .xceive_pin = 15, + .xceive_pin = 1, .pci_list = cx18_pci_leadtek_dvr3100h, .i2c = &cx18_i2c_std, }; diff --git a/linux/drivers/media/video/cx18/cx18-dvb.c b/linux/drivers/media/video/cx18/cx18-dvb.c index e7285a109..6ea3fe623 100644 --- a/linux/drivers/media/video/cx18/cx18-dvb.c +++ b/linux/drivers/media/video/cx18/cx18-dvb.c @@ -26,12 +26,17 @@ #include "cx18-queue.h" #include "cx18-streams.h" #include "cx18-cards.h" +#include "cx18-gpio.h" #include "s5h1409.h" #include "mxl5005s.h" +#include "zl10353.h" +#include "tuner-xc2028.h" DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); #define CX18_REG_DMUX_NUM_PORT_0_CONTROL 0xd5a000 +#define CX18_CLOCK_ENABLE2 0xc71024 +#define CX18_DMUX_CLK_MASK 0x0080 static struct mxl5005s_config hauppauge_hvr1600_tuner = { .i2c_address = 0xC6 >> 1, @@ -58,7 +63,15 @@ static struct s5h1409_config hauppauge_hvr1600_config = { .inversion = S5H1409_INVERSION_OFF, .status_mode = S5H1409_DEMODLOCKING, .mpeg_timing = S5H1409_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK +}; +/* Information/confirmation of proper config values provided by Terry Wu */ +static struct zl10353_config leadtek_dvr3100h_demod = { + .demod_address = 0x1e >> 1, /* Datasheet suggested straps */ + .if2 = 45600, /* 4.560 MHz IF from the XC3028 */ + .parallel_ts = 1, /* Not a serial TS */ + .no_tuner = 1, /* XC3028 is not behind the gate */ + .disable_i2c_gate_ctrl = 1, /* Disable the I2C gate */ }; static int dvb_register(struct cx18_stream *stream); @@ -99,6 +112,7 @@ static int cx18_dvb_start_feed(struct dvb_demux_feed *feed) cx18_write_reg(cx, v, CX18_REG_DMUX_NUM_PORT_0_CONTROL); break; + case CX18_CARD_LEADTEK_DVR3100H: default: /* Assumption - Parallel transport - Signalling * undefined or default. @@ -268,8 +282,7 @@ void cx18_dvb_unregister(struct cx18_stream *stream) } /* All the DVB attach calls go here, this function get's modified - * for each new card. No other function in this file needs - * to change. + * for each new card. cx18_dvb_start_feed() will also need changes. */ static int dvb_register(struct cx18_stream *stream) { @@ -290,6 +303,29 @@ static int dvb_register(struct cx18_stream *stream) ret = 0; } break; + case CX18_CARD_LEADTEK_DVR3100H: + dvb->fe = dvb_attach(zl10353_attach, + &leadtek_dvr3100h_demod, + &cx->i2c_adap[1]); + if (dvb->fe != NULL) { + struct dvb_frontend *fe; + struct xc2028_config cfg = { + .i2c_adap = &cx->i2c_adap[1], + .i2c_addr = 0xc2 >> 1, + .ctrl = NULL, + }; + static struct xc2028_ctrl ctrl = { + .fname = XC2028_DEFAULT_FIRMWARE, + .max_len = 64, + .demod = XC3028_FE_ZARLINK456, + .type = XC2028_AUTO, + }; + + fe = dvb_attach(xc2028_attach, dvb->fe, &cfg); + if (fe != NULL && fe->ops.tuner_ops.set_config != NULL) + fe->ops.tuner_ops.set_config(fe, &ctrl); + } + break; default: /* No Digital Tv Support */ break; @@ -300,6 +336,8 @@ static int dvb_register(struct cx18_stream *stream) return -1; } + dvb->fe->callback = cx18_reset_tuner_gpio; + ret = dvb_register_frontend(&dvb->dvb_adapter, dvb->fe); if (ret < 0) { if (dvb->fe->ops.release) @@ -307,5 +345,16 @@ static int dvb_register(struct cx18_stream *stream) return ret; } + /* + * The firmware seems to enable the TS DMUX clock + * under various circumstances. However, since we know we + * might use it, let's just turn it on ourselves here. + */ + cx18_write_reg_expect(cx, + (CX18_DMUX_CLK_MASK << 16) | CX18_DMUX_CLK_MASK, + CX18_CLOCK_ENABLE2, + CX18_DMUX_CLK_MASK, + (CX18_DMUX_CLK_MASK << 16) | CX18_DMUX_CLK_MASK); + return ret; } -- cgit v1.2.3 From f708b2952b9d0de978b0e0cf51d8e0a80c8fb2d9 Mon Sep 17 00:00:00 2001 From: Douglas Schilling Landgraf Date: Wed, 10 Jun 2009 23:17:27 -0300 Subject: V4L: return -ENOMEM From: Figo.zhang it is better return -ENOMEM than -EIO Priority: normal Signed-off-by: Figo.zhang Signed-off-by: Douglas Schilling Landgraf --- linux/drivers/media/video/videobuf-dma-sg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (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 623e2fc12..da83ac706 100644 --- a/linux/drivers/media/video/videobuf-dma-sg.c +++ b/linux/drivers/media/video/videobuf-dma-sg.c @@ -253,7 +253,7 @@ int videobuf_dma_map(struct videobuf_queue* q, struct videobuf_dmabuf *dma) vfree(dma->sglist); dma->sglist = NULL; dma->sglen = 0; - return -EIO; + return -ENOMEM; } } return 0; -- cgit v1.2.3 From da17eb94cb9a3f153994bdb52d41095c58d2732d Mon Sep 17 00:00:00 2001 From: Douglas Schilling Landgraf Date: Thu, 11 Jun 2009 00:17:06 -0300 Subject: dsbr100: remove radio->users counter From: Alexey Klimov Patch removes radio->users counter because it is not in use. Priority: normal Signed-off-by: Alexey Klimov Signed-off-by: Douglas Schilling Landgraf --- linux/drivers/media/radio/dsbr100.c | 8 -------- 1 file changed, 8 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/radio/dsbr100.c b/linux/drivers/media/radio/dsbr100.c index bd13bef85..f37c535a9 100644 --- a/linux/drivers/media/radio/dsbr100.c +++ b/linux/drivers/media/radio/dsbr100.c @@ -146,7 +146,6 @@ struct dsbr100_device { struct mutex lock; /* buffer locking */ int curfreq; int stereo; - int users; int removed; int muted; }; @@ -552,14 +551,12 @@ static int usb_dsbr100_open(struct file *file) int retval; lock_kernel(); - radio->users = 1; radio->muted = 1; retval = dsbr100_start(radio); if (retval < 0) { dev_warn(&radio->usbdev->dev, "Radio did not start up properly\n"); - radio->users = 0; unlock_kernel(); return -EIO; } @@ -581,10 +578,6 @@ static int usb_dsbr100_close(struct file *file) if (!radio) return -ENODEV; - mutex_lock(&radio->lock); - radio->users = 0; - mutex_unlock(&radio->lock); - if (!radio->removed) { retval = dsbr100_stop(radio); if (retval < 0) { @@ -698,7 +691,6 @@ static int usb_dsbr100_probe(struct usb_interface *intf, mutex_init(&radio->lock); radio->removed = 0; - radio->users = 0; radio->usbdev = interface_to_usbdev(intf); radio->curfreq = FREQ_MIN * FREQ_MUL; -- cgit v1.2.3 From 6bf2b298d078666cdb61e3360d5f478f2c0e6524 Mon Sep 17 00:00:00 2001 From: Douglas Schilling Landgraf Date: Thu, 11 Jun 2009 00:18:35 -0300 Subject: dsbr100: remove usb_dsbr100_open/close calls From: Alexey Klimov Priority: normal Signed-off-by: Alexey Klimov Signed-off-by: Douglas Schilling Landgraf --- linux/drivers/media/radio/dsbr100.c | 48 ------------------------------------- 1 file changed, 48 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/radio/dsbr100.c b/linux/drivers/media/radio/dsbr100.c index f37c535a9..e9bb4f9c1 100644 --- a/linux/drivers/media/radio/dsbr100.c +++ b/linux/drivers/media/radio/dsbr100.c @@ -127,8 +127,6 @@ devices, that would be 76 and 91. */ static int usb_dsbr100_probe(struct usb_interface *intf, const struct usb_device_id *id); static void usb_dsbr100_disconnect(struct usb_interface *intf); -static int usb_dsbr100_open(struct file *file); -static int usb_dsbr100_close(struct file *file); static int usb_dsbr100_suspend(struct usb_interface *intf, pm_message_t message); static int usb_dsbr100_resume(struct usb_interface *intf); @@ -545,50 +543,6 @@ static int vidioc_s_audio(struct file *file, void *priv, return 0; } -static int usb_dsbr100_open(struct file *file) -{ - struct dsbr100_device *radio = video_drvdata(file); - int retval; - - lock_kernel(); - radio->muted = 1; - - retval = dsbr100_start(radio); - if (retval < 0) { - dev_warn(&radio->usbdev->dev, - "Radio did not start up properly\n"); - unlock_kernel(); - return -EIO; - } - - retval = dsbr100_setfreq(radio, radio->curfreq); - if (retval < 0) - dev_warn(&radio->usbdev->dev, - "set frequency failed\n"); - - unlock_kernel(); - return 0; -} - -static int usb_dsbr100_close(struct file *file) -{ - struct dsbr100_device *radio = video_drvdata(file); - int retval; - - if (!radio) - return -ENODEV; - - if (!radio->removed) { - retval = dsbr100_stop(radio); - if (retval < 0) { - dev_warn(&radio->usbdev->dev, - "dsbr100_stop failed\n"); - } - - } - return 0; -} - /* Suspend device - stop device. */ static int usb_dsbr100_suspend(struct usb_interface *intf, pm_message_t message) { @@ -632,8 +586,6 @@ static void usb_dsbr100_video_device_release(struct video_device *videodev) /* File system interface */ static const struct v4l2_file_operations usb_dsbr100_fops = { .owner = THIS_MODULE, - .open = usb_dsbr100_open, - .release = usb_dsbr100_close, .ioctl = video_ioctl2, }; -- cgit v1.2.3 From 6bea6dd6ddb19d2e3257cc14e4df56daaee39aa0 Mon Sep 17 00:00:00 2001 From: Douglas Schilling Landgraf Date: Thu, 11 Jun 2009 00:19:49 -0300 Subject: dsbr100: no need to pass curfreq value to dsbr100_setfreq() From: Alexey Klimov Small cleanup of dsbr100_setfreq(). No need to pass radio->curfreq value to this function. Priority: normal Signed-off-by: Alexey Klimov Signed-off-by: Douglas Schilling Landgraf --- linux/drivers/media/radio/dsbr100.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/radio/dsbr100.c b/linux/drivers/media/radio/dsbr100.c index e9bb4f9c1..9b4f1d2ea 100644 --- a/linux/drivers/media/radio/dsbr100.c +++ b/linux/drivers/media/radio/dsbr100.c @@ -258,12 +258,12 @@ usb_control_msg_failed: } /* set a frequency, freq is defined by v4l's TUNER_LOW, i.e. 1/16th kHz */ -static int dsbr100_setfreq(struct dsbr100_device *radio, int freq) +static int dsbr100_setfreq(struct dsbr100_device *radio) { int retval; int request; + int freq = (radio->curfreq / 16 * 80) / 1000 + 856; - freq = (freq / 16 * 80) / 1000 + 856; mutex_lock(&radio->lock); retval = usb_control_msg(radio->usbdev, @@ -431,7 +431,7 @@ static int vidioc_s_frequency(struct file *file, void *priv, radio->curfreq = f->frequency; mutex_unlock(&radio->lock); - retval = dsbr100_setfreq(radio, radio->curfreq); + retval = dsbr100_setfreq(radio); if (retval < 0) dev_warn(&radio->usbdev->dev, "Set frequency failed\n"); return 0; -- cgit v1.2.3 From 2c27de496b19238e991e8e4cf930d2b9998fd71b Mon Sep 17 00:00:00 2001 From: Douglas Schilling Landgraf Date: Thu, 11 Jun 2009 00:22:42 -0300 Subject: dsbr100: change radio->muted to radio->status, update suspend/resume From: Alexey Klimov Patch renames radio->muted to radio->status, add defines for that variable, and fixes suspend/resume procedure. Radio->status set to STOPPED in usb_dsbr100_probe because of removing open call. Also, patch increases driver version. Priority: normal Signed-off-by: Alexey Klimov Signed-off-by: Douglas Schilling Landgraf --- linux/drivers/media/radio/dsbr100.c | 47 +++++++++++++++++++++++++++---------- 1 file changed, 35 insertions(+), 12 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/radio/dsbr100.c b/linux/drivers/media/radio/dsbr100.c index 9b4f1d2ea..2bb867720 100644 --- a/linux/drivers/media/radio/dsbr100.c +++ b/linux/drivers/media/radio/dsbr100.c @@ -33,6 +33,10 @@ History: + Version 0.46: + Removed usb_dsbr100_open/close calls and radio->users counter. Also, + radio->muted changed to radio->status and suspend/resume calls updated. + Version 0.45: Converted to v4l2_device. @@ -101,8 +105,8 @@ */ #include /* for KERNEL_VERSION MACRO */ -#define DRIVER_VERSION "v0.45" -#define RADIO_VERSION KERNEL_VERSION(0, 4, 5) +#define DRIVER_VERSION "v0.46" +#define RADIO_VERSION KERNEL_VERSION(0, 4, 6) #define DRIVER_AUTHOR "Markus Demleitner " #define DRIVER_DESC "D-Link DSB-R100 USB FM radio driver" @@ -122,6 +126,10 @@ devices, that would be 76 and 91. */ #define FREQ_MAX 108.0 #define FREQ_MUL 16000 +/* defines for radio->status */ +#define STARTED 0 +#define STOPPED 1 + #define videodev_to_radio(d) container_of(d, struct dsbr100_device, videodev) static int usb_dsbr100_probe(struct usb_interface *intf, @@ -145,7 +153,7 @@ struct dsbr100_device { int curfreq; int stereo; int removed; - int muted; + int status; }; static struct usb_device_id usb_dsbr100_device_table [] = { @@ -201,7 +209,7 @@ static int dsbr100_start(struct dsbr100_device *radio) goto usb_control_msg_failed; } - radio->muted = 0; + radio->status = STARTED; mutex_unlock(&radio->lock); return (radio->transfer_buffer)[0]; @@ -244,7 +252,7 @@ static int dsbr100_stop(struct dsbr100_device *radio) goto usb_control_msg_failed; } - radio->muted = 1; + radio->status = STOPPED; mutex_unlock(&radio->lock); return (radio->transfer_buffer)[0]; @@ -473,7 +481,7 @@ static int vidioc_g_ctrl(struct file *file, void *priv, switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: - ctrl->value = radio->muted; + ctrl->value = radio->status; return 0; } return -EINVAL; @@ -549,9 +557,21 @@ static int usb_dsbr100_suspend(struct usb_interface *intf, pm_message_t message) struct dsbr100_device *radio = usb_get_intfdata(intf); int retval; - retval = dsbr100_stop(radio); - if (retval < 0) - dev_warn(&intf->dev, "dsbr100_stop failed\n"); + if (radio->status == STARTED) { + retval = dsbr100_stop(radio); + if (retval < 0) + dev_warn(&intf->dev, "dsbr100_stop failed\n"); + + /* After dsbr100_stop() status set to STOPPED. + * If we want driver to start radio on resume + * we set status equal to STARTED. + * On resume we will check status and run radio if needed. + */ + + mutex_lock(&radio->lock); + radio->status = STARTED; + mutex_unlock(&radio->lock); + } dev_info(&intf->dev, "going into suspend..\n"); @@ -564,9 +584,11 @@ static int usb_dsbr100_resume(struct usb_interface *intf) struct dsbr100_device *radio = usb_get_intfdata(intf); int retval; - retval = dsbr100_start(radio); - if (retval < 0) - dev_warn(&intf->dev, "dsbr100_start failed\n"); + if (radio->status == STARTED) { + retval = dsbr100_start(radio); + if (retval < 0) + dev_warn(&intf->dev, "dsbr100_start failed\n"); + } dev_info(&intf->dev, "coming out of suspend..\n"); @@ -645,6 +667,7 @@ static int usb_dsbr100_probe(struct usb_interface *intf, radio->removed = 0; radio->usbdev = interface_to_usbdev(intf); radio->curfreq = FREQ_MIN * FREQ_MUL; + radio->status = STOPPED; video_set_drvdata(&radio->videodev, radio); -- cgit v1.2.3 From 29da0924e21b20128e9ce9eca275630941586d84 Mon Sep 17 00:00:00 2001 From: Patrick Boettcher Date: Thu, 11 Jun 2009 10:33:00 +0200 Subject: b2c2: Fix problems with frontend attachment From: Trent Piepho The frontend attachment code didn't handle cases where the frontend partially failed to attach. For instance, when the demod was attached successfully but the tuner driver wasn't compiled or fails to init for some reason. In these cases we try to clean up the partial attachment and fail instead of proceeding with a broken frontend. If frontend registration fails, clean up with dvb_frontend_detach() rather than just calling the frontend's main release method. The former does some additional stuff, like release an attached tuner and take care of putting symbols when dynamic binding is used. In skystar2_rev23_attach() it's not necessary to set fc->dev_type, that gets set before skystar2_rev23_attach() is called. Priority: normal Signed-off-by: Trent Piepho Signed-off-by: Patrick Boettcher --- linux/drivers/media/dvb/b2c2/flexcop-fe-tuner.c | 196 ++++++++++++++---------- 1 file changed, 113 insertions(+), 83 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/b2c2/flexcop-fe-tuner.c b/linux/drivers/media/dvb/b2c2/flexcop-fe-tuner.c index 3f485bf13..efb4a6c2b 100644 --- a/linux/drivers/media/dvb/b2c2/flexcop-fe-tuner.c +++ b/linux/drivers/media/dvb/b2c2/flexcop-fe-tuner.c @@ -175,23 +175,23 @@ static int skystar23_samsung_tbdu18132_tuner_set_params(struct dvb_frontend *fe, return 0; } -static void skystar2_rev23_attach(struct flexcop_device *fc, +static int skystar2_rev23_attach(struct flexcop_device *fc, struct i2c_adapter *i2c) { - fc->fe = dvb_attach(mt312_attach, - &skystar23_samsung_tbdu18132_config, 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->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; + return 1; } + return 0; } #endif @@ -307,7 +307,7 @@ static struct stv0299_config samsung_tbmu24112_config = { .set_symbol_rate = samsung_tbmu24112_set_symbol_rate, }; -static void skystar2_rev26_attach(struct flexcop_device *fc, +static int skystar2_rev26_attach(struct flexcop_device *fc, struct i2c_adapter *i2c) { fc->fe = dvb_attach(stv0299_attach, &samsung_tbmu24112_config, i2c); @@ -317,7 +317,9 @@ static void skystar2_rev26_attach(struct flexcop_device *fc, ops->set_voltage = flexcop_set_voltage; fc->fe_sleep = ops->sleep; ops->sleep = flexcop_sleep; + return 1; } + return 0; } #endif @@ -334,43 +336,54 @@ static struct itd1000_config skystar2_rev2_7_itd1000_config = { .i2c_address = 0x61, }; -static void skystar2_rev27_attach(struct flexcop_device *fc, +static int skystar2_rev27_attach(struct flexcop_device *fc, struct i2c_adapter *i2c) { + flexcop_ibi_value r108; + 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; - struct i2c_adapter *i2c_tuner \ - = s5h1420_get_tuner_i2c_adapter(fc->fe); - struct dvb_frontend_ops *ops = &fc->fe->ops; + fc->fe = dvb_attach(s5h1420_attach, &skystar2_rev2_7_s5h1420_config, + i2c); + if (!fc->fe) + goto fail; - 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 */ + i2c_tuner = s5h1420_get_tuner_i2c_adapter(fc->fe); + if (!i2c_tuner) + goto fail; + + fc->fe_sleep = fc->fe->ops.sleep; + fc->fe->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)) { + err("ISL6421 could NOT be attached"); + goto fail_isl; + } + 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 (!dvb_attach(itd1000_attach, fc->fe, i2c_tuner, + &skystar2_rev2_7_itd1000_config)) { + err("ITD1000 could NOT be attached"); + /* Should i2c clock be restored? */ + goto fail_isl; + } + info("ITD1000 successfully attached"); + + return 1; + +fail_isl: + fc->fc_i2c_adap[2].no_base_addr = 0; +fail: + /* for the next devices we need it again */ + fc->fc_i2c_adap[0].no_base_addr = 0; + return 0; } #endif @@ -387,32 +400,38 @@ static const struct cx24113_config skystar2_rev2_8_cx24113_config = { .xtal_khz = 10111, }; -static void skystar2_rev28_attach(struct flexcop_device *fc, +static int 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"); - } + struct i2c_adapter *i2c_tuner; + + fc->fe = dvb_attach(cx24123_attach, &skystar2_rev2_8_cx24123_config, + i2c); + if (!fc->fe) + return 0; + + i2c_tuner = cx24123_get_tuner_i2c_adapter(fc->fe);; + if (!i2c_tuner) + return 0; - 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"); + if (!dvb_attach(cx24113_attach, fc->fe, &skystar2_rev2_8_cx24113_config, + i2c_tuner)) { + err("CX24113 could NOT be attached"); + return 0; + } + 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)) { + err("ISL6421 could NOT be attached"); + fc->fc_i2c_adap[2].no_base_addr = 0; + return 0; + } + 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 ??? */ - } + return 1; } #endif @@ -466,12 +485,15 @@ static struct mt352_config samsung_tdtc9251dh0_config = { .demod_init = samsung_tdtc9251dh0_demod_init, }; -static void airstar_dvbt_attach(struct flexcop_device *fc, +static int 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) + if (fc->fe != NULL) { fc->fe->ops.tuner_ops.calc_regs = samsung_tdtc9251dh0_calc_regs; + return 1; + } + return 0; } #endif @@ -489,10 +511,11 @@ static struct bcm3510_config air2pc_atsc_first_gen_config = { .request_firmware = flexcop_fe_request_firmware, }; -static void airstar_atsc1_attach(struct flexcop_device *fc, +static int airstar_atsc1_attach(struct flexcop_device *fc, struct i2c_adapter *i2c) { fc->fe = dvb_attach(bcm3510_attach, &air2pc_atsc_first_gen_config, i2c); + return fc->fe != NULL; } #endif @@ -502,13 +525,15 @@ static struct nxt200x_config samsung_tbmv_config = { .demod_address = 0x0a, }; -static void airstar_atsc2_attach(struct flexcop_device *fc, +static int 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); + if (!fc->fe) + return 0; + + return !!dvb_attach(dvb_pll_attach, fc->fe, 0x61, NULL, + DVB_PLL_SAMSUNG_TBMV); } #endif @@ -521,14 +546,15 @@ static struct lgdt330x_config air2pc_atsc_hd5000_config = { .clock_polarity_flip = 1, }; -static void airstar_atsc3_attach(struct flexcop_device *fc, +static int 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); - } + if (!fc->fe) + return 0; + + return !!dvb_attach(simple_tuner_attach, fc->fe, i2c, 0x61, + TUNER_LG_TDVS_H06XF); } #endif @@ -659,22 +685,24 @@ static struct stv0297_config alps_tdee4_stv0297_config = { .inittab = alps_tdee4_stv0297_inittab, }; -static void cablestar2_attach(struct flexcop_device *fc, +static int cablestar2_attach(struct flexcop_device *fc, struct i2c_adapter *i2c) { 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->fe->ops.tuner_ops.set_params \ - = alps_tdee4_stv0297_tuner_set_params; - else + if (!fc->fe) { + /* Reset for next frontend to try */ fc->fc_i2c_adap[0].no_base_addr = 0; + return 0; + } + fc->fe->ops.tuner_ops.set_params = alps_tdee4_stv0297_tuner_set_params; + return 1; } #endif static struct { flexcop_device_type_t type; - void (*attach)(struct flexcop_device *, struct i2c_adapter *); + int (*attach)(struct flexcop_device *, struct i2c_adapter *); } flexcop_frontends[] = { #if defined(CONFIG_DVB_S5H1420_MODULE) { FC_SKY_REV27, skystar2_rev27_attach }, @@ -713,9 +741,13 @@ int flexcop_frontend_init(struct flexcop_device *fc) /* 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) + if (flexcop_frontends[i].attach(fc, &fc->fc_i2c_adap[0].i2c_adap)) goto fe_found; + /* Clean up partially attached frontend */ + if (fc->fe) { + dvb_frontend_detach(fc->fe); + fc->fe = NULL; + } } fc->dev_type = FC_UNK; err("no frontend driver found for this B2C2/FlexCop adapter"); @@ -724,10 +756,8 @@ int flexcop_frontend_init(struct flexcop_device *fc) 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!"); - if (ops->release != NULL) - ops->release(fc->fe); + dvb_frontend_detach(fc->fe); fc->fe = NULL; return -EINVAL; } -- cgit v1.2.3 From 3a81029396ea0bf8d3815ad1337b6d99a8b18240 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 11 Jun 2009 06:57:50 -0400 Subject: tuner-xc2028: Fix 7 MHz DVB-T From: Andy Walls The following patch should fix 7 MHz DVB-T with the XC3028 using the DTV7 firmware from the xc3028-v27.fw firmware image. Signed-off-by: Andy Walls Tested-by: Terry Wu [mchehab@redhat.com: thanks to John Ferlito, we have a real test in Australia] Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/common/tuners/tuner-xc2028.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 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 a7466867c..8ead0e1e1 100644 --- a/linux/drivers/media/common/tuners/tuner-xc2028.c +++ b/linux/drivers/media/common/tuners/tuner-xc2028.c @@ -1100,8 +1100,19 @@ static int xc2028_set_params(struct dvb_frontend *fe, } /* All S-code tables need a 200kHz shift */ - if (priv->ctrl.demod) + if (priv->ctrl.demod) { demod = priv->ctrl.demod + 200; + /* + * The DTV7 S-code table needs a 700 kHz shift. + * Thanks to Terry Wu for reporting this + * + * DTV7 is only used in Australia. Germany or Italy may also + * use this firmware after initialization, but a tune to a UHF + * channel should then cause DTV78 to be used. + */ + if (type & DTV7) + demod += 500; + } return generic_set_freq(fe, p->frequency, T_DIGITAL_TV, type, 0, demod); -- cgit v1.2.3 From f4b54f7a0bb1daf912ce8e3013e34cccebba6a34 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 11 Jun 2009 12:38:54 +0000 Subject: lgs8gxx: lgs8913 fake signal strength option default on From: David Wong lgs8gxx: lgs8913 fake signal strength option default on. Original calculation is too slow. Signed-off-by: David T.L. Wong gmail.com> Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/frontends/lgs8gxx.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/frontends/lgs8gxx.c b/linux/drivers/media/dvb/frontends/lgs8gxx.c index 1395f3b5b..a5b7bdeff 100644 --- a/linux/drivers/media/dvb/frontends/lgs8gxx.c +++ b/linux/drivers/media/dvb/frontends/lgs8gxx.c @@ -37,14 +37,14 @@ } while (0) static int debug; -static int fake_signal_str; +static int fake_signal_str = 1; module_param(debug, int, 0644); MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off)."); module_param(fake_signal_str, int, 0644); MODULE_PARM_DESC(fake_signal_str, "fake signal strength for LGS8913." -"Signal strength calculation is slow.(default:off)."); +"Signal strength calculation is slow.(default:on)."); /* LGS8GXX internal helper functions */ -- cgit v1.2.3 From 4a2e9d7d8ff2bfc867b6ac6b4ebf2c831b1c6e0a Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 11 Jun 2009 12:39:04 +0000 Subject: lgs8gxx: update signal strength scale From: David Wong lgs8gxx: update signal strength scale Signed-off-by: David T.L. Wong gmail.com> Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/frontends/lgs8gxx.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/frontends/lgs8gxx.c b/linux/drivers/media/dvb/frontends/lgs8gxx.c index a5b7bdeff..1ce30aa53 100644 --- a/linux/drivers/media/dvb/frontends/lgs8gxx.c +++ b/linux/drivers/media/dvb/frontends/lgs8gxx.c @@ -650,7 +650,7 @@ static int lgs8gxx_read_signal_agc(struct lgs8gxx_state *priv, u16 *signal) else cat = 0; - *signal = cat; + *signal = cat * 65535 / 5; return 0; } @@ -670,8 +670,8 @@ static int lgs8913_read_signal_strength(struct lgs8gxx_state *priv, u16 *signal) if (fake_signal_str) { if ((t & 0xC0) == 0xC0) { - dprintk("Fake signal strength as 50\n"); - *signal = 0x32; + dprintk("Fake signal strength\n"); + *signal = 0x7FFF; } else *signal = 0; return 0; -- cgit v1.2.3 From ec19d917aadc39178db95a5f7cc012f1cc8b6718 Mon Sep 17 00:00:00 2001 From: Douglas Schilling Landgraf Date: Thu, 11 Jun 2009 10:33:31 -0300 Subject: usbvision-core.c: vfree does its own NULL check From: Figo.zhang vfree() does it's own NULL checking,so no need for check before calling it. Priority: normal Signed-off-by: Figo.zhang Signed-off-by: Douglas Schilling Landgraf --- linux/drivers/media/video/usbvision/usbvision-core.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/usbvision/usbvision-core.c b/linux/drivers/media/video/usbvision/usbvision-core.c index 9253ec6dd..baf2e5621 100644 --- a/linux/drivers/media/video/usbvision/usbvision-core.c +++ b/linux/drivers/media/video/usbvision/usbvision-core.c @@ -390,10 +390,9 @@ int usbvision_scratch_alloc(struct usb_usbvision *usbvision) void usbvision_scratch_free(struct usb_usbvision *usbvision) { - if (usbvision->scratch != NULL) { - vfree(usbvision->scratch); - usbvision->scratch = NULL; - } + vfree(usbvision->scratch); + usbvision->scratch = NULL; + } /* @@ -506,10 +505,9 @@ int usbvision_decompress_alloc(struct usb_usbvision *usbvision) */ void usbvision_decompress_free(struct usb_usbvision *usbvision) { - if (usbvision->IntraFrameBuffer != NULL) { - vfree(usbvision->IntraFrameBuffer); - usbvision->IntraFrameBuffer = NULL; - } + vfree(usbvision->IntraFrameBuffer); + usbvision->IntraFrameBuffer = NULL; + } /************************************************************ -- cgit v1.2.3 From ac6085626ffae1908cb5c07d90bf7fcfed25c5f9 Mon Sep 17 00:00:00 2001 From: Douglas Schilling Landgraf Date: Thu, 11 Jun 2009 11:04:11 -0300 Subject: se401: Fix unsafe use of sprintf with identical source/destination From: Alan Cox Closes-bug: http://bugzilla.kernel.org/show_bug.cgi?id=13435 Priority: normal Signed-off-by: Alan Cox Signed-off-by: Douglas Schilling Landgraf --- linux/drivers/media/video/se401.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/se401.c b/linux/drivers/media/video/se401.c index cca1cb0c4..9ba500f8d 100644 --- a/linux/drivers/media/video/se401.c +++ b/linux/drivers/media/video/se401.c @@ -1252,17 +1252,18 @@ static int se401_init(struct usb_se401 *se401, int button) int i=0, rc; unsigned char cp[0x40]; char temp[200]; + int slen; /* led on */ se401_sndctrl(1, se401, SE401_REQ_LED_CONTROL, 1, NULL, 0); /* get camera descriptor */ rc=se401_sndctrl(0, se401, SE401_REQ_GET_CAMERA_DESCRIPTOR, 0, cp, sizeof(cp)); - if (cp[1]!=0x41) { + if (cp[1] != 0x41) { err("Wrong descriptor type"); return 1; } - sprintf (temp, "ExtraFeatures: %d", cp[3]); + slen = snprintf(temp, 200, "ExtraFeatures: %d", cp[3]); se401->sizes=cp[4]+cp[5]*256; se401->width=kmalloc(se401->sizes*sizeof(int), GFP_KERNEL); @@ -1277,9 +1278,10 @@ static int se401_init(struct usb_se401 *se401, int button) se401->width[i]=cp[6+i*4+0]+cp[6+i*4+1]*256; se401->height[i]=cp[6+i*4+2]+cp[6+i*4+3]*256; } - sprintf (temp, "%s Sizes:", temp); + slen += snprintf (temp + slen, 200 - slen, " Sizes:"); for (i=0; isizes; i++) { - sprintf(temp, "%s %dx%d", temp, se401->width[i], se401->height[i]); + slen += snprintf(temp + slen, 200 - slen, + " %dx%d", se401->width[i], se401->height[i]); } dev_info(&se401->dev->dev, "%s\n", temp); se401->maxframesize=se401->width[se401->sizes-1]*se401->height[se401->sizes-1]*3; -- cgit v1.2.3 From f554e1de646717a1ccbdb6af28fc936c1f80af46 Mon Sep 17 00:00:00 2001 From: Douglas Schilling Landgraf Date: Thu, 11 Jun 2009 11:19:33 -0300 Subject: v4l: generate KEY_CAMERA instead of BTN_0 key events on input devices From: Lennart Poettering A bunch of V4L drivers generate BTN_0 instead of KEY_CAMERA key presses. X11 is able to handle KEY_CAMERA automatically these days while BTN_0 is not treated at all. Thus it would be of big benefit if the camera drivers would consistently generate KEY_CAMERA. Some drivers (uvc) already do, this patch updates the remaining drivers to do the same. I only possess a limited set of webcams, so this isn't tested with all cameras. The patch is rather trivial and compile tested, so I'd say it's still good enough to get merged. Priority: normal Signed-off-by: Lennart Poettering Signed-off-by: Andrew Morton Signed-off-by: Douglas Schilling Landgraf --- linux/drivers/media/video/pwc/pwc-if.c | 4 ++-- linux/drivers/media/video/usbvideo/konicawc.c | 4 ++-- linux/drivers/media/video/usbvideo/quickcam_messenger.c | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/pwc/pwc-if.c b/linux/drivers/media/video/pwc/pwc-if.c index b3765e280..eaeea5520 100644 --- a/linux/drivers/media/video/pwc/pwc-if.c +++ b/linux/drivers/media/video/pwc/pwc-if.c @@ -605,7 +605,7 @@ static void pwc_snapshot_button(struct pwc_device *pdev, int down) #ifdef CONFIG_USB_PWC_INPUT_EVDEV if (pdev->button_dev) { - input_report_key(pdev->button_dev, BTN_0, down); + input_report_key(pdev->button_dev, KEY_CAMERA, down); input_sync(pdev->button_dev); } #endif @@ -1859,7 +1859,7 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id pdev->button_dev->cdev.dev = &pdev->udev->dev; #endif pdev->button_dev->evbit[0] = BIT_MASK(EV_KEY); - pdev->button_dev->keybit[BIT_WORD(BTN_0)] = BIT_MASK(BTN_0); + pdev->button_dev->keybit[BIT_WORD(KEY_CAMERA)] = BIT_MASK(KEY_CAMERA); rc = input_register_device(pdev->button_dev); if (rc) { diff --git a/linux/drivers/media/video/usbvideo/konicawc.c b/linux/drivers/media/video/usbvideo/konicawc.c index 75485168e..07bc85761 100644 --- a/linux/drivers/media/video/usbvideo/konicawc.c +++ b/linux/drivers/media/video/usbvideo/konicawc.c @@ -249,7 +249,7 @@ static void konicawc_register_input(struct konicawc *cam, struct usb_device *dev #endif input_dev->evbit[0] = BIT_MASK(EV_KEY); - input_dev->keybit[BIT_WORD(BTN_0)] = BIT_MASK(BTN_0); + input_dev->keybit[BIT_WORD(KEY_CAMERA)] = BIT_MASK(KEY_CAMERA); error = input_register_device(cam->input); if (error) { @@ -272,7 +272,7 @@ static void konicawc_unregister_input(struct konicawc *cam) static void konicawc_report_buttonstat(struct konicawc *cam) { if (cam->input) { - input_report_key(cam->input, BTN_0, cam->buttonsts); + input_report_key(cam->input, KEY_CAMERA, cam->buttonsts); input_sync(cam->input); } } diff --git a/linux/drivers/media/video/usbvideo/quickcam_messenger.c b/linux/drivers/media/video/usbvideo/quickcam_messenger.c index f129bea11..ab30ef54a 100644 --- a/linux/drivers/media/video/usbvideo/quickcam_messenger.c +++ b/linux/drivers/media/video/usbvideo/quickcam_messenger.c @@ -112,7 +112,7 @@ static void qcm_register_input(struct qcm *cam, struct usb_device *dev) #endif input_dev->evbit[0] = BIT_MASK(EV_KEY); - input_dev->keybit[BIT_WORD(BTN_0)] = BIT_MASK(BTN_0); + input_dev->keybit[BIT_WORD(KEY_CAMERA)] = BIT_MASK(KEY_CAMERA); error = input_register_device(cam->input); if (error) { @@ -135,7 +135,7 @@ static void qcm_unregister_input(struct qcm *cam) static void qcm_report_buttonstat(struct qcm *cam) { if (cam->input) { - input_report_key(cam->input, BTN_0, cam->button_sts); + input_report_key(cam->input, KEY_CAMERA, cam->button_sts); input_sync(cam->input); } } -- cgit v1.2.3 From 95a8589d453617556e56dfc53de6f18da19863a5 Mon Sep 17 00:00:00 2001 From: Douglas Schilling Landgraf Date: Thu, 11 Jun 2009 11:28:17 -0300 Subject: tvp514x: try_count off by one From: Roel Kluin With `while (try_count-- > 0)' try_count reaches -1 after the loop. Priority: normal Signed-off-by: Roel Kluin Signed-off-by: Andrew Morton Signed-off-by: Douglas Schilling Landgraf --- linux/drivers/media/video/tvp514x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/tvp514x.c b/linux/drivers/media/video/tvp514x.c index 4262e60b8..3750f7fad 100644 --- a/linux/drivers/media/video/tvp514x.c +++ b/linux/drivers/media/video/tvp514x.c @@ -692,7 +692,7 @@ static int ioctl_s_routing(struct v4l2_int_device *s, break; /* Input detected */ } - if ((current_std == STD_INVALID) || (try_count <= 0)) + if ((current_std == STD_INVALID) || (try_count < 0)) return -EINVAL; decoder->current_std = current_std; -- cgit v1.2.3 From c008f5393a7e3abe497be5721a1f16365053c6a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20Andr=C3=A9n?= Date: Thu, 11 Jun 2009 22:20:23 +0200 Subject: gspca - m5602-ov9650: Reorder quirk list and add A7V quirk MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: Erik Andrén The quirk list has grown and was in need of sorting. This is now done. Add a new vflip quirk for the ASUS A7V while we're at it. Thanks to Carsten Menzel for reporting. Priority: normal Signed-off-by: Erik Andrén --- .../drivers/media/video/gspca/m5602/m5602_ov9650.c | 34 +++++++++++----------- 1 file changed, 17 insertions(+), 17 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c index bd32fe827..a1245cca1 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c @@ -47,60 +47,60 @@ static #endif struct dmi_system_id ov9650_flip_dmi_table[] = { { - .ident = "ASUS A6VA", + .ident = "ASUS A6Ja", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."), - DMI_MATCH(DMI_PRODUCT_NAME, "A6VA") + DMI_MATCH(DMI_PRODUCT_NAME, "A6J") } }, { - - .ident = "ASUS A6VC", + .ident = "ASUS A6JC", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."), - DMI_MATCH(DMI_PRODUCT_NAME, "A6VC") + DMI_MATCH(DMI_PRODUCT_NAME, "A6JC") } }, { - .ident = "ASUS A6VM", + .ident = "ASUS A6K", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."), - DMI_MATCH(DMI_PRODUCT_NAME, "A6VM") + DMI_MATCH(DMI_PRODUCT_NAME, "A6K") } }, { - .ident = "ASUS A6JC", + .ident = "ASUS A6Kt", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."), - DMI_MATCH(DMI_PRODUCT_NAME, "A6JC") + DMI_MATCH(DMI_PRODUCT_NAME, "A6Kt") } }, { - .ident = "ASUS A6Ja", + .ident = "ASUS A6VA", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."), - DMI_MATCH(DMI_PRODUCT_NAME, "A6J") + DMI_MATCH(DMI_PRODUCT_NAME, "A6VA") } }, { - .ident = "ASUS A6Kt", + + .ident = "ASUS A6VC", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."), - DMI_MATCH(DMI_PRODUCT_NAME, "A6Kt") + DMI_MATCH(DMI_PRODUCT_NAME, "A6VC") } }, { - .ident = "ASUS A6K", + .ident = "ASUS A6VM", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."), - DMI_MATCH(DMI_PRODUCT_NAME, "A6K") + DMI_MATCH(DMI_PRODUCT_NAME, "A6VM") } }, { - .ident = "ASUS A6VA", + .ident = "ASUS A7V", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."), - DMI_MATCH(DMI_PRODUCT_NAME, "A6VA") + DMI_MATCH(DMI_PRODUCT_NAME, "A7V") } }, { -- cgit v1.2.3 From 99af65d5e0e8d81cebde342515a18d7bd641fc05 Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Thu, 11 Jun 2009 15:21:34 -0700 Subject: dvb-pll: Add Samsung TDTC9251DH0 DVB-T NIM From: Trent Piepho No datasheet, tuner data comes from code in flexcop driver. This tuner is also used on the AVerTV 771 supported by the bttv driver, but that code uses a different tuner configuration, which is surprising. Priority: normal Signed-off-by: Trent Piepho --- linux/drivers/media/dvb/frontends/dvb-pll.c | 15 +++++++++++++++ linux/drivers/media/dvb/frontends/dvb-pll.h | 1 + 2 files changed, 16 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/frontends/dvb-pll.c b/linux/drivers/media/dvb/frontends/dvb-pll.c index 8ef5d1eff..6c6506757 100644 --- a/linux/drivers/media/dvb/frontends/dvb-pll.c +++ b/linux/drivers/media/dvb/frontends/dvb-pll.c @@ -390,6 +390,20 @@ static struct dvb_pll_desc dvb_pll_samsung_dtos403ih102a = { } }; +/* Samsung TDTC9251DH0 DVB-T NIM, as used on AirStar 2 */ +static struct dvb_pll_desc dvb_pll_samsung_tdtc9251dh0 = { + .name = "Samsung TDTC9251DH0", + .min = 48000000, + .max = 863000000, + .iffreq = 36166667, + .count = 3, + .entries = { + { 157500000, 166667, 0xcc, 0x09 }, + { 443000000, 166667, 0xcc, 0x0a }, + { 863000000, 166667, 0xcc, 0x08 }, + } +}; + /* ----------------------------------------------------------- */ static struct dvb_pll_desc *pll_list[] = { @@ -408,6 +422,7 @@ static struct dvb_pll_desc *pll_list[] = { [DVB_PLL_PHILIPS_SD1878_TDA8261] = &dvb_pll_philips_sd1878_tda8261, [DVB_PLL_OPERA1] = &dvb_pll_opera1, [DVB_PLL_SAMSUNG_DTOS403IH102A] = &dvb_pll_samsung_dtos403ih102a, + [DVB_PLL_SAMSUNG_TDTC9251DH0] = &dvb_pll_samsung_tdtc9251dh0, }; /* ----------------------------------------------------------- */ diff --git a/linux/drivers/media/dvb/frontends/dvb-pll.h b/linux/drivers/media/dvb/frontends/dvb-pll.h index 05239f579..dcbb28333 100644 --- a/linux/drivers/media/dvb/frontends/dvb-pll.h +++ b/linux/drivers/media/dvb/frontends/dvb-pll.h @@ -23,6 +23,7 @@ #define DVB_PLL_PHILIPS_SD1878_TDA8261 12 #define DVB_PLL_OPERA1 13 #define DVB_PLL_SAMSUNG_DTOS403IH102A 14 +#define DVB_PLL_SAMSUNG_TDTC9251DH0 15 /** * Attach a dvb-pll to the supplied frontend structure. -- cgit v1.2.3 From 74c4537b6d3fadad69ae9955994e26ce67bdb454 Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Thu, 11 Jun 2009 15:21:34 -0700 Subject: dvb-pll: Add support for Samsung TBDU18132 DVB-S NIM From: Trent Piepho Tuner parameters taken from flexcop driver. This PLL has a 17 bit divisor while the dvb-pll driver is designed for 15 bit divisors. It's not a problem as 15 bits is enough for the tuner's entire range. But if a larger range was wanted, it could be done by adding additional bands with the extra divisor bits appearing as band switch bits. Priority: normal Signed-off-by: Trent Piepho --- linux/drivers/media/dvb/frontends/dvb-pll.c | 22 ++++++++++++++++++++++ linux/drivers/media/dvb/frontends/dvb-pll.h | 1 + 2 files changed, 23 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/frontends/dvb-pll.c b/linux/drivers/media/dvb/frontends/dvb-pll.c index 6c6506757..7abd33389 100644 --- a/linux/drivers/media/dvb/frontends/dvb-pll.c +++ b/linux/drivers/media/dvb/frontends/dvb-pll.c @@ -404,6 +404,27 @@ static struct dvb_pll_desc dvb_pll_samsung_tdtc9251dh0 = { } }; +/* Samsung TBDU18132 DVB-S NIM with TSA5059 PLL, used in SkyStar2 DVB-S 2.3 */ +static struct dvb_pll_desc dvb_pll_samsung_tbdu18132 = { + .name = "Samsung TBDU18132", + .min = 950000, + .max = 2150000, /* guesses */ + .iffreq = 0, + .count = 2, + .entries = { + { 1550000, 125, 0x84, 0x82 }, + { 4095937, 125, 0x84, 0x80 }, + } + /* TSA5059 PLL has a 17 bit divisor rather than the 15 bits supported + * by this driver. The two extra bits are 0x60 in the third byte. 15 + * bits is enough for over 4 GHz, which is enough to cover the range + * of this tuner. We could use the additional divisor bits by adding + * more entries, e.g. + { 0x0ffff * 125 + 125/2, 125, 0x84 | 0x20, }, + { 0x17fff * 125 + 125/2, 125, 0x84 | 0x40, }, + { 0x1ffff * 125 + 125/2, 125, 0x84 | 0x60, }, */ +}; + /* ----------------------------------------------------------- */ static struct dvb_pll_desc *pll_list[] = { @@ -423,6 +444,7 @@ static struct dvb_pll_desc *pll_list[] = { [DVB_PLL_OPERA1] = &dvb_pll_opera1, [DVB_PLL_SAMSUNG_DTOS403IH102A] = &dvb_pll_samsung_dtos403ih102a, [DVB_PLL_SAMSUNG_TDTC9251DH0] = &dvb_pll_samsung_tdtc9251dh0, + [DVB_PLL_SAMSUNG_TBDU18132] = &dvb_pll_samsung_tbdu18132, }; /* ----------------------------------------------------------- */ diff --git a/linux/drivers/media/dvb/frontends/dvb-pll.h b/linux/drivers/media/dvb/frontends/dvb-pll.h index dcbb28333..7905f3440 100644 --- a/linux/drivers/media/dvb/frontends/dvb-pll.h +++ b/linux/drivers/media/dvb/frontends/dvb-pll.h @@ -24,6 +24,7 @@ #define DVB_PLL_OPERA1 13 #define DVB_PLL_SAMSUNG_DTOS403IH102A 14 #define DVB_PLL_SAMSUNG_TDTC9251DH0 15 +#define DVB_PLL_SAMSUNG_TBDU18132 16 /** * Attach a dvb-pll to the supplied frontend structure. -- cgit v1.2.3 From 70cded874faac45e4b8c55850cfaccc4112ffc10 Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Thu, 11 Jun 2009 15:21:34 -0700 Subject: dvb-pll: Add support for Samsung TBMU24112 DVB-S NIM From: Trent Piepho Tuner parameters determined from code in flexcop driver. That code rounded the divisor down instead of to the nearest value. This was probably not intentional and the dvb-pll version will round to nearest. Priority: normal Signed-off-by: Trent Piepho --- linux/drivers/media/dvb/frontends/dvb-pll.c | 14 ++++++++++++++ linux/drivers/media/dvb/frontends/dvb-pll.h | 1 + 2 files changed, 15 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/frontends/dvb-pll.c b/linux/drivers/media/dvb/frontends/dvb-pll.c index 7abd33389..5dd999b8b 100644 --- a/linux/drivers/media/dvb/frontends/dvb-pll.c +++ b/linux/drivers/media/dvb/frontends/dvb-pll.c @@ -425,6 +425,19 @@ static struct dvb_pll_desc dvb_pll_samsung_tbdu18132 = { { 0x1ffff * 125 + 125/2, 125, 0x84 | 0x60, }, */ }; +/* Samsung TBMU24112 DVB-S NIM with SL1935 zero-IF tuner */ +static struct dvb_pll_desc dvb_pll_samsung_tbmu24112 = { + .name = "Samsung TBMU24112", + .min = 950000, + .max = 2150000, /* guesses */ + .iffreq = 0, + .count = 2, + .entries = { + { 1500000, 125, 0x84, 0x18 }, + { 9999999, 125, 0x84, 0x08 }, + } +}; + /* ----------------------------------------------------------- */ static struct dvb_pll_desc *pll_list[] = { @@ -445,6 +458,7 @@ static struct dvb_pll_desc *pll_list[] = { [DVB_PLL_SAMSUNG_DTOS403IH102A] = &dvb_pll_samsung_dtos403ih102a, [DVB_PLL_SAMSUNG_TDTC9251DH0] = &dvb_pll_samsung_tdtc9251dh0, [DVB_PLL_SAMSUNG_TBDU18132] = &dvb_pll_samsung_tbdu18132, + [DVB_PLL_SAMSUNG_TBMU24112] = &dvb_pll_samsung_tbmu24112, }; /* ----------------------------------------------------------- */ diff --git a/linux/drivers/media/dvb/frontends/dvb-pll.h b/linux/drivers/media/dvb/frontends/dvb-pll.h index 7905f3440..c1035812c 100644 --- a/linux/drivers/media/dvb/frontends/dvb-pll.h +++ b/linux/drivers/media/dvb/frontends/dvb-pll.h @@ -25,6 +25,7 @@ #define DVB_PLL_SAMSUNG_DTOS403IH102A 14 #define DVB_PLL_SAMSUNG_TDTC9251DH0 15 #define DVB_PLL_SAMSUNG_TBDU18132 16 +#define DVB_PLL_SAMSUNG_TBMU24112 17 /** * Attach a dvb-pll to the supplied frontend structure. -- cgit v1.2.3 From ed6182953e804ff70ba2fc087dfe131498f00278 Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Thu, 11 Jun 2009 15:24:00 -0700 Subject: dvb-pll: Add support for Alps TDEE4 DVB-C NIM From: Trent Piepho No datasheet, data take from code in flexcop driver. That code rounded down the divisor rather than rounding to nearest, which was probably not intentional and the dvb-pll code will round to nearest. Priority: normal Signed-off-by: Trent Piepho --- linux/drivers/media/dvb/frontends/dvb-pll.c | 24 ++++++++++++++++++++++++ linux/drivers/media/dvb/frontends/dvb-pll.h | 1 + 2 files changed, 25 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/frontends/dvb-pll.c b/linux/drivers/media/dvb/frontends/dvb-pll.c index 5dd999b8b..d8a7947e0 100644 --- a/linux/drivers/media/dvb/frontends/dvb-pll.c +++ b/linux/drivers/media/dvb/frontends/dvb-pll.c @@ -438,6 +438,29 @@ static struct dvb_pll_desc dvb_pll_samsung_tbmu24112 = { } }; +/* Alps TDEE4 DVB-C NIM, used on Cablestar 2 */ +/* byte 4 : 1 * * AGD R3 R2 R1 R0 + * byte 5 : C1 * RE RTS BS4 BS3 BS2 BS1 + * AGD = 1, R3 R2 R1 R0 = 0 1 0 1 => byte 4 = 1**10101 = 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 */ +static struct dvb_pll_desc dvb_pll_alps_tdee4 = { + .name = "ALPS TDEE4", + .min = 47000000, + .max = 862000000, + .iffreq = 36125000, + .count = 4, + .entries = { + { 153000000, 62500, 0x95, 0x01 }, + { 430000000, 62500, 0x95, 0x02 }, + { 822000000, 62500, 0x95, 0x08 }, + { 999999999, 62500, 0x95, 0x88 }, + } +}; + /* ----------------------------------------------------------- */ static struct dvb_pll_desc *pll_list[] = { @@ -451,6 +474,7 @@ static struct dvb_pll_desc *pll_list[] = { [DVB_PLL_TUA6034] = &dvb_pll_tua6034, [DVB_PLL_TDA665X] = &dvb_pll_tda665x, [DVB_PLL_TDED4] = &dvb_pll_tded4, + [DVB_PLL_TDEE4] = &dvb_pll_alps_tdee4, [DVB_PLL_TDHU2] = &dvb_pll_tdhu2, [DVB_PLL_SAMSUNG_TBMV] = &dvb_pll_samsung_tbmv, [DVB_PLL_PHILIPS_SD1878_TDA8261] = &dvb_pll_philips_sd1878_tda8261, diff --git a/linux/drivers/media/dvb/frontends/dvb-pll.h b/linux/drivers/media/dvb/frontends/dvb-pll.h index c1035812c..086964344 100644 --- a/linux/drivers/media/dvb/frontends/dvb-pll.h +++ b/linux/drivers/media/dvb/frontends/dvb-pll.h @@ -26,6 +26,7 @@ #define DVB_PLL_SAMSUNG_TDTC9251DH0 15 #define DVB_PLL_SAMSUNG_TBDU18132 16 #define DVB_PLL_SAMSUNG_TBMU24112 17 +#define DVB_PLL_TDEE4 18 /** * Attach a dvb-pll to the supplied frontend structure. -- cgit v1.2.3 From 8b87b848ca8a5e6465888220e57ec3e59104d677 Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Thu, 11 Jun 2009 15:31:22 -0700 Subject: b2c2: fix frontends compiled into kernel From: Trent Piepho A recent patch didn't take into account that frontends can be compiled into the kernel. Or that frontends compiled as modules can't be used by the b2c2 driver if it is not a module itself. Some frontends require multiple drivers, e.g. a demod driver and a tuner driver. The code for the frontend support was getting added if the demod driver was available. Change this to also require any needed tuner or SEC drivers as well. Priority: normal Signed-off-by: Trent Piepho --- linux/drivers/media/dvb/b2c2/flexcop-fe-tuner.c | 67 ++++++++++++++----------- 1 file changed, 37 insertions(+), 30 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/b2c2/flexcop-fe-tuner.c b/linux/drivers/media/dvb/b2c2/flexcop-fe-tuner.c index efb4a6c2b..9a6307a34 100644 --- a/linux/drivers/media/dvb/b2c2/flexcop-fe-tuner.c +++ b/linux/drivers/media/dvb/b2c2/flexcop-fe-tuner.c @@ -20,8 +20,14 @@ #include "tuner-simple.h" #include "stv0297.h" + +/* Can we use the specified front-end? Remember that if we are compiled + * into the kernel we can't call code that's in modules. */ +#define FE_SUPPORTED(fe) (defined(CONFIG_DVB_##fe) || \ + (defined(CONFIG_DVB_##fe##_MODULE) && defined(MODULE))) + /* lnb control */ -#if defined(CONFIG_DVB_MT312_MODULE) || defined(CONFIG_DVB_STV0299_MODULE) +#if FE_SUPPORTED(MT312) || FE_SUPPORTED(STV0299) static int flexcop_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) { struct flexcop_device *fc = fe->dvb->priv; @@ -49,8 +55,7 @@ static int flexcop_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage } #endif -#if defined(CONFIG_DVB_S5H1420_MODULE) || defined(CONFIG_DVB_STV0299_MODULE) \ - || defined(CONFIG_DVB_MT312_MODULE) +#if FE_SUPPORTED(S5H1420) || FE_SUPPORTED(STV0299) || FE_SUPPORTED(MT312) static int flexcop_sleep(struct dvb_frontend* fe) { struct flexcop_device *fc = fe->dvb->priv; @@ -61,7 +66,7 @@ static int flexcop_sleep(struct dvb_frontend* fe) #endif /* SkyStar2 DVB-S rev 2.3 */ -#if defined(CONFIG_DVB_MT312_MODULE) +#if FE_SUPPORTED(MT312) 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 }; */ @@ -193,10 +198,12 @@ static int skystar2_rev23_attach(struct flexcop_device *fc, } return 0; } +#else +#define skystar2_rev23_attach NULL #endif /* SkyStar2 DVB-S rev 2.6 */ -#if defined(CONFIG_DVB_STV0299_MODULE) +#if FE_SUPPORTED(STV0299) static int samsung_tbmu24112_set_symbol_rate(struct dvb_frontend *fe, u32 srate, u32 ratio) { @@ -321,10 +328,12 @@ static int skystar2_rev26_attach(struct flexcop_device *fc, } return 0; } +#else +#define skystar2_rev26_attach NULL #endif /* SkyStar2 DVB-S rev 2.7 */ -#if defined(CONFIG_DVB_S5H1420_MODULE) +#if FE_SUPPORTED(S5H1420) && FE_SUPPORTED(ISL6421) && FE_SUPPORTED(TUNER_ITD1000) static struct s5h1420_config skystar2_rev2_7_s5h1420_config = { .demod_address = 0x53, .invert = 1, @@ -385,10 +394,12 @@ fail: fc->fc_i2c_adap[0].no_base_addr = 0; return 0; } +#else +#define skystar2_rev27_attach NULL #endif /* SkyStar2 rev 2.8 */ -#if defined(CONFIG_DVB_CX24123_MODULE) +#if FE_SUPPORTED(CX24123) && FE_SUPPORTED(ISL6421) && FE_SUPPORTED(TUNER_CX24113) static struct cx24123_config skystar2_rev2_8_cx24123_config = { .demod_address = 0x55, .dont_use_pll = 1, @@ -433,10 +444,12 @@ static int skystar2_rev28_attach(struct flexcop_device *fc, * IR-receiver (PIC16F818) - but the card has no input for that ??? */ return 1; } +#else +#define skystar2_rev28_attach NULL #endif /* AirStar DVB-T */ -#if defined(CONFIG_DVB_MT352_MODULE) +#if FE_SUPPORTED(MT352) static int samsung_tdtc9251dh0_demod_init(struct dvb_frontend *fe) { static u8 mt352_clock_config[] = { 0x89, 0x18, 0x2d }; @@ -495,10 +508,12 @@ static int airstar_dvbt_attach(struct flexcop_device *fc, } return 0; } +#else +#define airstar_dvbt_attach NULL #endif /* AirStar ATSC 1st generation */ -#if defined(CONFIG_DVB_BCM3510_MODULE) +#if FE_SUPPORTED(BCM3510) static int flexcop_fe_request_firmware(struct dvb_frontend *fe, const struct firmware **fw, char* name) { @@ -517,10 +532,12 @@ static int airstar_atsc1_attach(struct flexcop_device *fc, fc->fe = dvb_attach(bcm3510_attach, &air2pc_atsc_first_gen_config, i2c); return fc->fe != NULL; } +#else +#define airstar_atsc1_attach NULL #endif /* AirStar ATSC 2nd generation */ -#if defined(CONFIG_DVB_NXT200X_MODULE) +#if FE_SUPPORTED(NXT200X) && FE_SUPPORTED(PLL) static struct nxt200x_config samsung_tbmv_config = { .demod_address = 0x0a, }; @@ -535,10 +552,12 @@ static int airstar_atsc2_attach(struct flexcop_device *fc, return !!dvb_attach(dvb_pll_attach, fc->fe, 0x61, NULL, DVB_PLL_SAMSUNG_TBMV); } +#else +#define airstar_atsc2_attach NULL #endif /* AirStar ATSC 3rd generation */ -#if defined(CONFIG_DVB_LGDT330X_MODULE) +#if FE_SUPPORTED(LGDT330X) static struct lgdt330x_config air2pc_atsc_hd5000_config = { .demod_address = 0x59, .demod_chip = LGDT3303, @@ -556,10 +575,12 @@ static int airstar_atsc3_attach(struct flexcop_device *fc, return !!dvb_attach(simple_tuner_attach, fc->fe, i2c, 0x61, TUNER_LG_TDVS_H06XF); } +#else +#define airstar_atsc3_attach NULL #endif /* CableStar2 DVB-C */ -#if defined(CONFIG_DVB_STV0297_MODULE) +#if FE_SUPPORTED(STV0297) static int alps_tdee4_stv0297_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *fep) { @@ -698,39 +719,23 @@ static int cablestar2_attach(struct flexcop_device *fc, fc->fe->ops.tuner_ops.set_params = alps_tdee4_stv0297_tuner_set_params; return 1; } +#else +#define cablestar2_attach NULL #endif static struct { flexcop_device_type_t type; int (*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 }; /* try to figure out the frontend */ @@ -738,6 +743,8 @@ int flexcop_frontend_init(struct flexcop_device *fc) { int i; for (i = 0; i < ARRAY_SIZE(flexcop_frontends); i++) { + if (!flexcop_frontends[i].attach) + continue; /* type needs to be set before, because of some workarounds * done based on the probed card type */ fc->dev_type = flexcop_frontends[i].type; -- cgit v1.2.3 From 8ec3691caa62885c1f9f47b05f580ac47b5db528 Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Thu, 11 Jun 2009 15:31:22 -0700 Subject: b2c2: Use dvb-pll for AirStar DVB-T's tuner From: Trent Piepho The code in samsung_tdtc9251dh0_calc_regs() is equivalent to what dvb-pll's code does. Priority: normal Signed-off-by: Trent Piepho --- linux/drivers/media/dvb/b2c2/flexcop-fe-tuner.c | 38 ++++--------------------- 1 file changed, 6 insertions(+), 32 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/b2c2/flexcop-fe-tuner.c b/linux/drivers/media/dvb/b2c2/flexcop-fe-tuner.c index 9a6307a34..0669a14da 100644 --- a/linux/drivers/media/dvb/b2c2/flexcop-fe-tuner.c +++ b/linux/drivers/media/dvb/b2c2/flexcop-fe-tuner.c @@ -449,7 +449,7 @@ static int skystar2_rev28_attach(struct flexcop_device *fc, #endif /* AirStar DVB-T */ -#if FE_SUPPORTED(MT352) +#if FE_SUPPORTED(MT352) && FE_SUPPORTED(PLL) static int samsung_tdtc9251dh0_demod_init(struct dvb_frontend *fe) { static u8 mt352_clock_config[] = { 0x89, 0x18, 0x2d }; @@ -467,32 +467,6 @@ static int samsung_tdtc9251dh0_demod_init(struct dvb_frontend *fe) return 0; } -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; - - if (buf_len < 5) - return -EINVAL; - -#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; - - pllbuf[0] = 0x61; - pllbuf[1] = div >> 8; - pllbuf[2] = div & 0xff; - pllbuf[3] = 0xcc; - pllbuf[4] = bs; - return 5; -} - static struct mt352_config samsung_tdtc9251dh0_config = { .demod_address = 0x0f, .demod_init = samsung_tdtc9251dh0_demod_init, @@ -502,11 +476,11 @@ static int 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; - return 1; - } - return 0; + if (!fc->fe) + return 0; + + return !!dvb_attach(dvb_pll_attach, fc->fe, 0x61, NULL, + DVB_PLL_SAMSUNG_TDTC9251DH0); } #else #define airstar_dvbt_attach NULL -- cgit v1.2.3 From a33131bc8be60a05f9abfa4bc0ce81b30a2af7e8 Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Thu, 11 Jun 2009 15:31:22 -0700 Subject: b2c2: Use dvb-pll for Skystar2 rev 2.3 and rev 2.6 From: Trent Piepho The code in skystar23_samsung_tbdu18132_tuner_set_params() and samsung_tbmu24112_tuner_set_params() is equivalent to what the dvb-pll code does. There could be an issue because the dvb-pll code will probe to check for the tuner, while the previous code didn't do any checks. Priority: normal Signed-off-by: Trent Piepho --- linux/drivers/media/dvb/b2c2/flexcop-fe-tuner.c | 105 +++++++----------------- 1 file changed, 31 insertions(+), 74 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/b2c2/flexcop-fe-tuner.c b/linux/drivers/media/dvb/b2c2/flexcop-fe-tuner.c index 0669a14da..928bc4d4d 100644 --- a/linux/drivers/media/dvb/b2c2/flexcop-fe-tuner.c +++ b/linux/drivers/media/dvb/b2c2/flexcop-fe-tuner.c @@ -66,7 +66,7 @@ static int flexcop_sleep(struct dvb_frontend* fe) #endif /* SkyStar2 DVB-S rev 2.3 */ -#if FE_SUPPORTED(MT312) +#if FE_SUPPORTED(MT312) && FE_SUPPORTED(PLL) 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 }; */ @@ -155,55 +155,34 @@ 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 int skystar2_rev23_attach(struct flexcop_device *fc, struct i2c_adapter *i2c) { + struct dvb_frontend_ops *ops; + 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; - return 1; - } - return 0; + if (!fc->fe) + return 0; + + if (!dvb_attach(dvb_pll_attach, fc->fe, 0x61, i2c, + DVB_PLL_SAMSUNG_TBDU18132)) + return 0; + + ops = &fc->fe->ops; + 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; + return 1; } #else #define skystar2_rev23_attach NULL #endif /* SkyStar2 DVB-S rev 2.6 */ -#if FE_SUPPORTED(STV0299) +#if FE_SUPPORTED(STV0299) && FE_SUPPORTED(PLL) static int samsung_tbmu24112_set_symbol_rate(struct dvb_frontend *fe, u32 srate, u32 ratio) { @@ -232,31 +211,6 @@ static int samsung_tbmu24112_set_symbol_rate(struct dvb_frontend *fe, return 0; } -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 flexcop_device *fc = fe->dvb->priv; - div = params->frequency / 125; - - buf[0] = (div >> 8) & 0x7f; - buf[1] = div & 0xff; - buf[2] = 0x84; /* 0xC4 */ - buf[3] = 0x08; - - if (params->frequency < 1500000) - buf[3] |= 0x10; - - 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 u8 samsung_tbmu24112_inittab[] = { 0x01, 0x15, 0x02, 0x30, @@ -318,15 +272,18 @@ static int skystar2_rev26_attach(struct flexcop_device *fc, struct i2c_adapter *i2c) { 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; - return 1; - } - return 0; + if (!fc->fe) + return 0; + + if (!dvb_attach(dvb_pll_attach, fc->fe, 0x61, i2c, + DVB_PLL_SAMSUNG_TBMU24112)) + return 0; + + fc->fe->ops.set_voltage = flexcop_set_voltage; + fc->fe_sleep = fc->fe->ops.sleep; + fc->fe->ops.sleep = flexcop_sleep; + return 1; + } #else #define skystar2_rev26_attach NULL -- cgit v1.2.3 From d6ff0d4097028addee38d92dff142e1e28259275 Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Thu, 11 Jun 2009 15:31:22 -0700 Subject: b2c2: Use dvb-pll for Cablestar2 From: Trent Piepho The dvb-pll code should do the same thing that alps_tdee4_stv0297_tuner_set_params() was doing. Except the dvb-pll code will check for tuner presence when attaching, while the old code didn't. This tuner appears to not be behind the stv0297's I2C gate but is instead on a different I2C adapter provided by the flexcop chip. The old code would turn the I2C gate off each time the tuner was used. I've changed it to turn the gate off when the tuner is attached and then disable the gate control function. This should result in the gate staying off, which should be even better. Priority: normal Signed-off-by: Trent Piepho --- linux/drivers/media/dvb/b2c2/flexcop-fe-tuner.c | 73 +++++++------------------ 1 file changed, 19 insertions(+), 54 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/b2c2/flexcop-fe-tuner.c b/linux/drivers/media/dvb/b2c2/flexcop-fe-tuner.c index 928bc4d4d..f56ffc0e2 100644 --- a/linux/drivers/media/dvb/b2c2/flexcop-fe-tuner.c +++ b/linux/drivers/media/dvb/b2c2/flexcop-fe-tuner.c @@ -511,54 +511,7 @@ static int airstar_atsc3_attach(struct flexcop_device *fc, #endif /* CableStar2 DVB-C */ -#if FE_SUPPORTED(STV0297) -static int alps_tdee4_stv0297_tuner_set_params(struct dvb_frontend* fe, - struct dvb_frontend_parameters *fep) -{ - struct flexcop_device *fc = fe->dvb->priv; - u8 buf[4]; - u16 div; - int ret; - -/* 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 */ - - buf[0] = (u8)( div >> 8) & 0x7f; - buf[1] = (u8) div & 0xff; - -/* F(osc) = N * Reference Freq. (62.5 kHz) - * byte 2 : 0 N14 N13 N12 N11 N10 N9 N8 - * byte 3 : N7 N6 N5 N4 N3 N2 N1 N0 - * byte 4 : 1 * * AGD R3 R2 R1 R0 - * byte 5 : C1 * RE RTS BS4 BS3 BS2 BS1 - * 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 */ - - if (fep->frequency <= 153000000) buf[3] = 0x01; - else if (fep->frequency <= 430000000) buf[3] = 0x02; - else if (fep->frequency <= 822000000) buf[3] = 0x08; - else buf[3] = 0x88; - - 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]); - ret = fc->i2c_request(&fc->fc_i2c_adap[2], - FC_WRITE, 0x61, buf[0], &buf[1], 3); - deb_tuner("tuner write returned: %d\n",ret); - return ret; -} - +#if FE_SUPPORTED(STV0297) && FE_SUPPORTED(PLL) static u8 alps_tdee4_stv0297_inittab[] = { 0x80, 0x01, 0x80, 0x00, @@ -642,13 +595,25 @@ static int cablestar2_attach(struct flexcop_device *fc, { fc->fc_i2c_adap[0].no_base_addr = 1; fc->fe = dvb_attach(stv0297_attach, &alps_tdee4_stv0297_config, i2c); - if (!fc->fe) { - /* Reset for next frontend to try */ - fc->fc_i2c_adap[0].no_base_addr = 0; - return 0; - } - fc->fe->ops.tuner_ops.set_params = alps_tdee4_stv0297_tuner_set_params; + if (!fc->fe) + goto fail; + + /* This tuner doesn't use the stv0297's I2C gate, but instead the + * tuner is connected to a different flexcop I2C adapter. */ + if (fc->fe->ops.i2c_gate_ctrl) + fc->fe->ops.i2c_gate_ctrl(fc->fe, 0); + fc->fe->ops.i2c_gate_ctrl = NULL; + + if (!dvb_attach(dvb_pll_attach, fc->fe, 0x61, + fc->fc_i2c_adap[2].i2c_adap, DVB_PLL_TDEE4)) + goto fail; + return 1; + +fail: + /* Reset for next frontend to try */ + fc->fc_i2c_adap[0].no_base_addr = 0; + return 0; } #else #define cablestar2_attach NULL -- cgit v1.2.3 From 0766523982a9f6ba627e38a286af9b523f82cdeb Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Fri, 12 Jun 2009 08:49:39 +0200 Subject: gspca - spca508: Extend the write_vector routine. From: Jean-Francois Moine Priority: normal Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/spca508.c | 59 ++++++++++++++++++++++++++++--- 1 file changed, 55 insertions(+), 4 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/spca508.c b/linux/drivers/media/video/gspca/spca508.c index 7fd8079c2..10006e257 100644 --- a/linux/drivers/media/video/gspca/spca508.c +++ b/linux/drivers/media/video/gspca/spca508.c @@ -1350,19 +1350,70 @@ static int reg_read(struct gspca_dev *gspca_dev, return gspca_dev->usb_buf[0]; } +/* send 1 or 2 bytes to the sensor via the Synchronous Serial Interface */ +static int ssi_w(struct gspca_dev *gspca_dev, + u16 reg, u16 val) +{ + struct usb_device *dev = gspca_dev->dev; + int ret, retry; + + ret = reg_write(dev, 0x8802, reg >> 8); + if (ret < 0) + goto out; + ret = reg_write(dev, 0x8801, reg & 0x00ff); + if (ret < 0) + goto out; + if ((reg & 0xff00) == 0x1000) { /* if 2 bytes */ + ret = reg_write(dev, 0x8805, val & 0x00ff); + if (ret < 0) + goto out; + val >>= 8; + } + ret = reg_write(dev, 0x8800, val); + if (ret < 0) + goto out; + + /* poll until not busy */ + retry = 10; + for (;;) { + ret = reg_read(gspca_dev, 0x8803); + if (ret < 0) + break; + if (gspca_dev->usb_buf[0] == 0) + break; + if (--retry <= 0) { + PDEBUG(D_ERR, "ssi_w busy %02x", + gspca_dev->usb_buf[0]); + ret = -1; + break; + } + msleep(8); + } + +out: + return ret; +} + static int write_vector(struct gspca_dev *gspca_dev, const u16 (*data)[2]) { struct usb_device *dev = gspca_dev->dev; - int ret; + int ret = 0; while ((*data)[1] != 0) { - ret = reg_write(dev, (*data)[1], (*data)[0]); + if ((*data)[1] & 0x8000) { + if ((*data)[1] == 0xdd00) /* delay */ + msleep((*data)[0]); + else + ret = reg_write(dev, (*data)[1], (*data)[0]); + } else { + ret = ssi_w(gspca_dev, (*data)[1], (*data)[0]); + } if (ret < 0) - return ret; + break; data++; } - return 0; + return ret; } /* this function is called at probe time */ -- cgit v1.2.3 From 609bc704ffcafedc2596bd393b0aab789fa7f9f6 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 12 Jun 2009 16:51:03 +0000 Subject: uvc: Fix for no return value check of uvc_ctrl_set() which calls mutex_lock_interruptible() From: Robert Krakora Fix for no return value check of uvc_ctrl_set() which calls mutex_lock_interruptible(). Priority: normal Signed-off-by: Robert Krakora Acked-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/uvc/uvc_v4l2.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/uvc/uvc_v4l2.c b/linux/drivers/media/video/uvc/uvc_v4l2.c index 736d8ae23..0be85adf3 100644 --- a/linux/drivers/media/video/uvc/uvc_v4l2.c +++ b/linux/drivers/media/video/uvc/uvc_v4l2.c @@ -538,7 +538,10 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) memset(&xctrl, 0, sizeof xctrl); xctrl.id = ctrl->id; - uvc_ctrl_begin(video); + ret = uvc_ctrl_begin(video); + if (ret < 0) + return ret; + ret = uvc_ctrl_get(video, &xctrl); uvc_ctrl_rollback(video); if (ret >= 0) @@ -555,7 +558,10 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) xctrl.id = ctrl->id; xctrl.value = ctrl->value; - uvc_ctrl_begin(video); + ret = uvc_ctrl_begin(video); + if (ret < 0) + return ret; + ret = uvc_ctrl_set(video, &xctrl); if (ret < 0) { uvc_ctrl_rollback(video); @@ -574,7 +580,10 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) struct v4l2_ext_control *ctrl = ctrls->controls; unsigned int i; - uvc_ctrl_begin(video); + ret = uvc_ctrl_begin(video); + if (ret < 0) + return ret; + for (i = 0; i < ctrls->count; ++ctrl, ++i) { ret = uvc_ctrl_get(video, ctrl); if (ret < 0) { -- cgit v1.2.3 From 505dee96b5f86facce4200d260ffec2fb5a737b8 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 12 Jun 2009 19:31:29 +0000 Subject: v4l2: Move bounding code outside I2C ifdef block From: Trent Piepho On Fri, 12 Jun 2009, Randy Dunlap wrote: > From: Randy Dunlap > > Move v4l_bound_align_image() outside of an #ifdef CONFIG_I2C block > so that it is always built. Fixes a build error: clamp_align() should be moved as well, since it's only used by v4l_bound_align_image(). I'm attaching an alternate version that fixes this. Labeled the endif too. Reported-by: Randy Dunlap Priority: normal Signed-off-by: Trent Piepho Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/v4l2-common.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/v4l2-common.c b/linux/drivers/media/video/v4l2-common.c index d81bae197..ba3790a98 100644 --- a/linux/drivers/media/video/v4l2-common.c +++ b/linux/drivers/media/video/v4l2-common.c @@ -997,6 +997,8 @@ const unsigned short *v4l2_i2c_tuner_addrs(enum v4l2_i2c_tuner_type type) } EXPORT_SYMBOL_GPL(v4l2_i2c_tuner_addrs); +#endif /* defined(CONFIG_I2C) */ + /* Clamp x to be between min and max, aligned to a multiple of 2^align. min * and max don't have to be aligned, but there must be at least one valid * value. E.g., min=17,max=31,align=4 is not allowed as there are no multiples @@ -1067,5 +1069,3 @@ void v4l_bound_align_image(u32 *w, unsigned int wmin, unsigned int wmax, } } EXPORT_SYMBOL_GPL(v4l_bound_align_image); - -#endif -- cgit v1.2.3 From 5a703518d6e338eb150ada6b8af5d1f4e0319b1e Mon Sep 17 00:00:00 2001 From: "hans@rhel5-devel.localdomain" Date: Sat, 13 Jun 2009 23:56:22 +0200 Subject: gspca: fix NULL pointer deref in query_ctrl From: Hans de Goede gspca: fix NULL pointer deref in query_ctrl Priority: normal Signed-off-by: Hans de Goede --- linux/drivers/media/video/gspca/gspca.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/gspca.c b/linux/drivers/media/video/gspca/gspca.c index e6ab4bb8c..f06aac676 100644 --- a/linux/drivers/media/video/gspca/gspca.c +++ b/linux/drivers/media/video/gspca/gspca.c @@ -1054,13 +1054,11 @@ static int vidioc_queryctrl(struct file *file, void *priv, for (i = 0; i < gspca_dev->sd_desc->nctrls; i++) { if (gspca_dev->ctrl_dis & (1 << i)) continue; - if (ctrls->qctrl.id < id) + if (gspca_dev->sd_desc->ctrls[i].qctrl.id < id) continue; - if (ctrls != NULL) { - if (gspca_dev->sd_desc->ctrls[i].qctrl.id + if (ctrls && gspca_dev->sd_desc->ctrls[i].qctrl.id > ctrls->qctrl.id) - continue; - } + continue; ctrls = &gspca_dev->sd_desc->ctrls[i]; } } else { -- cgit v1.2.3 From 6fec72e6a1cf47b8911090b29f5026267dad33cc Mon Sep 17 00:00:00 2001 From: "hans@rhel5-devel.localdomain" Date: Sun, 14 Jun 2009 09:32:04 +0200 Subject: gspca-ov519: add extra controls From: Hans de Goede This patch adds autobrightness (so that it can be turned off to make the already present brightness control work) and light frequency filtering controls. The lightfreq control needed 2 different entries in the ctrls array, as the number of options differs depending on the sensor. Always one of the 2 entires is disabled ofcourse. Priority: normal Signed-off-by: Hans de Goede --- linux/drivers/media/video/gspca/ov519.c | 214 ++++++++++++++++++++++++++++++-- 1 file changed, 205 insertions(+), 9 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/ov519.c b/linux/drivers/media/video/gspca/ov519.c index 2bd42f4e0..dfcdccf71 100644 --- a/linux/drivers/media/video/gspca/ov519.c +++ b/linux/drivers/media/video/gspca/ov519.c @@ -65,6 +65,8 @@ struct sd { __u8 colors; __u8 hflip; __u8 vflip; + __u8 autobrightness; + __u8 freq; __u8 stopped; /* Streaming is temporarily paused */ @@ -94,11 +96,17 @@ static int sd_sethflip(struct gspca_dev *gspca_dev, __s32 val); static int sd_gethflip(struct gspca_dev *gspca_dev, __s32 *val); static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val); static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val); +static int sd_setautobrightness(struct gspca_dev *gspca_dev, __s32 val); +static int sd_getautobrightness(struct gspca_dev *gspca_dev, __s32 *val); +static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val); +static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val); static void setbrightness(struct gspca_dev *gspca_dev); static void setcontrast(struct gspca_dev *gspca_dev); static void setcolors(struct gspca_dev *gspca_dev); +static void setautobrightness(struct sd *sd); +static void setfreq(struct sd *sd); -static struct ctrl sd_ctrls[] = { +static const struct ctrl sd_ctrls[] = { { { .id = V4L2_CID_BRIGHTNESS, @@ -141,7 +149,7 @@ static struct ctrl sd_ctrls[] = { .set = sd_setcolors, .get = sd_getcolors, }, -/* next controls work with ov7670 only */ +/* The flip controls work with ov7670 only */ #define HFLIP_IDX 3 { { @@ -172,6 +180,51 @@ static struct ctrl sd_ctrls[] = { .set = sd_setvflip, .get = sd_getvflip, }, +#define AUTOBRIGHT_IDX 5 + { + { + .id = V4L2_CID_AUTOBRIGHTNESS, + .type = V4L2_CTRL_TYPE_BOOLEAN, + .name = "Auto Brightness", + .minimum = 0, + .maximum = 1, + .step = 1, +#define AUTOBRIGHT_DEF 1 + .default_value = AUTOBRIGHT_DEF, + }, + .set = sd_setautobrightness, + .get = sd_getautobrightness, + }, +#define FREQ_IDX 6 + { + { + .id = V4L2_CID_POWER_LINE_FREQUENCY, + .type = V4L2_CTRL_TYPE_MENU, + .name = "Light frequency filter", + .minimum = 0, + .maximum = 2, /* 0: 0, 1: 50Hz, 2:60Hz */ + .step = 1, +#define FREQ_DEF 0 + .default_value = FREQ_DEF, + }, + .set = sd_setfreq, + .get = sd_getfreq, + }, +#define OV7670_FREQ_IDX 7 + { + { + .id = V4L2_CID_POWER_LINE_FREQUENCY, + .type = V4L2_CTRL_TYPE_MENU, + .name = "Light frequency filter", + .minimum = 0, + .maximum = 3, /* 0: 0, 1: 50Hz, 2:60Hz 3: Auto Hz */ + .step = 1, +#define OV7670_FREQ_DEF 3 + .default_value = OV7670_FREQ_DEF, + }, + .set = sd_setfreq, + .get = sd_getfreq, + }, }; static const struct v4l2_pix_format ov519_vga_mode[] = { @@ -416,7 +469,7 @@ static const struct ov_i2c_regvals norm_6x30[] = { { 0x07, 0x2d }, /* Sharpness */ { 0x0c, 0x20 }, { 0x0d, 0x20 }, - { 0x0e, 0x20 }, + { 0x0e, 0xa0 }, /* Was 0x20, bit7 enables a 2x gain which we need */ { 0x0f, 0x05 }, { 0x10, 0x9a }, { 0x11, 0x00 }, /* Pixel clock = fastest */ @@ -1659,9 +1712,21 @@ static int sd_config(struct gspca_dev *gspca_dev, sd->colors = COLOR_DEF; sd->hflip = HFLIP_DEF; sd->vflip = VFLIP_DEF; - if (sd->sensor != SEN_OV7670) - gspca_dev->ctrl_dis = (1 << HFLIP_IDX) - | (1 << VFLIP_IDX); + sd->autobrightness = AUTOBRIGHT_DEF; + if (sd->sensor == SEN_OV7670) { + sd->freq = OV7670_FREQ_DEF; + gspca_dev->ctrl_dis = 1 << FREQ_IDX; + } else { + sd->freq = FREQ_DEF; + gspca_dev->ctrl_dis = (1 << HFLIP_IDX) | (1 << VFLIP_IDX) | + (1 << OV7670_FREQ_IDX); + } + if (sd->sensor == SEN_OV7640 || sd->sensor == SEN_OV7670) + gspca_dev->ctrl_dis |= 1 << AUTOBRIGHT_IDX; + /* OV8610 Frequency filter control should work but needs testing */ + if (sd->sensor == SEN_OV8610) + gspca_dev->ctrl_dis |= 1 << FREQ_IDX; + return 0; error: PDEBUG(D_ERR, "OV519 Config failed"); @@ -2258,7 +2323,6 @@ static int set_ov_sensor_window(struct sd *sd) msleep(10); /* need to sleep between read and write to * same reg! */ i2c_w(sd, OV7670_REG_VREF, v); - sethvflip(sd); } else { i2c_w(sd, 0x17, hwsbase); i2c_w(sd, 0x18, hwebase + (sd->gspca_dev.width >> hwscale)); @@ -2293,6 +2357,9 @@ static int sd_start(struct gspca_dev *gspca_dev) setcontrast(gspca_dev); setbrightness(gspca_dev); setcolors(gspca_dev); + sethvflip(sd); + setautobrightness(sd); + setfreq(sd); ret = ov51x_restart(sd); if (ret < 0) @@ -2419,8 +2486,7 @@ static void setbrightness(struct gspca_dev *gspca_dev) break; case SEN_OV7620: /* 7620 doesn't like manual changes when in auto mode */ -/*fixme - * if (!sd->auto_brt) */ + if (!sd->autobrightness) i2c_w(sd, OV7610_REG_BRT, val); break; case SEN_OV7670: @@ -2507,6 +2573,70 @@ static void setcolors(struct gspca_dev *gspca_dev) } } +static void setautobrightness(struct sd *sd) +{ + if (sd->sensor == SEN_OV7640 || sd->sensor == SEN_OV7670) + return; + + i2c_w_mask(sd, 0x2d, sd->autobrightness ? 0x10 : 0x00, 0x10); +} + +static void setfreq(struct sd *sd) +{ + if (sd->sensor == SEN_OV7670) { + switch (sd->freq) { + case 0: /* Banding filter disabled */ + i2c_w_mask(sd, OV7670_REG_COM8, 0, OV7670_COM8_BFILT); + break; + case 1: /* 50 hz */ + i2c_w_mask(sd, OV7670_REG_COM8, OV7670_COM8_BFILT, + OV7670_COM8_BFILT); + i2c_w_mask(sd, OV7670_REG_COM11, 0x08, 0x18); + break; + case 2: /* 60 hz */ + i2c_w_mask(sd, OV7670_REG_COM8, OV7670_COM8_BFILT, + OV7670_COM8_BFILT); + i2c_w_mask(sd, OV7670_REG_COM11, 0x00, 0x18); + break; + case 3: /* Auto hz */ + i2c_w_mask(sd, OV7670_REG_COM8, OV7670_COM8_BFILT, + OV7670_COM8_BFILT); + i2c_w_mask(sd, OV7670_REG_COM11, OV7670_COM11_HZAUTO, + 0x18); + break; + } + } else { + switch (sd->freq) { + case 0: /* Banding filter disabled */ + i2c_w_mask(sd, 0x2d, 0x00, 0x04); + i2c_w_mask(sd, 0x2a, 0x00, 0x80); + break; + case 1: /* 50 hz (filter on and framerate adj) */ + i2c_w_mask(sd, 0x2d, 0x04, 0x04); + i2c_w_mask(sd, 0x2a, 0x80, 0x80); + /* 20 fps -> 16.667 fps */ + if (sd->sensor == SEN_OV6620 || + sd->sensor == SEN_OV6630) + i2c_w(sd, 0x2b, 0x5e); + else + i2c_w(sd, 0x2b, 0xac); + break; + case 2: /* 60 hz (filter on, ...) */ + i2c_w_mask(sd, 0x2d, 0x04, 0x04); + if (sd->sensor == SEN_OV6620 || + sd->sensor == SEN_OV6630) { + /* 20 fps -> 15 fps */ + i2c_w_mask(sd, 0x2a, 0x80, 0x80); + i2c_w(sd, 0x2b, 0xa8); + } else { + /* no framerate adj. */ + i2c_w_mask(sd, 0x2a, 0x00, 0x80); + } + break; + } + } +} + static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val) { struct sd *sd = (struct sd *) gspca_dev; @@ -2597,6 +2727,71 @@ static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val) return 0; } +static int sd_setautobrightness(struct gspca_dev *gspca_dev, __s32 val) +{ + struct sd *sd = (struct sd *) gspca_dev; + + sd->autobrightness = val; + if (gspca_dev->streaming) + setautobrightness(sd); + return 0; +} + +static int sd_getautobrightness(struct gspca_dev *gspca_dev, __s32 *val) +{ + struct sd *sd = (struct sd *) gspca_dev; + + *val = sd->autobrightness; + return 0; +} + +static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val) +{ + struct sd *sd = (struct sd *) gspca_dev; + + sd->freq = val; + if (gspca_dev->streaming) + setfreq(sd); + return 0; +} + +static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val) +{ + struct sd *sd = (struct sd *) gspca_dev; + + *val = sd->freq; + return 0; +} + +static int sd_querymenu(struct gspca_dev *gspca_dev, + struct v4l2_querymenu *menu) +{ + struct sd *sd = (struct sd *) gspca_dev; + + switch (menu->id) { + case V4L2_CID_POWER_LINE_FREQUENCY: + switch (menu->index) { + case 0: /* V4L2_CID_POWER_LINE_FREQUENCY_DISABLED */ + strcpy((char *) menu->name, "NoFliker"); + return 0; + case 1: /* V4L2_CID_POWER_LINE_FREQUENCY_50HZ */ + strcpy((char *) menu->name, "50 Hz"); + return 0; + case 2: /* V4L2_CID_POWER_LINE_FREQUENCY_60HZ */ + strcpy((char *) menu->name, "60 Hz"); + return 0; + case 3: + if (sd->sensor != SEN_OV7670) + return -EINVAL; + + strcpy((char *) menu->name, "Automatic"); + return 0; + } + break; + } + return -EINVAL; +} + /* sub-driver description */ static const struct sd_desc sd_desc = { .name = MODULE_NAME, @@ -2607,6 +2802,7 @@ static const struct sd_desc sd_desc = { .start = sd_start, .stopN = sd_stopN, .pkt_scan = sd_pkt_scan, + .querymenu = sd_querymenu, }; /* -- module initialisation -- */ -- cgit v1.2.3 From 03d777f511d5820441ae2f3584e7441dd019faea Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Tue, 16 Jun 2009 18:14:49 -0700 Subject: v4l2: Fix flaw in alignment code From: Trent Piepho It's possible that the height alignment would be increased beyond the maximum possible value when trying to satisfy size alignment. Please fold with b4d3ec8d363d v4l2: Create helper function for bounding and aligning images Priority: high Signed-off-by: Trent Piepho --- linux/drivers/media/video/v4l2-common.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/v4l2-common.c b/linux/drivers/media/video/v4l2-common.c index ba3790a98..f94b5d92a 100644 --- a/linux/drivers/media/video/v4l2-common.c +++ b/linux/drivers/media/video/v4l2-common.c @@ -1055,10 +1055,13 @@ void v4l_bound_align_image(u32 *w, unsigned int wmin, unsigned int wmax, if (walign + halign < salign) { /* Max walign where there is still a valid width */ unsigned int wmaxa = __fls(wmax ^ (wmin - 1)); + /* Max halign where there is still a valid height */ + unsigned int hmaxa = __fls(hmax ^ (hmin - 1)); /* up the smaller alignment until we have enough */ do { - if (walign <= halign && walign < wmaxa) { + if (halign >= hmaxa || + (walign <= halign && walign < wmaxa)) { *w = clamp_align(*w, wmin, wmax, walign + 1); walign = __ffs(*w); } else { -- cgit v1.2.3 From 3a6edb94d704d582201d9fad16a566691f176e76 Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Wed, 17 Jun 2009 09:06:21 -0700 Subject: pxa-camera: fix typo From: Trent Piepho v4l2_bound_align_image should be v4l_bound_align_image. Change comment to match coding style. Should be merged with cb48209c1841 pxa-camera: Use v4l bounding/alignment function Priority: high Signed-off-by: Trent Piepho --- linux/drivers/media/video/pxa_camera.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/pxa_camera.c b/linux/drivers/media/video/pxa_camera.c index 7578d0cfe..8964d60cd 100644 --- a/linux/drivers/media/video/pxa_camera.c +++ b/linux/drivers/media/video/pxa_camera.c @@ -1403,13 +1403,15 @@ static int pxa_camera_try_fmt(struct soc_camera_device *icd, return -EINVAL; } - /* Limit to pxa hardware capabilities. YUV422P planar format requires + /* + * Limit to pxa hardware capabilities. YUV422P planar format requires * images size to be a multiple of 16 bytes. If not, zeros will be * inserted between Y and U planes, and U and V planes, which violates - * the YUV422P standard. */ - v4l2_bound_align_image(&pix->width, 48, 2048, 1, - &pix->height, 32, 2048, 0, - xlate->host_fmt->fourcc == V4L2_PIX_FMT_YUV422P ? 4 : 0); + * the YUV422P standard. + */ + v4l_bound_align_image(&pix->width, 48, 2048, 1, + &pix->height, 32, 2048, 0, + xlate->host_fmt->fourcc == V4L2_PIX_FMT_YUV422P ? 4 : 0); pix->bytesperline = pix->width * DIV_ROUND_UP(xlate->host_fmt->depth, 8); -- cgit v1.2.3 From 3f42c839042d7e8f83941f38a529033a297ae400 Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Thu, 18 Jun 2009 23:20:28 -0400 Subject: em28xx: make sure the analog GPIOs are set if we used a card hint From: Devin Heitmueller In cases where the board had a default USB ID, we would not indentify the board until after the call to em28xx_set_mode(). As a result, for those boards the analog GPIOs were not being set before probing the i2c bus for devices (the probe would occur with the GPIOs being all high). Make a call to em28xx_set_mode() so that the GPIOs are set properly before probing the i2c bus for devices. This problem was detected with the EVGA inDtube, where the tvp5150 is not powered on unless GPIO1 is pulled low. Priority: normal Signed-off-by: Devin Heitmueller --- linux/drivers/media/video/em28xx/em28xx-cards.c | 6 ++++++ 1 file changed, 6 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 16093680b..153b73ebf 100644 --- a/linux/drivers/media/video/em28xx/em28xx-cards.c +++ b/linux/drivers/media/video/em28xx/em28xx-cards.c @@ -2204,6 +2204,12 @@ void em28xx_card_setup(struct em28xx *dev) case EM2880_BOARD_MSI_DIGIVOX_AD: if (!em28xx_hint_board(dev)) em28xx_set_model(dev); + + /* In cases where we had to use a board hint, the call to + em28xx_set_mode() in em28xx_pre_card_setup() was a no-op, + so make the call now so the analog GPIOs are set properly + before probing the i2c bus. */ + em28xx_set_mode(dev, EM28XX_ANALOG_MODE); break; } -- cgit v1.2.3 From e8ace46ff8aa80c3e6520cebc50b2e372b313a7c Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Thu, 18 Jun 2009 23:33:54 -0400 Subject: em28xx: add support for EVGA inDtube From: Devin Heitmueller Add support for the EVGA inDtube. Both ATSC and analog side validated as fully functional. Thanks to Jake Crimmins from EVGA for providing the correct GPIO info. Thanks to Alan Hagge for doing all the device testing. Thanks to Greg Williamson for providing hardware for testing. Priority: normal Signed-off-by: Devin Heitmueller Cc: Jake Crimmins Cc: Alan Hagge Cc: Greg Williamson --- linux/drivers/media/video/em28xx/em28xx-cards.c | 48 +++++++++++++++++++++++++ linux/drivers/media/video/em28xx/em28xx-dvb.c | 1 + linux/drivers/media/video/em28xx/em28xx.h | 1 + 3 files changed, 50 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 153b73ebf..0ba7d3aa6 100644 --- a/linux/drivers/media/video/em28xx/em28xx-cards.c +++ b/linux/drivers/media/video/em28xx/em28xx-cards.c @@ -152,6 +152,24 @@ static struct em28xx_reg_seq kworld_330u_digital[] = { { -1, -1, -1, -1}, }; +/* Evga inDtube + GPIO0 - Enable digital power (s5h1409) - low to enable + GPIO1 - Enable analog power (tvp5150/emp202) - low to enable + GPIO4 - xc3028 reset + GOP3 - s5h1409 reset + */ +static struct em28xx_reg_seq evga_indtube_analog[] = { + {EM28XX_R08_GPIO, 0x79, 0xff, 60}, + { -1, -1, -1, -1}, +}; + +static struct em28xx_reg_seq evga_indtube_digital[] = { + {EM28XX_R08_GPIO, 0x7a, 0xff, 1}, + {EM2880_R04_GPO, 0x04, 0xff, 10}, + {EM2880_R04_GPO, 0x0c, 0xff, 1}, + { -1, -1, -1, -1}, +}; + /* Callback for the most boards */ static struct em28xx_reg_seq default_tuner_gpio[] = { {EM28XX_R08_GPIO, EM_GPIO_4, EM_GPIO_4, 10}, @@ -1514,6 +1532,31 @@ struct em28xx_board em28xx_boards[] = { .gpio = terratec_av350_unmute_gpio, } }, }, + [EM2882_BOARD_EVGA_INDTUBE] = { + .name = "Evga inDtube", + .tuner_type = TUNER_XC2028, + .tuner_gpio = default_tuner_gpio, + .decoder = EM28XX_TVP5150, + .mts_firmware = 1, + .has_dvb = 1, + .dvb_gpio = evga_indtube_digital, + .input = { { + .type = EM28XX_VMUX_TELEVISION, + .vmux = TVP5150_COMPOSITE0, + .amux = EM28XX_AMUX_VIDEO, + .gpio = evga_indtube_analog, + }, { + .type = EM28XX_VMUX_COMPOSITE1, + .vmux = TVP5150_COMPOSITE1, + .amux = EM28XX_AMUX_LINE_IN, + .gpio = evga_indtube_analog, + }, { + .type = EM28XX_VMUX_SVIDEO, + .vmux = TVP5150_SVIDEO, + .amux = EM28XX_AMUX_LINE_IN, + .gpio = evga_indtube_analog, + } }, + }, }; const unsigned int em28xx_bcount = ARRAY_SIZE(em28xx_boards); @@ -1640,6 +1683,7 @@ static struct em28xx_hash_table em28xx_eeprom_hash[] = { {0x72cc5a8b, EM2820_BOARD_PROLINK_PLAYTV_BOX4_USB2, TUNER_YMEC_TVF_5533MF}, {0x966a0441, EM2880_BOARD_KWORLD_DVB_310U, TUNER_XC2028}, {0x9567eb1a, EM2880_BOARD_EMPIRE_DUAL_TV, TUNER_XC2028}, + {0xcee44a99, EM2882_BOARD_EVGA_INDTUBE, TUNER_XC2028}, }; /* I2C devicelist hash table for devices with generic USB IDs */ @@ -1903,6 +1947,10 @@ static void em28xx_setup_xc3028(struct em28xx *dev, struct xc2028_ctrl *ctl) ctl->demod = XC3028_FE_CHINA; ctl->fname = XC2028_DEFAULT_FIRMWARE; break; + case EM2882_BOARD_EVGA_INDTUBE: + ctl->demod = XC3028_FE_CHINA; + ctl->fname = XC3028L_DEFAULT_FIRMWARE; + break; default: ctl->demod = XC3028_FE_OREN538; } diff --git a/linux/drivers/media/video/em28xx/em28xx-dvb.c b/linux/drivers/media/video/em28xx/em28xx-dvb.c index 722cc709f..85afa0be0 100644 --- a/linux/drivers/media/video/em28xx/em28xx-dvb.c +++ b/linux/drivers/media/video/em28xx/em28xx-dvb.c @@ -446,6 +446,7 @@ static int dvb_init(struct em28xx *dev) } break; case EM2883_BOARD_KWORLD_HYBRID_330U: + case EM2882_BOARD_EVGA_INDTUBE: dvb->frontend = dvb_attach(s5h1409_attach, &em28xx_s5h1409_with_xc3028, &dev->i2c_adap); diff --git a/linux/drivers/media/video/em28xx/em28xx.h b/linux/drivers/media/video/em28xx/em28xx.h index aafc4a2d0..6fb890efa 100644 --- a/linux/drivers/media/video/em28xx/em28xx.h +++ b/linux/drivers/media/video/em28xx/em28xx.h @@ -107,6 +107,7 @@ #define EM2860_BOARD_TERRATEC_GRABBY 67 #define EM2860_BOARD_TERRATEC_AV350 68 #define EM2882_BOARD_KWORLD_ATSC_315U 69 +#define EM2882_BOARD_EVGA_INDTUBE 70 /* Limits minimum and default number of buffers */ #define EM28XX_MIN_BUF 4 -- cgit v1.2.3 From 0047b6a8d3ad87d40efdfbd209a059e90e7f98c9 Mon Sep 17 00:00:00 2001 From: "Igor M. Liplianin" Date: Fri, 19 Jun 2009 12:45:23 +0400 Subject: Create table for customize stv0900 ts registers. From: Igor M. Liplianin Signed-off-by: Igor M. Liplianin --- linux/drivers/media/dvb/frontends/stv0900.h | 7 ++++++- linux/drivers/media/dvb/frontends/stv0900_core.c | 21 +++++++++++++++++++-- linux/drivers/media/dvb/frontends/stv0900_priv.h | 2 ++ linux/drivers/media/video/cx23885/cx23885-dvb.c | 17 +++++++++++++++-- 4 files changed, 42 insertions(+), 5 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/frontends/stv0900.h b/linux/drivers/media/dvb/frontends/stv0900.h index 8a1332c20..bf4e9b633 100644 --- a/linux/drivers/media/dvb/frontends/stv0900.h +++ b/linux/drivers/media/dvb/frontends/stv0900.h @@ -29,6 +29,11 @@ #include #include "dvb_frontend.h" +struct stv0900_reg { + u16 addr; + u8 val; +}; + struct stv0900_config { u8 demod_address; u32 xtal; @@ -38,7 +43,7 @@ struct stv0900_config { u8 path1_mode; u8 path2_mode; - + struct stv0900_reg *ts_config_regs; u8 tun1_maddress;/* 0, 1, 2, 3 for 0xc0, 0xc2, 0xc4, 0xc6 */ u8 tun2_maddress; u8 tun1_adc;/* 1 for stv6110, 2 for stb6100 */ diff --git a/linux/drivers/media/dvb/frontends/stv0900_core.c b/linux/drivers/media/dvb/frontends/stv0900_core.c index 2e9e5fbbb..84bf35edb 100644 --- a/linux/drivers/media/dvb/frontends/stv0900_core.c +++ b/linux/drivers/media/dvb/frontends/stv0900_core.c @@ -1397,7 +1397,7 @@ static enum fe_stv0900_error stv0900_init_internal(struct dvb_frontend *fe, struct stv0900_state *state = fe->demodulator_priv; enum fe_stv0900_error error = STV0900_NO_ERROR; enum fe_stv0900_error demodError = STV0900_NO_ERROR; - int selosci; + int selosci, i; struct stv0900_inode *temp_int = find_inode(state->i2c_adap, state->config->demod_address); @@ -1444,7 +1444,23 @@ static enum fe_stv0900_error stv0900_init_internal(struct dvb_frontend *fe, stv0900_write_bits(state->internal, F0900_P1_ROLLOFF_CONTROL, p_init->rolloff); stv0900_write_bits(state->internal, F0900_P2_ROLLOFF_CONTROL, p_init->rolloff); - stv0900_set_ts_parallel_serial(state->internal, p_init->path1_ts_clock, p_init->path2_ts_clock); + state->internal->ts_config = p_init->ts_config; + if (state->internal->ts_config == NULL) + stv0900_set_ts_parallel_serial(state->internal, + p_init->path1_ts_clock, + p_init->path2_ts_clock); + else { + for (i = 0; state->internal->ts_config[i].addr != 0xffff; i++) + stv0900_write_reg(state->internal, + state->internal->ts_config[i].addr, + state->internal->ts_config[i].val); + + stv0900_write_bits(state->internal, F0900_P2_RST_HWARE, 1); + stv0900_write_bits(state->internal, F0900_P2_RST_HWARE, 0); + stv0900_write_bits(state->internal, F0900_P1_RST_HWARE, 1); + stv0900_write_bits(state->internal, F0900_P1_RST_HWARE, 0); + } + stv0900_write_bits(state->internal, F0900_P1_TUN_MADDRESS, p_init->tun1_maddress); switch (p_init->tuner1_adc) { case 1: @@ -1969,6 +1985,7 @@ struct dvb_frontend *stv0900_attach(const struct stv0900_config *config, init_params.tun1_iq_inversion = STV0900_IQ_NORMAL; init_params.tuner1_adc = config->tun1_adc; init_params.path2_ts_clock = config->path2_mode; + init_params.ts_config = config->ts_config_regs; init_params.tun2_maddress = config->tun2_maddress; init_params.tuner2_adc = config->tun2_adc; init_params.tun2_iq_inversion = STV0900_IQ_SWAPPED; diff --git a/linux/drivers/media/dvb/frontends/stv0900_priv.h b/linux/drivers/media/dvb/frontends/stv0900_priv.h index 67dc8ec63..5ed7a145c 100644 --- a/linux/drivers/media/dvb/frontends/stv0900_priv.h +++ b/linux/drivers/media/dvb/frontends/stv0900_priv.h @@ -271,6 +271,7 @@ struct stv0900_init_params{ /* IQ from the tuner2 to the demod */ enum stv0900_iq_inversion tun2_iq_inversion; + struct stv0900_reg *ts_config; }; struct stv0900_search_params { @@ -363,6 +364,7 @@ struct stv0900_internal{ u8 i2c_addr; u8 clkmode;/* 0 for CLKI, 2 for XTALI */ u8 chip_id; + struct stv0900_reg *ts_config; enum fe_stv0900_error errs; int dmds_used; }; diff --git a/linux/drivers/media/video/cx23885/cx23885-dvb.c b/linux/drivers/media/video/cx23885/cx23885-dvb.c index 10bb442b1..04ff417d1 100644 --- a/linux/drivers/media/video/cx23885/cx23885-dvb.c +++ b/linux/drivers/media/video/cx23885/cx23885-dvb.c @@ -46,6 +46,7 @@ #include "dibx000_common.h" #include "zl10353.h" #include "stv0900.h" +#include "stv0900_reg.h" #include "stv6110.h" #include "lnbh24.h" #include "cx24116.h" @@ -371,13 +372,25 @@ static struct zl10353_config dvico_fusionhdtv_xc3028 = { .disable_i2c_gate_ctrl = 1, }; +static struct stv0900_reg stv0900_ts_regs[] = { + { R0900_TSGENERAL, 0x00 }, + { R0900_P1_TSSPEED, 0x40 }, + { R0900_P2_TSSPEED, 0x40 }, + { R0900_P1_TSCFGM, 0xc0 }, + { R0900_P2_TSCFGM, 0xc0 }, + { R0900_P1_TSCFGH, 0xe0 }, + { R0900_P2_TSCFGH, 0xe0 }, + { R0900_P1_TSCFGL, 0x20 }, + { R0900_P2_TSCFGL, 0x20 }, + { 0xffff, 0xff }, /* terminate */ +}; + static struct stv0900_config netup_stv0900_config = { .demod_address = 0x68, .xtal = 27000000, .clkmode = 3,/* 0-CLKI, 2-XTALI, else AUTO */ .diseqc_mode = 2,/* 2/3 PWM */ - .path1_mode = 2,/*Serial continues clock */ - .path2_mode = 2,/*Serial continues clock */ + .ts_config_regs = stv0900_ts_regs, .tun1_maddress = 0,/* 0x60 */ .tun2_maddress = 3,/* 0x63 */ .tun1_adc = 1,/* 1 Vpp */ -- cgit v1.2.3 From 4b2b8049722233fd80417b5702b1debd5d0e0ad0 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 20 Jun 2009 21:25:44 -0300 Subject: Kbuild: make USB_STV06XX compile with RHEL5 kernels From: Mauro Carvalho Chehab Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/gspca/stv06xx/stv06xx.h | 1 + 1 file changed, 1 insertion(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/stv06xx/stv06xx.h b/linux/drivers/media/video/gspca/stv06xx/stv06xx.h index 9df7137fe..bb73c3288 100644 --- a/linux/drivers/media/video/gspca/stv06xx/stv06xx.h +++ b/linux/drivers/media/video/gspca/stv06xx/stv06xx.h @@ -31,6 +31,7 @@ #define STV06XX_H_ #include "gspca.h" +#include "compat.h" #define MODULE_NAME "STV06xx" -- cgit v1.2.3 From 0333db7369d656513aa455c497f1e5e56fd9fafa Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Sat, 20 Jun 2009 20:34:42 -0400 Subject: em28xx: add Remote control support for EVGA inDtube From: Devin Heitmueller Add an IR profile for the EVGA inDtube remote control (which is an NEC type remote) Priority: normal Signed-off-by: Devin Heitmueller --- linux/drivers/media/common/ir-keymaps.c | 23 +++++++++++++++++++++++ linux/drivers/media/video/em28xx/em28xx-cards.c | 2 ++ 2 files changed, 25 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/common/ir-keymaps.c b/linux/drivers/media/common/ir-keymaps.c index d5fd71968..56fa64b4c 100644 --- a/linux/drivers/media/common/ir-keymaps.c +++ b/linux/drivers/media/common/ir-keymaps.c @@ -2800,3 +2800,26 @@ IR_KEYTAB_TYPE ir_codes_dm1105_nec[IR_KEYTAB_SIZE] = { [0x1b] = KEY_B, /*recall*/ }; EXPORT_SYMBOL_GPL(ir_codes_dm1105_nec); + +/* EVGA inDtube + Devin Heitmueller + */ +IR_KEYTAB_TYPE ir_codes_evga_indtube[IR_KEYTAB_SIZE] = { + [0x12] = KEY_POWER, + [0x02] = KEY_MODE, /* TV */ + [0x14] = KEY_MUTE, + [0x1a] = KEY_CHANNELUP, + [0x16] = KEY_TV2, /* PIP */ + [0x1d] = KEY_VOLUMEUP, + [0x05] = KEY_CHANNELDOWN, + [0x0f] = KEY_PLAYPAUSE, + [0x19] = KEY_VOLUMEDOWN, + [0x1c] = KEY_REWIND, + [0x0d] = KEY_RECORD, + [0x18] = KEY_FORWARD, + [0x1e] = KEY_PREVIOUS, + [0x1b] = KEY_STOP, + [0x1f] = KEY_NEXT, + [0x13] = KEY_CAMERA, +}; +EXPORT_SYMBOL_GPL(ir_codes_evga_indtube); diff --git a/linux/drivers/media/video/em28xx/em28xx-cards.c b/linux/drivers/media/video/em28xx/em28xx-cards.c index 0ba7d3aa6..b824eed46 100644 --- a/linux/drivers/media/video/em28xx/em28xx-cards.c +++ b/linux/drivers/media/video/em28xx/em28xx-cards.c @@ -1537,9 +1537,11 @@ struct em28xx_board em28xx_boards[] = { .tuner_type = TUNER_XC2028, .tuner_gpio = default_tuner_gpio, .decoder = EM28XX_TVP5150, + .xclk = EM28XX_XCLK_FREQUENCY_12MHZ, /* NEC IR */ .mts_firmware = 1, .has_dvb = 1, .dvb_gpio = evga_indtube_digital, + .ir_codes = ir_codes_evga_indtube, .input = { { .type = EM28XX_VMUX_TELEVISION, .vmux = TVP5150_COMPOSITE0, -- cgit v1.2.3 From a7b0779afa5ca6b4ade07f4d4083194ea0bde9fb Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 14 Jun 2009 10:20:21 +0200 Subject: ivtv/cx18: fix regression: class controls are no longer seen From: Hans Verkuil A previous change (v4l2-common: remove v4l2_ctrl_query_fill_std) broke the handling of class controls in VIDIOC_QUERYCTRL. The MPEG class control was broken for all drivers that use the cx2341x module and the USER class control was broken for ivtv and cx18. This change adds back proper class control support. Priority: high Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/cx18/cx18-controls.c | 2 ++ linux/drivers/media/video/cx2341x.c | 2 ++ linux/drivers/media/video/ivtv/ivtv-controls.c | 2 ++ 3 files changed, 6 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/cx18/cx18-controls.c b/linux/drivers/media/video/cx18/cx18-controls.c index 8e35c3aed..5136df198 100644 --- a/linux/drivers/media/video/cx18/cx18-controls.c +++ b/linux/drivers/media/video/cx18/cx18-controls.c @@ -61,6 +61,8 @@ int cx18_queryctrl(struct file *file, void *fh, struct v4l2_queryctrl *qctrl) switch (qctrl->id) { /* Standard V4L2 controls */ + case V4L2_CID_USER_CLASS: + return v4l2_ctrl_query_fill(qctrl, 0, 0, 0, 0); case V4L2_CID_BRIGHTNESS: case V4L2_CID_HUE: case V4L2_CID_SATURATION: diff --git a/linux/drivers/media/video/cx2341x.c b/linux/drivers/media/video/cx2341x.c index 2cf0c5fee..8c468fc86 100644 --- a/linux/drivers/media/video/cx2341x.c +++ b/linux/drivers/media/video/cx2341x.c @@ -501,6 +501,8 @@ int cx2341x_ctrl_query(const struct cx2341x_mpeg_params *params, int err; switch (qctrl->id) { + case V4L2_CID_MPEG_CLASS: + return v4l2_ctrl_query_fill(qctrl, 0, 0, 0, 0); case V4L2_CID_MPEG_STREAM_TYPE: return v4l2_ctrl_query_fill(qctrl, V4L2_MPEG_STREAM_TYPE_MPEG2_PS, diff --git a/linux/drivers/media/video/ivtv/ivtv-controls.c b/linux/drivers/media/video/ivtv/ivtv-controls.c index 84995bcf4..a3b77ed3f 100644 --- a/linux/drivers/media/video/ivtv/ivtv-controls.c +++ b/linux/drivers/media/video/ivtv/ivtv-controls.c @@ -60,6 +60,8 @@ int ivtv_queryctrl(struct file *file, void *fh, struct v4l2_queryctrl *qctrl) switch (qctrl->id) { /* Standard V4L2 controls */ + case V4L2_CID_USER_CLASS: + return v4l2_ctrl_query_fill(qctrl, 0, 0, 0, 0); case V4L2_CID_BRIGHTNESS: case V4L2_CID_HUE: case V4L2_CID_SATURATION: -- cgit v1.2.3 From 2b10da9fa1b63700963d7163c05ce7d3502b2d65 Mon Sep 17 00:00:00 2001 From: "hans@rhel5-devel.localdomain" Date: Sun, 14 Jun 2009 10:28:17 +0200 Subject: gspca_ov519: limit ov6630 qvif uv swap fix to ov66308AF From: Hans de Goede The fix for the UV swapping in qcif mode with the ov6630, which I did to fix this issue on a ov518 cam with an ov66308AF, causes UV swapping in qcif with another cam of mine with the ov518 and an ov66308AE, so this patch changes the code to differentiate between the ov66308AF and other ov6630 versions, and restricts the UV swap fix to the ov66308AF. Priority: normal Signed-off-by: Hans de Goede --- linux/drivers/media/video/gspca/ov519.c | 38 +++++++++++++++++++++------------ 1 file changed, 24 insertions(+), 14 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/ov519.c b/linux/drivers/media/video/gspca/ov519.c index dfcdccf71..4a272aaa1 100644 --- a/linux/drivers/media/video/gspca/ov519.c +++ b/linux/drivers/media/video/gspca/ov519.c @@ -77,12 +77,13 @@ struct sd { #define SEN_UNKNOWN 0 #define SEN_OV6620 1 #define SEN_OV6630 2 -#define SEN_OV7610 3 -#define SEN_OV7620 4 -#define SEN_OV7640 5 -#define SEN_OV7670 6 -#define SEN_OV76BE 7 -#define SEN_OV8610 8 +#define SEN_OV66308AF 3 +#define SEN_OV7610 4 +#define SEN_OV7620 5 +#define SEN_OV7640 6 +#define SEN_OV7670 7 +#define SEN_OV76BE 8 +#define SEN_OV8610 9 }; /* V4L2 controls supported by the driver */ @@ -1415,13 +1416,14 @@ static int ov6xx0_configure(struct sd *sd) break; case 0x01: sd->sensor = SEN_OV6620; + PDEBUG(D_PROBE, "Sensor is an OV6620"); break; case 0x02: sd->sensor = SEN_OV6630; PDEBUG(D_PROBE, "Sensor is an OV66308AE"); break; case 0x03: - sd->sensor = SEN_OV6630; + sd->sensor = SEN_OV66308AF; PDEBUG(D_PROBE, "Sensor is an OV66308AF"); break; case 0x90: @@ -1745,6 +1747,7 @@ static int sd_init(struct gspca_dev *gspca_dev) return -EIO; break; case SEN_OV6630: + case SEN_OV66308AF: if (write_i2c_regvals(sd, norm_6x30, ARRAY_SIZE(norm_6x30))) return -EIO; break; @@ -2106,6 +2109,7 @@ static int mode_init_ov_sensor_regs(struct sd *sd) break; case SEN_OV6620: case SEN_OV6630: + case SEN_OV66308AF: i2c_w_mask(sd, 0x14, qvga ? 0x20 : 0x00, 0x20); break; default: @@ -2126,7 +2130,8 @@ static int mode_init_ov_sensor_regs(struct sd *sd) /* OV7640 is 8-bit only */ - if (sd->sensor != SEN_OV6630 && sd->sensor != SEN_OV7640) + if (sd->sensor != SEN_OV6630 && sd->sensor != SEN_OV66308AF && + sd->sensor != SEN_OV7640) i2c_w_mask(sd, 0x13, 0x00, 0x20); /******** Clock programming ********/ @@ -2213,15 +2218,14 @@ static int set_ov_sensor_window(struct sd *sd) break; case SEN_OV6620: case SEN_OV6630: + case SEN_OV66308AF: hwsbase = 0x38; hwebase = 0x3a; vwsbase = 0x05; vwebase = 0x06; - if (qvga) { + if (sd->sensor == SEN_OV66308AF && qvga) /* HDG: this fixes U and V getting swapped */ - hwsbase--; - vwsbase--; - } + hwsbase++; break; case SEN_OV7620: hwsbase = 0x2f; /* From 7620.SET (spec is wrong) */ @@ -2245,6 +2249,7 @@ static int set_ov_sensor_window(struct sd *sd) switch (sd->sensor) { case SEN_OV6620: case SEN_OV6630: + case SEN_OV66308AF: if (qvga) { /* QCIF */ hwscale = 0; vwscale = 0; @@ -2481,6 +2486,7 @@ static void setbrightness(struct gspca_dev *gspca_dev) case SEN_OV76BE: case SEN_OV6620: case SEN_OV6630: + case SEN_OV66308AF: case SEN_OV7640: i2c_w(sd, OV7610_REG_BRT, val); break; @@ -2509,6 +2515,7 @@ static void setcontrast(struct gspca_dev *gspca_dev) i2c_w(sd, OV7610_REG_CNT, val); break; case SEN_OV6630: + case SEN_OV66308AF: i2c_w_mask(sd, OV7610_REG_CNT, val >> 4, 0x0f); break; case SEN_OV8610: { @@ -2553,6 +2560,7 @@ static void setcolors(struct gspca_dev *gspca_dev) case SEN_OV76BE: case SEN_OV6620: case SEN_OV6630: + case SEN_OV66308AF: i2c_w(sd, OV7610_REG_SAT, val); break; case SEN_OV7620: @@ -2616,7 +2624,8 @@ static void setfreq(struct sd *sd) i2c_w_mask(sd, 0x2a, 0x80, 0x80); /* 20 fps -> 16.667 fps */ if (sd->sensor == SEN_OV6620 || - sd->sensor == SEN_OV6630) + sd->sensor == SEN_OV6630 || + sd->sensor == SEN_OV66308AF) i2c_w(sd, 0x2b, 0x5e); else i2c_w(sd, 0x2b, 0xac); @@ -2624,7 +2633,8 @@ static void setfreq(struct sd *sd) case 2: /* 60 hz (filter on, ...) */ i2c_w_mask(sd, 0x2d, 0x04, 0x04); if (sd->sensor == SEN_OV6620 || - sd->sensor == SEN_OV6630) { + sd->sensor == SEN_OV6630 || + sd->sensor == SEN_OV66308AF) { /* 20 fps -> 15 fps */ i2c_w_mask(sd, 0x2a, 0x80, 0x80); i2c_w(sd, 0x2b, 0xa8); -- cgit v1.2.3 From 5877f40d7d23a9f44d4bf1910cdefdda8f05a5af Mon Sep 17 00:00:00 2001 From: "hans@rhel5-devel.localdomain" Date: Sun, 14 Jun 2009 10:48:00 +0200 Subject: gspca_ov519: Add 320x240 and 160x120 support for cif sensor cams From: Hans de Goede gspca_ov519: Add 320x240 and 160x120 support for cif sensor cams Priority: normal Signed-off-by: Hans de Goede --- linux/drivers/media/video/gspca/ov519.c | 33 ++++++++++++++++++++++++++++++--- 1 file changed, 30 insertions(+), 3 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/ov519.c b/linux/drivers/media/video/gspca/ov519.c index 4a272aaa1..c2f054c3c 100644 --- a/linux/drivers/media/video/gspca/ov519.c +++ b/linux/drivers/media/video/gspca/ov519.c @@ -241,11 +241,21 @@ static const struct v4l2_pix_format ov519_vga_mode[] = { .priv = 0}, }; static const struct v4l2_pix_format ov519_sif_mode[] = { + {160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, + .bytesperline = 160, + .sizeimage = 160 * 120 * 3 / 8 + 590, + .colorspace = V4L2_COLORSPACE_JPEG, + .priv = 3}, {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, .bytesperline = 176, .sizeimage = 176 * 144 * 3 / 8 + 590, .colorspace = V4L2_COLORSPACE_JPEG, .priv = 1}, + {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, + .bytesperline = 320, + .sizeimage = 320 * 240 * 3 / 8 + 590, + .colorspace = V4L2_COLORSPACE_JPEG, + .priv = 2}, {352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, .bytesperline = 352, .sizeimage = 352 * 288 * 3 / 8 + 590, @@ -266,11 +276,21 @@ static const struct v4l2_pix_format ov518_vga_mode[] = { .priv = 0}, }; static const struct v4l2_pix_format ov518_sif_mode[] = { + {160, 120, V4L2_PIX_FMT_OV518, V4L2_FIELD_NONE, + .bytesperline = 160, + .sizeimage = 40000, + .colorspace = V4L2_COLORSPACE_JPEG, + .priv = 3}, {176, 144, V4L2_PIX_FMT_OV518, V4L2_FIELD_NONE, .bytesperline = 176, .sizeimage = 40000, .colorspace = V4L2_COLORSPACE_JPEG, .priv = 1}, + {320, 240, V4L2_PIX_FMT_OV518, V4L2_FIELD_NONE, + .bytesperline = 320, + .sizeimage = 320 * 240 * 3 / 8 + 590, + .colorspace = V4L2_COLORSPACE_JPEG, + .priv = 2}, {352, 288, V4L2_PIX_FMT_OV518, V4L2_FIELD_NONE, .bytesperline = 352, .sizeimage = 352 * 288 * 3 / 8 + 590, @@ -2039,7 +2059,7 @@ static int mode_init_ov_sensor_regs(struct sd *sd) int qvga; gspca_dev = &sd->gspca_dev; - qvga = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv; + qvga = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv & 1; /******** Mode (VGA/QVGA) and sensor specific regs ********/ switch (sd->sensor) { @@ -2193,13 +2213,14 @@ static void sethvflip(struct sd *sd) static int set_ov_sensor_window(struct sd *sd) { struct gspca_dev *gspca_dev; - int qvga; + int qvga, crop; int hwsbase, hwebase, vwsbase, vwebase, hwscale, vwscale; int ret, hstart, hstop, vstop, vstart; __u8 v; gspca_dev = &sd->gspca_dev; - qvga = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv; + qvga = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv & 1; + crop = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv & 2; /* The different sensor ICs handle setting up of window differently. * IF YOU SET IT WRONG, YOU WILL GET ALL ZERO ISOC DATA FROM OV51x!! */ @@ -2226,6 +2247,12 @@ static int set_ov_sensor_window(struct sd *sd) if (sd->sensor == SEN_OV66308AF && qvga) /* HDG: this fixes U and V getting swapped */ hwsbase++; + if (crop) { + hwsbase += 8; + hwebase += 8; + vwsbase += 11; + vwebase += 11; + } break; case SEN_OV7620: hwsbase = 0x2f; /* From 7620.SET (spec is wrong) */ -- cgit v1.2.3 From 543bd5c99a1c67289850a7833c92adf8fb18e086 Mon Sep 17 00:00:00 2001 From: "hans@rhel5-devel.localdomain" Date: Sun, 14 Jun 2009 11:21:35 +0200 Subject: gspca_ov519: check ov518 packet numbers From: Hans de Goede Check ov518 packet numbers to detect dropped packets. Priority: normal Signed-off-by: Hans de Goede --- linux/drivers/media/video/gspca/ov519.c | 29 +++++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/ov519.c b/linux/drivers/media/video/gspca/ov519.c index c2f054c3c..8849a70a6 100644 --- a/linux/drivers/media/video/gspca/ov519.c +++ b/linux/drivers/media/video/gspca/ov519.c @@ -50,6 +50,8 @@ static int i2c_detect_tries = 10; struct sd { struct gspca_dev gspca_dev; /* !! must be the first item */ + __u8 packet_nr; + char bridge; #define BRIDGE_OV511 0 #define BRIDGE_OV511PLUS 1 @@ -2416,18 +2418,33 @@ static void ov518_pkt_scan(struct gspca_dev *gspca_dev, __u8 *data, /* isoc packet */ int len) /* iso packet length */ { - PDEBUG(D_STREAM, "ov518_pkt_scan: %d bytes", len); - - if (len & 7) { - len--; - PDEBUG(D_STREAM, "packet number: %d\n", (int)data[len]); - } + struct sd *sd = (struct sd *) gspca_dev; /* A false positive here is likely, until OVT gives me * the definitive SOF/EOF format */ if ((!(data[0] | data[1] | data[2] | data[3] | data[5])) && data[6]) { gspca_frame_add(gspca_dev, LAST_PACKET, frame, data, 0); gspca_frame_add(gspca_dev, FIRST_PACKET, frame, data, 0); + sd->packet_nr = 0; + } + + if (gspca_dev->last_packet_type == DISCARD_PACKET) + return; + + /* Does this device use packet numbers ? */ + if (len & 7) { + len--; + if (sd->packet_nr == data[len]) + sd->packet_nr++; + /* The last few packets of the frame (which are all 0's + except that they may contain part of the footer), are + numbered 0 */ + else if (sd->packet_nr == 0 || data[len]) { + PDEBUG(D_ERR, "Invalid packet nr: %d (expect: %d)", + (int)data[len], (int)sd->packet_nr); + gspca_dev->last_packet_type = DISCARD_PACKET; + return; + } } /* intermediate packet */ -- cgit v1.2.3 From d2ee988a008ff044479ec88fd1832190df4bb4e3 Mon Sep 17 00:00:00 2001 From: "hans@rhel5-devel.localdomain" Date: Sun, 14 Jun 2009 11:25:06 +0200 Subject: gspca_ov519: Fix led inversion with some cams From: Hans de Goede My ov519 cam has it led inverted, the same has been reported on the ov51x-jpeg list for another creative cam. This patch fixes this without changing the behaviour for other cams. Priority: normal Signed-off-by: Hans de Goede --- linux/drivers/media/video/gspca/ov519.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/ov519.c b/linux/drivers/media/video/gspca/ov519.c index 8849a70a6..6dfe562a2 100644 --- a/linux/drivers/media/video/gspca/ov519.c +++ b/linux/drivers/media/video/gspca/ov519.c @@ -58,6 +58,10 @@ struct sd { #define BRIDGE_OV518 2 #define BRIDGE_OV518PLUS 3 #define BRIDGE_OV519 4 +#define BRIDGE_MASK 7 + + char invert_led; +#define BRIDGE_INVERT_LED 8 /* Determined by sensor type */ __u8 sif; @@ -1468,6 +1472,9 @@ static int ov6xx0_configure(struct sd *sd) /* Turns on or off the LED. Only has an effect with OV511+/OV518(+)/OV519 */ static void ov51x_led_control(struct sd *sd, int on) { + if (sd->invert_led) + on = !on; + switch (sd->bridge) { /* OV511 has no LED control */ case BRIDGE_OV511PLUS: @@ -1650,7 +1657,8 @@ static int sd_config(struct gspca_dev *gspca_dev, struct cam *cam; int ret = 0; - sd->bridge = id->driver_info; + sd->bridge = id->driver_info & BRIDGE_MASK; + sd->invert_led = id->driver_info & BRIDGE_INVERT_LED; switch (sd->bridge) { case BRIDGE_OV518: @@ -2865,8 +2873,10 @@ static const __devinitdata struct usb_device_id device_table[] = { {USB_DEVICE(0x041e, 0x405f), .driver_info = BRIDGE_OV519 }, {USB_DEVICE(0x041e, 0x4060), .driver_info = BRIDGE_OV519 }, {USB_DEVICE(0x041e, 0x4061), .driver_info = BRIDGE_OV519 }, - {USB_DEVICE(0x041e, 0x4064), .driver_info = BRIDGE_OV519 }, - {USB_DEVICE(0x041e, 0x4068), .driver_info = BRIDGE_OV519 }, + {USB_DEVICE(0x041e, 0x4064), + .driver_info = BRIDGE_OV519 | BRIDGE_INVERT_LED }, + {USB_DEVICE(0x041e, 0x4068), + .driver_info = BRIDGE_OV519 | BRIDGE_INVERT_LED }, {USB_DEVICE(0x045e, 0x028c), .driver_info = BRIDGE_OV519 }, {USB_DEVICE(0x054c, 0x0154), .driver_info = BRIDGE_OV519 }, {USB_DEVICE(0x054c, 0x0155), .driver_info = BRIDGE_OV519 }, -- cgit v1.2.3 From b66ae47f478b899e8be15db137f7dae5353c385d Mon Sep 17 00:00:00 2001 From: "hans@rhel5-devel.localdomain" Date: Sun, 14 Jun 2009 11:26:49 +0200 Subject: gspca_ov519: Fix 320x240 with ov7660 sensor From: Hans de Goede As reported on the ov51x-jpeg list, and as I can confirm with my own cam the ov7670 in 320x240 has a number of broken columns of pixels at the left of the picture. This was not present in the old driver as it always used 640x480 and did software downscaling (took me a while to figure that one out). The fix adds a sensor specific if in so far sensor neutral code :( But this is the only way to fix this, this cannot be fixed by only changing sensor registers. Priority: normal Signed-off-by: Hans de Goede --- linux/drivers/media/video/gspca/ov519.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/ov519.c b/linux/drivers/media/video/gspca/ov519.c index 6dfe562a2..129941693 100644 --- a/linux/drivers/media/video/gspca/ov519.c +++ b/linux/drivers/media/video/gspca/ov519.c @@ -1977,7 +1977,11 @@ static int ov519_mode_init_regs(struct sd *sd) reg_w(sd, OV519_R10_H_SIZE, sd->gspca_dev.width >> 4); reg_w(sd, OV519_R11_V_SIZE, sd->gspca_dev.height >> 3); - reg_w(sd, OV519_R12_X_OFFSETL, 0x00); + if (sd->sensor == SEN_OV7670 && + sd->gspca_dev.cam.cam_mode[sd->gspca_dev.curr_mode].priv) + reg_w(sd, OV519_R12_X_OFFSETL, 0x04); + else + reg_w(sd, OV519_R12_X_OFFSETL, 0x00); reg_w(sd, OV519_R13_X_OFFSETH, 0x00); reg_w(sd, OV519_R14_Y_OFFSETL, 0x00); reg_w(sd, OV519_R15_Y_OFFSETH, 0x00); @@ -2339,7 +2343,7 @@ static int set_ov_sensor_window(struct sd *sd) if (qvga) { /* QVGA from ov7670.c by * Jonathan Corbet */ hstart = 164; - hstop = 20; + hstop = 28; vstart = 14; vstop = 494; } else { /* VGA */ -- cgit v1.2.3 From dec7dfbe6bb0db2c291c8ce8578fd560c466924c Mon Sep 17 00:00:00 2001 From: "hans@rhel5-devel.localdomain" Date: Sun, 14 Jun 2009 11:32:52 +0200 Subject: gspca_ov519: Better default contrast for ov6630 From: Hans de Goede Hmm, another one with an extra if (life sucks) the default contrast really is no good for the ov6630, it isn't even high enough in full daylight, this gives the ov6630 a different initial value for a better out of the box experience. Priority: normal Signed-off-by: Hans de Goede --- linux/drivers/media/video/gspca/ov519.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/ov519.c b/linux/drivers/media/video/gspca/ov519.c index 129941693..4244819f1 100644 --- a/linux/drivers/media/video/gspca/ov519.c +++ b/linux/drivers/media/video/gspca/ov519.c @@ -1740,7 +1740,10 @@ static int sd_config(struct gspca_dev *gspca_dev, break; } sd->brightness = BRIGHTNESS_DEF; - sd->contrast = CONTRAST_DEF; + if (sd->sensor == SEN_OV6630 || sd->sensor == SEN_OV66308AF) + sd->contrast = 200; /* The default is too low for the ov6630 */ + else + sd->contrast = CONTRAST_DEF; sd->colors = COLOR_DEF; sd->hflip = HFLIP_DEF; sd->vflip = VFLIP_DEF; -- cgit v1.2.3 From 3ba85cbcd64cd86bc6b719e3e07090b40c910c7e Mon Sep 17 00:00:00 2001 From: "hans@rhel5-devel.localdomain" Date: Sun, 14 Jun 2009 11:45:50 +0200 Subject: gspca_ov519: add support for the ov511 bridge From: Hans de Goede gspca_ov519: add support for the ov511 bridge Priority: normal Signed-off-by: Hans de Goede --- linux/drivers/media/video/gspca/ov519.c | 537 +++++++++++++++++++++++++++++++- 1 file changed, 524 insertions(+), 13 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/ov519.c b/linux/drivers/media/video/gspca/ov519.c index 4244819f1..6b91921ce 100644 --- a/linux/drivers/media/video/gspca/ov519.c +++ b/linux/drivers/media/video/gspca/ov519.c @@ -76,8 +76,8 @@ struct sd { __u8 stopped; /* Streaming is temporarily paused */ - __u8 frame_rate; /* current Framerate (OV519 only) */ - __u8 clockdiv; /* clockdiv override for OV519 only */ + __u8 frame_rate; /* current Framerate */ + __u8 clockdiv; /* clockdiv override */ char sensor; /* Type of image sensor chip (SEN_*) */ #define SEN_UNKNOWN 0 @@ -304,17 +304,77 @@ static const struct v4l2_pix_format ov518_sif_mode[] = { .priv = 0}, }; +static const struct v4l2_pix_format ov511_vga_mode[] = { + {320, 240, V4L2_PIX_FMT_OV511, V4L2_FIELD_NONE, + .bytesperline = 320, + .sizeimage = 320 * 240 * 3, + .colorspace = V4L2_COLORSPACE_JPEG, + .priv = 1}, + {640, 480, V4L2_PIX_FMT_OV511, V4L2_FIELD_NONE, + .bytesperline = 640, + .sizeimage = 640 * 480 * 2, + .colorspace = V4L2_COLORSPACE_JPEG, + .priv = 0}, +}; +static const struct v4l2_pix_format ov511_sif_mode[] = { + {160, 120, V4L2_PIX_FMT_OV511, V4L2_FIELD_NONE, + .bytesperline = 160, + .sizeimage = 40000, + .colorspace = V4L2_COLORSPACE_JPEG, + .priv = 3}, + {176, 144, V4L2_PIX_FMT_OV511, V4L2_FIELD_NONE, + .bytesperline = 176, + .sizeimage = 40000, + .colorspace = V4L2_COLORSPACE_JPEG, + .priv = 1}, + {320, 240, V4L2_PIX_FMT_OV511, V4L2_FIELD_NONE, + .bytesperline = 320, + .sizeimage = 320 * 240 * 3, + .colorspace = V4L2_COLORSPACE_JPEG, + .priv = 2}, + {352, 288, V4L2_PIX_FMT_OV511, V4L2_FIELD_NONE, + .bytesperline = 352, + .sizeimage = 352 * 288 * 3, + .colorspace = V4L2_COLORSPACE_JPEG, + .priv = 0}, +}; /* Registers common to OV511 / OV518 */ +#define R51x_FIFO_PSIZE 0x30 /* 2 bytes wide w/ OV518(+) */ #define R51x_SYS_RESET 0x50 + /* Reset type flags */ + #define OV511_RESET_OMNICE 0x08 #define R51x_SYS_INIT 0x53 #define R51x_SYS_SNAP 0x52 #define R51x_SYS_CUST_ID 0x5F #define R51x_COMP_LUT_BEGIN 0x80 /* OV511 Camera interface register numbers */ +#define R511_CAM_DELAY 0x10 +#define R511_CAM_EDGE 0x11 +#define R511_CAM_PXCNT 0x12 +#define R511_CAM_LNCNT 0x13 +#define R511_CAM_PXDIV 0x14 +#define R511_CAM_LNDIV 0x15 +#define R511_CAM_UV_EN 0x16 +#define R511_CAM_LINE_MODE 0x17 +#define R511_CAM_OPTS 0x18 + +#define R511_SNAP_FRAME 0x19 +#define R511_SNAP_PXCNT 0x1A +#define R511_SNAP_LNCNT 0x1B +#define R511_SNAP_PXDIV 0x1C +#define R511_SNAP_LNDIV 0x1D +#define R511_SNAP_UV_EN 0x1E +#define R511_SNAP_UV_EN 0x1E +#define R511_SNAP_OPTS 0x1F + +#define R511_DRAM_FLOW_CTL 0x20 +#define R511_FIFO_OPTS 0x31 +#define R511_I2C_CTL 0x40 #define R511_SYS_LED_CTL 0x55 /* OV511+ only */ -#define OV511_RESET_NOREGS 0x3F /* All but OV511 & regs */ +#define R511_COMP_EN 0x78 +#define R511_COMP_LUT_EN 0x79 /* OV518 Camera interface register numbers */ #define R518_GPIO_OUT 0x56 /* OV518(+) only */ @@ -1079,13 +1139,132 @@ static int ov518_reg_w32(struct sd *sd, __u16 index, u32 value, int n) return ret; } +static int ov511_i2c_w(struct sd *sd, __u8 reg, __u8 value) +{ + int rc, retries; + + PDEBUG(D_USBO, "i2c 0x%02x -> [0x%02x]", value, reg); + + /* Three byte write cycle */ + for (retries = 6; ; ) { + /* Select camera register */ + rc = reg_w(sd, R51x_I2C_SADDR_3, reg); + if (rc < 0) + return rc; + + /* Write "value" to I2C data port of OV511 */ + rc = reg_w(sd, R51x_I2C_DATA, value); + if (rc < 0) + return rc; + + /* Initiate 3-byte write cycle */ + rc = reg_w(sd, R511_I2C_CTL, 0x01); + if (rc < 0) + return rc; + + do + rc = reg_r(sd, R511_I2C_CTL); + while (rc > 0 && ((rc & 1) == 0)); /* Retry until idle */ + + if (rc < 0) + return rc; + + if ((rc & 2) == 0) /* Ack? */ + break; +#if 0 + /* I2C abort */ + reg_w(sd, R511_I2C_CTL, 0x10); +#endif + if (--retries < 0) { + PDEBUG(D_USBO, "i2c write retries exhausted"); + return -1; + } + } + + return 0; +} + +static int ov511_i2c_r(struct sd *sd, __u8 reg) +{ + int rc, value, retries; + + /* Two byte write cycle */ + for (retries = 6; ; ) { + /* Select camera register */ + rc = reg_w(sd, R51x_I2C_SADDR_2, reg); + if (rc < 0) + return rc; + + /* Initiate 2-byte write cycle */ + rc = reg_w(sd, R511_I2C_CTL, 0x03); + if (rc < 0) + return rc; + + do + rc = reg_r(sd, R511_I2C_CTL); + while (rc > 0 && ((rc & 1) == 0)); /* Retry until idle */ + + if (rc < 0) + return rc; + + if ((rc & 2) == 0) /* Ack? */ + break; + + /* I2C abort */ + reg_w(sd, R511_I2C_CTL, 0x10); + + if (--retries < 0) { + PDEBUG(D_USBI, "i2c write retries exhausted"); + return -1; + } + } + + /* Two byte read cycle */ + for (retries = 6; ; ) { + /* Initiate 2-byte read cycle */ + rc = reg_w(sd, R511_I2C_CTL, 0x05); + if (rc < 0) + return rc; + + do + rc = reg_r(sd, R511_I2C_CTL); + while (rc > 0 && ((rc & 1) == 0)); /* Retry until idle */ + + if (rc < 0) + return rc; + + if ((rc & 2) == 0) /* Ack? */ + break; + + /* I2C abort */ + rc = reg_w(sd, R511_I2C_CTL, 0x10); + if (rc < 0) + return rc; + + if (--retries < 0) { + PDEBUG(D_USBI, "i2c read retries exhausted"); + return -1; + } + } + + value = reg_r(sd, R51x_I2C_DATA); + + PDEBUG(D_USBI, "i2c [0x%02X] -> 0x%02X", reg, value); + + /* This is needed to make i2c_w() work */ + rc = reg_w(sd, R511_I2C_CTL, 0x05); + if (rc < 0) + return rc; + + return value; +} /* * The OV518 I2C I/O procedure is different, hence, this function. * This is normally only called from i2c_w(). Note that this function * always succeeds regardless of whether the sensor is present and working. */ -static int i2c_w(struct sd *sd, +static int ov518_i2c_w(struct sd *sd, __u8 reg, __u8 value) { @@ -1120,7 +1299,7 @@ static int i2c_w(struct sd *sd, * This is normally only called from i2c_r(). Note that this function * always succeeds regardless of whether the sensor is present and working. */ -static int i2c_r(struct sd *sd, __u8 reg) +static int ov518_i2c_r(struct sd *sd, __u8 reg) { int rc, value; @@ -1143,6 +1322,34 @@ static int i2c_r(struct sd *sd, __u8 reg) return value; } +static int i2c_w(struct sd *sd, __u8 reg, __u8 value) +{ + switch (sd->bridge) { + case BRIDGE_OV511: + case BRIDGE_OV511PLUS: + return ov511_i2c_w(sd, reg, value); + case BRIDGE_OV518: + case BRIDGE_OV518PLUS: + case BRIDGE_OV519: + return ov518_i2c_w(sd, reg, value); + } + return -1; /* Should never happen */ +} + +static int i2c_r(struct sd *sd, __u8 reg) +{ + switch (sd->bridge) { + case BRIDGE_OV511: + case BRIDGE_OV511PLUS: + return ov511_i2c_r(sd, reg); + case BRIDGE_OV518: + case BRIDGE_OV518PLUS: + case BRIDGE_OV519: + return ov518_i2c_r(sd, reg); + } + return -1; /* Should never happen */ +} + /* Writes bits at positions specified by mask to an I2C reg. Bits that are in * the same position as 1's in "mask" are cleared and set to "value". Bits * that are in the same position as 0's in "mask" are preserved, regardless @@ -1490,9 +1697,31 @@ static void ov51x_led_control(struct sd *sd, int on) } } -/* OV518 quantization tables are 8x4 (instead of 8x8) */ -static int ov518_upload_quan_tables(struct sd *sd) +static int ov51x_upload_quan_tables(struct sd *sd) { + const unsigned char yQuanTable511[] = { + 0, 1, 1, 2, 2, 3, 3, 4, + 1, 1, 1, 2, 2, 3, 4, 4, + 1, 1, 2, 2, 3, 4, 4, 4, + 2, 2, 2, 3, 4, 4, 4, 4, + 2, 2, 3, 4, 4, 5, 5, 5, + 3, 3, 4, 4, 5, 5, 5, 5, + 3, 4, 4, 4, 5, 5, 5, 5, + 4, 4, 4, 4, 5, 5, 5, 5 + }; + + const unsigned char uvQuanTable511[] = { + 0, 2, 2, 3, 4, 4, 4, 4, + 2, 2, 2, 4, 4, 4, 4, 4, + 2, 2, 3, 4, 4, 4, 4, 4, + 3, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4 + }; + + /* OV518 quantization tables are 8x4 (instead of 8x8) */ const unsigned char yQuanTable518[] = { 5, 4, 5, 6, 6, 7, 7, 7, 5, 5, 5, 5, 6, 7, 7, 7, @@ -1507,14 +1736,23 @@ static int ov518_upload_quan_tables(struct sd *sd) 7, 7, 7, 7, 7, 7, 8, 8 }; - const unsigned char *pYTable = yQuanTable518; - const unsigned char *pUVTable = uvQuanTable518; + const unsigned char *pYTable, *pUVTable; unsigned char val0, val1; - int i, rc, reg = R51x_COMP_LUT_BEGIN; + int i, size, rc, reg = R51x_COMP_LUT_BEGIN; PDEBUG(D_PROBE, "Uploading quantization tables"); - for (i = 0; i < 16; i++) { + if (sd->bridge == BRIDGE_OV511 || sd->bridge == BRIDGE_OV511PLUS) { + pYTable = yQuanTable511; + pUVTable = uvQuanTable511; + size = 32; + } else { + pYTable = yQuanTable518; + pUVTable = uvQuanTable518; + size = 16; + } + + for (i = 0; i < size; i++) { val0 = *pYTable++; val1 = *pYTable++; val0 &= 0x0f; @@ -1529,7 +1767,7 @@ static int ov518_upload_quan_tables(struct sd *sd) val0 &= 0x0f; val1 &= 0x0f; val0 |= val1 << 4; - rc = reg_w(sd, reg + 16, val0); + rc = reg_w(sd, reg + size, val0); if (rc < 0) return rc; @@ -1539,6 +1777,87 @@ static int ov518_upload_quan_tables(struct sd *sd) return 0; } +/* This initializes the OV511/OV511+ and the sensor */ +static int ov511_configure(struct gspca_dev *gspca_dev) +{ + struct sd *sd = (struct sd *) gspca_dev; + int rc; + + /* For 511 and 511+ */ + const struct ov_regvals init_511[] = { + { R51x_SYS_RESET, 0x7f }, + { R51x_SYS_INIT, 0x01 }, + { R51x_SYS_RESET, 0x7f }, + { R51x_SYS_INIT, 0x01 }, + { R51x_SYS_RESET, 0x3f }, + { R51x_SYS_INIT, 0x01 }, + { R51x_SYS_RESET, 0x3d }, + }; + + const struct ov_regvals norm_511[] = { + { R511_DRAM_FLOW_CTL, 0x01 }, + { R51x_SYS_SNAP, 0x00 }, + { R51x_SYS_SNAP, 0x02 }, + { R51x_SYS_SNAP, 0x00 }, + { R511_FIFO_OPTS, 0x1f }, + { R511_COMP_EN, 0x00 }, + { R511_COMP_LUT_EN, 0x03 }, + }; + + const struct ov_regvals norm_511_p[] = { + { R511_DRAM_FLOW_CTL, 0xff }, + { R51x_SYS_SNAP, 0x00 }, + { R51x_SYS_SNAP, 0x02 }, + { R51x_SYS_SNAP, 0x00 }, + { R511_FIFO_OPTS, 0xff }, + { R511_COMP_EN, 0x00 }, + { R511_COMP_LUT_EN, 0x03 }, + }; + + const struct ov_regvals compress_511[] = { + { 0x70, 0x1f }, + { 0x71, 0x05 }, + { 0x72, 0x06 }, + { 0x73, 0x06 }, + { 0x74, 0x14 }, + { 0x75, 0x03 }, + { 0x76, 0x04 }, + { 0x77, 0x04 }, + }; + + PDEBUG(D_PROBE, "Device custom id %x", reg_r(sd, R51x_SYS_CUST_ID)); + + rc = write_regvals(sd, init_511, ARRAY_SIZE(init_511)); + if (rc < 0) + return rc; + + switch (sd->bridge) { + case BRIDGE_OV511: + rc = write_regvals(sd, norm_511, ARRAY_SIZE(norm_511)); + if (rc < 0) + return rc; + break; + case BRIDGE_OV511PLUS: + rc = write_regvals(sd, norm_511_p, ARRAY_SIZE(norm_511_p)); + if (rc < 0) + return rc; + break; + } + + /* Init compression */ + rc = write_regvals(sd, compress_511, ARRAY_SIZE(compress_511)); + if (rc < 0) + return rc; + + rc = ov51x_upload_quan_tables(sd); + if (rc < 0) { + PDEBUG(D_ERR, "Error uploading quantization tables"); + return rc; + } + + return 0; +} + /* This initializes the OV518/OV518+ and the sensor */ static int ov518_configure(struct gspca_dev *gspca_dev) { @@ -1615,7 +1934,7 @@ static int ov518_configure(struct gspca_dev *gspca_dev) break; } - rc = ov518_upload_quan_tables(sd); + rc = ov51x_upload_quan_tables(sd); if (rc < 0) { PDEBUG(D_ERR, "Error uploading quantization tables"); return rc; @@ -1661,6 +1980,10 @@ static int sd_config(struct gspca_dev *gspca_dev, sd->invert_led = id->driver_info & BRIDGE_INVERT_LED; switch (sd->bridge) { + case BRIDGE_OV511: + case BRIDGE_OV511PLUS: + ret = ov511_configure(gspca_dev); + break; case BRIDGE_OV518: case BRIDGE_OV518PLUS: ret = ov518_configure(gspca_dev); @@ -1719,6 +2042,16 @@ static int sd_config(struct gspca_dev *gspca_dev, cam = &gspca_dev->cam; switch (sd->bridge) { + case BRIDGE_OV511: + case BRIDGE_OV511PLUS: + if (!sd->sif) { + cam->cam_mode = ov511_vga_mode; + cam->nmodes = ARRAY_SIZE(ov511_vga_mode); + } else { + cam->cam_mode = ov511_sif_mode; + cam->nmodes = ARRAY_SIZE(ov511_sif_mode); + } + break; case BRIDGE_OV518: case BRIDGE_OV518PLUS: if (!sd->sif) { @@ -1810,6 +2143,126 @@ static int sd_init(struct gspca_dev *gspca_dev) return 0; } +/* Set up the OV511/OV511+ with the given image parameters. + * + * Do not put any sensor-specific code in here (including I2C I/O functions) + */ +static int ov511_mode_init_regs(struct sd *sd) +{ + int hsegs, vsegs, packet_size, fps, needed; + int interlaced = 0; + struct usb_host_interface *alt; + struct usb_interface *intf; + + intf = usb_ifnum_to_if(sd->gspca_dev.dev, sd->gspca_dev.iface); + alt = usb_altnum_to_altsetting(intf, sd->gspca_dev.alt); + if (!alt) { + PDEBUG(D_ERR, "Couldn't get altsetting"); + return -EIO; + } + + packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize); + reg_w(sd, R51x_FIFO_PSIZE, packet_size >> 5); + + reg_w(sd, R511_CAM_UV_EN, 0x01); + reg_w(sd, R511_SNAP_UV_EN, 0x01); + reg_w(sd, R511_SNAP_OPTS, 0x03); + + /* Here I'm assuming that snapshot size == image size. + * I hope that's always true. --claudio + */ + hsegs = (sd->gspca_dev.width >> 3) - 1; + vsegs = (sd->gspca_dev.height >> 3) - 1; + + reg_w(sd, R511_CAM_PXCNT, hsegs); + reg_w(sd, R511_CAM_LNCNT, vsegs); + reg_w(sd, R511_CAM_PXDIV, 0x00); + reg_w(sd, R511_CAM_LNDIV, 0x00); + + /* YUV420, low pass filter on */ + reg_w(sd, R511_CAM_OPTS, 0x03); + + /* Snapshot additions */ + reg_w(sd, R511_SNAP_PXCNT, hsegs); + reg_w(sd, R511_SNAP_LNCNT, vsegs); + reg_w(sd, R511_SNAP_PXDIV, 0x00); + reg_w(sd, R511_SNAP_LNDIV, 0x00); + + /******** Set the framerate ********/ + if (frame_rate > 0) + sd->frame_rate = frame_rate; + + switch (sd->sensor) { + case SEN_OV6620: + /* No framerate control, doesn't like higher rates yet */ + sd->clockdiv = 3; + break; + + /* Note once the FIXME's in mode_init_ov_sensor_regs() are fixed + for more sensors we need to do this for them too */ + case SEN_OV7620: + case SEN_OV7640: + if (sd->gspca_dev.width == 320) + interlaced = 1; + /* Fall through */ + case SEN_OV6630: + case SEN_OV76BE: + case SEN_OV7610: + case SEN_OV7670: + switch (sd->frame_rate) { + case 30: + case 25: + /* Not enough bandwidth to do 640x480 @ 30 fps */ + if (sd->gspca_dev.width != 640) { + sd->clockdiv = 0; + break; + } + /* Fall through for 640x480 case */ + default: +/* case 20: */ +/* case 15: */ + sd->clockdiv = 1; + break; + case 10: + sd->clockdiv = 2; + break; + case 5: + sd->clockdiv = 5; + break; + } + if (interlaced) { + sd->clockdiv = (sd->clockdiv + 1) * 2 - 1; + /* Higher then 10 does not work */ + if (sd->clockdiv > 10) + sd->clockdiv = 10; + } + break; + + case SEN_OV8610: + /* No framerate control ?? */ + sd->clockdiv = 0; + break; + } + + /* Check if we have enough bandwidth to disable compression */ + fps = (interlaced ? 60 : 30) / (sd->clockdiv + 1) + 1; + needed = fps * sd->gspca_dev.width * sd->gspca_dev.height * 3 / 2; + /* 1400 is a conservative estimate of the max nr of isoc packets/sec */ + if (needed > 1400 * packet_size) { + /* Enable Y and UV quantization and compression */ + reg_w(sd, R511_COMP_EN, 0x07); + reg_w(sd, R511_COMP_LUT_EN, 0x03); + } else { + reg_w(sd, R511_COMP_EN, 0x06); + reg_w(sd, R511_COMP_LUT_EN, 0x00); + } + + reg_w(sd, R51x_SYS_RESET, OV511_RESET_OMNICE); + reg_w(sd, R51x_SYS_RESET, 0); + + return 0; +} + /* Sets up the OV518/OV518+ with the given image parameters * * OV518 needs a completely different approach, until we can figure out what @@ -2388,6 +2841,10 @@ static int sd_start(struct gspca_dev *gspca_dev) int ret = 0; switch (sd->bridge) { + case BRIDGE_OV511: + case BRIDGE_OV511PLUS: + ret = ov511_mode_init_regs(sd); + break; case BRIDGE_OV518: case BRIDGE_OV518PLUS: ret = ov518_mode_init_regs(sd); @@ -2428,6 +2885,56 @@ static void sd_stopN(struct gspca_dev *gspca_dev) ov51x_led_control(sd, 0); } +static void ov511_pkt_scan(struct gspca_dev *gspca_dev, + struct gspca_frame *frame, /* target */ + __u8 *in, /* isoc packet */ + int len) /* iso packet length */ +{ + struct sd *sd = (struct sd *) gspca_dev; + + /* SOF/EOF packets have 1st to 8th bytes zeroed and the 9th + * byte non-zero. The EOF packet has image width/height in the + * 10th and 11th bytes. The 9th byte is given as follows: + * + * bit 7: EOF + * 6: compression enabled + * 5: 422/420/400 modes + * 4: 422/420/400 modes + * 3: 1 + * 2: snapshot button on + * 1: snapshot frame + * 0: even/odd field + */ + if (!(in[0] | in[1] | in[2] | in[3] | in[4] | in[5] | in[6] | in[7]) && + (in[8] & 0x08)) { + if (in[8] & 0x80) { + /* Frame end */ + if ((in[9] + 1) * 8 != gspca_dev->width || + (in[10] + 1) * 8 != gspca_dev->height) { + PDEBUG(D_ERR, "Invalid frame size, got: %dx%d," + " requested: %dx%d\n", + (in[9] + 1) * 8, (in[10] + 1) * 8, + gspca_dev->width, gspca_dev->height); + gspca_dev->last_packet_type = DISCARD_PACKET; + return; + } + /* Add 11 byte footer to frame, might be usefull */ + gspca_frame_add(gspca_dev, LAST_PACKET, frame, in, 11); + return; + } else { + /* Frame start */ + gspca_frame_add(gspca_dev, FIRST_PACKET, frame, in, 0); + sd->packet_nr = 0; + } + } + + /* Ignore the packet number */ + len--; + + /* intermediate packet */ + gspca_frame_add(gspca_dev, INTER_PACKET, frame, in, len); +} + static void ov518_pkt_scan(struct gspca_dev *gspca_dev, struct gspca_frame *frame, /* target */ __u8 *data, /* isoc packet */ @@ -2520,6 +3027,7 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, switch (sd->bridge) { case BRIDGE_OV511: case BRIDGE_OV511PLUS: + ov511_pkt_scan(gspca_dev, frame, data, len); break; case BRIDGE_OV518: case BRIDGE_OV518PLUS: @@ -2887,12 +3395,15 @@ static const __devinitdata struct usb_device_id device_table[] = { {USB_DEVICE(0x045e, 0x028c), .driver_info = BRIDGE_OV519 }, {USB_DEVICE(0x054c, 0x0154), .driver_info = BRIDGE_OV519 }, {USB_DEVICE(0x054c, 0x0155), .driver_info = BRIDGE_OV519 }, + {USB_DEVICE(0x05a9, 0x0511), .driver_info = BRIDGE_OV511 }, {USB_DEVICE(0x05a9, 0x0518), .driver_info = BRIDGE_OV518 }, {USB_DEVICE(0x05a9, 0x0519), .driver_info = BRIDGE_OV519 }, {USB_DEVICE(0x05a9, 0x0530), .driver_info = BRIDGE_OV519 }, {USB_DEVICE(0x05a9, 0x4519), .driver_info = BRIDGE_OV519 }, {USB_DEVICE(0x05a9, 0x8519), .driver_info = BRIDGE_OV519 }, + {USB_DEVICE(0x05a9, 0xa511), .driver_info = BRIDGE_OV511PLUS }, {USB_DEVICE(0x05a9, 0xa518), .driver_info = BRIDGE_OV518PLUS }, + {USB_DEVICE(0x0813, 0x0002), .driver_info = BRIDGE_OV511PLUS }, {} }; -- cgit v1.2.3 From 1d881651c4e9931b20895a9a124e06be1a15e759 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 14 Jun 2009 11:47:35 +0200 Subject: smscoreapi: fix compile warning From: Hans Verkuil gcc 4.3.1 generates this warning: v4l/smscoreapi.c: In function 'smscore_gpio_configure': v4l/smscoreapi.c:1481: warning: 'GroupNum' may be used uninitialized in this function v4l/smscoreapi.c:1480: warning: 'TranslatedPinNum' may be used uninitialized in this function While in practice this will not happen, it is something that the compiler can't determine. Initializing these two local variables to 0 suppresses this warning. Priority: normal Signed-off-by: Hans Verkuil CC: Udi Atar Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/siano/smscoreapi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/siano/smscoreapi.c b/linux/drivers/media/dvb/siano/smscoreapi.c index e513408fc..54f59f24e 100644 --- a/linux/drivers/media/dvb/siano/smscoreapi.c +++ b/linux/drivers/media/dvb/siano/smscoreapi.c @@ -1477,8 +1477,8 @@ int smscore_gpio_configure(struct smscore_device_t *coredev, u8 PinNum, struct smscore_gpio_config *pGpioConfig) { u32 totalLen; - u32 TranslatedPinNum; - u32 GroupNum; + u32 TranslatedPinNum = 0; + u32 GroupNum = 0; u32 ElectricChar; u32 groupCfg; void *buffer; -- cgit v1.2.3 From 83b57e1043e6047fd330998b8d782ef1845d83d7 Mon Sep 17 00:00:00 2001 From: "hans@rhel5-devel.localdomain" Date: Mon, 15 Jun 2009 00:10:40 +0200 Subject: gspca_ov519: Fix ov518+ with OV7620AE (Trust spacecam 320) From: Hans de Goede gspca_ov519: Fix ov518+ with OV7620AE (Trust spacecam 320) Priority: normal Signed-off-by: Hans de Goede --- linux/drivers/media/video/gspca/ov519.c | 96 ++++++++++++++++++--------------- 1 file changed, 53 insertions(+), 43 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/ov519.c b/linux/drivers/media/video/gspca/ov519.c index 6b91921ce..9b7dc5b3b 100644 --- a/linux/drivers/media/video/gspca/ov519.c +++ b/linux/drivers/media/video/gspca/ov519.c @@ -269,37 +269,43 @@ static const struct v4l2_pix_format ov519_sif_mode[] = { .priv = 0}, }; +/* Note some of the sizeimage values for the ov511 / ov518 may seem + larger then necessary, however they need to be this big as the ov511 / + ov518 always fills the entire isoc frame, using 0 padding bytes when + it doesn't have any data. So with low framerates the amount of data + transfered can become quite large (libv4l will remove all the 0 padding + in userspace). */ static const struct v4l2_pix_format ov518_vga_mode[] = { {320, 240, V4L2_PIX_FMT_OV518, V4L2_FIELD_NONE, .bytesperline = 320, - .sizeimage = 320 * 240 * 3 / 8 + 590, + .sizeimage = 320 * 240 * 3, .colorspace = V4L2_COLORSPACE_JPEG, .priv = 1}, {640, 480, V4L2_PIX_FMT_OV518, V4L2_FIELD_NONE, .bytesperline = 640, - .sizeimage = 640 * 480 * 3 / 8 + 590, + .sizeimage = 640 * 480 * 2, .colorspace = V4L2_COLORSPACE_JPEG, .priv = 0}, }; static const struct v4l2_pix_format ov518_sif_mode[] = { {160, 120, V4L2_PIX_FMT_OV518, V4L2_FIELD_NONE, .bytesperline = 160, - .sizeimage = 40000, + .sizeimage = 70000, .colorspace = V4L2_COLORSPACE_JPEG, .priv = 3}, {176, 144, V4L2_PIX_FMT_OV518, V4L2_FIELD_NONE, .bytesperline = 176, - .sizeimage = 40000, + .sizeimage = 70000, .colorspace = V4L2_COLORSPACE_JPEG, .priv = 1}, {320, 240, V4L2_PIX_FMT_OV518, V4L2_FIELD_NONE, .bytesperline = 320, - .sizeimage = 320 * 240 * 3 / 8 + 590, + .sizeimage = 320 * 240 * 3, .colorspace = V4L2_COLORSPACE_JPEG, .priv = 2}, {352, 288, V4L2_PIX_FMT_OV518, V4L2_FIELD_NONE, .bytesperline = 352, - .sizeimage = 352 * 288 * 3 / 8 + 590, + .sizeimage = 352 * 288 * 3, .colorspace = V4L2_COLORSPACE_JPEG, .priv = 0}, }; @@ -319,12 +325,12 @@ static const struct v4l2_pix_format ov511_vga_mode[] = { static const struct v4l2_pix_format ov511_sif_mode[] = { {160, 120, V4L2_PIX_FMT_OV511, V4L2_FIELD_NONE, .bytesperline = 160, - .sizeimage = 40000, + .sizeimage = 70000, .colorspace = V4L2_COLORSPACE_JPEG, .priv = 3}, {176, 144, V4L2_PIX_FMT_OV511, V4L2_FIELD_NONE, .bytesperline = 176, - .sizeimage = 40000, + .sizeimage = 70000, .colorspace = V4L2_COLORSPACE_JPEG, .priv = 1}, {320, 240, V4L2_PIX_FMT_OV511, V4L2_FIELD_NONE, @@ -698,7 +704,7 @@ static const struct ov_i2c_regvals norm_7620[] = { { 0x23, 0x00 }, { 0x26, 0xa2 }, { 0x27, 0xea }, - { 0x28, 0x20 }, + { 0x28, 0x22 }, /* Was 0x20, bit1 enables a 2x gain which we need */ { 0x29, 0x00 }, { 0x2a, 0x10 }, { 0x2b, 0x00 }, @@ -1529,7 +1535,6 @@ static int ov8xx0_configure(struct sd *sd) } /* Set sensor-specific vars */ -/* sd->sif = 0; already done */ return 0; } @@ -1566,15 +1571,13 @@ static int ov7xx0_configure(struct sd *sd) } } else if ((rc & 3) == 1) { /* I don't know what's different about the 76BE yet. */ - if (i2c_r(sd, 0x15) & 1) + if (i2c_r(sd, 0x15) & 1) { PDEBUG(D_PROBE, "Sensor is an OV7620AE"); - else + sd->sensor = SEN_OV7620; + } else { PDEBUG(D_PROBE, "Sensor is an OV76BE"); - - /* OV511+ will return all zero isoc data unless we - * configure the sensor as a 7620. Someone needs to - * find the exact reg. setting that causes this. */ - sd->sensor = SEN_OV76BE; + sd->sensor = SEN_OV76BE; + } } else if ((rc & 3) == 0) { /* try to read product id registers */ high = i2c_r(sd, 0x0a); @@ -1620,7 +1623,6 @@ static int ov7xx0_configure(struct sd *sd) } /* Set sensor-specific vars */ -/* sd->sif = 0; already done */ return 0; } @@ -2202,11 +2204,11 @@ static int ov511_mode_init_regs(struct sd *sd) for more sensors we need to do this for them too */ case SEN_OV7620: case SEN_OV7640: + case SEN_OV76BE: if (sd->gspca_dev.width == 320) interlaced = 1; /* Fall through */ case SEN_OV6630: - case SEN_OV76BE: case SEN_OV7610: case SEN_OV7670: switch (sd->frame_rate) { @@ -2272,7 +2274,19 @@ static int ov511_mode_init_regs(struct sd *sd) */ static int ov518_mode_init_regs(struct sd *sd) { - int hsegs, vsegs; + int hsegs, vsegs, packet_size; + struct usb_host_interface *alt; + struct usb_interface *intf; + + intf = usb_ifnum_to_if(sd->gspca_dev.dev, sd->gspca_dev.iface); + alt = usb_altnum_to_altsetting(intf, sd->gspca_dev.alt); + if (!alt) { + PDEBUG(D_ERR, "Couldn't get altsetting"); + return -EIO; + } + + packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize); + ov518_reg_w32(sd, R51x_FIFO_PSIZE, packet_size & ~7, 2); /******** Set the mode ********/ @@ -2309,20 +2323,30 @@ static int ov518_mode_init_regs(struct sd *sd) /* Windows driver does this here; who knows why */ reg_w(sd, 0x2f, 0x80); - /******** Set the framerate (to 30 FPS) ********/ - if (sd->bridge == BRIDGE_OV518PLUS) - sd->clockdiv = 1; - else - sd->clockdiv = 0; + /******** Set the framerate ********/ + sd->clockdiv = 1; /* Mode independent, but framerate dependent, regs */ - reg_w(sd, 0x51, 0x04); /* Clock divider; lower==faster */ + /* 0x51: Clock divider; Only works on some cams which use 2 crystals */ + reg_w(sd, 0x51, 0x04); reg_w(sd, 0x22, 0x18); reg_w(sd, 0x23, 0xff); - if (sd->bridge == BRIDGE_OV518PLUS) - reg_w(sd, 0x21, 0x19); - else + if (sd->bridge == BRIDGE_OV518PLUS) { + switch (sd->sensor) { + case SEN_OV7620: + if (sd->gspca_dev.width == 320) { + reg_w(sd, 0x20, 0x00); + reg_w(sd, 0x21, 0x19); + } else { + reg_w(sd, 0x20, 0x60); + reg_w(sd, 0x21, 0x1f); + } + break; + default: + reg_w(sd, 0x21, 0x19); + } + } else reg_w(sd, 0x71, 0x17); /* Compression-related? */ /* FIXME: Sensor-specific */ @@ -2557,30 +2581,16 @@ static int mode_init_ov_sensor_regs(struct sd *sd) #endif break; case SEN_OV7620: -/* i2c_w(sd, 0x2b, 0x00); */ - i2c_w_mask(sd, 0x14, qvga ? 0x20 : 0x00, 0x20); - i2c_w_mask(sd, 0x28, qvga ? 0x00 : 0x20, 0x20); - i2c_w(sd, 0x24, qvga ? 0x20 : 0x3a); - i2c_w(sd, 0x25, qvga ? 0x30 : 0x60); - i2c_w_mask(sd, 0x2d, qvga ? 0x40 : 0x00, 0x40); - i2c_w_mask(sd, 0x67, qvga ? 0xf0 : 0x90, 0xf0); - i2c_w_mask(sd, 0x74, qvga ? 0x20 : 0x00, 0x20); - break; case SEN_OV76BE: -/* i2c_w(sd, 0x2b, 0x00); */ i2c_w_mask(sd, 0x14, qvga ? 0x20 : 0x00, 0x20); -#if 0 - /* FIXME: Enable this once 7620AE uses 7620 initial settings */ i2c_w_mask(sd, 0x28, qvga ? 0x00 : 0x20, 0x20); i2c_w(sd, 0x24, qvga ? 0x20 : 0x3a); i2c_w(sd, 0x25, qvga ? 0x30 : 0x60); i2c_w_mask(sd, 0x2d, qvga ? 0x40 : 0x00, 0x40); i2c_w_mask(sd, 0x67, qvga ? 0xb0 : 0x90, 0xf0); i2c_w_mask(sd, 0x74, qvga ? 0x20 : 0x00, 0x20); -#endif break; case SEN_OV7640: -/* i2c_w(sd, 0x2b, 0x00); */ i2c_w_mask(sd, 0x14, qvga ? 0x20 : 0x00, 0x20); i2c_w_mask(sd, 0x28, qvga ? 0x00 : 0x20, 0x20); /* i2c_w(sd, 0x24, qvga ? 0x20 : 0x3a); */ -- cgit v1.2.3 From 291c1af51a21bad6283ffa005ed5ccd5b2a3a605 Mon Sep 17 00:00:00 2001 From: "hans@rhel5-devel.localdomain" Date: Mon, 15 Jun 2009 00:15:07 +0200 Subject: gspca_ov519: Cleanup some sensor special cases From: Hans de Goede gspca_ov519: Cleanup some sensor special cases Priority: normal Signed-off-by: Hans de Goede --- linux/drivers/media/video/gspca/ov519.c | 24 ++++-------------------- 1 file changed, 4 insertions(+), 20 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/ov519.c b/linux/drivers/media/video/gspca/ov519.c index 9b7dc5b3b..5759f9a46 100644 --- a/linux/drivers/media/video/gspca/ov519.c +++ b/linux/drivers/media/video/gspca/ov519.c @@ -529,7 +529,7 @@ static const struct ov_i2c_regvals norm_6x20[] = { { 0x28, 0x05 }, { 0x2a, 0x04 }, /* Disable framerate adjust */ /* { 0x2b, 0xac }, * Framerate; Set 2a[7] first */ - { 0x2d, 0x99 }, + { 0x2d, 0x85 }, { 0x33, 0xa0 }, /* Color Processing Parameter */ { 0x34, 0xd2 }, /* Max A/D range */ { 0x38, 0x8b }, @@ -2124,6 +2124,8 @@ static int sd_init(struct gspca_dev *gspca_dev) /* case SEN_OV76BE: */ if (write_i2c_regvals(sd, norm_7610, ARRAY_SIZE(norm_7610))) return -EIO; + if (i2c_w_mask(sd, 0x0e, 0x00, 0x40)) + return -EIO; break; case SEN_OV7620: if (write_i2c_regvals(sd, norm_7620, ARRAY_SIZE(norm_7620))) @@ -2617,10 +2619,6 @@ static int mode_init_ov_sensor_regs(struct sd *sd) } /******** Palette-specific regs ********/ - if (sd->sensor == SEN_OV7610 || sd->sensor == SEN_OV76BE) { - /* not valid on the OV6620/OV7620/6630? */ - i2c_w_mask(sd, 0x0e, 0x00, 0x40); - } /* The OV518 needs special treatment. Although both the OV518 * and the OV6630 support a 16-bit video bus, only the 8 bit Y @@ -2635,21 +2633,7 @@ static int mode_init_ov_sensor_regs(struct sd *sd) i2c_w_mask(sd, 0x13, 0x00, 0x20); /******** Clock programming ********/ - /* The OV6620 needs special handling. This prevents the - * severe banding that normally occurs */ - if (sd->sensor == SEN_OV6620) { - - /* Clock down */ - i2c_w(sd, 0x2a, 0x04); - i2c_w(sd, 0x11, sd->clockdiv); - i2c_w(sd, 0x2a, 0x84); - /* This next setting is critical. It seems to improve - * the gain or the contrast. The "reserved" bits seem - * to have some effect in this case. */ - i2c_w(sd, 0x2d, 0x85); - } else { - i2c_w(sd, 0x11, sd->clockdiv); - } + i2c_w(sd, 0x11, sd->clockdiv); /******** Special Features ********/ /* no evidence this is possible with OV7670, either */ -- cgit v1.2.3 From 944b8fa4c78bec5e481f59eaa0c02d2928be6309 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 16 Jun 2009 16:31:29 +0000 Subject: poll method lose race condition From: Figo.zhang bttv-driver.c,cx23885-video.c,cx88-video.c: poll method lose race condition for capture video. Signed-off-by: Figo.zhang Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/bt8xx/bttv-driver.c | 11 +++++++---- linux/drivers/media/video/cx23885/cx23885-video.c | 14 ++++++++++---- linux/drivers/media/video/cx88/cx88-video.c | 14 ++++++++++---- 3 files changed, 27 insertions(+), 12 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 67d06eb6c..27be1694b 100644 --- a/linux/drivers/media/video/bt8xx/bttv-driver.c +++ b/linux/drivers/media/video/bt8xx/bttv-driver.c @@ -3180,6 +3180,7 @@ static unsigned int bttv_poll(struct file *file, poll_table *wait) struct bttv_fh *fh = file->private_data; struct bttv_buffer *buf; enum v4l2_field field; + unsigned int rc = POLLERR; if (V4L2_BUF_TYPE_VBI_CAPTURE == fh->type) { if (!check_alloc_btres(fh->btv,fh,RESOURCE_VBI)) @@ -3188,9 +3189,10 @@ static unsigned int bttv_poll(struct file *file, poll_table *wait) } if (check_btres(fh,RESOURCE_VIDEO_STREAM)) { + mutex_lock(&fh->cap.vb_lock); /* streaming capture */ if (list_empty(&fh->cap.stream)) - return POLLERR; + goto err; buf = list_entry(fh->cap.stream.next,struct bttv_buffer,vb.stream); } else { /* read() capture */ @@ -3219,11 +3221,12 @@ static unsigned int bttv_poll(struct file *file, poll_table *wait) poll_wait(file, &buf->vb.done, wait); if (buf->vb.state == VIDEOBUF_DONE || buf->vb.state == VIDEOBUF_ERROR) - return POLLIN|POLLRDNORM; - return 0; + rc = POLLIN|POLLRDNORM; + else + rc = 0; err: mutex_unlock(&fh->cap.vb_lock); - return POLLERR; + return rc; } static int bttv_open(struct file *file) diff --git a/linux/drivers/media/video/cx23885/cx23885-video.c b/linux/drivers/media/video/cx23885/cx23885-video.c index 378943605..2248e0216 100644 --- a/linux/drivers/media/video/cx23885/cx23885-video.c +++ b/linux/drivers/media/video/cx23885/cx23885-video.c @@ -865,6 +865,7 @@ static unsigned int video_poll(struct file *file, { struct cx23885_fh *fh = file->private_data; struct cx23885_buffer *buf; + unsigned int rc = POLLERR; if (V4L2_BUF_TYPE_VBI_CAPTURE == fh->type) { if (!res_get(fh->dev, fh, RESOURCE_VBI)) @@ -872,23 +873,28 @@ static unsigned int video_poll(struct file *file, return videobuf_poll_stream(file, &fh->vbiq, wait); } + mutex_lock(&fh->vidq.vb_lock); if (res_check(fh, RESOURCE_VIDEO)) { /* streaming capture */ if (list_empty(&fh->vidq.stream)) - return POLLERR; + goto done; buf = list_entry(fh->vidq.stream.next, struct cx23885_buffer, vb.stream); } else { /* read() capture */ buf = (struct cx23885_buffer *)fh->vidq.read_buf; if (NULL == buf) - return POLLERR; + goto done; } poll_wait(file, &buf->vb.done, wait); if (buf->vb.state == VIDEOBUF_DONE || buf->vb.state == VIDEOBUF_ERROR) - return POLLIN|POLLRDNORM; - return 0; + rc = POLLIN|POLLRDNORM; + else + rc = 0; +done: + mutex_unlock(&fh->vidq.vb_lock); + return rc; } static int video_release(struct file *file) diff --git a/linux/drivers/media/video/cx88/cx88-video.c b/linux/drivers/media/video/cx88/cx88-video.c index 70b086fb7..a55053767 100644 --- a/linux/drivers/media/video/cx88/cx88-video.c +++ b/linux/drivers/media/video/cx88/cx88-video.c @@ -1095,6 +1095,7 @@ video_poll(struct file *file, struct poll_table_struct *wait) { struct cx8800_fh *fh = file->private_data; struct cx88_buffer *buf; + unsigned int rc = POLLERR; if (V4L2_BUF_TYPE_VBI_CAPTURE == fh->type) { if (!res_get(fh->dev,fh,RESOURCE_VBI)) @@ -1102,22 +1103,27 @@ video_poll(struct file *file, struct poll_table_struct *wait) return videobuf_poll_stream(file, &fh->vbiq, wait); } + mutex_lock(&fh->vidq.vb_lock); if (res_check(fh,RESOURCE_VIDEO)) { /* streaming capture */ if (list_empty(&fh->vidq.stream)) - return POLLERR; + goto done; buf = list_entry(fh->vidq.stream.next,struct cx88_buffer,vb.stream); } else { /* read() capture */ buf = (struct cx88_buffer*)fh->vidq.read_buf; if (NULL == buf) - return POLLERR; + goto done; } poll_wait(file, &buf->vb.done, wait); if (buf->vb.state == VIDEOBUF_DONE || buf->vb.state == VIDEOBUF_ERROR) - return POLLIN|POLLRDNORM; - return 0; + rc = POLLIN|POLLRDNORM; + else + rc = 0; +done: + mutex_unlock(&fh->vidq.vb_lock); + return rc; } static int video_release(struct file *file) -- cgit v1.2.3 From 52bcb7460a6934b8b53c40964e2094d7998147ab Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 16 Jun 2009 16:08:17 -0400 Subject: cx23885: add FIXME comment above set_frontend override From: Michael Krufky add FIXME comment to indicate that the set_frontend override is a temporary hack. This will be done a better way in the next kernel. Priority: normal Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/cx23885/cx23885-dvb.c | 1 + linux/drivers/media/video/cx23885/cx23885.h | 2 ++ 2 files changed, 3 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/cx23885/cx23885-dvb.c b/linux/drivers/media/video/cx23885/cx23885-dvb.c index 83584535a..4bab7c814 100644 --- a/linux/drivers/media/video/cx23885/cx23885-dvb.c +++ b/linux/drivers/media/video/cx23885/cx23885-dvb.c @@ -528,6 +528,7 @@ static int dvb_register(struct cx23885_tsport *port) &hauppauge_hvr127x_config); } + /* FIXME: temporary hack */ /* define bridge override to set_frontend */ port->set_frontend_save = fe0->dvb.frontend->ops.set_frontend; fe0->dvb.frontend->ops.set_frontend = cx23885_dvb_set_frontend; diff --git a/linux/drivers/media/video/cx23885/cx23885.h b/linux/drivers/media/video/cx23885/cx23885.h index 81af0ede1..aecaca4b4 100644 --- a/linux/drivers/media/video/cx23885/cx23885.h +++ b/linux/drivers/media/video/cx23885/cx23885.h @@ -289,6 +289,8 @@ struct cx23885_tsport { /* Allow a single tsport to have multiple frontends */ u32 num_frontends; void *port_priv; + + /* FIXME: temporary hack */ int (*set_frontend_save) (struct dvb_frontend *, struct dvb_frontend_parameters *); }; -- cgit v1.2.3 From 28f0a28c5e0c37bee44d914bde9533d5fc16b62d Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 16 Jun 2009 18:37:35 -0300 Subject: Backport language typo and whitespace differences From: Mauro Carvalho Chehab kernel-sync: Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/dvb-usb/Kconfig | 2 +- linux/drivers/media/video/hdpvr/hdpvr-video.c | 2 +- linux/drivers/media/video/ivtv/ivtv-i2c.c | 2 ++ 3 files changed, 4 insertions(+), 2 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/dvb-usb/Kconfig b/linux/drivers/media/dvb/dvb-usb/Kconfig index 8a8a1bede..496c1a370 100644 --- a/linux/drivers/media/dvb/dvb-usb/Kconfig +++ b/linux/drivers/media/dvb/dvb-usb/Kconfig @@ -216,7 +216,7 @@ config DVB_USB_TTUSB2 help Say Y here to support the Pinnacle 400e DVB-S USB2.0 receiver. The firmware protocol used by this module is similar to the one used by the - old ttusb-driver - that's why the module is called dvb-usb-ttusb2.ko. + old ttusb-driver - that's why the module is called dvb-usb-ttusb2. config DVB_USB_DTT200U tristate "WideView WT-200U and WT-220U (pen) DVB-T USB2.0 support (Yakumo/Hama/Typhoon/Yuan)" diff --git a/linux/drivers/media/video/hdpvr/hdpvr-video.c b/linux/drivers/media/video/hdpvr/hdpvr-video.c index 3e6ffee8d..ccd47f57f 100644 --- a/linux/drivers/media/video/hdpvr/hdpvr-video.c +++ b/linux/drivers/media/video/hdpvr/hdpvr-video.c @@ -181,7 +181,7 @@ static int hdpvr_submit_buffers(struct hdpvr_device *dev) buff_list); if (buf->status != BUFSTAT_AVAILABLE) { v4l2_err(&dev->v4l2_dev, - "buffer not marked as availbale\n"); + "buffer not marked as available\n"); ret = -EFAULT; goto err; } diff --git a/linux/drivers/media/video/ivtv/ivtv-i2c.c b/linux/drivers/media/video/ivtv/ivtv-i2c.c index eed4d2364..484a323f1 100644 --- a/linux/drivers/media/video/ivtv/ivtv-i2c.c +++ b/linux/drivers/media/video/ivtv/ivtv-i2c.c @@ -639,6 +639,7 @@ int init_ivtv_i2c(struct ivtv *itv) retval = i2c_add_adapter(&itv->i2c_adap); else retval = i2c_bit_add_bus(&itv->i2c_adap); + #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 30) /* Instantiate the IR receiver device, if present */ if (retval == 0) { @@ -666,6 +667,7 @@ int init_ivtv_i2c(struct ivtv *itv) i2c_new_probed_device(&itv->i2c_adap, &info, addr_list); } #endif + return retval; } -- cgit v1.2.3 From ca8ea83f7dfae217f7a0dec64a982cb04d158985 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 16 Jun 2009 18:48:44 -0300 Subject: backport commit c2e5307b902426247afa48d3f1ed4fa5409dcb49 From: Mauro Carvalho Chehab kernel-sync: Author: Valentin Longchamp Date: Wed May 6 11:54:48 2009 +0200 mx31: changed CONSISTENT_DMA_SIZE to 8M for mx31 video Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/Kconfig | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/Kconfig b/linux/drivers/media/video/Kconfig index 8de867d30..94f440535 100644 --- a/linux/drivers/media/video/Kconfig +++ b/linux/drivers/media/video/Kconfig @@ -776,10 +776,14 @@ config VIDEO_MX1 ---help--- This is a v4l2 driver for the i.MX1/i.MXL CMOS Sensor Interface +config MX3_VIDEO + bool + config VIDEO_MX3 tristate "i.MX3x Camera Sensor Interface driver" depends on VIDEO_DEV && MX3_IPU && SOC_CAMERA select VIDEOBUF_DMA_CONTIG + select MX3_VIDEO ---help--- This is a v4l2 driver for the i.MX3x Camera Sensor Interface -- cgit v1.2.3 From 9204bc59f7e30d4441efb2262a1debc8782b5b74 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 16 Jun 2009 19:02:10 -0300 Subject: dvb-net: backport upstream changes fb875333c8 and 0eade1f930 From: Mauro Carvalho Chehab kernel-sync: commit fb875333c80942455551f690f306a899ceeee5df Author: Stephen Hemminger Date: Wed Jan 7 18:02:53 2009 -0800 dvb: update network device to current API Use internal network_device_stats that exist in network device and net_device_ops. Compile tested only. commit 0eade1f930fa3ba6461b34baf3ed8fa7c4abc40f Author: Wang Chen Date: Wed Dec 3 21:13:13 2008 -0800 dvb: Kill directly reference of netdev->priv Simply replace netdev->priv with netdev_priv(). Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/dvb-core/dvb_net.c | 65 +++++++++++++++++++++++++++++- 1 file changed, 64 insertions(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/dvb-core/dvb_net.c b/linux/drivers/media/dvb/dvb-core/dvb_net.c index 5f4856c6d..1eede48a9 100644 --- a/linux/drivers/media/dvb/dvb-core/dvb_net.c +++ b/linux/drivers/media/dvb/dvb-core/dvb_net.c @@ -126,7 +126,9 @@ static void hexdump( const unsigned char *buf, unsigned short len ) struct dvb_net_priv { int in_use; +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 29) struct net_device_stats stats; +#endif u16 pid; #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20) struct net_device *net; @@ -391,8 +393,13 @@ static void dvb_net_ule( struct net_device *dev, const u8 *buf, size_t buf_len ) if (priv->ule_skb) { dev_kfree_skb( priv->ule_skb ); /* Prepare for next SNDU. */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 29) priv->stats.rx_errors++; priv->stats.rx_frame_errors++; +#else + dev->stats.rx_errors++; + dev->stats.rx_frame_errors++; +#endif } reset_ule(priv); priv->need_pusi = 1; @@ -445,8 +452,13 @@ static void dvb_net_ule( struct net_device *dev, const u8 *buf, size_t buf_len ) dev_kfree_skb( priv->ule_skb ); /* Prepare for next SNDU. */ // reset_ule(priv); moved to below. +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 29) priv->stats.rx_errors++; priv->stats.rx_frame_errors++; +#else + dev->stats.rx_errors++; + dev->stats.rx_frame_errors++; +#endif } reset_ule(priv); /* skip to next PUSI. */ @@ -467,8 +479,13 @@ static void dvb_net_ule( struct net_device *dev, const u8 *buf, size_t buf_len ) /* Drop partly decoded SNDU, reset state, resync on PUSI. */ if (priv->ule_skb) { dev_kfree_skb( priv->ule_skb ); +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 29) priv->stats.rx_errors++; priv->stats.rx_frame_errors++; +#else + dev->stats.rx_errors++; + dev->stats.rx_frame_errors++; +#endif } reset_ule(priv); priv->need_pusi = 1; @@ -484,8 +501,13 @@ static void dvb_net_ule( struct net_device *dev, const u8 *buf, size_t buf_len ) if (priv->ule_sndu_remain > 183) { /* Current SNDU lacks more data than there could be available in the * current TS cell. */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 29) priv->stats.rx_errors++; priv->stats.rx_length_errors++; +#else + dev->stats.rx_errors++; + dev->stats.rx_length_errors++; +#endif printk(KERN_WARNING "%lu: Expected %d more SNDU bytes, but " "got PUSI (pf %d, ts_remain %d). Flushing incomplete payload.\n", priv->ts_count, priv->ule_sndu_remain, ts[4], ts_remain); @@ -527,8 +549,13 @@ static void dvb_net_ule( struct net_device *dev, const u8 *buf, size_t buf_len ) if (priv->ule_sndu_len < 5) { printk(KERN_WARNING "%lu: Invalid ULE SNDU length %u. " "Resyncing.\n", priv->ts_count, priv->ule_sndu_len); +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 29) priv->stats.rx_errors++; priv->stats.rx_length_errors++; +#else + dev->stats.rx_errors++; + dev->stats.rx_length_errors++; +#endif priv->ule_sndu_len = 0; priv->need_pusi = 1; new_ts = 1; @@ -580,7 +607,11 @@ static void dvb_net_ule( struct net_device *dev, const u8 *buf, size_t buf_len ) if (priv->ule_skb == NULL) { printk(KERN_NOTICE "%s: Memory squeeze, dropping packet.\n", dev->name); +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 29) priv->stats.rx_dropped++; +#else + dev->stats.rx_dropped++; +#endif return; } @@ -653,8 +684,13 @@ static void dvb_net_ule( struct net_device *dev, const u8 *buf, size_t buf_len ) ule_dump = 1; #endif +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 29) priv->stats.rx_errors++; priv->stats.rx_crc_errors++; +#else + dev->stats.rx_errors++; + dev->stats.rx_crc_errors++; +#endif dev_kfree_skb(priv->ule_skb); } else { /* CRC32 verified OK. */ @@ -764,8 +800,13 @@ static void dvb_net_ule( struct net_device *dev, const u8 *buf, size_t buf_len ) * receive the packet anyhow. */ /* if (priv->ule_dbit && skb->pkt_type == PACKET_OTHERHOST) priv->ule_skb->pkt_type = PACKET_HOST; */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 29) priv->stats.rx_packets++; priv->stats.rx_bytes += priv->ule_skb->len; +#else + dev->stats.rx_packets++; + dev->stats.rx_bytes += priv->ule_skb->len; +#endif netif_rx(priv->ule_skb); } sndu_done: @@ -820,8 +861,12 @@ static void dvb_net_sec(struct net_device *dev, { u8 *eth; struct sk_buff *skb; +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 29) struct net_device_stats *stats = &((struct dvb_net_priv *) netdev_priv(dev))->stats; +#else + struct net_device_stats *stats = &dev->stats; +#endif int snap = 0; /* note: pkt_len includes a 32bit checksum */ @@ -1269,11 +1314,12 @@ static int dvb_net_stop(struct net_device *dev) return dvb_net_feed_stop(dev); } +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 29) static struct net_device_stats * dvb_net_get_stats(struct net_device *dev) { return &((struct dvb_net_priv *) netdev_priv(dev))->stats; } - +#endif #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24) static const struct header_ops dvb_header_ops = { .create = eth_header, @@ -1282,6 +1328,19 @@ static const struct header_ops dvb_header_ops = { }; #endif + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29) +static const struct net_device_ops dvb_netdev_ops = { + .ndo_open = dvb_net_open, + .ndo_stop = dvb_net_stop, + .ndo_start_xmit = dvb_net_tx, + .ndo_set_multicast_list = dvb_net_set_multicast_list, + .ndo_set_mac_address = dvb_net_set_mac, + .ndo_change_mtu = eth_change_mtu, + .ndo_validate_addr = eth_validate_addr, +}; +#endif + static void dvb_net_setup(struct net_device *dev) { ether_setup(dev); @@ -1291,12 +1350,16 @@ static void dvb_net_setup(struct net_device *dev) #else dev->hard_header_cache = NULL; #endif +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 29) dev->open = dvb_net_open; dev->stop = dvb_net_stop; dev->hard_start_xmit = dvb_net_tx; dev->get_stats = dvb_net_get_stats; dev->set_multicast_list = dvb_net_set_multicast_list; dev->set_mac_address = dvb_net_set_mac; +#else + dev->netdev_ops = &dvb_netdev_ops; +#endif dev->mtu = 4096; dev->mc_count = 0; -- cgit v1.2.3 From d751a965ff35ef575d2863b5d1256dd8e2a0bddf Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 16 Jun 2009 23:55:44 -0300 Subject: cx88: Properly support Leadtek TV2000 XP Global From: Mauro Carvalho Chehab Fix Leadtek TV2000 XP Global entries and add missing PCI ID's. Thanks to Terry Wu for pointing us for the proper settings. Priority: normal CC: Terry Wu Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/cx88/cx88-cards.c | 94 +++++++++++++++++++++++------ 1 file changed, 75 insertions(+), 19 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 825b1f25d..bf0f26c03 100644 --- a/linux/drivers/media/video/cx88/cx88-cards.c +++ b/linux/drivers/media/video/cx88/cx88-cards.c @@ -1557,33 +1557,45 @@ static const struct cx88_board cx88_boards[] = { }, .mpeg = CX88_MPEG_DVB, }, + /* Terry Wu */ + /* TV Audio : set GPIO 2, 18, 19 value to 0, 1, 0 */ + /* FM Audio : set GPIO 2, 18, 19 value to 0, 0, 0 */ + /* Line-in Audio : set GPIO 2, 18, 19 value to 0, 1, 1 */ + /* Mute Audio : set GPIO 2 value to 1 */ [CX88_BOARD_WINFAST_TV2000_XP_GLOBAL] = { - .name = "Winfast TV2000 XP Global", + .name = "Leadtek TV2000 XP Global", .tuner_type = TUNER_XC2028, .tuner_addr = 0x61, + .radio_type = TUNER_XC2028, + .radio_addr = 0x61, .input = { { .type = CX88_VMUX_TELEVISION, .vmux = 0, - .gpio0 = 0x0400, /* pin 2:mute = 0 (off?) */ + .gpio0 = 0x0400, /* pin 2 = 0 */ .gpio1 = 0x0000, - .gpio2 = 0x0800, /* pin 19:audio = 0 (tv) */ - + .gpio2 = 0x0C04, /* pin 18 = 1, pin 19 = 0 */ + .gpio3 = 0x0000, }, { .type = CX88_VMUX_COMPOSITE1, .vmux = 1, - .gpio0 = 0x0400, /* probably? or 0x0404 to turn mute on */ + .gpio0 = 0x0400, /* pin 2 = 0 */ .gpio1 = 0x0000, - .gpio2 = 0x0808, /* pin 19:audio = 1 (line) */ - + .gpio2 = 0x0C0C, /* pin 18 = 1, pin 19 = 1 */ + .gpio3 = 0x0000, }, { .type = CX88_VMUX_SVIDEO, .vmux = 2, + .gpio0 = 0x0400, /* pin 2 = 0 */ + .gpio1 = 0x0000, + .gpio2 = 0x0C0C, /* pin 18 = 1, pin 19 = 1 */ + .gpio3 = 0x0000, } }, .radio = { .type = CX88_RADIO, - .gpio0 = 0x004ff, - .gpio1 = 0x010ff, - .gpio2 = 0x0ff, + .gpio0 = 0x0400, /* pin 2 = 0 */ + .gpio1 = 0x0000, + .gpio2 = 0x0C00, /* pin 18 = 0, pin 19 = 0 */ + .gpio3 = 0x0000, }, }, [CX88_BOARD_POWERCOLOR_REAL_ANGEL] = { @@ -2471,6 +2483,41 @@ static const struct cx88_subid cx88_subids[] = { .subvendor = 0x107d, .subdevice = 0x6654, .card = CX88_BOARD_WINFAST_DTV1800H, + }, { + /* PVR2000 PAL Model [107d:6630] */ + .subvendor = 0x107d, + .subdevice = 0x6630, + .card = CX88_BOARD_LEADTEK_PVR2000, + }, { + /* PVR2000 PAL Model [107d:6638] */ + .subvendor = 0x107d, + .subdevice = 0x6638, + .card = CX88_BOARD_LEADTEK_PVR2000, + }, { + /* PVR2000 NTSC Model [107d:6631] */ + .subvendor = 0x107d, + .subdevice = 0x6631, + .card = CX88_BOARD_LEADTEK_PVR2000, + }, { + /* PVR2000 NTSC Model [107d:6637] */ + .subvendor = 0x107d, + .subdevice = 0x6637, + .card = CX88_BOARD_LEADTEK_PVR2000, + }, { + /* PVR2000 NTSC Model [107d:663d] */ + .subvendor = 0x107d, + .subdevice = 0x663d, + .card = CX88_BOARD_LEADTEK_PVR2000, + }, { + /* DV2000 NTSC Model [107d:6621] */ + .subvendor = 0x107d, + .subdevice = 0x6621, + .card = CX88_BOARD_WINFAST_DV2000, + }, { + /* TV2000 XP Global [107d:6618] */ + .subvendor = 0x107d, + .subdevice = 0x6618, + .card = CX88_BOARD_WINFAST_TV2000_XP_GLOBAL, }, }; @@ -2479,12 +2526,6 @@ static const struct cx88_subid cx88_subids[] = { static void leadtek_eeprom(struct cx88_core *core, u8 *eeprom_data) { - /* This is just for the "Winfast 2000XP Expert" board ATM; I don't have data on - * any others. - * - * Byte 0 is 1 on the NTSC board. - */ - if (eeprom_data[4] != 0x7d || eeprom_data[5] != 0x10 || eeprom_data[7] != 0x66) { @@ -2492,8 +2533,19 @@ static void leadtek_eeprom(struct cx88_core *core, u8 *eeprom_data) return; } - core->board.tuner_type = (eeprom_data[6] == 0x13) ? - TUNER_PHILIPS_FM1236_MK3 : TUNER_PHILIPS_FM1216ME_MK3; + /* Terry Wu */ + switch (eeprom_data[6]) { + case 0x13: /* SSID 6613 for TV2000 XP Expert NTSC Model */ + case 0x21: /* SSID 6621 for DV2000 NTSC Model */ + case 0x31: /* SSID 6631 for PVR2000 NTSC Model */ + case 0x37: /* SSID 6637 for PVR2000 NTSC Model */ + case 0x3d: /* SSID 6637 for PVR2000 NTSC Model */ + core->board.tuner_type = TUNER_PHILIPS_FM1236_MK3; + break; + default: + core->board.tuner_type = TUNER_PHILIPS_FM1216ME_MK3; + break; + } info_printk(core, "Leadtek Winfast 2000XP Expert config: " "tuner=%d, eeprom[0]=0x%02x\n", @@ -2746,7 +2798,6 @@ static int cx88_xc2028_tuner_callback(struct cx88_core *core, { /* Board-specific callbacks */ switch (core->boardnr) { - case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL: case CX88_BOARD_POWERCOLOR_REAL_ANGEL: case CX88_BOARD_GENIATECH_X8000_MT: case CX88_BOARD_KWORLD_ATSC_120: @@ -2758,6 +2809,7 @@ static int cx88_xc2028_tuner_callback(struct cx88_core *core, case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO: case CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO: return cx88_dvico_xc2028_callback(core, command, arg); + case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL: case CX88_BOARD_WINFAST_DTV1800H: return cx88_xc3028_winfast1800h_callback(core, command, arg); } @@ -2947,6 +2999,7 @@ static void cx88_card_setup_pre_i2c(struct cx88_core *core) udelay(1000); break; + case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL: case CX88_BOARD_WINFAST_DTV1800H: /* GPIO 12 (xc3028 tuner reset) */ cx_set(MO_GP1_IO, 0x1010); @@ -2983,6 +3036,7 @@ void cx88_setup_xc3028(struct cx88_core *core, struct xc2028_ctrl *ctl) case CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO: ctl->demod = XC3028_FE_OREN538; break; + case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL: case CX88_BOARD_PROLINK_PV_GLOBAL_XTREME: case CX88_BOARD_PROLINK_PV_8000GT: /* @@ -3026,6 +3080,8 @@ static void cx88_card_setup(struct cx88_core *core) if (0 == core->i2c_rc) gdi_eeprom(core, eeprom); break; + case CX88_BOARD_LEADTEK_PVR2000: + case CX88_BOARD_WINFAST_DV2000: case CX88_BOARD_WINFAST2000XP_EXPERT: if (0 == core->i2c_rc) leadtek_eeprom(core, eeprom); -- cgit v1.2.3 From 8cba5139f0ceaec9221a9eec09bab7c6fdc4b46b Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 17 Jun 2009 04:38:10 +0000 Subject: lgs8gxx: add lgs8g75 support From: David Wong lgs8gxx: add lgs8g75 demodulator support Signed-off-by: David T.L. Wong Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/frontends/lgs8gxx.c | 505 +++++++++++++++++------ linux/drivers/media/dvb/frontends/lgs8gxx.h | 11 +- linux/drivers/media/dvb/frontends/lgs8gxx_priv.h | 12 +- 3 files changed, 401 insertions(+), 127 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/frontends/lgs8gxx.c b/linux/drivers/media/dvb/frontends/lgs8gxx.c index 1ce30aa53..226536ae0 100644 --- a/linux/drivers/media/dvb/frontends/lgs8gxx.c +++ b/linux/drivers/media/dvb/frontends/lgs8gxx.c @@ -1,9 +1,9 @@ /* - * Support for Legend Silicon DMB-TH demodulator - * LGS8913, LGS8GL5 + * Support for Legend Silicon GB20600 (a.k.a DMB-TH) demodulator + * LGS8913, LGS8GL5, LGS8G75 * experimental support LGS8G42, LGS8G52 * - * Copyright (C) 2007,2008 David T.L. Wong + * Copyright (C) 2007-2009 David T.L. Wong * Copyright (C) 2008 Sirius International (Hong Kong) Limited * Timothy Lee (for initial work on LGS8GL5) * @@ -46,6 +46,42 @@ module_param(fake_signal_str, int, 0644); MODULE_PARM_DESC(fake_signal_str, "fake signal strength for LGS8913." "Signal strength calculation is slow.(default:on)."); +static const u8 lgs8g75_initdat[] = { + 0x01, 0x30, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xE4, 0xF5, 0xA8, 0xF5, 0xB8, 0xF5, 0x88, 0xF5, + 0x89, 0xF5, 0x87, 0x75, 0xD0, 0x00, 0x11, 0x50, + 0x11, 0x50, 0xF4, 0xF5, 0x80, 0xF5, 0x90, 0xF5, + 0xA0, 0xF5, 0xB0, 0x75, 0x81, 0x30, 0x80, 0x01, + 0x32, 0x90, 0x80, 0x12, 0x74, 0xFF, 0xF0, 0x90, + 0x80, 0x13, 0x74, 0x1F, 0xF0, 0x90, 0x80, 0x23, + 0x74, 0x01, 0xF0, 0x90, 0x80, 0x22, 0xF0, 0x90, + 0x00, 0x48, 0x74, 0x00, 0xF0, 0x90, 0x80, 0x4D, + 0x74, 0x05, 0xF0, 0x90, 0x80, 0x09, 0xE0, 0x60, + 0x21, 0x12, 0x00, 0xDD, 0x14, 0x60, 0x1B, 0x12, + 0x00, 0xDD, 0x14, 0x60, 0x15, 0x12, 0x00, 0xDD, + 0x14, 0x60, 0x0F, 0x12, 0x00, 0xDD, 0x14, 0x60, + 0x09, 0x12, 0x00, 0xDD, 0x14, 0x60, 0x03, 0x12, + 0x00, 0xDD, 0x90, 0x80, 0x42, 0xE0, 0x60, 0x0B, + 0x14, 0x60, 0x0C, 0x14, 0x60, 0x0D, 0x14, 0x60, + 0x0E, 0x01, 0xB3, 0x74, 0x04, 0x01, 0xB9, 0x74, + 0x05, 0x01, 0xB9, 0x74, 0x07, 0x01, 0xB9, 0x74, + 0x0A, 0xC0, 0xE0, 0x74, 0xC8, 0x12, 0x00, 0xE2, + 0xD0, 0xE0, 0x14, 0x70, 0xF4, 0x90, 0x80, 0x09, + 0xE0, 0x70, 0xAE, 0x12, 0x00, 0xF6, 0x12, 0x00, + 0xFE, 0x90, 0x00, 0x48, 0xE0, 0x04, 0xF0, 0x90, + 0x80, 0x4E, 0xF0, 0x01, 0x73, 0x90, 0x80, 0x08, + 0xF0, 0x22, 0xF8, 0x7A, 0x0C, 0x79, 0xFD, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD9, + 0xF6, 0xDA, 0xF2, 0xD8, 0xEE, 0x22, 0x90, 0x80, + 0x65, 0xE0, 0x54, 0xFD, 0xF0, 0x22, 0x90, 0x80, + 0x65, 0xE0, 0x44, 0xC2, 0xF0, 0x22 +}; + /* LGS8GXX internal helper functions */ static int lgs8gxx_write_reg(struct lgs8gxx_state *priv, u8 reg, u8 data) @@ -55,7 +91,7 @@ static int lgs8gxx_write_reg(struct lgs8gxx_state *priv, u8 reg, u8 data) struct i2c_msg msg = { .flags = 0, .buf = buf, .len = 2 }; msg.addr = priv->config->demod_address; - if (reg >= 0xC0) + if (priv->config->prod != LGS8GXX_PROD_LGS8G75 && reg >= 0xC0) msg.addr += 0x02; if (debug >= 2) @@ -84,7 +120,7 @@ static int lgs8gxx_read_reg(struct lgs8gxx_state *priv, u8 reg, u8 *p_data) }; dev_addr = priv->config->demod_address; - if (reg >= 0xC0) + if (priv->config->prod != LGS8GXX_PROD_LGS8G75 && reg >= 0xC0) dev_addr += 0x02; msg[1].addr = msg[0].addr = dev_addr; @@ -112,19 +148,36 @@ static int lgs8gxx_soft_reset(struct lgs8gxx_state *priv) return 0; } +static int wait_reg_mask(struct lgs8gxx_state *priv, u8 reg, u8 mask, + u8 val, u8 delay, u8 tries) +{ + u8 t; + int i; + + for (i = 0; i < tries; i++) { + lgs8gxx_read_reg(priv, reg, &t); + + if ((t & mask) == val) + return 0; + msleep(delay); + } + + return 1; +} + static int lgs8gxx_set_ad_mode(struct lgs8gxx_state *priv) { const struct lgs8gxx_config *config = priv->config; u8 if_conf; - if_conf = 0x10; /* AGC output on; */ + if_conf = 0x10; /* AGC output on, RF_AGC output off; */ if_conf |= ((config->ext_adc) ? 0x80 : 0x00) | ((config->if_neg_center) ? 0x04 : 0x00) | ((config->if_freq == 0) ? 0x08 : 0x00) | /* Baseband */ - ((config->ext_adc && config->adc_signed) ? 0x02 : 0x00) | - ((config->ext_adc && config->if_neg_edge) ? 0x01 : 0x00); + ((config->adc_signed) ? 0x02 : 0x00) | + ((config->if_neg_edge) ? 0x01 : 0x00); if (config->ext_adc && (config->prod == LGS8GXX_PROD_LGS8G52)) { @@ -157,39 +210,82 @@ static int lgs8gxx_set_if_freq(struct lgs8gxx_state *priv, u32 freq /*in kHz*/) } dprintk("AFC_INIT_FREQ = 0x%08X\n", v32); - lgs8gxx_write_reg(priv, 0x09, 0xFF & (v32)); - lgs8gxx_write_reg(priv, 0x0A, 0xFF & (v32 >> 8)); - lgs8gxx_write_reg(priv, 0x0B, 0xFF & (v32 >> 16)); - lgs8gxx_write_reg(priv, 0x0C, 0xFF & (v32 >> 24)); + if (priv->config->prod == LGS8GXX_PROD_LGS8G75) { + lgs8gxx_write_reg(priv, 0x08, 0xFF & (v32)); + lgs8gxx_write_reg(priv, 0x09, 0xFF & (v32 >> 8)); + lgs8gxx_write_reg(priv, 0x0A, 0xFF & (v32 >> 16)); + lgs8gxx_write_reg(priv, 0x0B, 0xFF & (v32 >> 24)); + } else { + lgs8gxx_write_reg(priv, 0x09, 0xFF & (v32)); + lgs8gxx_write_reg(priv, 0x0A, 0xFF & (v32 >> 8)); + lgs8gxx_write_reg(priv, 0x0B, 0xFF & (v32 >> 16)); + lgs8gxx_write_reg(priv, 0x0C, 0xFF & (v32 >> 24)); + } return 0; } +static int lgs8gxx_get_afc_phase(struct lgs8gxx_state *priv) +{ + u64 val; + u32 v32 = 0; + u8 reg_addr, t; + int i; + + if (priv->config->prod == LGS8GXX_PROD_LGS8G75) + reg_addr = 0x23; + else + reg_addr = 0x48; + + for (i = 0; i < 4; i++) { + lgs8gxx_read_reg(priv, reg_addr, &t); + v32 <<= 8; + v32 |= t; + reg_addr--; + } + + val = v32; + val *= priv->config->if_clk_freq; + val /= (u64)1 << 32; + dprintk("AFC = %u kHz\n", (u32)val); + return 0; +} + static int lgs8gxx_set_mode_auto(struct lgs8gxx_state *priv) { u8 t; + u8 prod = priv->config->prod; - if (priv->config->prod == LGS8GXX_PROD_LGS8913) + if (prod == LGS8GXX_PROD_LGS8913) lgs8gxx_write_reg(priv, 0xC6, 0x01); - lgs8gxx_read_reg(priv, 0x7E, &t); - lgs8gxx_write_reg(priv, 0x7E, t | 0x01); - - /* clear FEC self reset */ - lgs8gxx_read_reg(priv, 0xC5, &t); - lgs8gxx_write_reg(priv, 0xC5, t & 0xE0); + if (prod == LGS8GXX_PROD_LGS8G75) { + lgs8gxx_read_reg(priv, 0x0C, &t); + t &= (~0x04); + lgs8gxx_write_reg(priv, 0x0C, t | 0x80); + lgs8gxx_write_reg(priv, 0x39, 0x00); + lgs8gxx_write_reg(priv, 0x3D, 0x04); + } else if (prod == LGS8GXX_PROD_LGS8913 || + prod == LGS8GXX_PROD_LGS8GL5 || + prod == LGS8GXX_PROD_LGS8G42 || + prod == LGS8GXX_PROD_LGS8G52 || + prod == LGS8GXX_PROD_LGS8G54) { + lgs8gxx_read_reg(priv, 0x7E, &t); + lgs8gxx_write_reg(priv, 0x7E, t | 0x01); + + /* clear FEC self reset */ + lgs8gxx_read_reg(priv, 0xC5, &t); + lgs8gxx_write_reg(priv, 0xC5, t & 0xE0); + } - if (priv->config->prod == LGS8GXX_PROD_LGS8913) { + if (prod == LGS8GXX_PROD_LGS8913) { /* FEC auto detect */ lgs8gxx_write_reg(priv, 0xC1, 0x03); lgs8gxx_read_reg(priv, 0x7C, &t); t = (t & 0x8C) | 0x03; lgs8gxx_write_reg(priv, 0x7C, t); - } - - if (priv->config->prod == LGS8GXX_PROD_LGS8913) { /* BER test mode */ lgs8gxx_read_reg(priv, 0xC3, &t); t = (t & 0xEF) | 0x10; @@ -207,6 +303,32 @@ static int lgs8gxx_set_mode_manual(struct lgs8gxx_state *priv) int ret = 0; u8 t; + if (priv->config->prod == LGS8GXX_PROD_LGS8G75) { + u8 t2; + lgs8gxx_read_reg(priv, 0x0C, &t); + t &= (~0x80); + lgs8gxx_write_reg(priv, 0x0C, t); + + lgs8gxx_read_reg(priv, 0x0C, &t); + lgs8gxx_read_reg(priv, 0x19, &t2); + + if (((t&0x03) == 0x01) && (t2&0x01)) { + lgs8gxx_write_reg(priv, 0x6E, 0x05); + lgs8gxx_write_reg(priv, 0x39, 0x02); + lgs8gxx_write_reg(priv, 0x39, 0x03); + lgs8gxx_write_reg(priv, 0x3D, 0x05); + lgs8gxx_write_reg(priv, 0x3E, 0x28); + lgs8gxx_write_reg(priv, 0x53, 0x80); + } else { + lgs8gxx_write_reg(priv, 0x6E, 0x3F); + lgs8gxx_write_reg(priv, 0x39, 0x00); + lgs8gxx_write_reg(priv, 0x3D, 0x04); + } + + lgs8gxx_soft_reset(priv); + return 0; + } + /* turn off auto-detect; manual settings */ lgs8gxx_write_reg(priv, 0x7E, 0); if (priv->config->prod == LGS8GXX_PROD_LGS8913) @@ -226,11 +348,39 @@ static int lgs8gxx_is_locked(struct lgs8gxx_state *priv, u8 *locked) int ret = 0; u8 t; - ret = lgs8gxx_read_reg(priv, 0x4B, &t); + if (priv->config->prod == LGS8GXX_PROD_LGS8G75) + ret = lgs8gxx_read_reg(priv, 0x13, &t); + else + ret = lgs8gxx_read_reg(priv, 0x4B, &t); if (ret != 0) return ret; - *locked = ((t & 0xC0) == 0xC0) ? 1 : 0; + if (priv->config->prod == LGS8GXX_PROD_LGS8G75) + *locked = ((t & 0x80) == 0x80) ? 1 : 0; + else + *locked = ((t & 0xC0) == 0xC0) ? 1 : 0; + return 0; +} + +/* Wait for Code Acquisition Lock */ +static int lgs8gxx_wait_ca_lock(struct lgs8gxx_state *priv, u8 *locked) +{ + int ret = 0; + u8 reg, mask, val; + + if (priv->config->prod == LGS8GXX_PROD_LGS8G75) { + reg = 0x13; + mask = 0x80; + val = 0x80; + } else { + reg = 0x4B; + mask = 0xC0; + val = 0xC0; + } + + ret = wait_reg_mask(priv, reg, mask, val, 50, 40); + *locked = (ret == 0) ? 1 : 0; + return 0; } @@ -238,21 +388,30 @@ static int lgs8gxx_is_autodetect_finished(struct lgs8gxx_state *priv, u8 *finished) { int ret = 0; - u8 t; + u8 reg, mask, val; - ret = lgs8gxx_read_reg(priv, 0xA4, &t); - if (ret != 0) - return ret; + if (priv->config->prod == LGS8GXX_PROD_LGS8G75) { + reg = 0x1f; + mask = 0xC0; + val = 0x80; + } else { + reg = 0xA4; + mask = 0x03; + val = 0x01; + } - *finished = ((t & 0x3) == 0x1) ? 1 : 0; + ret = wait_reg_mask(priv, reg, mask, val, 10, 20); + *finished = (ret == 0) ? 1 : 0; return 0; } -static int lgs8gxx_autolock_gi(struct lgs8gxx_state *priv, u8 gi, u8 *locked) +static int lgs8gxx_autolock_gi(struct lgs8gxx_state *priv, u8 gi, u8 cpn, + u8 *locked) { - int err; + int err = 0; u8 ad_fini = 0; + u8 t1, t2; if (gi == GI_945) dprintk("try GI 945\n"); @@ -260,17 +419,29 @@ static int lgs8gxx_autolock_gi(struct lgs8gxx_state *priv, u8 gi, u8 *locked) dprintk("try GI 595\n"); else if (gi == GI_420) dprintk("try GI 420\n"); - lgs8gxx_write_reg(priv, 0x04, gi); + if (priv->config->prod == LGS8GXX_PROD_LGS8G75) { + lgs8gxx_read_reg(priv, 0x0C, &t1); + lgs8gxx_read_reg(priv, 0x18, &t2); + t1 &= ~(GI_MASK); + t1 |= gi; + t2 &= 0xFE; + t2 |= cpn ? 0x01 : 0x00; + lgs8gxx_write_reg(priv, 0x0C, t1); + lgs8gxx_write_reg(priv, 0x18, t2); + } else { + lgs8gxx_write_reg(priv, 0x04, gi); + } lgs8gxx_soft_reset(priv); - msleep(50); + err = lgs8gxx_wait_ca_lock(priv, locked); + if (err || !(*locked)) + return err; err = lgs8gxx_is_autodetect_finished(priv, &ad_fini); if (err != 0) return err; if (ad_fini) { - err = lgs8gxx_is_locked(priv, locked); - if (err != 0) - return err; - } + dprintk("auto detect finished\n"); + } else + *locked = 0; return 0; } @@ -285,13 +456,18 @@ static int lgs8gxx_auto_detect(struct lgs8gxx_state *priv, dprintk("%s\n", __func__); lgs8gxx_set_mode_auto(priv); - /* Guard Interval */ - lgs8gxx_write_reg(priv, 0x03, 00); + if (priv->config->prod == LGS8GXX_PROD_LGS8G75) { + lgs8gxx_write_reg(priv, 0x67, 0xAA); + lgs8gxx_write_reg(priv, 0x6E, 0x3F); + } else { + /* Guard Interval */ + lgs8gxx_write_reg(priv, 0x03, 00); + } for (i = 0; i < 2; i++) { for (j = 0; j < 2; j++) { tmp_gi = GI_945; - err = lgs8gxx_autolock_gi(priv, GI_945, &locked); + err = lgs8gxx_autolock_gi(priv, GI_945, j, &locked); if (err) goto out; if (locked) @@ -299,14 +475,14 @@ static int lgs8gxx_auto_detect(struct lgs8gxx_state *priv, } for (j = 0; j < 2; j++) { tmp_gi = GI_420; - err = lgs8gxx_autolock_gi(priv, GI_420, &locked); + err = lgs8gxx_autolock_gi(priv, GI_420, j, &locked); if (err) goto out; if (locked) goto locked; } tmp_gi = GI_595; - err = lgs8gxx_autolock_gi(priv, GI_595, &locked); + err = lgs8gxx_autolock_gi(priv, GI_595, 1, &locked); if (err) goto out; if (locked) @@ -317,8 +493,13 @@ locked: if ((err == 0) && (locked == 1)) { u8 t; - lgs8gxx_read_reg(priv, 0xA2, &t); - *detected_param = t; + if (priv->config->prod != LGS8GXX_PROD_LGS8G75) { + lgs8gxx_read_reg(priv, 0xA2, &t); + *detected_param = t; + } else { + lgs8gxx_read_reg(priv, 0x1F, &t); + *detected_param = t & 0x3F; + } if (tmp_gi == GI_945) dprintk("GI 945 locked\n"); @@ -349,18 +530,28 @@ static void lgs8gxx_auto_lock(struct lgs8gxx_state *priv) lgs8gxx_write_reg(priv, 0x03, 0x01); #endif dprintk("lgs8gxx_auto_detect failed\n"); - } + } else + dprintk("detected param = 0x%02X\n", detected_param); /* Apply detected parameters */ if (priv->config->prod == LGS8GXX_PROD_LGS8913) { u8 inter_leave_len = detected_param & TIM_MASK ; - inter_leave_len = (inter_leave_len == TIM_LONG) ? 0x60 : 0x40; + /* Fix 8913 time interleaver detection bug */ + inter_leave_len = (inter_leave_len == TIM_MIDDLE) ? 0x60 : 0x40; detected_param &= CF_MASK | SC_MASK | LGS_FEC_MASK; detected_param |= inter_leave_len; } - lgs8gxx_write_reg(priv, 0x7D, detected_param); - if (priv->config->prod == LGS8GXX_PROD_LGS8913) - lgs8gxx_write_reg(priv, 0xC0, detected_param); + if (priv->config->prod == LGS8GXX_PROD_LGS8G75) { + u8 t; + lgs8gxx_read_reg(priv, 0x19, &t); + t &= 0x81; + t |= detected_param << 1; + lgs8gxx_write_reg(priv, 0x19, t); + } else { + lgs8gxx_write_reg(priv, 0x7D, detected_param); + if (priv->config->prod == LGS8GXX_PROD_LGS8913) + lgs8gxx_write_reg(priv, 0xC0, detected_param); + } /* lgs8gxx_soft_reset(priv); */ /* Enter manual mode */ @@ -382,9 +573,10 @@ static int lgs8gxx_set_mpeg_mode(struct lgs8gxx_state *priv, u8 serial, u8 clk_pol, u8 clk_gated) { int ret = 0; - u8 t; + u8 t, reg_addr; - ret = lgs8gxx_read_reg(priv, 0xC2, &t); + reg_addr = (priv->config->prod == LGS8GXX_PROD_LGS8G75) ? 0x30 : 0xC2; + ret = lgs8gxx_read_reg(priv, reg_addr, &t); if (ret != 0) return ret; @@ -393,13 +585,29 @@ static int lgs8gxx_set_mpeg_mode(struct lgs8gxx_state *priv, t |= clk_pol ? TS_CLK_INVERTED : TS_CLK_NORMAL; t |= clk_gated ? TS_CLK_GATED : TS_CLK_FREERUN; - ret = lgs8gxx_write_reg(priv, 0xC2, t); + ret = lgs8gxx_write_reg(priv, reg_addr, t); if (ret != 0) return ret; return 0; } +/* A/D input peak-to-peak voltage range */ +static int lgs8g75_set_adc_vpp(struct lgs8gxx_state *priv, + u8 sel) +{ + u8 r26 = 0x73, r27 = 0x90; + + if (priv->config->prod != LGS8GXX_PROD_LGS8G75) + return 0; + + r26 |= (sel & 0x01) << 7; + r27 |= (sel & 0x02) >> 1; + lgs8gxx_write_reg(priv, 0x26, r26); + lgs8gxx_write_reg(priv, 0x27, r27); + + return 0; +} /* LGS8913 demod frontend functions */ @@ -428,6 +636,34 @@ static int lgs8913_init(struct lgs8gxx_state *priv) return 0; } +static int lgs8g75_init_data(struct lgs8gxx_state *priv) +{ + const u8 *p = lgs8g75_initdat; + int i; + + lgs8gxx_write_reg(priv, 0xC6, 0x40); + + lgs8gxx_write_reg(priv, 0x3D, 0x04); + lgs8gxx_write_reg(priv, 0x39, 0x00); + + lgs8gxx_write_reg(priv, 0x3A, 0x00); + lgs8gxx_write_reg(priv, 0x38, 0x00); + lgs8gxx_write_reg(priv, 0x3B, 0x00); + lgs8gxx_write_reg(priv, 0x38, 0x00); + + for (i = 0; i < sizeof(lgs8g75_initdat); i++) { + lgs8gxx_write_reg(priv, 0x38, 0x00); + lgs8gxx_write_reg(priv, 0x3A, (u8)(i&0xff)); + lgs8gxx_write_reg(priv, 0x3B, (u8)(i>>8)); + lgs8gxx_write_reg(priv, 0x3C, *p); + p++; + } + + lgs8gxx_write_reg(priv, 0x38, 0x00); + + return 0; +} + static int lgs8gxx_init(struct dvb_frontend *fe) { struct lgs8gxx_state *priv = @@ -440,6 +676,9 @@ static int lgs8gxx_init(struct dvb_frontend *fe) lgs8gxx_read_reg(priv, 0, &data); dprintk("reg 0 = 0x%02X\n", data); + if (config->prod == LGS8GXX_PROD_LGS8G75) + lgs8g75_set_adc_vpp(priv, config->adc_vpp); + /* Setup MPEG output format */ err = lgs8gxx_set_mpeg_mode(priv, config->serial_ts, config->ts_clk_pol, @@ -450,8 +689,7 @@ static int lgs8gxx_init(struct dvb_frontend *fe) if (config->prod == LGS8GXX_PROD_LGS8913) lgs8913_init(priv); lgs8gxx_set_if_freq(priv, priv->config->if_freq); - if (config->prod != LGS8GXX_PROD_LGS8913) - lgs8gxx_set_ad_mode(priv); + lgs8gxx_set_ad_mode(priv); return 0; } @@ -508,12 +746,6 @@ static int lgs8gxx_set_fe(struct dvb_frontend *fe, static int lgs8gxx_get_fe(struct dvb_frontend *fe, struct dvb_frontend_parameters *fe_params) { - struct lgs8gxx_state *priv = fe->demodulator_priv; - u8 t; -#if 0 - int translated_fec = FEC_1_2; -#endif - dprintk("%s\n", __func__); /* TODO: get real readings from device */ @@ -523,47 +755,10 @@ static int lgs8gxx_get_fe(struct dvb_frontend *fe, /* bandwidth */ fe_params->u.ofdm.bandwidth = BANDWIDTH_8_MHZ; - - lgs8gxx_read_reg(priv, 0x7D, &t); -#if 0 - /* FEC. No exact match for DMB-TH, pick approx. value */ - switch (t & LGS_FEC_MASK) { - case LGS_FEC_0_4: /* FEC 0.4 */ - translated_fec = FEC_1_2; - break; - case LGS_FEC_0_6: /* FEC 0.6 */ - translated_fec = FEC_2_3; - break; - case LGS_FEC_0_8: /* FEC 0.8 */ - translated_fec = FEC_5_6; - break; - default: - translated_fec = FEC_1_2; - } - fe_params->u.ofdm.code_rate_HP = translated_fec; - fe_params->u.ofdm.code_rate_LP = translated_fec; -#endif fe_params->u.ofdm.code_rate_HP = FEC_AUTO; fe_params->u.ofdm.code_rate_LP = FEC_AUTO; - /* constellation */ - switch (t & SC_MASK) { - case SC_QAM64: - fe_params->u.ofdm.constellation = QAM_64; - break; - case SC_QAM32: - fe_params->u.ofdm.constellation = QAM_32; - break; - case SC_QAM16: - fe_params->u.ofdm.constellation = QAM_16; - break; - case SC_QAM4: - case SC_QAM4NR: - fe_params->u.ofdm.constellation = QPSK; - break; - default: - fe_params->u.ofdm.constellation = QAM_64; - } + fe_params->u.ofdm.constellation = QAM_AUTO; /* transmission mode */ fe_params->u.ofdm.transmission_mode = TRANSMISSION_MODE_AUTO; @@ -592,9 +787,19 @@ static int lgs8gxx_read_status(struct dvb_frontend *fe, fe_status_t *fe_status) { struct lgs8gxx_state *priv = fe->demodulator_priv; s8 ret; - u8 t; + u8 t, locked = 0; dprintk("%s\n", __func__); + *fe_status = 0; + + lgs8gxx_get_afc_phase(priv); + lgs8gxx_is_locked(priv, &locked); + if (priv->config->prod == LGS8GXX_PROD_LGS8G75) { + if (locked) + *fe_status |= FE_HAS_SIGNAL | FE_HAS_CARRIER | + FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK; + return 0; + } ret = lgs8gxx_read_reg(priv, 0x4B, &t); if (ret != 0) @@ -698,12 +903,33 @@ static int lgs8913_read_signal_strength(struct lgs8gxx_state *priv, u16 *signal) return 0; } +static int lgs8g75_read_signal_strength(struct lgs8gxx_state *priv, u16 *signal) +{ + u8 t; + s16 v = 0; + + dprintk("%s\n", __func__); + + lgs8gxx_read_reg(priv, 0xB1, &t); + v |= t; + v <<= 8; + lgs8gxx_read_reg(priv, 0xB0, &t); + v |= t; + + *signal = v; + dprintk("%s: signal=0x%02X\n", __func__, *signal); + + return 0; +} + static int lgs8gxx_read_signal_strength(struct dvb_frontend *fe, u16 *signal) { struct lgs8gxx_state *priv = fe->demodulator_priv; if (priv->config->prod == LGS8GXX_PROD_LGS8913) return lgs8913_read_signal_strength(priv, signal); + else if (priv->config->prod == LGS8GXX_PROD_LGS8G75) + return lgs8g75_read_signal_strength(priv, signal); else return lgs8gxx_read_signal_agc(priv, signal); } @@ -714,7 +940,10 @@ static int lgs8gxx_read_snr(struct dvb_frontend *fe, u16 *snr) u8 t; *snr = 0; - lgs8gxx_read_reg(priv, 0x95, &t); + if (priv->config->prod == LGS8GXX_PROD_LGS8G75) + lgs8gxx_read_reg(priv, 0x34, &t); + else + lgs8gxx_read_reg(priv, 0x95, &t); dprintk("AVG Noise=0x%02X\n", t); *snr = 256 - t; *snr <<= 8; @@ -730,31 +959,68 @@ static int lgs8gxx_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) return 0; } +static void packet_counter_start(struct lgs8gxx_state *priv) +{ + u8 orig, t; + + if (priv->config->prod == LGS8GXX_PROD_LGS8G75) { + lgs8gxx_read_reg(priv, 0x30, &orig); + orig &= 0xE7; + t = orig | 0x10; + lgs8gxx_write_reg(priv, 0x30, t); + t = orig | 0x18; + lgs8gxx_write_reg(priv, 0x30, t); + t = orig | 0x10; + lgs8gxx_write_reg(priv, 0x30, t); + } else { + lgs8gxx_write_reg(priv, 0xC6, 0x01); + lgs8gxx_write_reg(priv, 0xC6, 0x41); + lgs8gxx_write_reg(priv, 0xC6, 0x01); + } +} + +static void packet_counter_stop(struct lgs8gxx_state *priv) +{ + u8 t; + + if (priv->config->prod == LGS8GXX_PROD_LGS8G75) { + lgs8gxx_read_reg(priv, 0x30, &t); + t &= 0xE7; + lgs8gxx_write_reg(priv, 0x30, t); + } else { + lgs8gxx_write_reg(priv, 0xC6, 0x81); + } +} + static int lgs8gxx_read_ber(struct dvb_frontend *fe, u32 *ber) { struct lgs8gxx_state *priv = fe->demodulator_priv; - u8 r0, r1, r2, r3; - u32 total_cnt, err_cnt; + u8 reg_err, reg_total, t; + u32 total_cnt = 0, err_cnt = 0; + int i; dprintk("%s\n", __func__); - lgs8gxx_write_reg(priv, 0xc6, 0x01); - lgs8gxx_write_reg(priv, 0xc6, 0x41); - lgs8gxx_write_reg(priv, 0xc6, 0x01); - + packet_counter_start(priv); msleep(200); + packet_counter_stop(priv); + + if (priv->config->prod == LGS8GXX_PROD_LGS8G75) { + reg_total = 0x28; reg_err = 0x2C; + } else { + reg_total = 0xD0; reg_err = 0xD4; + } - lgs8gxx_write_reg(priv, 0xc6, 0x81); - lgs8gxx_read_reg(priv, 0xd0, &r0); - lgs8gxx_read_reg(priv, 0xd1, &r1); - lgs8gxx_read_reg(priv, 0xd2, &r2); - lgs8gxx_read_reg(priv, 0xd3, &r3); - total_cnt = (r3 << 24) | (r2 << 16) | (r1 << 8) | (r0); - lgs8gxx_read_reg(priv, 0xd4, &r0); - lgs8gxx_read_reg(priv, 0xd5, &r1); - lgs8gxx_read_reg(priv, 0xd6, &r2); - lgs8gxx_read_reg(priv, 0xd7, &r3); - err_cnt = (r3 << 24) | (r2 << 16) | (r1 << 8) | (r0); + for (i = 0; i < 4; i++) { + total_cnt <<= 8; + lgs8gxx_read_reg(priv, reg_total+3-i, &t); + total_cnt |= t; + } + for (i = 0; i < 4; i++) { + err_cnt <<= 8; + lgs8gxx_read_reg(priv, reg_err+3-i, &t); + err_cnt |= t; + } dprintk("error=%d total=%d\n", err_cnt, total_cnt); if (total_cnt == 0) @@ -844,6 +1110,9 @@ struct dvb_frontend *lgs8gxx_attach(const struct lgs8gxx_config *config, sizeof(struct dvb_frontend_ops)); priv->frontend.demodulator_priv = priv; + if (config->prod == LGS8GXX_PROD_LGS8G75) + lgs8g75_init_data(priv); + return &priv->frontend; error_out: diff --git a/linux/drivers/media/dvb/frontends/lgs8gxx.h b/linux/drivers/media/dvb/frontends/lgs8gxx.h index 321d366a8..33c3c5e16 100644 --- a/linux/drivers/media/dvb/frontends/lgs8gxx.h +++ b/linux/drivers/media/dvb/frontends/lgs8gxx.h @@ -1,9 +1,9 @@ /* - * Support for Legend Silicon DMB-TH demodulator - * LGS8913, LGS8GL5 + * Support for Legend Silicon GB20600 (a.k.a DMB-TH) demodulator + * LGS8913, LGS8GL5, LGS8G75 * experimental support LGS8G42, LGS8G52 * - * Copyright (C) 2007,2008 David T.L. Wong + * Copyright (C) 2007-2009 David T.L. Wong * Copyright (C) 2008 Sirius International (Hong Kong) Limited * Timothy Lee (for initial work on LGS8GL5) * @@ -34,6 +34,7 @@ #define LGS8GXX_PROD_LGS8G42 3 #define LGS8GXX_PROD_LGS8G52 4 #define LGS8GXX_PROD_LGS8G54 5 +#define LGS8GXX_PROD_LGS8G75 6 struct lgs8gxx_config { @@ -70,6 +71,10 @@ struct lgs8gxx_config { /*IF use Negative center frequency*/ u8 if_neg_center; + /*8G75 internal ADC input range selection*/ + /*0: 0.8Vpp, 1: 1.0Vpp, 2: 1.6Vpp, 3: 2.0Vpp*/ + u8 adc_vpp; + /* slave address and configuration of the tuner */ u8 tuner_address; }; diff --git a/linux/drivers/media/dvb/frontends/lgs8gxx_priv.h b/linux/drivers/media/dvb/frontends/lgs8gxx_priv.h index 9776d3068..8ef376f14 100644 --- a/linux/drivers/media/dvb/frontends/lgs8gxx_priv.h +++ b/linux/drivers/media/dvb/frontends/lgs8gxx_priv.h @@ -1,9 +1,9 @@ /* - * Support for Legend Silicon DMB-TH demodulator - * LGS8913, LGS8GL5 + * Support for Legend Silicon GB20600 (a.k.a DMB-TH) demodulator + * LGS8913, LGS8GL5, LGS8G75 * experimental support LGS8G42, LGS8G52 * - * Copyright (C) 2007,2008 David T.L. Wong + * Copyright (C) 2007-2009 David T.L. Wong * Copyright (C) 2008 Sirius International (Hong Kong) Limited * Timothy Lee (for initial work on LGS8GL5) * @@ -38,7 +38,7 @@ struct lgs8gxx_state { #define SC_QAM64 0x10 /* 64QAM modulation */ #define SC_QAM32 0x0C /* 32QAM modulation */ #define SC_QAM16 0x08 /* 16QAM modulation */ -#define SC_QAM4NR 0x04 /* 4QAM modulation */ +#define SC_QAM4NR 0x04 /* 4QAM-NR modulation */ #define SC_QAM4 0x00 /* 4QAM modulation */ #define LGS_FEC_MASK 0x03 /* FEC Rate Mask */ @@ -47,8 +47,8 @@ struct lgs8gxx_state { #define LGS_FEC_0_8 0x02 /* FEC Rate 0.8 */ #define TIM_MASK 0x20 /* Time Interleave Length Mask */ -#define TIM_LONG 0x00 /* Time Interleave Length = 720 */ -#define TIM_MIDDLE 0x20 /* Time Interleave Length = 240 */ +#define TIM_LONG 0x20 /* Time Interleave Length = 720 */ +#define TIM_MIDDLE 0x00 /* Time Interleave Length = 240 */ #define CF_MASK 0x80 /* Control Frame Mask */ #define CF_EN 0x80 /* Control Frame On */ -- cgit v1.2.3 From 8b9e242409ed16e33bc5b4e7ab3c83724a221366 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 17 Jun 2009 04:38:12 +0000 Subject: cx23885: add card Magic-Pro ProHDTV Extreme 2 From: David Wong cx23885: add card Magic-Pro ProHDTV Extreme 2 PCI-E. Signed-off-by: David T.L. Wong Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/cx23885/cx23885-cards.c | 12 ++++++++- linux/drivers/media/video/cx23885/cx23885-dvb.c | 33 +++++++++++++++++++++++ linux/drivers/media/video/cx23885/cx23885.h | 1 + 3 files changed, 45 insertions(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/cx23885/cx23885-cards.c b/linux/drivers/media/video/cx23885/cx23885-cards.c index 35b2abd6a..bf426f041 100644 --- a/linux/drivers/media/video/cx23885/cx23885-cards.c +++ b/linux/drivers/media/video/cx23885/cx23885-cards.c @@ -202,6 +202,10 @@ struct cx23885_board cx23885_boards[] = { .name = "Mygica X8506 DMB-TH", .portb = CX23885_MPEG_DVB, }, + [CX23885_BOARD_MAGICPRO_PROHDTVE2] = { + .name = "Magic-Pro ProHDTV Extreme 2", + .portb = CX23885_MPEG_DVB, + }, }; const unsigned int cx23885_bcount = ARRAY_SIZE(cx23885_boards); @@ -325,6 +329,10 @@ struct cx23885_subid cx23885_subids[] = { .subvendor = 0x14f1, .subdevice = 0x8651, .card = CX23885_BOARD_MYGICA_X8506, + }, { + .subvendor = 0x14f1, + .subdevice = 0x8657, + .card = CX23885_BOARD_MAGICPRO_PROHDTVE2, }, }; const unsigned int cx23885_idcount = ARRAY_SIZE(cx23885_subids); @@ -716,8 +724,9 @@ void cx23885_gpio_setup(struct cx23885_dev *dev) cx23885_gpio_set(dev, GPIO_9); break; case CX23885_BOARD_MYGICA_X8506: + case CX23885_BOARD_MAGICPRO_PROHDTVE2: /* GPIO-1 reset XC5000 */ - /* GPIO-2 reset LGS8GL5 */ + /* GPIO-2 reset LGS8GL5 / LGS8G75 */ cx_set(GP0_IO, 0x00060000); cx_clear(GP0_IO, 0x00000006); mdelay(100); @@ -828,6 +837,7 @@ void cx23885_card_setup(struct cx23885_dev *dev) ts2->src_sel_val = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO; break; case CX23885_BOARD_MYGICA_X8506: + case CX23885_BOARD_MAGICPRO_PROHDTVE2: ts1->gen_ctrl_val = 0x5; /* Parallel */ ts1->ts_clk_en_val = 0x1; /* Enable TS_CLK */ ts1->src_sel_val = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO; diff --git a/linux/drivers/media/video/cx23885/cx23885-dvb.c b/linux/drivers/media/video/cx23885/cx23885-dvb.c index 4bab7c814..85fac41e7 100644 --- a/linux/drivers/media/video/cx23885/cx23885-dvb.c +++ b/linux/drivers/media/video/cx23885/cx23885-dvb.c @@ -488,6 +488,26 @@ static int cx23885_dvb_set_frontend(struct dvb_frontend *fe, port->set_frontend_save(fe, param) : -ENODEV; } +static struct lgs8gxx_config magicpro_prohdtve2_lgs8g75_config = { + .prod = LGS8GXX_PROD_LGS8G75, + .demod_address = 0x19, + .serial_ts = 0, + .ts_clk_pol = 1, + .ts_clk_gated = 1, + .if_clk_freq = 30400, /* 30.4 MHz */ + .if_freq = 6500, /* 6.50 MHz */ + .if_neg_center = 1, + .ext_adc = 0, + .adc_signed = 1, + .adc_vpp = 2, /* 1.6 Vpp */ + .if_neg_edge = 1, +}; + +static struct xc5000_config magicpro_prohdtve2_xc5000_config = { + .i2c_address = 0x61, + .if_khz = 6500, +}; + static int dvb_register(struct cx23885_tsport *port) { struct cx23885_dev *dev = port->dev; @@ -834,6 +854,19 @@ static int dvb_register(struct cx23885_tsport *port) &mygica_x8506_xc5000_config); } break; + case CX23885_BOARD_MAGICPRO_PROHDTVE2: + i2c_bus = &dev->i2c_bus[0]; + i2c_bus2 = &dev->i2c_bus[1]; + fe0->dvb.frontend = dvb_attach(lgs8gxx_attach, + &magicpro_prohdtve2_lgs8g75_config, + &i2c_bus->i2c_adap); + if (fe0->dvb.frontend != NULL) { + dvb_attach(xc5000_attach, + fe0->dvb.frontend, + &i2c_bus2->i2c_adap, + &magicpro_prohdtve2_xc5000_config); + } + break; default: printk(KERN_INFO "%s: The frontend of your DVB/ATSC card " " isn't supported yet\n", diff --git a/linux/drivers/media/video/cx23885/cx23885.h b/linux/drivers/media/video/cx23885/cx23885.h index fe3feb001..2a384e6aa 100644 --- a/linux/drivers/media/video/cx23885/cx23885.h +++ b/linux/drivers/media/video/cx23885/cx23885.h @@ -77,6 +77,7 @@ #define CX23885_BOARD_HAUPPAUGE_HVR1255 20 #define CX23885_BOARD_HAUPPAUGE_HVR1210 21 #define CX23885_BOARD_MYGICA_X8506 22 +#define CX23885_BOARD_MAGICPRO_PROHDTVE2 23 #define GPIO_0 0x00000001 #define GPIO_1 0x00000002 -- cgit v1.2.3 From f40ea9829416dcd77a605a2d16a82c115a235cd2 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Wed, 17 Jun 2009 23:48:17 +0400 Subject: Fix a redundant compiler warning From: Manu Abraham Signed-off-by: Manu Abraham --- linux/drivers/media/dvb/frontends/stv090x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/frontends/stv090x.c b/linux/drivers/media/dvb/frontends/stv090x.c index 62078400f..fc6e1a42b 100644 --- a/linux/drivers/media/dvb/frontends/stv090x.c +++ b/linux/drivers/media/dvb/frontends/stv090x.c @@ -3405,7 +3405,7 @@ static u8 stv090x_optimize_carloop(struct stv090x_state *state, enum stv090x_mod static u8 stv090x_optimize_carloop_short(struct stv090x_state *state) { - struct stv090x_short_frame_crloop *short_crl; + struct stv090x_short_frame_crloop *short_crl = NULL; s32 index = 0; u8 aclc = 0x0b; -- cgit v1.2.3 From d8fa9cae0793f268eb9fbb9b06e25511730f7fd0 Mon Sep 17 00:00:00 2001 From: "hans@rhel5-devel.localdomain" Date: Wed, 17 Jun 2009 23:37:57 +0200 Subject: gspca_stv06xx: Add support for st6422 bridge and sensor From: Hans de Goede Add support for st6422 bridge and sensor to the stv06xx gspca sub driver, tested with: Logitech QuickCam Messenger 046d:08f0 ST6422 integrated Logitech QuickCam Mess. Plus 046d:08f6 ST6422 integrated Priority: normal Signed-off-by: Hans de Goede --- linux/drivers/media/video/gspca/stv06xx/Makefile | 3 +- linux/drivers/media/video/gspca/stv06xx/stv06xx.c | 53 ++- linux/drivers/media/video/gspca/stv06xx/stv06xx.h | 11 + .../media/video/gspca/stv06xx/stv06xx_hdcs.c | 10 +- .../media/video/gspca/stv06xx/stv06xx_sensor.h | 3 +- .../media/video/gspca/stv06xx/stv06xx_st6422.c | 453 +++++++++++++++++++++ .../media/video/gspca/stv06xx/stv06xx_st6422.h | 59 +++ 7 files changed, 577 insertions(+), 15 deletions(-) create mode 100644 linux/drivers/media/video/gspca/stv06xx/stv06xx_st6422.c create mode 100644 linux/drivers/media/video/gspca/stv06xx/stv06xx_st6422.h (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/stv06xx/Makefile b/linux/drivers/media/video/gspca/stv06xx/Makefile index feeaa94ab..2f3c3a606 100644 --- a/linux/drivers/media/video/gspca/stv06xx/Makefile +++ b/linux/drivers/media/video/gspca/stv06xx/Makefile @@ -3,7 +3,8 @@ obj-$(CONFIG_USB_STV06XX) += gspca_stv06xx.o gspca_stv06xx-objs := stv06xx.o \ stv06xx_vv6410.o \ stv06xx_hdcs.o \ - stv06xx_pb0100.o + stv06xx_pb0100.o \ + stv06xx_st6422.o EXTRA_CFLAGS += -Idrivers/media/video/gspca diff --git a/linux/drivers/media/video/gspca/stv06xx/stv06xx.c b/linux/drivers/media/video/gspca/stv06xx/stv06xx.c index e573c3406..0da8e0de0 100644 --- a/linux/drivers/media/video/gspca/stv06xx/stv06xx.c +++ b/linux/drivers/media/video/gspca/stv06xx/stv06xx.c @@ -92,11 +92,10 @@ static int stv06xx_write_sensor_finish(struct sd *sd) { int err = 0; - if (IS_850(sd)) { + if (sd->bridge == BRIDGE_STV610) { struct usb_device *udev = sd->gspca_dev.dev; __u8 *buf = sd->gspca_dev.usb_buf; - /* Quickam Web needs an extra packet */ buf[0] = 0; err = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x04, 0x40, 0x1704, 0, buf, 1, @@ -253,7 +252,7 @@ static int stv06xx_init(struct gspca_dev *gspca_dev) err = sd->sensor->init(sd); - if (dump_sensor) + if (dump_sensor && sd->sensor->dump) sd->sensor->dump(sd); return (err < 0) ? err : 0; @@ -318,6 +317,8 @@ static void stv06xx_pkt_scan(struct gspca_dev *gspca_dev, __u8 *data, /* isoc packet */ int len) /* iso packet length */ { + struct sd *sd = (struct sd *) gspca_dev; + PDEBUG(D_PACK, "Packet of length %d arrived", len); /* A packet may contain several frames @@ -343,14 +344,29 @@ static void stv06xx_pkt_scan(struct gspca_dev *gspca_dev, if (len < chunk_len) { PDEBUG(D_ERR, "URB packet length is smaller" " than the specified chunk length"); + gspca_dev->last_packet_type = DISCARD_PACKET; return; } + /* First byte seem to be 02=data 2nd byte is unknown??? */ + if (sd->bridge == BRIDGE_ST6422 && (id & 0xFF00) == 0x0200) + goto frame_data; + switch (id) { case 0x0200: case 0x4200: +frame_data: PDEBUG(D_PACK, "Frame data packet detected"); + if (sd->to_skip) { + int skip = (sd->to_skip < chunk_len) ? + sd->to_skip : chunk_len; + data += skip; + len -= skip; + chunk_len -= skip; + sd->to_skip -= skip; + } + gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, chunk_len); break; @@ -365,6 +381,9 @@ static void stv06xx_pkt_scan(struct gspca_dev *gspca_dev, gspca_frame_add(gspca_dev, FIRST_PACKET, frame, data, 0); + if (sd->bridge == BRIDGE_ST6422) + sd->to_skip = gspca_dev->width * 4; + if (chunk_len) PDEBUG(D_ERR, "Chunk length is " "non-zero on a SOF"); @@ -395,8 +414,12 @@ static void stv06xx_pkt_scan(struct gspca_dev *gspca_dev, /* Unknown chunk with 2 bytes of data, occurs 2-3 times per USB interrupt */ break; + case 0x42ff: + PDEBUG(D_PACK, "Chunk 0x42ff detected"); + /* Special chunk seen sometimes on the ST6422 */ + break; default: - PDEBUG(D_PACK, "Unknown chunk %d detected", id); + PDEBUG(D_PACK, "Unknown chunk 0x%04x detected", id); /* Unknown chunk */ } data += chunk_len; @@ -428,11 +451,16 @@ static int stv06xx_config(struct gspca_dev *gspca_dev, cam = &gspca_dev->cam; sd->desc = sd_desc; + sd->bridge = id->driver_info; gspca_dev->sd_desc = &sd->desc; if (dump_bridge) stv06xx_dump_bridge(sd); + sd->sensor = &stv06xx_sensor_st6422; + if (!sd->sensor->probe(sd)) + return 0; + sd->sensor = &stv06xx_sensor_vv6410; if (!sd->sensor->probe(sd)) return 0; @@ -457,9 +485,20 @@ static int stv06xx_config(struct gspca_dev *gspca_dev, /* -- module initialisation -- */ static const __devinitdata struct usb_device_id device_table[] = { - {USB_DEVICE(0x046d, 0x0840)}, /* QuickCam Express */ - {USB_DEVICE(0x046d, 0x0850)}, /* LEGO cam / QuickCam Web */ - {USB_DEVICE(0x046d, 0x0870)}, /* Dexxa WebCam USB */ + /* QuickCam Express */ + {USB_DEVICE(0x046d, 0x0840), .driver_info = BRIDGE_STV600 }, + /* LEGO cam / QuickCam Web */ + {USB_DEVICE(0x046d, 0x0850), .driver_info = BRIDGE_STV610 }, + /* Dexxa WebCam USB */ + {USB_DEVICE(0x046d, 0x0870), .driver_info = BRIDGE_STV602 }, + /* QuickCam Messenger */ + {USB_DEVICE(0x046D, 0x08F0), .driver_info = BRIDGE_ST6422 }, + /* QuickCam Communicate */ + {USB_DEVICE(0x046D, 0x08F5), .driver_info = BRIDGE_ST6422 }, + /* QuickCam Messenger (new) */ + {USB_DEVICE(0x046D, 0x08F6), .driver_info = BRIDGE_ST6422 }, + /* QuickCam Messenger (new) */ + {USB_DEVICE(0x046D, 0x08DA), .driver_info = BRIDGE_ST6422 }, {} }; MODULE_DEVICE_TABLE(usb, device_table); diff --git a/linux/drivers/media/video/gspca/stv06xx/stv06xx.h b/linux/drivers/media/video/gspca/stv06xx/stv06xx.h index 1207e7d17..9df7137fe 100644 --- a/linux/drivers/media/video/gspca/stv06xx/stv06xx.h +++ b/linux/drivers/media/video/gspca/stv06xx/stv06xx.h @@ -93,6 +93,17 @@ struct sd { /* Sensor private data */ void *sensor_priv; + + /* The first 4 lines produced by the stv6422 are no good, this keeps + track of how many bytes we still need to skip during a frame */ + int to_skip; + + /* Bridge / Camera type */ + u8 bridge; + #define BRIDGE_STV600 0 + #define BRIDGE_STV602 1 + #define BRIDGE_STV610 2 + #define BRIDGE_ST6422 3 /* With integrated sensor */ }; int stv06xx_write_bridge(struct sd *sd, u16 address, u16 i2c_data); diff --git a/linux/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.c b/linux/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.c index b16903814..3039ec208 100644 --- a/linux/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.c +++ b/linux/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.c @@ -434,7 +434,7 @@ static int hdcs_probe_1x00(struct sd *sd) hdcs->exp.er = 100; /* - * Frame rate on HDCS-1000 0x46D:0x840 depends on PSMP: + * Frame rate on HDCS-1000 with STV600 depends on PSMP: * 4 = doesn't work at all * 5 = 7.8 fps, * 6 = 6.9 fps, @@ -443,7 +443,7 @@ static int hdcs_probe_1x00(struct sd *sd) * 15 = 4.4 fps, * 31 = 2.8 fps * - * Frame rate on HDCS-1000 0x46D:0x870 depends on PSMP: + * Frame rate on HDCS-1000 with STV602 depends on PSMP: * 15 = doesn't work at all * 18 = doesn't work at all * 19 = 7.3 fps @@ -453,7 +453,7 @@ static int hdcs_probe_1x00(struct sd *sd) * 24 = 6.3 fps * 30 = 5.4 fps */ - hdcs->psmp = IS_870(sd) ? 20 : 5; + hdcs->psmp = (sd->bridge == BRIDGE_STV602) ? 20 : 5; sd->sensor_priv = hdcs; @@ -530,7 +530,7 @@ static int hdcs_init(struct sd *sd) int i, err = 0; /* Set the STV0602AA in STV0600 emulation mode */ - if (IS_870(sd)) + if (sd->bridge == BRIDGE_STV602) stv06xx_write_bridge(sd, STV_STV0600_EMULATION, 1); /* Execute the bridge init */ @@ -558,7 +558,7 @@ static int hdcs_init(struct sd *sd) return err; /* Set PGA sample duration - (was 0x7E for IS_870, but caused slow framerate with HDCS-1020) */ + (was 0x7E for the STV602, but caused slow framerate with HDCS-1020) */ if (IS_1020(sd)) err = stv06xx_write_sensor(sd, HDCS_TCTRL, (HDCS_ADC_START_SIG_DUR << 6) | hdcs->psmp); diff --git a/linux/drivers/media/video/gspca/stv06xx/stv06xx_sensor.h b/linux/drivers/media/video/gspca/stv06xx/stv06xx_sensor.h index e88c42f7d..934b9cebc 100644 --- a/linux/drivers/media/video/gspca/stv06xx/stv06xx_sensor.h +++ b/linux/drivers/media/video/gspca/stv06xx/stv06xx_sensor.h @@ -32,14 +32,13 @@ #include "stv06xx.h" -#define IS_850(sd) ((sd)->gspca_dev.dev->descriptor.idProduct == 0x850) -#define IS_870(sd) ((sd)->gspca_dev.dev->descriptor.idProduct == 0x870) #define IS_1020(sd) ((sd)->sensor == &stv06xx_sensor_hdcs1020) extern const struct stv06xx_sensor stv06xx_sensor_vv6410; extern const struct stv06xx_sensor stv06xx_sensor_hdcs1x00; extern const struct stv06xx_sensor stv06xx_sensor_hdcs1020; extern const struct stv06xx_sensor stv06xx_sensor_pb0100; +extern const struct stv06xx_sensor stv06xx_sensor_st6422; struct stv06xx_sensor { /* Defines the name of a sensor */ diff --git a/linux/drivers/media/video/gspca/stv06xx/stv06xx_st6422.c b/linux/drivers/media/video/gspca/stv06xx/stv06xx_st6422.c new file mode 100644 index 000000000..87cb5b9dd --- /dev/null +++ b/linux/drivers/media/video/gspca/stv06xx/stv06xx_st6422.c @@ -0,0 +1,453 @@ +/* + * Support for the sensor part which is integrated (I think) into the + * st6422 stv06xx alike bridge, as its integrated there are no i2c writes + * but instead direct bridge writes. + * + * Copyright (c) 2009 Hans de Goede + * + * Strongly based on qc-usb-messenger, which is: + * Copyright (c) 2001 Jean-Fredric Clere, Nikolas Zimmermann, Georg Acher + * Mark Cave-Ayland, Carlo E Prelz, Dick Streefland + * Copyright (c) 2002, 2003 Tuukka Toivonen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include "stv06xx_st6422.h" + +static struct v4l2_pix_format st6422_mode[] = { + /* Note we actually get 124 lines of data, of which we skip the 4st + 4 as they are garbage */ + { + 162, + 120, + V4L2_PIX_FMT_SGRBG8, + V4L2_FIELD_NONE, + .sizeimage = 162 * 120, + .bytesperline = 162, + .colorspace = V4L2_COLORSPACE_SRGB, + .priv = 1 + }, + /* Note we actually get 248 lines of data, of which we skip the 4st + 4 as they are garbage, and we tell the app it only gets the + first 240 of the 244 lines it actually gets, so that it ignores + the last 4. */ + { + 324, + 240, + V4L2_PIX_FMT_SGRBG8, + V4L2_FIELD_NONE, + .sizeimage = 324 * 244, + .bytesperline = 324, + .colorspace = V4L2_COLORSPACE_SRGB, + .priv = 0 + }, +}; + +static const struct ctrl st6422_ctrl[] = { +#define BRIGHTNESS_IDX 0 + { + { + .id = V4L2_CID_BRIGHTNESS, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Brightness", + .minimum = 0, + .maximum = 31, + .step = 1, + .default_value = 3 + }, + .set = st6422_set_brightness, + .get = st6422_get_brightness + }, +#define CONTRAST_IDX 1 + { + { + .id = V4L2_CID_CONTRAST, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Contrast", + .minimum = 0, + .maximum = 15, + .step = 1, + .default_value = 11 + }, + .set = st6422_set_contrast, + .get = st6422_get_contrast + }, +#define GAIN_IDX 2 + { + { + .id = V4L2_CID_GAIN, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Gain", + .minimum = 0, + .maximum = 255, + .step = 1, + .default_value = 64 + }, + .set = st6422_set_gain, + .get = st6422_get_gain + }, +#define EXPOSURE_IDX 3 + { + { + .id = V4L2_CID_EXPOSURE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Exposure", + .minimum = 0, + .maximum = 1023, + .step = 1, + .default_value = 256 + }, + .set = st6422_set_exposure, + .get = st6422_get_exposure + }, +}; + +static int st6422_probe(struct sd *sd) +{ + int i; + s32 *sensor_settings; + + if (sd->bridge != BRIDGE_ST6422) + return -ENODEV; + + info("st6422 sensor detected"); + + sensor_settings = kmalloc(ARRAY_SIZE(st6422_ctrl) * sizeof(s32), + GFP_KERNEL); + if (!sensor_settings) + return -ENOMEM; + + sd->gspca_dev.cam.cam_mode = st6422_mode; + sd->gspca_dev.cam.nmodes = ARRAY_SIZE(st6422_mode); + sd->desc.ctrls = st6422_ctrl; + sd->desc.nctrls = ARRAY_SIZE(st6422_ctrl); + sd->sensor_priv = sensor_settings; + + for (i = 0; i < sd->desc.nctrls; i++) + sensor_settings[i] = st6422_ctrl[i].qctrl.default_value; + + return 0; +} + +static int st6422_init(struct sd *sd) +{ + int err = 0, i; + + const u16 st6422_bridge_init[][2] = { + { STV_ISO_ENABLE, 0x00 }, /* disable capture */ + { 0x1436, 0x00 }, + { 0x1432, 0x03 }, /* 0x00-0x1F brightness */ + { 0x143a, 0xF9 }, /* 0x00-0x0F contrast */ + { 0x0509, 0x38 }, /* R */ + { 0x050a, 0x38 }, /* G */ + { 0x050b, 0x38 }, /* B */ + { 0x050c, 0x2A }, + { 0x050d, 0x01 }, + + + { 0x1431, 0x00 }, /* 0x00-0x07 ??? */ + { 0x1433, 0x34 }, /* 160x120, 0x00-0x01 night filter */ + { 0x1438, 0x18 }, /* 640x480 */ +/* 18 bayes */ +/* 10 compressed? */ + + { 0x1439, 0x00 }, +/* antiflimmer?? 0xa2 ger perfekt bild mot monitor */ + + { 0x143b, 0x05 }, + { 0x143c, 0x00 }, /* 0x00-0x01 - ??? */ + + +/* shutter time 0x0000-0x03FF */ +/* low value give good picures on moving objects (but requires much light) */ +/* high value gives good picures in darkness (but tends to be overexposed) */ + { 0x143e, 0x01 }, + { 0x143d, 0x00 }, + + { 0x1442, 0xe2 }, +/* write: 1x1x xxxx */ +/* read: 1x1x xxxx */ +/* bit 5 == button pressed and hold if 0 */ +/* write 0xe2,0xea */ + +/* 0x144a */ +/* 0x00 init */ +/* bit 7 == button has been pressed, but not handled */ + +/* interrupt */ +/* if(urb->iso_frame_desc[i].status == 0x80) { */ +/* if(urb->iso_frame_desc[i].status == 0x88) { */ + + { 0x1500, 0xd0 }, + { 0x1500, 0xd0 }, + { 0x1500, 0x50 }, /* 0x00 - 0xFF 0x80 == compr ? */ + + { 0x1501, 0xaf }, +/* high val-> ljus area blir morkare. */ +/* low val -> ljus area blir ljusare. */ + { 0x1502, 0xc2 }, +/* high val-> ljus area blir morkare. */ +/* low val -> ljus area blir ljusare. */ + { 0x1503, 0x45 }, +/* high val-> ljus area blir morkare. */ +/* low val -> ljus area blir ljusare. */ + + { 0x1505, 0x02 }, +/* 2 : 324x248 80352 bytes */ +/* 7 : 248x162 40176 bytes */ +/* c+f: 162*124 20088 bytes */ + + { 0x150e, 0x8e }, + { 0x150f, 0x37 }, + { 0x15c0, 0x00 }, + { 0x15c1, 1023 }, /* 160x120, ISOC_PACKET_SIZE */ + { 0x15c3, 0x08 }, /* 0x04/0x14 ... test pictures ??? */ + + + { 0x143f, 0x01 }, /* commit settings */ + + }; + + for (i = 0; i < ARRAY_SIZE(st6422_bridge_init) && !err; i++) { + err = stv06xx_write_bridge(sd, st6422_bridge_init[i][0], + st6422_bridge_init[i][1]); + } + + return err; +} + +static void st6422_disconnect(struct sd *sd) +{ + sd->sensor = NULL; + kfree(sd->sensor_priv); +} + +static int st6422_start(struct sd *sd) +{ + int err, packet_size; + struct cam *cam = &sd->gspca_dev.cam; + s32 *sensor_settings = sd->sensor_priv; + struct usb_host_interface *alt; + struct usb_interface *intf; + + intf = usb_ifnum_to_if(sd->gspca_dev.dev, sd->gspca_dev.iface); + alt = usb_altnum_to_altsetting(intf, sd->gspca_dev.alt); + if (!alt) { + PDEBUG(D_ERR, "Couldn't get altsetting"); + return -EIO; + } + + packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize); + err = stv06xx_write_bridge(sd, 0x15c1, packet_size); + if (err < 0) + return err; + + if (cam->cam_mode[sd->gspca_dev.curr_mode].priv) + err = stv06xx_write_bridge(sd, 0x1505, 0x0f); + else + err = stv06xx_write_bridge(sd, 0x1505, 0x02); + if (err < 0) + return err; + + err = st6422_set_brightness(&sd->gspca_dev, + sensor_settings[BRIGHTNESS_IDX]); + if (err < 0) + return err; + + err = st6422_set_contrast(&sd->gspca_dev, + sensor_settings[CONTRAST_IDX]); + if (err < 0) + return err; + + err = st6422_set_exposure(&sd->gspca_dev, + sensor_settings[EXPOSURE_IDX]); + if (err < 0) + return err; + + err = st6422_set_gain(&sd->gspca_dev, + sensor_settings[GAIN_IDX]); + if (err < 0) + return err; + + PDEBUG(D_STREAM, "Starting stream"); + + return 0; +} + +static int st6422_stop(struct sd *sd) +{ + PDEBUG(D_STREAM, "Halting stream"); + + return 0; +} + +static int st6422_get_brightness(struct gspca_dev *gspca_dev, __s32 *val) +{ + struct sd *sd = (struct sd *) gspca_dev; + s32 *sensor_settings = sd->sensor_priv; + + *val = sensor_settings[BRIGHTNESS_IDX]; + + PDEBUG(D_V4L2, "Read brightness %d", *val); + + return 0; +} + +static int st6422_set_brightness(struct gspca_dev *gspca_dev, __s32 val) +{ + int err; + struct sd *sd = (struct sd *) gspca_dev; + s32 *sensor_settings = sd->sensor_priv; + + sensor_settings[BRIGHTNESS_IDX] = val; + + if (!gspca_dev->streaming) + return 0; + + /* val goes from 0 -> 31 */ + PDEBUG(D_V4L2, "Set brightness to %d", val); + err = stv06xx_write_bridge(sd, 0x1432, val); + if (err < 0) + return err; + + /* commit settings */ + err = stv06xx_write_bridge(sd, 0x143f, 0x01); + return (err < 0) ? err : 0; +} + +static int st6422_get_contrast(struct gspca_dev *gspca_dev, __s32 *val) +{ + struct sd *sd = (struct sd *) gspca_dev; + s32 *sensor_settings = sd->sensor_priv; + + *val = sensor_settings[CONTRAST_IDX]; + + PDEBUG(D_V4L2, "Read contrast %d", *val); + + return 0; +} + +static int st6422_set_contrast(struct gspca_dev *gspca_dev, __s32 val) +{ + int err; + struct sd *sd = (struct sd *) gspca_dev; + s32 *sensor_settings = sd->sensor_priv; + + sensor_settings[CONTRAST_IDX] = val; + + if (!gspca_dev->streaming) + return 0; + + /* Val goes from 0 -> 15 */ + PDEBUG(D_V4L2, "Set contrast to %d\n", val); + err = stv06xx_write_bridge(sd, 0x143a, 0xf0 | val); + if (err < 0) + return err; + + /* commit settings */ + err = stv06xx_write_bridge(sd, 0x143f, 0x01); + return (err < 0) ? err : 0; +} + +static int st6422_get_gain(struct gspca_dev *gspca_dev, __s32 *val) +{ + struct sd *sd = (struct sd *) gspca_dev; + s32 *sensor_settings = sd->sensor_priv; + + *val = sensor_settings[GAIN_IDX]; + + PDEBUG(D_V4L2, "Read gain %d", *val); + + return 0; +} + +static int st6422_set_gain(struct gspca_dev *gspca_dev, __s32 val) +{ + int err; + struct sd *sd = (struct sd *) gspca_dev; + s32 *sensor_settings = sd->sensor_priv; + + sensor_settings[GAIN_IDX] = val; + + if (!gspca_dev->streaming) + return 0; + + PDEBUG(D_V4L2, "Set gain to %d", val); + + /* Set red, green, blue, gain */ + err = stv06xx_write_bridge(sd, 0x0509, val); + if (err < 0) + return err; + + err = stv06xx_write_bridge(sd, 0x050a, val); + if (err < 0) + return err; + + err = stv06xx_write_bridge(sd, 0x050b, val); + if (err < 0) + return err; + + /* 2 mystery writes */ + err = stv06xx_write_bridge(sd, 0x050c, 0x2a); + if (err < 0) + return err; + + err = stv06xx_write_bridge(sd, 0x050d, 0x01); + if (err < 0) + return err; + + /* commit settings */ + err = stv06xx_write_bridge(sd, 0x143f, 0x01); + return (err < 0) ? err : 0; +} + +static int st6422_get_exposure(struct gspca_dev *gspca_dev, __s32 *val) +{ + struct sd *sd = (struct sd *) gspca_dev; + s32 *sensor_settings = sd->sensor_priv; + + *val = sensor_settings[EXPOSURE_IDX]; + + PDEBUG(D_V4L2, "Read exposure %d", *val); + + return 0; +} + +static int st6422_set_exposure(struct gspca_dev *gspca_dev, __s32 val) +{ + int err; + struct sd *sd = (struct sd *) gspca_dev; + s32 *sensor_settings = sd->sensor_priv; + + sensor_settings[EXPOSURE_IDX] = val; + + if (!gspca_dev->streaming) + return 0; + + PDEBUG(D_V4L2, "Set exposure to %d\n", val); + err = stv06xx_write_bridge(sd, 0x143d, val & 0xff); + if (err < 0) + return err; + + err = stv06xx_write_bridge(sd, 0x143e, val >> 8); + if (err < 0) + return err; + + /* commit settings */ + err = stv06xx_write_bridge(sd, 0x143f, 0x01); + return (err < 0) ? err : 0; +} diff --git a/linux/drivers/media/video/gspca/stv06xx/stv06xx_st6422.h b/linux/drivers/media/video/gspca/stv06xx/stv06xx_st6422.h new file mode 100644 index 000000000..b2d45fe50 --- /dev/null +++ b/linux/drivers/media/video/gspca/stv06xx/stv06xx_st6422.h @@ -0,0 +1,59 @@ +/* + * Support for the sensor part which is integrated (I think) into the + * st6422 stv06xx alike bridge, as its integrated there are no i2c writes + * but instead direct bridge writes. + * + * Copyright (c) 2009 Hans de Goede + * + * Strongly based on qc-usb-messenger, which is: + * Copyright (c) 2001 Jean-Fredric Clere, Nikolas Zimmermann, Georg Acher + * Mark Cave-Ayland, Carlo E Prelz, Dick Streefland + * Copyright (c) 2002, 2003 Tuukka Toivonen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#ifndef STV06XX_ST6422_H_ +#define STV06XX_ST6422_H_ + +#include "stv06xx_sensor.h" + +static int st6422_probe(struct sd *sd); +static int st6422_start(struct sd *sd); +static int st6422_init(struct sd *sd); +static int st6422_stop(struct sd *sd); +static void st6422_disconnect(struct sd *sd); + +/* V4L2 controls supported by the driver */ +static int st6422_get_brightness(struct gspca_dev *gspca_dev, __s32 *val); +static int st6422_set_brightness(struct gspca_dev *gspca_dev, __s32 val); +static int st6422_get_contrast(struct gspca_dev *gspca_dev, __s32 *val); +static int st6422_set_contrast(struct gspca_dev *gspca_dev, __s32 val); +static int st6422_get_gain(struct gspca_dev *gspca_dev, __s32 *val); +static int st6422_set_gain(struct gspca_dev *gspca_dev, __s32 val); +static int st6422_get_exposure(struct gspca_dev *gspca_dev, __s32 *val); +static int st6422_set_exposure(struct gspca_dev *gspca_dev, __s32 val); + +const struct stv06xx_sensor stv06xx_sensor_st6422 = { + .name = "ST6422", + .init = st6422_init, + .probe = st6422_probe, + .start = st6422_start, + .stop = st6422_stop, + .disconnect = st6422_disconnect, +}; + +#endif -- cgit v1.2.3 From 907ba53ad38cf9b0d8fae0d9d998060ccf939961 Mon Sep 17 00:00:00 2001 From: "hans@rhel5-devel.localdomain" Date: Wed, 17 Jun 2009 23:41:01 +0200 Subject: ov511: remove ov518 usb id's from the driver From: Hans de Goede ov511: remove ov518 usb id's from the driver, as they have not been working ever since the decompression code got removed from the kernel, and they are no supported by the gspca_ov519 module. Priority: normal Signed-off-by: Hans de Goede --- linux/drivers/media/video/ov511.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/ov511.c b/linux/drivers/media/video/ov511.c index 2839546b1..346eed722 100644 --- a/linux/drivers/media/video/ov511.c +++ b/linux/drivers/media/video/ov511.c @@ -211,8 +211,6 @@ static const int i2c_detect_tries = 5; static struct usb_device_id device_table [] = { { USB_DEVICE(VEND_OMNIVISION, PROD_OV511) }, { USB_DEVICE(VEND_OMNIVISION, PROD_OV511PLUS) }, - { USB_DEVICE(VEND_OMNIVISION, PROD_OV518) }, - { USB_DEVICE(VEND_OMNIVISION, PROD_OV518PLUS) }, { USB_DEVICE(VEND_MATTEL, PROD_ME2CAM) }, { } /* Terminating entry */ }; -- cgit v1.2.3 From 009d182e2d2e68aa96f29155fcd8bc88108d7ed2 Mon Sep 17 00:00:00 2001 From: "hans@rhel5-devel.localdomain" Date: Wed, 17 Jun 2009 23:50:10 +0200 Subject: ov511: mark as deprecated From: Hans de Goede Mark the v4l1 ov511 as deprecated as we now have ov511 support in the gspca ov519 driver. Note we should really also keep track of this in Documentation/feature-removal-schedule.txt, but that is not part of the v4l-dvb tree. Priority: normal Signed-off-by: Hans de Goede --- linux/drivers/media/video/Kconfig | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/Kconfig b/linux/drivers/media/video/Kconfig index 94f440535..061e147f6 100644 --- a/linux/drivers/media/video/Kconfig +++ b/linux/drivers/media/video/Kconfig @@ -866,9 +866,13 @@ config USB_W9968CF module will be called w9968cf. config USB_OV511 - tristate "USB OV511 Camera support" + tristate "USB OV511 Camera support (DEPRECATED)" depends on VIDEO_V4L1 ---help--- + This driver is DEPRECATED please use the gspca ov519 module + instead. Note that for the ov511 / ov518 support of the gspca module + you need atleast version 0.6.0 of libv4l. + Say Y here if you want to connect this type of camera to your computer's USB port. See for more information and for a list of supported cameras. -- cgit v1.2.3 From e7002b4ad7d625111ed8894228d81b0032a9ca01 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Thu, 18 Jun 2009 11:50:53 +0400 Subject: BUGFIX: An incorrect Carrier Recovery Loop optimization table was being loaded for a given chip version. This would cause the optimization in tuning not to be applied and thus a failed expectation, in tuning speed increment. The patch swaps the tables in use. It also fixes a possible one in a million condition where state->dev_ver implies an older Cut (Cut < 2.0, eventhough the driver doesn't attach to any Cut older than 2.0) or even negative (due to a bad I2C bus master driver) for the card combination. Thanks to Mauro Carvalho Chehab for pointing out the issue at large. From: Manu Abraham Signed-off-by: Manu Abraham --- linux/drivers/media/dvb/frontends/stv090x.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/frontends/stv090x.c b/linux/drivers/media/dvb/frontends/stv090x.c index fc6e1a42b..8b152bea3 100644 --- a/linux/drivers/media/dvb/frontends/stv090x.c +++ b/linux/drivers/media/dvb/frontends/stv090x.c @@ -3425,10 +3425,13 @@ static u8 stv090x_optimize_carloop_short(struct stv090x_state *state) break; } - if (state->dev_ver >= 0x30) - short_crl = stv090x_s2_short_crl_cut20; - else if (state->dev_ver >= 0x20) + if (state->dev_ver >= 0x30) { + /* Cut 3.0 and up */ short_crl = stv090x_s2_short_crl_cut30; + } else { + /* Cut 2.0 and up: we don't support cuts older than 2.0 */ + short_crl = stv090x_s2_short_crl_cut20; + } if (state->srate <= 3000000) aclc = short_crl[index].crl_2; -- cgit v1.2.3 From c7000e36b7ab711d11d6a8e3b86f0f1b77931cba Mon Sep 17 00:00:00 2001 From: "hans@rhel5-devel.localdomain" Date: Thu, 18 Jun 2009 10:03:16 +0200 Subject: gspca_ov519: constify ov518 inititial register value tables From: Hans de Goede gspca_ov519: constify ov518 inititial register value tables Priority: normal Signed-off-by: Hans de Goede --- linux/drivers/media/video/gspca/ov519.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/ov519.c b/linux/drivers/media/video/gspca/ov519.c index 5759f9a46..cde3a0177 100644 --- a/linux/drivers/media/video/gspca/ov519.c +++ b/linux/drivers/media/video/gspca/ov519.c @@ -1867,7 +1867,7 @@ static int ov518_configure(struct gspca_dev *gspca_dev) int rc; /* For 518 and 518+ */ - static struct ov_regvals init_518[] = { + const struct ov_regvals init_518[] = { { R51x_SYS_RESET, 0x40 }, { R51x_SYS_INIT, 0xe1 }, { R51x_SYS_RESET, 0x3e }, @@ -1878,7 +1878,7 @@ static int ov518_configure(struct gspca_dev *gspca_dev) { 0x5d, 0x03 }, }; - static struct ov_regvals norm_518[] = { + const struct ov_regvals norm_518[] = { { R51x_SYS_SNAP, 0x02 }, /* Reset */ { R51x_SYS_SNAP, 0x01 }, /* Enable */ { 0x31, 0x0f }, @@ -1891,7 +1891,7 @@ static int ov518_configure(struct gspca_dev *gspca_dev) { 0x2f, 0x80 }, }; - static struct ov_regvals norm_518_p[] = { + const struct ov_regvals norm_518_p[] = { { R51x_SYS_SNAP, 0x02 }, /* Reset */ { R51x_SYS_SNAP, 0x01 }, /* Enable */ { 0x31, 0x0f }, -- cgit v1.2.3 From 6c708ba6cc18126da65fd6231e16da9716747c11 Mon Sep 17 00:00:00 2001 From: "hans@rhel5-devel.localdomain" Date: Thu, 18 Jun 2009 10:08:11 +0200 Subject: gspca_sonixj: Fix control index numbering From: Hans de Goede The control index defines for the gspca_sonixj driver were numbered wrong, causing us to disable the wrong controls on various sensors Priority: normal Signed-off-by: Hans de Goede --- linux/drivers/media/video/gspca/sonixj.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/sonixj.c b/linux/drivers/media/video/gspca/sonixj.c index a4c935d69..f83fbba1d 100644 --- a/linux/drivers/media/video/gspca/sonixj.c +++ b/linux/drivers/media/video/gspca/sonixj.c @@ -98,6 +98,7 @@ static int sd_setinfrared(struct gspca_dev *gspca_dev, __s32 val); static int sd_getinfrared(struct gspca_dev *gspca_dev, __s32 *val); static struct ctrl sd_ctrls[] = { +#define BRIGHTNESS_IDX 0 { { .id = V4L2_CID_BRIGHTNESS, @@ -113,6 +114,7 @@ static struct ctrl sd_ctrls[] = { .set = sd_setbrightness, .get = sd_getbrightness, }, +#define CONTRAST_IDX 1 { { .id = V4L2_CID_CONTRAST, @@ -128,6 +130,7 @@ static struct ctrl sd_ctrls[] = { .set = sd_setcontrast, .get = sd_getcontrast, }, +#define COLOR_IDX 2 { { .id = V4L2_CID_SATURATION, @@ -142,6 +145,7 @@ static struct ctrl sd_ctrls[] = { .set = sd_setcolors, .get = sd_getcolors, }, +#define BLUE_BALANCE_IDX 3 { { .id = V4L2_CID_BLUE_BALANCE, @@ -156,6 +160,7 @@ static struct ctrl sd_ctrls[] = { .set = sd_setblue_balance, .get = sd_getblue_balance, }, +#define RED_BALANCE_IDX 4 { { .id = V4L2_CID_RED_BALANCE, @@ -170,6 +175,7 @@ static struct ctrl sd_ctrls[] = { .set = sd_setred_balance, .get = sd_getred_balance, }, +#define GAMMA_IDX 5 { { .id = V4L2_CID_GAMMA, @@ -184,7 +190,7 @@ static struct ctrl sd_ctrls[] = { .set = sd_setgamma, .get = sd_getgamma, }, -#define AUTOGAIN_IDX 5 +#define AUTOGAIN_IDX 6 { { .id = V4L2_CID_AUTOGAIN, @@ -200,7 +206,7 @@ static struct ctrl sd_ctrls[] = { .get = sd_getautogain, }, /* ov7630/ov7648 only */ -#define VFLIP_IDX 6 +#define VFLIP_IDX 7 { { .id = V4L2_CID_VFLIP, @@ -216,7 +222,7 @@ static struct ctrl sd_ctrls[] = { .get = sd_getvflip, }, /* mt9v111 only */ -#define INFRARED_IDX 7 +#define INFRARED_IDX 8 { { .id = V4L2_CID_INFRARED, -- cgit v1.2.3 From 29c95ac01b1ff4a23c0fbaf5dc5da56aad806a8f Mon Sep 17 00:00:00 2001 From: "hans@rhel5-devel.localdomain" Date: Thu, 18 Jun 2009 10:14:42 +0200 Subject: gspca_sonixj: enable support for 0c45:613e camera From: Hans de Goede gspca_sonixj: enable support for 0c45:613e camera, and slightly tweak the ov7630 register init values for a much better picture. Priority: normal Signed-off-by: Hans de Goede --- linux/drivers/media/video/gspca/sonixj.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/sonixj.c b/linux/drivers/media/video/gspca/sonixj.c index f83fbba1d..9ca72e2ac 100644 --- a/linux/drivers/media/video/gspca/sonixj.c +++ b/linux/drivers/media/video/gspca/sonixj.c @@ -618,7 +618,9 @@ static const u8 ov7630_sensor_init[][8] = { /* win: i2c_r from 00 to 80 */ {0xd1, 0x21, 0x03, 0x80, 0x10, 0x20, 0x80, 0x10}, {0xb1, 0x21, 0x0c, 0x20, 0x20, 0x00, 0x00, 0x10}, - {0xd1, 0x21, 0x11, 0x00, 0x48, 0xc0, 0x00, 0x10}, +/* HDG: 0x11 was 0x00 change to 0x01 for better exposure (15 fps instead of 30) + 0x13 was 0xc0 change to 0xc3 for auto gain and exposure */ + {0xd1, 0x21, 0x11, 0x01, 0x48, 0xc3, 0x00, 0x10}, {0xb1, 0x21, 0x15, 0x80, 0x03, 0x00, 0x00, 0x10}, {0xd1, 0x21, 0x17, 0x1b, 0xbd, 0x05, 0xf6, 0x10}, {0xa1, 0x21, 0x1b, 0x04, 0x00, 0x00, 0x00, 0x10}, @@ -652,7 +654,6 @@ static const u8 ov7630_sensor_init[][8] = { {0xa1, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10}, {0xb1, 0x21, 0x01, 0x80, 0x80, 0x00, 0x00, 0x10}, /* */ - {0xa1, 0x21, 0x11, 0x00, 0x00, 0x00, 0x00, 0x10}, {0xa1, 0x21, 0x2a, 0x88, 0x00, 0x00, 0x00, 0x10}, {0xa1, 0x21, 0x2b, 0x34, 0x00, 0x00, 0x00, 0x10}, /* */ @@ -2276,7 +2277,7 @@ static const __devinitdata struct usb_device_id device_table[] = { {USB_DEVICE(0x0c45, 0x613b), BSI(SN9C120, OV7660, 0x21)}, #endif {USB_DEVICE(0x0c45, 0x613c), BSI(SN9C120, HV7131R, 0x11)}, -/* {USB_DEVICE(0x0c45, 0x613e), BSI(SN9C120, OV7630, 0x??)}, */ + {USB_DEVICE(0x0c45, 0x613e), BSI(SN9C120, OV7630, 0x21)}, {USB_DEVICE(0x0c45, 0x6143), BSI(SN9C120, SP80708, 0x18)}, {} }; -- cgit v1.2.3 From 3c6cdde4a672a5ea91daf67cb9c53009c6c11d67 Mon Sep 17 00:00:00 2001 From: "hans@rhel5-devel.localdomain" Date: Thu, 18 Jun 2009 10:20:51 +0200 Subject: Mark the v4l1 uvcvideo quickcam messenger driver as deprecated From: Hans de Goede Mark the v4l1 uvcvideo quickcam messenger driver as deprecated, the one cam it supports, is now also supported by the v4l2 gspca stv06xx driver. Priority: normal Signed-off-by: Hans de Goede --- linux/drivers/media/video/usbvideo/Kconfig | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/usbvideo/Kconfig b/linux/drivers/media/video/usbvideo/Kconfig index e4cb99c1f..adb1c044a 100644 --- a/linux/drivers/media/video/usbvideo/Kconfig +++ b/linux/drivers/media/video/usbvideo/Kconfig @@ -38,10 +38,13 @@ config USB_KONICAWC module will be called konicawc. config USB_QUICKCAM_MESSENGER - tristate "USB Logitech Quickcam Messenger" + tristate "USB Logitech Quickcam Messenger (DEPRECATED)" depends on VIDEO_V4L1 select VIDEO_USBVIDEO ---help--- + This driver is DEPRECATED please use the gspca stv06xx module + instead. + Say Y or M here to enable support for the USB Logitech Quickcam Messenger webcam. -- cgit v1.2.3 From 0d075253d693d11e8836f40d3fe3641f8e8901b1 Mon Sep 17 00:00:00 2001 From: "hans@rhel5-devel.localdomain" Date: Thu, 18 Jun 2009 11:03:20 +0200 Subject: gspca_sonixj: increase 640x480 frame-buffersize From: Hans de Goede gspca_sonixj: increase 640x480 frame-buffersize, as I was getting buffer overflows during my testing of a "Premier" 0c45:613e cam Priority: normal Signed-off-by: Hans de Goede --- linux/drivers/media/video/gspca/sonixj.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/sonixj.c b/linux/drivers/media/video/gspca/sonixj.c index 9ca72e2ac..621eee625 100644 --- a/linux/drivers/media/video/gspca/sonixj.c +++ b/linux/drivers/media/video/gspca/sonixj.c @@ -278,7 +278,8 @@ static const struct v4l2_pix_format vga_mode[] = { .priv = 1}, {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, .bytesperline = 640, - .sizeimage = 640 * 480 * 3 / 8 + 590, + /* Note 3 / 8 is not large enough, not even 5 / 8 is ?! */ + .sizeimage = 640 * 480 * 3 / 4 + 590, .colorspace = V4L2_COLORSPACE_JPEG, .priv = 0}, }; -- cgit v1.2.3 From b64b09a54ba1e2dd7477e0a96c335efdd6e80a87 Mon Sep 17 00:00:00 2001 From: "hans@rhel5-devel.localdomain" Date: Thu, 18 Jun 2009 11:05:07 +0200 Subject: gspca_sonixj: enable autogain control for the ov7620 From: Hans de Goede gspca_sonixj: enable autogain control for the ov7620, and not only make it enable autogain but also auto exposure (and do the same for the ov7648). Priority: normal Signed-off-by: Hans de Goede --- linux/drivers/media/video/gspca/sonixj.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/sonixj.c b/linux/drivers/media/video/gspca/sonixj.c index 621eee625..6233df970 100644 --- a/linux/drivers/media/video/gspca/sonixj.c +++ b/linux/drivers/media/video/gspca/sonixj.c @@ -255,7 +255,7 @@ static __u32 ctrl_dis[] = { /* SENSOR_MT9V111 3 */ (1 << INFRARED_IDX) | (1 << VFLIP_IDX), /* SENSOR_OM6802 4 */ - (1 << AUTOGAIN_IDX) | (1 << INFRARED_IDX), + (1 << INFRARED_IDX), /* SENSOR_OV7630 5 */ (1 << INFRARED_IDX), /* SENSOR_OV7648 6 */ @@ -1603,7 +1603,7 @@ static void setautogain(struct gspca_dev *gspca_dev) else comb = 0xa0; if (sd->autogain) - comb |= 0x02; + comb |= 0x03; i2c_w1(&sd->gspca_dev, 0x13, comb); return; } -- cgit v1.2.3 From 1bee18b3646766a3bcaf53f8826438032e0e91ed Mon Sep 17 00:00:00 2001 From: "hans@rhel5-devel.localdomain" Date: Thu, 18 Jun 2009 12:35:36 +0200 Subject: gspca_sonixj: Add light frequency control From: Hans de Goede gspca_sonixj: Add light frequency control Priority: normal Signed-off-by: Hans de Goede --- linux/drivers/media/video/gspca/sonixj.c | 135 ++++++++++++++++++++++++++++--- 1 file changed, 124 insertions(+), 11 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/sonixj.c b/linux/drivers/media/video/gspca/sonixj.c index 6233df970..aeeab0b51 100644 --- a/linux/drivers/media/video/gspca/sonixj.c +++ b/linux/drivers/media/video/gspca/sonixj.c @@ -46,6 +46,7 @@ struct sd { u8 gamma; u8 vflip; /* ov7630/ov7648 only */ u8 infrared; /* mt9v111 only */ + u8 freq; /* ov76xx only */ u8 quality; /* image quality */ #define QUALITY_MIN 60 #define QUALITY_MAX 95 @@ -96,6 +97,8 @@ static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val); static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val); static int sd_setinfrared(struct gspca_dev *gspca_dev, __s32 val); static int sd_getinfrared(struct gspca_dev *gspca_dev, __s32 *val); +static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val); +static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val); static struct ctrl sd_ctrls[] = { #define BRIGHTNESS_IDX 0 @@ -237,23 +240,39 @@ static struct ctrl sd_ctrls[] = { .set = sd_setinfrared, .get = sd_getinfrared, }, +/* ov7630/ov7648/ov7660 only */ +#define FREQ_IDX 9 + { + { + .id = V4L2_CID_POWER_LINE_FREQUENCY, + .type = V4L2_CTRL_TYPE_MENU, + .name = "Light frequency filter", + .minimum = 0, + .maximum = 2, /* 0: 0, 1: 50Hz, 2:60Hz */ + .step = 1, +#define FREQ_DEF 2 + .default_value = FREQ_DEF, + }, + .set = sd_setfreq, + .get = sd_getfreq, + }, }; /* table of the disabled controls */ static __u32 ctrl_dis[] = { - (1 << INFRARED_IDX) | (1 << VFLIP_IDX), + (1 << INFRARED_IDX) | (1 << VFLIP_IDX) | (1 << FREQ_IDX), /* SENSOR_HV7131R 0 */ - (1 << INFRARED_IDX) | (1 << VFLIP_IDX), + (1 << INFRARED_IDX) | (1 << VFLIP_IDX) | (1 << FREQ_IDX), /* SENSOR_MI0360 1 */ - (1 << INFRARED_IDX) | (1 << VFLIP_IDX), + (1 << INFRARED_IDX) | (1 << VFLIP_IDX) | (1 << FREQ_IDX), /* SENSOR_MO4000 2 */ #if 1 - (1 << VFLIP_IDX), + (1 << VFLIP_IDX) | (1 << FREQ_IDX), #else - (1 << AUTOGAIN_IDX) | (1 << VFLIP_IDX), + (1 << AUTOGAIN_IDX) | (1 << VFLIP_IDX) | (1 << FREQ_IDX), #endif /* SENSOR_MT9V111 3 */ - (1 << INFRARED_IDX) | (1 << VFLIP_IDX), + (1 << INFRARED_IDX) | (1 << VFLIP_IDX) | (1 << FREQ_IDX), /* SENSOR_OM6802 4 */ (1 << INFRARED_IDX), /* SENSOR_OV7630 5 */ @@ -261,8 +280,8 @@ static __u32 ctrl_dis[] = { /* SENSOR_OV7648 6 */ (1 << AUTOGAIN_IDX) | (1 << INFRARED_IDX) | (1 << VFLIP_IDX), /* SENSOR_OV7660 7 */ - (1 << AUTOGAIN_IDX) | (1 << INFRARED_IDX) | (1 << VFLIP_IDX), - /* SENSOR_SP80708 8 */ + (1 << AUTOGAIN_IDX) | (1 << INFRARED_IDX) | (1 << VFLIP_IDX) | + (1 << FREQ_IDX), /* SENSOR_SP80708 8 */ }; static const struct v4l2_pix_format vga_mode[] = { @@ -655,8 +674,8 @@ static const u8 ov7630_sensor_init[][8] = { {0xa1, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10}, {0xb1, 0x21, 0x01, 0x80, 0x80, 0x00, 0x00, 0x10}, /* */ - {0xa1, 0x21, 0x2a, 0x88, 0x00, 0x00, 0x00, 0x10}, - {0xa1, 0x21, 0x2b, 0x34, 0x00, 0x00, 0x00, 0x10}, +/* {0xa1, 0x21, 0x2a, 0x88, 0x00, 0x00, 0x00, 0x10}, * set by setfreq */ +/* {0xa1, 0x21, 0x2b, 0x34, 0x00, 0x00, 0x00, 0x10}, * set by setfreq */ /* */ {0xa1, 0x21, 0x10, 0x83, 0x00, 0x00, 0x00, 0x10}, /* {0xb1, 0x21, 0x01, 0x88, 0x70, 0x00, 0x00, 0x10}, */ @@ -689,7 +708,7 @@ static const u8 ov7648_sensor_init[][8] = { {0xd1, 0x21, 0x21, 0x86, 0x00, 0xde, 0xa0, 0x10}, /* {0xd1, 0x21, 0x25, 0x80, 0x32, 0xfe, 0xa0, 0x10}, jfm done */ /* {0xd1, 0x21, 0x29, 0x00, 0x91, 0x00, 0x88, 0x10}, jfm done */ - {0xb1, 0x21, 0x2d, 0x85, 0x00, 0x00, 0x00, 0x10}, +/* {0xb1, 0x21, 0x2d, 0x85, 0x00, 0x00, 0x00, 0x10}, set by setfreq */ /*...*/ /* {0xa1, 0x21, 0x12, 0x08, 0x00, 0x00, 0x00, 0x10}, jfm done */ /* {0xa1, 0x21, 0x75, 0x06, 0x00, 0x00, 0x00, 0x10}, * COMN @@ -1323,6 +1342,7 @@ static int sd_config(struct gspca_dev *gspca_dev, else sd->vflip = 1; sd->infrared = INFRARED_DEF; + sd->freq = FREQ_DEF; sd->quality = QUALITY_DEF; sd->jpegqual = 80; @@ -1642,6 +1662,58 @@ static void setinfrared(struct sd *sd) #endif } +static void setfreq(struct gspca_dev *gspca_dev) +{ + struct sd *sd = (struct sd *) gspca_dev; + + if (sd->sensor == SENSOR_OV7660) { + switch (sd->freq) { + case 0: /* Banding filter disabled */ + i2c_w1(gspca_dev, 0x13, 0xdf); + break; + case 1: /* 50 hz */ + i2c_w1(gspca_dev, 0x13, 0xff); + i2c_w1(gspca_dev, 0x3b, 0x0a); + break; + case 2: /* 60 hz */ + i2c_w1(gspca_dev, 0x13, 0xff); + i2c_w1(gspca_dev, 0x3b, 0x02); + break; + } + } else { + u8 reg2a = 0, reg2b = 0, reg2d = 0; + + /* Get reg2a / reg2d base values */ + switch (sd->sensor) { + case SENSOR_OV7630: + reg2a = 0x08; + reg2d = 0x01; + break; + case SENSOR_OV7648: + reg2a = 0x11; + reg2d = 0x81; + break; + } + + switch (sd->freq) { + case 0: /* Banding filter disabled */ + break; + case 1: /* 50 hz (filter on and framerate adj) */ + reg2a |= 0x80; + reg2b = 0xac; + reg2d |= 0x04; + break; + case 2: /* 60 hz (filter on, no framerate adj) */ + reg2a |= 0x80; + reg2d |= 0x04; + break; + } + i2c_w1(gspca_dev, 0x2a, reg2a); + i2c_w1(gspca_dev, 0x2b, reg2b); + i2c_w1(gspca_dev, 0x2d, reg2d); + } +} + static void setjpegqual(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; @@ -1873,6 +1945,7 @@ static int sd_start(struct gspca_dev *gspca_dev) setbrightness(gspca_dev); setcontrast(gspca_dev); setautogain(gspca_dev); + setfreq(gspca_dev); return 0; } @@ -2176,6 +2249,24 @@ static int sd_getinfrared(struct gspca_dev *gspca_dev, __s32 *val) return 0; } +static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val) +{ + struct sd *sd = (struct sd *) gspca_dev; + + sd->freq = val; + if (gspca_dev->streaming) + setfreq(gspca_dev); + return 0; +} + +static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val) +{ + struct sd *sd = (struct sd *) gspca_dev; + + *val = sd->freq; + return 0; +} + static int sd_set_jcomp(struct gspca_dev *gspca_dev, struct v4l2_jpegcompression *jcomp) { @@ -2204,6 +2295,27 @@ static int sd_get_jcomp(struct gspca_dev *gspca_dev, return 0; } +static int sd_querymenu(struct gspca_dev *gspca_dev, + struct v4l2_querymenu *menu) +{ + switch (menu->id) { + case V4L2_CID_POWER_LINE_FREQUENCY: + switch (menu->index) { + case 0: /* V4L2_CID_POWER_LINE_FREQUENCY_DISABLED */ + strcpy((char *) menu->name, "NoFliker"); + return 0; + case 1: /* V4L2_CID_POWER_LINE_FREQUENCY_50HZ */ + strcpy((char *) menu->name, "50 Hz"); + return 0; + case 2: /* V4L2_CID_POWER_LINE_FREQUENCY_60HZ */ + strcpy((char *) menu->name, "60 Hz"); + return 0; + } + break; + } + return -EINVAL; +} + /* sub-driver description */ static const struct sd_desc sd_desc = { .name = MODULE_NAME, @@ -2218,6 +2330,7 @@ static const struct sd_desc sd_desc = { .dq_callback = do_autogain, .get_jcomp = sd_get_jcomp, .set_jcomp = sd_set_jcomp, + .querymenu = sd_querymenu, }; /* -- module initialisation -- */ -- cgit v1.2.3 From c847e3dd95dce3751a45cac3b01a73b6f8f293c9 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 27 Jul 2009 08:24:29 -0300 Subject: mtv9v011: Add a missing chip version to the driver From: Mauro Carvalho Chehab Some mt9v011 webcams report 0x8332 chip version, instead of 0x8243. From the revision history at the mt9v011 datasheet, it seems that the chip version has changed from the first release of the chip. Thanks-to hermann pitton for pointing this to me, on his tests with a Silvercrest webcam. Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/em28xx/em28xx-cards.c | 3 ++- linux/drivers/media/video/mt9v011.c | 14 +++++++++----- linux/drivers/media/video/mt9v011.h | 3 ++- 3 files changed, 13 insertions(+), 7 deletions(-) (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 8a22caf01..6e4a44331 100644 --- a/linux/drivers/media/video/em28xx/em28xx-cards.c +++ b/linux/drivers/media/video/em28xx/em28xx-cards.c @@ -1838,7 +1838,8 @@ static int em28xx_hint_sensor(struct em28xx *dev) version = be16_to_cpu(version_be); switch (version) { - case 0x8243: /* mt9v011 640x480 1.3 Mpix sensor */ + case 0x8232: /* mt9v011 640x480 1.3 Mpix sensor */ + case 0x8243: /* mt9v011 rev B 640x480 1.3 Mpix sensor */ dev->model = EM2820_BOARD_SILVERCREST_WEBCAM; sensor_name = "mt9v011"; dev->em28xx_sensor = EM28XX_MT9V011; diff --git a/linux/drivers/media/video/mt9v011.c b/linux/drivers/media/video/mt9v011.c index bf68ea63f..c9706b889 100644 --- a/linux/drivers/media/video/mt9v011.c +++ b/linux/drivers/media/video/mt9v011.c @@ -403,10 +403,13 @@ static int mt9v011_s_register(struct v4l2_subdev *sd, static int mt9v011_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip) { + u16 version; struct i2c_client *client = v4l2_get_subdevdata(sd); + version = mt9v011_read(sd, R00_MT9V011_CHIP_VERSION); + return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_MT9V011, - MT9V011_VERSION); + version); } static const struct v4l2_subdev_core_ops mt9v011_core_ops = { @@ -459,8 +462,9 @@ static int mt9v011_probe(struct i2c_client *c, /* Check if the sensor is really a MT9V011 */ version = mt9v011_read(sd, R00_MT9V011_CHIP_VERSION); - if (version != MT9V011_VERSION) { - v4l2_info(sd, "*** unknown micron chip detected (0x%04x.\n", + if ((version != MT9V011_VERSION) && + (version != MT9V011_REV_B_VERSION)) { + v4l2_info(sd, "*** unknown micron chip detected (0x%04x).\n", version); kfree(core); return -EINVAL; @@ -471,8 +475,8 @@ static int mt9v011_probe(struct i2c_client *c, core->height = 480; core->xtal = 27000000; /* Hz */ - v4l_info(c, "chip found @ 0x%02x (%s)\n", - c->addr << 1, c->adapter->name); + v4l_info(c, "chip found @ 0x%02x (%s - chip version 0x%04x)\n", + c->addr << 1, c->adapter->name, version); return 0; } diff --git a/linux/drivers/media/video/mt9v011.h b/linux/drivers/media/video/mt9v011.h index 9e443ee30..3350fd608 100644 --- a/linux/drivers/media/video/mt9v011.h +++ b/linux/drivers/media/video/mt9v011.h @@ -30,6 +30,7 @@ #define R35_MT9V011_GLOBAL_GAIN 0x35 #define RF1_MT9V011_CHIP_ENABLE 0xf1 -#define MT9V011_VERSION 0x8243 +#define MT9V011_VERSION 0x8232 +#define MT9V011_REV_B_VERSION 0x8243 #endif -- cgit v1.2.3 From f7ea703f977df67b32fa86271669d8d4a5d3ce7f Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 18 Jun 2009 11:11:57 +0000 Subject: zl10353 and qt1010: fix stack corruption bug From: Jan Nikitenko Fixes stack corruption bug present in dump_regs function of zl10353 and qt1010 drivers: the buffer buf was one byte smaller than required - there are 4 chars for address prefix, 16 * 3 chars for dump of 16 eeprom bytes per line and 1 byte for zero ending the string required, i.e. 53 bytes, but only 52 were provided. The one byte missing in stack based buffer buf can cause stack corruption possibly leading to kernel oops, as discovered originally with af9015 driver (af9015: fix stack corruption bug). Signed-off-by: Jan Nikitenko Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/common/tuners/qt1010.c | 12 +++++------- linux/drivers/media/dvb/frontends/zl10353.c | 12 +++++------- 2 files changed, 10 insertions(+), 14 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/common/tuners/qt1010.c b/linux/drivers/media/common/tuners/qt1010.c index 4afed44ab..d877c59a7 100644 --- a/linux/drivers/media/common/tuners/qt1010.c +++ b/linux/drivers/media/common/tuners/qt1010.c @@ -65,24 +65,22 @@ static int qt1010_writereg(struct qt1010_priv *priv, u8 reg, u8 val) /* dump all registers */ static void qt1010_dump_regs(struct qt1010_priv *priv) { - char buf[52], buf2[4]; u8 reg, val; for (reg = 0; ; reg++) { if (reg % 16 == 0) { if (reg) - printk("%s\n", buf); - sprintf(buf, "%02x: ", reg); + printk(KERN_CONT "\n"); + printk(KERN_DEBUG "%02x:", reg); } if (qt1010_readreg(priv, reg, &val) == 0) - sprintf(buf2, "%02x ", val); + printk(KERN_CONT " %02x", val); else - strcpy(buf2, "-- "); - strcat(buf, buf2); + printk(KERN_CONT " --"); if (reg == 0x2f) break; } - printk("%s\n", buf); + printk(KERN_CONT "\n"); } static int qt1010_set_params(struct dvb_frontend *fe, diff --git a/linux/drivers/media/dvb/frontends/zl10353.c b/linux/drivers/media/dvb/frontends/zl10353.c index 6b58bf961..a69e9602c 100644 --- a/linux/drivers/media/dvb/frontends/zl10353.c +++ b/linux/drivers/media/dvb/frontends/zl10353.c @@ -102,7 +102,6 @@ static int zl10353_read_register(struct zl10353_state *state, u8 reg) static void zl10353_dump_regs(struct dvb_frontend *fe) { struct zl10353_state *state = fe->demodulator_priv; - char buf[52], buf2[4]; int ret; u8 reg; @@ -110,19 +109,18 @@ static void zl10353_dump_regs(struct dvb_frontend *fe) for (reg = 0; ; reg++) { if (reg % 16 == 0) { if (reg) - printk(KERN_DEBUG "%s\n", buf); - sprintf(buf, "%02x: ", reg); + printk(KERN_CONT "\n"); + printk(KERN_DEBUG "%02x:", reg); } ret = zl10353_read_register(state, reg); if (ret >= 0) - sprintf(buf2, "%02x ", (u8)ret); + printk(KERN_CONT " %02x", (u8)ret); else - strcpy(buf2, "-- "); - strcat(buf, buf2); + printk(KERN_CONT " --"); if (reg == 0xff) break; } - printk(KERN_DEBUG "%s\n", buf); + printk(KERN_CONT "\n"); } #endif -- cgit v1.2.3 From 5e6bb851c631e3940d0d15d290f0a1eac1081d82 Mon Sep 17 00:00:00 2001 From: "hans@rhel5-devel.localdomain" Date: Thu, 18 Jun 2009 19:29:20 +0200 Subject: gspca_sonixj + ov7630: invert vflip control instead of changing default From: Hans de Goede gspca_sonixj + ov7630 had the default value for flip enabled, as otherwise the picture is upside down. It is better to instead invert the meaning of the control in the set function, and have the default be no vflip, as one would expect vflip enabled to be upside down. Priority: normal Signed-off-by: Hans de Goede --- linux/drivers/media/video/gspca/sonixj.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/sonixj.c b/linux/drivers/media/video/gspca/sonixj.c index aeeab0b51..f47986a1c 100644 --- a/linux/drivers/media/video/gspca/sonixj.c +++ b/linux/drivers/media/video/gspca/sonixj.c @@ -218,7 +218,7 @@ static struct ctrl sd_ctrls[] = { .minimum = 0, .maximum = 1, .step = 1, -#define VFLIP_DEF 0 /* vflip def = 1 for ov7630 */ +#define VFLIP_DEF 0 .default_value = VFLIP_DEF, }, .set = sd_setvflip, @@ -1337,10 +1337,7 @@ static int sd_config(struct gspca_dev *gspca_dev, sd->gamma = GAMMA_DEF; sd->autogain = AUTOGAIN_DEF; sd->ag_cnt = -1; - if (sd->sensor != SENSOR_OV7630) - sd->vflip = 0; - else - sd->vflip = 1; + sd->vflip = VFLIP_DEF; sd->infrared = INFRARED_DEF; sd->freq = FREQ_DEF; sd->quality = QUALITY_DEF; @@ -1639,12 +1636,15 @@ static void setvflip(struct sd *sd) { u8 comn; - if (sd->sensor == SENSOR_OV7630) + if (sd->sensor == SENSOR_OV7630) { comn = 0x02; - else + if (!sd->vflip) + comn |= 0x80; + } else { comn = 0x06; - if (sd->vflip) - comn |= 0x80; + if (sd->vflip) + comn |= 0x80; + } i2c_w1(&sd->gspca_dev, 0x75, comn); } -- cgit v1.2.3 From b6b5cafa2594a09626f8a3a4d23bbb0f1b712941 Mon Sep 17 00:00:00 2001 From: "hans@rhel5-devel.localdomain" Date: Thu, 18 Jun 2009 19:31:36 +0200 Subject: gspca_sonixj: Name saturation control saturation, not color From: Hans de Goede Name saturation control saturation, not color and make the default less saturated (the old default was overdoing it). Priority: normal Signed-off-by: Hans de Goede --- linux/drivers/media/video/gspca/sonixj.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/sonixj.c b/linux/drivers/media/video/gspca/sonixj.c index f47986a1c..a2fb94eb7 100644 --- a/linux/drivers/media/video/gspca/sonixj.c +++ b/linux/drivers/media/video/gspca/sonixj.c @@ -138,11 +138,11 @@ static struct ctrl sd_ctrls[] = { { .id = V4L2_CID_SATURATION, .type = V4L2_CTRL_TYPE_INTEGER, - .name = "Color", + .name = "Saturation", .minimum = 0, .maximum = 40, .step = 1, -#define COLOR_DEF 32 +#define COLOR_DEF 25 .default_value = COLOR_DEF, }, .set = sd_setcolors, -- cgit v1.2.3 From fc9122feb731e5b2e40ba38de622dca900898fb5 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 19 Jun 2009 12:13:44 +0200 Subject: tvp514x: Migration to sub-device framework From: Muralidharan Karicheri This patch converts TVP514x driver to sub-device framework from V4L2-int framework. Priority: normal Signed-off-by: Brijesh Jadav Signed-off-by: Hardik Shah Signed-off-by: Vaibhav Hiremath Signed-off-by: Murali Karicheri [hverkuil@xs4all.nl: remove inline from the dump_reg function] Signed-off-by: Hans Verkuil --- linux/drivers/media/video/tvp514x.c | 875 ++++++++++++------------------- linux/drivers/media/video/tvp514x_regs.h | 10 - 2 files changed, 349 insertions(+), 536 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/tvp514x.c b/linux/drivers/media/video/tvp514x.c index 3750f7fad..c8386e2f7 100644 --- a/linux/drivers/media/video/tvp514x.c +++ b/linux/drivers/media/video/tvp514x.c @@ -31,7 +31,10 @@ #include #include #include -#include + +#include +#include +#include #include #include "tvp514x_regs.h" @@ -49,13 +52,11 @@ static int debug; module_param(debug, bool, 0644); MODULE_PARM_DESC(debug, "Debug level (0-1)"); -#define dump_reg(client, reg, val) \ - do { \ - val = tvp514x_read_reg(client, reg); \ - v4l_info(client, "Reg(0x%.2X): 0x%.2X\n", reg, val); \ - } while (0) +MODULE_AUTHOR("Texas Instruments"); +MODULE_DESCRIPTION("TVP514X linux decoder driver"); +MODULE_LICENSE("GPL"); -/** +/* * enum tvp514x_std - enum for supported standards */ enum tvp514x_std { @@ -64,15 +65,7 @@ enum tvp514x_std { STD_INVALID }; -/** - * enum tvp514x_state - enum for different decoder states - */ -enum tvp514x_state { - STATE_NOT_DETECTED, - STATE_DETECTED -}; - -/** +/* * struct tvp514x_std_info - Structure to store standard informations * @width: Line width in pixels * @height:Number of active lines @@ -87,35 +80,29 @@ struct tvp514x_std_info { }; static struct tvp514x_reg tvp514x_reg_list_default[0x40]; -/** +/* * struct tvp514x_decoder - TVP5146/47 decoder object - * @v4l2_int_device: Slave handle - * @tvp514x_slave: Slave pointer which is used by @v4l2_int_device + * @sd: Subdevice Slave handle * @tvp514x_regs: copy of hw's regs with preset values. * @pdata: Board specific - * @client: I2C client data - * @id: Entry from I2C table * @ver: Chip version - * @state: TVP5146/47 decoder state - detected or not-detected + * @streaming: TVP5146/47 decoder streaming - enabled or disabled. * @pix: Current pixel format * @num_fmts: Number of formats * @fmt_list: Format list * @current_std: Current standard * @num_stds: Number of standards * @std_list: Standards list - * @route: input and output routing at chip level + * @input: Input routing at chip level + * @output: Output routing at chip level */ struct tvp514x_decoder { - struct v4l2_int_device v4l2_int_device; - struct v4l2_int_slave tvp514x_slave; + struct v4l2_subdev sd; struct tvp514x_reg tvp514x_regs[ARRAY_SIZE(tvp514x_reg_list_default)]; const struct tvp514x_platform_data *pdata; - struct i2c_client *client; - - struct i2c_device_id *id; int ver; - enum tvp514x_state state; + int streaming; struct v4l2_pix_format pix; int num_fmts; @@ -124,8 +111,11 @@ struct tvp514x_decoder { enum tvp514x_std current_std; int num_stds; struct tvp514x_std_info *std_list; - - struct v4l2_routing route; + /* + * Input and Output Routing parameters + */ + u32 input; + u32 output; }; /* TVP514x default register values */ @@ -191,7 +181,8 @@ static struct tvp514x_reg tvp514x_reg_list_default[] = { {TOK_TERM, 0, 0}, }; -/* List of image formats supported by TVP5146/47 decoder +/* + * List of image formats supported by TVP5146/47 decoder * Currently we are using 8 bit mode only, but can be * extended to 10/20 bit mode. */ @@ -240,35 +231,29 @@ static struct tvp514x_std_info tvp514x_std_list[] = { }, /* Standard: need to add for additional standard */ }; -/* - * Control structure for Auto Gain - * This is temporary data, will get replaced once - * v4l2_ctrl_query_fill supports it. - */ -static const struct v4l2_queryctrl tvp514x_autogain_ctrl = { - .id = V4L2_CID_AUTOGAIN, - .name = "Gain, Automatic", - .type = V4L2_CTRL_TYPE_BOOLEAN, - .minimum = 0, - .maximum = 1, - .step = 1, - .default_value = 1, -}; + + +static inline struct tvp514x_decoder *to_decoder(struct v4l2_subdev *sd) +{ + return container_of(sd, struct tvp514x_decoder, sd); +} + /* * Read a value from a register in an TVP5146/47 decoder device. * Returns value read if successful, or non-zero (-1) otherwise. */ -static int tvp514x_read_reg(struct i2c_client *client, u8 reg) +static int tvp514x_read_reg(struct v4l2_subdev *sd, u8 reg) { - int err; - int retry = 0; + int err, retry = 0; + struct i2c_client *client = v4l2_get_subdevdata(sd); + read_again: err = i2c_smbus_read_byte_data(client, reg); if (err == -1) { if (retry <= I2C_RETRY_COUNT) { - v4l_warn(client, "Read: retry ... %d\n", retry); + v4l2_warn(sd, "Read: retry ... %d\n", retry); retry++; msleep_interruptible(10); goto read_again; @@ -278,20 +263,29 @@ read_again: return err; } +static void dump_reg(struct v4l2_subdev *sd, u8 reg) +{ + u32 val; + + val = tvp514x_read_reg(sd, reg); + v4l2_info(sd, "Reg(0x%.2X): 0x%.2X\n", reg, val); +} + /* * Write a value to a register in an TVP5146/47 decoder device. * Returns zero if successful, or non-zero otherwise. */ -static int tvp514x_write_reg(struct i2c_client *client, u8 reg, u8 val) +static int tvp514x_write_reg(struct v4l2_subdev *sd, u8 reg, u8 val) { - int err; - int retry = 0; + int err, retry = 0; + struct i2c_client *client = v4l2_get_subdevdata(sd); + write_again: err = i2c_smbus_write_byte_data(client, reg, val); if (err) { if (retry <= I2C_RETRY_COUNT) { - v4l_warn(client, "Write: retry ... %d\n", retry); + v4l2_warn(sd, "Write: retry ... %d\n", retry); retry++; msleep_interruptible(10); goto write_again; @@ -311,7 +305,7 @@ write_again: * reglist - list of registers to be written * Returns zero if successful, or non-zero otherwise. */ -static int tvp514x_write_regs(struct i2c_client *client, +static int tvp514x_write_regs(struct v4l2_subdev *sd, const struct tvp514x_reg reglist[]) { int err; @@ -326,9 +320,9 @@ static int tvp514x_write_regs(struct i2c_client *client, if (next->token == TOK_SKIP) continue; - err = tvp514x_write_reg(client, next->reg, (u8) next->val); + err = tvp514x_write_reg(sd, next->reg, (u8) next->val); if (err) { - v4l_err(client, "Write failed. Err[%d]\n", err); + v4l2_err(sd, "Write failed. Err[%d]\n", err); return err; } } @@ -339,17 +333,15 @@ static int tvp514x_write_regs(struct i2c_client *client, * tvp514x_get_current_std: * Returns the current standard detected by TVP5146/47 */ -static enum tvp514x_std tvp514x_get_current_std(struct tvp514x_decoder - *decoder) +static enum tvp514x_std tvp514x_get_current_std(struct v4l2_subdev *sd) { u8 std, std_status; - std = tvp514x_read_reg(decoder->client, REG_VIDEO_STD); - if ((std & VIDEO_STD_MASK) == VIDEO_STD_AUTO_SWITCH_BIT) { + std = tvp514x_read_reg(sd, REG_VIDEO_STD); + if ((std & VIDEO_STD_MASK) == VIDEO_STD_AUTO_SWITCH_BIT) /* use the standard status register */ - std_status = tvp514x_read_reg(decoder->client, - REG_VIDEO_STD_STATUS); - } else + std_status = tvp514x_read_reg(sd, REG_VIDEO_STD_STATUS); + else std_status = std; /* use the standard register itself */ switch (std_status & VIDEO_STD_MASK) { @@ -369,70 +361,69 @@ static enum tvp514x_std tvp514x_get_current_std(struct tvp514x_decoder /* * TVP5146/47 register dump function */ -static void tvp514x_reg_dump(struct tvp514x_decoder *decoder) +static void tvp514x_reg_dump(struct v4l2_subdev *sd) { - u8 value; - - dump_reg(decoder->client, REG_INPUT_SEL, value); - dump_reg(decoder->client, REG_AFE_GAIN_CTRL, value); - dump_reg(decoder->client, REG_VIDEO_STD, value); - dump_reg(decoder->client, REG_OPERATION_MODE, value); - dump_reg(decoder->client, REG_COLOR_KILLER, value); - dump_reg(decoder->client, REG_LUMA_CONTROL1, value); - dump_reg(decoder->client, REG_LUMA_CONTROL2, value); - dump_reg(decoder->client, REG_LUMA_CONTROL3, value); - dump_reg(decoder->client, REG_BRIGHTNESS, value); - dump_reg(decoder->client, REG_CONTRAST, value); - dump_reg(decoder->client, REG_SATURATION, value); - dump_reg(decoder->client, REG_HUE, value); - dump_reg(decoder->client, REG_CHROMA_CONTROL1, value); - dump_reg(decoder->client, REG_CHROMA_CONTROL2, value); - dump_reg(decoder->client, REG_COMP_PR_SATURATION, value); - dump_reg(decoder->client, REG_COMP_Y_CONTRAST, value); - dump_reg(decoder->client, REG_COMP_PB_SATURATION, value); - dump_reg(decoder->client, REG_COMP_Y_BRIGHTNESS, value); - dump_reg(decoder->client, REG_AVID_START_PIXEL_LSB, value); - dump_reg(decoder->client, REG_AVID_START_PIXEL_MSB, value); - dump_reg(decoder->client, REG_AVID_STOP_PIXEL_LSB, value); - dump_reg(decoder->client, REG_AVID_STOP_PIXEL_MSB, value); - dump_reg(decoder->client, REG_HSYNC_START_PIXEL_LSB, value); - dump_reg(decoder->client, REG_HSYNC_START_PIXEL_MSB, value); - dump_reg(decoder->client, REG_HSYNC_STOP_PIXEL_LSB, value); - dump_reg(decoder->client, REG_HSYNC_STOP_PIXEL_MSB, value); - dump_reg(decoder->client, REG_VSYNC_START_LINE_LSB, value); - dump_reg(decoder->client, REG_VSYNC_START_LINE_MSB, value); - dump_reg(decoder->client, REG_VSYNC_STOP_LINE_LSB, value); - dump_reg(decoder->client, REG_VSYNC_STOP_LINE_MSB, value); - dump_reg(decoder->client, REG_VBLK_START_LINE_LSB, value); - dump_reg(decoder->client, REG_VBLK_START_LINE_MSB, value); - dump_reg(decoder->client, REG_VBLK_STOP_LINE_LSB, value); - dump_reg(decoder->client, REG_VBLK_STOP_LINE_MSB, value); - dump_reg(decoder->client, REG_SYNC_CONTROL, value); - dump_reg(decoder->client, REG_OUTPUT_FORMATTER1, value); - dump_reg(decoder->client, REG_OUTPUT_FORMATTER2, value); - dump_reg(decoder->client, REG_OUTPUT_FORMATTER3, value); - dump_reg(decoder->client, REG_OUTPUT_FORMATTER4, value); - dump_reg(decoder->client, REG_OUTPUT_FORMATTER5, value); - dump_reg(decoder->client, REG_OUTPUT_FORMATTER6, value); - dump_reg(decoder->client, REG_CLEAR_LOST_LOCK, value); + dump_reg(sd, REG_INPUT_SEL); + dump_reg(sd, REG_AFE_GAIN_CTRL); + dump_reg(sd, REG_VIDEO_STD); + dump_reg(sd, REG_OPERATION_MODE); + dump_reg(sd, REG_COLOR_KILLER); + dump_reg(sd, REG_LUMA_CONTROL1); + dump_reg(sd, REG_LUMA_CONTROL2); + dump_reg(sd, REG_LUMA_CONTROL3); + dump_reg(sd, REG_BRIGHTNESS); + dump_reg(sd, REG_CONTRAST); + dump_reg(sd, REG_SATURATION); + dump_reg(sd, REG_HUE); + dump_reg(sd, REG_CHROMA_CONTROL1); + dump_reg(sd, REG_CHROMA_CONTROL2); + dump_reg(sd, REG_COMP_PR_SATURATION); + dump_reg(sd, REG_COMP_Y_CONTRAST); + dump_reg(sd, REG_COMP_PB_SATURATION); + dump_reg(sd, REG_COMP_Y_BRIGHTNESS); + dump_reg(sd, REG_AVID_START_PIXEL_LSB); + dump_reg(sd, REG_AVID_START_PIXEL_MSB); + dump_reg(sd, REG_AVID_STOP_PIXEL_LSB); + dump_reg(sd, REG_AVID_STOP_PIXEL_MSB); + dump_reg(sd, REG_HSYNC_START_PIXEL_LSB); + dump_reg(sd, REG_HSYNC_START_PIXEL_MSB); + dump_reg(sd, REG_HSYNC_STOP_PIXEL_LSB); + dump_reg(sd, REG_HSYNC_STOP_PIXEL_MSB); + dump_reg(sd, REG_VSYNC_START_LINE_LSB); + dump_reg(sd, REG_VSYNC_START_LINE_MSB); + dump_reg(sd, REG_VSYNC_STOP_LINE_LSB); + dump_reg(sd, REG_VSYNC_STOP_LINE_MSB); + dump_reg(sd, REG_VBLK_START_LINE_LSB); + dump_reg(sd, REG_VBLK_START_LINE_MSB); + dump_reg(sd, REG_VBLK_STOP_LINE_LSB); + dump_reg(sd, REG_VBLK_STOP_LINE_MSB); + dump_reg(sd, REG_SYNC_CONTROL); + dump_reg(sd, REG_OUTPUT_FORMATTER1); + dump_reg(sd, REG_OUTPUT_FORMATTER2); + dump_reg(sd, REG_OUTPUT_FORMATTER3); + dump_reg(sd, REG_OUTPUT_FORMATTER4); + dump_reg(sd, REG_OUTPUT_FORMATTER5); + dump_reg(sd, REG_OUTPUT_FORMATTER6); + dump_reg(sd, REG_CLEAR_LOST_LOCK); } /* * Configure the TVP5146/47 with the current register settings * Returns zero if successful, or non-zero otherwise. */ -static int tvp514x_configure(struct tvp514x_decoder *decoder) +static int tvp514x_configure(struct v4l2_subdev *sd, + struct tvp514x_decoder *decoder) { int err; /* common register initialization */ err = - tvp514x_write_regs(decoder->client, decoder->tvp514x_regs); + tvp514x_write_regs(sd, decoder->tvp514x_regs); if (err) return err; if (debug) - tvp514x_reg_dump(decoder); + tvp514x_reg_dump(sd); return 0; } @@ -445,15 +436,17 @@ static int tvp514x_configure(struct tvp514x_decoder *decoder) * Returns ENODEV error number if no device is detected, or zero * if a device is detected. */ -static int tvp514x_detect(struct tvp514x_decoder *decoder) +static int tvp514x_detect(struct v4l2_subdev *sd, + struct tvp514x_decoder *decoder) { u8 chip_id_msb, chip_id_lsb, rom_ver; + struct i2c_client *client = v4l2_get_subdevdata(sd); - chip_id_msb = tvp514x_read_reg(decoder->client, REG_CHIP_ID_MSB); - chip_id_lsb = tvp514x_read_reg(decoder->client, REG_CHIP_ID_LSB); - rom_ver = tvp514x_read_reg(decoder->client, REG_ROM_VERSION); + chip_id_msb = tvp514x_read_reg(sd, REG_CHIP_ID_MSB); + chip_id_lsb = tvp514x_read_reg(sd, REG_CHIP_ID_LSB); + rom_ver = tvp514x_read_reg(sd, REG_ROM_VERSION); - v4l_dbg(1, debug, decoder->client, + v4l2_dbg(1, debug, sd, "chip id detected msb:0x%x lsb:0x%x rom version:0x%x\n", chip_id_msb, chip_id_lsb, rom_ver); if ((chip_id_msb != TVP514X_CHIP_ID_MSB) @@ -462,19 +455,16 @@ static int tvp514x_detect(struct tvp514x_decoder *decoder) /* We didn't read the values we expected, so this must not be * an TVP5146/47. */ - v4l_err(decoder->client, - "chip id mismatch msb:0x%x lsb:0x%x\n", - chip_id_msb, chip_id_lsb); + v4l2_err(sd, "chip id mismatch msb:0x%x lsb:0x%x\n", + chip_id_msb, chip_id_lsb); return -ENODEV; } decoder->ver = rom_ver; - decoder->state = STATE_DETECTED; - v4l_info(decoder->client, - "%s found at 0x%x (%s)\n", decoder->client->name, - decoder->client->addr << 1, - decoder->client->adapter->name); + v4l2_info(sd, "%s (Version - 0x%.2x) found at 0x%x (%s)\n", + client->name, decoder->ver, + client->addr << 1, client->adapter->name); return 0; } @@ -483,17 +473,17 @@ static int tvp514x_detect(struct tvp514x_decoder *decoder) * TVP5146/47 decoder driver. */ -/** - * ioctl_querystd - V4L2 decoder interface handler for VIDIOC_QUERYSTD ioctl - * @s: pointer to standard V4L2 device structure +/* + * tvp514x_querystd - V4L2 decoder interface handler for VIDIOC_QUERYSTD ioctl + * @sd: pointer to standard V4L2 sub-device structure * @std_id: standard V4L2 std_id ioctl enum * * Returns the current standard detected by TVP5146/47. If no active input is * detected, returns -EINVAL */ -static int ioctl_querystd(struct v4l2_int_device *s, v4l2_std_id *std_id) +static int tvp514x_querystd(struct v4l2_subdev *sd, v4l2_std_id *std_id) { - struct tvp514x_decoder *decoder = s->priv; + struct tvp514x_decoder *decoder = to_decoder(sd); enum tvp514x_std current_std; enum tvp514x_input input_sel; u8 sync_lock_status, lock_mask; @@ -502,11 +492,11 @@ static int ioctl_querystd(struct v4l2_int_device *s, v4l2_std_id *std_id) return -EINVAL; /* get the current standard */ - current_std = tvp514x_get_current_std(decoder); + current_std = tvp514x_get_current_std(sd); if (current_std == STD_INVALID) return -EINVAL; - input_sel = decoder->route.input; + input_sel = decoder->input; switch (input_sel) { case INPUT_CVBS_VI1A: @@ -544,42 +534,39 @@ static int ioctl_querystd(struct v4l2_int_device *s, v4l2_std_id *std_id) return -EINVAL; } /* check whether signal is locked */ - sync_lock_status = tvp514x_read_reg(decoder->client, REG_STATUS1); + sync_lock_status = tvp514x_read_reg(sd, REG_STATUS1); if (lock_mask != (sync_lock_status & lock_mask)) return -EINVAL; /* No input detected */ decoder->current_std = current_std; *std_id = decoder->std_list[current_std].standard.id; - v4l_dbg(1, debug, decoder->client, "Current STD: %s", + v4l2_dbg(1, debug, sd, "Current STD: %s", decoder->std_list[current_std].standard.name); return 0; } -/** - * ioctl_s_std - V4L2 decoder interface handler for VIDIOC_S_STD ioctl - * @s: pointer to standard V4L2 device structure +/* + * tvp514x_s_std - V4L2 decoder interface handler for VIDIOC_S_STD ioctl + * @sd: pointer to standard V4L2 sub-device structure * @std_id: standard V4L2 v4l2_std_id ioctl enum * * If std_id is supported, sets the requested standard. Otherwise, returns * -EINVAL */ -static int ioctl_s_std(struct v4l2_int_device *s, v4l2_std_id *std_id) +static int tvp514x_s_std(struct v4l2_subdev *sd, v4l2_std_id std_id) { - struct tvp514x_decoder *decoder = s->priv; + struct tvp514x_decoder *decoder = to_decoder(sd); int err, i; - if (std_id == NULL) - return -EINVAL; - for (i = 0; i < decoder->num_stds; i++) - if (*std_id & decoder->std_list[i].standard.id) + if (std_id & decoder->std_list[i].standard.id) break; if ((i == decoder->num_stds) || (i == STD_INVALID)) return -EINVAL; - err = tvp514x_write_reg(decoder->client, REG_VIDEO_STD, + err = tvp514x_write_reg(sd, REG_VIDEO_STD, decoder->std_list[i].video_std); if (err) return err; @@ -588,24 +575,24 @@ static int ioctl_s_std(struct v4l2_int_device *s, v4l2_std_id *std_id) decoder->tvp514x_regs[REG_VIDEO_STD].val = decoder->std_list[i].video_std; - v4l_dbg(1, debug, decoder->client, "Standard set to: %s", + v4l2_dbg(1, debug, sd, "Standard set to: %s", decoder->std_list[i].standard.name); return 0; } -/** - * ioctl_s_routing - V4L2 decoder interface handler for VIDIOC_S_INPUT ioctl - * @s: pointer to standard V4L2 device structure +/* + * tvp514x_s_routing - V4L2 decoder interface handler for VIDIOC_S_INPUT ioctl + * @sd: pointer to standard V4L2 sub-device structure * @index: number of the input * * If index is valid, selects the requested input. Otherwise, returns -EINVAL if * the input is not supported or there is no active signal present in the * selected input. */ -static int ioctl_s_routing(struct v4l2_int_device *s, - struct v4l2_routing *route) +static int tvp514x_s_routing(struct v4l2_subdev *sd, + u32 input, u32 output, u32 config) { - struct tvp514x_decoder *decoder = s->priv; + struct tvp514x_decoder *decoder = to_decoder(sd); int err; enum tvp514x_input input_sel; enum tvp514x_output output_sel; @@ -613,20 +600,20 @@ static int ioctl_s_routing(struct v4l2_int_device *s, u8 sync_lock_status, lock_mask; int try_count = LOCK_RETRY_COUNT; - if ((!route) || (route->input >= INPUT_INVALID) || - (route->output >= OUTPUT_INVALID)) + if ((input >= INPUT_INVALID) || + (output >= OUTPUT_INVALID)) return -EINVAL; /* Index out of bound */ - input_sel = route->input; - output_sel = route->output; + input_sel = input; + output_sel = output; - err = tvp514x_write_reg(decoder->client, REG_INPUT_SEL, input_sel); + err = tvp514x_write_reg(sd, REG_INPUT_SEL, input_sel); if (err) return err; - output_sel |= tvp514x_read_reg(decoder->client, + output_sel |= tvp514x_read_reg(sd, REG_OUTPUT_FORMATTER1) & 0x7; - err = tvp514x_write_reg(decoder->client, REG_OUTPUT_FORMATTER1, + err = tvp514x_write_reg(sd, REG_OUTPUT_FORMATTER1, output_sel); if (err) return err; @@ -637,7 +624,7 @@ static int ioctl_s_routing(struct v4l2_int_device *s, /* Clear status */ msleep(LOCK_RETRY_DELAY); err = - tvp514x_write_reg(decoder->client, REG_CLEAR_LOST_LOCK, 0x01); + tvp514x_write_reg(sd, REG_CLEAR_LOST_LOCK, 0x01); if (err) return err; @@ -682,11 +669,11 @@ static int ioctl_s_routing(struct v4l2_int_device *s, msleep(LOCK_RETRY_DELAY); /* get the current standard for future reference */ - current_std = tvp514x_get_current_std(decoder); + current_std = tvp514x_get_current_std(sd); if (current_std == STD_INVALID) continue; - sync_lock_status = tvp514x_read_reg(decoder->client, + sync_lock_status = tvp514x_read_reg(sd, REG_STATUS1); if (lock_mask == (sync_lock_status & lock_mask)) break; /* Input detected */ @@ -696,28 +683,26 @@ static int ioctl_s_routing(struct v4l2_int_device *s, return -EINVAL; decoder->current_std = current_std; - decoder->route.input = route->input; - decoder->route.output = route->output; + decoder->input = input; + decoder->output = output; - v4l_dbg(1, debug, decoder->client, - "Input set to: %d, std : %d", + v4l2_dbg(1, debug, sd, "Input set to: %d, std : %d", input_sel, current_std); return 0; } -/** - * ioctl_queryctrl - V4L2 decoder interface handler for VIDIOC_QUERYCTRL ioctl - * @s: pointer to standard V4L2 device structure +/* + * tvp514x_queryctrl - V4L2 decoder interface handler for VIDIOC_QUERYCTRL ioctl + * @sd: pointer to standard V4L2 sub-device structure * @qctrl: standard V4L2 v4l2_queryctrl structure * * If the requested control is supported, returns the control information. * Otherwise, returns -EINVAL if the control is not supported. */ static int -ioctl_queryctrl(struct v4l2_int_device *s, struct v4l2_queryctrl *qctrl) +tvp514x_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qctrl) { - struct tvp514x_decoder *decoder = s->priv; int err = -EINVAL; if (qctrl == NULL) @@ -744,30 +729,27 @@ ioctl_queryctrl(struct v4l2_int_device *s, struct v4l2_queryctrl *qctrl) err = v4l2_ctrl_query_fill(qctrl, -180, 180, 180, 0); break; case V4L2_CID_AUTOGAIN: - /* Autogain is either 0 or 1*/ - memcpy(qctrl, &tvp514x_autogain_ctrl, - sizeof(struct v4l2_queryctrl)); - err = 0; + /* + * Auto Gain supported is - + * 0 - 1 (Default - 1) + */ + err = v4l2_ctrl_query_fill(qctrl, 0, 1, 1, 1); break; default: - v4l_err(decoder->client, - "invalid control id %d\n", qctrl->id); + v4l2_err(sd, "invalid control id %d\n", qctrl->id); return err; } - v4l_dbg(1, debug, decoder->client, - "Query Control: %s : Min - %d, Max - %d, Def - %d", - qctrl->name, - qctrl->minimum, - qctrl->maximum, + v4l2_dbg(1, debug, sd, "Query Control:%s: Min - %d, Max - %d, Def - %d", + qctrl->name, qctrl->minimum, qctrl->maximum, qctrl->default_value); return err; } -/** - * ioctl_g_ctrl - V4L2 decoder interface handler for VIDIOC_G_CTRL ioctl - * @s: pointer to standard V4L2 device structure +/* + * tvp514x_g_ctrl - V4L2 decoder interface handler for VIDIOC_G_CTRL ioctl + * @sd: pointer to standard V4L2 sub-device structure * @ctrl: pointer to v4l2_control structure * * If the requested control is supported, returns the control's current @@ -775,9 +757,9 @@ ioctl_queryctrl(struct v4l2_int_device *s, struct v4l2_queryctrl *qctrl) * supported. */ static int -ioctl_g_ctrl(struct v4l2_int_device *s, struct v4l2_control *ctrl) +tvp514x_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) { - struct tvp514x_decoder *decoder = s->priv; + struct tvp514x_decoder *decoder = to_decoder(sd); if (ctrl == NULL) return -EINVAL; @@ -811,74 +793,70 @@ ioctl_g_ctrl(struct v4l2_int_device *s, struct v4l2_control *ctrl) break; default: - v4l_err(decoder->client, - "invalid control id %d\n", ctrl->id); + v4l2_err(sd, "invalid control id %d\n", ctrl->id); return -EINVAL; } - v4l_dbg(1, debug, decoder->client, - "Get Control: ID - %d - %d", + v4l2_dbg(1, debug, sd, "Get Control: ID - %d - %d", ctrl->id, ctrl->value); return 0; } -/** - * ioctl_s_ctrl - V4L2 decoder interface handler for VIDIOC_S_CTRL ioctl - * @s: pointer to standard V4L2 device structure +/* + * tvp514x_s_ctrl - V4L2 decoder interface handler for VIDIOC_S_CTRL ioctl + * @sd: pointer to standard V4L2 sub-device structure * @ctrl: pointer to v4l2_control structure * * If the requested control is supported, sets the control's current * value in HW. Otherwise, returns -EINVAL if the control is not supported. */ static int -ioctl_s_ctrl(struct v4l2_int_device *s, struct v4l2_control *ctrl) +tvp514x_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) { - struct tvp514x_decoder *decoder = s->priv; + struct tvp514x_decoder *decoder = to_decoder(sd); int err = -EINVAL, value; if (ctrl == NULL) return err; - value = (__s32) ctrl->value; + value = ctrl->value; switch (ctrl->id) { case V4L2_CID_BRIGHTNESS: if (ctrl->value < 0 || ctrl->value > 255) { - v4l_err(decoder->client, - "invalid brightness setting %d\n", + v4l2_err(sd, "invalid brightness setting %d\n", ctrl->value); return -ERANGE; } - err = tvp514x_write_reg(decoder->client, REG_BRIGHTNESS, + err = tvp514x_write_reg(sd, REG_BRIGHTNESS, value); if (err) return err; + decoder->tvp514x_regs[REG_BRIGHTNESS].val = value; break; case V4L2_CID_CONTRAST: if (ctrl->value < 0 || ctrl->value > 255) { - v4l_err(decoder->client, - "invalid contrast setting %d\n", + v4l2_err(sd, "invalid contrast setting %d\n", ctrl->value); return -ERANGE; } - err = tvp514x_write_reg(decoder->client, REG_CONTRAST, - value); + err = tvp514x_write_reg(sd, REG_CONTRAST, value); if (err) return err; + decoder->tvp514x_regs[REG_CONTRAST].val = value; break; case V4L2_CID_SATURATION: if (ctrl->value < 0 || ctrl->value > 255) { - v4l_err(decoder->client, - "invalid saturation setting %d\n", + v4l2_err(sd, "invalid saturation setting %d\n", ctrl->value); return -ERANGE; } - err = tvp514x_write_reg(decoder->client, REG_SATURATION, - value); + err = tvp514x_write_reg(sd, REG_SATURATION, value); if (err) return err; + decoder->tvp514x_regs[REG_SATURATION].val = value; break; case V4L2_CID_HUE: @@ -889,15 +867,13 @@ ioctl_s_ctrl(struct v4l2_int_device *s, struct v4l2_control *ctrl) else if (value == 0) value = 0; else { - v4l_err(decoder->client, - "invalid hue setting %d\n", - ctrl->value); + v4l2_err(sd, "invalid hue setting %d\n", ctrl->value); return -ERANGE; } - err = tvp514x_write_reg(decoder->client, REG_HUE, - value); + err = tvp514x_write_reg(sd, REG_HUE, value); if (err) return err; + decoder->tvp514x_regs[REG_HUE].val = value; break; case V4L2_CID_AUTOGAIN: @@ -906,41 +882,38 @@ ioctl_s_ctrl(struct v4l2_int_device *s, struct v4l2_control *ctrl) else if (value == 0) value = 0x0C; else { - v4l_err(decoder->client, - "invalid auto gain setting %d\n", + v4l2_err(sd, "invalid auto gain setting %d\n", ctrl->value); return -ERANGE; } - err = tvp514x_write_reg(decoder->client, REG_AFE_GAIN_CTRL, - value); + err = tvp514x_write_reg(sd, REG_AFE_GAIN_CTRL, value); if (err) return err; + decoder->tvp514x_regs[REG_AFE_GAIN_CTRL].val = value; break; default: - v4l_err(decoder->client, - "invalid control id %d\n", ctrl->id); + v4l2_err(sd, "invalid control id %d\n", ctrl->id); return err; } - v4l_dbg(1, debug, decoder->client, - "Set Control: ID - %d - %d", + v4l2_dbg(1, debug, sd, "Set Control: ID - %d - %d", ctrl->id, ctrl->value); return err; } -/** - * ioctl_enum_fmt_cap - Implement the CAPTURE buffer VIDIOC_ENUM_FMT ioctl - * @s: pointer to standard V4L2 device structure +/* + * tvp514x_enum_fmt_cap - Implement the CAPTURE buffer VIDIOC_ENUM_FMT ioctl + * @sd: pointer to standard V4L2 sub-device structure * @fmt: standard V4L2 VIDIOC_ENUM_FMT ioctl structure * * Implement the VIDIOC_ENUM_FMT ioctl to enumerate supported formats */ static int -ioctl_enum_fmt_cap(struct v4l2_int_device *s, struct v4l2_fmtdesc *fmt) +tvp514x_enum_fmt_cap(struct v4l2_subdev *sd, struct v4l2_fmtdesc *fmt) { - struct tvp514x_decoder *decoder = s->priv; + struct tvp514x_decoder *decoder = to_decoder(sd); int index; if (fmt == NULL) @@ -956,16 +929,15 @@ ioctl_enum_fmt_cap(struct v4l2_int_device *s, struct v4l2_fmtdesc *fmt) memcpy(fmt, &decoder->fmt_list[index], sizeof(struct v4l2_fmtdesc)); - v4l_dbg(1, debug, decoder->client, - "Current FMT: index - %d (%s)", + v4l2_dbg(1, debug, sd, "Current FMT: index - %d (%s)", decoder->fmt_list[index].index, decoder->fmt_list[index].description); return 0; } -/** - * ioctl_try_fmt_cap - Implement the CAPTURE buffer VIDIOC_TRY_FMT ioctl - * @s: pointer to standard V4L2 device structure +/* + * tvp514x_try_fmt_cap - Implement the CAPTURE buffer VIDIOC_TRY_FMT ioctl + * @sd: pointer to standard V4L2 sub-device structure * @f: pointer to standard V4L2 VIDIOC_TRY_FMT ioctl structure * * Implement the VIDIOC_TRY_FMT ioctl for the CAPTURE buffer type. This @@ -973,9 +945,9 @@ ioctl_enum_fmt_cap(struct v4l2_int_device *s, struct v4l2_fmtdesc *fmt) * without actually making it take effect. */ static int -ioctl_try_fmt_cap(struct v4l2_int_device *s, struct v4l2_format *f) +tvp514x_try_fmt_cap(struct v4l2_subdev *sd, struct v4l2_format *f) { - struct tvp514x_decoder *decoder = s->priv; + struct tvp514x_decoder *decoder = to_decoder(sd); int ifmt; struct v4l2_pix_format *pix; enum tvp514x_std current_std; @@ -989,7 +961,7 @@ ioctl_try_fmt_cap(struct v4l2_int_device *s, struct v4l2_format *f) pix = &f->fmt.pix; /* Calculate height and width based on current standard */ - current_std = tvp514x_get_current_std(decoder); + current_std = tvp514x_get_current_std(sd); if (current_std == STD_INVALID) return -EINVAL; @@ -1012,17 +984,16 @@ ioctl_try_fmt_cap(struct v4l2_int_device *s, struct v4l2_format *f) pix->colorspace = V4L2_COLORSPACE_SMPTE170M; pix->priv = 0; - v4l_dbg(1, debug, decoder->client, - "Try FMT: pixelformat - %s, bytesperline - %d" + v4l2_dbg(1, debug, sd, "Try FMT: pixelformat - %s, bytesperline - %d" "Width - %d, Height - %d", decoder->fmt_list[ifmt].description, pix->bytesperline, pix->width, pix->height); return 0; } -/** - * ioctl_s_fmt_cap - V4L2 decoder interface handler for VIDIOC_S_FMT ioctl - * @s: pointer to standard V4L2 device structure +/* + * tvp514x_s_fmt_cap - V4L2 decoder interface handler for VIDIOC_S_FMT ioctl + * @sd: pointer to standard V4L2 sub-device structure * @f: pointer to standard V4L2 VIDIOC_S_FMT ioctl structure * * If the requested format is supported, configures the HW to use that @@ -1030,9 +1001,9 @@ ioctl_try_fmt_cap(struct v4l2_int_device *s, struct v4l2_format *f) * correctly configured. */ static int -ioctl_s_fmt_cap(struct v4l2_int_device *s, struct v4l2_format *f) +tvp514x_s_fmt_cap(struct v4l2_subdev *sd, struct v4l2_format *f) { - struct tvp514x_decoder *decoder = s->priv; + struct tvp514x_decoder *decoder = to_decoder(sd); struct v4l2_pix_format *pix; int rval; @@ -1043,7 +1014,7 @@ ioctl_s_fmt_cap(struct v4l2_int_device *s, struct v4l2_format *f) return -EINVAL; /* only capture is supported */ pix = &f->fmt.pix; - rval = ioctl_try_fmt_cap(s, f); + rval = tvp514x_try_fmt_cap(sd, f); if (rval) return rval; @@ -1052,18 +1023,18 @@ ioctl_s_fmt_cap(struct v4l2_int_device *s, struct v4l2_format *f) return rval; } -/** - * ioctl_g_fmt_cap - V4L2 decoder interface handler for ioctl_g_fmt_cap - * @s: pointer to standard V4L2 device structure +/* + * tvp514x_g_fmt_cap - V4L2 decoder interface handler for tvp514x_g_fmt_cap + * @sd: pointer to standard V4L2 sub-device structure * @f: pointer to standard V4L2 v4l2_format structure * * Returns the decoder's current pixel format in the v4l2_format * parameter. */ static int -ioctl_g_fmt_cap(struct v4l2_int_device *s, struct v4l2_format *f) +tvp514x_g_fmt_cap(struct v4l2_subdev *sd, struct v4l2_format *f) { - struct tvp514x_decoder *decoder = s->priv; + struct tvp514x_decoder *decoder = to_decoder(sd); if (f == NULL) return -EINVAL; @@ -1073,25 +1044,24 @@ ioctl_g_fmt_cap(struct v4l2_int_device *s, struct v4l2_format *f) f->fmt.pix = decoder->pix; - v4l_dbg(1, debug, decoder->client, - "Current FMT: bytesperline - %d" + v4l2_dbg(1, debug, sd, "Current FMT: bytesperline - %d" "Width - %d, Height - %d", decoder->pix.bytesperline, decoder->pix.width, decoder->pix.height); return 0; } -/** - * ioctl_g_parm - V4L2 decoder interface handler for VIDIOC_G_PARM ioctl - * @s: pointer to standard V4L2 device structure +/* + * tvp514x_g_parm - V4L2 decoder interface handler for VIDIOC_G_PARM ioctl + * @sd: pointer to standard V4L2 sub-device structure * @a: pointer to standard V4L2 VIDIOC_G_PARM ioctl structure * * Returns the decoder's video CAPTURE parameters. */ static int -ioctl_g_parm(struct v4l2_int_device *s, struct v4l2_streamparm *a) +tvp514x_g_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *a) { - struct tvp514x_decoder *decoder = s->priv; + struct tvp514x_decoder *decoder = to_decoder(sd); struct v4l2_captureparm *cparm; enum tvp514x_std current_std; @@ -1105,7 +1075,7 @@ ioctl_g_parm(struct v4l2_int_device *s, struct v4l2_streamparm *a) a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; /* get the current standard */ - current_std = tvp514x_get_current_std(decoder); + current_std = tvp514x_get_current_std(sd); if (current_std == STD_INVALID) return -EINVAL; @@ -1119,18 +1089,18 @@ ioctl_g_parm(struct v4l2_int_device *s, struct v4l2_streamparm *a) return 0; } -/** - * ioctl_s_parm - V4L2 decoder interface handler for VIDIOC_S_PARM ioctl - * @s: pointer to standard V4L2 device structure +/* + * tvp514x_s_parm - V4L2 decoder interface handler for VIDIOC_S_PARM ioctl + * @sd: pointer to standard V4L2 sub-device structure * @a: pointer to standard V4L2 VIDIOC_S_PARM ioctl structure * * Configures the decoder to use the input parameters, if possible. If * not possible, returns the appropriate error code. */ static int -ioctl_s_parm(struct v4l2_int_device *s, struct v4l2_streamparm *a) +tvp514x_s_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *a) { - struct tvp514x_decoder *decoder = s->priv; + struct tvp514x_decoder *decoder = to_decoder(sd); struct v4l2_fract *timeperframe; enum tvp514x_std current_std; @@ -1143,7 +1113,7 @@ ioctl_s_parm(struct v4l2_int_device *s, struct v4l2_streamparm *a) timeperframe = &a->parm.capture.timeperframe; /* get the current standard */ - current_std = tvp514x_get_current_std(decoder); + current_std = tvp514x_get_current_std(sd); if (current_std == STD_INVALID) return -EINVAL; @@ -1155,112 +1125,59 @@ ioctl_s_parm(struct v4l2_int_device *s, struct v4l2_streamparm *a) return 0; } -/** - * ioctl_g_ifparm - V4L2 decoder interface handler for vidioc_int_g_ifparm_num - * @s: pointer to standard V4L2 device structure - * @p: pointer to standard V4L2 vidioc_int_g_ifparm_num ioctl structure - * - * Gets slave interface parameters. - * Calculates the required xclk value to support the requested - * clock parameters in p. This value is returned in the p - * parameter. - */ -static int ioctl_g_ifparm(struct v4l2_int_device *s, struct v4l2_ifparm *p) -{ - struct tvp514x_decoder *decoder = s->priv; - int rval; - - if (p == NULL) - return -EINVAL; - - if (NULL == decoder->pdata->ifparm) - return -EINVAL; - - rval = decoder->pdata->ifparm(p); - if (rval) { - v4l_err(decoder->client, "g_ifparm.Err[%d]\n", rval); - return rval; - } - - p->u.bt656.clock_curr = TVP514X_XCLK_BT656; - - return 0; -} - -/** - * ioctl_g_priv - V4L2 decoder interface handler for vidioc_int_g_priv_num - * @s: pointer to standard V4L2 device structure - * @p: void pointer to hold decoder's private data address - * - * Returns device's (decoder's) private data area address in p parameter - */ -static int ioctl_g_priv(struct v4l2_int_device *s, void *p) -{ - struct tvp514x_decoder *decoder = s->priv; - - if (NULL == decoder->pdata->priv_data_set) - return -EINVAL; - - return decoder->pdata->priv_data_set(p); -} - -/** - * ioctl_s_power - V4L2 decoder interface handler for vidioc_int_s_power_num - * @s: pointer to standard V4L2 device structure - * @on: power state to which device is to be set +/* + * tvp514x_s_stream - V4L2 decoder interface handler for vidioc_int_s_power_num + * @sd: pointer to standard V4L2 sub-device structure + * @enable: streaming enable or disable * - * Sets devices power state to requrested state, if possible. + * Sets streaming to enable or disable, if possible. */ -static int ioctl_s_power(struct v4l2_int_device *s, enum v4l2_power on) +static int tvp514x_s_stream(struct v4l2_subdev *sd, int enable) { - struct tvp514x_decoder *decoder = s->priv; int err = 0; + struct i2c_client *client = v4l2_get_subdevdata(sd); + struct tvp514x_decoder *decoder = to_decoder(sd); - switch (on) { - case V4L2_POWER_OFF: - /* Power Down Sequence */ - err = - tvp514x_write_reg(decoder->client, REG_OPERATION_MODE, - 0x01); - /* Disable mux for TVP5146/47 decoder data path */ - if (decoder->pdata->power_set) - err |= decoder->pdata->power_set(on); - decoder->state = STATE_NOT_DETECTED; - break; + if (decoder->streaming == enable) + return 0; - case V4L2_POWER_STANDBY: - if (decoder->pdata->power_set) - err = decoder->pdata->power_set(on); + switch (enable) { + case 0: + { + /* Power Down Sequence */ + err = tvp514x_write_reg(sd, REG_OPERATION_MODE, 0x01); + if (err) { + v4l2_err(sd, "Unable to turn off decoder\n"); + return err; + } + decoder->streaming = enable; break; + } + case 1: + { + struct tvp514x_reg *int_seq = (struct tvp514x_reg *) + client->driver->id_table->driver_data; - case V4L2_POWER_ON: - /* Enable mux for TVP5146/47 decoder data path */ - if ((decoder->pdata->power_set) && - (decoder->state == STATE_NOT_DETECTED)) { - int i; - struct tvp514x_init_seq *int_seq = - (struct tvp514x_init_seq *) - decoder->id->driver_data; - - err = decoder->pdata->power_set(on); - - /* Power Up Sequence */ - for (i = 0; i < int_seq->no_regs; i++) { - err |= tvp514x_write_reg(decoder->client, - int_seq->init_reg_seq[i].reg, - int_seq->init_reg_seq[i].val); - } - /* Detect the sensor is not already detected */ - err |= tvp514x_detect(decoder); - if (err) { - v4l_err(decoder->client, - "Unable to detect decoder\n"); - return err; - } + /* Power Up Sequence */ + err = tvp514x_write_regs(sd, int_seq); + if (err) { + v4l2_err(sd, "Unable to turn on decoder\n"); + return err; + } + /* Detect if not already detected */ + err = tvp514x_detect(sd, decoder); + if (err) { + v4l2_err(sd, "Unable to detect decoder\n"); + return err; } - err |= tvp514x_configure(decoder); + err = tvp514x_configure(sd, decoder); + if (err) { + v4l2_err(sd, "Unable to configure decoder\n"); + return err; + } + decoder->streaming = enable; break; - + } default: err = -ENODEV; break; @@ -1269,93 +1186,37 @@ static int ioctl_s_power(struct v4l2_int_device *s, enum v4l2_power on) return err; } -/** - * ioctl_init - V4L2 decoder interface handler for VIDIOC_INT_INIT - * @s: pointer to standard V4L2 device structure - * - * Initialize the decoder device (calls tvp514x_configure()) - */ -static int ioctl_init(struct v4l2_int_device *s) -{ - struct tvp514x_decoder *decoder = s->priv; - - /* Set default standard to auto */ - decoder->tvp514x_regs[REG_VIDEO_STD].val = - VIDEO_STD_AUTO_SWITCH_BIT; - - return tvp514x_configure(decoder); -} - -/** - * ioctl_dev_exit - V4L2 decoder interface handler for vidioc_int_dev_exit_num - * @s: pointer to standard V4L2 device structure - * - * Delinitialise the dev. at slave detach. The complement of ioctl_dev_init. - */ -static int ioctl_dev_exit(struct v4l2_int_device *s) -{ - return 0; -} - -/** - * ioctl_dev_init - V4L2 decoder interface handler for vidioc_int_dev_init_num - * @s: pointer to standard V4L2 device structure - * - * Initialise the device when slave attaches to the master. Returns 0 if - * TVP5146/47 device could be found, otherwise returns appropriate error. - */ -static int ioctl_dev_init(struct v4l2_int_device *s) -{ - struct tvp514x_decoder *decoder = s->priv; - int err; - - err = tvp514x_detect(decoder); - if (err < 0) { - v4l_err(decoder->client, - "Unable to detect decoder\n"); - return err; - } - - v4l_info(decoder->client, - "chip version 0x%.2x detected\n", decoder->ver); +static const struct v4l2_subdev_core_ops tvp514x_core_ops = { + .queryctrl = tvp514x_queryctrl, + .g_ctrl = tvp514x_g_ctrl, + .s_ctrl = tvp514x_s_ctrl, + .s_std = tvp514x_s_std, +}; - return 0; -} +static const struct v4l2_subdev_video_ops tvp514x_video_ops = { + .s_routing = tvp514x_s_routing, + .querystd = tvp514x_querystd, + .enum_fmt = tvp514x_enum_fmt_cap, + .g_fmt = tvp514x_g_fmt_cap, + .try_fmt = tvp514x_try_fmt_cap, + .s_fmt = tvp514x_s_fmt_cap, + .g_parm = tvp514x_g_parm, + .s_parm = tvp514x_s_parm, + .s_stream = tvp514x_s_stream, +}; -static struct v4l2_int_ioctl_desc tvp514x_ioctl_desc[] = { - {vidioc_int_dev_init_num, (v4l2_int_ioctl_func*) ioctl_dev_init}, - {vidioc_int_dev_exit_num, (v4l2_int_ioctl_func*) ioctl_dev_exit}, - {vidioc_int_s_power_num, (v4l2_int_ioctl_func*) ioctl_s_power}, - {vidioc_int_g_priv_num, (v4l2_int_ioctl_func*) ioctl_g_priv}, - {vidioc_int_g_ifparm_num, (v4l2_int_ioctl_func*) ioctl_g_ifparm}, - {vidioc_int_init_num, (v4l2_int_ioctl_func*) ioctl_init}, - {vidioc_int_enum_fmt_cap_num, - (v4l2_int_ioctl_func *) ioctl_enum_fmt_cap}, - {vidioc_int_try_fmt_cap_num, - (v4l2_int_ioctl_func *) ioctl_try_fmt_cap}, - {vidioc_int_g_fmt_cap_num, - (v4l2_int_ioctl_func *) ioctl_g_fmt_cap}, - {vidioc_int_s_fmt_cap_num, - (v4l2_int_ioctl_func *) ioctl_s_fmt_cap}, - {vidioc_int_g_parm_num, (v4l2_int_ioctl_func *) ioctl_g_parm}, - {vidioc_int_s_parm_num, (v4l2_int_ioctl_func *) ioctl_s_parm}, - {vidioc_int_queryctrl_num, - (v4l2_int_ioctl_func *) ioctl_queryctrl}, - {vidioc_int_g_ctrl_num, (v4l2_int_ioctl_func *) ioctl_g_ctrl}, - {vidioc_int_s_ctrl_num, (v4l2_int_ioctl_func *) ioctl_s_ctrl}, - {vidioc_int_querystd_num, (v4l2_int_ioctl_func *) ioctl_querystd}, - {vidioc_int_s_std_num, (v4l2_int_ioctl_func *) ioctl_s_std}, - {vidioc_int_s_video_routing_num, - (v4l2_int_ioctl_func *) ioctl_s_routing}, +static const struct v4l2_subdev_ops tvp514x_ops = { + .core = &tvp514x_core_ops, + .video = &tvp514x_video_ops, }; static struct tvp514x_decoder tvp514x_dev = { - .state = STATE_NOT_DETECTED, + .streaming = 0, .fmt_list = tvp514x_fmt_list, .num_fmts = ARRAY_SIZE(tvp514x_fmt_list), - .pix = { /* Default to NTSC 8-bit YUV 422 */ + .pix = {/* Default to NTSC 8-bit YUV 422 */ .width = NTSC_NUM_ACTIVE_PIXELS, .height = NTSC_NUM_ACTIVE_LINES, .pixelformat = V4L2_PIX_FMT_UYVY, @@ -1369,20 +1230,13 @@ static struct tvp514x_decoder tvp514x_dev = { .current_std = STD_NTSC_MJ, .std_list = tvp514x_std_list, .num_stds = ARRAY_SIZE(tvp514x_std_list), - .v4l2_int_device = { - .module = THIS_MODULE, - .name = TVP514X_MODULE_NAME, - .type = v4l2_int_type_slave, - }, - .tvp514x_slave = { - .ioctls = tvp514x_ioctl_desc, - .num_ioctls = ARRAY_SIZE(tvp514x_ioctl_desc), - }, + }; -/** +/* * tvp514x_probe - decoder driver i2c probe handler * @client: i2c driver client device structure + * @id: i2c driver id table * * Register decoder as an i2c client device and V4L2 * device. @@ -1391,82 +1245,71 @@ static int tvp514x_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct tvp514x_decoder *decoder; - int err; + struct v4l2_subdev *sd; /* Check if the adapter supports the needed features */ if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) return -EIO; + if (!client->dev.platform_data) { + v4l2_err(client, "No platform data!!\n"); + return -ENODEV; + } + decoder = kzalloc(sizeof(*decoder), GFP_KERNEL); if (!decoder) return -ENOMEM; - if (!client->dev.platform_data) { - v4l_err(client, "No platform data!!\n"); - err = -ENODEV; - goto out_free; - } - + /* + * Initialize the tvp514x_decoder with default configuration + */ *decoder = tvp514x_dev; - decoder->v4l2_int_device.priv = decoder; - decoder->pdata = client->dev.platform_data; - decoder->v4l2_int_device.u.slave = &decoder->tvp514x_slave; + /* Copy default register configuration */ memcpy(decoder->tvp514x_regs, tvp514x_reg_list_default, sizeof(tvp514x_reg_list_default)); + + /* + * Copy board specific information here + */ + decoder->pdata = client->dev.platform_data; + /* * Fetch platform specific data, and configure the * tvp514x_reg_list[] accordingly. Since this is one * time configuration, no need to preserve. */ decoder->tvp514x_regs[REG_OUTPUT_FORMATTER2].val |= - (decoder->pdata->clk_polarity << 1); + (decoder->pdata->clk_polarity << 1); decoder->tvp514x_regs[REG_SYNC_CONTROL].val |= - ((decoder->pdata->hs_polarity << 2) | - (decoder->pdata->vs_polarity << 3)); - /* - * Save the id data, required for power up sequence - */ - decoder->id = (struct i2c_device_id *)id; - /* Attach to Master */ - strcpy(decoder->v4l2_int_device.u.slave->attach_to, - decoder->pdata->master); - decoder->client = client; - i2c_set_clientdata(client, decoder); + ((decoder->pdata->hs_polarity << 2) | + (decoder->pdata->vs_polarity << 3)); + /* Set default standard to auto */ + decoder->tvp514x_regs[REG_VIDEO_STD].val = + VIDEO_STD_AUTO_SWITCH_BIT; /* Register with V4L2 layer as slave device */ - err = v4l2_int_device_register(&decoder->v4l2_int_device); - if (err) { - i2c_set_clientdata(client, NULL); - v4l_err(client, - "Unable to register to v4l2. Err[%d]\n", err); - goto out_free; - - } else - v4l_info(client, "Registered to v4l2 master %s!!\n", - decoder->pdata->master); + sd = &decoder->sd; + v4l2_i2c_subdev_init(sd, client, &tvp514x_ops); + + v4l2_info(sd, "%s decoder driver registered !!\n", sd->name); + return 0; -out_free: - kfree(decoder); - return err; } -/** +/* * tvp514x_remove - decoder driver i2c remove handler * @client: i2c driver client device structure * * Unregister decoder as an i2c client device and V4L2 * device. Complement of tvp514x_probe(). */ -static int __exit tvp514x_remove(struct i2c_client *client) +static int tvp514x_remove(struct i2c_client *client) { - struct tvp514x_decoder *decoder = i2c_get_clientdata(client); - - if (!client->adapter) - return -ENODEV; /* our client isn't attached */ + struct v4l2_subdev *sd = i2c_get_clientdata(client); + struct tvp514x_decoder *decoder = to_decoder(sd); - v4l2_int_device_unregister(&decoder->v4l2_int_device); - i2c_set_clientdata(client, NULL); + v4l2_device_unregister_subdev(sd); kfree(decoder); return 0; } @@ -1485,11 +1328,9 @@ static const struct tvp514x_reg tvp5146_init_reg_seq[] = { {TOK_WRITE, REG_VBUS_DATA_ACCESS_NO_VBUS_ADDR_INCR, 0x00}, {TOK_WRITE, REG_OPERATION_MODE, 0x01}, {TOK_WRITE, REG_OPERATION_MODE, 0x00}, + {TOK_TERM, 0, 0}, }; -static const struct tvp514x_init_seq tvp5146_init = { - .no_regs = ARRAY_SIZE(tvp5146_init_reg_seq), - .init_reg_seq = tvp5146_init_reg_seq, -}; + /* * TVP5147 Init/Power on Sequence */ @@ -1512,22 +1353,18 @@ static const struct tvp514x_reg tvp5147_init_reg_seq[] = { {TOK_WRITE, REG_VBUS_DATA_ACCESS_NO_VBUS_ADDR_INCR, 0x00}, {TOK_WRITE, REG_OPERATION_MODE, 0x01}, {TOK_WRITE, REG_OPERATION_MODE, 0x00}, + {TOK_TERM, 0, 0}, }; -static const struct tvp514x_init_seq tvp5147_init = { - .no_regs = ARRAY_SIZE(tvp5147_init_reg_seq), - .init_reg_seq = tvp5147_init_reg_seq, -}; + /* * TVP5146M2/TVP5147M1 Init/Power on Sequence */ static const struct tvp514x_reg tvp514xm_init_reg_seq[] = { {TOK_WRITE, REG_OPERATION_MODE, 0x01}, {TOK_WRITE, REG_OPERATION_MODE, 0x00}, + {TOK_TERM, 0, 0}, }; -static const struct tvp514x_init_seq tvp514xm_init = { - .no_regs = ARRAY_SIZE(tvp514xm_init_reg_seq), - .init_reg_seq = tvp514xm_init_reg_seq, -}; + /* * I2C Device Table - * @@ -1535,48 +1372,34 @@ static const struct tvp514x_init_seq tvp514xm_init = { * driver_data - Driver data */ static const struct i2c_device_id tvp514x_id[] = { - {"tvp5146", (unsigned long)&tvp5146_init}, - {"tvp5146m2", (unsigned long)&tvp514xm_init}, - {"tvp5147", (unsigned long)&tvp5147_init}, - {"tvp5147m1", (unsigned long)&tvp514xm_init}, + {"tvp5146", (unsigned long)tvp5146_init_reg_seq}, + {"tvp5146m2", (unsigned long)tvp514xm_init_reg_seq}, + {"tvp5147", (unsigned long)tvp5147_init_reg_seq}, + {"tvp5147m1", (unsigned long)tvp514xm_init_reg_seq}, {}, }; MODULE_DEVICE_TABLE(i2c, tvp514x_id); -static struct i2c_driver tvp514x_i2c_driver = { +static struct i2c_driver tvp514x_driver = { .driver = { - .name = TVP514X_MODULE_NAME, - .owner = THIS_MODULE, - }, + .owner = THIS_MODULE, + .name = TVP514X_MODULE_NAME, + }, .probe = tvp514x_probe, - .remove = __exit_p(tvp514x_remove), + .remove = tvp514x_remove, .id_table = tvp514x_id, }; -/** - * tvp514x_init - * - * Module init function - */ static int __init tvp514x_init(void) { - return i2c_add_driver(&tvp514x_i2c_driver); + return i2c_add_driver(&tvp514x_driver); } -/** - * tvp514x_cleanup - * - * Module exit function - */ -static void __exit tvp514x_cleanup(void) +static void __exit tvp514x_exit(void) { - i2c_del_driver(&tvp514x_i2c_driver); + i2c_del_driver(&tvp514x_driver); } module_init(tvp514x_init); -module_exit(tvp514x_cleanup); - -MODULE_AUTHOR("Texas Instruments"); -MODULE_DESCRIPTION("TVP514X linux decoder driver"); -MODULE_LICENSE("GPL"); +module_exit(tvp514x_exit); diff --git a/linux/drivers/media/video/tvp514x_regs.h b/linux/drivers/media/video/tvp514x_regs.h index 351620aee..18f29ad0d 100644 --- a/linux/drivers/media/video/tvp514x_regs.h +++ b/linux/drivers/media/video/tvp514x_regs.h @@ -284,14 +284,4 @@ struct tvp514x_reg { u32 val; }; -/** - * struct tvp514x_init_seq - Structure for TVP5146/47/46M2/47M1 power up - * Sequence. - * @ no_regs - Number of registers to write for power up sequence. - * @ init_reg_seq - Array of registers and respective value to write. - */ -struct tvp514x_init_seq { - unsigned int no_regs; - const struct tvp514x_reg *init_reg_seq; -}; #endif /* ifndef _TVP514X_REGS_H */ -- cgit v1.2.3 From 60ea01f2166060a29cbc120e0af381ba1fccfaea Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 1 Jul 2009 09:20:43 +0200 Subject: tvp514x: formatting comments as per kernel documentation From: Muralidharan Karicheri Fix documentation style based on comments from Mauro. Reviewed by: Hans Verkuil Priority: normal Signed-off-by: Muralidharan Karicheri Signed-off-by: Hans Verkuil --- linux/drivers/media/video/tvp514x.c | 275 ++++++++++++++++++++---------------- 1 file changed, 157 insertions(+), 118 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/tvp514x.c b/linux/drivers/media/video/tvp514x.c index c8386e2f7..244372627 100644 --- a/linux/drivers/media/video/tvp514x.c +++ b/linux/drivers/media/video/tvp514x.c @@ -56,16 +56,14 @@ MODULE_AUTHOR("Texas Instruments"); MODULE_DESCRIPTION("TVP514X linux decoder driver"); MODULE_LICENSE("GPL"); -/* - * enum tvp514x_std - enum for supported standards - */ +/* enum tvp514x_std - enum for supported standards */ enum tvp514x_std { STD_NTSC_MJ = 0, STD_PAL_BDGHIN, STD_INVALID }; -/* +/** * struct tvp514x_std_info - Structure to store standard informations * @width: Line width in pixels * @height:Number of active lines @@ -80,7 +78,7 @@ struct tvp514x_std_info { }; static struct tvp514x_reg tvp514x_reg_list_default[0x40]; -/* +/** * struct tvp514x_decoder - TVP5146/47 decoder object * @sd: Subdevice Slave handle * @tvp514x_regs: copy of hw's regs with preset values. @@ -111,18 +109,18 @@ struct tvp514x_decoder { enum tvp514x_std current_std; int num_stds; struct tvp514x_std_info *std_list; - /* - * Input and Output Routing parameters - */ + /* Input and Output Routing parameters */ u32 input; u32 output; }; /* TVP514x default register values */ static struct tvp514x_reg tvp514x_reg_list_default[] = { - {TOK_WRITE, REG_INPUT_SEL, 0x05}, /* Composite selected */ + /* Composite selected */ + {TOK_WRITE, REG_INPUT_SEL, 0x05}, {TOK_WRITE, REG_AFE_GAIN_CTRL, 0x0F}, - {TOK_WRITE, REG_VIDEO_STD, 0x00}, /* Auto mode */ + /* Auto mode */ + {TOK_WRITE, REG_VIDEO_STD, 0x00}, {TOK_WRITE, REG_OPERATION_MODE, 0x00}, {TOK_SKIP, REG_AUTOSWITCH_MASK, 0x3F}, {TOK_WRITE, REG_COLOR_KILLER, 0x10}, @@ -135,53 +133,73 @@ static struct tvp514x_reg tvp514x_reg_list_default[] = { {TOK_WRITE, REG_HUE, 0x00}, {TOK_WRITE, REG_CHROMA_CONTROL1, 0x00}, {TOK_WRITE, REG_CHROMA_CONTROL2, 0x0E}, - {TOK_SKIP, 0x0F, 0x00}, /* Reserved */ + /* Reserved */ + {TOK_SKIP, 0x0F, 0x00}, {TOK_WRITE, REG_COMP_PR_SATURATION, 0x80}, {TOK_WRITE, REG_COMP_Y_CONTRAST, 0x80}, {TOK_WRITE, REG_COMP_PB_SATURATION, 0x80}, - {TOK_SKIP, 0x13, 0x00}, /* Reserved */ + /* Reserved */ + {TOK_SKIP, 0x13, 0x00}, {TOK_WRITE, REG_COMP_Y_BRIGHTNESS, 0x80}, - {TOK_SKIP, 0x15, 0x00}, /* Reserved */ - {TOK_SKIP, REG_AVID_START_PIXEL_LSB, 0x55}, /* NTSC timing */ + /* Reserved */ + {TOK_SKIP, 0x15, 0x00}, + /* NTSC timing */ + {TOK_SKIP, REG_AVID_START_PIXEL_LSB, 0x55}, {TOK_SKIP, REG_AVID_START_PIXEL_MSB, 0x00}, {TOK_SKIP, REG_AVID_STOP_PIXEL_LSB, 0x25}, {TOK_SKIP, REG_AVID_STOP_PIXEL_MSB, 0x03}, - {TOK_SKIP, REG_HSYNC_START_PIXEL_LSB, 0x00}, /* NTSC timing */ + /* NTSC timing */ + {TOK_SKIP, REG_HSYNC_START_PIXEL_LSB, 0x00}, {TOK_SKIP, REG_HSYNC_START_PIXEL_MSB, 0x00}, {TOK_SKIP, REG_HSYNC_STOP_PIXEL_LSB, 0x40}, {TOK_SKIP, REG_HSYNC_STOP_PIXEL_MSB, 0x00}, - {TOK_SKIP, REG_VSYNC_START_LINE_LSB, 0x04}, /* NTSC timing */ + /* NTSC timing */ + {TOK_SKIP, REG_VSYNC_START_LINE_LSB, 0x04}, {TOK_SKIP, REG_VSYNC_START_LINE_MSB, 0x00}, {TOK_SKIP, REG_VSYNC_STOP_LINE_LSB, 0x07}, {TOK_SKIP, REG_VSYNC_STOP_LINE_MSB, 0x00}, - {TOK_SKIP, REG_VBLK_START_LINE_LSB, 0x01}, /* NTSC timing */ + /* NTSC timing */ + {TOK_SKIP, REG_VBLK_START_LINE_LSB, 0x01}, {TOK_SKIP, REG_VBLK_START_LINE_MSB, 0x00}, {TOK_SKIP, REG_VBLK_STOP_LINE_LSB, 0x15}, {TOK_SKIP, REG_VBLK_STOP_LINE_MSB, 0x00}, - {TOK_SKIP, 0x26, 0x00}, /* Reserved */ - {TOK_SKIP, 0x27, 0x00}, /* Reserved */ + /* Reserved */ + {TOK_SKIP, 0x26, 0x00}, + /* Reserved */ + {TOK_SKIP, 0x27, 0x00}, {TOK_SKIP, REG_FAST_SWTICH_CONTROL, 0xCC}, - {TOK_SKIP, 0x29, 0x00}, /* Reserved */ + /* Reserved */ + {TOK_SKIP, 0x29, 0x00}, {TOK_SKIP, REG_FAST_SWTICH_SCART_DELAY, 0x00}, - {TOK_SKIP, 0x2B, 0x00}, /* Reserved */ + /* Reserved */ + {TOK_SKIP, 0x2B, 0x00}, {TOK_SKIP, REG_SCART_DELAY, 0x00}, {TOK_SKIP, REG_CTI_DELAY, 0x00}, {TOK_SKIP, REG_CTI_CONTROL, 0x00}, - {TOK_SKIP, 0x2F, 0x00}, /* Reserved */ - {TOK_SKIP, 0x30, 0x00}, /* Reserved */ - {TOK_SKIP, 0x31, 0x00}, /* Reserved */ - {TOK_WRITE, REG_SYNC_CONTROL, 0x00}, /* HS, VS active high */ - {TOK_WRITE, REG_OUTPUT_FORMATTER1, 0x00}, /* 10-bit BT.656 */ - {TOK_WRITE, REG_OUTPUT_FORMATTER2, 0x11}, /* Enable clk & data */ - {TOK_WRITE, REG_OUTPUT_FORMATTER3, 0xEE}, /* Enable AVID & FLD */ - {TOK_WRITE, REG_OUTPUT_FORMATTER4, 0xAF}, /* Enable VS & HS */ + /* Reserved */ + {TOK_SKIP, 0x2F, 0x00}, + /* Reserved */ + {TOK_SKIP, 0x30, 0x00}, + /* Reserved */ + {TOK_SKIP, 0x31, 0x00}, + /* HS, VS active high */ + {TOK_WRITE, REG_SYNC_CONTROL, 0x00}, + /* 10-bit BT.656 */ + {TOK_WRITE, REG_OUTPUT_FORMATTER1, 0x00}, + /* Enable clk & data */ + {TOK_WRITE, REG_OUTPUT_FORMATTER2, 0x11}, + /* Enable AVID & FLD */ + {TOK_WRITE, REG_OUTPUT_FORMATTER3, 0xEE}, + /* Enable VS & HS */ + {TOK_WRITE, REG_OUTPUT_FORMATTER4, 0xAF}, {TOK_WRITE, REG_OUTPUT_FORMATTER5, 0xFF}, {TOK_WRITE, REG_OUTPUT_FORMATTER6, 0xFF}, - {TOK_WRITE, REG_CLEAR_LOST_LOCK, 0x01}, /* Clear status */ + /* Clear status */ + {TOK_WRITE, REG_CLEAR_LOST_LOCK, 0x01}, {TOK_TERM, 0, 0}, }; -/* +/** * List of image formats supported by TVP5146/47 decoder * Currently we are using 8 bit mode only, but can be * extended to 10/20 bit mode. @@ -196,7 +214,7 @@ static const struct v4l2_fmtdesc tvp514x_fmt_list[] = { }, }; -/* +/** * Supported standards - * * Currently supports two standards only, need to add support for rest of the @@ -239,8 +257,11 @@ static inline struct tvp514x_decoder *to_decoder(struct v4l2_subdev *sd) } -/* - * Read a value from a register in an TVP5146/47 decoder device. +/** + * tvp514x_read_reg() - Read a value from a register in an TVP5146/47. + * @sd: ptr to v4l2_subdev struct + * @reg: TVP5146/47 register address + * * Returns value read if successful, or non-zero (-1) otherwise. */ static int tvp514x_read_reg(struct v4l2_subdev *sd, u8 reg) @@ -263,6 +284,11 @@ read_again: return err; } +/** + * dump_reg() - dump the register content of TVP5146/47. + * @sd: ptr to v4l2_subdev struct + * @reg: TVP5146/47 register address + */ static void dump_reg(struct v4l2_subdev *sd, u8 reg) { u32 val; @@ -271,7 +297,12 @@ static void dump_reg(struct v4l2_subdev *sd, u8 reg) v4l2_info(sd, "Reg(0x%.2X): 0x%.2X\n", reg, val); } -/* +/** + * tvp514x_write_reg() - Write a value to a register in TVP5146/47 + * @sd: ptr to v4l2_subdev struct + * @reg: TVP5146/47 register address + * @val: value to be written to the register + * * Write a value to a register in an TVP5146/47 decoder device. * Returns zero if successful, or non-zero otherwise. */ @@ -295,14 +326,16 @@ write_again: return err; } -/* - * tvp514x_write_regs : Initializes a list of TVP5146/47 registers +/** + * tvp514x_write_regs() : Initializes a list of TVP5146/47 registers + * @sd: ptr to v4l2_subdev struct + * @reglist: list of TVP5146/47 registers and values + * + * Initializes a list of TVP5146/47 registers:- * if token is TOK_TERM, then entire write operation terminates * if token is TOK_DELAY, then a delay of 'val' msec is introduced * if token is TOK_SKIP, then the register write is skipped * if token is TOK_WRITE, then the register write is performed - * - * reglist - list of registers to be written * Returns zero if successful, or non-zero otherwise. */ static int tvp514x_write_regs(struct v4l2_subdev *sd, @@ -329,9 +362,12 @@ static int tvp514x_write_regs(struct v4l2_subdev *sd, return 0; } -/* - * tvp514x_get_current_std: - * Returns the current standard detected by TVP5146/47 +/** + * tvp514x_get_current_std() : Get the current standard detected by TVP5146/47 + * @sd: ptr to v4l2_subdev struct + * + * Get current standard detected by TVP5146/47, STD_INVALID if there is no + * standard detected. */ static enum tvp514x_std tvp514x_get_current_std(struct v4l2_subdev *sd) { @@ -342,7 +378,8 @@ static enum tvp514x_std tvp514x_get_current_std(struct v4l2_subdev *sd) /* use the standard status register */ std_status = tvp514x_read_reg(sd, REG_VIDEO_STD_STATUS); else - std_status = std; /* use the standard register itself */ + /* use the standard register itself */ + std_status = std; switch (std_status & VIDEO_STD_MASK) { case VIDEO_STD_NTSC_MJ_BIT: @@ -358,9 +395,7 @@ static enum tvp514x_std tvp514x_get_current_std(struct v4l2_subdev *sd) return STD_INVALID; } -/* - * TVP5146/47 register dump function - */ +/* TVP5146/47 register dump function */ static void tvp514x_reg_dump(struct v4l2_subdev *sd) { dump_reg(sd, REG_INPUT_SEL); @@ -407,8 +442,11 @@ static void tvp514x_reg_dump(struct v4l2_subdev *sd) dump_reg(sd, REG_CLEAR_LOST_LOCK); } -/* - * Configure the TVP5146/47 with the current register settings +/** + * tvp514x_configure() - Configure the TVP5146/47 registers + * @sd: ptr to v4l2_subdev struct + * @decoder: ptr to tvp514x_decoder structure + * * Returns zero if successful, or non-zero otherwise. */ static int tvp514x_configure(struct v4l2_subdev *sd, @@ -428,8 +466,11 @@ static int tvp514x_configure(struct v4l2_subdev *sd, return 0; } -/* - * Detect if an tvp514x is present, and if so which revision. +/** + * tvp514x_detect() - Detect if an tvp514x is present, and if so which revision. + * @sd: pointer to standard V4L2 sub-device structure + * @decoder: pointer to tvp514x_decoder structure + * * A device is considered to be detected if the chip ID (LSB and MSB) * registers match the expected values. * Any value of the rom version register is accepted. @@ -468,13 +509,8 @@ static int tvp514x_detect(struct v4l2_subdev *sd, return 0; } -/* - * Following are decoder interface functions implemented by - * TVP5146/47 decoder driver. - */ - -/* - * tvp514x_querystd - V4L2 decoder interface handler for VIDIOC_QUERYSTD ioctl +/** + * tvp514x_querystd() - V4L2 decoder interface handler for querystd * @sd: pointer to standard V4L2 sub-device structure * @std_id: standard V4L2 std_id ioctl enum * @@ -546,8 +582,8 @@ static int tvp514x_querystd(struct v4l2_subdev *sd, v4l2_std_id *std_id) return 0; } -/* - * tvp514x_s_std - V4L2 decoder interface handler for VIDIOC_S_STD ioctl +/** + * tvp514x_s_std() - V4L2 decoder interface handler for s_std * @sd: pointer to standard V4L2 sub-device structure * @std_id: standard V4L2 v4l2_std_id ioctl enum * @@ -580,10 +616,12 @@ static int tvp514x_s_std(struct v4l2_subdev *sd, v4l2_std_id std_id) return 0; } -/* - * tvp514x_s_routing - V4L2 decoder interface handler for VIDIOC_S_INPUT ioctl +/** + * tvp514x_s_routing() - V4L2 decoder interface handler for s_routing * @sd: pointer to standard V4L2 sub-device structure - * @index: number of the input + * @input: input selector for routing the signal + * @output: output selector for routing the signal + * @config: config value. Not used * * If index is valid, selects the requested input. Otherwise, returns -EINVAL if * the input is not supported or there is no active signal present in the @@ -602,7 +640,8 @@ static int tvp514x_s_routing(struct v4l2_subdev *sd, if ((input >= INPUT_INVALID) || (output >= OUTPUT_INVALID)) - return -EINVAL; /* Index out of bound */ + /* Index out of bound */ + return -EINVAL; input_sel = input; output_sel = output; @@ -659,7 +698,7 @@ static int tvp514x_s_routing(struct v4l2_subdev *sd, lock_mask = STATUS_HORZ_SYNC_LOCK_BIT | STATUS_VIRT_SYNC_LOCK_BIT; break; - /*Need to add other interfaces*/ + /* Need to add other interfaces*/ default: return -EINVAL; } @@ -676,7 +715,8 @@ static int tvp514x_s_routing(struct v4l2_subdev *sd, sync_lock_status = tvp514x_read_reg(sd, REG_STATUS1); if (lock_mask == (sync_lock_status & lock_mask)) - break; /* Input detected */ + /* Input detected */ + break; } if ((current_std == STD_INVALID) || (try_count < 0)) @@ -692,8 +732,8 @@ static int tvp514x_s_routing(struct v4l2_subdev *sd, return 0; } -/* - * tvp514x_queryctrl - V4L2 decoder interface handler for VIDIOC_QUERYCTRL ioctl +/** + * tvp514x_queryctrl() - V4L2 decoder interface handler for queryctrl * @sd: pointer to standard V4L2 sub-device structure * @qctrl: standard V4L2 v4l2_queryctrl structure * @@ -710,13 +750,13 @@ tvp514x_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qctrl) switch (qctrl->id) { case V4L2_CID_BRIGHTNESS: - /* Brightness supported is (0-255), - */ + /* Brightness supported is (0-255), */ err = v4l2_ctrl_query_fill(qctrl, 0, 255, 1, 128); break; case V4L2_CID_CONTRAST: case V4L2_CID_SATURATION: - /* Saturation and Contrast supported is - + /** + * Saturation and Contrast supported is - * Contrast: 0 - 255 (Default - 128) * Saturation: 0 - 255 (Default - 128) */ @@ -729,7 +769,7 @@ tvp514x_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qctrl) err = v4l2_ctrl_query_fill(qctrl, -180, 180, 180, 0); break; case V4L2_CID_AUTOGAIN: - /* + /** * Auto Gain supported is - * 0 - 1 (Default - 1) */ @@ -747,8 +787,8 @@ tvp514x_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qctrl) return err; } -/* - * tvp514x_g_ctrl - V4L2 decoder interface handler for VIDIOC_G_CTRL ioctl +/** + * tvp514x_g_ctrl() - V4L2 decoder interface handler for g_ctrl * @sd: pointer to standard V4L2 sub-device structure * @ctrl: pointer to v4l2_control structure * @@ -802,8 +842,8 @@ tvp514x_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) return 0; } -/* - * tvp514x_s_ctrl - V4L2 decoder interface handler for VIDIOC_S_CTRL ioctl +/** + * tvp514x_s_ctrl() - V4L2 decoder interface handler for s_ctrl * @sd: pointer to standard V4L2 sub-device structure * @ctrl: pointer to v4l2_control structure * @@ -903,8 +943,8 @@ tvp514x_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) return err; } -/* - * tvp514x_enum_fmt_cap - Implement the CAPTURE buffer VIDIOC_ENUM_FMT ioctl +/** + * tvp514x_enum_fmt_cap() - V4L2 decoder interface handler for enum_fmt * @sd: pointer to standard V4L2 sub-device structure * @fmt: standard V4L2 VIDIOC_ENUM_FMT ioctl structure * @@ -921,10 +961,12 @@ tvp514x_enum_fmt_cap(struct v4l2_subdev *sd, struct v4l2_fmtdesc *fmt) index = fmt->index; if ((index >= decoder->num_fmts) || (index < 0)) - return -EINVAL; /* Index out of bound */ + /* Index out of bound */ + return -EINVAL; if (fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; /* only capture is supported */ + /* only capture is supported */ + return -EINVAL; memcpy(fmt, &decoder->fmt_list[index], sizeof(struct v4l2_fmtdesc)); @@ -935,8 +977,8 @@ tvp514x_enum_fmt_cap(struct v4l2_subdev *sd, struct v4l2_fmtdesc *fmt) return 0; } -/* - * tvp514x_try_fmt_cap - Implement the CAPTURE buffer VIDIOC_TRY_FMT ioctl +/** + * tvp514x_try_fmt_cap() - V4L2 decoder interface handler for try_fmt * @sd: pointer to standard V4L2 sub-device structure * @f: pointer to standard V4L2 VIDIOC_TRY_FMT ioctl structure * @@ -956,6 +998,7 @@ tvp514x_try_fmt_cap(struct v4l2_subdev *sd, struct v4l2_format *f) return -EINVAL; if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + /* only capture is supported */ f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; pix = &f->fmt.pix; @@ -975,7 +1018,8 @@ tvp514x_try_fmt_cap(struct v4l2_subdev *sd, struct v4l2_format *f) break; } if (ifmt == decoder->num_fmts) - ifmt = 0; /* None of the format matched, select default */ + /* None of the format matched, select default */ + ifmt = 0; pix->pixelformat = decoder->fmt_list[ifmt].pixelformat; pix->field = V4L2_FIELD_INTERLACED; @@ -991,8 +1035,8 @@ tvp514x_try_fmt_cap(struct v4l2_subdev *sd, struct v4l2_format *f) return 0; } -/* - * tvp514x_s_fmt_cap - V4L2 decoder interface handler for VIDIOC_S_FMT ioctl +/** + * tvp514x_s_fmt_cap() - V4L2 decoder interface handler for s_fmt * @sd: pointer to standard V4L2 sub-device structure * @f: pointer to standard V4L2 VIDIOC_S_FMT ioctl structure * @@ -1011,7 +1055,8 @@ tvp514x_s_fmt_cap(struct v4l2_subdev *sd, struct v4l2_format *f) return -EINVAL; if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; /* only capture is supported */ + /* only capture is supported */ + return -EINVAL; pix = &f->fmt.pix; rval = tvp514x_try_fmt_cap(sd, f); @@ -1023,8 +1068,8 @@ tvp514x_s_fmt_cap(struct v4l2_subdev *sd, struct v4l2_format *f) return rval; } -/* - * tvp514x_g_fmt_cap - V4L2 decoder interface handler for tvp514x_g_fmt_cap +/** + * tvp514x_g_fmt_cap() - V4L2 decoder interface handler for tvp514x_g_fmt_cap * @sd: pointer to standard V4L2 sub-device structure * @f: pointer to standard V4L2 v4l2_format structure * @@ -1040,7 +1085,8 @@ tvp514x_g_fmt_cap(struct v4l2_subdev *sd, struct v4l2_format *f) return -EINVAL; if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; /* only capture is supported */ + /* only capture is supported */ + return -EINVAL; f->fmt.pix = decoder->pix; @@ -1051,8 +1097,8 @@ tvp514x_g_fmt_cap(struct v4l2_subdev *sd, struct v4l2_format *f) return 0; } -/* - * tvp514x_g_parm - V4L2 decoder interface handler for VIDIOC_G_PARM ioctl +/** + * tvp514x_g_parm() - V4L2 decoder interface handler for g_parm * @sd: pointer to standard V4L2 sub-device structure * @a: pointer to standard V4L2 VIDIOC_G_PARM ioctl structure * @@ -1069,7 +1115,8 @@ tvp514x_g_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *a) return -EINVAL; if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; /* only capture is supported */ + /* only capture is supported */ + return -EINVAL; memset(a, 0, sizeof(*a)); a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; @@ -1089,8 +1136,8 @@ tvp514x_g_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *a) return 0; } -/* - * tvp514x_s_parm - V4L2 decoder interface handler for VIDIOC_S_PARM ioctl +/** + * tvp514x_s_parm() - V4L2 decoder interface handler for s_parm * @sd: pointer to standard V4L2 sub-device structure * @a: pointer to standard V4L2 VIDIOC_S_PARM ioctl structure * @@ -1108,7 +1155,8 @@ tvp514x_s_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *a) return -EINVAL; if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; /* only capture is supported */ + /* only capture is supported */ + return -EINVAL; timeperframe = &a->parm.capture.timeperframe; @@ -1125,8 +1173,8 @@ tvp514x_s_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *a) return 0; } -/* - * tvp514x_s_stream - V4L2 decoder interface handler for vidioc_int_s_power_num +/** + * tvp514x_s_stream() - V4L2 decoder i/f handler for s_stream * @sd: pointer to standard V4L2 sub-device structure * @enable: streaming enable or disable * @@ -1216,7 +1264,8 @@ static struct tvp514x_decoder tvp514x_dev = { .fmt_list = tvp514x_fmt_list, .num_fmts = ARRAY_SIZE(tvp514x_fmt_list), - .pix = {/* Default to NTSC 8-bit YUV 422 */ + .pix = { + /* Default to NTSC 8-bit YUV 422 */ .width = NTSC_NUM_ACTIVE_PIXELS, .height = NTSC_NUM_ACTIVE_LINES, .pixelformat = V4L2_PIX_FMT_UYVY, @@ -1233,8 +1282,8 @@ static struct tvp514x_decoder tvp514x_dev = { }; -/* - * tvp514x_probe - decoder driver i2c probe handler +/** + * tvp514x_probe() - decoder driver i2c probe handler * @client: i2c driver client device structure * @id: i2c driver id table * @@ -1260,20 +1309,16 @@ tvp514x_probe(struct i2c_client *client, const struct i2c_device_id *id) if (!decoder) return -ENOMEM; - /* - * Initialize the tvp514x_decoder with default configuration - */ + /* Initialize the tvp514x_decoder with default configuration */ *decoder = tvp514x_dev; /* Copy default register configuration */ memcpy(decoder->tvp514x_regs, tvp514x_reg_list_default, sizeof(tvp514x_reg_list_default)); - /* - * Copy board specific information here - */ + /* Copy board specific information here */ decoder->pdata = client->dev.platform_data; - /* + /** * Fetch platform specific data, and configure the * tvp514x_reg_list[] accordingly. Since this is one * time configuration, no need to preserve. @@ -1297,8 +1342,8 @@ tvp514x_probe(struct i2c_client *client, const struct i2c_device_id *id) } -/* - * tvp514x_remove - decoder driver i2c remove handler +/** + * tvp514x_remove() - decoder driver i2c remove handler * @client: i2c driver client device structure * * Unregister decoder as an i2c client device and V4L2 @@ -1313,9 +1358,7 @@ static int tvp514x_remove(struct i2c_client *client) kfree(decoder); return 0; } -/* - * TVP5146 Init/Power on Sequence - */ +/* TVP5146 Init/Power on Sequence */ static const struct tvp514x_reg tvp5146_init_reg_seq[] = { {TOK_WRITE, REG_VBUS_ADDRESS_ACCESS1, 0x02}, {TOK_WRITE, REG_VBUS_ADDRESS_ACCESS2, 0x00}, @@ -1331,9 +1374,7 @@ static const struct tvp514x_reg tvp5146_init_reg_seq[] = { {TOK_TERM, 0, 0}, }; -/* - * TVP5147 Init/Power on Sequence - */ +/* TVP5147 Init/Power on Sequence */ static const struct tvp514x_reg tvp5147_init_reg_seq[] = { {TOK_WRITE, REG_VBUS_ADDRESS_ACCESS1, 0x02}, {TOK_WRITE, REG_VBUS_ADDRESS_ACCESS2, 0x00}, @@ -1356,16 +1397,14 @@ static const struct tvp514x_reg tvp5147_init_reg_seq[] = { {TOK_TERM, 0, 0}, }; -/* - * TVP5146M2/TVP5147M1 Init/Power on Sequence - */ +/* TVP5146M2/TVP5147M1 Init/Power on Sequence */ static const struct tvp514x_reg tvp514xm_init_reg_seq[] = { {TOK_WRITE, REG_OPERATION_MODE, 0x01}, {TOK_WRITE, REG_OPERATION_MODE, 0x00}, {TOK_TERM, 0, 0}, }; -/* +/** * I2C Device Table - * * name - Name of the actual device/chip. -- cgit v1.2.3 From 0ec62142b0a383a2c32114b2c8e44713b88eea8b Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 6 Jul 2009 20:04:12 +0200 Subject: v4l: vpfe capture bridge driver for DM355 and DM6446 From: Muralidharan Karicheri This the vpfe capture bridge driver for doing video capture on DM355 and DM6446 evms. The ccdc hw modules register with the driver and are used for configuring the CCD Controller for a specific decoder interface. The driver also registers the sub devices required for a specific evm. More than one sub devices can be registered. This allows driver to switch dynamically to capture video from any sub device that is registered. Currently only one sub device (tvp5146) is supported. But in future this driver is expected to do capture from sensor devices such as Micron's MT9T001, MT9T031 and MT9P031 etc. The driver currently supports MMAP based IO. Reviewed by: Laurent Pinchart Reviewed by: Alexey Klimov Priority: normal Signed-off-by: Muralidharan Karicheri Signed-off-by: Hans Verkuil --- linux/drivers/media/video/davinci/vpfe_capture.c | 2124 ++++++++++++++++++++++ 1 file changed, 2124 insertions(+) create mode 100644 linux/drivers/media/video/davinci/vpfe_capture.c (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/davinci/vpfe_capture.c b/linux/drivers/media/video/davinci/vpfe_capture.c new file mode 100644 index 000000000..402ce43ef --- /dev/null +++ b/linux/drivers/media/video/davinci/vpfe_capture.c @@ -0,0 +1,2124 @@ +/* + * Copyright (C) 2008-2009 Texas Instruments Inc + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Driver name : VPFE Capture driver + * VPFE Capture driver allows applications to capture and stream video + * frames on DaVinci SoCs (DM6446, DM355 etc) from a YUV source such as + * TVP5146 or Raw Bayer RGB image data from an image sensor + * such as Microns' MT9T001, MT9T031 etc. + * + * These SoCs have, in common, a Video Processing Subsystem (VPSS) that + * consists of a Video Processing Front End (VPFE) for capturing + * video/raw image data and Video Processing Back End (VPBE) for displaying + * YUV data through an in-built analog encoder or Digital LCD port. This + * driver is for capture through VPFE. A typical EVM using these SoCs have + * following high level configuration. + * + * + * decoder(TVP5146/ YUV/ + * MT9T001) --> Raw Bayer RGB ---> MUX -> VPFE (CCDC/ISIF) + * data input | | + * V | + * SDRAM | + * V + * Image Processor + * | + * V + * SDRAM + * The data flow happens from a decoder connected to the VPFE over a + * YUV embedded (BT.656/BT.1120) or separate sync or raw bayer rgb interface + * and to the input of VPFE through an optional MUX (if more inputs are + * to be interfaced on the EVM). The input data is first passed through + * CCDC (CCD Controller, a.k.a Image Sensor Interface, ISIF). The CCDC + * does very little or no processing on YUV data and does pre-process Raw + * Bayer RGB data through modules such as Defect Pixel Correction (DFC) + * Color Space Conversion (CSC), data gain/offset etc. After this, data + * can be written to SDRAM or can be connected to the image processing + * block such as IPIPE (on DM355 only). + * + * Features supported + * - MMAP IO + * - Capture using TVP5146 over BT.656 + * - support for interfacing decoders using sub device model + * - Work with DM355 or DM6446 CCDC to do Raw Bayer RGB/YUV + * data capture to SDRAM. + * TODO list + * - Support multiple REQBUF after open + * - Support for de-allocating buffers through REQBUF + * - Support for Raw Bayer RGB capture + * - Support for chaining Image Processor + * - Support for static allocation of buffers + * - Support for USERPTR IO + * - Support for STREAMON before QBUF + * - Support for control ioctls + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include "ccdc_hw_device.h" + +static int debug; +static u32 numbuffers = 3; +static u32 bufsize = (720 * 576 * 2); + +module_param(numbuffers, uint, S_IRUGO); +module_param(bufsize, uint, S_IRUGO); +module_param(debug, int, 0644); + +MODULE_PARM_DESC(numbuffers, "buffer count (default:3)"); +MODULE_PARM_DESC(bufsize, "buffer size in bytes (default:720 x 576 x 2)"); +MODULE_PARM_DESC(debug, "Debug level 0-1"); + +MODULE_DESCRIPTION("VPFE Video for Linux Capture Driver"); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Texas Instruments"); + +/* standard information */ +struct vpfe_standard { + v4l2_std_id std_id; + unsigned int width; + unsigned int height; + struct v4l2_fract pixelaspect; + /* 0 - progressive, 1 - interlaced */ + int frame_format; +}; + +/* ccdc configuration */ +struct ccdc_config { + /* This make sure vpfe is probed and ready to go */ + int vpfe_probed; + /* name of ccdc device */ + char name[32]; + /* for storing mem maps for CCDC */ + int ccdc_addr_size; + void *__iomem ccdc_addr; +}; + +/* data structures */ +static struct vpfe_config_params config_params = { + .min_numbuffers = 3, + .numbuffers = 3, + .min_bufsize = 720 * 480 * 2, + .device_bufsize = 720 * 576 * 2, +}; + +/* ccdc device registered */ +static struct ccdc_hw_device *ccdc_dev; +/* lock for accessing ccdc information */ +static DEFINE_MUTEX(ccdc_lock); +/* ccdc configuration */ +static struct ccdc_config *ccdc_cfg; + +const struct vpfe_standard vpfe_standards[] = { + {V4L2_STD_525_60, 720, 480, {11, 10}, 1}, + {V4L2_STD_625_50, 720, 576, {54, 59}, 1}, +}; + +/* Used when raw Bayer image from ccdc is directly captured to SDRAM */ +static const struct vpfe_pixel_format vpfe_pix_fmts[] = { + { + .fmtdesc = { + .index = 0, + .type = V4L2_BUF_TYPE_VIDEO_CAPTURE, + .description = "Bayer GrRBGb 8bit A-Law compr.", + .pixelformat = V4L2_PIX_FMT_SBGGR8, + }, + .bpp = 1, + }, + { + .fmtdesc = { + .index = 1, + .type = V4L2_BUF_TYPE_VIDEO_CAPTURE, + .description = "Bayer GrRBGb - 16bit", + .pixelformat = V4L2_PIX_FMT_SBGGR16, + }, + .bpp = 2, + }, + { + .fmtdesc = { + .index = 2, + .type = V4L2_BUF_TYPE_VIDEO_CAPTURE, + .description = "Bayer GrRBGb 8bit DPCM compr.", + .pixelformat = V4L2_PIX_FMT_SGRBG10DPCM8, + }, + .bpp = 1, + }, + { + .fmtdesc = { + .index = 3, + .type = V4L2_BUF_TYPE_VIDEO_CAPTURE, + .description = "YCbCr 4:2:2 Interleaved UYVY", + .pixelformat = V4L2_PIX_FMT_UYVY, + }, + .bpp = 2, + }, + { + .fmtdesc = { + .index = 4, + .type = V4L2_BUF_TYPE_VIDEO_CAPTURE, + .description = "YCbCr 4:2:2 Interleaved YUYV", + .pixelformat = V4L2_PIX_FMT_YUYV, + }, + .bpp = 2, + }, + { + .fmtdesc = { + .index = 5, + .type = V4L2_BUF_TYPE_VIDEO_CAPTURE, + .description = "Y/CbCr 4:2:0 - Semi planar", + .pixelformat = V4L2_PIX_FMT_NV12, + }, + .bpp = 1, + }, +}; + +/* + * vpfe_lookup_pix_format() + * lookup an entry in the vpfe pix format table based on pix_format + */ +static const struct vpfe_pixel_format *vpfe_lookup_pix_format(u32 pix_format) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(vpfe_pix_fmts); i++) { + if (pix_format == vpfe_pix_fmts[i].fmtdesc.pixelformat) + return &vpfe_pix_fmts[i]; + } + return NULL; +} + +/* + * vpfe_register_ccdc_device. CCDC module calls this to + * register with vpfe capture + */ +int vpfe_register_ccdc_device(struct ccdc_hw_device *dev) +{ + int ret = 0; + printk(KERN_NOTICE "vpfe_register_ccdc_device: %s\n", dev->name); + + BUG_ON(!dev->hw_ops.open); + BUG_ON(!dev->hw_ops.enable); + BUG_ON(!dev->hw_ops.set_hw_if_params); + BUG_ON(!dev->hw_ops.configure); + BUG_ON(!dev->hw_ops.set_buftype); + BUG_ON(!dev->hw_ops.get_buftype); + BUG_ON(!dev->hw_ops.enum_pix); + BUG_ON(!dev->hw_ops.set_frame_format); + BUG_ON(!dev->hw_ops.get_frame_format); + BUG_ON(!dev->hw_ops.get_pixel_format); + BUG_ON(!dev->hw_ops.set_pixel_format); + BUG_ON(!dev->hw_ops.set_params); + BUG_ON(!dev->hw_ops.set_image_window); + BUG_ON(!dev->hw_ops.get_image_window); + BUG_ON(!dev->hw_ops.get_line_length); + BUG_ON(!dev->hw_ops.setfbaddr); + BUG_ON(!dev->hw_ops.getfid); + + mutex_lock(&ccdc_lock); + if (NULL == ccdc_cfg) { + /* + * TODO. Will this ever happen? if so, we need to fix it. + * Proabably we need to add the request to a linked list and + * walk through it during vpfe probe + */ + printk(KERN_ERR "vpfe capture not initialized\n"); + ret = -1; + goto unlock; + } + + if (strcmp(dev->name, ccdc_cfg->name)) { + /* ignore this ccdc */ + ret = -1; + goto unlock; + } + + if (ccdc_dev) { + printk(KERN_ERR "ccdc already registered\n"); + ret = -1; + goto unlock; + } + + ccdc_dev = dev; + dev->hw_ops.set_ccdc_base(ccdc_cfg->ccdc_addr, + ccdc_cfg->ccdc_addr_size); +unlock: + mutex_unlock(&ccdc_lock); + return ret; +} +EXPORT_SYMBOL(vpfe_register_ccdc_device); + +/* + * vpfe_unregister_ccdc_device. CCDC module calls this to + * unregister with vpfe capture + */ +void vpfe_unregister_ccdc_device(struct ccdc_hw_device *dev) +{ + if (NULL == dev) { + printk(KERN_ERR "invalid ccdc device ptr\n"); + return; + } + + printk(KERN_NOTICE "vpfe_unregister_ccdc_device, dev->name = %s\n", + dev->name); + + if (strcmp(dev->name, ccdc_cfg->name)) { + /* ignore this ccdc */ + return; + } + + mutex_lock(&ccdc_lock); + ccdc_dev = NULL; + mutex_unlock(&ccdc_lock); + return; +} +EXPORT_SYMBOL(vpfe_unregister_ccdc_device); + +/* + * vpfe_get_ccdc_image_format - Get image parameters based on CCDC settings + */ +static int vpfe_get_ccdc_image_format(struct vpfe_device *vpfe_dev, + struct v4l2_format *f) +{ + struct v4l2_rect image_win; + enum ccdc_buftype buf_type; + enum ccdc_frmfmt frm_fmt; + + memset(f, 0, sizeof(*f)); + f->type = V4L2_BUF_TYPE_VIDEO_OUTPUT; + ccdc_dev->hw_ops.get_image_window(&image_win); + f->fmt.pix.width = image_win.width; + f->fmt.pix.height = image_win.height; + f->fmt.pix.bytesperline = ccdc_dev->hw_ops.get_line_length(); + f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * + f->fmt.pix.height; + buf_type = ccdc_dev->hw_ops.get_buftype(); + f->fmt.pix.pixelformat = ccdc_dev->hw_ops.get_pixel_format(); + frm_fmt = ccdc_dev->hw_ops.get_frame_format(); + if (frm_fmt == CCDC_FRMFMT_PROGRESSIVE) + f->fmt.pix.field = V4L2_FIELD_NONE; + else if (frm_fmt == CCDC_FRMFMT_INTERLACED) { + if (buf_type == CCDC_BUFTYPE_FLD_INTERLEAVED) + f->fmt.pix.field = V4L2_FIELD_INTERLACED; + else if (buf_type == CCDC_BUFTYPE_FLD_SEPARATED) + f->fmt.pix.field = V4L2_FIELD_SEQ_TB; + else { + v4l2_err(&vpfe_dev->v4l2_dev, "Invalid buf_type\n"); + return -EINVAL; + } + } else { + v4l2_err(&vpfe_dev->v4l2_dev, "Invalid frm_fmt\n"); + return -EINVAL; + } + return 0; +} + +/* + * vpfe_config_ccdc_image_format() + * For a pix format, configure ccdc to setup the capture + */ +static int vpfe_config_ccdc_image_format(struct vpfe_device *vpfe_dev) +{ + enum ccdc_frmfmt frm_fmt = CCDC_FRMFMT_INTERLACED; + int ret = 0; + + if (ccdc_dev->hw_ops.set_pixel_format( + vpfe_dev->fmt.fmt.pix.pixelformat) < 0) { + v4l2_err(&vpfe_dev->v4l2_dev, + "couldn't set pix format in ccdc\n"); + return -EINVAL; + } + /* configure the image window */ + ccdc_dev->hw_ops.set_image_window(&vpfe_dev->crop); + + switch (vpfe_dev->fmt.fmt.pix.field) { + case V4L2_FIELD_INTERLACED: + /* do nothing, since it is default */ + ret = ccdc_dev->hw_ops.set_buftype( + CCDC_BUFTYPE_FLD_INTERLEAVED); + break; + case V4L2_FIELD_NONE: + frm_fmt = CCDC_FRMFMT_PROGRESSIVE; + /* buffer type only applicable for interlaced scan */ + break; + case V4L2_FIELD_SEQ_TB: + ret = ccdc_dev->hw_ops.set_buftype( + CCDC_BUFTYPE_FLD_SEPARATED); + break; + default: + return -EINVAL; + } + + /* set the frame format */ + if (!ret) + ret = ccdc_dev->hw_ops.set_frame_format(frm_fmt); + return ret; +} +/* + * vpfe_config_image_format() + * For a given standard, this functions sets up the default + * pix format & crop values in the vpfe device and ccdc. It first + * starts with defaults based values from the standard table. + * It then checks if sub device support g_fmt and then override the + * values based on that.Sets crop values to match with scan resolution + * starting at 0,0. It calls vpfe_config_ccdc_image_format() set the + * values in ccdc + */ +static int vpfe_config_image_format(struct vpfe_device *vpfe_dev, + const v4l2_std_id *std_id) +{ + struct vpfe_subdev_info *sdinfo = vpfe_dev->current_subdev; + int i, ret = 0; + + for (i = 0; i < ARRAY_SIZE(vpfe_standards); i++) { + if (vpfe_standards[i].std_id & *std_id) { + vpfe_dev->std_info.active_pixels = + vpfe_standards[i].width; + vpfe_dev->std_info.active_lines = + vpfe_standards[i].height; + vpfe_dev->std_info.frame_format = + vpfe_standards[i].frame_format; + vpfe_dev->std_index = i; + break; + } + } + + if (i == ARRAY_SIZE(vpfe_standards)) { + v4l2_err(&vpfe_dev->v4l2_dev, "standard not supported\n"); + return -EINVAL; + } + + vpfe_dev->crop.top = 0; + vpfe_dev->crop.left = 0; + vpfe_dev->crop.width = vpfe_dev->std_info.active_pixels; + vpfe_dev->crop.height = vpfe_dev->std_info.active_lines; + vpfe_dev->fmt.fmt.pix.width = vpfe_dev->crop.width; + vpfe_dev->fmt.fmt.pix.height = vpfe_dev->crop.height; + + /* first field and frame format based on standard frame format */ + if (vpfe_dev->std_info.frame_format) { + vpfe_dev->fmt.fmt.pix.field = V4L2_FIELD_INTERLACED; + /* assume V4L2_PIX_FMT_UYVY as default */ + vpfe_dev->fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_UYVY; + } else { + vpfe_dev->fmt.fmt.pix.field = V4L2_FIELD_NONE; + /* assume V4L2_PIX_FMT_SBGGR8 */ + vpfe_dev->fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_SBGGR8; + } + + /* if sub device supports g_fmt, override the defaults */ + ret = v4l2_device_call_until_err(&vpfe_dev->v4l2_dev, + sdinfo->grp_id, video, g_fmt, &vpfe_dev->fmt); + + if (ret && ret != -ENOIOCTLCMD) { + v4l2_err(&vpfe_dev->v4l2_dev, + "error in getting g_fmt from sub device\n"); + return ret; + } + + /* Sets the values in CCDC */ + ret = vpfe_config_ccdc_image_format(vpfe_dev); + if (ret) + return ret; + + /* Update the values of sizeimage and bytesperline */ + if (!ret) { + vpfe_dev->fmt.fmt.pix.bytesperline = + ccdc_dev->hw_ops.get_line_length(); + vpfe_dev->fmt.fmt.pix.sizeimage = + vpfe_dev->fmt.fmt.pix.bytesperline * + vpfe_dev->fmt.fmt.pix.height; + } + return ret; +} + +static int vpfe_initialize_device(struct vpfe_device *vpfe_dev) +{ + int ret = 0; + + /* set first input of current subdevice as the current input */ + vpfe_dev->current_input = 0; + + /* set default standard */ + vpfe_dev->std_index = 0; + + /* Configure the default format information */ + ret = vpfe_config_image_format(vpfe_dev, + &vpfe_standards[vpfe_dev->std_index].std_id); + if (ret) + return ret; + + /* now open the ccdc device to initialize it */ + mutex_lock(&ccdc_lock); + if (NULL == ccdc_dev) { + v4l2_err(&vpfe_dev->v4l2_dev, "ccdc device not registered\n"); + ret = -ENODEV; + goto unlock; + } + + if (!try_module_get(ccdc_dev->owner)) { + v4l2_err(&vpfe_dev->v4l2_dev, "Couldn't lock ccdc module\n"); + ret = -ENODEV; + goto unlock; + } + ret = ccdc_dev->hw_ops.open(vpfe_dev->pdev); + if (!ret) + vpfe_dev->initialized = 1; +unlock: + mutex_unlock(&ccdc_lock); + return ret; +} + +/* + * vpfe_open : It creates object of file handle structure and + * stores it in private_data member of filepointer + */ +static int vpfe_open(struct file *file) +{ + struct vpfe_device *vpfe_dev = video_drvdata(file); + struct vpfe_fh *fh; + + v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_open\n"); + + if (!vpfe_dev->cfg->num_subdevs) { + v4l2_err(&vpfe_dev->v4l2_dev, "No decoder registered\n"); + return -ENODEV; + } + + /* Allocate memory for the file handle object */ + fh = kmalloc(sizeof(struct vpfe_fh), GFP_KERNEL); + if (NULL == fh) { + v4l2_err(&vpfe_dev->v4l2_dev, + "unable to allocate memory for file handle object\n"); + return -ENOMEM; + } + /* store pointer to fh in private_data member of file */ + file->private_data = fh; + fh->vpfe_dev = vpfe_dev; + mutex_lock(&vpfe_dev->lock); + /* If decoder is not initialized. initialize it */ + if (!vpfe_dev->initialized) { + if (vpfe_initialize_device(vpfe_dev)) { + mutex_unlock(&vpfe_dev->lock); + return -ENODEV; + } + } + /* Increment device usrs counter */ + vpfe_dev->usrs++; + /* Set io_allowed member to false */ + fh->io_allowed = 0; + /* Initialize priority of this instance to default priority */ + fh->prio = V4L2_PRIORITY_UNSET; + v4l2_prio_open(&vpfe_dev->prio, &fh->prio); + mutex_unlock(&vpfe_dev->lock); + return 0; +} + +static void vpfe_schedule_next_buffer(struct vpfe_device *vpfe_dev) +{ + unsigned long addr; + + vpfe_dev->next_frm = list_entry(vpfe_dev->dma_queue.next, + struct videobuf_buffer, queue); + list_del(&vpfe_dev->next_frm->queue); + vpfe_dev->next_frm->state = VIDEOBUF_ACTIVE; + addr = videobuf_to_dma_contig(vpfe_dev->next_frm); + ccdc_dev->hw_ops.setfbaddr(addr); +} + +static void vpfe_process_buffer_complete(struct vpfe_device *vpfe_dev) +{ + struct timeval timevalue; + + do_gettimeofday(&timevalue); + vpfe_dev->cur_frm->ts = timevalue; + vpfe_dev->cur_frm->state = VIDEOBUF_DONE; + vpfe_dev->cur_frm->size = vpfe_dev->fmt.fmt.pix.sizeimage; + wake_up_interruptible(&vpfe_dev->cur_frm->done); + vpfe_dev->cur_frm = vpfe_dev->next_frm; +} + +/* ISR for VINT0*/ +static irqreturn_t vpfe_isr(int irq, void *dev_id) +{ + struct vpfe_device *vpfe_dev = dev_id; + enum v4l2_field field; + unsigned long addr; + int fid; + + v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "\nStarting vpfe_isr...\n"); + field = vpfe_dev->fmt.fmt.pix.field; + + /* if streaming not started, don't do anything */ + if (!vpfe_dev->started) + return IRQ_HANDLED; + + /* only for 6446 this will be applicable */ + if (NULL != ccdc_dev->hw_ops.reset) + ccdc_dev->hw_ops.reset(); + + if (field == V4L2_FIELD_NONE) { + /* handle progressive frame capture */ + v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, + "frame format is progressive...\n"); + if (vpfe_dev->cur_frm != vpfe_dev->next_frm) + vpfe_process_buffer_complete(vpfe_dev); + return IRQ_HANDLED; + } + + /* interlaced or TB capture check which field we are in hardware */ + fid = ccdc_dev->hw_ops.getfid(); + + /* switch the software maintained field id */ + vpfe_dev->field_id ^= 1; + v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "field id = %x:%x.\n", + fid, vpfe_dev->field_id); + if (fid == vpfe_dev->field_id) { + /* we are in-sync here,continue */ + if (fid == 0) { + /* + * One frame is just being captured. If the next frame + * is available, release the current frame and move on + */ + if (vpfe_dev->cur_frm != vpfe_dev->next_frm) + vpfe_process_buffer_complete(vpfe_dev); + /* + * based on whether the two fields are stored + * interleavely or separately in memory, reconfigure + * the CCDC memory address + */ + if (field == V4L2_FIELD_SEQ_TB) { + addr = + videobuf_to_dma_contig(vpfe_dev->cur_frm); + addr += vpfe_dev->field_off; + ccdc_dev->hw_ops.setfbaddr(addr); + } + return IRQ_HANDLED; + } + /* + * if one field is just being captured configure + * the next frame get the next frame from the empty + * queue if no frame is available hold on to the + * current buffer + */ + spin_lock(&vpfe_dev->dma_queue_lock); + if (!list_empty(&vpfe_dev->dma_queue) && + vpfe_dev->cur_frm == vpfe_dev->next_frm) + vpfe_schedule_next_buffer(vpfe_dev); + spin_unlock(&vpfe_dev->dma_queue_lock); + } else if (fid == 0) { + /* + * out of sync. Recover from any hardware out-of-sync. + * May loose one frame + */ + vpfe_dev->field_id = fid; + } + return IRQ_HANDLED; +} + +/* vdint1_isr - isr handler for VINT1 interrupt */ +static irqreturn_t vdint1_isr(int irq, void *dev_id) +{ + struct vpfe_device *vpfe_dev = dev_id; + + v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "\nInside vdint1_isr...\n"); + + /* if streaming not started, don't do anything */ + if (!vpfe_dev->started) + return IRQ_HANDLED; + + spin_lock(&vpfe_dev->dma_queue_lock); + if ((vpfe_dev->fmt.fmt.pix.field == V4L2_FIELD_NONE) && + !list_empty(&vpfe_dev->dma_queue) && + vpfe_dev->cur_frm == vpfe_dev->next_frm) + vpfe_schedule_next_buffer(vpfe_dev); + spin_unlock(&vpfe_dev->dma_queue_lock); + return IRQ_HANDLED; +} + +static void vpfe_detach_irq(struct vpfe_device *vpfe_dev) +{ + enum ccdc_frmfmt frame_format; + + frame_format = ccdc_dev->hw_ops.get_frame_format(); + if (frame_format == CCDC_FRMFMT_PROGRESSIVE) + free_irq(IRQ_VDINT1, vpfe_dev); +} + +static int vpfe_attach_irq(struct vpfe_device *vpfe_dev) +{ + enum ccdc_frmfmt frame_format; + + frame_format = ccdc_dev->hw_ops.get_frame_format(); + if (frame_format == CCDC_FRMFMT_PROGRESSIVE) { + return request_irq(vpfe_dev->ccdc_irq1, vdint1_isr, + IRQF_DISABLED, "vpfe_capture1", + vpfe_dev); + } + return 0; +} + +/* vpfe_stop_ccdc_capture: stop streaming in ccdc/isif */ +static void vpfe_stop_ccdc_capture(struct vpfe_device *vpfe_dev) +{ + vpfe_dev->started = 0; + ccdc_dev->hw_ops.enable(0); + if (ccdc_dev->hw_ops.enable_out_to_sdram) + ccdc_dev->hw_ops.enable_out_to_sdram(0); +} + +/* + * vpfe_release : This function deletes buffer queue, frees the + * buffers and the vpfe file handle + */ +static int vpfe_release(struct file *file) +{ + struct vpfe_device *vpfe_dev = video_drvdata(file); + struct vpfe_fh *fh = file->private_data; + struct vpfe_subdev_info *sdinfo; + int ret; + + v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_release\n"); + + /* Get the device lock */ + mutex_lock(&vpfe_dev->lock); + /* if this instance is doing IO */ + if (fh->io_allowed) { + if (vpfe_dev->started) { + sdinfo = vpfe_dev->current_subdev; + ret = v4l2_device_call_until_err(&vpfe_dev->v4l2_dev, + sdinfo->grp_id, + video, s_stream, 0); + if (ret && (ret != -ENOIOCTLCMD)) + v4l2_err(&vpfe_dev->v4l2_dev, + "stream off failed in subdev\n"); + vpfe_stop_ccdc_capture(vpfe_dev); + vpfe_detach_irq(vpfe_dev); + videobuf_streamoff(&vpfe_dev->buffer_queue); + } + vpfe_dev->io_usrs = 0; + vpfe_dev->numbuffers = config_params.numbuffers; + } + + /* Decrement device usrs counter */ + vpfe_dev->usrs--; + /* Close the priority */ + v4l2_prio_close(&vpfe_dev->prio, &fh->prio); + /* If this is the last file handle */ + if (!vpfe_dev->usrs) { + vpfe_dev->initialized = 0; + if (ccdc_dev->hw_ops.close) + ccdc_dev->hw_ops.close(vpfe_dev->pdev); + module_put(ccdc_dev->owner); + } + mutex_unlock(&vpfe_dev->lock); + file->private_data = NULL; + /* Free memory allocated to file handle object */ + kfree(fh); + return 0; +} + +/* + * vpfe_mmap : It is used to map kernel space buffers + * into user spaces + */ +static int vpfe_mmap(struct file *file, struct vm_area_struct *vma) +{ + /* Get the device object and file handle object */ + struct vpfe_device *vpfe_dev = video_drvdata(file); + + v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_mmap\n"); + + return videobuf_mmap_mapper(&vpfe_dev->buffer_queue, vma); +} + +/* + * vpfe_poll: It is used for select/poll system call + */ +static unsigned int vpfe_poll(struct file *file, poll_table *wait) +{ + struct vpfe_device *vpfe_dev = video_drvdata(file); + + v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_poll\n"); + + if (vpfe_dev->started) + return videobuf_poll_stream(file, + &vpfe_dev->buffer_queue, wait); + return 0; +} + +/* vpfe capture driver file operations */ +static const struct v4l2_file_operations vpfe_fops = { + .owner = THIS_MODULE, + .open = vpfe_open, + .release = vpfe_release, + .unlocked_ioctl = video_ioctl2, + .mmap = vpfe_mmap, + .poll = vpfe_poll +}; + +/* + * vpfe_check_format() + * This function adjust the input pixel format as per hardware + * capabilities and update the same in pixfmt. + * Following algorithm used :- + * + * If given pixformat is not in the vpfe list of pix formats or not + * supported by the hardware, current value of pixformat in the device + * is used + * If given field is not supported, then current field is used. If field + * is different from current, then it is matched with that from sub device. + * Minimum height is 2 lines for interlaced or tb field and 1 line for + * progressive. Maximum height is clamped to active active lines of scan + * Minimum width is 32 bytes in memory and width is clamped to active + * pixels of scan. + * bytesperline is a multiple of 32. + */ +static const struct vpfe_pixel_format * + vpfe_check_format(struct vpfe_device *vpfe_dev, + struct v4l2_pix_format *pixfmt) +{ + u32 min_height = 1, min_width = 32, max_width, max_height; + const struct vpfe_pixel_format *vpfe_pix_fmt; + u32 pix; + int temp, found; + + vpfe_pix_fmt = vpfe_lookup_pix_format(pixfmt->pixelformat); + if (NULL == vpfe_pix_fmt) { + /* + * use current pixel format in the vpfe device. We + * will find this pix format in the table + */ + pixfmt->pixelformat = vpfe_dev->fmt.fmt.pix.pixelformat; + vpfe_pix_fmt = vpfe_lookup_pix_format(pixfmt->pixelformat); + } + + /* check if hw supports it */ + temp = 0; + found = 0; + while (ccdc_dev->hw_ops.enum_pix(&pix, temp) >= 0) { + if (vpfe_pix_fmt->fmtdesc.pixelformat == pix) { + found = 1; + break; + } + temp++; + } + + if (!found) { + /* use current pixel format */ + pixfmt->pixelformat = vpfe_dev->fmt.fmt.pix.pixelformat; + /* + * Since this is currently used in the vpfe device, we + * will find this pix format in the table + */ + vpfe_pix_fmt = vpfe_lookup_pix_format(pixfmt->pixelformat); + } + + /* check what field format is supported */ + if (pixfmt->field == V4L2_FIELD_ANY) { + /* if field is any, use current value as default */ + pixfmt->field = vpfe_dev->fmt.fmt.pix.field; + } + + /* + * if field is not same as current field in the vpfe device + * try matching the field with the sub device field + */ + if (vpfe_dev->fmt.fmt.pix.field != pixfmt->field) { + /* + * If field value is not in the supported fields, use current + * field used in the device as default + */ + switch (pixfmt->field) { + case V4L2_FIELD_INTERLACED: + case V4L2_FIELD_SEQ_TB: + /* if sub device is supporting progressive, use that */ + if (!vpfe_dev->std_info.frame_format) + pixfmt->field = V4L2_FIELD_NONE; + break; + case V4L2_FIELD_NONE: + if (vpfe_dev->std_info.frame_format) + pixfmt->field = V4L2_FIELD_INTERLACED; + break; + + default: + /* use current field as default */ + pixfmt->field = vpfe_dev->fmt.fmt.pix.field; + break; + } + } + + /* Now adjust image resolutions supported */ + if (pixfmt->field == V4L2_FIELD_INTERLACED || + pixfmt->field == V4L2_FIELD_SEQ_TB) + min_height = 2; + + max_width = vpfe_dev->std_info.active_pixels; + max_height = vpfe_dev->std_info.active_lines; + min_width /= vpfe_pix_fmt->bpp; + + v4l2_info(&vpfe_dev->v4l2_dev, "width = %d, height = %d, bpp = %d\n", + pixfmt->width, pixfmt->height, vpfe_pix_fmt->bpp); + + pixfmt->width = clamp((pixfmt->width), min_width, max_width); + pixfmt->height = clamp((pixfmt->height), min_height, max_height); + + /* If interlaced, adjust height to be a multiple of 2 */ + if (pixfmt->field == V4L2_FIELD_INTERLACED) + pixfmt->height &= (~1); + /* + * recalculate bytesperline and sizeimage since width + * and height might have changed + */ + pixfmt->bytesperline = (((pixfmt->width * vpfe_pix_fmt->bpp) + 31) + & ~31); + if (pixfmt->pixelformat == V4L2_PIX_FMT_NV12) + pixfmt->sizeimage = + pixfmt->bytesperline * pixfmt->height + + ((pixfmt->bytesperline * pixfmt->height) >> 1); + else + pixfmt->sizeimage = pixfmt->bytesperline * pixfmt->height; + + v4l2_info(&vpfe_dev->v4l2_dev, "adjusted width = %d, height =" + " %d, bpp = %d, bytesperline = %d, sizeimage = %d\n", + pixfmt->width, pixfmt->height, vpfe_pix_fmt->bpp, + pixfmt->bytesperline, pixfmt->sizeimage); + return vpfe_pix_fmt; +} + +static int vpfe_querycap(struct file *file, void *priv, + struct v4l2_capability *cap) +{ + struct vpfe_device *vpfe_dev = video_drvdata(file); + + v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_querycap\n"); + + cap->version = VPFE_CAPTURE_VERSION_CODE; + cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING; + strlcpy(cap->driver, CAPTURE_DRV_NAME, sizeof(cap->driver)); + strlcpy(cap->bus_info, "VPFE", sizeof(cap->bus_info)); + strlcpy(cap->card, vpfe_dev->cfg->card_name, sizeof(cap->card)); + return 0; +} + +static int vpfe_g_fmt_vid_cap(struct file *file, void *priv, + struct v4l2_format *fmt) +{ + struct vpfe_device *vpfe_dev = video_drvdata(file); + int ret = 0; + + v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_g_fmt_vid_cap\n"); + /* Fill in the information about format */ + *fmt = vpfe_dev->fmt; + return ret; +} + +static int vpfe_enum_fmt_vid_cap(struct file *file, void *priv, + struct v4l2_fmtdesc *fmt) +{ + struct vpfe_device *vpfe_dev = video_drvdata(file); + const struct vpfe_pixel_format *pix_fmt; + int temp_index; + u32 pix; + + v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_enum_fmt_vid_cap\n"); + + if (ccdc_dev->hw_ops.enum_pix(&pix, fmt->index) < 0) + return -EINVAL; + + /* Fill in the information about format */ + pix_fmt = vpfe_lookup_pix_format(pix); + if (NULL != pix_fmt) { + temp_index = fmt->index; + *fmt = pix_fmt->fmtdesc; + fmt->index = temp_index; + return 0; + } + return -EINVAL; +} + +static int vpfe_s_fmt_vid_cap(struct file *file, void *priv, + struct v4l2_format *fmt) +{ + struct vpfe_device *vpfe_dev = video_drvdata(file); + const struct vpfe_pixel_format *pix_fmts; + int ret = 0; + + v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_s_fmt_vid_cap\n"); + + /* If streaming is started, return error */ + if (vpfe_dev->started) { + v4l2_err(&vpfe_dev->v4l2_dev, "Streaming is started\n"); + return -EBUSY; + } + + /* Check for valid frame format */ + pix_fmts = vpfe_check_format(vpfe_dev, &fmt->fmt.pix); + + if (NULL == pix_fmts) + return -EINVAL; + + /* store the pixel format in the device object */ + ret = mutex_lock_interruptible(&vpfe_dev->lock); + if (ret) + return ret; + + /* First detach any IRQ if currently attached */ + vpfe_detach_irq(vpfe_dev); + vpfe_dev->fmt = *fmt; + /* set image capture parameters in the ccdc */ + ret = vpfe_config_ccdc_image_format(vpfe_dev); + mutex_unlock(&vpfe_dev->lock); + return ret; +} + +static int vpfe_try_fmt_vid_cap(struct file *file, void *priv, + struct v4l2_format *f) +{ + struct vpfe_device *vpfe_dev = video_drvdata(file); + const struct vpfe_pixel_format *pix_fmts; + + v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_try_fmt_vid_cap\n"); + + pix_fmts = vpfe_check_format(vpfe_dev, &f->fmt.pix); + if (NULL == pix_fmts) + return -EINVAL; + return 0; +} + +/* + * vpfe_get_subdev_input_index - Get subdev index and subdev input index for a + * given app input index + */ +static int vpfe_get_subdev_input_index(struct vpfe_device *vpfe_dev, + int *subdev_index, + int *subdev_input_index, + int app_input_index) +{ + struct vpfe_config *cfg = vpfe_dev->cfg; + struct vpfe_subdev_info *sdinfo; + int i, j = 0; + + for (i = 0; i < cfg->num_subdevs; i++) { + sdinfo = &cfg->sub_devs[i]; + if (app_input_index < (j + sdinfo->num_inputs)) { + *subdev_index = i; + *subdev_input_index = app_input_index - j; + return 0; + } + j += sdinfo->num_inputs; + } + return -EINVAL; +} + +/* + * vpfe_get_app_input - Get app input index for a given subdev input index + * driver stores the input index of the current sub device and translate it + * when application request the current input + */ +static int vpfe_get_app_input_index(struct vpfe_device *vpfe_dev, + int *app_input_index) +{ + struct vpfe_config *cfg = vpfe_dev->cfg; + struct vpfe_subdev_info *sdinfo; + int i, j = 0; + + for (i = 0; i < cfg->num_subdevs; i++) { + sdinfo = &cfg->sub_devs[i]; + if (!strcmp(sdinfo->name, vpfe_dev->current_subdev->name)) { + if (vpfe_dev->current_input >= sdinfo->num_inputs) + return -1; + *app_input_index = j + vpfe_dev->current_input; + return 0; + } + j += sdinfo->num_inputs; + } + return -EINVAL; +} + +static int vpfe_enum_input(struct file *file, void *priv, + struct v4l2_input *inp) +{ + struct vpfe_device *vpfe_dev = video_drvdata(file); + struct vpfe_subdev_info *sdinfo; + int subdev, index ; + + v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_enum_input\n"); + + if (vpfe_get_subdev_input_index(vpfe_dev, + &subdev, + &index, + inp->index) < 0) { + v4l2_err(&vpfe_dev->v4l2_dev, "input information not found" + " for the subdev\n"); + return -EINVAL; + } + sdinfo = &vpfe_dev->cfg->sub_devs[subdev]; + memcpy(inp, &sdinfo->inputs[index], sizeof(struct v4l2_input)); + return 0; +} + +static int vpfe_g_input(struct file *file, void *priv, unsigned int *index) +{ + struct vpfe_device *vpfe_dev = video_drvdata(file); + + v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_g_input\n"); + + return vpfe_get_app_input_index(vpfe_dev, index); +} + + +static int vpfe_s_input(struct file *file, void *priv, unsigned int index) +{ + struct vpfe_device *vpfe_dev = video_drvdata(file); + struct vpfe_subdev_info *sdinfo; + int subdev_index, inp_index; + struct vpfe_route *route; + u32 input = 0, output = 0; + int ret = -EINVAL; + + v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_s_input\n"); + + ret = mutex_lock_interruptible(&vpfe_dev->lock); + if (ret) + return ret; + + /* + * If streaming is started return device busy + * error + */ + if (vpfe_dev->started) { + v4l2_err(&vpfe_dev->v4l2_dev, "Streaming is on\n"); + ret = -EBUSY; + goto unlock_out; + } + + if (vpfe_get_subdev_input_index(vpfe_dev, + &subdev_index, + &inp_index, + index) < 0) { + v4l2_err(&vpfe_dev->v4l2_dev, "invalid input index\n"); + goto unlock_out; + } + + sdinfo = &vpfe_dev->cfg->sub_devs[subdev_index]; + route = &sdinfo->routes[inp_index]; + if (route && sdinfo->can_route) { + input = route->input; + output = route->output; + } + + ret = v4l2_device_call_until_err(&vpfe_dev->v4l2_dev, sdinfo->grp_id, + video, s_routing, input, output, 0); + + if (ret) { + v4l2_err(&vpfe_dev->v4l2_dev, + "vpfe_doioctl:error in setting input in decoder\n"); + ret = -EINVAL; + goto unlock_out; + } + vpfe_dev->current_subdev = sdinfo; + vpfe_dev->current_input = index; + vpfe_dev->std_index = 0; + + /* set the bus/interface parameter for the sub device in ccdc */ + ret = ccdc_dev->hw_ops.set_hw_if_params(&sdinfo->ccdc_if_params); + if (ret) + goto unlock_out; + + /* set the default image parameters in the device */ + ret = vpfe_config_image_format(vpfe_dev, + &vpfe_standards[vpfe_dev->std_index].std_id); +unlock_out: + mutex_unlock(&vpfe_dev->lock); + return ret; +} + +static int vpfe_querystd(struct file *file, void *priv, v4l2_std_id *std_id) +{ + struct vpfe_device *vpfe_dev = video_drvdata(file); + struct vpfe_subdev_info *sdinfo; + int ret = 0; + + v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_querystd\n"); + + ret = mutex_lock_interruptible(&vpfe_dev->lock); + sdinfo = vpfe_dev->current_subdev; + if (ret) + return ret; + /* Call querystd function of decoder device */ + ret = v4l2_device_call_until_err(&vpfe_dev->v4l2_dev, sdinfo->grp_id, + video, querystd, std_id); + mutex_unlock(&vpfe_dev->lock); + return ret; +} + +static int vpfe_s_std(struct file *file, void *priv, v4l2_std_id *std_id) +{ + struct vpfe_device *vpfe_dev = video_drvdata(file); + struct vpfe_subdev_info *sdinfo; + int ret = 0; + + v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_s_std\n"); + + /* Call decoder driver function to set the standard */ + ret = mutex_lock_interruptible(&vpfe_dev->lock); + if (ret) + return ret; + + sdinfo = vpfe_dev->current_subdev; + /* If streaming is started, return device busy error */ + if (vpfe_dev->started) { + v4l2_err(&vpfe_dev->v4l2_dev, "streaming is started\n"); + ret = -EBUSY; + goto unlock_out; + } + + ret = v4l2_device_call_until_err(&vpfe_dev->v4l2_dev, sdinfo->grp_id, + core, s_std, *std_id); + if (ret < 0) { + v4l2_err(&vpfe_dev->v4l2_dev, "Failed to set standard\n"); + goto unlock_out; + } + ret = vpfe_config_image_format(vpfe_dev, std_id); + +unlock_out: + mutex_unlock(&vpfe_dev->lock); + return ret; +} + +static int vpfe_g_std(struct file *file, void *priv, v4l2_std_id *std_id) +{ + struct vpfe_device *vpfe_dev = video_drvdata(file); + + v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_g_std\n"); + + *std_id = vpfe_standards[vpfe_dev->std_index].std_id; + return 0; +} +/* + * Videobuf operations + */ +static int vpfe_videobuf_setup(struct videobuf_queue *vq, + unsigned int *count, + unsigned int *size) +{ + struct vpfe_fh *fh = vq->priv_data; + struct vpfe_device *vpfe_dev = fh->vpfe_dev; + + v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_buffer_setup\n"); + *size = config_params.device_bufsize; + + if (*count < config_params.min_numbuffers) + *count = config_params.min_numbuffers; + v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, + "count=%d, size=%d\n", *count, *size); + return 0; +} + +static int vpfe_videobuf_prepare(struct videobuf_queue *vq, + struct videobuf_buffer *vb, + enum v4l2_field field) +{ + struct vpfe_fh *fh = vq->priv_data; + struct vpfe_device *vpfe_dev = fh->vpfe_dev; + + v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_buffer_prepare\n"); + + /* If buffer is not initialized, initialize it */ + if (VIDEOBUF_NEEDS_INIT == vb->state) { + vb->width = vpfe_dev->fmt.fmt.pix.width; + vb->height = vpfe_dev->fmt.fmt.pix.height; + vb->size = vpfe_dev->fmt.fmt.pix.sizeimage; + vb->field = field; + } + vb->state = VIDEOBUF_PREPARED; + return 0; +} + +static void vpfe_videobuf_queue(struct videobuf_queue *vq, + struct videobuf_buffer *vb) +{ + /* Get the file handle object and device object */ + struct vpfe_fh *fh = vq->priv_data; + struct vpfe_device *vpfe_dev = fh->vpfe_dev; + unsigned long flags; + + v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_buffer_queue\n"); + + /* add the buffer to the DMA queue */ + spin_lock_irqsave(&vpfe_dev->dma_queue_lock, flags); + list_add_tail(&vb->queue, &vpfe_dev->dma_queue); + spin_unlock_irqrestore(&vpfe_dev->dma_queue_lock, flags); + + /* Change state of the buffer */ + vb->state = VIDEOBUF_QUEUED; +} + +static void vpfe_videobuf_release(struct videobuf_queue *vq, + struct videobuf_buffer *vb) +{ + struct vpfe_fh *fh = vq->priv_data; + struct vpfe_device *vpfe_dev = fh->vpfe_dev; + unsigned long flags; + + v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_videobuf_release\n"); + + /* + * We need to flush the buffer from the dma queue since + * they are de-allocated + */ + spin_lock_irqsave(&vpfe_dev->dma_queue_lock, flags); + INIT_LIST_HEAD(&vpfe_dev->dma_queue); + spin_unlock_irqrestore(&vpfe_dev->dma_queue_lock, flags); + videobuf_dma_contig_free(vq, vb); + vb->state = VIDEOBUF_NEEDS_INIT; +} + +static struct videobuf_queue_ops vpfe_videobuf_qops = { + .buf_setup = vpfe_videobuf_setup, + .buf_prepare = vpfe_videobuf_prepare, + .buf_queue = vpfe_videobuf_queue, + .buf_release = vpfe_videobuf_release, +}; + +/* + * vpfe_reqbufs. currently support REQBUF only once opening + * the device. + */ +static int vpfe_reqbufs(struct file *file, void *priv, + struct v4l2_requestbuffers *req_buf) +{ + struct vpfe_device *vpfe_dev = video_drvdata(file); + struct vpfe_fh *fh = file->private_data; + int ret = 0; + + v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_reqbufs\n"); + + if (V4L2_BUF_TYPE_VIDEO_CAPTURE != req_buf->type) { + v4l2_err(&vpfe_dev->v4l2_dev, "Invalid buffer type\n"); + return -EINVAL; + } + + if (V4L2_MEMORY_USERPTR == req_buf->memory) { + /* we don't support user ptr IO */ + v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_reqbufs:" + " USERPTR IO not supported\n"); + return -EINVAL; + } + + ret = mutex_lock_interruptible(&vpfe_dev->lock); + if (ret) + return ret; + + if (vpfe_dev->io_usrs != 0) { + v4l2_err(&vpfe_dev->v4l2_dev, "Only one IO user allowed\n"); + ret = -EBUSY; + goto unlock_out; + } + + vpfe_dev->memory = req_buf->memory; + videobuf_queue_dma_contig_init(&vpfe_dev->buffer_queue, + &vpfe_videobuf_qops, + NULL, + &vpfe_dev->irqlock, + req_buf->type, + vpfe_dev->fmt.fmt.pix.field, + sizeof(struct videobuf_buffer), + fh); + + fh->io_allowed = 1; + vpfe_dev->io_usrs = 1; + INIT_LIST_HEAD(&vpfe_dev->dma_queue); + ret = videobuf_reqbufs(&vpfe_dev->buffer_queue, req_buf); +unlock_out: + mutex_unlock(&vpfe_dev->lock); + return ret; +} + +static int vpfe_querybuf(struct file *file, void *priv, + struct v4l2_buffer *buf) +{ + struct vpfe_device *vpfe_dev = video_drvdata(file); + + v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_querybuf\n"); + + if (V4L2_BUF_TYPE_VIDEO_CAPTURE != buf->type) { + v4l2_err(&vpfe_dev->v4l2_dev, "Invalid buf type\n"); + return -EINVAL; + } + + if (vpfe_dev->memory != V4L2_MEMORY_MMAP) { + v4l2_err(&vpfe_dev->v4l2_dev, "Invalid memory\n"); + return -EINVAL; + } + /* Call videobuf_querybuf to get information */ + return videobuf_querybuf(&vpfe_dev->buffer_queue, buf); +} + +static int vpfe_qbuf(struct file *file, void *priv, + struct v4l2_buffer *p) +{ + struct vpfe_device *vpfe_dev = video_drvdata(file); + struct vpfe_fh *fh = file->private_data; + + v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_qbuf\n"); + + if (V4L2_BUF_TYPE_VIDEO_CAPTURE != p->type) { + v4l2_err(&vpfe_dev->v4l2_dev, "Invalid buf type\n"); + return -EINVAL; + } + + /* + * If this file handle is not allowed to do IO, + * return error + */ + if (!fh->io_allowed) { + v4l2_err(&vpfe_dev->v4l2_dev, "fh->io_allowed\n"); + return -EACCES; + } + return videobuf_qbuf(&vpfe_dev->buffer_queue, p); +} + +static int vpfe_dqbuf(struct file *file, void *priv, + struct v4l2_buffer *buf) +{ + struct vpfe_device *vpfe_dev = video_drvdata(file); + + v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_dqbuf\n"); + + if (V4L2_BUF_TYPE_VIDEO_CAPTURE != buf->type) { + v4l2_err(&vpfe_dev->v4l2_dev, "Invalid buf type\n"); + return -EINVAL; + } + return videobuf_dqbuf(&vpfe_dev->buffer_queue, + buf, file->f_flags & O_NONBLOCK); +} + +/* + * vpfe_calculate_offsets : This function calculates buffers offset + * for top and bottom field + */ +static void vpfe_calculate_offsets(struct vpfe_device *vpfe_dev) +{ + struct v4l2_rect image_win; + + v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_calculate_offsets\n"); + + ccdc_dev->hw_ops.get_image_window(&image_win); + vpfe_dev->field_off = image_win.height * image_win.width; +} + +/* vpfe_start_ccdc_capture: start streaming in ccdc/isif */ +static void vpfe_start_ccdc_capture(struct vpfe_device *vpfe_dev) +{ + ccdc_dev->hw_ops.enable(1); + if (ccdc_dev->hw_ops.enable_out_to_sdram) + ccdc_dev->hw_ops.enable_out_to_sdram(1); + vpfe_dev->started = 1; +} + +/* + * vpfe_streamon. Assume the DMA queue is not empty. + * application is expected to call QBUF before calling + * this ioctl. If not, driver returns error + */ +static int vpfe_streamon(struct file *file, void *priv, + enum v4l2_buf_type buf_type) +{ + struct vpfe_device *vpfe_dev = video_drvdata(file); + struct vpfe_fh *fh = file->private_data; + struct vpfe_subdev_info *sdinfo; + unsigned long addr; + int ret = 0; + + v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_streamon\n"); + + if (V4L2_BUF_TYPE_VIDEO_CAPTURE != buf_type) { + v4l2_err(&vpfe_dev->v4l2_dev, "Invalid buf type\n"); + return -EINVAL; + } + + /* If file handle is not allowed IO, return error */ + if (!fh->io_allowed) { + v4l2_err(&vpfe_dev->v4l2_dev, "fh->io_allowed\n"); + return -EACCES; + } + + sdinfo = vpfe_dev->current_subdev; + ret = v4l2_device_call_until_err(&vpfe_dev->v4l2_dev, sdinfo->grp_id, + video, s_stream, 1); + + if (ret && (ret != -ENOIOCTLCMD)) { + v4l2_err(&vpfe_dev->v4l2_dev, "stream on failed in subdev\n"); + return -EINVAL; + } + + /* If buffer queue is empty, return error */ + if (list_empty(&vpfe_dev->buffer_queue.stream)) { + v4l2_err(&vpfe_dev->v4l2_dev, "buffer queue is empty\n"); + return -EIO; + } + + /* Call videobuf_streamon to start streaming * in videobuf */ + ret = videobuf_streamon(&vpfe_dev->buffer_queue); + if (ret) + return ret; + + + ret = mutex_lock_interruptible(&vpfe_dev->lock); + if (ret) + goto streamoff; + /* Get the next frame from the buffer queue */ + vpfe_dev->next_frm = list_entry(vpfe_dev->dma_queue.next, + struct videobuf_buffer, queue); + vpfe_dev->cur_frm = vpfe_dev->next_frm; + /* Remove buffer from the buffer queue */ + list_del(&vpfe_dev->cur_frm->queue); + /* Mark state of the current frame to active */ + vpfe_dev->cur_frm->state = VIDEOBUF_ACTIVE; + /* Initialize field_id and started member */ + vpfe_dev->field_id = 0; + addr = videobuf_to_dma_contig(vpfe_dev->cur_frm); + + /* Calculate field offset */ + vpfe_calculate_offsets(vpfe_dev); + + if (vpfe_attach_irq(vpfe_dev) < 0) { + v4l2_err(&vpfe_dev->v4l2_dev, + "Error in attaching interrupt handle\n"); + ret = -EFAULT; + goto unlock_out; + } + if (ccdc_dev->hw_ops.configure() < 0) { + v4l2_err(&vpfe_dev->v4l2_dev, + "Error in configuring ccdc\n"); + ret = -EINVAL; + goto unlock_out; + } + ccdc_dev->hw_ops.setfbaddr((unsigned long)(addr)); + vpfe_start_ccdc_capture(vpfe_dev); + mutex_unlock(&vpfe_dev->lock); + return ret; +unlock_out: + mutex_unlock(&vpfe_dev->lock); +streamoff: + ret = videobuf_streamoff(&vpfe_dev->buffer_queue); + return ret; +} + +static int vpfe_streamoff(struct file *file, void *priv, + enum v4l2_buf_type buf_type) +{ + struct vpfe_device *vpfe_dev = video_drvdata(file); + struct vpfe_fh *fh = file->private_data; + struct vpfe_subdev_info *sdinfo; + int ret = 0; + + v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_streamoff\n"); + + if (V4L2_BUF_TYPE_VIDEO_CAPTURE != buf_type) { + v4l2_err(&vpfe_dev->v4l2_dev, "Invalid buf type\n"); + return -EINVAL; + } + + /* If io is allowed for this file handle, return error */ + if (!fh->io_allowed) { + v4l2_err(&vpfe_dev->v4l2_dev, "fh->io_allowed\n"); + return -EACCES; + } + + /* If streaming is not started, return error */ + if (!vpfe_dev->started) { + v4l2_err(&vpfe_dev->v4l2_dev, "device started\n"); + return -EINVAL; + } + + ret = mutex_lock_interruptible(&vpfe_dev->lock); + if (ret) + return ret; + + vpfe_stop_ccdc_capture(vpfe_dev); + vpfe_detach_irq(vpfe_dev); + + sdinfo = vpfe_dev->current_subdev; + ret = v4l2_device_call_until_err(&vpfe_dev->v4l2_dev, sdinfo->grp_id, + video, s_stream, 0); + + if (ret && (ret != -ENOIOCTLCMD)) + v4l2_err(&vpfe_dev->v4l2_dev, "stream off failed in subdev\n"); + ret = videobuf_streamoff(&vpfe_dev->buffer_queue); + mutex_unlock(&vpfe_dev->lock); + return ret; +} + +static int vpfe_cropcap(struct file *file, void *priv, + struct v4l2_cropcap *crop) +{ + struct vpfe_device *vpfe_dev = video_drvdata(file); + + v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_cropcap\n"); + + if (vpfe_dev->std_index > ARRAY_SIZE(vpfe_standards)) + return -EINVAL; + + memset(crop, 0, sizeof(struct v4l2_cropcap)); + crop->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + crop->bounds.width = crop->defrect.width = + vpfe_standards[vpfe_dev->std_index].width; + crop->bounds.height = crop->defrect.height = + vpfe_standards[vpfe_dev->std_index].height; + crop->pixelaspect = vpfe_standards[vpfe_dev->std_index].pixelaspect; + return 0; +} + +static int vpfe_g_crop(struct file *file, void *priv, + struct v4l2_crop *crop) +{ + struct vpfe_device *vpfe_dev = video_drvdata(file); + + v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_g_crop\n"); + + crop->c = vpfe_dev->crop; + return 0; +} + +static int vpfe_s_crop(struct file *file, void *priv, + struct v4l2_crop *crop) +{ + struct vpfe_device *vpfe_dev = video_drvdata(file); + int ret = 0; + + v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_s_crop\n"); + + if (vpfe_dev->started) { + /* make sure streaming is not started */ + v4l2_err(&vpfe_dev->v4l2_dev, + "Cannot change crop when streaming is ON\n"); + return -EBUSY; + } + + ret = mutex_lock_interruptible(&vpfe_dev->lock); + if (ret) + return ret; + + if (crop->c.top < 0 || crop->c.left < 0) { + v4l2_err(&vpfe_dev->v4l2_dev, + "doesn't support negative values for top & left\n"); + ret = -EINVAL; + goto unlock_out; + } + + /* adjust the width to 16 pixel boundry */ + crop->c.width = ((crop->c.width + 15) & ~0xf); + + /* make sure parameters are valid */ + if ((crop->c.left + crop->c.width > + vpfe_dev->std_info.active_pixels) || + (crop->c.top + crop->c.height > + vpfe_dev->std_info.active_lines)) { + v4l2_err(&vpfe_dev->v4l2_dev, "Error in S_CROP params\n"); + ret = -EINVAL; + goto unlock_out; + } + ccdc_dev->hw_ops.set_image_window(&crop->c); + vpfe_dev->fmt.fmt.pix.width = crop->c.width; + vpfe_dev->fmt.fmt.pix.height = crop->c.height; + vpfe_dev->fmt.fmt.pix.bytesperline = + ccdc_dev->hw_ops.get_line_length(); + vpfe_dev->fmt.fmt.pix.sizeimage = + vpfe_dev->fmt.fmt.pix.bytesperline * + vpfe_dev->fmt.fmt.pix.height; + vpfe_dev->crop = crop->c; +unlock_out: + mutex_unlock(&vpfe_dev->lock); + return ret; +} + + +static long vpfe_param_handler(struct file *file, void *priv, + int cmd, void *param) +{ + struct vpfe_device *vpfe_dev = video_drvdata(file); + int ret = 0; + + v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_param_handler\n"); + + if (vpfe_dev->started) { + /* only allowed if streaming is not started */ + v4l2_err(&vpfe_dev->v4l2_dev, "device already started\n"); + return -EBUSY; + } + + ret = mutex_lock_interruptible(&vpfe_dev->lock); + if (ret) + return ret; + + switch (cmd) { + case VPFE_CMD_S_CCDC_RAW_PARAMS: + v4l2_warn(&vpfe_dev->v4l2_dev, + "VPFE_CMD_S_CCDC_RAW_PARAMS: experimental ioctl\n"); + ret = ccdc_dev->hw_ops.set_params(param); + if (ret) { + v4l2_err(&vpfe_dev->v4l2_dev, + "Error in setting parameters in CCDC\n"); + goto unlock_out; + } + if (vpfe_get_ccdc_image_format(vpfe_dev, &vpfe_dev->fmt) < 0) { + v4l2_err(&vpfe_dev->v4l2_dev, + "Invalid image format at CCDC\n"); + goto unlock_out; + } + break; + default: + ret = -EINVAL; + } +unlock_out: + mutex_unlock(&vpfe_dev->lock); + return ret; +} + + +/* vpfe capture ioctl operations */ +static const struct v4l2_ioctl_ops vpfe_ioctl_ops = { + .vidioc_querycap = vpfe_querycap, + .vidioc_g_fmt_vid_cap = vpfe_g_fmt_vid_cap, + .vidioc_enum_fmt_vid_cap = vpfe_enum_fmt_vid_cap, + .vidioc_s_fmt_vid_cap = vpfe_s_fmt_vid_cap, + .vidioc_try_fmt_vid_cap = vpfe_try_fmt_vid_cap, + .vidioc_enum_input = vpfe_enum_input, + .vidioc_g_input = vpfe_g_input, + .vidioc_s_input = vpfe_s_input, + .vidioc_querystd = vpfe_querystd, + .vidioc_s_std = vpfe_s_std, + .vidioc_g_std = vpfe_g_std, + .vidioc_reqbufs = vpfe_reqbufs, + .vidioc_querybuf = vpfe_querybuf, + .vidioc_qbuf = vpfe_qbuf, + .vidioc_dqbuf = vpfe_dqbuf, + .vidioc_streamon = vpfe_streamon, + .vidioc_streamoff = vpfe_streamoff, + .vidioc_cropcap = vpfe_cropcap, + .vidioc_g_crop = vpfe_g_crop, + .vidioc_s_crop = vpfe_s_crop, + .vidioc_default = vpfe_param_handler, +}; + +static struct vpfe_device *vpfe_initialize(void) +{ + struct vpfe_device *vpfe_dev; + + /* Default number of buffers should be 3 */ + if ((numbuffers > 0) && + (numbuffers < config_params.min_numbuffers)) + numbuffers = config_params.min_numbuffers; + + /* + * Set buffer size to min buffers size if invalid buffer size is + * given + */ + if (bufsize < config_params.min_bufsize) + bufsize = config_params.min_bufsize; + + config_params.numbuffers = numbuffers; + + if (numbuffers) + config_params.device_bufsize = bufsize; + + /* Allocate memory for device objects */ + vpfe_dev = kzalloc(sizeof(*vpfe_dev), GFP_KERNEL); + + return vpfe_dev; +} + +static void vpfe_disable_clock(struct vpfe_device *vpfe_dev) +{ + struct vpfe_config *vpfe_cfg = vpfe_dev->cfg; + + clk_disable(vpfe_cfg->vpssclk); + clk_put(vpfe_cfg->vpssclk); + clk_disable(vpfe_cfg->slaveclk); + clk_put(vpfe_cfg->slaveclk); + v4l2_info(vpfe_dev->pdev->driver, + "vpfe vpss master & slave clocks disabled\n"); +} + +static int vpfe_enable_clock(struct vpfe_device *vpfe_dev) +{ + struct vpfe_config *vpfe_cfg = vpfe_dev->cfg; + int ret = -ENOENT; + + vpfe_cfg->vpssclk = clk_get(vpfe_dev->pdev, "vpss_master"); + if (NULL == vpfe_cfg->vpssclk) { + v4l2_err(vpfe_dev->pdev->driver, "No clock defined for" + "vpss_master\n"); + return ret; + } + + if (clk_enable(vpfe_cfg->vpssclk)) { + v4l2_err(vpfe_dev->pdev->driver, + "vpfe vpss master clock not enabled\n"); + goto out; + } + v4l2_info(vpfe_dev->pdev->driver, + "vpfe vpss master clock enabled\n"); + + vpfe_cfg->slaveclk = clk_get(vpfe_dev->pdev, "vpss_slave"); + if (NULL == vpfe_cfg->slaveclk) { + v4l2_err(vpfe_dev->pdev->driver, + "No clock defined for vpss slave\n"); + goto out; + } + + if (clk_enable(vpfe_cfg->slaveclk)) { + v4l2_err(vpfe_dev->pdev->driver, + "vpfe vpss slave clock not enabled\n"); + goto out; + } + v4l2_info(vpfe_dev->pdev->driver, "vpfe vpss slave clock enabled\n"); + return 0; +out: + if (vpfe_cfg->vpssclk) + clk_put(vpfe_cfg->vpssclk); + if (vpfe_cfg->slaveclk) + clk_put(vpfe_cfg->slaveclk); + + return -1; +} + +/* + * vpfe_probe : This function creates device entries by register + * itself to the V4L2 driver and initializes fields of each + * device objects + */ +static __init int vpfe_probe(struct platform_device *pdev) +{ + struct vpfe_subdev_info *sdinfo; + struct vpfe_config *vpfe_cfg; + struct resource *res1; + struct vpfe_device *vpfe_dev; + struct i2c_adapter *i2c_adap; + struct video_device *vfd; + int ret = -ENOMEM, i, j; + int num_subdevs = 0; + + /* Get the pointer to the device object */ + vpfe_dev = vpfe_initialize(); + + if (!vpfe_dev) { + v4l2_err(pdev->dev.driver, + "Failed to allocate memory for vpfe_dev\n"); + return ret; + } + + vpfe_dev->pdev = &pdev->dev; + + if (NULL == pdev->dev.platform_data) { + v4l2_err(pdev->dev.driver, "Unable to get vpfe config\n"); + ret = -ENOENT; + goto probe_free_dev_mem; + } + + vpfe_cfg = pdev->dev.platform_data; + vpfe_dev->cfg = vpfe_cfg; + if (NULL == vpfe_cfg->ccdc || + NULL == vpfe_cfg->card_name || + NULL == vpfe_cfg->sub_devs) { + v4l2_err(pdev->dev.driver, "null ptr in vpfe_cfg\n"); + ret = -ENOENT; + goto probe_free_dev_mem; + } + + /* enable vpss clocks */ + ret = vpfe_enable_clock(vpfe_dev); + if (ret) + goto probe_free_dev_mem; + + mutex_lock(&ccdc_lock); + /* Allocate memory for ccdc configuration */ + ccdc_cfg = kmalloc(sizeof(struct ccdc_config), GFP_KERNEL); + if (NULL == ccdc_cfg) { + v4l2_err(pdev->dev.driver, + "Memory allocation failed for ccdc_cfg\n"); + goto probe_disable_clock; + } + + strncpy(ccdc_cfg->name, vpfe_cfg->ccdc, 32); + /* Get VINT0 irq resource */ + res1 = platform_get_resource(pdev, IORESOURCE_IRQ, 0); + if (!res1) { + v4l2_err(pdev->dev.driver, + "Unable to get interrupt for VINT0\n"); + ret = -ENOENT; + goto probe_disable_clock; + } + vpfe_dev->ccdc_irq0 = res1->start; + + /* Get VINT1 irq resource */ + res1 = platform_get_resource(pdev, + IORESOURCE_IRQ, 1); + if (!res1) { + v4l2_err(pdev->dev.driver, + "Unable to get interrupt for VINT1\n"); + ret = -ENOENT; + goto probe_disable_clock; + } + vpfe_dev->ccdc_irq1 = res1->start; + + /* Get address base of CCDC */ + res1 = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res1) { + v4l2_err(pdev->dev.driver, + "Unable to get register address map\n"); + ret = -ENOENT; + goto probe_disable_clock; + } + + ccdc_cfg->ccdc_addr_size = res1->end - res1->start + 1; + if (!request_mem_region(res1->start, ccdc_cfg->ccdc_addr_size, + pdev->dev.driver->name)) { + v4l2_err(pdev->dev.driver, + "Failed request_mem_region for ccdc base\n"); + ret = -ENXIO; + goto probe_disable_clock; + } + ccdc_cfg->ccdc_addr = ioremap_nocache(res1->start, + ccdc_cfg->ccdc_addr_size); + if (!ccdc_cfg->ccdc_addr) { + v4l2_err(pdev->dev.driver, "Unable to ioremap ccdc addr\n"); + ret = -ENXIO; + goto probe_out_release_mem1; + } + + ret = request_irq(vpfe_dev->ccdc_irq0, vpfe_isr, IRQF_DISABLED, + "vpfe_capture0", vpfe_dev); + + if (0 != ret) { + v4l2_err(pdev->dev.driver, "Unable to request interrupt\n"); + goto probe_out_unmap1; + } + + /* Allocate memory for video device */ + vfd = video_device_alloc(); + if (NULL == vfd) { + ret = -ENOMEM; + v4l2_err(pdev->dev.driver, + "Unable to alloc video device\n"); + goto probe_out_release_irq; + } + + /* Initialize field of video device */ + vfd->release = video_device_release; + vfd->fops = &vpfe_fops; + vfd->ioctl_ops = &vpfe_ioctl_ops; + vfd->minor = -1; + vfd->tvnorms = 0; + vfd->current_norm = V4L2_STD_PAL; + vfd->v4l2_dev = &vpfe_dev->v4l2_dev; + snprintf(vfd->name, sizeof(vfd->name), + "%s_V%d.%d.%d", + CAPTURE_DRV_NAME, + (VPFE_CAPTURE_VERSION_CODE >> 16) & 0xff, + (VPFE_CAPTURE_VERSION_CODE >> 8) & 0xff, + (VPFE_CAPTURE_VERSION_CODE) & 0xff); + /* Set video_dev to the video device */ + vpfe_dev->video_dev = vfd; + + ret = v4l2_device_register(&pdev->dev, &vpfe_dev->v4l2_dev); + if (ret) { + v4l2_err(pdev->dev.driver, + "Unable to register v4l2 device.\n"); + goto probe_out_video_release; + } + v4l2_info(&vpfe_dev->v4l2_dev, "v4l2 device registered\n"); + spin_lock_init(&vpfe_dev->irqlock); + spin_lock_init(&vpfe_dev->dma_queue_lock); + mutex_init(&vpfe_dev->lock); + + /* Initialize field of the device objects */ + vpfe_dev->numbuffers = config_params.numbuffers; + + /* Initialize prio member of device object */ + v4l2_prio_init(&vpfe_dev->prio); + /* register video device */ + v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, + "trying to register vpfe device.\n"); + v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, + "video_dev=%x\n", (int)&vpfe_dev->video_dev); + vpfe_dev->fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + ret = video_register_device(vpfe_dev->video_dev, + VFL_TYPE_GRABBER, -1); + + if (ret) { + v4l2_err(pdev->dev.driver, + "Unable to register video device.\n"); + goto probe_out_v4l2_unregister; + } + + v4l2_info(&vpfe_dev->v4l2_dev, "video device registered\n"); + /* set the driver data in platform device */ + platform_set_drvdata(pdev, vpfe_dev); + /* set driver private data */ + video_set_drvdata(vpfe_dev->video_dev, vpfe_dev); + i2c_adap = i2c_get_adapter(1); + vpfe_cfg = pdev->dev.platform_data; + num_subdevs = vpfe_cfg->num_subdevs; + vpfe_dev->sd = kmalloc(sizeof(struct v4l2_subdev *) * num_subdevs, + GFP_KERNEL); + if (NULL == vpfe_dev->sd) { + v4l2_err(&vpfe_dev->v4l2_dev, + "unable to allocate memory for subdevice pointers\n"); + ret = -ENOMEM; + goto probe_out_video_unregister; + } + + for (i = 0; i < num_subdevs; i++) { + struct v4l2_input *inps; + + sdinfo = &vpfe_cfg->sub_devs[i]; + + /* Load up the subdevice */ + vpfe_dev->sd[i] = + v4l2_i2c_new_subdev_board(&vpfe_dev->v4l2_dev, + i2c_adap, + sdinfo->name, + &sdinfo->board_info, + NULL); + if (vpfe_dev->sd[i]) { + v4l2_info(&vpfe_dev->v4l2_dev, + "v4l2 sub device %s registered\n", + sdinfo->name); + vpfe_dev->sd[i]->grp_id = sdinfo->grp_id; + /* update tvnorms from the sub devices */ + for (j = 0; j < sdinfo->num_inputs; j++) { + inps = &sdinfo->inputs[j]; + vfd->tvnorms |= inps->std; + } + } else { + v4l2_info(&vpfe_dev->v4l2_dev, + "v4l2 sub device %s register fails\n", + sdinfo->name); + goto probe_sd_out; + } + } + + /* set first sub device as current one */ + vpfe_dev->current_subdev = &vpfe_cfg->sub_devs[0]; + + /* We have at least one sub device to work with */ + mutex_unlock(&ccdc_lock); + return 0; + +probe_sd_out: + kfree(vpfe_dev->sd); +probe_out_video_unregister: + video_unregister_device(vpfe_dev->video_dev); +probe_out_v4l2_unregister: + v4l2_device_unregister(&vpfe_dev->v4l2_dev); +probe_out_video_release: + if (vpfe_dev->video_dev->minor == -1) + video_device_release(vpfe_dev->video_dev); +probe_out_release_irq: + free_irq(vpfe_dev->ccdc_irq0, vpfe_dev); +probe_out_unmap1: + iounmap(ccdc_cfg->ccdc_addr); +probe_out_release_mem1: + release_mem_region(res1->start, res1->end - res1->start + 1); +probe_disable_clock: + vpfe_disable_clock(vpfe_dev); + mutex_unlock(&ccdc_lock); + kfree(ccdc_cfg); +probe_free_dev_mem: + kfree(vpfe_dev); + return ret; +} + +/* + * vpfe_remove : It un-register device from V4L2 driver + */ +static int vpfe_remove(struct platform_device *pdev) +{ + struct vpfe_device *vpfe_dev = platform_get_drvdata(pdev); + struct resource *res; + + v4l2_info(pdev->dev.driver, "vpfe_remove\n"); + + free_irq(vpfe_dev->ccdc_irq0, vpfe_dev); + kfree(vpfe_dev->sd); + v4l2_device_unregister(&vpfe_dev->v4l2_dev); + video_unregister_device(vpfe_dev->video_dev); + mutex_lock(&ccdc_lock); + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + release_mem_region(res->start, res->end - res->start + 1); + iounmap(ccdc_cfg->ccdc_addr); + mutex_unlock(&ccdc_lock); + vpfe_disable_clock(vpfe_dev); + kfree(vpfe_dev); + kfree(ccdc_cfg); + return 0; +} + +static int +vpfe_suspend(struct device *dev) +{ + /* add suspend code here later */ + return -1; +} + +static int +vpfe_resume(struct device *dev) +{ + /* add resume code here later */ + return -1; +} + +static struct dev_pm_ops vpfe_dev_pm_ops = { + .suspend = vpfe_suspend, + .resume = vpfe_resume, +}; + +static struct platform_driver vpfe_driver = { + .driver = { + .name = CAPTURE_DRV_NAME, + .owner = THIS_MODULE, + .pm = &vpfe_dev_pm_ops, + }, + .probe = vpfe_probe, + .remove = __devexit_p(vpfe_remove), +}; + +static __init int vpfe_init(void) +{ + printk(KERN_NOTICE "vpfe_init\n"); + /* Register driver to the kernel */ + return platform_driver_register(&vpfe_driver); +} + +/* + * vpfe_cleanup : This function un-registers device driver + */ +static void vpfe_cleanup(void) +{ + platform_driver_unregister(&vpfe_driver); +} + +module_init(vpfe_init); +module_exit(vpfe_cleanup); -- cgit v1.2.3 From 03807cf31be76b6ca1ac32e44bbed5df8b2adef4 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 19 Jun 2009 14:14:10 +0200 Subject: v4l: ccdc hw device header file for vpfe capture From: Muralidharan Karicheri Adds ccdc hw device header for vpfe capture driver Reviewed by: Hans Verkuil Reviewed by: Laurent Pinchart Priority: normal Signed-off-by: Muralidharan Karicheri Signed-off-by: Hans Verkuil --- linux/drivers/media/video/davinci/ccdc_hw_device.h | 110 +++++++++++++++++++++ 1 file changed, 110 insertions(+) create mode 100644 linux/drivers/media/video/davinci/ccdc_hw_device.h (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/davinci/ccdc_hw_device.h b/linux/drivers/media/video/davinci/ccdc_hw_device.h new file mode 100644 index 000000000..86b9b3518 --- /dev/null +++ b/linux/drivers/media/video/davinci/ccdc_hw_device.h @@ -0,0 +1,110 @@ +/* + * Copyright (C) 2008-2009 Texas Instruments Inc + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * ccdc device API + */ +#ifndef _CCDC_HW_DEVICE_H +#define _CCDC_HW_DEVICE_H + +#ifdef __KERNEL__ +#include +#include +#include +#include + +/* + * ccdc hw operations + */ +struct ccdc_hw_ops { + /* Pointer to initialize function to initialize ccdc device */ + int (*open) (struct device *dev); + /* Pointer to deinitialize function */ + int (*close) (struct device *dev); + /* set ccdc base address */ + void (*set_ccdc_base)(void *base, int size); + /* Pointer to function to enable or disable ccdc */ + void (*enable) (int en); + /* reset sbl. only for 6446 */ + void (*reset) (void); + /* enable output to sdram */ + void (*enable_out_to_sdram) (int en); + /* Pointer to function to set hw parameters */ + int (*set_hw_if_params) (struct vpfe_hw_if_param *param); + /* get interface parameters */ + int (*get_hw_if_params) (struct vpfe_hw_if_param *param); + /* + * Pointer to function to set parameters. Used + * for implementing VPFE_S_CCDC_PARAMS + */ + int (*set_params) (void *params); + /* + * Pointer to function to get parameter. Used + * for implementing VPFE_G_CCDC_PARAMS + */ + int (*get_params) (void *params); + /* Pointer to function to configure ccdc */ + int (*configure) (void); + + /* Pointer to function to set buffer type */ + int (*set_buftype) (enum ccdc_buftype buf_type); + /* Pointer to function to get buffer type */ + enum ccdc_buftype (*get_buftype) (void); + /* Pointer to function to set frame format */ + int (*set_frame_format) (enum ccdc_frmfmt frm_fmt); + /* Pointer to function to get frame format */ + enum ccdc_frmfmt (*get_frame_format) (void); + /* enumerate hw pix formats */ + int (*enum_pix)(u32 *hw_pix, int i); + /* Pointer to function to set buffer type */ + u32 (*get_pixel_format) (void); + /* Pointer to function to get pixel format. */ + int (*set_pixel_format) (u32 pixfmt); + /* Pointer to function to set image window */ + int (*set_image_window) (struct v4l2_rect *win); + /* Pointer to function to set image window */ + void (*get_image_window) (struct v4l2_rect *win); + /* Pointer to function to get line length */ + unsigned int (*get_line_length) (void); + + /* Query CCDC control IDs */ + int (*queryctrl)(struct v4l2_queryctrl *qctrl); + /* Set CCDC control */ + int (*set_control)(struct v4l2_control *ctrl); + /* Get CCDC control */ + int (*get_control)(struct v4l2_control *ctrl); + + /* Pointer to function to set frame buffer address */ + void (*setfbaddr) (unsigned long addr); + /* Pointer to function to get field id */ + int (*getfid) (void); +}; + +struct ccdc_hw_device { + /* ccdc device name */ + char name[32]; + /* module owner */ + struct module *owner; + /* hw ops */ + struct ccdc_hw_ops hw_ops; +}; + +/* Used by CCDC module to register & unregister with vpfe capture driver */ +int vpfe_register_ccdc_device(struct ccdc_hw_device *dev); +void vpfe_unregister_ccdc_device(struct ccdc_hw_device *dev); + +#endif +#endif -- cgit v1.2.3 From 91f3825a3a2bd6f368a38e2d00422dcab4d637fa Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 3 Jul 2009 10:23:07 +0200 Subject: v4l: dm355 ccdc module for vpfe capture driver From: Muralidharan Karicheri Adds ccdc hw module for DM355 CCDC. This registers with the bridge driver a set of hw_ops for configuring the CCDC for a specific decoder device connected to vpfe. Reviewed by: Hans Verkuil Reviewed by: Laurent Pinchart Reviewed by: Mauro Carvalho Chehab Priority: normal Signed-off-by: Muralidharan Karicheri Signed-off-by: Hans Verkuil --- linux/drivers/media/video/davinci/dm355_ccdc.c | 978 +++++++++++++++++++++ .../drivers/media/video/davinci/dm355_ccdc_regs.h | 310 +++++++ 2 files changed, 1288 insertions(+) create mode 100644 linux/drivers/media/video/davinci/dm355_ccdc.c create mode 100644 linux/drivers/media/video/davinci/dm355_ccdc_regs.h (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/davinci/dm355_ccdc.c b/linux/drivers/media/video/davinci/dm355_ccdc.c new file mode 100644 index 000000000..4629cabe3 --- /dev/null +++ b/linux/drivers/media/video/davinci/dm355_ccdc.c @@ -0,0 +1,978 @@ +/* + * Copyright (C) 2005-2009 Texas Instruments Inc + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * CCDC hardware module for DM355 + * ------------------------------ + * + * This module is for configuring DM355 CCD controller of VPFE to capture + * Raw yuv or Bayer RGB data from a decoder. CCDC has several modules + * such as Defect Pixel Correction, Color Space Conversion etc to + * pre-process the Bayer RGB data, before writing it to SDRAM. This + * module also allows application to configure individual + * module parameters through VPFE_CMD_S_CCDC_RAW_PARAMS IOCTL. + * To do so, application include dm355_ccdc.h and vpfe_capture.h header + * files. The setparams() API is called by vpfe_capture driver + * to configure module parameters + * + * TODO: 1) Raw bayer parameter settings and bayer capture + * 2) Split module parameter structure to module specific ioctl structs + * 3) add support for lense shading correction + * 4) investigate if enum used for user space type definition + * to be replaced by #defines or integer + */ +#include +#include +#include +#include +#include +#include "dm355_ccdc_regs.h" +#include "ccdc_hw_device.h" + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("CCDC Driver for DM355"); +MODULE_AUTHOR("Texas Instruments"); + +static struct device *dev; + +/* Object for CCDC raw mode */ +static struct ccdc_params_raw ccdc_hw_params_raw = { + .pix_fmt = CCDC_PIXFMT_RAW, + .frm_fmt = CCDC_FRMFMT_PROGRESSIVE, + .win = CCDC_WIN_VGA, + .fid_pol = VPFE_PINPOL_POSITIVE, + .vd_pol = VPFE_PINPOL_POSITIVE, + .hd_pol = VPFE_PINPOL_POSITIVE, + .gain = { + .r_ye = 256, + .gb_g = 256, + .gr_cy = 256, + .b_mg = 256 + }, + .config_params = { + .datasft = 2, + .data_sz = CCDC_DATA_10BITS, + .mfilt1 = CCDC_NO_MEDIAN_FILTER1, + .mfilt2 = CCDC_NO_MEDIAN_FILTER2, + .alaw = { + .gama_wd = 2, + }, + .blk_clamp = { + .sample_pixel = 1, + .dc_sub = 25 + }, + .col_pat_field0 = { + .olop = CCDC_GREEN_BLUE, + .olep = CCDC_BLUE, + .elop = CCDC_RED, + .elep = CCDC_GREEN_RED + }, + .col_pat_field1 = { + .olop = CCDC_GREEN_BLUE, + .olep = CCDC_BLUE, + .elop = CCDC_RED, + .elep = CCDC_GREEN_RED + }, + }, +}; + + +/* Object for CCDC ycbcr mode */ +static struct ccdc_params_ycbcr ccdc_hw_params_ycbcr = { + .win = CCDC_WIN_PAL, + .pix_fmt = CCDC_PIXFMT_YCBCR_8BIT, + .frm_fmt = CCDC_FRMFMT_INTERLACED, + .fid_pol = VPFE_PINPOL_POSITIVE, + .vd_pol = VPFE_PINPOL_POSITIVE, + .hd_pol = VPFE_PINPOL_POSITIVE, + .bt656_enable = 1, + .pix_order = CCDC_PIXORDER_CBYCRY, + .buf_type = CCDC_BUFTYPE_FLD_INTERLEAVED +}; + +static enum vpfe_hw_if_type ccdc_if_type; +static void *__iomem ccdc_base_addr; +static int ccdc_addr_size; + +/* Raw Bayer formats */ +static u32 ccdc_raw_bayer_pix_formats[] = + {V4L2_PIX_FMT_SBGGR8, V4L2_PIX_FMT_SBGGR16}; + +/* Raw YUV formats */ +static u32 ccdc_raw_yuv_pix_formats[] = + {V4L2_PIX_FMT_UYVY, V4L2_PIX_FMT_YUYV}; + +/* register access routines */ +static inline u32 regr(u32 offset) +{ + return __raw_readl(ccdc_base_addr + offset); +} + +static inline void regw(u32 val, u32 offset) +{ + __raw_writel(val, ccdc_base_addr + offset); +} + +static void ccdc_set_ccdc_base(void *addr, int size) +{ + ccdc_base_addr = addr; + ccdc_addr_size = size; +} + +static void ccdc_enable(int en) +{ + unsigned int temp; + temp = regr(SYNCEN); + temp &= (~CCDC_SYNCEN_VDHDEN_MASK); + temp |= (en & CCDC_SYNCEN_VDHDEN_MASK); + regw(temp, SYNCEN); +} + +static void ccdc_enable_output_to_sdram(int en) +{ + unsigned int temp; + temp = regr(SYNCEN); + temp &= (~(CCDC_SYNCEN_WEN_MASK)); + temp |= ((en << CCDC_SYNCEN_WEN_SHIFT) & CCDC_SYNCEN_WEN_MASK); + regw(temp, SYNCEN); +} + +static void ccdc_config_gain_offset(void) +{ + /* configure gain */ + regw(ccdc_hw_params_raw.gain.r_ye, RYEGAIN); + regw(ccdc_hw_params_raw.gain.gr_cy, GRCYGAIN); + regw(ccdc_hw_params_raw.gain.gb_g, GBGGAIN); + regw(ccdc_hw_params_raw.gain.b_mg, BMGGAIN); + /* configure offset */ + regw(ccdc_hw_params_raw.ccdc_offset, OFFSET); +} + +/* + * ccdc_restore_defaults() + * This function restore power on defaults in the ccdc registers + */ +static int ccdc_restore_defaults(void) +{ + int i; + + dev_dbg(dev, "\nstarting ccdc_restore_defaults..."); + /* set all registers to zero */ + for (i = 0; i <= CCDC_REG_LAST; i += 4) + regw(0, i); + + /* now override the values with power on defaults in registers */ + regw(MODESET_DEFAULT, MODESET); + /* no culling support */ + regw(CULH_DEFAULT, CULH); + regw(CULV_DEFAULT, CULV); + /* Set default Gain and Offset */ + ccdc_hw_params_raw.gain.r_ye = GAIN_DEFAULT; + ccdc_hw_params_raw.gain.gb_g = GAIN_DEFAULT; + ccdc_hw_params_raw.gain.gr_cy = GAIN_DEFAULT; + ccdc_hw_params_raw.gain.b_mg = GAIN_DEFAULT; + ccdc_config_gain_offset(); + regw(OUTCLIP_DEFAULT, OUTCLIP); + regw(LSCCFG2_DEFAULT, LSCCFG2); + /* select ccdc input */ + if (vpss_select_ccdc_source(VPSS_CCDCIN)) { + dev_dbg(dev, "\ncouldn't select ccdc input source"); + return -EFAULT; + } + /* select ccdc clock */ + if (vpss_enable_clock(VPSS_CCDC_CLOCK, 1) < 0) { + dev_dbg(dev, "\ncouldn't enable ccdc clock"); + return -EFAULT; + } + dev_dbg(dev, "\nEnd of ccdc_restore_defaults..."); + return 0; +} + +static int ccdc_open(struct device *device) +{ + dev = device; + return ccdc_restore_defaults(); +} + +static int ccdc_close(struct device *device) +{ + /* disable clock */ + vpss_enable_clock(VPSS_CCDC_CLOCK, 0); + /* do nothing for now */ + return 0; +} +/* + * ccdc_setwin() + * This function will configure the window size to + * be capture in CCDC reg. + */ +static void ccdc_setwin(struct v4l2_rect *image_win, + enum ccdc_frmfmt frm_fmt, int ppc) +{ + int horz_start, horz_nr_pixels; + int vert_start, vert_nr_lines; + int mid_img = 0; + + dev_dbg(dev, "\nStarting ccdc_setwin..."); + + /* + * ppc - per pixel count. indicates how many pixels per cell + * output to SDRAM. example, for ycbcr, it is one y and one c, so 2. + * raw capture this is 1 + */ + horz_start = image_win->left << (ppc - 1); + horz_nr_pixels = ((image_win->width) << (ppc - 1)) - 1; + + /* Writing the horizontal info into the registers */ + regw(horz_start, SPH); + regw(horz_nr_pixels, NPH); + vert_start = image_win->top; + + if (frm_fmt == CCDC_FRMFMT_INTERLACED) { + vert_nr_lines = (image_win->height >> 1) - 1; + vert_start >>= 1; + /* Since first line doesn't have any data */ + vert_start += 1; + /* configure VDINT0 and VDINT1 */ + regw(vert_start, VDINT0); + } else { + /* Since first line doesn't have any data */ + vert_start += 1; + vert_nr_lines = image_win->height - 1; + /* configure VDINT0 and VDINT1 */ + mid_img = vert_start + (image_win->height / 2); + regw(vert_start, VDINT0); + regw(mid_img, VDINT1); + } + regw(vert_start & CCDC_START_VER_ONE_MASK, SLV0); + regw(vert_start & CCDC_START_VER_TWO_MASK, SLV1); + regw(vert_nr_lines & CCDC_NUM_LINES_VER, NLV); + dev_dbg(dev, "\nEnd of ccdc_setwin..."); +} + +static int validate_ccdc_param(struct ccdc_config_params_raw *ccdcparam) +{ + if (ccdcparam->datasft < CCDC_DATA_NO_SHIFT || + ccdcparam->datasft > CCDC_DATA_SHIFT_6BIT) { + dev_dbg(dev, "Invalid value of data shift\n"); + return -EINVAL; + } + + if (ccdcparam->mfilt1 < CCDC_NO_MEDIAN_FILTER1 || + ccdcparam->mfilt1 > CCDC_MEDIAN_FILTER1) { + dev_dbg(dev, "Invalid value of median filter1\n"); + return -EINVAL; + } + + if (ccdcparam->mfilt2 < CCDC_NO_MEDIAN_FILTER2 || + ccdcparam->mfilt2 > CCDC_MEDIAN_FILTER2) { + dev_dbg(dev, "Invalid value of median filter2\n"); + return -EINVAL; + } + + if ((ccdcparam->med_filt_thres < 0) || + (ccdcparam->med_filt_thres > CCDC_MED_FILT_THRESH)) { + dev_dbg(dev, "Invalid value of median filter thresold\n"); + return -EINVAL; + } + + if (ccdcparam->data_sz < CCDC_DATA_16BITS || + ccdcparam->data_sz > CCDC_DATA_8BITS) { + dev_dbg(dev, "Invalid value of data size\n"); + return -EINVAL; + } + + if (ccdcparam->alaw.enable) { + if (ccdcparam->alaw.gama_wd < CCDC_GAMMA_BITS_13_4 || + ccdcparam->alaw.gama_wd > CCDC_GAMMA_BITS_09_0) { + dev_dbg(dev, "Invalid value of ALAW\n"); + return -EINVAL; + } + } + + if (ccdcparam->blk_clamp.b_clamp_enable) { + if (ccdcparam->blk_clamp.sample_pixel < CCDC_SAMPLE_1PIXELS || + ccdcparam->blk_clamp.sample_pixel > CCDC_SAMPLE_16PIXELS) { + dev_dbg(dev, "Invalid value of sample pixel\n"); + return -EINVAL; + } + if (ccdcparam->blk_clamp.sample_ln < CCDC_SAMPLE_1LINES || + ccdcparam->blk_clamp.sample_ln > CCDC_SAMPLE_16LINES) { + dev_dbg(dev, "Invalid value of sample lines\n"); + return -EINVAL; + } + } + return 0; +} + +/* Parameter operations */ +static int ccdc_set_params(void __user *params) +{ + struct ccdc_config_params_raw ccdc_raw_params; + int x; + + /* only raw module parameters can be set through the IOCTL */ + if (ccdc_if_type != VPFE_RAW_BAYER) + return -EINVAL; + + x = copy_from_user(&ccdc_raw_params, params, sizeof(ccdc_raw_params)); + if (x) { + dev_dbg(dev, "ccdc_set_params: error in copying ccdc" + "params, %d\n", x); + return -EFAULT; + } + + if (!validate_ccdc_param(&ccdc_raw_params)) { + memcpy(&ccdc_hw_params_raw.config_params, + &ccdc_raw_params, + sizeof(ccdc_raw_params)); + return 0; + } + return -EINVAL; +} + +/* This function will configure CCDC for YCbCr video capture */ +static void ccdc_config_ycbcr(void) +{ + struct ccdc_params_ycbcr *params = &ccdc_hw_params_ycbcr; + u32 temp; + + /* first set the CCDC power on defaults values in all registers */ + dev_dbg(dev, "\nStarting ccdc_config_ycbcr..."); + ccdc_restore_defaults(); + + /* configure pixel format & video frame format */ + temp = (((params->pix_fmt & CCDC_INPUT_MODE_MASK) << + CCDC_INPUT_MODE_SHIFT) | + ((params->frm_fmt & CCDC_FRM_FMT_MASK) << + CCDC_FRM_FMT_SHIFT)); + + /* setup BT.656 sync mode */ + if (params->bt656_enable) { + regw(CCDC_REC656IF_BT656_EN, REC656IF); + /* + * configure the FID, VD, HD pin polarity fld,hd pol positive, + * vd negative, 8-bit pack mode + */ + temp |= CCDC_VD_POL_NEGATIVE; + } else { /* y/c external sync mode */ + temp |= (((params->fid_pol & CCDC_FID_POL_MASK) << + CCDC_FID_POL_SHIFT) | + ((params->hd_pol & CCDC_HD_POL_MASK) << + CCDC_HD_POL_SHIFT) | + ((params->vd_pol & CCDC_VD_POL_MASK) << + CCDC_VD_POL_SHIFT)); + } + + /* pack the data to 8-bit */ + temp |= CCDC_DATA_PACK_ENABLE; + + regw(temp, MODESET); + + /* configure video window */ + ccdc_setwin(¶ms->win, params->frm_fmt, 2); + + /* configure the order of y cb cr in SD-RAM */ + temp = (params->pix_order << CCDC_Y8POS_SHIFT); + temp |= CCDC_LATCH_ON_VSYNC_DISABLE | CCDC_CCDCFG_FIDMD_NO_LATCH_VSYNC; + regw(temp, CCDCFG); + + /* + * configure the horizontal line offset. This is done by rounding up + * width to a multiple of 16 pixels and multiply by two to account for + * y:cb:cr 4:2:2 data + */ + regw(((params->win.width * 2 + 31) >> 5), HSIZE); + + /* configure the memory line offset */ + if (params->buf_type == CCDC_BUFTYPE_FLD_INTERLEAVED) { + /* two fields are interleaved in memory */ + regw(CCDC_SDOFST_FIELD_INTERLEAVED, SDOFST); + } + + dev_dbg(dev, "\nEnd of ccdc_config_ycbcr...\n"); +} + +/* + * ccdc_config_black_clamp() + * configure parameters for Optical Black Clamp + */ +static void ccdc_config_black_clamp(struct ccdc_black_clamp *bclamp) +{ + u32 val; + + if (!bclamp->b_clamp_enable) { + /* configure DCSub */ + regw(bclamp->dc_sub & CCDC_BLK_DC_SUB_MASK, DCSUB); + regw(0x0000, CLAMP); + return; + } + /* Enable the Black clamping, set sample lines and pixels */ + val = (bclamp->start_pixel & CCDC_BLK_ST_PXL_MASK) | + ((bclamp->sample_pixel & CCDC_BLK_SAMPLE_LN_MASK) << + CCDC_BLK_SAMPLE_LN_SHIFT) | CCDC_BLK_CLAMP_ENABLE; + regw(val, CLAMP); + + /* If Black clamping is enable then make dcsub 0 */ + val = (bclamp->sample_ln & CCDC_NUM_LINE_CALC_MASK) + << CCDC_NUM_LINE_CALC_SHIFT; + regw(val, DCSUB); +} + +/* + * ccdc_config_black_compense() + * configure parameters for Black Compensation + */ +static void ccdc_config_black_compense(struct ccdc_black_compensation *bcomp) +{ + u32 val; + + val = (bcomp->b & CCDC_BLK_COMP_MASK) | + ((bcomp->gb & CCDC_BLK_COMP_MASK) << + CCDC_BLK_COMP_GB_COMP_SHIFT); + regw(val, BLKCMP1); + + val = ((bcomp->gr & CCDC_BLK_COMP_MASK) << + CCDC_BLK_COMP_GR_COMP_SHIFT) | + ((bcomp->r & CCDC_BLK_COMP_MASK) << + CCDC_BLK_COMP_R_COMP_SHIFT); + regw(val, BLKCMP0); +} + +/* + * ccdc_write_dfc_entry() + * write an entry in the dfc table. + */ +int ccdc_write_dfc_entry(int index, struct ccdc_vertical_dft *dfc) +{ +/* TODO This is to be re-visited and adjusted */ +#define DFC_WRITE_WAIT_COUNT 1000 + u32 val, count = DFC_WRITE_WAIT_COUNT; + + regw(dfc->dft_corr_vert[index], DFCMEM0); + regw(dfc->dft_corr_horz[index], DFCMEM1); + regw(dfc->dft_corr_sub1[index], DFCMEM2); + regw(dfc->dft_corr_sub2[index], DFCMEM3); + regw(dfc->dft_corr_sub3[index], DFCMEM4); + /* set WR bit to write */ + val = regr(DFCMEMCTL) | CCDC_DFCMEMCTL_DFCMWR_MASK; + regw(val, DFCMEMCTL); + + /* + * Assume, it is very short. If we get an error, we need to + * adjust this value + */ + while (regr(DFCMEMCTL) & CCDC_DFCMEMCTL_DFCMWR_MASK) + count--; + /* + * TODO We expect the count to be non-zero to be successful. Adjust + * the count if write requires more time + */ + + if (count) { + dev_err(dev, "defect table write timeout !!!\n"); + return -1; + } + return 0; +} + +/* + * ccdc_config_vdfc() + * configure parameters for Vertical Defect Correction + */ +static int ccdc_config_vdfc(struct ccdc_vertical_dft *dfc) +{ + u32 val; + int i; + + /* Configure General Defect Correction. The table used is from IPIPE */ + val = dfc->gen_dft_en & CCDC_DFCCTL_GDFCEN_MASK; + + /* Configure Vertical Defect Correction if needed */ + if (!dfc->ver_dft_en) { + /* Enable only General Defect Correction */ + regw(val, DFCCTL); + return 0; + } + + if (dfc->table_size > CCDC_DFT_TABLE_SIZE) + return -EINVAL; + + val |= CCDC_DFCCTL_VDFC_DISABLE; + val |= (dfc->dft_corr_ctl.vdfcsl & CCDC_DFCCTL_VDFCSL_MASK) << + CCDC_DFCCTL_VDFCSL_SHIFT; + val |= (dfc->dft_corr_ctl.vdfcuda & CCDC_DFCCTL_VDFCUDA_MASK) << + CCDC_DFCCTL_VDFCUDA_SHIFT; + val |= (dfc->dft_corr_ctl.vdflsft & CCDC_DFCCTL_VDFLSFT_MASK) << + CCDC_DFCCTL_VDFLSFT_SHIFT; + regw(val , DFCCTL); + + /* clear address ptr to offset 0 */ + val = CCDC_DFCMEMCTL_DFCMARST_MASK << CCDC_DFCMEMCTL_DFCMARST_SHIFT; + + /* write defect table entries */ + for (i = 0; i < dfc->table_size; i++) { + /* increment address for non zero index */ + if (i != 0) + val = CCDC_DFCMEMCTL_INC_ADDR; + regw(val, DFCMEMCTL); + if (ccdc_write_dfc_entry(i, dfc) < 0) + return -EFAULT; + } + + /* update saturation level and enable dfc */ + regw(dfc->saturation_ctl & CCDC_VDC_DFCVSAT_MASK, DFCVSAT); + val = regr(DFCCTL) | (CCDC_DFCCTL_VDFCEN_MASK << + CCDC_DFCCTL_VDFCEN_SHIFT); + regw(val, DFCCTL); + return 0; +} + +/* + * ccdc_config_csc() + * configure parameters for color space conversion + * Each register CSCM0-7 has two values in S8Q5 format. + */ +static void ccdc_config_csc(struct ccdc_csc *csc) +{ + u32 val1, val2; + int i; + + if (!csc->enable) + return; + + /* Enable the CSC sub-module */ + regw(CCDC_CSC_ENABLE, CSCCTL); + + /* Converting the co-eff as per the format of the register */ + for (i = 0; i < CCDC_CSC_COEFF_TABLE_SIZE; i++) { + if ((i % 2) == 0) { + /* CSCM - LSB */ + val1 = (csc->coeff[i].integer & + CCDC_CSC_COEF_INTEG_MASK) + << CCDC_CSC_COEF_INTEG_SHIFT; + /* + * convert decimal part to binary. Use 2 decimal + * precision, user values range from .00 - 0.99 + */ + val1 |= (((csc->coeff[i].decimal & + CCDC_CSC_COEF_DECIMAL_MASK) * + CCDC_CSC_DEC_MAX) / 100); + } else { + + /* CSCM - MSB */ + val2 = (csc->coeff[i].integer & + CCDC_CSC_COEF_INTEG_MASK) + << CCDC_CSC_COEF_INTEG_SHIFT; + val2 |= (((csc->coeff[i].decimal & + CCDC_CSC_COEF_DECIMAL_MASK) * + CCDC_CSC_DEC_MAX) / 100); + val2 <<= CCDC_CSCM_MSB_SHIFT; + val2 |= val1; + regw(val2, (CSCM0 + ((i - 1) << 1))); + } + } +} + +/* + * ccdc_config_color_patterns() + * configure parameters for color patterns + */ +static void ccdc_config_color_patterns(struct ccdc_col_pat *pat0, + struct ccdc_col_pat *pat1) +{ + u32 val; + + val = (pat0->olop | (pat0->olep << 2) | (pat0->elop << 4) | + (pat0->elep << 6) | (pat1->olop << 8) | (pat1->olep << 10) | + (pat1->elop << 12) | (pat1->elep << 14)); + regw(val, COLPTN); +} + +/* This function will configure CCDC for Raw mode image capture */ +static int ccdc_config_raw(void) +{ + struct ccdc_params_raw *params = &ccdc_hw_params_raw; + struct ccdc_config_params_raw *config_params = + &ccdc_hw_params_raw.config_params; + unsigned int val; + + dev_dbg(dev, "\nStarting ccdc_config_raw..."); + + /* restore power on defaults to register */ + ccdc_restore_defaults(); + + /* CCDCFG register: + * set CCD Not to swap input since input is RAW data + * set FID detection function to Latch at V-Sync + * set WENLOG - ccdc valid area to AND + * set TRGSEL to WENBIT + * set EXTRG to DISABLE + * disable latching function on VSYNC - shadowed registers + */ + regw(CCDC_YCINSWP_RAW | CCDC_CCDCFG_FIDMD_LATCH_VSYNC | + CCDC_CCDCFG_WENLOG_AND | CCDC_CCDCFG_TRGSEL_WEN | + CCDC_CCDCFG_EXTRG_DISABLE | CCDC_LATCH_ON_VSYNC_DISABLE, CCDCFG); + + /* + * Set VDHD direction to input, input type to raw input + * normal data polarity, do not use external WEN + */ + val = (CCDC_VDHDOUT_INPUT | CCDC_RAW_IP_MODE | CCDC_DATAPOL_NORMAL | + CCDC_EXWEN_DISABLE); + + /* + * Configure the vertical sync polarity (MODESET.VDPOL), horizontal + * sync polarity (MODESET.HDPOL), field id polarity (MODESET.FLDPOL), + * frame format(progressive or interlace), & pixel format (Input mode) + */ + val |= (((params->vd_pol & CCDC_VD_POL_MASK) << CCDC_VD_POL_SHIFT) | + ((params->hd_pol & CCDC_HD_POL_MASK) << CCDC_HD_POL_SHIFT) | + ((params->fid_pol & CCDC_FID_POL_MASK) << CCDC_FID_POL_SHIFT) | + ((params->frm_fmt & CCDC_FRM_FMT_MASK) << CCDC_FRM_FMT_SHIFT) | + ((params->pix_fmt & CCDC_PIX_FMT_MASK) << CCDC_PIX_FMT_SHIFT)); + + /* set pack for alaw compression */ + if ((config_params->data_sz == CCDC_DATA_8BITS) || + config_params->alaw.enable) + val |= CCDC_DATA_PACK_ENABLE; + + /* Configure for LPF */ + if (config_params->lpf_enable) + val |= (config_params->lpf_enable & CCDC_LPF_MASK) << + CCDC_LPF_SHIFT; + + /* Configure the data shift */ + val |= (config_params->datasft & CCDC_DATASFT_MASK) << + CCDC_DATASFT_SHIFT; + regw(val , MODESET); + dev_dbg(dev, "\nWriting 0x%x to MODESET...\n", val); + + /* Configure the Median Filter threshold */ + regw((config_params->med_filt_thres) & CCDC_MED_FILT_THRESH, MEDFILT); + + /* Configure GAMMAWD register. defaur 11-2, and Mosaic cfa pattern */ + val = CCDC_GAMMA_BITS_11_2 << CCDC_GAMMAWD_INPUT_SHIFT | + CCDC_CFA_MOSAIC; + + /* Enable and configure aLaw register if needed */ + if (config_params->alaw.enable) { + val |= (CCDC_ALAW_ENABLE | + ((config_params->alaw.gama_wd & + CCDC_ALAW_GAMA_WD_MASK) << + CCDC_GAMMAWD_INPUT_SHIFT)); + } + + /* Configure Median filter1 & filter2 */ + val |= ((config_params->mfilt1 << CCDC_MFILT1_SHIFT) | + (config_params->mfilt2 << CCDC_MFILT2_SHIFT)); + + regw(val, GAMMAWD); + dev_dbg(dev, "\nWriting 0x%x to GAMMAWD...\n", val); + + /* configure video window */ + ccdc_setwin(¶ms->win, params->frm_fmt, 1); + + /* Optical Clamp Averaging */ + ccdc_config_black_clamp(&config_params->blk_clamp); + + /* Black level compensation */ + ccdc_config_black_compense(&config_params->blk_comp); + + /* Vertical Defect Correction if needed */ + if (ccdc_config_vdfc(&config_params->vertical_dft) < 0) + return -EFAULT; + + /* color space conversion */ + ccdc_config_csc(&config_params->csc); + + /* color pattern */ + ccdc_config_color_patterns(&config_params->col_pat_field0, + &config_params->col_pat_field1); + + /* Configure the Gain & offset control */ + ccdc_config_gain_offset(); + + dev_dbg(dev, "\nWriting %x to COLPTN...\n", val); + + /* Configure DATAOFST register */ + val = (config_params->data_offset.horz_offset & CCDC_DATAOFST_MASK) << + CCDC_DATAOFST_H_SHIFT; + val |= (config_params->data_offset.vert_offset & CCDC_DATAOFST_MASK) << + CCDC_DATAOFST_V_SHIFT; + regw(val, DATAOFST); + + /* configuring HSIZE register */ + val = (params->horz_flip_enable & CCDC_HSIZE_FLIP_MASK) << + CCDC_HSIZE_FLIP_SHIFT; + + /* If pack 8 is enable then 1 pixel will take 1 byte */ + if ((config_params->data_sz == CCDC_DATA_8BITS) || + config_params->alaw.enable) { + val |= (((params->win.width) + 31) >> 5) & + CCDC_HSIZE_VAL_MASK; + + /* adjust to multiple of 32 */ + dev_dbg(dev, "\nWriting 0x%x to HSIZE...\n", + (((params->win.width) + 31) >> 5) & + CCDC_HSIZE_VAL_MASK); + } else { + /* else one pixel will take 2 byte */ + val |= (((params->win.width * 2) + 31) >> 5) & + CCDC_HSIZE_VAL_MASK; + + dev_dbg(dev, "\nWriting 0x%x to HSIZE...\n", + (((params->win.width * 2) + 31) >> 5) & + CCDC_HSIZE_VAL_MASK); + } + regw(val, HSIZE); + + /* Configure SDOFST register */ + if (params->frm_fmt == CCDC_FRMFMT_INTERLACED) { + if (params->image_invert_enable) { + /* For interlace inverse mode */ + regw(CCDC_SDOFST_INTERLACE_INVERSE, SDOFST); + dev_dbg(dev, "\nWriting %x to SDOFST...\n", + CCDC_SDOFST_INTERLACE_INVERSE); + } else { + /* For interlace non inverse mode */ + regw(CCDC_SDOFST_INTERLACE_NORMAL, SDOFST); + dev_dbg(dev, "\nWriting %x to SDOFST...\n", + CCDC_SDOFST_INTERLACE_NORMAL); + } + } else if (params->frm_fmt == CCDC_FRMFMT_PROGRESSIVE) { + if (params->image_invert_enable) { + /* For progessive inverse mode */ + regw(CCDC_SDOFST_PROGRESSIVE_INVERSE, SDOFST); + dev_dbg(dev, "\nWriting %x to SDOFST...\n", + CCDC_SDOFST_PROGRESSIVE_INVERSE); + } else { + /* For progessive non inverse mode */ + regw(CCDC_SDOFST_PROGRESSIVE_NORMAL, SDOFST); + dev_dbg(dev, "\nWriting %x to SDOFST...\n", + CCDC_SDOFST_PROGRESSIVE_NORMAL); + } + } + dev_dbg(dev, "\nend of ccdc_config_raw..."); + return 0; +} + +static int ccdc_configure(void) +{ + if (ccdc_if_type == VPFE_RAW_BAYER) + return ccdc_config_raw(); + else + ccdc_config_ycbcr(); + return 0; +} + +static int ccdc_set_buftype(enum ccdc_buftype buf_type) +{ + if (ccdc_if_type == VPFE_RAW_BAYER) + ccdc_hw_params_raw.buf_type = buf_type; + else + ccdc_hw_params_ycbcr.buf_type = buf_type; + return 0; +} +static enum ccdc_buftype ccdc_get_buftype(void) +{ + if (ccdc_if_type == VPFE_RAW_BAYER) + return ccdc_hw_params_raw.buf_type; + return ccdc_hw_params_ycbcr.buf_type; +} + +static int ccdc_enum_pix(u32 *pix, int i) +{ + int ret = -EINVAL; + if (ccdc_if_type == VPFE_RAW_BAYER) { + if (i < ARRAY_SIZE(ccdc_raw_bayer_pix_formats)) { + *pix = ccdc_raw_bayer_pix_formats[i]; + ret = 0; + } + } else { + if (i < ARRAY_SIZE(ccdc_raw_yuv_pix_formats)) { + *pix = ccdc_raw_yuv_pix_formats[i]; + ret = 0; + } + } + return ret; +} + +static int ccdc_set_pixel_format(u32 pixfmt) +{ + struct ccdc_a_law *alaw = + &ccdc_hw_params_raw.config_params.alaw; + + if (ccdc_if_type == VPFE_RAW_BAYER) { + ccdc_hw_params_raw.pix_fmt = CCDC_PIXFMT_RAW; + if (pixfmt == V4L2_PIX_FMT_SBGGR8) + alaw->enable = 1; + else if (pixfmt != V4L2_PIX_FMT_SBGGR16) + return -EINVAL; + } else { + if (pixfmt == V4L2_PIX_FMT_YUYV) + ccdc_hw_params_ycbcr.pix_order = CCDC_PIXORDER_YCBYCR; + else if (pixfmt == V4L2_PIX_FMT_UYVY) + ccdc_hw_params_ycbcr.pix_order = CCDC_PIXORDER_CBYCRY; + else + return -EINVAL; + } + return 0; +} +static u32 ccdc_get_pixel_format(void) +{ + struct ccdc_a_law *alaw = + &ccdc_hw_params_raw.config_params.alaw; + u32 pixfmt; + + if (ccdc_if_type == VPFE_RAW_BAYER) + if (alaw->enable) + pixfmt = V4L2_PIX_FMT_SBGGR8; + else + pixfmt = V4L2_PIX_FMT_SBGGR16; + else { + if (ccdc_hw_params_ycbcr.pix_order == CCDC_PIXORDER_YCBYCR) + pixfmt = V4L2_PIX_FMT_YUYV; + else + pixfmt = V4L2_PIX_FMT_UYVY; + } + return pixfmt; +} +static int ccdc_set_image_window(struct v4l2_rect *win) +{ + if (ccdc_if_type == VPFE_RAW_BAYER) + ccdc_hw_params_raw.win = *win; + else + ccdc_hw_params_ycbcr.win = *win; + return 0; +} + +static void ccdc_get_image_window(struct v4l2_rect *win) +{ + if (ccdc_if_type == VPFE_RAW_BAYER) + *win = ccdc_hw_params_raw.win; + else + *win = ccdc_hw_params_ycbcr.win; +} + +static unsigned int ccdc_get_line_length(void) +{ + struct ccdc_config_params_raw *config_params = + &ccdc_hw_params_raw.config_params; + unsigned int len; + + if (ccdc_if_type == VPFE_RAW_BAYER) { + if ((config_params->alaw.enable) || + (config_params->data_sz == CCDC_DATA_8BITS)) + len = ccdc_hw_params_raw.win.width; + else + len = ccdc_hw_params_raw.win.width * 2; + } else + len = ccdc_hw_params_ycbcr.win.width * 2; + return ALIGN(len, 32); +} + +static int ccdc_set_frame_format(enum ccdc_frmfmt frm_fmt) +{ + if (ccdc_if_type == VPFE_RAW_BAYER) + ccdc_hw_params_raw.frm_fmt = frm_fmt; + else + ccdc_hw_params_ycbcr.frm_fmt = frm_fmt; + return 0; +} + +static enum ccdc_frmfmt ccdc_get_frame_format(void) +{ + if (ccdc_if_type == VPFE_RAW_BAYER) + return ccdc_hw_params_raw.frm_fmt; + else + return ccdc_hw_params_ycbcr.frm_fmt; +} + +static int ccdc_getfid(void) +{ + return (regr(MODESET) >> 15) & 1; +} + +/* misc operations */ +static inline void ccdc_setfbaddr(unsigned long addr) +{ + regw((addr >> 21) & 0x007f, STADRH); + regw((addr >> 5) & 0x0ffff, STADRL); +} + +static int ccdc_set_hw_if_params(struct vpfe_hw_if_param *params) +{ + ccdc_if_type = params->if_type; + + switch (params->if_type) { + case VPFE_BT656: + case VPFE_YCBCR_SYNC_16: + case VPFE_YCBCR_SYNC_8: + ccdc_hw_params_ycbcr.vd_pol = params->vdpol; + ccdc_hw_params_ycbcr.hd_pol = params->hdpol; + break; + default: + /* TODO add support for raw bayer here */ + return -EINVAL; + } + return 0; +} + +static struct ccdc_hw_device ccdc_hw_dev = { + .name = "DM355 CCDC", + .owner = THIS_MODULE, + .hw_ops = { + .open = ccdc_open, + .close = ccdc_close, + .set_ccdc_base = ccdc_set_ccdc_base, + .enable = ccdc_enable, + .enable_out_to_sdram = ccdc_enable_output_to_sdram, + .set_hw_if_params = ccdc_set_hw_if_params, + .set_params = ccdc_set_params, + .configure = ccdc_configure, + .set_buftype = ccdc_set_buftype, + .get_buftype = ccdc_get_buftype, + .enum_pix = ccdc_enum_pix, + .set_pixel_format = ccdc_set_pixel_format, + .get_pixel_format = ccdc_get_pixel_format, + .set_frame_format = ccdc_set_frame_format, + .get_frame_format = ccdc_get_frame_format, + .set_image_window = ccdc_set_image_window, + .get_image_window = ccdc_get_image_window, + .get_line_length = ccdc_get_line_length, + .setfbaddr = ccdc_setfbaddr, + .getfid = ccdc_getfid, + }, +}; + +static int dm355_ccdc_init(void) +{ + printk(KERN_NOTICE "dm355_ccdc_init\n"); + if (vpfe_register_ccdc_device(&ccdc_hw_dev) < 0) + return -1; + printk(KERN_NOTICE "%s is registered with vpfe.\n", + ccdc_hw_dev.name); + return 0; +} + +static void dm355_ccdc_exit(void) +{ + vpfe_unregister_ccdc_device(&ccdc_hw_dev); +} + +module_init(dm355_ccdc_init); +module_exit(dm355_ccdc_exit); diff --git a/linux/drivers/media/video/davinci/dm355_ccdc_regs.h b/linux/drivers/media/video/davinci/dm355_ccdc_regs.h new file mode 100644 index 000000000..d6d2ef053 --- /dev/null +++ b/linux/drivers/media/video/davinci/dm355_ccdc_regs.h @@ -0,0 +1,310 @@ +/* + * Copyright (C) 2005-2009 Texas Instruments Inc + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef _DM355_CCDC_REGS_H +#define _DM355_CCDC_REGS_H + +/**************************************************************************\ +* Register OFFSET Definitions +\**************************************************************************/ +#define SYNCEN 0x00 +#define MODESET 0x04 +#define HDWIDTH 0x08 +#define VDWIDTH 0x0c +#define PPLN 0x10 +#define LPFR 0x14 +#define SPH 0x18 +#define NPH 0x1c +#define SLV0 0x20 +#define SLV1 0x24 +#define NLV 0x28 +#define CULH 0x2c +#define CULV 0x30 +#define HSIZE 0x34 +#define SDOFST 0x38 +#define STADRH 0x3c +#define STADRL 0x40 +#define CLAMP 0x44 +#define DCSUB 0x48 +#define COLPTN 0x4c +#define BLKCMP0 0x50 +#define BLKCMP1 0x54 +#define MEDFILT 0x58 +#define RYEGAIN 0x5c +#define GRCYGAIN 0x60 +#define GBGGAIN 0x64 +#define BMGGAIN 0x68 +#define OFFSET 0x6c +#define OUTCLIP 0x70 +#define VDINT0 0x74 +#define VDINT1 0x78 +#define RSV0 0x7c +#define GAMMAWD 0x80 +#define REC656IF 0x84 +#define CCDCFG 0x88 +#define FMTCFG 0x8c +#define FMTPLEN 0x90 +#define FMTSPH 0x94 +#define FMTLNH 0x98 +#define FMTSLV 0x9c +#define FMTLNV 0xa0 +#define FMTRLEN 0xa4 +#define FMTHCNT 0xa8 +#define FMT_ADDR_PTR_B 0xac +#define FMT_ADDR_PTR(i) (FMT_ADDR_PTR_B + (i * 4)) +#define FMTPGM_VF0 0xcc +#define FMTPGM_VF1 0xd0 +#define FMTPGM_AP0 0xd4 +#define FMTPGM_AP1 0xd8 +#define FMTPGM_AP2 0xdc +#define FMTPGM_AP3 0xe0 +#define FMTPGM_AP4 0xe4 +#define FMTPGM_AP5 0xe8 +#define FMTPGM_AP6 0xec +#define FMTPGM_AP7 0xf0 +#define LSCCFG1 0xf4 +#define LSCCFG2 0xf8 +#define LSCH0 0xfc +#define LSCV0 0x100 +#define LSCKH 0x104 +#define LSCKV 0x108 +#define LSCMEMCTL 0x10c +#define LSCMEMD 0x110 +#define LSCMEMQ 0x114 +#define DFCCTL 0x118 +#define DFCVSAT 0x11c +#define DFCMEMCTL 0x120 +#define DFCMEM0 0x124 +#define DFCMEM1 0x128 +#define DFCMEM2 0x12c +#define DFCMEM3 0x130 +#define DFCMEM4 0x134 +#define CSCCTL 0x138 +#define CSCM0 0x13c +#define CSCM1 0x140 +#define CSCM2 0x144 +#define CSCM3 0x148 +#define CSCM4 0x14c +#define CSCM5 0x150 +#define CSCM6 0x154 +#define CSCM7 0x158 +#define DATAOFST 0x15c +#define CCDC_REG_LAST DATAOFST +/************************************************************** +* Define for various register bit mask and shifts for CCDC +* +**************************************************************/ +#define CCDC_RAW_IP_MODE 0 +#define CCDC_VDHDOUT_INPUT 0 +#define CCDC_YCINSWP_RAW (0 << 4) +#define CCDC_EXWEN_DISABLE 0 +#define CCDC_DATAPOL_NORMAL 0 +#define CCDC_CCDCFG_FIDMD_LATCH_VSYNC 0 +#define CCDC_CCDCFG_FIDMD_NO_LATCH_VSYNC (1 << 6) +#define CCDC_CCDCFG_WENLOG_AND 0 +#define CCDC_CCDCFG_TRGSEL_WEN 0 +#define CCDC_CCDCFG_EXTRG_DISABLE 0 +#define CCDC_CFA_MOSAIC 0 +#define CCDC_Y8POS_SHIFT 11 + +#define CCDC_VDC_DFCVSAT_MASK 0x3fff +#define CCDC_DATAOFST_MASK 0x0ff +#define CCDC_DATAOFST_H_SHIFT 0 +#define CCDC_DATAOFST_V_SHIFT 8 +#define CCDC_GAMMAWD_CFA_MASK 1 +#define CCDC_GAMMAWD_CFA_SHIFT 5 +#define CCDC_GAMMAWD_INPUT_SHIFT 2 +#define CCDC_FID_POL_MASK 1 +#define CCDC_FID_POL_SHIFT 4 +#define CCDC_HD_POL_MASK 1 +#define CCDC_HD_POL_SHIFT 3 +#define CCDC_VD_POL_MASK 1 +#define CCDC_VD_POL_SHIFT 2 +#define CCDC_VD_POL_NEGATIVE (1 << 2) +#define CCDC_FRM_FMT_MASK 1 +#define CCDC_FRM_FMT_SHIFT 7 +#define CCDC_DATA_SZ_MASK 7 +#define CCDC_DATA_SZ_SHIFT 8 +#define CCDC_VDHDOUT_MASK 1 +#define CCDC_VDHDOUT_SHIFT 0 +#define CCDC_EXWEN_MASK 1 +#define CCDC_EXWEN_SHIFT 5 +#define CCDC_INPUT_MODE_MASK 3 +#define CCDC_INPUT_MODE_SHIFT 12 +#define CCDC_PIX_FMT_MASK 3 +#define CCDC_PIX_FMT_SHIFT 12 +#define CCDC_DATAPOL_MASK 1 +#define CCDC_DATAPOL_SHIFT 6 +#define CCDC_WEN_ENABLE (1 << 1) +#define CCDC_VDHDEN_ENABLE (1 << 16) +#define CCDC_LPF_ENABLE (1 << 14) +#define CCDC_ALAW_ENABLE 1 +#define CCDC_ALAW_GAMA_WD_MASK 7 +#define CCDC_REC656IF_BT656_EN 3 + +#define CCDC_FMTCFG_FMTMODE_MASK 3 +#define CCDC_FMTCFG_FMTMODE_SHIFT 1 +#define CCDC_FMTCFG_LNUM_MASK 3 +#define CCDC_FMTCFG_LNUM_SHIFT 4 +#define CCDC_FMTCFG_ADDRINC_MASK 7 +#define CCDC_FMTCFG_ADDRINC_SHIFT 8 + +#define CCDC_CCDCFG_FIDMD_SHIFT 6 +#define CCDC_CCDCFG_WENLOG_SHIFT 8 +#define CCDC_CCDCFG_TRGSEL_SHIFT 9 +#define CCDC_CCDCFG_EXTRG_SHIFT 10 +#define CCDC_CCDCFG_MSBINVI_SHIFT 13 + +#define CCDC_HSIZE_FLIP_SHIFT 12 +#define CCDC_HSIZE_FLIP_MASK 1 +#define CCDC_HSIZE_VAL_MASK 0xFFF +#define CCDC_SDOFST_FIELD_INTERLEAVED 0x249 +#define CCDC_SDOFST_INTERLACE_INVERSE 0x4B6D +#define CCDC_SDOFST_INTERLACE_NORMAL 0x0B6D +#define CCDC_SDOFST_PROGRESSIVE_INVERSE 0x4000 +#define CCDC_SDOFST_PROGRESSIVE_NORMAL 0 +#define CCDC_START_PX_HOR_MASK 0x7FFF +#define CCDC_NUM_PX_HOR_MASK 0x7FFF +#define CCDC_START_VER_ONE_MASK 0x7FFF +#define CCDC_START_VER_TWO_MASK 0x7FFF +#define CCDC_NUM_LINES_VER 0x7FFF + +#define CCDC_BLK_CLAMP_ENABLE (1 << 15) +#define CCDC_BLK_SGAIN_MASK 0x1F +#define CCDC_BLK_ST_PXL_MASK 0x1FFF +#define CCDC_BLK_SAMPLE_LN_MASK 3 +#define CCDC_BLK_SAMPLE_LN_SHIFT 13 + +#define CCDC_NUM_LINE_CALC_MASK 3 +#define CCDC_NUM_LINE_CALC_SHIFT 14 + +#define CCDC_BLK_DC_SUB_MASK 0x3FFF +#define CCDC_BLK_COMP_MASK 0xFF +#define CCDC_BLK_COMP_GB_COMP_SHIFT 8 +#define CCDC_BLK_COMP_GR_COMP_SHIFT 0 +#define CCDC_BLK_COMP_R_COMP_SHIFT 8 +#define CCDC_LATCH_ON_VSYNC_DISABLE (1 << 15) +#define CCDC_LATCH_ON_VSYNC_ENABLE (0 << 15) +#define CCDC_FPC_ENABLE (1 << 15) +#define CCDC_FPC_FPC_NUM_MASK 0x7FFF +#define CCDC_DATA_PACK_ENABLE (1 << 11) +#define CCDC_FMT_HORZ_FMTLNH_MASK 0x1FFF +#define CCDC_FMT_HORZ_FMTSPH_MASK 0x1FFF +#define CCDC_FMT_HORZ_FMTSPH_SHIFT 16 +#define CCDC_FMT_VERT_FMTLNV_MASK 0x1FFF +#define CCDC_FMT_VERT_FMTSLV_MASK 0x1FFF +#define CCDC_FMT_VERT_FMTSLV_SHIFT 16 +#define CCDC_VP_OUT_VERT_NUM_MASK 0x3FFF +#define CCDC_VP_OUT_VERT_NUM_SHIFT 17 +#define CCDC_VP_OUT_HORZ_NUM_MASK 0x1FFF +#define CCDC_VP_OUT_HORZ_NUM_SHIFT 4 +#define CCDC_VP_OUT_HORZ_ST_MASK 0xF + +#define CCDC_CSC_COEF_INTEG_MASK 7 +#define CCDC_CSC_COEF_DECIMAL_MASK 0x1f +#define CCDC_CSC_COEF_INTEG_SHIFT 5 +#define CCDC_CSCM_MSB_SHIFT 8 +#define CCDC_CSC_ENABLE 1 +#define CCDC_CSC_DEC_MAX 32 + +#define CCDC_MFILT1_SHIFT 10 +#define CCDC_MFILT2_SHIFT 8 +#define CCDC_MED_FILT_THRESH 0x3FFF +#define CCDC_LPF_MASK 1 +#define CCDC_LPF_SHIFT 14 +#define CCDC_OFFSET_MASK 0x3FF +#define CCDC_DATASFT_MASK 7 +#define CCDC_DATASFT_SHIFT 8 + +#define CCDC_DF_ENABLE 1 + +#define CCDC_FMTPLEN_P0_MASK 0xF +#define CCDC_FMTPLEN_P1_MASK 0xF +#define CCDC_FMTPLEN_P2_MASK 7 +#define CCDC_FMTPLEN_P3_MASK 7 +#define CCDC_FMTPLEN_P0_SHIFT 0 +#define CCDC_FMTPLEN_P1_SHIFT 4 +#define CCDC_FMTPLEN_P2_SHIFT 8 +#define CCDC_FMTPLEN_P3_SHIFT 12 + +#define CCDC_FMTSPH_MASK 0x1FFF +#define CCDC_FMTLNH_MASK 0x1FFF +#define CCDC_FMTSLV_MASK 0x1FFF +#define CCDC_FMTLNV_MASK 0x7FFF +#define CCDC_FMTRLEN_MASK 0x1FFF +#define CCDC_FMTHCNT_MASK 0x1FFF + +#define CCDC_ADP_INIT_MASK 0x1FFF +#define CCDC_ADP_LINE_SHIFT 13 +#define CCDC_ADP_LINE_MASK 3 +#define CCDC_FMTPGN_APTR_MASK 7 + +#define CCDC_DFCCTL_GDFCEN_MASK 1 +#define CCDC_DFCCTL_VDFCEN_MASK 1 +#define CCDC_DFCCTL_VDFC_DISABLE (0 << 4) +#define CCDC_DFCCTL_VDFCEN_SHIFT 4 +#define CCDC_DFCCTL_VDFCSL_MASK 3 +#define CCDC_DFCCTL_VDFCSL_SHIFT 5 +#define CCDC_DFCCTL_VDFCUDA_MASK 1 +#define CCDC_DFCCTL_VDFCUDA_SHIFT 7 +#define CCDC_DFCCTL_VDFLSFT_MASK 3 +#define CCDC_DFCCTL_VDFLSFT_SHIFT 8 +#define CCDC_DFCMEMCTL_DFCMARST_MASK 1 +#define CCDC_DFCMEMCTL_DFCMARST_SHIFT 2 +#define CCDC_DFCMEMCTL_DFCMWR_MASK 1 +#define CCDC_DFCMEMCTL_DFCMWR_SHIFT 0 +#define CCDC_DFCMEMCTL_INC_ADDR (0 << 2) + +#define CCDC_LSCCFG_GFTSF_MASK 7 +#define CCDC_LSCCFG_GFTSF_SHIFT 1 +#define CCDC_LSCCFG_GFTINV_MASK 0xf +#define CCDC_LSCCFG_GFTINV_SHIFT 4 +#define CCDC_LSC_GFTABLE_SEL_MASK 3 +#define CCDC_LSC_GFTABLE_EPEL_SHIFT 8 +#define CCDC_LSC_GFTABLE_OPEL_SHIFT 10 +#define CCDC_LSC_GFTABLE_EPOL_SHIFT 12 +#define CCDC_LSC_GFTABLE_OPOL_SHIFT 14 +#define CCDC_LSC_GFMODE_MASK 3 +#define CCDC_LSC_GFMODE_SHIFT 4 +#define CCDC_LSC_DISABLE 0 +#define CCDC_LSC_ENABLE 1 +#define CCDC_LSC_TABLE1_SLC 0 +#define CCDC_LSC_TABLE2_SLC 1 +#define CCDC_LSC_TABLE3_SLC 2 +#define CCDC_LSC_MEMADDR_RESET (1 << 2) +#define CCDC_LSC_MEMADDR_INCR (0 << 2) +#define CCDC_LSC_FRAC_MASK_T1 0xFF +#define CCDC_LSC_INT_MASK 3 +#define CCDC_LSC_FRAC_MASK 0x3FFF +#define CCDC_LSC_CENTRE_MASK 0x3FFF +#define CCDC_LSC_COEF_MASK 0xff +#define CCDC_LSC_COEFL_SHIFT 0 +#define CCDC_LSC_COEFU_SHIFT 8 +#define CCDC_GAIN_MASK 0x7FF +#define CCDC_SYNCEN_VDHDEN_MASK (1 << 0) +#define CCDC_SYNCEN_WEN_MASK (1 << 1) +#define CCDC_SYNCEN_WEN_SHIFT 1 + +/* Power on Defaults in hardware */ +#define MODESET_DEFAULT 0x200 +#define CULH_DEFAULT 0xFFFF +#define CULV_DEFAULT 0xFF +#define GAIN_DEFAULT 256 +#define OUTCLIP_DEFAULT 0x3FFF +#define LSCCFG2_DEFAULT 0xE + +#endif -- cgit v1.2.3 From 7a9ed65a4e1e7c25cab4104eae7bea6b400389d2 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 19 Jun 2009 14:18:14 +0200 Subject: v4l: dm644x ccdc module for vpfe capture driver From: Muralidharan Karicheri This is the hw module for DM644x CCDC. This registers with the vpfe capture driver and provides a set of hw_ops to configure CCDC for a specific decoder device connected to the VPFE. Reviewed by: Hans Verkuil Reviewed by: Laurent Pinchart Priority: normal Signed-off-by: Muralidharan Karicheri Signed-off-by: Hans Verkuil --- linux/drivers/media/video/davinci/dm644x_ccdc.c | 878 +++++++++++++++++++++ .../drivers/media/video/davinci/dm644x_ccdc_regs.h | 145 ++++ 2 files changed, 1023 insertions(+) create mode 100644 linux/drivers/media/video/davinci/dm644x_ccdc.c create mode 100644 linux/drivers/media/video/davinci/dm644x_ccdc_regs.h (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/davinci/dm644x_ccdc.c b/linux/drivers/media/video/davinci/dm644x_ccdc.c new file mode 100644 index 000000000..2f19a919f --- /dev/null +++ b/linux/drivers/media/video/davinci/dm644x_ccdc.c @@ -0,0 +1,878 @@ +/* + * Copyright (C) 2006-2009 Texas Instruments Inc + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * CCDC hardware module for DM6446 + * ------------------------------ + * + * This module is for configuring CCD controller of DM6446 VPFE to capture + * Raw yuv or Bayer RGB data from a decoder. CCDC has several modules + * such as Defect Pixel Correction, Color Space Conversion etc to + * pre-process the Raw Bayer RGB data, before writing it to SDRAM. This + * module also allows application to configure individual + * module parameters through VPFE_CMD_S_CCDC_RAW_PARAMS IOCTL. + * To do so, application includes dm644x_ccdc.h and vpfe_capture.h header + * files. The setparams() API is called by vpfe_capture driver + * to configure module parameters. This file is named DM644x so that other + * variants such DM6443 may be supported using the same module. + * + * TODO: Test Raw bayer parameter settings and bayer capture + * Split module parameter structure to module specific ioctl structs + * investigate if enum used for user space type definition + * to be replaced by #defines or integer + */ +#include +#include +#include +#include +#include +#include "dm644x_ccdc_regs.h" +#include "ccdc_hw_device.h" + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("CCDC Driver for DM6446"); +MODULE_AUTHOR("Texas Instruments"); + +static struct device *dev; + +/* Object for CCDC raw mode */ +static struct ccdc_params_raw ccdc_hw_params_raw = { + .pix_fmt = CCDC_PIXFMT_RAW, + .frm_fmt = CCDC_FRMFMT_PROGRESSIVE, + .win = CCDC_WIN_VGA, + .fid_pol = VPFE_PINPOL_POSITIVE, + .vd_pol = VPFE_PINPOL_POSITIVE, + .hd_pol = VPFE_PINPOL_POSITIVE, + .config_params = { + .data_sz = CCDC_DATA_10BITS, + }, +}; + +/* Object for CCDC ycbcr mode */ +static struct ccdc_params_ycbcr ccdc_hw_params_ycbcr = { + .pix_fmt = CCDC_PIXFMT_YCBCR_8BIT, + .frm_fmt = CCDC_FRMFMT_INTERLACED, + .win = CCDC_WIN_PAL, + .fid_pol = VPFE_PINPOL_POSITIVE, + .vd_pol = VPFE_PINPOL_POSITIVE, + .hd_pol = VPFE_PINPOL_POSITIVE, + .bt656_enable = 1, + .pix_order = CCDC_PIXORDER_CBYCRY, + .buf_type = CCDC_BUFTYPE_FLD_INTERLEAVED +}; + +#define CCDC_MAX_RAW_YUV_FORMATS 2 + +/* Raw Bayer formats */ +static u32 ccdc_raw_bayer_pix_formats[] = + {V4L2_PIX_FMT_SBGGR8, V4L2_PIX_FMT_SBGGR16}; + +/* Raw YUV formats */ +static u32 ccdc_raw_yuv_pix_formats[] = + {V4L2_PIX_FMT_UYVY, V4L2_PIX_FMT_YUYV}; + +static void *__iomem ccdc_base_addr; +static int ccdc_addr_size; +static enum vpfe_hw_if_type ccdc_if_type; + +/* register access routines */ +static inline u32 regr(u32 offset) +{ + return __raw_readl(ccdc_base_addr + offset); +} + +static inline void regw(u32 val, u32 offset) +{ + __raw_writel(val, ccdc_base_addr + offset); +} + +static void ccdc_set_ccdc_base(void *addr, int size) +{ + ccdc_base_addr = addr; + ccdc_addr_size = size; +} + +static void ccdc_enable(int flag) +{ + regw(flag, CCDC_PCR); +} + +static void ccdc_enable_vport(int flag) +{ + if (flag) + /* enable video port */ + regw(CCDC_ENABLE_VIDEO_PORT, CCDC_FMTCFG); + else + regw(CCDC_DISABLE_VIDEO_PORT, CCDC_FMTCFG); +} + +/* + * ccdc_setwin() + * This function will configure the window size + * to be capture in CCDC reg + */ +void ccdc_setwin(struct v4l2_rect *image_win, + enum ccdc_frmfmt frm_fmt, + int ppc) +{ + int horz_start, horz_nr_pixels; + int vert_start, vert_nr_lines; + int val = 0, mid_img = 0; + + dev_dbg(dev, "\nStarting ccdc_setwin..."); + /* + * ppc - per pixel count. indicates how many pixels per cell + * output to SDRAM. example, for ycbcr, it is one y and one c, so 2. + * raw capture this is 1 + */ + horz_start = image_win->left << (ppc - 1); + horz_nr_pixels = (image_win->width << (ppc - 1)) - 1; + regw((horz_start << CCDC_HORZ_INFO_SPH_SHIFT) | horz_nr_pixels, + CCDC_HORZ_INFO); + + vert_start = image_win->top; + + if (frm_fmt == CCDC_FRMFMT_INTERLACED) { + vert_nr_lines = (image_win->height >> 1) - 1; + vert_start >>= 1; + /* Since first line doesn't have any data */ + vert_start += 1; + /* configure VDINT0 */ + val = (vert_start << CCDC_VDINT_VDINT0_SHIFT); + regw(val, CCDC_VDINT); + + } else { + /* Since first line doesn't have any data */ + vert_start += 1; + vert_nr_lines = image_win->height - 1; + /* + * configure VDINT0 and VDINT1. VDINT1 will be at half + * of image height + */ + mid_img = vert_start + (image_win->height / 2); + val = (vert_start << CCDC_VDINT_VDINT0_SHIFT) | + (mid_img & CCDC_VDINT_VDINT1_MASK); + regw(val, CCDC_VDINT); + + } + regw((vert_start << CCDC_VERT_START_SLV0_SHIFT) | vert_start, + CCDC_VERT_START); + regw(vert_nr_lines, CCDC_VERT_LINES); + dev_dbg(dev, "\nEnd of ccdc_setwin..."); +} + +static void ccdc_readregs(void) +{ + unsigned int val = 0; + + val = regr(CCDC_ALAW); + dev_notice(dev, "\nReading 0x%x to ALAW...\n", val); + val = regr(CCDC_CLAMP); + dev_notice(dev, "\nReading 0x%x to CLAMP...\n", val); + val = regr(CCDC_DCSUB); + dev_notice(dev, "\nReading 0x%x to DCSUB...\n", val); + val = regr(CCDC_BLKCMP); + dev_notice(dev, "\nReading 0x%x to BLKCMP...\n", val); + val = regr(CCDC_FPC_ADDR); + dev_notice(dev, "\nReading 0x%x to FPC_ADDR...\n", val); + val = regr(CCDC_FPC); + dev_notice(dev, "\nReading 0x%x to FPC...\n", val); + val = regr(CCDC_FMTCFG); + dev_notice(dev, "\nReading 0x%x to FMTCFG...\n", val); + val = regr(CCDC_COLPTN); + dev_notice(dev, "\nReading 0x%x to COLPTN...\n", val); + val = regr(CCDC_FMT_HORZ); + dev_notice(dev, "\nReading 0x%x to FMT_HORZ...\n", val); + val = regr(CCDC_FMT_VERT); + dev_notice(dev, "\nReading 0x%x to FMT_VERT...\n", val); + val = regr(CCDC_HSIZE_OFF); + dev_notice(dev, "\nReading 0x%x to HSIZE_OFF...\n", val); + val = regr(CCDC_SDOFST); + dev_notice(dev, "\nReading 0x%x to SDOFST...\n", val); + val = regr(CCDC_VP_OUT); + dev_notice(dev, "\nReading 0x%x to VP_OUT...\n", val); + val = regr(CCDC_SYN_MODE); + dev_notice(dev, "\nReading 0x%x to SYN_MODE...\n", val); + val = regr(CCDC_HORZ_INFO); + dev_notice(dev, "\nReading 0x%x to HORZ_INFO...\n", val); + val = regr(CCDC_VERT_START); + dev_notice(dev, "\nReading 0x%x to VERT_START...\n", val); + val = regr(CCDC_VERT_LINES); + dev_notice(dev, "\nReading 0x%x to VERT_LINES...\n", val); +} + +static int validate_ccdc_param(struct ccdc_config_params_raw *ccdcparam) +{ + if (ccdcparam->alaw.enable) { + if ((ccdcparam->alaw.gama_wd > CCDC_GAMMA_BITS_09_0) || + (ccdcparam->alaw.gama_wd < CCDC_GAMMA_BITS_15_6) || + (ccdcparam->alaw.gama_wd < ccdcparam->data_sz)) { + dev_dbg(dev, "\nInvalid data line select"); + return -1; + } + } + return 0; +} + +static int ccdc_update_raw_params(struct ccdc_config_params_raw *raw_params) +{ + struct ccdc_config_params_raw *config_params = + &ccdc_hw_params_raw.config_params; + unsigned int *fpc_virtaddr = NULL; + unsigned int *fpc_physaddr = NULL; + + memcpy(config_params, raw_params, sizeof(*raw_params)); + /* + * allocate memory for fault pixel table and copy the user + * values to the table + */ + if (!config_params->fault_pxl.enable) + return 0; + + fpc_physaddr = (unsigned int *)config_params->fault_pxl.fpc_table_addr; + fpc_virtaddr = (unsigned int *)phys_to_virt( + (unsigned long)fpc_physaddr); + /* + * Allocate memory for FPC table if current + * FPC table buffer is not big enough to + * accomodate FPC Number requested + */ + if (raw_params->fault_pxl.fp_num != config_params->fault_pxl.fp_num) { + if (fpc_physaddr != NULL) { + free_pages((unsigned long)fpc_physaddr, + get_order + (config_params->fault_pxl.fp_num * + FP_NUM_BYTES)); + } + + /* Allocate memory for FPC table */ + fpc_virtaddr = + (unsigned int *)__get_free_pages(GFP_KERNEL | GFP_DMA, + get_order(raw_params-> + fault_pxl.fp_num * + FP_NUM_BYTES)); + + if (fpc_virtaddr == NULL) { + dev_dbg(dev, + "\nUnable to allocate memory for FPC"); + return -EFAULT; + } + fpc_physaddr = + (unsigned int *)virt_to_phys((void *)fpc_virtaddr); + } + + /* Copy number of fault pixels and FPC table */ + config_params->fault_pxl.fp_num = raw_params->fault_pxl.fp_num; + if (copy_from_user(fpc_virtaddr, + (void __user *)raw_params->fault_pxl.fpc_table_addr, + config_params->fault_pxl.fp_num * FP_NUM_BYTES)) { + dev_dbg(dev, "\n copy_from_user failed"); + return -EFAULT; + } + config_params->fault_pxl.fpc_table_addr = (unsigned int)fpc_physaddr; + return 0; +} + +static int ccdc_close(struct device *dev) +{ + struct ccdc_config_params_raw *config_params = + &ccdc_hw_params_raw.config_params; + unsigned int *fpc_physaddr = NULL, *fpc_virtaddr = NULL; + + fpc_physaddr = (unsigned int *)config_params->fault_pxl.fpc_table_addr; + + if (fpc_physaddr != NULL) { + fpc_virtaddr = (unsigned int *) + phys_to_virt((unsigned long)fpc_physaddr); + free_pages((unsigned long)fpc_virtaddr, + get_order(config_params->fault_pxl.fp_num * + FP_NUM_BYTES)); + } + return 0; +} + +/* + * ccdc_restore_defaults() + * This function will write defaults to all CCDC registers + */ +static void ccdc_restore_defaults(void) +{ + int i; + + /* disable CCDC */ + ccdc_enable(0); + /* set all registers to default value */ + for (i = 4; i <= 0x94; i += 4) + regw(0, i); + regw(CCDC_NO_CULLING, CCDC_CULLING); + regw(CCDC_GAMMA_BITS_11_2, CCDC_ALAW); +} + +static int ccdc_open(struct device *device) +{ + dev = device; + ccdc_restore_defaults(); + if (ccdc_if_type == VPFE_RAW_BAYER) + ccdc_enable_vport(1); + return 0; +} + +static void ccdc_sbl_reset(void) +{ + vpss_clear_wbl_overflow(VPSS_PCR_CCDC_WBL_O); +} + +/* Parameter operations */ +static int ccdc_set_params(void __user *params) +{ + struct ccdc_config_params_raw ccdc_raw_params; + int x; + + if (ccdc_if_type != VPFE_RAW_BAYER) + return -EINVAL; + + x = copy_from_user(&ccdc_raw_params, params, sizeof(ccdc_raw_params)); + if (x) { + dev_dbg(dev, "ccdc_set_params: error in copying" + "ccdc params, %d\n", x); + return -EFAULT; + } + + if (!validate_ccdc_param(&ccdc_raw_params)) { + if (!ccdc_update_raw_params(&ccdc_raw_params)) + return 0; + } + return -EINVAL; +} + +/* + * ccdc_config_ycbcr() + * This function will configure CCDC for YCbCr video capture + */ +void ccdc_config_ycbcr(void) +{ + struct ccdc_params_ycbcr *params = &ccdc_hw_params_ycbcr; + u32 syn_mode; + + dev_dbg(dev, "\nStarting ccdc_config_ycbcr..."); + /* + * first restore the CCDC registers to default values + * This is important since we assume default values to be set in + * a lot of registers that we didn't touch + */ + ccdc_restore_defaults(); + + /* + * configure pixel format, frame format, configure video frame + * format, enable output to SDRAM, enable internal timing generator + * and 8bit pack mode + */ + syn_mode = (((params->pix_fmt & CCDC_SYN_MODE_INPMOD_MASK) << + CCDC_SYN_MODE_INPMOD_SHIFT) | + ((params->frm_fmt & CCDC_SYN_FLDMODE_MASK) << + CCDC_SYN_FLDMODE_SHIFT) | CCDC_VDHDEN_ENABLE | + CCDC_WEN_ENABLE | CCDC_DATA_PACK_ENABLE); + + /* setup BT.656 sync mode */ + if (params->bt656_enable) { + regw(CCDC_REC656IF_BT656_EN, CCDC_REC656IF); + + /* + * configure the FID, VD, HD pin polarity, + * fld,hd pol positive, vd negative, 8-bit data + */ + syn_mode |= CCDC_SYN_MODE_VD_POL_NEGATIVE | CCDC_SYN_MODE_8BITS; + } else { + /* y/c external sync mode */ + syn_mode |= (((params->fid_pol & CCDC_FID_POL_MASK) << + CCDC_FID_POL_SHIFT) | + ((params->hd_pol & CCDC_HD_POL_MASK) << + CCDC_HD_POL_SHIFT) | + ((params->vd_pol & CCDC_VD_POL_MASK) << + CCDC_VD_POL_SHIFT)); + } + regw(syn_mode, CCDC_SYN_MODE); + + /* configure video window */ + ccdc_setwin(¶ms->win, params->frm_fmt, 2); + + /* + * configure the order of y cb cr in SDRAM, and disable latch + * internal register on vsync + */ + regw((params->pix_order << CCDC_CCDCFG_Y8POS_SHIFT) | + CCDC_LATCH_ON_VSYNC_DISABLE, CCDC_CCDCFG); + + /* + * configure the horizontal line offset. This should be a + * on 32 byte bondary. So clear LSB 5 bits + */ + regw(((params->win.width * 2 + 31) & ~0x1f), CCDC_HSIZE_OFF); + + /* configure the memory line offset */ + if (params->buf_type == CCDC_BUFTYPE_FLD_INTERLEAVED) + /* two fields are interleaved in memory */ + regw(CCDC_SDOFST_FIELD_INTERLEAVED, CCDC_SDOFST); + + ccdc_sbl_reset(); + dev_dbg(dev, "\nEnd of ccdc_config_ycbcr...\n"); + ccdc_readregs(); +} + +static void ccdc_config_black_clamp(struct ccdc_black_clamp *bclamp) +{ + u32 val; + + if (!bclamp->enable) { + /* configure DCSub */ + val = (bclamp->dc_sub) & CCDC_BLK_DC_SUB_MASK; + regw(val, CCDC_DCSUB); + dev_dbg(dev, "\nWriting 0x%x to DCSUB...\n", val); + regw(CCDC_CLAMP_DEFAULT_VAL, CCDC_CLAMP); + dev_dbg(dev, "\nWriting 0x0000 to CLAMP...\n"); + return; + } + /* + * Configure gain, Start pixel, No of line to be avg, + * No of pixel/line to be avg, & Enable the Black clamping + */ + val = ((bclamp->sgain & CCDC_BLK_SGAIN_MASK) | + ((bclamp->start_pixel & CCDC_BLK_ST_PXL_MASK) << + CCDC_BLK_ST_PXL_SHIFT) | + ((bclamp->sample_ln & CCDC_BLK_SAMPLE_LINE_MASK) << + CCDC_BLK_SAMPLE_LINE_SHIFT) | + ((bclamp->sample_pixel & CCDC_BLK_SAMPLE_LN_MASK) << + CCDC_BLK_SAMPLE_LN_SHIFT) | CCDC_BLK_CLAMP_ENABLE); + regw(val, CCDC_CLAMP); + dev_dbg(dev, "\nWriting 0x%x to CLAMP...\n", val); + /* If Black clamping is enable then make dcsub 0 */ + regw(CCDC_DCSUB_DEFAULT_VAL, CCDC_DCSUB); + dev_dbg(dev, "\nWriting 0x00000000 to DCSUB...\n"); +} + +static void ccdc_config_black_compense(struct ccdc_black_compensation *bcomp) +{ + u32 val; + + val = ((bcomp->b & CCDC_BLK_COMP_MASK) | + ((bcomp->gb & CCDC_BLK_COMP_MASK) << + CCDC_BLK_COMP_GB_COMP_SHIFT) | + ((bcomp->gr & CCDC_BLK_COMP_MASK) << + CCDC_BLK_COMP_GR_COMP_SHIFT) | + ((bcomp->r & CCDC_BLK_COMP_MASK) << + CCDC_BLK_COMP_R_COMP_SHIFT)); + regw(val, CCDC_BLKCMP); +} + +static void ccdc_config_fpc(struct ccdc_fault_pixel *fpc) +{ + u32 val; + + /* Initially disable FPC */ + val = CCDC_FPC_DISABLE; + regw(val, CCDC_FPC); + + if (!fpc->enable) + return; + + /* Configure Fault pixel if needed */ + regw(fpc->fpc_table_addr, CCDC_FPC_ADDR); + dev_dbg(dev, "\nWriting 0x%x to FPC_ADDR...\n", + (fpc->fpc_table_addr)); + /* Write the FPC params with FPC disable */ + val = fpc->fp_num & CCDC_FPC_FPC_NUM_MASK; + regw(val, CCDC_FPC); + + dev_dbg(dev, "\nWriting 0x%x to FPC...\n", val); + /* read the FPC register */ + val = regr(CCDC_FPC) | CCDC_FPC_ENABLE; + regw(val, CCDC_FPC); + dev_dbg(dev, "\nWriting 0x%x to FPC...\n", val); +} + +/* + * ccdc_config_raw() + * This function will configure CCDC for Raw capture mode + */ +void ccdc_config_raw(void) +{ + struct ccdc_params_raw *params = &ccdc_hw_params_raw; + struct ccdc_config_params_raw *config_params = + &ccdc_hw_params_raw.config_params; + unsigned int syn_mode = 0; + unsigned int val; + + dev_dbg(dev, "\nStarting ccdc_config_raw..."); + + /* Reset CCDC */ + ccdc_restore_defaults(); + + /* Disable latching function registers on VSYNC */ + regw(CCDC_LATCH_ON_VSYNC_DISABLE, CCDC_CCDCFG); + + /* + * Configure the vertical sync polarity(SYN_MODE.VDPOL), + * horizontal sync polarity (SYN_MODE.HDPOL), frame id polarity + * (SYN_MODE.FLDPOL), frame format(progressive or interlace), + * data size(SYNMODE.DATSIZ), &pixel format (Input mode), output + * SDRAM, enable internal timing generator + */ + syn_mode = + (((params->vd_pol & CCDC_VD_POL_MASK) << CCDC_VD_POL_SHIFT) | + ((params->hd_pol & CCDC_HD_POL_MASK) << CCDC_HD_POL_SHIFT) | + ((params->fid_pol & CCDC_FID_POL_MASK) << CCDC_FID_POL_SHIFT) | + ((params->frm_fmt & CCDC_FRM_FMT_MASK) << CCDC_FRM_FMT_SHIFT) | + ((config_params->data_sz & CCDC_DATA_SZ_MASK) << + CCDC_DATA_SZ_SHIFT) | + ((params->pix_fmt & CCDC_PIX_FMT_MASK) << CCDC_PIX_FMT_SHIFT) | + CCDC_WEN_ENABLE | CCDC_VDHDEN_ENABLE); + + /* Enable and configure aLaw register if needed */ + if (config_params->alaw.enable) { + val = ((config_params->alaw.gama_wd & + CCDC_ALAW_GAMA_WD_MASK) | CCDC_ALAW_ENABLE); + regw(val, CCDC_ALAW); + dev_dbg(dev, "\nWriting 0x%x to ALAW...\n", val); + } + + /* Configure video window */ + ccdc_setwin(¶ms->win, params->frm_fmt, CCDC_PPC_RAW); + + /* Configure Black Clamp */ + ccdc_config_black_clamp(&config_params->blk_clamp); + + /* Configure Black level compensation */ + ccdc_config_black_compense(&config_params->blk_comp); + + /* Configure Fault Pixel Correction */ + ccdc_config_fpc(&config_params->fault_pxl); + + /* If data size is 8 bit then pack the data */ + if ((config_params->data_sz == CCDC_DATA_8BITS) || + config_params->alaw.enable) + syn_mode |= CCDC_DATA_PACK_ENABLE; + +#ifdef CONFIG_DM644X_VIDEO_PORT_ENABLE + /* enable video port */ + val = CCDC_ENABLE_VIDEO_PORT; +#else + /* disable video port */ + val = CCDC_DISABLE_VIDEO_PORT; +#endif + + if (config_params->data_sz == CCDC_DATA_8BITS) + val |= (CCDC_DATA_10BITS & CCDC_FMTCFG_VPIN_MASK) + << CCDC_FMTCFG_VPIN_SHIFT; + else + val |= (config_params->data_sz & CCDC_FMTCFG_VPIN_MASK) + << CCDC_FMTCFG_VPIN_SHIFT; + /* Write value in FMTCFG */ + regw(val, CCDC_FMTCFG); + + dev_dbg(dev, "\nWriting 0x%x to FMTCFG...\n", val); + /* Configure the color pattern according to mt9t001 sensor */ + regw(CCDC_COLPTN_VAL, CCDC_COLPTN); + + dev_dbg(dev, "\nWriting 0xBB11BB11 to COLPTN...\n"); + /* + * Configure Data formatter(Video port) pixel selection + * (FMT_HORZ, FMT_VERT) + */ + val = ((params->win.left & CCDC_FMT_HORZ_FMTSPH_MASK) << + CCDC_FMT_HORZ_FMTSPH_SHIFT) | + (params->win.width & CCDC_FMT_HORZ_FMTLNH_MASK); + regw(val, CCDC_FMT_HORZ); + + dev_dbg(dev, "\nWriting 0x%x to FMT_HORZ...\n", val); + val = (params->win.top & CCDC_FMT_VERT_FMTSLV_MASK) + << CCDC_FMT_VERT_FMTSLV_SHIFT; + if (params->frm_fmt == CCDC_FRMFMT_PROGRESSIVE) + val |= (params->win.height) & CCDC_FMT_VERT_FMTLNV_MASK; + else + val |= (params->win.height >> 1) & CCDC_FMT_VERT_FMTLNV_MASK; + + dev_dbg(dev, "\nparams->win.height 0x%x ...\n", + params->win.height); + regw(val, CCDC_FMT_VERT); + + dev_dbg(dev, "\nWriting 0x%x to FMT_VERT...\n", val); + + dev_dbg(dev, "\nbelow regw(val, FMT_VERT)..."); + + /* + * Configure Horizontal offset register. If pack 8 is enabled then + * 1 pixel will take 1 byte + */ + if ((config_params->data_sz == CCDC_DATA_8BITS) || + config_params->alaw.enable) + regw((params->win.width + CCDC_32BYTE_ALIGN_VAL) & + CCDC_HSIZE_OFF_MASK, CCDC_HSIZE_OFF); + else + /* else one pixel will take 2 byte */ + regw(((params->win.width * CCDC_TWO_BYTES_PER_PIXEL) + + CCDC_32BYTE_ALIGN_VAL) & CCDC_HSIZE_OFF_MASK, + CCDC_HSIZE_OFF); + + /* Set value for SDOFST */ + if (params->frm_fmt == CCDC_FRMFMT_INTERLACED) { + if (params->image_invert_enable) { + /* For intelace inverse mode */ + regw(CCDC_INTERLACED_IMAGE_INVERT, CCDC_SDOFST); + dev_dbg(dev, "\nWriting 0x4B6D to SDOFST...\n"); + } + + else { + /* For intelace non inverse mode */ + regw(CCDC_INTERLACED_NO_IMAGE_INVERT, CCDC_SDOFST); + dev_dbg(dev, "\nWriting 0x0249 to SDOFST...\n"); + } + } else if (params->frm_fmt == CCDC_FRMFMT_PROGRESSIVE) { + regw(CCDC_PROGRESSIVE_NO_IMAGE_INVERT, CCDC_SDOFST); + dev_dbg(dev, "\nWriting 0x0000 to SDOFST...\n"); + } + + /* + * Configure video port pixel selection (VPOUT) + * Here -1 is to make the height value less than FMT_VERT.FMTLNV + */ + if (params->frm_fmt == CCDC_FRMFMT_PROGRESSIVE) + val = (((params->win.height - 1) & CCDC_VP_OUT_VERT_NUM_MASK)) + << CCDC_VP_OUT_VERT_NUM_SHIFT; + else + val = + ((((params->win.height >> CCDC_INTERLACED_HEIGHT_SHIFT) - + 1) & CCDC_VP_OUT_VERT_NUM_MASK)) << + CCDC_VP_OUT_VERT_NUM_SHIFT; + + val |= ((((params->win.width))) & CCDC_VP_OUT_HORZ_NUM_MASK) + << CCDC_VP_OUT_HORZ_NUM_SHIFT; + val |= (params->win.left) & CCDC_VP_OUT_HORZ_ST_MASK; + regw(val, CCDC_VP_OUT); + + dev_dbg(dev, "\nWriting 0x%x to VP_OUT...\n", val); + regw(syn_mode, CCDC_SYN_MODE); + dev_dbg(dev, "\nWriting 0x%x to SYN_MODE...\n", syn_mode); + + ccdc_sbl_reset(); + dev_dbg(dev, "\nend of ccdc_config_raw..."); + ccdc_readregs(); +} + +static int ccdc_configure(void) +{ + if (ccdc_if_type == VPFE_RAW_BAYER) + ccdc_config_raw(); + else + ccdc_config_ycbcr(); + return 0; +} + +static int ccdc_set_buftype(enum ccdc_buftype buf_type) +{ + if (ccdc_if_type == VPFE_RAW_BAYER) + ccdc_hw_params_raw.buf_type = buf_type; + else + ccdc_hw_params_ycbcr.buf_type = buf_type; + return 0; +} + +static enum ccdc_buftype ccdc_get_buftype(void) +{ + if (ccdc_if_type == VPFE_RAW_BAYER) + return ccdc_hw_params_raw.buf_type; + return ccdc_hw_params_ycbcr.buf_type; +} + +static int ccdc_enum_pix(u32 *pix, int i) +{ + int ret = -EINVAL; + if (ccdc_if_type == VPFE_RAW_BAYER) { + if (i < ARRAY_SIZE(ccdc_raw_bayer_pix_formats)) { + *pix = ccdc_raw_bayer_pix_formats[i]; + ret = 0; + } + } else { + if (i < ARRAY_SIZE(ccdc_raw_yuv_pix_formats)) { + *pix = ccdc_raw_yuv_pix_formats[i]; + ret = 0; + } + } + return ret; +} + +static int ccdc_set_pixel_format(u32 pixfmt) +{ + if (ccdc_if_type == VPFE_RAW_BAYER) { + ccdc_hw_params_raw.pix_fmt = CCDC_PIXFMT_RAW; + if (pixfmt == V4L2_PIX_FMT_SBGGR8) + ccdc_hw_params_raw.config_params.alaw.enable = 1; + else if (pixfmt != V4L2_PIX_FMT_SBGGR16) + return -EINVAL; + } else { + if (pixfmt == V4L2_PIX_FMT_YUYV) + ccdc_hw_params_ycbcr.pix_order = CCDC_PIXORDER_YCBYCR; + else if (pixfmt == V4L2_PIX_FMT_UYVY) + ccdc_hw_params_ycbcr.pix_order = CCDC_PIXORDER_CBYCRY; + else + return -EINVAL; + } + return 0; +} + +static u32 ccdc_get_pixel_format(void) +{ + struct ccdc_a_law *alaw = + &ccdc_hw_params_raw.config_params.alaw; + u32 pixfmt; + + if (ccdc_if_type == VPFE_RAW_BAYER) + if (alaw->enable) + pixfmt = V4L2_PIX_FMT_SBGGR8; + else + pixfmt = V4L2_PIX_FMT_SBGGR16; + else { + if (ccdc_hw_params_ycbcr.pix_order == CCDC_PIXORDER_YCBYCR) + pixfmt = V4L2_PIX_FMT_YUYV; + else + pixfmt = V4L2_PIX_FMT_UYVY; + } + return pixfmt; +} + +static int ccdc_set_image_window(struct v4l2_rect *win) +{ + if (ccdc_if_type == VPFE_RAW_BAYER) + ccdc_hw_params_raw.win = *win; + else + ccdc_hw_params_ycbcr.win = *win; + return 0; +} + +static void ccdc_get_image_window(struct v4l2_rect *win) +{ + if (ccdc_if_type == VPFE_RAW_BAYER) + *win = ccdc_hw_params_raw.win; + else + *win = ccdc_hw_params_ycbcr.win; +} + +static unsigned int ccdc_get_line_length(void) +{ + struct ccdc_config_params_raw *config_params = + &ccdc_hw_params_raw.config_params; + unsigned int len; + + if (ccdc_if_type == VPFE_RAW_BAYER) { + if ((config_params->alaw.enable) || + (config_params->data_sz == CCDC_DATA_8BITS)) + len = ccdc_hw_params_raw.win.width; + else + len = ccdc_hw_params_raw.win.width * 2; + } else + len = ccdc_hw_params_ycbcr.win.width * 2; + return ALIGN(len, 32); +} + +static int ccdc_set_frame_format(enum ccdc_frmfmt frm_fmt) +{ + if (ccdc_if_type == VPFE_RAW_BAYER) + ccdc_hw_params_raw.frm_fmt = frm_fmt; + else + ccdc_hw_params_ycbcr.frm_fmt = frm_fmt; + return 0; +} + +static enum ccdc_frmfmt ccdc_get_frame_format(void) +{ + if (ccdc_if_type == VPFE_RAW_BAYER) + return ccdc_hw_params_raw.frm_fmt; + else + return ccdc_hw_params_ycbcr.frm_fmt; +} + +static int ccdc_getfid(void) +{ + return (regr(CCDC_SYN_MODE) >> 15) & 1; +} + +/* misc operations */ +static inline void ccdc_setfbaddr(unsigned long addr) +{ + regw(addr & 0xffffffe0, CCDC_SDR_ADDR); +} + +static int ccdc_set_hw_if_params(struct vpfe_hw_if_param *params) +{ + ccdc_if_type = params->if_type; + + switch (params->if_type) { + case VPFE_BT656: + case VPFE_YCBCR_SYNC_16: + case VPFE_YCBCR_SYNC_8: + ccdc_hw_params_ycbcr.vd_pol = params->vdpol; + ccdc_hw_params_ycbcr.hd_pol = params->hdpol; + break; + default: + /* TODO add support for raw bayer here */ + return -EINVAL; + } + return 0; +} + +static struct ccdc_hw_device ccdc_hw_dev = { + .name = "DM6446 CCDC", + .owner = THIS_MODULE, + .hw_ops = { + .open = ccdc_open, + .close = ccdc_close, + .set_ccdc_base = ccdc_set_ccdc_base, + .reset = ccdc_sbl_reset, + .enable = ccdc_enable, + .set_hw_if_params = ccdc_set_hw_if_params, + .set_params = ccdc_set_params, + .configure = ccdc_configure, + .set_buftype = ccdc_set_buftype, + .get_buftype = ccdc_get_buftype, + .enum_pix = ccdc_enum_pix, + .set_pixel_format = ccdc_set_pixel_format, + .get_pixel_format = ccdc_get_pixel_format, + .set_frame_format = ccdc_set_frame_format, + .get_frame_format = ccdc_get_frame_format, + .set_image_window = ccdc_set_image_window, + .get_image_window = ccdc_get_image_window, + .get_line_length = ccdc_get_line_length, + .setfbaddr = ccdc_setfbaddr, + .getfid = ccdc_getfid, + }, +}; + +static int dm644x_ccdc_init(void) +{ + printk(KERN_NOTICE "dm644x_ccdc_init\n"); + if (vpfe_register_ccdc_device(&ccdc_hw_dev) < 0) + return -1; + printk(KERN_NOTICE "%s is registered with vpfe.\n", + ccdc_hw_dev.name); + return 0; +} + +static void dm644x_ccdc_exit(void) +{ + vpfe_unregister_ccdc_device(&ccdc_hw_dev); +} + +module_init(dm644x_ccdc_init); +module_exit(dm644x_ccdc_exit); diff --git a/linux/drivers/media/video/davinci/dm644x_ccdc_regs.h b/linux/drivers/media/video/davinci/dm644x_ccdc_regs.h new file mode 100644 index 000000000..6e5d05324 --- /dev/null +++ b/linux/drivers/media/video/davinci/dm644x_ccdc_regs.h @@ -0,0 +1,145 @@ +/* + * Copyright (C) 2006-2009 Texas Instruments Inc + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef _DM644X_CCDC_REGS_H +#define _DM644X_CCDC_REGS_H + +/**************************************************************************\ +* Register OFFSET Definitions +\**************************************************************************/ +#define CCDC_PID 0x0 +#define CCDC_PCR 0x4 +#define CCDC_SYN_MODE 0x8 +#define CCDC_HD_VD_WID 0xc +#define CCDC_PIX_LINES 0x10 +#define CCDC_HORZ_INFO 0x14 +#define CCDC_VERT_START 0x18 +#define CCDC_VERT_LINES 0x1c +#define CCDC_CULLING 0x20 +#define CCDC_HSIZE_OFF 0x24 +#define CCDC_SDOFST 0x28 +#define CCDC_SDR_ADDR 0x2c +#define CCDC_CLAMP 0x30 +#define CCDC_DCSUB 0x34 +#define CCDC_COLPTN 0x38 +#define CCDC_BLKCMP 0x3c +#define CCDC_FPC 0x40 +#define CCDC_FPC_ADDR 0x44 +#define CCDC_VDINT 0x48 +#define CCDC_ALAW 0x4c +#define CCDC_REC656IF 0x50 +#define CCDC_CCDCFG 0x54 +#define CCDC_FMTCFG 0x58 +#define CCDC_FMT_HORZ 0x5c +#define CCDC_FMT_VERT 0x60 +#define CCDC_FMT_ADDR0 0x64 +#define CCDC_FMT_ADDR1 0x68 +#define CCDC_FMT_ADDR2 0x6c +#define CCDC_FMT_ADDR3 0x70 +#define CCDC_FMT_ADDR4 0x74 +#define CCDC_FMT_ADDR5 0x78 +#define CCDC_FMT_ADDR6 0x7c +#define CCDC_FMT_ADDR7 0x80 +#define CCDC_PRGEVEN_0 0x84 +#define CCDC_PRGEVEN_1 0x88 +#define CCDC_PRGODD_0 0x8c +#define CCDC_PRGODD_1 0x90 +#define CCDC_VP_OUT 0x94 + + +/*************************************************************** +* Define for various register bit mask and shifts for CCDC +****************************************************************/ +#define CCDC_FID_POL_MASK 1 +#define CCDC_FID_POL_SHIFT 4 +#define CCDC_HD_POL_MASK 1 +#define CCDC_HD_POL_SHIFT 3 +#define CCDC_VD_POL_MASK 1 +#define CCDC_VD_POL_SHIFT 2 +#define CCDC_HSIZE_OFF_MASK 0xffffffe0 +#define CCDC_32BYTE_ALIGN_VAL 31 +#define CCDC_FRM_FMT_MASK 0x1 +#define CCDC_FRM_FMT_SHIFT 7 +#define CCDC_DATA_SZ_MASK 7 +#define CCDC_DATA_SZ_SHIFT 8 +#define CCDC_PIX_FMT_MASK 3 +#define CCDC_PIX_FMT_SHIFT 12 +#define CCDC_VP2SDR_DISABLE 0xFFFBFFFF +#define CCDC_WEN_ENABLE (1 << 17) +#define CCDC_SDR2RSZ_DISABLE 0xFFF7FFFF +#define CCDC_VDHDEN_ENABLE (1 << 16) +#define CCDC_LPF_ENABLE (1 << 14) +#define CCDC_ALAW_ENABLE (1 << 3) +#define CCDC_ALAW_GAMA_WD_MASK 7 +#define CCDC_BLK_CLAMP_ENABLE (1 << 31) +#define CCDC_BLK_SGAIN_MASK 0x1F +#define CCDC_BLK_ST_PXL_MASK 0x7FFF +#define CCDC_BLK_ST_PXL_SHIFT 10 +#define CCDC_BLK_SAMPLE_LN_MASK 7 +#define CCDC_BLK_SAMPLE_LN_SHIFT 28 +#define CCDC_BLK_SAMPLE_LINE_MASK 7 +#define CCDC_BLK_SAMPLE_LINE_SHIFT 25 +#define CCDC_BLK_DC_SUB_MASK 0x03FFF +#define CCDC_BLK_COMP_MASK 0xFF +#define CCDC_BLK_COMP_GB_COMP_SHIFT 8 +#define CCDC_BLK_COMP_GR_COMP_SHIFT 16 +#define CCDC_BLK_COMP_R_COMP_SHIFT 24 +#define CCDC_LATCH_ON_VSYNC_DISABLE (1 << 15) +#define CCDC_FPC_ENABLE (1 << 15) +#define CCDC_FPC_DISABLE 0 +#define CCDC_FPC_FPC_NUM_MASK 0x7FFF +#define CCDC_DATA_PACK_ENABLE (1 << 11) +#define CCDC_FMTCFG_VPIN_MASK 7 +#define CCDC_FMTCFG_VPIN_SHIFT 12 +#define CCDC_FMT_HORZ_FMTLNH_MASK 0x1FFF +#define CCDC_FMT_HORZ_FMTSPH_MASK 0x1FFF +#define CCDC_FMT_HORZ_FMTSPH_SHIFT 16 +#define CCDC_FMT_VERT_FMTLNV_MASK 0x1FFF +#define CCDC_FMT_VERT_FMTSLV_MASK 0x1FFF +#define CCDC_FMT_VERT_FMTSLV_SHIFT 16 +#define CCDC_VP_OUT_VERT_NUM_MASK 0x3FFF +#define CCDC_VP_OUT_VERT_NUM_SHIFT 17 +#define CCDC_VP_OUT_HORZ_NUM_MASK 0x1FFF +#define CCDC_VP_OUT_HORZ_NUM_SHIFT 4 +#define CCDC_VP_OUT_HORZ_ST_MASK 0xF +#define CCDC_HORZ_INFO_SPH_SHIFT 16 +#define CCDC_VERT_START_SLV0_SHIFT 16 +#define CCDC_VDINT_VDINT0_SHIFT 16 +#define CCDC_VDINT_VDINT1_MASK 0xFFFF +#define CCDC_PPC_RAW 1 +#define CCDC_DCSUB_DEFAULT_VAL 0 +#define CCDC_CLAMP_DEFAULT_VAL 0 +#define CCDC_ENABLE_VIDEO_PORT 0x8000 +#define CCDC_DISABLE_VIDEO_PORT 0 +#define CCDC_COLPTN_VAL 0xBB11BB11 +#define CCDC_TWO_BYTES_PER_PIXEL 2 +#define CCDC_INTERLACED_IMAGE_INVERT 0x4B6D +#define CCDC_INTERLACED_NO_IMAGE_INVERT 0x0249 +#define CCDC_PROGRESSIVE_IMAGE_INVERT 0x4000 +#define CCDC_PROGRESSIVE_NO_IMAGE_INVERT 0 +#define CCDC_INTERLACED_HEIGHT_SHIFT 1 +#define CCDC_SYN_MODE_INPMOD_SHIFT 12 +#define CCDC_SYN_MODE_INPMOD_MASK 3 +#define CCDC_SYN_MODE_8BITS (7 << 8) +#define CCDC_SYN_FLDMODE_MASK 1 +#define CCDC_SYN_FLDMODE_SHIFT 7 +#define CCDC_REC656IF_BT656_EN 3 +#define CCDC_SYN_MODE_VD_POL_NEGATIVE (1 << 2) +#define CCDC_CCDCFG_Y8POS_SHIFT 11 +#define CCDC_SDOFST_FIELD_INTERLEAVED 0x249 +#define CCDC_NO_CULLING 0xffff00ff +#endif -- cgit v1.2.3 From 4f2e24628e0f385f1b57e57524fb345cea8a8333 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 19 Jun 2009 14:20:16 +0200 Subject: v4l: common vpss module for video drivers From: Muralidharan Karicheri This is a new module added for vpss library functions that are used for configuring vpss system module. All video drivers will include vpss.h header file and call functions defined in this module to configure vpss system module. Reviewed by: Hans Verkuil Reviewed by: Laurent Pinchart Reviewed by: Alexey Klimov Priority: normal Signed-off-by: Muralidharan Karicheri Signed-off-by: Hans Verkuil --- linux/drivers/media/video/davinci/vpss.c | 301 +++++++++++++++++++++++++++++++ 1 file changed, 301 insertions(+) create mode 100644 linux/drivers/media/video/davinci/vpss.c (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/davinci/vpss.c b/linux/drivers/media/video/davinci/vpss.c new file mode 100644 index 000000000..6d709ca8c --- /dev/null +++ b/linux/drivers/media/video/davinci/vpss.c @@ -0,0 +1,301 @@ +/* + * Copyright (C) 2009 Texas Instruments. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * common vpss driver for all video drivers. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("VPSS Driver"); +MODULE_AUTHOR("Texas Instruments"); + +/* DM644x defines */ +#define DM644X_SBL_PCR_VPSS (4) + +/* vpss BL register offsets */ +#define DM355_VPSSBL_CCDCMUX 0x1c +/* vpss CLK register offsets */ +#define DM355_VPSSCLK_CLKCTRL 0x04 +/* masks and shifts */ +#define VPSS_HSSISEL_SHIFT 4 + +/* + * vpss operations. Depends on platform. Not all functions are available + * on all platforms. The api, first check if a functio is available before + * invoking it. In the probe, the function ptrs are intialized based on + * vpss name. vpss name can be "dm355_vpss", "dm644x_vpss" etc. + */ +struct vpss_hw_ops { + /* enable clock */ + int (*enable_clock)(enum vpss_clock_sel clock_sel, int en); + /* select input to ccdc */ + void (*select_ccdc_source)(enum vpss_ccdc_source_sel src_sel); + /* clear wbl overlflow bit */ + int (*clear_wbl_overflow)(enum vpss_wbl_sel wbl_sel); +}; + +/* vpss configuration */ +struct vpss_oper_config { + __iomem void *vpss_bl_regs_base; + __iomem void *vpss_regs_base; + struct resource *r1; + resource_size_t len1; + struct resource *r2; + resource_size_t len2; + char vpss_name[32]; + spinlock_t vpss_lock; + struct vpss_hw_ops hw_ops; +}; + +static struct vpss_oper_config oper_cfg; + +/* register access routines */ +static inline u32 bl_regr(u32 offset) +{ + return __raw_readl(oper_cfg.vpss_bl_regs_base + offset); +} + +static inline void bl_regw(u32 val, u32 offset) +{ + __raw_writel(val, oper_cfg.vpss_bl_regs_base + offset); +} + +static inline u32 vpss_regr(u32 offset) +{ + return __raw_readl(oper_cfg.vpss_regs_base + offset); +} + +static inline void vpss_regw(u32 val, u32 offset) +{ + __raw_writel(val, oper_cfg.vpss_regs_base + offset); +} + +static void dm355_select_ccdc_source(enum vpss_ccdc_source_sel src_sel) +{ + bl_regw(src_sel << VPSS_HSSISEL_SHIFT, DM355_VPSSBL_CCDCMUX); +} + +int vpss_select_ccdc_source(enum vpss_ccdc_source_sel src_sel) +{ + if (!oper_cfg.hw_ops.select_ccdc_source) + return -1; + + dm355_select_ccdc_source(src_sel); + return 0; +} +EXPORT_SYMBOL(vpss_select_ccdc_source); + +static int dm644x_clear_wbl_overflow(enum vpss_wbl_sel wbl_sel) +{ + u32 mask = 1, val; + + if (wbl_sel < VPSS_PCR_AEW_WBL_0 || + wbl_sel > VPSS_PCR_CCDC_WBL_O) + return -1; + + /* writing a 0 clear the overflow */ + mask = ~(mask << wbl_sel); + val = bl_regr(DM644X_SBL_PCR_VPSS) & mask; + bl_regw(val, DM644X_SBL_PCR_VPSS); + return 0; +} + +int vpss_clear_wbl_overflow(enum vpss_wbl_sel wbl_sel) +{ + if (!oper_cfg.hw_ops.clear_wbl_overflow) + return -1; + + return oper_cfg.hw_ops.clear_wbl_overflow(wbl_sel); +} +EXPORT_SYMBOL(vpss_clear_wbl_overflow); + +/* + * dm355_enable_clock - Enable VPSS Clock + * @clock_sel: CLock to be enabled/disabled + * @en: enable/disable flag + * + * This is called to enable or disable a vpss clock + */ +static int dm355_enable_clock(enum vpss_clock_sel clock_sel, int en) +{ + unsigned long flags; + u32 utemp, mask = 0x1, shift = 0; + + switch (clock_sel) { + case VPSS_VPBE_CLOCK: + /* nothing since lsb */ + break; + case VPSS_VENC_CLOCK_SEL: + shift = 2; + break; + case VPSS_CFALD_CLOCK: + shift = 3; + break; + case VPSS_H3A_CLOCK: + shift = 4; + break; + case VPSS_IPIPE_CLOCK: + shift = 5; + break; + case VPSS_CCDC_CLOCK: + shift = 6; + break; + default: + printk(KERN_ERR "dm355_enable_clock:" + " Invalid selector: %d\n", clock_sel); + return -1; + } + + spin_lock_irqsave(&oper_cfg.vpss_lock, flags); + utemp = vpss_regr(DM355_VPSSCLK_CLKCTRL); + if (!en) + utemp &= ~(mask << shift); + else + utemp |= (mask << shift); + + vpss_regw(utemp, DM355_VPSSCLK_CLKCTRL); + spin_unlock_irqrestore(&oper_cfg.vpss_lock, flags); + return 0; +} + +int vpss_enable_clock(enum vpss_clock_sel clock_sel, int en) +{ + if (!oper_cfg.hw_ops.enable_clock) + return -1; + + return oper_cfg.hw_ops.enable_clock(clock_sel, en); +} +EXPORT_SYMBOL(vpss_enable_clock); + +static int __init vpss_probe(struct platform_device *pdev) +{ + int status, dm355 = 0; + + if (!pdev->dev.platform_data) { + dev_err(&pdev->dev, "no platform data\n"); + return -ENOENT; + } + strcpy(oper_cfg.vpss_name, pdev->dev.platform_data); + + if (!strcmp(oper_cfg.vpss_name, "dm355_vpss")) + dm355 = 1; + else if (strcmp(oper_cfg.vpss_name, "dm644x_vpss")) { + dev_err(&pdev->dev, "vpss driver not supported on" + " this platform\n"); + return -ENODEV; + } + + dev_info(&pdev->dev, "%s vpss probed\n", oper_cfg.vpss_name); + oper_cfg.r1 = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!oper_cfg.r1) + return -ENOENT; + + oper_cfg.len1 = oper_cfg.r1->end - oper_cfg.r1->start + 1; + + oper_cfg.r1 = request_mem_region(oper_cfg.r1->start, oper_cfg.len1, + oper_cfg.r1->name); + if (!oper_cfg.r1) + return -EBUSY; + + oper_cfg.vpss_bl_regs_base = ioremap(oper_cfg.r1->start, oper_cfg.len1); + if (!oper_cfg.vpss_bl_regs_base) { + status = -EBUSY; + goto fail1; + } + + if (dm355) { + oper_cfg.r2 = platform_get_resource(pdev, IORESOURCE_MEM, 1); + if (!oper_cfg.r2) { + status = -ENOENT; + goto fail2; + } + oper_cfg.len2 = oper_cfg.r2->end - oper_cfg.r2->start + 1; + oper_cfg.r2 = request_mem_region(oper_cfg.r2->start, + oper_cfg.len2, + oper_cfg.r2->name); + if (!oper_cfg.r2) { + status = -EBUSY; + goto fail2; + } + + oper_cfg.vpss_regs_base = ioremap(oper_cfg.r2->start, + oper_cfg.len2); + if (!oper_cfg.vpss_regs_base) { + status = -EBUSY; + goto fail3; + } + } + + if (dm355) { + oper_cfg.hw_ops.enable_clock = dm355_enable_clock; + oper_cfg.hw_ops.select_ccdc_source = dm355_select_ccdc_source; + } else + oper_cfg.hw_ops.clear_wbl_overflow = dm644x_clear_wbl_overflow; + + spin_lock_init(&oper_cfg.vpss_lock); + dev_info(&pdev->dev, "%s vpss probe success\n", oper_cfg.vpss_name); + return 0; + +fail3: + release_mem_region(oper_cfg.r2->start, oper_cfg.len2); +fail2: + iounmap(oper_cfg.vpss_bl_regs_base); +fail1: + release_mem_region(oper_cfg.r1->start, oper_cfg.len1); + return status; +} + +static int vpss_remove(struct platform_device *pdev) +{ + iounmap(oper_cfg.vpss_bl_regs_base); + release_mem_region(oper_cfg.r1->start, oper_cfg.len1); + if (!strcmp(oper_cfg.vpss_name, "dm355_vpss")) { + iounmap(oper_cfg.vpss_regs_base); + release_mem_region(oper_cfg.r2->start, oper_cfg.len2); + } + return 0; +} + +static struct platform_driver vpss_driver = { + .driver = { + .name = "vpss", + .owner = THIS_MODULE, + }, + .remove = __devexit_p(vpss_remove), + .probe = vpss_probe, +}; + +static void vpss_exit(void) +{ + platform_driver_unregister(&vpss_driver); +} + +static int __init vpss_init(void) +{ + return platform_driver_register(&vpss_driver); +} +subsys_initcall(vpss_init); +module_exit(vpss_exit); -- cgit v1.2.3 From b561142eefcee2657f23d0af7838791f063f10f6 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 6 Jul 2009 20:08:31 +0200 Subject: v4l: Makefile and config files for vpfe capture driver From: Muralidharan Karicheri This adds Makefile and Kconfig changes to build vpfe capture driver. Reviewed by: Laurent Pinchart Priority: normal Signed-off-by: Muralidharan Karicheri Signed-off-by: Hans Verkuil --- linux/drivers/media/video/Kconfig | 49 ++++++++++++++++++++++++++++++ linux/drivers/media/video/Makefile | 2 ++ linux/drivers/media/video/davinci/Makefile | 6 ++++ 3 files changed, 57 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/Kconfig b/linux/drivers/media/video/Kconfig index e54bf1e70..8460013a0 100644 --- a/linux/drivers/media/video/Kconfig +++ b/linux/drivers/media/video/Kconfig @@ -527,6 +527,55 @@ config VIDEO_VIVI Say Y here if you want to test video apps or debug V4L devices. In doubt, say N. +config VIDEO_VPSS_SYSTEM + tristate "VPSS System module driver" + depends on ARCH_DAVINCI + help + Support for vpss system module for video driver + default y + +config VIDEO_VPFE_CAPTURE + tristate "VPFE Video Capture Driver" + depends on VIDEO_V4L2 && ARCH_DAVINCI + select VIDEOBUF_DMA_CONTIG + help + Support for DMXXXX VPFE based frame grabber. This is the + common V4L2 module for following DMXXX SoCs from Texas + Instruments:- DM6446 & DM355. + + To compile this driver as a module, choose M here: the + module will be called vpfe-capture. + +config VIDEO_DM6446_CCDC + tristate "DM6446 CCDC HW module" + depends on ARCH_DAVINCI_DM644x && VIDEO_VPFE_CAPTURE + select VIDEO_VPSS_SYSTEM + default y + help + Enables DaVinci CCD hw module. DaVinci CCDC hw interfaces + with decoder modules such as TVP5146 over BT656 or + sensor module such as MT9T001 over a raw interface. This + module configures the interface and CCDC/ISIF to do + video frame capture from slave decoders. + + To compile this driver as a module, choose M here: the + module will be called vpfe. + +config VIDEO_DM355_CCDC + tristate "DM355 CCDC HW module" + depends on ARCH_DAVINCI_DM355 && VIDEO_VPFE_CAPTURE + select VIDEO_VPSS_SYSTEM + default y + help + Enables DM355 CCD hw module. DM355 CCDC hw interfaces + with decoder modules such as TVP5146 over BT656 or + sensor module such as MT9T001 over a raw interface. This + module configures the interface and CCDC/ISIF to do + video frame capture from a slave decoders + + To compile this driver as a module, choose M here: the + module will be called vpfe. + source "drivers/media/video/bt8xx/Kconfig" config VIDEO_PMS diff --git a/linux/drivers/media/video/Makefile b/linux/drivers/media/video/Makefile index d3ec3a2fd..00fb23e64 100644 --- a/linux/drivers/media/video/Makefile +++ b/linux/drivers/media/video/Makefile @@ -154,6 +154,8 @@ obj-$(CONFIG_VIDEO_MX3) += mx3_camera.o obj-$(CONFIG_VIDEO_PXA27x) += pxa_camera.o obj-$(CONFIG_VIDEO_SH_MOBILE_CEU) += sh_mobile_ceu_camera.o +obj-$(CONFIG_ARCH_DAVINCI) += davinci/ + obj-$(CONFIG_VIDEO_AU0828) += au0828/ obj-$(CONFIG_USB_VIDEO_CLASS) += uvc/ diff --git a/linux/drivers/media/video/davinci/Makefile b/linux/drivers/media/video/davinci/Makefile index 7fe9bce97..f44cad2f5 100644 --- a/linux/drivers/media/video/davinci/Makefile +++ b/linux/drivers/media/video/davinci/Makefile @@ -7,3 +7,9 @@ obj-$(CONFIG_VIDEO_DAVINCI_VPIF) += vpif.o #DM646x EVM Display driver obj-$(CONFIG_DISPLAY_DAVINCI_DM646X_EVM) += vpif_display.o + +# Capture: DM6446 and DM355 +obj-$(CONFIG_VIDEO_VPSS_SYSTEM) += vpss.o +obj-$(CONFIG_VIDEO_VPFE_CAPTURE) += vpfe_capture.o +obj-$(CONFIG_VIDEO_DM6446_CCDC) += dm644x_ccdc.o +obj-$(CONFIG_VIDEO_DM355_CCDC) += dm355_ccdc.o -- cgit v1.2.3 From 78b537e32fbc1e45a9d5fe1086c4e6c303661e53 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 10 Aug 2009 07:49:08 +0200 Subject: v4l: simplify v4l2_i2c_new_subdev and friends From: Hans Verkuil Rewrite v4l2_i2c_new_subdev as a simplified version of v4l2_i2c_new_subdev_cfg and remove v4l2_i2c_new_probed_subdev and v4l2_i2c_new_probed_subdev_addr. This simplifies this API substantially. Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/au0828/au0828-cards.c | 4 +- linux/drivers/media/video/bt8xx/bttv-cards.c | 44 +++--- linux/drivers/media/video/cafe_ccic.c | 2 +- linux/drivers/media/video/cx18/cx18-i2c.c | 14 +- linux/drivers/media/video/cx231xx/cx231xx-cards.c | 4 +- linux/drivers/media/video/cx23885/cx23885-cards.c | 2 +- linux/drivers/media/video/cx23885/cx23885-video.c | 6 +- linux/drivers/media/video/cx88/cx88-cards.c | 14 +- linux/drivers/media/video/cx88/cx88-video.c | 6 +- linux/drivers/media/video/davinci/vpif_display.c | 4 +- linux/drivers/media/video/em28xx/em28xx-cards.c | 34 ++--- linux/drivers/media/video/ivtv/ivtv-i2c.c | 18 +-- linux/drivers/media/video/mxb.c | 14 +- linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c | 10 +- linux/drivers/media/video/saa7134/saa7134-cards.c | 12 +- linux/drivers/media/video/saa7134/saa7134-core.c | 6 +- .../drivers/media/video/usbvision/usbvision-i2c.c | 12 +- linux/drivers/media/video/v4l2-common.c | 157 --------------------- linux/drivers/media/video/vino.c | 8 +- linux/drivers/media/video/w9968cf.c | 4 +- linux/drivers/media/video/zoran/zoran_card.c | 8 +- 21 files changed, 113 insertions(+), 270 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 830c4a933..57dd9195d 100644 --- a/linux/drivers/media/video/au0828/au0828-cards.c +++ b/linux/drivers/media/video/au0828/au0828-cards.c @@ -212,7 +212,7 @@ void au0828_card_setup(struct au0828_dev *dev) be abstracted out if we ever need to support a different demod) */ sd = v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap, - "au8522", "au8522", 0x8e >> 1); + "au8522", "au8522", 0x8e >> 1, NULL); if (sd == NULL) printk(KERN_ERR "analog subdev registration failed\n"); } @@ -221,7 +221,7 @@ void au0828_card_setup(struct au0828_dev *dev) if (dev->board.tuner_type != TUNER_ABSENT) { /* Load the tuner module, which does the attach */ sd = v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap, - "tuner", "tuner", dev->board.tuner_addr); + "tuner", "tuner", dev->board.tuner_addr, NULL); if (sd == NULL) printk(KERN_ERR "tuner subdev registration fail\n"); diff --git a/linux/drivers/media/video/bt8xx/bttv-cards.c b/linux/drivers/media/video/bt8xx/bttv-cards.c index fdca5f67c..6b41aa5dc 100644 --- a/linux/drivers/media/video/bt8xx/bttv-cards.c +++ b/linux/drivers/media/video/bt8xx/bttv-cards.c @@ -3561,8 +3561,8 @@ void __devinit bttv_init_card2(struct bttv *btv) }; struct v4l2_subdev *sd; - sd = v4l2_i2c_new_probed_subdev(&btv->c.v4l2_dev, - &btv->c.i2c_adap, "saa6588", "saa6588", addrs); + sd = v4l2_i2c_new_subdev(&btv->c.v4l2_dev, + &btv->c.i2c_adap, "saa6588", "saa6588", 0, addrs); btv->has_saa6588 = (sd != NULL); } @@ -3586,8 +3586,8 @@ void __devinit bttv_init_card2(struct bttv *btv) I2C_CLIENT_END }; - btv->sd_msp34xx = v4l2_i2c_new_probed_subdev(&btv->c.v4l2_dev, - &btv->c.i2c_adap, "msp3400", "msp3400", addrs); + btv->sd_msp34xx = v4l2_i2c_new_subdev(&btv->c.v4l2_dev, + &btv->c.i2c_adap, "msp3400", "msp3400", 0, addrs); if (btv->sd_msp34xx) return; goto no_audio; @@ -3600,16 +3600,16 @@ void __devinit bttv_init_card2(struct bttv *btv) I2C_CLIENT_END }; - if (v4l2_i2c_new_probed_subdev(&btv->c.v4l2_dev, - &btv->c.i2c_adap, "tda7432", "tda7432", addrs)) + if (v4l2_i2c_new_subdev(&btv->c.v4l2_dev, + &btv->c.i2c_adap, "tda7432", "tda7432", 0, addrs)) return; goto no_audio; } case 3: { /* The user specified that we should probe for tvaudio */ - btv->sd_tvaudio = v4l2_i2c_new_probed_subdev(&btv->c.v4l2_dev, - &btv->c.i2c_adap, "tvaudio", "tvaudio", tvaudio_addrs()); + btv->sd_tvaudio = v4l2_i2c_new_subdev(&btv->c.v4l2_dev, + &btv->c.i2c_adap, "tvaudio", "tvaudio", 0, tvaudio_addrs()); if (btv->sd_tvaudio) return; goto no_audio; @@ -3628,13 +3628,13 @@ void __devinit bttv_init_card2(struct bttv *btv) it really is a msp3400, so it will return NULL when the device found is really something else (e.g. a tea6300). */ if (!bttv_tvcards[btv->c.type].no_msp34xx) { - btv->sd_msp34xx = v4l2_i2c_new_probed_subdev_addr(&btv->c.v4l2_dev, + btv->sd_msp34xx = v4l2_i2c_new_subdev(&btv->c.v4l2_dev, &btv->c.i2c_adap, "msp3400", "msp3400", - I2C_ADDR_MSP3400 >> 1); + 0, I2C_ADDRS(I2C_ADDR_MSP3400 >> 1)); } else if (bttv_tvcards[btv->c.type].msp34xx_alt) { - btv->sd_msp34xx = v4l2_i2c_new_probed_subdev_addr(&btv->c.v4l2_dev, + btv->sd_msp34xx = v4l2_i2c_new_subdev(&btv->c.v4l2_dev, &btv->c.i2c_adap, "msp3400", "msp3400", - I2C_ADDR_MSP3400_ALT >> 1); + 0, I2C_ADDRS(I2C_ADDR_MSP3400_ALT >> 1)); } /* If we found a msp34xx, then we're done. */ @@ -3648,14 +3648,14 @@ void __devinit bttv_init_card2(struct bttv *btv) I2C_CLIENT_END }; - if (v4l2_i2c_new_probed_subdev(&btv->c.v4l2_dev, - &btv->c.i2c_adap, "tda7432", "tda7432", addrs)) + if (v4l2_i2c_new_subdev(&btv->c.v4l2_dev, + &btv->c.i2c_adap, "tda7432", "tda7432", 0, addrs)) return; } /* Now see if we can find one of the tvaudio devices. */ - btv->sd_tvaudio = v4l2_i2c_new_probed_subdev(&btv->c.v4l2_dev, - &btv->c.i2c_adap, "tvaudio", "tvaudio", tvaudio_addrs()); + btv->sd_tvaudio = v4l2_i2c_new_subdev(&btv->c.v4l2_dev, + &btv->c.i2c_adap, "tvaudio", "tvaudio", 0, tvaudio_addrs()); if (btv->sd_tvaudio) return; @@ -3678,15 +3678,15 @@ void __devinit bttv_init_tuner(struct bttv *btv) /* Load tuner module before issuing tuner config call! */ if (bttv_tvcards[btv->c.type].has_radio) - v4l2_i2c_new_probed_subdev(&btv->c.v4l2_dev, + v4l2_i2c_new_subdev(&btv->c.v4l2_dev, &btv->c.i2c_adap, "tuner", "tuner", - v4l2_i2c_tuner_addrs(ADDRS_RADIO)); - v4l2_i2c_new_probed_subdev(&btv->c.v4l2_dev, + 0, v4l2_i2c_tuner_addrs(ADDRS_RADIO)); + v4l2_i2c_new_subdev(&btv->c.v4l2_dev, &btv->c.i2c_adap, "tuner", "tuner", - v4l2_i2c_tuner_addrs(ADDRS_DEMOD)); - v4l2_i2c_new_probed_subdev(&btv->c.v4l2_dev, + 0, v4l2_i2c_tuner_addrs(ADDRS_DEMOD)); + v4l2_i2c_new_subdev(&btv->c.v4l2_dev, &btv->c.i2c_adap, "tuner", "tuner", - v4l2_i2c_tuner_addrs(ADDRS_TV_WITH_DEMOD)); + 0, v4l2_i2c_tuner_addrs(ADDRS_TV_WITH_DEMOD)); tun_setup.mode_mask = T_ANALOG_TV | T_DIGITAL_TV; tun_setup.type = btv->tuner_type; diff --git a/linux/drivers/media/video/cafe_ccic.c b/linux/drivers/media/video/cafe_ccic.c index 2c78c35e8..7e86e9bfb 100644 --- a/linux/drivers/media/video/cafe_ccic.c +++ b/linux/drivers/media/video/cafe_ccic.c @@ -1956,7 +1956,7 @@ static int cafe_pci_probe(struct pci_dev *pdev, cam->sensor_addr = 0x42; cam->sensor = v4l2_i2c_new_subdev(&cam->v4l2_dev, &cam->i2c_adapter, - "ov7670", "ov7670", cam->sensor_addr); + "ov7670", "ov7670", cam->sensor_addr, NULL); if (cam->sensor == NULL) { ret = -ENODEV; goto out_smbus; diff --git a/linux/drivers/media/video/cx18/cx18-i2c.c b/linux/drivers/media/video/cx18/cx18-i2c.c index c551fcd47..7d4272d33 100644 --- a/linux/drivers/media/video/cx18/cx18-i2c.c +++ b/linux/drivers/media/video/cx18/cx18-i2c.c @@ -144,16 +144,16 @@ int cx18_i2c_register(struct cx18 *cx, unsigned idx) if (hw == CX18_HW_TUNER) { /* special tuner group handling */ - sd = v4l2_i2c_new_probed_subdev(&cx->v4l2_dev, - adap, mod, type, cx->card_i2c->radio); + sd = v4l2_i2c_new_subdev(&cx->v4l2_dev, + adap, mod, type, 0, cx->card_i2c->radio); if (sd != NULL) sd->grp_id = hw; - sd = v4l2_i2c_new_probed_subdev(&cx->v4l2_dev, - adap, mod, type, cx->card_i2c->demod); + sd = v4l2_i2c_new_subdev(&cx->v4l2_dev, + adap, mod, type, 0, cx->card_i2c->demod); if (sd != NULL) sd->grp_id = hw; - sd = v4l2_i2c_new_probed_subdev(&cx->v4l2_dev, - adap, mod, type, cx->card_i2c->tv); + sd = v4l2_i2c_new_subdev(&cx->v4l2_dev, + adap, mod, type, 0, cx->card_i2c->tv); if (sd != NULL) sd->grp_id = hw; return sd != NULL ? 0 : -1; @@ -167,7 +167,7 @@ int cx18_i2c_register(struct cx18 *cx, unsigned idx) return -1; /* It's an I2C device other than an analog tuner or IR chip */ - sd = v4l2_i2c_new_subdev(&cx->v4l2_dev, adap, mod, type, hw_addrs[idx]); + sd = v4l2_i2c_new_subdev(&cx->v4l2_dev, adap, mod, type, hw_addrs[idx], NULL); if (sd != NULL) sd->grp_id = hw; return sd != NULL ? 0 : -1; diff --git a/linux/drivers/media/video/cx231xx/cx231xx-cards.c b/linux/drivers/media/video/cx231xx/cx231xx-cards.c index f388262bd..84b37a906 100644 --- a/linux/drivers/media/video/cx231xx/cx231xx-cards.c +++ b/linux/drivers/media/video/cx231xx/cx231xx-cards.c @@ -327,7 +327,7 @@ void cx231xx_card_setup(struct cx231xx *dev) if (dev->board.decoder == CX231XX_AVDECODER) { dev->sd_cx25840 = v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_bus[0].i2c_adap, - "cx25840", "cx25840", 0x88 >> 1); + "cx25840", "cx25840", 0x88 >> 1, NULL); if (dev->sd_cx25840 == NULL) cx231xx_info("cx25840 subdev registration failure\n"); cx25840_call(dev, core, load_fw); @@ -337,7 +337,7 @@ void cx231xx_card_setup(struct cx231xx *dev) if (dev->board.tuner_type != TUNER_ABSENT) { dev->sd_tuner = v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_bus[1].i2c_adap, - "tuner", "tuner", 0xc2 >> 1); + "tuner", "tuner", 0xc2 >> 1, NULL); if (dev->sd_tuner == NULL) cx231xx_info("tuner subdev registration failure\n"); diff --git a/linux/drivers/media/video/cx23885/cx23885-cards.c b/linux/drivers/media/video/cx23885/cx23885-cards.c index 2ffc83e60..8be8b819e 100644 --- a/linux/drivers/media/video/cx23885/cx23885-cards.c +++ b/linux/drivers/media/video/cx23885/cx23885-cards.c @@ -930,7 +930,7 @@ void cx23885_card_setup(struct cx23885_dev *dev) case CX23885_BOARD_NETUP_DUAL_DVBS2_CI: dev->sd_cx25840 = v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_bus[2].i2c_adap, - "cx25840", "cx25840", 0x88 >> 1); + "cx25840", "cx25840", 0x88 >> 1, NULL); v4l2_subdev_call(dev->sd_cx25840, core, load_fw); break; } diff --git a/linux/drivers/media/video/cx23885/cx23885-video.c b/linux/drivers/media/video/cx23885/cx23885-video.c index fc7af991e..1f8161829 100644 --- a/linux/drivers/media/video/cx23885/cx23885-video.c +++ b/linux/drivers/media/video/cx23885/cx23885-video.c @@ -1777,11 +1777,11 @@ int cx23885_video_register(struct cx23885_dev *dev) if (dev->tuner_addr) sd = v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_bus[1].i2c_adap, - "tuner", "tuner", dev->tuner_addr); + "tuner", "tuner", dev->tuner_addr, NULL); else - sd = v4l2_i2c_new_probed_subdev(&dev->v4l2_dev, + sd = v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_bus[1].i2c_adap, - "tuner", "tuner", v4l2_i2c_tuner_addrs(ADDRS_TV)); + "tuner", "tuner", 0, v4l2_i2c_tuner_addrs(ADDRS_TV)); if (sd) { struct tuner_setup tun_setup; diff --git a/linux/drivers/media/video/cx88/cx88-cards.c b/linux/drivers/media/video/cx88/cx88-cards.c index 67ccc59a7..c3cfdd463 100644 --- a/linux/drivers/media/video/cx88/cx88-cards.c +++ b/linux/drivers/media/video/cx88/cx88-cards.c @@ -3418,20 +3418,20 @@ struct cx88_core *cx88_core_create(struct pci_dev *pci, int nr) The radio_type is sometimes missing, or set to UNSET but later code configures a tea5767. */ - v4l2_i2c_new_probed_subdev(&core->v4l2_dev, &core->i2c_adap, + v4l2_i2c_new_subdev(&core->v4l2_dev, &core->i2c_adap, "tuner", "tuner", - v4l2_i2c_tuner_addrs(ADDRS_RADIO)); + 0, v4l2_i2c_tuner_addrs(ADDRS_RADIO)); if (has_demod) - v4l2_i2c_new_probed_subdev(&core->v4l2_dev, + v4l2_i2c_new_subdev(&core->v4l2_dev, &core->i2c_adap, "tuner", "tuner", - v4l2_i2c_tuner_addrs(ADDRS_DEMOD)); + 0, v4l2_i2c_tuner_addrs(ADDRS_DEMOD)); if (core->board.tuner_addr == ADDR_UNSET) { - v4l2_i2c_new_probed_subdev(&core->v4l2_dev, + v4l2_i2c_new_subdev(&core->v4l2_dev, &core->i2c_adap, "tuner", "tuner", - has_demod ? tv_addrs + 4 : tv_addrs); + 0, has_demod ? tv_addrs + 4 : tv_addrs); } else { v4l2_i2c_new_subdev(&core->v4l2_dev, &core->i2c_adap, - "tuner", "tuner", core->board.tuner_addr); + "tuner", "tuner", core->board.tuner_addr, NULL); } } diff --git a/linux/drivers/media/video/cx88/cx88-video.c b/linux/drivers/media/video/cx88/cx88-video.c index d4bd9ba68..9ec7d2f57 100644 --- a/linux/drivers/media/video/cx88/cx88-video.c +++ b/linux/drivers/media/video/cx88/cx88-video.c @@ -2155,14 +2155,14 @@ static int __devinit cx8800_initdev(struct pci_dev *pci_dev, if (core->board.audio_chip == V4L2_IDENT_WM8775) v4l2_i2c_new_subdev(&core->v4l2_dev, &core->i2c_adap, - "wm8775", "wm8775", 0x36 >> 1); + "wm8775", "wm8775", 0x36 >> 1, NULL); if (core->board.audio_chip == V4L2_IDENT_TVAUDIO) { /* This probes for a tda9874 as is used on some Pixelview Ultra boards. */ - v4l2_i2c_new_probed_subdev_addr(&core->v4l2_dev, + v4l2_i2c_new_subdev(&core->v4l2_dev, &core->i2c_adap, - "tvaudio", "tvaudio", 0xb0 >> 1); + "tvaudio", "tvaudio", 0, I2C_ADDRS(0xb0 >> 1)); } switch (core->boardnr) { diff --git a/linux/drivers/media/video/davinci/vpif_display.c b/linux/drivers/media/video/davinci/vpif_display.c index 969d4b3aa..0f0ec8dc6 100644 --- a/linux/drivers/media/video/davinci/vpif_display.c +++ b/linux/drivers/media/video/davinci/vpif_display.c @@ -1566,10 +1566,10 @@ static __init int vpif_probe(struct platform_device *pdev) } for (i = 0; i < subdev_count; i++) { - vpif_obj.sd[i] = v4l2_i2c_new_probed_subdev(&vpif_obj.v4l2_dev, + vpif_obj.sd[i] = v4l2_i2c_new_subdev(&vpif_obj.v4l2_dev, i2c_adap, subdevdata[i].name, subdevdata[i].name, - &subdevdata[i].addr); + 0, I2C_ADDRS(subdevdata[i].addr)); if (!vpif_obj.sd[i]) { vpif_err("Error registering v4l2 subdevice\n"); goto probe_subdev_out; diff --git a/linux/drivers/media/video/em28xx/em28xx-cards.c b/linux/drivers/media/video/em28xx/em28xx-cards.c index 9a09df296..02e251f8c 100644 --- a/linux/drivers/media/video/em28xx/em28xx-cards.c +++ b/linux/drivers/media/video/em28xx/em28xx-cards.c @@ -2428,61 +2428,61 @@ void em28xx_card_setup(struct em28xx *dev) /* request some modules */ if (dev->board.has_msp34xx) - v4l2_i2c_new_probed_subdev(&dev->v4l2_dev, &dev->i2c_adap, - "msp3400", "msp3400", msp3400_addrs); + v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap, + "msp3400", "msp3400", 0, msp3400_addrs); if (dev->board.decoder == EM28XX_SAA711X) - v4l2_i2c_new_probed_subdev(&dev->v4l2_dev, &dev->i2c_adap, - "saa7115", "saa7115_auto", saa711x_addrs); + v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap, + "saa7115", "saa7115_auto", 0, saa711x_addrs); if (dev->board.decoder == EM28XX_TVP5150) - v4l2_i2c_new_probed_subdev(&dev->v4l2_dev, &dev->i2c_adap, - "tvp5150", "tvp5150", tvp5150_addrs); + v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap, + "tvp5150", "tvp5150", 0, tvp5150_addrs); if (dev->em28xx_sensor == EM28XX_MT9V011) { struct v4l2_subdev *sd; - sd = v4l2_i2c_new_probed_subdev(&dev->v4l2_dev, - &dev->i2c_adap, "mt9v011", "mt9v011", mt9v011_addrs); + sd = v4l2_i2c_new_subdev(&dev->v4l2_dev, + &dev->i2c_adap, "mt9v011", "mt9v011", 0, mt9v011_addrs); v4l2_subdev_call(sd, core, s_config, 0, &dev->sensor_xtal); } #if 0 /* FIXME: use mt9m001 after their conversion to v4l dev/subdev */ if (dev->em28xx_sensor == EM28XX_MT9M001) - v4l2_i2c_new_probed_subdev(&dev->v4l2_dev, &dev->i2c_adap, - "mt9m001", "mt9m001", mt9v011_addrs); + v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap, + "mt9m001", "mt9m001", 0, mt9v011_addrs); #endif if (dev->board.adecoder == EM28XX_TVAUDIO) v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap, - "tvaudio", "tvaudio", dev->board.tvaudio_addr); + "tvaudio", "tvaudio", dev->board.tvaudio_addr, NULL); if (dev->board.tuner_type != TUNER_ABSENT) { int has_demod = (dev->tda9887_conf & TDA9887_PRESENT); if (dev->board.radio.type) v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap, - "tuner", "tuner", dev->board.radio_addr); + "tuner", "tuner", dev->board.radio_addr, NULL); if (has_demod) - v4l2_i2c_new_probed_subdev(&dev->v4l2_dev, + v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap, "tuner", "tuner", - v4l2_i2c_tuner_addrs(ADDRS_DEMOD)); + 0, v4l2_i2c_tuner_addrs(ADDRS_DEMOD)); if (dev->tuner_addr == 0) { enum v4l2_i2c_tuner_type type = has_demod ? ADDRS_TV_WITH_DEMOD : ADDRS_TV; struct v4l2_subdev *sd; - sd = v4l2_i2c_new_probed_subdev(&dev->v4l2_dev, + sd = v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap, "tuner", "tuner", - v4l2_i2c_tuner_addrs(type)); + 0, v4l2_i2c_tuner_addrs(type)); if (sd) dev->tuner_addr = v4l2_i2c_subdev_addr(sd); } else { v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap, - "tuner", "tuner", dev->tuner_addr); + "tuner", "tuner", dev->tuner_addr, NULL); } } diff --git a/linux/drivers/media/video/ivtv/ivtv-i2c.c b/linux/drivers/media/video/ivtv/ivtv-i2c.c index b5c94d646..32d0b84d7 100644 --- a/linux/drivers/media/video/ivtv/ivtv-i2c.c +++ b/linux/drivers/media/video/ivtv/ivtv-i2c.c @@ -165,19 +165,19 @@ int ivtv_i2c_register(struct ivtv *itv, unsigned idx) return -1; if (hw == IVTV_HW_TUNER) { /* special tuner handling */ - sd = v4l2_i2c_new_probed_subdev(&itv->v4l2_dev, + sd = v4l2_i2c_new_subdev(&itv->v4l2_dev, adap, mod, type, - itv->card_i2c->radio); + 0, itv->card_i2c->radio); if (sd) sd->grp_id = 1 << idx; - sd = v4l2_i2c_new_probed_subdev(&itv->v4l2_dev, + sd = v4l2_i2c_new_subdev(&itv->v4l2_dev, adap, mod, type, - itv->card_i2c->demod); + 0, itv->card_i2c->demod); if (sd) sd->grp_id = 1 << idx; - sd = v4l2_i2c_new_probed_subdev(&itv->v4l2_dev, + sd = v4l2_i2c_new_subdev(&itv->v4l2_dev, adap, mod, type, - itv->card_i2c->tv); + 0, itv->card_i2c->tv); if (sd) sd->grp_id = 1 << idx; return sd ? 0 : -1; @@ -185,11 +185,11 @@ int ivtv_i2c_register(struct ivtv *itv, unsigned idx) if (!hw_addrs[idx]) return -1; if (hw == IVTV_HW_UPD64031A || hw == IVTV_HW_UPD6408X) { - sd = v4l2_i2c_new_probed_subdev_addr(&itv->v4l2_dev, - adap, mod, type, hw_addrs[idx]); + sd = v4l2_i2c_new_subdev(&itv->v4l2_dev, + adap, mod, type, 0, I2C_ADDRS(hw_addrs[idx])); } else { sd = v4l2_i2c_new_subdev(&itv->v4l2_dev, - adap, mod, type, hw_addrs[idx]); + adap, mod, type, hw_addrs[idx], NULL); } if (sd) sd->grp_id = 1 << idx; diff --git a/linux/drivers/media/video/mxb.c b/linux/drivers/media/video/mxb.c index 411efcd34..d727acaa5 100644 --- a/linux/drivers/media/video/mxb.c +++ b/linux/drivers/media/video/mxb.c @@ -190,19 +190,19 @@ static int mxb_probe(struct saa7146_dev *dev) } mxb->saa7111a = v4l2_i2c_new_subdev(&dev->v4l2_dev, &mxb->i2c_adapter, - "saa7115", "saa7111", I2C_SAA7111A); + "saa7115", "saa7111", I2C_SAA7111A, NULL); mxb->tea6420_1 = v4l2_i2c_new_subdev(&dev->v4l2_dev, &mxb->i2c_adapter, - "tea6420", "tea6420", I2C_TEA6420_1); + "tea6420", "tea6420", I2C_TEA6420_1, NULL); mxb->tea6420_2 = v4l2_i2c_new_subdev(&dev->v4l2_dev, &mxb->i2c_adapter, - "tea6420", "tea6420", I2C_TEA6420_2); + "tea6420", "tea6420", I2C_TEA6420_2, NULL); mxb->tea6415c = v4l2_i2c_new_subdev(&dev->v4l2_dev, &mxb->i2c_adapter, - "tea6415c", "tea6415c", I2C_TEA6415C); + "tea6415c", "tea6415c", I2C_TEA6415C, NULL); mxb->tda9840 = v4l2_i2c_new_subdev(&dev->v4l2_dev, &mxb->i2c_adapter, - "tda9840", "tda9840", I2C_TDA9840); + "tda9840", "tda9840", I2C_TDA9840, NULL); mxb->tuner = v4l2_i2c_new_subdev(&dev->v4l2_dev, &mxb->i2c_adapter, - "tuner", "tuner", I2C_TUNER); + "tuner", "tuner", I2C_TUNER, NULL); if (v4l2_i2c_new_subdev(&dev->v4l2_dev, &mxb->i2c_adapter, - "saa5246a", "saa5246a", I2C_SAA5246A)) { + "saa5246a", "saa5246a", I2C_SAA5246A, NULL)) { printk(KERN_INFO "mxb: found teletext decoder\n"); } diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c index 0bbd20f13..493232936 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -2080,8 +2080,8 @@ static int pvr2_hdw_load_subdev(struct pvr2_hdw *hdw, return -EINVAL; } - /* Note how the 2nd and 3rd arguments are the same for both - * v4l2_i2c_new_subdev() and v4l2_i2c_new_probed_subdev(). Why? + /* Note how the 2nd and 3rd arguments are the same for + * v4l2_i2c_new_subdev(). Why? * Well the 2nd argument is the module name to load, while the 3rd * argument is documented in the framework as being the "chipid" - * and every other place where I can find examples of this, the @@ -2094,15 +2094,15 @@ static int pvr2_hdw_load_subdev(struct pvr2_hdw *hdw, mid, i2caddr[0]); sd = v4l2_i2c_new_subdev(&hdw->v4l2_dev, &hdw->i2c_adap, fname, fname, - i2caddr[0]); + i2caddr[0], NULL); } else { pvr2_trace(PVR2_TRACE_INIT, "Module ID %u:" " Setting up with address probe list", mid); - sd = v4l2_i2c_new_probed_subdev(&hdw->v4l2_dev, &hdw->i2c_adap, + sd = v4l2_i2c_new_subdev(&hdw->v4l2_dev, &hdw->i2c_adap, fname, fname, - i2caddr); + 0, i2caddr); } if (!sd) { diff --git a/linux/drivers/media/video/saa7134/saa7134-cards.c b/linux/drivers/media/video/saa7134/saa7134-cards.c index c18b41ee6..22fdc40d1 100644 --- a/linux/drivers/media/video/saa7134/saa7134-cards.c +++ b/linux/drivers/media/video/saa7134/saa7134-cards.c @@ -7110,22 +7110,22 @@ int saa7134_board_init2(struct saa7134_dev *dev) if (dev->radio_type != UNSET) v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap, "tuner", "tuner", - dev->radio_addr); + dev->radio_addr, NULL); if (has_demod) - v4l2_i2c_new_probed_subdev(&dev->v4l2_dev, + v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap, "tuner", "tuner", - v4l2_i2c_tuner_addrs(ADDRS_DEMOD)); + 0, v4l2_i2c_tuner_addrs(ADDRS_DEMOD)); if (dev->tuner_addr == ADDR_UNSET) { enum v4l2_i2c_tuner_type type = has_demod ? ADDRS_TV_WITH_DEMOD : ADDRS_TV; - v4l2_i2c_new_probed_subdev(&dev->v4l2_dev, + v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap, "tuner", "tuner", - v4l2_i2c_tuner_addrs(type)); + 0, v4l2_i2c_tuner_addrs(type)); } else { v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap, "tuner", "tuner", - dev->tuner_addr); + dev->tuner_addr, NULL); } } diff --git a/linux/drivers/media/video/saa7134/saa7134-core.c b/linux/drivers/media/video/saa7134/saa7134-core.c index e466afd18..d0080370f 100644 --- a/linux/drivers/media/video/saa7134/saa7134-core.c +++ b/linux/drivers/media/video/saa7134/saa7134-core.c @@ -1061,7 +1061,7 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev, struct v4l2_subdev *sd = v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap, "saa6752hs", "saa6752hs", - saa7134_boards[dev->board].empress_addr); + saa7134_boards[dev->board].empress_addr, NULL); if (sd) sd->grp_id = GRP_EMPRESS; @@ -1070,9 +1070,9 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev, if (saa7134_boards[dev->board].rds_addr) { struct v4l2_subdev *sd; - sd = v4l2_i2c_new_probed_subdev_addr(&dev->v4l2_dev, + sd = v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap, "saa6588", "saa6588", - saa7134_boards[dev->board].rds_addr); + 0, I2C_ADDRS(saa7134_boards[dev->board].rds_addr)); if (sd) { printk(KERN_INFO "%s: found RDS decoder\n", dev->name); dev->has_rds = 1; diff --git a/linux/drivers/media/video/usbvision/usbvision-i2c.c b/linux/drivers/media/video/usbvision/usbvision-i2c.c index b74ada0c6..82c7d298d 100644 --- a/linux/drivers/media/video/usbvision/usbvision-i2c.c +++ b/linux/drivers/media/video/usbvision/usbvision-i2c.c @@ -250,9 +250,9 @@ int usbvision_i2c_register(struct usb_usbvision *usbvision) switch (usbvision_device_data[usbvision->DevModel].Codec) { case CODEC_SAA7113: case CODEC_SAA7111: - v4l2_i2c_new_probed_subdev(&usbvision->v4l2_dev, + v4l2_i2c_new_subdev(&usbvision->v4l2_dev, &usbvision->i2c_adap, "saa7115", - "saa7115_auto", saa711x_addrs); + "saa7115_auto", 0, saa711x_addrs); break; } if (usbvision_device_data[usbvision->DevModel].Tuner == 1) { @@ -260,16 +260,16 @@ int usbvision_i2c_register(struct usb_usbvision *usbvision) enum v4l2_i2c_tuner_type type; struct tuner_setup tun_setup; - sd = v4l2_i2c_new_probed_subdev(&usbvision->v4l2_dev, + sd = v4l2_i2c_new_subdev(&usbvision->v4l2_dev, &usbvision->i2c_adap, "tuner", - "tuner", v4l2_i2c_tuner_addrs(ADDRS_DEMOD)); + "tuner", 0, v4l2_i2c_tuner_addrs(ADDRS_DEMOD)); /* depending on whether we found a demod or not, select the tuner type. */ type = sd ? ADDRS_TV_WITH_DEMOD : ADDRS_TV; - sd = v4l2_i2c_new_probed_subdev(&usbvision->v4l2_dev, + sd = v4l2_i2c_new_subdev(&usbvision->v4l2_dev, &usbvision->i2c_adap, "tuner", - "tuner", v4l2_i2c_tuner_addrs(type)); + "tuner", 0, v4l2_i2c_tuner_addrs(type)); if (usbvision->tuner_type != -1) { tun_setup.mode_mask = T_ANALOG_TV | T_RADIO; diff --git a/linux/drivers/media/video/v4l2-common.c b/linux/drivers/media/video/v4l2-common.c index 864ee0772..fe1dfc00b 100644 --- a/linux/drivers/media/video/v4l2-common.c +++ b/linux/drivers/media/video/v4l2-common.c @@ -818,163 +818,6 @@ static struct i2c_client *v4l2_i2c_legacy_find_client(struct i2c_adapter *adap, #endif -/* Load an i2c sub-device. */ -struct v4l2_subdev *v4l2_i2c_new_subdev(struct v4l2_device *v4l2_dev, - struct i2c_adapter *adapter, - const char *module_name, const char *client_type, u8 addr) -{ - struct v4l2_subdev *sd = NULL; - struct i2c_client *client; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) - struct i2c_board_info info; -#endif - - BUG_ON(!v4l2_dev); - - if (module_name) - request_module(module_name); - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) - /* Setup the i2c board info with the device type and - the device address. */ - memset(&info, 0, sizeof(info)); - strlcpy(info.type, client_type, sizeof(info.type)); - info.addr = addr; - - /* Create the i2c client */ - client = i2c_new_device(adapter, &info); -#else - /* Legacy code: loading the module automatically - probes and creates the i2c_client on the adapter. - Try to find the client by walking the adapter's client list. */ - client = v4l2_i2c_legacy_find_client(adapter, addr); -#endif - /* Note: it is possible in the future that - c->driver is NULL if the driver is still being loaded. - We need better support from the kernel so that we - can easily wait for the load to finish. */ - if (client == NULL || client->driver == NULL) - goto error; - - /* Lock the module so we can safely get the v4l2_subdev pointer */ - if (!try_module_get(client->driver->driver.owner)) - goto error; - sd = i2c_get_clientdata(client); - - /* Register with the v4l2_device which increases the module's - use count as well. */ - if (v4l2_device_register_subdev(v4l2_dev, sd)) - sd = NULL; - /* Decrease the module use count to match the first try_module_get. */ - module_put(client->driver->driver.owner); - - if (sd) { - /* We return errors from v4l2_subdev_call only if we have the - callback as the .s_config is not mandatory */ - int err = v4l2_subdev_call(sd, core, s_config, 0, NULL); - - if (err && err != -ENOIOCTLCMD) { - v4l2_device_unregister_subdev(sd); - sd = NULL; - } - } - -error: -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) - /* If we have a client but no subdev, then something went wrong and - we must unregister the client. */ - if (client && sd == NULL) - i2c_unregister_device(client); -#endif - return sd; -} -EXPORT_SYMBOL_GPL(v4l2_i2c_new_subdev); - -/* Probe and load an i2c sub-device. */ -struct v4l2_subdev *v4l2_i2c_new_probed_subdev(struct v4l2_device *v4l2_dev, - struct i2c_adapter *adapter, - const char *module_name, const char *client_type, - const unsigned short *addrs) -{ - struct v4l2_subdev *sd = NULL; - struct i2c_client *client = NULL; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) - struct i2c_board_info info; -#endif - - BUG_ON(!v4l2_dev); - - if (module_name) - request_module(module_name); - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) - /* Setup the i2c board info with the device type and - the device address. */ - memset(&info, 0, sizeof(info)); - strlcpy(info.type, client_type, sizeof(info.type)); - - /* Probe and create the i2c client */ - client = i2c_new_probed_device(adapter, &info, addrs); -#else - /* Legacy code: loading the module should automatically - probe and create the i2c_client on the adapter. - Try to find the client by walking the adapter's client list - for each of the possible addresses. */ - while (!client && *addrs != I2C_CLIENT_END) - client = v4l2_i2c_legacy_find_client(adapter, *addrs++); -#endif - /* Note: it is possible in the future that - c->driver is NULL if the driver is still being loaded. - We need better support from the kernel so that we - can easily wait for the load to finish. */ - if (client == NULL || client->driver == NULL) - goto error; - - /* Lock the module so we can safely get the v4l2_subdev pointer */ - if (!try_module_get(client->driver->driver.owner)) - goto error; - sd = i2c_get_clientdata(client); - - /* Register with the v4l2_device which increases the module's - use count as well. */ - if (v4l2_device_register_subdev(v4l2_dev, sd)) - sd = NULL; - /* Decrease the module use count to match the first try_module_get. */ - module_put(client->driver->driver.owner); - - if (sd) { - /* We return errors from v4l2_subdev_call only if we have the - callback as the .s_config is not mandatory */ - int err = v4l2_subdev_call(sd, core, s_config, 0, NULL); - - if (err && err != -ENOIOCTLCMD) { - v4l2_device_unregister_subdev(sd); - sd = NULL; - } - } - -error: -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) - /* If we have a client but no subdev, then something went wrong and - we must unregister the client. */ - if (client && sd == NULL) - i2c_unregister_device(client); -#endif - return sd; -} -EXPORT_SYMBOL_GPL(v4l2_i2c_new_probed_subdev); - -struct v4l2_subdev *v4l2_i2c_new_probed_subdev_addr(struct v4l2_device *v4l2_dev, - struct i2c_adapter *adapter, - const char *module_name, const char *client_type, u8 addr) -{ - unsigned short addrs[2] = { addr, I2C_CLIENT_END }; - - return v4l2_i2c_new_probed_subdev(v4l2_dev, adapter, - module_name, client_type, addrs); -} -EXPORT_SYMBOL_GPL(v4l2_i2c_new_probed_subdev_addr); - /* Load an i2c sub-device. */ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) struct v4l2_subdev *v4l2_i2c_new_subdev_board(struct v4l2_device *v4l2_dev, diff --git a/linux/drivers/media/video/vino.c b/linux/drivers/media/video/vino.c index af03ec2d5..8383e6f80 100644 --- a/linux/drivers/media/video/vino.c +++ b/linux/drivers/media/video/vino.c @@ -4337,11 +4337,11 @@ static int __init vino_module_init(void) vino_init_stage++; vino_drvdata->decoder = - v4l2_i2c_new_probed_subdev_addr(&vino_drvdata->v4l2_dev, - &vino_i2c_adapter, "saa7191", "saa7191", 0x45); + v4l2_i2c_new_subdev(&vino_drvdata->v4l2_dev, &vino_i2c_adapter, + "saa7191", "saa7191", 0, I2C_ADDRS(0x45)); vino_drvdata->camera = - v4l2_i2c_new_probed_subdev_addr(&vino_drvdata->v4l2_dev, - &vino_i2c_adapter, "indycam", "indycam", 0x2b); + v4l2_i2c_new_subdev(&vino_drvdata->v4l2_dev, &vino_i2c_adapter, + "indycam", "indycam", 0, I2C_ADDRS(0x2b)); dprintk("init complete!\n"); diff --git a/linux/drivers/media/video/w9968cf.c b/linux/drivers/media/video/w9968cf.c index 5324c092a..c52301762 100644 --- a/linux/drivers/media/video/w9968cf.c +++ b/linux/drivers/media/video/w9968cf.c @@ -3529,9 +3529,9 @@ w9968cf_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) w9968cf_turn_on_led(cam); w9968cf_i2c_init(cam); - cam->sensor_sd = v4l2_i2c_new_probed_subdev(&cam->v4l2_dev, + cam->sensor_sd = v4l2_i2c_new_subdev(&cam->v4l2_dev, &cam->i2c_adapter, - "ovcamchip", "ovcamchip", addrs); + "ovcamchip", "ovcamchip", 0, addrs); usb_set_intfdata(intf, cam); mutex_unlock(&cam->dev_mutex); diff --git a/linux/drivers/media/video/zoran/zoran_card.c b/linux/drivers/media/video/zoran/zoran_card.c index 217fec9e4..74509d627 100644 --- a/linux/drivers/media/video/zoran/zoran_card.c +++ b/linux/drivers/media/video/zoran/zoran_card.c @@ -1358,15 +1358,15 @@ static int __devinit zoran_probe(struct pci_dev *pdev, goto zr_free_irq; } - zr->decoder = v4l2_i2c_new_probed_subdev(&zr->v4l2_dev, + zr->decoder = v4l2_i2c_new_subdev(&zr->v4l2_dev, &zr->i2c_adapter, zr->card.mod_decoder, zr->card.i2c_decoder, - zr->card.addrs_decoder); + 0, zr->card.addrs_decoder); if (zr->card.mod_encoder) - zr->encoder = v4l2_i2c_new_probed_subdev(&zr->v4l2_dev, + zr->encoder = v4l2_i2c_new_subdev(&zr->v4l2_dev, &zr->i2c_adapter, zr->card.mod_encoder, zr->card.i2c_encoder, - zr->card.addrs_encoder); + 0, zr->card.addrs_encoder); dprintk(2, KERN_INFO "%s: Initializing videocodec bus...\n", -- cgit v1.2.3 From 06db2bf24db3684dec5bc4cb6883c196e8a8cbba Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 19 Jun 2009 16:32:56 +0200 Subject: v4l: remove video_register_device_index From: Hans Verkuil video_register_device_index is never actually called, instead the stream index number is always calculated automatically. This patch removes this function and simplifies the internal get_index function since that can now always just return the first free index. Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/v4l2-dev.c | 55 ++++++++++-------------------------- 1 file changed, 15 insertions(+), 40 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/v4l2-dev.c b/linux/drivers/media/video/v4l2-dev.c index 9969abb28..9f04a8e6d 100644 --- a/linux/drivers/media/video/v4l2-dev.c +++ b/linux/drivers/media/video/v4l2-dev.c @@ -337,32 +337,28 @@ static const struct file_operations v4l2_fops = { }; /** - * get_index - assign stream number based on parent device + * get_index - assign stream index number based on parent device * @vdev: video_device to assign index number to, vdev->parent should be assigned - * @num: -1 if auto assign, requested number otherwise * * Note that when this is called the new device has not yet been registered - * in the video_device array. + * in the video_device array, but it was able to obtain a minor number. * - * Returns -ENFILE if num is already in use, a free index number if - * successful. + * This means that we can always obtain a free stream index number since + * the worst case scenario is that there are VIDEO_NUM_DEVICES - 1 slots in + * use of the video_device array. + * + * Returns a free index number. */ -static int get_index(struct video_device *vdev, int num) +static int get_index(struct video_device *vdev) { /* This can be static since this function is called with the global videodev_lock held. */ static DECLARE_BITMAP(used, VIDEO_NUM_DEVICES); int i; - if (num >= VIDEO_NUM_DEVICES) { - printk(KERN_ERR "videodev: %s num is too large\n", __func__); - return -EINVAL; - } - - /* Some drivers do not set the parent. In that case always return - num or 0. */ + /* Some drivers do not set the parent. In that case always return 0. */ if (vdev->parent == NULL) - return num >= 0 ? num : 0; + return 0; bitmap_zero(used, VIDEO_NUM_DEVICES); @@ -373,30 +369,15 @@ static int get_index(struct video_device *vdev, int num) } } - if (num >= 0) { - if (test_bit(num, used)) - return -ENFILE; - return num; - } - - i = find_first_zero_bit(used, VIDEO_NUM_DEVICES); - return i == VIDEO_NUM_DEVICES ? -ENFILE : i; + return find_first_zero_bit(used, VIDEO_NUM_DEVICES); } -int video_register_device(struct video_device *vdev, int type, int nr) -{ - return video_register_device_index(vdev, type, nr, -1); -} -EXPORT_SYMBOL(video_register_device); - /** - * video_register_device_index - register video4linux devices + * video_register_device - register video4linux devices * @vdev: video device structure we want to register * @type: type of device to register * @nr: which device number (0 == /dev/video0, 1 == /dev/video1, ... * -1 == first free) - * @index: stream number based on parent device; - * -1 if auto assign, requested number otherwise * * The registration code assigns minor numbers based on the type * requested. -ENFILE is returned in all the device slots for this @@ -415,8 +396,7 @@ EXPORT_SYMBOL(video_register_device); * * %VFL_TYPE_RADIO - A radio card */ -int video_register_device_index(struct video_device *vdev, int type, int nr, - int index) +int video_register_device(struct video_device *vdev, int type, int nr) { int i = 0; int ret; @@ -519,14 +499,9 @@ int video_register_device_index(struct video_device *vdev, int type, int nr, set_bit(nr, video_nums[type]); /* Should not happen since we thought this minor was free */ WARN_ON(video_device[vdev->minor] != NULL); - ret = vdev->index = get_index(vdev, index); + vdev->index = get_index(vdev); mutex_unlock(&videodev_lock); - if (ret < 0) { - printk(KERN_ERR "%s: get_index failed\n", __func__); - goto cleanup; - } - /* Part 3: Initialize the character device */ vdev->cdev = cdev_alloc(); if (vdev->cdev == NULL) { @@ -611,7 +586,7 @@ cleanup: vdev->minor = -1; return ret; } -EXPORT_SYMBOL(video_register_device_index); +EXPORT_SYMBOL(video_register_device); /** * video_unregister_device - unregister a video4linux device -- cgit v1.2.3 From bce52916562346cea9474564c12897c762d87e46 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 27 Jul 2009 19:05:19 -0300 Subject: af9015: avoid magically sized temporary buffer in eeprom_dump From: Jan Nikitenko Replace printing to magically sized temporary buffer with use of KERN_CONT for continual printing of eeprom registers dump. Since deb_info is defined as dprintk, which is conditionally defined to printk without additional parameters, meaning that deb_info is equivalent to direct printk (without adding KERN_ facility), we can use KERN_DEBUG and KERN_CONT in there, eliminating the need for sprintf into temporary buffer with not easily readable/magical size. Though it's strange, that deb_info definition uses printk without KERN_ facility and callers don't use it either. Signed-off-by: Jan Nikitenko Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/dvb-usb/af9015.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/dvb-usb/af9015.c b/linux/drivers/media/dvb/dvb-usb/af9015.c index b6fc8ddf3..a94f4d305 100644 --- a/linux/drivers/media/dvb/dvb-usb/af9015.c +++ b/linux/drivers/media/dvb/dvb-usb/af9015.c @@ -541,24 +541,22 @@ exit: /* dump eeprom */ static int af9015_eeprom_dump(struct dvb_usb_device *d) { - char buf[4+3*16+1], buf2[4]; u8 reg, val; for (reg = 0; ; reg++) { if (reg % 16 == 0) { if (reg) - deb_info("%s\n", buf); - sprintf(buf, "%02x: ", reg); + deb_info(KERN_CONT "\n"); + deb_info(KERN_DEBUG "%02x:", reg); } if (af9015_read_reg_i2c(d, AF9015_I2C_EEPROM, reg, &val) == 0) - sprintf(buf2, "%02x ", val); + deb_info(KERN_CONT " %02x", val); else - strcpy(buf2, "-- "); - strcat(buf, buf2); + deb_info(KERN_CONT " --"); if (reg == 0xff) break; } - deb_info("%s\n", buf); + deb_info(KERN_CONT "\n"); return 0; } -- cgit v1.2.3 From f47aedd6b5ff27a36bee52be6cd41b022375b133 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 19 Jun 2009 19:56:56 +0000 Subject: Stop defining I2C adapter IDs nobody uses From: Jean Delvare There is no point in defining I2C adapter IDs when no code is using them. As this field might go away in the future, stop using it when we don't need to. Signed-off-by: Jean Delvare Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/au0828/au0828-i2c.c | 1 - linux/drivers/media/video/bt8xx/bttv-i2c.c | 4 ++++ linux/drivers/media/video/cafe_ccic.c | 1 - linux/drivers/media/video/cx18/cx18-i2c.c | 2 ++ linux/drivers/media/video/cx231xx/cx231xx-i2c.c | 1 - linux/drivers/media/video/cx23885/cx23885-i2c.c | 2 ++ linux/drivers/media/video/em28xx/em28xx-i2c.c | 2 ++ linux/drivers/media/video/hdpvr/hdpvr-i2c.c | 1 - linux/drivers/media/video/ivtv/ivtv-i2c.c | 4 ++++ linux/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c | 2 ++ linux/drivers/media/video/vino.c | 1 - linux/drivers/media/video/w9968cf.c | 1 - linux/drivers/media/video/zoran/zoran_card.c | 1 - 13 files changed, 16 insertions(+), 7 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/au0828/au0828-i2c.c b/linux/drivers/media/video/au0828/au0828-i2c.c index bbe38a7a2..4031d6bd3 100644 --- a/linux/drivers/media/video/au0828/au0828-i2c.c +++ b/linux/drivers/media/video/au0828/au0828-i2c.c @@ -324,7 +324,6 @@ static struct i2c_algorithm au0828_i2c_algo_template = { static struct i2c_adapter au0828_i2c_adap_template = { .name = DRIVER_NAME, .owner = THIS_MODULE, - .id = I2C_HW_B_AU0828, .algo = &au0828_i2c_algo_template, #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26) .class = I2C_CLASS_TV_ANALOG, diff --git a/linux/drivers/media/video/bt8xx/bttv-i2c.c b/linux/drivers/media/video/bt8xx/bttv-i2c.c index 4febaf881..84c1e7167 100644 --- a/linux/drivers/media/video/bt8xx/bttv-i2c.c +++ b/linux/drivers/media/video/bt8xx/bttv-i2c.c @@ -355,7 +355,9 @@ int __devinit init_bttv_i2c(struct bttv *btv) /* bt878 */ strlcpy(btv->c.i2c_adap.name, "bt878", sizeof(btv->c.i2c_adap.name)); +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 31) btv->c.i2c_adap.id = I2C_HW_B_BT848; /* FIXME */ +#endif #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19) btv->c.i2c_adap.algo = (struct i2c_algorithm *)&bttv_algo; #else @@ -369,7 +371,9 @@ int __devinit init_bttv_i2c(struct bttv *btv) strlcpy(btv->c.i2c_adap.name, "bttv", sizeof(btv->c.i2c_adap.name)); +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 31) btv->c.i2c_adap.id = I2C_HW_B_BT848; +#endif memcpy(&btv->i2c_algo, &bttv_i2c_algo_bit_template, sizeof(bttv_i2c_algo_bit_template)); btv->i2c_algo.udelay = i2c_udelay; diff --git a/linux/drivers/media/video/cafe_ccic.c b/linux/drivers/media/video/cafe_ccic.c index 4b8ecad1b..2c78c35e8 100644 --- a/linux/drivers/media/video/cafe_ccic.c +++ b/linux/drivers/media/video/cafe_ccic.c @@ -491,7 +491,6 @@ static int cafe_smbus_setup(struct cafe_camera *cam) int ret; cafe_smbus_enable_irq(cam); - adap->id = I2C_HW_SMBUS_CAFE; adap->owner = THIS_MODULE; adap->algo = &cafe_smbus_algo; strcpy(adap->name, "cafe_ccic"); diff --git a/linux/drivers/media/video/cx18/cx18-i2c.c b/linux/drivers/media/video/cx18/cx18-i2c.c index 3c76a1e27..cee650c58 100644 --- a/linux/drivers/media/video/cx18/cx18-i2c.c +++ b/linux/drivers/media/video/cx18/cx18-i2c.c @@ -190,7 +190,9 @@ static int cx18_getsda(void *data) /* template for i2c-bit-algo */ static struct i2c_adapter cx18_i2c_adap_template = { .name = "cx18 i2c driver", +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 31) .id = I2C_HW_B_CX2341X, +#endif .algo = NULL, /* set by i2c-algo-bit */ .algo_data = NULL, /* filled from template */ .owner = THIS_MODULE, diff --git a/linux/drivers/media/video/cx231xx/cx231xx-i2c.c b/linux/drivers/media/video/cx231xx/cx231xx-i2c.c index 4525fab35..f9bfb10bd 100644 --- a/linux/drivers/media/video/cx231xx/cx231xx-i2c.c +++ b/linux/drivers/media/video/cx231xx/cx231xx-i2c.c @@ -435,7 +435,6 @@ static struct i2c_algorithm cx231xx_algo = { static struct i2c_adapter cx231xx_adap_template = { .owner = THIS_MODULE, .name = "cx231xx", - .id = I2C_HW_B_CX231XX, .algo = &cx231xx_algo, }; diff --git a/linux/drivers/media/video/cx23885/cx23885-i2c.c b/linux/drivers/media/video/cx23885/cx23885-i2c.c index 2e3f3d37c..8823c8781 100644 --- a/linux/drivers/media/video/cx23885/cx23885-i2c.c +++ b/linux/drivers/media/video/cx23885/cx23885-i2c.c @@ -287,7 +287,9 @@ static struct i2c_algorithm cx23885_i2c_algo_template = { static struct i2c_adapter cx23885_i2c_adap_template = { .name = "cx23885", .owner = THIS_MODULE, +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 31) .id = I2C_HW_B_CX23885, +#endif .algo = &cx23885_i2c_algo_template, #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26) .class = I2C_CLASS_TV_ANALOG, diff --git a/linux/drivers/media/video/em28xx/em28xx-i2c.c b/linux/drivers/media/video/em28xx/em28xx-i2c.c index 91cff2af3..5ed24c23a 100644 --- a/linux/drivers/media/video/em28xx/em28xx-i2c.c +++ b/linux/drivers/media/video/em28xx/em28xx-i2c.c @@ -465,7 +465,9 @@ static struct i2c_adapter em28xx_adap_template = { .class = I2C_CLASS_TV_ANALOG, #endif .name = "em28xx", +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 31) .id = I2C_HW_B_EM28XX, +#endif .algo = &em28xx_algo, }; diff --git a/linux/drivers/media/video/hdpvr/hdpvr-i2c.c b/linux/drivers/media/video/hdpvr/hdpvr-i2c.c index c4b5d1515..296330a0e 100644 --- a/linux/drivers/media/video/hdpvr/hdpvr-i2c.c +++ b/linux/drivers/media/video/hdpvr/hdpvr-i2c.c @@ -127,7 +127,6 @@ int hdpvr_register_i2c_adapter(struct hdpvr_device *dev) sizeof(i2c_adap->name)); i2c_adap->algo = &hdpvr_algo; i2c_adap->class = I2C_CLASS_TV_ANALOG; - i2c_adap->id = I2C_HW_B_HDPVR; i2c_adap->owner = THIS_MODULE; i2c_adap->dev.parent = &dev->udev->dev; diff --git a/linux/drivers/media/video/ivtv/ivtv-i2c.c b/linux/drivers/media/video/ivtv/ivtv-i2c.c index 484a323f1..b5c94d646 100644 --- a/linux/drivers/media/video/ivtv/ivtv-i2c.c +++ b/linux/drivers/media/video/ivtv/ivtv-i2c.c @@ -516,7 +516,9 @@ static struct i2c_algorithm ivtv_algo = { /* template for our-bit banger */ static struct i2c_adapter ivtv_i2c_adap_hw_template = { .name = "ivtv i2c driver", +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 31) .id = I2C_HW_B_CX2341X, +#endif .algo = &ivtv_algo, .algo_data = NULL, /* filled from template */ .owner = THIS_MODULE, @@ -570,7 +572,9 @@ static int ivtv_getsda_old(void *data) /* template for i2c-bit-algo */ static struct i2c_adapter ivtv_i2c_adap_template = { .name = "ivtv i2c driver", +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 31) .id = I2C_HW_B_CX2341X, +#endif .algo = NULL, /* set by i2c-algo-bit */ .algo_data = NULL, /* filled from template */ .owner = THIS_MODULE, diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c b/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c index 24644fc96..dbc0551f0 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c @@ -618,7 +618,9 @@ static struct i2c_algorithm pvr2_i2c_algo_template = { static struct i2c_adapter pvr2_i2c_adap_template = { .owner = THIS_MODULE, .class = 0, +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 31) .id = I2C_HW_B_BT848, +#endif }; diff --git a/linux/drivers/media/video/vino.c b/linux/drivers/media/video/vino.c index 7c39b43ee..af03ec2d5 100644 --- a/linux/drivers/media/video/vino.c +++ b/linux/drivers/media/video/vino.c @@ -1776,7 +1776,6 @@ static struct i2c_algo_sgi_data i2c_sgi_vino_data = { static struct i2c_adapter vino_i2c_adapter = { .name = "VINO I2C bus", - .id = I2C_HW_SGI_VINO, .algo = &sgi_algo, .algo_data = &i2c_sgi_vino_data, .owner = THIS_MODULE, diff --git a/linux/drivers/media/video/w9968cf.c b/linux/drivers/media/video/w9968cf.c index 86738d186..5324c092a 100644 --- a/linux/drivers/media/video/w9968cf.c +++ b/linux/drivers/media/video/w9968cf.c @@ -1508,7 +1508,6 @@ static int w9968cf_i2c_init(struct w9968cf_device* cam) }; static struct i2c_adapter adap = { - .id = I2C_HW_SMBUS_W9968CF, .owner = THIS_MODULE, #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26) .class = I2C_CLASS_TV_ANALOG, diff --git a/linux/drivers/media/video/zoran/zoran_card.c b/linux/drivers/media/video/zoran/zoran_card.c index 85f63116d..217fec9e4 100644 --- a/linux/drivers/media/video/zoran/zoran_card.c +++ b/linux/drivers/media/video/zoran/zoran_card.c @@ -733,7 +733,6 @@ zoran_register_i2c (struct zoran *zr) memcpy(&zr->i2c_algo, &zoran_i2c_bit_data_template, sizeof(struct i2c_algo_bit_data)); zr->i2c_algo.data = zr; - zr->i2c_adapter.id = I2C_HW_B_ZR36067; strlcpy(zr->i2c_adapter.name, ZR_DEVNAME(zr), sizeof(zr->i2c_adapter.name)); i2c_set_adapdata(&zr->i2c_adapter, &zr->v4l2_dev); -- cgit v1.2.3 From 8bb4698d464cdc18e0a36599e76fb4234d37c0eb Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Sat, 20 Jun 2009 09:58:57 +0200 Subject: gspca - pac7311: Webcam 093a:2629 added. From: Jean-Francois Moine Priority: normal Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/pac7311.c | 1 + 1 file changed, 1 insertion(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/pac7311.c b/linux/drivers/media/video/gspca/pac7311.c index 6a857805a..ed10134c9 100644 --- a/linux/drivers/media/video/gspca/pac7311.c +++ b/linux/drivers/media/video/gspca/pac7311.c @@ -1082,6 +1082,7 @@ static __devinitdata struct usb_device_id device_table[] = { {USB_DEVICE(0x093a, 0x2622), .driver_info = SENSOR_PAC7302}, {USB_DEVICE(0x093a, 0x2624), .driver_info = SENSOR_PAC7302}, {USB_DEVICE(0x093a, 0x2626), .driver_info = SENSOR_PAC7302}, + {USB_DEVICE(0x093a, 0x2629), .driver_info = SENSOR_PAC7302}, {USB_DEVICE(0x093a, 0x262a), .driver_info = SENSOR_PAC7302}, {USB_DEVICE(0x093a, 0x262c), .driver_info = SENSOR_PAC7302}, {} -- cgit v1.2.3 From bf4c25c5673f3c61136300f25c14379f0f08757a Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 20 Jun 2009 11:29:12 +0200 Subject: radio-tea5764: fix incorrect rxsubchans value From: Hans Verkuil rxsubchans was only set when stereo was detected, otherwise it was left to 0 instead of setting it to mono. Priority: normal Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/radio/radio-tea5764.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/radio/radio-tea5764.c b/linux/drivers/media/radio/radio-tea5764.c index 9194a70aa..83a5aff7b 100644 --- a/linux/drivers/media/radio/radio-tea5764.c +++ b/linux/drivers/media/radio/radio-tea5764.c @@ -326,7 +326,9 @@ static int vidioc_g_tuner(struct file *file, void *priv, v->rangehigh = FREQ_MAX * FREQ_MUL; v->capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO; if (r->tunchk & TEA5764_TUNCHK_STEREO) - v->rxsubchans = V4L2_TUNER_SUB_STEREO; + v->rxsubchans = V4L2_TUNER_SUB_STEREO; + else + v->rxsubchans = V4L2_TUNER_SUB_MONO; v->audmode = tea5764_get_audout_mode(radio); v->signal = TEA5764_TUNCHK_LEVEL(r->tunchk) * 0xffff / 0xf; v->afc = TEA5764_TUNCHK_IFCNT(r->tunchk); -- cgit v1.2.3 From 4481521273b6eb72974a3ce99b8eb642a4b39e13 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 20 Jun 2009 11:09:33 +0200 Subject: bttv: set RDS capability if applicable. From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/bt8xx/bttv-driver.c | 2 ++ 1 file changed, 2 insertions(+) (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 27be1694b..4bb66f246 100644 --- a/linux/drivers/media/video/bt8xx/bttv-driver.c +++ b/linux/drivers/media/video/bt8xx/bttv-driver.c @@ -2679,6 +2679,8 @@ static int bttv_querycap(struct file *file, void *priv, V4L2_CAP_VBI_CAPTURE | V4L2_CAP_READWRITE | V4L2_CAP_STREAMING; + if (btv->has_saa6588) + cap->capabilities |= V4L2_CAP_RDS_CAPTURE; if (no_overlay <= 0) cap->capabilities |= V4L2_CAP_VIDEO_OVERLAY; -- cgit v1.2.3 From c6a19e6b9dad80e01be1cd3fb194309f2e20478e Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 20 Jun 2009 11:09:14 +0200 Subject: saa6588: conform to the final RDS spec. From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/saa6588.c | 60 +++++++++++++++++++++++++++++-------- 1 file changed, 47 insertions(+), 13 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/saa6588.c b/linux/drivers/media/video/saa6588.c index 58aff8305..dcc83511e 100644 --- a/linux/drivers/media/video/saa6588.c +++ b/linux/drivers/media/video/saa6588.c @@ -51,7 +51,7 @@ I2C_CLIENT_INSMOD; /* insmod options */ static unsigned int debug; static unsigned int xtal; -static unsigned int rbds; +static unsigned int mmbs; static unsigned int plvl; static unsigned int bufblocks = 100; @@ -59,8 +59,8 @@ module_param(debug, int, 0644); MODULE_PARM_DESC(debug, "enable debug messages"); module_param(xtal, int, 0); MODULE_PARM_DESC(xtal, "select oscillator frequency (0..3), default 0"); -module_param(rbds, int, 0); -MODULE_PARM_DESC(rbds, "select mode, 0=RDS, 1=RBDS, default 0"); +module_param(mmbs, int, 0); +MODULE_PARM_DESC(mmbs, "enable MMBS mode: 0=off (default), 1=on"); module_param(plvl, int, 0); MODULE_PARM_DESC(plvl, "select pause level (0..3), default 0"); module_param(bufblocks, int, 0); @@ -89,6 +89,7 @@ struct saa6588 { unsigned char last_blocknum; wait_queue_head_t read_queue; int data_available_for_read; + u8 sync; }; static inline struct saa6588 *to_saa6588(struct v4l2_subdev *sd) @@ -272,13 +273,16 @@ static void saa6588_i2c_poll(struct saa6588 *s) unsigned char tmp; /* Although we only need 3 bytes, we have to read at least 6. - SAA6588 returns garbage otherwise */ + SAA6588 returns garbage otherwise. */ if (6 != i2c_master_recv(client, &tmpbuf[0], 6)) { if (debug > 1) dprintk(PREFIX "read error!\n"); return; } + s->sync = tmpbuf[0] & 0x10; + if (!s->sync) + return; blocknum = tmpbuf[0] >> 5; if (blocknum == s->last_blocknum) { if (debug > 3) @@ -297,9 +301,8 @@ static void saa6588_i2c_poll(struct saa6588 *s) occurred during reception of this block. Bit 6: Corrected bit. Indicates that an error was corrected for this data block. - Bits 5-3: Received Offset. Indicates the offset received - by the sync system. - Bits 2-0: Offset Name. Indicates the offset applied to this data. + Bits 5-3: Same as bits 0-2. + Bits 2-0: Block number. SAA6588 byte order is Status-MSB-LSB, so we have to swap the first and the last of the 3 bytes block. @@ -309,12 +312,21 @@ static void saa6588_i2c_poll(struct saa6588 *s) tmpbuf[2] = tmpbuf[0]; tmpbuf[0] = tmp; + /* Map 'Invalid block E' to 'Invalid Block' */ + if (blocknum == 6) + blocknum = V4L2_RDS_BLOCK_INVALID; + /* And if are not in mmbs mode, then 'Block E' is also mapped + to 'Invalid Block'. As far as I can tell MMBS is discontinued, + and if there is ever a need to support E blocks, then please + contact the linux-media mailinglist. */ + else if (!mmbs && blocknum == 5) + blocknum = V4L2_RDS_BLOCK_INVALID; tmp = blocknum; tmp |= blocknum << 3; /* Received offset == Offset Name (OK ?) */ if ((tmpbuf[2] & 0x03) == 0x03) - tmp |= 0x80; /* uncorrectable error */ + tmp |= V4L2_RDS_BLOCK_ERROR; /* uncorrectable error */ else if ((tmpbuf[2] & 0x03) != 0x00) - tmp |= 0x40; /* corrected error */ + tmp |= V4L2_RDS_BLOCK_CORRECTED; /* corrected error */ tmpbuf[2] = tmp; /* Is this enough ? Should we also check other bits ? */ spin_lock_irqsave(&s->lock, flags); @@ -340,14 +352,14 @@ static void saa6588_work(struct work_struct *work) schedule_delayed_work(&s->work, msecs_to_jiffies(20)); } -static int saa6588_configure(struct saa6588 *s) +static void saa6588_configure(struct saa6588 *s) { struct i2c_client *client = v4l2_get_subdevdata(&s->sd); unsigned char buf[3]; int rc; buf[0] = cSyncRestart; - if (rbds) + if (mmbs) buf[0] |= cProcessingModeRBDS; buf[1] = cFlywheelDefault; @@ -393,8 +405,6 @@ static int saa6588_configure(struct saa6588 *s) rc = i2c_master_send(client, buf, 3); if (rc != 3) printk(PREFIX "i2c i/o error: rc == %d (should be 3)\n", rc); - - return 0; } /* ---------------------------------------------------------------------- */ @@ -435,6 +445,24 @@ static long saa6588_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) return 0; } +static int saa6588_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt) +{ + struct saa6588 *s = to_saa6588(sd); + + vt->capability |= V4L2_TUNER_CAP_RDS; + if (s->sync) + vt->rxsubchans |= V4L2_TUNER_SUB_RDS; + return 0; +} + +static int saa6588_s_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt) +{ + struct saa6588 *s = to_saa6588(sd); + + saa6588_configure(s); + return 0; +} + static int saa6588_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip) { struct i2c_client *client = v4l2_get_subdevdata(sd); @@ -449,8 +477,14 @@ static const struct v4l2_subdev_core_ops saa6588_core_ops = { .ioctl = saa6588_ioctl, }; +static const struct v4l2_subdev_tuner_ops saa6588_tuner_ops = { + .g_tuner = saa6588_g_tuner, + .s_tuner = saa6588_s_tuner, +}; + static const struct v4l2_subdev_ops saa6588_ops = { .core = &saa6588_core_ops, + .tuner = &saa6588_tuner_ops, }; /* ---------------------------------------------------------------------- */ -- cgit v1.2.3 From 0c148383f104b18d677cf7877e17f7dbd2366837 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 20 Jun 2009 11:09:52 +0200 Subject: saa7134: set RDS capability if applicable. From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/saa7134/saa7134-core.c | 4 +++- linux/drivers/media/video/saa7134/saa7134-video.c | 2 ++ linux/drivers/media/video/saa7134/saa7134.h | 1 + 3 files changed, 6 insertions(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/saa7134/saa7134-core.c b/linux/drivers/media/video/saa7134/saa7134-core.c index da73430ad..e466afd18 100644 --- a/linux/drivers/media/video/saa7134/saa7134-core.c +++ b/linux/drivers/media/video/saa7134/saa7134-core.c @@ -1073,8 +1073,10 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev, sd = v4l2_i2c_new_probed_subdev_addr(&dev->v4l2_dev, &dev->i2c_adap, "saa6588", "saa6588", saa7134_boards[dev->board].rds_addr); - if (sd) + if (sd) { printk(KERN_INFO "%s: found RDS decoder\n", dev->name); + dev->has_rds = 1; + } } request_submodules(dev); diff --git a/linux/drivers/media/video/saa7134/saa7134-video.c b/linux/drivers/media/video/saa7134/saa7134-video.c index 4212c4ec8..c97ed1611 100644 --- a/linux/drivers/media/video/saa7134/saa7134-video.c +++ b/linux/drivers/media/video/saa7134/saa7134-video.c @@ -1826,6 +1826,8 @@ static int saa7134_querycap(struct file *file, void *priv, V4L2_CAP_READWRITE | V4L2_CAP_STREAMING | V4L2_CAP_TUNER; + if (dev->has_rds) + cap->capabilities |= V4L2_CAP_RDS_CAPTURE; if (saa7134_no_overlay <= 0) cap->capabilities |= V4L2_CAP_VIDEO_OVERLAY; diff --git a/linux/drivers/media/video/saa7134/saa7134.h b/linux/drivers/media/video/saa7134/saa7134.h index 454802e73..be5abf059 100644 --- a/linux/drivers/media/video/saa7134/saa7134.h +++ b/linux/drivers/media/video/saa7134/saa7134.h @@ -544,6 +544,7 @@ struct saa7134_dev { struct i2c_adapter i2c_adap; struct i2c_client i2c_client; unsigned char eedata[256]; + int has_rds; /* video overlay */ struct v4l2_framebuffer ovbuf; -- cgit v1.2.3 From 5927a4573d2ce0d49736a2fcb4b1e9673deda2fd Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 20 Jun 2009 11:19:09 +0200 Subject: radio-cadet: conform to the RDS spec. From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/radio/radio-cadet.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/radio/radio-cadet.c b/linux/drivers/media/radio/radio-cadet.c index 2fd4aae2e..99551d836 100644 --- a/linux/drivers/media/radio/radio-cadet.c +++ b/linux/drivers/media/radio/radio-cadet.c @@ -386,7 +386,8 @@ static int vidioc_querycap(struct file *file, void *priv, strlcpy(v->card, "ADS Cadet", sizeof(v->card)); strlcpy(v->bus_info, "ISA", sizeof(v->bus_info)); v->version = CADET_VERSION; - v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO | V4L2_CAP_READWRITE; + v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO | + V4L2_CAP_READWRITE | V4L2_CAP_RDS_CAPTURE; return 0; } @@ -399,7 +400,7 @@ static int vidioc_g_tuner(struct file *file, void *priv, switch (v->index) { case 0: strlcpy(v->name, "FM", sizeof(v->name)); - v->capability = V4L2_TUNER_CAP_STEREO; + v->capability = V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_RDS; v->rangelow = 1400; /* 87.5 MHz */ v->rangehigh = 1728; /* 108.0 MHz */ v->rxsubchans = cadet_getstereo(dev); @@ -413,6 +414,7 @@ static int vidioc_g_tuner(struct file *file, void *priv, default: break; } + v->rxsubchans |= V4L2_TUNER_SUB_RDS; break; case 1: strlcpy(v->name, "AM", sizeof(v->name)); -- cgit v1.2.3 From 80dc1cf3077100baf270a70d8624f5b682544baf Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 20 Jun 2009 11:25:14 +0200 Subject: radio-si470x: conform to the RDS spec. From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/radio/radio-si470x.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/radio/radio-si470x.c b/linux/drivers/media/radio/radio-si470x.c index 101ede1cf..81795da6d 100644 --- a/linux/drivers/media/radio/radio-si470x.c +++ b/linux/drivers/media/radio/radio-si470x.c @@ -1278,7 +1278,7 @@ static int si470x_vidioc_querycap(struct file *file, void *priv, usb_make_path(radio->usbdev, capability->bus_info, sizeof(capability->bus_info)); capability->version = DRIVER_KERNEL_VERSION; capability->capabilities = V4L2_CAP_HW_FREQ_SEEK | - V4L2_CAP_TUNER | V4L2_CAP_RADIO; + V4L2_CAP_TUNER | V4L2_CAP_RADIO | V4L2_CAP_RDS_CAPTURE; return 0; } @@ -1439,7 +1439,8 @@ static int si470x_vidioc_g_tuner(struct file *file, void *priv, /* driver constants */ strcpy(tuner->name, "FM"); tuner->type = V4L2_TUNER_RADIO; - tuner->capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO; + tuner->capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO | + V4L2_TUNER_CAP_RDS; /* range limits */ switch ((radio->registers[SYSCONFIG2] & SYSCONFIG2_BAND) >> 6) { @@ -1465,6 +1466,10 @@ static int si470x_vidioc_g_tuner(struct file *file, void *priv, tuner->rxsubchans = V4L2_TUNER_SUB_MONO; else tuner->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO; + /* If there is a reliable method of detecting an RDS channel, + then this code should check for that before setting this + RDS subchannel. */ + tuner->rxsubchans |= V4L2_TUNER_SUB_RDS; /* mono/stereo selector */ if ((radio->registers[POWERCFG] & POWERCFG_MONO) == 0) -- cgit v1.2.3 From 0d71e86e4235ce3ffe135f5b5d39118c0f0597c5 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 20 Jun 2009 14:18:34 +0200 Subject: tcm825x: remove incorrect __exit_p wrapper From: Hans Verkuil tcm825x_remove is not necessarily called on module exit, it can also be called when the i2c_adapter is removed. While the i2c adapter might never be removed on an embedded system, in practice this sensor driver can also be used in e.g. a USB webcam where this is a perfectly acceptable thing to do. Priority: normal Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/tcm825x.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/tcm825x.c b/linux/drivers/media/video/tcm825x.c index 559ade821..d778c41ef 100644 --- a/linux/drivers/media/video/tcm825x.c +++ b/linux/drivers/media/video/tcm825x.c @@ -882,7 +882,7 @@ static int tcm825x_probe(struct i2c_client *client, return rval; } -static int __exit tcm825x_remove(struct i2c_client *client) +static int tcm825x_remove(struct i2c_client *client) { struct tcm825x_sensor *sensor = i2c_get_clientdata(client); @@ -908,7 +908,7 @@ static struct i2c_driver tcm825x_i2c_driver = { .name = TCM825X_NAME, }, .probe = tcm825x_probe, - .remove = __exit_p(tcm825x_remove), + .remove = tcm825x_remove, #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) .id_table = tcm825x_id, #endif -- cgit v1.2.3 From ba1331c45ace13485b9d68ac3f2d574f1e80e229 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 20 Jun 2009 14:21:37 +0200 Subject: cx231xx: fix uninitialized variable. From: Hans Verkuil The variable 'rc' could be used uninitialized in the cx231xx_capture_start function. Sri informed me that it should be initialized to -1. Priority: normal Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/cx231xx/cx231xx-avcore.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/cx231xx/cx231xx-avcore.c b/linux/drivers/media/video/cx231xx/cx231xx-avcore.c index bbbb3f50e..28f48f41f 100644 --- a/linux/drivers/media/video/cx231xx/cx231xx-avcore.c +++ b/linux/drivers/media/video/cx231xx/cx231xx-avcore.c @@ -2046,7 +2046,7 @@ int cx231xx_initialize_stream_xfer(struct cx231xx *dev, u32 media_type) int cx231xx_capture_start(struct cx231xx *dev, int start, u8 media_type) { - int rc; + int rc = -1; u32 ep_mask = -1; struct pcb_config *pcb_config; -- cgit v1.2.3 From acf23fa81cd74df218b6eeafdb66477a6884e60a Mon Sep 17 00:00:00 2001 From: "Igor M. Liplianin" Date: Sat, 20 Jun 2009 15:51:48 +0300 Subject: Add ce5039(zl10039) tuner support. From: Igor M. Liplianin The code from Jan D. Louw with some minor changes. http://article.gmane.org/gmane.linux.drivers.dvb/38163 Tested with TeVii S630 DVB-S USB card by me (Igor) Signed-off-by: Igor M. Liplianin --- linux/drivers/media/dvb/frontends/Kconfig | 7 + linux/drivers/media/dvb/frontends/Makefile | 1 + linux/drivers/media/dvb/frontends/zl10039.c | 308 ++++++++++++++++++++++++++++ linux/drivers/media/dvb/frontends/zl10039.h | 40 ++++ 4 files changed, 356 insertions(+) create mode 100644 linux/drivers/media/dvb/frontends/zl10039.c create mode 100644 linux/drivers/media/dvb/frontends/zl10039.h (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/frontends/Kconfig b/linux/drivers/media/dvb/frontends/Kconfig index be967ac09..b794e860b 100644 --- a/linux/drivers/media/dvb/frontends/Kconfig +++ b/linux/drivers/media/dvb/frontends/Kconfig @@ -81,6 +81,13 @@ config DVB_ZL10036 help A DVB-S tuner module. Say Y when you want to support this frontend. +config DVB_ZL10039 + tristate "Zarlink ZL10039 silicon tuner" + depends on DVB_CORE && I2C + default m if DVB_FE_CUSTOMISE + help + A DVB-S tuner module. Say Y when you want to support this frontend. + config DVB_S5H1420 tristate "Samsung S5H1420 based" depends on DVB_CORE && I2C diff --git a/linux/drivers/media/dvb/frontends/Makefile b/linux/drivers/media/dvb/frontends/Makefile index 832473c1e..3b49d37ab 100644 --- a/linux/drivers/media/dvb/frontends/Makefile +++ b/linux/drivers/media/dvb/frontends/Makefile @@ -31,6 +31,7 @@ obj-$(CONFIG_DVB_SP887X) += sp887x.o obj-$(CONFIG_DVB_NXT6000) += nxt6000.o obj-$(CONFIG_DVB_MT352) += mt352.o obj-$(CONFIG_DVB_ZL10036) += zl10036.o +obj-$(CONFIG_DVB_ZL10039) += zl10039.o obj-$(CONFIG_DVB_ZL10353) += zl10353.o obj-$(CONFIG_DVB_CX22702) += cx22702.o obj-$(CONFIG_DVB_DRX397XD) += drx397xD.o diff --git a/linux/drivers/media/dvb/frontends/zl10039.c b/linux/drivers/media/dvb/frontends/zl10039.c new file mode 100644 index 000000000..11b29cb88 --- /dev/null +++ b/linux/drivers/media/dvb/frontends/zl10039.c @@ -0,0 +1,308 @@ +/* + * Driver for Zarlink ZL10039 DVB-S tuner + * + * Copyright 2007 Jan D. Louw + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include + +#include "dvb_frontend.h" +#include "zl10039.h" + +static int debug; + +#define dprintk(args...) \ + do { \ + if (debug) \ + printk(KERN_DEBUG args); \ + } while (0) + +enum zl10039_model_id { + ID_ZL10039 = 1 +}; + +struct zl10039_state { + struct i2c_adapter *i2c; + u8 i2c_addr; + u8 id; +}; + +enum zl10039_reg_addr { + PLL0 = 0, + PLL1, + PLL2, + PLL3, + RFFE, + BASE0, + BASE1, + BASE2, + LO0, + LO1, + LO2, + LO3, + LO4, + LO5, + LO6, + GENERAL +}; + +static int zl10039_read(const struct zl10039_state *state, + const enum zl10039_reg_addr reg, u8 *buf, + const size_t count) +{ + u8 regbuf[] = { reg }; + struct i2c_msg msg[] = { + {/* Write register address */ + .addr = state->i2c_addr, + .flags = 0, + .buf = regbuf, + .len = 1, + }, {/* Read count bytes */ + .addr = state->i2c_addr, + .flags = I2C_M_RD, + .buf = buf, + .len = count, + }, + }; + + dprintk("%s\n", __func__); + + if (i2c_transfer(state->i2c, msg, 2) != 2) { + dprintk("%s: i2c read error\n", __func__); + return -EREMOTEIO; + } + + return 0; /* Success */ +} + +static int zl10039_write(struct zl10039_state *state, + const enum zl10039_reg_addr reg, const u8 *src, + const size_t count) +{ + u8 buf[count + 1]; + struct i2c_msg msg = { + .addr = state->i2c_addr, + .flags = 0, + .buf = buf, + .len = count + 1, + }; + + dprintk("%s\n", __func__); + /* Write register address and data in one go */ + buf[0] = reg; + memcpy(&buf[1], src, count); + if (i2c_transfer(state->i2c, &msg, 1) != 1) { + dprintk("%s: i2c write error\n", __func__); + return -EREMOTEIO; + } + + return 0; /* Success */ +} + +static inline int zl10039_readreg(struct zl10039_state *state, + const enum zl10039_reg_addr reg, u8 *val) +{ + return zl10039_read(state, reg, val, 1); +} + +static inline int zl10039_writereg(struct zl10039_state *state, + const enum zl10039_reg_addr reg, + const u8 val) +{ + return zl10039_write(state, reg, &val, 1); +} + +static int zl10039_init(struct dvb_frontend *fe) +{ + struct zl10039_state *state = fe->tuner_priv; + int ret; + + dprintk("%s\n", __func__); + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); + /* Reset logic */ + ret = zl10039_writereg(state, GENERAL, 0x40); + if (ret < 0) { + dprintk("Note: i2c write error normal when resetting the " + "tuner\n"); + } + /* Wake up */ + ret = zl10039_writereg(state, GENERAL, 0x01); + if (ret < 0) { + dprintk("Tuner power up failed\n"); + return ret; + } + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 0); + + return 0; +} + +static int zl10039_sleep(struct dvb_frontend *fe) +{ + struct zl10039_state *state = fe->tuner_priv; + int ret; + + dprintk("%s\n", __func__); + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); + ret = zl10039_writereg(state, GENERAL, 0x80); + if (ret < 0) { + dprintk("Tuner sleep failed\n"); + return ret; + } + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 0); + + return 0; +} + +static int zl10039_set_params(struct dvb_frontend *fe, + struct dvb_frontend_parameters *params) +{ + struct zl10039_state *state = fe->tuner_priv; + u8 buf[6]; + u8 bf; + u32 fbw; + u32 div; + int ret; + + dprintk("%s\n", __func__); + dprintk("Set frequency = %d, symbol rate = %d\n", + params->frequency, params->u.qpsk.symbol_rate); + + /* Assumed 10.111 MHz crystal oscillator */ + /* Cancelled num/den 80 to prevent overflow */ + div = (params->frequency * 1000) / 126387; + fbw = (params->u.qpsk.symbol_rate * 27) / 32000; + /* Cancelled num/den 10 to prevent overflow */ + bf = ((fbw * 5088) / 1011100) - 1; + + /*PLL divider*/ + buf[0] = (div >> 8) & 0x7f; + buf[1] = (div >> 0) & 0xff; + /*Reference divider*/ + /* Select reference ratio of 80 */ + buf[2] = 0x1D; + /*PLL test modes*/ + buf[3] = 0x40; + /*RF Control register*/ + buf[4] = 0x6E; /* Bypass enable */ + /*Baseband filter cutoff */ + buf[5] = bf; + + /* Open i2c gate */ + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); + /* BR = 10, Enable filter adjustment */ + ret = zl10039_writereg(state, BASE1, 0x0A); + if (ret < 0) + goto error; + /* Write new config values */ + ret = zl10039_write(state, PLL0, buf, sizeof(buf)); + if (ret < 0) + goto error; + /* BR = 10, Disable filter adjustment */ + ret = zl10039_writereg(state, BASE1, 0x6A); + if (ret < 0) + goto error; + + /* Close i2c gate */ + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 0); + return 0; +error: + dprintk("Error setting tuner\n"); + return ret; +} + +static int zl10039_release(struct dvb_frontend *fe) +{ + struct zl10039_state *state = fe->tuner_priv; + + dprintk("%s\n", __func__); + kfree(state); + fe->tuner_priv = NULL; + return 0; +} + +static struct dvb_tuner_ops zl10039_ops = { + .release = zl10039_release, + .init = zl10039_init, + .sleep = zl10039_sleep, + .set_params = zl10039_set_params, +}; + +struct dvb_frontend *zl10039_attach(struct dvb_frontend *fe, + u8 i2c_addr, struct i2c_adapter *i2c) +{ + struct zl10039_state *state = NULL; + + dprintk("%s\n", __func__); + state = kmalloc(sizeof(struct zl10039_state), GFP_KERNEL); + if (state == NULL) + goto error; + + state->i2c = i2c; + state->i2c_addr = i2c_addr; + + /* Open i2c gate */ + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); + /* check if this is a valid tuner */ + if (zl10039_readreg(state, GENERAL, &state->id) < 0) { + /* Close i2c gate */ + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 0); + goto error; + } + /* Close i2c gate */ + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 0); + + state->id = state->id & 0x0f; + switch (state->id) { + case ID_ZL10039: + strcpy(fe->ops.tuner_ops.info.name, + "Zarlink ZL10039 DVB-S tuner"); + break; + default: + dprintk("Chip ID=%x does not match a known type\n", state->id); + break; + goto error; + } + + memcpy(&fe->ops.tuner_ops, &zl10039_ops, sizeof(struct dvb_tuner_ops)); + fe->tuner_priv = state; + dprintk("Tuner attached @ i2c address 0x%02x\n", i2c_addr); + return fe; +error: + kfree(state); + return NULL; +} +EXPORT_SYMBOL(zl10039_attach); + +module_param(debug, int, 0644); +MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off)."); +MODULE_DESCRIPTION("Zarlink ZL10039 DVB-S tuner driver"); +MODULE_AUTHOR("Jan D. Louw "); +MODULE_LICENSE("GPL"); diff --git a/linux/drivers/media/dvb/frontends/zl10039.h b/linux/drivers/media/dvb/frontends/zl10039.h new file mode 100644 index 000000000..5eee7ea16 --- /dev/null +++ b/linux/drivers/media/dvb/frontends/zl10039.h @@ -0,0 +1,40 @@ +/* + Driver for Zarlink ZL10039 DVB-S tuner + + Copyright (C) 2007 Jan D. Louw + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef ZL10039_H +#define ZL10039_H + +#if defined(CONFIG_DVB_ZL10039) || (defined(CONFIG_DVB_ZL10039_MODULE) \ + && defined(MODULE)) +struct dvb_frontend *zl10039_attach(struct dvb_frontend *fe, + u8 i2c_addr, + struct i2c_adapter *i2c); +#else +static inline struct dvb_frontend *zl10039_attach(struct dvb_frontend *fe, + u8 i2c_addr, + struct i2c_adapter *i2c) +{ + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); + return NULL; +} +#endif /* CONFIG_DVB_ZL10039 */ + +#endif /* ZL10039_H */ -- cgit v1.2.3 From a06280dab2e0258fda0e80e548df8a0e9c0eddca Mon Sep 17 00:00:00 2001 From: "Igor M. Liplianin" Date: Sat, 20 Jun 2009 15:54:18 +0300 Subject: Add TeVii S630 USB DVB-S card support. From: Igor M. Liplianin The card includes Intel ce5039(Zarlink zl10039) tuner and Intel ce6313 (Zarlink zl10313) demod. Signed-off-by: Igor M. Liplianin --- linux/drivers/media/dvb/dvb-usb/Kconfig | 6 +- linux/drivers/media/dvb/dvb-usb/dw2102.c | 184 ++++++++++++++++++++++++++++++- 2 files changed, 185 insertions(+), 5 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/dvb-usb/Kconfig b/linux/drivers/media/dvb/dvb-usb/Kconfig index 496c1a370..8b8bc04ee 100644 --- a/linux/drivers/media/dvb/dvb-usb/Kconfig +++ b/linux/drivers/media/dvb/dvb-usb/Kconfig @@ -253,7 +253,7 @@ config DVB_USB_AF9005_REMOTE Afatech AF9005 based receiver. config DVB_USB_DW2102 - tristate "DvbWorld DVB-S/S2 USB2.0 support" + tristate "DvbWorld & TeVii DVB-S/S2 USB2.0 support" depends on DVB_USB select DVB_PLL if !DVB_FE_CUSTOMISE select DVB_STV0299 if !DVB_FE_CUSTOMISE @@ -262,9 +262,11 @@ config DVB_USB_DW2102 select DVB_CX24116 if !DVB_FE_CUSTOMISE select DVB_SI21XX if !DVB_FE_CUSTOMISE select DVB_TDA10021 if !DVB_FE_CUSTOMISE + select DVB_MT312 if !DVB_FE_CUSTOMISE + select DVB_ZL10039 if !DVB_FE_CUSTOMISE help Say Y here to support the DvbWorld DVB-S/S2 USB2.0 receivers - and the TeVii S650. + and the TeVii S650, S630. config DVB_USB_CINERGY_T2 tristate "Terratec CinergyT2/qanu USB 2.0 DVB-T receiver" diff --git a/linux/drivers/media/dvb/dvb-usb/dw2102.c b/linux/drivers/media/dvb/dvb-usb/dw2102.c index 0fc9be43a..c8bdb2e78 100644 --- a/linux/drivers/media/dvb/dvb-usb/dw2102.c +++ b/linux/drivers/media/dvb/dvb-usb/dw2102.c @@ -1,6 +1,6 @@ /* DVB USB framework compliant Linux driver for the * DVBWorld DVB-S 2101, 2102, DVB-S2 2104, DVB-C 3101, -* TeVii S600, S650 Cards +* TeVii S600, S630, S650 Cards * Copyright (C) 2008,2009 Igor M. Liplianin (liplianin@me.by) * * This program is free software; you can redistribute it and/or modify it @@ -18,6 +18,8 @@ #include "eds1547.h" #include "cx24116.h" #include "tda1002x.h" +#include "mt312.h" +#include "zl10039.h" #ifndef USB_PID_DW2102 #define USB_PID_DW2102 0x2102 @@ -39,6 +41,10 @@ #define USB_PID_TEVII_S650 0xd650 #endif +#ifndef USB_PID_TEVII_S630 +#define USB_PID_TEVII_S630 0xd630 +#endif + #define DW210X_READ_MSG 0 #define DW210X_WRITE_MSG 1 @@ -436,6 +442,69 @@ static int dw3101_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[], return num; } +static int s630_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[], + int num) +{ + struct dvb_usb_device *d = i2c_get_adapdata(adap); + int ret = 0; + + if (!d) + return -ENODEV; + if (mutex_lock_interruptible(&d->i2c_mutex) < 0) + return -EAGAIN; + + switch (num) { + case 2: { /* read */ + u8 ibuf[msg[1].len], obuf[3]; + obuf[0] = msg[1].len; + obuf[1] = (msg[0].addr << 1); + obuf[2] = msg[0].buf[0]; + + ret = dw210x_op_rw(d->udev, 0x90, 0, 0, + obuf, 3, DW210X_WRITE_MSG); + msleep(5); + ret = dw210x_op_rw(d->udev, 0x91, 0, 0, + ibuf, msg[1].len, DW210X_READ_MSG); + memcpy(msg[1].buf, ibuf, msg[1].len); + break; + } + case 1: + switch (msg[0].addr) { + case 0x60: + case 0x0e: { + /* write to zl10313, zl10039 register, */ + u8 obuf[msg[0].len + 2]; + obuf[0] = msg[0].len + 1; + obuf[1] = (msg[0].addr << 1); + memcpy(obuf + 2, msg[0].buf, msg[0].len); + ret = dw210x_op_rw(d->udev, 0x80, 0, 0, + obuf, msg[0].len + 2, DW210X_WRITE_MSG); + break; + } + case (DW2102_RC_QUERY): { + u8 ibuf[4]; + ret = dw210x_op_rw(d->udev, 0xb8, 0, 0, + ibuf, 4, DW210X_READ_MSG); + msg[0].buf[0] = ibuf[3]; + break; + } + case (DW2102_VOLTAGE_CTRL): { + u8 obuf[2]; + obuf[0] = 0x03; + obuf[1] = msg[0].buf[0]; + ret = dw210x_op_rw(d->udev, 0x8a, 0, 0, + obuf, 2, DW210X_WRITE_MSG); + break; + } + } + + break; + } + + mutex_unlock(&d->i2c_mutex); + return num; +} + static u32 dw210x_i2c_func(struct i2c_adapter *adapter) { return I2C_FUNC_I2C; @@ -481,6 +550,14 @@ static struct i2c_algorithm dw3101_i2c_algo = { #endif }; +static struct i2c_algorithm s630_i2c_algo = { + .master_xfer = s630_i2c_transfer, + .functionality = dw210x_i2c_func, +#ifdef NEED_ALGO_CONTROL + .algo_control = dummy_algo_control, +#endif +}; + static int dw210x_read_mac_address(struct dvb_usb_device *d, u8 mac[6]) { int i; @@ -505,6 +582,37 @@ static int dw210x_read_mac_address(struct dvb_usb_device *d, u8 mac[6]) return 0; }; +static int s630_read_mac_address(struct dvb_usb_device *d, u8 mac[6]) +{ + int i, ret; + u8 buf[3], eeprom[256], eepromline[16]; + + for (i = 0; i < 256; i++) { + buf[0] = 1; + buf[1] = 0xa0; + buf[2] = i; + ret = dw210x_op_rw(d->udev, 0x90, 0, 0, + buf, 3, DW210X_WRITE_MSG); + ret = dw210x_op_rw(d->udev, 0x91, 0, 0, + buf, 1, DW210X_READ_MSG); + if (ret < 0) { + err("read eeprom failed."); + return -1; + } else { + eepromline[i % 16] = buf[0]; + eeprom[i] = buf[0]; + } + + if ((i % 16) == 15) { + deb_xfer("%02x: ", i - 15); + debug_dump(eepromline, 16, deb_xfer); + } + } + + memcpy(mac, eeprom + 16, 6); + return 0; +}; + static int dw210x_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) { static u8 command_13v[1] = {0x00}; @@ -550,6 +658,10 @@ static struct tda10023_config dw3101_tda10023_config = { .invert = 1, }; +static struct mt312_config zl313_config = { + .demod_address = 0x0e, +}; + static int dw2104_frontend_attach(struct dvb_usb_adapter *d) { if ((d->fe = dvb_attach(cx24116_attach, &dw2104_config, @@ -611,6 +723,18 @@ static int dw3101_frontend_attach(struct dvb_usb_adapter *d) return -EIO; } +static int s630_frontend_attach(struct dvb_usb_adapter *d) +{ + d->fe = dvb_attach(mt312_attach, &zl313_config, + &d->dev->i2c_adap); + if (d->fe != NULL) { + d->fe->ops.set_voltage = dw210x_set_voltage; + info("Attached zl10313!\n"); + return 0; + } + return -EIO; +} + static int dw2102_tuner_attach(struct dvb_usb_adapter *adap) { dvb_attach(dvb_pll_attach, adap->fe, 0x60, @@ -634,6 +758,14 @@ static int dw3101_tuner_attach(struct dvb_usb_adapter *adap) return 0; } +static int s630_zl10039_tuner_attach(struct dvb_usb_adapter *adap) +{ + dvb_attach(zl10039_attach, adap->fe, 0x60, + &adap->dev->i2c_adap); + + return 0; +} + static struct dvb_usb_rc_key dw210x_rc_keys[] = { { 0xf8, 0x0a, KEY_Q }, /*power*/ { 0xf8, 0x0c, KEY_M }, /*mute*/ @@ -778,7 +910,7 @@ static int dw2102_rc_query(struct dvb_usb_device *d, u32 *event, int *state) } *state = REMOTE_NO_KEY_PRESSED; - if (dw2102_i2c_transfer(&d->i2c_adap, &msg, 1) == 1) { + if (d->props.i2c_algo->master_xfer(&d->i2c_adap, &msg, 1) == 1) { for (i = 0; i < keymap_size ; i++) { if (keymap[i].data == msg.buf[0]) { *state = REMOTE_KEY_PRESSED; @@ -807,6 +939,7 @@ static struct usb_device_id dw2102_table[] = { {USB_DEVICE(0x9022, USB_PID_TEVII_S650)}, {USB_DEVICE(USB_VID_TERRATEC, USB_PID_CINERGY_S)}, {USB_DEVICE(USB_VID_CYPRESS, USB_PID_DW3101)}, + {USB_DEVICE(0x9022, USB_PID_TEVII_S630)}, { } }; @@ -821,6 +954,7 @@ static int dw2102_load_firmware(struct usb_device *dev, u8 reset16[] = {0, 0, 0, 0, 0, 0, 0}; const struct firmware *fw; const char *filename = "dvb-usb-dw2101.fw"; + switch (dev->descriptor.idProduct) { case 0x2101: ret = request_firmware(&fw, filename, &dev->dev); @@ -1068,6 +1202,48 @@ static struct dvb_usb_device_properties dw3101_properties = { } }; +static struct dvb_usb_device_properties s630_properties = { + .caps = DVB_USB_IS_AN_I2C_ADAPTER, + .usb_ctrl = DEVICE_SPECIFIC, + .firmware = "dvb-usb-s630.fw", + .no_reconnect = 1, + + .i2c_algo = &s630_i2c_algo, + .rc_key_map = tevii_rc_keys, + .rc_key_map_size = ARRAY_SIZE(tevii_rc_keys), + .rc_interval = 150, + .rc_query = dw2102_rc_query, + + .generic_bulk_ctrl_endpoint = 0x81, + .num_adapters = 1, + .download_firmware = dw2102_load_firmware, + .read_mac_address = s630_read_mac_address, + .adapter = { + { + .frontend_attach = s630_frontend_attach, + .streaming_ctrl = NULL, + .tuner_attach = s630_zl10039_tuner_attach, + .stream = { + .type = USB_BULK, + .count = 8, + .endpoint = 0x82, + .u = { + .bulk = { + .buffersize = 4096, + } + } + }, + } + }, + .num_device_descs = 1, + .devices = { + {"TeVii S630 USB", + {&dw2102_table[6], NULL}, + {NULL}, + }, + } +}; + static int dw2102_probe(struct usb_interface *intf, const struct usb_device_id *id) { @@ -1076,6 +1252,8 @@ static int dw2102_probe(struct usb_interface *intf, 0 == dvb_usb_device_init(intf, &dw2104_properties, THIS_MODULE, NULL, adapter_nr) || 0 == dvb_usb_device_init(intf, &dw3101_properties, + THIS_MODULE, NULL, adapter_nr) || + 0 == dvb_usb_device_init(intf, &s630_properties, THIS_MODULE, NULL, adapter_nr)) { return 0; } @@ -1109,6 +1287,6 @@ module_exit(dw2102_module_exit); MODULE_AUTHOR("Igor M. Liplianin (c) liplianin@me.by"); MODULE_DESCRIPTION("Driver for DVBWorld DVB-S 2101, 2102, DVB-S2 2104," " DVB-C 3101 USB2.0," - " TeVii S600, S650 USB2.0 devices"); + " TeVii S600, S630, S650 USB2.0 devices"); MODULE_VERSION("0.1"); MODULE_LICENSE("GPL"); -- cgit v1.2.3 From 425ae9ead3f700da2ef961eec1d70a603445ce42 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Sat, 20 Jun 2009 12:45:52 -0500 Subject: pvrusb2: Fix hardware scaling when used with cx25840 From: Mike Isely The cx25840 module requires that its VBI initialization entry point be called in order for hardware-scaled video capture to work properly - even if we don't care about VBI. Making this behavior even more subtle is that if the capture resolution is set to 720x480 - which is the default that the pvrusb2 driver sets up - then the cx25840 bypasses the hardware scaler. Therefore this problem does not manifest itself until some other resolution, e.g. 640x480, is tried. MythTV typically defaults to 640x480 or 480x480, which means that things break whenever the driver is used with MythTV. This all has been known for a while (since at least Nov 2006), but recent changes in the pvrusb2 driver (specifically in regards to sub-device support) caused this to break again. VBI initialization must happen *after* the chip's firmware is loaded, not before. With this fix, 24xxx devices work correctly again. A related fix that is part of this changeset is that now we re-initialize VBI any time after we issue a reset to the cx25840 driver. Issuing a chip reset erases the state that the VBI setup previously did. Until the HVR-1950 came along this subtlety went unnoticed, because the pvrusb2 driver previously never issued such a reset. But with the HVR-1950 we have to do that reset in order to correctly transition from digital back to analog mode - and since the HVR-1950 always starts in digital mode (required for the DVB side to initialize correctly) then this device has never had a chance to work correctly in analog mode! Analog capture on the HVR-1950 has been broken this *ENTIRE* time. I had missed it until now because I've usually been testing at the default 720x480 resolution which does not require scaling... What fun. By re-initializing VBI after a cx25840 chip reset, correct behavior is restored. Priority: high Signed-off-by: Mike Isely --- linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c | 55 ++++++++++++++----------- 1 file changed, 31 insertions(+), 24 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c index 3411cb36a..aeb2108e8 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -2004,6 +2004,34 @@ static unsigned int pvr2_copy_i2c_addr_list( } +static void pvr2_hdw_cx25840_vbi_hack(struct pvr2_hdw *hdw) +{ + /* + Mike Isely 19-Nov-2006 - This bit of nuttiness + for cx25840 causes that module to correctly set up its video + scaling. This is really a problem in the cx25840 module itself, + but we work around it here. The problem has not been seen in + ivtv because there VBI is supported and set up. We don't do VBI + here (at least not yet) and thus we never attempted to even set + it up. + */ + struct v4l2_format fmt; + if (hdw->decoder_client_id != PVR2_CLIENT_ID_CX25840) { + /* We're not using a cx25840 so don't enable the hack */ + return; + } + + pvr2_trace(PVR2_TRACE_INIT, + "Module ID %u:" + " Executing cx25840 VBI hack", + hdw->decoder_client_id); + memset(&fmt, 0, sizeof(fmt)); + fmt.type = V4L2_BUF_TYPE_SLICED_VBI_CAPTURE; + v4l2_device_call_all(&hdw->v4l2_dev, hdw->decoder_client_id, + video, s_fmt, &fmt); +} + + static int pvr2_hdw_load_subdev(struct pvr2_hdw *hdw, const struct pvr2_device_client_desc *cd) { @@ -2095,30 +2123,6 @@ static int pvr2_hdw_load_subdev(struct pvr2_hdw *hdw, /* client-specific setup... */ switch (mid) { case PVR2_CLIENT_ID_CX25840: - hdw->decoder_client_id = mid; - { - /* - Mike Isely 19-Nov-2006 - This - bit of nuttiness for cx25840 causes that module - to correctly set up its video scaling. This is - really a problem in the cx25840 module itself, - but we work around it here. The problem has not - been seen in ivtv because there VBI is supported - and set up. We don't do VBI here (at least not - yet) and thus we never attempted to even set it - up. - */ - struct v4l2_format fmt; - pvr2_trace(PVR2_TRACE_INIT, - "Module ID %u:" - " Executing cx25840 VBI hack", - mid); - memset(&fmt, 0, sizeof(fmt)); - fmt.type = V4L2_BUF_TYPE_SLICED_VBI_CAPTURE; - v4l2_device_call_all(&hdw->v4l2_dev, mid, - video, s_fmt, &fmt); - } - break; case PVR2_CLIENT_ID_SAA7115: hdw->decoder_client_id = mid; break; @@ -2219,6 +2223,8 @@ static void pvr2_hdw_setup_low(struct pvr2_hdw *hdw) cptr->info->set_value(cptr,~0,cptr->info->default_value); } + pvr2_hdw_cx25840_vbi_hack(hdw); + /* Set up special default values for the television and radio frequencies here. It's not really important what these defaults are, but I set them to something usable in the Chicago area just @@ -4170,6 +4176,7 @@ int pvr2_hdw_cmd_decoder_reset(struct pvr2_hdw *hdw) if (hdw->decoder_client_id) { v4l2_device_call_all(&hdw->v4l2_dev, hdw->decoder_client_id, core, reset, 0); + pvr2_hdw_cx25840_vbi_hack(hdw); return 0; } pvr2_trace(PVR2_TRACE_INIT, -- cgit v1.2.3 From 3ca980b27b7bbe0fea6a05ff9f978afe87e9f72b Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Sat, 20 Jun 2009 12:50:14 -0500 Subject: pvrusb2: Re-fix hardware scaling on video standard change From: Mike Isely The cx25840 module's VBI initialization logic uses the current video standard as part of its internal algorithm. This therefore means that we probably need to make sure that the correct video standard has been set before initializing VBI. (Normally we would not care about VBI, but as described in an earlier changeset, VBI must be initialized correctly on the cx25840 in order for the chip's hardware scaler to operate correctly.) It's kind of messy to force the video standard to be set before initializing VBI (mainly because we can't know what the app really wants that early in the initialization process). So this patch does the next best thing: VBI is re-initialized after any point where the video standard has been set. Priority: high Signed-off-by: Mike Isely --- linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c | 1 + 1 file changed, 1 insertion(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c index aeb2108e8..7b685c25c 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -2982,6 +2982,7 @@ static void pvr2_subdev_update(struct pvr2_hdw *hdw) vs = hdw->std_mask_cur; v4l2_device_call_all(&hdw->v4l2_dev, 0, core, s_std, vs); + pvr2_hdw_cx25840_vbi_hack(hdw); } hdw->tuner_signal_stale = !0; hdw->cropcap_stale = !0; -- cgit v1.2.3 From 174f826e6ffcaed552a04fd19771199c6aa95002 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Sat, 20 Jun 2009 12:51:29 -0500 Subject: pvrusb2: Change initial default frequency setting From: Mike Isely Change default frequency to be US Broadcast channel 3 - with the transition to d igital the previous value has now become useless. This change is PURELY to help with my testing (I need to set some kind of default so it might as well be some thing usable). Priority: normal Signed-off-by: Mike Isely --- linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c index 7b685c25c..0bbd20f13 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -86,8 +86,8 @@ MODULE_PARM_DESC(video_std,"specify initial video standard"); module_param_array(tolerance, int, NULL, 0444); MODULE_PARM_DESC(tolerance,"specify stream error tolerance"); -/* US Broadcast channel 7 (175.25 MHz) */ -static int default_tv_freq = 175250000L; +/* US Broadcast channel 3 (61.25 MHz), to help with testing */ +static int default_tv_freq = 61250000L; /* 104.3 MHz, a usable FM station for my area */ static int default_radio_freq = 104300000L; -- cgit v1.2.3 From 1f30421cb0e68cbe8e33c96a120610732666c5a1 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Sat, 20 Jun 2009 12:55:31 -0500 Subject: pvrusb2: Improve handling of routing schemes From: Mike Isely The pvrusb2 driver has a concept of "routing scheme" which defines which physical inputs should be connected based on application's choice of logical input. The correct "routing scheme" depends on the specific device since different devices might wire up their muxes differently - it can't be coded into the sub-device driver and it can't be just a single setting in the pvrusb2 driver since the driver handles multiple different devices. This concept has been in place for a while and works, however there are cases where a specific input for a specific device has no route - previously due to an oversight this was handled badly. With these changes the driver can now specifically recognize cases where there is no defined route for a given input. Priority: normal Signed-off-by: Mike Isely --- linux/drivers/media/video/pvrusb2/pvrusb2-audio.c | 14 +++++++------ .../drivers/media/video/pvrusb2/pvrusb2-cs53l32a.c | 14 +++++++------ .../media/video/pvrusb2/pvrusb2-cx2584x-v4l.c | 24 +++++++++++++--------- .../media/video/pvrusb2/pvrusb2-video-v4l.c | 24 +++++++++++++--------- 4 files changed, 44 insertions(+), 32 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-audio.c b/linux/drivers/media/video/pvrusb2/pvrusb2-audio.c index 86049f412..42875ec21 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-audio.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-audio.c @@ -49,11 +49,13 @@ static const int routing_scheme0[] = { MSP_DSP_IN_SCART), }; -static const struct routing_scheme routing_schemes[] = { - [PVR2_ROUTING_SCHEME_HAUPPAUGE] = { - .def = routing_scheme0, - .cnt = ARRAY_SIZE(routing_scheme0), - }, +static const struct routing_scheme routing_def0 = { + .def = routing_scheme0, + .cnt = ARRAY_SIZE(routing_scheme0), +}; + +static const struct routing_scheme *routing_schemes[] = { + [PVR2_ROUTING_SCHEME_HAUPPAUGE] = &routing_def0, }; void pvr2_msp3400_subdev_update(struct pvr2_hdw *hdw, struct v4l2_subdev *sd) @@ -66,7 +68,7 @@ void pvr2_msp3400_subdev_update(struct pvr2_hdw *hdw, struct v4l2_subdev *sd) pvr2_trace(PVR2_TRACE_CHIPS, "subdev msp3400 v4l2 set_stereo"); if ((sid < ARRAY_SIZE(routing_schemes)) && - ((sp = routing_schemes + sid) != NULL) && + ((sp = routing_schemes[sid]) != NULL) && (hdw->input_val >= 0) && (hdw->input_val < sp->cnt)) { input = sp->def[hdw->input_val]; diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-cs53l32a.c b/linux/drivers/media/video/pvrusb2/pvrusb2-cs53l32a.c index f99b77c92..0c361e0ce 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-cs53l32a.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-cs53l32a.c @@ -50,11 +50,13 @@ static const int routing_scheme1[] = { [PVR2_CVAL_INPUT_SVIDEO] = 0, }; -static const struct routing_scheme routing_schemes[] = { - [PVR2_ROUTING_SCHEME_ONAIR] = { - .def = routing_scheme1, - .cnt = ARRAY_SIZE(routing_scheme1), - }, +static const struct routing_scheme routing_def1 = { + .def = routing_scheme1, + .cnt = ARRAY_SIZE(routing_scheme1), +}; + +static const struct routing_scheme *routing_schemes[] = { + [PVR2_ROUTING_SCHEME_ONAIR] = &routing_def1, }; @@ -67,7 +69,7 @@ void pvr2_cs53l32a_subdev_update(struct pvr2_hdw *hdw, struct v4l2_subdev *sd) pvr2_trace(PVR2_TRACE_CHIPS, "subdev v4l2 set_input(%d)", hdw->input_val); if ((sid < ARRAY_SIZE(routing_schemes)) && - ((sp = routing_schemes + sid) != NULL) && + ((sp = routing_schemes[sid]) != NULL) && (hdw->input_val >= 0) && (hdw->input_val < sp->cnt)) { input = sp->def[hdw->input_val]; diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c b/linux/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c index ef47c3874..2334ece5f 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c @@ -69,6 +69,11 @@ static const struct routing_scheme_item routing_scheme0[] = { }, }; +static const struct routing_scheme routing_def0 = { + .def = routing_scheme0, + .cnt = ARRAY_SIZE(routing_scheme0), +}; + /* Specific to gotview device */ static const struct routing_scheme_item routing_schemegv[] = { [PVR2_CVAL_INPUT_TV] = { @@ -91,15 +96,14 @@ static const struct routing_scheme_item routing_schemegv[] = { }, }; -static const struct routing_scheme routing_schemes[] = { - [PVR2_ROUTING_SCHEME_HAUPPAUGE] = { - .def = routing_scheme0, - .cnt = ARRAY_SIZE(routing_scheme0), - }, - [PVR2_ROUTING_SCHEME_GOTVIEW] = { - .def = routing_schemegv, - .cnt = ARRAY_SIZE(routing_schemegv), - }, +static const struct routing_scheme routing_defgv = { + .def = routing_schemegv, + .cnt = ARRAY_SIZE(routing_schemegv), +}; + +static const struct routing_scheme *routing_schemes[] = { + [PVR2_ROUTING_SCHEME_HAUPPAUGE] = &routing_def0, + [PVR2_ROUTING_SCHEME_GOTVIEW] = &routing_defgv, }; void pvr2_cx25840_subdev_update(struct pvr2_hdw *hdw, struct v4l2_subdev *sd) @@ -112,7 +116,7 @@ void pvr2_cx25840_subdev_update(struct pvr2_hdw *hdw, struct v4l2_subdev *sd) unsigned int sid = hdw->hdw_desc->signal_routing_scheme; if ((sid < ARRAY_SIZE(routing_schemes)) && - ((sp = routing_schemes + sid) != NULL) && + ((sp = routing_schemes[sid]) != NULL) && (hdw->input_val >= 0) && (hdw->input_val < sp->cnt)) { vid_input = sp->def[hdw->input_val].vid; diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-video-v4l.c b/linux/drivers/media/video/pvrusb2/pvrusb2-video-v4l.c index d240331a6..915452b4d 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-video-v4l.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-video-v4l.c @@ -55,6 +55,11 @@ static const int routing_scheme0[] = { [PVR2_CVAL_INPUT_SVIDEO] = SAA7115_SVIDEO2, }; +static const struct routing_scheme routing_def0 = { + .def = routing_scheme0, + .cnt = ARRAY_SIZE(routing_scheme0), +}; + static const int routing_scheme1[] = { [PVR2_CVAL_INPUT_TV] = SAA7115_COMPOSITE4, [PVR2_CVAL_INPUT_RADIO] = SAA7115_COMPOSITE5, @@ -62,15 +67,14 @@ static const int routing_scheme1[] = { [PVR2_CVAL_INPUT_SVIDEO] = SAA7115_SVIDEO2, /* or SVIDEO0, it seems */ }; -static const struct routing_scheme routing_schemes[] = { - [PVR2_ROUTING_SCHEME_HAUPPAUGE] = { - .def = routing_scheme0, - .cnt = ARRAY_SIZE(routing_scheme0), - }, - [PVR2_ROUTING_SCHEME_ONAIR] = { - .def = routing_scheme1, - .cnt = ARRAY_SIZE(routing_scheme1), - }, +static const struct routing_scheme routing_def1 = { + .def = routing_scheme1, + .cnt = ARRAY_SIZE(routing_scheme1), +}; + +static const struct routing_scheme *routing_schemes[] = { + [PVR2_ROUTING_SCHEME_HAUPPAUGE] = &routing_def0, + [PVR2_ROUTING_SCHEME_ONAIR] = &routing_def1, }; void pvr2_saa7115_subdev_update(struct pvr2_hdw *hdw, struct v4l2_subdev *sd) @@ -83,7 +87,7 @@ void pvr2_saa7115_subdev_update(struct pvr2_hdw *hdw, struct v4l2_subdev *sd) pvr2_trace(PVR2_TRACE_CHIPS, "subdev v4l2 set_input(%d)", hdw->input_val); if ((sid < ARRAY_SIZE(routing_schemes)) && - ((sp = routing_schemes + sid) != NULL) && + ((sp = routing_schemes[sid]) != NULL) && (hdw->input_val >= 0) && (hdw->input_val < sp->cnt)) { input = sp->def[hdw->input_val]; -- cgit v1.2.3 From b5fad74c736ea557049dd331ad48dc4bef7a81bd Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Sat, 20 Jun 2009 12:57:24 -0500 Subject: pvrusb2: De-obfuscate code which handles routing schemes From: Mike Isely This change does not change any outward behavior; it merely chops down some large if-conditions with embedded assignments into something a little more maintainable for others (I of course never had a problem with this...). Priority: normal Signed-off-by: Mike Isely --- linux/drivers/media/video/pvrusb2/pvrusb2-cs53l32a.c | 12 ++++++------ linux/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c | 15 +++++++-------- linux/drivers/media/video/pvrusb2/pvrusb2-video-v4l.c | 13 +++++++------ 3 files changed, 20 insertions(+), 20 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-cs53l32a.c b/linux/drivers/media/video/pvrusb2/pvrusb2-cs53l32a.c index 0c361e0ce..7bcaa0cd4 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-cs53l32a.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-cs53l32a.c @@ -68,12 +68,11 @@ void pvr2_cs53l32a_subdev_update(struct pvr2_hdw *hdw, struct v4l2_subdev *sd) u32 input; pvr2_trace(PVR2_TRACE_CHIPS, "subdev v4l2 set_input(%d)", hdw->input_val); - if ((sid < ARRAY_SIZE(routing_schemes)) && - ((sp = routing_schemes[sid]) != NULL) && - (hdw->input_val >= 0) && - (hdw->input_val < sp->cnt)) { - input = sp->def[hdw->input_val]; - } else { + sp = (sid < ARRAY_SIZE(routing_schemes)) ? + routing_schemes[sid] : NULL; + if ((sp == NULL) || + (hdw->input_val < 0) || + (hdw->input_val >= sp->cnt)) { pvr2_trace(PVR2_TRACE_ERROR_LEGS, "*** WARNING *** subdev v4l2 set_input:" " Invalid routing scheme (%u)" @@ -81,6 +80,7 @@ void pvr2_cs53l32a_subdev_update(struct pvr2_hdw *hdw, struct v4l2_subdev *sd) sid, hdw->input_val); return; } + input = sp->def[hdw->input_val]; sd->ops->audio->s_routing(sd, input, 0, 0); } } diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c b/linux/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c index 2334ece5f..e15d7fb6c 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c @@ -115,13 +115,11 @@ void pvr2_cx25840_subdev_update(struct pvr2_hdw *hdw, struct v4l2_subdev *sd) const struct routing_scheme *sp; unsigned int sid = hdw->hdw_desc->signal_routing_scheme; - if ((sid < ARRAY_SIZE(routing_schemes)) && - ((sp = routing_schemes[sid]) != NULL) && - (hdw->input_val >= 0) && - (hdw->input_val < sp->cnt)) { - vid_input = sp->def[hdw->input_val].vid; - aud_input = sp->def[hdw->input_val].aud; - } else { + sp = (sid < ARRAY_SIZE(routing_schemes)) ? + routing_schemes[sid] : NULL; + if ((sp == NULL) || + (hdw->input_val < 0) || + (hdw->input_val >= sp->cnt)) { pvr2_trace(PVR2_TRACE_ERROR_LEGS, "*** WARNING *** subdev cx2584x set_input:" " Invalid routing scheme (%u)" @@ -129,7 +127,8 @@ void pvr2_cx25840_subdev_update(struct pvr2_hdw *hdw, struct v4l2_subdev *sd) sid, hdw->input_val); return; } - + vid_input = sp->def[hdw->input_val].vid; + aud_input = sp->def[hdw->input_val].aud; pvr2_trace(PVR2_TRACE_CHIPS, "subdev cx2584x set_input vid=0x%x aud=0x%x", vid_input, aud_input); diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-video-v4l.c b/linux/drivers/media/video/pvrusb2/pvrusb2-video-v4l.c index 915452b4d..4be489c45 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-video-v4l.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-video-v4l.c @@ -86,12 +86,12 @@ void pvr2_saa7115_subdev_update(struct pvr2_hdw *hdw, struct v4l2_subdev *sd) pvr2_trace(PVR2_TRACE_CHIPS, "subdev v4l2 set_input(%d)", hdw->input_val); - if ((sid < ARRAY_SIZE(routing_schemes)) && - ((sp = routing_schemes[sid]) != NULL) && - (hdw->input_val >= 0) && - (hdw->input_val < sp->cnt)) { - input = sp->def[hdw->input_val]; - } else { + + sp = (sid < ARRAY_SIZE(routing_schemes)) ? + routing_schemes[sid] : NULL; + if ((sp == NULL) || + (hdw->input_val < 0) || + (hdw->input_val >= sp->cnt)) { pvr2_trace(PVR2_TRACE_ERROR_LEGS, "*** WARNING *** subdev v4l2 set_input:" " Invalid routing scheme (%u)" @@ -99,6 +99,7 @@ void pvr2_saa7115_subdev_update(struct pvr2_hdw *hdw, struct v4l2_subdev *sd) sid, hdw->input_val); return; } + input = sp->def[hdw->input_val]; sd->ops->video->s_routing(sd, input, 0, 0); } } -- cgit v1.2.3 From 3f5baede21113b8adf1b40d403e19a1ced1b07b8 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 21 Jun 2009 22:37:12 -0300 Subject: /v4l2-ioctl: better output debug messages for VIDIOC_ENUM_FRAMESIZES From: Mauro Carvalho Chehab Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/v4l2-ioctl.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/v4l2-ioctl.c b/linux/drivers/media/video/v4l2-ioctl.c index 22b380dfd..625fe7698 100644 --- a/linux/drivers/media/video/v4l2-ioctl.c +++ b/linux/drivers/media/video/v4l2-ioctl.c @@ -1718,24 +1718,29 @@ static long __video_do_ioctl(struct file *file, ret = ops->vidioc_enum_framesizes(file, fh, p); dbgarg(cmd, - "index=%d, pixelformat=%d, type=%d ", - p->index, p->pixel_format, p->type); + "index=%d, pixelformat=%c%c%c%c, type=%d ", + p->index, + (p->pixel_format & 0xff), + (p->pixel_format >> 8) & 0xff, + (p->pixel_format >> 16) & 0xff, + (p->pixel_format >> 24) & 0xff, + p->type); switch (p->type) { case V4L2_FRMSIZE_TYPE_DISCRETE: - dbgarg2("width = %d, height=%d\n", + printk("width = %d, height=%d\n", p->discrete.width, p->discrete.height); break; case V4L2_FRMSIZE_TYPE_STEPWISE: - dbgarg2("min %dx%d, max %dx%d, step %dx%d\n", + printk("min %dx%d, max %dx%d, step %dx%d\n", p->stepwise.min_width, p->stepwise.min_height, p->stepwise.step_width, p->stepwise.step_height, p->stepwise.max_width, p->stepwise.max_height); break; case V4L2_FRMSIZE_TYPE_CONTINUOUS: - dbgarg2("continuous\n"); + printk("continuous\n"); break; default: - dbgarg2("- Unknown type!\n"); + printk("- Unknown type!\n"); } break; -- cgit v1.2.3 From e060bd6ae7ce4dee0f07e3ac5051de35b4908bd0 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 22 Jun 2009 14:02:55 +0200 Subject: DaVinci: DM646x Video: Fix compile time warnings for mutex locking From: Chaithrika U S mutex_lock_interruptible return value has to be handled properly to indicate the status to the higher layers of the kernel. Priority: normal Signed-off-by: Chaithrika U S Signed-off-by: Hans Verkuil --- linux/drivers/media/video/davinci/vpif_display.c | 31 ++++++++++++++++++------ 1 file changed, 23 insertions(+), 8 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/davinci/vpif_display.c b/linux/drivers/media/video/davinci/vpif_display.c index 5e2b86b3f..969d4b3aa 100644 --- a/linux/drivers/media/video/davinci/vpif_display.c +++ b/linux/drivers/media/video/davinci/vpif_display.c @@ -636,7 +636,9 @@ static int vpif_release(struct file *filep) struct channel_obj *ch = fh->channel; struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; - mutex_lock_interruptible(&common->lock); + if (mutex_lock_interruptible(&common->lock)) + return -ERESTARTSYS; + /* if this instance is doing IO */ if (fh->io_allowed[VPIF_VIDEO_INDEX]) { /* Reset io_usrs member of channel object */ @@ -720,7 +722,9 @@ static int vpif_g_fmt_vid_out(struct file *file, void *priv, return -EINVAL; /* Fill in the information about format */ - mutex_lock_interruptible(&common->lock); + if (mutex_lock_interruptible(&common->lock)) + return -ERESTARTSYS; + if (vpif_get_std_info(ch)) { vpif_err("Error getting the standard info\n"); return -EINVAL; @@ -768,7 +772,9 @@ static int vpif_s_fmt_vid_out(struct file *file, void *priv, /* store the pix format in the channel object */ common->fmt.fmt.pix = *pixfmt; /* store the format in the channel object */ - mutex_lock_interruptible(&common->lock); + if (mutex_lock_interruptible(&common->lock)) + return -ERESTARTSYS; + common->fmt = *fmt; mutex_unlock(&common->lock); @@ -819,7 +825,9 @@ static int vpif_reqbufs(struct file *file, void *priv, index = VPIF_VIDEO_INDEX; common = &ch->common[index]; - mutex_lock_interruptible(&common->lock); + if (mutex_lock_interruptible(&common->lock)) + return -ERESTARTSYS; + if (common->fmt.type != reqbuf->type) { ret = -EINVAL; goto reqbuf_exit; @@ -979,7 +987,8 @@ static int vpif_s_std(struct file *file, void *priv, v4l2_std_id *std_id) } /* Call encoder subdevice function to set the standard */ - mutex_lock_interruptible(&common->lock); + if (mutex_lock_interruptible(&common->lock)) + return -ERESTARTSYS; ch->video.stdid = *std_id; /* Get the information about the standard */ @@ -1085,7 +1094,9 @@ static int vpif_streamon(struct file *file, void *priv, return ret; } - mutex_lock_interruptible(&common->lock); + if (mutex_lock_interruptible(&common->lock)) + return -ERESTARTSYS; + /* If buffer queue is empty, return error */ if (list_empty(&common->dma_queue)) { vpif_err("buffer queue is empty\n"); @@ -1185,7 +1196,9 @@ static int vpif_streamoff(struct file *file, void *priv, return -EINVAL; } - mutex_lock_interruptible(&common->lock); + if (mutex_lock_interruptible(&common->lock)) + return -ERESTARTSYS; + if (buftype == V4L2_BUF_TYPE_VIDEO_OUTPUT) { /* disable channel */ if (VPIF_CHANNEL2_VIDEO == ch->channel_id) { @@ -1248,7 +1261,9 @@ static int vpif_s_output(struct file *file, void *priv, unsigned int i) struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; int ret = 0; - mutex_lock_interruptible(&common->lock); + if (mutex_lock_interruptible(&common->lock)) + return -ERESTARTSYS; + if (common->started) { vpif_err("Streaming in progress\n"); ret = -EBUSY; -- cgit v1.2.3 From 1da6ad98e478b29ad30ad485246a768225407d8b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20Andr=C3=A9n?= Date: Tue, 23 Jun 2009 17:22:48 +0200 Subject: gspca - stv06xx-hdcs: Actually update the sensor state MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: Erik Andrén Priority: high Signed-off-by: Erik Andrén --- linux/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.c b/linux/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.c index 3039ec208..ec7f5536a 100644 --- a/linux/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.c +++ b/linux/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.c @@ -174,7 +174,9 @@ static int hdcs_set_state(struct sd *sd, enum hdcs_power_state state) } ret = stv06xx_write_sensor(sd, HDCS_REG_CONTROL(sd), val); - if (ret < 0) + + /* Update the state if the write succeeded */ + if (!ret) hdcs->state = state; return ret; -- cgit v1.2.3 From 78b0beaf9e13ab3591c37baea35488feeccfa152 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20Andr=C3=A9n?= Date: Wed, 24 Jun 2009 09:30:56 +0200 Subject: gspca - stv06xx-hdcs: Fix sensor sequence bug MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: Erik Andrén All hdcs registers use bit 0 as a read/write flag and needs to be shifted one bit to the left. This wasn't accounted for when doing a sequence of writes. Priority: high Signed-off-by: Erik Andrén --- linux/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.c b/linux/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.c index ec7f5536a..a45171be3 100644 --- a/linux/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.c +++ b/linux/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.c @@ -131,9 +131,11 @@ static int hdcs_reg_write_seq(struct sd *sd, u8 reg, u8 *vals, u8 len) (reg + len > 0xff))) return -EINVAL; - for (i = 0; i < len; i++, reg++) { - regs[2*i] = reg; - regs[2*i+1] = vals[i]; + for (i = 0; i < len; i++) { + regs[2 * i] = reg; + regs[2 * i + 1] = vals[i]; + /* All addresses are shifted left one bit as bit 0 toggles r/w */ + reg += 2; } return stv06xx_write_sensor_bytes(sd, regs, len); -- cgit v1.2.3 From 337e432b2e75655ab7d267af800bd4853f8cf3c9 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Sun, 19 Jul 2009 17:19:18 -0400 Subject: cx23885-417: fix broken IOCTL handling From: Michael Krufky IOCTLS will never get handled if we dont connect video_ioctl2 to mpeg_fops.ioctl Priority: high Signed-off-by: Michael Krufky --- linux/drivers/media/video/cx23885/cx23885-417.c | 1 + 1 file changed, 1 insertion(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/cx23885/cx23885-417.c b/linux/drivers/media/video/cx23885/cx23885-417.c index 9974d9a78..9c5233906 100644 --- a/linux/drivers/media/video/cx23885/cx23885-417.c +++ b/linux/drivers/media/video/cx23885/cx23885-417.c @@ -1683,6 +1683,7 @@ static struct v4l2_file_operations mpeg_fops = { .read = mpeg_read, .poll = mpeg_poll, .mmap = mpeg_mmap, + .ioctl = video_ioctl2, }; static const struct v4l2_ioctl_ops mpeg_ioctl_ops = { -- cgit v1.2.3 From ac5128d842099f6536d4acef3243b0881043e519 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Sun, 19 Jul 2009 16:55:35 -0400 Subject: cx23885: check pointers before dereferencing in dprintk macro From: Michael Krufky When enabling debug with v4l_debug set to 2 or greater, the driver OOPS's on startup. Checks dev pointer before dereferencing, in order to prevent this OOPS. Priority: high Signed-off-by: Michael Krufky --- linux/drivers/media/video/cx23885/cx23885-417.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/cx23885/cx23885-417.c b/linux/drivers/media/video/cx23885/cx23885-417.c index 9c5233906..02909d7a9 100644 --- a/linux/drivers/media/video/cx23885/cx23885-417.c +++ b/linux/drivers/media/video/cx23885/cx23885-417.c @@ -57,7 +57,8 @@ MODULE_PARM_DESC(v4l_debug, "enable V4L debug messages"); #define dprintk(level, fmt, arg...)\ do { if (v4l_debug >= level) \ - printk(KERN_DEBUG "%s: " fmt, dev->name , ## arg);\ + printk(KERN_DEBUG "%s: " fmt, \ + (dev) ? dev->name : "cx23885[?]", ## arg); \ } while (0) static struct cx23885_tvnorm cx23885_tvnorms[] = { -- cgit v1.2.3 From 1024f9d1fd44ef073b47efac545a4d16b4ced8f7 Mon Sep 17 00:00:00 2001 From: Steven Toth Date: Thu, 25 Jun 2009 22:43:31 -0400 Subject: cx23885: Remove hardcoded gpio bits from the encoder driver From: Steven Toth The encoder driver has hardcoded GPIO bits set for the HVR1800, regardless of whether it's being used by a HVR1800 or not. I've implemented some generic GPIO manipulation routines and I'm calling them only when appropriate. Priority: normal Signed-off-by: Steven Toth --- linux/drivers/media/video/cx23885/cx23885-417.c | 57 ++++++++++++++--------- linux/drivers/media/video/cx23885/cx23885-cards.c | 9 ++++ linux/drivers/media/video/cx23885/cx23885-core.c | 8 ++++ linux/drivers/media/video/cx23885/cx23885.h | 9 ++++ 4 files changed, 61 insertions(+), 22 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/cx23885/cx23885-417.c b/linux/drivers/media/video/cx23885/cx23885-417.c index 02909d7a9..fe0b3c41d 100644 --- a/linux/drivers/media/video/cx23885/cx23885-417.c +++ b/linux/drivers/media/video/cx23885/cx23885-417.c @@ -629,6 +629,39 @@ int mc417_memory_read(struct cx23885_dev *dev, u32 address, u32 *value) return retval; } +void mc417_gpio_set(struct cx23885_dev *dev, u32 mask) +{ + u32 val; + + /* Set the gpio value */ + mc417_register_read(dev, 0x900C, &val); + val |= (mask & 0x000ffff); + mc417_register_write(dev, 0x900C, val); +} + +void mc417_gpio_clear(struct cx23885_dev *dev, u32 mask) +{ + u32 val; + + /* Clear the gpio value */ + mc417_register_read(dev, 0x900C, &val); + val &= ~(mask & 0x0000ffff); + mc417_register_write(dev, 0x900C, val); +} + +void mc417_gpio_enable(struct cx23885_dev *dev, u32 mask, int asoutput) +{ + u32 val; + + /* Enable GPIO direction bits */ + mc417_register_read(dev, 0x9020, &val); + if (asoutput) + val |= (mask & 0x0000ffff); + else + val &= ~(mask & 0x0000ffff); + + mc417_register_write(dev, 0x9020, val); +} /* ------------------------------------------------------------------ */ /* MPEG encoder API */ @@ -954,25 +987,8 @@ static int cx23885_load_firmware(struct cx23885_dev *dev) retval |= mc417_register_write(dev, IVTV_REG_HW_BLOCKS, IVTV_CMD_HW_BLOCKS_RST); - /* Restore GPIO settings, make sure EIO14 is enabled as an output. */ - dprintk(2, "%s: GPIO output EIO 0-15 was = 0x%x\n", - __func__, gpio_output); - /* Power-up seems to have GPIOs AFU. This was causing digital side - * to fail at power-up. Seems GPIOs should be set to 0x10ff0411 at - * power-up. - * gpio_output |= (1<<14); - */ - /* Note: GPIO14 is specific to the HVR1800 here */ - gpio_output = 0x10ff0411 | (1<<14); - retval |= mc417_register_write(dev, 0x9020, gpio_output | (1<<14)); - dprintk(2, "%s: GPIO output EIO 0-15 now = 0x%x\n", - __func__, gpio_output); - - dprintk(1, "%s: GPIO value EIO 0-15 was = 0x%x\n", - __func__, value); - value |= (1<<14); - dprintk(1, "%s: GPIO value EIO 0-15 now = 0x%x\n", - __func__, value); + /* F/W power up disturbs the GPIOs, restore state */ + retval |= mc417_register_write(dev, 0x9020, gpio_output); retval |= mc417_register_write(dev, 0x900C, value); retval |= mc417_register_read(dev, IVTV_REG_VPU, &value); @@ -1792,9 +1808,6 @@ int cx23885_417_register(struct cx23885_dev *dev) return err; } - /* Initialize MC417 registers */ - cx23885_mc417_init(dev); - printk(KERN_INFO "%s: registered device video%d [mpeg]\n", dev->name, dev->v4l_device->num); diff --git a/linux/drivers/media/video/cx23885/cx23885-cards.c b/linux/drivers/media/video/cx23885/cx23885-cards.c index bf426f041..623607b55 100644 --- a/linux/drivers/media/video/cx23885/cx23885-cards.c +++ b/linux/drivers/media/video/cx23885/cx23885-cards.c @@ -583,6 +583,15 @@ void cx23885_gpio_setup(struct cx23885_dev *dev) /* CX23417 GPIO's */ /* EIO15 Zilog Reset */ /* EIO14 S5H1409/CX24227 Reset */ + mc417_gpio_enable(dev, GPIO_15 | GPIO_14, 1); + + /* Put the demod into reset and protect the eeprom */ + mc417_gpio_clear(dev, GPIO_15 | GPIO_14); + mdelay(100); + + /* Bring the demod and blaster out of reset */ + mc417_gpio_set(dev, GPIO_15 | GPIO_14); + mdelay(100); /* Force the TDA8295A into reset and back */ cx_set(GP0_IO, 0x00040004); diff --git a/linux/drivers/media/video/cx23885/cx23885-core.c b/linux/drivers/media/video/cx23885/cx23885-core.c index 6988361c9..351210e5c 100644 --- a/linux/drivers/media/video/cx23885/cx23885-core.c +++ b/linux/drivers/media/video/cx23885/cx23885-core.c @@ -869,6 +869,14 @@ static int cx23885_dev_setup(struct cx23885_dev *dev) dprintk(1, "%s() radio_type = 0x%x radio_addr = 0x%x\n", __func__, dev->radio_type, dev->radio_addr); + /* The cx23417 encoder has GPIO's that need to be initialised + * before DVB, so that demodulators and tuners are out of + * reset before DVB uses them. + */ + if ((cx23885_boards[dev->board].portb == CX23885_MPEG_ENCODER) || + (cx23885_boards[dev->board].portc == CX23885_MPEG_ENCODER)) + cx23885_mc417_init(dev); + /* init hardware */ cx23885_reset(dev); diff --git a/linux/drivers/media/video/cx23885/cx23885.h b/linux/drivers/media/video/cx23885/cx23885.h index 2a384e6aa..a507af77a 100644 --- a/linux/drivers/media/video/cx23885/cx23885.h +++ b/linux/drivers/media/video/cx23885/cx23885.h @@ -89,6 +89,12 @@ #define GPIO_7 0x00000080 #define GPIO_8 0x00000100 #define GPIO_9 0x00000200 +#define GPIO_10 0x00000400 +#define GPIO_11 0x00000800 +#define GPIO_12 0x00001000 +#define GPIO_13 0x00002000 +#define GPIO_14 0x00004000 +#define GPIO_15 0x00008000 /* Currently unsupported by the driver: PAL/H, NTSC/Kr, SECAM B/G/H/LC */ #define CX23885_NORMS (\ @@ -506,6 +512,9 @@ extern void cx23885_417_check_encoder(struct cx23885_dev *dev); extern void cx23885_mc417_init(struct cx23885_dev *dev); extern int mc417_memory_read(struct cx23885_dev *dev, u32 address, u32 *value); extern int mc417_memory_write(struct cx23885_dev *dev, u32 address, u32 value); +extern void mc417_gpio_set(struct cx23885_dev *dev, u32 mask); +extern void mc417_gpio_clear(struct cx23885_dev *dev, u32 mask); +extern void mc417_gpio_enable(struct cx23885_dev *dev, u32 mask, int asoutput); /* ----------------------------------------------------------- */ -- cgit v1.2.3 From 9565b71c51910214d91b7ffa96bffa3f2665c75c Mon Sep 17 00:00:00 2001 From: Steven Toth Date: Thu, 25 Jun 2009 22:50:39 -0400 Subject: cx23885: Convert existing HVR1800 GPIO calls into new format From: Steven Toth ... improves readability and routes the calls through a specific single point. Priority: normal Signed-off-by: Steven Toth --- linux/drivers/media/video/cx23885/cx23885-cards.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/cx23885/cx23885-cards.c b/linux/drivers/media/video/cx23885/cx23885-cards.c index 623607b55..edb99215b 100644 --- a/linux/drivers/media/video/cx23885/cx23885-cards.c +++ b/linux/drivers/media/video/cx23885/cx23885-cards.c @@ -594,11 +594,12 @@ void cx23885_gpio_setup(struct cx23885_dev *dev) mdelay(100); /* Force the TDA8295A into reset and back */ - cx_set(GP0_IO, 0x00040004); + cx23885_gpio_enable(dev, GPIO_2, 1); + cx23885_gpio_set(dev, GPIO_2); mdelay(20); - cx_clear(GP0_IO, 0x00000004); + cx23885_gpio_clear(dev, GPIO_2); mdelay(20); - cx_set(GP0_IO, 0x00040004); + cx23885_gpio_set(dev, GPIO_2); mdelay(20); break; case CX23885_BOARD_HAUPPAUGE_HVR1200: -- cgit v1.2.3 From a4c5c6c582583fcb31b975ebacd779ea0c8e5eae Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 26 Jun 2009 08:56:09 +0200 Subject: v4l2-common: fix uninitialized variable From: Hans Verkuil Fix compiler warning for uninitialized variable when compiling for pre 2.6.26 kernels. Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/v4l2-common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/v4l2-common.c b/linux/drivers/media/video/v4l2-common.c index ab91734b1..864ee0772 100644 --- a/linux/drivers/media/video/v4l2-common.c +++ b/linux/drivers/media/video/v4l2-common.c @@ -1066,7 +1066,7 @@ struct v4l2_subdev *v4l2_i2c_new_subdev_cfg(struct v4l2_device *v4l2_dev, u8 addr, const unsigned short *probe_addrs) { struct v4l2_subdev *sd = NULL; - struct i2c_client *client; + struct i2c_client *client = NULL; BUG_ON(!v4l2_dev); -- cgit v1.2.3 From e4340839f4ea666cb09caf45d10d30a18a17d2f9 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 26 Jun 2009 10:39:36 +0200 Subject: em28xx: enable new-style i2c API for kernels >= 2.6.26, not 2.6.22. From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/em28xx/em28xx-i2c.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/em28xx/em28xx-i2c.c b/linux/drivers/media/video/em28xx/em28xx-i2c.c index 1cdd88361..24eebd4a3 100644 --- a/linux/drivers/media/video/em28xx/em28xx-i2c.c +++ b/linux/drivers/media/video/em28xx/em28xx-i2c.c @@ -461,7 +461,7 @@ static struct i2c_algorithm em28xx_algo = { static struct i2c_adapter em28xx_adap_template = { .owner = THIS_MODULE, -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22) +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26) .class = I2C_CLASS_TV_ANALOG, #endif .name = "em28xx", -- cgit v1.2.3 From 64bbe9f77eea6c4b12ed4bcc1b561375594be6d8 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Fri, 26 Jun 2009 16:30:09 +0200 Subject: uvcvideo: Use class-specific descriptor types from usb/ch9.h From: Laurent Pinchart uvcvideo.h redefines class-specific descriptor types already present in usb/ch9.h. Remove the duplicated definitions and use the ones from usb/ch9.h. Priority: normal Signed-off-by: Laurent Pinchart --- linux/drivers/media/video/uvc/uvc_driver.c | 4 ++-- linux/drivers/media/video/uvc/uvcvideo.h | 7 ------- 2 files changed, 2 insertions(+), 9 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 40df6828f..b64be45f7 100644 --- a/linux/drivers/media/video/uvc/uvc_driver.c +++ b/linux/drivers/media/video/uvc/uvc_driver.c @@ -644,7 +644,7 @@ static int uvc_parse_streaming(struct uvc_device *dev, _buflen = buflen; /* Count the format and frame descriptors. */ - while (_buflen > 2 && _buffer[1] == CS_INTERFACE) { + while (_buflen > 2 && _buffer[1] == USB_DT_CS_INTERFACE) { switch (_buffer[2]) { case VS_FORMAT_UNCOMPRESSED: case VS_FORMAT_MJPEG: @@ -709,7 +709,7 @@ static int uvc_parse_streaming(struct uvc_device *dev, streaming->nformats = nformats; /* Parse the format descriptors. */ - while (buflen > 2 && buffer[1] == CS_INTERFACE) { + while (buflen > 2 && buffer[1] == USB_DT_CS_INTERFACE) { switch (buffer[2]) { case VS_FORMAT_UNCOMPRESSED: case VS_FORMAT_MJPEG: diff --git a/linux/drivers/media/video/uvc/uvcvideo.h b/linux/drivers/media/video/uvc/uvcvideo.h index de13c86f2..347fb4d7d 100644 --- a/linux/drivers/media/video/uvc/uvcvideo.h +++ b/linux/drivers/media/video/uvc/uvcvideo.h @@ -80,13 +80,6 @@ struct uvc_xu_control { #define PC_PROTOCOL_UNDEFINED 0x00 -#define CS_UNDEFINED 0x20 -#define CS_DEVICE 0x21 -#define CS_CONFIGURATION 0x22 -#define CS_STRING 0x23 -#define CS_INTERFACE 0x24 -#define CS_ENDPOINT 0x25 - /* VideoControl class specific interface descriptor */ #define VC_DESCRIPTOR_UNDEFINED 0x00 #define VC_HEADER 0x01 -- cgit v1.2.3 From 1fe117a75d92c10de7be6de18254f671e9a27ad9 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Fri, 26 Jun 2009 16:39:42 +0200 Subject: uvcvideo: Prefix all UVC constants with UVC_ From: Laurent Pinchart In preparation to moving UVC constants to a public location, prefix all constants with UVC_ to avoid namespace clashes. Priority: normal Signed-off-by: Laurent Pinchart --- linux/drivers/media/video/uvc/uvc_ctrl.c | 205 ++++++++++++++------------- linux/drivers/media/video/uvc/uvc_driver.c | 132 ++++++++--------- linux/drivers/media/video/uvc/uvc_v4l2.c | 14 +- linux/drivers/media/video/uvc/uvc_video.c | 30 ++-- linux/drivers/media/video/uvc/uvcvideo.h | 218 ++++++++++++++--------------- 5 files changed, 307 insertions(+), 292 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/uvc/uvc_ctrl.c b/linux/drivers/media/video/uvc/uvc_ctrl.c index ef55bc35a..81928f838 100644 --- a/linux/drivers/media/video/uvc/uvc_ctrl.c +++ b/linux/drivers/media/video/uvc/uvc_ctrl.c @@ -36,7 +36,7 @@ static struct uvc_control_info uvc_ctrls[] = { { .entity = UVC_GUID_UVC_PROCESSING, - .selector = PU_BRIGHTNESS_CONTROL, + .selector = UVC_PU_BRIGHTNESS_CONTROL, .index = 0, .size = 2, .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE @@ -44,7 +44,7 @@ static struct uvc_control_info uvc_ctrls[] = { }, { .entity = UVC_GUID_UVC_PROCESSING, - .selector = PU_CONTRAST_CONTROL, + .selector = UVC_PU_CONTRAST_CONTROL, .index = 1, .size = 2, .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE @@ -52,7 +52,7 @@ static struct uvc_control_info uvc_ctrls[] = { }, { .entity = UVC_GUID_UVC_PROCESSING, - .selector = PU_HUE_CONTROL, + .selector = UVC_PU_HUE_CONTROL, .index = 2, .size = 2, .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE @@ -60,7 +60,7 @@ static struct uvc_control_info uvc_ctrls[] = { }, { .entity = UVC_GUID_UVC_PROCESSING, - .selector = PU_SATURATION_CONTROL, + .selector = UVC_PU_SATURATION_CONTROL, .index = 3, .size = 2, .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE @@ -68,7 +68,7 @@ static struct uvc_control_info uvc_ctrls[] = { }, { .entity = UVC_GUID_UVC_PROCESSING, - .selector = PU_SHARPNESS_CONTROL, + .selector = UVC_PU_SHARPNESS_CONTROL, .index = 4, .size = 2, .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE @@ -76,7 +76,7 @@ static struct uvc_control_info uvc_ctrls[] = { }, { .entity = UVC_GUID_UVC_PROCESSING, - .selector = PU_GAMMA_CONTROL, + .selector = UVC_PU_GAMMA_CONTROL, .index = 5, .size = 2, .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE @@ -84,7 +84,7 @@ static struct uvc_control_info uvc_ctrls[] = { }, { .entity = UVC_GUID_UVC_PROCESSING, - .selector = PU_WHITE_BALANCE_TEMPERATURE_CONTROL, + .selector = UVC_PU_WHITE_BALANCE_TEMPERATURE_CONTROL, .index = 6, .size = 2, .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE @@ -92,7 +92,7 @@ static struct uvc_control_info uvc_ctrls[] = { }, { .entity = UVC_GUID_UVC_PROCESSING, - .selector = PU_WHITE_BALANCE_COMPONENT_CONTROL, + .selector = UVC_PU_WHITE_BALANCE_COMPONENT_CONTROL, .index = 7, .size = 4, .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE @@ -100,7 +100,7 @@ static struct uvc_control_info uvc_ctrls[] = { }, { .entity = UVC_GUID_UVC_PROCESSING, - .selector = PU_BACKLIGHT_COMPENSATION_CONTROL, + .selector = UVC_PU_BACKLIGHT_COMPENSATION_CONTROL, .index = 8, .size = 2, .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE @@ -108,7 +108,7 @@ static struct uvc_control_info uvc_ctrls[] = { }, { .entity = UVC_GUID_UVC_PROCESSING, - .selector = PU_GAIN_CONTROL, + .selector = UVC_PU_GAIN_CONTROL, .index = 9, .size = 2, .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE @@ -116,7 +116,7 @@ static struct uvc_control_info uvc_ctrls[] = { }, { .entity = UVC_GUID_UVC_PROCESSING, - .selector = PU_POWER_LINE_FREQUENCY_CONTROL, + .selector = UVC_PU_POWER_LINE_FREQUENCY_CONTROL, .index = 10, .size = 1, .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE @@ -124,7 +124,7 @@ static struct uvc_control_info uvc_ctrls[] = { }, { .entity = UVC_GUID_UVC_PROCESSING, - .selector = PU_HUE_AUTO_CONTROL, + .selector = UVC_PU_HUE_AUTO_CONTROL, .index = 11, .size = 1, .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_CUR @@ -132,7 +132,7 @@ static struct uvc_control_info uvc_ctrls[] = { }, { .entity = UVC_GUID_UVC_PROCESSING, - .selector = PU_WHITE_BALANCE_TEMPERATURE_AUTO_CONTROL, + .selector = UVC_PU_WHITE_BALANCE_TEMPERATURE_AUTO_CONTROL, .index = 12, .size = 1, .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_CUR @@ -140,7 +140,7 @@ static struct uvc_control_info uvc_ctrls[] = { }, { .entity = UVC_GUID_UVC_PROCESSING, - .selector = PU_WHITE_BALANCE_COMPONENT_AUTO_CONTROL, + .selector = UVC_PU_WHITE_BALANCE_COMPONENT_AUTO_CONTROL, .index = 13, .size = 1, .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_CUR @@ -148,7 +148,7 @@ static struct uvc_control_info uvc_ctrls[] = { }, { .entity = UVC_GUID_UVC_PROCESSING, - .selector = PU_DIGITAL_MULTIPLIER_CONTROL, + .selector = UVC_PU_DIGITAL_MULTIPLIER_CONTROL, .index = 14, .size = 2, .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE @@ -156,7 +156,7 @@ static struct uvc_control_info uvc_ctrls[] = { }, { .entity = UVC_GUID_UVC_PROCESSING, - .selector = PU_DIGITAL_MULTIPLIER_LIMIT_CONTROL, + .selector = UVC_PU_DIGITAL_MULTIPLIER_LIMIT_CONTROL, .index = 15, .size = 2, .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE @@ -164,21 +164,21 @@ static struct uvc_control_info uvc_ctrls[] = { }, { .entity = UVC_GUID_UVC_PROCESSING, - .selector = PU_ANALOG_VIDEO_STANDARD_CONTROL, + .selector = UVC_PU_ANALOG_VIDEO_STANDARD_CONTROL, .index = 16, .size = 1, .flags = UVC_CONTROL_GET_CUR, }, { .entity = UVC_GUID_UVC_PROCESSING, - .selector = PU_ANALOG_LOCK_STATUS_CONTROL, + .selector = UVC_PU_ANALOG_LOCK_STATUS_CONTROL, .index = 17, .size = 1, .flags = UVC_CONTROL_GET_CUR, }, { .entity = UVC_GUID_UVC_CAMERA, - .selector = CT_SCANNING_MODE_CONTROL, + .selector = UVC_CT_SCANNING_MODE_CONTROL, .index = 0, .size = 1, .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_CUR @@ -186,7 +186,7 @@ static struct uvc_control_info uvc_ctrls[] = { }, { .entity = UVC_GUID_UVC_CAMERA, - .selector = CT_AE_MODE_CONTROL, + .selector = UVC_CT_AE_MODE_CONTROL, .index = 1, .size = 1, .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_CUR @@ -195,7 +195,7 @@ static struct uvc_control_info uvc_ctrls[] = { }, { .entity = UVC_GUID_UVC_CAMERA, - .selector = CT_AE_PRIORITY_CONTROL, + .selector = UVC_CT_AE_PRIORITY_CONTROL, .index = 2, .size = 1, .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_CUR @@ -203,7 +203,7 @@ static struct uvc_control_info uvc_ctrls[] = { }, { .entity = UVC_GUID_UVC_CAMERA, - .selector = CT_EXPOSURE_TIME_ABSOLUTE_CONTROL, + .selector = UVC_CT_EXPOSURE_TIME_ABSOLUTE_CONTROL, .index = 3, .size = 4, .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE @@ -211,7 +211,7 @@ static struct uvc_control_info uvc_ctrls[] = { }, { .entity = UVC_GUID_UVC_CAMERA, - .selector = CT_EXPOSURE_TIME_RELATIVE_CONTROL, + .selector = UVC_CT_EXPOSURE_TIME_RELATIVE_CONTROL, .index = 4, .size = 1, .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_CUR @@ -219,7 +219,7 @@ static struct uvc_control_info uvc_ctrls[] = { }, { .entity = UVC_GUID_UVC_CAMERA, - .selector = CT_FOCUS_ABSOLUTE_CONTROL, + .selector = UVC_CT_FOCUS_ABSOLUTE_CONTROL, .index = 5, .size = 2, .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE @@ -227,7 +227,7 @@ static struct uvc_control_info uvc_ctrls[] = { }, { .entity = UVC_GUID_UVC_CAMERA, - .selector = CT_FOCUS_RELATIVE_CONTROL, + .selector = UVC_CT_FOCUS_RELATIVE_CONTROL, .index = 6, .size = 2, .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE @@ -235,7 +235,7 @@ static struct uvc_control_info uvc_ctrls[] = { }, { .entity = UVC_GUID_UVC_CAMERA, - .selector = CT_IRIS_ABSOLUTE_CONTROL, + .selector = UVC_CT_IRIS_ABSOLUTE_CONTROL, .index = 7, .size = 2, .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE @@ -243,7 +243,7 @@ static struct uvc_control_info uvc_ctrls[] = { }, { .entity = UVC_GUID_UVC_CAMERA, - .selector = CT_IRIS_RELATIVE_CONTROL, + .selector = UVC_CT_IRIS_RELATIVE_CONTROL, .index = 8, .size = 1, .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_CUR @@ -251,7 +251,7 @@ static struct uvc_control_info uvc_ctrls[] = { }, { .entity = UVC_GUID_UVC_CAMERA, - .selector = CT_ZOOM_ABSOLUTE_CONTROL, + .selector = UVC_CT_ZOOM_ABSOLUTE_CONTROL, .index = 9, .size = 2, .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE @@ -259,7 +259,7 @@ static struct uvc_control_info uvc_ctrls[] = { }, { .entity = UVC_GUID_UVC_CAMERA, - .selector = CT_ZOOM_RELATIVE_CONTROL, + .selector = UVC_CT_ZOOM_RELATIVE_CONTROL, .index = 10, .size = 3, .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE @@ -267,7 +267,7 @@ static struct uvc_control_info uvc_ctrls[] = { }, { .entity = UVC_GUID_UVC_CAMERA, - .selector = CT_PANTILT_ABSOLUTE_CONTROL, + .selector = UVC_CT_PANTILT_ABSOLUTE_CONTROL, .index = 11, .size = 8, .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE @@ -275,7 +275,7 @@ static struct uvc_control_info uvc_ctrls[] = { }, { .entity = UVC_GUID_UVC_CAMERA, - .selector = CT_PANTILT_RELATIVE_CONTROL, + .selector = UVC_CT_PANTILT_RELATIVE_CONTROL, .index = 12, .size = 4, .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE @@ -283,7 +283,7 @@ static struct uvc_control_info uvc_ctrls[] = { }, { .entity = UVC_GUID_UVC_CAMERA, - .selector = CT_ROLL_ABSOLUTE_CONTROL, + .selector = UVC_CT_ROLL_ABSOLUTE_CONTROL, .index = 13, .size = 2, .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE @@ -291,7 +291,7 @@ static struct uvc_control_info uvc_ctrls[] = { }, { .entity = UVC_GUID_UVC_CAMERA, - .selector = CT_ROLL_RELATIVE_CONTROL, + .selector = UVC_CT_ROLL_RELATIVE_CONTROL, .index = 14, .size = 2, .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE @@ -299,7 +299,7 @@ static struct uvc_control_info uvc_ctrls[] = { }, { .entity = UVC_GUID_UVC_CAMERA, - .selector = CT_FOCUS_AUTO_CONTROL, + .selector = UVC_CT_FOCUS_AUTO_CONTROL, .index = 17, .size = 1, .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_CUR @@ -307,7 +307,7 @@ static struct uvc_control_info uvc_ctrls[] = { }, { .entity = UVC_GUID_UVC_CAMERA, - .selector = CT_PRIVACY_CONTROL, + .selector = UVC_CT_PRIVACY_CONTROL, .index = 18, .size = 1, .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_CUR @@ -334,13 +334,13 @@ static __s32 uvc_ctrl_get_zoom(struct uvc_control_mapping *mapping, __s8 zoom = (__s8)data[0]; switch (query) { - case GET_CUR: + case UVC_GET_CUR: return (zoom == 0) ? 0 : (zoom > 0 ? data[2] : -data[2]); - case GET_MIN: - case GET_MAX: - case GET_RES: - case GET_DEF: + case UVC_GET_MIN: + case UVC_GET_MAX: + case UVC_GET_RES: + case UVC_GET_DEF: default: return data[2]; } @@ -358,7 +358,7 @@ static struct uvc_control_mapping uvc_ctrl_mappings[] = { .id = V4L2_CID_BRIGHTNESS, .name = "Brightness", .entity = UVC_GUID_UVC_PROCESSING, - .selector = PU_BRIGHTNESS_CONTROL, + .selector = UVC_PU_BRIGHTNESS_CONTROL, .size = 16, .offset = 0, .v4l2_type = V4L2_CTRL_TYPE_INTEGER, @@ -368,7 +368,7 @@ static struct uvc_control_mapping uvc_ctrl_mappings[] = { .id = V4L2_CID_CONTRAST, .name = "Contrast", .entity = UVC_GUID_UVC_PROCESSING, - .selector = PU_CONTRAST_CONTROL, + .selector = UVC_PU_CONTRAST_CONTROL, .size = 16, .offset = 0, .v4l2_type = V4L2_CTRL_TYPE_INTEGER, @@ -378,7 +378,7 @@ static struct uvc_control_mapping uvc_ctrl_mappings[] = { .id = V4L2_CID_HUE, .name = "Hue", .entity = UVC_GUID_UVC_PROCESSING, - .selector = PU_HUE_CONTROL, + .selector = UVC_PU_HUE_CONTROL, .size = 16, .offset = 0, .v4l2_type = V4L2_CTRL_TYPE_INTEGER, @@ -388,7 +388,7 @@ static struct uvc_control_mapping uvc_ctrl_mappings[] = { .id = V4L2_CID_SATURATION, .name = "Saturation", .entity = UVC_GUID_UVC_PROCESSING, - .selector = PU_SATURATION_CONTROL, + .selector = UVC_PU_SATURATION_CONTROL, .size = 16, .offset = 0, .v4l2_type = V4L2_CTRL_TYPE_INTEGER, @@ -398,7 +398,7 @@ static struct uvc_control_mapping uvc_ctrl_mappings[] = { .id = V4L2_CID_SHARPNESS, .name = "Sharpness", .entity = UVC_GUID_UVC_PROCESSING, - .selector = PU_SHARPNESS_CONTROL, + .selector = UVC_PU_SHARPNESS_CONTROL, .size = 16, .offset = 0, .v4l2_type = V4L2_CTRL_TYPE_INTEGER, @@ -408,7 +408,7 @@ static struct uvc_control_mapping uvc_ctrl_mappings[] = { .id = V4L2_CID_GAMMA, .name = "Gamma", .entity = UVC_GUID_UVC_PROCESSING, - .selector = PU_GAMMA_CONTROL, + .selector = UVC_PU_GAMMA_CONTROL, .size = 16, .offset = 0, .v4l2_type = V4L2_CTRL_TYPE_INTEGER, @@ -418,7 +418,7 @@ static struct uvc_control_mapping uvc_ctrl_mappings[] = { .id = V4L2_CID_BACKLIGHT_COMPENSATION, .name = "Backlight Compensation", .entity = UVC_GUID_UVC_PROCESSING, - .selector = PU_BACKLIGHT_COMPENSATION_CONTROL, + .selector = UVC_PU_BACKLIGHT_COMPENSATION_CONTROL, .size = 16, .offset = 0, .v4l2_type = V4L2_CTRL_TYPE_INTEGER, @@ -428,7 +428,7 @@ static struct uvc_control_mapping uvc_ctrl_mappings[] = { .id = V4L2_CID_GAIN, .name = "Gain", .entity = UVC_GUID_UVC_PROCESSING, - .selector = PU_GAIN_CONTROL, + .selector = UVC_PU_GAIN_CONTROL, .size = 16, .offset = 0, .v4l2_type = V4L2_CTRL_TYPE_INTEGER, @@ -438,7 +438,7 @@ static struct uvc_control_mapping uvc_ctrl_mappings[] = { .id = V4L2_CID_POWER_LINE_FREQUENCY, .name = "Power Line Frequency", .entity = UVC_GUID_UVC_PROCESSING, - .selector = PU_POWER_LINE_FREQUENCY_CONTROL, + .selector = UVC_PU_POWER_LINE_FREQUENCY_CONTROL, .size = 2, .offset = 0, .v4l2_type = V4L2_CTRL_TYPE_MENU, @@ -450,7 +450,7 @@ static struct uvc_control_mapping uvc_ctrl_mappings[] = { .id = V4L2_CID_HUE_AUTO, .name = "Hue, Auto", .entity = UVC_GUID_UVC_PROCESSING, - .selector = PU_HUE_AUTO_CONTROL, + .selector = UVC_PU_HUE_AUTO_CONTROL, .size = 1, .offset = 0, .v4l2_type = V4L2_CTRL_TYPE_BOOLEAN, @@ -460,7 +460,7 @@ static struct uvc_control_mapping uvc_ctrl_mappings[] = { .id = V4L2_CID_EXPOSURE_AUTO, .name = "Exposure, Auto", .entity = UVC_GUID_UVC_CAMERA, - .selector = CT_AE_MODE_CONTROL, + .selector = UVC_CT_AE_MODE_CONTROL, .size = 4, .offset = 0, .v4l2_type = V4L2_CTRL_TYPE_MENU, @@ -472,7 +472,7 @@ static struct uvc_control_mapping uvc_ctrl_mappings[] = { .id = V4L2_CID_EXPOSURE_AUTO_PRIORITY, .name = "Exposure, Auto Priority", .entity = UVC_GUID_UVC_CAMERA, - .selector = CT_AE_PRIORITY_CONTROL, + .selector = UVC_CT_AE_PRIORITY_CONTROL, .size = 1, .offset = 0, .v4l2_type = V4L2_CTRL_TYPE_BOOLEAN, @@ -482,7 +482,7 @@ static struct uvc_control_mapping uvc_ctrl_mappings[] = { .id = V4L2_CID_EXPOSURE_ABSOLUTE, .name = "Exposure (Absolute)", .entity = UVC_GUID_UVC_CAMERA, - .selector = CT_EXPOSURE_TIME_ABSOLUTE_CONTROL, + .selector = UVC_CT_EXPOSURE_TIME_ABSOLUTE_CONTROL, .size = 32, .offset = 0, .v4l2_type = V4L2_CTRL_TYPE_INTEGER, @@ -492,7 +492,7 @@ static struct uvc_control_mapping uvc_ctrl_mappings[] = { .id = V4L2_CID_AUTO_WHITE_BALANCE, .name = "White Balance Temperature, Auto", .entity = UVC_GUID_UVC_PROCESSING, - .selector = PU_WHITE_BALANCE_TEMPERATURE_AUTO_CONTROL, + .selector = UVC_PU_WHITE_BALANCE_TEMPERATURE_AUTO_CONTROL, .size = 1, .offset = 0, .v4l2_type = V4L2_CTRL_TYPE_BOOLEAN, @@ -502,7 +502,7 @@ static struct uvc_control_mapping uvc_ctrl_mappings[] = { .id = V4L2_CID_WHITE_BALANCE_TEMPERATURE, .name = "White Balance Temperature", .entity = UVC_GUID_UVC_PROCESSING, - .selector = PU_WHITE_BALANCE_TEMPERATURE_CONTROL, + .selector = UVC_PU_WHITE_BALANCE_TEMPERATURE_CONTROL, .size = 16, .offset = 0, .v4l2_type = V4L2_CTRL_TYPE_INTEGER, @@ -512,7 +512,7 @@ static struct uvc_control_mapping uvc_ctrl_mappings[] = { .id = V4L2_CID_AUTO_WHITE_BALANCE, .name = "White Balance Component, Auto", .entity = UVC_GUID_UVC_PROCESSING, - .selector = PU_WHITE_BALANCE_COMPONENT_AUTO_CONTROL, + .selector = UVC_PU_WHITE_BALANCE_COMPONENT_AUTO_CONTROL, .size = 1, .offset = 0, .v4l2_type = V4L2_CTRL_TYPE_BOOLEAN, @@ -522,7 +522,7 @@ static struct uvc_control_mapping uvc_ctrl_mappings[] = { .id = V4L2_CID_BLUE_BALANCE, .name = "White Balance Blue Component", .entity = UVC_GUID_UVC_PROCESSING, - .selector = PU_WHITE_BALANCE_COMPONENT_CONTROL, + .selector = UVC_PU_WHITE_BALANCE_COMPONENT_CONTROL, .size = 16, .offset = 0, .v4l2_type = V4L2_CTRL_TYPE_INTEGER, @@ -532,7 +532,7 @@ static struct uvc_control_mapping uvc_ctrl_mappings[] = { .id = V4L2_CID_RED_BALANCE, .name = "White Balance Red Component", .entity = UVC_GUID_UVC_PROCESSING, - .selector = PU_WHITE_BALANCE_COMPONENT_CONTROL, + .selector = UVC_PU_WHITE_BALANCE_COMPONENT_CONTROL, .size = 16, .offset = 16, .v4l2_type = V4L2_CTRL_TYPE_INTEGER, @@ -542,7 +542,7 @@ static struct uvc_control_mapping uvc_ctrl_mappings[] = { .id = V4L2_CID_FOCUS_ABSOLUTE, .name = "Focus (absolute)", .entity = UVC_GUID_UVC_CAMERA, - .selector = CT_FOCUS_ABSOLUTE_CONTROL, + .selector = UVC_CT_FOCUS_ABSOLUTE_CONTROL, .size = 16, .offset = 0, .v4l2_type = V4L2_CTRL_TYPE_INTEGER, @@ -552,7 +552,7 @@ static struct uvc_control_mapping uvc_ctrl_mappings[] = { .id = V4L2_CID_FOCUS_AUTO, .name = "Focus, Auto", .entity = UVC_GUID_UVC_CAMERA, - .selector = CT_FOCUS_AUTO_CONTROL, + .selector = UVC_CT_FOCUS_AUTO_CONTROL, .size = 1, .offset = 0, .v4l2_type = V4L2_CTRL_TYPE_BOOLEAN, @@ -562,7 +562,7 @@ static struct uvc_control_mapping uvc_ctrl_mappings[] = { .id = V4L2_CID_ZOOM_ABSOLUTE, .name = "Zoom, Absolute", .entity = UVC_GUID_UVC_CAMERA, - .selector = CT_ZOOM_ABSOLUTE_CONTROL, + .selector = UVC_CT_ZOOM_ABSOLUTE_CONTROL, .size = 16, .offset = 0, .v4l2_type = V4L2_CTRL_TYPE_INTEGER, @@ -572,7 +572,7 @@ static struct uvc_control_mapping uvc_ctrl_mappings[] = { .id = V4L2_CID_ZOOM_CONTINUOUS, .name = "Zoom, Continuous", .entity = UVC_GUID_UVC_CAMERA, - .selector = CT_ZOOM_RELATIVE_CONTROL, + .selector = UVC_CT_ZOOM_RELATIVE_CONTROL, .size = 0, .offset = 0, .v4l2_type = V4L2_CTRL_TYPE_INTEGER, @@ -584,7 +584,7 @@ static struct uvc_control_mapping uvc_ctrl_mappings[] = { .id = V4L2_CID_PRIVACY, .name = "Privacy", .entity = UVC_GUID_UVC_CAMERA, - .selector = CT_PRIVACY_CONTROL, + .selector = UVC_CT_PRIVACY_CONTROL, .size = 1, .offset = 0, .v4l2_type = V4L2_CTRL_TYPE_BOOLEAN, @@ -677,16 +677,16 @@ static const __u8 uvc_media_transport_input_guid[16] = static int uvc_entity_match_guid(struct uvc_entity *entity, __u8 guid[16]) { switch (UVC_ENTITY_TYPE(entity)) { - case ITT_CAMERA: + case UVC_ITT_CAMERA: return memcmp(uvc_camera_guid, guid, 16) == 0; - case ITT_MEDIA_TRANSPORT_INPUT: + case UVC_ITT_MEDIA_TRANSPORT_INPUT: return memcmp(uvc_media_transport_input_guid, guid, 16) == 0; - case VC_PROCESSING_UNIT: + case UVC_VC_PROCESSING_UNIT: return memcmp(uvc_processing_guid, guid, 16) == 0; - case VC_EXTENSION_UNIT: + case UVC_VC_EXTENSION_UNIT: return memcmp(entity->extension.guidExtensionCode, guid, 16) == 0; @@ -795,11 +795,13 @@ int uvc_query_v4l2_ctrl(struct uvc_video_device *video, v4l2_ctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY; if (ctrl->info->flags & UVC_CONTROL_GET_DEF) { - if ((ret = uvc_query_ctrl(video->dev, GET_DEF, ctrl->entity->id, - video->dev->intfnum, ctrl->info->selector, - data, ctrl->info->size)) < 0) + ret = uvc_query_ctrl(video->dev, UVC_GET_DEF, ctrl->entity->id, + video->dev->intfnum, ctrl->info->selector, data, + ctrl->info->size); + if (ret < 0) goto out; - v4l2_ctrl->default_value = mapping->get(mapping, GET_DEF, data); + v4l2_ctrl->default_value = + mapping->get(mapping, UVC_GET_DEF, data); } switch (mapping->v4l2_type) { @@ -831,25 +833,28 @@ int uvc_query_v4l2_ctrl(struct uvc_video_device *video, } if (ctrl->info->flags & UVC_CONTROL_GET_MIN) { - if ((ret = uvc_query_ctrl(video->dev, GET_MIN, ctrl->entity->id, - video->dev->intfnum, ctrl->info->selector, - data, ctrl->info->size)) < 0) + ret = uvc_query_ctrl(video->dev, UVC_GET_MIN, ctrl->entity->id, + video->dev->intfnum, ctrl->info->selector, data, + ctrl->info->size); + if (ret < 0) goto out; - v4l2_ctrl->minimum = mapping->get(mapping, GET_MIN, data); + v4l2_ctrl->minimum = mapping->get(mapping, UVC_GET_MIN, data); } if (ctrl->info->flags & UVC_CONTROL_GET_MAX) { - if ((ret = uvc_query_ctrl(video->dev, GET_MAX, ctrl->entity->id, - video->dev->intfnum, ctrl->info->selector, - data, ctrl->info->size)) < 0) + ret = uvc_query_ctrl(video->dev, UVC_GET_MAX, ctrl->entity->id, + video->dev->intfnum, ctrl->info->selector, data, + ctrl->info->size); + if (ret < 0) goto out; - v4l2_ctrl->maximum = mapping->get(mapping, GET_MAX, data); + v4l2_ctrl->maximum = mapping->get(mapping, UVC_GET_MAX, data); } if (ctrl->info->flags & UVC_CONTROL_GET_RES) { - if ((ret = uvc_query_ctrl(video->dev, GET_RES, ctrl->entity->id, - video->dev->intfnum, ctrl->info->selector, - data, ctrl->info->size)) < 0) + ret = uvc_query_ctrl(video->dev, UVC_GET_RES, ctrl->entity->id, + video->dev->intfnum, ctrl->info->selector, data, + ctrl->info->size); + if (ret < 0) goto out; - v4l2_ctrl->step = mapping->get(mapping, GET_RES, data); + v4l2_ctrl->step = mapping->get(mapping, UVC_GET_RES, data); } ret = 0; @@ -914,7 +919,7 @@ static int uvc_ctrl_commit_entity(struct uvc_device *dev, continue; if (!rollback) - ret = uvc_query_ctrl(dev, SET_CUR, ctrl->entity->id, + ret = uvc_query_ctrl(dev, UVC_SET_CUR, ctrl->entity->id, dev->intfnum, ctrl->info->selector, uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT), ctrl->info->size); @@ -976,7 +981,7 @@ int uvc_ctrl_get(struct uvc_video_device *video, return -EINVAL; if (!ctrl->loaded) { - ret = uvc_query_ctrl(video->dev, GET_CUR, ctrl->entity->id, + ret = uvc_query_ctrl(video->dev, UVC_GET_CUR, ctrl->entity->id, video->dev->intfnum, ctrl->info->selector, uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT), ctrl->info->size); @@ -986,7 +991,7 @@ int uvc_ctrl_get(struct uvc_video_device *video, ctrl->loaded = 1; } - xctrl->value = mapping->get(mapping, GET_CUR, + xctrl->value = mapping->get(mapping, UVC_GET_CUR, uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT)); if (mapping->v4l2_type == V4L2_CTRL_TYPE_MENU) { @@ -1025,7 +1030,7 @@ int uvc_ctrl_set(struct uvc_video_device *video, memset(uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT), 0, ctrl->info->size); } else { - ret = uvc_query_ctrl(video->dev, GET_CUR, + ret = uvc_query_ctrl(video->dev, UVC_GET_CUR, ctrl->entity->id, video->dev->intfnum, ctrl->info->selector, uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT), @@ -1117,9 +1122,9 @@ int uvc_xu_ctrl_query(struct uvc_video_device *video, goto out; } - ret = uvc_query_ctrl(video->dev, set ? SET_CUR : GET_CUR, xctrl->unit, - video->dev->intfnum, xctrl->selector, data, - xctrl->size); + ret = uvc_query_ctrl(video->dev, set ? UVC_SET_CUR : UVC_GET_CUR, + xctrl->unit, video->dev->intfnum, xctrl->selector, + data, xctrl->size); if (ret < 0) goto out; @@ -1213,7 +1218,7 @@ static void uvc_ctrl_add_ctrl(struct uvc_device *dev, if (!found) return; - if (UVC_ENTITY_TYPE(entity) == VC_EXTENSION_UNIT) { + if (UVC_ENTITY_TYPE(entity) == UVC_VC_EXTENSION_UNIT) { /* Check if the device control information and length match * the user supplied information. */ @@ -1221,8 +1226,9 @@ static void uvc_ctrl_add_ctrl(struct uvc_device *dev, __le16 size; __u8 inf; - if ((ret = uvc_query_ctrl(dev, GET_LEN, ctrl->entity->id, - dev->intfnum, info->selector, (__u8 *)&size, 2)) < 0) { + ret = uvc_query_ctrl(dev, UVC_GET_LEN, ctrl->entity->id, + dev->intfnum, info->selector, (__u8 *)&size, 2); + if (ret < 0) { uvc_trace(UVC_TRACE_CONTROL, "GET_LEN failed on " "control " UVC_GUID_FORMAT "/%u (%d).\n", UVC_GUID_ARGS(info->entity), info->selector, @@ -1238,8 +1244,9 @@ static void uvc_ctrl_add_ctrl(struct uvc_device *dev, return; } - if ((ret = uvc_query_ctrl(dev, GET_INFO, ctrl->entity->id, - dev->intfnum, info->selector, &inf, 1)) < 0) { + ret = uvc_query_ctrl(dev, UVC_GET_INFO, ctrl->entity->id, + dev->intfnum, info->selector, &inf, 1); + if (ret < 0) { uvc_trace(UVC_TRACE_CONTROL, "GET_INFO failed on " "control " UVC_GUID_FORMAT "/%u (%d).\n", UVC_GUID_ARGS(info->entity), info->selector, @@ -1393,7 +1400,7 @@ uvc_ctrl_prune_entity(struct uvc_device *dev, struct uvc_entity *entity) unsigned int size; unsigned int i; - if (UVC_ENTITY_TYPE(entity) != VC_PROCESSING_UNIT) + if (UVC_ENTITY_TYPE(entity) != UVC_VC_PROCESSING_UNIT) return; controls = entity->processing.bmControls; @@ -1429,13 +1436,13 @@ int uvc_ctrl_init_device(struct uvc_device *dev) unsigned int bControlSize = 0, ncontrols = 0; __u8 *bmControls = NULL; - if (UVC_ENTITY_TYPE(entity) == VC_EXTENSION_UNIT) { + if (UVC_ENTITY_TYPE(entity) == UVC_VC_EXTENSION_UNIT) { bmControls = entity->extension.bmControls; bControlSize = entity->extension.bControlSize; - } else if (UVC_ENTITY_TYPE(entity) == VC_PROCESSING_UNIT) { + } else if (UVC_ENTITY_TYPE(entity) == UVC_VC_PROCESSING_UNIT) { bmControls = entity->processing.bmControls; bControlSize = entity->processing.bControlSize; - } else if (UVC_ENTITY_TYPE(entity) == ITT_CAMERA) { + } else if (UVC_ENTITY_TYPE(entity) == UVC_ITT_CAMERA) { bmControls = entity->camera.bmControls; bControlSize = entity->camera.bControlSize; } diff --git a/linux/drivers/media/video/uvc/uvc_driver.c b/linux/drivers/media/video/uvc/uvc_driver.c index b64be45f7..f03e567a1 100644 --- a/linux/drivers/media/video/uvc/uvc_driver.c +++ b/linux/drivers/media/video/uvc/uvc_driver.c @@ -249,23 +249,23 @@ static struct uvc_entity *uvc_entity_by_reference(struct uvc_device *dev, list_for_each_entry_continue(entity, &dev->entities, list) { switch (UVC_ENTITY_TYPE(entity)) { - case TT_STREAMING: + case UVC_TT_STREAMING: if (entity->output.bSourceID == id) return entity; break; - case VC_PROCESSING_UNIT: + case UVC_VC_PROCESSING_UNIT: if (entity->processing.bSourceID == id) return entity; break; - case VC_SELECTOR_UNIT: + case UVC_VC_SELECTOR_UNIT: for (i = 0; i < entity->selector.bNrInPins; ++i) if (entity->selector.baSourceID[i] == id) return entity; break; - case VC_EXTENSION_UNIT: + case UVC_VC_EXTENSION_UNIT: for (i = 0; i < entity->extension.bNrInPins; ++i) if (entity->extension.baSourceID[i] == id) return entity; @@ -297,9 +297,9 @@ static int uvc_parse_format(struct uvc_device *dev, format->index = buffer[3]; switch (buffer[2]) { - case VS_FORMAT_UNCOMPRESSED: - case VS_FORMAT_FRAME_BASED: - n = buffer[2] == VS_FORMAT_UNCOMPRESSED ? 27 : 28; + case UVC_VS_FORMAT_UNCOMPRESSED: + case UVC_VS_FORMAT_FRAME_BASED: + n = buffer[2] == UVC_VS_FORMAT_UNCOMPRESSED ? 27 : 28; if (buflen < n) { uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming " "interface %d FORMAT error\n", @@ -325,16 +325,16 @@ static int uvc_parse_format(struct uvc_device *dev, } format->bpp = buffer[21]; - if (buffer[2] == VS_FORMAT_UNCOMPRESSED) { - ftype = VS_FRAME_UNCOMPRESSED; + if (buffer[2] == UVC_VS_FORMAT_UNCOMPRESSED) { + ftype = UVC_VS_FRAME_UNCOMPRESSED; } else { - ftype = VS_FRAME_FRAME_BASED; + ftype = UVC_VS_FRAME_FRAME_BASED; if (buffer[27]) format->flags = UVC_FMT_FLAG_COMPRESSED; } break; - case VS_FORMAT_MJPEG: + case UVC_VS_FORMAT_MJPEG: if (buflen < 11) { uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming " "interface %d FORMAT error\n", @@ -347,10 +347,10 @@ static int uvc_parse_format(struct uvc_device *dev, format->fcc = V4L2_PIX_FMT_MJPEG; format->flags = UVC_FMT_FLAG_COMPRESSED; format->bpp = 0; - ftype = VS_FRAME_MJPEG; + ftype = UVC_VS_FRAME_MJPEG; break; - case VS_FORMAT_DV: + case UVC_VS_FORMAT_DV: if (buflen < 9) { uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming " "interface %d FORMAT error\n", @@ -395,8 +395,8 @@ static int uvc_parse_format(struct uvc_device *dev, format->nframes = 1; break; - case VS_FORMAT_MPEG2TS: - case VS_FORMAT_STREAM_BASED: + case UVC_VS_FORMAT_MPEG2TS: + case UVC_VS_FORMAT_STREAM_BASED: /* Not supported yet. */ default: uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming " @@ -416,7 +416,7 @@ static int uvc_parse_format(struct uvc_device *dev, */ while (buflen > 2 && buffer[2] == ftype) { frame = &format->frame[format->nframes]; - if (ftype != VS_FRAME_FRAME_BASED) + if (ftype != UVC_VS_FRAME_FRAME_BASED) n = buflen > 25 ? buffer[25] : 0; else n = buflen > 21 ? buffer[21] : 0; @@ -436,7 +436,7 @@ static int uvc_parse_format(struct uvc_device *dev, frame->wHeight = get_unaligned_le16(&buffer[7]); frame->dwMinBitRate = get_unaligned_le32(&buffer[9]); frame->dwMaxBitRate = get_unaligned_le32(&buffer[13]); - if (ftype != VS_FRAME_FRAME_BASED) { + if (ftype != UVC_VS_FRAME_FRAME_BASED) { frame->dwMaxVideoFrameBufferSize = get_unaligned_le32(&buffer[17]); frame->dwDefaultFrameInterval = @@ -491,12 +491,12 @@ static int uvc_parse_format(struct uvc_device *dev, buffer += buffer[0]; } - if (buflen > 2 && buffer[2] == VS_STILL_IMAGE_FRAME) { + if (buflen > 2 && buffer[2] == UVC_VS_STILL_IMAGE_FRAME) { buflen -= buffer[0]; buffer += buffer[0]; } - if (buflen > 2 && buffer[2] == VS_COLORFORMAT) { + if (buflen > 2 && buffer[2] == UVC_VS_COLORFORMAT) { if (buflen < 6) { uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming " "interface %d COLORFORMAT error\n", @@ -530,7 +530,7 @@ static int uvc_parse_streaming(struct uvc_device *dev, int ret = -EINVAL; if (intf->cur_altsetting->desc.bInterfaceSubClass - != SC_VIDEOSTREAMING) { + != UVC_SC_VIDEOSTREAMING) { uvc_trace(UVC_TRACE_DESCR, "device %d interface %d isn't a " "video streaming interface\n", dev->udev->devnum, intf->altsetting[0].desc.bInterfaceNumber); @@ -589,12 +589,12 @@ static int uvc_parse_streaming(struct uvc_device *dev, /* Parse the header descriptor. */ switch (buffer[2]) { - case VS_OUTPUT_HEADER: + case UVC_VS_OUTPUT_HEADER: streaming->type = V4L2_BUF_TYPE_VIDEO_OUTPUT; size = 9; break; - case VS_INPUT_HEADER: + case UVC_VS_INPUT_HEADER: streaming->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; size = 13; break; @@ -618,7 +618,7 @@ static int uvc_parse_streaming(struct uvc_device *dev, streaming->header.bNumFormats = p; streaming->header.bEndpointAddress = buffer[6]; - if (buffer[2] == VS_INPUT_HEADER) { + if (buffer[2] == UVC_VS_INPUT_HEADER) { streaming->header.bmInfo = buffer[7]; streaming->header.bTerminalLink = buffer[8]; streaming->header.bStillCaptureMethod = buffer[9]; @@ -646,13 +646,13 @@ static int uvc_parse_streaming(struct uvc_device *dev, /* Count the format and frame descriptors. */ while (_buflen > 2 && _buffer[1] == USB_DT_CS_INTERFACE) { switch (_buffer[2]) { - case VS_FORMAT_UNCOMPRESSED: - case VS_FORMAT_MJPEG: - case VS_FORMAT_FRAME_BASED: + case UVC_VS_FORMAT_UNCOMPRESSED: + case UVC_VS_FORMAT_MJPEG: + case UVC_VS_FORMAT_FRAME_BASED: nformats++; break; - case VS_FORMAT_DV: + case UVC_VS_FORMAT_DV: /* DV format has no frame descriptor. We will create a * dummy frame descriptor with a dummy frame interval. */ @@ -661,22 +661,22 @@ static int uvc_parse_streaming(struct uvc_device *dev, nintervals++; break; - case VS_FORMAT_MPEG2TS: - case VS_FORMAT_STREAM_BASED: + case UVC_VS_FORMAT_MPEG2TS: + case UVC_VS_FORMAT_STREAM_BASED: uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming " "interface %d FORMAT %u is not supported.\n", dev->udev->devnum, alts->desc.bInterfaceNumber, _buffer[2]); break; - case VS_FRAME_UNCOMPRESSED: - case VS_FRAME_MJPEG: + case UVC_VS_FRAME_UNCOMPRESSED: + case UVC_VS_FRAME_MJPEG: nframes++; if (_buflen > 25) nintervals += _buffer[25] ? _buffer[25] : 3; break; - case VS_FRAME_FRAME_BASED: + case UVC_VS_FRAME_FRAME_BASED: nframes++; if (_buflen > 21) nintervals += _buffer[21] ? _buffer[21] : 3; @@ -711,10 +711,10 @@ static int uvc_parse_streaming(struct uvc_device *dev, /* Parse the format descriptors. */ while (buflen > 2 && buffer[1] == USB_DT_CS_INTERFACE) { switch (buffer[2]) { - case VS_FORMAT_UNCOMPRESSED: - case VS_FORMAT_MJPEG: - case VS_FORMAT_DV: - case VS_FORMAT_FRAME_BASED: + case UVC_VS_FORMAT_UNCOMPRESSED: + case UVC_VS_FORMAT_MJPEG: + case UVC_VS_FORMAT_DV: + case UVC_VS_FORMAT_FRAME_BASED: format->frame = frame; ret = uvc_parse_format(dev, streaming, format, &interval, buffer, buflen); @@ -819,7 +819,7 @@ static int uvc_parse_vendor_control(struct uvc_device *dev, return -ENOMEM; unit->id = buffer[3]; - unit->type = VC_EXTENSION_UNIT; + unit->type = UVC_VC_EXTENSION_UNIT; memcpy(unit->extension.guidExtensionCode, &buffer[4], 16); unit->extension.bNumControls = buffer[20]; unit->extension.bNrInPins = get_unaligned_le16(&buffer[21]); @@ -856,7 +856,7 @@ static int uvc_parse_standard_control(struct uvc_device *dev, __u16 type; switch (buffer[2]) { - case VC_HEADER: + case UVC_VC_HEADER: n = buflen >= 12 ? buffer[11] : 0; if (buflen < 12 || buflen < 12 + n) { @@ -883,7 +883,7 @@ static int uvc_parse_standard_control(struct uvc_device *dev, } break; - case VC_INPUT_TERMINAL: + case UVC_VC_INPUT_TERMINAL: if (buflen < 8) { uvc_trace(UVC_TRACE_DESCR, "device %d videocontrol " "interface %d INPUT_TERMINAL error\n", @@ -908,11 +908,11 @@ static int uvc_parse_standard_control(struct uvc_device *dev, p = 0; len = 8; - if (type == ITT_CAMERA) { + if (type == UVC_ITT_CAMERA) { n = buflen >= 15 ? buffer[14] : 0; len = 15; - } else if (type == ITT_MEDIA_TRANSPORT_INPUT) { + } else if (type == UVC_ITT_MEDIA_TRANSPORT_INPUT) { n = buflen >= 9 ? buffer[8] : 0; p = buflen >= 10 + n ? buffer[9+n] : 0; len = 10; @@ -932,7 +932,7 @@ static int uvc_parse_standard_control(struct uvc_device *dev, term->id = buffer[3]; term->type = type | UVC_TERM_INPUT; - if (UVC_ENTITY_TYPE(term) == ITT_CAMERA) { + if (UVC_ENTITY_TYPE(term) == UVC_ITT_CAMERA) { term->camera.bControlSize = n; term->camera.bmControls = (__u8 *)term + sizeof *term; term->camera.wObjectiveFocalLengthMin = @@ -942,7 +942,8 @@ static int uvc_parse_standard_control(struct uvc_device *dev, term->camera.wOcularFocalLength = get_unaligned_le16(&buffer[12]); memcpy(term->camera.bmControls, &buffer[15], n); - } else if (UVC_ENTITY_TYPE(term) == ITT_MEDIA_TRANSPORT_INPUT) { + } else if (UVC_ENTITY_TYPE(term) == + UVC_ITT_MEDIA_TRANSPORT_INPUT) { term->media.bControlSize = n; term->media.bmControls = (__u8 *)term + sizeof *term; term->media.bTransportModeSize = p; @@ -955,9 +956,9 @@ static int uvc_parse_standard_control(struct uvc_device *dev, if (buffer[7] != 0) usb_string(udev, buffer[7], term->name, sizeof term->name); - else if (UVC_ENTITY_TYPE(term) == ITT_CAMERA) + else if (UVC_ENTITY_TYPE(term) == UVC_ITT_CAMERA) sprintf(term->name, "Camera %u", buffer[3]); - else if (UVC_ENTITY_TYPE(term) == ITT_MEDIA_TRANSPORT_INPUT) + else if (UVC_ENTITY_TYPE(term) == UVC_ITT_MEDIA_TRANSPORT_INPUT) sprintf(term->name, "Media %u", buffer[3]); else sprintf(term->name, "Input %u", buffer[3]); @@ -965,7 +966,7 @@ static int uvc_parse_standard_control(struct uvc_device *dev, list_add_tail(&term->list, &dev->entities); break; - case VC_OUTPUT_TERMINAL: + case UVC_VC_OUTPUT_TERMINAL: if (buflen < 9) { uvc_trace(UVC_TRACE_DESCR, "device %d videocontrol " "interface %d OUTPUT_TERMINAL error\n", @@ -1002,7 +1003,7 @@ static int uvc_parse_standard_control(struct uvc_device *dev, list_add_tail(&term->list, &dev->entities); break; - case VC_SELECTOR_UNIT: + case UVC_VC_SELECTOR_UNIT: p = buflen >= 5 ? buffer[4] : 0; if (buflen < 5 || buflen < 6 + p) { @@ -1031,7 +1032,7 @@ static int uvc_parse_standard_control(struct uvc_device *dev, list_add_tail(&unit->list, &dev->entities); break; - case VC_PROCESSING_UNIT: + case UVC_VC_PROCESSING_UNIT: n = buflen >= 8 ? buffer[7] : 0; p = dev->uvc_version >= 0x0110 ? 10 : 9; @@ -1066,7 +1067,7 @@ static int uvc_parse_standard_control(struct uvc_device *dev, list_add_tail(&unit->list, &dev->entities); break; - case VC_EXTENSION_UNIT: + case UVC_VC_EXTENSION_UNIT: p = buflen >= 22 ? buffer[21] : 0; n = buflen >= 24 + p ? buffer[22+p] : 0; @@ -1194,7 +1195,7 @@ static int uvc_scan_chain_entity(struct uvc_video_device *video, struct uvc_entity *entity) { switch (UVC_ENTITY_TYPE(entity)) { - case VC_EXTENSION_UNIT: + case UVC_VC_EXTENSION_UNIT: if (uvc_trace_param & UVC_TRACE_PROBE) printk(" <- XU %d", entity->id); @@ -1207,7 +1208,7 @@ static int uvc_scan_chain_entity(struct uvc_video_device *video, list_add_tail(&entity->chain, &video->extensions); break; - case VC_PROCESSING_UNIT: + case UVC_VC_PROCESSING_UNIT: if (uvc_trace_param & UVC_TRACE_PROBE) printk(" <- PU %d", entity->id); @@ -1220,7 +1221,7 @@ static int uvc_scan_chain_entity(struct uvc_video_device *video, video->processing = entity; break; - case VC_SELECTOR_UNIT: + case UVC_VC_SELECTOR_UNIT: if (uvc_trace_param & UVC_TRACE_PROBE) printk(" <- SU %d", entity->id); @@ -1237,16 +1238,16 @@ static int uvc_scan_chain_entity(struct uvc_video_device *video, video->selector = entity; break; - case ITT_VENDOR_SPECIFIC: - case ITT_CAMERA: - case ITT_MEDIA_TRANSPORT_INPUT: + case UVC_ITT_VENDOR_SPECIFIC: + case UVC_ITT_CAMERA: + case UVC_ITT_MEDIA_TRANSPORT_INPUT: if (uvc_trace_param & UVC_TRACE_PROBE) printk(" <- IT %d\n", entity->id); list_add_tail(&entity->chain, &video->iterms); break; - case TT_STREAMING: + case UVC_TT_STREAMING: if (uvc_trace_param & UVC_TRACE_PROBE) printk(" <- IT %d\n", entity->id); @@ -1291,7 +1292,7 @@ static int uvc_scan_chain_forward(struct uvc_video_device *video, if (forward == NULL) break; - if (UVC_ENTITY_TYPE(forward) != VC_EXTENSION_UNIT || + if (UVC_ENTITY_TYPE(forward) != UVC_VC_EXTENSION_UNIT || forward == prev) continue; @@ -1323,15 +1324,15 @@ static int uvc_scan_chain_backward(struct uvc_video_device *video, int id = -1, i; switch (UVC_ENTITY_TYPE(entity)) { - case VC_EXTENSION_UNIT: + case UVC_VC_EXTENSION_UNIT: id = entity->extension.baSourceID[0]; break; - case VC_PROCESSING_UNIT: + case UVC_VC_PROCESSING_UNIT: id = entity->processing.bSourceID; break; - case VC_SELECTOR_UNIT: + case UVC_VC_SELECTOR_UNIT: /* Single-input selector units are ignored. */ if (entity->selector.bNrInPins == 1) { id = entity->selector.baSourceID[0]; @@ -1377,7 +1378,7 @@ static int uvc_scan_chain(struct uvc_video_device *video) entity = video->oterm; uvc_trace(UVC_TRACE_PROBE, "Scanning UVC chain: OT %d", entity->id); - if (UVC_ENTITY_TYPE(entity) == TT_STREAMING) + if (UVC_ENTITY_TYPE(entity) == UVC_TT_STREAMING) video->sterm = entity; id = entity->output.bSourceID; @@ -1664,7 +1665,8 @@ static void uvc_disconnect(struct usb_interface *intf) */ usb_set_intfdata(intf, NULL); - if (intf->cur_altsetting->desc.bInterfaceSubClass == SC_VIDEOSTREAMING) + if (intf->cur_altsetting->desc.bInterfaceSubClass == + UVC_SC_VIDEOSTREAMING) return; /* uvc_v4l2_open() might race uvc_disconnect(). A static driver-wide @@ -1692,7 +1694,8 @@ static int uvc_suspend(struct usb_interface *intf, pm_message_t message) intf->cur_altsetting->desc.bInterfaceNumber); /* Controls are cached on the fly so they don't need to be saved. */ - if (intf->cur_altsetting->desc.bInterfaceSubClass == SC_VIDEOCONTROL) + if (intf->cur_altsetting->desc.bInterfaceSubClass == + UVC_SC_VIDEOCONTROL) return uvc_status_suspend(dev); if (dev->video.streaming->intf != intf) { @@ -1711,7 +1714,8 @@ static int __uvc_resume(struct usb_interface *intf, int reset) uvc_trace(UVC_TRACE_SUSPEND, "Resuming interface %u\n", intf->cur_altsetting->desc.bInterfaceNumber); - if (intf->cur_altsetting->desc.bInterfaceSubClass == SC_VIDEOCONTROL) { + if (intf->cur_altsetting->desc.bInterfaceSubClass == + UVC_SC_VIDEOCONTROL) { if (reset) { int ret = uvc_ctrl_resume_device(dev); diff --git a/linux/drivers/media/video/uvc/uvc_v4l2.c b/linux/drivers/media/video/uvc/uvc_v4l2.c index 736d8ae23..a49d41764 100644 --- a/linux/drivers/media/video/uvc/uvc_v4l2.c +++ b/linux/drivers/media/video/uvc/uvc_v4l2.c @@ -647,7 +647,7 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) memset(input, 0, sizeof *input); input->index = index; strlcpy(input->name, iterm->name, sizeof input->name); - if (UVC_ENTITY_TYPE(iterm) == ITT_CAMERA) + if (UVC_ENTITY_TYPE(iterm) == UVC_ITT_CAMERA) input->type = V4L2_INPUT_TYPE_CAMERA; break; } @@ -662,9 +662,9 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) break; } - ret = uvc_query_ctrl(video->dev, GET_CUR, video->selector->id, - video->dev->intfnum, SU_INPUT_SELECT_CONTROL, - &input, 1); + ret = uvc_query_ctrl(video->dev, UVC_GET_CUR, + video->selector->id, video->dev->intfnum, + UVC_SU_INPUT_SELECT_CONTROL, &input, 1); if (ret < 0) return ret; @@ -689,9 +689,9 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) if (input == 0 || input > video->selector->selector.bNrInPins) return -EINVAL; - return uvc_query_ctrl(video->dev, SET_CUR, video->selector->id, - video->dev->intfnum, SU_INPUT_SELECT_CONTROL, - &input, 1); + return uvc_query_ctrl(video->dev, UVC_SET_CUR, + video->selector->id, video->dev->intfnum, + UVC_SU_INPUT_SELECT_CONTROL, &input, 1); } /* Try, Get, Set & Enum format */ diff --git a/linux/drivers/media/video/uvc/uvc_video.c b/linux/drivers/media/video/uvc/uvc_video.c index 07e755ba7..c833e984e 100644 --- a/linux/drivers/media/video/uvc/uvc_video.c +++ b/linux/drivers/media/video/uvc/uvc_video.c @@ -129,10 +129,10 @@ static int uvc_get_video_ctrl(struct uvc_video_device *video, return -ENOMEM; ret = __uvc_query_ctrl(video->dev, query, 0, video->streaming->intfnum, - probe ? VS_PROBE_CONTROL : VS_COMMIT_CONTROL, data, size, - UVC_CTRL_STREAMING_TIMEOUT); + probe ? UVC_VS_PROBE_CONTROL : UVC_VS_COMMIT_CONTROL, data, + size, UVC_CTRL_STREAMING_TIMEOUT); - if ((query == GET_MIN || query == GET_MAX) && ret == 2) { + if ((query == UVC_GET_MIN || query == UVC_GET_MAX) && ret == 2) { /* Some cameras, mostly based on Bison Electronics chipsets, * answer a GET_MIN or GET_MAX request with the wCompQuality * field only. @@ -144,7 +144,7 @@ static int uvc_get_video_ctrl(struct uvc_video_device *video, ctrl->wCompQuality = le16_to_cpup((__le16 *)data); ret = 0; goto out; - } else if (query == GET_DEF && probe == 1 && ret != size) { + } else if (query == UVC_GET_DEF && probe == 1 && ret != size) { /* Many cameras don't support the GET_DEF request on their * video probe control. Warn once and return, the caller will * fall back to GET_CUR. @@ -232,10 +232,10 @@ static int uvc_set_video_ctrl(struct uvc_video_device *video, data[33] = ctrl->bMaxVersion; } - ret = __uvc_query_ctrl(video->dev, SET_CUR, 0, + ret = __uvc_query_ctrl(video->dev, UVC_SET_CUR, 0, video->streaming->intfnum, - probe ? VS_PROBE_CONTROL : VS_COMMIT_CONTROL, data, size, - UVC_CTRL_STREAMING_TIMEOUT); + probe ? UVC_VS_PROBE_CONTROL : UVC_VS_COMMIT_CONTROL, data, + size, UVC_CTRL_STREAMING_TIMEOUT); if (ret != size) { uvc_printk(KERN_ERR, "Failed to set UVC %s control : " "%d (exp. %u).\n", probe ? "probe" : "commit", @@ -269,10 +269,10 @@ int uvc_probe_video(struct uvc_video_device *video, /* Get the minimum and maximum values for compression settings. */ if (!(video->dev->quirks & UVC_QUIRK_PROBE_MINMAX)) { - ret = uvc_get_video_ctrl(video, &probe_min, 1, GET_MIN); + ret = uvc_get_video_ctrl(video, &probe_min, 1, UVC_GET_MIN); if (ret < 0) goto done; - ret = uvc_get_video_ctrl(video, &probe_max, 1, GET_MAX); + ret = uvc_get_video_ctrl(video, &probe_max, 1, UVC_GET_MAX); if (ret < 0) goto done; @@ -280,8 +280,11 @@ int uvc_probe_video(struct uvc_video_device *video, } for (i = 0; i < 2; ++i) { - if ((ret = uvc_set_video_ctrl(video, probe, 1)) < 0 || - (ret = uvc_get_video_ctrl(video, probe, 1, GET_CUR)) < 0) + ret = uvc_set_video_ctrl(video, probe, 1); + if (ret < 0) + goto done; + ret = uvc_get_video_ctrl(video, probe, 1, UVC_GET_CUR); + if (ret < 0) goto done; if (video->streaming->intf->num_altsetting == 1) @@ -1069,7 +1072,7 @@ int uvc_video_init(struct uvc_video_device *video) * requests on the probe control will just keep their current streaming * parameters. */ - if (uvc_get_video_ctrl(video, probe, 1, GET_DEF) == 0) + if (uvc_get_video_ctrl(video, probe, 1, UVC_GET_DEF) == 0) uvc_set_video_ctrl(video, probe, 1); /* Initialize the streaming parameters with the probe control current @@ -1077,7 +1080,8 @@ int uvc_video_init(struct uvc_video_device *video) * control will always use values retrieved from a successful GET_CUR * request on the probe control, as required by the UVC specification. */ - if ((ret = uvc_get_video_ctrl(video, probe, 1, GET_CUR)) < 0) + ret = uvc_get_video_ctrl(video, probe, 1, UVC_GET_CUR); + if (ret < 0) return ret; /* Check if the default format descriptor exists. Use the first diff --git a/linux/drivers/media/video/uvc/uvcvideo.h b/linux/drivers/media/video/uvc/uvcvideo.h index 347fb4d7d..56fae496d 100644 --- a/linux/drivers/media/video/uvc/uvcvideo.h +++ b/linux/drivers/media/video/uvc/uvcvideo.h @@ -73,142 +73,142 @@ struct uvc_xu_control { * UVC constants */ -#define SC_UNDEFINED 0x00 -#define SC_VIDEOCONTROL 0x01 -#define SC_VIDEOSTREAMING 0x02 -#define SC_VIDEO_INTERFACE_COLLECTION 0x03 +#define UVC_SC_UNDEFINED 0x00 +#define UVC_SC_VIDEOCONTROL 0x01 +#define UVC_SC_VIDEOSTREAMING 0x02 +#define UVC_SC_VIDEO_INTERFACE_COLLECTION 0x03 -#define PC_PROTOCOL_UNDEFINED 0x00 +#define UVC_PC_PROTOCOL_UNDEFINED 0x00 /* VideoControl class specific interface descriptor */ -#define VC_DESCRIPTOR_UNDEFINED 0x00 -#define VC_HEADER 0x01 -#define VC_INPUT_TERMINAL 0x02 -#define VC_OUTPUT_TERMINAL 0x03 -#define VC_SELECTOR_UNIT 0x04 -#define VC_PROCESSING_UNIT 0x05 -#define VC_EXTENSION_UNIT 0x06 +#define UVC_VC_DESCRIPTOR_UNDEFINED 0x00 +#define UVC_VC_HEADER 0x01 +#define UVC_VC_INPUT_TERMINAL 0x02 +#define UVC_VC_OUTPUT_TERMINAL 0x03 +#define UVC_VC_SELECTOR_UNIT 0x04 +#define UVC_VC_PROCESSING_UNIT 0x05 +#define UVC_VC_EXTENSION_UNIT 0x06 /* VideoStreaming class specific interface descriptor */ -#define VS_UNDEFINED 0x00 -#define VS_INPUT_HEADER 0x01 -#define VS_OUTPUT_HEADER 0x02 -#define VS_STILL_IMAGE_FRAME 0x03 -#define VS_FORMAT_UNCOMPRESSED 0x04 -#define VS_FRAME_UNCOMPRESSED 0x05 -#define VS_FORMAT_MJPEG 0x06 -#define VS_FRAME_MJPEG 0x07 -#define VS_FORMAT_MPEG2TS 0x0a -#define VS_FORMAT_DV 0x0c -#define VS_COLORFORMAT 0x0d -#define VS_FORMAT_FRAME_BASED 0x10 -#define VS_FRAME_FRAME_BASED 0x11 -#define VS_FORMAT_STREAM_BASED 0x12 +#define UVC_VS_UNDEFINED 0x00 +#define UVC_VS_INPUT_HEADER 0x01 +#define UVC_VS_OUTPUT_HEADER 0x02 +#define UVC_VS_STILL_IMAGE_FRAME 0x03 +#define UVC_VS_FORMAT_UNCOMPRESSED 0x04 +#define UVC_VS_FRAME_UNCOMPRESSED 0x05 +#define UVC_VS_FORMAT_MJPEG 0x06 +#define UVC_VS_FRAME_MJPEG 0x07 +#define UVC_VS_FORMAT_MPEG2TS 0x0a +#define UVC_VS_FORMAT_DV 0x0c +#define UVC_VS_COLORFORMAT 0x0d +#define UVC_VS_FORMAT_FRAME_BASED 0x10 +#define UVC_VS_FRAME_FRAME_BASED 0x11 +#define UVC_VS_FORMAT_STREAM_BASED 0x12 /* Endpoint type */ -#define EP_UNDEFINED 0x00 -#define EP_GENERAL 0x01 -#define EP_ENDPOINT 0x02 -#define EP_INTERRUPT 0x03 +#define UVC_EP_UNDEFINED 0x00 +#define UVC_EP_GENERAL 0x01 +#define UVC_EP_ENDPOINT 0x02 +#define UVC_EP_INTERRUPT 0x03 /* Request codes */ -#define RC_UNDEFINED 0x00 -#define SET_CUR 0x01 -#define GET_CUR 0x81 -#define GET_MIN 0x82 -#define GET_MAX 0x83 -#define GET_RES 0x84 -#define GET_LEN 0x85 -#define GET_INFO 0x86 -#define GET_DEF 0x87 +#define UVC_RC_UNDEFINED 0x00 +#define UVC_SET_CUR 0x01 +#define UVC_GET_CUR 0x81 +#define UVC_GET_MIN 0x82 +#define UVC_GET_MAX 0x83 +#define UVC_GET_RES 0x84 +#define UVC_GET_LEN 0x85 +#define UVC_GET_INFO 0x86 +#define UVC_GET_DEF 0x87 /* VideoControl interface controls */ -#define VC_CONTROL_UNDEFINED 0x00 -#define VC_VIDEO_POWER_MODE_CONTROL 0x01 -#define VC_REQUEST_ERROR_CODE_CONTROL 0x02 +#define UVC_VC_CONTROL_UNDEFINED 0x00 +#define UVC_VC_VIDEO_POWER_MODE_CONTROL 0x01 +#define UVC_VC_REQUEST_ERROR_CODE_CONTROL 0x02 /* Terminal controls */ -#define TE_CONTROL_UNDEFINED 0x00 +#define UVC_TE_CONTROL_UNDEFINED 0x00 /* Selector Unit controls */ -#define SU_CONTROL_UNDEFINED 0x00 -#define SU_INPUT_SELECT_CONTROL 0x01 +#define UVC_SU_CONTROL_UNDEFINED 0x00 +#define UVC_SU_INPUT_SELECT_CONTROL 0x01 /* Camera Terminal controls */ -#define CT_CONTROL_UNDEFINED 0x00 -#define CT_SCANNING_MODE_CONTROL 0x01 -#define CT_AE_MODE_CONTROL 0x02 -#define CT_AE_PRIORITY_CONTROL 0x03 -#define CT_EXPOSURE_TIME_ABSOLUTE_CONTROL 0x04 -#define CT_EXPOSURE_TIME_RELATIVE_CONTROL 0x05 -#define CT_FOCUS_ABSOLUTE_CONTROL 0x06 -#define CT_FOCUS_RELATIVE_CONTROL 0x07 -#define CT_FOCUS_AUTO_CONTROL 0x08 -#define CT_IRIS_ABSOLUTE_CONTROL 0x09 -#define CT_IRIS_RELATIVE_CONTROL 0x0a -#define CT_ZOOM_ABSOLUTE_CONTROL 0x0b -#define CT_ZOOM_RELATIVE_CONTROL 0x0c -#define CT_PANTILT_ABSOLUTE_CONTROL 0x0d -#define CT_PANTILT_RELATIVE_CONTROL 0x0e -#define CT_ROLL_ABSOLUTE_CONTROL 0x0f -#define CT_ROLL_RELATIVE_CONTROL 0x10 -#define CT_PRIVACY_CONTROL 0x11 +#define UVC_CT_CONTROL_UNDEFINED 0x00 +#define UVC_CT_SCANNING_MODE_CONTROL 0x01 +#define UVC_CT_AE_MODE_CONTROL 0x02 +#define UVC_CT_AE_PRIORITY_CONTROL 0x03 +#define UVC_CT_EXPOSURE_TIME_ABSOLUTE_CONTROL 0x04 +#define UVC_CT_EXPOSURE_TIME_RELATIVE_CONTROL 0x05 +#define UVC_CT_FOCUS_ABSOLUTE_CONTROL 0x06 +#define UVC_CT_FOCUS_RELATIVE_CONTROL 0x07 +#define UVC_CT_FOCUS_AUTO_CONTROL 0x08 +#define UVC_CT_IRIS_ABSOLUTE_CONTROL 0x09 +#define UVC_CT_IRIS_RELATIVE_CONTROL 0x0a +#define UVC_CT_ZOOM_ABSOLUTE_CONTROL 0x0b +#define UVC_CT_ZOOM_RELATIVE_CONTROL 0x0c +#define UVC_CT_PANTILT_ABSOLUTE_CONTROL 0x0d +#define UVC_CT_PANTILT_RELATIVE_CONTROL 0x0e +#define UVC_CT_ROLL_ABSOLUTE_CONTROL 0x0f +#define UVC_CT_ROLL_RELATIVE_CONTROL 0x10 +#define UVC_CT_PRIVACY_CONTROL 0x11 /* Processing Unit controls */ -#define PU_CONTROL_UNDEFINED 0x00 -#define PU_BACKLIGHT_COMPENSATION_CONTROL 0x01 -#define PU_BRIGHTNESS_CONTROL 0x02 -#define PU_CONTRAST_CONTROL 0x03 -#define PU_GAIN_CONTROL 0x04 -#define PU_POWER_LINE_FREQUENCY_CONTROL 0x05 -#define PU_HUE_CONTROL 0x06 -#define PU_SATURATION_CONTROL 0x07 -#define PU_SHARPNESS_CONTROL 0x08 -#define PU_GAMMA_CONTROL 0x09 -#define PU_WHITE_BALANCE_TEMPERATURE_CONTROL 0x0a -#define PU_WHITE_BALANCE_TEMPERATURE_AUTO_CONTROL 0x0b -#define PU_WHITE_BALANCE_COMPONENT_CONTROL 0x0c -#define PU_WHITE_BALANCE_COMPONENT_AUTO_CONTROL 0x0d -#define PU_DIGITAL_MULTIPLIER_CONTROL 0x0e -#define PU_DIGITAL_MULTIPLIER_LIMIT_CONTROL 0x0f -#define PU_HUE_AUTO_CONTROL 0x10 -#define PU_ANALOG_VIDEO_STANDARD_CONTROL 0x11 -#define PU_ANALOG_LOCK_STATUS_CONTROL 0x12 - -#define LXU_MOTOR_PANTILT_RELATIVE_CONTROL 0x01 -#define LXU_MOTOR_PANTILT_RESET_CONTROL 0x02 -#define LXU_MOTOR_FOCUS_MOTOR_CONTROL 0x03 +#define UVC_PU_CONTROL_UNDEFINED 0x00 +#define UVC_PU_BACKLIGHT_COMPENSATION_CONTROL 0x01 +#define UVC_PU_BRIGHTNESS_CONTROL 0x02 +#define UVC_PU_CONTRAST_CONTROL 0x03 +#define UVC_PU_GAIN_CONTROL 0x04 +#define UVC_PU_POWER_LINE_FREQUENCY_CONTROL 0x05 +#define UVC_PU_HUE_CONTROL 0x06 +#define UVC_PU_SATURATION_CONTROL 0x07 +#define UVC_PU_SHARPNESS_CONTROL 0x08 +#define UVC_PU_GAMMA_CONTROL 0x09 +#define UVC_PU_WHITE_BALANCE_TEMPERATURE_CONTROL 0x0a +#define UVC_PU_WHITE_BALANCE_TEMPERATURE_AUTO_CONTROL 0x0b +#define UVC_PU_WHITE_BALANCE_COMPONENT_CONTROL 0x0c +#define UVC_PU_WHITE_BALANCE_COMPONENT_AUTO_CONTROL 0x0d +#define UVC_PU_DIGITAL_MULTIPLIER_CONTROL 0x0e +#define UVC_PU_DIGITAL_MULTIPLIER_LIMIT_CONTROL 0x0f +#define UVC_PU_HUE_AUTO_CONTROL 0x10 +#define UVC_PU_ANALOG_VIDEO_STANDARD_CONTROL 0x11 +#define UVC_PU_ANALOG_LOCK_STATUS_CONTROL 0x12 + +#define UVC_LXU_MOTOR_PANTILT_RELATIVE_CONTROL 0x01 +#define UVC_LXU_MOTOR_PANTILT_RESET_CONTROL 0x02 +#define UVC_LXU_MOTOR_FOCUS_MOTOR_CONTROL 0x03 /* VideoStreaming interface controls */ -#define VS_CONTROL_UNDEFINED 0x00 -#define VS_PROBE_CONTROL 0x01 -#define VS_COMMIT_CONTROL 0x02 -#define VS_STILL_PROBE_CONTROL 0x03 -#define VS_STILL_COMMIT_CONTROL 0x04 -#define VS_STILL_IMAGE_TRIGGER_CONTROL 0x05 -#define VS_STREAM_ERROR_CODE_CONTROL 0x06 -#define VS_GENERATE_KEY_FRAME_CONTROL 0x07 -#define VS_UPDATE_FRAME_SEGMENT_CONTROL 0x08 -#define VS_SYNC_DELAY_CONTROL 0x09 - -#define TT_VENDOR_SPECIFIC 0x0100 -#define TT_STREAMING 0x0101 +#define UVC_VS_CONTROL_UNDEFINED 0x00 +#define UVC_VS_PROBE_CONTROL 0x01 +#define UVC_VS_COMMIT_CONTROL 0x02 +#define UVC_VS_STILL_PROBE_CONTROL 0x03 +#define UVC_VS_STILL_COMMIT_CONTROL 0x04 +#define UVC_VS_STILL_IMAGE_TRIGGER_CONTROL 0x05 +#define UVC_VS_STREAM_ERROR_CODE_CONTROL 0x06 +#define UVC_VS_GENERATE_KEY_FRAME_CONTROL 0x07 +#define UVC_VS_UPDATE_FRAME_SEGMENT_CONTROL 0x08 +#define UVC_VS_SYNC_DELAY_CONTROL 0x09 + +#define UVC_TT_VENDOR_SPECIFIC 0x0100 +#define UVC_TT_STREAMING 0x0101 /* Input Terminal types */ -#define ITT_VENDOR_SPECIFIC 0x0200 -#define ITT_CAMERA 0x0201 -#define ITT_MEDIA_TRANSPORT_INPUT 0x0202 +#define UVC_ITT_VENDOR_SPECIFIC 0x0200 +#define UVC_ITT_CAMERA 0x0201 +#define UVC_ITT_MEDIA_TRANSPORT_INPUT 0x0202 /* Output Terminal types */ -#define OTT_VENDOR_SPECIFIC 0x0300 -#define OTT_DISPLAY 0x0301 -#define OTT_MEDIA_TRANSPORT_OUTPUT 0x0302 +#define UVC_OTT_VENDOR_SPECIFIC 0x0300 +#define UVC_OTT_DISPLAY 0x0301 +#define UVC_OTT_MEDIA_TRANSPORT_OUTPUT 0x0302 /* External Terminal types */ -#define EXTERNAL_VENDOR_SPECIFIC 0x0400 -#define COMPOSITE_CONNECTOR 0x0401 -#define SVIDEO_CONNECTOR 0x0402 -#define COMPONENT_CONNECTOR 0x0403 +#define UVC_EXTERNAL_VENDOR_SPECIFIC 0x0400 +#define UVC_COMPOSITE_CONNECTOR 0x0401 +#define UVC_SVIDEO_CONNECTOR 0x0402 +#define UVC_COMPONENT_CONNECTOR 0x0403 #define UVC_TERM_INPUT 0x0000 #define UVC_TERM_OUTPUT 0x8000 -- cgit v1.2.3 From 86ff6bf394e404a01c2a88b2b7ea90c6fd4eb456 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Fri, 26 Jun 2009 16:41:04 +0200 Subject: uvcvideo: Remove unused Logitech-specific constants From: Laurent Pinchart Those constants are not used anymore, remove them. Priority: normal Signed-off-by: Laurent Pinchart --- linux/drivers/media/video/uvc/uvcvideo.h | 17 ----------------- 1 file changed, 17 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/uvc/uvcvideo.h b/linux/drivers/media/video/uvc/uvcvideo.h index 56fae496d..2009c359a 100644 --- a/linux/drivers/media/video/uvc/uvcvideo.h +++ b/linux/drivers/media/video/uvc/uvcvideo.h @@ -175,10 +175,6 @@ struct uvc_xu_control { #define UVC_PU_ANALOG_VIDEO_STANDARD_CONTROL 0x11 #define UVC_PU_ANALOG_LOCK_STATUS_CONTROL 0x12 -#define UVC_LXU_MOTOR_PANTILT_RELATIVE_CONTROL 0x01 -#define UVC_LXU_MOTOR_PANTILT_RESET_CONTROL 0x02 -#define UVC_LXU_MOTOR_FOCUS_MOTOR_CONTROL 0x03 - /* VideoStreaming interface controls */ #define UVC_VS_CONTROL_UNDEFINED 0x00 #define UVC_VS_PROBE_CONTROL 0x01 @@ -243,19 +239,6 @@ struct uvc_xu_control { {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02} -#define UVC_GUID_LOGITECH_DEV_INFO \ - {0x82, 0x06, 0x61, 0x63, 0x70, 0x50, 0xab, 0x49, \ - 0xb8, 0xcc, 0xb3, 0x85, 0x5e, 0x8d, 0x22, 0x1e} -#define UVC_GUID_LOGITECH_USER_HW \ - {0x82, 0x06, 0x61, 0x63, 0x70, 0x50, 0xab, 0x49, \ - 0xb8, 0xcc, 0xb3, 0x85, 0x5e, 0x8d, 0x22, 0x1f} -#define UVC_GUID_LOGITECH_VIDEO \ - {0x82, 0x06, 0x61, 0x63, 0x70, 0x50, 0xab, 0x49, \ - 0xb8, 0xcc, 0xb3, 0x85, 0x5e, 0x8d, 0x22, 0x50} -#define UVC_GUID_LOGITECH_MOTOR \ - {0x82, 0x06, 0x61, 0x63, 0x70, 0x50, 0xab, 0x49, \ - 0xb8, 0xcc, 0xb3, 0x85, 0x5e, 0x8d, 0x22, 0x56} - #define UVC_GUID_FORMAT_MJPEG \ { 'M', 'J', 'P', 'G', 0x00, 0x00, 0x10, 0x00, \ 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71} -- cgit v1.2.3 From 8471361a8fff5c935da73faa3a790716b63e0fcd Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Fri, 26 Jun 2009 17:15:38 +0200 Subject: uvcvideo: Move UVC definitions to linux/usb/video.h From: Laurent Pinchart To make UVC constants accessible by a future UVC gadget driver, move them from drivers/media/video/uvc/uvcvideo.h to include/linux/usb/video.h. Priority: normal Signed-off-by: Laurent Pinchart --- linux/drivers/media/video/uvc/uvcvideo.h | 136 +------------------------------ 1 file changed, 1 insertion(+), 135 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/uvc/uvcvideo.h b/linux/drivers/media/video/uvc/uvcvideo.h index 2009c359a..4887650c9 100644 --- a/linux/drivers/media/video/uvc/uvcvideo.h +++ b/linux/drivers/media/video/uvc/uvcvideo.h @@ -67,145 +67,13 @@ struct uvc_xu_control { #ifdef __KERNEL__ #include +#include #include "compat.h" /* -------------------------------------------------------------------------- * UVC constants */ -#define UVC_SC_UNDEFINED 0x00 -#define UVC_SC_VIDEOCONTROL 0x01 -#define UVC_SC_VIDEOSTREAMING 0x02 -#define UVC_SC_VIDEO_INTERFACE_COLLECTION 0x03 - -#define UVC_PC_PROTOCOL_UNDEFINED 0x00 - -/* VideoControl class specific interface descriptor */ -#define UVC_VC_DESCRIPTOR_UNDEFINED 0x00 -#define UVC_VC_HEADER 0x01 -#define UVC_VC_INPUT_TERMINAL 0x02 -#define UVC_VC_OUTPUT_TERMINAL 0x03 -#define UVC_VC_SELECTOR_UNIT 0x04 -#define UVC_VC_PROCESSING_UNIT 0x05 -#define UVC_VC_EXTENSION_UNIT 0x06 - -/* VideoStreaming class specific interface descriptor */ -#define UVC_VS_UNDEFINED 0x00 -#define UVC_VS_INPUT_HEADER 0x01 -#define UVC_VS_OUTPUT_HEADER 0x02 -#define UVC_VS_STILL_IMAGE_FRAME 0x03 -#define UVC_VS_FORMAT_UNCOMPRESSED 0x04 -#define UVC_VS_FRAME_UNCOMPRESSED 0x05 -#define UVC_VS_FORMAT_MJPEG 0x06 -#define UVC_VS_FRAME_MJPEG 0x07 -#define UVC_VS_FORMAT_MPEG2TS 0x0a -#define UVC_VS_FORMAT_DV 0x0c -#define UVC_VS_COLORFORMAT 0x0d -#define UVC_VS_FORMAT_FRAME_BASED 0x10 -#define UVC_VS_FRAME_FRAME_BASED 0x11 -#define UVC_VS_FORMAT_STREAM_BASED 0x12 - -/* Endpoint type */ -#define UVC_EP_UNDEFINED 0x00 -#define UVC_EP_GENERAL 0x01 -#define UVC_EP_ENDPOINT 0x02 -#define UVC_EP_INTERRUPT 0x03 - -/* Request codes */ -#define UVC_RC_UNDEFINED 0x00 -#define UVC_SET_CUR 0x01 -#define UVC_GET_CUR 0x81 -#define UVC_GET_MIN 0x82 -#define UVC_GET_MAX 0x83 -#define UVC_GET_RES 0x84 -#define UVC_GET_LEN 0x85 -#define UVC_GET_INFO 0x86 -#define UVC_GET_DEF 0x87 - -/* VideoControl interface controls */ -#define UVC_VC_CONTROL_UNDEFINED 0x00 -#define UVC_VC_VIDEO_POWER_MODE_CONTROL 0x01 -#define UVC_VC_REQUEST_ERROR_CODE_CONTROL 0x02 - -/* Terminal controls */ -#define UVC_TE_CONTROL_UNDEFINED 0x00 - -/* Selector Unit controls */ -#define UVC_SU_CONTROL_UNDEFINED 0x00 -#define UVC_SU_INPUT_SELECT_CONTROL 0x01 - -/* Camera Terminal controls */ -#define UVC_CT_CONTROL_UNDEFINED 0x00 -#define UVC_CT_SCANNING_MODE_CONTROL 0x01 -#define UVC_CT_AE_MODE_CONTROL 0x02 -#define UVC_CT_AE_PRIORITY_CONTROL 0x03 -#define UVC_CT_EXPOSURE_TIME_ABSOLUTE_CONTROL 0x04 -#define UVC_CT_EXPOSURE_TIME_RELATIVE_CONTROL 0x05 -#define UVC_CT_FOCUS_ABSOLUTE_CONTROL 0x06 -#define UVC_CT_FOCUS_RELATIVE_CONTROL 0x07 -#define UVC_CT_FOCUS_AUTO_CONTROL 0x08 -#define UVC_CT_IRIS_ABSOLUTE_CONTROL 0x09 -#define UVC_CT_IRIS_RELATIVE_CONTROL 0x0a -#define UVC_CT_ZOOM_ABSOLUTE_CONTROL 0x0b -#define UVC_CT_ZOOM_RELATIVE_CONTROL 0x0c -#define UVC_CT_PANTILT_ABSOLUTE_CONTROL 0x0d -#define UVC_CT_PANTILT_RELATIVE_CONTROL 0x0e -#define UVC_CT_ROLL_ABSOLUTE_CONTROL 0x0f -#define UVC_CT_ROLL_RELATIVE_CONTROL 0x10 -#define UVC_CT_PRIVACY_CONTROL 0x11 - -/* Processing Unit controls */ -#define UVC_PU_CONTROL_UNDEFINED 0x00 -#define UVC_PU_BACKLIGHT_COMPENSATION_CONTROL 0x01 -#define UVC_PU_BRIGHTNESS_CONTROL 0x02 -#define UVC_PU_CONTRAST_CONTROL 0x03 -#define UVC_PU_GAIN_CONTROL 0x04 -#define UVC_PU_POWER_LINE_FREQUENCY_CONTROL 0x05 -#define UVC_PU_HUE_CONTROL 0x06 -#define UVC_PU_SATURATION_CONTROL 0x07 -#define UVC_PU_SHARPNESS_CONTROL 0x08 -#define UVC_PU_GAMMA_CONTROL 0x09 -#define UVC_PU_WHITE_BALANCE_TEMPERATURE_CONTROL 0x0a -#define UVC_PU_WHITE_BALANCE_TEMPERATURE_AUTO_CONTROL 0x0b -#define UVC_PU_WHITE_BALANCE_COMPONENT_CONTROL 0x0c -#define UVC_PU_WHITE_BALANCE_COMPONENT_AUTO_CONTROL 0x0d -#define UVC_PU_DIGITAL_MULTIPLIER_CONTROL 0x0e -#define UVC_PU_DIGITAL_MULTIPLIER_LIMIT_CONTROL 0x0f -#define UVC_PU_HUE_AUTO_CONTROL 0x10 -#define UVC_PU_ANALOG_VIDEO_STANDARD_CONTROL 0x11 -#define UVC_PU_ANALOG_LOCK_STATUS_CONTROL 0x12 - -/* VideoStreaming interface controls */ -#define UVC_VS_CONTROL_UNDEFINED 0x00 -#define UVC_VS_PROBE_CONTROL 0x01 -#define UVC_VS_COMMIT_CONTROL 0x02 -#define UVC_VS_STILL_PROBE_CONTROL 0x03 -#define UVC_VS_STILL_COMMIT_CONTROL 0x04 -#define UVC_VS_STILL_IMAGE_TRIGGER_CONTROL 0x05 -#define UVC_VS_STREAM_ERROR_CODE_CONTROL 0x06 -#define UVC_VS_GENERATE_KEY_FRAME_CONTROL 0x07 -#define UVC_VS_UPDATE_FRAME_SEGMENT_CONTROL 0x08 -#define UVC_VS_SYNC_DELAY_CONTROL 0x09 - -#define UVC_TT_VENDOR_SPECIFIC 0x0100 -#define UVC_TT_STREAMING 0x0101 - -/* Input Terminal types */ -#define UVC_ITT_VENDOR_SPECIFIC 0x0200 -#define UVC_ITT_CAMERA 0x0201 -#define UVC_ITT_MEDIA_TRANSPORT_INPUT 0x0202 - -/* Output Terminal types */ -#define UVC_OTT_VENDOR_SPECIFIC 0x0300 -#define UVC_OTT_DISPLAY 0x0301 -#define UVC_OTT_MEDIA_TRANSPORT_OUTPUT 0x0302 - -/* External Terminal types */ -#define UVC_EXTERNAL_VENDOR_SPECIFIC 0x0400 -#define UVC_COMPOSITE_CONNECTOR 0x0401 -#define UVC_SVIDEO_CONNECTOR 0x0402 -#define UVC_COMPONENT_CONNECTOR 0x0403 - #define UVC_TERM_INPUT 0x0000 #define UVC_TERM_OUTPUT 0x8000 @@ -217,8 +85,6 @@ struct uvc_xu_control { #define UVC_ENTITY_IS_OTERM(entity) \ (((entity)->type & 0x8000) == UVC_TERM_OUTPUT) -#define UVC_STATUS_TYPE_CONTROL 1 -#define UVC_STATUS_TYPE_STREAMING 2 /* ------------------------------------------------------------------------ * GUIDs -- cgit v1.2.3 From b59d997727eebbc353fdcf766af87931971f2c55 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Fri, 26 Jun 2009 15:00:59 -0400 Subject: au0828: fix i2c for kernels prior to 2.6.26 From: Michael Krufky Priority: normal Signed-off-by: Michael Krufky --- linux/drivers/media/video/au0828/au0828-i2c.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/au0828/au0828-i2c.c b/linux/drivers/media/video/au0828/au0828-i2c.c index a589d2ccb..bbe38a7a2 100644 --- a/linux/drivers/media/video/au0828/au0828-i2c.c +++ b/linux/drivers/media/video/au0828/au0828-i2c.c @@ -326,6 +326,9 @@ static struct i2c_adapter au0828_i2c_adap_template = { .owner = THIS_MODULE, .id = I2C_HW_B_AU0828, .algo = &au0828_i2c_algo_template, +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26) + .class = I2C_CLASS_TV_ANALOG, +#endif }; static struct i2c_client au0828_i2c_client_template = { -- cgit v1.2.3 From eb7f4d690e75f54bb19acf87a6c1878c65199455 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Sat, 27 Jun 2009 10:33:48 +0200 Subject: gspca - vc032x: Webcam 0ac8:c301 added. From: Jean-Francois Moine Only the back sensor (mi1320_soc) is usable. Priority: normal Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/vc032x.c | 50 +++++++++++++++++++++++--------- 1 file changed, 37 insertions(+), 13 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/vc032x.c b/linux/drivers/media/video/gspca/vc032x.c index a29c85cac..d8d2c5dc7 100644 --- a/linux/drivers/media/video/gspca/vc032x.c +++ b/linux/drivers/media/video/gspca/vc032x.c @@ -52,6 +52,7 @@ struct sd { #define SENSOR_OV7670 6 #define SENSOR_PO1200 7 #define SENSOR_PO3130NC 8 + u8 ninput; /* != 0 when 2 sensors - SamsungQ1 */ }; /* V4L2 controls supported by the driver */ @@ -2784,11 +2785,22 @@ static u16 read_sensor_register(struct gspca_dev *gspca_dev, static int vc032x_probe_sensor(struct gspca_dev *gspca_dev) { + struct sd *sd = (struct sd *) gspca_dev; struct usb_device *dev = gspca_dev->dev; int i; u16 value; const struct sensor_info *ptsensor_info; +/*fixme: should also check the other sensor (back mi1320_soc, front mc501cb)*/ + if (sd->ninput != 0) { + reg_w(dev, 0xa0, 0x01, 0xb301); +#if 1 + reg_w(dev, 0x89, 0xf0ff, 0xffff); /* select the back sensor */ +#else + reg_w(dev, 0x89, 0xf3ff, 0xffff); /* select the front sensor */ +#endif + } + reg_r(gspca_dev, 0xa1, 0xbfcf, 1); PDEBUG(D_PROBE, "check sensor header %02x", gspca_dev->usb_buf[0]); for (i = 0; i < ARRAY_SIZE(sensor_info_data); i++) { @@ -2918,7 +2930,8 @@ static int sd_config(struct gspca_dev *gspca_dev, }; cam = &gspca_dev->cam; - sd->bridge = id->driver_info; + sd->bridge = id->driver_info >> 8; + sd->ninput = id->driver_info & 0xff; #if 0 vc0321_reset(gspca_dev); #endif @@ -3095,6 +3108,13 @@ static int sd_start(struct gspca_dev *gspca_dev) #endif }; +/*fixme: back sensor only*/ + if (sd->ninput != 0) { + reg_w(gspca_dev->dev, 0x89, 0xf0ff, 0xffff); + reg_w(gspca_dev->dev, 0xa9, 0x8348, 0x000e); + reg_w(gspca_dev->dev, 0xa9, 0x0000, 0x001a); + } + /* Assume start use the good resolution from gspca_dev->mode */ if (sd->bridge == BRIDGE_VC0321) { reg_w(gspca_dev->dev, 0xa0, 0xff, 0xbfec); @@ -3366,19 +3386,23 @@ static const struct sd_desc sd_desc = { }; /* -- module initialisation -- */ +#define BF(bridge, flags) \ + .driver_info = (BRIDGE_ ## bridge << 8) \ + | (flags) static const __devinitdata struct usb_device_id device_table[] = { - {USB_DEVICE(0x041e, 0x405b), .driver_info = BRIDGE_VC0323}, - {USB_DEVICE(0x046d, 0x0892), .driver_info = BRIDGE_VC0321}, - {USB_DEVICE(0x046d, 0x0896), .driver_info = BRIDGE_VC0321}, - {USB_DEVICE(0x046d, 0x0897), .driver_info = BRIDGE_VC0321}, - {USB_DEVICE(0x0ac8, 0x0321), .driver_info = BRIDGE_VC0321}, - {USB_DEVICE(0x0ac8, 0x0323), .driver_info = BRIDGE_VC0323}, - {USB_DEVICE(0x0ac8, 0x0328), .driver_info = BRIDGE_VC0321}, - {USB_DEVICE(0x0ac8, 0xc001), .driver_info = BRIDGE_VC0321}, - {USB_DEVICE(0x0ac8, 0xc002), .driver_info = BRIDGE_VC0321}, - {USB_DEVICE(0x15b8, 0x6001), .driver_info = BRIDGE_VC0323}, - {USB_DEVICE(0x15b8, 0x6002), .driver_info = BRIDGE_VC0323}, - {USB_DEVICE(0x17ef, 0x4802), .driver_info = BRIDGE_VC0323}, + {USB_DEVICE(0x041e, 0x405b), BF(VC0323, 0)}, + {USB_DEVICE(0x046d, 0x0892), BF(VC0321, 0)}, + {USB_DEVICE(0x046d, 0x0896), BF(VC0321, 0)}, + {USB_DEVICE(0x046d, 0x0897), BF(VC0321, 0)}, + {USB_DEVICE(0x0ac8, 0x0321), BF(VC0321, 0)}, + {USB_DEVICE(0x0ac8, 0x0323), BF(VC0323, 0)}, + {USB_DEVICE(0x0ac8, 0x0328), BF(VC0321, 0)}, + {USB_DEVICE(0x0ac8, 0xc001), BF(VC0321, 0)}, + {USB_DEVICE(0x0ac8, 0xc002), BF(VC0321, 0)}, + {USB_DEVICE(0x0ac8, 0xc301), BF(VC0323, 1)}, + {USB_DEVICE(0x15b8, 0x6001), BF(VC0323, 0)}, + {USB_DEVICE(0x15b8, 0x6002), BF(VC0323, 0)}, + {USB_DEVICE(0x17ef, 0x4802), BF(VC0323, 0)}, {} }; MODULE_DEVICE_TABLE(usb, device_table); -- cgit v1.2.3 From 8b3e3e1439154e2c003f09c7fdcc0253bf878b66 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 12 Aug 2009 16:21:44 -0700 Subject: adds webcam for Micron device MT9M111 0x143A to em28xx From: Mauro Carvalho Chehab Priority: normal Signed-off-by: Steve Gotthardt [mchehab@redhat.com: fix merge conflict and a few CodingStyle issues] Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/em28xx/em28xx-cards.c | 40 +++++++++++++++++++++++-- linux/drivers/media/video/em28xx/em28xx.h | 1 + 2 files changed, 39 insertions(+), 2 deletions(-) (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 c936e7660..a38586176 100644 --- a/linux/drivers/media/video/em28xx/em28xx-cards.c +++ b/linux/drivers/media/video/em28xx/em28xx-cards.c @@ -1802,6 +1802,25 @@ static inline void em28xx_set_model(struct em28xx *dev) EM28XX_I2C_FREQ_100_KHZ; } + +/* FIXME: Should be replaced by a proper mt9m111 driver */ +static int em28xx_initialize_mt9m111(struct em28xx *dev) +{ + int i; + unsigned char regs[][3] = { + { 0x0d, 0x00, 0x01, }, /* reset and use defaults */ + { 0x0d, 0x00, 0x00, }, + { 0x0a, 0x00, 0x21, }, + { 0x21, 0x04, 0x00, }, /* full readout speed, no row/col skipping */ + }; + + for (i = 0; i < ARRAY_SIZE(regs); i++) + i2c_master_send(&dev->i2c_client, ®s[i][0], 3); + + return 0; +} + + /* FIXME: Should be replaced by a proper mt9m001 driver */ static int em28xx_initialize_mt9m001(struct em28xx *dev) { @@ -1830,7 +1849,7 @@ static int em28xx_initialize_mt9m001(struct em28xx *dev) /* HINT method: webcam I2C chips * - * This method work for webcams with Micron sensors + * This method works for webcams with Micron sensors */ static int em28xx_hint_sensor(struct em28xx *dev) { @@ -1876,6 +1895,23 @@ static int em28xx_hint_sensor(struct em28xx *dev) dev->vinctl = 0x00; break; + + case 0x143a: /* MT9M111 as found in the ECS G200 */ + dev->model = EM2750_BOARD_UNKNOWN; + em28xx_set_model(dev); + + sensor_name = "mt9m111"; + dev->board.xclk = EM28XX_XCLK_FREQUENCY_48MHZ; + dev->em28xx_sensor = EM28XX_MT9M111; + em28xx_initialize_mt9m111(dev); + dev->sensor_xres = 640; + dev->sensor_yres = 512; + + dev->vinmode = 0x0a; + dev->vinctl = 0x00; + + break; + #if 0 case 0x8411: case 0x8421: @@ -1896,7 +1932,7 @@ static int em28xx_hint_sensor(struct em28xx *dev) break; default: - printk("Unknown Micron Sensor 0x%04x\n", be16_to_cpu(version)); + printk("Unknown Micron Sensor 0x%04x\n", version); return -EINVAL; } diff --git a/linux/drivers/media/video/em28xx/em28xx.h b/linux/drivers/media/video/em28xx/em28xx.h index c76da6985..70a41b640 100644 --- a/linux/drivers/media/video/em28xx/em28xx.h +++ b/linux/drivers/media/video/em28xx/em28xx.h @@ -368,6 +368,7 @@ enum em28xx_sensor { EM28XX_NOSENSOR = 0, EM28XX_MT9V011, EM28XX_MT9M001, + EM28XX_MT9M111, }; enum em28xx_adecoder { -- cgit v1.2.3 From 6e05c460e54586ee98bad3744eef1e47d90176fa Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 28 Jun 2009 07:22:55 +0000 Subject: Siano: Fixed SDIO compilation bugs From: Udi Atar Fixed SDIO compilation bugs (for latest kernel). Also fixed a memory overrun issue in buffer management. Priority: normal Signed-off-by: Udi Atar Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/siano/smssdio.c | 54 ++++++++++++++++++--------------- 1 file changed, 30 insertions(+), 24 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/siano/smssdio.c b/linux/drivers/media/dvb/siano/smssdio.c index dfaa49a53..d1d652e7f 100644 --- a/linux/drivers/media/dvb/siano/smssdio.c +++ b/linux/drivers/media/dvb/siano/smssdio.c @@ -46,6 +46,7 @@ #define SMSSDIO_DATA 0x00 #define SMSSDIO_INT 0x04 +#define SMSSDIO_BLOCK_SIZE 128 static const struct sdio_device_id smssdio_ids[] = { {SDIO_DEVICE(SDIO_VENDOR_ID_SIANO, SDIO_DEVICE_ID_SIANO_STELLAR), @@ -85,7 +86,8 @@ static int smssdio_sendrequest(void *context, void *buffer, size_t size) sdio_claim_host(smsdev->func); while (size >= smsdev->func->cur_blksize) { - ret = sdio_write_blocks(smsdev->func, SMSSDIO_DATA, buffer, 1); + ret = sdio_memcpy_toio(smsdev->func, SMSSDIO_DATA, + buffer, smsdev->func->cur_blksize); if (ret) goto out; @@ -94,8 +96,8 @@ static int smssdio_sendrequest(void *context, void *buffer, size_t size) } if (size) { - ret = sdio_write_bytes(smsdev->func, SMSSDIO_DATA, - buffer, size); + ret = sdio_memcpy_toio(smsdev->func, SMSSDIO_DATA, + buffer, size); } out: @@ -125,23 +127,23 @@ static void smssdio_interrupt(struct sdio_func *func) */ isr = sdio_readb(func, SMSSDIO_INT, &ret); if (ret) { - dev_err(&smsdev->func->dev, - "Unable to read interrupt register!\n"); + sms_err("Unable to read interrupt register!\n"); return; } if (smsdev->split_cb == NULL) { cb = smscore_getbuffer(smsdev->coredev); if (!cb) { - dev_err(&smsdev->func->dev, - "Unable to allocate data buffer!\n"); + sms_err("Unable to allocate data buffer!\n"); return; } - ret = sdio_read_blocks(smsdev->func, cb->p, SMSSDIO_DATA, 1); + ret = sdio_memcpy_fromio(smsdev->func, + cb->p, + SMSSDIO_DATA, + SMSSDIO_BLOCK_SIZE); if (ret) { - dev_err(&smsdev->func->dev, - "Error %d reading initial block!\n", ret); + sms_err("Error %d reading initial block!\n", ret); return; } @@ -152,7 +154,10 @@ static void smssdio_interrupt(struct sdio_func *func) return; } - size = hdr->msgLength - smsdev->func->cur_blksize; + if (hdr->msgLength > smsdev->func->cur_blksize) + size = hdr->msgLength - smsdev->func->cur_blksize; + else + size = 0; } else { cb = smsdev->split_cb; hdr = cb->p; @@ -162,23 +167,24 @@ static void smssdio_interrupt(struct sdio_func *func) smsdev->split_cb = NULL; } - if (hdr->msgLength > smsdev->func->cur_blksize) { + if (size) { void *buffer; - size = ALIGN(size, 128); - buffer = cb->p + hdr->msgLength; + buffer = cb->p + (hdr->msgLength - size); + size = ALIGN(size, SMSSDIO_BLOCK_SIZE); - BUG_ON(smsdev->func->cur_blksize != 128); + BUG_ON(smsdev->func->cur_blksize != SMSSDIO_BLOCK_SIZE); /* * First attempt to transfer all of it in one go... */ - ret = sdio_read_blocks(smsdev->func, buffer, - SMSSDIO_DATA, size / 128); + ret = sdio_memcpy_fromio(smsdev->func, + buffer, + SMSSDIO_DATA, + size); if (ret && ret != -EINVAL) { smscore_putbuffer(smsdev->coredev, cb); - dev_err(&smsdev->func->dev, - "Error %d reading data from card!\n", ret); + sms_err("Error %d reading data from card!\n", ret); return; } @@ -191,12 +197,12 @@ static void smssdio_interrupt(struct sdio_func *func) */ if (ret == -EINVAL) { while (size) { - ret = sdio_read_blocks(smsdev->func, - buffer, SMSSDIO_DATA, 1); + ret = sdio_memcpy_fromio(smsdev->func, + buffer, SMSSDIO_DATA, + smsdev->func->cur_blksize); if (ret) { smscore_putbuffer(smsdev->coredev, cb); - dev_err(&smsdev->func->dev, - "Error %d reading " + sms_err("Error %d reading " "data from card!\n", ret); return; } @@ -269,7 +275,7 @@ static int smssdio_probe(struct sdio_func *func, if (ret) goto release; - ret = sdio_set_block_size(func, 128); + ret = sdio_set_block_size(func, SMSSDIO_BLOCK_SIZE); if (ret) goto disable; -- cgit v1.2.3 From 515fc60834c8e3e51c3fb97e362c74a3324d817e Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Sun, 28 Jun 2009 13:37:50 +0200 Subject: uvcvideo: Restructure the driver to support multiple simultaneous streams. From: Laurent Pinchart As a first step towards multiple streaming interfaces support, reorganize the driver's data structures to cleanly separate video control and video streaming data. Priority: normal Signed-off-by: Laurent Pinchart --- linux/drivers/media/video/uvc/uvc_driver.c | 174 ++++++------ linux/drivers/media/video/uvc/uvc_isight.c | 7 +- linux/drivers/media/video/uvc/uvc_v4l2.c | 195 +++++++------- linux/drivers/media/video/uvc/uvc_video.c | 415 +++++++++++++++-------------- linux/drivers/media/video/uvc/uvcvideo.h | 86 +++--- 5 files changed, 456 insertions(+), 421 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 1d09751a3..70d15a926 100644 --- a/linux/drivers/media/video/uvc/uvc_driver.c +++ b/linux/drivers/media/video/uvc/uvc_driver.c @@ -551,6 +551,7 @@ static int uvc_parse_streaming(struct uvc_device *dev, } mutex_init(&streaming->mutex); + streaming->dev = dev; streaming->intf = usb_get_intf(intf); streaming->intfnum = intf->cur_altsetting->desc.bInterfaceNumber; @@ -751,7 +752,7 @@ static int uvc_parse_streaming(struct uvc_device *dev, streaming->maxpsize = psize; } - list_add_tail(&streaming->list, &dev->streaming); + list_add_tail(&streaming->list, &dev->streams); return 0; error: @@ -1167,13 +1168,75 @@ next_descriptor: */ static void uvc_unregister_video(struct uvc_device *dev) { - if (dev->video.vdev) { - if (dev->video.vdev->minor == -1) - video_device_release(dev->video.vdev); + struct uvc_streaming *streaming; + + list_for_each_entry(streaming, &dev->streams, list) { + if (streaming->vdev == NULL) + continue; + + if (streaming->vdev->minor == -1) + video_device_release(streaming->vdev); else - video_unregister_device(dev->video.vdev); - dev->video.vdev = NULL; + video_unregister_device(streaming->vdev); + streaming->vdev = NULL; + } +} + +static int uvc_register_video(struct uvc_device *dev, + struct uvc_streaming *stream) +{ + struct video_device *vdev; + struct uvc_entity *term; + int ret; + + if (uvc_trace_param & UVC_TRACE_PROBE) { + uvc_printk(KERN_INFO, "Found a valid video chain ("); + list_for_each_entry(term, &dev->video.iterms, chain) { + printk("%d", term->id); + if (term->chain.next != &dev->video.iterms) + printk(","); + } + printk(" -> %d).\n", dev->video.oterm->id); + } + + /* Initialize the streaming interface with default streaming + * parameters. + */ + ret = uvc_video_init(stream); + if (ret < 0) { + uvc_printk(KERN_ERR, "Failed to initialize the device " + "(%d).\n", ret); + return ret; + } + + /* Register the device with V4L. */ + vdev = video_device_alloc(); + if (vdev == NULL) + return -1; + + /* We already hold a reference to dev->udev. The video device will be + * unregistered before the reference is released, so we don't need to + * get another one. + */ + vdev->parent = &dev->intf->dev; + vdev->minor = -1; + vdev->fops = &uvc_fops; + vdev->release = video_device_release; + strlcpy(vdev->name, dev->name, sizeof vdev->name); + + /* Set the driver data before calling video_register_device, otherwise + * uvc_v4l2_open might race us. + */ + stream->vdev = vdev; + video_set_drvdata(vdev, stream); + + if (video_register_device(vdev, VFL_TYPE_GRABBER, -1) < 0) { + stream->vdev = NULL; + video_device_release(vdev); + return -1; } + + return 0; } /* @@ -1419,7 +1482,7 @@ static int uvc_scan_chain(struct uvc_video_device *video) } /* - * Register the video devices. + * Scan the device for video chains and register video devices. * * The driver currently supports a single video device per control interface * only. The terminal and units must match the following structure: @@ -1432,15 +1495,14 @@ static int uvc_scan_chain(struct uvc_video_device *video) * Extension Units connected to the main chain as single-unit branches are * also supported. */ -static int uvc_register_video(struct uvc_device *dev) +static int uvc_scan_device(struct uvc_device *dev) { - struct video_device *vdev; struct uvc_entity *term; - int found = 0, ret; + int found = 0; /* Check if the control interface matches the structure we expect. */ list_for_each_entry(term, &dev->entities, list) { - struct uvc_streaming *streaming; + struct uvc_streaming *stream; if (!UVC_ENTITY_IS_TERM(term) || !UVC_ENTITY_IS_OTERM(term)) continue; @@ -1454,17 +1516,14 @@ static int uvc_register_video(struct uvc_device *dev) if (uvc_scan_chain(&dev->video) < 0) continue; - list_for_each_entry(streaming, &dev->streaming, list) { - if (streaming->header.bTerminalLink == + list_for_each_entry(stream, &dev->streams, list) { + if (stream->header.bTerminalLink == dev->video.sterm->id) { - dev->video.streaming = streaming; + uvc_register_video(dev, stream); found = 1; break; } } - - if (found) - break; } if (!found) { @@ -1472,55 +1531,6 @@ static int uvc_register_video(struct uvc_device *dev) return -1; } - if (uvc_trace_param & UVC_TRACE_PROBE) { - uvc_printk(KERN_INFO, "Found a valid video chain ("); - list_for_each_entry(term, &dev->video.iterms, chain) { - printk("%d", term->id); - if (term->chain.next != &dev->video.iterms) - printk(","); - } - printk(" -> %d).\n", dev->video.oterm->id); - } - - /* Initialize the video buffers queue. */ - uvc_queue_init(&dev->video.queue, dev->video.streaming->type); - - /* Initialize the streaming interface with default streaming - * parameters. - */ - if ((ret = uvc_video_init(&dev->video)) < 0) { - uvc_printk(KERN_ERR, "Failed to initialize the device " - "(%d).\n", ret); - return ret; - } - - /* Register the device with V4L. */ - vdev = video_device_alloc(); - if (vdev == NULL) - return -1; - - /* We already hold a reference to dev->udev. The video device will be - * unregistered before the reference is released, so we don't need to - * get another one. - */ - vdev->parent = &dev->intf->dev; - vdev->minor = -1; - vdev->fops = &uvc_fops; - vdev->release = video_device_release; - strlcpy(vdev->name, dev->name, sizeof vdev->name); - - /* Set the driver data before calling video_register_device, otherwise - * uvc_v4l2_open might race us. - */ - dev->video.vdev = vdev; - video_set_drvdata(vdev, &dev->video); - - if (video_register_device(vdev, VFL_TYPE_GRABBER, -1) < 0) { - dev->video.vdev = NULL; - video_device_release(vdev); - return -1; - } - return 0; } @@ -1559,7 +1569,7 @@ void uvc_delete(struct kref *kref) kfree(entity); } - list_for_each_safe(p, n, &dev->streaming) { + list_for_each_safe(p, n, &dev->streams) { struct uvc_streaming *streaming; streaming = list_entry(p, struct uvc_streaming, list); usb_driver_release_interface(&uvc_driver.driver, @@ -1593,7 +1603,7 @@ static int uvc_probe(struct usb_interface *intf, return -ENOMEM; INIT_LIST_HEAD(&dev->entities); - INIT_LIST_HEAD(&dev->streaming); + INIT_LIST_HEAD(&dev->streams); kref_init(&dev->kref); atomic_set(&dev->users, 0); @@ -1634,8 +1644,8 @@ static int uvc_probe(struct usb_interface *intf, if (uvc_ctrl_init_device(dev) < 0) goto error; - /* Register the video devices. */ - if (uvc_register_video(dev) < 0) + /* Scan the device for video chains and register video devices. */ + if (uvc_scan_device(dev) < 0) goto error; /* Save our data pointer in the interface data. */ @@ -1689,6 +1699,7 @@ static void uvc_disconnect(struct usb_interface *intf) static int uvc_suspend(struct usb_interface *intf, pm_message_t message) { struct uvc_device *dev = usb_get_intfdata(intf); + struct uvc_streaming *stream; uvc_trace(UVC_TRACE_SUSPEND, "Suspending interface %u\n", intf->cur_altsetting->desc.bInterfaceNumber); @@ -1698,18 +1709,20 @@ static int uvc_suspend(struct usb_interface *intf, pm_message_t message) UVC_SC_VIDEOCONTROL) return uvc_status_suspend(dev); - if (dev->video.streaming->intf != intf) { - uvc_trace(UVC_TRACE_SUSPEND, "Suspend: video streaming USB " - "interface mismatch.\n"); - return -EINVAL; + list_for_each_entry(stream, &dev->streams, list) { + if (stream->intf == intf) + return uvc_video_suspend(stream); } - return uvc_video_suspend(&dev->video); + uvc_trace(UVC_TRACE_SUSPEND, "Suspend: video streaming USB interface " + "mismatch.\n"); + return -EINVAL; } static int __uvc_resume(struct usb_interface *intf, int reset) { struct uvc_device *dev = usb_get_intfdata(intf); + struct uvc_streaming *stream; uvc_trace(UVC_TRACE_SUSPEND, "Resuming interface %u\n", intf->cur_altsetting->desc.bInterfaceNumber); @@ -1726,13 +1739,14 @@ static int __uvc_resume(struct usb_interface *intf, int reset) return uvc_status_resume(dev); } - if (dev->video.streaming->intf != intf) { - uvc_trace(UVC_TRACE_SUSPEND, "Resume: video streaming USB " - "interface mismatch.\n"); - return -EINVAL; + list_for_each_entry(stream, &dev->streams, list) { + if (stream->intf == intf) + return uvc_video_resume(stream); } - return uvc_video_resume(&dev->video); + uvc_trace(UVC_TRACE_SUSPEND, "Resume: video streaming USB interface " + "mismatch.\n"); + return -EINVAL; } static int uvc_resume(struct usb_interface *intf) diff --git a/linux/drivers/media/video/uvc/uvc_isight.c b/linux/drivers/media/video/uvc/uvc_isight.c index 436f46268..a9285b570 100644 --- a/linux/drivers/media/video/uvc/uvc_isight.c +++ b/linux/drivers/media/video/uvc/uvc_isight.c @@ -99,7 +99,7 @@ static int isight_decode(struct uvc_video_queue *queue, struct uvc_buffer *buf, return 0; } -void uvc_video_decode_isight(struct urb *urb, struct uvc_video_device *video, +void uvc_video_decode_isight(struct urb *urb, struct uvc_streaming *stream, struct uvc_buffer *buf) { int ret, i; @@ -120,7 +120,7 @@ void uvc_video_decode_isight(struct urb *urb, struct uvc_video_device *video, * processes the data of the first payload of the new frame. */ do { - ret = isight_decode(&video->queue, buf, + ret = isight_decode(&stream->queue, buf, urb->transfer_buffer + urb->iso_frame_desc[i].offset, urb->iso_frame_desc[i].actual_length); @@ -130,7 +130,8 @@ void uvc_video_decode_isight(struct urb *urb, struct uvc_video_device *video, if (buf->state == UVC_BUF_STATE_DONE || buf->state == UVC_BUF_STATE_ERROR) - buf = uvc_queue_next_buffer(&video->queue, buf); + buf = uvc_queue_next_buffer(&stream->queue, + buf); } while (ret == -EAGAIN); } } diff --git a/linux/drivers/media/video/uvc/uvc_v4l2.c b/linux/drivers/media/video/uvc/uvc_v4l2.c index 31a9ed4ff..3379e1320 100644 --- a/linux/drivers/media/video/uvc/uvc_v4l2.c +++ b/linux/drivers/media/video/uvc/uvc_v4l2.c @@ -103,7 +103,7 @@ static __u32 uvc_try_frame_interval(struct uvc_frame *frame, __u32 interval) return interval; } -static int uvc_v4l2_try_format(struct uvc_video_device *video, +static int uvc_v4l2_try_format(struct uvc_streaming *stream, struct v4l2_format *fmt, struct uvc_streaming_control *probe, struct uvc_format **uvc_format, struct uvc_frame **uvc_frame) { @@ -116,7 +116,7 @@ static int uvc_v4l2_try_format(struct uvc_video_device *video, int ret = 0; __u8 *fcc; - if (fmt->type != video->streaming->type) + if (fmt->type != stream->type) return -EINVAL; fcc = (__u8 *)&fmt->fmt.pix.pixelformat; @@ -126,8 +126,8 @@ static int uvc_v4l2_try_format(struct uvc_video_device *video, fmt->fmt.pix.width, fmt->fmt.pix.height); /* Check if the hardware supports the requested format. */ - for (i = 0; i < video->streaming->nformats; ++i) { - format = &video->streaming->format[i]; + for (i = 0; i < stream->nformats; ++i) { + format = &stream->format[i]; if (format->fcc == fmt->fmt.pix.pixelformat) break; } @@ -191,12 +191,13 @@ static int uvc_v4l2_try_format(struct uvc_video_device *video, * developers test their webcams with the Linux driver as well as with * the Windows driver). */ - if (video->dev->quirks & UVC_QUIRK_PROBE_EXTRAFIELDS) + if (stream->dev->quirks & UVC_QUIRK_PROBE_EXTRAFIELDS) probe->dwMaxVideoFrameSize = - video->streaming->ctrl.dwMaxVideoFrameSize; + stream->ctrl.dwMaxVideoFrameSize; /* Probe the device. */ - if ((ret = uvc_probe_video(video, probe)) < 0) + ret = uvc_probe_video(stream, probe); + if (ret < 0) goto done; fmt->fmt.pix.width = frame->wWidth; @@ -216,13 +217,13 @@ done: return ret; } -static int uvc_v4l2_get_format(struct uvc_video_device *video, +static int uvc_v4l2_get_format(struct uvc_streaming *stream, struct v4l2_format *fmt) { - struct uvc_format *format = video->streaming->cur_format; - struct uvc_frame *frame = video->streaming->cur_frame; + struct uvc_format *format = stream->cur_format; + struct uvc_frame *frame = stream->cur_frame; - if (fmt->type != video->streaming->type) + if (fmt->type != stream->type) return -EINVAL; if (format == NULL || frame == NULL) @@ -233,14 +234,14 @@ static int uvc_v4l2_get_format(struct uvc_video_device *video, fmt->fmt.pix.height = frame->wHeight; fmt->fmt.pix.field = V4L2_FIELD_NONE; fmt->fmt.pix.bytesperline = format->bpp * frame->wWidth / 8; - fmt->fmt.pix.sizeimage = video->streaming->ctrl.dwMaxVideoFrameSize; + fmt->fmt.pix.sizeimage = stream->ctrl.dwMaxVideoFrameSize; fmt->fmt.pix.colorspace = format->colorspace; fmt->fmt.pix.priv = 0; return 0; } -static int uvc_v4l2_set_format(struct uvc_video_device *video, +static int uvc_v4l2_set_format(struct uvc_streaming *stream, struct v4l2_format *fmt) { struct uvc_streaming_control probe; @@ -248,39 +249,39 @@ static int uvc_v4l2_set_format(struct uvc_video_device *video, struct uvc_frame *frame; int ret; - if (fmt->type != video->streaming->type) + if (fmt->type != stream->type) return -EINVAL; - if (uvc_queue_allocated(&video->queue)) + if (uvc_queue_allocated(&stream->queue)) return -EBUSY; - ret = uvc_v4l2_try_format(video, fmt, &probe, &format, &frame); + ret = uvc_v4l2_try_format(stream, fmt, &probe, &format, &frame); if (ret < 0) return ret; - memcpy(&video->streaming->ctrl, &probe, sizeof probe); - video->streaming->cur_format = format; - video->streaming->cur_frame = frame; + memcpy(&stream->ctrl, &probe, sizeof probe); + stream->cur_format = format; + stream->cur_frame = frame; return 0; } -static int uvc_v4l2_get_streamparm(struct uvc_video_device *video, +static int uvc_v4l2_get_streamparm(struct uvc_streaming *stream, struct v4l2_streamparm *parm) { uint32_t numerator, denominator; - if (parm->type != video->streaming->type) + if (parm->type != stream->type) return -EINVAL; - numerator = video->streaming->ctrl.dwFrameInterval; + numerator = stream->ctrl.dwFrameInterval; denominator = 10000000; uvc_simplify_fraction(&numerator, &denominator, 8, 333); memset(parm, 0, sizeof *parm); - parm->type = video->streaming->type; + parm->type = stream->type; - if (video->streaming->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { + if (stream->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { parm->parm.capture.capability = V4L2_CAP_TIMEPERFRAME; parm->parm.capture.capturemode = 0; parm->parm.capture.timeperframe.numerator = numerator; @@ -297,19 +298,19 @@ static int uvc_v4l2_get_streamparm(struct uvc_video_device *video, return 0; } -static int uvc_v4l2_set_streamparm(struct uvc_video_device *video, +static int uvc_v4l2_set_streamparm(struct uvc_streaming *stream, struct v4l2_streamparm *parm) { - struct uvc_frame *frame = video->streaming->cur_frame; + struct uvc_frame *frame = stream->cur_frame; struct uvc_streaming_control probe; struct v4l2_fract timeperframe; uint32_t interval; int ret; - if (parm->type != video->streaming->type) + if (parm->type != stream->type) return -EINVAL; - if (uvc_queue_streaming(&video->queue)) + if (uvc_queue_streaming(&stream->queue)) return -EBUSY; if (parm->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) @@ -317,7 +318,7 @@ static int uvc_v4l2_set_streamparm(struct uvc_video_device *video, else timeperframe = parm->parm.output.timeperframe; - memcpy(&probe, &video->streaming->ctrl, sizeof probe); + memcpy(&probe, &stream->ctrl, sizeof probe); interval = uvc_fraction_to_interval(timeperframe.numerator, timeperframe.denominator); @@ -326,10 +327,11 @@ static int uvc_v4l2_set_streamparm(struct uvc_video_device *video, probe.dwFrameInterval = uvc_try_frame_interval(frame, interval); /* Probe the device with the new settings. */ - if ((ret = uvc_probe_video(video, &probe)) < 0) + ret = uvc_probe_video(stream, &probe); + if (ret < 0) return ret; - memcpy(&video->streaming->ctrl, &probe, sizeof probe); + memcpy(&stream->ctrl, &probe, sizeof probe); /* Return the actual frame period. */ timeperframe.numerator = probe.dwFrameInterval; @@ -382,8 +384,8 @@ static int uvc_acquire_privileges(struct uvc_fh *handle) /* Check if the device already has a privileged handle. */ mutex_lock(&uvc_driver.open_mutex); - if (atomic_inc_return(&handle->device->active) != 1) { - atomic_dec(&handle->device->active); + if (atomic_inc_return(&handle->stream->active) != 1) { + atomic_dec(&handle->stream->active); ret = -EBUSY; goto done; } @@ -398,7 +400,7 @@ done: static void uvc_dismiss_privileges(struct uvc_fh *handle) { if (handle->state == UVC_HANDLE_ACTIVE) - atomic_dec(&handle->device->active); + atomic_dec(&handle->stream->active); handle->state = UVC_HANDLE_PASSIVE; } @@ -414,21 +416,21 @@ static int uvc_has_privileges(struct uvc_fh *handle) static int uvc_v4l2_open(struct file *file) { - struct uvc_video_device *video; + struct uvc_streaming *stream; struct uvc_fh *handle; int ret = 0; uvc_trace(UVC_TRACE_CALLS, "uvc_v4l2_open\n"); mutex_lock(&uvc_driver.open_mutex); - video = video_drvdata(file); + stream = video_drvdata(file); - if (video->dev->state & UVC_DEV_DISCONNECTED) { + if (stream->dev->state & UVC_DEV_DISCONNECTED) { ret = -ENODEV; goto done; } #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19) - ret = usb_autopm_get_interface(video->dev->intf); + ret = usb_autopm_get_interface(stream->dev->intf); if (ret < 0) goto done; #endif @@ -437,28 +439,30 @@ static int uvc_v4l2_open(struct file *file) handle = kzalloc(sizeof *handle, GFP_KERNEL); if (handle == NULL) { #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19) - usb_autopm_put_interface(video->dev->intf); + usb_autopm_put_interface(stream->dev->intf); #endif ret = -ENOMEM; goto done; } - if (atomic_inc_return(&video->dev->users) == 1) { - if ((ret = uvc_status_start(video->dev)) < 0) { + if (atomic_inc_return(&stream->dev->users) == 1) { + ret = uvc_status_start(stream->dev); + if (ret < 0) { #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19) - usb_autopm_put_interface(video->dev->intf); + usb_autopm_put_interface(stream->dev->intf); #endif - atomic_dec(&video->dev->users); + atomic_dec(&stream->dev->users); kfree(handle); goto done; } } - handle->device = video; + handle->video = &stream->dev->video; + handle->stream = stream; handle->state = UVC_HANDLE_PASSIVE; file->private_data = handle; - kref_get(&video->dev->kref); + kref_get(&stream->dev->kref); done: mutex_unlock(&uvc_driver.open_mutex); @@ -467,20 +471,20 @@ done: static int uvc_v4l2_release(struct file *file) { - struct uvc_video_device *video = video_drvdata(file); struct uvc_fh *handle = (struct uvc_fh *)file->private_data; + struct uvc_streaming *stream = handle->stream; uvc_trace(UVC_TRACE_CALLS, "uvc_v4l2_release\n"); /* Only free resources if this is a privileged handle. */ if (uvc_has_privileges(handle)) { - uvc_video_enable(video, 0); + uvc_video_enable(stream, 0); - mutex_lock(&video->queue.mutex); - if (uvc_free_buffers(&video->queue) < 0) + mutex_lock(&stream->queue.mutex); + if (uvc_free_buffers(&stream->queue) < 0) uvc_printk(KERN_ERR, "uvc_v4l2_release: Unable to " "free buffers.\n"); - mutex_unlock(&video->queue.mutex); + mutex_unlock(&stream->queue.mutex); } /* Release the file handle. */ @@ -488,21 +492,22 @@ 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 (atomic_dec_return(&stream->dev->users) == 0) + uvc_status_stop(stream->dev); #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19) - usb_autopm_put_interface(video->dev->intf); + usb_autopm_put_interface(stream->dev->intf); #endif - kref_put(&video->dev->kref, uvc_delete); + kref_put(&stream->dev->kref, uvc_delete); return 0; } static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) { struct video_device *vdev = video_devdata(file); - struct uvc_video_device *video = video_get_drvdata(vdev); struct uvc_fh *handle = (struct uvc_fh *)file->private_data; + struct uvc_video_device *video = handle->video; + struct uvc_streaming *stream = handle->stream; long ret = 0; switch (cmd) { @@ -514,10 +519,10 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) memset(cap, 0, sizeof *cap); strlcpy(cap->driver, "uvcvideo", sizeof cap->driver); strlcpy(cap->card, vdev->name, sizeof cap->card); - usb_make_path(video->dev->udev, + usb_make_path(stream->dev->udev, cap->bus_info, sizeof(cap->bus_info)); cap->version = DRIVER_VERSION_NUMBER; - if (video->streaming->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) + if (stream->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING; else @@ -711,15 +716,15 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) enum v4l2_buf_type type = fmt->type; __u32 index = fmt->index; - if (fmt->type != video->streaming->type || - fmt->index >= video->streaming->nformats) + if (fmt->type != stream->type || + fmt->index >= stream->nformats) return -EINVAL; memset(fmt, 0, sizeof(*fmt)); fmt->index = index; fmt->type = type; - format = &video->streaming->format[fmt->index]; + format = &stream->format[fmt->index]; fmt->flags = 0; if (format->flags & UVC_FMT_FLAG_COMPRESSED) fmt->flags |= V4L2_FMT_FLAG_COMPRESSED; @@ -737,17 +742,17 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) if ((ret = uvc_acquire_privileges(handle)) < 0) return ret; - return uvc_v4l2_try_format(video, arg, &probe, NULL, NULL); + return uvc_v4l2_try_format(stream, arg, &probe, NULL, NULL); } case VIDIOC_S_FMT: if ((ret = uvc_acquire_privileges(handle)) < 0) return ret; - return uvc_v4l2_set_format(video, arg); + return uvc_v4l2_set_format(stream, arg); case VIDIOC_G_FMT: - return uvc_v4l2_get_format(video, arg); + return uvc_v4l2_get_format(stream, arg); /* Frame size enumeration */ case VIDIOC_ENUM_FRAMESIZES: @@ -758,10 +763,10 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) int i; /* Look for the given pixel format */ - for (i = 0; i < video->streaming->nformats; i++) { - if (video->streaming->format[i].fcc == + for (i = 0; i < stream->nformats; i++) { + if (stream->format[i].fcc == fsize->pixel_format) { - format = &video->streaming->format[i]; + format = &stream->format[i]; break; } } @@ -787,10 +792,10 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) int i; /* Look for the given pixel format and frame size */ - for (i = 0; i < video->streaming->nformats; i++) { - if (video->streaming->format[i].fcc == + for (i = 0; i < stream->nformats; i++) { + if (stream->format[i].fcc == fival->pixel_format) { - format = &video->streaming->format[i]; + format = &stream->format[i]; break; } } @@ -840,21 +845,21 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) /* Get & Set streaming parameters */ case VIDIOC_G_PARM: - return uvc_v4l2_get_streamparm(video, arg); + return uvc_v4l2_get_streamparm(stream, arg); case VIDIOC_S_PARM: if ((ret = uvc_acquire_privileges(handle)) < 0) return ret; - return uvc_v4l2_set_streamparm(video, arg); + return uvc_v4l2_set_streamparm(stream, arg); /* Cropping and scaling */ case VIDIOC_CROPCAP: { struct v4l2_cropcap *ccap = arg; - struct uvc_frame *frame = video->streaming->cur_frame; + struct uvc_frame *frame = stream->cur_frame; - if (ccap->type != video->streaming->type) + if (ccap->type != stream->type) return -EINVAL; ccap->bounds.left = 0; @@ -878,16 +883,16 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) { struct v4l2_requestbuffers *rb = arg; unsigned int bufsize = - video->streaming->ctrl.dwMaxVideoFrameSize; + stream->ctrl.dwMaxVideoFrameSize; - if (rb->type != video->streaming->type || + if (rb->type != stream->type || rb->memory != V4L2_MEMORY_MMAP) return -EINVAL; if ((ret = uvc_acquire_privileges(handle)) < 0) return ret; - ret = uvc_alloc_buffers(&video->queue, rb->count, bufsize); + ret = uvc_alloc_buffers(&stream->queue, rb->count, bufsize); if (ret < 0) return ret; @@ -900,39 +905,40 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) { struct v4l2_buffer *buf = arg; - if (buf->type != video->streaming->type) + if (buf->type != stream->type) return -EINVAL; if (!uvc_has_privileges(handle)) return -EBUSY; - return uvc_query_buffer(&video->queue, buf); + return uvc_query_buffer(&stream->queue, buf); } case VIDIOC_QBUF: if (!uvc_has_privileges(handle)) return -EBUSY; - return uvc_queue_buffer(&video->queue, arg); + return uvc_queue_buffer(&stream->queue, arg); case VIDIOC_DQBUF: if (!uvc_has_privileges(handle)) return -EBUSY; - return uvc_dequeue_buffer(&video->queue, arg, + return uvc_dequeue_buffer(&stream->queue, arg, file->f_flags & O_NONBLOCK); case VIDIOC_STREAMON: { int *type = arg; - if (*type != video->streaming->type) + if (*type != stream->type) return -EINVAL; if (!uvc_has_privileges(handle)) return -EBUSY; - if ((ret = uvc_video_enable(video, 1)) < 0) + ret = uvc_video_enable(stream, 1); + if (ret < 0) return ret; break; } @@ -941,13 +947,13 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) { int *type = arg; - if (*type != video->streaming->type) + if (*type != stream->type) return -EINVAL; if (!uvc_has_privileges(handle)) return -EBUSY; - return uvc_video_enable(video, 0); + return uvc_video_enable(stream, 0); } /* Analog video standards make no sense for digital cameras. */ @@ -1078,7 +1084,9 @@ static struct vm_operations_struct uvc_vm_ops = { static int uvc_v4l2_mmap(struct file *file, struct vm_area_struct *vma) { - struct uvc_video_device *video = video_drvdata(file); + struct uvc_fh *handle = (struct uvc_fh *)file->private_data; + struct uvc_streaming *stream = handle->stream; + struct uvc_video_queue *queue = &stream->queue; struct uvc_buffer *uninitialized_var(buffer); struct page *page; unsigned long addr, start, size; @@ -1090,15 +1098,15 @@ static int uvc_v4l2_mmap(struct file *file, struct vm_area_struct *vma) start = vma->vm_start; size = vma->vm_end - vma->vm_start; - mutex_lock(&video->queue.mutex); + mutex_lock(&queue->mutex); - for (i = 0; i < video->queue.count; ++i) { - buffer = &video->queue.buffer[i]; + for (i = 0; i < queue->count; ++i) { + buffer = &queue->buffer[i]; if ((buffer->buf.m.offset >> PAGE_SHIFT) == vma->vm_pgoff) break; } - if (i == video->queue.count || size != video->queue.buf_size) { + if (i == queue->count || size != queue->buf_size) { ret = -EINVAL; goto done; } @@ -1109,7 +1117,7 @@ static int uvc_v4l2_mmap(struct file *file, struct vm_area_struct *vma) */ vma->vm_flags |= VM_IO; - addr = (unsigned long)video->queue.mem + buffer->buf.m.offset; + addr = (unsigned long)queue->mem + buffer->buf.m.offset; while (size > 0) { page = vmalloc_to_page((void *)addr); if ((ret = vm_insert_page(vma, start, page)) < 0) @@ -1125,17 +1133,18 @@ static int uvc_v4l2_mmap(struct file *file, struct vm_area_struct *vma) uvc_vm_open(vma); done: - mutex_unlock(&video->queue.mutex); + mutex_unlock(&queue->mutex); return ret; } static unsigned int uvc_v4l2_poll(struct file *file, poll_table *wait) { - struct uvc_video_device *video = video_drvdata(file); + struct uvc_fh *handle = (struct uvc_fh *)file->private_data; + struct uvc_streaming *stream = handle->stream; uvc_trace(UVC_TRACE_CALLS, "uvc_v4l2_poll\n"); - return uvc_queue_poll(&video->queue, file, wait); + return uvc_queue_poll(&stream->queue, file, wait); } const struct v4l2_file_operations uvc_fops = { diff --git a/linux/drivers/media/video/uvc/uvc_video.c b/linux/drivers/media/video/uvc/uvc_video.c index f4f4e1bb3..38cb7a367 100644 --- a/linux/drivers/media/video/uvc/uvc_video.c +++ b/linux/drivers/media/video/uvc/uvc_video.c @@ -61,7 +61,7 @@ int uvc_query_ctrl(struct uvc_device *dev, __u8 query, __u8 unit, return 0; } -static void uvc_fixup_video_ctrl(struct uvc_video_device *video, +static void uvc_fixup_video_ctrl(struct uvc_streaming *stream, struct uvc_streaming_control *ctrl) { struct uvc_format *format; @@ -69,10 +69,10 @@ static void uvc_fixup_video_ctrl(struct uvc_video_device *video, unsigned int i; if (ctrl->bFormatIndex <= 0 || - ctrl->bFormatIndex > video->streaming->nformats) + ctrl->bFormatIndex > stream->nformats) return; - format = &video->streaming->format[ctrl->bFormatIndex - 1]; + format = &stream->format[ctrl->bFormatIndex - 1]; for (i = 0; i < format->nframes; ++i) { if (format->frame[i].bFrameIndex == ctrl->bFrameIndex) { @@ -86,12 +86,12 @@ static void uvc_fixup_video_ctrl(struct uvc_video_device *video, if (!(format->flags & UVC_FMT_FLAG_COMPRESSED) || (ctrl->dwMaxVideoFrameSize == 0 && - video->dev->uvc_version < 0x0110)) + stream->dev->uvc_version < 0x0110)) ctrl->dwMaxVideoFrameSize = frame->dwMaxVideoFrameBufferSize; - if (video->dev->quirks & UVC_QUIRK_FIX_BANDWIDTH && - video->streaming->intf->num_altsetting > 1) { + if (stream->dev->quirks & UVC_QUIRK_FIX_BANDWIDTH && + stream->intf->num_altsetting > 1) { u32 interval; u32 bandwidth; @@ -108,7 +108,7 @@ static void uvc_fixup_video_ctrl(struct uvc_video_device *video, bandwidth = frame->wWidth * frame->wHeight / 8 * format->bpp; bandwidth *= 10000000 / interval + 1; bandwidth /= 1000; - if (video->dev->udev->speed == USB_SPEED_HIGH) + if (stream->dev->udev->speed == USB_SPEED_HIGH) bandwidth /= 8; bandwidth += 12; @@ -116,14 +116,14 @@ static void uvc_fixup_video_ctrl(struct uvc_video_device *video, } } -static int uvc_get_video_ctrl(struct uvc_video_device *video, +static int uvc_get_video_ctrl(struct uvc_streaming *stream, struct uvc_streaming_control *ctrl, int probe, __u8 query) { __u8 *data; __u16 size; int ret; - size = video->dev->uvc_version >= 0x0110 ? 34 : 26; + size = stream->dev->uvc_version >= 0x0110 ? 34 : 26; data = kmalloc(size, GFP_KERNEL); if (data == NULL) return -ENOMEM; @@ -131,7 +131,7 @@ static int uvc_get_video_ctrl(struct uvc_video_device *video, if ((video->dev->quirks & UVC_QUIRK_PROBE_DEF) && query == UVC_GET_DEF) return -EIO; - ret = __uvc_query_ctrl(video->dev, query, 0, video->streaming->intfnum, + ret = __uvc_query_ctrl(stream->dev, query, 0, stream->intfnum, probe ? UVC_VS_PROBE_CONTROL : UVC_VS_COMMIT_CONTROL, data, size, UVC_CTRL_STREAMING_TIMEOUT); @@ -140,7 +140,7 @@ static int uvc_get_video_ctrl(struct uvc_video_device *video, * answer a GET_MIN or GET_MAX request with the wCompQuality * field only. */ - uvc_warn_once(video->dev, UVC_WARN_MINMAX, "UVC non " + uvc_warn_once(stream->dev, UVC_WARN_MINMAX, "UVC non " "compliance - GET_MIN/MAX(PROBE) incorrectly " "supported. Enabling workaround.\n"); memset(ctrl, 0, sizeof ctrl); @@ -152,7 +152,7 @@ static int uvc_get_video_ctrl(struct uvc_video_device *video, * video probe control. Warn once and return, the caller will * fall back to GET_CUR. */ - uvc_warn_once(video->dev, UVC_WARN_PROBE_DEF, "UVC non " + uvc_warn_once(stream->dev, UVC_WARN_PROBE_DEF, "UVC non " "compliance - GET_DEF(PROBE) not supported. " "Enabling workaround.\n"); ret = -EIO; @@ -184,7 +184,7 @@ static int uvc_get_video_ctrl(struct uvc_video_device *video, ctrl->bMinVersion = data[32]; ctrl->bMaxVersion = data[33]; } else { - ctrl->dwClockFrequency = video->dev->clock_frequency; + ctrl->dwClockFrequency = stream->dev->clock_frequency; ctrl->bmFramingInfo = 0; ctrl->bPreferedVersion = 0; ctrl->bMinVersion = 0; @@ -195,7 +195,7 @@ static int uvc_get_video_ctrl(struct uvc_video_device *video, * dwMaxPayloadTransferSize fields. Try to get the value from the * format and frame descriptors. */ - uvc_fixup_video_ctrl(video, ctrl); + uvc_fixup_video_ctrl(stream, ctrl); ret = 0; out: @@ -203,14 +203,14 @@ out: return ret; } -static int uvc_set_video_ctrl(struct uvc_video_device *video, +static int uvc_set_video_ctrl(struct uvc_streaming *stream, struct uvc_streaming_control *ctrl, int probe) { __u8 *data; __u16 size; int ret; - size = video->dev->uvc_version >= 0x0110 ? 34 : 26; + size = stream->dev->uvc_version >= 0x0110 ? 34 : 26; data = kzalloc(size, GFP_KERNEL); if (data == NULL) return -ENOMEM; @@ -235,8 +235,7 @@ static int uvc_set_video_ctrl(struct uvc_video_device *video, data[33] = ctrl->bMaxVersion; } - ret = __uvc_query_ctrl(video->dev, UVC_SET_CUR, 0, - video->streaming->intfnum, + ret = __uvc_query_ctrl(stream->dev, UVC_SET_CUR, 0, stream->intfnum, probe ? UVC_VS_PROBE_CONTROL : UVC_VS_COMMIT_CONTROL, data, size, UVC_CTRL_STREAMING_TIMEOUT); if (ret != size) { @@ -250,7 +249,7 @@ static int uvc_set_video_ctrl(struct uvc_video_device *video, return ret; } -int uvc_probe_video(struct uvc_video_device *video, +int uvc_probe_video(struct uvc_streaming *stream, struct uvc_streaming_control *probe) { struct uvc_streaming_control probe_min, probe_max; @@ -258,7 +257,7 @@ int uvc_probe_video(struct uvc_video_device *video, unsigned int i; int ret; - mutex_lock(&video->streaming->mutex); + mutex_lock(&stream->mutex); /* Perform probing. The device should adjust the requested values * according to its capabilities. However, some devices, namely the @@ -267,15 +266,16 @@ int uvc_probe_video(struct uvc_video_device *video, * that reason, if the needed bandwidth exceeds the maximum available * bandwidth, try to lower the quality. */ - if ((ret = uvc_set_video_ctrl(video, probe, 1)) < 0) + ret = uvc_set_video_ctrl(stream, probe, 1); + if (ret < 0) goto done; /* Get the minimum and maximum values for compression settings. */ - if (!(video->dev->quirks & UVC_QUIRK_PROBE_MINMAX)) { - ret = uvc_get_video_ctrl(video, &probe_min, 1, UVC_GET_MIN); + if (!(stream->dev->quirks & UVC_QUIRK_PROBE_MINMAX)) { + ret = uvc_get_video_ctrl(stream, &probe_min, 1, UVC_GET_MIN); if (ret < 0) goto done; - ret = uvc_get_video_ctrl(video, &probe_max, 1, UVC_GET_MAX); + ret = uvc_get_video_ctrl(stream, &probe_max, 1, UVC_GET_MAX); if (ret < 0) goto done; @@ -283,21 +283,21 @@ int uvc_probe_video(struct uvc_video_device *video, } for (i = 0; i < 2; ++i) { - ret = uvc_set_video_ctrl(video, probe, 1); + ret = uvc_set_video_ctrl(stream, probe, 1); if (ret < 0) goto done; - ret = uvc_get_video_ctrl(video, probe, 1, UVC_GET_CUR); + ret = uvc_get_video_ctrl(stream, probe, 1, UVC_GET_CUR); if (ret < 0) goto done; - if (video->streaming->intf->num_altsetting == 1) + if (stream->intf->num_altsetting == 1) break; bandwidth = probe->dwMaxPayloadTransferSize; - if (bandwidth <= video->streaming->maxpsize) + if (bandwidth <= stream->maxpsize) break; - if (video->dev->quirks & UVC_QUIRK_PROBE_MINMAX) { + if (stream->dev->quirks & UVC_QUIRK_PROBE_MINMAX) { ret = -ENOSPC; goto done; } @@ -310,14 +310,14 @@ int uvc_probe_video(struct uvc_video_device *video, } done: - mutex_unlock(&video->streaming->mutex); + mutex_unlock(&stream->mutex); return ret; } -int uvc_commit_video(struct uvc_video_device *video, +int uvc_commit_video(struct uvc_streaming *stream, struct uvc_streaming_control *probe) { - return uvc_set_video_ctrl(video, probe, 0); + return uvc_set_video_ctrl(stream, probe, 0); } /* ------------------------------------------------------------------------ @@ -369,7 +369,7 @@ int uvc_commit_video(struct uvc_video_device *video, * to be called with a NULL buf parameter. uvc_video_decode_data and * uvc_video_decode_end will never be called with a NULL buffer. */ -static int uvc_video_decode_start(struct uvc_video_device *video, +static int uvc_video_decode_start(struct uvc_streaming *stream, struct uvc_buffer *buf, const __u8 *data, int len) { __u8 fid; @@ -395,25 +395,25 @@ static int uvc_video_decode_start(struct uvc_video_device *video, * NULL. */ if (buf == NULL) { - video->last_fid = fid; + stream->last_fid = fid; return -ENODATA; } /* Synchronize to the input stream by waiting for the FID bit to be * toggled when the the buffer state is not UVC_BUF_STATE_ACTIVE. - * video->last_fid is initialized to -1, so the first isochronous + * stream->last_fid is initialized to -1, so the first isochronous * frame will always be in sync. * - * If the device doesn't toggle the FID bit, invert video->last_fid + * If the device doesn't toggle the FID bit, invert stream->last_fid * when the EOF bit is set to force synchronisation on the next packet. */ if (buf->state != UVC_BUF_STATE_ACTIVE) { - if (fid == video->last_fid) { + if (fid == stream->last_fid) { uvc_trace(UVC_TRACE_FRAME, "Dropping payload (out of " "sync).\n"); - if ((video->dev->quirks & UVC_QUIRK_STREAM_NO_FID) && + if ((stream->dev->quirks & UVC_QUIRK_STREAM_NO_FID) && (data[1] & UVC_STREAM_EOF)) - video->last_fid ^= UVC_STREAM_FID; + stream->last_fid ^= UVC_STREAM_FID; return -ENODATA; } @@ -428,7 +428,7 @@ static int uvc_video_decode_start(struct uvc_video_device *video, * last payload can be lost anyway). We thus must check if the FID has * been toggled. * - * video->last_fid is initialized to -1, so the first isochronous + * stream->last_fid is initialized to -1, so the first isochronous * frame will never trigger an end of frame detection. * * Empty buffers (bytesused == 0) don't trigger end of frame detection @@ -436,22 +436,22 @@ static int uvc_video_decode_start(struct uvc_video_device *video, * avoids detecting end of frame conditions at FID toggling if the * previous payload had the EOF bit set. */ - if (fid != video->last_fid && buf->buf.bytesused != 0) { + if (fid != stream->last_fid && buf->buf.bytesused != 0) { uvc_trace(UVC_TRACE_FRAME, "Frame complete (FID bit " "toggled).\n"); buf->state = UVC_BUF_STATE_DONE; return -EAGAIN; } - video->last_fid = fid; + stream->last_fid = fid; return data[0]; } -static void uvc_video_decode_data(struct uvc_video_device *video, +static void uvc_video_decode_data(struct uvc_streaming *stream, struct uvc_buffer *buf, const __u8 *data, int len) { - struct uvc_video_queue *queue = &video->queue; + struct uvc_video_queue *queue = &stream->queue; unsigned int maxlen, nbytes; void *mem; @@ -472,7 +472,7 @@ static void uvc_video_decode_data(struct uvc_video_device *video, } } -static void uvc_video_decode_end(struct uvc_video_device *video, +static void uvc_video_decode_end(struct uvc_streaming *stream, struct uvc_buffer *buf, const __u8 *data, int len) { /* Mark the buffer as done if the EOF marker is set. */ @@ -481,8 +481,8 @@ static void uvc_video_decode_end(struct uvc_video_device *video, if (data[0] == len) uvc_trace(UVC_TRACE_FRAME, "EOF in empty payload.\n"); buf->state = UVC_BUF_STATE_DONE; - if (video->dev->quirks & UVC_QUIRK_STREAM_NO_FID) - video->last_fid ^= UVC_STREAM_FID; + if (stream->dev->quirks & UVC_QUIRK_STREAM_NO_FID) + stream->last_fid ^= UVC_STREAM_FID; } } @@ -497,26 +497,26 @@ static void uvc_video_decode_end(struct uvc_video_device *video, * uvc_video_encode_data is called for every URB and copies the data from the * video buffer to the transfer buffer. */ -static int uvc_video_encode_header(struct uvc_video_device *video, +static int uvc_video_encode_header(struct uvc_streaming *stream, struct uvc_buffer *buf, __u8 *data, int len) { data[0] = 2; /* Header length */ data[1] = UVC_STREAM_EOH | UVC_STREAM_EOF - | (video->last_fid & UVC_STREAM_FID); + | (stream->last_fid & UVC_STREAM_FID); return 2; } -static int uvc_video_encode_data(struct uvc_video_device *video, +static int uvc_video_encode_data(struct uvc_streaming *stream, struct uvc_buffer *buf, __u8 *data, int len) { - struct uvc_video_queue *queue = &video->queue; + struct uvc_video_queue *queue = &stream->queue; unsigned int nbytes; void *mem; /* Copy video data to the URB buffer. */ mem = queue->mem + buf->buf.m.offset + queue->buf_used; nbytes = min((unsigned int)len, buf->buf.bytesused - queue->buf_used); - nbytes = min(video->bulk.max_payload_size - video->bulk.payload_size, + nbytes = min(stream->bulk.max_payload_size - stream->bulk.payload_size, nbytes); memcpy(data, mem, nbytes); @@ -532,8 +532,8 @@ static int uvc_video_encode_data(struct uvc_video_device *video, /* * Completion handler for video URBs. */ -static void uvc_video_decode_isoc(struct urb *urb, - struct uvc_video_device *video, struct uvc_buffer *buf) +static void uvc_video_decode_isoc(struct urb *urb, struct uvc_streaming *stream, + struct uvc_buffer *buf) { u8 *mem; int ret, i; @@ -548,31 +548,32 @@ static void uvc_video_decode_isoc(struct urb *urb, /* Decode the payload header. */ mem = urb->transfer_buffer + urb->iso_frame_desc[i].offset; do { - ret = uvc_video_decode_start(video, buf, mem, + ret = uvc_video_decode_start(stream, buf, mem, urb->iso_frame_desc[i].actual_length); if (ret == -EAGAIN) - buf = uvc_queue_next_buffer(&video->queue, buf); + buf = uvc_queue_next_buffer(&stream->queue, + buf); } while (ret == -EAGAIN); if (ret < 0) continue; /* Decode the payload data. */ - uvc_video_decode_data(video, buf, mem + ret, + uvc_video_decode_data(stream, buf, mem + ret, urb->iso_frame_desc[i].actual_length - ret); /* Process the header again. */ - uvc_video_decode_end(video, buf, mem, + uvc_video_decode_end(stream, buf, mem, urb->iso_frame_desc[i].actual_length); if (buf->state == UVC_BUF_STATE_DONE || buf->state == UVC_BUF_STATE_ERROR) - buf = uvc_queue_next_buffer(&video->queue, buf); + buf = uvc_queue_next_buffer(&stream->queue, buf); } } -static void uvc_video_decode_bulk(struct urb *urb, - struct uvc_video_device *video, struct uvc_buffer *buf) +static void uvc_video_decode_bulk(struct urb *urb, struct uvc_streaming *stream, + struct uvc_buffer *buf) { u8 *mem; int len, ret; @@ -582,24 +583,25 @@ static void uvc_video_decode_bulk(struct urb *urb, mem = urb->transfer_buffer; len = urb->actual_length; - video->bulk.payload_size += len; + stream->bulk.payload_size += len; /* If the URB is the first of its payload, decode and save the * header. */ - if (video->bulk.header_size == 0 && !video->bulk.skip_payload) { + if (stream->bulk.header_size == 0 && !stream->bulk.skip_payload) { do { - ret = uvc_video_decode_start(video, buf, mem, len); + ret = uvc_video_decode_start(stream, buf, mem, len); if (ret == -EAGAIN) - buf = uvc_queue_next_buffer(&video->queue, buf); + buf = uvc_queue_next_buffer(&stream->queue, + buf); } while (ret == -EAGAIN); /* If an error occured skip the rest of the payload. */ if (ret < 0 || buf == NULL) { - video->bulk.skip_payload = 1; + stream->bulk.skip_payload = 1; } else { - memcpy(video->bulk.header, mem, ret); - video->bulk.header_size = ret; + memcpy(stream->bulk.header, mem, ret); + stream->bulk.header_size = ret; mem += ret; len -= ret; @@ -612,33 +614,34 @@ static void uvc_video_decode_bulk(struct urb *urb, */ /* Process video data. */ - if (!video->bulk.skip_payload && buf != NULL) - uvc_video_decode_data(video, buf, mem, len); + if (!stream->bulk.skip_payload && buf != NULL) + uvc_video_decode_data(stream, buf, mem, len); /* Detect the payload end by a URB smaller than the maximum size (or * a payload size equal to the maximum) and process the header again. */ if (urb->actual_length < urb->transfer_buffer_length || - video->bulk.payload_size >= video->bulk.max_payload_size) { - if (!video->bulk.skip_payload && buf != NULL) { - uvc_video_decode_end(video, buf, video->bulk.header, - video->bulk.payload_size); + stream->bulk.payload_size >= stream->bulk.max_payload_size) { + if (!stream->bulk.skip_payload && buf != NULL) { + uvc_video_decode_end(stream, buf, stream->bulk.header, + stream->bulk.payload_size); if (buf->state == UVC_BUF_STATE_DONE || buf->state == UVC_BUF_STATE_ERROR) - buf = uvc_queue_next_buffer(&video->queue, buf); + buf = uvc_queue_next_buffer(&stream->queue, + buf); } - video->bulk.header_size = 0; - video->bulk.skip_payload = 0; - video->bulk.payload_size = 0; + stream->bulk.header_size = 0; + stream->bulk.skip_payload = 0; + stream->bulk.payload_size = 0; } } -static void uvc_video_encode_bulk(struct urb *urb, - struct uvc_video_device *video, struct uvc_buffer *buf) +static void uvc_video_encode_bulk(struct urb *urb, struct uvc_streaming *stream, + struct uvc_buffer *buf) { u8 *mem = urb->transfer_buffer; - int len = video->urb_size, ret; + int len = stream->urb_size, ret; if (buf == NULL) { urb->transfer_buffer_length = 0; @@ -646,34 +649,34 @@ static void uvc_video_encode_bulk(struct urb *urb, } /* If the URB is the first of its payload, add the header. */ - if (video->bulk.header_size == 0) { - ret = uvc_video_encode_header(video, buf, mem, len); - video->bulk.header_size = ret; - video->bulk.payload_size += ret; + if (stream->bulk.header_size == 0) { + ret = uvc_video_encode_header(stream, buf, mem, len); + stream->bulk.header_size = ret; + stream->bulk.payload_size += ret; mem += ret; len -= ret; } /* Process video data. */ - ret = uvc_video_encode_data(video, buf, mem, len); + ret = uvc_video_encode_data(stream, buf, mem, len); - video->bulk.payload_size += ret; + stream->bulk.payload_size += ret; len -= ret; - if (buf->buf.bytesused == video->queue.buf_used || - video->bulk.payload_size == video->bulk.max_payload_size) { - if (buf->buf.bytesused == video->queue.buf_used) { - video->queue.buf_used = 0; + if (buf->buf.bytesused == stream->queue.buf_used || + stream->bulk.payload_size == stream->bulk.max_payload_size) { + if (buf->buf.bytesused == stream->queue.buf_used) { + stream->queue.buf_used = 0; buf->state = UVC_BUF_STATE_DONE; - uvc_queue_next_buffer(&video->queue, buf); - video->last_fid ^= UVC_STREAM_FID; + uvc_queue_next_buffer(&stream->queue, buf); + stream->last_fid ^= UVC_STREAM_FID; } - video->bulk.header_size = 0; - video->bulk.payload_size = 0; + stream->bulk.header_size = 0; + stream->bulk.payload_size = 0; } - urb->transfer_buffer_length = video->urb_size - len; + urb->transfer_buffer_length = stream->urb_size - len; } #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19) @@ -682,8 +685,8 @@ static void uvc_video_complete(struct urb *urb, struct pt_regs *regs) static void uvc_video_complete(struct urb *urb) #endif { - struct uvc_video_device *video = urb->context; - struct uvc_video_queue *queue = &video->queue; + struct uvc_streaming *stream = urb->context; + struct uvc_video_queue *queue = &stream->queue; struct uvc_buffer *buf = NULL; unsigned long flags; int ret; @@ -697,7 +700,7 @@ static void uvc_video_complete(struct urb *urb) "completion handler.\n", urb->status); case -ENOENT: /* usb_kill_urb() called. */ - if (video->frozen) + if (stream->frozen) return; case -ECONNRESET: /* usb_unlink_urb() called. */ @@ -712,7 +715,7 @@ static void uvc_video_complete(struct urb *urb) queue); spin_unlock_irqrestore(&queue->irqlock, flags); - video->decode(urb, video, buf); + stream->decode(urb, stream, buf); if ((ret = usb_submit_urb(urb, GFP_ATOMIC)) < 0) { uvc_printk(KERN_ERR, "Failed to resubmit video URB (%d).\n", @@ -723,19 +726,19 @@ static void uvc_video_complete(struct urb *urb) /* * Free transfer buffers. */ -static void uvc_free_urb_buffers(struct uvc_video_device *video) +static void uvc_free_urb_buffers(struct uvc_streaming *stream) { unsigned int i; for (i = 0; i < UVC_URBS; ++i) { - if (video->urb_buffer[i]) { - usb_buffer_free(video->dev->udev, video->urb_size, - video->urb_buffer[i], video->urb_dma[i]); - video->urb_buffer[i] = NULL; + if (stream->urb_buffer[i]) { + usb_buffer_free(stream->dev->udev, stream->urb_size, + stream->urb_buffer[i], stream->urb_dma[i]); + stream->urb_buffer[i] = NULL; } } - video->urb_size = 0; + stream->urb_size = 0; } /* @@ -749,15 +752,15 @@ static void uvc_free_urb_buffers(struct uvc_video_device *video) * * Return the number of allocated packets on success or 0 when out of memory. */ -static int uvc_alloc_urb_buffers(struct uvc_video_device *video, +static int uvc_alloc_urb_buffers(struct uvc_streaming *stream, unsigned int size, unsigned int psize, gfp_t gfp_flags) { unsigned int npackets; unsigned int i; /* Buffers are already allocated, bail out. */ - if (video->urb_size) - return video->urb_size / psize; + if (stream->urb_size) + return stream->urb_size / psize; /* Compute the number of packets. Bulk endpoints might transfer UVC * payloads accross multiple URBs. @@ -769,17 +772,17 @@ static int uvc_alloc_urb_buffers(struct uvc_video_device *video, /* Retry allocations until one succeed. */ for (; npackets > 1; npackets /= 2) { for (i = 0; i < UVC_URBS; ++i) { - video->urb_buffer[i] = usb_buffer_alloc( - video->dev->udev, psize * npackets, - gfp_flags | __GFP_NOWARN, &video->urb_dma[i]); - if (!video->urb_buffer[i]) { - uvc_free_urb_buffers(video); + stream->urb_buffer[i] = usb_buffer_alloc( + stream->dev->udev, psize * npackets, + gfp_flags | __GFP_NOWARN, &stream->urb_dma[i]); + if (!stream->urb_buffer[i]) { + uvc_free_urb_buffers(stream); break; } } if (i == UVC_URBS) { - video->urb_size = psize * npackets; + stream->urb_size = psize * npackets; return npackets; } } @@ -790,29 +793,30 @@ static int uvc_alloc_urb_buffers(struct uvc_video_device *video, /* * Uninitialize isochronous/bulk URBs and free transfer buffers. */ -static void uvc_uninit_video(struct uvc_video_device *video, int free_buffers) +static void uvc_uninit_video(struct uvc_streaming *stream, int free_buffers) { struct urb *urb; unsigned int i; for (i = 0; i < UVC_URBS; ++i) { - if ((urb = video->urb[i]) == NULL) + urb = stream->urb[i]; + if (urb == NULL) continue; usb_kill_urb(urb); usb_free_urb(urb); - video->urb[i] = NULL; + stream->urb[i] = NULL; } if (free_buffers) - uvc_free_urb_buffers(video); + uvc_free_urb_buffers(stream); } /* * Initialize isochronous URBs and allocate transfer buffers. The packet size * is given by the endpoint. */ -static int uvc_init_video_isoc(struct uvc_video_device *video, +static int uvc_init_video_isoc(struct uvc_streaming *stream, struct usb_host_endpoint *ep, gfp_t gfp_flags) { struct urb *urb; @@ -822,9 +826,9 @@ static int uvc_init_video_isoc(struct uvc_video_device *video, psize = le16_to_cpu(ep->desc.wMaxPacketSize); psize = (psize & 0x07ff) * (1 + ((psize >> 11) & 3)); - size = video->streaming->ctrl.dwMaxVideoFrameSize; + size = stream->ctrl.dwMaxVideoFrameSize; - npackets = uvc_alloc_urb_buffers(video, size, psize, gfp_flags); + npackets = uvc_alloc_urb_buffers(stream, size, psize, gfp_flags); if (npackets == 0) return -ENOMEM; @@ -833,18 +837,18 @@ static int uvc_init_video_isoc(struct uvc_video_device *video, for (i = 0; i < UVC_URBS; ++i) { urb = usb_alloc_urb(npackets, gfp_flags); if (urb == NULL) { - uvc_uninit_video(video, 1); + uvc_uninit_video(stream, 1); return -ENOMEM; } - urb->dev = video->dev->udev; - urb->context = video; - urb->pipe = usb_rcvisocpipe(video->dev->udev, + urb->dev = stream->dev->udev; + urb->context = stream; + urb->pipe = usb_rcvisocpipe(stream->dev->udev, ep->desc.bEndpointAddress); urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP; urb->interval = ep->desc.bInterval; - urb->transfer_buffer = video->urb_buffer[i]; - urb->transfer_dma = video->urb_dma[i]; + urb->transfer_buffer = stream->urb_buffer[i]; + urb->transfer_dma = stream->urb_dma[i]; urb->complete = uvc_video_complete; urb->number_of_packets = npackets; urb->transfer_buffer_length = size; @@ -854,7 +858,7 @@ static int uvc_init_video_isoc(struct uvc_video_device *video, urb->iso_frame_desc[j].length = psize; } - video->urb[i] = urb; + stream->urb[i] = urb; } return 0; @@ -864,7 +868,7 @@ static int uvc_init_video_isoc(struct uvc_video_device *video, * Initialize bulk URBs and allocate transfer buffers. The packet size is * given by the endpoint. */ -static int uvc_init_video_bulk(struct uvc_video_device *video, +static int uvc_init_video_bulk(struct uvc_streaming *stream, struct usb_host_endpoint *ep, gfp_t gfp_flags) { struct urb *urb; @@ -873,39 +877,39 @@ static int uvc_init_video_bulk(struct uvc_video_device *video, u32 size; psize = le16_to_cpu(ep->desc.wMaxPacketSize) & 0x07ff; - size = video->streaming->ctrl.dwMaxPayloadTransferSize; - video->bulk.max_payload_size = size; + size = stream->ctrl.dwMaxPayloadTransferSize; + stream->bulk.max_payload_size = size; - npackets = uvc_alloc_urb_buffers(video, size, psize, gfp_flags); + npackets = uvc_alloc_urb_buffers(stream, size, psize, gfp_flags); if (npackets == 0) return -ENOMEM; size = npackets * psize; if (usb_endpoint_dir_in(&ep->desc)) - pipe = usb_rcvbulkpipe(video->dev->udev, + pipe = usb_rcvbulkpipe(stream->dev->udev, ep->desc.bEndpointAddress); else - pipe = usb_sndbulkpipe(video->dev->udev, + pipe = usb_sndbulkpipe(stream->dev->udev, ep->desc.bEndpointAddress); - if (video->streaming->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) + if (stream->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) size = 0; for (i = 0; i < UVC_URBS; ++i) { urb = usb_alloc_urb(0, gfp_flags); if (urb == NULL) { - uvc_uninit_video(video, 1); + uvc_uninit_video(stream, 1); return -ENOMEM; } - usb_fill_bulk_urb(urb, video->dev->udev, pipe, - video->urb_buffer[i], size, uvc_video_complete, - video); + usb_fill_bulk_urb(urb, stream->dev->udev, pipe, + stream->urb_buffer[i], size, uvc_video_complete, + stream); urb->transfer_flags = URB_NO_TRANSFER_DMA_MAP; - urb->transfer_dma = video->urb_dma[i]; + urb->transfer_dma = stream->urb_dma[i]; - video->urb[i] = urb; + stream->urb[i] = urb; } return 0; @@ -914,35 +918,35 @@ static int uvc_init_video_bulk(struct uvc_video_device *video, /* * Initialize isochronous/bulk URBs and allocate transfer buffers. */ -static int uvc_init_video(struct uvc_video_device *video, gfp_t gfp_flags) +static int uvc_init_video(struct uvc_streaming *stream, gfp_t gfp_flags) { - struct usb_interface *intf = video->streaming->intf; + struct usb_interface *intf = stream->intf; struct usb_host_interface *alts; struct usb_host_endpoint *ep = NULL; - int intfnum = video->streaming->intfnum; + int intfnum = stream->intfnum; unsigned int bandwidth, psize, i; int ret; - video->last_fid = -1; - video->bulk.header_size = 0; - video->bulk.skip_payload = 0; - video->bulk.payload_size = 0; + stream->last_fid = -1; + stream->bulk.header_size = 0; + stream->bulk.skip_payload = 0; + stream->bulk.payload_size = 0; if (intf->num_altsetting > 1) { /* Isochronous endpoint, select the alternate setting. */ - bandwidth = video->streaming->ctrl.dwMaxPayloadTransferSize; + bandwidth = stream->ctrl.dwMaxPayloadTransferSize; if (bandwidth == 0) { uvc_printk(KERN_WARNING, "device %s requested null " "bandwidth, defaulting to lowest.\n", - video->vdev->name); + stream->dev->name); bandwidth = 1; } for (i = 0; i < intf->num_altsetting; ++i) { alts = &intf->altsetting[i]; ep = uvc_find_endpoint(alts, - video->streaming->header.bEndpointAddress); + stream->header.bEndpointAddress); if (ep == NULL) continue; @@ -956,18 +960,19 @@ static int uvc_init_video(struct uvc_video_device *video, gfp_t gfp_flags) if (i >= intf->num_altsetting) return -EIO; - if ((ret = usb_set_interface(video->dev->udev, intfnum, i)) < 0) + ret = usb_set_interface(stream->dev->udev, intfnum, i); + if (ret < 0) return ret; - ret = uvc_init_video_isoc(video, ep, gfp_flags); + ret = uvc_init_video_isoc(stream, ep, gfp_flags); } else { /* Bulk endpoint, proceed to URB initialization. */ ep = uvc_find_endpoint(&intf->altsetting[0], - video->streaming->header.bEndpointAddress); + stream->header.bEndpointAddress); if (ep == NULL) return -EIO; - ret = uvc_init_video_bulk(video, ep, gfp_flags); + ret = uvc_init_video_bulk(stream, ep, gfp_flags); } if (ret < 0) @@ -975,10 +980,11 @@ static int uvc_init_video(struct uvc_video_device *video, gfp_t gfp_flags) /* Submit the URBs. */ for (i = 0; i < UVC_URBS; ++i) { - if ((ret = usb_submit_urb(video->urb[i], gfp_flags)) < 0) { + ret = usb_submit_urb(stream->urb[i], gfp_flags); + if (ret < 0) { uvc_printk(KERN_ERR, "Failed to submit URB %u " "(%d).\n", i, ret); - uvc_uninit_video(video, 1); + uvc_uninit_video(stream, 1); return ret; } } @@ -997,14 +1003,14 @@ static int uvc_init_video(struct uvc_video_device *video, gfp_t gfp_flags) * video buffers in any way. We mark the device as frozen to make sure the URB * completion handler won't try to cancel the queue when we kill the URBs. */ -int uvc_video_suspend(struct uvc_video_device *video) +int uvc_video_suspend(struct uvc_streaming *stream) { - if (!uvc_queue_streaming(&video->queue)) + if (!uvc_queue_streaming(&stream->queue)) return 0; - video->frozen = 1; - uvc_uninit_video(video, 0); - usb_set_interface(video->dev->udev, video->streaming->intfnum, 0); + stream->frozen = 1; + uvc_uninit_video(stream, 0); + usb_set_interface(stream->dev->udev, stream->intfnum, 0); return 0; } @@ -1016,22 +1022,24 @@ int uvc_video_suspend(struct uvc_video_device *video) * buffers, making sure userspace applications are notified of the problem * instead of waiting forever. */ -int uvc_video_resume(struct uvc_video_device *video) +int uvc_video_resume(struct uvc_streaming *stream) { int ret; - video->frozen = 0; + stream->frozen = 0; - if ((ret = uvc_commit_video(video, &video->streaming->ctrl)) < 0) { - uvc_queue_enable(&video->queue, 0); + ret = uvc_commit_video(stream, &stream->ctrl); + if (ret < 0) { + uvc_queue_enable(&stream->queue, 0); return ret; } - if (!uvc_queue_streaming(&video->queue)) + if (!uvc_queue_streaming(&stream->queue)) return 0; - if ((ret = uvc_init_video(video, GFP_NOIO)) < 0) - uvc_queue_enable(&video->queue, 0); + ret = uvc_init_video(stream, GFP_NOIO); + if (ret < 0) + uvc_queue_enable(&stream->queue, 0); return ret; } @@ -1050,48 +1058,53 @@ int uvc_video_resume(struct uvc_video_device *video) * * This function is called before registering the device with V4L. */ -int uvc_video_init(struct uvc_video_device *video) +int uvc_video_init(struct uvc_streaming *stream) { - struct uvc_streaming_control *probe = &video->streaming->ctrl; + struct uvc_streaming_control *probe = &stream->ctrl; struct uvc_format *format = NULL; struct uvc_frame *frame = NULL; unsigned int i; int ret; - if (video->streaming->nformats == 0) { + if (stream->nformats == 0) { uvc_printk(KERN_INFO, "No supported video formats found.\n"); return -EINVAL; } + atomic_set(&stream->active, 0); + + /* Initialize the video buffers queue. */ + uvc_queue_init(&stream->queue, stream->type); + /* Alternate setting 0 should be the default, yet the XBox Live Vision * Cam (and possibly other devices) crash or otherwise misbehave if * they don't receive a SET_INTERFACE request before any other video * control request. */ - usb_set_interface(video->dev->udev, video->streaming->intfnum, 0); + usb_set_interface(stream->dev->udev, stream->intfnum, 0); /* Set the streaming probe control with default streaming parameters * retrieved from the device. Webcams that don't suport GET_DEF * requests on the probe control will just keep their current streaming * parameters. */ - if (uvc_get_video_ctrl(video, probe, 1, UVC_GET_DEF) == 0) - uvc_set_video_ctrl(video, probe, 1); + if (uvc_get_video_ctrl(stream, probe, 1, UVC_GET_DEF) == 0) + uvc_set_video_ctrl(stream, probe, 1); /* Initialize the streaming parameters with the probe control current * value. This makes sure SET_CUR requests on the streaming commit * control will always use values retrieved from a successful GET_CUR * request on the probe control, as required by the UVC specification. */ - ret = uvc_get_video_ctrl(video, probe, 1, UVC_GET_CUR); + ret = uvc_get_video_ctrl(stream, probe, 1, UVC_GET_CUR); if (ret < 0) return ret; /* Check if the default format descriptor exists. Use the first * available format otherwise. */ - for (i = video->streaming->nformats; i > 0; --i) { - format = &video->streaming->format[i-1]; + for (i = stream->nformats; i > 0; --i) { + format = &stream->format[i-1]; if (format->index == probe->bFormatIndex) break; } @@ -1116,21 +1129,20 @@ int uvc_video_init(struct uvc_video_device *video) probe->bFormatIndex = format->index; probe->bFrameIndex = frame->bFrameIndex; - video->streaming->cur_format = format; - video->streaming->cur_frame = frame; - atomic_set(&video->active, 0); + stream->cur_format = format; + stream->cur_frame = frame; /* Select the video decoding function */ - if (video->streaming->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { - if (video->dev->quirks & UVC_QUIRK_BUILTIN_ISIGHT) - video->decode = uvc_video_decode_isight; - else if (video->streaming->intf->num_altsetting > 1) - video->decode = uvc_video_decode_isoc; + if (stream->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { + if (stream->dev->quirks & UVC_QUIRK_BUILTIN_ISIGHT) + stream->decode = uvc_video_decode_isight; + else if (stream->intf->num_altsetting > 1) + stream->decode = uvc_video_decode_isoc; else - video->decode = uvc_video_decode_bulk; + stream->decode = uvc_video_decode_bulk; } else { - if (video->streaming->intf->num_altsetting == 1) - video->decode = uvc_video_encode_bulk; + if (stream->intf->num_altsetting == 1) + stream->decode = uvc_video_encode_bulk; else { uvc_printk(KERN_INFO, "Isochronous endpoints are not " "supported for video output devices.\n"); @@ -1144,31 +1156,32 @@ int uvc_video_init(struct uvc_video_device *video) /* * Enable or disable the video stream. */ -int uvc_video_enable(struct uvc_video_device *video, int enable) +int uvc_video_enable(struct uvc_streaming *stream, int enable) { int ret; if (!enable) { - uvc_uninit_video(video, 1); - usb_set_interface(video->dev->udev, - video->streaming->intfnum, 0); - uvc_queue_enable(&video->queue, 0); + uvc_uninit_video(stream, 1); + usb_set_interface(stream->dev->udev, stream->intfnum, 0); + uvc_queue_enable(&stream->queue, 0); return 0; } - if ((video->streaming->cur_format->flags & UVC_FMT_FLAG_COMPRESSED) || + if ((stream->cur_format->flags & UVC_FMT_FLAG_COMPRESSED) || uvc_no_drop_param) - video->queue.flags &= ~UVC_QUEUE_DROP_INCOMPLETE; + stream->queue.flags &= ~UVC_QUEUE_DROP_INCOMPLETE; else - video->queue.flags |= UVC_QUEUE_DROP_INCOMPLETE; + stream->queue.flags |= UVC_QUEUE_DROP_INCOMPLETE; - if ((ret = uvc_queue_enable(&video->queue, 1)) < 0) + ret = uvc_queue_enable(&stream->queue, 1); + if (ret < 0) return ret; /* Commit the streaming parameters. */ - if ((ret = uvc_commit_video(video, &video->streaming->ctrl)) < 0) + ret = uvc_commit_video(stream, &stream->ctrl); + if (ret < 0) return ret; - return uvc_init_video(video, GFP_KERNEL); + return uvc_init_video(stream, GFP_KERNEL); } diff --git a/linux/drivers/media/video/uvc/uvcvideo.h b/linux/drivers/media/video/uvc/uvcvideo.h index e700bdc20..c385b7bde 100644 --- a/linux/drivers/media/video/uvc/uvcvideo.h +++ b/linux/drivers/media/video/uvc/uvcvideo.h @@ -362,26 +362,6 @@ struct uvc_streaming_header { __u8 bTriggerUsage; }; -struct uvc_streaming { - struct list_head list; - - struct usb_interface *intf; - int intfnum; - __u16 maxpsize; - - struct uvc_streaming_header header; - enum v4l2_buf_type type; - - unsigned int nformats; - struct uvc_format *format; - - struct uvc_streaming_control ctrl; - struct uvc_format *cur_format; - struct uvc_frame *cur_frame; - - struct mutex mutex; -}; - enum uvc_buffer_state { UVC_BUF_STATE_IDLE = 0, UVC_BUF_STATE_QUEUED = 1, @@ -423,26 +403,31 @@ struct uvc_video_queue { struct list_head irqqueue; }; -struct uvc_video_device { +struct uvc_streaming { + struct list_head list; struct uvc_device *dev; struct video_device *vdev; atomic_t active; - unsigned int frozen : 1; - struct list_head iterms; /* Input terminals */ - struct uvc_entity *oterm; /* Output terminal */ - struct uvc_entity *sterm; /* USB streaming terminal */ - struct uvc_entity *processing; - struct uvc_entity *selector; - struct list_head extensions; - struct mutex ctrl_mutex; + struct usb_interface *intf; + int intfnum; + __u16 maxpsize; - struct uvc_video_queue queue; + struct uvc_streaming_header header; + enum v4l2_buf_type type; + + unsigned int nformats; + struct uvc_format *format; - /* Video streaming object, must always be non-NULL. */ - struct uvc_streaming *streaming; + struct uvc_streaming_control ctrl; + struct uvc_format *cur_format; + struct uvc_frame *cur_frame; + + struct mutex mutex; - void (*decode) (struct urb *urb, struct uvc_video_device *video, + unsigned int frozen : 1; + struct uvc_video_queue queue; + void (*decode) (struct urb *urb, struct uvc_streaming *video, struct uvc_buffer *buf); /* Context data used by the bulk completion handler. */ @@ -462,6 +447,18 @@ struct uvc_video_device { __u8 last_fid; }; +struct uvc_video_device { + struct uvc_device *dev; + + struct list_head iterms; /* Input terminals */ + struct uvc_entity *oterm; /* Output terminal */ + struct uvc_entity *sterm; /* USB streaming terminal */ + struct uvc_entity *processing; + struct uvc_entity *selector; + struct list_head extensions; + struct mutex ctrl_mutex; +}; + enum uvc_device_state { UVC_DEV_DISCONNECTED = 1, }; @@ -487,15 +484,15 @@ struct uvc_device { struct uvc_video_device video; + /* Video Streaming interfaces */ + struct list_head streams; + /* Status Interrupt Endpoint */ struct usb_host_endpoint *int_ep; struct urb *int_urb; __u8 *status; struct input_dev *input; char input_phys[64]; - - /* Video Streaming interfaces */ - struct list_head streaming; }; enum uvc_handle_state { @@ -504,7 +501,8 @@ enum uvc_handle_state { }; struct uvc_fh { - struct uvc_video_device *device; + struct uvc_video_device *video; + struct uvc_streaming *stream; enum uvc_handle_state state; }; @@ -601,13 +599,13 @@ static inline int uvc_queue_streaming(struct uvc_video_queue *queue) extern const struct v4l2_file_operations uvc_fops; /* Video */ -extern int uvc_video_init(struct uvc_video_device *video); -extern int uvc_video_suspend(struct uvc_video_device *video); -extern int uvc_video_resume(struct uvc_video_device *video); -extern int uvc_video_enable(struct uvc_video_device *video, int enable); -extern int uvc_probe_video(struct uvc_video_device *video, +extern int uvc_video_init(struct uvc_streaming *stream); +extern int uvc_video_suspend(struct uvc_streaming *stream); +extern int uvc_video_resume(struct uvc_streaming *stream); +extern int uvc_video_enable(struct uvc_streaming *stream, int enable); +extern int uvc_probe_video(struct uvc_streaming *stream, struct uvc_streaming_control *probe); -extern int uvc_commit_video(struct uvc_video_device *video, +extern int uvc_commit_video(struct uvc_streaming *stream, struct uvc_streaming_control *ctrl); extern int uvc_query_ctrl(struct uvc_device *dev, __u8 query, __u8 unit, __u8 intfnum, __u8 cs, void *data, __u16 size); @@ -661,7 +659,7 @@ extern struct usb_host_endpoint *uvc_find_endpoint( struct usb_host_interface *alts, __u8 epaddr); /* Quirks support */ -void uvc_video_decode_isight(struct urb *urb, struct uvc_video_device *video, +void uvc_video_decode_isight(struct urb *urb, struct uvc_streaming *stream, struct uvc_buffer *buf); #endif /* __KERNEL__ */ -- cgit v1.2.3 From 46599e77452ecf841cc58ea17be53e29fc9c808f Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Tue, 30 Jun 2009 12:07:01 +0200 Subject: gspca - main: Change the ISOC initialization mechanism. From: Jean-Francois Moine - call a new subdriver function 'isoc_init' before chosing the first alternate setting. - call a new subdriver function 'isoc_nego' when submitting the URBs failed. Priority: normal Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/gspca.c | 55 ++++++++++++++++++++++----------- linux/drivers/media/video/gspca/gspca.h | 5 ++- 2 files changed, 41 insertions(+), 19 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/gspca.c b/linux/drivers/media/video/gspca/gspca.c index f06aac676..e526d9323 100644 --- a/linux/drivers/media/video/gspca/gspca.c +++ b/linux/drivers/media/video/gspca/gspca.c @@ -524,7 +524,10 @@ static int create_urbs(struct gspca_dev *gspca_dev, if (!gspca_dev->cam.bulk) { /* isoc */ /* See paragraph 5.9 / table 5-11 of the usb 2.0 spec. */ - psize = (psize & 0x07ff) * (1 + ((psize >> 11) & 3)); + if (gspca_dev->pkt_size == 0) + psize = (psize & 0x07ff) * (1 + ((psize >> 11) & 3)); + else + psize = gspca_dev->pkt_size; npkt = gspca_dev->cam.npkt; if (npkt == 0) npkt = 32; /* default value */ @@ -609,13 +612,18 @@ static int gspca_init_transfer(struct gspca_dev *gspca_dev) /* set the higher alternate setting and * loop until urb submit succeeds */ gspca_dev->alt = gspca_dev->nbalt; + if (gspca_dev->sd_desc->isoc_init) { + ret = gspca_dev->sd_desc->isoc_init(gspca_dev); + if (ret < 0) + goto out; + } + ep = get_ep(gspca_dev); + if (ep == NULL) { + ret = -EIO; + goto out; + } for (;;) { PDEBUG(D_STREAM, "init transfer alt %d", gspca_dev->alt); - ep = get_ep(gspca_dev); - if (ep == NULL) { - ret = -EIO; - goto out; - } ret = create_urbs(gspca_dev, ep); if (ret < 0) goto out; @@ -640,21 +648,32 @@ static int gspca_init_transfer(struct gspca_dev *gspca_dev) /* submit the URBs */ for (n = 0; n < gspca_dev->nurbs; n++) { ret = usb_submit_urb(gspca_dev->urb[n], GFP_KERNEL); - if (ret < 0) { - PDEBUG(D_ERR|D_STREAM, - "usb_submit_urb [%d] err %d", n, ret); - gspca_dev->streaming = 0; - destroy_urbs(gspca_dev); - if (ret == -ENOSPC) { - msleep(20); /* wait for kill - * complete */ - break; /* try the previous alt */ - } - goto out; - } + if (ret < 0) + break; } if (ret >= 0) break; + PDEBUG(D_ERR|D_STREAM, + "usb_submit_urb alt %d err %d", gspca_dev->alt, ret); + gspca_dev->streaming = 0; + destroy_urbs(gspca_dev); + if (ret != -ENOSPC) + goto out; + + /* the bandwidth is not wide enough + * negociate or try a lower alternate setting */ + msleep(20); /* wait for kill complete */ + if (gspca_dev->sd_desc->isoc_nego) { + ret = gspca_dev->sd_desc->isoc_nego(gspca_dev); + if (ret < 0) + goto out; + } else { + ep = get_ep(gspca_dev); + if (ep == NULL) { + ret = -EIO; + goto out; + } + } } out: mutex_unlock(&gspca_dev->usb_lock); diff --git a/linux/drivers/media/video/gspca/gspca.h b/linux/drivers/media/video/gspca/gspca.h index bd1faff88..0508a23b9 100644 --- a/linux/drivers/media/video/gspca/gspca.h +++ b/linux/drivers/media/video/gspca/gspca.h @@ -94,9 +94,11 @@ struct sd_desc { /* mandatory operations */ cam_cf_op config; /* called on probe */ cam_op init; /* called on probe and resume */ - cam_op start; /* called on stream on */ + cam_op start; /* called on stream on after URBs creation */ cam_pkt_op pkt_scan; /* optional operations */ + cam_op isoc_init; /* called on stream on before getting the EP */ + cam_op isoc_nego; /* called when URB submit failed with NOSPC */ cam_v_op stopN; /* called on stream off - main alt */ cam_v_op stop0; /* called on stream off & disconnect - alt 0 */ cam_v_op dq_callback; /* called when a frame has been dequeued */ @@ -169,6 +171,7 @@ struct gspca_dev { __u8 iface; /* USB interface number */ __u8 alt; /* USB alternate setting */ __u8 nbalt; /* number of USB alternate settings */ + u16 pkt_size; /* ISOC packet size */ }; int gspca_dev_probe(struct usb_interface *intf, -- cgit v1.2.3 From 900f5eab6c506d9e1832d73b2f9c9dfb03101e83 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20Andr=C3=A9n?= Date: Wed, 1 Jul 2009 07:56:44 +0200 Subject: gspca - stv06xx-hdcs: Correct the pixelformat MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: Erik Andrén Priority: high Signed-off-by: Erik Andrén --- linux/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.c b/linux/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.c index a45171be3..e5024c849 100644 --- a/linux/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.c +++ b/linux/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.c @@ -64,7 +64,7 @@ static struct v4l2_pix_format hdcs1x00_mode[] = { { HDCS_1X00_DEF_WIDTH, HDCS_1X00_DEF_HEIGHT, - V4L2_PIX_FMT_SBGGR8, + V4L2_PIX_FMT_SGRBG8, V4L2_FIELD_NONE, .sizeimage = HDCS_1X00_DEF_WIDTH * HDCS_1X00_DEF_HEIGHT, @@ -80,7 +80,7 @@ static struct v4l2_pix_format hdcs1020_mode[] = { { HDCS_1020_DEF_WIDTH, HDCS_1020_DEF_HEIGHT, - V4L2_PIX_FMT_SBGGR8, + V4L2_PIX_FMT_SGRBG8, V4L2_FIELD_NONE, .sizeimage = HDCS_1020_DEF_WIDTH * HDCS_1020_DEF_HEIGHT, -- cgit v1.2.3 From c5bf599bcaa4cba04f76ae9edce2d9766a9602fd Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Thu, 2 Jul 2009 01:24:47 +0200 Subject: uvcvideo: Multiple streaming interfaces support From: Laurent Pinchart Restructure the UVC descriptors parsing code to handle multiple streaming interfaces. The driver now creates a uvc_video_chain instance for each chain detected in the UVC control interface descriptors, and tries to register one video device per streaming endpoint. Priority: normal Signed-off-by: Laurent Pinchart --- linux/drivers/media/video/uvc/uvc_ctrl.c | 82 ++--- linux/drivers/media/video/uvc/uvc_driver.c | 466 ++++++++++++++++++----------- linux/drivers/media/video/uvc/uvc_v4l2.c | 80 ++--- linux/drivers/media/video/uvc/uvc_video.c | 2 +- linux/drivers/media/video/uvc/uvcvideo.h | 59 ++-- 5 files changed, 411 insertions(+), 278 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/uvc/uvc_ctrl.c b/linux/drivers/media/video/uvc/uvc_ctrl.c index 81928f838..57b6fe937 100644 --- a/linux/drivers/media/video/uvc/uvc_ctrl.c +++ b/linux/drivers/media/video/uvc/uvc_ctrl.c @@ -731,7 +731,7 @@ static void __uvc_find_control(struct uvc_entity *entity, __u32 v4l2_id, } } -struct uvc_control *uvc_find_control(struct uvc_video_device *video, +struct uvc_control *uvc_find_control(struct uvc_video_chain *chain, __u32 v4l2_id, struct uvc_control_mapping **mapping) { struct uvc_control *ctrl = NULL; @@ -744,17 +744,17 @@ struct uvc_control *uvc_find_control(struct uvc_video_device *video, v4l2_id &= V4L2_CTRL_ID_MASK; /* Find the control. */ - __uvc_find_control(video->processing, v4l2_id, mapping, &ctrl, next); + __uvc_find_control(chain->processing, v4l2_id, mapping, &ctrl, next); if (ctrl && !next) return ctrl; - list_for_each_entry(entity, &video->iterms, chain) { + list_for_each_entry(entity, &chain->iterms, chain) { __uvc_find_control(entity, v4l2_id, mapping, &ctrl, next); if (ctrl && !next) return ctrl; } - list_for_each_entry(entity, &video->extensions, chain) { + list_for_each_entry(entity, &chain->extensions, chain) { __uvc_find_control(entity, v4l2_id, mapping, &ctrl, next); if (ctrl && !next) return ctrl; @@ -767,7 +767,7 @@ struct uvc_control *uvc_find_control(struct uvc_video_device *video, return ctrl; } -int uvc_query_v4l2_ctrl(struct uvc_video_device *video, +int uvc_query_v4l2_ctrl(struct uvc_video_chain *chain, struct v4l2_queryctrl *v4l2_ctrl) { struct uvc_control *ctrl; @@ -777,7 +777,7 @@ int uvc_query_v4l2_ctrl(struct uvc_video_device *video, __u8 *data; int ret; - ctrl = uvc_find_control(video, v4l2_ctrl->id, &mapping); + ctrl = uvc_find_control(chain, v4l2_ctrl->id, &mapping); if (ctrl == NULL) return -EINVAL; @@ -795,9 +795,9 @@ int uvc_query_v4l2_ctrl(struct uvc_video_device *video, v4l2_ctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY; if (ctrl->info->flags & UVC_CONTROL_GET_DEF) { - ret = uvc_query_ctrl(video->dev, UVC_GET_DEF, ctrl->entity->id, - video->dev->intfnum, ctrl->info->selector, data, - ctrl->info->size); + ret = uvc_query_ctrl(chain->dev, UVC_GET_DEF, ctrl->entity->id, + chain->dev->intfnum, ctrl->info->selector, + data, ctrl->info->size); if (ret < 0) goto out; v4l2_ctrl->default_value = @@ -833,25 +833,25 @@ int uvc_query_v4l2_ctrl(struct uvc_video_device *video, } if (ctrl->info->flags & UVC_CONTROL_GET_MIN) { - ret = uvc_query_ctrl(video->dev, UVC_GET_MIN, ctrl->entity->id, - video->dev->intfnum, ctrl->info->selector, data, - ctrl->info->size); + ret = uvc_query_ctrl(chain->dev, UVC_GET_MIN, ctrl->entity->id, + chain->dev->intfnum, ctrl->info->selector, + data, ctrl->info->size); if (ret < 0) goto out; v4l2_ctrl->minimum = mapping->get(mapping, UVC_GET_MIN, data); } if (ctrl->info->flags & UVC_CONTROL_GET_MAX) { - ret = uvc_query_ctrl(video->dev, UVC_GET_MAX, ctrl->entity->id, - video->dev->intfnum, ctrl->info->selector, data, - ctrl->info->size); + ret = uvc_query_ctrl(chain->dev, UVC_GET_MAX, ctrl->entity->id, + chain->dev->intfnum, ctrl->info->selector, + data, ctrl->info->size); if (ret < 0) goto out; v4l2_ctrl->maximum = mapping->get(mapping, UVC_GET_MAX, data); } if (ctrl->info->flags & UVC_CONTROL_GET_RES) { - ret = uvc_query_ctrl(video->dev, UVC_GET_RES, ctrl->entity->id, - video->dev->intfnum, ctrl->info->selector, data, - ctrl->info->size); + ret = uvc_query_ctrl(chain->dev, UVC_GET_RES, ctrl->entity->id, + chain->dev->intfnum, ctrl->info->selector, + data, ctrl->info->size); if (ret < 0) goto out; v4l2_ctrl->step = mapping->get(mapping, UVC_GET_RES, data); @@ -888,9 +888,9 @@ out: * (UVC_CTRL_DATA_BACKUP) for all dirty controls. Both functions release the * control lock. */ -int uvc_ctrl_begin(struct uvc_video_device *video) +int uvc_ctrl_begin(struct uvc_video_chain *chain) { - return mutex_lock_interruptible(&video->ctrl_mutex) ? -ERESTARTSYS : 0; + return mutex_lock_interruptible(&chain->ctrl_mutex) ? -ERESTARTSYS : 0; } static int uvc_ctrl_commit_entity(struct uvc_device *dev, @@ -940,34 +940,34 @@ static int uvc_ctrl_commit_entity(struct uvc_device *dev, return 0; } -int __uvc_ctrl_commit(struct uvc_video_device *video, int rollback) +int __uvc_ctrl_commit(struct uvc_video_chain *chain, int rollback) { struct uvc_entity *entity; int ret = 0; /* Find the control. */ - ret = uvc_ctrl_commit_entity(video->dev, video->processing, rollback); + ret = uvc_ctrl_commit_entity(chain->dev, chain->processing, rollback); if (ret < 0) goto done; - list_for_each_entry(entity, &video->iterms, chain) { - ret = uvc_ctrl_commit_entity(video->dev, entity, rollback); + list_for_each_entry(entity, &chain->iterms, chain) { + ret = uvc_ctrl_commit_entity(chain->dev, entity, rollback); if (ret < 0) goto done; } - list_for_each_entry(entity, &video->extensions, chain) { - ret = uvc_ctrl_commit_entity(video->dev, entity, rollback); + list_for_each_entry(entity, &chain->extensions, chain) { + ret = uvc_ctrl_commit_entity(chain->dev, entity, rollback); if (ret < 0) goto done; } done: - mutex_unlock(&video->ctrl_mutex); + mutex_unlock(&chain->ctrl_mutex); return ret; } -int uvc_ctrl_get(struct uvc_video_device *video, +int uvc_ctrl_get(struct uvc_video_chain *chain, struct v4l2_ext_control *xctrl) { struct uvc_control *ctrl; @@ -976,13 +976,13 @@ int uvc_ctrl_get(struct uvc_video_device *video, unsigned int i; int ret; - ctrl = uvc_find_control(video, xctrl->id, &mapping); + ctrl = uvc_find_control(chain, xctrl->id, &mapping); if (ctrl == NULL || (ctrl->info->flags & UVC_CONTROL_GET_CUR) == 0) return -EINVAL; if (!ctrl->loaded) { - ret = uvc_query_ctrl(video->dev, UVC_GET_CUR, ctrl->entity->id, - video->dev->intfnum, ctrl->info->selector, + ret = uvc_query_ctrl(chain->dev, UVC_GET_CUR, ctrl->entity->id, + chain->dev->intfnum, ctrl->info->selector, uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT), ctrl->info->size); if (ret < 0) @@ -1007,7 +1007,7 @@ int uvc_ctrl_get(struct uvc_video_device *video, return 0; } -int uvc_ctrl_set(struct uvc_video_device *video, +int uvc_ctrl_set(struct uvc_video_chain *chain, struct v4l2_ext_control *xctrl) { struct uvc_control *ctrl; @@ -1015,7 +1015,7 @@ int uvc_ctrl_set(struct uvc_video_device *video, s32 value = xctrl->value; int ret; - ctrl = uvc_find_control(video, xctrl->id, &mapping); + ctrl = uvc_find_control(chain, xctrl->id, &mapping); if (ctrl == NULL || (ctrl->info->flags & UVC_CONTROL_SET_CUR) == 0) return -EINVAL; @@ -1030,8 +1030,8 @@ int uvc_ctrl_set(struct uvc_video_device *video, memset(uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT), 0, ctrl->info->size); } else { - ret = uvc_query_ctrl(video->dev, UVC_GET_CUR, - ctrl->entity->id, video->dev->intfnum, + ret = uvc_query_ctrl(chain->dev, UVC_GET_CUR, + ctrl->entity->id, chain->dev->intfnum, ctrl->info->selector, uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT), ctrl->info->size); @@ -1060,7 +1060,7 @@ int uvc_ctrl_set(struct uvc_video_device *video, * Dynamic controls */ -int uvc_xu_ctrl_query(struct uvc_video_device *video, +int uvc_xu_ctrl_query(struct uvc_video_chain *chain, struct uvc_xu_control *xctrl, int set) { struct uvc_entity *entity; @@ -1070,7 +1070,7 @@ int uvc_xu_ctrl_query(struct uvc_video_device *video, int ret; /* Find the extension unit. */ - list_for_each_entry(entity, &video->extensions, chain) { + list_for_each_entry(entity, &chain->extensions, chain) { if (entity->id == xctrl->unit) break; } @@ -1109,7 +1109,7 @@ int uvc_xu_ctrl_query(struct uvc_video_device *video, (!set && !(ctrl->info->flags & UVC_CONTROL_GET_CUR))) return -EINVAL; - if (mutex_lock_interruptible(&video->ctrl_mutex)) + if (mutex_lock_interruptible(&chain->ctrl_mutex)) return -ERESTARTSYS; memcpy(uvc_ctrl_data(ctrl, UVC_CTRL_DATA_BACKUP), @@ -1122,8 +1122,8 @@ int uvc_xu_ctrl_query(struct uvc_video_device *video, goto out; } - ret = uvc_query_ctrl(video->dev, set ? UVC_SET_CUR : UVC_GET_CUR, - xctrl->unit, video->dev->intfnum, xctrl->selector, + ret = uvc_query_ctrl(chain->dev, set ? UVC_SET_CUR : UVC_GET_CUR, + xctrl->unit, chain->dev->intfnum, xctrl->selector, data, xctrl->size); if (ret < 0) goto out; @@ -1139,7 +1139,7 @@ out: uvc_ctrl_data(ctrl, UVC_CTRL_DATA_BACKUP), xctrl->size); - mutex_unlock(&video->ctrl_mutex); + mutex_unlock(&chain->ctrl_mutex); return ret; } diff --git a/linux/drivers/media/video/uvc/uvc_driver.c b/linux/drivers/media/video/uvc/uvc_driver.c index 70d15a926..fa13b6765 100644 --- a/linux/drivers/media/video/uvc/uvc_driver.c +++ b/linux/drivers/media/video/uvc/uvc_driver.c @@ -276,8 +276,20 @@ static struct uvc_entity *uvc_entity_by_reference(struct uvc_device *dev, return NULL; } +static struct uvc_streaming *uvc_stream_by_id(struct uvc_device *dev, int id) +{ + struct uvc_streaming *stream; + + list_for_each_entry(stream, &dev->streams, list) { + if (stream->header.bTerminalLink == id) + return stream; + } + + return NULL; +} + /* ------------------------------------------------------------------------ - * Descriptors handling + * Descriptors parsing */ static int uvc_parse_format(struct uvc_device *dev, @@ -1160,101 +1172,36 @@ next_descriptor: } /* ------------------------------------------------------------------------ - * USB probe and disconnect + * UVC device scan */ -/* - * Unregister the video devices. - */ -static void uvc_unregister_video(struct uvc_device *dev) -{ - struct uvc_streaming *streaming; - - list_for_each_entry(streaming, &dev->streams, list) { - if (streaming->vdev == NULL) - continue; - - if (streaming->vdev->minor == -1) - video_device_release(streaming->vdev); - else - video_unregister_device(streaming->vdev); - streaming->vdev = NULL; - } -} - -static int uvc_register_video(struct uvc_device *dev, - struct uvc_streaming *stream) -{ - struct video_device *vdev; - struct uvc_entity *term; - int ret; - - if (uvc_trace_param & UVC_TRACE_PROBE) { - uvc_printk(KERN_INFO, "Found a valid video chain ("); - list_for_each_entry(term, &dev->video.iterms, chain) { - printk("%d", term->id); - if (term->chain.next != &dev->video.iterms) - printk(","); - } - printk(" -> %d).\n", dev->video.oterm->id); - } - - /* Initialize the streaming interface with default streaming - * parameters. - */ - ret = uvc_video_init(stream); - if (ret < 0) { - uvc_printk(KERN_ERR, "Failed to initialize the device " - "(%d).\n", ret); - return ret; - } - - /* Register the device with V4L. */ - vdev = video_device_alloc(); - if (vdev == NULL) - return -1; - - /* We already hold a reference to dev->udev. The video device will be - * unregistered before the reference is released, so we don't need to - * get another one. - */ - vdev->parent = &dev->intf->dev; - vdev->minor = -1; - vdev->fops = &uvc_fops; - vdev->release = video_device_release; - strlcpy(vdev->name, dev->name, sizeof vdev->name); - - /* Set the driver data before calling video_register_device, otherwise - * uvc_v4l2_open might race us. - */ - stream->vdev = vdev; - video_set_drvdata(vdev, stream); - - if (video_register_device(vdev, VFL_TYPE_GRABBER, -1) < 0) { - stream->vdev = NULL; - video_device_release(vdev); - return -1; - } - - return 0; -} - /* * Scan the UVC descriptors to locate a chain starting at an Output Terminal * and containing the following units: * - * - one Output Terminal (USB Streaming or Display) + * - one or more Output Terminals (USB Streaming or Display) * - zero or one Processing Unit - * - zero, one or mode single-input Selector Units + * - zero, one or more single-input Selector Units * - zero or one multiple-input Selector Units, provided all inputs are * connected to input terminals * - zero, one or mode single-input Extension Units * - one or more Input Terminals (Camera, External or USB Streaming) * - * A side forward scan is made on each detected entity to check for additional - * extension units. + * The terminal and units must match on of the following structures: + * + * ITT_*(0) -> +---------+ +---------+ +---------+ -> TT_STREAMING(0) + * ... | SU{0,1} | -> | PU{0,1} | -> | XU{0,n} | ... + * ITT_*(n) -> +---------+ +---------+ +---------+ -> TT_STREAMING(n) + * + * +---------+ +---------+ -> OTT_*(0) + * TT_STREAMING -> | PU{0,1} | -> | XU{0,n} | ... + * +---------+ +---------+ -> OTT_*(n) + * + * The Processing Unit and Extension Units can be in any order. Additional + * Extension Units connected to the main chain as single-unit branches are + * also supported. Single-input Selector Units are ignored. */ -static int uvc_scan_chain_entity(struct uvc_video_device *video, +static int uvc_scan_chain_entity(struct uvc_video_chain *chain, struct uvc_entity *entity) { switch (UVC_ENTITY_TYPE(entity)) { @@ -1268,20 +1215,20 @@ static int uvc_scan_chain_entity(struct uvc_video_device *video, return -1; } - list_add_tail(&entity->chain, &video->extensions); + list_add_tail(&entity->chain, &chain->extensions); break; case UVC_VC_PROCESSING_UNIT: if (uvc_trace_param & UVC_TRACE_PROBE) printk(" <- PU %d", entity->id); - if (video->processing != NULL) { + if (chain->processing != NULL) { uvc_trace(UVC_TRACE_DESCR, "Found multiple " "Processing Units in chain.\n"); return -1; } - video->processing = entity; + chain->processing = entity; break; case UVC_VC_SELECTOR_UNIT: @@ -1292,13 +1239,13 @@ static int uvc_scan_chain_entity(struct uvc_video_device *video, if (entity->selector.bNrInPins == 1) break; - if (video->selector != NULL) { + if (chain->selector != NULL) { uvc_trace(UVC_TRACE_DESCR, "Found multiple Selector " "Units in chain.\n"); return -1; } - video->selector = entity; + chain->selector = entity; break; case UVC_ITT_VENDOR_SPECIFIC: @@ -1307,7 +1254,7 @@ static int uvc_scan_chain_entity(struct uvc_video_device *video, if (uvc_trace_param & UVC_TRACE_PROBE) printk(" <- IT %d\n", entity->id); - list_add_tail(&entity->chain, &video->iterms); + list_add_tail(&entity->chain, &chain->iterms); break; case UVC_TT_STREAMING: @@ -1320,14 +1267,7 @@ static int uvc_scan_chain_entity(struct uvc_video_device *video, return -1; } - if (video->sterm != NULL) { - uvc_trace(UVC_TRACE_DESCR, "Found multiple streaming " - "entities in chain.\n"); - return -1; - } - - list_add_tail(&entity->chain, &video->iterms); - video->sterm = entity; + list_add_tail(&entity->chain, &chain->iterms); break; default: @@ -1339,7 +1279,7 @@ static int uvc_scan_chain_entity(struct uvc_video_device *video, return 0; } -static int uvc_scan_chain_forward(struct uvc_video_device *video, +static int uvc_scan_chain_forward(struct uvc_video_chain *chain, struct uvc_entity *entity, struct uvc_entity *prev) { struct uvc_entity *forward; @@ -1350,28 +1290,51 @@ static int uvc_scan_chain_forward(struct uvc_video_device *video, found = 0; while (1) { - forward = uvc_entity_by_reference(video->dev, entity->id, + forward = uvc_entity_by_reference(chain->dev, entity->id, forward); if (forward == NULL) break; - - if (UVC_ENTITY_TYPE(forward) != UVC_VC_EXTENSION_UNIT || - forward == prev) + if (forward == prev) continue; - if (forward->extension.bNrInPins != 1) { - uvc_trace(UVC_TRACE_DESCR, "Extension unit %d has " - "more than 1 input pin.\n", entity->id); - return -1; - } + switch (UVC_ENTITY_TYPE(forward)) { + case UVC_VC_EXTENSION_UNIT: + if (forward->extension.bNrInPins != 1) { + uvc_trace(UVC_TRACE_DESCR, "Extension unit %d " + "has more than 1 input pin.\n", + entity->id); + return -EINVAL; + } + + list_add_tail(&forward->chain, &chain->extensions); + if (uvc_trace_param & UVC_TRACE_PROBE) { + if (!found) + printk(" (->"); + + printk(" XU %d", forward->id); + found = 1; + } + break; + + case UVC_OTT_VENDOR_SPECIFIC: + case UVC_OTT_DISPLAY: + case UVC_OTT_MEDIA_TRANSPORT_OUTPUT: + case UVC_TT_STREAMING: + if (UVC_ENTITY_IS_ITERM(forward)) { + uvc_trace(UVC_TRACE_DESCR, "Unsupported input " + "terminal %u.\n", forward->id); + return -EINVAL; + } - list_add_tail(&forward->chain, &video->extensions); - if (uvc_trace_param & UVC_TRACE_PROBE) { - if (!found) - printk(" (-> XU"); + list_add_tail(&forward->chain, &chain->oterms); + if (uvc_trace_param & UVC_TRACE_PROBE) { + if (!found) + printk(" (->"); - printk(" %d", forward->id); - found = 1; + printk(" OT %d", forward->id); + found = 1; + } + break; } } if (found) @@ -1380,7 +1343,7 @@ static int uvc_scan_chain_forward(struct uvc_video_device *video, return 0; } -static int uvc_scan_chain_backward(struct uvc_video_device *video, +static int uvc_scan_chain_backward(struct uvc_video_chain *chain, struct uvc_entity *entity) { struct uvc_entity *term; @@ -1405,10 +1368,10 @@ static int uvc_scan_chain_backward(struct uvc_video_device *video, if (uvc_trace_param & UVC_TRACE_PROBE) printk(" <- IT"); - video->selector = entity; + chain->selector = entity; for (i = 0; i < entity->selector.bNrInPins; ++i) { id = entity->selector.baSourceID[i]; - term = uvc_entity_by_id(video->dev, id); + term = uvc_entity_by_id(chain->dev, id); if (term == NULL || !UVC_ENTITY_IS_ITERM(term)) { uvc_trace(UVC_TRACE_DESCR, "Selector unit %d " "input %d isn't connected to an " @@ -1419,8 +1382,8 @@ static int uvc_scan_chain_backward(struct uvc_video_device *video, if (uvc_trace_param & UVC_TRACE_PROBE) printk(" %d", term->id); - list_add_tail(&term->chain, &video->iterms); - uvc_scan_chain_forward(video, term, entity); + list_add_tail(&term->chain, &chain->iterms); + uvc_scan_chain_forward(chain, term, entity); } if (uvc_trace_param & UVC_TRACE_PROBE) @@ -1433,100 +1396,129 @@ static int uvc_scan_chain_backward(struct uvc_video_device *video, return id; } -static int uvc_scan_chain(struct uvc_video_device *video) +static int uvc_scan_chain(struct uvc_video_chain *chain, + struct uvc_entity *oterm) { struct uvc_entity *entity, *prev; int id; - entity = video->oterm; + entity = oterm; + list_add_tail(&entity->chain, &chain->oterms); uvc_trace(UVC_TRACE_PROBE, "Scanning UVC chain: OT %d", entity->id); - if (UVC_ENTITY_TYPE(entity) == UVC_TT_STREAMING) - video->sterm = entity; - id = entity->output.bSourceID; while (id != 0) { prev = entity; - entity = uvc_entity_by_id(video->dev, id); + entity = uvc_entity_by_id(chain->dev, id); if (entity == NULL) { uvc_trace(UVC_TRACE_DESCR, "Found reference to " "unknown entity %d.\n", id); - return -1; + return -EINVAL; + } + + if (entity->chain.next || entity->chain.prev) { + uvc_trace(UVC_TRACE_DESCR, "Found reference to " + "entity %d already in chain.\n", id); + return -EINVAL; } /* Process entity */ - if (uvc_scan_chain_entity(video, entity) < 0) - return -1; + if (uvc_scan_chain_entity(chain, entity) < 0) + return -EINVAL; /* Forward scan */ - if (uvc_scan_chain_forward(video, entity, prev) < 0) - return -1; + if (uvc_scan_chain_forward(chain, entity, prev) < 0) + return -EINVAL; /* Stop when a terminal is found. */ - if (!UVC_ENTITY_IS_UNIT(entity)) + if (UVC_ENTITY_IS_TERM(entity)) break; /* Backward scan */ - id = uvc_scan_chain_backward(video, entity); + id = uvc_scan_chain_backward(chain, entity); if (id < 0) return id; } - if (video->sterm == NULL) { - uvc_trace(UVC_TRACE_DESCR, "No streaming entity found in " - "chain.\n"); - return -1; + return 0; +} + +static unsigned int uvc_print_terms(struct list_head *terms, char *buffer) +{ + struct uvc_entity *term; + unsigned int nterms = 0; + char *p = buffer; + + list_for_each_entry(term, terms, chain) { + p += sprintf(p, "%u", term->id); + if (term->chain.next != terms) { + p += sprintf(p, ","); + if (++nterms >= 4) { + p += sprintf(p, "..."); + break; + } + } } - return 0; + return p - buffer; +} + +static const char *uvc_print_chain(struct uvc_video_chain *chain) +{ + static char buffer[43]; + char *p = buffer; + + p += uvc_print_terms(&chain->iterms, p); + p += sprintf(p, " -> "); + uvc_print_terms(&chain->oterms, p); + + return buffer; } /* * Scan the device for video chains and register video devices. * - * The driver currently supports a single video device per control interface - * only. The terminal and units must match the following structure: - * - * ITT_* -> VC_PROCESSING_UNIT -> VC_EXTENSION_UNIT{0,n} -> TT_STREAMING - * TT_STREAMING -> VC_PROCESSING_UNIT -> VC_EXTENSION_UNIT{0,n} -> OTT_* - * - * The Extension Units, if present, must have a single input pin. The - * Processing Unit and Extension Units can be in any order. Additional - * Extension Units connected to the main chain as single-unit branches are - * also supported. + * Chains are scanned starting at their output terminals and walked backwards. */ static int uvc_scan_device(struct uvc_device *dev) { + struct uvc_video_chain *chain; struct uvc_entity *term; - int found = 0; - /* Check if the control interface matches the structure we expect. */ list_for_each_entry(term, &dev->entities, list) { - struct uvc_streaming *stream; - - if (!UVC_ENTITY_IS_TERM(term) || !UVC_ENTITY_IS_OTERM(term)) + if (!UVC_ENTITY_IS_OTERM(term)) continue; - memset(&dev->video, 0, sizeof dev->video); - mutex_init(&dev->video.ctrl_mutex); - INIT_LIST_HEAD(&dev->video.iterms); - INIT_LIST_HEAD(&dev->video.extensions); - dev->video.oterm = term; - dev->video.dev = dev; - if (uvc_scan_chain(&dev->video) < 0) + /* If the terminal is already included in a chain, skip it. + * This can happen for chains that have multiple output + * terminals, where all output terminals beside the first one + * will be inserted in the chain in forward scans. + */ + if (term->chain.next || term->chain.prev) continue; - list_for_each_entry(stream, &dev->streams, list) { - if (stream->header.bTerminalLink == - dev->video.sterm->id) { - uvc_register_video(dev, stream); - found = 1; - break; - } + chain = kzalloc(sizeof(*chain), GFP_KERNEL); + if (chain == NULL) + return -ENOMEM; + + INIT_LIST_HEAD(&chain->iterms); + INIT_LIST_HEAD(&chain->oterms); + INIT_LIST_HEAD(&chain->extensions); + mutex_init(&chain->ctrl_mutex); + chain->dev = dev; + + if (uvc_scan_chain(chain, term) < 0) { + kfree(chain); + continue; } + + uvc_trace(UVC_TRACE_PROBE, "Found a valid video chain (%s).\n", + uvc_print_chain(chain)); + + list_add_tail(&chain->list, &dev->chains); } - if (!found) { + if (list_empty(&dev->chains)) { uvc_printk(KERN_INFO, "No valid video chain found.\n"); return -1; } @@ -1534,6 +1526,133 @@ static int uvc_scan_device(struct uvc_device *dev) return 0; } +/* ------------------------------------------------------------------------ + * Video device registration and unregistration + */ + +/* + * Unregister the video devices. + */ +static void uvc_unregister_video(struct uvc_device *dev) +{ + struct uvc_streaming *stream; + + list_for_each_entry(stream, &dev->streams, list) { + if (stream->vdev == NULL) + continue; + + if (stream->vdev->minor == -1) + video_device_release(stream->vdev); + else + video_unregister_device(stream->vdev); + stream->vdev = NULL; + } +} + +static int uvc_register_video(struct uvc_device *dev, + struct uvc_streaming *stream) +{ + struct video_device *vdev; + int ret; + + /* Initialize the streaming interface with default streaming + * parameters. + */ + ret = uvc_video_init(stream); + if (ret < 0) { + uvc_printk(KERN_ERR, "Failed to initialize the device " + "(%d).\n", ret); + return ret; + } + + /* Register the device with V4L. */ + vdev = video_device_alloc(); + if (vdev == NULL) { + uvc_printk(KERN_ERR, "Failed to allocate video device (%d).\n", + ret); + return -ENOMEM; + } + + /* We already hold a reference to dev->udev. The video device will be + * unregistered before the reference is released, so we don't need to + * get another one. + */ + vdev->parent = &dev->intf->dev; + vdev->minor = -1; + vdev->fops = &uvc_fops; + vdev->release = video_device_release; + strlcpy(vdev->name, dev->name, sizeof vdev->name); + + /* Set the driver data before calling video_register_device, otherwise + * uvc_v4l2_open might race us. + */ + stream->vdev = vdev; + video_set_drvdata(vdev, stream); + + ret = video_register_device(vdev, VFL_TYPE_GRABBER, -1); + if (ret < 0) { + uvc_printk(KERN_ERR, "Failed to register video device (%d).\n", + ret); + stream->vdev = NULL; + video_device_release(vdev); + return ret; + } + + return 0; +} + +/* + * Register all video devices in all chains. + */ +static int uvc_register_terms(struct uvc_device *dev, + struct uvc_video_chain *chain, struct list_head *terms) +{ + struct uvc_streaming *stream; + struct uvc_entity *term; + int ret; + + list_for_each_entry(term, terms, chain) { + if (UVC_ENTITY_TYPE(term) != UVC_TT_STREAMING) + continue; + + stream = uvc_stream_by_id(dev, term->id); + if (stream == NULL) { + uvc_printk(KERN_INFO, "No streaming interface found " + "for terminal %u.", term->id); + continue; + } + + stream->chain = chain; + ret = uvc_register_video(dev, stream); + if (ret < 0) + return ret; + } + + return 0; +} + +static int uvc_register_chains(struct uvc_device *dev) +{ + struct uvc_video_chain *chain; + int ret; + + list_for_each_entry(chain, &dev->chains, list) { + ret = uvc_register_terms(dev, chain, &chain->iterms); + if (ret < 0) + return ret; + + ret = uvc_register_terms(dev, chain, &chain->oterms); + if (ret < 0) + return ret; + } + + return 0; +} + +/* ------------------------------------------------------------------------ + * USB probe, disconnect, suspend and resume + */ + /* * Delete the UVC device. * @@ -1555,7 +1674,7 @@ void uvc_delete(struct kref *kref) struct uvc_device *dev = container_of(kref, struct uvc_device, kref); struct list_head *p, *n; - /* Unregister the video device. */ + /* Unregister the video devices. */ uvc_unregister_video(dev); usb_put_intf(dev->intf); usb_put_dev(dev->udev); @@ -1563,6 +1682,12 @@ void uvc_delete(struct kref *kref) uvc_status_cleanup(dev); uvc_ctrl_cleanup_device(dev); + list_for_each_safe(p, n, &dev->chains) { + struct uvc_video_chain *chain; + chain = list_entry(p, struct uvc_video_chain, list); + kfree(chain); + } + list_for_each_safe(p, n, &dev->entities) { struct uvc_entity *entity; entity = list_entry(p, struct uvc_entity, list); @@ -1603,6 +1728,7 @@ static int uvc_probe(struct usb_interface *intf, return -ENOMEM; INIT_LIST_HEAD(&dev->entities); + INIT_LIST_HEAD(&dev->chains); INIT_LIST_HEAD(&dev->streams); kref_init(&dev->kref); atomic_set(&dev->users, 0); @@ -1644,10 +1770,14 @@ static int uvc_probe(struct usb_interface *intf, if (uvc_ctrl_init_device(dev) < 0) goto error; - /* Scan the device for video chains and register video devices. */ + /* Scan the device for video chains. */ if (uvc_scan_device(dev) < 0) goto error; + /* Register video devices. */ + if (uvc_register_chains(dev) < 0) + goto error; + /* Save our data pointer in the interface data. */ usb_set_intfdata(intf, dev); diff --git a/linux/drivers/media/video/uvc/uvc_v4l2.c b/linux/drivers/media/video/uvc/uvc_v4l2.c index 3379e1320..b5a16acb6 100644 --- a/linux/drivers/media/video/uvc/uvc_v4l2.c +++ b/linux/drivers/media/video/uvc/uvc_v4l2.c @@ -40,7 +40,7 @@ * table for the controls that can be mapped directly, and handle the others * manually. */ -static int uvc_v4l2_query_menu(struct uvc_video_device *video, +static int uvc_v4l2_query_menu(struct uvc_video_chain *chain, struct v4l2_querymenu *query_menu) { struct uvc_menu_info *menu_info; @@ -49,7 +49,7 @@ static int uvc_v4l2_query_menu(struct uvc_video_device *video, u32 index = query_menu->index; u32 id = query_menu->id; - ctrl = uvc_find_control(video, query_menu->id, &mapping); + ctrl = uvc_find_control(chain, query_menu->id, &mapping); if (ctrl == NULL || mapping->v4l2_type != V4L2_CTRL_TYPE_MENU) return -EINVAL; @@ -457,7 +457,7 @@ static int uvc_v4l2_open(struct file *file) } } - handle->video = &stream->dev->video; + handle->chain = stream->chain; handle->stream = stream; handle->state = UVC_HANDLE_PASSIVE; file->private_data = handle; @@ -506,7 +506,7 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) { struct video_device *vdev = video_devdata(file); struct uvc_fh *handle = (struct uvc_fh *)file->private_data; - struct uvc_video_device *video = handle->video; + struct uvc_video_chain *chain = handle->chain; struct uvc_streaming *stream = handle->stream; long ret = 0; @@ -533,7 +533,7 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) /* Get, Set & Query control */ case VIDIOC_QUERYCTRL: - return uvc_query_v4l2_ctrl(video, arg); + return uvc_query_v4l2_ctrl(chain, arg); case VIDIOC_G_CTRL: { @@ -543,12 +543,12 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) memset(&xctrl, 0, sizeof xctrl); xctrl.id = ctrl->id; - ret = uvc_ctrl_begin(video); - if (ret < 0) + ret = uvc_ctrl_begin(chain); + if (ret < 0) return ret; - ret = uvc_ctrl_get(video, &xctrl); - uvc_ctrl_rollback(video); + ret = uvc_ctrl_get(chain, &xctrl); + uvc_ctrl_rollback(chain); if (ret >= 0) ctrl->value = xctrl.value; break; @@ -563,21 +563,21 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) xctrl.id = ctrl->id; xctrl.value = ctrl->value; - ret = uvc_ctrl_begin(video); - if (ret < 0) + uvc_ctrl_begin(chain); + if (ret < 0) return ret; - ret = uvc_ctrl_set(video, &xctrl); + ret = uvc_ctrl_set(chain, &xctrl); if (ret < 0) { - uvc_ctrl_rollback(video); + uvc_ctrl_rollback(chain); return ret; } - ret = uvc_ctrl_commit(video); + ret = uvc_ctrl_commit(chain); break; } case VIDIOC_QUERYMENU: - return uvc_v4l2_query_menu(video, arg); + return uvc_v4l2_query_menu(chain, arg); case VIDIOC_G_EXT_CTRLS: { @@ -585,20 +585,20 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) struct v4l2_ext_control *ctrl = ctrls->controls; unsigned int i; - ret = uvc_ctrl_begin(video); - if (ret < 0) + ret = uvc_ctrl_begin(chain); + if (ret < 0) return ret; for (i = 0; i < ctrls->count; ++ctrl, ++i) { - ret = uvc_ctrl_get(video, ctrl); + ret = uvc_ctrl_get(chain, ctrl); if (ret < 0) { - uvc_ctrl_rollback(video); + uvc_ctrl_rollback(chain); ctrls->error_idx = i; return ret; } } ctrls->error_idx = 0; - ret = uvc_ctrl_rollback(video); + ret = uvc_ctrl_rollback(chain); break; } @@ -609,14 +609,14 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) struct v4l2_ext_control *ctrl = ctrls->controls; unsigned int i; - ret = uvc_ctrl_begin(video); + ret = uvc_ctrl_begin(chain); if (ret < 0) return ret; for (i = 0; i < ctrls->count; ++ctrl, ++i) { - ret = uvc_ctrl_set(video, ctrl); + ret = uvc_ctrl_set(chain, ctrl); if (ret < 0) { - uvc_ctrl_rollback(video); + uvc_ctrl_rollback(chain); ctrls->error_idx = i; return ret; } @@ -625,31 +625,31 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) ctrls->error_idx = 0; if (cmd == VIDIOC_S_EXT_CTRLS) - ret = uvc_ctrl_commit(video); + ret = uvc_ctrl_commit(chain); else - ret = uvc_ctrl_rollback(video); + ret = uvc_ctrl_rollback(chain); break; } /* Get, Set & Enum input */ case VIDIOC_ENUMINPUT: { - const struct uvc_entity *selector = video->selector; + const struct uvc_entity *selector = chain->selector; struct v4l2_input *input = arg; struct uvc_entity *iterm = NULL; u32 index = input->index; int pin = 0; if (selector == NULL || - (video->dev->quirks & UVC_QUIRK_IGNORE_SELECTOR_UNIT)) { + (chain->dev->quirks & UVC_QUIRK_IGNORE_SELECTOR_UNIT)) { if (index != 0) return -EINVAL; - iterm = list_first_entry(&video->iterms, + iterm = list_first_entry(&chain->iterms, struct uvc_entity, chain); pin = iterm->id; } else if (pin < selector->selector.bNrInPins) { pin = selector->selector.baSourceID[index]; - list_for_each_entry(iterm, video->iterms.next, chain) { + list_for_each_entry(iterm, chain->iterms.next, chain) { if (iterm->id == pin) break; } @@ -670,14 +670,14 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) { u8 input; - if (video->selector == NULL || - (video->dev->quirks & UVC_QUIRK_IGNORE_SELECTOR_UNIT)) { + if (chain->selector == NULL || + (chain->dev->quirks & UVC_QUIRK_IGNORE_SELECTOR_UNIT)) { *(int *)arg = 0; break; } - ret = uvc_query_ctrl(video->dev, UVC_GET_CUR, - video->selector->id, video->dev->intfnum, + ret = uvc_query_ctrl(chain->dev, UVC_GET_CUR, + chain->selector->id, chain->dev->intfnum, UVC_SU_INPUT_SELECT_CONTROL, &input, 1); if (ret < 0) return ret; @@ -693,18 +693,18 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) if ((ret = uvc_acquire_privileges(handle)) < 0) return ret; - if (video->selector == NULL || - (video->dev->quirks & UVC_QUIRK_IGNORE_SELECTOR_UNIT)) { + if (chain->selector == NULL || + (chain->dev->quirks & UVC_QUIRK_IGNORE_SELECTOR_UNIT)) { if (input != 1) return -EINVAL; break; } - if (input == 0 || input > video->selector->selector.bNrInPins) + if (input == 0 || input > chain->selector->selector.bNrInPins) return -EINVAL; - return uvc_query_ctrl(video->dev, UVC_SET_CUR, - video->selector->id, video->dev->intfnum, + return uvc_query_ctrl(chain->dev, UVC_SET_CUR, + chain->selector->id, chain->dev->intfnum, UVC_SU_INPUT_SELECT_CONTROL, &input, 1); } @@ -1027,10 +1027,10 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) } case UVCIOC_CTRL_GET: - return uvc_xu_ctrl_query(video, arg, 0); + return uvc_xu_ctrl_query(chain, arg, 0); case UVCIOC_CTRL_SET: - return uvc_xu_ctrl_query(video, arg, 1); + return uvc_xu_ctrl_query(chain, arg, 1); default: if ((ret = v4l_compat_translate_ioctl(file, cmd, arg, diff --git a/linux/drivers/media/video/uvc/uvc_video.c b/linux/drivers/media/video/uvc/uvc_video.c index 38cb7a367..792a93a1c 100644 --- a/linux/drivers/media/video/uvc/uvc_video.c +++ b/linux/drivers/media/video/uvc/uvc_video.c @@ -128,7 +128,7 @@ static int uvc_get_video_ctrl(struct uvc_streaming *stream, if (data == NULL) return -ENOMEM; - if ((video->dev->quirks & UVC_QUIRK_PROBE_DEF) && query == UVC_GET_DEF) + if ((stream->dev->quirks & UVC_QUIRK_PROBE_DEF) && query == UVC_GET_DEF) return -EIO; ret = __uvc_query_ctrl(stream->dev, query, 0, stream->intfnum, diff --git a/linux/drivers/media/video/uvc/uvcvideo.h b/linux/drivers/media/video/uvc/uvcvideo.h index c385b7bde..30a17f24e 100644 --- a/linux/drivers/media/video/uvc/uvcvideo.h +++ b/linux/drivers/media/video/uvc/uvcvideo.h @@ -81,9 +81,11 @@ struct uvc_xu_control { #define UVC_ENTITY_IS_UNIT(entity) (((entity)->type & 0xff00) == 0) #define UVC_ENTITY_IS_TERM(entity) (((entity)->type & 0xff00) != 0) #define UVC_ENTITY_IS_ITERM(entity) \ - (((entity)->type & 0x8000) == UVC_TERM_INPUT) + (UVC_ENTITY_IS_TERM(entity) && \ + ((entity)->type & 0x8000) == UVC_TERM_INPUT) #define UVC_ENTITY_IS_OTERM(entity) \ - (((entity)->type & 0x8000) == UVC_TERM_OUTPUT) + (UVC_ENTITY_IS_TERM(entity) && \ + ((entity)->type & 0x8000) == UVC_TERM_OUTPUT) /* ------------------------------------------------------------------------ @@ -403,10 +405,24 @@ struct uvc_video_queue { struct list_head irqqueue; }; +struct uvc_video_chain { + struct uvc_device *dev; + struct list_head list; + + struct list_head iterms; /* Input terminals */ + struct list_head oterms; /* Output terminals */ + struct uvc_entity *processing; /* Processing unit */ + struct uvc_entity *selector; /* Selector unit */ + struct list_head extensions; /* Extension units */ + + struct mutex ctrl_mutex; +}; + struct uvc_streaming { struct list_head list; struct uvc_device *dev; struct video_device *vdev; + struct uvc_video_chain *chain; atomic_t active; struct usb_interface *intf; @@ -447,18 +463,6 @@ struct uvc_streaming { __u8 last_fid; }; -struct uvc_video_device { - struct uvc_device *dev; - - struct list_head iterms; /* Input terminals */ - struct uvc_entity *oterm; /* Output terminal */ - struct uvc_entity *sterm; /* USB streaming terminal */ - struct uvc_entity *processing; - struct uvc_entity *selector; - struct list_head extensions; - struct mutex ctrl_mutex; -}; - enum uvc_device_state { UVC_DEV_DISCONNECTED = 1, }; @@ -481,8 +485,7 @@ struct uvc_device { __u32 clock_frequency; struct list_head entities; - - struct uvc_video_device video; + struct list_head chains; /* Video Streaming interfaces */ struct list_head streams; @@ -501,7 +504,7 @@ enum uvc_handle_state { }; struct uvc_fh { - struct uvc_video_device *video; + struct uvc_video_chain *chain; struct uvc_streaming *stream; enum uvc_handle_state state; }; @@ -619,9 +622,9 @@ extern int uvc_status_suspend(struct uvc_device *dev); extern int uvc_status_resume(struct uvc_device *dev); /* Controls */ -extern struct uvc_control *uvc_find_control(struct uvc_video_device *video, +extern struct uvc_control *uvc_find_control(struct uvc_video_chain *chain, __u32 v4l2_id, struct uvc_control_mapping **mapping); -extern int uvc_query_v4l2_ctrl(struct uvc_video_device *video, +extern int uvc_query_v4l2_ctrl(struct uvc_video_chain *chain, struct v4l2_queryctrl *v4l2_ctrl); extern int uvc_ctrl_add_info(struct uvc_control_info *info); @@ -631,23 +634,23 @@ extern void uvc_ctrl_cleanup_device(struct uvc_device *dev); extern int uvc_ctrl_resume_device(struct uvc_device *dev); extern void uvc_ctrl_init(void); -extern int uvc_ctrl_begin(struct uvc_video_device *video); -extern int __uvc_ctrl_commit(struct uvc_video_device *video, int rollback); -static inline int uvc_ctrl_commit(struct uvc_video_device *video) +extern int uvc_ctrl_begin(struct uvc_video_chain *chain); +extern int __uvc_ctrl_commit(struct uvc_video_chain *chain, int rollback); +static inline int uvc_ctrl_commit(struct uvc_video_chain *chain) { - return __uvc_ctrl_commit(video, 0); + return __uvc_ctrl_commit(chain, 0); } -static inline int uvc_ctrl_rollback(struct uvc_video_device *video) +static inline int uvc_ctrl_rollback(struct uvc_video_chain *chain) { - return __uvc_ctrl_commit(video, 1); + return __uvc_ctrl_commit(chain, 1); } -extern int uvc_ctrl_get(struct uvc_video_device *video, +extern int uvc_ctrl_get(struct uvc_video_chain *chain, struct v4l2_ext_control *xctrl); -extern int uvc_ctrl_set(struct uvc_video_device *video, +extern int uvc_ctrl_set(struct uvc_video_chain *chain, struct v4l2_ext_control *xctrl); -extern int uvc_xu_ctrl_query(struct uvc_video_device *video, +extern int uvc_xu_ctrl_query(struct uvc_video_chain *chain, struct uvc_xu_control *ctrl, int set); /* Utility functions */ -- cgit v1.2.3 From b2133bbb6784e940062cb5d074414242add4c58f Mon Sep 17 00:00:00 2001 From: Douglas Schilling Landgraf Date: Thu, 2 Jul 2009 13:52:46 -0300 Subject: cx18-fileops.c: Remove unnecessary semicolons From: Joe Perches Priority: normal Signed-off-by: Joe Perches Acked-by: Andy Walls Signed-off-by: Douglas Schilling Landgraf --- linux/drivers/media/video/cx18/cx18-fileops.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/cx18/cx18-fileops.c b/linux/drivers/media/video/cx18/cx18-fileops.c index 817bb9263..227c99f24 100644 --- a/linux/drivers/media/video/cx18/cx18-fileops.c +++ b/linux/drivers/media/video/cx18/cx18-fileops.c @@ -726,7 +726,7 @@ int cx18_v4l2_open(struct file *filp) int res; struct video_device *video_dev = video_devdata(filp); struct cx18_stream *s = video_get_drvdata(video_dev); - struct cx18 *cx = s->cx;; + struct cx18 *cx = s->cx; mutex_lock(&cx->serialize_lock); if (cx18_init_on_first_open(cx)) { -- cgit v1.2.3 From 5af690d071934a6ca068cb9e4967224eb9bba9eb Mon Sep 17 00:00:00 2001 From: Douglas Schilling Landgraf Date: Thu, 2 Jul 2009 15:57:09 -0300 Subject: Remove unnecessary semicolons From: Joe Perches Priority: normal Signed-off-by: Joe Perches CC: Patrick Boettcher CC: Steven Toth CC: Igor M. Liplianin CC: Srinivasa Deevi Signed-off-by: Douglas Schilling Landgraf --- linux/drivers/media/dvb/b2c2/flexcop-fe-tuner.c | 2 +- linux/drivers/media/dvb/dvb-usb/dib0700_devices.c | 2 +- linux/drivers/media/dvb/frontends/cx24123.c | 2 +- linux/drivers/media/dvb/frontends/dib0070.c | 2 +- linux/drivers/media/dvb/frontends/stv0900_sw.c | 2 +- linux/drivers/media/video/cx231xx/cx231xx-video.c | 4 ++-- linux/drivers/media/video/cx23885/cx23885.h | 2 +- 7 files changed, 8 insertions(+), 8 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/b2c2/flexcop-fe-tuner.c b/linux/drivers/media/dvb/b2c2/flexcop-fe-tuner.c index efb4a6c2b..bc370183e 100644 --- a/linux/drivers/media/dvb/b2c2/flexcop-fe-tuner.c +++ b/linux/drivers/media/dvb/b2c2/flexcop-fe-tuner.c @@ -410,7 +410,7 @@ static int skystar2_rev28_attach(struct flexcop_device *fc, if (!fc->fe) return 0; - i2c_tuner = cx24123_get_tuner_i2c_adapter(fc->fe);; + i2c_tuner = cx24123_get_tuner_i2c_adapter(fc->fe); if (!i2c_tuner) return 0; diff --git a/linux/drivers/media/dvb/dvb-usb/dib0700_devices.c b/linux/drivers/media/dvb/dvb-usb/dib0700_devices.c index eda025714..8ec98f6e0 100644 --- a/linux/drivers/media/dvb/dvb-usb/dib0700_devices.c +++ b/linux/drivers/media/dvb/dvb-usb/dib0700_devices.c @@ -310,7 +310,7 @@ static int stk7700d_tuner_attach(struct dvb_usb_adapter *adap) struct i2c_adapter *tun_i2c; tun_i2c = dib7000p_get_i2c_master(adap->fe, DIBX000_I2C_INTERFACE_TUNER, 1); return dvb_attach(mt2266_attach, adap->fe, tun_i2c, - &stk7700d_mt2266_config[adap->id]) == NULL ? -ENODEV : 0;; + &stk7700d_mt2266_config[adap->id]) == NULL ? -ENODEV : 0; } /* STK7700-PH: Digital/Analog Hybrid Tuner, e.h. Cinergy HT USB HE */ diff --git a/linux/drivers/media/dvb/frontends/cx24123.c b/linux/drivers/media/dvb/frontends/cx24123.c index f431f0c56..5fdc81b53 100644 --- a/linux/drivers/media/dvb/frontends/cx24123.c +++ b/linux/drivers/media/dvb/frontends/cx24123.c @@ -470,7 +470,7 @@ static int cx24123_set_symbolrate(struct cx24123_state *state, u32 srate) /* check if symbol rate is within limits */ if ((srate > state->frontend.ops.info.symbol_rate_max) || (srate < state->frontend.ops.info.symbol_rate_min)) - return -EOPNOTSUPP;; + return -EOPNOTSUPP; /* choose the sampling rate high enough for the required operation, while optimizing the power consumed by the demodulator */ diff --git a/linux/drivers/media/dvb/frontends/dib0070.c b/linux/drivers/media/dvb/frontends/dib0070.c index e9fab2d3e..7dd131fb3 100644 --- a/linux/drivers/media/dvb/frontends/dib0070.c +++ b/linux/drivers/media/dvb/frontends/dib0070.c @@ -168,7 +168,7 @@ static int dib0070_tune_digital(struct dvb_frontend *fe, struct dvb_frontend_par break; case BAND_SBAND: LO4_SET_VCO_HFDIV(lo4, 0, 0); - LO4_SET_CTRIM(lo4, 1);; + LO4_SET_CTRIM(lo4, 1); c = 1; break; case BAND_UHF: diff --git a/linux/drivers/media/dvb/frontends/stv0900_sw.c b/linux/drivers/media/dvb/frontends/stv0900_sw.c index a5a31536c..962fde143 100644 --- a/linux/drivers/media/dvb/frontends/stv0900_sw.c +++ b/linux/drivers/media/dvb/frontends/stv0900_sw.c @@ -1721,7 +1721,7 @@ static enum fe_stv0900_signal_type stv0900_dvbs1_acq_workaround(struct dvb_front s32 srate, demod_timeout, fec_timeout, freq1, freq0; - enum fe_stv0900_signal_type signal_type = STV0900_NODATA;; + enum fe_stv0900_signal_type signal_type = STV0900_NODATA; switch (demod) { case STV0900_DEMOD_1: diff --git a/linux/drivers/media/video/cx231xx/cx231xx-video.c b/linux/drivers/media/video/cx231xx/cx231xx-video.c index e00edd0aa..7e5bfcc94 100644 --- a/linux/drivers/media/video/cx231xx/cx231xx-video.c +++ b/linux/drivers/media/video/cx231xx/cx231xx-video.c @@ -923,8 +923,8 @@ static int vidioc_g_fmt_vid_cap(struct file *file, void *priv, f->fmt.pix.width = dev->width; f->fmt.pix.height = dev->height; - f->fmt.pix.pixelformat = dev->format->fourcc;; - f->fmt.pix.bytesperline = (dev->width * dev->format->depth + 7) >> 3;; + f->fmt.pix.pixelformat = dev->format->fourcc; + f->fmt.pix.bytesperline = (dev->width * dev->format->depth + 7) >> 3; f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * dev->height; f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; diff --git a/linux/drivers/media/video/cx23885/cx23885.h b/linux/drivers/media/video/cx23885/cx23885.h index aecaca4b4..fe3feb001 100644 --- a/linux/drivers/media/video/cx23885/cx23885.h +++ b/linux/drivers/media/video/cx23885/cx23885.h @@ -396,7 +396,7 @@ struct sram_channel { u32 cmds_start; u32 ctrl_start; u32 cdt; - u32 fifo_start;; + u32 fifo_start; u32 fifo_size; u32 ptr1_reg; u32 ptr2_reg; -- cgit v1.2.3 From 245f6c63367b27a65d9c74ed93f133dfa0684d7b Mon Sep 17 00:00:00 2001 From: Douglas Schilling Landgraf Date: Thu, 2 Jul 2009 16:02:20 -0300 Subject: ivtv-driver.c: Remove unnecessary semicolons From: Joe Perches Priority: normal Signed-off-by: Joe Perches CC: Hans Verkuil Signed-off-by: Douglas Schilling Landgraf --- linux/drivers/media/video/ivtv/ivtv-driver.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/ivtv/ivtv-driver.c b/linux/drivers/media/video/ivtv/ivtv-driver.c index 9f91838d7..c4cae0651 100644 --- a/linux/drivers/media/video/ivtv/ivtv-driver.c +++ b/linux/drivers/media/video/ivtv/ivtv-driver.c @@ -218,7 +218,7 @@ MODULE_PARM_DESC(ivtv_yuv_mode, "\t\t\tDefault: 0 (interlaced)"); MODULE_PARM_DESC(ivtv_yuv_threshold, "If ivtv_yuv_mode is 2 (auto) then playback content as\n\t\tprogressive if src height <= ivtv_yuvthreshold\n" - "\t\t\tDefault: 480");; + "\t\t\tDefault: 480"); MODULE_PARM_DESC(enc_mpg_buffers, "Encoder MPG Buffers (in MB)\n" "\t\t\tDefault: " __stringify(IVTV_DEFAULT_ENC_MPG_BUFFERS)); -- cgit v1.2.3 From a9ce895e4fbe314a0e7d2b967f576367a8c38acb Mon Sep 17 00:00:00 2001 From: Douglas Schilling Landgraf Date: Thu, 2 Jul 2009 16:09:25 -0300 Subject: remove redundant tests on unsigned From: Roel Kluin input, inp and i are unsigned. When negative they are wrapped and caught by the other test. Priority: normal Signed-off-by: Roel Kluin CC: Andy Walls Signed-off-by: Douglas Schilling Landgraf --- linux/drivers/media/dvb/ttpci/av7110_v4l.c | 2 +- linux/drivers/media/video/cx18/cx18-ioctl.c | 2 +- linux/drivers/media/video/saa7134/saa7134-video.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/ttpci/av7110_v4l.c b/linux/drivers/media/dvb/ttpci/av7110_v4l.c index ce64c6214..8986d967d 100644 --- a/linux/drivers/media/dvb/ttpci/av7110_v4l.c +++ b/linux/drivers/media/dvb/ttpci/av7110_v4l.c @@ -490,7 +490,7 @@ static int vidioc_s_input(struct file *file, void *fh, unsigned int input) if (!av7110->analog_tuner_flags) return 0; - if (input < 0 || input >= 4) + if (input >= 4) return -EINVAL; av7110->current_input = input; diff --git a/linux/drivers/media/video/cx18/cx18-ioctl.c b/linux/drivers/media/video/cx18/cx18-ioctl.c index 65e2ef425..107b57880 100644 --- a/linux/drivers/media/video/cx18/cx18-ioctl.c +++ b/linux/drivers/media/video/cx18/cx18-ioctl.c @@ -613,7 +613,7 @@ int cx18_s_input(struct file *file, void *fh, unsigned int inp) if (ret) return ret; - if (inp < 0 || inp >= cx->nof_inputs) + if (inp >= cx->nof_inputs) return -EINVAL; if (inp == cx->active_input) { diff --git a/linux/drivers/media/video/saa7134/saa7134-video.c b/linux/drivers/media/video/saa7134/saa7134-video.c index 4212c4ec8..e7f78fcb8 100644 --- a/linux/drivers/media/video/saa7134/saa7134-video.c +++ b/linux/drivers/media/video/saa7134/saa7134-video.c @@ -1797,7 +1797,7 @@ static int saa7134_s_input(struct file *file, void *priv, unsigned int i) if (0 != err) return err; - if (i < 0 || i >= SAA7134_INPUT_MAX) + if (i >= SAA7134_INPUT_MAX) return -EINVAL; if (NULL == card_in(dev, i).name) return -EINVAL; -- cgit v1.2.3 From 9a36522fc136e81e75184ee8a62f7376f457e810 Mon Sep 17 00:00:00 2001 From: Douglas Schilling Landgraf Date: Thu, 2 Jul 2009 16:17:28 -0300 Subject: mt312: Fix checkpatch warnings From: Matthias Schwarzott This patch fixes some checkpatch warnings in mt312-driver. Priority: normal Signed-off-by: Matthias Schwarzott Signed-off-by: Douglas Schilling Landgraf --- linux/drivers/media/dvb/frontends/mt312.c | 7 ++++--- linux/drivers/media/dvb/frontends/zl10036.c | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/frontends/mt312.c b/linux/drivers/media/dvb/frontends/mt312.c index a621f7279..071328d7b 100644 --- a/linux/drivers/media/dvb/frontends/mt312.c +++ b/linux/drivers/media/dvb/frontends/mt312.c @@ -85,7 +85,7 @@ static int mt312_read(struct mt312_state *state, const enum mt312_reg_addr reg, int i; dprintk("R(%d):", reg & 0x7f); for (i = 0; i < count; i++) - printk(" %02x", buf[i]); + printk(KERN_CONT " %02x", buf[i]); printk("\n"); } @@ -103,7 +103,7 @@ static int mt312_write(struct mt312_state *state, const enum mt312_reg_addr reg, int i; dprintk("W(%d):", reg & 0x7f); for (i = 0; i < count; i++) - printk(" %02x", src[i]); + printk(KERN_CONT " %02x", src[i]); printk("\n"); } @@ -744,7 +744,8 @@ static struct dvb_frontend_ops mt312_ops = { .type = FE_QPSK, .frequency_min = 950000, .frequency_max = 2150000, - .frequency_stepsize = (MT312_PLL_CLK / 1000) / 128, /* FIXME: adjust freq to real used xtal */ + /* FIXME: adjust freq to real used xtal */ + .frequency_stepsize = (MT312_PLL_CLK / 1000) / 128, .symbol_rate_min = MT312_SYS_CLK / 128, /* FIXME as above */ .symbol_rate_max = MT312_SYS_CLK / 2, .caps = diff --git a/linux/drivers/media/dvb/frontends/zl10036.c b/linux/drivers/media/dvb/frontends/zl10036.c index 67cdb056f..ce2a2703b 100644 --- a/linux/drivers/media/dvb/frontends/zl10036.c +++ b/linux/drivers/media/dvb/frontends/zl10036.c @@ -29,7 +29,7 @@ #include #include -#include +#include #include "compat.h" #include "zl10036.h" -- cgit v1.2.3 From ecb01359f35d66a31d65002a40bee45b64cec4d7 Mon Sep 17 00:00:00 2001 From: Douglas Schilling Landgraf Date: Thu, 2 Jul 2009 16:54:14 -0300 Subject: adv7343: remove unused #include From: Huang Weiyi Remove unused #include 's in drivers/media/video/adv7343.c. Priority: normal Signed-off-by: Huang Weiyi CC: Chaithrika U S Signed-off-by: Douglas Schilling Landgraf --- linux/drivers/media/video/adv7343.c | 1 - 1 file changed, 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/adv7343.c b/linux/drivers/media/video/adv7343.c index 30f5caf5d..df26f2fe4 100644 --- a/linux/drivers/media/video/adv7343.c +++ b/linux/drivers/media/video/adv7343.c @@ -24,7 +24,6 @@ #include #include #include -#include #include #include -- cgit v1.2.3 From 7f7e5771a2066c2e13c278643b4fe12c4a3e228f Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 2 Jul 2009 17:07:32 -0300 Subject: v4l2-ioctl: avoid flooding log with unasked debug messages From: Mauro Carvalho Chehab Thanks to Hans Verkuil for pointing this issue on my last patch. Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/v4l2-ioctl.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/v4l2-ioctl.c b/linux/drivers/media/video/v4l2-ioctl.c index 625fe7698..80c94dc5a 100644 --- a/linux/drivers/media/video/v4l2-ioctl.c +++ b/linux/drivers/media/video/v4l2-ioctl.c @@ -43,6 +43,12 @@ printk(KERN_DEBUG "%s: " fmt, vfd->name, ## arg);\ } while (0) +#define dbgarg3(fmt, arg...) \ + do { \ + if (vfd->debug & V4L2_DEBUG_IOCTL_ARG) \ + printk(KERN_CONT "%s: " fmt, vfd->name, ## arg);\ + } while (0) + /* Zero out the end of the struct pointed to by p. Everthing after, but * not including, the specified field is cleared. */ #define CLEAR_AFTER_FIELD(p, field) \ @@ -1727,20 +1733,20 @@ static long __video_do_ioctl(struct file *file, p->type); switch (p->type) { case V4L2_FRMSIZE_TYPE_DISCRETE: - printk("width = %d, height=%d\n", + dbgarg3("width = %d, height=%d\n", p->discrete.width, p->discrete.height); break; case V4L2_FRMSIZE_TYPE_STEPWISE: - printk("min %dx%d, max %dx%d, step %dx%d\n", + dbgarg3("min %dx%d, max %dx%d, step %dx%d\n", p->stepwise.min_width, p->stepwise.min_height, p->stepwise.step_width, p->stepwise.step_height, p->stepwise.max_width, p->stepwise.max_height); break; case V4L2_FRMSIZE_TYPE_CONTINUOUS: - printk("continuous\n"); + dbgarg3("continuous\n"); break; default: - printk("- Unknown type!\n"); + dbgarg3("- Unknown type!\n"); } break; -- cgit v1.2.3 From 0e9def6497f0f045e2740fa24b0864b260678959 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 2 Jul 2009 17:34:04 -0300 Subject: em28xx-video: fix VIDIOC_G_FMT and VIDIOC_ENUMFMT with webcams From: Mauro Carvalho Chehab Webcams have different constraints than other v4l devices. This patch makes the format ioctls to behave better. It also fixes a bug at open() handler, that were always reseting resolution to the maximum available one. Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/em28xx/em28xx-video.c | 79 +++++++++++++++---------- 1 file changed, 49 insertions(+), 30 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/em28xx/em28xx-video.c b/linux/drivers/media/video/em28xx/em28xx-video.c index 3c47acee3..157996e5f 100644 --- a/linux/drivers/media/video/em28xx/em28xx-video.c +++ b/linux/drivers/media/video/em28xx/em28xx-video.c @@ -788,13 +788,41 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, return 0; } +static int em28xx_set_video_format(struct em28xx *dev, unsigned int fourcc, + unsigned width, unsigned height) +{ + struct em28xx_fmt *fmt; + + /* FIXME: This is the only supported fmt */ + if (dev->board.is_27xx) { + fourcc = V4L2_PIX_FMT_RGB565; + width = 640; + height = 480; + } + + fmt = format_by_fourcc(fourcc); + if (!fmt) + return -EINVAL; + + dev->format = fmt; + dev->width = width; + dev->height = height; + + /* set new image size */ + get_scale(dev, dev->width, dev->height, &dev->hscale, &dev->vscale); + + em28xx_set_alternate(dev); + em28xx_resolution_set(dev); + + return 0; +} + static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) { struct em28xx_fh *fh = priv; struct em28xx *dev = fh->dev; int rc; - struct em28xx_fmt *fmt; rc = check_dev(dev); if (rc < 0) @@ -802,18 +830,8 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, mutex_lock(&dev->lock); - /* FIXME: This is the only supported fmt */ - if (dev->board.is_27xx) - f->fmt.pix.pixelformat = V4L2_PIX_FMT_RGB565; - vidioc_try_fmt_vid_cap(file, priv, f); - fmt = format_by_fourcc(f->fmt.pix.pixelformat); - if (!fmt) { - rc = -EINVAL; - goto out; - } - if (videobuf_queue_is_busy(&fh->vb_vidq)) { em28xx_errdev("%s queue busy\n", __func__); rc = -EBUSY; @@ -826,16 +844,8 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, goto out; } - /* set new image size */ - dev->width = f->fmt.pix.width; - dev->height = f->fmt.pix.height; - dev->format = fmt; - get_scale(dev, dev->width, dev->height, &dev->hscale, &dev->vscale); - - em28xx_set_alternate(dev); - em28xx_resolution_set(dev); - - rc = 0; + rc = em28xx_set_video_format(dev, f->fmt.pix.pixelformat, + f->fmt.pix.width, f->fmt.pix.height); out: mutex_unlock(&dev->lock); @@ -1428,9 +1438,24 @@ static int vidioc_querycap(struct file *file, void *priv, static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, struct v4l2_fmtdesc *f) { + struct em28xx_fh *fh = priv; + struct em28xx *dev = fh->dev; + if (unlikely(f->index >= ARRAY_SIZE(format))) return -EINVAL; + if (dev->board.is_27xx) { + struct em28xx_fmt *fmt; + if (f->index) + return -EINVAL; + + f->pixelformat = V4L2_PIX_FMT_RGB565; + fmt = format_by_fourcc(f->pixelformat); + strlcpy(f->description, fmt->name, sizeof(f->description)); + + return 0; + } + strlcpy(f->description, format[f->index].name, sizeof(f->description)); f->pixelformat = format[f->index].fourcc; @@ -1726,11 +1751,6 @@ static int em28xx_v4l2_open(struct file *filp) filp->private_data = fh; if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE && dev->users == 0) { - dev->width = norm_maxw(dev); - dev->height = norm_maxh(dev); - dev->hscale = 0; - dev->vscale = 0; - em28xx_set_mode(dev, EM28XX_ANALOG_MODE); em28xx_set_alternate(dev); em28xx_resolution_set(dev); @@ -2084,15 +2104,14 @@ int em28xx_register_analog_devices(struct em28xx *dev) /* set default norm */ dev->norm = em28xx_video_template.current_norm; - dev->width = norm_maxw(dev); - dev->height = norm_maxh(dev); dev->interlaced = EM28XX_INTERLACED_DEFAULT; - dev->hscale = 0; - dev->vscale = 0; dev->ctl_input = 0; /* Analog specific initialization */ dev->format = &format[0]; + em28xx_set_video_format(dev, format[0].fourcc, + norm_maxw(dev), norm_maxh(dev)); + video_mux(dev, dev->ctl_input); /* Audio defaults */ -- cgit v1.2.3 From a560be0d3b4e9eeb8ece7539da7d299d29e4b8d9 Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Thu, 2 Jul 2009 22:08:59 -0400 Subject: ivtv: Add card entry for AVerMedia UltraTV 1500 MCE (M113 variant) From: Andy Walls Priority: normal Signed-off-by: Andy Walls --- linux/drivers/media/video/ivtv/ivtv-cards.c | 44 ++++++++++++++++++++++++++++ linux/drivers/media/video/ivtv/ivtv-cards.h | 3 +- linux/drivers/media/video/ivtv/ivtv-driver.c | 1 + 3 files changed, 47 insertions(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/ivtv/ivtv-cards.c b/linux/drivers/media/video/ivtv/ivtv-cards.c index 2883c8780..553a314fa 100644 --- a/linux/drivers/media/video/ivtv/ivtv-cards.c +++ b/linux/drivers/media/video/ivtv/ivtv-cards.c @@ -1016,6 +1016,50 @@ static const struct ivtv_card ivtv_card_aver_pvr150 = { /* ------------------------------------------------------------------------- */ +/* AVerMedia UltraTV 1500 MCE (newer non-cx88 version, M113 variant) card */ + +static const struct ivtv_card_pci_info ivtv_pci_aver_ultra1500mce[] = { + { PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_AVERMEDIA, 0xc019 }, + { 0, 0, 0 } +}; + +static const struct ivtv_card ivtv_card_aver_ultra1500mce = { + .type = IVTV_CARD_AVER_ULTRA1500MCE, + .name = "AVerMedia UltraTV 1500 MCE / AVerTV M113", + .v4l2_capabilities = IVTV_CAP_ENCODER, + .hw_video = IVTV_HW_CX25840, + .hw_audio = IVTV_HW_CX25840, + .hw_audio_ctrl = IVTV_HW_CX25840, + .hw_muxer = IVTV_HW_GPIO, + .hw_all = IVTV_HW_CX25840 | IVTV_HW_TUNER | + IVTV_HW_WM8739 | IVTV_HW_GPIO, + .video_inputs = { + { IVTV_CARD_INPUT_VID_TUNER, 0, CX25840_COMPOSITE2 }, + { IVTV_CARD_INPUT_SVIDEO1, 1, + CX25840_SVIDEO_LUMA3 | CX25840_SVIDEO_CHROMA4 }, + { IVTV_CARD_INPUT_COMPOSITE1, 1, CX25840_COMPOSITE1 }, + }, + .audio_inputs = { + { IVTV_CARD_INPUT_AUD_TUNER, CX25840_AUDIO5, 0 }, + { IVTV_CARD_INPUT_LINE_IN1, CX25840_AUDIO_SERIAL, 1 }, + }, + .radio_input = { IVTV_CARD_INPUT_AUD_TUNER, CX25840_AUDIO_SERIAL, 2 }, + /* The 74HC4502 Dual 4:1 multiplexer is controlled by 2 GPIO lines */ + .gpio_init = { .direction = 0xc000, .initial_value = 0 }, + .gpio_audio_input = { .mask = 0xc000, + .tuner = 0x0000, + .linein = 0x4000, + .radio = 0x8000 }, + .tuners = { + /* The UltraTV 1500 MCE has a Philips FM1236 MK5 TV/FM tuner */ + { .std = V4L2_STD_MN, .tuner = TUNER_PHILIPS_FM1236_MK3 }, + }, + .pci_list = ivtv_pci_aver_ultra1500mce, + .i2c = &ivtv_i2c_std, +}; + +/* ------------------------------------------------------------------------- */ + /* AVerMedia EZMaker PCI Deluxe card */ static const struct ivtv_card_pci_info ivtv_pci_aver_ezmaker[] = { diff --git a/linux/drivers/media/video/ivtv/ivtv-cards.h b/linux/drivers/media/video/ivtv/ivtv-cards.h index 0b8fe85fb..e99a0a255 100644 --- a/linux/drivers/media/video/ivtv/ivtv-cards.h +++ b/linux/drivers/media/video/ivtv/ivtv-cards.h @@ -50,7 +50,8 @@ #define IVTV_CARD_AVER_EZMAKER 23 /* AVerMedia EZMaker PCI Deluxe */ #define IVTV_CARD_AVER_M104 24 /* AverMedia M104 miniPCI card */ #define IVTV_CARD_BUFFALO_MV5L 25 /* Buffalo PC-MV5L/PCI card */ -#define IVTV_CARD_LAST 25 +#define IVTV_CARD_AVER_ULTRA1500MCE 26 /* AVerMedia UltraTV 1500 MCE */ +#define IVTV_CARD_LAST 26 /* Variants of existing cards but with the same PCI IDs. The driver detects these based on other device information. diff --git a/linux/drivers/media/video/ivtv/ivtv-driver.c b/linux/drivers/media/video/ivtv/ivtv-driver.c index 9f91838d7..394af7221 100644 --- a/linux/drivers/media/video/ivtv/ivtv-driver.c +++ b/linux/drivers/media/video/ivtv/ivtv-driver.c @@ -186,6 +186,7 @@ MODULE_PARM_DESC(cardtype, "\t\t\t24 = AverMedia EZMaker PCI Deluxe\n" "\t\t\t25 = AverMedia M104 (not yet working)\n" "\t\t\t26 = Buffalo PC-MV5L/PCI\n" + "\t\t\t27 = AVerMedia UltraTV 1500 MCE\n" "\t\t\t 0 = Autodetect (default)\n" "\t\t\t-1 = Ignore this card\n\t\t"); MODULE_PARM_DESC(pal, "Set PAL standard: BGH, DK, I, M, N, Nc, 60"); -- cgit v1.2.3 From 5fd0c79afbb036e1e2147505dd8902716e8ed08a Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 3 Jul 2009 02:54:18 -0300 Subject: em28xx: Allow its usage with other different output formats From: Mauro Carvalho Chehab Discovered the bug that were limiting the output format to just RGB565. Now, it is possible to output image at Bayer format (the original one, as generated by Silvercrest sensor, and two others), and also on YUY. Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/em28xx/em28xx-core.c | 1 - linux/drivers/media/video/em28xx/em28xx-video.c | 67 +++++++++---------------- 2 files changed, 25 insertions(+), 43 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 7ad8edff2..1033824bd 100644 --- a/linux/drivers/media/video/em28xx/em28xx-core.c +++ b/linux/drivers/media/video/em28xx/em28xx-core.c @@ -655,7 +655,6 @@ int em28xx_set_outfmt(struct em28xx *dev) if (dev->board.is_27xx) { vinmode = 0x0d; vinctl = 0x00; - outfmt = 0x24; } else { vinmode = 0x10; vinctl = 0x11; diff --git a/linux/drivers/media/video/em28xx/em28xx-video.c b/linux/drivers/media/video/em28xx/em28xx-video.c index 157996e5f..fff90faca 100644 --- a/linux/drivers/media/video/em28xx/em28xx-video.c +++ b/linux/drivers/media/video/em28xx/em28xx-video.c @@ -90,52 +90,52 @@ MODULE_PARM_DESC(video_debug, "enable debug messages [video]"); /* supported video standards */ static struct em28xx_fmt format[] = { { - .name = "16bpp YUY2, 4:2:2, packed", + .name = "16 bpp YUY2, 4:2:2, packed", .fourcc = V4L2_PIX_FMT_YUYV, .depth = 16, .reg = EM28XX_OUTFMT_YUV422_Y0UY1V, }, { - .name = "16 bpp RGB, le", + .name = "16 bpp RGB 565, LE", .fourcc = V4L2_PIX_FMT_RGB565, .depth = 16, - .reg = EM28XX_OUTFMT_YUV211, -#if 0 - /* TODO: need tests and newer definitions */ + .reg = EM28XX_OUTFMT_RGB_16_656, }, { - .name = "Y1-U-Y0-V, 16 bpp", - .fourcc = 0, - .depth = 16, - .reg = EM28XX_OUTFMT_YUV422_Y1UY0V + .name = "8 bpp Bayer BGBG..GRGR", + .fourcc = V4L2_PIX_FMT_SBGGR8, + .depth = 8, + .reg = EM28XX_OUTFMT_RGB_8_BGBG, }, { - .name = "YUV211, 8 bpp", - .fourcc = 0, + .name = "8 bpp Bayer GRGR..BGBG", + .fourcc = V4L2_PIX_FMT_SGRBG8, .depth = 8, - .reg = EM28XX_OUTFMT_YUV211, + .reg = EM28XX_OUTFMT_RGB_8_GRGR, }, { - .name = "YUV411, 12 bpp", - .fourcc = 0, + .name = "8 bpp Bayer GBGB..RGRG", + .fourcc = V4L2_PIX_FMT_SGBRG8, + .depth = 8, + .reg = EM28XX_OUTFMT_RGB_8_GBGB, + }, { + .name = "12 bpp YUV411", + .fourcc = V4L2_PIX_FMT_YUV411P, .depth = 12, .reg = EM28XX_OUTFMT_YUV411, +#if 0 + /* TODO: Those formats need test and fourcc entries */ }, { - .name = "RGB, 8bit RGRG", + .name = "Bayer, 8bit RGRG..GBGB", .fourcc = 0, .depth = 8, - .reg = EM28XX_OUTFMT_YUV211, + .reg = EM28XX_OUTFMT_RGB_8_GBGB, }, { - .name = "RGB, 8bit GRGR", + .name = "Y1-U-Y0-V, 16 bpp", .fourcc = 0, - .depth = 8, - .reg = EM28XX_OUTFMT_YUV211, + .depth = 16, + .reg = EM28XX_OUTFMT_YUV422_Y1UY0V }, { - .name = "RGB, 8bit GBGB", + .name = "YUV211, 8 bpp", .fourcc = 0, .depth = 8, .reg = EM28XX_OUTFMT_YUV211, - }, { - .name = "RGB, 8bit BGBG", - .fourcc = 0, - .depth = 8, - .reg = EM28XX_OUTFMT_RGB_8_BGBG, #endif }, }; @@ -741,10 +741,6 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, unsigned int hscale, vscale; struct em28xx_fmt *fmt; - /* FIXME: This is the only supported fmt */ - if (dev->board.is_27xx) - f->fmt.pix.pixelformat = V4L2_PIX_FMT_RGB565; - fmt = format_by_fourcc(f->fmt.pix.pixelformat); if (!fmt) { em28xx_videodbg("Fourcc format (%08x) invalid.\n", @@ -795,7 +791,6 @@ static int em28xx_set_video_format(struct em28xx *dev, unsigned int fourcc, /* FIXME: This is the only supported fmt */ if (dev->board.is_27xx) { - fourcc = V4L2_PIX_FMT_RGB565; width = 640; height = 480; } @@ -1444,18 +1439,6 @@ static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, if (unlikely(f->index >= ARRAY_SIZE(format))) return -EINVAL; - if (dev->board.is_27xx) { - struct em28xx_fmt *fmt; - if (f->index) - return -EINVAL; - - f->pixelformat = V4L2_PIX_FMT_RGB565; - fmt = format_by_fourcc(f->pixelformat); - strlcpy(f->description, fmt->name, sizeof(f->description)); - - return 0; - } - strlcpy(f->description, format[f->index].name, sizeof(f->description)); f->pixelformat = format[f->index].fourcc; -- cgit v1.2.3 From 9f2cb39e1fc931d1c94ebc93e064b9dc24b6df38 Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Fri, 3 Jul 2009 10:30:27 -0400 Subject: cx18: Update Yuan MPC-718 card entry with better information and guesses From: Andy Walls Priority: normal Signed-off-by: Andy Walls --- linux/drivers/media/video/cx18/cx18-cards.c | 34 +++++++++++++++++++---------- 1 file changed, 22 insertions(+), 12 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/cx18/cx18-cards.c b/linux/drivers/media/video/cx18/cx18-cards.c index fa755a982..adf44db58 100644 --- a/linux/drivers/media/video/cx18/cx18-cards.c +++ b/linux/drivers/media/video/cx18/cx18-cards.c @@ -198,11 +198,14 @@ static const struct cx18_card_pci_info cx18_pci_mpc718[] = { static const struct cx18_card cx18_card_mpc718 = { .type = CX18_CARD_YUAN_MPC718, - .name = "Yuan MPC718", - .comment = "Analog video capture works; some audio line in may not.\n", + .name = "Yuan MPC718 MiniPCI DVB-T/Analog", + .comment = "Experimenters needed for device to work well.\n" + "\tTo help, mail the ivtv-devel list (www.ivtvdriver.org).\n", .v4l2_capabilities = CX18_CAP_ENCODER, .hw_audio_ctrl = CX18_HW_418_AV, - .hw_all = CX18_HW_418_AV | CX18_HW_TUNER | CX18_HW_GPIO_RESET_CTRL, + .hw_muxer = CX18_HW_GPIO_MUX, + .hw_all = CX18_HW_418_AV | CX18_HW_TUNER | CX18_HW_GPIO_MUX | + CX18_HW_GPIO_RESET_CTRL, .video_inputs = { { CX18_CARD_INPUT_VID_TUNER, 0, CX18_AV_COMPOSITE2 }, { CX18_CARD_INPUT_SVIDEO1, 1, @@ -211,27 +214,34 @@ static const struct cx18_card cx18_card_mpc718 = { { CX18_CARD_INPUT_SVIDEO2, 2, CX18_AV_SVIDEO_LUMA7 | CX18_AV_SVIDEO_CHROMA8 }, { CX18_CARD_INPUT_COMPOSITE2, 2, CX18_AV_COMPOSITE6 }, - { CX18_CARD_INPUT_COMPOSITE3, 2, CX18_AV_COMPOSITE3 }, }, .audio_inputs = { { CX18_CARD_INPUT_AUD_TUNER, CX18_AV_AUDIO5, 0 }, - { CX18_CARD_INPUT_LINE_IN1, CX18_AV_AUDIO_SERIAL1, 0 }, - { CX18_CARD_INPUT_LINE_IN2, CX18_AV_AUDIO_SERIAL1, 0 }, + { CX18_CARD_INPUT_LINE_IN1, CX18_AV_AUDIO_SERIAL1, 1 }, + { CX18_CARD_INPUT_LINE_IN2, CX18_AV_AUDIO_SERIAL2, 1 }, }, - .radio_input = { CX18_CARD_INPUT_AUD_TUNER, CX18_AV_AUDIO_SERIAL1, 0 }, .tuners = { /* XC3028 tuner */ { .std = V4L2_STD_ALL, .tuner = TUNER_XC2028 }, }, + /* FIXME - the FM radio is just a guess and driver doesn't use SIF */ + .radio_input = { CX18_CARD_INPUT_AUD_TUNER, CX18_AV_AUDIO5, 2 }, .ddr = { - /* Probably Samsung K4D263238G-VC33 memory */ - .chip_config = 0x003, - .refresh = 0x30c, - .timing1 = 0x23230b73, - .timing2 = 0x08, + /* Hynix HY5DU283222B DDR RAM */ + .chip_config = 0x303, + .refresh = 0x3bd, + .timing1 = 0x36320966, + .timing2 = 0x1f, .tune_lane = 0, .initial_emrs = 2, }, + .gpio_init.initial_value = 0x1, + .gpio_init.direction = 0x3, + /* FIXME - these GPIO's are just guesses */ + .gpio_audio_input = { .mask = 0x3, + .tuner = 0x1, + .linein = 0x3, + .radio = 0x1 }, .xceive_pin = 0, .pci_list = cx18_pci_mpc718, .i2c = &cx18_i2c_std, -- cgit v1.2.3 From 249b5a4539777b7bbc76ce4ce3b7207113098925 Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Fri, 3 Jul 2009 10:54:40 -0400 Subject: cx18: Add DVB-T support for Yuan MPC-718 cards with an MT352 or ZL10353 From: Andy Walls Add DVB-T support for Yuan MPC-718 cards with an MT352 or ZL10353 demodulator. There are apparently some units with a DiBcom demodulator which could be supported by one of the dib7000 modules - but this is not implemented in the cx18 driver (yet). Due to lack of porgramming details for the MT352 and the mt352 module requiring a "demod_init" function, a "firmware" must be obtained and loaded to get DVB-T working for Yuan MPC-718 cards with an MT352. Priority: normal Tested-by: Steve Firth Signed-off-by: Andy Walls --- linux/drivers/media/video/cx18/cx18-cards.c | 4 +- linux/drivers/media/video/cx18/cx18-dvb.c | 160 ++++++++++++++++++++++++++++ 2 files changed, 162 insertions(+), 2 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/cx18/cx18-cards.c b/linux/drivers/media/video/cx18/cx18-cards.c index adf44db58..d9a407681 100644 --- a/linux/drivers/media/video/cx18/cx18-cards.c +++ b/linux/drivers/media/video/cx18/cx18-cards.c @@ -204,8 +204,8 @@ static const struct cx18_card cx18_card_mpc718 = { .v4l2_capabilities = CX18_CAP_ENCODER, .hw_audio_ctrl = CX18_HW_418_AV, .hw_muxer = CX18_HW_GPIO_MUX, - .hw_all = CX18_HW_418_AV | CX18_HW_TUNER | CX18_HW_GPIO_MUX | - CX18_HW_GPIO_RESET_CTRL, + .hw_all = CX18_HW_418_AV | CX18_HW_TUNER | + CX18_HW_GPIO_MUX | CX18_HW_DVB | CX18_HW_GPIO_RESET_CTRL, .video_inputs = { { CX18_CARD_INPUT_VID_TUNER, 0, CX18_AV_COMPOSITE2 }, { CX18_CARD_INPUT_SVIDEO1, 1, diff --git a/linux/drivers/media/video/cx18/cx18-dvb.c b/linux/drivers/media/video/cx18/cx18-dvb.c index 6ea3fe623..51a0c33b2 100644 --- a/linux/drivers/media/video/cx18/cx18-dvb.c +++ b/linux/drivers/media/video/cx18/cx18-dvb.c @@ -30,6 +30,10 @@ #include "s5h1409.h" #include "mxl5005s.h" #include "zl10353.h" + +#include +#include "mt352.h" +#include "mt352_priv.h" #include "tuner-xc2028.h" DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); @@ -38,6 +42,11 @@ DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); #define CX18_CLOCK_ENABLE2 0xc71024 #define CX18_DMUX_CLK_MASK 0x0080 +/* + * CX18_CARD_HVR_1600_ESMT + * CX18_CARD_HVR_1600_SAMSUNG + */ + static struct mxl5005s_config hauppauge_hvr1600_tuner = { .i2c_address = 0xC6 >> 1, .if_freq = IF_FREQ_5380000HZ, @@ -65,6 +74,9 @@ static struct s5h1409_config hauppauge_hvr1600_config = { .mpeg_timing = S5H1409_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK }; +/* + * CX18_CARD_LEADTEK_DVR3100H + */ /* Information/confirmation of proper config values provided by Terry Wu */ static struct zl10353_config leadtek_dvr3100h_demod = { .demod_address = 0x1e >> 1, /* Datasheet suggested straps */ @@ -74,6 +86,121 @@ static struct zl10353_config leadtek_dvr3100h_demod = { .disable_i2c_gate_ctrl = 1, /* Disable the I2C gate */ }; +/* + * CX18_CARD_YUAN_MPC718 + */ +/* + * Due to + * + * 1. an absence of information on how to prgram the MT352 + * 2. the Linux mt352 module pushing MT352 initialzation off onto us here + * + * We have to use an init sequence that *you* must extract from the Windows + * driver (yuanrap.sys) and which we load as a firmware. + * + * If someone can provide me with a Zarlink MT352 (Intel CE6352?) Design Manual + * with chip programming details, then I can remove this annoyance. + */ +static int yuan_mpc718_mt352_reqfw(struct cx18_stream *stream, + const struct firmware **fw) +{ + struct cx18 *cx = stream->cx; + const char *fn = "dvb-cx18-mpc718-mt352.fw"; + int ret; + + ret = request_firmware(fw, fn, &cx->pci_dev->dev); + if (ret) + CX18_ERR("Unable to open firmware file %s\n", fn); + else { + size_t sz = (*fw)->size; + if (sz < 2 || sz > 64 || (sz % 2) != 0) { + CX18_ERR("Firmware %s has a bad size: %lu bytes\n", + fn, (unsigned long) sz); + ret = -EILSEQ; + release_firmware(*fw); + *fw = NULL; + } + } + + if (ret) { + CX18_ERR("The MPC718 board variant with the MT352 DVB-T" + "demodualtor will not work without it\n"); + CX18_ERR("Run 'linux/Documentation/dvb/get_dvb_firmware " + "mpc718' if you need the firmware\n"); + } + return ret; +} + +static int yuan_mpc718_mt352_init(struct dvb_frontend *fe) +{ + struct cx18_dvb *dvb = container_of(fe->dvb, + struct cx18_dvb, dvb_adapter); + struct cx18_stream *stream = container_of(dvb, struct cx18_stream, dvb); + const struct firmware *fw = NULL; + int ret; + int i; + u8 buf[3]; + + ret = yuan_mpc718_mt352_reqfw(stream, &fw); + if (ret) + return ret; + + /* Loop through all the register-value pairs in the firmware file */ + for (i = 0; i < fw->size; i += 2) { + buf[0] = fw->data[i]; + /* Intercept a few registers we want to set ourselves */ + switch (buf[0]) { + case TRL_NOMINAL_RATE_0: + /* Set our custom OFDM bandwidth in the case below */ + break; + case TRL_NOMINAL_RATE_1: + /* 6 MHz: 64/7 * 6/8 / 20.48 * 2^16 = 0x55b6.db6 */ + /* 7 MHz: 64/7 * 7/8 / 20.48 * 2^16 = 0x6400 */ + /* 8 MHz: 64/7 * 8/8 / 20.48 * 2^16 = 0x7249.249 */ + buf[1] = 0x72; + buf[2] = 0x49; + mt352_write(fe, buf, 3); + break; + case INPUT_FREQ_0: + /* Set our custom IF in the case below */ + break; + case INPUT_FREQ_1: + /* 4.56 MHz IF: (20.48 - 4.56)/20.48 * 2^14 = 0x31c0 */ + buf[1] = 0x31; + buf[2] = 0xc0; + mt352_write(fe, buf, 3); + break; + default: + /* Pass through the register-value pair from the fw */ + buf[1] = fw->data[i+1]; + mt352_write(fe, buf, 2); + break; + } + } + + buf[0] = (u8) TUNER_GO; + buf[1] = 0x01; /* Go */ + mt352_write(fe, buf, 2); + release_firmware(fw); + return 0; +} + +static struct mt352_config yuan_mpc718_mt352_demod = { + .demod_address = 0x1e >> 1, + .adc_clock = 20480, /* 20.480 MHz */ + .if2 = 4560, /* 4.560 MHz */ + .no_tuner = 1, /* XC3028 is not behind the gate */ + .demod_init = yuan_mpc718_mt352_init, +}; + +static struct zl10353_config yuan_mpc718_zl10353_demod = { + .demod_address = 0x1e >> 1, /* Datasheet suggested straps */ + .if2 = 45600, /* 4.560 MHz IF from the XC3028 */ + .parallel_ts = 1, /* Not a serial TS */ + .no_tuner = 1, /* XC3028 is not behind the gate */ + .disable_i2c_gate_ctrl = 1, /* Disable the I2C gate */ +}; + static int dvb_register(struct cx18_stream *stream); /* Kernel DVB framework calls this when the feed needs to start. @@ -113,6 +240,7 @@ static int cx18_dvb_start_feed(struct dvb_demux_feed *feed) break; case CX18_CARD_LEADTEK_DVR3100H: + case CX18_CARD_YUAN_MPC718: default: /* Assumption - Parallel transport - Signalling * undefined or default. @@ -326,6 +454,38 @@ static int dvb_register(struct cx18_stream *stream) fe->ops.tuner_ops.set_config(fe, &ctrl); } break; + case CX18_CARD_YUAN_MPC718: + /* + * TODO + * Apparently, these cards also could instead have a + * DiBcom demod supported by one of the db7000 drivers + */ + dvb->fe = dvb_attach(mt352_attach, + &yuan_mpc718_mt352_demod, + &cx->i2c_adap[1]); + if (dvb->fe == NULL) + dvb->fe = dvb_attach(zl10353_attach, + &yuan_mpc718_zl10353_demod, + &cx->i2c_adap[1]); + if (dvb->fe != NULL) { + struct dvb_frontend *fe; + struct xc2028_config cfg = { + .i2c_adap = &cx->i2c_adap[1], + .i2c_addr = 0xc2 >> 1, + .ctrl = NULL, + }; + static struct xc2028_ctrl ctrl = { + .fname = XC2028_DEFAULT_FIRMWARE, + .max_len = 64, + .demod = XC3028_FE_ZARLINK456, + .type = XC2028_AUTO, + }; + + fe = dvb_attach(xc2028_attach, dvb->fe, &cfg); + if (fe != NULL && fe->ops.tuner_ops.set_config != NULL) + fe->ops.tuner_ops.set_config(fe, &ctrl); + } + break; default: /* No Digital Tv Support */ break; -- cgit v1.2.3 From 0e410bd1fdf38a0923227a82254f1b4cca094f7e Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Fri, 3 Jul 2009 17:32:46 +0200 Subject: uvcvideo: Set PROBE_MINMAX quirk for Aveo Technology webcams From: Laurent Pinchart Some Aveo Technology USB 2.0 Camera (1871:0306) revisions seem to require the PROBE_MINMAX quirk. As the camera supports uncompressed YUYV data only, it's safe to set the quirk even if not strictly required for all models. Update the device entry in the device IDs list. Priority: normal Signed-off-by: Laurent Pinchart --- linux/drivers/media/video/uvc/uvc_driver.c | 3 ++- 1 file changed, 2 insertions(+), 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 f03e567a1..f7b76884d 100644 --- a/linux/drivers/media/video/uvc/uvc_driver.c +++ b/linux/drivers/media/video/uvc/uvc_driver.c @@ -1931,7 +1931,8 @@ static struct usb_device_id uvc_ids[] = { .bInterfaceClass = USB_CLASS_VIDEO, .bInterfaceSubClass = 1, .bInterfaceProtocol = 0, - .driver_info = UVC_QUIRK_PROBE_EXTRAFIELDS }, + .driver_info = UVC_QUIRK_PROBE_MINMAX + | UVC_QUIRK_PROBE_EXTRAFIELDS }, /* Ecamm Pico iMage */ { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO, -- cgit v1.2.3 From 2dfcd826496c586960e88da243e0a42c0ca322b8 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 3 Jul 2009 15:36:18 -0300 Subject: em28xx: Add autodetection code for Silvercrest 1.3 mpix From: Mauro Carvalho Chehab Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/em28xx/em28xx-cards.c | 44 +++++++++++++++++++++++++ linux/drivers/media/video/em28xx/em28xx-i2c.c | 2 +- 2 files changed, 45 insertions(+), 1 deletion(-) (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 e63c2e64e..928384e65 100644 --- a/linux/drivers/media/video/em28xx/em28xx-cards.c +++ b/linux/drivers/media/video/em28xx/em28xx-cards.c @@ -59,6 +59,8 @@ static unsigned int card[] = {[0 ... (EM28XX_MAXBOARDS - 1)] = UNSET }; module_param_array(card, int, NULL, 0444); MODULE_PARM_DESC(card, "card type"); +#define MT9V011_VERSION 0x8243 + /* Bitmask marking allocated devices from 0 to EM28XX_MAXBOARDS */ static unsigned long em28xx_devused; @@ -1771,6 +1773,46 @@ static inline void em28xx_set_model(struct em28xx *dev) EM28XX_I2C_FREQ_100_KHZ; } +/* HINT method: webcam I2C chips + * + * This method work for webcams with Micron sensors + */ +static int em28xx_hint_sensor(struct em28xx *dev) +{ + int rc; + char *sensor_name; + unsigned char cmd; + __be16 version_be; + u16 version; + + if (dev->model != EM2820_BOARD_UNKNOWN) + return 0; + + dev->i2c_client.addr = 0xba >> 1; + cmd = 0; + i2c_master_send(&dev->i2c_client, &cmd, 1); + rc = i2c_master_recv(&dev->i2c_client, (char *)&version_be, 2); + if (rc != 2) + return -EINVAL; + + version = be16_to_cpu(version_be); + + switch (version) { + case MT9V011_VERSION: + dev->model = EM2820_BOARD_SILVERCREST_WEBCAM; + sensor_name = "mt9v011"; + break; + default: + printk("Unknown Sensor 0x%04x\n", be16_to_cpu(version)); + return -EINVAL; + } + + em28xx_errdev("Sensor is %s, assuming that webcam is %s\n", + sensor_name, em28xx_boards[dev->model].name); + + return 0; +} + /* Since em28xx_pre_card_setup() requires a proper dev->model, * this won't work for boards with generic PCI IDs */ @@ -2482,6 +2524,8 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, return errCode; } + em28xx_hint_sensor(dev); + /* Do board specific init and eeprom reading */ em28xx_card_setup(dev); diff --git a/linux/drivers/media/video/em28xx/em28xx-i2c.c b/linux/drivers/media/video/em28xx/em28xx-i2c.c index 24eebd4a3..91cff2af3 100644 --- a/linux/drivers/media/video/em28xx/em28xx-i2c.c +++ b/linux/drivers/media/video/em28xx/em28xx-i2c.c @@ -489,7 +489,7 @@ static char *i2c_devs[128] = { [0xa0 >> 1] = "eeprom", [0xb0 >> 1] = "tda9874", [0xb8 >> 1] = "tvp5150a", - [0xba >> 1] = "tvp5150a", + [0xba >> 1] = "webcam sensor or tvp5150a", [0xc0 >> 1] = "tuner (analog)", [0xc2 >> 1] = "tuner (analog)", [0xc4 >> 1] = "tuner (analog)", -- cgit v1.2.3 From 4a782628ed2966858fcf5acac0b890dea02c5b11 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 4 Jul 2009 08:03:48 -0300 Subject: mt9v011: properly calculate image resolution registers From: Mauro Carvalho Chehab Instead of working with a table of precalculated values, fill them with the proper values. Also, adds format functions that allow changing the resolution, by cropping the image to the center of the sensor. While here, move the sensor version check to the probe routine, to indicate to the caller if the sensor is not supported by this driver. Also, fixes a stupid bug where we're using &buffer[] instead of buffer[]. Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/mt9v011.c | 114 +++++++++++++++++++++++++++++------- 1 file changed, 94 insertions(+), 20 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/mt9v011.c b/linux/drivers/media/video/mt9v011.c index d3f2b4dc5..17a4fa386 100644 --- a/linux/drivers/media/video/mt9v011.c +++ b/linux/drivers/media/video/mt9v011.c @@ -66,6 +66,7 @@ static struct v4l2_queryctrl mt9v011_qctrl[] = { struct mt9v011 { struct v4l2_subdev sd; + unsigned width, height; u16 global_gain, red_bal, blue_bal; }; @@ -113,7 +114,7 @@ static void mt9v011_write(struct v4l2_subdev *sd, unsigned char addr, v4l2_dbg(2, debug, sd, "mt9v011: writing 0x%02x 0x%04x\n", buffer[0], value); - rc = i2c_master_send(c, &buffer, 3); + rc = i2c_master_send(c, buffer, 3); if (rc != 3) v4l2_dbg(0, debug, sd, "i2c i/o error: rc == %d (should be 3)\n", rc); @@ -133,12 +134,6 @@ static const struct i2c_reg_value mt9v011_init_default[] = { { R0D_MT9V011_RESET, 0x0001 }, { R0D_MT9V011_RESET, 0x0000 }, - { R01_MT9V011_ROWSTART, 0x0008 }, - { R02_MT9V011_COLSTART, 0x0014 }, - { R03_MT9V011_HEIGHT, 0x01e0 }, - { R04_MT9V011_WIDTH, 0x0280 }, - { R05_MT9V011_HBLANK, 0x007b }, - { R06_MT9V011_VBLANK, 0x001c }, { R09_MT9V011_SHUTTER_WIDTH, 0x0418 }, { R0A_MT9V011_CLK_SPEED, 0x0000 }, { R0C_MT9V011_SHUTTER_DELAY, 0x0000 }, @@ -181,25 +176,40 @@ static void set_balance(struct v4l2_subdev *sd) mt9v011_write(sd, R2D_MT9V011_RED_GAIN, red_gain); } +static void set_res(struct v4l2_subdev *sd) +{ + struct mt9v011 *core = to_mt9v011(sd); + unsigned vstart, hstart; + + /* + * The mt9v011 doesn't have scaling. So, in order to select the desired + * resolution, we're cropping at the middle of the sensor. + * hblank and vblank should be adjusted, in order to warrant that + * we'll preserve the line timings for 30 fps, no matter what resolution + * is selected. + */ + + hstart = 14 + (640 - core->width) / 2; + mt9v011_write(sd, R02_MT9V011_COLSTART, hstart); + mt9v011_write(sd, R04_MT9V011_WIDTH, core->width); + mt9v011_write(sd, R05_MT9V011_HBLANK, 771 - core->width); + + vstart = 8 + (640 - core->height) / 2; + mt9v011_write(sd, R01_MT9V011_ROWSTART, vstart); + mt9v011_write(sd, R03_MT9V011_HEIGHT, core->height); + mt9v011_write(sd, R06_MT9V011_VBLANK, 508 - core->height); +}; + static int mt9v011_reset(struct v4l2_subdev *sd, u32 val) { - u16 version; int i; - version = mt9v011_read(sd, R00_MT9V011_CHIP_VERSION); - - if (version != MT9V011_VERSION) { - v4l2_info(sd, "*** unknown micron chip detected (0x%04x.\n", - version); - return -EINVAL; - - } - for (i = 0; i < ARRAY_SIZE(mt9v011_init_default); i++) mt9v011_write(sd, mt9v011_init_default[i].reg, mt9v011_init_default[i].value); set_balance(sd); + set_res(sd); return 0; }; @@ -260,6 +270,50 @@ static int mt9v011_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) return 0; } +static int mt9v011_enum_fmt(struct v4l2_subdev *sd, struct v4l2_fmtdesc *fmt) +{ + if (fmt->index > 0) + return -EINVAL; + + fmt->flags = 0; + strcpy(fmt->description, "8 bpp Bayer GRGR..BGBG"); + fmt->pixelformat = V4L2_PIX_FMT_SGRBG8; + + return 0; +} + +static int mt9v011_try_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) +{ + struct v4l2_pix_format *pix = &fmt->fmt.pix; + + if (pix->pixelformat != V4L2_PIX_FMT_SGRBG8) + return -EINVAL; + + v4l_bound_align_image(&pix->width, 48, 639, 1, + &pix->height, 32, 480, 1, 0); + + return 0; +} + +static int mt9v011_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) +{ + struct v4l2_pix_format *pix = &fmt->fmt.pix; + struct mt9v011 *core = to_mt9v011(sd); + int rc; + + rc = mt9v011_try_fmt(sd, fmt); + if (rc < 0) + return -EINVAL; + + core->width = pix->width; + core->height = pix->height; + + set_res(sd); + + return 0; +} + + #ifdef CONFIG_VIDEO_ADV_DEBUG static int mt9v011_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg) @@ -313,8 +367,15 @@ static const struct v4l2_subdev_core_ops mt9v011_core_ops = { #endif }; +static const struct v4l2_subdev_video_ops mt9v011_video_ops = { + .enum_fmt = mt9v011_enum_fmt, + .try_fmt = mt9v011_try_fmt, + .s_fmt = mt9v011_s_fmt, +}; + static const struct v4l2_subdev_ops mt9v011_ops = { - .core = &mt9v011_core_ops, + .core = &mt9v011_core_ops, + .video = &mt9v011_video_ops, }; @@ -325,6 +386,7 @@ static const struct v4l2_subdev_ops mt9v011_ops = { static int mt9v011_probe(struct i2c_client *c, const struct i2c_device_id *id) { + u16 version; struct mt9v011 *core; struct v4l2_subdev *sd; @@ -337,10 +399,22 @@ static int mt9v011_probe(struct i2c_client *c, if (!core) return -ENOMEM; - core->global_gain = 0x0024; - sd = &core->sd; v4l2_i2c_subdev_init(sd, c, &mt9v011_ops); + + /* Check if the sensor is really a MT9V011 */ + version = mt9v011_read(sd, R00_MT9V011_CHIP_VERSION); + if (version != MT9V011_VERSION) { + v4l2_info(sd, "*** unknown micron chip detected (0x%04x.\n", + version); + kfree(core); + return -EINVAL; + } + + core->global_gain = 0x0024; + core->width = 640; + core->height = 480; + v4l_info(c, "chip found @ 0x%02x (%s)\n", c->addr << 1, c->adapter->name); -- cgit v1.2.3 From 6dfa16c1aa732ce5a5c0f0404e70ed2d65675b6b Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 4 Jul 2009 08:15:11 -0300 Subject: mt9v011: let's stick with datasheet values where it works From: Mauro Carvalho Chehab The original driver for Silvercrest cameras were using some values that are different from what datasheet says. As result, it was taken very less snapshots per second than expected. A test with the datasheet values showed that they work fine and give a better frame rate. So, let's stick with datasheet values. Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/mt9v011.c | 23 +++++++---------------- 1 file changed, 7 insertions(+), 16 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/mt9v011.c b/linux/drivers/media/video/mt9v011.c index 17a4fa386..505529e3e 100644 --- a/linux/drivers/media/video/mt9v011.c +++ b/linux/drivers/media/video/mt9v011.c @@ -134,24 +134,12 @@ static const struct i2c_reg_value mt9v011_init_default[] = { { R0D_MT9V011_RESET, 0x0001 }, { R0D_MT9V011_RESET, 0x0000 }, - { R09_MT9V011_SHUTTER_WIDTH, 0x0418 }, - { R0A_MT9V011_CLK_SPEED, 0x0000 }, { R0C_MT9V011_SHUTTER_DELAY, 0x0000 }, + { R09_MT9V011_SHUTTER_WIDTH, 0x1fc }, + + { R0A_MT9V011_CLK_SPEED, 0x0000 }, { R1E_MT9V011_DIGITAL_ZOOM, 0x0000 }, - { R20_MT9V011_READ_MODE, 0x1100 }, - - /* - * Those registers are not docummented at the datasheet. - * However, the original driver initializes them - */ - { 0x30, 0x0005 }, - { 0x34, 0x0100 }, - { 0x3d, 0x068f }, - { 0x40, 0x01e0 }, - { 0x52, 0x0100 }, - { 0x58, 0x0038 }, /* Datasheet default 0x0078 */ - { 0x59, 0x0723 }, /* Datasheet default 0x0703 */ - { 0x62, 0x041a }, /* Datasheet default 0x0418 */ + { R20_MT9V011_READ_MODE, 0x1000 }, { R07_MT9V011_OUT_CTRL, 0x000a }, /* chip enable */ }; @@ -187,6 +175,9 @@ static void set_res(struct v4l2_subdev *sd) * hblank and vblank should be adjusted, in order to warrant that * we'll preserve the line timings for 30 fps, no matter what resolution * is selected. + * NOTE: datasheet says that width (and height) should be filled with + * width-1. However, this doesn't work, since one pixel per line will + * be missing. */ hstart = 14 + (640 - core->width) / 2; -- cgit v1.2.3 From 29a44e254bb209b88022dcc4c4eee0e301ae847f Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 5 Jul 2009 21:51:21 +0800 Subject: em28xx: Add support for Gadmei UTV330+ From: Zhenyu Wang em28xx: Add support for Gadmei UTV330+ Signed-off-by: Zhenyu Wang Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/em28xx/em28xx-cards.c | 2 ++ 1 file changed, 2 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 928384e65..7f4004a00 100644 --- a/linux/drivers/media/video/em28xx/em28xx-cards.c +++ b/linux/drivers/media/video/em28xx/em28xx-cards.c @@ -1693,6 +1693,8 @@ struct usb_device_id em28xx_id_table[] = { .driver_info = EM2861_BOARD_PLEXTOR_PX_TV100U }, { USB_DEVICE(0x04bb, 0x0515), .driver_info = EM2820_BOARD_IODATA_GVMVP_SZ }, + { USB_DEVICE(0xeb1a, 0x50a6), + .driver_info = EM2860_BOARD_GADMEI_UTV330 }, { }, }; MODULE_DEVICE_TABLE(usb, em28xx_id_table); -- cgit v1.2.3 From 682a54d47d1548a8a20bb80cb5377c53b77e0f78 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 5 Jul 2009 12:19:59 -0300 Subject: em28xx: remove uneeded vars From: Mauro Carvalho Chehab Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/em28xx/em28xx-video.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/em28xx/em28xx-video.c b/linux/drivers/media/video/em28xx/em28xx-video.c index fff90faca..b0554ab08 100644 --- a/linux/drivers/media/video/em28xx/em28xx-video.c +++ b/linux/drivers/media/video/em28xx/em28xx-video.c @@ -1433,9 +1433,6 @@ static int vidioc_querycap(struct file *file, void *priv, static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, struct v4l2_fmtdesc *f) { - struct em28xx_fh *fh = priv; - struct em28xx *dev = fh->dev; - if (unlikely(f->index >= ARRAY_SIZE(format))) return -EINVAL; -- cgit v1.2.3 From 86ef69f11da81856aff2e001226cc47cafacb68b Mon Sep 17 00:00:00 2001 From: Douglas Schilling Landgraf Date: Sun, 5 Jul 2009 14:06:41 -0300 Subject: em28xx, fix lock imbalance From: Jiri Slaby There is one omitted unlock in em28xx_usb_probe. Fix that. Priority: normal Signed-off-by: Jiri Slaby Signed-off-by: Douglas Schilling Landgraf --- linux/drivers/media/video/em28xx/em28xx-cards.c | 1 + 1 file changed, 1 insertion(+) (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 e63c2e64e..dd6d42830 100644 --- a/linux/drivers/media/video/em28xx/em28xx-cards.c +++ b/linux/drivers/media/video/em28xx/em28xx-cards.c @@ -2725,6 +2725,7 @@ static int em28xx_usb_probe(struct usb_interface *interface, retval = em28xx_init_dev(&dev, udev, interface, nr); if (retval) { em28xx_devused &= ~(1<devno); + mutex_unlock(&dev->lock); kfree(dev); goto err; } -- cgit v1.2.3 From 279c5f3afbe8df017510c35a0fb21214f5ba71cc Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 5 Jul 2009 14:55:41 -0300 Subject: backport commit 4327b77ed7e73336069c441f91df58a251c77975 From: Mauro Carvalho Chehab kernel-sync: Author: Samuel Ortiz Date: Wed May 27 00:49:33 2009 +0200 firmware: tuners/xc2028: prepare for FIRMWARE_NAME_MAX removal We're going to remove the FIRMWARE_NAME_MAX definition in order to avoid any firmware name length restriction. This patch gets rid of the xc2028 FIRMWARE_NAME_MAX reference. Signed-off-by: Mauro Carvalho Chehab --- 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 8ead0e1e1..3de5d6685 100644 --- a/linux/drivers/media/common/tuners/tuner-xc2028.c +++ b/linux/drivers/media/common/tuners/tuner-xc2028.c @@ -52,7 +52,7 @@ MODULE_PARM_DESC(audio_std, "NICAM/A\n" "NICAM/B\n"); -static char firmware_name[FIRMWARE_NAME_MAX]; +static char firmware_name[30]; module_param_string(firmware_name, firmware_name, sizeof(firmware_name), 0); MODULE_PARM_DESC(firmware_name, "Firmware file name. Allows overriding the " "default firmware name\n"); -- cgit v1.2.3 From aebfdafbbe60eb6798f9e81686a33b519af8e3c8 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 5 Jul 2009 14:59:27 -0300 Subject: backport commit 56aec8d874e222f68baffbda33322c9be4cbf2ea From: Mauro Carvalho Chehab kernel-sync: Author: Samuel Ortiz Date: Wed May 27 00:49:34 2009 +0200 firmware: dvb/dvb-usb: prepare for FIRMWARE_NAME_MAX removal We're going to remove the FIRMWARE_NAME_MAX definition in order to avoid any firmware name length restriction. This patch changes the dvb_usb_device_properties firmware field accordingly. Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/dvb-usb/dvb-usb.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/dvb-usb/dvb-usb.h b/linux/drivers/media/dvb/dvb-usb/dvb-usb.h index 8874221c1..f4819c32f 100644 --- a/linux/drivers/media/dvb/dvb-usb/dvb-usb.h +++ b/linux/drivers/media/dvb/dvb-usb/dvb-usb.h @@ -197,7 +197,7 @@ struct dvb_usb_device_properties { #define CYPRESS_FX2 3 int usb_ctrl; int (*download_firmware) (struct usb_device *, const struct firmware *); - const char firmware[FIRMWARE_NAME_MAX]; + const char *firmware; int no_reconnect; int size_of_priv; -- cgit v1.2.3 From 33059960a17b83a720e88a4093d4fc40a1a307a4 Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Sun, 5 Jul 2009 14:13:56 -0400 Subject: ivtv: Fix automatic detection of AVerMedia UltraTV 1500MCE. From: Andy Walls My initial change left the AVerMedia UtlraTV 1500MCE card entry out of the list of cards to check during the probe. This change adds it to the ivtv_card_list[]. Priority: normal Signed-off-by: Andy Walls --- linux/drivers/media/video/ivtv/ivtv-cards.c | 1 + 1 file changed, 1 insertion(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/ivtv/ivtv-cards.c b/linux/drivers/media/video/ivtv/ivtv-cards.c index 553a314fa..40c29032f 100644 --- a/linux/drivers/media/video/ivtv/ivtv-cards.c +++ b/linux/drivers/media/video/ivtv/ivtv-cards.c @@ -1224,6 +1224,7 @@ static const struct ivtv_card *ivtv_card_list[] = { &ivtv_card_aver_ezmaker, &ivtv_card_aver_m104, &ivtv_card_buffalo, + &ivtv_card_aver_ultra1500mce, /* Variations of standard cards but with the same PCI IDs. These cards must come last in this list. */ -- cgit v1.2.3 From e1afff6e5f2d6b35928ab6651ac5705659713ca0 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 5 Jul 2009 15:27:33 -0300 Subject: backport commit 0a861e9eb76c68b23be1aa4758269c5b412089a9 From: Mauro Carvalho Chehab kernel-sync: Author: Guennadi Liakhovetski Date: Tue May 12 15:13:32 2009 +0000 soc-camera: unify i2c camera device platform data Unify i2c camera device platform data to point to struct soc_camera_link for a smooth transition to soc-camera as a platform driver. Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/ov772x.c | 6 ++++-- linux/drivers/media/video/tw9910.c | 6 ++++-- 2 files changed, 8 insertions(+), 4 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/ov772x.c b/linux/drivers/media/video/ov772x.c index b17a7400d..4b0363940 100644 --- a/linux/drivers/media/video/ov772x.c +++ b/linux/drivers/media/video/ov772x.c @@ -1071,10 +1071,12 @@ static int ov772x_probe(struct i2c_client *client, struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); int ret; - info = client->dev.platform_data; - if (!info) + if (!client->dev.platform_data) return -EINVAL; + info = container_of(client->dev.platform_data, + struct ov772x_camera_info, link); + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { dev_err(&adapter->dev, "I2C-Adapter doesn't support " diff --git a/linux/drivers/media/video/tw9910.c b/linux/drivers/media/video/tw9910.c index 5c145085a..f75787594 100644 --- a/linux/drivers/media/video/tw9910.c +++ b/linux/drivers/media/video/tw9910.c @@ -879,10 +879,12 @@ static int tw9910_probe(struct i2c_client *client, const struct tw9910_scale_ctrl *scale; int i, ret; - info = client->dev.platform_data; - if (!info) + if (!client->dev.platform_data) return -EINVAL; + info = container_of(client->dev.platform_data, + struct tw9910_video_info, link); + if (!i2c_check_functionality(to_i2c_adapter(client->dev.parent), I2C_FUNC_SMBUS_BYTE_DATA)) { dev_err(&client->dev, -- cgit v1.2.3 From 0082053685c27f18e24c1d3e564bb43f51fc28f4 Mon Sep 17 00:00:00 2001 From: Douglas Schilling Landgraf Date: Sun, 5 Jul 2009 15:44:20 -0300 Subject: radio-si470x: fix lock imbalance From: Jiri Slaby There is one path with omitted unlock in si470x_fops_release. Fix that. Priority: normal Signed-off-by: Jiri Slaby CC: Tobias Lorenz Signed-off-by: Douglas Schilling Landgraf --- linux/drivers/media/radio/radio-si470x.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/radio/radio-si470x.c b/linux/drivers/media/radio/radio-si470x.c index de4673b3a..20aa447cc 100644 --- a/linux/drivers/media/radio/radio-si470x.c +++ b/linux/drivers/media/radio/radio-si470x.c @@ -1206,7 +1206,7 @@ static int si470x_fops_release(struct file *file) kfree(radio->int_in_buffer); kfree(radio->buffer); kfree(radio); - goto done; + goto unlock; } /* cancel read processes */ @@ -1216,9 +1216,8 @@ static int si470x_fops_release(struct file *file) retval = si470x_stop(radio); usb_autopm_put_interface(radio->intf); } - +unlock: mutex_unlock(&radio->disconnect_lock); - done: return retval; } -- cgit v1.2.3 From 3304a5198cc1315ca633f1d17bcbdb36a07e9bfb Mon Sep 17 00:00:00 2001 From: Douglas Schilling Landgraf Date: Sun, 5 Jul 2009 15:59:21 -0300 Subject: bttv and meye: Use PCI_VDEVICE From: Joe Perches Priority: normal Signed-off-by: Joe Perches Signed-off-by: Douglas Schilling Landgraf --- linux/drivers/media/video/bt8xx/bttv-driver.c | 12 ++++-------- linux/drivers/media/video/meye.c | 3 +-- 2 files changed, 5 insertions(+), 10 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 27be1694b..bd5dde3f8 100644 --- a/linux/drivers/media/video/bt8xx/bttv-driver.c +++ b/linux/drivers/media/video/bt8xx/bttv-driver.c @@ -4628,14 +4628,10 @@ static int bttv_resume(struct pci_dev *pci_dev) #endif static struct pci_device_id bttv_pci_tbl[] = { - {PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT848, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, - {PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT849, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, - {PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT878, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, - {PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT879, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VDEVICE(BROOKTREE, PCI_DEVICE_ID_BT848), 0}, + {PCI_VDEVICE(BROOKTREE, PCI_DEVICE_ID_BT849), 0}, + {PCI_VDEVICE(BROOKTREE, PCI_DEVICE_ID_BT878), 0}, + {PCI_VDEVICE(BROOKTREE, PCI_DEVICE_ID_BT879), 0}, {0,} }; diff --git a/linux/drivers/media/video/meye.c b/linux/drivers/media/video/meye.c index 1fb7024a5..1d0a0cc81 100644 --- a/linux/drivers/media/video/meye.c +++ b/linux/drivers/media/video/meye.c @@ -1925,8 +1925,7 @@ static void __devexit meye_remove(struct pci_dev *pcidev) } static struct pci_device_id meye_pci_tbl[] = { - { PCI_VENDOR_ID_KAWASAKI, PCI_DEVICE_ID_MCHIP_KL5A72002, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, + { PCI_VDEVICE(KAWASAKI, PCI_DEVICE_ID_MCHIP_KL5A72002), 0 }, { } }; -- cgit v1.2.3 From 9cc45cab6319967ccacdcb3b8c848ec555941200 Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Sun, 5 Jul 2009 16:09:28 -0400 Subject: cx18: Add an EEPROM dump routine for the Yuan MPC718 and future cards From: Andy Walls Add a routine for dumping the EEPROM of the MPC718. It is generic enough to use for other cards in the future that may have an EEPROM. Priority: normal Signed-off-by: Andy Walls --- linux/drivers/media/video/cx18/cx18-cards.c | 2 +- linux/drivers/media/video/cx18/cx18-driver.c | 41 ++++++++++++++++++++++++++-- 2 files changed, 40 insertions(+), 3 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/cx18/cx18-cards.c b/linux/drivers/media/video/cx18/cx18-cards.c index d9a407681..c0abf3476 100644 --- a/linux/drivers/media/video/cx18/cx18-cards.c +++ b/linux/drivers/media/video/cx18/cx18-cards.c @@ -204,7 +204,7 @@ static const struct cx18_card cx18_card_mpc718 = { .v4l2_capabilities = CX18_CAP_ENCODER, .hw_audio_ctrl = CX18_HW_418_AV, .hw_muxer = CX18_HW_GPIO_MUX, - .hw_all = CX18_HW_418_AV | CX18_HW_TUNER | + .hw_all = CX18_HW_TVEEPROM | CX18_HW_418_AV | CX18_HW_TUNER | CX18_HW_GPIO_MUX | CX18_HW_DVB | CX18_HW_GPIO_RESET_CTRL, .video_inputs = { { CX18_CARD_INPUT_VID_TUNER, 0, CX18_AV_COMPOSITE2 }, diff --git a/linux/drivers/media/video/cx18/cx18-driver.c b/linux/drivers/media/video/cx18/cx18-driver.c index 7ffdda49c..ae13a1546 100644 --- a/linux/drivers/media/video/cx18/cx18-driver.c +++ b/linux/drivers/media/video/cx18/cx18-driver.c @@ -268,6 +268,20 @@ static void cx18_iounmap(struct cx18 *cx) } } +static void cx18_eeprom_dump(struct cx18 *cx, unsigned char *eedata, int len) +{ + int i; + + CX18_INFO("eeprom dump:\n"); + for (i = 0; i < len; i++) { + if (0 == (i % 16)) + CX18_INFO("eeprom %02x:", i); + printk(KERN_CONT " %02x", eedata[i]); + if (15 == (i % 16)) + printk(KERN_CONT "\n"); + } +} + /* Hauppauge card? get values from tveeprom */ void cx18_read_eeprom(struct cx18 *cx, struct tveeprom *tv) { @@ -279,8 +293,26 @@ void cx18_read_eeprom(struct cx18 *cx, struct tveeprom *tv) c.adapter = &cx->i2c_adap[0]; c.addr = 0xA0 >> 1; - tveeprom_read(&c, eedata, sizeof(eedata)); - tveeprom_hauppauge_analog(&c, tv, eedata); + memset(tv, 0, sizeof(*tv)); + if (tveeprom_read(&c, eedata, sizeof(eedata))) + return; + + switch (cx->card->type) { + case CX18_CARD_HVR_1600_ESMT: + case CX18_CARD_HVR_1600_SAMSUNG: + tveeprom_hauppauge_analog(&c, tv, eedata); + break; + case CX18_CARD_YUAN_MPC718: + tv->model = 0x718; + cx18_eeprom_dump(cx, eedata, sizeof(eedata)); + CX18_INFO("eeprom PCI ID: %02x%02x:%02x%02x\n", + eedata[2], eedata[1], eedata[4], eedata[3]); + break; + default: + tv->model = 0xffffffff; + cx18_eeprom_dump(cx, eedata, sizeof(eedata)); + break; + } } static void cx18_process_eeprom(struct cx18 *cx) @@ -298,6 +330,11 @@ static void cx18_process_eeprom(struct cx18 *cx) case 74000 ... 74999: cx->card = cx18_get_card(CX18_CARD_HVR_1600_ESMT); break; + case 0x718: + return; + case 0xffffffff: + CX18_INFO("Unknown EEPROM encoding\n"); + return; case 0: CX18_ERR("Invalid EEPROM\n"); return; -- cgit v1.2.3 From 0286fa6a54c3f6a36700ce23a094750b03a01c9f Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Tue, 7 Jul 2009 09:03:24 +0200 Subject: gspca - t613: Change tas5130a init sequences. From: Jean-Francois Moine Priority: normal Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/t613.c | 249 ++++++++++++++++++++------------- 1 file changed, 149 insertions(+), 100 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/t613.c b/linux/drivers/media/video/gspca/t613.c index 1b58b65fb..10530b465 100644 --- a/linux/drivers/media/video/gspca/t613.c +++ b/linux/drivers/media/video/gspca/t613.c @@ -264,6 +264,10 @@ static const struct v4l2_pix_format vga_mode_t16[] = { /* sensor specific data */ struct additional_sensor_data { + const u8 n3[6]; + const u8 *n4, n4sz; + const u8 reg80, reg8e; + const u8 nset8[6]; const u8 data1[10]; const u8 data2[9]; const u8 data3[9]; @@ -272,28 +276,98 @@ struct additional_sensor_data { const u8 stream[4]; }; +static const u8 n4_om6802[] = { + 0x09, 0x01, 0x12, 0x04, 0x66, 0x8a, 0x80, 0x3c, + 0x81, 0x22, 0x84, 0x50, 0x8a, 0x78, 0x8b, 0x68, + 0x8c, 0x88, 0x8e, 0x33, 0x8f, 0x24, 0xaa, 0xb1, + 0xa2, 0x60, 0xa5, 0x30, 0xa6, 0x3a, 0xa8, 0xe8, + 0xae, 0x05, 0xb1, 0x00, 0xbb, 0x04, 0xbc, 0x48, + 0xbe, 0x36, 0xc6, 0x88, 0xe9, 0x00, 0xc5, 0xc0, + 0x65, 0x0a, 0xbb, 0x86, 0xaf, 0x58, 0xb0, 0x68, + 0x87, 0x40, 0x89, 0x2b, 0x8d, 0xff, 0x83, 0x40, + 0xac, 0x84, 0xad, 0x86, 0xaf, 0x46 +}; +static const u8 n4_other[] = { + 0x66, 0x00, 0x7f, 0x00, 0x80, 0xac, 0x81, 0x69, + 0x84, 0x40, 0x85, 0x70, 0x86, 0x20, 0x8a, 0x68, + 0x8b, 0x58, 0x8c, 0x88, 0x8d, 0xff, 0x8e, 0xb8, + 0x8f, 0x28, 0xa2, 0x60, 0xa5, 0x40, 0xa8, 0xa8, + 0xac, 0x84, 0xad, 0x84, 0xae, 0x24, 0xaf, 0x56, + 0xb0, 0x68, 0xb1, 0x00, 0xb2, 0x88, 0xbb, 0xc5, + 0xbc, 0x4a, 0xbe, 0x36, 0xc2, 0x88, 0xc5, 0xc0, + 0xc6, 0xda, 0xe9, 0x26, 0xeb, 0x00 +}; +static const u8 n4_tas5130a[] = { + 0x80, 0x3c, 0x81, 0x68, 0x83, 0xa0, 0x84, 0x20, + 0x8a, 0x68, 0x8b, 0x58, 0x8c, 0x88, 0x8e, 0xb4, + 0x8f, 0x24, 0xa1, 0xb1, 0xa2, 0x30, 0xa5, 0x10, + 0xa6, 0x4a, 0xae, 0x03, 0xb1, 0x44, 0xb2, 0x08, + 0xb7, 0x06, 0xb9, 0xe7, 0xbb, 0xc4, 0xbc, 0x4a, + 0xbe, 0x36, 0xbf, 0xff, 0xc2, 0x88, 0xc5, 0xc8, + 0xc6, 0xda +}; + static const struct additional_sensor_data sensor_data[] = { - { /* OM6802 */ + { /* 0: OM6802 */ + .n3 = + {0x61, 0x68, 0x65, 0x0a, 0x60, 0x04}, + .n4 = n4_om6802, + .n4sz = sizeof n4_om6802, + .reg80 = 0x3c, + .reg8e = 0x33, + .nset8 = {0xa8, 0xf0, 0xc6, 0x88, 0xc0, 0x00}, .data1 = +#if 1 {0xc2, 0x28, 0x0f, 0x22, 0xcd, 0x27, 0x2c, 0x06, 0xb3, 0xfc}, +#else + {0xbb, 0x28, 0x10, 0x10, 0xbb, 0x28, 0x1e, 0x27, + 0xc8, 0xfc}, +#endif .data2 = +#if 1 + {0x80, 0xff, 0xff, 0x80, 0xff, 0xff, 0x80, 0xff, + 0xff}, +#else + {0x60, 0xa8, 0xe0, 0x60, 0xa8, 0xe0, 0x60, 0xa8, + 0xe0}, +#endif + .data3 = +#if 1 {0x80, 0xff, 0xff, 0x80, 0xff, 0xff, 0x80, 0xff, 0xff}, +#else + {0x60, 0xa8, 0xe0, 0x60, 0xa8, 0xe0, 0x60, 0xa8, + 0xe0}, +#endif .data4 = /*Freq (50/60Hz). Splitted for test purpose */ +#if 0 + {0x66, 0x8a, 0xa8, 0xe8}, +#else {0x66, 0xca, 0xa8, 0xf0}, +#endif .data5 = /* this could be removed later */ {0x0c, 0x03, 0xab, 0x13, 0x81, 0x23}, .stream = {0x0b, 0x04, 0x0a, 0x78}, }, - { /* OTHER */ + { /* 1: OTHER */ + .n3 = + {0x61, 0xc2, 0x65, 0x88, 0x60, 0x00}, + .n4 = n4_other, + .n4sz = sizeof n4_other, + .reg80 = 0xac, + .reg8e = 0xb8, + .nset8 = {0xa8, 0xa8, 0xc6, 0xda, 0xc0, 0x00}, .data1 = {0xc1, 0x48, 0x04, 0x1b, 0xca, 0x2e, 0x33, 0x3a, 0xe8, 0xfc}, .data2 = {0x4e, 0x9c, 0xec, 0x40, 0x80, 0xc0, 0x48, 0x96, 0xd9}, + .data3 = + {0x4e, 0x9c, 0xec, 0x40, 0x80, 0xc0, 0x48, 0x96, + 0xd9}, .data4 = {0x66, 0x00, 0xa8, 0xa8}, .data5 = @@ -301,17 +375,50 @@ static const struct additional_sensor_data sensor_data[] = { .stream = {0x0b, 0x04, 0x0a, 0x00}, }, - { /* TAS5130A */ + { /* 2: TAS5130A */ + .n3 = + {0x61, 0xc2, 0x65, 0x0d, 0x60, 0x08}, + .n4 = n4_tas5130a, + .n4sz = sizeof n4_tas5130a, + .reg80 = 0x3c, + .reg8e = 0xb4, + .nset8 = {0xa8, 0xf0, 0xc6, 0xda, 0xc0, 0x00}, .data1 = +#if 1 {0xbb, 0x28, 0x10, 0x10, 0xbb, 0x28, 0x1e, 0x27, 0xc8, 0xfc}, +#else + {0xf3, 0xa1, 0x0a, 0x2f, 0xbb, 0x2e, 0x21, 0x68, + 0xea, 0xbf}, +#endif .data2 = +#if 1 {0x60, 0xa8, 0xe0, 0x60, 0xa8, 0xe0, 0x60, 0xa8, 0xe0}, +#else + {0x40, 0x80, 0xc0, 0x40, 0x80, 0xc0, 0x4d, 0x97, + 0xe4}, +#endif + .data3 = +#if 1 + {0x60, 0xa8, 0xe0, 0x60, 0xa8, 0xe0, 0x60, 0xa8, + 0xe0}, +#else + {0x40, 0x80, 0xc0, 0x41, 0x81, 0xc3, 0x5c, 0x99, + 0xe0}, +#endif .data4 = /* Freq (50/60Hz). Splitted for test purpose */ +#if 1 {0x66, 0x00, 0xa8, 0xe8}, +#else + {0x66, 0x40, 0xa8, 0xf0}, +#endif .data5 = +#if 0 + {0x0c, 0x03, 0xab, 0x08, 0x81, 0x68}, +#else {0x0c, 0x03, 0xab, 0x10, 0x81, 0x20}, +#endif .stream = {0x0b, 0x04, 0x0a, 0x40}, }, @@ -364,7 +471,7 @@ static const u8 gamma_table[GAMMA_MAX][17] = { {0x00, 0x18, 0x2b, 0x44, 0x60, 0x70, 0x80, 0x8e, /* 10 */ 0x9c, 0xaa, 0xb7, 0xc4, 0xd0, 0xd8, 0xe2, 0xf0, 0xff}, - {0x00, 0x1a, 0x34, 0x52, 0x66, 0x7e, 0x8D, 0x9B, /* 11 */ + {0x00, 0x1a, 0x34, 0x52, 0x66, 0x7e, 0x8d, 0x9b, /* 11 */ 0xa8, 0xb4, 0xc0, 0xcb, 0xd6, 0xe1, 0xeb, 0xf5, 0xff}, {0x00, 0x3f, 0x5a, 0x6e, 0x7f, 0x8e, 0x9c, 0xa8, /* 12 */ @@ -385,8 +492,6 @@ static const u8 tas5130a_sensor_init[][8] = { {0x62, 0x08, 0x63, 0x70, 0x64, 0x1d, 0x60, 0x09}, {0x62, 0x20, 0x63, 0x01, 0x64, 0x02, 0x60, 0x09}, {0x62, 0x07, 0x63, 0x03, 0x64, 0x00, 0x60, 0x09}, - {0x62, 0x07, 0x63, 0x03, 0x64, 0x00, 0x60, 0x09}, - {}, }; static u8 sensor_reset[] = {0x61, 0x68, 0x62, 0xff, 0x60, 0x07}; @@ -633,10 +738,10 @@ static int sd_init(struct gspca_dev *gspca_dev) * but wont hurt anyway, and can help someone with similar webcam * to see the initial parameters.*/ struct sd *sd = (struct sd *) gspca_dev; + const struct additional_sensor_data *sensor; int i; u16 sensor_id; u8 test_byte = 0; - u16 reg80, reg8e; static const u8 read_indexs[] = { 0x0a, 0x0b, 0x66, 0x80, 0x81, 0x8e, 0x8f, 0xa5, @@ -645,37 +750,6 @@ static int sd_init(struct gspca_dev *gspca_dev) {0x08, 0x03, 0x09, 0x03, 0x12, 0x04}; static const u8 n2[] = {0x08, 0x00}; - static const u8 n3[6] = - {0x61, 0x68, 0x65, 0x0a, 0x60, 0x04}; - static const u8 n3_other[6] = - {0x61, 0xc2, 0x65, 0x88, 0x60, 0x00}; - static const u8 n4[] = - {0x09, 0x01, 0x12, 0x04, 0x66, 0x8a, 0x80, 0x3c, - 0x81, 0x22, 0x84, 0x50, 0x8a, 0x78, 0x8b, 0x68, - 0x8c, 0x88, 0x8e, 0x33, 0x8f, 0x24, 0xaa, 0xb1, - 0xa2, 0x60, 0xa5, 0x30, 0xa6, 0x3a, 0xa8, 0xe8, - 0xae, 0x05, 0xb1, 0x00, 0xbb, 0x04, 0xbc, 0x48, - 0xbe, 0x36, 0xc6, 0x88, 0xe9, 0x00, 0xc5, 0xc0, - 0x65, 0x0a, 0xbb, 0x86, 0xaf, 0x58, 0xb0, 0x68, - 0x87, 0x40, 0x89, 0x2b, 0x8d, 0xff, 0x83, 0x40, - 0xac, 0x84, 0xad, 0x86, 0xaf, 0x46}; - static const u8 n4_other[] = - {0x66, 0x00, 0x7f, 0x00, 0x80, 0xac, 0x81, 0x69, - 0x84, 0x40, 0x85, 0x70, 0x86, 0x20, 0x8a, 0x68, - 0x8b, 0x58, 0x8c, 0x88, 0x8d, 0xff, 0x8e, 0xb8, - 0x8f, 0x28, 0xa2, 0x60, 0xa5, 0x40, 0xa8, 0xa8, - 0xac, 0x84, 0xad, 0x84, 0xae, 0x24, 0xaf, 0x56, - 0xb0, 0x68, 0xb1, 0x00, 0xb2, 0x88, 0xbb, 0xc5, - 0xbc, 0x4a, 0xbe, 0x36, 0xc2, 0x88, 0xc5, 0xc0, - 0xc6, 0xda, 0xe9, 0x26, 0xeb, 0x00}; - static const u8 nset8[6] = - { 0xa8, 0xf0, 0xc6, 0x88, 0xc0, 0x00 }; - static const u8 nset8_other[6] = - { 0xa8, 0xa8, 0xc6, 0xda, 0xc0, 0x00 }; - static const u8 nset9[4] = - { 0x0b, 0x04, 0x0a, 0x78 }; - static const u8 nset9_other[4] = - { 0x0b, 0x04, 0x0a, 0x00 }; sensor_id = (reg_r(gspca_dev, 0x06) << 8) | reg_r(gspca_dev, 0x07); @@ -709,8 +783,7 @@ static int sd_init(struct gspca_dev *gspca_dev) } if (i < 0) { err("Bad sensor reset %02x", test_byte); -/* return -EIO; */ -/*fixme: test - continue */ + return -EIO; } reg_w_buf(gspca_dev, n2, sizeof n2); } @@ -723,31 +796,17 @@ static int sd_init(struct gspca_dev *gspca_dev) i++; } - if (sd->sensor != SENSOR_OTHER) { - reg_w_buf(gspca_dev, n3, sizeof n3); - reg_w_buf(gspca_dev, n4, sizeof n4); - reg_r(gspca_dev, 0x0080); - reg_w(gspca_dev, 0x2c80); - reg80 = 0x3880; - reg8e = 0x338e; - } else { - reg_w_buf(gspca_dev, n3_other, sizeof n3_other); - reg_w_buf(gspca_dev, n4_other, sizeof n4_other); - sd->gamma = 5; - reg80 = 0xac80; - reg8e = 0xb88e; - } + sensor = &sensor_data[sd->sensor]; + reg_w_buf(gspca_dev, sensor->n3, sizeof sensor->n3); + reg_w_buf(gspca_dev, sensor->n4, sensor->n4sz); - reg_w_ixbuf(gspca_dev, 0xd0, sensor_data[sd->sensor].data1, - sizeof sensor_data[sd->sensor].data1); - reg_w_ixbuf(gspca_dev, 0xc7, sensor_data[sd->sensor].data2, - sizeof sensor_data[sd->sensor].data2); - reg_w_ixbuf(gspca_dev, 0xe0, sensor_data[sd->sensor].data2, - sizeof sensor_data[sd->sensor].data2); + reg_w_ixbuf(gspca_dev, 0xd0, sensor->data1, sizeof sensor->data1); + reg_w_ixbuf(gspca_dev, 0xc7, sensor->data2, sizeof sensor->data2); + reg_w_ixbuf(gspca_dev, 0xe0, sensor->data3, sizeof sensor->data3); - reg_w(gspca_dev, reg80); - reg_w(gspca_dev, reg80); - reg_w(gspca_dev, reg8e); + reg_w(gspca_dev, (sensor->reg80 << 8) + 0x80); + reg_w(gspca_dev, (sensor->reg80 << 8) + 0x80); + reg_w(gspca_dev, (sensor->reg8e << 8) + 0x8e); setbrightness(gspca_dev); setcontrast(gspca_dev); @@ -760,25 +819,14 @@ static int sd_init(struct gspca_dev *gspca_dev) reg_w(gspca_dev, 0x2088); reg_w(gspca_dev, 0x2089); - reg_w_buf(gspca_dev, sensor_data[sd->sensor].data4, - sizeof sensor_data[sd->sensor].data4); - reg_w_buf(gspca_dev, sensor_data[sd->sensor].data5, - sizeof sensor_data[sd->sensor].data5); - if (sd->sensor != SENSOR_OTHER) { - reg_w_buf(gspca_dev, nset8, sizeof nset8); - reg_w_buf(gspca_dev, nset9, sizeof nset9); - reg_w(gspca_dev, 0x2880); - } else { - reg_w_buf(gspca_dev, nset8_other, sizeof nset8_other); - reg_w_buf(gspca_dev, nset9_other, sizeof nset9_other); - } + reg_w_buf(gspca_dev, sensor->data4, sizeof sensor->data4); + reg_w_buf(gspca_dev, sensor->data5, sizeof sensor->data5); + reg_w_buf(gspca_dev, sensor->nset8, sizeof sensor->nset8); + reg_w_buf(gspca_dev, sensor->stream, sizeof sensor->stream); - reg_w_ixbuf(gspca_dev, 0xd0, sensor_data[sd->sensor].data1, - sizeof sensor_data[sd->sensor].data1); - reg_w_ixbuf(gspca_dev, 0xc7, sensor_data[sd->sensor].data2, - sizeof sensor_data[sd->sensor].data2); - reg_w_ixbuf(gspca_dev, 0xe0, sensor_data[sd->sensor].data2, - sizeof sensor_data[sd->sensor].data2); + reg_w_ixbuf(gspca_dev, 0xd0, sensor->data1, sizeof sensor->data1); + reg_w_ixbuf(gspca_dev, 0xc7, sensor->data2, sizeof sensor->data2); + reg_w_ixbuf(gspca_dev, 0xe0, sensor->data3, sizeof sensor->data3); return 0; } @@ -828,7 +876,6 @@ static void setlightfreq(struct gspca_dev *gspca_dev) * i added some module parameters for test with some users */ static void poll_sensor(struct gspca_dev *gspca_dev) { - struct sd *sd = (struct sd *) gspca_dev; static const u8 poll1[] = {0x67, 0x05, 0x68, 0x81, 0x69, 0x80, 0x6a, 0x82, 0x6b, 0x68, 0x6c, 0x69, 0x72, 0xd9, 0x73, 0x34, @@ -844,24 +891,23 @@ static void poll_sensor(struct gspca_dev *gspca_dev) 0xa1, 0xb1, 0xda, 0x6b, 0xdb, 0x98, 0xdf, 0x0c, 0xc2, 0x80, 0xc3, 0x10}; - if (sd->sensor == SENSOR_OM6802) { - PDEBUG(D_STREAM, "[Sensor requires polling]"); - reg_w_buf(gspca_dev, poll1, sizeof poll1); - reg_w_buf(gspca_dev, poll2, sizeof poll2); - reg_w_buf(gspca_dev, poll3, sizeof poll3); - reg_w_buf(gspca_dev, poll4, sizeof poll4); - } + PDEBUG(D_STREAM, "[Sensor requires polling]"); + reg_w_buf(gspca_dev, poll1, sizeof poll1); + reg_w_buf(gspca_dev, poll2, sizeof poll2); + reg_w_buf(gspca_dev, poll3, sizeof poll3); + reg_w_buf(gspca_dev, poll4, sizeof poll4); } static int sd_start(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; + const struct additional_sensor_data *sensor; int i, mode; u8 t2[] = { 0x07, 0x00, 0x0d, 0x60, 0x0e, 0x80 }; static const u8 t3[] = { 0x07, 0x00, 0x88, 0x02, 0x06, 0x00, 0xe7, 0x01 }; - mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode]. priv; + mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv; switch (mode) { case 0: /* 640x480 (0x00) */ break; @@ -889,35 +935,39 @@ static int sd_start(struct gspca_dev *gspca_dev) default: /* case SENSOR_TAS5130A: */ i = 0; - while (tas5130a_sensor_init[i][0] != 0) { + for (;;) { reg_w_buf(gspca_dev, tas5130a_sensor_init[i], sizeof tas5130a_sensor_init[0]); + if (i >= ARRAY_SIZE(tas5130a_sensor_init) - 1) + break; i++; } reg_w(gspca_dev, 0x3c80); /* just in case and to keep sync with logs (for mine) */ - reg_w_buf(gspca_dev, tas5130a_sensor_init[3], + reg_w_buf(gspca_dev, tas5130a_sensor_init[i], sizeof tas5130a_sensor_init[0]); reg_w(gspca_dev, 0x3c80); break; } - reg_w_buf(gspca_dev, sensor_data[sd->sensor].data4, - sizeof sensor_data[sd->sensor].data4); + sensor = &sensor_data[sd->sensor]; + reg_w_buf(gspca_dev, sensor->data4, sizeof sensor->data4); reg_r(gspca_dev, 0x0012); reg_w_buf(gspca_dev, t2, sizeof t2); reg_w_ixbuf(gspca_dev, 0xb3, t3, sizeof t3); reg_w(gspca_dev, 0x0013); msleep(15); - reg_w_buf(gspca_dev, sensor_data[sd->sensor].stream, - sizeof sensor_data[sd->sensor].stream); - poll_sensor(gspca_dev); + reg_w_buf(gspca_dev, sensor->stream, sizeof sensor->stream); + reg_w_buf(gspca_dev, sensor->stream, sizeof sensor->stream); + + if (sd->sensor == SENSOR_OM6802) + poll_sensor(gspca_dev); +#if 0 /* restart on each start, just in case, sometimes regs goes wrong * when using controls from app */ setbrightness(gspca_dev); setcontrast(gspca_dev); setcolors(gspca_dev); -#if 0 seteffect(gspca_dev); setflip(gspca_dev); #endif @@ -930,10 +980,9 @@ static void sd_stopN(struct gspca_dev *gspca_dev) reg_w_buf(gspca_dev, sensor_data[sd->sensor].stream, sizeof sensor_data[sd->sensor].stream); - msleep(20); reg_w_buf(gspca_dev, sensor_data[sd->sensor].stream, sizeof sensor_data[sd->sensor].stream); - if (sd->sensor != SENSOR_OTHER) { + if (sd->sensor == SENSOR_OM6802) { msleep(20); reg_w(gspca_dev, 0x0309); } -- cgit v1.2.3 From a1c8491b8f5c2464b7f0fabb43dca9ac3690c097 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Tue, 7 Jul 2009 09:13:23 +0200 Subject: gspca - main: Version change. From: Jean-Francois Moine Priority: normal Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/gspca.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/gspca.c b/linux/drivers/media/video/gspca/gspca.c index e526d9323..fe759178f 100644 --- a/linux/drivers/media/video/gspca/gspca.c +++ b/linux/drivers/media/video/gspca/gspca.c @@ -51,7 +51,7 @@ MODULE_AUTHOR("Jean-Francois Moine "); MODULE_DESCRIPTION("GSPCA USB Camera Driver"); MODULE_LICENSE("GPL"); -#define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 6, 0) +#define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 7, 0) #ifdef GSPCA_DEBUG int gspca_debug = D_ERR | D_PROBE; -- cgit v1.2.3 From e18804d1a527fe032a9ca9c4ce0b19bcd1e4b9e5 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Wed, 8 Jul 2009 10:21:50 +0200 Subject: gspca - sonixj: Bad sensor init of non ov76xx sensors. From: Jean-Francois Moine The bug was introduced when adding the light frequency control Priority: high Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/sonixj.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/sonixj.c b/linux/drivers/media/video/gspca/sonixj.c index a2fb94eb7..915b3a13e 100644 --- a/linux/drivers/media/video/gspca/sonixj.c +++ b/linux/drivers/media/video/gspca/sonixj.c @@ -1666,6 +1666,8 @@ static void setfreq(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; + if (gspca_dev->ctrl_dis & (1 << FREQ_IDX)) + return; if (sd->sensor == SENSOR_OV7660) { switch (sd->freq) { case 0: /* Banding filter disabled */ -- cgit v1.2.3 From c0f8b9a193501684bb2c80845b24d71465941e03 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Wed, 8 Jul 2009 11:33:44 +0200 Subject: gspca - sonixj: Remove auto gain/wb/expo for the ov7660 sensor. From: Jean-Francois Moine Priority: normal Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/sonixj.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/sonixj.c b/linux/drivers/media/video/gspca/sonixj.c index 915b3a13e..3d2722704 100644 --- a/linux/drivers/media/video/gspca/sonixj.c +++ b/linux/drivers/media/video/gspca/sonixj.c @@ -735,13 +735,17 @@ static const u8 ov7660_sensor_init[][8] = { {0xa1, 0x21, 0x12, 0x05, 0x00, 0x00, 0x00, 0x10}, /* Outformat = rawRGB */ {0xa1, 0x21, 0x13, 0xb8, 0x00, 0x00, 0x00, 0x10}, /* init COM8 */ - {0xd1, 0x21, 0x00, 0x01, 0x74, 0x74, 0x00, 0x10}, + {0xd1, 0x21, 0x00, 0x01, 0x74, 0x92, 0x00, 0x10}, /* GAIN BLUE RED VREF */ {0xd1, 0x21, 0x04, 0x00, 0x7d, 0x62, 0x00, 0x10}, /* COM 1 BAVE GEAVE AECHH */ {0xb1, 0x21, 0x08, 0x83, 0x01, 0x00, 0x00, 0x10}, /* RAVE COM2 */ {0xd1, 0x21, 0x0c, 0x00, 0x08, 0x04, 0x4f, 0x10}, /* COM 3 4 5 6 */ +#if 1 + {0xd1, 0x21, 0x10, 0x7f, 0x40, 0x05, 0xf8, 0x10}, +#else {0xd1, 0x21, 0x10, 0x7f, 0x40, 0x05, 0xff, 0x10}, +#endif /* AECH CLKRC COM7 COM8 */ {0xc1, 0x21, 0x14, 0x2c, 0x00, 0x02, 0x00, 0x10}, /* COM9 COM10 */ {0xd1, 0x21, 0x17, 0x10, 0x60, 0x02, 0x7b, 0x10}, @@ -1669,16 +1673,23 @@ static void setfreq(struct gspca_dev *gspca_dev) if (gspca_dev->ctrl_dis & (1 << FREQ_IDX)) return; if (sd->sensor == SENSOR_OV7660) { + u8 com8; + +#if 1 + com8 = 0xf8; /* no auto gain/wb/expo */ +#else + com8 = 0xff; +#endif switch (sd->freq) { case 0: /* Banding filter disabled */ - i2c_w1(gspca_dev, 0x13, 0xdf); + i2c_w1(gspca_dev, 0x13, com8 & 0xdf); break; case 1: /* 50 hz */ - i2c_w1(gspca_dev, 0x13, 0xff); + i2c_w1(gspca_dev, 0x13, com8); i2c_w1(gspca_dev, 0x3b, 0x0a); break; case 2: /* 60 hz */ - i2c_w1(gspca_dev, 0x13, 0xff); + i2c_w1(gspca_dev, 0x13, com8); i2c_w1(gspca_dev, 0x3b, 0x02); break; } -- cgit v1.2.3 From 1bc63b5e2937a0a86714eb692c820245116e1325 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20Andr=C3=A9n?= Date: Wed, 8 Jul 2009 19:47:16 +0200 Subject: gspca - m5602-s5k4aa: Remove erroneous register writes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: Erik Andrén A couple of erroneous register writes snuck in that made the image go haywire. Remove these. Many thanks to Grégory Lardière for finding this out Priority: high Signed-off-by: Erik Andrén --- linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c | 6 ------ 1 file changed, 6 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c b/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c index 4a105cb38..1dd7c161f 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c @@ -476,9 +476,6 @@ static int s5k4aa_set_vflip(struct gspca_dev *gspca_dev, __s32 val) PDEBUG(D_V4L2, "Set vertical flip to %d", val); err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1); - if (err < 0) - return err; - err = m5602_write_sensor(sd, S5K4AA_READ_MODE, &data, 1); if (err < 0) return err; @@ -524,9 +521,6 @@ static int s5k4aa_set_hflip(struct gspca_dev *gspca_dev, __s32 val) PDEBUG(D_V4L2, "Set horizontal flip to %d", val); err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1); - if (err < 0) - return err; - err = m5602_write_sensor(sd, S5K4AA_READ_MODE, &data, 1); if (err < 0) return err; -- cgit v1.2.3 From 070ce9c8a3bce3b2cea1976e129d0e4731c1538a Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Wed, 8 Jul 2009 20:51:35 -0400 Subject: em28xx: make support work for the Pinnacle Hybrid Pro (eb1a:2881) From: Devin Heitmueller Setup the GPIOs properly and enable support for the DVB side of the Pinnacle Hybrid Pro USB stick. Thanks to Andreas Lunderhage for testing patches and providing a remote debug environment. Priority: normal Cc: Andreas Lunderhage Signed-off-by: Devin Heitmueller --- linux/drivers/media/video/em28xx/em28xx-cards.c | 26 ++++++++++++++++++------- linux/drivers/media/video/em28xx/em28xx-dvb.c | 1 + 2 files changed, 20 insertions(+), 7 deletions(-) (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 e13f141c7..2fe7a85fc 100644 --- a/linux/drivers/media/video/em28xx/em28xx-cards.c +++ b/linux/drivers/media/video/em28xx/em28xx-cards.c @@ -172,6 +172,20 @@ static struct em28xx_reg_seq evga_indtube_digital[] = { { -1, -1, -1, -1}, }; +/* Pinnacle Hybrid Pro eb1a:2881 */ +static struct em28xx_reg_seq pinnacle_hybrid_pro_analog[] = { + {EM28XX_R08_GPIO, 0x6f, ~EM_GPIO_4, 10}, + { -1, -1, -1, -1}, +}; + +static struct em28xx_reg_seq pinnacle_hybrid_pro_digital[] = { + {EM28XX_R08_GPIO, 0x6e, ~EM_GPIO_4, 10}, + {EM2880_R04_GPO, 0x04, 0xff, 100},/* zl10353 reset */ + {EM2880_R04_GPO, 0x0c, 0xff, 1}, + { -1, -1, -1, -1}, +}; + + /* Callback for the most boards */ static struct em28xx_reg_seq default_tuner_gpio[] = { {EM28XX_R08_GPIO, EM_GPIO_4, EM_GPIO_4, 10}, @@ -1303,29 +1317,26 @@ struct em28xx_board em28xx_boards[] = { }, [EM2881_BOARD_PINNACLE_HYBRID_PRO] = { .name = "Pinnacle Hybrid Pro", - .valid = EM28XX_BOARD_NOT_VALIDATED, .tuner_type = TUNER_XC2028, .tuner_gpio = default_tuner_gpio, .decoder = EM28XX_TVP5150, -#if 0 /* FIXME: add an entry at em28xx-dvb */ .has_dvb = 1, - .dvb_gpio = default_digital, -#endif + .dvb_gpio = pinnacle_hybrid_pro_digital, .input = { { .type = EM28XX_VMUX_TELEVISION, .vmux = TVP5150_COMPOSITE0, .amux = EM28XX_AMUX_VIDEO, - .gpio = default_analog, + .gpio = pinnacle_hybrid_pro_analog, }, { .type = EM28XX_VMUX_COMPOSITE1, .vmux = TVP5150_COMPOSITE1, .amux = EM28XX_AMUX_LINE_IN, - .gpio = default_analog, + .gpio = pinnacle_hybrid_pro_analog, }, { .type = EM28XX_VMUX_SVIDEO, .vmux = TVP5150_SVIDEO, .amux = EM28XX_AMUX_LINE_IN, - .gpio = default_analog, + .gpio = pinnacle_hybrid_pro_analog, } }, }, [EM2882_BOARD_PINNACLE_HYBRID_PRO] = { @@ -1709,6 +1720,7 @@ static struct em28xx_hash_table em28xx_eeprom_hash[] = { {0x966a0441, EM2880_BOARD_KWORLD_DVB_310U, TUNER_XC2028}, {0x9567eb1a, EM2880_BOARD_EMPIRE_DUAL_TV, TUNER_XC2028}, {0xcee44a99, EM2882_BOARD_EVGA_INDTUBE, TUNER_XC2028}, + {0xb8846b20, EM2881_BOARD_PINNACLE_HYBRID_PRO, TUNER_XC2028}, }; /* I2C devicelist hash table for devices with generic USB IDs */ diff --git a/linux/drivers/media/video/em28xx/em28xx-dvb.c b/linux/drivers/media/video/em28xx/em28xx-dvb.c index 86be58641..36c5197ee 100644 --- a/linux/drivers/media/video/em28xx/em28xx-dvb.c +++ b/linux/drivers/media/video/em28xx/em28xx-dvb.c @@ -453,6 +453,7 @@ static int dvb_init(struct em28xx *dev) } break; case EM2880_BOARD_TERRATEC_HYBRID_XS: + case EM2881_BOARD_PINNACLE_HYBRID_PRO: dvb->frontend = dvb_attach(zl10353_attach, &em28xx_terratec_xs_zl10353_xc3028, &dev->i2c_adap); -- cgit v1.2.3 From 0898779f1c75c6821866a08052cd171590af009c Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Wed, 8 Jul 2009 21:18:15 -0400 Subject: em28xx: set GPIO properly for Pinnacle Hybrid Pro analog support From: Devin Heitmueller Set the GPIO properly for the analog side of the Pinnacle Hybrid Pro, or else the emp202 doesn't get detected properly. Priority: normal Signed-off-by: Devin Heitmueller --- linux/drivers/media/video/em28xx/em28xx-cards.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (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 2fe7a85fc..3599d6223 100644 --- a/linux/drivers/media/video/em28xx/em28xx-cards.c +++ b/linux/drivers/media/video/em28xx/em28xx-cards.c @@ -174,7 +174,7 @@ static struct em28xx_reg_seq evga_indtube_digital[] = { /* Pinnacle Hybrid Pro eb1a:2881 */ static struct em28xx_reg_seq pinnacle_hybrid_pro_analog[] = { - {EM28XX_R08_GPIO, 0x6f, ~EM_GPIO_4, 10}, + {EM28XX_R08_GPIO, 0xfd, ~EM_GPIO_4, 10}, { -1, -1, -1, -1}, }; -- cgit v1.2.3 From e85e9d72ef3cca1749a676ac0e0a99506f2e87c3 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Thu, 9 Jul 2009 08:28:46 +0200 Subject: gspca - sunplus: Webcam 052b:1803 added. From: Johannes Goerner Priority: normal Signed-off-by: Johannes Goerner Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/sunplus.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/sunplus.c b/linux/drivers/media/video/gspca/sunplus.c index 16bc65dc7..f23594e0b 100644 --- a/linux/drivers/media/video/gspca/sunplus.c +++ b/linux/drivers/media/video/gspca/sunplus.c @@ -52,6 +52,7 @@ struct sd { #define LogitechClickSmart420 2 #define LogitechClickSmart820 3 #define MegapixV4 4 +#define MegaImageVI 5 u8 *jpeg_hdr; }; @@ -875,7 +876,10 @@ static int sd_config(struct gspca_dev *gspca_dev, break; case BRIDGE_SPCA533: cam->cam_mode = custom_mode; - cam->nmodes = sizeof custom_mode / sizeof custom_mode[0]; + if (sd->subtype == MegaImageVI) /* 320x240 only */ + cam->nmodes = ARRAY_SIZE(custom_mode) - 1; + else + cam->nmodes = ARRAY_SIZE(custom_mode); break; case BRIDGE_SPCA504C: cam->cam_mode = vga_mode2; @@ -1017,7 +1021,8 @@ static int sd_start(struct gspca_dev *gspca_dev) /* case BRIDGE_SPCA533: */ /* case BRIDGE_SPCA536: */ if (sd->subtype == MegapixV4 || - sd->subtype == LogitechClickSmart820) { + sd->subtype == LogitechClickSmart820 || + sd->subtype == MegaImageVI) { reg_w(gspca_dev, 0xf0, 0, 0, 0); spca504B_WaitCmdStatus(gspca_dev); reg_r(gspca_dev, 0xf0, 4, 0); @@ -1413,6 +1418,7 @@ static const __devinitdata struct usb_device_id device_table[] = { {USB_DEVICE(0x04fc, 0x5360), BS(SPCA536, 0)}, {USB_DEVICE(0x04fc, 0xffff), BS(SPCA504B, 0)}, {USB_DEVICE(0x052b, 0x1513), BS(SPCA533, MegapixV4)}, + {USB_DEVICE(0x052b, 0x1803), BS(SPCA533, MegaImageVI)}, {USB_DEVICE(0x0546, 0x3155), BS(SPCA533, 0)}, {USB_DEVICE(0x0546, 0x3191), BS(SPCA504B, 0)}, {USB_DEVICE(0x0546, 0x3273), BS(SPCA504B, 0)}, -- cgit v1.2.3 From 4e59bbd4f49a574bb00ea82a9394afe1f62cd317 Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Sat, 11 Jul 2009 02:03:43 +0300 Subject: af9013: auto-detect parameters in case of garbage given by app From: Antti Palosaari Request demodulator auto-detect transmission parameters in case of garbage parameters provided by application for compatibility. That's needed at least for MPlayer compatibility currently. Thanks to Jelle de Jong for reporting issue and providing SSH access to Devin for debugging. Thanks to Devin Heitmueller for hard debug work he did to find that bug. Priority: high Signed-off-by: Antti Palosaari Cc: Devin Heitmueller Cc: Jelle de Jong --- linux/drivers/media/dvb/frontends/af9013.c | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/frontends/af9013.c b/linux/drivers/media/dvb/frontends/af9013.c index d12d99802..62d3185ee 100644 --- a/linux/drivers/media/dvb/frontends/af9013.c +++ b/linux/drivers/media/dvb/frontends/af9013.c @@ -528,6 +528,10 @@ static int af9013_set_ofdm_params(struct af9013_state *state, u8 i, buf[3] = {0, 0, 0}; *auto_mode = 0; /* set if parameters are requested to auto set */ + /* Try auto-detect transmission parameters in case of AUTO requested or + garbage parameters given by application for compatibility. + MPlayer seems to provide garbage parameters currently. */ + switch (params->transmission_mode) { case TRANSMISSION_MODE_AUTO: *auto_mode = 1; @@ -537,7 +541,8 @@ static int af9013_set_ofdm_params(struct af9013_state *state, buf[0] |= (1 << 0); break; default: - return -EINVAL; + deb_info("%s: invalid transmission_mode\n", __func__); + *auto_mode = 1; } switch (params->guard_interval) { @@ -555,7 +560,8 @@ static int af9013_set_ofdm_params(struct af9013_state *state, buf[0] |= (3 << 2); break; default: - return -EINVAL; + deb_info("%s: invalid guard_interval\n", __func__); + *auto_mode = 1; } switch (params->hierarchy_information) { @@ -573,7 +579,8 @@ static int af9013_set_ofdm_params(struct af9013_state *state, buf[0] |= (3 << 4); break; default: - return -EINVAL; + deb_info("%s: invalid hierarchy_information\n", __func__); + *auto_mode = 1; }; switch (params->constellation) { @@ -588,7 +595,8 @@ static int af9013_set_ofdm_params(struct af9013_state *state, buf[1] |= (2 << 6); break; default: - return -EINVAL; + deb_info("%s: invalid constellation\n", __func__); + *auto_mode = 1; } /* Use HP. How and which case we can switch to LP? */ @@ -612,7 +620,8 @@ static int af9013_set_ofdm_params(struct af9013_state *state, buf[2] |= (4 << 0); break; default: - return -EINVAL; + deb_info("%s: invalid code_rate_HP\n", __func__); + *auto_mode = 1; } switch (params->code_rate_LP) { @@ -639,7 +648,8 @@ static int af9013_set_ofdm_params(struct af9013_state *state, if (params->hierarchy_information == HIERARCHY_AUTO) break; default: - return -EINVAL; + deb_info("%s: invalid code_rate_LP\n", __func__); + *auto_mode = 1; } switch (params->bandwidth) { @@ -652,7 +662,8 @@ static int af9013_set_ofdm_params(struct af9013_state *state, buf[1] |= (2 << 2); break; default: - return -EINVAL; + deb_info("%s: invalid bandwidth\n", __func__); + buf[1] |= (2 << 2); /* cannot auto-detect BW, try 8 MHz */ } /* program */ -- cgit v1.2.3 From 3301abf170615ab6fa08ca3b456980b67c22022b Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 12 Jul 2009 10:23:23 -0300 Subject: em28xx: rename is_27xx to is_webcam From: Mauro Carvalho Chehab Just renames the flag, to use a clearer name. Later patches will use this flag to properly set some drivers behaviors for webcams. Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/em28xx/em28xx-cards.c | 4 ++-- linux/drivers/media/video/em28xx/em28xx-core.c | 4 ++-- linux/drivers/media/video/em28xx/em28xx-video.c | 4 ++-- linux/drivers/media/video/em28xx/em28xx.h | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) (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 e13f141c7..040303cf6 100644 --- a/linux/drivers/media/video/em28xx/em28xx-cards.c +++ b/linux/drivers/media/video/em28xx/em28xx-cards.c @@ -463,7 +463,7 @@ struct em28xx_board em28xx_boards[] = { [EM2820_BOARD_SILVERCREST_WEBCAM] = { .name = "Silvercrest Webcam 1.3mpix", .tuner_type = TUNER_ABSENT, - .is_27xx = 1, + .is_webcam = 1, .decoder = EM28XX_MT9V011, .input = { { .type = EM28XX_VMUX_COMPOSITE1, @@ -1843,7 +1843,7 @@ void em28xx_pre_card_setup(struct em28xx *dev) em28xx_info("chip ID is em2750\n"); break; case CHIP_ID_EM2820: - if (dev->board.is_27xx) + if (dev->board.is_webcam) em28xx_info("chip is em2710\n"); else em28xx_info("chip ID is em2820\n"); diff --git a/linux/drivers/media/video/em28xx/em28xx-core.c b/linux/drivers/media/video/em28xx/em28xx-core.c index 1033824bd..420e343f2 100644 --- a/linux/drivers/media/video/em28xx/em28xx-core.c +++ b/linux/drivers/media/video/em28xx/em28xx-core.c @@ -652,7 +652,7 @@ int em28xx_set_outfmt(struct em28xx *dev) outfmt = dev->format->reg; - if (dev->board.is_27xx) { + if (dev->board.is_webcam) { vinmode = 0x0d; vinctl = 0x00; } else { @@ -707,7 +707,7 @@ static int em28xx_scaler_set(struct em28xx *dev, u16 h, u16 v) u8 mode; /* the em2800 scaler only supports scaling down to 50% */ - if (dev->board.is_27xx) { + if (dev->board.is_webcam) { /* FIXME: Don't use the scaler yet */ mode = 0; } else if (dev->board.is_em2800) { diff --git a/linux/drivers/media/video/em28xx/em28xx-video.c b/linux/drivers/media/video/em28xx/em28xx-video.c index b0554ab08..e447c9f0a 100644 --- a/linux/drivers/media/video/em28xx/em28xx-video.c +++ b/linux/drivers/media/video/em28xx/em28xx-video.c @@ -748,7 +748,7 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, return -EINVAL; } - if (dev->board.is_27xx) { + if (dev->board.is_webcam) { /* FIXME: This is the only supported fmt */ width = 640; height = 480; @@ -790,7 +790,7 @@ static int em28xx_set_video_format(struct em28xx *dev, unsigned int fourcc, struct em28xx_fmt *fmt; /* FIXME: This is the only supported fmt */ - if (dev->board.is_27xx) { + if (dev->board.is_webcam) { width = 640; height = 480; } diff --git a/linux/drivers/media/video/em28xx/em28xx.h b/linux/drivers/media/video/em28xx/em28xx.h index 2eedfef53..459a84e40 100644 --- a/linux/drivers/media/video/em28xx/em28xx.h +++ b/linux/drivers/media/video/em28xx/em28xx.h @@ -391,7 +391,7 @@ struct em28xx_board { unsigned int max_range_640_480:1; unsigned int has_dvb:1; unsigned int has_snapshot_button:1; - unsigned int is_27xx:1; + unsigned int is_webcam:1; unsigned int valid:1; unsigned char xclk, i2c_speed; -- cgit v1.2.3 From 2fcdd2e821f5a9e43d178378bd1d8801158ea794 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 12 Jul 2009 10:26:36 -0300 Subject: em28xx-cards: use is_webcam flag for devices that are known to be webcams From: Mauro Carvalho Chehab By having the webcam devices marked as such, it will help the em28xx driver to do the right thing on those devices. Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/em28xx/em28xx-cards.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (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 040303cf6..f8a3f28a2 100644 --- a/linux/drivers/media/video/em28xx/em28xx-cards.c +++ b/linux/drivers/media/video/em28xx/em28xx-cards.c @@ -220,7 +220,8 @@ struct em28xx_board em28xx_boards[] = { [EM2750_BOARD_UNKNOWN] = { .name = "Unknown EM2750/EM2751 webcam grabber", .xclk = EM28XX_XCLK_FREQUENCY_48MHZ, - .tuner_type = TUNER_ABSENT, /* This is a webcam */ + .tuner_type = TUNER_ABSENT, + .is_webcam = 1, .input = { { .type = EM28XX_VMUX_COMPOSITE1, .vmux = 0, @@ -252,7 +253,8 @@ struct em28xx_board em28xx_boards[] = { .name = "Huaqi DLCW-130", .valid = EM28XX_BOARD_NOT_VALIDATED, .xclk = EM28XX_XCLK_FREQUENCY_48MHZ, - .tuner_type = TUNER_ABSENT, /* This is a webcam */ + .tuner_type = TUNER_ABSENT, + .is_webcam = 1, .input = { { .type = EM28XX_VMUX_COMPOSITE1, .vmux = 0, @@ -453,7 +455,8 @@ struct em28xx_board em28xx_boards[] = { [EM2820_BOARD_VIDEOLOGY_20K14XUSB] = { .name = "Videology 20K14XUSB USB2.0", .valid = EM28XX_BOARD_NOT_VALIDATED, - .tuner_type = TUNER_ABSENT, /* This is a webcam */ + .tuner_type = TUNER_ABSENT, + .is_webcam = 1, .input = { { .type = EM28XX_VMUX_COMPOSITE1, .vmux = 0, @@ -513,7 +516,8 @@ struct em28xx_board em28xx_boards[] = { /* Beijing Huaqi Information Digital Technology Co., Ltd */ .name = "NetGMBH Cam", .valid = EM28XX_BOARD_NOT_VALIDATED, - .tuner_type = TUNER_ABSENT, /* This is a webcam */ + .tuner_type = TUNER_ABSENT, + .is_webcam = 1, .input = { { .type = EM28XX_VMUX_COMPOSITE1, .vmux = 0, -- cgit v1.2.3 From 6cef2ed6aed0628ee5e9eb3c56a5b265ce53d128 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 12 Jul 2009 10:56:21 -0300 Subject: em28xx: detects sensors also with the generic em2750/2750 entry From: Mauro Carvalho Chehab Webcams in general don't have eeprom. So, the sensor hint code should be called to properly detect what sensor is inside. Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/em28xx/em28xx-cards.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (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 f8a3f28a2..a50ef1216 100644 --- a/linux/drivers/media/video/em28xx/em28xx-cards.c +++ b/linux/drivers/media/video/em28xx/em28xx-cards.c @@ -218,7 +218,7 @@ static struct em28xx_reg_seq silvercrest_reg_seq[] = { */ struct em28xx_board em28xx_boards[] = { [EM2750_BOARD_UNKNOWN] = { - .name = "Unknown EM2750/EM2751 webcam grabber", + .name = "EM2710/EM2750/EM2751 webcam grabber", .xclk = EM28XX_XCLK_FREQUENCY_48MHZ, .tuner_type = TUNER_ABSENT, .is_webcam = 1, @@ -1791,7 +1791,8 @@ static int em28xx_hint_sensor(struct em28xx *dev) __be16 version_be; u16 version; - if (dev->model != EM2820_BOARD_UNKNOWN) + if (dev->model != EM2820_BOARD_UNKNOWN && + dev->model != EM2750_BOARD_UNKNOWN) return 0; dev->i2c_client.addr = 0xba >> 1; @@ -1809,11 +1810,11 @@ static int em28xx_hint_sensor(struct em28xx *dev) sensor_name = "mt9v011"; break; default: - printk("Unknown Sensor 0x%04x\n", be16_to_cpu(version)); + printk("Unknown Micron Sensor 0x%04x\n", be16_to_cpu(version)); return -EINVAL; } - em28xx_errdev("Sensor is %s, assuming that webcam is %s\n", + em28xx_errdev("Sensor is %s, using model %s entry.\n", sensor_name, em28xx_boards[dev->model].name); return 0; -- cgit v1.2.3 From 1b0617b59589491cf91d95950da297a72b9c42ad Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 12 Jul 2009 11:04:15 -0300 Subject: em28xx: stop abusing of board->decoder for sensor information From: Mauro Carvalho Chehab Instead of using em28xx board decoder field for storing sensor information, let's use instead a separate field for it. Also, as sensors are currently autodetected, there's no need of having it at the boards description. So, move it to the main em28xx struct. Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/em28xx/em28xx-cards.c | 4 ++-- linux/drivers/media/video/em28xx/em28xx.h | 8 +++++++- 2 files changed, 9 insertions(+), 3 deletions(-) (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 a50ef1216..5f063e4a1 100644 --- a/linux/drivers/media/video/em28xx/em28xx-cards.c +++ b/linux/drivers/media/video/em28xx/em28xx-cards.c @@ -467,7 +467,6 @@ struct em28xx_board em28xx_boards[] = { .name = "Silvercrest Webcam 1.3mpix", .tuner_type = TUNER_ABSENT, .is_webcam = 1, - .decoder = EM28XX_MT9V011, .input = { { .type = EM28XX_VMUX_COMPOSITE1, .vmux = 0, @@ -1808,6 +1807,7 @@ static int em28xx_hint_sensor(struct em28xx *dev) case MT9V011_VERSION: dev->model = EM2820_BOARD_SILVERCREST_WEBCAM; sensor_name = "mt9v011"; + dev->em28xx_sensor = EM28XX_MT9V011; break; default: printk("Unknown Micron Sensor 0x%04x\n", be16_to_cpu(version)); @@ -2372,7 +2372,7 @@ void em28xx_card_setup(struct em28xx *dev) v4l2_i2c_new_probed_subdev(&dev->v4l2_dev, &dev->i2c_adap, "tvp5150", "tvp5150", tvp5150_addrs); - if (dev->board.decoder == EM28XX_MT9V011) + if (dev->em28xx_sensor == EM28XX_MT9V011) v4l2_i2c_new_probed_subdev(&dev->v4l2_dev, &dev->i2c_adap, "mt9v011", "mt9v011", mt9v011_addrs); diff --git a/linux/drivers/media/video/em28xx/em28xx.h b/linux/drivers/media/video/em28xx/em28xx.h index 459a84e40..559903b2a 100644 --- a/linux/drivers/media/video/em28xx/em28xx.h +++ b/linux/drivers/media/video/em28xx/em28xx.h @@ -359,9 +359,13 @@ struct em28xx_input { #define INPUT(nr) (&em28xx_boards[dev->model].input[nr]) enum em28xx_decoder { - EM28XX_NODECODER, + EM28XX_NODECODER = 0, EM28XX_TVP5150, EM28XX_SAA711X, +}; + +enum em28xx_sensor { + EM28XX_NOSENSOR = 0, EM28XX_MT9V011, }; @@ -483,6 +487,8 @@ struct em28xx { struct v4l2_device v4l2_dev; struct em28xx_board board; + enum em28xx_sensor em28xx_sensor; + unsigned int stream_on:1; /* Locks streams */ unsigned int has_audio_class:1; unsigned int has_alsa_audio:1; -- cgit v1.2.3 From 6897951e3af638926c8bf5f660760f4c15fbdee1 Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Sun, 12 Jul 2009 16:05:02 -0400 Subject: em28xx: fix tuning problem in HVR-900 (R1) From: Devin Heitmueller When the change was introduced in the zl10353 for the i2c gate behavior, this broke the HVR-900 which was not behind a gate. Use a version of the zl10353 config profile that indicates the tuner is not behind such a gate. Without this patch the first tune succeeds, but subsequent tuning attempts will fail. The change also renames the terratec zl10353 profile I wrote to be more generic, since it is shared by the non-terratec device. Thanks to Michael Krufky for providing a HVR-900 and DVB-T environment to test with. Priority: high Cc: Michael Krufky Signed-off-by: Devin Heitmueller --- linux/drivers/media/video/em28xx/em28xx-dvb.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/em28xx/em28xx-dvb.c b/linux/drivers/media/video/em28xx/em28xx-dvb.c index 86be58641..032eb38d6 100644 --- a/linux/drivers/media/video/em28xx/em28xx-dvb.c +++ b/linux/drivers/media/video/em28xx/em28xx-dvb.c @@ -244,7 +244,7 @@ static struct s5h1409_config em28xx_s5h1409_with_xc3028 = { .mpeg_timing = S5H1409_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK }; -static struct zl10353_config em28xx_terratec_xs_zl10353_xc3028 = { +static struct zl10353_config em28xx_zl10353_xc3028_no_i2c_gate = { .demod_address = (0x1e >> 1), .no_tuner = 1, .disable_i2c_gate_ctrl = 1, @@ -441,7 +441,6 @@ static int dvb_init(struct em28xx *dev) goto out_free; } break; - case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900: case EM2880_BOARD_KWORLD_DVB_310U: case EM2880_BOARD_EMPIRE_DUAL_TV: dvb->frontend = dvb_attach(zl10353_attach, @@ -452,9 +451,18 @@ static int dvb_init(struct em28xx *dev) goto out_free; } break; + case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900: + dvb->frontend = dvb_attach(zl10353_attach, + &em28xx_zl10353_xc3028_no_i2c_gate, + &dev->i2c_adap); + if (attach_xc3028(0x61, dev) < 0) { + result = -EINVAL; + goto out_free; + } + break; case EM2880_BOARD_TERRATEC_HYBRID_XS: dvb->frontend = dvb_attach(zl10353_attach, - &em28xx_terratec_xs_zl10353_xc3028, + &em28xx_zl10353_xc3028_no_i2c_gate, &dev->i2c_adap); if (dvb->frontend == NULL) { /* This board could have either a zl10353 or a mt352. -- cgit v1.2.3 From 13f1c7cf90c6107ba936578859f469bae7e31a96 Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Sun, 12 Jul 2009 16:51:12 -0400 Subject: em28xx: make tuning work for Terratec Cinergy T XS USB (mt352 variant) From: Devin Heitmueller The Terratec Cinergy T XS USB can have either a zl10353 or an mt352. Add support for the MT352 variant. Thanks to Jelle de Jong for providing a unit to test/debug with. Priority: normal Cc: Jelle de Jong Signed-off-by: Devin Heitmueller --- linux/drivers/media/video/em28xx/em28xx-dvb.c | 47 +++++++++++++++++++++++---- 1 file changed, 41 insertions(+), 6 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/em28xx/em28xx-dvb.c b/linux/drivers/media/video/em28xx/em28xx-dvb.c index 86be58641..56833da59 100644 --- a/linux/drivers/media/video/em28xx/em28xx-dvb.c +++ b/linux/drivers/media/video/em28xx/em28xx-dvb.c @@ -32,6 +32,8 @@ #include "lgdt330x.h" #include "zl10353.h" #include "s5h1409.h" +#include "mt352.h" +#include "mt352_priv.h" /* FIXME */ MODULE_DESCRIPTION("driver for em28xx based DVB cards"); MODULE_AUTHOR("Mauro Carvalho Chehab "); @@ -259,6 +261,41 @@ static struct drx397xD_config em28xx_drx397xD_with_xc3028 = { }; #endif +static int mt352_terratec_xs_init(struct dvb_frontend *fe) +{ + /* Values extracted from a USB trace of the Terratec Windows driver */ + static u8 clock_config[] = { CLOCK_CTL, 0x38, 0x2c }; + static u8 reset[] = { RESET, 0x80 }; + static u8 adc_ctl_1_cfg[] = { ADC_CTL_1, 0x40 }; + static u8 agc_cfg[] = { AGC_TARGET, 0x28, 0xa0 }; + static u8 input_freq_cfg[] = { INPUT_FREQ_1, 0x31, 0xb8 }; + static u8 rs_err_cfg[] = { RS_ERR_PER_1, 0x00, 0x4d }; + static u8 capt_range_cfg[] = { CAPT_RANGE, 0x32 }; + static u8 trl_nom_cfg[] = { TRL_NOMINAL_RATE_1, 0x64, 0x00 }; + static u8 tps_given_cfg[] = { TPS_GIVEN_1, 0x40, 0x80, 0x50 }; + static u8 tuner_go[] = { TUNER_GO, 0x5d}; + + mt352_write(fe, clock_config, sizeof(clock_config)); + udelay(200); + mt352_write(fe, reset, sizeof(reset)); + mt352_write(fe, adc_ctl_1_cfg, sizeof(adc_ctl_1_cfg)); + mt352_write(fe, agc_cfg, sizeof(agc_cfg)); + mt352_write(fe, input_freq_cfg, sizeof(input_freq_cfg)); + mt352_write(fe, rs_err_cfg, sizeof(rs_err_cfg)); + mt352_write(fe, capt_range_cfg, sizeof(capt_range_cfg)); + mt352_write(fe, trl_nom_cfg, sizeof(trl_nom_cfg)); + mt352_write(fe, tps_given_cfg, sizeof(tps_given_cfg)); + mt352_write(fe, tuner_go, sizeof(tuner_go)); + return 0; +} + +static struct mt352_config terratec_xs_mt352_cfg = { + .demod_address = (0x1e >> 1), + .no_tuner = 1, + .if2 = 45600, + .demod_init = mt352_terratec_xs_init, +}; + /* ------------------------------------------------------------------ */ static int attach_xc3028(u8 addr, struct em28xx *dev) @@ -459,13 +496,11 @@ static int dvb_init(struct em28xx *dev) if (dvb->frontend == NULL) { /* This board could have either a zl10353 or a mt352. If the chip id isn't for zl10353, try mt352 */ - - /* FIXME: make support for mt352 work */ - printk(KERN_ERR "version of this board with mt352 not " - "currently supported\n"); - result = -EINVAL; - goto out_free; + dvb->frontend = dvb_attach(mt352_attach, + &terratec_xs_mt352_cfg, + &dev->i2c_adap); } + if (attach_xc3028(0x61, dev) < 0) { result = -EINVAL; goto out_free; -- cgit v1.2.3 From abed55d1925015d07d0afd92eb50a0b2df2eca27 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Sun, 12 Jul 2009 17:25:45 -0400 Subject: sms1xxx: fix broken Hauppauge devices From: Michael Krufky The current GPIO configuration breaks all Hauppauge devices. The code being removed affects Hauppauge devices only, and is the cause of the breakage. Priority: high Signed-off-by: Michael Krufky --- linux/drivers/media/dvb/siano/sms-cards.c | 100 ------------------------------ 1 file changed, 100 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 d8b15d583..76bd3cb82 100644 --- a/linux/drivers/media/dvb/siano/sms-cards.c +++ b/linux/drivers/media/dvb/siano/sms-cards.c @@ -124,91 +124,15 @@ int sms_board_event(struct smscore_device_t *coredev, switch (gevent) { case BOARD_EVENT_POWER_INIT: /* including hotplug */ - switch (board_id) { - case SMS1XXX_BOARD_HAUPPAUGE_WINDHAM: - /* set I/O and turn off all LEDs */ - smscore_gpio_configure(coredev, - board->board_cfg.leds_power, - &MyGpioConfig); - smscore_gpio_set_level(coredev, - board->board_cfg.leds_power, 0); - smscore_gpio_configure(coredev, board->board_cfg.led0, - &MyGpioConfig); - smscore_gpio_set_level(coredev, - board->board_cfg.led0, 0); - smscore_gpio_configure(coredev, board->board_cfg.led1, - &MyGpioConfig); - smscore_gpio_set_level(coredev, - board->board_cfg.led1, 0); - break; - case SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD_R2: - case SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD: - /* set I/O and turn off LNA */ - smscore_gpio_configure(coredev, - board->board_cfg.foreign_lna0_ctrl, - &MyGpioConfig); - smscore_gpio_set_level(coredev, - board->board_cfg.foreign_lna0_ctrl, - 0); - break; - } break; /* BOARD_EVENT_BIND */ case BOARD_EVENT_POWER_SUSPEND: - switch (board_id) { - case SMS1XXX_BOARD_HAUPPAUGE_WINDHAM: - smscore_gpio_set_level(coredev, - board->board_cfg.leds_power, 0); - smscore_gpio_set_level(coredev, - board->board_cfg.led0, 0); - smscore_gpio_set_level(coredev, - board->board_cfg.led1, 0); - break; - case SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD_R2: - case SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD: - smscore_gpio_set_level(coredev, - board->board_cfg.foreign_lna0_ctrl, - 0); - break; - } break; /* BOARD_EVENT_POWER_SUSPEND */ case BOARD_EVENT_POWER_RESUME: - switch (board_id) { - case SMS1XXX_BOARD_HAUPPAUGE_WINDHAM: - smscore_gpio_set_level(coredev, - board->board_cfg.leds_power, 1); - smscore_gpio_set_level(coredev, - board->board_cfg.led0, 1); - smscore_gpio_set_level(coredev, - board->board_cfg.led1, 0); - break; - case SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD_R2: - case SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD: - smscore_gpio_set_level(coredev, - board->board_cfg.foreign_lna0_ctrl, - 1); - break; - } break; /* BOARD_EVENT_POWER_RESUME */ case BOARD_EVENT_BIND: - switch (board_id) { - case SMS1XXX_BOARD_HAUPPAUGE_WINDHAM: - smscore_gpio_set_level(coredev, - board->board_cfg.leds_power, 1); - smscore_gpio_set_level(coredev, - board->board_cfg.led0, 1); - smscore_gpio_set_level(coredev, - board->board_cfg.led1, 0); - break; - case SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD_R2: - case SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD: - smscore_gpio_set_level(coredev, - board->board_cfg.foreign_lna0_ctrl, - 1); - break; - } break; /* BOARD_EVENT_BIND */ case BOARD_EVENT_SCAN_PROG: @@ -218,20 +142,8 @@ int sms_board_event(struct smscore_device_t *coredev, case BOARD_EVENT_EMERGENCY_WARNING_SIGNAL: break; /* BOARD_EVENT_EMERGENCY_WARNING_SIGNAL */ case BOARD_EVENT_FE_LOCK: - switch (board_id) { - case SMS1XXX_BOARD_HAUPPAUGE_WINDHAM: - smscore_gpio_set_level(coredev, - board->board_cfg.led1, 1); - break; - } break; /* BOARD_EVENT_FE_LOCK */ case BOARD_EVENT_FE_UNLOCK: - switch (board_id) { - case SMS1XXX_BOARD_HAUPPAUGE_WINDHAM: - smscore_gpio_set_level(coredev, - board->board_cfg.led1, 0); - break; - } break; /* BOARD_EVENT_FE_UNLOCK */ case BOARD_EVENT_DEMOD_LOCK: break; /* BOARD_EVENT_DEMOD_LOCK */ @@ -248,20 +160,8 @@ int sms_board_event(struct smscore_device_t *coredev, case BOARD_EVENT_RECEPTION_LOST_0: break; /* BOARD_EVENT_RECEPTION_LOST_0 */ case BOARD_EVENT_MULTIPLEX_OK: - switch (board_id) { - case SMS1XXX_BOARD_HAUPPAUGE_WINDHAM: - smscore_gpio_set_level(coredev, - board->board_cfg.led1, 1); - break; - } break; /* BOARD_EVENT_MULTIPLEX_OK */ case BOARD_EVENT_MULTIPLEX_ERRORS: - switch (board_id) { - case SMS1XXX_BOARD_HAUPPAUGE_WINDHAM: - smscore_gpio_set_level(coredev, - board->board_cfg.led1, 0); - break; - } break; /* BOARD_EVENT_MULTIPLEX_ERRORS */ default: -- cgit v1.2.3 From fa9a1b962b866f12ef1eaa0fd14cc9f828b251d6 Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Sun, 12 Jul 2009 17:44:19 -0400 Subject: em28xx: fix typo in mt352 init sequence for Terratec Cinergy T XS USB From: Devin Heitmueller Andy walls pointed out that we were passing 0x5d to the TUNER_GO register, instead of 0x01. Set the register properly (note the code did still work with the incorrect value, so this does not address a regression). Thanks to Andy Walls for noticing the issue. Priority: normal Cc: Andy Walls Signed-off-by: Devin Heitmueller --- linux/drivers/media/video/em28xx/em28xx-dvb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/em28xx/em28xx-dvb.c b/linux/drivers/media/video/em28xx/em28xx-dvb.c index 56833da59..ca881d7c0 100644 --- a/linux/drivers/media/video/em28xx/em28xx-dvb.c +++ b/linux/drivers/media/video/em28xx/em28xx-dvb.c @@ -273,7 +273,7 @@ static int mt352_terratec_xs_init(struct dvb_frontend *fe) static u8 capt_range_cfg[] = { CAPT_RANGE, 0x32 }; static u8 trl_nom_cfg[] = { TRL_NOMINAL_RATE_1, 0x64, 0x00 }; static u8 tps_given_cfg[] = { TPS_GIVEN_1, 0x40, 0x80, 0x50 }; - static u8 tuner_go[] = { TUNER_GO, 0x5d}; + static u8 tuner_go[] = { TUNER_GO, 0x01}; mt352_write(fe, clock_config, sizeof(clock_config)); udelay(200); -- cgit v1.2.3 From db44a7d2b169cceeafa7a8b5fc5b8fe921d4088d Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Sun, 12 Jul 2009 22:30:14 -0400 Subject: sms1xxx: restore GPIO functionality for all Hauppauge devices From: Michael Krufky Previous changesets broke Hauppauge devices and their GPIO configurations. This changeset restores the LED & LNA functionality. Priority: high Signed-off-by: Michael Krufky --- linux/drivers/media/dvb/siano/smsdvb.c | 44 ++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/siano/smsdvb.c b/linux/drivers/media/dvb/siano/smsdvb.c index f8856d9c8..67634899d 100644 --- a/linux/drivers/media/dvb/siano/smsdvb.c +++ b/linux/drivers/media/dvb/siano/smsdvb.c @@ -325,6 +325,16 @@ static int smsdvb_sendrequest_and_wait(struct smsdvb_client_t *client, 0 : -ETIME; } +static inline int led_feedback(struct smsdvb_client_t *client) +{ + if (client->fe_status & FE_HAS_LOCK) + return sms_board_led_feedback(client->coredev, + (client->sms_stat_dvb.ReceptionData.BER + == 0) ? SMS_LED_HI : SMS_LED_LO); + else + return sms_board_led_feedback(client->coredev, SMS_LED_OFF); +} + static int smsdvb_read_status(struct dvb_frontend *fe, fe_status_t *stat) { struct smsdvb_client_t *client; @@ -332,6 +342,8 @@ static int smsdvb_read_status(struct dvb_frontend *fe, fe_status_t *stat) *stat = client->fe_status; + led_feedback(client); + return 0; } @@ -342,6 +354,8 @@ static int smsdvb_read_ber(struct dvb_frontend *fe, u32 *ber) *ber = client->sms_stat_dvb.ReceptionData.BER; + led_feedback(client); + return 0; } @@ -359,6 +373,8 @@ static int smsdvb_read_signal_strength(struct dvb_frontend *fe, u16 *strength) (client->sms_stat_dvb.ReceptionData.InBandPwr + 95) * 3 / 2; + led_feedback(client); + return 0; } @@ -369,6 +385,8 @@ static int smsdvb_read_snr(struct dvb_frontend *fe, u16 *snr) *snr = client->sms_stat_dvb.ReceptionData.SNR; + led_feedback(client); + return 0; } @@ -379,6 +397,8 @@ static int smsdvb_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) *ucblocks = client->sms_stat_dvb.ReceptionData.ErrorTSPackets; + led_feedback(client); + return 0; } @@ -404,6 +424,8 @@ static int smsdvb_set_frontend(struct dvb_frontend *fe, u32 Data[3]; } Msg; + int ret; + client->fe_status = FE_HAS_SIGNAL; client->event_fe_state = -1; client->event_unc_state = -1; @@ -429,6 +451,23 @@ static int smsdvb_set_frontend(struct dvb_frontend *fe, case BANDWIDTH_AUTO: return -EOPNOTSUPP; default: return -EINVAL; } + /* Disable LNA, if any. An error is returned if no LNA is present */ + ret = sms_board_lna_control(client->coredev, 0); + if (ret == 0) { + fe_status_t status; + + /* tune with LNA off at first */ + ret = smsdvb_sendrequest_and_wait(client, &Msg, sizeof(Msg), + &client->tune_done); + + smsdvb_read_status(fe, &status); + + if (status & FE_HAS_LOCK) + return ret; + + /* previous tune didnt lock - enable LNA and tune again */ + sms_board_lna_control(client->coredev, 1); + } return smsdvb_sendrequest_and_wait(client, &Msg, sizeof(Msg), &client->tune_done); @@ -454,6 +493,8 @@ static int smsdvb_init(struct dvb_frontend *fe) struct smsdvb_client_t *client = container_of(fe, struct smsdvb_client_t, frontend); + sms_board_power(client->coredev, 1); + sms_board_dvb3_event(client, DVB3_EVENT_INIT); return 0; } @@ -463,6 +504,9 @@ static int smsdvb_sleep(struct dvb_frontend *fe) struct smsdvb_client_t *client = container_of(fe, struct smsdvb_client_t, frontend); + sms_board_led_feedback(client->coredev, SMS_LED_OFF); + sms_board_power(client->coredev, 0); + sms_board_dvb3_event(client, DVB3_EVENT_SLEEP); return 0; -- cgit v1.2.3 From 1dc7f8632084630ef1289d688a85629fbc39d059 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 13 Jul 2009 01:03:37 -0300 Subject: mt9v011: implement VIDIOC_QUERYCTRL From: Mauro Carvalho Chehab Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/mt9v011.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/mt9v011.c b/linux/drivers/media/video/mt9v011.c index 505529e3e..947a23ac0 100644 --- a/linux/drivers/media/video/mt9v011.c +++ b/linux/drivers/media/video/mt9v011.c @@ -225,6 +225,23 @@ static int mt9v011_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) return -EINVAL; } +static int mt9v011_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc) +{ + int i; + + v4l2_dbg(1, debug, sd, "queryctrl called\n"); + + for (i = 0; i < ARRAY_SIZE(mt9v011_qctrl); i++) + if (qc->id && qc->id == mt9v011_qctrl[i].id) { + memcpy(qc, &(mt9v011_qctrl[i]), + sizeof(*qc)); + return 0; + } + + return -EINVAL; +} + + static int mt9v011_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) { struct mt9v011 *core = to_mt9v011(sd); @@ -348,6 +365,7 @@ static int mt9v011_g_chip_ident(struct v4l2_subdev *sd, } static const struct v4l2_subdev_core_ops mt9v011_core_ops = { + .queryctrl = mt9v011_queryctrl, .g_ctrl = mt9v011_g_ctrl, .s_ctrl = mt9v011_s_ctrl, .reset = mt9v011_reset, -- cgit v1.2.3 From 8c6e58b4adfb075524553ae7b390f8ea7406370d Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 13 Jul 2009 01:28:21 -0300 Subject: em28xx: call sensor detection code for all webcam entries From: Mauro Carvalho Chehab With the previous approach, autodetection were working only for the two generic entries (em275x and em2820 unknown ones). So, if someone would try to force probing an specific device, the code would not properly run the autodetection code. With the new approach, the sensor autodetection will be run not only for the two generic entries, but also do webcam specific ones. Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/em28xx/em28xx-cards.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (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 5f063e4a1..56aa11a46 100644 --- a/linux/drivers/media/video/em28xx/em28xx-cards.c +++ b/linux/drivers/media/video/em28xx/em28xx-cards.c @@ -247,6 +247,7 @@ struct em28xx_board em28xx_boards[] = { [EM2820_BOARD_UNKNOWN] = { .name = "Unknown EM2750/28xx video grabber", .tuner_type = TUNER_ABSENT, + .is_webcam = 1, /* To enable sensor probe */ }, [EM2750_BOARD_DLCW_130] = { /* Beijing Huaqi Information Digital Technology Co., Ltd */ @@ -1790,10 +1791,6 @@ static int em28xx_hint_sensor(struct em28xx *dev) __be16 version_be; u16 version; - if (dev->model != EM2820_BOARD_UNKNOWN && - dev->model != EM2750_BOARD_UNKNOWN) - return 0; - dev->i2c_client.addr = 0xba >> 1; cmd = 0; i2c_master_send(&dev->i2c_client, &cmd, 1); @@ -1848,10 +1845,7 @@ void em28xx_pre_card_setup(struct em28xx *dev) em28xx_info("chip ID is em2750\n"); break; case CHIP_ID_EM2820: - if (dev->board.is_webcam) - em28xx_info("chip is em2710\n"); - else - em28xx_info("chip ID is em2820\n"); + em28xx_info("chip ID is em2710 or em2820\n"); break; case CHIP_ID_EM2840: em28xx_info("chip ID is em2840\n"); @@ -2531,7 +2525,13 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, return errCode; } - em28xx_hint_sensor(dev); + /* + * If the device can be a webcam, seek for a sensor. + * If sensor is not found, then it isn't a webcam. + */ + if (dev->board.is_webcam) + if (em28xx_hint_sensor(dev) < 0) + dev->board.is_webcam = 0; /* Do board specific init and eeprom reading */ em28xx_card_setup(dev); -- cgit v1.2.3 From 50d2769688b47965b7ef2a6b60eba8d80d5dc156 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 13 Jul 2009 20:15:02 -0300 Subject: em28xx: fix webcam scaling From: Mauro Carvalho Chehab While trying to fix an mt9v001 webcam, I noticed that HSCALE/VSCALE do work with em28xx + webcam. The issue is that the scaling setup depends on the number of visible rows/cols of the input image. With mt9v011 (Silvercrest), the resolution is 640x480. So, the scaling is different from a normal TV image (720x480 on NTSC). This were causing a wrong scaling and a previous patch disabled scaling. As each sensor have their different resolution setting, the xres/yres should be adjusted accordingly with the input sensor. Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/em28xx/em28xx-cards.c | 6 +++--- linux/drivers/media/video/em28xx/em28xx-core.c | 5 +---- linux/drivers/media/video/em28xx/em28xx-video.c | 16 +++------------- linux/drivers/media/video/em28xx/em28xx.h | 15 +++++++++++---- 4 files changed, 18 insertions(+), 24 deletions(-) (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 56aa11a46..d5ebfb8be 100644 --- a/linux/drivers/media/video/em28xx/em28xx-cards.c +++ b/linux/drivers/media/video/em28xx/em28xx-cards.c @@ -59,8 +59,6 @@ static unsigned int card[] = {[0 ... (EM28XX_MAXBOARDS - 1)] = UNSET }; module_param_array(card, int, NULL, 0444); MODULE_PARM_DESC(card, "card type"); -#define MT9V011_VERSION 0x8243 - /* Bitmask marking allocated devices from 0 to EM28XX_MAXBOARDS */ static unsigned long em28xx_devused; @@ -1801,10 +1799,12 @@ static int em28xx_hint_sensor(struct em28xx *dev) version = be16_to_cpu(version_be); switch (version) { - case MT9V011_VERSION: + case 0x8243: /* mt9v011 640x480 1.3 Mpix sensor */ dev->model = EM2820_BOARD_SILVERCREST_WEBCAM; sensor_name = "mt9v011"; dev->em28xx_sensor = EM28XX_MT9V011; + dev->sensor_xres = 640; + dev->sensor_yres = 480; break; default: printk("Unknown Micron Sensor 0x%04x\n", be16_to_cpu(version)); diff --git a/linux/drivers/media/video/em28xx/em28xx-core.c b/linux/drivers/media/video/em28xx/em28xx-core.c index 420e343f2..22481e5dd 100644 --- a/linux/drivers/media/video/em28xx/em28xx-core.c +++ b/linux/drivers/media/video/em28xx/em28xx-core.c @@ -707,10 +707,7 @@ static int em28xx_scaler_set(struct em28xx *dev, u16 h, u16 v) u8 mode; /* the em2800 scaler only supports scaling down to 50% */ - if (dev->board.is_webcam) { - /* FIXME: Don't use the scaler yet */ - mode = 0; - } else if (dev->board.is_em2800) { + if (dev->board.is_em2800) { mode = (v ? 0x20 : 0x00) | (h ? 0x10 : 0x00); } else { u8 buf[2]; diff --git a/linux/drivers/media/video/em28xx/em28xx-video.c b/linux/drivers/media/video/em28xx/em28xx-video.c index e447c9f0a..cef676bf8 100644 --- a/linux/drivers/media/video/em28xx/em28xx-video.c +++ b/linux/drivers/media/video/em28xx/em28xx-video.c @@ -679,8 +679,8 @@ static void get_scale(struct em28xx *dev, unsigned int width, unsigned int height, unsigned int *hscale, unsigned int *vscale) { - unsigned int maxw = norm_maxw(dev); - unsigned int maxh = norm_maxh(dev); + unsigned int maxw = norm_maxw(dev); + unsigned int maxh = norm_maxh(dev); *hscale = (((unsigned long)maxw) << 12) / width - 4096L; if (*hscale >= 0x4000) @@ -748,11 +748,7 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, return -EINVAL; } - if (dev->board.is_webcam) { - /* FIXME: This is the only supported fmt */ - width = 640; - height = 480; - } else if (dev->board.is_em2800) { + if (dev->board.is_em2800) { /* the em2800 can only scale down to 50% */ height = height > (3 * maxh / 4) ? maxh : maxh / 2; width = width > (3 * maxw / 4) ? maxw : maxw / 2; @@ -789,12 +785,6 @@ static int em28xx_set_video_format(struct em28xx *dev, unsigned int fourcc, { struct em28xx_fmt *fmt; - /* FIXME: This is the only supported fmt */ - if (dev->board.is_webcam) { - width = 640; - height = 480; - } - fmt = format_by_fourcc(fourcc); if (!fmt) return -EINVAL; diff --git a/linux/drivers/media/video/em28xx/em28xx.h b/linux/drivers/media/video/em28xx/em28xx.h index 559903b2a..40b228438 100644 --- a/linux/drivers/media/video/em28xx/em28xx.h +++ b/linux/drivers/media/video/em28xx/em28xx.h @@ -488,6 +488,7 @@ struct em28xx { struct em28xx_board board; enum em28xx_sensor em28xx_sensor; + int sensor_xres, sensor_yres; unsigned int stream_on:1; /* Locks streams */ unsigned int has_audio_class:1; @@ -769,17 +770,23 @@ static inline int em28xx_gamma_set(struct em28xx *dev, s32 val) /*FIXME: maxw should be dependent of alt mode */ static inline unsigned int norm_maxw(struct em28xx *dev) { + if (dev->board.is_webcam) + return dev->sensor_xres; + if (dev->board.max_range_640_480) return 640; - else - return 720; + + return 720; } static inline unsigned int norm_maxh(struct em28xx *dev) { + if (dev->board.is_webcam) + return dev->sensor_yres; + if (dev->board.max_range_640_480) return 480; - else - return (dev->norm & V4L2_STD_625_50) ? 576 : 480; + + return (dev->norm & V4L2_STD_625_50) ? 576 : 480; } #endif -- cgit v1.2.3 From 3c16945bd290ac09d7aa8a70c69d8f359eb53a09 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 14 Jul 2009 02:38:18 -0300 Subject: mt9v011: add a function to calculate frames per second rate From: Mauro Carvalho Chehab It is possible to adjust the fps rate by changing some register values. This is function of the connected Xtal at the camera sensor, being a 27 MHz cristal needed, in order to support 640x480 at 30 fps. For now, it will only calculate the values for fps. Later patches may introduce V4L2 ioctls, to allow frequency rate adjustments. Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/mt9v011.c | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/mt9v011.c b/linux/drivers/media/video/mt9v011.c index 947a23ac0..43420d311 100644 --- a/linux/drivers/media/video/mt9v011.c +++ b/linux/drivers/media/video/mt9v011.c @@ -9,6 +9,7 @@ #include "compat.h" #include #include +#include #include #include "mt9v011.h" #include @@ -67,6 +68,7 @@ static struct v4l2_queryctrl mt9v011_qctrl[] = { struct mt9v011 { struct v4l2_subdev sd; unsigned width, height; + unsigned xtal; u16 global_gain, red_bal, blue_bal; }; @@ -141,7 +143,7 @@ static const struct i2c_reg_value mt9v011_init_default[] = { { R1E_MT9V011_DIGITAL_ZOOM, 0x0000 }, { R20_MT9V011_READ_MODE, 0x1000 }, - { R07_MT9V011_OUT_CTRL, 0x000a }, /* chip enable */ + { R07_MT9V011_OUT_CTRL, 0x0002 }, /* chip enable */ }; static void set_balance(struct v4l2_subdev *sd) @@ -164,6 +166,31 @@ static void set_balance(struct v4l2_subdev *sd) mt9v011_write(sd, R2D_MT9V011_RED_GAIN, red_gain); } +static void calc_fps(struct v4l2_subdev *sd) +{ + struct mt9v011 *core = to_mt9v011(sd); + unsigned height, width, hblank, vblank, speed; + unsigned row_time, t_time; + u64 frames_per_ms; + unsigned tmp; + + height = mt9v011_read(sd, R03_MT9V011_HEIGHT); + width = mt9v011_read(sd, R04_MT9V011_WIDTH); + hblank = mt9v011_read(sd, R05_MT9V011_HBLANK); + vblank = mt9v011_read(sd, R06_MT9V011_VBLANK); + speed = mt9v011_read(sd, R0A_MT9V011_CLK_SPEED); + + row_time = (width + 113 + hblank) * (speed + 2); + t_time = row_time * (height + vblank + 1); + + frames_per_ms = core->xtal * 1000l; + do_div(frames_per_ms, t_time); + tmp = frames_per_ms; + + v4l2_dbg(1, debug, sd, "Programmed to %u.%03u fps (%d pixel clcks)\n", + tmp / 1000, tmp % 1000, t_time); +} + static void set_res(struct v4l2_subdev *sd) { struct mt9v011 *core = to_mt9v011(sd); @@ -189,6 +216,8 @@ static void set_res(struct v4l2_subdev *sd) mt9v011_write(sd, R01_MT9V011_ROWSTART, vstart); mt9v011_write(sd, R03_MT9V011_HEIGHT, core->height); mt9v011_write(sd, R06_MT9V011_VBLANK, 508 - core->height); + + calc_fps(sd); }; static int mt9v011_reset(struct v4l2_subdev *sd, u32 val) @@ -423,6 +452,7 @@ static int mt9v011_probe(struct i2c_client *c, core->global_gain = 0x0024; core->width = 640; core->height = 480; + core->xtal = 27000000; /* Hz */ v4l_info(c, "chip found @ 0x%02x (%s)\n", c->addr << 1, c->adapter->name); -- cgit v1.2.3 From bd8a28419f128638347a77d46de11461f0c17fd6 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 14 Jul 2009 02:39:19 -0300 Subject: mt9v011: Fix vstart From: Mauro Carvalho Chehab vstart calculus were wrong. Fix it. Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/mt9v011.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/mt9v011.c b/linux/drivers/media/video/mt9v011.c index 43420d311..46b5a3cf5 100644 --- a/linux/drivers/media/video/mt9v011.c +++ b/linux/drivers/media/video/mt9v011.c @@ -212,7 +212,7 @@ static void set_res(struct v4l2_subdev *sd) mt9v011_write(sd, R04_MT9V011_WIDTH, core->width); mt9v011_write(sd, R05_MT9V011_HBLANK, 771 - core->width); - vstart = 8 + (640 - core->height) / 2; + vstart = 8 + (480 - core->height) / 2; mt9v011_write(sd, R01_MT9V011_ROWSTART, vstart); mt9v011_write(sd, R03_MT9V011_HEIGHT, core->height); mt9v011_write(sd, R06_MT9V011_VBLANK, 508 - core->height); -- cgit v1.2.3 From a8d41efd6cd091346a1276f0c7d818874b10bc36 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 14 Jul 2009 03:14:21 -0300 Subject: mt9v011: implement core->s_config to allow adjusting xtal frequency From: Mauro Carvalho Chehab Since frames per second is a function of cristal frequency, and this is device-specific, add a function that allows adjusting it, via subdev->core->s_config callback. Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/mt9v011.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/mt9v011.c b/linux/drivers/media/video/mt9v011.c index 46b5a3cf5..bf68ea63f 100644 --- a/linux/drivers/media/video/mt9v011.c +++ b/linux/drivers/media/video/mt9v011.c @@ -350,6 +350,22 @@ static int mt9v011_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) return 0; } +static int mt9v011_s_config(struct v4l2_subdev *sd, int dumb, void *data) +{ + struct mt9v011 *core = to_mt9v011(sd); + unsigned *xtal = data; + + v4l2_dbg(1, debug, sd, "s_config called\n"); + + if (xtal) { + core->xtal = *xtal; + v4l2_dbg(1, debug, sd, "xtal set to %d.%03d MHz\n", + *xtal / 1000000, (*xtal / 1000) % 1000); + } + + return 0; +} + #ifdef CONFIG_VIDEO_ADV_DEBUG static int mt9v011_g_register(struct v4l2_subdev *sd, @@ -398,6 +414,7 @@ static const struct v4l2_subdev_core_ops mt9v011_core_ops = { .g_ctrl = mt9v011_g_ctrl, .s_ctrl = mt9v011_s_ctrl, .reset = mt9v011_reset, + .s_config = mt9v011_s_config, .g_chip_ident = mt9v011_g_chip_ident, #ifdef CONFIG_VIDEO_ADV_DEBUG .g_register = mt9v011_g_register, -- cgit v1.2.3 From 0edfef5c337eb0bd9d0146246fae01a308faea4f Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 14 Jul 2009 03:18:39 -0300 Subject: em28xx: allow specifying sensor xtal frequency From: Mauro Carvalho Chehab In order to properly estimate fps, mt9v011 sensor driver needs to know what is the used frequency on the sensor cristal. Adds the proper fields and initialization code for specifying the cristal frequency. Also, based on experimentation, it was noticed that the Silvercrest is outputing data at 7 fps. This means that it should be using a 6.3 MHz cristal. This information needs to be double checked later, by opening the device. Anyway, by using this value for xtal, at least now we have the correct fps report. Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/em28xx/em28xx-cards.c | 11 ++++++++--- linux/drivers/media/video/em28xx/em28xx.h | 2 ++ 2 files changed, 10 insertions(+), 3 deletions(-) (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 d5ebfb8be..75032271d 100644 --- a/linux/drivers/media/video/em28xx/em28xx-cards.c +++ b/linux/drivers/media/video/em28xx/em28xx-cards.c @@ -1805,6 +1805,7 @@ static int em28xx_hint_sensor(struct em28xx *dev) dev->em28xx_sensor = EM28XX_MT9V011; dev->sensor_xres = 640; dev->sensor_yres = 480; + dev->sensor_xtal = 6300000; break; default: printk("Unknown Micron Sensor 0x%04x\n", be16_to_cpu(version)); @@ -2366,9 +2367,13 @@ void em28xx_card_setup(struct em28xx *dev) v4l2_i2c_new_probed_subdev(&dev->v4l2_dev, &dev->i2c_adap, "tvp5150", "tvp5150", tvp5150_addrs); - if (dev->em28xx_sensor == EM28XX_MT9V011) - v4l2_i2c_new_probed_subdev(&dev->v4l2_dev, &dev->i2c_adap, - "mt9v011", "mt9v011", mt9v011_addrs); + if (dev->em28xx_sensor == EM28XX_MT9V011) { + struct v4l2_subdev *sd; + + sd = v4l2_i2c_new_probed_subdev(&dev->v4l2_dev, + &dev->i2c_adap, "mt9v011", "mt9v011", mt9v011_addrs); + v4l2_subdev_call(sd, core, s_config, 0, &dev->sensor_xtal); + } if (dev->board.adecoder == EM28XX_TVAUDIO) v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap, diff --git a/linux/drivers/media/video/em28xx/em28xx.h b/linux/drivers/media/video/em28xx/em28xx.h index 40b228438..26011bf37 100644 --- a/linux/drivers/media/video/em28xx/em28xx.h +++ b/linux/drivers/media/video/em28xx/em28xx.h @@ -487,8 +487,10 @@ struct em28xx { struct v4l2_device v4l2_dev; struct em28xx_board board; + /* Webcam specific fields */ enum em28xx_sensor em28xx_sensor; int sensor_xres, sensor_yres; + int sensor_xtal; unsigned int stream_on:1; /* Locks streams */ unsigned int has_audio_class:1; -- cgit v1.2.3 From f4a61c7eab17e012ce6341745b57b329d9feda98 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 14 Jul 2009 12:33:25 -0300 Subject: em28xx: adjust vinmode/vinctl based on the stream input format From: Mauro Carvalho Chehab Depending on the video input format, vinmode/vinctl needs adjustments. For TV, this is not relevant, since the supported decoders output data at the same format. However, webcam sensors may have different formats, so, this needs to be adjusted based on the device. Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/em28xx/em28xx-cards.c | 11 +++++++++++ linux/drivers/media/video/em28xx/em28xx-core.c | 17 +++-------------- linux/drivers/media/video/em28xx/em28xx.h | 3 +++ 3 files changed, 17 insertions(+), 14 deletions(-) (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 75032271d..b40a01e91 100644 --- a/linux/drivers/media/video/em28xx/em28xx-cards.c +++ b/linux/drivers/media/video/em28xx/em28xx-cards.c @@ -1806,6 +1806,11 @@ static int em28xx_hint_sensor(struct em28xx *dev) dev->sensor_xres = 640; dev->sensor_yres = 480; dev->sensor_xtal = 6300000; + + /* probably means GRGB 16 bit bayer */ + dev->vinmode = 0x0d; + dev->vinctl = 0x00; + break; default: printk("Unknown Micron Sensor 0x%04x\n", be16_to_cpu(version)); @@ -2530,6 +2535,12 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, return errCode; } + /* + * Default format, used for tvp5150 or saa711x output formats + */ + dev->vinmode = 0x10; + dev->vinctl = 0x11; + /* * If the device can be a webcam, seek for a sensor. * If sensor is not found, then it isn't a webcam. diff --git a/linux/drivers/media/video/em28xx/em28xx-core.c b/linux/drivers/media/video/em28xx/em28xx-core.c index 22481e5dd..f24af40df 100644 --- a/linux/drivers/media/video/em28xx/em28xx-core.c +++ b/linux/drivers/media/video/em28xx/em28xx-core.c @@ -648,28 +648,17 @@ int em28xx_capture_start(struct em28xx *dev, int start) int em28xx_set_outfmt(struct em28xx *dev) { int ret; - int vinmode, vinctl, outfmt; - - outfmt = dev->format->reg; - - if (dev->board.is_webcam) { - vinmode = 0x0d; - vinctl = 0x00; - } else { - vinmode = 0x10; - vinctl = 0x11; - } ret = em28xx_write_reg_bits(dev, EM28XX_R27_OUTFMT, - outfmt | 0x20, 0xff); + dev->format->reg | 0x20, 0xff); if (ret < 0) return ret; - ret = em28xx_write_reg(dev, EM28XX_R10_VINMODE, vinmode); + ret = em28xx_write_reg(dev, EM28XX_R10_VINMODE, dev->vinmode); if (ret < 0) return ret; - return em28xx_write_reg(dev, EM28XX_R11_VINCTRL, vinctl); + return em28xx_write_reg(dev, EM28XX_R11_VINCTRL, dev->vinctl); } static int em28xx_accumulator_set(struct em28xx *dev, u8 xmin, u8 xmax, diff --git a/linux/drivers/media/video/em28xx/em28xx.h b/linux/drivers/media/video/em28xx/em28xx.h index 26011bf37..783799324 100644 --- a/linux/drivers/media/video/em28xx/em28xx.h +++ b/linux/drivers/media/video/em28xx/em28xx.h @@ -492,6 +492,9 @@ struct em28xx { int sensor_xres, sensor_yres; int sensor_xtal; + /* Vinmode/Vinctl used at the driver */ + int vinmode, vinctl; + unsigned int stream_on:1; /* Locks streams */ unsigned int has_audio_class:1; unsigned int has_alsa_audio:1; -- cgit v1.2.3 From 9a656496a57cf7f0b434af1b04d02c20e3976cbc Mon Sep 17 00:00:00 2001 From: Andreas Oberritter Date: Wed, 15 Jul 2009 01:28:50 +0200 Subject: Add two new ioctls: DMX_ADD_PID and DMX_REMOVE_PID From: Andreas Oberritter DMX_ADD_PID allows to add multiple PIDs to a transport stream filter previously set up with DMX_SET_PES_FILTER and output=DMX_OUT_TSDEMUX_TAP. DMX_REMOVE_PID is used to drop a PID from a filter. These ioctls are to be used by readers of /dev/dvb/adapterX/demuxY. They may be called at any time, i.e. before or after the first filter on the shared file descriptor was started. They make it possible to record multiple services without the need to de- or re-multiplex TS packets. To accomplish this, dmxdev_filter->feed.ts has been converted to a list of struct dmxdev_feeds, each containing a PID value and a pointer to a struct dmx_ts_feed. Priority: normal Signed-off-by: Andreas Oberritter --- linux/drivers/media/dvb/dvb-core/dmxdev.c | 231 ++++++++++++++++++++++-------- linux/drivers/media/dvb/dvb-core/dmxdev.h | 9 +- 2 files changed, 182 insertions(+), 58 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 6d6121eb5..3750ff48c 100644 --- a/linux/drivers/media/dvb/dvb-core/dmxdev.c +++ b/linux/drivers/media/dvb/dvb-core/dmxdev.c @@ -430,6 +430,8 @@ static int dvb_dmxdev_ts_callback(const u8 *buffer1, size_t buffer1_len, /* stop feed but only mark the specified filter as stopped (state set) */ static int dvb_dmxdev_feed_stop(struct dmxdev_filter *dmxdevfilter) { + struct dmxdev_feed *feed; + dvb_dmxdev_filter_state_set(dmxdevfilter, DMXDEV_STATE_SET); switch (dmxdevfilter->type) { @@ -438,7 +440,8 @@ static int dvb_dmxdev_feed_stop(struct dmxdev_filter *dmxdevfilter) dmxdevfilter->feed.sec->stop_filtering(dmxdevfilter->feed.sec); break; case DMXDEV_TYPE_PES: - dmxdevfilter->feed.ts->stop_filtering(dmxdevfilter->feed.ts); + list_for_each_entry(feed, &dmxdevfilter->feed.ts, next) + feed->ts->stop_filtering(feed->ts); break; default: return -EINVAL; @@ -449,13 +452,23 @@ static int dvb_dmxdev_feed_stop(struct dmxdev_filter *dmxdevfilter) /* start feed associated with the specified filter */ static int dvb_dmxdev_feed_start(struct dmxdev_filter *filter) { + struct dmxdev_feed *feed; + int ret; + dvb_dmxdev_filter_state_set(filter, DMXDEV_STATE_GO); switch (filter->type) { case DMXDEV_TYPE_SEC: return filter->feed.sec->start_filtering(filter->feed.sec); case DMXDEV_TYPE_PES: - return filter->feed.ts->start_filtering(filter->feed.ts); + list_for_each_entry(feed, &filter->feed.ts, next) { + ret = feed->ts->start_filtering(feed->ts); + if (ret < 0) { + dvb_dmxdev_feed_stop(filter); + return ret; + } + } + break; default: return -EINVAL; } @@ -487,6 +500,9 @@ static int dvb_dmxdev_feed_restart(struct dmxdev_filter *filter) static int dvb_dmxdev_filter_stop(struct dmxdev_filter *dmxdevfilter) { + struct dmxdev_feed *feed; + struct dmx_demux *demux; + if (dmxdevfilter->state < DMXDEV_STATE_GO) return 0; @@ -503,13 +519,12 @@ static int dvb_dmxdev_filter_stop(struct dmxdev_filter *dmxdevfilter) dmxdevfilter->feed.sec = NULL; break; case DMXDEV_TYPE_PES: - if (!dmxdevfilter->feed.ts) - break; dvb_dmxdev_feed_stop(dmxdevfilter); - dmxdevfilter->dev->demux-> - release_ts_feed(dmxdevfilter->dev->demux, - dmxdevfilter->feed.ts); - dmxdevfilter->feed.ts = NULL; + demux = dmxdevfilter->dev->demux; + list_for_each_entry(feed, &dmxdevfilter->feed.ts, next) { + demux->release_ts_feed(demux, feed->ts); + feed->ts = NULL; + } break; default: if (dmxdevfilter->state == DMXDEV_STATE_ALLOCATED) @@ -521,19 +536,88 @@ static int dvb_dmxdev_filter_stop(struct dmxdev_filter *dmxdevfilter) return 0; } +static void dvb_dmxdev_delete_pids(struct dmxdev_filter *dmxdevfilter) +{ + struct dmxdev_feed *feed, *tmp; + + /* delete all PIDs */ + list_for_each_entry_safe(feed, tmp, &dmxdevfilter->feed.ts, next) { + list_del(&feed->next); + kfree(feed); + } + + BUG_ON(!list_empty(&dmxdevfilter->feed.ts)); +} + static inline int dvb_dmxdev_filter_reset(struct dmxdev_filter *dmxdevfilter) { if (dmxdevfilter->state < DMXDEV_STATE_SET) return 0; + if (dmxdevfilter->type == DMXDEV_TYPE_PES) + dvb_dmxdev_delete_pids(dmxdevfilter); + dmxdevfilter->type = DMXDEV_TYPE_NONE; dvb_dmxdev_filter_state_set(dmxdevfilter, DMXDEV_STATE_ALLOCATED); return 0; } +static int dvb_dmxdev_start_feed(struct dmxdev *dmxdev, + struct dmxdev_filter *filter, + struct dmxdev_feed *feed) +{ + struct timespec timeout = { 0 }; + struct dmx_pes_filter_params *para = &filter->params.pes; + dmx_output_t otype; + int ret; + int ts_type; + enum dmx_ts_pes ts_pes; + struct dmx_ts_feed *tsfeed; + + feed->ts = NULL; + otype = para->output; + + ts_pes = (enum dmx_ts_pes)para->pes_type; + + if (ts_pes < DMX_PES_OTHER) + ts_type = TS_DECODER; + else + ts_type = 0; + + if (otype == DMX_OUT_TS_TAP) + ts_type |= TS_PACKET; + else if (otype == DMX_OUT_TSDEMUX_TAP) + ts_type |= TS_PACKET | TS_DEMUX; + else if (otype == DMX_OUT_TAP) + ts_type |= TS_PACKET | TS_DEMUX | TS_PAYLOAD_ONLY; + + ret = dmxdev->demux->allocate_ts_feed(dmxdev->demux, &feed->ts, + dvb_dmxdev_ts_callback); + if (ret < 0) + return ret; + + tsfeed = feed->ts; + tsfeed->priv = filter; + + ret = tsfeed->set(tsfeed, feed->pid, ts_type, ts_pes, 32768, timeout); + if (ret < 0) { + dmxdev->demux->release_ts_feed(dmxdev->demux, tsfeed); + return ret; + } + + ret = tsfeed->start_filtering(tsfeed); + if (ret < 0) { + dmxdev->demux->release_ts_feed(dmxdev->demux, tsfeed); + return ret; + } + + return 0; +} + static int dvb_dmxdev_filter_start(struct dmxdev_filter *filter) { struct dmxdev *dmxdev = filter->dev; + struct dmxdev_feed *feed; void *mem; int ret, i; @@ -631,56 +715,14 @@ static int dvb_dmxdev_filter_start(struct dmxdev_filter *filter) break; } case DMXDEV_TYPE_PES: - { - struct timespec timeout = { 0 }; - struct dmx_pes_filter_params *para = &filter->params.pes; - dmx_output_t otype; - int ts_type; - enum dmx_ts_pes ts_pes; - struct dmx_ts_feed **tsfeed = &filter->feed.ts; - - filter->feed.ts = NULL; - otype = para->output; - - ts_pes = (enum dmx_ts_pes)para->pes_type; - - if (ts_pes < DMX_PES_OTHER) - ts_type = TS_DECODER; - else - ts_type = 0; - - if (otype == DMX_OUT_TS_TAP) - ts_type |= TS_PACKET; - else if (otype == DMX_OUT_TSDEMUX_TAP) - ts_type |= TS_PACKET | TS_DEMUX; - else if (otype == DMX_OUT_TAP) - ts_type |= TS_PACKET | TS_DEMUX | TS_PAYLOAD_ONLY; - - ret = dmxdev->demux->allocate_ts_feed(dmxdev->demux, - tsfeed, - dvb_dmxdev_ts_callback); - if (ret < 0) - return ret; - - (*tsfeed)->priv = filter; - - ret = (*tsfeed)->set(*tsfeed, para->pid, ts_type, ts_pes, - 32768, timeout); - if (ret < 0) { - dmxdev->demux->release_ts_feed(dmxdev->demux, - *tsfeed); - return ret; - } - - ret = filter->feed.ts->start_filtering(filter->feed.ts); - if (ret < 0) { - dmxdev->demux->release_ts_feed(dmxdev->demux, - *tsfeed); - return ret; + list_for_each_entry(feed, &filter->feed.ts, next) { + ret = dvb_dmxdev_start_feed(dmxdev, filter, feed); + if (ret < 0) { + dvb_dmxdev_filter_stop(filter); + return ret; + } } - break; - } default: return -EINVAL; } @@ -718,7 +760,7 @@ static int dvb_demux_open(struct inode *inode, struct file *file) dvb_ringbuffer_init(&dmxdevfilter->buffer, NULL, 8192); dmxdevfilter->type = DMXDEV_TYPE_NONE; dvb_dmxdev_filter_state_set(dmxdevfilter, DMXDEV_STATE_ALLOCATED); - dmxdevfilter->feed.ts = NULL; + INIT_LIST_HEAD(&dmxdevfilter->feed.ts); init_timer(&dmxdevfilter->timer); dvbdev->users++; @@ -760,6 +802,55 @@ static inline void invert_mode(dmx_filter_t *filter) filter->mode[i] ^= 0xff; } +static int dvb_dmxdev_add_pid(struct dmxdev *dmxdev, + struct dmxdev_filter *filter, u16 pid) +{ + struct dmxdev_feed *feed; + + if ((filter->type != DMXDEV_TYPE_PES) || + (filter->state < DMXDEV_STATE_SET)) + return -EINVAL; + + /* only TS packet filters may have multiple PIDs */ + if ((filter->params.pes.output != DMX_OUT_TSDEMUX_TAP) && + (!list_empty(&filter->feed.ts))) + return -EINVAL; + + feed = kzalloc(sizeof(struct dmxdev_feed), GFP_KERNEL); + if (feed == NULL) + return -ENOMEM; + + feed->pid = pid; + list_add(&feed->next, &filter->feed.ts); + + if (filter->state >= DMXDEV_STATE_GO) + return dvb_dmxdev_start_feed(dmxdev, filter, feed); + + return 0; +} + +static int dvb_dmxdev_remove_pid(struct dmxdev *dmxdev, + struct dmxdev_filter *filter, u16 pid) +{ + struct dmxdev_feed *feed, *tmp; + + if ((filter->type != DMXDEV_TYPE_PES) || + (filter->state < DMXDEV_STATE_SET)) + return -EINVAL; + + list_for_each_entry_safe(feed, tmp, &filter->feed.ts, next) { + if ((feed->pid == pid) && (feed->ts != NULL)) { + feed->ts->stop_filtering(feed->ts); + filter->dev->demux->release_ts_feed(filter->dev->demux, + feed->ts); + list_del(&feed->next); + kfree(feed); + } + } + + return 0; +} + static int dvb_dmxdev_filter_set(struct dmxdev *dmxdev, struct dmxdev_filter *dmxdevfilter, struct dmx_sct_filter_params *params) @@ -784,7 +875,10 @@ static int dvb_dmxdev_pes_filter_set(struct dmxdev *dmxdev, struct dmxdev_filter *dmxdevfilter, struct dmx_pes_filter_params *params) { + int ret; + dvb_dmxdev_filter_stop(dmxdevfilter); + dvb_dmxdev_filter_reset(dmxdevfilter); if (params->pes_type > DMX_PES_OTHER || params->pes_type < 0) return -EINVAL; @@ -795,6 +889,11 @@ static int dvb_dmxdev_pes_filter_set(struct dmxdev *dmxdev, dvb_dmxdev_filter_state_set(dmxdevfilter, DMXDEV_STATE_SET); + ret = dvb_dmxdev_add_pid(dmxdev, dmxdevfilter, + dmxdevfilter->params.pes.pid); + if (ret < 0) + return ret; + if (params->flags & DMX_IMMEDIATE_START) return dvb_dmxdev_filter_start(dmxdevfilter); @@ -958,6 +1057,24 @@ static int dvb_demux_do_ioctl(struct inode *inode, struct file *file, &((struct dmx_stc *)parg)->base); break; + case DMX_ADD_PID: + if (mutex_lock_interruptible(&dmxdevfilter->mutex)) { + ret = -ERESTARTSYS; + break; + } + ret = dvb_dmxdev_add_pid(dmxdev, dmxdevfilter, *(u16 *)parg); + mutex_unlock(&dmxdevfilter->mutex); + break; + + case DMX_REMOVE_PID: + if (mutex_lock_interruptible(&dmxdevfilter->mutex)) { + ret = -ERESTARTSYS; + break; + } + ret = dvb_dmxdev_remove_pid(dmxdev, dmxdevfilter, *(u16 *)parg); + mutex_unlock(&dmxdevfilter->mutex); + break; + default: ret = -EINVAL; break; diff --git a/linux/drivers/media/dvb/dvb-core/dmxdev.h b/linux/drivers/media/dvb/dvb-core/dmxdev.h index 7e8137d0b..be63783ad 100644 --- a/linux/drivers/media/dvb/dvb-core/dmxdev.h +++ b/linux/drivers/media/dvb/dvb-core/dmxdev.h @@ -54,13 +54,20 @@ enum dmxdev_state { DMXDEV_STATE_TIMEDOUT }; +struct dmxdev_feed { + u16 pid; + struct dmx_ts_feed *ts; + struct list_head next; +}; + struct dmxdev_filter { union { struct dmx_section_filter *sec; } filter; union { - struct dmx_ts_feed *ts; + /* list of TS and PES feeds (struct dmxdev_feed) */ + struct list_head ts; struct dmx_section_feed *sec; } feed; -- cgit v1.2.3 From 02d22c9b0bfab80d3180aac81f95ca44084fc116 Mon Sep 17 00:00:00 2001 From: Andreas Oberritter Date: Wed, 15 Jul 2009 01:48:37 +0200 Subject: Remove a useless check from dvb_dmx_swfilter_packet() From: Andreas Oberritter Values for 'pid' range from 0 to 0x1fff. Therefore 'feed->pid' can never be equal to both 'pid' and 0x2000. This makes the continue statement have no effect. Priority: normal Signed-off-by: Andreas Oberritter --- linux/drivers/media/dvb/dvb-core/dvb_demux.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/dvb-core/dvb_demux.c b/linux/drivers/media/dvb/dvb-core/dvb_demux.c index cfe2768d2..eef6d3616 100644 --- a/linux/drivers/media/dvb/dvb-core/dvb_demux.c +++ b/linux/drivers/media/dvb/dvb-core/dvb_demux.c @@ -425,13 +425,9 @@ no_dvb_demux_tscheck: if ((DVR_FEED(feed)) && (dvr_done++)) continue; - if (feed->pid == pid) { + if (feed->pid == pid) dvb_dmx_swfilter_packet_type(feed, buf); - if (DVR_FEED(feed)) - continue; - } - - if (feed->pid == 0x2000) + else if (feed->pid == 0x2000) feed->cb.ts(buf, 188, NULL, 0, &feed->feed.ts, DMX_OK); } } -- cgit v1.2.3 From 780de7a15fcc2833d415c0ddf001647ac3b24df8 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 14 Jul 2009 21:08:22 -0300 Subject: em28xx: add support for mt9m001 webcams From: Mauro Carvalho Chehab Thanks to Wally for bringing the issue and helping with the tests. Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/em28xx/em28xx-cards.c | 51 +++++++++++++++++++++++++ linux/drivers/media/video/em28xx/em28xx.h | 1 + 2 files changed, 52 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 b40a01e91..6d80e9a38 100644 --- a/linux/drivers/media/video/em28xx/em28xx-cards.c +++ b/linux/drivers/media/video/em28xx/em28xx-cards.c @@ -224,6 +224,7 @@ struct em28xx_board em28xx_boards[] = { .type = EM28XX_VMUX_COMPOSITE1, .vmux = 0, .amux = EM28XX_AMUX_VIDEO, + .gpio = silvercrest_reg_seq, } }, }, [EM2800_BOARD_UNKNOWN] = { @@ -1777,6 +1778,32 @@ static inline void em28xx_set_model(struct em28xx *dev) EM28XX_I2C_FREQ_100_KHZ; } +/* FIXME: Should be replaced by a proper mt9m001 driver */ +static int em28xx_initialize_mt9m001(struct em28xx *dev) +{ + int i; + unsigned char regs[][3] = { + { 0x0d, 0x00, 0x01, }, + { 0x0d, 0x00, 0x00, }, + { 0x04, 0x05, 0x00, }, /* hres = 1280 */ + { 0x03, 0x04, 0x00, }, /* vres = 1024 */ + { 0x20, 0x11, 0x00, }, + { 0x06, 0x00, 0x10, }, + { 0x2b, 0x00, 0x24, }, + { 0x2e, 0x00, 0x24, }, + { 0x35, 0x00, 0x24, }, + { 0x2d, 0x00, 0x20, }, + { 0x2c, 0x00, 0x20, }, + { 0x09, 0x0a, 0xd4, }, + { 0x35, 0x00, 0x57, }, + }; + + for (i = 0; i < ARRAY_SIZE(regs); i++) + i2c_master_send(&dev->i2c_client, ®s[i][0], 3); + + return 0; +} + /* HINT method: webcam I2C chips * * This method work for webcams with Micron sensors @@ -1811,6 +1838,23 @@ static int em28xx_hint_sensor(struct em28xx *dev) dev->vinmode = 0x0d; dev->vinctl = 0x00; + break; +#if 0 + case 0x8411: + case 0x8421: +#endif + case 0x8431: + dev->model = EM2750_BOARD_UNKNOWN; + sensor_name = "mt9m001"; + dev->em28xx_sensor = EM28XX_MT9M001; + em28xx_initialize_mt9m001(dev); + dev->sensor_xres = 1280; + dev->sensor_yres = 1024; + + /* probably means BGGR 16 bit bayer */ + dev->vinmode = 0x0c; + dev->vinctl = 0x00; + break; default: printk("Unknown Micron Sensor 0x%04x\n", be16_to_cpu(version)); @@ -2380,6 +2424,13 @@ void em28xx_card_setup(struct em28xx *dev) v4l2_subdev_call(sd, core, s_config, 0, &dev->sensor_xtal); } +#if 0 + /* FIXME: use mt9m001 after their conversion to v4l dev/subdev */ + if (dev->em28xx_sensor == EM28XX_MT9M001) + v4l2_i2c_new_probed_subdev(&dev->v4l2_dev, &dev->i2c_adap, + "mt9m001", "mt9m001", mt9v011_addrs); +#endif + if (dev->board.adecoder == EM28XX_TVAUDIO) v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap, "tvaudio", "tvaudio", dev->board.tvaudio_addr); diff --git a/linux/drivers/media/video/em28xx/em28xx.h b/linux/drivers/media/video/em28xx/em28xx.h index 783799324..df7fe9af7 100644 --- a/linux/drivers/media/video/em28xx/em28xx.h +++ b/linux/drivers/media/video/em28xx/em28xx.h @@ -367,6 +367,7 @@ enum em28xx_decoder { enum em28xx_sensor { EM28XX_NOSENSOR = 0, EM28XX_MT9V011, + EM28XX_MT9M001, }; enum em28xx_adecoder { -- cgit v1.2.3 From d4a045723fae91cc87a8dd7c71f47bf6fc6ae09f Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Tue, 14 Jul 2009 23:35:47 -0400 Subject: em28xx: Make sure the tuner is initialized if generic empia USB id was used From: Devin Heitmueller In cases where the device has a generic Empia USB ID, the call in the precard setup phase did not set the tuner GPIO. As a result, the tuner may not be taken out of reset before attempting initialization in the analog driver. This problem was not seen before with the EVGA inDtube, since that particular board has the analog GPIO setup to include taking the tuner out of reset. Thanks to Andreas Lunderhage for testing patches and providing a remote debug environment for the Pinnacle 320e. Priority: normal Cc: Andreas Lunderhage Signed-off-by: Devin Heitmueller --- linux/drivers/media/video/em28xx/em28xx-cards.c | 1 + 1 file changed, 1 insertion(+) (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 3599d6223..3be05dcc1 100644 --- a/linux/drivers/media/video/em28xx/em28xx-cards.c +++ b/linux/drivers/media/video/em28xx/em28xx-cards.c @@ -2342,6 +2342,7 @@ void em28xx_card_setup(struct em28xx *dev) em28xx_set_mode() in em28xx_pre_card_setup() was a no-op, so make the call now so the analog GPIOs are set properly before probing the i2c bus. */ + em28xx_gpio_set(dev, dev->board.tuner_gpio); em28xx_set_mode(dev, EM28XX_ANALOG_MODE); break; case EM2820_BOARD_SILVERCREST_WEBCAM: -- cgit v1.2.3 From 5d42bf58c3798d11494482f0c4ce11e4264e5fab Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Tue, 14 Jul 2009 23:37:22 -0400 Subject: em28xx: set demod profile for Pinnacle Hybrid Pro 320e From: Devin Heitmueller The Pinnacle Hybrid Pro 320e was missing a demod config for the xc3028, which is required for digital tuning to work properly. Add the missing profile. Thanks to Andreas Lunderhage for testing patches and providing a remote debug environment. Priority: normal Cc: Andreas Lunderhage Signed-off-by: Devin Heitmueller --- linux/drivers/media/video/em28xx/em28xx-cards.c | 1 + 1 file changed, 1 insertion(+) (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 3be05dcc1..a608f0906 100644 --- a/linux/drivers/media/video/em28xx/em28xx-cards.c +++ b/linux/drivers/media/video/em28xx/em28xx-cards.c @@ -2012,6 +2012,7 @@ static void em28xx_setup_xc3028(struct em28xx *dev, struct xc2028_ctrl *ctl) ctl->demod = XC3028_FE_ZARLINK456; break; case EM2880_BOARD_TERRATEC_HYBRID_XS: + case EM2881_BOARD_PINNACLE_HYBRID_PRO: ctl->demod = XC3028_FE_ZARLINK456; break; case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900_R2: -- cgit v1.2.3 From 340a2011aeb2b8f88e241a9165733518fb97a61c Mon Sep 17 00:00:00 2001 From: Antoine Jacquet Date: Wed, 15 Jul 2009 20:54:55 -0300 Subject: zr364xx: implement V4L2_CAP_STREAMING From: Lamarque Vieira Souza This patch implements V4L2_CAP_STREAMING for the zr364xx driver, by converting the driver to use videobuf. This version is synced with v4l-dvb as of 15/Jul/2009. Tested with Creative PC-CAM 880. It basically: . implements V4L2_CAP_STREAMING using videobuf; . re-implements V4L2_CAP_READWRITE using videobuf; . copies cam->udev->product to the card field of the v4l2_capability struct. That gives more information to the users about the webcam; . moves the brightness setting code from before requesting a frame (in read_frame) to the vidioc_s_ctrl ioctl. This way the brightness code is executed only when the application requests a change in brightness and not before every frame read; . comments part of zr364xx_vidioc_try_fmt_vid_cap that says that Skype + libv4l do not work. This patch fixes zr364xx for applications such as mplayer, Kopete+libv4l and Skype+libv4l can make use of the webcam that comes with zr364xx chip. Signed-off-by: Lamarque V. Souza Signed-off-by: Antoine Jacquet --- linux/drivers/media/video/zr364xx.c | 1165 ++++++++++++++++++++++++++++------- 1 file changed, 938 insertions(+), 227 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/zr364xx.c b/linux/drivers/media/video/zr364xx.c index 8746f067d..7dff47834 100644 --- a/linux/drivers/media/video/zr364xx.c +++ b/linux/drivers/media/video/zr364xx.c @@ -1,5 +1,5 @@ /* - * Zoran 364xx based USB webcam module version 0.72 + * Zoran 364xx based USB webcam module version 0.73 * * Allows you to use your USB webcam with V4L2 applications * This is still in heavy developpement ! @@ -10,6 +10,8 @@ * Heavily inspired by usb-skeleton.c, vicam.c, cpia.c and spca50x.c drivers * V4L2 version inspired by meye.c driver * + * Some video buffer code by Lamarque based on s2255drv.c and vivi.c drivers. + * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or @@ -35,25 +37,34 @@ #include #include #include +#include #include "compat.h" /* Version Information */ -#define DRIVER_VERSION "v0.72" +#define DRIVER_VERSION "v0.73" +#define ZR364_VERSION_CODE KERNEL_VERSION(0, 7, 3) #define DRIVER_AUTHOR "Antoine Jacquet, http://royale.zerezo.com/" #define DRIVER_DESC "Zoran 364xx" /* Camera */ -#define FRAMES 2 +#define FRAMES 1 #define MAX_FRAME_SIZE 100000 #define BUFFER_SIZE 0x1000 #define CTRL_TIMEOUT 500 +#define ZR364XX_DEF_BUFS 4 +#define ZR364XX_READ_IDLE 0 +#define ZR364XX_READ_FRAME 1 /* Debug macro */ -#define DBG(x...) if (debug) printk(KERN_INFO KBUILD_MODNAME x) - +#define DBG(fmt, args...) \ + do { \ + if (debug) { \ + printk(KERN_INFO KBUILD_MODNAME " " fmt, ##args); \ + } \ + } while (0) /* Init methods, need to find nicer names for these * the exact names of the chipsets would be the best if someone finds it */ @@ -102,24 +113,93 @@ static struct usb_device_id device_table[] = { MODULE_DEVICE_TABLE(usb, device_table); +struct zr364xx_mode { + u32 color; /* output video color format */ + u32 brightness; /* brightness */ +}; + +/* frame structure */ +struct zr364xx_framei { + unsigned long ulState; /* ulState:ZR364XX_READ_IDLE, + ZR364XX_READ_FRAME */ + void *lpvbits; /* image data */ + unsigned long cur_size; /* current data copied to it */ +}; + +/* image buffer structure */ +struct zr364xx_bufferi { + unsigned long dwFrames; /* number of frames in buffer */ + struct zr364xx_framei frame[FRAMES]; /* array of FRAME structures */ +}; + +struct zr364xx_dmaqueue { + struct list_head active; + struct zr364xx_camera *cam; +}; + +struct zr364xx_pipeinfo { + u32 transfer_size; + u8 *transfer_buffer; + u32 state; + void *stream_urb; + void *cam; /* back pointer to zr364xx_camera struct */ + u32 err_count; + u32 idx; +}; + +struct zr364xx_fmt { + char *name; + u32 fourcc; + int depth; +}; + +/* image formats. */ +static const struct zr364xx_fmt formats[] = { + { + .name = "JPG", + .fourcc = V4L2_PIX_FMT_JPEG, + .depth = 24 + } +}; /* Camera stuff */ struct zr364xx_camera { struct usb_device *udev; /* save off the usb device pointer */ struct usb_interface *interface;/* the interface for this device */ struct video_device *vdev; /* v4l video device */ - u8 *framebuf; int nb; - unsigned char *buffer; + struct zr364xx_bufferi buffer; int skip; - int brightness; int width; int height; int method; struct mutex lock; + struct mutex open_lock; int users; + + spinlock_t slock; + struct zr364xx_dmaqueue vidq; + int resources; + int last_frame; + int cur_frame; + unsigned long frame_count; + int b_acquire; + struct zr364xx_pipeinfo pipe[1]; + + u8 read_endpoint; + + const struct zr364xx_fmt *fmt; + struct videobuf_queue vb_vidq; + enum v4l2_buf_type type; + struct zr364xx_mode mode; }; +/* buffer for one video frame */ +struct zr364xx_buffer { + /* common v4l buffer stuff -- must be first */ + struct videobuf_buffer vb; + const struct zr364xx_fmt *fmt; +}; /* function used to send initialisation commands to the camera */ static int send_control_msg(struct usb_device *udev, u8 request, u16 value, @@ -273,139 +353,116 @@ static unsigned char header2[] = { }; static unsigned char header3; +/* ------------------------------------------------------------------ + Videobuf operations + ------------------------------------------------------------------*/ +static int buffer_setup(struct videobuf_queue *vq, unsigned int *count, + unsigned int *size) +{ + struct zr364xx_camera *cam = vq->priv_data; -/********************/ -/* V4L2 integration */ -/********************/ + *size = cam->width * cam->height * (cam->fmt->depth >> 3); -/* this function reads a full JPEG picture synchronously - * TODO: do it asynchronously... */ -static int read_frame(struct zr364xx_camera *cam, int framenum) -{ - int i, n, temp, head, size, actual_length; - unsigned char *ptr = NULL, *jpeg; - - redo: - /* hardware brightness */ - n = send_control_msg(cam->udev, 1, 0x2001, 0, NULL, 0); - temp = (0x60 << 8) + 127 - cam->brightness; - n = send_control_msg(cam->udev, 1, temp, 0, NULL, 0); - - /* during the first loop we are going to insert JPEG header */ - head = 0; - /* this is the place in memory where we are going to build - * the JPEG image */ - jpeg = cam->framebuf + framenum * MAX_FRAME_SIZE; - /* read data... */ - do { - n = usb_bulk_msg(cam->udev, - usb_rcvbulkpipe(cam->udev, 0x81), - cam->buffer, BUFFER_SIZE, &actual_length, - CTRL_TIMEOUT); - DBG("buffer : %d %d", cam->buffer[0], cam->buffer[1]); - DBG("bulk : n=%d size=%d", n, actual_length); - if (n < 0) { - dev_err(&cam->udev->dev, "error reading bulk msg\n"); - return 0; - } - if (actual_length < 0 || actual_length > BUFFER_SIZE) { - dev_err(&cam->udev->dev, "wrong number of bytes\n"); - return 0; - } + if (*count == 0) + *count = ZR364XX_DEF_BUFS; - /* swap bytes if camera needs it */ - if (cam->method == METHOD0) { - u16 *buf = (u16*)cam->buffer; - for (i = 0; i < BUFFER_SIZE/2; i++) - swab16s(buf + i); - } + while (*size * (*count) > ZR364XX_DEF_BUFS * 1024 * 1024) + (*count)--; - /* write the JPEG header */ - if (!head) { - DBG("jpeg header"); - ptr = jpeg; - memcpy(ptr, header1, sizeof(header1)); - ptr += sizeof(header1); - header3 = 0; - memcpy(ptr, &header3, 1); - ptr++; - memcpy(ptr, cam->buffer, 64); - ptr += 64; - header3 = 1; - memcpy(ptr, &header3, 1); - ptr++; - memcpy(ptr, cam->buffer + 64, 64); - ptr += 64; - memcpy(ptr, header2, sizeof(header2)); - ptr += sizeof(header2); - memcpy(ptr, cam->buffer + 128, - actual_length - 128); - ptr += actual_length - 128; - head = 1; - DBG("header : %d %d %d %d %d %d %d %d %d", - cam->buffer[0], cam->buffer[1], cam->buffer[2], - cam->buffer[3], cam->buffer[4], cam->buffer[5], - cam->buffer[6], cam->buffer[7], cam->buffer[8]); - } else { - memcpy(ptr, cam->buffer, actual_length); - ptr += actual_length; - } - } - /* ... until there is no more */ - while (actual_length == BUFFER_SIZE); + return 0; +} - /* we skip the 2 first frames which are usually buggy */ - if (cam->skip) { - cam->skip--; - goto redo; - } +static void free_buffer(struct videobuf_queue *vq, struct zr364xx_buffer *buf) +{ + DBG("%s\n", __func__); - /* go back to find the JPEG EOI marker */ - size = ptr - jpeg; - ptr -= 2; - while (ptr > jpeg) { - if (*ptr == 0xFF && *(ptr + 1) == 0xD9 - && *(ptr + 2) == 0xFF) - break; - ptr--; - } - if (ptr == jpeg) - DBG("No EOI marker"); + if (in_interrupt()) + BUG(); - /* Sometimes there is junk data in the middle of the picture, - * we want to skip this bogus frames */ - while (ptr > jpeg) { - if (*ptr == 0xFF && *(ptr + 1) == 0xFF - && *(ptr + 2) == 0xFF) - break; - ptr--; + videobuf_vmalloc_free(&buf->vb); + buf->vb.state = VIDEOBUF_NEEDS_INIT; +} + +static int buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb, + enum v4l2_field field) +{ + struct zr364xx_camera *cam = vq->priv_data; + struct zr364xx_buffer *buf = container_of(vb, struct zr364xx_buffer, + vb); + int rc; + + DBG("%s, field=%d, fmt name = %s\n", __func__, field, cam->fmt != NULL ? + cam->fmt->name : ""); + if (cam->fmt == NULL) + return -EINVAL; + + buf->vb.size = cam->width * cam->height * (cam->fmt->depth >> 3); + + if (buf->vb.baddr != 0 && buf->vb.bsize < buf->vb.size) { + DBG("invalid buffer prepare\n"); + return -EINVAL; } - if (ptr != jpeg) { - DBG("Bogus frame ? %d", cam->nb); - goto redo; + + buf->fmt = cam->fmt; + buf->vb.width = cam->width; + buf->vb.height = cam->height; + buf->vb.field = field; + + if (buf->vb.state == VIDEOBUF_NEEDS_INIT) { + rc = videobuf_iolock(vq, &buf->vb, NULL); + if (rc < 0) + goto fail; } - DBG("jpeg : %d %d %d %d %d %d %d %d", - jpeg[0], jpeg[1], jpeg[2], jpeg[3], - jpeg[4], jpeg[5], jpeg[6], jpeg[7]); + buf->vb.state = VIDEOBUF_PREPARED; + return 0; +fail: + free_buffer(vq, buf); + return rc; +} + +static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) +{ + struct zr364xx_buffer *buf = container_of(vb, struct zr364xx_buffer, + vb); + struct zr364xx_camera *cam = vq->priv_data; + + DBG("%s\n", __func__); - return size; + buf->vb.state = VIDEOBUF_QUEUED; + list_add_tail(&buf->vb.queue, &cam->vidq.active); } +static void buffer_release(struct videobuf_queue *vq, + struct videobuf_buffer *vb) +{ + struct zr364xx_buffer *buf = container_of(vb, struct zr364xx_buffer, + vb); + + DBG("%s\n", __func__); + free_buffer(vq, buf); +} + +static struct videobuf_queue_ops zr364xx_video_qops = { + .buf_setup = buffer_setup, + .buf_prepare = buffer_prepare, + .buf_queue = buffer_queue, + .buf_release = buffer_release, +}; + +/********************/ +/* V4L2 integration */ +/********************/ +static int zr364xx_vidioc_streamon(struct file *file, void *priv, + enum v4l2_buf_type type); -static ssize_t zr364xx_read(struct file *file, char __user *buf, size_t cnt, +static ssize_t zr364xx_read(struct file *file, char __user *buf, size_t count, loff_t * ppos) { - unsigned long count = cnt; - struct video_device *vdev = video_devdata(file); - struct zr364xx_camera *cam; + struct zr364xx_camera *cam = video_drvdata(file); - DBG("zr364xx_read: read %d bytes.", (int) count); - - if (vdev == NULL) - return -ENODEV; - cam = video_get_drvdata(vdev); + DBG("%s\n", __func__); if (!buf) return -EINVAL; @@ -413,21 +470,275 @@ static ssize_t zr364xx_read(struct file *file, char __user *buf, size_t cnt, if (!count) return -EINVAL; - /* NoMan Sux ! */ - count = read_frame(cam, 0); + if (cam->type == V4L2_BUF_TYPE_VIDEO_CAPTURE && + zr364xx_vidioc_streamon(file, cam, cam->type) == 0) { + DBG("%s: reading %d bytes at pos %d.\n", __func__, (int) count, + (int) *ppos); + + /* NoMan Sux ! */ + return videobuf_read_one(&cam->vb_vidq, buf, count, ppos, + file->f_flags & O_NONBLOCK); + } + + return 0; +} + +/* video buffer vmalloc implementation based partly on VIVI driver which is + * Copyright (c) 2006 by + * Mauro Carvalho Chehab + * Ted Walther + * John Sokol + * http://v4l.videotechnology.com/ + * + */ +static void zr364xx_fillbuff(struct zr364xx_camera *cam, + struct zr364xx_buffer *buf, + int jpgsize) +{ + int pos = 0; + struct timeval ts; + const char *tmpbuf; + char *vbuf = videobuf_to_vmalloc(&buf->vb); + unsigned long last_frame; + struct zr364xx_framei *frm; + + if (!vbuf) + return; + + last_frame = cam->last_frame; + if (last_frame != -1) { + frm = &cam->buffer.frame[last_frame]; + tmpbuf = (const char *)cam->buffer.frame[last_frame].lpvbits; + switch (buf->fmt->fourcc) { + case V4L2_PIX_FMT_JPEG: + buf->vb.size = jpgsize; + memcpy(vbuf, tmpbuf, buf->vb.size); + break; + default: + printk(KERN_DEBUG KBUILD_MODNAME ": unknown format?\n"); + } + cam->last_frame = -1; + } else { + printk(KERN_ERR KBUILD_MODNAME ": =======no frame\n"); + return; + } + DBG("%s: Buffer 0x%08lx size= %d\n", __func__, + (unsigned long)vbuf, pos); + /* tell v4l buffer was filled */ + + buf->vb.field_count = cam->frame_count * 2; + do_gettimeofday(&ts); + buf->vb.ts = ts; + buf->vb.state = VIDEOBUF_DONE; +} + +static int zr364xx_got_frame(struct zr364xx_camera *cam, int jpgsize) +{ + struct zr364xx_dmaqueue *dma_q = &cam->vidq; + struct zr364xx_buffer *buf; + unsigned long flags = 0; + int rc = 0; + + DBG("wakeup: %p\n", &dma_q); + spin_lock_irqsave(&cam->slock, flags); + + if (list_empty(&dma_q->active)) { + DBG("No active queue to serve\n"); + rc = -1; + goto unlock; + } + buf = list_entry(dma_q->active.next, + struct zr364xx_buffer, vb.queue); + + if (!waitqueue_active(&buf->vb.done)) { + /* no one active */ + rc = -1; + goto unlock; + } + list_del(&buf->vb.queue); + do_gettimeofday(&buf->vb.ts); + DBG("[%p/%d] wakeup\n", buf, buf->vb.i); + zr364xx_fillbuff(cam, buf, jpgsize); + wake_up(&buf->vb.done); + DBG("wakeup [buf/i] [%p/%d]\n", buf, buf->vb.i); +unlock: + spin_unlock_irqrestore(&cam->slock, flags); + return 0; +} + +/* this function moves the usb stream read pipe data + * into the system buffers. + * returns 0 on success, EAGAIN if more data to process (call this + * function again). + */ +static int zr364xx_read_video_callback(struct zr364xx_camera *cam, + struct zr364xx_pipeinfo *pipe_info, + struct urb *purb) +{ + unsigned char *pdest; + unsigned char *psrc; + s32 idx = -1; + struct zr364xx_framei *frm; + int i = 0; + unsigned char *ptr = NULL; + + /*DBG("buffer to user\n");*/ + idx = cam->cur_frame; + frm = &cam->buffer.frame[idx]; + + /* swap bytes if camera needs it */ + if (cam->method == METHOD0) { + u16 *buf = (u16 *)pipe_info->transfer_buffer; + for (i = 0; i < purb->actual_length/2; i++) + swab16s(buf + i); + } + + /* search done. now find out if should be acquiring */ + if (!cam->b_acquire) { + /* we found a frame, but this channel is turned off */ + frm->ulState = ZR364XX_READ_IDLE; + return -EINVAL; + } + + if (frm->lpvbits == NULL) { + DBG("%s: frame buffer == NULL.%p %p %d\n", __func__, + frm, cam, idx); + return -ENOMEM; + } - if (copy_to_user(buf, cam->framebuf, count)) - return -EFAULT; + psrc = (u8 *)pipe_info->transfer_buffer; + ptr = pdest = frm->lpvbits; + + if (frm->ulState == ZR364XX_READ_IDLE) { + frm->ulState = ZR364XX_READ_FRAME; + frm->cur_size = 0; + + DBG("jpeg header, "); + memcpy(ptr, header1, sizeof(header1)); + ptr += sizeof(header1); + header3 = 0; + memcpy(ptr, &header3, 1); + ptr++; + memcpy(ptr, psrc, 64); + ptr += 64; + header3 = 1; + memcpy(ptr, &header3, 1); + ptr++; + memcpy(ptr, psrc + 64, 64); + ptr += 64; + memcpy(ptr, header2, sizeof(header2)); + ptr += sizeof(header2); + memcpy(ptr, psrc + 128, + purb->actual_length - 128); + ptr += purb->actual_length - 128; + DBG("header : %d %d %d %d %d %d %d %d %d\n", + psrc[0], psrc[1], psrc[2], + psrc[3], psrc[4], psrc[5], + psrc[6], psrc[7], psrc[8]); + frm->cur_size = ptr - pdest; + } else { + pdest += frm->cur_size; + memcpy(pdest, psrc, purb->actual_length); + frm->cur_size += purb->actual_length; + } + /*DBG("cur_size %lu urb size %d\n", frm->cur_size, + purb->actual_length);*/ + + if (purb->actual_length < pipe_info->transfer_size) { + DBG("****************Buffer[%d]full*************\n", idx); + cam->last_frame = cam->cur_frame; + cam->cur_frame++; + /* end of system frame ring buffer, start at zero */ + if (cam->cur_frame == cam->buffer.dwFrames) + cam->cur_frame = 0; + + /* frame ready */ + /* go back to find the JPEG EOI marker */ + ptr = pdest = frm->lpvbits; + ptr += frm->cur_size - 2; + while (ptr > pdest) { + if (*ptr == 0xFF && *(ptr + 1) == 0xD9 + && *(ptr + 2) == 0xFF) + break; + ptr--; + } + if (ptr == pdest) + DBG("No EOI marker\n"); + + /* Sometimes there is junk data in the middle of the picture, + * we want to skip this bogus frames */ + while (ptr > pdest) { + if (*ptr == 0xFF && *(ptr + 1) == 0xFF + && *(ptr + 2) == 0xFF) + break; + ptr--; + } + if (ptr != pdest) { + DBG("Bogus frame ? %d\n", ++(cam->nb)); + } else if (cam->b_acquire) { + /* we skip the 2 first frames which are usually buggy */ + if (cam->skip) + cam->skip--; + else { + DBG("jpeg(%lu): %d %d %d %d %d %d %d %d\n", + frm->cur_size, + pdest[0], pdest[1], pdest[2], pdest[3], + pdest[4], pdest[5], pdest[6], pdest[7]); + + zr364xx_got_frame(cam, frm->cur_size); + } + } + cam->frame_count++; + frm->ulState = ZR364XX_READ_IDLE; + frm->cur_size = 0; + } + /* done successfully */ + return 0; +} + +static int res_get(struct zr364xx_camera *cam) +{ + /* is it free? */ + mutex_lock(&cam->lock); + if (cam->resources) { + /* no, someone else uses it */ + mutex_unlock(&cam->lock); + return 0; + } + /* it's free, grab it */ + cam->resources = 1; + DBG("res: get\n"); + mutex_unlock(&cam->lock); + return 1; +} - return count; +static inline int res_check(struct zr364xx_camera *cam) +{ + return cam->resources; } +static void res_free(struct zr364xx_camera *cam) +{ + mutex_lock(&cam->lock); + cam->resources = 0; + mutex_unlock(&cam->lock); + DBG("res: put\n"); +} static int zr364xx_vidioc_querycap(struct file *file, void *priv, struct v4l2_capability *cap) { - strcpy(cap->driver, DRIVER_DESC); - cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE; + struct zr364xx_camera *cam = video_drvdata(file); + + strlcpy(cap->driver, DRIVER_DESC, sizeof(cap->driver)); + strlcpy(cap->card, cam->udev->product, sizeof(cap->card)); + strlcpy(cap->bus_info, dev_name(&cam->udev->dev), + sizeof(cap->bus_info)); + cap->version = ZR364_VERSION_CODE; + cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | + V4L2_CAP_READWRITE | + V4L2_CAP_STREAMING; + return 0; } @@ -459,12 +770,11 @@ static int zr364xx_vidioc_s_input(struct file *file, void *priv, static int zr364xx_vidioc_queryctrl(struct file *file, void *priv, struct v4l2_queryctrl *c) { - struct video_device *vdev = video_devdata(file); struct zr364xx_camera *cam; - if (vdev == NULL) + if (file == NULL) return -ENODEV; - cam = video_get_drvdata(vdev); + cam = video_drvdata(file); switch (c->id) { case V4L2_CID_BRIGHTNESS: @@ -473,7 +783,7 @@ static int zr364xx_vidioc_queryctrl(struct file *file, void *priv, c->minimum = 0; c->maximum = 127; c->step = 1; - c->default_value = cam->brightness; + c->default_value = cam->mode.brightness; c->flags = 0; break; default: @@ -485,36 +795,42 @@ static int zr364xx_vidioc_queryctrl(struct file *file, void *priv, static int zr364xx_vidioc_s_ctrl(struct file *file, void *priv, struct v4l2_control *c) { - struct video_device *vdev = video_devdata(file); struct zr364xx_camera *cam; + int temp; - if (vdev == NULL) + if (file == NULL) return -ENODEV; - cam = video_get_drvdata(vdev); + cam = video_drvdata(file); switch (c->id) { case V4L2_CID_BRIGHTNESS: - cam->brightness = c->value; + cam->mode.brightness = c->value; + /* hardware brightness */ + mutex_lock(&cam->lock); + send_control_msg(cam->udev, 1, 0x2001, 0, NULL, 0); + temp = (0x60 << 8) + 127 - cam->mode.brightness; + send_control_msg(cam->udev, 1, temp, 0, NULL, 0); + mutex_unlock(&cam->lock); break; default: return -EINVAL; } + return 0; } static int zr364xx_vidioc_g_ctrl(struct file *file, void *priv, struct v4l2_control *c) { - struct video_device *vdev = video_devdata(file); struct zr364xx_camera *cam; - if (vdev == NULL) + if (file == NULL) return -ENODEV; - cam = video_get_drvdata(vdev); + cam = video_drvdata(file); switch (c->id) { case V4L2_CID_BRIGHTNESS: - c->value = cam->brightness; + c->value = cam->mode.brightness; break; default: return -EINVAL; @@ -528,26 +844,36 @@ static int zr364xx_vidioc_enum_fmt_vid_cap(struct file *file, if (f->index > 0) return -EINVAL; f->flags = V4L2_FMT_FLAG_COMPRESSED; - strcpy(f->description, "JPEG"); - f->pixelformat = V4L2_PIX_FMT_JPEG; + strcpy(f->description, formats[0].name); + f->pixelformat = formats[0].fourcc; return 0; } +static char *decode_fourcc(__u32 pixelformat, char *buf) +{ + buf[0] = pixelformat & 0xff; + buf[1] = (pixelformat >> 8) & 0xff; + buf[2] = (pixelformat >> 16) & 0xff; + buf[3] = (pixelformat >> 24) & 0xff; + buf[4] = '\0'; + return buf; +} + static int zr364xx_vidioc_try_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) { - struct video_device *vdev = video_devdata(file); - struct zr364xx_camera *cam; + struct zr364xx_camera *cam = video_drvdata(file); + char pixelformat_name[5]; - if (vdev == NULL) + if (cam == NULL) return -ENODEV; - cam = video_get_drvdata(vdev); - if (f->fmt.pix.pixelformat != V4L2_PIX_FMT_JPEG) - return -EINVAL; - if (f->fmt.pix.field != V4L2_FIELD_ANY && - f->fmt.pix.field != V4L2_FIELD_NONE) + if (f->fmt.pix.pixelformat != V4L2_PIX_FMT_JPEG) { + DBG("%s: unsupported pixelformat V4L2_PIX_FMT_%s\n", __func__, + decode_fourcc(f->fmt.pix.pixelformat, pixelformat_name)); return -EINVAL; + } + f->fmt.pix.field = V4L2_FIELD_NONE; f->fmt.pix.width = cam->width; f->fmt.pix.height = cam->height; @@ -555,20 +881,22 @@ static int zr364xx_vidioc_try_fmt_vid_cap(struct file *file, void *priv, f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline; f->fmt.pix.colorspace = 0; f->fmt.pix.priv = 0; + DBG("%s: V4L2_PIX_FMT_%s (%d) ok!\n", __func__, + decode_fourcc(f->fmt.pix.pixelformat, pixelformat_name), + f->fmt.pix.field); return 0; } static int zr364xx_vidioc_g_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) { - struct video_device *vdev = video_devdata(file); struct zr364xx_camera *cam; - if (vdev == NULL) + if (file == NULL) return -ENODEV; - cam = video_get_drvdata(vdev); + cam = video_drvdata(file); - f->fmt.pix.pixelformat = V4L2_PIX_FMT_JPEG; + f->fmt.pix.pixelformat = formats[0].fourcc; f->fmt.pix.field = V4L2_FIELD_NONE; f->fmt.pix.width = cam->width; f->fmt.pix.height = cam->height; @@ -579,21 +907,26 @@ static int zr364xx_vidioc_g_fmt_vid_cap(struct file *file, void *priv, return 0; } +/* Lamarque TODO: implement changing resolution on the fly */ static int zr364xx_vidioc_s_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) { - struct video_device *vdev = video_devdata(file); - struct zr364xx_camera *cam; + struct zr364xx_camera *cam = video_drvdata(file); + struct videobuf_queue *q = &cam->vb_vidq; + char pixelformat_name[5]; + int ret = zr364xx_vidioc_try_fmt_vid_cap(file, cam, f); - if (vdev == NULL) - return -ENODEV; - cam = video_get_drvdata(vdev); + if (ret < 0) + return ret; + + mutex_lock(&q->vb_lock); + + if (videobuf_queue_is_busy(&cam->vb_vidq)) { + DBG("%s queue busy\n", __func__); + ret = -EBUSY; + goto out; + } - if (f->fmt.pix.pixelformat != V4L2_PIX_FMT_JPEG) - return -EINVAL; - if (f->fmt.pix.field != V4L2_FIELD_ANY && - f->fmt.pix.field != V4L2_FIELD_NONE) - return -EINVAL; f->fmt.pix.field = V4L2_FIELD_NONE; f->fmt.pix.width = cam->width; f->fmt.pix.height = cam->height; @@ -601,19 +934,265 @@ static int zr364xx_vidioc_s_fmt_vid_cap(struct file *file, void *priv, f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline; f->fmt.pix.colorspace = 0; f->fmt.pix.priv = 0; - DBG("ok!"); + cam->vb_vidq.field = f->fmt.pix.field; + cam->mode.color = V4L2_PIX_FMT_JPEG; + ret = 0; + +out: + mutex_unlock(&q->vb_lock); + + DBG("%s: V4L2_PIX_FMT_%s (%d) ok!\n", __func__, + decode_fourcc(f->fmt.pix.pixelformat, pixelformat_name), + f->fmt.pix.field); + return ret; +} + +static int zr364xx_vidioc_reqbufs(struct file *file, void *priv, + struct v4l2_requestbuffers *p) +{ + int rc; + struct zr364xx_camera *cam = video_drvdata(file); + rc = videobuf_reqbufs(&cam->vb_vidq, p); + return rc; +} + +static int zr364xx_vidioc_querybuf(struct file *file, + void *priv, + struct v4l2_buffer *p) +{ + int rc; + struct zr364xx_camera *cam = video_drvdata(file); + rc = videobuf_querybuf(&cam->vb_vidq, p); + return rc; +} + +static int zr364xx_vidioc_qbuf(struct file *file, + void *priv, + struct v4l2_buffer *p) +{ + int rc; + struct zr364xx_camera *cam = video_drvdata(file); + DBG("%s\n", __func__); + rc = videobuf_qbuf(&cam->vb_vidq, p); + return rc; +} + +static int zr364xx_vidioc_dqbuf(struct file *file, + void *priv, + struct v4l2_buffer *p) +{ + int rc; + struct zr364xx_camera *cam = video_drvdata(file); + DBG("%s\n", __func__); + rc = videobuf_dqbuf(&cam->vb_vidq, p, file->f_flags & O_NONBLOCK); + return rc; +} + +static void read_pipe_completion(struct urb *purb) +{ + struct zr364xx_pipeinfo *pipe_info; + struct zr364xx_camera *cam; + int pipe; + + pipe_info = purb->context; + /*DBG("%s %p, status %d\n", __func__, purb, purb->status);*/ + if (pipe_info == NULL) { + printk(KERN_ERR KBUILD_MODNAME ": no context!\n"); + return; + } + + cam = pipe_info->cam; + if (cam == NULL) { + printk(KERN_ERR KBUILD_MODNAME ": no context!\n"); + return; + } + + /* if shutting down, do not resubmit, exit immediately */ + if (purb->status == -ESHUTDOWN) { + DBG("%s, err shutdown\n", __func__); + pipe_info->err_count++; + return; + } + + if (pipe_info->state == 0) { + DBG("exiting USB pipe\n"); + return; + } + + if (purb->actual_length < 0 || + purb->actual_length > pipe_info->transfer_size) { + dev_err(&cam->udev->dev, "wrong number of bytes\n"); + return; + } + + if (purb->status == 0) + zr364xx_read_video_callback(cam, pipe_info, purb); + else { + pipe_info->err_count++; + DBG("%s: failed URB %d\n", __func__, purb->status); + } + + pipe = usb_rcvbulkpipe(cam->udev, cam->read_endpoint); + + /* reuse urb */ + usb_fill_bulk_urb(pipe_info->stream_urb, cam->udev, + pipe, + pipe_info->transfer_buffer, + pipe_info->transfer_size, + read_pipe_completion, pipe_info); + + if (pipe_info->state != 0) { + purb->status = usb_submit_urb(pipe_info->stream_urb, + GFP_ATOMIC); + + if (purb->status) + dev_err(&cam->udev->dev, + "error submitting urb (error=%i)\n", + purb->status); + } else + DBG("read pipe complete state 0\n"); +} + +static int zr364xx_start_readpipe(struct zr364xx_camera *cam) +{ + int pipe; + int retval; + struct zr364xx_pipeinfo *pipe_info = cam->pipe; + pipe = usb_rcvbulkpipe(cam->udev, cam->read_endpoint); + DBG("%s: start pipe IN x%x\n", __func__, cam->read_endpoint); + + pipe_info->state = 1; + pipe_info->err_count = 0; + pipe_info->stream_urb = usb_alloc_urb(0, GFP_KERNEL); + if (!pipe_info->stream_urb) { + dev_err(&cam->udev->dev, "ReadStream: Unable to alloc URB\n"); + return -ENOMEM; + } + /* transfer buffer allocated in board_init */ + usb_fill_bulk_urb(pipe_info->stream_urb, cam->udev, + pipe, + pipe_info->transfer_buffer, + pipe_info->transfer_size, + read_pipe_completion, pipe_info); + + DBG("submitting URB %p\n", pipe_info->stream_urb); + retval = usb_submit_urb(pipe_info->stream_urb, GFP_KERNEL); + if (retval) { + printk(KERN_ERR KBUILD_MODNAME ": start read pipe failed\n"); + return retval; + } + + return 0; +} + +static void zr364xx_stop_readpipe(struct zr364xx_camera *cam) +{ + struct zr364xx_pipeinfo *pipe_info; + + if (cam == NULL) { + printk(KERN_ERR KBUILD_MODNAME ": invalid device\n"); + return; + } + DBG("stop read pipe\n"); + pipe_info = cam->pipe; + if (pipe_info) { + if (pipe_info->state != 0) + pipe_info->state = 0; + + if (pipe_info->stream_urb) { + /* cancel urb */ + usb_kill_urb(pipe_info->stream_urb); + usb_free_urb(pipe_info->stream_urb); + pipe_info->stream_urb = NULL; + } + } + DBG("stop read pipe\n"); + return; +} + +/* starts acquisition process */ +static int zr364xx_start_acquire(struct zr364xx_camera *cam) +{ + int j; + + DBG("start acquire\n"); + + cam->last_frame = -1; + cam->cur_frame = 0; + for (j = 0; j < FRAMES; j++) { + cam->buffer.frame[j].ulState = ZR364XX_READ_IDLE; + cam->buffer.frame[j].cur_size = 0; + } + return 0; +} + +static inline int zr364xx_stop_acquire(struct zr364xx_camera *cam) +{ + cam->b_acquire = 0; return 0; } static int zr364xx_vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type type) { - return 0; + struct zr364xx_camera *cam = video_drvdata(file); + int j; + int res; + + DBG("%s\n", __func__); + + if (cam->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { + dev_err(&cam->udev->dev, "invalid fh type0\n"); + return -EINVAL; + } + if (cam->type != type) { + dev_err(&cam->udev->dev, "invalid fh type1\n"); + return -EINVAL; + } + + if (!res_get(cam)) { + dev_err(&cam->udev->dev, "stream busy\n"); + return -EBUSY; + } + + cam->last_frame = -1; + cam->cur_frame = 0; + cam->frame_count = 0; + for (j = 0; j < FRAMES; j++) { + cam->buffer.frame[j].ulState = ZR364XX_READ_IDLE; + cam->buffer.frame[j].cur_size = 0; + } + res = videobuf_streamon(&cam->vb_vidq); + if (res == 0) { + zr364xx_start_acquire(cam); + cam->b_acquire = 1; + } else { + res_free(cam); + } + DBG("%s: %d\n", __func__, res); + return res; } static int zr364xx_vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type type) { + int res; + struct zr364xx_camera *cam = video_drvdata(file); + + DBG("%s\n", __func__); + if (cam->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { + dev_err(&cam->udev->dev, "invalid fh type0\n"); + return -EINVAL; + } + if (cam->type != type) { + dev_err(&cam->udev->dev, "invalid fh type1\n"); + return -EINVAL; + } + zr364xx_stop_acquire(cam); + res = videobuf_streamoff(&cam->vb_vidq); + if (res < 0) + return res; + res_free(cam); return 0; } @@ -622,28 +1201,19 @@ static int zr364xx_vidioc_streamoff(struct file *file, void *priv, static int zr364xx_open(struct file *file) { struct video_device *vdev = video_devdata(file); - struct zr364xx_camera *cam = video_get_drvdata(vdev); + struct zr364xx_camera *cam = video_drvdata(file); struct usb_device *udev = cam->udev; int i, err; - DBG("zr364xx_open"); + DBG("%s\n", __func__); - mutex_lock(&cam->lock); + mutex_lock(&cam->open_lock); if (cam->users) { err = -EBUSY; goto out; } - if (!cam->framebuf) { - cam->framebuf = vmalloc_32(MAX_FRAME_SIZE * FRAMES); - if (!cam->framebuf) { - dev_err(&cam->udev->dev, "vmalloc_32 failed!\n"); - err = -ENOMEM; - goto out; - } - } - for (i = 0; init[cam->method][i].size != -1; i++) { err = send_control_msg(udev, 1, init[cam->method][i].value, @@ -659,6 +1229,14 @@ static int zr364xx_open(struct file *file) cam->skip = 2; cam->users++; file->private_data = vdev; + cam->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + cam->fmt = formats; + + videobuf_queue_vmalloc_init(&cam->vb_vidq, &zr364xx_video_qops, + NULL, &cam->slock, + cam->type, + V4L2_FIELD_NONE, + sizeof(struct zr364xx_buffer), cam); /* Added some delay here, since opening/closing the camera quickly, * like Ekiga does during its startup, can crash the webcam @@ -667,28 +1245,72 @@ static int zr364xx_open(struct file *file) err = 0; out: - mutex_unlock(&cam->lock); + mutex_unlock(&cam->open_lock); + DBG("%s: %d\n", __func__, err); return err; } +static void zr364xx_destroy(struct zr364xx_camera *cam) +{ + unsigned long i; + + if (!cam) { + printk(KERN_ERR KBUILD_MODNAME ", %s: no device\n", __func__); + return; + } + mutex_lock(&cam->open_lock); + if (cam->vdev) + video_unregister_device(cam->vdev); + cam->vdev = NULL; + + /* stops the read pipe if it is running */ + if (cam->b_acquire) + zr364xx_stop_acquire(cam); + + zr364xx_stop_readpipe(cam); + + /* release sys buffers */ + for (i = 0; i < FRAMES; i++) { + if (cam->buffer.frame[i].lpvbits) { + DBG("vfree %p\n", cam->buffer.frame[i].lpvbits); + vfree(cam->buffer.frame[i].lpvbits); + } + cam->buffer.frame[i].lpvbits = NULL; + } + + /* release transfer buffer */ + kfree(cam->pipe->transfer_buffer); + cam->pipe->transfer_buffer = NULL; + + DBG("%s\n", __func__); + mutex_unlock(&cam->open_lock); + kfree(cam); + cam = NULL; +} /* release the camera */ static int zr364xx_release(struct file *file) { - struct video_device *vdev = video_devdata(file); struct zr364xx_camera *cam; struct usb_device *udev; int i, err; - DBG("zr364xx_release"); + DBG("%s\n", __func__); + cam = video_drvdata(file); - if (vdev == NULL) + if (!cam) return -ENODEV; - cam = video_get_drvdata(vdev); + mutex_lock(&cam->open_lock); udev = cam->udev; - mutex_lock(&cam->lock); + /* turn off stream */ + if (res_check(cam)) { + if (cam->b_acquire) + zr364xx_stop_acquire(cam); + videobuf_streamoff(&cam->vb_vidq); + res_free(cam); + } cam->users--; file->private_data = NULL; @@ -711,40 +1333,43 @@ static int zr364xx_release(struct file *file) err = 0; out: - mutex_unlock(&cam->lock); + mutex_unlock(&cam->open_lock); + return err; } static int zr364xx_mmap(struct file *file, struct vm_area_struct *vma) { - void *pos; - unsigned long start = vma->vm_start; - unsigned long size = vma->vm_end - vma->vm_start; - struct video_device *vdev = video_devdata(file); - struct zr364xx_camera *cam; - - DBG("zr364xx_mmap: %ld\n", size); + struct zr364xx_camera *cam = video_drvdata(file); + int ret; - if (vdev == NULL) + if (cam == NULL) { + DBG("%s: cam == NULL\n", __func__); return -ENODEV; - cam = video_get_drvdata(vdev); - - pos = cam->framebuf; - while (size > 0) { - if (vm_insert_page(vma, start, vmalloc_to_page(pos))) - return -EAGAIN; - start += PAGE_SIZE; - pos += PAGE_SIZE; - if (size > PAGE_SIZE) - size -= PAGE_SIZE; - else - size = 0; } + DBG("mmap called, vma=0x%08lx\n", (unsigned long)vma); - return 0; + ret = videobuf_mmap_mapper(&cam->vb_vidq, vma); + + DBG("vma start=0x%08lx, size=%ld, ret=%d\n", + (unsigned long)vma->vm_start, + (unsigned long)vma->vm_end - (unsigned long)vma->vm_start, ret); + return ret; } +static unsigned int zr364xx_poll(struct file *file, + struct poll_table_struct *wait) +{ + struct zr364xx_camera *cam = video_drvdata(file); + struct videobuf_queue *q = &cam->vb_vidq; + DBG("%s\n", __func__); + + if (cam->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return POLLERR; + + return videobuf_poll_stream(file, q, wait); +} static const struct v4l2_file_operations zr364xx_fops = { .owner = THIS_MODULE, @@ -753,6 +1378,7 @@ static const struct v4l2_file_operations zr364xx_fops = { .read = zr364xx_read, .mmap = zr364xx_mmap, .ioctl = video_ioctl2, + .poll = zr364xx_poll, }; static const struct v4l2_ioctl_ops zr364xx_ioctl_ops = { @@ -769,6 +1395,10 @@ static const struct v4l2_ioctl_ops zr364xx_ioctl_ops = { .vidioc_queryctrl = zr364xx_vidioc_queryctrl, .vidioc_g_ctrl = zr364xx_vidioc_g_ctrl, .vidioc_s_ctrl = zr364xx_vidioc_s_ctrl, + .vidioc_reqbufs = zr364xx_vidioc_reqbufs, + .vidioc_querybuf = zr364xx_vidioc_querybuf, + .vidioc_qbuf = zr364xx_vidioc_qbuf, + .vidioc_dqbuf = zr364xx_vidioc_dqbuf, }; static struct video_device zr364xx_template = { @@ -784,15 +1414,76 @@ static struct video_device zr364xx_template = { /*******************/ /* USB integration */ /*******************/ +static int zr364xx_board_init(struct zr364xx_camera *cam) +{ + struct zr364xx_pipeinfo *pipe = cam->pipe; + unsigned long i; + + DBG("board init: %p\n", cam); + memset(pipe, 0, sizeof(*pipe)); + pipe->cam = cam; + pipe->transfer_size = BUFFER_SIZE; + + pipe->transfer_buffer = kzalloc(pipe->transfer_size, + GFP_KERNEL); + if (pipe->transfer_buffer == NULL) { + DBG("out of memory!\n"); + return -ENOMEM; + } + + cam->b_acquire = 0; + cam->frame_count = 0; + + /*** start create system buffers ***/ + for (i = 0; i < FRAMES; i++) { + /* always allocate maximum size for system buffers */ + cam->buffer.frame[i].lpvbits = vmalloc(MAX_FRAME_SIZE); + + DBG("valloc %p, idx %lu, pdata %p\n", + &cam->buffer.frame[i], i, + cam->buffer.frame[i].lpvbits); + if (cam->buffer.frame[i].lpvbits == NULL) { + printk(KERN_INFO KBUILD_MODNAME ": out of memory. " + "Using less frames\n"); + break; + } + } + + if (i == 0) { + printk(KERN_INFO KBUILD_MODNAME ": out of memory. Aborting\n"); + kfree(cam->pipe->transfer_buffer); + cam->pipe->transfer_buffer = NULL; + return -ENOMEM; + } else + cam->buffer.dwFrames = i; + + /* make sure internal states are set */ + for (i = 0; i < FRAMES; i++) { + cam->buffer.frame[i].ulState = ZR364XX_READ_IDLE; + cam->buffer.frame[i].cur_size = 0; + } + + cam->cur_frame = 0; + cam->last_frame = -1; + /*** end create system buffers ***/ + + /* start read pipe */ + zr364xx_start_readpipe(cam); + DBG(": board initialized\n"); + return 0; +} static int zr364xx_probe(struct usb_interface *intf, const struct usb_device_id *id) { struct usb_device *udev = interface_to_usbdev(intf); struct zr364xx_camera *cam = NULL; + struct usb_host_interface *iface_desc; + struct usb_endpoint_descriptor *endpoint; int err; + int i; - DBG("probing..."); + DBG("probing...\n"); dev_info(&intf->dev, DRIVER_DESC " compatible webcam plugged\n"); dev_info(&intf->dev, "model %04x:%04x detected\n", @@ -811,22 +1502,17 @@ static int zr364xx_probe(struct usb_interface *intf, if (cam->vdev == NULL) { dev_err(&udev->dev, "cam->vdev: out of memory !\n"); kfree(cam); + cam = NULL; return -ENOMEM; } memcpy(cam->vdev, &zr364xx_template, sizeof(zr364xx_template)); + cam->vdev->parent = &intf->dev; video_set_drvdata(cam->vdev, cam); if (debug) cam->vdev->debug = V4L2_DEBUG_IOCTL | V4L2_DEBUG_IOCTL_ARG; cam->udev = udev; - if ((cam->buffer = kmalloc(BUFFER_SIZE, GFP_KERNEL)) == NULL) { - dev_info(&udev->dev, "cam->buffer: out of memory !\n"); - video_device_release(cam->vdev); - kfree(cam); - return -ENODEV; - } - switch (mode) { case 1: dev_info(&udev->dev, "160x120 mode selected\n"); @@ -853,21 +1539,53 @@ static int zr364xx_probe(struct usb_interface *intf, header2[439] = cam->width / 256; header2[440] = cam->width % 256; + cam->users = 0; cam->nb = 0; - cam->brightness = 64; + cam->mode.brightness = 64; mutex_init(&cam->lock); + mutex_init(&cam->open_lock); + + DBG("dev: %p, udev %p interface %p\n", cam, cam->udev, intf); + + /* set up the endpoint information */ + iface_desc = intf->cur_altsetting; + DBG("num endpoints %d\n", iface_desc->desc.bNumEndpoints); + for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { + endpoint = &iface_desc->endpoint[i].desc; + if (!cam->read_endpoint && usb_endpoint_is_bulk_in(endpoint)) { + /* we found the bulk in endpoint */ + cam->read_endpoint = endpoint->bEndpointAddress; + } + } + if (!cam->read_endpoint) { + dev_err(&intf->dev, "Could not find bulk-in endpoint\n"); + return -ENOMEM; + } + + /* v4l */ + INIT_LIST_HEAD(&cam->vidq.active); + cam->vidq.cam = cam; err = video_register_device(cam->vdev, VFL_TYPE_GRABBER, -1); if (err) { dev_err(&udev->dev, "video_register_device failed\n"); video_device_release(cam->vdev); - kfree(cam->buffer); kfree(cam); + cam = NULL; return err; } usb_set_intfdata(intf, cam); + /* load zr364xx board specific */ + err = zr364xx_board_init(cam); + if (err) { + spin_lock_init(&cam->slock); + return err; + } + + spin_lock_init(&cam->slock); + dev_info(&udev->dev, DRIVER_DESC " controlling video device %d\n", cam->vdev->num); return 0; @@ -877,17 +1595,10 @@ static int zr364xx_probe(struct usb_interface *intf, static void zr364xx_disconnect(struct usb_interface *intf) { struct zr364xx_camera *cam = usb_get_intfdata(intf); + videobuf_mmap_free(&cam->vb_vidq); usb_set_intfdata(intf, NULL); dev_info(&intf->dev, DRIVER_DESC " webcam unplugged\n"); - if (cam->vdev) - video_unregister_device(cam->vdev); - cam->vdev = NULL; - kfree(cam->buffer); - cam->buffer = NULL; - vfree(cam->framebuf); - cam->framebuf = NULL; - kfree(cam); - cam = NULL; + zr364xx_destroy(cam); } -- cgit v1.2.3 From 2f2fb3516ed879fd5591730ade5d05328d3afaa5 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Sun, 19 Jul 2009 10:29:20 +0200 Subject: gspca - main: Support for vidioc_g_chip_ident and vidioc_g/s_register. From: Brian Johnson Priority: high Signed-off-by: Brian Johnson Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/gspca.c | 73 +++++++++++++++++++++++++++++++++ linux/drivers/media/video/gspca/gspca.h | 9 ++++ 2 files changed, 82 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/gspca.c b/linux/drivers/media/video/gspca/gspca.c index fe759178f..eedf9a60c 100644 --- a/linux/drivers/media/video/gspca/gspca.c +++ b/linux/drivers/media/video/gspca/gspca.c @@ -758,6 +758,74 @@ static int gspca_get_mode(struct gspca_dev *gspca_dev, return -EINVAL; } +#ifdef CONFIG_VIDEO_ADV_DEBUG +static int vidioc_g_register(struct file *file, void *priv, + struct v4l2_dbg_register *reg) +{ + int ret; + struct gspca_dev *gspca_dev = priv; + + if (!gspca_dev->sd_desc->get_chip_ident) + return -EINVAL; + + if (!gspca_dev->sd_desc->get_register) + return -EINVAL; + + if (mutex_lock_interruptible(&gspca_dev->usb_lock)) + return -ERESTARTSYS; + if (gspca_dev->present) + ret = gspca_dev->sd_desc->get_register(gspca_dev, reg); + else + ret = -ENODEV; + mutex_unlock(&gspca_dev->usb_lock); + + return ret; +} + +static int vidioc_s_register(struct file *file, void *priv, + struct v4l2_dbg_register *reg) +{ + int ret; + struct gspca_dev *gspca_dev = priv; + + if (!gspca_dev->sd_desc->get_chip_ident) + return -EINVAL; + + if (!gspca_dev->sd_desc->set_register) + return -EINVAL; + + if (mutex_lock_interruptible(&gspca_dev->usb_lock)) + return -ERESTARTSYS; + if (gspca_dev->present) + ret = gspca_dev->sd_desc->set_register(gspca_dev, reg); + else + ret = -ENODEV; + mutex_unlock(&gspca_dev->usb_lock); + + return ret; +} +#endif + +static int vidioc_g_chip_ident(struct file *file, void *priv, + struct v4l2_dbg_chip_ident *chip) +{ + int ret; + struct gspca_dev *gspca_dev = priv; + + if (!gspca_dev->sd_desc->get_chip_ident) + return -EINVAL; + + if (mutex_lock_interruptible(&gspca_dev->usb_lock)) + return -ERESTARTSYS; + if (gspca_dev->present) + ret = gspca_dev->sd_desc->get_chip_ident(gspca_dev, chip); + else + ret = -ENODEV; + mutex_unlock(&gspca_dev->usb_lock); + + return ret; +} + static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, struct v4l2_fmtdesc *fmtdesc) { @@ -1914,6 +1982,11 @@ static const struct v4l2_ioctl_ops dev_ioctl_ops = { .vidioc_s_parm = vidioc_s_parm, .vidioc_s_std = vidioc_s_std, .vidioc_enum_framesizes = vidioc_enum_framesizes, +#ifdef CONFIG_VIDEO_ADV_DEBUG + .vidioc_g_register = vidioc_g_register, + .vidioc_s_register = vidioc_s_register, +#endif + .vidioc_g_chip_ident = vidioc_g_chip_ident, #ifdef CONFIG_VIDEO_V4L1_COMPAT .vidiocgmbuf = vidiocgmbuf, #endif diff --git a/linux/drivers/media/video/gspca/gspca.h b/linux/drivers/media/video/gspca/gspca.h index 0508a23b9..70b1fd830 100644 --- a/linux/drivers/media/video/gspca/gspca.h +++ b/linux/drivers/media/video/gspca/gspca.h @@ -69,6 +69,10 @@ typedef void (*cam_v_op) (struct gspca_dev *); typedef int (*cam_cf_op) (struct gspca_dev *, const struct usb_device_id *); typedef int (*cam_jpg_op) (struct gspca_dev *, struct v4l2_jpegcompression *); +typedef int (*cam_reg_op) (struct gspca_dev *, + struct v4l2_dbg_register *); +typedef int (*cam_ident_op) (struct gspca_dev *, + struct v4l2_dbg_chip_ident *); typedef int (*cam_streamparm_op) (struct gspca_dev *, struct v4l2_streamparm *); typedef int (*cam_qmnu_op) (struct gspca_dev *, @@ -107,6 +111,11 @@ struct sd_desc { cam_qmnu_op querymenu; cam_streamparm_op get_streamparm; cam_streamparm_op set_streamparm; +#ifdef CONFIG_VIDEO_ADV_DEBUG + cam_reg_op set_register; + cam_reg_op get_register; +#endif + cam_ident_op get_chip_ident; }; /* packet types when moving from iso buf to frame buf */ -- cgit v1.2.3 From 624d36913e55b452914dcaa83e0ff84330bf3ec0 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Sun, 19 Jul 2009 10:52:58 +0200 Subject: gspca - sn9c20x: New subdriver for sn9c201 and sn9c202 bridges. From: Brian Johnson Priority: high Signed-off-by: Brian Johnson Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/Kconfig | 16 + linux/drivers/media/video/gspca/Makefile | 2 + linux/drivers/media/video/gspca/sn9c20x.c | 2433 +++++++++++++++++++++++++++++ 3 files changed, 2451 insertions(+) create mode 100644 linux/drivers/media/video/gspca/sn9c20x.c (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/Kconfig b/linux/drivers/media/video/gspca/Kconfig index 578dc4ffc..34f46f2bc 100644 --- a/linux/drivers/media/video/gspca/Kconfig +++ b/linux/drivers/media/video/gspca/Kconfig @@ -102,6 +102,22 @@ config USB_GSPCA_PAC7311 To compile this driver as a module, choose M here: the module will be called gspca_pac7311. +config USB_GSPCA_SN9C20X + tristate "SN9C20X USB Camera Driver" + depends on VIDEO_V4L2 && USB_GSPCA + help + Say Y here if you want support for cameras based on the + sn9c20x chips (SN9C201 and SN9C202). + + To compile this driver as a module, choose M here: the + module will be called gspca_sn9c20x. + +config USB_GSPCA_SN9C20X_EVDEV + bool "Enable evdev support" + depends on USB_GSPCA_SN9C20X + ---help--- + Say Y here in order to enable evdev support for sn9c20x webcam button. + config USB_GSPCA_SONIXB tristate "SONIX Bayer USB Camera Driver" depends on VIDEO_V4L2 && USB_GSPCA diff --git a/linux/drivers/media/video/gspca/Makefile b/linux/drivers/media/video/gspca/Makefile index 8a6643e8e..f6d3b86e9 100644 --- a/linux/drivers/media/video/gspca/Makefile +++ b/linux/drivers/media/video/gspca/Makefile @@ -8,6 +8,7 @@ obj-$(CONFIG_USB_GSPCA_OV519) += gspca_ov519.o obj-$(CONFIG_USB_GSPCA_OV534) += gspca_ov534.o obj-$(CONFIG_USB_GSPCA_PAC207) += gspca_pac207.o obj-$(CONFIG_USB_GSPCA_PAC7311) += gspca_pac7311.o +obj-$(CONFIG_USB_GSPCA_SN9C20X) += gspca_sn9c20x.o obj-$(CONFIG_USB_GSPCA_SONIXB) += gspca_sonixb.o obj-$(CONFIG_USB_GSPCA_SONIXJ) += gspca_sonixj.o obj-$(CONFIG_USB_GSPCA_SPCA500) += gspca_spca500.o @@ -35,6 +36,7 @@ gspca_ov519-objs := ov519.o gspca_ov534-objs := ov534.o gspca_pac207-objs := pac207.o gspca_pac7311-objs := pac7311.o +gspca_sn9c20x-objs := sn9c20x.o gspca_sonixb-objs := sonixb.o gspca_sonixj-objs := sonixj.o gspca_spca500-objs := spca500.o diff --git a/linux/drivers/media/video/gspca/sn9c20x.c b/linux/drivers/media/video/gspca/sn9c20x.c new file mode 100644 index 000000000..78ab26ceb --- /dev/null +++ b/linux/drivers/media/video/gspca/sn9c20x.c @@ -0,0 +1,2433 @@ +/* + * Sonix sn9c201 sn9c202 library + * Copyright (C) 2008-2009 microdia project + * Copyright (C) 2009 Brian Johnson + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "gspca.h" +#include "jpeg.h" + +#include +#ifdef CONFIG_USB_GSPCA_SN9C20X_EVDEV +#include +#include +#include +#include +#endif + +MODULE_AUTHOR("Brian Johnson , " + "microdia project "); +MODULE_DESCRIPTION("GSPCA/SN9C20X USB Camera Driver"); +MODULE_LICENSE("GPL"); + +#define MODULE_NAME "sn9c20x" + +#define MODE_RAW 0x10 +#define MODE_JPEG 0x20 +#define MODE_SXGA 0x80 + +#define SENSOR_OV9650 0 +#define SENSOR_OV9655 1 +#define SENSOR_SOI968 2 +#define SENSOR_OV7660 3 +#define SENSOR_OV7670 4 +#define SENSOR_MT9V011 5 +#define SENSOR_MT9V111 6 +#define SENSOR_MT9V112 7 +#define SENSOR_MT9M001 8 +#define SENSOR_MT9M111 9 +#define SENSOR_HV7131R 10 +#define SENSOR_MT9VPRB 20 + +/* specific webcam descriptor */ +struct sd { + struct gspca_dev gspca_dev; + +#define MIN_AVG_LUM 80 +#define MAX_AVG_LUM 130 + atomic_t avg_lum; + u8 old_step; + u8 older_step; + u8 exposure_step; + + u8 brightness; + u8 contrast; + u8 saturation; + s16 hue; + u8 gamma; + u8 red; + u8 blue; + + u8 hflip; + u8 vflip; + u8 gain; + u16 exposure; + u8 auto_exposure; + + u8 i2c_addr; + u8 sensor; + u8 hstart; + u8 vstart; + + u8 *jpeg_hdr; + u8 quality; + +#ifdef CONFIG_USB_GSPCA_SN9C20X_EVDEV + struct input_dev *input_dev; + u8 input_gpio; + struct task_struct *input_task; +#endif +}; + +static int sd_setbrightness(struct gspca_dev *gspca_dev, s32 val); +static int sd_getbrightness(struct gspca_dev *gspca_dev, s32 *val); +static int sd_setcontrast(struct gspca_dev *gspca_dev, s32 val); +static int sd_getcontrast(struct gspca_dev *gspca_dev, s32 *val); +static int sd_setsaturation(struct gspca_dev *gspca_dev, s32 val); +static int sd_getsaturation(struct gspca_dev *gspca_dev, s32 *val); +static int sd_sethue(struct gspca_dev *gspca_dev, s32 val); +static int sd_gethue(struct gspca_dev *gspca_dev, s32 *val); +static int sd_setgamma(struct gspca_dev *gspca_dev, s32 val); +static int sd_getgamma(struct gspca_dev *gspca_dev, s32 *val); +static int sd_setredbalance(struct gspca_dev *gspca_dev, s32 val); +static int sd_getredbalance(struct gspca_dev *gspca_dev, s32 *val); +static int sd_setbluebalance(struct gspca_dev *gspca_dev, s32 val); +static int sd_getbluebalance(struct gspca_dev *gspca_dev, s32 *val); +static int sd_setvflip(struct gspca_dev *gspca_dev, s32 val); +static int sd_getvflip(struct gspca_dev *gspca_dev, s32 *val); +static int sd_sethflip(struct gspca_dev *gspca_dev, s32 val); +static int sd_gethflip(struct gspca_dev *gspca_dev, s32 *val); +static int sd_setgain(struct gspca_dev *gspca_dev, s32 val); +static int sd_getgain(struct gspca_dev *gspca_dev, s32 *val); +static int sd_setexposure(struct gspca_dev *gspca_dev, s32 val); +static int sd_getexposure(struct gspca_dev *gspca_dev, s32 *val); +static int sd_setautoexposure(struct gspca_dev *gspca_dev, s32 val); +static int sd_getautoexposure(struct gspca_dev *gspca_dev, s32 *val); + +static struct ctrl sd_ctrls[] = { + { +#define BRIGHTNESS_IDX 0 + { + .id = V4L2_CID_BRIGHTNESS, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Brightness", + .minimum = 0, + .maximum = 0xff, + .step = 1, +#define BRIGHTNESS_DEFAULT 0x7f + .default_value = BRIGHTNESS_DEFAULT, + }, + .set = sd_setbrightness, + .get = sd_getbrightness, + }, + { +#define CONTRAST_IDX 1 + { + .id = V4L2_CID_CONTRAST, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Contrast", + .minimum = 0, + .maximum = 0xff, + .step = 1, +#define CONTRAST_DEFAULT 0x7f + .default_value = CONTRAST_DEFAULT, + }, + .set = sd_setcontrast, + .get = sd_getcontrast, + }, + { +#define SATURATION_IDX 2 + { + .id = V4L2_CID_SATURATION, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Saturation", + .minimum = 0, + .maximum = 0xff, + .step = 1, +#define SATURATION_DEFAULT 0x7f + .default_value = SATURATION_DEFAULT, + }, + .set = sd_setsaturation, + .get = sd_getsaturation, + }, + { +#define HUE_IDX 3 + { + .id = V4L2_CID_HUE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Hue", + .minimum = -180, + .maximum = 180, + .step = 1, +#define HUE_DEFAULT 0 + .default_value = HUE_DEFAULT, + }, + .set = sd_sethue, + .get = sd_gethue, + }, + { +#define GAMMA_IDX 4 + { + .id = V4L2_CID_GAMMA, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Gamma", + .minimum = 0, + .maximum = 0xff, + .step = 1, +#define GAMMA_DEFAULT 0x10 + .default_value = GAMMA_DEFAULT, + }, + .set = sd_setgamma, + .get = sd_getgamma, + }, + { +#define BLUE_IDX 5 + { + .id = V4L2_CID_BLUE_BALANCE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Blue Balance", + .minimum = 0, + .maximum = 0x7f, + .step = 1, +#define BLUE_DEFAULT 0x28 + .default_value = BLUE_DEFAULT, + }, + .set = sd_setbluebalance, + .get = sd_getbluebalance, + }, + { +#define RED_IDX 6 + { + .id = V4L2_CID_RED_BALANCE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Red Balance", + .minimum = 0, + .maximum = 0x7f, + .step = 1, +#define RED_DEFAULT 0x28 + .default_value = RED_DEFAULT, + }, + .set = sd_setredbalance, + .get = sd_getredbalance, + }, + { +#define HFLIP_IDX 7 + { + .id = V4L2_CID_HFLIP, + .type = V4L2_CTRL_TYPE_BOOLEAN, + .name = "Horizontal Flip", + .minimum = 0, + .maximum = 1, + .step = 1, +#define HFLIP_DEFAULT 0 + .default_value = HFLIP_DEFAULT, + }, + .set = sd_sethflip, + .get = sd_gethflip, + }, + { +#define VFLIP_IDX 8 + { + .id = V4L2_CID_VFLIP, + .type = V4L2_CTRL_TYPE_BOOLEAN, + .name = "Vertical Flip", + .minimum = 0, + .maximum = 1, + .step = 1, +#define VFLIP_DEFAULT 0 + .default_value = VFLIP_DEFAULT, + }, + .set = sd_setvflip, + .get = sd_getvflip, + }, + { +#define EXPOSURE_IDX 9 + { + .id = V4L2_CID_EXPOSURE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Exposure", + .minimum = 0, + .maximum = 0x1780, + .step = 1, +#define EXPOSURE_DEFAULT 0x33 + .default_value = EXPOSURE_DEFAULT, + }, + .set = sd_setexposure, + .get = sd_getexposure, + }, + { +#define GAIN_IDX 10 + { + .id = V4L2_CID_GAIN, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Gain", + .minimum = 0, + .maximum = 28, + .step = 1, +#define GAIN_DEFAULT 0x00 + .default_value = GAIN_DEFAULT, + }, + .set = sd_setgain, + .get = sd_getgain, + }, + { +#define AUTOGAIN_IDX 11 + { + .id = V4L2_CID_AUTOGAIN, + .type = V4L2_CTRL_TYPE_BOOLEAN, + .name = "Auto Exposure", + .minimum = 0, + .maximum = 1, + .step = 1, +#define AUTO_EXPOSURE_DEFAULT 1 + .default_value = AUTO_EXPOSURE_DEFAULT, + }, + .set = sd_setautoexposure, + .get = sd_getautoexposure, + }, +}; + +static const struct v4l2_pix_format vga_mode[] = { + {160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, + .bytesperline = 240, + .sizeimage = 240 * 120, + .colorspace = V4L2_COLORSPACE_JPEG, + .priv = 0 | MODE_JPEG}, + {160, 120, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, + .bytesperline = 160, + .sizeimage = 160 * 120, + .colorspace = V4L2_COLORSPACE_SRGB, + .priv = 0 | MODE_RAW}, + {160, 120, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE, + .bytesperline = 240, + .sizeimage = 240 * 120, + .colorspace = V4L2_COLORSPACE_SRGB, + .priv = 0}, + {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, + .bytesperline = 480, + .sizeimage = 480 * 240 , + .colorspace = V4L2_COLORSPACE_JPEG, + .priv = 1 | MODE_JPEG}, + {320, 240, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, + .bytesperline = 320, + .sizeimage = 320 * 240 , + .colorspace = V4L2_COLORSPACE_SRGB, + .priv = 1 | MODE_RAW}, + {320, 240, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE, + .bytesperline = 480, + .sizeimage = 480 * 240 , + .colorspace = V4L2_COLORSPACE_SRGB, + .priv = 1}, + {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, + .bytesperline = 960, + .sizeimage = 960 * 480, + .colorspace = V4L2_COLORSPACE_JPEG, + .priv = 2 | MODE_JPEG}, + {640, 480, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, + .bytesperline = 640, + .sizeimage = 640 * 480, + .colorspace = V4L2_COLORSPACE_SRGB, + .priv = 2 | MODE_RAW}, + {640, 480, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE, + .bytesperline = 960, + .sizeimage = 960 * 480, + .colorspace = V4L2_COLORSPACE_SRGB, + .priv = 2}, +}; + +static const struct v4l2_pix_format sxga_mode[] = { + {160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, + .bytesperline = 240, + .sizeimage = 240 * 120, + .colorspace = V4L2_COLORSPACE_JPEG, + .priv = 0 | MODE_JPEG}, + {160, 120, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, + .bytesperline = 160, + .sizeimage = 160 * 120, + .colorspace = V4L2_COLORSPACE_SRGB, + .priv = 0 | MODE_RAW}, + {160, 120, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE, + .bytesperline = 240, + .sizeimage = 240 * 120, + .colorspace = V4L2_COLORSPACE_SRGB, + .priv = 0}, + {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, + .bytesperline = 480, + .sizeimage = 480 * 240 , + .colorspace = V4L2_COLORSPACE_JPEG, + .priv = 1 | MODE_JPEG}, + {320, 240, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, + .bytesperline = 320, + .sizeimage = 320 * 240 , + .colorspace = V4L2_COLORSPACE_SRGB, + .priv = 1 | MODE_RAW}, + {320, 240, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE, + .bytesperline = 480, + .sizeimage = 480 * 240 , + .colorspace = V4L2_COLORSPACE_SRGB, + .priv = 1}, + {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, + .bytesperline = 960, + .sizeimage = 960 * 480, + .colorspace = V4L2_COLORSPACE_JPEG, + .priv = 2 | MODE_JPEG}, + {640, 480, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, + .bytesperline = 640, + .sizeimage = 640 * 480, + .colorspace = V4L2_COLORSPACE_SRGB, + .priv = 2 | MODE_RAW}, + {640, 480, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE, + .bytesperline = 960, + .sizeimage = 960 * 480, + .colorspace = V4L2_COLORSPACE_SRGB, + .priv = 2}, + {1280, 1024, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, + .bytesperline = 1280, + .sizeimage = (1280 * 1024) + 64, + .colorspace = V4L2_COLORSPACE_SRGB, + .priv = 3 | MODE_RAW | MODE_SXGA}, +}; + +static const int hsv_red_x[] = { + 41, 44, 46, 48, 50, 52, 54, 56, + 58, 60, 62, 64, 66, 68, 70, 72, + 74, 76, 78, 80, 81, 83, 85, 87, + 88, 90, 92, 93, 95, 97, 98, 100, + 101, 102, 104, 105, 107, 108, 109, 110, + 112, 113, 114, 115, 116, 117, 118, 119, + 120, 121, 122, 123, 123, 124, 125, 125, + 126, 127, 127, 128, 128, 129, 129, 129, + 130, 130, 130, 130, 131, 131, 131, 131, + 131, 131, 131, 131, 130, 130, 130, 130, + 129, 129, 129, 128, 128, 127, 127, 126, + 125, 125, 124, 123, 122, 122, 121, 120, + 119, 118, 117, 116, 115, 114, 112, 111, + 110, 109, 107, 106, 105, 103, 102, 101, + 99, 98, 96, 94, 93, 91, 90, 88, + 86, 84, 83, 81, 79, 77, 75, 74, + 72, 70, 68, 66, 64, 62, 60, 58, + 56, 54, 52, 49, 47, 45, 43, 41, + 39, 36, 34, 32, 30, 28, 25, 23, + 21, 19, 16, 14, 12, 9, 7, 5, + 3, 0, -1, -3, -6, -8, -10, -12, + -15, -17, -19, -22, -24, -26, -28, -30, + -33, -35, -37, -39, -41, -44, -46, -48, + -50, -52, -54, -56, -58, -60, -62, -64, + -66, -68, -70, -72, -74, -76, -78, -80, + -81, -83, -85, -87, -88, -90, -92, -93, + -95, -97, -98, -100, -101, -102, -104, -105, + -107, -108, -109, -110, -112, -113, -114, -115, + -116, -117, -118, -119, -120, -121, -122, -123, + -123, -124, -125, -125, -126, -127, -127, -128, + -128, -128, -128, -128, -128, -128, -128, -128, + -128, -128, -128, -128, -128, -128, -128, -128, + -128, -128, -128, -128, -128, -128, -128, -128, + -128, -127, -127, -126, -125, -125, -124, -123, + -122, -122, -121, -120, -119, -118, -117, -116, + -115, -114, -112, -111, -110, -109, -107, -106, + -105, -103, -102, -101, -99, -98, -96, -94, + -93, -91, -90, -88, -86, -84, -83, -81, + -79, -77, -75, -74, -72, -70, -68, -66, + -64, -62, -60, -58, -56, -54, -52, -49, + -47, -45, -43, -41, -39, -36, -34, -32, + -30, -28, -25, -23, -21, -19, -16, -14, + -12, -9, -7, -5, -3, 0, 1, 3, + 6, 8, 10, 12, 15, 17, 19, 22, + 24, 26, 28, 30, 33, 35, 37, 39, 41 +}; + +static const int hsv_red_y[] = { + 82, 80, 78, 76, 74, 73, 71, 69, + 67, 65, 63, 61, 58, 56, 54, 52, + 50, 48, 46, 44, 41, 39, 37, 35, + 32, 30, 28, 26, 23, 21, 19, 16, + 14, 12, 10, 7, 5, 3, 0, -1, + -3, -6, -8, -10, -13, -15, -17, -19, + -22, -24, -26, -29, -31, -33, -35, -38, + -40, -42, -44, -46, -48, -51, -53, -55, + -57, -59, -61, -63, -65, -67, -69, -71, + -73, -75, -77, -79, -81, -82, -84, -86, + -88, -89, -91, -93, -94, -96, -98, -99, + -101, -102, -104, -105, -106, -108, -109, -110, + -112, -113, -114, -115, -116, -117, -119, -120, + -120, -121, -122, -123, -124, -125, -126, -126, + -127, -128, -128, -128, -128, -128, -128, -128, + -128, -128, -128, -128, -128, -128, -128, -128, + -128, -128, -128, -128, -128, -128, -128, -128, + -128, -128, -128, -128, -128, -128, -128, -128, + -127, -127, -126, -125, -125, -124, -123, -122, + -121, -120, -119, -118, -117, -116, -115, -114, + -113, -111, -110, -109, -107, -106, -105, -103, + -102, -100, -99, -97, -96, -94, -92, -91, + -89, -87, -85, -84, -82, -80, -78, -76, + -74, -73, -71, -69, -67, -65, -63, -61, + -58, -56, -54, -52, -50, -48, -46, -44, + -41, -39, -37, -35, -32, -30, -28, -26, + -23, -21, -19, -16, -14, -12, -10, -7, + -5, -3, 0, 1, 3, 6, 8, 10, + 13, 15, 17, 19, 22, 24, 26, 29, + 31, 33, 35, 38, 40, 42, 44, 46, + 48, 51, 53, 55, 57, 59, 61, 63, + 65, 67, 69, 71, 73, 75, 77, 79, + 81, 82, 84, 86, 88, 89, 91, 93, + 94, 96, 98, 99, 101, 102, 104, 105, + 106, 108, 109, 110, 112, 113, 114, 115, + 116, 117, 119, 120, 120, 121, 122, 123, + 124, 125, 126, 126, 127, 128, 128, 129, + 129, 130, 130, 131, 131, 131, 131, 132, + 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 131, 131, 131, 130, 130, + 130, 129, 129, 128, 127, 127, 126, 125, + 125, 124, 123, 122, 121, 120, 119, 118, + 117, 116, 115, 114, 113, 111, 110, 109, + 107, 106, 105, 103, 102, 100, 99, 97, + 96, 94, 92, 91, 89, 87, 85, 84, 82 +}; + +static const int hsv_green_x[] = { + -124, -124, -125, -125, -125, -125, -125, -125, + -125, -126, -126, -125, -125, -125, -125, -125, + -125, -124, -124, -124, -123, -123, -122, -122, + -121, -121, -120, -120, -119, -118, -117, -117, + -116, -115, -114, -113, -112, -111, -110, -109, + -108, -107, -105, -104, -103, -102, -100, -99, + -98, -96, -95, -93, -92, -91, -89, -87, + -86, -84, -83, -81, -79, -77, -76, -74, + -72, -70, -69, -67, -65, -63, -61, -59, + -57, -55, -53, -51, -49, -47, -45, -43, + -41, -39, -37, -35, -33, -30, -28, -26, + -24, -22, -20, -18, -15, -13, -11, -9, + -7, -4, -2, 0, 1, 3, 6, 8, + 10, 12, 14, 17, 19, 21, 23, 25, + 27, 29, 32, 34, 36, 38, 40, 42, + 44, 46, 48, 50, 52, 54, 56, 58, + 60, 62, 64, 66, 68, 70, 71, 73, + 75, 77, 78, 80, 82, 83, 85, 87, + 88, 90, 91, 93, 94, 96, 97, 98, + 100, 101, 102, 104, 105, 106, 107, 108, + 109, 111, 112, 113, 113, 114, 115, 116, + 117, 118, 118, 119, 120, 120, 121, 122, + 122, 123, 123, 124, 124, 124, 125, 125, + 125, 125, 125, 125, 125, 126, 126, 125, + 125, 125, 125, 125, 125, 124, 124, 124, + 123, 123, 122, 122, 121, 121, 120, 120, + 119, 118, 117, 117, 116, 115, 114, 113, + 112, 111, 110, 109, 108, 107, 105, 104, + 103, 102, 100, 99, 98, 96, 95, 93, + 92, 91, 89, 87, 86, 84, 83, 81, + 79, 77, 76, 74, 72, 70, 69, 67, + 65, 63, 61, 59, 57, 55, 53, 51, + 49, 47, 45, 43, 41, 39, 37, 35, + 33, 30, 28, 26, 24, 22, 20, 18, + 15, 13, 11, 9, 7, 4, 2, 0, + -1, -3, -6, -8, -10, -12, -14, -17, + -19, -21, -23, -25, -27, -29, -32, -34, + -36, -38, -40, -42, -44, -46, -48, -50, + -52, -54, -56, -58, -60, -62, -64, -66, + -68, -70, -71, -73, -75, -77, -78, -80, + -82, -83, -85, -87, -88, -90, -91, -93, + -94, -96, -97, -98, -100, -101, -102, -104, + -105, -106, -107, -108, -109, -111, -112, -113, + -113, -114, -115, -116, -117, -118, -118, -119, + -120, -120, -121, -122, -122, -123, -123, -124, -124 +}; + +static const int hsv_green_y[] = { + -100, -99, -98, -97, -95, -94, -93, -91, + -90, -89, -87, -86, -84, -83, -81, -80, + -78, -76, -75, -73, -71, -70, -68, -66, + -64, -63, -61, -59, -57, -55, -53, -51, + -49, -48, -46, -44, -42, -40, -38, -36, + -34, -32, -30, -27, -25, -23, -21, -19, + -17, -15, -13, -11, -9, -7, -4, -2, + 0, 1, 3, 5, 7, 9, 11, 14, + 16, 18, 20, 22, 24, 26, 28, 30, + 32, 34, 36, 38, 40, 42, 44, 46, + 48, 50, 52, 54, 56, 58, 59, 61, + 63, 65, 67, 68, 70, 72, 74, 75, + 77, 78, 80, 82, 83, 85, 86, 88, + 89, 90, 92, 93, 95, 96, 97, 98, + 100, 101, 102, 103, 104, 105, 106, 107, + 108, 109, 110, 111, 112, 112, 113, 114, + 115, 115, 116, 116, 117, 117, 118, 118, + 119, 119, 119, 120, 120, 120, 120, 120, + 121, 121, 121, 121, 121, 121, 120, 120, + 120, 120, 120, 119, 119, 119, 118, 118, + 117, 117, 116, 116, 115, 114, 114, 113, + 112, 111, 111, 110, 109, 108, 107, 106, + 105, 104, 103, 102, 100, 99, 98, 97, + 95, 94, 93, 91, 90, 89, 87, 86, + 84, 83, 81, 80, 78, 76, 75, 73, + 71, 70, 68, 66, 64, 63, 61, 59, + 57, 55, 53, 51, 49, 48, 46, 44, + 42, 40, 38, 36, 34, 32, 30, 27, + 25, 23, 21, 19, 17, 15, 13, 11, + 9, 7, 4, 2, 0, -1, -3, -5, + -7, -9, -11, -14, -16, -18, -20, -22, + -24, -26, -28, -30, -32, -34, -36, -38, + -40, -42, -44, -46, -48, -50, -52, -54, + -56, -58, -59, -61, -63, -65, -67, -68, + -70, -72, -74, -75, -77, -78, -80, -82, + -83, -85, -86, -88, -89, -90, -92, -93, + -95, -96, -97, -98, -100, -101, -102, -103, + -104, -105, -106, -107, -108, -109, -110, -111, + -112, -112, -113, -114, -115, -115, -116, -116, + -117, -117, -118, -118, -119, -119, -119, -120, + -120, -120, -120, -120, -121, -121, -121, -121, + -121, -121, -120, -120, -120, -120, -120, -119, + -119, -119, -118, -118, -117, -117, -116, -116, + -115, -114, -114, -113, -112, -111, -111, -110, + -109, -108, -107, -106, -105, -104, -103, -102, -100 +}; + +static const int hsv_blue_x[] = { + 112, 113, 114, 114, 115, 116, 117, 117, + 118, 118, 119, 119, 120, 120, 120, 121, + 121, 121, 122, 122, 122, 122, 122, 122, + 122, 122, 122, 122, 122, 122, 121, 121, + 121, 120, 120, 120, 119, 119, 118, 118, + 117, 116, 116, 115, 114, 113, 113, 112, + 111, 110, 109, 108, 107, 106, 105, 104, + 103, 102, 100, 99, 98, 97, 95, 94, + 93, 91, 90, 88, 87, 85, 84, 82, + 80, 79, 77, 76, 74, 72, 70, 69, + 67, 65, 63, 61, 60, 58, 56, 54, + 52, 50, 48, 46, 44, 42, 40, 38, + 36, 34, 32, 30, 28, 26, 24, 22, + 19, 17, 15, 13, 11, 9, 7, 5, + 2, 0, -1, -3, -5, -7, -9, -12, + -14, -16, -18, -20, -22, -24, -26, -28, + -31, -33, -35, -37, -39, -41, -43, -45, + -47, -49, -51, -53, -54, -56, -58, -60, + -62, -64, -66, -67, -69, -71, -73, -74, + -76, -78, -79, -81, -83, -84, -86, -87, + -89, -90, -92, -93, -94, -96, -97, -98, + -99, -101, -102, -103, -104, -105, -106, -107, + -108, -109, -110, -111, -112, -113, -114, -114, + -115, -116, -117, -117, -118, -118, -119, -119, + -120, -120, -120, -121, -121, -121, -122, -122, + -122, -122, -122, -122, -122, -122, -122, -122, + -122, -122, -121, -121, -121, -120, -120, -120, + -119, -119, -118, -118, -117, -116, -116, -115, + -114, -113, -113, -112, -111, -110, -109, -108, + -107, -106, -105, -104, -103, -102, -100, -99, + -98, -97, -95, -94, -93, -91, -90, -88, + -87, -85, -84, -82, -80, -79, -77, -76, + -74, -72, -70, -69, -67, -65, -63, -61, + -60, -58, -56, -54, -52, -50, -48, -46, + -44, -42, -40, -38, -36, -34, -32, -30, + -28, -26, -24, -22, -19, -17, -15, -13, + -11, -9, -7, -5, -2, 0, 1, 3, + 5, 7, 9, 12, 14, 16, 18, 20, + 22, 24, 26, 28, 31, 33, 35, 37, + 39, 41, 43, 45, 47, 49, 51, 53, + 54, 56, 58, 60, 62, 64, 66, 67, + 69, 71, 73, 74, 76, 78, 79, 81, + 83, 84, 86, 87, 89, 90, 92, 93, + 94, 96, 97, 98, 99, 101, 102, 103, + 104, 105, 106, 107, 108, 109, 110, 111, 112 +}; + +static const int hsv_blue_y[] = { + -11, -13, -15, -17, -19, -21, -23, -25, + -27, -29, -31, -33, -35, -37, -39, -41, + -43, -45, -46, -48, -50, -52, -54, -55, + -57, -59, -61, -62, -64, -66, -67, -69, + -71, -72, -74, -75, -77, -78, -80, -81, + -83, -84, -86, -87, -88, -90, -91, -92, + -93, -95, -96, -97, -98, -99, -100, -101, + -102, -103, -104, -105, -106, -106, -107, -108, + -109, -109, -110, -111, -111, -112, -112, -113, + -113, -114, -114, -114, -115, -115, -115, -115, + -116, -116, -116, -116, -116, -116, -116, -116, + -116, -115, -115, -115, -115, -114, -114, -114, + -113, -113, -112, -112, -111, -111, -110, -110, + -109, -108, -108, -107, -106, -105, -104, -103, + -102, -101, -100, -99, -98, -97, -96, -95, + -94, -93, -91, -90, -89, -88, -86, -85, + -84, -82, -81, -79, -78, -76, -75, -73, + -71, -70, -68, -67, -65, -63, -62, -60, + -58, -56, -55, -53, -51, -49, -47, -45, + -44, -42, -40, -38, -36, -34, -32, -30, + -28, -26, -24, -22, -20, -18, -16, -14, + -12, -10, -8, -6, -4, -2, 0, 1, + 3, 5, 7, 9, 11, 13, 15, 17, + 19, 21, 23, 25, 27, 29, 31, 33, + 35, 37, 39, 41, 43, 45, 46, 48, + 50, 52, 54, 55, 57, 59, 61, 62, + 64, 66, 67, 69, 71, 72, 74, 75, + 77, 78, 80, 81, 83, 84, 86, 87, + 88, 90, 91, 92, 93, 95, 96, 97, + 98, 99, 100, 101, 102, 103, 104, 105, + 106, 106, 107, 108, 109, 109, 110, 111, + 111, 112, 112, 113, 113, 114, 114, 114, + 115, 115, 115, 115, 116, 116, 116, 116, + 116, 116, 116, 116, 116, 115, 115, 115, + 115, 114, 114, 114, 113, 113, 112, 112, + 111, 111, 110, 110, 109, 108, 108, 107, + 106, 105, 104, 103, 102, 101, 100, 99, + 98, 97, 96, 95, 94, 93, 91, 90, + 89, 88, 86, 85, 84, 82, 81, 79, + 78, 76, 75, 73, 71, 70, 68, 67, + 65, 63, 62, 60, 58, 56, 55, 53, + 51, 49, 47, 45, 44, 42, 40, 38, + 36, 34, 32, 30, 28, 26, 24, 22, + 20, 18, 16, 14, 12, 10, 8, 6, + 4, 2, 0, -1, -3, -5, -7, -9, -11 +}; + +static u16 i2c_ident[] = { + V4L2_IDENT_OV9650, + V4L2_IDENT_OV9655, + V4L2_IDENT_SOI968, + V4L2_IDENT_OV7660, + V4L2_IDENT_OV7670, + V4L2_IDENT_MT9V011, + V4L2_IDENT_MT9V111, + V4L2_IDENT_MT9V112, + V4L2_IDENT_MT9M001C12ST, + V4L2_IDENT_MT9M111, + V4L2_IDENT_HV7131R, +}; + +static u16 bridge_init[][2] = { + {0x1000, 0x78}, {0x1001, 0x40}, {0x1002, 0x1c}, + {0x1020, 0x80}, {0x1061, 0x01}, {0x1067, 0x40}, + {0x1068, 0x30}, {0x1069, 0x20}, {0x106a, 0x10}, + {0x106b, 0x08}, {0x1188, 0x87}, {0x11a1, 0x00}, + {0x11a2, 0x00}, {0x11a3, 0x6a}, {0x11a4, 0x50}, + {0x11ab, 0x00}, {0x11ac, 0x00}, {0x11ad, 0x50}, + {0x11ae, 0x3c}, {0x118a, 0x04}, {0x0395, 0x04}, + {0x11b8, 0x3a}, {0x118b, 0x0e}, {0x10f7, 0x05}, + {0x10f8, 0x14}, {0x10fa, 0xff}, {0x10f9, 0x00}, + {0x11ba, 0x0a}, {0x11a5, 0x2d}, {0x11a6, 0x2d}, + {0x11a7, 0x3a}, {0x11a8, 0x05}, {0x11a9, 0x04}, + {0x11aa, 0x3f}, {0x11af, 0x28}, {0x11b0, 0xd8}, + {0x11b1, 0x14}, {0x11b2, 0xec}, {0x11b3, 0x32}, + {0x11b4, 0xdd}, {0x11b5, 0x32}, {0x11b6, 0xdd}, + {0x10e0, 0x2c}, {0x11bc, 0x40}, {0x11bd, 0x01}, + {0x11be, 0xf0}, {0x11bf, 0x00}, {0x118c, 0x1f}, + {0x118d, 0x1f}, {0x118e, 0x1f}, {0x118f, 0x1f}, + {0x1180, 0x01}, {0x1181, 0x00}, {0x1182, 0x01}, + {0x1183, 0x00}, {0x1184, 0x50}, {0x1185, 0x80} +}; + +/* Gain = (bit[3:0] / 16 + 1) * (bit[4] + 1) * (bit[5] + 1) * (bit[6] + 1) */ +static u8 ov_gain[] = { + 0x00 /* 1x */, 0x04 /* 1.25x */, 0x08 /* 1.5x */, 0x0c /* 1.75x */, + 0x10 /* 2x */, 0x12 /* 2.25x */, 0x14 /* 2.5x */, 0x16 /* 2.75x */, + 0x18 /* 3x */, 0x1a /* 3.25x */, 0x1c /* 3.5x */, 0x1e /* 3.75x */, + 0x30 /* 4x */, 0x31 /* 4.25x */, 0x32 /* 4.5x */, 0x33 /* 4.75x */, + 0x34 /* 5x */, 0x35 /* 5.25x */, 0x36 /* 5.5x */, 0x37 /* 5.75x */, + 0x38 /* 6x */, 0x39 /* 6.25x */, 0x3a /* 6.5x */, 0x3b /* 6.75x */, + 0x3c /* 7x */, 0x3d /* 7.25x */, 0x3e /* 7.5x */, 0x3f /* 7.75x */, + 0x70 /* 8x */ +}; + +/* Gain = (bit[8] + 1) * (bit[7] + 1) * (bit[6:0] * 0.03125) */ +static u16 micron1_gain[] = { + /* 1x 1.25x 1.5x 1.75x */ + 0x0020, 0x0028, 0x0030, 0x0038, + /* 2x 2.25x 2.5x 2.75x */ + 0x00a0, 0x00a4, 0x00a8, 0x00ac, + /* 3x 3.25x 3.5x 3.75x */ + 0x00b0, 0x00b4, 0x00b8, 0x00bc, + /* 4x 4.25x 4.5x 4.75x */ + 0x00c0, 0x00c4, 0x00c8, 0x00cc, + /* 5x 5.25x 5.5x 5.75x */ + 0x00d0, 0x00d4, 0x00d8, 0x00dc, + /* 6x 6.25x 6.5x 6.75x */ + 0x00e0, 0x00e4, 0x00e8, 0x00ec, + /* 7x 7.25x 7.5x 7.75x */ + 0x00f0, 0x00f4, 0x00f8, 0x00fc, + /* 8x */ + 0x01c0 +}; + +/* mt9m001 sensor uses a different gain formula then other micron sensors */ +/* Gain = (bit[6] + 1) * (bit[5-0] * 0.125) */ +static u16 micron2_gain[] = { + /* 1x 1.25x 1.5x 1.75x */ + 0x0008, 0x000a, 0x000c, 0x000e, + /* 2x 2.25x 2.5x 2.75x */ + 0x0010, 0x0012, 0x0014, 0x0016, + /* 3x 3.25x 3.5x 3.75x */ + 0x0018, 0x001a, 0x001c, 0x001e, + /* 4x 4.25x 4.5x 4.75x */ + 0x0020, 0x0051, 0x0052, 0x0053, + /* 5x 5.25x 5.5x 5.75x */ + 0x0054, 0x0055, 0x0056, 0x0057, + /* 6x 6.25x 6.5x 6.75x */ + 0x0058, 0x0059, 0x005a, 0x005b, + /* 7x 7.25x 7.5x 7.75x */ + 0x005c, 0x005d, 0x005e, 0x005f, + /* 8x */ + 0x0060 +}; + +/* Gain = .5 + bit[7:0] / 16 */ +static u8 hv7131r_gain[] = { + 0x08 /* 1x */, 0x0c /* 1.25x */, 0x10 /* 1.5x */, 0x14 /* 1.75x */, + 0x18 /* 2x */, 0x1c /* 2.25x */, 0x20 /* 2.5x */, 0x24 /* 2.75x */, + 0x28 /* 3x */, 0x2c /* 3.25x */, 0x30 /* 3.5x */, 0x34 /* 3.75x */, + 0x38 /* 4x */, 0x3c /* 4.25x */, 0x40 /* 4.5x */, 0x44 /* 4.75x */, + 0x48 /* 5x */, 0x4c /* 5.25x */, 0x50 /* 5.5x */, 0x54 /* 5.75x */, + 0x58 /* 6x */, 0x5c /* 6.25x */, 0x60 /* 6.5x */, 0x64 /* 6.75x */, + 0x68 /* 7x */, 0x6c /* 7.25x */, 0x70 /* 7.5x */, 0x74 /* 7.75x */, + 0x78 /* 8x */ +}; + +static u8 soi968_init[][2] = { + {0x12, 0x80}, {0x0c, 0x00}, {0x0f, 0x1f}, + {0x11, 0x80}, {0x38, 0x52}, {0x1e, 0x00}, + {0x33, 0x08}, {0x35, 0x8c}, {0x36, 0x0c}, + {0x37, 0x04}, {0x45, 0x04}, {0x47, 0xff}, + {0x3e, 0x00}, {0x3f, 0x00}, {0x3b, 0x20}, + {0x3a, 0x96}, {0x3d, 0x0a}, {0x14, 0x8e}, + {0x13, 0x8a}, {0x12, 0x40}, {0x17, 0x13}, + {0x18, 0x63}, {0x19, 0x01}, {0x1a, 0x79}, + {0x32, 0x24}, {0x03, 0x00}, {0x11, 0x40}, + {0x2a, 0x10}, {0x2b, 0xe0}, {0x10, 0x32}, + {0x00, 0x00}, {0x01, 0x80}, {0x02, 0x80}, +}; + +static u8 ov7660_init[][2] = { + {0x0e, 0x80}, {0x0d, 0x08}, {0x0f, 0xc3}, + {0x04, 0xc3}, {0x10, 0x40}, {0x11, 0x40}, + {0x12, 0x05}, {0x13, 0xba}, {0x14, 0x2a}, + {0x37, 0x0f}, {0x38, 0x02}, {0x39, 0x43}, + {0x3a, 0x00}, {0x69, 0x90}, {0x2d, 0xf6}, + {0x2e, 0x0b}, {0x01, 0x78}, {0x02, 0x50}, +}; + +static u8 ov7670_init[][2] = { + {0x12, 0x80}, {0x11, 0x80}, {0x3a, 0x04}, {0x12, 0x01}, + {0x32, 0xb6}, {0x03, 0x0a}, {0x0c, 0x00}, {0x3e, 0x00}, + {0x70, 0x3a}, {0x71, 0x35}, {0x72, 0x11}, {0x73, 0xf0}, + {0xa2, 0x02}, {0x13, 0xe0}, {0x00, 0x00}, {0x10, 0x00}, + {0x0d, 0x40}, {0x14, 0x28}, {0xa5, 0x05}, {0xab, 0x07}, + {0x24, 0x95}, {0x25, 0x33}, {0x26, 0xe3}, {0x9f, 0x75}, + {0xa0, 0x65}, {0xa1, 0x0b}, {0xa6, 0xd8}, {0xa7, 0xd8}, + {0xa8, 0xf0}, {0xa9, 0x90}, {0xaa, 0x94}, {0x13, 0xe5}, + {0x0e, 0x61}, {0x0f, 0x4b}, {0x16, 0x02}, {0x1e, 0x27}, + {0x21, 0x02}, {0x22, 0x91}, {0x29, 0x07}, {0x33, 0x0b}, + {0x35, 0x0b}, {0x37, 0x1d}, {0x38, 0x71}, {0x39, 0x2a}, + {0x3c, 0x78}, {0x4d, 0x40}, {0x4e, 0x20}, {0x69, 0x00}, + {0x74, 0x19}, {0x8d, 0x4f}, {0x8e, 0x00}, {0x8f, 0x00}, + {0x90, 0x00}, {0x91, 0x00}, {0x96, 0x00}, {0x9a, 0x80}, + {0xb0, 0x84}, {0xb1, 0x0c}, {0xb2, 0x0e}, {0xb3, 0x82}, + {0xb8, 0x0a}, {0x43, 0x0a}, {0x44, 0xf0}, {0x45, 0x20}, + {0x46, 0x7d}, {0x47, 0x29}, {0x48, 0x4a}, {0x59, 0x8c}, + {0x5a, 0xa5}, {0x5b, 0xde}, {0x5c, 0x96}, {0x5d, 0x66}, + {0x5e, 0x10}, {0x6c, 0x0a}, {0x6d, 0x55}, {0x6e, 0x11}, + {0x6f, 0x9e}, {0x6a, 0x40}, {0x01, 0x40}, {0x02, 0x40}, + {0x13, 0xe7}, {0x4f, 0x6e}, {0x50, 0x70}, {0x51, 0x02}, + {0x52, 0x1d}, {0x53, 0x56}, {0x54, 0x73}, {0x55, 0x0a}, + {0x56, 0x55}, {0x57, 0x80}, {0x58, 0x9e}, {0x41, 0x08}, + {0x3f, 0x02}, {0x75, 0x03}, {0x76, 0x63}, {0x4c, 0x04}, + {0x77, 0x06}, {0x3d, 0x02}, {0x4b, 0x09}, {0xc9, 0x30}, + {0x41, 0x08}, {0x56, 0x48}, {0x34, 0x11}, {0xa4, 0x88}, + {0x96, 0x00}, {0x97, 0x30}, {0x98, 0x20}, {0x99, 0x30}, + {0x9a, 0x84}, {0x9b, 0x29}, {0x9c, 0x03}, {0x9d, 0x99}, + {0x9e, 0x7f}, {0x78, 0x04}, {0x79, 0x01}, {0xc8, 0xf0}, + {0x79, 0x0f}, {0xc8, 0x00}, {0x79, 0x10}, {0xc8, 0x7e}, + {0x79, 0x0a}, {0xc8, 0x80}, {0x79, 0x0b}, {0xc8, 0x01}, + {0x79, 0x0c}, {0xc8, 0x0f}, {0x79, 0x0d}, {0xc8, 0x20}, + {0x79, 0x09}, {0xc8, 0x80}, {0x79, 0x02}, {0xc8, 0xc0}, + {0x79, 0x03}, {0xc8, 0x40}, {0x79, 0x05}, {0xc8, 0x30}, + {0x79, 0x26}, {0x62, 0x20}, {0x63, 0x00}, {0x64, 0x06}, + {0x65, 0x00}, {0x66, 0x05}, {0x94, 0x05}, {0x95, 0x0a}, + {0x17, 0x13}, {0x18, 0x01}, {0x19, 0x02}, {0x1a, 0x7a}, + {0x46, 0x59}, {0x47, 0x30}, {0x58, 0x9a}, {0x59, 0x84}, + {0x5a, 0x91}, {0x5b, 0x57}, {0x5c, 0x75}, {0x5d, 0x6d}, + {0x5e, 0x13}, {0x64, 0x07}, {0x94, 0x07}, {0x95, 0x0d}, + {0xa6, 0xdf}, {0xa7, 0xdf}, {0x48, 0x4d}, {0x51, 0x00}, + {0x6b, 0x0a}, {0x11, 0x80}, {0x2a, 0x00}, {0x2b, 0x00}, + {0x92, 0x00}, {0x93, 0x00}, {0x55, 0x0a}, {0x56, 0x60}, + {0x4f, 0x6e}, {0x50, 0x70}, {0x51, 0x00}, {0x52, 0x1d}, + {0x53, 0x56}, {0x54, 0x73}, {0x58, 0x9a}, {0x4f, 0x6e}, + {0x50, 0x70}, {0x51, 0x00}, {0x52, 0x1d}, {0x53, 0x56}, + {0x54, 0x73}, {0x58, 0x9a}, {0x3f, 0x01}, {0x7b, 0x03}, + {0x7c, 0x09}, {0x7d, 0x16}, {0x7e, 0x38}, {0x7f, 0x47}, + {0x80, 0x53}, {0x81, 0x5e}, {0x82, 0x6a}, {0x83, 0x74}, + {0x84, 0x80}, {0x85, 0x8c}, {0x86, 0x9b}, {0x87, 0xb2}, + {0x88, 0xcc}, {0x89, 0xe5}, {0x7a, 0x24}, {0x3b, 0x00}, + {0x9f, 0x76}, {0xa0, 0x65}, {0x13, 0xe2}, {0x6b, 0x0a}, + {0x11, 0x80}, {0x2a, 0x00}, {0x2b, 0x00}, {0x92, 0x00}, + {0x93, 0x00}, +}; + +static u8 ov9650_init[][2] = { + {0x12, 0x80}, {0x00, 0x00}, {0x01, 0x78}, + {0x02, 0x78}, {0x03, 0x36}, {0x04, 0x03}, + {0x05, 0x00}, {0x06, 0x00}, {0x08, 0x00}, + {0x09, 0x01}, {0x0c, 0x00}, {0x0d, 0x00}, + {0x0e, 0xa0}, {0x0f, 0x52}, {0x10, 0x7c}, + {0x11, 0x80}, {0x12, 0x45}, {0x13, 0xc2}, + {0x14, 0x2e}, {0x15, 0x00}, {0x16, 0x07}, + {0x17, 0x24}, {0x18, 0xc5}, {0x19, 0x00}, + {0x1a, 0x3c}, {0x1b, 0x00}, {0x1e, 0x04}, + {0x1f, 0x00}, {0x24, 0x78}, {0x25, 0x68}, + {0x26, 0xd4}, {0x27, 0x80}, {0x28, 0x80}, + {0x29, 0x30}, {0x2a, 0x00}, {0x2b, 0x00}, + {0x2c, 0x80}, {0x2d, 0x00}, {0x2e, 0x00}, + {0x2f, 0x00}, {0x30, 0x08}, {0x31, 0x30}, + {0x32, 0x84}, {0x33, 0xe2}, {0x34, 0xbf}, + {0x35, 0x81}, {0x36, 0xf9}, {0x37, 0x00}, + {0x38, 0x93}, {0x39, 0x50}, {0x3a, 0x01}, + {0x3b, 0x01}, {0x3c, 0x73}, {0x3d, 0x19}, + {0x3e, 0x0b}, {0x3f, 0x80}, {0x40, 0xc1}, + {0x41, 0x00}, {0x42, 0x08}, {0x67, 0x80}, + {0x68, 0x80}, {0x69, 0x40}, {0x6a, 0x00}, + {0x6b, 0x0a}, {0x8b, 0x06}, {0x8c, 0x20}, + {0x8d, 0x00}, {0x8e, 0x00}, {0x8f, 0xdf}, + {0x92, 0x00}, {0x93, 0x00}, {0x94, 0x88}, + {0x95, 0x88}, {0x96, 0x04}, {0xa1, 0x00}, + {0xa5, 0x80}, {0xa8, 0x80}, {0xa9, 0xb8}, + {0xaa, 0x92}, {0xab, 0x0a}, +}; + +static u8 ov9655_init[][2] = { + {0x12, 0x80}, {0x12, 0x01}, {0x0d, 0x00}, {0x0e, 0x61}, + {0x11, 0x80}, {0x13, 0xba}, {0x14, 0x2e}, {0x16, 0x24}, + {0x1e, 0x04}, {0x1e, 0x04}, {0x1e, 0x04}, {0x27, 0x08}, + {0x28, 0x08}, {0x29, 0x15}, {0x2c, 0x08}, {0x32, 0xbf}, + {0x34, 0x3d}, {0x35, 0x00}, {0x36, 0xf8}, {0x38, 0x12}, + {0x39, 0x57}, {0x3a, 0x00}, {0x3b, 0xcc}, {0x3c, 0x0c}, + {0x3d, 0x19}, {0x3e, 0x0c}, {0x3f, 0x01}, {0x41, 0x40}, + {0x42, 0x80}, {0x45, 0x46}, {0x46, 0x62}, {0x47, 0x2a}, + {0x48, 0x3c}, {0x4a, 0xf0}, {0x4b, 0xdc}, {0x4c, 0xdc}, + {0x4d, 0xdc}, {0x4e, 0xdc}, {0x69, 0x02}, {0x6c, 0x04}, + {0x6f, 0x9e}, {0x70, 0x05}, {0x71, 0x78}, {0x77, 0x02}, + {0x8a, 0x23}, {0x8c, 0x0d}, {0x90, 0x7e}, {0x91, 0x7c}, + {0x9f, 0x6e}, {0xa0, 0x6e}, {0xa5, 0x68}, {0xa6, 0x60}, + {0xa8, 0xc1}, {0xa9, 0xfa}, {0xaa, 0x92}, {0xab, 0x04}, + {0xac, 0x80}, {0xad, 0x80}, {0xae, 0x80}, {0xaf, 0x80}, + {0xb2, 0xf2}, {0xb3, 0x20}, {0xb5, 0x00}, {0xb6, 0xaf}, + {0xbb, 0xae}, {0xbc, 0x44}, {0xbd, 0x44}, {0xbe, 0x3b}, + {0xbf, 0x3a}, {0xc0, 0xe2}, {0xc1, 0xc8}, {0xc2, 0x01}, + {0xc4, 0x00}, {0xc6, 0x85}, {0xc7, 0x81}, {0xc9, 0xe0}, + {0xca, 0xe8}, {0xcc, 0xd8}, {0xcd, 0x93}, {0x12, 0x61}, + {0x36, 0xfa}, {0x8c, 0x8d}, {0xc0, 0xaa}, {0x69, 0x0a}, + {0x03, 0x12}, {0x17, 0x14}, {0x18, 0x00}, {0x19, 0x01}, + {0x1a, 0x3d}, {0x32, 0xbf}, {0x11, 0x80}, {0x2a, 0x10}, + {0x2b, 0x0a}, {0x92, 0x00}, {0x93, 0x00}, {0x1e, 0x04}, + {0x1e, 0x04}, {0x10, 0x7c}, {0x04, 0x03}, {0xa1, 0x00}, + {0x2d, 0x00}, {0x2e, 0x00}, {0x00, 0x00}, {0x01, 0x80}, + {0x02, 0x80}, {0x12, 0x61}, {0x36, 0xfa}, {0x8c, 0x8d}, + {0xc0, 0xaa}, {0x69, 0x0a}, {0x03, 0x12}, {0x17, 0x14}, + {0x18, 0x00}, {0x19, 0x01}, {0x1a, 0x3d}, {0x32, 0xbf}, + {0x11, 0x80}, {0x2a, 0x10}, {0x2b, 0x0a}, {0x92, 0x00}, + {0x93, 0x00}, {0x04, 0x01}, {0x10, 0x1f}, {0xa1, 0x00}, + {0x00, 0x0a}, {0xa1, 0x00}, {0x10, 0x5d}, {0x04, 0x03}, + {0x00, 0x01}, {0xa1, 0x00}, {0x10, 0x7c}, {0x04, 0x03}, + {0x00, 0x03}, {0x00, 0x0a}, {0x00, 0x10}, {0x00, 0x13}, +}; + +static u16 mt9v112_init[][2] = { + {0xf0, 0x0000}, {0x0d, 0x0021}, {0x0d, 0x0020}, + {0x34, 0xc019}, {0x0a, 0x0011}, {0x0b, 0x000b}, + {0x20, 0x0703}, {0x35, 0x2022}, {0xf0, 0x0001}, + {0x05, 0x0000}, {0x06, 0x340c}, {0x3b, 0x042a}, + {0x3c, 0x0400}, {0xf0, 0x0002}, {0x2e, 0x0c58}, + {0x5b, 0x0001}, {0xc8, 0x9f0b}, {0xf0, 0x0001}, + {0x9b, 0x5300}, {0xf0, 0x0000}, {0x2b, 0x0020}, + {0x2c, 0x002a}, {0x2d, 0x0032}, {0x2e, 0x0020}, + {0x09, 0x01dc}, {0x01, 0x000c}, {0x02, 0x0020}, + {0x03, 0x01e0}, {0x04, 0x0280}, {0x06, 0x000c}, + {0x05, 0x0098}, {0x20, 0x0703}, {0x09, 0x01f2}, + {0x2b, 0x00a0}, {0x2c, 0x00a0}, {0x2d, 0x00a0}, + {0x2e, 0x00a0}, {0x01, 0x000c}, {0x02, 0x0020}, + {0x03, 0x01e0}, {0x04, 0x0280}, {0x06, 0x000c}, + {0x05, 0x0098}, {0x09, 0x01c1}, {0x2b, 0x00ae}, + {0x2c, 0x00ae}, {0x2d, 0x00ae}, {0x2e, 0x00ae}, +}; + +static u16 mt9v111_init[][2] = { + {0x01, 0x0004}, {0x0d, 0x0001}, {0x0d, 0x0000}, + {0x01, 0x0001}, {0x02, 0x0016}, {0x03, 0x01e1}, + {0x04, 0x0281}, {0x05, 0x0004}, {0x07, 0x3002}, + {0x21, 0x0000}, {0x25, 0x4024}, {0x26, 0xff03}, + {0x27, 0xff10}, {0x2b, 0x7828}, {0x2c, 0xb43c}, + {0x2d, 0xf0a0}, {0x2e, 0x0c64}, {0x2f, 0x0064}, + {0x67, 0x4010}, {0x06, 0x301e}, {0x08, 0x0480}, + {0x01, 0x0004}, {0x02, 0x0016}, {0x03, 0x01e6}, + {0x04, 0x0286}, {0x05, 0x0004}, {0x06, 0x0000}, + {0x07, 0x3002}, {0x08, 0x0008}, {0x0c, 0x0000}, + {0x0d, 0x0000}, {0x0e, 0x0000}, {0x0f, 0x0000}, + {0x10, 0x0000}, {0x11, 0x0000}, {0x12, 0x00b0}, + {0x13, 0x007c}, {0x14, 0x0000}, {0x15, 0x0000}, + {0x16, 0x0000}, {0x17, 0x0000}, {0x18, 0x0000}, + {0x19, 0x0000}, {0x1a, 0x0000}, {0x1b, 0x0000}, + {0x1c, 0x0000}, {0x1d, 0x0000}, {0x30, 0x0000}, + {0x30, 0x0005}, {0x31, 0x0000}, {0x02, 0x0016}, + {0x03, 0x01e1}, {0x04, 0x0281}, {0x05, 0x0004}, + {0x06, 0x0000}, {0x07, 0x3002}, {0x06, 0x002d}, + {0x05, 0x0004}, {0x09, 0x0064}, {0x2b, 0x00a0}, + {0x2c, 0x00a0}, {0x2d, 0x00a0}, {0x2e, 0x00a0}, + {0x02, 0x0016}, {0x03, 0x01e1}, {0x04, 0x0281}, + {0x05, 0x0004}, {0x06, 0x002d}, {0x07, 0x3002}, + {0x0e, 0x0008}, {0x06, 0x002d}, {0x05, 0x0004}, +}; + +static u16 mt9v011_init[][2] = { + {0x07, 0x0002}, {0x0d, 0x0001}, {0x0d, 0x0000}, + {0x01, 0x0008}, {0x02, 0x0016}, {0x03, 0x01e1}, + {0x04, 0x0281}, {0x05, 0x0083}, {0x06, 0x0006}, + {0x0d, 0x0002}, {0x0a, 0x0000}, {0x0b, 0x0000}, + {0x0c, 0x0000}, {0x0d, 0x0000}, {0x0e, 0x0000}, + {0x0f, 0x0000}, {0x10, 0x0000}, {0x11, 0x0000}, + {0x12, 0x0000}, {0x13, 0x0000}, {0x14, 0x0000}, + {0x15, 0x0000}, {0x16, 0x0000}, {0x17, 0x0000}, + {0x18, 0x0000}, {0x19, 0x0000}, {0x1a, 0x0000}, + {0x1b, 0x0000}, {0x1c, 0x0000}, {0x1d, 0x0000}, + {0x32, 0x0000}, {0x20, 0x1101}, {0x21, 0x0000}, + {0x22, 0x0000}, {0x23, 0x0000}, {0x24, 0x0000}, + {0x25, 0x0000}, {0x26, 0x0000}, {0x27, 0x0024}, + {0x2f, 0xf7b0}, {0x30, 0x0005}, {0x31, 0x0000}, + {0x32, 0x0000}, {0x33, 0x0000}, {0x34, 0x0100}, + {0x3d, 0x068f}, {0x40, 0x01e0}, {0x41, 0x00d1}, + {0x44, 0x0082}, {0x5a, 0x0000}, {0x5b, 0x0000}, + {0x5c, 0x0000}, {0x5d, 0x0000}, {0x5e, 0x0000}, + {0x5f, 0xa31d}, {0x62, 0x0611}, {0x0a, 0x0000}, + {0x06, 0x0029}, {0x05, 0x0009}, {0x20, 0x1101}, + {0x20, 0x1101}, {0x09, 0x0064}, {0x07, 0x0003}, + {0x2b, 0x0033}, {0x2c, 0x00a0}, {0x2d, 0x00a0}, + {0x2e, 0x0033}, {0x07, 0x0002}, {0x06, 0x0000}, + {0x06, 0x0029}, {0x05, 0x0009}, +}; + +static u16 mt9m001_init[][2] = { + {0x0d, 0x0001}, {0x0d, 0x0000}, {0x01, 0x000e}, + {0x02, 0x0014}, {0x03, 0x03c1}, {0x04, 0x0501}, + {0x05, 0x0083}, {0x06, 0x0006}, {0x0d, 0x0002}, + {0x0a, 0x0000}, {0x0c, 0x0000}, {0x11, 0x0000}, + {0x1e, 0x8000}, {0x5f, 0x8904}, {0x60, 0x0000}, + {0x61, 0x0000}, {0x62, 0x0498}, {0x63, 0x0000}, + {0x64, 0x0000}, {0x20, 0x111d}, {0x06, 0x00f2}, + {0x05, 0x0013}, {0x09, 0x10f2}, {0x07, 0x0003}, + {0x2b, 0x002a}, {0x2d, 0x002a}, {0x2c, 0x002a}, + {0x2e, 0x0029}, {0x07, 0x0002}, +}; + +static u16 mt9m111_init[][2] = { + {0xf0, 0x0000}, {0x0d, 0x0008}, {0x0d, 0x0009}, + {0x0d, 0x0008}, {0xf0, 0x0001}, {0x3a, 0x4300}, + {0x9b, 0x4300}, {0xa1, 0x0280}, {0xa4, 0x0200}, + {0x06, 0x308e}, {0xf0, 0x0000}, +}; + +static u8 hv7131r_init[][2] = { + {0x02, 0x08}, {0x02, 0x00}, {0x01, 0x08}, + {0x02, 0x00}, {0x20, 0x00}, {0x21, 0xd0}, + {0x22, 0x00}, {0x23, 0x09}, {0x01, 0x08}, + {0x01, 0x08}, {0x01, 0x08}, {0x25, 0x07}, + {0x26, 0xc3}, {0x27, 0x50}, {0x30, 0x62}, + {0x31, 0x10}, {0x32, 0x06}, {0x33, 0x10}, + {0x20, 0x00}, {0x21, 0xd0}, {0x22, 0x00}, + {0x23, 0x09}, {0x01, 0x08}, +}; + +int reg_r(struct gspca_dev *gspca_dev, u16 reg, u16 length) +{ + struct usb_device *dev = gspca_dev->dev; + int result; + result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), + 0x00, + USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, + reg, + 0x00, + gspca_dev->usb_buf, + length, + 500); + if (unlikely(result < 0 || result != length)) { + err("Read register failed 0x%02X", reg); + return -EIO; + } + return 0; +} + +int reg_w(struct gspca_dev *gspca_dev, u16 reg, const u8 *buffer, int length) +{ + struct usb_device *dev = gspca_dev->dev; + int result; + memcpy(gspca_dev->usb_buf, buffer, length); + result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), + 0x08, + USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, + reg, + 0x00, + gspca_dev->usb_buf, + length, + 500); + if (unlikely(result < 0 || result != length)) { + err("Write register failed index 0x%02X", reg); + return -EIO; + } + return 0; +} + +int reg_w1(struct gspca_dev *gspca_dev, u16 reg, const u8 value) +{ + u8 data[1] = {value}; + return reg_w(gspca_dev, reg, data, 1); +} + +int i2c_w(struct gspca_dev *gspca_dev, const u8 *buffer) +{ + int i; + reg_w(gspca_dev, 0x10c0, buffer, 8); + for (i = 0; i < 5; i++) { + reg_r(gspca_dev, 0x10c0, 1); + if (gspca_dev->usb_buf[0] & 0x04) { + if (gspca_dev->usb_buf[0] & 0x08) + return -1; + return 0; + } + msleep(1); + } + return -1; +} + +int i2c_w1(struct gspca_dev *gspca_dev, u8 reg, u8 val) +{ + struct sd *sd = (struct sd *) gspca_dev; + + u8 row[8]; + + /* + * from the point of view of the bridge, the length + * includes the address + */ + row[0] = 0x81 | (2 << 4); + row[1] = sd->i2c_addr; + row[2] = reg; + row[3] = val; + row[4] = 0x00; + row[5] = 0x00; + row[6] = 0x00; + row[7] = 0x10; + + return i2c_w(gspca_dev, row); +} + +int i2c_w2(struct gspca_dev *gspca_dev, u8 reg, u16 val) +{ + struct sd *sd = (struct sd *) gspca_dev; + u8 row[8]; + + /* + * from the point of view of the bridge, the length + * includes the address + */ + row[0] = 0x81 | (3 << 4); + row[1] = sd->i2c_addr; + row[2] = reg; + row[3] = (val >> 8) & 0xff; + row[4] = val & 0xff; + row[5] = 0x00; + row[6] = 0x00; + row[7] = 0x10; + + return i2c_w(gspca_dev, row); +} + +int i2c_r1(struct gspca_dev *gspca_dev, u8 reg, u8 *val) +{ + struct sd *sd = (struct sd *) gspca_dev; + u8 row[8]; + + row[0] = 0x81 | 0x10; + row[1] = sd->i2c_addr; + row[2] = reg; + row[3] = 0; + row[4] = 0; + row[5] = 0; + row[6] = 0; + row[7] = 0x10; + reg_w(gspca_dev, 0x10c0, row, 8); + msleep(1); + row[0] = 0x81 | (2 << 4) | 0x02; + row[2] = 0; + reg_w(gspca_dev, 0x10c0, row, 8); + msleep(1); + reg_r(gspca_dev, 0x10c2, 5); + *val = gspca_dev->usb_buf[3]; + return 0; +} + +int i2c_r2(struct gspca_dev *gspca_dev, u8 reg, u16 *val) +{ + struct sd *sd = (struct sd *) gspca_dev; + u8 row[8]; + + row[0] = 0x81 | 0x10; + row[1] = sd->i2c_addr; + row[2] = reg; + row[3] = 0; + row[4] = 0; + row[5] = 0; + row[6] = 0; + row[7] = 0x10; + reg_w(gspca_dev, 0x10c0, row, 8); + msleep(1); + row[0] = 0x81 | (3 << 4) | 0x02; + row[2] = 0; + reg_w(gspca_dev, 0x10c0, row, 8); + msleep(1); + reg_r(gspca_dev, 0x10c2, 5); + *val = (gspca_dev->usb_buf[2] << 8) | gspca_dev->usb_buf[3]; + return 0; +} + +static int ov9650_init_sensor(struct gspca_dev *gspca_dev) +{ + int i; + struct sd *sd = (struct sd *) gspca_dev; + + for (i = 0; i < ARRAY_SIZE(ov9650_init); i++) { + if (i2c_w1(gspca_dev, ov9650_init[i][0], + ov9650_init[i][1]) < 0) { + err("OV9650 sensor initialization failed"); + return -ENODEV; + } + } + sd->hstart = 1; + sd->vstart = 7; + return 0; +} + +static int ov9655_init_sensor(struct gspca_dev *gspca_dev) +{ + int i; + struct sd *sd = (struct sd *) gspca_dev; + + for (i = 0; i < ARRAY_SIZE(ov9655_init); i++) { + if (i2c_w1(gspca_dev, ov9655_init[i][0], + ov9655_init[i][1]) < 0) { + err("OV9655 sensor initialization failed"); + return -ENODEV; + } + } + /* disable hflip and vflip */ + gspca_dev->ctrl_dis = (1 << HFLIP_IDX) | (1 << VFLIP_IDX); + sd->hstart = 0; + sd->vstart = 7; + return 0; +} + +static int soi968_init_sensor(struct gspca_dev *gspca_dev) +{ + int i; + struct sd *sd = (struct sd *) gspca_dev; + + for (i = 0; i < ARRAY_SIZE(soi968_init); i++) { + if (i2c_w1(gspca_dev, soi968_init[i][0], + soi968_init[i][1]) < 0) { + err("SOI968 sensor initialization failed"); + return -ENODEV; + } + } + /* disable hflip and vflip */ + gspca_dev->ctrl_dis = (1 << HFLIP_IDX) | (1 << VFLIP_IDX); + sd->hstart = 60; + sd->vstart = 11; + return 0; +} + +static int ov7660_init_sensor(struct gspca_dev *gspca_dev) +{ + int i; + struct sd *sd = (struct sd *) gspca_dev; + + for (i = 0; i < ARRAY_SIZE(ov7660_init); i++) { + if (i2c_w1(gspca_dev, ov7660_init[i][0], + ov7660_init[i][1]) < 0) { + err("OV7660 sensor initialization failed"); + return -ENODEV; + } + } + /* disable hflip and vflip */ + gspca_dev->ctrl_dis = (1 << HFLIP_IDX) | (1 << VFLIP_IDX); + sd->hstart = 1; + sd->vstart = 1; + return 0; +} + +static int ov7670_init_sensor(struct gspca_dev *gspca_dev) +{ + int i; + struct sd *sd = (struct sd *) gspca_dev; + + for (i = 0; i < ARRAY_SIZE(ov7670_init); i++) { + if (i2c_w1(gspca_dev, ov7670_init[i][0], + ov7670_init[i][1]) < 0) { + err("OV7670 sensor initialization failed"); + return -ENODEV; + } + } + /* disable hflip and vflip */ + gspca_dev->ctrl_dis = (1 << HFLIP_IDX) | (1 << VFLIP_IDX); + sd->hstart = 0; + sd->vstart = 1; + return 0; +} + +static int mt9v_init_sensor(struct gspca_dev *gspca_dev) +{ + struct sd *sd = (struct sd *) gspca_dev; + int i; + u16 value; + int ret; + + sd->i2c_addr = 0x5d; + ret = i2c_r2(gspca_dev, 0xff, &value); + if ((ret == 0) && (value == 0x8243)) { + for (i = 0; i < ARRAY_SIZE(mt9v011_init); i++) { + if (i2c_w2(gspca_dev, mt9v011_init[i][0], + mt9v011_init[i][1]) < 0) { + err("MT9V011 sensor initialization failed"); + return -ENODEV; + } + } + sd->hstart = 2; + sd->vstart = 2; + sd->sensor = SENSOR_MT9V011; + info("MT9V011 sensor detected"); + return 0; + } + + sd->i2c_addr = 0x5c; + i2c_w2(gspca_dev, 0x01, 0x0004); + ret = i2c_r2(gspca_dev, 0xff, &value); + if ((ret == 0) && (value == 0x823a)) { + for (i = 0; i < ARRAY_SIZE(mt9v111_init); i++) { + if (i2c_w2(gspca_dev, mt9v111_init[i][0], + mt9v111_init[i][1]) < 0) { + err("MT9V111 sensor initialization failed"); + return -ENODEV; + } + } + sd->hstart = 2; + sd->vstart = 2; + sd->sensor = SENSOR_MT9V111; + info("MT9V111 sensor detected"); + return 0; + } + + sd->i2c_addr = 0x5d; + ret = i2c_w2(gspca_dev, 0xf0, 0x0000); + if (ret < 0) { + sd->i2c_addr = 0x48; + i2c_w2(gspca_dev, 0xf0, 0x0000); + } + ret = i2c_r2(gspca_dev, 0x00, &value); + if ((ret == 0) && (value == 0x1229)) { + for (i = 0; i < ARRAY_SIZE(mt9v112_init); i++) { + if (i2c_w2(gspca_dev, mt9v112_init[i][0], + mt9v112_init[i][1]) < 0) { + err("MT9V112 sensor initialization failed"); + return -ENODEV; + } + } + sd->hstart = 6; + sd->vstart = 2; + sd->sensor = SENSOR_MT9V112; + info("MT9V112 sensor detected"); + return 0; + } + + return -ENODEV; +} + +static int mt9m111_init_sensor(struct gspca_dev *gspca_dev) +{ + struct sd *sd = (struct sd *) gspca_dev; + int i; + for (i = 0; i < ARRAY_SIZE(mt9m111_init); i++) { + if (i2c_w2(gspca_dev, mt9m111_init[i][0], + mt9m111_init[i][1]) < 0) { + err("MT9M111 sensor initialization failed"); + return -ENODEV; + } + } + sd->hstart = 0; + sd->vstart = 2; + return 0; +} + +static int mt9m001_init_sensor(struct gspca_dev *gspca_dev) +{ + struct sd *sd = (struct sd *) gspca_dev; + int i; + for (i = 0; i < ARRAY_SIZE(mt9m001_init); i++) { + if (i2c_w2(gspca_dev, mt9m001_init[i][0], + mt9m001_init[i][1]) < 0) { + err("MT9M001 sensor initialization failed"); + return -ENODEV; + } + } + /* disable hflip and vflip */ + gspca_dev->ctrl_dis = (1 << HFLIP_IDX) | (1 << VFLIP_IDX); + sd->hstart = 2; + sd->vstart = 2; + return 0; +} + +static int hv7131r_init_sensor(struct gspca_dev *gspca_dev) +{ + int i; + struct sd *sd = (struct sd *) gspca_dev; + + for (i = 0; i < ARRAY_SIZE(hv7131r_init); i++) { + if (i2c_w1(gspca_dev, hv7131r_init[i][0], + hv7131r_init[i][1]) < 0) { + err("HV7131R Sensor initialization failed"); + return -ENODEV; + } + } + sd->hstart = 0; + sd->vstart = 1; + return 0; +} + +#ifdef CONFIG_USB_GSPCA_SN9C20X_EVDEV +static int input_kthread(void *data) +{ + struct gspca_dev *gspca_dev = (struct gspca_dev *)data; + struct sd *sd = (struct sd *) gspca_dev; + + DECLARE_WAIT_QUEUE_HEAD(wait); + set_freezable(); + for (;;) { + if (kthread_should_stop()) + break; + + if (reg_r(gspca_dev, 0x1005, 1) < 0) + continue; + + input_report_key(sd->input_dev, + KEY_CAMERA, + gspca_dev->usb_buf[0] & sd->input_gpio); + input_sync(sd->input_dev); + + wait_event_freezable_timeout(wait, + kthread_should_stop(), + msecs_to_jiffies(100)); + } + return 0; +} + + +static int sn9c20x_input_init(struct gspca_dev *gspca_dev) +{ + struct sd *sd = (struct sd *) gspca_dev; + if (sd->input_gpio == 0) + return 0; + + sd->input_dev = input_allocate_device(); + if (!sd->input_dev) + return -ENOMEM; + + sd->input_dev->name = "SN9C20X Webcam"; + + sd->input_dev->phys = kasprintf(GFP_KERNEL, "usb-%s-%s", + gspca_dev->dev->bus->bus_name, + gspca_dev->dev->devpath); + + if (!sd->input_dev->phys) + return -ENOMEM; + + usb_to_input_id(gspca_dev->dev, &sd->input_dev->id); + sd->input_dev->dev.parent = &gspca_dev->dev->dev; + + set_bit(EV_KEY, sd->input_dev->evbit); + set_bit(KEY_CAMERA, sd->input_dev->keybit); + + if (input_register_device(sd->input_dev)) + return -EINVAL; + + sd->input_task = kthread_run(input_kthread, gspca_dev, "sn9c20x/%d", + gspca_dev->vdev.minor); + + if (IS_ERR(sd->input_task)) + return -EINVAL; + + return 0; +} + +static void sn9c20x_input_cleanup(struct gspca_dev *gspca_dev) +{ + struct sd *sd = (struct sd *) gspca_dev; + if (sd->input_task != NULL && !IS_ERR(sd->input_task)) + kthread_stop(sd->input_task); + + if (sd->input_dev != NULL) { + input_unregister_device(sd->input_dev); + kfree(sd->input_dev->phys); + input_free_device(sd->input_dev); + sd->input_dev = NULL; + } +} +#endif + +static int set_cmatrix(struct gspca_dev *gspca_dev) +{ + struct sd *sd = (struct sd *) gspca_dev; + s32 hue_coord, hue_index = 180 + sd->hue; + u8 cmatrix[21]; + memset(cmatrix, 0, 21); + + cmatrix[2] = (sd->contrast * 0x25 / 0x100) + 0x26; + cmatrix[0] = 0x13 + (cmatrix[2] - 0x26) * 0x13 / 0x25; + cmatrix[4] = 0x07 + (cmatrix[2] - 0x26) * 0x07 / 0x25; + cmatrix[18] = sd->brightness - 0x80; + + hue_coord = (hsv_red_x[hue_index] * sd->saturation) >> 8; + cmatrix[6] = (unsigned char)(hue_coord & 0xff); + cmatrix[7] = (unsigned char)((hue_coord >> 8) & 0x0f); + + hue_coord = (hsv_red_y[hue_index] * sd->saturation) >> 8; + cmatrix[8] = (unsigned char)(hue_coord & 0xff); + cmatrix[9] = (unsigned char)((hue_coord >> 8) & 0x0f); + + hue_coord = (hsv_green_x[hue_index] * sd->saturation) >> 8; + cmatrix[10] = (unsigned char)(hue_coord & 0xff); + cmatrix[11] = (unsigned char)((hue_coord >> 8) & 0x0f); + + hue_coord = (hsv_green_y[hue_index] * sd->saturation) >> 8; + cmatrix[12] = (unsigned char)(hue_coord & 0xff); + cmatrix[13] = (unsigned char)((hue_coord >> 8) & 0x0f); + + hue_coord = (hsv_blue_x[hue_index] * sd->saturation) >> 8; + cmatrix[14] = (unsigned char)(hue_coord & 0xff); + cmatrix[15] = (unsigned char)((hue_coord >> 8) & 0x0f); + + hue_coord = (hsv_blue_y[hue_index] * sd->saturation) >> 8; + cmatrix[16] = (unsigned char)(hue_coord & 0xff); + cmatrix[17] = (unsigned char)((hue_coord >> 8) & 0x0f); + + return reg_w(gspca_dev, 0x10e1, cmatrix, 21); +} + +static int set_gamma(struct gspca_dev *gspca_dev) +{ + struct sd *sd = (struct sd *) gspca_dev; + u8 gamma[17]; + u8 gval = sd->gamma * 0xb8 / 0x100; + + + gamma[0] = 0x0a; + gamma[1] = 0x13 + (gval * (0xcb - 0x13) / 0xb8); + gamma[2] = 0x25 + (gval * (0xee - 0x25) / 0xb8); + gamma[3] = 0x37 + (gval * (0xfa - 0x37) / 0xb8); + gamma[4] = 0x45 + (gval * (0xfc - 0x45) / 0xb8); + gamma[5] = 0x55 + (gval * (0xfb - 0x55) / 0xb8); + gamma[6] = 0x65 + (gval * (0xfc - 0x65) / 0xb8); + gamma[7] = 0x74 + (gval * (0xfd - 0x74) / 0xb8); + gamma[8] = 0x83 + (gval * (0xfe - 0x83) / 0xb8); + gamma[9] = 0x92 + (gval * (0xfc - 0x92) / 0xb8); + gamma[10] = 0xa1 + (gval * (0xfc - 0xa1) / 0xb8); + gamma[11] = 0xb0 + (gval * (0xfc - 0xb0) / 0xb8); + gamma[12] = 0xbf + (gval * (0xfb - 0xbf) / 0xb8); + gamma[13] = 0xce + (gval * (0xfb - 0xce) / 0xb8); + gamma[14] = 0xdf + (gval * (0xfd - 0xdf) / 0xb8); + gamma[15] = 0xea + (gval * (0xf9 - 0xea) / 0xb8); + gamma[16] = 0xf5; + + return reg_w(gspca_dev, 0x1190, gamma, 17); +} + +static int set_redblue(struct gspca_dev *gspca_dev) +{ + struct sd *sd = (struct sd *) gspca_dev; + reg_w1(gspca_dev, 0x118c, sd->red); + reg_w1(gspca_dev, 0x118f, sd->blue); + return 0; +} + +static int set_hvflip(struct gspca_dev *gspca_dev) +{ + u8 value, tslb; + u16 value2; + struct sd *sd = (struct sd *) gspca_dev; + switch (sd->sensor) { + case SENSOR_OV9650: + i2c_r1(gspca_dev, 0x1e, &value); + value &= ~0x30; + tslb = 0x01; + if (sd->hflip) + value |= 0x20; + if (sd->vflip) { + value |= 0x10; + tslb = 0x49; + } + i2c_w1(gspca_dev, 0x1e, value); + i2c_w1(gspca_dev, 0x3a, tslb); + break; + case SENSOR_MT9V111: + case SENSOR_MT9V011: + i2c_r2(gspca_dev, 0x20, &value2); + value2 &= ~0xc0a0; + if (sd->hflip) + value2 |= 0x8080; + if (sd->vflip) + value2 |= 0x4020; + i2c_w2(gspca_dev, 0x20, value2); + break; + case SENSOR_MT9M111: + case SENSOR_MT9V112: + i2c_r2(gspca_dev, 0x20, &value2); + value2 &= ~0x0003; + if (sd->hflip) + value2 |= 0x0002; + if (sd->vflip) + value2 |= 0x0001; + i2c_w2(gspca_dev, 0x20, value2); + break; + case SENSOR_HV7131R: + i2c_r1(gspca_dev, 0x01, &value); + value &= ~0x03; + if (sd->vflip) + value |= 0x01; + if (sd->hflip) + value |= 0x02; + i2c_w1(gspca_dev, 0x01, value); + break; + } + return 0; +} + +static int set_exposure(struct gspca_dev *gspca_dev) +{ + struct sd *sd = (struct sd *) gspca_dev; + u8 exp[8] = {0x81, sd->i2c_addr, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e}; + switch (sd->sensor) { + case SENSOR_OV7660: + case SENSOR_OV7670: + case SENSOR_SOI968: + case SENSOR_OV9655: + case SENSOR_OV9650: + exp[0] |= (3 << 4); + exp[2] = 0x2d; + exp[3] = sd->exposure & 0xff; + exp[4] = sd->exposure >> 8; + break; + case SENSOR_MT9M001: + case SENSOR_MT9M111: + case SENSOR_MT9V112: + case SENSOR_MT9V111: + case SENSOR_MT9V011: + exp[0] |= (3 << 4); + exp[2] = 0x09; + exp[3] = sd->exposure >> 8; + exp[4] = sd->exposure & 0xff; + break; + case SENSOR_HV7131R: + exp[0] |= (4 << 4); + exp[2] = 0x25; + exp[3] = ((sd->exposure * 0xffffff) / 0xffff) >> 16; + exp[4] = ((sd->exposure * 0xffffff) / 0xffff) >> 8; + exp[5] = ((sd->exposure * 0xffffff) / 0xffff) & 0xff; + break; + } + i2c_w(gspca_dev, exp); + return 0; +} + +static int set_gain(struct gspca_dev *gspca_dev) +{ + struct sd *sd = (struct sd *) gspca_dev; + u8 gain[8] = {0x81, sd->i2c_addr, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1d}; + switch (sd->sensor) { + case SENSOR_OV7660: + case SENSOR_OV7670: + case SENSOR_SOI968: + case SENSOR_OV9655: + case SENSOR_OV9650: + gain[0] |= (2 << 4); + gain[3] = ov_gain[sd->gain]; + break; + case SENSOR_MT9V011: + case SENSOR_MT9V111: + gain[0] |= (3 << 4); + gain[2] = 0x35; + gain[3] = micron1_gain[sd->gain] >> 8; + gain[4] = micron1_gain[sd->gain] & 0xff; + break; + case SENSOR_MT9V112: + case SENSOR_MT9M111: + gain[0] |= (3 << 4); + gain[2] = 0x2f; + gain[3] = micron1_gain[sd->gain] >> 8; + gain[4] = micron1_gain[sd->gain] & 0xff; + break; + case SENSOR_MT9M001: + gain[0] |= (3 << 4); + gain[2] = 0x2f; + gain[3] = micron2_gain[sd->gain] >> 8; + gain[4] = micron2_gain[sd->gain] & 0xff; + break; + case SENSOR_HV7131R: + gain[0] |= (2 << 4); + gain[2] = 0x30; + gain[3] = hv7131r_gain[sd->gain]; + break; + } + i2c_w(gspca_dev, gain); + return 0; +} + +static int sd_setbrightness(struct gspca_dev *gspca_dev, s32 val) +{ + struct sd *sd = (struct sd *) gspca_dev; + + sd->brightness = val; + if (gspca_dev->streaming) + return set_cmatrix(gspca_dev); + return 0; +} + +static int sd_getbrightness(struct gspca_dev *gspca_dev, s32 *val) +{ + struct sd *sd = (struct sd *) gspca_dev; + *val = sd->brightness; + return 0; +} + + +static int sd_setcontrast(struct gspca_dev *gspca_dev, s32 val) +{ + struct sd *sd = (struct sd *) gspca_dev; + + sd->contrast = val; + if (gspca_dev->streaming) + return set_cmatrix(gspca_dev); + return 0; +} + +static int sd_getcontrast(struct gspca_dev *gspca_dev, s32 *val) +{ + struct sd *sd = (struct sd *) gspca_dev; + *val = sd->contrast; + return 0; +} + +static int sd_setsaturation(struct gspca_dev *gspca_dev, s32 val) +{ + struct sd *sd = (struct sd *) gspca_dev; + + sd->saturation = val; + if (gspca_dev->streaming) + return set_cmatrix(gspca_dev); + return 0; +} + +static int sd_getsaturation(struct gspca_dev *gspca_dev, s32 *val) +{ + struct sd *sd = (struct sd *) gspca_dev; + *val = sd->saturation; + return 0; +} + +static int sd_sethue(struct gspca_dev *gspca_dev, s32 val) +{ + struct sd *sd = (struct sd *) gspca_dev; + + sd->hue = val; + if (gspca_dev->streaming) + return set_cmatrix(gspca_dev); + return 0; +} + +static int sd_gethue(struct gspca_dev *gspca_dev, s32 *val) +{ + struct sd *sd = (struct sd *) gspca_dev; + *val = sd->hue; + return 0; +} + +static int sd_setgamma(struct gspca_dev *gspca_dev, s32 val) +{ + struct sd *sd = (struct sd *) gspca_dev; + + sd->gamma = val; + if (gspca_dev->streaming) + return set_gamma(gspca_dev); + return 0; +} + +static int sd_getgamma(struct gspca_dev *gspca_dev, s32 *val) +{ + struct sd *sd = (struct sd *) gspca_dev; + *val = sd->gamma; + return 0; +} + +static int sd_setredbalance(struct gspca_dev *gspca_dev, s32 val) +{ + struct sd *sd = (struct sd *) gspca_dev; + + sd->red = val; + if (gspca_dev->streaming) + return set_redblue(gspca_dev); + return 0; +} + +static int sd_getredbalance(struct gspca_dev *gspca_dev, s32 *val) +{ + struct sd *sd = (struct sd *) gspca_dev; + *val = sd->red; + return 0; +} + +static int sd_setbluebalance(struct gspca_dev *gspca_dev, s32 val) +{ + struct sd *sd = (struct sd *) gspca_dev; + + sd->blue = val; + if (gspca_dev->streaming) + return set_redblue(gspca_dev); + return 0; +} + +static int sd_getbluebalance(struct gspca_dev *gspca_dev, s32 *val) +{ + struct sd *sd = (struct sd *) gspca_dev; + *val = sd->blue; + return 0; +} + +static int sd_sethflip(struct gspca_dev *gspca_dev, s32 val) +{ + struct sd *sd = (struct sd *) gspca_dev; + + sd->hflip = val; + if (gspca_dev->streaming) + return set_hvflip(gspca_dev); + return 0; +} + +static int sd_gethflip(struct gspca_dev *gspca_dev, s32 *val) +{ + struct sd *sd = (struct sd *) gspca_dev; + *val = sd->hflip; + return 0; +} + +static int sd_setvflip(struct gspca_dev *gspca_dev, s32 val) +{ + struct sd *sd = (struct sd *) gspca_dev; + + sd->vflip = val; + if (gspca_dev->streaming) + return set_hvflip(gspca_dev); + return 0; +} + +static int sd_getvflip(struct gspca_dev *gspca_dev, s32 *val) +{ + struct sd *sd = (struct sd *) gspca_dev; + *val = sd->vflip; + return 0; +} + +static int sd_setexposure(struct gspca_dev *gspca_dev, s32 val) +{ + struct sd *sd = (struct sd *) gspca_dev; + + sd->exposure = val; + if (gspca_dev->streaming) + return set_exposure(gspca_dev); + return 0; +} + +static int sd_getexposure(struct gspca_dev *gspca_dev, s32 *val) +{ + struct sd *sd = (struct sd *) gspca_dev; + *val = sd->exposure; + return 0; +} + +static int sd_setgain(struct gspca_dev *gspca_dev, s32 val) +{ + struct sd *sd = (struct sd *) gspca_dev; + + sd->gain = val; + if (gspca_dev->streaming) + return set_gain(gspca_dev); + return 0; +} + +static int sd_getgain(struct gspca_dev *gspca_dev, s32 *val) +{ + struct sd *sd = (struct sd *) gspca_dev; + *val = sd->gain; + return 0; +} + +static int sd_setautoexposure(struct gspca_dev *gspca_dev, s32 val) +{ + struct sd *sd = (struct sd *) gspca_dev; + sd->auto_exposure = val; + return 0; +} + +static int sd_getautoexposure(struct gspca_dev *gspca_dev, s32 *val) +{ + struct sd *sd = (struct sd *) gspca_dev; + *val = sd->auto_exposure; + return 0; +} + +#ifdef CONFIG_VIDEO_ADV_DEBUG +static int sd_dbg_g_register(struct gspca_dev *gspca_dev, + struct v4l2_dbg_register *reg) +{ + struct sd *sd = (struct sd *) gspca_dev; + switch (reg->match.type) { + case V4L2_CHIP_MATCH_HOST: + if (reg->match.addr != 0) + return -EINVAL; + if (reg->reg < 0x1000 || reg->reg > 0x11ff) + return -EINVAL; + if (reg_r(gspca_dev, reg->reg, 1) < 0) + return -EINVAL; + reg->val = gspca_dev->usb_buf[0]; + return 0; + case V4L2_CHIP_MATCH_I2C_ADDR: + if (reg->match.addr != sd->i2c_addr) + return -EINVAL; + if (sd->sensor >= SENSOR_MT9V011 && + sd->sensor <= SENSOR_MT9M111) { + if (i2c_r2(gspca_dev, reg->reg, (u16 *)®->val) < 0) + return -EINVAL; + } else { + if (i2c_r1(gspca_dev, reg->reg, (u8 *)®->val) < 0) + return -EINVAL; + } + return 0; + } + return -EINVAL; +} + +static int sd_dbg_s_register(struct gspca_dev *gspca_dev, + struct v4l2_dbg_register *reg) +{ + struct sd *sd = (struct sd *) gspca_dev; + switch (reg->match.type) { + case V4L2_CHIP_MATCH_HOST: + if (reg->match.addr != 0) + return -EINVAL; + if (reg->reg < 0x1000 || reg->reg > 0x11ff) + return -EINVAL; + if (reg_w1(gspca_dev, reg->reg, reg->val) < 0) + return -EINVAL; + return 0; + case V4L2_CHIP_MATCH_I2C_ADDR: + if (reg->match.addr != sd->i2c_addr) + return -EINVAL; + if (sd->sensor >= SENSOR_MT9V011 && + sd->sensor <= SENSOR_MT9M111) { + if (i2c_w2(gspca_dev, reg->reg, reg->val) < 0) + return -EINVAL; + } else { + if (i2c_w1(gspca_dev, reg->reg, reg->val) < 0) + return -EINVAL; + } + return 0; + } + return -EINVAL; +} +#endif + +static int sd_chip_ident(struct gspca_dev *gspca_dev, + struct v4l2_dbg_chip_ident *chip) +{ + struct sd *sd = (struct sd *) gspca_dev; + + switch (chip->match.type) { + case V4L2_CHIP_MATCH_HOST: + if (chip->match.addr != 0) + return -EINVAL; + chip->revision = 0; + chip->ident = V4L2_IDENT_SN9C20X; + return 0; + case V4L2_CHIP_MATCH_I2C_ADDR: + if (chip->match.addr != sd->i2c_addr) + return -EINVAL; + chip->revision = 0; + chip->ident = i2c_ident[sd->sensor]; + return 0; + } + return -EINVAL; +} + +static int sd_config(struct gspca_dev *gspca_dev, + const struct usb_device_id *id) +{ + struct sd *sd = (struct sd *) gspca_dev; + struct cam *cam; + + cam = &gspca_dev->cam; + + sd->sensor = (id->driver_info >> 8) & 0xff; + sd->i2c_addr = id->driver_info & 0xff; + + switch (sd->sensor) { + case SENSOR_OV9650: + cam->cam_mode = sxga_mode; + cam->nmodes = ARRAY_SIZE(sxga_mode); + break; + default: + cam->cam_mode = vga_mode; + cam->nmodes = ARRAY_SIZE(vga_mode); + } + + sd->old_step = 0; + sd->older_step = 0; + sd->exposure_step = 16; + + sd->brightness = BRIGHTNESS_DEFAULT; + sd->contrast = CONTRAST_DEFAULT; + sd->saturation = SATURATION_DEFAULT; + sd->hue = HUE_DEFAULT; + sd->gamma = GAMMA_DEFAULT; + sd->red = RED_DEFAULT; + sd->blue = BLUE_DEFAULT; + + sd->hflip = HFLIP_DEFAULT; + sd->vflip = VFLIP_DEFAULT; + sd->exposure = EXPOSURE_DEFAULT; + sd->gain = GAIN_DEFAULT; + sd->auto_exposure = AUTO_EXPOSURE_DEFAULT; + + sd->quality = 95; + +#ifdef CONFIG_USB_GSPCA_SN9C20X_EVDEV + sd->input_gpio = (id->driver_info >> 16) & 0xff; + if (sn9c20x_input_init(gspca_dev) < 0) + return -ENODEV; +#endif + return 0; +} + +static int sd_init(struct gspca_dev *gspca_dev) +{ + struct sd *sd = (struct sd *) gspca_dev; + int i; + u8 value; + u8 i2c_init[9] = + {0x80, sd->i2c_addr, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03}; + + for (i = 0; i < ARRAY_SIZE(bridge_init); i++) { + value = bridge_init[i][1]; + if (reg_w(gspca_dev, bridge_init[i][0], &value, 1) < 0) { + err("Device initialization failed"); + return -ENODEV; + } + } + + if (reg_w(gspca_dev, 0x10c0, i2c_init, 9) < 0) { + err("Device initialization failed"); + return -ENODEV; + } + + switch (sd->sensor) { + case SENSOR_OV9650: + if (ov9650_init_sensor(gspca_dev) < 0) + return -ENODEV; + info("OV9650 sensor detected"); + break; + case SENSOR_OV9655: + if (ov9655_init_sensor(gspca_dev) < 0) + return -ENODEV; + info("OV9655 sensor detected"); + break; + case SENSOR_SOI968: + if (soi968_init_sensor(gspca_dev) < 0) + return -ENODEV; + info("SOI968 sensor detected"); + break; + case SENSOR_OV7660: + if (ov7660_init_sensor(gspca_dev) < 0) + return -ENODEV; + info("OV7660 sensor detected"); + break; + case SENSOR_OV7670: + if (ov7670_init_sensor(gspca_dev) < 0) + return -ENODEV; + info("OV7670 sensor detected"); + break; + case SENSOR_MT9VPRB: + if (mt9v_init_sensor(gspca_dev) < 0) + return -ENODEV; + break; + case SENSOR_MT9M111: + if (mt9m111_init_sensor(gspca_dev) < 0) + return -ENODEV; + info("MT9M111 sensor detected"); + break; + case SENSOR_MT9M001: + if (mt9m001_init_sensor(gspca_dev) < 0) + return -ENODEV; + info("MT9M001 sensor detected"); + break; + case SENSOR_HV7131R: + if (hv7131r_init_sensor(gspca_dev) < 0) + return -ENODEV; + info("HV7131R sensor detected"); + break; + default: + info("Unsupported Sensor"); + return -ENODEV; + } + + return 0; +} + +static void configure_sensor_output(struct gspca_dev *gspca_dev, int mode) +{ + struct sd *sd = (struct sd *) gspca_dev; + u8 value; + switch (sd->sensor) { + case SENSOR_OV9650: + if (mode & MODE_SXGA) { + i2c_w1(gspca_dev, 0x17, 0x1b); + i2c_w1(gspca_dev, 0x18, 0xbc); + i2c_w1(gspca_dev, 0x19, 0x01); + i2c_w1(gspca_dev, 0x1a, 0x82); + i2c_r1(gspca_dev, 0x12, &value); + i2c_w1(gspca_dev, 0x12, value & 0x07); + } else { + i2c_w1(gspca_dev, 0x17, 0x24); + i2c_w1(gspca_dev, 0x18, 0xc5); + i2c_w1(gspca_dev, 0x19, 0x00); + i2c_w1(gspca_dev, 0x1a, 0x3c); + i2c_r1(gspca_dev, 0x12, &value); + i2c_w1(gspca_dev, 0x12, (value & 0x7) | 0x40); + } + break; + } +} + +#define HW_WIN(mode, hstart, vstart) \ +((const u8 []){hstart & 0xff, hstart >> 8, \ +vstart & 0xff, vstart >> 8, \ +(mode & MODE_SXGA ? 1280 >> 4 : 640 >> 4), \ +(mode & MODE_SXGA ? 1024 >> 3 : 480 >> 3)}) + +#define CLR_WIN(width, height) \ +((const u8 [])\ +{0, width >> 2, 0, height >> 1,\ +((width >> 10) & 0x01) | ((height >> 8) & 0x6)}) + +static int sd_start(struct gspca_dev *gspca_dev) +{ + struct sd *sd = (struct sd *) gspca_dev; + int mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv; + int width = gspca_dev->width; + int height = gspca_dev->height; + u8 fmt, scale = 0; + + sd->jpeg_hdr = kmalloc(JPEG_HDR_SZ, GFP_KERNEL); + if (sd->jpeg_hdr == NULL) + return -ENOMEM; + + jpeg_define(sd->jpeg_hdr, height, width, + 0x21); + jpeg_set_qual(sd->jpeg_hdr, sd->quality); + + if (mode & MODE_RAW) + fmt = 0x2d; + else if (mode & MODE_JPEG) + fmt = 0x2c; + else + fmt = 0x2f; + + switch (mode & 0x0f) { + case 3: + scale = 0xc0; + info("Set 1280x1024"); + break; + case 2: + scale = 0x80; + info("Set 640x480"); + break; + case 1: + scale = 0x90; + info("Set 320x240"); + break; + case 0: + scale = 0xa0; + info("Set 160x120"); + break; + } + + configure_sensor_output(gspca_dev, mode); + reg_w(gspca_dev, 0x1100, sd->jpeg_hdr + JPEG_QT0_OFFSET, 64); + reg_w(gspca_dev, 0x1140, sd->jpeg_hdr + JPEG_QT1_OFFSET, 64); + reg_w(gspca_dev, 0x10fb, CLR_WIN(width, height), 5); + reg_w(gspca_dev, 0x1180, HW_WIN(mode, sd->hstart, sd->vstart), 6); + reg_w1(gspca_dev, 0x1189, scale); + reg_w1(gspca_dev, 0x10e0, fmt); + + set_cmatrix(gspca_dev); + set_gamma(gspca_dev); + set_redblue(gspca_dev); + set_gain(gspca_dev); + set_exposure(gspca_dev); + set_hvflip(gspca_dev); + + reg_r(gspca_dev, 0x1061, 1); + reg_w1(gspca_dev, 0x1061, gspca_dev->usb_buf[0] | 0x02); + return 0; +} + +static void sd_stopN(struct gspca_dev *gspca_dev) +{ + reg_r(gspca_dev, 0x1061, 1); + reg_w1(gspca_dev, 0x1061, gspca_dev->usb_buf[0] & ~0x02); +} + +static void sd_stop0(struct gspca_dev *gspca_dev) +{ + struct sd *sd = (struct sd *) gspca_dev; + kfree(sd->jpeg_hdr); +} + +static void do_autoexposure(struct gspca_dev *gspca_dev) +{ + struct sd *sd = (struct sd *) gspca_dev; + int avg_lum, new_exp; + + if (!sd->auto_exposure) + return; + + avg_lum = atomic_read(&sd->avg_lum); + + /* + * some hardcoded values are present + * like those for maximal/minimal exposure + * and exposure steps + */ + if (avg_lum < MIN_AVG_LUM) { + if (sd->exposure > 0x1770) + return; + + new_exp = sd->exposure + sd->exposure_step; + if (new_exp > 0x1770) + new_exp = 0x1770; + if (new_exp < 0x10) + new_exp = 0x10; + sd->exposure = new_exp; + set_exposure(gspca_dev); + + sd->older_step = sd->old_step; + sd->old_step = 1; + + if (sd->old_step ^ sd->older_step) + sd->exposure_step /= 2; + else + sd->exposure_step += 2; + } + if (avg_lum > MAX_AVG_LUM) { + if (sd->exposure < 0x10) + return; + new_exp = sd->exposure - sd->exposure_step; + if (new_exp > 0x1700) + new_exp = 0x1770; + if (new_exp < 0x10) + new_exp = 0x10; + sd->exposure = new_exp; + set_exposure(gspca_dev); + sd->older_step = sd->old_step; + sd->old_step = 0; + + if (sd->old_step ^ sd->older_step) + sd->exposure_step /= 2; + else + sd->exposure_step += 2; + } +} + +static void sd_pkt_scan(struct gspca_dev *gspca_dev, + struct gspca_frame *frame, /* target */ + u8 *data, /* isoc packet */ + int len) /* iso packet length */ +{ + struct sd *sd = (struct sd *) gspca_dev; + int avg_lum; + static unsigned char frame_header[] = + {0xff, 0xff, 0x00, 0xc4, 0xc4, 0x96}; + if (len == 64 && memcmp(data, frame_header, 6) == 0) { + avg_lum = ((data[35] >> 2) & 3) | + (data[20] << 2) | + (data[19] << 10); + avg_lum += ((data[35] >> 4) & 3) | + (data[22] << 2) | + (data[21] << 10); + avg_lum += ((data[35] >> 6) & 3) | + (data[24] << 2) | + (data[23] << 10); + avg_lum += (data[36] & 3) | + (data[26] << 2) | + (data[25] << 10); + avg_lum += ((data[36] >> 2) & 3) | + (data[28] << 2) | + (data[27] << 10); + avg_lum += ((data[36] >> 4) & 3) | + (data[30] << 2) | + (data[29] << 10); + avg_lum += ((data[36] >> 6) & 3) | + (data[32] << 2) | + (data[31] << 10); + avg_lum += ((data[44] >> 4) & 3) | + (data[34] << 2) | + (data[33] << 10); + avg_lum >>= 9; + atomic_set(&sd->avg_lum, avg_lum); + gspca_frame_add(gspca_dev, LAST_PACKET, + frame, data, len); + return; + } + if (gspca_dev->last_packet_type == LAST_PACKET) { + if (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv + & MODE_JPEG) { + gspca_frame_add(gspca_dev, FIRST_PACKET, frame, + sd->jpeg_hdr, JPEG_HDR_SZ); + gspca_frame_add(gspca_dev, INTER_PACKET, frame, + data, len); + } else { + gspca_frame_add(gspca_dev, FIRST_PACKET, frame, + data, len); + } + } else { + gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len); + } +} + +/* sub-driver description */ +static const struct sd_desc sd_desc = { + .name = MODULE_NAME, + .ctrls = sd_ctrls, + .nctrls = ARRAY_SIZE(sd_ctrls), + .config = sd_config, + .init = sd_init, + .start = sd_start, + .stopN = sd_stopN, + .stop0 = sd_stop0, + .pkt_scan = sd_pkt_scan, + .dq_callback = do_autoexposure, +#ifdef CONFIG_VIDEO_ADV_DEBUG + .set_register = sd_dbg_s_register, + .get_register = sd_dbg_g_register, +#endif + .get_chip_ident = sd_chip_ident, +}; + +#define SN9C20X(sensor, i2c_addr, button_mask) \ + .driver_info = (button_mask << 16) \ + | (SENSOR_ ## sensor << 8) \ + | (i2c_addr) + +static const __devinitdata struct usb_device_id device_table[] = { + {USB_DEVICE(0x0c45, 0x6240), SN9C20X(MT9M001, 0x5d, 0)}, + {USB_DEVICE(0x0c45, 0x6242), SN9C20X(MT9M111, 0x5d, 0)}, + {USB_DEVICE(0x0c45, 0x6248), SN9C20X(OV9655, 0x30, 0)}, + {USB_DEVICE(0x0c45, 0x624e), SN9C20X(SOI968, 0x30, 0x10)}, + {USB_DEVICE(0x0c45, 0x624f), SN9C20X(OV9650, 0x30, 0)}, + {USB_DEVICE(0x0c45, 0x6251), SN9C20X(OV9650, 0x30, 0)}, + {USB_DEVICE(0x0c45, 0x6253), SN9C20X(OV9650, 0x30, 0)}, + {USB_DEVICE(0x0c45, 0x6260), SN9C20X(OV7670, 0x21, 0)}, + {USB_DEVICE(0x0c45, 0x6270), SN9C20X(MT9VPRB, 0x00, 0)}, + {USB_DEVICE(0x0c45, 0x627b), SN9C20X(OV7660, 0x21, 0)}, + {USB_DEVICE(0x0c45, 0x627c), SN9C20X(HV7131R, 0x11, 0)}, + {USB_DEVICE(0x0c45, 0x627f), SN9C20X(OV9650, 0x30, 0)}, + {USB_DEVICE(0x0c45, 0x6280), SN9C20X(MT9M001, 0x5d, 0)}, + {USB_DEVICE(0x0c45, 0x6282), SN9C20X(MT9M111, 0x5d, 0)}, + {USB_DEVICE(0x0c45, 0x6288), SN9C20X(OV9655, 0x30, 0)}, + {USB_DEVICE(0x0c45, 0x628e), SN9C20X(SOI968, 0x30, 0)}, + {USB_DEVICE(0x0c45, 0x628f), SN9C20X(OV9650, 0x30, 0)}, + {USB_DEVICE(0x0c45, 0x62a0), SN9C20X(OV7670, 0x21, 0)}, + {USB_DEVICE(0x0c45, 0x62b0), SN9C20X(MT9VPRB, 0x00, 0)}, + {USB_DEVICE(0x0c45, 0x62b3), SN9C20X(OV9655, 0x30, 0)}, + {USB_DEVICE(0x0c45, 0x62bb), SN9C20X(OV7660, 0x21, 0)}, + {USB_DEVICE(0x0c45, 0x62bc), SN9C20X(HV7131R, 0x11, 0)}, + {USB_DEVICE(0x045e, 0x00f4), SN9C20X(OV9650, 0x30, 0)}, + {USB_DEVICE(0x145f, 0x013d), SN9C20X(OV7660, 0x21, 0)}, + {USB_DEVICE(0x0458, 0x7029), SN9C20X(HV7131R, 0x11, 0)}, + {USB_DEVICE(0xa168, 0x0610), SN9C20X(HV7131R, 0x11, 0)}, + {USB_DEVICE(0xa168, 0x0611), SN9C20X(HV7131R, 0x11, 0)}, + {USB_DEVICE(0xa168, 0x0613), SN9C20X(HV7131R, 0x11, 0)}, + {USB_DEVICE(0xa168, 0x0618), SN9C20X(HV7131R, 0x11, 0)}, + {USB_DEVICE(0xa168, 0x0614), SN9C20X(MT9M111, 0x5d, 0)}, + {USB_DEVICE(0xa168, 0x0615), SN9C20X(MT9M111, 0x5d, 0)}, + {USB_DEVICE(0xa168, 0x0617), SN9C20X(MT9M111, 0x5d, 0)}, + {} +}; +MODULE_DEVICE_TABLE(usb, device_table); + +/* -- device connect -- */ +static int sd_probe(struct usb_interface *intf, + const struct usb_device_id *id) +{ + return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd), + THIS_MODULE); +} + +static void sd_disconnect(struct usb_interface *intf) +{ +#ifdef CONFIG_USB_GSPCA_SN9C20X_EVDEV + struct gspca_dev *gspca_dev = usb_get_intfdata(intf); + + sn9c20x_input_cleanup(gspca_dev); +#endif + + gspca_disconnect(intf); +} + +static struct usb_driver sd_driver = { + .name = MODULE_NAME, + .id_table = device_table, + .probe = sd_probe, + .disconnect = sd_disconnect, +#ifdef CONFIG_PM + .suspend = gspca_suspend, + .resume = gspca_resume, + .reset_resume = gspca_resume, +#endif +}; + +/* -- module insert / remove -- */ +static int __init sd_mod_init(void) +{ + int ret; + ret = usb_register(&sd_driver); + if (ret < 0) + return ret; + info("registered"); + return 0; +} +static void __exit sd_mod_exit(void) +{ + usb_deregister(&sd_driver); + info("deregistered"); +} + +module_init(sd_mod_init); +module_exit(sd_mod_exit); -- cgit v1.2.3 From 13f81b30dcdaede4d7b3fc982a6d63c494aff666 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Sun, 19 Jul 2009 12:09:32 +0200 Subject: gspca - jpeg subdrivers: Check the result of kmalloc(jpeg header). From: Julia Lawall Priority: high Signed-off-by: Julia Lawall Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/conex.c | 2 ++ linux/drivers/media/video/gspca/mars.c | 2 ++ linux/drivers/media/video/gspca/sonixj.c | 2 ++ linux/drivers/media/video/gspca/spca500.c | 2 ++ linux/drivers/media/video/gspca/stk014.c | 2 ++ linux/drivers/media/video/gspca/sunplus.c | 2 ++ linux/drivers/media/video/gspca/zc3xx.c | 2 ++ 7 files changed, 14 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/conex.c b/linux/drivers/media/video/gspca/conex.c index 219cfa6fb..8d48ea174 100644 --- a/linux/drivers/media/video/gspca/conex.c +++ b/linux/drivers/media/video/gspca/conex.c @@ -846,6 +846,8 @@ static int sd_start(struct gspca_dev *gspca_dev) /* create the JPEG header */ sd->jpeg_hdr = kmalloc(JPEG_HDR_SZ, GFP_KERNEL); + if (!sd->jpeg_hdr) + return -ENOMEM; jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width, 0x22); /* JPEG 411 */ jpeg_set_qual(sd->jpeg_hdr, sd->quality); diff --git a/linux/drivers/media/video/gspca/mars.c b/linux/drivers/media/video/gspca/mars.c index 789fd178a..68dd1ea0f 100644 --- a/linux/drivers/media/video/gspca/mars.c +++ b/linux/drivers/media/video/gspca/mars.c @@ -201,6 +201,8 @@ static int sd_start(struct gspca_dev *gspca_dev) /* create the JPEG header */ sd->jpeg_hdr = kmalloc(JPEG_HDR_SZ, GFP_KERNEL); + if (!sd->jpeg_hdr) + return -ENOMEM; jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width, 0x21); /* JPEG 422 */ jpeg_set_qual(sd->jpeg_hdr, sd->quality); diff --git a/linux/drivers/media/video/gspca/sonixj.c b/linux/drivers/media/video/gspca/sonixj.c index 3d2722704..5568401e8 100644 --- a/linux/drivers/media/video/gspca/sonixj.c +++ b/linux/drivers/media/video/gspca/sonixj.c @@ -1780,6 +1780,8 @@ static int sd_start(struct gspca_dev *gspca_dev) /* create the JPEG header */ sd->jpeg_hdr = kmalloc(JPEG_HDR_SZ, GFP_KERNEL); + if (!sd->jpeg_hdr) + return -ENOMEM; jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width, 0x21); /* JPEG 422 */ jpeg_set_qual(sd->jpeg_hdr, sd->quality); diff --git a/linux/drivers/media/video/gspca/spca500.c b/linux/drivers/media/video/gspca/spca500.c index 9717da6af..1fbad8d8f 100644 --- a/linux/drivers/media/video/gspca/spca500.c +++ b/linux/drivers/media/video/gspca/spca500.c @@ -687,6 +687,8 @@ static int sd_start(struct gspca_dev *gspca_dev) /* create the JPEG header */ sd->jpeg_hdr = kmalloc(JPEG_HDR_SZ, GFP_KERNEL); + if (!sd->jpeg_hdr) + return -ENOMEM; jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width, 0x22); /* JPEG 411 */ jpeg_set_qual(sd->jpeg_hdr, sd->quality); diff --git a/linux/drivers/media/video/gspca/stk014.c b/linux/drivers/media/video/gspca/stk014.c index f25be20cf..476289648 100644 --- a/linux/drivers/media/video/gspca/stk014.c +++ b/linux/drivers/media/video/gspca/stk014.c @@ -333,6 +333,8 @@ static int sd_start(struct gspca_dev *gspca_dev) /* create the JPEG header */ sd->jpeg_hdr = kmalloc(JPEG_HDR_SZ, GFP_KERNEL); + if (!sd->jpeg_hdr) + return -ENOMEM; jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width, 0x22); /* JPEG 411 */ jpeg_set_qual(sd->jpeg_hdr, sd->quality); diff --git a/linux/drivers/media/video/gspca/sunplus.c b/linux/drivers/media/video/gspca/sunplus.c index f23594e0b..270b86f24 100644 --- a/linux/drivers/media/video/gspca/sunplus.c +++ b/linux/drivers/media/video/gspca/sunplus.c @@ -1008,6 +1008,8 @@ static int sd_start(struct gspca_dev *gspca_dev) /* create the JPEG header */ sd->jpeg_hdr = kmalloc(JPEG_HDR_SZ, GFP_KERNEL); + if (!sd->jpeg_hdr) + return -ENOMEM; jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width, 0x22); /* JPEG 411 */ jpeg_set_qual(sd->jpeg_hdr, sd->quality); diff --git a/linux/drivers/media/video/gspca/zc3xx.c b/linux/drivers/media/video/gspca/zc3xx.c index 2855ebf90..2a9480138 100644 --- a/linux/drivers/media/video/gspca/zc3xx.c +++ b/linux/drivers/media/video/gspca/zc3xx.c @@ -7272,6 +7272,8 @@ static int sd_start(struct gspca_dev *gspca_dev) /* create the JPEG header */ sd->jpeg_hdr = kmalloc(JPEG_HDR_SZ, GFP_KERNEL); + if (!sd->jpeg_hdr) + return -ENOMEM; jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width, 0x21); /* JPEG 422 */ jpeg_set_qual(sd->jpeg_hdr, sd->quality); -- cgit v1.2.3 From b510105ff1dd5026a33548ef518f1dc40f97d313 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 19 Jul 2009 09:10:06 -0300 Subject: em28xx-video: rename ac97 audio controls to better document it From: Mauro Carvalho Chehab As em28xx chip has nothing to do with volume/mute controls, rename those controls to properly indicate that they control the companion AC97 chip that it is inside the boards with this chip. Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/em28xx/em28xx-video.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/em28xx/em28xx-video.c b/linux/drivers/media/video/em28xx/em28xx-video.c index cef676bf8..635f5b6d2 100644 --- a/linux/drivers/media/video/em28xx/em28xx-video.c +++ b/linux/drivers/media/video/em28xx/em28xx-video.c @@ -142,7 +142,7 @@ static struct em28xx_fmt format[] = { /* supported controls */ /* Common to all boards */ -static struct v4l2_queryctrl em28xx_qctrl[] = { +static struct v4l2_queryctrl ac97_qctrl[] = { { .id = V4L2_CID_AUDIO_VOLUME, .type = V4L2_CTRL_TYPE_INTEGER, @@ -1027,9 +1027,9 @@ static int vidioc_queryctrl(struct file *file, void *priv, qc->id = id; if (!dev->board.has_msp34xx) { - for (i = 0; i < ARRAY_SIZE(em28xx_qctrl); i++) { - if (qc->id && qc->id == em28xx_qctrl[i].id) { - memcpy(qc, &(em28xx_qctrl[i]), sizeof(*qc)); + for (i = 0; i < ARRAY_SIZE(ac97_qctrl); i++) { + if (qc->id && qc->id == ac97_qctrl[i].id) { + memcpy(qc, &(ac97_qctrl[i]), sizeof(*qc)); return 0; } } @@ -1091,10 +1091,10 @@ static int vidioc_s_ctrl(struct file *file, void *priv, v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_ctrl, ctrl); else { rc = 1; - for (i = 0; i < ARRAY_SIZE(em28xx_qctrl); i++) { - if (ctrl->id == em28xx_qctrl[i].id) { - if (ctrl->value < em28xx_qctrl[i].minimum || - ctrl->value > em28xx_qctrl[i].maximum) { + for (i = 0; i < ARRAY_SIZE(ac97_qctrl); i++) { + if (ctrl->id == ac97_qctrl[i].id) { + if (ctrl->value < ac97_qctrl[i].minimum || + ctrl->value > ac97_qctrl[i].maximum) { rc = -ERANGE; break; } @@ -1668,9 +1668,9 @@ static int radio_queryctrl(struct file *file, void *priv, qc->id >= V4L2_CID_LASTP1) return -EINVAL; - for (i = 0; i < ARRAY_SIZE(em28xx_qctrl); i++) { - if (qc->id && qc->id == em28xx_qctrl[i].id) { - memcpy(qc, &(em28xx_qctrl[i]), sizeof(*qc)); + for (i = 0; i < ARRAY_SIZE(ac97_qctrl); i++) { + if (qc->id && qc->id == ac97_qctrl[i].id) { + memcpy(qc, &(ac97_qctrl[i]), sizeof(*qc)); return 0; } } -- cgit v1.2.3 From 2344fe31e157aac9a1b78033e60f064e6131de04 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 19 Jul 2009 10:45:49 -0300 Subject: em28xx-video: better implement ac97 control ioctls From: Mauro Carvalho Chehab In the past, some devices with saa711x had their parameters controlled directly inside em28xx driver, instead of using their proper module for it. Due to that, the ac97 controls were mixed with saa711x ones. Older patches removed all saa711x controls, but we still need to control ac97 devices on em28xx, since we don't have a separate v4l2 device for it. The proper way to address is to create a separate ac97 v4l2 device. While we don't have it, we should clean up the code to allow having a better view of what is part of em28xx core code and what's due to ac97 control inside it. Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/em28xx/em28xx-video.c | 117 ++++++++++++++---------- 1 file changed, 68 insertions(+), 49 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/em28xx/em28xx-video.c b/linux/drivers/media/video/em28xx/em28xx-video.c index 635f5b6d2..1237e325d 100644 --- a/linux/drivers/media/video/em28xx/em28xx-video.c +++ b/linux/drivers/media/video/em28xx/em28xx-video.c @@ -151,7 +151,7 @@ static struct v4l2_queryctrl ac97_qctrl[] = { .maximum = 0x1f, .step = 0x1, .default_value = 0x1f, - .flags = 0, + .flags = V4L2_CTRL_FLAG_SLIDER, }, { .id = V4L2_CID_AUDIO_MUTE, .type = V4L2_CTRL_TYPE_BOOLEAN, @@ -622,10 +622,29 @@ static void res_free(struct em28xx_fh *fh) } /* - * em28xx_get_ctrl() - * return the current saturation, brightness or contrast, mute state + * ac97_queryctrl() + * return the ac97 supported controls + */ +static int ac97_queryctrl(struct v4l2_queryctrl *qc) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(ac97_qctrl); i++) { + if (qc->id && qc->id == ac97_qctrl[i].id) { + memcpy(qc, &(ac97_qctrl[i]), sizeof(*qc)); + return 0; + } + } + + /* Control is not ac97 related */ + return 1; +} + +/* + * ac97_get_ctrl() + * return the current values for ac97 mute and volume */ -static int em28xx_get_ctrl(struct em28xx *dev, struct v4l2_control *ctrl) +static int ac97_get_ctrl(struct em28xx *dev, struct v4l2_control *ctrl) { switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: @@ -635,29 +654,41 @@ static int em28xx_get_ctrl(struct em28xx *dev, struct v4l2_control *ctrl) ctrl->value = dev->volume; return 0; default: - return -EINVAL; + /* Control is not ac97 related */ + return 1; } } /* - * em28xx_set_ctrl() - * mute or set new saturation, brightness or contrast + * ac97_set_ctrl() + * set values for ac97 mute and volume */ -static int em28xx_set_ctrl(struct em28xx *dev, const struct v4l2_control *ctrl) +static int ac97_set_ctrl(struct em28xx *dev, const struct v4l2_control *ctrl) { + int i; + + for (i = 0; i < ARRAY_SIZE(ac97_qctrl); i++) + if (ctrl->id == ac97_qctrl[i].id) + goto handle; + + /* Announce that hasn't handle it */ + return 1; + +handle: + if (ctrl->value < ac97_qctrl[i].minimum || + ctrl->value > ac97_qctrl[i].maximum) + return -ERANGE; + switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: - if (ctrl->value != dev->mute) { - dev->mute = ctrl->value; - return em28xx_audio_analog_set(dev); - } - return 0; + dev->mute = ctrl->value; + break; case V4L2_CID_AUDIO_VOLUME: dev->volume = ctrl->value; - return em28xx_audio_analog_set(dev); - default: - return -EINVAL; + break; } + + return em28xx_audio_analog_set(dev); } static int check_dev(struct em28xx *dev) @@ -1015,7 +1046,6 @@ static int vidioc_queryctrl(struct file *file, void *priv, struct em28xx_fh *fh = priv; struct em28xx *dev = fh->dev; int id = qc->id; - int i; int rc; rc = check_dev(dev); @@ -1026,15 +1056,14 @@ static int vidioc_queryctrl(struct file *file, void *priv, qc->id = id; - if (!dev->board.has_msp34xx) { - for (i = 0; i < ARRAY_SIZE(ac97_qctrl); i++) { - if (qc->id && qc->id == ac97_qctrl[i].id) { - memcpy(qc, &(ac97_qctrl[i]), sizeof(*qc)); - return 0; - } - } + /* enumberate AC97 controls */ + if (dev->audio_mode.ac97 != EM28XX_NO_AC97) { + rc = ac97_queryctrl(qc); + if (!rc) + return 0; } + /* enumberate V4L2 device controls */ mutex_lock(&dev->lock); v4l2_device_call_all(&dev->v4l2_dev, 0, core, queryctrl, qc); mutex_unlock(&dev->lock); @@ -1059,14 +1088,16 @@ static int vidioc_g_ctrl(struct file *file, void *priv, mutex_lock(&dev->lock); - if (dev->board.has_msp34xx) + /* Set an AC97 control */ + if (dev->audio_mode.ac97 != EM28XX_NO_AC97) + rc = ac97_get_ctrl(dev, ctrl); + else + rc = 1; + + /* It were not an AC97 control. Sends it to the v4l2 dev interface */ + if (rc == 1) { v4l2_device_call_all(&dev->v4l2_dev, 0, core, g_ctrl, ctrl); - else { - rc = em28xx_get_ctrl(dev, ctrl); - if (rc < 0) { - v4l2_device_call_all(&dev->v4l2_dev, 0, core, g_ctrl, ctrl); - rc = 0; - } + rc = 0; } mutex_unlock(&dev->lock); @@ -1078,7 +1109,6 @@ static int vidioc_s_ctrl(struct file *file, void *priv, { struct em28xx_fh *fh = priv; struct em28xx *dev = fh->dev; - u8 i; int rc; rc = check_dev(dev); @@ -1087,27 +1117,16 @@ static int vidioc_s_ctrl(struct file *file, void *priv, mutex_lock(&dev->lock); - if (dev->board.has_msp34xx) - v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_ctrl, ctrl); - else { + /* Set an AC97 control */ + if (dev->audio_mode.ac97 != EM28XX_NO_AC97) + rc = ac97_set_ctrl(dev, ctrl); + else rc = 1; - for (i = 0; i < ARRAY_SIZE(ac97_qctrl); i++) { - if (ctrl->id == ac97_qctrl[i].id) { - if (ctrl->value < ac97_qctrl[i].minimum || - ctrl->value > ac97_qctrl[i].maximum) { - rc = -ERANGE; - break; - } - - rc = em28xx_set_ctrl(dev, ctrl); - break; - } - } - } - /* Control not found - try to send it to the attached devices */ + /* It were not an AC97 control. Sends it to the v4l2 dev interface */ if (rc == 1) { v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_ctrl, ctrl); + /* FIXME: should be returning a meaninful value */ rc = 0; } -- cgit v1.2.3 From 680b58a1db752ccb021764aae84f0a40b1825e7e Mon Sep 17 00:00:00 2001 From: "Igor M. Liplianin" Date: Mon, 20 Jul 2009 00:37:09 +0400 Subject: Add output clock configuration for stv6110 tuner. From: Igor M. Liplianin Signed-off-by: Igor M. Liplianin --- linux/drivers/media/dvb/frontends/stv6110.c | 10 ++++++++++ linux/drivers/media/dvb/frontends/stv6110.h | 1 + 2 files changed, 11 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/frontends/stv6110.c b/linux/drivers/media/dvb/frontends/stv6110.c index 70efac869..5aabb782e 100644 --- a/linux/drivers/media/dvb/frontends/stv6110.c +++ b/linux/drivers/media/dvb/frontends/stv6110.c @@ -36,6 +36,7 @@ struct stv6110_priv { struct i2c_adapter *i2c; u32 mclk; + u8 clk_div; u8 regs[8]; }; @@ -221,6 +222,10 @@ static int stv6110_init(struct dvb_frontend *fe) priv->regs[RSTV6110_CTRL1] |= ((((priv->mclk / 1000000) - 16) & 0x1f) << 3); + /* divisor value for the output clock */ + priv->regs[RSTV6110_CTRL2] &= ~0xc0; + priv->regs[RSTV6110_CTRL2] |= (priv->clk_div << 6); + stv6110_write_regs(fe, &priv->regs[RSTV6110_CTRL1], RSTV6110_CTRL1, 8); msleep(1); stv6110_set_bandwidth(fe, 72000000); @@ -418,6 +423,10 @@ struct dvb_frontend *stv6110_attach(struct dvb_frontend *fe, }; int ret; + /* divisor value for the output clock */ + reg0[2] &= ~0xc0; + reg0[2] |= (config->clk_div << 6); + if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 1); @@ -436,6 +445,7 @@ struct dvb_frontend *stv6110_attach(struct dvb_frontend *fe, priv->i2c_address = config->i2c_address; priv->i2c = i2c; priv->mclk = config->mclk; + priv->clk_div = config->clk_div; memcpy(&priv->regs, ®0[1], 8); diff --git a/linux/drivers/media/dvb/frontends/stv6110.h b/linux/drivers/media/dvb/frontends/stv6110.h index 1c0314d6a..2574e1fba 100644 --- a/linux/drivers/media/dvb/frontends/stv6110.h +++ b/linux/drivers/media/dvb/frontends/stv6110.h @@ -42,6 +42,7 @@ struct stv6110_config { u8 i2c_address; u32 mclk; int iq_wiring; + u8 clk_div; /* divisor value for the output clock */ }; #if defined(CONFIG_DVB_STV6110) || (defined(CONFIG_DVB_STV6110_MODULE) \ -- cgit v1.2.3 From f3641acdca07f8402060ee7ff77cb0bc72634413 Mon Sep 17 00:00:00 2001 From: "Igor M. Liplianin" Date: Mon, 20 Jul 2009 00:57:29 +0400 Subject: stv6110 tuner: remove unused iq_wiring configuration parameter. From: Igor M. Liplianin Signed-off-by: Igor M. Liplianin --- linux/drivers/media/dvb/frontends/stv6110.h | 1 - linux/drivers/media/video/cx23885/cx23885-dvb.c | 2 -- 2 files changed, 3 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/frontends/stv6110.h b/linux/drivers/media/dvb/frontends/stv6110.h index 2574e1fba..9db240241 100644 --- a/linux/drivers/media/dvb/frontends/stv6110.h +++ b/linux/drivers/media/dvb/frontends/stv6110.h @@ -41,7 +41,6 @@ struct stv6110_config { u8 i2c_address; u32 mclk; - int iq_wiring; u8 clk_div; /* divisor value for the output clock */ }; diff --git a/linux/drivers/media/video/cx23885/cx23885-dvb.c b/linux/drivers/media/video/cx23885/cx23885-dvb.c index 85fac41e7..805272239 100644 --- a/linux/drivers/media/video/cx23885/cx23885-dvb.c +++ b/linux/drivers/media/video/cx23885/cx23885-dvb.c @@ -410,13 +410,11 @@ static struct stv0900_config netup_stv0900_config = { static struct stv6110_config netup_stv6110_tunerconfig_a = { .i2c_address = 0x60, .mclk = 27000000, - .iq_wiring = 0, }; static struct stv6110_config netup_stv6110_tunerconfig_b = { .i2c_address = 0x63, .mclk = 27000000, - .iq_wiring = 1, }; static int tbs_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) -- cgit v1.2.3 From 20d8713a89d5f49511495e944294806642ec6a13 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 19 Jul 2009 18:03:23 -0300 Subject: sn9c20x: backport to work since 2.6.18 From: Mauro Carvalho Chehab Make sn9c20x driver to work with RHEL5 kernel. Yet, the event interface needs a little more work. Since I'm lazy, I've backported just the webcam driver. While here, reorder includes to the order used on other drivers. Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/gspca/sn9c20x.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/sn9c20x.c b/linux/drivers/media/video/gspca/sn9c20x.c index 78ab26ceb..a516866a2 100644 --- a/linux/drivers/media/video/gspca/sn9c20x.c +++ b/linux/drivers/media/video/gspca/sn9c20x.c @@ -18,17 +18,21 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "gspca.h" -#include "jpeg.h" - -#include #ifdef CONFIG_USB_GSPCA_SN9C20X_EVDEV #include +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 20) #include +#endif #include #include #endif +#include "gspca.h" +#include "jpeg.h" +#include "compat.h" + +#include + MODULE_AUTHOR("Brian Johnson , " "microdia project "); MODULE_DESCRIPTION("GSPCA/SN9C20X USB Camera Driver"); @@ -2409,8 +2413,10 @@ static struct usb_driver sd_driver = { #ifdef CONFIG_PM .suspend = gspca_suspend, .resume = gspca_resume, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 23) .reset_resume = gspca_resume, #endif +#endif }; /* -- module insert / remove -- */ -- cgit v1.2.3 From 20de14406ca4448efc8d965f5bfe0ab0def25b3e Mon Sep 17 00:00:00 2001 From: Abylay Ospan Date: Mon, 20 Jul 2009 01:06:00 +0400 Subject: Change clocking configuration and frequency for NetUP card. From: Abylay Ospan Signed-off-by: Abylay Ospan --- linux/drivers/media/video/cx23885/cx23885-dvb.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/cx23885/cx23885-dvb.c b/linux/drivers/media/video/cx23885/cx23885-dvb.c index 805272239..7f8692f97 100644 --- a/linux/drivers/media/video/cx23885/cx23885-dvb.c +++ b/linux/drivers/media/video/cx23885/cx23885-dvb.c @@ -397,7 +397,7 @@ static struct stv0900_reg stv0900_ts_regs[] = { static struct stv0900_config netup_stv0900_config = { .demod_address = 0x68, - .xtal = 27000000, + .xtal = 8000000, .clkmode = 3,/* 0-CLKI, 2-XTALI, else AUTO */ .diseqc_mode = 2,/* 2/3 PWM */ .ts_config_regs = stv0900_ts_regs, @@ -409,12 +409,14 @@ static struct stv0900_config netup_stv0900_config = { static struct stv6110_config netup_stv6110_tunerconfig_a = { .i2c_address = 0x60, - .mclk = 27000000, + .mclk = 16000000, + .clk_div = 1, }; static struct stv6110_config netup_stv6110_tunerconfig_b = { .i2c_address = 0x63, - .mclk = 27000000, + .mclk = 16000000, + .clk_div = 1, }; static int tbs_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) -- cgit v1.2.3 From ab5fd1dec1bf106e22d4bc18f3119830270f20aa Mon Sep 17 00:00:00 2001 From: Abylay Ospan Date: Mon, 20 Jul 2009 01:15:45 +0400 Subject: Bug fix: stv0900 i2c repeater configuration must be set to manual. From: Abylay Ospan In automatic mode every stop event on SDA line ends repetition. However, in NetUP Dual card on the same i2c bus we have several devices. If someone using both adapters to lock simultaneously or working with CAM interface during lock procedure, it lead to end repetition prematurely quite often. Set stv0900 i2c repeater to manual mode prevents such situation. Signed-off-by: Abylay Ospan --- linux/drivers/media/dvb/frontends/stv0900_core.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/frontends/stv0900_core.c b/linux/drivers/media/dvb/frontends/stv0900_core.c index 84bf35edb..5dbcf215f 100644 --- a/linux/drivers/media/dvb/frontends/stv0900_core.c +++ b/linux/drivers/media/dvb/frontends/stv0900_core.c @@ -234,8 +234,8 @@ enum fe_stv0900_error stv0900_initialize(struct stv0900_internal *i_params) #endif stv0900_write_reg(i_params, R0900_P1_TNRCFG, 0x6c); stv0900_write_reg(i_params, R0900_P2_TNRCFG, 0x6f); - stv0900_write_reg(i_params, R0900_P1_I2CRPT, 0x24); - stv0900_write_reg(i_params, R0900_P2_I2CRPT, 0x24); + stv0900_write_reg(i_params, R0900_P1_I2CRPT, 0x20); + stv0900_write_reg(i_params, R0900_P2_I2CRPT, 0x20); stv0900_write_reg(i_params, R0900_NCOARSE, 0x13); msleep(3); stv0900_write_reg(i_params, R0900_I2CCFG, 0x08); @@ -374,8 +374,8 @@ static int stv0900_i2c_gate_ctrl(struct dvb_frontend *fe, int enable) u32 fi2c; dmd_reg(fi2c, F0900_P1_I2CT_ON, F0900_P2_I2CT_ON); - if (enable) - stv0900_write_bits(i_params, fi2c, 1); + + stv0900_write_bits(i_params, fi2c, enable); return 0; } -- cgit v1.2.3 From 1f04aaf2cbc9e510002eaabb94b8a85d21b12640 Mon Sep 17 00:00:00 2001 From: "Igor M. Liplianin" Date: Mon, 20 Jul 2009 01:21:38 +0400 Subject: stv6110 tuner: Read registers through one time i2c_transfer calling. From: Igor M. Liplianin Signed-off-by: Igor M. Liplianin --- linux/drivers/media/dvb/frontends/stv6110.c | 38 +++++++++++------------------ 1 file changed, 14 insertions(+), 24 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/frontends/stv6110.c b/linux/drivers/media/dvb/frontends/stv6110.c index 5aabb782e..dcf1b21ea 100644 --- a/linux/drivers/media/dvb/frontends/stv6110.c +++ b/linux/drivers/media/dvb/frontends/stv6110.c @@ -101,35 +101,25 @@ static int stv6110_read_regs(struct dvb_frontend *fe, u8 regs[], struct stv6110_priv *priv = fe->tuner_priv; int rc; u8 reg[] = { start }; - struct i2c_msg msg_wr = { - .addr = priv->i2c_address, - .flags = 0, - .buf = reg, - .len = 1, + struct i2c_msg msg[] = { + { + .addr = priv->i2c_address, + .flags = 0, + .buf = reg, + .len = 1, + }, { + .addr = priv->i2c_address, + .flags = I2C_M_RD, + .buf = regs, + .len = len, + }, }; - struct i2c_msg msg_rd = { - .addr = priv->i2c_address, - .flags = I2C_M_RD, - .buf = regs, - .len = len, - }; - /* write subaddr */ if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 1); - rc = i2c_transfer(priv->i2c, &msg_wr, 1); - if (rc != 1) - dprintk("%s: i2c error\n", __func__); - - if (fe->ops.i2c_gate_ctrl) - fe->ops.i2c_gate_ctrl(fe, 0); - /* read registers */ - if (fe->ops.i2c_gate_ctrl) - fe->ops.i2c_gate_ctrl(fe, 1); - - rc = i2c_transfer(priv->i2c, &msg_rd, 1); - if (rc != 1) + rc = i2c_transfer(priv->i2c, msg, 2); + if (rc != 2) dprintk("%s: i2c error\n", __func__); if (fe->ops.i2c_gate_ctrl) -- cgit v1.2.3 From 391fa9b1286e89a5b82f26c2efc3df18d72428e5 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Sun, 19 Jul 2009 23:39:56 +0200 Subject: uvcvideo: Add PROBE_DEF quirk and enable it for the MT6227 device From: Laurent Pinchart At least one MT6227 model crashes when receiving a GET_DEF request on the video probe control. As the various models can't be told apart based on the descriptors, add a PROBE_DEF quirk to avoid sending the GET_DEF request and enable the quirk for all models. Priority: normal Signed-off-by: Laurent Pinchart --- linux/drivers/media/video/uvc/uvc_driver.c | 3 ++- linux/drivers/media/video/uvc/uvc_video.c | 3 +++ linux/drivers/media/video/uvc/uvcvideo.h | 1 + 3 files changed, 6 insertions(+), 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 f7b76884d..1c09cd809 100644 --- a/linux/drivers/media/video/uvc/uvc_driver.c +++ b/linux/drivers/media/video/uvc/uvc_driver.c @@ -1868,7 +1868,8 @@ static struct usb_device_id uvc_ids[] = { .bInterfaceClass = USB_CLASS_VIDEO, .bInterfaceSubClass = 1, .bInterfaceProtocol = 0, - .driver_info = UVC_QUIRK_PROBE_MINMAX }, + .driver_info = UVC_QUIRK_PROBE_MINMAX + | UVC_QUIRK_PROBE_DEF }, /* Syntek (HP Spartan) */ { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO, diff --git a/linux/drivers/media/video/uvc/uvc_video.c b/linux/drivers/media/video/uvc/uvc_video.c index c833e984e..f4f4e1bb3 100644 --- a/linux/drivers/media/video/uvc/uvc_video.c +++ b/linux/drivers/media/video/uvc/uvc_video.c @@ -128,6 +128,9 @@ static int uvc_get_video_ctrl(struct uvc_video_device *video, if (data == NULL) return -ENOMEM; + if ((video->dev->quirks & UVC_QUIRK_PROBE_DEF) && query == UVC_GET_DEF) + return -EIO; + ret = __uvc_query_ctrl(video->dev, query, 0, video->streaming->intfnum, probe ? UVC_VS_PROBE_CONTROL : UVC_VS_COMMIT_CONTROL, data, size, UVC_CTRL_STREAMING_TIMEOUT); diff --git a/linux/drivers/media/video/uvc/uvcvideo.h b/linux/drivers/media/video/uvc/uvcvideo.h index 4887650c9..e700bdc20 100644 --- a/linux/drivers/media/video/uvc/uvcvideo.h +++ b/linux/drivers/media/video/uvc/uvcvideo.h @@ -157,6 +157,7 @@ struct uvc_xu_control { #define UVC_QUIRK_STREAM_NO_FID 0x00000010 #define UVC_QUIRK_IGNORE_SELECTOR_UNIT 0x00000020 #define UVC_QUIRK_FIX_BANDWIDTH 0x00000080 +#define UVC_QUIRK_PROBE_DEF 0x00000100 /* Format flags */ #define UVC_FMT_FLAG_COMPRESSED 0x00000001 -- cgit v1.2.3 From f32c3e119058285fb6ceadc44d235717e45c7d5c Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Mon, 20 Jul 2009 00:16:05 +0200 Subject: uvcvideo: Don't apply the FIX_BANDWIDTH quirk to all ViMicro devices From: Laurent Pinchart Commit 50144aeeb702ea105697ae5249f059ea3990b838 broke the Samsung NC10 netbook webcam. Instead of applying the FIX_BANDWIDTH quirk to all ViMicro devices, list the devices explicitly. Priority: normal Signed-off-by: Laurent Pinchart --- linux/drivers/media/video/uvc/uvc_driver.c | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 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 1c09cd809..1d09751a3 100644 --- a/linux/drivers/media/video/uvc/uvc_driver.c +++ b/linux/drivers/media/video/uvc/uvc_driver.c @@ -1851,11 +1851,29 @@ static struct usb_device_id uvc_ids[] = { .bInterfaceSubClass = 1, .bInterfaceProtocol = 0, .driver_info = UVC_QUIRK_STREAM_NO_FID }, - /* ViMicro */ + /* ViMicro Vega */ { .match_flags = USB_DEVICE_ID_MATCH_VENDOR | USB_DEVICE_ID_MATCH_INT_INFO, .idVendor = 0x0ac8, - .idProduct = 0x0000, + .idProduct = 0x332d, + .bInterfaceClass = USB_CLASS_VIDEO, + .bInterfaceSubClass = 1, + .bInterfaceProtocol = 0, + .driver_info = UVC_QUIRK_FIX_BANDWIDTH }, + /* ViMicro - Minoru3D */ + { .match_flags = USB_DEVICE_ID_MATCH_VENDOR + | USB_DEVICE_ID_MATCH_INT_INFO, + .idVendor = 0x0ac8, + .idProduct = 0x3410, + .bInterfaceClass = USB_CLASS_VIDEO, + .bInterfaceSubClass = 1, + .bInterfaceProtocol = 0, + .driver_info = UVC_QUIRK_FIX_BANDWIDTH }, + /* ViMicro Venus - Minoru3D */ + { .match_flags = USB_DEVICE_ID_MATCH_VENDOR + | USB_DEVICE_ID_MATCH_INT_INFO, + .idVendor = 0x0ac8, + .idProduct = 0x3420, .bInterfaceClass = USB_CLASS_VIDEO, .bInterfaceSubClass = 1, .bInterfaceProtocol = 0, -- cgit v1.2.3 From 41e2b46981cc531fe61b04a83a5e2bc4171c9257 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 20 Jul 2009 13:14:17 +0200 Subject: bttv: fix regression: tvaudio must be loaded before tuner From: Hans Verkuil Both tvaudio and the tuner share i2c address 0x42. The tvaudio module can check whether it really is a tda9840, but the tuner can't. So the tvaudio module must be loaded before the tuner module. This was also the case for 2.6.29, but the order was swapped in 2.6.30. Thanks to Krzysztof Grygiencz for reporting and testing this. Priority: high Signed-off-by: Hans Verkuil --- linux/drivers/media/video/bt8xx/bttv-cards.c | 92 ++++++++++++++------------- linux/drivers/media/video/bt8xx/bttv-driver.c | 1 + linux/drivers/media/video/bt8xx/bttv.h | 1 + 3 files changed, 50 insertions(+), 44 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/bt8xx/bttv-cards.c b/linux/drivers/media/video/bt8xx/bttv-cards.c index 38b238f0f..fdca5f67c 100644 --- a/linux/drivers/media/video/bt8xx/bttv-cards.c +++ b/linux/drivers/media/video/bt8xx/bttv-cards.c @@ -3362,8 +3362,6 @@ void __devinit bttv_init_card1(struct bttv *btv) /* initialization part two -- after registering i2c bus */ void __devinit bttv_init_card2(struct bttv *btv) { - int addr=ADDR_UNSET; - btv->tuner_type = UNSET; if (BTTV_BOARD_UNKNOWN == btv->c.type) { @@ -3508,9 +3506,6 @@ void __devinit bttv_init_card2(struct bttv *btv) btv->pll.pll_current = -1; /* tuner configuration (from card list / autodetect / insmod option) */ - if (ADDR_UNSET != bttv_tvcards[btv->c.type].tuner_addr) - addr = bttv_tvcards[btv->c.type].tuner_addr; - if (UNSET != bttv_tvcards[btv->c.type].tuner_type) if (UNSET == btv->tuner_type) btv->tuner_type = bttv_tvcards[btv->c.type].tuner_type; @@ -3534,40 +3529,6 @@ void __devinit bttv_init_card2(struct bttv *btv) if (UNSET == btv->tuner_type) btv->tuner_type = TUNER_ABSENT; - if (btv->tuner_type != TUNER_ABSENT) { - struct tuner_setup tun_setup; - - /* Load tuner module before issuing tuner config call! */ - if (bttv_tvcards[btv->c.type].has_radio) - v4l2_i2c_new_probed_subdev(&btv->c.v4l2_dev, - &btv->c.i2c_adap, "tuner", "tuner", - v4l2_i2c_tuner_addrs(ADDRS_RADIO)); - v4l2_i2c_new_probed_subdev(&btv->c.v4l2_dev, - &btv->c.i2c_adap, "tuner", "tuner", - v4l2_i2c_tuner_addrs(ADDRS_DEMOD)); - v4l2_i2c_new_probed_subdev(&btv->c.v4l2_dev, - &btv->c.i2c_adap, "tuner", "tuner", - v4l2_i2c_tuner_addrs(ADDRS_TV_WITH_DEMOD)); - - tun_setup.mode_mask = T_ANALOG_TV | T_DIGITAL_TV; - tun_setup.type = btv->tuner_type; - tun_setup.addr = addr; - - if (bttv_tvcards[btv->c.type].has_radio) - tun_setup.mode_mask |= T_RADIO; - - bttv_call_all(btv, tuner, s_type_addr, &tun_setup); - } - - if (btv->tda9887_conf) { - struct v4l2_priv_tun_config tda9887_cfg; - - tda9887_cfg.tuner = TUNER_TDA9887; - tda9887_cfg.priv = &btv->tda9887_conf; - - bttv_call_all(btv, tuner, s_config, &tda9887_cfg); - } - btv->dig = bttv_tvcards[btv->c.type].has_dig_in ? bttv_tvcards[btv->c.type].video_inputs - 1 : UNSET; btv->svhs = bttv_tvcards[btv->c.type].svhs == NO_SVHS ? @@ -3578,15 +3539,15 @@ void __devinit bttv_init_card2(struct bttv *btv) btv->has_remote = remote[btv->c.nr]; if (bttv_tvcards[btv->c.type].has_radio) - btv->has_radio=1; + btv->has_radio = 1; if (bttv_tvcards[btv->c.type].has_remote) - btv->has_remote=1; + btv->has_remote = 1; if (!bttv_tvcards[btv->c.type].no_gpioirq) - btv->gpioirq=1; + btv->gpioirq = 1; if (bttv_tvcards[btv->c.type].volume_gpio) - btv->volume_gpio=bttv_tvcards[btv->c.type].volume_gpio; + btv->volume_gpio = bttv_tvcards[btv->c.type].volume_gpio; if (bttv_tvcards[btv->c.type].audio_mode_gpio) - btv->audio_mode_gpio=bttv_tvcards[btv->c.type].audio_mode_gpio; + btv->audio_mode_gpio = bttv_tvcards[btv->c.type].audio_mode_gpio; if (btv->tuner_type == TUNER_ABSENT) return; /* no tuner or related drivers to load */ @@ -3704,6 +3665,49 @@ no_audio: } +/* initialize the tuner */ +void __devinit bttv_init_tuner(struct bttv *btv) +{ + int addr = ADDR_UNSET; + + if (ADDR_UNSET != bttv_tvcards[btv->c.type].tuner_addr) + addr = bttv_tvcards[btv->c.type].tuner_addr; + + if (btv->tuner_type != TUNER_ABSENT) { + struct tuner_setup tun_setup; + + /* Load tuner module before issuing tuner config call! */ + if (bttv_tvcards[btv->c.type].has_radio) + v4l2_i2c_new_probed_subdev(&btv->c.v4l2_dev, + &btv->c.i2c_adap, "tuner", "tuner", + v4l2_i2c_tuner_addrs(ADDRS_RADIO)); + v4l2_i2c_new_probed_subdev(&btv->c.v4l2_dev, + &btv->c.i2c_adap, "tuner", "tuner", + v4l2_i2c_tuner_addrs(ADDRS_DEMOD)); + v4l2_i2c_new_probed_subdev(&btv->c.v4l2_dev, + &btv->c.i2c_adap, "tuner", "tuner", + v4l2_i2c_tuner_addrs(ADDRS_TV_WITH_DEMOD)); + + tun_setup.mode_mask = T_ANALOG_TV | T_DIGITAL_TV; + tun_setup.type = btv->tuner_type; + tun_setup.addr = addr; + + if (bttv_tvcards[btv->c.type].has_radio) + tun_setup.mode_mask |= T_RADIO; + + bttv_call_all(btv, tuner, s_type_addr, &tun_setup); + } + + if (btv->tda9887_conf) { + struct v4l2_priv_tun_config tda9887_cfg; + + tda9887_cfg.tuner = TUNER_TDA9887; + tda9887_cfg.priv = &btv->tda9887_conf; + + bttv_call_all(btv, tuner, s_config, &tda9887_cfg); + } +} + /* ----------------------------------------------------------------------- */ static void modtec_eeprom(struct bttv *btv) diff --git a/linux/drivers/media/video/bt8xx/bttv-driver.c b/linux/drivers/media/video/bt8xx/bttv-driver.c index 9c25efe06..18085ba61 100644 --- a/linux/drivers/media/video/bt8xx/bttv-driver.c +++ b/linux/drivers/media/video/bt8xx/bttv-driver.c @@ -4457,6 +4457,7 @@ static int __devinit bttv_probe(struct pci_dev *dev, /* some card-specific stuff (needs working i2c) */ bttv_init_card2(btv); + bttv_init_tuner(btv); init_irqreg(btv); /* register video4linux + input */ diff --git a/linux/drivers/media/video/bt8xx/bttv.h b/linux/drivers/media/video/bt8xx/bttv.h index 6b7b62bd4..a0cb26b4a 100644 --- a/linux/drivers/media/video/bt8xx/bttv.h +++ b/linux/drivers/media/video/bt8xx/bttv.h @@ -284,6 +284,7 @@ extern struct tvcard bttv_tvcards[]; extern void bttv_idcard(struct bttv *btv); extern void bttv_init_card1(struct bttv *btv); extern void bttv_init_card2(struct bttv *btv); +extern void bttv_init_tuner(struct bttv *btv); /* card-specific funtions */ extern void tea5757_set_freq(struct bttv *btv, unsigned short freq); -- cgit v1.2.3 From e466ec6a572b81252cdc4a681c8ca4949b929dcd Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 20 Jul 2009 14:59:21 +0200 Subject: mt312: fix build for kernels < 2.6.24 From: Hans Verkuil Add compat.h include to get the KERN_CONT define needed for older kernels. Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/dvb/frontends/mt312.c | 1 + 1 file changed, 1 insertion(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/frontends/mt312.c b/linux/drivers/media/dvb/frontends/mt312.c index 071328d7b..f348f8bea 100644 --- a/linux/drivers/media/dvb/frontends/mt312.c +++ b/linux/drivers/media/dvb/frontends/mt312.c @@ -35,6 +35,7 @@ #include "dvb_frontend.h" #include "mt312_priv.h" #include "mt312.h" +#include "compat.h" struct mt312_state { -- cgit v1.2.3 From 49baec9371209e4c77da0321f577b9a33be0fe48 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Mon, 20 Jul 2009 11:20:58 -0400 Subject: cx23885-417: fix manipulation of tvnorms From: Michael Krufky Currently, the VIDIOC_S_STD ioctl just returns -EINVAL regardless of the norm passed. This patch sets cx23885_mpeg_template.tvnorms and cx23885_mpeg_template.current_norm so that the VIDIOC_S_STD will work. Thanks to Joseph Yasi for pointing this out, even though this particular fix was already pushed into a development repository, merge priority of this changeset has been escalated as a result of Joseph posting this identical patch. Priority: high Signed-off-by: Michael Krufky Signed-off-by: Joseph A. Yasi Reviewed-by: Steven Toth --- linux/drivers/media/video/cx23885/cx23885-417.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/cx23885/cx23885-417.c b/linux/drivers/media/video/cx23885/cx23885-417.c index fe0b3c41d..0751fa4dc 100644 --- a/linux/drivers/media/video/cx23885/cx23885-417.c +++ b/linux/drivers/media/video/cx23885/cx23885-417.c @@ -1737,6 +1737,8 @@ static struct video_device cx23885_mpeg_template = { .fops = &mpeg_fops, .ioctl_ops = &mpeg_ioctl_ops, .minor = -1, + .tvnorms = CX23885_NORMS, + .current_norm = V4L2_STD_NTSC_M, }; void cx23885_417_unregister(struct cx23885_dev *dev) -- cgit v1.2.3 From 59ac780bc36a1d932e6290e0ea492085f2ec35cd Mon Sep 17 00:00:00 2001 From: "Igor M. Liplianin" Date: Mon, 20 Jul 2009 19:27:27 +0400 Subject: Add CAM presence checkout during CiMax init for NetUP card. From: Igor M. Liplianin CAM presence checkout is needed after power on PC. Signed-off-by: Igor M. Liplianin --- linux/drivers/media/video/cx23885/cimax2.c | 1 + 1 file changed, 1 insertion(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/cx23885/cimax2.c b/linux/drivers/media/video/cx23885/cimax2.c index fed6d9f9f..d717b9416 100644 --- a/linux/drivers/media/video/cx23885/cimax2.c +++ b/linux/drivers/media/video/cx23885/cimax2.c @@ -455,6 +455,7 @@ int netup_ci_init(struct cx23885_tsport *port) #else INIT_WORK(&state->work, netup_read_ci_status); #endif + schedule_work(&state->work); ci_dbg_print("%s: CI initialized!\n", __func__); -- cgit v1.2.3 From 7991d8e7d32620e4b6f0fd92a78e4a090b4a09ee Mon Sep 17 00:00:00 2001 From: Steven Toth Date: Mon, 20 Jul 2009 14:37:25 -0400 Subject: cx23885: Add support for ATSC/QAM on Hauppauge HVR-1850 From: Steven Toth cx23885: Add support for ATSC/QAM on Hauppauge HVR-1850 Priority: normal Signed-off-by: Steven Toth --- linux/drivers/media/video/cx23885/cx23885-cards.c | 49 ++++++++++++++++++++++- linux/drivers/media/video/cx23885/cx23885-dvb.c | 11 +++++ linux/drivers/media/video/cx23885/cx23885.h | 1 + 3 files changed, 60 insertions(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/cx23885/cx23885-cards.c b/linux/drivers/media/video/cx23885/cx23885-cards.c index edb99215b..2ffc83e60 100644 --- a/linux/drivers/media/video/cx23885/cx23885-cards.c +++ b/linux/drivers/media/video/cx23885/cx23885-cards.c @@ -206,6 +206,11 @@ struct cx23885_board cx23885_boards[] = { .name = "Magic-Pro ProHDTV Extreme 2", .portb = CX23885_MPEG_DVB, }, + [CX23885_BOARD_HAUPPAUGE_HVR1850] = { + .name = "Hauppauge WinTV-HVR1850", + .portb = CX23885_MPEG_ENCODER, + .portc = CX23885_MPEG_DVB, + }, }; const unsigned int cx23885_bcount = ARRAY_SIZE(cx23885_boards); @@ -333,6 +338,10 @@ struct cx23885_subid cx23885_subids[] = { .subvendor = 0x14f1, .subdevice = 0x8657, .card = CX23885_BOARD_MAGICPRO_PROHDTVE2, + }, { + .subvendor = 0x0070, + .subdevice = 0x8541, + .card = CX23885_BOARD_HAUPPAUGE_HVR1850, }, }; const unsigned int cx23885_idcount = ARRAY_SIZE(cx23885_subids); @@ -492,8 +501,13 @@ static void hauppauge_eeprom(struct cx23885_dev *dev, u8 *eeprom_data) /* WinTV-HVR1700 (PCIe, OEM, No IR, full height) * DVB-T and MPEG2 HW Encoder */ break; + case 85021: + /* WinTV-HVR1850 (PCIe, OEM, RCA in, IR, FM, + Dual channel ATSC and MPEG2 HW Encoder */ + break; default: - printk(KERN_WARNING "%s: warning: unknown hauppauge model #%d\n", + printk(KERN_WARNING "%s: warning: " + "unknown hauppauge model #%d\n", dev->name, tv.model); break; } @@ -743,6 +757,36 @@ void cx23885_gpio_setup(struct cx23885_dev *dev) cx_set(GP0_IO, 0x00060006); mdelay(100); break; + case CX23885_BOARD_HAUPPAUGE_HVR1850: + /* GPIO-0 656_CLK */ + /* GPIO-1 656_D0 */ + /* GPIO-2 Wake# */ + /* GPIO-3-10 cx23417 data0-7 */ + /* GPIO-11-14 cx23417 addr0-3 */ + /* GPIO-15-18 cx23417 READY, CS, RD, WR */ + /* GPIO-19 IR_RX */ + /* GPIO-20 C_IR_TX */ + /* GPIO-21 I2S DAT */ + /* GPIO-22 I2S WCLK */ + /* GPIO-23 I2S BCLK */ + /* ALT GPIO: EXP GPIO LATCH */ + + /* CX23417 GPIO's */ + /* GPIO-14 S5H1411/CX24228 Reset */ + /* GPIO-13 EEPROM write protect */ + mc417_gpio_enable(dev, GPIO_14 | GPIO_13, 1); + + /* Put the demod into reset and protect the eeprom */ + mc417_gpio_clear(dev, GPIO_14 | GPIO_13); + mdelay(100); + + /* Bring the demod out of reset */ + mc417_gpio_set(dev, GPIO_14); + mdelay(100); + + /* CX24228 GPIO */ + /* Connected to IF / Mux */ + break; } } @@ -759,6 +803,7 @@ int cx23885_ir_init(struct cx23885_dev *dev) case CX23885_BOARD_HAUPPAUGE_HVR1275: case CX23885_BOARD_HAUPPAUGE_HVR1255: case CX23885_BOARD_HAUPPAUGE_HVR1210: + case CX23885_BOARD_HAUPPAUGE_HVR1850: /* FIXME: Implement me */ break; case CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP: @@ -798,6 +843,7 @@ void cx23885_card_setup(struct cx23885_dev *dev) case CX23885_BOARD_HAUPPAUGE_HVR1275: case CX23885_BOARD_HAUPPAUGE_HVR1255: case CX23885_BOARD_HAUPPAUGE_HVR1210: + case CX23885_BOARD_HAUPPAUGE_HVR1850: if (dev->i2c_bus[0].i2c_rc == 0) hauppauge_eeprom(dev, eeprom+0xc0); break; @@ -865,6 +911,7 @@ void cx23885_card_setup(struct cx23885_dev *dev) case CX23885_BOARD_HAUPPAUGE_HVR1275: case CX23885_BOARD_HAUPPAUGE_HVR1255: case CX23885_BOARD_HAUPPAUGE_HVR1210: + case CX23885_BOARD_HAUPPAUGE_HVR1850: default: ts2->gen_ctrl_val = 0xc; /* Serial bus + punctured clock */ ts2->ts_clk_en_val = 0x1; /* Enable TS_CLK */ diff --git a/linux/drivers/media/video/cx23885/cx23885-dvb.c b/linux/drivers/media/video/cx23885/cx23885-dvb.c index 85fac41e7..6edfbbc81 100644 --- a/linux/drivers/media/video/cx23885/cx23885-dvb.c +++ b/linux/drivers/media/video/cx23885/cx23885-dvb.c @@ -867,6 +867,17 @@ static int dvb_register(struct cx23885_tsport *port) &magicpro_prohdtve2_xc5000_config); } break; + case CX23885_BOARD_HAUPPAUGE_HVR1850: + i2c_bus = &dev->i2c_bus[0]; + fe0->dvb.frontend = dvb_attach(s5h1411_attach, + &hcw_s5h1411_config, + &i2c_bus->i2c_adap); + if (fe0->dvb.frontend != NULL) + dvb_attach(tda18271_attach, fe0->dvb.frontend, + 0x60, &dev->i2c_bus[0].i2c_adap, + &hauppauge_tda18271_config); + break; + default: printk(KERN_INFO "%s: The frontend of your DVB/ATSC card " " isn't supported yet\n", diff --git a/linux/drivers/media/video/cx23885/cx23885.h b/linux/drivers/media/video/cx23885/cx23885.h index a507af77a..f71277845 100644 --- a/linux/drivers/media/video/cx23885/cx23885.h +++ b/linux/drivers/media/video/cx23885/cx23885.h @@ -78,6 +78,7 @@ #define CX23885_BOARD_HAUPPAUGE_HVR1210 21 #define CX23885_BOARD_MYGICA_X8506 22 #define CX23885_BOARD_MAGICPRO_PROHDTVE2 23 +#define CX23885_BOARD_HAUPPAUGE_HVR1850 24 #define GPIO_0 0x00000001 #define GPIO_1 0x00000002 -- cgit v1.2.3 From 988cd25daffa554b51e3f0d5858cb1727f8a9c09 Mon Sep 17 00:00:00 2001 From: Steven Toth Date: Mon, 20 Jul 2009 14:40:31 -0400 Subject: cx23885: Modify hardware revision detection for newer silicon From: Steven Toth cx23885: Modify hardware revision detection for newer silicon Priority: normal Signed-off-by: Steven Toth --- linux/drivers/media/video/cx23885/cx23885-core.c | 22 +++++++++++++++++++--- linux/drivers/media/video/cx23885/cx23885.h | 1 + 2 files changed, 20 insertions(+), 3 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/cx23885/cx23885-core.c b/linux/drivers/media/video/cx23885/cx23885-core.c index 351210e5c..4854d54f1 100644 --- a/linux/drivers/media/video/cx23885/cx23885-core.c +++ b/linux/drivers/media/video/cx23885/cx23885-core.c @@ -714,12 +714,26 @@ static void cx23885_dev_checkrevision(struct cx23885_dev *dev) dev->hwrevision = 0xa1; break; case 0x02: - /* CX23885-13Z */ + /* CX23885-13Z/14Z */ dev->hwrevision = 0xb0; break; case 0x03: - /* CX23888-22Z */ - dev->hwrevision = 0xc0; + if (dev->pci->device == 0x8880) { + /* CX23888-21Z/22Z */ + dev->hwrevision = 0xc0; + } else { + /* CX23885-14Z */ + dev->hwrevision = 0xa4; + } + break; + case 0x04: + if (dev->pci->device == 0x8880) { + /* CX23888-31Z */ + dev->hwrevision = 0xd0; + } else { + /* CX23885-15Z, CX23888-31Z */ + dev->hwrevision = 0xa5; + } break; case 0x0e: /* CX23887-15Z */ @@ -757,6 +771,7 @@ static int cx23885_dev_setup(struct cx23885_dev *dev) /* Configure the internal memory */ if (dev->pci->device == 0x8880) { + /* Could be 887 or 888, assume a default */ dev->bridge = CX23885_BRIDGE_887; /* Apply a sensible clock frequency for the PCIe bridge */ dev->clk_freq = 25000000; @@ -1259,6 +1274,7 @@ static int cx23885_start_dma(struct cx23885_tsport *port, switch (dev->bridge) { case CX23885_BRIDGE_885: case CX23885_BRIDGE_887: + case CX23885_BRIDGE_888: /* enable irqs */ dprintk(1, "%s() enabling TS int's and DMA\n", __func__); cx_set(port->reg_ts_int_msk, port->ts_int_msk_val); diff --git a/linux/drivers/media/video/cx23885/cx23885.h b/linux/drivers/media/video/cx23885/cx23885.h index f71277845..6ddabc263 100644 --- a/linux/drivers/media/video/cx23885/cx23885.h +++ b/linux/drivers/media/video/cx23885/cx23885.h @@ -340,6 +340,7 @@ struct cx23885_dev { CX23885_BRIDGE_UNDEFINED = 0, CX23885_BRIDGE_885 = 885, CX23885_BRIDGE_887 = 887, + CX23885_BRIDGE_888 = 888, } bridge; /* Analog video */ -- cgit v1.2.3 From f48a1698a65eb9b345a625027ac3b8895ab1917a Mon Sep 17 00:00:00 2001 From: Antoine Jacquet Date: Mon, 20 Jul 2009 20:46:42 -0300 Subject: Implement changing resolution on the fly for zr364xx driver From: Lamarque Vieira Souza This patch implements changing resolution in zr364xx_vidioc_s_fmt_vid_cap for zr364xx driver. This version is synced with v4l-dvb as of 20/Jul/2009. Tested with Creative PC-CAM 880. OBS: I had to increase MAX_FRAME_SIZE to prevent a hard crash in my notebook (caps lock blinking) when testing with mplayer, which automatically sets resolution to the maximum (640x480). Maybe we should add code to auto-detect frame size to prevent this kind of crash in the future. Signed-off-by: Lamarque V. Souza Signed-off-by: Antoine Jacquet --- linux/drivers/media/video/zr364xx.c | 65 +++++++++++++++++++++++++++++++------ 1 file changed, 55 insertions(+), 10 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/zr364xx.c b/linux/drivers/media/video/zr364xx.c index 084f97f6a..29ba9f932 100644 --- a/linux/drivers/media/video/zr364xx.c +++ b/linux/drivers/media/video/zr364xx.c @@ -44,14 +44,14 @@ /* Version Information */ #define DRIVER_VERSION "v0.73" -#define ZR364_VERSION_CODE KERNEL_VERSION(0, 7, 3) +#define ZR364XX_VERSION_CODE KERNEL_VERSION(0, 7, 3) #define DRIVER_AUTHOR "Antoine Jacquet, http://royale.zerezo.com/" #define DRIVER_DESC "Zoran 364xx" /* Camera */ #define FRAMES 1 -#define MAX_FRAME_SIZE 100000 +#define MAX_FRAME_SIZE 200000 #define BUFFER_SIZE 0x1000 #define CTRL_TIMEOUT 500 @@ -735,7 +735,7 @@ static int zr364xx_vidioc_querycap(struct file *file, void *priv, strlcpy(cap->card, cam->udev->product, sizeof(cap->card)); strlcpy(cap->bus_info, dev_name(&cam->udev->dev), sizeof(cap->bus_info)); - cap->version = ZR364_VERSION_CODE; + cap->version = ZR364XX_VERSION_CODE; cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE | V4L2_CAP_STREAMING; @@ -875,9 +875,14 @@ static int zr364xx_vidioc_try_fmt_vid_cap(struct file *file, void *priv, return -EINVAL; } + if (!(f->fmt.pix.width == 160 && f->fmt.pix.height == 120) && + !(f->fmt.pix.width == 640 && f->fmt.pix.height == 480)) { + f->fmt.pix.width = 320; + f->fmt.pix.height = 240; + } + f->fmt.pix.field = V4L2_FIELD_NONE; - f->fmt.pix.width = cam->width; - f->fmt.pix.height = cam->height; + f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; f->fmt.pix.bytesperline = f->fmt.pix.width * 2; f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline; f->fmt.pix.colorspace = 0; @@ -908,7 +913,6 @@ static int zr364xx_vidioc_g_fmt_vid_cap(struct file *file, void *priv, return 0; } -/* Lamarque TODO: implement changing resolution on the fly */ static int zr364xx_vidioc_s_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) { @@ -916,6 +920,7 @@ static int zr364xx_vidioc_s_fmt_vid_cap(struct file *file, void *priv, struct videobuf_queue *q = &cam->vb_vidq; char pixelformat_name[5]; int ret = zr364xx_vidioc_try_fmt_vid_cap(file, cam, f); + int i; if (ret < 0) return ret; @@ -928,15 +933,55 @@ static int zr364xx_vidioc_s_fmt_vid_cap(struct file *file, void *priv, goto out; } - f->fmt.pix.field = V4L2_FIELD_NONE; - f->fmt.pix.width = cam->width; - f->fmt.pix.height = cam->height; + if (res_check(cam)) { + DBG("%s can't change format after started\n", __func__); + ret = -EBUSY; + goto out; + } + + cam->width = f->fmt.pix.width; + cam->height = f->fmt.pix.height; + dev_info(&cam->udev->dev, "%s: %dx%d mode selected\n", __func__, + cam->width, cam->height); f->fmt.pix.bytesperline = f->fmt.pix.width * 2; f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline; f->fmt.pix.colorspace = 0; f->fmt.pix.priv = 0; cam->vb_vidq.field = f->fmt.pix.field; cam->mode.color = V4L2_PIX_FMT_JPEG; + + if (f->fmt.pix.width == 160 && f->fmt.pix.height == 120) + mode = 1; + else if (f->fmt.pix.width == 640 && f->fmt.pix.height == 480) + mode = 2; + else + mode = 0; + + m0d1[0] = mode; + m1[2].value = 0xf000 + mode; + m2[1].value = 0xf000 + mode; + header2[437] = cam->height / 256; + header2[438] = cam->height % 256; + header2[439] = cam->width / 256; + header2[440] = cam->width % 256; + + for (i = 0; init[cam->method][i].size != -1; i++) { + ret = + send_control_msg(cam->udev, 1, init[cam->method][i].value, + 0, init[cam->method][i].bytes, + init[cam->method][i].size); + if (ret < 0) { + dev_err(&cam->udev->dev, + "error during resolution change sequence: %d\n", i); + goto out; + } + } + + /* Added some delay here, since opening/closing the camera quickly, + * like Ekiga does during its startup, can crash the webcam + */ + mdelay(100); + cam->skip = 2; ret = 0; out: @@ -1124,6 +1169,7 @@ static int zr364xx_start_acquire(struct zr364xx_camera *cam) cam->buffer.frame[j].ulState = ZR364XX_READ_IDLE; cam->buffer.frame[j].cur_size = 0; } + cam->b_acquire = 1; return 0; } @@ -1166,7 +1212,6 @@ static int zr364xx_vidioc_streamon(struct file *file, void *priv, res = videobuf_streamon(&cam->vb_vidq); if (res == 0) { zr364xx_start_acquire(cam); - cam->b_acquire = 1; } else { res_free(cam); } -- cgit v1.2.3 From e788c8488b451e3c429a140a054712e15e195134 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Tue, 21 Jul 2009 08:33:16 +0200 Subject: flexcop: fix compile error From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/dvb/b2c2/flexcop-fe-tuner.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/b2c2/flexcop-fe-tuner.c b/linux/drivers/media/dvb/b2c2/flexcop-fe-tuner.c index 301bf1688..850a6c606 100644 --- a/linux/drivers/media/dvb/b2c2/flexcop-fe-tuner.c +++ b/linux/drivers/media/dvb/b2c2/flexcop-fe-tuner.c @@ -605,7 +605,7 @@ static int cablestar2_attach(struct flexcop_device *fc, fc->fe->ops.i2c_gate_ctrl = NULL; if (!dvb_attach(dvb_pll_attach, fc->fe, 0x61, - fc->fc_i2c_adap[2].i2c_adap, DVB_PLL_TDEE4)) + &fc->fc_i2c_adap[2].i2c_adap, DVB_PLL_TDEE4)) goto fail; return 1; -- cgit v1.2.3 From 1b5f53fa337a5c09750864277d21a723ac28c389 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 21 Jul 2009 04:23:22 -0300 Subject: zr364xx: Need to include linux/version.h MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit drivers/media/video/zr364xx.c: In function ‘zr364xx_vidioc_querycap’: drivers/media/video/zr364xx.c:736: error: implicit declaration of function ‘KERNEL_VERSION’ kernel-sync: Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/zr364xx.c | 1 + 1 file changed, 1 insertion(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/zr364xx.c b/linux/drivers/media/video/zr364xx.c index 7dff47834..084f97f6a 100644 --- a/linux/drivers/media/video/zr364xx.c +++ b/linux/drivers/media/video/zr364xx.c @@ -29,6 +29,7 @@ #include +#include #include #include #include -- cgit v1.2.3 From d614ff9f8b6297350f6d1690599733960e186b77 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 21 Jul 2009 09:17:24 -0300 Subject: backport commit 405f55712dfe464b3240d7816cc4fe4174831be2 kernel-sync: Author: Alexey Dobriyan Date: Sat Jul 11 22:08:37 2009 +0400 headers: smp_lock.h redux * Remove smp_lock.h from files which don't need it (including some headers!) * Add smp_lock.h to files which do need it * Make smp_lock.h include conditional in hardirq.h It's needed only for one kernel_locked() usage which is under CONFIG_PREEMPT This will make hardirq.h inclusion cheaper for every PREEMPT=n config (which includes allmodconfig/allyesconfig, BTW) Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/bt8xx/dst_ca.c | 1 + linux/drivers/media/dvb/dvb-core/dvbdev.h | 1 - linux/drivers/media/dvb/ttpci/av7110.c | 1 - linux/drivers/media/radio/radio-mr800.c | 1 + linux/drivers/media/radio/radio-si470x.c | 1 + linux/drivers/media/video/bt8xx/bttv-driver.c | 1 + linux/drivers/media/video/cx23885/cx23885-417.c | 1 + linux/drivers/media/video/cx23885/cx23885-video.c | 1 + linux/drivers/media/video/cx88/cx88-blackbird.c | 1 + linux/drivers/media/video/cx88/cx88-video.c | 1 + linux/drivers/media/video/dabusb.c | 1 + linux/drivers/media/video/pwc/pwc-if.c | 1 + linux/drivers/media/video/pwc/pwc.h | 1 - linux/drivers/media/video/s2255drv.c | 1 + linux/drivers/media/video/saa5246a.c | 1 - linux/drivers/media/video/saa5249.c | 1 - linux/drivers/media/video/saa7134/saa7134-empress.c | 1 + linux/drivers/media/video/se401.c | 1 + linux/drivers/media/video/stk-webcam.c | 1 + linux/drivers/media/video/stradis.c | 1 + linux/drivers/media/video/stv680.c | 1 + linux/drivers/media/video/usbvideo/vicam.c | 1 + linux/drivers/media/video/usbvision/usbvision-video.c | 1 + linux/drivers/media/video/v4l2-dev.c | 1 - linux/drivers/media/video/zoran/zoran_driver.c | 1 + 25 files changed, 19 insertions(+), 6 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/bt8xx/dst_ca.c b/linux/drivers/media/dvb/bt8xx/dst_ca.c index bdc22a467..cf35a916c 100644 --- a/linux/drivers/media/dvb/bt8xx/dst_ca.c +++ b/linux/drivers/media/dvb/bt8xx/dst_ca.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include "dvbdev.h" diff --git a/linux/drivers/media/dvb/dvb-core/dvbdev.h b/linux/drivers/media/dvb/dvb-core/dvbdev.h index 79927305e..487919bea 100644 --- a/linux/drivers/media/dvb/dvb-core/dvbdev.h +++ b/linux/drivers/media/dvb/dvb-core/dvbdev.h @@ -27,7 +27,6 @@ #include #include #include -#include #define DVB_MAJOR 212 diff --git a/linux/drivers/media/dvb/ttpci/av7110.c b/linux/drivers/media/dvb/ttpci/av7110.c index 1b961db62..23f45a971 100644 --- a/linux/drivers/media/dvb/ttpci/av7110.c +++ b/linux/drivers/media/dvb/ttpci/av7110.c @@ -36,7 +36,6 @@ #include #include #include -#include #include #include diff --git a/linux/drivers/media/radio/radio-mr800.c b/linux/drivers/media/radio/radio-mr800.c index 5ff444cee..2e8d50be8 100644 --- a/linux/drivers/media/radio/radio-mr800.c +++ b/linux/drivers/media/radio/radio-mr800.c @@ -58,6 +58,7 @@ #include #include #include +#include #include #include #include diff --git a/linux/drivers/media/radio/radio-si470x.c b/linux/drivers/media/radio/radio-si470x.c index 3efd397d1..5b4cab3d0 100644 --- a/linux/drivers/media/radio/radio-si470x.c +++ b/linux/drivers/media/radio/radio-si470x.c @@ -131,6 +131,7 @@ #include #include #include +#include #include #include #include diff --git a/linux/drivers/media/video/bt8xx/bttv-driver.c b/linux/drivers/media/video/bt8xx/bttv-driver.c index 18085ba61..63b0043e2 100644 --- a/linux/drivers/media/video/bt8xx/bttv-driver.c +++ b/linux/drivers/media/video/bt8xx/bttv-driver.c @@ -41,6 +41,7 @@ #include #include #include +#include #include #include #include "bttvp.h" diff --git a/linux/drivers/media/video/cx23885/cx23885-417.c b/linux/drivers/media/video/cx23885/cx23885-417.c index fe0b3c41d..d55246072 100644 --- a/linux/drivers/media/video/cx23885/cx23885-417.c +++ b/linux/drivers/media/video/cx23885/cx23885-417.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include diff --git a/linux/drivers/media/video/cx23885/cx23885-video.c b/linux/drivers/media/video/cx23885/cx23885-video.c index 2248e0216..fc7af991e 100644 --- a/linux/drivers/media/video/cx23885/cx23885-video.c +++ b/linux/drivers/media/video/cx23885/cx23885-video.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include "compat.h" diff --git a/linux/drivers/media/video/cx88/cx88-blackbird.c b/linux/drivers/media/video/cx88/cx88-blackbird.c index b62eadc71..36212fad7 100644 --- a/linux/drivers/media/video/cx88/cx88-blackbird.c +++ b/linux/drivers/media/video/cx88/cx88-blackbird.c @@ -32,6 +32,7 @@ #include #include #include +#include #include #include #include diff --git a/linux/drivers/media/video/cx88/cx88-video.c b/linux/drivers/media/video/cx88/cx88-video.c index a55053767..d4bd9ba68 100644 --- a/linux/drivers/media/video/cx88/cx88-video.c +++ b/linux/drivers/media/video/cx88/cx88-video.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include diff --git a/linux/drivers/media/video/dabusb.c b/linux/drivers/media/video/dabusb.c index 9e9cba431..cb0a41c45 100644 --- a/linux/drivers/media/video/dabusb.c +++ b/linux/drivers/media/video/dabusb.c @@ -32,6 +32,7 @@ #include #include #include +#include #include #include #include diff --git a/linux/drivers/media/video/pwc/pwc-if.c b/linux/drivers/media/video/pwc/pwc-if.c index 4087612ee..f695c6624 100644 --- a/linux/drivers/media/video/pwc/pwc-if.c +++ b/linux/drivers/media/video/pwc/pwc-if.c @@ -62,6 +62,7 @@ #include #include #include +#include #ifdef CONFIG_USB_PWC_INPUT_EVDEV #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18) #include diff --git a/linux/drivers/media/video/pwc/pwc.h b/linux/drivers/media/video/pwc/pwc.h index 7a766eb35..12c869d71 100644 --- a/linux/drivers/media/video/pwc/pwc.h +++ b/linux/drivers/media/video/pwc/pwc.h @@ -29,7 +29,6 @@ #include #include #include -#include #include #include #include diff --git a/linux/drivers/media/video/s2255drv.c b/linux/drivers/media/video/s2255drv.c index 203f6e3ff..4478f26fe 100644 --- a/linux/drivers/media/video/s2255drv.c +++ b/linux/drivers/media/video/s2255drv.c @@ -48,6 +48,7 @@ #include #include #include +#include #include #include #include diff --git a/linux/drivers/media/video/saa5246a.c b/linux/drivers/media/video/saa5246a.c index 1b19a72cc..4593ace1c 100644 --- a/linux/drivers/media/video/saa5246a.c +++ b/linux/drivers/media/video/saa5246a.c @@ -43,7 +43,6 @@ #include #include #include -#include #include #include #include diff --git a/linux/drivers/media/video/saa5249.c b/linux/drivers/media/video/saa5249.c index 2d9d7d7fd..b7cf17361 100644 --- a/linux/drivers/media/video/saa5249.c +++ b/linux/drivers/media/video/saa5249.c @@ -46,7 +46,6 @@ #include #include #include -#include #include #include #include diff --git a/linux/drivers/media/video/saa7134/saa7134-empress.c b/linux/drivers/media/video/saa7134/saa7134-empress.c index 96334a20b..181d96e83 100644 --- a/linux/drivers/media/video/saa7134/saa7134-empress.c +++ b/linux/drivers/media/video/saa7134/saa7134-empress.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include "saa7134-reg.h" diff --git a/linux/drivers/media/video/se401.c b/linux/drivers/media/video/se401.c index 1274a5966..de9e25035 100644 --- a/linux/drivers/media/video/se401.c +++ b/linux/drivers/media/video/se401.c @@ -31,6 +31,7 @@ static const char version[] = "0.24"; #include #include #include +#include #include #include #include "se401.h" diff --git a/linux/drivers/media/video/stk-webcam.c b/linux/drivers/media/video/stk-webcam.c index 886caf736..849867ab2 100644 --- a/linux/drivers/media/video/stk-webcam.c +++ b/linux/drivers/media/video/stk-webcam.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include diff --git a/linux/drivers/media/video/stradis.c b/linux/drivers/media/video/stradis.c index 33001b426..9e28eb2d8 100644 --- a/linux/drivers/media/video/stradis.c +++ b/linux/drivers/media/video/stradis.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include diff --git a/linux/drivers/media/video/stv680.c b/linux/drivers/media/video/stv680.c index a2d7ec732..eafe68502 100644 --- a/linux/drivers/media/video/stv680.c +++ b/linux/drivers/media/video/stv680.c @@ -62,6 +62,7 @@ #include #include #include +#include #include #include #include diff --git a/linux/drivers/media/video/usbvideo/vicam.c b/linux/drivers/media/video/usbvideo/vicam.c index 3b332ef52..b8d9e81b4 100644 --- a/linux/drivers/media/video/usbvideo/vicam.c +++ b/linux/drivers/media/video/usbvideo/vicam.c @@ -43,6 +43,7 @@ #include #include #include +#include #include #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) #include diff --git a/linux/drivers/media/video/usbvision/usbvision-video.c b/linux/drivers/media/video/usbvision/usbvision-video.c index 90b58914f..90d9b5c0e 100644 --- a/linux/drivers/media/video/usbvision/usbvision-video.c +++ b/linux/drivers/media/video/usbvision/usbvision-video.c @@ -50,6 +50,7 @@ #include #include #include +#include #include #include #include diff --git a/linux/drivers/media/video/v4l2-dev.c b/linux/drivers/media/video/v4l2-dev.c index f7e128729..9969abb28 100644 --- a/linux/drivers/media/video/v4l2-dev.c +++ b/linux/drivers/media/video/v4l2-dev.c @@ -25,7 +25,6 @@ #include #include #include -#include #include #include diff --git a/linux/drivers/media/video/zoran/zoran_driver.c b/linux/drivers/media/video/zoran/zoran_driver.c index 8c17d47b3..450a00c98 100644 --- a/linux/drivers/media/video/zoran/zoran_driver.c +++ b/linux/drivers/media/video/zoran/zoran_driver.c @@ -49,6 +49,7 @@ #include #include #include +#include #include #include #include -- cgit v1.2.3 From 9eeecdeb0316860051424e4fa4fe315c10fcc0ad Mon Sep 17 00:00:00 2001 From: Antoine Jacquet Date: Wed, 22 Jul 2009 16:54:51 -0300 Subject: zr364xx: error message when buffer is too small and code cleanup From: Lamarque Vieira Souza . added code to print an error message when buffer is too small to hold frame data, that is better than just a hard crash. Tested using MAX_FRAME_SIZE = 50000, lots of error messages appeared in /var/log/messages but no crash. . removed line "f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;" in zr364xx_vidioc_try_fmt_vid_cap, it should not be there. . changes to improve performance (or at least not hurt it): removed some unneeded debug messages; added macro FULL_DEBUG to enable debug messages in performance critical places, this macro is disabled by default; removed "if (frm->lpvbits == NULL)..." in zr364xx_read_video_callback because after analisying the source code I concluded it will always results to false, so it is not needed. . some small code reorganization. Signed-off-by: Lamarque V. Souza Signed-off-by: Antoine Jacquet --- linux/drivers/media/video/zr364xx.c | 63 +++++++++++++++++++------------------ 1 file changed, 33 insertions(+), 30 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/zr364xx.c b/linux/drivers/media/video/zr364xx.c index 29ba9f932..c298ce625 100644 --- a/linux/drivers/media/video/zr364xx.c +++ b/linux/drivers/media/video/zr364xx.c @@ -67,6 +67,13 @@ } \ } while (0) +/*#define FULL_DEBUG 1*/ +#ifdef FULL_DEBUG +#define _DBG DBG +#else +#define _DBG(fmt, args...) +#endif + /* Init methods, need to find nicer names for these * the exact names of the chipsets would be the best if someone finds it */ #define METHOD0 0 @@ -376,7 +383,7 @@ static int buffer_setup(struct videobuf_queue *vq, unsigned int *count, static void free_buffer(struct videobuf_queue *vq, struct zr364xx_buffer *buf) { - DBG("%s\n", __func__); + _DBG("%s\n", __func__); if (in_interrupt()) BUG(); @@ -429,7 +436,7 @@ static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) vb); struct zr364xx_camera *cam = vq->priv_data; - DBG("%s\n", __func__); + _DBG("%s\n", __func__); buf->vb.state = VIDEOBUF_QUEUED; list_add_tail(&buf->vb.queue, &cam->vidq.active); @@ -441,7 +448,7 @@ static void buffer_release(struct videobuf_queue *vq, struct zr364xx_buffer *buf = container_of(vb, struct zr364xx_buffer, vb); - DBG("%s\n", __func__); + _DBG("%s\n", __func__); free_buffer(vq, buf); } @@ -463,7 +470,7 @@ static ssize_t zr364xx_read(struct file *file, char __user *buf, size_t count, { struct zr364xx_camera *cam = video_drvdata(file); - DBG("%s\n", __func__); + _DBG("%s\n", __func__); if (!buf) return -EINVAL; @@ -583,7 +590,7 @@ static int zr364xx_read_video_callback(struct zr364xx_camera *cam, int i = 0; unsigned char *ptr = NULL; - /*DBG("buffer to user\n");*/ + _DBG("buffer to user\n"); idx = cam->cur_frame; frm = &cam->buffer.frame[idx]; @@ -601,12 +608,6 @@ static int zr364xx_read_video_callback(struct zr364xx_camera *cam, return -EINVAL; } - if (frm->lpvbits == NULL) { - DBG("%s: frame buffer == NULL.%p %p %d\n", __func__, - frm, cam, idx); - return -ENOMEM; - } - psrc = (u8 *)pipe_info->transfer_buffer; ptr = pdest = frm->lpvbits; @@ -614,7 +615,7 @@ static int zr364xx_read_video_callback(struct zr364xx_camera *cam, frm->ulState = ZR364XX_READ_FRAME; frm->cur_size = 0; - DBG("jpeg header, "); + _DBG("jpeg header, "); memcpy(ptr, header1, sizeof(header1)); ptr += sizeof(header1); header3 = 0; @@ -632,21 +633,28 @@ static int zr364xx_read_video_callback(struct zr364xx_camera *cam, memcpy(ptr, psrc + 128, purb->actual_length - 128); ptr += purb->actual_length - 128; - DBG("header : %d %d %d %d %d %d %d %d %d\n", + _DBG("header : %d %d %d %d %d %d %d %d %d\n", psrc[0], psrc[1], psrc[2], psrc[3], psrc[4], psrc[5], psrc[6], psrc[7], psrc[8]); frm->cur_size = ptr - pdest; } else { - pdest += frm->cur_size; - memcpy(pdest, psrc, purb->actual_length); - frm->cur_size += purb->actual_length; + if (frm->cur_size + purb->actual_length > MAX_FRAME_SIZE) { + dev_info(&cam->udev->dev, + "%s: buffer (%d bytes) too small to hold " + "frame data. Discarding frame data.\n", + __func__, MAX_FRAME_SIZE); + } else { + pdest += frm->cur_size; + memcpy(pdest, psrc, purb->actual_length); + frm->cur_size += purb->actual_length; + } } - /*DBG("cur_size %lu urb size %d\n", frm->cur_size, + /*_DBG("cur_size %lu urb size %d\n", frm->cur_size, purb->actual_length);*/ if (purb->actual_length < pipe_info->transfer_size) { - DBG("****************Buffer[%d]full*************\n", idx); + _DBG("****************Buffer[%d]full*************\n", idx); cam->last_frame = cam->cur_frame; cam->cur_frame++; /* end of system frame ring buffer, start at zero */ @@ -681,7 +689,7 @@ static int zr364xx_read_video_callback(struct zr364xx_camera *cam, if (cam->skip) cam->skip--; else { - DBG("jpeg(%lu): %d %d %d %d %d %d %d %d\n", + _DBG("jpeg(%lu): %d %d %d %d %d %d %d %d\n", frm->cur_size, pdest[0], pdest[1], pdest[2], pdest[3], pdest[4], pdest[5], pdest[6], pdest[7]); @@ -708,7 +716,7 @@ static int res_get(struct zr364xx_camera *cam) } /* it's free, grab it */ cam->resources = 1; - DBG("res: get\n"); + _DBG("res: get\n"); mutex_unlock(&cam->lock); return 1; } @@ -723,7 +731,7 @@ static void res_free(struct zr364xx_camera *cam) mutex_lock(&cam->lock); cam->resources = 0; mutex_unlock(&cam->lock); - DBG("res: put\n"); + _DBG("res: put\n"); } static int zr364xx_vidioc_querycap(struct file *file, void *priv, @@ -882,7 +890,6 @@ static int zr364xx_vidioc_try_fmt_vid_cap(struct file *file, void *priv, } f->fmt.pix.field = V4L2_FIELD_NONE; - f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; f->fmt.pix.bytesperline = f->fmt.pix.width * 2; f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline; f->fmt.pix.colorspace = 0; @@ -1018,7 +1025,7 @@ static int zr364xx_vidioc_qbuf(struct file *file, { int rc; struct zr364xx_camera *cam = video_drvdata(file); - DBG("%s\n", __func__); + _DBG("%s\n", __func__); rc = videobuf_qbuf(&cam->vb_vidq, p); return rc; } @@ -1029,7 +1036,7 @@ static int zr364xx_vidioc_dqbuf(struct file *file, { int rc; struct zr364xx_camera *cam = video_drvdata(file); - DBG("%s\n", __func__); + _DBG("%s\n", __func__); rc = videobuf_dqbuf(&cam->vb_vidq, p, file->f_flags & O_NONBLOCK); return rc; } @@ -1041,7 +1048,7 @@ static void read_pipe_completion(struct urb *purb) int pipe; pipe_info = purb->context; - /*DBG("%s %p, status %d\n", __func__, purb, purb->status);*/ + _DBG("%s %p, status %d\n", __func__, purb, purb->status); if (pipe_info == NULL) { printk(KERN_ERR KBUILD_MODNAME ": no context!\n"); return; @@ -1152,7 +1159,6 @@ static void zr364xx_stop_readpipe(struct zr364xx_camera *cam) pipe_info->stream_urb = NULL; } } - DBG("stop read pipe\n"); return; } @@ -1215,7 +1221,6 @@ static int zr364xx_vidioc_streamon(struct file *file, void *priv, } else { res_free(cam); } - DBG("%s: %d\n", __func__, res); return res; } @@ -1327,8 +1332,6 @@ static void zr364xx_destroy(struct zr364xx_camera *cam) /* release transfer buffer */ kfree(cam->pipe->transfer_buffer); cam->pipe->transfer_buffer = NULL; - - DBG("%s\n", __func__); mutex_unlock(&cam->open_lock); kfree(cam); cam = NULL; @@ -1409,7 +1412,7 @@ static unsigned int zr364xx_poll(struct file *file, { struct zr364xx_camera *cam = video_drvdata(file); struct videobuf_queue *q = &cam->vb_vidq; - DBG("%s\n", __func__); + _DBG("%s\n", __func__); if (cam->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) return POLLERR; -- cgit v1.2.3 From 72e561371a01666dd61a04af3cc6c0eac757f542 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Wed, 22 Jul 2009 22:20:50 +0200 Subject: pxa_camera: Fix Oops in pxa_camera_probe. From: Antonio Ospite mclk_get_divisor uses pcdev->soc_host.dev, make sure it is initialized. Priority: high Signed-off-by: Antonio Ospite Signed-off-by: Guennadi Liakhovetski --- drivers/media/video/pxa_camera.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) --- linux/drivers/media/video/pxa_camera.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/pxa_camera.c b/linux/drivers/media/video/pxa_camera.c index 8964d60cd..3f1b63e4e 100644 --- a/linux/drivers/media/video/pxa_camera.c +++ b/linux/drivers/media/video/pxa_camera.c @@ -1591,6 +1591,7 @@ static int __devinit pxa_camera_probe(struct platform_device *pdev) pcdev->mclk = 20000000; } + pcdev->soc_host.dev = &pdev->dev; pcdev->mclk_divisor = mclk_get_divisor(pcdev); INIT_LIST_HEAD(&pcdev->capture); @@ -1656,7 +1657,6 @@ static int __devinit pxa_camera_probe(struct platform_device *pdev) pcdev->soc_host.drv_name = PXA_CAM_DRV_NAME; pcdev->soc_host.ops = &pxa_soc_camera_host_ops; pcdev->soc_host.priv = pcdev; - pcdev->soc_host.dev = &pdev->dev; pcdev->soc_host.nr = pdev->id; err = soc_camera_host_register(&pcdev->soc_host); -- cgit v1.2.3 From 0c962c2acd61e781501914a4b96fd47a707bccc5 Mon Sep 17 00:00:00 2001 From: "Igor M. Liplianin" Date: Wed, 22 Jul 2009 23:30:25 +0300 Subject: Create card parameters array in SDMC DM1105 driver. From: Igor M. Liplianin Create card parameters array in SDMC DM1105 driver. It is useful for cards with the same pci id, but different tuners, lnb power control circuits, etc. Signed-off-by: Igor M. Liplianin --- linux/drivers/media/dvb/dm1105/dm1105.c | 148 ++++++++++++++++++++++++++++---- 1 file changed, 133 insertions(+), 15 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/dm1105/dm1105.c b/linux/drivers/media/dvb/dm1105/dm1105.c index 17edeb66b..f937151b3 100644 --- a/linux/drivers/media/dvb/dm1105/dm1105.c +++ b/linux/drivers/media/dvb/dm1105/dm1105.c @@ -44,6 +44,14 @@ #include "cx24116.h" #include "z0194a.h" +#define UNSET (-1U) + +#define DM1105_BOARD_NOAUTO UNSET +#define DM1105_BOARD_UNKNOWN 0 +#define DM1105_BOARD_DVBWORLD_2002 1 +#define DM1105_BOARD_DVBWORLD_2004 2 +#define DM1105_BOARD_AXESS_DM05 3 + /* ----------------------------------------------- */ /* * PCI ID's @@ -153,20 +161,105 @@ /* GPIO's for LNB power control */ #define DM1105_LNB_MASK 0x00000000 +#define DM1105_LNB_OFF 0x00020000 #define DM1105_LNB_13V 0x00010100 #define DM1105_LNB_18V 0x00000100 /* GPIO's for LNB power control for Axess DM05 */ #define DM05_LNB_MASK 0x00000000 +#define DM05_LNB_OFF 0x00020000/* actually 13v */ #define DM05_LNB_13V 0x00020000 #define DM05_LNB_18V 0x00030000 +static unsigned int card[] = {[0 ... 3] = UNSET }; +module_param_array(card, int, NULL, 0444); +MODULE_PARM_DESC(card, "card type"); + static int ir_debug; module_param(ir_debug, int, 0644); MODULE_PARM_DESC(ir_debug, "enable debugging information for IR decoding"); +static unsigned int dm1105_devcount; + DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); +struct dm1105_board { + char *name; +}; + +struct dm1105_subid { + u16 subvendor; + u16 subdevice; + u32 card; +}; + +static const struct dm1105_board dm1105_boards[] = { + [DM1105_BOARD_UNKNOWN] = { + .name = "UNKNOWN/GENERIC", + }, + [DM1105_BOARD_DVBWORLD_2002] = { + .name = "DVBWorld PCI 2002", + }, + [DM1105_BOARD_DVBWORLD_2004] = { + .name = "DVBWorld PCI 2004", + }, + [DM1105_BOARD_AXESS_DM05] = { + .name = "Axess/EasyTv DM05", + }, +}; + +static const struct dm1105_subid dm1105_subids[] = { + { + .subvendor = 0x0000, + .subdevice = 0x2002, + .card = DM1105_BOARD_DVBWORLD_2002, + }, { + .subvendor = 0x0001, + .subdevice = 0x2002, + .card = DM1105_BOARD_DVBWORLD_2002, + }, { + .subvendor = 0x0000, + .subdevice = 0x2004, + .card = DM1105_BOARD_DVBWORLD_2004, + }, { + .subvendor = 0x0001, + .subdevice = 0x2004, + .card = DM1105_BOARD_DVBWORLD_2004, + }, { + .subvendor = 0x195d, + .subdevice = 0x1105, + .card = DM1105_BOARD_AXESS_DM05, + }, +}; + +static void dm1105_card_list(struct pci_dev *pci) +{ + int i; + + if (0 == pci->subsystem_vendor && + 0 == pci->subsystem_device) { + printk(KERN_ERR + "dm1105: Your board has no valid PCI Subsystem ID\n" + "dm1105: and thus can't be autodetected\n" + "dm1105: Please pass card= insmod option to\n" + "dm1105: workaround that. Redirect complaints to\n" + "dm1105: the vendor of the TV card. Best regards,\n" + "dm1105: -- tux\n"); + } else { + printk(KERN_ERR + "dm1105: Your board isn't known (yet) to the driver.\n" + "dm1105: You can try to pick one of the existing\n" + "dm1105: card configs via card= insmod option.\n" + "dm1105: Updating to the latest version might help\n" + "dm1105: as well.\n"); + } + printk(KERN_ERR "Here is a list of valid choices for the card= " + "insmod option:\n"); + for (i = 0; i < ARRAY_SIZE(dm1105_boards); i++) + printk(KERN_ERR "dm1105: card=%d -> %s\n", + i, dm1105_boards[i].name); +} + /* infrared remote control */ struct infrared { struct input_dev *input_dev; @@ -193,6 +286,8 @@ struct dm1105dvb { struct dvb_frontend *fe; struct dvb_net dvbnet; unsigned int full_ts_users; + unsigned int boardnr; + int nr; /* i2c */ struct i2c_adapter i2c_adap; @@ -211,7 +306,6 @@ struct dm1105dvb { unsigned int PacketErrorCount; unsigned int dmarst; spinlock_t lock; - }; #define dm_io_mem(reg) ((unsigned long)(&dm1105dvb->io_mem[reg])) @@ -329,16 +423,20 @@ static inline struct dm1105dvb *frontend_to_dm1105dvb(struct dvb_frontend *fe) static int dm1105dvb_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) { struct dm1105dvb *dm1105dvb = frontend_to_dm1105dvb(fe); - u32 lnb_mask, lnb_13v, lnb_18v; + u32 lnb_mask, lnb_13v, lnb_18v, lnb_off; - switch (dm1105dvb->pdev->subsystem_device) { - case PCI_DEVICE_ID_DM05: + switch (dm1105dvb->boardnr) { + case DM1105_BOARD_AXESS_DM05: lnb_mask = DM05_LNB_MASK; + lnb_off = DM05_LNB_OFF; lnb_13v = DM05_LNB_13V; lnb_18v = DM05_LNB_18V; break; + case DM1105_BOARD_DVBWORLD_2002: + case DM1105_BOARD_DVBWORLD_2004: default: lnb_mask = DM1105_LNB_MASK; + lnb_off = DM1105_LNB_OFF; lnb_13v = DM1105_LNB_13V; lnb_18v = DM1105_LNB_18V; } @@ -346,8 +444,10 @@ static int dm1105dvb_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t volta outl(lnb_mask, dm_io_mem(DM1105_GPIOCTR)); if (voltage == SEC_VOLTAGE_18) outl(lnb_18v , dm_io_mem(DM1105_GPIOVAL)); - else + else if (voltage == SEC_VOLTAGE_13) outl(lnb_13v, dm_io_mem(DM1105_GPIOVAL)); + else + outl(lnb_off, dm_io_mem(DM1105_GPIOVAL)); return 0; } @@ -621,8 +721,8 @@ static int __devinit frontend_init(struct dm1105dvb *dm1105dvb) { int ret; - switch (dm1105dvb->pdev->subsystem_device) { - case PCI_DEVICE_ID_DW2004: + switch (dm1105dvb->boardnr) { + case DM1105_BOARD_DVBWORLD_2004: dm1105dvb->fe = dvb_attach( cx24116_attach, &serit_sp2633_config, &dm1105dvb->i2c_adap); @@ -630,6 +730,8 @@ static int __devinit frontend_init(struct dm1105dvb *dm1105dvb) dm1105dvb->fe->ops.set_voltage = dm1105dvb_set_voltage; break; + case DM1105_BOARD_DVBWORLD_2002: + case DM1105_BOARD_AXESS_DM05: default: dm1105dvb->fe = dvb_attach( stv0299_attach, &sharp_z0194a_config, @@ -708,11 +810,31 @@ static int __devinit dm1105_probe(struct pci_dev *pdev, struct dvb_demux *dvbdemux; struct dmx_demux *dmx; int ret = -ENOMEM; + int i; dm1105dvb = kzalloc(sizeof(struct dm1105dvb), GFP_KERNEL); if (!dm1105dvb) return -ENOMEM; + /* board config */ + dm1105dvb->nr = dm1105_devcount; + dm1105dvb->boardnr = UNSET; + if (card[dm1105dvb->nr] < ARRAY_SIZE(dm1105_boards)) + dm1105dvb->boardnr = card[dm1105dvb->nr]; + for (i = 0; UNSET == dm1105dvb->boardnr && + i < ARRAY_SIZE(dm1105_subids); i++) + if (pdev->subsystem_vendor == + dm1105_subids[i].subvendor && + pdev->subsystem_device == + dm1105_subids[i].subdevice) + dm1105dvb->boardnr = dm1105_subids[i].card; + + if (UNSET == dm1105dvb->boardnr) { + dm1105dvb->boardnr = DM1105_BOARD_UNKNOWN; + dm1105_card_list(pdev); + } + + dm1105_devcount++; dm1105dvb->pdev = pdev; dm1105dvb->buffer_size = 5 * DM1105_DMA_BYTES; dm1105dvb->PacketErrorCount = 0; @@ -889,6 +1011,7 @@ static void __devexit dm1105_remove(struct pci_dev *pdev) pci_release_regions(pdev); pci_disable_device(pdev); pci_set_drvdata(pdev, NULL); + dm1105_devcount--; kfree(dm1105dvb); } @@ -897,17 +1020,12 @@ static struct pci_device_id dm1105_id_table[] __devinitdata = { .vendor = PCI_VENDOR_ID_TRIGEM, .device = PCI_DEVICE_ID_DM1105, .subvendor = PCI_ANY_ID, - .subdevice = PCI_DEVICE_ID_DW2002, - }, { - .vendor = PCI_VENDOR_ID_TRIGEM, - .device = PCI_DEVICE_ID_DM1105, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_DEVICE_ID_DW2004, + .subdevice = PCI_ANY_ID, }, { .vendor = PCI_VENDOR_ID_AXESS, .device = PCI_DEVICE_ID_DM05, - .subvendor = PCI_VENDOR_ID_AXESS, - .subdevice = PCI_DEVICE_ID_DM05, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, }, { /* empty */ }, -- cgit v1.2.3 From f28ced8b3b15803ed5c0d99c29aaa51c4153e842 Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Wed, 22 Jul 2009 20:02:44 -0400 Subject: tuner-simple: Add an entry for the Partsnic PTI-5NF05 NTSC tuner From: Andy Walls Priority: normal Signed-off-by: Andy Walls --- linux/drivers/media/common/tuners/tuner-types.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/common/tuners/tuner-types.c b/linux/drivers/media/common/tuners/tuner-types.c index e57d7cb2f..c4bbb460a 100644 --- a/linux/drivers/media/common/tuners/tuner-types.c +++ b/linux/drivers/media/common/tuners/tuner-types.c @@ -1302,6 +1302,25 @@ static struct tuner_params tuner_fq1216lme_mk3_params[] = { }, }; +/* ----- TUNER_PARTSNIC_PTI_5NF05 - Partsnic (Daewoo) PTI-5NF05 NTSC ----- */ + +static struct tuner_range tuner_partsnic_pti_5nf05_ranges[] = { + /* The datasheet specified channel ranges and the bandswitch byte */ + /* The control byte value of 0x8e is just a guess */ + { 16 * 133.25 /*MHz*/, 0x8e, 0x01, }, /* Channels 2 - B */ + { 16 * 367.25 /*MHz*/, 0x8e, 0x02, }, /* Channels C - W+11 */ + { 16 * 999.99 , 0x8e, 0x08, }, /* Channels W+12 - 69 */ +}; + +static struct tuner_params tuner_partsnic_pti_5nf05_params[] = { + { + .type = TUNER_PARAM_TYPE_NTSC, + .ranges = tuner_partsnic_pti_5nf05_ranges, + .count = ARRAY_SIZE(tuner_partsnic_pti_5nf05_ranges), + .cb_first_if_lower_freq = 1, /* not specified but safe to do */ + }, +}; + /* --------------------------------------------------------------------- */ struct tunertype tuners[] = { @@ -1754,6 +1773,12 @@ struct tunertype tuners[] = { .params = tuner_fq1216lme_mk3_params, .count = ARRAY_SIZE(tuner_fq1216lme_mk3_params), }, + + [TUNER_PARTSNIC_PTI_5NF05] = { + .name = "Partsnic (Daewoo) PTI-5NF05", + .params = tuner_partsnic_pti_5nf05_params, + .count = ARRAY_SIZE(tuner_partsnic_pti_5nf05_params), + }, }; EXPORT_SYMBOL(tuners); -- cgit v1.2.3 From 97c94bc15d7a898a7061e5655947214479655a20 Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Wed, 22 Jul 2009 20:15:58 -0400 Subject: ivtv: Fix errors in AVerTV M113 card definitions and add a new M113 card From: Andy Walls Priority: normal Tested-by: Ravi A. Signed-off-by: Andy Walls --- linux/drivers/media/video/ivtv/ivtv-cards.c | 33 +++++++++++++++++------------ 1 file changed, 19 insertions(+), 14 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/ivtv/ivtv-cards.c b/linux/drivers/media/video/ivtv/ivtv-cards.c index 40c29032f..4873b6ca5 100644 --- a/linux/drivers/media/video/ivtv/ivtv-cards.c +++ b/linux/drivers/media/video/ivtv/ivtv-cards.c @@ -977,26 +977,27 @@ static const struct ivtv_card ivtv_card_avertv_mce116 = { /* ------------------------------------------------------------------------- */ -/* AVerMedia PVR-150 Plus (M113) card */ +/* AVerMedia PVR-150 Plus / AVerTV M113 cards with a Daewoo/Partsnic Tuner */ static const struct ivtv_card_pci_info ivtv_pci_aver_pvr150[] = { - { PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_AVERMEDIA, 0xc035 }, + { PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_AVERMEDIA, 0xc034 }, /* NTSC */ + { PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_AVERMEDIA, 0xc035 }, /* NTSC FM */ { 0, 0, 0 } }; static const struct ivtv_card ivtv_card_aver_pvr150 = { .type = IVTV_CARD_AVER_PVR150PLUS, - .name = "AVerMedia PVR-150 Plus", + .name = "AVerMedia PVR-150 Plus / AVerTV M113 Partsnic (Daewoo) Tuner", .v4l2_capabilities = IVTV_CAP_ENCODER, .hw_video = IVTV_HW_CX25840, .hw_audio = IVTV_HW_CX25840, .hw_audio_ctrl = IVTV_HW_CX25840, .hw_muxer = IVTV_HW_GPIO, - .hw_all = IVTV_HW_CX25840 | IVTV_HW_TUNER, + .hw_all = IVTV_HW_CX25840 | IVTV_HW_TUNER | + IVTV_HW_WM8739 | IVTV_HW_GPIO, .video_inputs = { { IVTV_CARD_INPUT_VID_TUNER, 0, CX25840_COMPOSITE2 }, - { IVTV_CARD_INPUT_SVIDEO1, 1, - CX25840_SVIDEO_LUMA3 | CX25840_SVIDEO_CHROMA4 }, + { IVTV_CARD_INPUT_SVIDEO1, 1, CX25840_SVIDEO3 }, { IVTV_CARD_INPUT_COMPOSITE1, 1, CX25840_COMPOSITE1 }, }, .audio_inputs = { @@ -1004,13 +1005,18 @@ static const struct ivtv_card ivtv_card_aver_pvr150 = { { IVTV_CARD_INPUT_LINE_IN1, CX25840_AUDIO_SERIAL, 1 }, }, .radio_input = { IVTV_CARD_INPUT_AUD_TUNER, CX25840_AUDIO_SERIAL, 2 }, - .gpio_init = { .direction = 0x0800, .initial_value = 0 }, - .gpio_audio_input = { .mask = 0x0800, .tuner = 0, .linein = 0, .radio = 0x0800 }, + /* The 74HC4052 Dual 4:1 multiplexer is controlled by 2 GPIO lines */ + .gpio_init = { .direction = 0xc000, .initial_value = 0 }, + .gpio_audio_input = { .mask = 0xc000, + .tuner = 0x0000, + .linein = 0x4000, + .radio = 0x8000 }, .tuners = { - /* This card has a Partsnic PTI-5NF05 tuner */ - { .std = V4L2_STD_MN, .tuner = TUNER_TCL_2002N }, + /* Subsystem ID's 0xc03[45] have a Partsnic PTI-5NF05 tuner */ + { .std = V4L2_STD_MN, .tuner = TUNER_PARTSNIC_PTI_5NF05 }, }, .pci_list = ivtv_pci_aver_pvr150, + /* Subsystem ID 0xc035 has a TEA5767(?) FM tuner, 0xc034 does not */ .i2c = &ivtv_i2c_radio, }; @@ -1025,7 +1031,7 @@ static const struct ivtv_card_pci_info ivtv_pci_aver_ultra1500mce[] = { static const struct ivtv_card ivtv_card_aver_ultra1500mce = { .type = IVTV_CARD_AVER_ULTRA1500MCE, - .name = "AVerMedia UltraTV 1500 MCE / AVerTV M113", + .name = "AVerMedia UltraTV 1500 MCE / AVerTV M113 Philips Tuner", .v4l2_capabilities = IVTV_CAP_ENCODER, .hw_video = IVTV_HW_CX25840, .hw_audio = IVTV_HW_CX25840, @@ -1035,8 +1041,7 @@ static const struct ivtv_card ivtv_card_aver_ultra1500mce = { IVTV_HW_WM8739 | IVTV_HW_GPIO, .video_inputs = { { IVTV_CARD_INPUT_VID_TUNER, 0, CX25840_COMPOSITE2 }, - { IVTV_CARD_INPUT_SVIDEO1, 1, - CX25840_SVIDEO_LUMA3 | CX25840_SVIDEO_CHROMA4 }, + { IVTV_CARD_INPUT_SVIDEO1, 1, CX25840_SVIDEO3 }, { IVTV_CARD_INPUT_COMPOSITE1, 1, CX25840_COMPOSITE1 }, }, .audio_inputs = { @@ -1044,7 +1049,7 @@ static const struct ivtv_card ivtv_card_aver_ultra1500mce = { { IVTV_CARD_INPUT_LINE_IN1, CX25840_AUDIO_SERIAL, 1 }, }, .radio_input = { IVTV_CARD_INPUT_AUD_TUNER, CX25840_AUDIO_SERIAL, 2 }, - /* The 74HC4502 Dual 4:1 multiplexer is controlled by 2 GPIO lines */ + /* The 74HC4052 Dual 4:1 multiplexer is controlled by 2 GPIO lines */ .gpio_init = { .direction = 0xc000, .initial_value = 0 }, .gpio_audio_input = { .mask = 0xc000, .tuner = 0x0000, -- cgit v1.2.3 From f1fdde7178e4aee3df0e79c6c181d16e75776343 Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Wed, 22 Jul 2009 20:24:53 -0400 Subject: ivtv: Fix improper GPIO audio mux input switch on video standard change From: Andy Walls Remove the subdev_s_std() method from the GPIO subdev. It appears it was used in the past to effect the switch back from radio mode to tuner mode, but it had a side effect that is improper and against the V4L2 spec, when you were not in radio mode. Whenever the video stanadrd was changed, the GPIO audio mux was set back to the tuner audio input, even if you were set to a Line In input. Thanks to Ravi A. for doing the troubleshooting to point me right to the problem. Reported-by: Ravi A Priority: normal Signed-off-by: Andy Walls --- linux/drivers/media/video/ivtv/ivtv-gpio.c | 13 ------------- 1 file changed, 13 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/ivtv/ivtv-gpio.c b/linux/drivers/media/video/ivtv/ivtv-gpio.c index 85ac70722..aede061ca 100644 --- a/linux/drivers/media/video/ivtv/ivtv-gpio.c +++ b/linux/drivers/media/video/ivtv/ivtv-gpio.c @@ -236,18 +236,6 @@ static int subdev_s_radio(struct v4l2_subdev *sd) return 0; } -static int subdev_s_std(struct v4l2_subdev *sd, v4l2_std_id std) -{ - struct ivtv *itv = sd_to_ivtv(sd); - u16 mask, data; - - mask = itv->card->gpio_audio_input.mask; - data = itv->card->gpio_audio_input.tuner; - if (mask) - write_reg((read_reg(IVTV_REG_GPIO_OUT) & ~mask) | (data & mask), IVTV_REG_GPIO_OUT); - return 0; -} - static int subdev_s_audio_routing(struct v4l2_subdev *sd, u32 input, u32 output, u32 config) { @@ -344,7 +332,6 @@ static const struct v4l2_subdev_core_ops subdev_core_ops = { .g_ctrl = subdev_g_ctrl, .s_ctrl = subdev_s_ctrl, .queryctrl = subdev_queryctrl, - .s_std = subdev_s_std, }; static const struct v4l2_subdev_tuner_ops subdev_tuner_ops = { -- cgit v1.2.3 From d4d9fba26b4460171132eb9f8dad28fc4ae8fca4 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Thu, 23 Jul 2009 10:55:43 +0200 Subject: gspca - sn9c20x: Misc fixes. From: Brian Johnson * use i2c_w instead of reg_w * return error on failure * read the correct number of bytes Priority: normal Signed-off-by: Brian Johnson Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/sn9c20x.c | 38 ++++++++++++++++--------------- 1 file changed, 20 insertions(+), 18 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/sn9c20x.c b/linux/drivers/media/video/gspca/sn9c20x.c index a516866a2..fc47f978e 100644 --- a/linux/drivers/media/video/gspca/sn9c20x.c +++ b/linux/drivers/media/video/gspca/sn9c20x.c @@ -1099,12 +1099,12 @@ int i2c_w(struct gspca_dev *gspca_dev, const u8 *buffer) reg_r(gspca_dev, 0x10c0, 1); if (gspca_dev->usb_buf[0] & 0x04) { if (gspca_dev->usb_buf[0] & 0x08) - return -1; + return -EIO; return 0; } msleep(1); } - return -1; + return -EIO; } int i2c_w1(struct gspca_dev *gspca_dev, u8 reg, u8 val) @@ -1155,7 +1155,7 @@ int i2c_r1(struct gspca_dev *gspca_dev, u8 reg, u8 *val) struct sd *sd = (struct sd *) gspca_dev; u8 row[8]; - row[0] = 0x81 | 0x10; + row[0] = 0x81 | (1 << 4); row[1] = sd->i2c_addr; row[2] = reg; row[3] = 0; @@ -1163,14 +1163,15 @@ int i2c_r1(struct gspca_dev *gspca_dev, u8 reg, u8 *val) row[5] = 0; row[6] = 0; row[7] = 0x10; - reg_w(gspca_dev, 0x10c0, row, 8); - msleep(1); - row[0] = 0x81 | (2 << 4) | 0x02; + if (i2c_w(gspca_dev, row) < 0) + return -EIO; + row[0] = 0x81 | (1 << 4) | 0x02; row[2] = 0; - reg_w(gspca_dev, 0x10c0, row, 8); - msleep(1); - reg_r(gspca_dev, 0x10c2, 5); - *val = gspca_dev->usb_buf[3]; + if (i2c_w(gspca_dev, row) < 0) + return -EIO; + if (reg_r(gspca_dev, 0x10c2, 5) < 0) + return -EIO; + *val = gspca_dev->usb_buf[4]; return 0; } @@ -1179,7 +1180,7 @@ int i2c_r2(struct gspca_dev *gspca_dev, u8 reg, u16 *val) struct sd *sd = (struct sd *) gspca_dev; u8 row[8]; - row[0] = 0x81 | 0x10; + row[0] = 0x81 | (1 << 4); row[1] = sd->i2c_addr; row[2] = reg; row[3] = 0; @@ -1187,14 +1188,15 @@ int i2c_r2(struct gspca_dev *gspca_dev, u8 reg, u16 *val) row[5] = 0; row[6] = 0; row[7] = 0x10; - reg_w(gspca_dev, 0x10c0, row, 8); - msleep(1); - row[0] = 0x81 | (3 << 4) | 0x02; + if (i2c_w(gspca_dev, row) < 0) + return -EIO; + row[0] = 0x81 | (2 << 4) | 0x02; row[2] = 0; - reg_w(gspca_dev, 0x10c0, row, 8); - msleep(1); - reg_r(gspca_dev, 0x10c2, 5); - *val = (gspca_dev->usb_buf[2] << 8) | gspca_dev->usb_buf[3]; + if (i2c_w(gspca_dev, row) < 0) + return -EIO; + if (reg_r(gspca_dev, 0x10c2, 5) < 0) + return -EIO; + *val = (gspca_dev->usb_buf[3] << 8) | gspca_dev->usb_buf[4]; return 0; } -- cgit v1.2.3 From e568b608a89f187c88cbbff8149047e16754aec7 Mon Sep 17 00:00:00 2001 From: Steven Toth Date: Thu, 23 Jul 2009 11:18:54 -0400 Subject: cx25840: Bugfix for no DVB-T on the Hauppauge HVR-1700 From: Steven Toth After the i2c subdev changes the ordering of initialization changed, causing a total loss of previous GPIO settings and a loss of DTV. The generic firmware loading routine has now changed to preserve GPIO values if the device is cx23885 based (safety) and I've moved the GPIO configuration from probe() into the cx23885 init func which is a little clearer and fixes the bug. Priority: normal Tested-By: Sohail Syyed Reviewed-by: Michael Krufky Signed-off-by: Steven Toth --- linux/drivers/media/video/cx25840/cx25840-core.c | 15 +++++++++------ linux/drivers/media/video/cx25840/cx25840-firmware.c | 13 ++++++++++++- 2 files changed, 21 insertions(+), 7 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/cx25840/cx25840-core.c b/linux/drivers/media/video/cx25840/cx25840-core.c index 2929bf3b7..557a3eaa1 100644 --- a/linux/drivers/media/video/cx25840/cx25840-core.c +++ b/linux/drivers/media/video/cx25840/cx25840-core.c @@ -341,6 +341,15 @@ static void cx23885_initialize(struct i2c_client *client) /* Select AFE clock pad output source */ cx25840_write(client, 0x144, 0x05); + /* Drive GPIO2 direction and values for HVR1700 + * where an onboard mux selects the output of demodulator + * vs the 417. Failure to set this results in no DTV. + * It's safe to set this across all Hauppauge boards + * currently, regardless of the board type. + */ + cx25840_write(client, 0x160, 0x1d); + cx25840_write(client, 0x164, 0x00); + /* Do the firmware load in a work handler to prevent. Otherwise the kernel is blocked waiting for the bit-banging i2c interface to finish uploading the @@ -1610,12 +1619,6 @@ static int cx25840_probe(struct i2c_client *client, state->id = id; state->rev = device_id; - if (state->is_cx23885) { - /* Drive GPIO2 direction and values */ - cx25840_write(client, 0x160, 0x1d); - cx25840_write(client, 0x164, 0x00); - } - return 0; } diff --git a/linux/drivers/media/video/cx25840/cx25840-firmware.c b/linux/drivers/media/video/cx25840/cx25840-firmware.c index f01456ec4..bdc630f0f 100644 --- a/linux/drivers/media/video/cx25840/cx25840-firmware.c +++ b/linux/drivers/media/video/cx25840/cx25840-firmware.c @@ -99,9 +99,14 @@ int cx25840_loadfw(struct i2c_client *client) const u8 *ptr; int size, retval; int MAX_BUF_SIZE = FWSEND; + u32 gpio_oe = 0, gpio_da = 0; - if (state->is_cx23885) + if (state->is_cx23885) { firmware = FWFILE_CX23885; + /* Preserve the GPIO OE and output bits */ + gpio_oe = cx25840_read(client, 0x160); + gpio_da = cx25840_read(client, 0x164); + } else if (state->is_cx231xx) firmware = FWFILE_CX231XX; @@ -143,5 +148,11 @@ int cx25840_loadfw(struct i2c_client *client) size = fw->size; release_firmware(fw); + if (state->is_cx23885) { + /* Restore GPIO configuration after f/w load */ + cx25840_write(client, 0x160, gpio_oe); + cx25840_write(client, 0x164, gpio_da); + } + return check_fw_load(client, size); } -- cgit v1.2.3 From f1f1d841250e56e65222123f52c87e33f58d2e87 Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Thu, 23 Jul 2009 20:46:57 -0400 Subject: ivtv: Read buffer overflow From: Roel Kluin This mistakenly tests against sizeof(freqs) instead of the array size. Due to the mask the only illegal value possible was 3. Priority: high Signed-off-by: Roel Kluin Signed-off-by: Andy Walls --- linux/drivers/media/video/ivtv/ivtv-controls.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/ivtv/ivtv-controls.c b/linux/drivers/media/video/ivtv/ivtv-controls.c index a3b77ed3f..4a9c8ce0e 100644 --- a/linux/drivers/media/video/ivtv/ivtv-controls.c +++ b/linux/drivers/media/video/ivtv/ivtv-controls.c @@ -17,6 +17,7 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#include #include "ivtv-driver.h" #include "ivtv-cards.h" @@ -281,7 +282,7 @@ int ivtv_s_ext_ctrls(struct file *file, void *fh, struct v4l2_ext_controls *c) idx = p.audio_properties & 0x03; /* The audio clock of the digitizer must match the codec sample rate otherwise you get some very strange effects. */ - if (idx < sizeof(freqs)) + if (idx < ARRAY_SIZE(freqs)) ivtv_call_all(itv, audio, s_clock_freq, freqs[idx]); return err; } -- cgit v1.2.3 From 54a9310128f01c9c97607d99f52ced91e050e834 Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Thu, 23 Jul 2009 20:51:29 -0400 Subject: cx18: Read buffer overflow From: Andy Walls This mistakenly tested against sizeof(freqs) instead of the array size. Due to the mask the only illegal value possible was 3. Reported-by: Roel Kluin Priority: high Signed-off-by: Andy Walls --- linux/drivers/media/video/cx18/cx18-controls.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/cx18/cx18-controls.c b/linux/drivers/media/video/cx18/cx18-controls.c index 5136df198..93f0dae01 100644 --- a/linux/drivers/media/video/cx18/cx18-controls.c +++ b/linux/drivers/media/video/cx18/cx18-controls.c @@ -20,6 +20,7 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * 02111-1307 USA */ +#include #include "cx18-driver.h" #include "cx18-cards.h" @@ -317,7 +318,7 @@ int cx18_s_ext_ctrls(struct file *file, void *fh, struct v4l2_ext_controls *c) idx = p.audio_properties & 0x03; /* The audio clock of the digitizer must match the codec sample rate otherwise you get some very strange effects. */ - if (idx < sizeof(freqs)) + if (idx < ARRAY_SIZE(freqs)) cx18_call_all(cx, audio, s_clock_freq, freqs[idx]); return err; } -- cgit v1.2.3 From 54165c372c7e8c065545a4916acef9b54786f8c0 Mon Sep 17 00:00:00 2001 From: Steven Toth Date: Sun, 26 Jul 2009 10:06:20 -0400 Subject: cx88: HVR1300 ensure switching from Encoder to DVB-T and back is reliable From: Sohail Syyed Current tip is broken and does not switch back to DVB-T correctly Priority: high Signed-off-by: Sohail Syyed Signed-off-by: Steven Toth --- linux/drivers/media/video/cx88/cx88-mpeg.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/cx88/cx88-mpeg.c b/linux/drivers/media/video/cx88/cx88-mpeg.c index ba083d249..e1bcd556b 100644 --- a/linux/drivers/media/video/cx88/cx88-mpeg.c +++ b/linux/drivers/media/video/cx88/cx88-mpeg.c @@ -129,6 +129,10 @@ static int cx8802_start_dma(struct cx8802_dev *dev, udelay(100); break; case CX88_BOARD_HAUPPAUGE_HVR1300: + /* Enable MPEG parallel IO and video signal pins */ + cx_write(MO_PINMUX_IO, 0x88); + cx_write(TS_SOP_STAT, 0); + cx_write(TS_VALERR_CNTRL, 0); break; case CX88_BOARD_PINNACLE_PCTV_HD_800i: /* Enable MPEG parallel IO and video signal pins */ -- cgit v1.2.3 From edb37f2afad7a2b06f7df8873a4b4c991924a280 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Mon, 27 Jul 2009 10:43:55 +0200 Subject: gspca - vc032x: Fix mi1310_soc preview and LED. From: AceLan Kao The patches gspca - vc032x: Add resolution 1280x1024 for sensor mi1310_soc. gspca - vc032x: Webcam 041e:405b added and mi1310_soc updated. will make the preview function not work, so I disable the 1280x1024 resolution and revert back to the origin mi1310_soc settings. And, using USB snoop tool on Windows to get the correct i2c commands to turn on/off the LED flash. Priority: normal Signed-off-by: AceLan Kao Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/vc032x.c | 397 ++++++++++++++++--------------- 1 file changed, 205 insertions(+), 192 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/vc032x.c b/linux/drivers/media/video/gspca/vc032x.c index d8d2c5dc7..85cb790fc 100644 --- a/linux/drivers/media/video/gspca/vc032x.c +++ b/linux/drivers/media/video/gspca/vc032x.c @@ -446,208 +446,92 @@ static const __u8 mi0360_initQVGA_JPG[][4] = { static const __u8 mi1310_socinitVGA_JPG[][4] = { {0xb0, 0x03, 0x19, 0xcc}, {0xb0, 0x04, 0x02, 0xcc}, - {0xb3, 0x00, 0x24, 0xcc}, - {0xb3, 0x00, 0x25, 0xcc}, - {0xb3, 0x05, 0x01, 0xcc}, - {0xb3, 0x06, 0x03, 0xcc}, - {0xb3, 0x5c, 0x01, 0xcc}, + {0xb3, 0x00, 0x64, 0xcc}, + {0xb3, 0x00, 0x65, 0xcc}, + {0xb3, 0x05, 0x00, 0xcc}, + {0xb3, 0x06, 0x00, 0xcc}, {0xb3, 0x08, 0x01, 0xcc}, {0xb3, 0x09, 0x0c, 0xcc}, {0xb3, 0x34, 0x02, 0xcc}, {0xb3, 0x35, 0xdd, 0xcc}, + {0xb3, 0x02, 0x00, 0xcc}, {0xb3, 0x03, 0x0a, 0xcc}, - {0xb3, 0x04, 0x0d, 0xcc}, + {0xb3, 0x04, 0x05, 0xcc}, {0xb3, 0x20, 0x00, 0xcc}, {0xb3, 0x21, 0x00, 0xcc}, - {0xb3, 0x22, 0x01, 0xcc}, - {0xb3, 0x23, 0xe0, 0xcc}, + {0xb3, 0x22, 0x03, 0xcc}, + {0xb3, 0x23, 0xc0, 0xcc}, {0xb3, 0x14, 0x00, 0xcc}, {0xb3, 0x15, 0x00, 0xcc}, - {0xb3, 0x16, 0x02, 0xcc}, - {0xb3, 0x17, 0x7f, 0xcc}, - {0xb8, 0x01, 0x7d, 0xcc}, - {0xb8, 0x81, 0x09, 0xcc}, - {0xb8, 0x27, 0x20, 0xcc}, - {0xb8, 0x26, 0x80, 0xcc}, - {0xb3, 0x00, 0x25, 0xcc}, - {0xb8, 0x00, 0x13, 0xcc}, - {0xbc, 0x00, 0x71, 0xcc}, - {0xb8, 0x81, 0x01, 0xcc}, - {0xb8, 0x2c, 0x5a, 0xcc}, - {0xb8, 0x2d, 0xff, 0xcc}, - {0xb8, 0x2e, 0xee, 0xcc}, - {0xb8, 0x2f, 0xfb, 0xcc}, - {0xb8, 0x30, 0x52, 0xcc}, - {0xb8, 0x31, 0xf8, 0xcc}, - {0xb8, 0x32, 0xf1, 0xcc}, - {0xb8, 0x33, 0xff, 0xcc}, - {0xb8, 0x34, 0x54, 0xcc}, - {0xb8, 0x35, 0x00, 0xcc}, - {0xb8, 0x36, 0x00, 0xcc}, - {0xb8, 0x37, 0x00, 0xcc}, + {0xb3, 0x16, 0x04, 0xcc}, + {0xb3, 0x17, 0xff, 0xcc}, + {0xb3, 0x00, 0x65, 0xcc}, + {0xb8, 0x00, 0x00, 0xcc}, + {0xbc, 0x00, 0xd0, 0xcc}, + {0xbc, 0x01, 0x01, 0xcc}, + {0xf0, 0x00, 0x02, 0xbb}, + {0xc8, 0x9f, 0x0b, 0xbb}, + {0x5b, 0x00, 0x01, 0xbb}, + {0x2f, 0xde, 0x20, 0xbb}, {0xf0, 0x00, 0x00, 0xbb}, - {0x00, 0x01, 0x00, 0xdd}, - {0x0d, 0x00, 0x09, 0xbb}, - {0x0d, 0x00, 0x08, 0xbb}, + {0x20, 0x03, 0x02, 0xbb}, {0xf0, 0x00, 0x01, 0xbb}, - {0x00, 0x01, 0x00, 0xdd}, - {0x06, 0x00, 0x14, 0xbb}, - {0x3a, 0x10, 0x00, 0xbb}, - {0x00, 0x00, 0x10, 0xdd}, - {0x9b, 0x10, 0x00, 0xbb}, - {0x00, 0x00, 0x10, 0xdd}, + {0x05, 0x00, 0x07, 0xbb}, + {0x34, 0x00, 0x00, 0xbb}, + {0x35, 0xff, 0x00, 0xbb}, + {0xdc, 0x07, 0x02, 0xbb}, + {0xdd, 0x3c, 0x18, 0xbb}, + {0xde, 0x92, 0x6d, 0xbb}, + {0xdf, 0xcd, 0xb1, 0xbb}, + {0xe0, 0xff, 0xe7, 0xbb}, + {0x06, 0xf0, 0x0d, 0xbb}, + {0x06, 0x70, 0x0e, 0xbb}, + {0x4c, 0x00, 0x01, 0xbb}, + {0x4d, 0x00, 0x01, 0xbb}, + {0xf0, 0x00, 0x02, 0xbb}, + {0x2e, 0x0c, 0x55, 0xbb}, + {0x21, 0xb6, 0x6e, 0xbb}, + {0x36, 0x30, 0x10, 0xbb}, + {0x37, 0x00, 0xc1, 0xbb}, {0xf0, 0x00, 0x00, 0xbb}, - {0x00, 0x01, 0x00, 0xdd}, - {0x2b, 0x00, 0x28, 0xbb}, - {0x2c, 0x00, 0x30, 0xbb}, - {0x2d, 0x00, 0x30, 0xbb}, - {0x2e, 0x00, 0x28, 0xbb}, - {0x41, 0x00, 0xd7, 0xbb}, - {0x09, 0x02, 0x3a, 0xbb}, - {0x0c, 0x00, 0x00, 0xbb}, - {0x20, 0x00, 0x00, 0xbb}, - {0x05, 0x00, 0x8c, 0xbb}, - {0x06, 0x00, 0x32, 0xbb}, - {0x07, 0x00, 0xc6, 0xbb}, - {0x08, 0x00, 0x19, 0xbb}, - {0x24, 0x80, 0x6f, 0xbb}, - {0xc8, 0x00, 0x0f, 0xbb}, - {0x20, 0x00, 0x0f, 0xbb}, + {0x07, 0x00, 0x84, 0xbb}, + {0x08, 0x02, 0x4a, 0xbb}, + {0x05, 0x01, 0x10, 0xbb}, + {0x06, 0x00, 0x39, 0xbb}, + {0xf0, 0x00, 0x02, 0xbb}, + {0x58, 0x02, 0x67, 0xbb}, + {0x57, 0x02, 0x00, 0xbb}, + {0x5a, 0x02, 0x67, 0xbb}, + {0x59, 0x02, 0x00, 0xbb}, + {0x5c, 0x12, 0x0d, 0xbb}, + {0x5d, 0x16, 0x11, 0xbb}, + {0x39, 0x06, 0x18, 0xbb}, + {0x3a, 0x06, 0x18, 0xbb}, + {0x3b, 0x06, 0x18, 0xbb}, + {0x3c, 0x06, 0x18, 0xbb}, + {0x64, 0x7b, 0x5b, 0xbb}, + {0xf0, 0x00, 0x02, 0xbb}, + {0x36, 0x30, 0x10, 0xbb}, + {0x37, 0x00, 0xc0, 0xbb}, + {0xbc, 0x0e, 0x00, 0xcc}, + {0xbc, 0x0f, 0x05, 0xcc}, + {0xbc, 0x10, 0xc0, 0xcc}, + {0xbc, 0x11, 0x03, 0xcc}, {0xb6, 0x00, 0x00, 0xcc}, {0xb6, 0x03, 0x02, 0xcc}, {0xb6, 0x02, 0x80, 0xcc}, {0xb6, 0x05, 0x01, 0xcc}, {0xb6, 0x04, 0xe0, 0xcc}, - {0xb6, 0x12, 0x78, 0xcc}, + {0xb6, 0x12, 0xf8, 0xcc}, + {0xb6, 0x13, 0x25, 0xcc}, {0xb6, 0x18, 0x02, 0xcc}, {0xb6, 0x17, 0x58, 0xcc}, {0xb6, 0x16, 0x00, 0xcc}, {0xb6, 0x22, 0x12, 0xcc}, {0xb6, 0x23, 0x0b, 0xcc}, - {0xb3, 0x02, 0x02, 0xcc}, {0xbf, 0xc0, 0x39, 0xcc}, {0xbf, 0xc1, 0x04, 0xcc}, - {0xbf, 0xcc, 0x10, 0xcc}, - {0xb9, 0x12, 0x00, 0xcc}, - {0xb9, 0x13, 0x0a, 0xcc}, - {0xb9, 0x14, 0x0a, 0xcc}, - {0xb9, 0x15, 0x0a, 0xcc}, - {0xb9, 0x16, 0x0a, 0xcc}, - {0xb9, 0x18, 0x00, 0xcc}, - {0xb9, 0x19, 0x0f, 0xcc}, - {0xb9, 0x1a, 0x0f, 0xcc}, - {0xb9, 0x1b, 0x0f, 0xcc}, - {0xb9, 0x1c, 0x0f, 0xcc}, - {0xb8, 0x8e, 0x00, 0xcc}, - {0xb8, 0x8f, 0xff, 0xcc}, - {0xb3, 0x01, 0x41, 0xcc}, - {0x03, 0x03, 0xc0, 0xbb}, - {0x06, 0x00, 0x10, 0xbb}, - {0xb6, 0x12, 0xf8, 0xcc}, - {0xb8, 0x0c, 0x20, 0xcc}, - {0xb8, 0x0d, 0x70, 0xcc}, - {0xb6, 0x13, 0x13, 0xcc}, - {0x2f, 0x00, 0xC0, 0xbb}, - {0xb8, 0xa0, 0x12, 0xcc}, - {}, -}; -static const __u8 mi1310_socinitQVGA_JPG[][4] = { - {0xb0, 0x03, 0x19, 0xcc}, - {0xb0, 0x04, 0x02, 0xcc}, - {0xb3, 0x00, 0x24, 0xcc}, - {0xb3, 0x00, 0x25, 0xcc}, - {0xb3, 0x05, 0x01, 0xcc}, - {0xb3, 0x06, 0x03, 0xcc}, - {0xb3, 0x5c, 0x01, 0xcc}, - {0xb3, 0x08, 0x01, 0xcc}, - {0xb3, 0x09, 0x0c, 0xcc}, - {0xb3, 0x34, 0x02, 0xcc}, - {0xb3, 0x35, 0xdd, 0xcc}, - {0xb3, 0x03, 0x0a, 0xcc}, - {0xb3, 0x04, 0x0d, 0xcc}, - {0xb3, 0x20, 0x00, 0xcc}, - {0xb3, 0x21, 0x00, 0xcc}, - {0xb3, 0x22, 0x01, 0xcc}, - {0xb3, 0x23, 0xe0, 0xcc}, - {0xb3, 0x14, 0x00, 0xcc}, - {0xb3, 0x15, 0x00, 0xcc}, - {0xb3, 0x16, 0x02, 0xcc}, - {0xb3, 0x17, 0x7f, 0xcc}, - {0xb8, 0x01, 0x7d, 0xcc}, - {0xb8, 0x81, 0x09, 0xcc}, - {0xb8, 0x27, 0x20, 0xcc}, - {0xb8, 0x26, 0x80, 0xcc}, - {0xb3, 0x00, 0x25, 0xcc}, - {0xb8, 0x00, 0x13, 0xcc}, - {0xbc, 0x00, 0xd1, 0xcc}, - {0xb8, 0x81, 0x01, 0xcc}, - {0xb8, 0x2c, 0x5a, 0xcc}, - {0xb8, 0x2d, 0xff, 0xcc}, - {0xb8, 0x2e, 0xee, 0xcc}, - {0xb8, 0x2f, 0xfb, 0xcc}, - {0xb8, 0x30, 0x52, 0xcc}, - {0xb8, 0x31, 0xf8, 0xcc}, - {0xb8, 0x32, 0xf1, 0xcc}, - {0xb8, 0x33, 0xff, 0xcc}, - {0xb8, 0x34, 0x54, 0xcc}, - {0xb8, 0x35, 0x00, 0xcc}, - {0xb8, 0x36, 0x00, 0xcc}, - {0xb8, 0x37, 0x00, 0xcc}, - {0xf0, 0x00, 0x00, 0xbb}, - {0x00, 0x01, 0x00, 0xdd}, - {0x0d, 0x00, 0x09, 0xbb}, - {0x0d, 0x00, 0x08, 0xbb}, - {0xf0, 0x00, 0x01, 0xbb}, - {0x00, 0x01, 0x00, 0xdd}, - {0x06, 0x00, 0x14, 0xbb}, - {0x3a, 0x10, 0x00, 0xbb}, - {0x00, 0x00, 0x10, 0xdd}, - {0x9b, 0x10, 0x00, 0xbb}, - {0x00, 0x00, 0x10, 0xdd}, - {0xf0, 0x00, 0x00, 0xbb}, - {0x00, 0x01, 0x00, 0xdd}, - {0x2b, 0x00, 0x28, 0xbb}, - {0x2c, 0x00, 0x30, 0xbb}, - {0x2d, 0x00, 0x30, 0xbb}, - {0x2e, 0x00, 0x28, 0xbb}, - {0x41, 0x00, 0xd7, 0xbb}, - {0x09, 0x02, 0x3a, 0xbb}, - {0x0c, 0x00, 0x00, 0xbb}, - {0x20, 0x00, 0x00, 0xbb}, - {0x05, 0x00, 0x8c, 0xbb}, - {0x06, 0x00, 0x32, 0xbb}, - {0x07, 0x00, 0xc6, 0xbb}, - {0x08, 0x00, 0x19, 0xbb}, - {0x24, 0x80, 0x6f, 0xbb}, - {0xc8, 0x00, 0x0f, 0xbb}, - {0x20, 0x00, 0x0f, 0xbb}, - {0xb6, 0x00, 0x00, 0xcc}, - {0xb6, 0x03, 0x01, 0xcc}, - {0xb6, 0x02, 0x40, 0xcc}, - {0xb6, 0x05, 0x00, 0xcc}, - {0xb6, 0x04, 0xf0, 0xcc}, - {0xb6, 0x12, 0x78, 0xcc}, - {0xb6, 0x18, 0x00, 0xcc}, - {0xb6, 0x17, 0x96, 0xcc}, - {0xb6, 0x16, 0x00, 0xcc}, - {0xb6, 0x22, 0x12, 0xcc}, - {0xb6, 0x23, 0x0b, 0xcc}, - {0xb3, 0x02, 0x02, 0xcc}, - {0xbf, 0xc0, 0x39, 0xcc}, - {0xbf, 0xc1, 0x04, 0xcc}, - {0xbf, 0xcc, 0x10, 0xcc}, - {0xb9, 0x12, 0x00, 0xcc}, - {0xb9, 0x13, 0x0a, 0xcc}, - {0xb9, 0x14, 0x0a, 0xcc}, - {0xb9, 0x15, 0x0a, 0xcc}, - {0xb9, 0x16, 0x0a, 0xcc}, - {0xb9, 0x18, 0x00, 0xcc}, - {0xb9, 0x19, 0x0f, 0xcc}, - {0xb9, 0x1a, 0x0f, 0xcc}, - {0xb9, 0x1b, 0x0f, 0xcc}, - {0xb9, 0x1c, 0x0f, 0xcc}, - {0xb8, 0x8e, 0x00, 0xcc}, - {0xb8, 0x8f, 0xff, 0xcc}, + {0xbf, 0xcc, 0x00, 0xcc}, {0xbc, 0x02, 0x18, 0xcc}, {0xbc, 0x03, 0x50, 0xcc}, {0xbc, 0x04, 0x18, 0xcc}, @@ -658,15 +542,130 @@ static const __u8 mi1310_socinitQVGA_JPG[][4] = { {0xbc, 0x0a, 0x10, 0xcc}, {0xbc, 0x0b, 0x00, 0xcc}, {0xbc, 0x0c, 0x00, 0xcc}, + {0xb3, 0x5c, 0x01, 0xcc}, + {0xf0, 0x00, 0x01, 0xbb}, + {0x80, 0x00, 0x03, 0xbb}, + {0x81, 0xc7, 0x14, 0xbb}, + {0x82, 0xeb, 0xe8, 0xbb}, + {0x83, 0xfe, 0xf4, 0xbb}, + {0x84, 0xcd, 0x10, 0xbb}, + {0x85, 0xf3, 0xee, 0xbb}, + {0x86, 0xff, 0xf1, 0xbb}, + {0x87, 0xcd, 0x10, 0xbb}, + {0x88, 0xf3, 0xee, 0xbb}, + {0x89, 0x01, 0xf1, 0xbb}, + {0x8a, 0xe5, 0x17, 0xbb}, + {0x8b, 0xe8, 0xe2, 0xbb}, + {0x8c, 0xf7, 0xed, 0xbb}, + {0x8d, 0x00, 0xff, 0xbb}, + {0x8e, 0xec, 0x10, 0xbb}, + {0x8f, 0xf0, 0xed, 0xbb}, + {0x90, 0xf9, 0xf2, 0xbb}, + {0x91, 0x00, 0x00, 0xbb}, + {0x92, 0xe9, 0x0d, 0xbb}, + {0x93, 0xf4, 0xf2, 0xbb}, + {0x94, 0xfb, 0xf5, 0xbb}, + {0x95, 0x00, 0xff, 0xbb}, + {0xb6, 0x0f, 0x08, 0xbb}, + {0xb7, 0x3d, 0x16, 0xbb}, + {0xb8, 0x0c, 0x04, 0xbb}, + {0xb9, 0x1c, 0x07, 0xbb}, + {0xba, 0x0a, 0x03, 0xbb}, + {0xbb, 0x1b, 0x09, 0xbb}, + {0xbc, 0x17, 0x0d, 0xbb}, + {0xbd, 0x23, 0x1d, 0xbb}, + {0xbe, 0x00, 0x28, 0xbb}, + {0xbf, 0x11, 0x09, 0xbb}, + {0xc0, 0x16, 0x15, 0xbb}, + {0xc1, 0x00, 0x1b, 0xbb}, + {0xc2, 0x0e, 0x07, 0xbb}, + {0xc3, 0x14, 0x10, 0xbb}, + {0xc4, 0x00, 0x17, 0xbb}, + {0x06, 0x74, 0x8e, 0xbb}, + {0xf0, 0x00, 0x01, 0xbb}, + {0x06, 0xf4, 0x8e, 0xbb}, + {0x00, 0x00, 0x50, 0xdd}, + {0x06, 0x74, 0x8e, 0xbb}, + {0xf0, 0x00, 0x02, 0xbb}, + {0x24, 0x50, 0x20, 0xbb}, + {0xf0, 0x00, 0x02, 0xbb}, + {0x34, 0x0c, 0x50, 0xbb}, {0xb3, 0x01, 0x41, 0xcc}, + {0xf0, 0x00, 0x00, 0xbb}, + {0x03, 0x03, 0xc0, 0xbb}, + {}, +}; +static const __u8 mi1310_socinitQVGA_JPG[][4] = { + {0xb0, 0x03, 0x19, 0xcc}, {0xb0, 0x04, 0x02, 0xcc}, + {0xb3, 0x00, 0x64, 0xcc}, {0xb3, 0x00, 0x65, 0xcc}, + {0xb3, 0x05, 0x00, 0xcc}, {0xb3, 0x06, 0x00, 0xcc}, + {0xb3, 0x08, 0x01, 0xcc}, {0xb3, 0x09, 0x0c, 0xcc}, + {0xb3, 0x34, 0x02, 0xcc}, {0xb3, 0x35, 0xdd, 0xcc}, + {0xb3, 0x02, 0x00, 0xcc}, {0xb3, 0x03, 0x0a, 0xcc}, + {0xb3, 0x04, 0x05, 0xcc}, {0xb3, 0x20, 0x00, 0xcc}, + {0xb3, 0x21, 0x00, 0xcc}, {0xb3, 0x22, 0x03, 0xcc}, + {0xb3, 0x23, 0xc0, 0xcc}, {0xb3, 0x14, 0x00, 0xcc}, + {0xb3, 0x15, 0x00, 0xcc}, {0xb3, 0x16, 0x04, 0xcc}, + {0xb3, 0x17, 0xff, 0xcc}, {0xb3, 0x00, 0x65, 0xcc}, + {0xb8, 0x00, 0x00, 0xcc}, {0xbc, 0x00, 0xf0, 0xcc}, + {0xbc, 0x01, 0x01, 0xcc}, {0xf0, 0x00, 0x02, 0xbb}, + {0xc8, 0x9f, 0x0b, 0xbb}, {0x5b, 0x00, 0x01, 0xbb}, + {0x2f, 0xde, 0x20, 0xbb}, {0xf0, 0x00, 0x00, 0xbb}, + {0x20, 0x03, 0x02, 0xbb}, {0xf0, 0x00, 0x01, 0xbb}, + {0x05, 0x00, 0x07, 0xbb}, {0x34, 0x00, 0x00, 0xbb}, + {0x35, 0xff, 0x00, 0xbb}, {0xdc, 0x07, 0x02, 0xbb}, + {0xdd, 0x3c, 0x18, 0xbb}, {0xde, 0x92, 0x6d, 0xbb}, + {0xdf, 0xcd, 0xb1, 0xbb}, {0xe0, 0xff, 0xe7, 0xbb}, + {0x06, 0xf0, 0x0d, 0xbb}, {0x06, 0x70, 0x0e, 0xbb}, + {0x4c, 0x00, 0x01, 0xbb}, {0x4d, 0x00, 0x01, 0xbb}, + {0xf0, 0x00, 0x02, 0xbb}, {0x2e, 0x0c, 0x55, 0xbb}, + {0x21, 0xb6, 0x6e, 0xbb}, {0x36, 0x30, 0x10, 0xbb}, + {0x37, 0x00, 0xc1, 0xbb}, {0xf0, 0x00, 0x00, 0xbb}, + {0x07, 0x00, 0x84, 0xbb}, {0x08, 0x02, 0x4a, 0xbb}, + {0x05, 0x01, 0x10, 0xbb}, {0x06, 0x00, 0x39, 0xbb}, + {0xf0, 0x00, 0x02, 0xbb}, {0x58, 0x02, 0x67, 0xbb}, + {0x57, 0x02, 0x00, 0xbb}, {0x5a, 0x02, 0x67, 0xbb}, + {0x59, 0x02, 0x00, 0xbb}, {0x5c, 0x12, 0x0d, 0xbb}, + {0x5d, 0x16, 0x11, 0xbb}, {0x39, 0x06, 0x18, 0xbb}, + {0x3a, 0x06, 0x18, 0xbb}, {0x3b, 0x06, 0x18, 0xbb}, + {0x3c, 0x06, 0x18, 0xbb}, {0x64, 0x7b, 0x5b, 0xbb}, + {0xf0, 0x00, 0x02, 0xbb}, {0x36, 0x30, 0x10, 0xbb}, + {0x37, 0x00, 0xc0, 0xbb}, {0xbc, 0x0e, 0x00, 0xcc}, + {0xbc, 0x0f, 0x05, 0xcc}, {0xbc, 0x10, 0xc0, 0xcc}, + {0xbc, 0x11, 0x03, 0xcc}, {0xb6, 0x00, 0x00, 0xcc}, + {0xb6, 0x03, 0x01, 0xcc}, {0xb6, 0x02, 0x40, 0xcc}, + {0xb6, 0x05, 0x00, 0xcc}, {0xb6, 0x04, 0xf0, 0xcc}, + {0xb6, 0x12, 0xf8, 0xcc}, {0xb6, 0x13, 0x25, 0xcc}, + {0xb6, 0x18, 0x00, 0xcc}, {0xb6, 0x17, 0x96, 0xcc}, + {0xb6, 0x16, 0x00, 0xcc}, {0xb6, 0x22, 0x12, 0xcc}, + {0xb6, 0x23, 0x0b, 0xcc}, {0xbf, 0xc0, 0x39, 0xcc}, + {0xbf, 0xc1, 0x04, 0xcc}, {0xbf, 0xcc, 0x00, 0xcc}, + {0xb3, 0x5c, 0x01, 0xcc}, {0xf0, 0x00, 0x01, 0xbb}, + {0x80, 0x00, 0x03, 0xbb}, {0x81, 0xc7, 0x14, 0xbb}, + {0x82, 0xeb, 0xe8, 0xbb}, {0x83, 0xfe, 0xf4, 0xbb}, + {0x84, 0xcd, 0x10, 0xbb}, {0x85, 0xf3, 0xee, 0xbb}, + {0x86, 0xff, 0xf1, 0xbb}, {0x87, 0xcd, 0x10, 0xbb}, + {0x88, 0xf3, 0xee, 0xbb}, {0x89, 0x01, 0xf1, 0xbb}, + {0x8a, 0xe5, 0x17, 0xbb}, {0x8b, 0xe8, 0xe2, 0xbb}, + {0x8c, 0xf7, 0xed, 0xbb}, {0x8d, 0x00, 0xff, 0xbb}, + {0x8e, 0xec, 0x10, 0xbb}, {0x8f, 0xf0, 0xed, 0xbb}, + {0x90, 0xf9, 0xf2, 0xbb}, {0x91, 0x00, 0x00, 0xbb}, + {0x92, 0xe9, 0x0d, 0xbb}, {0x93, 0xf4, 0xf2, 0xbb}, + {0x94, 0xfb, 0xf5, 0xbb}, {0x95, 0x00, 0xff, 0xbb}, + {0xb6, 0x0f, 0x08, 0xbb}, {0xb7, 0x3d, 0x16, 0xbb}, + {0xb8, 0x0c, 0x04, 0xbb}, {0xb9, 0x1c, 0x07, 0xbb}, + {0xba, 0x0a, 0x03, 0xbb}, {0xbb, 0x1b, 0x09, 0xbb}, + {0xbc, 0x17, 0x0d, 0xbb}, {0xbd, 0x23, 0x1d, 0xbb}, + {0xbe, 0x00, 0x28, 0xbb}, {0xbf, 0x11, 0x09, 0xbb}, + {0xc0, 0x16, 0x15, 0xbb}, {0xc1, 0x00, 0x1b, 0xbb}, + {0xc2, 0x0e, 0x07, 0xbb}, {0xc3, 0x14, 0x10, 0xbb}, + {0xc4, 0x00, 0x17, 0xbb}, {0x06, 0x74, 0x8e, 0xbb}, + {0xf0, 0x00, 0x01, 0xbb}, {0x06, 0xf4, 0x8e, 0xbb}, + {0x00, 0x00, 0x50, 0xdd}, {0x06, 0x74, 0x8e, 0xbb}, + {0xf0, 0x00, 0x02, 0xbb}, {0x24, 0x50, 0x20, 0xbb}, + {0xf0, 0x00, 0x02, 0xbb}, {0x34, 0x0c, 0x50, 0xbb}, + {0xb3, 0x01, 0x41, 0xcc}, {0xf0, 0x00, 0x00, 0xbb}, {0x03, 0x03, 0xc0, 0xbb}, - {0x06, 0x00, 0x10, 0xbb}, - {0xb6, 0x12, 0xf8, 0xcc}, - {0xb8, 0x0c, 0x20, 0xcc}, - {0xb8, 0x0d, 0x70, 0xcc}, - {0xb6, 0x13, 0x13, 0xcc}, - {0x2f, 0x00, 0xC0, 0xbb}, - {0xb8, 0xa0, 0x12, 0xcc}, {}, }; static const u8 mi1310_soc_InitSXGA_JPG[][4] = { @@ -2982,7 +2981,8 @@ static int sd_config(struct gspca_dev *gspca_dev, break; case SENSOR_MI1310_SOC: cam->cam_mode = vc0323_mode; - cam->nmodes = ARRAY_SIZE(vc0323_mode); + /* TODO: 1280x1024 resolution setting is incorrect, so don't export it now*/ + cam->nmodes = ARRAY_SIZE(vc0323_mode) - 1; break; case SENSOR_MI1320_SOC: cam->cam_mode = bi_mode; @@ -3217,15 +3217,20 @@ static int sd_start(struct gspca_dev *gspca_dev) put_tab_to_reg(gspca_dev, MatrixT, 9, 0xb82c); /* set the led on 0x0892 0x0896 */ - if (sd->sensor != SENSOR_PO1200) { - reg_w(gspca_dev->dev, 0x89, 0xffff, 0xfdff); + if (sd->sensor == SENSOR_PO1200) { + setsharpness(gspca_dev); + sethvflip(gspca_dev); + reg_w(gspca_dev->dev, 0x89, 0x0400, 0x1415); + } else if (sd->sensor == SENSOR_MI1310_SOC) { + reg_w(gspca_dev->dev, 0x89, 0x058c, 0x0000); msleep(100); sethvflip(gspca_dev); setlightfreq(gspca_dev); } else { - setsharpness(gspca_dev); + reg_w(gspca_dev->dev, 0x89, 0xffff, 0xfdff); + msleep(100); sethvflip(gspca_dev); - reg_w(gspca_dev->dev, 0x89, 0x0400, 0x1415); + setlightfreq(gspca_dev); } } return 0; @@ -3234,8 +3239,12 @@ static int sd_start(struct gspca_dev *gspca_dev) static void sd_stopN(struct gspca_dev *gspca_dev) { struct usb_device *dev = gspca_dev->dev; + struct sd *sd = (struct sd *) gspca_dev; - reg_w(dev, 0x89, 0xffff, 0xffff); + if( sd->sensor == SENSOR_MI1310_SOC) + reg_w(dev, 0x89, 0x058c, 0x00ff); + else + reg_w(dev, 0x89, 0xffff, 0xffff); reg_w(dev, 0xa0, 0x01, 0xb301); reg_w(dev, 0xa0, 0x09, 0xb003); } @@ -3244,10 +3253,14 @@ static void sd_stopN(struct gspca_dev *gspca_dev) static void sd_stop0(struct gspca_dev *gspca_dev) { struct usb_device *dev = gspca_dev->dev; + struct sd *sd = (struct sd *) gspca_dev; if (!gspca_dev->present) return; - reg_w(dev, 0x89, 0xffff, 0xffff); + if( sd->sensor == SENSOR_MI1310_SOC) + reg_w(dev, 0x89, 0x058c, 0x00ff); + else + reg_w(dev, 0x89, 0xffff, 0xffff); } static void sd_pkt_scan(struct gspca_dev *gspca_dev, -- cgit v1.2.3 From 5ff3ce2a04c7a20cc6190c1dd5dd200cb551bbea Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Mon, 27 Jul 2009 10:52:27 +0200 Subject: gspca - vc032x: Add the 1280x960 resolution for sensor mi1310_soc. From: Jean-Francois Moine Priority: normal Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/vc032x.c | 245 +++++++++++++++++++++---------- 1 file changed, 165 insertions(+), 80 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/vc032x.c b/linux/drivers/media/video/gspca/vc032x.c index 85cb790fc..6fe1c77d6 100644 --- a/linux/drivers/media/video/gspca/vc032x.c +++ b/linux/drivers/media/video/gspca/vc032x.c @@ -153,9 +153,9 @@ static const struct v4l2_pix_format vc0323_mode[] = { .sizeimage = 640 * 480 * 3 / 8 + 590, .colorspace = V4L2_COLORSPACE_JPEG, .priv = 0}, - {1280, 1024, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, /* mi13x0_soc only */ + {1280, 960, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, /* mi1310_soc only */ .bytesperline = 1280, - .sizeimage = 1280 * 1024 * 1 / 4 + 590, + .sizeimage = 1280 * 960 * 3 / 8 + 590, .colorspace = V4L2_COLORSPACE_JPEG, .priv = 2}, }; @@ -671,108 +671,194 @@ static const __u8 mi1310_socinitQVGA_JPG[][4] = { static const u8 mi1310_soc_InitSXGA_JPG[][4] = { {0xb0, 0x03, 0x19, 0xcc}, {0xb0, 0x04, 0x02, 0xcc}, - {0xb3, 0x00, 0x24, 0xcc}, - {0xb3, 0x00, 0x25, 0xcc}, + {0xb3, 0x00, 0x64, 0xcc}, + {0xb3, 0x00, 0x65, 0xcc}, {0xb3, 0x05, 0x00, 0xcc}, - {0xb3, 0x06, 0x01, 0xcc}, - {0xb3, 0x5c, 0x01, 0xcc}, + {0xb3, 0x06, 0x00, 0xcc}, {0xb3, 0x08, 0x01, 0xcc}, {0xb3, 0x09, 0x0c, 0xcc}, {0xb3, 0x34, 0x02, 0xcc}, {0xb3, 0x35, 0xdd, 0xcc}, + {0xb3, 0x02, 0x00, 0xcc}, {0xb3, 0x03, 0x0a, 0xcc}, {0xb3, 0x04, 0x0d, 0xcc}, {0xb3, 0x20, 0x00, 0xcc}, {0xb3, 0x21, 0x00, 0xcc}, - {0xb3, 0x22, 0x04, 0xcc}, - {0xb3, 0x23, 0x00, 0xcc}, + {0xb3, 0x22, 0x03, 0xcc}, + {0xb3, 0x23, 0xc0, 0xcc}, {0xb3, 0x14, 0x00, 0xcc}, {0xb3, 0x15, 0x00, 0xcc}, {0xb3, 0x16, 0x04, 0xcc}, {0xb3, 0x17, 0xff, 0xcc}, - {0xb8, 0x01, 0x7d, 0xcc}, - {0xb8, 0x81, 0x09, 0xcc}, - {0xb8, 0x27, 0x20, 0xcc}, - {0xb8, 0x26, 0x80, 0xcc}, - {0xb8, 0x06, 0x00, 0xcc}, - {0xb8, 0x07, 0x05, 0xcc}, - {0xb8, 0x08, 0x00, 0xcc}, - {0xb8, 0x09, 0x04, 0xcc}, - {0xb3, 0x00, 0x25, 0xcc}, - {0xb8, 0x00, 0x11, 0xcc}, - {0xbc, 0x00, 0x71, 0xcc}, - {0xb8, 0x81, 0x01, 0xcc}, - {0xb8, 0x2c, 0x5a, 0xcc}, - {0xb8, 0x2d, 0xff, 0xcc}, - {0xb8, 0x2e, 0xee, 0xcc}, - {0xb8, 0x2f, 0xfb, 0xcc}, - {0xb8, 0x30, 0x52, 0xcc}, - {0xb8, 0x31, 0xf8, 0xcc}, - {0xb8, 0x32, 0xf1, 0xcc}, - {0xb8, 0x33, 0xff, 0xcc}, - {0xb8, 0x34, 0x54, 0xcc}, + {0xb3, 0x00, 0x65, 0xcc}, + {0xb8, 0x00, 0x00, 0xcc}, + {0xbc, 0x00, 0x70, 0xcc}, + {0xbc, 0x01, 0x01, 0xcc}, + {0xf0, 0x00, 0x02, 0xbb}, + {0xc8, 0x9f, 0x0b, 0xbb}, + {0x5b, 0x00, 0x01, 0xbb}, {0xf0, 0x00, 0x00, 0xbb}, - {0x00, 0x01, 0x00, 0xdd}, - {0x0d, 0x00, 0x09, 0xbb}, - {0x0d, 0x00, 0x08, 0xbb}, + {0x20, 0x03, 0x03, 0xbb}, {0xf0, 0x00, 0x01, 0xbb}, - {0x00, 0x01, 0x00, 0xdd}, - {0x06, 0x00, 0x14, 0xbb}, - {0x3a, 0x10, 0x00, 0xbb}, - {0x00, 0x00, 0x10, 0xdd}, - {0x9b, 0x10, 0x00, 0xbb}, - {0x00, 0x00, 0x10, 0xdd}, + {0x05, 0x00, 0x07, 0xbb}, + {0x34, 0x00, 0x00, 0xbb}, + {0x35, 0xff, 0x00, 0xbb}, + {0xdc, 0x07, 0x02, 0xbb}, + {0xdd, 0x3c, 0x18, 0xbb}, + {0xde, 0x92, 0x6d, 0xbb}, + {0xdf, 0xcd, 0xb1, 0xbb}, + {0xe0, 0xff, 0xe7, 0xbb}, + {0x06, 0xf0, 0x0d, 0xbb}, + {0x06, 0x70, 0x0e, 0xbb}, + {0x4c, 0x00, 0x01, 0xbb}, + {0x4d, 0x00, 0x01, 0xbb}, + {0xf0, 0x00, 0x02, 0xbb}, + {0x2e, 0x0c, 0x60, 0xbb}, + {0x21, 0xb6, 0x6e, 0xbb}, + {0x37, 0x01, 0x40, 0xbb}, {0xf0, 0x00, 0x00, 0xbb}, - {0x00, 0x01, 0x00, 0xdd}, - {0x2b, 0x00, 0x28, 0xbb}, - {0x2c, 0x00, 0x30, 0xbb}, - {0x2d, 0x00, 0x30, 0xbb}, - {0x2e, 0x00, 0x28, 0xbb}, - {0x41, 0x00, 0xd7, 0xbb}, - {0x09, 0x02, 0x3a, 0xbb}, - {0x0c, 0x00, 0x00, 0xbb}, - {0x20, 0x00, 0x00, 0xbb}, - {0x05, 0x00, 0x8c, 0xbb}, - {0x06, 0x00, 0x32, 0xbb}, - {0x07, 0x00, 0xc6, 0xbb}, - {0x08, 0x00, 0x19, 0xbb}, - {0x24, 0x80, 0x6f, 0xbb}, - {0xc8, 0x00, 0x0f, 0xbb}, - {0x20, 0x00, 0x03, 0xbb}, + {0x07, 0x00, 0x84, 0xbb}, + {0x08, 0x02, 0x4a, 0xbb}, + {0x05, 0x01, 0x10, 0xbb}, + {0x06, 0x00, 0x39, 0xbb}, + {0xf0, 0x00, 0x02, 0xbb}, + {0x58, 0x02, 0x67, 0xbb}, + {0x57, 0x02, 0x00, 0xbb}, + {0x5a, 0x02, 0x67, 0xbb}, + {0x59, 0x02, 0x00, 0xbb}, + {0x5c, 0x12, 0x0d, 0xbb}, + {0x5d, 0x16, 0x11, 0xbb}, + {0x39, 0x06, 0x18, 0xbb}, + {0x3a, 0x06, 0x18, 0xbb}, + {0x3b, 0x06, 0x18, 0xbb}, + {0x3c, 0x06, 0x18, 0xbb}, + {0x64, 0x7b, 0x5b, 0xbb}, {0xb6, 0x00, 0x00, 0xcc}, {0xb6, 0x03, 0x05, 0xcc}, {0xb6, 0x02, 0x00, 0xcc}, - {0xb6, 0x05, 0x04, 0xcc}, - {0xb6, 0x04, 0x00, 0xcc}, + {0xb6, 0x05, 0x03, 0xcc}, + {0xb6, 0x04, 0xc0, 0xcc}, {0xb6, 0x12, 0xf8, 0xcc}, - {0xb6, 0x18, 0x0a, 0xcc}, - {0xb6, 0x17, 0x00, 0xcc}, + {0xb6, 0x13, 0x29, 0xcc}, + {0xb6, 0x18, 0x09, 0xcc}, + {0xb6, 0x17, 0x60, 0xcc}, {0xb6, 0x16, 0x00, 0xcc}, {0xb6, 0x22, 0x12, 0xcc}, {0xb6, 0x23, 0x0b, 0xcc}, - {0xb3, 0x02, 0x02, 0xcc}, {0xbf, 0xc0, 0x39, 0xcc}, {0xbf, 0xc1, 0x04, 0xcc}, - {0xbf, 0xcc, 0x10, 0xcc}, - {0xb9, 0x12, 0x00, 0xcc}, - {0xb9, 0x13, 0x14, 0xcc}, - {0xb9, 0x14, 0x14, 0xcc}, - {0xb9, 0x15, 0x14, 0xcc}, - {0xb9, 0x16, 0x14, 0xcc}, - {0xb9, 0x18, 0x00, 0xcc}, - {0xb9, 0x19, 0x1e, 0xcc}, - {0xb9, 0x1a, 0x1e, 0xcc}, - {0xb9, 0x1b, 0x1e, 0xcc}, - {0xb9, 0x1c, 0x1e, 0xcc}, + {0xbf, 0xcc, 0x00, 0xcc}, {0xb3, 0x01, 0x41, 0xcc}, - {0xb8, 0x8e, 0x00, 0xcc}, - {0xb8, 0x8f, 0xff, 0xcc}, - {0xb6, 0x12, 0xf8, 0xcc}, - {0xb8, 0x0c, 0x20, 0xcc}, - {0xb8, 0x0d, 0x70, 0xcc}, - {0xb6, 0x13, 0x13, 0xcc}, - {0x2f, 0x00, 0xC0, 0xbb}, - {0xb8, 0xa0, 0x12, 0xcc}, + {0x00, 0x00, 0x80, 0xdd}, + {0xf0, 0x00, 0x02, 0xbb}, + {0x00, 0x00, 0x10, 0xdd}, + {0x22, 0xa0, 0x78, 0xbb}, + {0x23, 0xa0, 0x78, 0xbb}, + {0x24, 0x7f, 0x00, 0xbb}, + {0x28, 0xea, 0x02, 0xbb}, + {0x29, 0x86, 0x7a, 0xbb}, + {0x5e, 0x52, 0x4c, 0xbb}, + {0x5f, 0x20, 0x24, 0xbb}, + {0x60, 0x00, 0x02, 0xbb}, + {0x02, 0x00, 0xee, 0xbb}, + {0x03, 0x39, 0x23, 0xbb}, + {0x04, 0x07, 0x24, 0xbb}, + {0x09, 0x00, 0xc0, 0xbb}, + {0x0a, 0x00, 0x79, 0xbb}, + {0x0b, 0x00, 0x04, 0xbb}, + {0x0c, 0x00, 0x5c, 0xbb}, + {0x0d, 0x00, 0xd9, 0xbb}, + {0x0e, 0x00, 0x53, 0xbb}, + {0x0f, 0x00, 0x21, 0xbb}, + {0x10, 0x00, 0xa4, 0xbb}, + {0x11, 0x00, 0xe5, 0xbb}, + {0x15, 0x00, 0x00, 0xbb}, + {0x16, 0x00, 0x00, 0xbb}, + {0x17, 0x00, 0x00, 0xbb}, + {0x18, 0x00, 0x00, 0xbb}, + {0x19, 0x00, 0x00, 0xbb}, + {0x1a, 0x00, 0x00, 0xbb}, + {0x1b, 0x00, 0x00, 0xbb}, + {0x1c, 0x00, 0x00, 0xbb}, + {0x1d, 0x00, 0x00, 0xbb}, + {0x1e, 0x00, 0x00, 0xbb}, + {0xf0, 0x00, 0x01, 0xbb}, + {0x00, 0x00, 0x20, 0xdd}, + {0x06, 0xf0, 0x8e, 0xbb}, + {0x00, 0x00, 0x80, 0xdd}, + {0x06, 0x70, 0x8e, 0xbb}, + {0xf0, 0x00, 0x02, 0xbb}, + {0x00, 0x00, 0x20, 0xdd}, + {0x5e, 0x6a, 0x53, 0xbb}, + {0x5f, 0x40, 0x2c, 0xbb}, + {0xf0, 0x00, 0x01, 0xbb}, + {0x00, 0x00, 0x20, 0xdd}, + {0x58, 0x00, 0x00, 0xbb}, + {0x53, 0x09, 0x03, 0xbb}, + {0x54, 0x31, 0x18, 0xbb}, + {0x55, 0x8b, 0x5f, 0xbb}, + {0x56, 0xc0, 0xa9, 0xbb}, + {0x57, 0xe0, 0xd2, 0xbb}, + {0xe1, 0x00, 0x00, 0xbb}, + {0xdc, 0x09, 0x03, 0xbb}, + {0xdd, 0x31, 0x18, 0xbb}, + {0xde, 0x8b, 0x5f, 0xbb}, + {0xdf, 0xc0, 0xa9, 0xbb}, + {0xe0, 0xe0, 0xd2, 0xbb}, + {0xb3, 0x5c, 0x01, 0xcc}, + {0xf0, 0x00, 0x01, 0xbb}, + {0x06, 0xf0, 0x8e, 0xbb}, + {0xf0, 0x00, 0x02, 0xbb}, + {0x2f, 0xde, 0x20, 0xbb}, + {0xf0, 0x00, 0x02, 0xbb}, + {0x24, 0x50, 0x20, 0xbb}, + {0xbc, 0x0e, 0x00, 0xcc}, + {0xbc, 0x0f, 0x05, 0xcc}, + {0xbc, 0x10, 0xc0, 0xcc}, + {0xf0, 0x00, 0x02, 0xbb}, + {0x34, 0x0c, 0x50, 0xbb}, + {0xbc, 0x11, 0x03, 0xcc}, + {0xf0, 0x00, 0x01, 0xbb}, + {0x80, 0x00, 0x03, 0xbb}, + {0x81, 0xc7, 0x14, 0xbb}, + {0x82, 0xeb, 0xe8, 0xbb}, + {0x83, 0xfe, 0xf4, 0xbb}, + {0x84, 0xcd, 0x10, 0xbb}, + {0x85, 0xf3, 0xee, 0xbb}, + {0x86, 0xff, 0xf1, 0xbb}, + {0x87, 0xcd, 0x10, 0xbb}, + {0x88, 0xf3, 0xee, 0xbb}, + {0x89, 0x01, 0xf1, 0xbb}, + {0x8a, 0xe5, 0x17, 0xbb}, + {0x8b, 0xe8, 0xe2, 0xbb}, + {0x8c, 0xf7, 0xed, 0xbb}, + {0x8d, 0x00, 0xff, 0xbb}, + {0x8e, 0xec, 0x10, 0xbb}, + {0x8f, 0xf0, 0xed, 0xbb}, + {0x90, 0xf9, 0xf2, 0xbb}, + {0x91, 0x00, 0x00, 0xbb}, + {0x92, 0xe9, 0x0d, 0xbb}, + {0x93, 0xf4, 0xf2, 0xbb}, + {0x94, 0xfb, 0xf5, 0xbb}, + {0x95, 0x00, 0xff, 0xbb}, + {0xb6, 0x0f, 0x08, 0xbb}, + {0xb7, 0x3d, 0x16, 0xbb}, + {0xb8, 0x0c, 0x04, 0xbb}, + {0xb9, 0x1c, 0x07, 0xbb}, + {0xba, 0x0a, 0x03, 0xbb}, + {0xbb, 0x1b, 0x09, 0xbb}, + {0xbc, 0x17, 0x0d, 0xbb}, + {0xbd, 0x23, 0x1d, 0xbb}, + {0xbe, 0x00, 0x28, 0xbb}, + {0xbf, 0x11, 0x09, 0xbb}, + {0xc0, 0x16, 0x15, 0xbb}, + {0xc1, 0x00, 0x1b, 0xbb}, + {0xc2, 0x0e, 0x07, 0xbb}, + {0xc3, 0x14, 0x10, 0xbb}, + {0xc4, 0x00, 0x17, 0xbb}, + {0x06, 0x74, 0x8e, 0xbb}, + {0xf0, 0x00, 0x00, 0xbb}, + {0x03, 0x03, 0xc0, 0xbb}, {} }; @@ -2981,8 +3067,7 @@ static int sd_config(struct gspca_dev *gspca_dev, break; case SENSOR_MI1310_SOC: cam->cam_mode = vc0323_mode; - /* TODO: 1280x1024 resolution setting is incorrect, so don't export it now*/ - cam->nmodes = ARRAY_SIZE(vc0323_mode) - 1; + cam->nmodes = ARRAY_SIZE(vc0323_mode); break; case SENSOR_MI1320_SOC: cam->cam_mode = bi_mode; -- cgit v1.2.3 From 21625be118a5ac52bdd1fe150079ab19e931c02c Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Mon, 27 Jul 2009 11:00:03 +0200 Subject: gspca - vc032x: H and V flip controls added for mi13x0_soc sensors. From: Jean-Francois Moine Also, H/V flip default values adjusted according to the webcam IDs. Priority: normal Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/vc032x.c | 111 ++++++++++++++++++------------- 1 file changed, 64 insertions(+), 47 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/vc032x.c b/linux/drivers/media/video/gspca/vc032x.c index 6fe1c77d6..97b9d677c 100644 --- a/linux/drivers/media/video/gspca/vc032x.c +++ b/linux/drivers/media/video/gspca/vc032x.c @@ -52,7 +52,10 @@ struct sd { #define SENSOR_OV7670 6 #define SENSOR_PO1200 7 #define SENSOR_PO3130NC 8 - u8 ninput; /* != 0 when 2 sensors - SamsungQ1 */ + u8 flags; +#define FL_SAMSUNG 0x01 /* SamsungQ1 (2 sensors) */ +#define FL_HFLIP 0x02 /* mirrored by default */ +#define FL_VFLIP 0x04 /* vertical flipped by default */ }; /* V4L2 controls supported by the driver */ @@ -66,7 +69,7 @@ static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val); static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val); static struct ctrl sd_ctrls[] = { -/* next 2 controls work with ov7660 and ov7670 only */ +/* next 2 controls work with some sensors only */ #define HFLIP_IDX 0 { { @@ -474,7 +477,7 @@ static const __u8 mi1310_socinitVGA_JPG[][4] = { {0x5b, 0x00, 0x01, 0xbb}, {0x2f, 0xde, 0x20, 0xbb}, {0xf0, 0x00, 0x00, 0xbb}, - {0x20, 0x03, 0x02, 0xbb}, + {0x20, 0x03, 0x02, 0xbb}, /* h/v flip */ {0xf0, 0x00, 0x01, 0xbb}, {0x05, 0x00, 0x07, 0xbb}, {0x34, 0x00, 0x00, 0xbb}, @@ -611,7 +614,8 @@ static const __u8 mi1310_socinitQVGA_JPG[][4] = { {0xbc, 0x01, 0x01, 0xcc}, {0xf0, 0x00, 0x02, 0xbb}, {0xc8, 0x9f, 0x0b, 0xbb}, {0x5b, 0x00, 0x01, 0xbb}, {0x2f, 0xde, 0x20, 0xbb}, {0xf0, 0x00, 0x00, 0xbb}, - {0x20, 0x03, 0x02, 0xbb}, {0xf0, 0x00, 0x01, 0xbb}, + {0x20, 0x03, 0x02, 0xbb}, /* h/v flip */ + {0xf0, 0x00, 0x01, 0xbb}, {0x05, 0x00, 0x07, 0xbb}, {0x34, 0x00, 0x00, 0xbb}, {0x35, 0xff, 0x00, 0xbb}, {0xdc, 0x07, 0x02, 0xbb}, {0xdd, 0x3c, 0x18, 0xbb}, {0xde, 0x92, 0x6d, 0xbb}, @@ -698,7 +702,11 @@ static const u8 mi1310_soc_InitSXGA_JPG[][4] = { {0xc8, 0x9f, 0x0b, 0xbb}, {0x5b, 0x00, 0x01, 0xbb}, {0xf0, 0x00, 0x00, 0xbb}, - {0x20, 0x03, 0x03, 0xbb}, +#if 1 + {0x20, 0x03, 0x02, 0xbb}, /* h/v flip */ +#else + {0x20, 0x03, 0x03, 0xbb}, /* h/v flip */ +#endif {0xf0, 0x00, 0x01, 0xbb}, {0x05, 0x00, 0x07, 0xbb}, {0x34, 0x00, 0x00, 0xbb}, @@ -1055,7 +1063,7 @@ static const u8 mi1320_soc_InitVGA[][4] = { {0x07, 0x00, 0xe0, 0xbb}, {0x08, 0x00, 0x0b, 0xbb}, {0x21, 0x00, 0x0c, 0xbb}, - {0x20, 0x01, 0x03, 0xbb}, + {0x20, 0x01, 0x03, 0xbb}, /* h/v flip */ {0xbf, 0xc0, 0x26, 0xcc}, {0xbf, 0xc1, 0x02, 0xcc}, {0xbf, 0xcc, 0x04, 0xcc}, @@ -1065,7 +1073,7 @@ static const u8 mi1320_soc_InitVGA[][4] = { {0x06, 0x00, 0x11, 0xbb}, {0x07, 0x01, 0x42, 0xbb}, {0x08, 0x00, 0x11, 0xbb}, - {0x20, 0x01, 0x03, 0xbb}, + {0x20, 0x01, 0x03, 0xbb}, /* h/v flip */ {0x21, 0x80, 0x00, 0xbb}, {0x22, 0x0d, 0x0f, 0xbb}, {0x24, 0x80, 0x00, 0xbb}, @@ -1159,7 +1167,7 @@ static const u8 mi1320_soc_InitVGA_JPG[][4] = { {0x07, 0x00, 0xe0, 0xbb}, {0x08, 0x00, 0x0b, 0xbb}, {0x21, 0x00, 0x0c, 0xbb}, - {0x20, 0x01, 0x03, 0xbb}, + {0x20, 0x01, 0x03, 0xbb}, /* h/v flip */ {0xb6, 0x00, 0x00, 0xcc}, {0xb6, 0x03, 0x02, 0xcc}, {0xb6, 0x02, 0x80, 0xcc}, @@ -1181,7 +1189,7 @@ static const u8 mi1320_soc_InitVGA_JPG[][4] = { {0x06, 0x00, 0x11, 0xbb}, {0x07, 0x01, 0x42, 0xbb}, {0x08, 0x00, 0x11, 0xbb}, - {0x20, 0x01, 0x03, 0xbb}, + {0x20, 0x01, 0x03, 0xbb}, /* h/v flip */ {0x21, 0x80, 0x00, 0xbb}, {0x22, 0x0d, 0x0f, 0xbb}, {0x24, 0x80, 0x00, 0xbb}, @@ -1275,7 +1283,7 @@ static const u8 mi1320_soc_InitQVGA[][4] = { {0x07, 0x00, 0xe0, 0xbb}, {0x08, 0x00, 0x0b, 0xbb}, {0x21, 0x00, 0x0c, 0xbb}, - {0x20, 0x01, 0x03, 0xbb}, + {0x20, 0x01, 0x03, 0xbb}, /* h/v flip */ {0xbf, 0xc0, 0x26, 0xcc}, {0xbf, 0xc1, 0x02, 0xcc}, {0xbf, 0xcc, 0x04, 0xcc}, @@ -1295,7 +1303,7 @@ static const u8 mi1320_soc_InitQVGA[][4] = { {0x06, 0x00, 0x11, 0xbb}, {0x07, 0x01, 0x42, 0xbb}, {0x08, 0x00, 0x11, 0xbb}, - {0x20, 0x01, 0x03, 0xbb}, + {0x20, 0x01, 0x03, 0xbb}, /* h/v flip */ {0x21, 0x80, 0x00, 0xbb}, {0x22, 0x0d, 0x0f, 0xbb}, {0x24, 0x80, 0x00, 0xbb}, @@ -1389,7 +1397,7 @@ static const u8 mi1320_soc_InitQVGA_JPG[][4] = { {0x07, 0x00, 0xe0, 0xbb}, {0x08, 0x00, 0x0b, 0xbb}, {0x21, 0x00, 0x0c, 0xbb}, - {0x20, 0x01, 0x03, 0xbb}, + {0x20, 0x01, 0x03, 0xbb}, /* h/v flip */ {0xb6, 0x00, 0x00, 0xcc}, {0xb6, 0x03, 0x01, 0xcc}, {0xb6, 0x02, 0x40, 0xcc}, @@ -1421,7 +1429,7 @@ static const u8 mi1320_soc_InitQVGA_JPG[][4] = { {0x06, 0x00, 0x11, 0xbb}, {0x07, 0x01, 0x42, 0xbb}, {0x08, 0x00, 0x11, 0xbb}, - {0x20, 0x01, 0x03, 0xbb}, + {0x20, 0x01, 0x03, 0xbb}, /* h/v flip */ {0x21, 0x80, 0x00, 0xbb}, {0x22, 0x0d, 0x0f, 0xbb}, {0x24, 0x80, 0x00, 0xbb}, @@ -1513,7 +1521,7 @@ static const u8 mi1320_soc_InitSXGA_JPG[][4] = { {0x00, 0x00, 0x20, 0xdd}, {0xf0, 0x00, 0x00, 0xbb}, {0x00, 0x00, 0x30, 0xdd}, - {0x20, 0x01, 0x03, 0xbb}, + {0x20, 0x01, 0x03, 0xbb}, /* h/v flip */ {0x00, 0x00, 0x20, 0xdd}, {0xb6, 0x00, 0x00, 0xcc}, {0xb6, 0x03, 0x05, 0xcc}, @@ -1537,7 +1545,7 @@ static const u8 mi1320_soc_InitSXGA_JPG[][4] = { {0x06, 0x00, 0x11, 0xbb}, {0x07, 0x01, 0x42, 0xbb}, {0x08, 0x00, 0x11, 0xbb}, - {0x20, 0x01, 0x03, 0xbb}, + {0x20, 0x01, 0x03, 0xbb}, /* h/v flip */ {0x21, 0x80, 0x00, 0xbb}, {0x22, 0x0d, 0x0f, 0xbb}, {0x24, 0x80, 0x00, 0xbb}, @@ -1595,7 +1603,7 @@ static const u8 mi1320_soc_InitSXGA_JPG[][4] = { {0x06, 0x00, 0x11, 0xbb}, {0x07, 0x00, 0x85, 0xbb}, {0x08, 0x00, 0x27, 0xbb}, - {0x20, 0x01, 0x03, 0xbb}, + {0x20, 0x01, 0x03, 0xbb}, /* h/v flip */ {0x21, 0x80, 0x00, 0xbb}, {0x22, 0x0d, 0x0f, 0xbb}, {0x24, 0x80, 0x00, 0xbb}, @@ -1651,7 +1659,7 @@ static const u8 mi1320_soc_InitSXGA[][4] = { {0x00, 0x00, 0x20, 0xdd}, {0xf0, 0x00, 0x00, 0xbb}, {0x00, 0x00, 0x30, 0xdd}, - {0x20, 0x01, 0x03, 0xbb}, + {0x20, 0x01, 0x03, 0xbb}, /* h/v flip */ {0x00, 0x00, 0x20, 0xdd}, {0xbf, 0xc0, 0x26, 0xcc}, {0xbf, 0xc1, 0x02, 0xcc}, @@ -1662,7 +1670,7 @@ static const u8 mi1320_soc_InitSXGA[][4] = { {0x06, 0x00, 0x11, 0xbb}, {0x07, 0x01, 0x42, 0xbb}, {0x08, 0x00, 0x11, 0xbb}, - {0x20, 0x01, 0x03, 0xbb}, + {0x20, 0x01, 0x03, 0xbb}, /* h/v flip */ {0x21, 0x80, 0x00, 0xbb}, {0x22, 0x0d, 0x0f, 0xbb}, {0x24, 0x80, 0x00, 0xbb}, @@ -1720,7 +1728,7 @@ static const u8 mi1320_soc_InitSXGA[][4] = { {0x06, 0x00, 0x11, 0xbb}, {0x07, 0x00, 0x85, 0xbb}, {0x08, 0x00, 0x27, 0xbb}, - {0x20, 0x01, 0x03, 0xbb}, + {0x20, 0x01, 0x03, 0xbb}, /* h/v flip */ {0x21, 0x80, 0x00, 0xbb}, {0x22, 0x0d, 0x0f, 0xbb}, {0x24, 0x80, 0x00, 0xbb}, @@ -2877,7 +2885,7 @@ static int vc032x_probe_sensor(struct gspca_dev *gspca_dev) const struct sensor_info *ptsensor_info; /*fixme: should also check the other sensor (back mi1320_soc, front mc501cb)*/ - if (sd->ninput != 0) { + if (sd->flags & FL_SAMSUNG) { reg_w(dev, 0xa0, 0x01, 0xb301); #if 1 reg_w(dev, 0x89, 0xf0ff, 0xffff); /* select the back sensor */ @@ -3016,7 +3024,7 @@ static int sd_config(struct gspca_dev *gspca_dev, cam = &gspca_dev->cam; sd->bridge = id->driver_info >> 8; - sd->ninput = id->driver_info & 0xff; + sd->flags = id->driver_info & 0xff; #if 0 vc0321_reset(gspca_dev); #endif @@ -3072,8 +3080,6 @@ static int sd_config(struct gspca_dev *gspca_dev, case SENSOR_MI1320_SOC: cam->cam_mode = bi_mode; cam->nmodes = ARRAY_SIZE(bi_mode); - cam->input_flags = V4L2_IN_ST_VFLIP | - V4L2_IN_ST_HFLIP; break; default: cam->cam_mode = vc0323_mode; @@ -3085,14 +3091,14 @@ static int sd_config(struct gspca_dev *gspca_dev, sd->hflip = HFLIP_DEF; sd->vflip = VFLIP_DEF; - if (sd->sensor == SENSOR_OV7670) { - sd->hflip = 1; - sd->vflip = 1; - } + if (sd->sensor == SENSOR_OV7670) + sd->flags |= FL_HFLIP | FL_VFLIP; sd->lightfreq = FREQ_DEF; if (sd->sensor != SENSOR_OV7670) gspca_dev->ctrl_dis = (1 << LIGHTFREQ_IDX); switch (sd->sensor) { + case SENSOR_MI1310_SOC: + case SENSOR_MI1320_SOC: case SENSOR_OV7660: case SENSOR_OV7670: case SENSOR_PO1200: @@ -3121,33 +3127,44 @@ static int sd_init(struct gspca_dev *gspca_dev) return 0; } -/* for OV7660 and OV7670 only */ +/* some sensors only */ static void sethvflip(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; - __u8 data; - + u8 data[2], hflip, vflip; + + hflip = sd->hflip; + if (sd->flags & FL_HFLIP) + hflip != hflip; + vflip = sd->vflip; + if (sd->flags & FL_VFLIP) + vflip != vflip; switch (sd->sensor) { - case SENSOR_OV7660: - data = 1; + case SENSOR_MI1310_SOC: + case SENSOR_MI1320_SOC: + data[0] = data[1] = 0; /* select page 0 */ + i2c_write(gspca_dev, 0xf0, data, 2); + data[0] = sd->sensor == SENSOR_MI1310_SOC ? 0x03 : 0x01; + data[1] = 0x02 * hflip + | 0x01 * vflip; + i2c_write(gspca_dev, 0x20, data, 2); break; + case SENSOR_OV7660: case SENSOR_OV7670: - data = 7; + data[0] = sd->sensor == SENSOR_OV7660 ? 0x01 : 0x07; + data[0] |= OV7660_MVFP_MIRROR * hflip + | OV7660_MVFP_VFLIP * vflip; + i2c_write(gspca_dev, OV7660_REG_MVFP, data, 1); break; case SENSOR_PO1200: - data = 0; - i2c_write(gspca_dev, 0x03, &data, 1); - data = 0x80 * sd->hflip - | 0x40 * sd->vflip + data[0] = 0; + i2c_write(gspca_dev, 0x03, data, 1); + data[0] = 0x80 * hflip + | 0x40 * vflip | 0x06; - i2c_write(gspca_dev, 0x1e, &data, 1); - return; - default: - return; + i2c_write(gspca_dev, 0x1e, data, 1); + break; } - data |= OV7660_MVFP_MIRROR * sd->hflip - | OV7660_MVFP_VFLIP * sd->vflip; - i2c_write(gspca_dev, OV7660_REG_MVFP, &data, 1); } static void setlightfreq(struct gspca_dev *gspca_dev) @@ -3194,7 +3211,7 @@ static int sd_start(struct gspca_dev *gspca_dev) }; /*fixme: back sensor only*/ - if (sd->ninput != 0) { + if (sd->flags & FL_SAMSUNG) { reg_w(gspca_dev->dev, 0x89, 0xf0ff, 0xffff); reg_w(gspca_dev->dev, 0xa9, 0x8348, 0x000e); reg_w(gspca_dev->dev, 0xa9, 0x0000, 0x001a); @@ -3488,7 +3505,7 @@ static const struct sd_desc sd_desc = { .driver_info = (BRIDGE_ ## bridge << 8) \ | (flags) static const __devinitdata struct usb_device_id device_table[] = { - {USB_DEVICE(0x041e, 0x405b), BF(VC0323, 0)}, + {USB_DEVICE(0x041e, 0x405b), BF(VC0323, FL_VFLIP)}, {USB_DEVICE(0x046d, 0x0892), BF(VC0321, 0)}, {USB_DEVICE(0x046d, 0x0896), BF(VC0321, 0)}, {USB_DEVICE(0x046d, 0x0897), BF(VC0321, 0)}, @@ -3497,7 +3514,7 @@ static const __devinitdata struct usb_device_id device_table[] = { {USB_DEVICE(0x0ac8, 0x0328), BF(VC0321, 0)}, {USB_DEVICE(0x0ac8, 0xc001), BF(VC0321, 0)}, {USB_DEVICE(0x0ac8, 0xc002), BF(VC0321, 0)}, - {USB_DEVICE(0x0ac8, 0xc301), BF(VC0323, 1)}, + {USB_DEVICE(0x0ac8, 0xc301), BF(VC0323, FL_SAMSUNG)}, {USB_DEVICE(0x15b8, 0x6001), BF(VC0323, 0)}, {USB_DEVICE(0x15b8, 0x6002), BF(VC0323, 0)}, {USB_DEVICE(0x17ef, 0x4802), BF(VC0323, 0)}, -- cgit v1.2.3 From c5009fa8355db0bbf3316c237eda11f593344e75 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Mon, 27 Jul 2009 11:28:37 +0200 Subject: gspca - vc032x: Cleanup source. From: Jean-Francois Moine Priority: normal Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/vc032x.c | 122 +++++++++++++++---------------- 1 file changed, 57 insertions(+), 65 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/vc032x.c b/linux/drivers/media/video/gspca/vc032x.c index 97b9d677c..44dea7949 100644 --- a/linux/drivers/media/video/gspca/vc032x.c +++ b/linux/drivers/media/video/gspca/vc032x.c @@ -32,14 +32,14 @@ MODULE_LICENSE("GPL"); struct sd { struct gspca_dev gspca_dev; /* !! must be the first item */ - __u8 hflip; - __u8 vflip; - __u8 lightfreq; - __u8 sharpness; + u8 hflip; + u8 vflip; + u8 lightfreq; + u8 sharpness; u8 image_offset; - char bridge; + u8 bridge; #define BRIDGE_VC0321 0 #define BRIDGE_VC0323 1 u8 sensor; @@ -213,11 +213,11 @@ static const struct v4l2_pix_format svga_mode[] = { #define OV7660_MVFP_MIRROR 0x20 #define OV7660_MVFP_VFLIP 0x10 -static const __u8 mi0360_matrix[9] = { +static const u8 mi0360_matrix[9] = { 0x50, 0xf8, 0xf8, 0xf5, 0x50, 0xfb, 0xff, 0xf1, 0x50 }; -static const __u8 mi0360_initVGA_JPG[][4] = { +static const u8 mi0360_initVGA_JPG[][4] = { {0xb0, 0x03, 0x19, 0xcc}, {0xb0, 0x04, 0x02, 0xcc}, {0xb3, 0x00, 0x24, 0xcc}, @@ -326,7 +326,7 @@ static const __u8 mi0360_initVGA_JPG[][4] = { {0xb3, 0x5c, 0x01, 0xcc}, {} }; -static const __u8 mi0360_initQVGA_JPG[][4] = { +static const u8 mi0360_initQVGA_JPG[][4] = { {0xb0, 0x03, 0x19, 0xcc}, {0xb0, 0x04, 0x02, 0xcc}, {0xb3, 0x00, 0x24, 0xcc}, @@ -446,7 +446,7 @@ static const __u8 mi0360_initQVGA_JPG[][4] = { {} }; -static const __u8 mi1310_socinitVGA_JPG[][4] = { +static const u8 mi1310_socinitVGA_JPG[][4] = { {0xb0, 0x03, 0x19, 0xcc}, {0xb0, 0x04, 0x02, 0xcc}, {0xb3, 0x00, 0x64, 0xcc}, @@ -598,7 +598,7 @@ static const __u8 mi1310_socinitVGA_JPG[][4] = { {0x03, 0x03, 0xc0, 0xbb}, {}, }; -static const __u8 mi1310_socinitQVGA_JPG[][4] = { +static const u8 mi1310_socinitQVGA_JPG[][4] = { {0xb0, 0x03, 0x19, 0xcc}, {0xb0, 0x04, 0x02, 0xcc}, {0xb3, 0x00, 0x64, 0xcc}, {0xb3, 0x00, 0x65, 0xcc}, {0xb3, 0x05, 0x00, 0xcc}, {0xb3, 0x06, 0x00, 0xcc}, @@ -870,14 +870,14 @@ static const u8 mi1310_soc_InitSXGA_JPG[][4] = { {} }; -static const __u8 mi1320_gamma[17] = { +static const u8 mi1320_gamma[17] = { 0x00, 0x13, 0x38, 0x59, 0x79, 0x92, 0xa7, 0xb9, 0xc8, 0xd4, 0xdf, 0xe7, 0xee, 0xf4, 0xf9, 0xfc, 0xff }; -static const __u8 mi1320_matrix[9] = { +static const u8 mi1320_matrix[9] = { 0x54, 0xda, 0x06, 0xf1, 0x50, 0xf4, 0xf7, 0xea, 0x52 }; -static const __u8 mi1320_initVGA_data[][4] = { +static const u8 mi1320_initVGA_data[][4] = { {0xb3, 0x01, 0x01, 0xcc}, {0x00, 0x00, 0x33, 0xdd}, {0xb0, 0x03, 0x19, 0xcc}, {0x00, 0x00, 0x33, 0xdd}, {0xb0, 0x04, 0x02, 0xcc}, {0x00, 0x00, 0x33, 0xdd}, @@ -956,7 +956,7 @@ static const __u8 mi1320_initVGA_data[][4] = { {0xb3, 0x5c, 0x01, 0xcc}, {0xb3, 0x01, 0x41, 0xcc}, {} }; -static const __u8 mi1320_initQVGA_data[][4] = { +static const u8 mi1320_initQVGA_data[][4] = { {0xb3, 0x01, 0x01, 0xcc}, {0x00, 0x00, 0x33, 0xdd}, {0xb0, 0x03, 0x19, 0xcc}, {0x00, 0x00, 0x33, 0xdd}, {0xb0, 0x04, 0x02, 0xcc}, {0x00, 0x00, 0x33, 0xdd}, @@ -1747,15 +1747,15 @@ static const u8 mi1320_soc_InitSXGA[][4] = { {0x64, 0x5e, 0x1c, 0xbb}, {} }; -static const __u8 po3130_gamma[17] = { +static const u8 po3130_gamma[17] = { 0x00, 0x13, 0x38, 0x59, 0x79, 0x92, 0xa7, 0xb9, 0xc8, 0xd4, 0xdf, 0xe7, 0xee, 0xf4, 0xf9, 0xfc, 0xff }; -static const __u8 po3130_matrix[9] = { +static const u8 po3130_matrix[9] = { 0x5f, 0xec, 0xf5, 0xf1, 0x5a, 0xf5, 0xf1, 0xec, 0x63 }; -static const __u8 po3130_initVGA_data[][4] = { +static const u8 po3130_initVGA_data[][4] = { {0xb0, 0x4d, 0x00, 0xcc}, {0xb3, 0x01, 0x01, 0xcc}, {0x00, 0x00, 0x50, 0xdd}, {0xb0, 0x03, 0x01, 0xcc}, {0xb3, 0x00, 0x04, 0xcc}, {0xb3, 0x00, 0x24, 0xcc}, @@ -1838,7 +1838,7 @@ static const __u8 po3130_initVGA_data[][4] = { {0xb3, 0x5c, 0x00, 0xcc}, {0xb3, 0x01, 0x41, 0xcc}, {} }; -static const __u8 po3130_rundata[][4] = { +static const u8 po3130_rundata[][4] = { {0x00, 0x47, 0x45, 0xaa}, {0x00, 0x48, 0x9b, 0xaa}, {0x00, 0x49, 0x3a, 0xaa}, {0x00, 0x4a, 0x01, 0xaa}, {0x00, 0x44, 0x40, 0xaa}, @@ -1853,7 +1853,7 @@ static const __u8 po3130_rundata[][4] = { {} }; -static const __u8 po3130_initQVGA_data[][4] = { +static const u8 po3130_initQVGA_data[][4] = { {0xb0, 0x4d, 0x00, 0xcc}, {0xb3, 0x01, 0x01, 0xcc}, {0x00, 0x00, 0x50, 0xdd}, {0xb0, 0x03, 0x09, 0xcc}, {0xb3, 0x00, 0x04, 0xcc}, {0xb3, 0x00, 0x24, 0xcc}, @@ -1939,16 +1939,16 @@ static const __u8 po3130_initQVGA_data[][4] = { {} }; -static const __u8 hv7131r_gamma[17] = { +static const u8 hv7131r_gamma[17] = { /* 0x00, 0x13, 0x38, 0x59, 0x79, 0x92, 0xa7, 0xb9, 0xc8, * 0xd4, 0xdf, 0xe7, 0xee, 0xf4, 0xf9, 0xfc, 0xff */ 0x04, 0x1a, 0x36, 0x55, 0x6f, 0x87, 0x9d, 0xb0, 0xc1, 0xcf, 0xda, 0xe4, 0xec, 0xf3, 0xf8, 0xfd, 0xff }; -static const __u8 hv7131r_matrix[9] = { +static const u8 hv7131r_matrix[9] = { 0x5f, 0xec, 0xf5, 0xf1, 0x5a, 0xf5, 0xf1, 0xec, 0x63 }; -static const __u8 hv7131r_initVGA_data[][4] = { +static const u8 hv7131r_initVGA_data[][4] = { {0xb0, 0x4d, 0x00, 0xcc}, {0xb3, 0x01, 0x01, 0xcc}, {0x00, 0x00, 0x50, 0xdd}, {0xb0, 0x03, 0x01, 0xcc}, {0xb3, 0x00, 0x24, 0xcc}, @@ -1991,7 +1991,7 @@ static const __u8 hv7131r_initVGA_data[][4] = { {} }; -static const __u8 hv7131r_initQVGA_data[][4] = { +static const u8 hv7131r_initQVGA_data[][4] = { {0xb0, 0x4d, 0x00, 0xcc}, {0xb3, 0x01, 0x01, 0xcc}, {0x00, 0x00, 0x50, 0xdd}, {0xb0, 0x03, 0x01, 0xcc}, {0xb3, 0x00, 0x24, 0xcc}, @@ -2046,14 +2046,14 @@ static const __u8 hv7131r_initQVGA_data[][4] = { {} }; -static const __u8 ov7660_gamma[17] = { +static const u8 ov7660_gamma[17] = { 0x00, 0x13, 0x38, 0x59, 0x79, 0x92, 0xa7, 0xb9, 0xc8, 0xd4, 0xdf, 0xe7, 0xee, 0xf4, 0xf9, 0xfc, 0xff }; -static const __u8 ov7660_matrix[9] = { +static const u8 ov7660_matrix[9] = { 0x5a, 0xf0, 0xf6, 0xf3, 0x57, 0xf6, 0xf3, 0xef, 0x62 }; -static const __u8 ov7660_initVGA_data[][4] = { +static const u8 ov7660_initVGA_data[][4] = { {0xb0, 0x4d, 0x00, 0xcc}, {0xb3, 0x01, 0x01, 0xcc}, {0x00, 0x00, 0x50, 0xdd}, {0xb0, 0x03, 0x01, 0xcc}, @@ -2111,7 +2111,7 @@ static const __u8 ov7660_initVGA_data[][4] = { {0x00, 0x29, 0x3c, 0xaa}, {0xb3, 0x01, 0x45, 0xcc}, {} }; -static const __u8 ov7660_initQVGA_data[][4] = { +static const u8 ov7660_initQVGA_data[][4] = { {0xb0, 0x4d, 0x00, 0xcc}, {0xb3, 0x01, 0x01, 0xcc}, {0x00, 0x00, 0x50, 0xdd}, {0xb0, 0x03, 0x01, 0xcc}, {0xb3, 0x00, 0x21, 0xcc}, {0xb3, 0x00, 0x26, 0xcc}, @@ -2180,26 +2180,26 @@ static const __u8 ov7660_initQVGA_data[][4] = { {} }; -static const __u8 ov7660_50HZ[][4] = { +static const u8 ov7660_50HZ[][4] = { {0x00, 0x3b, 0x08, 0xaa}, {0x00, 0x9d, 0x40, 0xaa}, {0x00, 0x13, 0xa7, 0xaa}, {} }; -static const __u8 ov7660_60HZ[][4] = { +static const u8 ov7660_60HZ[][4] = { {0x00, 0x3b, 0x00, 0xaa}, {0x00, 0x9e, 0x40, 0xaa}, {0x00, 0x13, 0xa7, 0xaa}, {} }; -static const __u8 ov7660_NoFliker[][4] = { +static const u8 ov7660_NoFliker[][4] = { {0x00, 0x13, 0x87, 0xaa}, {} }; -static const __u8 ov7670_initVGA_JPG[][4] = { +static const u8 ov7670_initVGA_JPG[][4] = { {0xb3, 0x01, 0x05, 0xcc}, {0x00, 0x00, 0x30, 0xdd}, {0xb0, 0x03, 0x19, 0xcc}, {0x00, 0x00, 0x10, 0xdd}, @@ -2329,7 +2329,7 @@ static const __u8 ov7670_initVGA_JPG[][4] = { {}, }; -static const __u8 ov7670_initQVGA_JPG[][4] = { +static const u8 ov7670_initQVGA_JPG[][4] = { {0xb3, 0x01, 0x05, 0xcc}, {0x00, 0x00, 0x30, 0xdd}, {0xb0, 0x03, 0x19, 0xcc}, {0x00, 0x00, 0x10, 0xdd}, {0xb0, 0x04, 0x02, 0xcc}, {0x00, 0x00, 0x10, 0xdd}, @@ -2464,7 +2464,7 @@ static const __u8 ov7670_initQVGA_JPG[][4] = { }; /* PO1200 - values from usbvm326.inf and ms-win trace */ -static const __u8 po1200_gamma[17] = { +static const u8 po1200_gamma[17] = { #if 1 0x00, 0x13, 0x38, 0x59, 0x79, 0x92, 0xa7, 0xb9, 0xc8, 0xd4, 0xdf, 0xe7, 0xee, 0xf4, 0xf9, 0xfc, 0xff @@ -2474,10 +2474,10 @@ static const __u8 po1200_gamma[17] = { 0xc1, 0xd0, 0xdd, 0xe8, 0xf2, 0xf9, 0xff, 0xff #endif }; -static const __u8 po1200_matrix[9] = { +static const u8 po1200_matrix[9] = { 0x60, 0xf9, 0xe5, 0xe7, 0x50, 0x05, 0xf3, 0xe6, 0x5e }; -static const __u8 po1200_initVGA_data[][4] = { +static const u8 po1200_initVGA_data[][4] = { {0xb0, 0x03, 0x19, 0xcc}, /* reset? */ #if 0 {0x00, 0x00, 0x64, 0xdd}, @@ -2812,9 +2812,9 @@ static const struct sensor_info sensor_info_data[] = { /* read 'len' bytes in gspca_dev->usb_buf */ static void reg_r(struct gspca_dev *gspca_dev, - __u16 req, - __u16 index, - __u16 len) + u16 req, + u16 index, + u16 len) { usb_control_msg(gspca_dev->dev, usb_rcvctrlpipe(gspca_dev->dev, 0), @@ -2826,9 +2826,9 @@ static void reg_r(struct gspca_dev *gspca_dev, } static void reg_w(struct usb_device *dev, - __u16 req, - __u16 value, - __u16 index) + u16 req, + u16 value, + u16 index) { usb_control_msg(dev, usb_sndctrlpipe(dev, 0), @@ -2953,17 +2953,17 @@ static void i2c_write(struct gspca_dev *gspca_dev, } static void put_tab_to_reg(struct gspca_dev *gspca_dev, - const __u8 *tab, __u8 tabsize, __u16 addr) + const u8 *tab, u8 tabsize, u16 addr) { int j; - __u16 ad = addr; + u16 ad = addr; for (j = 0; j < tabsize; j++) reg_w(gspca_dev->dev, 0xa0, tab[j], ad++); } static void usb_exchange(struct gspca_dev *gspca_dev, - const __u8 data[][4]) + const u8 data[][4]) { struct usb_device *dev = gspca_dev->dev; int i = 0; @@ -3170,7 +3170,7 @@ static void sethvflip(struct gspca_dev *gspca_dev) static void setlightfreq(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; - static const __u8 (*ov7660_freq_tb[3])[4] = + static const u8 (*ov7660_freq_tb[3])[4] = {ov7660_NoFliker, ov7660_50HZ, ov7660_60HZ}; if (sd->sensor != SENSOR_OV7660) @@ -3182,7 +3182,7 @@ static void setlightfreq(struct gspca_dev *gspca_dev) static void setsharpness(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; - __u8 data; + u8 data; if (sd->sensor != SENSOR_PO1200) return; @@ -3195,9 +3195,9 @@ static void setsharpness(struct gspca_dev *gspca_dev) static int sd_start(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; - const __u8 (*init)[4]; - const __u8 *GammaT = NULL; - const __u8 *MatrixT = NULL; + const u8 (*init)[4]; + const u8 *GammaT = NULL; + const u8 *MatrixT = NULL; int mode; static const u8 (*mi1320_soc_init[])[4] = { mi1320_soc_InitSXGA, @@ -3343,7 +3343,7 @@ static void sd_stopN(struct gspca_dev *gspca_dev) struct usb_device *dev = gspca_dev->dev; struct sd *sd = (struct sd *) gspca_dev; - if( sd->sensor == SENSOR_MI1310_SOC) + if (sd->sensor == SENSOR_MI1310_SOC) reg_w(dev, 0x89, 0x058c, 0x00ff); else reg_w(dev, 0x89, 0xffff, 0xffff); @@ -3359,7 +3359,8 @@ static void sd_stop0(struct gspca_dev *gspca_dev) if (!gspca_dev->present) return; - if( sd->sensor == SENSOR_MI1310_SOC) +/*fixme: is this useful?*/ + if (sd->sensor == SENSOR_MI1310_SOC) reg_w(dev, 0x89, 0x058c, 0x00ff); else reg_w(dev, 0x89, 0xffff, 0xffff); @@ -3367,7 +3368,7 @@ static void sd_stop0(struct gspca_dev *gspca_dev) static void sd_pkt_scan(struct gspca_dev *gspca_dev, struct gspca_frame *frame, /* target */ - __u8 *data, /* isoc packet */ + u8 *data, /* isoc packet */ int len) /* iso pkt length */ { struct sd *sd = (struct sd *) gspca_dev; @@ -3467,21 +3468,12 @@ static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val) static int sd_querymenu(struct gspca_dev *gspca_dev, struct v4l2_querymenu *menu) { + static const char *freq_nm[3] = {"NoFliker", "50 Hz", "60 Hz"}; + switch (menu->id) { case V4L2_CID_POWER_LINE_FREQUENCY: - switch (menu->index) { - case 0: /* V4L2_CID_POWER_LINE_FREQUENCY_DISABLED */ - strcpy((char *) menu->name, "NoFliker"); - return 0; - case 1: /* V4L2_CID_POWER_LINE_FREQUENCY_50HZ */ - strcpy((char *) menu->name, "50 Hz"); - return 0; - default: -/* case 2: * V4L2_CID_POWER_LINE_FREQUENCY_60HZ */ - strcpy((char *) menu->name, "60 Hz"); - return 0; - } - break; + strcpy((char *) menu->name, freq_nm[menu->index]); + return 0; } return -EINVAL; } -- cgit v1.2.3 From 09967917f95eee6651fb685695f91598840e114b Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Mon, 27 Jul 2009 16:35:59 -0400 Subject: au0828: fix typo: dvb uses bulk xfer, dont say isoc in debug From: Michael Krufky The au0828-dvb driver uses bulk usb transfers for digital transport, but the debug reports, "iso xfer already running!\n". Fix this to report bulk instead of isoc. Priority: normal Signed-off-by: Michael Krufky --- linux/drivers/media/video/au0828/au0828-dvb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/au0828/au0828-dvb.c b/linux/drivers/media/video/au0828/au0828-dvb.c index 104f15cc3..93c665067 100644 --- a/linux/drivers/media/video/au0828/au0828-dvb.c +++ b/linux/drivers/media/video/au0828/au0828-dvb.c @@ -156,7 +156,7 @@ static int start_urb_transfer(struct au0828_dev *dev) dprintk(2, "%s()\n", __func__); if (dev->urb_streaming) { - dprintk(2, "%s: iso xfer already running!\n", __func__); + dprintk(2, "%s: bulk xfer already running!\n", __func__); return 0; } -- cgit v1.2.3 From f2405beb3c4b581cfb5754e7891dec8a3129b299 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Tue, 28 Jul 2009 08:39:10 +0200 Subject: gspca - sonixj: Webcam 0c45:6148 added. From: Denis Loginov Priority: normal Signed-off-by: Denis Loginov Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/sonixj.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/sonixj.c b/linux/drivers/media/video/gspca/sonixj.c index 5568401e8..98fb39c99 100644 --- a/linux/drivers/media/video/gspca/sonixj.c +++ b/linux/drivers/media/video/gspca/sonixj.c @@ -2384,7 +2384,8 @@ static const __devinitdata struct usb_device_id device_table[] = { {USB_DEVICE(0x0c45, 0x60fe), BSI(SN9C105, OV7630, 0x21)}, #endif {USB_DEVICE(0x0c45, 0x6100), BSI(SN9C120, MI0360, 0x5d)}, /*sn9c128*/ -/* {USB_DEVICE(0x0c45, 0x6108), BSI(SN9C120, OM6801, 0x??)}, */ +/* {USB_DEVICE(0x0c45, 0x6102), BSI(SN9C120, PO2030N, ??)}, */ +/* {USB_DEVICE(0x0c45, 0x6108), BSI(SN9C120, OM6802, 0x21)}, */ {USB_DEVICE(0x0c45, 0x610a), BSI(SN9C120, OV7648, 0x21)}, /*sn9c128*/ {USB_DEVICE(0x0c45, 0x610b), BSI(SN9C120, OV7660, 0x21)}, /*sn9c128*/ {USB_DEVICE(0x0c45, 0x610c), BSI(SN9C120, HV7131R, 0x11)}, /*sn9c128*/ @@ -2400,6 +2401,7 @@ static const __devinitdata struct usb_device_id device_table[] = { #if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE {USB_DEVICE(0x0c45, 0x6130), BSI(SN9C120, MI0360, 0x5d)}, #endif +/* {USB_DEVICE(0x0c45, 0x6132), BSI(SN9C120, OV7670, 0x21)}, */ {USB_DEVICE(0x0c45, 0x6138), BSI(SN9C120, MO4000, 0x21)}, {USB_DEVICE(0x0c45, 0x613a), BSI(SN9C120, OV7648, 0x21)}, #if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE @@ -2407,7 +2409,9 @@ static const __devinitdata struct usb_device_id device_table[] = { #endif {USB_DEVICE(0x0c45, 0x613c), BSI(SN9C120, HV7131R, 0x11)}, {USB_DEVICE(0x0c45, 0x613e), BSI(SN9C120, OV7630, 0x21)}, - {USB_DEVICE(0x0c45, 0x6143), BSI(SN9C120, SP80708, 0x18)}, +/* {USB_DEVICE(0x0c45, 0x6142), BSI(SN9C120, PO2030N, ??)}, *sn9c120b*/ + {USB_DEVICE(0x0c45, 0x6143), BSI(SN9C120, SP80708, 0x18)}, /*sn9c120b*/ + {USB_DEVICE(0x0c45, 0x6148), BSI(SN9C120, OM6802, 0x21)}, /*sn9c120b*/ {} }; MODULE_DEVICE_TABLE(usb, device_table); -- cgit v1.2.3 From bf8e2366acf0eddbefdabe74b14e0b3634fcd669 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Tue, 28 Jul 2009 09:28:45 +0200 Subject: gspca - tv8532: Bad ISOC packet scan. From: Hans de Goede Priority: normal Signed-off-by: Hans de Goede Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/tv8532.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/tv8532.c b/linux/drivers/media/video/gspca/tv8532.c index 79b78f234..29c765304 100644 --- a/linux/drivers/media/video/gspca/tv8532.c +++ b/linux/drivers/media/video/gspca/tv8532.c @@ -432,7 +432,7 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, gspca_frame_add(gspca_dev, packet_type0, frame, data + 2, gspca_dev->width); gspca_frame_add(gspca_dev, packet_type1, - frame, data + gspca_dev->width + 6, gspca_dev->width); + frame, data + gspca_dev->width + 5, gspca_dev->width); } static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val) -- cgit v1.2.3 From f36217342b748f16badc1abb3aaeb433ee088020 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Tue, 28 Jul 2009 09:38:25 +0200 Subject: gspca - main: Memorize the current alt before setting it. From: Jean-Francois Moine This prevents a loop if a permanent error occurs in usb_set_interface(). Priority: normal Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/gspca.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/gspca.c b/linux/drivers/media/video/gspca/gspca.c index eedf9a60c..2e5197073 100644 --- a/linux/drivers/media/video/gspca/gspca.c +++ b/linux/drivers/media/video/gspca/gspca.c @@ -498,6 +498,7 @@ static struct usb_host_endpoint *get_ep(struct gspca_dev *gspca_dev) } PDEBUG(D_STREAM, "use alt %d ep 0x%02x", i, ep->desc.bEndpointAddress); + gspca_dev->alt = i; /* memorize the current alt setting */ if (gspca_dev->nbalt > 1) { ret = usb_set_interface(gspca_dev->dev, gspca_dev->iface, i); if (ret < 0) { @@ -505,7 +506,6 @@ static struct usb_host_endpoint *get_ep(struct gspca_dev *gspca_dev) return NULL; } } - gspca_dev->alt = i; /* memorize the current alt setting */ return ep; } -- cgit v1.2.3 From 79035e11d5ad4166c51bf7e7c334000494e0a859 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 29 Jul 2009 01:39:12 -0300 Subject: em28xx: fix support for Plextor ConvertX PX-TV100U From: Mauro Carvalho Chehab This device uses msp34xx and uses 2.048 MHz frequency for I2S communication. Thanks to Angelo Cano for pointing the issues with this device and proposing an approach for fixing the issue. Priority: normal Tested-by: Angelo Cano Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/em28xx/em28xx-cards.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (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 6e4a44331..795fd16a5 100644 --- a/linux/drivers/media/video/em28xx/em28xx-cards.c +++ b/linux/drivers/media/video/em28xx/em28xx-cards.c @@ -639,22 +639,27 @@ struct em28xx_board em28xx_boards[] = { }, [EM2861_BOARD_PLEXTOR_PX_TV100U] = { .name = "Plextor ConvertX PX-TV100U", - .valid = EM28XX_BOARD_NOT_VALIDATED, .tuner_type = TUNER_TNF_5335MF, + .xclk = EM28XX_XCLK_I2S_MSB_TIMING | + EM28XX_XCLK_FREQUENCY_12MHZ, .tda9887_conf = TDA9887_PRESENT, .decoder = EM28XX_TVP5150, + .has_msp34xx = 1, .input = { { .type = EM28XX_VMUX_TELEVISION, .vmux = TVP5150_COMPOSITE0, .amux = EM28XX_AMUX_LINE_IN, + .gpio = pinnacle_hybrid_pro_analog, }, { .type = EM28XX_VMUX_COMPOSITE1, .vmux = TVP5150_COMPOSITE1, .amux = EM28XX_AMUX_LINE_IN, + .gpio = pinnacle_hybrid_pro_analog, }, { .type = EM28XX_VMUX_SVIDEO, .vmux = TVP5150_SVIDEO, .amux = EM28XX_AMUX_LINE_IN, + .gpio = pinnacle_hybrid_pro_analog, } }, }, @@ -1948,9 +1953,8 @@ void em28xx_pre_card_setup(struct em28xx *dev) /* request some modules */ switch (dev->model) { case EM2861_BOARD_PLEXTOR_PX_TV100U: - /* FIXME guess */ - /* Turn on analog audio output */ - em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xfd); + /* Sets the msp34xx I2S speed */ + dev->i2s_speed = 2048000; break; case EM2861_BOARD_KWORLD_PVRTV_300U: case EM2880_BOARD_KWORLD_DVB_305U: -- cgit v1.2.3 From b6e13ad1e52efcb4693b9260cb0cff0c6e85537f Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 29 Jul 2009 01:42:02 -0300 Subject: em28xx: fix audio VIDIOC_S_CTRL adjustments on devices without ac97 From: Mauro Carvalho Chehab Even devices without ac97 needs to call analog audio setup function, to properly set xclk and mute/unmute. Thanks to Angelo Cano for reporting and testing it. Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/em28xx/em28xx-video.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/em28xx/em28xx-video.c b/linux/drivers/media/video/em28xx/em28xx-video.c index 1237e325d..8cb8674c9 100644 --- a/linux/drivers/media/video/em28xx/em28xx-video.c +++ b/linux/drivers/media/video/em28xx/em28xx-video.c @@ -1123,9 +1123,26 @@ static int vidioc_s_ctrl(struct file *file, void *priv, else rc = 1; - /* It were not an AC97 control. Sends it to the v4l2 dev interface */ + /* It isn't an AC97 control. Sends it to the v4l2 dev interface */ if (rc == 1) { v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_ctrl, ctrl); + + /* + * In the case of non-AC97 volume controls, we still need + * to do some setups at em28xx, in order to mute/unmute + * and to adjust audio volume. However, the value ranges + * should be checked by the corresponding V4L subdriver. + */ + switch (ctrl->id) { + case V4L2_CID_AUDIO_MUTE: + dev->mute = ctrl->value; + return em28xx_audio_analog_set(dev); + break; + case V4L2_CID_AUDIO_VOLUME: + dev->volume = ctrl->value; + return em28xx_audio_analog_set(dev); + } + /* FIXME: should be returning a meaninful value */ rc = 0; } -- cgit v1.2.3 From ba0a4fd1311b247e1b3d5954c7412e72240542a1 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 30 Jul 2009 19:59:13 -0300 Subject: em28xx: fix mutex inbalance From: Mauro Carvalho Chehab Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/em28xx/em28xx-video.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/em28xx/em28xx-video.c b/linux/drivers/media/video/em28xx/em28xx-video.c index 8cb8674c9..fcb99fb71 100644 --- a/linux/drivers/media/video/em28xx/em28xx-video.c +++ b/linux/drivers/media/video/em28xx/em28xx-video.c @@ -1136,15 +1136,12 @@ static int vidioc_s_ctrl(struct file *file, void *priv, switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: dev->mute = ctrl->value; - return em28xx_audio_analog_set(dev); + rc = em28xx_audio_analog_set(dev); break; case V4L2_CID_AUDIO_VOLUME: dev->volume = ctrl->value; - return em28xx_audio_analog_set(dev); + rc = em28xx_audio_analog_set(dev); } - - /* FIXME: should be returning a meaninful value */ - rc = 0; } mutex_unlock(&dev->lock); -- cgit v1.2.3 From 51e081d10118c1d432f7aedc4cadd3776d56e700 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 28 Jul 2009 11:39:02 -0300 Subject: ir-kbd-i2c: fix spaces From: Douglas Schilling Landgraf Fixed checkpath warnings Priority: normal Signed-off-by: Douglas Schilling Landgraf Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/ir-kbd-i2c.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 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 cdf369129..fffe8239d 100644 --- a/linux/drivers/media/video/ir-kbd-i2c.c +++ b/linux/drivers/media/video/ir-kbd-i2c.c @@ -354,19 +354,19 @@ static struct i2c_driver driver = { .driver = { .name = "ir-kbd-i2c", }, - .id = I2C_DRIVERID_INFRARED, - .attach_adapter = ir_probe, - .detach_client = ir_detach, + .id = I2C_DRIVERID_INFRARED, + .attach_adapter = ir_probe, + .detach_client = ir_detach, }; - + static struct i2c_client client = { - .name = "unset", - .driver = &driver + .name = "unset", + .driver = &driver }; static int ir_attach(struct i2c_adapter *adap, int addr, - unsigned short flags, int kind) + unsigned short flags, int kind) #else static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) #endif @@ -492,7 +492,7 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) /* Sets name */ #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30) - snprintf(ir->c.name, sizeof(ir->c.name), "i2c IR (%s)", name); + snprintf(ir->c.name, sizeof(ir->c.name), "i2c IR (%s)", name); #else snprintf(ir->name, sizeof(ir->name), "i2c IR (%s)", name); #endif -- cgit v1.2.3 From 8239798d50a90e8d80bafdeade1aa38e77c537e1 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 28 Jul 2009 11:41:35 -0300 Subject: ir-kbd-i2c: Remove superfulous inlines From: Jean Delvare Functions which are referenced by their address can't be inlined by definition. Priority: normal Signed-off-by: Jean Delvare Signed-off-by: Andy Walls Signed-off-by: Douglas Schilling Landgraf Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/ir-kbd-i2c.c | 4 ++-- 1 file changed, 2 insertions(+), 2 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 fffe8239d..c61b22d25 100644 --- a/linux/drivers/media/video/ir-kbd-i2c.c +++ b/linux/drivers/media/video/ir-kbd-i2c.c @@ -127,12 +127,12 @@ static int get_key_haup_common(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw, return 1; } -static inline int get_key_haup(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) +static int get_key_haup(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) { return get_key_haup_common (ir, ir_key, ir_raw, 3, 0); } -static inline int get_key_haup_xvr(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) +static int get_key_haup_xvr(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) { return get_key_haup_common (ir, ir_key, ir_raw, 6, 3); } -- cgit v1.2.3 From 7059988b9d5badb3606286718c371665ff4a70ae Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 28 Jul 2009 11:44:05 -0300 Subject: ir-kbd-i2c: Allow use of ir-kdb-i2c internal get_key funcs and set ir_type From: Andy Walls This patch augments the init data passed by bridge drivers to ir-kbd-i2c, so that the ir_type can be set explicitly, and so ir-kbd-i2c internal get_key functions can be reused without requiring symbols from ir-kbd-i2c in the bridge driver. Priority: normal Signed-off-by: Andy Walls Reviewed-by: Jean Delvare Signed-off-by: Douglas Schilling Landgraf Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/ir-kbd-i2c.c | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) (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 c61b22d25..ae928be28 100644 --- a/linux/drivers/media/video/ir-kbd-i2c.c +++ b/linux/drivers/media/video/ir-kbd-i2c.c @@ -478,7 +478,36 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) ir_codes = init_data->ir_codes; name = init_data->name; - ir->get_key = init_data->get_key; + if (init_data->type) + ir_type = init_data->type; + + switch (init_data->internal_get_key_func) { + case IR_KBD_GET_KEY_CUSTOM: + /* The bridge driver provided us its own function */ + ir->get_key = init_data->get_key; + break; + case IR_KBD_GET_KEY_PIXELVIEW: + ir->get_key = get_key_pixelview; + break; + case IR_KBD_GET_KEY_PV951: + ir->get_key = get_key_pv951; + break; + case IR_KBD_GET_KEY_HAUP: + ir->get_key = get_key_haup; + break; + case IR_KBD_GET_KEY_KNC1: + ir->get_key = get_key_knc1; + break; + case IR_KBD_GET_KEY_FUSIONHDTV: + ir->get_key = get_key_fusionhdtv; + break; + case IR_KBD_GET_KEY_HAUP_XVR: + ir->get_key = get_key_haup_xvr; + break; + case IR_KBD_GET_KEY_AVERMEDIA_CARDBUS: + ir->get_key = get_key_avermedia_cardbus; + break; + } } /* Make sure we are all setup before going on */ -- cgit v1.2.3 From 0be3a0fdedcfa1995a6b1398ccea67554e7edad6 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 28 Jul 2009 11:48:18 -0300 Subject: cx18: Add i2c initialization for Z8F0811/Hauppage IR transceivers From: Andy Walls This patch add support to the cx18 driver for setting up the Z8F0811/Hauppauge IR Tx/Rx chip with the i2c binding model in newer kernels. Priority: normal Signed-off-by: Andy Walls Reviewed-by: Jean Delvare Signed-off-by: Douglas Schilling Landgraf Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/cx18/cx18-cards.c | 6 ++- linux/drivers/media/video/cx18/cx18-cards.h | 18 +++++---- linux/drivers/media/video/cx18/cx18-i2c.c | 63 +++++++++++++++++++++++++---- 3 files changed, 70 insertions(+), 17 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/cx18/cx18-cards.c b/linux/drivers/media/video/cx18/cx18-cards.c index c0abf3476..d34cba6a7 100644 --- a/linux/drivers/media/video/cx18/cx18-cards.c +++ b/linux/drivers/media/video/cx18/cx18-cards.c @@ -56,7 +56,8 @@ static const struct cx18_card cx18_card_hvr1600_esmt = { .hw_audio_ctrl = CX18_HW_418_AV, .hw_muxer = CX18_HW_CS5345, .hw_all = CX18_HW_TVEEPROM | CX18_HW_418_AV | CX18_HW_TUNER | - CX18_HW_CS5345 | CX18_HW_DVB | CX18_HW_GPIO_RESET_CTRL, + CX18_HW_CS5345 | CX18_HW_DVB | CX18_HW_GPIO_RESET_CTRL | + CX18_HW_Z8F0811_IR_HAUP, .video_inputs = { { CX18_CARD_INPUT_VID_TUNER, 0, CX18_AV_COMPOSITE7 }, { CX18_CARD_INPUT_SVIDEO1, 1, CX18_AV_SVIDEO1 }, @@ -102,7 +103,8 @@ static const struct cx18_card cx18_card_hvr1600_samsung = { .hw_audio_ctrl = CX18_HW_418_AV, .hw_muxer = CX18_HW_CS5345, .hw_all = CX18_HW_TVEEPROM | CX18_HW_418_AV | CX18_HW_TUNER | - CX18_HW_CS5345 | CX18_HW_DVB | CX18_HW_GPIO_RESET_CTRL, + CX18_HW_CS5345 | CX18_HW_DVB | CX18_HW_GPIO_RESET_CTRL | + CX18_HW_Z8F0811_IR_HAUP, .video_inputs = { { CX18_CARD_INPUT_VID_TUNER, 0, CX18_AV_COMPOSITE7 }, { CX18_CARD_INPUT_SVIDEO1, 1, CX18_AV_SVIDEO1 }, diff --git a/linux/drivers/media/video/cx18/cx18-cards.h b/linux/drivers/media/video/cx18/cx18-cards.h index 3c552b6b7..444e3c7c5 100644 --- a/linux/drivers/media/video/cx18/cx18-cards.h +++ b/linux/drivers/media/video/cx18/cx18-cards.h @@ -22,13 +22,17 @@ */ /* hardware flags */ -#define CX18_HW_TUNER (1 << 0) -#define CX18_HW_TVEEPROM (1 << 1) -#define CX18_HW_CS5345 (1 << 2) -#define CX18_HW_DVB (1 << 3) -#define CX18_HW_418_AV (1 << 4) -#define CX18_HW_GPIO_MUX (1 << 5) -#define CX18_HW_GPIO_RESET_CTRL (1 << 6) +#define CX18_HW_TUNER (1 << 0) +#define CX18_HW_TVEEPROM (1 << 1) +#define CX18_HW_CS5345 (1 << 2) +#define CX18_HW_DVB (1 << 3) +#define CX18_HW_418_AV (1 << 4) +#define CX18_HW_GPIO_MUX (1 << 5) +#define CX18_HW_GPIO_RESET_CTRL (1 << 6) +#define CX18_HW_Z8F0811_IR_TX_HAUP (1 << 7) +#define CX18_HW_Z8F0811_IR_RX_HAUP (1 << 8) +#define CX18_HW_Z8F0811_IR_HAUP (CX18_HW_Z8F0811_IR_RX_HAUP | \ + CX18_HW_Z8F0811_IR_TX_HAUP) /* video inputs */ #define CX18_CARD_INPUT_VID_TUNER 1 diff --git a/linux/drivers/media/video/cx18/cx18-i2c.c b/linux/drivers/media/video/cx18/cx18-i2c.c index cee650c58..c551fcd47 100644 --- a/linux/drivers/media/video/cx18/cx18-i2c.c +++ b/linux/drivers/media/video/cx18/cx18-i2c.c @@ -28,6 +28,9 @@ #include "cx18-gpio.h" #include "cx18-i2c.h" #include "cx18-irq.h" +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 30) +#include +#endif #define CX18_REG_I2C_1_WR 0xf15000 #define CX18_REG_I2C_1_RD 0xf15008 @@ -40,16 +43,20 @@ #define GETSDL_BIT 0x0008 #define CX18_CS5345_I2C_ADDR 0x4c +#define CX18_Z8F0811_IR_TX_I2C_ADDR 0x70 +#define CX18_Z8F0811_IR_RX_I2C_ADDR 0x71 /* This array should match the CX18_HW_ defines */ static const u8 hw_addrs[] = { - 0, /* CX18_HW_TUNER */ - 0, /* CX18_HW_TVEEPROM */ - CX18_CS5345_I2C_ADDR, /* CX18_HW_CS5345 */ - 0, /* CX18_HW_DVB */ - 0, /* CX18_HW_418_AV */ - 0, /* CX18_HW_GPIO_MUX */ - 0, /* CX18_HW_GPIO_RESET_CTRL */ + 0, /* CX18_HW_TUNER */ + 0, /* CX18_HW_TVEEPROM */ + CX18_CS5345_I2C_ADDR, /* CX18_HW_CS5345 */ + 0, /* CX18_HW_DVB */ + 0, /* CX18_HW_418_AV */ + 0, /* CX18_HW_GPIO_MUX */ + 0, /* CX18_HW_GPIO_RESET_CTRL */ + CX18_Z8F0811_IR_TX_I2C_ADDR, /* CX18_HW_Z8F0811_IR_TX_HAUP */ + CX18_Z8F0811_IR_RX_I2C_ADDR, /* CX18_HW_Z8F0811_IR_RX_HAUP */ }; /* This array should match the CX18_HW_ defines */ @@ -62,6 +69,8 @@ static const u8 hw_bus[] = { 0, /* CX18_HW_418_AV */ 0, /* CX18_HW_GPIO_MUX */ 0, /* CX18_HW_GPIO_RESET_CTRL */ + 0, /* CX18_HW_Z8F0811_IR_TX_HAUP */ + 0, /* CX18_HW_Z8F0811_IR_RX_HAUP */ }; /* This array should match the CX18_HW_ defines */ @@ -73,6 +82,8 @@ static const char * const hw_modules[] = { NULL, /* CX18_HW_418_AV */ NULL, /* CX18_HW_GPIO_MUX */ NULL, /* CX18_HW_GPIO_RESET_CTRL */ + NULL, /* CX18_HW_Z8F0811_IR_TX_HAUP */ + NULL, /* CX18_HW_Z8F0811_IR_RX_HAUP */ }; /* This array should match the CX18_HW_ defines */ @@ -84,8 +95,41 @@ static const char * const hw_devicenames[] = { "cx23418_AV", "gpio_mux", "gpio_reset_ctrl", + "ir_tx_z8f0811_haup", + "ir_rx_z8f0811_haup", }; +static int cx18_i2c_new_ir(struct i2c_adapter *adap, u32 hw, const char *type, + u8 addr) +{ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 30) + struct i2c_board_info info; + struct IR_i2c_init_data ir_init_data; + unsigned short addr_list[2] = { addr, I2C_CLIENT_END }; + + memset(&info, 0, sizeof(struct i2c_board_info)); + strlcpy(info.type, type, I2C_NAME_SIZE); + + /* Our default information for ir-kbd-i2c.c to use */ + switch (hw) { + case CX18_HW_Z8F0811_IR_RX_HAUP: + memset(&ir_init_data, 0, sizeof(struct IR_i2c_init_data)); + ir_init_data.ir_codes = ir_codes_hauppauge_new; + ir_init_data.internal_get_key_func = IR_KBD_GET_KEY_HAUP_XVR; + ir_init_data.type = IR_TYPE_RC5; + ir_init_data.name = "CX23418 Z8F0811 Hauppauge"; + info.platform_data = &ir_init_data; + break; + default: + break; + } + + return i2c_new_probed_device(adap, &info, addr_list) == NULL ? -1 : 0; +#else + return -1; +#endif +} + int cx18_i2c_register(struct cx18 *cx, unsigned idx) { struct v4l2_subdev *sd; @@ -115,11 +159,14 @@ int cx18_i2c_register(struct cx18 *cx, unsigned idx) return sd != NULL ? 0 : -1; } + if (hw & CX18_HW_Z8F0811_IR_HAUP) + return cx18_i2c_new_ir(adap, hw, type, hw_addrs[idx]); + /* Is it not an I2C device or one we do not wish to register? */ if (!hw_addrs[idx]) return -1; - /* It's an I2C device other than an analog tuner */ + /* It's an I2C device other than an analog tuner or IR chip */ sd = v4l2_i2c_new_subdev(&cx->v4l2_dev, adap, mod, type, hw_addrs[idx]); if (sd != NULL) sd->grp_id = hw; -- cgit v1.2.3 From e0cc8a30c11596d8e20080c03a1ee6d79b5b353a Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 28 Jul 2009 11:50:14 -0300 Subject: ir-kbd-i2c: Add support for Z8F0811/Hauppage IR transceivers From: Andy Walls This patch adds support for Zilog Z8F0811 IR transceiver chips on CX2341[68] based boards to ir-kbd-i2c for both the old i2c binding model and the new i2c binding model. Priority: normal Signed-off-by: Andy Walls Reviewed-by: Jean Delvare Signed-off-by: Douglas Schilling Landgraf Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/ir-kbd-i2c.c | 9 ++++++--- 1 file changed, 6 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 ae928be28..a1e8fb561 100644 --- a/linux/drivers/media/video/ir-kbd-i2c.c +++ b/linux/drivers/media/video/ir-kbd-i2c.c @@ -442,9 +442,11 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) case 0x47: case 0x71: case 0x2d: - if (adap->id == I2C_HW_B_CX2388x) { + if (adap->id == I2C_HW_B_CX2388x || + adap->id == I2C_HW_B_CX2341X) { /* Handled by cx88-input */ - name = "CX2388x remote"; + name = adap->id == I2C_HW_B_CX2341X ? "CX2341x remote" + : "CX2388x remote"; ir_type = IR_TYPE_RC5; ir->get_key = get_key_haup_xvr; if (hauppauge == 1) { @@ -726,7 +728,8 @@ static int ir_probe(struct i2c_adapter *adap) 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 */ + /* IR device specific entries should be added here */ + { "ir_rx_z8f0811_haup", 0 }, { } }; -- cgit v1.2.3 From 3defb5a7493d187675c33898730f3ee456530a76 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 28 Jul 2009 11:52:10 -0300 Subject: stv680: kfree called before usb_kill_urb From: Oliver Neukum The irq handler will touch memory. Even in the error case some URBs may complete. Thus no memory must be kfreed before all URBs are killed. Priority: normal Signed-off-by: Oliver Neukum Acked-by: Greg Kroah-Hartman Signed-off-by: Douglas Schilling Landgraf Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/stv680.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/stv680.c b/linux/drivers/media/video/stv680.c index eafe68502..600c19a78 100644 --- a/linux/drivers/media/video/stv680.c +++ b/linux/drivers/media/video/stv680.c @@ -739,10 +739,6 @@ static int stv680_start_stream (struct usb_stv *stv680) return 0; nomem_err: - for (i = 0; i < STV680_NUMSCRATCH; i++) { - kfree(stv680->scratch[i].data); - stv680->scratch[i].data = NULL; - } for (i = 0; i < STV680_NUMSBUF; i++) { usb_kill_urb(stv680->urb[i]); usb_free_urb(stv680->urb[i]); @@ -750,6 +746,11 @@ static int stv680_start_stream (struct usb_stv *stv680) kfree(stv680->sbuf[i].data); stv680->sbuf[i].data = NULL; } + /* used in irq, free only as all URBs are dead */ + for (i = 0; i < STV680_NUMSCRATCH; i++) { + kfree(stv680->scratch[i].data); + stv680->scratch[i].data = NULL; + } return -ENOMEM; } -- cgit v1.2.3 From e93775b260028520447ff7c8bf8f0978bed9d2f8 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 28 Jul 2009 11:54:52 -0300 Subject: af9015: Fix for crash in dvb-usb-af9015 From: Nils Kassube Moving BOOT fixes problem. Priority: normal Signed-off-by: Nils Kassube Acked-by: Antti Palosaari Signed-off-by: Douglas Schilling Landgraf Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/dvb-usb/af9015.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/dvb-usb/af9015.c b/linux/drivers/media/dvb/dvb-usb/af9015.c index a94f4d305..7798aabaa 100644 --- a/linux/drivers/media/dvb/dvb-usb/af9015.c +++ b/linux/drivers/media/dvb/dvb-usb/af9015.c @@ -81,7 +81,6 @@ static int af9015_rw_udev(struct usb_device *udev, struct req_t *req) switch (req->cmd) { case GET_CONFIG: - case BOOT: case READ_MEMORY: case RECONNECT_USB: case GET_IR_CODE: @@ -100,6 +99,7 @@ static int af9015_rw_udev(struct usb_device *udev, struct req_t *req) case WRITE_VIRTUAL_MEMORY: case COPY_FIRMWARE: case DOWNLOAD_FIRMWARE: + case BOOT: break; default: err("unknown command:%d", req->cmd); -- cgit v1.2.3 From b790d1d65f747cf5694a44470f45539c42859b0e Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 28 Jul 2009 11:56:33 -0300 Subject: saa7134: fix lock imbalance From: Jiri Slaby There seems to be one superfluos unlock in a poll function. Remove it. Priority: normal Signed-off-by: Jiri Slaby Signed-off-by: Douglas Schilling Landgraf Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/saa7134/saa7134-video.c | 1 - 1 file changed, 1 deletion(-) (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 5be072c57..04d7e8d66 100644 --- a/linux/drivers/media/video/saa7134/saa7134-video.c +++ b/linux/drivers/media/video/saa7134/saa7134-video.c @@ -1444,7 +1444,6 @@ video_poll(struct file *file, struct poll_table_struct *wait) fh->cap.ops->buf_queue(&fh->cap,fh->cap.read_buf); fh->cap.read_off = 0; } - mutex_unlock(&fh->cap.vb_lock); buf = fh->cap.read_buf; } -- cgit v1.2.3 From 63f6769bcad76518a85506b5f19de1a48707d6fb Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Wed, 29 Jul 2009 10:01:54 +0200 Subject: gspca - main: Remove vidioc_s_std(). From: Marton Nemeth The vidioc_s_std() is not necessary when vdev->tvnorms == 0. Priority: normal Signed-off-by: Marton Nemeth Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/gspca.c | 7 ------- 1 file changed, 7 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/gspca.c b/linux/drivers/media/video/gspca/gspca.c index 2e5197073..670091e42 100644 --- a/linux/drivers/media/video/gspca/gspca.c +++ b/linux/drivers/media/video/gspca/gspca.c @@ -1504,12 +1504,6 @@ static int vidioc_s_parm(struct file *filp, void *priv, return 0; } -static int vidioc_s_std(struct file *filp, void *priv, - v4l2_std_id *parm) -{ - return 0; -} - #ifdef CONFIG_VIDEO_V4L1_COMPAT static int vidiocgmbuf(struct file *file, void *priv, struct video_mbuf *mbuf) @@ -1980,7 +1974,6 @@ static const struct v4l2_ioctl_ops dev_ioctl_ops = { .vidioc_s_jpegcomp = vidioc_s_jpegcomp, .vidioc_g_parm = vidioc_g_parm, .vidioc_s_parm = vidioc_s_parm, - .vidioc_s_std = vidioc_s_std, .vidioc_enum_framesizes = vidioc_enum_framesizes, #ifdef CONFIG_VIDEO_ADV_DEBUG .vidioc_g_register = vidioc_g_register, -- cgit v1.2.3 From e523ddb42e0588210df880e0e32f0de801803e94 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 30 Jul 2009 20:00:44 -0300 Subject: hdpvr: fix lock imbalances From: Jiri Slaby There are many lock imbalances in this driver. Fix all found. Priority: normal Signed-off-by: Jiri Slaby Signed-off-by: Douglas Schilling Landgraf Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/hdpvr/hdpvr-core.c | 12 ++++++------ linux/drivers/media/video/hdpvr/hdpvr-video.c | 6 ++++-- 2 files changed, 10 insertions(+), 8 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/hdpvr/hdpvr-core.c b/linux/drivers/media/video/hdpvr/hdpvr-core.c index 188bd5aea..1c9bc94c9 100644 --- a/linux/drivers/media/video/hdpvr/hdpvr-core.c +++ b/linux/drivers/media/video/hdpvr/hdpvr-core.c @@ -126,7 +126,7 @@ static int device_authorization(struct hdpvr_device *dev) char *print_buf = kzalloc(5*buf_size+1, GFP_KERNEL); if (!print_buf) { v4l2_err(&dev->v4l2_dev, "Out of memory\n"); - goto error; + return retval; } #endif @@ -140,7 +140,7 @@ static int device_authorization(struct hdpvr_device *dev) if (ret != 46) { v4l2_err(&dev->v4l2_dev, "unexpected answer of status request, len %d\n", ret); - goto error; + goto unlock; } #ifdef HDPVR_DEBUG else { @@ -163,7 +163,7 @@ static int device_authorization(struct hdpvr_device *dev) v4l2_err(&dev->v4l2_dev, "unknown firmware version 0x%x\n", dev->usbc_buf[1]); ret = -EINVAL; - goto error; + goto unlock; } response = dev->usbc_buf+38; @@ -188,10 +188,10 @@ static int device_authorization(struct hdpvr_device *dev) 10000); v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev, "magic request returned %d\n", ret); - mutex_unlock(&dev->usbc_mutex); retval = ret != 8; -error: +unlock: + mutex_unlock(&dev->usbc_mutex); return retval; } @@ -350,6 +350,7 @@ static int hdpvr_probe(struct usb_interface *interface, mutex_lock(&dev->io_mutex); if (hdpvr_alloc_buffers(dev, NUM_BUFFERS)) { + mutex_unlock(&dev->io_mutex); v4l2_err(&dev->v4l2_dev, "allocating transfer buffers failed\n"); goto error; @@ -381,7 +382,6 @@ static int hdpvr_probe(struct usb_interface *interface, error: if (dev) { - mutex_unlock(&dev->io_mutex); /* this frees allocated memory */ hdpvr_delete(dev); } diff --git a/linux/drivers/media/video/hdpvr/hdpvr-video.c b/linux/drivers/media/video/hdpvr/hdpvr-video.c index ccd47f57f..5937de23c 100644 --- a/linux/drivers/media/video/hdpvr/hdpvr-video.c +++ b/linux/drivers/media/video/hdpvr/hdpvr-video.c @@ -375,6 +375,7 @@ static int hdpvr_open(struct file *file) * in resumption */ mutex_lock(&dev->io_mutex); dev->open_count++; + mutex_unlock(&dev->io_mutex); fh->dev = dev; @@ -383,7 +384,6 @@ static int hdpvr_open(struct file *file) retval = 0; err: - mutex_unlock(&dev->io_mutex); return retval; } @@ -519,8 +519,10 @@ static unsigned int hdpvr_poll(struct file *filp, poll_table *wait) mutex_lock(&dev->io_mutex); - if (video_is_unregistered(dev->video_dev)) + if (video_is_unregistered(dev->video_dev)) { + mutex_unlock(&dev->io_mutex); return -EIO; + } if (dev->status == STATUS_IDLE) { if (hdpvr_start_streaming(dev)) { -- cgit v1.2.3 From be7e7366b6e627b24db77147c07f9a3deb5f3933 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Sat, 1 Aug 2009 23:14:24 +0200 Subject: uvcvideo: Avoid flooding the kernel log with "unknown event type" messages From: Laurent Pinchart The iSight sends non-UVC status events through the interrupt endpoint. Those invalid events are reported to the kernel log, resulting in a log flood. Only log the events when the UVC_TRACE_STATUS flag is set. Priority: high Signed-off-by: Laurent Pinchart --- linux/drivers/media/video/uvc/uvc_status.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/uvc/uvc_status.c b/linux/drivers/media/video/uvc/uvc_status.c index b05df63b4..48614d39c 100644 --- a/linux/drivers/media/video/uvc/uvc_status.c +++ b/linux/drivers/media/video/uvc/uvc_status.c @@ -157,8 +157,8 @@ static void uvc_status_complete(struct urb *urb) break; default: - uvc_printk(KERN_INFO, "unknown event type %u.\n", - dev->status[0]); + uvc_trace(UVC_TRACE_STATUS, "Unknown status event " + "type %u.\n", dev->status[0]); break; } } -- cgit v1.2.3 From 0315e4babbc90dd9a89e82968fd924cae514d993 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Sun, 2 Aug 2009 11:56:47 +0200 Subject: gspca - vc032x: Bad h/v flip controls when inverted by default. From: Jean-Francois Moine Priority: normal Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/vc032x.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/vc032x.c b/linux/drivers/media/video/gspca/vc032x.c index 44dea7949..6f9aab89c 100644 --- a/linux/drivers/media/video/gspca/vc032x.c +++ b/linux/drivers/media/video/gspca/vc032x.c @@ -3135,10 +3135,10 @@ static void sethvflip(struct gspca_dev *gspca_dev) hflip = sd->hflip; if (sd->flags & FL_HFLIP) - hflip != hflip; + hflip = !hflip; vflip = sd->vflip; if (sd->flags & FL_VFLIP) - vflip != vflip; + vflip = !vflip; switch (sd->sensor) { case SENSOR_MI1310_SOC: case SENSOR_MI1320_SOC: -- cgit v1.2.3 From 920d68bc15da48dcaf2144b777f7dcae138599ca Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Sun, 2 Aug 2009 11:37:34 -0400 Subject: sms1xxx: fix build warning: unused variable 'board' From: Michael Krufky Remove the following build warning: sms-cards.c: In function 'sms_board_event': sms-cards.c:120: warning: unused variable 'board' Thanks to Hans Verkuil for pointing this out. The problem code has been #if 0'd for now, this will likely be used again in the future, once the event interface is complete. Priority: high Signed-off-by: Michael Krufky Cc: Hans Verkuil --- linux/drivers/media/dvb/siano/sms-cards.c | 2 ++ 1 file changed, 2 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 76bd3cb82..62c1bf604 100644 --- a/linux/drivers/media/dvb/siano/sms-cards.c +++ b/linux/drivers/media/dvb/siano/sms-cards.c @@ -116,8 +116,10 @@ static inline void sms_gpio_assign_11xx_default_led_config( int sms_board_event(struct smscore_device_t *coredev, enum SMS_BOARD_EVENTS gevent) { +#if 0 int board_id = smscore_get_board_id(coredev); struct sms_board *board = sms_get_board(board_id); +#endif struct smscore_gpio_config MyGpioConfig; sms_gpio_assign_11xx_default_led_config(&MyGpioConfig); -- cgit v1.2.3 From 2e966abec56337af8c6314850d990720869b8786 Mon Sep 17 00:00:00 2001 From: Thierry MERLE Date: Sun, 2 Aug 2009 20:44:37 +0200 Subject: dvb-usb: fix tuning with Cinergy T2 From: Eberhard Mattes cinergyInitialize param.flags. Priority: normal Signed-off-by: Eberhard Mattes Signed-off-by: Thierry MERLE --- linux/drivers/media/dvb/dvb-usb/cinergyT2-fe.c | 1 + 1 file changed, 1 insertion(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/dvb-usb/cinergyT2-fe.c b/linux/drivers/media/dvb/dvb-usb/cinergyT2-fe.c index 649f25cca..9cd51ac12 100644 --- a/linux/drivers/media/dvb/dvb-usb/cinergyT2-fe.c +++ b/linux/drivers/media/dvb/dvb-usb/cinergyT2-fe.c @@ -275,6 +275,7 @@ static int cinergyt2_fe_set_frontend(struct dvb_frontend *fe, param.tps = cpu_to_le16(compute_tps(fep)); param.freq = cpu_to_le32(fep->frequency / 1000); param.bandwidth = 8 - fep->u.ofdm.bandwidth - BANDWIDTH_8_MHZ; + param.flags = 0; err = dvb_usb_generic_rw(state->d, (char *)¶m, sizeof(param), -- cgit v1.2.3 From a692c68699d6ba2a72b200dac53a34a8f5d889a2 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Mon, 3 Aug 2009 09:13:23 +0200 Subject: gspca - jeilinj: New subdriver for Jeilin chip. From: Theodore Kilgore Priority: normal Signed-off-by: Theodore Kilgore Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/Kconfig | 9 + linux/drivers/media/video/gspca/Makefile | 2 + linux/drivers/media/video/gspca/jeilinj.c | 388 ++++++++++++++++++++++++++++++ 3 files changed, 399 insertions(+) create mode 100644 linux/drivers/media/video/gspca/jeilinj.c (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/Kconfig b/linux/drivers/media/video/gspca/Kconfig index a14561956..c9166e543 100644 --- a/linux/drivers/media/video/gspca/Kconfig +++ b/linux/drivers/media/video/gspca/Kconfig @@ -47,6 +47,15 @@ config USB_GSPCA_FINEPIX To compile this driver as a module, choose M here: the module will be called gspca_finepix. +config USB_GSPCA_JEILINJ + tristate "Jeilin JPEG USB V4L2 driver" + depends on VIDEO_V4L2 && USB_GSPCA + help + Say Y here if you want support for cameras based on this Jeilin chip. + + To compile this driver as a module, choose M here: the + module will be called gspca_jeilinj. + config USB_GSPCA_MARS tristate "Mars USB Camera Driver" depends on VIDEO_V4L2 && USB_GSPCA diff --git a/linux/drivers/media/video/gspca/Makefile b/linux/drivers/media/video/gspca/Makefile index f6d3b86e9..035616b5e 100644 --- a/linux/drivers/media/video/gspca/Makefile +++ b/linux/drivers/media/video/gspca/Makefile @@ -2,6 +2,7 @@ obj-$(CONFIG_USB_GSPCA) += gspca_main.o obj-$(CONFIG_USB_GSPCA_CONEX) += gspca_conex.o obj-$(CONFIG_USB_GSPCA_ETOMS) += gspca_etoms.o obj-$(CONFIG_USB_GSPCA_FINEPIX) += gspca_finepix.o +obj-$(CONFIG_USB_GSPCA_JEILINJ) += gspca_jeilinj.o obj-$(CONFIG_USB_GSPCA_MARS) += gspca_mars.o obj-$(CONFIG_USB_GSPCA_MR97310A) += gspca_mr97310a.o obj-$(CONFIG_USB_GSPCA_OV519) += gspca_ov519.o @@ -30,6 +31,7 @@ gspca_main-objs := gspca.o gspca_conex-objs := conex.o gspca_etoms-objs := etoms.o gspca_finepix-objs := finepix.o +gspca_jeilinj-objs := jeilinj.o gspca_mars-objs := mars.o gspca_mr97310a-objs := mr97310a.o gspca_ov519-objs := ov519.o diff --git a/linux/drivers/media/video/gspca/jeilinj.c b/linux/drivers/media/video/gspca/jeilinj.c new file mode 100644 index 000000000..dbfa3ed6e --- /dev/null +++ b/linux/drivers/media/video/gspca/jeilinj.c @@ -0,0 +1,388 @@ +/* + * Jeilinj subdriver + * + * Supports some Jeilin dual-mode cameras which use bulk transport and + * download raw JPEG data. + * + * Copyright (C) 2009 Theodore Kilgore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#define MODULE_NAME "jeilinj" + +#include +#include "gspca.h" +#include "jpeg.h" + +MODULE_AUTHOR("Theodore Kilgore "); +MODULE_DESCRIPTION("GSPCA/JEILINJ USB Camera Driver"); +MODULE_LICENSE("GPL"); + +/* Default timeouts, in ms */ +#define JEILINJ_CMD_TIMEOUT 500 +#define JEILINJ_DATA_TIMEOUT 1000 + +/* Maximum transfer size to use. */ +#define JEILINJ_MAX_TRANSFER 0x200 + +#define FRAME_HEADER_LEN 0x10 + +/* Structure to hold all of our device specific stuff */ +struct sd { + struct gspca_dev gspca_dev; /* !! must be the first item */ + const struct v4l2_pix_format *cap_mode; + /* Driver stuff */ + struct work_struct work_struct; + struct workqueue_struct *work_thread; + u8 quality; /* image quality */ + u8 jpegqual; /* webcam quality */ + u8 *jpeg_hdr; +}; + + struct jlj_command { + unsigned char instruction[2]; + unsigned char ack_wanted; + }; + +/* AFAICT these cameras will only do 320x240. */ +static struct v4l2_pix_format jlj_mode[] = { + { 320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, + .bytesperline = 320, + .sizeimage = 320 * 240, + .colorspace = V4L2_COLORSPACE_JPEG, + .priv = 0} +}; + +/* + * cam uses endpoint 0x03 to send commands, 0x84 for read commands, + * and 0x82 for bulk transfer. + */ + +/* All commands are two bytes only */ +static int jlj_write2(struct gspca_dev *gspca_dev, unsigned char *command) +{ + int retval; + + memcpy(gspca_dev->usb_buf, command, 2); + retval = usb_bulk_msg(gspca_dev->dev, + usb_sndbulkpipe(gspca_dev->dev, 3), + gspca_dev->usb_buf, 2, NULL, 500); + if (retval < 0) + PDEBUG(D_ERR, "command write [%02x] error %d", + gspca_dev->usb_buf[0], retval); + return retval; +} + +/* Responses are one byte only */ +static int jlj_read1(struct gspca_dev *gspca_dev, unsigned char response) +{ + int retval; + + retval = usb_bulk_msg(gspca_dev->dev, + usb_rcvbulkpipe(gspca_dev->dev, 0x84), + gspca_dev->usb_buf, 1, NULL, 500); + response = gspca_dev->usb_buf[0]; + if (retval < 0) + PDEBUG(D_ERR, "read command [%02x] error %d", + gspca_dev->usb_buf[0], retval); + return retval; +} + +static int jlj_start(struct gspca_dev *gspca_dev) +{ + int i; + int retval = -1; + u8 response = 0xff; + struct jlj_command start_commands[] = { + {{0x71, 0x81}, 0}, + {{0x70, 0x05}, 0}, + {{0x95, 0x70}, 1}, + {{0x71, 0x81}, 0}, + {{0x70, 0x04}, 0}, + {{0x95, 0x70}, 1}, + {{0x71, 0x00}, 0}, + {{0x70, 0x08}, 0}, + {{0x95, 0x70}, 1}, + {{0x94, 0x02}, 0}, + {{0xde, 0x24}, 0}, + {{0x94, 0x02}, 0}, + {{0xdd, 0xf0}, 0}, + {{0x94, 0x02}, 0}, + {{0xe3, 0x2c}, 0}, + {{0x94, 0x02}, 0}, + {{0xe4, 0x00}, 0}, + {{0x94, 0x02}, 0}, + {{0xe5, 0x00}, 0}, + {{0x94, 0x02}, 0}, + {{0xe6, 0x2c}, 0}, + {{0x94, 0x03}, 0}, + {{0xaa, 0x00}, 0}, + {{0x71, 0x1e}, 0}, + {{0x70, 0x06}, 0}, + {{0x71, 0x80}, 0}, + {{0x70, 0x07}, 0} + }; + for (i = 0; i < ARRAY_SIZE(start_commands); i++) { + retval = jlj_write2(gspca_dev, start_commands[i].instruction); + if (retval < 0) + return retval; + if (start_commands[i].ack_wanted) + retval = jlj_read1(gspca_dev, response); + if (retval < 0) + return retval; + } + PDEBUG(D_ERR, "jlj_start retval is %d", retval); + return retval; +} + +static int jlj_stop(struct gspca_dev *gspca_dev) +{ + int i; + int retval; + struct jlj_command stop_commands[] = { + {{0x71, 0x00}, 0}, + {{0x70, 0x09}, 0}, + {{0x71, 0x80}, 0}, + {{0x70, 0x05}, 0} + }; + for (i = 0; i < ARRAY_SIZE(stop_commands); i++) { + retval = jlj_write2(gspca_dev, stop_commands[i].instruction); + if (retval < 0) + return retval; + } + return retval; +} + +/* This function is called as a workqueue function and runs whenever the camera + * is streaming data. Because it is a workqueue function it is allowed to sleep + * so we can use synchronous USB calls. To avoid possible collisions with other + * threads attempting to use the camera's USB interface the gspca usb_lock is + * used when performing the one USB control operation inside the workqueue, + * which tells the camera to close the stream. In practice the only thing + * which needs to be protected against is the usb_set_interface call that + * gspca makes during stream_off. Otherwise the camera doesn't provide any + * controls that the user could try to change. + */ + +static void jlj_dostream(struct work_struct *work) +{ + struct sd *dev = container_of(work, struct sd, work_struct); + struct gspca_dev *gspca_dev = &dev->gspca_dev; + struct gspca_frame *frame; + int blocks_left; /* 0x200-sized blocks remaining in current frame. */ + int size_in_blocks; + int act_len; + int discarding = 0; /* true if we failed to get space for frame. */ + int packet_type; + int ret; + u8 *buffer; + + buffer = kmalloc(JEILINJ_MAX_TRANSFER, GFP_KERNEL | GFP_DMA); + if (!buffer) { + PDEBUG(D_ERR, "Couldn't allocate USB buffer"); + goto quit_stream; + } + while (gspca_dev->present && gspca_dev->streaming) { + if (!gspca_dev->present) + goto quit_stream; + /* Start a new frame, and add the JPEG header, first thing */ + frame = gspca_get_i_frame(gspca_dev); + if (frame && !discarding) + gspca_frame_add(gspca_dev, FIRST_PACKET, frame, + dev->jpeg_hdr, JPEG_HDR_SZ); + else + discarding = 1; + /* + * Now request data block 0. Line 0 reports the size + * to download, in blocks of size 0x200, and also tells the + * "actual" data size, in bytes, which seems best to ignore. + */ + ret = usb_bulk_msg(gspca_dev->dev, + usb_rcvbulkpipe(gspca_dev->dev, 0x82), + buffer, JEILINJ_MAX_TRANSFER, &act_len, + JEILINJ_DATA_TIMEOUT); + PDEBUG(D_STREAM, + "Got %d bytes out of %d for Block 0", + act_len, JEILINJ_MAX_TRANSFER); + if (ret < 0 || act_len < FRAME_HEADER_LEN) + goto quit_stream; + size_in_blocks = buffer[0x0a]; + blocks_left = buffer[0x0a] - 1; + PDEBUG(D_STREAM, "blocks_left = 0x%x", blocks_left); + packet_type = INTER_PACKET; + if (frame && !discarding) + /* Toss line 0 of data block 0, keep the rest. */ + gspca_frame_add(gspca_dev, packet_type, + frame, buffer + FRAME_HEADER_LEN, + JEILINJ_MAX_TRANSFER - FRAME_HEADER_LEN); + else + discarding = 1; + while (blocks_left > 0) { + if (!gspca_dev->present) + goto quit_stream; + ret = usb_bulk_msg(gspca_dev->dev, + usb_rcvbulkpipe(gspca_dev->dev, 0x82), + buffer, JEILINJ_MAX_TRANSFER, &act_len, + JEILINJ_DATA_TIMEOUT); + if (ret < 0 || act_len < JEILINJ_MAX_TRANSFER) + goto quit_stream; + PDEBUG(D_STREAM, + "%d blocks remaining for frame", blocks_left); + blocks_left -= 1; + if (blocks_left == 0) + packet_type = LAST_PACKET; + else + packet_type = INTER_PACKET; + if (frame && !discarding) + gspca_frame_add(gspca_dev, packet_type, + frame, buffer, + JEILINJ_MAX_TRANSFER); + else + discarding = 1; + } + } +quit_stream: + mutex_lock(&gspca_dev->usb_lock); + if (gspca_dev->present) + jlj_stop(gspca_dev); + mutex_unlock(&gspca_dev->usb_lock); + kfree(buffer); +} + +/* This function is called at probe time just before sd_init */ +static int sd_config(struct gspca_dev *gspca_dev, + const struct usb_device_id *id) +{ + struct cam *cam = &gspca_dev->cam; + struct sd *dev = (struct sd *) gspca_dev; + + dev->quality = 85; + dev->jpegqual = 85; + PDEBUG(D_PROBE, + "JEILINJ camera detected" + " (vid/pid 0x%04X:0x%04X)", id->idVendor, id->idProduct); + cam->cam_mode = jlj_mode; + cam->nmodes = 1; + cam->bulk = 1; + /* We don't use the buffer gspca allocates so make it small. */ + cam->bulk_size = 32; + INIT_WORK(&dev->work_struct, jlj_dostream); + return 0; +} + +/* called on streamoff with alt==0 and on disconnect */ +/* the usb_lock is held at entry - restore on exit */ +static void sd_stop0(struct gspca_dev *gspca_dev) +{ + struct sd *dev = (struct sd *) gspca_dev; + + /* wait for the work queue to terminate */ + mutex_unlock(&gspca_dev->usb_lock); + /* This waits for jlj_dostream to finish */ + destroy_workqueue(dev->work_thread); + dev->work_thread = NULL; + mutex_lock(&gspca_dev->usb_lock); + kfree(dev->jpeg_hdr); +} + +/* this function is called at probe and resume time */ +static int sd_init(struct gspca_dev *gspca_dev) +{ + return 0; +} + +/* Set up for getting frames. */ +static int sd_start(struct gspca_dev *gspca_dev) +{ + struct sd *dev = (struct sd *) gspca_dev; + int ret; + + /* create the JPEG header */ + dev->jpeg_hdr = kmalloc(JPEG_HDR_SZ, GFP_KERNEL); + jpeg_define(dev->jpeg_hdr, gspca_dev->height, gspca_dev->width, + 0x21); /* JPEG 422 */ + jpeg_set_qual(dev->jpeg_hdr, dev->quality); + PDEBUG(D_STREAM, "Start streaming at 320x240"); + ret = jlj_start(gspca_dev); + if (ret < 0) { + PDEBUG(D_ERR, "Start streaming command failed"); + return ret; + } + /* Start the workqueue function to do the streaming */ + dev->work_thread = create_singlethread_workqueue(MODULE_NAME); + queue_work(dev->work_thread, &dev->work_struct); + + return 0; +} + +/* Table of supported USB devices */ +static const __devinitdata struct usb_device_id device_table[] = { + {USB_DEVICE(0x0979, 0x0280)}, + {} +}; + +MODULE_DEVICE_TABLE(usb, device_table); + +/* sub-driver description */ +static const struct sd_desc sd_desc = { + .name = MODULE_NAME, + .config = sd_config, + .init = sd_init, + .start = sd_start, + .stop0 = sd_stop0, +}; + +/* -- device connect -- */ +static int sd_probe(struct usb_interface *intf, + const struct usb_device_id *id) +{ + return gspca_dev_probe(intf, id, + &sd_desc, + sizeof(struct sd), + THIS_MODULE); +} + +static struct usb_driver sd_driver = { + .name = MODULE_NAME, + .id_table = device_table, + .probe = sd_probe, + .disconnect = gspca_disconnect, +#ifdef CONFIG_PM + .suspend = gspca_suspend, + .resume = gspca_resume, +#endif +}; + +/* -- module insert / remove -- */ +static int __init sd_mod_init(void) +{ + int ret; + + ret = usb_register(&sd_driver); + if (ret < 0) + return ret; + PDEBUG(D_PROBE, "registered"); + return 0; +} + +static void __exit sd_mod_exit(void) +{ + usb_deregister(&sd_driver); + PDEBUG(D_PROBE, "deregistered"); +} + +module_init(sd_mod_init); +module_exit(sd_mod_exit); -- cgit v1.2.3 From deec85326356815e5bdd8c0442d5c758b12fe7eb Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Mon, 3 Aug 2009 15:51:33 -0400 Subject: saa7134: Use correct product name for Hauppauge WinTV-HVR1150 ATSC/QAM-Hybrid From: Michael Krufky Priority: high Signed-off-by: Michael Krufky --- linux/drivers/media/video/saa7134/saa7134-cards.c | 20 ++++++++++---------- linux/drivers/media/video/saa7134/saa7134-dvb.c | 2 +- linux/drivers/media/video/saa7134/saa7134.h | 2 +- 3 files changed, 12 insertions(+), 12 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/saa7134/saa7134-cards.c b/linux/drivers/media/video/saa7134/saa7134-cards.c index e2d98ff5c..fcdb20676 100644 --- a/linux/drivers/media/video/saa7134/saa7134-cards.c +++ b/linux/drivers/media/video/saa7134/saa7134-cards.c @@ -3370,8 +3370,8 @@ struct saa7134_board saa7134_boards[] = { .gpio = 0x0200100, }, }, - [SAA7134_BOARD_HAUPPAUGE_HVR1120] = { - .name = "Hauppauge WinTV-HVR1120 ATSC/QAM-Hybrid", + [SAA7134_BOARD_HAUPPAUGE_HVR1150] = { + .name = "Hauppauge WinTV-HVR1150 ATSC/QAM-Hybrid", .audio_clock = 0x00187de7, .tuner_type = TUNER_PHILIPS_TDA8290, .radio_type = UNSET, @@ -5901,7 +5901,7 @@ struct pci_device_id saa7134_pci_tbl[] = { .device = PCI_DEVICE_ID_PHILIPS_SAA7133, .subvendor = 0x0070, .subdevice = 0x6706, - .driver_data = SAA7134_BOARD_HAUPPAUGE_HVR1120, + .driver_data = SAA7134_BOARD_HAUPPAUGE_HVR1150, },{ .vendor = PCI_VENDOR_ID_PHILIPS, .device = PCI_DEVICE_ID_PHILIPS_SAA7133, @@ -5913,7 +5913,7 @@ struct pci_device_id saa7134_pci_tbl[] = { .device = PCI_DEVICE_ID_PHILIPS_SAA7133, .subvendor = 0x0070, .subdevice = 0x6708, - .driver_data = SAA7134_BOARD_HAUPPAUGE_HVR1120, + .driver_data = SAA7134_BOARD_HAUPPAUGE_HVR1150, },{ .vendor = PCI_VENDOR_ID_PHILIPS, .device = PCI_DEVICE_ID_PHILIPS_SAA7133, @@ -6458,7 +6458,7 @@ static int saa7134_tda8290_18271_callback(struct saa7134_dev *dev, switch (command) { case TDA18271_CALLBACK_CMD_AGC_ENABLE: /* 0 */ switch (dev->board) { - case SAA7134_BOARD_HAUPPAUGE_HVR1120: + case SAA7134_BOARD_HAUPPAUGE_HVR1150: case SAA7134_BOARD_HAUPPAUGE_HVR1110R3: ret = saa7134_tda18271_hvr11x0_toggle_agc(dev, arg); break; @@ -6479,7 +6479,7 @@ static int saa7134_tda8290_callback(struct saa7134_dev *dev, int ret; switch (dev->board) { - case SAA7134_BOARD_HAUPPAUGE_HVR1120: + case SAA7134_BOARD_HAUPPAUGE_HVR1150: case SAA7134_BOARD_HAUPPAUGE_HVR1110R3: /* tda8290 + tda18271 */ ret = saa7134_tda8290_18271_callback(dev, command, arg); @@ -6526,7 +6526,7 @@ static void hauppauge_eeprom(struct saa7134_dev *dev, u8 *eeprom_data) switch (tv.model) { case 67019: /* WinTV-HVR1110 (Retail, IR Blaster, hybrid, FM, SVid/Comp, 3.5mm audio in) */ case 67109: /* WinTV-HVR1000 (Retail, IR Receive, analog, no FM, SVid/Comp, 3.5mm audio in) */ - case 67201: /* WinTV-HVR1120 (Retail, IR Receive, hybrid, FM, SVid/Comp, 3.5mm audio in) */ + case 67201: /* WinTV-HVR1150 (Retail, IR Receive, hybrid, FM, SVid/Comp, 3.5mm audio in) */ case 67301: /* WinTV-HVR1000 (Retail, IR Receive, analog, no FM, SVid/Comp, 3.5mm audio in) */ case 67209: /* WinTV-HVR1110 (Retail, IR Receive, hybrid, FM, SVid/Comp, 3.5mm audio in) */ case 67559: /* WinTV-HVR1110 (OEM, no IR, hybrid, FM, SVid/Comp, RCA aud) */ @@ -6534,7 +6534,7 @@ static void hauppauge_eeprom(struct saa7134_dev *dev, u8 *eeprom_data) case 67579: /* WinTV-HVR1110 (OEM, no IR, hybrid, no FM) */ case 67589: /* WinTV-HVR1110 (OEM, no IR, hybrid, no FM, SVid/Comp, RCA aud) */ case 67599: /* WinTV-HVR1110 (OEM, no IR, hybrid, no FM, SVid/Comp, RCA aud) */ - case 67651: /* WinTV-HVR1120 (OEM, no IR, hybrid, FM, SVid/Comp, RCA aud) */ + case 67651: /* WinTV-HVR1150 (OEM, no IR, hybrid, FM, SVid/Comp, RCA aud) */ case 67659: /* WinTV-HVR1110 (OEM, no IR, hybrid, FM, SVid/Comp, RCA aud) */ break; default: @@ -6728,7 +6728,7 @@ int saa7134_board_init1(struct saa7134_dev *dev) saa_writeb (SAA7134_PRODUCTION_TEST_MODE, 0x00); break; - case SAA7134_BOARD_HAUPPAUGE_HVR1120: + case SAA7134_BOARD_HAUPPAUGE_HVR1150: case SAA7134_BOARD_HAUPPAUGE_HVR1110R3: /* GPIO 26 high for digital, low for analog */ saa7134_set_gpio(dev, 26, 0); @@ -6994,7 +6994,7 @@ int saa7134_board_init2(struct saa7134_dev *dev) dev->name, saa7134_boards[dev->board].name); } break; - case SAA7134_BOARD_HAUPPAUGE_HVR1120: + case SAA7134_BOARD_HAUPPAUGE_HVR1150: case SAA7134_BOARD_HAUPPAUGE_HVR1110R3: hauppauge_eeprom(dev, dev->eedata+0x80); break; diff --git a/linux/drivers/media/video/saa7134/saa7134-dvb.c b/linux/drivers/media/video/saa7134/saa7134-dvb.c index 360fbdf19..377645a17 100644 --- a/linux/drivers/media/video/saa7134/saa7134-dvb.c +++ b/linux/drivers/media/video/saa7134/saa7134-dvb.c @@ -1147,7 +1147,7 @@ static int dvb_init(struct saa7134_dev *dev) &tda827x_cfg_1) < 0) goto dettach_frontend; break; - case SAA7134_BOARD_HAUPPAUGE_HVR1120: + case SAA7134_BOARD_HAUPPAUGE_HVR1150: fe0->dvb.frontend = dvb_attach(lgdt3305_attach, &hcw_lgdt3305_config, &dev->i2c_adap); diff --git a/linux/drivers/media/video/saa7134/saa7134.h b/linux/drivers/media/video/saa7134/saa7134.h index be5abf059..a6e8c7f92 100644 --- a/linux/drivers/media/video/saa7134/saa7134.h +++ b/linux/drivers/media/video/saa7134/saa7134.h @@ -279,7 +279,7 @@ struct saa7134_format { #define SAA7134_BOARD_ASUSTeK_TIGER 152 #define SAA7134_BOARD_KWORLD_PLUS_TV_ANALOG 153 #define SAA7134_BOARD_AVERMEDIA_GO_007_FM_PLUS 154 -#define SAA7134_BOARD_HAUPPAUGE_HVR1120 155 +#define SAA7134_BOARD_HAUPPAUGE_HVR1150 155 #define SAA7134_BOARD_HAUPPAUGE_HVR1110R3 156 #define SAA7134_BOARD_AVERMEDIA_STUDIO_507UA 157 #define SAA7134_BOARD_AVERMEDIA_CARDBUS_501 158 -- cgit v1.2.3 From 219fe38bd79dab42db83cacc1f5444d0e27fa8ea Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Mon, 3 Aug 2009 15:51:33 -0400 Subject: saa7134: Use correct product name for Hauppauge WinTV-HVR1120 DVB-T/Hybrid From: Michael Krufky Priority: high Signed-off-by: Michael Krufky --- linux/drivers/media/video/saa7134/saa7134-cards.c | 18 +++++++++--------- linux/drivers/media/video/saa7134/saa7134-dvb.c | 2 +- linux/drivers/media/video/saa7134/saa7134.h | 2 +- 3 files changed, 11 insertions(+), 11 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/saa7134/saa7134-cards.c b/linux/drivers/media/video/saa7134/saa7134-cards.c index fcdb20676..c18b41ee6 100644 --- a/linux/drivers/media/video/saa7134/saa7134-cards.c +++ b/linux/drivers/media/video/saa7134/saa7134-cards.c @@ -3402,8 +3402,8 @@ struct saa7134_board saa7134_boards[] = { .gpio = 0x0800100, /* GPIO 23 HI for FM */ }, }, - [SAA7134_BOARD_HAUPPAUGE_HVR1110R3] = { - .name = "Hauppauge WinTV-HVR1110r3 DVB-T/Hybrid", + [SAA7134_BOARD_HAUPPAUGE_HVR1120] = { + .name = "Hauppauge WinTV-HVR1120 DVB-T/Hybrid", .audio_clock = 0x00187de7, .tuner_type = TUNER_PHILIPS_TDA8290, .radio_type = UNSET, @@ -5907,7 +5907,7 @@ struct pci_device_id saa7134_pci_tbl[] = { .device = PCI_DEVICE_ID_PHILIPS_SAA7133, .subvendor = 0x0070, .subdevice = 0x6707, - .driver_data = SAA7134_BOARD_HAUPPAUGE_HVR1110R3, + .driver_data = SAA7134_BOARD_HAUPPAUGE_HVR1120, },{ .vendor = PCI_VENDOR_ID_PHILIPS, .device = PCI_DEVICE_ID_PHILIPS_SAA7133, @@ -5919,13 +5919,13 @@ struct pci_device_id saa7134_pci_tbl[] = { .device = PCI_DEVICE_ID_PHILIPS_SAA7133, .subvendor = 0x0070, .subdevice = 0x6709, - .driver_data = SAA7134_BOARD_HAUPPAUGE_HVR1110R3, + .driver_data = SAA7134_BOARD_HAUPPAUGE_HVR1120, },{ .vendor = PCI_VENDOR_ID_PHILIPS, .device = PCI_DEVICE_ID_PHILIPS_SAA7133, .subvendor = 0x0070, .subdevice = 0x670a, - .driver_data = SAA7134_BOARD_HAUPPAUGE_HVR1110R3, + .driver_data = SAA7134_BOARD_HAUPPAUGE_HVR1120, },{ .vendor = PCI_VENDOR_ID_PHILIPS, .device = PCI_DEVICE_ID_PHILIPS_SAA7133, @@ -6459,7 +6459,7 @@ static int saa7134_tda8290_18271_callback(struct saa7134_dev *dev, case TDA18271_CALLBACK_CMD_AGC_ENABLE: /* 0 */ switch (dev->board) { case SAA7134_BOARD_HAUPPAUGE_HVR1150: - case SAA7134_BOARD_HAUPPAUGE_HVR1110R3: + case SAA7134_BOARD_HAUPPAUGE_HVR1120: ret = saa7134_tda18271_hvr11x0_toggle_agc(dev, arg); break; default: @@ -6480,7 +6480,7 @@ static int saa7134_tda8290_callback(struct saa7134_dev *dev, switch (dev->board) { case SAA7134_BOARD_HAUPPAUGE_HVR1150: - case SAA7134_BOARD_HAUPPAUGE_HVR1110R3: + case SAA7134_BOARD_HAUPPAUGE_HVR1120: /* tda8290 + tda18271 */ ret = saa7134_tda8290_18271_callback(dev, command, arg); break; @@ -6729,7 +6729,7 @@ int saa7134_board_init1(struct saa7134_dev *dev) saa_writeb (SAA7134_PRODUCTION_TEST_MODE, 0x00); break; case SAA7134_BOARD_HAUPPAUGE_HVR1150: - case SAA7134_BOARD_HAUPPAUGE_HVR1110R3: + case SAA7134_BOARD_HAUPPAUGE_HVR1120: /* GPIO 26 high for digital, low for analog */ saa7134_set_gpio(dev, 26, 0); msleep(1); @@ -6995,7 +6995,7 @@ int saa7134_board_init2(struct saa7134_dev *dev) } break; case SAA7134_BOARD_HAUPPAUGE_HVR1150: - case SAA7134_BOARD_HAUPPAUGE_HVR1110R3: + case SAA7134_BOARD_HAUPPAUGE_HVR1120: hauppauge_eeprom(dev, dev->eedata+0x80); break; case SAA7134_BOARD_HAUPPAUGE_HVR1110: diff --git a/linux/drivers/media/video/saa7134/saa7134-dvb.c b/linux/drivers/media/video/saa7134/saa7134-dvb.c index 377645a17..a5263c391 100644 --- a/linux/drivers/media/video/saa7134/saa7134-dvb.c +++ b/linux/drivers/media/video/saa7134/saa7134-dvb.c @@ -1119,7 +1119,7 @@ static int dvb_init(struct saa7134_dev *dev) &tda827x_cfg_2) < 0) goto dettach_frontend; break; - case SAA7134_BOARD_HAUPPAUGE_HVR1110R3: + case SAA7134_BOARD_HAUPPAUGE_HVR1120: fe0->dvb.frontend = dvb_attach(tda10048_attach, &hcw_tda10048_config, &dev->i2c_adap); diff --git a/linux/drivers/media/video/saa7134/saa7134.h b/linux/drivers/media/video/saa7134/saa7134.h index a6e8c7f92..6b0742ad7 100644 --- a/linux/drivers/media/video/saa7134/saa7134.h +++ b/linux/drivers/media/video/saa7134/saa7134.h @@ -280,7 +280,7 @@ struct saa7134_format { #define SAA7134_BOARD_KWORLD_PLUS_TV_ANALOG 153 #define SAA7134_BOARD_AVERMEDIA_GO_007_FM_PLUS 154 #define SAA7134_BOARD_HAUPPAUGE_HVR1150 155 -#define SAA7134_BOARD_HAUPPAUGE_HVR1110R3 156 +#define SAA7134_BOARD_HAUPPAUGE_HVR1120 156 #define SAA7134_BOARD_AVERMEDIA_STUDIO_507UA 157 #define SAA7134_BOARD_AVERMEDIA_CARDBUS_501 158 #define SAA7134_BOARD_BEHOLD_505RDS 159 -- cgit v1.2.3 From f0b81434ee6e958e7ffc72aa28d580c3d08cb31c Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Mon, 3 Aug 2009 21:40:16 -0400 Subject: cx88: fix regression in tuning for Geniatech X8000 MT From: Devin Heitmueller The introduction of the zl10353 i2c gate control broke support for the Geniatech board (which is not behind an i2 gate). Add the needed parameter. Priority: high Signed-off-by: Devin Heitmueller --- linux/drivers/media/video/cx88/cx88-dvb.c | 1 + 1 file changed, 1 insertion(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/cx88/cx88-dvb.c b/linux/drivers/media/video/cx88/cx88-dvb.c index 36f35f0b5..9c88b6c0f 100644 --- a/linux/drivers/media/video/cx88/cx88-dvb.c +++ b/linux/drivers/media/video/cx88/cx88-dvb.c @@ -502,6 +502,7 @@ static struct zl10353_config cx88_pinnacle_hybrid_pctv = { static struct zl10353_config cx88_geniatech_x8000_mt = { .demod_address = (0x1e >> 1), .no_tuner = 1, + .disable_i2c_gate_ctrl = 1, #if 0 .input_frequency = 0xe609, .parallel_ts = 1, -- cgit v1.2.3 From aa7df40721e36bcf9d4f1a60b9e58e69c08aac48 Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Mon, 3 Aug 2009 21:52:59 -0400 Subject: cx88: Disable xc3028 power management for Geniatech x8000 From: Devin Heitmueller A user discovered that the Geniatech x8000 encountered a regression when the xc3028 power management was introduced. The xc3028 never recovers after setting the powerdown register, which is probably because the xc3028 reset GPIO is not properly configured. Since I do not have access to the hardware and thus cannot determine the correct GPIO configuration, just disable xc3028 power management on this board, which fixes the regression. Thanks to user "ritec" for reporting the issue and testing the fix. Priority: high Cc: rictec Signed-off-by: Devin Heitmueller --- linux/drivers/media/common/tuners/tuner-xc2028.c | 4 ++-- linux/drivers/media/common/tuners/tuner-xc2028.h | 1 + linux/drivers/media/video/cx88/cx88-cards.c | 8 ++++++++ 3 files changed, 11 insertions(+), 2 deletions(-) (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 3de5d6685..3cf380e6b 100644 --- a/linux/drivers/media/common/tuners/tuner-xc2028.c +++ b/linux/drivers/media/common/tuners/tuner-xc2028.c @@ -1123,8 +1123,8 @@ static int xc2028_sleep(struct dvb_frontend *fe) struct xc2028_data *priv = fe->tuner_priv; int rc = 0; - /* Avoid firmware reload on slow devices */ - if (no_poweroff) + /* Avoid firmware reload on slow devices or if PM disabled */ + if (no_poweroff || priv->ctrl.disable_power_mgmt) return 0; tuner_dbg("Putting xc2028/3028 into poweroff mode.\n"); diff --git a/linux/drivers/media/common/tuners/tuner-xc2028.h b/linux/drivers/media/common/tuners/tuner-xc2028.h index 19de7928a..a90c35d50 100644 --- a/linux/drivers/media/common/tuners/tuner-xc2028.h +++ b/linux/drivers/media/common/tuners/tuner-xc2028.h @@ -38,6 +38,7 @@ struct xc2028_ctrl { unsigned int input1:1; unsigned int vhfbw7:1; unsigned int uhfbw8:1; + unsigned int disable_power_mgmt:1; unsigned int demod; enum firmware_type type:2; }; diff --git a/linux/drivers/media/video/cx88/cx88-cards.c b/linux/drivers/media/video/cx88/cx88-cards.c index bf0f26c03..67ccc59a7 100644 --- a/linux/drivers/media/video/cx88/cx88-cards.c +++ b/linux/drivers/media/video/cx88/cx88-cards.c @@ -3036,6 +3036,14 @@ void cx88_setup_xc3028(struct cx88_core *core, struct xc2028_ctrl *ctl) case CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO: ctl->demod = XC3028_FE_OREN538; break; + case CX88_BOARD_GENIATECH_X8000_MT: + /* FIXME: For this board, the xc3028 never recovers after being + powered down (the reset GPIO probably is not set properly). + We don't have access to the hardware so we cannot determine + which GPIO is used for xc3028, so just disable power xc3028 + power management for now */ + ctl->disable_power_mgmt = 1; + break; case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL: case CX88_BOARD_PROLINK_PV_GLOBAL_XTREME: case CX88_BOARD_PROLINK_PV_8000GT: -- cgit v1.2.3 From 6355bbe94603dee693331f5ae62c8c1a109a8007 Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Mon, 3 Aug 2009 22:56:51 -0400 Subject: em28xx: add support for Terratec Cinergy Hybrid T USB XS remote control From: Devin Heitmueller Add support for the remote control that comes with the Cinergy Hybrid T USB XS Thanks to Jelle de Jong for providing sample hardware to test with. Priority: normal Signed-off-by: Devin Heitmueller Cc: Jelle de Jong --- linux/drivers/media/common/ir-keymaps.c | 55 +++++++++++++++++++++++++ linux/drivers/media/video/em28xx/em28xx-cards.c | 2 + 2 files changed, 57 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/common/ir-keymaps.c b/linux/drivers/media/common/ir-keymaps.c index 56fa64b4c..67c67430d 100644 --- a/linux/drivers/media/common/ir-keymaps.c +++ b/linux/drivers/media/common/ir-keymaps.c @@ -2801,6 +2801,61 @@ IR_KEYTAB_TYPE ir_codes_dm1105_nec[IR_KEYTAB_SIZE] = { }; EXPORT_SYMBOL_GPL(ir_codes_dm1105_nec); + +/* Terratec Cinergy Hybrid T USB XS + Devin Heitmueller + */ +IR_KEYTAB_TYPE ir_codes_terratec_cinergy_xs[IR_KEYTAB_SIZE] = { + [0x41] = KEY_HOME, + [0x01] = KEY_POWER, + [0x42] = KEY_MENU, + [0x02] = KEY_1, + [0x03] = KEY_2, + [0x04] = KEY_3, + [0x43] = KEY_SUBTITLE, + [0x05] = KEY_4, + [0x06] = KEY_5, + [0x07] = KEY_6, + [0x44] = KEY_TEXT, + [0x08] = KEY_7, + [0x09] = KEY_8, + [0x0a] = KEY_9, + [0x45] = KEY_DELETE, + [0x0b] = KEY_TUNER, + [0x0c] = KEY_0, + [0x0d] = KEY_MODE, + [0x46] = KEY_TV, + [0x47] = KEY_DVD, + [0x49] = KEY_VIDEO, + [0x4b] = KEY_AUX, + [0x10] = KEY_UP, + [0x11] = KEY_LEFT, + [0x12] = KEY_OK, + [0x13] = KEY_RIGHT, + [0x14] = KEY_DOWN, + [0x0f] = KEY_EPG, + [0x16] = KEY_INFO, + [0x4d] = KEY_BACKSPACE, + [0x1c] = KEY_VOLUMEUP, + [0x4c] = KEY_PLAY, + [0x1b] = KEY_CHANNELUP, + [0x1e] = KEY_VOLUMEDOWN, + [0x1d] = KEY_MUTE, + [0x1f] = KEY_CHANNELDOWN, + [0x17] = KEY_RED, + [0x18] = KEY_GREEN, + [0x19] = KEY_YELLOW, + [0x1a] = KEY_BLUE, + [0x58] = KEY_RECORD, + [0x48] = KEY_STOP, + [0x40] = KEY_PAUSE, + [0x54] = KEY_LAST, + [0x4e] = KEY_REWIND, + [0x4f] = KEY_FASTFORWARD, + [0x5c] = KEY_NEXT, +}; +EXPORT_SYMBOL_GPL(ir_codes_terratec_cinergy_xs); + /* EVGA inDtube Devin Heitmueller */ diff --git a/linux/drivers/media/video/em28xx/em28xx-cards.c b/linux/drivers/media/video/em28xx/em28xx-cards.c index 795fd16a5..daa710b36 100644 --- a/linux/drivers/media/video/em28xx/em28xx-cards.c +++ b/linux/drivers/media/video/em28xx/em28xx-cards.c @@ -907,6 +907,8 @@ struct em28xx_board em28xx_boards[] = { .decoder = EM28XX_TVP5150, .has_dvb = 1, .dvb_gpio = default_digital, + .ir_codes = ir_codes_terratec_cinergy_xs, + .xclk = EM28XX_XCLK_FREQUENCY_12MHZ, /* NEC IR */ .input = { { .type = EM28XX_VMUX_TELEVISION, .vmux = TVP5150_COMPOSITE0, -- cgit v1.2.3 From 33a9a00f41338f5ab7589a2611da979c87b884ce Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 4 Aug 2009 19:52:37 -0300 Subject: em28xx: fix V4L2 API compliance: don't expose audio inputs for devices without it From: Mauro Carvalho Chehab V4L2 API (chapter 1.5) states that: Drivers must implement all input ioctls when the device has one or more inputs, all output ioctls when the device has one or more outputs. When the device has any audio inputs or outputs the driver must set the V4L2_CAP_AUDIO flag in the struct v4l2_capability returned by the VIDIOC_QUERYCAP ioctl. So, devices without audio input should return -EINVAL. Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/em28xx/em28xx-video.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/em28xx/em28xx-video.c b/linux/drivers/media/video/em28xx/em28xx-video.c index fcb99fb71..258cd38ce 100644 --- a/linux/drivers/media/video/em28xx/em28xx-video.c +++ b/linux/drivers/media/video/em28xx/em28xx-video.c @@ -976,6 +976,9 @@ static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a) struct em28xx_fh *fh = priv; struct em28xx *dev = fh->dev; + if (!dev->audio_mode.has_audio) + return -EINVAL; + switch (a->index) { case EM28XX_AMUX_VIDEO: strcpy(a->name, "Television"); @@ -1022,6 +1025,9 @@ static int vidioc_s_audio(struct file *file, void *priv, struct v4l2_audio *a) return -EINVAL; #else + if (!dev->audio_mode.has_audio) + return -EINVAL; + if (a->index >= MAX_EM28XX_INPUT) return -EINVAL; if (0 == INPUT(a->index)->type) @@ -1444,9 +1450,11 @@ static int vidioc_querycap(struct file *file, void *priv, #endif V4L2_CAP_SLICED_VBI_CAPTURE | V4L2_CAP_VIDEO_CAPTURE | - V4L2_CAP_AUDIO | V4L2_CAP_READWRITE | V4L2_CAP_STREAMING; + if (dev->audio_mode.has_audio) + cap->capabilities |= V4L2_CAP_AUDIO; + if (dev->tuner_type != TUNER_ABSENT) cap->capabilities |= V4L2_CAP_TUNER; -- cgit v1.2.3 From 3d106fc1f1a62d4ad61ba0ab78a9171508a97f16 Mon Sep 17 00:00:00 2001 From: Tobias Lorenz Date: Sun, 9 Aug 2009 19:22:20 +0200 Subject: radio-si470x: separate common and usb code This patch is a preceding work to add the i2c interface of si470x. The si470x directory includes a common file and usb specific file and header file. The part unrelated with usb interface and i2c interface exists in radio-si470x-common.c file, and The usb specific part exists in radio-si470x-usb.c file. Signed-off-by: Joonyoung Shim Small changes, due to new include "linux/smp_lock.h". Acked-by: Tobias Lorenz --- linux/drivers/media/radio/Kconfig | 26 +- linux/drivers/media/radio/Makefile | 2 +- linux/drivers/media/radio/radio-si470x.c | 1870 -------------------- linux/drivers/media/radio/si470x/Kconfig | 24 + linux/drivers/media/radio/si470x/Makefile | 7 + .../media/radio/si470x/radio-si470x-common.c | 794 +++++++++ .../drivers/media/radio/si470x/radio-si470x-usb.c | 958 ++++++++++ linux/drivers/media/radio/si470x/radio-si470x.h | 202 +++ 8 files changed, 1989 insertions(+), 1892 deletions(-) delete mode 100644 linux/drivers/media/radio/radio-si470x.c create mode 100644 linux/drivers/media/radio/si470x/Kconfig create mode 100644 linux/drivers/media/radio/si470x/Makefile create mode 100644 linux/drivers/media/radio/si470x/radio-si470x-common.c create mode 100644 linux/drivers/media/radio/si470x/radio-si470x-usb.c create mode 100644 linux/drivers/media/radio/si470x/radio-si470x.h --- linux/drivers/media/radio/Kconfig | 26 +- linux/drivers/media/radio/Makefile | 2 +- linux/drivers/media/radio/radio-si470x.c | 1870 -------------------- linux/drivers/media/radio/si470x/Kconfig | 24 + linux/drivers/media/radio/si470x/Makefile | 7 + .../media/radio/si470x/radio-si470x-common.c | 794 +++++++++ .../drivers/media/radio/si470x/radio-si470x-usb.c | 958 ++++++++++ linux/drivers/media/radio/si470x/radio-si470x.h | 202 +++ 8 files changed, 1990 insertions(+), 1893 deletions(-) delete mode 100644 linux/drivers/media/radio/radio-si470x.c create mode 100644 linux/drivers/media/radio/si470x/Kconfig create mode 100644 linux/drivers/media/radio/si470x/Makefile create mode 100644 linux/drivers/media/radio/si470x/radio-si470x-common.c create mode 100644 linux/drivers/media/radio/si470x/radio-si470x-usb.c create mode 100644 linux/drivers/media/radio/si470x/radio-si470x.h (limited to 'linux/drivers') diff --git a/linux/drivers/media/radio/Kconfig b/linux/drivers/media/radio/Kconfig index 3315cac87..41bbec6df 100644 --- a/linux/drivers/media/radio/Kconfig +++ b/linux/drivers/media/radio/Kconfig @@ -351,29 +351,11 @@ config USB_DSBR To compile this driver as a module, choose M here: the module will be called dsbr100. -config USB_SI470X - tristate "Silicon Labs Si470x FM Radio Receiver support" - depends on USB && VIDEO_V4L2 - ---help--- - This is a driver for USB devices with the Silicon Labs SI470x - chip. Currently these devices are known to work: - - 10c4:818a: Silicon Labs USB FM Radio Reference Design - - 06e1:a155: ADS/Tech FM Radio Receiver (formerly Instant FM Music) - - 1b80:d700: KWorld USB FM Radio SnapMusic Mobile 700 (FM700) - - Sound is provided by the ALSA USB Audio/MIDI driver. Therefore - if you don't want to use the device solely for RDS receiving, - it is recommended to also select SND_USB_AUDIO. - - Please have a look at the documentation, especially on how - to redirect the audio stream from the radio to your sound device: - Documentation/video4linux/si470x.txt - - Say Y here if you want to connect this type of radio to your - computer's USB port. +config RADIO_SI470X + bool "Silicon Labs Si470x FM Radio Receiver support" + depends on VIDEO_V4L2 - To compile this driver as a module, choose M here: the - module will be called radio-si470x. +source "drivers/media/radio/si470x/Kconfig" config USB_MR800 tristate "AverMedia MR 800 USB FM radio support" diff --git a/linux/drivers/media/radio/Makefile b/linux/drivers/media/radio/Makefile index 0f2b35b3e..18111e1fe 100644 --- a/linux/drivers/media/radio/Makefile +++ b/linux/drivers/media/radio/Makefile @@ -17,7 +17,7 @@ obj-$(CONFIG_RADIO_GEMTEK_PCI) += radio-gemtek-pci.o obj-$(CONFIG_RADIO_TRUST) += radio-trust.o obj-$(CONFIG_RADIO_MAESTRO) += radio-maestro.o obj-$(CONFIG_USB_DSBR) += dsbr100.o -obj-$(CONFIG_USB_SI470X) += radio-si470x.o +obj-$(CONFIG_RADIO_SI470X) += si470x/ obj-$(CONFIG_USB_MR800) += radio-mr800.o obj-$(CONFIG_RADIO_TEA5764) += radio-tea5764.o diff --git a/linux/drivers/media/radio/radio-si470x.c b/linux/drivers/media/radio/radio-si470x.c deleted file mode 100644 index 5b4cab3d0..000000000 --- a/linux/drivers/media/radio/radio-si470x.c +++ /dev/null @@ -1,1870 +0,0 @@ -/* - * drivers/media/radio/radio-si470x.c - * - * Driver for USB radios for the Silicon Labs Si470x FM Radio Receivers: - * - Silicon Labs USB FM Radio Reference Design - * - ADS/Tech FM Radio Receiver (formerly Instant FM Music) (RDX-155-EF) - * - KWorld USB FM Radio SnapMusic Mobile 700 (FM700) - * - Sanei Electric, Inc. FM USB Radio (sold as DealExtreme.com PCear) - * - * Copyright (c) 2009 Tobias Lorenz - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - - -/* - * History: - * 2008-01-12 Tobias Lorenz - * Version 1.0.0 - * - First working version - * 2008-01-13 Tobias Lorenz - * Version 1.0.1 - * - Improved error handling, every function now returns errno - * - Improved multi user access (start/mute/stop) - * - Channel doesn't get lost anymore after start/mute/stop - * - RDS support added (polling mode via interrupt EP 1) - * - marked default module parameters with *value* - * - switched from bit structs to bit masks - * - header file cleaned and integrated - * 2008-01-14 Tobias Lorenz - * Version 1.0.2 - * - hex values are now lower case - * - commented USB ID for ADS/Tech moved on todo list - * - blacklisted si470x in hid-quirks.c - * - rds buffer handling functions integrated into *_work, *_read - * - rds_command in si470x_poll exchanged against simple retval - * - check for firmware version 15 - * - code order and prototypes still remain the same - * - spacing and bottom of band codes remain the same - * 2008-01-16 Tobias Lorenz - * Version 1.0.3 - * - code reordered to avoid function prototypes - * - switch/case defaults are now more user-friendly - * - unified comment style - * - applied all checkpatch.pl v1.12 suggestions - * except the warning about the too long lines with bit comments - * - renamed FMRADIO to RADIO to cut line length (checkpatch.pl) - * 2008-01-22 Tobias Lorenz - * Version 1.0.4 - * - avoid poss. locking when doing copy_to_user which may sleep - * - RDS is automatically activated on read now - * - code cleaned of unnecessary rds_commands - * - USB Vendor/Product ID for ADS/Tech FM Radio Receiver verified - * (thanks to Guillaume RAMOUSSE) - * 2008-01-27 Tobias Lorenz - * Version 1.0.5 - * - number of seek_retries changed to tune_timeout - * - fixed problem with incomplete tune operations by own buffers - * - optimization of variables and printf types - * - improved error logging - * 2008-01-31 Tobias Lorenz - * Oliver Neukum - * Version 1.0.6 - * - fixed coverity checker warnings in *_usb_driver_disconnect - * - probe()/open() race by correct ordering in probe() - * - DMA coherency rules by separate allocation of all buffers - * - use of endianness macros - * - abuse of spinlock, replaced by mutex - * - racy handling of timer in disconnect, - * replaced by delayed_work - * - racy interruptible_sleep_on(), - * replaced with wait_event_interruptible() - * - handle signals in read() - * 2008-02-08 Tobias Lorenz - * Oliver Neukum - * Version 1.0.7 - * - usb autosuspend support - * - unplugging fixed - * 2008-05-07 Tobias Lorenz - * Version 1.0.8 - * - hardware frequency seek support - * - afc indication - * - more safety checks, let si470x_get_freq return errno - * - vidioc behavior corrected according to v4l2 spec - * 2008-10-20 Alexey Klimov - * - add support for KWorld USB FM Radio FM700 - * - blacklisted KWorld radio in hid-core.c and hid-ids.h - * 2008-12-03 Mark Lord - * - add support for DealExtreme USB Radio - * 2009-01-31 Bob Ross - * - correction of stereo detection/setting - * - correction of signal strength indicator scaling - * 2009-01-31 Rick Bronson - * Tobias Lorenz - * - add LED status output - * - get HW/SW version from scratchpad - * 2009-06-16 Edouard Lafargue - * Version 1.0.10 - * - add support for interrupt mode for RDS endpoint, - * instead of polling. - * Improves RDS reception significantly - * - * ToDo: - * - add firmware download/update support - */ - - -/* driver definitions */ -#define DRIVER_AUTHOR "Tobias Lorenz " -#define DRIVER_NAME "radio-si470x" -#define DRIVER_KERNEL_VERSION KERNEL_VERSION(1, 0, 10) -#define DRIVER_CARD "Silicon Labs Si470x FM Radio Receiver" -#define DRIVER_DESC "USB radio driver for Si470x FM Radio Receivers" -#define DRIVER_VERSION "1.0.10" - - -/* kernel includes */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "compat.h" -#include -#include -#include -#include -#include -#include - - -/* USB Device ID List */ -static struct usb_device_id si470x_usb_driver_id_table[] = { - /* Silicon Labs USB FM Radio Reference Design */ - { USB_DEVICE_AND_INTERFACE_INFO(0x10c4, 0x818a, USB_CLASS_HID, 0, 0) }, - /* ADS/Tech FM Radio Receiver (formerly Instant FM Music) */ - { USB_DEVICE_AND_INTERFACE_INFO(0x06e1, 0xa155, USB_CLASS_HID, 0, 0) }, - /* KWorld USB FM Radio SnapMusic Mobile 700 (FM700) */ - { USB_DEVICE_AND_INTERFACE_INFO(0x1b80, 0xd700, USB_CLASS_HID, 0, 0) }, - /* Sanei Electric, Inc. FM USB Radio (sold as DealExtreme.com PCear) */ - { USB_DEVICE_AND_INTERFACE_INFO(0x10c5, 0x819a, USB_CLASS_HID, 0, 0) }, - /* Terminating entry */ - { } -}; -MODULE_DEVICE_TABLE(usb, si470x_usb_driver_id_table); - - - -/************************************************************************** - * Module Parameters - **************************************************************************/ - -/* Radio Nr */ -static int radio_nr = -1; -module_param(radio_nr, int, 0444); -MODULE_PARM_DESC(radio_nr, "Radio Nr"); - -/* Spacing (kHz) */ -/* 0: 200 kHz (USA, Australia) */ -/* 1: 100 kHz (Europe, Japan) */ -/* 2: 50 kHz */ -static unsigned short space = 2; -module_param(space, ushort, 0444); -MODULE_PARM_DESC(space, "Spacing: 0=200kHz 1=100kHz *2=50kHz*"); - -/* Bottom of Band (MHz) */ -/* 0: 87.5 - 108 MHz (USA, Europe)*/ -/* 1: 76 - 108 MHz (Japan wide band) */ -/* 2: 76 - 90 MHz (Japan) */ -static unsigned short band = 1; -module_param(band, ushort, 0444); -MODULE_PARM_DESC(band, "Band: 0=87.5..108MHz *1=76..108MHz* 2=76..90MHz"); - -/* De-emphasis */ -/* 0: 75 us (USA) */ -/* 1: 50 us (Europe, Australia, Japan) */ -static unsigned short de = 1; -module_param(de, ushort, 0444); -MODULE_PARM_DESC(de, "De-emphasis: 0=75us *1=50us*"); - -/* USB timeout */ -static unsigned int usb_timeout = 500; -module_param(usb_timeout, uint, 0644); -MODULE_PARM_DESC(usb_timeout, "USB timeout (ms): *500*"); - -/* Tune timeout */ -static unsigned int tune_timeout = 3000; -module_param(tune_timeout, uint, 0644); -MODULE_PARM_DESC(tune_timeout, "Tune timeout: *3000*"); - -/* Seek timeout */ -static unsigned int seek_timeout = 5000; -module_param(seek_timeout, uint, 0644); -MODULE_PARM_DESC(seek_timeout, "Seek timeout: *5000*"); - -/* RDS buffer blocks */ -static unsigned int rds_buf = 100; -module_param(rds_buf, uint, 0444); -MODULE_PARM_DESC(rds_buf, "RDS buffer entries: *100*"); - -/* RDS maximum block errors */ -static unsigned short max_rds_errors = 1; -/* 0 means 0 errors requiring correction */ -/* 1 means 1-2 errors requiring correction (used by original USBRadio.exe) */ -/* 2 means 3-5 errors requiring correction */ -/* 3 means 6+ errors or errors in checkword, correction not possible */ -module_param(max_rds_errors, ushort, 0644); -MODULE_PARM_DESC(max_rds_errors, "RDS maximum block errors: *1*"); - - -/************************************************************************** - * Register Definitions - **************************************************************************/ -#define RADIO_REGISTER_SIZE 2 /* 16 register bit width */ -#define RADIO_REGISTER_NUM 16 /* DEVICEID ... RDSD */ -#define RDS_REGISTER_NUM 6 /* STATUSRSSI ... RDSD */ - -#define DEVICEID 0 /* Device ID */ -#define DEVICEID_PN 0xf000 /* bits 15..12: Part Number */ -#define DEVICEID_MFGID 0x0fff /* bits 11..00: Manufacturer ID */ - -#define CHIPID 1 /* Chip ID */ -#define CHIPID_REV 0xfc00 /* bits 15..10: Chip Version */ -#define CHIPID_DEV 0x0200 /* bits 09..09: Device */ -#define CHIPID_FIRMWARE 0x01ff /* bits 08..00: Firmware Version */ - -#define POWERCFG 2 /* Power Configuration */ -#define POWERCFG_DSMUTE 0x8000 /* bits 15..15: Softmute Disable */ -#define POWERCFG_DMUTE 0x4000 /* bits 14..14: Mute Disable */ -#define POWERCFG_MONO 0x2000 /* bits 13..13: Mono Select */ -#define POWERCFG_RDSM 0x0800 /* bits 11..11: RDS Mode (Si4701 only) */ -#define POWERCFG_SKMODE 0x0400 /* bits 10..10: Seek Mode */ -#define POWERCFG_SEEKUP 0x0200 /* bits 09..09: Seek Direction */ -#define POWERCFG_SEEK 0x0100 /* bits 08..08: Seek */ -#define POWERCFG_DISABLE 0x0040 /* bits 06..06: Powerup Disable */ -#define POWERCFG_ENABLE 0x0001 /* bits 00..00: Powerup Enable */ - -#define CHANNEL 3 /* Channel */ -#define CHANNEL_TUNE 0x8000 /* bits 15..15: Tune */ -#define CHANNEL_CHAN 0x03ff /* bits 09..00: Channel Select */ - -#define SYSCONFIG1 4 /* System Configuration 1 */ -#define SYSCONFIG1_RDSIEN 0x8000 /* bits 15..15: RDS Interrupt Enable (Si4701 only) */ -#define SYSCONFIG1_STCIEN 0x4000 /* bits 14..14: Seek/Tune Complete Interrupt Enable */ -#define SYSCONFIG1_RDS 0x1000 /* bits 12..12: RDS Enable (Si4701 only) */ -#define SYSCONFIG1_DE 0x0800 /* bits 11..11: De-emphasis (0=75us 1=50us) */ -#define SYSCONFIG1_AGCD 0x0400 /* bits 10..10: AGC Disable */ -#define SYSCONFIG1_BLNDADJ 0x00c0 /* bits 07..06: Stereo/Mono Blend Level Adjustment */ -#define SYSCONFIG1_GPIO3 0x0030 /* bits 05..04: General Purpose I/O 3 */ -#define SYSCONFIG1_GPIO2 0x000c /* bits 03..02: General Purpose I/O 2 */ -#define SYSCONFIG1_GPIO1 0x0003 /* bits 01..00: General Purpose I/O 1 */ - -#define SYSCONFIG2 5 /* System Configuration 2 */ -#define SYSCONFIG2_SEEKTH 0xff00 /* bits 15..08: RSSI Seek Threshold */ -#define SYSCONFIG2_BAND 0x0080 /* bits 07..06: Band Select */ -#define SYSCONFIG2_SPACE 0x0030 /* bits 05..04: Channel Spacing */ -#define SYSCONFIG2_VOLUME 0x000f /* bits 03..00: Volume */ - -#define SYSCONFIG3 6 /* System Configuration 3 */ -#define SYSCONFIG3_SMUTER 0xc000 /* bits 15..14: Softmute Attack/Recover Rate */ -#define SYSCONFIG3_SMUTEA 0x3000 /* bits 13..12: Softmute Attenuation */ -#define SYSCONFIG3_SKSNR 0x00f0 /* bits 07..04: Seek SNR Threshold */ -#define SYSCONFIG3_SKCNT 0x000f /* bits 03..00: Seek FM Impulse Detection Threshold */ - -#define TEST1 7 /* Test 1 */ -#define TEST1_AHIZEN 0x4000 /* bits 14..14: Audio High-Z Enable */ - -#define TEST2 8 /* Test 2 */ -/* TEST2 only contains reserved bits */ - -#define BOOTCONFIG 9 /* Boot Configuration */ -/* BOOTCONFIG only contains reserved bits */ - -#define STATUSRSSI 10 /* Status RSSI */ -#define STATUSRSSI_RDSR 0x8000 /* bits 15..15: RDS Ready (Si4701 only) */ -#define STATUSRSSI_STC 0x4000 /* bits 14..14: Seek/Tune Complete */ -#define STATUSRSSI_SF 0x2000 /* bits 13..13: Seek Fail/Band Limit */ -#define STATUSRSSI_AFCRL 0x1000 /* bits 12..12: AFC Rail */ -#define STATUSRSSI_RDSS 0x0800 /* bits 11..11: RDS Synchronized (Si4701 only) */ -#define STATUSRSSI_BLERA 0x0600 /* bits 10..09: RDS Block A Errors (Si4701 only) */ -#define STATUSRSSI_ST 0x0100 /* bits 08..08: Stereo Indicator */ -#define STATUSRSSI_RSSI 0x00ff /* bits 07..00: RSSI (Received Signal Strength Indicator) */ - -#define READCHAN 11 /* Read Channel */ -#define READCHAN_BLERB 0xc000 /* bits 15..14: RDS Block D Errors (Si4701 only) */ -#define READCHAN_BLERC 0x3000 /* bits 13..12: RDS Block C Errors (Si4701 only) */ -#define READCHAN_BLERD 0x0c00 /* bits 11..10: RDS Block B Errors (Si4701 only) */ -#define READCHAN_READCHAN 0x03ff /* bits 09..00: Read Channel */ - -#define RDSA 12 /* RDSA */ -#define RDSA_RDSA 0xffff /* bits 15..00: RDS Block A Data (Si4701 only) */ - -#define RDSB 13 /* RDSB */ -#define RDSB_RDSB 0xffff /* bits 15..00: RDS Block B Data (Si4701 only) */ - -#define RDSC 14 /* RDSC */ -#define RDSC_RDSC 0xffff /* bits 15..00: RDS Block C Data (Si4701 only) */ - -#define RDSD 15 /* RDSD */ -#define RDSD_RDSD 0xffff /* bits 15..00: RDS Block D Data (Si4701 only) */ - - - -/************************************************************************** - * USB HID Reports - **************************************************************************/ - -/* Reports 1-16 give direct read/write access to the 16 Si470x registers */ -/* with the (REPORT_ID - 1) corresponding to the register address across USB */ -/* endpoint 0 using GET_REPORT and SET_REPORT */ -#define REGISTER_REPORT_SIZE (RADIO_REGISTER_SIZE + 1) -#define REGISTER_REPORT(reg) ((reg) + 1) - -/* Report 17 gives direct read/write access to the entire Si470x register */ -/* map across endpoint 0 using GET_REPORT and SET_REPORT */ -#define ENTIRE_REPORT_SIZE (RADIO_REGISTER_NUM * RADIO_REGISTER_SIZE + 1) -#define ENTIRE_REPORT 17 - -/* Report 18 is used to send the lowest 6 Si470x registers up the HID */ -/* interrupt endpoint 1 to Windows every 20 milliseconds for status */ -#define RDS_REPORT_SIZE (RDS_REGISTER_NUM * RADIO_REGISTER_SIZE + 1) -#define RDS_REPORT 18 - -/* Report 19: LED state */ -#define LED_REPORT_SIZE 3 -#define LED_REPORT 19 - -/* Report 19: stream */ -#define STREAM_REPORT_SIZE 3 -#define STREAM_REPORT 19 - -/* Report 20: scratch */ -#define SCRATCH_PAGE_SIZE 63 -#define SCRATCH_REPORT_SIZE (SCRATCH_PAGE_SIZE + 1) -#define SCRATCH_REPORT 20 - -/* Reports 19-22: flash upgrade of the C8051F321 */ -#define WRITE_REPORT_SIZE 4 -#define WRITE_REPORT 19 -#define FLASH_REPORT_SIZE 64 -#define FLASH_REPORT 20 -#define CRC_REPORT_SIZE 3 -#define CRC_REPORT 21 -#define RESPONSE_REPORT_SIZE 2 -#define RESPONSE_REPORT 22 - -/* Report 23: currently unused, but can accept 60 byte reports on the HID */ -/* interrupt out endpoint 2 every 1 millisecond */ -#define UNUSED_REPORT 23 - - - -/************************************************************************** - * Software/Hardware Versions - **************************************************************************/ -#define RADIO_SW_VERSION_NOT_BOOTLOADABLE 6 -#define RADIO_SW_VERSION 7 -#define RADIO_SW_VERSION_CURRENT 15 -#define RADIO_HW_VERSION 1 - -#define SCRATCH_PAGE_SW_VERSION 1 -#define SCRATCH_PAGE_HW_VERSION 2 - - - -/************************************************************************** - * LED State Definitions - **************************************************************************/ -#define LED_COMMAND 0x35 - -#define NO_CHANGE_LED 0x00 -#define ALL_COLOR_LED 0x01 /* streaming state */ -#define BLINK_GREEN_LED 0x02 /* connect state */ -#define BLINK_RED_LED 0x04 -#define BLINK_ORANGE_LED 0x10 /* disconnect state */ -#define SOLID_GREEN_LED 0x20 /* tuning/seeking state */ -#define SOLID_RED_LED 0x40 /* bootload state */ -#define SOLID_ORANGE_LED 0x80 - - - -/************************************************************************** - * Stream State Definitions - **************************************************************************/ -#define STREAM_COMMAND 0x36 -#define STREAM_VIDPID 0x00 -#define STREAM_AUDIO 0xff - - - -/************************************************************************** - * Bootloader / Flash Commands - **************************************************************************/ - -/* unique id sent to bootloader and required to put into a bootload state */ -#define UNIQUE_BL_ID 0x34 - -/* mask for the flash data */ -#define FLASH_DATA_MASK 0x55 - -/* bootloader commands */ -#define GET_SW_VERSION_COMMAND 0x00 -#define SET_PAGE_COMMAND 0x01 -#define ERASE_PAGE_COMMAND 0x02 -#define WRITE_PAGE_COMMAND 0x03 -#define CRC_ON_PAGE_COMMAND 0x04 -#define READ_FLASH_BYTE_COMMAND 0x05 -#define RESET_DEVICE_COMMAND 0x06 -#define GET_HW_VERSION_COMMAND 0x07 -#define BLANK 0xff - -/* bootloader command responses */ -#define COMMAND_OK 0x01 -#define COMMAND_FAILED 0x02 -#define COMMAND_PENDING 0x03 - - - -/************************************************************************** - * General Driver Definitions - **************************************************************************/ - -/* - * si470x_device - private data - */ -struct si470x_device { - /* reference to USB and video device */ - struct usb_device *usbdev; - struct usb_interface *intf; - struct video_device *videodev; - - /* Interrupt endpoint handling */ - char *int_in_buffer; - struct usb_endpoint_descriptor *int_in_endpoint; - struct urb *int_in_urb; - int int_in_running; - - /* driver management */ - unsigned int users; - unsigned char disconnected; - struct mutex disconnect_lock; - - /* Silabs internal registers (0..15) */ - unsigned short registers[RADIO_REGISTER_NUM]; - - /* RDS receive buffer */ - wait_queue_head_t read_queue; - struct mutex lock; /* buffer locking */ - unsigned char *buffer; /* size is always multiple of three */ - unsigned int buf_size; - unsigned int rd_index; - unsigned int wr_index; - - /* scratch page */ - unsigned char software_version; - unsigned char hardware_version; -}; - - -/* - * The frequency is set in units of 62.5 Hz when using V4L2_TUNER_CAP_LOW, - * 62.5 kHz otherwise. - * The tuner is able to have a channel spacing of 50, 100 or 200 kHz. - * tuner->capability is therefore set to V4L2_TUNER_CAP_LOW - * The FREQ_MUL is then: 1 MHz / 62.5 Hz = 16000 - */ -#define FREQ_MUL (1000000 / 62.5) - - - -/************************************************************************** - * General Driver Functions - REGISTER_REPORTs - **************************************************************************/ - -/* - * si470x_get_report - receive a HID report - */ -static int si470x_get_report(struct si470x_device *radio, void *buf, int size) -{ - unsigned char *report = (unsigned char *) buf; - int retval; - - retval = usb_control_msg(radio->usbdev, - usb_rcvctrlpipe(radio->usbdev, 0), - HID_REQ_GET_REPORT, - USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN, - report[0], 2, - buf, size, usb_timeout); - - if (retval < 0) - printk(KERN_WARNING DRIVER_NAME - ": si470x_get_report: usb_control_msg returned %d\n", - retval); - return retval; -} - - -/* - * si470x_set_report - send a HID report - */ -static int si470x_set_report(struct si470x_device *radio, void *buf, int size) -{ - unsigned char *report = (unsigned char *) buf; - int retval; - - retval = usb_control_msg(radio->usbdev, - usb_sndctrlpipe(radio->usbdev, 0), - HID_REQ_SET_REPORT, - USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT, - report[0], 2, - buf, size, usb_timeout); - - if (retval < 0) - printk(KERN_WARNING DRIVER_NAME - ": si470x_set_report: usb_control_msg returned %d\n", - retval); - return retval; -} - - -/* - * si470x_get_register - read register - */ -static int si470x_get_register(struct si470x_device *radio, int regnr) -{ - unsigned char buf[REGISTER_REPORT_SIZE]; - int retval; - - buf[0] = REGISTER_REPORT(regnr); - - retval = si470x_get_report(radio, (void *) &buf, sizeof(buf)); - - if (retval >= 0) - radio->registers[regnr] = get_unaligned_be16(&buf[1]); - - return (retval < 0) ? -EINVAL : 0; -} - - -/* - * si470x_set_register - write register - */ -static int si470x_set_register(struct si470x_device *radio, int regnr) -{ - unsigned char buf[REGISTER_REPORT_SIZE]; - int retval; - - buf[0] = REGISTER_REPORT(regnr); - put_unaligned_be16(radio->registers[regnr], &buf[1]); - - retval = si470x_set_report(radio, (void *) &buf, sizeof(buf)); - - return (retval < 0) ? -EINVAL : 0; -} - - -/* - * si470x_set_chan - set the channel - */ -static int si470x_set_chan(struct si470x_device *radio, unsigned short chan) -{ - int retval; - unsigned long timeout; - bool timed_out = 0; - - /* start tuning */ - radio->registers[CHANNEL] &= ~CHANNEL_CHAN; - radio->registers[CHANNEL] |= CHANNEL_TUNE | chan; - retval = si470x_set_register(radio, CHANNEL); - if (retval < 0) - goto done; - - /* wait till tune operation has completed */ - timeout = jiffies + msecs_to_jiffies(tune_timeout); - do { - retval = si470x_get_register(radio, STATUSRSSI); - if (retval < 0) - goto stop; - timed_out = time_after(jiffies, timeout); - } while (((radio->registers[STATUSRSSI] & STATUSRSSI_STC) == 0) && - (!timed_out)); - if ((radio->registers[STATUSRSSI] & STATUSRSSI_STC) == 0) - printk(KERN_WARNING DRIVER_NAME ": tune does not complete\n"); - if (timed_out) - printk(KERN_WARNING DRIVER_NAME - ": tune timed out after %u ms\n", tune_timeout); - -stop: - /* stop tuning */ - radio->registers[CHANNEL] &= ~CHANNEL_TUNE; - retval = si470x_set_register(radio, CHANNEL); - -done: - return retval; -} - - -/* - * si470x_get_freq - get the frequency - */ -static int si470x_get_freq(struct si470x_device *radio, unsigned int *freq) -{ - unsigned int spacing, band_bottom; - unsigned short chan; - int retval; - - /* Spacing (kHz) */ - switch ((radio->registers[SYSCONFIG2] & SYSCONFIG2_SPACE) >> 4) { - /* 0: 200 kHz (USA, Australia) */ - case 0: - spacing = 0.200 * FREQ_MUL; break; - /* 1: 100 kHz (Europe, Japan) */ - case 1: - spacing = 0.100 * FREQ_MUL; break; - /* 2: 50 kHz */ - default: - spacing = 0.050 * FREQ_MUL; break; - }; - - /* Bottom of Band (MHz) */ - switch ((radio->registers[SYSCONFIG2] & SYSCONFIG2_BAND) >> 6) { - /* 0: 87.5 - 108 MHz (USA, Europe) */ - case 0: - band_bottom = 87.5 * FREQ_MUL; break; - /* 1: 76 - 108 MHz (Japan wide band) */ - default: - band_bottom = 76 * FREQ_MUL; break; - /* 2: 76 - 90 MHz (Japan) */ - case 2: - band_bottom = 76 * FREQ_MUL; break; - }; - - /* read channel */ - retval = si470x_get_register(radio, READCHAN); - chan = radio->registers[READCHAN] & READCHAN_READCHAN; - - /* Frequency (MHz) = Spacing (kHz) x Channel + Bottom of Band (MHz) */ - *freq = chan * spacing + band_bottom; - - return retval; -} - - -/* - * si470x_set_freq - set the frequency - */ -static int si470x_set_freq(struct si470x_device *radio, unsigned int freq) -{ - unsigned int spacing, band_bottom; - unsigned short chan; - - /* Spacing (kHz) */ - switch ((radio->registers[SYSCONFIG2] & SYSCONFIG2_SPACE) >> 4) { - /* 0: 200 kHz (USA, Australia) */ - case 0: - spacing = 0.200 * FREQ_MUL; break; - /* 1: 100 kHz (Europe, Japan) */ - case 1: - spacing = 0.100 * FREQ_MUL; break; - /* 2: 50 kHz */ - default: - spacing = 0.050 * FREQ_MUL; break; - }; - - /* Bottom of Band (MHz) */ - switch ((radio->registers[SYSCONFIG2] & SYSCONFIG2_BAND) >> 6) { - /* 0: 87.5 - 108 MHz (USA, Europe) */ - case 0: - band_bottom = 87.5 * FREQ_MUL; break; - /* 1: 76 - 108 MHz (Japan wide band) */ - default: - band_bottom = 76 * FREQ_MUL; break; - /* 2: 76 - 90 MHz (Japan) */ - case 2: - band_bottom = 76 * FREQ_MUL; break; - }; - - /* Chan = [ Freq (Mhz) - Bottom of Band (MHz) ] / Spacing (kHz) */ - chan = (freq - band_bottom) / spacing; - - return si470x_set_chan(radio, chan); -} - - -/* - * si470x_set_seek - set seek - */ -static int si470x_set_seek(struct si470x_device *radio, - unsigned int wrap_around, unsigned int seek_upward) -{ - int retval = 0; - unsigned long timeout; - bool timed_out = 0; - - /* start seeking */ - radio->registers[POWERCFG] |= POWERCFG_SEEK; - if (wrap_around == 1) - radio->registers[POWERCFG] &= ~POWERCFG_SKMODE; - else - radio->registers[POWERCFG] |= POWERCFG_SKMODE; - if (seek_upward == 1) - radio->registers[POWERCFG] |= POWERCFG_SEEKUP; - else - radio->registers[POWERCFG] &= ~POWERCFG_SEEKUP; - retval = si470x_set_register(radio, POWERCFG); - if (retval < 0) - goto done; - - /* wait till seek operation has completed */ - timeout = jiffies + msecs_to_jiffies(seek_timeout); - do { - retval = si470x_get_register(radio, STATUSRSSI); - if (retval < 0) - goto stop; - timed_out = time_after(jiffies, timeout); - } while (((radio->registers[STATUSRSSI] & STATUSRSSI_STC) == 0) && - (!timed_out)); - if ((radio->registers[STATUSRSSI] & STATUSRSSI_STC) == 0) - printk(KERN_WARNING DRIVER_NAME ": seek does not complete\n"); - if (radio->registers[STATUSRSSI] & STATUSRSSI_SF) - printk(KERN_WARNING DRIVER_NAME - ": seek failed / band limit reached\n"); - if (timed_out) - printk(KERN_WARNING DRIVER_NAME - ": seek timed out after %u ms\n", seek_timeout); - -stop: - /* stop seeking */ - radio->registers[POWERCFG] &= ~POWERCFG_SEEK; - retval = si470x_set_register(radio, POWERCFG); - -done: - /* try again, if timed out */ - if ((retval == 0) && timed_out) - retval = -EAGAIN; - - return retval; -} - - -/* - * si470x_start - switch on radio - */ -static int si470x_start(struct si470x_device *radio) -{ - int retval; - - /* powercfg */ - radio->registers[POWERCFG] = - POWERCFG_DMUTE | POWERCFG_ENABLE | POWERCFG_RDSM; - retval = si470x_set_register(radio, POWERCFG); - if (retval < 0) - goto done; - - /* sysconfig 1 */ - radio->registers[SYSCONFIG1] = SYSCONFIG1_DE; - retval = si470x_set_register(radio, SYSCONFIG1); - if (retval < 0) - goto done; - - /* sysconfig 2 */ - radio->registers[SYSCONFIG2] = - (0x3f << 8) | /* SEEKTH */ - ((band << 6) & SYSCONFIG2_BAND) | /* BAND */ - ((space << 4) & SYSCONFIG2_SPACE) | /* SPACE */ - 15; /* VOLUME (max) */ - retval = si470x_set_register(radio, SYSCONFIG2); - if (retval < 0) - goto done; - - /* reset last channel */ - retval = si470x_set_chan(radio, - radio->registers[CHANNEL] & CHANNEL_CHAN); - -done: - return retval; -} - - -/* - * si470x_stop - switch off radio - */ -static int si470x_stop(struct si470x_device *radio) -{ - int retval; - - /* sysconfig 1 */ - radio->registers[SYSCONFIG1] &= ~SYSCONFIG1_RDS; - retval = si470x_set_register(radio, SYSCONFIG1); - if (retval < 0) - goto done; - - /* powercfg */ - radio->registers[POWERCFG] &= ~POWERCFG_DMUTE; - /* POWERCFG_ENABLE has to automatically go low */ - radio->registers[POWERCFG] |= POWERCFG_ENABLE | POWERCFG_DISABLE; - retval = si470x_set_register(radio, POWERCFG); - -done: - return retval; -} - - -/* - * si470x_rds_on - switch on rds reception - */ -static int si470x_rds_on(struct si470x_device *radio) -{ - int retval; - - /* sysconfig 1 */ - mutex_lock(&radio->lock); - radio->registers[SYSCONFIG1] |= SYSCONFIG1_RDS; - retval = si470x_set_register(radio, SYSCONFIG1); - if (retval < 0) - radio->registers[SYSCONFIG1] &= ~SYSCONFIG1_RDS; - mutex_unlock(&radio->lock); - - return retval; -} - - - -/************************************************************************** - * General Driver Functions - ENTIRE_REPORT - **************************************************************************/ - -/* - * si470x_get_all_registers - read entire registers - */ -static int si470x_get_all_registers(struct si470x_device *radio) -{ - unsigned char buf[ENTIRE_REPORT_SIZE]; - int retval; - unsigned char regnr; - - buf[0] = ENTIRE_REPORT; - - retval = si470x_get_report(radio, (void *) &buf, sizeof(buf)); - - if (retval >= 0) - for (regnr = 0; regnr < RADIO_REGISTER_NUM; regnr++) - radio->registers[regnr] = get_unaligned_be16( - &buf[regnr * RADIO_REGISTER_SIZE + 1]); - - return (retval < 0) ? -EINVAL : 0; -} - - - -/************************************************************************** - * General Driver Functions - LED_REPORT - **************************************************************************/ - -/* - * si470x_set_led_state - sets the led state - */ -static int si470x_set_led_state(struct si470x_device *radio, - unsigned char led_state) -{ - unsigned char buf[LED_REPORT_SIZE]; - int retval; - - buf[0] = LED_REPORT; - buf[1] = LED_COMMAND; - buf[2] = led_state; - - retval = si470x_set_report(radio, (void *) &buf, sizeof(buf)); - - return (retval < 0) ? -EINVAL : 0; -} - - - -/************************************************************************** - * General Driver Functions - SCRATCH_REPORT - **************************************************************************/ - -/* - * si470x_get_scratch_versions - gets the scratch page and version infos - */ -static int si470x_get_scratch_page_versions(struct si470x_device *radio) -{ - unsigned char buf[SCRATCH_REPORT_SIZE]; - int retval; - - buf[0] = SCRATCH_REPORT; - - retval = si470x_get_report(radio, (void *) &buf, sizeof(buf)); - - if (retval < 0) - printk(KERN_WARNING DRIVER_NAME ": si470x_get_scratch: " - "si470x_get_report returned %d\n", retval); - else { - radio->software_version = buf[1]; - radio->hardware_version = buf[2]; - } - - return (retval < 0) ? -EINVAL : 0; -} - - - -/************************************************************************** - * RDS Driver Functions - **************************************************************************/ - -/* - * si470x_int_in_callback - rds callback and processing function - * - * TODO: do we need to use mutex locks in some sections? - */ -static void si470x_int_in_callback(struct urb *urb) -{ - struct si470x_device *radio = urb->context; - unsigned char buf[RDS_REPORT_SIZE]; - int retval; - unsigned char regnr; - unsigned char blocknum; - unsigned short bler; /* rds block errors */ - unsigned short rds; - unsigned char tmpbuf[3]; - - if (urb->status) { - if (urb->status == -ENOENT || - urb->status == -ECONNRESET || - urb->status == -ESHUTDOWN) { - return; - } else { - printk(KERN_WARNING DRIVER_NAME - ": non-zero urb status (%d)\n", urb->status); - goto resubmit; /* Maybe we can recover. */ - } - } - - /* safety checks */ - if (radio->disconnected) - return; - if ((radio->registers[SYSCONFIG1] & SYSCONFIG1_RDS) == 0) - goto resubmit; - - if (urb->actual_length > 0) { - /* Update RDS registers with URB data */ - buf[0] = RDS_REPORT; - for (regnr = 0; regnr < RDS_REGISTER_NUM; regnr++) - radio->registers[STATUSRSSI + regnr] = - get_unaligned_be16(&radio->int_in_buffer[ - regnr * RADIO_REGISTER_SIZE + 1]); - /* get rds blocks */ - if ((radio->registers[STATUSRSSI] & STATUSRSSI_RDSR) == 0) { - /* No RDS group ready, better luck next time */ - goto resubmit; - } - if ((radio->registers[STATUSRSSI] & STATUSRSSI_RDSS) == 0) { - /* RDS decoder not synchronized */ - goto resubmit; - } - for (blocknum = 0; blocknum < 4; blocknum++) { - switch (blocknum) { - default: - bler = (radio->registers[STATUSRSSI] & - STATUSRSSI_BLERA) >> 9; - rds = radio->registers[RDSA]; - break; - case 1: - bler = (radio->registers[READCHAN] & - READCHAN_BLERB) >> 14; - rds = radio->registers[RDSB]; - break; - case 2: - bler = (radio->registers[READCHAN] & - READCHAN_BLERC) >> 12; - rds = radio->registers[RDSC]; - break; - case 3: - bler = (radio->registers[READCHAN] & - READCHAN_BLERD) >> 10; - rds = radio->registers[RDSD]; - break; - }; - - /* Fill the V4L2 RDS buffer */ - put_unaligned_le16(rds, &tmpbuf); - tmpbuf[2] = blocknum; /* offset name */ - tmpbuf[2] |= blocknum << 3; /* received offset */ - if (bler > max_rds_errors) - tmpbuf[2] |= 0x80; /* uncorrectable errors */ - else if (bler > 0) - tmpbuf[2] |= 0x40; /* corrected error(s) */ - - /* copy RDS block to internal buffer */ - memcpy(&radio->buffer[radio->wr_index], &tmpbuf, 3); - radio->wr_index += 3; - - /* wrap write pointer */ - if (radio->wr_index >= radio->buf_size) - radio->wr_index = 0; - - /* check for overflow */ - if (radio->wr_index == radio->rd_index) { - /* increment and wrap read pointer */ - radio->rd_index += 3; - if (radio->rd_index >= radio->buf_size) - radio->rd_index = 0; - } - } - if (radio->wr_index != radio->rd_index) - wake_up_interruptible(&radio->read_queue); - } - -resubmit: - /* Resubmit if we're still running. */ - if (radio->int_in_running && radio->usbdev) { - retval = usb_submit_urb(radio->int_in_urb, GFP_ATOMIC); - if (retval) { - printk(KERN_WARNING DRIVER_NAME - ": resubmitting urb failed (%d)", retval); - radio->int_in_running = 0; - } - } -} - - - -/************************************************************************** - * File Operations Interface - **************************************************************************/ - -/* - * si470x_fops_read - read RDS data - */ -static ssize_t si470x_fops_read(struct file *file, char __user *buf, - size_t count, loff_t *ppos) -{ - struct si470x_device *radio = video_drvdata(file); - int retval = 0; - unsigned int block_count = 0; - - /* switch on rds reception */ - if ((radio->registers[SYSCONFIG1] & SYSCONFIG1_RDS) == 0) { - si470x_rds_on(radio); - } - - /* block if no new data available */ - while (radio->wr_index == radio->rd_index) { - if (file->f_flags & O_NONBLOCK) { - retval = -EWOULDBLOCK; - goto done; - } - if (wait_event_interruptible(radio->read_queue, - radio->wr_index != radio->rd_index) < 0) { - retval = -EINTR; - goto done; - } - } - - /* calculate block count from byte count */ - count /= 3; - - /* copy RDS block out of internal buffer and to user buffer */ - mutex_lock(&radio->lock); - while (block_count < count) { - if (radio->rd_index == radio->wr_index) - break; - - /* always transfer rds complete blocks */ - if (copy_to_user(buf, &radio->buffer[radio->rd_index], 3)) - /* retval = -EFAULT; */ - break; - - /* increment and wrap read pointer */ - radio->rd_index += 3; - if (radio->rd_index >= radio->buf_size) - radio->rd_index = 0; - - /* increment counters */ - block_count++; - buf += 3; - retval += 3; - } - mutex_unlock(&radio->lock); - -done: - return retval; -} - - -/* - * si470x_fops_poll - poll RDS data - */ -static unsigned int si470x_fops_poll(struct file *file, - struct poll_table_struct *pts) -{ - struct si470x_device *radio = video_drvdata(file); - int retval = 0; - - /* switch on rds reception */ - if ((radio->registers[SYSCONFIG1] & SYSCONFIG1_RDS) == 0) { - si470x_rds_on(radio); - } - - poll_wait(file, &radio->read_queue, pts); - - if (radio->rd_index != radio->wr_index) - retval = POLLIN | POLLRDNORM; - - return retval; -} - - -/* - * si470x_fops_open - file open - */ -static int si470x_fops_open(struct file *file) -{ - struct si470x_device *radio = video_drvdata(file); - int retval; - - lock_kernel(); - radio->users++; - - retval = usb_autopm_get_interface(radio->intf); - if (retval < 0) { - radio->users--; - retval = -EIO; - goto done; - } - - if (radio->users == 1) { - /* start radio */ - retval = si470x_start(radio); - if (retval < 0) { - usb_autopm_put_interface(radio->intf); - goto done; - } - - /* initialize interrupt urb */ - usb_fill_int_urb(radio->int_in_urb, radio->usbdev, - usb_rcvintpipe(radio->usbdev, - radio->int_in_endpoint->bEndpointAddress), - radio->int_in_buffer, - le16_to_cpu(radio->int_in_endpoint->wMaxPacketSize), - si470x_int_in_callback, - radio, - radio->int_in_endpoint->bInterval); - - radio->int_in_running = 1; - mb(); - - retval = usb_submit_urb(radio->int_in_urb, GFP_KERNEL); - if (retval) { - printk(KERN_INFO DRIVER_NAME - ": submitting int urb failed (%d)\n", retval); - radio->int_in_running = 0; - usb_autopm_put_interface(radio->intf); - } - } - -done: - unlock_kernel(); - return retval; -} - - -/* - * si470x_fops_release - file release - */ -static int si470x_fops_release(struct file *file) -{ - struct si470x_device *radio = video_drvdata(file); - int retval = 0; - - /* safety check */ - if (!radio) { - retval = -ENODEV; - goto done; - } - - mutex_lock(&radio->disconnect_lock); - radio->users--; - if (radio->users == 0) { - /* shutdown interrupt handler */ - if (radio->int_in_running) { - radio->int_in_running = 0; - if (radio->int_in_urb) - usb_kill_urb(radio->int_in_urb); - } - - if (radio->disconnected) { - video_unregister_device(radio->videodev); - kfree(radio->int_in_buffer); - kfree(radio->buffer); - kfree(radio); - goto unlock; - } - - /* cancel read processes */ - wake_up_interruptible(&radio->read_queue); - - /* stop radio */ - retval = si470x_stop(radio); - usb_autopm_put_interface(radio->intf); - } -unlock: - mutex_unlock(&radio->disconnect_lock); -done: - return retval; -} - - -/* - * si470x_fops - file operations interface - */ -static const struct v4l2_file_operations si470x_fops = { - .owner = THIS_MODULE, - .read = si470x_fops_read, - .poll = si470x_fops_poll, - .ioctl = video_ioctl2, - .open = si470x_fops_open, - .release = si470x_fops_release, -}; - - - -/************************************************************************** - * Video4Linux Interface - **************************************************************************/ - -/* - * si470x_vidioc_querycap - query device capabilities - */ -static int si470x_vidioc_querycap(struct file *file, void *priv, - struct v4l2_capability *capability) -{ - struct si470x_device *radio = video_drvdata(file); - - strlcpy(capability->driver, DRIVER_NAME, sizeof(capability->driver)); - strlcpy(capability->card, DRIVER_CARD, sizeof(capability->card)); - usb_make_path(radio->usbdev, capability->bus_info, sizeof(capability->bus_info)); - capability->version = DRIVER_KERNEL_VERSION; - capability->capabilities = V4L2_CAP_HW_FREQ_SEEK | - V4L2_CAP_TUNER | V4L2_CAP_RADIO | V4L2_CAP_RDS_CAPTURE; - - return 0; -} - - -/* - * si470x_vidioc_queryctrl - enumerate control items - */ -static int si470x_vidioc_queryctrl(struct file *file, void *priv, - struct v4l2_queryctrl *qc) -{ - int retval = -EINVAL; - - /* abort if qc->id is below V4L2_CID_BASE */ - if (qc->id < V4L2_CID_BASE) - goto done; - - /* search video control */ - switch (qc->id) { - case V4L2_CID_AUDIO_VOLUME: - return v4l2_ctrl_query_fill(qc, 0, 15, 1, 15); - case V4L2_CID_AUDIO_MUTE: - return v4l2_ctrl_query_fill(qc, 0, 1, 1, 1); - } - - /* disable unsupported base controls */ - /* to satisfy kradio and such apps */ - if ((retval == -EINVAL) && (qc->id < V4L2_CID_LASTP1)) { - qc->flags = V4L2_CTRL_FLAG_DISABLED; - retval = 0; - } - -done: - if (retval < 0) - printk(KERN_WARNING DRIVER_NAME - ": query controls failed with %d\n", retval); - return retval; -} - - -/* - * si470x_vidioc_g_ctrl - get the value of a control - */ -static int si470x_vidioc_g_ctrl(struct file *file, void *priv, - struct v4l2_control *ctrl) -{ - struct si470x_device *radio = video_drvdata(file); - int retval = 0; - - /* safety checks */ - if (radio->disconnected) { - retval = -EIO; - goto done; - } - - switch (ctrl->id) { - case V4L2_CID_AUDIO_VOLUME: - ctrl->value = radio->registers[SYSCONFIG2] & - SYSCONFIG2_VOLUME; - break; - case V4L2_CID_AUDIO_MUTE: - ctrl->value = ((radio->registers[POWERCFG] & - POWERCFG_DMUTE) == 0) ? 1 : 0; - break; - default: - retval = -EINVAL; - } - -done: - if (retval < 0) - printk(KERN_WARNING DRIVER_NAME - ": get control failed with %d\n", retval); - return retval; -} - - -/* - * si470x_vidioc_s_ctrl - set the value of a control - */ -static int si470x_vidioc_s_ctrl(struct file *file, void *priv, - struct v4l2_control *ctrl) -{ - struct si470x_device *radio = video_drvdata(file); - int retval = 0; - - /* safety checks */ - if (radio->disconnected) { - retval = -EIO; - goto done; - } - - switch (ctrl->id) { - case V4L2_CID_AUDIO_VOLUME: - radio->registers[SYSCONFIG2] &= ~SYSCONFIG2_VOLUME; - radio->registers[SYSCONFIG2] |= ctrl->value; - retval = si470x_set_register(radio, SYSCONFIG2); - break; - case V4L2_CID_AUDIO_MUTE: - if (ctrl->value == 1) - radio->registers[POWERCFG] &= ~POWERCFG_DMUTE; - else - radio->registers[POWERCFG] |= POWERCFG_DMUTE; - retval = si470x_set_register(radio, POWERCFG); - break; - default: - retval = -EINVAL; - } - -done: - if (retval < 0) - printk(KERN_WARNING DRIVER_NAME - ": set control failed with %d\n", retval); - return retval; -} - - -/* - * si470x_vidioc_g_audio - get audio attributes - */ -static int si470x_vidioc_g_audio(struct file *file, void *priv, - struct v4l2_audio *audio) -{ - /* driver constants */ - audio->index = 0; - strcpy(audio->name, "Radio"); - audio->capability = V4L2_AUDCAP_STEREO; - audio->mode = 0; - - return 0; -} - - -/* - * si470x_vidioc_g_tuner - get tuner attributes - */ -static int si470x_vidioc_g_tuner(struct file *file, void *priv, - struct v4l2_tuner *tuner) -{ - struct si470x_device *radio = video_drvdata(file); - int retval = 0; - - /* safety checks */ - if (radio->disconnected) { - retval = -EIO; - goto done; - } - if (tuner->index != 0) { - retval = -EINVAL; - goto done; - } - - retval = si470x_get_register(radio, STATUSRSSI); - if (retval < 0) - goto done; - - /* driver constants */ - strcpy(tuner->name, "FM"); - tuner->type = V4L2_TUNER_RADIO; - tuner->capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO | - V4L2_TUNER_CAP_RDS; - - /* range limits */ - switch ((radio->registers[SYSCONFIG2] & SYSCONFIG2_BAND) >> 6) { - /* 0: 87.5 - 108 MHz (USA, Europe, default) */ - default: - tuner->rangelow = 87.5 * FREQ_MUL; - tuner->rangehigh = 108 * FREQ_MUL; - break; - /* 1: 76 - 108 MHz (Japan wide band) */ - case 1 : - tuner->rangelow = 76 * FREQ_MUL; - tuner->rangehigh = 108 * FREQ_MUL; - break; - /* 2: 76 - 90 MHz (Japan) */ - case 2 : - tuner->rangelow = 76 * FREQ_MUL; - tuner->rangehigh = 90 * FREQ_MUL; - break; - }; - - /* stereo indicator == stereo (instead of mono) */ - if ((radio->registers[STATUSRSSI] & STATUSRSSI_ST) == 0) - tuner->rxsubchans = V4L2_TUNER_SUB_MONO; - else - tuner->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO; - /* If there is a reliable method of detecting an RDS channel, - then this code should check for that before setting this - RDS subchannel. */ - tuner->rxsubchans |= V4L2_TUNER_SUB_RDS; - - /* mono/stereo selector */ - if ((radio->registers[POWERCFG] & POWERCFG_MONO) == 0) - tuner->audmode = V4L2_TUNER_MODE_STEREO; - else - tuner->audmode = V4L2_TUNER_MODE_MONO; - - /* min is worst, max is best; signal:0..0xffff; rssi: 0..0xff */ - /* measured in units of dbµV in 1 db increments (max at ~75 dbµV) */ - tuner->signal = (radio->registers[STATUSRSSI] & STATUSRSSI_RSSI); - /* the ideal factor is 0xffff/75 = 873,8 */ - tuner->signal = (tuner->signal * 873) + (8 * tuner->signal / 10); - - /* automatic frequency control: -1: freq to low, 1 freq to high */ - /* AFCRL does only indicate that freq. differs, not if too low/high */ - tuner->afc = (radio->registers[STATUSRSSI] & STATUSRSSI_AFCRL) ? 1 : 0; - -done: - if (retval < 0) - printk(KERN_WARNING DRIVER_NAME - ": get tuner failed with %d\n", retval); - return retval; -} - - -/* - * si470x_vidioc_s_tuner - set tuner attributes - */ -static int si470x_vidioc_s_tuner(struct file *file, void *priv, - struct v4l2_tuner *tuner) -{ - struct si470x_device *radio = video_drvdata(file); - int retval = -EINVAL; - - /* safety checks */ - if (radio->disconnected) { - retval = -EIO; - goto done; - } - if (tuner->index != 0) - goto done; - - /* mono/stereo selector */ - switch (tuner->audmode) { - case V4L2_TUNER_MODE_MONO: - radio->registers[POWERCFG] |= POWERCFG_MONO; /* force mono */ - break; - case V4L2_TUNER_MODE_STEREO: - radio->registers[POWERCFG] &= ~POWERCFG_MONO; /* try stereo */ - break; - default: - goto done; - } - - retval = si470x_set_register(radio, POWERCFG); - -done: - if (retval < 0) - printk(KERN_WARNING DRIVER_NAME - ": set tuner failed with %d\n", retval); - return retval; -} - - -/* - * si470x_vidioc_g_frequency - get tuner or modulator radio frequency - */ -static int si470x_vidioc_g_frequency(struct file *file, void *priv, - struct v4l2_frequency *freq) -{ - struct si470x_device *radio = video_drvdata(file); - int retval = 0; - - /* safety checks */ - if (radio->disconnected) { - retval = -EIO; - goto done; - } - if (freq->tuner != 0) { - retval = -EINVAL; - goto done; - } - - freq->type = V4L2_TUNER_RADIO; - retval = si470x_get_freq(radio, &freq->frequency); - -done: - if (retval < 0) - printk(KERN_WARNING DRIVER_NAME - ": get frequency failed with %d\n", retval); - return retval; -} - - -/* - * si470x_vidioc_s_frequency - set tuner or modulator radio frequency - */ -static int si470x_vidioc_s_frequency(struct file *file, void *priv, - struct v4l2_frequency *freq) -{ - struct si470x_device *radio = video_drvdata(file); - int retval = 0; - - /* safety checks */ - if (radio->disconnected) { - retval = -EIO; - goto done; - } - if (freq->tuner != 0) { - retval = -EINVAL; - goto done; - } - - retval = si470x_set_freq(radio, freq->frequency); - -done: - if (retval < 0) - printk(KERN_WARNING DRIVER_NAME - ": set frequency failed with %d\n", retval); - return retval; -} - - -/* - * si470x_vidioc_s_hw_freq_seek - set hardware frequency seek - */ -static int si470x_vidioc_s_hw_freq_seek(struct file *file, void *priv, - struct v4l2_hw_freq_seek *seek) -{ - struct si470x_device *radio = video_drvdata(file); - int retval = 0; - - /* safety checks */ - if (radio->disconnected) { - retval = -EIO; - goto done; - } - if (seek->tuner != 0) { - retval = -EINVAL; - goto done; - } - - retval = si470x_set_seek(radio, seek->wrap_around, seek->seek_upward); - -done: - if (retval < 0) - printk(KERN_WARNING DRIVER_NAME - ": set hardware frequency seek failed with %d\n", - retval); - return retval; -} - - -/* - * si470x_ioctl_ops - video device ioctl operations - */ -static const struct v4l2_ioctl_ops si470x_ioctl_ops = { - .vidioc_querycap = si470x_vidioc_querycap, - .vidioc_queryctrl = si470x_vidioc_queryctrl, - .vidioc_g_ctrl = si470x_vidioc_g_ctrl, - .vidioc_s_ctrl = si470x_vidioc_s_ctrl, - .vidioc_g_audio = si470x_vidioc_g_audio, - .vidioc_g_tuner = si470x_vidioc_g_tuner, - .vidioc_s_tuner = si470x_vidioc_s_tuner, - .vidioc_g_frequency = si470x_vidioc_g_frequency, - .vidioc_s_frequency = si470x_vidioc_s_frequency, - .vidioc_s_hw_freq_seek = si470x_vidioc_s_hw_freq_seek, -}; - - -/* - * si470x_viddev_template - video device interface - */ -static struct video_device si470x_viddev_template = { - .fops = &si470x_fops, - .name = DRIVER_NAME, - .release = video_device_release, - .ioctl_ops = &si470x_ioctl_ops, -}; - - - -/************************************************************************** - * USB Interface - **************************************************************************/ - -/* - * si470x_usb_driver_probe - probe for the device - */ -static int si470x_usb_driver_probe(struct usb_interface *intf, - const struct usb_device_id *id) -{ - struct si470x_device *radio; - struct usb_host_interface *iface_desc; - struct usb_endpoint_descriptor *endpoint; - int i, int_end_size, retval = 0; - - /* private data allocation and initialization */ - radio = kzalloc(sizeof(struct si470x_device), GFP_KERNEL); - if (!radio) { - retval = -ENOMEM; - goto err_initial; - } - radio->users = 0; - radio->disconnected = 0; - radio->usbdev = interface_to_usbdev(intf); - radio->intf = intf; - mutex_init(&radio->disconnect_lock); - mutex_init(&radio->lock); - - iface_desc = intf->cur_altsetting; - - /* Set up interrupt endpoint information. */ - for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { - endpoint = &iface_desc->endpoint[i].desc; - if (((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == - USB_DIR_IN) && ((endpoint->bmAttributes & - USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT)) - radio->int_in_endpoint = endpoint; - } - if (!radio->int_in_endpoint) { - printk(KERN_INFO DRIVER_NAME - ": could not find interrupt in endpoint\n"); - retval = -EIO; - goto err_radio; - } - - int_end_size = le16_to_cpu(radio->int_in_endpoint->wMaxPacketSize); - - radio->int_in_buffer = kmalloc(int_end_size, GFP_KERNEL); - if (!radio->int_in_buffer) { - printk(KERN_INFO DRIVER_NAME - "could not allocate int_in_buffer"); - retval = -ENOMEM; - goto err_radio; - } - - radio->int_in_urb = usb_alloc_urb(0, GFP_KERNEL); - if (!radio->int_in_urb) { - printk(KERN_INFO DRIVER_NAME "could not allocate int_in_urb"); - retval = -ENOMEM; - goto err_intbuffer; - } - - /* video device allocation and initialization */ - radio->videodev = video_device_alloc(); - if (!radio->videodev) { - retval = -ENOMEM; - goto err_intbuffer; - } - memcpy(radio->videodev, &si470x_viddev_template, - sizeof(si470x_viddev_template)); - video_set_drvdata(radio->videodev, radio); - - /* show some infos about the specific si470x device */ - if (si470x_get_all_registers(radio) < 0) { - retval = -EIO; - goto err_video; - } - printk(KERN_INFO DRIVER_NAME ": DeviceID=0x%4.4hx ChipID=0x%4.4hx\n", - radio->registers[DEVICEID], radio->registers[CHIPID]); - - /* get software and hardware versions */ - if (si470x_get_scratch_page_versions(radio) < 0) { - retval = -EIO; - goto err_video; - } - printk(KERN_INFO DRIVER_NAME - ": software version %d, hardware version %d\n", - radio->software_version, radio->hardware_version); - - /* check if device and firmware is current */ - if ((radio->registers[CHIPID] & CHIPID_FIRMWARE) - < RADIO_SW_VERSION_CURRENT) { - printk(KERN_WARNING DRIVER_NAME - ": This driver is known to work with " - "firmware version %hu,\n", RADIO_SW_VERSION_CURRENT); - printk(KERN_WARNING DRIVER_NAME - ": but the device has firmware version %hu.\n", - radio->registers[CHIPID] & CHIPID_FIRMWARE); - printk(KERN_WARNING DRIVER_NAME - ": If you have some trouble using this driver,\n"); - printk(KERN_WARNING DRIVER_NAME - ": please report to V4L ML at " - "linux-media@vger.kernel.org\n"); - } - - /* set initial frequency */ - si470x_set_freq(radio, 87.5 * FREQ_MUL); /* available in all regions */ - - /* set led to connect state */ - si470x_set_led_state(radio, BLINK_GREEN_LED); - - /* rds buffer allocation */ - radio->buf_size = rds_buf * 3; - radio->buffer = kmalloc(radio->buf_size, GFP_KERNEL); - if (!radio->buffer) { - retval = -EIO; - goto err_video; - } - - /* rds buffer configuration */ - radio->wr_index = 0; - radio->rd_index = 0; - init_waitqueue_head(&radio->read_queue); - - /* register video device */ - retval = video_register_device(radio->videodev, VFL_TYPE_RADIO, radio_nr); - if (retval) { - printk(KERN_WARNING DRIVER_NAME - ": Could not register video device\n"); - goto err_all; - } - usb_set_intfdata(intf, radio); - - return 0; -err_all: - kfree(radio->buffer); -err_video: - video_device_release(radio->videodev); -err_intbuffer: - kfree(radio->int_in_buffer); -err_radio: - kfree(radio); -err_initial: - return retval; -} - - -/* - * si470x_usb_driver_suspend - suspend the device - */ -static int si470x_usb_driver_suspend(struct usb_interface *intf, - pm_message_t message) -{ - printk(KERN_INFO DRIVER_NAME ": suspending now...\n"); - - return 0; -} - - -/* - * si470x_usb_driver_resume - resume the device - */ -static int si470x_usb_driver_resume(struct usb_interface *intf) -{ - printk(KERN_INFO DRIVER_NAME ": resuming now...\n"); - - return 0; -} - - -/* - * si470x_usb_driver_disconnect - disconnect the device - */ -static void si470x_usb_driver_disconnect(struct usb_interface *intf) -{ - struct si470x_device *radio = usb_get_intfdata(intf); - - mutex_lock(&radio->disconnect_lock); - radio->disconnected = 1; - usb_set_intfdata(intf, NULL); - if (radio->users == 0) { - /* set led to disconnect state */ - si470x_set_led_state(radio, BLINK_ORANGE_LED); - - /* Free data structures. */ - usb_free_urb(radio->int_in_urb); - - kfree(radio->int_in_buffer); - video_unregister_device(radio->videodev); - kfree(radio->buffer); - kfree(radio); - } - mutex_unlock(&radio->disconnect_lock); -} - - -/* - * si470x_usb_driver - usb driver interface - */ -static struct usb_driver si470x_usb_driver = { - .name = DRIVER_NAME, - .probe = si470x_usb_driver_probe, - .disconnect = si470x_usb_driver_disconnect, - .suspend = si470x_usb_driver_suspend, - .resume = si470x_usb_driver_resume, - .id_table = si470x_usb_driver_id_table, - .supports_autosuspend = 1, -}; - - - -/************************************************************************** - * Module Interface - **************************************************************************/ - -/* - * si470x_module_init - module init - */ -static int __init si470x_module_init(void) -{ - printk(KERN_INFO DRIVER_DESC ", Version " DRIVER_VERSION "\n"); - return usb_register(&si470x_usb_driver); -} - - -/* - * si470x_module_exit - module exit - */ -static void __exit si470x_module_exit(void) -{ - usb_deregister(&si470x_usb_driver); -} - - -module_init(si470x_module_init); -module_exit(si470x_module_exit); - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR(DRIVER_AUTHOR); -MODULE_DESCRIPTION(DRIVER_DESC); -MODULE_VERSION(DRIVER_VERSION); diff --git a/linux/drivers/media/radio/si470x/Kconfig b/linux/drivers/media/radio/si470x/Kconfig new file mode 100644 index 000000000..20d05c04f --- /dev/null +++ b/linux/drivers/media/radio/si470x/Kconfig @@ -0,0 +1,24 @@ +config USB_SI470X + tristate "Silicon Labs Si470x FM Radio Receiver support with USB" + depends on USB && RADIO_SI470X + ---help--- + This is a driver for USB devices with the Silicon Labs SI470x + chip. Currently these devices are known to work: + - 10c4:818a: Silicon Labs USB FM Radio Reference Design + - 06e1:a155: ADS/Tech FM Radio Receiver (formerly Instant FM Music) + - 1b80:d700: KWorld USB FM Radio SnapMusic Mobile 700 (FM700) + - 10c5:819a: Sanei Electric FM USB Radio (aka DealExtreme.com PCear) + + Sound is provided by the ALSA USB Audio/MIDI driver. Therefore + if you don't want to use the device solely for RDS receiving, + it is recommended to also select SND_USB_AUDIO. + + Please have a look at the documentation, especially on how + to redirect the audio stream from the radio to your sound device: + Documentation/video4linux/si470x.txt + + Say Y here if you want to connect this type of radio to your + computer's USB port. + + To compile this driver as a module, choose M here: the + module will be called radio-usb-si470x. diff --git a/linux/drivers/media/radio/si470x/Makefile b/linux/drivers/media/radio/si470x/Makefile new file mode 100644 index 000000000..3cb777fe3 --- /dev/null +++ b/linux/drivers/media/radio/si470x/Makefile @@ -0,0 +1,7 @@ +# +# Makefile for radios with Silicon Labs Si470x FM Radio Receivers +# + +radio-usb-si470x-objs := radio-si470x-usb.o radio-si470x-common.o + +obj-$(CONFIG_USB_SI470X) += radio-usb-si470x.o diff --git a/linux/drivers/media/radio/si470x/radio-si470x-common.c b/linux/drivers/media/radio/si470x/radio-si470x-common.c new file mode 100644 index 000000000..b64559d56 --- /dev/null +++ b/linux/drivers/media/radio/si470x/radio-si470x-common.c @@ -0,0 +1,794 @@ +/* + * drivers/media/radio/si470x/radio-si470x-common.c + * + * Driver for radios with Silicon Labs Si470x FM Radio Receivers + * + * Copyright (c) 2009 Tobias Lorenz + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +/* + * History: + * 2008-01-12 Tobias Lorenz + * Version 1.0.0 + * - First working version + * 2008-01-13 Tobias Lorenz + * Version 1.0.1 + * - Improved error handling, every function now returns errno + * - Improved multi user access (start/mute/stop) + * - Channel doesn't get lost anymore after start/mute/stop + * - RDS support added (polling mode via interrupt EP 1) + * - marked default module parameters with *value* + * - switched from bit structs to bit masks + * - header file cleaned and integrated + * 2008-01-14 Tobias Lorenz + * Version 1.0.2 + * - hex values are now lower case + * - commented USB ID for ADS/Tech moved on todo list + * - blacklisted si470x in hid-quirks.c + * - rds buffer handling functions integrated into *_work, *_read + * - rds_command in si470x_poll exchanged against simple retval + * - check for firmware version 15 + * - code order and prototypes still remain the same + * - spacing and bottom of band codes remain the same + * 2008-01-16 Tobias Lorenz + * Version 1.0.3 + * - code reordered to avoid function prototypes + * - switch/case defaults are now more user-friendly + * - unified comment style + * - applied all checkpatch.pl v1.12 suggestions + * except the warning about the too long lines with bit comments + * - renamed FMRADIO to RADIO to cut line length (checkpatch.pl) + * 2008-01-22 Tobias Lorenz + * Version 1.0.4 + * - avoid poss. locking when doing copy_to_user which may sleep + * - RDS is automatically activated on read now + * - code cleaned of unnecessary rds_commands + * - USB Vendor/Product ID for ADS/Tech FM Radio Receiver verified + * (thanks to Guillaume RAMOUSSE) + * 2008-01-27 Tobias Lorenz + * Version 1.0.5 + * - number of seek_retries changed to tune_timeout + * - fixed problem with incomplete tune operations by own buffers + * - optimization of variables and printf types + * - improved error logging + * 2008-01-31 Tobias Lorenz + * Oliver Neukum + * Version 1.0.6 + * - fixed coverity checker warnings in *_usb_driver_disconnect + * - probe()/open() race by correct ordering in probe() + * - DMA coherency rules by separate allocation of all buffers + * - use of endianness macros + * - abuse of spinlock, replaced by mutex + * - racy handling of timer in disconnect, + * replaced by delayed_work + * - racy interruptible_sleep_on(), + * replaced with wait_event_interruptible() + * - handle signals in read() + * 2008-02-08 Tobias Lorenz + * Oliver Neukum + * Version 1.0.7 + * - usb autosuspend support + * - unplugging fixed + * 2008-05-07 Tobias Lorenz + * Version 1.0.8 + * - hardware frequency seek support + * - afc indication + * - more safety checks, let si470x_get_freq return errno + * - vidioc behavior corrected according to v4l2 spec + * 2008-10-20 Alexey Klimov + * - add support for KWorld USB FM Radio FM700 + * - blacklisted KWorld radio in hid-core.c and hid-ids.h + * 2008-12-03 Mark Lord + * - add support for DealExtreme USB Radio + * 2009-01-31 Bob Ross + * - correction of stereo detection/setting + * - correction of signal strength indicator scaling + * 2009-01-31 Rick Bronson + * Tobias Lorenz + * - add LED status output + * - get HW/SW version from scratchpad + * 2009-06-16 Edouard Lafargue + * Version 1.0.10 + * - add support for interrupt mode for RDS endpoint, + * instead of polling. + * Improves RDS reception significantly + */ + + +/* kernel includes */ +#include "radio-si470x.h" + + + +/************************************************************************** + * Module Parameters + **************************************************************************/ + +/* Spacing (kHz) */ +/* 0: 200 kHz (USA, Australia) */ +/* 1: 100 kHz (Europe, Japan) */ +/* 2: 50 kHz */ +static unsigned short space = 2; +module_param(space, ushort, 0444); +MODULE_PARM_DESC(space, "Spacing: 0=200kHz 1=100kHz *2=50kHz*"); + +/* Bottom of Band (MHz) */ +/* 0: 87.5 - 108 MHz (USA, Europe)*/ +/* 1: 76 - 108 MHz (Japan wide band) */ +/* 2: 76 - 90 MHz (Japan) */ +static unsigned short band = 1; +module_param(band, ushort, 0444); +MODULE_PARM_DESC(band, "Band: 0=87.5..108MHz *1=76..108MHz* 2=76..90MHz"); + +/* De-emphasis */ +/* 0: 75 us (USA) */ +/* 1: 50 us (Europe, Australia, Japan) */ +static unsigned short de = 1; +module_param(de, ushort, 0444); +MODULE_PARM_DESC(de, "De-emphasis: 0=75us *1=50us*"); + +/* Tune timeout */ +static unsigned int tune_timeout = 3000; +module_param(tune_timeout, uint, 0644); +MODULE_PARM_DESC(tune_timeout, "Tune timeout: *3000*"); + +/* Seek timeout */ +static unsigned int seek_timeout = 5000; +module_param(seek_timeout, uint, 0644); +MODULE_PARM_DESC(seek_timeout, "Seek timeout: *5000*"); + + + +/************************************************************************** + * Generic Functions + **************************************************************************/ + +/* + * si470x_set_chan - set the channel + */ +static int si470x_set_chan(struct si470x_device *radio, unsigned short chan) +{ + int retval; + unsigned long timeout; + bool timed_out = 0; + + /* start tuning */ + radio->registers[CHANNEL] &= ~CHANNEL_CHAN; + radio->registers[CHANNEL] |= CHANNEL_TUNE | chan; + retval = si470x_set_register(radio, CHANNEL); + if (retval < 0) + goto done; + + /* wait till tune operation has completed */ + timeout = jiffies + msecs_to_jiffies(tune_timeout); + do { + retval = si470x_get_register(radio, STATUSRSSI); + if (retval < 0) + goto stop; + timed_out = time_after(jiffies, timeout); + } while (((radio->registers[STATUSRSSI] & STATUSRSSI_STC) == 0) && + (!timed_out)); + if ((radio->registers[STATUSRSSI] & STATUSRSSI_STC) == 0) + printk(KERN_WARNING DRIVER_NAME ": tune does not complete\n"); + if (timed_out) + printk(KERN_WARNING DRIVER_NAME + ": tune timed out after %u ms\n", tune_timeout); + +stop: + /* stop tuning */ + radio->registers[CHANNEL] &= ~CHANNEL_TUNE; + retval = si470x_set_register(radio, CHANNEL); + +done: + return retval; +} + + +/* + * si470x_get_freq - get the frequency + */ +static int si470x_get_freq(struct si470x_device *radio, unsigned int *freq) +{ + unsigned int spacing, band_bottom; + unsigned short chan; + int retval; + + /* Spacing (kHz) */ + switch ((radio->registers[SYSCONFIG2] & SYSCONFIG2_SPACE) >> 4) { + /* 0: 200 kHz (USA, Australia) */ + case 0: + spacing = 0.200 * FREQ_MUL; break; + /* 1: 100 kHz (Europe, Japan) */ + case 1: + spacing = 0.100 * FREQ_MUL; break; + /* 2: 50 kHz */ + default: + spacing = 0.050 * FREQ_MUL; break; + }; + + /* Bottom of Band (MHz) */ + switch ((radio->registers[SYSCONFIG2] & SYSCONFIG2_BAND) >> 6) { + /* 0: 87.5 - 108 MHz (USA, Europe) */ + case 0: + band_bottom = 87.5 * FREQ_MUL; break; + /* 1: 76 - 108 MHz (Japan wide band) */ + default: + band_bottom = 76 * FREQ_MUL; break; + /* 2: 76 - 90 MHz (Japan) */ + case 2: + band_bottom = 76 * FREQ_MUL; break; + }; + + /* read channel */ + retval = si470x_get_register(radio, READCHAN); + chan = radio->registers[READCHAN] & READCHAN_READCHAN; + + /* Frequency (MHz) = Spacing (kHz) x Channel + Bottom of Band (MHz) */ + *freq = chan * spacing + band_bottom; + + return retval; +} + + +/* + * si470x_set_freq - set the frequency + */ +int si470x_set_freq(struct si470x_device *radio, unsigned int freq) +{ + unsigned int spacing, band_bottom; + unsigned short chan; + + /* Spacing (kHz) */ + switch ((radio->registers[SYSCONFIG2] & SYSCONFIG2_SPACE) >> 4) { + /* 0: 200 kHz (USA, Australia) */ + case 0: + spacing = 0.200 * FREQ_MUL; break; + /* 1: 100 kHz (Europe, Japan) */ + case 1: + spacing = 0.100 * FREQ_MUL; break; + /* 2: 50 kHz */ + default: + spacing = 0.050 * FREQ_MUL; break; + }; + + /* Bottom of Band (MHz) */ + switch ((radio->registers[SYSCONFIG2] & SYSCONFIG2_BAND) >> 6) { + /* 0: 87.5 - 108 MHz (USA, Europe) */ + case 0: + band_bottom = 87.5 * FREQ_MUL; break; + /* 1: 76 - 108 MHz (Japan wide band) */ + default: + band_bottom = 76 * FREQ_MUL; break; + /* 2: 76 - 90 MHz (Japan) */ + case 2: + band_bottom = 76 * FREQ_MUL; break; + }; + + /* Chan = [ Freq (Mhz) - Bottom of Band (MHz) ] / Spacing (kHz) */ + chan = (freq - band_bottom) / spacing; + + return si470x_set_chan(radio, chan); +} + + +/* + * si470x_set_seek - set seek + */ +static int si470x_set_seek(struct si470x_device *radio, + unsigned int wrap_around, unsigned int seek_upward) +{ + int retval = 0; + unsigned long timeout; + bool timed_out = 0; + + /* start seeking */ + radio->registers[POWERCFG] |= POWERCFG_SEEK; + if (wrap_around == 1) + radio->registers[POWERCFG] &= ~POWERCFG_SKMODE; + else + radio->registers[POWERCFG] |= POWERCFG_SKMODE; + if (seek_upward == 1) + radio->registers[POWERCFG] |= POWERCFG_SEEKUP; + else + radio->registers[POWERCFG] &= ~POWERCFG_SEEKUP; + retval = si470x_set_register(radio, POWERCFG); + if (retval < 0) + goto done; + + /* wait till seek operation has completed */ + timeout = jiffies + msecs_to_jiffies(seek_timeout); + do { + retval = si470x_get_register(radio, STATUSRSSI); + if (retval < 0) + goto stop; + timed_out = time_after(jiffies, timeout); + } while (((radio->registers[STATUSRSSI] & STATUSRSSI_STC) == 0) && + (!timed_out)); + if ((radio->registers[STATUSRSSI] & STATUSRSSI_STC) == 0) + printk(KERN_WARNING DRIVER_NAME ": seek does not complete\n"); + if (radio->registers[STATUSRSSI] & STATUSRSSI_SF) + printk(KERN_WARNING DRIVER_NAME + ": seek failed / band limit reached\n"); + if (timed_out) + printk(KERN_WARNING DRIVER_NAME + ": seek timed out after %u ms\n", seek_timeout); + +stop: + /* stop seeking */ + radio->registers[POWERCFG] &= ~POWERCFG_SEEK; + retval = si470x_set_register(radio, POWERCFG); + +done: + /* try again, if timed out */ + if ((retval == 0) && timed_out) + retval = -EAGAIN; + + return retval; +} + + +/* + * si470x_start - switch on radio + */ +int si470x_start(struct si470x_device *radio) +{ + int retval; + + /* powercfg */ + radio->registers[POWERCFG] = + POWERCFG_DMUTE | POWERCFG_ENABLE | POWERCFG_RDSM; + retval = si470x_set_register(radio, POWERCFG); + if (retval < 0) + goto done; + + /* sysconfig 1 */ + radio->registers[SYSCONFIG1] = SYSCONFIG1_DE; + retval = si470x_set_register(radio, SYSCONFIG1); + if (retval < 0) + goto done; + + /* sysconfig 2 */ + radio->registers[SYSCONFIG2] = + (0x3f << 8) | /* SEEKTH */ + ((band << 6) & SYSCONFIG2_BAND) | /* BAND */ + ((space << 4) & SYSCONFIG2_SPACE) | /* SPACE */ + 15; /* VOLUME (max) */ + retval = si470x_set_register(radio, SYSCONFIG2); + if (retval < 0) + goto done; + + /* reset last channel */ + retval = si470x_set_chan(radio, + radio->registers[CHANNEL] & CHANNEL_CHAN); + +done: + return retval; +} + + +/* + * si470x_stop - switch off radio + */ +int si470x_stop(struct si470x_device *radio) +{ + int retval; + + /* sysconfig 1 */ + radio->registers[SYSCONFIG1] &= ~SYSCONFIG1_RDS; + retval = si470x_set_register(radio, SYSCONFIG1); + if (retval < 0) + goto done; + + /* powercfg */ + radio->registers[POWERCFG] &= ~POWERCFG_DMUTE; + /* POWERCFG_ENABLE has to automatically go low */ + radio->registers[POWERCFG] |= POWERCFG_ENABLE | POWERCFG_DISABLE; + retval = si470x_set_register(radio, POWERCFG); + +done: + return retval; +} + + +/* + * si470x_rds_on - switch on rds reception + */ +int si470x_rds_on(struct si470x_device *radio) +{ + int retval; + + /* sysconfig 1 */ + mutex_lock(&radio->lock); + radio->registers[SYSCONFIG1] |= SYSCONFIG1_RDS; + retval = si470x_set_register(radio, SYSCONFIG1); + if (retval < 0) + radio->registers[SYSCONFIG1] &= ~SYSCONFIG1_RDS; + mutex_unlock(&radio->lock); + + return retval; +} + + + +/************************************************************************** + * Video4Linux Interface + **************************************************************************/ + +/* + * si470x_vidioc_queryctrl - enumerate control items + */ +static int si470x_vidioc_queryctrl(struct file *file, void *priv, + struct v4l2_queryctrl *qc) +{ + int retval = -EINVAL; + + /* abort if qc->id is below V4L2_CID_BASE */ + if (qc->id < V4L2_CID_BASE) + goto done; + + /* search video control */ + switch (qc->id) { + case V4L2_CID_AUDIO_VOLUME: + return v4l2_ctrl_query_fill(qc, 0, 15, 1, 15); + case V4L2_CID_AUDIO_MUTE: + return v4l2_ctrl_query_fill(qc, 0, 1, 1, 1); + } + + /* disable unsupported base controls */ + /* to satisfy kradio and such apps */ + if ((retval == -EINVAL) && (qc->id < V4L2_CID_LASTP1)) { + qc->flags = V4L2_CTRL_FLAG_DISABLED; + retval = 0; + } + +done: + if (retval < 0) + printk(KERN_WARNING DRIVER_NAME + ": query controls failed with %d\n", retval); + return retval; +} + + +/* + * si470x_vidioc_g_ctrl - get the value of a control + */ +static int si470x_vidioc_g_ctrl(struct file *file, void *priv, + struct v4l2_control *ctrl) +{ + struct si470x_device *radio = video_drvdata(file); + int retval = 0; + + /* safety checks */ + if (radio->disconnected) { + retval = -EIO; + goto done; + } + + switch (ctrl->id) { + case V4L2_CID_AUDIO_VOLUME: + ctrl->value = radio->registers[SYSCONFIG2] & + SYSCONFIG2_VOLUME; + break; + case V4L2_CID_AUDIO_MUTE: + ctrl->value = ((radio->registers[POWERCFG] & + POWERCFG_DMUTE) == 0) ? 1 : 0; + break; + default: + retval = -EINVAL; + } + +done: + if (retval < 0) + printk(KERN_WARNING DRIVER_NAME + ": get control failed with %d\n", retval); + return retval; +} + + +/* + * si470x_vidioc_s_ctrl - set the value of a control + */ +static int si470x_vidioc_s_ctrl(struct file *file, void *priv, + struct v4l2_control *ctrl) +{ + struct si470x_device *radio = video_drvdata(file); + int retval = 0; + + /* safety checks */ + if (radio->disconnected) { + retval = -EIO; + goto done; + } + + switch (ctrl->id) { + case V4L2_CID_AUDIO_VOLUME: + radio->registers[SYSCONFIG2] &= ~SYSCONFIG2_VOLUME; + radio->registers[SYSCONFIG2] |= ctrl->value; + retval = si470x_set_register(radio, SYSCONFIG2); + break; + case V4L2_CID_AUDIO_MUTE: + if (ctrl->value == 1) + radio->registers[POWERCFG] &= ~POWERCFG_DMUTE; + else + radio->registers[POWERCFG] |= POWERCFG_DMUTE; + retval = si470x_set_register(radio, POWERCFG); + break; + default: + retval = -EINVAL; + } + +done: + if (retval < 0) + printk(KERN_WARNING DRIVER_NAME + ": set control failed with %d\n", retval); + return retval; +} + + +/* + * si470x_vidioc_g_audio - get audio attributes + */ +static int si470x_vidioc_g_audio(struct file *file, void *priv, + struct v4l2_audio *audio) +{ + /* driver constants */ + audio->index = 0; + strcpy(audio->name, "Radio"); + audio->capability = V4L2_AUDCAP_STEREO; + audio->mode = 0; + + return 0; +} + + +/* + * si470x_vidioc_g_tuner - get tuner attributes + */ +static int si470x_vidioc_g_tuner(struct file *file, void *priv, + struct v4l2_tuner *tuner) +{ + struct si470x_device *radio = video_drvdata(file); + int retval = 0; + + /* safety checks */ + if (radio->disconnected) { + retval = -EIO; + goto done; + } + if (tuner->index != 0) { + retval = -EINVAL; + goto done; + } + + retval = si470x_get_register(radio, STATUSRSSI); + if (retval < 0) + goto done; + + /* driver constants */ + strcpy(tuner->name, "FM"); + tuner->type = V4L2_TUNER_RADIO; + tuner->capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO | + V4L2_TUNER_CAP_RDS; + + /* range limits */ + switch ((radio->registers[SYSCONFIG2] & SYSCONFIG2_BAND) >> 6) { + /* 0: 87.5 - 108 MHz (USA, Europe, default) */ + default: + tuner->rangelow = 87.5 * FREQ_MUL; + tuner->rangehigh = 108 * FREQ_MUL; + break; + /* 1: 76 - 108 MHz (Japan wide band) */ + case 1: + tuner->rangelow = 76 * FREQ_MUL; + tuner->rangehigh = 108 * FREQ_MUL; + break; + /* 2: 76 - 90 MHz (Japan) */ + case 2: + tuner->rangelow = 76 * FREQ_MUL; + tuner->rangehigh = 90 * FREQ_MUL; + break; + }; + + /* stereo indicator == stereo (instead of mono) */ + if ((radio->registers[STATUSRSSI] & STATUSRSSI_ST) == 0) + tuner->rxsubchans = V4L2_TUNER_SUB_MONO; + else + tuner->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO; + /* If there is a reliable method of detecting an RDS channel, + then this code should check for that before setting this + RDS subchannel. */ + tuner->rxsubchans |= V4L2_TUNER_SUB_RDS; + + /* mono/stereo selector */ + if ((radio->registers[POWERCFG] & POWERCFG_MONO) == 0) + tuner->audmode = V4L2_TUNER_MODE_STEREO; + else + tuner->audmode = V4L2_TUNER_MODE_MONO; + + /* min is worst, max is best; signal:0..0xffff; rssi: 0..0xff */ + /* measured in units of db쨉V in 1 db increments (max at ~75 db쨉V) */ + tuner->signal = (radio->registers[STATUSRSSI] & STATUSRSSI_RSSI); + /* the ideal factor is 0xffff/75 = 873,8 */ + tuner->signal = (tuner->signal * 873) + (8 * tuner->signal / 10); + + /* automatic frequency control: -1: freq to low, 1 freq to high */ + /* AFCRL does only indicate that freq. differs, not if too low/high */ + tuner->afc = (radio->registers[STATUSRSSI] & STATUSRSSI_AFCRL) ? 1 : 0; + +done: + if (retval < 0) + printk(KERN_WARNING DRIVER_NAME + ": get tuner failed with %d\n", retval); + return retval; +} + + +/* + * si470x_vidioc_s_tuner - set tuner attributes + */ +static int si470x_vidioc_s_tuner(struct file *file, void *priv, + struct v4l2_tuner *tuner) +{ + struct si470x_device *radio = video_drvdata(file); + int retval = -EINVAL; + + /* safety checks */ + if (radio->disconnected) { + retval = -EIO; + goto done; + } + if (tuner->index != 0) + goto done; + + /* mono/stereo selector */ + switch (tuner->audmode) { + case V4L2_TUNER_MODE_MONO: + radio->registers[POWERCFG] |= POWERCFG_MONO; /* force mono */ + break; + case V4L2_TUNER_MODE_STEREO: + radio->registers[POWERCFG] &= ~POWERCFG_MONO; /* try stereo */ + break; + default: + goto done; + } + + retval = si470x_set_register(radio, POWERCFG); + +done: + if (retval < 0) + printk(KERN_WARNING DRIVER_NAME + ": set tuner failed with %d\n", retval); + return retval; +} + + +/* + * si470x_vidioc_g_frequency - get tuner or modulator radio frequency + */ +static int si470x_vidioc_g_frequency(struct file *file, void *priv, + struct v4l2_frequency *freq) +{ + struct si470x_device *radio = video_drvdata(file); + int retval = 0; + + /* safety checks */ + if (radio->disconnected) { + retval = -EIO; + goto done; + } + if (freq->tuner != 0) { + retval = -EINVAL; + goto done; + } + + freq->type = V4L2_TUNER_RADIO; + retval = si470x_get_freq(radio, &freq->frequency); + +done: + if (retval < 0) + printk(KERN_WARNING DRIVER_NAME + ": get frequency failed with %d\n", retval); + return retval; +} + + +/* + * si470x_vidioc_s_frequency - set tuner or modulator radio frequency + */ +static int si470x_vidioc_s_frequency(struct file *file, void *priv, + struct v4l2_frequency *freq) +{ + struct si470x_device *radio = video_drvdata(file); + int retval = 0; + + /* safety checks */ + if (radio->disconnected) { + retval = -EIO; + goto done; + } + if (freq->tuner != 0) { + retval = -EINVAL; + goto done; + } + + retval = si470x_set_freq(radio, freq->frequency); + +done: + if (retval < 0) + printk(KERN_WARNING DRIVER_NAME + ": set frequency failed with %d\n", retval); + return retval; +} + + +/* + * si470x_vidioc_s_hw_freq_seek - set hardware frequency seek + */ +static int si470x_vidioc_s_hw_freq_seek(struct file *file, void *priv, + struct v4l2_hw_freq_seek *seek) +{ + struct si470x_device *radio = video_drvdata(file); + int retval = 0; + + /* safety checks */ + if (radio->disconnected) { + retval = -EIO; + goto done; + } + if (seek->tuner != 0) { + retval = -EINVAL; + goto done; + } + + retval = si470x_set_seek(radio, seek->wrap_around, seek->seek_upward); + +done: + if (retval < 0) + printk(KERN_WARNING DRIVER_NAME + ": set hardware frequency seek failed with %d\n", + retval); + return retval; +} + + +/* + * si470x_ioctl_ops - video device ioctl operations + */ +static const struct v4l2_ioctl_ops si470x_ioctl_ops = { + .vidioc_querycap = si470x_vidioc_querycap, + .vidioc_queryctrl = si470x_vidioc_queryctrl, + .vidioc_g_ctrl = si470x_vidioc_g_ctrl, + .vidioc_s_ctrl = si470x_vidioc_s_ctrl, + .vidioc_g_audio = si470x_vidioc_g_audio, + .vidioc_g_tuner = si470x_vidioc_g_tuner, + .vidioc_s_tuner = si470x_vidioc_s_tuner, + .vidioc_g_frequency = si470x_vidioc_g_frequency, + .vidioc_s_frequency = si470x_vidioc_s_frequency, + .vidioc_s_hw_freq_seek = si470x_vidioc_s_hw_freq_seek, +}; + + +/* + * si470x_viddev_template - video device interface + */ +struct video_device si470x_viddev_template = { + .fops = &si470x_fops, + .name = DRIVER_NAME, + .release = video_device_release, + .ioctl_ops = &si470x_ioctl_ops, +}; diff --git a/linux/drivers/media/radio/si470x/radio-si470x-usb.c b/linux/drivers/media/radio/si470x/radio-si470x-usb.c new file mode 100644 index 000000000..f3d805f70 --- /dev/null +++ b/linux/drivers/media/radio/si470x/radio-si470x-usb.c @@ -0,0 +1,958 @@ +/* + * drivers/media/radio/si470x/radio-si470x-usb.c + * + * USB driver for radios with Silicon Labs Si470x FM Radio Receivers + * + * Copyright (c) 2009 Tobias Lorenz + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +/* + * ToDo: + * - add firmware download/update support + */ + + +/* driver definitions */ +#define DRIVER_AUTHOR "Tobias Lorenz " +#define DRIVER_KERNEL_VERSION KERNEL_VERSION(1, 0, 10) +#define DRIVER_CARD "Silicon Labs Si470x FM Radio Receiver" +#define DRIVER_DESC "USB radio driver for Si470x FM Radio Receivers" +#define DRIVER_VERSION "1.0.10" + +/* kernel includes */ +#include +#include + +#include "radio-si470x.h" + + +/* USB Device ID List */ +static struct usb_device_id si470x_usb_driver_id_table[] = { + /* Silicon Labs USB FM Radio Reference Design */ + { USB_DEVICE_AND_INTERFACE_INFO(0x10c4, 0x818a, USB_CLASS_HID, 0, 0) }, + /* ADS/Tech FM Radio Receiver (formerly Instant FM Music) */ + { USB_DEVICE_AND_INTERFACE_INFO(0x06e1, 0xa155, USB_CLASS_HID, 0, 0) }, + /* KWorld USB FM Radio SnapMusic Mobile 700 (FM700) */ + { USB_DEVICE_AND_INTERFACE_INFO(0x1b80, 0xd700, USB_CLASS_HID, 0, 0) }, + /* Sanei Electric, Inc. FM USB Radio (sold as DealExtreme.com PCear) */ + { USB_DEVICE_AND_INTERFACE_INFO(0x10c5, 0x819a, USB_CLASS_HID, 0, 0) }, + /* Terminating entry */ + { } +}; +MODULE_DEVICE_TABLE(usb, si470x_usb_driver_id_table); + + + +/************************************************************************** + * Module Parameters + **************************************************************************/ + +/* Radio Nr */ +static int radio_nr = -1; +module_param(radio_nr, int, 0444); +MODULE_PARM_DESC(radio_nr, "Radio Nr"); + +/* USB timeout */ +static unsigned int usb_timeout = 500; +module_param(usb_timeout, uint, 0644); +MODULE_PARM_DESC(usb_timeout, "USB timeout (ms): *500*"); + +/* RDS buffer blocks */ +static unsigned int rds_buf = 100; +module_param(rds_buf, uint, 0444); +MODULE_PARM_DESC(rds_buf, "RDS buffer entries: *100*"); + +/* RDS maximum block errors */ +static unsigned short max_rds_errors = 1; +/* 0 means 0 errors requiring correction */ +/* 1 means 1-2 errors requiring correction (used by original USBRadio.exe) */ +/* 2 means 3-5 errors requiring correction */ +/* 3 means 6+ errors or errors in checkword, correction not possible */ +module_param(max_rds_errors, ushort, 0644); +MODULE_PARM_DESC(max_rds_errors, "RDS maximum block errors: *1*"); + + + +/************************************************************************** + * USB HID Reports + **************************************************************************/ + +/* Reports 1-16 give direct read/write access to the 16 Si470x registers */ +/* with the (REPORT_ID - 1) corresponding to the register address across USB */ +/* endpoint 0 using GET_REPORT and SET_REPORT */ +#define REGISTER_REPORT_SIZE (RADIO_REGISTER_SIZE + 1) +#define REGISTER_REPORT(reg) ((reg) + 1) + +/* Report 17 gives direct read/write access to the entire Si470x register */ +/* map across endpoint 0 using GET_REPORT and SET_REPORT */ +#define ENTIRE_REPORT_SIZE (RADIO_REGISTER_NUM * RADIO_REGISTER_SIZE + 1) +#define ENTIRE_REPORT 17 + +/* Report 18 is used to send the lowest 6 Si470x registers up the HID */ +/* interrupt endpoint 1 to Windows every 20 milliseconds for status */ +#define RDS_REPORT_SIZE (RDS_REGISTER_NUM * RADIO_REGISTER_SIZE + 1) +#define RDS_REPORT 18 + +/* Report 19: LED state */ +#define LED_REPORT_SIZE 3 +#define LED_REPORT 19 + +/* Report 19: stream */ +#define STREAM_REPORT_SIZE 3 +#define STREAM_REPORT 19 + +/* Report 20: scratch */ +#define SCRATCH_PAGE_SIZE 63 +#define SCRATCH_REPORT_SIZE (SCRATCH_PAGE_SIZE + 1) +#define SCRATCH_REPORT 20 + +/* Reports 19-22: flash upgrade of the C8051F321 */ +#define WRITE_REPORT_SIZE 4 +#define WRITE_REPORT 19 +#define FLASH_REPORT_SIZE 64 +#define FLASH_REPORT 20 +#define CRC_REPORT_SIZE 3 +#define CRC_REPORT 21 +#define RESPONSE_REPORT_SIZE 2 +#define RESPONSE_REPORT 22 + +/* Report 23: currently unused, but can accept 60 byte reports on the HID */ +/* interrupt out endpoint 2 every 1 millisecond */ +#define UNUSED_REPORT 23 + + + +/************************************************************************** + * Software/Hardware Versions + **************************************************************************/ +#define RADIO_SW_VERSION_NOT_BOOTLOADABLE 6 +#define RADIO_SW_VERSION 7 +#define RADIO_SW_VERSION_CURRENT 15 +#define RADIO_HW_VERSION 1 + +#define SCRATCH_PAGE_SW_VERSION 1 +#define SCRATCH_PAGE_HW_VERSION 2 + + + +/************************************************************************** + * LED State Definitions + **************************************************************************/ +#define LED_COMMAND 0x35 + +#define NO_CHANGE_LED 0x00 +#define ALL_COLOR_LED 0x01 /* streaming state */ +#define BLINK_GREEN_LED 0x02 /* connect state */ +#define BLINK_RED_LED 0x04 +#define BLINK_ORANGE_LED 0x10 /* disconnect state */ +#define SOLID_GREEN_LED 0x20 /* tuning/seeking state */ +#define SOLID_RED_LED 0x40 /* bootload state */ +#define SOLID_ORANGE_LED 0x80 + + + +/************************************************************************** + * Stream State Definitions + **************************************************************************/ +#define STREAM_COMMAND 0x36 +#define STREAM_VIDPID 0x00 +#define STREAM_AUDIO 0xff + + + +/************************************************************************** + * Bootloader / Flash Commands + **************************************************************************/ + +/* unique id sent to bootloader and required to put into a bootload state */ +#define UNIQUE_BL_ID 0x34 + +/* mask for the flash data */ +#define FLASH_DATA_MASK 0x55 + +/* bootloader commands */ +#define GET_SW_VERSION_COMMAND 0x00 +#define SET_PAGE_COMMAND 0x01 +#define ERASE_PAGE_COMMAND 0x02 +#define WRITE_PAGE_COMMAND 0x03 +#define CRC_ON_PAGE_COMMAND 0x04 +#define READ_FLASH_BYTE_COMMAND 0x05 +#define RESET_DEVICE_COMMAND 0x06 +#define GET_HW_VERSION_COMMAND 0x07 +#define BLANK 0xff + +/* bootloader command responses */ +#define COMMAND_OK 0x01 +#define COMMAND_FAILED 0x02 +#define COMMAND_PENDING 0x03 + + + +/************************************************************************** + * General Driver Functions - REGISTER_REPORTs + **************************************************************************/ + +/* + * si470x_get_report - receive a HID report + */ +static int si470x_get_report(struct si470x_device *radio, void *buf, int size) +{ + unsigned char *report = (unsigned char *) buf; + int retval; + + retval = usb_control_msg(radio->usbdev, + usb_rcvctrlpipe(radio->usbdev, 0), + HID_REQ_GET_REPORT, + USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN, + report[0], 2, + buf, size, usb_timeout); + + if (retval < 0) + printk(KERN_WARNING DRIVER_NAME + ": si470x_get_report: usb_control_msg returned %d\n", + retval); + return retval; +} + + +/* + * si470x_set_report - send a HID report + */ +static int si470x_set_report(struct si470x_device *radio, void *buf, int size) +{ + unsigned char *report = (unsigned char *) buf; + int retval; + + retval = usb_control_msg(radio->usbdev, + usb_sndctrlpipe(radio->usbdev, 0), + HID_REQ_SET_REPORT, + USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT, + report[0], 2, + buf, size, usb_timeout); + + if (retval < 0) + printk(KERN_WARNING DRIVER_NAME + ": si470x_set_report: usb_control_msg returned %d\n", + retval); + return retval; +} + + +/* + * si470x_get_register - read register + */ +int si470x_get_register(struct si470x_device *radio, int regnr) +{ + unsigned char buf[REGISTER_REPORT_SIZE]; + int retval; + + buf[0] = REGISTER_REPORT(regnr); + + retval = si470x_get_report(radio, (void *) &buf, sizeof(buf)); + + if (retval >= 0) + radio->registers[regnr] = get_unaligned_be16(&buf[1]); + + return (retval < 0) ? -EINVAL : 0; +} + + +/* + * si470x_set_register - write register + */ +int si470x_set_register(struct si470x_device *radio, int regnr) +{ + unsigned char buf[REGISTER_REPORT_SIZE]; + int retval; + + buf[0] = REGISTER_REPORT(regnr); + put_unaligned_be16(radio->registers[regnr], &buf[1]); + + retval = si470x_set_report(radio, (void *) &buf, sizeof(buf)); + + return (retval < 0) ? -EINVAL : 0; +} + + + +/************************************************************************** + * General Driver Functions - ENTIRE_REPORT + **************************************************************************/ + +/* + * si470x_get_all_registers - read entire registers + */ +static int si470x_get_all_registers(struct si470x_device *radio) +{ + unsigned char buf[ENTIRE_REPORT_SIZE]; + int retval; + unsigned char regnr; + + buf[0] = ENTIRE_REPORT; + + retval = si470x_get_report(radio, (void *) &buf, sizeof(buf)); + + if (retval >= 0) + for (regnr = 0; regnr < RADIO_REGISTER_NUM; regnr++) + radio->registers[regnr] = get_unaligned_be16( + &buf[regnr * RADIO_REGISTER_SIZE + 1]); + + return (retval < 0) ? -EINVAL : 0; +} + + + +/************************************************************************** + * General Driver Functions - LED_REPORT + **************************************************************************/ + +/* + * si470x_set_led_state - sets the led state + */ +static int si470x_set_led_state(struct si470x_device *radio, + unsigned char led_state) +{ + unsigned char buf[LED_REPORT_SIZE]; + int retval; + + buf[0] = LED_REPORT; + buf[1] = LED_COMMAND; + buf[2] = led_state; + + retval = si470x_set_report(radio, (void *) &buf, sizeof(buf)); + + return (retval < 0) ? -EINVAL : 0; +} + + + +/************************************************************************** + * General Driver Functions - SCRATCH_REPORT + **************************************************************************/ + +/* + * si470x_get_scratch_versions - gets the scratch page and version infos + */ +static int si470x_get_scratch_page_versions(struct si470x_device *radio) +{ + unsigned char buf[SCRATCH_REPORT_SIZE]; + int retval; + + buf[0] = SCRATCH_REPORT; + + retval = si470x_get_report(radio, (void *) &buf, sizeof(buf)); + + if (retval < 0) + printk(KERN_WARNING DRIVER_NAME ": si470x_get_scratch: " + "si470x_get_report returned %d\n", retval); + else { + radio->software_version = buf[1]; + radio->hardware_version = buf[2]; + } + + return (retval < 0) ? -EINVAL : 0; +} + + + +/************************************************************************** + * RDS Driver Functions + **************************************************************************/ + +/* + * si470x_int_in_callback - rds callback and processing function + * + * TODO: do we need to use mutex locks in some sections? + */ +static void si470x_int_in_callback(struct urb *urb) +{ + struct si470x_device *radio = urb->context; + unsigned char buf[RDS_REPORT_SIZE]; + int retval; + unsigned char regnr; + unsigned char blocknum; + unsigned short bler; /* rds block errors */ + unsigned short rds; + unsigned char tmpbuf[3]; + + if (urb->status) { + if (urb->status == -ENOENT || + urb->status == -ECONNRESET || + urb->status == -ESHUTDOWN) { + return; + } else { + printk(KERN_WARNING DRIVER_NAME + ": non-zero urb status (%d)\n", urb->status); + goto resubmit; /* Maybe we can recover. */ + } + } + + /* safety checks */ + if (radio->disconnected) + return; + if ((radio->registers[SYSCONFIG1] & SYSCONFIG1_RDS) == 0) + goto resubmit; + + if (urb->actual_length > 0) { + /* Update RDS registers with URB data */ + buf[0] = RDS_REPORT; + for (regnr = 0; regnr < RDS_REGISTER_NUM; regnr++) + radio->registers[STATUSRSSI + regnr] = + get_unaligned_be16(&radio->int_in_buffer[ + regnr * RADIO_REGISTER_SIZE + 1]); + /* get rds blocks */ + if ((radio->registers[STATUSRSSI] & STATUSRSSI_RDSR) == 0) { + /* No RDS group ready, better luck next time */ + goto resubmit; + } + if ((radio->registers[STATUSRSSI] & STATUSRSSI_RDSS) == 0) { + /* RDS decoder not synchronized */ + goto resubmit; + } + for (blocknum = 0; blocknum < 4; blocknum++) { + switch (blocknum) { + default: + bler = (radio->registers[STATUSRSSI] & + STATUSRSSI_BLERA) >> 9; + rds = radio->registers[RDSA]; + break; + case 1: + bler = (radio->registers[READCHAN] & + READCHAN_BLERB) >> 14; + rds = radio->registers[RDSB]; + break; + case 2: + bler = (radio->registers[READCHAN] & + READCHAN_BLERC) >> 12; + rds = radio->registers[RDSC]; + break; + case 3: + bler = (radio->registers[READCHAN] & + READCHAN_BLERD) >> 10; + rds = radio->registers[RDSD]; + break; + }; + + /* Fill the V4L2 RDS buffer */ + put_unaligned_le16(rds, &tmpbuf); + tmpbuf[2] = blocknum; /* offset name */ + tmpbuf[2] |= blocknum << 3; /* received offset */ + if (bler > max_rds_errors) + tmpbuf[2] |= 0x80; /* uncorrectable errors */ + else if (bler > 0) + tmpbuf[2] |= 0x40; /* corrected error(s) */ + + /* copy RDS block to internal buffer */ + memcpy(&radio->buffer[radio->wr_index], &tmpbuf, 3); + radio->wr_index += 3; + + /* wrap write pointer */ + if (radio->wr_index >= radio->buf_size) + radio->wr_index = 0; + + /* check for overflow */ + if (radio->wr_index == radio->rd_index) { + /* increment and wrap read pointer */ + radio->rd_index += 3; + if (radio->rd_index >= radio->buf_size) + radio->rd_index = 0; + } + } + if (radio->wr_index != radio->rd_index) + wake_up_interruptible(&radio->read_queue); + } + +resubmit: + /* Resubmit if we're still running. */ + if (radio->int_in_running && radio->usbdev) { + retval = usb_submit_urb(radio->int_in_urb, GFP_ATOMIC); + if (retval) { + printk(KERN_WARNING DRIVER_NAME + ": resubmitting urb failed (%d)", retval); + radio->int_in_running = 0; + } + } +} + + + +/************************************************************************** + * File Operations Interface + **************************************************************************/ + +/* + * si470x_fops_read - read RDS data + */ +static ssize_t si470x_fops_read(struct file *file, char __user *buf, + size_t count, loff_t *ppos) +{ + struct si470x_device *radio = video_drvdata(file); + int retval = 0; + unsigned int block_count = 0; + + /* switch on rds reception */ + if ((radio->registers[SYSCONFIG1] & SYSCONFIG1_RDS) == 0) + si470x_rds_on(radio); + + /* block if no new data available */ + while (radio->wr_index == radio->rd_index) { + if (file->f_flags & O_NONBLOCK) { + retval = -EWOULDBLOCK; + goto done; + } + if (wait_event_interruptible(radio->read_queue, + radio->wr_index != radio->rd_index) < 0) { + retval = -EINTR; + goto done; + } + } + + /* calculate block count from byte count */ + count /= 3; + + /* copy RDS block out of internal buffer and to user buffer */ + mutex_lock(&radio->lock); + while (block_count < count) { + if (radio->rd_index == radio->wr_index) + break; + + /* always transfer rds complete blocks */ + if (copy_to_user(buf, &radio->buffer[radio->rd_index], 3)) + /* retval = -EFAULT; */ + break; + + /* increment and wrap read pointer */ + radio->rd_index += 3; + if (radio->rd_index >= radio->buf_size) + radio->rd_index = 0; + + /* increment counters */ + block_count++; + buf += 3; + retval += 3; + } + mutex_unlock(&radio->lock); + +done: + return retval; +} + + +/* + * si470x_fops_poll - poll RDS data + */ +static unsigned int si470x_fops_poll(struct file *file, + struct poll_table_struct *pts) +{ + struct si470x_device *radio = video_drvdata(file); + int retval = 0; + + /* switch on rds reception */ + if ((radio->registers[SYSCONFIG1] & SYSCONFIG1_RDS) == 0) + si470x_rds_on(radio); + + poll_wait(file, &radio->read_queue, pts); + + if (radio->rd_index != radio->wr_index) + retval = POLLIN | POLLRDNORM; + + return retval; +} + + +/* + * si470x_fops_open - file open + */ +static int si470x_fops_open(struct file *file) +{ + struct si470x_device *radio = video_drvdata(file); + int retval; + + lock_kernel(); + radio->users++; + + retval = usb_autopm_get_interface(radio->intf); + if (retval < 0) { + radio->users--; + retval = -EIO; + goto done; + } + + if (radio->users == 1) { + /* start radio */ + retval = si470x_start(radio); + if (retval < 0) { + usb_autopm_put_interface(radio->intf); + goto done; + } + + /* initialize interrupt urb */ + usb_fill_int_urb(radio->int_in_urb, radio->usbdev, + usb_rcvintpipe(radio->usbdev, + radio->int_in_endpoint->bEndpointAddress), + radio->int_in_buffer, + le16_to_cpu(radio->int_in_endpoint->wMaxPacketSize), + si470x_int_in_callback, + radio, + radio->int_in_endpoint->bInterval); + + radio->int_in_running = 1; + mb(); + + retval = usb_submit_urb(radio->int_in_urb, GFP_KERNEL); + if (retval) { + printk(KERN_INFO DRIVER_NAME + ": submitting int urb failed (%d)\n", retval); + radio->int_in_running = 0; + usb_autopm_put_interface(radio->intf); + } + } + +done: + unlock_kernel(); + return retval; +} + + +/* + * si470x_fops_release - file release + */ +static int si470x_fops_release(struct file *file) +{ + struct si470x_device *radio = video_drvdata(file); + int retval = 0; + + /* safety check */ + if (!radio) { + retval = -ENODEV; + goto done; + } + + mutex_lock(&radio->disconnect_lock); + radio->users--; + if (radio->users == 0) { + /* shutdown interrupt handler */ + if (radio->int_in_running) { + radio->int_in_running = 0; + if (radio->int_in_urb) + usb_kill_urb(radio->int_in_urb); + } + + if (radio->disconnected) { + video_unregister_device(radio->videodev); + kfree(radio->int_in_buffer); + kfree(radio->buffer); + kfree(radio); + goto unlock; + } + + /* cancel read processes */ + wake_up_interruptible(&radio->read_queue); + + /* stop radio */ + retval = si470x_stop(radio); + usb_autopm_put_interface(radio->intf); + } +unlock: + mutex_unlock(&radio->disconnect_lock); +done: + return retval; +} + + +/* + * si470x_fops - file operations interface + */ +const struct v4l2_file_operations si470x_fops = { + .owner = THIS_MODULE, + .read = si470x_fops_read, + .poll = si470x_fops_poll, + .ioctl = video_ioctl2, + .open = si470x_fops_open, + .release = si470x_fops_release, +}; + + + +/************************************************************************** + * Video4Linux Interface + **************************************************************************/ + +/* + * si470x_vidioc_querycap - query device capabilities + */ +int si470x_vidioc_querycap(struct file *file, void *priv, + struct v4l2_capability *capability) +{ + struct si470x_device *radio = video_drvdata(file); + + strlcpy(capability->driver, DRIVER_NAME, sizeof(capability->driver)); + strlcpy(capability->card, DRIVER_CARD, sizeof(capability->card)); + usb_make_path(radio->usbdev, capability->bus_info, + sizeof(capability->bus_info)); + capability->version = DRIVER_KERNEL_VERSION; + capability->capabilities = V4L2_CAP_HW_FREQ_SEEK | + V4L2_CAP_TUNER | V4L2_CAP_RADIO | V4L2_CAP_RDS_CAPTURE; + + return 0; +} + + + +/************************************************************************** + * USB Interface + **************************************************************************/ + +/* + * si470x_usb_driver_probe - probe for the device + */ +static int si470x_usb_driver_probe(struct usb_interface *intf, + const struct usb_device_id *id) +{ + struct si470x_device *radio; + struct usb_host_interface *iface_desc; + struct usb_endpoint_descriptor *endpoint; + int i, int_end_size, retval = 0; + + /* private data allocation and initialization */ + radio = kzalloc(sizeof(struct si470x_device), GFP_KERNEL); + if (!radio) { + retval = -ENOMEM; + goto err_initial; + } + radio->users = 0; + radio->disconnected = 0; + radio->usbdev = interface_to_usbdev(intf); + radio->intf = intf; + mutex_init(&radio->disconnect_lock); + mutex_init(&radio->lock); + + iface_desc = intf->cur_altsetting; + + /* Set up interrupt endpoint information. */ + for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { + endpoint = &iface_desc->endpoint[i].desc; + if (((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == + USB_DIR_IN) && ((endpoint->bmAttributes & + USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT)) + radio->int_in_endpoint = endpoint; + } + if (!radio->int_in_endpoint) { + printk(KERN_INFO DRIVER_NAME + ": could not find interrupt in endpoint\n"); + retval = -EIO; + goto err_radio; + } + + int_end_size = le16_to_cpu(radio->int_in_endpoint->wMaxPacketSize); + + radio->int_in_buffer = kmalloc(int_end_size, GFP_KERNEL); + if (!radio->int_in_buffer) { + printk(KERN_INFO DRIVER_NAME + "could not allocate int_in_buffer"); + retval = -ENOMEM; + goto err_radio; + } + + radio->int_in_urb = usb_alloc_urb(0, GFP_KERNEL); + if (!radio->int_in_urb) { + printk(KERN_INFO DRIVER_NAME "could not allocate int_in_urb"); + retval = -ENOMEM; + goto err_intbuffer; + } + + /* video device allocation and initialization */ + radio->videodev = video_device_alloc(); + if (!radio->videodev) { + retval = -ENOMEM; + goto err_intbuffer; + } + memcpy(radio->videodev, &si470x_viddev_template, + sizeof(si470x_viddev_template)); + video_set_drvdata(radio->videodev, radio); + + /* show some infos about the specific si470x device */ + if (si470x_get_all_registers(radio) < 0) { + retval = -EIO; + goto err_video; + } + printk(KERN_INFO DRIVER_NAME ": DeviceID=0x%4.4hx ChipID=0x%4.4hx\n", + radio->registers[DEVICEID], radio->registers[CHIPID]); + + /* get software and hardware versions */ + if (si470x_get_scratch_page_versions(radio) < 0) { + retval = -EIO; + goto err_video; + } + printk(KERN_INFO DRIVER_NAME + ": software version %d, hardware version %d\n", + radio->software_version, radio->hardware_version); + + /* check if device and firmware is current */ + if ((radio->registers[CHIPID] & CHIPID_FIRMWARE) + < RADIO_SW_VERSION_CURRENT) { + printk(KERN_WARNING DRIVER_NAME + ": This driver is known to work with " + "firmware version %hu,\n", RADIO_SW_VERSION_CURRENT); + printk(KERN_WARNING DRIVER_NAME + ": but the device has firmware version %hu.\n", + radio->registers[CHIPID] & CHIPID_FIRMWARE); + printk(KERN_WARNING DRIVER_NAME + ": If you have some trouble using this driver,\n"); + printk(KERN_WARNING DRIVER_NAME + ": please report to V4L ML at " + "linux-media@vger.kernel.org\n"); + } + + /* set initial frequency */ + si470x_set_freq(radio, 87.5 * FREQ_MUL); /* available in all regions */ + + /* set led to connect state */ + si470x_set_led_state(radio, BLINK_GREEN_LED); + + /* rds buffer allocation */ + radio->buf_size = rds_buf * 3; + radio->buffer = kmalloc(radio->buf_size, GFP_KERNEL); + if (!radio->buffer) { + retval = -EIO; + goto err_video; + } + + /* rds buffer configuration */ + radio->wr_index = 0; + radio->rd_index = 0; + init_waitqueue_head(&radio->read_queue); + + /* register video device */ + retval = video_register_device(radio->videodev, VFL_TYPE_RADIO, + radio_nr); + if (retval) { + printk(KERN_WARNING DRIVER_NAME + ": Could not register video device\n"); + goto err_all; + } + usb_set_intfdata(intf, radio); + + return 0; +err_all: + kfree(radio->buffer); +err_video: + video_device_release(radio->videodev); +err_intbuffer: + kfree(radio->int_in_buffer); +err_radio: + kfree(radio); +err_initial: + return retval; +} + + +/* + * si470x_usb_driver_suspend - suspend the device + */ +static int si470x_usb_driver_suspend(struct usb_interface *intf, + pm_message_t message) +{ + printk(KERN_INFO DRIVER_NAME ": suspending now...\n"); + + return 0; +} + + +/* + * si470x_usb_driver_resume - resume the device + */ +static int si470x_usb_driver_resume(struct usb_interface *intf) +{ + printk(KERN_INFO DRIVER_NAME ": resuming now...\n"); + + return 0; +} + + +/* + * si470x_usb_driver_disconnect - disconnect the device + */ +static void si470x_usb_driver_disconnect(struct usb_interface *intf) +{ + struct si470x_device *radio = usb_get_intfdata(intf); + + mutex_lock(&radio->disconnect_lock); + radio->disconnected = 1; + usb_set_intfdata(intf, NULL); + if (radio->users == 0) { + /* set led to disconnect state */ + si470x_set_led_state(radio, BLINK_ORANGE_LED); + + /* Free data structures. */ + usb_free_urb(radio->int_in_urb); + + kfree(radio->int_in_buffer); + video_unregister_device(radio->videodev); + kfree(radio->buffer); + kfree(radio); + } + mutex_unlock(&radio->disconnect_lock); +} + + +/* + * si470x_usb_driver - usb driver interface + */ +static struct usb_driver si470x_usb_driver = { + .name = DRIVER_NAME, + .probe = si470x_usb_driver_probe, + .disconnect = si470x_usb_driver_disconnect, + .suspend = si470x_usb_driver_suspend, + .resume = si470x_usb_driver_resume, + .id_table = si470x_usb_driver_id_table, + .supports_autosuspend = 1, +}; + + + +/************************************************************************** + * Module Interface + **************************************************************************/ + +/* + * si470x_module_init - module init + */ +static int __init si470x_module_init(void) +{ + printk(KERN_INFO DRIVER_DESC ", Version " DRIVER_VERSION "\n"); + return usb_register(&si470x_usb_driver); +} + + +/* + * si470x_module_exit - module exit + */ +static void __exit si470x_module_exit(void) +{ + usb_deregister(&si470x_usb_driver); +} + + +module_init(si470x_module_init); +module_exit(si470x_module_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR(DRIVER_AUTHOR); +MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_VERSION(DRIVER_VERSION); diff --git a/linux/drivers/media/radio/si470x/radio-si470x.h b/linux/drivers/media/radio/si470x/radio-si470x.h new file mode 100644 index 000000000..88d3ebbe2 --- /dev/null +++ b/linux/drivers/media/radio/si470x/radio-si470x.h @@ -0,0 +1,202 @@ +/* + * drivers/media/radio/si470x/radio-si470x.h + * + * Driver for radios with Silicon Labs Si470x FM Radio Receivers + * + * Copyright (c) 2009 Tobias Lorenz + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +/* driver definitions */ +#define DRIVER_NAME "radio-si470x" + + +/* kernel includes */ +#include +#include +#include +#include +#include +#include +#include +#include "compat.h" +#include +#include +#include +#include +#include +#include + + +/************************************************************************** + * Register Definitions + **************************************************************************/ +#define RADIO_REGISTER_SIZE 2 /* 16 register bit width */ +#define RADIO_REGISTER_NUM 16 /* DEVICEID ... RDSD */ +#define RDS_REGISTER_NUM 6 /* STATUSRSSI ... RDSD */ + +#define DEVICEID 0 /* Device ID */ +#define DEVICEID_PN 0xf000 /* bits 15..12: Part Number */ +#define DEVICEID_MFGID 0x0fff /* bits 11..00: Manufacturer ID */ + +#define CHIPID 1 /* Chip ID */ +#define CHIPID_REV 0xfc00 /* bits 15..10: Chip Version */ +#define CHIPID_DEV 0x0200 /* bits 09..09: Device */ +#define CHIPID_FIRMWARE 0x01ff /* bits 08..00: Firmware Version */ + +#define POWERCFG 2 /* Power Configuration */ +#define POWERCFG_DSMUTE 0x8000 /* bits 15..15: Softmute Disable */ +#define POWERCFG_DMUTE 0x4000 /* bits 14..14: Mute Disable */ +#define POWERCFG_MONO 0x2000 /* bits 13..13: Mono Select */ +#define POWERCFG_RDSM 0x0800 /* bits 11..11: RDS Mode (Si4701 only) */ +#define POWERCFG_SKMODE 0x0400 /* bits 10..10: Seek Mode */ +#define POWERCFG_SEEKUP 0x0200 /* bits 09..09: Seek Direction */ +#define POWERCFG_SEEK 0x0100 /* bits 08..08: Seek */ +#define POWERCFG_DISABLE 0x0040 /* bits 06..06: Powerup Disable */ +#define POWERCFG_ENABLE 0x0001 /* bits 00..00: Powerup Enable */ + +#define CHANNEL 3 /* Channel */ +#define CHANNEL_TUNE 0x8000 /* bits 15..15: Tune */ +#define CHANNEL_CHAN 0x03ff /* bits 09..00: Channel Select */ + +#define SYSCONFIG1 4 /* System Configuration 1 */ +#define SYSCONFIG1_RDSIEN 0x8000 /* bits 15..15: RDS Interrupt Enable (Si4701 only) */ +#define SYSCONFIG1_STCIEN 0x4000 /* bits 14..14: Seek/Tune Complete Interrupt Enable */ +#define SYSCONFIG1_RDS 0x1000 /* bits 12..12: RDS Enable (Si4701 only) */ +#define SYSCONFIG1_DE 0x0800 /* bits 11..11: De-emphasis (0=75us 1=50us) */ +#define SYSCONFIG1_AGCD 0x0400 /* bits 10..10: AGC Disable */ +#define SYSCONFIG1_BLNDADJ 0x00c0 /* bits 07..06: Stereo/Mono Blend Level Adjustment */ +#define SYSCONFIG1_GPIO3 0x0030 /* bits 05..04: General Purpose I/O 3 */ +#define SYSCONFIG1_GPIO2 0x000c /* bits 03..02: General Purpose I/O 2 */ +#define SYSCONFIG1_GPIO1 0x0003 /* bits 01..00: General Purpose I/O 1 */ + +#define SYSCONFIG2 5 /* System Configuration 2 */ +#define SYSCONFIG2_SEEKTH 0xff00 /* bits 15..08: RSSI Seek Threshold */ +#define SYSCONFIG2_BAND 0x0080 /* bits 07..06: Band Select */ +#define SYSCONFIG2_SPACE 0x0030 /* bits 05..04: Channel Spacing */ +#define SYSCONFIG2_VOLUME 0x000f /* bits 03..00: Volume */ + +#define SYSCONFIG3 6 /* System Configuration 3 */ +#define SYSCONFIG3_SMUTER 0xc000 /* bits 15..14: Softmute Attack/Recover Rate */ +#define SYSCONFIG3_SMUTEA 0x3000 /* bits 13..12: Softmute Attenuation */ +#define SYSCONFIG3_SKSNR 0x00f0 /* bits 07..04: Seek SNR Threshold */ +#define SYSCONFIG3_SKCNT 0x000f /* bits 03..00: Seek FM Impulse Detection Threshold */ + +#define TEST1 7 /* Test 1 */ +#define TEST1_AHIZEN 0x4000 /* bits 14..14: Audio High-Z Enable */ + +#define TEST2 8 /* Test 2 */ +/* TEST2 only contains reserved bits */ + +#define BOOTCONFIG 9 /* Boot Configuration */ +/* BOOTCONFIG only contains reserved bits */ + +#define STATUSRSSI 10 /* Status RSSI */ +#define STATUSRSSI_RDSR 0x8000 /* bits 15..15: RDS Ready (Si4701 only) */ +#define STATUSRSSI_STC 0x4000 /* bits 14..14: Seek/Tune Complete */ +#define STATUSRSSI_SF 0x2000 /* bits 13..13: Seek Fail/Band Limit */ +#define STATUSRSSI_AFCRL 0x1000 /* bits 12..12: AFC Rail */ +#define STATUSRSSI_RDSS 0x0800 /* bits 11..11: RDS Synchronized (Si4701 only) */ +#define STATUSRSSI_BLERA 0x0600 /* bits 10..09: RDS Block A Errors (Si4701 only) */ +#define STATUSRSSI_ST 0x0100 /* bits 08..08: Stereo Indicator */ +#define STATUSRSSI_RSSI 0x00ff /* bits 07..00: RSSI (Received Signal Strength Indicator) */ + +#define READCHAN 11 /* Read Channel */ +#define READCHAN_BLERB 0xc000 /* bits 15..14: RDS Block D Errors (Si4701 only) */ +#define READCHAN_BLERC 0x3000 /* bits 13..12: RDS Block C Errors (Si4701 only) */ +#define READCHAN_BLERD 0x0c00 /* bits 11..10: RDS Block B Errors (Si4701 only) */ +#define READCHAN_READCHAN 0x03ff /* bits 09..00: Read Channel */ + +#define RDSA 12 /* RDSA */ +#define RDSA_RDSA 0xffff /* bits 15..00: RDS Block A Data (Si4701 only) */ + +#define RDSB 13 /* RDSB */ +#define RDSB_RDSB 0xffff /* bits 15..00: RDS Block B Data (Si4701 only) */ + +#define RDSC 14 /* RDSC */ +#define RDSC_RDSC 0xffff /* bits 15..00: RDS Block C Data (Si4701 only) */ + +#define RDSD 15 /* RDSD */ +#define RDSD_RDSD 0xffff /* bits 15..00: RDS Block D Data (Si4701 only) */ + + +/************************************************************************** + * General Driver Definitions + **************************************************************************/ + +/* + * si470x_device - private data + */ +struct si470x_device { + struct video_device *videodev; + + /* reference to USB and video device */ + struct usb_device *usbdev; + struct usb_interface *intf; + + /* Interrupt endpoint handling */ + char *int_in_buffer; + struct usb_endpoint_descriptor *int_in_endpoint; + struct urb *int_in_urb; + int int_in_running; + + /* scratch page */ + unsigned char software_version; + unsigned char hardware_version; + + /* driver management */ + unsigned char disconnected; + struct mutex disconnect_lock; + unsigned int users; + + /* Silabs internal registers (0..15) */ + unsigned short registers[RADIO_REGISTER_NUM]; + + /* RDS receive buffer */ + wait_queue_head_t read_queue; + struct mutex lock; /* buffer locking */ + unsigned char *buffer; /* size is always multiple of three */ + unsigned int buf_size; + unsigned int rd_index; + unsigned int wr_index; +}; + + +/* + * The frequency is set in units of 62.5 Hz when using V4L2_TUNER_CAP_LOW, + * 62.5 kHz otherwise. + * The tuner is able to have a channel spacing of 50, 100 or 200 kHz. + * tuner->capability is therefore set to V4L2_TUNER_CAP_LOW + * The FREQ_MUL is then: 1 MHz / 62.5 Hz = 16000 + */ +#define FREQ_MUL (1000000 / 62.5) + + + +/************************************************************************** + * Common Functions + **************************************************************************/ +extern const struct v4l2_file_operations si470x_fops; +extern struct video_device si470x_viddev_template; +int si470x_get_register(struct si470x_device *radio, int regnr); +int si470x_set_register(struct si470x_device *radio, int regnr); +int si470x_set_freq(struct si470x_device *radio, unsigned int freq); +int si470x_start(struct si470x_device *radio); +int si470x_stop(struct si470x_device *radio); +int si470x_rds_on(struct si470x_device *radio); +int si470x_vidioc_querycap(struct file *file, void *priv, + struct v4l2_capability *capability); -- cgit v1.2.3 From 951be4abc87f0caf46aba5d23981a83c323deda2 Mon Sep 17 00:00:00 2001 From: Tobias Lorenz Date: Sun, 9 Aug 2009 19:22:41 +0200 Subject: radio-si470x: change to dev_* macro from printk This patch is for using dev_* macro instead of printk. Signed-off-by: Joonyoung Shim Acked-by: Tobias Lorenz --- .../media/radio/si470x/radio-si470x-common.c | 50 +++++++++--------- .../drivers/media/radio/si470x/radio-si470x-usb.c | 58 +++++++++----------- 2 files changed, 52 insertions(+), 56 deletions(-) --- .../media/radio/si470x/radio-si470x-common.c | 50 +++++++++---------- .../drivers/media/radio/si470x/radio-si470x-usb.c | 58 ++++++++++------------ 2 files changed, 52 insertions(+), 56 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/radio/si470x/radio-si470x-common.c b/linux/drivers/media/radio/si470x/radio-si470x-common.c index b64559d56..fd9fc4aa8 100644 --- a/linux/drivers/media/radio/si470x/radio-si470x-common.c +++ b/linux/drivers/media/radio/si470x/radio-si470x-common.c @@ -184,10 +184,10 @@ static int si470x_set_chan(struct si470x_device *radio, unsigned short chan) } while (((radio->registers[STATUSRSSI] & STATUSRSSI_STC) == 0) && (!timed_out)); if ((radio->registers[STATUSRSSI] & STATUSRSSI_STC) == 0) - printk(KERN_WARNING DRIVER_NAME ": tune does not complete\n"); + dev_warn(&radio->videodev->dev, "tune does not complete\n"); if (timed_out) - printk(KERN_WARNING DRIVER_NAME - ": tune timed out after %u ms\n", tune_timeout); + dev_warn(&radio->videodev->dev, + "tune timed out after %u ms\n", tune_timeout); stop: /* stop tuning */ @@ -320,13 +320,13 @@ static int si470x_set_seek(struct si470x_device *radio, } while (((radio->registers[STATUSRSSI] & STATUSRSSI_STC) == 0) && (!timed_out)); if ((radio->registers[STATUSRSSI] & STATUSRSSI_STC) == 0) - printk(KERN_WARNING DRIVER_NAME ": seek does not complete\n"); + dev_warn(&radio->videodev->dev, "seek does not complete\n"); if (radio->registers[STATUSRSSI] & STATUSRSSI_SF) - printk(KERN_WARNING DRIVER_NAME - ": seek failed / band limit reached\n"); + dev_warn(&radio->videodev->dev, + "seek failed / band limit reached\n"); if (timed_out) - printk(KERN_WARNING DRIVER_NAME - ": seek timed out after %u ms\n", seek_timeout); + dev_warn(&radio->videodev->dev, + "seek timed out after %u ms\n", seek_timeout); stop: /* stop seeking */ @@ -435,6 +435,7 @@ int si470x_rds_on(struct si470x_device *radio) static int si470x_vidioc_queryctrl(struct file *file, void *priv, struct v4l2_queryctrl *qc) { + struct si470x_device *radio = video_drvdata(file); int retval = -EINVAL; /* abort if qc->id is below V4L2_CID_BASE */ @@ -458,8 +459,8 @@ static int si470x_vidioc_queryctrl(struct file *file, void *priv, done: if (retval < 0) - printk(KERN_WARNING DRIVER_NAME - ": query controls failed with %d\n", retval); + dev_warn(&radio->videodev->dev, + "query controls failed with %d\n", retval); return retval; } @@ -494,8 +495,8 @@ static int si470x_vidioc_g_ctrl(struct file *file, void *priv, done: if (retval < 0) - printk(KERN_WARNING DRIVER_NAME - ": get control failed with %d\n", retval); + dev_warn(&radio->videodev->dev, + "get control failed with %d\n", retval); return retval; } @@ -534,8 +535,8 @@ static int si470x_vidioc_s_ctrl(struct file *file, void *priv, done: if (retval < 0) - printk(KERN_WARNING DRIVER_NAME - ": set control failed with %d\n", retval); + dev_warn(&radio->videodev->dev, + "set control failed with %d\n", retval); return retval; } @@ -632,8 +633,8 @@ static int si470x_vidioc_g_tuner(struct file *file, void *priv, done: if (retval < 0) - printk(KERN_WARNING DRIVER_NAME - ": get tuner failed with %d\n", retval); + dev_warn(&radio->videodev->dev, + "get tuner failed with %d\n", retval); return retval; } @@ -671,8 +672,8 @@ static int si470x_vidioc_s_tuner(struct file *file, void *priv, done: if (retval < 0) - printk(KERN_WARNING DRIVER_NAME - ": set tuner failed with %d\n", retval); + dev_warn(&radio->videodev->dev, + "set tuner failed with %d\n", retval); return retval; } @@ -701,8 +702,8 @@ static int si470x_vidioc_g_frequency(struct file *file, void *priv, done: if (retval < 0) - printk(KERN_WARNING DRIVER_NAME - ": get frequency failed with %d\n", retval); + dev_warn(&radio->videodev->dev, + "get frequency failed with %d\n", retval); return retval; } @@ -730,8 +731,8 @@ static int si470x_vidioc_s_frequency(struct file *file, void *priv, done: if (retval < 0) - printk(KERN_WARNING DRIVER_NAME - ": set frequency failed with %d\n", retval); + dev_warn(&radio->videodev->dev, + "set frequency failed with %d\n", retval); return retval; } @@ -759,9 +760,8 @@ static int si470x_vidioc_s_hw_freq_seek(struct file *file, void *priv, done: if (retval < 0) - printk(KERN_WARNING DRIVER_NAME - ": set hardware frequency seek failed with %d\n", - retval); + dev_warn(&radio->videodev->dev, + "set hardware frequency seek failed with %d\n", retval); return retval; } diff --git a/linux/drivers/media/radio/si470x/radio-si470x-usb.c b/linux/drivers/media/radio/si470x/radio-si470x-usb.c index f3d805f70..650816140 100644 --- a/linux/drivers/media/radio/si470x/radio-si470x-usb.c +++ b/linux/drivers/media/radio/si470x/radio-si470x-usb.c @@ -223,8 +223,8 @@ static int si470x_get_report(struct si470x_device *radio, void *buf, int size) buf, size, usb_timeout); if (retval < 0) - printk(KERN_WARNING DRIVER_NAME - ": si470x_get_report: usb_control_msg returned %d\n", + dev_warn(&radio->intf->dev, + "si470x_get_report: usb_control_msg returned %d\n", retval); return retval; } @@ -246,8 +246,8 @@ static int si470x_set_report(struct si470x_device *radio, void *buf, int size) buf, size, usb_timeout); if (retval < 0) - printk(KERN_WARNING DRIVER_NAME - ": si470x_set_report: usb_control_msg returned %d\n", + dev_warn(&radio->intf->dev, + "si470x_set_report: usb_control_msg returned %d\n", retval); return retval; } @@ -358,7 +358,7 @@ static int si470x_get_scratch_page_versions(struct si470x_device *radio) retval = si470x_get_report(radio, (void *) &buf, sizeof(buf)); if (retval < 0) - printk(KERN_WARNING DRIVER_NAME ": si470x_get_scratch: " + dev_warn(&radio->intf->dev, "si470x_get_scratch: " "si470x_get_report returned %d\n", retval); else { radio->software_version = buf[1]; @@ -396,8 +396,8 @@ static void si470x_int_in_callback(struct urb *urb) urb->status == -ESHUTDOWN) { return; } else { - printk(KERN_WARNING DRIVER_NAME - ": non-zero urb status (%d)\n", urb->status); + dev_warn(&radio->intf->dev, + "non-zero urb status (%d)\n", urb->status); goto resubmit; /* Maybe we can recover. */ } } @@ -482,8 +482,8 @@ resubmit: if (radio->int_in_running && radio->usbdev) { retval = usb_submit_urb(radio->int_in_urb, GFP_ATOMIC); if (retval) { - printk(KERN_WARNING DRIVER_NAME - ": resubmitting urb failed (%d)", retval); + dev_warn(&radio->intf->dev, + "resubmitting urb failed (%d)", retval); radio->int_in_running = 0; } } @@ -616,8 +616,8 @@ static int si470x_fops_open(struct file *file) retval = usb_submit_urb(radio->int_in_urb, GFP_KERNEL); if (retval) { - printk(KERN_INFO DRIVER_NAME - ": submitting int urb failed (%d)\n", retval); + dev_info(&radio->intf->dev, + "submitting int urb failed (%d)\n", retval); radio->int_in_running = 0; usb_autopm_put_interface(radio->intf); } @@ -753,8 +753,7 @@ static int si470x_usb_driver_probe(struct usb_interface *intf, radio->int_in_endpoint = endpoint; } if (!radio->int_in_endpoint) { - printk(KERN_INFO DRIVER_NAME - ": could not find interrupt in endpoint\n"); + dev_info(&intf->dev, "could not find interrupt in endpoint\n"); retval = -EIO; goto err_radio; } @@ -763,15 +762,14 @@ static int si470x_usb_driver_probe(struct usb_interface *intf, radio->int_in_buffer = kmalloc(int_end_size, GFP_KERNEL); if (!radio->int_in_buffer) { - printk(KERN_INFO DRIVER_NAME - "could not allocate int_in_buffer"); + dev_info(&intf->dev, "could not allocate int_in_buffer"); retval = -ENOMEM; goto err_radio; } radio->int_in_urb = usb_alloc_urb(0, GFP_KERNEL); if (!radio->int_in_urb) { - printk(KERN_INFO DRIVER_NAME "could not allocate int_in_urb"); + dev_info(&intf->dev, "could not allocate int_in_urb"); retval = -ENOMEM; goto err_intbuffer; } @@ -791,7 +789,7 @@ static int si470x_usb_driver_probe(struct usb_interface *intf, retval = -EIO; goto err_video; } - printk(KERN_INFO DRIVER_NAME ": DeviceID=0x%4.4hx ChipID=0x%4.4hx\n", + dev_info(&intf->dev, "DeviceID=0x%4.4hx ChipID=0x%4.4hx\n", radio->registers[DEVICEID], radio->registers[CHIPID]); /* get software and hardware versions */ @@ -799,23 +797,22 @@ static int si470x_usb_driver_probe(struct usb_interface *intf, retval = -EIO; goto err_video; } - printk(KERN_INFO DRIVER_NAME - ": software version %d, hardware version %d\n", + dev_info(&intf->dev, "software version %d, hardware version %d\n", radio->software_version, radio->hardware_version); /* check if device and firmware is current */ if ((radio->registers[CHIPID] & CHIPID_FIRMWARE) < RADIO_SW_VERSION_CURRENT) { - printk(KERN_WARNING DRIVER_NAME - ": This driver is known to work with " + dev_warn(&intf->dev, + "This driver is known to work with " "firmware version %hu,\n", RADIO_SW_VERSION_CURRENT); - printk(KERN_WARNING DRIVER_NAME - ": but the device has firmware version %hu.\n", + dev_warn(&intf->dev, + "but the device has firmware version %hu.\n", radio->registers[CHIPID] & CHIPID_FIRMWARE); - printk(KERN_WARNING DRIVER_NAME - ": If you have some trouble using this driver,\n"); - printk(KERN_WARNING DRIVER_NAME - ": please report to V4L ML at " + dev_warn(&intf->dev, + "If you have some trouble using this driver,\n"); + dev_warn(&intf->dev, + "please report to V4L ML at " "linux-media@vger.kernel.org\n"); } @@ -842,8 +839,7 @@ static int si470x_usb_driver_probe(struct usb_interface *intf, retval = video_register_device(radio->videodev, VFL_TYPE_RADIO, radio_nr); if (retval) { - printk(KERN_WARNING DRIVER_NAME - ": Could not register video device\n"); + dev_warn(&intf->dev, "Could not register video device\n"); goto err_all; } usb_set_intfdata(intf, radio); @@ -868,7 +864,7 @@ err_initial: static int si470x_usb_driver_suspend(struct usb_interface *intf, pm_message_t message) { - printk(KERN_INFO DRIVER_NAME ": suspending now...\n"); + dev_info(&intf->dev, "suspending now...\n"); return 0; } @@ -879,7 +875,7 @@ static int si470x_usb_driver_suspend(struct usb_interface *intf, */ static int si470x_usb_driver_resume(struct usb_interface *intf) { - printk(KERN_INFO DRIVER_NAME ": resuming now...\n"); + dev_info(&intf->dev, "resuming now...\n"); return 0; } -- cgit v1.2.3 From edce5773436aeaa6d195d1db0cc80f4c10a7acf1 Mon Sep 17 00:00:00 2001 From: Tobias Lorenz Date: Sun, 9 Aug 2009 19:23:02 +0200 Subject: radio-si470x: add disconnect check function The si470x_disconnect_check is function to check disconnect state of radio in common file. The function is implemented in each interface file. Signed-off-by: Joonyoung Shim Acked-by: Tobias Lorenz --- .../media/radio/si470x/radio-si470x-common.c | 40 +++++++++---------- .../drivers/media/radio/si470x/radio-si470x-usb.c | 17 ++++++++ linux/drivers/media/radio/si470x/radio-si470x.h | 1 + 3 files changed, 37 insertions(+), 21 deletions(-) --- .../media/radio/si470x/radio-si470x-common.c | 40 ++++++++++------------ .../drivers/media/radio/si470x/radio-si470x-usb.c | 17 +++++++++ linux/drivers/media/radio/si470x/radio-si470x.h | 1 + 3 files changed, 37 insertions(+), 21 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/radio/si470x/radio-si470x-common.c b/linux/drivers/media/radio/si470x/radio-si470x-common.c index fd9fc4aa8..9f9a417ca 100644 --- a/linux/drivers/media/radio/si470x/radio-si470x-common.c +++ b/linux/drivers/media/radio/si470x/radio-si470x-common.c @@ -475,10 +475,9 @@ static int si470x_vidioc_g_ctrl(struct file *file, void *priv, int retval = 0; /* safety checks */ - if (radio->disconnected) { - retval = -EIO; + retval = si470x_disconnect_check(radio); + if (retval) goto done; - } switch (ctrl->id) { case V4L2_CID_AUDIO_VOLUME: @@ -511,10 +510,9 @@ static int si470x_vidioc_s_ctrl(struct file *file, void *priv, int retval = 0; /* safety checks */ - if (radio->disconnected) { - retval = -EIO; + retval = si470x_disconnect_check(radio); + if (retval) goto done; - } switch (ctrl->id) { case V4L2_CID_AUDIO_VOLUME: @@ -567,10 +565,10 @@ static int si470x_vidioc_g_tuner(struct file *file, void *priv, int retval = 0; /* safety checks */ - if (radio->disconnected) { - retval = -EIO; + retval = si470x_disconnect_check(radio); + if (retval) goto done; - } + if (tuner->index != 0) { retval = -EINVAL; goto done; @@ -649,10 +647,10 @@ static int si470x_vidioc_s_tuner(struct file *file, void *priv, int retval = -EINVAL; /* safety checks */ - if (radio->disconnected) { - retval = -EIO; + retval = si470x_disconnect_check(radio); + if (retval) goto done; - } + if (tuner->index != 0) goto done; @@ -688,10 +686,10 @@ static int si470x_vidioc_g_frequency(struct file *file, void *priv, int retval = 0; /* safety checks */ - if (radio->disconnected) { - retval = -EIO; + retval = si470x_disconnect_check(radio); + if (retval) goto done; - } + if (freq->tuner != 0) { retval = -EINVAL; goto done; @@ -718,10 +716,10 @@ static int si470x_vidioc_s_frequency(struct file *file, void *priv, int retval = 0; /* safety checks */ - if (radio->disconnected) { - retval = -EIO; + retval = si470x_disconnect_check(radio); + if (retval) goto done; - } + if (freq->tuner != 0) { retval = -EINVAL; goto done; @@ -747,10 +745,10 @@ static int si470x_vidioc_s_hw_freq_seek(struct file *file, void *priv, int retval = 0; /* safety checks */ - if (radio->disconnected) { - retval = -EIO; + retval = si470x_disconnect_check(radio); + if (retval) goto done; - } + if (seek->tuner != 0) { retval = -EINVAL; goto done; diff --git a/linux/drivers/media/radio/si470x/radio-si470x-usb.c b/linux/drivers/media/radio/si470x/radio-si470x-usb.c index 650816140..2f5cf6c72 100644 --- a/linux/drivers/media/radio/si470x/radio-si470x-usb.c +++ b/linux/drivers/media/radio/si470x/radio-si470x-usb.c @@ -370,6 +370,23 @@ static int si470x_get_scratch_page_versions(struct si470x_device *radio) +/************************************************************************** + * General Driver Functions - DISCONNECT_CHECK + **************************************************************************/ + +/* + * si470x_disconnect_check - check whether radio disconnects + */ +int si470x_disconnect_check(struct si470x_device *radio) +{ + if (radio->disconnected) + return -EIO; + else + return 0; +} + + + /************************************************************************** * RDS Driver Functions **************************************************************************/ diff --git a/linux/drivers/media/radio/si470x/radio-si470x.h b/linux/drivers/media/radio/si470x/radio-si470x.h index 88d3ebbe2..eb36b6451 100644 --- a/linux/drivers/media/radio/si470x/radio-si470x.h +++ b/linux/drivers/media/radio/si470x/radio-si470x.h @@ -194,6 +194,7 @@ extern const struct v4l2_file_operations si470x_fops; extern struct video_device si470x_viddev_template; int si470x_get_register(struct si470x_device *radio, int regnr); int si470x_set_register(struct si470x_device *radio, int regnr); +int si470x_disconnect_check(struct si470x_device *radio); int si470x_set_freq(struct si470x_device *radio, unsigned int freq); int si470x_start(struct si470x_device *radio); int si470x_stop(struct si470x_device *radio); -- cgit v1.2.3 From b17608ffc4ff53dbf7bab4bbcdb1d3ad808e9ff0 Mon Sep 17 00:00:00 2001 From: Tobias Lorenz Date: Sun, 9 Aug 2009 19:23:35 +0200 Subject: radio-si470x: add i2c driver for si470x This patch supports i2c interface of si470x. The i2c specific part exists in radio-si470x-i2c.c file and the common part uses radio-si470x-common.c file. The '#if defined' is inserted inevitably because of parts used only si470x usb in the common file. The current driver version doesn't support the RDS. Signed-off-by: Joonyoung Shim Acked-by: Tobias Lorenz --- linux/drivers/media/radio/si470x/Kconfig | 13 + linux/drivers/media/radio/si470x/Makefile | 2 + .../media/radio/si470x/radio-si470x-common.c | 6 + .../drivers/media/radio/si470x/radio-si470x-i2c.c | 254 ++++++++++++++++++++ linux/drivers/media/radio/si470x/radio-si470x.h | 6 + 5 files changed, 281 insertions(+), 0 deletions(-) create mode 100644 linux/drivers/media/radio/si470x/radio-si470x-i2c.c --- linux/drivers/media/radio/si470x/Kconfig | 13 ++ linux/drivers/media/radio/si470x/Makefile | 2 + .../media/radio/si470x/radio-si470x-common.c | 6 + .../drivers/media/radio/si470x/radio-si470x-i2c.c | 254 +++++++++++++++++++++ linux/drivers/media/radio/si470x/radio-si470x.h | 6 + 5 files changed, 281 insertions(+) create mode 100644 linux/drivers/media/radio/si470x/radio-si470x-i2c.c (limited to 'linux/drivers') diff --git a/linux/drivers/media/radio/si470x/Kconfig b/linux/drivers/media/radio/si470x/Kconfig index 20d05c04f..a466654ee 100644 --- a/linux/drivers/media/radio/si470x/Kconfig +++ b/linux/drivers/media/radio/si470x/Kconfig @@ -22,3 +22,16 @@ config USB_SI470X To compile this driver as a module, choose M here: the module will be called radio-usb-si470x. + +config I2C_SI470X + tristate "Silicon Labs Si470x FM Radio Receiver support with I2C" + depends on I2C && RADIO_SI470X && !USB_SI470X + ---help--- + This is a driver for I2C devices with the Silicon Labs SI470x + chip. + + Say Y here if you want to connect this type of radio to your + computer's I2C port. + + To compile this driver as a module, choose M here: the + module will be called radio-i2c-si470x. diff --git a/linux/drivers/media/radio/si470x/Makefile b/linux/drivers/media/radio/si470x/Makefile index 3cb777fe3..06964816c 100644 --- a/linux/drivers/media/radio/si470x/Makefile +++ b/linux/drivers/media/radio/si470x/Makefile @@ -3,5 +3,7 @@ # radio-usb-si470x-objs := radio-si470x-usb.o radio-si470x-common.o +radio-i2c-si470x-objs := radio-si470x-i2c.o radio-si470x-common.o obj-$(CONFIG_USB_SI470X) += radio-usb-si470x.o +obj-$(CONFIG_I2C_SI470X) += radio-i2c-si470x.o diff --git a/linux/drivers/media/radio/si470x/radio-si470x-common.c b/linux/drivers/media/radio/si470x/radio-si470x-common.c index 9f9a417ca..f33315f2c 100644 --- a/linux/drivers/media/radio/si470x/radio-si470x-common.c +++ b/linux/drivers/media/radio/si470x/radio-si470x-common.c @@ -581,8 +581,12 @@ static int si470x_vidioc_g_tuner(struct file *file, void *priv, /* driver constants */ strcpy(tuner->name, "FM"); tuner->type = V4L2_TUNER_RADIO; +#if defined(CONFIG_USB_SI470X) || defined(CONFIG_USB_SI470X_MODULE) tuner->capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_RDS; +#else + tuner->capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO; +#endif /* range limits */ switch ((radio->registers[SYSCONFIG2] & SYSCONFIG2_BAND) >> 6) { @@ -608,10 +612,12 @@ static int si470x_vidioc_g_tuner(struct file *file, void *priv, tuner->rxsubchans = V4L2_TUNER_SUB_MONO; else tuner->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO; +#if defined(CONFIG_USB_SI470X) || defined(CONFIG_USB_SI470X_MODULE) /* If there is a reliable method of detecting an RDS channel, then this code should check for that before setting this RDS subchannel. */ tuner->rxsubchans |= V4L2_TUNER_SUB_RDS; +#endif /* mono/stereo selector */ if ((radio->registers[POWERCFG] & POWERCFG_MONO) == 0) diff --git a/linux/drivers/media/radio/si470x/radio-si470x-i2c.c b/linux/drivers/media/radio/si470x/radio-si470x-i2c.c new file mode 100644 index 000000000..218102184 --- /dev/null +++ b/linux/drivers/media/radio/si470x/radio-si470x-i2c.c @@ -0,0 +1,254 @@ +/* + * drivers/media/radio/si470x/radio-si470x-i2c.c + * + * I2C driver for radios with Silicon Labs Si470x FM Radio Receivers + * + * Copyright (C) 2009 Samsung Electronics Co.Ltd + * Author: Joonyoung Shim + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * + * TODO: + * - RDS support + * + */ + +#include +#include +#include +#include + +#include "radio-si470x.h" + +#define DRIVER_KERNEL_VERSION KERNEL_VERSION(1, 0, 0) +#define DRIVER_CARD "Silicon Labs Si470x FM Radio Receiver" +#define DRIVER_VERSION "1.0.0" + +/* starting with the upper byte of register 0x0a */ +#define READ_REG_NUM RADIO_REGISTER_NUM +#define READ_INDEX(i) ((i + RADIO_REGISTER_NUM - 0x0a) % READ_REG_NUM) + +static int si470x_get_all_registers(struct si470x_device *radio) +{ + int i; + u16 buf[READ_REG_NUM]; + struct i2c_msg msgs[1] = { + { radio->client->addr, I2C_M_RD, sizeof(u16) * READ_REG_NUM, + (void *)buf }, + }; + + if (i2c_transfer(radio->client->adapter, msgs, 1) != 1) + return -EIO; + + for (i = 0; i < READ_REG_NUM; i++) + radio->registers[i] = __be16_to_cpu(buf[READ_INDEX(i)]); + + return 0; +} + +int si470x_get_register(struct si470x_device *radio, int regnr) +{ + u16 buf[READ_REG_NUM]; + struct i2c_msg msgs[1] = { + { radio->client->addr, I2C_M_RD, sizeof(u16) * READ_REG_NUM, + (void *)buf }, + }; + + if (i2c_transfer(radio->client->adapter, msgs, 1) != 1) + return -EIO; + + radio->registers[regnr] = __be16_to_cpu(buf[READ_INDEX(regnr)]); + + return 0; +} + +/* starting with the upper byte of register 0x02h */ +#define WRITE_REG_NUM 8 +#define WRITE_INDEX(i) (i + 0x02) + +int si470x_set_register(struct si470x_device *radio, int regnr) +{ + int i; + u16 buf[WRITE_REG_NUM]; + struct i2c_msg msgs[1] = { + { radio->client->addr, 0, sizeof(u16) * WRITE_REG_NUM, + (void *)buf }, + }; + + for (i = 0; i < WRITE_REG_NUM; i++) + buf[i] = __cpu_to_be16(radio->registers[WRITE_INDEX(i)]); + + if (i2c_transfer(radio->client->adapter, msgs, 1) != 1) + return -EIO; + + return 0; +} + +int si470x_disconnect_check(struct si470x_device *radio) +{ + return 0; +} + +static int si470x_fops_open(struct file *file) +{ + struct si470x_device *radio = video_drvdata(file); + int retval = 0; + + mutex_lock(&radio->lock); + radio->users++; + + if (radio->users == 1) + /* start radio */ + retval = si470x_start(radio); + mutex_unlock(&radio->lock); + + return retval; +} + +static int si470x_fops_release(struct file *file) +{ + struct si470x_device *radio = video_drvdata(file); + int retval = 0; + + /* safety check */ + if (!radio) + return -ENODEV; + + mutex_lock(&radio->lock); + radio->users--; + if (radio->users == 0) + /* stop radio */ + retval = si470x_stop(radio); + mutex_unlock(&radio->lock); + + return retval; +} + +const struct v4l2_file_operations si470x_fops = { + .owner = THIS_MODULE, + .ioctl = video_ioctl2, + .open = si470x_fops_open, + .release = si470x_fops_release, +}; + +int si470x_vidioc_querycap(struct file *file, void *priv, + struct v4l2_capability *capability) +{ + strlcpy(capability->driver, DRIVER_NAME, sizeof(capability->driver)); + strlcpy(capability->card, DRIVER_CARD, sizeof(capability->card)); + capability->version = DRIVER_KERNEL_VERSION; + capability->capabilities = V4L2_CAP_HW_FREQ_SEEK | + V4L2_CAP_TUNER | V4L2_CAP_RADIO; + + return 0; +} + +static int __devinit si470x_i2c_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct si470x_device *radio; + int retval = 0; + + /* private data allocation and initialization */ + radio = kzalloc(sizeof(struct si470x_device), GFP_KERNEL); + if (!radio) { + retval = -ENOMEM; + goto err_initial; + } + radio->client = client; + radio->users = 0; + mutex_init(&radio->lock); + + /* video device allocation and initialization */ + radio->videodev = video_device_alloc(); + if (!radio->videodev) { + retval = -ENOMEM; + goto err_radio; + } + memcpy(radio->videodev, &si470x_viddev_template, + sizeof(si470x_viddev_template)); + video_set_drvdata(radio->videodev, radio); + + /* power up : need 110ms */ + radio->registers[POWERCFG] = POWERCFG_ENABLE; + if (si470x_set_register(radio, POWERCFG) < 0) { + retval = -EIO; + goto err_all; + } + msleep(110); + + /* show some infos about the specific si470x device */ + if (si470x_get_all_registers(radio) < 0) { + retval = -EIO; + goto err_radio; + } + dev_info(&client->dev, "DeviceID=0x%4.4hx ChipID=0x%4.4hx\n", + radio->registers[DEVICEID], radio->registers[CHIPID]); + + /* set initial frequency */ + si470x_set_freq(radio, 87.5 * FREQ_MUL); /* available in all regions */ + + /* register video device */ + retval = video_register_device(radio->videodev, VFL_TYPE_RADIO, -1); + if (retval) { + dev_warn(&client->dev, "Could not register video device\n"); + goto err_all; + } + + i2c_set_clientdata(client, radio); + + return 0; +err_all: + video_device_release(radio->videodev); +err_radio: + kfree(radio); +err_initial: + return retval; +} + +static __devexit int si470x_i2c_remove(struct i2c_client *client) +{ + struct si470x_device *radio = i2c_get_clientdata(client); + + video_unregister_device(radio->videodev); + kfree(radio); + i2c_set_clientdata(client, NULL); + + return 0; +} + +static const struct i2c_device_id si470x_i2c_id[] = { + { "si470x", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, si470x_i2c_id); + +static struct i2c_driver si470x_i2c_driver = { + .driver = { + .name = "si470x", + .owner = THIS_MODULE, + }, + .probe = si470x_i2c_probe, + .remove = __devexit_p(si470x_i2c_remove), + .id_table = si470x_i2c_id, +}; + +static int __init si470x_i2c_init(void) +{ + return i2c_add_driver(&si470x_i2c_driver); +} +module_init(si470x_i2c_init); + +static void __exit si470x_i2c_exit(void) +{ + i2c_del_driver(&si470x_i2c_driver); +} +module_exit(si470x_i2c_exit); + +MODULE_DESCRIPTION("i2c radio driver for si470x fm radio receivers"); +MODULE_AUTHOR("Joonyoung Shim "); +MODULE_LICENSE("GPL"); diff --git a/linux/drivers/media/radio/si470x/radio-si470x.h b/linux/drivers/media/radio/si470x/radio-si470x.h index eb36b6451..791c367be 100644 --- a/linux/drivers/media/radio/si470x/radio-si470x.h +++ b/linux/drivers/media/radio/si470x/radio-si470x.h @@ -144,6 +144,11 @@ struct si470x_device { struct video_device *videodev; +#if defined(CONFIG_I2C_SI470X) || defined(CONFIG_I2C_SI470X_MODULE) + struct i2c_client *client; +#endif + +#if defined(CONFIG_USB_SI470X) || defined(CONFIG_USB_SI470X_MODULE) /* reference to USB and video device */ struct usb_device *usbdev; struct usb_interface *intf; @@ -161,6 +166,7 @@ struct si470x_device { /* driver management */ unsigned char disconnected; struct mutex disconnect_lock; +#endif unsigned int users; /* Silabs internal registers (0..15) */ -- cgit v1.2.3 From 4a8acba072fef7a5126e7193667e6b0746555606 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 9 Aug 2009 19:39:23 -0300 Subject: em28xx: Implement g/s_register via address match From: Mauro Carvalho Chehab Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/em28xx/em28xx-video.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/em28xx/em28xx-video.c b/linux/drivers/media/video/em28xx/em28xx-video.c index 77ec51dad..c7d723a03 100644 --- a/linux/drivers/media/video/em28xx/em28xx-video.c +++ b/linux/drivers/media/video/em28xx/em28xx-video.c @@ -1342,8 +1342,9 @@ static int vidioc_g_register(struct file *file, void *priv, v4l2_device_call_all(&dev->v4l2_dev, 0, core, g_register, reg); return 0; case V4L2_CHIP_MATCH_I2C_ADDR: - /* Not supported yet */ - return -EINVAL; + /* TODO: is this correct? */ + v4l2_device_call_all(&dev->v4l2_dev, 0, core, g_register, reg); + return 0; default: if (!v4l2_chip_match_host(®->match)) return -EINVAL; @@ -1394,8 +1395,9 @@ static int vidioc_s_register(struct file *file, void *priv, v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_register, reg); return 0; case V4L2_CHIP_MATCH_I2C_ADDR: - /* Not supported yet */ - return -EINVAL; + /* TODO: is this correct? */ + v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_register, reg); + return 0; default: if (!v4l2_chip_match_host(®->match)) return -EINVAL; -- cgit v1.2.3 From 67924cd04f67ef0bf649ab43a317717fbbeb69af Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 10 Aug 2009 02:57:57 -0300 Subject: em28xx: Move the non-board dependent part to be outside em28xx_pre_card_setup() From: Mauro Carvalho Chehab em28xx_pre_card_setup() is meant to contain board-specific initialization. Also, as autodetection sometimes occur only after having i2c bus enabled, this function may need to be called later. Moving those setups to happen outside the function avoids calling it twice without need and without duplicating output lines at dmesg. Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/em28xx/em28xx-cards.c | 111 +++++++++++------------- 1 file changed, 53 insertions(+), 58 deletions(-) (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 9a09df296..ee46460f0 100644 --- a/linux/drivers/media/video/em28xx/em28xx-cards.c +++ b/linux/drivers/media/video/em28xx/em28xx-cards.c @@ -1895,63 +1895,6 @@ static int em28xx_hint_sensor(struct em28xx *dev) */ void em28xx_pre_card_setup(struct em28xx *dev) { - int rc; - - em28xx_set_model(dev); - - em28xx_info("Identified as %s (card=%d)\n", - dev->board.name, dev->model); - - /* Set the default GPO/GPIO for legacy devices */ - dev->reg_gpo_num = EM2880_R04_GPO; - dev->reg_gpio_num = EM28XX_R08_GPIO; - - dev->wait_after_write = 5; - - /* Based on the Chip ID, set the device configuration */ - rc = em28xx_read_reg(dev, EM28XX_R0A_CHIPID); - if (rc > 0) { - dev->chip_id = rc; - - switch (dev->chip_id) { - case CHIP_ID_EM2710: - em28xx_info("chip ID is em2710\n"); - break; - case CHIP_ID_EM2750: - em28xx_info("chip ID is em2750\n"); - break; - case CHIP_ID_EM2820: - em28xx_info("chip ID is em2820 (or em2710)\n"); - break; - case CHIP_ID_EM2840: - em28xx_info("chip ID is em2840\n"); - break; - case CHIP_ID_EM2860: - em28xx_info("chip ID is em2860\n"); - break; - case CHIP_ID_EM2870: - em28xx_info("chip ID is em2870\n"); - dev->wait_after_write = 0; - break; - case CHIP_ID_EM2874: - em28xx_info("chip ID is em2874\n"); - dev->reg_gpio_num = EM2874_R80_GPIO; - dev->wait_after_write = 0; - break; - case CHIP_ID_EM2883: - em28xx_info("chip ID is em2882/em2883\n"); - dev->wait_after_write = 0; - break; - default: - em28xx_info("em28xx chip ID = %d\n", dev->chip_id); - } - } - - /* Prepopulate cached GPO register content */ - rc = em28xx_read_reg(dev, dev->reg_gpo_num); - if (rc >= 0) - dev->reg_gpo = rc; - /* Set the initial XCLK and I2C clock values based on the board definition */ em28xx_write_reg(dev, EM28XX_R0F_XCLK, dev->board.xclk & 0x7f); @@ -2564,7 +2507,7 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, int minor) { struct em28xx *dev = *devhandle; - int retval = -ENOMEM; + int retval; int errCode; dev->udev = udev; @@ -2581,6 +2524,58 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, dev->em28xx_read_reg_req = em28xx_read_reg_req; dev->board.is_em2800 = em28xx_boards[dev->model].is_em2800; + em28xx_set_model(dev); + + /* Set the default GPO/GPIO for legacy devices */ + dev->reg_gpo_num = EM2880_R04_GPO; + dev->reg_gpio_num = EM28XX_R08_GPIO; + + dev->wait_after_write = 5; + + /* Based on the Chip ID, set the device configuration */ + retval = em28xx_read_reg(dev, EM28XX_R0A_CHIPID); + if (retval > 0) { + dev->chip_id = retval; + + switch (dev->chip_id) { + case CHIP_ID_EM2710: + em28xx_info("chip ID is em2710\n"); + break; + case CHIP_ID_EM2750: + em28xx_info("chip ID is em2750\n"); + break; + case CHIP_ID_EM2820: + em28xx_info("chip ID is em2820 (or em2710)\n"); + break; + case CHIP_ID_EM2840: + em28xx_info("chip ID is em2840\n"); + break; + case CHIP_ID_EM2860: + em28xx_info("chip ID is em2860\n"); + break; + case CHIP_ID_EM2870: + em28xx_info("chip ID is em2870\n"); + dev->wait_after_write = 0; + break; + case CHIP_ID_EM2874: + em28xx_info("chip ID is em2874\n"); + dev->reg_gpio_num = EM2874_R80_GPIO; + dev->wait_after_write = 0; + break; + case CHIP_ID_EM2883: + em28xx_info("chip ID is em2882/em2883\n"); + dev->wait_after_write = 0; + break; + default: + em28xx_info("em28xx chip ID = %d\n", dev->chip_id); + } + } + + /* Prepopulate cached GPO register content */ + retval = em28xx_read_reg(dev, dev->reg_gpo_num); + if (retval >= 0) + dev->reg_gpo = retval; + em28xx_pre_card_setup(dev); if (!dev->board.is_em2800) { -- cgit v1.2.3 From 3c6dcb306a9773419a04a1f47bfa00ed856b5517 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 10 Aug 2009 10:29:27 -0300 Subject: em28xx: Fix artifacts with Silvercrest webcam From: Mauro Carvalho Chehab Silvercrest mt9v011 sensor produces a 640x480 image. However, previously, the code were getting only half of the lines and merging two consecutive frames to "produce" a 640x480 image. With the addition of progressive mode, now em28xx is working with a full image. However, when the number of lines is bigger than 240, the beginning of some odd lines are filled with blank. After lots of testing, and physically checking the device for a Xtal, it was noticed experimentally that mt9v011 is using em28xx XCLK as its clock. Due to that, changing XCLK value changes the maximum speed of the stream. At the tests, it were possible to produce up to 32 fps, using a 30 MHz XCLK. However, at that rate, the artifacts happen even at 320x240. Lower values of XCLK produces artifacts only at 640x480. At some values of xclk (for example XCLKK = 6 MHz, 640x480), it is possible to see an invalid sucession of artifacts with this pattern: .xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ..xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ...xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ....xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx .xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ..xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ...xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ....xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx (where the dots represent the blanked pixels) So, it seems that a waveform in the format of a ramp is interferring at the image. The cause of this interference is currently unknown. Some possibilities are: - electrical interference (maybe this device is broken?); - some issue at mt9v011 programming; - some bug at em28xx chip. So, for now, let's be conservative and use a value of XCLK that we know for sure that it won't cause artifacts. As I'm waiting for more of such devices with different em28xx chipset revisions, I'll have the opportunity to double check the issue with other pieces of hardware. Later patches can vary XCLK depending on the vertical resolutions, if a proper fix is not discovered. Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/em28xx/em28xx-cards.c | 50 +++++++++++++++++-------- 1 file changed, 34 insertions(+), 16 deletions(-) (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 ee46460f0..4b7526fa2 100644 --- a/linux/drivers/media/video/em28xx/em28xx-cards.c +++ b/linux/drivers/media/video/em28xx/em28xx-cards.c @@ -231,7 +231,7 @@ static struct em28xx_reg_seq silvercrest_reg_seq[] = { struct em28xx_board em28xx_boards[] = { [EM2750_BOARD_UNKNOWN] = { .name = "EM2710/EM2750/EM2751 webcam grabber", - .xclk = EM28XX_XCLK_FREQUENCY_48MHZ, + .xclk = EM28XX_XCLK_FREQUENCY_20MHZ, .tuner_type = TUNER_ABSENT, .is_webcam = 1, .no_audio = 1, @@ -1838,6 +1838,7 @@ static int em28xx_hint_sensor(struct em28xx *dev) __be16 version_be; u16 version; + /* Micron sensor detection */ dev->i2c_client.addr = 0xba >> 1; cmd = 0; i2c_master_send(&dev->i2c_client, &cmd, 1); @@ -1846,16 +1847,27 @@ static int em28xx_hint_sensor(struct em28xx *dev) return -EINVAL; version = be16_to_cpu(version_be); - switch (version) { case 0x8232: /* mt9v011 640x480 1.3 Mpix sensor */ case 0x8243: /* mt9v011 rev B 640x480 1.3 Mpix sensor */ dev->model = EM2820_BOARD_SILVERCREST_WEBCAM; + em28xx_set_model(dev); + sensor_name = "mt9v011"; dev->em28xx_sensor = EM28XX_MT9V011; dev->sensor_xres = 640; dev->sensor_yres = 480; - dev->sensor_xtal = 12150000; + /* + * FIXME: mt9v011 uses I2S speed as xtal clk - at least with + * the Silvercrest cam I have here for testing - for higher + * resolutions, a high clock cause horizontal artifacts, so we + * need to use a lower xclk frequency. + * Yet, it would be possible to adjust xclk depending on the + * desired resolution, since this affects directly the + * frame rate. + */ + dev->board.xclk = EM28XX_XCLK_FREQUENCY_4_3MHZ; + dev->sensor_xtal = 4300000; /* probably means GRGB 16 bit bayer */ dev->vinmode = 0x0d; @@ -1868,6 +1880,8 @@ static int em28xx_hint_sensor(struct em28xx *dev) #endif case 0x8431: dev->model = EM2750_BOARD_UNKNOWN; + em28xx_set_model(dev); + sensor_name = "mt9m001"; dev->em28xx_sensor = EM28XX_MT9M001; em28xx_initialize_mt9m001(dev); @@ -1884,6 +1898,9 @@ static int em28xx_hint_sensor(struct em28xx *dev) return -EINVAL; } + /* Setup webcam defaults */ + em28xx_pre_card_setup(dev); + em28xx_errdev("Sensor is %s, using model %s entry.\n", sensor_name, em28xx_boards[dev->model].name); @@ -2277,7 +2294,20 @@ void em28xx_register_i2c_ir(struct em28xx *dev) void em28xx_card_setup(struct em28xx *dev) { - em28xx_set_model(dev); + /* + * If the device can be a webcam, seek for a sensor. + * If sensor is not found, then it isn't a webcam. + */ + if (dev->board.is_webcam) { + if (em28xx_hint_sensor(dev) < 0) + dev->board.is_webcam = 0; + else + dev->progressive = 1; + } else + em28xx_set_model(dev); + + em28xx_info("Identified as %s (card=%d)\n", + dev->board.name, dev->model); dev->tuner_type = em28xx_boards[dev->model].tuner_type; if (em28xx_boards[dev->model].tuner_addr) @@ -2610,18 +2640,6 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, dev->vinmode = 0x10; dev->vinctl = 0x11; - /* - * If the device can be a webcam, seek for a sensor. - * If sensor is not found, then it isn't a webcam. - */ - if (dev->board.is_webcam) - if (em28xx_hint_sensor(dev) < 0) - dev->board.is_webcam = 0; - - /* It makes no sense to use de-interlacing mode on webcams */ - if (dev->board.is_webcam) - dev->progressive = 1; - /* Do board specific init and eeprom reading */ em28xx_card_setup(dev); -- cgit v1.2.3 From a4fd422232350c268306a54f169e5b1fe3655f8f Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 10 Aug 2009 10:53:00 -0300 Subject: em28xx: fix: avoid having a bad colored image with webcams From: Mauro Carvalho Chehab Register 0x13 seems to be a sort of image control, maybe gamma. Lower values produce better images, while higher values increases the contrast and shifts colors to green. 0xff produces a black image. If this register is left alone, a random value can be found at the register, producing weird results. This register doesn't seem to affect tv streams. Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/em28xx/em28xx-core.c | 3 +++ 1 file changed, 3 insertions(+) (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 10da3ad82..46cb13182 100644 --- a/linux/drivers/media/video/em28xx/em28xx-core.c +++ b/linux/drivers/media/video/em28xx/em28xx-core.c @@ -632,6 +632,9 @@ int em28xx_capture_start(struct em28xx *dev, int start) return rc; } + if (dev->board.is_webcam) + rc = em28xx_write_reg(dev, 0x13, 0x0c); + /* enable video capture */ rc = em28xx_write_reg(dev, 0x48, 0x00); -- cgit v1.2.3 From 61fe68b877246eb29fc7cccb96a73ffa3c7267fe Mon Sep 17 00:00:00 2001 From: Tobias Lorenz Date: Mon, 10 Aug 2009 23:44:14 +0200 Subject: I2C cleanups and version checks The structure and comments of the I2C part have been adopted to fit to the USB part. Some additional cleanups and precisements have been made to the version detection and checking functionality to clearly separate HW/SW/FW version. Signed-off-by: Tobias Lorenz --- .../drivers/media/radio/si470x/radio-si470x-i2c.c | 245 ++++++++++++++++----- .../drivers/media/radio/si470x/radio-si470x-usb.c | 43 ++-- linux/drivers/media/radio/si470x/radio-si470x.h | 45 ++-- 3 files changed, 257 insertions(+), 76 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/radio/si470x/radio-si470x-i2c.c b/linux/drivers/media/radio/si470x/radio-si470x-i2c.c index 218102184..2d53b6a94 100644 --- a/linux/drivers/media/radio/si470x/radio-si470x-i2c.c +++ b/linux/drivers/media/radio/si470x/radio-si470x-i2c.c @@ -3,53 +3,88 @@ * * I2C driver for radios with Silicon Labs Si470x FM Radio Receivers * - * Copyright (C) 2009 Samsung Electronics Co.Ltd + * Copyright (c) 2009 Samsung Electronics Co.Ltd * Author: Joonyoung Shim * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * TODO: + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +/* + * ToDo: * - RDS support - * */ -#include -#include + +/* driver definitions */ +#define DRIVER_AUTHOR "Joonyoung Shim "; +#define DRIVER_KERNEL_VERSION KERNEL_VERSION(1, 0, 0) +#define DRIVER_CARD "Silicon Labs Si470x FM Radio Receiver" +#define DRIVER_DESC "I2C radio driver for Si470x FM Radio Receivers" +#define DRIVER_VERSION "1.0.0" + +/* kernel includes */ #include #include #include "radio-si470x.h" -#define DRIVER_KERNEL_VERSION KERNEL_VERSION(1, 0, 0) -#define DRIVER_CARD "Silicon Labs Si470x FM Radio Receiver" -#define DRIVER_VERSION "1.0.0" -/* starting with the upper byte of register 0x0a */ +/* I2C Device ID List */ +static const struct i2c_device_id si470x_i2c_id[] = { + /* Generic Entry */ + { "si470x", 0 }, + /* Terminating entry */ + { } +}; +MODULE_DEVICE_TABLE(i2c, si470x_i2c_id); + + + +/************************************************************************** + * Module Parameters + **************************************************************************/ + +/* Radio Nr */ +static int radio_nr = -1; +module_param(radio_nr, int, 0444); +MODULE_PARM_DESC(radio_nr, "Radio Nr"); + + + +/************************************************************************** + * I2C Definitions + **************************************************************************/ + +/* Write starts with the upper byte of register 0x02 */ +#define WRITE_REG_NUM 8 +#define WRITE_INDEX(i) (i + 0x02) + +/* Read starts with the upper byte of register 0x0a */ #define READ_REG_NUM RADIO_REGISTER_NUM #define READ_INDEX(i) ((i + RADIO_REGISTER_NUM - 0x0a) % READ_REG_NUM) -static int si470x_get_all_registers(struct si470x_device *radio) -{ - int i; - u16 buf[READ_REG_NUM]; - struct i2c_msg msgs[1] = { - { radio->client->addr, I2C_M_RD, sizeof(u16) * READ_REG_NUM, - (void *)buf }, - }; - - if (i2c_transfer(radio->client->adapter, msgs, 1) != 1) - return -EIO; - for (i = 0; i < READ_REG_NUM; i++) - radio->registers[i] = __be16_to_cpu(buf[READ_INDEX(i)]); - return 0; -} +/************************************************************************** + * General Driver Functions - REGISTERs + **************************************************************************/ +/* + * si470x_get_register - read register + */ int si470x_get_register(struct si470x_device *radio, int regnr) { u16 buf[READ_REG_NUM]; @@ -66,10 +101,10 @@ int si470x_get_register(struct si470x_device *radio, int regnr) return 0; } -/* starting with the upper byte of register 0x02h */ -#define WRITE_REG_NUM 8 -#define WRITE_INDEX(i) (i + 0x02) +/* + * si470x_set_register - write register + */ int si470x_set_register(struct si470x_device *radio, int regnr) { int i; @@ -88,11 +123,56 @@ int si470x_set_register(struct si470x_device *radio, int regnr) return 0; } + + +/************************************************************************** + * General Driver Functions - ENTIRE REGISTERS + **************************************************************************/ + +/* + * si470x_get_all_registers - read entire registers + */ +static int si470x_get_all_registers(struct si470x_device *radio) +{ + int i; + u16 buf[READ_REG_NUM]; + struct i2c_msg msgs[1] = { + { radio->client->addr, I2C_M_RD, sizeof(u16) * READ_REG_NUM, + (void *)buf }, + }; + + if (i2c_transfer(radio->client->adapter, msgs, 1) != 1) + return -EIO; + + for (i = 0; i < READ_REG_NUM; i++) + radio->registers[i] = __be16_to_cpu(buf[READ_INDEX(i)]); + + return 0; +} + + + +/************************************************************************** + * General Driver Functions - DISCONNECT_CHECK + **************************************************************************/ + +/* + * si470x_disconnect_check - check whether radio disconnects + */ int si470x_disconnect_check(struct si470x_device *radio) { return 0; } + + +/************************************************************************** + * File Operations Interface + **************************************************************************/ + +/* + * si470x_fops_open - file open + */ static int si470x_fops_open(struct file *file) { struct si470x_device *radio = video_drvdata(file); @@ -104,11 +184,16 @@ static int si470x_fops_open(struct file *file) if (radio->users == 1) /* start radio */ retval = si470x_start(radio); + mutex_unlock(&radio->lock); return retval; } + +/* + * si470x_fops_release - file release + */ static int si470x_fops_release(struct file *file) { struct si470x_device *radio = video_drvdata(file); @@ -123,11 +208,16 @@ static int si470x_fops_release(struct file *file) if (radio->users == 0) /* stop radio */ retval = si470x_stop(radio); + mutex_unlock(&radio->lock); return retval; } + +/* + * si470x_fops - file operations interface + */ const struct v4l2_file_operations si470x_fops = { .owner = THIS_MODULE, .ioctl = video_ioctl2, @@ -135,6 +225,15 @@ const struct v4l2_file_operations si470x_fops = { .release = si470x_fops_release, }; + + +/************************************************************************** + * Video4Linux Interface + **************************************************************************/ + +/* + * si470x_vidioc_querycap - query device capabilities + */ int si470x_vidioc_querycap(struct file *file, void *priv, struct v4l2_capability *capability) { @@ -147,11 +246,21 @@ int si470x_vidioc_querycap(struct file *file, void *priv, return 0; } + + +/************************************************************************** + * I2C Interface + **************************************************************************/ + +/* + * si470x_i2c_probe - probe for the device + */ static int __devinit si470x_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct si470x_device *radio; int retval = 0; + unsigned char version_warning = 0; /* private data allocation and initialization */ radio = kzalloc(sizeof(struct si470x_device), GFP_KERNEL); @@ -159,8 +268,8 @@ static int __devinit si470x_i2c_probe(struct i2c_client *client, retval = -ENOMEM; goto err_initial; } - radio->client = client; radio->users = 0; + radio->client = client; mutex_init(&radio->lock); /* video device allocation and initialization */ @@ -181,28 +290,47 @@ static int __devinit si470x_i2c_probe(struct i2c_client *client, } msleep(110); - /* show some infos about the specific si470x device */ + /* get device and chip versions */ if (si470x_get_all_registers(radio) < 0) { retval = -EIO; - goto err_radio; + goto err_video; } dev_info(&client->dev, "DeviceID=0x%4.4hx ChipID=0x%4.4hx\n", radio->registers[DEVICEID], radio->registers[CHIPID]); + if ((radio->registers[CHIPID] & CHIPID_FIRMWARE) < RADIO_FW_VERSION) { + dev_warn(&client->dev, + "This driver is known to work with " + "firmware version %hu,\n", RADIO_FW_VERSION); + dev_warn(&client->dev, + "but the device has firmware version %hu.\n", + radio->registers[CHIPID] & CHIPID_FIRMWARE); + version_warning = 1; + } + + /* give out version warning */ + if (version_warning == 1) { + dev_warn(&client->dev, + "If you have some trouble using this driver,\n"); + dev_warn(&client->dev, + "please report to V4L ML at " + "linux-media@vger.kernel.org\n"); + } /* set initial frequency */ si470x_set_freq(radio, 87.5 * FREQ_MUL); /* available in all regions */ /* register video device */ - retval = video_register_device(radio->videodev, VFL_TYPE_RADIO, -1); + retval = video_register_device(radio->videodev, VFL_TYPE_RADIO, + radio_nr); if (retval) { dev_warn(&client->dev, "Could not register video device\n"); goto err_all; } - i2c_set_clientdata(client, radio); return 0; err_all: +err_video: video_device_release(radio->videodev); err_radio: kfree(radio); @@ -210,6 +338,10 @@ err_initial: return retval; } + +/* + * si470x_i2c_remove - remove the device + */ static __devexit int si470x_i2c_remove(struct i2c_client *client) { struct si470x_device *radio = i2c_get_clientdata(client); @@ -221,34 +353,49 @@ static __devexit int si470x_i2c_remove(struct i2c_client *client) return 0; } -static const struct i2c_device_id si470x_i2c_id[] = { - { "si470x", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, si470x_i2c_id); +/* + * si470x_i2c_driver - i2c driver interface + */ static struct i2c_driver si470x_i2c_driver = { .driver = { - .name = "si470x", - .owner = THIS_MODULE, + .name = "si470x", + .owner = THIS_MODULE, }, - .probe = si470x_i2c_probe, - .remove = __devexit_p(si470x_i2c_remove), - .id_table = si470x_i2c_id, + .probe = si470x_i2c_probe, + .remove = __devexit_p(si470x_i2c_remove), + .id_table = si470x_i2c_id, }; + + +/************************************************************************** + * Module Interface + **************************************************************************/ + +/* + * si470x_i2c_init - module init + */ static int __init si470x_i2c_init(void) { + printk(KERN_INFO DRIVER_DESC ", Version " DRIVER_VERSION "\n"); return i2c_add_driver(&si470x_i2c_driver); } -module_init(si470x_i2c_init); + +/* + * si470x_i2c_exit - module exit + */ static void __exit si470x_i2c_exit(void) { i2c_del_driver(&si470x_i2c_driver); } + + +module_init(si470x_i2c_init); module_exit(si470x_i2c_exit); -MODULE_DESCRIPTION("i2c radio driver for si470x fm radio receivers"); -MODULE_AUTHOR("Joonyoung Shim "); MODULE_LICENSE("GPL"); +MODULE_AUTHOR(DRIVER_AUTHOR); +MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_VERSION(DRIVER_VERSION); diff --git a/linux/drivers/media/radio/si470x/radio-si470x-usb.c b/linux/drivers/media/radio/si470x/radio-si470x-usb.c index 2f5cf6c72..f2d0e1ddb 100644 --- a/linux/drivers/media/radio/si470x/radio-si470x-usb.c +++ b/linux/drivers/media/radio/si470x/radio-si470x-usb.c @@ -138,16 +138,12 @@ MODULE_PARM_DESC(max_rds_errors, "RDS maximum block errors: *1*"); /************************************************************************** - * Software/Hardware Versions + * Software/Hardware Versions from Scratch Page **************************************************************************/ #define RADIO_SW_VERSION_NOT_BOOTLOADABLE 6 #define RADIO_SW_VERSION 7 -#define RADIO_SW_VERSION_CURRENT 15 #define RADIO_HW_VERSION 1 -#define SCRATCH_PAGE_SW_VERSION 1 -#define SCRATCH_PAGE_HW_VERSION 2 - /************************************************************************** @@ -745,6 +741,7 @@ static int si470x_usb_driver_probe(struct usb_interface *intf, struct usb_host_interface *iface_desc; struct usb_endpoint_descriptor *endpoint; int i, int_end_size, retval = 0; + unsigned char version_warning = 0; /* private data allocation and initialization */ radio = kzalloc(sizeof(struct si470x_device), GFP_KERNEL); @@ -801,13 +798,22 @@ static int si470x_usb_driver_probe(struct usb_interface *intf, sizeof(si470x_viddev_template)); video_set_drvdata(radio->videodev, radio); - /* show some infos about the specific si470x device */ + /* get device and chip versions */ if (si470x_get_all_registers(radio) < 0) { retval = -EIO; goto err_video; } dev_info(&intf->dev, "DeviceID=0x%4.4hx ChipID=0x%4.4hx\n", radio->registers[DEVICEID], radio->registers[CHIPID]); + if ((radio->registers[CHIPID] & CHIPID_FIRMWARE) < RADIO_FW_VERSION) { + dev_warn(&intf->dev, + "This driver is known to work with " + "firmware version %hu,\n", RADIO_FW_VERSION); + dev_warn(&intf->dev, + "but the device has firmware version %hu.\n", + radio->registers[CHIPID] & CHIPID_FIRMWARE); + version_warning = 1; + } /* get software and hardware versions */ if (si470x_get_scratch_page_versions(radio) < 0) { @@ -816,16 +822,27 @@ static int si470x_usb_driver_probe(struct usb_interface *intf, } dev_info(&intf->dev, "software version %d, hardware version %d\n", radio->software_version, radio->hardware_version); - - /* check if device and firmware is current */ - if ((radio->registers[CHIPID] & CHIPID_FIRMWARE) - < RADIO_SW_VERSION_CURRENT) { + if (radio->software_version < RADIO_SW_VERSION) { dev_warn(&intf->dev, "This driver is known to work with " - "firmware version %hu,\n", RADIO_SW_VERSION_CURRENT); + "software version %hu,\n", RADIO_SW_VERSION); dev_warn(&intf->dev, - "but the device has firmware version %hu.\n", - radio->registers[CHIPID] & CHIPID_FIRMWARE); + "but the device has software version %hu.\n", + radio->software_version); + version_warning = 1; + } + if (radio->hardware_version < RADIO_HW_VERSION) { + dev_warn(&intf->dev, + "This driver is known to work with " + "hardware version %hu,\n", RADIO_HW_VERSION); + dev_warn(&intf->dev, + "but the device has hardware version %hu.\n", + radio->hardware_version); + version_warning = 1; + } + + /* give out version warning */ + if (version_warning == 1) { dev_warn(&intf->dev, "If you have some trouble using this driver,\n"); dev_warn(&intf->dev, diff --git a/linux/drivers/media/radio/si470x/radio-si470x.h b/linux/drivers/media/radio/si470x/radio-si470x.h index 791c367be..f931789c2 100644 --- a/linux/drivers/media/radio/si470x/radio-si470x.h +++ b/linux/drivers/media/radio/si470x/radio-si470x.h @@ -42,6 +42,7 @@ #include + /************************************************************************** * Register Definitions **************************************************************************/ @@ -134,6 +135,7 @@ #define RDSD_RDSD 0xffff /* bits 15..00: RDS Block D Data (Si4701 only) */ + /************************************************************************** * General Driver Definitions **************************************************************************/ @@ -144,9 +146,19 @@ struct si470x_device { struct video_device *videodev; -#if defined(CONFIG_I2C_SI470X) || defined(CONFIG_I2C_SI470X_MODULE) - struct i2c_client *client; -#endif + /* driver management */ + unsigned int users; + + /* Silabs internal registers (0..15) */ + unsigned short registers[RADIO_REGISTER_NUM]; + + /* RDS receive buffer */ + wait_queue_head_t read_queue; + struct mutex lock; /* buffer locking */ + unsigned char *buffer; /* size is always multiple of three */ + unsigned int buf_size; + unsigned int rd_index; + unsigned int wr_index; #if defined(CONFIG_USB_SI470X) || defined(CONFIG_USB_SI470X_MODULE) /* reference to USB and video device */ @@ -167,21 +179,26 @@ struct si470x_device { unsigned char disconnected; struct mutex disconnect_lock; #endif - unsigned int users; - - /* Silabs internal registers (0..15) */ - unsigned short registers[RADIO_REGISTER_NUM]; - /* RDS receive buffer */ - wait_queue_head_t read_queue; - struct mutex lock; /* buffer locking */ - unsigned char *buffer; /* size is always multiple of three */ - unsigned int buf_size; - unsigned int rd_index; - unsigned int wr_index; +#if defined(CONFIG_I2C_SI470X) || defined(CONFIG_I2C_SI470X_MODULE) + struct i2c_client *client; +#endif }; + +/************************************************************************** + * Firmware Versions + **************************************************************************/ + +#define RADIO_FW_VERSION 15 + + + +/************************************************************************** + * Frequency Multiplicator + **************************************************************************/ + /* * The frequency is set in units of 62.5 Hz when using V4L2_TUNER_CAP_LOW, * 62.5 kHz otherwise. -- cgit v1.2.3 From f2315820af3c8b9a218c05c0fd44b6f0741c4a35 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 4 Aug 2009 20:07:42 -0300 Subject: Fix incorrect type of tuner for the BeholdTV H6 card From: Beholder Intl. Ltd. Dmitry Belimov Define correct tuner in config. Radio now works fine Priority: normal Signed-off-by: Beholder Intl. Ltd. Dmitry Belimov Signed-off-by: Douglas Schilling Landgraf Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/saa7134/saa7134-cards.c | 2 +- linux/drivers/media/video/saa7134/saa7134-dvb.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/saa7134/saa7134-cards.c b/linux/drivers/media/video/saa7134/saa7134-cards.c index c18b41ee6..40aa654d2 100644 --- a/linux/drivers/media/video/saa7134/saa7134-cards.c +++ b/linux/drivers/media/video/saa7134/saa7134-cards.c @@ -4900,7 +4900,7 @@ struct saa7134_board saa7134_boards[] = { /* Igor Kuznetsov */ .name = "Beholder BeholdTV H6", .audio_clock = 0x00187de7, - .tuner_type = TUNER_PHILIPS_FMD1216ME_MK3, + .tuner_type = TUNER_PHILIPS_FMD1216MEX_MK3, .radio_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, diff --git a/linux/drivers/media/video/saa7134/saa7134-dvb.c b/linux/drivers/media/video/saa7134/saa7134-dvb.c index a5263c391..afd9b7e5c 100644 --- a/linux/drivers/media/video/saa7134/saa7134-dvb.c +++ b/linux/drivers/media/video/saa7134/saa7134-dvb.c @@ -1461,7 +1461,7 @@ static int dvb_init(struct saa7134_dev *dev) if (fe0->dvb.frontend) { dvb_attach(simple_tuner_attach, fe0->dvb.frontend, &dev->i2c_adap, 0x61, - TUNER_PHILIPS_FMD1216ME_MK3); + TUNER_PHILIPS_FMD1216MEX_MK3); } break; case SAA7134_BOARD_AVERMEDIA_A700_PRO: -- cgit v1.2.3 From 0ffdf3c011bae5197f3e30f633d32645be8df021 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 4 Aug 2009 20:11:43 -0300 Subject: saa7134: fix the radio on Avermedia GO 007 FM From: hermann pitton We have support for radio on saa7133/35/31e cards with tda8290/8275(a) and 5.5MHz ceramic filter on the bridge chips since a while. It was previously not tested, if this card supports it too, but the old "ghost" radio with wrong filters doesn't work anymore. Thanks go to Pham Thanh Nam and Laszlo Kustan for reporting it working on that input. Priority: normal Signed-off-by: hermann pitton Signed-off-by: Douglas Schilling Landgraf Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/saa7134/saa7134-cards.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/saa7134/saa7134-cards.c b/linux/drivers/media/video/saa7134/saa7134-cards.c index 40aa654d2..3ab7732e6 100644 --- a/linux/drivers/media/video/saa7134/saa7134-cards.c +++ b/linux/drivers/media/video/saa7134/saa7134-cards.c @@ -1633,7 +1633,7 @@ struct saa7134_board saa7134_boards[] = { }}, .radio = { .name = name_radio, - .amux = LINE1, + .amux = TV, .gpio = 0x00300001, }, .mute = { -- cgit v1.2.3 From 84b33bda3d8447bc0f28a9eae22039ec4a0bb3bf Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 4 Aug 2009 20:33:42 -0300 Subject: em28xx: fix: some webcams don't have audio inputs From: Mauro Carvalho Chehab Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/em28xx/em28xx-cards.c | 3 +++ linux/drivers/media/video/em28xx/em28xx-core.c | 2 +- linux/drivers/media/video/em28xx/em28xx.h | 1 + 3 files changed, 5 insertions(+), 1 deletion(-) (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 795fd16a5..2f4777f76 100644 --- a/linux/drivers/media/video/em28xx/em28xx-cards.c +++ b/linux/drivers/media/video/em28xx/em28xx-cards.c @@ -234,6 +234,7 @@ struct em28xx_board em28xx_boards[] = { .xclk = EM28XX_XCLK_FREQUENCY_48MHZ, .tuner_type = TUNER_ABSENT, .is_webcam = 1, + .no_audio = 1, .input = { { .type = EM28XX_VMUX_COMPOSITE1, .vmux = 0, @@ -261,6 +262,7 @@ struct em28xx_board em28xx_boards[] = { .name = "Unknown EM2750/28xx video grabber", .tuner_type = TUNER_ABSENT, .is_webcam = 1, /* To enable sensor probe */ + .no_audio = 1, }, [EM2750_BOARD_DLCW_130] = { /* Beijing Huaqi Information Digital Technology Co., Ltd */ @@ -481,6 +483,7 @@ struct em28xx_board em28xx_boards[] = { .name = "Silvercrest Webcam 1.3mpix", .tuner_type = TUNER_ABSENT, .is_webcam = 1, + .no_audio = 1, .input = { { .type = EM28XX_VMUX_COMPOSITE1, .vmux = 0, diff --git a/linux/drivers/media/video/em28xx/em28xx-core.c b/linux/drivers/media/video/em28xx/em28xx-core.c index f24af40df..a1de593ec 100644 --- a/linux/drivers/media/video/em28xx/em28xx-core.c +++ b/linux/drivers/media/video/em28xx/em28xx-core.c @@ -494,7 +494,7 @@ int em28xx_audio_setup(struct em28xx *dev) /* If device doesn't support Usb Audio Class, use vendor class */ if (!dev->has_audio_class) - dev->has_alsa_audio = 1; + dev->has_alsa_audio = ~dev->board.no_audio; dev->audio_mode.has_audio = 1; diff --git a/linux/drivers/media/video/em28xx/em28xx.h b/linux/drivers/media/video/em28xx/em28xx.h index df7fe9af7..3c4cd00b2 100644 --- a/linux/drivers/media/video/em28xx/em28xx.h +++ b/linux/drivers/media/video/em28xx/em28xx.h @@ -397,6 +397,7 @@ struct em28xx_board { unsigned int has_dvb:1; unsigned int has_snapshot_button:1; unsigned int is_webcam:1; + unsigned int no_audio:1; unsigned int valid:1; unsigned char xclk, i2c_speed; -- cgit v1.2.3 From ba28fa4eca1b69daa57024d9c0c9fe880ac0b2c9 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 4 Aug 2009 22:00:24 -0300 Subject: drivers/media/video/gspca: introduce missing kfree MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: Julia Lawall Error handling code following a kmalloc should free the allocated data. Priority: normal Signed-off-by: Julia Lawall Acked-by: Erik Andrén Signed-off-by: Douglas Schilling Landgraf Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/gspca/m5602/m5602_s5k83a.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.c b/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.c index 7127321ac..6b89f33a4 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.c @@ -178,8 +178,10 @@ sensor_found: sens_priv->settings = kmalloc(sizeof(s32)*ARRAY_SIZE(s5k83a_ctrls), GFP_KERNEL); - if (!sens_priv->settings) + if (!sens_priv->settings) { + kfree(sens_priv); return -ENOMEM; + } sd->gspca_dev.cam.cam_mode = s5k83a_modes; sd->gspca_dev.cam.nmodes = ARRAY_SIZE(s5k83a_modes); -- cgit v1.2.3 From fbcd7beea764d905edd7aec98388395e0d112a9d Mon Sep 17 00:00:00 2001 From: Patrick Boettcher Date: Wed, 5 Aug 2009 16:46:38 +0200 Subject: [patch] Added Support for STK7700D (DVB) From: Pete Hildebrandt This patch adds support for the STK7700D USB-DVB-Device. lsusb identifies it as: idVendor 0x1164 YUAN High-Tech Development Co., Ltd idProduct 0x1efc iProduct 2 STK7700D The device is build into a Samsung R55-T5500 notebook. Priority: normal Signed-off-by: Pete Hildebrandt 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, 7 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 8ec98f6e0..81cda8061 100644 --- a/linux/drivers/media/dvb/dvb-usb/dib0700_devices.c +++ b/linux/drivers/media/dvb/dvb-usb/dib0700_devices.c @@ -1501,6 +1501,7 @@ struct usb_device_id dib0700_usb_id_table[] = { { 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) }, + { USB_DEVICE(USB_VID_YUAN, USB_PID_YUAN_STK7700D) }, { 0 } /* Terminating entry */ }; MODULE_DEVICE_TABLE(usb, dib0700_usb_id_table); @@ -1826,7 +1827,7 @@ struct dvb_usb_device_properties dib0700_devices[] = { }, }, - .num_device_descs = 8, + .num_device_descs = 9, .devices = { { "Terratec Cinergy HT USB XE", { &dib0700_usb_id_table[27], NULL }, @@ -1860,7 +1861,10 @@ struct dvb_usb_device_properties dib0700_devices[] = { { &dib0700_usb_id_table[51], NULL }, { NULL }, }, - + { "YUAN High-Tech STK7700D", + { &dib0700_usb_id_table[54], 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 9593b7289..6eccce1a7 100644 --- a/linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h +++ b/linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h @@ -252,6 +252,7 @@ #define USB_PID_YUAN_STK7700PH 0x1f08 #define USB_PID_YUAN_PD378S 0x2edc #define USB_PID_YUAN_MC770 0x0871 +#define USB_PID_YUAN_STK7700D 0x1efc #define USB_PID_DW2102 0x2102 #define USB_PID_XTENSIONS_XD_380 0x0381 #define USB_PID_TELESTAR_STARSTICK_2 0x8000 -- cgit v1.2.3 From 2f25ba7a8bf7364ee4bd4aee7b283b0ea273b160 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 5 Aug 2009 12:58:47 -0300 Subject: media/zr364xx: fix build errors From: Randy Dunlap Fix build errors in zr364xx by adding selects: zr364xx.c:(.text+0x195ed7): undefined reference to `videobuf_streamon' zr364xx.c:(.text+0x196030): undefined reference to `videobuf_dqbuf' zr364xx.c:(.text+0x1960c4): undefined reference to `videobuf_qbuf' zr364xx.c:(.text+0x196123): undefined reference to `videobuf_querybuf' zr364xx.c:(.text+0x196182): undefined reference to `videobuf_reqbufs' zr364xx.c:(.text+0x196224): undefined reference to `videobuf_queue_is_busy' zr364xx.c:(.text+0x196390): undefined reference to `videobuf_vmalloc_free' zr364xx.c:(.text+0x196571): undefined reference to `videobuf_iolock' zr364xx.c:(.text+0x196678): undefined reference to `videobuf_mmap_mapper' zr364xx.c:(.text+0x196760): undefined reference to `videobuf_poll_stream' zr364xx.c:(.text+0x19689a): undefined reference to `videobuf_read_one' zr364xx.c:(.text+0x1969ec): undefined reference to `videobuf_mmap_free' zr364xx.c:(.text+0x197862): undefined reference to `videobuf_queue_vmalloc_init' zr364xx.c:(.text+0x197a28): undefined reference to `videobuf_streamoff' zr364xx.c:(.text+0x198203): undefined reference to `videobuf_to_vmalloc' zr364xx.c:(.text+0x198603): undefined reference to `videobuf_streamoff' drivers/built-in.o: In function `free_buffer': zr364xx.c:(.text+0x19930c): undefined reference to `videobuf_vmalloc_free' drivers/built-in.o: In function `zr364xx_open': zr364xx.c:(.text+0x19a7de): undefined reference to `videobuf_queue_vmalloc_init' drivers/built-in.o: In function `read_pipe_completion': zr364xx.c:(.text+0x19b17f): undefined reference to `videobuf_to_vmalloc' Priority: normal Signed-off-by: Randy Dunlap Signed-off-by: Douglas Schilling Landgraf Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/Kconfig | 2 ++ 1 file changed, 2 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/Kconfig b/linux/drivers/media/video/Kconfig index 8460013a0..e8a6e4de4 100644 --- a/linux/drivers/media/video/Kconfig +++ b/linux/drivers/media/video/Kconfig @@ -991,6 +991,8 @@ source "drivers/media/video/pwc/Kconfig" config USB_ZR364XX tristate "USB ZR364XX Camera support" depends on VIDEO_V4L2 + select VIDEOBUF_GEN + select VIDEOBUF_VMALLOC ---help--- Say Y here if you want to connect this type of camera to your computer's USB port. -- cgit v1.2.3 From d3f91b69f01b8f1c132d1037137ef9b6fba4a142 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 5 Aug 2009 13:07:10 -0300 Subject: cxusb, d680 dmbth use unified lgs8gxx code instead of lgs8gl5 From: David T.L. Wong Use unified lgs8gxx frontend instead of reverse engineered lgs8gl5 frontend. After this patch, lgs8gl5 frontend could be mark as deprecated. Future development should base on unified lgs8gxx frontend. Priority: normal Signed-off-by: David T.L. Wong Signed-off-by: Douglas Schilling Landgraf Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/dvb-usb/cxusb.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/dvb-usb/cxusb.c b/linux/drivers/media/dvb/dvb-usb/cxusb.c index f467cad8a..05da84c90 100644 --- a/linux/drivers/media/dvb/dvb-usb/cxusb.c +++ b/linux/drivers/media/dvb/dvb-usb/cxusb.c @@ -38,7 +38,7 @@ #include "mxl5005s.h" #include "dib7000p.h" #include "dib0070.h" -#include "lgs8gl5.h" +#include "lgs8gxx.h" /* debug */ static int dvb_usb_cxusb_debug; @@ -1097,8 +1097,18 @@ static int cxusb_nano2_frontend_attach(struct dvb_usb_adapter *adap) return -EIO; } -static struct lgs8gl5_config lgs8gl5_cfg = { +static struct lgs8gxx_config d680_lgs8gl5_cfg = { + .prod = LGS8GXX_PROD_LGS8GL5, .demod_address = 0x19, + .serial_ts = 0, + .ts_clk_pol = 0, + .ts_clk_gated = 1, + .if_clk_freq = 30400, /* 30.4 MHz */ + .if_freq = 5725, /* 5.725 MHz */ + .if_neg_center = 0, + .ext_adc = 0, + .adc_signed = 0, + .if_neg_edge = 0, }; static int cxusb_d680_dmb_frontend_attach(struct dvb_usb_adapter *adap) @@ -1138,7 +1148,7 @@ static int cxusb_d680_dmb_frontend_attach(struct dvb_usb_adapter *adap) msleep(100); /* Attach frontend */ - adap->fe = dvb_attach(lgs8gl5_attach, &lgs8gl5_cfg, &d->i2c_adap); + adap->fe = dvb_attach(lgs8gxx_attach, &d680_lgs8gl5_cfg, &d->i2c_adap); if (adap->fe == NULL) return -EIO; -- cgit v1.2.3 From 431b7b75e8f6cc9c89cfca9f7e307731c3b07d0d Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Thu, 6 Aug 2009 01:06:31 +0200 Subject: soc-camera: fix recursive locking in .buf_queue() From: Guennadi Liakhovetski The .buf_queue() V4L2 driver method is called under spinlock_irqsave(q->irqlock,...), don't take the lock again inside the function. Reported-by: Antonio Ospite Signed-off-by: Guennadi Liakhovetski --- drivers/media/video/mx1_camera.c | 6 +----- drivers/media/video/mx3_camera.c | 19 ++++++++++--------- drivers/media/video/pxa_camera.c | 6 +----- drivers/media/video/sh_mobile_ceu_camera.c | 5 +---- 4 files changed, 13 insertions(+), 23 deletions(-) --- linux/drivers/media/video/mx1_camera.c | 6 +----- linux/drivers/media/video/mx3_camera.c | 19 ++++++++++--------- linux/drivers/media/video/pxa_camera.c | 6 +----- linux/drivers/media/video/sh_mobile_ceu_camera.c | 5 +---- 4 files changed, 13 insertions(+), 23 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/mx1_camera.c b/linux/drivers/media/video/mx1_camera.c index 2d075205b..736c31d23 100644 --- a/linux/drivers/media/video/mx1_camera.c +++ b/linux/drivers/media/video/mx1_camera.c @@ -234,6 +234,7 @@ static int mx1_camera_setup_dma(struct mx1_camera_dev *pcdev) return ret; } +/* Called under spinlock_irqsave(&pcdev->lock, ...) */ static void mx1_videobuf_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) { @@ -241,13 +242,10 @@ static void mx1_videobuf_queue(struct videobuf_queue *vq, struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); struct mx1_camera_dev *pcdev = ici->priv; struct mx1_buffer *buf = container_of(vb, struct mx1_buffer, vb); - unsigned long flags; dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__, vb, vb->baddr, vb->bsize); - spin_lock_irqsave(&pcdev->lock, flags); - list_add_tail(&vb->queue, &pcdev->capture); vb->state = VIDEOBUF_ACTIVE; @@ -264,8 +262,6 @@ static void mx1_videobuf_queue(struct videobuf_queue *vq, __raw_writel(temp, pcdev->base + CSICR1); } } - - spin_unlock_irqrestore(&pcdev->lock, flags); } static void mx1_videobuf_release(struct videobuf_queue *vq, diff --git a/linux/drivers/media/video/mx3_camera.c b/linux/drivers/media/video/mx3_camera.c index e605c076e..9770cb793 100644 --- a/linux/drivers/media/video/mx3_camera.c +++ b/linux/drivers/media/video/mx3_camera.c @@ -332,7 +332,10 @@ static enum pixel_fmt fourcc_to_ipu_pix(__u32 fourcc) } } -/* Called with .vb_lock held */ +/* + * Called with .vb_lock mutex held and + * under spinlock_irqsave(&mx3_cam->lock, ...) + */ static void mx3_videobuf_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) { @@ -346,7 +349,8 @@ static void mx3_videobuf_queue(struct videobuf_queue *vq, struct idmac_video_param *video = &ichan->params.video; const struct soc_camera_data_format *data_fmt = icd->current_fmt; dma_cookie_t cookie; - unsigned long flags; + + BUG_ON(!irqs_disabled()); /* This is the configuration of one sg-element */ video->out_pixel_fmt = fourcc_to_ipu_pix(data_fmt->fourcc); @@ -359,8 +363,6 @@ static void mx3_videobuf_queue(struct videobuf_queue *vq, memset((void *)vb->baddr, 0xaa, vb->bsize); #endif - spin_lock_irqsave(&mx3_cam->lock, flags); - list_add_tail(&vb->queue, &mx3_cam->capture); if (!mx3_cam->active) { @@ -370,24 +372,23 @@ static void mx3_videobuf_queue(struct videobuf_queue *vq, vb->state = VIDEOBUF_QUEUED; } - spin_unlock_irqrestore(&mx3_cam->lock, flags); + spin_unlock_irq(&mx3_cam->lock); cookie = txd->tx_submit(txd); dev_dbg(&icd->dev, "Submitted cookie %d DMA 0x%08x\n", cookie, sg_dma_address(&buf->sg)); + + spin_lock_irq(&mx3_cam->lock); + if (cookie >= 0) return; /* Submit error */ vb->state = VIDEOBUF_PREPARED; - spin_lock_irqsave(&mx3_cam->lock, flags); - list_del_init(&vb->queue); if (mx3_cam->active == buf) mx3_cam->active = NULL; - - spin_unlock_irqrestore(&mx3_cam->lock, flags); } /* Called with .vb_lock held */ diff --git a/linux/drivers/media/video/pxa_camera.c b/linux/drivers/media/video/pxa_camera.c index 3f1b63e4e..92fb8b191 100644 --- a/linux/drivers/media/video/pxa_camera.c +++ b/linux/drivers/media/video/pxa_camera.c @@ -624,6 +624,7 @@ static void pxa_camera_stop_capture(struct pxa_camera_dev *pcdev) dev_dbg(pcdev->soc_host.dev, "%s\n", __func__); } +/* Called under spinlock_irqsave(&pcdev->lock, ...) */ static void pxa_videobuf_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) { @@ -631,13 +632,10 @@ static void pxa_videobuf_queue(struct videobuf_queue *vq, struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); struct pxa_camera_dev *pcdev = ici->priv; struct pxa_buffer *buf = container_of(vb, struct pxa_buffer, vb); - unsigned long flags; dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %d active=%p\n", __func__, vb, vb->baddr, vb->bsize, pcdev->active); - spin_lock_irqsave(&pcdev->lock, flags); - list_add_tail(&vb->queue, &pcdev->capture); vb->state = VIDEOBUF_ACTIVE; @@ -645,8 +643,6 @@ static void pxa_videobuf_queue(struct videobuf_queue *vq, if (!pcdev->active) pxa_camera_start_capture(pcdev); - - spin_unlock_irqrestore(&pcdev->lock, flags); } static void pxa_videobuf_release(struct videobuf_queue *vq, diff --git a/linux/drivers/media/video/sh_mobile_ceu_camera.c b/linux/drivers/media/video/sh_mobile_ceu_camera.c index 7ea2a0edf..1bae28a98 100644 --- a/linux/drivers/media/video/sh_mobile_ceu_camera.c +++ b/linux/drivers/media/video/sh_mobile_ceu_camera.c @@ -283,27 +283,24 @@ out: return ret; } +/* Called under spinlock_irqsave(&pcdev->lock, ...) */ static void sh_mobile_ceu_videobuf_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) { struct soc_camera_device *icd = vq->priv_data; struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); struct sh_mobile_ceu_dev *pcdev = ici->priv; - unsigned long flags; dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %zd\n", __func__, vb, vb->baddr, vb->bsize); vb->state = VIDEOBUF_QUEUED; - spin_lock_irqsave(&pcdev->lock, flags); list_add_tail(&vb->queue, &pcdev->capture); if (!pcdev->active) { pcdev->active = vb; sh_mobile_ceu_capture(pcdev); } - - spin_unlock_irqrestore(&pcdev->lock, flags); } static void sh_mobile_ceu_videobuf_release(struct videobuf_queue *vq, -- cgit v1.2.3 From 672911c86336621bf8d82bb070c84d7082e53a05 Mon Sep 17 00:00:00 2001 From: Douglas Schilling Landgraf Date: Thu, 6 Aug 2009 12:52:11 -0300 Subject: em28xx: fix empire auto-detect From: Douglas Schilling Landgraf Fixed eeprom hash table Priority: normal Signed-off-by: Douglas Schilling Landgraf --- linux/drivers/media/video/em28xx/em28xx-cards.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (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 2f4777f76..5b33e2dd1 100644 --- a/linux/drivers/media/video/em28xx/em28xx-cards.c +++ b/linux/drivers/media/video/em28xx/em28xx-cards.c @@ -1729,7 +1729,7 @@ static struct em28xx_hash_table em28xx_eeprom_hash[] = { {0x6ce05a8f, EM2820_BOARD_PROLINK_PLAYTV_USB2, TUNER_YMEC_TVF_5533MF}, {0x72cc5a8b, EM2820_BOARD_PROLINK_PLAYTV_BOX4_USB2, TUNER_YMEC_TVF_5533MF}, {0x966a0441, EM2880_BOARD_KWORLD_DVB_310U, TUNER_XC2028}, - {0x9567eb1a, EM2880_BOARD_EMPIRE_DUAL_TV, TUNER_XC2028}, + {0x166a0441, EM2880_BOARD_EMPIRE_DUAL_TV, TUNER_XC2028}, {0xcee44a99, EM2882_BOARD_EVGA_INDTUBE, TUNER_XC2028}, {0xb8846b20, EM2881_BOARD_PINNACLE_HYBRID_PRO, TUNER_XC2028}, }; -- cgit v1.2.3 From 65a908e5b37515512c5cf89fa74a533c77e5ec62 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 6 Aug 2009 21:03:35 -0300 Subject: mt9v011: Add support for controlling frame rates From: Mauro Carvalho Chehab Implement g_parm/s_parm ioctls. Those are used to check the current frame rate (in fps) and to set it to a value. In practice, there are only 15 possible different speeds, due to chip limits. Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/mt9v011.c | 89 ++++++++++++++++++++++++++++++++++++- 1 file changed, 87 insertions(+), 2 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/mt9v011.c b/linux/drivers/media/video/mt9v011.c index c9706b889..a76d02d40 100644 --- a/linux/drivers/media/video/mt9v011.c +++ b/linux/drivers/media/video/mt9v011.c @@ -166,7 +166,7 @@ static void set_balance(struct v4l2_subdev *sd) mt9v011_write(sd, R2D_MT9V011_RED_GAIN, red_gain); } -static void calc_fps(struct v4l2_subdev *sd) +static void calc_fps(struct v4l2_subdev *sd, u32 *numerator, u32 *denominator) { struct mt9v011 *core = to_mt9v011(sd); unsigned height, width, hblank, vblank, speed; @@ -189,6 +189,51 @@ static void calc_fps(struct v4l2_subdev *sd) v4l2_dbg(1, debug, sd, "Programmed to %u.%03u fps (%d pixel clcks)\n", tmp / 1000, tmp % 1000, t_time); + + if (numerator && denominator) { + *numerator = 1000; + *denominator = (u32)frames_per_ms; + } +} + +static u16 calc_speed(struct v4l2_subdev *sd, u32 numerator, u32 denominator) +{ + struct mt9v011 *core = to_mt9v011(sd); + unsigned height, width, hblank, vblank; + unsigned row_time, line_time; + u64 t_time, speed; + + /* Avoid bogus calculus */ + if (!numerator || !denominator) + return 0; + + height = mt9v011_read(sd, R03_MT9V011_HEIGHT); + width = mt9v011_read(sd, R04_MT9V011_WIDTH); + hblank = mt9v011_read(sd, R05_MT9V011_HBLANK); + vblank = mt9v011_read(sd, R06_MT9V011_VBLANK); + + row_time = width + 113 + hblank; + line_time = height + vblank + 1; + + t_time = core->xtal * ((u64)numerator); + /* round to the closest value */ + t_time += denominator / 2; + do_div(t_time, denominator); + + speed = t_time; + do_div(speed, row_time * line_time); + + /* Avoid having a negative value for speed */ + if (speed < 2) + speed = 0; + else + speed -= 2; + + /* Avoid speed overflow */ + if (speed > 15) + return 15; + + return (u16)speed; } static void set_res(struct v4l2_subdev *sd) @@ -217,7 +262,7 @@ static void set_res(struct v4l2_subdev *sd) mt9v011_write(sd, R03_MT9V011_HEIGHT, core->height); mt9v011_write(sd, R06_MT9V011_VBLANK, 508 - core->height); - calc_fps(sd); + calc_fps(sd, NULL, NULL); }; static int mt9v011_reset(struct v4l2_subdev *sd, u32 val) @@ -332,6 +377,44 @@ static int mt9v011_try_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) return 0; } +static int mt9v011_g_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *parms) +{ + struct v4l2_captureparm *cp = &parms->parm.capture; + + if (parms->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + + memset(cp, 0, sizeof(struct v4l2_captureparm)); + cp->capability = V4L2_CAP_TIMEPERFRAME; + calc_fps(sd, + &cp->timeperframe.numerator, + &cp->timeperframe.denominator); + + return 0; +} + +static int mt9v011_s_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *parms) +{ + struct v4l2_captureparm *cp = &parms->parm.capture; + struct v4l2_fract *tpf = &cp->timeperframe; + u16 speed; + + if (parms->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + if (cp->extendedmode != 0) + return -EINVAL; + + speed = calc_speed(sd, tpf->numerator, tpf->denominator); + + mt9v011_write(sd, R0A_MT9V011_CLK_SPEED, speed); + v4l2_dbg(1, debug, sd, "Setting speed to %d\n", speed); + + /* Recalculate and update fps info */ + calc_fps(sd, &tpf->numerator, &tpf->denominator); + + return 0; +} + static int mt9v011_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) { struct v4l2_pix_format *pix = &fmt->fmt.pix; @@ -429,6 +512,8 @@ static const struct v4l2_subdev_video_ops mt9v011_video_ops = { .enum_fmt = mt9v011_enum_fmt, .try_fmt = mt9v011_try_fmt, .s_fmt = mt9v011_s_fmt, + .g_parm = mt9v011_g_parm, + .s_parm = mt9v011_s_parm, }; static const struct v4l2_subdev_ops mt9v011_ops = { -- cgit v1.2.3 From 4eec1f6fb9e9c0c57fac129490eadead77179246 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 6 Aug 2009 21:53:59 -0300 Subject: em28xx: Allow changing fps on webcams From: Mauro Carvalho Chehab em28xx doesn't have temporal scaling. However, on webcams, sensors are capable of changing the output rate. So, VIDIOC_[G|S]_PARM ioctls should be passed to the sensor for it to properly set frame rate. Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/em28xx/em28xx-video.c | 37 +++++++++++++++++++++++++ 1 file changed, 37 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/em28xx/em28xx-video.c b/linux/drivers/media/video/em28xx/em28xx-video.c index 258cd38ce..f2d9564e9 100644 --- a/linux/drivers/media/video/em28xx/em28xx-video.c +++ b/linux/drivers/media/video/em28xx/em28xx-video.c @@ -899,6 +899,41 @@ static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *norm) return 0; } +static int vidioc_g_parm(struct file *file, void *priv, + struct v4l2_streamparm *p) +{ + struct em28xx_fh *fh = priv; + struct em28xx *dev = fh->dev; + int rc = 0; + + if (p->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + + if (dev->board.is_webcam) + rc = v4l2_device_call_until_err(&dev->v4l2_dev, 0, + video, g_parm, p); + else + v4l2_video_std_frame_period(dev->norm, + &p->parm.capture.timeperframe); + + return rc; +} + +static int vidioc_s_parm(struct file *file, void *priv, + struct v4l2_streamparm *p) +{ + struct em28xx_fh *fh = priv; + struct em28xx *dev = fh->dev; + + if (!dev->board.is_webcam) + return -EINVAL; + + if (p->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + + return v4l2_device_call_until_err(&dev->v4l2_dev, 0, video, s_parm, p); +} + static const char *iname[] = { [EM28XX_VMUX_COMPOSITE1] = "Composite1", [EM28XX_VMUX_COMPOSITE2] = "Composite2", @@ -2011,6 +2046,8 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = { .vidioc_qbuf = vidioc_qbuf, .vidioc_dqbuf = vidioc_dqbuf, .vidioc_s_std = vidioc_s_std, + .vidioc_g_parm = vidioc_g_parm, + .vidioc_s_parm = vidioc_s_parm, .vidioc_enum_input = vidioc_enum_input, .vidioc_g_input = vidioc_g_input, .vidioc_s_input = vidioc_s_input, -- cgit v1.2.3 From 124a5014e044c9b27016719a40c1dcf0b77210bd Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 7 Aug 2009 01:09:54 -0300 Subject: m9v011: add vflip/hflip controls to control mirror/upside down From: Mauro Carvalho Chehab Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/mt9v011.c | 53 +++++++++++++++++++++++++++++++++++-- 1 file changed, 51 insertions(+), 2 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/mt9v011.c b/linux/drivers/media/video/mt9v011.c index a76d02d40..70d359d84 100644 --- a/linux/drivers/media/video/mt9v011.c +++ b/linux/drivers/media/video/mt9v011.c @@ -62,13 +62,34 @@ static struct v4l2_queryctrl mt9v011_qctrl[] = { .step = 1, .default_value = 0, .flags = 0, - }, + }, { + .id = V4L2_CID_HFLIP, + .type = V4L2_CTRL_TYPE_BOOLEAN, + .name = "Mirror", + .minimum = 0, + .maximum = 1, + .step = 1, + .default_value = 0, + .flags = 0, + }, { + .id = V4L2_CID_VFLIP, + .type = V4L2_CTRL_TYPE_BOOLEAN, + .name = "Vflip", + .minimum = 0, + .maximum = 1, + .step = 1, + .default_value = 0, + .flags = 0, + }, { + } }; struct mt9v011 { struct v4l2_subdev sd; unsigned width, height; unsigned xtal; + unsigned hflip:1; + unsigned vflip:1; u16 global_gain, red_bal, blue_bal; }; @@ -141,7 +162,6 @@ static const struct i2c_reg_value mt9v011_init_default[] = { { R0A_MT9V011_CLK_SPEED, 0x0000 }, { R1E_MT9V011_DIGITAL_ZOOM, 0x0000 }, - { R20_MT9V011_READ_MODE, 0x1000 }, { R07_MT9V011_OUT_CTRL, 0x0002 }, /* chip enable */ }; @@ -265,6 +285,20 @@ static void set_res(struct v4l2_subdev *sd) calc_fps(sd, NULL, NULL); }; +static void set_read_mode(struct v4l2_subdev *sd) +{ + struct mt9v011 *core = to_mt9v011(sd); + unsigned mode = 0x1000; + + if (core->hflip) + mode |= 0x4000; + + if (core->vflip) + mode |= 0x8000; + + mt9v011_write(sd, R20_MT9V011_READ_MODE, mode); +} + static int mt9v011_reset(struct v4l2_subdev *sd, u32 val) { int i; @@ -275,6 +309,7 @@ static int mt9v011_reset(struct v4l2_subdev *sd, u32 val) set_balance(sd); set_res(sd); + set_read_mode(sd); return 0; }; @@ -295,6 +330,12 @@ static int mt9v011_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) case V4L2_CID_BLUE_BALANCE: ctrl->value = core->blue_bal; return 0; + case V4L2_CID_HFLIP: + ctrl->value = core->hflip ? 1 : 0; + return 0; + case V4L2_CID_VFLIP: + ctrl->value = core->vflip ? 1 : 0; + return 0; } return -EINVAL; } @@ -343,6 +384,14 @@ static int mt9v011_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) case V4L2_CID_BLUE_BALANCE: core->blue_bal = ctrl->value; break; + case V4L2_CID_HFLIP: + core->hflip = ctrl->value; + set_read_mode(sd); + return 0; + case V4L2_CID_VFLIP: + core->vflip = ctrl->value; + set_read_mode(sd); + return 0; default: return -EINVAL; } -- cgit v1.2.3 From cc7fbc37dcf48dbb639f032d01717600ccc540ea Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 7 Aug 2009 12:08:02 -0300 Subject: em28xx: fix: some em2710 chips use a different vendor ID From: Mauro Carvalho Chehab Thanks to hermann pitton for pointing this new variation. Priority: normal Tested-by: hermann pitton Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/em28xx/em28xx-cards.c | 2 ++ 1 file changed, 2 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 2f4777f76..6e68d534e 100644 --- a/linux/drivers/media/video/em28xx/em28xx-cards.c +++ b/linux/drivers/media/video/em28xx/em28xx-cards.c @@ -1613,6 +1613,8 @@ struct usb_device_id em28xx_id_table[] = { .driver_info = EM2750_BOARD_UNKNOWN }, { USB_DEVICE(0xeb1a, 0x2800), .driver_info = EM2800_BOARD_UNKNOWN }, + { USB_DEVICE(0xeb1a, 0x2710), + .driver_info = EM2820_BOARD_UNKNOWN }, { USB_DEVICE(0xeb1a, 0x2820), .driver_info = EM2820_BOARD_UNKNOWN }, { USB_DEVICE(0xeb1a, 0x2821), -- cgit v1.2.3 From 3304f06c0482f2180d240ec11da525578d33868a Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 7 Aug 2009 12:13:31 -0300 Subject: em28xx: properly reports some em2710 chips From: Mauro Carvalho Chehab As reported by hermann pitton , some devices has a different chip id for em2710 (likely the older ones): em28xx: New device @ 480 Mbps (eb1a:2710, interface 0, class 0) em28xx #0: Identified as EM2710/EM2750/EM2751 webcam grabber (card=22) em28xx #0: em28xx chip ID = 17 Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/em28xx/em28xx-cards.c | 5 ++++- linux/drivers/media/video/em28xx/em28xx-reg.h | 3 ++- 2 files changed, 6 insertions(+), 2 deletions(-) (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 6e68d534e..9dddd53c7 100644 --- a/linux/drivers/media/video/em28xx/em28xx-cards.c +++ b/linux/drivers/media/video/em28xx/em28xx-cards.c @@ -1914,11 +1914,14 @@ void em28xx_pre_card_setup(struct em28xx *dev) dev->chip_id = rc; switch (dev->chip_id) { + case CHIP_ID_EM2710: + em28xx_info("chip ID is em2710\n"); + break; case CHIP_ID_EM2750: em28xx_info("chip ID is em2750\n"); break; case CHIP_ID_EM2820: - em28xx_info("chip ID is em2710 or em2820\n"); + em28xx_info("chip ID is em2820 (or em2710)\n"); break; case CHIP_ID_EM2840: em28xx_info("chip ID is em2840\n"); diff --git a/linux/drivers/media/video/em28xx/em28xx-reg.h b/linux/drivers/media/video/em28xx/em28xx-reg.h index a2676d63c..6bf84bd78 100644 --- a/linux/drivers/media/video/em28xx/em28xx-reg.h +++ b/linux/drivers/media/video/em28xx/em28xx-reg.h @@ -176,7 +176,8 @@ /* FIXME: Need to be populated with the other chip ID's */ enum em28xx_chip_id { - CHIP_ID_EM2820 = 18, /* Also used by em2710 */ + CHIP_ID_EM2710 = 17, + CHIP_ID_EM2820 = 18, /* Also used by some em2710 */ CHIP_ID_EM2840 = 20, CHIP_ID_EM2750 = 33, CHIP_ID_EM2860 = 34, -- cgit v1.2.3 From 32405a38daa6df56e36a1569031515af7a72f192 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 7 Aug 2009 18:43:00 -0300 Subject: em28xx-cards: remove a code that doesn't seem to affect the webcam From: Mauro Carvalho Chehab Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/em28xx/em28xx-cards.c | 4 ---- 1 file changed, 4 deletions(-) (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 9dddd53c7..27725c0ed 100644 --- a/linux/drivers/media/video/em28xx/em28xx-cards.c +++ b/linux/drivers/media/video/em28xx/em28xx-cards.c @@ -2408,10 +2408,6 @@ void em28xx_card_setup(struct em28xx *dev) em28xx_gpio_set(dev, dev->board.tuner_gpio); em28xx_set_mode(dev, EM28XX_ANALOG_MODE); break; - case EM2820_BOARD_SILVERCREST_WEBCAM: - /* FIXME: need to document the registers bellow */ - em28xx_write_reg(dev, 0x0d, 0x42); - em28xx_write_reg(dev, 0x13, 0x08); } if (dev->board.has_snapshot_button) -- cgit v1.2.3 From 3f5d03feb375c275dac631a9d5819d4d2bc25c46 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 8 Aug 2009 03:14:55 -0300 Subject: em28xx: fix: don't do image interlacing on webcams From: Mauro Carvalho Chehab Due to historical reasons, em28xx driver gets two consecutive frames and fold them into an unique framing, doing interlacing. While this works fine for TV images, this produces two bad effects with webcams: 1) webcam images are progressive. Merging two consecutive images produce interlacing artifacts on the image; 2) since the driver needs to get two frames, it reduces the maximum frame rate by two. Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/em28xx/em28xx-cards.c | 4 +++ linux/drivers/media/video/em28xx/em28xx-core.c | 5 +++- linux/drivers/media/video/em28xx/em28xx-video.c | 40 +++++++++++++++++++------ linux/drivers/media/video/em28xx/em28xx.h | 3 ++ 4 files changed, 42 insertions(+), 10 deletions(-) (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 27725c0ed..594461739 100644 --- a/linux/drivers/media/video/em28xx/em28xx-cards.c +++ b/linux/drivers/media/video/em28xx/em28xx-cards.c @@ -2623,6 +2623,10 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, if (em28xx_hint_sensor(dev) < 0) dev->board.is_webcam = 0; + /* It makes no sense to use de-interlacing mode on webcams */ + if (dev->board.is_webcam) + dev->progressive = 1; + /* Do board specific init and eeprom reading */ em28xx_card_setup(dev); diff --git a/linux/drivers/media/video/em28xx/em28xx-core.c b/linux/drivers/media/video/em28xx/em28xx-core.c index a1de593ec..10da3ad82 100644 --- a/linux/drivers/media/video/em28xx/em28xx-core.c +++ b/linux/drivers/media/video/em28xx/em28xx-core.c @@ -720,7 +720,10 @@ int em28xx_resolution_set(struct em28xx *dev) { int width, height; width = norm_maxw(dev); - height = norm_maxh(dev) >> 1; + height = norm_maxh(dev); + + if (!dev->progressive) + height >>= norm_maxh(dev); em28xx_set_outfmt(dev); diff --git a/linux/drivers/media/video/em28xx/em28xx-video.c b/linux/drivers/media/video/em28xx/em28xx-video.c index f2d9564e9..77ec51dad 100644 --- a/linux/drivers/media/video/em28xx/em28xx-video.c +++ b/linux/drivers/media/video/em28xx/em28xx-video.c @@ -212,15 +212,24 @@ static void em28xx_copy_video(struct em28xx *dev, startread = p; remain = len; - /* Interlaces frame */ - if (buf->top_field) + if (dev->progressive) fieldstart = outp; - else - fieldstart = outp + bytesperline; + else { + /* Interlaces two half frames */ + if (buf->top_field) + fieldstart = outp; + else + fieldstart = outp + bytesperline; + } linesdone = dma_q->pos / bytesperline; currlinedone = dma_q->pos % bytesperline; - offset = linesdone * bytesperline * 2 + currlinedone; + + if (dev->progressive) + offset = linesdone * bytesperline + currlinedone; + else + offset = linesdone * bytesperline * 2 + currlinedone; + startwrite = fieldstart + offset; lencopy = bytesperline - currlinedone; lencopy = lencopy > remain ? remain : lencopy; @@ -398,7 +407,7 @@ static inline int em28xx_isoc_copy(struct em28xx *dev, struct urb *urb) em28xx_isocdbg("Video frame %d, length=%i, %s\n", p[2], len, (p[2] & 1) ? "odd" : "even"); - if (!(p[2] & 1)) { + if (dev->progressive || !(p[2] & 1)) { if (buf != NULL) buffer_filled(dev, dma_q, buf); get_next_buf(dma_q, &buf); @@ -742,7 +751,10 @@ static int vidioc_g_fmt_vid_cap(struct file *file, void *priv, f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; /* FIXME: TOP? NONE? BOTTOM? ALTENATE? */ - f->fmt.pix.field = dev->interlaced ? + if (dev->progressive) + f->fmt.pix.field = V4L2_FIELD_NONE; + else + f->fmt.pix.field = dev->interlaced ? V4L2_FIELD_INTERLACED : V4L2_FIELD_TOP; mutex_unlock(&dev->lock); @@ -806,7 +818,11 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, f->fmt.pix.bytesperline = (dev->width * fmt->depth + 7) >> 3; f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * height; f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; - f->fmt.pix.field = V4L2_FIELD_INTERLACED; + if (dev->progressive) + f->fmt.pix.field = V4L2_FIELD_NONE; + else + f->fmt.pix.field = dev->interlaced ? + V4L2_FIELD_INTERLACED : V4L2_FIELD_TOP; return 0; } @@ -1765,6 +1781,7 @@ static int em28xx_v4l2_open(struct file *filp) struct em28xx *dev; enum v4l2_buf_type fh_type; struct em28xx_fh *fh; + enum v4l2_field field; dev = em28xx_get_device(minor, &fh_type, &radio); @@ -1821,8 +1838,13 @@ static int em28xx_v4l2_open(struct file *filp) dev->users++; + if (dev->progressive) + field = V4L2_FIELD_NONE; + else + field = V4L2_FIELD_INTERLACED; + videobuf_queue_vmalloc_init(&fh->vb_vidq, &em28xx_video_qops, - NULL, &dev->slock, fh->type, V4L2_FIELD_INTERLACED, + NULL, &dev->slock, fh->type, field, sizeof(struct em28xx_buffer), fh); mutex_unlock(&dev->lock); diff --git a/linux/drivers/media/video/em28xx/em28xx.h b/linux/drivers/media/video/em28xx/em28xx.h index 3c4cd00b2..c76da6985 100644 --- a/linux/drivers/media/video/em28xx/em28xx.h +++ b/linux/drivers/media/video/em28xx/em28xx.h @@ -494,6 +494,9 @@ struct em28xx { int sensor_xres, sensor_yres; int sensor_xtal; + /* Allows progressive (e. g. non-interlaced) mode */ + int progressive; + /* Vinmode/Vinctl used at the driver */ int vinmode, vinctl; -- cgit v1.2.3 From 731b07aacdb288bdc2e0d55090224470c064cac0 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 8 Aug 2009 03:28:41 -0300 Subject: em28xx: Adjust Silvercrest xtal frequency From: Mauro Carvalho Chehab We don't know the xtal frequency of Silvercrest, but we need to have some value in order to allow controlling the frame rate frequency. The value is probably still wrong, since the manufacturer announces this device as being capable of 30fps, but the maximum we can get is 13.5 fps. Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/em28xx/em28xx-cards.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (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 594461739..9a09df296 100644 --- a/linux/drivers/media/video/em28xx/em28xx-cards.c +++ b/linux/drivers/media/video/em28xx/em28xx-cards.c @@ -1855,7 +1855,7 @@ static int em28xx_hint_sensor(struct em28xx *dev) dev->em28xx_sensor = EM28XX_MT9V011; dev->sensor_xres = 640; dev->sensor_yres = 480; - dev->sensor_xtal = 6300000; + dev->sensor_xtal = 12150000; /* probably means GRGB 16 bit bayer */ dev->vinmode = 0x0d; -- cgit v1.2.3 From 73dd04edca69ade43ea5604f1842feed69d35def Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 7 Aug 2009 10:32:20 +0200 Subject: pvrusb2: fix compile warning From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil CC: Mike Isely --- linux/drivers/media/video/pvrusb2/pvrusb2-audio.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-audio.c b/linux/drivers/media/video/pvrusb2/pvrusb2-audio.c index 42875ec21..d8c9e6632 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-audio.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-audio.c @@ -66,9 +66,10 @@ void pvr2_msp3400_subdev_update(struct pvr2_hdw *hdw, struct v4l2_subdev *sd) u32 input; pvr2_trace(PVR2_TRACE_CHIPS, "subdev msp3400 v4l2 set_stereo"); + sp = (sid < ARRAY_SIZE(routing_schemes)) ? + routing_schemes[sid] : NULL; - if ((sid < ARRAY_SIZE(routing_schemes)) && - ((sp = routing_schemes[sid]) != NULL) && + if ((sp != NULL) && (hdw->input_val >= 0) && (hdw->input_val < sp->cnt)) { input = sp->def[hdw->input_val]; -- cgit v1.2.3 From a1eb3529b0c857e8de54c34b526aca3e07f5b34a Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 7 Aug 2009 10:50:02 +0200 Subject: cx24113: fix mips compiler warning From: Hans Verkuil do_div requires an u64 as the first argument, not a s64. Priority: normal Signed-off-by: Hans Verkuil CC: Patrick Boettcher --- linux/drivers/media/dvb/frontends/cx24113.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/frontends/cx24113.c b/linux/drivers/media/dvb/frontends/cx24113.c index e4fd533a4..075b2b57c 100644 --- a/linux/drivers/media/dvb/frontends/cx24113.c +++ b/linux/drivers/media/dvb/frontends/cx24113.c @@ -303,6 +303,7 @@ static void cx24113_calc_pll_nf(struct cx24113_state *state, u16 *n, s32 *f) { s32 N; s64 F; + u64 dividend; u8 R, r; u8 vcodiv; u8 factor; @@ -346,7 +347,10 @@ static void cx24113_calc_pll_nf(struct cx24113_state *state, u16 *n, s32 *f) F = freq_hz; F *= (u64) (R * vcodiv * 262144); dprintk("1 N: %d, F: %lld, R: %d\n", N, (long long)F, R); - do_div(F, state->config->xtal_khz*1000 * factor * 2); + /* do_div needs an u64 as first argument */ + dividend = F; + do_div(dividend, state->config->xtal_khz * 1000 * factor * 2); + F = dividend; dprintk("2 N: %d, F: %lld, R: %d\n", N, (long long)F, R); F -= (N + 32) * 262144; -- cgit v1.2.3 From 84ca12cecb8b0b28efb9403b9ea6da6a9589caec Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 7 Aug 2009 12:10:52 +0200 Subject: hdpvr: add missing initialization of current_norm From: Hans Verkuil Drivers should either set current_norm or supply a g_std callback. The hdpvr driver does neither. Since it initializes to a 60 Hz format I've initialized the current_norm to NTSC | PAL_M | PAL_60 which is the 60 Hz subset of tvnorms. Priority: normal Signed-off-by: Hans Verkuil CC: Janne Grunau --- linux/drivers/media/video/hdpvr/hdpvr-video.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/hdpvr/hdpvr-video.c b/linux/drivers/media/video/hdpvr/hdpvr-video.c index 5937de23c..2eb9dc2eb 100644 --- a/linux/drivers/media/video/hdpvr/hdpvr-video.c +++ b/linux/drivers/media/video/hdpvr/hdpvr-video.c @@ -1222,6 +1222,8 @@ static const struct video_device hdpvr_video_template = { V4L2_STD_PAL_G | V4L2_STD_PAL_H | V4L2_STD_PAL_I | V4L2_STD_PAL_D | V4L2_STD_PAL_M | V4L2_STD_PAL_N | V4L2_STD_PAL_60, + .current_norm = V4L2_STD_NTSC | V4L2_STD_PAL_M | + V4L2_STD_PAL_60, }; int hdpvr_register_videodev(struct hdpvr_device *dev, struct device *parent, -- cgit v1.2.3 From f4002f575cdc4c826c424b19d21b8979de737d64 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 7 Aug 2009 12:28:16 +0200 Subject: v4l2-ioctl: fix G_STD and G_PARM default handlers From: Hans Verkuil The v4l core supplies default handlers for G_STD and G_PARM. However, both default handlers are buggy. This patch fixes the following: 1) If no g_std is supplied and current_norm == 0, then this driver does not support TV video standards (e.g. a radio or webcam driver). Return -EINVAL. This ensures that there is no bogus VIDIOC_G_STD support for such drivers. 2) The default VIDIOC_G_PARM handler used current_norm instead of first checking if the driver supported g_std and calling that to get the norm. It also didn't check if current_norm was 0, since in that case the driver does not support TV standards (or no standard was set at all) and the default handler should return -EINVAL. Note that I am very unhappy with these default handlers: I think they basically behave like some very strange and unexpected side-effect. Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/v4l2-ioctl.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/v4l2-ioctl.c b/linux/drivers/media/video/v4l2-ioctl.c index 80c94dc5a..d746d9555 100644 --- a/linux/drivers/media/video/v4l2-ioctl.c +++ b/linux/drivers/media/video/v4l2-ioctl.c @@ -1088,8 +1088,10 @@ static long __video_do_ioctl(struct file *file, /* Calls the specific handler */ if (ops->vidioc_g_std) ret = ops->vidioc_g_std(file, fh, id); - else + else if (vfd->current_norm) *id = vfd->current_norm; + else + ret = -EINVAL; if (!ret) dbgarg(cmd, "std=0x%08Lx\n", (long long unsigned)*id); @@ -1560,12 +1562,19 @@ static long __video_do_ioctl(struct file *file, break; ret = ops->vidioc_g_parm(file, fh, p); } else { + v4l2_std_id std = vfd->current_norm; + if (p->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) return -EINVAL; - v4l2_video_std_frame_period(vfd->current_norm, - &p->parm.capture.timeperframe); ret = 0; + if (ops->vidioc_g_std) + ret = ops->vidioc_g_std(file, fh, &std); + else if (std == 0) + ret = -EINVAL; + if (ret == 0) + v4l2_video_std_frame_period(std, + &p->parm.capture.timeperframe); } dbgarg(cmd, "type=%d\n", p->type); -- cgit v1.2.3 From 2ba96e655011fe3e04a32e5498ef82485b930c6f Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Fri, 7 Aug 2009 08:25:06 -0400 Subject: em28xx: fix regression in Empire DualTV digital tuning From: Devin Heitmueller Restore support for digital tuning caused by regression during introduction of disable_i2c_gate parameter to zl10353 driver. Thanks to user "Xwang" for reporting the problem and testing the fix Priority: high Cc: Xwang Signed-off-by: Devin Heitmueller --- linux/drivers/media/video/em28xx/em28xx-dvb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/em28xx/em28xx-dvb.c b/linux/drivers/media/video/em28xx/em28xx-dvb.c index e32267383..3d522d547 100644 --- a/linux/drivers/media/video/em28xx/em28xx-dvb.c +++ b/linux/drivers/media/video/em28xx/em28xx-dvb.c @@ -479,7 +479,6 @@ static int dvb_init(struct em28xx *dev) } break; case EM2880_BOARD_KWORLD_DVB_310U: - case EM2880_BOARD_EMPIRE_DUAL_TV: dvb->frontend = dvb_attach(zl10353_attach, &em28xx_zl10353_with_xc3028, &dev->i2c_adap); @@ -489,6 +488,7 @@ static int dvb_init(struct em28xx *dev) } break; case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900: + case EM2880_BOARD_EMPIRE_DUAL_TV: dvb->frontend = dvb_attach(zl10353_attach, &em28xx_zl10353_xc3028_no_i2c_gate, &dev->i2c_adap); -- cgit v1.2.3 From d029b650929bd8c6cda3c88135a3b754ca6ae0bb Mon Sep 17 00:00:00 2001 From: Douglas Schilling Landgraf Date: Sat, 8 Aug 2009 12:58:52 -0300 Subject: strlcpy() will always null terminate the string. From: Roel Kluin Priority: normal Signed-off-by: Roel Kluin Signed-off-by: Andrew Morton Signed-off-by: Douglas Schilling Landgraf --- linux/drivers/media/dvb/dvb-usb/dvb-usb-i2c.c | 2 +- linux/drivers/media/video/pwc/pwc-v4l.c | 2 +- linux/drivers/media/video/zoran/zoran_card.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/dvb-usb/dvb-usb-i2c.c b/linux/drivers/media/dvb/dvb-usb/dvb-usb-i2c.c index 326f76089..cead089bb 100644 --- a/linux/drivers/media/dvb/dvb-usb/dvb-usb-i2c.c +++ b/linux/drivers/media/dvb/dvb-usb/dvb-usb-i2c.c @@ -19,7 +19,7 @@ int dvb_usb_i2c_init(struct dvb_usb_device *d) return -EINVAL; } - strncpy(d->i2c_adap.name, d->desc->name, sizeof(d->i2c_adap.name)); + strlcpy(d->i2c_adap.name, d->desc->name, sizeof(d->i2c_adap.name)); d->i2c_adap.class = I2C_CLASS_TV_DIGITAL, d->i2c_adap.algo = d->props.i2c_algo; d->i2c_adap.algo_data = NULL; diff --git a/linux/drivers/media/video/pwc/pwc-v4l.c b/linux/drivers/media/video/pwc/pwc-v4l.c index 2876ce084..bdb4ced57 100644 --- a/linux/drivers/media/video/pwc/pwc-v4l.c +++ b/linux/drivers/media/video/pwc/pwc-v4l.c @@ -1033,7 +1033,7 @@ long pwc_video_do_ioctl(struct file *file, unsigned int cmd, void *arg) if (std->index != 0) return -EINVAL; std->id = V4L2_STD_UNKNOWN; - strncpy(std->name, "webcam", sizeof(std->name)); + strlcpy(std->name, "webcam", sizeof(std->name)); return 0; } diff --git a/linux/drivers/media/video/zoran/zoran_card.c b/linux/drivers/media/video/zoran/zoran_card.c index 217fec9e4..375f158fd 100644 --- a/linux/drivers/media/video/zoran/zoran_card.c +++ b/linux/drivers/media/video/zoran/zoran_card.c @@ -1169,7 +1169,7 @@ zoran_setup_videocodec (struct zoran *zr, m->type = 0; m->flags = CODEC_FLAG_ENCODER | CODEC_FLAG_DECODER; - strncpy(m->name, ZR_DEVNAME(zr), sizeof(m->name)); + strlcpy(m->name, ZR_DEVNAME(zr), sizeof(m->name)); m->data = zr; switch (type) -- cgit v1.2.3 From b876feaf9b088d50b7519f8d6bbf15be977cd325 Mon Sep 17 00:00:00 2001 From: Douglas Schilling Landgraf Date: Mon, 10 Aug 2009 22:17:25 -0300 Subject: stk-webcam: read buffer overflow From: Roel Kluin It tested the value of stk_sizes[i].m before checking whether i was in range. Priority: normal Signed-off-by: Roel Kluin Cc: Hans Verkuil Cc: Trent Piepho Signed-off-by: Andrew Morton Signed-off-by: Douglas Schilling Landgraf --- linux/drivers/media/video/stk-webcam.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/stk-webcam.c b/linux/drivers/media/video/stk-webcam.c index 849867ab2..aaeee8319 100644 --- a/linux/drivers/media/video/stk-webcam.c +++ b/linux/drivers/media/video/stk-webcam.c @@ -1051,8 +1051,8 @@ static int stk_setup_format(struct stk_camera *dev) depth = 1; else depth = 2; - while (stk_sizes[i].m != dev->vsettings.mode - && i < ARRAY_SIZE(stk_sizes)) + while (i < ARRAY_SIZE(stk_sizes) && + stk_sizes[i].m != dev->vsettings.mode) i++; if (i == ARRAY_SIZE(stk_sizes)) { STK_ERROR("Something is broken in %s\n", __func__); -- cgit v1.2.3 From b8961acc4142f124a11a2b33594790dc49dd194a Mon Sep 17 00:00:00 2001 From: Douglas Schilling Landgraf Date: Mon, 10 Aug 2009 20:59:16 -0400 Subject: dvb: siano uses/depends on INPUT From: Randy Dunlap siano uses input_*() functions so it should depend on INPUT to prevent build errors: ERROR: "input_event" [drivers/media/dvb/siano/sms1xxx.ko] undefined! ERROR: "input_register_device" [drivers/media/dvb/siano/sms1xxx.ko] undefined! ERROR: "input_free_device" [drivers/media/dvb/siano/sms1xxx.ko] undefined! ERROR: "input_unregister_device" [drivers/media/dvb/siano/sms1xxx.ko] undefined! ERROR: "input_allocate_device" [drivers/media/dvb/siano/sms1xxx.ko] undefined! Priority: normal Signed-off-by: Randy Dunlap Cc: Michael Krufky Cc: Uri Shkolnik Signed-off-by: Douglas Schilling Landgraf --- linux/drivers/media/dvb/siano/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/siano/Kconfig b/linux/drivers/media/dvb/siano/Kconfig index dd863f261..88847d1dc 100644 --- a/linux/drivers/media/dvb/siano/Kconfig +++ b/linux/drivers/media/dvb/siano/Kconfig @@ -4,7 +4,7 @@ config DVB_SIANO_SMS1XXX tristate "Siano SMS1XXX USB dongle support" - depends on DVB_CORE && USB + depends on DVB_CORE && USB && INPUT ---help--- Choose Y here if you have a USB dongle with a SMS1XXX chipset. -- cgit v1.2.3 From b889b807125e28911afda8c7740b18658aeb96fe Mon Sep 17 00:00:00 2001 From: Douglas Schilling Landgraf Date: Mon, 10 Aug 2009 21:07:54 -0400 Subject: Read buffer overflow From: Roel Kluin parport[n] is checked before n < MAX_CAMS Priority: normal Signed-off-by: Roel Kluin Signed-off-by: Douglas Schilling Landgraf --- linux/drivers/media/video/bw-qcam.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/bw-qcam.c b/linux/drivers/media/video/bw-qcam.c index 3702baad6..8f6bb845e 100644 --- a/linux/drivers/media/video/bw-qcam.c +++ b/linux/drivers/media/video/bw-qcam.c @@ -993,7 +993,7 @@ static int accept_bwqcam(struct parport *port) if (parport[0] && strncmp(parport[0], "auto", 4) != 0) { /* user gave parport parameters */ - for(n=0; parport[n] && n Date: Mon, 10 Aug 2009 21:15:54 -0400 Subject: cx88: add support for WinFast DTV2000H rev. J From: Vlastimil Labsky I updated and simplyfied patch from Zbynek Hrabovsky for recent kernel. It enables autodetection of card, sound in analog TV , sound in FM radio and switching between antenna and cable RF input. Radio tuner still doesn't work, I don't even know how it works. Some guys wrote me that FM radio works with TV tuner used instead of radio part (symlink video0 -> radio0). Priority: normal Signed-off-by: Vlastimil Labsky Cc: Gerd Knorr Signed-off-by: Andrew Morton Signed-off-by: Douglas Schilling Landgraf --- linux/drivers/media/video/cx88/cx88-cards.c | 49 +++++++++++++++++++++++++++++ linux/drivers/media/video/cx88/cx88-dvb.c | 1 + linux/drivers/media/video/cx88/cx88-input.c | 1 + linux/drivers/media/video/cx88/cx88.h | 1 + 4 files changed, 52 insertions(+) (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 67ccc59a7..19d57e698 100644 --- a/linux/drivers/media/video/cx88/cx88-cards.c +++ b/linux/drivers/media/video/cx88/cx88-cards.c @@ -1316,6 +1316,51 @@ static const struct cx88_board cx88_boards[] = { }, .mpeg = CX88_MPEG_DVB, }, + [CX88_BOARD_WINFAST_DTV2000H_J] = { + .name = "WinFast DTV2000 H rev. J", + .tuner_type = TUNER_PHILIPS_FMD1216ME_MK3, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .tda9887_conf = TDA9887_PRESENT, + .input = {{ + .type = CX88_VMUX_TELEVISION, + .vmux = 0, + .gpio0 = 0x00017300, + .gpio1 = 0x00008207, + .gpio2 = 0x00000000, + .gpio3 = 0x02000000, + },{ + .type = CX88_VMUX_TELEVISION, + .vmux = 0, + .gpio0 = 0x00018300, + .gpio1 = 0x0000f207, + .gpio2 = 0x00017304, + .gpio3 = 0x02000000, + },{ + .type = CX88_VMUX_COMPOSITE1, + .vmux = 1, + .gpio0 = 0x00018301, + .gpio1 = 0x0000f207, + .gpio2 = 0x00017304, + .gpio3 = 0x02000000, + },{ + .type = CX88_VMUX_SVIDEO, + .vmux = 2, + .gpio0 = 0x00018301, + .gpio1 = 0x0000f207, + .gpio2 = 0x00017304, + .gpio3 = 0x02000000, + }}, + .radio = { + .type = CX88_RADIO, + .gpio0 = 0x00015702, + .gpio1 = 0x0000f207, + .gpio2 = 0x00015702, + .gpio3 = 0x02000000, + }, + .mpeg = CX88_MPEG_DVB, + }, [CX88_BOARD_GENIATECH_DVBS] = { .name = "Geniatech DVB-S", .tuner_type = TUNER_ABSENT, @@ -2314,6 +2359,10 @@ static const struct cx88_subid cx88_subids[] = { .subvendor = 0x107d, .subdevice = 0x665e, .card = CX88_BOARD_WINFAST_DTV2000H, + },{ + .subvendor = 0x107d, + .subdevice = 0x6f2b, + .card = CX88_BOARD_WINFAST_DTV2000H_J, },{ .subvendor = 0x18ac, .subdevice = 0xd800, /* FusionHDTV 3 Gold (original revision) */ diff --git a/linux/drivers/media/video/cx88/cx88-dvb.c b/linux/drivers/media/video/cx88/cx88-dvb.c index 9c88b6c0f..ab84c085f 100644 --- a/linux/drivers/media/video/cx88/cx88-dvb.c +++ b/linux/drivers/media/video/cx88/cx88-dvb.c @@ -703,6 +703,7 @@ static int dvb_register(struct cx8802_dev *dev) } break; case CX88_BOARD_WINFAST_DTV2000H: + case CX88_BOARD_WINFAST_DTV2000H_J: case CX88_BOARD_HAUPPAUGE_HVR1100: case CX88_BOARD_HAUPPAUGE_HVR1100LP: case CX88_BOARD_HAUPPAUGE_HVR1300: diff --git a/linux/drivers/media/video/cx88/cx88-input.c b/linux/drivers/media/video/cx88/cx88-input.c index 7c5e94916..8d0042ab2 100644 --- a/linux/drivers/media/video/cx88/cx88-input.c +++ b/linux/drivers/media/video/cx88/cx88-input.c @@ -238,6 +238,7 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) ir->sampling = 1; break; case CX88_BOARD_WINFAST_DTV2000H: + case CX88_BOARD_WINFAST_DTV2000H_J: case CX88_BOARD_WINFAST_DTV1800H: ir_codes = ir_codes_winfast; ir->gpio_addr = MO_GP0_IO; diff --git a/linux/drivers/media/video/cx88/cx88.h b/linux/drivers/media/video/cx88/cx88.h index 59fc01a53..014004acd 100644 --- a/linux/drivers/media/video/cx88/cx88.h +++ b/linux/drivers/media/video/cx88/cx88.h @@ -238,6 +238,7 @@ extern struct sram_channel cx88_sram_channels[]; #define CX88_BOARD_TERRATEC_CINERGY_HT_PCI_MKII 79 #define CX88_BOARD_HAUPPAUGE_IRONLY 80 #define CX88_BOARD_WINFAST_DTV1800H 81 +#define CX88_BOARD_WINFAST_DTV2000H_J 82 enum cx88_itype { CX88_VMUX_COMPOSITE1 = 1, -- cgit v1.2.3 From 84b86128572d1cef2f921fda840e365d8f01bdee Mon Sep 17 00:00:00 2001 From: Douglas Schilling Landgraf Date: Mon, 10 Aug 2009 21:51:01 -0400 Subject: Use kzalloc for frontend states to have struct dvb_frontend properly From: Matthias Schwarzott This patch changes most frontend drivers to allocate their state structure via kzalloc and not kmalloc. This is done to properly initialize the embedded "struct dvb_frontend frontend" field, that they all have. The visible effect of this struct being uninitalized is, that the member "id" that is used to set the name of kernel thread is totally random. Some board drivers (for example cx88-dvb) set this "id" via videobuf_dvb_alloc_frontend but most do not. So I at least get random id values for saa7134, flexcop and ttpci based cards. It looks like this in dmesg: DVB: registering adapter 1 frontend -10551321 (ST STV0299 DVB-S) The related kernel thread then also gets a strange name like "kdvb-ad-1-fe--1". Priority: normal Signed-off-by: Matthias Schwarzott CC: Michael Krufky CC: Steven Toth CC: Timothy Lee CC: Igor M. Liplianin Acked-by: Andreas Oberritter Signed-off-by: Douglas Schilling Landgraf --- linux/drivers/media/dvb/frontends/at76c651.c | 2 +- linux/drivers/media/dvb/frontends/cx22700.c | 2 +- linux/drivers/media/dvb/frontends/cx22702.c | 2 +- linux/drivers/media/dvb/frontends/cx24110.c | 2 +- linux/drivers/media/dvb/frontends/dvb_dummy_fe.c | 6 +++--- linux/drivers/media/dvb/frontends/l64781.c | 2 +- linux/drivers/media/dvb/frontends/lgs8gl5.c | 2 +- linux/drivers/media/dvb/frontends/mt312.c | 2 +- linux/drivers/media/dvb/frontends/nxt6000.c | 2 +- linux/drivers/media/dvb/frontends/or51132.c | 2 +- linux/drivers/media/dvb/frontends/or51211.c | 2 +- linux/drivers/media/dvb/frontends/s5h1409.c | 2 +- linux/drivers/media/dvb/frontends/s5h1411.c | 2 +- linux/drivers/media/dvb/frontends/si21xx.c | 2 +- linux/drivers/media/dvb/frontends/sp8870.c | 2 +- linux/drivers/media/dvb/frontends/sp887x.c | 2 +- linux/drivers/media/dvb/frontends/stv0288.c | 2 +- linux/drivers/media/dvb/frontends/stv0297.c | 2 +- linux/drivers/media/dvb/frontends/stv0299.c | 2 +- linux/drivers/media/dvb/frontends/tda10021.c | 2 +- linux/drivers/media/dvb/frontends/tda10048.c | 2 +- linux/drivers/media/dvb/frontends/tda1004x.c | 4 ++-- linux/drivers/media/dvb/frontends/tda10086.c | 2 +- linux/drivers/media/dvb/frontends/tda8083.c | 2 +- linux/drivers/media/dvb/frontends/tda80xx.c | 2 +- linux/drivers/media/dvb/frontends/ves1820.c | 2 +- linux/drivers/media/dvb/frontends/ves1x93.c | 2 +- 27 files changed, 30 insertions(+), 30 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/frontends/at76c651.c b/linux/drivers/media/dvb/frontends/at76c651.c index 33486d54c..510e08f5a 100644 --- a/linux/drivers/media/dvb/frontends/at76c651.c +++ b/linux/drivers/media/dvb/frontends/at76c651.c @@ -369,7 +369,7 @@ struct dvb_frontend* at76c651_attach(const struct at76c651_config* config, struct at76c651_state* state = NULL; /* allocate memory for the internal state */ - state = kmalloc(sizeof(struct at76c651_state), GFP_KERNEL); + state = kzalloc(sizeof(struct at76c651_state), GFP_KERNEL); if (state == NULL) goto error; /* setup the state */ diff --git a/linux/drivers/media/dvb/frontends/cx22700.c b/linux/drivers/media/dvb/frontends/cx22700.c index ace5cb171..fbd838eca 100644 --- a/linux/drivers/media/dvb/frontends/cx22700.c +++ b/linux/drivers/media/dvb/frontends/cx22700.c @@ -380,7 +380,7 @@ struct dvb_frontend* cx22700_attach(const struct cx22700_config* config, struct cx22700_state* state = NULL; /* allocate memory for the internal state */ - state = kmalloc(sizeof(struct cx22700_state), GFP_KERNEL); + state = kzalloc(sizeof(struct cx22700_state), GFP_KERNEL); if (state == NULL) goto error; /* setup the state */ diff --git a/linux/drivers/media/dvb/frontends/cx22702.c b/linux/drivers/media/dvb/frontends/cx22702.c index 5d1abe34b..00b5c7e91 100644 --- a/linux/drivers/media/dvb/frontends/cx22702.c +++ b/linux/drivers/media/dvb/frontends/cx22702.c @@ -580,7 +580,7 @@ struct dvb_frontend *cx22702_attach(const struct cx22702_config *config, struct cx22702_state *state = NULL; /* allocate memory for the internal state */ - state = kmalloc(sizeof(struct cx22702_state), GFP_KERNEL); + state = kzalloc(sizeof(struct cx22702_state), GFP_KERNEL); if (state == NULL) goto error; diff --git a/linux/drivers/media/dvb/frontends/cx24110.c b/linux/drivers/media/dvb/frontends/cx24110.c index 87ae29db0..ffbcfabd8 100644 --- a/linux/drivers/media/dvb/frontends/cx24110.c +++ b/linux/drivers/media/dvb/frontends/cx24110.c @@ -598,7 +598,7 @@ struct dvb_frontend* cx24110_attach(const struct cx24110_config* config, int ret; /* allocate memory for the internal state */ - state = kmalloc(sizeof(struct cx24110_state), GFP_KERNEL); + state = kzalloc(sizeof(struct cx24110_state), GFP_KERNEL); if (state == NULL) goto error; /* setup the state */ diff --git a/linux/drivers/media/dvb/frontends/dvb_dummy_fe.c b/linux/drivers/media/dvb/frontends/dvb_dummy_fe.c index db8a937cc..a7fc7e53a 100644 --- a/linux/drivers/media/dvb/frontends/dvb_dummy_fe.c +++ b/linux/drivers/media/dvb/frontends/dvb_dummy_fe.c @@ -117,7 +117,7 @@ struct dvb_frontend* dvb_dummy_fe_ofdm_attach(void) struct dvb_dummy_fe_state* state = NULL; /* allocate memory for the internal state */ - state = kmalloc(sizeof(struct dvb_dummy_fe_state), GFP_KERNEL); + state = kzalloc(sizeof(struct dvb_dummy_fe_state), GFP_KERNEL); if (state == NULL) goto error; /* create dvb_frontend */ @@ -137,7 +137,7 @@ struct dvb_frontend *dvb_dummy_fe_qpsk_attach(void) struct dvb_dummy_fe_state* state = NULL; /* allocate memory for the internal state */ - state = kmalloc(sizeof(struct dvb_dummy_fe_state), GFP_KERNEL); + state = kzalloc(sizeof(struct dvb_dummy_fe_state), GFP_KERNEL); if (state == NULL) goto error; /* create dvb_frontend */ @@ -157,7 +157,7 @@ struct dvb_frontend *dvb_dummy_fe_qam_attach(void) struct dvb_dummy_fe_state* state = NULL; /* allocate memory for the internal state */ - state = kmalloc(sizeof(struct dvb_dummy_fe_state), GFP_KERNEL); + state = kzalloc(sizeof(struct dvb_dummy_fe_state), GFP_KERNEL); if (state == NULL) goto error; /* create dvb_frontend */ diff --git a/linux/drivers/media/dvb/frontends/l64781.c b/linux/drivers/media/dvb/frontends/l64781.c index e1e70e9e0..3051b64aa 100644 --- a/linux/drivers/media/dvb/frontends/l64781.c +++ b/linux/drivers/media/dvb/frontends/l64781.c @@ -501,7 +501,7 @@ struct dvb_frontend* l64781_attach(const struct l64781_config* config, { .addr = config->demod_address, .flags = I2C_M_RD, .buf = b1, .len = 1 } }; /* allocate memory for the internal state */ - state = kmalloc(sizeof(struct l64781_state), GFP_KERNEL); + state = kzalloc(sizeof(struct l64781_state), GFP_KERNEL); if (state == NULL) goto error; /* setup the state */ diff --git a/linux/drivers/media/dvb/frontends/lgs8gl5.c b/linux/drivers/media/dvb/frontends/lgs8gl5.c index 380ae1868..8780905bc 100644 --- a/linux/drivers/media/dvb/frontends/lgs8gl5.c +++ b/linux/drivers/media/dvb/frontends/lgs8gl5.c @@ -411,7 +411,7 @@ lgs8gl5_attach(const struct lgs8gl5_config *config, struct i2c_adapter *i2c) dprintk("%s\n", __func__); /* Allocate memory for the internal state */ - state = kmalloc(sizeof(struct lgs8gl5_state), GFP_KERNEL); + state = kzalloc(sizeof(struct lgs8gl5_state), GFP_KERNEL); if (state == NULL) goto error; diff --git a/linux/drivers/media/dvb/frontends/mt312.c b/linux/drivers/media/dvb/frontends/mt312.c index f348f8bea..4d14f084d 100644 --- a/linux/drivers/media/dvb/frontends/mt312.c +++ b/linux/drivers/media/dvb/frontends/mt312.c @@ -784,7 +784,7 @@ struct dvb_frontend *mt312_attach(const struct mt312_config *config, struct mt312_state *state = NULL; /* allocate memory for the internal state */ - state = kmalloc(sizeof(struct mt312_state), GFP_KERNEL); + state = kzalloc(sizeof(struct mt312_state), GFP_KERNEL); if (state == NULL) goto error; diff --git a/linux/drivers/media/dvb/frontends/nxt6000.c b/linux/drivers/media/dvb/frontends/nxt6000.c index 0eef22dbf..a763ec756 100644 --- a/linux/drivers/media/dvb/frontends/nxt6000.c +++ b/linux/drivers/media/dvb/frontends/nxt6000.c @@ -545,7 +545,7 @@ struct dvb_frontend* nxt6000_attach(const struct nxt6000_config* config, struct nxt6000_state* state = NULL; /* allocate memory for the internal state */ - state = kmalloc(sizeof(struct nxt6000_state), GFP_KERNEL); + state = kzalloc(sizeof(struct nxt6000_state), GFP_KERNEL); if (state == NULL) goto error; /* setup the state */ diff --git a/linux/drivers/media/dvb/frontends/or51132.c b/linux/drivers/media/dvb/frontends/or51132.c index 8133ea3cd..38e67accb 100644 --- a/linux/drivers/media/dvb/frontends/or51132.c +++ b/linux/drivers/media/dvb/frontends/or51132.c @@ -562,7 +562,7 @@ struct dvb_frontend* or51132_attach(const struct or51132_config* config, struct or51132_state* state = NULL; /* Allocate memory for the internal state */ - state = kmalloc(sizeof(struct or51132_state), GFP_KERNEL); + state = kzalloc(sizeof(struct or51132_state), GFP_KERNEL); if (state == NULL) return NULL; diff --git a/linux/drivers/media/dvb/frontends/or51211.c b/linux/drivers/media/dvb/frontends/or51211.c index 16cf2fdd5..c709ce677 100644 --- a/linux/drivers/media/dvb/frontends/or51211.c +++ b/linux/drivers/media/dvb/frontends/or51211.c @@ -527,7 +527,7 @@ struct dvb_frontend* or51211_attach(const struct or51211_config* config, struct or51211_state* state = NULL; /* Allocate memory for the internal state */ - state = kmalloc(sizeof(struct or51211_state), GFP_KERNEL); + state = kzalloc(sizeof(struct or51211_state), GFP_KERNEL); if (state == NULL) return NULL; diff --git a/linux/drivers/media/dvb/frontends/s5h1409.c b/linux/drivers/media/dvb/frontends/s5h1409.c index 3e08d985d..fb3011518 100644 --- a/linux/drivers/media/dvb/frontends/s5h1409.c +++ b/linux/drivers/media/dvb/frontends/s5h1409.c @@ -796,7 +796,7 @@ struct dvb_frontend *s5h1409_attach(const struct s5h1409_config *config, u16 reg; /* allocate memory for the internal state */ - state = kmalloc(sizeof(struct s5h1409_state), GFP_KERNEL); + state = kzalloc(sizeof(struct s5h1409_state), GFP_KERNEL); if (state == NULL) goto error; diff --git a/linux/drivers/media/dvb/frontends/s5h1411.c b/linux/drivers/media/dvb/frontends/s5h1411.c index 66e2dd6d6..d8adf1e32 100644 --- a/linux/drivers/media/dvb/frontends/s5h1411.c +++ b/linux/drivers/media/dvb/frontends/s5h1411.c @@ -844,7 +844,7 @@ struct dvb_frontend *s5h1411_attach(const struct s5h1411_config *config, u16 reg; /* allocate memory for the internal state */ - state = kmalloc(sizeof(struct s5h1411_state), GFP_KERNEL); + state = kzalloc(sizeof(struct s5h1411_state), GFP_KERNEL); if (state == NULL) goto error; diff --git a/linux/drivers/media/dvb/frontends/si21xx.c b/linux/drivers/media/dvb/frontends/si21xx.c index 216a532ab..ee0a0a2dd 100644 --- a/linux/drivers/media/dvb/frontends/si21xx.c +++ b/linux/drivers/media/dvb/frontends/si21xx.c @@ -1003,7 +1003,7 @@ struct dvb_frontend *si21xx_attach(const struct si21xx_config *config, dprintk("%s\n", __func__); /* allocate memory for the internal state */ - state = kmalloc(sizeof(struct si21xx_state), GFP_KERNEL); + state = kzalloc(sizeof(struct si21xx_state), GFP_KERNEL); if (state == NULL) goto error; diff --git a/linux/drivers/media/dvb/frontends/sp8870.c b/linux/drivers/media/dvb/frontends/sp8870.c index 1c9a9b405..b85eb60a8 100644 --- a/linux/drivers/media/dvb/frontends/sp8870.c +++ b/linux/drivers/media/dvb/frontends/sp8870.c @@ -557,7 +557,7 @@ struct dvb_frontend* sp8870_attach(const struct sp8870_config* config, struct sp8870_state* state = NULL; /* allocate memory for the internal state */ - state = kmalloc(sizeof(struct sp8870_state), GFP_KERNEL); + state = kzalloc(sizeof(struct sp8870_state), GFP_KERNEL); if (state == NULL) goto error; /* setup the state */ diff --git a/linux/drivers/media/dvb/frontends/sp887x.c b/linux/drivers/media/dvb/frontends/sp887x.c index 559509ab4..4a7c3d842 100644 --- a/linux/drivers/media/dvb/frontends/sp887x.c +++ b/linux/drivers/media/dvb/frontends/sp887x.c @@ -557,7 +557,7 @@ struct dvb_frontend* sp887x_attach(const struct sp887x_config* config, struct sp887x_state* state = NULL; /* allocate memory for the internal state */ - state = kmalloc(sizeof(struct sp887x_state), GFP_KERNEL); + state = kzalloc(sizeof(struct sp887x_state), GFP_KERNEL); if (state == NULL) goto error; /* setup the state */ diff --git a/linux/drivers/media/dvb/frontends/stv0288.c b/linux/drivers/media/dvb/frontends/stv0288.c index ff1194de3..2930a5d67 100644 --- a/linux/drivers/media/dvb/frontends/stv0288.c +++ b/linux/drivers/media/dvb/frontends/stv0288.c @@ -570,7 +570,7 @@ struct dvb_frontend *stv0288_attach(const struct stv0288_config *config, int id; /* allocate memory for the internal state */ - state = kmalloc(sizeof(struct stv0288_state), GFP_KERNEL); + state = kzalloc(sizeof(struct stv0288_state), GFP_KERNEL); if (state == NULL) goto error; diff --git a/linux/drivers/media/dvb/frontends/stv0297.c b/linux/drivers/media/dvb/frontends/stv0297.c index 1c5a0ae82..2e709a7a5 100644 --- a/linux/drivers/media/dvb/frontends/stv0297.c +++ b/linux/drivers/media/dvb/frontends/stv0297.c @@ -663,7 +663,7 @@ struct dvb_frontend *stv0297_attach(const struct stv0297_config *config, struct stv0297_state *state = NULL; /* allocate memory for the internal state */ - state = kmalloc(sizeof(struct stv0297_state), GFP_KERNEL); + state = kzalloc(sizeof(struct stv0297_state), GFP_KERNEL); if (state == NULL) goto error; diff --git a/linux/drivers/media/dvb/frontends/stv0299.c b/linux/drivers/media/dvb/frontends/stv0299.c index 6c1cb1973..968874469 100644 --- a/linux/drivers/media/dvb/frontends/stv0299.c +++ b/linux/drivers/media/dvb/frontends/stv0299.c @@ -667,7 +667,7 @@ struct dvb_frontend* stv0299_attach(const struct stv0299_config* config, int id; /* allocate memory for the internal state */ - state = kmalloc(sizeof(struct stv0299_state), GFP_KERNEL); + state = kzalloc(sizeof(struct stv0299_state), GFP_KERNEL); if (state == NULL) goto error; /* setup the state */ diff --git a/linux/drivers/media/dvb/frontends/tda10021.c b/linux/drivers/media/dvb/frontends/tda10021.c index c6f90f33a..242636e59 100644 --- a/linux/drivers/media/dvb/frontends/tda10021.c +++ b/linux/drivers/media/dvb/frontends/tda10021.c @@ -413,7 +413,7 @@ struct dvb_frontend* tda10021_attach(const struct tda1002x_config* config, u8 id; /* allocate memory for the internal state */ - state = kmalloc(sizeof(struct tda10021_state), GFP_KERNEL); + state = kzalloc(sizeof(struct tda10021_state), GFP_KERNEL); if (state == NULL) goto error; /* setup the state */ diff --git a/linux/drivers/media/dvb/frontends/tda10048.c b/linux/drivers/media/dvb/frontends/tda10048.c index edf5a19a3..fd8c4cf00 100644 --- a/linux/drivers/media/dvb/frontends/tda10048.c +++ b/linux/drivers/media/dvb/frontends/tda10048.c @@ -1100,7 +1100,7 @@ struct dvb_frontend *tda10048_attach(const struct tda10048_config *config, dprintk(1, "%s()\n", __func__); /* allocate memory for the internal state */ - state = kmalloc(sizeof(struct tda10048_state), GFP_KERNEL); + state = kzalloc(sizeof(struct tda10048_state), GFP_KERNEL); if (state == NULL) goto error; diff --git a/linux/drivers/media/dvb/frontends/tda1004x.c b/linux/drivers/media/dvb/frontends/tda1004x.c index 4981cef8b..f2a8abe0a 100644 --- a/linux/drivers/media/dvb/frontends/tda1004x.c +++ b/linux/drivers/media/dvb/frontends/tda1004x.c @@ -1269,7 +1269,7 @@ struct dvb_frontend* tda10045_attach(const struct tda1004x_config* config, int id; /* allocate memory for the internal state */ - state = kmalloc(sizeof(struct tda1004x_state), GFP_KERNEL); + state = kzalloc(sizeof(struct tda1004x_state), GFP_KERNEL); if (!state) { printk(KERN_ERR "Can't alocate memory for tda10045 state\n"); return NULL; @@ -1339,7 +1339,7 @@ struct dvb_frontend* tda10046_attach(const struct tda1004x_config* config, int id; /* allocate memory for the internal state */ - state = kmalloc(sizeof(struct tda1004x_state), GFP_KERNEL); + state = kzalloc(sizeof(struct tda1004x_state), GFP_KERNEL); if (!state) { printk(KERN_ERR "Can't alocate memory for tda10046 state\n"); return NULL; diff --git a/linux/drivers/media/dvb/frontends/tda10086.c b/linux/drivers/media/dvb/frontends/tda10086.c index c749f96c2..502ce67cf 100644 --- a/linux/drivers/media/dvb/frontends/tda10086.c +++ b/linux/drivers/media/dvb/frontends/tda10086.c @@ -746,7 +746,7 @@ struct dvb_frontend* tda10086_attach(const struct tda10086_config* config, dprintk ("%s\n", __func__); /* allocate memory for the internal state */ - state = kmalloc(sizeof(struct tda10086_state), GFP_KERNEL); + state = kzalloc(sizeof(struct tda10086_state), GFP_KERNEL); if (!state) return NULL; diff --git a/linux/drivers/media/dvb/frontends/tda8083.c b/linux/drivers/media/dvb/frontends/tda8083.c index 5b843b2e6..9369f7442 100644 --- a/linux/drivers/media/dvb/frontends/tda8083.c +++ b/linux/drivers/media/dvb/frontends/tda8083.c @@ -417,7 +417,7 @@ struct dvb_frontend* tda8083_attach(const struct tda8083_config* config, struct tda8083_state* state = NULL; /* allocate memory for the internal state */ - state = kmalloc(sizeof(struct tda8083_state), GFP_KERNEL); + state = kzalloc(sizeof(struct tda8083_state), GFP_KERNEL); if (state == NULL) goto error; /* setup the state */ diff --git a/linux/drivers/media/dvb/frontends/tda80xx.c b/linux/drivers/media/dvb/frontends/tda80xx.c index 83fc57a22..e04fd984f 100644 --- a/linux/drivers/media/dvb/frontends/tda80xx.c +++ b/linux/drivers/media/dvb/frontends/tda80xx.c @@ -646,7 +646,7 @@ struct dvb_frontend* tda80xx_attach(const struct tda80xx_config* config, int ret; /* allocate memory for the internal state */ - state = kmalloc(sizeof(struct tda80xx_state), GFP_KERNEL); + state = kzalloc(sizeof(struct tda80xx_state), GFP_KERNEL); if (state == NULL) goto error; /* setup the state */ diff --git a/linux/drivers/media/dvb/frontends/ves1820.c b/linux/drivers/media/dvb/frontends/ves1820.c index a184597f1..6e78e4865 100644 --- a/linux/drivers/media/dvb/frontends/ves1820.c +++ b/linux/drivers/media/dvb/frontends/ves1820.c @@ -374,7 +374,7 @@ struct dvb_frontend* ves1820_attach(const struct ves1820_config* config, struct ves1820_state* state = NULL; /* allocate memory for the internal state */ - state = kmalloc(sizeof(struct ves1820_state), GFP_KERNEL); + state = kzalloc(sizeof(struct ves1820_state), GFP_KERNEL); if (state == NULL) goto error; diff --git a/linux/drivers/media/dvb/frontends/ves1x93.c b/linux/drivers/media/dvb/frontends/ves1x93.c index bd558960b..8d7854c2f 100644 --- a/linux/drivers/media/dvb/frontends/ves1x93.c +++ b/linux/drivers/media/dvb/frontends/ves1x93.c @@ -456,7 +456,7 @@ struct dvb_frontend* ves1x93_attach(const struct ves1x93_config* config, u8 identity; /* allocate memory for the internal state */ - state = kmalloc(sizeof(struct ves1x93_state), GFP_KERNEL); + state = kzalloc(sizeof(struct ves1x93_state), GFP_KERNEL); if (state == NULL) goto error; /* setup the state */ -- cgit v1.2.3 From 1537b0475bd1f694226d14373ed31298f2d0e8ef Mon Sep 17 00:00:00 2001 From: Douglas Schilling Landgraf Date: Mon, 10 Aug 2009 21:59:33 -0400 Subject: siano: read buffer overflow From: Roel Kluin With mode DEVICE_MODE_RAW_TUNER a read occurs past the end of smscore_fw_lkup[]. Subsequently an attempt is made to load the firmware from the resulting filename. Priority: normal Signed-off-by: Roel Kluin Signed-off-by: Andrew Morton Signed-off-by: Douglas Schilling Landgraf --- 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 54f59f24e..c0306af09 100644 --- a/linux/drivers/media/dvb/siano/smscoreapi.c +++ b/linux/drivers/media/dvb/siano/smscoreapi.c @@ -816,7 +816,7 @@ int smscore_set_device_mode(struct smscore_device_t *coredev, int mode) sms_debug("set device mode to %d", mode); if (coredev->device_flags & SMS_DEVICE_FAMILY2) { - if (mode < DEVICE_MODE_DVBT || mode > DEVICE_MODE_RAW_TUNER) { + if (mode < DEVICE_MODE_DVBT || mode >= DEVICE_MODE_RAW_TUNER) { sms_err("invalid mode specified %d", mode); return -EINVAL; } -- cgit v1.2.3 From 796c449e9807bc070a33bcbbab2f4cae6cfc6d14 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 9 Aug 2009 12:14:26 +0200 Subject: fix device match logic From: Laurent Pinchart I forgot to change USB_DEVICE_ID_MATCH_VENDOR to USB_DEVICE_ID_MATCH_DEVICE in the last commit, defeating its whole purpose. Fix this. kernel-sync: Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/uvc/uvc_driver.c | 6 +++--- 1 file changed, 3 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 fa13b6765..09b2e4ad5 100644 --- a/linux/drivers/media/video/uvc/uvc_driver.c +++ b/linux/drivers/media/video/uvc/uvc_driver.c @@ -1996,7 +1996,7 @@ static struct usb_device_id uvc_ids[] = { .bInterfaceProtocol = 0, .driver_info = UVC_QUIRK_STREAM_NO_FID }, /* ViMicro Vega */ - { .match_flags = USB_DEVICE_ID_MATCH_VENDOR + { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO, .idVendor = 0x0ac8, .idProduct = 0x332d, @@ -2005,7 +2005,7 @@ static struct usb_device_id uvc_ids[] = { .bInterfaceProtocol = 0, .driver_info = UVC_QUIRK_FIX_BANDWIDTH }, /* ViMicro - Minoru3D */ - { .match_flags = USB_DEVICE_ID_MATCH_VENDOR + { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO, .idVendor = 0x0ac8, .idProduct = 0x3410, @@ -2014,7 +2014,7 @@ static struct usb_device_id uvc_ids[] = { .bInterfaceProtocol = 0, .driver_info = UVC_QUIRK_FIX_BANDWIDTH }, /* ViMicro Venus - Minoru3D */ - { .match_flags = USB_DEVICE_ID_MATCH_VENDOR + { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO, .idVendor = 0x0ac8, .idProduct = 0x3420, -- cgit v1.2.3 From 69f4f9ea01bb7203787bb5ba9cf384944660dd3f Mon Sep 17 00:00:00 2001 From: Antoine Jacquet Date: Tue, 11 Aug 2009 13:10:25 +0200 Subject: zr364: wrong indexes From: Roel Kluin The order of indexes is reversed Priority: high Signed-off-by: Roel Kluin Signed-off-by: Antoine Jacquet --- linux/drivers/media/video/zr364xx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/zr364xx.c b/linux/drivers/media/video/zr364xx.c index c298ce625..ee5534230 100644 --- a/linux/drivers/media/video/zr364xx.c +++ b/linux/drivers/media/video/zr364xx.c @@ -1367,7 +1367,7 @@ static int zr364xx_release(struct file *file) for (i = 0; i < 2; i++) { err = send_control_msg(udev, 1, init[cam->method][i].value, - 0, init[i][cam->method].bytes, + 0, init[cam->method][i].bytes, init[cam->method][i].size); if (err < 0) { dev_err(&udev->dev, "error during release sequence\n"); -- cgit v1.2.3 From ba4502fc619943b78f8231e8889f9799bf12de61 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 12 Aug 2009 15:10:20 +0200 Subject: radio-typhoon: remove obsolete RADIO_TYPHOON_PROC_FS config option From: Hans Verkuil Thanks to Robert P.J. Day for finding this. Priority: normal Signed-off-by: Hans Verkuil Thanks-to: Robert P.J. Day --- linux/drivers/media/radio/Kconfig | 10 ---------- 1 file changed, 10 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/radio/Kconfig b/linux/drivers/media/radio/Kconfig index 41bbec6df..0e39edf75 100644 --- a/linux/drivers/media/radio/Kconfig +++ b/linux/drivers/media/radio/Kconfig @@ -288,16 +288,6 @@ config RADIO_TYPHOON To compile this driver as a module, choose M here: the module will be called radio-typhoon. -config RADIO_TYPHOON_PROC_FS - bool "Support for /proc/radio-typhoon" - depends on PROC_FS && RADIO_TYPHOON - help - Say Y here if you want the typhoon radio card driver to write - status information (frequency, volume, muted, mute frequency, - base address) to /proc/radio-typhoon. The file can be viewed with - your favorite pager (i.e. use "more /proc/radio-typhoon" or "less - /proc/radio-typhoon" or simply "cat /proc/radio-typhoon"). - config RADIO_TYPHOON_PORT hex "Typhoon I/O port (0x316 or 0x336)" depends on RADIO_TYPHOON=y -- cgit v1.2.3 From 1b6c4f0e847da28690a2d746d09e80e25eb22fbc Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 13 Aug 2009 16:30:25 -0300 Subject: Update KConfig File to enable SDIO and USB interfaces From: Udi Atar Update KConfig file to enbale selection of SDIO and USB interfaces, and add dependancy on relevant modules. Priority: normal Signed-off-by: Udi Atar [mchehab@redhat.com: fix merge conflicts and remove default: m] Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/siano/Kconfig | 41 +++++++++++++++++++++------------- linux/drivers/media/dvb/siano/Makefile | 9 ++++---- 2 files changed, 30 insertions(+), 20 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/siano/Kconfig b/linux/drivers/media/dvb/siano/Kconfig index 88847d1dc..cd2285f6d 100644 --- a/linux/drivers/media/dvb/siano/Kconfig +++ b/linux/drivers/media/dvb/siano/Kconfig @@ -2,25 +2,34 @@ # Siano Mobile Silicon Digital TV device configuration # -config DVB_SIANO_SMS1XXX - tristate "Siano SMS1XXX USB dongle support" - depends on DVB_CORE && USB && INPUT +config SMS_SIANO_MDTV + tristate "Siano SMS1xxx based MDTV receiver" + depends on DVB_CORE && INPUT ---help--- - Choose Y here if you have a USB dongle with a SMS1XXX chipset. + Choose Y or M here if you have MDTV receiver with a Siano chipset. - To compile this driver as a module, choose M here: the - module will be called sms1xxx. + To compile this driver as a module, choose M here + (The module will be called smsmdtv). -config DVB_SIANO_SMS1XXX_SMS_IDS - bool "Enable support for Siano Mobile Silicon default USB IDs" - depends on DVB_SIANO_SMS1XXX - default y - ---help--- - Choose Y here if you have a USB dongle with a SMS1XXX chipset - that uses Siano Mobile Silicon's default usb vid:pid. + Further documentation on this driver can be found on the WWW + at http://www.siano-ms.com/ + +if SMS_SIANO_MDTV +menu "Siano module components" - Choose N here if you would prefer to use Siano's external driver. +# Hardware interfaces support - Further documentation on this driver can be found on the WWW at - . +config SMS_USB_DRV + tristate "USB interface support" + depends on DVB_CORE && USB + ---help--- + Choose if you would like to have Siano's support for USB interface + +config SMS_SDIO_DRV + tristate "SDIO interface support" + depends on DVB_CORE && MMC + default m + ---help--- + Choose if you would like to have Siano's support for SDIO interface +endif # SMS_SIANO_MDTV diff --git a/linux/drivers/media/dvb/siano/Makefile b/linux/drivers/media/dvb/siano/Makefile index c6644d909..c54140b5a 100644 --- a/linux/drivers/media/dvb/siano/Makefile +++ b/linux/drivers/media/dvb/siano/Makefile @@ -1,8 +1,9 @@ -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 -obj-$(CONFIG_DVB_SIANO_SMS1XXX) += smsdvb.o +smsmdtv-objs := smscoreapi.o sms-cards.o smsendian.o smsir.o + +obj-$(CONFIG_SMS_SIANO_MDTV) += smsmdtv.o smsdvb.o +obj-$(CONFIG_SMS_USB_DRV) += smsusb.o +obj-$(CONFIG_SMS_SDIO_DRV) += smssdio.o EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core -- cgit v1.2.3 From 74b375ad36003080f781c9f2bdad6b837f4bc052 Mon Sep 17 00:00:00 2001 From: "Igor M. Liplianin" Date: Fri, 14 Aug 2009 03:42:21 +0300 Subject: Add support for Compro VideoMate S350 DVB-S PCI card. From: Igor M. Liplianin Add Compro VideoMate S350 DVB-S driver. The card uses zl10313, zl10039, saa7130 integrated circuits. Signed-off-by: Igor M. Liplianin --- linux/drivers/media/common/ir-keymaps.c | 48 +++++++++++++++++++++++ linux/drivers/media/video/saa7134/Kconfig | 1 + linux/drivers/media/video/saa7134/saa7134-cards.c | 31 ++++++++++++++- linux/drivers/media/video/saa7134/saa7134-dvb.c | 15 +++++++ linux/drivers/media/video/saa7134/saa7134-input.c | 5 +++ linux/drivers/media/video/saa7134/saa7134.h | 1 + 6 files changed, 100 insertions(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/common/ir-keymaps.c b/linux/drivers/media/common/ir-keymaps.c index 67c67430d..0b1566d34 100644 --- a/linux/drivers/media/common/ir-keymaps.c +++ b/linux/drivers/media/common/ir-keymaps.c @@ -2878,3 +2878,51 @@ IR_KEYTAB_TYPE ir_codes_evga_indtube[IR_KEYTAB_SIZE] = { [0x13] = KEY_CAMERA, }; EXPORT_SYMBOL_GPL(ir_codes_evga_indtube); + +IR_KEYTAB_TYPE ir_codes_videomate_s350[IR_KEYTAB_SIZE] = { + [0x00] = KEY_TV, + [0x01] = KEY_DVD, + [0x04] = KEY_RECORD, + [0x05] = KEY_VIDEO, /* TV/Video */ + [0x07] = KEY_STOP, + [0x08] = KEY_PLAYPAUSE, + [0x0a] = KEY_REWIND, + [0x0f] = KEY_FASTFORWARD, + [0x10] = KEY_CHANNELUP, + [0x12] = KEY_VOLUMEUP, + [0x13] = KEY_CHANNELDOWN, + [0x14] = KEY_MUTE, + [0x15] = KEY_VOLUMEDOWN, + [0x16] = KEY_1, + [0x17] = KEY_2, + [0x18] = KEY_3, + [0x19] = KEY_4, + [0x1a] = KEY_5, + [0x1b] = KEY_6, + [0x1c] = KEY_7, + [0x1d] = KEY_8, + [0x1e] = KEY_9, + [0x1f] = KEY_0, + [0x21] = KEY_SLEEP, + [0x24] = KEY_ZOOM, + [0x25] = KEY_LAST, /* Recall */ + [0x26] = KEY_SUBTITLE, /* CC */ + [0x27] = KEY_LANGUAGE, /* MTS */ + [0x29] = KEY_CHANNEL, /* SURF */ + [0x2b] = KEY_A, + [0x2c] = KEY_B, + [0x2f] = KEY_SHUFFLE, /* Snapshot */ + [0x23] = KEY_RADIO, + [0x02] = KEY_PREVIOUSSONG, + [0x06] = KEY_NEXTSONG, + [0x03] = KEY_EPG, + [0x09] = KEY_SETUP, + [0x22] = KEY_BACKSPACE, + [0x0c] = KEY_UP, + [0x0e] = KEY_DOWN, + [0x0b] = KEY_LEFT, + [0x0d] = KEY_RIGHT, + [0x11] = KEY_ENTER, + [0x20] = KEY_TEXT, +}; +EXPORT_SYMBOL_GPL(ir_codes_videomate_s350); diff --git a/linux/drivers/media/video/saa7134/Kconfig b/linux/drivers/media/video/saa7134/Kconfig index 5bcce092e..22bfd62c9 100644 --- a/linux/drivers/media/video/saa7134/Kconfig +++ b/linux/drivers/media/video/saa7134/Kconfig @@ -47,6 +47,7 @@ config VIDEO_SAA7134_DVB select DVB_TDA10048 if !DVB_FE_CUSTOMISE select MEDIA_TUNER_TDA18271 if !MEDIA_TUNER_CUSTOMISE select MEDIA_TUNER_TDA8290 if !MEDIA_TUNER_CUSTOMISE + select DVB_ZL10039 if !DVB_FE_CUSTOMISE ---help--- This adds support for DVB cards based on the Philips saa7134 chip. diff --git a/linux/drivers/media/video/saa7134/saa7134-cards.c b/linux/drivers/media/video/saa7134/saa7134-cards.c index 3ab7732e6..64933b5da 100644 --- a/linux/drivers/media/video/saa7134/saa7134-cards.c +++ b/linux/drivers/media/video/saa7134/saa7134-cards.c @@ -5155,6 +5155,25 @@ struct saa7134_board saa7134_boards[] = { .gpio = 0x00, }, }, + [SAA7134_BOARD_VIDEOMATE_S350] = { + /* Jan D. Louw > 2, 0x80040100, 0x80040100); saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x80040100, 0x00040100); break; + case SAA7134_BOARD_VIDEOMATE_S350: + dev->has_remote = SAA7134_REMOTE_GPIO; + saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, 0x00008000, 0x00008000); + saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x00008000, 0x00008000); + break; } return 0; } diff --git a/linux/drivers/media/video/saa7134/saa7134-dvb.c b/linux/drivers/media/video/saa7134/saa7134-dvb.c index afd9b7e5c..18223dafe 100644 --- a/linux/drivers/media/video/saa7134/saa7134-dvb.c +++ b/linux/drivers/media/video/saa7134/saa7134-dvb.c @@ -56,6 +56,7 @@ #include "zl10353.h" #include "zl10036.h" +#include "zl10039.h" #include "mt312.h" MODULE_AUTHOR("Gerd Knorr [SuSE Labs]"); @@ -968,6 +969,10 @@ static struct zl10036_config avertv_a700_tuner = { .tuner_address = 0x60, }; +static struct mt312_config zl10313_compro_s350_config = { + .demod_address = 0x0e, +}; + static struct lgdt3305_config hcw_lgdt3305_config = { .i2c_addr = 0x0e, .mpeg_mode = LGDT3305_MPEG_SERIAL, @@ -1476,6 +1481,16 @@ static int dvb_init(struct saa7134_dev *dev) __func__); } } + break; + case SAA7134_BOARD_VIDEOMATE_S350: + fe0->dvb.frontend = dvb_attach(mt312_attach, + &zl10313_compro_s350_config, &dev->i2c_adap); + if (fe0->dvb.frontend) + if (dvb_attach(zl10039_attach, fe0->dvb.frontend, + 0x60, &dev->i2c_adap) == NULL) + wprintk("%s: No zl10039 found!\n", + __func__); + break; default: wprintk("Huh? unknown DVB card?\n"); diff --git a/linux/drivers/media/video/saa7134/saa7134-input.c b/linux/drivers/media/video/saa7134/saa7134-input.c index b54bfd645..c6547f423 100644 --- a/linux/drivers/media/video/saa7134/saa7134-input.c +++ b/linux/drivers/media/video/saa7134/saa7134-input.c @@ -646,6 +646,11 @@ int saa7134_input_init1(struct saa7134_dev *dev) mask_keycode = 0x7f; polling = 40; /* ms */ break; + case SAA7134_BOARD_VIDEOMATE_S350: + ir_codes = ir_codes_videomate_s350; + mask_keycode = 0x003f00; + mask_keydown = 0x040000; + break; } if (NULL == ir_codes) { printk("%s: Oops: IR config error [card=%d]\n", diff --git a/linux/drivers/media/video/saa7134/saa7134.h b/linux/drivers/media/video/saa7134/saa7134.h index 6b0742ad7..c0757f8a1 100644 --- a/linux/drivers/media/video/saa7134/saa7134.h +++ b/linux/drivers/media/video/saa7134/saa7134.h @@ -293,6 +293,7 @@ struct saa7134_format { #define SAA7134_BOARD_BEHOLD_607RDS_MK5 166 #define SAA7134_BOARD_BEHOLD_609RDS_MK3 167 #define SAA7134_BOARD_BEHOLD_609RDS_MK5 168 +#define SAA7134_BOARD_VIDEOMATE_S350 169 #define SAA7134_MAXBOARDS 32 #define SAA7134_INPUT_MAX 8 -- cgit v1.2.3 From e67c964a2ec0b30fed9da5588068d39cbcc8e163 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 14 Aug 2009 01:45:57 -0300 Subject: gspca/Kconfig: Fix bad identation for USB_GSPCA_SN9C20X_EVDEV From: Mauro Carvalho Chehab Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/gspca/Kconfig | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/Kconfig b/linux/drivers/media/video/gspca/Kconfig index 34f46f2bc..a14561956 100644 --- a/linux/drivers/media/video/gspca/Kconfig +++ b/linux/drivers/media/video/gspca/Kconfig @@ -113,10 +113,10 @@ config USB_GSPCA_SN9C20X module will be called gspca_sn9c20x. config USB_GSPCA_SN9C20X_EVDEV - bool "Enable evdev support" - depends on USB_GSPCA_SN9C20X - ---help--- - Say Y here in order to enable evdev support for sn9c20x webcam button. + bool "Enable evdev support" + depends on USB_GSPCA_SN9C20X + ---help--- + Say Y here in order to enable evdev support for sn9c20x webcam button. config USB_GSPCA_SONIXB tristate "SONIX Bayer USB Camera Driver" -- cgit v1.2.3 From 797d74746b7e94cbcd14b03b00bc7c467834ce07 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 14 Aug 2009 01:48:42 -0300 Subject: siano/Kconfig: add missing endmenu From: Mauro Carvalho Chehab Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/siano/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/siano/Kconfig b/linux/drivers/media/dvb/siano/Kconfig index cd2285f6d..ff297ceaf 100644 --- a/linux/drivers/media/dvb/siano/Kconfig +++ b/linux/drivers/media/dvb/siano/Kconfig @@ -31,5 +31,5 @@ config SMS_SDIO_DRV default m ---help--- Choose if you would like to have Siano's support for SDIO interface - +endmenu endif # SMS_SIANO_MDTV -- cgit v1.2.3 From 9e69ff729e59aa0acf91cb2a2aa546e874f53a51 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 2 Jul 2009 14:50:35 +0000 Subject: cx88: High resolution timer for Remote Controls From: Andrzej Hajda Patch solves problem of missed keystrokes on some remote controls, as reported on http://bugzilla.kernel.org/show_bug.cgi?id=9637 . Signed-off-by: Andrzej Hajda Signed-off-by: Jean Delvare Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/cx88/cx88-input.c | 37 +++++++++++++---------------- 1 file changed, 17 insertions(+), 20 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/cx88/cx88-input.c b/linux/drivers/media/video/cx88/cx88-input.c index 8d0042ab2..a585245df 100644 --- a/linux/drivers/media/video/cx88/cx88-input.c +++ b/linux/drivers/media/video/cx88/cx88-input.c @@ -23,10 +23,10 @@ */ #include -#include #include #include #include +#include #include "compat.h" #include "cx88.h" @@ -49,7 +49,7 @@ struct cx88_IR { /* poll external decoder */ int polling; - struct delayed_work work; + struct hrtimer timer; u32 gpio_addr; u32 last_gpio; u32 mask_keycode; @@ -145,31 +145,28 @@ static void cx88_ir_handle_key(struct cx88_IR *ir) } } -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) -static void cx88_ir_work(void *data) -#else -static void cx88_ir_work(struct work_struct *work) -#endif +enum hrtimer_restart cx88_ir_work(struct hrtimer *timer) { -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) - struct cx88_IR *ir = data; -#else - struct cx88_IR *ir = container_of(work, struct cx88_IR, work.work); -#endif + unsigned long missed; + struct cx88_IR *ir = container_of(timer, struct cx88_IR, timer); cx88_ir_handle_key(ir); - schedule_delayed_work(&ir->work, msecs_to_jiffies(ir->polling)); + missed = hrtimer_forward_now(&ir->timer, + ktime_set(0, ir->polling * 1000000)); + if (missed > 1) + ir_dprintk("Missed ticks %ld\n", missed - 1); + + return HRTIMER_RESTART; } void cx88_ir_start(struct cx88_core *core, struct cx88_IR *ir) { if (ir->polling) { -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) - INIT_DELAYED_WORK(&ir->work, cx88_ir_work, ir); -#else - INIT_DELAYED_WORK(&ir->work, cx88_ir_work); -#endif - schedule_delayed_work(&ir->work, 0); + hrtimer_init(&ir->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); + ir->timer.function = cx88_ir_work; + hrtimer_start(&ir->timer, + ktime_set(0, ir->polling * 1000000), + HRTIMER_MODE_REL); } if (ir->sampling) { core->pci_irqmask |= PCI_INT_IR_SMPINT; @@ -186,7 +183,7 @@ void cx88_ir_stop(struct cx88_core *core, struct cx88_IR *ir) } if (ir->polling) - cancel_delayed_work_sync(&ir->work); + hrtimer_cancel(&ir->timer); } /* ---------------------------------------------------------------------- */ -- cgit v1.2.3 From 2773722d57fb06561b98c93bfd44f63f640cb77a Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 20 Aug 2009 09:38:44 -0300 Subject: Kconfig files: Fix improper use of whitespaces From: Mauro Carvalho Chehab On VIDEO_M52790 and USB_GSPCA_SN9C20X, instead of tab, it were using 7 whitespaces at the beginning, probably due to some cut-and-paste trouble. Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/Kconfig | 6 +++--- linux/drivers/media/video/gspca/Kconfig | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/Kconfig b/linux/drivers/media/video/Kconfig index e8a6e4de4..14a1b6160 100644 --- a/linux/drivers/media/video/Kconfig +++ b/linux/drivers/media/video/Kconfig @@ -203,9 +203,9 @@ config VIDEO_CS53L32A module will be called cs53l32a. config VIDEO_M52790 - tristate "Mitsubishi M52790 A/V switch" - depends on VIDEO_V4L2 && I2C - ---help--- + tristate "Mitsubishi M52790 A/V switch" + depends on VIDEO_V4L2 && I2C + ---help--- Support for the Mitsubishi M52790 A/V switch. To compile this driver as a module, choose M here: the diff --git a/linux/drivers/media/video/gspca/Kconfig b/linux/drivers/media/video/gspca/Kconfig index c9166e543..6ae1522ec 100644 --- a/linux/drivers/media/video/gspca/Kconfig +++ b/linux/drivers/media/video/gspca/Kconfig @@ -112,9 +112,9 @@ config USB_GSPCA_PAC7311 module will be called gspca_pac7311. config USB_GSPCA_SN9C20X - tristate "SN9C20X USB Camera Driver" - depends on VIDEO_V4L2 && USB_GSPCA - help + tristate "SN9C20X USB Camera Driver" + depends on VIDEO_V4L2 && USB_GSPCA + help Say Y here if you want support for cameras based on the sn9c20x chips (SN9C201 and SN9C202). -- cgit v1.2.3 From a5c6c097f7fa84eb79be22e98a6cd65267c52aa9 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 20 Aug 2009 09:39:54 -0300 Subject: em28xx: MT9M111 patch introduced some broken whitespaces From: Mauro Carvalho Chehab Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/em28xx/em28xx-cards.c | 2 +- linux/drivers/media/video/em28xx/em28xx.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (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 a38586176..b8778577d 100644 --- a/linux/drivers/media/video/em28xx/em28xx-cards.c +++ b/linux/drivers/media/video/em28xx/em28xx-cards.c @@ -1896,7 +1896,7 @@ static int em28xx_hint_sensor(struct em28xx *dev) break; - case 0x143a: /* MT9M111 as found in the ECS G200 */ + case 0x143a: /* MT9M111 as found in the ECS G200 */ dev->model = EM2750_BOARD_UNKNOWN; em28xx_set_model(dev); diff --git a/linux/drivers/media/video/em28xx/em28xx.h b/linux/drivers/media/video/em28xx/em28xx.h index 70a41b640..8203c6e1d 100644 --- a/linux/drivers/media/video/em28xx/em28xx.h +++ b/linux/drivers/media/video/em28xx/em28xx.h @@ -368,7 +368,7 @@ enum em28xx_sensor { EM28XX_NOSENSOR = 0, EM28XX_MT9V011, EM28XX_MT9M001, - EM28XX_MT9M111, + EM28XX_MT9M111, }; enum em28xx_adecoder { -- cgit v1.2.3 From faf00e29cab3d09eeb930702f997a11e42b6d7f2 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 20 Aug 2009 10:13:40 -0300 Subject: saa7134: Fix bad whitespacing From: Mauro Carvalho Chehab The patch that aded ASUSTeK P7131 Analog were using 7 spaces instead of tab, probably due to some bad cut-and-paste. Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/saa7134/saa7134-cards.c | 6 +++--- linux/drivers/media/video/saa7134/saa7134-input.c | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/saa7134/saa7134-cards.c b/linux/drivers/media/video/saa7134/saa7134-cards.c index 64933b5da..32f8bdb91 100644 --- a/linux/drivers/media/video/saa7134/saa7134-cards.c +++ b/linux/drivers/media/video/saa7134/saa7134-cards.c @@ -3702,8 +3702,8 @@ struct saa7134_board saa7134_boards[] = { .amux = TV, .gpio = 0x0200000, }, - }, - [SAA7134_BOARD_ASUSTeK_P7131_ANALOG] = { + }, + [SAA7134_BOARD_ASUSTeK_P7131_ANALOG] = { .name = "ASUSTeK P7131 Analog", .audio_clock = 0x00187de7, .tuner_type = TUNER_PHILIPS_TDA8290, @@ -6623,7 +6623,7 @@ int saa7134_board_init1(struct saa7134_dev *dev) case SAA7134_BOARD_FLYDVBT_LR301: case SAA7134_BOARD_ASUSTeK_P7131_DUAL: case SAA7134_BOARD_ASUSTeK_P7131_HYBRID_LNA: - case SAA7134_BOARD_ASUSTeK_P7131_ANALOG: + case SAA7134_BOARD_ASUSTeK_P7131_ANALOG: case SAA7134_BOARD_FLYDVBTDUO: case SAA7134_BOARD_PROTEUS_2309: case SAA7134_BOARD_AVERMEDIA_A16AR: diff --git a/linux/drivers/media/video/saa7134/saa7134-input.c b/linux/drivers/media/video/saa7134/saa7134-input.c index c6547f423..585f78af3 100644 --- a/linux/drivers/media/video/saa7134/saa7134-input.c +++ b/linux/drivers/media/video/saa7134/saa7134-input.c @@ -605,7 +605,7 @@ int saa7134_input_init1(struct saa7134_dev *dev) break; case SAA7134_BOARD_ASUSTeK_P7131_DUAL: case SAA7134_BOARD_ASUSTeK_P7131_HYBRID_LNA: - case SAA7134_BOARD_ASUSTeK_P7131_ANALOG: + case SAA7134_BOARD_ASUSTeK_P7131_ANALOG: ir_codes = ir_codes_asus_pc39; mask_keydown = 0x0040000; rc5_gpio = 1; -- cgit v1.2.3 From fcf0d8c091324e9b5c0607af50b692fed42f9ec5 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 20 Aug 2009 10:14:45 -0300 Subject: fix bad whitespaces at cx88_geniatech_x8000_mt From: Mauro Carvalho Chehab It were using 7 spaces instead of tab for indent. Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/cx88/cx88-dvb.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/cx88/cx88-dvb.c b/linux/drivers/media/video/cx88/cx88-dvb.c index ab84c085f..d3d4c67ec 100644 --- a/linux/drivers/media/video/cx88/cx88-dvb.c +++ b/linux/drivers/media/video/cx88/cx88-dvb.c @@ -500,14 +500,14 @@ static struct zl10353_config cx88_pinnacle_hybrid_pctv = { }; static struct zl10353_config cx88_geniatech_x8000_mt = { - .demod_address = (0x1e >> 1), - .no_tuner = 1, - .disable_i2c_gate_ctrl = 1, + .demod_address = (0x1e >> 1), + .no_tuner = 1, + .disable_i2c_gate_ctrl = 1, #if 0 - .input_frequency = 0xe609, - .parallel_ts = 1, - .r56_agc_targets = 0x2b, - .r5c_clk_mpegts_output = 0x75, + .input_frequency = 0xe609, + .parallel_ts = 1, + .r56_agc_targets = 0x2b, + .r5c_clk_mpegts_output = 0x75, #endif }; -- cgit v1.2.3 From 2260966cdc908fdac4676bcb68dcb7fd2baea022 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 20 Aug 2009 10:15:48 -0300 Subject: cx231xx/cx231xx-conf-reg.h: fix bad whitespaces From: Mauro Carvalho Chehab It were using 7 spaces instead of tab for indent. Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/cx231xx/cx231xx-conf-reg.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/cx231xx/cx231xx-conf-reg.h b/linux/drivers/media/video/cx231xx/cx231xx-conf-reg.h index a6f398a17..31a8759f6 100644 --- a/linux/drivers/media/video/cx231xx/cx231xx-conf-reg.h +++ b/linux/drivers/media/video/cx231xx/cx231xx-conf-reg.h @@ -60,10 +60,10 @@ #define PWR_RESETOUT_EN 0x100 /* bit8 */ enum AV_MODE{ - POLARIS_AVMODE_DEFAULT = 0, - POLARIS_AVMODE_DIGITAL = 0x10, - POLARIS_AVMODE_ANALOGT_TV = 0x20, - POLARIS_AVMODE_ENXTERNAL_AV = 0x30, + POLARIS_AVMODE_DEFAULT = 0, + POLARIS_AVMODE_DIGITAL = 0x10, + POLARIS_AVMODE_ANALOGT_TV = 0x20, + POLARIS_AVMODE_ENXTERNAL_AV = 0x30, }; -- cgit v1.2.3 From 630128e6e1b7574d909def0cfdb204555e28b43b Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 20 Aug 2009 10:18:29 -0300 Subject: stv06xx: fix bad whitespaces From: Mauro Carvalho Chehab It were using 7 spaces instead of tab for indent. CC: Erik Andren Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/gspca/stv06xx/stv06xx.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/stv06xx/stv06xx.c b/linux/drivers/media/video/gspca/stv06xx/stv06xx.c index 0da8e0de0..7af511b5e 100644 --- a/linux/drivers/media/video/gspca/stv06xx/stv06xx.c +++ b/linux/drivers/media/video/gspca/stv06xx/stv06xx.c @@ -130,8 +130,8 @@ int stv06xx_write_sensor_bytes(struct sd *sd, const u8 *data, u8 len) STV06XX_URB_MSG_TIMEOUT); if (err < 0) return err; - } - return stv06xx_write_sensor_finish(sd); + } + return stv06xx_write_sensor_finish(sd); } int stv06xx_write_sensor_words(struct sd *sd, const u16 *data, u8 len) -- cgit v1.2.3 From 31da1cf039c5d397bbe955fd1e9903d19e7ff9e2 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 20 Aug 2009 10:20:06 -0300 Subject: hdpvr-control: fix bad whitespaces From: Mauro Carvalho Chehab It were using 7 spaces instead of tab for indent. CC: Janne Grunau Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/hdpvr/hdpvr-control.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/hdpvr/hdpvr-control.c b/linux/drivers/media/video/hdpvr/hdpvr-control.c index 06791749d..5a6b78b8d 100644 --- a/linux/drivers/media/video/hdpvr/hdpvr-control.c +++ b/linux/drivers/media/video/hdpvr/hdpvr-control.c @@ -178,24 +178,24 @@ error: int hdpvr_set_options(struct hdpvr_device *dev) { - hdpvr_config_call(dev, CTRL_VIDEO_STD_TYPE, dev->options.video_std); + hdpvr_config_call(dev, CTRL_VIDEO_STD_TYPE, dev->options.video_std); - hdpvr_config_call(dev, CTRL_VIDEO_INPUT_VALUE, + hdpvr_config_call(dev, CTRL_VIDEO_INPUT_VALUE, dev->options.video_input+1); - hdpvr_set_audio(dev, dev->options.audio_input+1, + hdpvr_set_audio(dev, dev->options.audio_input+1, dev->options.audio_codec); - hdpvr_set_bitrate(dev); - hdpvr_config_call(dev, CTRL_BITRATE_MODE_VALUE, + hdpvr_set_bitrate(dev); + hdpvr_config_call(dev, CTRL_BITRATE_MODE_VALUE, dev->options.bitrate_mode); - hdpvr_config_call(dev, CTRL_GOP_MODE_VALUE, dev->options.gop_mode); + hdpvr_config_call(dev, CTRL_GOP_MODE_VALUE, dev->options.gop_mode); - hdpvr_config_call(dev, CTRL_BRIGHTNESS, dev->options.brightness); - hdpvr_config_call(dev, CTRL_CONTRAST, dev->options.contrast); - hdpvr_config_call(dev, CTRL_HUE, dev->options.hue); - hdpvr_config_call(dev, CTRL_SATURATION, dev->options.saturation); - hdpvr_config_call(dev, CTRL_SHARPNESS, dev->options.sharpness); + hdpvr_config_call(dev, CTRL_BRIGHTNESS, dev->options.brightness); + hdpvr_config_call(dev, CTRL_CONTRAST, dev->options.contrast); + hdpvr_config_call(dev, CTRL_HUE, dev->options.hue); + hdpvr_config_call(dev, CTRL_SATURATION, dev->options.saturation); + hdpvr_config_call(dev, CTRL_SHARPNESS, dev->options.sharpness); - return 0; + return 0; } -- cgit v1.2.3 From 990c9e823d0db2e126fae7a2ead592ebd1ea2e6f Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 20 Aug 2009 10:28:17 -0300 Subject: cx88: Apply version 2 of high resolution timer for RC From: Mauro Carvalho Chehab Patch solves problem of missed keystrokes on some remote controls, as reported on http://bugzilla.kernel.org/show_bug.cgi?id=9637 . Changes of version 2: * Driver no longer builds on kernels < 2.6.22, so add an entry to v4l/versions.txt * Add a missing static. Build-tested on 2.6.22. Priority: normal Signed-off-by: Andrzej Hajda Signed-off-by: Jean Delvare [mchehab@redhat.com: this patch will be merged with version 1 for upstream submission] Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/cx88/cx88-input.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/cx88/cx88-input.c b/linux/drivers/media/video/cx88/cx88-input.c index a585245df..6a3687a88 100644 --- a/linux/drivers/media/video/cx88/cx88-input.c +++ b/linux/drivers/media/video/cx88/cx88-input.c @@ -23,10 +23,10 @@ */ #include +#include #include #include #include -#include #include "compat.h" #include "cx88.h" @@ -145,7 +145,7 @@ static void cx88_ir_handle_key(struct cx88_IR *ir) } } -enum hrtimer_restart cx88_ir_work(struct hrtimer *timer) +static enum hrtimer_restart cx88_ir_work(struct hrtimer *timer) { unsigned long missed; struct cx88_IR *ir = container_of(timer, struct cx88_IR, timer); -- cgit v1.2.3 From 68dc7281f696cd47941ab39f96e7e783bed14f1f Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 12 Jul 2009 14:51:10 +0000 Subject: Add support for Humax/Coex DVB-T USB Stick 2.0 High Speed MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: Nam Phạm Thành This patch adds support for Humax/Coex DVB-T USB Stick 2.0 High Speed which is a very popular tuner sold in Vietnam. Tested with at least 3 tuners. CC: Patrick Boettcher Signed-off-by: Pham Thanh Nam Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/dvb-usb/dibusb-mc.c | 10 ++++++++-- linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h | 3 +++ 2 files changed, 11 insertions(+), 2 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/dvb-usb/dibusb-mc.c b/linux/drivers/media/dvb/dvb-usb/dibusb-mc.c index 059cec955..a05b9f875 100644 --- a/linux/drivers/media/dvb/dvb-usb/dibusb-mc.c +++ b/linux/drivers/media/dvb/dvb-usb/dibusb-mc.c @@ -42,6 +42,8 @@ static struct usb_device_id dibusb_dib3000mc_table [] = { /* 11 */ { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ARTEC_T14_WARM) }, /* 12 */ { USB_DEVICE(USB_VID_LEADTEK, USB_PID_WINFAST_DTV_DONGLE_COLD) }, /* 13 */ { USB_DEVICE(USB_VID_LEADTEK, USB_PID_WINFAST_DTV_DONGLE_WARM) }, +/* 14 */ { USB_DEVICE(USB_VID_HUMAX_COEX, USB_PID_DVB_T_USB_STICK_HIGH_SPEED_COLD) }, +/* 15 */ { USB_DEVICE(USB_VID_HUMAX_COEX, USB_PID_DVB_T_USB_STICK_HIGH_SPEED_WARM) }, { } /* Terminating entry */ }; MODULE_DEVICE_TABLE (usb, dibusb_dib3000mc_table); @@ -66,7 +68,7 @@ static struct dvb_usb_device_properties dibusb_mc_properties = { /* parameter for the MPEG2-data transfer */ .stream = { .type = USB_BULK, - .count = 7, + .count = 8, .endpoint = 0x06, .u = { .bulk = { @@ -88,7 +90,7 @@ static struct dvb_usb_device_properties dibusb_mc_properties = { .generic_bulk_ctrl_endpoint = 0x01, - .num_device_descs = 7, + .num_device_descs = 8, .devices = { { "DiBcom USB2.0 DVB-T reference design (MOD3000P)", { &dibusb_dib3000mc_table[0], NULL }, @@ -119,6 +121,10 @@ static struct dvb_usb_device_properties dibusb_mc_properties = { { &dibusb_dib3000mc_table[12], NULL }, { &dibusb_dib3000mc_table[13], NULL }, }, + { "Humax/Coex DVB-T USB Stick 2.0 High Speed", + { &dibusb_dib3000mc_table[14], NULL }, + { &dibusb_dib3000mc_table[15], NULL }, + }, { NULL }, } }; 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 6eccce1a7..bf7320167 100644 --- a/linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h +++ b/linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h @@ -58,6 +58,7 @@ #define USB_VID_GIGABYTE 0x1044 #define USB_VID_YUAN 0x1164 #define USB_VID_XTENSIONS 0x1ae7 +#define USB_VID_HUMAX_COEX 0x10b9 /* Product IDs */ #define USB_PID_ADSTECH_USB2_COLD 0xa333 @@ -260,5 +261,7 @@ #define USB_PID_SONY_PLAYTV 0x0003 #define USB_PID_ELGATO_EYETV_DTT 0x0021 #define USB_PID_ELGATO_EYETV_DTT_Dlx 0x0020 +#define USB_PID_DVB_T_USB_STICK_HIGH_SPEED_COLD 0x5000 +#define USB_PID_DVB_T_USB_STICK_HIGH_SPEED_WARM 0x5001 #endif -- cgit v1.2.3 From 6bd143668c399af17edddaaff09227d2217e6dd6 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 20 Jul 2009 14:20:47 +0000 Subject: make digital side of pcHDTV HD-3000 functional again From: Jarod Wilson The dvb side of the pcHDTV HD-3000 doesn't work since at least 2.6.29. The crux of the problem is this: the HD-3000's device ID matches the modalias for the cx8800 driver, but not the cx8802 driver, which is required to set up the digital side of the card. You can load up cx8802 just fine, but cx88-dvb falls on its face, because the call to cx8802_register_driver() attempts to traverse the cx8802_devlist, which is completely empty. The list is only populated by the cx8802_probe() function, which never gets called for the HD-3000, as its device ID isn't matched by the cx8802 driver, so you wind up getting an -ENODEV return from cx8802_register_driver() back to cx88-dvb, and as a result, no digital side of the card for you. Long story short, by simply adding a vendor/device/subvendor/subdevice block to cx88-mpeg.c, cx8802_probe() will run, the cx88-2_devlist will get populated, cx8802_register_driver() won't fail, and cx88-dvb can actually load up all the way on this card. Channel scanning is of course currently failing for me still (works fine on several other cards I have handy), but that's another problem for another day... There might be a Better Way to do this, and I'm open to suggestions and willing to try them out, but this Works For Me. Signed-off-by: Jarod Wilson Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/cx88/cx88-mpeg.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/cx88/cx88-mpeg.c b/linux/drivers/media/video/cx88/cx88-mpeg.c index e1bcd556b..c77981a8e 100644 --- a/linux/drivers/media/video/cx88/cx88-mpeg.c +++ b/linux/drivers/media/video/cx88/cx88-mpeg.c @@ -897,6 +897,11 @@ static struct pci_device_id cx8802_pci_tbl[] = { .device = 0x8802, .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID, + },{ /* pcHDTV HD-3000 */ + .vendor = 0x14f1, + .device = 0x8800, + .subvendor = 0x7063, + .subdevice = 0x3000, },{ /* --- end of list --- */ } -- cgit v1.2.3 From 232a32e4823887e382af8b96a5f21e7ab3891e21 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 21 Jul 2009 16:47:46 +0000 Subject: Use dst_type field instead of type_flags From: Julia Lawall It seems from other code that it is the dst_type field rather than the type_flags field that contains values of the form DST_TYPE_IS... The type_flags field contains values of the form DST_TYPE_HAS... The semantic match that finds this problem is as follows: (http://www.emn.fr/x-info/coccinelle/) // @@ struct dst_state E; @@ ( *E.type_flags == \( DST_TYPE_IS_SAT\|DST_TYPE_IS_TERR\|DST_TYPE_IS_CABLE\|DST_TYPE_IS_ATSC \) | *E.type_flags != \( DST_TYPE_IS_SAT\|DST_TYPE_IS_TERR\|DST_TYPE_IS_CABLE\|DST_TYPE_IS_ATSC \) ) // CC: Manu Abraham Signed-off-by: Julia Lawall Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/bt8xx/dst.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/bt8xx/dst.c b/linux/drivers/media/dvb/bt8xx/dst.c index fec1d77fa..91353a6fa 100644 --- a/linux/drivers/media/dvb/bt8xx/dst.c +++ b/linux/drivers/media/dvb/bt8xx/dst.c @@ -1059,7 +1059,7 @@ static int dst_get_tuner_info(struct dst_state *state) dprintk(verbose, DST_ERROR, 1, "DST type has TS=188"); } if (state->board_info[0] == 0xbc) { - if (state->type_flags != DST_TYPE_IS_ATSC) + if (state->dst_type != DST_TYPE_IS_ATSC) state->type_flags |= DST_TYPE_HAS_TS188; else state->type_flags |= DST_TYPE_HAS_NEWTUNE_2; -- cgit v1.2.3 From 27ec6ede22cb9fd152a2701c4f24b7f54ffb5b2f Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 22 Jul 2009 03:02:29 +0000 Subject: ARRAY_SIZE changes From: Mauro Carvalho Chehab These changes were a direct result of using a semantic patch More information can be found at http://www.emn.fr/x-info/coccinelle/ Priority: normal [mchehab@redhat.com: fix a merge conflict] Signed-off-by: Stoyan Gaydarov Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/gspca/conex.c | 2 +- linux/drivers/media/video/gspca/etoms.c | 4 ++-- linux/drivers/media/video/gspca/spca501.c | 2 +- linux/drivers/media/video/gspca/spca506.c | 2 +- linux/drivers/media/video/gspca/sunplus.c | 4 ++-- linux/drivers/media/video/gspca/zc3xx.c | 2 +- linux/drivers/media/video/tveeprom.c | 4 ++-- 7 files changed, 10 insertions(+), 10 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/conex.c b/linux/drivers/media/video/gspca/conex.c index 8d48ea174..eca003566 100644 --- a/linux/drivers/media/video/gspca/conex.c +++ b/linux/drivers/media/video/gspca/conex.c @@ -820,7 +820,7 @@ static int sd_config(struct gspca_dev *gspca_dev, cam = &gspca_dev->cam; cam->cam_mode = vga_mode; - cam->nmodes = sizeof vga_mode / sizeof vga_mode[0]; + cam->nmodes = ARRAY_SIZE(vga_mode); sd->brightness = BRIGHTNESS_DEF; sd->contrast = CONTRAST_DEF; diff --git a/linux/drivers/media/video/gspca/etoms.c b/linux/drivers/media/video/gspca/etoms.c index 84f3a5eb8..42b36b8b7 100644 --- a/linux/drivers/media/video/gspca/etoms.c +++ b/linux/drivers/media/video/gspca/etoms.c @@ -635,10 +635,10 @@ static int sd_config(struct gspca_dev *gspca_dev, sd->sensor = id->driver_info; if (sd->sensor == SENSOR_PAS106) { cam->cam_mode = sif_mode; - cam->nmodes = sizeof sif_mode / sizeof sif_mode[0]; + cam->nmodes = ARRAY_SIZE(sif_mode); } else { cam->cam_mode = vga_mode; - cam->nmodes = sizeof vga_mode / sizeof vga_mode[0]; + cam->nmodes = ARRAY_SIZE(vga_mode); gspca_dev->ctrl_dis = (1 << COLOR_IDX); } sd->brightness = BRIGHTNESS_DEF; diff --git a/linux/drivers/media/video/gspca/spca501.c b/linux/drivers/media/video/gspca/spca501.c index 61dfc714f..9c4a2e6db 100644 --- a/linux/drivers/media/video/gspca/spca501.c +++ b/linux/drivers/media/video/gspca/spca501.c @@ -1948,7 +1948,7 @@ static int sd_config(struct gspca_dev *gspca_dev, cam = &gspca_dev->cam; cam->cam_mode = vga_mode; - cam->nmodes = sizeof vga_mode / sizeof vga_mode[0]; + cam->nmodes = ARRAY_SIZE(vga_mode); sd->subtype = id->driver_info; sd->brightness = sd_ctrls[MY_BRIGHTNESS].qctrl.default_value; sd->contrast = sd_ctrls[MY_CONTRAST].qctrl.default_value; diff --git a/linux/drivers/media/video/gspca/spca506.c b/linux/drivers/media/video/gspca/spca506.c index 3a0c893f9..a199298a6 100644 --- a/linux/drivers/media/video/gspca/spca506.c +++ b/linux/drivers/media/video/gspca/spca506.c @@ -286,7 +286,7 @@ static int sd_config(struct gspca_dev *gspca_dev, cam = &gspca_dev->cam; cam->cam_mode = vga_mode; - cam->nmodes = sizeof vga_mode / sizeof vga_mode[0]; + cam->nmodes = ARRAY_SIZE(vga_mode); sd->brightness = sd_ctrls[SD_BRIGHTNESS].qctrl.default_value; sd->contrast = sd_ctrls[SD_CONTRAST].qctrl.default_value; sd->colors = sd_ctrls[SD_COLOR].qctrl.default_value; diff --git a/linux/drivers/media/video/gspca/sunplus.c b/linux/drivers/media/video/gspca/sunplus.c index 270b86f24..33bac051d 100644 --- a/linux/drivers/media/video/gspca/sunplus.c +++ b/linux/drivers/media/video/gspca/sunplus.c @@ -872,7 +872,7 @@ static int sd_config(struct gspca_dev *gspca_dev, /* case BRIDGE_SPCA504: */ /* case BRIDGE_SPCA536: */ cam->cam_mode = vga_mode; - cam->nmodes = sizeof vga_mode / sizeof vga_mode[0]; + cam->nmodes =ARRAY_SIZE(vga_mode); break; case BRIDGE_SPCA533: cam->cam_mode = custom_mode; @@ -883,7 +883,7 @@ static int sd_config(struct gspca_dev *gspca_dev, break; case BRIDGE_SPCA504C: cam->cam_mode = vga_mode2; - cam->nmodes = sizeof vga_mode2 / sizeof vga_mode2[0]; + cam->nmodes = ARRAY_SIZE(vga_mode2); break; } sd->brightness = sd_ctrls[SD_BRIGHTNESS].qctrl.default_value; diff --git a/linux/drivers/media/video/gspca/zc3xx.c b/linux/drivers/media/video/gspca/zc3xx.c index 2a9480138..02b6e185f 100644 --- a/linux/drivers/media/video/gspca/zc3xx.c +++ b/linux/drivers/media/video/gspca/zc3xx.c @@ -7607,7 +7607,7 @@ static int sd_get_jcomp(struct gspca_dev *gspca_dev, static const struct sd_desc sd_desc = { .name = MODULE_NAME, .ctrls = sd_ctrls, - .nctrls = sizeof sd_ctrls / sizeof sd_ctrls[0], + .nctrls = ARRAY_SIZE(sd_ctrls), .config = sd_config, .init = sd_init, .start = sd_start, diff --git a/linux/drivers/media/video/tveeprom.c b/linux/drivers/media/video/tveeprom.c index 5e3c9f4e2..085b869f5 100644 --- a/linux/drivers/media/video/tveeprom.c +++ b/linux/drivers/media/video/tveeprom.c @@ -647,14 +647,14 @@ void tveeprom_hauppauge_analog(struct i2c_client *c, struct tveeprom *tvee, tvee->has_radio = 1; } - if (tuner1 < sizeof(hauppauge_tuner)/sizeof(struct HAUPPAUGE_TUNER)) { + if (tuner1 < ARRAY_SIZE(hauppauge_tuner)) { tvee->tuner_type = hauppauge_tuner[tuner1].id; t_name1 = hauppauge_tuner[tuner1].name; } else { t_name1 = "unknown"; } - if (tuner2 < sizeof(hauppauge_tuner)/sizeof(struct HAUPPAUGE_TUNER)) { + if (tuner2 < ARRAY_SIZE(hauppauge_tuner)) { tvee->tuner2_type = hauppauge_tuner[tuner2].id; t_name2 = hauppauge_tuner[tuner2].name; } else { -- cgit v1.2.3 From 56c2830bdf4029ac6336993016266d843f99fe35 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 20 Aug 2009 11:58:08 -0300 Subject: revert changeset 12476:a03f8edcaba7 From: Mauro Carvalho Chehab As asked by Jarod Wilson, this patch doesn't work properly. Reverting it. Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/cx88/cx88-mpeg.c | 5 ----- 1 file changed, 5 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/cx88/cx88-mpeg.c b/linux/drivers/media/video/cx88/cx88-mpeg.c index c77981a8e..e1bcd556b 100644 --- a/linux/drivers/media/video/cx88/cx88-mpeg.c +++ b/linux/drivers/media/video/cx88/cx88-mpeg.c @@ -897,11 +897,6 @@ static struct pci_device_id cx8802_pci_tbl[] = { .device = 0x8802, .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID, - },{ /* pcHDTV HD-3000 */ - .vendor = 0x14f1, - .device = 0x8800, - .subvendor = 0x7063, - .subdevice = 0x3000, },{ /* --- end of list --- */ } -- cgit v1.2.3 From 6d6da3a7c53bcd97db93c50943018e880d31412e Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 24 Jul 2009 16:45:41 +0000 Subject: V4L/DVB: af9015: add new USB ID for KWorld PlusTV Dual DVB-T Stick (DVB-T 399U) From: Mart Raudsepp Add new USB ID (1b80:e400) for KWorld PlusTV Dual DVB-T Stick (DVB-T 399U). The model number on the devices sticker label is "KW-DVB-T 399UR". Signed-off-by: Mart Raudsepp Acked-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/dvb-usb/af9015.c | 4 +++- linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/dvb-usb/af9015.c b/linux/drivers/media/dvb/dvb-usb/af9015.c index 7798aabaa..21815367f 100644 --- a/linux/drivers/media/dvb/dvb-usb/af9015.c +++ b/linux/drivers/media/dvb/dvb-usb/af9015.c @@ -1267,6 +1267,7 @@ static struct usb_device_id af9015_usb_table[] = { {USB_DEVICE(USB_VID_KWORLD_2, USB_PID_CONCEPTRONIC_CTVDIGRCU)}, {USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_MC810)}, {USB_DEVICE(USB_VID_KYE, USB_PID_GENIUS_TVGO_DVB_T03)}, +/* 25 */{USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_399U_2)}, {0}, }; MODULE_DEVICE_TABLE(usb, af9015_usb_table); @@ -1347,7 +1348,8 @@ static struct dvb_usb_device_properties af9015_properties[] = { { .name = "KWorld PlusTV Dual DVB-T Stick " \ "(DVB-T 399U)", - .cold_ids = {&af9015_usb_table[4], NULL}, + .cold_ids = {&af9015_usb_table[4], + &af9015_usb_table[25], NULL}, .warm_ids = {NULL}, }, { 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 bf7320167..3324a73d5 100644 --- a/linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h +++ b/linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h @@ -104,6 +104,7 @@ #define USB_PID_GRANDTEC_DVBT_USB_WARM 0x0fa1 #define USB_PID_INTEL_CE9500 0x9500 #define USB_PID_KWORLD_399U 0xe399 +#define USB_PID_KWORLD_399U_2 0xe400 #define USB_PID_KWORLD_395U 0xe396 #define USB_PID_KWORLD_395U_2 0xe39b #define USB_PID_KWORLD_395U_3 0xe395 -- cgit v1.2.3 From 6d42d3dbff0a3351611853581210b9fda6301510 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 31 Jul 2009 16:40:43 +0000 Subject: Fix lowband tuning with tda8261 From: Julian Scheel Attached is a patch which fixes tuning to low frequency channels with stb0899+tda8261 cards like the KNC TV-Station DVB-S2. The cause of the issue was a broken if construct, which should have been an if/else if, so that the setting for the lowest matching frequency is applied. Without this patch for example tuning to "arte" on Astra 19.2, 10744MHz SR22000 failed most times and when it failed the communication between driver and tda8261 was completely broken. This problem disappears with the attached patch. Signed-off-by: Julian Scheel Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/frontends/tda8261.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/frontends/tda8261.c b/linux/drivers/media/dvb/frontends/tda8261.c index b6d177799..320c3c36d 100644 --- a/linux/drivers/media/dvb/frontends/tda8261.c +++ b/linux/drivers/media/dvb/frontends/tda8261.c @@ -136,9 +136,9 @@ static int tda8261_set_state(struct dvb_frontend *fe, if (frequency < 1450000) buf[3] = 0x00; - if (frequency < 2000000) + else if (frequency < 2000000) buf[3] = 0x40; - if (frequency < 2150000) + else if (frequency < 2150000) buf[3] = 0x80; /* Set params */ -- cgit v1.2.3 From 2cf40a2b22144d35374eec8c26aab124bc129818 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 1 Aug 2009 11:02:38 +0000 Subject: firedtv: add PID filtering for SW zigzag retune From: Henrik Kurelid The AVC protocol uses the same command for tuning and PID filtering and since dvb-core uses a software zigzagging to do automatic retuning this could cause all PID filters to be cleared. PID filter information is now included in all DSD commands to the card. Background: There is a problem in the firedtv driver that causes recordings to stop if the SW zigzag algorithm in dvb-core kicks in with a retune after the application has set up the PID filters. Since tuning and setting PID filters uses the same AVC command (DSD) and only the replace subfunction is supported by the card, it is not possible to do a retune without setting the PID filters. This means that the PID filtering has to be sent in each tune. This problem applies to C and T cards since S and S2 cards tune using a vendor specific command. The patch corrects the problem by sending the PID list in each tune. I have tested it on my T card with a good result. How to trigger problem: Zap to a channel and output AV to a file, e.g. "tzap -c channels.conf SVT1 -r -o SVT1.ts". After a short while, pull the antenna cable from the card. The lock on the channel will disappear and the TS file will stop increasing in size. Wait a couple of seconds. Replug the cable again. You will get a lock on the channel again, but the TS file will never increase in size agains sinze no PIDS are filtered. Tested with kaffeine with DVB-T and DVB-C: Fixes retuning after antenna was plugged out and back in with DVB-T. Does not fix this with DVB-C, but also doesn't regress on DVB-C. Signed-off-by: Henrik Kurelid Signed-off-by: Stefan Richter Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/firewire/firedtv-avc.c | 40 +++++++++++++++++++------- 1 file changed, 30 insertions(+), 10 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/firewire/firedtv-avc.c b/linux/drivers/media/dvb/firewire/firedtv-avc.c index 620fa2c65..a2041df5f 100644 --- a/linux/drivers/media/dvb/firewire/firedtv-avc.c +++ b/linux/drivers/media/dvb/firewire/firedtv-avc.c @@ -259,6 +259,26 @@ int avc_recv(struct firedtv *fdtv, void *data, size_t length) return 0; } +static int add_pid_filter(struct firedtv *fdtv, u8 *operand) +{ + int i, n, pos = 1; + + for (i = 0, n = 0; i < 16; i++) { + if (test_bit(i, &fdtv->channel_active)) { + operand[pos++] = 0x13; /* flowfunction relay */ + operand[pos++] = 0x80; /* dsd_sel_spec_valid_flags -> PID */ + operand[pos++] = (fdtv->channel_pid[i] >> 8) & 0x1f; + operand[pos++] = fdtv->channel_pid[i] & 0xff; + operand[pos++] = 0x00; /* tableID */ + operand[pos++] = 0x00; /* filter_length */ + n++; + } + } + operand[0] = n; + + return pos; +} + /* * tuning command for setting the relative LNB frequency * (not supported by the AVC standard) @@ -321,7 +341,8 @@ static void avc_tuner_tuneqpsk(struct firedtv *fdtv, } } -static void avc_tuner_dsd_dvb_c(struct dvb_frontend_parameters *params, +static void avc_tuner_dsd_dvb_c(struct firedtv *fdtv, + struct dvb_frontend_parameters *params, struct avc_command_frame *c) { c->opcode = AVC_OPCODE_DSD; @@ -383,13 +404,13 @@ static void avc_tuner_dsd_dvb_c(struct dvb_frontend_parameters *params, c->operand[20] = 0x00; c->operand[21] = 0x00; - /* Nr_of_dsd_sel_specs = 0 -> no PIDs are transmitted */ - c->operand[22] = 0x00; - c->length = 28; + /* Add PIDs to filter */ + c->length = ALIGN(22 + add_pid_filter(fdtv, &c->operand[22]) + 3, 4); } -static void avc_tuner_dsd_dvb_t(struct dvb_frontend_parameters *params, +static void avc_tuner_dsd_dvb_t(struct firedtv *fdtv, + struct dvb_frontend_parameters *params, struct avc_command_frame *c) { struct dvb_ofdm_parameters *ofdm = ¶ms->u.ofdm; @@ -486,10 +507,9 @@ static void avc_tuner_dsd_dvb_t(struct dvb_frontend_parameters *params, c->operand[15] = 0x00; /* network_ID[0] */ c->operand[16] = 0x00; /* network_ID[1] */ - /* Nr_of_dsd_sel_specs = 0 -> no PIDs are transmitted */ - c->operand[17] = 0x00; - c->length = 24; + /* Add PIDs to filter */ + c->length = ALIGN(17 + add_pid_filter(fdtv, &c->operand[17]) + 3, 4); } int avc_tuner_dsd(struct firedtv *fdtv, @@ -507,8 +527,8 @@ int avc_tuner_dsd(struct firedtv *fdtv, switch (fdtv->type) { case FIREDTV_DVB_S: case FIREDTV_DVB_S2: avc_tuner_tuneqpsk(fdtv, params, c); break; - case FIREDTV_DVB_C: avc_tuner_dsd_dvb_c(params, c); break; - case FIREDTV_DVB_T: avc_tuner_dsd_dvb_t(params, c); break; + case FIREDTV_DVB_C: avc_tuner_dsd_dvb_c(fdtv, params, c); break; + case FIREDTV_DVB_T: avc_tuner_dsd_dvb_t(fdtv, params, c); break; default: BUG(); } -- cgit v1.2.3 From 3a5d86fcd1ef7eb3617d26046cdffea4245ca987 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 1 Aug 2009 19:48:41 +0000 Subject: Use DIV_ROUND_CLOSEST From: Julia Lawall The kernel.h macro DIV_ROUND_CLOSEST performs the computation (x + d/2)/d but is perhaps more readable. The semantic patch that makes this change is as follows: (http://www.emn.fr/x-info/coccinelle/) // @haskernel@ @@ @depends on haskernel@ expression x,__divisor; @@ - (((x) + ((__divisor) / 2)) / (__divisor)) + DIV_ROUND_CLOSEST(x,__divisor) // Signed-off-by: Julia Lawall Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/frontends/dib7000p.c | 2 +- linux/drivers/media/dvb/frontends/stb6100.c | 4 +++- linux/drivers/media/dvb/frontends/tda10021.c | 2 +- linux/drivers/media/dvb/frontends/ves1820.c | 2 +- linux/drivers/media/dvb/pluto2/pluto2.c | 2 +- linux/drivers/media/video/tuner-core.c | 4 ++-- linux/drivers/media/video/v4l1-compat.c | 5 ++--- 7 files changed, 11 insertions(+), 10 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/frontends/dib7000p.c b/linux/drivers/media/dvb/frontends/dib7000p.c index ebb7594e3..d56de75db 100644 --- a/linux/drivers/media/dvb/frontends/dib7000p.c +++ b/linux/drivers/media/dvb/frontends/dib7000p.c @@ -909,7 +909,7 @@ static void dib7000p_spur_protect(struct dib7000p_state *state, u32 rf_khz, u32 255, 255, 255, 255, 255, 255}; u32 xtal = state->cfg.bw->xtal_hz / 1000; - int f_rel = ( (rf_khz + xtal/2) / xtal) * xtal - rf_khz; + int f_rel = DIV_ROUND_CLOSEST(rf_khz, xtal) * xtal - rf_khz; int k; int coef_re[8],coef_im[8]; int bw_khz = bw; diff --git a/linux/drivers/media/dvb/frontends/stb6100.c b/linux/drivers/media/dvb/frontends/stb6100.c index 2b1af36b8..540967545 100644 --- a/linux/drivers/media/dvb/frontends/stb6100.c +++ b/linux/drivers/media/dvb/frontends/stb6100.c @@ -374,7 +374,9 @@ static int stb6100_set_frequency(struct dvb_frontend *fe, u32 frequency) /* N(I) = floor(f(VCO) / (f(XTAL) * (PSD2 ? 2 : 1))) */ nint = fvco / (state->reference << psd2); /* N(F) = round(f(VCO) / f(XTAL) * (PSD2 ? 2 : 1) - N(I)) * 2 ^ 9 */ - nfrac = (((fvco - (nint * state->reference << psd2)) << (9 - psd2)) + state->reference / 2) / state->reference; + nfrac = DIV_ROUND_CLOSEST((fvco - (nint * state->reference << psd2)) + << (9 - psd2), + state->reference); dprintk(verbose, FE_DEBUG, 1, "frequency = %u, srate = %u, g = %u, odiv = %u, psd2 = %u, fxtal = %u, osm = %u, fvco = %u, N(I) = %u, N(F) = %u", frequency, srate, (unsigned int)g, (unsigned int)odiv, diff --git a/linux/drivers/media/dvb/frontends/tda10021.c b/linux/drivers/media/dvb/frontends/tda10021.c index 242636e59..d90cd60ce 100644 --- a/linux/drivers/media/dvb/frontends/tda10021.c +++ b/linux/drivers/media/dvb/frontends/tda10021.c @@ -176,7 +176,7 @@ static int tda10021_set_symbolrate (struct tda10021_state* state, u32 symbolrate tmp = ((symbolrate << 4) % FIN) << 8; ratio = (ratio << 8) + tmp / FIN; tmp = (tmp % FIN) << 8; - ratio = (ratio << 8) + (tmp + FIN/2) / FIN; + ratio = (ratio << 8) + DIV_ROUND_CLOSEST(tmp, FIN); BDR = ratio; BDRI = (((XIN << 5) / symbolrate) + 1) / 2; diff --git a/linux/drivers/media/dvb/frontends/ves1820.c b/linux/drivers/media/dvb/frontends/ves1820.c index 6e78e4865..550a07a8a 100644 --- a/linux/drivers/media/dvb/frontends/ves1820.c +++ b/linux/drivers/media/dvb/frontends/ves1820.c @@ -165,7 +165,7 @@ static int ves1820_set_symbolrate(struct ves1820_state *state, u32 symbolrate) tmp = ((symbolrate << 4) % fin) << 8; ratio = (ratio << 8) + tmp / fin; tmp = (tmp % fin) << 8; - ratio = (ratio << 8) + (tmp + fin / 2) / fin; + ratio = (ratio << 8) + DIV_ROUND_CLOSEST(tmp, fin); BDR = ratio; BDRI = (((state->config->xin << 5) / symbolrate) + 1) / 2; diff --git a/linux/drivers/media/dvb/pluto2/pluto2.c b/linux/drivers/media/dvb/pluto2/pluto2.c index 647f6290e..8b6b2c094 100644 --- a/linux/drivers/media/dvb/pluto2/pluto2.c +++ b/linux/drivers/media/dvb/pluto2/pluto2.c @@ -447,7 +447,7 @@ static inline u32 divide(u32 numerator, u32 denominator) if (denominator == 0) return ~0; - return (numerator + denominator / 2) / denominator; + return DIV_ROUND_CLOSEST(numerator, denominator); } /* LG Innotek TDTE-E001P (Infineon TUA6034) */ diff --git a/linux/drivers/media/video/tuner-core.c b/linux/drivers/media/video/tuner-core.c index 85b133df4..a4f6c19b7 100644 --- a/linux/drivers/media/video/tuner-core.c +++ b/linux/drivers/media/video/tuner-core.c @@ -842,8 +842,8 @@ static int tuner_g_frequency(struct v4l2_subdev *sd, struct v4l2_frequency *f) fe_tuner_ops->get_frequency(&t->fe, &abs_freq); f->frequency = (V4L2_TUNER_RADIO == t->mode) ? - (abs_freq * 2 + 125/2) / 125 : - (abs_freq + 62500/2) / 62500; + DIV_ROUND_CLOSEST(abs_freq * 2, 125) : + DIV_ROUND_CLOSEST(abs_freq, 62500); return 0; } f->frequency = (V4L2_TUNER_RADIO == t->mode) ? diff --git a/linux/drivers/media/video/v4l1-compat.c b/linux/drivers/media/video/v4l1-compat.c index ee3991f2f..2225243ad 100644 --- a/linux/drivers/media/video/v4l1-compat.c +++ b/linux/drivers/media/video/v4l1-compat.c @@ -77,9 +77,8 @@ get_v4l_control(struct file *file, dprintk("VIDIOC_G_CTRL: %d\n", err); return 0; } - return ((ctrl2.value - qctrl2.minimum) * 65535 - + (qctrl2.maximum - qctrl2.minimum) / 2) - / (qctrl2.maximum - qctrl2.minimum); + return DIV_ROUND_CLOSEST((ctrl2.value-qctrl2.minimum) * 65535, + qctrl2.maximum - qctrl2.minimum); } return 0; } -- cgit v1.2.3 From 6a6c67ec6ada8fcc26c4fdbfbee70531fa737bcf Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 2 Aug 2009 19:01:19 +0000 Subject: zl10353: correct implementation of FE_READ_UNCORRECTED_BLOCKS From: Aleksandr V. Piskunov Makes zl10353 a bit more DVB API compliant: FE_READ_UNCORRECTED_BLOCKS - keep a counter of UNC blocks FE_GET_FRONTEND - return last set frequency instead of zero Signed-off-by: Aleksandr V. Piskunov Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/frontends/zl10353.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/frontends/zl10353.c b/linux/drivers/media/dvb/frontends/zl10353.c index a69e9602c..37a050efd 100644 --- a/linux/drivers/media/dvb/frontends/zl10353.c +++ b/linux/drivers/media/dvb/frontends/zl10353.c @@ -39,6 +39,8 @@ struct zl10353_state { struct zl10353_config config; enum fe_bandwidth bandwidth; + u32 ucblocks; + u32 frequency; }; static int debug; @@ -204,6 +206,8 @@ static int zl10353_set_parameters(struct dvb_frontend *fe, u16 tps = 0; struct dvb_ofdm_parameters *op = ¶m->u.ofdm; + state->frequency = param->frequency; + zl10353_single_write(fe, RESET, 0x80); udelay(200); zl10353_single_write(fe, 0xEA, 0x01); @@ -469,7 +473,7 @@ static int zl10353_get_parameters(struct dvb_frontend *fe, break; } - param->frequency = 0; + param->frequency = state->frequency; op->bandwidth = state->bandwidth; param->inversion = INVERSION_AUTO; @@ -549,9 +553,13 @@ static int zl10353_read_snr(struct dvb_frontend *fe, u16 *snr) static int zl10353_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) { struct zl10353_state *state = fe->demodulator_priv; + u32 ubl = 0; + + ubl = zl10353_read_register(state, RS_UBC_1) << 8 | + zl10353_read_register(state, RS_UBC_0); - *ucblocks = zl10353_read_register(state, RS_UBC_1) << 8 | - zl10353_read_register(state, RS_UBC_0); + state->ucblocks += ubl; + *ucblocks = state->ucblocks; return 0; } -- cgit v1.2.3 From 002b57013de6ad9e597eb9912dd16658b548d9f4 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 30 Jul 2009 01:18:28 +0300 Subject: cx88: fix TBS 8920 card support From: Igor M. Liplianin It does matter to set explicitly gpio0 value in cx88_board structure for TBS 8920 card. Signed-off-by: Igor M. Liplianin Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/cx88/cx88-cards.c | 7 ++++++- linux/drivers/media/video/cx88/cx88-dvb.c | 9 ++++----- 2 files changed, 10 insertions(+), 6 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 19d57e698..31256666c 100644 --- a/linux/drivers/media/video/cx88/cx88-cards.c +++ b/linux/drivers/media/video/cx88/cx88-cards.c @@ -1986,7 +1986,8 @@ static const struct cx88_board cx88_boards[] = { .radio_addr = ADDR_UNSET, .input = {{ .type = CX88_VMUX_DVB, - .vmux = 1, + .vmux = 0, + .gpio0 = 0x8080, } }, .mpeg = CX88_MPEG_DVB, }, @@ -3244,7 +3245,11 @@ static void cx88_card_setup(struct cx88_core *core) case CX88_BOARD_PROF_6200: case CX88_BOARD_PROF_7300: case CX88_BOARD_SATTRADE_ST4200: + cx_write(MO_GP0_IO, 0x8000); + msleep(100); cx_write(MO_SRST_IO, 0); + msleep(10); + cx_write(MO_GP0_IO, 0x8080); msleep(100); cx_write(MO_SRST_IO, 1); msleep(100); diff --git a/linux/drivers/media/video/cx88/cx88-dvb.c b/linux/drivers/media/video/cx88/cx88-dvb.c index d3d4c67ec..28042ad5a 100644 --- a/linux/drivers/media/video/cx88/cx88-dvb.c +++ b/linux/drivers/media/video/cx88/cx88-dvb.c @@ -425,17 +425,16 @@ static int tevii_dvbs_set_voltage(struct dvb_frontend *fe, struct cx8802_dev *dev= fe->dvb->priv; struct cx88_core *core = dev->core; + cx_set(MO_GP0_IO, 0x6040); switch (voltage) { case SEC_VOLTAGE_13: - printk("LNB Voltage SEC_VOLTAGE_13\n"); - cx_write(MO_GP0_IO, 0x00006040); + cx_clear(MO_GP0_IO, 0x20); break; case SEC_VOLTAGE_18: - printk("LNB Voltage SEC_VOLTAGE_18\n"); - cx_write(MO_GP0_IO, 0x00006060); + cx_set(MO_GP0_IO, 0x20); break; case SEC_VOLTAGE_OFF: - printk("LNB Voltage SEC_VOLTAGE_off\n"); + cx_clear(MO_GP0_IO, 0x20); break; } -- cgit v1.2.3 From 981223e70ff82e9b3868c6eb8964536149ad3f24 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 10 Aug 2009 07:48:16 +0000 Subject: Fix control AC-3 of the 6752HS From: Dmitri Belimov Fix error for AC-3 control of the 6752HS MPEG-2 coder. Signed-off-by: Beholder Intl. Ltd. Dmitry Belimov Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/saa7134/saa6752hs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/saa7134/saa6752hs.c b/linux/drivers/media/video/saa7134/saa6752hs.c index 860f271dd..32ecebe8c 100644 --- a/linux/drivers/media/video/saa7134/saa6752hs.c +++ b/linux/drivers/media/video/saa7134/saa6752hs.c @@ -475,7 +475,7 @@ static int handle_ctrl(int has_ac3, struct saa6752hs_mpeg_params *params, if (set && new != V4L2_MPEG_AUDIO_ENCODING_LAYER_2 && (!has_ac3 || new != V4L2_MPEG_AUDIO_ENCODING_AC3)) return -ERANGE; - new = old; + params->au_encoding = new; break; case V4L2_CID_MPEG_AUDIO_L2_BITRATE: old = params->au_l2_bitrate; -- cgit v1.2.3 From ed2baf21f311d3b8c28315ea54a05cd3c60ce47a Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 11 Aug 2009 00:47:29 +0000 Subject: Add RDS config for BeholdTV cards From: Dmitri Belimov Add config of RDS part for the BeholdTV tuners. Signed-off-by: Beholder Intl. Ltd. Dmitry Belimov Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/saa7134/saa7134-cards.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/saa7134/saa7134-cards.c b/linux/drivers/media/video/saa7134/saa7134-cards.c index 32f8bdb91..82b60b9ff 100644 --- a/linux/drivers/media/video/saa7134/saa7134-cards.c +++ b/linux/drivers/media/video/saa7134/saa7134-cards.c @@ -4120,6 +4120,7 @@ struct saa7134_board saa7134_boards[] = { .radio_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, + .rds_addr = 0x10, .tda9887_conf = TDA9887_PRESENT, .gpiomask = 0x00008000, .inputs = {{ @@ -4184,6 +4185,7 @@ struct saa7134_board saa7134_boards[] = { .radio_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, + .rds_addr = 0x10, .tda9887_conf = TDA9887_PRESENT, .gpiomask = 0x00008000, .inputs = {{ @@ -4214,6 +4216,7 @@ struct saa7134_board saa7134_boards[] = { .radio_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, + .rds_addr = 0x10, .tda9887_conf = TDA9887_PRESENT, .gpiomask = 0x00008000, .inputs = {{ @@ -4389,6 +4392,7 @@ struct saa7134_board saa7134_boards[] = { .radio_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, + .rds_addr = 0x10, .tda9887_conf = TDA9887_PRESENT, .inputs = {{ .name = name_tv, @@ -4417,6 +4421,7 @@ struct saa7134_board saa7134_boards[] = { .radio_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, + .rds_addr = 0x10, .tda9887_conf = TDA9887_PRESENT, .inputs = {{ .name = name_tv, @@ -4445,6 +4450,7 @@ struct saa7134_board saa7134_boards[] = { .radio_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, + .rds_addr = 0x10, .tda9887_conf = TDA9887_PRESENT, .inputs = {{ .name = name_tv, @@ -4473,6 +4479,7 @@ struct saa7134_board saa7134_boards[] = { .radio_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, + .rds_addr = 0x10, .tda9887_conf = TDA9887_PRESENT, .inputs = {{ .name = name_tv, @@ -4579,6 +4586,7 @@ struct saa7134_board saa7134_boards[] = { .radio_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, + .rds_addr = 0x10, .empress_addr = 0x20, .tda9887_conf = TDA9887_PRESENT, .inputs = { { -- cgit v1.2.3 From 24cb4c279c0d10fdc6b5649936b8bb0dbfd56433 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 14 Aug 2009 05:22:52 +0000 Subject: pwc - fix few use-after-free and memory leaks From: Dmitry Torokhov I just happen to peek inside the PWC driver and did not like what I saw there. Please consider applying the patch below. Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/pwc/pwc-if.c | 78 +++++++++++++++------------------- linux/drivers/media/video/pwc/pwc.h | 1 + 2 files changed, 36 insertions(+), 43 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/pwc/pwc-if.c b/linux/drivers/media/video/pwc/pwc-if.c index f695c6624..788de22df 100644 --- a/linux/drivers/media/video/pwc/pwc-if.c +++ b/linux/drivers/media/video/pwc/pwc-if.c @@ -1065,7 +1065,8 @@ static int pwc_create_sysfs_files(struct video_device *vdev) goto err; if (pdev->features & FEATURE_MOTOR_PANTILT) { rc = device_create_file(&vdev->dev, &dev_attr_pan_tilt); - if (rc) goto err_button; + if (rc) + goto err_button; } return 0; @@ -1080,6 +1081,7 @@ err: static void pwc_remove_sysfs_files(struct video_device *vdev) { struct pwc_device *pdev = video_get_drvdata(vdev); + if (pdev->features & FEATURE_MOTOR_PANTILT) device_remove_file(&vdev->dev, &dev_attr_pan_tilt); device_remove_file(&vdev->dev, &dev_attr_button); @@ -1237,13 +1239,11 @@ static void pwc_cleanup(struct pwc_device *pdev) video_unregister_device(pdev->vdev); #ifdef CONFIG_USB_PWC_INPUT_EVDEV - if (pdev->button_dev) { + if (pdev->button_dev) input_unregister_device(pdev->button_dev); - input_free_device(pdev->button_dev); - kfree(pdev->button_dev->phys); - pdev->button_dev = NULL; - } #endif + + kfree(pdev); } /* Note that all cleanup is done in the reverse order as in _open */ @@ -1289,8 +1289,6 @@ static int pwc_video_close(struct file *file) PWC_DEBUG_OPEN("<< video_close() vopen=%d\n", pdev->vopen); } else { pwc_cleanup(pdev); - /* Free memory (don't set pdev to 0 just yet) */ - kfree(pdev); /* search device_hint[] table if we occupy a slot, by any chance */ for (hint = 0; hint < MAX_DEV_HINTS; hint++) if (device_hint[hint].pdev == pdev) @@ -1507,13 +1505,10 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id struct usb_device *udev = interface_to_usbdev(intf); struct pwc_device *pdev = NULL; int vendor_id, product_id, type_id; - int i, hint, rc; + int hint, rc; int features = 0; int video_nr = -1; /* default: use next available device */ char serial_number[30], *name; -#ifdef CONFIG_USB_PWC_INPUT_EVDEV - char *phys = NULL; -#endif vendor_id = le16_to_cpu(udev->descriptor.idVendor); product_id = le16_to_cpu(udev->descriptor.idProduct); @@ -1765,8 +1760,7 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id pdev->vframes = default_fps; strcpy(pdev->serial, serial_number); pdev->features = features; - if (vendor_id == 0x046D && product_id == 0x08B5) - { + if (vendor_id == 0x046D && product_id == 0x08B5) { /* Logitech QuickCam Orbit The ranges have been determined experimentally; they may differ from cam to cam. Also, the exact ranges left-right and up-down are different for my cam @@ -1788,8 +1782,8 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id pdev->vdev = video_device_alloc(); if (!pdev->vdev) { PWC_ERROR("Err, cannot allocate video_device struture. Failing probe."); - kfree(pdev); - return -ENOMEM; + rc = -ENOMEM; + goto err_free_mem; } memcpy(pdev->vdev, &pwc_template, sizeof(pwc_template)); pdev->vdev->parent = &intf->dev; @@ -1814,25 +1808,23 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id } pdev->vdev->release = video_device_release; - i = video_register_device(pdev->vdev, VFL_TYPE_GRABBER, video_nr); - if (i < 0) { - PWC_ERROR("Failed to register as video device (%d).\n", i); - rc = i; - goto err; - } - else { - PWC_INFO("Registered as /dev/video%d.\n", pdev->vdev->num); + rc = video_register_device(pdev->vdev, VFL_TYPE_GRABBER, video_nr); + if (rc < 0) { + PWC_ERROR("Failed to register as video device (%d).\n", rc); + goto err_video_release; } + PWC_INFO("Registered as /dev/video%d.\n", pdev->vdev->num); + /* occupy slot */ if (hint < MAX_DEV_HINTS) device_hint[hint].pdev = pdev; PWC_DEBUG_PROBE("probe() function returning struct at 0x%p.\n", pdev); - usb_set_intfdata (intf, pdev); + usb_set_intfdata(intf, pdev); rc = pwc_create_sysfs_files(pdev->vdev); if (rc) - goto err_unreg; + goto err_video_unreg; /* Set the leds off */ pwc_set_leds(pdev, 0, 0); @@ -1843,16 +1835,16 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id pdev->button_dev = input_allocate_device(); if (!pdev->button_dev) { PWC_ERROR("Err, insufficient memory for webcam snapshot button device."); - return -ENOMEM; + rc = -ENOMEM; + pwc_remove_sysfs_files(pdev->vdev); + goto err_video_unreg; } + usb_make_path(udev, pdev->button_phys, sizeof(pdev->button_phys)); + strlcat(pdev->button_phys, "/input0", sizeof(pdev->button_phys)); + pdev->button_dev->name = "PWC snapshot button"; - phys = kasprintf(GFP_KERNEL,"usb-%s-%s", pdev->udev->bus->bus_name, pdev->udev->devpath); - if (!phys) { - input_free_device(pdev->button_dev); - return -ENOMEM; - } - pdev->button_dev->phys = phys; + pdev->button_dev->phys = pdev->button_phys; usb_to_input_id(pdev->udev, &pdev->button_dev->id); #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 22) pdev->button_dev->dev.parent = &pdev->udev->dev; @@ -1865,25 +1857,27 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id rc = input_register_device(pdev->button_dev); if (rc) { input_free_device(pdev->button_dev); - kfree(pdev->button_dev->phys); pdev->button_dev = NULL; - return rc; + pwc_remove_sysfs_files(pdev->vdev); + goto err_video_unreg; } #endif return 0; -err_unreg: +err_video_unreg: if (hint < MAX_DEV_HINTS) device_hint[hint].pdev = NULL; video_unregister_device(pdev->vdev); -err: - video_device_release(pdev->vdev); /* Drip... drip... drip... */ - kfree(pdev); /* Oops, no memory leaks please */ + pdev->vdev = NULL; /* So we don't try to release it below */ +err_video_release: + video_device_release(pdev->vdev); +err_free_mem: + kfree(pdev); return rc; } -/* The user janked out the cable... */ +/* The user yanked out the cable... */ static void usb_pwc_disconnect(struct usb_interface *intf) { struct pwc_device *pdev; @@ -1914,7 +1908,7 @@ static void usb_pwc_disconnect(struct usb_interface *intf) /* Alert waiting processes */ wake_up_interruptible(&pdev->frameq); /* Wait until device is closed */ - if(pdev->vopen) { + if (pdev->vopen) { mutex_lock(&pdev->modlock); pdev->unplugged = 1; mutex_unlock(&pdev->modlock); @@ -1923,8 +1917,6 @@ static void usb_pwc_disconnect(struct usb_interface *intf) /* Device is closed, so we can safely unregister it */ PWC_DEBUG_PROBE("Unregistering video device in disconnect().\n"); pwc_cleanup(pdev); - /* Free memory (don't set pdev to 0 just yet) */ - kfree(pdev); disconnect_out: /* search device_hint[] table if we occupy a slot, by any chance */ diff --git a/linux/drivers/media/video/pwc/pwc.h b/linux/drivers/media/video/pwc/pwc.h index 12c869d71..94c8e5a69 100644 --- a/linux/drivers/media/video/pwc/pwc.h +++ b/linux/drivers/media/video/pwc/pwc.h @@ -254,6 +254,7 @@ struct pwc_device int snapshot_button_status; /* set to 1 when the user push the button, reset to 0 when this value is read */ #ifdef CONFIG_USB_PWC_INPUT_EVDEV struct input_dev *button_dev; /* webcam snapshot button input */ + char button_phys[64]; #endif /*** Misc. data ***/ -- cgit v1.2.3 From 9835197004d3cc8362791e5a4db613d8e2b25b46 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 18 Aug 2009 19:24:54 +0000 Subject: Report only 32kHz for ALSA MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: Oldřich Jedlička There are several reasons: - SAA7133/35 uses DDEP (DemDec Easy Programming mode), which works in 32kHz only - SAA7134 for TV mode uses DemDec mode (32kHz) - Radio works in 32kHz only - When recording 48kHz from Line1/Line2, switching of capture source to TV means switching to 32kHz without any frequency translation Signed-off-by: Oldřich Jedlička Acked-by: hermann pitton Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/saa7134/saa7134-alsa.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/saa7134/saa7134-alsa.c b/linux/drivers/media/video/saa7134/saa7134-alsa.c index c09ec3e6f..504186ae6 100644 --- a/linux/drivers/media/video/saa7134/saa7134-alsa.c +++ b/linux/drivers/media/video/saa7134/saa7134-alsa.c @@ -440,6 +440,16 @@ snd_card_saa7134_capture_pointer(struct snd_pcm_substream * substream) /* * ALSA hardware capabilities definition + * + * Report only 32kHz for ALSA: + * + * - SAA7133/35 uses DDEP (DemDec Easy Programming mode), which works in 32kHz + * only + * - SAA7134 for TV mode uses DemDec mode (32kHz) + * - Radio works in 32kHz only + * - When recording 48kHz from Line1/Line2, switching of capture source to TV + * means + * switching to 32kHz without any frequency translation */ static struct snd_pcm_hardware snd_card_saa7134_capture = @@ -453,9 +463,9 @@ static struct snd_pcm_hardware snd_card_saa7134_capture = SNDRV_PCM_FMTBIT_U8 | \ SNDRV_PCM_FMTBIT_U16_LE | \ SNDRV_PCM_FMTBIT_U16_BE, - .rates = SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000, + .rates = SNDRV_PCM_RATE_32000, .rate_min = 32000, - .rate_max = 48000, + .rate_max = 32000, .channels_min = 1, .channels_max = 2, .buffer_bytes_max = (256*1024), -- cgit v1.2.3 From 5ba9b1fa2dc6d6832ae773956d09922c9a7f3780 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 19 Aug 2009 19:41:59 +0000 Subject: remove unnecessary power management primitive in stk-webcam From: Oliver Neukum This patch removes an unneeded power management primitive. Power management is automatically enabled as probe ends. Signed-off-by: Oliver Neukum Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/stk-webcam.c | 1 - 1 file changed, 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/stk-webcam.c b/linux/drivers/media/video/stk-webcam.c index aaeee8319..3034a31a5 100644 --- a/linux/drivers/media/video/stk-webcam.c +++ b/linux/drivers/media/video/stk-webcam.c @@ -1401,7 +1401,6 @@ static int stk_camera_probe(struct usb_interface *interface, } stk_create_sysfs_files(&dev->vdev); - usb_autopm_enable(dev->interface); return 0; -- cgit v1.2.3 From ef36e0392e76322283553a75b4f0e656c8151598 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 20 Aug 2009 01:30:58 +0000 Subject: saa7134-input: don't probe for the Pinnacle remotes anymore From: hermann pitton With the recent improvements we don't need to probe anymore, if we know the i2c address of the receiver. The address of the receiver for the remote with the gray buttons is not confirmed anywhere, but it is very unlikely to see it on something else. We want to have that information anyway. BTW, those remaining still probing, please join. Signed-off-by: hermann pitton Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/saa7134/saa7134-input.c | 2 ++ 1 file changed, 2 insertions(+) (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 585f78af3..146ac816a 100644 --- a/linux/drivers/media/video/saa7134/saa7134-input.c +++ b/linux/drivers/media/video/saa7134/saa7134-input.c @@ -787,6 +787,7 @@ void saa7134_probe_i2c_ir(struct saa7134_dev *dev) #else init_data.get_key = get_key_pinnacle_color; init_data.ir_codes = ir_codes_pinnacle_color; + info.addr = 0x47; #endif } else { #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30) @@ -795,6 +796,7 @@ void saa7134_probe_i2c_ir(struct saa7134_dev *dev) #else init_data.get_key = get_key_pinnacle_grey; init_data.ir_codes = ir_codes_pinnacle_grey; + info.addr = 0x47; #endif } break; -- cgit v1.2.3 From 55978f5ebca02a1b6f03e130bdcd5b6957004025 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 21 Aug 2009 02:49:26 +0000 Subject: em28xx: Don't call em28xx_ir_init when disable_ir is true From: Shine Liu We should call em28xx_ir_init(dev) only when disable_ir is true. Signed-off-by: Shine Liu Reviewed-by: Devin Heitmueller Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/em28xx/em28xx-cards.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (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 b8778577d..36bcaad4c 100644 --- a/linux/drivers/media/video/em28xx/em28xx-cards.c +++ b/linux/drivers/media/video/em28xx/em28xx-cards.c @@ -2498,7 +2498,9 @@ void em28xx_card_setup(struct em28xx *dev) } em28xx_tuner_setup(dev); - em28xx_ir_init(dev); + + if(!disable_ir) + em28xx_ir_init(dev); } -- cgit v1.2.3 From 0cba7f108664f9efc0e34a388c51cb943c72d68b Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 21 Aug 2009 16:41:21 +0000 Subject: compat: Fix build for older kernels using DIV_ROUND_CLOSEST From: Andy Walls DIV_ROUND_CLOSEST() is not available on older kernels. Include compat.h in a few files to fix building v4l-dvb from mercurial on older kernels. Reported-by: Lou Otway Reported-by: Avo Aasma Signed-off-by: Andy Walls Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/frontends/stb6100.c | 1 + linux/drivers/media/dvb/frontends/tda10021.c | 1 + linux/drivers/media/dvb/frontends/ves1820.c | 1 + 3 files changed, 3 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/frontends/stb6100.c b/linux/drivers/media/dvb/frontends/stb6100.c index 540967545..2de9e0c01 100644 --- a/linux/drivers/media/dvb/frontends/stb6100.c +++ b/linux/drivers/media/dvb/frontends/stb6100.c @@ -24,6 +24,7 @@ #include #include +#include "compat.h" #include "dvb_frontend.h" #include "stb6100.h" diff --git a/linux/drivers/media/dvb/frontends/tda10021.c b/linux/drivers/media/dvb/frontends/tda10021.c index d90cd60ce..f410fd5e2 100644 --- a/linux/drivers/media/dvb/frontends/tda10021.c +++ b/linux/drivers/media/dvb/frontends/tda10021.c @@ -29,6 +29,7 @@ #include #include +#include "compat.h" #include "dvb_frontend.h" #include "tda1002x.h" diff --git a/linux/drivers/media/dvb/frontends/ves1820.c b/linux/drivers/media/dvb/frontends/ves1820.c index 550a07a8a..afd7f09ac 100644 --- a/linux/drivers/media/dvb/frontends/ves1820.c +++ b/linux/drivers/media/dvb/frontends/ves1820.c @@ -27,6 +27,7 @@ #include #include +#include "compat.h" #include "dvb_frontend.h" #include "ves1820.h" -- cgit v1.2.3 From c8ad89b126394193632a77bc2502ea045cb383cf Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Tue, 25 Aug 2009 11:14:54 +0200 Subject: gspca - sonixj: Do the ov7660 sensor work again. From: Jean-Francois Moine - bad sensor power - bad edge gain/threshold - set back the auto gain - light frequency filter inverted Priority: high Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/sonixj.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/sonixj.c b/linux/drivers/media/video/gspca/sonixj.c index 98fb39c99..6a668deb1 100644 --- a/linux/drivers/media/video/gspca/sonixj.c +++ b/linux/drivers/media/video/gspca/sonixj.c @@ -741,7 +741,7 @@ static const u8 ov7660_sensor_init[][8] = { /* COM 1 BAVE GEAVE AECHH */ {0xb1, 0x21, 0x08, 0x83, 0x01, 0x00, 0x00, 0x10}, /* RAVE COM2 */ {0xd1, 0x21, 0x0c, 0x00, 0x08, 0x04, 0x4f, 0x10}, /* COM 3 4 5 6 */ -#if 1 +#if 0 {0xd1, 0x21, 0x10, 0x7f, 0x40, 0x05, 0xf8, 0x10}, #else {0xd1, 0x21, 0x10, 0x7f, 0x40, 0x05, 0xff, 0x10}, @@ -795,7 +795,7 @@ static const u8 ov7660_sensor_init[][8] = { {0xc1, 0x21, 0x88, 0xaf, 0xc7, 0xdf, 0x00, 0x10}, /* gamma curve */ {0xc1, 0x21, 0x8b, 0x99, 0x99, 0xcf, 0x00, 0x10}, /* reserved */ {0xb1, 0x21, 0x92, 0x00, 0x00, 0x00, 0x00, 0x10}, /* DM_LNL/H */ - {0xb1, 0x21, 0xa1, 0x00, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x21, 0xa1, 0x00, 0x00, 0x00, 0x00, 0x10}, /****** (some exchanges in the win trace) ******/ {0xa1, 0x21, 0x1e, 0x01, 0x00, 0x00, 0x00, 0x10}, /* MVFP */ /* bits[3..0]reserved */ @@ -1165,11 +1165,13 @@ static int configure_gpio(struct gspca_dev *gspca_dev, reg_w1(gspca_dev, 0x01, 0x42); break; case SENSOR_OV7660: +#if 0 reg_w1(gspca_dev, 0x01, 0x61); reg_w1(gspca_dev, 0x17, 0x20); reg_w1(gspca_dev, 0x01, 0x60); reg_w1(gspca_dev, 0x01, 0x40); break; +#endif case SENSOR_SP80708: reg_w1(gspca_dev, 0x01, 0x63); reg_w1(gspca_dev, 0x17, 0x20); @@ -1654,6 +1656,8 @@ static void setvflip(struct sd *sd) static void setinfrared(struct sd *sd) { + if (sd->gspca_dev.ctrl_dis & (1 << INFRARED_IDX)) + return; /*fixme: different sequence for StarCam Clip and StarCam 370i */ #if 1 /* Clip */ @@ -1675,14 +1679,14 @@ static void setfreq(struct gspca_dev *gspca_dev) if (sd->sensor == SENSOR_OV7660) { u8 com8; -#if 1 - com8 = 0xf8; /* no auto gain/wb/expo */ +#if 0 + com8 = 0xd8; /* no auto gain/wb/expo */ #else - com8 = 0xff; + com8 = 0xdf; /* auto gain/wb/expo */ #endif switch (sd->freq) { case 0: /* Banding filter disabled */ - i2c_w1(gspca_dev, 0x13, com8 & 0xdf); + i2c_w1(gspca_dev, 0x13, com8 | 0x20); break; case 1: /* 50 hz */ i2c_w1(gspca_dev, 0x13, com8); @@ -1839,12 +1843,14 @@ static int sd_start(struct gspca_dev *gspca_dev) reg_w1(gspca_dev, 0x99, 0x60); break; case SENSOR_OV7660: +#if 0 reg_w1(gspca_dev, 0x9a, 0x05); if (sd->bridge == BRIDGE_SN9C105) reg_w1(gspca_dev, 0x99, 0xff); else reg_w1(gspca_dev, 0x99, 0x5b); break; +#endif case SENSOR_SP80708: reg_w1(gspca_dev, 0x9a, 0x05); reg_w1(gspca_dev, 0x99, 0x59); @@ -2373,7 +2379,7 @@ static const __devinitdata struct usb_device_id device_table[] = { {USB_DEVICE(0x0c45, 0x607c), BSI(SN9C102P, HV7131R, 0x11)}, /* {USB_DEVICE(0x0c45, 0x607e), BSI(SN9C102P, OV7630, 0x??)}, */ {USB_DEVICE(0x0c45, 0x60c0), BSI(SN9C105, MI0360, 0x5d)}, -/* {USB_DEVICE(0x0c45, 0x60c8), BSI(SN9C105, OM6801, 0x??)}, */ +/* {USB_DEVICE(0x0c45, 0x60c8), BSI(SN9C105, OM6802, 0x??)}, */ /* {USB_DEVICE(0x0c45, 0x60cc), BSI(SN9C105, HV7131GP, 0x??)}, */ {USB_DEVICE(0x0c45, 0x60ec), BSI(SN9C105, MO4000, 0x21)}, /* {USB_DEVICE(0x0c45, 0x60ef), BSI(SN9C105, ICM105C, 0x??)}, */ -- cgit v1.2.3 From aea41520a95b61491620e5702c8322a8fcfbf12e Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Tue, 25 Aug 2009 16:06:21 +0200 Subject: soc-camera: prepare soc_camera_platform.c and its users for conversion From: Guennadi Liakhovetski soc_camera_platform.c is only used by y SuperH ap325rxa board. This patch converts soc_camera_platform.c and its users for the soc-camera platform- device conversion and also extends soc-camera core to handle non-I2C cameras. Signed-off-by: Guennadi Liakhovetski Cc: Paul Mundt Acked-by: Paul Mundt Priority: low --- arch/sh/boards/board-ap325rxa.c | 43 ++++++++++++++++++------ drivers/media/video/soc_camera.c | 61 ++++++++++++++++++++++++++-------- include/media/soc_camera.h | 6 +++ include/media/soc_camera_platform.h | 2 + 4 files changed, 86 insertions(+), 26 deletions(-) --- linux/drivers/media/video/soc_camera.c | 61 +++++++++++++++++++++++++--------- 1 file changed, 46 insertions(+), 15 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/soc_camera.c b/linux/drivers/media/video/soc_camera.c index 4f315c1b7..8de620b78 100644 --- a/linux/drivers/media/video/soc_camera.c +++ b/linux/drivers/media/video/soc_camera.c @@ -1166,45 +1166,76 @@ void soc_camera_video_stop(struct soc_camera_device *icd) } EXPORT_SYMBOL(soc_camera_video_stop); -static int __devinit soc_camera_pdrv_probe(struct platform_device *pdev) +#ifdef CONFIG_I2C_BOARDINFO +static int soc_camera_init_i2c(struct platform_device *pdev, + struct soc_camera_link *icl) { - struct soc_camera_link *icl = pdev->dev.platform_data; - struct i2c_adapter *adap; struct i2c_client *client; + struct i2c_adapter *adap = i2c_get_adapter(icl->i2c_adapter_id); + int ret; - if (!icl) - return -EINVAL; - - adap = i2c_get_adapter(icl->i2c_adapter_id); if (!adap) { - dev_warn(&pdev->dev, "Cannot get adapter #%d. No driver?\n", - icl->i2c_adapter_id); - /* -ENODEV and -ENXIO do not produce an error on probe()... */ - return -ENOENT; + ret = -ENODEV; + dev_err(&pdev->dev, "Cannot get adapter #%d. No driver?\n", + icl->i2c_adapter_id); + goto ei2cga; } icl->board_info->platform_data = icl; client = i2c_new_device(adap, icl->board_info); if (!client) { - i2c_put_adapter(adap); - return -ENOMEM; + ret = -ENOMEM; + goto ei2cnd; } platform_set_drvdata(pdev, client); return 0; +ei2cnd: + i2c_put_adapter(adap); +ei2cga: + return ret; } -static int __devexit soc_camera_pdrv_remove(struct platform_device *pdev) +static void soc_camera_free_i2c(struct platform_device *pdev) { struct i2c_client *client = platform_get_drvdata(pdev); if (!client) - return -ENODEV; + return; i2c_unregister_device(client); i2c_put_adapter(client->adapter); +} +#else +#define soc_camera_init_i2c(d, icl) (-ENODEV) +#define soc_camera_free_i2c(d) do {} while (0) +#endif +static int __devinit soc_camera_pdrv_probe(struct platform_device *pdev) +{ + struct soc_camera_link *icl = pdev->dev.platform_data; + + if (!icl) + return -EINVAL; + + if (icl->board_info) + return soc_camera_init_i2c(pdev, icl); + else if (!icl->add_device || !icl->del_device) + return -EINVAL; + + /* &pdev->dev will become &icd->dev */ + return icl->add_device(icl, &pdev->dev); +} + +static int __devexit soc_camera_pdrv_remove(struct platform_device *pdev) +{ + struct soc_camera_link *icl = pdev->dev.platform_data; + + if (icl->board_info) + soc_camera_free_i2c(pdev); + else + icl->del_device(icl); return 0; } -- cgit v1.2.3 From 0326f126a4d2f1e2cda2c11725a7f7d7d8273f7f Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Tue, 25 Aug 2009 16:28:22 +0200 Subject: soc-camera: convert to platform device From: Guennadi Liakhovetski Convert soc-camera core and all drivers to platform device API. We already converted platforms to register a platform device for each soc-camera client, now we remove the compatibility code and switch completely to the new scheme. This is a preparatory step for the v4l2-subdev conversion. Signed-off-by: Guennadi Liakhovetski Priority: low --- linux/drivers/media/video/mt9m001.c | 114 +++--- linux/drivers/media/video/mt9m111.c | 154 ++++---- linux/drivers/media/video/mt9t031.c | 116 +++--- linux/drivers/media/video/mt9v022.c | 119 +++---- linux/drivers/media/video/mx3_camera.c | 27 +- linux/drivers/media/video/ov772x.c | 157 +++++---- linux/drivers/media/video/pxa_camera.c | 29 +- linux/drivers/media/video/sh_mobile_ceu_camera.c | 13 +- linux/drivers/media/video/soc_camera.c | 431 +++++++++++------------ linux/drivers/media/video/soc_camera_platform.c | 76 ++-- linux/drivers/media/video/tw9910.c | 110 +++--- 11 files changed, 682 insertions(+), 664 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/mt9m001.c b/linux/drivers/media/video/mt9m001.c index e609d68c4..ad308da71 100644 --- a/linux/drivers/media/video/mt9m001.c +++ b/linux/drivers/media/video/mt9m001.c @@ -69,8 +69,6 @@ static const struct soc_camera_data_format mt9m001_monochrome_formats[] = { }; struct mt9m001 { - struct i2c_client *client; - struct soc_camera_device icd; int model; /* V4L2_IDENT_MT9M001* codes from v4l2-chip-ident.h */ unsigned char autoexposure; }; @@ -111,11 +109,11 @@ static int reg_clear(struct i2c_client *client, const u8 reg, static int mt9m001_init(struct soc_camera_device *icd) { - struct i2c_client *client = to_i2c_client(icd->control); - struct soc_camera_link *icl = client->dev.platform_data; + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct soc_camera_link *icl = to_soc_camera_link(icd); int ret; - dev_dbg(icd->vdev->parent, "%s\n", __func__); + dev_dbg(&icd->dev, "%s\n", __func__); if (icl->power) { ret = icl->power(&client->dev, 1); @@ -147,8 +145,8 @@ static int mt9m001_init(struct soc_camera_device *icd) static int mt9m001_release(struct soc_camera_device *icd) { - struct i2c_client *client = to_i2c_client(icd->control); - struct soc_camera_link *icl = client->dev.platform_data; + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct soc_camera_link *icl = to_soc_camera_link(icd); /* Disable the chip */ reg_write(client, MT9M001_OUTPUT_CONTROL, 0); @@ -161,7 +159,7 @@ static int mt9m001_release(struct soc_camera_device *icd) static int mt9m001_start_capture(struct soc_camera_device *icd) { - struct i2c_client *client = to_i2c_client(icd->control); + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); /* Switch to master "normal" mode */ if (reg_write(client, MT9M001_OUTPUT_CONTROL, 2) < 0) @@ -171,7 +169,7 @@ static int mt9m001_start_capture(struct soc_camera_device *icd) static int mt9m001_stop_capture(struct soc_camera_device *icd) { - struct i2c_client *client = to_i2c_client(icd->control); + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); /* Stop sensor readout */ if (reg_write(client, MT9M001_OUTPUT_CONTROL, 0) < 0) @@ -182,8 +180,7 @@ static int mt9m001_stop_capture(struct soc_camera_device *icd) static int mt9m001_set_bus_param(struct soc_camera_device *icd, unsigned long flags) { - struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd); - struct soc_camera_link *icl = mt9m001->client->dev.platform_data; + struct soc_camera_link *icl = to_soc_camera_link(icd); unsigned long width_flag = flags & SOCAM_DATAWIDTH_MASK; /* Only one width bit may be set */ @@ -205,8 +202,7 @@ static int mt9m001_set_bus_param(struct soc_camera_device *icd, static unsigned long mt9m001_query_bus_param(struct soc_camera_device *icd) { - struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd); - struct soc_camera_link *icl = mt9m001->client->dev.platform_data; + struct soc_camera_link *icl = to_soc_camera_link(icd); /* MT9M001 has all capture_format parameters fixed */ unsigned long flags = SOCAM_PCLK_SAMPLE_FALLING | SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_VSYNC_ACTIVE_HIGH | @@ -223,8 +219,8 @@ static unsigned long mt9m001_query_bus_param(struct soc_camera_device *icd) static int mt9m001_set_crop(struct soc_camera_device *icd, struct v4l2_rect *rect) { - struct i2c_client *client = to_i2c_client(icd->control); - struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd); + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct mt9m001 *mt9m001 = i2c_get_clientdata(client); int ret; const u16 hblank = 9, vblank = 25; @@ -290,12 +286,13 @@ static int mt9m001_try_fmt(struct soc_camera_device *icd, static int mt9m001_get_chip_id(struct soc_camera_device *icd, struct v4l2_dbg_chip_ident *id) { - struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd); + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct mt9m001 *mt9m001 = i2c_get_clientdata(client); if (id->match.type != V4L2_CHIP_MATCH_I2C_ADDR) return -EINVAL; - if (id->match.addr != mt9m001->client->addr) + if (id->match.addr != client->addr) return -ENODEV; id->ident = mt9m001->model; @@ -308,7 +305,7 @@ static int mt9m001_get_chip_id(struct soc_camera_device *icd, static int mt9m001_get_register(struct soc_camera_device *icd, struct v4l2_dbg_register *reg) { - struct i2c_client *client = to_i2c_client(icd->control); + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff) return -EINVAL; @@ -328,7 +325,7 @@ static int mt9m001_get_register(struct soc_camera_device *icd, static int mt9m001_set_register(struct soc_camera_device *icd, struct v4l2_dbg_register *reg) { - struct i2c_client *client = to_i2c_client(icd->control); + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff) return -EINVAL; @@ -381,15 +378,11 @@ static const struct v4l2_queryctrl mt9m001_controls[] = { } }; -static int mt9m001_video_probe(struct soc_camera_device *); -static void mt9m001_video_remove(struct soc_camera_device *); static int mt9m001_get_control(struct soc_camera_device *, struct v4l2_control *); static int mt9m001_set_control(struct soc_camera_device *, struct v4l2_control *); static struct soc_camera_ops mt9m001_ops = { .owner = THIS_MODULE, - .probe = mt9m001_video_probe, - .remove = mt9m001_video_remove, .init = mt9m001_init, .release = mt9m001_release, .start_capture = mt9m001_start_capture, @@ -412,8 +405,8 @@ static struct soc_camera_ops mt9m001_ops = { static int mt9m001_get_control(struct soc_camera_device *icd, struct v4l2_control *ctrl) { - struct i2c_client *client = to_i2c_client(icd->control); - struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd); + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct mt9m001 *mt9m001 = i2c_get_clientdata(client); int data; switch (ctrl->id) { @@ -432,8 +425,8 @@ static int mt9m001_get_control(struct soc_camera_device *icd, struct v4l2_contro static int mt9m001_set_control(struct soc_camera_device *icd, struct v4l2_control *ctrl) { - struct i2c_client *client = to_i2c_client(icd->control); - struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd); + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct mt9m001 *mt9m001 = i2c_get_clientdata(client); const struct v4l2_queryctrl *qctrl; int data; @@ -525,11 +518,11 @@ static int mt9m001_set_control(struct soc_camera_device *icd, struct v4l2_contro /* Interface active, can use i2c. If it fails, it can indeed mean, that * this wasn't our capture interface, so, we wait for the right one */ -static int mt9m001_video_probe(struct soc_camera_device *icd) +static int mt9m001_video_probe(struct soc_camera_device *icd, + struct i2c_client *client) { - struct i2c_client *client = to_i2c_client(icd->control); - struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd); - struct soc_camera_link *icl = client->dev.platform_data; + struct mt9m001 *mt9m001 = i2c_get_clientdata(client); + struct soc_camera_link *icl = to_soc_camera_link(icd); s32 data; int ret; unsigned long flags; @@ -540,6 +533,11 @@ static int mt9m001_video_probe(struct soc_camera_device *icd) to_soc_camera_host(icd->dev.parent)->nr != icd->iface) return -ENODEV; + /* Switch master clock on */ + ret = soc_camera_video_start(icd, &client->dev); + if (ret) + return ret; + /* Enable the chip */ data = reg_write(client, MT9M001_CHIP_ENABLE, 1); dev_dbg(&icd->dev, "write: %d\n", data); @@ -547,6 +545,8 @@ static int mt9m001_video_probe(struct soc_camera_device *icd) /* Read out the chip version register */ data = reg_read(client, MT9M001_CHIP_VERSION); + soc_camera_video_stop(icd); + /* must be 0x8411 or 0x8421 for colour sensor and 8431 for bw */ switch (data) { case 0x8411: @@ -559,10 +559,9 @@ static int mt9m001_video_probe(struct soc_camera_device *icd) icd->formats = mt9m001_monochrome_formats; break; default: - ret = -ENODEV; dev_err(&icd->dev, "No MT9M001 chip detected, register read %x\n", data); - goto ei2c; + return -ENODEV; } icd->num_formats = 0; @@ -588,26 +587,16 @@ static int mt9m001_video_probe(struct soc_camera_device *icd) dev_info(&icd->dev, "Detected a MT9M001 chip ID %x (%s)\n", data, data == 0x8431 ? "C12STM" : "C12ST"); - /* Now that we know the model, we can start video */ - ret = soc_camera_video_start(icd); - if (ret) - goto eisis; - return 0; - -eisis: -ei2c: - return ret; } static void mt9m001_video_remove(struct soc_camera_device *icd) { - struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd); - struct soc_camera_link *icl = mt9m001->client->dev.platform_data; + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct soc_camera_link *icl = to_soc_camera_link(icd); - dev_dbg(&icd->dev, "Video %x removed: %p, %p\n", mt9m001->client->addr, + dev_dbg(&icd->dev, "Video %x removed: %p, %p\n", client->addr, icd->dev.parent, icd->vdev); - soc_camera_video_stop(icd); if (icl->free_bus) icl->free_bus(icl); } @@ -620,11 +609,17 @@ static int mt9m001_probe(struct i2c_client *client) #endif { struct mt9m001 *mt9m001; - struct soc_camera_device *icd; + struct soc_camera_device *icd = client->dev.platform_data; struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); - struct soc_camera_link *icl = client->dev.platform_data; + struct soc_camera_link *icl; int ret; + if (!icd) { + dev_err(&client->dev, "MT9M001: missing soc-camera data!\n"); + return -EINVAL; + } + + icl = to_soc_camera_link(icd); if (!icl) { dev_err(&client->dev, "MT9M001 driver needs platform data\n"); return -EINVAL; @@ -640,13 +635,10 @@ static int mt9m001_probe(struct i2c_client *client) if (!mt9m001) return -ENOMEM; - mt9m001->client = client; i2c_set_clientdata(client, mt9m001); /* Second stage probe - when a capture adapter is there */ - icd = &mt9m001->icd; icd->ops = &mt9m001_ops; - icd->control = &client->dev; icd->x_min = 20; icd->y_min = 12; icd->x_current = 20; @@ -656,27 +648,29 @@ static int mt9m001_probe(struct i2c_client *client) icd->height_min = 32; icd->height_max = 1024; icd->y_skip_top = 1; - icd->iface = icl->bus_id; /* Simulated autoexposure. If enabled, we calculate shutter width * ourselves in the driver based on vertical blanking and frame width */ mt9m001->autoexposure = 1; - ret = soc_camera_device_register(icd); - if (ret) - goto eisdr; - - return 0; + ret = mt9m001_video_probe(icd, client); + if (ret) { + icd->ops = NULL; + i2c_set_clientdata(client, NULL); + kfree(mt9m001); + } -eisdr: - kfree(mt9m001); return ret; } static int mt9m001_remove(struct i2c_client *client) { struct mt9m001 *mt9m001 = i2c_get_clientdata(client); + struct soc_camera_device *icd = client->dev.platform_data; - soc_camera_device_unregister(&mt9m001->icd); + icd->ops = NULL; + mt9m001_video_remove(icd); + i2c_set_clientdata(client, NULL); + client->driver = NULL; kfree(mt9m001); return 0; diff --git a/linux/drivers/media/video/mt9m111.c b/linux/drivers/media/video/mt9m111.c index 77639ae5c..5c6ab7b53 100644 --- a/linux/drivers/media/video/mt9m111.c +++ b/linux/drivers/media/video/mt9m111.c @@ -148,8 +148,6 @@ enum mt9m111_context { }; struct mt9m111 { - struct i2c_client *client; - struct soc_camera_device icd; int model; /* V4L2_IDENT_MT9M11x* codes from v4l2-chip-ident.h */ enum mt9m111_context context; struct v4l2_rect rect; @@ -203,7 +201,7 @@ static int mt9m111_reg_write(struct i2c_client *client, const u16 reg, ret = reg_page_map_set(client, reg); if (!ret) - ret = i2c_smbus_write_word_data(client, (reg & 0xff), + ret = i2c_smbus_write_word_data(client, reg & 0xff, swab16(data)); dev_dbg(&client->dev, "write reg.%03x = %04x -> %d\n", reg, data, ret); return ret; @@ -232,7 +230,7 @@ static int mt9m111_reg_clear(struct i2c_client *client, const u16 reg, static int mt9m111_set_context(struct soc_camera_device *icd, enum mt9m111_context ctxt) { - struct i2c_client *client = to_i2c_client(icd->control); + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); int valB = MT9M111_CTXT_CTRL_RESTART | MT9M111_CTXT_CTRL_DEFECTCOR_B | MT9M111_CTXT_CTRL_RESIZE_B | MT9M111_CTXT_CTRL_CTRL2_B | MT9M111_CTXT_CTRL_GAMMA_B | MT9M111_CTXT_CTRL_READ_MODE_B @@ -249,8 +247,8 @@ static int mt9m111_set_context(struct soc_camera_device *icd, static int mt9m111_setup_rect(struct soc_camera_device *icd, struct v4l2_rect *rect) { - struct i2c_client *client = to_i2c_client(icd->control); - struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct mt9m111 *mt9m111 = i2c_get_clientdata(client); int ret, is_raw_format; int width = rect->width; int height = rect->height; @@ -294,7 +292,7 @@ static int mt9m111_setup_rect(struct soc_camera_device *icd, static int mt9m111_setup_pixfmt(struct soc_camera_device *icd, u16 outfmt) { - struct i2c_client *client = to_i2c_client(icd->control); + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); int ret; ret = reg_write(OUTPUT_FORMAT_CTRL2_A, outfmt); @@ -315,7 +313,8 @@ static int mt9m111_setfmt_bayer10(struct soc_camera_device *icd) static int mt9m111_setfmt_rgb565(struct soc_camera_device *icd) { - struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct mt9m111 *mt9m111 = i2c_get_clientdata(client); int val = 0; if (mt9m111->swap_rgb_red_blue) @@ -329,7 +328,8 @@ static int mt9m111_setfmt_rgb565(struct soc_camera_device *icd) static int mt9m111_setfmt_rgb555(struct soc_camera_device *icd) { - struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct mt9m111 *mt9m111 = i2c_get_clientdata(client); int val = 0; if (mt9m111->swap_rgb_red_blue) @@ -343,7 +343,8 @@ static int mt9m111_setfmt_rgb555(struct soc_camera_device *icd) static int mt9m111_setfmt_yuv(struct soc_camera_device *icd) { - struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct mt9m111 *mt9m111 = i2c_get_clientdata(client); int val = 0; if (mt9m111->swap_yuv_cb_cr) @@ -356,9 +357,9 @@ static int mt9m111_setfmt_yuv(struct soc_camera_device *icd) static int mt9m111_enable(struct soc_camera_device *icd) { - struct i2c_client *client = to_i2c_client(icd->control); - struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); - struct soc_camera_link *icl = client->dev.platform_data; + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct soc_camera_link *icl = to_soc_camera_link(icd); + struct mt9m111 *mt9m111 = i2c_get_clientdata(client); int ret; if (icl->power) { @@ -378,9 +379,9 @@ static int mt9m111_enable(struct soc_camera_device *icd) static int mt9m111_disable(struct soc_camera_device *icd) { - struct i2c_client *client = to_i2c_client(icd->control); - struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); - struct soc_camera_link *icl = client->dev.platform_data; + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct soc_camera_link *icl = to_soc_camera_link(icd); + struct mt9m111 *mt9m111 = i2c_get_clientdata(client); int ret; ret = reg_clear(RESET, MT9M111_RESET_CHIP_ENABLE); @@ -395,8 +396,8 @@ static int mt9m111_disable(struct soc_camera_device *icd) static int mt9m111_reset(struct soc_camera_device *icd) { - struct i2c_client *client = to_i2c_client(icd->control); - struct soc_camera_link *icl = client->dev.platform_data; + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct soc_camera_link *icl = to_soc_camera_link(icd); int ret; ret = reg_set(RESET, MT9M111_RESET_RESET_MODE); @@ -424,8 +425,7 @@ static int mt9m111_stop_capture(struct soc_camera_device *icd) static unsigned long mt9m111_query_bus_param(struct soc_camera_device *icd) { - struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); - struct soc_camera_link *icl = mt9m111->client->dev.platform_data; + struct soc_camera_link *icl = to_soc_camera_link(icd); unsigned long flags = SOCAM_MASTER | SOCAM_PCLK_SAMPLE_RISING | SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_DATA_ACTIVE_HIGH | SOCAM_DATAWIDTH_8; @@ -441,7 +441,8 @@ static int mt9m111_set_bus_param(struct soc_camera_device *icd, unsigned long f) static int mt9m111_set_crop(struct soc_camera_device *icd, struct v4l2_rect *rect) { - struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct mt9m111 *mt9m111 = i2c_get_clientdata(client); int ret; dev_dbg(&icd->dev, "%s left=%d, top=%d, width=%d, height=%d\n", @@ -456,7 +457,8 @@ static int mt9m111_set_crop(struct soc_camera_device *icd, static int mt9m111_set_pixfmt(struct soc_camera_device *icd, u32 pixfmt) { - struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct mt9m111 *mt9m111 = i2c_get_clientdata(client); int ret; switch (pixfmt) { @@ -506,7 +508,8 @@ static int mt9m111_set_pixfmt(struct soc_camera_device *icd, u32 pixfmt) static int mt9m111_set_fmt(struct soc_camera_device *icd, struct v4l2_format *f) { - struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct mt9m111 *mt9m111 = i2c_get_clientdata(client); struct v4l2_pix_format *pix = &f->fmt.pix; struct v4l2_rect rect = { .left = mt9m111->rect.left, @@ -544,12 +547,13 @@ static int mt9m111_try_fmt(struct soc_camera_device *icd, static int mt9m111_get_chip_id(struct soc_camera_device *icd, struct v4l2_dbg_chip_ident *id) { - struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct mt9m111 *mt9m111 = i2c_get_clientdata(client); if (id->match.type != V4L2_CHIP_MATCH_I2C_ADDR) return -EINVAL; - if (id->match.addr != mt9m111->client->addr) + if (id->match.addr != client->addr) return -ENODEV; id->ident = mt9m111->model; @@ -562,8 +566,8 @@ static int mt9m111_get_chip_id(struct soc_camera_device *icd, static int mt9m111_get_register(struct soc_camera_device *icd, struct v4l2_dbg_register *reg) { + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); int val; - struct i2c_client *client = to_i2c_client(icd->control); if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0x2ff) return -EINVAL; @@ -583,7 +587,7 @@ static int mt9m111_get_register(struct soc_camera_device *icd, static int mt9m111_set_register(struct soc_camera_device *icd, struct v4l2_dbg_register *reg) { - struct i2c_client *client = to_i2c_client(icd->control); + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0x2ff) return -EINVAL; @@ -635,8 +639,6 @@ static const struct v4l2_queryctrl mt9m111_controls[] = { } }; -static int mt9m111_video_probe(struct soc_camera_device *); -static void mt9m111_video_remove(struct soc_camera_device *); static int mt9m111_get_control(struct soc_camera_device *, struct v4l2_control *); static int mt9m111_set_control(struct soc_camera_device *, @@ -647,8 +649,6 @@ static int mt9m111_release(struct soc_camera_device *icd); static struct soc_camera_ops mt9m111_ops = { .owner = THIS_MODULE, - .probe = mt9m111_video_probe, - .remove = mt9m111_video_remove, .init = mt9m111_init, .resume = mt9m111_resume, .release = mt9m111_release, @@ -672,8 +672,8 @@ static struct soc_camera_ops mt9m111_ops = { static int mt9m111_set_flip(struct soc_camera_device *icd, int flip, int mask) { - struct i2c_client *client = to_i2c_client(icd->control); - struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct mt9m111 *mt9m111 = i2c_get_clientdata(client); int ret; if (mt9m111->context == HIGHPOWER) { @@ -693,7 +693,7 @@ static int mt9m111_set_flip(struct soc_camera_device *icd, int flip, int mask) static int mt9m111_get_global_gain(struct soc_camera_device *icd) { - struct i2c_client *client = to_i2c_client(icd->control); + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); int data; data = reg_read(GLOBAL_GAIN); @@ -705,7 +705,7 @@ static int mt9m111_get_global_gain(struct soc_camera_device *icd) static int mt9m111_set_global_gain(struct soc_camera_device *icd, int gain) { - struct i2c_client *client = to_i2c_client(icd->control); + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); u16 val; if (gain > 63 * 2 * 2) @@ -724,8 +724,8 @@ static int mt9m111_set_global_gain(struct soc_camera_device *icd, int gain) static int mt9m111_set_autoexposure(struct soc_camera_device *icd, int on) { - struct i2c_client *client = to_i2c_client(icd->control); - struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct mt9m111 *mt9m111 = i2c_get_clientdata(client); int ret; if (on) @@ -741,8 +741,8 @@ static int mt9m111_set_autoexposure(struct soc_camera_device *icd, int on) static int mt9m111_set_autowhitebalance(struct soc_camera_device *icd, int on) { - struct i2c_client *client = to_i2c_client(icd->control); - struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct mt9m111 *mt9m111 = i2c_get_clientdata(client); int ret; if (on) @@ -759,8 +759,8 @@ static int mt9m111_set_autowhitebalance(struct soc_camera_device *icd, int on) static int mt9m111_get_control(struct soc_camera_device *icd, struct v4l2_control *ctrl) { - struct i2c_client *client = to_i2c_client(icd->control); - struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct mt9m111 *mt9m111 = i2c_get_clientdata(client); int data; switch (ctrl->id) { @@ -803,7 +803,8 @@ static int mt9m111_get_control(struct soc_camera_device *icd, static int mt9m111_set_control(struct soc_camera_device *icd, struct v4l2_control *ctrl) { - struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct mt9m111 *mt9m111 = i2c_get_clientdata(client); const struct v4l2_queryctrl *qctrl; int ret; @@ -841,7 +842,8 @@ static int mt9m111_set_control(struct soc_camera_device *icd, static int mt9m111_restore_state(struct soc_camera_device *icd) { - struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct mt9m111 *mt9m111 = i2c_get_clientdata(client); mt9m111_set_context(icd, mt9m111->context); mt9m111_set_pixfmt(icd, mt9m111->pixfmt); @@ -856,7 +858,8 @@ static int mt9m111_restore_state(struct soc_camera_device *icd) static int mt9m111_resume(struct soc_camera_device *icd) { - struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct mt9m111 *mt9m111 = i2c_get_clientdata(client); int ret = 0; if (mt9m111->powered) { @@ -871,7 +874,8 @@ static int mt9m111_resume(struct soc_camera_device *icd) static int mt9m111_init(struct soc_camera_device *icd) { - struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct mt9m111 *mt9m111 = i2c_get_clientdata(client); int ret; mt9m111->context = HIGHPOWER; @@ -902,10 +906,10 @@ static int mt9m111_release(struct soc_camera_device *icd) * Interface active, can use i2c. If it fails, it can indeed mean, that * this wasn't our capture interface, so, we wait for the right one */ -static int mt9m111_video_probe(struct soc_camera_device *icd) +static int mt9m111_video_probe(struct soc_camera_device *icd, + struct i2c_client *client) { - struct i2c_client *client = to_i2c_client(icd->control); - struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); + struct mt9m111 *mt9m111 = i2c_get_clientdata(client); s32 data; int ret; @@ -917,6 +921,11 @@ static int mt9m111_video_probe(struct soc_camera_device *icd) to_soc_camera_host(icd->dev.parent)->nr != icd->iface) return -ENODEV; + /* Switch master clock on */ + ret = soc_camera_video_start(icd, &client->dev); + if (ret) + goto evstart; + ret = mt9m111_enable(icd); if (ret) goto ei2c; @@ -945,31 +954,18 @@ static int mt9m111_video_probe(struct soc_camera_device *icd) dev_info(&icd->dev, "Detected a MT9M11x chip ID %x\n", data); - ret = soc_camera_video_start(icd); - if (ret) - goto eisis; - mt9m111->autoexposure = 1; mt9m111->autowhitebalance = 1; mt9m111->swap_rgb_even_odd = 1; mt9m111->swap_rgb_red_blue = 1; - return 0; -eisis: ei2c: + soc_camera_video_stop(icd); +evstart: return ret; } -static void mt9m111_video_remove(struct soc_camera_device *icd) -{ - struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); - - dev_dbg(&icd->dev, "Video %x removed: %p, %p\n", mt9m111->client->addr, - mt9m111->icd.dev.parent, mt9m111->icd.vdev); - soc_camera_video_stop(&mt9m111->icd); -} - #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26) static int mt9m111_probe(struct i2c_client *client) #else @@ -978,11 +974,17 @@ static int mt9m111_probe(struct i2c_client *client, #endif { struct mt9m111 *mt9m111; - struct soc_camera_device *icd; + struct soc_camera_device *icd = client->dev.platform_data; struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); - struct soc_camera_link *icl = client->dev.platform_data; + struct soc_camera_link *icl; int ret; + if (!icd) { + dev_err(&client->dev, "MT9M11x: missing soc-camera data!\n"); + return -EINVAL; + } + + icl = to_soc_camera_link(icd); if (!icl) { dev_err(&client->dev, "MT9M11x driver needs platform data\n"); return -EINVAL; @@ -998,13 +1000,10 @@ static int mt9m111_probe(struct i2c_client *client, if (!mt9m111) return -ENOMEM; - mt9m111->client = client; i2c_set_clientdata(client, mt9m111); /* Second stage probe - when a capture adapter is there */ - icd = &mt9m111->icd; icd->ops = &mt9m111_ops; - icd->control = &client->dev; icd->x_min = MT9M111_MIN_DARK_COLS; icd->y_min = MT9M111_MIN_DARK_ROWS; icd->x_current = icd->x_min; @@ -1014,22 +1013,25 @@ static int mt9m111_probe(struct i2c_client *client, icd->height_min = MT9M111_MIN_DARK_COLS; icd->height_max = MT9M111_MAX_HEIGHT; icd->y_skip_top = 0; - icd->iface = icl->bus_id; - ret = soc_camera_device_register(icd); - if (ret) - goto eisdr; - return 0; + ret = mt9m111_video_probe(icd, client); + if (ret) { + icd->ops = NULL; + i2c_set_clientdata(client, NULL); + kfree(mt9m111); + } -eisdr: - kfree(mt9m111); return ret; } static int mt9m111_remove(struct i2c_client *client) { struct mt9m111 *mt9m111 = i2c_get_clientdata(client); - soc_camera_device_unregister(&mt9m111->icd); + struct soc_camera_device *icd = client->dev.platform_data; + + icd->ops = NULL; + i2c_set_clientdata(client, NULL); + client->driver = NULL; kfree(mt9m111); return 0; diff --git a/linux/drivers/media/video/mt9t031.c b/linux/drivers/media/video/mt9t031.c index a57051522..b389223bc 100644 --- a/linux/drivers/media/video/mt9t031.c +++ b/linux/drivers/media/video/mt9t031.c @@ -68,8 +68,6 @@ static const struct soc_camera_data_format mt9t031_colour_formats[] = { }; struct mt9t031 { - struct i2c_client *client; - struct soc_camera_device icd; int model; /* V4L2_IDENT_MT9T031* codes from v4l2-chip-ident.h */ unsigned char autoexposure; u16 xskip; @@ -138,8 +136,8 @@ static int get_shutter(struct i2c_client *client, u32 *data) static int mt9t031_init(struct soc_camera_device *icd) { - struct i2c_client *client = to_i2c_client(icd->control); - struct soc_camera_link *icl = client->dev.platform_data; + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct soc_camera_link *icl = to_soc_camera_link(icd); int ret; if (icl->power) { @@ -166,8 +164,8 @@ static int mt9t031_init(struct soc_camera_device *icd) static int mt9t031_release(struct soc_camera_device *icd) { - struct i2c_client *client = to_i2c_client(icd->control); - struct soc_camera_link *icl = client->dev.platform_data; + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct soc_camera_link *icl = to_soc_camera_link(icd); /* Disable the chip */ reg_clear(client, MT9T031_OUTPUT_CONTROL, 2); @@ -180,7 +178,7 @@ static int mt9t031_release(struct soc_camera_device *icd) static int mt9t031_start_capture(struct soc_camera_device *icd) { - struct i2c_client *client = to_i2c_client(icd->control); + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); /* Switch to master "normal" mode */ if (reg_set(client, MT9T031_OUTPUT_CONTROL, 2) < 0) @@ -190,7 +188,7 @@ static int mt9t031_start_capture(struct soc_camera_device *icd) static int mt9t031_stop_capture(struct soc_camera_device *icd) { - struct i2c_client *client = to_i2c_client(icd->control); + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); /* Stop sensor readout */ if (reg_clear(client, MT9T031_OUTPUT_CONTROL, 2) < 0) @@ -201,7 +199,7 @@ static int mt9t031_stop_capture(struct soc_camera_device *icd) static int mt9t031_set_bus_param(struct soc_camera_device *icd, unsigned long flags) { - struct i2c_client *client = to_i2c_client(icd->control); + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); /* The caller should have queried our parameters, check anyway */ if (flags & ~MT9T031_BUS_PARAM) @@ -217,8 +215,7 @@ static int mt9t031_set_bus_param(struct soc_camera_device *icd, static unsigned long mt9t031_query_bus_param(struct soc_camera_device *icd) { - struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd); - struct soc_camera_link *icl = mt9t031->client->dev.platform_data; + struct soc_camera_link *icl = to_soc_camera_link(icd); return soc_camera_apply_sensor_flags(icl, MT9T031_BUS_PARAM); } @@ -238,8 +235,8 @@ static void recalculate_limits(struct soc_camera_device *icd, static int mt9t031_set_params(struct soc_camera_device *icd, struct v4l2_rect *rect, u16 xskip, u16 yskip) { - struct i2c_client *client = to_i2c_client(icd->control); - struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd); + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct mt9t031 *mt9t031 = i2c_get_clientdata(client); int ret; u16 xbin, ybin, width, height, left, top; const u16 hblank = MT9T031_HORIZONTAL_BLANK, @@ -336,7 +333,8 @@ static int mt9t031_set_params(struct soc_camera_device *icd, static int mt9t031_set_crop(struct soc_camera_device *icd, struct v4l2_rect *rect) { - struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd); + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct mt9t031 *mt9t031 = i2c_get_clientdata(client); /* CROP - no change in scaling, or in limits */ return mt9t031_set_params(icd, rect, mt9t031->xskip, mt9t031->yskip); @@ -345,7 +343,8 @@ static int mt9t031_set_crop(struct soc_camera_device *icd, static int mt9t031_set_fmt(struct soc_camera_device *icd, struct v4l2_format *f) { - struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd); + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct mt9t031 *mt9t031 = i2c_get_clientdata(client); int ret; u16 xskip, yskip; struct v4l2_rect rect = { @@ -395,12 +394,13 @@ static int mt9t031_try_fmt(struct soc_camera_device *icd, static int mt9t031_get_chip_id(struct soc_camera_device *icd, struct v4l2_dbg_chip_ident *id) { - struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd); + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct mt9t031 *mt9t031 = i2c_get_clientdata(client); if (id->match.type != V4L2_CHIP_MATCH_I2C_ADDR) return -EINVAL; - if (id->match.addr != mt9t031->client->addr) + if (id->match.addr != client->addr) return -ENODEV; id->ident = mt9t031->model; @@ -413,7 +413,7 @@ static int mt9t031_get_chip_id(struct soc_camera_device *icd, static int mt9t031_get_register(struct soc_camera_device *icd, struct v4l2_dbg_register *reg) { - struct i2c_client *client = to_i2c_client(icd->control); + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff) return -EINVAL; @@ -432,7 +432,7 @@ static int mt9t031_get_register(struct soc_camera_device *icd, static int mt9t031_set_register(struct soc_camera_device *icd, struct v4l2_dbg_register *reg) { - struct i2c_client *client = to_i2c_client(icd->control); + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff) return -EINVAL; @@ -493,15 +493,11 @@ static const struct v4l2_queryctrl mt9t031_controls[] = { } }; -static int mt9t031_video_probe(struct soc_camera_device *); -static void mt9t031_video_remove(struct soc_camera_device *); static int mt9t031_get_control(struct soc_camera_device *, struct v4l2_control *); static int mt9t031_set_control(struct soc_camera_device *, struct v4l2_control *); static struct soc_camera_ops mt9t031_ops = { .owner = THIS_MODULE, - .probe = mt9t031_video_probe, - .remove = mt9t031_video_remove, .init = mt9t031_init, .release = mt9t031_release, .start_capture = mt9t031_start_capture, @@ -524,8 +520,8 @@ static struct soc_camera_ops mt9t031_ops = { static int mt9t031_get_control(struct soc_camera_device *icd, struct v4l2_control *ctrl) { - struct i2c_client *client = to_i2c_client(icd->control); - struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd); + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct mt9t031 *mt9t031 = i2c_get_clientdata(client); int data; switch (ctrl->id) { @@ -550,8 +546,8 @@ static int mt9t031_get_control(struct soc_camera_device *icd, struct v4l2_contro static int mt9t031_set_control(struct soc_camera_device *icd, struct v4l2_control *ctrl) { - struct i2c_client *client = to_i2c_client(icd->control); - struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd); + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct mt9t031 *mt9t031 = i2c_get_clientdata(client); const struct v4l2_queryctrl *qctrl; int data; @@ -657,10 +653,10 @@ static int mt9t031_set_control(struct soc_camera_device *icd, struct v4l2_contro /* Interface active, can use i2c. If it fails, it can indeed mean, that * this wasn't our capture interface, so, we wait for the right one */ -static int mt9t031_video_probe(struct soc_camera_device *icd) +static int mt9t031_video_probe(struct soc_camera_device *icd, + struct i2c_client *client) { - struct i2c_client *client = to_i2c_client(icd->control); - struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd); + struct mt9t031 *mt9t031 = i2c_get_clientdata(client); s32 data; int ret; @@ -670,6 +666,11 @@ static int mt9t031_video_probe(struct soc_camera_device *icd) to_soc_camera_host(icd->dev.parent)->nr != icd->iface) return -ENODEV; + /* Switch master clock on */ + ret = soc_camera_video_start(icd, &client->dev); + if (ret) + return ret; + /* Enable the chip */ data = reg_write(client, MT9T031_CHIP_ENABLE, 1); dev_dbg(&icd->dev, "write: %d\n", data); @@ -677,6 +678,8 @@ static int mt9t031_video_probe(struct soc_camera_device *icd) /* Read out the chip version register */ data = reg_read(client, MT9T031_CHIP_VERSION); + soc_camera_video_stop(icd); + switch (data) { case 0x1621: mt9t031->model = V4L2_IDENT_MT9T031; @@ -684,33 +687,14 @@ static int mt9t031_video_probe(struct soc_camera_device *icd) icd->num_formats = ARRAY_SIZE(mt9t031_colour_formats); break; default: - ret = -ENODEV; dev_err(&icd->dev, "No MT9T031 chip detected, register read %x\n", data); - goto ei2c; + return -ENODEV; } dev_info(&icd->dev, "Detected a MT9T031 chip ID %x\n", data); - /* Now that we know the model, we can start video */ - ret = soc_camera_video_start(icd); - if (ret) - goto evstart; - return 0; - -evstart: -ei2c: - return ret; -} - -static void mt9t031_video_remove(struct soc_camera_device *icd) -{ - struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd); - - dev_dbg(&icd->dev, "Video %x removed: %p, %p\n", mt9t031->client->addr, - icd->dev.parent, icd->vdev); - soc_camera_video_stop(icd); } #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26) @@ -721,11 +705,17 @@ static int mt9t031_probe(struct i2c_client *client, #endif { struct mt9t031 *mt9t031; - struct soc_camera_device *icd; + struct soc_camera_device *icd = client->dev.platform_data; struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); - struct soc_camera_link *icl = client->dev.platform_data; + struct soc_camera_link *icl; int ret; + if (!icd) { + dev_err(&client->dev, "MT9T031: missing soc-camera data!\n"); + return -EINVAL; + } + + icl = to_soc_camera_link(icd); if (!icl) { dev_err(&client->dev, "MT9T031 driver needs platform data\n"); return -EINVAL; @@ -741,13 +731,10 @@ static int mt9t031_probe(struct i2c_client *client, if (!mt9t031) return -ENOMEM; - mt9t031->client = client; i2c_set_clientdata(client, mt9t031); /* Second stage probe - when a capture adapter is there */ - icd = &mt9t031->icd; icd->ops = &mt9t031_ops; - icd->control = &client->dev; icd->x_min = MT9T031_COLUMN_SKIP; icd->y_min = MT9T031_ROW_SKIP; icd->x_current = icd->x_min; @@ -757,7 +744,6 @@ static int mt9t031_probe(struct i2c_client *client, icd->height_min = MT9T031_MIN_HEIGHT; icd->height_max = MT9T031_MAX_HEIGHT; icd->y_skip_top = 0; - icd->iface = icl->bus_id; /* Simulated autoexposure. If enabled, we calculate shutter width * ourselves in the driver based on vertical blanking and frame width */ mt9t031->autoexposure = 1; @@ -765,24 +751,24 @@ static int mt9t031_probe(struct i2c_client *client, mt9t031->xskip = 1; mt9t031->yskip = 1; - ret = soc_camera_device_register(icd); - if (ret) - goto eisdr; - - return 0; + ret = mt9t031_video_probe(icd, client); + if (ret) { + icd->ops = NULL; + i2c_set_clientdata(client, NULL); + kfree(mt9t031); + } -eisdr: - i2c_set_clientdata(client, NULL); - kfree(mt9t031); return ret; } static int mt9t031_remove(struct i2c_client *client) { struct mt9t031 *mt9t031 = i2c_get_clientdata(client); + struct soc_camera_device *icd = client->dev.platform_data; - soc_camera_device_unregister(&mt9t031->icd); + icd->ops = NULL; i2c_set_clientdata(client, NULL); + client->driver = NULL; kfree(mt9t031); return 0; diff --git a/linux/drivers/media/video/mt9v022.c b/linux/drivers/media/video/mt9v022.c index 4841e6eea..204481f77 100644 --- a/linux/drivers/media/video/mt9v022.c +++ b/linux/drivers/media/video/mt9v022.c @@ -85,8 +85,6 @@ static const struct soc_camera_data_format mt9v022_monochrome_formats[] = { }; struct mt9v022 { - struct i2c_client *client; - struct soc_camera_device icd; int model; /* V4L2_IDENT_MT9V022* codes from v4l2-chip-ident.h */ u16 chip_control; }; @@ -127,9 +125,9 @@ static int reg_clear(struct i2c_client *client, const u8 reg, static int mt9v022_init(struct soc_camera_device *icd) { - struct i2c_client *client = to_i2c_client(icd->control); - struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd); - struct soc_camera_link *icl = client->dev.platform_data; + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct soc_camera_link *icl = to_soc_camera_link(icd); + struct mt9v022 *mt9v022 = i2c_get_clientdata(client); int ret; if (icl->power) { @@ -173,19 +171,19 @@ static int mt9v022_init(struct soc_camera_device *icd) static int mt9v022_release(struct soc_camera_device *icd) { - struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd); - struct soc_camera_link *icl = mt9v022->client->dev.platform_data; + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct soc_camera_link *icl = to_soc_camera_link(icd); if (icl->power) - icl->power(&mt9v022->client->dev, 0); + icl->power(&client->dev, 0); return 0; } static int mt9v022_start_capture(struct soc_camera_device *icd) { - struct i2c_client *client = to_i2c_client(icd->control); - struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd); + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct mt9v022 *mt9v022 = i2c_get_clientdata(client); /* Switch to master "normal" mode */ mt9v022->chip_control &= ~0x10; if (reg_write(client, MT9V022_CHIP_CONTROL, @@ -196,8 +194,8 @@ static int mt9v022_start_capture(struct soc_camera_device *icd) static int mt9v022_stop_capture(struct soc_camera_device *icd) { - struct i2c_client *client = to_i2c_client(icd->control); - struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd); + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct mt9v022 *mt9v022 = i2c_get_clientdata(client); /* Switch to snapshot mode */ mt9v022->chip_control |= 0x10; if (reg_write(client, MT9V022_CHIP_CONTROL, @@ -209,9 +207,9 @@ static int mt9v022_stop_capture(struct soc_camera_device *icd) static int mt9v022_set_bus_param(struct soc_camera_device *icd, unsigned long flags) { - struct i2c_client *client = to_i2c_client(icd->control); - struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd); - struct soc_camera_link *icl = client->dev.platform_data; + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct mt9v022 *mt9v022 = i2c_get_clientdata(client); + struct soc_camera_link *icl = to_soc_camera_link(icd); unsigned int width_flag = flags & SOCAM_DATAWIDTH_MASK; int ret; u16 pixclk = 0; @@ -263,8 +261,7 @@ static int mt9v022_set_bus_param(struct soc_camera_device *icd, static unsigned long mt9v022_query_bus_param(struct soc_camera_device *icd) { - struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd); - struct soc_camera_link *icl = mt9v022->client->dev.platform_data; + struct soc_camera_link *icl = to_soc_camera_link(icd); unsigned int width_flag; if (icl->query_bus_param) @@ -283,7 +280,7 @@ static unsigned long mt9v022_query_bus_param(struct soc_camera_device *icd) static int mt9v022_set_crop(struct soc_camera_device *icd, struct v4l2_rect *rect) { - struct i2c_client *client = to_i2c_client(icd->control); + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); int ret; /* Like in example app. Contradicts the datasheet though */ @@ -326,7 +323,8 @@ static int mt9v022_set_crop(struct soc_camera_device *icd, static int mt9v022_set_fmt(struct soc_camera_device *icd, struct v4l2_format *f) { - struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd); + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct mt9v022 *mt9v022 = i2c_get_clientdata(client); struct v4l2_pix_format *pix = &f->fmt.pix; struct v4l2_rect rect = { .left = icd->x_current, @@ -374,12 +372,13 @@ static int mt9v022_try_fmt(struct soc_camera_device *icd, static int mt9v022_get_chip_id(struct soc_camera_device *icd, struct v4l2_dbg_chip_ident *id) { - struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd); + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct mt9v022 *mt9v022 = i2c_get_clientdata(client); if (id->match.type != V4L2_CHIP_MATCH_I2C_ADDR) return -EINVAL; - if (id->match.addr != mt9v022->client->addr) + if (id->match.addr != client->addr) return -ENODEV; id->ident = mt9v022->model; @@ -392,7 +391,7 @@ static int mt9v022_get_chip_id(struct soc_camera_device *icd, static int mt9v022_get_register(struct soc_camera_device *icd, struct v4l2_dbg_register *reg) { - struct i2c_client *client = to_i2c_client(icd->control); + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff) return -EINVAL; @@ -412,7 +411,7 @@ static int mt9v022_get_register(struct soc_camera_device *icd, static int mt9v022_set_register(struct soc_camera_device *icd, struct v4l2_dbg_register *reg) { - struct i2c_client *client = to_i2c_client(icd->control); + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff) return -EINVAL; @@ -481,15 +480,11 @@ static const struct v4l2_queryctrl mt9v022_controls[] = { } }; -static int mt9v022_video_probe(struct soc_camera_device *); -static void mt9v022_video_remove(struct soc_camera_device *); static int mt9v022_get_control(struct soc_camera_device *, struct v4l2_control *); static int mt9v022_set_control(struct soc_camera_device *, struct v4l2_control *); static struct soc_camera_ops mt9v022_ops = { .owner = THIS_MODULE, - .probe = mt9v022_video_probe, - .remove = mt9v022_video_remove, .init = mt9v022_init, .release = mt9v022_release, .start_capture = mt9v022_start_capture, @@ -513,7 +508,7 @@ static struct soc_camera_ops mt9v022_ops = { static int mt9v022_get_control(struct soc_camera_device *icd, struct v4l2_control *ctrl) { - struct i2c_client *client = to_i2c_client(icd->control); + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); int data; switch (ctrl->id) { @@ -549,7 +544,7 @@ static int mt9v022_set_control(struct soc_camera_device *icd, struct v4l2_control *ctrl) { int data; - struct i2c_client *client = to_i2c_client(icd->control); + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); const struct v4l2_queryctrl *qctrl; qctrl = soc_camera_find_qctrl(&mt9v022_ops, ctrl->id); @@ -646,11 +641,11 @@ static int mt9v022_set_control(struct soc_camera_device *icd, /* Interface active, can use i2c. If it fails, it can indeed mean, that * this wasn't our capture interface, so, we wait for the right one */ -static int mt9v022_video_probe(struct soc_camera_device *icd) +static int mt9v022_video_probe(struct soc_camera_device *icd, + struct i2c_client *client) { - struct i2c_client *client = to_i2c_client(icd->control); - struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd); - struct soc_camera_link *icl = client->dev.platform_data; + struct mt9v022 *mt9v022 = i2c_get_clientdata(client); + struct soc_camera_link *icl = to_soc_camera_link(icd); s32 data; int ret; unsigned long flags; @@ -659,6 +654,11 @@ static int mt9v022_video_probe(struct soc_camera_device *icd) to_soc_camera_host(icd->dev.parent)->nr != icd->iface) return -ENODEV; + /* Switch master clock on */ + ret = soc_camera_video_start(icd, &client->dev); + if (ret) + return ret; + /* Read out the chip version register */ data = reg_read(client, MT9V022_CHIP_VERSION); @@ -678,6 +678,8 @@ static int mt9v022_video_probe(struct soc_camera_device *icd) udelay(200); if (reg_read(client, MT9V022_RESET)) { dev_err(&icd->dev, "Resetting MT9V022 failed!\n"); + if (ret > 0) + ret = -EIO; goto ei2c; } @@ -694,7 +696,7 @@ static int mt9v022_video_probe(struct soc_camera_device *icd) } if (ret < 0) - goto eisis; + goto ei2c; icd->num_formats = 0; @@ -716,29 +718,23 @@ static int mt9v022_video_probe(struct soc_camera_device *icd) if (flags & SOCAM_DATAWIDTH_8) icd->num_formats++; - ret = soc_camera_video_start(icd); - if (ret < 0) - goto eisis; - dev_info(&icd->dev, "Detected a MT9V022 chip ID %x, %s sensor\n", data, mt9v022->model == V4L2_IDENT_MT9V022IX7ATM ? "monochrome" : "colour"); - return 0; - -eisis: ei2c: + soc_camera_video_stop(icd); + return ret; } static void mt9v022_video_remove(struct soc_camera_device *icd) { - struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd); - struct soc_camera_link *icl = mt9v022->client->dev.platform_data; + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct soc_camera_link *icl = to_soc_camera_link(icd); - dev_dbg(&icd->dev, "Video %x removed: %p, %p\n", mt9v022->client->addr, + dev_dbg(&icd->dev, "Video %x removed: %p, %p\n", client->addr, icd->dev.parent, icd->vdev); - soc_camera_video_stop(icd); if (icl->free_bus) icl->free_bus(icl); } @@ -751,11 +747,17 @@ static int mt9v022_probe(struct i2c_client *client) #endif { struct mt9v022 *mt9v022; - struct soc_camera_device *icd; + struct soc_camera_device *icd = client->dev.platform_data; struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); - struct soc_camera_link *icl = client->dev.platform_data; + struct soc_camera_link *icl; int ret; + if (!icd) { + dev_err(&client->dev, "MT9V022: missing soc-camera data!\n"); + return -EINVAL; + } + + icl = to_soc_camera_link(icd); if (!icl) { dev_err(&client->dev, "MT9V022 driver needs platform data\n"); return -EINVAL; @@ -772,12 +774,9 @@ static int mt9v022_probe(struct i2c_client *client) return -ENOMEM; mt9v022->chip_control = MT9V022_CHIP_CONTROL_DEFAULT; - mt9v022->client = client; i2c_set_clientdata(client, mt9v022); - icd = &mt9v022->icd; icd->ops = &mt9v022_ops; - icd->control = &client->dev; icd->x_min = 1; icd->y_min = 4; icd->x_current = 1; @@ -787,24 +786,26 @@ static int mt9v022_probe(struct i2c_client *client) icd->height_min = 32; icd->height_max = 480; icd->y_skip_top = 1; - icd->iface = icl->bus_id; - - ret = soc_camera_device_register(icd); - if (ret) - goto eisdr; - return 0; + ret = mt9v022_video_probe(icd, client); + if (ret) { + icd->ops = NULL; + i2c_set_clientdata(client, NULL); + kfree(mt9v022); + } -eisdr: - kfree(mt9v022); return ret; } static int mt9v022_remove(struct i2c_client *client) { struct mt9v022 *mt9v022 = i2c_get_clientdata(client); + struct soc_camera_device *icd = client->dev.platform_data; - soc_camera_device_unregister(&mt9v022->icd); + icd->ops = NULL; + mt9v022_video_remove(icd); + i2c_set_clientdata(client, NULL); + client->driver = NULL; kfree(mt9v022); return 0; diff --git a/linux/drivers/media/video/mx3_camera.c b/linux/drivers/media/video/mx3_camera.c index 9770cb793..2edf77a62 100644 --- a/linux/drivers/media/video/mx3_camera.c +++ b/linux/drivers/media/video/mx3_camera.c @@ -503,18 +503,19 @@ static int mx3_camera_add_device(struct soc_camera_device *icd) mx3_camera_activate(mx3_cam, icd); ret = icd->ops->init(icd); - if (ret < 0) { - clk_disable(mx3_cam->clk); + if (ret < 0) goto einit; - } mx3_cam->icd = icd; + dev_info(&icd->dev, "MX3 Camera driver attached to camera %d\n", + icd->devnum); + + return 0; + einit: + clk_disable(mx3_cam->clk); ebusy: - if (!ret) - dev_info(&icd->dev, "MX3 Camera driver attached to camera %d\n", - icd->devnum); return ret; } @@ -947,9 +948,10 @@ static int mx3_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt) camera_flags = icd->ops->query_bus_param(icd); common_flags = soc_camera_bus_param_compatible(camera_flags, bus_flags); + dev_dbg(ici->dev, "Flags cam: 0x%lx host: 0x%lx common: 0x%lx\n", + camera_flags, bus_flags, common_flags); if (!common_flags) { - dev_dbg(ici->dev, "no common flags: camera %lx, host %lx\n", - camera_flags, bus_flags); + dev_dbg(ici->dev, "no common flags"); return -EINVAL; } @@ -1002,8 +1004,11 @@ static int mx3_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt) SOCAM_DATAWIDTH_4; ret = icd->ops->set_bus_param(icd, common_flags); - if (ret < 0) + if (ret < 0) { + dev_dbg(ici->dev, "camera set_bus_param(%lx) returned %d\n", + common_flags, ret); return ret; + } /* * So far only gated clock mode is supported. Add a line @@ -1127,8 +1132,9 @@ static int __devinit mx3_camera_probe(struct platform_device *pdev) INIT_LIST_HEAD(&mx3_cam->capture); spin_lock_init(&mx3_cam->lock); - base = ioremap(res->start, res->end - res->start + 1); + base = ioremap(res->start, resource_size(res)); if (!base) { + pr_err("Couldn't map %x@%x\n", resource_size(res), res->start); err = -ENOMEM; goto eioremap; } @@ -1215,3 +1221,4 @@ module_exit(mx3_camera_exit); MODULE_DESCRIPTION("i.MX3x SoC Camera Host driver"); MODULE_AUTHOR("Guennadi Liakhovetski "); MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:" MX3_CAM_DRV_NAME); diff --git a/linux/drivers/media/video/ov772x.c b/linux/drivers/media/video/ov772x.c index 4b0363940..297a46fc9 100644 --- a/linux/drivers/media/video/ov772x.c +++ b/linux/drivers/media/video/ov772x.c @@ -399,8 +399,6 @@ struct ov772x_win_size { struct ov772x_priv { struct ov772x_camera_info *info; - struct i2c_client *client; - struct soc_camera_device icd; const struct ov772x_color_format *fmt; const struct ov772x_win_size *win; int model; @@ -619,53 +617,56 @@ static int ov772x_reset(struct i2c_client *client) static int ov772x_init(struct soc_camera_device *icd) { - struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd); + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct soc_camera_link *icl = to_soc_camera_link(icd); int ret = 0; - if (priv->info->link.power) { - ret = priv->info->link.power(&priv->client->dev, 1); + if (icl->power) { + ret = icl->power(&client->dev, 1); if (ret < 0) return ret; } - if (priv->info->link.reset) - ret = priv->info->link.reset(&priv->client->dev); + if (icl->reset) + ret = icl->reset(&client->dev); return ret; } static int ov772x_release(struct soc_camera_device *icd) { - struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd); + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct soc_camera_link *icl = to_soc_camera_link(icd); int ret = 0; - if (priv->info->link.power) - ret = priv->info->link.power(&priv->client->dev, 0); + if (icl->power) + ret = icl->power(&client->dev, 0); return ret; } static int ov772x_start_capture(struct soc_camera_device *icd) { - struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd); + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct ov772x_priv *priv = i2c_get_clientdata(client); if (!priv->win || !priv->fmt) { dev_err(&icd->dev, "norm or win select error\n"); return -EPERM; } - ov772x_mask_set(priv->client, COM2, SOFT_SLEEP_MODE, 0); + ov772x_mask_set(client, COM2, SOFT_SLEEP_MODE, 0); dev_dbg(&icd->dev, - "format %s, win %s\n", priv->fmt->name, priv->win->name); + "format %s, win %s\n", priv->fmt->name, priv->win->name); return 0; } static int ov772x_stop_capture(struct soc_camera_device *icd) { - struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd); - ov772x_mask_set(priv->client, COM2, SOFT_SLEEP_MODE, SOFT_SLEEP_MODE); + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + ov772x_mask_set(client, COM2, SOFT_SLEEP_MODE, SOFT_SLEEP_MODE); return 0; } @@ -677,8 +678,9 @@ static int ov772x_set_bus_param(struct soc_camera_device *icd, static unsigned long ov772x_query_bus_param(struct soc_camera_device *icd) { - struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd); - struct soc_camera_link *icl = &priv->info->link; + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct ov772x_priv *priv = i2c_get_clientdata(client); + struct soc_camera_link *icl = to_soc_camera_link(icd); unsigned long flags = SOCAM_PCLK_SAMPLE_RISING | SOCAM_MASTER | SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_DATA_ACTIVE_HIGH | priv->info->buswidth; @@ -689,7 +691,8 @@ static unsigned long ov772x_query_bus_param(struct soc_camera_device *icd) static int ov772x_get_control(struct soc_camera_device *icd, struct v4l2_control *ctrl) { - struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd); + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct ov772x_priv *priv = i2c_get_clientdata(client); switch (ctrl->id) { case V4L2_CID_VFLIP: @@ -705,7 +708,8 @@ static int ov772x_get_control(struct soc_camera_device *icd, static int ov772x_set_control(struct soc_camera_device *icd, struct v4l2_control *ctrl) { - struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd); + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct ov772x_priv *priv = i2c_get_clientdata(client); int ret = 0; u8 val; @@ -715,14 +719,14 @@ static int ov772x_set_control(struct soc_camera_device *icd, priv->flag_vflip = ctrl->value; if (priv->info->flags & OV772X_FLAG_VFLIP) val ^= VFLIP_IMG; - ret = ov772x_mask_set(priv->client, COM3, VFLIP_IMG, val); + ret = ov772x_mask_set(client, COM3, VFLIP_IMG, val); break; case V4L2_CID_HFLIP: val = ctrl->value ? HFLIP_IMG : 0x00; priv->flag_hflip = ctrl->value; if (priv->info->flags & OV772X_FLAG_HFLIP) val ^= HFLIP_IMG; - ret = ov772x_mask_set(priv->client, COM3, HFLIP_IMG, val); + ret = ov772x_mask_set(client, COM3, HFLIP_IMG, val); break; } @@ -730,9 +734,10 @@ static int ov772x_set_control(struct soc_camera_device *icd, } static int ov772x_get_chip_id(struct soc_camera_device *icd, - struct v4l2_dbg_chip_ident *id) + struct v4l2_dbg_chip_ident *id) { - struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd); + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct ov772x_priv *priv = i2c_get_clientdata(client); id->ident = priv->model; id->revision = 0; @@ -744,14 +749,14 @@ static int ov772x_get_chip_id(struct soc_camera_device *icd, static int ov772x_get_register(struct soc_camera_device *icd, struct v4l2_dbg_register *reg) { - struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd); - int ret; + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + int ret; reg->size = 1; if (reg->reg > 0xff) return -EINVAL; - ret = i2c_smbus_read_byte_data(priv->client, reg->reg); + ret = i2c_smbus_read_byte_data(client, reg->reg); if (ret < 0) return ret; @@ -763,13 +768,13 @@ static int ov772x_get_register(struct soc_camera_device *icd, static int ov772x_set_register(struct soc_camera_device *icd, struct v4l2_dbg_register *reg) { - struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd); + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); if (reg->reg > 0xff || reg->val > 0xff) return -EINVAL; - return i2c_smbus_write_byte_data(priv->client, reg->reg, reg->val); + return i2c_smbus_write_byte_data(client, reg->reg, reg->val); } #endif @@ -793,9 +798,11 @@ ov772x_select_win(u32 width, u32 height) return win; } -static int ov772x_set_params(struct ov772x_priv *priv, u32 width, u32 height, - u32 pixfmt) +static int ov772x_set_params(struct soc_camera_device *icd, + u32 width, u32 height, u32 pixfmt) { + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct ov772x_priv *priv = i2c_get_clientdata(client); int ret = -EINVAL; u8 val; int i; @@ -810,6 +817,7 @@ static int ov772x_set_params(struct ov772x_priv *priv, u32 width, u32 height, break; } } + dev_dbg(&icd->dev, "Using fmt %x #%d\n", pixfmt, i); if (!priv->fmt) goto ov772x_set_fmt_error; @@ -821,7 +829,7 @@ static int ov772x_set_params(struct ov772x_priv *priv, u32 width, u32 height, /* * reset hardware */ - ov772x_reset(priv->client); + ov772x_reset(client); /* * Edge Ctrl @@ -835,17 +843,17 @@ static int ov772x_set_params(struct ov772x_priv *priv, u32 width, u32 height, * Remove it when manual mode. */ - ret = ov772x_mask_set(priv->client, DSPAUTO, EDGE_ACTRL, 0x00); + ret = ov772x_mask_set(client, DSPAUTO, EDGE_ACTRL, 0x00); if (ret < 0) goto ov772x_set_fmt_error; - ret = ov772x_mask_set(priv->client, + ret = ov772x_mask_set(client, EDGE_TRSHLD, EDGE_THRESHOLD_MASK, priv->info->edgectrl.threshold); if (ret < 0) goto ov772x_set_fmt_error; - ret = ov772x_mask_set(priv->client, + ret = ov772x_mask_set(client, EDGE_STRNGT, EDGE_STRENGTH_MASK, priv->info->edgectrl.strength); if (ret < 0) @@ -857,13 +865,13 @@ static int ov772x_set_params(struct ov772x_priv *priv, u32 width, u32 height, * * set upper and lower limit */ - ret = ov772x_mask_set(priv->client, + ret = ov772x_mask_set(client, EDGE_UPPER, EDGE_UPPER_MASK, priv->info->edgectrl.upper); if (ret < 0) goto ov772x_set_fmt_error; - ret = ov772x_mask_set(priv->client, + ret = ov772x_mask_set(client, EDGE_LOWER, EDGE_LOWER_MASK, priv->info->edgectrl.lower); if (ret < 0) @@ -873,7 +881,7 @@ static int ov772x_set_params(struct ov772x_priv *priv, u32 width, u32 height, /* * set size format */ - ret = ov772x_write_array(priv->client, priv->win->regs); + ret = ov772x_write_array(client, priv->win->regs); if (ret < 0) goto ov772x_set_fmt_error; @@ -882,7 +890,7 @@ static int ov772x_set_params(struct ov772x_priv *priv, u32 width, u32 height, */ val = priv->fmt->dsp3; if (val) { - ret = ov772x_mask_set(priv->client, + ret = ov772x_mask_set(client, DSP_CTRL3, UV_MASK, val); if (ret < 0) goto ov772x_set_fmt_error; @@ -901,7 +909,7 @@ static int ov772x_set_params(struct ov772x_priv *priv, u32 width, u32 height, if (priv->flag_hflip) val ^= HFLIP_IMG; - ret = ov772x_mask_set(priv->client, + ret = ov772x_mask_set(client, COM3, SWAP_MASK | IMG_MASK, val); if (ret < 0) goto ov772x_set_fmt_error; @@ -910,7 +918,7 @@ static int ov772x_set_params(struct ov772x_priv *priv, u32 width, u32 height, * set COM7 */ val = priv->win->com7_bit | priv->fmt->com7; - ret = ov772x_mask_set(priv->client, + ret = ov772x_mask_set(client, COM7, (SLCT_MASK | FMT_MASK | OFMT_MASK), val); if (ret < 0) @@ -920,7 +928,7 @@ static int ov772x_set_params(struct ov772x_priv *priv, u32 width, u32 height, ov772x_set_fmt_error: - ov772x_reset(priv->client); + ov772x_reset(client); priv->win = NULL; priv->fmt = NULL; @@ -930,22 +938,22 @@ ov772x_set_fmt_error: static int ov772x_set_crop(struct soc_camera_device *icd, struct v4l2_rect *rect) { - struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd); + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct ov772x_priv *priv = i2c_get_clientdata(client); if (!priv->fmt) return -EINVAL; - return ov772x_set_params(priv, rect->width, rect->height, + return ov772x_set_params(icd, rect->width, rect->height, priv->fmt->fourcc); } static int ov772x_set_fmt(struct soc_camera_device *icd, struct v4l2_format *f) { - struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd); struct v4l2_pix_format *pix = &f->fmt.pix; - return ov772x_set_params(priv, pix->width, pix->height, + return ov772x_set_params(icd, pix->width, pix->height, pix->pixelformat); } @@ -967,11 +975,13 @@ static int ov772x_try_fmt(struct soc_camera_device *icd, return 0; } -static int ov772x_video_probe(struct soc_camera_device *icd) +static int ov772x_video_probe(struct soc_camera_device *icd, + struct i2c_client *client) { - struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd); + struct ov772x_priv *priv = i2c_get_clientdata(client); u8 pid, ver; const char *devname; + int ret; /* * We must have a parent by now. And it cannot be a wrong one. @@ -993,11 +1003,16 @@ static int ov772x_video_probe(struct soc_camera_device *icd) icd->formats = ov772x_fmt_lists; icd->num_formats = ARRAY_SIZE(ov772x_fmt_lists); + /* Switch master clock on */ + ret = soc_camera_video_start(icd, &client->dev); + if (ret) + return ret; + /* * check and show product ID and manufacturer ID */ - pid = i2c_smbus_read_byte_data(priv->client, PID); - ver = i2c_smbus_read_byte_data(priv->client, VER); + pid = i2c_smbus_read_byte_data(client, PID); + ver = i2c_smbus_read_byte_data(client, VER); switch (VERSION(pid, ver)) { case OV7720: @@ -1011,7 +1026,8 @@ static int ov772x_video_probe(struct soc_camera_device *icd) default: dev_err(&icd->dev, "Product ID error %x:%x\n", pid, ver); - return -ENODEV; + ret = -ENODEV; + goto ever; } dev_info(&icd->dev, @@ -1019,21 +1035,17 @@ static int ov772x_video_probe(struct soc_camera_device *icd) devname, pid, ver, - i2c_smbus_read_byte_data(priv->client, MIDH), - i2c_smbus_read_byte_data(priv->client, MIDL)); - - return soc_camera_video_start(icd); -} + i2c_smbus_read_byte_data(client, MIDH), + i2c_smbus_read_byte_data(client, MIDL)); -static void ov772x_video_remove(struct soc_camera_device *icd) -{ soc_camera_video_stop(icd); + +ever: + return ret; } static struct soc_camera_ops ov772x_ops = { .owner = THIS_MODULE, - .probe = ov772x_video_probe, - .remove = ov772x_video_remove, .init = ov772x_init, .release = ov772x_release, .start_capture = ov772x_start_capture, @@ -1062,20 +1074,26 @@ static struct soc_camera_ops ov772x_ops = { static int ov772x_probe(struct i2c_client *client) #else static int ov772x_probe(struct i2c_client *client, - const struct i2c_device_id *did) + const struct i2c_device_id *did) #endif { struct ov772x_priv *priv; struct ov772x_camera_info *info; - struct soc_camera_device *icd; + struct soc_camera_device *icd = client->dev.platform_data; struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); + struct soc_camera_link *icl; int ret; - if (!client->dev.platform_data) + if (!icd) { + dev_err(&client->dev, "MT9M001: missing soc-camera data!\n"); return -EINVAL; + } - info = container_of(client->dev.platform_data, - struct ov772x_camera_info, link); + icl = to_soc_camera_link(icd); + if (!icl) + return -EINVAL; + + info = container_of(icl, struct ov772x_camera_info, link); if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { dev_err(&adapter->dev, @@ -1089,19 +1107,15 @@ static int ov772x_probe(struct i2c_client *client, return -ENOMEM; priv->info = info; - priv->client = client; i2c_set_clientdata(client, priv); - icd = &priv->icd; icd->ops = &ov772x_ops; - icd->control = &client->dev; icd->width_max = MAX_WIDTH; icd->height_max = MAX_HEIGHT; - icd->iface = priv->info->link.bus_id; - - ret = soc_camera_device_register(icd); + ret = ov772x_video_probe(icd, client); if (ret) { + icd->ops = NULL; i2c_set_clientdata(client, NULL); kfree(priv); } @@ -1112,8 +1126,9 @@ static int ov772x_probe(struct i2c_client *client, static int ov772x_remove(struct i2c_client *client) { struct ov772x_priv *priv = i2c_get_clientdata(client); + struct soc_camera_device *icd = client->dev.platform_data; - soc_camera_device_unregister(&priv->icd); + icd->ops = NULL; i2c_set_clientdata(client, NULL); kfree(priv); return 0; diff --git a/linux/drivers/media/video/pxa_camera.c b/linux/drivers/media/video/pxa_camera.c index 92fb8b191..8b1537581 100644 --- a/linux/drivers/media/video/pxa_camera.c +++ b/linux/drivers/media/video/pxa_camera.c @@ -842,7 +842,8 @@ static void pxa_camera_init_videobuf(struct videobuf_queue *q, sizeof(struct pxa_buffer), icd); } -static u32 mclk_get_divisor(struct pxa_camera_dev *pcdev) +static u32 mclk_get_divisor(struct platform_device *pdev, + struct pxa_camera_dev *pcdev) { unsigned long mclk = pcdev->mclk; u32 div; @@ -854,7 +855,7 @@ static u32 mclk_get_divisor(struct pxa_camera_dev *pcdev) /* mclk <= ciclk / 4 (27.4.2) */ if (mclk > lcdclk / 4) { mclk = lcdclk / 4; - dev_warn(pcdev->soc_host.dev, "Limiting master clock to %lu\n", mclk); + dev_warn(&pdev->dev, "Limiting master clock to %lu\n", mclk); } /* We verify mclk != 0, so if anyone breaks it, here comes their Oops */ @@ -864,8 +865,8 @@ static u32 mclk_get_divisor(struct pxa_camera_dev *pcdev) if (pcdev->platform_flags & PXA_CAMERA_MCLK_EN) pcdev->mclk = lcdclk / (2 * (div + 1)); - dev_dbg(pcdev->soc_host.dev, "LCD clock %luHz, target freq %luHz, " - "divisor %u\n", lcdclk, mclk, div); + dev_dbg(&pdev->dev, "LCD clock %luHz, target freq %luHz, divisor %u\n", + lcdclk, mclk, div); return div; } @@ -970,15 +971,20 @@ static int pxa_camera_add_device(struct soc_camera_device *icd) goto ebusy; } - dev_info(&icd->dev, "PXA Camera driver attached to camera %d\n", - icd->devnum); - pxa_camera_activate(pcdev); ret = icd->ops->init(icd); + if (ret < 0) + goto einit; + + pcdev->icd = icd; - if (!ret) - pcdev->icd = icd; + dev_info(&icd->dev, "PXA Camera driver attached to camera %d\n", + icd->devnum); + return 0; + +einit: + pxa_camera_deactivate(pcdev); ebusy: return ret; } @@ -1587,8 +1593,7 @@ static int __devinit pxa_camera_probe(struct platform_device *pdev) pcdev->mclk = 20000000; } - pcdev->soc_host.dev = &pdev->dev; - pcdev->mclk_divisor = mclk_get_divisor(pcdev); + pcdev->mclk_divisor = mclk_get_divisor(pdev, pcdev); INIT_LIST_HEAD(&pcdev->capture); spin_lock_init(&pcdev->lock); @@ -1653,6 +1658,7 @@ static int __devinit pxa_camera_probe(struct platform_device *pdev) pcdev->soc_host.drv_name = PXA_CAM_DRV_NAME; pcdev->soc_host.ops = &pxa_soc_camera_host_ops; pcdev->soc_host.priv = pcdev; + pcdev->soc_host.dev = &pdev->dev; pcdev->soc_host.nr = pdev->id; err = soc_camera_host_register(&pcdev->soc_host); @@ -1734,3 +1740,4 @@ module_exit(pxa_camera_exit); MODULE_DESCRIPTION("PXA27x SoC Camera Host driver"); MODULE_AUTHOR("Guennadi Liakhovetski "); MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:" PXA_CAM_DRV_NAME); diff --git a/linux/drivers/media/video/sh_mobile_ceu_camera.c b/linux/drivers/media/video/sh_mobile_ceu_camera.c index 1bae28a98..f8e4b5481 100644 --- a/linux/drivers/media/video/sh_mobile_ceu_camera.c +++ b/linux/drivers/media/video/sh_mobile_ceu_camera.c @@ -358,11 +358,13 @@ static int sh_mobile_ceu_add_device(struct soc_camera_device *icd) "SuperH Mobile CEU driver attached to camera %d\n", icd->devnum); + clk_enable(pcdev->clk); + ret = icd->ops->init(icd); - if (ret) + if (ret) { + clk_disable(pcdev->clk); goto err; - - clk_enable(pcdev->clk); + } ceu_write(pcdev, CAPSR, 1 << 16); /* reset */ while (ceu_read(pcdev, CSTSR) & 1) @@ -396,10 +398,10 @@ static void sh_mobile_ceu_remove_device(struct soc_camera_device *icd) } spin_unlock_irqrestore(&pcdev->lock, flags); - clk_disable(pcdev->clk); - icd->ops->release(icd); + clk_disable(pcdev->clk); + dev_info(&icd->dev, "SuperH Mobile CEU driver detached from camera %d\n", icd->devnum); @@ -938,3 +940,4 @@ module_exit(sh_mobile_ceu_exit); MODULE_DESCRIPTION("SuperH Mobile CEU driver"); MODULE_AUTHOR("Magnus Damm"); MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:sh_mobile_ceu"); diff --git a/linux/drivers/media/video/soc_camera.c b/linux/drivers/media/video/soc_camera.c index 8de620b78..f248ae27f 100644 --- a/linux/drivers/media/video/soc_camera.c +++ b/linux/drivers/media/video/soc_camera.c @@ -21,15 +21,15 @@ #include #include #include -#include #include +#include #include #include #include #include -#include #include +#include #include #include "compat.h" @@ -39,7 +39,7 @@ static LIST_HEAD(hosts); static LIST_HEAD(devices); -static DEFINE_MUTEX(list_lock); +static DEFINE_MUTEX(list_lock); /* Protects the list of hosts */ const struct soc_camera_data_format *soc_camera_format_by_fourcc( struct soc_camera_device *icd, unsigned int fourcc) @@ -210,6 +210,7 @@ static int soc_camera_dqbuf(struct file *file, void *priv, return videobuf_dqbuf(&icf->vb_vidq, p, file->f_flags & O_NONBLOCK); } +/* Always entered with .video_lock held */ static int soc_camera_init_user_formats(struct soc_camera_device *icd) { struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); @@ -258,9 +259,12 @@ static int soc_camera_init_user_formats(struct soc_camera_device *icd) return 0; } +/* Always entered with .video_lock held */ static void soc_camera_free_user_formats(struct soc_camera_device *icd) { + icd->current_fmt = NULL; vfree(icd->user_formats); + icd->user_formats = NULL; } /* Called with .vb_lock held */ @@ -311,10 +315,6 @@ static int soc_camera_open(struct file *file) struct soc_camera_file *icf; int ret; - icf = vmalloc(sizeof(*icf)); - if (!icf) - return -ENOMEM; - /* * It is safe to dereference these pointers now as long as a user has * the video device open - we are protected by the held cdev reference. @@ -322,8 +322,17 @@ static int soc_camera_open(struct file *file) vdev = video_devdata(file); icd = container_of(vdev->parent, struct soc_camera_device, dev); + + if (!icd->ops) + /* No device driver attached */ + return -ENODEV; + ici = to_soc_camera_host(icd->dev.parent); + icf = vmalloc(sizeof(*icf)); + if (!icf) + return -ENOMEM; + if (!try_module_get(icd->ops->owner)) { dev_err(&icd->dev, "Couldn't lock sensor driver.\n"); ret = -EINVAL; @@ -336,7 +345,7 @@ static int soc_camera_open(struct file *file) goto emgi; } - /* Protect against icd->remove() until we module_get() both drivers. */ + /* Protect against icd->ops->remove() until we module_get() both drivers. */ mutex_lock(&icd->video_lock); icf->icd = icd; @@ -351,11 +360,18 @@ static int soc_camera_open(struct file *file) .width = icd->width, .height = icd->height, .field = icd->field, - .pixelformat = icd->current_fmt->fourcc, - .colorspace = icd->current_fmt->colorspace, }, }; + ret = soc_camera_init_user_formats(icd); + if (ret < 0) + goto eiufmt; + + dev_dbg(&icd->dev, "Using fmt %x\n", icd->current_fmt->fourcc); + + f.fmt.pix.pixelformat = icd->current_fmt->fourcc; + f.fmt.pix.colorspace = icd->current_fmt->colorspace; + ret = ici->ops->add(icd); if (ret < 0) { dev_err(&icd->dev, "Couldn't activate the camera: %d\n", ret); @@ -384,6 +400,8 @@ static int soc_camera_open(struct file *file) esfmt: ici->ops->remove(icd); eiciadd: + soc_camera_free_user_formats(icd); +eiufmt: icd->use_count--; mutex_unlock(&icd->video_lock); module_put(ici->ops->owner); @@ -403,8 +421,10 @@ static int soc_camera_close(struct file *file) mutex_lock(&icd->video_lock); icd->use_count--; - if (!icd->use_count) + if (!icd->use_count) { ici->ops->remove(icd); + soc_camera_free_user_formats(icd); + } mutex_unlock(&icd->video_lock); @@ -765,29 +785,6 @@ static int soc_camera_s_register(struct file *file, void *fh, } #endif -static int device_register_link(struct soc_camera_device *icd) -{ - int ret = dev_set_name(&icd->dev, "%u-%u", icd->iface, icd->devnum); - - if (!ret) - ret = device_register(&icd->dev); - - if (ret < 0) { - /* Prevent calling device_unregister() */ - icd->dev.parent = NULL; - dev_err(&icd->dev, "Cannot register device: %d\n", ret); - /* Even if probe() was unsuccessful for all registered drivers, - * device_register() returns 0, and we add the link, just to - * document this camera's control device */ - } else if (icd->control) - /* Have to sysfs_remove_link() before device_unregister()? */ - if (sysfs_create_link(&icd->dev.kobj, &icd->control->kobj, - "control")) - dev_warn(&icd->dev, - "Failed creating the control symlink\n"); - return ret; -} - /* So far this function cannot fail */ static void scan_add_host(struct soc_camera_host *ici) { @@ -797,106 +794,124 @@ static void scan_add_host(struct soc_camera_host *ici) list_for_each_entry(icd, &devices, list) { if (icd->iface == ici->nr) { + int ret; icd->dev.parent = ici->dev; - device_register_link(icd); + dev_set_name(&icd->dev, "%u-%u", icd->iface, + icd->devnum); + ret = device_register(&icd->dev); + if (ret < 0) { + icd->dev.parent = NULL; + dev_err(&icd->dev, + "Cannot register device: %d\n", ret); + } } } mutex_unlock(&list_lock); } -/* return: 0 if no match found or a match found and - * device_register() successful, error code otherwise */ -static int scan_add_device(struct soc_camera_device *icd) +#ifdef CONFIG_I2C_BOARDINFO +static int soc_camera_init_i2c(struct soc_camera_device *icd, + struct soc_camera_link *icl) { - struct soc_camera_host *ici; - int ret = 0; + struct i2c_client *client; + struct i2c_adapter *adap = i2c_get_adapter(icl->i2c_adapter_id); + int ret; - mutex_lock(&list_lock); + if (!adap) { + ret = -ENODEV; + dev_err(&icd->dev, "Cannot get I2C adapter #%d. No driver?\n", + icl->i2c_adapter_id); + goto ei2cga; + } - list_add_tail(&icd->list, &devices); + icl->board_info->platform_data = icd; - /* Watch out for class_for_each_device / class_find_device API by - * Dave Young */ - list_for_each_entry(ici, &hosts, list) { - if (icd->iface == ici->nr) { - ret = 1; - icd->dev.parent = ici->dev; - break; - } + client = i2c_new_device(adap, icl->board_info); + if (!client) { + ret = -ENOMEM; + goto ei2cnd; } - mutex_unlock(&list_lock); - - if (ret) - ret = device_register_link(icd); + /* + * We set icd drvdata at two locations - here and in + * soc_camera_video_start(). Depending on the module loading / + * initialisation order one of these locations will be entered first + */ + /* Use to_i2c_client(dev) to recover the i2c client */ + dev_set_drvdata(&icd->dev, &client->dev); + return 0; +ei2cnd: + i2c_put_adapter(adap); +ei2cga: return ret; } +static void soc_camera_free_i2c(struct soc_camera_device *icd) +{ + struct i2c_client *client = + to_i2c_client(to_soc_camera_control(icd)); + dev_set_drvdata(&icd->dev, NULL); + i2c_unregister_device(client); + i2c_put_adapter(client->adapter); +} +#else +#define soc_camera_init_i2c(icd, icl) (-ENODEV) +#define soc_camera_free_i2c(icd) do {} while (0) +#endif + +static int video_dev_create(struct soc_camera_device *icd); +/* Called during host-driver probe */ static int soc_camera_probe(struct device *dev) { struct soc_camera_device *icd = to_soc_camera_dev(dev); - struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); + struct soc_camera_link *icl = to_soc_camera_link(icd); int ret; - /* - * Possible race scenario: - * modprobe triggers __func__ - * at this moment respective gets rmmod'ed - * to protect take module references. - */ + dev_info(dev, "Probing %s\n", dev_name(dev)); - if (!try_module_get(icd->ops->owner)) { - dev_err(&icd->dev, "Couldn't lock sensor driver.\n"); - ret = -EINVAL; - goto emgd; - } + ret = video_dev_create(icd); + if (ret < 0) + goto evdc; - if (!try_module_get(ici->ops->owner)) { - dev_err(&icd->dev, "Couldn't lock capture bus driver.\n"); + /* Non-i2c cameras, e.g., soc_camera_platform, have no board_info */ + if (icl->board_info) { + ret = soc_camera_init_i2c(icd, icl); + if (ret < 0) + goto eadddev; + } else if (!icl->add_device || !icl->del_device) { ret = -EINVAL; - goto emgi; + goto eadddev; + } else { + ret = icl->add_device(icl, &icd->dev); + if (ret < 0) + goto eadddev; } - mutex_lock(&icd->video_lock); - - /* We only call ->add() here to activate and probe the camera. - * We shall ->remove() and deactivate it immediately afterwards. */ - ret = ici->ops->add(icd); - if (ret < 0) - goto eiadd; - - ret = icd->ops->probe(icd); - if (ret >= 0) { - const struct v4l2_queryctrl *qctrl; + ret = video_register_device(icd->vdev, VFL_TYPE_GRABBER, icd->vdev->minor); + if (ret < 0) { + dev_err(&icd->dev, "video_register_device failed: %d\n", ret); + goto evidregd; + } - qctrl = soc_camera_find_qctrl(icd->ops, V4L2_CID_GAIN); - icd->gain = qctrl ? qctrl->default_value : (unsigned short)~0; - qctrl = soc_camera_find_qctrl(icd->ops, V4L2_CID_EXPOSURE); - icd->exposure = qctrl ? qctrl->default_value : - (unsigned short)~0; + /* Do we have to sysfs_remove_link() before device_unregister()? */ + if (to_soc_camera_control(icd) && + sysfs_create_link(&icd->dev.kobj, &to_soc_camera_control(icd)->kobj, + "control")) + dev_warn(&icd->dev, "Failed creating the control symlink\n"); - ret = soc_camera_init_user_formats(icd); - if (ret < 0) { - if (icd->ops->remove) - icd->ops->remove(icd); - goto eiufmt; - } - icd->height = DEFAULT_HEIGHT; - icd->width = DEFAULT_WIDTH; - icd->field = V4L2_FIELD_ANY; - } + return 0; -eiufmt: - ici->ops->remove(icd); -eiadd: - mutex_unlock(&icd->video_lock); - module_put(ici->ops->owner); -emgi: - module_put(icd->ops->owner); -emgd: +evidregd: + if (icl->board_info) + soc_camera_free_i2c(icd); + else + icl->del_device(icl); +eadddev: + video_device_release(icd->vdev); +evdc: return ret; } @@ -905,13 +920,22 @@ emgd: static int soc_camera_remove(struct device *dev) { struct soc_camera_device *icd = to_soc_camera_dev(dev); + struct soc_camera_link *icl = to_soc_camera_link(icd); + struct video_device *vdev = icd->vdev; - mutex_lock(&icd->video_lock); - if (icd->ops->remove) - icd->ops->remove(icd); - mutex_unlock(&icd->video_lock); + BUG_ON(!dev->parent); - soc_camera_free_user_formats(icd); + if (vdev) { + mutex_lock(&icd->video_lock); + video_unregister_device(vdev); + icd->vdev = NULL; + mutex_unlock(&icd->video_lock); + } + + if (icl->board_info) + soc_camera_free_i2c(icd); + else + icl->del_device(icl); return 0; } @@ -1006,10 +1030,14 @@ void soc_camera_host_unregister(struct soc_camera_host *ici) list_for_each_entry(icd, &devices, list) { if (icd->dev.parent == ici->dev) { + /* The bus->remove will be called */ device_unregister(&icd->dev); /* Not before device_unregister(), .remove * needs parent to call ici->ops->remove() */ icd->dev.parent = NULL; + + /* If the host module is loaded again, device_register() + * would complain "already initialised" */ memset(&icd->dev.kobj, 0, sizeof(icd->dev.kobj)); } } @@ -1021,26 +1049,14 @@ void soc_camera_host_unregister(struct soc_camera_host *ici) EXPORT_SYMBOL(soc_camera_host_unregister); /* Image capture device */ -int soc_camera_device_register(struct soc_camera_device *icd) +static int soc_camera_device_register(struct soc_camera_device *icd) { struct soc_camera_device *ix; int num = -1, i; - if (!icd || !icd->ops || - !icd->ops->probe || - !icd->ops->init || - !icd->ops->release || - !icd->ops->start_capture || - !icd->ops->stop_capture || - !icd->ops->set_crop || - !icd->ops->set_fmt || - !icd->ops->try_fmt || - !icd->ops->query_bus_param || - !icd->ops->set_bus_param) - return -EINVAL; - for (i = 0; i < 256 && num < 0; i++) { num = i; + /* Check if this index is available on this interface */ list_for_each_entry(ix, &devices, list) { if (ix->iface == icd->iface && ix->devnum == i) { num = -1; @@ -1062,21 +1078,15 @@ int soc_camera_device_register(struct soc_camera_device *icd) icd->host_priv = NULL; mutex_init(&icd->video_lock); - return scan_add_device(icd); + list_add_tail(&icd->list, &devices); + + return 0; } -EXPORT_SYMBOL(soc_camera_device_register); -void soc_camera_device_unregister(struct soc_camera_device *icd) +static void soc_camera_device_unregister(struct soc_camera_device *icd) { - mutex_lock(&list_lock); list_del(&icd->list); - - /* The bus->remove will be eventually called */ - if (icd->dev.parent) - device_unregister(&icd->dev); - mutex_unlock(&list_lock); } -EXPORT_SYMBOL(soc_camera_device_unregister); static const struct v4l2_ioctl_ops soc_camera_ioctl_ops = { .vidioc_querycap = soc_camera_querycap, @@ -1107,22 +1117,13 @@ static const struct v4l2_ioctl_ops soc_camera_ioctl_ops = { #endif }; -/* - * Usually called from the struct soc_camera_ops .probe() method, i.e., from - * soc_camera_probe() above with .video_lock held - */ -int soc_camera_video_start(struct soc_camera_device *icd) +static int video_dev_create(struct soc_camera_device *icd) { struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); - int err = -ENOMEM; - struct video_device *vdev; + struct video_device *vdev = video_device_alloc(); - if (!icd->dev.parent) - return -ENODEV; - - vdev = video_device_alloc(); if (!vdev) - goto evidallocd; + return -ENOMEM; dev_dbg(ici->dev, "Allocated video_device %p\n", vdev); strlcpy(vdev->name, ici->drv_name, sizeof(vdev->name)); @@ -1133,118 +1134,110 @@ int soc_camera_video_start(struct soc_camera_device *icd) vdev->ioctl_ops = &soc_camera_ioctl_ops; vdev->release = video_device_release; vdev->minor = -1; - vdev->tvnorms = V4L2_STD_UNKNOWN, + vdev->tvnorms = V4L2_STD_UNKNOWN; - err = video_register_device(vdev, VFL_TYPE_GRABBER, vdev->minor); - if (err < 0) { - dev_err(vdev->parent, "video_register_device failed\n"); - goto evidregd; - } icd->vdev = vdev; return 0; +} -evidregd: - video_device_release(vdev); -evidallocd: - return err; +/* + * Usually called from the struct soc_camera_ops .probe() method, i.e., from + * soc_camera_probe() above with .video_lock held + */ +int soc_camera_video_start(struct soc_camera_device *icd, struct device *dev) +{ + struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); + const struct v4l2_queryctrl *qctrl; + + if (!icd->dev.parent) + return -ENODEV; + + if (!icd->ops || + !icd->ops->init || + !icd->ops->release || + !icd->ops->start_capture || + !icd->ops->stop_capture || + !icd->ops->set_fmt || + !icd->ops->try_fmt || + !icd->ops->query_bus_param || + !icd->ops->set_bus_param) + return -EINVAL; + + /* See comment in soc_camera_probe() */ + dev_set_drvdata(&icd->dev, dev); + + qctrl = soc_camera_find_qctrl(icd->ops, V4L2_CID_GAIN); + icd->gain = qctrl ? qctrl->default_value : (unsigned short)~0; + qctrl = soc_camera_find_qctrl(icd->ops, V4L2_CID_EXPOSURE); + icd->exposure = qctrl ? qctrl->default_value : (unsigned short)~0; + + return ici->ops->add(icd); } EXPORT_SYMBOL(soc_camera_video_start); /* Called from client .remove() methods with .video_lock held */ void soc_camera_video_stop(struct soc_camera_device *icd) { - struct video_device *vdev = icd->vdev; + struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); dev_dbg(&icd->dev, "%s\n", __func__); - if (!icd->dev.parent || !vdev) - return; - - video_unregister_device(vdev); - icd->vdev = NULL; + ici->ops->remove(icd); } EXPORT_SYMBOL(soc_camera_video_stop); -#ifdef CONFIG_I2C_BOARDINFO -static int soc_camera_init_i2c(struct platform_device *pdev, - struct soc_camera_link *icl) +static int __devinit soc_camera_pdrv_probe(struct platform_device *pdev) { - struct i2c_client *client; - struct i2c_adapter *adap = i2c_get_adapter(icl->i2c_adapter_id); + struct soc_camera_link *icl = pdev->dev.platform_data; + struct soc_camera_device *icd; int ret; - if (!adap) { - ret = -ENODEV; - dev_err(&pdev->dev, "Cannot get adapter #%d. No driver?\n", - icl->i2c_adapter_id); - goto ei2cga; - } + if (!icl) + return -EINVAL; - icl->board_info->platform_data = icl; - client = i2c_new_device(adap, icl->board_info); - if (!client) { - ret = -ENOMEM; - goto ei2cnd; - } + icd = kzalloc(sizeof(*icd), GFP_KERNEL); + if (!icd) + return -ENOMEM; - platform_set_drvdata(pdev, client); + icd->iface = icl->bus_id; + platform_set_drvdata(pdev, icd); + icd->dev.platform_data = icl; - return 0; -ei2cnd: - i2c_put_adapter(adap); -ei2cga: - return ret; -} + ret = soc_camera_device_register(icd); + if (ret < 0) + goto escdevreg; -static void soc_camera_free_i2c(struct platform_device *pdev) -{ - struct i2c_client *client = platform_get_drvdata(pdev); + return 0; - if (!client) - return; +escdevreg: + kfree(icd); - i2c_unregister_device(client); - i2c_put_adapter(client->adapter); + return ret; } -#else -#define soc_camera_init_i2c(d, icl) (-ENODEV) -#define soc_camera_free_i2c(d) do {} while (0) -#endif -static int __devinit soc_camera_pdrv_probe(struct platform_device *pdev) +/* Only called on rmmod for each platform device, since they are not + * hot-pluggable. Now we know, that all our users - hosts and devices have + * been unloaded already */ +static int __devexit soc_camera_pdrv_remove(struct platform_device *pdev) { - struct soc_camera_link *icl = pdev->dev.platform_data; + struct soc_camera_device *icd = platform_get_drvdata(pdev); - if (!icl) + if (!icd) return -EINVAL; - if (icl->board_info) - return soc_camera_init_i2c(pdev, icl); - else if (!icl->add_device || !icl->del_device) - return -EINVAL; + soc_camera_device_unregister(icd); - /* &pdev->dev will become &icd->dev */ - return icl->add_device(icl, &pdev->dev); -} + kfree(icd); -static int __devexit soc_camera_pdrv_remove(struct platform_device *pdev) -{ - struct soc_camera_link *icl = pdev->dev.platform_data; - - if (icl->board_info) - soc_camera_free_i2c(pdev); - else - icl->del_device(icl); return 0; } static struct platform_driver __refdata soc_camera_pdrv = { - .probe = soc_camera_pdrv_probe, - .remove = __devexit_p(soc_camera_pdrv_remove), - .driver = { - .name = "soc-camera-pdrv", - .owner = THIS_MODULE, + .remove = __devexit_p(soc_camera_pdrv_remove), + .driver = { + .name = "soc-camera-pdrv", + .owner = THIS_MODULE, }, }; @@ -1257,7 +1250,7 @@ static int __init soc_camera_init(void) if (ret) goto edrvr; - ret = platform_driver_register(&soc_camera_pdrv); + ret = platform_driver_probe(&soc_camera_pdrv, soc_camera_pdrv_probe); if (ret) goto epdr; diff --git a/linux/drivers/media/video/soc_camera_platform.c b/linux/drivers/media/video/soc_camera_platform.c index c48676356..d84c134f8 100644 --- a/linux/drivers/media/video/soc_camera_platform.c +++ b/linux/drivers/media/video/soc_camera_platform.c @@ -21,35 +21,32 @@ #include struct soc_camera_platform_priv { - struct soc_camera_platform_info *info; - struct soc_camera_device icd; struct soc_camera_data_format format; }; static struct soc_camera_platform_info * soc_camera_platform_get_info(struct soc_camera_device *icd) { - struct soc_camera_platform_priv *priv; - priv = container_of(icd, struct soc_camera_platform_priv, icd); - return priv->info; + struct platform_device *pdev = to_platform_device(dev_get_drvdata(&icd->dev)); + return pdev->dev.platform_data; } static int soc_camera_platform_init(struct soc_camera_device *icd) { - struct soc_camera_platform_info *p = soc_camera_platform_get_info(icd); + struct soc_camera_link *icl = to_soc_camera_link(icd); - if (p->power) - p->power(1); + if (icl->power) + icl->power(dev_get_drvdata(&icd->dev), 1); return 0; } static int soc_camera_platform_release(struct soc_camera_device *icd) { - struct soc_camera_platform_info *p = soc_camera_platform_get_info(icd); + struct soc_camera_link *icl = to_soc_camera_link(icd); - if (p->power) - p->power(0); + if (icl->power) + icl->power(dev_get_drvdata(&icd->dev), 0); return 0; } @@ -102,31 +99,29 @@ static int soc_camera_platform_try_fmt(struct soc_camera_device *icd, return 0; } -static int soc_camera_platform_video_probe(struct soc_camera_device *icd) +static int soc_camera_platform_video_probe(struct soc_camera_device *icd, + struct platform_device *pdev) { - struct soc_camera_platform_priv *priv; - priv = container_of(icd, struct soc_camera_platform_priv, icd); + struct soc_camera_platform_priv *priv = platform_get_drvdata(pdev); + struct soc_camera_platform_info *p = pdev->dev.platform_data; + int ret; - priv->format.name = priv->info->format_name; - priv->format.depth = priv->info->format_depth; - priv->format.fourcc = priv->info->format.pixelformat; - priv->format.colorspace = priv->info->format.colorspace; + priv->format.name = p->format_name; + priv->format.depth = p->format_depth; + priv->format.fourcc = p->format.pixelformat; + priv->format.colorspace = p->format.colorspace; icd->formats = &priv->format; icd->num_formats = 1; - return soc_camera_video_start(icd); -} - -static void soc_camera_platform_video_remove(struct soc_camera_device *icd) -{ + /* ..._video_start() does dev_set_drvdata(&icd->dev, &pdev->dev) */ + ret = soc_camera_video_start(icd, &pdev->dev); soc_camera_video_stop(icd); + return ret; } static struct soc_camera_ops soc_camera_platform_ops = { .owner = THIS_MODULE, - .probe = soc_camera_platform_video_probe, - .remove = soc_camera_platform_video_remove, .init = soc_camera_platform_init, .release = soc_camera_platform_release, .start_capture = soc_camera_platform_start_capture, @@ -141,11 +136,10 @@ static struct soc_camera_ops soc_camera_platform_ops = { static int soc_camera_platform_probe(struct platform_device *pdev) { struct soc_camera_platform_priv *priv; - struct soc_camera_platform_info *p; + struct soc_camera_platform_info *p = pdev->dev.platform_data; struct soc_camera_device *icd; int ret; - p = pdev->dev.platform_data; if (!p) return -EINVAL; @@ -153,31 +147,40 @@ static int soc_camera_platform_probe(struct platform_device *pdev) if (!priv) return -ENOMEM; - priv->info = p; platform_set_drvdata(pdev, priv); - icd = &priv->icd; + icd = to_soc_camera_dev(p->dev); + if (!icd) + goto enoicd; + icd->ops = &soc_camera_platform_ops; - icd->control = &pdev->dev; + dev_set_drvdata(&icd->dev, &pdev->dev); icd->width_min = 0; - icd->width_max = priv->info->format.width; + icd->width_max = p->format.width; icd->height_min = 0; - icd->height_max = priv->info->format.height; + icd->height_max = p->format.height; icd->y_skip_top = 0; - icd->iface = priv->info->iface; - ret = soc_camera_device_register(icd); - if (ret) + ret = soc_camera_platform_video_probe(icd, pdev); + if (ret) { + icd->ops = NULL; kfree(priv); + } return ret; + +enoicd: + kfree(priv); + return -EINVAL; } static int soc_camera_platform_remove(struct platform_device *pdev) { struct soc_camera_platform_priv *priv = platform_get_drvdata(pdev); + struct soc_camera_platform_info *p = pdev->dev.platform_data; + struct soc_camera_device *icd = to_soc_camera_dev(p->dev); - soc_camera_device_unregister(&priv->icd); + icd->ops = NULL; kfree(priv); return 0; } @@ -206,3 +209,4 @@ module_exit(soc_camera_platform_module_exit); MODULE_DESCRIPTION("SoC Camera Platform driver"); MODULE_AUTHOR("Magnus Damm"); MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:soc_camera_platform"); diff --git a/linux/drivers/media/video/tw9910.c b/linux/drivers/media/video/tw9910.c index f75787594..432dd3edc 100644 --- a/linux/drivers/media/video/tw9910.c +++ b/linux/drivers/media/video/tw9910.c @@ -224,8 +224,6 @@ struct tw9910_hsync_ctrl { struct tw9910_priv { struct tw9910_video_info *info; - struct i2c_client *client; - struct soc_camera_device icd; const struct tw9910_scale_ctrl *scale; }; @@ -511,35 +509,38 @@ tw9910_select_norm(struct soc_camera_device *icd, u32 width, u32 height) */ static int tw9910_init(struct soc_camera_device *icd) { - struct tw9910_priv *priv = container_of(icd, struct tw9910_priv, icd); + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct soc_camera_link *icl = to_soc_camera_link(icd); int ret = 0; - if (priv->info->link.power) { - ret = priv->info->link.power(&priv->client->dev, 1); + if (icl->power) { + ret = icl->power(&client->dev, 1); if (ret < 0) return ret; } - if (priv->info->link.reset) - ret = priv->info->link.reset(&priv->client->dev); + if (icl->reset) + ret = icl->reset(&client->dev); return ret; } static int tw9910_release(struct soc_camera_device *icd) { - struct tw9910_priv *priv = container_of(icd, struct tw9910_priv, icd); + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct soc_camera_link *icl = to_soc_camera_link(icd); int ret = 0; - if (priv->info->link.power) - ret = priv->info->link.power(&priv->client->dev, 0); + if (icl->power) + ret = icl->power(&client->dev, 0); return ret; } static int tw9910_start_capture(struct soc_camera_device *icd) { - struct tw9910_priv *priv = container_of(icd, struct tw9910_priv, icd); + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct tw9910_priv *priv = i2c_get_clientdata(client); if (!priv->scale) { dev_err(&icd->dev, "norm select error\n"); @@ -567,8 +568,9 @@ static int tw9910_set_bus_param(struct soc_camera_device *icd, static unsigned long tw9910_query_bus_param(struct soc_camera_device *icd) { - struct tw9910_priv *priv = container_of(icd, struct tw9910_priv, icd); - struct soc_camera_link *icl = priv->client->dev.platform_data; + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct tw9910_priv *priv = i2c_get_clientdata(client); + struct soc_camera_link *icl = to_soc_camera_link(icd); unsigned long flags = SOCAM_PCLK_SAMPLE_RISING | SOCAM_MASTER | SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_DATA_ACTIVE_HIGH | priv->info->buswidth; @@ -610,13 +612,13 @@ static int tw9910_enum_input(struct soc_camera_device *icd, static int tw9910_get_register(struct soc_camera_device *icd, struct v4l2_dbg_register *reg) { - struct tw9910_priv *priv = container_of(icd, struct tw9910_priv, icd); + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); int ret; if (reg->reg > 0xff) return -EINVAL; - ret = i2c_smbus_read_byte_data(priv->client, reg->reg); + ret = i2c_smbus_read_byte_data(client, reg->reg); if (ret < 0) return ret; @@ -631,20 +633,21 @@ static int tw9910_get_register(struct soc_camera_device *icd, static int tw9910_set_register(struct soc_camera_device *icd, struct v4l2_dbg_register *reg) { - struct tw9910_priv *priv = container_of(icd, struct tw9910_priv, icd); + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); if (reg->reg > 0xff || reg->val > 0xff) return -EINVAL; - return i2c_smbus_write_byte_data(priv->client, reg->reg, reg->val); + return i2c_smbus_write_byte_data(client, reg->reg, reg->val); } #endif static int tw9910_set_crop(struct soc_camera_device *icd, struct v4l2_rect *rect) { - struct tw9910_priv *priv = container_of(icd, struct tw9910_priv, icd); + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct tw9910_priv *priv = i2c_get_clientdata(client); int ret = -EINVAL; u8 val; @@ -658,8 +661,8 @@ static int tw9910_set_crop(struct soc_camera_device *icd, /* * reset hardware */ - tw9910_reset(priv->client); - ret = tw9910_write_array(priv->client, tw9910_default_regs); + tw9910_reset(client); + ret = tw9910_write_array(client, tw9910_default_regs); if (ret < 0) goto tw9910_set_fmt_error; @@ -670,7 +673,7 @@ static int tw9910_set_crop(struct soc_camera_device *icd, if (SOCAM_DATAWIDTH_16 == priv->info->buswidth) val = LEN; - ret = tw9910_mask_set(priv->client, OPFORM, LEN, val); + ret = tw9910_mask_set(client, OPFORM, LEN, val); if (ret < 0) goto tw9910_set_fmt_error; @@ -698,28 +701,28 @@ static int tw9910_set_crop(struct soc_camera_device *icd, val = 0; } - ret = tw9910_mask_set(priv->client, VBICNTL, RTSEL_MASK, val); + ret = tw9910_mask_set(client, VBICNTL, RTSEL_MASK, val); if (ret < 0) goto tw9910_set_fmt_error; /* * set scale */ - ret = tw9910_set_scale(priv->client, priv->scale); + ret = tw9910_set_scale(client, priv->scale); if (ret < 0) goto tw9910_set_fmt_error; /* * set cropping */ - ret = tw9910_set_cropping(priv->client, &tw9910_cropping_ctrl); + ret = tw9910_set_cropping(client, &tw9910_cropping_ctrl); if (ret < 0) goto tw9910_set_fmt_error; /* * set hsync */ - ret = tw9910_set_hsync(priv->client, &tw9910_hsync_ctrl); + ret = tw9910_set_hsync(client, &tw9910_hsync_ctrl); if (ret < 0) goto tw9910_set_fmt_error; @@ -727,7 +730,7 @@ static int tw9910_set_crop(struct soc_camera_device *icd, tw9910_set_fmt_error: - tw9910_reset(priv->client); + tw9910_reset(client); priv->scale = NULL; return ret; @@ -784,9 +787,10 @@ static int tw9910_try_fmt(struct soc_camera_device *icd, return 0; } -static int tw9910_video_probe(struct soc_camera_device *icd) +static int tw9910_video_probe(struct soc_camera_device *icd, + struct i2c_client *client) { - struct tw9910_priv *priv = container_of(icd, struct tw9910_priv, icd); + struct tw9910_priv *priv = i2c_get_clientdata(client); s32 val; int ret; @@ -810,10 +814,18 @@ static int tw9910_video_probe(struct soc_camera_device *icd) icd->formats = tw9910_color_fmt; icd->num_formats = ARRAY_SIZE(tw9910_color_fmt); + /* Switch master clock on */ + ret = soc_camera_video_start(icd, &client->dev); + if (ret) + return ret; + /* * check and show Product ID */ - val = i2c_smbus_read_byte_data(priv->client, ID); + val = i2c_smbus_read_byte_data(client, ID); + + soc_camera_video_stop(icd); + if (0x0B != GET_ID(val) || 0x00 != GET_ReV(val)) { dev_err(&icd->dev, @@ -824,25 +836,14 @@ static int tw9910_video_probe(struct soc_camera_device *icd) dev_info(&icd->dev, "tw9910 Product ID %0x:%0x\n", GET_ID(val), GET_ReV(val)); - ret = soc_camera_video_start(icd); - if (ret < 0) - return ret; - icd->vdev->tvnorms = V4L2_STD_NTSC | V4L2_STD_PAL; icd->vdev->current_norm = V4L2_STD_NTSC; return ret; } -static void tw9910_video_remove(struct soc_camera_device *icd) -{ - soc_camera_video_stop(icd); -} - static struct soc_camera_ops tw9910_ops = { .owner = THIS_MODULE, - .probe = tw9910_video_probe, - .remove = tw9910_video_remove, .init = tw9910_init, .release = tw9910_release, .start_capture = tw9910_start_capture, @@ -875,18 +876,25 @@ static int tw9910_probe(struct i2c_client *client, { struct tw9910_priv *priv; struct tw9910_video_info *info; - struct soc_camera_device *icd; + struct soc_camera_device *icd = client->dev.platform_data; + struct i2c_adapter *adapter = + to_i2c_adapter(client->dev.parent); + struct soc_camera_link *icl; const struct tw9910_scale_ctrl *scale; int i, ret; - if (!client->dev.platform_data) + if (!icd) { + dev_err(&client->dev, "TW9910: missing soc-camera data!\n"); return -EINVAL; + } - info = container_of(client->dev.platform_data, - struct tw9910_video_info, link); + icl = to_soc_camera_link(icd); + if (!icl) + return -EINVAL; - if (!i2c_check_functionality(to_i2c_adapter(client->dev.parent), - I2C_FUNC_SMBUS_BYTE_DATA)) { + info = container_of(icl, struct tw9910_video_info, link); + + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { dev_err(&client->dev, "I2C-Adapter doesn't support " "I2C_FUNC_SMBUS_BYTE_DATA\n"); @@ -898,12 +906,9 @@ static int tw9910_probe(struct i2c_client *client, return -ENOMEM; priv->info = info; - priv->client = client; i2c_set_clientdata(client, priv); - icd = &priv->icd; icd->ops = &tw9910_ops; - icd->control = &client->dev; icd->iface = info->link.bus_id; /* @@ -929,9 +934,9 @@ static int tw9910_probe(struct i2c_client *client, icd->height_min = min(scale[i].height, icd->height_min); } - ret = soc_camera_device_register(icd); - + ret = tw9910_video_probe(icd, client); if (ret) { + icd->ops = NULL; i2c_set_clientdata(client, NULL); kfree(priv); } @@ -942,8 +947,9 @@ static int tw9910_probe(struct i2c_client *client, static int tw9910_remove(struct i2c_client *client) { struct tw9910_priv *priv = i2c_get_clientdata(client); + struct soc_camera_device *icd = client->dev.platform_data; - soc_camera_device_unregister(&priv->icd); + icd->ops = NULL; i2c_set_clientdata(client, NULL); kfree(priv); return 0; -- cgit v1.2.3 From a9c698e163df3064b2a003395d6115985d8a4f78 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Tue, 25 Aug 2009 16:43:33 +0200 Subject: soc-camera: (partially) convert to v4l2-(sub)dev API From: Guennadi Liakhovetski Convert the soc-camera framework to use the v4l2-(sub)dev API. Start using v4l2-subdev operations. Only a part of the interface between the soc_camera core, soc_camera host drivers on one side and soc_camera device drivers on the other side is replaced so far. The rest of the interface will be replaced in incremental steps, and will require extensions and, possibly, modifications to the v4l2-subdev code. Signed-off-by: Guennadi Liakhovetski Priority: low --- linux/drivers/media/video/mt9m001.c | 157 +++++------- linux/drivers/media/video/mt9m111.c | 309 ++++++++++------------- linux/drivers/media/video/mt9t031.c | 173 ++++++------- linux/drivers/media/video/mt9v022.c | 167 +++++------- linux/drivers/media/video/mx1_camera.c | 31 +-- linux/drivers/media/video/mx3_camera.c | 54 ++-- linux/drivers/media/video/ov772x.c | 169 +++++-------- linux/drivers/media/video/pxa_camera.c | 107 ++++---- linux/drivers/media/video/sh_mobile_ceu_camera.c | 45 ++-- linux/drivers/media/video/soc_camera.c | 250 ++++++++++-------- linux/drivers/media/video/soc_camera_platform.c | 115 ++++----- linux/drivers/media/video/tw9910.c | 151 +++++------ 12 files changed, 783 insertions(+), 945 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/mt9m001.c b/linux/drivers/media/video/mt9m001.c index ad308da71..45d8fad25 100644 --- a/linux/drivers/media/video/mt9m001.c +++ b/linux/drivers/media/video/mt9m001.c @@ -13,13 +13,13 @@ #include #include -#include +#include #include #include /* mt9m001 i2c address 0x5d - * The platform has to define i2c_board_info - * and call i2c_register_board_info() */ + * The platform has to define ctruct i2c_board_info objects and link to them + * from struct soc_camera_link */ /* mt9m001 selected register addresses */ #define MT9M001_CHIP_VERSION 0x00 @@ -69,10 +69,16 @@ static const struct soc_camera_data_format mt9m001_monochrome_formats[] = { }; struct mt9m001 { + struct v4l2_subdev subdev; int model; /* V4L2_IDENT_MT9M001* codes from v4l2-chip-ident.h */ unsigned char autoexposure; }; +static struct mt9m001 *to_mt9m001(const struct i2c_client *client) +{ + return container_of(i2c_get_clientdata(client), struct mt9m001, subdev); +} + static int reg_read(struct i2c_client *client, const u8 reg) { s32 data = i2c_smbus_read_word_data(client, reg); @@ -110,32 +116,18 @@ static int reg_clear(struct i2c_client *client, const u8 reg, static int mt9m001_init(struct soc_camera_device *icd) { struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); - struct soc_camera_link *icl = to_soc_camera_link(icd); int ret; dev_dbg(&icd->dev, "%s\n", __func__); - if (icl->power) { - ret = icl->power(&client->dev, 1); - if (ret < 0) { - dev_err(icd->vdev->parent, - "Platform failed to power-on the camera.\n"); - return ret; - } - } - - /* The camera could have been already on, we reset it additionally */ - if (icl->reset) - ret = icl->reset(&client->dev); - else - ret = -ENODEV; + /* + * We don't know, whether platform provides reset, + * issue a soft reset too + */ + ret = reg_write(client, MT9M001_RESET, 1); + if (!ret) + ret = reg_write(client, MT9M001_RESET, 0); - if (ret < 0) { - /* Either no platform reset, or platform reset failed */ - ret = reg_write(client, MT9M001_RESET, 1); - if (!ret) - ret = reg_write(client, MT9M001_RESET, 0); - } /* Disable chip, synchronous option update */ if (!ret) ret = reg_write(client, MT9M001_OUTPUT_CONTROL, 0); @@ -146,33 +138,19 @@ static int mt9m001_init(struct soc_camera_device *icd) static int mt9m001_release(struct soc_camera_device *icd) { struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); - struct soc_camera_link *icl = to_soc_camera_link(icd); /* Disable the chip */ reg_write(client, MT9M001_OUTPUT_CONTROL, 0); - if (icl->power) - icl->power(&client->dev, 0); - return 0; } -static int mt9m001_start_capture(struct soc_camera_device *icd) +static int mt9m001_s_stream(struct v4l2_subdev *sd, int enable) { - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct i2c_client *client = sd->priv; - /* Switch to master "normal" mode */ - if (reg_write(client, MT9M001_OUTPUT_CONTROL, 2) < 0) - return -EIO; - return 0; -} - -static int mt9m001_stop_capture(struct soc_camera_device *icd) -{ - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); - - /* Stop sensor readout */ - if (reg_write(client, MT9M001_OUTPUT_CONTROL, 0) < 0) + /* Switch to master "normal" mode or stop sensor readout */ + if (reg_write(client, MT9M001_OUTPUT_CONTROL, enable ? 2 : 0) < 0) return -EIO; return 0; } @@ -220,7 +198,7 @@ static int mt9m001_set_crop(struct soc_camera_device *icd, struct v4l2_rect *rect) { struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); - struct mt9m001 *mt9m001 = i2c_get_clientdata(client); + struct mt9m001 *mt9m001 = to_mt9m001(client); int ret; const u16 hblank = 9, vblank = 25; @@ -257,9 +235,10 @@ static int mt9m001_set_crop(struct soc_camera_device *icd, return ret; } -static int mt9m001_set_fmt(struct soc_camera_device *icd, - struct v4l2_format *f) +static int mt9m001_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) { + struct i2c_client *client = sd->priv; + struct soc_camera_device *icd = client->dev.platform_data; struct v4l2_rect rect = { .left = icd->x_current, .top = icd->y_current, @@ -271,9 +250,10 @@ static int mt9m001_set_fmt(struct soc_camera_device *icd, return mt9m001_set_crop(icd, &rect); } -static int mt9m001_try_fmt(struct soc_camera_device *icd, - struct v4l2_format *f) +static int mt9m001_try_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) { + struct i2c_client *client = sd->priv; + struct soc_camera_device *icd = client->dev.platform_data; struct v4l2_pix_format *pix = &f->fmt.pix; v4l_bound_align_image(&pix->width, 48, 1280, 1, @@ -283,11 +263,11 @@ static int mt9m001_try_fmt(struct soc_camera_device *icd, return 0; } -static int mt9m001_get_chip_id(struct soc_camera_device *icd, - struct v4l2_dbg_chip_ident *id) +static int mt9m001_g_chip_ident(struct v4l2_subdev *sd, + struct v4l2_dbg_chip_ident *id) { - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); - struct mt9m001 *mt9m001 = i2c_get_clientdata(client); + struct i2c_client *client = sd->priv; + struct mt9m001 *mt9m001 = to_mt9m001(client); if (id->match.type != V4L2_CHIP_MATCH_I2C_ADDR) return -EINVAL; @@ -302,10 +282,10 @@ static int mt9m001_get_chip_id(struct soc_camera_device *icd, } #ifdef CONFIG_VIDEO_ADV_DEBUG -static int mt9m001_get_register(struct soc_camera_device *icd, - struct v4l2_dbg_register *reg) +static int mt9m001_g_register(struct v4l2_subdev *sd, + struct v4l2_dbg_register *reg) { - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct i2c_client *client = sd->priv; if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff) return -EINVAL; @@ -322,10 +302,10 @@ static int mt9m001_get_register(struct soc_camera_device *icd, return 0; } -static int mt9m001_set_register(struct soc_camera_device *icd, - struct v4l2_dbg_register *reg) +static int mt9m001_s_register(struct v4l2_subdev *sd, + struct v4l2_dbg_register *reg) { - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct i2c_client *client = sd->priv; if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff) return -EINVAL; @@ -378,35 +358,20 @@ static const struct v4l2_queryctrl mt9m001_controls[] = { } }; -static int mt9m001_get_control(struct soc_camera_device *, struct v4l2_control *); -static int mt9m001_set_control(struct soc_camera_device *, struct v4l2_control *); - static struct soc_camera_ops mt9m001_ops = { - .owner = THIS_MODULE, .init = mt9m001_init, .release = mt9m001_release, - .start_capture = mt9m001_start_capture, - .stop_capture = mt9m001_stop_capture, .set_crop = mt9m001_set_crop, - .set_fmt = mt9m001_set_fmt, - .try_fmt = mt9m001_try_fmt, .set_bus_param = mt9m001_set_bus_param, .query_bus_param = mt9m001_query_bus_param, .controls = mt9m001_controls, .num_controls = ARRAY_SIZE(mt9m001_controls), - .get_control = mt9m001_get_control, - .set_control = mt9m001_set_control, - .get_chip_id = mt9m001_get_chip_id, -#ifdef CONFIG_VIDEO_ADV_DEBUG - .get_register = mt9m001_get_register, - .set_register = mt9m001_set_register, -#endif }; -static int mt9m001_get_control(struct soc_camera_device *icd, struct v4l2_control *ctrl) +static int mt9m001_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) { - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); - struct mt9m001 *mt9m001 = i2c_get_clientdata(client); + struct i2c_client *client = sd->priv; + struct mt9m001 *mt9m001 = to_mt9m001(client); int data; switch (ctrl->id) { @@ -423,10 +388,11 @@ static int mt9m001_get_control(struct soc_camera_device *icd, struct v4l2_contro return 0; } -static int mt9m001_set_control(struct soc_camera_device *icd, struct v4l2_control *ctrl) +static int mt9m001_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) { - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); - struct mt9m001 *mt9m001 = i2c_get_clientdata(client); + struct i2c_client *client = sd->priv; + struct mt9m001 *mt9m001 = to_mt9m001(client); + struct soc_camera_device *icd = client->dev.platform_data; const struct v4l2_queryctrl *qctrl; int data; @@ -521,10 +487,9 @@ static int mt9m001_set_control(struct soc_camera_device *icd, struct v4l2_contro static int mt9m001_video_probe(struct soc_camera_device *icd, struct i2c_client *client) { - struct mt9m001 *mt9m001 = i2c_get_clientdata(client); + struct mt9m001 *mt9m001 = to_mt9m001(client); struct soc_camera_link *icl = to_soc_camera_link(icd); s32 data; - int ret; unsigned long flags; /* We must have a parent by now. And it cannot be a wrong one. @@ -533,11 +498,6 @@ static int mt9m001_video_probe(struct soc_camera_device *icd, to_soc_camera_host(icd->dev.parent)->nr != icd->iface) return -ENODEV; - /* Switch master clock on */ - ret = soc_camera_video_start(icd, &client->dev); - if (ret) - return ret; - /* Enable the chip */ data = reg_write(client, MT9M001_CHIP_ENABLE, 1); dev_dbg(&icd->dev, "write: %d\n", data); @@ -545,8 +505,6 @@ static int mt9m001_video_probe(struct soc_camera_device *icd, /* Read out the chip version register */ data = reg_read(client, MT9M001_CHIP_VERSION); - soc_camera_video_stop(icd); - /* must be 0x8411 or 0x8421 for colour sensor and 8431 for bw */ switch (data) { case 0x8411: @@ -601,6 +559,27 @@ static void mt9m001_video_remove(struct soc_camera_device *icd) icl->free_bus(icl); } +static struct v4l2_subdev_core_ops mt9m001_subdev_core_ops = { + .g_ctrl = mt9m001_g_ctrl, + .s_ctrl = mt9m001_s_ctrl, + .g_chip_ident = mt9m001_g_chip_ident, +#ifdef CONFIG_VIDEO_ADV_DEBUG + .g_register = mt9m001_g_register, + .s_register = mt9m001_s_register, +#endif +}; + +static struct v4l2_subdev_video_ops mt9m001_subdev_video_ops = { + .s_stream = mt9m001_s_stream, + .s_fmt = mt9m001_s_fmt, + .try_fmt = mt9m001_try_fmt, +}; + +static struct v4l2_subdev_ops mt9m001_subdev_ops = { + .core = &mt9m001_subdev_core_ops, + .video = &mt9m001_subdev_video_ops, +}; + #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) static int mt9m001_probe(struct i2c_client *client, const struct i2c_device_id *did) @@ -635,7 +614,7 @@ static int mt9m001_probe(struct i2c_client *client) if (!mt9m001) return -ENOMEM; - i2c_set_clientdata(client, mt9m001); + v4l2_i2c_subdev_init(&mt9m001->subdev, client, &mt9m001_subdev_ops); /* Second stage probe - when a capture adapter is there */ icd->ops = &mt9m001_ops; @@ -664,7 +643,7 @@ static int mt9m001_probe(struct i2c_client *client) static int mt9m001_remove(struct i2c_client *client) { - struct mt9m001 *mt9m001 = i2c_get_clientdata(client); + struct mt9m001 *mt9m001 = to_mt9m001(client); struct soc_camera_device *icd = client->dev.platform_data; icd->ops = NULL; diff --git a/linux/drivers/media/video/mt9m111.c b/linux/drivers/media/video/mt9m111.c index 5c6ab7b53..4b00033c4 100644 --- a/linux/drivers/media/video/mt9m111.c +++ b/linux/drivers/media/video/mt9m111.c @@ -148,6 +148,7 @@ enum mt9m111_context { }; struct mt9m111 { + struct v4l2_subdev subdev; int model; /* V4L2_IDENT_MT9M11x* codes from v4l2-chip-ident.h */ enum mt9m111_context context; struct v4l2_rect rect; @@ -164,6 +165,11 @@ struct mt9m111 { unsigned int autowhitebalance:1; }; +static struct mt9m111 *to_mt9m111(const struct i2c_client *client) +{ + return container_of(i2c_get_clientdata(client), struct mt9m111, subdev); +} + static int reg_page_map_set(struct i2c_client *client, const u16 reg) { int ret; @@ -227,10 +233,9 @@ static int mt9m111_reg_clear(struct i2c_client *client, const u16 reg, return mt9m111_reg_write(client, reg, ret & ~data); } -static int mt9m111_set_context(struct soc_camera_device *icd, +static int mt9m111_set_context(struct i2c_client *client, enum mt9m111_context ctxt) { - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); int valB = MT9M111_CTXT_CTRL_RESTART | MT9M111_CTXT_CTRL_DEFECTCOR_B | MT9M111_CTXT_CTRL_RESIZE_B | MT9M111_CTXT_CTRL_CTRL2_B | MT9M111_CTXT_CTRL_GAMMA_B | MT9M111_CTXT_CTRL_READ_MODE_B @@ -244,11 +249,10 @@ static int mt9m111_set_context(struct soc_camera_device *icd, return reg_write(CONTEXT_CONTROL, valA); } -static int mt9m111_setup_rect(struct soc_camera_device *icd, +static int mt9m111_setup_rect(struct i2c_client *client, struct v4l2_rect *rect) { - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); - struct mt9m111 *mt9m111 = i2c_get_clientdata(client); + struct mt9m111 *mt9m111 = to_mt9m111(client); int ret, is_raw_format; int width = rect->width; int height = rect->height; @@ -290,9 +294,8 @@ static int mt9m111_setup_rect(struct soc_camera_device *icd, return ret; } -static int mt9m111_setup_pixfmt(struct soc_camera_device *icd, u16 outfmt) +static int mt9m111_setup_pixfmt(struct i2c_client *client, u16 outfmt) { - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); int ret; ret = reg_write(OUTPUT_FORMAT_CTRL2_A, outfmt); @@ -301,20 +304,19 @@ static int mt9m111_setup_pixfmt(struct soc_camera_device *icd, u16 outfmt) return ret; } -static int mt9m111_setfmt_bayer8(struct soc_camera_device *icd) +static int mt9m111_setfmt_bayer8(struct i2c_client *client) { - return mt9m111_setup_pixfmt(icd, MT9M111_OUTFMT_PROCESSED_BAYER); + return mt9m111_setup_pixfmt(client, MT9M111_OUTFMT_PROCESSED_BAYER); } -static int mt9m111_setfmt_bayer10(struct soc_camera_device *icd) +static int mt9m111_setfmt_bayer10(struct i2c_client *client) { - return mt9m111_setup_pixfmt(icd, MT9M111_OUTFMT_BYPASS_IFP); + return mt9m111_setup_pixfmt(client, MT9M111_OUTFMT_BYPASS_IFP); } -static int mt9m111_setfmt_rgb565(struct soc_camera_device *icd) +static int mt9m111_setfmt_rgb565(struct i2c_client *client) { - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); - struct mt9m111 *mt9m111 = i2c_get_clientdata(client); + struct mt9m111 *mt9m111 = to_mt9m111(client); int val = 0; if (mt9m111->swap_rgb_red_blue) @@ -323,13 +325,12 @@ static int mt9m111_setfmt_rgb565(struct soc_camera_device *icd) val |= MT9M111_OUTFMT_SWAP_RGB_EVEN; val |= MT9M111_OUTFMT_RGB | MT9M111_OUTFMT_RGB565; - return mt9m111_setup_pixfmt(icd, val); + return mt9m111_setup_pixfmt(client, val); } -static int mt9m111_setfmt_rgb555(struct soc_camera_device *icd) +static int mt9m111_setfmt_rgb555(struct i2c_client *client) { - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); - struct mt9m111 *mt9m111 = i2c_get_clientdata(client); + struct mt9m111 *mt9m111 = to_mt9m111(client); int val = 0; if (mt9m111->swap_rgb_red_blue) @@ -338,13 +339,12 @@ static int mt9m111_setfmt_rgb555(struct soc_camera_device *icd) val |= MT9M111_OUTFMT_SWAP_RGB_EVEN; val |= MT9M111_OUTFMT_RGB | MT9M111_OUTFMT_RGB555; - return mt9m111_setup_pixfmt(icd, val); + return mt9m111_setup_pixfmt(client, val); } -static int mt9m111_setfmt_yuv(struct soc_camera_device *icd) +static int mt9m111_setfmt_yuv(struct i2c_client *client) { - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); - struct mt9m111 *mt9m111 = i2c_get_clientdata(client); + struct mt9m111 *mt9m111 = to_mt9m111(client); int val = 0; if (mt9m111->swap_yuv_cb_cr) @@ -352,52 +352,22 @@ static int mt9m111_setfmt_yuv(struct soc_camera_device *icd) if (mt9m111->swap_yuv_y_chromas) val |= MT9M111_OUTFMT_SWAP_YCbCr_C_Y; - return mt9m111_setup_pixfmt(icd, val); + return mt9m111_setup_pixfmt(client, val); } -static int mt9m111_enable(struct soc_camera_device *icd) +static int mt9m111_enable(struct i2c_client *client) { - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); - struct soc_camera_link *icl = to_soc_camera_link(icd); - struct mt9m111 *mt9m111 = i2c_get_clientdata(client); + struct mt9m111 *mt9m111 = to_mt9m111(client); int ret; - if (icl->power) { - ret = icl->power(&client->dev, 1); - if (ret < 0) { - dev_err(icd->vdev->parent, - "Platform failed to power-on the camera.\n"); - return ret; - } - } - ret = reg_set(RESET, MT9M111_RESET_CHIP_ENABLE); if (!ret) mt9m111->powered = 1; return ret; } -static int mt9m111_disable(struct soc_camera_device *icd) -{ - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); - struct soc_camera_link *icl = to_soc_camera_link(icd); - struct mt9m111 *mt9m111 = i2c_get_clientdata(client); - int ret; - - ret = reg_clear(RESET, MT9M111_RESET_CHIP_ENABLE); - if (!ret) - mt9m111->powered = 0; - - if (icl->power) - icl->power(&client->dev, 0); - - return ret; -} - -static int mt9m111_reset(struct soc_camera_device *icd) +static int mt9m111_reset(struct i2c_client *client) { - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); - struct soc_camera_link *icl = to_soc_camera_link(icd); int ret; ret = reg_set(RESET, MT9M111_RESET_RESET_MODE); @@ -407,22 +377,9 @@ static int mt9m111_reset(struct soc_camera_device *icd) ret = reg_clear(RESET, MT9M111_RESET_RESET_MODE | MT9M111_RESET_RESET_SOC); - if (icl->reset) - icl->reset(&client->dev); - return ret; } -static int mt9m111_start_capture(struct soc_camera_device *icd) -{ - return 0; -} - -static int mt9m111_stop_capture(struct soc_camera_device *icd) -{ - return 0; -} - static unsigned long mt9m111_query_bus_param(struct soc_camera_device *icd) { struct soc_camera_link *icl = to_soc_camera_link(icd); @@ -442,60 +399,59 @@ static int mt9m111_set_crop(struct soc_camera_device *icd, struct v4l2_rect *rect) { struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); - struct mt9m111 *mt9m111 = i2c_get_clientdata(client); + struct mt9m111 *mt9m111 = to_mt9m111(client); int ret; dev_dbg(&icd->dev, "%s left=%d, top=%d, width=%d, height=%d\n", __func__, rect->left, rect->top, rect->width, rect->height); - ret = mt9m111_setup_rect(icd, rect); + ret = mt9m111_setup_rect(client, rect); if (!ret) mt9m111->rect = *rect; return ret; } -static int mt9m111_set_pixfmt(struct soc_camera_device *icd, u32 pixfmt) +static int mt9m111_set_pixfmt(struct i2c_client *client, u32 pixfmt) { - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); - struct mt9m111 *mt9m111 = i2c_get_clientdata(client); + struct mt9m111 *mt9m111 = to_mt9m111(client); int ret; switch (pixfmt) { case V4L2_PIX_FMT_SBGGR8: - ret = mt9m111_setfmt_bayer8(icd); + ret = mt9m111_setfmt_bayer8(client); break; case V4L2_PIX_FMT_SBGGR16: - ret = mt9m111_setfmt_bayer10(icd); + ret = mt9m111_setfmt_bayer10(client); break; case V4L2_PIX_FMT_RGB555: - ret = mt9m111_setfmt_rgb555(icd); + ret = mt9m111_setfmt_rgb555(client); break; case V4L2_PIX_FMT_RGB565: - ret = mt9m111_setfmt_rgb565(icd); + ret = mt9m111_setfmt_rgb565(client); break; case V4L2_PIX_FMT_UYVY: mt9m111->swap_yuv_y_chromas = 0; mt9m111->swap_yuv_cb_cr = 0; - ret = mt9m111_setfmt_yuv(icd); + ret = mt9m111_setfmt_yuv(client); break; case V4L2_PIX_FMT_VYUY: mt9m111->swap_yuv_y_chromas = 0; mt9m111->swap_yuv_cb_cr = 1; - ret = mt9m111_setfmt_yuv(icd); + ret = mt9m111_setfmt_yuv(client); break; case V4L2_PIX_FMT_YUYV: mt9m111->swap_yuv_y_chromas = 1; mt9m111->swap_yuv_cb_cr = 0; - ret = mt9m111_setfmt_yuv(icd); + ret = mt9m111_setfmt_yuv(client); break; case V4L2_PIX_FMT_YVYU: mt9m111->swap_yuv_y_chromas = 1; mt9m111->swap_yuv_cb_cr = 1; - ret = mt9m111_setfmt_yuv(icd); + ret = mt9m111_setfmt_yuv(client); break; default: - dev_err(&icd->dev, "Pixel format not handled : %x\n", pixfmt); + dev_err(&client->dev, "Pixel format not handled : %x\n", pixfmt); ret = -EINVAL; } @@ -505,11 +461,10 @@ static int mt9m111_set_pixfmt(struct soc_camera_device *icd, u32 pixfmt) return ret; } -static int mt9m111_set_fmt(struct soc_camera_device *icd, - struct v4l2_format *f) +static int mt9m111_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) { - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); - struct mt9m111 *mt9m111 = i2c_get_clientdata(client); + struct i2c_client *client = sd->priv; + struct mt9m111 *mt9m111 = to_mt9m111(client); struct v4l2_pix_format *pix = &f->fmt.pix; struct v4l2_rect rect = { .left = mt9m111->rect.left, @@ -519,20 +474,19 @@ static int mt9m111_set_fmt(struct soc_camera_device *icd, }; int ret; - dev_dbg(&icd->dev, "%s fmt=%x left=%d, top=%d, width=%d, height=%d\n", + dev_dbg(&client->dev, "%s fmt=%x left=%d, top=%d, width=%d, height=%d\n", __func__, pix->pixelformat, rect.left, rect.top, rect.width, rect.height); - ret = mt9m111_setup_rect(icd, &rect); + ret = mt9m111_setup_rect(client, &rect); if (!ret) - ret = mt9m111_set_pixfmt(icd, pix->pixelformat); + ret = mt9m111_set_pixfmt(client, pix->pixelformat); if (!ret) mt9m111->rect = rect; return ret; } -static int mt9m111_try_fmt(struct soc_camera_device *icd, - struct v4l2_format *f) +static int mt9m111_try_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) { struct v4l2_pix_format *pix = &f->fmt.pix; @@ -544,11 +498,11 @@ static int mt9m111_try_fmt(struct soc_camera_device *icd, return 0; } -static int mt9m111_get_chip_id(struct soc_camera_device *icd, - struct v4l2_dbg_chip_ident *id) +static int mt9m111_g_chip_ident(struct v4l2_subdev *sd, + struct v4l2_dbg_chip_ident *id) { - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); - struct mt9m111 *mt9m111 = i2c_get_clientdata(client); + struct i2c_client *client = sd->priv; + struct mt9m111 *mt9m111 = to_mt9m111(client); if (id->match.type != V4L2_CHIP_MATCH_I2C_ADDR) return -EINVAL; @@ -563,10 +517,10 @@ static int mt9m111_get_chip_id(struct soc_camera_device *icd, } #ifdef CONFIG_VIDEO_ADV_DEBUG -static int mt9m111_get_register(struct soc_camera_device *icd, - struct v4l2_dbg_register *reg) +static int mt9m111_g_register(struct v4l2_subdev *sd, + struct v4l2_dbg_register *reg) { - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct i2c_client *client = sd->priv; int val; if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0x2ff) @@ -584,10 +538,10 @@ static int mt9m111_get_register(struct soc_camera_device *icd, return 0; } -static int mt9m111_set_register(struct soc_camera_device *icd, - struct v4l2_dbg_register *reg) +static int mt9m111_s_register(struct v4l2_subdev *sd, + struct v4l2_dbg_register *reg) { - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct i2c_client *client = sd->priv; if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0x2ff) return -EINVAL; @@ -639,41 +593,24 @@ static const struct v4l2_queryctrl mt9m111_controls[] = { } }; -static int mt9m111_get_control(struct soc_camera_device *, - struct v4l2_control *); -static int mt9m111_set_control(struct soc_camera_device *, - struct v4l2_control *); static int mt9m111_resume(struct soc_camera_device *icd); static int mt9m111_init(struct soc_camera_device *icd); static int mt9m111_release(struct soc_camera_device *icd); static struct soc_camera_ops mt9m111_ops = { - .owner = THIS_MODULE, .init = mt9m111_init, .resume = mt9m111_resume, .release = mt9m111_release, - .start_capture = mt9m111_start_capture, - .stop_capture = mt9m111_stop_capture, .set_crop = mt9m111_set_crop, - .set_fmt = mt9m111_set_fmt, - .try_fmt = mt9m111_try_fmt, .query_bus_param = mt9m111_query_bus_param, .set_bus_param = mt9m111_set_bus_param, .controls = mt9m111_controls, .num_controls = ARRAY_SIZE(mt9m111_controls), - .get_control = mt9m111_get_control, - .set_control = mt9m111_set_control, - .get_chip_id = mt9m111_get_chip_id, -#ifdef CONFIG_VIDEO_ADV_DEBUG - .get_register = mt9m111_get_register, - .set_register = mt9m111_set_register, -#endif }; -static int mt9m111_set_flip(struct soc_camera_device *icd, int flip, int mask) +static int mt9m111_set_flip(struct i2c_client *client, int flip, int mask) { - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); - struct mt9m111 *mt9m111 = i2c_get_clientdata(client); + struct mt9m111 *mt9m111 = to_mt9m111(client); int ret; if (mt9m111->context == HIGHPOWER) { @@ -691,9 +628,8 @@ static int mt9m111_set_flip(struct soc_camera_device *icd, int flip, int mask) return ret; } -static int mt9m111_get_global_gain(struct soc_camera_device *icd) +static int mt9m111_get_global_gain(struct i2c_client *client) { - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); int data; data = reg_read(GLOBAL_GAIN); @@ -703,9 +639,9 @@ static int mt9m111_get_global_gain(struct soc_camera_device *icd) return data; } -static int mt9m111_set_global_gain(struct soc_camera_device *icd, int gain) +static int mt9m111_set_global_gain(struct i2c_client *client, int gain) { - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct soc_camera_device *icd = client->dev.platform_data; u16 val; if (gain > 63 * 2 * 2) @@ -722,10 +658,9 @@ static int mt9m111_set_global_gain(struct soc_camera_device *icd, int gain) return reg_write(GLOBAL_GAIN, val); } -static int mt9m111_set_autoexposure(struct soc_camera_device *icd, int on) +static int mt9m111_set_autoexposure(struct i2c_client *client, int on) { - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); - struct mt9m111 *mt9m111 = i2c_get_clientdata(client); + struct mt9m111 *mt9m111 = to_mt9m111(client); int ret; if (on) @@ -739,10 +674,9 @@ static int mt9m111_set_autoexposure(struct soc_camera_device *icd, int on) return ret; } -static int mt9m111_set_autowhitebalance(struct soc_camera_device *icd, int on) +static int mt9m111_set_autowhitebalance(struct i2c_client *client, int on) { - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); - struct mt9m111 *mt9m111 = i2c_get_clientdata(client); + struct mt9m111 *mt9m111 = to_mt9m111(client); int ret; if (on) @@ -756,11 +690,10 @@ static int mt9m111_set_autowhitebalance(struct soc_camera_device *icd, int on) return ret; } -static int mt9m111_get_control(struct soc_camera_device *icd, - struct v4l2_control *ctrl) +static int mt9m111_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) { - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); - struct mt9m111 *mt9m111 = i2c_get_clientdata(client); + struct i2c_client *client = sd->priv; + struct mt9m111 *mt9m111 = to_mt9m111(client); int data; switch (ctrl->id) { @@ -785,7 +718,7 @@ static int mt9m111_get_control(struct soc_camera_device *icd, ctrl->value = !!(data & MT9M111_RMB_MIRROR_COLS); break; case V4L2_CID_GAIN: - data = mt9m111_get_global_gain(icd); + data = mt9m111_get_global_gain(client); if (data < 0) return data; ctrl->value = data; @@ -800,38 +733,36 @@ static int mt9m111_get_control(struct soc_camera_device *icd, return 0; } -static int mt9m111_set_control(struct soc_camera_device *icd, - struct v4l2_control *ctrl) +static int mt9m111_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) { - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); - struct mt9m111 *mt9m111 = i2c_get_clientdata(client); + struct i2c_client *client = sd->priv; + struct mt9m111 *mt9m111 = to_mt9m111(client); const struct v4l2_queryctrl *qctrl; int ret; qctrl = soc_camera_find_qctrl(&mt9m111_ops, ctrl->id); - if (!qctrl) return -EINVAL; switch (ctrl->id) { case V4L2_CID_VFLIP: mt9m111->vflip = ctrl->value; - ret = mt9m111_set_flip(icd, ctrl->value, + ret = mt9m111_set_flip(client, ctrl->value, MT9M111_RMB_MIRROR_ROWS); break; case V4L2_CID_HFLIP: mt9m111->hflip = ctrl->value; - ret = mt9m111_set_flip(icd, ctrl->value, + ret = mt9m111_set_flip(client, ctrl->value, MT9M111_RMB_MIRROR_COLS); break; case V4L2_CID_GAIN: - ret = mt9m111_set_global_gain(icd, ctrl->value); + ret = mt9m111_set_global_gain(client, ctrl->value); break; case V4L2_CID_EXPOSURE_AUTO: - ret = mt9m111_set_autoexposure(icd, ctrl->value); + ret = mt9m111_set_autoexposure(client, ctrl->value); break; case V4L2_CID_AUTO_WHITE_BALANCE: - ret = mt9m111_set_autowhitebalance(icd, ctrl->value); + ret = mt9m111_set_autowhitebalance(client, ctrl->value); break; default: ret = -EINVAL; @@ -840,34 +771,34 @@ static int mt9m111_set_control(struct soc_camera_device *icd, return ret; } -static int mt9m111_restore_state(struct soc_camera_device *icd) +static int mt9m111_restore_state(struct i2c_client *client) { - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); - struct mt9m111 *mt9m111 = i2c_get_clientdata(client); - - mt9m111_set_context(icd, mt9m111->context); - mt9m111_set_pixfmt(icd, mt9m111->pixfmt); - mt9m111_setup_rect(icd, &mt9m111->rect); - mt9m111_set_flip(icd, mt9m111->hflip, MT9M111_RMB_MIRROR_COLS); - mt9m111_set_flip(icd, mt9m111->vflip, MT9M111_RMB_MIRROR_ROWS); - mt9m111_set_global_gain(icd, icd->gain); - mt9m111_set_autoexposure(icd, mt9m111->autoexposure); - mt9m111_set_autowhitebalance(icd, mt9m111->autowhitebalance); + struct mt9m111 *mt9m111 = to_mt9m111(client); + struct soc_camera_device *icd = client->dev.platform_data; + + mt9m111_set_context(client, mt9m111->context); + mt9m111_set_pixfmt(client, mt9m111->pixfmt); + mt9m111_setup_rect(client, &mt9m111->rect); + mt9m111_set_flip(client, mt9m111->hflip, MT9M111_RMB_MIRROR_COLS); + mt9m111_set_flip(client, mt9m111->vflip, MT9M111_RMB_MIRROR_ROWS); + mt9m111_set_global_gain(client, icd->gain); + mt9m111_set_autoexposure(client, mt9m111->autoexposure); + mt9m111_set_autowhitebalance(client, mt9m111->autowhitebalance); return 0; } static int mt9m111_resume(struct soc_camera_device *icd) { struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); - struct mt9m111 *mt9m111 = i2c_get_clientdata(client); + struct mt9m111 *mt9m111 = to_mt9m111(client); int ret = 0; if (mt9m111->powered) { - ret = mt9m111_enable(icd); + ret = mt9m111_enable(client); if (!ret) - ret = mt9m111_reset(icd); + ret = mt9m111_reset(client); if (!ret) - ret = mt9m111_restore_state(icd); + ret = mt9m111_restore_state(client); } return ret; } @@ -875,17 +806,17 @@ static int mt9m111_resume(struct soc_camera_device *icd) static int mt9m111_init(struct soc_camera_device *icd) { struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); - struct mt9m111 *mt9m111 = i2c_get_clientdata(client); + struct mt9m111 *mt9m111 = to_mt9m111(client); int ret; mt9m111->context = HIGHPOWER; - ret = mt9m111_enable(icd); + ret = mt9m111_enable(client); if (!ret) - ret = mt9m111_reset(icd); + ret = mt9m111_reset(client); if (!ret) - ret = mt9m111_set_context(icd, mt9m111->context); + ret = mt9m111_set_context(client, mt9m111->context); if (!ret) - ret = mt9m111_set_autoexposure(icd, mt9m111->autoexposure); + ret = mt9m111_set_autoexposure(client, mt9m111->autoexposure); if (ret) dev_err(&icd->dev, "mt9m11x init failed: %d\n", ret); return ret; @@ -893,9 +824,14 @@ static int mt9m111_init(struct soc_camera_device *icd) static int mt9m111_release(struct soc_camera_device *icd) { + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct mt9m111 *mt9m111 = to_mt9m111(client); int ret; - ret = mt9m111_disable(icd); + ret = reg_clear(RESET, MT9M111_RESET_CHIP_ENABLE); + if (!ret) + mt9m111->powered = 0; + if (ret < 0) dev_err(&icd->dev, "mt9m11x release failed: %d\n", ret); @@ -909,7 +845,7 @@ static int mt9m111_release(struct soc_camera_device *icd) static int mt9m111_video_probe(struct soc_camera_device *icd, struct i2c_client *client) { - struct mt9m111 *mt9m111 = i2c_get_clientdata(client); + struct mt9m111 *mt9m111 = to_mt9m111(client); s32 data; int ret; @@ -921,15 +857,10 @@ static int mt9m111_video_probe(struct soc_camera_device *icd, to_soc_camera_host(icd->dev.parent)->nr != icd->iface) return -ENODEV; - /* Switch master clock on */ - ret = soc_camera_video_start(icd, &client->dev); - if (ret) - goto evstart; - - ret = mt9m111_enable(icd); + ret = mt9m111_enable(client); if (ret) goto ei2c; - ret = mt9m111_reset(icd); + ret = mt9m111_reset(client); if (ret) goto ei2c; @@ -961,11 +892,29 @@ static int mt9m111_video_probe(struct soc_camera_device *icd, mt9m111->swap_rgb_red_blue = 1; ei2c: - soc_camera_video_stop(icd); -evstart: return ret; } +static struct v4l2_subdev_core_ops mt9m111_subdev_core_ops = { + .g_ctrl = mt9m111_g_ctrl, + .s_ctrl = mt9m111_s_ctrl, + .g_chip_ident = mt9m111_g_chip_ident, +#ifdef CONFIG_VIDEO_ADV_DEBUG + .g_register = mt9m111_g_register, + .s_register = mt9m111_s_register, +#endif +}; + +static struct v4l2_subdev_video_ops mt9m111_subdev_video_ops = { + .s_fmt = mt9m111_s_fmt, + .try_fmt = mt9m111_try_fmt, +}; + +static struct v4l2_subdev_ops mt9m111_subdev_ops = { + .core = &mt9m111_subdev_core_ops, + .video = &mt9m111_subdev_video_ops, +}; + #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26) static int mt9m111_probe(struct i2c_client *client) #else @@ -1000,7 +949,7 @@ static int mt9m111_probe(struct i2c_client *client, if (!mt9m111) return -ENOMEM; - i2c_set_clientdata(client, mt9m111); + v4l2_i2c_subdev_init(&mt9m111->subdev, client, &mt9m111_subdev_ops); /* Second stage probe - when a capture adapter is there */ icd->ops = &mt9m111_ops; @@ -1026,7 +975,7 @@ static int mt9m111_probe(struct i2c_client *client, static int mt9m111_remove(struct i2c_client *client) { - struct mt9m111 *mt9m111 = i2c_get_clientdata(client); + struct mt9m111 *mt9m111 = to_mt9m111(client); struct soc_camera_device *icd = client->dev.platform_data; icd->ops = NULL; diff --git a/linux/drivers/media/video/mt9t031.c b/linux/drivers/media/video/mt9t031.c index b389223bc..2aff92cfc 100644 --- a/linux/drivers/media/video/mt9t031.c +++ b/linux/drivers/media/video/mt9t031.c @@ -13,13 +13,13 @@ #include #include -#include +#include #include #include /* mt9t031 i2c address 0x5d - * The platform has to define i2c_board_info - * and call i2c_register_board_info() */ + * The platform has to define i2c_board_info and link to it from + * struct soc_camera_link */ /* mt9t031 selected register addresses */ #define MT9T031_CHIP_VERSION 0x00 @@ -68,12 +68,18 @@ static const struct soc_camera_data_format mt9t031_colour_formats[] = { }; struct mt9t031 { + struct v4l2_subdev subdev; int model; /* V4L2_IDENT_MT9T031* codes from v4l2-chip-ident.h */ unsigned char autoexposure; u16 xskip; u16 yskip; }; +static struct mt9t031 *to_mt9t031(const struct i2c_client *client) +{ + return container_of(i2c_get_clientdata(client), struct mt9t031, subdev); +} + static int reg_read(struct i2c_client *client, const u8 reg) { s32 data = i2c_smbus_read_word_data(client, reg); @@ -134,21 +140,10 @@ static int get_shutter(struct i2c_client *client, u32 *data) return ret < 0 ? ret : 0; } -static int mt9t031_init(struct soc_camera_device *icd) +static int mt9t031_idle(struct i2c_client *client) { - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); - struct soc_camera_link *icl = to_soc_camera_link(icd); int ret; - if (icl->power) { - ret = icl->power(&client->dev, 1); - if (ret < 0) { - dev_err(icd->vdev->parent, - "Platform failed to power-on the camera.\n"); - return ret; - } - } - /* Disable chip output, synchronous option update */ ret = reg_write(client, MT9T031_RESET, 1); if (ret >= 0) @@ -156,43 +151,46 @@ static int mt9t031_init(struct soc_camera_device *icd) if (ret >= 0) ret = reg_clear(client, MT9T031_OUTPUT_CONTROL, 2); - if (ret < 0 && icl->power) - icl->power(&client->dev, 0); - return ret >= 0 ? 0 : -EIO; } -static int mt9t031_release(struct soc_camera_device *icd) +static int mt9t031_disable(struct i2c_client *client) { - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); - struct soc_camera_link *icl = to_soc_camera_link(icd); - /* Disable the chip */ reg_clear(client, MT9T031_OUTPUT_CONTROL, 2); - if (icl->power) - icl->power(&client->dev, 0); - return 0; } -static int mt9t031_start_capture(struct soc_camera_device *icd) +static int mt9t031_init(struct soc_camera_device *icd) { struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); - /* Switch to master "normal" mode */ - if (reg_set(client, MT9T031_OUTPUT_CONTROL, 2) < 0) - return -EIO; - return 0; + return mt9t031_idle(client); } -static int mt9t031_stop_capture(struct soc_camera_device *icd) +static int mt9t031_release(struct soc_camera_device *icd) { struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); - /* Stop sensor readout */ - if (reg_clear(client, MT9T031_OUTPUT_CONTROL, 2) < 0) + return mt9t031_disable(client); +} + +static int mt9t031_s_stream(struct v4l2_subdev *sd, int enable) +{ + struct i2c_client *client = sd->priv; + int ret; + + if (enable) + /* Switch to master "normal" mode */ + ret = reg_set(client, MT9T031_OUTPUT_CONTROL, 2); + else + /* Stop sensor readout */ + ret = reg_clear(client, MT9T031_OUTPUT_CONTROL, 2); + + if (ret < 0) return -EIO; + return 0; } @@ -236,7 +234,7 @@ static int mt9t031_set_params(struct soc_camera_device *icd, struct v4l2_rect *rect, u16 xskip, u16 yskip) { struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); - struct mt9t031 *mt9t031 = i2c_get_clientdata(client); + struct mt9t031 *mt9t031 = to_mt9t031(client); int ret; u16 xbin, ybin, width, height, left, top; const u16 hblank = MT9T031_HORIZONTAL_BLANK, @@ -334,17 +332,17 @@ static int mt9t031_set_crop(struct soc_camera_device *icd, struct v4l2_rect *rect) { struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); - struct mt9t031 *mt9t031 = i2c_get_clientdata(client); + struct mt9t031 *mt9t031 = to_mt9t031(client); /* CROP - no change in scaling, or in limits */ return mt9t031_set_params(icd, rect, mt9t031->xskip, mt9t031->yskip); } -static int mt9t031_set_fmt(struct soc_camera_device *icd, - struct v4l2_format *f) +static int mt9t031_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) { - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); - struct mt9t031 *mt9t031 = i2c_get_clientdata(client); + struct i2c_client *client = sd->priv; + struct mt9t031 *mt9t031 = to_mt9t031(client); + struct soc_camera_device *icd = client->dev.platform_data; int ret; u16 xskip, yskip; struct v4l2_rect rect = { @@ -379,8 +377,7 @@ static int mt9t031_set_fmt(struct soc_camera_device *icd, return ret; } -static int mt9t031_try_fmt(struct soc_camera_device *icd, - struct v4l2_format *f) +static int mt9t031_try_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) { struct v4l2_pix_format *pix = &f->fmt.pix; @@ -391,11 +388,11 @@ static int mt9t031_try_fmt(struct soc_camera_device *icd, return 0; } -static int mt9t031_get_chip_id(struct soc_camera_device *icd, - struct v4l2_dbg_chip_ident *id) +static int mt9t031_g_chip_ident(struct v4l2_subdev *sd, + struct v4l2_dbg_chip_ident *id) { - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); - struct mt9t031 *mt9t031 = i2c_get_clientdata(client); + struct i2c_client *client = sd->priv; + struct mt9t031 *mt9t031 = to_mt9t031(client); if (id->match.type != V4L2_CHIP_MATCH_I2C_ADDR) return -EINVAL; @@ -410,10 +407,10 @@ static int mt9t031_get_chip_id(struct soc_camera_device *icd, } #ifdef CONFIG_VIDEO_ADV_DEBUG -static int mt9t031_get_register(struct soc_camera_device *icd, - struct v4l2_dbg_register *reg) +static int mt9t031_g_register(struct v4l2_subdev *sd, + struct v4l2_dbg_register *reg) { - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct i2c_client *client = sd->priv; if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff) return -EINVAL; @@ -429,10 +426,10 @@ static int mt9t031_get_register(struct soc_camera_device *icd, return 0; } -static int mt9t031_set_register(struct soc_camera_device *icd, - struct v4l2_dbg_register *reg) +static int mt9t031_s_register(struct v4l2_subdev *sd, + struct v4l2_dbg_register *reg) { - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct i2c_client *client = sd->priv; if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff) return -EINVAL; @@ -493,35 +490,20 @@ static const struct v4l2_queryctrl mt9t031_controls[] = { } }; -static int mt9t031_get_control(struct soc_camera_device *, struct v4l2_control *); -static int mt9t031_set_control(struct soc_camera_device *, struct v4l2_control *); - static struct soc_camera_ops mt9t031_ops = { - .owner = THIS_MODULE, .init = mt9t031_init, .release = mt9t031_release, - .start_capture = mt9t031_start_capture, - .stop_capture = mt9t031_stop_capture, .set_crop = mt9t031_set_crop, - .set_fmt = mt9t031_set_fmt, - .try_fmt = mt9t031_try_fmt, .set_bus_param = mt9t031_set_bus_param, .query_bus_param = mt9t031_query_bus_param, .controls = mt9t031_controls, .num_controls = ARRAY_SIZE(mt9t031_controls), - .get_control = mt9t031_get_control, - .set_control = mt9t031_set_control, - .get_chip_id = mt9t031_get_chip_id, -#ifdef CONFIG_VIDEO_ADV_DEBUG - .get_register = mt9t031_get_register, - .set_register = mt9t031_set_register, -#endif }; -static int mt9t031_get_control(struct soc_camera_device *icd, struct v4l2_control *ctrl) +static int mt9t031_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) { - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); - struct mt9t031 *mt9t031 = i2c_get_clientdata(client); + struct i2c_client *client = sd->priv; + struct mt9t031 *mt9t031 = to_mt9t031(client); int data; switch (ctrl->id) { @@ -544,10 +526,11 @@ static int mt9t031_get_control(struct soc_camera_device *icd, struct v4l2_contro return 0; } -static int mt9t031_set_control(struct soc_camera_device *icd, struct v4l2_control *ctrl) +static int mt9t031_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) { - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); - struct mt9t031 *mt9t031 = i2c_get_clientdata(client); + struct i2c_client *client = sd->priv; + struct mt9t031 *mt9t031 = to_mt9t031(client); + struct soc_camera_device *icd = client->dev.platform_data; const struct v4l2_queryctrl *qctrl; int data; @@ -653,12 +636,11 @@ static int mt9t031_set_control(struct soc_camera_device *icd, struct v4l2_contro /* Interface active, can use i2c. If it fails, it can indeed mean, that * this wasn't our capture interface, so, we wait for the right one */ -static int mt9t031_video_probe(struct soc_camera_device *icd, - struct i2c_client *client) +static int mt9t031_video_probe(struct i2c_client *client) { - struct mt9t031 *mt9t031 = i2c_get_clientdata(client); + struct soc_camera_device *icd = client->dev.platform_data; + struct mt9t031 *mt9t031 = to_mt9t031(client); s32 data; - int ret; /* We must have a parent by now. And it cannot be a wrong one. * So this entire test is completely redundant. */ @@ -666,11 +648,6 @@ static int mt9t031_video_probe(struct soc_camera_device *icd, to_soc_camera_host(icd->dev.parent)->nr != icd->iface) return -ENODEV; - /* Switch master clock on */ - ret = soc_camera_video_start(icd, &client->dev); - if (ret) - return ret; - /* Enable the chip */ data = reg_write(client, MT9T031_CHIP_ENABLE, 1); dev_dbg(&icd->dev, "write: %d\n", data); @@ -678,8 +655,6 @@ static int mt9t031_video_probe(struct soc_camera_device *icd, /* Read out the chip version register */ data = reg_read(client, MT9T031_CHIP_VERSION); - soc_camera_video_stop(icd); - switch (data) { case 0x1621: mt9t031->model = V4L2_IDENT_MT9T031; @@ -697,6 +672,27 @@ static int mt9t031_video_probe(struct soc_camera_device *icd, return 0; } +static struct v4l2_subdev_core_ops mt9t031_subdev_core_ops = { + .g_ctrl = mt9t031_g_ctrl, + .s_ctrl = mt9t031_s_ctrl, + .g_chip_ident = mt9t031_g_chip_ident, +#ifdef CONFIG_VIDEO_ADV_DEBUG + .g_register = mt9t031_g_register, + .s_register = mt9t031_s_register, +#endif +}; + +static struct v4l2_subdev_video_ops mt9t031_subdev_video_ops = { + .s_stream = mt9t031_s_stream, + .s_fmt = mt9t031_s_fmt, + .try_fmt = mt9t031_try_fmt, +}; + +static struct v4l2_subdev_ops mt9t031_subdev_ops = { + .core = &mt9t031_subdev_core_ops, + .video = &mt9t031_subdev_video_ops, +}; + #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26) static int mt9t031_probe(struct i2c_client *client) #else @@ -731,7 +727,7 @@ static int mt9t031_probe(struct i2c_client *client, if (!mt9t031) return -ENOMEM; - i2c_set_clientdata(client, mt9t031); + v4l2_i2c_subdev_init(&mt9t031->subdev, client, &mt9t031_subdev_ops); /* Second stage probe - when a capture adapter is there */ icd->ops = &mt9t031_ops; @@ -751,7 +747,12 @@ static int mt9t031_probe(struct i2c_client *client, mt9t031->xskip = 1; mt9t031->yskip = 1; - ret = mt9t031_video_probe(icd, client); + mt9t031_idle(client); + + ret = mt9t031_video_probe(client); + + mt9t031_disable(client); + if (ret) { icd->ops = NULL; i2c_set_clientdata(client, NULL); @@ -763,7 +764,7 @@ static int mt9t031_probe(struct i2c_client *client, static int mt9t031_remove(struct i2c_client *client) { - struct mt9t031 *mt9t031 = i2c_get_clientdata(client); + struct mt9t031 *mt9t031 = to_mt9t031(client); struct soc_camera_device *icd = client->dev.platform_data; icd->ops = NULL; diff --git a/linux/drivers/media/video/mt9v022.c b/linux/drivers/media/video/mt9v022.c index 204481f77..b09cd0913 100644 --- a/linux/drivers/media/video/mt9v022.c +++ b/linux/drivers/media/video/mt9v022.c @@ -14,13 +14,13 @@ #include #include -#include +#include #include #include /* mt9v022 i2c address 0x48, 0x4c, 0x58, 0x5c - * The platform has to define i2c_board_info - * and call i2c_register_board_info() */ + * The platform has to define ctruct i2c_board_info objects and link to them + * from struct soc_camera_link */ static char *sensor_type; module_param(sensor_type, charp, S_IRUGO); @@ -85,10 +85,16 @@ static const struct soc_camera_data_format mt9v022_monochrome_formats[] = { }; struct mt9v022 { + struct v4l2_subdev subdev; int model; /* V4L2_IDENT_MT9V022* codes from v4l2-chip-ident.h */ u16 chip_control; }; +static struct mt9v022 *to_mt9v022(const struct i2c_client *client) +{ + return container_of(i2c_get_clientdata(client), struct mt9v022, subdev); +} + static int reg_read(struct i2c_client *client, const u8 reg) { s32 data = i2c_smbus_read_word_data(client, reg); @@ -126,26 +132,9 @@ static int reg_clear(struct i2c_client *client, const u8 reg, static int mt9v022_init(struct soc_camera_device *icd) { struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); - struct soc_camera_link *icl = to_soc_camera_link(icd); - struct mt9v022 *mt9v022 = i2c_get_clientdata(client); + struct mt9v022 *mt9v022 = to_mt9v022(client); int ret; - if (icl->power) { - ret = icl->power(&client->dev, 1); - if (ret < 0) { - dev_err(icd->vdev->parent, - "Platform failed to power-on the camera.\n"); - return ret; - } - } - - /* - * The camera could have been already on, we hard-reset it additionally, - * if available. Soft reset is done in video_probe(). - */ - if (icl->reset) - icl->reset(&client->dev); - /* Almost the default mode: master, parallel, simultaneous, and an * undocumented bit 0x200, which is present in table 7, but not in 8, * plus snapshot mode to disable scan for now */ @@ -169,37 +158,19 @@ static int mt9v022_init(struct soc_camera_device *icd) return ret; } -static int mt9v022_release(struct soc_camera_device *icd) +static int mt9v022_s_stream(struct v4l2_subdev *sd, int enable) { - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); - struct soc_camera_link *icl = to_soc_camera_link(icd); + struct i2c_client *client = sd->priv; + struct mt9v022 *mt9v022 = to_mt9v022(client); - if (icl->power) - icl->power(&client->dev, 0); - - return 0; -} - -static int mt9v022_start_capture(struct soc_camera_device *icd) -{ - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); - struct mt9v022 *mt9v022 = i2c_get_clientdata(client); - /* Switch to master "normal" mode */ - mt9v022->chip_control &= ~0x10; - if (reg_write(client, MT9V022_CHIP_CONTROL, - mt9v022->chip_control) < 0) - return -EIO; - return 0; -} + if (enable) + /* Switch to master "normal" mode */ + mt9v022->chip_control &= ~0x10; + else + /* Switch to snapshot mode */ + mt9v022->chip_control |= 0x10; -static int mt9v022_stop_capture(struct soc_camera_device *icd) -{ - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); - struct mt9v022 *mt9v022 = i2c_get_clientdata(client); - /* Switch to snapshot mode */ - mt9v022->chip_control |= 0x10; - if (reg_write(client, MT9V022_CHIP_CONTROL, - mt9v022->chip_control) < 0) + if (reg_write(client, MT9V022_CHIP_CONTROL, mt9v022->chip_control) < 0) return -EIO; return 0; } @@ -208,7 +179,7 @@ static int mt9v022_set_bus_param(struct soc_camera_device *icd, unsigned long flags) { struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); - struct mt9v022 *mt9v022 = i2c_get_clientdata(client); + struct mt9v022 *mt9v022 = to_mt9v022(client); struct soc_camera_link *icl = to_soc_camera_link(icd); unsigned int width_flag = flags & SOCAM_DATAWIDTH_MASK; int ret; @@ -320,11 +291,11 @@ static int mt9v022_set_crop(struct soc_camera_device *icd, return 0; } -static int mt9v022_set_fmt(struct soc_camera_device *icd, - struct v4l2_format *f) +static int mt9v022_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) { - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); - struct mt9v022 *mt9v022 = i2c_get_clientdata(client); + struct i2c_client *client = sd->priv; + struct mt9v022 *mt9v022 = to_mt9v022(client); + struct soc_camera_device *icd = client->dev.platform_data; struct v4l2_pix_format *pix = &f->fmt.pix; struct v4l2_rect rect = { .left = icd->x_current, @@ -357,9 +328,10 @@ static int mt9v022_set_fmt(struct soc_camera_device *icd, return mt9v022_set_crop(icd, &rect); } -static int mt9v022_try_fmt(struct soc_camera_device *icd, - struct v4l2_format *f) +static int mt9v022_try_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) { + struct i2c_client *client = sd->priv; + struct soc_camera_device *icd = client->dev.platform_data; struct v4l2_pix_format *pix = &f->fmt.pix; v4l_bound_align_image(&pix->width, 48, 752, 2 /* ? */, @@ -369,11 +341,11 @@ static int mt9v022_try_fmt(struct soc_camera_device *icd, return 0; } -static int mt9v022_get_chip_id(struct soc_camera_device *icd, - struct v4l2_dbg_chip_ident *id) +static int mt9v022_g_chip_ident(struct v4l2_subdev *sd, + struct v4l2_dbg_chip_ident *id) { - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); - struct mt9v022 *mt9v022 = i2c_get_clientdata(client); + struct i2c_client *client = sd->priv; + struct mt9v022 *mt9v022 = to_mt9v022(client); if (id->match.type != V4L2_CHIP_MATCH_I2C_ADDR) return -EINVAL; @@ -388,10 +360,10 @@ static int mt9v022_get_chip_id(struct soc_camera_device *icd, } #ifdef CONFIG_VIDEO_ADV_DEBUG -static int mt9v022_get_register(struct soc_camera_device *icd, - struct v4l2_dbg_register *reg) +static int mt9v022_g_register(struct v4l2_subdev *sd, + struct v4l2_dbg_register *reg) { - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct i2c_client *client = sd->priv; if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff) return -EINVAL; @@ -408,10 +380,10 @@ static int mt9v022_get_register(struct soc_camera_device *icd, return 0; } -static int mt9v022_set_register(struct soc_camera_device *icd, - struct v4l2_dbg_register *reg) +static int mt9v022_s_register(struct v4l2_subdev *sd, + struct v4l2_dbg_register *reg) { - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct i2c_client *client = sd->priv; if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff) return -EINVAL; @@ -480,35 +452,18 @@ static const struct v4l2_queryctrl mt9v022_controls[] = { } }; -static int mt9v022_get_control(struct soc_camera_device *, struct v4l2_control *); -static int mt9v022_set_control(struct soc_camera_device *, struct v4l2_control *); - static struct soc_camera_ops mt9v022_ops = { - .owner = THIS_MODULE, .init = mt9v022_init, - .release = mt9v022_release, - .start_capture = mt9v022_start_capture, - .stop_capture = mt9v022_stop_capture, .set_crop = mt9v022_set_crop, - .set_fmt = mt9v022_set_fmt, - .try_fmt = mt9v022_try_fmt, .set_bus_param = mt9v022_set_bus_param, .query_bus_param = mt9v022_query_bus_param, .controls = mt9v022_controls, .num_controls = ARRAY_SIZE(mt9v022_controls), - .get_control = mt9v022_get_control, - .set_control = mt9v022_set_control, - .get_chip_id = mt9v022_get_chip_id, -#ifdef CONFIG_VIDEO_ADV_DEBUG - .get_register = mt9v022_get_register, - .set_register = mt9v022_set_register, -#endif }; -static int mt9v022_get_control(struct soc_camera_device *icd, - struct v4l2_control *ctrl) +static int mt9v022_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) { - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct i2c_client *client = sd->priv; int data; switch (ctrl->id) { @@ -540,15 +495,14 @@ static int mt9v022_get_control(struct soc_camera_device *icd, return 0; } -static int mt9v022_set_control(struct soc_camera_device *icd, - struct v4l2_control *ctrl) +static int mt9v022_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) { int data; - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct i2c_client *client = sd->priv; + struct soc_camera_device *icd = client->dev.platform_data; const struct v4l2_queryctrl *qctrl; qctrl = soc_camera_find_qctrl(&mt9v022_ops, ctrl->id); - if (!qctrl) return -EINVAL; @@ -644,7 +598,7 @@ static int mt9v022_set_control(struct soc_camera_device *icd, static int mt9v022_video_probe(struct soc_camera_device *icd, struct i2c_client *client) { - struct mt9v022 *mt9v022 = i2c_get_clientdata(client); + struct mt9v022 *mt9v022 = to_mt9v022(client); struct soc_camera_link *icl = to_soc_camera_link(icd); s32 data; int ret; @@ -654,11 +608,6 @@ static int mt9v022_video_probe(struct soc_camera_device *icd, to_soc_camera_host(icd->dev.parent)->nr != icd->iface) return -ENODEV; - /* Switch master clock on */ - ret = soc_camera_video_start(icd, &client->dev); - if (ret) - return ret; - /* Read out the chip version register */ data = reg_read(client, MT9V022_CHIP_VERSION); @@ -723,8 +672,6 @@ static int mt9v022_video_probe(struct soc_camera_device *icd, "monochrome" : "colour"); ei2c: - soc_camera_video_stop(icd); - return ret; } @@ -739,6 +686,27 @@ static void mt9v022_video_remove(struct soc_camera_device *icd) icl->free_bus(icl); } +static struct v4l2_subdev_core_ops mt9v022_subdev_core_ops = { + .g_ctrl = mt9v022_g_ctrl, + .s_ctrl = mt9v022_s_ctrl, + .g_chip_ident = mt9v022_g_chip_ident, +#ifdef CONFIG_VIDEO_ADV_DEBUG + .g_register = mt9v022_g_register, + .s_register = mt9v022_s_register, +#endif +}; + +static struct v4l2_subdev_video_ops mt9v022_subdev_video_ops = { + .s_stream = mt9v022_s_stream, + .s_fmt = mt9v022_s_fmt, + .try_fmt = mt9v022_try_fmt, +}; + +static struct v4l2_subdev_ops mt9v022_subdev_ops = { + .core = &mt9v022_subdev_core_ops, + .video = &mt9v022_subdev_video_ops, +}; + #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) static int mt9v022_probe(struct i2c_client *client, const struct i2c_device_id *did) @@ -773,8 +741,9 @@ static int mt9v022_probe(struct i2c_client *client) if (!mt9v022) return -ENOMEM; + v4l2_i2c_subdev_init(&mt9v022->subdev, client, &mt9v022_subdev_ops); + mt9v022->chip_control = MT9V022_CHIP_CONTROL_DEFAULT; - i2c_set_clientdata(client, mt9v022); icd->ops = &mt9v022_ops; icd->x_min = 1; @@ -799,7 +768,7 @@ static int mt9v022_probe(struct i2c_client *client) static int mt9v022_remove(struct i2c_client *client) { - struct mt9v022 *mt9v022 = i2c_get_clientdata(client); + struct mt9v022 *mt9v022 = to_mt9v022(client); struct soc_camera_device *icd = client->dev.platform_data; icd->ops = NULL; diff --git a/linux/drivers/media/video/mx1_camera.c b/linux/drivers/media/video/mx1_camera.c index 736c31d23..ea4ceaec8 100644 --- a/linux/drivers/media/video/mx1_camera.c +++ b/linux/drivers/media/video/mx1_camera.c @@ -219,7 +219,7 @@ static int mx1_camera_setup_dma(struct mx1_camera_dev *pcdev) int ret; if (unlikely(!pcdev->active)) { - dev_err(pcdev->soc_host.dev, "DMA End IRQ with no active buffer\n"); + dev_err(pcdev->icd->dev.parent, "DMA End IRQ with no active buffer\n"); return -EFAULT; } @@ -229,7 +229,7 @@ static int mx1_camera_setup_dma(struct mx1_camera_dev *pcdev) vbuf->size, pcdev->res->start + CSIRXR, DMA_MODE_READ); if (unlikely(ret)) - dev_err(pcdev->soc_host.dev, "Failed to setup DMA sg list\n"); + dev_err(pcdev->icd->dev.parent, "Failed to setup DMA sg list\n"); return ret; } @@ -334,14 +334,14 @@ static void mx1_camera_dma_irq(int channel, void *data) imx_dma_disable(channel); if (unlikely(!pcdev->active)) { - dev_err(pcdev->soc_host.dev, "DMA End IRQ with no active buffer\n"); + dev_err(pcdev->icd->dev.parent, "DMA End IRQ with no active buffer\n"); goto out; } vb = &pcdev->active->vb; buf = container_of(vb, struct mx1_buffer, vb); WARN_ON(buf->inwork || list_empty(&vb->queue)); - dev_dbg(pcdev->soc_host.dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__, + dev_dbg(pcdev->icd->dev.parent, "%s (vb=0x%p) 0x%08lx %d\n", __func__, vb, vb->baddr, vb->bsize); mx1_camera_wakeup(pcdev, vb, buf); @@ -362,7 +362,7 @@ static void mx1_camera_init_videobuf(struct videobuf_queue *q, struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); struct mx1_camera_dev *pcdev = ici->priv; - videobuf_queue_dma_contig_init(q, &mx1_videobuf_ops, ici->dev, + videobuf_queue_dma_contig_init(q, &mx1_videobuf_ops, icd->dev.parent, &pcdev->lock, V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_NONE, @@ -381,7 +381,7 @@ static int mclk_get_divisor(struct mx1_camera_dev *pcdev) * they get a nice Oops */ div = (lcdclk + 2 * mclk - 1) / (2 * mclk) - 1; - dev_dbg(pcdev->soc_host.dev, "System clock %lukHz, target freq %dkHz, " + dev_dbg(pcdev->icd->dev.parent, "System clock %lukHz, target freq %dkHz, " "divisor %lu\n", lcdclk / 1000, mclk / 1000, div); return div; @@ -391,7 +391,7 @@ static void mx1_camera_activate(struct mx1_camera_dev *pcdev) { unsigned int csicr1 = CSICR1_EN; - dev_dbg(pcdev->soc_host.dev, "Activate device\n"); + dev_dbg(pcdev->icd->dev.parent, "Activate device\n"); clk_enable(pcdev->clk); @@ -407,7 +407,7 @@ static void mx1_camera_activate(struct mx1_camera_dev *pcdev) static void mx1_camera_deactivate(struct mx1_camera_dev *pcdev) { - dev_dbg(pcdev->soc_host.dev, "Deactivate device\n"); + dev_dbg(pcdev->icd->dev.parent, "Deactivate device\n"); /* Disable all CSI interface */ __raw_writel(0x00, pcdev->base + CSICR1); @@ -432,10 +432,8 @@ static int mx1_camera_add_device(struct soc_camera_device *icd) icd->devnum); mx1_camera_activate(pcdev); - ret = icd->ops->init(icd); - if (!ret) - pcdev->icd = icd; + pcdev->icd = icd; ebusy: return ret; @@ -459,8 +457,6 @@ static void mx1_camera_remove_device(struct soc_camera_device *icd) dev_info(&icd->dev, "MX1 Camera driver detached from camera %d\n", icd->devnum); - icd->ops->release(icd); - mx1_camera_deactivate(pcdev); pcdev->icd = NULL; @@ -546,11 +542,11 @@ static int mx1_camera_set_fmt(struct soc_camera_device *icd, xlate = soc_camera_xlate_by_fourcc(icd, pix->pixelformat); if (!xlate) { - dev_warn(ici->dev, "Format %x not found\n", pix->pixelformat); + dev_warn(icd->dev.parent, "Format %x not found\n", pix->pixelformat); return -EINVAL; } - ret = icd->ops->set_fmt(icd, f); + ret = v4l2_device_call_until_err(&ici->v4l2_dev, 0, video, s_fmt, f); if (!ret) { icd->buswidth = xlate->buswidth; icd->current_fmt = xlate->host_fmt; @@ -562,10 +558,11 @@ static int mx1_camera_set_fmt(struct soc_camera_device *icd, static int mx1_camera_try_fmt(struct soc_camera_device *icd, struct v4l2_format *f) { + struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); /* TODO: limit to mx1 hardware capabilities */ /* limit to sensor capabilities */ - return icd->ops->try_fmt(icd, f); + return v4l2_device_call_until_err(&ici->v4l2_dev, 0, video, try_fmt, f); } static int mx1_camera_reqbufs(struct soc_camera_file *icf, @@ -737,7 +734,7 @@ static int __init mx1_camera_probe(struct platform_device *pdev) pcdev->soc_host.drv_name = DRIVER_NAME; pcdev->soc_host.ops = &mx1_soc_camera_host_ops; pcdev->soc_host.priv = pcdev; - pcdev->soc_host.dev = &pdev->dev; + pcdev->soc_host.v4l2_dev.dev = &pdev->dev; pcdev->soc_host.nr = pdev->id; err = soc_camera_host_register(&pcdev->soc_host); if (err) diff --git a/linux/drivers/media/video/mx3_camera.c b/linux/drivers/media/video/mx3_camera.c index 2edf77a62..677d355be 100644 --- a/linux/drivers/media/video/mx3_camera.c +++ b/linux/drivers/media/video/mx3_camera.c @@ -431,7 +431,7 @@ static void mx3_camera_init_videobuf(struct videobuf_queue *q, struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); struct mx3_camera_dev *mx3_cam = ici->priv; - videobuf_queue_dma_contig_init(q, &mx3_videobuf_ops, ici->dev, + videobuf_queue_dma_contig_init(q, &mx3_videobuf_ops, icd->dev.parent, &mx3_cam->lock, V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_NONE, @@ -494,17 +494,11 @@ static int mx3_camera_add_device(struct soc_camera_device *icd) { struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); struct mx3_camera_dev *mx3_cam = ici->priv; - int ret; - if (mx3_cam->icd) { - ret = -EBUSY; - goto ebusy; - } + if (mx3_cam->icd) + return -EBUSY; mx3_camera_activate(mx3_cam, icd); - ret = icd->ops->init(icd); - if (ret < 0) - goto einit; mx3_cam->icd = icd; @@ -512,12 +506,6 @@ static int mx3_camera_add_device(struct soc_camera_device *icd) icd->devnum); return 0; - -einit: - clk_disable(mx3_cam->clk); -ebusy: - - return ret; } /* Called with .video_lock held */ @@ -534,8 +522,6 @@ static void mx3_camera_remove_device(struct soc_camera_device *icd) *ichan = NULL; } - icd->ops->release(icd); - clk_disable(mx3_cam->clk); mx3_cam->icd = NULL; @@ -600,7 +586,7 @@ static int test_platform_param(struct mx3_camera_dev *mx3_cam, *flags |= SOCAM_DATAWIDTH_4; break; default: - dev_info(mx3_cam->soc_host.dev, "Unsupported bus width %d\n", + dev_info(mx3_cam->soc_host.v4l2_dev.dev, "Unsupported bus width %d\n", buswidth); return -EINVAL; } @@ -616,7 +602,7 @@ static int mx3_camera_try_bus_param(struct soc_camera_device *icd, unsigned long bus_flags, camera_flags; int ret = test_platform_param(mx3_cam, depth, &bus_flags); - dev_dbg(ici->dev, "requested bus width %d bit: %d\n", depth, ret); + dev_dbg(icd->dev.parent, "requested bus width %d bit: %d\n", depth, ret); if (ret < 0) return ret; @@ -639,7 +625,7 @@ static bool chan_filter(struct dma_chan *chan, void *arg) if (!rq) return false; - pdata = rq->mx3_cam->soc_host.dev->platform_data; + pdata = rq->mx3_cam->soc_host.v4l2_dev.dev->platform_data; return rq->id == chan->chan_id && pdata->dma_dev == chan->device->dev; @@ -699,7 +685,7 @@ static int mx3_camera_get_formats(struct soc_camera_device *icd, int idx, xlate->cam_fmt = icd->formats + idx; xlate->buswidth = buswidth; xlate++; - dev_dbg(ici->dev, "Providing format %s using %s\n", + dev_dbg(icd->dev.parent, "Providing format %s using %s\n", mx3_camera_formats[0].name, icd->formats[idx].name); } @@ -711,7 +697,7 @@ static int mx3_camera_get_formats(struct soc_camera_device *icd, int idx, xlate->cam_fmt = icd->formats + idx; xlate->buswidth = buswidth; xlate++; - dev_dbg(ici->dev, "Providing format %s using %s\n", + dev_dbg(icd->dev.parent, "Providing format %s using %s\n", mx3_camera_formats[0].name, icd->formats[idx].name); } @@ -724,7 +710,7 @@ passthrough: xlate->cam_fmt = icd->formats + idx; xlate->buswidth = buswidth; xlate++; - dev_dbg(ici->dev, + dev_dbg(icd->dev.parent, "Providing format %s in pass-through mode\n", icd->formats[idx].name); } @@ -831,7 +817,7 @@ static int mx3_camera_set_fmt(struct soc_camera_device *icd, xlate = soc_camera_xlate_by_fourcc(icd, pix->pixelformat); if (!xlate) { - dev_warn(ici->dev, "Format %x not found\n", pix->pixelformat); + dev_warn(icd->dev.parent, "Format %x not found\n", pix->pixelformat); return -EINVAL; } @@ -847,7 +833,7 @@ static int mx3_camera_set_fmt(struct soc_camera_device *icd, configure_geometry(mx3_cam, &rect); - ret = icd->ops->set_fmt(icd, f); + ret = v4l2_device_call_until_err(&ici->v4l2_dev, 0, video, s_fmt, f); if (!ret) { icd->buswidth = xlate->buswidth; icd->current_fmt = xlate->host_fmt; @@ -868,7 +854,7 @@ static int mx3_camera_try_fmt(struct soc_camera_device *icd, xlate = soc_camera_xlate_by_fourcc(icd, pixfmt); if (pixfmt && !xlate) { - dev_warn(ici->dev, "Format %x not found\n", pixfmt); + dev_warn(icd->dev.parent, "Format %x not found\n", pixfmt); return -EINVAL; } @@ -885,7 +871,7 @@ static int mx3_camera_try_fmt(struct soc_camera_device *icd, /* camera has to see its format, but the user the original one */ pix->pixelformat = xlate->cam_fmt->fourcc; /* limit to sensor capabilities */ - ret = icd->ops->try_fmt(icd, f); + ret = v4l2_device_call_until_err(&ici->v4l2_dev, 0, video, try_fmt, f); pix->pixelformat = xlate->host_fmt->fourcc; field = pix->field; @@ -935,11 +921,11 @@ static int mx3_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt) xlate = soc_camera_xlate_by_fourcc(icd, pixfmt); if (!xlate) { - dev_warn(ici->dev, "Format %x not found\n", pixfmt); + dev_warn(icd->dev.parent, "Format %x not found\n", pixfmt); return -EINVAL; } - dev_dbg(ici->dev, "requested bus width %d bit: %d\n", + dev_dbg(icd->dev.parent, "requested bus width %d bit: %d\n", icd->buswidth, ret); if (ret < 0) @@ -948,10 +934,10 @@ static int mx3_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt) camera_flags = icd->ops->query_bus_param(icd); common_flags = soc_camera_bus_param_compatible(camera_flags, bus_flags); - dev_dbg(ici->dev, "Flags cam: 0x%lx host: 0x%lx common: 0x%lx\n", + dev_dbg(icd->dev.parent, "Flags cam: 0x%lx host: 0x%lx common: 0x%lx\n", camera_flags, bus_flags, common_flags); if (!common_flags) { - dev_dbg(ici->dev, "no common flags"); + dev_dbg(icd->dev.parent, "no common flags"); return -EINVAL; } @@ -1005,7 +991,7 @@ static int mx3_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt) ret = icd->ops->set_bus_param(icd, common_flags); if (ret < 0) { - dev_dbg(ici->dev, "camera set_bus_param(%lx) returned %d\n", + dev_dbg(icd->dev.parent, "camera set_bus_param(%lx) returned %d\n", common_flags, ret); return ret; } @@ -1060,7 +1046,7 @@ static int mx3_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt) csi_reg_write(mx3_cam, sens_conf | dw, CSI_SENS_CONF); - dev_dbg(ici->dev, "Set SENS_CONF to %x\n", sens_conf | dw); + dev_dbg(icd->dev.parent, "Set SENS_CONF to %x\n", sens_conf | dw); return 0; } @@ -1145,7 +1131,7 @@ static int __devinit mx3_camera_probe(struct platform_device *pdev) soc_host->drv_name = MX3_CAM_DRV_NAME; soc_host->ops = &mx3_soc_camera_host_ops; soc_host->priv = mx3_cam; - soc_host->dev = &pdev->dev; + soc_host->v4l2_dev.dev = &pdev->dev; soc_host->nr = pdev->id; err = soc_camera_host_register(soc_host); diff --git a/linux/drivers/media/video/ov772x.c b/linux/drivers/media/video/ov772x.c index 297a46fc9..4da12e8c4 100644 --- a/linux/drivers/media/video/ov772x.c +++ b/linux/drivers/media/video/ov772x.c @@ -22,7 +22,7 @@ #include #include #include -#include +#include #include #include @@ -398,6 +398,7 @@ struct ov772x_win_size { }; struct ov772x_priv { + struct v4l2_subdev subdev; struct ov772x_camera_info *info; const struct ov772x_color_format *fmt; const struct ov772x_win_size *win; @@ -575,6 +576,11 @@ static const struct v4l2_queryctrl ov772x_controls[] = { * general function */ +static struct ov772x_priv *to_ov772x(const struct i2c_client *client) +{ + return container_of(i2c_get_clientdata(client), struct ov772x_priv, subdev); +} + static int ov772x_write_array(struct i2c_client *client, const struct regval_list *vals) { @@ -615,61 +621,29 @@ static int ov772x_reset(struct i2c_client *client) * soc_camera_ops function */ -static int ov772x_init(struct soc_camera_device *icd) +static int ov772x_s_stream(struct v4l2_subdev *sd, int enable) { - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); - struct soc_camera_link *icl = to_soc_camera_link(icd); - int ret = 0; + struct i2c_client *client = sd->priv; + struct ov772x_priv *priv = to_ov772x(client); - if (icl->power) { - ret = icl->power(&client->dev, 1); - if (ret < 0) - return ret; + if (!enable) { + ov772x_mask_set(client, COM2, SOFT_SLEEP_MODE, SOFT_SLEEP_MODE); + return 0; } - if (icl->reset) - ret = icl->reset(&client->dev); - - return ret; -} - -static int ov772x_release(struct soc_camera_device *icd) -{ - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); - struct soc_camera_link *icl = to_soc_camera_link(icd); - int ret = 0; - - if (icl->power) - ret = icl->power(&client->dev, 0); - - return ret; -} - -static int ov772x_start_capture(struct soc_camera_device *icd) -{ - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); - struct ov772x_priv *priv = i2c_get_clientdata(client); - if (!priv->win || !priv->fmt) { - dev_err(&icd->dev, "norm or win select error\n"); + dev_err(&client->dev, "norm or win select error\n"); return -EPERM; } ov772x_mask_set(client, COM2, SOFT_SLEEP_MODE, 0); - dev_dbg(&icd->dev, + dev_dbg(&client->dev, "format %s, win %s\n", priv->fmt->name, priv->win->name); return 0; } -static int ov772x_stop_capture(struct soc_camera_device *icd) -{ - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); - ov772x_mask_set(client, COM2, SOFT_SLEEP_MODE, SOFT_SLEEP_MODE); - return 0; -} - static int ov772x_set_bus_param(struct soc_camera_device *icd, unsigned long flags) { @@ -688,11 +662,10 @@ static unsigned long ov772x_query_bus_param(struct soc_camera_device *icd) return soc_camera_apply_sensor_flags(icl, flags); } -static int ov772x_get_control(struct soc_camera_device *icd, - struct v4l2_control *ctrl) +static int ov772x_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) { - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); - struct ov772x_priv *priv = i2c_get_clientdata(client); + struct i2c_client *client = sd->priv; + struct ov772x_priv *priv = to_ov772x(client); switch (ctrl->id) { case V4L2_CID_VFLIP: @@ -705,11 +678,10 @@ static int ov772x_get_control(struct soc_camera_device *icd, return 0; } -static int ov772x_set_control(struct soc_camera_device *icd, - struct v4l2_control *ctrl) +static int ov772x_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) { - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); - struct ov772x_priv *priv = i2c_get_clientdata(client); + struct i2c_client *client = sd->priv; + struct ov772x_priv *priv = to_ov772x(client); int ret = 0; u8 val; @@ -733,11 +705,11 @@ static int ov772x_set_control(struct soc_camera_device *icd, return ret; } -static int ov772x_get_chip_id(struct soc_camera_device *icd, - struct v4l2_dbg_chip_ident *id) +static int ov772x_g_chip_ident(struct v4l2_subdev *sd, + struct v4l2_dbg_chip_ident *id) { - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); - struct ov772x_priv *priv = i2c_get_clientdata(client); + struct i2c_client *client = sd->priv; + struct ov772x_priv *priv = to_ov772x(client); id->ident = priv->model; id->revision = 0; @@ -746,10 +718,10 @@ static int ov772x_get_chip_id(struct soc_camera_device *icd, } #ifdef CONFIG_VIDEO_ADV_DEBUG -static int ov772x_get_register(struct soc_camera_device *icd, - struct v4l2_dbg_register *reg) +static int ov772x_g_register(struct v4l2_subdev *sd, + struct v4l2_dbg_register *reg) { - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct i2c_client *client = sd->priv; int ret; reg->size = 1; @@ -765,10 +737,10 @@ static int ov772x_get_register(struct soc_camera_device *icd, return 0; } -static int ov772x_set_register(struct soc_camera_device *icd, - struct v4l2_dbg_register *reg) +static int ov772x_s_register(struct v4l2_subdev *sd, + struct v4l2_dbg_register *reg) { - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct i2c_client *client = sd->priv; if (reg->reg > 0xff || reg->val > 0xff) @@ -778,8 +750,7 @@ static int ov772x_set_register(struct soc_camera_device *icd, } #endif -static const struct ov772x_win_size* -ov772x_select_win(u32 width, u32 height) +static const struct ov772x_win_size *ov772x_select_win(u32 width, u32 height) { __u32 diff; const struct ov772x_win_size *win; @@ -798,11 +769,10 @@ ov772x_select_win(u32 width, u32 height) return win; } -static int ov772x_set_params(struct soc_camera_device *icd, +static int ov772x_set_params(struct i2c_client *client, u32 width, u32 height, u32 pixfmt) { - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); - struct ov772x_priv *priv = i2c_get_clientdata(client); + struct ov772x_priv *priv = to_ov772x(client); int ret = -EINVAL; u8 val; int i; @@ -817,7 +787,6 @@ static int ov772x_set_params(struct soc_camera_device *icd, break; } } - dev_dbg(&icd->dev, "Using fmt %x #%d\n", pixfmt, i); if (!priv->fmt) goto ov772x_set_fmt_error; @@ -939,26 +908,26 @@ static int ov772x_set_crop(struct soc_camera_device *icd, struct v4l2_rect *rect) { struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); - struct ov772x_priv *priv = i2c_get_clientdata(client); + struct ov772x_priv *priv = to_ov772x(client); if (!priv->fmt) return -EINVAL; - return ov772x_set_params(icd, rect->width, rect->height, + return ov772x_set_params(client, rect->width, rect->height, priv->fmt->fourcc); } -static int ov772x_set_fmt(struct soc_camera_device *icd, - struct v4l2_format *f) +static int ov772x_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) { + struct i2c_client *client = sd->priv; struct v4l2_pix_format *pix = &f->fmt.pix; - return ov772x_set_params(icd, pix->width, pix->height, + return ov772x_set_params(client, pix->width, pix->height, pix->pixelformat); } -static int ov772x_try_fmt(struct soc_camera_device *icd, - struct v4l2_format *f) +static int ov772x_try_fmt(struct v4l2_subdev *sd, + struct v4l2_format *f) { struct v4l2_pix_format *pix = &f->fmt.pix; const struct ov772x_win_size *win; @@ -978,10 +947,9 @@ static int ov772x_try_fmt(struct soc_camera_device *icd, static int ov772x_video_probe(struct soc_camera_device *icd, struct i2c_client *client) { - struct ov772x_priv *priv = i2c_get_clientdata(client); + struct ov772x_priv *priv = to_ov772x(client); u8 pid, ver; const char *devname; - int ret; /* * We must have a parent by now. And it cannot be a wrong one. @@ -1003,11 +971,6 @@ static int ov772x_video_probe(struct soc_camera_device *icd, icd->formats = ov772x_fmt_lists; icd->num_formats = ARRAY_SIZE(ov772x_fmt_lists); - /* Switch master clock on */ - ret = soc_camera_video_start(icd, &client->dev); - if (ret) - return ret; - /* * check and show product ID and manufacturer ID */ @@ -1026,8 +989,7 @@ static int ov772x_video_probe(struct soc_camera_device *icd, default: dev_err(&icd->dev, "Product ID error %x:%x\n", pid, ver); - ret = -ENODEV; - goto ever; + return -ENODEV; } dev_info(&icd->dev, @@ -1038,34 +1000,38 @@ static int ov772x_video_probe(struct soc_camera_device *icd, i2c_smbus_read_byte_data(client, MIDH), i2c_smbus_read_byte_data(client, MIDL)); - soc_camera_video_stop(icd); - -ever: - return ret; + return 0; } static struct soc_camera_ops ov772x_ops = { - .owner = THIS_MODULE, - .init = ov772x_init, - .release = ov772x_release, - .start_capture = ov772x_start_capture, - .stop_capture = ov772x_stop_capture, .set_crop = ov772x_set_crop, - .set_fmt = ov772x_set_fmt, - .try_fmt = ov772x_try_fmt, .set_bus_param = ov772x_set_bus_param, .query_bus_param = ov772x_query_bus_param, .controls = ov772x_controls, .num_controls = ARRAY_SIZE(ov772x_controls), - .get_control = ov772x_get_control, - .set_control = ov772x_set_control, - .get_chip_id = ov772x_get_chip_id, +}; + +static struct v4l2_subdev_core_ops ov772x_subdev_core_ops = { + .g_ctrl = ov772x_g_ctrl, + .s_ctrl = ov772x_s_ctrl, + .g_chip_ident = ov772x_g_chip_ident, #ifdef CONFIG_VIDEO_ADV_DEBUG - .get_register = ov772x_get_register, - .set_register = ov772x_set_register, + .g_register = ov772x_g_register, + .s_register = ov772x_s_register, #endif }; +static struct v4l2_subdev_video_ops ov772x_subdev_video_ops = { + .s_stream = ov772x_s_stream, + .s_fmt = ov772x_s_fmt, + .try_fmt = ov772x_try_fmt, +}; + +static struct v4l2_subdev_ops ov772x_subdev_ops = { + .core = &ov772x_subdev_core_ops, + .video = &ov772x_subdev_video_ops, +}; + /* * i2c_driver function */ @@ -1085,7 +1051,7 @@ static int ov772x_probe(struct i2c_client *client, int ret; if (!icd) { - dev_err(&client->dev, "MT9M001: missing soc-camera data!\n"); + dev_err(&client->dev, "OV772X: missing soc-camera data!\n"); return -EINVAL; } @@ -1106,8 +1072,9 @@ static int ov772x_probe(struct i2c_client *client, if (!priv) return -ENOMEM; - priv->info = info; - i2c_set_clientdata(client, priv); + priv->info = info; + + v4l2_i2c_subdev_init(&priv->subdev, client, &ov772x_subdev_ops); icd->ops = &ov772x_ops; icd->width_max = MAX_WIDTH; @@ -1125,7 +1092,7 @@ static int ov772x_probe(struct i2c_client *client, static int ov772x_remove(struct i2c_client *client) { - struct ov772x_priv *priv = i2c_get_clientdata(client); + struct ov772x_priv *priv = to_ov772x(client); struct soc_camera_device *icd = client->dev.platform_data; icd->ops = NULL; diff --git a/linux/drivers/media/video/pxa_camera.c b/linux/drivers/media/video/pxa_camera.c index 8b1537581..4c73b7d88 100644 --- a/linux/drivers/media/video/pxa_camera.c +++ b/linux/drivers/media/video/pxa_camera.c @@ -282,7 +282,7 @@ static void free_buffer(struct videobuf_queue *vq, struct pxa_buffer *buf) for (i = 0; i < ARRAY_SIZE(buf->dmas); i++) { if (buf->dmas[i].sg_cpu) - dma_free_coherent(ici->dev, buf->dmas[i].sg_size, + dma_free_coherent(ici->v4l2_dev.dev, buf->dmas[i].sg_size, buf->dmas[i].sg_cpu, buf->dmas[i].sg_dma); buf->dmas[i].sg_cpu = NULL; @@ -337,19 +337,20 @@ static int pxa_init_dma_channel(struct pxa_camera_dev *pcdev, struct scatterlist **sg_first, int *sg_first_ofs) { struct pxa_cam_dma *pxa_dma = &buf->dmas[channel]; + struct device *dev = pcdev->soc_host.v4l2_dev.dev; struct scatterlist *sg; int i, offset, sglen; int dma_len = 0, xfer_len = 0; if (pxa_dma->sg_cpu) - dma_free_coherent(pcdev->soc_host.dev, pxa_dma->sg_size, + dma_free_coherent(dev, pxa_dma->sg_size, pxa_dma->sg_cpu, pxa_dma->sg_dma); sglen = calculate_dma_sglen(*sg_first, dma->sglen, *sg_first_ofs, size); pxa_dma->sg_size = (sglen + 1) * sizeof(struct pxa_dma_desc); - pxa_dma->sg_cpu = dma_alloc_coherent(pcdev->soc_host.dev, pxa_dma->sg_size, + pxa_dma->sg_cpu = dma_alloc_coherent(dev, pxa_dma->sg_size, &pxa_dma->sg_dma, GFP_KERNEL); if (!pxa_dma->sg_cpu) return -ENOMEM; @@ -357,7 +358,7 @@ static int pxa_init_dma_channel(struct pxa_camera_dev *pcdev, pxa_dma->sglen = sglen; offset = *sg_first_ofs; - dev_dbg(pcdev->soc_host.dev, "DMA: sg_first=%p, sglen=%d, ofs=%d, dma.desc=%x\n", + dev_dbg(dev, "DMA: sg_first=%p, sglen=%d, ofs=%d, dma.desc=%x\n", *sg_first, sglen, *sg_first_ofs, pxa_dma->sg_dma); @@ -380,7 +381,7 @@ static int pxa_init_dma_channel(struct pxa_camera_dev *pcdev, pxa_dma->sg_cpu[i].ddadr = pxa_dma->sg_dma + (i + 1) * sizeof(struct pxa_dma_desc); - dev_vdbg(pcdev->soc_host.dev, "DMA: desc.%08x->@phys=0x%08x, len=%d\n", + dev_vdbg(dev, "DMA: desc.%08x->@phys=0x%08x, len=%d\n", pxa_dma->sg_dma + i * sizeof(struct pxa_dma_desc), sg_dma_address(sg) + offset, xfer_len); offset = 0; @@ -430,11 +431,12 @@ static int pxa_videobuf_prepare(struct videobuf_queue *vq, struct soc_camera_device *icd = vq->priv_data; struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); struct pxa_camera_dev *pcdev = ici->priv; + struct device *dev = pcdev->soc_host.v4l2_dev.dev; struct pxa_buffer *buf = container_of(vb, struct pxa_buffer, vb); int ret; int size_y, size_u = 0, size_v = 0; - dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__, + dev_dbg(dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__, vb, vb->baddr, vb->bsize); /* Added list head initialization on alloc */ @@ -492,8 +494,7 @@ static int pxa_videobuf_prepare(struct videobuf_queue *vq, ret = pxa_init_dma_channel(pcdev, buf, dma, 0, CIBR0, size_y, &sg, &next_ofs); if (ret) { - dev_err(pcdev->soc_host.dev, - "DMA initialization for Y/RGB failed\n"); + dev_err(dev, "DMA initialization for Y/RGB failed\n"); goto fail; } @@ -502,8 +503,7 @@ static int pxa_videobuf_prepare(struct videobuf_queue *vq, ret = pxa_init_dma_channel(pcdev, buf, dma, 1, CIBR1, size_u, &sg, &next_ofs); if (ret) { - dev_err(pcdev->soc_host.dev, - "DMA initialization for U failed\n"); + dev_err(dev, "DMA initialization for U failed\n"); goto fail_u; } @@ -512,8 +512,7 @@ static int pxa_videobuf_prepare(struct videobuf_queue *vq, ret = pxa_init_dma_channel(pcdev, buf, dma, 2, CIBR2, size_v, &sg, &next_ofs); if (ret) { - dev_err(pcdev->soc_host.dev, - "DMA initialization for V failed\n"); + dev_err(dev, "DMA initialization for V failed\n"); goto fail_v; } @@ -526,10 +525,10 @@ static int pxa_videobuf_prepare(struct videobuf_queue *vq, return 0; fail_v: - dma_free_coherent(pcdev->soc_host.dev, buf->dmas[1].sg_size, + dma_free_coherent(dev, buf->dmas[1].sg_size, buf->dmas[1].sg_cpu, buf->dmas[1].sg_dma); fail_u: - dma_free_coherent(pcdev->soc_host.dev, buf->dmas[0].sg_size, + dma_free_coherent(dev, buf->dmas[0].sg_size, buf->dmas[0].sg_cpu, buf->dmas[0].sg_dma); fail: free_buffer(vq, buf); @@ -553,7 +552,7 @@ static void pxa_dma_start_channels(struct pxa_camera_dev *pcdev) active = pcdev->active; for (i = 0; i < pcdev->channels; i++) { - dev_dbg(pcdev->soc_host.dev, "%s (channel=%d) ddadr=%08x\n", __func__, + dev_dbg(pcdev->soc_host.v4l2_dev.dev, "%s (channel=%d) ddadr=%08x\n", __func__, i, active->dmas[i].sg_dma); DDADR(pcdev->dma_chans[i]) = active->dmas[i].sg_dma; DCSR(pcdev->dma_chans[i]) = DCSR_RUN; @@ -565,7 +564,7 @@ static void pxa_dma_stop_channels(struct pxa_camera_dev *pcdev) int i; for (i = 0; i < pcdev->channels; i++) { - dev_dbg(pcdev->soc_host.dev, "%s (channel=%d)\n", __func__, i); + dev_dbg(pcdev->soc_host.v4l2_dev.dev, "%s (channel=%d)\n", __func__, i); DCSR(pcdev->dma_chans[i]) = 0; } } @@ -601,7 +600,7 @@ static void pxa_camera_start_capture(struct pxa_camera_dev *pcdev) { unsigned long cicr0, cifr; - dev_dbg(pcdev->soc_host.dev, "%s\n", __func__); + dev_dbg(pcdev->soc_host.v4l2_dev.dev, "%s\n", __func__); /* Reset the FIFOs */ cifr = __raw_readl(pcdev->base + CIFR) | CIFR_RESET_F; __raw_writel(cifr, pcdev->base + CIFR); @@ -621,7 +620,7 @@ static void pxa_camera_stop_capture(struct pxa_camera_dev *pcdev) __raw_writel(cicr0, pcdev->base + CICR0); pcdev->active = NULL; - dev_dbg(pcdev->soc_host.dev, "%s\n", __func__); + dev_dbg(pcdev->soc_host.v4l2_dev.dev, "%s\n", __func__); } /* Called under spinlock_irqsave(&pcdev->lock, ...) */ @@ -686,7 +685,8 @@ static void pxa_camera_wakeup(struct pxa_camera_dev *pcdev, do_gettimeofday(&vb->ts); vb->field_count++; wake_up(&vb->done); - dev_dbg(pcdev->soc_host.dev, "%s dequeud buffer (vb=0x%p)\n", __func__, vb); + dev_dbg(pcdev->soc_host.v4l2_dev.dev, "%s dequeud buffer (vb=0x%p)\n", + __func__, vb); if (list_empty(&pcdev->capture)) { pxa_camera_stop_capture(pcdev); @@ -722,7 +722,8 @@ static void pxa_camera_check_link_miss(struct pxa_camera_dev *pcdev) for (i = 0; i < pcdev->channels; i++) if (DDADR(pcdev->dma_chans[i]) != DDADR_STOP) is_dma_stopped = 0; - dev_dbg(pcdev->soc_host.dev, "%s : top queued buffer=%p, dma_stopped=%d\n", + dev_dbg(pcdev->soc_host.v4l2_dev.dev, + "%s : top queued buffer=%p, dma_stopped=%d\n", __func__, pcdev->active, is_dma_stopped); if (pcdev->active && is_dma_stopped) pxa_camera_start_capture(pcdev); @@ -731,6 +732,7 @@ static void pxa_camera_check_link_miss(struct pxa_camera_dev *pcdev) static void pxa_camera_dma_irq(int channel, struct pxa_camera_dev *pcdev, enum pxa_camera_active_dma act_dma) { + struct device *dev = pcdev->soc_host.v4l2_dev.dev; struct pxa_buffer *buf; unsigned long flags; u32 status, camera_status, overrun; @@ -747,13 +749,13 @@ static void pxa_camera_dma_irq(int channel, struct pxa_camera_dev *pcdev, overrun |= CISR_IFO_1 | CISR_IFO_2; if (status & DCSR_BUSERR) { - dev_err(pcdev->soc_host.dev, "DMA Bus Error IRQ!\n"); + dev_err(dev, "DMA Bus Error IRQ!\n"); goto out; } if (!(status & (DCSR_ENDINTR | DCSR_STARTINTR))) { - dev_err(pcdev->soc_host.dev, "Unknown DMA IRQ source, " - "status: 0x%08x\n", status); + dev_err(dev, "Unknown DMA IRQ source, status: 0x%08x\n", + status); goto out; } @@ -776,7 +778,7 @@ static void pxa_camera_dma_irq(int channel, struct pxa_camera_dev *pcdev, buf = container_of(vb, struct pxa_buffer, vb); WARN_ON(buf->inwork || list_empty(&vb->queue)); - dev_dbg(pcdev->soc_host.dev, "%s channel=%d %s%s(vb=0x%p) dma.desc=%x\n", + dev_dbg(dev, "%s channel=%d %s%s(vb=0x%p) dma.desc=%x\n", __func__, channel, status & DCSR_STARTINTR ? "SOF " : "", status & DCSR_ENDINTR ? "EOF " : "", vb, DDADR(channel)); @@ -787,7 +789,7 @@ static void pxa_camera_dma_irq(int channel, struct pxa_camera_dev *pcdev, */ if (camera_status & overrun && !list_is_last(pcdev->capture.next, &pcdev->capture)) { - dev_dbg(pcdev->soc_host.dev, "FIFO overrun! CISR: %x\n", + dev_dbg(dev, "FIFO overrun! CISR: %x\n", camera_status); pxa_camera_stop_capture(pcdev); pxa_camera_start_capture(pcdev); @@ -846,6 +848,7 @@ static u32 mclk_get_divisor(struct platform_device *pdev, struct pxa_camera_dev *pcdev) { unsigned long mclk = pcdev->mclk; + struct device *dev = pcdev->soc_host.v4l2_dev.dev; u32 div; unsigned long lcdclk; @@ -855,7 +858,7 @@ static u32 mclk_get_divisor(struct platform_device *pdev, /* mclk <= ciclk / 4 (27.4.2) */ if (mclk > lcdclk / 4) { mclk = lcdclk / 4; - dev_warn(&pdev->dev, "Limiting master clock to %lu\n", mclk); + dev_warn(dev, "Limiting master clock to %lu\n", mclk); } /* We verify mclk != 0, so if anyone breaks it, here comes their Oops */ @@ -865,7 +868,7 @@ static u32 mclk_get_divisor(struct platform_device *pdev, if (pcdev->platform_flags & PXA_CAMERA_MCLK_EN) pcdev->mclk = lcdclk / (2 * (div + 1)); - dev_dbg(&pdev->dev, "LCD clock %luHz, target freq %luHz, divisor %u\n", + dev_dbg(dev, "LCD clock %luHz, target freq %luHz, divisor %u\n", lcdclk, mclk, div); return div; @@ -883,14 +886,15 @@ static void recalculate_fifo_timeout(struct pxa_camera_dev *pcdev, static void pxa_camera_activate(struct pxa_camera_dev *pcdev) { struct pxacamera_platform_data *pdata = pcdev->pdata; + struct device *dev = pcdev->soc_host.v4l2_dev.dev; u32 cicr4 = 0; - dev_dbg(pcdev->soc_host.dev, "Registered platform device at %p data %p\n", + dev_dbg(dev, "Registered platform device at %p data %p\n", pcdev, pdata); if (pdata && pdata->init) { - dev_dbg(pcdev->soc_host.dev, "%s: Init gpios\n", __func__); - pdata->init(pcdev->soc_host.dev); + dev_dbg(dev, "%s: Init gpios\n", __func__); + pdata->init(dev); } /* disable all interrupts */ @@ -932,7 +936,7 @@ static irqreturn_t pxa_camera_irq(int irq, void *data) struct videobuf_buffer *vb; status = __raw_readl(pcdev->base + CISR); - dev_dbg(pcdev->soc_host.dev, "Camera interrupt status 0x%lx\n", status); + dev_dbg(pcdev->soc_host.v4l2_dev.dev, "Camera interrupt status 0x%lx\n", status); if (!status) return IRQ_NONE; @@ -964,17 +968,11 @@ static int pxa_camera_add_device(struct soc_camera_device *icd) { struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); struct pxa_camera_dev *pcdev = ici->priv; - int ret; - if (pcdev->icd) { - ret = -EBUSY; - goto ebusy; - } + if (pcdev->icd) + return -EBUSY; pxa_camera_activate(pcdev); - ret = icd->ops->init(icd); - if (ret < 0) - goto einit; pcdev->icd = icd; @@ -982,11 +980,6 @@ static int pxa_camera_add_device(struct soc_camera_device *icd) icd->devnum); return 0; - -einit: - pxa_camera_deactivate(pcdev); -ebusy: - return ret; } /* Called with .video_lock held */ @@ -1008,8 +1001,6 @@ static void pxa_camera_remove_device(struct soc_camera_device *icd) DCSR(pcdev->dma_chans[1]) = 0; DCSR(pcdev->dma_chans[2]) = 0; - icd->ops->release(icd); - pxa_camera_deactivate(pcdev); pcdev->icd = NULL; @@ -1265,7 +1256,7 @@ static int pxa_camera_get_formats(struct soc_camera_device *icd, int idx, xlate->cam_fmt = icd->formats + idx; xlate->buswidth = buswidth; xlate++; - dev_dbg(ici->dev, "Providing format %s using %s\n", + dev_dbg(ici->v4l2_dev.dev, "Providing format %s using %s\n", pxa_camera_formats[0].name, icd->formats[idx].name); } @@ -1280,7 +1271,7 @@ static int pxa_camera_get_formats(struct soc_camera_device *icd, int idx, xlate->cam_fmt = icd->formats + idx; xlate->buswidth = buswidth; xlate++; - dev_dbg(ici->dev, "Providing format %s packed\n", + dev_dbg(ici->v4l2_dev.dev, "Providing format %s packed\n", icd->formats[idx].name); } break; @@ -1292,7 +1283,7 @@ static int pxa_camera_get_formats(struct soc_camera_device *icd, int idx, xlate->cam_fmt = icd->formats + idx; xlate->buswidth = icd->formats[idx].depth; xlate++; - dev_dbg(ici->dev, + dev_dbg(ici->v4l2_dev.dev, "Providing format %s in pass-through mode\n", icd->formats[idx].name); } @@ -1321,11 +1312,11 @@ static int pxa_camera_set_crop(struct soc_camera_device *icd, icd->sense = NULL; if (ret < 0) { - dev_warn(ici->dev, "Failed to crop to %ux%u@%u:%u\n", + dev_warn(ici->v4l2_dev.dev, "Failed to crop to %ux%u@%u:%u\n", rect->width, rect->height, rect->left, rect->top); } else if (sense.flags & SOCAM_SENSE_PCLK_CHANGED) { if (sense.pixel_clock > sense.pixel_clock_max) { - dev_err(ici->dev, + dev_err(ici->v4l2_dev.dev, "pixel clock %lu set by the camera too high!", sense.pixel_clock); return -EIO; @@ -1353,7 +1344,7 @@ static int pxa_camera_set_fmt(struct soc_camera_device *icd, xlate = soc_camera_xlate_by_fourcc(icd, pix->pixelformat); if (!xlate) { - dev_warn(ici->dev, "Format %x not found\n", pix->pixelformat); + dev_warn(ici->v4l2_dev.dev, "Format %x not found\n", pix->pixelformat); return -EINVAL; } @@ -1364,16 +1355,16 @@ static int pxa_camera_set_fmt(struct soc_camera_device *icd, icd->sense = &sense; cam_f.fmt.pix.pixelformat = cam_fmt->fourcc; - ret = icd->ops->set_fmt(icd, &cam_f); + ret = v4l2_device_call_until_err(&ici->v4l2_dev, 0, video, s_fmt, f); icd->sense = NULL; if (ret < 0) { - dev_warn(ici->dev, "Failed to configure for format %x\n", + dev_warn(ici->v4l2_dev.dev, "Failed to configure for format %x\n", pix->pixelformat); } else if (sense.flags & SOCAM_SENSE_PCLK_CHANGED) { if (sense.pixel_clock > sense.pixel_clock_max) { - dev_err(ici->dev, + dev_err(ici->v4l2_dev.dev, "pixel clock %lu set by the camera too high!", sense.pixel_clock); return -EIO; @@ -1401,7 +1392,7 @@ static int pxa_camera_try_fmt(struct soc_camera_device *icd, xlate = soc_camera_xlate_by_fourcc(icd, pixfmt); if (!xlate) { - dev_warn(ici->dev, "Format %x not found\n", pixfmt); + dev_warn(ici->v4l2_dev.dev, "Format %x not found\n", pixfmt); return -EINVAL; } @@ -1422,7 +1413,7 @@ static int pxa_camera_try_fmt(struct soc_camera_device *icd, /* camera has to see its format, but the user the original one */ pix->pixelformat = xlate->cam_fmt->fourcc; /* limit to sensor capabilities */ - ret = icd->ops->try_fmt(icd, f); + ret = v4l2_device_call_until_err(&ici->v4l2_dev, 0, video, try_fmt, f); pix->pixelformat = xlate->host_fmt->fourcc; field = pix->field; @@ -1658,7 +1649,7 @@ static int __devinit pxa_camera_probe(struct platform_device *pdev) pcdev->soc_host.drv_name = PXA_CAM_DRV_NAME; pcdev->soc_host.ops = &pxa_soc_camera_host_ops; pcdev->soc_host.priv = pcdev; - pcdev->soc_host.dev = &pdev->dev; + pcdev->soc_host.v4l2_dev.dev = &pdev->dev; pcdev->soc_host.nr = pdev->id; err = soc_camera_host_register(&pcdev->soc_host); diff --git a/linux/drivers/media/video/sh_mobile_ceu_camera.c b/linux/drivers/media/video/sh_mobile_ceu_camera.c index f8e4b5481..f1ab7b690 100644 --- a/linux/drivers/media/video/sh_mobile_ceu_camera.c +++ b/linux/drivers/media/video/sh_mobile_ceu_camera.c @@ -349,10 +349,9 @@ static int sh_mobile_ceu_add_device(struct soc_camera_device *icd) { struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); struct sh_mobile_ceu_dev *pcdev = ici->priv; - int ret = -EBUSY; if (pcdev->icd) - goto err; + return -EBUSY; dev_info(&icd->dev, "SuperH Mobile CEU driver attached to camera %d\n", @@ -360,19 +359,13 @@ static int sh_mobile_ceu_add_device(struct soc_camera_device *icd) clk_enable(pcdev->clk); - ret = icd->ops->init(icd); - if (ret) { - clk_disable(pcdev->clk); - goto err; - } - ceu_write(pcdev, CAPSR, 1 << 16); /* reset */ while (ceu_read(pcdev, CSTSR) & 1) msleep(1); pcdev->icd = icd; -err: - return ret; + + return 0; } /* Called with .video_lock held */ @@ -398,8 +391,6 @@ static void sh_mobile_ceu_remove_device(struct soc_camera_device *icd) } spin_unlock_irqrestore(&pcdev->lock, flags); - icd->ops->release(icd); - clk_disable(pcdev->clk); dev_info(&icd->dev, @@ -616,7 +607,7 @@ static int sh_mobile_ceu_get_formats(struct soc_camera_device *icd, int idx, xlate->cam_fmt = icd->formats + idx; xlate->buswidth = icd->formats[idx].depth; xlate++; - dev_dbg(ici->dev, "Providing format %s using %s\n", + dev_dbg(ici->v4l2_dev.dev, "Providing format %s using %s\n", sh_mobile_ceu_formats[k].name, icd->formats[idx].name); } @@ -629,7 +620,7 @@ add_single_format: xlate->cam_fmt = icd->formats + idx; xlate->buswidth = icd->formats[idx].depth; xlate++; - dev_dbg(ici->dev, + dev_dbg(ici->v4l2_dev.dev, "Providing format %s in pass-through mode\n", icd->formats[idx].name); } @@ -651,18 +642,17 @@ static int sh_mobile_ceu_set_fmt(struct soc_camera_device *icd, struct sh_mobile_ceu_dev *pcdev = ici->priv; __u32 pixfmt = f->fmt.pix.pixelformat; const struct soc_camera_format_xlate *xlate; - struct v4l2_format cam_f = *f; int ret; xlate = soc_camera_xlate_by_fourcc(icd, pixfmt); if (!xlate) { - dev_warn(ici->dev, "Format %x not found\n", pixfmt); + dev_warn(ici->v4l2_dev.dev, "Format %x not found\n", pixfmt); return -EINVAL; } - cam_f.fmt.pix.pixelformat = xlate->cam_fmt->fourcc; - ret = icd->ops->set_fmt(icd, &cam_f); - + f->fmt.pix.pixelformat = xlate->cam_fmt->fourcc; + ret = v4l2_device_call_until_err(&ici->v4l2_dev, (__u32)icd, video, s_fmt, f); + f->fmt.pix.pixelformat = pixfmt; if (!ret) { icd->buswidth = xlate->buswidth; icd->current_fmt = xlate->host_fmt; @@ -683,7 +673,7 @@ static int sh_mobile_ceu_try_fmt(struct soc_camera_device *icd, xlate = soc_camera_xlate_by_fourcc(icd, pixfmt); if (!xlate) { - dev_warn(ici->dev, "Format %x not found\n", pixfmt); + dev_warn(ici->v4l2_dev.dev, "Format %x not found\n", pixfmt); return -EINVAL; } @@ -696,8 +686,11 @@ static int sh_mobile_ceu_try_fmt(struct soc_camera_device *icd, DIV_ROUND_UP(xlate->host_fmt->depth, 8); f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline; + f->fmt.pix.pixelformat = xlate->cam_fmt->fourcc; + /* limit to sensor capabilities */ - ret = icd->ops->try_fmt(icd, f); + ret = v4l2_device_call_until_err(&ici->v4l2_dev, (__u32)icd, video, try_fmt, f); + f->fmt.pix.pixelformat = pixfmt; if (ret < 0) return ret; @@ -773,7 +766,7 @@ static void sh_mobile_ceu_init_videobuf(struct videobuf_queue *q, videobuf_queue_dma_contig_init(q, &sh_mobile_ceu_videobuf_ops, - ici->dev, &pcdev->lock, + ici->v4l2_dev.dev, &pcdev->lock, V4L2_BUF_TYPE_VIDEO_CAPTURE, pcdev->is_interlaced ? V4L2_FIELD_INTERLACED : V4L2_FIELD_NONE, @@ -796,7 +789,7 @@ static struct soc_camera_host_ops sh_mobile_ceu_host_ops = { .init_videobuf = sh_mobile_ceu_init_videobuf, }; -static int sh_mobile_ceu_probe(struct platform_device *pdev) +static int __devinit sh_mobile_ceu_probe(struct platform_device *pdev) { struct sh_mobile_ceu_dev *pcdev; struct resource *res; @@ -874,7 +867,7 @@ static int sh_mobile_ceu_probe(struct platform_device *pdev) } pcdev->ici.priv = pcdev; - pcdev->ici.dev = &pdev->dev; + pcdev->ici.v4l2_dev.dev = &pdev->dev; pcdev->ici.nr = pdev->id; pcdev->ici.drv_name = dev_name(&pdev->dev); pcdev->ici.ops = &sh_mobile_ceu_host_ops; @@ -900,7 +893,7 @@ exit: return err; } -static int sh_mobile_ceu_remove(struct platform_device *pdev) +static int __devexit sh_mobile_ceu_remove(struct platform_device *pdev) { struct soc_camera_host *soc_host = to_soc_camera_host(&pdev->dev); struct sh_mobile_ceu_dev *pcdev = container_of(soc_host, @@ -921,7 +914,7 @@ static struct platform_driver sh_mobile_ceu_driver = { .name = "sh_mobile_ceu", }, .probe = sh_mobile_ceu_probe, - .remove = sh_mobile_ceu_remove, + .remove = __exit_p(sh_mobile_ceu_remove), }; static int __init sh_mobile_ceu_init(void) diff --git a/linux/drivers/media/video/soc_camera.c b/linux/drivers/media/video/soc_camera.c index f248ae27f..e759400cc 100644 --- a/linux/drivers/media/video/soc_camera.c +++ b/linux/drivers/media/video/soc_camera.c @@ -171,8 +171,6 @@ static int soc_camera_reqbufs(struct file *file, void *priv, WARN_ON(priv != file->private_data); - dev_dbg(&icd->dev, "%s: %d\n", __func__, p->memory); - ret = videobuf_reqbufs(&icf->vb_vidq, p); if (ret < 0) return ret; @@ -286,7 +284,7 @@ static int soc_camera_set_fmt(struct soc_camera_file *icf, return ret; } else if (!icd->current_fmt || icd->current_fmt->fourcc != pix->pixelformat) { - dev_err(ici->dev, + dev_err(ici->v4l2_dev.dev, "Host driver hasn't set up current format correctly!\n"); return -EINVAL; } @@ -309,20 +307,13 @@ static int soc_camera_set_fmt(struct soc_camera_file *icf, static int soc_camera_open(struct file *file) { - struct video_device *vdev; - struct soc_camera_device *icd; + struct video_device *vdev = video_devdata(file); + struct soc_camera_device *icd = container_of(vdev->parent, struct soc_camera_device, dev); + struct soc_camera_link *icl = to_soc_camera_link(icd); struct soc_camera_host *ici; struct soc_camera_file *icf; int ret; - /* - * It is safe to dereference these pointers now as long as a user has - * the video device open - we are protected by the held cdev reference. - */ - - vdev = video_devdata(file); - icd = container_of(vdev->parent, struct soc_camera_device, dev); - if (!icd->ops) /* No device driver attached */ return -ENODEV; @@ -333,12 +324,6 @@ static int soc_camera_open(struct file *file) if (!icf) return -ENOMEM; - if (!try_module_get(icd->ops->owner)) { - dev_err(&icd->dev, "Couldn't lock sensor driver.\n"); - ret = -EINVAL; - goto emgd; - } - if (!try_module_get(ici->ops->owner)) { dev_err(&icd->dev, "Couldn't lock capture bus driver.\n"); ret = -EINVAL; @@ -367,47 +352,65 @@ static int soc_camera_open(struct file *file) if (ret < 0) goto eiufmt; - dev_dbg(&icd->dev, "Using fmt %x\n", icd->current_fmt->fourcc); - f.fmt.pix.pixelformat = icd->current_fmt->fourcc; f.fmt.pix.colorspace = icd->current_fmt->colorspace; + if (icl->power) { + ret = icl->power(icd->pdev, 1); + if (ret < 0) + goto epower; + } + + /* The camera could have been already on, try to reset */ + if (icl->reset) + icl->reset(icd->pdev); + ret = ici->ops->add(icd); if (ret < 0) { dev_err(&icd->dev, "Couldn't activate the camera: %d\n", ret); goto eiciadd; } + if (icd->ops->init) { + ret = icd->ops->init(icd); + if (ret < 0) + goto einit; + } + /* Try to configure with default parameters */ ret = soc_camera_set_fmt(icf, &f); if (ret < 0) goto esfmt; } - mutex_unlock(&icd->video_lock); - file->private_data = icf; dev_dbg(&icd->dev, "camera device open\n"); ici->ops->init_videobuf(&icf->vb_vidq, icd); + mutex_unlock(&icd->video_lock); + return 0; /* - * First three errors are entered with the .video_lock held + * First five errors are entered with the .video_lock held * and use_count == 1 */ esfmt: + if (icd->ops->release) + icd->ops->release(icd); +einit: ici->ops->remove(icd); eiciadd: + if (icl->power) + icl->power(icd->pdev, 0); +epower: soc_camera_free_user_formats(icd); eiufmt: icd->use_count--; mutex_unlock(&icd->video_lock); module_put(ici->ops->owner); emgi: - module_put(icd->ops->owner); -emgd: vfree(icf); return ret; } @@ -422,13 +425,18 @@ static int soc_camera_close(struct file *file) mutex_lock(&icd->video_lock); icd->use_count--; if (!icd->use_count) { + struct soc_camera_link *icl = to_soc_camera_link(icd); + + if (icd->ops->release) + icd->ops->release(icd); ici->ops->remove(icd); + if (icl->power) + icl->power(icd->pdev, 0); soc_camera_free_user_formats(icd); } mutex_unlock(&icd->video_lock); - module_put(icd->ops->owner); module_put(ici->ops->owner); vfree(icf); @@ -576,18 +584,17 @@ static int soc_camera_streamon(struct file *file, void *priv, { struct soc_camera_file *icf = file->private_data; struct soc_camera_device *icd = icf->icd; + struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); int ret; WARN_ON(priv != file->private_data); - dev_dbg(&icd->dev, "%s\n", __func__); - if (i != V4L2_BUF_TYPE_VIDEO_CAPTURE) return -EINVAL; mutex_lock(&icd->video_lock); - icd->ops->start_capture(icd); + v4l2_device_call_until_err(&ici->v4l2_dev, (__u32)icd, video, s_stream, 1); /* This calls buf_queue from host driver's videobuf_queue_ops */ ret = videobuf_streamon(&icf->vb_vidq); @@ -602,11 +609,10 @@ static int soc_camera_streamoff(struct file *file, void *priv, { struct soc_camera_file *icf = file->private_data; struct soc_camera_device *icd = icf->icd; + struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); WARN_ON(priv != file->private_data); - dev_dbg(&icd->dev, "%s\n", __func__); - if (i != V4L2_BUF_TYPE_VIDEO_CAPTURE) return -EINVAL; @@ -616,7 +622,7 @@ static int soc_camera_streamoff(struct file *file, void *priv, * remaining buffers. When the last buffer is freed, stop capture */ videobuf_streamoff(&icf->vb_vidq); - icd->ops->stop_capture(icd); + v4l2_device_call_until_err(&ici->v4l2_dev, (__u32)icd, video, s_stream, 0); mutex_unlock(&icd->video_lock); @@ -650,6 +656,7 @@ static int soc_camera_g_ctrl(struct file *file, void *priv, { struct soc_camera_file *icf = file->private_data; struct soc_camera_device *icd = icf->icd; + struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); WARN_ON(priv != file->private_data); @@ -666,9 +673,7 @@ static int soc_camera_g_ctrl(struct file *file, void *priv, return 0; } - if (icd->ops->get_control) - return icd->ops->get_control(icd, ctrl); - return -EINVAL; + return v4l2_device_call_until_err(&ici->v4l2_dev, (__u32)icd, core, g_ctrl, ctrl); } static int soc_camera_s_ctrl(struct file *file, void *priv, @@ -676,12 +681,11 @@ static int soc_camera_s_ctrl(struct file *file, void *priv, { struct soc_camera_file *icf = file->private_data; struct soc_camera_device *icd = icf->icd; + struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); WARN_ON(priv != file->private_data); - if (icd->ops->set_control) - return icd->ops->set_control(icd, ctrl); - return -EINVAL; + return v4l2_device_call_until_err(&ici->v4l2_dev, (__u32)icd, core, s_ctrl, ctrl); } static int soc_camera_cropcap(struct file *file, void *fh, @@ -752,11 +756,9 @@ static int soc_camera_g_chip_ident(struct file *file, void *fh, { struct soc_camera_file *icf = file->private_data; struct soc_camera_device *icd = icf->icd; + struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); - if (!icd->ops->get_chip_id) - return -EINVAL; - - return icd->ops->get_chip_id(icd, id); + return v4l2_device_call_until_err(&ici->v4l2_dev, (__u32)icd, core, g_chip_ident, id); } #ifdef CONFIG_VIDEO_ADV_DEBUG @@ -765,11 +767,9 @@ static int soc_camera_g_register(struct file *file, void *fh, { struct soc_camera_file *icf = file->private_data; struct soc_camera_device *icd = icf->icd; + struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); - if (!icd->ops->get_register) - return -EINVAL; - - return icd->ops->get_register(icd, reg); + return v4l2_device_call_until_err(&ici->v4l2_dev, (__u32)icd, core, g_register, reg); } static int soc_camera_s_register(struct file *file, void *fh, @@ -777,11 +777,9 @@ static int soc_camera_s_register(struct file *file, void *fh, { struct soc_camera_file *icf = file->private_data; struct soc_camera_device *icd = icf->icd; + struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); - if (!icd->ops->set_register) - return -EINVAL; - - return icd->ops->set_register(icd, reg); + return v4l2_device_call_until_err(&ici->v4l2_dev, (__u32)icd, core, s_register, reg); } #endif @@ -795,7 +793,7 @@ static void scan_add_host(struct soc_camera_host *ici) list_for_each_entry(icd, &devices, list) { if (icd->iface == ici->nr) { int ret; - icd->dev.parent = ici->dev; + icd->dev.parent = ici->v4l2_dev.dev; dev_set_name(&icd->dev, "%u-%u", icd->iface, icd->devnum); ret = device_register(&icd->dev); @@ -815,7 +813,9 @@ static int soc_camera_init_i2c(struct soc_camera_device *icd, struct soc_camera_link *icl) { struct i2c_client *client; + struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); struct i2c_adapter *adap = i2c_get_adapter(icl->i2c_adapter_id); + struct v4l2_subdev *subdev; int ret; if (!adap) { @@ -827,17 +827,16 @@ static int soc_camera_init_i2c(struct soc_camera_device *icd, icl->board_info->platform_data = icd; - client = i2c_new_device(adap, icl->board_info); - if (!client) { + subdev = v4l2_i2c_new_subdev_board(&ici->v4l2_dev, adap, + icl->module_name, icl->board_info, NULL); + if (!subdev) { ret = -ENOMEM; goto ei2cnd; } - /* - * We set icd drvdata at two locations - here and in - * soc_camera_video_start(). Depending on the module loading / - * initialisation order one of these locations will be entered first - */ + subdev->grp_id = (__u32)icd; + client = subdev->priv; + /* Use to_i2c_client(dev) to recover the i2c client */ dev_set_drvdata(&icd->dev, &client->dev); @@ -853,6 +852,7 @@ static void soc_camera_free_i2c(struct soc_camera_device *icd) struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); dev_set_drvdata(&icd->dev, NULL); + v4l2_device_unregister_subdev(i2c_get_clientdata(client)); i2c_unregister_device(client); i2c_put_adapter(client->adapter); } @@ -861,16 +861,37 @@ static void soc_camera_free_i2c(struct soc_camera_device *icd) #define soc_camera_free_i2c(icd) do {} while (0) #endif +static int soc_camera_video_start(struct soc_camera_device *icd); static int video_dev_create(struct soc_camera_device *icd); /* Called during host-driver probe */ static int soc_camera_probe(struct device *dev) { struct soc_camera_device *icd = to_soc_camera_dev(dev); + struct soc_camera_host *ici = to_soc_camera_host(dev->parent); struct soc_camera_link *icl = to_soc_camera_link(icd); + struct device *control = NULL; int ret; dev_info(dev, "Probing %s\n", dev_name(dev)); + if (icl->power) { + ret = icl->power(icd->pdev, 1); + if (ret < 0) { + dev_err(dev, + "Platform failed to power-on the camera.\n"); + goto epower; + } + } + + /* The camera could have been already on, try to reset */ + if (icl->reset) + icl->reset(icd->pdev); + + ret = ici->ops->add(icd); + if (ret < 0) + goto eadd; + + /* Must have icd->vdev before registering the device */ ret = video_dev_create(icd); if (ret < 0) goto evdc; @@ -884,34 +905,61 @@ static int soc_camera_probe(struct device *dev) ret = -EINVAL; goto eadddev; } else { + if (icl->module_name) + ret = request_module(icl->module_name); + ret = icl->add_device(icl, &icd->dev); if (ret < 0) goto eadddev; - } - ret = video_register_device(icd->vdev, VFL_TYPE_GRABBER, icd->vdev->minor); - if (ret < 0) { - dev_err(&icd->dev, "video_register_device failed: %d\n", ret); - goto evidregd; + /* FIXME: this is racy, have to use driver-binding notification */ + control = to_soc_camera_control(icd); + if (!control || !control->driver || + !try_module_get(control->driver->owner)) { + icl->del_device(icl); + goto enodrv; + } } + /* ..._video_start() will create a device node, so we have to protect */ + mutex_lock(&icd->video_lock); + + ret = soc_camera_video_start(icd); + if (ret < 0) + goto evidstart; + /* Do we have to sysfs_remove_link() before device_unregister()? */ if (to_soc_camera_control(icd) && sysfs_create_link(&icd->dev.kobj, &to_soc_camera_control(icd)->kobj, "control")) dev_warn(&icd->dev, "Failed creating the control symlink\n"); + ici->ops->remove(icd); + + if (icl->power) + icl->power(icd->pdev, 0); + + mutex_unlock(&icd->video_lock); return 0; -evidregd: - if (icl->board_info) +evidstart: + mutex_unlock(&icd->video_lock); + if (icl->board_info) { soc_camera_free_i2c(icd); - else + } else { icl->del_device(icl); + module_put(control->driver->owner); + } +enodrv: eadddev: video_device_release(icd->vdev); evdc: + ici->ops->remove(icd); +eadd: + if (icl->power) + icl->power(icd->pdev, 0); +epower: return ret; } @@ -932,10 +980,16 @@ static int soc_camera_remove(struct device *dev) mutex_unlock(&icd->video_lock); } - if (icl->board_info) + if (icl->board_info) { soc_camera_free_i2c(icd); - else - icl->del_device(icl); + } else { + struct device_driver *drv = to_soc_camera_control(icd) ? + to_soc_camera_control(icd)->driver : NULL; + if (drv) { + icl->del_device(icl); + module_put(drv->owner); + } + } return 0; } @@ -985,6 +1039,7 @@ static void dummy_release(struct device *dev) int soc_camera_host_register(struct soc_camera_host *ici) { struct soc_camera_host *ix; + int ret; if (!ici || !ici->ops || !ici->ops->try_fmt || @@ -997,18 +1052,20 @@ int soc_camera_host_register(struct soc_camera_host *ici) !ici->ops->add || !ici->ops->remove || !ici->ops->poll || - !ici->dev) + !ici->v4l2_dev.dev) return -EINVAL; mutex_lock(&list_lock); list_for_each_entry(ix, &hosts, list) { if (ix->nr == ici->nr) { - mutex_unlock(&list_lock); - return -EBUSY; + ret = -EBUSY; + goto edevreg; } } - dev_set_drvdata(ici->dev, ici); + ret = v4l2_device_register(ici->v4l2_dev.dev, &ici->v4l2_dev); + if (ret < 0) + goto edevreg; list_add_tail(&ici->list, &hosts); mutex_unlock(&list_lock); @@ -1016,6 +1073,10 @@ int soc_camera_host_register(struct soc_camera_host *ici) scan_add_host(ici); return 0; + +edevreg: + mutex_unlock(&list_lock); + return ret; } EXPORT_SYMBOL(soc_camera_host_register); @@ -1029,7 +1090,7 @@ void soc_camera_host_unregister(struct soc_camera_host *ici) list_del(&ici->list); list_for_each_entry(icd, &devices, list) { - if (icd->dev.parent == ici->dev) { + if (icd->iface == ici->nr) { /* The bus->remove will be called */ device_unregister(&icd->dev); /* Not before device_unregister(), .remove @@ -1044,7 +1105,7 @@ void soc_camera_host_unregister(struct soc_camera_host *ici) mutex_unlock(&list_lock); - dev_set_drvdata(ici->dev, NULL); + v4l2_device_unregister(&ici->v4l2_dev); } EXPORT_SYMBOL(soc_camera_host_unregister); @@ -1124,7 +1185,6 @@ static int video_dev_create(struct soc_camera_device *icd) if (!vdev) return -ENOMEM; - dev_dbg(ici->dev, "Allocated video_device %p\n", vdev); strlcpy(vdev->name, ici->drv_name, sizeof(vdev->name)); @@ -1142,50 +1202,35 @@ static int video_dev_create(struct soc_camera_device *icd) } /* - * Usually called from the struct soc_camera_ops .probe() method, i.e., from - * soc_camera_probe() above with .video_lock held + * Called from soc_camera_probe() above (with .video_lock held???) */ -int soc_camera_video_start(struct soc_camera_device *icd, struct device *dev) +static int soc_camera_video_start(struct soc_camera_device *icd) { - struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); const struct v4l2_queryctrl *qctrl; + int ret; if (!icd->dev.parent) return -ENODEV; if (!icd->ops || - !icd->ops->init || - !icd->ops->release || - !icd->ops->start_capture || - !icd->ops->stop_capture || - !icd->ops->set_fmt || - !icd->ops->try_fmt || !icd->ops->query_bus_param || !icd->ops->set_bus_param) return -EINVAL; - /* See comment in soc_camera_probe() */ - dev_set_drvdata(&icd->dev, dev); + ret = video_register_device(icd->vdev, VFL_TYPE_GRABBER, + icd->vdev->minor); + if (ret < 0) { + dev_err(&icd->dev, "video_register_device failed: %d\n", ret); + return ret; + } qctrl = soc_camera_find_qctrl(icd->ops, V4L2_CID_GAIN); icd->gain = qctrl ? qctrl->default_value : (unsigned short)~0; qctrl = soc_camera_find_qctrl(icd->ops, V4L2_CID_EXPOSURE); icd->exposure = qctrl ? qctrl->default_value : (unsigned short)~0; - return ici->ops->add(icd); -} -EXPORT_SYMBOL(soc_camera_video_start); - -/* Called from client .remove() methods with .video_lock held */ -void soc_camera_video_stop(struct soc_camera_device *icd) -{ - struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); - - dev_dbg(&icd->dev, "%s\n", __func__); - - ici->ops->remove(icd); + return 0; } -EXPORT_SYMBOL(soc_camera_video_stop); static int __devinit soc_camera_pdrv_probe(struct platform_device *pdev) { @@ -1201,6 +1246,7 @@ static int __devinit soc_camera_pdrv_probe(struct platform_device *pdev) return -ENOMEM; icd->iface = icl->bus_id; + icd->pdev = &pdev->dev; platform_set_drvdata(pdev, icd); icd->dev.platform_data = icl; diff --git a/linux/drivers/media/video/soc_camera_platform.c b/linux/drivers/media/video/soc_camera_platform.c index d84c134f8..8168cf470 100644 --- a/linux/drivers/media/video/soc_camera_platform.c +++ b/linux/drivers/media/video/soc_camera_platform.c @@ -16,11 +16,12 @@ #include #include #include -#include +#include #include #include struct soc_camera_platform_priv { + struct v4l2_subdev subdev; struct soc_camera_data_format format; }; @@ -31,36 +32,10 @@ soc_camera_platform_get_info(struct soc_camera_device *icd) return pdev->dev.platform_data; } -static int soc_camera_platform_init(struct soc_camera_device *icd) +static int soc_camera_platform_s_stream(struct v4l2_subdev *sd, int enable) { - struct soc_camera_link *icl = to_soc_camera_link(icd); - - if (icl->power) - icl->power(dev_get_drvdata(&icd->dev), 1); - - return 0; -} - -static int soc_camera_platform_release(struct soc_camera_device *icd) -{ - struct soc_camera_link *icl = to_soc_camera_link(icd); - - if (icl->power) - icl->power(dev_get_drvdata(&icd->dev), 0); - - return 0; -} - -static int soc_camera_platform_start_capture(struct soc_camera_device *icd) -{ - struct soc_camera_platform_info *p = soc_camera_platform_get_info(icd); - return p->set_capture(p, 1); -} - -static int soc_camera_platform_stop_capture(struct soc_camera_device *icd) -{ - struct soc_camera_platform_info *p = soc_camera_platform_get_info(icd); - return p->set_capture(p, 0); + struct soc_camera_platform_info *p = v4l2_get_subdevdata(sd); + return p->set_capture(p, enable); } static int soc_camera_platform_set_bus_param(struct soc_camera_device *icd, @@ -82,16 +57,10 @@ static int soc_camera_platform_set_crop(struct soc_camera_device *icd, return 0; } -static int soc_camera_platform_set_fmt(struct soc_camera_device *icd, +static int soc_camera_platform_try_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) { - return 0; -} - -static int soc_camera_platform_try_fmt(struct soc_camera_device *icd, - struct v4l2_format *f) -{ - struct soc_camera_platform_info *p = soc_camera_platform_get_info(icd); + struct soc_camera_platform_info *p = v4l2_get_subdevdata(sd); struct v4l2_pix_format *pix = &f->fmt.pix; pix->width = p->format.width; @@ -99,12 +68,11 @@ static int soc_camera_platform_try_fmt(struct soc_camera_device *icd, return 0; } -static int soc_camera_platform_video_probe(struct soc_camera_device *icd, - struct platform_device *pdev) +static void soc_camera_platform_video_probe(struct soc_camera_device *icd, + struct platform_device *pdev) { struct soc_camera_platform_priv *priv = platform_get_drvdata(pdev); struct soc_camera_platform_info *p = pdev->dev.platform_data; - int ret; priv->format.name = p->format_name; priv->format.depth = p->format_depth; @@ -113,28 +81,29 @@ static int soc_camera_platform_video_probe(struct soc_camera_device *icd, icd->formats = &priv->format; icd->num_formats = 1; - - /* ..._video_start() does dev_set_drvdata(&icd->dev, &pdev->dev) */ - ret = soc_camera_video_start(icd, &pdev->dev); - soc_camera_video_stop(icd); - return ret; } +static struct v4l2_subdev_core_ops platform_subdev_core_ops; + +static struct v4l2_subdev_video_ops platform_subdev_video_ops = { + .s_stream = soc_camera_platform_s_stream, + .try_fmt = soc_camera_platform_try_fmt, +}; + +static struct v4l2_subdev_ops platform_subdev_ops = { + .core = &platform_subdev_core_ops, + .video = &platform_subdev_video_ops, +}; + static struct soc_camera_ops soc_camera_platform_ops = { - .owner = THIS_MODULE, - .init = soc_camera_platform_init, - .release = soc_camera_platform_release, - .start_capture = soc_camera_platform_start_capture, - .stop_capture = soc_camera_platform_stop_capture, .set_crop = soc_camera_platform_set_crop, - .set_fmt = soc_camera_platform_set_fmt, - .try_fmt = soc_camera_platform_try_fmt, .set_bus_param = soc_camera_platform_set_bus_param, .query_bus_param = soc_camera_platform_query_bus_param, }; static int soc_camera_platform_probe(struct platform_device *pdev) { + struct soc_camera_host *ici; struct soc_camera_platform_priv *priv; struct soc_camera_platform_info *p = pdev->dev.platform_data; struct soc_camera_device *icd; @@ -143,35 +112,48 @@ static int soc_camera_platform_probe(struct platform_device *pdev) if (!p) return -EINVAL; + if (!p->dev) { + dev_err(&pdev->dev, + "Platform has not set soc_camera_device pointer!\n"); + return -EINVAL; + } + priv = kzalloc(sizeof(*priv), GFP_KERNEL); if (!priv) return -ENOMEM; - platform_set_drvdata(pdev, priv); - icd = to_soc_camera_dev(p->dev); - if (!icd) - goto enoicd; - icd->ops = &soc_camera_platform_ops; + platform_set_drvdata(pdev, priv); dev_set_drvdata(&icd->dev, &pdev->dev); + icd->width_min = 0; icd->width_max = p->format.width; icd->height_min = 0; icd->height_max = p->format.height; icd->y_skip_top = 0; + icd->ops = &soc_camera_platform_ops; - ret = soc_camera_platform_video_probe(icd, pdev); - if (ret) { - icd->ops = NULL; - kfree(priv); - } + ici = to_soc_camera_host(icd->dev.parent); + + soc_camera_platform_video_probe(icd, pdev); + + v4l2_subdev_init(&priv->subdev, &platform_subdev_ops); + v4l2_set_subdevdata(&priv->subdev, p); + priv->subdev.grp_id = (__u32)icd; + strncpy(priv->subdev.name, dev_name(&pdev->dev), V4L2_SUBDEV_NAME_SIZE); + + ret = v4l2_device_register_subdev(&ici->v4l2_dev, &priv->subdev); + if (ret) + goto evdrs; return ret; -enoicd: +evdrs: + icd->ops = NULL; + platform_set_drvdata(pdev, NULL); kfree(priv); - return -EINVAL; + return ret; } static int soc_camera_platform_remove(struct platform_device *pdev) @@ -180,7 +162,9 @@ static int soc_camera_platform_remove(struct platform_device *pdev) struct soc_camera_platform_info *p = pdev->dev.platform_data; struct soc_camera_device *icd = to_soc_camera_dev(p->dev); + v4l2_device_unregister_subdev(&priv->subdev); icd->ops = NULL; + platform_set_drvdata(pdev, NULL); kfree(priv); return 0; } @@ -188,6 +172,7 @@ static int soc_camera_platform_remove(struct platform_device *pdev) static struct platform_driver soc_camera_platform_driver = { .driver = { .name = "soc_camera_platform", + .owner = THIS_MODULE, }, .probe = soc_camera_platform_probe, .remove = soc_camera_platform_remove, diff --git a/linux/drivers/media/video/tw9910.c b/linux/drivers/media/video/tw9910.c index 432dd3edc..61dc1b812 100644 --- a/linux/drivers/media/video/tw9910.c +++ b/linux/drivers/media/video/tw9910.c @@ -24,7 +24,7 @@ #include #include #include -#include +#include #include #include @@ -223,6 +223,7 @@ struct tw9910_hsync_ctrl { }; struct tw9910_priv { + struct v4l2_subdev subdev; struct tw9910_video_info *info; const struct tw9910_scale_ctrl *scale; }; @@ -354,6 +355,11 @@ static const struct tw9910_hsync_ctrl tw9910_hsync_ctrl = { /* * general function */ +static struct tw9910_priv *to_tw9910(const struct i2c_client *client) +{ + return container_of(i2c_get_clientdata(client), struct tw9910_priv, subdev); +} + static int tw9910_set_scale(struct i2c_client *client, const struct tw9910_scale_ctrl *scale) { @@ -507,47 +513,20 @@ tw9910_select_norm(struct soc_camera_device *icd, u32 width, u32 height) /* * soc_camera_ops function */ -static int tw9910_init(struct soc_camera_device *icd) +static int tw9910_s_stream(struct v4l2_subdev *sd, int enable) { - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); - struct soc_camera_link *icl = to_soc_camera_link(icd); - int ret = 0; + struct i2c_client *client = sd->priv; + struct tw9910_priv *priv = to_tw9910(client); - if (icl->power) { - ret = icl->power(&client->dev, 1); - if (ret < 0) - return ret; - } - - if (icl->reset) - ret = icl->reset(&client->dev); - - return ret; -} - -static int tw9910_release(struct soc_camera_device *icd) -{ - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); - struct soc_camera_link *icl = to_soc_camera_link(icd); - int ret = 0; - - if (icl->power) - ret = icl->power(&client->dev, 0); - - return ret; -} - -static int tw9910_start_capture(struct soc_camera_device *icd) -{ - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); - struct tw9910_priv *priv = i2c_get_clientdata(client); + if (!enable) + return 0; if (!priv->scale) { - dev_err(&icd->dev, "norm select error\n"); + dev_err(&client->dev, "norm select error\n"); return -EPERM; } - dev_dbg(&icd->dev, "%s %dx%d\n", + dev_dbg(&client->dev, "%s %dx%d\n", priv->scale->name, priv->scale->width, priv->scale->height); @@ -555,11 +534,6 @@ static int tw9910_start_capture(struct soc_camera_device *icd) return 0; } -static int tw9910_stop_capture(struct soc_camera_device *icd) -{ - return 0; -} - static int tw9910_set_bus_param(struct soc_camera_device *icd, unsigned long flags) { @@ -569,7 +543,7 @@ static int tw9910_set_bus_param(struct soc_camera_device *icd, static unsigned long tw9910_query_bus_param(struct soc_camera_device *icd) { struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); - struct tw9910_priv *priv = i2c_get_clientdata(client); + struct tw9910_priv *priv = to_tw9910(client); struct soc_camera_link *icl = to_soc_camera_link(icd); unsigned long flags = SOCAM_PCLK_SAMPLE_RISING | SOCAM_MASTER | SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_HSYNC_ACTIVE_HIGH | @@ -578,21 +552,11 @@ static unsigned long tw9910_query_bus_param(struct soc_camera_device *icd) return soc_camera_apply_sensor_flags(icl, flags); } -static int tw9910_get_chip_id(struct soc_camera_device *icd, - struct v4l2_dbg_chip_ident *id) -{ - id->ident = V4L2_IDENT_TW9910; - id->revision = 0; - - return 0; -} - -static int tw9910_set_std(struct soc_camera_device *icd, - v4l2_std_id *a) +static int tw9910_s_std(struct v4l2_subdev *sd, v4l2_std_id norm) { int ret = -EINVAL; - if (*a & (V4L2_STD_NTSC | V4L2_STD_PAL)) + if (norm & (V4L2_STD_NTSC | V4L2_STD_PAL)) ret = 0; return ret; @@ -608,11 +572,20 @@ static int tw9910_enum_input(struct soc_camera_device *icd, return 0; } +static int tw9910_g_chip_ident(struct v4l2_subdev *sd, + struct v4l2_dbg_chip_ident *id) +{ + id->ident = V4L2_IDENT_TW9910; + id->revision = 0; + + return 0; +} + #ifdef CONFIG_VIDEO_ADV_DEBUG -static int tw9910_get_register(struct soc_camera_device *icd, - struct v4l2_dbg_register *reg) +static int tw9910_g_register(struct v4l2_subdev *sd, + struct v4l2_dbg_register *reg) { - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct i2c_client *client = sd->priv; int ret; if (reg->reg > 0xff) @@ -630,10 +603,10 @@ static int tw9910_get_register(struct soc_camera_device *icd, return 0; } -static int tw9910_set_register(struct soc_camera_device *icd, - struct v4l2_dbg_register *reg) +static int tw9910_s_register(struct v4l2_subdev *sd, + struct v4l2_dbg_register *reg) { - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct i2c_client *client = sd->priv; if (reg->reg > 0xff || reg->val > 0xff) @@ -647,7 +620,7 @@ static int tw9910_set_crop(struct soc_camera_device *icd, struct v4l2_rect *rect) { struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); - struct tw9910_priv *priv = i2c_get_clientdata(client); + struct tw9910_priv *priv = to_tw9910(client); int ret = -EINVAL; u8 val; @@ -736,9 +709,10 @@ tw9910_set_fmt_error: return ret; } -static int tw9910_set_fmt(struct soc_camera_device *icd, - struct v4l2_format *f) +static int tw9910_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) { + struct i2c_client *client = sd->priv; + struct soc_camera_device *icd = client->dev.platform_data; struct v4l2_pix_format *pix = &f->fmt.pix; struct v4l2_rect rect = { .left = icd->x_current, @@ -761,16 +735,17 @@ static int tw9910_set_fmt(struct soc_camera_device *icd, return tw9910_set_crop(icd, &rect); } -static int tw9910_try_fmt(struct soc_camera_device *icd, - struct v4l2_format *f) +static int tw9910_try_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) { + struct i2c_client *client = sd->priv; + struct soc_camera_device *icd = client->dev.platform_data; struct v4l2_pix_format *pix = &f->fmt.pix; const struct tw9910_scale_ctrl *scale; if (V4L2_FIELD_ANY == pix->field) { pix->field = V4L2_FIELD_INTERLACED; } else if (V4L2_FIELD_INTERLACED != pix->field) { - dev_err(&icd->dev, "Field type invalid.\n"); + dev_err(&client->dev, "Field type invalid.\n"); return -EINVAL; } @@ -790,9 +765,8 @@ static int tw9910_try_fmt(struct soc_camera_device *icd, static int tw9910_video_probe(struct soc_camera_device *icd, struct i2c_client *client) { - struct tw9910_priv *priv = i2c_get_clientdata(client); + struct tw9910_priv *priv = to_tw9910(client); s32 val; - int ret; /* * We must have a parent by now. And it cannot be a wrong one. @@ -814,18 +788,11 @@ static int tw9910_video_probe(struct soc_camera_device *icd, icd->formats = tw9910_color_fmt; icd->num_formats = ARRAY_SIZE(tw9910_color_fmt); - /* Switch master clock on */ - ret = soc_camera_video_start(icd, &client->dev); - if (ret) - return ret; - /* * check and show Product ID */ val = i2c_smbus_read_byte_data(client, ID); - soc_camera_video_stop(icd); - if (0x0B != GET_ID(val) || 0x00 != GET_ReV(val)) { dev_err(&icd->dev, @@ -839,29 +806,36 @@ static int tw9910_video_probe(struct soc_camera_device *icd, icd->vdev->tvnorms = V4L2_STD_NTSC | V4L2_STD_PAL; icd->vdev->current_norm = V4L2_STD_NTSC; - return ret; + return 0; } static struct soc_camera_ops tw9910_ops = { - .owner = THIS_MODULE, - .init = tw9910_init, - .release = tw9910_release, - .start_capture = tw9910_start_capture, - .stop_capture = tw9910_stop_capture, .set_crop = tw9910_set_crop, - .set_fmt = tw9910_set_fmt, - .try_fmt = tw9910_try_fmt, .set_bus_param = tw9910_set_bus_param, .query_bus_param = tw9910_query_bus_param, - .get_chip_id = tw9910_get_chip_id, - .set_std = tw9910_set_std, .enum_input = tw9910_enum_input, +}; + +static struct v4l2_subdev_core_ops tw9910_subdev_core_ops = { + .g_chip_ident = tw9910_g_chip_ident, + .s_std = tw9910_s_std, #ifdef CONFIG_VIDEO_ADV_DEBUG - .get_register = tw9910_get_register, - .set_register = tw9910_set_register, + .g_register = tw9910_g_register, + .s_register = tw9910_s_register, #endif }; +static struct v4l2_subdev_video_ops tw9910_subdev_video_ops = { + .s_stream = tw9910_s_stream, + .s_fmt = tw9910_s_fmt, + .try_fmt = tw9910_try_fmt, +}; + +static struct v4l2_subdev_ops tw9910_subdev_ops = { + .core = &tw9910_subdev_core_ops, + .video = &tw9910_subdev_video_ops, +}; + /* * i2c_driver function */ @@ -906,7 +880,8 @@ static int tw9910_probe(struct i2c_client *client, return -ENOMEM; priv->info = info; - i2c_set_clientdata(client, priv); + + v4l2_i2c_subdev_init(&priv->subdev, client, &tw9910_subdev_ops); icd->ops = &tw9910_ops; icd->iface = info->link.bus_id; @@ -946,7 +921,7 @@ static int tw9910_probe(struct i2c_client *client, static int tw9910_remove(struct i2c_client *client) { - struct tw9910_priv *priv = i2c_get_clientdata(client); + struct tw9910_priv *priv = to_tw9910(client); struct soc_camera_device *icd = client->dev.platform_data; icd->ops = NULL; -- cgit v1.2.3 From 4e4ce6d0b364f6dcab06b9f80942339fbfef9e0a Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Tue, 25 Aug 2009 16:44:14 +0200 Subject: ov772x: implement a band-stop filter support From: Guennadi Liakhovetski The V4L2_CID_BAND_STOP_FILTER control is used to switch the "Banding Filter" on OV772x cameras on and off and to set the minimum AEC value in BDBASE register. Signed-off-by: Guennadi Liakhovetski Priority: low --- drivers/media/video/ov772x.c | 52 ++++++++++++++++++++++++++++++++++++++++- 1 files changed, 50 insertions(+), 2 deletions(-) --- linux/drivers/media/video/ov772x.c | 52 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 50 insertions(+), 2 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/ov772x.c b/linux/drivers/media/video/ov772x.c index 4da12e8c4..05e06f5b8 100644 --- a/linux/drivers/media/video/ov772x.c +++ b/linux/drivers/media/video/ov772x.c @@ -403,8 +403,9 @@ struct ov772x_priv { const struct ov772x_color_format *fmt; const struct ov772x_win_size *win; int model; - unsigned int flag_vflip:1; - unsigned int flag_hflip:1; + unsigned short flag_vflip:1; + unsigned short flag_hflip:1; + unsigned short band_filter; /* 256 - BDBASE, 0 if (!COM8[5]) */ }; #define ENDMARKER { 0xff, 0xff } @@ -569,6 +570,15 @@ static const struct v4l2_queryctrl ov772x_controls[] = { .step = 1, .default_value = 0, }, + { + .id = V4L2_CID_BAND_STOP_FILTER, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Band-stop filter", + .minimum = 0, + .maximum = 256, + .step = 1, + .default_value = 0, + }, }; @@ -674,6 +684,9 @@ static int ov772x_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) case V4L2_CID_HFLIP: ctrl->value = priv->flag_hflip; break; + case V4L2_CID_BAND_STOP_FILTER: + ctrl->value = priv->band_filter; + break; } return 0; } @@ -700,6 +713,29 @@ static int ov772x_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) val ^= HFLIP_IMG; ret = ov772x_mask_set(client, COM3, HFLIP_IMG, val); break; + case V4L2_CID_BAND_STOP_FILTER: + if ((unsigned)ctrl->value > 256) + ctrl->value = 256; + if (ctrl->value == priv->band_filter) + break; + if (!ctrl->value) { + /* Switch the filter off, it is on now */ + ret = ov772x_mask_set(client, BDBASE, 0xff, 0xff); + if (!ret) + ret = ov772x_mask_set(client, COM8, + BNDF_ON_OFF, 0); + } else { + /* Switch the filter on, set AEC low limit */ + val = 256 - ctrl->value; + ret = ov772x_mask_set(client, COM8, + BNDF_ON_OFF, BNDF_ON_OFF); + if (!ret) + ret = ov772x_mask_set(client, BDBASE, + 0xff, val); + } + if (!ret) + priv->band_filter = ctrl->value; + break; } return ret; @@ -893,6 +929,18 @@ static int ov772x_set_params(struct i2c_client *client, if (ret < 0) goto ov772x_set_fmt_error; + /* + * set COM8 + */ + if (priv->band_filter) { + ret = ov772x_mask_set(client, COM8, BNDF_ON_OFF, 1); + if (!ret) + ret = ov772x_mask_set(client, BDBASE, + 0xff, 256 - priv->band_filter); + if (ret < 0) + goto ov772x_set_fmt_error; + } + return ret; ov772x_set_fmt_error: -- cgit v1.2.3 From ac97b8b24a867c8c2d3dd71d3c3d12b078b8091c Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Tue, 25 Aug 2009 16:44:15 +0200 Subject: soc-camera: add support for camera-host controls From: Guennadi Liakhovetski Until now soc-camera only supported client (sensor) controls. This patch enables camera-host drivers to implement their own controls too. Signed-off-by: Guennadi Liakhovetski Priority: low --- drivers/media/video/soc_camera.c | 24 ++++++++++++++++++++++++ include/media/soc_camera.h | 4 ++++ 2 files changed, 28 insertions(+), 0 deletions(-) --- linux/drivers/media/video/soc_camera.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/soc_camera.c b/linux/drivers/media/video/soc_camera.c index e759400cc..42e7acd9b 100644 --- a/linux/drivers/media/video/soc_camera.c +++ b/linux/drivers/media/video/soc_camera.c @@ -634,6 +634,7 @@ static int soc_camera_queryctrl(struct file *file, void *priv, { struct soc_camera_file *icf = file->private_data; struct soc_camera_device *icd = icf->icd; + struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); int i; WARN_ON(priv != file->private_data); @@ -641,6 +642,15 @@ static int soc_camera_queryctrl(struct file *file, void *priv, if (!qc->id) return -EINVAL; + /* First check host controls */ + for (i = 0; i < ici->ops->num_controls; i++) + if (qc->id == ici->ops->controls[i].id) { + memcpy(qc, &(ici->ops->controls[i]), + sizeof(*qc)); + return 0; + } + + /* Then device controls */ for (i = 0; i < icd->ops->num_controls; i++) if (qc->id == icd->ops->controls[i].id) { memcpy(qc, &(icd->ops->controls[i]), @@ -657,6 +667,7 @@ static int soc_camera_g_ctrl(struct file *file, void *priv, struct soc_camera_file *icf = file->private_data; struct soc_camera_device *icd = icf->icd; struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); + int ret; WARN_ON(priv != file->private_data); @@ -673,6 +684,12 @@ static int soc_camera_g_ctrl(struct file *file, void *priv, return 0; } + if (ici->ops->get_ctrl) { + ret = ici->ops->get_ctrl(icd, ctrl); + if (ret != -ENOIOCTLCMD) + return ret; + } + return v4l2_device_call_until_err(&ici->v4l2_dev, (__u32)icd, core, g_ctrl, ctrl); } @@ -682,9 +699,16 @@ static int soc_camera_s_ctrl(struct file *file, void *priv, struct soc_camera_file *icf = file->private_data; struct soc_camera_device *icd = icf->icd; struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); + int ret; WARN_ON(priv != file->private_data); + if (ici->ops->set_ctrl) { + ret = ici->ops->set_ctrl(icd, ctrl); + if (ret != -ENOIOCTLCMD) + return ret; + } + return v4l2_device_call_until_err(&ici->v4l2_dev, (__u32)icd, core, s_ctrl, ctrl); } -- cgit v1.2.3 From cf579adf1e145c22f0c7178612e4781cc8b089cc Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Tue, 25 Aug 2009 16:44:15 +0200 Subject: sh_mobile_ceu_camera: add a control for the camera low-pass filter From: Guennadi Liakhovetski Use the V4L2_CID_SHARPNESS control to switch SH-mobile camera low-pass filter. Signed-off-by: Guennadi Liakhovetski Priority: low --- drivers/media/video/sh_mobile_ceu_camera.c | 54 +++++++++++++++++++++++++++- 1 files changed, 53 insertions(+), 1 deletions(-) --- linux/drivers/media/video/sh_mobile_ceu_camera.c | 54 +++++++++++++++++++++++- 1 file changed, 53 insertions(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/sh_mobile_ceu_camera.c b/linux/drivers/media/video/sh_mobile_ceu_camera.c index f1ab7b690..99ea30896 100644 --- a/linux/drivers/media/video/sh_mobile_ceu_camera.c +++ b/linux/drivers/media/video/sh_mobile_ceu_camera.c @@ -497,7 +497,6 @@ static int sh_mobile_ceu_set_bus_param(struct soc_camera_device *icd, ceu_write(pcdev, CAPWR, (height << 16) | width); ceu_write(pcdev, CFLCR, 0); /* no scaling */ ceu_write(pcdev, CFSZR, (height << 16) | cfszr_width); - ceu_write(pcdev, CLFCR, 0); /* no lowpass filter */ /* A few words about byte order (observed in Big Endian mode) * @@ -774,6 +773,55 @@ static void sh_mobile_ceu_init_videobuf(struct videobuf_queue *q, icd); } +static int sh_mobile_ceu_get_ctrl(struct soc_camera_device *icd, + struct v4l2_control *ctrl) +{ + struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); + struct sh_mobile_ceu_dev *pcdev = ici->priv; + u32 val; + + switch (ctrl->id) { + case V4L2_CID_SHARPNESS: + val = ceu_read(pcdev, CLFCR); + ctrl->value = val ^ 1; + return 0; + } + return -ENOIOCTLCMD; +} + +static int sh_mobile_ceu_set_ctrl(struct soc_camera_device *icd, + struct v4l2_control *ctrl) +{ + struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); + struct sh_mobile_ceu_dev *pcdev = ici->priv; + + switch (ctrl->id) { + case V4L2_CID_SHARPNESS: + switch (icd->current_fmt->fourcc) { + case V4L2_PIX_FMT_NV12: + case V4L2_PIX_FMT_NV21: + case V4L2_PIX_FMT_NV16: + case V4L2_PIX_FMT_NV61: + ceu_write(pcdev, CLFCR, !ctrl->value); + return 0; + } + return -EINVAL; + } + return -ENOIOCTLCMD; +} + +static const struct v4l2_queryctrl sh_mobile_ceu_controls[] = { + { + .id = V4L2_CID_SHARPNESS, + .type = V4L2_CTRL_TYPE_BOOLEAN, + .name = "Low-pass filter", + .minimum = 0, + .maximum = 1, + .step = 1, + .default_value = 0, + }, +}; + static struct soc_camera_host_ops sh_mobile_ceu_host_ops = { .owner = THIS_MODULE, .add = sh_mobile_ceu_add_device, @@ -782,11 +830,15 @@ static struct soc_camera_host_ops sh_mobile_ceu_host_ops = { .set_crop = sh_mobile_ceu_set_crop, .set_fmt = sh_mobile_ceu_set_fmt, .try_fmt = sh_mobile_ceu_try_fmt, + .set_ctrl = sh_mobile_ceu_set_ctrl, + .get_ctrl = sh_mobile_ceu_get_ctrl, .reqbufs = sh_mobile_ceu_reqbufs, .poll = sh_mobile_ceu_poll, .querycap = sh_mobile_ceu_querycap, .set_bus_param = sh_mobile_ceu_set_bus_param, .init_videobuf = sh_mobile_ceu_init_videobuf, + .controls = sh_mobile_ceu_controls, + .num_controls = ARRAY_SIZE(sh_mobile_ceu_controls), }; static int __devinit sh_mobile_ceu_probe(struct platform_device *pdev) -- cgit v1.2.3 From 67b6fcc4c0404e94f16820566585bb0ff9891b89 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Tue, 25 Aug 2009 16:46:17 +0200 Subject: soc-camera: use struct v4l2_rect in struct soc_camera_device From: Guennadi Liakhovetski Switch to using struct v4l2_rect in struct soc_camera_device for uniformity and simplicity. Signed-off-by: Guennadi Liakhovetski Priority: low --- linux/drivers/media/video/mt9m001.c | 30 ++++++------ linux/drivers/media/video/mt9m111.c | 20 ++++---- linux/drivers/media/video/mt9t031.c | 49 ++++++++++--------- linux/drivers/media/video/mt9v022.c | 24 ++++----- linux/drivers/media/video/mx1_camera.c | 10 ++-- linux/drivers/media/video/mx3_camera.c | 25 +++++----- linux/drivers/media/video/ov772x.c | 6 +-- linux/drivers/media/video/pxa_camera.c | 14 +++--- linux/drivers/media/video/sh_mobile_ceu_camera.c | 28 ++++++----- linux/drivers/media/video/soc_camera.c | 62 ++++++++++++++---------- linux/drivers/media/video/soc_camera_platform.c | 12 ++--- linux/drivers/media/video/tw9910.c | 38 +++++++++------ 12 files changed, 172 insertions(+), 146 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/mt9m001.c b/linux/drivers/media/video/mt9m001.c index 45d8fad25..7a9435f9b 100644 --- a/linux/drivers/media/video/mt9m001.c +++ b/linux/drivers/media/video/mt9m001.c @@ -240,8 +240,8 @@ static int mt9m001_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) struct i2c_client *client = sd->priv; struct soc_camera_device *icd = client->dev.platform_data; struct v4l2_rect rect = { - .left = icd->x_current, - .top = icd->y_current, + .left = icd->rect_current.left, + .top = icd->rect_current.top, .width = f->fmt.pix.width, .height = f->fmt.pix.height, }; @@ -467,11 +467,13 @@ static int mt9m001_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) case V4L2_CID_EXPOSURE_AUTO: if (ctrl->value) { const u16 vblank = 25; - if (reg_write(client, MT9M001_SHUTTER_WIDTH, icd->height + + if (reg_write(client, MT9M001_SHUTTER_WIDTH, + icd->rect_current.height + icd->y_skip_top + vblank) < 0) return -EIO; qctrl = soc_camera_find_qctrl(icd->ops, V4L2_CID_EXPOSURE); - icd->exposure = (524 + (icd->height + icd->y_skip_top + vblank - 1) * + icd->exposure = (524 + (icd->rect_current.height + + icd->y_skip_top + vblank - 1) * (qctrl->maximum - qctrl->minimum)) / 1048 + qctrl->minimum; mt9m001->autoexposure = 1; @@ -617,16 +619,16 @@ static int mt9m001_probe(struct i2c_client *client) v4l2_i2c_subdev_init(&mt9m001->subdev, client, &mt9m001_subdev_ops); /* Second stage probe - when a capture adapter is there */ - icd->ops = &mt9m001_ops; - icd->x_min = 20; - icd->y_min = 12; - icd->x_current = 20; - icd->y_current = 12; - icd->width_min = 48; - icd->width_max = 1280; - icd->height_min = 32; - icd->height_max = 1024; - icd->y_skip_top = 1; + icd->ops = &mt9m001_ops; + icd->rect_max.left = 20; + icd->rect_max.top = 12; + icd->rect_max.width = 1280; + icd->rect_max.height = 1024; + icd->rect_current.left = 20; + icd->rect_current.top = 12; + icd->width_min = 48; + icd->height_min = 32; + icd->y_skip_top = 1; /* Simulated autoexposure. If enabled, we calculate shutter width * ourselves in the driver based on vertical blanking and frame width */ mt9m001->autoexposure = 1; diff --git a/linux/drivers/media/video/mt9m111.c b/linux/drivers/media/video/mt9m111.c index 4b00033c4..8770dfd2a 100644 --- a/linux/drivers/media/video/mt9m111.c +++ b/linux/drivers/media/video/mt9m111.c @@ -952,16 +952,16 @@ static int mt9m111_probe(struct i2c_client *client, v4l2_i2c_subdev_init(&mt9m111->subdev, client, &mt9m111_subdev_ops); /* Second stage probe - when a capture adapter is there */ - icd->ops = &mt9m111_ops; - icd->x_min = MT9M111_MIN_DARK_COLS; - icd->y_min = MT9M111_MIN_DARK_ROWS; - icd->x_current = icd->x_min; - icd->y_current = icd->y_min; - icd->width_min = MT9M111_MIN_DARK_ROWS; - icd->width_max = MT9M111_MAX_WIDTH; - icd->height_min = MT9M111_MIN_DARK_COLS; - icd->height_max = MT9M111_MAX_HEIGHT; - icd->y_skip_top = 0; + icd->ops = &mt9m111_ops; + icd->rect_max.left = MT9M111_MIN_DARK_COLS; + icd->rect_max.top = MT9M111_MIN_DARK_ROWS; + icd->rect_max.width = MT9M111_MAX_WIDTH; + icd->rect_max.height = MT9M111_MAX_HEIGHT; + icd->rect_current.left = icd->rect_max.left; + icd->rect_current.top = icd->rect_max.top; + icd->width_min = MT9M111_MIN_DARK_ROWS; + icd->height_min = MT9M111_MIN_DARK_COLS; + icd->y_skip_top = 0; ret = mt9m111_video_probe(icd, client); if (ret) { diff --git a/linux/drivers/media/video/mt9t031.c b/linux/drivers/media/video/mt9t031.c index 2aff92cfc..405fe5c25 100644 --- a/linux/drivers/media/video/mt9t031.c +++ b/linux/drivers/media/video/mt9t031.c @@ -222,12 +222,12 @@ static unsigned long mt9t031_query_bus_param(struct soc_camera_device *icd) static void recalculate_limits(struct soc_camera_device *icd, u16 xskip, u16 yskip) { - icd->x_min = (MT9T031_COLUMN_SKIP + xskip - 1) / xskip; - icd->y_min = (MT9T031_ROW_SKIP + yskip - 1) / yskip; + icd->rect_max.left = (MT9T031_COLUMN_SKIP + xskip - 1) / xskip; + icd->rect_max.top = (MT9T031_ROW_SKIP + yskip - 1) / yskip; icd->width_min = (MT9T031_MIN_WIDTH + xskip - 1) / xskip; icd->height_min = (MT9T031_MIN_HEIGHT + yskip - 1) / yskip; - icd->width_max = MT9T031_MAX_WIDTH / xskip; - icd->height_max = MT9T031_MAX_HEIGHT / yskip; + icd->rect_max.width = MT9T031_MAX_WIDTH / xskip; + icd->rect_max.height = MT9T031_MAX_HEIGHT / yskip; } static int mt9t031_set_params(struct soc_camera_device *icd, @@ -241,11 +241,13 @@ static int mt9t031_set_params(struct soc_camera_device *icd, vblank = MT9T031_VERTICAL_BLANK; /* Make sure we don't exceed sensor limits */ - if (rect->left + rect->width > icd->width_max) - rect->left = (icd->width_max - rect->width) / 2 + icd->x_min; + if (rect->left + rect->width > icd->rect_max.width) + rect->left = (icd->rect_max.width - rect->width) / 2 + + icd->rect_max.left; - if (rect->top + rect->height > icd->height_max) - rect->top = (icd->height_max - rect->height) / 2 + icd->y_min; + if (rect->top + rect->height > icd->rect_max.height) + rect->top = (icd->rect_max.height - rect->height) / 2 + + icd->rect_max.top; width = rect->width * xskip; height = rect->height * yskip; @@ -346,8 +348,8 @@ static int mt9t031_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) int ret; u16 xskip, yskip; struct v4l2_rect rect = { - .left = icd->x_current, - .top = icd->y_current, + .left = icd->rect_current.left, + .top = icd->rect_current.top, .width = f->fmt.pix.width, .height = f->fmt.pix.height, }; @@ -618,12 +620,13 @@ static int mt9t031_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) if (ctrl->value) { const u16 vblank = MT9T031_VERTICAL_BLANK; const u32 shutter_max = MT9T031_MAX_HEIGHT + vblank; - if (set_shutter(client, icd->height + + if (set_shutter(client, icd->rect_current.height + icd->y_skip_top + vblank) < 0) return -EIO; qctrl = soc_camera_find_qctrl(icd->ops, V4L2_CID_EXPOSURE); - icd->exposure = (shutter_max / 2 + (icd->height + - icd->y_skip_top + vblank - 1) * + icd->exposure = (shutter_max / 2 + + (icd->rect_current.height + + icd->y_skip_top + vblank - 1) * (qctrl->maximum - qctrl->minimum)) / shutter_max + qctrl->minimum; mt9t031->autoexposure = 1; @@ -730,16 +733,16 @@ static int mt9t031_probe(struct i2c_client *client, v4l2_i2c_subdev_init(&mt9t031->subdev, client, &mt9t031_subdev_ops); /* Second stage probe - when a capture adapter is there */ - icd->ops = &mt9t031_ops; - icd->x_min = MT9T031_COLUMN_SKIP; - icd->y_min = MT9T031_ROW_SKIP; - icd->x_current = icd->x_min; - icd->y_current = icd->y_min; - icd->width_min = MT9T031_MIN_WIDTH; - icd->width_max = MT9T031_MAX_WIDTH; - icd->height_min = MT9T031_MIN_HEIGHT; - icd->height_max = MT9T031_MAX_HEIGHT; - icd->y_skip_top = 0; + icd->ops = &mt9t031_ops; + icd->rect_max.left = MT9T031_COLUMN_SKIP; + icd->rect_max.top = MT9T031_ROW_SKIP; + icd->rect_current.left = icd->rect_max.left; + icd->rect_current.top = icd->rect_max.top; + icd->width_min = MT9T031_MIN_WIDTH; + icd->rect_max.width = MT9T031_MAX_WIDTH; + icd->height_min = MT9T031_MIN_HEIGHT; + icd->rect_max.height = MT9T031_MAX_HEIGHT; + icd->y_skip_top = 0; /* Simulated autoexposure. If enabled, we calculate shutter width * ourselves in the driver based on vertical blanking and frame width */ mt9t031->autoexposure = 1; diff --git a/linux/drivers/media/video/mt9v022.c b/linux/drivers/media/video/mt9v022.c index b09cd0913..de74f7bda 100644 --- a/linux/drivers/media/video/mt9v022.c +++ b/linux/drivers/media/video/mt9v022.c @@ -298,8 +298,8 @@ static int mt9v022_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) struct soc_camera_device *icd = client->dev.platform_data; struct v4l2_pix_format *pix = &f->fmt.pix; struct v4l2_rect rect = { - .left = icd->x_current, - .top = icd->y_current, + .left = icd->rect_current.left, + .top = icd->rect_current.top, .width = pix->width, .height = pix->height, }; @@ -745,16 +745,16 @@ static int mt9v022_probe(struct i2c_client *client) mt9v022->chip_control = MT9V022_CHIP_CONTROL_DEFAULT; - icd->ops = &mt9v022_ops; - icd->x_min = 1; - icd->y_min = 4; - icd->x_current = 1; - icd->y_current = 4; - icd->width_min = 48; - icd->width_max = 752; - icd->height_min = 32; - icd->height_max = 480; - icd->y_skip_top = 1; + icd->ops = &mt9v022_ops; + icd->rect_max.left = 1; + icd->rect_max.top = 4; + icd->rect_max.width = 752; + icd->rect_max.height = 480; + icd->rect_current.left = 1; + icd->rect_current.top = 4; + icd->width_min = 48; + icd->height_min = 32; + icd->y_skip_top = 1; ret = mt9v022_video_probe(icd, client); if (ret) { diff --git a/linux/drivers/media/video/mx1_camera.c b/linux/drivers/media/video/mx1_camera.c index ea4ceaec8..948a4714b 100644 --- a/linux/drivers/media/video/mx1_camera.c +++ b/linux/drivers/media/video/mx1_camera.c @@ -126,7 +126,7 @@ static int mx1_videobuf_setup(struct videobuf_queue *vq, unsigned int *count, { struct soc_camera_device *icd = vq->priv_data; - *size = icd->width * icd->height * + *size = icd->rect_current.width * icd->rect_current.height * ((icd->current_fmt->depth + 7) >> 3); if (!*count) @@ -178,12 +178,12 @@ static int mx1_videobuf_prepare(struct videobuf_queue *vq, buf->inwork = 1; if (buf->fmt != icd->current_fmt || - vb->width != icd->width || - vb->height != icd->height || + vb->width != icd->rect_current.width || + vb->height != icd->rect_current.height || vb->field != field) { buf->fmt = icd->current_fmt; - vb->width = icd->width; - vb->height = icd->height; + vb->width = icd->rect_current.width; + vb->height = icd->rect_current.height; vb->field = field; vb->state = VIDEOBUF_NEEDS_INIT; } diff --git a/linux/drivers/media/video/mx3_camera.c b/linux/drivers/media/video/mx3_camera.c index 677d355be..6c3b7f9b9 100644 --- a/linux/drivers/media/video/mx3_camera.c +++ b/linux/drivers/media/video/mx3_camera.c @@ -220,7 +220,7 @@ static int mx3_videobuf_setup(struct videobuf_queue *vq, unsigned int *count, if (!mx3_cam->idmac_channel[0]) return -EINVAL; - *size = icd->width * icd->height * bpp; + *size = icd->rect_current.width * icd->rect_current.height * bpp; if (!*count) *count = 32; @@ -241,7 +241,7 @@ static int mx3_videobuf_prepare(struct videobuf_queue *vq, struct mx3_camera_buffer *buf = container_of(vb, struct mx3_camera_buffer, vb); /* current_fmt _must_ always be set */ - size_t new_size = icd->width * icd->height * + size_t new_size = icd->rect_current.width * icd->rect_current.height * ((icd->current_fmt->depth + 7) >> 3); int ret; @@ -251,12 +251,12 @@ static int mx3_videobuf_prepare(struct videobuf_queue *vq, */ if (buf->fmt != icd->current_fmt || - vb->width != icd->width || - vb->height != icd->height || + vb->width != icd->rect_current.width || + vb->height != icd->rect_current.height || vb->field != field) { buf->fmt = icd->current_fmt; - vb->width = icd->width; - vb->height = icd->height; + vb->width = icd->rect_current.width; + vb->height = icd->rect_current.height; vb->field = field; if (vb->state != VIDEOBUF_NEEDS_INIT) free_buffer(vq, buf); @@ -354,9 +354,9 @@ static void mx3_videobuf_queue(struct videobuf_queue *vq, /* This is the configuration of one sg-element */ video->out_pixel_fmt = fourcc_to_ipu_pix(data_fmt->fourcc); - video->out_width = icd->width; - video->out_height = icd->height; - video->out_stride = icd->width; + video->out_width = icd->rect_current.width; + video->out_height = icd->rect_current.height; + video->out_stride = icd->rect_current.width; #ifdef DEBUG /* helps to see what DMA actually has written */ @@ -538,7 +538,8 @@ static bool channel_change_requested(struct soc_camera_device *icd, struct idmac_channel *ichan = mx3_cam->idmac_channel[0]; /* Do buffers have to be re-allocated or channel re-configured? */ - return ichan && rect->width * rect->height > icd->width * icd->height; + return ichan && rect->width * rect->height > + icd->rect_current.width * icd->rect_current.height; } static int test_platform_param(struct mx3_camera_dev *mx3_cam, @@ -808,8 +809,8 @@ static int mx3_camera_set_fmt(struct soc_camera_device *icd, const struct soc_camera_format_xlate *xlate; struct v4l2_pix_format *pix = &f->fmt.pix; struct v4l2_rect rect = { - .left = icd->x_current, - .top = icd->y_current, + .left = icd->rect_current.left, + .top = icd->rect_current.top, .width = pix->width, .height = pix->height, }; diff --git a/linux/drivers/media/video/ov772x.c b/linux/drivers/media/video/ov772x.c index 05e06f5b8..a853c3514 100644 --- a/linux/drivers/media/video/ov772x.c +++ b/linux/drivers/media/video/ov772x.c @@ -1124,9 +1124,9 @@ static int ov772x_probe(struct i2c_client *client, v4l2_i2c_subdev_init(&priv->subdev, client, &ov772x_subdev_ops); - icd->ops = &ov772x_ops; - icd->width_max = MAX_WIDTH; - icd->height_max = MAX_HEIGHT; + icd->ops = &ov772x_ops; + icd->rect_max.width = MAX_WIDTH; + icd->rect_max.height = MAX_HEIGHT; ret = ov772x_video_probe(icd, client); if (ret) { diff --git a/linux/drivers/media/video/pxa_camera.c b/linux/drivers/media/video/pxa_camera.c index 4c73b7d88..6f2aef033 100644 --- a/linux/drivers/media/video/pxa_camera.c +++ b/linux/drivers/media/video/pxa_camera.c @@ -251,7 +251,7 @@ static int pxa_videobuf_setup(struct videobuf_queue *vq, unsigned int *count, dev_dbg(&icd->dev, "count=%d, size=%d\n", *count, *size); - *size = roundup(icd->width * icd->height * + *size = roundup(icd->rect_current.width * icd->rect_current.height * ((icd->current_fmt->depth + 7) >> 3), 8); if (0 == *count) @@ -455,12 +455,12 @@ static int pxa_videobuf_prepare(struct videobuf_queue *vq, buf->inwork = 1; if (buf->fmt != icd->current_fmt || - vb->width != icd->width || - vb->height != icd->height || + vb->width != icd->rect_current.width || + vb->height != icd->rect_current.height || vb->field != field) { buf->fmt = icd->current_fmt; - vb->width = icd->width; - vb->height = icd->height; + vb->width = icd->rect_current.width; + vb->height = icd->rect_current.height; vb->field = field; vb->state = VIDEOBUF_NEEDS_INIT; } @@ -1130,7 +1130,7 @@ static int pxa_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt) if (cicr0 & CICR0_ENB) __raw_writel(cicr0 & ~CICR0_ENB, pcdev->base + CICR0); - cicr1 = CICR1_PPL_VAL(icd->width - 1) | bpp | dw; + cicr1 = CICR1_PPL_VAL(icd->rect_current.width - 1) | bpp | dw; switch (pixfmt) { case V4L2_PIX_FMT_YUV422P: @@ -1159,7 +1159,7 @@ static int pxa_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt) } cicr2 = 0; - cicr3 = CICR3_LPF_VAL(icd->height - 1) | + cicr3 = CICR3_LPF_VAL(icd->rect_current.height - 1) | CICR3_BFW_VAL(min((unsigned short)255, icd->y_skip_top)); cicr4 |= pcdev->mclk_divisor; diff --git a/linux/drivers/media/video/sh_mobile_ceu_camera.c b/linux/drivers/media/video/sh_mobile_ceu_camera.c index 99ea30896..4c33c3efd 100644 --- a/linux/drivers/media/video/sh_mobile_ceu_camera.c +++ b/linux/drivers/media/video/sh_mobile_ceu_camera.c @@ -148,7 +148,8 @@ static int sh_mobile_ceu_videobuf_setup(struct videobuf_queue *vq, struct sh_mobile_ceu_dev *pcdev = ici->priv; int bytes_per_pixel = (icd->current_fmt->depth + 7) >> 3; - *size = PAGE_ALIGN(icd->width * icd->height * bytes_per_pixel); + *size = PAGE_ALIGN(icd->rect_current.width * icd->rect_current.height * + bytes_per_pixel); if (0 == *count) *count = 2; @@ -207,7 +208,7 @@ static void sh_mobile_ceu_capture(struct sh_mobile_ceu_dev *pcdev) phys_addr_top = videobuf_to_dma_contig(pcdev->active); ceu_write(pcdev, CDAYR, phys_addr_top); if (pcdev->is_interlaced) { - phys_addr_bottom = phys_addr_top + icd->width; + phys_addr_bottom = phys_addr_top + icd->rect_current.width; ceu_write(pcdev, CDBYR, phys_addr_bottom); } @@ -216,10 +217,12 @@ static void sh_mobile_ceu_capture(struct sh_mobile_ceu_dev *pcdev) case V4L2_PIX_FMT_NV21: case V4L2_PIX_FMT_NV16: case V4L2_PIX_FMT_NV61: - phys_addr_top += icd->width * icd->height; + phys_addr_top += icd->rect_current.width * + icd->rect_current.height; ceu_write(pcdev, CDACR, phys_addr_top); if (pcdev->is_interlaced) { - phys_addr_bottom = phys_addr_top + icd->width; + phys_addr_bottom = phys_addr_top + + icd->rect_current.width; ceu_write(pcdev, CDBCR, phys_addr_bottom); } } @@ -253,12 +256,12 @@ static int sh_mobile_ceu_videobuf_prepare(struct videobuf_queue *vq, BUG_ON(NULL == icd->current_fmt); if (buf->fmt != icd->current_fmt || - vb->width != icd->width || - vb->height != icd->height || + vb->width != icd->rect_current.width || + vb->height != icd->rect_current.height || vb->field != field) { buf->fmt = icd->current_fmt; - vb->width = icd->width; - vb->height = icd->height; + vb->width = icd->rect_current.width; + vb->height = icd->rect_current.height; vb->field = field; vb->state = VIDEOBUF_NEEDS_INIT; } @@ -477,17 +480,18 @@ static int sh_mobile_ceu_set_bus_param(struct soc_camera_device *icd, mdelay(1); if (yuv_mode) { - width = icd->width * 2; + width = icd->rect_current.width * 2; width = buswidth == 16 ? width / 2 : width; - cfszr_width = cdwdr_width = icd->width; + cfszr_width = cdwdr_width = icd->rect_current.width; } else { - width = icd->width * ((icd->current_fmt->depth + 7) >> 3); + width = icd->rect_current.width * + ((icd->current_fmt->depth + 7) >> 3); width = buswidth == 16 ? width / 2 : width; cfszr_width = buswidth == 8 ? width / 2 : width; cdwdr_width = buswidth == 16 ? width * 2 : width; } - height = icd->height; + height = icd->rect_current.height; if (pcdev->is_interlaced) { height /= 2; cdwdr_width *= 2; diff --git a/linux/drivers/media/video/soc_camera.c b/linux/drivers/media/video/soc_camera.c index 42e7acd9b..9a7139e31 100644 --- a/linux/drivers/media/video/soc_camera.c +++ b/linux/drivers/media/video/soc_camera.c @@ -289,17 +289,17 @@ static int soc_camera_set_fmt(struct soc_camera_file *icf, return -EINVAL; } - icd->width = pix->width; - icd->height = pix->height; - icf->vb_vidq.field = - icd->field = pix->field; + icd->rect_current.width = pix->width; + icd->rect_current.height = pix->height; + icf->vb_vidq.field = + icd->field = pix->field; if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) dev_warn(&icd->dev, "Attention! Wrong buf-type %d\n", f->type); dev_dbg(&icd->dev, "set width: %d height: %d\n", - icd->width, icd->height); + icd->rect_current.width, icd->rect_current.height); /* set physical bus parameters */ return ici->ops->set_bus_param(icd, pix->pixelformat); @@ -342,8 +342,8 @@ static int soc_camera_open(struct file *file) struct v4l2_format f = { .type = V4L2_BUF_TYPE_VIDEO_CAPTURE, .fmt.pix = { - .width = icd->width, - .height = icd->height, + .width = icd->rect_current.width, + .height = icd->rect_current.height, .field = icd->field, }, }; @@ -554,8 +554,8 @@ static int soc_camera_g_fmt_vid_cap(struct file *file, void *priv, WARN_ON(priv != file->private_data); - pix->width = icd->width; - pix->height = icd->height; + pix->width = icd->rect_current.width; + pix->height = icd->rect_current.height; pix->field = icf->vb_vidq.field; pix->pixelformat = icd->current_fmt->fourcc; pix->bytesperline = pix->width * @@ -719,12 +719,9 @@ static int soc_camera_cropcap(struct file *file, void *fh, struct soc_camera_device *icd = icf->icd; a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - a->bounds.left = icd->x_min; - a->bounds.top = icd->y_min; - a->bounds.width = icd->width_max; - a->bounds.height = icd->height_max; - a->defrect.left = icd->x_min; - a->defrect.top = icd->y_min; + a->bounds = icd->rect_max; + a->defrect.left = icd->rect_max.left; + a->defrect.top = icd->rect_max.top; a->defrect.width = DEFAULT_WIDTH; a->defrect.height = DEFAULT_HEIGHT; a->pixelaspect.numerator = 1; @@ -739,11 +736,8 @@ static int soc_camera_g_crop(struct file *file, void *fh, struct soc_camera_file *icf = file->private_data; struct soc_camera_device *icd = icf->icd; - a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - a->c.left = icd->x_current; - a->c.top = icd->y_current; - a->c.width = icd->width; - a->c.height = icd->height; + a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + a->c = icd->rect_current; return 0; } @@ -762,13 +756,29 @@ static int soc_camera_s_crop(struct file *file, void *fh, /* Cropping is allowed during a running capture, guard consistency */ mutex_lock(&icf->vb_vidq.vb_lock); + if (a->c.width > icd->rect_max.width) + a->c.width = icd->rect_max.width; + + if (a->c.width < icd->width_min) + a->c.width = icd->width_min; + + if (a->c.height > icd->rect_max.height) + a->c.height = icd->rect_max.height; + + if (a->c.height < icd->height_min) + a->c.height = icd->height_min; + + if (a->c.width + a->c.left > icd->rect_max.width + icd->rect_max.left) + a->c.left = icd->rect_max.width + icd->rect_max.left - + a->c.width; + + if (a->c.height + a->c.top > icd->rect_max.height + icd->rect_max.top) + a->c.top = icd->rect_max.height + icd->rect_max.top - + a->c.height; + ret = ici->ops->set_crop(icd, &a->c); - if (!ret) { - icd->width = a->c.width; - icd->height = a->c.height; - icd->x_current = a->c.left; - icd->y_current = a->c.top; - } + if (!ret) + icd->rect_current = a->c; mutex_unlock(&icf->vb_vidq.vb_lock); diff --git a/linux/drivers/media/video/soc_camera_platform.c b/linux/drivers/media/video/soc_camera_platform.c index 8168cf470..9e406c113 100644 --- a/linux/drivers/media/video/soc_camera_platform.c +++ b/linux/drivers/media/video/soc_camera_platform.c @@ -127,12 +127,12 @@ static int soc_camera_platform_probe(struct platform_device *pdev) platform_set_drvdata(pdev, priv); dev_set_drvdata(&icd->dev, &pdev->dev); - icd->width_min = 0; - icd->width_max = p->format.width; - icd->height_min = 0; - icd->height_max = p->format.height; - icd->y_skip_top = 0; - icd->ops = &soc_camera_platform_ops; + icd->width_min = 0; + icd->rect_max.width = p->format.width; + icd->height_min = 0; + icd->rect_max.height = p->format.height; + icd->y_skip_top = 0; + icd->ops = &soc_camera_platform_ops; ici = to_soc_camera_host(icd->dev.parent); diff --git a/linux/drivers/media/video/tw9910.c b/linux/drivers/media/video/tw9910.c index 61dc1b812..f1a146807 100644 --- a/linux/drivers/media/video/tw9910.c +++ b/linux/drivers/media/video/tw9910.c @@ -715,8 +715,8 @@ static int tw9910_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) struct soc_camera_device *icd = client->dev.platform_data; struct v4l2_pix_format *pix = &f->fmt.pix; struct v4l2_rect rect = { - .left = icd->x_current, - .top = icd->y_current, + .left = icd->rect_current.left, + .top = icd->rect_current.top, .width = pix->width, .height = pix->height, }; @@ -840,6 +840,19 @@ static struct v4l2_subdev_ops tw9910_subdev_ops = { * i2c_driver function */ +static void limit_to_scale(struct soc_camera_device *icd, + const struct tw9910_scale_ctrl *scale) +{ + if (scale->width > icd->rect_max.width) + icd->rect_max.width = scale->width; + if (scale->width < icd->width_min) + icd->width_min = scale->width; + if (scale->height > icd->rect_max.height) + icd->rect_max.height = scale->height; + if (scale->height < icd->height_min) + icd->height_min = scale->height; +} + #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26) static int tw9910_probe(struct i2c_client *client) #else @@ -889,25 +902,18 @@ static int tw9910_probe(struct i2c_client *client, /* * set width and height */ - icd->width_max = tw9910_ntsc_scales[0].width; /* set default */ + icd->rect_max.width = tw9910_ntsc_scales[0].width; /* set default */ icd->width_min = tw9910_ntsc_scales[0].width; - icd->height_max = tw9910_ntsc_scales[0].height; + icd->rect_max.height = tw9910_ntsc_scales[0].height; icd->height_min = tw9910_ntsc_scales[0].height; scale = tw9910_ntsc_scales; - for (i = 0; i < ARRAY_SIZE(tw9910_ntsc_scales); i++) { - icd->width_max = max(scale[i].width, icd->width_max); - icd->width_min = min(scale[i].width, icd->width_min); - icd->height_max = max(scale[i].height, icd->height_max); - icd->height_min = min(scale[i].height, icd->height_min); - } + for (i = 0; i < ARRAY_SIZE(tw9910_ntsc_scales); i++) + limit_to_scale(icd, scale + i); + scale = tw9910_pal_scales; - for (i = 0; i < ARRAY_SIZE(tw9910_pal_scales); i++) { - icd->width_max = max(scale[i].width, icd->width_max); - icd->width_min = min(scale[i].width, icd->width_min); - icd->height_max = max(scale[i].height, icd->height_max); - icd->height_min = min(scale[i].height, icd->height_min); - } + for (i = 0; i < ARRAY_SIZE(tw9910_pal_scales); i++) + limit_to_scale(icd, scale + i); ret = tw9910_video_probe(icd, client); if (ret) { -- cgit v1.2.3 From bbbc50159e8cab3ba46fe1491657840d91490829 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Tue, 25 Aug 2009 16:46:42 +0200 Subject: ov772x: successful S_FMT and S_CROP must update user-provided rectangle From: Guennadi Liakhovetski Signed-off-by: Guennadi Liakhovetski Priority: low --- drivers/media/video/ov772x.c | 11 +++++++---- 1 files changed, 7 insertions(+), 4 deletions(-) --- linux/drivers/media/video/ov772x.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/ov772x.c b/linux/drivers/media/video/ov772x.c index a853c3514..a9f9c04c1 100644 --- a/linux/drivers/media/video/ov772x.c +++ b/linux/drivers/media/video/ov772x.c @@ -806,7 +806,7 @@ static const struct ov772x_win_size *ov772x_select_win(u32 width, u32 height) } static int ov772x_set_params(struct i2c_client *client, - u32 width, u32 height, u32 pixfmt) + u32 *width, u32 *height, u32 pixfmt) { struct ov772x_priv *priv = to_ov772x(client); int ret = -EINVAL; @@ -829,7 +829,7 @@ static int ov772x_set_params(struct i2c_client *client, /* * select win */ - priv->win = ov772x_select_win(width, height); + priv->win = ov772x_select_win(*width, *height); /* * reset hardware @@ -941,6 +941,9 @@ static int ov772x_set_params(struct i2c_client *client, goto ov772x_set_fmt_error; } + *width = priv->win->width; + *height = priv->win->height; + return ret; ov772x_set_fmt_error: @@ -961,7 +964,7 @@ static int ov772x_set_crop(struct soc_camera_device *icd, if (!priv->fmt) return -EINVAL; - return ov772x_set_params(client, rect->width, rect->height, + return ov772x_set_params(client, &rect->width, &rect->height, priv->fmt->fourcc); } @@ -970,7 +973,7 @@ static int ov772x_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) struct i2c_client *client = sd->priv; struct v4l2_pix_format *pix = &f->fmt.pix; - return ov772x_set_params(client, pix->width, pix->height, + return ov772x_set_params(client, &pix->width, &pix->height, pix->pixelformat); } -- cgit v1.2.3 From 5eccdb2f169fdba3dcf0eef1f8c87a8232fa3cf0 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Tue, 25 Aug 2009 16:46:42 +0200 Subject: mt9t031: improve rectangle placement in invalid S_CROP From: Guennadi Liakhovetski 1. soc-camera always requests a valid rectangle, when calling .s_fmt(), no need to check and adjust 2. in .s_crop(), if the rectangle exceeds sensor limits, push it to the respective border instead of centering 3. take into account left and top borders when checking Signed-off-by: Guennadi Liakhovetski Priority: low --- drivers/media/video/mt9t031.c | 18 +++++++++--------- 1 files changed, 9 insertions(+), 9 deletions(-) --- linux/drivers/media/video/mt9t031.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/mt9t031.c b/linux/drivers/media/video/mt9t031.c index 405fe5c25..b69a34c87 100644 --- a/linux/drivers/media/video/mt9t031.c +++ b/linux/drivers/media/video/mt9t031.c @@ -240,15 +240,6 @@ static int mt9t031_set_params(struct soc_camera_device *icd, const u16 hblank = MT9T031_HORIZONTAL_BLANK, vblank = MT9T031_VERTICAL_BLANK; - /* Make sure we don't exceed sensor limits */ - if (rect->left + rect->width > icd->rect_max.width) - rect->left = (icd->rect_max.width - rect->width) / 2 + - icd->rect_max.left; - - if (rect->top + rect->height > icd->rect_max.height) - rect->top = (icd->rect_max.height - rect->height) / 2 + - icd->rect_max.top; - width = rect->width * xskip; height = rect->height * yskip; left = rect->left * xskip; @@ -336,6 +327,15 @@ static int mt9t031_set_crop(struct soc_camera_device *icd, struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); struct mt9t031 *mt9t031 = to_mt9t031(client); + /* Make sure we don't exceed sensor limits */ + if (rect->left + rect->width > icd->rect_max.left + icd->rect_max.width) + rect->left = icd->rect_max.width + icd->rect_max.left - + rect->width; + + if (rect->top + rect->height > icd->rect_max.height + icd->rect_max.top) + rect->top = icd->rect_max.height + icd->rect_max.top - + rect->height; + /* CROP - no change in scaling, or in limits */ return mt9t031_set_params(icd, rect, mt9t031->xskip, mt9t031->yskip); } -- cgit v1.2.3 From 50dda2d882c41d334002fb2437c66080c5d87080 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Tue, 25 Aug 2009 16:46:42 +0200 Subject: ov772x: S_CROP must return actually configured geometry From: Guennadi Liakhovetski V4L2 drivers are allowed to configure a geometry different than what has been requested by the user with S_CROP, but then they have to adjust the input rectangle accordingly. Fix ov772x to comply with this requirement. Signed-off-by: Guennadi Liakhovetski Priority: low --- drivers/media/video/ov772x.c | 10 ++++++++-- 1 files changed, 8 insertions(+), 2 deletions(-) --- linux/drivers/media/video/ov772x.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/ov772x.c b/linux/drivers/media/video/ov772x.c index a9f9c04c1..700f655fd 100644 --- a/linux/drivers/media/video/ov772x.c +++ b/linux/drivers/media/video/ov772x.c @@ -960,12 +960,18 @@ static int ov772x_set_crop(struct soc_camera_device *icd, { struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); struct ov772x_priv *priv = to_ov772x(client); + int ret; if (!priv->fmt) return -EINVAL; - return ov772x_set_params(client, &rect->width, &rect->height, - priv->fmt->fourcc); + ret = ov772x_set_params(client, &rect->width, &rect->height, + priv->fmt->fourcc); + if (!ret) { + rect->left = 0; + rect->top = 0; + } + return ret; } static int ov772x_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) -- cgit v1.2.3 From 1e42790cf4308ec89ea72d095fe8aa119ea43dc5 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Tue, 25 Aug 2009 16:46:43 +0200 Subject: soc-camera: put pixel format initialisation back in probe, add .put_formats() From: Guennadi Liakhovetski The move of format translation initialisation into soc_camera_open() was temporary for the soc-camera as platform driver intermediate step, put it back into soc_camera_probe(). Also add a .put_formats() method to soc_camera_host_ops to free any resources host driver might have allocated in .get_formats(). Signed-off-by: Guennadi Liakhovetski Priority: low --- drivers/media/video/soc_camera.c | 50 ++++++++++++++++++++++++++----------- include/media/soc_camera.h | 7 +++++ 2 files changed, 42 insertions(+), 15 deletions(-) --- linux/drivers/media/video/soc_camera.c | 50 ++++++++++++++++++++++++---------- 1 file changed, 35 insertions(+), 15 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/soc_camera.c b/linux/drivers/media/video/soc_camera.c index 9a7139e31..dd348a0b3 100644 --- a/linux/drivers/media/video/soc_camera.c +++ b/linux/drivers/media/video/soc_camera.c @@ -212,7 +212,7 @@ static int soc_camera_dqbuf(struct file *file, void *priv, static int soc_camera_init_user_formats(struct soc_camera_device *icd) { struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); - int i, fmts = 0; + int i, fmts = 0, ret; if (!ici->ops->get_formats) /* @@ -225,8 +225,12 @@ static int soc_camera_init_user_formats(struct soc_camera_device *icd) * First pass - only count formats this host-sensor * configuration can provide */ - for (i = 0; i < icd->num_formats; i++) - fmts += ici->ops->get_formats(icd, i, NULL); + for (i = 0; i < icd->num_formats; i++) { + ret = ici->ops->get_formats(icd, i, NULL); + if (ret < 0) + return ret; + fmts += ret; + } if (!fmts) return -ENXIO; @@ -248,19 +252,32 @@ static int soc_camera_init_user_formats(struct soc_camera_device *icd) icd->user_formats[i].cam_fmt = icd->formats + i; icd->user_formats[i].buswidth = icd->formats[i].depth; } else { - fmts += ici->ops->get_formats(icd, i, - &icd->user_formats[fmts]); + ret = ici->ops->get_formats(icd, i, + &icd->user_formats[fmts]); + if (ret < 0) + goto egfmt; + fmts += ret; } icd->current_fmt = icd->user_formats[0].host_fmt; return 0; + +egfmt: + icd->num_user_formats = 0; + vfree(icd->user_formats); + return ret; } /* Always entered with .video_lock held */ static void soc_camera_free_user_formats(struct soc_camera_device *icd) { + struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); + + if (ici->ops->put_formats) + ici->ops->put_formats(icd); icd->current_fmt = NULL; + icd->num_user_formats = 0; vfree(icd->user_formats); icd->user_formats = NULL; } @@ -345,16 +362,11 @@ static int soc_camera_open(struct file *file) .width = icd->rect_current.width, .height = icd->rect_current.height, .field = icd->field, + .pixelformat = icd->current_fmt->fourcc, + .colorspace = icd->current_fmt->colorspace, }, }; - ret = soc_camera_init_user_formats(icd); - if (ret < 0) - goto eiufmt; - - f.fmt.pix.pixelformat = icd->current_fmt->fourcc; - f.fmt.pix.colorspace = icd->current_fmt->colorspace; - if (icl->power) { ret = icl->power(icd->pdev, 1); if (ret < 0) @@ -405,8 +417,6 @@ eiciadd: if (icl->power) icl->power(icd->pdev, 0); epower: - soc_camera_free_user_formats(icd); -eiufmt: icd->use_count--; mutex_unlock(&icd->video_lock); module_put(ici->ops->owner); @@ -432,7 +442,6 @@ static int soc_camera_close(struct file *file) ici->ops->remove(icd); if (icl->power) icl->power(icd->pdev, 0); - soc_camera_free_user_formats(icd); } mutex_unlock(&icd->video_lock); @@ -955,6 +964,14 @@ static int soc_camera_probe(struct device *dev) } } + /* At this point client .probe() should have run already */ + ret = soc_camera_init_user_formats(icd); + if (ret < 0) + goto eiufmt; + + icd->rect_current = icd->rect_max; + icd->field = V4L2_FIELD_ANY; + /* ..._video_start() will create a device node, so we have to protect */ mutex_lock(&icd->video_lock); @@ -979,6 +996,8 @@ static int soc_camera_probe(struct device *dev) evidstart: mutex_unlock(&icd->video_lock); + soc_camera_free_user_formats(icd); +eiufmt: if (icl->board_info) { soc_camera_free_i2c(icd); } else { @@ -1024,6 +1043,7 @@ static int soc_camera_remove(struct device *dev) module_put(drv->owner); } } + soc_camera_free_user_formats(icd); return 0; } -- cgit v1.2.3 From 476b4e44d0836e75896fd12b0d5f33fdc706bee9 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Tue, 25 Aug 2009 16:46:51 +0200 Subject: sh-mobile-ceu-camera: do not wait for interrupt when releasing buffers From: Guennadi Liakhovetski Patch [PATCH] video: use videobuf_waiton() in sh_mobile_ceu free_buffer() was not quite correct. It closed a race, but introduced a potential lock-up, if for some reason an interrupt does not come. This has been observed in tests with tw9910. This patch safely dequeues buffers without waiting for their completion. It also moves a buffer state assignment under a spinlock to make it atomic with queuing of the buffer. Signed-off-by: Guennadi Liakhovetski Priority: low --- drivers/media/video/sh_mobile_ceu_camera.c | 27 +++++++++++++++++++++++++++ 1 files changed, 27 insertions(+), 0 deletions(-) --- linux/drivers/media/video/sh_mobile_ceu_camera.c | 27 ++++++++++++++++++++++++ 1 file changed, 27 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/sh_mobile_ceu_camera.c b/linux/drivers/media/video/sh_mobile_ceu_camera.c index 4c33c3efd..f54a9f23f 100644 --- a/linux/drivers/media/video/sh_mobile_ceu_camera.c +++ b/linux/drivers/media/video/sh_mobile_ceu_camera.c @@ -309,6 +309,27 @@ static void sh_mobile_ceu_videobuf_queue(struct videobuf_queue *vq, static void sh_mobile_ceu_videobuf_release(struct videobuf_queue *vq, struct videobuf_buffer *vb) { + struct soc_camera_device *icd = vq->priv_data; + struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); + struct sh_mobile_ceu_dev *pcdev = ici->priv; + unsigned long flags; + + spin_lock_irqsave(&pcdev->lock, flags); + + if (pcdev->active == vb) { + /* disable capture (release DMA buffer), reset */ + ceu_write(pcdev, CAPSR, 1 << 16); + pcdev->active = NULL; + } + + if ((vb->state == VIDEOBUF_ACTIVE || vb->state == VIDEOBUF_QUEUED) && + !list_empty(&vb->queue)) { + vb->state = VIDEOBUF_ERROR; + list_del_init(&vb->queue); + } + + spin_unlock_irqrestore(&pcdev->lock, flags); + free_buffer(vq, container_of(vb, struct sh_mobile_ceu_buffer, vb)); } @@ -328,6 +349,10 @@ static irqreturn_t sh_mobile_ceu_irq(int irq, void *data) spin_lock_irqsave(&pcdev->lock, flags); vb = pcdev->active; + if (!vb) + /* Stale interrupt from a released buffer */ + goto out; + list_del_init(&vb->queue); if (!list_empty(&pcdev->capture)) @@ -342,6 +367,8 @@ static irqreturn_t sh_mobile_ceu_irq(int irq, void *data) do_gettimeofday(&vb->ts); vb->field_count++; wake_up(&vb->done); + +out: spin_unlock_irqrestore(&pcdev->lock, flags); return IRQ_HANDLED; -- cgit v1.2.3 From 4cba5b9dc9691179938d5481bda3c97e376e0964 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Tue, 25 Aug 2009 16:46:51 +0200 Subject: soc-camera: use .s_std() from struct v4l2_subdev_core_ops From: Guennadi Liakhovetski Remove .set_std() method from struct soc_camera_ops, use .s_std() from struct v4l2_subdev_core_ops instead. Signed-off-by: Guennadi Liakhovetski Priority: low --- drivers/media/video/soc_camera.c | 7 ++----- include/media/soc_camera.h | 1 - 2 files changed, 2 insertions(+), 6 deletions(-) --- linux/drivers/media/video/soc_camera.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/soc_camera.c b/linux/drivers/media/video/soc_camera.c index dd348a0b3..104496141 100644 --- a/linux/drivers/media/video/soc_camera.c +++ b/linux/drivers/media/video/soc_camera.c @@ -153,12 +153,9 @@ static int soc_camera_s_std(struct file *file, void *priv, v4l2_std_id *a) { struct soc_camera_file *icf = file->private_data; struct soc_camera_device *icd = icf->icd; - int ret = 0; - - if (icd->ops->set_std) - ret = icd->ops->set_std(icd, a); + struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); - return ret; + return v4l2_device_call_until_err(&ici->v4l2_dev, (__u32)icd, core, s_std, *a); } static int soc_camera_reqbufs(struct file *file, void *priv, -- cgit v1.2.3 From 83741e5418caf367ba88caf33d4475755826ff4f Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Tue, 25 Aug 2009 16:46:52 +0200 Subject: sh-mobile-ceu-camera: implement host-side cropping From: Guennadi Liakhovetski Not all video capture devices can configure arbitrary cropping, whereas the CEU module on SuperH CPUs can crop with pixel precision. However, we want to use camera cropping if possible to save bandwidth and increase the frame-rate. This patch verifies whether the camera managed to crop exactly the requested rectangle, and if not, uses host-side cropping. To be able to crop on CEU we have to preserve camera rectangle too, for which the host_priv member in struct soc_camera_device is used. We now allocate memory dynamically, thus we have to use the .put_formats() method from struct soc_camera_host_ops to free it. Signed-off-by: Guennadi Liakhovetski Priority: low --- drivers/media/video/sh_mobile_ceu_camera.c | 309 +++++++++++++++++++++++----- 1 files changed, 259 insertions(+), 50 deletions(-) --- linux/drivers/media/video/sh_mobile_ceu_camera.c | 309 +++++++++++++++++++---- 1 file changed, 259 insertions(+), 50 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/sh_mobile_ceu_camera.c b/linux/drivers/media/video/sh_mobile_ceu_camera.c index f54a9f23f..befc84ce1 100644 --- a/linux/drivers/media/video/sh_mobile_ceu_camera.c +++ b/linux/drivers/media/video/sh_mobile_ceu_camera.c @@ -94,10 +94,17 @@ struct sh_mobile_ceu_dev { spinlock_t lock; struct list_head capture; struct videobuf_buffer *active; - int is_interlaced; struct sh_mobile_ceu_info *pdata; + unsigned int is_interlaced:1; + unsigned int image_mode:1; + unsigned int is_16bit:1; +}; + +struct sh_mobile_ceu_cam { + struct v4l2_rect camera_rect; + const struct soc_camera_data_format *extra_fmt; const struct soc_camera_data_format *camera_fmt; }; @@ -430,14 +437,101 @@ static void sh_mobile_ceu_remove_device(struct soc_camera_device *icd) pcdev->icd = NULL; } +static void sh_mobile_ceu_set_rect(struct soc_camera_device *icd, + struct v4l2_rect *rect) +{ + struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); + struct sh_mobile_ceu_cam *cam = icd->host_priv; + struct sh_mobile_ceu_dev *pcdev = ici->priv; + int width, height, cfszr_width, cdwdr_width; + unsigned int left_offset, top_offset; + u32 camor; + + if (rect->left > cam->camera_rect.left) { + left_offset = rect->left - cam->camera_rect.left; + } else { + left_offset = 0; + rect->left = cam->camera_rect.left; + } + + if (rect->top > cam->camera_rect.top) { + top_offset = rect->top - cam->camera_rect.top; + } else { + top_offset = 0; + rect->top = cam->camera_rect.top; + } + + dev_dbg(&icd->dev, "Offsets %u:%u\n", left_offset, top_offset); + + if (pcdev->image_mode) { + width = rect->width; + if (!pcdev->is_16bit) + width *= 2; + cfszr_width = cdwdr_width = rect->width; + } else { + width = rect->width * + ((icd->current_fmt->depth + 7) >> 3); + width = pcdev->is_16bit ? width / 2 : width; + cfszr_width = pcdev->is_16bit ? width : width / 2; + cdwdr_width = pcdev->is_16bit ? width * 2 : width; + } + + height = rect->height; + if (pcdev->is_interlaced) { + height /= 2; + cdwdr_width *= 2; + } + + camor = left_offset | (top_offset << 16); + ceu_write(pcdev, CAMOR, camor); + ceu_write(pcdev, CAPWR, (height << 16) | width); + ceu_write(pcdev, CFSZR, (height << 16) | cfszr_width); + ceu_write(pcdev, CDWDR, cdwdr_width); +} + +static u32 capture_save_reset(struct sh_mobile_ceu_dev *pcdev) +{ + u32 capsr = ceu_read(pcdev, CAPSR); + ceu_write(pcdev, CAPSR, 1 << 16); /* reset, stop capture */ + return capsr; +} + +static void capture_restore(struct sh_mobile_ceu_dev *pcdev, u32 capsr) +{ + unsigned long timeout = jiffies + 10 * HZ; + + /* + * Wait until the end of the current frame. It can take a long time, + * but if it has been aborted by a CAPSR reset, it shoule exit sooner. + */ + while ((ceu_read(pcdev, CSTSR) & 1) && time_before(jiffies, timeout)) + msleep(1); + + if (time_after(jiffies, timeout)) { + dev_err(pcdev->ici.v4l2_dev.dev, + "Timeout waiting for frame end! Interface problem?\n"); + return; + } + + /* Wait until reset clears, this shall not hang... */ + while (ceu_read(pcdev, CAPSR) & (1 << 16)) + udelay(10); + + /* Anything to restore? */ + if (capsr & ~(1 << 16)) + ceu_write(pcdev, CAPSR, capsr); +} + static int sh_mobile_ceu_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt) { struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); struct sh_mobile_ceu_dev *pcdev = ici->priv; - int ret, buswidth, width, height, cfszr_width, cdwdr_width; + int ret; unsigned long camera_flags, common_flags, value; - int yuv_mode, yuv_lineskip; + int yuv_lineskip; + struct sh_mobile_ceu_cam *cam = icd->host_priv; + u32 capsr = capture_save_reset(pcdev); camera_flags = icd->ops->query_bus_param(icd); common_flags = soc_camera_bus_param_compatible(camera_flags, @@ -451,10 +545,10 @@ static int sh_mobile_ceu_set_bus_param(struct soc_camera_device *icd, switch (common_flags & SOCAM_DATAWIDTH_MASK) { case SOCAM_DATAWIDTH_8: - buswidth = 8; + pcdev->is_16bit = 0; break; case SOCAM_DATAWIDTH_16: - buswidth = 16; + pcdev->is_16bit = 1; break; default: return -EINVAL; @@ -464,7 +558,7 @@ static int sh_mobile_ceu_set_bus_param(struct soc_camera_device *icd, ceu_write(pcdev, CRCMPR, 0); value = 0x00000010; /* data fetch by default */ - yuv_mode = yuv_lineskip = 0; + pcdev->image_mode = yuv_lineskip = 0; switch (icd->current_fmt->fourcc) { case V4L2_PIX_FMT_NV12: @@ -473,8 +567,8 @@ static int sh_mobile_ceu_set_bus_param(struct soc_camera_device *icd, /* fall-through */ case V4L2_PIX_FMT_NV16: case V4L2_PIX_FMT_NV61: - yuv_mode = 1; - switch (pcdev->camera_fmt->fourcc) { + pcdev->image_mode = 1; + switch (cam->camera_fmt->fourcc) { case V4L2_PIX_FMT_UYVY: value = 0x00000000; /* Cb0, Y0, Cr0, Y1 */ break; @@ -498,36 +592,16 @@ static int sh_mobile_ceu_set_bus_param(struct soc_camera_device *icd, value |= common_flags & SOCAM_VSYNC_ACTIVE_LOW ? 1 << 1 : 0; value |= common_flags & SOCAM_HSYNC_ACTIVE_LOW ? 1 << 0 : 0; - value |= buswidth == 16 ? 1 << 12 : 0; + value |= pcdev->is_16bit ? 1 << 12 : 0; ceu_write(pcdev, CAMCR, value); ceu_write(pcdev, CAPCR, 0x00300000); ceu_write(pcdev, CAIFR, pcdev->is_interlaced ? 0x101 : 0); mdelay(1); + sh_mobile_ceu_set_rect(icd, &icd->rect_current); - if (yuv_mode) { - width = icd->rect_current.width * 2; - width = buswidth == 16 ? width / 2 : width; - cfszr_width = cdwdr_width = icd->rect_current.width; - } else { - width = icd->rect_current.width * - ((icd->current_fmt->depth + 7) >> 3); - width = buswidth == 16 ? width / 2 : width; - cfszr_width = buswidth == 8 ? width / 2 : width; - cdwdr_width = buswidth == 16 ? width * 2 : width; - } - - height = icd->rect_current.height; - if (pcdev->is_interlaced) { - height /= 2; - cdwdr_width *= 2; - } - - ceu_write(pcdev, CAMOR, 0); - ceu_write(pcdev, CAPWR, (height << 16) | width); ceu_write(pcdev, CFLCR, 0); /* no scaling */ - ceu_write(pcdev, CFSZR, (height << 16) | cfszr_width); /* A few words about byte order (observed in Big Endian mode) * @@ -546,10 +620,16 @@ static int sh_mobile_ceu_set_bus_param(struct soc_camera_device *icd, value &= ~0x00000010; /* convert 4:2:2 -> 4:2:0 */ ceu_write(pcdev, CDOCR, value); - - ceu_write(pcdev, CDWDR, cdwdr_width); ceu_write(pcdev, CFWCR, 0); /* keep "datafetch firewall" disabled */ + dev_dbg(&icd->dev, "S_FMT successful for %c%c%c%c %ux%u@%u.%u\n", + pixfmt & 0xff, (pixfmt >> 8) & 0xff, + (pixfmt >> 16) & 0xff, (pixfmt >> 24) & 0xff, + icd->rect_current.width, icd->rect_current.height, + icd->rect_current.left, icd->rect_current.top); + + capture_restore(pcdev, capsr); + /* not in bundle mode: skip CBDSR, CDAYR2, CDACR2, CDBYR2, CDBCR2 */ return 0; } @@ -602,21 +682,32 @@ static int sh_mobile_ceu_get_formats(struct soc_camera_device *icd, int idx, struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); int ret, k, n; int formats = 0; + struct sh_mobile_ceu_cam *cam; ret = sh_mobile_ceu_try_bus_param(icd); if (ret < 0) return 0; + if (!icd->host_priv) { + cam = kzalloc(sizeof(*cam), GFP_KERNEL); + if (!cam) + return -ENOMEM; + + icd->host_priv = cam; + } else { + cam = icd->host_priv; + } + /* Beginning of a pass */ if (!idx) - icd->host_priv = NULL; + cam->extra_fmt = NULL; switch (icd->formats[idx].fourcc) { case V4L2_PIX_FMT_UYVY: case V4L2_PIX_FMT_VYUY: case V4L2_PIX_FMT_YUYV: case V4L2_PIX_FMT_YVYU: - if (icd->host_priv) + if (cam->extra_fmt) goto add_single_format; /* @@ -628,7 +719,7 @@ static int sh_mobile_ceu_get_formats(struct soc_camera_device *icd, int idx, * the host_priv pointer and check whether the format you're * going to add now is already there. */ - icd->host_priv = (void *)sh_mobile_ceu_formats; + cam->extra_fmt = (void *)sh_mobile_ceu_formats; n = ARRAY_SIZE(sh_mobile_ceu_formats); formats += n; @@ -659,18 +750,130 @@ add_single_format: return formats; } +static void sh_mobile_ceu_put_formats(struct soc_camera_device *icd) +{ + kfree(icd->host_priv); + icd->host_priv = NULL; +} + +static bool is_smaller(struct v4l2_rect *r1, struct v4l2_rect *r2) +{ + return r1->width < r2->width || r1->height < r2->height; +} + static int sh_mobile_ceu_set_crop(struct soc_camera_device *icd, struct v4l2_rect *rect) { - return icd->ops->set_crop(icd, rect); + struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); + struct sh_mobile_ceu_dev *pcdev = ici->priv; + struct v4l2_rect cam_rect = *rect; + struct sh_mobile_ceu_cam *cam = icd->host_priv; + unsigned short width, height; + u32 capsr; + int ret; + + capsr = capture_save_reset(pcdev); + dev_dbg(&icd->dev, "CAPSR %x\n", capsr); + + ret = icd->ops->set_crop(icd, &cam_rect); + if (!ret && !memcmp(rect, &cam_rect, sizeof(*rect))) { + dev_dbg(&icd->dev, "Camera S_CROP successful for %ux%u@%u.%u\n", + cam_rect.width, cam_rect.height, + cam_rect.left, cam_rect.top); + goto ceu_set_rect; + } + + /* Try to fix cropping, that camera hasn't managed to do */ + dev_dbg(&icd->dev, "Fix camera S_CROP %d for %ux%u@%u.%u\n", + ret, cam_rect.width, cam_rect.height, + cam_rect.left, cam_rect.top); + + /* + * Popular special case - some cameras can only handle fixed sizes like + * QVGA, VGA,... Take care to avoid infinite loop. + */ + width = max(cam_rect.width, 1) * 2; + height = max(cam_rect.height, 1) * 2; + while (!ret && is_smaller(&cam_rect, rect) && + (icd->rect_max.width >= width && + icd->rect_max.height >= height)) { + cam_rect.width = width; + cam_rect.height = height; + + if (cam_rect.width + cam_rect.left > + icd->rect_max.width + icd->rect_max.left) + cam_rect.left = icd->rect_max.width + + icd->rect_max.left - cam_rect.width; + + if (cam_rect.height + cam_rect.top > + icd->rect_max.height + icd->rect_max.top) + cam_rect.top = icd->rect_max.height + + icd->rect_max.top - cam_rect.height; + + ret = icd->ops->set_crop(icd, &cam_rect); + dev_dbg(&icd->dev, "Camera S_CROP %d for %ux%u@%u.%u\n", + ret, cam_rect.width, cam_rect.height, + cam_rect.left, cam_rect.top); + width *= 2; + height *= 2; + } + + /* + * If the camera failed to configure cropping, it should not modify the + * rectangle + */ + if ((ret < 0 && is_smaller(&icd->rect_current, rect)) || + is_smaller(&cam_rect, rect)) { + /* + * The camera failed to configure a suitable cropping, + * we cannot use the current rectangle, set to max + */ + cam_rect = icd->rect_max; + ret = icd->ops->set_crop(icd, &cam_rect); + dev_dbg(&icd->dev, "Camera S_CROP %d for max %ux%u@%u.%u\n", + ret, cam_rect.width, cam_rect.height, + cam_rect.left, cam_rect.top); + if (ret < 0) + /* All failed, hopefully resume current capture */ + goto resume_capture; + } + + /* We now have a rectangle, larger than requested, let's crop */ + + /* + * We have to preserve camera rectangle between close() / open(), + * because soc-camera core calls .set_fmt() on each first open() with + * last before last close() _user_ rectangle, which can be different + * from camera rectangle. + */ + dev_dbg(&icd->dev, "SH S_CROP from %ux%u@%u.%u to %ux%u@%u.%u\n", + cam_rect.width, cam_rect.height, cam_rect.left, cam_rect.top, + rect->width, rect->height, rect->left, rect->top); + + ret = 0; + +ceu_set_rect: + cam->camera_rect = cam_rect; + + /* Set CAMOR, CAPWR, CFSZR, take care of CDWDR */ + if (pcdev->active) + capsr |= 1; + sh_mobile_ceu_set_rect(icd, rect); + capture_restore(pcdev, capsr); + +resume_capture: + + /* Even if only camera cropping succeeded */ + return ret; } static int sh_mobile_ceu_set_fmt(struct soc_camera_device *icd, struct v4l2_format *f) { struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); - struct sh_mobile_ceu_dev *pcdev = ici->priv; - __u32 pixfmt = f->fmt.pix.pixelformat; + struct sh_mobile_ceu_cam *cam = icd->host_priv; + struct v4l2_pix_format *pix = &f->fmt.pix; + __u32 pixfmt = pix->pixelformat; const struct soc_camera_format_xlate *xlate; int ret; @@ -680,13 +883,17 @@ static int sh_mobile_ceu_set_fmt(struct soc_camera_device *icd, return -EINVAL; } - f->fmt.pix.pixelformat = xlate->cam_fmt->fourcc; + pix->pixelformat = xlate->cam_fmt->fourcc; ret = v4l2_device_call_until_err(&ici->v4l2_dev, (__u32)icd, video, s_fmt, f); - f->fmt.pix.pixelformat = pixfmt; + pix->pixelformat = pixfmt; if (!ret) { icd->buswidth = xlate->buswidth; icd->current_fmt = xlate->host_fmt; - pcdev->camera_fmt = xlate->cam_fmt; + cam->camera_fmt = xlate->cam_fmt; + cam->camera_rect.width = pix->width; + cam->camera_rect.height = pix->height; + cam->camera_rect.left = icd->rect_current.left; + cam->camera_rect.top = icd->rect_current.top; } return ret; @@ -698,7 +905,8 @@ static int sh_mobile_ceu_try_fmt(struct soc_camera_device *icd, struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); struct sh_mobile_ceu_dev *pcdev = ici->priv; const struct soc_camera_format_xlate *xlate; - __u32 pixfmt = f->fmt.pix.pixelformat; + struct v4l2_pix_format *pix = &f->fmt.pix; + __u32 pixfmt = pix->pixelformat; int ret; xlate = soc_camera_xlate_by_fourcc(icd, pixfmt); @@ -709,27 +917,27 @@ static int sh_mobile_ceu_try_fmt(struct soc_camera_device *icd, /* FIXME: calculate using depth and bus width */ - v4l_bound_align_image(&f->fmt.pix.width, 2, 2560, 1, - &f->fmt.pix.height, 4, 1920, 2, 0); + v4l_bound_align_image(&pix->width, 2, 2560, 1, + &pix->height, 4, 1920, 2, 0); - f->fmt.pix.bytesperline = f->fmt.pix.width * + pix->bytesperline = pix->width * DIV_ROUND_UP(xlate->host_fmt->depth, 8); - f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline; + pix->sizeimage = pix->height * pix->bytesperline; - f->fmt.pix.pixelformat = xlate->cam_fmt->fourcc; + pix->pixelformat = xlate->cam_fmt->fourcc; /* limit to sensor capabilities */ ret = v4l2_device_call_until_err(&ici->v4l2_dev, (__u32)icd, video, try_fmt, f); - f->fmt.pix.pixelformat = pixfmt; + pix->pixelformat = pixfmt; if (ret < 0) return ret; - switch (f->fmt.pix.field) { + switch (pix->field) { case V4L2_FIELD_INTERLACED: pcdev->is_interlaced = 1; break; case V4L2_FIELD_ANY: - f->fmt.pix.field = V4L2_FIELD_NONE; + pix->field = V4L2_FIELD_NONE; /* fall-through */ case V4L2_FIELD_NONE: pcdev->is_interlaced = 0; @@ -858,6 +1066,7 @@ static struct soc_camera_host_ops sh_mobile_ceu_host_ops = { .add = sh_mobile_ceu_add_device, .remove = sh_mobile_ceu_remove_device, .get_formats = sh_mobile_ceu_get_formats, + .put_formats = sh_mobile_ceu_put_formats, .set_crop = sh_mobile_ceu_set_crop, .set_fmt = sh_mobile_ceu_set_fmt, .try_fmt = sh_mobile_ceu_try_fmt, -- cgit v1.2.3 From 0b4b46ce45c942a26e9a5b68cd826cbbcfb39d8f Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Tue, 25 Aug 2009 16:46:52 +0200 Subject: tw9910: return updated geometry on successful S_FMT and S_CROP From: Guennadi Liakhovetski Signed-off-by: Guennadi Liakhovetski Priority: low --- drivers/media/video/tw9910.c | 14 ++++++++++++-- 1 files changed, 12 insertions(+), 2 deletions(-) --- linux/drivers/media/video/tw9910.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/tw9910.c b/linux/drivers/media/video/tw9910.c index f1a146807..29bafb3f3 100644 --- a/linux/drivers/media/video/tw9910.c +++ b/linux/drivers/media/video/tw9910.c @@ -699,6 +699,11 @@ static int tw9910_set_crop(struct soc_camera_device *icd, if (ret < 0) goto tw9910_set_fmt_error; + rect->width = priv->scale->width; + rect->height = priv->scale->height; + rect->left = 0; + rect->top = 0; + return ret; tw9910_set_fmt_error: @@ -720,7 +725,7 @@ static int tw9910_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) .width = pix->width, .height = pix->height, }; - int i; + int i, ret; /* * check color format @@ -732,7 +737,12 @@ static int tw9910_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) if (i == ARRAY_SIZE(tw9910_color_fmt)) return -EINVAL; - return tw9910_set_crop(icd, &rect); + ret = tw9910_set_crop(icd, &rect); + if (!ret) { + pix->width = rect.width; + pix->height = rect.height; + } + return ret; } static int tw9910_try_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) -- cgit v1.2.3 From 4325d71881ee891f6b5313cdb76c08c1d95d2091 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Tue, 25 Aug 2009 16:46:52 +0200 Subject: soc-camera: S_CROP V4L2 API compliance fix From: Guennadi Liakhovetski V4L2 API mandates, that drivers do not update the argument of the S_CROP ioctl() with the actual geometry. Comply. Signed-off-by: Guennadi Liakhovetski Priority: low --- drivers/media/video/soc_camera.c | 39 ++++++++++++++++++++++--------------- 1 files changed, 23 insertions(+), 16 deletions(-) --- linux/drivers/media/video/soc_camera.c | 39 ++++++++++++++++++++-------------- 1 file changed, 23 insertions(+), 16 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/soc_camera.c b/linux/drivers/media/video/soc_camera.c index 104496141..e4740359d 100644 --- a/linux/drivers/media/video/soc_camera.c +++ b/linux/drivers/media/video/soc_camera.c @@ -748,12 +748,19 @@ static int soc_camera_g_crop(struct file *file, void *fh, return 0; } +/* + * According to the V4L2 API, drivers shall not update the struct v4l2_crop + * argument with the actual geometry, instead, the user shall use G_CROP to + * retrieve it. However, we expect camera host and client drivers to update + * the argument, which we then use internally, but do not return to the user. + */ static int soc_camera_s_crop(struct file *file, void *fh, struct v4l2_crop *a) { struct soc_camera_file *icf = file->private_data; struct soc_camera_device *icd = icf->icd; struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); + struct v4l2_rect rect = a->c; int ret; if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) @@ -762,29 +769,29 @@ static int soc_camera_s_crop(struct file *file, void *fh, /* Cropping is allowed during a running capture, guard consistency */ mutex_lock(&icf->vb_vidq.vb_lock); - if (a->c.width > icd->rect_max.width) - a->c.width = icd->rect_max.width; + if (rect.width > icd->rect_max.width) + rect.width = icd->rect_max.width; - if (a->c.width < icd->width_min) - a->c.width = icd->width_min; + if (rect.width < icd->width_min) + rect.width = icd->width_min; - if (a->c.height > icd->rect_max.height) - a->c.height = icd->rect_max.height; + if (rect.height > icd->rect_max.height) + rect.height = icd->rect_max.height; - if (a->c.height < icd->height_min) - a->c.height = icd->height_min; + if (rect.height < icd->height_min) + rect.height = icd->height_min; - if (a->c.width + a->c.left > icd->rect_max.width + icd->rect_max.left) - a->c.left = icd->rect_max.width + icd->rect_max.left - - a->c.width; + if (rect.width + rect.left > icd->rect_max.width + icd->rect_max.left) + rect.left = icd->rect_max.width + icd->rect_max.left - + rect.width; - if (a->c.height + a->c.top > icd->rect_max.height + icd->rect_max.top) - a->c.top = icd->rect_max.height + icd->rect_max.top - - a->c.height; + if (rect.height + rect.top > icd->rect_max.height + icd->rect_max.top) + rect.top = icd->rect_max.height + icd->rect_max.top - + rect.height; - ret = ici->ops->set_crop(icd, &a->c); + ret = ici->ops->set_crop(icd, &rect); if (!ret) - icd->rect_current = a->c; + icd->rect_current = rect; mutex_unlock(&icf->vb_vidq.vb_lock); -- cgit v1.2.3 From fee3ccfc8db428f3108858be9c73a4c28a618e4d Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Tue, 25 Aug 2009 16:46:53 +0200 Subject: soc-camera: prohibit geometry change with initialised buffers From: Guennadi Liakhovetski Prohibit S_FMT and S_CROP with a different window width or height after video buffer initialisation. This simplifies the work to be done in specific host and client drivers, and it doesn't seem to make much sense to allow these changes. We do however allow S_CROP with equal width and height to just move the window, this doesn't affect video buffer management and is usually easy enough to implement. Signed-off-by: Guennadi Liakhovetski Priority: low --- drivers/media/video/soc_camera.c | 14 ++++++++++++-- 1 files changed, 12 insertions(+), 2 deletions(-) --- linux/drivers/media/video/soc_camera.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/soc_camera.c b/linux/drivers/media/video/soc_camera.c index e4740359d..ec564a90e 100644 --- a/linux/drivers/media/video/soc_camera.c +++ b/linux/drivers/media/video/soc_camera.c @@ -518,8 +518,8 @@ static int soc_camera_s_fmt_vid_cap(struct file *file, void *priv, mutex_lock(&icf->vb_vidq.vb_lock); - if (videobuf_queue_is_busy(&icf->vb_vidq)) { - dev_err(&icd->dev, "S_FMT denied: queue busy\n"); + if (icf->vb_vidq.bufs[0]) { + dev_err(&icd->dev, "S_FMT denied: queue initialised\n"); ret = -EBUSY; goto unlock; } @@ -769,6 +769,15 @@ static int soc_camera_s_crop(struct file *file, void *fh, /* Cropping is allowed during a running capture, guard consistency */ mutex_lock(&icf->vb_vidq.vb_lock); + /* Prohibit window size change with initialised buffers */ + if (icf->vb_vidq.bufs[0] && (rect.width != icd->rect_current.width || + rect.height != icd->rect_current.height)) { + dev_err(&icd->dev, + "S_CROP denied: queue initialised and sizes differ\n"); + ret = -EBUSY; + goto unlock; + } + if (rect.width > icd->rect_max.width) rect.width = icd->rect_max.width; @@ -793,6 +802,7 @@ static int soc_camera_s_crop(struct file *file, void *fh, if (!ret) icd->rect_current = rect; +unlock: mutex_unlock(&icf->vb_vidq.vb_lock); return ret; -- cgit v1.2.3 From 4eb5903e517a1d50a63f75fef61090f5f90b81ea Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Tue, 25 Aug 2009 16:46:53 +0200 Subject: ov772x: do not use scaling for cropping From: Guennadi Liakhovetski OV772x sensors cannot crop, they only support two fixed formats: VGA and QVGA. We should not change the format when requested to crop, only S_FMT can do this. Signed-off-by: Guennadi Liakhovetski Priority: low --- drivers/media/video/ov772x.c | 17 ++++++++--------- 1 files changed, 8 insertions(+), 9 deletions(-) --- linux/drivers/media/video/ov772x.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/ov772x.c b/linux/drivers/media/video/ov772x.c index 700f655fd..e8bb337da 100644 --- a/linux/drivers/media/video/ov772x.c +++ b/linux/drivers/media/video/ov772x.c @@ -955,23 +955,22 @@ ov772x_set_fmt_error: return ret; } +/* Cannot crop, just return the current geometry */ static int ov772x_set_crop(struct soc_camera_device *icd, struct v4l2_rect *rect) { struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); struct ov772x_priv *priv = to_ov772x(client); - int ret; - if (!priv->fmt) + if (!priv->fmt || !priv->win) return -EINVAL; - ret = ov772x_set_params(client, &rect->width, &rect->height, - priv->fmt->fourcc); - if (!ret) { - rect->left = 0; - rect->top = 0; - } - return ret; + rect->left = 0; + rect->top = 0; + rect->width = priv->win->width; + rect->height = priv->win->height; + + return 0; } static int ov772x_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) -- cgit v1.2.3 From 9be813fc0bfdb82513f0e232f0dda18b2dba8e84 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Tue, 25 Aug 2009 16:46:53 +0200 Subject: tw9910: do not lie about cropping abilities From: Guennadi Liakhovetski The current tw9910 driver does not implement cropping correctly. Therefore, and also because various rectangles in struct soc_camera_device are in user scale, we cannot and shall not use rect_current as window location. Signed-off-by: Guennadi Liakhovetski Priority: low --- drivers/media/video/tw9910.c | 6 ++++-- 1 files changed, 4 insertions(+), 2 deletions(-) --- linux/drivers/media/video/tw9910.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/tw9910.c b/linux/drivers/media/video/tw9910.c index 29bafb3f3..852c7859f 100644 --- a/linux/drivers/media/video/tw9910.c +++ b/linux/drivers/media/video/tw9910.c @@ -719,9 +719,10 @@ static int tw9910_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) struct i2c_client *client = sd->priv; struct soc_camera_device *icd = client->dev.platform_data; struct v4l2_pix_format *pix = &f->fmt.pix; + /* See tw9910_set_crop() - no proper cropping support */ struct v4l2_rect rect = { - .left = icd->rect_current.left, - .top = icd->rect_current.top, + .left = 0, + .top = 0, .width = pix->width, .height = pix->height, }; @@ -850,6 +851,7 @@ static struct v4l2_subdev_ops tw9910_subdev_ops = { * i2c_driver function */ +/* This is called during probe, so, setting rect_max is Ok here: scale == 1 */ static void limit_to_scale(struct soc_camera_device *icd, const struct tw9910_scale_ctrl *scale) { -- cgit v1.2.3 From 6bd7b0281dd65988d5cf613bc99541ef4a8f16cf Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Tue, 25 Aug 2009 16:46:54 +0200 Subject: sh_mobile_ceu_camera: implement host-side image scaling From: Guennadi Liakhovetski Use host-side image scaling when the client fails to set the requested format. We also have to take scaling into account when performing host-side cropping. Similar to cropping we try to use client-side scaling as much as possible to preserve bus bandwidth and optimise the frame-rate. Signed-off-by: Guennadi Liakhovetski Priority: low --- drivers/media/video/sh_mobile_ceu_camera.c | 392 +++++++++++++++++++++++----- 1 files changed, 321 insertions(+), 71 deletions(-) --- linux/drivers/media/video/sh_mobile_ceu_camera.c | 392 +++++++++++++++++++---- 1 file changed, 321 insertions(+), 71 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/sh_mobile_ceu_camera.c b/linux/drivers/media/video/sh_mobile_ceu_camera.c index befc84ce1..a1108cc03 100644 --- a/linux/drivers/media/video/sh_mobile_ceu_camera.c +++ b/linux/drivers/media/video/sh_mobile_ceu_camera.c @@ -97,6 +97,8 @@ struct sh_mobile_ceu_dev { struct sh_mobile_ceu_info *pdata; + u32 cflcr; + unsigned int is_interlaced:1; unsigned int image_mode:1; unsigned int is_16bit:1; @@ -104,6 +106,7 @@ struct sh_mobile_ceu_dev { struct sh_mobile_ceu_cam { struct v4l2_rect camera_rect; + struct v4l2_rect camera_max; const struct soc_camera_data_format *extra_fmt; const struct soc_camera_data_format *camera_fmt; }; @@ -437,54 +440,119 @@ static void sh_mobile_ceu_remove_device(struct soc_camera_device *icd) pcdev->icd = NULL; } +/* + * See chapter 29.4.12 "Capture Filter Control Register (CFLCR)" + * in SH7722 Hardware Manual + */ +static unsigned int size_dst(unsigned int src, unsigned int scale) +{ + unsigned int mant_pre = scale >> 12; + if (!src || !scale) + return src; + return ((mant_pre + 2 * (src - 1)) / (2 * mant_pre) - 1) * + mant_pre * 4096 / scale + 1; +} + +static unsigned int size_src(unsigned int dst, unsigned int scale) +{ + unsigned int mant_pre = scale >> 12, tmp; + if (!dst || !scale) + return dst; + for (tmp = ((dst - 1) * scale + 2048 * mant_pre) / 4096 + 1; + size_dst(tmp, scale) < dst; + tmp++) + ; + return tmp; +} + +static u16 calc_scale(unsigned int src, unsigned int *dst) +{ + u16 scale; + + if (src == *dst) + return 0; + + scale = (src * 4096 / *dst) & ~7; + + while (scale > 4096 && size_dst(src, scale) < *dst) + scale -= 8; + + *dst = size_dst(src, scale); + + return scale; +} + +/* rect is guaranteed to not exceed the scaled camera rectangle */ static void sh_mobile_ceu_set_rect(struct soc_camera_device *icd, struct v4l2_rect *rect) { struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); struct sh_mobile_ceu_cam *cam = icd->host_priv; struct sh_mobile_ceu_dev *pcdev = ici->priv; - int width, height, cfszr_width, cdwdr_width; - unsigned int left_offset, top_offset; + int width, height, cfszr_width, cdwdr_width, in_width, in_height; + unsigned int left_offset, top_offset, left, top; + unsigned int hscale = pcdev->cflcr & 0xffff; + unsigned int vscale = (pcdev->cflcr >> 16) & 0xffff; u32 camor; - if (rect->left > cam->camera_rect.left) { - left_offset = rect->left - cam->camera_rect.left; + /* Switch to the camera scale */ + left = size_src(rect->left, hscale); + top = size_src(rect->top, vscale); + + dev_dbg(&icd->dev, "Left %u * 0x%x = %u, top %u * 0x%x = %u\n", + rect->left, hscale, left, rect->top, vscale, top); + + if (left > cam->camera_rect.left) { + left_offset = left - cam->camera_rect.left; } else { left_offset = 0; - rect->left = cam->camera_rect.left; + left = cam->camera_rect.left; } - if (rect->top > cam->camera_rect.top) { - top_offset = rect->top - cam->camera_rect.top; + if (top > cam->camera_rect.top) { + top_offset = top - cam->camera_rect.top; } else { top_offset = 0; - rect->top = cam->camera_rect.top; + top = cam->camera_rect.top; } - dev_dbg(&icd->dev, "Offsets %u:%u\n", left_offset, top_offset); + dev_dbg(&icd->dev, "New left %u, top %u, offsets %u:%u\n", + rect->left, rect->top, left_offset, top_offset); if (pcdev->image_mode) { width = rect->width; - if (!pcdev->is_16bit) + in_width = cam->camera_rect.width; + if (!pcdev->is_16bit) { width *= 2; + in_width *= 2; + left_offset *= 2; + } cfszr_width = cdwdr_width = rect->width; } else { - width = rect->width * - ((icd->current_fmt->depth + 7) >> 3); - width = pcdev->is_16bit ? width / 2 : width; + unsigned int w_factor = (icd->current_fmt->depth + 7) >> 3; + if (!pcdev->is_16bit) + w_factor *= 2; + + width = rect->width * w_factor / 2; + in_width = cam->camera_rect.width * w_factor / 2; + left_offset = left_offset * w_factor / 2; + cfszr_width = pcdev->is_16bit ? width : width / 2; cdwdr_width = pcdev->is_16bit ? width * 2 : width; } height = rect->height; + in_height = cam->camera_rect.height; if (pcdev->is_interlaced) { height /= 2; + in_height /= 2; + top_offset /= 2; cdwdr_width *= 2; } camor = left_offset | (top_offset << 16); ceu_write(pcdev, CAMOR, camor); - ceu_write(pcdev, CAPWR, (height << 16) | width); + ceu_write(pcdev, CAPWR, (in_height << 16) | in_width); ceu_write(pcdev, CFSZR, (height << 16) | cfszr_width); ceu_write(pcdev, CDWDR, cdwdr_width); } @@ -558,7 +626,7 @@ static int sh_mobile_ceu_set_bus_param(struct soc_camera_device *icd, ceu_write(pcdev, CRCMPR, 0); value = 0x00000010; /* data fetch by default */ - pcdev->image_mode = yuv_lineskip = 0; + yuv_lineskip = 0; switch (icd->current_fmt->fourcc) { case V4L2_PIX_FMT_NV12: @@ -567,7 +635,6 @@ static int sh_mobile_ceu_set_bus_param(struct soc_camera_device *icd, /* fall-through */ case V4L2_PIX_FMT_NV16: case V4L2_PIX_FMT_NV61: - pcdev->image_mode = 1; switch (cam->camera_fmt->fourcc) { case V4L2_PIX_FMT_UYVY: value = 0x00000000; /* Cb0, Y0, Cr0, Y1 */ @@ -601,7 +668,7 @@ static int sh_mobile_ceu_set_bus_param(struct soc_camera_device *icd, mdelay(1); sh_mobile_ceu_set_rect(icd, &icd->rect_current); - ceu_write(pcdev, CFLCR, 0); /* no scaling */ + ceu_write(pcdev, CFLCR, pcdev->cflcr); /* A few words about byte order (observed in Big Endian mode) * @@ -622,7 +689,7 @@ static int sh_mobile_ceu_set_bus_param(struct soc_camera_device *icd, ceu_write(pcdev, CDOCR, value); ceu_write(pcdev, CFWCR, 0); /* keep "datafetch firewall" disabled */ - dev_dbg(&icd->dev, "S_FMT successful for %c%c%c%c %ux%u@%u.%u\n", + dev_dbg(&icd->dev, "S_FMT successful for %c%c%c%c %ux%u@%u:%u\n", pixfmt & 0xff, (pixfmt >> 8) & 0xff, (pixfmt >> 16) & 0xff, (pixfmt >> 24) & 0xff, icd->rect_current.width, icd->rect_current.height, @@ -694,6 +761,7 @@ static int sh_mobile_ceu_get_formats(struct soc_camera_device *icd, int idx, return -ENOMEM; icd->host_priv = cam; + cam->camera_max = icd->rect_max; } else { cam = icd->host_priv; } @@ -756,86 +824,150 @@ static void sh_mobile_ceu_put_formats(struct soc_camera_device *icd) icd->host_priv = NULL; } +/* Check if any dimension of r1 is smaller than respective one of r2 */ static bool is_smaller(struct v4l2_rect *r1, struct v4l2_rect *r2) { return r1->width < r2->width || r1->height < r2->height; } +/* Check if r1 fails to cover r2 */ +static bool is_inside(struct v4l2_rect *r1, struct v4l2_rect *r2) +{ + return r1->left > r2->left || r1->top > r2->top || + r1->left + r1->width < r2->left + r2->width || + r1->top + r1->height < r2->top + r2->height; +} + +/* + * CEU can scale and crop, but we don't want to waste bandwidth and kill the + * framerate by always requesting the maximum image from the client. For + * cropping we also have to take care of the current scale. The common for both + * scaling and cropping approach is: + * 1. try if the client can produce exactly what requested by the user + * 2. if (1) failed, try to double the client image until we get one big enough + * 3. if (2) failed, try to request the maximum image + */ static int sh_mobile_ceu_set_crop(struct soc_camera_device *icd, struct v4l2_rect *rect) { struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); struct sh_mobile_ceu_dev *pcdev = ici->priv; - struct v4l2_rect cam_rect = *rect; + struct v4l2_rect cam_rect, target, cam_max; struct sh_mobile_ceu_cam *cam = icd->host_priv; + unsigned int hscale = pcdev->cflcr & 0xffff; + unsigned int vscale = (pcdev->cflcr >> 16) & 0xffff; unsigned short width, height; u32 capsr; int ret; + /* Scale back up into client units */ + cam_rect.left = size_src(rect->left, hscale); + cam_rect.width = size_src(rect->width, hscale); + cam_rect.top = size_src(rect->top, vscale); + cam_rect.height = size_src(rect->height, vscale); + + target = cam_rect; + capsr = capture_save_reset(pcdev); - dev_dbg(&icd->dev, "CAPSR %x\n", capsr); + dev_dbg(&icd->dev, "CAPSR 0x%x, CFLCR 0x%x\n", capsr, pcdev->cflcr); + /* First attempt - see if the client can deliver a perfect result */ ret = icd->ops->set_crop(icd, &cam_rect); - if (!ret && !memcmp(rect, &cam_rect, sizeof(*rect))) { - dev_dbg(&icd->dev, "Camera S_CROP successful for %ux%u@%u.%u\n", + if (!ret && !memcmp(&target, &cam_rect, sizeof(target))) { + dev_dbg(&icd->dev, "Camera S_CROP successful for %ux%u@%u:%u\n", cam_rect.width, cam_rect.height, cam_rect.left, cam_rect.top); goto ceu_set_rect; } /* Try to fix cropping, that camera hasn't managed to do */ - dev_dbg(&icd->dev, "Fix camera S_CROP %d for %ux%u@%u.%u\n", + dev_dbg(&icd->dev, "Fix camera S_CROP %d for %ux%u@%u:%u" + " to %ux%u@%u:%u\n", ret, cam_rect.width, cam_rect.height, - cam_rect.left, cam_rect.top); + cam_rect.left, cam_rect.top, + target.width, target.height, target.left, target.top); /* * Popular special case - some cameras can only handle fixed sizes like * QVGA, VGA,... Take care to avoid infinite loop. */ - width = max(cam_rect.width, 1) * 2; - height = max(cam_rect.height, 1) * 2; - while (!ret && is_smaller(&cam_rect, rect) && - (icd->rect_max.width >= width && - icd->rect_max.height >= height)) { + width = max(cam_rect.width, 1); + height = max(cam_rect.height, 1); + cam_max.width = size_src(icd->rect_max.width, hscale); + cam_max.left = size_src(icd->rect_max.left, hscale); + cam_max.height = size_src(icd->rect_max.height, vscale); + cam_max.top = size_src(icd->rect_max.top, vscale); + while (!ret && (is_smaller(&cam_rect, &target) || + is_inside(&cam_rect, &target)) && + cam_max.width >= width && cam_max.height >= height) { + + width *= 2; + height *= 2; cam_rect.width = width; cam_rect.height = height; + /* We do not know what the camera is capable of, play safe */ + if (cam_rect.left > target.left) + cam_rect.left = cam_max.left; + + if (cam_rect.left + cam_rect.width < target.left + target.width) + cam_rect.width = target.left + target.width - + cam_rect.left; + + if (cam_rect.top > target.top) + cam_rect.top = cam_max.top; + + if (cam_rect.top + cam_rect.height < target.top + target.height) + cam_rect.height = target.top + target.height - + cam_rect.top; + if (cam_rect.width + cam_rect.left > - icd->rect_max.width + icd->rect_max.left) - cam_rect.left = icd->rect_max.width + - icd->rect_max.left - cam_rect.width; + cam_max.width + cam_max.left) + cam_rect.left = max(cam_max.width + cam_max.left - + cam_rect.width, cam_max.left); if (cam_rect.height + cam_rect.top > - icd->rect_max.height + icd->rect_max.top) - cam_rect.top = icd->rect_max.height + - icd->rect_max.top - cam_rect.height; + cam_max.height + cam_max.top) + cam_rect.top = max(cam_max.height + cam_max.top - + cam_rect.height, cam_max.top); ret = icd->ops->set_crop(icd, &cam_rect); - dev_dbg(&icd->dev, "Camera S_CROP %d for %ux%u@%u.%u\n", + dev_dbg(&icd->dev, "Camera S_CROP %d for %ux%u@%u:%u\n", ret, cam_rect.width, cam_rect.height, cam_rect.left, cam_rect.top); - width *= 2; - height *= 2; } /* * If the camera failed to configure cropping, it should not modify the * rectangle */ - if ((ret < 0 && is_smaller(&icd->rect_current, rect)) || - is_smaller(&cam_rect, rect)) { + if ((ret < 0 && (is_smaller(&icd->rect_current, rect) || + is_inside(&icd->rect_current, rect))) || + is_smaller(&cam_rect, &target) || is_inside(&cam_rect, &target)) { /* * The camera failed to configure a suitable cropping, * we cannot use the current rectangle, set to max */ - cam_rect = icd->rect_max; + cam_rect = cam_max; ret = icd->ops->set_crop(icd, &cam_rect); - dev_dbg(&icd->dev, "Camera S_CROP %d for max %ux%u@%u.%u\n", + dev_dbg(&icd->dev, "Camera S_CROP %d for max %ux%u@%u:%u\n", ret, cam_rect.width, cam_rect.height, cam_rect.left, cam_rect.top); if (ret < 0) /* All failed, hopefully resume current capture */ goto resume_capture; + + /* Finally, adjust the target rectangle */ + if (target.width > cam_rect.width) + target.width = cam_rect.width; + if (target.height > cam_rect.height) + target.height = cam_rect.height; + if (target.left + target.width > cam_rect.left + cam_rect.width) + target.left = cam_rect.left + cam_rect.width - + target.width; + if (target.top + target.height > cam_rect.top + cam_rect.height) + target.top = cam_rect.top + cam_rect.height - + target.height; } /* We now have a rectangle, larger than requested, let's crop */ @@ -846,8 +978,10 @@ static int sh_mobile_ceu_set_crop(struct soc_camera_device *icd, * last before last close() _user_ rectangle, which can be different * from camera rectangle. */ - dev_dbg(&icd->dev, "SH S_CROP from %ux%u@%u.%u to %ux%u@%u.%u\n", + dev_dbg(&icd->dev, + "SH S_CROP from %ux%u@%u:%u to %ux%u@%u:%u, scale to %ux%u@%u:%u\n", cam_rect.width, cam_rect.height, cam_rect.left, cam_rect.top, + target.width, target.height, target.left, target.top, rect->width, rect->height, rect->left, rect->top); ret = 0; @@ -855,27 +989,49 @@ static int sh_mobile_ceu_set_crop(struct soc_camera_device *icd, ceu_set_rect: cam->camera_rect = cam_rect; + rect->width = size_dst(target.width, hscale); + rect->left = size_dst(target.left, hscale); + rect->height = size_dst(target.height, vscale); + rect->top = size_dst(target.top, vscale); + + sh_mobile_ceu_set_rect(icd, rect); + +resume_capture: /* Set CAMOR, CAPWR, CFSZR, take care of CDWDR */ if (pcdev->active) capsr |= 1; - sh_mobile_ceu_set_rect(icd, rect); capture_restore(pcdev, capsr); -resume_capture: - /* Even if only camera cropping succeeded */ return ret; } +/* Similar to set_crop multistage iterative algorithm */ static int sh_mobile_ceu_set_fmt(struct soc_camera_device *icd, struct v4l2_format *f) { struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); + struct sh_mobile_ceu_dev *pcdev = ici->priv; struct sh_mobile_ceu_cam *cam = icd->host_priv; struct v4l2_pix_format *pix = &f->fmt.pix; __u32 pixfmt = pix->pixelformat; const struct soc_camera_format_xlate *xlate; - int ret; + unsigned int width = pix->width, height = pix->height, tmp_w, tmp_h; + u16 vscale, hscale; + int ret, is_interlaced; + + switch (pix->field) { + case V4L2_FIELD_INTERLACED: + is_interlaced = 1; + break; + case V4L2_FIELD_ANY: + default: + pix->field = V4L2_FIELD_NONE; + /* fall-through */ + case V4L2_FIELD_NONE: + is_interlaced = 0; + break; + } xlate = soc_camera_xlate_by_fourcc(icd, pixfmt); if (!xlate) { @@ -886,27 +1042,104 @@ static int sh_mobile_ceu_set_fmt(struct soc_camera_device *icd, pix->pixelformat = xlate->cam_fmt->fourcc; ret = v4l2_device_call_until_err(&ici->v4l2_dev, (__u32)icd, video, s_fmt, f); pix->pixelformat = pixfmt; - if (!ret) { - icd->buswidth = xlate->buswidth; - icd->current_fmt = xlate->host_fmt; - cam->camera_fmt = xlate->cam_fmt; - cam->camera_rect.width = pix->width; - cam->camera_rect.height = pix->height; - cam->camera_rect.left = icd->rect_current.left; - cam->camera_rect.top = icd->rect_current.top; + dev_dbg(&icd->dev, "Camera %d fmt %ux%u, requested %ux%u, max %ux%u\n", + ret, pix->width, pix->height, width, height, + icd->rect_max.width, icd->rect_max.height); + if (ret < 0) + return ret; + + switch (pixfmt) { + case V4L2_PIX_FMT_NV12: + case V4L2_PIX_FMT_NV21: + case V4L2_PIX_FMT_NV16: + case V4L2_PIX_FMT_NV61: + pcdev->image_mode = 1; + break; + default: + pcdev->image_mode = 0; } - return ret; + if ((abs(width - pix->width) < 4 && abs(height - pix->height) < 4) || + !pcdev->image_mode || is_interlaced) { + hscale = 0; + vscale = 0; + goto out; + } + + /* Camera set a format, but geometry is not precise, try to improve */ + /* + * FIXME: when soc-camera is converted to implement traditional S_FMT + * and S_CROP semantics, replace CEU limits with camera maxima + */ + tmp_w = pix->width; + tmp_h = pix->height; + while ((width > tmp_w || height > tmp_h) && + tmp_w < 2560 && tmp_h < 1920) { + tmp_w = min(2 * tmp_w, (__u32)2560); + tmp_h = min(2 * tmp_h, (__u32)1920); + pix->width = tmp_w; + pix->height = tmp_h; + pix->pixelformat = xlate->cam_fmt->fourcc; + ret = v4l2_device_call_until_err(&ici->v4l2_dev, (__u32)icd, + video, s_fmt, f); + pix->pixelformat = pixfmt; + dev_dbg(&icd->dev, "Camera scaled to %ux%u\n", + pix->width, pix->height); + if (ret < 0) { + /* This shouldn't happen */ + dev_err(&icd->dev, "Client failed to set format: %d\n", + ret); + return ret; + } + } + + /* We cannot scale up */ + if (width > pix->width) + width = pix->width; + + if (height > pix->height) + height = pix->height; + + /* Let's rock: scale pix->{width x height} down to width x height */ + hscale = calc_scale(pix->width, &width); + vscale = calc_scale(pix->height, &height); + + dev_dbg(&icd->dev, "W: %u : 0x%x = %u, H: %u : 0x%x = %u\n", + pix->width, hscale, width, pix->height, vscale, height); + +out: + pcdev->cflcr = hscale | (vscale << 16); + + icd->buswidth = xlate->buswidth; + icd->current_fmt = xlate->host_fmt; + cam->camera_fmt = xlate->cam_fmt; + cam->camera_rect.width = pix->width; + cam->camera_rect.height = pix->height; + + icd->rect_max.left = size_dst(cam->camera_max.left, hscale); + icd->rect_max.width = size_dst(cam->camera_max.width, hscale); + icd->rect_max.top = size_dst(cam->camera_max.top, vscale); + icd->rect_max.height = size_dst(cam->camera_max.height, vscale); + + icd->rect_current.left = icd->rect_max.left; + icd->rect_current.top = icd->rect_max.top; + + pcdev->is_interlaced = is_interlaced; + + pix->width = width; + pix->height = height; + + return 0; } static int sh_mobile_ceu_try_fmt(struct soc_camera_device *icd, struct v4l2_format *f) { struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); - struct sh_mobile_ceu_dev *pcdev = ici->priv; const struct soc_camera_format_xlate *xlate; struct v4l2_pix_format *pix = &f->fmt.pix; __u32 pixfmt = pix->pixelformat; + int width, height; int ret; xlate = soc_camera_xlate_by_fourcc(icd, pixfmt); @@ -920,6 +1153,9 @@ static int sh_mobile_ceu_try_fmt(struct soc_camera_device *icd, v4l_bound_align_image(&pix->width, 2, 2560, 1, &pix->height, 4, 1920, 2, 0); + width = pix->width; + height = pix->height; + pix->bytesperline = pix->width * DIV_ROUND_UP(xlate->host_fmt->depth, 8); pix->sizeimage = pix->height * pix->bytesperline; @@ -927,24 +1163,38 @@ static int sh_mobile_ceu_try_fmt(struct soc_camera_device *icd, pix->pixelformat = xlate->cam_fmt->fourcc; /* limit to sensor capabilities */ - ret = v4l2_device_call_until_err(&ici->v4l2_dev, (__u32)icd, video, try_fmt, f); + ret = v4l2_device_call_until_err(&ici->v4l2_dev, (__u32)icd, video, + try_fmt, f); pix->pixelformat = pixfmt; if (ret < 0) return ret; - switch (pix->field) { - case V4L2_FIELD_INTERLACED: - pcdev->is_interlaced = 1; - break; - case V4L2_FIELD_ANY: - pix->field = V4L2_FIELD_NONE; - /* fall-through */ - case V4L2_FIELD_NONE: - pcdev->is_interlaced = 0; - break; - default: - ret = -EINVAL; - break; + switch (pixfmt) { + case V4L2_PIX_FMT_NV12: + case V4L2_PIX_FMT_NV21: + case V4L2_PIX_FMT_NV16: + case V4L2_PIX_FMT_NV61: + /* FIXME: check against rect_max after converting soc-camera */ + /* We can scale precisely, need a bigger image from camera */ + if (pix->width < width || pix->height < height) { + int tmp_w = pix->width, tmp_h = pix->height; + pix->width = 2560; + pix->height = 1920; + ret = v4l2_device_call_until_err(&ici->v4l2_dev, + (__u32)icd, video, + try_fmt, f); + if (ret < 0) { + /* Shouldn't actually happen... */ + dev_err(&icd->dev, + "FIXME: try_fmt() returned %d\n", ret); + pix->width = tmp_w; + pix->height = tmp_h; + } + } + if (pix->width > width) + pix->width = width; + if (pix->height > height) + pix->height = height; } return ret; -- cgit v1.2.3 From a94ff67f3f3091badb6034566504ad58206989ef Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Tue, 25 Aug 2009 16:46:54 +0200 Subject: soc-camera: switch to s_crop v4l2-subdev video operation From: Guennadi Liakhovetski Remove set_crop soc-camera device method and switch to s_crop from v4l2-subdev video operations. Also extend non-i2c drivers to also hold a pointer to their v4l2-subdev instance in control device driver-data, i.e., in dev_get_drvdata((struct device *)to_soc_camera_control(icd)) Signed-off-by: Guennadi Liakhovetski Priority: low --- drivers/media/video/mt9m001.c | 23 +++--- drivers/media/video/mt9m111.c | 9 +- drivers/media/video/mt9t031.c | 9 +- drivers/media/video/mt9v022.c | 23 +++--- drivers/media/video/mx1_camera.c | 8 ++- drivers/media/video/mx3_camera.c | 7 +- drivers/media/video/ov772x.c | 19 ----- drivers/media/video/pxa_camera.c | 7 +- drivers/media/video/sh_mobile_ceu_camera.c | 110 ++++++++++++++------------- drivers/media/video/soc_camera.c | 4 +- drivers/media/video/soc_camera_platform.c | 28 ++++---- drivers/media/video/tw9910.c | 31 ++++---- include/media/soc_camera.h | 3 +- 13 files changed, 142 insertions(+), 139 deletions(-) --- linux/drivers/media/video/mt9m001.c | 23 ++--- linux/drivers/media/video/mt9m111.c | 9 +- linux/drivers/media/video/mt9t031.c | 9 +- linux/drivers/media/video/mt9v022.c | 23 ++--- linux/drivers/media/video/mx1_camera.c | 8 +- linux/drivers/media/video/mx3_camera.c | 7 +- linux/drivers/media/video/ov772x.c | 19 ---- linux/drivers/media/video/pxa_camera.c | 7 +- linux/drivers/media/video/sh_mobile_ceu_camera.c | 110 ++++++++++++----------- linux/drivers/media/video/soc_camera.c | 4 +- linux/drivers/media/video/soc_camera_platform.c | 28 +++--- linux/drivers/media/video/tw9910.c | 31 +++---- 12 files changed, 141 insertions(+), 137 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/mt9m001.c b/linux/drivers/media/video/mt9m001.c index 7a9435f9b..b74ef6cea 100644 --- a/linux/drivers/media/video/mt9m001.c +++ b/linux/drivers/media/video/mt9m001.c @@ -194,11 +194,12 @@ static unsigned long mt9m001_query_bus_param(struct soc_camera_device *icd) return soc_camera_apply_sensor_flags(icl, flags); } -static int mt9m001_set_crop(struct soc_camera_device *icd, - struct v4l2_rect *rect) +static int mt9m001_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) { - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct v4l2_rect *rect = &a->c; + struct i2c_client *client = sd->priv; struct mt9m001 *mt9m001 = to_mt9m001(client); + struct soc_camera_device *icd = client->dev.platform_data; int ret; const u16 hblank = 9, vblank = 25; @@ -239,15 +240,17 @@ static int mt9m001_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) { struct i2c_client *client = sd->priv; struct soc_camera_device *icd = client->dev.platform_data; - struct v4l2_rect rect = { - .left = icd->rect_current.left, - .top = icd->rect_current.top, - .width = f->fmt.pix.width, - .height = f->fmt.pix.height, + struct v4l2_crop a = { + .c = { + .left = icd->rect_current.left, + .top = icd->rect_current.top, + .width = f->fmt.pix.width, + .height = f->fmt.pix.height, + }, }; /* No support for scaling so far, just crop. TODO: use skipping */ - return mt9m001_set_crop(icd, &rect); + return mt9m001_s_crop(sd, &a); } static int mt9m001_try_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) @@ -361,7 +364,6 @@ static const struct v4l2_queryctrl mt9m001_controls[] = { static struct soc_camera_ops mt9m001_ops = { .init = mt9m001_init, .release = mt9m001_release, - .set_crop = mt9m001_set_crop, .set_bus_param = mt9m001_set_bus_param, .query_bus_param = mt9m001_query_bus_param, .controls = mt9m001_controls, @@ -575,6 +577,7 @@ static struct v4l2_subdev_video_ops mt9m001_subdev_video_ops = { .s_stream = mt9m001_s_stream, .s_fmt = mt9m001_s_fmt, .try_fmt = mt9m001_try_fmt, + .s_crop = mt9m001_s_crop, }; static struct v4l2_subdev_ops mt9m001_subdev_ops = { diff --git a/linux/drivers/media/video/mt9m111.c b/linux/drivers/media/video/mt9m111.c index 8770dfd2a..cab9de000 100644 --- a/linux/drivers/media/video/mt9m111.c +++ b/linux/drivers/media/video/mt9m111.c @@ -395,11 +395,12 @@ static int mt9m111_set_bus_param(struct soc_camera_device *icd, unsigned long f) return 0; } -static int mt9m111_set_crop(struct soc_camera_device *icd, - struct v4l2_rect *rect) +static int mt9m111_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) { - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct v4l2_rect *rect = &a->c; + struct i2c_client *client = sd->priv; struct mt9m111 *mt9m111 = to_mt9m111(client); + struct soc_camera_device *icd = client->dev.platform_data; int ret; dev_dbg(&icd->dev, "%s left=%d, top=%d, width=%d, height=%d\n", @@ -601,7 +602,6 @@ static struct soc_camera_ops mt9m111_ops = { .init = mt9m111_init, .resume = mt9m111_resume, .release = mt9m111_release, - .set_crop = mt9m111_set_crop, .query_bus_param = mt9m111_query_bus_param, .set_bus_param = mt9m111_set_bus_param, .controls = mt9m111_controls, @@ -908,6 +908,7 @@ static struct v4l2_subdev_core_ops mt9m111_subdev_core_ops = { static struct v4l2_subdev_video_ops mt9m111_subdev_video_ops = { .s_fmt = mt9m111_s_fmt, .try_fmt = mt9m111_try_fmt, + .s_crop = mt9m111_s_crop, }; static struct v4l2_subdev_ops mt9m111_subdev_ops = { diff --git a/linux/drivers/media/video/mt9t031.c b/linux/drivers/media/video/mt9t031.c index b69a34c87..6bcea4165 100644 --- a/linux/drivers/media/video/mt9t031.c +++ b/linux/drivers/media/video/mt9t031.c @@ -321,11 +321,12 @@ static int mt9t031_set_params(struct soc_camera_device *icd, return ret < 0 ? ret : 0; } -static int mt9t031_set_crop(struct soc_camera_device *icd, - struct v4l2_rect *rect) +static int mt9t031_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) { - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct v4l2_rect *rect = &a->c; + struct i2c_client *client = sd->priv; struct mt9t031 *mt9t031 = to_mt9t031(client); + struct soc_camera_device *icd = client->dev.platform_data; /* Make sure we don't exceed sensor limits */ if (rect->left + rect->width > icd->rect_max.left + icd->rect_max.width) @@ -495,7 +496,6 @@ static const struct v4l2_queryctrl mt9t031_controls[] = { static struct soc_camera_ops mt9t031_ops = { .init = mt9t031_init, .release = mt9t031_release, - .set_crop = mt9t031_set_crop, .set_bus_param = mt9t031_set_bus_param, .query_bus_param = mt9t031_query_bus_param, .controls = mt9t031_controls, @@ -689,6 +689,7 @@ static struct v4l2_subdev_video_ops mt9t031_subdev_video_ops = { .s_stream = mt9t031_s_stream, .s_fmt = mt9t031_s_fmt, .try_fmt = mt9t031_try_fmt, + .s_crop = mt9t031_s_crop, }; static struct v4l2_subdev_ops mt9t031_subdev_ops = { diff --git a/linux/drivers/media/video/mt9v022.c b/linux/drivers/media/video/mt9v022.c index de74f7bda..088ffa464 100644 --- a/linux/drivers/media/video/mt9v022.c +++ b/linux/drivers/media/video/mt9v022.c @@ -248,10 +248,11 @@ static unsigned long mt9v022_query_bus_param(struct soc_camera_device *icd) width_flag; } -static int mt9v022_set_crop(struct soc_camera_device *icd, - struct v4l2_rect *rect) +static int mt9v022_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) { - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct v4l2_rect *rect = &a->c; + struct i2c_client *client = sd->priv; + struct soc_camera_device *icd = client->dev.platform_data; int ret; /* Like in example app. Contradicts the datasheet though */ @@ -297,11 +298,13 @@ static int mt9v022_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) struct mt9v022 *mt9v022 = to_mt9v022(client); struct soc_camera_device *icd = client->dev.platform_data; struct v4l2_pix_format *pix = &f->fmt.pix; - struct v4l2_rect rect = { - .left = icd->rect_current.left, - .top = icd->rect_current.top, - .width = pix->width, - .height = pix->height, + struct v4l2_crop a = { + .c = { + .left = icd->rect_current.left, + .top = icd->rect_current.top, + .width = pix->width, + .height = pix->height, + }, }; /* The caller provides a supported format, as verified per call to @@ -325,7 +328,7 @@ static int mt9v022_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) } /* No support for scaling on this camera, just crop. */ - return mt9v022_set_crop(icd, &rect); + return mt9v022_s_crop(sd, &a); } static int mt9v022_try_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) @@ -454,7 +457,6 @@ static const struct v4l2_queryctrl mt9v022_controls[] = { static struct soc_camera_ops mt9v022_ops = { .init = mt9v022_init, - .set_crop = mt9v022_set_crop, .set_bus_param = mt9v022_set_bus_param, .query_bus_param = mt9v022_query_bus_param, .controls = mt9v022_controls, @@ -700,6 +702,7 @@ static struct v4l2_subdev_video_ops mt9v022_subdev_video_ops = { .s_stream = mt9v022_s_stream, .s_fmt = mt9v022_s_fmt, .try_fmt = mt9v022_try_fmt, + .s_crop = mt9v022_s_crop, }; static struct v4l2_subdev_ops mt9v022_subdev_ops = { diff --git a/linux/drivers/media/video/mx1_camera.c b/linux/drivers/media/video/mx1_camera.c index 948a4714b..add496fca 100644 --- a/linux/drivers/media/video/mx1_camera.c +++ b/linux/drivers/media/video/mx1_camera.c @@ -463,9 +463,13 @@ static void mx1_camera_remove_device(struct soc_camera_device *icd) } static int mx1_camera_set_crop(struct soc_camera_device *icd, - struct v4l2_rect *rect) + struct v4l2_crop *a) { - return icd->ops->set_crop(icd, rect); + struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); + struct device *control = to_soc_camera_control(icd); + struct v4l2_subdev *sd = dev_get_drvdata(control); + + return v4l2_subdev_call(sd, video, s_crop, a); } static int mx1_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt) diff --git a/linux/drivers/media/video/mx3_camera.c b/linux/drivers/media/video/mx3_camera.c index 6c3b7f9b9..de7ebfbf0 100644 --- a/linux/drivers/media/video/mx3_camera.c +++ b/linux/drivers/media/video/mx3_camera.c @@ -781,10 +781,13 @@ static int acquire_dma_channel(struct mx3_camera_dev *mx3_cam) } static int mx3_camera_set_crop(struct soc_camera_device *icd, - struct v4l2_rect *rect) + struct v4l2_crop *a) { + struct v4l2_rect *rect = &a->c; struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); struct mx3_camera_dev *mx3_cam = ici->priv; + struct device *control = to_soc_camera_control(icd); + struct v4l2_subdev *sd = dev_get_drvdata(control); /* * We now know pixel formats and can decide upon DMA-channel(s) @@ -798,7 +801,7 @@ static int mx3_camera_set_crop(struct soc_camera_device *icd, configure_geometry(mx3_cam, rect); - return icd->ops->set_crop(icd, rect); + return v4l2_subdev_call(sd, video, s_crop, a); } static int mx3_camera_set_fmt(struct soc_camera_device *icd, diff --git a/linux/drivers/media/video/ov772x.c b/linux/drivers/media/video/ov772x.c index e8bb337da..c5b63f420 100644 --- a/linux/drivers/media/video/ov772x.c +++ b/linux/drivers/media/video/ov772x.c @@ -955,24 +955,6 @@ ov772x_set_fmt_error: return ret; } -/* Cannot crop, just return the current geometry */ -static int ov772x_set_crop(struct soc_camera_device *icd, - struct v4l2_rect *rect) -{ - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); - struct ov772x_priv *priv = to_ov772x(client); - - if (!priv->fmt || !priv->win) - return -EINVAL; - - rect->left = 0; - rect->top = 0; - rect->width = priv->win->width; - rect->height = priv->win->height; - - return 0; -} - static int ov772x_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) { struct i2c_client *client = sd->priv; @@ -1060,7 +1042,6 @@ static int ov772x_video_probe(struct soc_camera_device *icd, } static struct soc_camera_ops ov772x_ops = { - .set_crop = ov772x_set_crop, .set_bus_param = ov772x_set_bus_param, .query_bus_param = ov772x_query_bus_param, .controls = ov772x_controls, diff --git a/linux/drivers/media/video/pxa_camera.c b/linux/drivers/media/video/pxa_camera.c index 6f2aef033..d447e5b59 100644 --- a/linux/drivers/media/video/pxa_camera.c +++ b/linux/drivers/media/video/pxa_camera.c @@ -1293,10 +1293,13 @@ static int pxa_camera_get_formats(struct soc_camera_device *icd, int idx, } static int pxa_camera_set_crop(struct soc_camera_device *icd, - struct v4l2_rect *rect) + struct v4l2_crop *a) { + struct v4l2_rect *rect = &a->c; struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); struct pxa_camera_dev *pcdev = ici->priv; + struct device *control = to_soc_camera_control(icd); + struct v4l2_subdev *sd = dev_get_drvdata(control); struct soc_camera_sense sense = { .master_clock = pcdev->mclk, .pixel_clock_max = pcdev->ciclk / 4, @@ -1307,7 +1310,7 @@ static int pxa_camera_set_crop(struct soc_camera_device *icd, if (pcdev->platform_flags & PXA_CAMERA_PCLK_EN) icd->sense = &sense; - ret = icd->ops->set_crop(icd, rect); + ret = v4l2_subdev_call(sd, video, s_crop, a); icd->sense = NULL; diff --git a/linux/drivers/media/video/sh_mobile_ceu_camera.c b/linux/drivers/media/video/sh_mobile_ceu_camera.c index a1108cc03..c60088447 100644 --- a/linux/drivers/media/video/sh_mobile_ceu_camera.c +++ b/linux/drivers/media/video/sh_mobile_ceu_camera.c @@ -848,12 +848,16 @@ static bool is_inside(struct v4l2_rect *r1, struct v4l2_rect *r2) * 3. if (2) failed, try to request the maximum image */ static int sh_mobile_ceu_set_crop(struct soc_camera_device *icd, - struct v4l2_rect *rect) + struct v4l2_crop *a) { + struct v4l2_rect *rect = &a->c; struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); struct sh_mobile_ceu_dev *pcdev = ici->priv; - struct v4l2_rect cam_rect, target, cam_max; + struct v4l2_crop cam_crop; + struct v4l2_rect *cam_rect = &cam_crop.c, target, cam_max; struct sh_mobile_ceu_cam *cam = icd->host_priv; + struct device *control = to_soc_camera_control(icd); + struct v4l2_subdev *sd = dev_get_drvdata(control); unsigned int hscale = pcdev->cflcr & 0xffff; unsigned int vscale = (pcdev->cflcr >> 16) & 0xffff; unsigned short width, height; @@ -861,80 +865,80 @@ static int sh_mobile_ceu_set_crop(struct soc_camera_device *icd, int ret; /* Scale back up into client units */ - cam_rect.left = size_src(rect->left, hscale); - cam_rect.width = size_src(rect->width, hscale); - cam_rect.top = size_src(rect->top, vscale); - cam_rect.height = size_src(rect->height, vscale); + cam_rect->left = size_src(rect->left, hscale); + cam_rect->width = size_src(rect->width, hscale); + cam_rect->top = size_src(rect->top, vscale); + cam_rect->height = size_src(rect->height, vscale); - target = cam_rect; + target = *cam_rect; capsr = capture_save_reset(pcdev); dev_dbg(&icd->dev, "CAPSR 0x%x, CFLCR 0x%x\n", capsr, pcdev->cflcr); /* First attempt - see if the client can deliver a perfect result */ - ret = icd->ops->set_crop(icd, &cam_rect); + ret = v4l2_subdev_call(sd, video, s_crop, &cam_crop); if (!ret && !memcmp(&target, &cam_rect, sizeof(target))) { dev_dbg(&icd->dev, "Camera S_CROP successful for %ux%u@%u:%u\n", - cam_rect.width, cam_rect.height, - cam_rect.left, cam_rect.top); + cam_rect->width, cam_rect->height, + cam_rect->left, cam_rect->top); goto ceu_set_rect; } /* Try to fix cropping, that camera hasn't managed to do */ dev_dbg(&icd->dev, "Fix camera S_CROP %d for %ux%u@%u:%u" " to %ux%u@%u:%u\n", - ret, cam_rect.width, cam_rect.height, - cam_rect.left, cam_rect.top, + ret, cam_rect->width, cam_rect->height, + cam_rect->left, cam_rect->top, target.width, target.height, target.left, target.top); /* * Popular special case - some cameras can only handle fixed sizes like * QVGA, VGA,... Take care to avoid infinite loop. */ - width = max(cam_rect.width, 1); - height = max(cam_rect.height, 1); + width = max(cam_rect->width, 1); + height = max(cam_rect->height, 1); cam_max.width = size_src(icd->rect_max.width, hscale); cam_max.left = size_src(icd->rect_max.left, hscale); cam_max.height = size_src(icd->rect_max.height, vscale); cam_max.top = size_src(icd->rect_max.top, vscale); - while (!ret && (is_smaller(&cam_rect, &target) || - is_inside(&cam_rect, &target)) && + while (!ret && (is_smaller(cam_rect, &target) || + is_inside(cam_rect, &target)) && cam_max.width >= width && cam_max.height >= height) { width *= 2; height *= 2; - cam_rect.width = width; - cam_rect.height = height; + cam_rect->width = width; + cam_rect->height = height; /* We do not know what the camera is capable of, play safe */ - if (cam_rect.left > target.left) - cam_rect.left = cam_max.left; + if (cam_rect->left > target.left) + cam_rect->left = cam_max.left; - if (cam_rect.left + cam_rect.width < target.left + target.width) - cam_rect.width = target.left + target.width - - cam_rect.left; + if (cam_rect->left + cam_rect->width < target.left + target.width) + cam_rect->width = target.left + target.width - + cam_rect->left; - if (cam_rect.top > target.top) - cam_rect.top = cam_max.top; + if (cam_rect->top > target.top) + cam_rect->top = cam_max.top; - if (cam_rect.top + cam_rect.height < target.top + target.height) - cam_rect.height = target.top + target.height - - cam_rect.top; + if (cam_rect->top + cam_rect->height < target.top + target.height) + cam_rect->height = target.top + target.height - + cam_rect->top; - if (cam_rect.width + cam_rect.left > + if (cam_rect->width + cam_rect->left > cam_max.width + cam_max.left) - cam_rect.left = max(cam_max.width + cam_max.left - - cam_rect.width, cam_max.left); + cam_rect->left = max(cam_max.width + cam_max.left - + cam_rect->width, cam_max.left); - if (cam_rect.height + cam_rect.top > + if (cam_rect->height + cam_rect->top > cam_max.height + cam_max.top) - cam_rect.top = max(cam_max.height + cam_max.top - - cam_rect.height, cam_max.top); + cam_rect->top = max(cam_max.height + cam_max.top - + cam_rect->height, cam_max.top); - ret = icd->ops->set_crop(icd, &cam_rect); + ret = v4l2_subdev_call(sd, video, s_crop, &cam_crop); dev_dbg(&icd->dev, "Camera S_CROP %d for %ux%u@%u:%u\n", - ret, cam_rect.width, cam_rect.height, - cam_rect.left, cam_rect.top); + ret, cam_rect->width, cam_rect->height, + cam_rect->left, cam_rect->top); } /* @@ -943,30 +947,30 @@ static int sh_mobile_ceu_set_crop(struct soc_camera_device *icd, */ if ((ret < 0 && (is_smaller(&icd->rect_current, rect) || is_inside(&icd->rect_current, rect))) || - is_smaller(&cam_rect, &target) || is_inside(&cam_rect, &target)) { + is_smaller(cam_rect, &target) || is_inside(cam_rect, &target)) { /* * The camera failed to configure a suitable cropping, * we cannot use the current rectangle, set to max */ - cam_rect = cam_max; - ret = icd->ops->set_crop(icd, &cam_rect); + *cam_rect = cam_max; + ret = v4l2_subdev_call(sd, video, s_crop, &cam_crop); dev_dbg(&icd->dev, "Camera S_CROP %d for max %ux%u@%u:%u\n", - ret, cam_rect.width, cam_rect.height, - cam_rect.left, cam_rect.top); - if (ret < 0) + ret, cam_rect->width, cam_rect->height, + cam_rect->left, cam_rect->top); + if (ret < 0 && ret != -ENOIOCTLCMD) /* All failed, hopefully resume current capture */ goto resume_capture; /* Finally, adjust the target rectangle */ - if (target.width > cam_rect.width) - target.width = cam_rect.width; - if (target.height > cam_rect.height) - target.height = cam_rect.height; - if (target.left + target.width > cam_rect.left + cam_rect.width) - target.left = cam_rect.left + cam_rect.width - + if (target.width > cam_rect->width) + target.width = cam_rect->width; + if (target.height > cam_rect->height) + target.height = cam_rect->height; + if (target.left + target.width > cam_rect->left + cam_rect->width) + target.left = cam_rect->left + cam_rect->width - target.width; - if (target.top + target.height > cam_rect.top + cam_rect.height) - target.top = cam_rect.top + cam_rect.height - + if (target.top + target.height > cam_rect->top + cam_rect->height) + target.top = cam_rect->top + cam_rect->height - target.height; } @@ -980,14 +984,14 @@ static int sh_mobile_ceu_set_crop(struct soc_camera_device *icd, */ dev_dbg(&icd->dev, "SH S_CROP from %ux%u@%u:%u to %ux%u@%u:%u, scale to %ux%u@%u:%u\n", - cam_rect.width, cam_rect.height, cam_rect.left, cam_rect.top, + cam_rect->width, cam_rect->height, cam_rect->left, cam_rect->top, target.width, target.height, target.left, target.top, rect->width, rect->height, rect->left, rect->top); ret = 0; ceu_set_rect: - cam->camera_rect = cam_rect; + cam->camera_rect = *cam_rect; rect->width = size_dst(target.width, hscale); rect->left = size_dst(target.left, hscale); diff --git a/linux/drivers/media/video/soc_camera.c b/linux/drivers/media/video/soc_camera.c index ec564a90e..ab469554b 100644 --- a/linux/drivers/media/video/soc_camera.c +++ b/linux/drivers/media/video/soc_camera.c @@ -798,7 +798,7 @@ static int soc_camera_s_crop(struct file *file, void *fh, rect.top = icd->rect_max.height + icd->rect_max.top - rect.height; - ret = ici->ops->set_crop(icd, &rect); + ret = ici->ops->set_crop(icd, a); if (!ret) icd->rect_current = rect; @@ -971,7 +971,7 @@ static int soc_camera_probe(struct device *dev) /* FIXME: this is racy, have to use driver-binding notification */ control = to_soc_camera_control(icd); - if (!control || !control->driver || + if (!control || !control->driver || !dev_get_drvdata(control) || !try_module_get(control->driver->owner)) { icl->del_device(icl); goto enodrv; diff --git a/linux/drivers/media/video/soc_camera_platform.c b/linux/drivers/media/video/soc_camera_platform.c index 9e406c113..aec2cadbd 100644 --- a/linux/drivers/media/video/soc_camera_platform.c +++ b/linux/drivers/media/video/soc_camera_platform.c @@ -25,10 +25,15 @@ struct soc_camera_platform_priv { struct soc_camera_data_format format; }; -static struct soc_camera_platform_info * -soc_camera_platform_get_info(struct soc_camera_device *icd) +static struct soc_camera_platform_priv *get_priv(struct platform_device *pdev) { - struct platform_device *pdev = to_platform_device(dev_get_drvdata(&icd->dev)); + struct v4l2_subdev *subdev = platform_get_drvdata(pdev); + return container_of(subdev, struct soc_camera_platform_priv, subdev); +} + +static struct soc_camera_platform_info *get_info(struct soc_camera_device *icd) +{ + struct platform_device *pdev = to_platform_device(to_soc_camera_control(icd)); return pdev->dev.platform_data; } @@ -47,16 +52,10 @@ static int soc_camera_platform_set_bus_param(struct soc_camera_device *icd, static unsigned long soc_camera_platform_query_bus_param(struct soc_camera_device *icd) { - struct soc_camera_platform_info *p = soc_camera_platform_get_info(icd); + struct soc_camera_platform_info *p = get_info(icd); return p->bus_param; } -static int soc_camera_platform_set_crop(struct soc_camera_device *icd, - struct v4l2_rect *rect) -{ - return 0; -} - static int soc_camera_platform_try_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) { @@ -71,7 +70,7 @@ static int soc_camera_platform_try_fmt(struct v4l2_subdev *sd, static void soc_camera_platform_video_probe(struct soc_camera_device *icd, struct platform_device *pdev) { - struct soc_camera_platform_priv *priv = platform_get_drvdata(pdev); + struct soc_camera_platform_priv *priv = get_priv(pdev); struct soc_camera_platform_info *p = pdev->dev.platform_data; priv->format.name = p->format_name; @@ -96,7 +95,6 @@ static struct v4l2_subdev_ops platform_subdev_ops = { }; static struct soc_camera_ops soc_camera_platform_ops = { - .set_crop = soc_camera_platform_set_crop, .set_bus_param = soc_camera_platform_set_bus_param, .query_bus_param = soc_camera_platform_query_bus_param, }; @@ -124,7 +122,9 @@ static int soc_camera_platform_probe(struct platform_device *pdev) icd = to_soc_camera_dev(p->dev); - platform_set_drvdata(pdev, priv); + /* soc-camera convention: control's drvdata points to the subdev */ + platform_set_drvdata(pdev, &priv->subdev); + /* Set the control device reference */ dev_set_drvdata(&icd->dev, &pdev->dev); icd->width_min = 0; @@ -158,7 +158,7 @@ evdrs: static int soc_camera_platform_remove(struct platform_device *pdev) { - struct soc_camera_platform_priv *priv = platform_get_drvdata(pdev); + struct soc_camera_platform_priv *priv = get_priv(pdev); struct soc_camera_platform_info *p = pdev->dev.platform_data; struct soc_camera_device *icd = to_soc_camera_dev(p->dev); diff --git a/linux/drivers/media/video/tw9910.c b/linux/drivers/media/video/tw9910.c index 852c7859f..266cf594c 100644 --- a/linux/drivers/media/video/tw9910.c +++ b/linux/drivers/media/video/tw9910.c @@ -616,11 +616,12 @@ static int tw9910_s_register(struct v4l2_subdev *sd, } #endif -static int tw9910_set_crop(struct soc_camera_device *icd, - struct v4l2_rect *rect) +static int tw9910_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) { - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct v4l2_rect *rect = &a->c; + struct i2c_client *client = sd->priv; struct tw9910_priv *priv = to_tw9910(client); + struct soc_camera_device *icd = client->dev.platform_data; int ret = -EINVAL; u8 val; @@ -716,15 +717,15 @@ tw9910_set_fmt_error: static int tw9910_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) { - struct i2c_client *client = sd->priv; - struct soc_camera_device *icd = client->dev.platform_data; struct v4l2_pix_format *pix = &f->fmt.pix; - /* See tw9910_set_crop() - no proper cropping support */ - struct v4l2_rect rect = { - .left = 0, - .top = 0, - .width = pix->width, - .height = pix->height, + /* See tw9910_s_crop() - no proper cropping support */ + struct v4l2_crop a = { + .c = { + .left = 0, + .top = 0, + .width = pix->width, + .height = pix->height, + }, }; int i, ret; @@ -738,10 +739,10 @@ static int tw9910_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) if (i == ARRAY_SIZE(tw9910_color_fmt)) return -EINVAL; - ret = tw9910_set_crop(icd, &rect); + ret = tw9910_s_crop(sd, &a); if (!ret) { - pix->width = rect.width; - pix->height = rect.height; + pix->width = a.c.width; + pix->height = a.c.height; } return ret; } @@ -821,7 +822,6 @@ static int tw9910_video_probe(struct soc_camera_device *icd, } static struct soc_camera_ops tw9910_ops = { - .set_crop = tw9910_set_crop, .set_bus_param = tw9910_set_bus_param, .query_bus_param = tw9910_query_bus_param, .enum_input = tw9910_enum_input, @@ -840,6 +840,7 @@ static struct v4l2_subdev_video_ops tw9910_subdev_video_ops = { .s_stream = tw9910_s_stream, .s_fmt = tw9910_s_fmt, .try_fmt = tw9910_try_fmt, + .s_crop = tw9910_s_crop, }; static struct v4l2_subdev_ops tw9910_subdev_ops = { -- cgit v1.2.3 From 7cf68de59618e578e4c22038d200ae3f42ad4fbb Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Tue, 25 Aug 2009 16:46:59 +0200 Subject: soc-camera: switch to using v4l2_subdev_call() From: Guennadi Liakhovetski Use v4l2_subdev_call() instead of v4l2_device_call_until_err() in all host drivers and in soc-camera core. Signed-off-by: Guennadi Liakhovetski Priority: low --- drivers/media/video/mx1_camera.c | 12 ++++------ drivers/media/video/mx3_camera.c | 10 ++++---- drivers/media/video/pxa_camera.c | 9 ++++--- drivers/media/video/sh_mobile_ceu_camera.c | 17 ++++++--------- drivers/media/video/soc_camera.c | 30 ++++++++++++++------------- include/media/soc_camera.h | 14 +++++++++--- 6 files changed, 48 insertions(+), 44 deletions(-) --- linux/drivers/media/video/mx1_camera.c | 12 ++++------ linux/drivers/media/video/mx3_camera.c | 10 ++++---- linux/drivers/media/video/pxa_camera.c | 9 +++---- linux/drivers/media/video/sh_mobile_ceu_camera.c | 17 ++++++-------- linux/drivers/media/video/soc_camera.c | 30 +++++++++++++----------- 5 files changed, 38 insertions(+), 40 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/mx1_camera.c b/linux/drivers/media/video/mx1_camera.c index add496fca..ed7856bda 100644 --- a/linux/drivers/media/video/mx1_camera.c +++ b/linux/drivers/media/video/mx1_camera.c @@ -465,9 +465,7 @@ static void mx1_camera_remove_device(struct soc_camera_device *icd) static int mx1_camera_set_crop(struct soc_camera_device *icd, struct v4l2_crop *a) { - struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); - struct device *control = to_soc_camera_control(icd); - struct v4l2_subdev *sd = dev_get_drvdata(control); + struct v4l2_subdev *sd = soc_camera_to_subdev(icd); return v4l2_subdev_call(sd, video, s_crop, a); } @@ -539,7 +537,7 @@ static int mx1_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt) static int mx1_camera_set_fmt(struct soc_camera_device *icd, struct v4l2_format *f) { - struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); + struct v4l2_subdev *sd = soc_camera_to_subdev(icd); const struct soc_camera_format_xlate *xlate; struct v4l2_pix_format *pix = &f->fmt.pix; int ret; @@ -550,7 +548,7 @@ static int mx1_camera_set_fmt(struct soc_camera_device *icd, return -EINVAL; } - ret = v4l2_device_call_until_err(&ici->v4l2_dev, 0, video, s_fmt, f); + ret = v4l2_subdev_call(sd, video, s_fmt, f); if (!ret) { icd->buswidth = xlate->buswidth; icd->current_fmt = xlate->host_fmt; @@ -562,11 +560,11 @@ static int mx1_camera_set_fmt(struct soc_camera_device *icd, static int mx1_camera_try_fmt(struct soc_camera_device *icd, struct v4l2_format *f) { - struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); + struct v4l2_subdev *sd = soc_camera_to_subdev(icd); /* TODO: limit to mx1 hardware capabilities */ /* limit to sensor capabilities */ - return v4l2_device_call_until_err(&ici->v4l2_dev, 0, video, try_fmt, f); + return v4l2_subdev_call(sd, video, try_fmt, f); } static int mx1_camera_reqbufs(struct soc_camera_file *icf, diff --git a/linux/drivers/media/video/mx3_camera.c b/linux/drivers/media/video/mx3_camera.c index de7ebfbf0..f7888f30d 100644 --- a/linux/drivers/media/video/mx3_camera.c +++ b/linux/drivers/media/video/mx3_camera.c @@ -786,8 +786,7 @@ static int mx3_camera_set_crop(struct soc_camera_device *icd, struct v4l2_rect *rect = &a->c; struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); struct mx3_camera_dev *mx3_cam = ici->priv; - struct device *control = to_soc_camera_control(icd); - struct v4l2_subdev *sd = dev_get_drvdata(control); + struct v4l2_subdev *sd = soc_camera_to_subdev(icd); /* * We now know pixel formats and can decide upon DMA-channel(s) @@ -809,6 +808,7 @@ static int mx3_camera_set_fmt(struct soc_camera_device *icd, { struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); struct mx3_camera_dev *mx3_cam = ici->priv; + struct v4l2_subdev *sd = soc_camera_to_subdev(icd); const struct soc_camera_format_xlate *xlate; struct v4l2_pix_format *pix = &f->fmt.pix; struct v4l2_rect rect = { @@ -837,7 +837,7 @@ static int mx3_camera_set_fmt(struct soc_camera_device *icd, configure_geometry(mx3_cam, &rect); - ret = v4l2_device_call_until_err(&ici->v4l2_dev, 0, video, s_fmt, f); + ret = v4l2_subdev_call(sd, video, s_fmt, f); if (!ret) { icd->buswidth = xlate->buswidth; icd->current_fmt = xlate->host_fmt; @@ -849,7 +849,7 @@ static int mx3_camera_set_fmt(struct soc_camera_device *icd, static int mx3_camera_try_fmt(struct soc_camera_device *icd, struct v4l2_format *f) { - struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); + struct v4l2_subdev *sd = soc_camera_to_subdev(icd); const struct soc_camera_format_xlate *xlate; struct v4l2_pix_format *pix = &f->fmt.pix; __u32 pixfmt = pix->pixelformat; @@ -875,7 +875,7 @@ static int mx3_camera_try_fmt(struct soc_camera_device *icd, /* camera has to see its format, but the user the original one */ pix->pixelformat = xlate->cam_fmt->fourcc; /* limit to sensor capabilities */ - ret = v4l2_device_call_until_err(&ici->v4l2_dev, 0, video, try_fmt, f); + ret = v4l2_subdev_call(sd, video, try_fmt, f); pix->pixelformat = xlate->host_fmt->fourcc; field = pix->field; diff --git a/linux/drivers/media/video/pxa_camera.c b/linux/drivers/media/video/pxa_camera.c index d447e5b59..c35b07ae3 100644 --- a/linux/drivers/media/video/pxa_camera.c +++ b/linux/drivers/media/video/pxa_camera.c @@ -1298,8 +1298,7 @@ static int pxa_camera_set_crop(struct soc_camera_device *icd, struct v4l2_rect *rect = &a->c; struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); struct pxa_camera_dev *pcdev = ici->priv; - struct device *control = to_soc_camera_control(icd); - struct v4l2_subdev *sd = dev_get_drvdata(control); + struct v4l2_subdev *sd = soc_camera_to_subdev(icd); struct soc_camera_sense sense = { .master_clock = pcdev->mclk, .pixel_clock_max = pcdev->ciclk / 4, @@ -1335,6 +1334,7 @@ static int pxa_camera_set_fmt(struct soc_camera_device *icd, { struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); struct pxa_camera_dev *pcdev = ici->priv; + struct v4l2_subdev *sd = soc_camera_to_subdev(icd); const struct soc_camera_data_format *cam_fmt = NULL; const struct soc_camera_format_xlate *xlate = NULL; struct soc_camera_sense sense = { @@ -1358,7 +1358,7 @@ static int pxa_camera_set_fmt(struct soc_camera_device *icd, icd->sense = &sense; cam_f.fmt.pix.pixelformat = cam_fmt->fourcc; - ret = v4l2_device_call_until_err(&ici->v4l2_dev, 0, video, s_fmt, f); + ret = v4l2_subdev_call(sd, video, s_fmt, f); icd->sense = NULL; @@ -1387,6 +1387,7 @@ static int pxa_camera_try_fmt(struct soc_camera_device *icd, struct v4l2_format *f) { struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); + struct v4l2_subdev *sd = soc_camera_to_subdev(icd); const struct soc_camera_format_xlate *xlate; struct v4l2_pix_format *pix = &f->fmt.pix; __u32 pixfmt = pix->pixelformat; @@ -1416,7 +1417,7 @@ static int pxa_camera_try_fmt(struct soc_camera_device *icd, /* camera has to see its format, but the user the original one */ pix->pixelformat = xlate->cam_fmt->fourcc; /* limit to sensor capabilities */ - ret = v4l2_device_call_until_err(&ici->v4l2_dev, 0, video, try_fmt, f); + ret = v4l2_subdev_call(sd, video, try_fmt, f); pix->pixelformat = xlate->host_fmt->fourcc; field = pix->field; diff --git a/linux/drivers/media/video/sh_mobile_ceu_camera.c b/linux/drivers/media/video/sh_mobile_ceu_camera.c index c60088447..01371416e 100644 --- a/linux/drivers/media/video/sh_mobile_ceu_camera.c +++ b/linux/drivers/media/video/sh_mobile_ceu_camera.c @@ -856,8 +856,7 @@ static int sh_mobile_ceu_set_crop(struct soc_camera_device *icd, struct v4l2_crop cam_crop; struct v4l2_rect *cam_rect = &cam_crop.c, target, cam_max; struct sh_mobile_ceu_cam *cam = icd->host_priv; - struct device *control = to_soc_camera_control(icd); - struct v4l2_subdev *sd = dev_get_drvdata(control); + struct v4l2_subdev *sd = soc_camera_to_subdev(icd); unsigned int hscale = pcdev->cflcr & 0xffff; unsigned int vscale = (pcdev->cflcr >> 16) & 0xffff; unsigned short width, height; @@ -1018,6 +1017,7 @@ static int sh_mobile_ceu_set_fmt(struct soc_camera_device *icd, struct sh_mobile_ceu_dev *pcdev = ici->priv; struct sh_mobile_ceu_cam *cam = icd->host_priv; struct v4l2_pix_format *pix = &f->fmt.pix; + struct v4l2_subdev *sd = soc_camera_to_subdev(icd); __u32 pixfmt = pix->pixelformat; const struct soc_camera_format_xlate *xlate; unsigned int width = pix->width, height = pix->height, tmp_w, tmp_h; @@ -1044,7 +1044,7 @@ static int sh_mobile_ceu_set_fmt(struct soc_camera_device *icd, } pix->pixelformat = xlate->cam_fmt->fourcc; - ret = v4l2_device_call_until_err(&ici->v4l2_dev, (__u32)icd, video, s_fmt, f); + ret = v4l2_subdev_call(sd, video, s_fmt, f); pix->pixelformat = pixfmt; dev_dbg(&icd->dev, "Camera %d fmt %ux%u, requested %ux%u, max %ux%u\n", ret, pix->width, pix->height, width, height, @@ -1084,8 +1084,7 @@ static int sh_mobile_ceu_set_fmt(struct soc_camera_device *icd, pix->width = tmp_w; pix->height = tmp_h; pix->pixelformat = xlate->cam_fmt->fourcc; - ret = v4l2_device_call_until_err(&ici->v4l2_dev, (__u32)icd, - video, s_fmt, f); + ret = v4l2_subdev_call(sd, video, s_fmt, f); pix->pixelformat = pixfmt; dev_dbg(&icd->dev, "Camera scaled to %ux%u\n", pix->width, pix->height); @@ -1142,6 +1141,7 @@ static int sh_mobile_ceu_try_fmt(struct soc_camera_device *icd, struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); const struct soc_camera_format_xlate *xlate; struct v4l2_pix_format *pix = &f->fmt.pix; + struct v4l2_subdev *sd = soc_camera_to_subdev(icd); __u32 pixfmt = pix->pixelformat; int width, height; int ret; @@ -1167,8 +1167,7 @@ static int sh_mobile_ceu_try_fmt(struct soc_camera_device *icd, pix->pixelformat = xlate->cam_fmt->fourcc; /* limit to sensor capabilities */ - ret = v4l2_device_call_until_err(&ici->v4l2_dev, (__u32)icd, video, - try_fmt, f); + ret = v4l2_subdev_call(sd, video, try_fmt, f); pix->pixelformat = pixfmt; if (ret < 0) return ret; @@ -1184,9 +1183,7 @@ static int sh_mobile_ceu_try_fmt(struct soc_camera_device *icd, int tmp_w = pix->width, tmp_h = pix->height; pix->width = 2560; pix->height = 1920; - ret = v4l2_device_call_until_err(&ici->v4l2_dev, - (__u32)icd, video, - try_fmt, f); + ret = v4l2_subdev_call(sd, video, try_fmt, f); if (ret < 0) { /* Shouldn't actually happen... */ dev_err(&icd->dev, diff --git a/linux/drivers/media/video/soc_camera.c b/linux/drivers/media/video/soc_camera.c index ab469554b..0517754f7 100644 --- a/linux/drivers/media/video/soc_camera.c +++ b/linux/drivers/media/video/soc_camera.c @@ -153,9 +153,9 @@ static int soc_camera_s_std(struct file *file, void *priv, v4l2_std_id *a) { struct soc_camera_file *icf = file->private_data; struct soc_camera_device *icd = icf->icd; - struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); + struct v4l2_subdev *sd = soc_camera_to_subdev(icd); - return v4l2_device_call_until_err(&ici->v4l2_dev, (__u32)icd, core, s_std, *a); + return v4l2_subdev_call(sd, core, s_std, *a); } static int soc_camera_reqbufs(struct file *file, void *priv, @@ -590,7 +590,7 @@ static int soc_camera_streamon(struct file *file, void *priv, { struct soc_camera_file *icf = file->private_data; struct soc_camera_device *icd = icf->icd; - struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); + struct v4l2_subdev *sd = soc_camera_to_subdev(icd); int ret; WARN_ON(priv != file->private_data); @@ -600,7 +600,7 @@ static int soc_camera_streamon(struct file *file, void *priv, mutex_lock(&icd->video_lock); - v4l2_device_call_until_err(&ici->v4l2_dev, (__u32)icd, video, s_stream, 1); + v4l2_subdev_call(sd, video, s_stream, 1); /* This calls buf_queue from host driver's videobuf_queue_ops */ ret = videobuf_streamon(&icf->vb_vidq); @@ -615,7 +615,7 @@ static int soc_camera_streamoff(struct file *file, void *priv, { struct soc_camera_file *icf = file->private_data; struct soc_camera_device *icd = icf->icd; - struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); + struct v4l2_subdev *sd = soc_camera_to_subdev(icd); WARN_ON(priv != file->private_data); @@ -628,7 +628,7 @@ static int soc_camera_streamoff(struct file *file, void *priv, * remaining buffers. When the last buffer is freed, stop capture */ videobuf_streamoff(&icf->vb_vidq); - v4l2_device_call_until_err(&ici->v4l2_dev, (__u32)icd, video, s_stream, 0); + v4l2_subdev_call(sd, video, s_stream, 0); mutex_unlock(&icd->video_lock); @@ -673,6 +673,7 @@ static int soc_camera_g_ctrl(struct file *file, void *priv, struct soc_camera_file *icf = file->private_data; struct soc_camera_device *icd = icf->icd; struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); + struct v4l2_subdev *sd = soc_camera_to_subdev(icd); int ret; WARN_ON(priv != file->private_data); @@ -696,7 +697,7 @@ static int soc_camera_g_ctrl(struct file *file, void *priv, return ret; } - return v4l2_device_call_until_err(&ici->v4l2_dev, (__u32)icd, core, g_ctrl, ctrl); + return v4l2_subdev_call(sd, core, g_ctrl, ctrl); } static int soc_camera_s_ctrl(struct file *file, void *priv, @@ -705,6 +706,7 @@ static int soc_camera_s_ctrl(struct file *file, void *priv, struct soc_camera_file *icf = file->private_data; struct soc_camera_device *icd = icf->icd; struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); + struct v4l2_subdev *sd = soc_camera_to_subdev(icd); int ret; WARN_ON(priv != file->private_data); @@ -715,7 +717,7 @@ static int soc_camera_s_ctrl(struct file *file, void *priv, return ret; } - return v4l2_device_call_until_err(&ici->v4l2_dev, (__u32)icd, core, s_ctrl, ctrl); + return v4l2_subdev_call(sd, core, s_ctrl, ctrl); } static int soc_camera_cropcap(struct file *file, void *fh, @@ -813,9 +815,9 @@ static int soc_camera_g_chip_ident(struct file *file, void *fh, { struct soc_camera_file *icf = file->private_data; struct soc_camera_device *icd = icf->icd; - struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); + struct v4l2_subdev *sd = soc_camera_to_subdev(icd); - return v4l2_device_call_until_err(&ici->v4l2_dev, (__u32)icd, core, g_chip_ident, id); + return v4l2_subdev_call(sd, core, g_chip_ident, id); } #ifdef CONFIG_VIDEO_ADV_DEBUG @@ -824,9 +826,9 @@ static int soc_camera_g_register(struct file *file, void *fh, { struct soc_camera_file *icf = file->private_data; struct soc_camera_device *icd = icf->icd; - struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); + struct v4l2_subdev *sd = soc_camera_to_subdev(icd); - return v4l2_device_call_until_err(&ici->v4l2_dev, (__u32)icd, core, g_register, reg); + return v4l2_subdev_call(sd, core, g_register, reg); } static int soc_camera_s_register(struct file *file, void *fh, @@ -834,9 +836,9 @@ static int soc_camera_s_register(struct file *file, void *fh, { struct soc_camera_file *icf = file->private_data; struct soc_camera_device *icd = icf->icd; - struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); + struct v4l2_subdev *sd = soc_camera_to_subdev(icd); - return v4l2_device_call_until_err(&ici->v4l2_dev, (__u32)icd, core, s_register, reg); + return v4l2_subdev_call(sd, core, s_register, reg); } #endif -- cgit v1.2.3 From 3a76b0c22111746bd099bc5c9279dbedc734e3ac Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Tue, 25 Aug 2009 16:47:00 +0200 Subject: soc-camera: Use I2C device for dev_{dbg,info,...} output in all clients From: Guennadi Liakhovetski Signed-off-by: Guennadi Liakhovetski Priority: low --- drivers/media/video/mt9m001.c | 20 +++++++++++--------- drivers/media/video/mt9m111.c | 11 +++++------ drivers/media/video/mt9t031.c | 16 ++++++++-------- drivers/media/video/mt9v022.c | 16 ++++++++-------- drivers/media/video/ov772x.c | 6 +++--- drivers/media/video/tw9910.c | 6 +++--- 6 files changed, 38 insertions(+), 37 deletions(-) --- linux/drivers/media/video/mt9m001.c | 20 +++++++++++--------- linux/drivers/media/video/mt9m111.c | 11 +++++------ linux/drivers/media/video/mt9t031.c | 16 ++++++++-------- linux/drivers/media/video/mt9v022.c | 16 ++++++++-------- linux/drivers/media/video/ov772x.c | 6 +++--- linux/drivers/media/video/tw9910.c | 6 +++--- 6 files changed, 38 insertions(+), 37 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/mt9m001.c b/linux/drivers/media/video/mt9m001.c index b74ef6cea..d4ebab8c2 100644 --- a/linux/drivers/media/video/mt9m001.c +++ b/linux/drivers/media/video/mt9m001.c @@ -118,7 +118,7 @@ static int mt9m001_init(struct soc_camera_device *icd) struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); int ret; - dev_dbg(&icd->dev, "%s\n", __func__); + dev_dbg(&client->dev, "%s\n", __func__); /* * We don't know, whether platform provides reset, @@ -421,7 +421,7 @@ static int mt9m001_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) unsigned long range = qctrl->default_value - qctrl->minimum; data = ((ctrl->value - qctrl->minimum) * 8 + range / 2) / range; - dev_dbg(&icd->dev, "Setting gain %d\n", data); + dev_dbg(&client->dev, "Setting gain %d\n", data); data = reg_write(client, MT9M001_GLOBAL_GAIN, data); if (data < 0) return -EIO; @@ -439,7 +439,7 @@ static int mt9m001_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) else data = ((gain - 64) * 7 + 28) / 56 + 96; - dev_dbg(&icd->dev, "Setting gain from %d to %d\n", + dev_dbg(&client->dev, "Setting gain from %d to %d\n", reg_read(client, MT9M001_GLOBAL_GAIN), data); data = reg_write(client, MT9M001_GLOBAL_GAIN, data); if (data < 0) @@ -458,8 +458,10 @@ static int mt9m001_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) unsigned long shutter = ((ctrl->value - qctrl->minimum) * 1048 + range / 2) / range + 1; - dev_dbg(&icd->dev, "Setting shutter width from %d to %lu\n", - reg_read(client, MT9M001_SHUTTER_WIDTH), shutter); + dev_dbg(&client->dev, + "Setting shutter width from %d to %lu\n", + reg_read(client, MT9M001_SHUTTER_WIDTH), + shutter); if (reg_write(client, MT9M001_SHUTTER_WIDTH, shutter) < 0) return -EIO; icd->exposure = ctrl->value; @@ -504,7 +506,7 @@ static int mt9m001_video_probe(struct soc_camera_device *icd, /* Enable the chip */ data = reg_write(client, MT9M001_CHIP_ENABLE, 1); - dev_dbg(&icd->dev, "write: %d\n", data); + dev_dbg(&client->dev, "write: %d\n", data); /* Read out the chip version register */ data = reg_read(client, MT9M001_CHIP_VERSION); @@ -521,7 +523,7 @@ static int mt9m001_video_probe(struct soc_camera_device *icd, icd->formats = mt9m001_monochrome_formats; break; default: - dev_err(&icd->dev, + dev_err(&client->dev, "No MT9M001 chip detected, register read %x\n", data); return -ENODEV; } @@ -546,7 +548,7 @@ static int mt9m001_video_probe(struct soc_camera_device *icd, if (flags & SOCAM_DATAWIDTH_8) icd->num_formats++; - dev_info(&icd->dev, "Detected a MT9M001 chip ID %x (%s)\n", data, + dev_info(&client->dev, "Detected a MT9M001 chip ID %x (%s)\n", data, data == 0x8431 ? "C12STM" : "C12ST"); return 0; @@ -557,7 +559,7 @@ static void mt9m001_video_remove(struct soc_camera_device *icd) struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); struct soc_camera_link *icl = to_soc_camera_link(icd); - dev_dbg(&icd->dev, "Video %x removed: %p, %p\n", client->addr, + dev_dbg(&client->dev, "Video %x removed: %p, %p\n", client->addr, icd->dev.parent, icd->vdev); if (icl->free_bus) icl->free_bus(icl); diff --git a/linux/drivers/media/video/mt9m111.c b/linux/drivers/media/video/mt9m111.c index cab9de000..44e565faf 100644 --- a/linux/drivers/media/video/mt9m111.c +++ b/linux/drivers/media/video/mt9m111.c @@ -400,10 +400,9 @@ static int mt9m111_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) struct v4l2_rect *rect = &a->c; struct i2c_client *client = sd->priv; struct mt9m111 *mt9m111 = to_mt9m111(client); - struct soc_camera_device *icd = client->dev.platform_data; int ret; - dev_dbg(&icd->dev, "%s left=%d, top=%d, width=%d, height=%d\n", + dev_dbg(&client->dev, "%s left=%d, top=%d, width=%d, height=%d\n", __func__, rect->left, rect->top, rect->width, rect->height); @@ -818,7 +817,7 @@ static int mt9m111_init(struct soc_camera_device *icd) if (!ret) ret = mt9m111_set_autoexposure(client, mt9m111->autoexposure); if (ret) - dev_err(&icd->dev, "mt9m11x init failed: %d\n", ret); + dev_err(&client->dev, "mt9m11x init failed: %d\n", ret); return ret; } @@ -833,7 +832,7 @@ static int mt9m111_release(struct soc_camera_device *icd) mt9m111->powered = 0; if (ret < 0) - dev_err(&icd->dev, "mt9m11x release failed: %d\n", ret); + dev_err(&client->dev, "mt9m11x release failed: %d\n", ret); return ret; } @@ -875,7 +874,7 @@ static int mt9m111_video_probe(struct soc_camera_device *icd, break; default: ret = -ENODEV; - dev_err(&icd->dev, + dev_err(&client->dev, "No MT9M11x chip detected, register read %x\n", data); goto ei2c; } @@ -883,7 +882,7 @@ static int mt9m111_video_probe(struct soc_camera_device *icd, icd->formats = mt9m111_colour_formats; icd->num_formats = ARRAY_SIZE(mt9m111_colour_formats); - dev_info(&icd->dev, "Detected a MT9M11x chip ID %x\n", data); + dev_info(&client->dev, "Detected a MT9M11x chip ID %x\n", data); mt9m111->autoexposure = 1; mt9m111->autowhitebalance = 1; diff --git a/linux/drivers/media/video/mt9t031.c b/linux/drivers/media/video/mt9t031.c index 6bcea4165..00877b4ae 100644 --- a/linux/drivers/media/video/mt9t031.c +++ b/linux/drivers/media/video/mt9t031.c @@ -248,7 +248,7 @@ static int mt9t031_set_params(struct soc_camera_device *icd, xbin = min(xskip, (u16)3); ybin = min(yskip, (u16)3); - dev_dbg(&icd->dev, "xskip %u, width %u/%u, yskip %u, height %u/%u\n", + dev_dbg(&client->dev, "xskip %u, width %u/%u, yskip %u, height %u/%u\n", xskip, width, rect->width, yskip, height, rect->height); /* Could just do roundup(rect->left, [xy]bin * 2); but this is cheaper */ @@ -287,7 +287,7 @@ static int mt9t031_set_params(struct soc_camera_device *icd, ret = reg_write(client, MT9T031_ROW_ADDRESS_MODE, ((ybin - 1) << 4) | (yskip - 1)); } - dev_dbg(&icd->dev, "new physical left %u, top %u\n", left, top); + dev_dbg(&client->dev, "new physical left %u, top %u\n", left, top); /* The caller provides a supported format, as guaranteed by * icd->try_fmt_cap(), soc_camera_s_crop() and soc_camera_cropcap() */ @@ -567,7 +567,7 @@ static int mt9t031_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) unsigned long range = qctrl->default_value - qctrl->minimum; data = ((ctrl->value - qctrl->minimum) * 8 + range / 2) / range; - dev_dbg(&icd->dev, "Setting gain %d\n", data); + dev_dbg(&client->dev, "Setting gain %d\n", data); data = reg_write(client, MT9T031_GLOBAL_GAIN, data); if (data < 0) return -EIO; @@ -587,7 +587,7 @@ static int mt9t031_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) /* calculated gain 65..1024 -> (1..120) << 8 + 0x60 */ data = (((gain - 64 + 7) * 32) & 0xff00) | 0x60; - dev_dbg(&icd->dev, "Setting gain from 0x%x to 0x%x\n", + dev_dbg(&client->dev, "Set gain from 0x%x to 0x%x\n", reg_read(client, MT9T031_GLOBAL_GAIN), data); data = reg_write(client, MT9T031_GLOBAL_GAIN, data); if (data < 0) @@ -608,7 +608,7 @@ static int mt9t031_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) u32 old; get_shutter(client, &old); - dev_dbg(&icd->dev, "Setting shutter width from %u to %u\n", + dev_dbg(&client->dev, "Set shutter from %u to %u\n", old, shutter); if (set_shutter(client, shutter) < 0) return -EIO; @@ -653,7 +653,7 @@ static int mt9t031_video_probe(struct i2c_client *client) /* Enable the chip */ data = reg_write(client, MT9T031_CHIP_ENABLE, 1); - dev_dbg(&icd->dev, "write: %d\n", data); + dev_dbg(&client->dev, "write: %d\n", data); /* Read out the chip version register */ data = reg_read(client, MT9T031_CHIP_VERSION); @@ -665,12 +665,12 @@ static int mt9t031_video_probe(struct i2c_client *client) icd->num_formats = ARRAY_SIZE(mt9t031_colour_formats); break; default: - dev_err(&icd->dev, + dev_err(&client->dev, "No MT9T031 chip detected, register read %x\n", data); return -ENODEV; } - dev_info(&icd->dev, "Detected a MT9T031 chip ID %x\n", data); + dev_info(&client->dev, "Detected a MT9T031 chip ID %x\n", data); return 0; } diff --git a/linux/drivers/media/video/mt9v022.c b/linux/drivers/media/video/mt9v022.c index 088ffa464..fd2d13d6c 100644 --- a/linux/drivers/media/video/mt9v022.c +++ b/linux/drivers/media/video/mt9v022.c @@ -224,7 +224,7 @@ static int mt9v022_set_bus_param(struct soc_camera_device *icd, if (ret < 0) return ret; - dev_dbg(&icd->dev, "Calculated pixclk 0x%x, chip control 0x%x\n", + dev_dbg(&client->dev, "Calculated pixclk 0x%x, chip control 0x%x\n", pixclk, mt9v022->chip_control); return 0; @@ -287,7 +287,7 @@ static int mt9v022_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) if (ret < 0) return ret; - dev_dbg(&icd->dev, "Frame %ux%u pixel\n", rect->width, rect->height); + dev_dbg(&client->dev, "Frame %ux%u pixel\n", rect->width, rect->height); return 0; } @@ -545,7 +545,7 @@ static int mt9v022_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) if (reg_clear(client, MT9V022_AEC_AGC_ENABLE, 0x2) < 0) return -EIO; - dev_info(&icd->dev, "Setting gain from %d to %lu\n", + dev_info(&client->dev, "Setting gain from %d to %lu\n", reg_read(client, MT9V022_ANALOG_GAIN), gain); if (reg_write(client, MT9V022_ANALOG_GAIN, gain) < 0) return -EIO; @@ -566,7 +566,7 @@ static int mt9v022_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) if (reg_clear(client, MT9V022_AEC_AGC_ENABLE, 0x1) < 0) return -EIO; - dev_dbg(&icd->dev, "Shutter width from %d to %lu\n", + dev_dbg(&client->dev, "Shutter width from %d to %lu\n", reg_read(client, MT9V022_TOTAL_SHUTTER_WIDTH), shutter); if (reg_write(client, MT9V022_TOTAL_SHUTTER_WIDTH, @@ -616,7 +616,7 @@ static int mt9v022_video_probe(struct soc_camera_device *icd, /* must be 0x1311 or 0x1313 */ if (data != 0x1311 && data != 0x1313) { ret = -ENODEV; - dev_info(&icd->dev, "No MT9V022 detected, ID register 0x%x\n", + dev_info(&client->dev, "No MT9V022 found, ID register 0x%x\n", data); goto ei2c; } @@ -628,7 +628,7 @@ static int mt9v022_video_probe(struct soc_camera_device *icd, /* 15 clock cycles */ udelay(200); if (reg_read(client, MT9V022_RESET)) { - dev_err(&icd->dev, "Resetting MT9V022 failed!\n"); + dev_err(&client->dev, "Resetting MT9V022 failed!\n"); if (ret > 0) ret = -EIO; goto ei2c; @@ -669,7 +669,7 @@ static int mt9v022_video_probe(struct soc_camera_device *icd, if (flags & SOCAM_DATAWIDTH_8) icd->num_formats++; - dev_info(&icd->dev, "Detected a MT9V022 chip ID %x, %s sensor\n", + dev_info(&client->dev, "Detected a MT9V022 chip ID %x, %s sensor\n", data, mt9v022->model == V4L2_IDENT_MT9V022IX7ATM ? "monochrome" : "colour"); @@ -682,7 +682,7 @@ static void mt9v022_video_remove(struct soc_camera_device *icd) struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); struct soc_camera_link *icl = to_soc_camera_link(icd); - dev_dbg(&icd->dev, "Video %x removed: %p, %p\n", client->addr, + dev_dbg(&client->dev, "Video %x removed: %p, %p\n", client->addr, icd->dev.parent, icd->vdev); if (icl->free_bus) icl->free_bus(icl); diff --git a/linux/drivers/media/video/ov772x.c b/linux/drivers/media/video/ov772x.c index c5b63f420..392327b72 100644 --- a/linux/drivers/media/video/ov772x.c +++ b/linux/drivers/media/video/ov772x.c @@ -1002,7 +1002,7 @@ static int ov772x_video_probe(struct soc_camera_device *icd, */ if (SOCAM_DATAWIDTH_10 != priv->info->buswidth && SOCAM_DATAWIDTH_8 != priv->info->buswidth) { - dev_err(&icd->dev, "bus width error\n"); + dev_err(&client->dev, "bus width error\n"); return -ENODEV; } @@ -1025,12 +1025,12 @@ static int ov772x_video_probe(struct soc_camera_device *icd, priv->model = V4L2_IDENT_OV7725; break; default: - dev_err(&icd->dev, + dev_err(&client->dev, "Product ID error %x:%x\n", pid, ver); return -ENODEV; } - dev_info(&icd->dev, + dev_info(&client->dev, "%s Product ID %0x:%0x Manufacturer ID %x:%x\n", devname, pid, diff --git a/linux/drivers/media/video/tw9910.c b/linux/drivers/media/video/tw9910.c index 266cf594c..e8c6cf119 100644 --- a/linux/drivers/media/video/tw9910.c +++ b/linux/drivers/media/video/tw9910.c @@ -793,7 +793,7 @@ static int tw9910_video_probe(struct soc_camera_device *icd, */ if (SOCAM_DATAWIDTH_16 != priv->info->buswidth && SOCAM_DATAWIDTH_8 != priv->info->buswidth) { - dev_err(&icd->dev, "bus width error\n"); + dev_err(&client->dev, "bus width error\n"); return -ENODEV; } @@ -807,12 +807,12 @@ static int tw9910_video_probe(struct soc_camera_device *icd, if (0x0B != GET_ID(val) || 0x00 != GET_ReV(val)) { - dev_err(&icd->dev, + dev_err(&client->dev, "Product ID error %x:%x\n", GET_ID(val), GET_ReV(val)); return -ENODEV; } - dev_info(&icd->dev, + dev_info(&client->dev, "tw9910 Product ID %0x:%0x\n", GET_ID(val), GET_ReV(val)); icd->vdev->tvnorms = V4L2_STD_NTSC | V4L2_STD_PAL; -- cgit v1.2.3 From d1d25e3f57f0395cafed266bfcb95fe4b21d45f3 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Tue, 25 Aug 2009 16:47:00 +0200 Subject: soc-camera: Use camera device object for core output From: Guennadi Liakhovetski Signed-off-by: Guennadi Liakhovetski Priority: low --- drivers/media/video/soc_camera.c | 8 +++----- 1 files changed, 3 insertions(+), 5 deletions(-) --- linux/drivers/media/video/soc_camera.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/soc_camera.c b/linux/drivers/media/video/soc_camera.c index 0517754f7..6145846f7 100644 --- a/linux/drivers/media/video/soc_camera.c +++ b/linux/drivers/media/video/soc_camera.c @@ -298,7 +298,7 @@ static int soc_camera_set_fmt(struct soc_camera_file *icf, return ret; } else if (!icd->current_fmt || icd->current_fmt->fourcc != pix->pixelformat) { - dev_err(ici->v4l2_dev.dev, + dev_err(&icd->dev, "Host driver hasn't set up current format correctly!\n"); return -EINVAL; } @@ -427,7 +427,6 @@ static int soc_camera_close(struct file *file) struct soc_camera_file *icf = file->private_data; struct soc_camera_device *icd = icf->icd; struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); - struct video_device *vdev = icd->vdev; mutex_lock(&icd->video_lock); icd->use_count--; @@ -447,7 +446,7 @@ static int soc_camera_close(struct file *file) vfree(icf); - dev_dbg(vdev->parent, "camera device close\n"); + dev_dbg(&icd->dev, "camera device close\n"); return 0; } @@ -457,10 +456,9 @@ static ssize_t soc_camera_read(struct file *file, char __user *buf, { struct soc_camera_file *icf = file->private_data; struct soc_camera_device *icd = icf->icd; - struct video_device *vdev = icd->vdev; int err = -EINVAL; - dev_err(vdev->parent, "camera device read not implemented\n"); + dev_err(&icd->dev, "camera device read not implemented\n"); return err; } -- cgit v1.2.3 From bb52712a084d97b0bcfff36d62fc9c69c33858e5 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Tue, 25 Aug 2009 16:47:00 +0200 Subject: soc-camera: Use video device object for output in host drivers From: Guennadi Liakhovetski Signed-off-by: Guennadi Liakhovetski Priority: low --- drivers/media/video/mx1_camera.c | 38 ++++++++++-------- drivers/media/video/mx3_camera.c | 46 ++++++++++++--------- drivers/media/video/pxa_camera.c | 54 ++++++++++++++----------- drivers/media/video/sh_mobile_ceu_camera.c | 61 ++++++++++++++------------- 4 files changed, 110 insertions(+), 89 deletions(-) --- linux/drivers/media/video/mx1_camera.c | 38 ++++++++------- linux/drivers/media/video/mx3_camera.c | 46 ++++++++++-------- linux/drivers/media/video/pxa_camera.c | 54 +++++++++++---------- linux/drivers/media/video/sh_mobile_ceu_camera.c | 61 +++++++++++++----------- 4 files changed, 110 insertions(+), 89 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/mx1_camera.c b/linux/drivers/media/video/mx1_camera.c index ed7856bda..1f1324a1d 100644 --- a/linux/drivers/media/video/mx1_camera.c +++ b/linux/drivers/media/video/mx1_camera.c @@ -135,7 +135,7 @@ static int mx1_videobuf_setup(struct videobuf_queue *vq, unsigned int *count, while (*size * *count > MAX_VIDEO_MEM * 1024 * 1024) (*count)--; - dev_dbg(&icd->dev, "count=%d, size=%d\n", *count, *size); + dev_dbg(icd->dev.parent, "count=%d, size=%d\n", *count, *size); return 0; } @@ -147,7 +147,7 @@ static void free_buffer(struct videobuf_queue *vq, struct mx1_buffer *buf) BUG_ON(in_interrupt()); - dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__, + dev_dbg(icd->dev.parent, "%s (vb=0x%p) 0x%08lx %d\n", __func__, vb, vb->baddr, vb->bsize); /* This waits until this buffer is out of danger, i.e., until it is no @@ -165,7 +165,7 @@ static int mx1_videobuf_prepare(struct videobuf_queue *vq, struct mx1_buffer *buf = container_of(vb, struct mx1_buffer, vb); int ret; - dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__, + dev_dbg(icd->dev.parent, "%s (vb=0x%p) 0x%08lx %d\n", __func__, vb, vb->baddr, vb->bsize); /* Added list head initialization on alloc */ @@ -216,10 +216,11 @@ out: static int mx1_camera_setup_dma(struct mx1_camera_dev *pcdev) { struct videobuf_buffer *vbuf = &pcdev->active->vb; + struct device *dev = pcdev->icd->dev.parent; int ret; if (unlikely(!pcdev->active)) { - dev_err(pcdev->icd->dev.parent, "DMA End IRQ with no active buffer\n"); + dev_err(dev, "DMA End IRQ with no active buffer\n"); return -EFAULT; } @@ -229,7 +230,7 @@ static int mx1_camera_setup_dma(struct mx1_camera_dev *pcdev) vbuf->size, pcdev->res->start + CSIRXR, DMA_MODE_READ); if (unlikely(ret)) - dev_err(pcdev->icd->dev.parent, "Failed to setup DMA sg list\n"); + dev_err(dev, "Failed to setup DMA sg list\n"); return ret; } @@ -243,7 +244,7 @@ static void mx1_videobuf_queue(struct videobuf_queue *vq, struct mx1_camera_dev *pcdev = ici->priv; struct mx1_buffer *buf = container_of(vb, struct mx1_buffer, vb); - dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__, + dev_dbg(icd->dev.parent, "%s (vb=0x%p) 0x%08lx %d\n", __func__, vb, vb->baddr, vb->bsize); list_add_tail(&vb->queue, &pcdev->capture); @@ -270,22 +271,23 @@ static void mx1_videobuf_release(struct videobuf_queue *vq, struct mx1_buffer *buf = container_of(vb, struct mx1_buffer, vb); #ifdef DEBUG struct soc_camera_device *icd = vq->priv_data; + struct device *dev = icd->dev.parent; - dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__, + dev_dbg(dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__, vb, vb->baddr, vb->bsize); switch (vb->state) { case VIDEOBUF_ACTIVE: - dev_dbg(&icd->dev, "%s (active)\n", __func__); + dev_dbg(dev, "%s (active)\n", __func__); break; case VIDEOBUF_QUEUED: - dev_dbg(&icd->dev, "%s (queued)\n", __func__); + dev_dbg(dev, "%s (queued)\n", __func__); break; case VIDEOBUF_PREPARED: - dev_dbg(&icd->dev, "%s (prepared)\n", __func__); + dev_dbg(dev, "%s (prepared)\n", __func__); break; default: - dev_dbg(&icd->dev, "%s (unknown)\n", __func__); + dev_dbg(dev, "%s (unknown)\n", __func__); break; } #endif @@ -325,6 +327,7 @@ static void mx1_camera_wakeup(struct mx1_camera_dev *pcdev, static void mx1_camera_dma_irq(int channel, void *data) { struct mx1_camera_dev *pcdev = data; + struct device *dev = pcdev->icd->dev.parent; struct mx1_buffer *buf; struct videobuf_buffer *vb; unsigned long flags; @@ -334,14 +337,14 @@ static void mx1_camera_dma_irq(int channel, void *data) imx_dma_disable(channel); if (unlikely(!pcdev->active)) { - dev_err(pcdev->icd->dev.parent, "DMA End IRQ with no active buffer\n"); + dev_err(dev, "DMA End IRQ with no active buffer\n"); goto out; } vb = &pcdev->active->vb; buf = container_of(vb, struct mx1_buffer, vb); WARN_ON(buf->inwork || list_empty(&vb->queue)); - dev_dbg(pcdev->icd->dev.parent, "%s (vb=0x%p) 0x%08lx %d\n", __func__, + dev_dbg(dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__, vb, vb->baddr, vb->bsize); mx1_camera_wakeup(pcdev, vb, buf); @@ -381,8 +384,9 @@ static int mclk_get_divisor(struct mx1_camera_dev *pcdev) * they get a nice Oops */ div = (lcdclk + 2 * mclk - 1) / (2 * mclk) - 1; - dev_dbg(pcdev->icd->dev.parent, "System clock %lukHz, target freq %dkHz, " - "divisor %lu\n", lcdclk / 1000, mclk / 1000, div); + dev_dbg(pcdev->icd->dev.parent, + "System clock %lukHz, target freq %dkHz, divisor %lu\n", + lcdclk / 1000, mclk / 1000, div); return div; } @@ -428,7 +432,7 @@ static int mx1_camera_add_device(struct soc_camera_device *icd) goto ebusy; } - dev_info(&icd->dev, "MX1 Camera driver attached to camera %d\n", + dev_info(icd->dev.parent, "MX1 Camera driver attached to camera %d\n", icd->devnum); mx1_camera_activate(pcdev); @@ -454,7 +458,7 @@ static void mx1_camera_remove_device(struct soc_camera_device *icd) /* Stop DMA engine */ imx_dma_disable(pcdev->dma_chan); - dev_info(&icd->dev, "MX1 Camera driver detached from camera %d\n", + dev_info(icd->dev.parent, "MX1 Camera driver detached from camera %d\n", icd->devnum); mx1_camera_deactivate(pcdev); diff --git a/linux/drivers/media/video/mx3_camera.c b/linux/drivers/media/video/mx3_camera.c index f7888f30d..d5b51e990 100644 --- a/linux/drivers/media/video/mx3_camera.c +++ b/linux/drivers/media/video/mx3_camera.c @@ -178,7 +178,7 @@ static void free_buffer(struct videobuf_queue *vq, struct mx3_camera_buffer *buf BUG_ON(in_interrupt()); - dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__, + dev_dbg(icd->dev.parent, "%s (vb=0x%p) 0x%08lx %d\n", __func__, vb, vb->baddr, vb->bsize); /* @@ -375,7 +375,8 @@ static void mx3_videobuf_queue(struct videobuf_queue *vq, spin_unlock_irq(&mx3_cam->lock); cookie = txd->tx_submit(txd); - dev_dbg(&icd->dev, "Submitted cookie %d DMA 0x%08x\n", cookie, sg_dma_address(&buf->sg)); + dev_dbg(icd->dev.parent, "Submitted cookie %d DMA 0x%08x\n", + cookie, sg_dma_address(&buf->sg)); spin_lock_irq(&mx3_cam->lock); @@ -402,9 +403,10 @@ static void mx3_videobuf_release(struct videobuf_queue *vq, container_of(vb, struct mx3_camera_buffer, vb); unsigned long flags; - dev_dbg(&icd->dev, "Release%s DMA 0x%08x (state %d), queue %sempty\n", + dev_dbg(icd->dev.parent, + "Release%s DMA 0x%08x (state %d), queue %sempty\n", mx3_cam->active == buf ? " active" : "", sg_dma_address(&buf->sg), - vb->state, list_empty(&vb->queue) ? "" : "not "); + vb->state, list_empty(&vb->queue) ? "" : "not "); spin_lock_irqsave(&mx3_cam->lock, flags); if ((vb->state == VIDEOBUF_ACTIVE || vb->state == VIDEOBUF_QUEUED) && !list_empty(&vb->queue)) { @@ -484,7 +486,7 @@ static void mx3_camera_activate(struct mx3_camera_dev *mx3_cam, clk_enable(mx3_cam->clk); rate = clk_round_rate(mx3_cam->clk, mx3_cam->mclk); - dev_dbg(&icd->dev, "Set SENS_CONF to %x, rate %ld\n", conf, rate); + dev_dbg(icd->dev.parent, "Set SENS_CONF to %x, rate %ld\n", conf, rate); if (rate) clk_set_rate(mx3_cam->clk, rate); } @@ -502,7 +504,7 @@ static int mx3_camera_add_device(struct soc_camera_device *icd) mx3_cam->icd = icd; - dev_info(&icd->dev, "MX3 Camera driver attached to camera %d\n", + dev_info(icd->dev.parent, "MX3 Camera driver attached to camera %d\n", icd->devnum); return 0; @@ -526,7 +528,7 @@ static void mx3_camera_remove_device(struct soc_camera_device *icd) mx3_cam->icd = NULL; - dev_info(&icd->dev, "MX3 Camera driver detached from camera %d\n", + dev_info(icd->dev.parent, "MX3 Camera driver detached from camera %d\n", icd->devnum); } @@ -603,7 +605,8 @@ static int mx3_camera_try_bus_param(struct soc_camera_device *icd, unsigned long bus_flags, camera_flags; int ret = test_platform_param(mx3_cam, depth, &bus_flags); - dev_dbg(icd->dev.parent, "requested bus width %d bit: %d\n", depth, ret); + dev_dbg(icd->dev.parent, "requested bus width %d bit: %d\n", + depth, ret); if (ret < 0) return ret; @@ -612,7 +615,8 @@ static int mx3_camera_try_bus_param(struct soc_camera_device *icd, ret = soc_camera_bus_param_compatible(camera_flags, bus_flags); if (ret < 0) - dev_warn(&icd->dev, "Flags incompatible: camera %lx, host %lx\n", + dev_warn(icd->dev.parent, + "Flags incompatible: camera %lx, host %lx\n", camera_flags, bus_flags); return ret; @@ -686,7 +690,8 @@ static int mx3_camera_get_formats(struct soc_camera_device *icd, int idx, xlate->cam_fmt = icd->formats + idx; xlate->buswidth = buswidth; xlate++; - dev_dbg(icd->dev.parent, "Providing format %s using %s\n", + dev_dbg(icd->dev.parent, + "Providing format %s using %s\n", mx3_camera_formats[0].name, icd->formats[idx].name); } @@ -698,7 +703,8 @@ static int mx3_camera_get_formats(struct soc_camera_device *icd, int idx, xlate->cam_fmt = icd->formats + idx; xlate->buswidth = buswidth; xlate++; - dev_dbg(icd->dev.parent, "Providing format %s using %s\n", + dev_dbg(icd->dev.parent, + "Providing format %s using %s\n", mx3_camera_formats[0].name, icd->formats[idx].name); } @@ -821,7 +827,8 @@ static int mx3_camera_set_fmt(struct soc_camera_device *icd, xlate = soc_camera_xlate_by_fourcc(icd, pix->pixelformat); if (!xlate) { - dev_warn(icd->dev.parent, "Format %x not found\n", pix->pixelformat); + dev_warn(icd->dev.parent, "Format %x not found\n", + pix->pixelformat); return -EINVAL; } @@ -883,7 +890,7 @@ static int mx3_camera_try_fmt(struct soc_camera_device *icd, if (field == V4L2_FIELD_ANY) { pix->field = V4L2_FIELD_NONE; } else if (field != V4L2_FIELD_NONE) { - dev_err(&icd->dev, "Field type %d unsupported.\n", field); + dev_err(icd->dev.parent, "Field type %d unsupported.\n", field); return -EINVAL; } @@ -922,14 +929,15 @@ static int mx3_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt) u32 dw, sens_conf; int ret = test_platform_param(mx3_cam, icd->buswidth, &bus_flags); const struct soc_camera_format_xlate *xlate; + struct device *dev = icd->dev.parent; xlate = soc_camera_xlate_by_fourcc(icd, pixfmt); if (!xlate) { - dev_warn(icd->dev.parent, "Format %x not found\n", pixfmt); + dev_warn(dev, "Format %x not found\n", pixfmt); return -EINVAL; } - dev_dbg(icd->dev.parent, "requested bus width %d bit: %d\n", + dev_dbg(dev, "requested bus width %d bit: %d\n", icd->buswidth, ret); if (ret < 0) @@ -938,10 +946,10 @@ static int mx3_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt) camera_flags = icd->ops->query_bus_param(icd); common_flags = soc_camera_bus_param_compatible(camera_flags, bus_flags); - dev_dbg(icd->dev.parent, "Flags cam: 0x%lx host: 0x%lx common: 0x%lx\n", + dev_dbg(dev, "Flags cam: 0x%lx host: 0x%lx common: 0x%lx\n", camera_flags, bus_flags, common_flags); if (!common_flags) { - dev_dbg(icd->dev.parent, "no common flags"); + dev_dbg(dev, "no common flags"); return -EINVAL; } @@ -995,7 +1003,7 @@ static int mx3_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt) ret = icd->ops->set_bus_param(icd, common_flags); if (ret < 0) { - dev_dbg(icd->dev.parent, "camera set_bus_param(%lx) returned %d\n", + dev_dbg(dev, "camera set_bus_param(%lx) returned %d\n", common_flags, ret); return ret; } @@ -1050,7 +1058,7 @@ static int mx3_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt) csi_reg_write(mx3_cam, sens_conf | dw, CSI_SENS_CONF); - dev_dbg(icd->dev.parent, "Set SENS_CONF to %x\n", sens_conf | dw); + dev_dbg(dev, "Set SENS_CONF to %x\n", sens_conf | dw); return 0; } diff --git a/linux/drivers/media/video/pxa_camera.c b/linux/drivers/media/video/pxa_camera.c index c35b07ae3..611e7ff7f 100644 --- a/linux/drivers/media/video/pxa_camera.c +++ b/linux/drivers/media/video/pxa_camera.c @@ -249,7 +249,7 @@ static int pxa_videobuf_setup(struct videobuf_queue *vq, unsigned int *count, { struct soc_camera_device *icd = vq->priv_data; - dev_dbg(&icd->dev, "count=%d, size=%d\n", *count, *size); + dev_dbg(icd->dev.parent, "count=%d, size=%d\n", *count, *size); *size = roundup(icd->rect_current.width * icd->rect_current.height * ((icd->current_fmt->depth + 7) >> 3), 8); @@ -271,7 +271,7 @@ static void free_buffer(struct videobuf_queue *vq, struct pxa_buffer *buf) BUG_ON(in_interrupt()); - dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__, + dev_dbg(icd->dev.parent, "%s (vb=0x%p) 0x%08lx %d\n", __func__, &buf->vb, buf->vb.baddr, buf->vb.bsize); /* This waits until this buffer is out of danger, i.e., until it is no @@ -552,7 +552,8 @@ static void pxa_dma_start_channels(struct pxa_camera_dev *pcdev) active = pcdev->active; for (i = 0; i < pcdev->channels; i++) { - dev_dbg(pcdev->soc_host.v4l2_dev.dev, "%s (channel=%d) ddadr=%08x\n", __func__, + dev_dbg(pcdev->soc_host.v4l2_dev.dev, + "%s (channel=%d) ddadr=%08x\n", __func__, i, active->dmas[i].sg_dma); DDADR(pcdev->dma_chans[i]) = active->dmas[i].sg_dma; DCSR(pcdev->dma_chans[i]) = DCSR_RUN; @@ -564,7 +565,8 @@ static void pxa_dma_stop_channels(struct pxa_camera_dev *pcdev) int i; for (i = 0; i < pcdev->channels; i++) { - dev_dbg(pcdev->soc_host.v4l2_dev.dev, "%s (channel=%d)\n", __func__, i); + dev_dbg(pcdev->soc_host.v4l2_dev.dev, + "%s (channel=%d)\n", __func__, i); DCSR(pcdev->dma_chans[i]) = 0; } } @@ -632,8 +634,8 @@ static void pxa_videobuf_queue(struct videobuf_queue *vq, struct pxa_camera_dev *pcdev = ici->priv; struct pxa_buffer *buf = container_of(vb, struct pxa_buffer, vb); - dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %d active=%p\n", __func__, - vb, vb->baddr, vb->bsize, pcdev->active); + dev_dbg(icd->dev.parent, "%s (vb=0x%p) 0x%08lx %d active=%p\n", + __func__, vb, vb->baddr, vb->bsize, pcdev->active); list_add_tail(&vb->queue, &pcdev->capture); @@ -650,22 +652,23 @@ static void pxa_videobuf_release(struct videobuf_queue *vq, struct pxa_buffer *buf = container_of(vb, struct pxa_buffer, vb); #ifdef DEBUG struct soc_camera_device *icd = vq->priv_data; + struct device *dev = icd->dev.parent; - dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__, + dev_dbg(dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__, vb, vb->baddr, vb->bsize); switch (vb->state) { case VIDEOBUF_ACTIVE: - dev_dbg(&icd->dev, "%s (active)\n", __func__); + dev_dbg(dev, "%s (active)\n", __func__); break; case VIDEOBUF_QUEUED: - dev_dbg(&icd->dev, "%s (queued)\n", __func__); + dev_dbg(dev, "%s (queued)\n", __func__); break; case VIDEOBUF_PREPARED: - dev_dbg(&icd->dev, "%s (prepared)\n", __func__); + dev_dbg(dev, "%s (prepared)\n", __func__); break; default: - dev_dbg(&icd->dev, "%s (unknown)\n", __func__); + dev_dbg(dev, "%s (unknown)\n", __func__); break; } #endif @@ -936,7 +939,8 @@ static irqreturn_t pxa_camera_irq(int irq, void *data) struct videobuf_buffer *vb; status = __raw_readl(pcdev->base + CISR); - dev_dbg(pcdev->soc_host.v4l2_dev.dev, "Camera interrupt status 0x%lx\n", status); + dev_dbg(pcdev->soc_host.v4l2_dev.dev, + "Camera interrupt status 0x%lx\n", status); if (!status) return IRQ_NONE; @@ -976,7 +980,7 @@ static int pxa_camera_add_device(struct soc_camera_device *icd) pcdev->icd = icd; - dev_info(&icd->dev, "PXA Camera driver attached to camera %d\n", + dev_info(icd->dev.parent, "PXA Camera driver attached to camera %d\n", icd->devnum); return 0; @@ -990,7 +994,7 @@ static void pxa_camera_remove_device(struct soc_camera_device *icd) BUG_ON(icd != pcdev->icd); - dev_info(&icd->dev, "PXA Camera driver detached from camera %d\n", + dev_info(icd->dev.parent, "PXA Camera driver detached from camera %d\n", icd->devnum); /* disable capture, disable interrupts */ @@ -1236,7 +1240,7 @@ static int required_buswidth(const struct soc_camera_data_format *fmt) static int pxa_camera_get_formats(struct soc_camera_device *icd, int idx, struct soc_camera_format_xlate *xlate) { - struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); + struct device *dev = icd->dev.parent; int formats = 0, buswidth, ret; buswidth = required_buswidth(icd->formats + idx); @@ -1256,7 +1260,7 @@ static int pxa_camera_get_formats(struct soc_camera_device *icd, int idx, xlate->cam_fmt = icd->formats + idx; xlate->buswidth = buswidth; xlate++; - dev_dbg(ici->v4l2_dev.dev, "Providing format %s using %s\n", + dev_dbg(dev, "Providing format %s using %s\n", pxa_camera_formats[0].name, icd->formats[idx].name); } @@ -1271,7 +1275,7 @@ static int pxa_camera_get_formats(struct soc_camera_device *icd, int idx, xlate->cam_fmt = icd->formats + idx; xlate->buswidth = buswidth; xlate++; - dev_dbg(ici->v4l2_dev.dev, "Providing format %s packed\n", + dev_dbg(dev, "Providing format %s packed\n", icd->formats[idx].name); } break; @@ -1283,7 +1287,7 @@ static int pxa_camera_get_formats(struct soc_camera_device *icd, int idx, xlate->cam_fmt = icd->formats + idx; xlate->buswidth = icd->formats[idx].depth; xlate++; - dev_dbg(ici->v4l2_dev.dev, + dev_dbg(dev, "Providing format %s in pass-through mode\n", icd->formats[idx].name); } @@ -1298,6 +1302,7 @@ static int pxa_camera_set_crop(struct soc_camera_device *icd, struct v4l2_rect *rect = &a->c; struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); struct pxa_camera_dev *pcdev = ici->priv; + struct device *dev = icd->dev.parent; struct v4l2_subdev *sd = soc_camera_to_subdev(icd); struct soc_camera_sense sense = { .master_clock = pcdev->mclk, @@ -1314,11 +1319,11 @@ static int pxa_camera_set_crop(struct soc_camera_device *icd, icd->sense = NULL; if (ret < 0) { - dev_warn(ici->v4l2_dev.dev, "Failed to crop to %ux%u@%u:%u\n", + dev_warn(dev, "Failed to crop to %ux%u@%u:%u\n", rect->width, rect->height, rect->left, rect->top); } else if (sense.flags & SOCAM_SENSE_PCLK_CHANGED) { if (sense.pixel_clock > sense.pixel_clock_max) { - dev_err(ici->v4l2_dev.dev, + dev_err(dev, "pixel clock %lu set by the camera too high!", sense.pixel_clock); return -EIO; @@ -1334,6 +1339,7 @@ static int pxa_camera_set_fmt(struct soc_camera_device *icd, { struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); struct pxa_camera_dev *pcdev = ici->priv; + struct device *dev = icd->dev.parent; struct v4l2_subdev *sd = soc_camera_to_subdev(icd); const struct soc_camera_data_format *cam_fmt = NULL; const struct soc_camera_format_xlate *xlate = NULL; @@ -1347,7 +1353,7 @@ static int pxa_camera_set_fmt(struct soc_camera_device *icd, xlate = soc_camera_xlate_by_fourcc(icd, pix->pixelformat); if (!xlate) { - dev_warn(ici->v4l2_dev.dev, "Format %x not found\n", pix->pixelformat); + dev_warn(dev, "Format %x not found\n", pix->pixelformat); return -EINVAL; } @@ -1363,11 +1369,11 @@ static int pxa_camera_set_fmt(struct soc_camera_device *icd, icd->sense = NULL; if (ret < 0) { - dev_warn(ici->v4l2_dev.dev, "Failed to configure for format %x\n", + dev_warn(dev, "Failed to configure for format %x\n", pix->pixelformat); } else if (sense.flags & SOCAM_SENSE_PCLK_CHANGED) { if (sense.pixel_clock > sense.pixel_clock_max) { - dev_err(ici->v4l2_dev.dev, + dev_err(dev, "pixel clock %lu set by the camera too high!", sense.pixel_clock); return -EIO; @@ -1425,7 +1431,7 @@ static int pxa_camera_try_fmt(struct soc_camera_device *icd, if (field == V4L2_FIELD_ANY) { pix->field = V4L2_FIELD_NONE; } else if (field != V4L2_FIELD_NONE) { - dev_err(&icd->dev, "Field type %d unsupported.\n", field); + dev_err(icd->dev.parent, "Field type %d unsupported.\n", field); return -EINVAL; } diff --git a/linux/drivers/media/video/sh_mobile_ceu_camera.c b/linux/drivers/media/video/sh_mobile_ceu_camera.c index 01371416e..142bdbc6f 100644 --- a/linux/drivers/media/video/sh_mobile_ceu_camera.c +++ b/linux/drivers/media/video/sh_mobile_ceu_camera.c @@ -169,7 +169,7 @@ static int sh_mobile_ceu_videobuf_setup(struct videobuf_queue *vq, (*count)--; } - dev_dbg(&icd->dev, "count=%d, size=%d\n", *count, *size); + dev_dbg(icd->dev.parent, "count=%d, size=%d\n", *count, *size); return 0; } @@ -179,7 +179,7 @@ static void free_buffer(struct videobuf_queue *vq, { struct soc_camera_device *icd = vq->priv_data; - dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %zd\n", __func__, + dev_dbg(icd->dev.parent, "%s (vb=0x%p) 0x%08lx %zd\n", __func__, &buf->vb, buf->vb.baddr, buf->vb.bsize); if (in_interrupt()) @@ -187,7 +187,7 @@ static void free_buffer(struct videobuf_queue *vq, videobuf_waiton(&buf->vb, 0, 0); videobuf_dma_contig_free(vq, &buf->vb); - dev_dbg(&icd->dev, "%s freed\n", __func__); + dev_dbg(icd->dev.parent, "%s freed\n", __func__); buf->vb.state = VIDEOBUF_NEEDS_INIT; } @@ -251,7 +251,7 @@ static int sh_mobile_ceu_videobuf_prepare(struct videobuf_queue *vq, buf = container_of(vb, struct sh_mobile_ceu_buffer, vb); - dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %zd\n", __func__, + dev_dbg(icd->dev.parent, "%s (vb=0x%p) 0x%08lx %zd\n", __func__, vb, vb->baddr, vb->bsize); /* Added list head initialization on alloc */ @@ -304,7 +304,7 @@ static void sh_mobile_ceu_videobuf_queue(struct videobuf_queue *vq, struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); struct sh_mobile_ceu_dev *pcdev = ici->priv; - dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %zd\n", __func__, + dev_dbg(icd->dev.parent, "%s (vb=0x%p) 0x%08lx %zd\n", __func__, vb, vb->baddr, vb->bsize); vb->state = VIDEOBUF_QUEUED; @@ -393,7 +393,7 @@ static int sh_mobile_ceu_add_device(struct soc_camera_device *icd) if (pcdev->icd) return -EBUSY; - dev_info(&icd->dev, + dev_info(icd->dev.parent, "SuperH Mobile CEU driver attached to camera %d\n", icd->devnum); @@ -433,7 +433,7 @@ static void sh_mobile_ceu_remove_device(struct soc_camera_device *icd) clk_disable(pcdev->clk); - dev_info(&icd->dev, + dev_info(icd->dev.parent, "SuperH Mobile CEU driver detached from camera %d\n", icd->devnum); @@ -499,7 +499,7 @@ static void sh_mobile_ceu_set_rect(struct soc_camera_device *icd, left = size_src(rect->left, hscale); top = size_src(rect->top, vscale); - dev_dbg(&icd->dev, "Left %u * 0x%x = %u, top %u * 0x%x = %u\n", + dev_dbg(icd->dev.parent, "Left %u * 0x%x = %u, top %u * 0x%x = %u\n", rect->left, hscale, left, rect->top, vscale, top); if (left > cam->camera_rect.left) { @@ -516,7 +516,7 @@ static void sh_mobile_ceu_set_rect(struct soc_camera_device *icd, top = cam->camera_rect.top; } - dev_dbg(&icd->dev, "New left %u, top %u, offsets %u:%u\n", + dev_dbg(icd->dev.parent, "New left %u, top %u, offsets %u:%u\n", rect->left, rect->top, left_offset, top_offset); if (pcdev->image_mode) { @@ -689,7 +689,7 @@ static int sh_mobile_ceu_set_bus_param(struct soc_camera_device *icd, ceu_write(pcdev, CDOCR, value); ceu_write(pcdev, CFWCR, 0); /* keep "datafetch firewall" disabled */ - dev_dbg(&icd->dev, "S_FMT successful for %c%c%c%c %ux%u@%u:%u\n", + dev_dbg(icd->dev.parent, "S_FMT successful for %c%c%c%c %ux%u@%u:%u\n", pixfmt & 0xff, (pixfmt >> 8) & 0xff, (pixfmt >> 16) & 0xff, (pixfmt >> 24) & 0xff, icd->rect_current.width, icd->rect_current.height, @@ -746,7 +746,6 @@ static const struct soc_camera_data_format sh_mobile_ceu_formats[] = { static int sh_mobile_ceu_get_formats(struct soc_camera_device *icd, int idx, struct soc_camera_format_xlate *xlate) { - struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); int ret, k, n; int formats = 0; struct sh_mobile_ceu_cam *cam; @@ -796,7 +795,8 @@ static int sh_mobile_ceu_get_formats(struct soc_camera_device *icd, int idx, xlate->cam_fmt = icd->formats + idx; xlate->buswidth = icd->formats[idx].depth; xlate++; - dev_dbg(ici->v4l2_dev.dev, "Providing format %s using %s\n", + dev_dbg(icd->dev.parent, + "Providing format %s using %s\n", sh_mobile_ceu_formats[k].name, icd->formats[idx].name); } @@ -809,7 +809,7 @@ add_single_format: xlate->cam_fmt = icd->formats + idx; xlate->buswidth = icd->formats[idx].depth; xlate++; - dev_dbg(ici->v4l2_dev.dev, + dev_dbg(icd->dev.parent, "Providing format %s in pass-through mode\n", icd->formats[idx].name); } @@ -872,19 +872,21 @@ static int sh_mobile_ceu_set_crop(struct soc_camera_device *icd, target = *cam_rect; capsr = capture_save_reset(pcdev); - dev_dbg(&icd->dev, "CAPSR 0x%x, CFLCR 0x%x\n", capsr, pcdev->cflcr); + dev_dbg(icd->dev.parent, "CAPSR 0x%x, CFLCR 0x%x\n", + capsr, pcdev->cflcr); /* First attempt - see if the client can deliver a perfect result */ ret = v4l2_subdev_call(sd, video, s_crop, &cam_crop); if (!ret && !memcmp(&target, &cam_rect, sizeof(target))) { - dev_dbg(&icd->dev, "Camera S_CROP successful for %ux%u@%u:%u\n", + dev_dbg(icd->dev.parent, + "Camera S_CROP successful for %ux%u@%u:%u\n", cam_rect->width, cam_rect->height, cam_rect->left, cam_rect->top); goto ceu_set_rect; } /* Try to fix cropping, that camera hasn't managed to do */ - dev_dbg(&icd->dev, "Fix camera S_CROP %d for %ux%u@%u:%u" + dev_dbg(icd->dev.parent, "Fix camera S_CROP %d for %ux%u@%u:%u" " to %ux%u@%u:%u\n", ret, cam_rect->width, cam_rect->height, cam_rect->left, cam_rect->top, @@ -935,7 +937,7 @@ static int sh_mobile_ceu_set_crop(struct soc_camera_device *icd, cam_rect->height, cam_max.top); ret = v4l2_subdev_call(sd, video, s_crop, &cam_crop); - dev_dbg(&icd->dev, "Camera S_CROP %d for %ux%u@%u:%u\n", + dev_dbg(icd->dev.parent, "Camera S_CROP %d for %ux%u@%u:%u\n", ret, cam_rect->width, cam_rect->height, cam_rect->left, cam_rect->top); } @@ -953,7 +955,8 @@ static int sh_mobile_ceu_set_crop(struct soc_camera_device *icd, */ *cam_rect = cam_max; ret = v4l2_subdev_call(sd, video, s_crop, &cam_crop); - dev_dbg(&icd->dev, "Camera S_CROP %d for max %ux%u@%u:%u\n", + dev_dbg(icd->dev.parent, + "Camera S_CROP %d for max %ux%u@%u:%u\n", ret, cam_rect->width, cam_rect->height, cam_rect->left, cam_rect->top); if (ret < 0 && ret != -ENOIOCTLCMD) @@ -981,7 +984,7 @@ static int sh_mobile_ceu_set_crop(struct soc_camera_device *icd, * last before last close() _user_ rectangle, which can be different * from camera rectangle. */ - dev_dbg(&icd->dev, + dev_dbg(icd->dev.parent, "SH S_CROP from %ux%u@%u:%u to %ux%u@%u:%u, scale to %ux%u@%u:%u\n", cam_rect->width, cam_rect->height, cam_rect->left, cam_rect->top, target.width, target.height, target.left, target.top, @@ -1039,14 +1042,15 @@ static int sh_mobile_ceu_set_fmt(struct soc_camera_device *icd, xlate = soc_camera_xlate_by_fourcc(icd, pixfmt); if (!xlate) { - dev_warn(ici->v4l2_dev.dev, "Format %x not found\n", pixfmt); + dev_warn(icd->dev.parent, "Format %x not found\n", pixfmt); return -EINVAL; } pix->pixelformat = xlate->cam_fmt->fourcc; ret = v4l2_subdev_call(sd, video, s_fmt, f); pix->pixelformat = pixfmt; - dev_dbg(&icd->dev, "Camera %d fmt %ux%u, requested %ux%u, max %ux%u\n", + dev_dbg(icd->dev.parent, + "Camera %d fmt %ux%u, requested %ux%u, max %ux%u\n", ret, pix->width, pix->height, width, height, icd->rect_max.width, icd->rect_max.height); if (ret < 0) @@ -1086,12 +1090,12 @@ static int sh_mobile_ceu_set_fmt(struct soc_camera_device *icd, pix->pixelformat = xlate->cam_fmt->fourcc; ret = v4l2_subdev_call(sd, video, s_fmt, f); pix->pixelformat = pixfmt; - dev_dbg(&icd->dev, "Camera scaled to %ux%u\n", + dev_dbg(icd->dev.parent, "Camera scaled to %ux%u\n", pix->width, pix->height); if (ret < 0) { /* This shouldn't happen */ - dev_err(&icd->dev, "Client failed to set format: %d\n", - ret); + dev_err(icd->dev.parent, + "Client failed to set format: %d\n", ret); return ret; } } @@ -1107,7 +1111,7 @@ static int sh_mobile_ceu_set_fmt(struct soc_camera_device *icd, hscale = calc_scale(pix->width, &width); vscale = calc_scale(pix->height, &height); - dev_dbg(&icd->dev, "W: %u : 0x%x = %u, H: %u : 0x%x = %u\n", + dev_dbg(icd->dev.parent, "W: %u : 0x%x = %u, H: %u : 0x%x = %u\n", pix->width, hscale, width, pix->height, vscale, height); out: @@ -1138,7 +1142,6 @@ out: static int sh_mobile_ceu_try_fmt(struct soc_camera_device *icd, struct v4l2_format *f) { - struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); const struct soc_camera_format_xlate *xlate; struct v4l2_pix_format *pix = &f->fmt.pix; struct v4l2_subdev *sd = soc_camera_to_subdev(icd); @@ -1148,7 +1151,7 @@ static int sh_mobile_ceu_try_fmt(struct soc_camera_device *icd, xlate = soc_camera_xlate_by_fourcc(icd, pixfmt); if (!xlate) { - dev_warn(ici->v4l2_dev.dev, "Format %x not found\n", pixfmt); + dev_warn(icd->dev.parent, "Format %x not found\n", pixfmt); return -EINVAL; } @@ -1186,7 +1189,7 @@ static int sh_mobile_ceu_try_fmt(struct soc_camera_device *icd, ret = v4l2_subdev_call(sd, video, try_fmt, f); if (ret < 0) { /* Shouldn't actually happen... */ - dev_err(&icd->dev, + dev_err(icd->dev.parent, "FIXME: try_fmt() returned %d\n", ret); pix->width = tmp_w; pix->height = tmp_h; @@ -1255,7 +1258,7 @@ static void sh_mobile_ceu_init_videobuf(struct videobuf_queue *q, videobuf_queue_dma_contig_init(q, &sh_mobile_ceu_videobuf_ops, - ici->v4l2_dev.dev, &pcdev->lock, + icd->dev.parent, &pcdev->lock, V4L2_BUF_TYPE_VIDEO_CAPTURE, pcdev->is_interlaced ? V4L2_FIELD_INTERLACED : V4L2_FIELD_NONE, -- cgit v1.2.3 From 30e8a71f69f2769f966054f168e9e4ced8a1d091 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Tue, 25 Aug 2009 16:50:46 +0200 Subject: soc-camera: V4L2 API compliant scaling (S_FMT) and cropping (S_CROP) From: Guennadi Liakhovetski The initial soc-camera scaling and cropping implementation turned out to be incompliant with the V4L2 API, e.g., it expected the user to specify cropping in output window pixels, instead of input window pixels. This patch converts the soc-camera core and all drivers to comply with the standard. Signed-off-by: Guennadi Liakhovetski Priority: low --- linux/drivers/media/video/mt9m001.c | 142 +++- linux/drivers/media/video/mt9m111.c | 112 ++- linux/drivers/media/video/mt9t031.c | 220 +++--- linux/drivers/media/video/mt9v022.c | 131 +++- linux/drivers/media/video/mx1_camera.c | 10 +- linux/drivers/media/video/mx3_camera.c | 114 +++- linux/drivers/media/video/ov772x.c | 84 ++- linux/drivers/media/video/pxa_camera.c | 201 ++++-- linux/drivers/media/video/sh_mobile_ceu_camera.c | 828 ++++++++++++++++------- linux/drivers/media/video/soc_camera.c | 130 ++-- linux/drivers/media/video/soc_camera_platform.c | 4 - linux/drivers/media/video/tw9910.c | 120 +++- 12 files changed, 1465 insertions(+), 631 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/mt9m001.c b/linux/drivers/media/video/mt9m001.c index d4ebab8c2..3fcf57118 100644 --- a/linux/drivers/media/video/mt9m001.c +++ b/linux/drivers/media/video/mt9m001.c @@ -39,6 +39,13 @@ #define MT9M001_GLOBAL_GAIN 0x35 #define MT9M001_CHIP_ENABLE 0xF1 +#define MT9M001_MAX_WIDTH 1280 +#define MT9M001_MAX_HEIGHT 1024 +#define MT9M001_MIN_WIDTH 48 +#define MT9M001_MIN_HEIGHT 32 +#define MT9M001_COLUMN_SKIP 20 +#define MT9M001_ROW_SKIP 12 + static const struct soc_camera_data_format mt9m001_colour_formats[] = { /* Order important: first natively supported, * second supported with a GPIO extender */ @@ -70,6 +77,8 @@ static const struct soc_camera_data_format mt9m001_monochrome_formats[] = { struct mt9m001 { struct v4l2_subdev subdev; + struct v4l2_rect rect; /* Sensor window */ + __u32 fourcc; int model; /* V4L2_IDENT_MT9M001* codes from v4l2-chip-ident.h */ unsigned char autoexposure; }; @@ -196,13 +205,31 @@ static unsigned long mt9m001_query_bus_param(struct soc_camera_device *icd) static int mt9m001_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) { - struct v4l2_rect *rect = &a->c; struct i2c_client *client = sd->priv; struct mt9m001 *mt9m001 = to_mt9m001(client); + struct v4l2_rect rect = a->c; struct soc_camera_device *icd = client->dev.platform_data; int ret; const u16 hblank = 9, vblank = 25; + if (mt9m001->fourcc == V4L2_PIX_FMT_SBGGR8 || + mt9m001->fourcc == V4L2_PIX_FMT_SBGGR16) + /* + * Bayer format - even number of rows for simplicity, + * but let the user play with the top row. + */ + rect.height = ALIGN(rect.height, 2); + + /* Datasheet requirement: see register description */ + rect.width = ALIGN(rect.width, 2); + rect.left = ALIGN(rect.left, 2); + + soc_camera_limit_side(&rect.left, &rect.width, + MT9M001_COLUMN_SKIP, MT9M001_MIN_WIDTH, MT9M001_MAX_WIDTH); + + soc_camera_limit_side(&rect.top, &rect.height, + MT9M001_ROW_SKIP, MT9M001_MIN_HEIGHT, MT9M001_MAX_HEIGHT); + /* Blanking and start values - default... */ ret = reg_write(client, MT9M001_HORIZONTAL_BLANKING, hblank); if (!ret) @@ -211,46 +238,98 @@ static int mt9m001_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) /* The caller provides a supported format, as verified per * call to icd->try_fmt() */ if (!ret) - ret = reg_write(client, MT9M001_COLUMN_START, rect->left); + ret = reg_write(client, MT9M001_COLUMN_START, rect.left); if (!ret) - ret = reg_write(client, MT9M001_ROW_START, rect->top); + ret = reg_write(client, MT9M001_ROW_START, rect.top); if (!ret) - ret = reg_write(client, MT9M001_WINDOW_WIDTH, rect->width - 1); + ret = reg_write(client, MT9M001_WINDOW_WIDTH, rect.width - 1); if (!ret) ret = reg_write(client, MT9M001_WINDOW_HEIGHT, - rect->height + icd->y_skip_top - 1); + rect.height + icd->y_skip_top - 1); if (!ret && mt9m001->autoexposure) { ret = reg_write(client, MT9M001_SHUTTER_WIDTH, - rect->height + icd->y_skip_top + vblank); + rect.height + icd->y_skip_top + vblank); if (!ret) { const struct v4l2_queryctrl *qctrl = soc_camera_find_qctrl(icd->ops, V4L2_CID_EXPOSURE); - icd->exposure = (524 + (rect->height + icd->y_skip_top + + icd->exposure = (524 + (rect.height + icd->y_skip_top + vblank - 1) * (qctrl->maximum - qctrl->minimum)) / 1048 + qctrl->minimum; } } + if (!ret) + mt9m001->rect = rect; + return ret; } +static int mt9m001_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) +{ + struct i2c_client *client = sd->priv; + struct mt9m001 *mt9m001 = to_mt9m001(client); + + a->c = mt9m001->rect; + a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + + return 0; +} + +static int mt9m001_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a) +{ + a->bounds.left = MT9M001_COLUMN_SKIP; + a->bounds.top = MT9M001_ROW_SKIP; + a->bounds.width = MT9M001_MAX_WIDTH; + a->bounds.height = MT9M001_MAX_HEIGHT; + a->defrect = a->bounds; + a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + a->pixelaspect.numerator = 1; + a->pixelaspect.denominator = 1; + + return 0; +} + +static int mt9m001_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) +{ + struct i2c_client *client = sd->priv; + struct mt9m001 *mt9m001 = to_mt9m001(client); + struct v4l2_pix_format *pix = &f->fmt.pix; + + pix->width = mt9m001->rect.width; + pix->height = mt9m001->rect.height; + pix->pixelformat = mt9m001->fourcc; + pix->field = V4L2_FIELD_NONE; + pix->colorspace = V4L2_COLORSPACE_SRGB; + + return 0; +} + static int mt9m001_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) { struct i2c_client *client = sd->priv; - struct soc_camera_device *icd = client->dev.platform_data; + struct mt9m001 *mt9m001 = to_mt9m001(client); + struct v4l2_pix_format *pix = &f->fmt.pix; struct v4l2_crop a = { .c = { - .left = icd->rect_current.left, - .top = icd->rect_current.top, - .width = f->fmt.pix.width, - .height = f->fmt.pix.height, + .left = mt9m001->rect.left, + .top = mt9m001->rect.top, + .width = pix->width, + .height = pix->height, }, }; + int ret; /* No support for scaling so far, just crop. TODO: use skipping */ - return mt9m001_s_crop(sd, &a); + ret = mt9m001_s_crop(sd, &a); + if (!ret) { + pix->width = mt9m001->rect.width; + pix->height = mt9m001->rect.height; + mt9m001->fourcc = pix->pixelformat; + } + + return ret; } static int mt9m001_try_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) @@ -259,9 +338,14 @@ static int mt9m001_try_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) struct soc_camera_device *icd = client->dev.platform_data; struct v4l2_pix_format *pix = &f->fmt.pix; - v4l_bound_align_image(&pix->width, 48, 1280, 1, - &pix->height, 32 + icd->y_skip_top, - 1024 + icd->y_skip_top, 0, 0); + v4l_bound_align_image(&pix->width, MT9M001_MIN_WIDTH, + MT9M001_MAX_WIDTH, 1, + &pix->height, MT9M001_MIN_HEIGHT + icd->y_skip_top, + MT9M001_MAX_HEIGHT + icd->y_skip_top, 0, 0); + + if (pix->pixelformat == V4L2_PIX_FMT_SBGGR8 || + pix->pixelformat == V4L2_PIX_FMT_SBGGR16) + pix->height = ALIGN(pix->height - 1, 2); return 0; } @@ -472,11 +556,11 @@ static int mt9m001_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) if (ctrl->value) { const u16 vblank = 25; if (reg_write(client, MT9M001_SHUTTER_WIDTH, - icd->rect_current.height + + mt9m001->rect.height + icd->y_skip_top + vblank) < 0) return -EIO; qctrl = soc_camera_find_qctrl(icd->ops, V4L2_CID_EXPOSURE); - icd->exposure = (524 + (icd->rect_current.height + + icd->exposure = (524 + (mt9m001->rect.height + icd->y_skip_top + vblank - 1) * (qctrl->maximum - qctrl->minimum)) / 1048 + qctrl->minimum; @@ -548,6 +632,8 @@ static int mt9m001_video_probe(struct soc_camera_device *icd, if (flags & SOCAM_DATAWIDTH_8) icd->num_formats++; + mt9m001->fourcc = icd->formats->fourcc; + dev_info(&client->dev, "Detected a MT9M001 chip ID %x (%s)\n", data, data == 0x8431 ? "C12STM" : "C12ST"); @@ -556,10 +642,9 @@ static int mt9m001_video_probe(struct soc_camera_device *icd, static void mt9m001_video_remove(struct soc_camera_device *icd) { - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); struct soc_camera_link *icl = to_soc_camera_link(icd); - dev_dbg(&client->dev, "Video %x removed: %p, %p\n", client->addr, + dev_dbg(&icd->dev, "Video removed: %p, %p\n", icd->dev.parent, icd->vdev); if (icl->free_bus) icl->free_bus(icl); @@ -578,8 +663,11 @@ static struct v4l2_subdev_core_ops mt9m001_subdev_core_ops = { static struct v4l2_subdev_video_ops mt9m001_subdev_video_ops = { .s_stream = mt9m001_s_stream, .s_fmt = mt9m001_s_fmt, + .g_fmt = mt9m001_g_fmt, .try_fmt = mt9m001_try_fmt, .s_crop = mt9m001_s_crop, + .g_crop = mt9m001_g_crop, + .cropcap = mt9m001_cropcap, }; static struct v4l2_subdev_ops mt9m001_subdev_ops = { @@ -625,15 +713,13 @@ static int mt9m001_probe(struct i2c_client *client) /* Second stage probe - when a capture adapter is there */ icd->ops = &mt9m001_ops; - icd->rect_max.left = 20; - icd->rect_max.top = 12; - icd->rect_max.width = 1280; - icd->rect_max.height = 1024; - icd->rect_current.left = 20; - icd->rect_current.top = 12; - icd->width_min = 48; - icd->height_min = 32; icd->y_skip_top = 1; + + mt9m001->rect.left = MT9M001_COLUMN_SKIP; + mt9m001->rect.top = MT9M001_ROW_SKIP; + mt9m001->rect.width = MT9M001_MAX_WIDTH; + mt9m001->rect.height = MT9M001_MAX_HEIGHT; + /* Simulated autoexposure. If enabled, we calculate shutter width * ourselves in the driver based on vertical blanking and frame width */ mt9m001->autoexposure = 1; diff --git a/linux/drivers/media/video/mt9m111.c b/linux/drivers/media/video/mt9m111.c index 44e565faf..905054e08 100644 --- a/linux/drivers/media/video/mt9m111.c +++ b/linux/drivers/media/video/mt9m111.c @@ -194,7 +194,7 @@ static int mt9m111_reg_read(struct i2c_client *client, const u16 reg) ret = reg_page_map_set(client, reg); if (!ret) - ret = swab16(i2c_smbus_read_word_data(client, (reg & 0xff))); + ret = swab16(i2c_smbus_read_word_data(client, reg & 0xff)); dev_dbg(&client->dev, "read reg.%03x -> %04x\n", reg, ret); return ret; @@ -257,8 +257,8 @@ static int mt9m111_setup_rect(struct i2c_client *client, int width = rect->width; int height = rect->height; - if ((mt9m111->pixfmt == V4L2_PIX_FMT_SBGGR8) - || (mt9m111->pixfmt == V4L2_PIX_FMT_SBGGR16)) + if (mt9m111->pixfmt == V4L2_PIX_FMT_SBGGR8 || + mt9m111->pixfmt == V4L2_PIX_FMT_SBGGR16) is_raw_format = 1; else is_raw_format = 0; @@ -395,23 +395,85 @@ static int mt9m111_set_bus_param(struct soc_camera_device *icd, unsigned long f) return 0; } +static int mt9m111_make_rect(struct i2c_client *client, + struct v4l2_rect *rect) +{ + struct mt9m111 *mt9m111 = to_mt9m111(client); + + if (mt9m111->pixfmt == V4L2_PIX_FMT_SBGGR8 || + mt9m111->pixfmt == V4L2_PIX_FMT_SBGGR16) { + /* Bayer format - even size lengths */ + rect->width = ALIGN(rect->width, 2); + rect->height = ALIGN(rect->height, 2); + /* Let the user play with the starting pixel */ + } + + /* FIXME: the datasheet doesn't specify minimum sizes */ + soc_camera_limit_side(&rect->left, &rect->width, + MT9M111_MIN_DARK_COLS, 2, MT9M111_MAX_WIDTH); + + soc_camera_limit_side(&rect->top, &rect->height, + MT9M111_MIN_DARK_ROWS, 2, MT9M111_MAX_HEIGHT); + + return mt9m111_setup_rect(client, rect); +} + static int mt9m111_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) { - struct v4l2_rect *rect = &a->c; + struct v4l2_rect rect = a->c; struct i2c_client *client = sd->priv; struct mt9m111 *mt9m111 = to_mt9m111(client); int ret; dev_dbg(&client->dev, "%s left=%d, top=%d, width=%d, height=%d\n", - __func__, rect->left, rect->top, rect->width, - rect->height); + __func__, rect.left, rect.top, rect.width, rect.height); - ret = mt9m111_setup_rect(client, rect); + ret = mt9m111_make_rect(client, &rect); if (!ret) - mt9m111->rect = *rect; + mt9m111->rect = rect; return ret; } +static int mt9m111_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) +{ + struct i2c_client *client = sd->priv; + struct mt9m111 *mt9m111 = to_mt9m111(client); + + a->c = mt9m111->rect; + a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + + return 0; +} + +static int mt9m111_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a) +{ + a->bounds.left = MT9M111_MIN_DARK_COLS; + a->bounds.top = MT9M111_MIN_DARK_ROWS; + a->bounds.width = MT9M111_MAX_WIDTH; + a->bounds.height = MT9M111_MAX_HEIGHT; + a->defrect = a->bounds; + a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + a->pixelaspect.numerator = 1; + a->pixelaspect.denominator = 1; + + return 0; +} + +static int mt9m111_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) +{ + struct i2c_client *client = sd->priv; + struct mt9m111 *mt9m111 = to_mt9m111(client); + struct v4l2_pix_format *pix = &f->fmt.pix; + + pix->width = mt9m111->rect.width; + pix->height = mt9m111->rect.height; + pix->pixelformat = mt9m111->pixfmt; + pix->field = V4L2_FIELD_NONE; + pix->colorspace = V4L2_COLORSPACE_SRGB; + + return 0; +} + static int mt9m111_set_pixfmt(struct i2c_client *client, u32 pixfmt) { struct mt9m111 *mt9m111 = to_mt9m111(client); @@ -478,7 +540,7 @@ static int mt9m111_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) __func__, pix->pixelformat, rect.left, rect.top, rect.width, rect.height); - ret = mt9m111_setup_rect(client, &rect); + ret = mt9m111_make_rect(client, &rect); if (!ret) ret = mt9m111_set_pixfmt(client, pix->pixelformat); if (!ret) @@ -489,11 +551,27 @@ static int mt9m111_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) static int mt9m111_try_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) { struct v4l2_pix_format *pix = &f->fmt.pix; + bool bayer = pix->pixelformat == V4L2_PIX_FMT_SBGGR8 || + pix->pixelformat == V4L2_PIX_FMT_SBGGR16; + + /* + * With Bayer format enforce even side lengths, but let the user play + * with the starting pixel + */ if (pix->height > MT9M111_MAX_HEIGHT) pix->height = MT9M111_MAX_HEIGHT; + else if (pix->height < 2) + pix->height = 2; + else if (bayer) + pix->height = ALIGN(pix->height, 2); + if (pix->width > MT9M111_MAX_WIDTH) pix->width = MT9M111_MAX_WIDTH; + else if (pix->width < 2) + pix->width = 2; + else if (bayer) + pix->width = ALIGN(pix->width, 2); return 0; } @@ -906,8 +984,11 @@ static struct v4l2_subdev_core_ops mt9m111_subdev_core_ops = { static struct v4l2_subdev_video_ops mt9m111_subdev_video_ops = { .s_fmt = mt9m111_s_fmt, + .g_fmt = mt9m111_g_fmt, .try_fmt = mt9m111_try_fmt, .s_crop = mt9m111_s_crop, + .g_crop = mt9m111_g_crop, + .cropcap = mt9m111_cropcap, }; static struct v4l2_subdev_ops mt9m111_subdev_ops = { @@ -953,16 +1034,13 @@ static int mt9m111_probe(struct i2c_client *client, /* Second stage probe - when a capture adapter is there */ icd->ops = &mt9m111_ops; - icd->rect_max.left = MT9M111_MIN_DARK_COLS; - icd->rect_max.top = MT9M111_MIN_DARK_ROWS; - icd->rect_max.width = MT9M111_MAX_WIDTH; - icd->rect_max.height = MT9M111_MAX_HEIGHT; - icd->rect_current.left = icd->rect_max.left; - icd->rect_current.top = icd->rect_max.top; - icd->width_min = MT9M111_MIN_DARK_ROWS; - icd->height_min = MT9M111_MIN_DARK_COLS; icd->y_skip_top = 0; + mt9m111->rect.left = MT9M111_MIN_DARK_COLS; + mt9m111->rect.top = MT9M111_MIN_DARK_ROWS; + mt9m111->rect.width = MT9M111_MAX_WIDTH; + mt9m111->rect.height = MT9M111_MAX_HEIGHT; + ret = mt9m111_video_probe(icd, client); if (ret) { icd->ops = NULL; diff --git a/linux/drivers/media/video/mt9t031.c b/linux/drivers/media/video/mt9t031.c index 00877b4ae..30d4aaf81 100644 --- a/linux/drivers/media/video/mt9t031.c +++ b/linux/drivers/media/video/mt9t031.c @@ -47,7 +47,7 @@ #define MT9T031_MAX_HEIGHT 1536 #define MT9T031_MAX_WIDTH 2048 #define MT9T031_MIN_HEIGHT 2 -#define MT9T031_MIN_WIDTH 2 +#define MT9T031_MIN_WIDTH 18 #define MT9T031_HORIZONTAL_BLANK 142 #define MT9T031_VERTICAL_BLANK 25 #define MT9T031_COLUMN_SKIP 32 @@ -69,10 +69,11 @@ static const struct soc_camera_data_format mt9t031_colour_formats[] = { struct mt9t031 { struct v4l2_subdev subdev; + struct v4l2_rect rect; /* Sensor window */ int model; /* V4L2_IDENT_MT9T031* codes from v4l2-chip-ident.h */ - unsigned char autoexposure; u16 xskip; u16 yskip; + unsigned char autoexposure; }; static struct mt9t031 *to_mt9t031(const struct i2c_client *client) @@ -218,56 +219,68 @@ static unsigned long mt9t031_query_bus_param(struct soc_camera_device *icd) return soc_camera_apply_sensor_flags(icl, MT9T031_BUS_PARAM); } -/* Round up minima and round down maxima */ -static void recalculate_limits(struct soc_camera_device *icd, - u16 xskip, u16 yskip) +/* target must be _even_ */ +static u16 mt9t031_skip(s32 *source, s32 target, s32 max) { - icd->rect_max.left = (MT9T031_COLUMN_SKIP + xskip - 1) / xskip; - icd->rect_max.top = (MT9T031_ROW_SKIP + yskip - 1) / yskip; - icd->width_min = (MT9T031_MIN_WIDTH + xskip - 1) / xskip; - icd->height_min = (MT9T031_MIN_HEIGHT + yskip - 1) / yskip; - icd->rect_max.width = MT9T031_MAX_WIDTH / xskip; - icd->rect_max.height = MT9T031_MAX_HEIGHT / yskip; + unsigned int skip; + + if (*source < target + target / 2) { + *source = target; + return 1; + } + + skip = min(max, *source + target / 2) / target; + if (skip > 8) + skip = 8; + *source = target * skip; + + return skip; } +/* rect is the sensor rectangle, the caller guarantees parameter validity */ static int mt9t031_set_params(struct soc_camera_device *icd, struct v4l2_rect *rect, u16 xskip, u16 yskip) { struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); struct mt9t031 *mt9t031 = to_mt9t031(client); int ret; - u16 xbin, ybin, width, height, left, top; + u16 xbin, ybin; const u16 hblank = MT9T031_HORIZONTAL_BLANK, vblank = MT9T031_VERTICAL_BLANK; - width = rect->width * xskip; - height = rect->height * yskip; - left = rect->left * xskip; - top = rect->top * yskip; - xbin = min(xskip, (u16)3); ybin = min(yskip, (u16)3); - dev_dbg(&client->dev, "xskip %u, width %u/%u, yskip %u, height %u/%u\n", - xskip, width, rect->width, yskip, height, rect->height); - - /* Could just do roundup(rect->left, [xy]bin * 2); but this is cheaper */ + /* + * Could just do roundup(rect->left, [xy]bin * 2); but this is cheaper. + * There is always a valid suitably aligned value. The worst case is + * xbin = 3, width = 2048. Then we will start at 36, the last read out + * pixel will be 2083, which is < 2085 - first black pixel. + * + * MT9T031 datasheet imposes window left border alignment, depending on + * the selected xskip. Failing to conform to this requirement produces + * dark horizontal stripes in the image. However, even obeying to this + * requirement doesn't eliminate the stripes in all configurations. They + * appear "locally reproducibly," but can differ between tests under + * different lighting conditions. + */ switch (xbin) { - case 2: - left = (left + 3) & ~3; + case 1: + rect->left &= ~1; break; - case 3: - left = roundup(left, 6); - } - - switch (ybin) { case 2: - top = (top + 3) & ~3; + rect->left &= ~3; break; case 3: - top = roundup(top, 6); + rect->left = rect->left > roundup(MT9T031_COLUMN_SKIP, 6) ? + (rect->left / 6) * 6 : roundup(MT9T031_COLUMN_SKIP, 6); } + rect->top &= ~1; + + dev_dbg(&client->dev, "skip %u:%u, rect %ux%u@%u:%u\n", + xskip, yskip, rect->width, rect->height, rect->left, rect->top); + /* Disable register update, reconfigure atomically */ ret = reg_set(client, MT9T031_OUTPUT_CONTROL, 1); if (ret < 0) @@ -287,27 +300,29 @@ static int mt9t031_set_params(struct soc_camera_device *icd, ret = reg_write(client, MT9T031_ROW_ADDRESS_MODE, ((ybin - 1) << 4) | (yskip - 1)); } - dev_dbg(&client->dev, "new physical left %u, top %u\n", left, top); + dev_dbg(&client->dev, "new physical left %u, top %u\n", + rect->left, rect->top); /* The caller provides a supported format, as guaranteed by * icd->try_fmt_cap(), soc_camera_s_crop() and soc_camera_cropcap() */ if (ret >= 0) - ret = reg_write(client, MT9T031_COLUMN_START, left); + ret = reg_write(client, MT9T031_COLUMN_START, rect->left); if (ret >= 0) - ret = reg_write(client, MT9T031_ROW_START, top); + ret = reg_write(client, MT9T031_ROW_START, rect->top); if (ret >= 0) - ret = reg_write(client, MT9T031_WINDOW_WIDTH, width - 1); + ret = reg_write(client, MT9T031_WINDOW_WIDTH, rect->width - 1); if (ret >= 0) ret = reg_write(client, MT9T031_WINDOW_HEIGHT, - height + icd->y_skip_top - 1); + rect->height + icd->y_skip_top - 1); if (ret >= 0 && mt9t031->autoexposure) { - ret = set_shutter(client, height + icd->y_skip_top + vblank); + ret = set_shutter(client, + rect->height + icd->y_skip_top + vblank); if (ret >= 0) { const u32 shutter_max = MT9T031_MAX_HEIGHT + vblank; const struct v4l2_queryctrl *qctrl = soc_camera_find_qctrl(icd->ops, V4L2_CID_EXPOSURE); - icd->exposure = (shutter_max / 2 + (height + + icd->exposure = (shutter_max / 2 + (rect->height + icd->y_skip_top + vblank - 1) * (qctrl->maximum - qctrl->minimum)) / shutter_max + qctrl->minimum; @@ -318,27 +333,72 @@ static int mt9t031_set_params(struct soc_camera_device *icd, if (ret >= 0) ret = reg_clear(client, MT9T031_OUTPUT_CONTROL, 1); + if (ret >= 0) { + mt9t031->rect = *rect; + mt9t031->xskip = xskip; + mt9t031->yskip = yskip; + } + return ret < 0 ? ret : 0; } static int mt9t031_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) { - struct v4l2_rect *rect = &a->c; + struct v4l2_rect rect = a->c; struct i2c_client *client = sd->priv; struct mt9t031 *mt9t031 = to_mt9t031(client); struct soc_camera_device *icd = client->dev.platform_data; - /* Make sure we don't exceed sensor limits */ - if (rect->left + rect->width > icd->rect_max.left + icd->rect_max.width) - rect->left = icd->rect_max.width + icd->rect_max.left - - rect->width; + rect.width = ALIGN(rect.width, 2); + rect.height = ALIGN(rect.height, 2); + + soc_camera_limit_side(&rect.left, &rect.width, + MT9T031_COLUMN_SKIP, MT9T031_MIN_WIDTH, MT9T031_MAX_WIDTH); + + soc_camera_limit_side(&rect.top, &rect.height, + MT9T031_ROW_SKIP, MT9T031_MIN_HEIGHT, MT9T031_MAX_HEIGHT); + + return mt9t031_set_params(icd, &rect, mt9t031->xskip, mt9t031->yskip); +} + +static int mt9t031_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) +{ + struct i2c_client *client = sd->priv; + struct mt9t031 *mt9t031 = to_mt9t031(client); + + a->c = mt9t031->rect; + a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - if (rect->top + rect->height > icd->rect_max.height + icd->rect_max.top) - rect->top = icd->rect_max.height + icd->rect_max.top - - rect->height; + return 0; +} + +static int mt9t031_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a) +{ + a->bounds.left = MT9T031_COLUMN_SKIP; + a->bounds.top = MT9T031_ROW_SKIP; + a->bounds.width = MT9T031_MAX_WIDTH; + a->bounds.height = MT9T031_MAX_HEIGHT; + a->defrect = a->bounds; + a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + a->pixelaspect.numerator = 1; + a->pixelaspect.denominator = 1; - /* CROP - no change in scaling, or in limits */ - return mt9t031_set_params(icd, rect, mt9t031->xskip, mt9t031->yskip); + return 0; +} + +static int mt9t031_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) +{ + struct i2c_client *client = sd->priv; + struct mt9t031 *mt9t031 = to_mt9t031(client); + struct v4l2_pix_format *pix = &f->fmt.pix; + + pix->width = mt9t031->rect.width / mt9t031->xskip; + pix->height = mt9t031->rect.height / mt9t031->yskip; + pix->pixelformat = V4L2_PIX_FMT_SGRBG10; + pix->field = V4L2_FIELD_NONE; + pix->colorspace = V4L2_COLORSPACE_SRGB; + + return 0; } static int mt9t031_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) @@ -346,40 +406,25 @@ static int mt9t031_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) struct i2c_client *client = sd->priv; struct mt9t031 *mt9t031 = to_mt9t031(client); struct soc_camera_device *icd = client->dev.platform_data; - int ret; + struct v4l2_pix_format *pix = &f->fmt.pix; u16 xskip, yskip; - struct v4l2_rect rect = { - .left = icd->rect_current.left, - .top = icd->rect_current.top, - .width = f->fmt.pix.width, - .height = f->fmt.pix.height, - }; + struct v4l2_rect rect = mt9t031->rect; /* - * try_fmt has put rectangle within limits. - * S_FMT - use binning and skipping for scaling, recalculate - * limits, used for cropping + * try_fmt has put width and height within limits. + * S_FMT: use binning and skipping for scaling */ - /* Is this more optimal than just a division? */ - for (xskip = 8; xskip > 1; xskip--) - if (rect.width * xskip <= MT9T031_MAX_WIDTH) - break; - - for (yskip = 8; yskip > 1; yskip--) - if (rect.height * yskip <= MT9T031_MAX_HEIGHT) - break; - - recalculate_limits(icd, xskip, yskip); - - ret = mt9t031_set_params(icd, &rect, xskip, yskip); - if (!ret) { - mt9t031->xskip = xskip; - mt9t031->yskip = yskip; - } + xskip = mt9t031_skip(&rect.width, pix->width, MT9T031_MAX_WIDTH); + yskip = mt9t031_skip(&rect.height, pix->height, MT9T031_MAX_HEIGHT); - return ret; + /* mt9t031_set_params() doesn't change width and height */ + return mt9t031_set_params(icd, &rect, xskip, yskip); } +/* + * If a user window larger than sensor window is requested, we'll increase the + * sensor window. + */ static int mt9t031_try_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) { struct v4l2_pix_format *pix = &f->fmt.pix; @@ -620,12 +665,12 @@ static int mt9t031_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) if (ctrl->value) { const u16 vblank = MT9T031_VERTICAL_BLANK; const u32 shutter_max = MT9T031_MAX_HEIGHT + vblank; - if (set_shutter(client, icd->rect_current.height + + if (set_shutter(client, mt9t031->rect.height + icd->y_skip_top + vblank) < 0) return -EIO; qctrl = soc_camera_find_qctrl(icd->ops, V4L2_CID_EXPOSURE); icd->exposure = (shutter_max / 2 + - (icd->rect_current.height + + (mt9t031->rect.height + icd->y_skip_top + vblank - 1) * (qctrl->maximum - qctrl->minimum)) / shutter_max + qctrl->minimum; @@ -645,12 +690,6 @@ static int mt9t031_video_probe(struct i2c_client *client) struct mt9t031 *mt9t031 = to_mt9t031(client); s32 data; - /* We must have a parent by now. And it cannot be a wrong one. - * So this entire test is completely redundant. */ - if (!icd->dev.parent || - to_soc_camera_host(icd->dev.parent)->nr != icd->iface) - return -ENODEV; - /* Enable the chip */ data = reg_write(client, MT9T031_CHIP_ENABLE, 1); dev_dbg(&client->dev, "write: %d\n", data); @@ -688,8 +727,11 @@ static struct v4l2_subdev_core_ops mt9t031_subdev_core_ops = { static struct v4l2_subdev_video_ops mt9t031_subdev_video_ops = { .s_stream = mt9t031_s_stream, .s_fmt = mt9t031_s_fmt, + .g_fmt = mt9t031_g_fmt, .try_fmt = mt9t031_try_fmt, .s_crop = mt9t031_s_crop, + .g_crop = mt9t031_g_crop, + .cropcap = mt9t031_cropcap, }; static struct v4l2_subdev_ops mt9t031_subdev_ops = { @@ -735,15 +777,13 @@ static int mt9t031_probe(struct i2c_client *client, /* Second stage probe - when a capture adapter is there */ icd->ops = &mt9t031_ops; - icd->rect_max.left = MT9T031_COLUMN_SKIP; - icd->rect_max.top = MT9T031_ROW_SKIP; - icd->rect_current.left = icd->rect_max.left; - icd->rect_current.top = icd->rect_max.top; - icd->width_min = MT9T031_MIN_WIDTH; - icd->rect_max.width = MT9T031_MAX_WIDTH; - icd->height_min = MT9T031_MIN_HEIGHT; - icd->rect_max.height = MT9T031_MAX_HEIGHT; icd->y_skip_top = 0; + + mt9t031->rect.left = MT9T031_COLUMN_SKIP; + mt9t031->rect.top = MT9T031_ROW_SKIP; + mt9t031->rect.width = MT9T031_MAX_WIDTH; + mt9t031->rect.height = MT9T031_MAX_HEIGHT; + /* Simulated autoexposure. If enabled, we calculate shutter width * ourselves in the driver based on vertical blanking and frame width */ mt9t031->autoexposure = 1; diff --git a/linux/drivers/media/video/mt9v022.c b/linux/drivers/media/video/mt9v022.c index fd2d13d6c..3153fd5d2 100644 --- a/linux/drivers/media/video/mt9v022.c +++ b/linux/drivers/media/video/mt9v022.c @@ -55,6 +55,13 @@ MODULE_PARM_DESC(sensor_type, "Sensor type: \"colour\" or \"monochrome\""); /* Progressive scan, master, defaults */ #define MT9V022_CHIP_CONTROL_DEFAULT 0x188 +#define MT9V022_MAX_WIDTH 752 +#define MT9V022_MAX_HEIGHT 480 +#define MT9V022_MIN_WIDTH 48 +#define MT9V022_MIN_HEIGHT 32 +#define MT9V022_COLUMN_SKIP 1 +#define MT9V022_ROW_SKIP 4 + static const struct soc_camera_data_format mt9v022_colour_formats[] = { /* Order important: first natively supported, * second supported with a GPIO extender */ @@ -86,6 +93,8 @@ static const struct soc_camera_data_format mt9v022_monochrome_formats[] = { struct mt9v022 { struct v4l2_subdev subdev; + struct v4l2_rect rect; /* Sensor window */ + __u32 fourcc; int model; /* V4L2_IDENT_MT9V022* codes from v4l2-chip-ident.h */ u16 chip_control; }; @@ -250,44 +259,101 @@ static unsigned long mt9v022_query_bus_param(struct soc_camera_device *icd) static int mt9v022_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) { - struct v4l2_rect *rect = &a->c; struct i2c_client *client = sd->priv; + struct mt9v022 *mt9v022 = to_mt9v022(client); + struct v4l2_rect rect = a->c; struct soc_camera_device *icd = client->dev.platform_data; int ret; + /* Bayer format - even size lengths */ + if (mt9v022->fourcc == V4L2_PIX_FMT_SBGGR8 || + mt9v022->fourcc == V4L2_PIX_FMT_SBGGR16) { + rect.width = ALIGN(rect.width, 2); + rect.height = ALIGN(rect.height, 2); + /* Let the user play with the starting pixel */ + } + + soc_camera_limit_side(&rect.left, &rect.width, + MT9V022_COLUMN_SKIP, MT9V022_MIN_WIDTH, MT9V022_MAX_WIDTH); + + soc_camera_limit_side(&rect.top, &rect.height, + MT9V022_ROW_SKIP, MT9V022_MIN_HEIGHT, MT9V022_MAX_HEIGHT); + /* Like in example app. Contradicts the datasheet though */ ret = reg_read(client, MT9V022_AEC_AGC_ENABLE); if (ret >= 0) { if (ret & 1) /* Autoexposure */ ret = reg_write(client, MT9V022_MAX_TOTAL_SHUTTER_WIDTH, - rect->height + icd->y_skip_top + 43); + rect.height + icd->y_skip_top + 43); else ret = reg_write(client, MT9V022_TOTAL_SHUTTER_WIDTH, - rect->height + icd->y_skip_top + 43); + rect.height + icd->y_skip_top + 43); } /* Setup frame format: defaults apart from width and height */ if (!ret) - ret = reg_write(client, MT9V022_COLUMN_START, rect->left); + ret = reg_write(client, MT9V022_COLUMN_START, rect.left); if (!ret) - ret = reg_write(client, MT9V022_ROW_START, rect->top); + ret = reg_write(client, MT9V022_ROW_START, rect.top); if (!ret) /* Default 94, Phytec driver says: * "width + horizontal blank >= 660" */ ret = reg_write(client, MT9V022_HORIZONTAL_BLANKING, - rect->width > 660 - 43 ? 43 : - 660 - rect->width); + rect.width > 660 - 43 ? 43 : + 660 - rect.width); if (!ret) ret = reg_write(client, MT9V022_VERTICAL_BLANKING, 45); if (!ret) - ret = reg_write(client, MT9V022_WINDOW_WIDTH, rect->width); + ret = reg_write(client, MT9V022_WINDOW_WIDTH, rect.width); if (!ret) ret = reg_write(client, MT9V022_WINDOW_HEIGHT, - rect->height + icd->y_skip_top); + rect.height + icd->y_skip_top); if (ret < 0) return ret; - dev_dbg(&client->dev, "Frame %ux%u pixel\n", rect->width, rect->height); + dev_dbg(&client->dev, "Frame %ux%u pixel\n", rect.width, rect.height); + + mt9v022->rect = rect; + + return 0; +} + +static int mt9v022_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) +{ + struct i2c_client *client = sd->priv; + struct mt9v022 *mt9v022 = to_mt9v022(client); + + a->c = mt9v022->rect; + a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + + return 0; +} + +static int mt9v022_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a) +{ + a->bounds.left = MT9V022_COLUMN_SKIP; + a->bounds.top = MT9V022_ROW_SKIP; + a->bounds.width = MT9V022_MAX_WIDTH; + a->bounds.height = MT9V022_MAX_HEIGHT; + a->defrect = a->bounds; + a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + a->pixelaspect.numerator = 1; + a->pixelaspect.denominator = 1; + + return 0; +} + +static int mt9v022_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) +{ + struct i2c_client *client = sd->priv; + struct mt9v022 *mt9v022 = to_mt9v022(client); + struct v4l2_pix_format *pix = &f->fmt.pix; + + pix->width = mt9v022->rect.width; + pix->height = mt9v022->rect.height; + pix->pixelformat = mt9v022->fourcc; + pix->field = V4L2_FIELD_NONE; + pix->colorspace = V4L2_COLORSPACE_SRGB; return 0; } @@ -296,16 +362,16 @@ static int mt9v022_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) { struct i2c_client *client = sd->priv; struct mt9v022 *mt9v022 = to_mt9v022(client); - struct soc_camera_device *icd = client->dev.platform_data; struct v4l2_pix_format *pix = &f->fmt.pix; struct v4l2_crop a = { .c = { - .left = icd->rect_current.left, - .top = icd->rect_current.top, + .left = mt9v022->rect.left, + .top = mt9v022->rect.top, .width = pix->width, .height = pix->height, }, }; + int ret; /* The caller provides a supported format, as verified per call to * icd->try_fmt(), datawidth is from our supported format list */ @@ -328,7 +394,14 @@ static int mt9v022_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) } /* No support for scaling on this camera, just crop. */ - return mt9v022_s_crop(sd, &a); + ret = mt9v022_s_crop(sd, &a); + if (!ret) { + pix->width = mt9v022->rect.width; + pix->height = mt9v022->rect.height; + mt9v022->fourcc = pix->pixelformat; + } + + return ret; } static int mt9v022_try_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) @@ -336,10 +409,13 @@ static int mt9v022_try_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) struct i2c_client *client = sd->priv; struct soc_camera_device *icd = client->dev.platform_data; struct v4l2_pix_format *pix = &f->fmt.pix; + int align = pix->pixelformat == V4L2_PIX_FMT_SBGGR8 || + pix->pixelformat == V4L2_PIX_FMT_SBGGR16; - v4l_bound_align_image(&pix->width, 48, 752, 2 /* ? */, - &pix->height, 32 + icd->y_skip_top, - 480 + icd->y_skip_top, 0, 0); + v4l_bound_align_image(&pix->width, MT9V022_MIN_WIDTH, + MT9V022_MAX_WIDTH, align, + &pix->height, MT9V022_MIN_HEIGHT + icd->y_skip_top, + MT9V022_MAX_HEIGHT + icd->y_skip_top, align, 0); return 0; } @@ -669,6 +745,8 @@ static int mt9v022_video_probe(struct soc_camera_device *icd, if (flags & SOCAM_DATAWIDTH_8) icd->num_formats++; + mt9v022->fourcc = icd->formats->fourcc; + dev_info(&client->dev, "Detected a MT9V022 chip ID %x, %s sensor\n", data, mt9v022->model == V4L2_IDENT_MT9V022IX7ATM ? "monochrome" : "colour"); @@ -679,10 +757,9 @@ ei2c: static void mt9v022_video_remove(struct soc_camera_device *icd) { - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); struct soc_camera_link *icl = to_soc_camera_link(icd); - dev_dbg(&client->dev, "Video %x removed: %p, %p\n", client->addr, + dev_dbg(&icd->dev, "Video removed: %p, %p\n", icd->dev.parent, icd->vdev); if (icl->free_bus) icl->free_bus(icl); @@ -701,8 +778,11 @@ static struct v4l2_subdev_core_ops mt9v022_subdev_core_ops = { static struct v4l2_subdev_video_ops mt9v022_subdev_video_ops = { .s_stream = mt9v022_s_stream, .s_fmt = mt9v022_s_fmt, + .g_fmt = mt9v022_g_fmt, .try_fmt = mt9v022_try_fmt, .s_crop = mt9v022_s_crop, + .g_crop = mt9v022_g_crop, + .cropcap = mt9v022_cropcap, }; static struct v4l2_subdev_ops mt9v022_subdev_ops = { @@ -749,16 +829,13 @@ static int mt9v022_probe(struct i2c_client *client) mt9v022->chip_control = MT9V022_CHIP_CONTROL_DEFAULT; icd->ops = &mt9v022_ops; - icd->rect_max.left = 1; - icd->rect_max.top = 4; - icd->rect_max.width = 752; - icd->rect_max.height = 480; - icd->rect_current.left = 1; - icd->rect_current.top = 4; - icd->width_min = 48; - icd->height_min = 32; icd->y_skip_top = 1; + mt9v022->rect.left = MT9V022_COLUMN_SKIP; + mt9v022->rect.top = MT9V022_ROW_SKIP; + mt9v022->rect.width = MT9V022_MAX_WIDTH; + mt9v022->rect.height = MT9V022_MAX_HEIGHT; + ret = mt9v022_video_probe(icd, client); if (ret) { icd->ops = NULL; diff --git a/linux/drivers/media/video/mx1_camera.c b/linux/drivers/media/video/mx1_camera.c index 1f1324a1d..3875483ab 100644 --- a/linux/drivers/media/video/mx1_camera.c +++ b/linux/drivers/media/video/mx1_camera.c @@ -126,7 +126,7 @@ static int mx1_videobuf_setup(struct videobuf_queue *vq, unsigned int *count, { struct soc_camera_device *icd = vq->priv_data; - *size = icd->rect_current.width * icd->rect_current.height * + *size = icd->user_width * icd->user_height * ((icd->current_fmt->depth + 7) >> 3); if (!*count) @@ -178,12 +178,12 @@ static int mx1_videobuf_prepare(struct videobuf_queue *vq, buf->inwork = 1; if (buf->fmt != icd->current_fmt || - vb->width != icd->rect_current.width || - vb->height != icd->rect_current.height || + vb->width != icd->user_width || + vb->height != icd->user_height || vb->field != field) { buf->fmt = icd->current_fmt; - vb->width = icd->rect_current.width; - vb->height = icd->rect_current.height; + vb->width = icd->user_width; + vb->height = icd->user_height; vb->field = field; vb->state = VIDEOBUF_NEEDS_INIT; } diff --git a/linux/drivers/media/video/mx3_camera.c b/linux/drivers/media/video/mx3_camera.c index d5b51e990..dff2e5e2d 100644 --- a/linux/drivers/media/video/mx3_camera.c +++ b/linux/drivers/media/video/mx3_camera.c @@ -220,7 +220,7 @@ static int mx3_videobuf_setup(struct videobuf_queue *vq, unsigned int *count, if (!mx3_cam->idmac_channel[0]) return -EINVAL; - *size = icd->rect_current.width * icd->rect_current.height * bpp; + *size = icd->user_width * icd->user_height * bpp; if (!*count) *count = 32; @@ -241,7 +241,7 @@ static int mx3_videobuf_prepare(struct videobuf_queue *vq, struct mx3_camera_buffer *buf = container_of(vb, struct mx3_camera_buffer, vb); /* current_fmt _must_ always be set */ - size_t new_size = icd->rect_current.width * icd->rect_current.height * + size_t new_size = icd->user_width * icd->user_height * ((icd->current_fmt->depth + 7) >> 3); int ret; @@ -251,12 +251,12 @@ static int mx3_videobuf_prepare(struct videobuf_queue *vq, */ if (buf->fmt != icd->current_fmt || - vb->width != icd->rect_current.width || - vb->height != icd->rect_current.height || + vb->width != icd->user_width || + vb->height != icd->user_height || vb->field != field) { buf->fmt = icd->current_fmt; - vb->width = icd->rect_current.width; - vb->height = icd->rect_current.height; + vb->width = icd->user_width; + vb->height = icd->user_height; vb->field = field; if (vb->state != VIDEOBUF_NEEDS_INIT) free_buffer(vq, buf); @@ -354,9 +354,9 @@ static void mx3_videobuf_queue(struct videobuf_queue *vq, /* This is the configuration of one sg-element */ video->out_pixel_fmt = fourcc_to_ipu_pix(data_fmt->fourcc); - video->out_width = icd->rect_current.width; - video->out_height = icd->rect_current.height; - video->out_stride = icd->rect_current.width; + video->out_width = icd->user_width; + video->out_height = icd->user_height; + video->out_stride = icd->user_width; #ifdef DEBUG /* helps to see what DMA actually has written */ @@ -541,7 +541,7 @@ static bool channel_change_requested(struct soc_camera_device *icd, /* Do buffers have to be re-allocated or channel re-configured? */ return ichan && rect->width * rect->height > - icd->rect_current.width * icd->rect_current.height; + icd->user_width * icd->user_height; } static int test_platform_param(struct mx3_camera_dev *mx3_cam, @@ -589,8 +589,8 @@ static int test_platform_param(struct mx3_camera_dev *mx3_cam, *flags |= SOCAM_DATAWIDTH_4; break; default: - dev_info(mx3_cam->soc_host.v4l2_dev.dev, "Unsupported bus width %d\n", - buswidth); + dev_warn(mx3_cam->soc_host.v4l2_dev.dev, + "Unsupported bus width %d\n", buswidth); return -EINVAL; } @@ -605,8 +605,7 @@ static int mx3_camera_try_bus_param(struct soc_camera_device *icd, unsigned long bus_flags, camera_flags; int ret = test_platform_param(mx3_cam, depth, &bus_flags); - dev_dbg(icd->dev.parent, "requested bus width %d bit: %d\n", - depth, ret); + dev_dbg(icd->dev.parent, "request bus width %d bit: %d\n", depth, ret); if (ret < 0) return ret; @@ -727,13 +726,13 @@ passthrough: } static void configure_geometry(struct mx3_camera_dev *mx3_cam, - struct v4l2_rect *rect) + unsigned int width, unsigned int height) { u32 ctrl, width_field, height_field; /* Setup frame size - this cannot be changed on-the-fly... */ - width_field = rect->width - 1; - height_field = rect->height - 1; + width_field = width - 1; + height_field = height - 1; csi_reg_write(mx3_cam, width_field | (height_field << 16), CSI_SENS_FRM_SIZE); csi_reg_write(mx3_cam, width_field << 16, CSI_FLASH_STROBE_1); @@ -745,11 +744,6 @@ static void configure_geometry(struct mx3_camera_dev *mx3_cam, ctrl = csi_reg_read(mx3_cam, CSI_OUT_FRM_CTRL) & 0xffff0000; /* Sensor does the cropping */ csi_reg_write(mx3_cam, ctrl | 0 | (0 << 8), CSI_OUT_FRM_CTRL); - - /* - * No need to free resources here if we fail, we'll see if we need to - * do this next time we are called - */ } static int acquire_dma_channel(struct mx3_camera_dev *mx3_cam) @@ -786,6 +780,22 @@ static int acquire_dma_channel(struct mx3_camera_dev *mx3_cam) return 0; } +/* + * FIXME: learn to use stride != width, then we can keep stride properly aligned + * and support arbitrary (even) widths. + */ +static inline void stride_align(__s32 *width) +{ + if (((*width + 7) & ~7) < 4096) + *width = (*width + 7) & ~7; + else + *width = *width & ~7; +} + +/* + * As long as we don't implement host-side cropping and scaling, we can use + * default g_crop and cropcap from soc_camera.c + */ static int mx3_camera_set_crop(struct soc_camera_device *icd, struct v4l2_crop *a) { @@ -793,20 +803,51 @@ static int mx3_camera_set_crop(struct soc_camera_device *icd, struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); struct mx3_camera_dev *mx3_cam = ici->priv; struct v4l2_subdev *sd = soc_camera_to_subdev(icd); + struct v4l2_format f = {.type = V4L2_BUF_TYPE_VIDEO_CAPTURE}; + struct v4l2_pix_format *pix = &f.fmt.pix; + int ret; - /* - * We now know pixel formats and can decide upon DMA-channel(s) - * So far only direct camera-to-memory is supported - */ - if (channel_change_requested(icd, rect)) { - int ret = acquire_dma_channel(mx3_cam); + soc_camera_limit_side(&rect->left, &rect->width, 0, 2, 4096); + soc_camera_limit_side(&rect->top, &rect->height, 0, 2, 4096); + + ret = v4l2_subdev_call(sd, video, s_crop, a); + if (ret < 0) + return ret; + + /* The capture device might have changed its output */ + ret = v4l2_subdev_call(sd, video, g_fmt, &f); + if (ret < 0) + return ret; + + if (pix->width & 7) { + /* Ouch! We can only handle 8-byte aligned width... */ + stride_align(&pix->width); + ret = v4l2_subdev_call(sd, video, s_fmt, &f); if (ret < 0) return ret; } - configure_geometry(mx3_cam, rect); + if (pix->width != icd->user_width || pix->height != icd->user_height) { + /* + * We now know pixel formats and can decide upon DMA-channel(s) + * So far only direct camera-to-memory is supported + */ + if (channel_change_requested(icd, rect)) { + int ret = acquire_dma_channel(mx3_cam); + if (ret < 0) + return ret; + } - return v4l2_subdev_call(sd, video, s_crop, a); + configure_geometry(mx3_cam, pix->width, pix->height); + } + + dev_dbg(icd->dev.parent, "Sensor cropped %dx%d\n", + pix->width, pix->height); + + icd->user_width = pix->width; + icd->user_height = pix->height; + + return ret; } static int mx3_camera_set_fmt(struct soc_camera_device *icd, @@ -817,12 +858,6 @@ static int mx3_camera_set_fmt(struct soc_camera_device *icd, struct v4l2_subdev *sd = soc_camera_to_subdev(icd); const struct soc_camera_format_xlate *xlate; struct v4l2_pix_format *pix = &f->fmt.pix; - struct v4l2_rect rect = { - .left = icd->rect_current.left, - .top = icd->rect_current.top, - .width = pix->width, - .height = pix->height, - }; int ret; xlate = soc_camera_xlate_by_fourcc(icd, pix->pixelformat); @@ -832,6 +867,9 @@ static int mx3_camera_set_fmt(struct soc_camera_device *icd, return -EINVAL; } + stride_align(&pix->width); + dev_dbg(icd->dev.parent, "Set format %dx%d\n", pix->width, pix->height); + ret = acquire_dma_channel(mx3_cam); if (ret < 0) return ret; @@ -842,7 +880,7 @@ static int mx3_camera_set_fmt(struct soc_camera_device *icd, * mxc_v4l2_s_fmt() */ - configure_geometry(mx3_cam, &rect); + configure_geometry(mx3_cam, pix->width, pix->height); ret = v4l2_subdev_call(sd, video, s_fmt, f); if (!ret) { @@ -850,6 +888,8 @@ static int mx3_camera_set_fmt(struct soc_camera_device *icd, icd->current_fmt = xlate->host_fmt; } + dev_dbg(icd->dev.parent, "Sensor set %dx%d\n", pix->width, pix->height); + return ret; } diff --git a/linux/drivers/media/video/ov772x.c b/linux/drivers/media/video/ov772x.c index 392327b72..2d48a7aeb 100644 --- a/linux/drivers/media/video/ov772x.c +++ b/linux/drivers/media/video/ov772x.c @@ -382,11 +382,10 @@ struct regval_list { }; struct ov772x_color_format { - char *name; - __u32 fourcc; - u8 dsp3; - u8 com3; - u8 com7; + const struct soc_camera_data_format *format; + u8 dsp3; + u8 com3; + u8 com7; }; struct ov772x_win_size { @@ -481,43 +480,43 @@ static const struct soc_camera_data_format ov772x_fmt_lists[] = { */ static const struct ov772x_color_format ov772x_cfmts[] = { { - SETFOURCC(YUYV), + .format = &ov772x_fmt_lists[0], .dsp3 = 0x0, .com3 = SWAP_YUV, .com7 = OFMT_YUV, }, { - SETFOURCC(YVYU), + .format = &ov772x_fmt_lists[1], .dsp3 = UV_ON, .com3 = SWAP_YUV, .com7 = OFMT_YUV, }, { - SETFOURCC(UYVY), + .format = &ov772x_fmt_lists[2], .dsp3 = 0x0, .com3 = 0x0, .com7 = OFMT_YUV, }, { - SETFOURCC(RGB555), + .format = &ov772x_fmt_lists[3], .dsp3 = 0x0, .com3 = SWAP_RGB, .com7 = FMT_RGB555 | OFMT_RGB, }, { - SETFOURCC(RGB555X), + .format = &ov772x_fmt_lists[4], .dsp3 = 0x0, .com3 = 0x0, .com7 = FMT_RGB555 | OFMT_RGB, }, { - SETFOURCC(RGB565), + .format = &ov772x_fmt_lists[5], .dsp3 = 0x0, .com3 = SWAP_RGB, .com7 = FMT_RGB565 | OFMT_RGB, }, { - SETFOURCC(RGB565X), + .format = &ov772x_fmt_lists[6], .dsp3 = 0x0, .com3 = 0x0, .com7 = FMT_RGB565 | OFMT_RGB, @@ -648,8 +647,8 @@ static int ov772x_s_stream(struct v4l2_subdev *sd, int enable) ov772x_mask_set(client, COM2, SOFT_SLEEP_MODE, 0); - dev_dbg(&client->dev, - "format %s, win %s\n", priv->fmt->name, priv->win->name); + dev_dbg(&client->dev, "format %s, win %s\n", + priv->fmt->format->name, priv->win->name); return 0; } @@ -818,7 +817,7 @@ static int ov772x_set_params(struct i2c_client *client, */ priv->fmt = NULL; for (i = 0; i < ARRAY_SIZE(ov772x_cfmts); i++) { - if (pixfmt == ov772x_cfmts[i].fourcc) { + if (pixfmt == ov772x_cfmts[i].format->fourcc) { priv->fmt = ov772x_cfmts + i; break; } @@ -955,6 +954,56 @@ ov772x_set_fmt_error: return ret; } +static int ov772x_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) +{ + a->c.left = 0; + a->c.top = 0; + a->c.width = VGA_WIDTH; + a->c.height = VGA_HEIGHT; + a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + + return 0; +} + +static int ov772x_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a) +{ + a->bounds.left = 0; + a->bounds.top = 0; + a->bounds.width = VGA_WIDTH; + a->bounds.height = VGA_HEIGHT; + a->defrect = a->bounds; + a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + a->pixelaspect.numerator = 1; + a->pixelaspect.denominator = 1; + + return 0; +} + +static int ov772x_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) +{ + struct i2c_client *client = sd->priv; + struct ov772x_priv *priv = to_ov772x(client); + struct v4l2_pix_format *pix = &f->fmt.pix; + + if (!priv->win || !priv->fmt) { + u32 width = VGA_WIDTH, height = VGA_HEIGHT; + int ret = ov772x_set_params(client, &width, &height, + V4L2_PIX_FMT_YUYV); + if (ret < 0) + return ret; + } + + f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + + pix->width = priv->win->width; + pix->height = priv->win->height; + pix->pixelformat = priv->fmt->format->fourcc; + pix->colorspace = priv->fmt->format->colorspace; + pix->field = V4L2_FIELD_NONE; + + return 0; +} + static int ov772x_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) { struct i2c_client *client = sd->priv; @@ -1060,8 +1109,11 @@ static struct v4l2_subdev_core_ops ov772x_subdev_core_ops = { static struct v4l2_subdev_video_ops ov772x_subdev_video_ops = { .s_stream = ov772x_s_stream, + .g_fmt = ov772x_g_fmt, .s_fmt = ov772x_s_fmt, .try_fmt = ov772x_try_fmt, + .cropcap = ov772x_cropcap, + .g_crop = ov772x_g_crop, }; static struct v4l2_subdev_ops ov772x_subdev_ops = { @@ -1114,8 +1166,6 @@ static int ov772x_probe(struct i2c_client *client, v4l2_i2c_subdev_init(&priv->subdev, client, &ov772x_subdev_ops); icd->ops = &ov772x_ops; - icd->rect_max.width = MAX_WIDTH; - icd->rect_max.height = MAX_HEIGHT; ret = ov772x_video_probe(icd, client); if (ret) { diff --git a/linux/drivers/media/video/pxa_camera.c b/linux/drivers/media/video/pxa_camera.c index 611e7ff7f..0364b35d5 100644 --- a/linux/drivers/media/video/pxa_camera.c +++ b/linux/drivers/media/video/pxa_camera.c @@ -237,6 +237,10 @@ struct pxa_camera_dev { u32 save_cicr[5]; }; +struct pxa_cam { + unsigned long flags; +}; + static const char *pxa_cam_driver_description = "PXA_Camera"; static unsigned int vid_limit = 16; /* Video memory limit, in Mb */ @@ -251,7 +255,7 @@ static int pxa_videobuf_setup(struct videobuf_queue *vq, unsigned int *count, dev_dbg(icd->dev.parent, "count=%d, size=%d\n", *count, *size); - *size = roundup(icd->rect_current.width * icd->rect_current.height * + *size = roundup(icd->user_width * icd->user_height * ((icd->current_fmt->depth + 7) >> 3), 8); if (0 == *count) @@ -455,12 +459,12 @@ static int pxa_videobuf_prepare(struct videobuf_queue *vq, buf->inwork = 1; if (buf->fmt != icd->current_fmt || - vb->width != icd->rect_current.width || - vb->height != icd->rect_current.height || + vb->width != icd->user_width || + vb->height != icd->user_height || vb->field != field) { buf->fmt = icd->current_fmt; - vb->width = icd->rect_current.width; - vb->height = icd->rect_current.height; + vb->width = icd->user_width; + vb->height = icd->user_height; vb->field = field; vb->state = VIDEOBUF_NEEDS_INIT; } @@ -851,7 +855,7 @@ static u32 mclk_get_divisor(struct platform_device *pdev, struct pxa_camera_dev *pcdev) { unsigned long mclk = pcdev->mclk; - struct device *dev = pcdev->soc_host.v4l2_dev.dev; + struct device *dev = &pdev->dev; u32 div; unsigned long lcdclk; @@ -1052,57 +1056,17 @@ static int test_platform_param(struct pxa_camera_dev *pcdev, return 0; } -static int pxa_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt) +static void pxa_camera_setup_cicr(struct soc_camera_device *icd, + unsigned long flags, __u32 pixfmt) { struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); struct pxa_camera_dev *pcdev = ici->priv; - unsigned long dw, bpp, bus_flags, camera_flags, common_flags; + unsigned long dw, bpp; u32 cicr0, cicr1, cicr2, cicr3, cicr4 = 0; - int ret = test_platform_param(pcdev, icd->buswidth, &bus_flags); - - if (ret < 0) - return ret; - - camera_flags = icd->ops->query_bus_param(icd); - - common_flags = soc_camera_bus_param_compatible(camera_flags, bus_flags); - if (!common_flags) - return -EINVAL; - - pcdev->channels = 1; - - /* Make choises, based on platform preferences */ - if ((common_flags & SOCAM_HSYNC_ACTIVE_HIGH) && - (common_flags & SOCAM_HSYNC_ACTIVE_LOW)) { - if (pcdev->platform_flags & PXA_CAMERA_HSP) - common_flags &= ~SOCAM_HSYNC_ACTIVE_HIGH; - else - common_flags &= ~SOCAM_HSYNC_ACTIVE_LOW; - } - - if ((common_flags & SOCAM_VSYNC_ACTIVE_HIGH) && - (common_flags & SOCAM_VSYNC_ACTIVE_LOW)) { - if (pcdev->platform_flags & PXA_CAMERA_VSP) - common_flags &= ~SOCAM_VSYNC_ACTIVE_HIGH; - else - common_flags &= ~SOCAM_VSYNC_ACTIVE_LOW; - } - - if ((common_flags & SOCAM_PCLK_SAMPLE_RISING) && - (common_flags & SOCAM_PCLK_SAMPLE_FALLING)) { - if (pcdev->platform_flags & PXA_CAMERA_PCP) - common_flags &= ~SOCAM_PCLK_SAMPLE_RISING; - else - common_flags &= ~SOCAM_PCLK_SAMPLE_FALLING; - } - - ret = icd->ops->set_bus_param(icd, common_flags); - if (ret < 0) - return ret; /* Datawidth is now guaranteed to be equal to one of the three values. * We fix bit-per-pixel equal to data-width... */ - switch (common_flags & SOCAM_DATAWIDTH_MASK) { + switch (flags & SOCAM_DATAWIDTH_MASK) { case SOCAM_DATAWIDTH_10: dw = 4; bpp = 0x40; @@ -1123,18 +1087,18 @@ static int pxa_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt) cicr4 |= CICR4_PCLK_EN; if (pcdev->platform_flags & PXA_CAMERA_MCLK_EN) cicr4 |= CICR4_MCLK_EN; - if (common_flags & SOCAM_PCLK_SAMPLE_FALLING) + if (flags & SOCAM_PCLK_SAMPLE_FALLING) cicr4 |= CICR4_PCP; - if (common_flags & SOCAM_HSYNC_ACTIVE_LOW) + if (flags & SOCAM_HSYNC_ACTIVE_LOW) cicr4 |= CICR4_HSP; - if (common_flags & SOCAM_VSYNC_ACTIVE_LOW) + if (flags & SOCAM_VSYNC_ACTIVE_LOW) cicr4 |= CICR4_VSP; cicr0 = __raw_readl(pcdev->base + CICR0); if (cicr0 & CICR0_ENB) __raw_writel(cicr0 & ~CICR0_ENB, pcdev->base + CICR0); - cicr1 = CICR1_PPL_VAL(icd->rect_current.width - 1) | bpp | dw; + cicr1 = CICR1_PPL_VAL(icd->user_width - 1) | bpp | dw; switch (pixfmt) { case V4L2_PIX_FMT_YUV422P: @@ -1163,7 +1127,7 @@ static int pxa_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt) } cicr2 = 0; - cicr3 = CICR3_LPF_VAL(icd->rect_current.height - 1) | + cicr3 = CICR3_LPF_VAL(icd->user_height - 1) | CICR3_BFW_VAL(min((unsigned short)255, icd->y_skip_top)); cicr4 |= pcdev->mclk_divisor; @@ -1177,6 +1141,59 @@ static int pxa_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt) CICR0_SIM_MP : (CICR0_SL_CAP_EN | CICR0_SIM_SP)); cicr0 |= CICR0_DMAEN | CICR0_IRQ_MASK; __raw_writel(cicr0, pcdev->base + CICR0); +} + +static int pxa_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt) +{ + struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); + struct pxa_camera_dev *pcdev = ici->priv; + unsigned long bus_flags, camera_flags, common_flags; + int ret = test_platform_param(pcdev, icd->buswidth, &bus_flags); + struct pxa_cam *cam = icd->host_priv; + + if (ret < 0) + return ret; + + camera_flags = icd->ops->query_bus_param(icd); + + common_flags = soc_camera_bus_param_compatible(camera_flags, bus_flags); + if (!common_flags) + return -EINVAL; + + pcdev->channels = 1; + + /* Make choises, based on platform preferences */ + if ((common_flags & SOCAM_HSYNC_ACTIVE_HIGH) && + (common_flags & SOCAM_HSYNC_ACTIVE_LOW)) { + if (pcdev->platform_flags & PXA_CAMERA_HSP) + common_flags &= ~SOCAM_HSYNC_ACTIVE_HIGH; + else + common_flags &= ~SOCAM_HSYNC_ACTIVE_LOW; + } + + if ((common_flags & SOCAM_VSYNC_ACTIVE_HIGH) && + (common_flags & SOCAM_VSYNC_ACTIVE_LOW)) { + if (pcdev->platform_flags & PXA_CAMERA_VSP) + common_flags &= ~SOCAM_VSYNC_ACTIVE_HIGH; + else + common_flags &= ~SOCAM_VSYNC_ACTIVE_LOW; + } + + if ((common_flags & SOCAM_PCLK_SAMPLE_RISING) && + (common_flags & SOCAM_PCLK_SAMPLE_FALLING)) { + if (pcdev->platform_flags & PXA_CAMERA_PCP) + common_flags &= ~SOCAM_PCLK_SAMPLE_RISING; + else + common_flags &= ~SOCAM_PCLK_SAMPLE_FALLING; + } + + cam->flags = common_flags; + + ret = icd->ops->set_bus_param(icd, common_flags); + if (ret < 0) + return ret; + + pxa_camera_setup_cicr(icd, common_flags, pixfmt); return 0; } @@ -1242,6 +1259,7 @@ static int pxa_camera_get_formats(struct soc_camera_device *icd, int idx, { struct device *dev = icd->dev.parent; int formats = 0, buswidth, ret; + struct pxa_cam *cam; buswidth = required_buswidth(icd->formats + idx); @@ -1252,6 +1270,16 @@ static int pxa_camera_get_formats(struct soc_camera_device *icd, int idx, if (ret < 0) return 0; + if (!icd->host_priv) { + cam = kzalloc(sizeof(*cam), GFP_KERNEL); + if (!cam) + return -ENOMEM; + + icd->host_priv = cam; + } else { + cam = icd->host_priv; + } + switch (icd->formats[idx].fourcc) { case V4L2_PIX_FMT_UYVY: formats++; @@ -1296,6 +1324,19 @@ static int pxa_camera_get_formats(struct soc_camera_device *icd, int idx, return formats; } +static void pxa_camera_put_formats(struct soc_camera_device *icd) +{ + kfree(icd->host_priv); + icd->host_priv = NULL; +} + +static int pxa_camera_check_frame(struct v4l2_pix_format *pix) +{ + /* limit to pxa hardware capabilities */ + return pix->height < 32 || pix->height > 2048 || pix->width < 48 || + pix->width > 2048 || (pix->width & 0x01); +} + static int pxa_camera_set_crop(struct soc_camera_device *icd, struct v4l2_crop *a) { @@ -1308,6 +1349,9 @@ static int pxa_camera_set_crop(struct soc_camera_device *icd, .master_clock = pcdev->mclk, .pixel_clock_max = pcdev->ciclk / 4, }; + struct v4l2_format f; + struct v4l2_pix_format *pix = &f.fmt.pix, pix_tmp; + struct pxa_cam *cam = icd->host_priv; int ret; /* If PCLK is used to latch data from the sensor, check sense */ @@ -1321,7 +1365,37 @@ static int pxa_camera_set_crop(struct soc_camera_device *icd, if (ret < 0) { dev_warn(dev, "Failed to crop to %ux%u@%u:%u\n", rect->width, rect->height, rect->left, rect->top); - } else if (sense.flags & SOCAM_SENSE_PCLK_CHANGED) { + return ret; + } + + f.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + + ret = v4l2_subdev_call(sd, video, g_fmt, &f); + if (ret < 0) + return ret; + + pix_tmp = *pix; + if (pxa_camera_check_frame(pix)) { + /* + * Camera cropping produced a frame beyond our capabilities. + * FIXME: just extract a subframe, that we can process. + */ + v4l_bound_align_image(&pix->width, 48, 2048, 1, + &pix->height, 32, 2048, 0, + icd->current_fmt->fourcc == V4L2_PIX_FMT_YUV422P ? + 4 : 0); + ret = v4l2_subdev_call(sd, video, s_fmt, &f); + if (ret < 0) + return ret; + + if (pxa_camera_check_frame(pix)) { + dev_warn(icd->dev.parent, + "Inconsistent state. Use S_FMT to repair\n"); + return -EINVAL; + } + } + + if (sense.flags & SOCAM_SENSE_PCLK_CHANGED) { if (sense.pixel_clock > sense.pixel_clock_max) { dev_err(dev, "pixel clock %lu set by the camera too high!", @@ -1331,6 +1405,11 @@ static int pxa_camera_set_crop(struct soc_camera_device *icd, recalculate_fifo_timeout(pcdev, sense.pixel_clock); } + icd->user_width = pix->width; + icd->user_height = pix->height; + + pxa_camera_setup_cicr(icd, cam->flags, icd->current_fmt->fourcc); + return ret; } @@ -1371,6 +1450,11 @@ static int pxa_camera_set_fmt(struct soc_camera_device *icd, if (ret < 0) { dev_warn(dev, "Failed to configure for format %x\n", pix->pixelformat); + } else if (pxa_camera_check_frame(pix)) { + dev_warn(dev, + "Camera driver produced an unsupported frame %dx%d\n", + pix->width, pix->height); + ret = -EINVAL; } else if (sense.flags & SOCAM_SENSE_PCLK_CHANGED) { if (sense.pixel_clock > sense.pixel_clock_max) { dev_err(dev, @@ -1414,7 +1498,7 @@ static int pxa_camera_try_fmt(struct soc_camera_device *icd, */ v4l_bound_align_image(&pix->width, 48, 2048, 1, &pix->height, 32, 2048, 0, - xlate->host_fmt->fourcc == V4L2_PIX_FMT_YUV422P ? 4 : 0); + pixfmt == V4L2_PIX_FMT_YUV422P ? 4 : 0); pix->bytesperline = pix->width * DIV_ROUND_UP(xlate->host_fmt->depth, 8); @@ -1424,7 +1508,7 @@ static int pxa_camera_try_fmt(struct soc_camera_device *icd, pix->pixelformat = xlate->cam_fmt->fourcc; /* limit to sensor capabilities */ ret = v4l2_subdev_call(sd, video, try_fmt, f); - pix->pixelformat = xlate->host_fmt->fourcc; + pix->pixelformat = pixfmt; field = pix->field; @@ -1537,6 +1621,7 @@ static struct soc_camera_host_ops pxa_soc_camera_host_ops = { .resume = pxa_camera_resume, .set_crop = pxa_camera_set_crop, .get_formats = pxa_camera_get_formats, + .put_formats = pxa_camera_put_formats, .set_fmt = pxa_camera_set_fmt, .try_fmt = pxa_camera_try_fmt, .init_videobuf = pxa_camera_init_videobuf, diff --git a/linux/drivers/media/video/sh_mobile_ceu_camera.c b/linux/drivers/media/video/sh_mobile_ceu_camera.c index 142bdbc6f..d35f66d8a 100644 --- a/linux/drivers/media/video/sh_mobile_ceu_camera.c +++ b/linux/drivers/media/video/sh_mobile_ceu_camera.c @@ -75,6 +75,13 @@ #define CDBYR2 0x98 /* Capture data bottom-field address Y register 2 */ #define CDBCR2 0x9c /* Capture data bottom-field address C register 2 */ +#undef DEBUG_GEOMETRY +#ifdef DEBUG_GEOMETRY +#define dev_geo dev_info +#else +#define dev_geo dev_dbg +#endif + /* per video frame buffer */ struct sh_mobile_ceu_buffer { struct videobuf_buffer vb; /* v4l buffer must be first */ @@ -105,8 +112,9 @@ struct sh_mobile_ceu_dev { }; struct sh_mobile_ceu_cam { - struct v4l2_rect camera_rect; - struct v4l2_rect camera_max; + struct v4l2_rect ceu_rect; + unsigned int cam_width; + unsigned int cam_height; const struct soc_camera_data_format *extra_fmt; const struct soc_camera_data_format *camera_fmt; }; @@ -158,7 +166,7 @@ static int sh_mobile_ceu_videobuf_setup(struct videobuf_queue *vq, struct sh_mobile_ceu_dev *pcdev = ici->priv; int bytes_per_pixel = (icd->current_fmt->depth + 7) >> 3; - *size = PAGE_ALIGN(icd->rect_current.width * icd->rect_current.height * + *size = PAGE_ALIGN(icd->user_width * icd->user_height * bytes_per_pixel); if (0 == *count) @@ -178,8 +186,9 @@ static void free_buffer(struct videobuf_queue *vq, struct sh_mobile_ceu_buffer *buf) { struct soc_camera_device *icd = vq->priv_data; + struct device *dev = icd->dev.parent; - dev_dbg(icd->dev.parent, "%s (vb=0x%p) 0x%08lx %zd\n", __func__, + dev_dbg(dev, "%s (vb=0x%p) 0x%08lx %zd\n", __func__, &buf->vb, buf->vb.baddr, buf->vb.bsize); if (in_interrupt()) @@ -187,7 +196,7 @@ static void free_buffer(struct videobuf_queue *vq, videobuf_waiton(&buf->vb, 0, 0); videobuf_dma_contig_free(vq, &buf->vb); - dev_dbg(icd->dev.parent, "%s freed\n", __func__); + dev_dbg(dev, "%s freed\n", __func__); buf->vb.state = VIDEOBUF_NEEDS_INIT; } @@ -218,7 +227,7 @@ static void sh_mobile_ceu_capture(struct sh_mobile_ceu_dev *pcdev) phys_addr_top = videobuf_to_dma_contig(pcdev->active); ceu_write(pcdev, CDAYR, phys_addr_top); if (pcdev->is_interlaced) { - phys_addr_bottom = phys_addr_top + icd->rect_current.width; + phys_addr_bottom = phys_addr_top + icd->user_width; ceu_write(pcdev, CDBYR, phys_addr_bottom); } @@ -227,12 +236,12 @@ static void sh_mobile_ceu_capture(struct sh_mobile_ceu_dev *pcdev) case V4L2_PIX_FMT_NV21: case V4L2_PIX_FMT_NV16: case V4L2_PIX_FMT_NV61: - phys_addr_top += icd->rect_current.width * - icd->rect_current.height; + phys_addr_top += icd->user_width * + icd->user_height; ceu_write(pcdev, CDACR, phys_addr_top); if (pcdev->is_interlaced) { phys_addr_bottom = phys_addr_top + - icd->rect_current.width; + icd->user_width; ceu_write(pcdev, CDBCR, phys_addr_bottom); } } @@ -266,12 +275,12 @@ static int sh_mobile_ceu_videobuf_prepare(struct videobuf_queue *vq, BUG_ON(NULL == icd->current_fmt); if (buf->fmt != icd->current_fmt || - vb->width != icd->rect_current.width || - vb->height != icd->rect_current.height || + vb->width != icd->user_width || + vb->height != icd->user_height || vb->field != field) { buf->fmt = icd->current_fmt; - vb->width = icd->rect_current.width; - vb->height = icd->rect_current.height; + vb->width = icd->user_width; + vb->height = icd->user_height; vb->field = field; vb->state = VIDEOBUF_NEEDS_INIT; } @@ -453,18 +462,6 @@ static unsigned int size_dst(unsigned int src, unsigned int scale) mant_pre * 4096 / scale + 1; } -static unsigned int size_src(unsigned int dst, unsigned int scale) -{ - unsigned int mant_pre = scale >> 12, tmp; - if (!dst || !scale) - return dst; - for (tmp = ((dst - 1) * scale + 2048 * mant_pre) / 4096 + 1; - size_dst(tmp, scale) < dst; - tmp++) - ; - return tmp; -} - static u16 calc_scale(unsigned int src, unsigned int *dst) { u16 scale; @@ -484,65 +481,46 @@ static u16 calc_scale(unsigned int src, unsigned int *dst) /* rect is guaranteed to not exceed the scaled camera rectangle */ static void sh_mobile_ceu_set_rect(struct soc_camera_device *icd, - struct v4l2_rect *rect) + unsigned int out_width, + unsigned int out_height) { struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); struct sh_mobile_ceu_cam *cam = icd->host_priv; + struct v4l2_rect *rect = &cam->ceu_rect; struct sh_mobile_ceu_dev *pcdev = ici->priv; - int width, height, cfszr_width, cdwdr_width, in_width, in_height; - unsigned int left_offset, top_offset, left, top; - unsigned int hscale = pcdev->cflcr & 0xffff; - unsigned int vscale = (pcdev->cflcr >> 16) & 0xffff; + unsigned int height, width, cdwdr_width, in_width, in_height; + unsigned int left_offset, top_offset; u32 camor; - /* Switch to the camera scale */ - left = size_src(rect->left, hscale); - top = size_src(rect->top, vscale); - - dev_dbg(icd->dev.parent, "Left %u * 0x%x = %u, top %u * 0x%x = %u\n", - rect->left, hscale, left, rect->top, vscale, top); - - if (left > cam->camera_rect.left) { - left_offset = left - cam->camera_rect.left; - } else { - left_offset = 0; - left = cam->camera_rect.left; - } - - if (top > cam->camera_rect.top) { - top_offset = top - cam->camera_rect.top; - } else { - top_offset = 0; - top = cam->camera_rect.top; - } + dev_dbg(icd->dev.parent, "Crop %ux%u@%u:%u\n", + rect->width, rect->height, rect->left, rect->top); - dev_dbg(icd->dev.parent, "New left %u, top %u, offsets %u:%u\n", - rect->left, rect->top, left_offset, top_offset); + left_offset = rect->left; + top_offset = rect->top; if (pcdev->image_mode) { - width = rect->width; - in_width = cam->camera_rect.width; + in_width = rect->width; if (!pcdev->is_16bit) { - width *= 2; in_width *= 2; left_offset *= 2; } - cfszr_width = cdwdr_width = rect->width; + width = cdwdr_width = out_width; } else { unsigned int w_factor = (icd->current_fmt->depth + 7) >> 3; + + width = out_width * w_factor / 2; + if (!pcdev->is_16bit) w_factor *= 2; - width = rect->width * w_factor / 2; - in_width = cam->camera_rect.width * w_factor / 2; + in_width = rect->width * w_factor / 2; left_offset = left_offset * w_factor / 2; - cfszr_width = pcdev->is_16bit ? width : width / 2; - cdwdr_width = pcdev->is_16bit ? width * 2 : width; + cdwdr_width = width * 2; } - height = rect->height; - in_height = cam->camera_rect.height; + height = out_height; + in_height = rect->height; if (pcdev->is_interlaced) { height /= 2; in_height /= 2; @@ -550,10 +528,17 @@ static void sh_mobile_ceu_set_rect(struct soc_camera_device *icd, cdwdr_width *= 2; } + /* Set CAMOR, CAPWR, CFSZR, take care of CDWDR */ camor = left_offset | (top_offset << 16); + + dev_geo(icd->dev.parent, + "CAMOR 0x%x, CAPWR 0x%x, CFSZR 0x%x, CDWDR 0x%x\n", camor, + (in_height << 16) | in_width, (height << 16) | width, + cdwdr_width); + ceu_write(pcdev, CAMOR, camor); ceu_write(pcdev, CAPWR, (in_height << 16) | in_width); - ceu_write(pcdev, CFSZR, (height << 16) | cfszr_width); + ceu_write(pcdev, CFSZR, (height << 16) | width); ceu_write(pcdev, CDWDR, cdwdr_width); } @@ -665,8 +650,8 @@ static int sh_mobile_ceu_set_bus_param(struct soc_camera_device *icd, ceu_write(pcdev, CAPCR, 0x00300000); ceu_write(pcdev, CAIFR, pcdev->is_interlaced ? 0x101 : 0); + sh_mobile_ceu_set_rect(icd, icd->user_width, icd->user_height); mdelay(1); - sh_mobile_ceu_set_rect(icd, &icd->rect_current); ceu_write(pcdev, CFLCR, pcdev->cflcr); @@ -689,11 +674,10 @@ static int sh_mobile_ceu_set_bus_param(struct soc_camera_device *icd, ceu_write(pcdev, CDOCR, value); ceu_write(pcdev, CFWCR, 0); /* keep "datafetch firewall" disabled */ - dev_dbg(icd->dev.parent, "S_FMT successful for %c%c%c%c %ux%u@%u:%u\n", + dev_dbg(icd->dev.parent, "S_FMT successful for %c%c%c%c %ux%u\n", pixfmt & 0xff, (pixfmt >> 8) & 0xff, (pixfmt >> 16) & 0xff, (pixfmt >> 24) & 0xff, - icd->rect_current.width, icd->rect_current.height, - icd->rect_current.left, icd->rect_current.top); + icd->user_width, icd->user_height); capture_restore(pcdev, capsr); @@ -746,6 +730,7 @@ static const struct soc_camera_data_format sh_mobile_ceu_formats[] = { static int sh_mobile_ceu_get_formats(struct soc_camera_device *icd, int idx, struct soc_camera_format_xlate *xlate) { + struct device *dev = icd->dev.parent; int ret, k, n; int formats = 0; struct sh_mobile_ceu_cam *cam; @@ -760,7 +745,6 @@ static int sh_mobile_ceu_get_formats(struct soc_camera_device *icd, int idx, return -ENOMEM; icd->host_priv = cam; - cam->camera_max = icd->rect_max; } else { cam = icd->host_priv; } @@ -795,8 +779,7 @@ static int sh_mobile_ceu_get_formats(struct soc_camera_device *icd, int idx, xlate->cam_fmt = icd->formats + idx; xlate->buswidth = icd->formats[idx].depth; xlate++; - dev_dbg(icd->dev.parent, - "Providing format %s using %s\n", + dev_dbg(dev, "Providing format %s using %s\n", sh_mobile_ceu_formats[k].name, icd->formats[idx].name); } @@ -809,7 +792,7 @@ add_single_format: xlate->cam_fmt = icd->formats + idx; xlate->buswidth = icd->formats[idx].depth; xlate++; - dev_dbg(icd->dev.parent, + dev_dbg(dev, "Providing format %s in pass-through mode\n", icd->formats[idx].name); } @@ -838,176 +821,487 @@ static bool is_inside(struct v4l2_rect *r1, struct v4l2_rect *r2) r1->top + r1->height < r2->top + r2->height; } +static unsigned int scale_down(unsigned int size, unsigned int scale) +{ + return (size * 4096 + scale / 2) / scale; +} + +static unsigned int scale_up(unsigned int size, unsigned int scale) +{ + return (size * scale + 2048) / 4096; +} + +static unsigned int calc_generic_scale(unsigned int input, unsigned int output) +{ + return (input * 4096 + output / 2) / output; +} + +static int client_g_rect(struct v4l2_subdev *sd, struct v4l2_rect *rect) +{ + struct v4l2_crop crop; + struct v4l2_cropcap cap; + int ret; + + crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + + ret = v4l2_subdev_call(sd, video, g_crop, &crop); + if (!ret) { + *rect = crop.c; + return ret; + } + + /* Camera driver doesn't support .g_crop(), assume default rectangle */ + cap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + + ret = v4l2_subdev_call(sd, video, cropcap, &cap); + if (ret < 0) + return ret; + + *rect = cap.defrect; + + return ret; +} + /* - * CEU can scale and crop, but we don't want to waste bandwidth and kill the - * framerate by always requesting the maximum image from the client. For - * cropping we also have to take care of the current scale. The common for both - * scaling and cropping approach is: + * The common for both scaling and cropping iterative approach is: * 1. try if the client can produce exactly what requested by the user * 2. if (1) failed, try to double the client image until we get one big enough * 3. if (2) failed, try to request the maximum image */ -static int sh_mobile_ceu_set_crop(struct soc_camera_device *icd, - struct v4l2_crop *a) +static int client_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *crop, + struct v4l2_crop *cam_crop) { - struct v4l2_rect *rect = &a->c; - struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); - struct sh_mobile_ceu_dev *pcdev = ici->priv; - struct v4l2_crop cam_crop; - struct v4l2_rect *cam_rect = &cam_crop.c, target, cam_max; - struct sh_mobile_ceu_cam *cam = icd->host_priv; - struct v4l2_subdev *sd = soc_camera_to_subdev(icd); - unsigned int hscale = pcdev->cflcr & 0xffff; - unsigned int vscale = (pcdev->cflcr >> 16) & 0xffff; - unsigned short width, height; - u32 capsr; + struct v4l2_rect *rect = &crop->c, *cam_rect = &cam_crop->c; + struct device *dev = sd->v4l2_dev->dev; + struct v4l2_cropcap cap; int ret; + unsigned int width, height; - /* Scale back up into client units */ - cam_rect->left = size_src(rect->left, hscale); - cam_rect->width = size_src(rect->width, hscale); - cam_rect->top = size_src(rect->top, vscale); - cam_rect->height = size_src(rect->height, vscale); - - target = *cam_rect; + v4l2_subdev_call(sd, video, s_crop, crop); + ret = client_g_rect(sd, cam_rect); + if (ret < 0) + return ret; - capsr = capture_save_reset(pcdev); - dev_dbg(icd->dev.parent, "CAPSR 0x%x, CFLCR 0x%x\n", - capsr, pcdev->cflcr); - - /* First attempt - see if the client can deliver a perfect result */ - ret = v4l2_subdev_call(sd, video, s_crop, &cam_crop); - if (!ret && !memcmp(&target, &cam_rect, sizeof(target))) { - dev_dbg(icd->dev.parent, - "Camera S_CROP successful for %ux%u@%u:%u\n", - cam_rect->width, cam_rect->height, - cam_rect->left, cam_rect->top); - goto ceu_set_rect; + /* + * Now cam_crop contains the current camera input rectangle, and it must + * be within camera cropcap bounds + */ + if (!memcmp(rect, cam_rect, sizeof(*rect))) { + /* Even if camera S_CROP failed, but camera rectangle matches */ + dev_dbg(dev, "Camera S_CROP successful for %ux%u@%u:%u\n", + rect->width, rect->height, rect->left, rect->top); + return 0; } - /* Try to fix cropping, that camera hasn't managed to do */ - dev_dbg(icd->dev.parent, "Fix camera S_CROP %d for %ux%u@%u:%u" - " to %ux%u@%u:%u\n", - ret, cam_rect->width, cam_rect->height, + /* Try to fix cropping, that camera hasn't managed to set */ + dev_geo(dev, "Fix camera S_CROP for %ux%u@%u:%u to %ux%u@%u:%u\n", + cam_rect->width, cam_rect->height, cam_rect->left, cam_rect->top, - target.width, target.height, target.left, target.top); + rect->width, rect->height, rect->left, rect->top); + + /* We need sensor maximum rectangle */ + ret = v4l2_subdev_call(sd, video, cropcap, &cap); + if (ret < 0) + return ret; + + soc_camera_limit_side(&rect->left, &rect->width, cap.bounds.left, 2, + cap.bounds.width); + soc_camera_limit_side(&rect->top, &rect->height, cap.bounds.top, 4, + cap.bounds.height); /* * Popular special case - some cameras can only handle fixed sizes like * QVGA, VGA,... Take care to avoid infinite loop. */ - width = max(cam_rect->width, 1); - height = max(cam_rect->height, 1); - cam_max.width = size_src(icd->rect_max.width, hscale); - cam_max.left = size_src(icd->rect_max.left, hscale); - cam_max.height = size_src(icd->rect_max.height, vscale); - cam_max.top = size_src(icd->rect_max.top, vscale); - while (!ret && (is_smaller(cam_rect, &target) || - is_inside(cam_rect, &target)) && - cam_max.width >= width && cam_max.height >= height) { + width = max(cam_rect->width, 2); + height = max(cam_rect->height, 2); + + while (!ret && (is_smaller(cam_rect, rect) || + is_inside(cam_rect, rect)) && + (cap.bounds.width > width || cap.bounds.height > height)) { width *= 2; height *= 2; + cam_rect->width = width; cam_rect->height = height; - /* We do not know what the camera is capable of, play safe */ - if (cam_rect->left > target.left) - cam_rect->left = cam_max.left; + /* + * We do not know what capabilities the camera has to set up + * left and top borders. We could try to be smarter in iterating + * them, e.g., if camera current left is to the right of the + * target left, set it to the middle point between the current + * left and minimum left. But that would add too much + * complexity: we would have to iterate each border separately. + */ + if (cam_rect->left > rect->left) + cam_rect->left = cap.bounds.left; - if (cam_rect->left + cam_rect->width < target.left + target.width) - cam_rect->width = target.left + target.width - + if (cam_rect->left + cam_rect->width < rect->left + rect->width) + cam_rect->width = rect->left + rect->width - cam_rect->left; - if (cam_rect->top > target.top) - cam_rect->top = cam_max.top; + if (cam_rect->top > rect->top) + cam_rect->top = cap.bounds.top; - if (cam_rect->top + cam_rect->height < target.top + target.height) - cam_rect->height = target.top + target.height - + if (cam_rect->top + cam_rect->height < rect->top + rect->height) + cam_rect->height = rect->top + rect->height - cam_rect->top; - if (cam_rect->width + cam_rect->left > - cam_max.width + cam_max.left) - cam_rect->left = max(cam_max.width + cam_max.left - - cam_rect->width, cam_max.left); - - if (cam_rect->height + cam_rect->top > - cam_max.height + cam_max.top) - cam_rect->top = max(cam_max.height + cam_max.top - - cam_rect->height, cam_max.top); - - ret = v4l2_subdev_call(sd, video, s_crop, &cam_crop); - dev_dbg(icd->dev.parent, "Camera S_CROP %d for %ux%u@%u:%u\n", - ret, cam_rect->width, cam_rect->height, + v4l2_subdev_call(sd, video, s_crop, cam_crop); + ret = client_g_rect(sd, cam_rect); + dev_geo(dev, "Camera S_CROP %d for %ux%u@%u:%u\n", ret, + cam_rect->width, cam_rect->height, cam_rect->left, cam_rect->top); } - /* - * If the camera failed to configure cropping, it should not modify the - * rectangle - */ - if ((ret < 0 && (is_smaller(&icd->rect_current, rect) || - is_inside(&icd->rect_current, rect))) || - is_smaller(cam_rect, &target) || is_inside(cam_rect, &target)) { + /* S_CROP must not modify the rectangle */ + if (is_smaller(cam_rect, rect) || is_inside(cam_rect, rect)) { /* * The camera failed to configure a suitable cropping, * we cannot use the current rectangle, set to max */ - *cam_rect = cam_max; - ret = v4l2_subdev_call(sd, video, s_crop, &cam_crop); - dev_dbg(icd->dev.parent, - "Camera S_CROP %d for max %ux%u@%u:%u\n", - ret, cam_rect->width, cam_rect->height, + *cam_rect = cap.bounds; + v4l2_subdev_call(sd, video, s_crop, cam_crop); + ret = client_g_rect(sd, cam_rect); + dev_geo(dev, "Camera S_CROP %d for max %ux%u@%u:%u\n", ret, + cam_rect->width, cam_rect->height, cam_rect->left, cam_rect->top); - if (ret < 0 && ret != -ENOIOCTLCMD) - /* All failed, hopefully resume current capture */ - goto resume_capture; - - /* Finally, adjust the target rectangle */ - if (target.width > cam_rect->width) - target.width = cam_rect->width; - if (target.height > cam_rect->height) - target.height = cam_rect->height; - if (target.left + target.width > cam_rect->left + cam_rect->width) - target.left = cam_rect->left + cam_rect->width - - target.width; - if (target.top + target.height > cam_rect->top + cam_rect->height) - target.top = cam_rect->top + cam_rect->height - - target.height; } - /* We now have a rectangle, larger than requested, let's crop */ + return ret; +} + +static int get_camera_scales(struct v4l2_subdev *sd, struct v4l2_rect *rect, + unsigned int *scale_h, unsigned int *scale_v) +{ + struct v4l2_format f; + int ret; + + f.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + + ret = v4l2_subdev_call(sd, video, g_fmt, &f); + if (ret < 0) + return ret; + + *scale_h = calc_generic_scale(rect->width, f.fmt.pix.width); + *scale_v = calc_generic_scale(rect->height, f.fmt.pix.height); + + return 0; +} + +static int get_camera_subwin(struct soc_camera_device *icd, + struct v4l2_rect *cam_subrect, + unsigned int cam_hscale, unsigned int cam_vscale) +{ + struct sh_mobile_ceu_cam *cam = icd->host_priv; + struct v4l2_rect *ceu_rect = &cam->ceu_rect; + + if (!ceu_rect->width) { + struct v4l2_subdev *sd = soc_camera_to_subdev(icd); + struct device *dev = icd->dev.parent; + struct v4l2_format f; + struct v4l2_pix_format *pix = &f.fmt.pix; + int ret; + /* First time */ + + f.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + + ret = v4l2_subdev_call(sd, video, g_fmt, &f); + if (ret < 0) + return ret; + + dev_geo(dev, "camera fmt %ux%u\n", pix->width, pix->height); + + if (pix->width > 2560) { + ceu_rect->width = 2560; + ceu_rect->left = (pix->width - 2560) / 2; + } else { + ceu_rect->width = pix->width; + ceu_rect->left = 0; + } + + if (pix->height > 1920) { + ceu_rect->height = 1920; + ceu_rect->top = (pix->height - 1920) / 2; + } else { + ceu_rect->height = pix->height; + ceu_rect->top = 0; + } + + dev_geo(dev, "initialised CEU rect %ux%u@%u:%u\n", + ceu_rect->width, ceu_rect->height, + ceu_rect->left, ceu_rect->top); + } + + cam_subrect->width = scale_up(ceu_rect->width, cam_hscale); + cam_subrect->left = scale_up(ceu_rect->left, cam_hscale); + cam_subrect->height = scale_up(ceu_rect->height, cam_vscale); + cam_subrect->top = scale_up(ceu_rect->top, cam_vscale); + + return 0; +} + +static int client_s_fmt(struct soc_camera_device *icd, struct v4l2_format *f, + bool ceu_can_scale) +{ + struct v4l2_subdev *sd = soc_camera_to_subdev(icd); + struct device *dev = icd->dev.parent; + struct v4l2_pix_format *pix = &f->fmt.pix; + unsigned int width = pix->width, height = pix->height, tmp_w, tmp_h; + unsigned int max_width, max_height; + struct v4l2_cropcap cap; + int ret; + + cap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + + ret = v4l2_subdev_call(sd, video, cropcap, &cap); + if (ret < 0) + return ret; + + max_width = min(cap.bounds.width, 2560); + max_height = min(cap.bounds.height, 1920); + + ret = v4l2_subdev_call(sd, video, s_fmt, f); + if (ret < 0) + return ret; + + dev_geo(dev, "camera scaled to %ux%u\n", pix->width, pix->height); + + if ((width == pix->width && height == pix->height) || !ceu_can_scale) + return 0; + + /* Camera set a format, but geometry is not precise, try to improve */ + tmp_w = pix->width; + tmp_h = pix->height; + + /* width <= max_width && height <= max_height - guaranteed by try_fmt */ + while ((width > tmp_w || height > tmp_h) && + tmp_w < max_width && tmp_h < max_height) { + tmp_w = min(2 * tmp_w, max_width); + tmp_h = min(2 * tmp_h, max_height); + pix->width = tmp_w; + pix->height = tmp_h; + ret = v4l2_subdev_call(sd, video, s_fmt, f); + dev_geo(dev, "Camera scaled to %ux%u\n", + pix->width, pix->height); + if (ret < 0) { + /* This shouldn't happen */ + dev_err(dev, "Client failed to set format: %d\n", ret); + return ret; + } + } + + return 0; +} + +/** + * @rect - camera cropped rectangle + * @sub_rect - CEU cropped rectangle, mapped back to camera input area + * @ceu_rect - on output calculated CEU crop rectangle + */ +static int client_scale(struct soc_camera_device *icd, struct v4l2_rect *rect, + struct v4l2_rect *sub_rect, struct v4l2_rect *ceu_rect, + struct v4l2_format *f, bool ceu_can_scale) +{ + struct v4l2_subdev *sd = soc_camera_to_subdev(icd); + struct sh_mobile_ceu_cam *cam = icd->host_priv; + struct device *dev = icd->dev.parent; + struct v4l2_format f_tmp = *f; + struct v4l2_pix_format *pix_tmp = &f_tmp.fmt.pix; + unsigned int scale_h, scale_v; + int ret; + + /* 5. Apply iterative camera S_FMT for camera user window. */ + ret = client_s_fmt(icd, &f_tmp, ceu_can_scale); + if (ret < 0) + return ret; + + dev_geo(dev, "5: camera scaled to %ux%u\n", + pix_tmp->width, pix_tmp->height); + + /* 6. Retrieve camera output window (g_fmt) */ + + /* unneeded - it is already in "f_tmp" */ + + /* 7. Calculate new camera scales. */ + ret = get_camera_scales(sd, rect, &scale_h, &scale_v); + if (ret < 0) + return ret; + + dev_geo(dev, "7: camera scales %u:%u\n", scale_h, scale_v); + + cam->cam_width = pix_tmp->width; + cam->cam_height = pix_tmp->height; + f->fmt.pix.width = pix_tmp->width; + f->fmt.pix.height = pix_tmp->height; /* - * We have to preserve camera rectangle between close() / open(), - * because soc-camera core calls .set_fmt() on each first open() with - * last before last close() _user_ rectangle, which can be different - * from camera rectangle. + * 8. Calculate new CEU crop - apply camera scales to previously + * calculated "effective" crop. */ - dev_dbg(icd->dev.parent, - "SH S_CROP from %ux%u@%u:%u to %ux%u@%u:%u, scale to %ux%u@%u:%u\n", - cam_rect->width, cam_rect->height, cam_rect->left, cam_rect->top, - target.width, target.height, target.left, target.top, - rect->width, rect->height, rect->left, rect->top); + ceu_rect->left = scale_down(sub_rect->left, scale_h); + ceu_rect->width = scale_down(sub_rect->width, scale_h); + ceu_rect->top = scale_down(sub_rect->top, scale_v); + ceu_rect->height = scale_down(sub_rect->height, scale_v); + + dev_geo(dev, "8: new CEU rect %ux%u@%u:%u\n", + ceu_rect->width, ceu_rect->height, + ceu_rect->left, ceu_rect->top); + + return 0; +} + +/* Get combined scales */ +static int get_scales(struct soc_camera_device *icd, + unsigned int *scale_h, unsigned int *scale_v) +{ + struct sh_mobile_ceu_cam *cam = icd->host_priv; + struct v4l2_subdev *sd = soc_camera_to_subdev(icd); + struct v4l2_crop cam_crop; + unsigned int width_in, height_in; + int ret; - ret = 0; + cam_crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; -ceu_set_rect: - cam->camera_rect = *cam_rect; + ret = client_g_rect(sd, &cam_crop.c); + if (ret < 0) + return ret; - rect->width = size_dst(target.width, hscale); - rect->left = size_dst(target.left, hscale); - rect->height = size_dst(target.height, vscale); - rect->top = size_dst(target.top, vscale); + ret = get_camera_scales(sd, &cam_crop.c, scale_h, scale_v); + if (ret < 0) + return ret; - sh_mobile_ceu_set_rect(icd, rect); + width_in = scale_up(cam->ceu_rect.width, *scale_h); + height_in = scale_up(cam->ceu_rect.height, *scale_v); -resume_capture: - /* Set CAMOR, CAPWR, CFSZR, take care of CDWDR */ + *scale_h = calc_generic_scale(cam->ceu_rect.width, icd->user_width); + *scale_v = calc_generic_scale(cam->ceu_rect.height, icd->user_height); + + return 0; +} + +/* + * CEU can scale and crop, but we don't want to waste bandwidth and kill the + * framerate by always requesting the maximum image from the client. See + * Documentation/video4linux/sh_mobile_camera_ceu.txt for a description of + * scaling and cropping algorithms and for the meaning of referenced here steps. + */ +static int sh_mobile_ceu_set_crop(struct soc_camera_device *icd, + struct v4l2_crop *a) +{ + struct v4l2_rect *rect = &a->c; + struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); + struct sh_mobile_ceu_dev *pcdev = ici->priv; + struct v4l2_crop cam_crop; + struct sh_mobile_ceu_cam *cam = icd->host_priv; + struct v4l2_rect *cam_rect = &cam_crop.c, *ceu_rect = &cam->ceu_rect; + struct v4l2_subdev *sd = soc_camera_to_subdev(icd); + struct device *dev = icd->dev.parent; + struct v4l2_format f; + struct v4l2_pix_format *pix = &f.fmt.pix; + unsigned int scale_comb_h, scale_comb_v, scale_ceu_h, scale_ceu_v, + out_width, out_height; + u32 capsr, cflcr; + int ret; + + /* 1. Calculate current combined scales. */ + ret = get_scales(icd, &scale_comb_h, &scale_comb_v); + if (ret < 0) + return ret; + + dev_geo(dev, "1: combined scales %u:%u\n", scale_comb_h, scale_comb_v); + + /* 2. Apply iterative camera S_CROP for new input window. */ + ret = client_s_crop(sd, a, &cam_crop); + if (ret < 0) + return ret; + + dev_geo(dev, "2: camera cropped to %ux%u@%u:%u\n", + cam_rect->width, cam_rect->height, + cam_rect->left, cam_rect->top); + + /* On success cam_crop contains current camera crop */ + + /* + * 3. If old combined scales applied to new crop produce an impossible + * user window, adjust scales to produce nearest possible window. + */ + out_width = scale_down(rect->width, scale_comb_h); + out_height = scale_down(rect->height, scale_comb_v); + + if (out_width > 2560) + out_width = 2560; + else if (out_width < 2) + out_width = 2; + + if (out_height > 1920) + out_height = 1920; + else if (out_height < 4) + out_height = 4; + + dev_geo(dev, "3: Adjusted output %ux%u\n", out_width, out_height); + + /* 4. Use G_CROP to retrieve actual input window: already in cam_crop */ + + /* + * 5. Using actual input window and calculated combined scales calculate + * camera target output window. + */ + pix->width = scale_down(cam_rect->width, scale_comb_h); + pix->height = scale_down(cam_rect->height, scale_comb_v); + + dev_geo(dev, "5: camera target %ux%u\n", pix->width, pix->height); + + /* 6. - 9. */ + pix->pixelformat = cam->camera_fmt->fourcc; + pix->colorspace = cam->camera_fmt->colorspace; + + capsr = capture_save_reset(pcdev); + dev_dbg(dev, "CAPSR 0x%x, CFLCR 0x%x\n", capsr, pcdev->cflcr); + + /* Make relative to camera rectangle */ + rect->left -= cam_rect->left; + rect->top -= cam_rect->top; + + f.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + + ret = client_scale(icd, cam_rect, rect, ceu_rect, &f, + pcdev->image_mode && !pcdev->is_interlaced); + + dev_geo(dev, "6-9: %d\n", ret); + + /* 10. Use CEU cropping to crop to the new window. */ + sh_mobile_ceu_set_rect(icd, out_width, out_height); + + dev_geo(dev, "10: CEU cropped to %ux%u@%u:%u\n", + ceu_rect->width, ceu_rect->height, + ceu_rect->left, ceu_rect->top); + + /* + * 11. Calculate CEU scales from camera scales from results of (10) and + * user window from (3) + */ + scale_ceu_h = calc_scale(ceu_rect->width, &out_width); + scale_ceu_v = calc_scale(ceu_rect->height, &out_height); + + dev_geo(dev, "11: CEU scales %u:%u\n", scale_ceu_h, scale_ceu_v); + + /* 12. Apply CEU scales. */ + cflcr = scale_ceu_h | (scale_ceu_v << 16); + if (cflcr != pcdev->cflcr) { + pcdev->cflcr = cflcr; + ceu_write(pcdev, CFLCR, cflcr); + } + + /* Restore capture */ if (pcdev->active) capsr |= 1; capture_restore(pcdev, capsr); + icd->user_width = out_width; + icd->user_height = out_height; + /* Even if only camera cropping succeeded */ return ret; } @@ -1020,121 +1314,137 @@ static int sh_mobile_ceu_set_fmt(struct soc_camera_device *icd, struct sh_mobile_ceu_dev *pcdev = ici->priv; struct sh_mobile_ceu_cam *cam = icd->host_priv; struct v4l2_pix_format *pix = &f->fmt.pix; + struct v4l2_format cam_f = *f; + struct v4l2_pix_format *cam_pix = &cam_f.fmt.pix; struct v4l2_subdev *sd = soc_camera_to_subdev(icd); + struct device *dev = icd->dev.parent; __u32 pixfmt = pix->pixelformat; const struct soc_camera_format_xlate *xlate; - unsigned int width = pix->width, height = pix->height, tmp_w, tmp_h; - u16 vscale, hscale; - int ret, is_interlaced; + struct v4l2_crop cam_crop; + struct v4l2_rect *cam_rect = &cam_crop.c, cam_subrect, ceu_rect; + unsigned int scale_cam_h, scale_cam_v; + u16 scale_v, scale_h; + int ret; + bool is_interlaced, image_mode; switch (pix->field) { case V4L2_FIELD_INTERLACED: - is_interlaced = 1; + is_interlaced = true; break; case V4L2_FIELD_ANY: default: pix->field = V4L2_FIELD_NONE; /* fall-through */ case V4L2_FIELD_NONE: - is_interlaced = 0; + is_interlaced = false; break; } xlate = soc_camera_xlate_by_fourcc(icd, pixfmt); if (!xlate) { - dev_warn(icd->dev.parent, "Format %x not found\n", pixfmt); + dev_warn(dev, "Format %x not found\n", pixfmt); return -EINVAL; } - pix->pixelformat = xlate->cam_fmt->fourcc; - ret = v4l2_subdev_call(sd, video, s_fmt, f); - pix->pixelformat = pixfmt; - dev_dbg(icd->dev.parent, - "Camera %d fmt %ux%u, requested %ux%u, max %ux%u\n", - ret, pix->width, pix->height, width, height, - icd->rect_max.width, icd->rect_max.height); + /* 1. Calculate current camera scales. */ + cam_crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + + ret = client_g_rect(sd, cam_rect); + if (ret < 0) + return ret; + + ret = get_camera_scales(sd, cam_rect, &scale_cam_h, &scale_cam_v); + if (ret < 0) + return ret; + + dev_geo(dev, "1: camera scales %u:%u\n", scale_cam_h, scale_cam_v); + + /* + * 2. Calculate "effective" input crop (sensor subwindow) - CEU crop + * scaled back at current camera scales onto input window. + */ + ret = get_camera_subwin(icd, &cam_subrect, scale_cam_h, scale_cam_v); if (ret < 0) return ret; + dev_geo(dev, "2: subwin %ux%u@%u:%u\n", + cam_subrect.width, cam_subrect.height, + cam_subrect.left, cam_subrect.top); + + /* + * 3. Calculate new combined scales from "effective" input window to + * requested user window. + */ + scale_h = calc_generic_scale(cam_subrect.width, pix->width); + scale_v = calc_generic_scale(cam_subrect.height, pix->height); + + dev_geo(dev, "3: scales %u:%u\n", scale_h, scale_v); + + /* + * 4. Calculate camera output window by applying combined scales to real + * input window. + */ + cam_pix->width = scale_down(cam_rect->width, scale_h); + cam_pix->height = scale_down(cam_rect->height, scale_v); + cam_pix->pixelformat = xlate->cam_fmt->fourcc; + switch (pixfmt) { case V4L2_PIX_FMT_NV12: case V4L2_PIX_FMT_NV21: case V4L2_PIX_FMT_NV16: case V4L2_PIX_FMT_NV61: - pcdev->image_mode = 1; + image_mode = true; break; default: - pcdev->image_mode = 0; + image_mode = false; } - if ((abs(width - pix->width) < 4 && abs(height - pix->height) < 4) || - !pcdev->image_mode || is_interlaced) { - hscale = 0; - vscale = 0; - goto out; - } + dev_geo(dev, "4: camera output %ux%u\n", + cam_pix->width, cam_pix->height); - /* Camera set a format, but geometry is not precise, try to improve */ - /* - * FIXME: when soc-camera is converted to implement traditional S_FMT - * and S_CROP semantics, replace CEU limits with camera maxima - */ - tmp_w = pix->width; - tmp_h = pix->height; - while ((width > tmp_w || height > tmp_h) && - tmp_w < 2560 && tmp_h < 1920) { - tmp_w = min(2 * tmp_w, (__u32)2560); - tmp_h = min(2 * tmp_h, (__u32)1920); - pix->width = tmp_w; - pix->height = tmp_h; - pix->pixelformat = xlate->cam_fmt->fourcc; - ret = v4l2_subdev_call(sd, video, s_fmt, f); - pix->pixelformat = pixfmt; - dev_dbg(icd->dev.parent, "Camera scaled to %ux%u\n", - pix->width, pix->height); - if (ret < 0) { - /* This shouldn't happen */ - dev_err(icd->dev.parent, - "Client failed to set format: %d\n", ret); - return ret; - } - } + /* 5. - 9. */ + ret = client_scale(icd, cam_rect, &cam_subrect, &ceu_rect, &cam_f, + image_mode && !is_interlaced); + + dev_geo(dev, "5-9: client scale %d\n", ret); + + /* Done with the camera. Now see if we can improve the result */ + + dev_dbg(dev, "Camera %d fmt %ux%u, requested %ux%u\n", + ret, cam_pix->width, cam_pix->height, pix->width, pix->height); + if (ret < 0) + return ret; + + /* 10. Use CEU scaling to scale to the requested user window. */ /* We cannot scale up */ - if (width > pix->width) - width = pix->width; + if (pix->width > cam_pix->width) + pix->width = cam_pix->width; + if (pix->width > ceu_rect.width) + pix->width = ceu_rect.width; - if (height > pix->height) - height = pix->height; + if (pix->height > cam_pix->height) + pix->height = cam_pix->height; + if (pix->height > ceu_rect.height) + pix->height = ceu_rect.height; /* Let's rock: scale pix->{width x height} down to width x height */ - hscale = calc_scale(pix->width, &width); - vscale = calc_scale(pix->height, &height); + scale_h = calc_scale(ceu_rect.width, &pix->width); + scale_v = calc_scale(ceu_rect.height, &pix->height); - dev_dbg(icd->dev.parent, "W: %u : 0x%x = %u, H: %u : 0x%x = %u\n", - pix->width, hscale, width, pix->height, vscale, height); + dev_geo(dev, "10: W: %u : 0x%x = %u, H: %u : 0x%x = %u\n", + ceu_rect.width, scale_h, pix->width, + ceu_rect.height, scale_v, pix->height); -out: - pcdev->cflcr = hscale | (vscale << 16); + pcdev->cflcr = scale_h | (scale_v << 16); icd->buswidth = xlate->buswidth; icd->current_fmt = xlate->host_fmt; cam->camera_fmt = xlate->cam_fmt; - cam->camera_rect.width = pix->width; - cam->camera_rect.height = pix->height; - - icd->rect_max.left = size_dst(cam->camera_max.left, hscale); - icd->rect_max.width = size_dst(cam->camera_max.width, hscale); - icd->rect_max.top = size_dst(cam->camera_max.top, vscale); - icd->rect_max.height = size_dst(cam->camera_max.height, vscale); - - icd->rect_current.left = icd->rect_max.left; - icd->rect_current.top = icd->rect_max.top; + cam->ceu_rect = ceu_rect; pcdev->is_interlaced = is_interlaced; - - pix->width = width; - pix->height = height; + pcdev->image_mode = image_mode; return 0; } diff --git a/linux/drivers/media/video/soc_camera.c b/linux/drivers/media/video/soc_camera.c index 6145846f7..2290118fb 100644 --- a/linux/drivers/media/video/soc_camera.c +++ b/linux/drivers/media/video/soc_camera.c @@ -279,6 +279,9 @@ static void soc_camera_free_user_formats(struct soc_camera_device *icd) icd->user_formats = NULL; } +#define pixfmtstr(x) (x) & 0xff, ((x) >> 8) & 0xff, ((x) >> 16) & 0xff, \ + ((x) >> 24) & 0xff + /* Called with .vb_lock held */ static int soc_camera_set_fmt(struct soc_camera_file *icf, struct v4l2_format *f) @@ -288,6 +291,9 @@ static int soc_camera_set_fmt(struct soc_camera_file *icf, struct v4l2_pix_format *pix = &f->fmt.pix; int ret; + dev_dbg(&icd->dev, "S_FMT(%c%c%c%c, %ux%u)\n", + pixfmtstr(pix->pixelformat), pix->width, pix->height); + /* We always call try_fmt() before set_fmt() or set_crop() */ ret = ici->ops->try_fmt(icd, f); if (ret < 0) @@ -303,17 +309,17 @@ static int soc_camera_set_fmt(struct soc_camera_file *icf, return -EINVAL; } - icd->rect_current.width = pix->width; - icd->rect_current.height = pix->height; - icf->vb_vidq.field = - icd->field = pix->field; + icd->user_width = pix->width; + icd->user_height = pix->height; + icf->vb_vidq.field = + icd->field = pix->field; if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) dev_warn(&icd->dev, "Attention! Wrong buf-type %d\n", f->type); dev_dbg(&icd->dev, "set width: %d height: %d\n", - icd->rect_current.width, icd->rect_current.height); + icd->user_width, icd->user_height); /* set physical bus parameters */ return ici->ops->set_bus_param(icd, pix->pixelformat); @@ -356,8 +362,8 @@ static int soc_camera_open(struct file *file) struct v4l2_format f = { .type = V4L2_BUF_TYPE_VIDEO_CAPTURE, .fmt.pix = { - .width = icd->rect_current.width, - .height = icd->rect_current.height, + .width = icd->user_width, + .height = icd->user_height, .field = icd->field, .pixelformat = icd->current_fmt->fourcc, .colorspace = icd->current_fmt->colorspace, @@ -558,8 +564,8 @@ static int soc_camera_g_fmt_vid_cap(struct file *file, void *priv, WARN_ON(priv != file->private_data); - pix->width = icd->rect_current.width; - pix->height = icd->rect_current.height; + pix->width = icd->user_width; + pix->height = icd->user_height; pix->field = icf->vb_vidq.field; pix->pixelformat = icd->current_fmt->fourcc; pix->bytesperline = pix->width * @@ -723,17 +729,9 @@ static int soc_camera_cropcap(struct file *file, void *fh, { struct soc_camera_file *icf = file->private_data; struct soc_camera_device *icd = icf->icd; + struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); - a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - a->bounds = icd->rect_max; - a->defrect.left = icd->rect_max.left; - a->defrect.top = icd->rect_max.top; - a->defrect.width = DEFAULT_WIDTH; - a->defrect.height = DEFAULT_HEIGHT; - a->pixelaspect.numerator = 1; - a->pixelaspect.denominator = 1; - - return 0; + return ici->ops->cropcap(icd, a); } static int soc_camera_g_crop(struct file *file, void *fh, @@ -741,11 +739,14 @@ static int soc_camera_g_crop(struct file *file, void *fh, { struct soc_camera_file *icf = file->private_data; struct soc_camera_device *icd = icf->icd; + struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); + int ret; - a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - a->c = icd->rect_current; + mutex_lock(&icf->vb_vidq.vb_lock); + ret = ici->ops->get_crop(icd, a); + mutex_unlock(&icf->vb_vidq.vb_lock); - return 0; + return ret; } /* @@ -760,49 +761,33 @@ static int soc_camera_s_crop(struct file *file, void *fh, struct soc_camera_file *icf = file->private_data; struct soc_camera_device *icd = icf->icd; struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); - struct v4l2_rect rect = a->c; + struct v4l2_rect *rect = &a->c; + struct v4l2_crop current_crop; int ret; if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) return -EINVAL; + dev_dbg(&icd->dev, "S_CROP(%ux%u@%u:%u)\n", + rect->width, rect->height, rect->left, rect->top); + /* Cropping is allowed during a running capture, guard consistency */ mutex_lock(&icf->vb_vidq.vb_lock); + /* If get_crop fails, we'll let host and / or client drivers decide */ + ret = ici->ops->get_crop(icd, ¤t_crop); + /* Prohibit window size change with initialised buffers */ - if (icf->vb_vidq.bufs[0] && (rect.width != icd->rect_current.width || - rect.height != icd->rect_current.height)) { + if (icf->vb_vidq.bufs[0] && !ret && + (a->c.width != current_crop.c.width || + a->c.height != current_crop.c.height)) { dev_err(&icd->dev, "S_CROP denied: queue initialised and sizes differ\n"); ret = -EBUSY; - goto unlock; + } else { + ret = ici->ops->set_crop(icd, a); } - if (rect.width > icd->rect_max.width) - rect.width = icd->rect_max.width; - - if (rect.width < icd->width_min) - rect.width = icd->width_min; - - if (rect.height > icd->rect_max.height) - rect.height = icd->rect_max.height; - - if (rect.height < icd->height_min) - rect.height = icd->height_min; - - if (rect.width + rect.left > icd->rect_max.width + icd->rect_max.left) - rect.left = icd->rect_max.width + icd->rect_max.left - - rect.width; - - if (rect.height + rect.top > icd->rect_max.height + icd->rect_max.top) - rect.top = icd->rect_max.height + icd->rect_max.top - - rect.height; - - ret = ici->ops->set_crop(icd, a); - if (!ret) - icd->rect_current = rect; - -unlock: mutex_unlock(&icf->vb_vidq.vb_lock); return ret; @@ -927,6 +912,8 @@ static int soc_camera_probe(struct device *dev) struct soc_camera_host *ici = to_soc_camera_host(dev->parent); struct soc_camera_link *icl = to_soc_camera_link(icd); struct device *control = NULL; + struct v4l2_subdev *sd; + struct v4l2_format f = {.type = V4L2_BUF_TYPE_VIDEO_CAPTURE}; int ret; dev_info(dev, "Probing %s\n", dev_name(dev)); @@ -983,7 +970,6 @@ static int soc_camera_probe(struct device *dev) if (ret < 0) goto eiufmt; - icd->rect_current = icd->rect_max; icd->field = V4L2_FIELD_ANY; /* ..._video_start() will create a device node, so we have to protect */ @@ -993,9 +979,15 @@ static int soc_camera_probe(struct device *dev) if (ret < 0) goto evidstart; + /* Try to improve our guess of a reasonable window format */ + sd = soc_camera_to_subdev(icd); + if (!v4l2_subdev_call(sd, video, g_fmt, &f)) { + icd->user_width = f.fmt.pix.width; + icd->user_height = f.fmt.pix.height; + } + /* Do we have to sysfs_remove_link() before device_unregister()? */ - if (to_soc_camera_control(icd) && - sysfs_create_link(&icd->dev.kobj, &to_soc_camera_control(icd)->kobj, + if (sysfs_create_link(&icd->dev.kobj, &to_soc_camera_control(icd)->kobj, "control")) dev_warn(&icd->dev, "Failed creating the control symlink\n"); @@ -1104,6 +1096,25 @@ static void dummy_release(struct device *dev) { } +static int default_cropcap(struct soc_camera_device *icd, + struct v4l2_cropcap *a) +{ + struct v4l2_subdev *sd = soc_camera_to_subdev(icd); + return v4l2_subdev_call(sd, video, cropcap, a); +} + +static int default_g_crop(struct soc_camera_device *icd, struct v4l2_crop *a) +{ + struct v4l2_subdev *sd = soc_camera_to_subdev(icd); + return v4l2_subdev_call(sd, video, g_crop, a); +} + +static int default_s_crop(struct soc_camera_device *icd, struct v4l2_crop *a) +{ + struct v4l2_subdev *sd = soc_camera_to_subdev(icd); + return v4l2_subdev_call(sd, video, s_crop, a); +} + int soc_camera_host_register(struct soc_camera_host *ici) { struct soc_camera_host *ix; @@ -1112,7 +1123,6 @@ int soc_camera_host_register(struct soc_camera_host *ici) if (!ici || !ici->ops || !ici->ops->try_fmt || !ici->ops->set_fmt || - !ici->ops->set_crop || !ici->ops->set_bus_param || !ici->ops->querycap || !ici->ops->init_videobuf || @@ -1123,6 +1133,13 @@ int soc_camera_host_register(struct soc_camera_host *ici) !ici->v4l2_dev.dev) return -EINVAL; + if (!ici->ops->set_crop) + ici->ops->set_crop = default_s_crop; + if (!ici->ops->get_crop) + ici->ops->get_crop = default_g_crop; + if (!ici->ops->cropcap) + ici->ops->cropcap = default_cropcap; + mutex_lock(&list_lock); list_for_each_entry(ix, &hosts, list) { if (ix->nr == ici->nr) { @@ -1322,6 +1339,9 @@ static int __devinit soc_camera_pdrv_probe(struct platform_device *pdev) if (ret < 0) goto escdevreg; + icd->user_width = DEFAULT_WIDTH; + icd->user_height = DEFAULT_HEIGHT; + return 0; escdevreg: diff --git a/linux/drivers/media/video/soc_camera_platform.c b/linux/drivers/media/video/soc_camera_platform.c index aec2cadbd..3825c3581 100644 --- a/linux/drivers/media/video/soc_camera_platform.c +++ b/linux/drivers/media/video/soc_camera_platform.c @@ -127,10 +127,6 @@ static int soc_camera_platform_probe(struct platform_device *pdev) /* Set the control device reference */ dev_set_drvdata(&icd->dev, &pdev->dev); - icd->width_min = 0; - icd->rect_max.width = p->format.width; - icd->height_min = 0; - icd->rect_max.height = p->format.height; icd->y_skip_top = 0; icd->ops = &soc_camera_platform_ops; diff --git a/linux/drivers/media/video/tw9910.c b/linux/drivers/media/video/tw9910.c index e8c6cf119..3ea12a66f 100644 --- a/linux/drivers/media/video/tw9910.c +++ b/linux/drivers/media/video/tw9910.c @@ -715,8 +715,88 @@ tw9910_set_fmt_error: return ret; } +static int tw9910_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) +{ + struct i2c_client *client = sd->priv; + struct tw9910_priv *priv = to_tw9910(client); + + if (!priv->scale) { + int ret; + struct v4l2_crop crop = { + .c = { + .left = 0, + .top = 0, + .width = 640, + .height = 480, + }, + }; + ret = tw9910_s_crop(sd, &crop); + if (ret < 0) + return ret; + } + + a->c.left = 0; + a->c.top = 0; + a->c.width = priv->scale->width; + a->c.height = priv->scale->height; + a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + + return 0; +} + +static int tw9910_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a) +{ + a->bounds.left = 0; + a->bounds.top = 0; + a->bounds.width = 768; + a->bounds.height = 576; + a->defrect.left = 0; + a->defrect.top = 0; + a->defrect.width = 640; + a->defrect.height = 480; + a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + a->pixelaspect.numerator = 1; + a->pixelaspect.denominator = 1; + + return 0; +} + +static int tw9910_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) +{ + struct i2c_client *client = sd->priv; + struct tw9910_priv *priv = to_tw9910(client); + struct v4l2_pix_format *pix = &f->fmt.pix; + + if (!priv->scale) { + int ret; + struct v4l2_crop crop = { + .c = { + .left = 0, + .top = 0, + .width = 640, + .height = 480, + }, + }; + ret = tw9910_s_crop(sd, &crop); + if (ret < 0) + return ret; + } + + f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + + pix->width = priv->scale->width; + pix->height = priv->scale->height; + pix->pixelformat = V4L2_PIX_FMT_VYUY; + pix->colorspace = V4L2_COLORSPACE_SMPTE170M; + pix->field = V4L2_FIELD_INTERLACED; + + return 0; +} + static int tw9910_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) { + struct i2c_client *client = sd->priv; + struct tw9910_priv *priv = to_tw9910(client); struct v4l2_pix_format *pix = &f->fmt.pix; /* See tw9910_s_crop() - no proper cropping support */ struct v4l2_crop a = { @@ -741,8 +821,8 @@ static int tw9910_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) ret = tw9910_s_crop(sd, &a); if (!ret) { - pix->width = a.c.width; - pix->height = a.c.height; + pix->width = priv->scale->width; + pix->height = priv->scale->height; } return ret; } @@ -838,8 +918,11 @@ static struct v4l2_subdev_core_ops tw9910_subdev_core_ops = { static struct v4l2_subdev_video_ops tw9910_subdev_video_ops = { .s_stream = tw9910_s_stream, + .g_fmt = tw9910_g_fmt, .s_fmt = tw9910_s_fmt, .try_fmt = tw9910_try_fmt, + .cropcap = tw9910_cropcap, + .g_crop = tw9910_g_crop, .s_crop = tw9910_s_crop, }; @@ -852,20 +935,6 @@ static struct v4l2_subdev_ops tw9910_subdev_ops = { * i2c_driver function */ -/* This is called during probe, so, setting rect_max is Ok here: scale == 1 */ -static void limit_to_scale(struct soc_camera_device *icd, - const struct tw9910_scale_ctrl *scale) -{ - if (scale->width > icd->rect_max.width) - icd->rect_max.width = scale->width; - if (scale->width < icd->width_min) - icd->width_min = scale->width; - if (scale->height > icd->rect_max.height) - icd->rect_max.height = scale->height; - if (scale->height < icd->height_min) - icd->height_min = scale->height; -} - #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26) static int tw9910_probe(struct i2c_client *client) #else @@ -880,8 +949,7 @@ static int tw9910_probe(struct i2c_client *client, struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); struct soc_camera_link *icl; - const struct tw9910_scale_ctrl *scale; - int i, ret; + int ret; if (!icd) { dev_err(&client->dev, "TW9910: missing soc-camera data!\n"); @@ -912,22 +980,6 @@ static int tw9910_probe(struct i2c_client *client, icd->ops = &tw9910_ops; icd->iface = info->link.bus_id; - /* - * set width and height - */ - icd->rect_max.width = tw9910_ntsc_scales[0].width; /* set default */ - icd->width_min = tw9910_ntsc_scales[0].width; - icd->rect_max.height = tw9910_ntsc_scales[0].height; - icd->height_min = tw9910_ntsc_scales[0].height; - - scale = tw9910_ntsc_scales; - for (i = 0; i < ARRAY_SIZE(tw9910_ntsc_scales); i++) - limit_to_scale(icd, scale + i); - - scale = tw9910_pal_scales; - for (i = 0; i < ARRAY_SIZE(tw9910_pal_scales); i++) - limit_to_scale(icd, scale + i); - ret = tw9910_video_probe(icd, client); if (ret) { icd->ops = NULL; -- cgit v1.2.3 From 243028968448b7efc378c94fb7b5f285ab01fbba Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Tue, 25 Aug 2009 16:53:23 +0200 Subject: soc-camera: remove .init() and .release() methods from struct soc_camera_ops From: Guennadi Liakhovetski Remove unneeded soc-camera operations, this also makes the soc-camera API to v4l2 subdevices thinner. Signed-off-by: Guennadi Liakhovetski Priority: low --- drivers/media/video/mt9m001.c | 22 ++++++-------------- drivers/media/video/mt9m111.c | 40 +++++++------------------------------ drivers/media/video/mt9t031.c | 23 +++++---------------- drivers/media/video/mt9v022.c | 8 ++++-- drivers/media/video/soc_camera.c | 11 ---------- include/media/soc_camera.h | 4 --- 6 files changed, 26 insertions(+), 82 deletions(-) --- linux/drivers/media/video/mt9m001.c | 22 ++++++------------- linux/drivers/media/video/mt9m111.c | 40 +++++++--------------------------- linux/drivers/media/video/mt9t031.c | 23 +++++-------------- linux/drivers/media/video/mt9v022.c | 8 ++++--- linux/drivers/media/video/soc_camera.c | 11 ---------- 5 files changed, 26 insertions(+), 78 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/mt9m001.c b/linux/drivers/media/video/mt9m001.c index 3fcf57118..9da7789e6 100644 --- a/linux/drivers/media/video/mt9m001.c +++ b/linux/drivers/media/video/mt9m001.c @@ -122,9 +122,8 @@ static int reg_clear(struct i2c_client *client, const u8 reg, return reg_write(client, reg, ret & ~data); } -static int mt9m001_init(struct soc_camera_device *icd) +static int mt9m001_init(struct i2c_client *client) { - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); int ret; dev_dbg(&client->dev, "%s\n", __func__); @@ -144,16 +143,6 @@ static int mt9m001_init(struct soc_camera_device *icd) return ret; } -static int mt9m001_release(struct soc_camera_device *icd) -{ - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); - - /* Disable the chip */ - reg_write(client, MT9M001_OUTPUT_CONTROL, 0); - - return 0; -} - static int mt9m001_s_stream(struct v4l2_subdev *sd, int enable) { struct i2c_client *client = sd->priv; @@ -446,8 +435,6 @@ static const struct v4l2_queryctrl mt9m001_controls[] = { }; static struct soc_camera_ops mt9m001_ops = { - .init = mt9m001_init, - .release = mt9m001_release, .set_bus_param = mt9m001_set_bus_param, .query_bus_param = mt9m001_query_bus_param, .controls = mt9m001_controls, @@ -581,6 +568,7 @@ static int mt9m001_video_probe(struct soc_camera_device *icd, struct soc_camera_link *icl = to_soc_camera_link(icd); s32 data; unsigned long flags; + int ret; /* We must have a parent by now. And it cannot be a wrong one. * So this entire test is completely redundant. */ @@ -637,7 +625,11 @@ static int mt9m001_video_probe(struct soc_camera_device *icd, dev_info(&client->dev, "Detected a MT9M001 chip ID %x (%s)\n", data, data == 0x8431 ? "C12STM" : "C12ST"); - return 0; + ret = mt9m001_init(client); + if (ret < 0) + dev_err(&client->dev, "Failed to initialise the camera\n"); + + return ret; } static void mt9m001_video_remove(struct soc_camera_device *icd) diff --git a/linux/drivers/media/video/mt9m111.c b/linux/drivers/media/video/mt9m111.c index 905054e08..957fe3e4f 100644 --- a/linux/drivers/media/video/mt9m111.c +++ b/linux/drivers/media/video/mt9m111.c @@ -672,13 +672,9 @@ static const struct v4l2_queryctrl mt9m111_controls[] = { }; static int mt9m111_resume(struct soc_camera_device *icd); -static int mt9m111_init(struct soc_camera_device *icd); -static int mt9m111_release(struct soc_camera_device *icd); static struct soc_camera_ops mt9m111_ops = { - .init = mt9m111_init, .resume = mt9m111_resume, - .release = mt9m111_release, .query_bus_param = mt9m111_query_bus_param, .set_bus_param = mt9m111_set_bus_param, .controls = mt9m111_controls, @@ -880,9 +876,8 @@ static int mt9m111_resume(struct soc_camera_device *icd) return ret; } -static int mt9m111_init(struct soc_camera_device *icd) +static int mt9m111_init(struct i2c_client *client) { - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); struct mt9m111 *mt9m111 = to_mt9m111(client); int ret; @@ -899,22 +894,6 @@ static int mt9m111_init(struct soc_camera_device *icd) return ret; } -static int mt9m111_release(struct soc_camera_device *icd) -{ - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); - struct mt9m111 *mt9m111 = to_mt9m111(client); - int ret; - - ret = reg_clear(RESET, MT9M111_RESET_CHIP_ENABLE); - if (!ret) - mt9m111->powered = 0; - - if (ret < 0) - dev_err(&client->dev, "mt9m11x release failed: %d\n", ret); - - return ret; -} - /* * Interface active, can use i2c. If it fails, it can indeed mean, that * this wasn't our capture interface, so, we wait for the right one @@ -934,10 +913,13 @@ static int mt9m111_video_probe(struct soc_camera_device *icd, to_soc_camera_host(icd->dev.parent)->nr != icd->iface) return -ENODEV; - ret = mt9m111_enable(client); - if (ret) - goto ei2c; - ret = mt9m111_reset(client); + mt9m111->autoexposure = 1; + mt9m111->autowhitebalance = 1; + + mt9m111->swap_rgb_even_odd = 1; + mt9m111->swap_rgb_red_blue = 1; + + ret = mt9m111_init(client); if (ret) goto ei2c; @@ -962,12 +944,6 @@ static int mt9m111_video_probe(struct soc_camera_device *icd, dev_info(&client->dev, "Detected a MT9M11x chip ID %x\n", data); - mt9m111->autoexposure = 1; - mt9m111->autowhitebalance = 1; - - mt9m111->swap_rgb_even_odd = 1; - mt9m111->swap_rgb_red_blue = 1; - ei2c: return ret; } diff --git a/linux/drivers/media/video/mt9t031.c b/linux/drivers/media/video/mt9t031.c index 30d4aaf81..5d9de61ee 100644 --- a/linux/drivers/media/video/mt9t031.c +++ b/linux/drivers/media/video/mt9t031.c @@ -163,20 +163,6 @@ static int mt9t031_disable(struct i2c_client *client) return 0; } -static int mt9t031_init(struct soc_camera_device *icd) -{ - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); - - return mt9t031_idle(client); -} - -static int mt9t031_release(struct soc_camera_device *icd) -{ - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); - - return mt9t031_disable(client); -} - static int mt9t031_s_stream(struct v4l2_subdev *sd, int enable) { struct i2c_client *client = sd->priv; @@ -539,8 +525,6 @@ static const struct v4l2_queryctrl mt9t031_controls[] = { }; static struct soc_camera_ops mt9t031_ops = { - .init = mt9t031_init, - .release = mt9t031_release, .set_bus_param = mt9t031_set_bus_param, .query_bus_param = mt9t031_query_bus_param, .controls = mt9t031_controls, @@ -689,6 +673,7 @@ static int mt9t031_video_probe(struct i2c_client *client) struct soc_camera_device *icd = client->dev.platform_data; struct mt9t031 *mt9t031 = to_mt9t031(client); s32 data; + int ret; /* Enable the chip */ data = reg_write(client, MT9T031_CHIP_ENABLE, 1); @@ -711,7 +696,11 @@ static int mt9t031_video_probe(struct i2c_client *client) dev_info(&client->dev, "Detected a MT9T031 chip ID %x\n", data); - return 0; + ret = mt9t031_idle(client); + if (ret < 0) + dev_err(&client->dev, "Failed to initialise the camera\n"); + + return ret; } static struct v4l2_subdev_core_ops mt9t031_subdev_core_ops = { diff --git a/linux/drivers/media/video/mt9v022.c b/linux/drivers/media/video/mt9v022.c index 3153fd5d2..2d5f7d121 100644 --- a/linux/drivers/media/video/mt9v022.c +++ b/linux/drivers/media/video/mt9v022.c @@ -138,9 +138,8 @@ static int reg_clear(struct i2c_client *client, const u8 reg, return reg_write(client, reg, ret & ~data); } -static int mt9v022_init(struct soc_camera_device *icd) +static int mt9v022_init(struct i2c_client *client) { - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); struct mt9v022 *mt9v022 = to_mt9v022(client); int ret; @@ -532,7 +531,6 @@ static const struct v4l2_queryctrl mt9v022_controls[] = { }; static struct soc_camera_ops mt9v022_ops = { - .init = mt9v022_init, .set_bus_param = mt9v022_set_bus_param, .query_bus_param = mt9v022_query_bus_param, .controls = mt9v022_controls, @@ -751,6 +749,10 @@ static int mt9v022_video_probe(struct soc_camera_device *icd, data, mt9v022->model == V4L2_IDENT_MT9V022IX7ATM ? "monochrome" : "colour"); + ret = mt9v022_init(client); + if (ret < 0) + dev_err(&client->dev, "Failed to initialise the camera\n"); + ei2c: return ret; } diff --git a/linux/drivers/media/video/soc_camera.c b/linux/drivers/media/video/soc_camera.c index 2290118fb..4e620978f 100644 --- a/linux/drivers/media/video/soc_camera.c +++ b/linux/drivers/media/video/soc_camera.c @@ -386,12 +386,6 @@ static int soc_camera_open(struct file *file) goto eiciadd; } - if (icd->ops->init) { - ret = icd->ops->init(icd); - if (ret < 0) - goto einit; - } - /* Try to configure with default parameters */ ret = soc_camera_set_fmt(icf, &f); if (ret < 0) @@ -412,9 +406,6 @@ static int soc_camera_open(struct file *file) * and use_count == 1 */ esfmt: - if (icd->ops->release) - icd->ops->release(icd); -einit: ici->ops->remove(icd); eiciadd: if (icl->power) @@ -439,8 +430,6 @@ static int soc_camera_close(struct file *file) if (!icd->use_count) { struct soc_camera_link *icl = to_soc_camera_link(icd); - if (icd->ops->release) - icd->ops->release(icd); ici->ops->remove(icd); if (icl->power) icl->power(icd->pdev, 0); -- cgit v1.2.3 From 0ac616e3dc8591b81ebfcb8a4d10b936c82fdeab Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Tue, 25 Aug 2009 16:53:23 +0200 Subject: soc-camera: remove .gain and .exposure struct soc_camera_device members From: Guennadi Liakhovetski This makes the soc-camera interface for V4L2 subdevices thinner yet. Handle gain and exposure internally in each driver just like all other controls. Signed-off-by: Guennadi Liakhovetski Priority: low --- drivers/media/video/mt9m001.c | 43 ++++++++++++++++++++++++------------- drivers/media/video/mt9m111.c | 20 ++++++++++++++--- drivers/media/video/mt9t031.c | 37 +++++++++++++++++++++----------- drivers/media/video/mt9v022.c | 43 ++++++++++++++++++++++++++++--------- drivers/media/video/soc_camera.c | 19 ---------------- include/media/soc_camera.h | 2 - 6 files changed, 100 insertions(+), 64 deletions(-) --- linux/drivers/media/video/mt9m001.c | 43 ++++++++++++++++++++++------------ linux/drivers/media/video/mt9m111.c | 20 ++++++++++++---- linux/drivers/media/video/mt9t031.c | 37 +++++++++++++++++++---------- linux/drivers/media/video/mt9v022.c | 43 +++++++++++++++++++++++++--------- linux/drivers/media/video/soc_camera.c | 19 --------------- 5 files changed, 100 insertions(+), 62 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/mt9m001.c b/linux/drivers/media/video/mt9m001.c index 9da7789e6..93052047c 100644 --- a/linux/drivers/media/video/mt9m001.c +++ b/linux/drivers/media/video/mt9m001.c @@ -80,6 +80,8 @@ struct mt9m001 { struct v4l2_rect rect; /* Sensor window */ __u32 fourcc; int model; /* V4L2_IDENT_MT9M001* codes from v4l2-chip-ident.h */ + unsigned int gain; + unsigned int exposure; unsigned char autoexposure; }; @@ -129,8 +131,8 @@ static int mt9m001_init(struct i2c_client *client) dev_dbg(&client->dev, "%s\n", __func__); /* - * We don't know, whether platform provides reset, - * issue a soft reset too + * We don't know, whether platform provides reset, issue a soft reset + * too. This returns all registers to their default values. */ ret = reg_write(client, MT9M001_RESET, 1); if (!ret) @@ -200,6 +202,7 @@ static int mt9m001_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) struct soc_camera_device *icd = client->dev.platform_data; int ret; const u16 hblank = 9, vblank = 25; + unsigned int total_h; if (mt9m001->fourcc == V4L2_PIX_FMT_SBGGR8 || mt9m001->fourcc == V4L2_PIX_FMT_SBGGR16) @@ -219,6 +222,8 @@ static int mt9m001_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) soc_camera_limit_side(&rect.top, &rect.height, MT9M001_ROW_SKIP, MT9M001_MIN_HEIGHT, MT9M001_MAX_HEIGHT); + total_h = rect.height + icd->y_skip_top + vblank; + /* Blanking and start values - default... */ ret = reg_write(client, MT9M001_HORIZONTAL_BLANKING, hblank); if (!ret) @@ -236,15 +241,13 @@ static int mt9m001_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) ret = reg_write(client, MT9M001_WINDOW_HEIGHT, rect.height + icd->y_skip_top - 1); if (!ret && mt9m001->autoexposure) { - ret = reg_write(client, MT9M001_SHUTTER_WIDTH, - rect.height + icd->y_skip_top + vblank); + ret = reg_write(client, MT9M001_SHUTTER_WIDTH, total_h); if (!ret) { const struct v4l2_queryctrl *qctrl = soc_camera_find_qctrl(icd->ops, V4L2_CID_EXPOSURE); - icd->exposure = (524 + (rect.height + icd->y_skip_top + - vblank - 1) * - (qctrl->maximum - qctrl->minimum)) / + mt9m001->exposure = (524 + (total_h - 1) * + (qctrl->maximum - qctrl->minimum)) / 1048 + qctrl->minimum; } } @@ -457,6 +460,12 @@ static int mt9m001_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) case V4L2_CID_EXPOSURE_AUTO: ctrl->value = mt9m001->autoexposure; break; + case V4L2_CID_GAIN: + ctrl->value = mt9m001->gain; + break; + case V4L2_CID_EXPOSURE: + ctrl->value = mt9m001->exposure; + break; } return 0; } @@ -518,7 +527,7 @@ static int mt9m001_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) } /* Success */ - icd->gain = ctrl->value; + mt9m001->gain = ctrl->value; break; case V4L2_CID_EXPOSURE: /* mt9m001 has maximum == default */ @@ -535,21 +544,21 @@ static int mt9m001_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) shutter); if (reg_write(client, MT9M001_SHUTTER_WIDTH, shutter) < 0) return -EIO; - icd->exposure = ctrl->value; + mt9m001->exposure = ctrl->value; mt9m001->autoexposure = 0; } break; case V4L2_CID_EXPOSURE_AUTO: if (ctrl->value) { const u16 vblank = 25; + unsigned int total_h = mt9m001->rect.height + + icd->y_skip_top + vblank; if (reg_write(client, MT9M001_SHUTTER_WIDTH, - mt9m001->rect.height + - icd->y_skip_top + vblank) < 0) + total_h) < 0) return -EIO; qctrl = soc_camera_find_qctrl(icd->ops, V4L2_CID_EXPOSURE); - icd->exposure = (524 + (mt9m001->rect.height + - icd->y_skip_top + vblank - 1) * - (qctrl->maximum - qctrl->minimum)) / + mt9m001->exposure = (524 + (total_h - 1) * + (qctrl->maximum - qctrl->minimum)) / 1048 + qctrl->minimum; mt9m001->autoexposure = 1; } else @@ -629,6 +638,10 @@ static int mt9m001_video_probe(struct soc_camera_device *icd, if (ret < 0) dev_err(&client->dev, "Failed to initialise the camera\n"); + /* mt9m001_init() has reset the chip, returning registers to defaults */ + mt9m001->gain = 64; + mt9m001->exposure = 255; + return ret; } @@ -705,7 +718,7 @@ static int mt9m001_probe(struct i2c_client *client) /* Second stage probe - when a capture adapter is there */ icd->ops = &mt9m001_ops; - icd->y_skip_top = 1; + icd->y_skip_top = 0; mt9m001->rect.left = MT9M001_COLUMN_SKIP; mt9m001->rect.top = MT9M001_ROW_SKIP; diff --git a/linux/drivers/media/video/mt9m111.c b/linux/drivers/media/video/mt9m111.c index 957fe3e4f..9ad087132 100644 --- a/linux/drivers/media/video/mt9m111.c +++ b/linux/drivers/media/video/mt9m111.c @@ -153,6 +153,7 @@ struct mt9m111 { enum mt9m111_context context; struct v4l2_rect rect; u32 pixfmt; + unsigned int gain; unsigned char autoexposure; unsigned char datawidth; unsigned int powered:1; @@ -672,8 +673,10 @@ static const struct v4l2_queryctrl mt9m111_controls[] = { }; static int mt9m111_resume(struct soc_camera_device *icd); +static int mt9m111_suspend(struct soc_camera_device *icd, pm_message_t state); static struct soc_camera_ops mt9m111_ops = { + .suspend = mt9m111_suspend, .resume = mt9m111_resume, .query_bus_param = mt9m111_query_bus_param, .set_bus_param = mt9m111_set_bus_param, @@ -714,13 +717,13 @@ static int mt9m111_get_global_gain(struct i2c_client *client) static int mt9m111_set_global_gain(struct i2c_client *client, int gain) { - struct soc_camera_device *icd = client->dev.platform_data; + struct mt9m111 *mt9m111 = to_mt9m111(client); u16 val; if (gain > 63 * 2 * 2) return -EINVAL; - icd->gain = gain; + mt9m111->gain = gain; if ((gain >= 64 * 2) && (gain < 63 * 2 * 2)) val = (1 << 10) | (1 << 9) | (gain / 4); else if ((gain >= 64) && (gain < 64 * 2)) @@ -844,17 +847,26 @@ static int mt9m111_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) return ret; } +static int mt9m111_suspend(struct soc_camera_device *icd, pm_message_t state) +{ + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct mt9m111 *mt9m111 = to_mt9m111(client); + + mt9m111->gain = mt9m111_get_global_gain(client); + + return 0; +} + static int mt9m111_restore_state(struct i2c_client *client) { struct mt9m111 *mt9m111 = to_mt9m111(client); - struct soc_camera_device *icd = client->dev.platform_data; mt9m111_set_context(client, mt9m111->context); mt9m111_set_pixfmt(client, mt9m111->pixfmt); mt9m111_setup_rect(client, &mt9m111->rect); mt9m111_set_flip(client, mt9m111->hflip, MT9M111_RMB_MIRROR_COLS); mt9m111_set_flip(client, mt9m111->vflip, MT9M111_RMB_MIRROR_ROWS); - mt9m111_set_global_gain(client, icd->gain); + mt9m111_set_global_gain(client, mt9m111->gain); mt9m111_set_autoexposure(client, mt9m111->autoexposure); mt9m111_set_autowhitebalance(client, mt9m111->autowhitebalance); return 0; diff --git a/linux/drivers/media/video/mt9t031.c b/linux/drivers/media/video/mt9t031.c index 5d9de61ee..bf3b54f9f 100644 --- a/linux/drivers/media/video/mt9t031.c +++ b/linux/drivers/media/video/mt9t031.c @@ -73,6 +73,8 @@ struct mt9t031 { int model; /* V4L2_IDENT_MT9T031* codes from v4l2-chip-ident.h */ u16 xskip; u16 yskip; + unsigned int gain; + unsigned int exposure; unsigned char autoexposure; }; @@ -301,16 +303,15 @@ static int mt9t031_set_params(struct soc_camera_device *icd, ret = reg_write(client, MT9T031_WINDOW_HEIGHT, rect->height + icd->y_skip_top - 1); if (ret >= 0 && mt9t031->autoexposure) { - ret = set_shutter(client, - rect->height + icd->y_skip_top + vblank); + unsigned int total_h = rect->height + icd->y_skip_top + vblank; + ret = set_shutter(client, total_h); if (ret >= 0) { const u32 shutter_max = MT9T031_MAX_HEIGHT + vblank; const struct v4l2_queryctrl *qctrl = soc_camera_find_qctrl(icd->ops, V4L2_CID_EXPOSURE); - icd->exposure = (shutter_max / 2 + (rect->height + - icd->y_skip_top + vblank - 1) * - (qctrl->maximum - qctrl->minimum)) / + mt9t031->exposure = (shutter_max / 2 + (total_h - 1) * + (qctrl->maximum - qctrl->minimum)) / shutter_max + qctrl->minimum; } } @@ -553,6 +554,12 @@ static int mt9t031_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) case V4L2_CID_EXPOSURE_AUTO: ctrl->value = mt9t031->autoexposure; break; + case V4L2_CID_GAIN: + ctrl->value = mt9t031->gain; + break; + case V4L2_CID_EXPOSURE: + ctrl->value = mt9t031->exposure; + break; } return 0; } @@ -624,7 +631,7 @@ static int mt9t031_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) } /* Success */ - icd->gain = ctrl->value; + mt9t031->gain = ctrl->value; break; case V4L2_CID_EXPOSURE: /* mt9t031 has maximum == default */ @@ -641,7 +648,7 @@ static int mt9t031_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) old, shutter); if (set_shutter(client, shutter) < 0) return -EIO; - icd->exposure = ctrl->value; + mt9t031->exposure = ctrl->value; mt9t031->autoexposure = 0; } break; @@ -649,14 +656,14 @@ static int mt9t031_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) if (ctrl->value) { const u16 vblank = MT9T031_VERTICAL_BLANK; const u32 shutter_max = MT9T031_MAX_HEIGHT + vblank; - if (set_shutter(client, mt9t031->rect.height + - icd->y_skip_top + vblank) < 0) + unsigned int total_h = mt9t031->rect.height + + icd->y_skip_top + vblank; + + if (set_shutter(client, total_h) < 0) return -EIO; qctrl = soc_camera_find_qctrl(icd->ops, V4L2_CID_EXPOSURE); - icd->exposure = (shutter_max / 2 + - (mt9t031->rect.height + - icd->y_skip_top + vblank - 1) * - (qctrl->maximum - qctrl->minimum)) / + mt9t031->exposure = (shutter_max / 2 + (total_h - 1) * + (qctrl->maximum - qctrl->minimum)) / shutter_max + qctrl->minimum; mt9t031->autoexposure = 1; } else @@ -700,6 +707,10 @@ static int mt9t031_video_probe(struct i2c_client *client) if (ret < 0) dev_err(&client->dev, "Failed to initialise the camera\n"); + /* mt9t031_idle() has reset the chip to default. */ + mt9t031->exposure = 255; + mt9t031->gain = 64; + return ret; } diff --git a/linux/drivers/media/video/mt9v022.c b/linux/drivers/media/video/mt9v022.c index 2d5f7d121..582fabcfd 100644 --- a/linux/drivers/media/video/mt9v022.c +++ b/linux/drivers/media/video/mt9v022.c @@ -45,7 +45,7 @@ MODULE_PARM_DESC(sensor_type, "Sensor type: \"colour\" or \"monochrome\""); #define MT9V022_PIXEL_OPERATION_MODE 0x0f #define MT9V022_LED_OUT_CONTROL 0x1b #define MT9V022_ADC_MODE_CONTROL 0x1c -#define MT9V022_ANALOG_GAIN 0x34 +#define MT9V022_ANALOG_GAIN 0x35 #define MT9V022_BLACK_LEVEL_CALIB_CTRL 0x47 #define MT9V022_PIXCLK_FV_LV 0x74 #define MT9V022_DIGITAL_TEST_PATTERN 0x7f @@ -155,6 +155,10 @@ static int mt9v022_init(struct i2c_client *client) if (!ret) /* AEC, AGC on */ ret = reg_set(client, MT9V022_AEC_AGC_ENABLE, 0x3); + if (!ret) + ret = reg_write(client, MT9V022_ANALOG_GAIN, 16); + if (!ret) + ret = reg_write(client, MT9V022_TOTAL_SHUTTER_WIDTH, 480); if (!ret) ret = reg_write(client, MT9V022_MAX_TOTAL_SHUTTER_WIDTH, 480); if (!ret) @@ -540,8 +544,12 @@ static struct soc_camera_ops mt9v022_ops = { static int mt9v022_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) { struct i2c_client *client = sd->priv; + const struct v4l2_queryctrl *qctrl; + unsigned long range; int data; + qctrl = soc_camera_find_qctrl(&mt9v022_ops, ctrl->id); + switch (ctrl->id) { case V4L2_CID_VFLIP: data = reg_read(client, MT9V022_READ_MODE); @@ -566,6 +574,24 @@ static int mt9v022_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) if (data < 0) return -EIO; ctrl->value = !!(data & 0x2); + break; + case V4L2_CID_GAIN: + data = reg_read(client, MT9V022_ANALOG_GAIN); + if (data < 0) + return -EIO; + + range = qctrl->maximum - qctrl->minimum; + ctrl->value = ((data - 16) * range + 24) / 48 + qctrl->minimum; + + break; + case V4L2_CID_EXPOSURE: + data = reg_read(client, MT9V022_TOTAL_SHUTTER_WIDTH); + if (data < 0) + return -EIO; + + range = qctrl->maximum - qctrl->minimum; + ctrl->value = ((data - 1) * range + 239) / 479 + qctrl->minimum; + break; } return 0; @@ -575,7 +601,6 @@ static int mt9v022_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) { int data; struct i2c_client *client = sd->priv; - struct soc_camera_device *icd = client->dev.platform_data; const struct v4l2_queryctrl *qctrl; qctrl = soc_camera_find_qctrl(&mt9v022_ops, ctrl->id); @@ -605,12 +630,9 @@ static int mt9v022_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) return -EINVAL; else { unsigned long range = qctrl->maximum - qctrl->minimum; - /* Datasheet says 16 to 64. autogain only works properly - * after setting gain to maximum 14. Larger values - * produce "white fly" noise effect. On the whole, - * manually setting analog gain does no good. */ + /* Valid values 16 to 64, 32 to 64 must be even. */ unsigned long gain = ((ctrl->value - qctrl->minimum) * - 10 + range / 2) / range + 4; + 48 + range / 2) / range + 16; if (gain >= 32) gain &= ~1; /* The user wants to set gain manually, hope, she @@ -619,11 +641,10 @@ static int mt9v022_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) if (reg_clear(client, MT9V022_AEC_AGC_ENABLE, 0x2) < 0) return -EIO; - dev_info(&client->dev, "Setting gain from %d to %lu\n", - reg_read(client, MT9V022_ANALOG_GAIN), gain); + dev_dbg(&client->dev, "Setting gain from %d to %lu\n", + reg_read(client, MT9V022_ANALOG_GAIN), gain); if (reg_write(client, MT9V022_ANALOG_GAIN, gain) < 0) return -EIO; - icd->gain = ctrl->value; } break; case V4L2_CID_EXPOSURE: @@ -646,7 +667,6 @@ static int mt9v022_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) if (reg_write(client, MT9V022_TOTAL_SHUTTER_WIDTH, shutter) < 0) return -EIO; - icd->exposure = ctrl->value; } break; case V4L2_CID_AUTOGAIN: @@ -831,6 +851,7 @@ static int mt9v022_probe(struct i2c_client *client) mt9v022->chip_control = MT9V022_CHIP_CONTROL_DEFAULT; icd->ops = &mt9v022_ops; + /* MT9V022 _really_ corrupts the first read out line. TODO: verify on i.MX31 */ icd->y_skip_top = 1; mt9v022->rect.left = MT9V022_COLUMN_SKIP; diff --git a/linux/drivers/media/video/soc_camera.c b/linux/drivers/media/video/soc_camera.c index 4e620978f..6fac3d0eb 100644 --- a/linux/drivers/media/video/soc_camera.c +++ b/linux/drivers/media/video/soc_camera.c @@ -671,19 +671,6 @@ static int soc_camera_g_ctrl(struct file *file, void *priv, WARN_ON(priv != file->private_data); - switch (ctrl->id) { - case V4L2_CID_GAIN: - if (icd->gain == (unsigned short)~0) - return -EINVAL; - ctrl->value = icd->gain; - return 0; - case V4L2_CID_EXPOSURE: - if (icd->exposure == (unsigned short)~0) - return -EINVAL; - ctrl->value = icd->exposure; - return 0; - } - if (ici->ops->get_ctrl) { ret = ici->ops->get_ctrl(icd, ctrl); if (ret != -ENOIOCTLCMD) @@ -1280,7 +1267,6 @@ static int video_dev_create(struct soc_camera_device *icd) */ static int soc_camera_video_start(struct soc_camera_device *icd) { - const struct v4l2_queryctrl *qctrl; int ret; if (!icd->dev.parent) @@ -1298,11 +1284,6 @@ static int soc_camera_video_start(struct soc_camera_device *icd) return ret; } - qctrl = soc_camera_find_qctrl(icd->ops, V4L2_CID_GAIN); - icd->gain = qctrl ? qctrl->default_value : (unsigned short)~0; - qctrl = soc_camera_find_qctrl(icd->ops, V4L2_CID_EXPOSURE); - icd->exposure = qctrl ? qctrl->default_value : (unsigned short)~0; - return 0; } -- cgit v1.2.3 From 92c15735f63a6159490a9b6110e81925d093a10d Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Tue, 25 Aug 2009 16:53:23 +0200 Subject: soc-camera: fix recently introduced overlong lines From: Guennadi Liakhovetski Signed-off-by: Guennadi Liakhovetski Cc: Paul Mundt Acked-by: Paul Mundt Priority: low --- arch/sh/boards/board-ap325rxa.c | 3 ++- drivers/media/video/mt9m111.c | 9 +++++---- drivers/media/video/mt9v022.c | 5 ++++- drivers/media/video/mx1_camera.c | 3 ++- drivers/media/video/ov772x.c | 6 ++++-- drivers/media/video/pxa_camera.c | 3 ++- drivers/media/video/soc_camera.c | 14 +++++++++++--- drivers/media/video/soc_camera_platform.c | 3 ++- drivers/media/video/tw9910.c | 3 ++- include/media/soc_camera.h | 15 ++++++++++----- 10 files changed, 44 insertions(+), 20 deletions(-) --- linux/drivers/media/video/mt9m111.c | 9 +++++---- linux/drivers/media/video/mt9v022.c | 5 ++++- linux/drivers/media/video/mx1_camera.c | 3 ++- linux/drivers/media/video/ov772x.c | 6 ++++-- linux/drivers/media/video/pxa_camera.c | 3 ++- linux/drivers/media/video/soc_camera.c | 14 +++++++++++--- linux/drivers/media/video/soc_camera_platform.c | 3 ++- linux/drivers/media/video/tw9910.c | 3 ++- 8 files changed, 32 insertions(+), 14 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/mt9m111.c b/linux/drivers/media/video/mt9m111.c index 9ad087132..8171edb72 100644 --- a/linux/drivers/media/video/mt9m111.c +++ b/linux/drivers/media/video/mt9m111.c @@ -514,7 +514,8 @@ static int mt9m111_set_pixfmt(struct i2c_client *client, u32 pixfmt) ret = mt9m111_setfmt_yuv(client); break; default: - dev_err(&client->dev, "Pixel format not handled : %x\n", pixfmt); + dev_err(&client->dev, "Pixel format not handled : %x\n", + pixfmt); ret = -EINVAL; } @@ -537,9 +538,9 @@ static int mt9m111_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) }; int ret; - dev_dbg(&client->dev, "%s fmt=%x left=%d, top=%d, width=%d, height=%d\n", - __func__, pix->pixelformat, rect.left, rect.top, rect.width, - rect.height); + dev_dbg(&client->dev, + "%s fmt=%x left=%d, top=%d, width=%d, height=%d\n", __func__, + pix->pixelformat, rect.left, rect.top, rect.width, rect.height); ret = mt9m111_make_rect(client, &rect); if (!ret) diff --git a/linux/drivers/media/video/mt9v022.c b/linux/drivers/media/video/mt9v022.c index 582fabcfd..9da3dde10 100644 --- a/linux/drivers/media/video/mt9v022.c +++ b/linux/drivers/media/video/mt9v022.c @@ -851,7 +851,10 @@ static int mt9v022_probe(struct i2c_client *client) mt9v022->chip_control = MT9V022_CHIP_CONTROL_DEFAULT; icd->ops = &mt9v022_ops; - /* MT9V022 _really_ corrupts the first read out line. TODO: verify on i.MX31 */ + /* + * MT9V022 _really_ corrupts the first read out line. + * TODO: verify on i.MX31 + */ icd->y_skip_top = 1; mt9v022->rect.left = MT9V022_COLUMN_SKIP; diff --git a/linux/drivers/media/video/mx1_camera.c b/linux/drivers/media/video/mx1_camera.c index 3875483ab..5f37952c7 100644 --- a/linux/drivers/media/video/mx1_camera.c +++ b/linux/drivers/media/video/mx1_camera.c @@ -548,7 +548,8 @@ static int mx1_camera_set_fmt(struct soc_camera_device *icd, xlate = soc_camera_xlate_by_fourcc(icd, pix->pixelformat); if (!xlate) { - dev_warn(icd->dev.parent, "Format %x not found\n", pix->pixelformat); + dev_warn(icd->dev.parent, "Format %x not found\n", + pix->pixelformat); return -EINVAL; } diff --git a/linux/drivers/media/video/ov772x.c b/linux/drivers/media/video/ov772x.c index 2d48a7aeb..47e7c7c53 100644 --- a/linux/drivers/media/video/ov772x.c +++ b/linux/drivers/media/video/ov772x.c @@ -404,7 +404,8 @@ struct ov772x_priv { int model; unsigned short flag_vflip:1; unsigned short flag_hflip:1; - unsigned short band_filter; /* 256 - BDBASE, 0 if (!COM8[5]) */ + /* band_filter = COM8[5] ? 256 - BDBASE : 0 */ + unsigned short band_filter; }; #define ENDMARKER { 0xff, 0xff } @@ -587,7 +588,8 @@ static const struct v4l2_queryctrl ov772x_controls[] = { static struct ov772x_priv *to_ov772x(const struct i2c_client *client) { - return container_of(i2c_get_clientdata(client), struct ov772x_priv, subdev); + return container_of(i2c_get_clientdata(client), struct ov772x_priv, + subdev); } static int ov772x_write_array(struct i2c_client *client, diff --git a/linux/drivers/media/video/pxa_camera.c b/linux/drivers/media/video/pxa_camera.c index 0364b35d5..8ab1a5792 100644 --- a/linux/drivers/media/video/pxa_camera.c +++ b/linux/drivers/media/video/pxa_camera.c @@ -286,7 +286,8 @@ static void free_buffer(struct videobuf_queue *vq, struct pxa_buffer *buf) for (i = 0; i < ARRAY_SIZE(buf->dmas); i++) { if (buf->dmas[i].sg_cpu) - dma_free_coherent(ici->v4l2_dev.dev, buf->dmas[i].sg_size, + dma_free_coherent(ici->v4l2_dev.dev, + buf->dmas[i].sg_size, buf->dmas[i].sg_cpu, buf->dmas[i].sg_dma); buf->dmas[i].sg_cpu = NULL; diff --git a/linux/drivers/media/video/soc_camera.c b/linux/drivers/media/video/soc_camera.c index 6fac3d0eb..55d4d9a22 100644 --- a/linux/drivers/media/video/soc_camera.c +++ b/linux/drivers/media/video/soc_camera.c @@ -328,7 +328,9 @@ static int soc_camera_set_fmt(struct soc_camera_file *icf, static int soc_camera_open(struct file *file) { struct video_device *vdev = video_devdata(file); - struct soc_camera_device *icd = container_of(vdev->parent, struct soc_camera_device, dev); + struct soc_camera_device *icd = container_of(vdev->parent, + struct soc_camera_device, + dev); struct soc_camera_link *icl = to_soc_camera_link(icd); struct soc_camera_host *ici; struct soc_camera_file *icf; @@ -350,7 +352,10 @@ static int soc_camera_open(struct file *file) goto emgi; } - /* Protect against icd->ops->remove() until we module_get() both drivers. */ + /* + * Protect against icd->ops->remove() until we module_get() both + * drivers. + */ mutex_lock(&icd->video_lock); icf->icd = icd; @@ -932,7 +937,10 @@ static int soc_camera_probe(struct device *dev) if (ret < 0) goto eadddev; - /* FIXME: this is racy, have to use driver-binding notification */ + /* + * FIXME: this is racy, have to use driver-binding notification, + * when it is available + */ control = to_soc_camera_control(icd); if (!control || !control->driver || !dev_get_drvdata(control) || !try_module_get(control->driver->owner)) { diff --git a/linux/drivers/media/video/soc_camera_platform.c b/linux/drivers/media/video/soc_camera_platform.c index 3825c3581..1b6dd02a8 100644 --- a/linux/drivers/media/video/soc_camera_platform.c +++ b/linux/drivers/media/video/soc_camera_platform.c @@ -33,7 +33,8 @@ static struct soc_camera_platform_priv *get_priv(struct platform_device *pdev) static struct soc_camera_platform_info *get_info(struct soc_camera_device *icd) { - struct platform_device *pdev = to_platform_device(to_soc_camera_control(icd)); + struct platform_device *pdev = + to_platform_device(to_soc_camera_control(icd)); return pdev->dev.platform_data; } diff --git a/linux/drivers/media/video/tw9910.c b/linux/drivers/media/video/tw9910.c index 3ea12a66f..db56ae683 100644 --- a/linux/drivers/media/video/tw9910.c +++ b/linux/drivers/media/video/tw9910.c @@ -357,7 +357,8 @@ static const struct tw9910_hsync_ctrl tw9910_hsync_ctrl = { */ static struct tw9910_priv *to_tw9910(const struct i2c_client *client) { - return container_of(i2c_get_clientdata(client), struct tw9910_priv, subdev); + return container_of(i2c_get_clientdata(client), struct tw9910_priv, + subdev); } static int tw9910_set_scale(struct i2c_client *client, -- cgit v1.2.3 From 3041f901c7458733517662e5a5bedb4341fed496 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Wed, 26 Aug 2009 08:34:16 +0200 Subject: gspca - sn9c20x: Fix gscpa sn9c20x build errors. From: Randy Dunlap Reported-by: Toralf Forster Priority: high Signed-off-by: Randy Dunlap Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/gspca/Kconfig b/linux/drivers/media/video/gspca/Kconfig index 6ae1522ec..8897283b0 100644 --- a/linux/drivers/media/video/gspca/Kconfig +++ b/linux/drivers/media/video/gspca/Kconfig @@ -123,7 +123,7 @@ config USB_GSPCA_SN9C20X config USB_GSPCA_SN9C20X_EVDEV bool "Enable evdev support" - depends on USB_GSPCA_SN9C20X + depends on USB_GSPCA_SN9C20X && INPUT ---help--- Say Y here in order to enable evdev support for sn9c20x webcam button. -- cgit v1.2.3 From 4be4cfbd5a49c25a5d4fb78aed2e1246415ac7aa Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 11 Aug 2009 23:47:18 +0200 Subject: v4l: introduce string control support. From: Hans Verkuil The upcoming RDS encoder needs support for string controls. This patch implements the core implementation. Priority: normal Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/v4l2-common.c | 2 + linux/drivers/media/video/v4l2-compat-ioctl32.c | 65 +++++++++++++++++-------- linux/drivers/media/video/v4l2-ioctl.c | 10 ++-- 3 files changed, 53 insertions(+), 24 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/v4l2-common.c b/linux/drivers/media/video/v4l2-common.c index fe1dfc00b..51c080c13 100644 --- a/linux/drivers/media/video/v4l2-common.c +++ b/linux/drivers/media/video/v4l2-common.c @@ -157,6 +157,8 @@ int v4l2_ctrl_check(struct v4l2_ext_control *ctrl, struct v4l2_queryctrl *qctrl, return -EINVAL; if (qctrl->flags & V4L2_CTRL_FLAG_GRABBED) return -EBUSY; + if (qctrl->type == V4L2_CTRL_TYPE_STRING) + return 0; if (qctrl->type == V4L2_CTRL_TYPE_BUTTON || qctrl->type == V4L2_CTRL_TYPE_INTEGER64 || qctrl->type == V4L2_CTRL_TYPE_CTRL_CLASS) diff --git a/linux/drivers/media/video/v4l2-compat-ioctl32.c b/linux/drivers/media/video/v4l2-compat-ioctl32.c index d9cee38cd..cd45c09ff 100644 --- a/linux/drivers/media/video/v4l2-compat-ioctl32.c +++ b/linux/drivers/media/video/v4l2-compat-ioctl32.c @@ -605,9 +605,35 @@ struct v4l2_ext_controls32 { compat_caddr_t controls; /* actually struct v4l2_ext_control32 * */ }; +struct v4l2_ext_control32 { + __u32 id; + __u32 size; + __u32 reserved2[1]; + union { + __s32 value; + __s64 value64; + compat_caddr_t string; /* actually char * */ + }; +} __attribute__ ((packed)); + +/* The following function really belong in v4l2-common, but that causes + a circular dependency between modules. We need to think about this, but + for now this will do. */ + +/* Return non-zero if this control is a pointer type. Currently only + * type STRING is a pointer type. + * + * Note that there are currently no controls of this type, but at least the + * compat32 code is in place to properly handle such controls. Please + * remove this note once the first pointer controls are added. */ +static inline int ctrl_is_pointer(u32 id) +{ + return 0; +} + static int get_v4l2_ext_controls32(struct v4l2_ext_controls *kp, struct v4l2_ext_controls32 __user *up) { - struct v4l2_ext_control __user *ucontrols; + struct v4l2_ext_control32 __user *ucontrols; struct v4l2_ext_control __user *kcontrols; int n; compat_caddr_t p; @@ -631,15 +657,17 @@ static int get_v4l2_ext_controls32(struct v4l2_ext_controls *kp, struct v4l2_ext kcontrols = compat_alloc_user_space(n * sizeof(struct v4l2_ext_control)); kp->controls = kcontrols; while (--n >= 0) { - if (copy_in_user(&kcontrols->id, &ucontrols->id, sizeof(__u32))) - return -EFAULT; - if (copy_in_user(&kcontrols->reserved2, &ucontrols->reserved2, sizeof(ucontrols->reserved2))) - return -EFAULT; - /* Note: if the void * part of the union ever becomes relevant - then we need to know the type of the control in order to do - the right thing here. Luckily, that is not yet an issue. */ - if (copy_in_user(&kcontrols->value, &ucontrols->value, sizeof(ucontrols->value))) + if (copy_in_user(kcontrols, ucontrols, sizeof(*kcontrols))) return -EFAULT; + if (ctrl_is_pointer(kcontrols->id)) { + void __user *s; + + if (get_user(p, &ucontrols->string)) + return -EFAULT; + s = compat_ptr(p); + if (put_user(s, &kcontrols->string)) + return -EFAULT; + } ucontrols++; kcontrols++; } @@ -648,7 +676,7 @@ static int get_v4l2_ext_controls32(struct v4l2_ext_controls *kp, struct v4l2_ext static int put_v4l2_ext_controls32(struct v4l2_ext_controls *kp, struct v4l2_ext_controls32 __user *up) { - struct v4l2_ext_control __user *ucontrols; + struct v4l2_ext_control32 __user *ucontrols; struct v4l2_ext_control __user *kcontrols = kp->controls; int n = kp->count; compat_caddr_t p; @@ -669,15 +697,14 @@ static int put_v4l2_ext_controls32(struct v4l2_ext_controls *kp, struct v4l2_ext return -EFAULT; while (--n >= 0) { - if (copy_in_user(&ucontrols->id, &kcontrols->id, sizeof(__u32))) - return -EFAULT; - if (copy_in_user(&ucontrols->reserved2, &kcontrols->reserved2, - sizeof(ucontrols->reserved2))) - return -EFAULT; - /* Note: if the void * part of the union ever becomes relevant - then we need to know the type of the control in order to do - the right thing here. Luckily, that is not yet an issue. */ - if (copy_in_user(&ucontrols->value, &kcontrols->value, sizeof(ucontrols->value))) + unsigned size = sizeof(*ucontrols); + + /* Do not modify the pointer when copying a pointer control. + The contents of the pointer was changed, not the pointer + itself. */ + if (ctrl_is_pointer(kcontrols->id)) + size -= sizeof(ucontrols->value64); + if (copy_in_user(ucontrols, kcontrols, size)) return -EFAULT; ucontrols++; kcontrols++; diff --git a/linux/drivers/media/video/v4l2-ioctl.c b/linux/drivers/media/video/v4l2-ioctl.c index d746d9555..d40c7bb2d 100644 --- a/linux/drivers/media/video/v4l2-ioctl.c +++ b/linux/drivers/media/video/v4l2-ioctl.c @@ -514,11 +514,12 @@ static inline void v4l_print_ext_ctrls(unsigned int cmd, dbgarg(cmd, ""); printk(KERN_CONT "class=0x%x", c->ctrl_class); for (i = 0; i < c->count; i++) { - if (show_vals) + if (show_vals && !c->controls[i].size) printk(KERN_CONT " id/val=0x%x/0x%x", c->controls[i].id, c->controls[i].value); else - printk(KERN_CONT " id=0x%x", c->controls[i].id); + printk(KERN_CONT " id=0x%x,size=%u", + c->controls[i].id, c->controls[i].size); } printk(KERN_CONT "\n"); }; @@ -529,10 +530,9 @@ static inline int check_ext_ctrls(struct v4l2_ext_controls *c, int allow_priv) /* zero the reserved fields */ c->reserved[0] = c->reserved[1] = 0; - for (i = 0; i < c->count; i++) { + for (i = 0; i < c->count; i++) c->controls[i].reserved2[0] = 0; - c->controls[i].reserved2[1] = 0; - } + /* V4L2_CID_PRIVATE_BASE cannot be used as control class when using extended controls. Only when passed in through VIDIOC_G_CTRL and VIDIOC_S_CTRL -- cgit v1.2.3 From 5f00630df328d9e746ca5f61f3413f5c80743663 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 11 Aug 2009 23:49:12 +0200 Subject: v4l2: video device: Add FM TX controls default configurations From: Eduardo Valentin This patch adds basic configurations for FM TX extended controls. That includes controls names, menu strings, pointer identification, type classification and flags configuration. Priority: normal Signed-off-by: Eduardo Valentin Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/v4l2-common.c | 50 +++++++++++++++++++++++++ linux/drivers/media/video/v4l2-compat-ioctl32.c | 14 ++++--- 2 files changed, 58 insertions(+), 6 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/v4l2-common.c b/linux/drivers/media/video/v4l2-common.c index 51c080c13..203945635 100644 --- a/linux/drivers/media/video/v4l2-common.c +++ b/linux/drivers/media/video/v4l2-common.c @@ -343,6 +343,12 @@ const char **v4l2_ctrl_get_menu(u32 id) "Sepia", NULL }; + static const char *tune_preemphasis[] = { + "No preemphasis", + "50 useconds", + "75 useconds", + NULL, + }; switch (id) { case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ: @@ -381,6 +387,8 @@ const char **v4l2_ctrl_get_menu(u32 id) return camera_exposure_auto; case V4L2_CID_COLORFX: return colorfx; + case V4L2_CID_TUNE_PREEMPHASIS: + return tune_preemphasis; default: return NULL; } @@ -479,6 +487,28 @@ const char *v4l2_ctrl_get_name(u32 id) case V4L2_CID_ZOOM_CONTINUOUS: return "Zoom, Continuous"; case V4L2_CID_PRIVACY: return "Privacy"; + /* FM Radio Modulator control */ + case V4L2_CID_FM_TX_CLASS: return "FM Radio Modulator Controls"; + case V4L2_CID_RDS_TX_DEVIATION: return "RDS Signal Deviation"; + case V4L2_CID_RDS_TX_PI: return "RDS Program ID"; + case V4L2_CID_RDS_TX_PTY: return "RDS Program Type"; + case V4L2_CID_RDS_TX_PS_NAME: return "RDS PS Name"; + case V4L2_CID_RDS_TX_RADIO_TEXT: return "RDS Radio Text"; + case V4L2_CID_AUDIO_LIMITER_ENABLED: return "Audio Limiter Feature Enabled"; + case V4L2_CID_AUDIO_LIMITER_RELEASE_TIME: return "Audio Limiter Release Time"; + case V4L2_CID_AUDIO_LIMITER_DEVIATION: return "Audio Limiter Deviation"; + case V4L2_CID_AUDIO_COMPRESSION_ENABLED: return "Audio Compression Feature Enabled"; + case V4L2_CID_AUDIO_COMPRESSION_GAIN: return "Audio Compression Gain"; + case V4L2_CID_AUDIO_COMPRESSION_THRESHOLD: return "Audio Compression Threshold"; + case V4L2_CID_AUDIO_COMPRESSION_ATTACK_TIME: return "Audio Compression Attack Time"; + case V4L2_CID_AUDIO_COMPRESSION_RELEASE_TIME: return "Audio Compression Release Time"; + case V4L2_CID_PILOT_TONE_ENABLED: return "Pilot Tone Feature Enabled"; + case V4L2_CID_PILOT_TONE_DEVIATION: return "Pilot Tone Deviation"; + case V4L2_CID_PILOT_TONE_FREQUENCY: return "Pilot Tone Frequency"; + case V4L2_CID_TUNE_PREEMPHASIS: return "Pre-emphasis settings"; + case V4L2_CID_TUNE_POWER_LEVEL: return "Tune Power Level"; + case V4L2_CID_TUNE_ANTENNA_CAPACITOR: return "Tune Antenna Capacitor"; + default: return NULL; } @@ -511,6 +541,9 @@ int v4l2_ctrl_query_fill(struct v4l2_queryctrl *qctrl, s32 min, s32 max, s32 ste case V4L2_CID_EXPOSURE_AUTO_PRIORITY: case V4L2_CID_FOCUS_AUTO: case V4L2_CID_PRIVACY: + case V4L2_CID_AUDIO_LIMITER_ENABLED: + case V4L2_CID_AUDIO_COMPRESSION_ENABLED: + case V4L2_CID_PILOT_TONE_ENABLED: qctrl->type = V4L2_CTRL_TYPE_BOOLEAN; min = 0; max = step = 1; @@ -539,12 +572,18 @@ int v4l2_ctrl_query_fill(struct v4l2_queryctrl *qctrl, s32 min, s32 max, s32 ste case V4L2_CID_MPEG_STREAM_VBI_FMT: case V4L2_CID_EXPOSURE_AUTO: case V4L2_CID_COLORFX: + case V4L2_CID_TUNE_PREEMPHASIS: qctrl->type = V4L2_CTRL_TYPE_MENU; step = 1; break; + case V4L2_CID_RDS_TX_PS_NAME: + case V4L2_CID_RDS_TX_RADIO_TEXT: + qctrl->type = V4L2_CTRL_TYPE_STRING; + break; case V4L2_CID_USER_CLASS: case V4L2_CID_CAMERA_CLASS: case V4L2_CID_MPEG_CLASS: + case V4L2_CID_FM_TX_CLASS: qctrl->type = V4L2_CTRL_TYPE_CTRL_CLASS; qctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY; min = max = step = def = 0; @@ -573,6 +612,17 @@ int v4l2_ctrl_query_fill(struct v4l2_queryctrl *qctrl, s32 min, s32 max, s32 ste case V4L2_CID_BLUE_BALANCE: case V4L2_CID_GAMMA: case V4L2_CID_SHARPNESS: + case V4L2_CID_RDS_TX_DEVIATION: + case V4L2_CID_AUDIO_LIMITER_RELEASE_TIME: + case V4L2_CID_AUDIO_LIMITER_DEVIATION: + case V4L2_CID_AUDIO_COMPRESSION_GAIN: + case V4L2_CID_AUDIO_COMPRESSION_THRESHOLD: + case V4L2_CID_AUDIO_COMPRESSION_ATTACK_TIME: + case V4L2_CID_AUDIO_COMPRESSION_RELEASE_TIME: + case V4L2_CID_PILOT_TONE_DEVIATION: + case V4L2_CID_PILOT_TONE_FREQUENCY: + case V4L2_CID_TUNE_POWER_LEVEL: + case V4L2_CID_TUNE_ANTENNA_CAPACITOR: qctrl->flags |= V4L2_CTRL_FLAG_SLIDER; break; case V4L2_CID_PAN_RELATIVE: diff --git a/linux/drivers/media/video/v4l2-compat-ioctl32.c b/linux/drivers/media/video/v4l2-compat-ioctl32.c index cd45c09ff..3454e7c64 100644 --- a/linux/drivers/media/video/v4l2-compat-ioctl32.c +++ b/linux/drivers/media/video/v4l2-compat-ioctl32.c @@ -621,14 +621,16 @@ struct v4l2_ext_control32 { for now this will do. */ /* Return non-zero if this control is a pointer type. Currently only - * type STRING is a pointer type. - * - * Note that there are currently no controls of this type, but at least the - * compat32 code is in place to properly handle such controls. Please - * remove this note once the first pointer controls are added. */ + type STRING is a pointer type. */ static inline int ctrl_is_pointer(u32 id) { - return 0; + switch (id) { + case V4L2_CID_RDS_TX_PS_NAME: + case V4L2_CID_RDS_TX_RADIO_TEXT: + return 1; + default: + return 0; + } } static int get_v4l2_ext_controls32(struct v4l2_ext_controls *kp, struct v4l2_ext_controls32 __user *up) -- cgit v1.2.3 From 18da6da5146ce9ae730fbca22f57b010ee5956ca Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 8 Aug 2009 14:00:37 +0200 Subject: FM TX: si4713: Add Kconfig and Makefile entries From: Hans Verkuil Simply add Makefile and Kconfig entries. Priority: normal Signed-off-by: Eduardo Valentin [hverkuil@xs4all.nl: auto-select I2C_SI4713] Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/radio/Kconfig | 23 +++++++++++++++++++++++ linux/drivers/media/radio/Makefile | 2 ++ 2 files changed, 25 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/radio/Kconfig b/linux/drivers/media/radio/Kconfig index 0e39edf75..25a36ad60 100644 --- a/linux/drivers/media/radio/Kconfig +++ b/linux/drivers/media/radio/Kconfig @@ -329,6 +329,29 @@ config RADIO_ZOLTRIX_PORT help Enter the I/O port of your Zoltrix radio card. +config I2C_SI4713 + tristate "I2C driver for Silicon Labs Si4713 device" + depends on I2C && VIDEO_V4L2 + ---help--- + Say Y here if you want support to Si4713 I2C device. + This device driver supports only i2c bus. + + To compile this driver as a module, choose M here: the + module will be called si4713. + +config RADIO_SI4713 + tristate "Silicon Labs Si4713 FM Radio Transmitter support" + depends on I2C && VIDEO_V4L2 + select I2C_SI4713 + ---help--- + Say Y here if you want support to Si4713 FM Radio Transmitter. + This device can transmit audio through FM. It can transmit + EDS and EBDS signals as well. This module is the v4l2 radio + interface for the i2c driver of this device. + + To compile this driver as a module, choose M here: the + module will be called radio-si4713. + config USB_DSBR tristate "D-Link/GemTek USB FM radio support" depends on USB && VIDEO_V4L2 diff --git a/linux/drivers/media/radio/Makefile b/linux/drivers/media/radio/Makefile index 18111e1fe..2a1be3bf4 100644 --- a/linux/drivers/media/radio/Makefile +++ b/linux/drivers/media/radio/Makefile @@ -15,6 +15,8 @@ obj-$(CONFIG_RADIO_ZOLTRIX) += radio-zoltrix.o obj-$(CONFIG_RADIO_GEMTEK) += radio-gemtek.o obj-$(CONFIG_RADIO_GEMTEK_PCI) += radio-gemtek-pci.o obj-$(CONFIG_RADIO_TRUST) += radio-trust.o +obj-$(CONFIG_I2C_SI4713) += si4713-i2c.o +obj-$(CONFIG_RADIO_SI4713) += radio-si4713.o obj-$(CONFIG_RADIO_MAESTRO) += radio-maestro.o obj-$(CONFIG_USB_DSBR) += dsbr100.o obj-$(CONFIG_RADIO_SI470X) += si470x/ -- cgit v1.2.3 From b98fedbf223090872b1b4b7ec8e89994b55fb9bb Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 26 Aug 2009 18:28:55 -0300 Subject: Fix a merge trouble From: Mauro Carvalho Chehab Unfortunately, mailimport added the new files at the wrong place. Fix it. Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/radio/radio-si4713.c | 367 ++++++ linux/drivers/media/radio/si4713-i2c.c | 2067 ++++++++++++++++++++++++++++++ linux/drivers/media/radio/si4713-i2c.h | 237 ++++ 3 files changed, 2671 insertions(+) create mode 100644 linux/drivers/media/radio/radio-si4713.c create mode 100644 linux/drivers/media/radio/si4713-i2c.c create mode 100644 linux/drivers/media/radio/si4713-i2c.h (limited to 'linux/drivers') diff --git a/linux/drivers/media/radio/radio-si4713.c b/linux/drivers/media/radio/radio-si4713.c new file mode 100644 index 000000000..65c14b704 --- /dev/null +++ b/linux/drivers/media/radio/radio-si4713.c @@ -0,0 +1,367 @@ +/* + * drivers/media/radio/radio-si4713.c + * + * Platform Driver for Silicon Labs Si4713 FM Radio Transmitter: + * + * Copyright (c) 2008 Instituto Nokia de Tecnologia - INdT + * Contact: Eduardo Valentin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* module parameters */ +static int radio_nr = -1; /* radio device minor (-1 ==> auto assign) */ +module_param(radio_nr, int, 0); +MODULE_PARM_DESC(radio_nr, + "Minor number for radio device (-1 ==> auto assign)"); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Eduardo Valentin "); +MODULE_DESCRIPTION("Platform driver for Si4713 FM Radio Transmitter"); +MODULE_VERSION("0.0.1"); + +/* Driver state struct */ +struct radio_si4713_device { + struct v4l2_device v4l2_dev; + struct video_device *radio_dev; +}; + +/* radio_si4713_fops - file operations interface */ +static const struct v4l2_file_operations radio_si4713_fops = { + .owner = THIS_MODULE, + .ioctl = video_ioctl2, +}; + +/* Video4Linux Interface */ +static int radio_si4713_fill_audout(struct v4l2_audioout *vao) +{ + /* TODO: check presence of audio output */ + strlcpy(vao->name, "FM Modulator Audio Out", 32); + + return 0; +} + +static int radio_si4713_enumaudout(struct file *file, void *priv, + struct v4l2_audioout *vao) +{ + return radio_si4713_fill_audout(vao); +} + +static int radio_si4713_g_audout(struct file *file, void *priv, + struct v4l2_audioout *vao) +{ + int rval = radio_si4713_fill_audout(vao); + + vao->index = 0; + + return rval; +} + +static int radio_si4713_s_audout(struct file *file, void *priv, + struct v4l2_audioout *vao) +{ + return vao->index ? -EINVAL : 0; +} + +/* radio_si4713_querycap - query device capabilities */ +static int radio_si4713_querycap(struct file *file, void *priv, + struct v4l2_capability *capability) +{ + struct radio_si4713_device *rsdev; + + rsdev = video_get_drvdata(video_devdata(file)); + + strlcpy(capability->driver, "radio-si4713", sizeof(capability->driver)); + strlcpy(capability->card, "Silicon Labs Si4713 Modulator", + sizeof(capability->card)); + capability->capabilities = V4L2_CAP_MODULATOR | V4L2_CAP_RDS_OUTPUT; + + return 0; +} + +/* radio_si4713_queryctrl - enumerate control items */ +static int radio_si4713_queryctrl(struct file *file, void *priv, + struct v4l2_queryctrl *qc) +{ + /* Must be sorted from low to high control ID! */ + static const u32 user_ctrls[] = { + V4L2_CID_USER_CLASS, + V4L2_CID_AUDIO_MUTE, + 0 + }; + + /* Must be sorted from low to high control ID! */ + static const u32 fmtx_ctrls[] = { + V4L2_CID_FM_TX_CLASS, + V4L2_CID_RDS_TX_DEVIATION, + V4L2_CID_RDS_TX_PI, + V4L2_CID_RDS_TX_PTY, + V4L2_CID_RDS_TX_PS_NAME, + V4L2_CID_RDS_TX_RADIO_TEXT, + V4L2_CID_AUDIO_LIMITER_ENABLED, + V4L2_CID_AUDIO_LIMITER_RELEASE_TIME, + V4L2_CID_AUDIO_LIMITER_DEVIATION, + V4L2_CID_AUDIO_COMPRESSION_ENABLED, + V4L2_CID_AUDIO_COMPRESSION_GAIN, + V4L2_CID_AUDIO_COMPRESSION_THRESHOLD, + V4L2_CID_AUDIO_COMPRESSION_ATTACK_TIME, + V4L2_CID_AUDIO_COMPRESSION_RELEASE_TIME, + V4L2_CID_PILOT_TONE_ENABLED, + V4L2_CID_PILOT_TONE_DEVIATION, + V4L2_CID_PILOT_TONE_FREQUENCY, + V4L2_CID_TUNE_PREEMPHASIS, + V4L2_CID_TUNE_POWER_LEVEL, + V4L2_CID_TUNE_ANTENNA_CAPACITOR, + 0 + }; + static const u32 *ctrl_classes[] = { + user_ctrls, + fmtx_ctrls, + NULL + }; + struct radio_si4713_device *rsdev; + + rsdev = video_get_drvdata(video_devdata(file)); + + qc->id = v4l2_ctrl_next(ctrl_classes, qc->id); + if (qc->id == 0) + return -EINVAL; + + if (qc->id == V4L2_CID_USER_CLASS || qc->id == V4L2_CID_FM_TX_CLASS) + return v4l2_ctrl_query_fill(qc, 0, 0, 0, 0); + + return v4l2_device_call_until_err(&rsdev->v4l2_dev, 0, core, + queryctrl, qc); +} + +/* + * v4l2 ioctl call backs. + * we are just a wrapper for v4l2_sub_devs. + */ +static inline struct v4l2_device *get_v4l2_dev(struct file *file) +{ + return &((struct radio_si4713_device *)video_drvdata(file))->v4l2_dev; +} + +static int radio_si4713_g_ext_ctrls(struct file *file, void *p, + struct v4l2_ext_controls *vecs) +{ + return v4l2_device_call_until_err(get_v4l2_dev(file), 0, core, + g_ext_ctrls, vecs); +} + +static int radio_si4713_s_ext_ctrls(struct file *file, void *p, + struct v4l2_ext_controls *vecs) +{ + return v4l2_device_call_until_err(get_v4l2_dev(file), 0, core, + s_ext_ctrls, vecs); +} + +static int radio_si4713_g_ctrl(struct file *file, void *p, + struct v4l2_control *vc) +{ + return v4l2_device_call_until_err(get_v4l2_dev(file), 0, core, + g_ctrl, vc); +} + +static int radio_si4713_s_ctrl(struct file *file, void *p, + struct v4l2_control *vc) +{ + return v4l2_device_call_until_err(get_v4l2_dev(file), 0, core, + s_ctrl, vc); +} + +static int radio_si4713_g_modulator(struct file *file, void *p, + struct v4l2_modulator *vm) +{ + return v4l2_device_call_until_err(get_v4l2_dev(file), 0, tuner, + g_modulator, vm); +} + +static int radio_si4713_s_modulator(struct file *file, void *p, + struct v4l2_modulator *vm) +{ + return v4l2_device_call_until_err(get_v4l2_dev(file), 0, tuner, + s_modulator, vm); +} + +static int radio_si4713_g_frequency(struct file *file, void *p, + struct v4l2_frequency *vf) +{ + return v4l2_device_call_until_err(get_v4l2_dev(file), 0, tuner, + g_frequency, vf); +} + +static int radio_si4713_s_frequency(struct file *file, void *p, + struct v4l2_frequency *vf) +{ + return v4l2_device_call_until_err(get_v4l2_dev(file), 0, tuner, + s_frequency, vf); +} + +static long radio_si4713_default(struct file *file, void *p, int cmd, void *arg) +{ + return v4l2_device_call_until_err(get_v4l2_dev(file), 0, core, + ioctl, cmd, arg); +} + +static struct v4l2_ioctl_ops radio_si4713_ioctl_ops = { + .vidioc_enumaudout = radio_si4713_enumaudout, + .vidioc_g_audout = radio_si4713_g_audout, + .vidioc_s_audout = radio_si4713_s_audout, + .vidioc_querycap = radio_si4713_querycap, + .vidioc_queryctrl = radio_si4713_queryctrl, + .vidioc_g_ext_ctrls = radio_si4713_g_ext_ctrls, + .vidioc_s_ext_ctrls = radio_si4713_s_ext_ctrls, + .vidioc_g_ctrl = radio_si4713_g_ctrl, + .vidioc_s_ctrl = radio_si4713_s_ctrl, + .vidioc_g_modulator = radio_si4713_g_modulator, + .vidioc_s_modulator = radio_si4713_s_modulator, + .vidioc_g_frequency = radio_si4713_g_frequency, + .vidioc_s_frequency = radio_si4713_s_frequency, + .vidioc_default = radio_si4713_default, +}; + +/* radio_si4713_vdev_template - video device interface */ +static struct video_device radio_si4713_vdev_template = { + .fops = &radio_si4713_fops, + .name = "radio-si4713", + .release = video_device_release, + .ioctl_ops = &radio_si4713_ioctl_ops, +}; + +/* Platform driver interface */ +/* radio_si4713_pdriver_probe - probe for the device */ +static int radio_si4713_pdriver_probe(struct platform_device *pdev) +{ + struct radio_si4713_platform_data *pdata = pdev->dev.platform_data; + struct radio_si4713_device *rsdev; + struct i2c_adapter *adapter; + struct v4l2_subdev *sd; + int rval = 0; + + if (!pdata) { + dev_err(&pdev->dev, "Cannot proceed without platform data.\n"); + rval = -EINVAL; + goto exit; + } + + rsdev = kzalloc(sizeof *rsdev, GFP_KERNEL); + if (!rsdev) { + dev_err(&pdev->dev, "Failed to alloc video device.\n"); + rval = -ENOMEM; + goto exit; + } + + rval = v4l2_device_register(&pdev->dev, &rsdev->v4l2_dev); + if (rval) { + dev_err(&pdev->dev, "Failed to register v4l2 device.\n"); + goto free_rsdev; + } + + adapter = i2c_get_adapter(pdata->i2c_bus); + if (!adapter) { + dev_err(&pdev->dev, "Cannot get i2c adapter %d\n", + pdata->i2c_bus); + rval = -ENODEV; + goto unregister_v4l2_dev; + } + + sd = v4l2_i2c_new_subdev_board(&rsdev->v4l2_dev, adapter, "si4713_i2c", + pdata->subdev_board_info, NULL); + if (!sd) { + dev_err(&pdev->dev, "Cannot get v4l2 subdevice\n"); + rval = -ENODEV; + goto unregister_v4l2_dev; + } + + rsdev->radio_dev = video_device_alloc(); + if (!rsdev->radio_dev) { + dev_err(&pdev->dev, "Failed to alloc video device.\n"); + rval = -ENOMEM; + goto unregister_v4l2_dev; + } + + memcpy(rsdev->radio_dev, &radio_si4713_vdev_template, + sizeof(radio_si4713_vdev_template)); + video_set_drvdata(rsdev->radio_dev, rsdev); + if (video_register_device(rsdev->radio_dev, VFL_TYPE_RADIO, radio_nr)) { + dev_err(&pdev->dev, "Could not register video device.\n"); + rval = -EIO; + goto free_vdev; + } + dev_info(&pdev->dev, "New device successfully probed\n"); + + goto exit; + +free_vdev: + video_device_release(rsdev->radio_dev); +unregister_v4l2_dev: + v4l2_device_unregister(&rsdev->v4l2_dev); +free_rsdev: + kfree(rsdev); +exit: + return rval; +} + +/* radio_si4713_pdriver_remove - remove the device */ +static int __exit radio_si4713_pdriver_remove(struct platform_device *pdev) +{ + struct v4l2_device *v4l2_dev = platform_get_drvdata(pdev); + struct radio_si4713_device *rsdev = container_of(v4l2_dev, + struct radio_si4713_device, + v4l2_dev); + + video_unregister_device(rsdev->radio_dev); + v4l2_device_unregister(&rsdev->v4l2_dev); + kfree(rsdev); + + return 0; +} + +static struct platform_driver radio_si4713_pdriver = { + .driver = { + .name = "radio-si4713", + }, + .probe = radio_si4713_pdriver_probe, + .remove = __exit_p(radio_si4713_pdriver_remove), +}; + +/* Module Interface */ +static int __init radio_si4713_module_init(void) +{ + return platform_driver_register(&radio_si4713_pdriver); +} + +static void __exit radio_si4713_module_exit(void) +{ + platform_driver_unregister(&radio_si4713_pdriver); +} + +module_init(radio_si4713_module_init); +module_exit(radio_si4713_module_exit); + diff --git a/linux/drivers/media/radio/si4713-i2c.c b/linux/drivers/media/radio/si4713-i2c.c new file mode 100644 index 000000000..8cbbe48b0 --- /dev/null +++ b/linux/drivers/media/radio/si4713-i2c.c @@ -0,0 +1,2067 @@ +/* + * drivers/media/radio/si4713-i2c.c + * + * Silicon Labs Si4713 FM Radio Transmitter I2C commands. + * + * Copyright (c) 2009 Nokia Corporation + * Contact: Eduardo Valentin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "si4713-i2c.h" + +/* module parameters */ +static int debug; +module_param(debug, int, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(debug, "Debug level (0 - 2)"); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Eduardo Valentin "); +MODULE_DESCRIPTION("I2C driver for Si4713 FM Radio Transmitter"); +MODULE_VERSION("0.0.1"); + +#define DEFAULT_RDS_PI 0x00 +#define DEFAULT_RDS_PTY 0x00 +#define DEFAULT_RDS_PS_NAME "" +#define DEFAULT_RDS_RADIO_TEXT DEFAULT_RDS_PS_NAME +#define DEFAULT_RDS_DEVIATION 0x00C8 +#define DEFAULT_RDS_PS_REPEAT_COUNT 0x0003 +#define DEFAULT_LIMITER_RTIME 0x1392 +#define DEFAULT_LIMITER_DEV 0x102CA +#define DEFAULT_PILOT_FREQUENCY 0x4A38 +#define DEFAULT_PILOT_DEVIATION 0x1A5E +#define DEFAULT_ACOMP_ATIME 0x0000 +#define DEFAULT_ACOMP_RTIME 0xF4240L +#define DEFAULT_ACOMP_GAIN 0x0F +#define DEFAULT_ACOMP_THRESHOLD (-0x28) +#define DEFAULT_MUTE 0x01 +#define DEFAULT_POWER_LEVEL 88 +#define DEFAULT_FREQUENCY 8800 +#define DEFAULT_PREEMPHASIS FMPE_EU +#define DEFAULT_TUNE_RNL 0xFF + +#define to_si4713_device(sd) container_of(sd, struct si4713_device, sd) + +/* frequency domain transformation (using times 10 to avoid floats) */ +#define FREQDEV_UNIT 100000 +#define FREQV4L2_MULTI 625 +#define si4713_to_v4l2(f) ((f * FREQDEV_UNIT) / FREQV4L2_MULTI) +#define v4l2_to_si4713(f) ((f * FREQV4L2_MULTI) / FREQDEV_UNIT) +#define FREQ_RANGE_LOW 7600 +#define FREQ_RANGE_HIGH 10800 + +#define MAX_ARGS 7 + +#define RDS_BLOCK 8 +#define RDS_BLOCK_CLEAR 0x03 +#define RDS_BLOCK_LOAD 0x04 +#define RDS_RADIOTEXT_2A 0x20 +#define RDS_RADIOTEXT_BLK_SIZE 4 +#define RDS_RADIOTEXT_INDEX_MAX 0x0F +#define RDS_CARRIAGE_RETURN 0x0D + +#define rds_ps_nblocks(len) ((len / RDS_BLOCK) + (len % RDS_BLOCK ? 1 : 0)) + +#define get_status_bit(p, b, m) (((p) & (m)) >> (b)) +#define set_bits(p, v, b, m) (((p) & ~(m)) | ((v) << (b))) + +#define ATTACK_TIME_UNIT 500 + +#define POWER_OFF 0x00 +#define POWER_ON 0x01 + +#define msb(x) ((u8)((u16) x >> 8)) +#define lsb(x) ((u8)((u16) x & 0x00FF)) +#define compose_u16(msb, lsb) (((u16)msb << 8) | lsb) +#define check_command_failed(status) (!(status & SI4713_CTS) || \ + (status & SI4713_ERR)) +/* mute definition */ +#define set_mute(p) ((p & 1) | ((p & 1) << 1)); +#define get_mute(p) (p & 0x01) + +#ifdef DEBUG +#define DBG_BUFFER(device, message, buffer, size) \ + { \ + int i; \ + char str[(size)*5]; \ + for (i = 0; i < size; i++) \ + sprintf(str + i * 5, " 0x%02x", buffer[i]); \ + v4l2_dbg(2, debug, device, "%s:%s\n", message, str); \ + } +#else +#define DBG_BUFFER(device, message, buffer, size) +#endif + +/* + * Values for limiter release time (sorted by second column) + * device release + * value time (us) + */ +static long limiter_times[] = { + 2000, 250, + 1000, 500, + 510, 1000, + 255, 2000, + 170, 3000, + 127, 4020, + 102, 5010, + 85, 6020, + 73, 7010, + 64, 7990, + 57, 8970, + 51, 10030, + 25, 20470, + 17, 30110, + 13, 39380, + 10, 51190, + 8, 63690, + 7, 73140, + 6, 85330, + 5, 102390, +}; + +/* + * Values for audio compression release time (sorted by second column) + * device release + * value time (us) + */ +static unsigned long acomp_rtimes[] = { + 0, 100000, + 1, 200000, + 2, 350000, + 3, 525000, + 4, 1000000, +}; + +/* + * Values for preemphasis (sorted by second column) + * device preemphasis + * value value (v4l2) + */ +static unsigned long preemphasis_values[] = { + FMPE_DISABLED, V4L2_PREEMPHASIS_DISABLED, + FMPE_EU, V4L2_PREEMPHASIS_50_uS, + FMPE_USA, V4L2_PREEMPHASIS_75_uS, +}; + +static int usecs_to_dev(unsigned long usecs, unsigned long const array[], + int size) +{ + int i; + int rval = -EINVAL; + + for (i = 0; i < size / 2; i++) + if (array[(i * 2) + 1] >= usecs) { + rval = array[i * 2]; + break; + } + + return rval; +} + +static unsigned long dev_to_usecs(int value, unsigned long const array[], + int size) +{ + int i; + int rval = -EINVAL; + + for (i = 0; i < size / 2; i++) + if (array[i * 2] == value) { + rval = array[(i * 2) + 1]; + break; + } + + return rval; +} + +/* si4713_handler: IRQ handler, just complete work */ +static irqreturn_t si4713_handler(int irq, void *dev) +{ + struct si4713_device *sdev = dev; + + v4l2_dbg(2, debug, &sdev->sd, + "%s: sending signal to completion work.\n", __func__); + complete(&sdev->work); + + return IRQ_HANDLED; +} + +/* + * si4713_send_command - sends a command to si4713 and waits its response + * @sdev: si4713_device structure for the device we are communicating + * @command: command id + * @args: command arguments we are sending (up to 7) + * @argn: actual size of @args + * @response: buffer to place the expected response from the device (up to 15) + * @respn: actual size of @response + * @usecs: amount of time to wait before reading the response (in usecs) + */ +static int si4713_send_command(struct si4713_device *sdev, const u8 command, + const u8 args[], const int argn, + u8 response[], const int respn, const int usecs) +{ + struct i2c_client *client = v4l2_get_subdevdata(&sdev->sd); + u8 data1[MAX_ARGS + 1]; + int err; + + if (!client->adapter) + return -ENODEV; + + /* First send the command and its arguments */ + data1[0] = command; + memcpy(data1 + 1, args, argn); + DBG_BUFFER(&sdev->sd, "Parameters", data1, argn + 1); + + err = i2c_master_send(client, data1, argn + 1); + if (err != argn + 1) { + v4l2_err(&sdev->sd, "Error while sending command 0x%02x\n", + command); + return (err > 0) ? -EIO : err; + } + + /* Wait response from interrupt */ + if (!wait_for_completion_timeout(&sdev->work, + usecs_to_jiffies(usecs) + 1)) + v4l2_warn(&sdev->sd, + "(%s) Device took too much time to answer.\n", + __func__); + + /* Then get the response */ + err = i2c_master_recv(client, response, respn); + if (err != respn) { + v4l2_err(&sdev->sd, + "Error while reading response for command 0x%02x\n", + command); + return (err > 0) ? -EIO : err; + } + + DBG_BUFFER(&sdev->sd, "Response", response, respn); + if (check_command_failed(response[0])) + return -EBUSY; + + return 0; +} + +/* + * si4713_read_property - reads a si4713 property + * @sdev: si4713_device structure for the device we are communicating + * @prop: property identification number + * @pv: property value to be returned on success + */ +static int si4713_read_property(struct si4713_device *sdev, u16 prop, u32 *pv) +{ + int err; + u8 val[SI4713_GET_PROP_NRESP]; + /* + * .First byte = 0 + * .Second byte = property's MSB + * .Third byte = property's LSB + */ + const u8 args[SI4713_GET_PROP_NARGS] = { + 0x00, + msb(prop), + lsb(prop), + }; + + err = si4713_send_command(sdev, SI4713_CMD_GET_PROPERTY, + args, ARRAY_SIZE(args), val, + ARRAY_SIZE(val), DEFAULT_TIMEOUT); + + if (err < 0) + return err; + + *pv = compose_u16(val[2], val[3]); + + v4l2_dbg(1, debug, &sdev->sd, + "%s: property=0x%02x value=0x%02x status=0x%02x\n", + __func__, prop, *pv, val[0]); + + return err; +} + +/* + * si4713_write_property - modifies a si4713 property + * @sdev: si4713_device structure for the device we are communicating + * @prop: property identification number + * @val: new value for that property + */ +static int si4713_write_property(struct si4713_device *sdev, u16 prop, u16 val) +{ + int rval; + u8 resp[SI4713_SET_PROP_NRESP]; + /* + * .First byte = 0 + * .Second byte = property's MSB + * .Third byte = property's LSB + * .Fourth byte = value's MSB + * .Fifth byte = value's LSB + */ + const u8 args[SI4713_SET_PROP_NARGS] = { + 0x00, + msb(prop), + lsb(prop), + msb(val), + lsb(val), + }; + + rval = si4713_send_command(sdev, SI4713_CMD_SET_PROPERTY, + args, ARRAY_SIZE(args), + resp, ARRAY_SIZE(resp), + DEFAULT_TIMEOUT); + + if (rval < 0) + return rval; + + v4l2_dbg(1, debug, &sdev->sd, + "%s: property=0x%02x value=0x%02x status=0x%02x\n", + __func__, prop, val, resp[0]); + + /* + * As there is no command response for SET_PROPERTY, + * wait Tcomp time to finish before proceed, in order + * to have property properly set. + */ + msleep(TIMEOUT_SET_PROPERTY); + + return rval; +} + +/* + * si4713_powerup - Powers the device up + * @sdev: si4713_device structure for the device we are communicating + */ +static int si4713_powerup(struct si4713_device *sdev) +{ + int err; + u8 resp[SI4713_PWUP_NRESP]; + /* + * .First byte = Enabled interrupts and boot function + * .Second byte = Input operation mode + */ + const u8 args[SI4713_PWUP_NARGS] = { + SI4713_PWUP_CTSIEN | SI4713_PWUP_GPO2OEN | SI4713_PWUP_FUNC_TX, + SI4713_PWUP_OPMOD_ANALOG, + }; + + if (sdev->power_state) + return 0; + + sdev->platform_data->set_power(1); + err = si4713_send_command(sdev, SI4713_CMD_POWER_UP, + args, ARRAY_SIZE(args), + resp, ARRAY_SIZE(resp), + TIMEOUT_POWER_UP); + + if (!err) { + v4l2_dbg(1, debug, &sdev->sd, "Powerup response: 0x%02x\n", + resp[0]); + v4l2_dbg(1, debug, &sdev->sd, "Device in power up mode\n"); + sdev->power_state = POWER_ON; + + err = si4713_write_property(sdev, SI4713_GPO_IEN, + SI4713_STC_INT | SI4713_CTS); + } else { + sdev->platform_data->set_power(0); + } + + return err; +} + +/* + * si4713_powerdown - Powers the device down + * @sdev: si4713_device structure for the device we are communicating + */ +static int si4713_powerdown(struct si4713_device *sdev) +{ + int err; + u8 resp[SI4713_PWDN_NRESP]; + + if (!sdev->power_state) + return 0; + + err = si4713_send_command(sdev, SI4713_CMD_POWER_DOWN, + NULL, 0, + resp, ARRAY_SIZE(resp), + DEFAULT_TIMEOUT); + + if (!err) { + v4l2_dbg(1, debug, &sdev->sd, "Power down response: 0x%02x\n", + resp[0]); + v4l2_dbg(1, debug, &sdev->sd, "Device in reset mode\n"); + sdev->platform_data->set_power(0); + sdev->power_state = POWER_OFF; + } + + return err; +} + +/* + * si4713_checkrev - Checks if we are treating a device with the correct rev. + * @sdev: si4713_device structure for the device we are communicating + */ +static int si4713_checkrev(struct si4713_device *sdev) +{ + struct i2c_client *client = v4l2_get_subdevdata(&sdev->sd); + int rval; + u8 resp[SI4713_GETREV_NRESP]; + + mutex_lock(&sdev->mutex); + + rval = si4713_send_command(sdev, SI4713_CMD_GET_REV, + NULL, 0, + resp, ARRAY_SIZE(resp), + DEFAULT_TIMEOUT); + + if (rval < 0) + goto unlock; + + if (resp[1] == SI4713_PRODUCT_NUMBER) { + v4l2_info(&sdev->sd, "chip found @ 0x%02x (%s)\n", + client->addr << 1, client->adapter->name); + } else { + v4l2_err(&sdev->sd, "Invalid product number\n"); + rval = -EINVAL; + } + +unlock: + mutex_unlock(&sdev->mutex); + return rval; +} + +/* + * si4713_wait_stc - Waits STC interrupt and clears status bits. Usefull + * for TX_TUNE_POWER, TX_TUNE_FREQ and TX_TUNE_MEAS + * @sdev: si4713_device structure for the device we are communicating + * @usecs: timeout to wait for STC interrupt signal + */ +static int si4713_wait_stc(struct si4713_device *sdev, const int usecs) +{ + int err; + u8 resp[SI4713_GET_STATUS_NRESP]; + + /* Wait response from STC interrupt */ + if (!wait_for_completion_timeout(&sdev->work, + usecs_to_jiffies(usecs) + 1)) + v4l2_warn(&sdev->sd, + "%s: device took too much time to answer (%d usec).\n", + __func__, usecs); + + /* Clear status bits */ + err = si4713_send_command(sdev, SI4713_CMD_GET_INT_STATUS, + NULL, 0, + resp, ARRAY_SIZE(resp), + DEFAULT_TIMEOUT); + + if (err < 0) + goto exit; + + v4l2_dbg(1, debug, &sdev->sd, + "%s: status bits: 0x%02x\n", __func__, resp[0]); + + if (!(resp[0] & SI4713_STC_INT)) + err = -EIO; + +exit: + return err; +} + +/* + * si4713_tx_tune_freq - Sets the state of the RF carrier and sets the tuning + * frequency between 76 and 108 MHz in 10 kHz units and + * steps of 50 kHz. + * @sdev: si4713_device structure for the device we are communicating + * @frequency: desired frequency (76 - 108 MHz, unit 10 KHz, step 50 kHz) + */ +static int si4713_tx_tune_freq(struct si4713_device *sdev, u16 frequency) +{ + int err; + u8 val[SI4713_TXFREQ_NRESP]; + /* + * .First byte = 0 + * .Second byte = frequency's MSB + * .Third byte = frequency's LSB + */ + const u8 args[SI4713_TXFREQ_NARGS] = { + 0x00, + msb(frequency), + lsb(frequency), + }; + + err = si4713_send_command(sdev, SI4713_CMD_TX_TUNE_FREQ, + args, ARRAY_SIZE(args), val, + ARRAY_SIZE(val), DEFAULT_TIMEOUT); + + if (err < 0) + return err; + + v4l2_dbg(1, debug, &sdev->sd, + "%s: frequency=0x%02x status=0x%02x\n", __func__, + frequency, val[0]); + + err = si4713_wait_stc(sdev, TIMEOUT_TX_TUNE); + if (err < 0) + return err; + + return compose_u16(args[1], args[2]); +} + +/* + * si4713_tx_tune_power - Sets the RF voltage level between 88 and 115 dBuV in + * 1 dB units. A value of 0x00 indicates off. The command + * also sets the antenna tuning capacitance. A value of 0 + * indicates autotuning, and a value of 1 - 191 indicates + * a manual override, which results in a tuning + * capacitance of 0.25 pF x @antcap. + * @sdev: si4713_device structure for the device we are communicating + * @power: tuning power (88 - 115 dBuV, unit/step 1 dB) + * @antcap: value of antenna tuning capacitor (0 - 191) + */ +static int si4713_tx_tune_power(struct si4713_device *sdev, u8 power, + u8 antcap) +{ + int err; + u8 val[SI4713_TXPWR_NRESP]; + /* + * .First byte = 0 + * .Second byte = 0 + * .Third byte = power + * .Fourth byte = antcap + */ + const u8 args[SI4713_TXPWR_NARGS] = { + 0x00, + 0x00, + power, + antcap, + }; + + if (((power > 0) && (power < SI4713_MIN_POWER)) || + power > SI4713_MAX_POWER || antcap > SI4713_MAX_ANTCAP) + return -EDOM; + + err = si4713_send_command(sdev, SI4713_CMD_TX_TUNE_POWER, + args, ARRAY_SIZE(args), val, + ARRAY_SIZE(val), DEFAULT_TIMEOUT); + + if (err < 0) + return err; + + v4l2_dbg(1, debug, &sdev->sd, + "%s: power=0x%02x antcap=0x%02x status=0x%02x\n", + __func__, power, antcap, val[0]); + + return si4713_wait_stc(sdev, TIMEOUT_TX_TUNE_POWER); +} + +/* + * si4713_tx_tune_measure - Enters receive mode and measures the received noise + * level in units of dBuV on the selected frequency. + * The Frequency must be between 76 and 108 MHz in 10 kHz + * units and steps of 50 kHz. The command also sets the + * antenna tuning capacitance. A value of 0 means + * autotuning, and a value of 1 to 191 indicates manual + * override. + * @sdev: si4713_device structure for the device we are communicating + * @frequency: desired frequency (76 - 108 MHz, unit 10 KHz, step 50 kHz) + * @antcap: value of antenna tuning capacitor (0 - 191) + */ +static int si4713_tx_tune_measure(struct si4713_device *sdev, u16 frequency, + u8 antcap) +{ + int err; + u8 val[SI4713_TXMEA_NRESP]; + /* + * .First byte = 0 + * .Second byte = frequency's MSB + * .Third byte = frequency's LSB + * .Fourth byte = antcap + */ + const u8 args[SI4713_TXMEA_NARGS] = { + 0x00, + msb(frequency), + lsb(frequency), + antcap, + }; + + sdev->tune_rnl = DEFAULT_TUNE_RNL; + + if (antcap > SI4713_MAX_ANTCAP) + return -EDOM; + + err = si4713_send_command(sdev, SI4713_CMD_TX_TUNE_MEASURE, + args, ARRAY_SIZE(args), val, + ARRAY_SIZE(val), DEFAULT_TIMEOUT); + + if (err < 0) + return err; + + v4l2_dbg(1, debug, &sdev->sd, + "%s: frequency=0x%02x antcap=0x%02x status=0x%02x\n", + __func__, frequency, antcap, val[0]); + + return si4713_wait_stc(sdev, TIMEOUT_TX_TUNE); +} + +/* + * si4713_tx_tune_status- Returns the status of the tx_tune_freq, tx_tune_mea or + * tx_tune_power commands. This command return the current + * frequency, output voltage in dBuV, the antenna tunning + * capacitance value and the received noise level. The + * command also clears the stcint interrupt bit when the + * first bit of its arguments is high. + * @sdev: si4713_device structure for the device we are communicating + * @intack: 0x01 to clear the seek/tune complete interrupt status indicator. + * @frequency: returned frequency + * @power: returned power + * @antcap: returned antenna capacitance + * @noise: returned noise level + */ +static int si4713_tx_tune_status(struct si4713_device *sdev, u8 intack, + u16 *frequency, u8 *power, + u8 *antcap, u8 *noise) +{ + int err; + u8 val[SI4713_TXSTATUS_NRESP]; + /* + * .First byte = intack bit + */ + const u8 args[SI4713_TXSTATUS_NARGS] = { + intack & SI4713_INTACK_MASK, + }; + + err = si4713_send_command(sdev, SI4713_CMD_TX_TUNE_STATUS, + args, ARRAY_SIZE(args), val, + ARRAY_SIZE(val), DEFAULT_TIMEOUT); + + if (!err) { + v4l2_dbg(1, debug, &sdev->sd, + "%s: status=0x%02x\n", __func__, val[0]); + *frequency = compose_u16(val[2], val[3]); + sdev->frequency = *frequency; + *power = val[5]; + *antcap = val[6]; + *noise = val[7]; + v4l2_dbg(1, debug, &sdev->sd, "%s: response: %d x 10 kHz " + "(power %d, antcap %d, rnl %d)\n", __func__, + *frequency, *power, *antcap, *noise); + } + + return err; +} + +/* + * si4713_tx_rds_buff - Loads the RDS group buffer FIFO or circular buffer. + * @sdev: si4713_device structure for the device we are communicating + * @mode: the buffer operation mode. + * @rdsb: RDS Block B + * @rdsc: RDS Block C + * @rdsd: RDS Block D + * @cbleft: returns the number of available circular buffer blocks minus the + * number of used circular buffer blocks. + */ +static int si4713_tx_rds_buff(struct si4713_device *sdev, u8 mode, u16 rdsb, + u16 rdsc, u16 rdsd, s8 *cbleft) +{ + int err; + u8 val[SI4713_RDSBUFF_NRESP]; + + const u8 args[SI4713_RDSBUFF_NARGS] = { + mode & SI4713_RDSBUFF_MODE_MASK, + msb(rdsb), + lsb(rdsb), + msb(rdsc), + lsb(rdsc), + msb(rdsd), + lsb(rdsd), + }; + + err = si4713_send_command(sdev, SI4713_CMD_TX_RDS_BUFF, + args, ARRAY_SIZE(args), val, + ARRAY_SIZE(val), DEFAULT_TIMEOUT); + + if (!err) { + v4l2_dbg(1, debug, &sdev->sd, + "%s: status=0x%02x\n", __func__, val[0]); + *cbleft = (s8)val[2] - val[3]; + v4l2_dbg(1, debug, &sdev->sd, "%s: response: interrupts" + " 0x%02x cb avail: %d cb used %d fifo avail" + " %d fifo used %d\n", __func__, val[1], + val[2], val[3], val[4], val[5]); + } + + return err; +} + +/* + * si4713_tx_rds_ps - Loads the program service buffer. + * @sdev: si4713_device structure for the device we are communicating + * @psid: program service id to be loaded. + * @pschar: assumed 4 size char array to be loaded into the program service + */ +static int si4713_tx_rds_ps(struct si4713_device *sdev, u8 psid, + unsigned char *pschar) +{ + int err; + u8 val[SI4713_RDSPS_NRESP]; + + const u8 args[SI4713_RDSPS_NARGS] = { + psid & SI4713_RDSPS_PSID_MASK, + pschar[0], + pschar[1], + pschar[2], + pschar[3], + }; + + err = si4713_send_command(sdev, SI4713_CMD_TX_RDS_PS, + args, ARRAY_SIZE(args), val, + ARRAY_SIZE(val), DEFAULT_TIMEOUT); + + if (err < 0) + return err; + + v4l2_dbg(1, debug, &sdev->sd, "%s: status=0x%02x\n", __func__, val[0]); + + return err; +} + +static int si4713_set_power_state(struct si4713_device *sdev, u8 value) +{ + int rval; + + mutex_lock(&sdev->mutex); + + if (value) + rval = si4713_powerup(sdev); + else + rval = si4713_powerdown(sdev); + + mutex_unlock(&sdev->mutex); + return rval; +} + +static int si4713_set_mute(struct si4713_device *sdev, u16 mute) +{ + int rval = 0; + + mute = set_mute(mute); + + mutex_lock(&sdev->mutex); + + if (sdev->power_state) + rval = si4713_write_property(sdev, + SI4713_TX_LINE_INPUT_MUTE, mute); + + if (rval >= 0) + sdev->mute = get_mute(mute); + + mutex_unlock(&sdev->mutex); + + return rval; +} + +static int si4713_set_rds_ps_name(struct si4713_device *sdev, char *ps_name) +{ + int rval = 0, i; + u8 len = 0; + + /* We want to clear the whole thing */ + if (!strlen(ps_name)) + memset(ps_name, 0, MAX_RDS_PS_NAME + 1); + + mutex_lock(&sdev->mutex); + + if (sdev->power_state) { + /* Write the new ps name and clear the padding */ + for (i = 0; i < MAX_RDS_PS_NAME; i += (RDS_BLOCK / 2)) { + rval = si4713_tx_rds_ps(sdev, (i / (RDS_BLOCK / 2)), + ps_name + i); + if (rval < 0) + goto unlock; + } + + /* Setup the size to be sent */ + if (strlen(ps_name)) + len = strlen(ps_name) - 1; + else + len = 1; + + rval = si4713_write_property(sdev, + SI4713_TX_RDS_PS_MESSAGE_COUNT, + rds_ps_nblocks(len)); + if (rval < 0) + goto unlock; + + rval = si4713_write_property(sdev, + SI4713_TX_RDS_PS_REPEAT_COUNT, + DEFAULT_RDS_PS_REPEAT_COUNT * 2); + if (rval < 0) + goto unlock; + } + + strncpy(sdev->rds_info.ps_name, ps_name, MAX_RDS_PS_NAME); + +unlock: + mutex_unlock(&sdev->mutex); + return rval; +} + +static int si4713_set_rds_radio_text(struct si4713_device *sdev, char *rt) +{ + int rval = 0, i; + u16 t_index = 0; + u8 b_index = 0, cr_inserted = 0; + s8 left; + + mutex_lock(&sdev->mutex); + + if (!sdev->power_state) + goto copy; + + rval = si4713_tx_rds_buff(sdev, RDS_BLOCK_CLEAR, 0, 0, 0, &left); + if (rval < 0) + goto unlock; + + if (!strlen(rt)) + goto copy; + + do { + /* RDS spec says that if the last block isn't used, + * then apply a carriage return + */ + if (t_index < (RDS_RADIOTEXT_INDEX_MAX * + RDS_RADIOTEXT_BLK_SIZE)) { + for (i = 0; i < RDS_RADIOTEXT_BLK_SIZE; i++) { + if (!rt[t_index + i] || rt[t_index + i] == + RDS_CARRIAGE_RETURN) { + rt[t_index + i] = RDS_CARRIAGE_RETURN; + cr_inserted = 1; + break; + } + } + } + + rval = si4713_tx_rds_buff(sdev, RDS_BLOCK_LOAD, + compose_u16(RDS_RADIOTEXT_2A, b_index++), + compose_u16(rt[t_index], rt[t_index + 1]), + compose_u16(rt[t_index + 2], rt[t_index + 3]), + &left); + if (rval < 0) + goto unlock; + + t_index += RDS_RADIOTEXT_BLK_SIZE; + + if (cr_inserted) + break; + } while (left > 0); + +copy: + strncpy(sdev->rds_info.radio_text, rt, MAX_RDS_RADIO_TEXT); + +unlock: + mutex_unlock(&sdev->mutex); + return rval; +} + +static int si4713_choose_econtrol_action(struct si4713_device *sdev, u32 id, + u32 **shadow, s32 *bit, s32 *mask, u16 *property, int *mul, + unsigned long **table, int *size) +{ + s32 rval = 0; + + switch (id) { + /* FM_TX class controls */ + case V4L2_CID_RDS_TX_PI: + *property = SI4713_TX_RDS_PI; + *mul = 1; + *shadow = &sdev->rds_info.pi; + break; + case V4L2_CID_AUDIO_COMPRESSION_THRESHOLD: + *property = SI4713_TX_ACOMP_THRESHOLD; + *mul = 1; + *shadow = &sdev->acomp_info.threshold; + break; + case V4L2_CID_AUDIO_COMPRESSION_GAIN: + *property = SI4713_TX_ACOMP_GAIN; + *mul = 1; + *shadow = &sdev->acomp_info.gain; + break; + case V4L2_CID_PILOT_TONE_FREQUENCY: + *property = SI4713_TX_PILOT_FREQUENCY; + *mul = 1; + *shadow = &sdev->pilot_info.frequency; + break; + case V4L2_CID_AUDIO_COMPRESSION_ATTACK_TIME: + *property = SI4713_TX_ACOMP_ATTACK_TIME; + *mul = ATTACK_TIME_UNIT; + *shadow = &sdev->acomp_info.attack_time; + break; + case V4L2_CID_PILOT_TONE_DEVIATION: + *property = SI4713_TX_PILOT_DEVIATION; + *mul = 10; + *shadow = &sdev->pilot_info.deviation; + break; + case V4L2_CID_AUDIO_LIMITER_DEVIATION: + *property = SI4713_TX_AUDIO_DEVIATION; + *mul = 10; + *shadow = &sdev->limiter_info.deviation; + break; + case V4L2_CID_RDS_TX_DEVIATION: + *property = SI4713_TX_RDS_DEVIATION; + *mul = 1; + *shadow = &sdev->rds_info.deviation; + break; + + case V4L2_CID_RDS_TX_PTY: + *property = SI4713_TX_RDS_PS_MISC; + *bit = 5; + *mask = 0x1F << 5; + *shadow = &sdev->rds_info.pty; + break; + case V4L2_CID_AUDIO_LIMITER_ENABLED: + *property = SI4713_TX_ACOMP_ENABLE; + *bit = 1; + *mask = 1 << 1; + *shadow = &sdev->limiter_info.enabled; + break; + case V4L2_CID_AUDIO_COMPRESSION_ENABLED: + *property = SI4713_TX_ACOMP_ENABLE; + *bit = 0; + *mask = 1 << 0; + *shadow = &sdev->acomp_info.enabled; + break; + case V4L2_CID_PILOT_TONE_ENABLED: + *property = SI4713_TX_COMPONENT_ENABLE; + *bit = 0; + *mask = 1 << 0; + *shadow = &sdev->pilot_info.enabled; + break; + + case V4L2_CID_AUDIO_LIMITER_RELEASE_TIME: + *property = SI4713_TX_LIMITER_RELEASE_TIME; + *table = limiter_times; + *size = ARRAY_SIZE(limiter_times); + *shadow = &sdev->limiter_info.release_time; + break; + case V4L2_CID_AUDIO_COMPRESSION_RELEASE_TIME: + *property = SI4713_TX_ACOMP_RELEASE_TIME; + *table = acomp_rtimes; + *size = ARRAY_SIZE(acomp_rtimes); + *shadow = &sdev->acomp_info.release_time; + break; + case V4L2_CID_TUNE_PREEMPHASIS: + *property = SI4713_TX_PREEMPHASIS; + *table = preemphasis_values; + *size = ARRAY_SIZE(preemphasis_values); + *shadow = &sdev->preemphasis; + break; + + default: + rval = -EINVAL; + }; + + return rval; +} + +static int si4713_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc); + +/* write string property */ +static int si4713_write_econtrol_string(struct si4713_device *sdev, + struct v4l2_ext_control *control) +{ + struct v4l2_queryctrl vqc; + int len; + s32 rval = 0; + + vqc.id = control->id; + rval = si4713_queryctrl(&sdev->sd, &vqc); + if (rval < 0) + goto exit; + + switch (control->id) { + case V4L2_CID_RDS_TX_PS_NAME: { + char ps_name[MAX_RDS_PS_NAME + 1]; + + len = control->size - 1; + if (len > MAX_RDS_PS_NAME) { + rval = -ERANGE; + goto exit; + } + rval = copy_from_user(ps_name, control->string, len); + if (rval < 0) + goto exit; + ps_name[len] = '\0'; + + if (strlen(ps_name) % vqc.step) { + rval = -ERANGE; + goto exit; + } + + rval = si4713_set_rds_ps_name(sdev, ps_name); + } + break; + + case V4L2_CID_RDS_TX_RADIO_TEXT: { + char radio_text[MAX_RDS_RADIO_TEXT + 1]; + + len = control->size - 1; + if (len > MAX_RDS_RADIO_TEXT) { + rval = -ERANGE; + goto exit; + } + rval = copy_from_user(radio_text, control->string, len); + if (rval < 0) + goto exit; + radio_text[len] = '\0'; + + if (strlen(radio_text) % vqc.step) { + rval = -ERANGE; + goto exit; + } + + rval = si4713_set_rds_radio_text(sdev, radio_text); + } + break; + + default: + rval = -EINVAL; + break; + }; + +exit: + return rval; +} + +static int validate_range(struct v4l2_subdev *sd, + struct v4l2_ext_control *control) +{ + struct v4l2_queryctrl vqc; + int rval; + + vqc.id = control->id; + rval = si4713_queryctrl(sd, &vqc); + if (rval < 0) + goto exit; + + if (control->value < vqc.minimum || control->value > vqc.maximum) + rval = -ERANGE; + +exit: + return rval; +} + +/* properties which use tx_tune_power*/ +static int si4713_write_econtrol_tune(struct si4713_device *sdev, + struct v4l2_ext_control *control) +{ + s32 rval = 0; + u8 power, antcap; + + rval = validate_range(&sdev->sd, control); + if (rval < 0) + goto exit; + + mutex_lock(&sdev->mutex); + + switch (control->id) { + case V4L2_CID_TUNE_POWER_LEVEL: + power = control->value; + antcap = sdev->antenna_capacitor; + break; + case V4L2_CID_TUNE_ANTENNA_CAPACITOR: + power = sdev->power_level; + antcap = control->value; + break; + default: + rval = -EINVAL; + goto unlock; + }; + + if (sdev->power_state) + rval = si4713_tx_tune_power(sdev, power, antcap); + + if (rval == 0) { + sdev->power_level = power; + sdev->antenna_capacitor = antcap; + } + +unlock: + mutex_unlock(&sdev->mutex); +exit: + return rval; +} + +static int si4713_write_econtrol_integers(struct si4713_device *sdev, + struct v4l2_ext_control *control) +{ + s32 rval; + u32 *shadow = NULL, val = 0; + s32 bit = 0, mask = 0; + u16 property = 0; + int mul = 0; + unsigned long *table = NULL; + int size = 0; + + rval = validate_range(&sdev->sd, control); + if (rval < 0) + goto exit; + + rval = si4713_choose_econtrol_action(sdev, control->id, &shadow, &bit, + &mask, &property, &mul, &table, &size); + if (rval < 0) + goto exit; + + val = control->value; + if (mul) { + val = control->value / mul; + } else if (table) { + rval = usecs_to_dev(control->value, table, size); + if (rval < 0) + goto exit; + val = rval; + rval = 0; + } + + mutex_lock(&sdev->mutex); + + if (sdev->power_state) { + if (mask) { + rval = si4713_read_property(sdev, property, &val); + if (rval < 0) + goto unlock; + val = set_bits(val, control->value, bit, mask); + } + + rval = si4713_write_property(sdev, property, val); + if (rval < 0) + goto unlock; + if (mask) + val = control->value; + } + + if (mul) { + *shadow = val * mul; + } else if (table) { + rval = dev_to_usecs(val, table, size); + if (rval < 0) + goto unlock; + *shadow = rval; + rval = 0; + } else { + *shadow = val; + } + +unlock: + mutex_unlock(&sdev->mutex); +exit: + return rval; +} + +static int si4713_s_frequency(struct v4l2_subdev *sd, struct v4l2_frequency *f); +static int si4713_s_modulator(struct v4l2_subdev *sd, struct v4l2_modulator *); +/* + * si4713_setup - Sets the device up with current configuration. + * @sdev: si4713_device structure for the device we are communicating + */ +static int si4713_setup(struct si4713_device *sdev) +{ + struct v4l2_ext_control ctrl; + struct v4l2_frequency f; + struct v4l2_modulator vm; + struct si4713_device *tmp; + int rval = 0; + + tmp = kmalloc(sizeof(*tmp), GFP_KERNEL); + if (!tmp) + return -ENOMEM; + + /* Get a local copy to avoid race */ + mutex_lock(&sdev->mutex); + memcpy(tmp, sdev, sizeof(*sdev)); + mutex_unlock(&sdev->mutex); + + ctrl.id = V4L2_CID_RDS_TX_PI; + ctrl.value = tmp->rds_info.pi; + rval |= si4713_write_econtrol_integers(sdev, &ctrl); + + ctrl.id = V4L2_CID_AUDIO_COMPRESSION_THRESHOLD; + ctrl.value = tmp->acomp_info.threshold; + rval |= si4713_write_econtrol_integers(sdev, &ctrl); + + ctrl.id = V4L2_CID_AUDIO_COMPRESSION_GAIN; + ctrl.value = tmp->acomp_info.gain; + rval |= si4713_write_econtrol_integers(sdev, &ctrl); + + ctrl.id = V4L2_CID_PILOT_TONE_FREQUENCY; + ctrl.value = tmp->pilot_info.frequency; + rval |= si4713_write_econtrol_integers(sdev, &ctrl); + + ctrl.id = V4L2_CID_AUDIO_COMPRESSION_ATTACK_TIME; + ctrl.value = tmp->acomp_info.attack_time; + rval |= si4713_write_econtrol_integers(sdev, &ctrl); + + ctrl.id = V4L2_CID_PILOT_TONE_DEVIATION; + ctrl.value = tmp->pilot_info.deviation; + rval |= si4713_write_econtrol_integers(sdev, &ctrl); + + ctrl.id = V4L2_CID_AUDIO_LIMITER_DEVIATION; + ctrl.value = tmp->limiter_info.deviation; + rval |= si4713_write_econtrol_integers(sdev, &ctrl); + + ctrl.id = V4L2_CID_RDS_TX_DEVIATION; + ctrl.value = tmp->rds_info.deviation; + rval |= si4713_write_econtrol_integers(sdev, &ctrl); + + ctrl.id = V4L2_CID_RDS_TX_PTY; + ctrl.value = tmp->rds_info.pty; + rval |= si4713_write_econtrol_integers(sdev, &ctrl); + + ctrl.id = V4L2_CID_AUDIO_LIMITER_ENABLED; + ctrl.value = tmp->limiter_info.enabled; + rval |= si4713_write_econtrol_integers(sdev, &ctrl); + + ctrl.id = V4L2_CID_AUDIO_COMPRESSION_ENABLED; + ctrl.value = tmp->acomp_info.enabled; + rval |= si4713_write_econtrol_integers(sdev, &ctrl); + + ctrl.id = V4L2_CID_PILOT_TONE_ENABLED; + ctrl.value = tmp->pilot_info.enabled; + rval |= si4713_write_econtrol_integers(sdev, &ctrl); + + ctrl.id = V4L2_CID_AUDIO_LIMITER_RELEASE_TIME; + ctrl.value = tmp->limiter_info.release_time; + rval |= si4713_write_econtrol_integers(sdev, &ctrl); + + ctrl.id = V4L2_CID_AUDIO_COMPRESSION_RELEASE_TIME; + ctrl.value = tmp->acomp_info.release_time; + rval |= si4713_write_econtrol_integers(sdev, &ctrl); + + ctrl.id = V4L2_CID_TUNE_PREEMPHASIS; + ctrl.value = tmp->preemphasis; + rval |= si4713_write_econtrol_integers(sdev, &ctrl); + + ctrl.id = V4L2_CID_RDS_TX_PS_NAME; + rval |= si4713_set_rds_ps_name(sdev, tmp->rds_info.ps_name); + + ctrl.id = V4L2_CID_RDS_TX_RADIO_TEXT; + rval |= si4713_set_rds_radio_text(sdev, tmp->rds_info.radio_text); + + /* Device procedure needs to set frequency first */ + f.frequency = tmp->frequency ? tmp->frequency : DEFAULT_FREQUENCY; + f.frequency = si4713_to_v4l2(f.frequency); + rval |= si4713_s_frequency(&sdev->sd, &f); + + ctrl.id = V4L2_CID_TUNE_POWER_LEVEL; + ctrl.value = tmp->power_level; + rval |= si4713_write_econtrol_tune(sdev, &ctrl); + + ctrl.id = V4L2_CID_TUNE_ANTENNA_CAPACITOR; + ctrl.value = tmp->antenna_capacitor; + rval |= si4713_write_econtrol_tune(sdev, &ctrl); + + vm.index = 0; + if (tmp->stereo) + vm.txsubchans = V4L2_TUNER_SUB_STEREO; + else + vm.txsubchans = V4L2_TUNER_SUB_MONO; + if (tmp->rds_info.enabled) + vm.txsubchans |= V4L2_TUNER_SUB_RDS; + si4713_s_modulator(&sdev->sd, &vm); + + kfree(tmp); + + return rval; +} + +/* + * si4713_initialize - Sets the device up with default configuration. + * @sdev: si4713_device structure for the device we are communicating + */ +static int si4713_initialize(struct si4713_device *sdev) +{ + int rval; + + rval = si4713_set_power_state(sdev, POWER_ON); + if (rval < 0) + goto exit; + + rval = si4713_checkrev(sdev); + if (rval < 0) + goto exit; + + rval = si4713_set_power_state(sdev, POWER_OFF); + if (rval < 0) + goto exit; + + mutex_lock(&sdev->mutex); + + sdev->rds_info.pi = DEFAULT_RDS_PI; + sdev->rds_info.pty = DEFAULT_RDS_PTY; + sdev->rds_info.deviation = DEFAULT_RDS_DEVIATION; + strlcpy(sdev->rds_info.ps_name, DEFAULT_RDS_PS_NAME, MAX_RDS_PS_NAME); + strlcpy(sdev->rds_info.radio_text, DEFAULT_RDS_RADIO_TEXT, + MAX_RDS_RADIO_TEXT); + sdev->rds_info.enabled = 1; + + sdev->limiter_info.release_time = DEFAULT_LIMITER_RTIME; + sdev->limiter_info.deviation = DEFAULT_LIMITER_DEV; + sdev->limiter_info.enabled = 1; + + sdev->pilot_info.deviation = DEFAULT_PILOT_DEVIATION; + sdev->pilot_info.frequency = DEFAULT_PILOT_FREQUENCY; + sdev->pilot_info.enabled = 1; + + sdev->acomp_info.release_time = DEFAULT_ACOMP_RTIME; + sdev->acomp_info.attack_time = DEFAULT_ACOMP_ATIME; + sdev->acomp_info.threshold = DEFAULT_ACOMP_THRESHOLD; + sdev->acomp_info.gain = DEFAULT_ACOMP_GAIN; + sdev->acomp_info.enabled = 1; + + sdev->frequency = DEFAULT_FREQUENCY; + sdev->preemphasis = DEFAULT_PREEMPHASIS; + sdev->mute = DEFAULT_MUTE; + sdev->power_level = DEFAULT_POWER_LEVEL; + sdev->antenna_capacitor = 0; + sdev->stereo = 1; + sdev->tune_rnl = DEFAULT_TUNE_RNL; + + mutex_unlock(&sdev->mutex); + +exit: + return rval; +} + +/* read string property */ +static int si4713_read_econtrol_string(struct si4713_device *sdev, + struct v4l2_ext_control *control) +{ + s32 rval = 0; + + switch (control->id) { + case V4L2_CID_RDS_TX_PS_NAME: + if (strlen(sdev->rds_info.ps_name) + 1 > control->size) { + control->size = MAX_RDS_PS_NAME + 1; + rval = -ENOSPC; + goto exit; + } + rval = copy_to_user(control->string, sdev->rds_info.ps_name, + strlen(sdev->rds_info.ps_name) + 1); + break; + + case V4L2_CID_RDS_TX_RADIO_TEXT: + if (strlen(sdev->rds_info.radio_text) + 1 > control->size) { + control->size = MAX_RDS_RADIO_TEXT + 1; + rval = -ENOSPC; + goto exit; + } + rval = copy_to_user(control->string, sdev->rds_info.radio_text, + strlen(sdev->rds_info.radio_text) + 1); + break; + + default: + rval = -EINVAL; + break; + }; + +exit: + return rval; +} + +/* + * si4713_update_tune_status - update properties from tx_tune_status + * command. Must be called with sdev->mutex held. + * @sdev: si4713_device structure for the device we are communicating + */ +static int si4713_update_tune_status(struct si4713_device *sdev) +{ + int rval; + u16 f = 0; + u8 p = 0, a = 0, n = 0; + + rval = si4713_tx_tune_status(sdev, 0x00, &f, &p, &a, &n); + + if (rval < 0) + goto exit; + + sdev->power_level = p; + sdev->antenna_capacitor = a; + sdev->tune_rnl = n; + +exit: + return rval; +} + +/* properties which use tx_tune_status */ +static int si4713_read_econtrol_tune(struct si4713_device *sdev, + struct v4l2_ext_control *control) +{ + s32 rval = 0; + + mutex_lock(&sdev->mutex); + + if (sdev->power_state) { + rval = si4713_update_tune_status(sdev); + if (rval < 0) + goto unlock; + } + + switch (control->id) { + case V4L2_CID_TUNE_POWER_LEVEL: + control->value = sdev->power_level; + break; + case V4L2_CID_TUNE_ANTENNA_CAPACITOR: + control->value = sdev->antenna_capacitor; + break; + default: + rval = -EINVAL; + }; + +unlock: + mutex_unlock(&sdev->mutex); + return rval; +} + +static int si4713_read_econtrol_integers(struct si4713_device *sdev, + struct v4l2_ext_control *control) +{ + s32 rval; + u32 *shadow = NULL, val = 0; + s32 bit = 0, mask = 0; + u16 property = 0; + int mul = 0; + unsigned long *table = NULL; + int size = 0; + + rval = si4713_choose_econtrol_action(sdev, control->id, &shadow, &bit, + &mask, &property, &mul, &table, &size); + if (rval < 0) + goto exit; + + mutex_lock(&sdev->mutex); + + if (sdev->power_state) { + rval = si4713_read_property(sdev, property, &val); + if (rval < 0) + goto unlock; + + /* Keep negative values for threshold */ + if (control->id == V4L2_CID_AUDIO_COMPRESSION_THRESHOLD) + *shadow = (s16)val; + else if (mask) + *shadow = get_status_bit(val, bit, mask); + else if (mul) + *shadow = val * mul; + else + *shadow = dev_to_usecs(val, table, size); + } + + control->value = *shadow; + +unlock: + mutex_unlock(&sdev->mutex); +exit: + return rval; +} + +/* + * Video4Linux Subdev Interface + */ +/* si4713_s_ext_ctrls - set extended controls value */ +static int si4713_s_ext_ctrls(struct v4l2_subdev *sd, + struct v4l2_ext_controls *ctrls) +{ + struct si4713_device *sdev = to_si4713_device(sd); + int i; + + if (ctrls->ctrl_class != V4L2_CTRL_CLASS_FM_TX) + return -EINVAL; + + for (i = 0; i < ctrls->count; i++) { + int err; + + switch ((ctrls->controls + i)->id) { + case V4L2_CID_RDS_TX_PS_NAME: + case V4L2_CID_RDS_TX_RADIO_TEXT: + err = si4713_write_econtrol_string(sdev, + ctrls->controls + i); + break; + case V4L2_CID_TUNE_ANTENNA_CAPACITOR: + case V4L2_CID_TUNE_POWER_LEVEL: + err = si4713_write_econtrol_tune(sdev, + ctrls->controls + i); + break; + default: + err = si4713_write_econtrol_integers(sdev, + ctrls->controls + i); + } + + if (err < 0) { + ctrls->error_idx = i; + return err; + } + } + + return 0; +} + +/* si4713_g_ext_ctrls - get extended controls value */ +static int si4713_g_ext_ctrls(struct v4l2_subdev *sd, + struct v4l2_ext_controls *ctrls) +{ + struct si4713_device *sdev = to_si4713_device(sd); + int i; + + if (ctrls->ctrl_class != V4L2_CTRL_CLASS_FM_TX) + return -EINVAL; + + for (i = 0; i < ctrls->count; i++) { + int err; + + switch ((ctrls->controls + i)->id) { + case V4L2_CID_RDS_TX_PS_NAME: + case V4L2_CID_RDS_TX_RADIO_TEXT: + err = si4713_read_econtrol_string(sdev, + ctrls->controls + i); + break; + case V4L2_CID_TUNE_ANTENNA_CAPACITOR: + case V4L2_CID_TUNE_POWER_LEVEL: + err = si4713_read_econtrol_tune(sdev, + ctrls->controls + i); + break; + default: + err = si4713_read_econtrol_integers(sdev, + ctrls->controls + i); + } + + if (err < 0) { + ctrls->error_idx = i; + return err; + } + } + + return 0; +} + +/* si4713_queryctrl - enumerate control items */ +static int si4713_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc) +{ + int rval = 0; + + switch (qc->id) { + /* User class controls */ + case V4L2_CID_AUDIO_MUTE: + rval = v4l2_ctrl_query_fill(qc, 0, 1, 1, DEFAULT_MUTE); + break; + /* FM_TX class controls */ + case V4L2_CID_RDS_TX_PI: + rval = v4l2_ctrl_query_fill(qc, 0, 0xFFFF, 1, DEFAULT_RDS_PI); + break; + case V4L2_CID_RDS_TX_PTY: + rval = v4l2_ctrl_query_fill(qc, 0, 31, 1, DEFAULT_RDS_PTY); + break; + case V4L2_CID_RDS_TX_DEVIATION: + rval = v4l2_ctrl_query_fill(qc, 0, MAX_RDS_DEVIATION, + 10, DEFAULT_RDS_DEVIATION); + break; + case V4L2_CID_RDS_TX_PS_NAME: + /* + * Report step as 8. From RDS spec, psname + * should be 8. But there are receivers which scroll strings + * sized as 8xN. + */ + rval = v4l2_ctrl_query_fill(qc, 0, MAX_RDS_PS_NAME, 8, 0); + break; + case V4L2_CID_RDS_TX_RADIO_TEXT: + /* + * Report step as 32 (2A block). From RDS spec, + * radio text should be 32 for 2A block. But there are receivers + * which scroll strings sized as 32xN. Setting default to 32. + */ + rval = v4l2_ctrl_query_fill(qc, 0, MAX_RDS_RADIO_TEXT, 32, 0); + break; + + case V4L2_CID_AUDIO_LIMITER_ENABLED: + rval = v4l2_ctrl_query_fill(qc, 0, 1, 1, 1); + break; + case V4L2_CID_AUDIO_LIMITER_RELEASE_TIME: + rval = v4l2_ctrl_query_fill(qc, 250, MAX_LIMITER_RELEASE_TIME, + 50, DEFAULT_LIMITER_RTIME); + break; + case V4L2_CID_AUDIO_LIMITER_DEVIATION: + rval = v4l2_ctrl_query_fill(qc, 0, MAX_LIMITER_DEVIATION, + 10, DEFAULT_LIMITER_DEV); + break; + + case V4L2_CID_AUDIO_COMPRESSION_ENABLED: + rval = v4l2_ctrl_query_fill(qc, 0, 1, 1, 1); + break; + case V4L2_CID_AUDIO_COMPRESSION_GAIN: + rval = v4l2_ctrl_query_fill(qc, 0, MAX_ACOMP_GAIN, 1, + DEFAULT_ACOMP_GAIN); + break; + case V4L2_CID_AUDIO_COMPRESSION_THRESHOLD: + rval = v4l2_ctrl_query_fill(qc, MIN_ACOMP_THRESHOLD, + MAX_ACOMP_THRESHOLD, 1, + DEFAULT_ACOMP_THRESHOLD); + break; + case V4L2_CID_AUDIO_COMPRESSION_ATTACK_TIME: + rval = v4l2_ctrl_query_fill(qc, 0, MAX_ACOMP_ATTACK_TIME, + 500, DEFAULT_ACOMP_ATIME); + break; + case V4L2_CID_AUDIO_COMPRESSION_RELEASE_TIME: + rval = v4l2_ctrl_query_fill(qc, 100000, MAX_ACOMP_RELEASE_TIME, + 100000, DEFAULT_ACOMP_RTIME); + break; + + case V4L2_CID_PILOT_TONE_ENABLED: + rval = v4l2_ctrl_query_fill(qc, 0, 1, 1, 1); + break; + case V4L2_CID_PILOT_TONE_DEVIATION: + rval = v4l2_ctrl_query_fill(qc, 0, MAX_PILOT_DEVIATION, + 10, DEFAULT_PILOT_DEVIATION); + break; + case V4L2_CID_PILOT_TONE_FREQUENCY: + rval = v4l2_ctrl_query_fill(qc, 0, MAX_PILOT_FREQUENCY, + 1, DEFAULT_PILOT_FREQUENCY); + break; + + case V4L2_CID_TUNE_PREEMPHASIS: + rval = v4l2_ctrl_query_fill(qc, V4L2_PREEMPHASIS_DISABLED, + V4L2_PREEMPHASIS_75_uS, 1, + V4L2_PREEMPHASIS_50_uS); + break; + case V4L2_CID_TUNE_POWER_LEVEL: + rval = v4l2_ctrl_query_fill(qc, 0, 120, 1, DEFAULT_POWER_LEVEL); + break; + case V4L2_CID_TUNE_ANTENNA_CAPACITOR: + rval = v4l2_ctrl_query_fill(qc, 0, 191, 1, 0); + break; + default: + rval = -EINVAL; + break; + }; + + return rval; +} + +/* si4713_g_ctrl - get the value of a control */ +static int si4713_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) +{ + struct si4713_device *sdev = to_si4713_device(sd); + int rval = 0; + + if (!sdev) + return -ENODEV; + + mutex_lock(&sdev->mutex); + + if (sdev->power_state) { + rval = si4713_read_property(sdev, SI4713_TX_LINE_INPUT_MUTE, + &sdev->mute); + + if (rval < 0) + goto unlock; + } + + switch (ctrl->id) { + case V4L2_CID_AUDIO_MUTE: + ctrl->value = get_mute(sdev->mute); + break; + } + +unlock: + mutex_unlock(&sdev->mutex); + return rval; +} + +/* si4713_s_ctrl - set the value of a control */ +static int si4713_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) +{ + struct si4713_device *sdev = to_si4713_device(sd); + int rval = 0; + + if (!sdev) + return -ENODEV; + + switch (ctrl->id) { + case V4L2_CID_AUDIO_MUTE: + if (ctrl->value) { + rval = si4713_set_mute(sdev, ctrl->value); + if (rval < 0) + goto exit; + + rval = si4713_set_power_state(sdev, POWER_DOWN); + } else { + rval = si4713_set_power_state(sdev, POWER_UP); + if (rval < 0) + goto exit; + + rval = si4713_setup(sdev); + if (rval < 0) + goto exit; + + rval = si4713_set_mute(sdev, ctrl->value); + } + break; + } + +exit: + return rval; +} + +/* si4713_ioctl - deal with private ioctls (only rnl for now) */ +long si4713_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) +{ + struct si4713_device *sdev = to_si4713_device(sd); + struct si4713_rnl *rnl = arg; + u16 frequency; + int rval = 0; + + if (!arg) + return -EINVAL; + + mutex_lock(&sdev->mutex); + switch (cmd) { + case SI4713_IOC_MEASURE_RNL: + frequency = v4l2_to_si4713(rnl->frequency); + + if (sdev->power_state) { + /* Set desired measurement frequency */ + rval = si4713_tx_tune_measure(sdev, frequency, 0); + if (rval < 0) + goto unlock; + /* get results from tune status */ + rval = si4713_update_tune_status(sdev); + if (rval < 0) + goto unlock; + } + rnl->rnl = sdev->tune_rnl; + break; + + default: + /* nothing */ + rval = -ENOIOCTLCMD; + } + +unlock: + mutex_unlock(&sdev->mutex); + return rval; +} + +static const struct v4l2_subdev_core_ops si4713_subdev_core_ops = { + .queryctrl = si4713_queryctrl, + .g_ext_ctrls = si4713_g_ext_ctrls, + .s_ext_ctrls = si4713_s_ext_ctrls, + .g_ctrl = si4713_g_ctrl, + .s_ctrl = si4713_s_ctrl, + .ioctl = si4713_ioctl, +}; + +/* si4713_g_modulator - get modulator attributes */ +static int si4713_g_modulator(struct v4l2_subdev *sd, struct v4l2_modulator *vm) +{ + struct si4713_device *sdev = to_si4713_device(sd); + int rval = 0; + + if (!sdev) { + rval = -ENODEV; + goto exit; + } + + if (vm->index > 0) { + rval = -EINVAL; + goto exit; + } + + strncpy(vm->name, "FM Modulator", 32); + vm->capability = V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_LOW | + V4L2_TUNER_CAP_RDS; + + /* Report current frequency range limits */ + vm->rangelow = si4713_to_v4l2(FREQ_RANGE_LOW); + vm->rangehigh = si4713_to_v4l2(FREQ_RANGE_HIGH); + + mutex_lock(&sdev->mutex); + + if (sdev->power_state) { + u32 comp_en = 0; + + rval = si4713_read_property(sdev, SI4713_TX_COMPONENT_ENABLE, + &comp_en); + if (rval < 0) + goto unlock; + + sdev->stereo = get_status_bit(comp_en, 1, 1 << 1); + sdev->rds_info.enabled = get_status_bit(comp_en, 2, 1 << 2); + } + + /* Report current audio mode: mono or stereo */ + if (sdev->stereo) + vm->txsubchans = V4L2_TUNER_SUB_STEREO; + else + vm->txsubchans = V4L2_TUNER_SUB_MONO; + + /* Report rds feature status */ + if (sdev->rds_info.enabled) + vm->txsubchans |= V4L2_TUNER_SUB_RDS; + else + vm->txsubchans &= ~V4L2_TUNER_SUB_RDS; + +unlock: + mutex_unlock(&sdev->mutex); +exit: + return rval; +} + +/* si4713_s_modulator - set modulator attributes */ +static int si4713_s_modulator(struct v4l2_subdev *sd, struct v4l2_modulator *vm) +{ + struct si4713_device *sdev = to_si4713_device(sd); + int rval = 0; + u16 stereo, rds; + u32 p; + + if (!sdev) { + rval = -ENODEV; + goto exit; + } + + if (vm->index > 0) { + rval = -EINVAL; + goto exit; + } + + /* Set audio mode: mono or stereo */ + if (vm->txsubchans & V4L2_TUNER_SUB_STEREO) + stereo = 1; + else if (vm->txsubchans & V4L2_TUNER_SUB_MONO) + stereo = 0; + else + rval = -EINVAL; + if (rval < 0) + goto exit; + + rds = !!(vm->txsubchans & V4L2_TUNER_SUB_RDS); + + mutex_lock(&sdev->mutex); + + if (sdev->power_state) { + rval = si4713_read_property(sdev, + SI4713_TX_COMPONENT_ENABLE, &p); + if (rval < 0) + goto unlock; + + p = set_bits(p, stereo, 1, 1 << 1); + p = set_bits(p, rds, 2, 1 << 2); + + rval = si4713_write_property(sdev, + SI4713_TX_COMPONENT_ENABLE, p); + if (rval < 0) + goto unlock; + } + + sdev->stereo = stereo; + sdev->rds_info.enabled = rds; + +unlock: + mutex_unlock(&sdev->mutex); +exit: + return rval; +} + +/* si4713_g_frequency - get tuner or modulator radio frequency */ +static int si4713_g_frequency(struct v4l2_subdev *sd, struct v4l2_frequency *f) +{ + struct si4713_device *sdev = to_si4713_device(sd); + int rval = 0; + + f->type = V4L2_TUNER_RADIO; + + mutex_lock(&sdev->mutex); + + if (sdev->power_state) { + u16 freq; + u8 p, a, n; + + rval = si4713_tx_tune_status(sdev, 0x00, &freq, &p, &a, &n); + if (rval < 0) + goto unlock; + + sdev->frequency = freq; + } + + f->frequency = si4713_to_v4l2(sdev->frequency); + +unlock: + mutex_unlock(&sdev->mutex); + return rval; +} + +/* si4713_s_frequency - set tuner or modulator radio frequency */ +static int si4713_s_frequency(struct v4l2_subdev *sd, struct v4l2_frequency *f) +{ + struct si4713_device *sdev = to_si4713_device(sd); + int rval = 0; + u16 frequency = v4l2_to_si4713(f->frequency); + + /* Check frequency range */ + if (frequency < FREQ_RANGE_LOW || frequency > FREQ_RANGE_HIGH) + return -EDOM; + + mutex_lock(&sdev->mutex); + + if (sdev->power_state) { + rval = si4713_tx_tune_freq(sdev, frequency); + if (rval < 0) + goto unlock; + frequency = rval; + rval = 0; + } + sdev->frequency = frequency; + f->frequency = si4713_to_v4l2(frequency); + +unlock: + mutex_unlock(&sdev->mutex); + return rval; +} + +static const struct v4l2_subdev_tuner_ops si4713_subdev_tuner_ops = { + .g_frequency = si4713_g_frequency, + .s_frequency = si4713_s_frequency, + .g_modulator = si4713_g_modulator, + .s_modulator = si4713_s_modulator, +}; + +static const struct v4l2_subdev_ops si4713_subdev_ops = { + .core = &si4713_subdev_core_ops, + .tuner = &si4713_subdev_tuner_ops, +}; + +/* + * I2C driver interface + */ +/* si4713_probe - probe for the device */ +static int si4713_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct si4713_device *sdev; + int rval; + + sdev = kzalloc(sizeof *sdev, GFP_KERNEL); + if (!sdev) { + dev_err(&client->dev, "Failed to alloc video device.\n"); + rval = -ENOMEM; + goto exit; + } + + sdev->platform_data = client->dev.platform_data; + if (!sdev->platform_data) { + v4l2_err(&sdev->sd, "No platform data registered.\n"); + rval = -ENODEV; + goto free_sdev; + } + + v4l2_i2c_subdev_init(&sdev->sd, client, &si4713_subdev_ops); + + mutex_init(&sdev->mutex); + init_completion(&sdev->work); + + if (client->irq) { + rval = request_irq(client->irq, + si4713_handler, IRQF_TRIGGER_FALLING | IRQF_DISABLED, + client->name, sdev); + if (rval < 0) { + v4l2_err(&sdev->sd, "Could not request IRQ\n"); + goto free_sdev; + } + v4l2_dbg(1, debug, &sdev->sd, "IRQ requested.\n"); + } else { + v4l2_warn(&sdev->sd, "IRQ not configured. Using timeouts.\n"); + } + + rval = si4713_initialize(sdev); + if (rval < 0) { + v4l2_err(&sdev->sd, "Failed to probe device information.\n"); + goto free_irq; + } + + return 0; + +free_irq: + if (client->irq) + free_irq(client->irq, sdev); +free_sdev: + kfree(sdev); +exit: + return rval; +} + +/* si4713_remove - remove the device */ +static int si4713_remove(struct i2c_client *client) +{ + struct v4l2_subdev *sd = i2c_get_clientdata(client); + struct si4713_device *sdev = to_si4713_device(sd); + + if (sdev->power_state) + si4713_set_power_state(sdev, POWER_DOWN); + + if (client->irq > 0) + free_irq(client->irq, sdev); + + v4l2_device_unregister_subdev(sd); + + kfree(sdev); + + return 0; +} + +/* si4713_i2c_driver - i2c driver interface */ +static const struct i2c_device_id si4713_id[] = { + { "si4713" , 0 }, + { }, +}; +MODULE_DEVICE_TABLE(i2c, si4713_id); + +static struct i2c_driver si4713_i2c_driver = { + .driver = { + .name = "si4713", + }, + .probe = si4713_probe, + .remove = si4713_remove, + .id_table = si4713_id, +}; + +/* Module Interface */ +static int __init si4713_module_init(void) +{ + return i2c_add_driver(&si4713_i2c_driver); +} + +static void __exit si4713_module_exit(void) +{ + i2c_del_driver(&si4713_i2c_driver); +} + +module_init(si4713_module_init); +module_exit(si4713_module_exit); + diff --git a/linux/drivers/media/radio/si4713-i2c.h b/linux/drivers/media/radio/si4713-i2c.h new file mode 100644 index 000000000..faf8cff12 --- /dev/null +++ b/linux/drivers/media/radio/si4713-i2c.h @@ -0,0 +1,237 @@ +/* + * drivers/media/radio/si4713-i2c.h + * + * Property and commands definitions for Si4713 radio transmitter chip. + * + * Copyright (c) 2008 Instituto Nokia de Tecnologia - INdT + * Contact: Eduardo Valentin + * + * This file is licensed under the terms of the GNU General Public License + * version 2. This program is licensed "as is" without any warranty of any + * kind, whether express or implied. + * + */ + +#ifndef SI4713_I2C_H +#define SI4713_I2C_H + +#include +#include + +#define SI4713_PRODUCT_NUMBER 0x0D + +/* Command Timeouts */ +#define DEFAULT_TIMEOUT 500 +#define TIMEOUT_SET_PROPERTY 20 +#define TIMEOUT_TX_TUNE_POWER 30000 +#define TIMEOUT_TX_TUNE 110000 +#define TIMEOUT_POWER_UP 200000 + +/* + * Command and its arguments definitions + */ +#define SI4713_PWUP_CTSIEN (1<<7) +#define SI4713_PWUP_GPO2OEN (1<<6) +#define SI4713_PWUP_PATCH (1<<5) +#define SI4713_PWUP_XOSCEN (1<<4) +#define SI4713_PWUP_FUNC_TX 0x02 +#define SI4713_PWUP_FUNC_PATCH 0x0F +#define SI4713_PWUP_OPMOD_ANALOG 0x50 +#define SI4713_PWUP_OPMOD_DIGITAL 0x0F +#define SI4713_PWUP_NARGS 2 +#define SI4713_PWUP_NRESP 1 +#define SI4713_CMD_POWER_UP 0x01 + +#define SI4713_GETREV_NRESP 9 +#define SI4713_CMD_GET_REV 0x10 + +#define SI4713_PWDN_NRESP 1 +#define SI4713_CMD_POWER_DOWN 0x11 + +#define SI4713_SET_PROP_NARGS 5 +#define SI4713_SET_PROP_NRESP 1 +#define SI4713_CMD_SET_PROPERTY 0x12 + +#define SI4713_GET_PROP_NARGS 3 +#define SI4713_GET_PROP_NRESP 4 +#define SI4713_CMD_GET_PROPERTY 0x13 + +#define SI4713_GET_STATUS_NRESP 1 +#define SI4713_CMD_GET_INT_STATUS 0x14 + +#define SI4713_CMD_PATCH_ARGS 0x15 +#define SI4713_CMD_PATCH_DATA 0x16 + +#define SI4713_MAX_FREQ 10800 +#define SI4713_MIN_FREQ 7600 +#define SI4713_TXFREQ_NARGS 3 +#define SI4713_TXFREQ_NRESP 1 +#define SI4713_CMD_TX_TUNE_FREQ 0x30 + +#define SI4713_MAX_POWER 120 +#define SI4713_MIN_POWER 88 +#define SI4713_MAX_ANTCAP 191 +#define SI4713_MIN_ANTCAP 0 +#define SI4713_TXPWR_NARGS 4 +#define SI4713_TXPWR_NRESP 1 +#define SI4713_CMD_TX_TUNE_POWER 0x31 + +#define SI4713_TXMEA_NARGS 4 +#define SI4713_TXMEA_NRESP 1 +#define SI4713_CMD_TX_TUNE_MEASURE 0x32 + +#define SI4713_INTACK_MASK 0x01 +#define SI4713_TXSTATUS_NARGS 1 +#define SI4713_TXSTATUS_NRESP 8 +#define SI4713_CMD_TX_TUNE_STATUS 0x33 + +#define SI4713_OVERMOD_BIT (1 << 2) +#define SI4713_IALH_BIT (1 << 1) +#define SI4713_IALL_BIT (1 << 0) +#define SI4713_ASQSTATUS_NARGS 1 +#define SI4713_ASQSTATUS_NRESP 5 +#define SI4713_CMD_TX_ASQ_STATUS 0x34 + +#define SI4713_RDSBUFF_MODE_MASK 0x87 +#define SI4713_RDSBUFF_NARGS 7 +#define SI4713_RDSBUFF_NRESP 6 +#define SI4713_CMD_TX_RDS_BUFF 0x35 + +#define SI4713_RDSPS_PSID_MASK 0x1F +#define SI4713_RDSPS_NARGS 5 +#define SI4713_RDSPS_NRESP 1 +#define SI4713_CMD_TX_RDS_PS 0x36 + +#define SI4713_CMD_GPO_CTL 0x80 +#define SI4713_CMD_GPO_SET 0x81 + +/* + * Bits from status response + */ +#define SI4713_CTS (1<<7) +#define SI4713_ERR (1<<6) +#define SI4713_RDS_INT (1<<2) +#define SI4713_ASQ_INT (1<<1) +#define SI4713_STC_INT (1<<0) + +/* + * Property definitions + */ +#define SI4713_GPO_IEN 0x0001 +#define SI4713_DIG_INPUT_FORMAT 0x0101 +#define SI4713_DIG_INPUT_SAMPLE_RATE 0x0103 +#define SI4713_REFCLK_FREQ 0x0201 +#define SI4713_REFCLK_PRESCALE 0x0202 +#define SI4713_TX_COMPONENT_ENABLE 0x2100 +#define SI4713_TX_AUDIO_DEVIATION 0x2101 +#define SI4713_TX_PILOT_DEVIATION 0x2102 +#define SI4713_TX_RDS_DEVIATION 0x2103 +#define SI4713_TX_LINE_INPUT_LEVEL 0x2104 +#define SI4713_TX_LINE_INPUT_MUTE 0x2105 +#define SI4713_TX_PREEMPHASIS 0x2106 +#define SI4713_TX_PILOT_FREQUENCY 0x2107 +#define SI4713_TX_ACOMP_ENABLE 0x2200 +#define SI4713_TX_ACOMP_THRESHOLD 0x2201 +#define SI4713_TX_ACOMP_ATTACK_TIME 0x2202 +#define SI4713_TX_ACOMP_RELEASE_TIME 0x2203 +#define SI4713_TX_ACOMP_GAIN 0x2204 +#define SI4713_TX_LIMITER_RELEASE_TIME 0x2205 +#define SI4713_TX_ASQ_INTERRUPT_SOURCE 0x2300 +#define SI4713_TX_ASQ_LEVEL_LOW 0x2301 +#define SI4713_TX_ASQ_DURATION_LOW 0x2302 +#define SI4713_TX_ASQ_LEVEL_HIGH 0x2303 +#define SI4713_TX_ASQ_DURATION_HIGH 0x2304 +#define SI4713_TX_RDS_INTERRUPT_SOURCE 0x2C00 +#define SI4713_TX_RDS_PI 0x2C01 +#define SI4713_TX_RDS_PS_MIX 0x2C02 +#define SI4713_TX_RDS_PS_MISC 0x2C03 +#define SI4713_TX_RDS_PS_REPEAT_COUNT 0x2C04 +#define SI4713_TX_RDS_PS_MESSAGE_COUNT 0x2C05 +#define SI4713_TX_RDS_PS_AF 0x2C06 +#define SI4713_TX_RDS_FIFO_SIZE 0x2C07 + +#define PREEMPHASIS_USA 75 +#define PREEMPHASIS_EU 50 +#define PREEMPHASIS_DISABLED 0 +#define FMPE_USA 0x00 +#define FMPE_EU 0x01 +#define FMPE_DISABLED 0x02 + +#define POWER_UP 0x01 +#define POWER_DOWN 0x00 + +struct rds_info { + u32 pi; +#define MAX_RDS_PTY 31 + u32 pty; +#define MAX_RDS_DEVIATION 90000 + u32 deviation; +/* + * PSNAME is known to be defined as 8 character sized (RDS Spec). + * However, there is receivers which scroll PSNAME 8xN sized. + */ +#define MAX_RDS_PS_NAME 96 + u8 ps_name[MAX_RDS_PS_NAME + 1]; +/* + * MAX_RDS_RADIO_TEXT is known to be defined as 32 (2A group) or 64 (2B group) + * character sized (RDS Spec). + * However, there is receivers which scroll them as well. + */ +#define MAX_RDS_RADIO_TEXT 384 + u8 radio_text[MAX_RDS_RADIO_TEXT + 1]; + u32 enabled; +}; + +struct limiter_info { +#define MAX_LIMITER_RELEASE_TIME 102390 + u32 release_time; +#define MAX_LIMITER_DEVIATION 90000 + u32 deviation; + u32 enabled; +}; + +struct pilot_info { +#define MAX_PILOT_DEVIATION 90000 + u32 deviation; +#define MAX_PILOT_FREQUENCY 19000 + u32 frequency; + u32 enabled; +}; + +struct acomp_info { +#define MAX_ACOMP_RELEASE_TIME 1000000 + u32 release_time; +#define MAX_ACOMP_ATTACK_TIME 5000 + u32 attack_time; +#define MAX_ACOMP_THRESHOLD 0 +#define MIN_ACOMP_THRESHOLD (-40) + s32 threshold; +#define MAX_ACOMP_GAIN 20 + u32 gain; + u32 enabled; +}; + +/* + * si4713_device - private data + */ +struct si4713_device { + /* v4l2_subdev and i2c reference (v4l2_subdev priv data) */ + struct v4l2_subdev sd; + /* private data structures */ + struct mutex mutex; + struct completion work; + struct si4713_platform_data *platform_data; + struct rds_info rds_info; + struct limiter_info limiter_info; + struct pilot_info pilot_info; + struct acomp_info acomp_info; + u32 frequency; + u32 preemphasis; + u32 mute; + u32 power_level; + u32 power_state; + u32 antenna_capacitor; + u32 stereo; + u32 tune_rnl; +}; +#endif /* ifndef SI4713_I2C_H */ -- cgit v1.2.3 From ffa87ee185160e8a3c127e3383a6038b7e85ffe4 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 27 Aug 2009 09:28:48 -0300 Subject: Use C99 comment CodingStyle From: Mauro Carvalho Chehab The ir-keymaps.c has frequent additions. As people tend to copy an old keyboard entry, a bad CodingStyle at an ancient entry may result on a freshly bad CodingStyle patch. So, better to fix the CodingStyle for the entire file. This patch is the first of a series of patches fixing it, generated by some perl magic plus manual handling. Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/common/ir-keymaps.c | 428 ++++++++++++++++---------------- 1 file changed, 216 insertions(+), 212 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/common/ir-keymaps.c b/linux/drivers/media/common/ir-keymaps.c index 0b1566d34..471df71a3 100644 --- a/linux/drivers/media/common/ir-keymaps.c +++ b/linux/drivers/media/common/ir-keymaps.c @@ -65,41 +65,41 @@ IR_KEYTAB_TYPE ir_codes_proteus_2309[IR_KEYTAB_SIZE] = { EXPORT_SYMBOL_GPL(ir_codes_proteus_2309); /* Matt Jesson >' - [ 0x3a ] = KEY_RECORD, // 'capture' - [ 0x0a ] = KEY_MUTE, // 'mute' - [ 0x2c ] = KEY_RECORD, // 'record' - [ 0x1c ] = KEY_PAUSE, // 'pause' - [ 0x3c ] = KEY_STOP, // 'stop' - [ 0x0c ] = KEY_PLAY, // 'play' - [ 0x2e ] = KEY_RED, // 'red' - [ 0x01 ] = KEY_BLUE, // 'blue' / 'cancel' - [ 0x0e ] = KEY_YELLOW, // 'yellow' / 'ok' - [ 0x21 ] = KEY_GREEN, // 'green' - [ 0x11 ] = KEY_CHANNELDOWN, // 'channel -' - [ 0x31 ] = KEY_CHANNELUP, // 'channel +' - [ 0x1e ] = KEY_VOLUMEDOWN, // 'volume -' - [ 0x3e ] = KEY_VOLUMEUP, // 'volume +' + [ 0x28 ] = KEY_0, /* '0' / 'enter' */ + [ 0x22 ] = KEY_1, /* '1' */ + [ 0x12 ] = KEY_2, /* '2' / 'up arrow' */ + [ 0x32 ] = KEY_3, /* '3' */ + [ 0x24 ] = KEY_4, /* '4' / 'left arrow' */ + [ 0x14 ] = KEY_5, /* '5' */ + [ 0x34 ] = KEY_6, /* '6' / 'right arrow' */ + [ 0x26 ] = KEY_7, /* '7' */ + [ 0x16 ] = KEY_8, /* '8' / 'down arrow' */ + [ 0x36 ] = KEY_9, /* '9' */ + + [ 0x20 ] = KEY_LIST, /* 'source' */ + [ 0x10 ] = KEY_TEXT, /* 'teletext' */ + [ 0x00 ] = KEY_POWER, /* 'power' */ + [ 0x04 ] = KEY_AUDIO, /* 'audio' */ + [ 0x06 ] = KEY_ZOOM, /* 'full screen' */ + [ 0x18 ] = KEY_VIDEO, /* 'display' */ + [ 0x38 ] = KEY_SEARCH, /* 'loop' */ + [ 0x08 ] = KEY_INFO, /* 'preview' */ + [ 0x2a ] = KEY_REWIND, /* 'backward <<' */ + [ 0x1a ] = KEY_FASTFORWARD, /* 'forward >>' */ + [ 0x3a ] = KEY_RECORD, /* 'capture' */ + [ 0x0a ] = KEY_MUTE, /* 'mute' */ + [ 0x2c ] = KEY_RECORD, /* 'record' */ + [ 0x1c ] = KEY_PAUSE, /* 'pause' */ + [ 0x3c ] = KEY_STOP, /* 'stop' */ + [ 0x0c ] = KEY_PLAY, /* 'play' */ + [ 0x2e ] = KEY_RED, /* 'red' */ + [ 0x01 ] = KEY_BLUE, /* 'blue' / 'cancel' */ + [ 0x0e ] = KEY_YELLOW, /* 'yellow' / 'ok' */ + [ 0x21 ] = KEY_GREEN, /* 'green' */ + [ 0x11 ] = KEY_CHANNELDOWN, /* 'channel -' */ + [ 0x31 ] = KEY_CHANNELUP, /* 'channel +' */ + [ 0x1e ] = KEY_VOLUMEDOWN, /* 'volume -' */ + [ 0x3e ] = KEY_VOLUMEUP, /* 'volume +' */ }; EXPORT_SYMBOL_GPL(ir_codes_avermedia_dvbt); @@ -226,32 +226,32 @@ IR_KEYTAB_TYPE ir_codes_apac_viewcomp[IR_KEYTAB_SIZE] = { [ 0x08 ] = KEY_8, [ 0x09 ] = KEY_9, [ 0x00 ] = KEY_0, - [ 0x17 ] = KEY_LAST, // +100 - [ 0x0a ] = KEY_LIST, // recall - - - [ 0x1c ] = KEY_TUNER, // TV/FM - [ 0x15 ] = KEY_SEARCH, // scan - [ 0x12 ] = KEY_POWER, // power - [ 0x1f ] = KEY_VOLUMEDOWN, // vol up - [ 0x1b ] = KEY_VOLUMEUP, // vol down - [ 0x1e ] = KEY_CHANNELDOWN, // chn up - [ 0x1a ] = KEY_CHANNELUP, // chn down - - [ 0x11 ] = KEY_VIDEO, // video - [ 0x0f ] = KEY_ZOOM, // full screen - [ 0x13 ] = KEY_MUTE, // mute/unmute - [ 0x10 ] = KEY_TEXT, // min - - [ 0x0d ] = KEY_STOP, // freeze - [ 0x0e ] = KEY_RECORD, // record - [ 0x1d ] = KEY_PLAYPAUSE, // stop - [ 0x19 ] = KEY_PLAY, // play - - [ 0x16 ] = KEY_GOTO, // osd - [ 0x14 ] = KEY_REFRESH, // default - [ 0x0c ] = KEY_KPPLUS, // fine tune >>>> - [ 0x18 ] = KEY_KPMINUS // fine tune <<<< + [ 0x17 ] = KEY_LAST, /* +100 */ + [ 0x0a ] = KEY_LIST, /* recall */ + + + [ 0x1c ] = KEY_TUNER, /* TV/FM */ + [ 0x15 ] = KEY_SEARCH, /* scan */ + [ 0x12 ] = KEY_POWER, /* power */ + [ 0x1f ] = KEY_VOLUMEDOWN, /* vol up */ + [ 0x1b ] = KEY_VOLUMEUP, /* vol down */ + [ 0x1e ] = KEY_CHANNELDOWN, /* chn up */ + [ 0x1a ] = KEY_CHANNELUP, /* chn down */ + + [ 0x11 ] = KEY_VIDEO, /* video */ + [ 0x0f ] = KEY_ZOOM, /* full screen */ + [ 0x13 ] = KEY_MUTE, /* mute/unmute */ + [ 0x10 ] = KEY_TEXT, /* min */ + + [ 0x0d ] = KEY_STOP, /* freeze */ + [ 0x0e ] = KEY_RECORD, /* record */ + [ 0x1d ] = KEY_PLAYPAUSE, /* stop */ + [ 0x19 ] = KEY_PLAY, /* play */ + + [ 0x16 ] = KEY_GOTO, /* osd */ + [ 0x14 ] = KEY_REFRESH, /* default */ + [ 0x0c ] = KEY_KPPLUS, /* fine tune >>>> */ + [ 0x18 ] = KEY_KPMINUS /* fine tune <<<< */ }; EXPORT_SYMBOL_GPL(ir_codes_apac_viewcomp); @@ -260,38 +260,42 @@ EXPORT_SYMBOL_GPL(ir_codes_apac_viewcomp); IR_KEYTAB_TYPE ir_codes_pixelview[IR_KEYTAB_SIZE] = { - [ 0x1e ] = KEY_POWER, // power - [ 0x07 ] = KEY_MEDIA, // source - [ 0x1c ] = KEY_SEARCH, // scan + [ 0x1e ] = KEY_POWER, /* power */ + [ 0x07 ] = KEY_MEDIA, /* source */ + [ 0x1c ] = KEY_SEARCH, /* scan */ -/* FIXME: duplicate keycodes? - * +#if 0 +/* FIXME: duplicate keycodes? */ + +/* * These four keys seem to share the same GPIO as CH+, CH-, <<< and >>> * The GPIO values are * 6397fb for both "Scan <" and "CH -", * 639ffb for "Scan >" and "CH+", * 6384fb for "Tune <" and "<<<", * 638cfb for "Tune >" and ">>>", regardless of the mask. - * - * [ 0x17 ] = KEY_BACK, // fm scan << - * [ 0x1f ] = KEY_FORWARD, // fm scan >> - * - * [ 0x04 ] = KEY_LEFT, // fm tuning < - * [ 0x0c ] = KEY_RIGHT, // fm tuning > - * + */ + [ 0x17 ] = KEY_BACK, /* fm scan << */ + [ 0x1f ] = KEY_FORWARD, /* fm scan >> */ + + [ 0x04 ] = KEY_LEFT, /* fm tuning < */ + [ 0x0c ] = KEY_RIGHT, /* fm tuning > */ + +/* * For now, these four keys are disabled. Pressing them will generate * the CH+/CH-/<<>> events */ +#endif - [ 0x03 ] = KEY_TUNER, // TV/FM + [ 0x03 ] = KEY_TUNER, /* TV/FM */ [ 0x00 ] = KEY_RECORD, [ 0x08 ] = KEY_STOP, [ 0x11 ] = KEY_PLAY, - [ 0x1a ] = KEY_PLAYPAUSE, // freeze - [ 0x19 ] = KEY_ZOOM, // zoom - [ 0x0f ] = KEY_TEXT, // min + [ 0x1a ] = KEY_PLAYPAUSE, /* freeze */ + [ 0x19 ] = KEY_ZOOM, /* zoom */ + [ 0x0f ] = KEY_TEXT, /* min */ [ 0x01 ] = KEY_1, [ 0x0b ] = KEY_2, @@ -303,21 +307,21 @@ IR_KEYTAB_TYPE ir_codes_pixelview[IR_KEYTAB_SIZE] = { [ 0x0a ] = KEY_8, [ 0x12 ] = KEY_9, [ 0x02 ] = KEY_0, - [ 0x10 ] = KEY_LAST, // +100 - [ 0x13 ] = KEY_LIST, // recall + [ 0x10 ] = KEY_LAST, /* +100 */ + [ 0x13 ] = KEY_LIST, /* recall */ - [ 0x1f ] = KEY_CHANNELUP, // chn down - [ 0x17 ] = KEY_CHANNELDOWN, // chn up - [ 0x16 ] = KEY_VOLUMEUP, // vol down - [ 0x14 ] = KEY_VOLUMEDOWN, // vol up + [ 0x1f ] = KEY_CHANNELUP, /* chn down */ + [ 0x17 ] = KEY_CHANNELDOWN, /* chn up */ + [ 0x16 ] = KEY_VOLUMEUP, /* vol down */ + [ 0x14 ] = KEY_VOLUMEDOWN, /* vol up */ - [ 0x04 ] = KEY_KPMINUS, // <<< - [ 0x0e ] = KEY_SETUP, // function - [ 0x0c ] = KEY_KPPLUS, // >>> + [ 0x04 ] = KEY_KPMINUS, /* <<< */ + [ 0x0e ] = KEY_SETUP, /* function */ + [ 0x0c ] = KEY_KPPLUS, /* >>> */ - [ 0x0d ] = KEY_GOTO, // mts - [ 0x1d ] = KEY_REFRESH, // reset - [ 0x18 ] = KEY_MUTE // mute/unmute + [ 0x0d ] = KEY_GOTO, /* mts */ + [ 0x1d ] = KEY_REFRESH, /* reset */ + [ 0x18 ] = KEY_MUTE /* mute/unmute */ }; EXPORT_SYMBOL_GPL(ir_codes_pixelview); @@ -958,31 +962,31 @@ IR_KEYTAB_TYPE ir_codes_flyvideo[IR_KEYTAB_SIZE] = { [ 0x0c ] = KEY_8, [ 0x0d ] = KEY_9, - [ 0x0e ] = KEY_MODE, // Air/Cable - [ 0x11 ] = KEY_VIDEO, // Video - [ 0x15 ] = KEY_AUDIO, // Audio - [ 0x00 ] = KEY_POWER, // Power - [ 0x18 ] = KEY_TUNER, // AV Source - [ 0x02 ] = KEY_ZOOM, // Fullscreen - [ 0x1a ] = KEY_LANGUAGE, // Stereo - [ 0x1b ] = KEY_MUTE, // Mute - [ 0x14 ] = KEY_VOLUMEUP, // Volume + - [ 0x17 ] = KEY_VOLUMEDOWN, // Volume - - [ 0x12 ] = KEY_CHANNELUP, // Channel + - [ 0x13 ] = KEY_CHANNELDOWN, // Channel - - [ 0x06 ] = KEY_AGAIN, // Recall - [ 0x10 ] = KEY_ENTER, // Enter - - [ 0x19 ] = KEY_BACK, // Rewind ( <<< ) - [ 0x1f ] = KEY_FORWARD, // Forward ( >>> ) - [ 0x0a ] = KEY_ANGLE, // (no label, may be used as the PAUSE button) + [ 0x0e ] = KEY_MODE, /* Air/Cable */ + [ 0x11 ] = KEY_VIDEO, /* Video */ + [ 0x15 ] = KEY_AUDIO, /* Audio */ + [ 0x00 ] = KEY_POWER, /* Power */ + [ 0x18 ] = KEY_TUNER, /* AV Source */ + [ 0x02 ] = KEY_ZOOM, /* Fullscreen */ + [ 0x1a ] = KEY_LANGUAGE, /* Stereo */ + [ 0x1b ] = KEY_MUTE, /* Mute */ + [ 0x14 ] = KEY_VOLUMEUP, /* Volume + */ + [ 0x17 ] = KEY_VOLUMEDOWN, /* Volume - */ + [ 0x12 ] = KEY_CHANNELUP, /* Channel + */ + [ 0x13 ] = KEY_CHANNELDOWN, /* Channel - */ + [ 0x06 ] = KEY_AGAIN, /* Recall */ + [ 0x10 ] = KEY_ENTER, /* Enter */ + + [ 0x19 ] = KEY_BACK, /* Rewind ( <<< ) */ + [ 0x1f ] = KEY_FORWARD, /* Forward ( >>> ) */ + [ 0x0a ] = KEY_ANGLE, /* (no label, may be used as the PAUSE button) */ }; EXPORT_SYMBOL_GPL(ir_codes_flyvideo); IR_KEYTAB_TYPE ir_codes_flydvb[IR_KEYTAB_SIZE] = { - [ 0x01 ] = KEY_ZOOM, // Full Screen - [ 0x00 ] = KEY_POWER, // Power + [ 0x01 ] = KEY_ZOOM, /* Full Screen */ + [ 0x00 ] = KEY_POWER, /* Power */ [ 0x03 ] = KEY_1, [ 0x04 ] = KEY_2, @@ -993,30 +997,30 @@ IR_KEYTAB_TYPE ir_codes_flydvb[IR_KEYTAB_SIZE] = { [ 0x0b ] = KEY_7, [ 0x0c ] = KEY_8, [ 0x0d ] = KEY_9, - [ 0x06 ] = KEY_AGAIN, // Recall + [ 0x06 ] = KEY_AGAIN, /* Recall */ [ 0x0f ] = KEY_0, - [ 0x10 ] = KEY_MUTE, // Mute - [ 0x02 ] = KEY_RADIO, // TV/Radio - [ 0x1b ] = KEY_LANGUAGE, // SAP (Second Audio Program) - - [ 0x14 ] = KEY_VOLUMEUP, // VOL+ - [ 0x17 ] = KEY_VOLUMEDOWN, // VOL- - [ 0x12 ] = KEY_CHANNELUP, // CH+ - [ 0x13 ] = KEY_CHANNELDOWN, // CH- - [ 0x1d ] = KEY_ENTER, // Enter - - [ 0x1a ] = KEY_MODE, // PIP - [ 0x18 ] = KEY_TUNER, // Source - - [ 0x1e ] = KEY_RECORD, // Record/Pause - [ 0x15 ] = KEY_ANGLE, // Swap (no label on key) - [ 0x1c ] = KEY_PAUSE, // Timeshift/Pause - [ 0x19 ] = KEY_BACK, // Rewind << - [ 0x0a ] = KEY_PLAYPAUSE, // Play/Pause - [ 0x1f ] = KEY_FORWARD, // Forward >> - [ 0x16 ] = KEY_PREVIOUS, // Back |<< - [ 0x11 ] = KEY_STOP, // Stop - [ 0x0e ] = KEY_NEXT, // End >>| + [ 0x10 ] = KEY_MUTE, /* Mute */ + [ 0x02 ] = KEY_RADIO, /* TV/Radio */ + [ 0x1b ] = KEY_LANGUAGE, /* SAP (Second Audio Program) */ + + [ 0x14 ] = KEY_VOLUMEUP, /* VOL+ */ + [ 0x17 ] = KEY_VOLUMEDOWN, /* VOL- */ + [ 0x12 ] = KEY_CHANNELUP, /* CH+ */ + [ 0x13 ] = KEY_CHANNELDOWN, /* CH- */ + [ 0x1d ] = KEY_ENTER, /* Enter */ + + [ 0x1a ] = KEY_MODE, /* PIP */ + [ 0x18 ] = KEY_TUNER, /* Source */ + + [ 0x1e ] = KEY_RECORD, /* Record/Pause */ + [ 0x15 ] = KEY_ANGLE, /* Swap (no label on key) */ + [ 0x1c ] = KEY_PAUSE, /* Timeshift/Pause */ + [ 0x19 ] = KEY_BACK, /* Rewind << */ + [ 0x0a ] = KEY_PLAYPAUSE, /* Play/Pause */ + [ 0x1f ] = KEY_FORWARD, /* Forward >> */ + [ 0x16 ] = KEY_PREVIOUS, /* Back |<< */ + [ 0x11 ] = KEY_STOP, /* Stop */ + [ 0x0e ] = KEY_NEXT, /* End >>| */ }; EXPORT_SYMBOL_GPL(ir_codes_flydvb); @@ -1034,15 +1038,15 @@ IR_KEYTAB_TYPE ir_codes_cinergy[IR_KEYTAB_SIZE] = { [ 0x09 ] = KEY_9, [ 0x0a ] = KEY_POWER, - [ 0x0b ] = KEY_PROG1, // app - [ 0x0c ] = KEY_ZOOM, // zoom/fullscreen - [ 0x0d ] = KEY_CHANNELUP, // channel - [ 0x0e ] = KEY_CHANNELDOWN, // channel- + [ 0x0b ] = KEY_PROG1, /* app */ + [ 0x0c ] = KEY_ZOOM, /* zoom/fullscreen */ + [ 0x0d ] = KEY_CHANNELUP, /* channel */ + [ 0x0e ] = KEY_CHANNELDOWN, /* channel- */ [ 0x0f ] = KEY_VOLUMEUP, [ 0x10 ] = KEY_VOLUMEDOWN, - [ 0x11 ] = KEY_TUNER, // AV - [ 0x12 ] = KEY_NUMLOCK, // -/-- - [ 0x13 ] = KEY_AUDIO, // audio + [ 0x11 ] = KEY_TUNER, /* AV */ + [ 0x12 ] = KEY_NUMLOCK, /* -/-- */ + [ 0x13 ] = KEY_AUDIO, /* audio */ [ 0x14 ] = KEY_MUTE, [ 0x15 ] = KEY_UP, [ 0x16 ] = KEY_DOWN, @@ -1050,7 +1054,7 @@ IR_KEYTAB_TYPE ir_codes_cinergy[IR_KEYTAB_SIZE] = { [ 0x18 ] = KEY_RIGHT, [ 0x19 ] = BTN_LEFT, [ 0x1a ] = BTN_RIGHT, - [ 0x1b ] = KEY_WWW, // text + [ 0x1b ] = KEY_WWW, /* text */ [ 0x1c ] = KEY_REWIND, [ 0x1d ] = KEY_FORWARD, [ 0x1e ] = KEY_RECORD, @@ -1067,38 +1071,38 @@ EXPORT_SYMBOL_GPL(ir_codes_cinergy); * updates from Job D. R. Borges */ IR_KEYTAB_TYPE ir_codes_eztv[IR_KEYTAB_SIZE] = { [ 0x12 ] = KEY_POWER, - [ 0x01 ] = KEY_TV, // DVR - [ 0x15 ] = KEY_DVD, // DVD - [ 0x17 ] = KEY_AUDIO, // music - // DVR mode / DVD mode / music mode - - [ 0x1b ] = KEY_MUTE, // mute - [ 0x02 ] = KEY_LANGUAGE, // MTS/SAP / audio / autoseek - [ 0x1e ] = KEY_SUBTITLE, // closed captioning / subtitle / seek - [ 0x16 ] = KEY_ZOOM, // full screen - [ 0x1c ] = KEY_VIDEO, // video source / eject / delall - [ 0x1d ] = KEY_RESTART, // playback / angle / del - [ 0x2f ] = KEY_SEARCH, // scan / menu / playlist - [ 0x30 ] = KEY_CHANNEL, // CH surfing / bookmark / memo - - [ 0x31 ] = KEY_HELP, // help - [ 0x32 ] = KEY_MODE, // num/memo - [ 0x33 ] = KEY_ESC, // cancel - - [ 0x0c ] = KEY_UP, // up - [ 0x10 ] = KEY_DOWN, // down - [ 0x08 ] = KEY_LEFT, // left - [ 0x04 ] = KEY_RIGHT, // right - [ 0x03 ] = KEY_SELECT, // select - - [ 0x1f ] = KEY_REWIND, // rewind - [ 0x20 ] = KEY_PLAYPAUSE, // play/pause - [ 0x29 ] = KEY_FORWARD, // forward - [ 0x14 ] = KEY_AGAIN, // repeat - [ 0x2b ] = KEY_RECORD, // recording - [ 0x2c ] = KEY_STOP, // stop - [ 0x2d ] = KEY_PLAY, // play - [ 0x2e ] = KEY_SHUFFLE, // snapshot / shuffle + [ 0x01 ] = KEY_TV, /* DVR */ + [ 0x15 ] = KEY_DVD, /* DVD */ + [ 0x17 ] = KEY_AUDIO, /* music */ + /* DVR mode / DVD mode / music mode */ + + [ 0x1b ] = KEY_MUTE, /* mute */ + [ 0x02 ] = KEY_LANGUAGE, /* MTS/SAP / audio / autoseek */ + [ 0x1e ] = KEY_SUBTITLE, /* closed captioning / subtitle / seek */ + [ 0x16 ] = KEY_ZOOM, /* full screen */ + [ 0x1c ] = KEY_VIDEO, /* video source / eject / delall */ + [ 0x1d ] = KEY_RESTART, /* playback / angle / del */ + [ 0x2f ] = KEY_SEARCH, /* scan / menu / playlist */ + [ 0x30 ] = KEY_CHANNEL, /* CH surfing / bookmark / memo */ + + [ 0x31 ] = KEY_HELP, /* help */ + [ 0x32 ] = KEY_MODE, /* num/memo */ + [ 0x33 ] = KEY_ESC, /* cancel */ + + [ 0x0c ] = KEY_UP, /* up */ + [ 0x10 ] = KEY_DOWN, /* down */ + [ 0x08 ] = KEY_LEFT, /* left */ + [ 0x04 ] = KEY_RIGHT, /* right */ + [ 0x03 ] = KEY_SELECT, /* select */ + + [ 0x1f ] = KEY_REWIND, /* rewind */ + [ 0x20 ] = KEY_PLAYPAUSE, /* play/pause */ + [ 0x29 ] = KEY_FORWARD, /* forward */ + [ 0x14 ] = KEY_AGAIN, /* repeat */ + [ 0x2b ] = KEY_RECORD, /* recording */ + [ 0x2c ] = KEY_STOP, /* stop */ + [ 0x2d ] = KEY_PLAY, /* play */ + [ 0x2e ] = KEY_SHUFFLE, /* snapshot / shuffle */ [ 0x00 ] = KEY_0, [ 0x05 ] = KEY_1, @@ -1113,11 +1117,11 @@ IR_KEYTAB_TYPE ir_codes_eztv[IR_KEYTAB_SIZE] = { [ 0x2a ] = KEY_VOLUMEUP, [ 0x11 ] = KEY_VOLUMEDOWN, - [ 0x18 ] = KEY_CHANNELUP, // CH.tracking up - [ 0x19 ] = KEY_CHANNELDOWN, // CH.tracking down + [ 0x18 ] = KEY_CHANNELUP, /* CH.tracking up */ + [ 0x19 ] = KEY_CHANNELDOWN, /* CH.tracking down */ - [ 0x13 ] = KEY_ENTER, // enter - [ 0x21 ] = KEY_DOT, // . (decimal dot) + [ 0x13 ] = KEY_ENTER, /* enter */ + [ 0x21 ] = KEY_DOT, /* . (decimal dot) */ }; EXPORT_SYMBOL_GPL(ir_codes_eztv); @@ -1315,7 +1319,7 @@ IR_KEYTAB_TYPE ir_codes_manli[IR_KEYTAB_SIZE] = { [ 0x13 ] = KEY_MUTE, [ 0x19 ] = KEY_RECORD, /*XXX*/ - // 0x1d unused ? + /* 0x1d unused ? */ }; EXPORT_SYMBOL_GPL(ir_codes_manli); @@ -1401,10 +1405,10 @@ IR_KEYTAB_TYPE ir_codes_purpletv[IR_KEYTAB_SIZE] = { [ 0x45 ] = KEY_PAUSE, /* Pause */ [ 0x44 ] = KEY_STOP, #if 0 - [ 0x43 ] = KEY_T, // Time Shift - [ 0x47 ] = KEY_Y, // Time Shift OFF - [ 0x4a ] = KEY_O, // TOP - [ 0x17 ] = KEY_F, // SURF CH + [ 0x43 ] = KEY_T, /* Time Shift */ + [ 0x47 ] = KEY_Y, /* Time Shift OFF */ + [ 0x4a ] = KEY_O, /* TOP */ + [ 0x17 ] = KEY_F, /* SURF CH */ #endif [ 0x40 ] = KEY_FORWARD, /* Forward ? */ [ 0x42 ] = KEY_REWIND, /* Backward ? */ @@ -1538,37 +1542,37 @@ IR_KEYTAB_TYPE ir_codes_rc5_tv[IR_KEYTAB_SIZE] = { [ 0x3d ] = KEY_SUSPEND, /* system standby */ #if 0 /* FIXME */ - [ 0x0a ] = KEY_RESERVED, // 1/2/3 digits (japan: 10) - [ 0x0e ] = KEY_RESERVED, // P.P. (personal preference) - [ 0x14 ] = KEY_RESERVED, // colour saturation + - [ 0x15 ] = KEY_RESERVED, // colour saturation - - [ 0x16 ] = KEY_RESERVED, // bass + - [ 0x17 ] = KEY_RESERVED, // bass - - [ 0x18 ] = KEY_RESERVED, // treble + - [ 0x19 ] = KEY_RESERVED, // treble - - [ 0x1a ] = KEY_RESERVED, // balance right - [ 0x1b ] = KEY_RESERVED, // balance left - [ 0x1c ] = KEY_RESERVED, // contrast + - [ 0x1d ] = KEY_RESERVED, // contrast - - [ 0x1f ] = KEY_RESERVED, // tint/hue + - [ 0x24 ] = KEY_RESERVED, // spacial stereo on/off - [ 0x25 ] = KEY_RESERVED, // mono / stereo (USA) - [ 0x27 ] = KEY_RESERVED, // tint / hue - - [ 0x28 ] = KEY_RESERVED, // RF switch/PIP select - [ 0x29 ] = KEY_RESERVED, // vote - [ 0x2a ] = KEY_RESERVED, // timed page/channel clck - [ 0x2b ] = KEY_RESERVED, // increment (USA) - [ 0x2c ] = KEY_RESERVED, // decrement (USA) - [ 0x2d ] = KEY_RESERVED, // - [ 0x2f ] = KEY_RESERVED, // PIP shift - [ 0x31 ] = KEY_RESERVED, // erase - [ 0x34 ] = KEY_RESERVED, // wind - [ 0x38 ] = KEY_RESERVED, // external 1 - [ 0x39 ] = KEY_RESERVED, // external 2 - [ 0x3a ] = KEY_RESERVED, // PIP display mode - [ 0x3b ] = KEY_RESERVED, // view data mode / advance - [ 0x3e ] = KEY_RESERVED, // crispener on/off - [ 0x3f ] = KEY_RESERVED, // system select + [ 0x0a ] = KEY_RESERVED, /* 1/2/3 digits (japan: 10) */ + [ 0x0e ] = KEY_RESERVED, /* P.P. (personal preference) */ + [ 0x14 ] = KEY_RESERVED, /* colour saturation + */ + [ 0x15 ] = KEY_RESERVED, /* colour saturation - */ + [ 0x16 ] = KEY_RESERVED, /* bass + */ + [ 0x17 ] = KEY_RESERVED, /* bass - */ + [ 0x18 ] = KEY_RESERVED, /* treble + */ + [ 0x19 ] = KEY_RESERVED, /* treble - */ + [ 0x1a ] = KEY_RESERVED, /* balance right */ + [ 0x1b ] = KEY_RESERVED, /* balance left */ + [ 0x1c ] = KEY_RESERVED, /* contrast + */ + [ 0x1d ] = KEY_RESERVED, /* contrast - */ + [ 0x1f ] = KEY_RESERVED, /* tint/hue + */ + [ 0x24 ] = KEY_RESERVED, /* spacial stereo on/off */ + [ 0x25 ] = KEY_RESERVED, /* mono / stereo (USA) */ + [ 0x27 ] = KEY_RESERVED, /* tint / hue - */ + [ 0x28 ] = KEY_RESERVED, /* RF switch/PIP select */ + [ 0x29 ] = KEY_RESERVED, /* vote */ + [ 0x2a ] = KEY_RESERVED, /* timed page/channel clck */ + [ 0x2b ] = KEY_RESERVED, /* increment (USA) */ + [ 0x2c ] = KEY_RESERVED, /* decrement (USA) */ + [ 0x2d ] = KEY_RESERVED, /* */ + [ 0x2f ] = KEY_RESERVED, /* PIP shift */ + [ 0x31 ] = KEY_RESERVED, /* erase */ + [ 0x34 ] = KEY_RESERVED, /* wind */ + [ 0x38 ] = KEY_RESERVED, /* external 1 */ + [ 0x39 ] = KEY_RESERVED, /* external 2 */ + [ 0x3a ] = KEY_RESERVED, /* PIP display mode */ + [ 0x3b ] = KEY_RESERVED, /* view data mode / advance */ + [ 0x3e ] = KEY_RESERVED, /* crispener on/off */ + [ 0x3f ] = KEY_RESERVED, /* system select */ #endif }; -- cgit v1.2.3 From 69e2a0c79f10cbafd694fdc7901ea3f1a98848bf Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 27 Aug 2009 09:31:30 -0300 Subject: CodingStyle: Use [0x0f] instead of [ 0x0f ] From: Mauro Carvalho Chehab Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/common/ir-keymaps.c | 3070 +++++++++++++++---------------- 1 file changed, 1535 insertions(+), 1535 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/common/ir-keymaps.c b/linux/drivers/media/common/ir-keymaps.c index 471df71a3..cf9950bf3 100644 --- a/linux/drivers/media/common/ir-keymaps.c +++ b/linux/drivers/media/common/ir-keymaps.c @@ -27,7 +27,7 @@ /* empty keytable, can be used as placeholder for not-yet created keytables */ IR_KEYTAB_TYPE ir_codes_empty[IR_KEYTAB_SIZE] = { - [ 0x2a ] = KEY_COFFEE, + [0x2a] = KEY_COFFEE, }; EXPORT_SYMBOL_GPL(ir_codes_empty); @@ -35,71 +35,71 @@ EXPORT_SYMBOL_GPL(ir_codes_empty); /* Michal Majchrowicz */ IR_KEYTAB_TYPE ir_codes_proteus_2309[IR_KEYTAB_SIZE] = { /* numeric */ - [ 0x00 ] = KEY_0, - [ 0x01 ] = KEY_1, - [ 0x02 ] = KEY_2, - [ 0x03 ] = KEY_3, - [ 0x04 ] = KEY_4, - [ 0x05 ] = KEY_5, - [ 0x06 ] = KEY_6, - [ 0x07 ] = KEY_7, - [ 0x08 ] = KEY_8, - [ 0x09 ] = KEY_9, - - [ 0x5c ] = KEY_POWER, /* power */ - [ 0x20 ] = KEY_F, /* full screen */ - [ 0x0f ] = KEY_BACKSPACE, /* recall */ - [ 0x1b ] = KEY_ENTER, /* mute */ - [ 0x41 ] = KEY_RECORD, /* record */ - [ 0x43 ] = KEY_STOP, /* stop */ - [ 0x16 ] = KEY_S, - [ 0x1a ] = KEY_Q, /* off */ - [ 0x2e ] = KEY_RED, - [ 0x1f ] = KEY_DOWN, /* channel - */ - [ 0x1c ] = KEY_UP, /* channel + */ - [ 0x10 ] = KEY_LEFT, /* volume - */ - [ 0x1e ] = KEY_RIGHT, /* volume + */ - [ 0x14 ] = KEY_F1, + [0x00] = KEY_0, + [0x01] = KEY_1, + [0x02] = KEY_2, + [0x03] = KEY_3, + [0x04] = KEY_4, + [0x05] = KEY_5, + [0x06] = KEY_6, + [0x07] = KEY_7, + [0x08] = KEY_8, + [0x09] = KEY_9, + + [0x5c] = KEY_POWER, /* power */ + [0x20] = KEY_F, /* full screen */ + [0x0f] = KEY_BACKSPACE, /* recall */ + [0x1b] = KEY_ENTER, /* mute */ + [0x41] = KEY_RECORD, /* record */ + [0x43] = KEY_STOP, /* stop */ + [0x16] = KEY_S, + [0x1a] = KEY_Q, /* off */ + [0x2e] = KEY_RED, + [0x1f] = KEY_DOWN, /* channel - */ + [0x1c] = KEY_UP, /* channel + */ + [0x10] = KEY_LEFT, /* volume - */ + [0x1e] = KEY_RIGHT, /* volume + */ + [0x14] = KEY_F1, }; EXPORT_SYMBOL_GPL(ir_codes_proteus_2309); /* Matt Jesson >' */ - [ 0x3a ] = KEY_RECORD, /* 'capture' */ - [ 0x0a ] = KEY_MUTE, /* 'mute' */ - [ 0x2c ] = KEY_RECORD, /* 'record' */ - [ 0x1c ] = KEY_PAUSE, /* 'pause' */ - [ 0x3c ] = KEY_STOP, /* 'stop' */ - [ 0x0c ] = KEY_PLAY, /* 'play' */ - [ 0x2e ] = KEY_RED, /* 'red' */ - [ 0x01 ] = KEY_BLUE, /* 'blue' / 'cancel' */ - [ 0x0e ] = KEY_YELLOW, /* 'yellow' / 'ok' */ - [ 0x21 ] = KEY_GREEN, /* 'green' */ - [ 0x11 ] = KEY_CHANNELDOWN, /* 'channel -' */ - [ 0x31 ] = KEY_CHANNELUP, /* 'channel +' */ - [ 0x1e ] = KEY_VOLUMEDOWN, /* 'volume -' */ - [ 0x3e ] = KEY_VOLUMEUP, /* 'volume +' */ + [0x28] = KEY_0, /* '0' / 'enter' */ + [0x22] = KEY_1, /* '1' */ + [0x12] = KEY_2, /* '2' / 'up arrow' */ + [0x32] = KEY_3, /* '3' */ + [0x24] = KEY_4, /* '4' / 'left arrow' */ + [0x14] = KEY_5, /* '5' */ + [0x34] = KEY_6, /* '6' / 'right arrow' */ + [0x26] = KEY_7, /* '7' */ + [0x16] = KEY_8, /* '8' / 'down arrow' */ + [0x36] = KEY_9, /* '9' */ + + [0x20] = KEY_LIST, /* 'source' */ + [0x10] = KEY_TEXT, /* 'teletext' */ + [0x00] = KEY_POWER, /* 'power' */ + [0x04] = KEY_AUDIO, /* 'audio' */ + [0x06] = KEY_ZOOM, /* 'full screen' */ + [0x18] = KEY_VIDEO, /* 'display' */ + [0x38] = KEY_SEARCH, /* 'loop' */ + [0x08] = KEY_INFO, /* 'preview' */ + [0x2a] = KEY_REWIND, /* 'backward <<' */ + [0x1a] = KEY_FASTFORWARD, /* 'forward >>' */ + [0x3a] = KEY_RECORD, /* 'capture' */ + [0x0a] = KEY_MUTE, /* 'mute' */ + [0x2c] = KEY_RECORD, /* 'record' */ + [0x1c] = KEY_PAUSE, /* 'pause' */ + [0x3c] = KEY_STOP, /* 'stop' */ + [0x0c] = KEY_PLAY, /* 'play' */ + [0x2e] = KEY_RED, /* 'red' */ + [0x01] = KEY_BLUE, /* 'blue' / 'cancel' */ + [0x0e] = KEY_YELLOW, /* 'yellow' / 'ok' */ + [0x21] = KEY_GREEN, /* 'green' */ + [0x11] = KEY_CHANNELDOWN, /* 'channel -' */ + [0x31] = KEY_CHANNELUP, /* 'channel +' */ + [0x1e] = KEY_VOLUMEDOWN, /* 'volume -' */ + [0x3e] = KEY_VOLUMEUP, /* 'volume +' */ }; EXPORT_SYMBOL_GPL(ir_codes_avermedia_dvbt); @@ -216,42 +216,42 @@ EXPORT_SYMBOL_GPL(ir_codes_avermedia_cardbus); /* Attila Kondoros */ IR_KEYTAB_TYPE ir_codes_apac_viewcomp[IR_KEYTAB_SIZE] = { - [ 0x01 ] = KEY_1, - [ 0x02 ] = KEY_2, - [ 0x03 ] = KEY_3, - [ 0x04 ] = KEY_4, - [ 0x05 ] = KEY_5, - [ 0x06 ] = KEY_6, - [ 0x07 ] = KEY_7, - [ 0x08 ] = KEY_8, - [ 0x09 ] = KEY_9, - [ 0x00 ] = KEY_0, - [ 0x17 ] = KEY_LAST, /* +100 */ - [ 0x0a ] = KEY_LIST, /* recall */ - - - [ 0x1c ] = KEY_TUNER, /* TV/FM */ - [ 0x15 ] = KEY_SEARCH, /* scan */ - [ 0x12 ] = KEY_POWER, /* power */ - [ 0x1f ] = KEY_VOLUMEDOWN, /* vol up */ - [ 0x1b ] = KEY_VOLUMEUP, /* vol down */ - [ 0x1e ] = KEY_CHANNELDOWN, /* chn up */ - [ 0x1a ] = KEY_CHANNELUP, /* chn down */ - - [ 0x11 ] = KEY_VIDEO, /* video */ - [ 0x0f ] = KEY_ZOOM, /* full screen */ - [ 0x13 ] = KEY_MUTE, /* mute/unmute */ - [ 0x10 ] = KEY_TEXT, /* min */ - - [ 0x0d ] = KEY_STOP, /* freeze */ - [ 0x0e ] = KEY_RECORD, /* record */ - [ 0x1d ] = KEY_PLAYPAUSE, /* stop */ - [ 0x19 ] = KEY_PLAY, /* play */ - - [ 0x16 ] = KEY_GOTO, /* osd */ - [ 0x14 ] = KEY_REFRESH, /* default */ - [ 0x0c ] = KEY_KPPLUS, /* fine tune >>>> */ - [ 0x18 ] = KEY_KPMINUS /* fine tune <<<< */ + [0x01] = KEY_1, + [0x02] = KEY_2, + [0x03] = KEY_3, + [0x04] = KEY_4, + [0x05] = KEY_5, + [0x06] = KEY_6, + [0x07] = KEY_7, + [0x08] = KEY_8, + [0x09] = KEY_9, + [0x00] = KEY_0, + [0x17] = KEY_LAST, /* +100 */ + [0x0a] = KEY_LIST, /* recall */ + + + [0x1c] = KEY_TUNER, /* TV/FM */ + [0x15] = KEY_SEARCH, /* scan */ + [0x12] = KEY_POWER, /* power */ + [0x1f] = KEY_VOLUMEDOWN, /* vol up */ + [0x1b] = KEY_VOLUMEUP, /* vol down */ + [0x1e] = KEY_CHANNELDOWN, /* chn up */ + [0x1a] = KEY_CHANNELUP, /* chn down */ + + [0x11] = KEY_VIDEO, /* video */ + [0x0f] = KEY_ZOOM, /* full screen */ + [0x13] = KEY_MUTE, /* mute/unmute */ + [0x10] = KEY_TEXT, /* min */ + + [0x0d] = KEY_STOP, /* freeze */ + [0x0e] = KEY_RECORD, /* record */ + [0x1d] = KEY_PLAYPAUSE, /* stop */ + [0x19] = KEY_PLAY, /* play */ + + [0x16] = KEY_GOTO, /* osd */ + [0x14] = KEY_REFRESH, /* default */ + [0x0c] = KEY_KPPLUS, /* fine tune >>>> */ + [0x18] = KEY_KPMINUS /* fine tune <<<< */ }; EXPORT_SYMBOL_GPL(ir_codes_apac_viewcomp); @@ -260,9 +260,9 @@ EXPORT_SYMBOL_GPL(ir_codes_apac_viewcomp); IR_KEYTAB_TYPE ir_codes_pixelview[IR_KEYTAB_SIZE] = { - [ 0x1e ] = KEY_POWER, /* power */ - [ 0x07 ] = KEY_MEDIA, /* source */ - [ 0x1c ] = KEY_SEARCH, /* scan */ + [0x1e] = KEY_POWER, /* power */ + [0x07] = KEY_MEDIA, /* source */ + [0x1c] = KEY_SEARCH, /* scan */ #if 0 /* FIXME: duplicate keycodes? */ @@ -275,11 +275,11 @@ IR_KEYTAB_TYPE ir_codes_pixelview[IR_KEYTAB_SIZE] = { * 6384fb for "Tune <" and "<<<", * 638cfb for "Tune >" and ">>>", regardless of the mask. */ - [ 0x17 ] = KEY_BACK, /* fm scan << */ - [ 0x1f ] = KEY_FORWARD, /* fm scan >> */ + [0x17] = KEY_BACK, /* fm scan << */ + [0x1f] = KEY_FORWARD, /* fm scan >> */ - [ 0x04 ] = KEY_LEFT, /* fm tuning < */ - [ 0x0c ] = KEY_RIGHT, /* fm tuning > */ + [0x04] = KEY_LEFT, /* fm tuning < */ + [0x0c] = KEY_RIGHT, /* fm tuning > */ /* * For now, these four keys are disabled. Pressing them will generate @@ -287,41 +287,41 @@ IR_KEYTAB_TYPE ir_codes_pixelview[IR_KEYTAB_SIZE] = { */ #endif - [ 0x03 ] = KEY_TUNER, /* TV/FM */ - - [ 0x00 ] = KEY_RECORD, - [ 0x08 ] = KEY_STOP, - [ 0x11 ] = KEY_PLAY, - - [ 0x1a ] = KEY_PLAYPAUSE, /* freeze */ - [ 0x19 ] = KEY_ZOOM, /* zoom */ - [ 0x0f ] = KEY_TEXT, /* min */ - - [ 0x01 ] = KEY_1, - [ 0x0b ] = KEY_2, - [ 0x1b ] = KEY_3, - [ 0x05 ] = KEY_4, - [ 0x09 ] = KEY_5, - [ 0x15 ] = KEY_6, - [ 0x06 ] = KEY_7, - [ 0x0a ] = KEY_8, - [ 0x12 ] = KEY_9, - [ 0x02 ] = KEY_0, - [ 0x10 ] = KEY_LAST, /* +100 */ - [ 0x13 ] = KEY_LIST, /* recall */ - - [ 0x1f ] = KEY_CHANNELUP, /* chn down */ - [ 0x17 ] = KEY_CHANNELDOWN, /* chn up */ - [ 0x16 ] = KEY_VOLUMEUP, /* vol down */ - [ 0x14 ] = KEY_VOLUMEDOWN, /* vol up */ - - [ 0x04 ] = KEY_KPMINUS, /* <<< */ - [ 0x0e ] = KEY_SETUP, /* function */ - [ 0x0c ] = KEY_KPPLUS, /* >>> */ - - [ 0x0d ] = KEY_GOTO, /* mts */ - [ 0x1d ] = KEY_REFRESH, /* reset */ - [ 0x18 ] = KEY_MUTE /* mute/unmute */ + [0x03] = KEY_TUNER, /* TV/FM */ + + [0x00] = KEY_RECORD, + [0x08] = KEY_STOP, + [0x11] = KEY_PLAY, + + [0x1a] = KEY_PLAYPAUSE, /* freeze */ + [0x19] = KEY_ZOOM, /* zoom */ + [0x0f] = KEY_TEXT, /* min */ + + [0x01] = KEY_1, + [0x0b] = KEY_2, + [0x1b] = KEY_3, + [0x05] = KEY_4, + [0x09] = KEY_5, + [0x15] = KEY_6, + [0x06] = KEY_7, + [0x0a] = KEY_8, + [0x12] = KEY_9, + [0x02] = KEY_0, + [0x10] = KEY_LAST, /* +100 */ + [0x13] = KEY_LIST, /* recall */ + + [0x1f] = KEY_CHANNELUP, /* chn down */ + [0x17] = KEY_CHANNELDOWN, /* chn up */ + [0x16] = KEY_VOLUMEUP, /* vol down */ + [0x14] = KEY_VOLUMEDOWN, /* vol up */ + + [0x04] = KEY_KPMINUS, /* <<< */ + [0x0e] = KEY_SETUP, /* function */ + [0x0c] = KEY_KPPLUS, /* >>> */ + + [0x0d] = KEY_GOTO, /* mts */ + [0x1d] = KEY_REFRESH, /* reset */ + [0x18] = KEY_MUTE /* mute/unmute */ }; EXPORT_SYMBOL_GPL(ir_codes_pixelview); @@ -372,102 +372,102 @@ IR_KEYTAB_TYPE ir_codes_pixelview_new[IR_KEYTAB_SIZE] = { EXPORT_SYMBOL_GPL(ir_codes_pixelview_new); IR_KEYTAB_TYPE ir_codes_nebula[IR_KEYTAB_SIZE] = { - [ 0x00 ] = KEY_0, - [ 0x01 ] = KEY_1, - [ 0x02 ] = KEY_2, - [ 0x03 ] = KEY_3, - [ 0x04 ] = KEY_4, - [ 0x05 ] = KEY_5, - [ 0x06 ] = KEY_6, - [ 0x07 ] = KEY_7, - [ 0x08 ] = KEY_8, - [ 0x09 ] = KEY_9, - [ 0x0a ] = KEY_TV, - [ 0x0b ] = KEY_AUX, - [ 0x0c ] = KEY_DVD, - [ 0x0d ] = KEY_POWER, - [ 0x0e ] = KEY_MHP, /* labelled 'Picture' */ - [ 0x0f ] = KEY_AUDIO, - [ 0x10 ] = KEY_INFO, - [ 0x11 ] = KEY_F13, /* 16:9 */ - [ 0x12 ] = KEY_F14, /* 14:9 */ - [ 0x13 ] = KEY_EPG, - [ 0x14 ] = KEY_EXIT, - [ 0x15 ] = KEY_MENU, - [ 0x16 ] = KEY_UP, - [ 0x17 ] = KEY_DOWN, - [ 0x18 ] = KEY_LEFT, - [ 0x19 ] = KEY_RIGHT, - [ 0x1a ] = KEY_ENTER, - [ 0x1b ] = KEY_CHANNELUP, - [ 0x1c ] = KEY_CHANNELDOWN, - [ 0x1d ] = KEY_VOLUMEUP, - [ 0x1e ] = KEY_VOLUMEDOWN, - [ 0x1f ] = KEY_RED, - [ 0x20 ] = KEY_GREEN, - [ 0x21 ] = KEY_YELLOW, - [ 0x22 ] = KEY_BLUE, - [ 0x23 ] = KEY_SUBTITLE, - [ 0x24 ] = KEY_F15, /* AD */ - [ 0x25 ] = KEY_TEXT, - [ 0x26 ] = KEY_MUTE, - [ 0x27 ] = KEY_REWIND, - [ 0x28 ] = KEY_STOP, - [ 0x29 ] = KEY_PLAY, - [ 0x2a ] = KEY_FASTFORWARD, - [ 0x2b ] = KEY_F16, /* chapter */ - [ 0x2c ] = KEY_PAUSE, - [ 0x2d ] = KEY_PLAY, - [ 0x2e ] = KEY_RECORD, - [ 0x2f ] = KEY_F17, /* picture in picture */ - [ 0x30 ] = KEY_KPPLUS, /* zoom in */ - [ 0x31 ] = KEY_KPMINUS, /* zoom out */ - [ 0x32 ] = KEY_F18, /* capture */ - [ 0x33 ] = KEY_F19, /* web */ - [ 0x34 ] = KEY_EMAIL, - [ 0x35 ] = KEY_PHONE, - [ 0x36 ] = KEY_PC + [0x00] = KEY_0, + [0x01] = KEY_1, + [0x02] = KEY_2, + [0x03] = KEY_3, + [0x04] = KEY_4, + [0x05] = KEY_5, + [0x06] = KEY_6, + [0x07] = KEY_7, + [0x08] = KEY_8, + [0x09] = KEY_9, + [0x0a] = KEY_TV, + [0x0b] = KEY_AUX, + [0x0c] = KEY_DVD, + [0x0d] = KEY_POWER, + [0x0e] = KEY_MHP, /* labelled 'Picture' */ + [0x0f] = KEY_AUDIO, + [0x10] = KEY_INFO, + [0x11] = KEY_F13, /* 16:9 */ + [0x12] = KEY_F14, /* 14:9 */ + [0x13] = KEY_EPG, + [0x14] = KEY_EXIT, + [0x15] = KEY_MENU, + [0x16] = KEY_UP, + [0x17] = KEY_DOWN, + [0x18] = KEY_LEFT, + [0x19] = KEY_RIGHT, + [0x1a] = KEY_ENTER, + [0x1b] = KEY_CHANNELUP, + [0x1c] = KEY_CHANNELDOWN, + [0x1d] = KEY_VOLUMEUP, + [0x1e] = KEY_VOLUMEDOWN, + [0x1f] = KEY_RED, + [0x20] = KEY_GREEN, + [0x21] = KEY_YELLOW, + [0x22] = KEY_BLUE, + [0x23] = KEY_SUBTITLE, + [0x24] = KEY_F15, /* AD */ + [0x25] = KEY_TEXT, + [0x26] = KEY_MUTE, + [0x27] = KEY_REWIND, + [0x28] = KEY_STOP, + [0x29] = KEY_PLAY, + [0x2a] = KEY_FASTFORWARD, + [0x2b] = KEY_F16, /* chapter */ + [0x2c] = KEY_PAUSE, + [0x2d] = KEY_PLAY, + [0x2e] = KEY_RECORD, + [0x2f] = KEY_F17, /* picture in picture */ + [0x30] = KEY_KPPLUS, /* zoom in */ + [0x31] = KEY_KPMINUS, /* zoom out */ + [0x32] = KEY_F18, /* capture */ + [0x33] = KEY_F19, /* web */ + [0x34] = KEY_EMAIL, + [0x35] = KEY_PHONE, + [0x36] = KEY_PC }; EXPORT_SYMBOL_GPL(ir_codes_nebula); /* DigitalNow DNTV Live DVB-T Remote */ IR_KEYTAB_TYPE ir_codes_dntv_live_dvb_t[IR_KEYTAB_SIZE] = { - [ 0x00 ] = KEY_ESC, /* 'go up a level?' */ + [0x00] = KEY_ESC, /* 'go up a level?' */ /* Keys 0 to 9 */ - [ 0x0a ] = KEY_0, - [ 0x01 ] = KEY_1, - [ 0x02 ] = KEY_2, - [ 0x03 ] = KEY_3, - [ 0x04 ] = KEY_4, - [ 0x05 ] = KEY_5, - [ 0x06 ] = KEY_6, - [ 0x07 ] = KEY_7, - [ 0x08 ] = KEY_8, - [ 0x09 ] = KEY_9, - - [ 0x0b ] = KEY_TUNER, /* tv/fm */ - [ 0x0c ] = KEY_SEARCH, /* scan */ - [ 0x0d ] = KEY_STOP, - [ 0x0e ] = KEY_PAUSE, - [ 0x0f ] = KEY_LIST, /* source */ - - [ 0x10 ] = KEY_MUTE, - [ 0x11 ] = KEY_REWIND, /* backward << */ - [ 0x12 ] = KEY_POWER, - [ 0x13 ] = KEY_S, /* snap */ - [ 0x14 ] = KEY_AUDIO, /* stereo */ - [ 0x15 ] = KEY_CLEAR, /* reset */ - [ 0x16 ] = KEY_PLAY, - [ 0x17 ] = KEY_ENTER, - [ 0x18 ] = KEY_ZOOM, /* full screen */ - [ 0x19 ] = KEY_FASTFORWARD, /* forward >> */ - [ 0x1a ] = KEY_CHANNELUP, - [ 0x1b ] = KEY_VOLUMEUP, - [ 0x1c ] = KEY_INFO, /* preview */ - [ 0x1d ] = KEY_RECORD, /* record */ - [ 0x1e ] = KEY_CHANNELDOWN, - [ 0x1f ] = KEY_VOLUMEDOWN, + [0x0a] = KEY_0, + [0x01] = KEY_1, + [0x02] = KEY_2, + [0x03] = KEY_3, + [0x04] = KEY_4, + [0x05] = KEY_5, + [0x06] = KEY_6, + [0x07] = KEY_7, + [0x08] = KEY_8, + [0x09] = KEY_9, + + [0x0b] = KEY_TUNER, /* tv/fm */ + [0x0c] = KEY_SEARCH, /* scan */ + [0x0d] = KEY_STOP, + [0x0e] = KEY_PAUSE, + [0x0f] = KEY_LIST, /* source */ + + [0x10] = KEY_MUTE, + [0x11] = KEY_REWIND, /* backward << */ + [0x12] = KEY_POWER, + [0x13] = KEY_S, /* snap */ + [0x14] = KEY_AUDIO, /* stereo */ + [0x15] = KEY_CLEAR, /* reset */ + [0x16] = KEY_PLAY, + [0x17] = KEY_ENTER, + [0x18] = KEY_ZOOM, /* full screen */ + [0x19] = KEY_FASTFORWARD, /* forward >> */ + [0x1a] = KEY_CHANNELUP, + [0x1b] = KEY_VOLUMEUP, + [0x1c] = KEY_INFO, /* preview */ + [0x1d] = KEY_RECORD, /* record */ + [0x1e] = KEY_CHANNELDOWN, + [0x1f] = KEY_VOLUMEDOWN, }; EXPORT_SYMBOL_GPL(ir_codes_dntv_live_dvb_t); @@ -476,51 +476,51 @@ EXPORT_SYMBOL_GPL(ir_codes_dntv_live_dvb_t); /* IO-DATA BCTV7E Remote */ IR_KEYTAB_TYPE ir_codes_iodata_bctv7e[IR_KEYTAB_SIZE] = { - [ 0x40 ] = KEY_TV, - [ 0x20 ] = KEY_RADIO, /* FM */ - [ 0x60 ] = KEY_EPG, - [ 0x00 ] = KEY_POWER, + [0x40] = KEY_TV, + [0x20] = KEY_RADIO, /* FM */ + [0x60] = KEY_EPG, + [0x00] = KEY_POWER, /* Keys 0 to 9 */ - [ 0x44 ] = KEY_0, /* 10 */ - [ 0x50 ] = KEY_1, - [ 0x30 ] = KEY_2, - [ 0x70 ] = KEY_3, - [ 0x48 ] = KEY_4, - [ 0x28 ] = KEY_5, - [ 0x68 ] = KEY_6, - [ 0x58 ] = KEY_7, - [ 0x38 ] = KEY_8, - [ 0x78 ] = KEY_9, - - [ 0x10 ] = KEY_L, /* Live */ - [ 0x08 ] = KEY_T, /* Time Shift */ - - [ 0x18 ] = KEY_PLAYPAUSE, /* Play */ - - [ 0x24 ] = KEY_ENTER, /* 11 */ - [ 0x64 ] = KEY_ESC, /* 12 */ - [ 0x04 ] = KEY_M, /* Multi */ - - [ 0x54 ] = KEY_VIDEO, - [ 0x34 ] = KEY_CHANNELUP, - [ 0x74 ] = KEY_VOLUMEUP, - [ 0x14 ] = KEY_MUTE, - - [ 0x4c ] = KEY_S, /* SVIDEO */ - [ 0x2c ] = KEY_CHANNELDOWN, - [ 0x6c ] = KEY_VOLUMEDOWN, - [ 0x0c ] = KEY_ZOOM, - - [ 0x5c ] = KEY_PAUSE, - [ 0x3c ] = KEY_C, /* || (red) */ - [ 0x7c ] = KEY_RECORD, /* recording */ - [ 0x1c ] = KEY_STOP, - - [ 0x41 ] = KEY_REWIND, /* backward << */ - [ 0x21 ] = KEY_PLAY, - [ 0x61 ] = KEY_FASTFORWARD, /* forward >> */ - [ 0x01 ] = KEY_NEXT, /* skip >| */ + [0x44] = KEY_0, /* 10 */ + [0x50] = KEY_1, + [0x30] = KEY_2, + [0x70] = KEY_3, + [0x48] = KEY_4, + [0x28] = KEY_5, + [0x68] = KEY_6, + [0x58] = KEY_7, + [0x38] = KEY_8, + [0x78] = KEY_9, + + [0x10] = KEY_L, /* Live */ + [0x08] = KEY_T, /* Time Shift */ + + [0x18] = KEY_PLAYPAUSE, /* Play */ + + [0x24] = KEY_ENTER, /* 11 */ + [0x64] = KEY_ESC, /* 12 */ + [0x04] = KEY_M, /* Multi */ + + [0x54] = KEY_VIDEO, + [0x34] = KEY_CHANNELUP, + [0x74] = KEY_VOLUMEUP, + [0x14] = KEY_MUTE, + + [0x4c] = KEY_S, /* SVIDEO */ + [0x2c] = KEY_CHANNELDOWN, + [0x6c] = KEY_VOLUMEDOWN, + [0x0c] = KEY_ZOOM, + + [0x5c] = KEY_PAUSE, + [0x3c] = KEY_C, /* || (red) */ + [0x7c] = KEY_RECORD, /* recording */ + [0x1c] = KEY_STOP, + + [0x41] = KEY_REWIND, /* backward << */ + [0x21] = KEY_PLAY, + [0x61] = KEY_FASTFORWARD, /* forward >> */ + [0x01] = KEY_NEXT, /* skip >| */ }; EXPORT_SYMBOL_GPL(ir_codes_iodata_bctv7e); @@ -530,51 +530,51 @@ EXPORT_SYMBOL_GPL(ir_codes_iodata_bctv7e); /* ADS Tech Instant TV DVB-T PCI Remote */ IR_KEYTAB_TYPE ir_codes_adstech_dvb_t_pci[IR_KEYTAB_SIZE] = { /* Keys 0 to 9 */ - [ 0x4d ] = KEY_0, - [ 0x57 ] = KEY_1, - [ 0x4f ] = KEY_2, - [ 0x53 ] = KEY_3, - [ 0x56 ] = KEY_4, - [ 0x4e ] = KEY_5, - [ 0x5e ] = KEY_6, - [ 0x54 ] = KEY_7, - [ 0x4c ] = KEY_8, - [ 0x5c ] = KEY_9, - - [ 0x5b ] = KEY_POWER, - [ 0x5f ] = KEY_MUTE, - [ 0x55 ] = KEY_GOTO, - [ 0x5d ] = KEY_SEARCH, - [ 0x17 ] = KEY_EPG, /* Guide */ - [ 0x1f ] = KEY_MENU, - [ 0x0f ] = KEY_UP, - [ 0x46 ] = KEY_DOWN, - [ 0x16 ] = KEY_LEFT, - [ 0x1e ] = KEY_RIGHT, - [ 0x0e ] = KEY_SELECT, /* Enter */ - [ 0x5a ] = KEY_INFO, - [ 0x52 ] = KEY_EXIT, - [ 0x59 ] = KEY_PREVIOUS, - [ 0x51 ] = KEY_NEXT, - [ 0x58 ] = KEY_REWIND, - [ 0x50 ] = KEY_FORWARD, - [ 0x44 ] = KEY_PLAYPAUSE, - [ 0x07 ] = KEY_STOP, - [ 0x1b ] = KEY_RECORD, - [ 0x13 ] = KEY_TUNER, /* Live */ - [ 0x0a ] = KEY_A, - [ 0x12 ] = KEY_B, - [ 0x03 ] = KEY_PROG1, /* 1 */ - [ 0x01 ] = KEY_PROG2, /* 2 */ - [ 0x00 ] = KEY_PROG3, /* 3 */ - [ 0x06 ] = KEY_DVD, - [ 0x48 ] = KEY_AUX, /* Photo */ - [ 0x40 ] = KEY_VIDEO, - [ 0x19 ] = KEY_AUDIO, /* Music */ - [ 0x0b ] = KEY_CHANNELUP, - [ 0x08 ] = KEY_CHANNELDOWN, - [ 0x15 ] = KEY_VOLUMEUP, - [ 0x1c ] = KEY_VOLUMEDOWN, + [0x4d] = KEY_0, + [0x57] = KEY_1, + [0x4f] = KEY_2, + [0x53] = KEY_3, + [0x56] = KEY_4, + [0x4e] = KEY_5, + [0x5e] = KEY_6, + [0x54] = KEY_7, + [0x4c] = KEY_8, + [0x5c] = KEY_9, + + [0x5b] = KEY_POWER, + [0x5f] = KEY_MUTE, + [0x55] = KEY_GOTO, + [0x5d] = KEY_SEARCH, + [0x17] = KEY_EPG, /* Guide */ + [0x1f] = KEY_MENU, + [0x0f] = KEY_UP, + [0x46] = KEY_DOWN, + [0x16] = KEY_LEFT, + [0x1e] = KEY_RIGHT, + [0x0e] = KEY_SELECT, /* Enter */ + [0x5a] = KEY_INFO, + [0x52] = KEY_EXIT, + [0x59] = KEY_PREVIOUS, + [0x51] = KEY_NEXT, + [0x58] = KEY_REWIND, + [0x50] = KEY_FORWARD, + [0x44] = KEY_PLAYPAUSE, + [0x07] = KEY_STOP, + [0x1b] = KEY_RECORD, + [0x13] = KEY_TUNER, /* Live */ + [0x0a] = KEY_A, + [0x12] = KEY_B, + [0x03] = KEY_PROG1, /* 1 */ + [0x01] = KEY_PROG2, /* 2 */ + [0x00] = KEY_PROG3, /* 3 */ + [0x06] = KEY_DVD, + [0x48] = KEY_AUX, /* Photo */ + [0x40] = KEY_VIDEO, + [0x19] = KEY_AUDIO, /* Music */ + [0x0b] = KEY_CHANNELUP, + [0x08] = KEY_CHANNELDOWN, + [0x15] = KEY_VOLUMEUP, + [0x1c] = KEY_VOLUMEDOWN, }; EXPORT_SYMBOL_GPL(ir_codes_adstech_dvb_t_pci); @@ -585,31 +585,31 @@ EXPORT_SYMBOL_GPL(ir_codes_adstech_dvb_t_pci); IR_KEYTAB_TYPE ir_codes_msi_tvanywhere[IR_KEYTAB_SIZE] = { /* Keys 0 to 9 */ - [ 0x00 ] = KEY_0, - [ 0x01 ] = KEY_1, - [ 0x02 ] = KEY_2, - [ 0x03 ] = KEY_3, - [ 0x04 ] = KEY_4, - [ 0x05 ] = KEY_5, - [ 0x06 ] = KEY_6, - [ 0x07 ] = KEY_7, - [ 0x08 ] = KEY_8, - [ 0x09 ] = KEY_9, - - [ 0x0c ] = KEY_MUTE, - [ 0x0f ] = KEY_SCREEN, /* Full Screen */ - [ 0x10 ] = KEY_F, /* Funtion */ - [ 0x11 ] = KEY_T, /* Time shift */ - [ 0x12 ] = KEY_POWER, - [ 0x13 ] = KEY_MEDIA, /* MTS */ - [ 0x14 ] = KEY_SLOW, - [ 0x16 ] = KEY_REWIND, /* backward << */ - [ 0x17 ] = KEY_ENTER, /* Return */ - [ 0x18 ] = KEY_FASTFORWARD, /* forward >> */ - [ 0x1a ] = KEY_CHANNELUP, - [ 0x1b ] = KEY_VOLUMEUP, - [ 0x1e ] = KEY_CHANNELDOWN, - [ 0x1f ] = KEY_VOLUMEDOWN, + [0x00] = KEY_0, + [0x01] = KEY_1, + [0x02] = KEY_2, + [0x03] = KEY_3, + [0x04] = KEY_4, + [0x05] = KEY_5, + [0x06] = KEY_6, + [0x07] = KEY_7, + [0x08] = KEY_8, + [0x09] = KEY_9, + + [0x0c] = KEY_MUTE, + [0x0f] = KEY_SCREEN, /* Full Screen */ + [0x10] = KEY_F, /* Funtion */ + [0x11] = KEY_T, /* Time shift */ + [0x12] = KEY_POWER, + [0x13] = KEY_MEDIA, /* MTS */ + [0x14] = KEY_SLOW, + [0x16] = KEY_REWIND, /* backward << */ + [0x17] = KEY_ENTER, /* Return */ + [0x18] = KEY_FASTFORWARD, /* forward >> */ + [0x1a] = KEY_CHANNELUP, + [0x1b] = KEY_VOLUMEUP, + [0x1e] = KEY_CHANNELDOWN, + [0x1f] = KEY_VOLUMEDOWN, }; EXPORT_SYMBOL_GPL(ir_codes_msi_tvanywhere); @@ -707,47 +707,47 @@ EXPORT_SYMBOL_GPL(ir_codes_msi_tvanywhere_plus); /* Cinergy 1400 DVB-T */ IR_KEYTAB_TYPE ir_codes_cinergy_1400[IR_KEYTAB_SIZE] = { - [ 0x01 ] = KEY_POWER, - [ 0x02 ] = KEY_1, - [ 0x03 ] = KEY_2, - [ 0x04 ] = KEY_3, - [ 0x05 ] = KEY_4, - [ 0x06 ] = KEY_5, - [ 0x07 ] = KEY_6, - [ 0x08 ] = KEY_7, - [ 0x09 ] = KEY_8, - [ 0x0a ] = KEY_9, - [ 0x0c ] = KEY_0, - - [ 0x0b ] = KEY_VIDEO, - [ 0x0d ] = KEY_REFRESH, - [ 0x0e ] = KEY_SELECT, - [ 0x0f ] = KEY_EPG, - [ 0x10 ] = KEY_UP, - [ 0x11 ] = KEY_LEFT, - [ 0x12 ] = KEY_OK, - [ 0x13 ] = KEY_RIGHT, - [ 0x14 ] = KEY_DOWN, - [ 0x15 ] = KEY_TEXT, - [ 0x16 ] = KEY_INFO, - - [ 0x17 ] = KEY_RED, - [ 0x18 ] = KEY_GREEN, - [ 0x19 ] = KEY_YELLOW, - [ 0x1a ] = KEY_BLUE, - - [ 0x1b ] = KEY_CHANNELUP, - [ 0x1c ] = KEY_VOLUMEUP, - [ 0x1d ] = KEY_MUTE, - [ 0x1e ] = KEY_VOLUMEDOWN, - [ 0x1f ] = KEY_CHANNELDOWN, - - [ 0x40 ] = KEY_PAUSE, - [ 0x4c ] = KEY_PLAY, - [ 0x58 ] = KEY_RECORD, - [ 0x54 ] = KEY_PREVIOUS, - [ 0x48 ] = KEY_STOP, - [ 0x5c ] = KEY_NEXT, + [0x01] = KEY_POWER, + [0x02] = KEY_1, + [0x03] = KEY_2, + [0x04] = KEY_3, + [0x05] = KEY_4, + [0x06] = KEY_5, + [0x07] = KEY_6, + [0x08] = KEY_7, + [0x09] = KEY_8, + [0x0a] = KEY_9, + [0x0c] = KEY_0, + + [0x0b] = KEY_VIDEO, + [0x0d] = KEY_REFRESH, + [0x0e] = KEY_SELECT, + [0x0f] = KEY_EPG, + [0x10] = KEY_UP, + [0x11] = KEY_LEFT, + [0x12] = KEY_OK, + [0x13] = KEY_RIGHT, + [0x14] = KEY_DOWN, + [0x15] = KEY_TEXT, + [0x16] = KEY_INFO, + + [0x17] = KEY_RED, + [0x18] = KEY_GREEN, + [0x19] = KEY_YELLOW, + [0x1a] = KEY_BLUE, + + [0x1b] = KEY_CHANNELUP, + [0x1c] = KEY_VOLUMEUP, + [0x1d] = KEY_MUTE, + [0x1e] = KEY_VOLUMEDOWN, + [0x1f] = KEY_CHANNELDOWN, + + [0x40] = KEY_PAUSE, + [0x4c] = KEY_PLAY, + [0x58] = KEY_RECORD, + [0x54] = KEY_PREVIOUS, + [0x48] = KEY_STOP, + [0x5c] = KEY_NEXT, }; EXPORT_SYMBOL_GPL(ir_codes_cinergy_1400); @@ -756,48 +756,48 @@ EXPORT_SYMBOL_GPL(ir_codes_cinergy_1400); /* AVERTV STUDIO 303 Remote */ IR_KEYTAB_TYPE ir_codes_avertv_303[IR_KEYTAB_SIZE] = { - [ 0x2a ] = KEY_1, - [ 0x32 ] = KEY_2, - [ 0x3a ] = KEY_3, - [ 0x4a ] = KEY_4, - [ 0x52 ] = KEY_5, - [ 0x5a ] = KEY_6, - [ 0x6a ] = KEY_7, - [ 0x72 ] = KEY_8, - [ 0x7a ] = KEY_9, - [ 0x0e ] = KEY_0, - - [ 0x02 ] = KEY_POWER, - [ 0x22 ] = KEY_VIDEO, - [ 0x42 ] = KEY_AUDIO, - [ 0x62 ] = KEY_ZOOM, - [ 0x0a ] = KEY_TV, - [ 0x12 ] = KEY_CD, - [ 0x1a ] = KEY_TEXT, - - [ 0x16 ] = KEY_SUBTITLE, - [ 0x1e ] = KEY_REWIND, - [ 0x06 ] = KEY_PRINT, - - [ 0x2e ] = KEY_SEARCH, - [ 0x36 ] = KEY_SLEEP, - [ 0x3e ] = KEY_SHUFFLE, - [ 0x26 ] = KEY_MUTE, - - [ 0x4e ] = KEY_RECORD, - [ 0x56 ] = KEY_PAUSE, - [ 0x5e ] = KEY_STOP, - [ 0x46 ] = KEY_PLAY, - - [ 0x6e ] = KEY_RED, - [ 0x0b ] = KEY_GREEN, - [ 0x66 ] = KEY_YELLOW, - [ 0x03 ] = KEY_BLUE, - - [ 0x76 ] = KEY_LEFT, - [ 0x7e ] = KEY_RIGHT, - [ 0x13 ] = KEY_DOWN, - [ 0x1b ] = KEY_UP, + [0x2a] = KEY_1, + [0x32] = KEY_2, + [0x3a] = KEY_3, + [0x4a] = KEY_4, + [0x52] = KEY_5, + [0x5a] = KEY_6, + [0x6a] = KEY_7, + [0x72] = KEY_8, + [0x7a] = KEY_9, + [0x0e] = KEY_0, + + [0x02] = KEY_POWER, + [0x22] = KEY_VIDEO, + [0x42] = KEY_AUDIO, + [0x62] = KEY_ZOOM, + [0x0a] = KEY_TV, + [0x12] = KEY_CD, + [0x1a] = KEY_TEXT, + + [0x16] = KEY_SUBTITLE, + [0x1e] = KEY_REWIND, + [0x06] = KEY_PRINT, + + [0x2e] = KEY_SEARCH, + [0x36] = KEY_SLEEP, + [0x3e] = KEY_SHUFFLE, + [0x26] = KEY_MUTE, + + [0x4e] = KEY_RECORD, + [0x56] = KEY_PAUSE, + [0x5e] = KEY_STOP, + [0x46] = KEY_PLAY, + + [0x6e] = KEY_RED, + [0x0b] = KEY_GREEN, + [0x66] = KEY_YELLOW, + [0x03] = KEY_BLUE, + + [0x76] = KEY_LEFT, + [0x7e] = KEY_RIGHT, + [0x13] = KEY_DOWN, + [0x1b] = KEY_UP, }; EXPORT_SYMBOL_GPL(ir_codes_avertv_303); @@ -806,263 +806,263 @@ EXPORT_SYMBOL_GPL(ir_codes_avertv_303); /* DigitalNow DNTV Live! DVB-T Pro Remote */ IR_KEYTAB_TYPE ir_codes_dntv_live_dvbt_pro[IR_KEYTAB_SIZE] = { - [ 0x16 ] = KEY_POWER, - [ 0x5b ] = KEY_HOME, - - [ 0x55 ] = KEY_TV, /* live tv */ - [ 0x58 ] = KEY_TUNER, /* digital Radio */ - [ 0x5a ] = KEY_RADIO, /* FM radio */ - [ 0x59 ] = KEY_DVD, /* dvd menu */ - [ 0x03 ] = KEY_1, - [ 0x01 ] = KEY_2, - [ 0x06 ] = KEY_3, - [ 0x09 ] = KEY_4, - [ 0x1d ] = KEY_5, - [ 0x1f ] = KEY_6, - [ 0x0d ] = KEY_7, - [ 0x19 ] = KEY_8, - [ 0x1b ] = KEY_9, - [ 0x0c ] = KEY_CANCEL, - [ 0x15 ] = KEY_0, - [ 0x4a ] = KEY_CLEAR, - [ 0x13 ] = KEY_BACK, - [ 0x00 ] = KEY_TAB, - [ 0x4b ] = KEY_UP, - [ 0x4e ] = KEY_LEFT, - [ 0x4f ] = KEY_OK, - [ 0x52 ] = KEY_RIGHT, - [ 0x51 ] = KEY_DOWN, - [ 0x1e ] = KEY_VOLUMEUP, - [ 0x0a ] = KEY_VOLUMEDOWN, - [ 0x02 ] = KEY_CHANNELDOWN, - [ 0x05 ] = KEY_CHANNELUP, - [ 0x11 ] = KEY_RECORD, - [ 0x14 ] = KEY_PLAY, - [ 0x4c ] = KEY_PAUSE, - [ 0x1a ] = KEY_STOP, - [ 0x40 ] = KEY_REWIND, - [ 0x12 ] = KEY_FASTFORWARD, - [ 0x41 ] = KEY_PREVIOUSSONG, /* replay |< */ - [ 0x42 ] = KEY_NEXTSONG, /* skip >| */ - [ 0x54 ] = KEY_CAMERA, /* capture */ - [ 0x50 ] = KEY_LANGUAGE, /* sap */ - [ 0x47 ] = KEY_TV2, /* pip */ - [ 0x4d ] = KEY_SCREEN, - [ 0x43 ] = KEY_SUBTITLE, - [ 0x10 ] = KEY_MUTE, - [ 0x49 ] = KEY_AUDIO, /* l/r */ - [ 0x07 ] = KEY_SLEEP, - [ 0x08 ] = KEY_VIDEO, /* a/v */ - [ 0x0e ] = KEY_PREVIOUS, /* recall */ - [ 0x45 ] = KEY_ZOOM, /* zoom + */ - [ 0x46 ] = KEY_ANGLE, /* zoom - */ - [ 0x56 ] = KEY_RED, - [ 0x57 ] = KEY_GREEN, - [ 0x5c ] = KEY_YELLOW, - [ 0x5d ] = KEY_BLUE, + [0x16] = KEY_POWER, + [0x5b] = KEY_HOME, + + [0x55] = KEY_TV, /* live tv */ + [0x58] = KEY_TUNER, /* digital Radio */ + [0x5a] = KEY_RADIO, /* FM radio */ + [0x59] = KEY_DVD, /* dvd menu */ + [0x03] = KEY_1, + [0x01] = KEY_2, + [0x06] = KEY_3, + [0x09] = KEY_4, + [0x1d] = KEY_5, + [0x1f] = KEY_6, + [0x0d] = KEY_7, + [0x19] = KEY_8, + [0x1b] = KEY_9, + [0x0c] = KEY_CANCEL, + [0x15] = KEY_0, + [0x4a] = KEY_CLEAR, + [0x13] = KEY_BACK, + [0x00] = KEY_TAB, + [0x4b] = KEY_UP, + [0x4e] = KEY_LEFT, + [0x4f] = KEY_OK, + [0x52] = KEY_RIGHT, + [0x51] = KEY_DOWN, + [0x1e] = KEY_VOLUMEUP, + [0x0a] = KEY_VOLUMEDOWN, + [0x02] = KEY_CHANNELDOWN, + [0x05] = KEY_CHANNELUP, + [0x11] = KEY_RECORD, + [0x14] = KEY_PLAY, + [0x4c] = KEY_PAUSE, + [0x1a] = KEY_STOP, + [0x40] = KEY_REWIND, + [0x12] = KEY_FASTFORWARD, + [0x41] = KEY_PREVIOUSSONG, /* replay |< */ + [0x42] = KEY_NEXTSONG, /* skip >| */ + [0x54] = KEY_CAMERA, /* capture */ + [0x50] = KEY_LANGUAGE, /* sap */ + [0x47] = KEY_TV2, /* pip */ + [0x4d] = KEY_SCREEN, + [0x43] = KEY_SUBTITLE, + [0x10] = KEY_MUTE, + [0x49] = KEY_AUDIO, /* l/r */ + [0x07] = KEY_SLEEP, + [0x08] = KEY_VIDEO, /* a/v */ + [0x0e] = KEY_PREVIOUS, /* recall */ + [0x45] = KEY_ZOOM, /* zoom + */ + [0x46] = KEY_ANGLE, /* zoom - */ + [0x56] = KEY_RED, + [0x57] = KEY_GREEN, + [0x5c] = KEY_YELLOW, + [0x5d] = KEY_BLUE, }; EXPORT_SYMBOL_GPL(ir_codes_dntv_live_dvbt_pro); IR_KEYTAB_TYPE ir_codes_em_terratec[IR_KEYTAB_SIZE] = { - [ 0x01 ] = KEY_CHANNEL, - [ 0x02 ] = KEY_SELECT, - [ 0x03 ] = KEY_MUTE, - [ 0x04 ] = KEY_POWER, - [ 0x05 ] = KEY_1, - [ 0x06 ] = KEY_2, - [ 0x07 ] = KEY_3, - [ 0x08 ] = KEY_CHANNELUP, - [ 0x09 ] = KEY_4, - [ 0x0a ] = KEY_5, - [ 0x0b ] = KEY_6, - [ 0x0c ] = KEY_CHANNELDOWN, - [ 0x0d ] = KEY_7, - [ 0x0e ] = KEY_8, - [ 0x0f ] = KEY_9, - [ 0x10 ] = KEY_VOLUMEUP, - [ 0x11 ] = KEY_0, - [ 0x12 ] = KEY_MENU, - [ 0x13 ] = KEY_PRINT, - [ 0x14 ] = KEY_VOLUMEDOWN, - [ 0x16 ] = KEY_PAUSE, - [ 0x18 ] = KEY_RECORD, - [ 0x19 ] = KEY_REWIND, - [ 0x1a ] = KEY_PLAY, - [ 0x1b ] = KEY_FORWARD, - [ 0x1c ] = KEY_BACKSPACE, - [ 0x1e ] = KEY_STOP, - [ 0x40 ] = KEY_ZOOM, + [0x01] = KEY_CHANNEL, + [0x02] = KEY_SELECT, + [0x03] = KEY_MUTE, + [0x04] = KEY_POWER, + [0x05] = KEY_1, + [0x06] = KEY_2, + [0x07] = KEY_3, + [0x08] = KEY_CHANNELUP, + [0x09] = KEY_4, + [0x0a] = KEY_5, + [0x0b] = KEY_6, + [0x0c] = KEY_CHANNELDOWN, + [0x0d] = KEY_7, + [0x0e] = KEY_8, + [0x0f] = KEY_9, + [0x10] = KEY_VOLUMEUP, + [0x11] = KEY_0, + [0x12] = KEY_MENU, + [0x13] = KEY_PRINT, + [0x14] = KEY_VOLUMEDOWN, + [0x16] = KEY_PAUSE, + [0x18] = KEY_RECORD, + [0x19] = KEY_REWIND, + [0x1a] = KEY_PLAY, + [0x1b] = KEY_FORWARD, + [0x1c] = KEY_BACKSPACE, + [0x1e] = KEY_STOP, + [0x40] = KEY_ZOOM, }; EXPORT_SYMBOL_GPL(ir_codes_em_terratec); IR_KEYTAB_TYPE ir_codes_pinnacle_grey[IR_KEYTAB_SIZE] = { - [ 0x3a ] = KEY_0, - [ 0x31 ] = KEY_1, - [ 0x32 ] = KEY_2, - [ 0x33 ] = KEY_3, - [ 0x34 ] = KEY_4, - [ 0x35 ] = KEY_5, - [ 0x36 ] = KEY_6, - [ 0x37 ] = KEY_7, - [ 0x38 ] = KEY_8, - [ 0x39 ] = KEY_9, - - [ 0x2f ] = KEY_POWER, - - [ 0x2e ] = KEY_P, - [ 0x1f ] = KEY_L, - [ 0x2b ] = KEY_I, - - [ 0x2d ] = KEY_SCREEN, - [ 0x1e ] = KEY_ZOOM, - [ 0x1b ] = KEY_VOLUMEUP, - [ 0x0f ] = KEY_VOLUMEDOWN, - [ 0x17 ] = KEY_CHANNELUP, - [ 0x1c ] = KEY_CHANNELDOWN, - [ 0x25 ] = KEY_INFO, - - [ 0x3c ] = KEY_MUTE, - - [ 0x3d ] = KEY_LEFT, - [ 0x3b ] = KEY_RIGHT, - - [ 0x3f ] = KEY_UP, - [ 0x3e ] = KEY_DOWN, - [ 0x1a ] = KEY_ENTER, - - [ 0x1d ] = KEY_MENU, - [ 0x19 ] = KEY_AGAIN, - [ 0x16 ] = KEY_PREVIOUSSONG, - [ 0x13 ] = KEY_NEXTSONG, - [ 0x15 ] = KEY_PAUSE, - [ 0x0e ] = KEY_REWIND, - [ 0x0d ] = KEY_PLAY, - [ 0x0b ] = KEY_STOP, - [ 0x07 ] = KEY_FORWARD, - [ 0x27 ] = KEY_RECORD, - [ 0x26 ] = KEY_TUNER, - [ 0x29 ] = KEY_TEXT, - [ 0x2a ] = KEY_MEDIA, - [ 0x18 ] = KEY_EPG, + [0x3a] = KEY_0, + [0x31] = KEY_1, + [0x32] = KEY_2, + [0x33] = KEY_3, + [0x34] = KEY_4, + [0x35] = KEY_5, + [0x36] = KEY_6, + [0x37] = KEY_7, + [0x38] = KEY_8, + [0x39] = KEY_9, + + [0x2f] = KEY_POWER, + + [0x2e] = KEY_P, + [0x1f] = KEY_L, + [0x2b] = KEY_I, + + [0x2d] = KEY_SCREEN, + [0x1e] = KEY_ZOOM, + [0x1b] = KEY_VOLUMEUP, + [0x0f] = KEY_VOLUMEDOWN, + [0x17] = KEY_CHANNELUP, + [0x1c] = KEY_CHANNELDOWN, + [0x25] = KEY_INFO, + + [0x3c] = KEY_MUTE, + + [0x3d] = KEY_LEFT, + [0x3b] = KEY_RIGHT, + + [0x3f] = KEY_UP, + [0x3e] = KEY_DOWN, + [0x1a] = KEY_ENTER, + + [0x1d] = KEY_MENU, + [0x19] = KEY_AGAIN, + [0x16] = KEY_PREVIOUSSONG, + [0x13] = KEY_NEXTSONG, + [0x15] = KEY_PAUSE, + [0x0e] = KEY_REWIND, + [0x0d] = KEY_PLAY, + [0x0b] = KEY_STOP, + [0x07] = KEY_FORWARD, + [0x27] = KEY_RECORD, + [0x26] = KEY_TUNER, + [0x29] = KEY_TEXT, + [0x2a] = KEY_MEDIA, + [0x18] = KEY_EPG, }; EXPORT_SYMBOL_GPL(ir_codes_pinnacle_grey); IR_KEYTAB_TYPE ir_codes_flyvideo[IR_KEYTAB_SIZE] = { - [ 0x0f ] = KEY_0, - [ 0x03 ] = KEY_1, - [ 0x04 ] = KEY_2, - [ 0x05 ] = KEY_3, - [ 0x07 ] = KEY_4, - [ 0x08 ] = KEY_5, - [ 0x09 ] = KEY_6, - [ 0x0b ] = KEY_7, - [ 0x0c ] = KEY_8, - [ 0x0d ] = KEY_9, - - [ 0x0e ] = KEY_MODE, /* Air/Cable */ - [ 0x11 ] = KEY_VIDEO, /* Video */ - [ 0x15 ] = KEY_AUDIO, /* Audio */ - [ 0x00 ] = KEY_POWER, /* Power */ - [ 0x18 ] = KEY_TUNER, /* AV Source */ - [ 0x02 ] = KEY_ZOOM, /* Fullscreen */ - [ 0x1a ] = KEY_LANGUAGE, /* Stereo */ - [ 0x1b ] = KEY_MUTE, /* Mute */ - [ 0x14 ] = KEY_VOLUMEUP, /* Volume + */ - [ 0x17 ] = KEY_VOLUMEDOWN, /* Volume - */ - [ 0x12 ] = KEY_CHANNELUP, /* Channel + */ - [ 0x13 ] = KEY_CHANNELDOWN, /* Channel - */ - [ 0x06 ] = KEY_AGAIN, /* Recall */ - [ 0x10 ] = KEY_ENTER, /* Enter */ - - [ 0x19 ] = KEY_BACK, /* Rewind ( <<< ) */ - [ 0x1f ] = KEY_FORWARD, /* Forward ( >>> ) */ - [ 0x0a ] = KEY_ANGLE, /* (no label, may be used as the PAUSE button) */ + [0x0f] = KEY_0, + [0x03] = KEY_1, + [0x04] = KEY_2, + [0x05] = KEY_3, + [0x07] = KEY_4, + [0x08] = KEY_5, + [0x09] = KEY_6, + [0x0b] = KEY_7, + [0x0c] = KEY_8, + [0x0d] = KEY_9, + + [0x0e] = KEY_MODE, /* Air/Cable */ + [0x11] = KEY_VIDEO, /* Video */ + [0x15] = KEY_AUDIO, /* Audio */ + [0x00] = KEY_POWER, /* Power */ + [0x18] = KEY_TUNER, /* AV Source */ + [0x02] = KEY_ZOOM, /* Fullscreen */ + [0x1a] = KEY_LANGUAGE, /* Stereo */ + [0x1b] = KEY_MUTE, /* Mute */ + [0x14] = KEY_VOLUMEUP, /* Volume + */ + [0x17] = KEY_VOLUMEDOWN, /* Volume - */ + [0x12] = KEY_CHANNELUP, /* Channel + */ + [0x13] = KEY_CHANNELDOWN, /* Channel - */ + [0x06] = KEY_AGAIN, /* Recall */ + [0x10] = KEY_ENTER, /* Enter */ + + [0x19] = KEY_BACK, /* Rewind ( <<< ) */ + [0x1f] = KEY_FORWARD, /* Forward ( >>> ) */ + [0x0a] = KEY_ANGLE, /* (no label, may be used as the PAUSE button) */ }; EXPORT_SYMBOL_GPL(ir_codes_flyvideo); IR_KEYTAB_TYPE ir_codes_flydvb[IR_KEYTAB_SIZE] = { - [ 0x01 ] = KEY_ZOOM, /* Full Screen */ - [ 0x00 ] = KEY_POWER, /* Power */ - - [ 0x03 ] = KEY_1, - [ 0x04 ] = KEY_2, - [ 0x05 ] = KEY_3, - [ 0x07 ] = KEY_4, - [ 0x08 ] = KEY_5, - [ 0x09 ] = KEY_6, - [ 0x0b ] = KEY_7, - [ 0x0c ] = KEY_8, - [ 0x0d ] = KEY_9, - [ 0x06 ] = KEY_AGAIN, /* Recall */ - [ 0x0f ] = KEY_0, - [ 0x10 ] = KEY_MUTE, /* Mute */ - [ 0x02 ] = KEY_RADIO, /* TV/Radio */ - [ 0x1b ] = KEY_LANGUAGE, /* SAP (Second Audio Program) */ - - [ 0x14 ] = KEY_VOLUMEUP, /* VOL+ */ - [ 0x17 ] = KEY_VOLUMEDOWN, /* VOL- */ - [ 0x12 ] = KEY_CHANNELUP, /* CH+ */ - [ 0x13 ] = KEY_CHANNELDOWN, /* CH- */ - [ 0x1d ] = KEY_ENTER, /* Enter */ - - [ 0x1a ] = KEY_MODE, /* PIP */ - [ 0x18 ] = KEY_TUNER, /* Source */ - - [ 0x1e ] = KEY_RECORD, /* Record/Pause */ - [ 0x15 ] = KEY_ANGLE, /* Swap (no label on key) */ - [ 0x1c ] = KEY_PAUSE, /* Timeshift/Pause */ - [ 0x19 ] = KEY_BACK, /* Rewind << */ - [ 0x0a ] = KEY_PLAYPAUSE, /* Play/Pause */ - [ 0x1f ] = KEY_FORWARD, /* Forward >> */ - [ 0x16 ] = KEY_PREVIOUS, /* Back |<< */ - [ 0x11 ] = KEY_STOP, /* Stop */ - [ 0x0e ] = KEY_NEXT, /* End >>| */ + [0x01] = KEY_ZOOM, /* Full Screen */ + [0x00] = KEY_POWER, /* Power */ + + [0x03] = KEY_1, + [0x04] = KEY_2, + [0x05] = KEY_3, + [0x07] = KEY_4, + [0x08] = KEY_5, + [0x09] = KEY_6, + [0x0b] = KEY_7, + [0x0c] = KEY_8, + [0x0d] = KEY_9, + [0x06] = KEY_AGAIN, /* Recall */ + [0x0f] = KEY_0, + [0x10] = KEY_MUTE, /* Mute */ + [0x02] = KEY_RADIO, /* TV/Radio */ + [0x1b] = KEY_LANGUAGE, /* SAP (Second Audio Program) */ + + [0x14] = KEY_VOLUMEUP, /* VOL+ */ + [0x17] = KEY_VOLUMEDOWN, /* VOL- */ + [0x12] = KEY_CHANNELUP, /* CH+ */ + [0x13] = KEY_CHANNELDOWN, /* CH- */ + [0x1d] = KEY_ENTER, /* Enter */ + + [0x1a] = KEY_MODE, /* PIP */ + [0x18] = KEY_TUNER, /* Source */ + + [0x1e] = KEY_RECORD, /* Record/Pause */ + [0x15] = KEY_ANGLE, /* Swap (no label on key) */ + [0x1c] = KEY_PAUSE, /* Timeshift/Pause */ + [0x19] = KEY_BACK, /* Rewind << */ + [0x0a] = KEY_PLAYPAUSE, /* Play/Pause */ + [0x1f] = KEY_FORWARD, /* Forward >> */ + [0x16] = KEY_PREVIOUS, /* Back |<< */ + [0x11] = KEY_STOP, /* Stop */ + [0x0e] = KEY_NEXT, /* End >>| */ }; EXPORT_SYMBOL_GPL(ir_codes_flydvb); IR_KEYTAB_TYPE ir_codes_cinergy[IR_KEYTAB_SIZE] = { - [ 0x00 ] = KEY_0, - [ 0x01 ] = KEY_1, - [ 0x02 ] = KEY_2, - [ 0x03 ] = KEY_3, - [ 0x04 ] = KEY_4, - [ 0x05 ] = KEY_5, - [ 0x06 ] = KEY_6, - [ 0x07 ] = KEY_7, - [ 0x08 ] = KEY_8, - [ 0x09 ] = KEY_9, - - [ 0x0a ] = KEY_POWER, - [ 0x0b ] = KEY_PROG1, /* app */ - [ 0x0c ] = KEY_ZOOM, /* zoom/fullscreen */ - [ 0x0d ] = KEY_CHANNELUP, /* channel */ - [ 0x0e ] = KEY_CHANNELDOWN, /* channel- */ - [ 0x0f ] = KEY_VOLUMEUP, - [ 0x10 ] = KEY_VOLUMEDOWN, - [ 0x11 ] = KEY_TUNER, /* AV */ - [ 0x12 ] = KEY_NUMLOCK, /* -/-- */ - [ 0x13 ] = KEY_AUDIO, /* audio */ - [ 0x14 ] = KEY_MUTE, - [ 0x15 ] = KEY_UP, - [ 0x16 ] = KEY_DOWN, - [ 0x17 ] = KEY_LEFT, - [ 0x18 ] = KEY_RIGHT, - [ 0x19 ] = BTN_LEFT, - [ 0x1a ] = BTN_RIGHT, - [ 0x1b ] = KEY_WWW, /* text */ - [ 0x1c ] = KEY_REWIND, - [ 0x1d ] = KEY_FORWARD, - [ 0x1e ] = KEY_RECORD, - [ 0x1f ] = KEY_PLAY, - [ 0x20 ] = KEY_PREVIOUSSONG, - [ 0x21 ] = KEY_NEXTSONG, - [ 0x22 ] = KEY_PAUSE, - [ 0x23 ] = KEY_STOP, + [0x00] = KEY_0, + [0x01] = KEY_1, + [0x02] = KEY_2, + [0x03] = KEY_3, + [0x04] = KEY_4, + [0x05] = KEY_5, + [0x06] = KEY_6, + [0x07] = KEY_7, + [0x08] = KEY_8, + [0x09] = KEY_9, + + [0x0a] = KEY_POWER, + [0x0b] = KEY_PROG1, /* app */ + [0x0c] = KEY_ZOOM, /* zoom/fullscreen */ + [0x0d] = KEY_CHANNELUP, /* channel */ + [0x0e] = KEY_CHANNELDOWN, /* channel- */ + [0x0f] = KEY_VOLUMEUP, + [0x10] = KEY_VOLUMEDOWN, + [0x11] = KEY_TUNER, /* AV */ + [0x12] = KEY_NUMLOCK, /* -/-- */ + [0x13] = KEY_AUDIO, /* audio */ + [0x14] = KEY_MUTE, + [0x15] = KEY_UP, + [0x16] = KEY_DOWN, + [0x17] = KEY_LEFT, + [0x18] = KEY_RIGHT, + [0x19] = BTN_LEFT, + [0x1a] = BTN_RIGHT, + [0x1b] = KEY_WWW, /* text */ + [0x1c] = KEY_REWIND, + [0x1d] = KEY_FORWARD, + [0x1e] = KEY_RECORD, + [0x1f] = KEY_PLAY, + [0x20] = KEY_PREVIOUSSONG, + [0x21] = KEY_NEXTSONG, + [0x22] = KEY_PAUSE, + [0x23] = KEY_STOP, }; EXPORT_SYMBOL_GPL(ir_codes_cinergy); @@ -1070,165 +1070,165 @@ EXPORT_SYMBOL_GPL(ir_codes_cinergy); /* Alfons Geser * updates from Job D. R. Borges */ IR_KEYTAB_TYPE ir_codes_eztv[IR_KEYTAB_SIZE] = { - [ 0x12 ] = KEY_POWER, - [ 0x01 ] = KEY_TV, /* DVR */ - [ 0x15 ] = KEY_DVD, /* DVD */ - [ 0x17 ] = KEY_AUDIO, /* music */ + [0x12] = KEY_POWER, + [0x01] = KEY_TV, /* DVR */ + [0x15] = KEY_DVD, /* DVD */ + [0x17] = KEY_AUDIO, /* music */ /* DVR mode / DVD mode / music mode */ - [ 0x1b ] = KEY_MUTE, /* mute */ - [ 0x02 ] = KEY_LANGUAGE, /* MTS/SAP / audio / autoseek */ - [ 0x1e ] = KEY_SUBTITLE, /* closed captioning / subtitle / seek */ - [ 0x16 ] = KEY_ZOOM, /* full screen */ - [ 0x1c ] = KEY_VIDEO, /* video source / eject / delall */ - [ 0x1d ] = KEY_RESTART, /* playback / angle / del */ - [ 0x2f ] = KEY_SEARCH, /* scan / menu / playlist */ - [ 0x30 ] = KEY_CHANNEL, /* CH surfing / bookmark / memo */ - - [ 0x31 ] = KEY_HELP, /* help */ - [ 0x32 ] = KEY_MODE, /* num/memo */ - [ 0x33 ] = KEY_ESC, /* cancel */ - - [ 0x0c ] = KEY_UP, /* up */ - [ 0x10 ] = KEY_DOWN, /* down */ - [ 0x08 ] = KEY_LEFT, /* left */ - [ 0x04 ] = KEY_RIGHT, /* right */ - [ 0x03 ] = KEY_SELECT, /* select */ - - [ 0x1f ] = KEY_REWIND, /* rewind */ - [ 0x20 ] = KEY_PLAYPAUSE, /* play/pause */ - [ 0x29 ] = KEY_FORWARD, /* forward */ - [ 0x14 ] = KEY_AGAIN, /* repeat */ - [ 0x2b ] = KEY_RECORD, /* recording */ - [ 0x2c ] = KEY_STOP, /* stop */ - [ 0x2d ] = KEY_PLAY, /* play */ - [ 0x2e ] = KEY_SHUFFLE, /* snapshot / shuffle */ - - [ 0x00 ] = KEY_0, - [ 0x05 ] = KEY_1, - [ 0x06 ] = KEY_2, - [ 0x07 ] = KEY_3, - [ 0x09 ] = KEY_4, - [ 0x0a ] = KEY_5, - [ 0x0b ] = KEY_6, - [ 0x0d ] = KEY_7, - [ 0x0e ] = KEY_8, - [ 0x0f ] = KEY_9, - - [ 0x2a ] = KEY_VOLUMEUP, - [ 0x11 ] = KEY_VOLUMEDOWN, - [ 0x18 ] = KEY_CHANNELUP, /* CH.tracking up */ - [ 0x19 ] = KEY_CHANNELDOWN, /* CH.tracking down */ - - [ 0x13 ] = KEY_ENTER, /* enter */ - [ 0x21 ] = KEY_DOT, /* . (decimal dot) */ + [0x1b] = KEY_MUTE, /* mute */ + [0x02] = KEY_LANGUAGE, /* MTS/SAP / audio / autoseek */ + [0x1e] = KEY_SUBTITLE, /* closed captioning / subtitle / seek */ + [0x16] = KEY_ZOOM, /* full screen */ + [0x1c] = KEY_VIDEO, /* video source / eject / delall */ + [0x1d] = KEY_RESTART, /* playback / angle / del */ + [0x2f] = KEY_SEARCH, /* scan / menu / playlist */ + [0x30] = KEY_CHANNEL, /* CH surfing / bookmark / memo */ + + [0x31] = KEY_HELP, /* help */ + [0x32] = KEY_MODE, /* num/memo */ + [0x33] = KEY_ESC, /* cancel */ + + [0x0c] = KEY_UP, /* up */ + [0x10] = KEY_DOWN, /* down */ + [0x08] = KEY_LEFT, /* left */ + [0x04] = KEY_RIGHT, /* right */ + [0x03] = KEY_SELECT, /* select */ + + [0x1f] = KEY_REWIND, /* rewind */ + [0x20] = KEY_PLAYPAUSE, /* play/pause */ + [0x29] = KEY_FORWARD, /* forward */ + [0x14] = KEY_AGAIN, /* repeat */ + [0x2b] = KEY_RECORD, /* recording */ + [0x2c] = KEY_STOP, /* stop */ + [0x2d] = KEY_PLAY, /* play */ + [0x2e] = KEY_SHUFFLE, /* snapshot / shuffle */ + + [0x00] = KEY_0, + [0x05] = KEY_1, + [0x06] = KEY_2, + [0x07] = KEY_3, + [0x09] = KEY_4, + [0x0a] = KEY_5, + [0x0b] = KEY_6, + [0x0d] = KEY_7, + [0x0e] = KEY_8, + [0x0f] = KEY_9, + + [0x2a] = KEY_VOLUMEUP, + [0x11] = KEY_VOLUMEDOWN, + [0x18] = KEY_CHANNELUP, /* CH.tracking up */ + [0x19] = KEY_CHANNELDOWN, /* CH.tracking down */ + + [0x13] = KEY_ENTER, /* enter */ + [0x21] = KEY_DOT, /* . (decimal dot) */ }; EXPORT_SYMBOL_GPL(ir_codes_eztv); /* Alex Hermann */ IR_KEYTAB_TYPE ir_codes_avermedia[IR_KEYTAB_SIZE] = { - [ 0x28 ] = KEY_1, - [ 0x18 ] = KEY_2, - [ 0x38 ] = KEY_3, - [ 0x24 ] = KEY_4, - [ 0x14 ] = KEY_5, - [ 0x34 ] = KEY_6, - [ 0x2c ] = KEY_7, - [ 0x1c ] = KEY_8, - [ 0x3c ] = KEY_9, - [ 0x22 ] = KEY_0, - - [ 0x20 ] = KEY_TV, /* TV/FM */ - [ 0x10 ] = KEY_CD, /* CD */ - [ 0x30 ] = KEY_TEXT, /* TELETEXT */ - [ 0x00 ] = KEY_POWER, /* POWER */ - - [ 0x08 ] = KEY_VIDEO, /* VIDEO */ - [ 0x04 ] = KEY_AUDIO, /* AUDIO */ - [ 0x0c ] = KEY_ZOOM, /* FULL SCREEN */ - - [ 0x12 ] = KEY_SUBTITLE, /* DISPLAY */ - [ 0x32 ] = KEY_REWIND, /* LOOP */ - [ 0x02 ] = KEY_PRINT, /* PREVIEW */ - - [ 0x2a ] = KEY_SEARCH, /* AUTOSCAN */ - [ 0x1a ] = KEY_SLEEP, /* FREEZE */ - [ 0x3a ] = KEY_SHUFFLE, /* SNAPSHOT */ - [ 0x0a ] = KEY_MUTE, /* MUTE */ - - [ 0x26 ] = KEY_RECORD, /* RECORD */ - [ 0x16 ] = KEY_PAUSE, /* PAUSE */ - [ 0x36 ] = KEY_STOP, /* STOP */ - [ 0x06 ] = KEY_PLAY, /* PLAY */ - - [ 0x2e ] = KEY_RED, /* RED */ - [ 0x21 ] = KEY_GREEN, /* GREEN */ - [ 0x0e ] = KEY_YELLOW, /* YELLOW */ - [ 0x01 ] = KEY_BLUE, /* BLUE */ - - [ 0x1e ] = KEY_VOLUMEDOWN, /* VOLUME- */ - [ 0x3e ] = KEY_VOLUMEUP, /* VOLUME+ */ - [ 0x11 ] = KEY_CHANNELDOWN, /* CHANNEL/PAGE- */ - [ 0x31 ] = KEY_CHANNELUP /* CHANNEL/PAGE+ */ + [0x28] = KEY_1, + [0x18] = KEY_2, + [0x38] = KEY_3, + [0x24] = KEY_4, + [0x14] = KEY_5, + [0x34] = KEY_6, + [0x2c] = KEY_7, + [0x1c] = KEY_8, + [0x3c] = KEY_9, + [0x22] = KEY_0, + + [0x20] = KEY_TV, /* TV/FM */ + [0x10] = KEY_CD, /* CD */ + [0x30] = KEY_TEXT, /* TELETEXT */ + [0x00] = KEY_POWER, /* POWER */ + + [0x08] = KEY_VIDEO, /* VIDEO */ + [0x04] = KEY_AUDIO, /* AUDIO */ + [0x0c] = KEY_ZOOM, /* FULL SCREEN */ + + [0x12] = KEY_SUBTITLE, /* DISPLAY */ + [0x32] = KEY_REWIND, /* LOOP */ + [0x02] = KEY_PRINT, /* PREVIEW */ + + [0x2a] = KEY_SEARCH, /* AUTOSCAN */ + [0x1a] = KEY_SLEEP, /* FREEZE */ + [0x3a] = KEY_SHUFFLE, /* SNAPSHOT */ + [0x0a] = KEY_MUTE, /* MUTE */ + + [0x26] = KEY_RECORD, /* RECORD */ + [0x16] = KEY_PAUSE, /* PAUSE */ + [0x36] = KEY_STOP, /* STOP */ + [0x06] = KEY_PLAY, /* PLAY */ + + [0x2e] = KEY_RED, /* RED */ + [0x21] = KEY_GREEN, /* GREEN */ + [0x0e] = KEY_YELLOW, /* YELLOW */ + [0x01] = KEY_BLUE, /* BLUE */ + + [0x1e] = KEY_VOLUMEDOWN, /* VOLUME- */ + [0x3e] = KEY_VOLUMEUP, /* VOLUME+ */ + [0x11] = KEY_CHANNELDOWN, /* CHANNEL/PAGE- */ + [0x31] = KEY_CHANNELUP /* CHANNEL/PAGE+ */ }; EXPORT_SYMBOL_GPL(ir_codes_avermedia); IR_KEYTAB_TYPE ir_codes_videomate_tv_pvr[IR_KEYTAB_SIZE] = { - [ 0x14 ] = KEY_MUTE, - [ 0x24 ] = KEY_ZOOM, - - [ 0x01 ] = KEY_DVD, - [ 0x23 ] = KEY_RADIO, - [ 0x00 ] = KEY_TV, - - [ 0x0a ] = KEY_REWIND, - [ 0x08 ] = KEY_PLAYPAUSE, - [ 0x0f ] = KEY_FORWARD, - - [ 0x02 ] = KEY_PREVIOUS, - [ 0x07 ] = KEY_STOP, - [ 0x06 ] = KEY_NEXT, - - [ 0x0c ] = KEY_UP, - [ 0x0e ] = KEY_DOWN, - [ 0x0b ] = KEY_LEFT, - [ 0x0d ] = KEY_RIGHT, - [ 0x11 ] = KEY_OK, - - [ 0x03 ] = KEY_MENU, - [ 0x09 ] = KEY_SETUP, - [ 0x05 ] = KEY_VIDEO, - [ 0x22 ] = KEY_CHANNEL, - - [ 0x12 ] = KEY_VOLUMEUP, - [ 0x15 ] = KEY_VOLUMEDOWN, - [ 0x10 ] = KEY_CHANNELUP, - [ 0x13 ] = KEY_CHANNELDOWN, - - [ 0x04 ] = KEY_RECORD, - - [ 0x16 ] = KEY_1, - [ 0x17 ] = KEY_2, - [ 0x18 ] = KEY_3, - [ 0x19 ] = KEY_4, - [ 0x1a ] = KEY_5, - [ 0x1b ] = KEY_6, - [ 0x1c ] = KEY_7, - [ 0x1d ] = KEY_8, - [ 0x1e ] = KEY_9, - [ 0x1f ] = KEY_0, - - [ 0x20 ] = KEY_LANGUAGE, - [ 0x21 ] = KEY_SLEEP, + [0x14] = KEY_MUTE, + [0x24] = KEY_ZOOM, + + [0x01] = KEY_DVD, + [0x23] = KEY_RADIO, + [0x00] = KEY_TV, + + [0x0a] = KEY_REWIND, + [0x08] = KEY_PLAYPAUSE, + [0x0f] = KEY_FORWARD, + + [0x02] = KEY_PREVIOUS, + [0x07] = KEY_STOP, + [0x06] = KEY_NEXT, + + [0x0c] = KEY_UP, + [0x0e] = KEY_DOWN, + [0x0b] = KEY_LEFT, + [0x0d] = KEY_RIGHT, + [0x11] = KEY_OK, + + [0x03] = KEY_MENU, + [0x09] = KEY_SETUP, + [0x05] = KEY_VIDEO, + [0x22] = KEY_CHANNEL, + + [0x12] = KEY_VOLUMEUP, + [0x15] = KEY_VOLUMEDOWN, + [0x10] = KEY_CHANNELUP, + [0x13] = KEY_CHANNELDOWN, + + [0x04] = KEY_RECORD, + + [0x16] = KEY_1, + [0x17] = KEY_2, + [0x18] = KEY_3, + [0x19] = KEY_4, + [0x1a] = KEY_5, + [0x1b] = KEY_6, + [0x1c] = KEY_7, + [0x1d] = KEY_8, + [0x1e] = KEY_9, + [0x1f] = KEY_0, + + [0x20] = KEY_LANGUAGE, + [0x21] = KEY_SLEEP, }; EXPORT_SYMBOL_GPL(ir_codes_videomate_tv_pvr); /* Michael Tokarev http://www.corpit.ru/mjt/beholdTV/remote_control.jpg - keytable is used by MANLI MTV00[ 0x0c ] and BeholdTV 40[13] at + keytable is used by MANLI MTV00[0x0c] and BeholdTV 40[13] at least, and probably other cards too. The "ascii-art picture" below (in comments, first row is the keycode in hex, and subsequent row(s) shows @@ -1241,8 +1241,8 @@ IR_KEYTAB_TYPE ir_codes_manli[IR_KEYTAB_SIZE] = { * FUNCTION POWER * * FM (|) * * */ - [ 0x1c ] = KEY_RADIO, /*XXX*/ - [ 0x12 ] = KEY_POWER, + [0x1c] = KEY_RADIO, /*XXX*/ + [0x12] = KEY_POWER, /* 0x01 0x02 0x03 * * 1 2 3 * @@ -1253,29 +1253,29 @@ IR_KEYTAB_TYPE ir_codes_manli[IR_KEYTAB_SIZE] = { * 0x07 0x08 0x09 * * 7 8 9 * * */ - [ 0x01 ] = KEY_1, - [ 0x02 ] = KEY_2, - [ 0x03 ] = KEY_3, - [ 0x04 ] = KEY_4, - [ 0x05 ] = KEY_5, - [ 0x06 ] = KEY_6, - [ 0x07 ] = KEY_7, - [ 0x08 ] = KEY_8, - [ 0x09 ] = KEY_9, + [0x01] = KEY_1, + [0x02] = KEY_2, + [0x03] = KEY_3, + [0x04] = KEY_4, + [0x05] = KEY_5, + [0x06] = KEY_6, + [0x07] = KEY_7, + [0x08] = KEY_8, + [0x09] = KEY_9, /* 0x0a 0x00 0x17 * * RECALL 0 +100 * * PLUS * * */ - [ 0x0a ] = KEY_AGAIN, /*XXX KEY_REWIND? */ - [ 0x00 ] = KEY_0, - [ 0x17 ] = KEY_DIGITS, /*XXX*/ + [0x0a] = KEY_AGAIN, /*XXX KEY_REWIND? */ + [0x00] = KEY_0, + [0x17] = KEY_DIGITS, /*XXX*/ /* 0x14 0x10 * * MENU INFO * * OSD */ - [ 0x14 ] = KEY_MENU, - [ 0x10 ] = KEY_INFO, + [0x14] = KEY_MENU, + [0x10] = KEY_INFO, /* 0x0b * * Up * @@ -1286,18 +1286,18 @@ IR_KEYTAB_TYPE ir_codes_manli[IR_KEYTAB_SIZE] = { * 0x015 * * Down * * */ - [ 0x0b ] = KEY_UP, /*XXX KEY_SCROLLUP? */ - [ 0x18 ] = KEY_LEFT, /*XXX KEY_BACK? */ - [ 0x16 ] = KEY_OK, /*XXX KEY_SELECT? KEY_ENTER? */ - [ 0x0c ] = KEY_RIGHT, /*XXX KEY_FORWARD? */ - [ 0x15 ] = KEY_DOWN, /*XXX KEY_SCROLLDOWN? */ + [0x0b] = KEY_UP, /*XXX KEY_SCROLLUP? */ + [0x18] = KEY_LEFT, /*XXX KEY_BACK? */ + [0x16] = KEY_OK, /*XXX KEY_SELECT? KEY_ENTER? */ + [0x0c] = KEY_RIGHT, /*XXX KEY_FORWARD? */ + [0x15] = KEY_DOWN, /*XXX KEY_SCROLLDOWN? */ /* 0x11 0x0d * * TV/AV MODE * * SOURCE STEREO * * */ - [ 0x11 ] = KEY_TV, /*XXX*/ - [ 0x0d ] = KEY_MODE, /*XXX there's no KEY_STEREO */ + [0x11] = KEY_TV, /*XXX*/ + [0x0d] = KEY_MODE, /*XXX there's no KEY_STEREO */ /* 0x0f 0x1b 0x1a * * AUDIO Vol+ Chan+ * @@ -1306,18 +1306,18 @@ IR_KEYTAB_TYPE ir_codes_manli[IR_KEYTAB_SIZE] = { * 0x0e 0x1f 0x1e * * SLEEP Vol- Chan- * * */ - [ 0x0f ] = KEY_AUDIO, - [ 0x1b ] = KEY_VOLUMEUP, - [ 0x1a ] = KEY_CHANNELUP, - [ 0x0e ] = KEY_SLEEP, /*XXX maybe KEY_PAUSE */ - [ 0x1f ] = KEY_VOLUMEDOWN, - [ 0x1e ] = KEY_CHANNELDOWN, + [0x0f] = KEY_AUDIO, + [0x1b] = KEY_VOLUMEUP, + [0x1a] = KEY_CHANNELUP, + [0x0e] = KEY_SLEEP, /*XXX maybe KEY_PAUSE */ + [0x1f] = KEY_VOLUMEDOWN, + [0x1e] = KEY_CHANNELDOWN, /* 0x13 0x19 * * MUTE SNAPSHOT* * */ - [ 0x13 ] = KEY_MUTE, - [ 0x19 ] = KEY_RECORD, /*XXX*/ + [0x13] = KEY_MUTE, + [0x19] = KEY_RECORD, /*XXX*/ /* 0x1d unused ? */ }; @@ -1327,91 +1327,91 @@ EXPORT_SYMBOL_GPL(ir_codes_manli); /* Mike Baikov */ IR_KEYTAB_TYPE ir_codes_gotview7135[IR_KEYTAB_SIZE] = { - [ 0x11 ] = KEY_POWER, - [ 0x35 ] = KEY_TV, - [ 0x1b ] = KEY_0, - [ 0x29 ] = KEY_1, - [ 0x19 ] = KEY_2, - [ 0x39 ] = KEY_3, - [ 0x1f ] = KEY_4, - [ 0x2c ] = KEY_5, - [ 0x21 ] = KEY_6, - [ 0x24 ] = KEY_7, - [ 0x18 ] = KEY_8, - [ 0x2b ] = KEY_9, - [ 0x3b ] = KEY_AGAIN, /* LOOP */ - [ 0x06 ] = KEY_AUDIO, - [ 0x31 ] = KEY_PRINT, /* PREVIEW */ - [ 0x3e ] = KEY_VIDEO, - [ 0x10 ] = KEY_CHANNELUP, - [ 0x20 ] = KEY_CHANNELDOWN, - [ 0x0c ] = KEY_VOLUMEDOWN, - [ 0x28 ] = KEY_VOLUMEUP, - [ 0x08 ] = KEY_MUTE, - [ 0x26 ] = KEY_SEARCH, /*SCAN*/ - [ 0x3f ] = KEY_SHUFFLE, /* SNAPSHOT */ - [ 0x12 ] = KEY_RECORD, - [ 0x32 ] = KEY_STOP, - [ 0x3c ] = KEY_PLAY, - [ 0x1d ] = KEY_REWIND, - [ 0x2d ] = KEY_PAUSE, - [ 0x0d ] = KEY_FORWARD, - [ 0x05 ] = KEY_ZOOM, /*FULL*/ - - [ 0x2a ] = KEY_F21, /* LIVE TIMESHIFT */ - [ 0x0e ] = KEY_F22, /* MIN TIMESHIFT */ - [ 0x1e ] = KEY_F23, /* TIMESHIFT */ - [ 0x38 ] = KEY_F24, /* NORMAL TIMESHIFT */ + [0x11] = KEY_POWER, + [0x35] = KEY_TV, + [0x1b] = KEY_0, + [0x29] = KEY_1, + [0x19] = KEY_2, + [0x39] = KEY_3, + [0x1f] = KEY_4, + [0x2c] = KEY_5, + [0x21] = KEY_6, + [0x24] = KEY_7, + [0x18] = KEY_8, + [0x2b] = KEY_9, + [0x3b] = KEY_AGAIN, /* LOOP */ + [0x06] = KEY_AUDIO, + [0x31] = KEY_PRINT, /* PREVIEW */ + [0x3e] = KEY_VIDEO, + [0x10] = KEY_CHANNELUP, + [0x20] = KEY_CHANNELDOWN, + [0x0c] = KEY_VOLUMEDOWN, + [0x28] = KEY_VOLUMEUP, + [0x08] = KEY_MUTE, + [0x26] = KEY_SEARCH, /*SCAN*/ + [0x3f] = KEY_SHUFFLE, /* SNAPSHOT */ + [0x12] = KEY_RECORD, + [0x32] = KEY_STOP, + [0x3c] = KEY_PLAY, + [0x1d] = KEY_REWIND, + [0x2d] = KEY_PAUSE, + [0x0d] = KEY_FORWARD, + [0x05] = KEY_ZOOM, /*FULL*/ + + [0x2a] = KEY_F21, /* LIVE TIMESHIFT */ + [0x0e] = KEY_F22, /* MIN TIMESHIFT */ + [0x1e] = KEY_F23, /* TIMESHIFT */ + [0x38] = KEY_F24, /* NORMAL TIMESHIFT */ }; EXPORT_SYMBOL_GPL(ir_codes_gotview7135); IR_KEYTAB_TYPE ir_codes_purpletv[IR_KEYTAB_SIZE] = { - [ 0x03 ] = KEY_POWER, - [ 0x6f ] = KEY_MUTE, - [ 0x10 ] = KEY_BACKSPACE, /* Recall */ - - [ 0x11 ] = KEY_0, - [ 0x04 ] = KEY_1, - [ 0x05 ] = KEY_2, - [ 0x06 ] = KEY_3, - [ 0x08 ] = KEY_4, - [ 0x09 ] = KEY_5, - [ 0x0a ] = KEY_6, - [ 0x0c ] = KEY_7, - [ 0x0d ] = KEY_8, - [ 0x0e ] = KEY_9, - [ 0x12 ] = KEY_DOT, /* 100+ */ - - [ 0x07 ] = KEY_VOLUMEUP, - [ 0x0b ] = KEY_VOLUMEDOWN, - [ 0x1a ] = KEY_KPPLUS, - [ 0x18 ] = KEY_KPMINUS, - [ 0x15 ] = KEY_UP, - [ 0x1d ] = KEY_DOWN, - [ 0x0f ] = KEY_CHANNELUP, - [ 0x13 ] = KEY_CHANNELDOWN, - [ 0x48 ] = KEY_ZOOM, - - [ 0x1b ] = KEY_VIDEO, /* Video source */ + [0x03] = KEY_POWER, + [0x6f] = KEY_MUTE, + [0x10] = KEY_BACKSPACE, /* Recall */ + + [0x11] = KEY_0, + [0x04] = KEY_1, + [0x05] = KEY_2, + [0x06] = KEY_3, + [0x08] = KEY_4, + [0x09] = KEY_5, + [0x0a] = KEY_6, + [0x0c] = KEY_7, + [0x0d] = KEY_8, + [0x0e] = KEY_9, + [0x12] = KEY_DOT, /* 100+ */ + + [0x07] = KEY_VOLUMEUP, + [0x0b] = KEY_VOLUMEDOWN, + [0x1a] = KEY_KPPLUS, + [0x18] = KEY_KPMINUS, + [0x15] = KEY_UP, + [0x1d] = KEY_DOWN, + [0x0f] = KEY_CHANNELUP, + [0x13] = KEY_CHANNELDOWN, + [0x48] = KEY_ZOOM, + + [0x1b] = KEY_VIDEO, /* Video source */ #if 0 - [ 0x1f ] = KEY_S, /* Snapshot */ + [0x1f] = KEY_S, /* Snapshot */ #endif - [ 0x49 ] = KEY_LANGUAGE, /* MTS Select */ - [ 0x19 ] = KEY_SEARCH, /* Auto Scan */ + [0x49] = KEY_LANGUAGE, /* MTS Select */ + [0x19] = KEY_SEARCH, /* Auto Scan */ - [ 0x4b ] = KEY_RECORD, - [ 0x46 ] = KEY_PLAY, - [ 0x45 ] = KEY_PAUSE, /* Pause */ - [ 0x44 ] = KEY_STOP, + [0x4b] = KEY_RECORD, + [0x46] = KEY_PLAY, + [0x45] = KEY_PAUSE, /* Pause */ + [0x44] = KEY_STOP, #if 0 - [ 0x43 ] = KEY_T, /* Time Shift */ - [ 0x47 ] = KEY_Y, /* Time Shift OFF */ - [ 0x4a ] = KEY_O, /* TOP */ - [ 0x17 ] = KEY_F, /* SURF CH */ + [0x43] = KEY_T, /* Time Shift */ + [0x47] = KEY_Y, /* Time Shift OFF */ + [0x4a] = KEY_O, /* TOP */ + [0x17] = KEY_F, /* SURF CH */ #endif - [ 0x40 ] = KEY_FORWARD, /* Forward ? */ - [ 0x42 ] = KEY_REWIND, /* Backward ? */ + [0x40] = KEY_FORWARD, /* Forward ? */ + [0x42] = KEY_REWIND, /* Backward ? */ }; @@ -1422,35 +1422,35 @@ EXPORT_SYMBOL_GPL(ir_codes_purpletv); Pavel Mihaylov Also for the remote bundled with Kozumi KTV-01C card */ IR_KEYTAB_TYPE ir_codes_pctv_sedna[IR_KEYTAB_SIZE] = { - [ 0x00 ] = KEY_0, - [ 0x01 ] = KEY_1, - [ 0x02 ] = KEY_2, - [ 0x03 ] = KEY_3, - [ 0x04 ] = KEY_4, - [ 0x05 ] = KEY_5, - [ 0x06 ] = KEY_6, - [ 0x07 ] = KEY_7, - [ 0x08 ] = KEY_8, - [ 0x09 ] = KEY_9, - - [ 0x0a ] = KEY_AGAIN, /* Recall */ - [ 0x0b ] = KEY_CHANNELUP, - [ 0x0c ] = KEY_VOLUMEUP, - [ 0x0d ] = KEY_MODE, /* Stereo */ - [ 0x0e ] = KEY_STOP, - [ 0x0f ] = KEY_PREVIOUSSONG, - [ 0x10 ] = KEY_ZOOM, - [ 0x11 ] = KEY_TUNER, /* Source */ - [ 0x12 ] = KEY_POWER, - [ 0x13 ] = KEY_MUTE, - [ 0x15 ] = KEY_CHANNELDOWN, - [ 0x18 ] = KEY_VOLUMEDOWN, - [ 0x19 ] = KEY_SHUFFLE, /* Snapshot */ - [ 0x1a ] = KEY_NEXTSONG, - [ 0x1b ] = KEY_TEXT, /* Time Shift */ - [ 0x1c ] = KEY_RADIO, /* FM Radio */ - [ 0x1d ] = KEY_RECORD, - [ 0x1e ] = KEY_PAUSE, + [0x00] = KEY_0, + [0x01] = KEY_1, + [0x02] = KEY_2, + [0x03] = KEY_3, + [0x04] = KEY_4, + [0x05] = KEY_5, + [0x06] = KEY_6, + [0x07] = KEY_7, + [0x08] = KEY_8, + [0x09] = KEY_9, + + [0x0a] = KEY_AGAIN, /* Recall */ + [0x0b] = KEY_CHANNELUP, + [0x0c] = KEY_VOLUMEUP, + [0x0d] = KEY_MODE, /* Stereo */ + [0x0e] = KEY_STOP, + [0x0f] = KEY_PREVIOUSSONG, + [0x10] = KEY_ZOOM, + [0x11] = KEY_TUNER, /* Source */ + [0x12] = KEY_POWER, + [0x13] = KEY_MUTE, + [0x15] = KEY_CHANNELDOWN, + [0x18] = KEY_VOLUMEDOWN, + [0x19] = KEY_SHUFFLE, /* Snapshot */ + [0x1a] = KEY_NEXTSONG, + [0x1b] = KEY_TEXT, /* Time Shift */ + [0x1c] = KEY_RADIO, /* FM Radio */ + [0x1d] = KEY_RECORD, + [0x1e] = KEY_PAUSE, /* additional codes for Kozumi's remote */ [0x14] = KEY_INFO, /* OSD */ [0x16] = KEY_OK, /* OK */ @@ -1462,41 +1462,41 @@ EXPORT_SYMBOL_GPL(ir_codes_pctv_sedna); /* Mark Phalan */ IR_KEYTAB_TYPE ir_codes_pv951[IR_KEYTAB_SIZE] = { - [ 0x00 ] = KEY_0, - [ 0x01 ] = KEY_1, - [ 0x02 ] = KEY_2, - [ 0x03 ] = KEY_3, - [ 0x04 ] = KEY_4, - [ 0x05 ] = KEY_5, - [ 0x06 ] = KEY_6, - [ 0x07 ] = KEY_7, - [ 0x08 ] = KEY_8, - [ 0x09 ] = KEY_9, - - [ 0x12 ] = KEY_POWER, - [ 0x10 ] = KEY_MUTE, - [ 0x1f ] = KEY_VOLUMEDOWN, - [ 0x1b ] = KEY_VOLUMEUP, - [ 0x1a ] = KEY_CHANNELUP, - [ 0x1e ] = KEY_CHANNELDOWN, - [ 0x0e ] = KEY_PAGEUP, - [ 0x1d ] = KEY_PAGEDOWN, - [ 0x13 ] = KEY_SOUND, - - [ 0x18 ] = KEY_KPPLUSMINUS, /* CH +/- */ - [ 0x16 ] = KEY_SUBTITLE, /* CC */ - [ 0x0d ] = KEY_TEXT, /* TTX */ - [ 0x0b ] = KEY_TV, /* AIR/CBL */ - [ 0x11 ] = KEY_PC, /* PC/TV */ - [ 0x17 ] = KEY_OK, /* CH RTN */ - [ 0x19 ] = KEY_MODE, /* FUNC */ - [ 0x0c ] = KEY_SEARCH, /* AUTOSCAN */ + [0x00] = KEY_0, + [0x01] = KEY_1, + [0x02] = KEY_2, + [0x03] = KEY_3, + [0x04] = KEY_4, + [0x05] = KEY_5, + [0x06] = KEY_6, + [0x07] = KEY_7, + [0x08] = KEY_8, + [0x09] = KEY_9, + + [0x12] = KEY_POWER, + [0x10] = KEY_MUTE, + [0x1f] = KEY_VOLUMEDOWN, + [0x1b] = KEY_VOLUMEUP, + [0x1a] = KEY_CHANNELUP, + [0x1e] = KEY_CHANNELDOWN, + [0x0e] = KEY_PAGEUP, + [0x1d] = KEY_PAGEDOWN, + [0x13] = KEY_SOUND, + + [0x18] = KEY_KPPLUSMINUS, /* CH +/- */ + [0x16] = KEY_SUBTITLE, /* CC */ + [0x0d] = KEY_TEXT, /* TTX */ + [0x0b] = KEY_TV, /* AIR/CBL */ + [0x11] = KEY_PC, /* PC/TV */ + [0x17] = KEY_OK, /* CH RTN */ + [0x19] = KEY_MODE, /* FUNC */ + [0x0c] = KEY_SEARCH, /* AUTOSCAN */ /* Not sure what to do with these ones! */ - [ 0x0f ] = KEY_SELECT, /* SOURCE */ - [ 0x0a ] = KEY_KPPLUS, /* +100 */ - [ 0x14 ] = KEY_EQUAL, /* SYNC */ - [ 0x1c ] = KEY_MEDIA, /* PC/TV */ + [0x0f] = KEY_SELECT, /* SOURCE */ + [0x0a] = KEY_KPPLUS, /* +100 */ + [0x14] = KEY_EQUAL, /* SYNC */ + [0x1c] = KEY_MEDIA, /* PC/TV */ }; EXPORT_SYMBOL_GPL(ir_codes_pv951); @@ -1506,73 +1506,73 @@ EXPORT_SYMBOL_GPL(ir_codes_pv951); /* used by old (black) Hauppauge remotes */ IR_KEYTAB_TYPE ir_codes_rc5_tv[IR_KEYTAB_SIZE] = { /* Keys 0 to 9 */ - [ 0x00 ] = KEY_0, - [ 0x01 ] = KEY_1, - [ 0x02 ] = KEY_2, - [ 0x03 ] = KEY_3, - [ 0x04 ] = KEY_4, - [ 0x05 ] = KEY_5, - [ 0x06 ] = KEY_6, - [ 0x07 ] = KEY_7, - [ 0x08 ] = KEY_8, - [ 0x09 ] = KEY_9, - - [ 0x0b ] = KEY_CHANNEL, /* channel / program (japan: 11) */ - [ 0x0c ] = KEY_POWER, /* standby */ - [ 0x0d ] = KEY_MUTE, /* mute / demute */ - [ 0x0f ] = KEY_TV, /* display */ - [ 0x10 ] = KEY_VOLUMEUP, - [ 0x11 ] = KEY_VOLUMEDOWN, - [ 0x12 ] = KEY_BRIGHTNESSUP, - [ 0x13 ] = KEY_BRIGHTNESSDOWN, - [ 0x1e ] = KEY_SEARCH, /* search + */ - [ 0x20 ] = KEY_CHANNELUP, /* channel / program + */ - [ 0x21 ] = KEY_CHANNELDOWN, /* channel / program - */ - [ 0x22 ] = KEY_CHANNEL, /* alt / channel */ - [ 0x23 ] = KEY_LANGUAGE, /* 1st / 2nd language */ - [ 0x26 ] = KEY_SLEEP, /* sleeptimer */ - [ 0x2e ] = KEY_MENU, /* 2nd controls (USA: menu) */ - [ 0x30 ] = KEY_PAUSE, - [ 0x32 ] = KEY_REWIND, - [ 0x33 ] = KEY_GOTO, - [ 0x35 ] = KEY_PLAY, - [ 0x36 ] = KEY_STOP, - [ 0x37 ] = KEY_RECORD, /* recording */ - [ 0x3c ] = KEY_TEXT, /* teletext submode (Japan: 12) */ - [ 0x3d ] = KEY_SUSPEND, /* system standby */ + [0x00] = KEY_0, + [0x01] = KEY_1, + [0x02] = KEY_2, + [0x03] = KEY_3, + [0x04] = KEY_4, + [0x05] = KEY_5, + [0x06] = KEY_6, + [0x07] = KEY_7, + [0x08] = KEY_8, + [0x09] = KEY_9, + + [0x0b] = KEY_CHANNEL, /* channel / program (japan: 11) */ + [0x0c] = KEY_POWER, /* standby */ + [0x0d] = KEY_MUTE, /* mute / demute */ + [0x0f] = KEY_TV, /* display */ + [0x10] = KEY_VOLUMEUP, + [0x11] = KEY_VOLUMEDOWN, + [0x12] = KEY_BRIGHTNESSUP, + [0x13] = KEY_BRIGHTNESSDOWN, + [0x1e] = KEY_SEARCH, /* search + */ + [0x20] = KEY_CHANNELUP, /* channel / program + */ + [0x21] = KEY_CHANNELDOWN, /* channel / program - */ + [0x22] = KEY_CHANNEL, /* alt / channel */ + [0x23] = KEY_LANGUAGE, /* 1st / 2nd language */ + [0x26] = KEY_SLEEP, /* sleeptimer */ + [0x2e] = KEY_MENU, /* 2nd controls (USA: menu) */ + [0x30] = KEY_PAUSE, + [0x32] = KEY_REWIND, + [0x33] = KEY_GOTO, + [0x35] = KEY_PLAY, + [0x36] = KEY_STOP, + [0x37] = KEY_RECORD, /* recording */ + [0x3c] = KEY_TEXT, /* teletext submode (Japan: 12) */ + [0x3d] = KEY_SUSPEND, /* system standby */ #if 0 /* FIXME */ - [ 0x0a ] = KEY_RESERVED, /* 1/2/3 digits (japan: 10) */ - [ 0x0e ] = KEY_RESERVED, /* P.P. (personal preference) */ - [ 0x14 ] = KEY_RESERVED, /* colour saturation + */ - [ 0x15 ] = KEY_RESERVED, /* colour saturation - */ - [ 0x16 ] = KEY_RESERVED, /* bass + */ - [ 0x17 ] = KEY_RESERVED, /* bass - */ - [ 0x18 ] = KEY_RESERVED, /* treble + */ - [ 0x19 ] = KEY_RESERVED, /* treble - */ - [ 0x1a ] = KEY_RESERVED, /* balance right */ - [ 0x1b ] = KEY_RESERVED, /* balance left */ - [ 0x1c ] = KEY_RESERVED, /* contrast + */ - [ 0x1d ] = KEY_RESERVED, /* contrast - */ - [ 0x1f ] = KEY_RESERVED, /* tint/hue + */ - [ 0x24 ] = KEY_RESERVED, /* spacial stereo on/off */ - [ 0x25 ] = KEY_RESERVED, /* mono / stereo (USA) */ - [ 0x27 ] = KEY_RESERVED, /* tint / hue - */ - [ 0x28 ] = KEY_RESERVED, /* RF switch/PIP select */ - [ 0x29 ] = KEY_RESERVED, /* vote */ - [ 0x2a ] = KEY_RESERVED, /* timed page/channel clck */ - [ 0x2b ] = KEY_RESERVED, /* increment (USA) */ - [ 0x2c ] = KEY_RESERVED, /* decrement (USA) */ - [ 0x2d ] = KEY_RESERVED, /* */ - [ 0x2f ] = KEY_RESERVED, /* PIP shift */ - [ 0x31 ] = KEY_RESERVED, /* erase */ - [ 0x34 ] = KEY_RESERVED, /* wind */ - [ 0x38 ] = KEY_RESERVED, /* external 1 */ - [ 0x39 ] = KEY_RESERVED, /* external 2 */ - [ 0x3a ] = KEY_RESERVED, /* PIP display mode */ - [ 0x3b ] = KEY_RESERVED, /* view data mode / advance */ - [ 0x3e ] = KEY_RESERVED, /* crispener on/off */ - [ 0x3f ] = KEY_RESERVED, /* system select */ + [0x0a] = KEY_RESERVED, /* 1/2/3 digits (japan: 10) */ + [0x0e] = KEY_RESERVED, /* P.P. (personal preference) */ + [0x14] = KEY_RESERVED, /* colour saturation + */ + [0x15] = KEY_RESERVED, /* colour saturation - */ + [0x16] = KEY_RESERVED, /* bass + */ + [0x17] = KEY_RESERVED, /* bass - */ + [0x18] = KEY_RESERVED, /* treble + */ + [0x19] = KEY_RESERVED, /* treble - */ + [0x1a] = KEY_RESERVED, /* balance right */ + [0x1b] = KEY_RESERVED, /* balance left */ + [0x1c] = KEY_RESERVED, /* contrast + */ + [0x1d] = KEY_RESERVED, /* contrast - */ + [0x1f] = KEY_RESERVED, /* tint/hue + */ + [0x24] = KEY_RESERVED, /* spacial stereo on/off */ + [0x25] = KEY_RESERVED, /* mono / stereo (USA) */ + [0x27] = KEY_RESERVED, /* tint / hue - */ + [0x28] = KEY_RESERVED, /* RF switch/PIP select */ + [0x29] = KEY_RESERVED, /* vote */ + [0x2a] = KEY_RESERVED, /* timed page/channel clck */ + [0x2b] = KEY_RESERVED, /* increment (USA) */ + [0x2c] = KEY_RESERVED, /* decrement (USA) */ + [0x2d] = KEY_RESERVED, /* */ + [0x2f] = KEY_RESERVED, /* PIP shift */ + [0x31] = KEY_RESERVED, /* erase */ + [0x34] = KEY_RESERVED, /* wind */ + [0x38] = KEY_RESERVED, /* external 1 */ + [0x39] = KEY_RESERVED, /* external 2 */ + [0x3a] = KEY_RESERVED, /* PIP display mode */ + [0x3b] = KEY_RESERVED, /* view data mode / advance */ + [0x3e] = KEY_RESERVED, /* crispener on/off */ + [0x3f] = KEY_RESERVED, /* system select */ #endif }; @@ -1581,123 +1581,123 @@ EXPORT_SYMBOL_GPL(ir_codes_rc5_tv); /* Table for Leadtek Winfast Remote Controls - used by both bttv and cx88 */ IR_KEYTAB_TYPE ir_codes_winfast[IR_KEYTAB_SIZE] = { /* Keys 0 to 9 */ - [ 0x12 ] = KEY_0, - [ 0x05 ] = KEY_1, - [ 0x06 ] = KEY_2, - [ 0x07 ] = KEY_3, - [ 0x09 ] = KEY_4, - [ 0x0a ] = KEY_5, - [ 0x0b ] = KEY_6, - [ 0x0d ] = KEY_7, - [ 0x0e ] = KEY_8, - [ 0x0f ] = KEY_9, - - [ 0x00 ] = KEY_POWER, - [ 0x1b ] = KEY_AUDIO, /* Audio Source */ - [ 0x02 ] = KEY_TUNER, /* TV/FM, not on Y0400052 */ - [ 0x1e ] = KEY_VIDEO, /* Video Source */ - [ 0x16 ] = KEY_INFO, /* Display information */ - [ 0x04 ] = KEY_VOLUMEUP, - [ 0x08 ] = KEY_VOLUMEDOWN, - [ 0x0c ] = KEY_CHANNELUP, - [ 0x10 ] = KEY_CHANNELDOWN, - [ 0x03 ] = KEY_ZOOM, /* fullscreen */ - [ 0x1f ] = KEY_TEXT, /* closed caption/teletext */ - [ 0x20 ] = KEY_SLEEP, - [ 0x29 ] = KEY_CLEAR, /* boss key */ - [ 0x14 ] = KEY_MUTE, - [ 0x2b ] = KEY_RED, - [ 0x2c ] = KEY_GREEN, - [ 0x2d ] = KEY_YELLOW, - [ 0x2e ] = KEY_BLUE, - [ 0x18 ] = KEY_KPPLUS, /* fine tune + , not on Y040052 */ - [ 0x19 ] = KEY_KPMINUS, /* fine tune - , not on Y040052 */ - [ 0x2a ] = KEY_MEDIA, /* PIP (Picture in picture */ - [ 0x21 ] = KEY_DOT, - [ 0x13 ] = KEY_ENTER, - [ 0x11 ] = KEY_LAST, /* Recall (last channel */ - [ 0x22 ] = KEY_PREVIOUS, - [ 0x23 ] = KEY_PLAYPAUSE, - [ 0x24 ] = KEY_NEXT, - [ 0x25 ] = KEY_ARCHIVE, /* Time Shifting */ - [ 0x26 ] = KEY_STOP, - [ 0x27 ] = KEY_RECORD, - [ 0x28 ] = KEY_SAVE, /* Screenshot */ - [ 0x2f ] = KEY_MENU, - [ 0x30 ] = KEY_CANCEL, - [ 0x31 ] = KEY_CHANNEL, /* Channel Surf */ - [ 0x32 ] = KEY_SUBTITLE, - [ 0x33 ] = KEY_LANGUAGE, - [ 0x34 ] = KEY_REWIND, - [ 0x35 ] = KEY_FASTFORWARD, - [ 0x36 ] = KEY_TV, - [ 0x37 ] = KEY_RADIO, /* FM */ - [ 0x38 ] = KEY_DVD, - - [ 0x3e ] = KEY_F21, /* MCE +VOL, on Y04G0033 */ - [ 0x3a ] = KEY_F22, /* MCE -VOL, on Y04G0033 */ - [ 0x3b ] = KEY_F23, /* MCE +CH, on Y04G0033 */ - [ 0x3f ] = KEY_F24 /* MCE -CH, on Y04G0033 */ + [0x12] = KEY_0, + [0x05] = KEY_1, + [0x06] = KEY_2, + [0x07] = KEY_3, + [0x09] = KEY_4, + [0x0a] = KEY_5, + [0x0b] = KEY_6, + [0x0d] = KEY_7, + [0x0e] = KEY_8, + [0x0f] = KEY_9, + + [0x00] = KEY_POWER, + [0x1b] = KEY_AUDIO, /* Audio Source */ + [0x02] = KEY_TUNER, /* TV/FM, not on Y0400052 */ + [0x1e] = KEY_VIDEO, /* Video Source */ + [0x16] = KEY_INFO, /* Display information */ + [0x04] = KEY_VOLUMEUP, + [0x08] = KEY_VOLUMEDOWN, + [0x0c] = KEY_CHANNELUP, + [0x10] = KEY_CHANNELDOWN, + [0x03] = KEY_ZOOM, /* fullscreen */ + [0x1f] = KEY_TEXT, /* closed caption/teletext */ + [0x20] = KEY_SLEEP, + [0x29] = KEY_CLEAR, /* boss key */ + [0x14] = KEY_MUTE, + [0x2b] = KEY_RED, + [0x2c] = KEY_GREEN, + [0x2d] = KEY_YELLOW, + [0x2e] = KEY_BLUE, + [0x18] = KEY_KPPLUS, /* fine tune + , not on Y040052 */ + [0x19] = KEY_KPMINUS, /* fine tune - , not on Y040052 */ + [0x2a] = KEY_MEDIA, /* PIP (Picture in picture */ + [0x21] = KEY_DOT, + [0x13] = KEY_ENTER, + [0x11] = KEY_LAST, /* Recall (last channel */ + [0x22] = KEY_PREVIOUS, + [0x23] = KEY_PLAYPAUSE, + [0x24] = KEY_NEXT, + [0x25] = KEY_ARCHIVE, /* Time Shifting */ + [0x26] = KEY_STOP, + [0x27] = KEY_RECORD, + [0x28] = KEY_SAVE, /* Screenshot */ + [0x2f] = KEY_MENU, + [0x30] = KEY_CANCEL, + [0x31] = KEY_CHANNEL, /* Channel Surf */ + [0x32] = KEY_SUBTITLE, + [0x33] = KEY_LANGUAGE, + [0x34] = KEY_REWIND, + [0x35] = KEY_FASTFORWARD, + [0x36] = KEY_TV, + [0x37] = KEY_RADIO, /* FM */ + [0x38] = KEY_DVD, + + [0x3e] = KEY_F21, /* MCE +VOL, on Y04G0033 */ + [0x3a] = KEY_F22, /* MCE -VOL, on Y04G0033 */ + [0x3b] = KEY_F23, /* MCE +CH, on Y04G0033 */ + [0x3f] = KEY_F24 /* MCE -CH, on Y04G0033 */ }; EXPORT_SYMBOL_GPL(ir_codes_winfast); IR_KEYTAB_TYPE ir_codes_pinnacle_color[IR_KEYTAB_SIZE] = { - [ 0x59 ] = KEY_MUTE, - [ 0x4a ] = KEY_POWER, - - [ 0x18 ] = KEY_TEXT, - [ 0x26 ] = KEY_TV, - [ 0x3d ] = KEY_PRINT, + [0x59] = KEY_MUTE, + [0x4a] = KEY_POWER, - [ 0x48 ] = KEY_RED, - [ 0x04 ] = KEY_GREEN, - [ 0x11 ] = KEY_YELLOW, - [ 0x00 ] = KEY_BLUE, + [0x18] = KEY_TEXT, + [0x26] = KEY_TV, + [0x3d] = KEY_PRINT, - [ 0x2d ] = KEY_VOLUMEUP, - [ 0x1e ] = KEY_VOLUMEDOWN, + [0x48] = KEY_RED, + [0x04] = KEY_GREEN, + [0x11] = KEY_YELLOW, + [0x00] = KEY_BLUE, - [ 0x49 ] = KEY_MENU, - - [ 0x16 ] = KEY_CHANNELUP, - [ 0x17 ] = KEY_CHANNELDOWN, - - [ 0x20 ] = KEY_UP, - [ 0x21 ] = KEY_DOWN, - [ 0x22 ] = KEY_LEFT, - [ 0x23 ] = KEY_RIGHT, - [ 0x0d ] = KEY_SELECT, - - - - [ 0x08 ] = KEY_BACK, - [ 0x07 ] = KEY_REFRESH, - - [ 0x2f ] = KEY_ZOOM, - [ 0x29 ] = KEY_RECORD, + [0x2d] = KEY_VOLUMEUP, + [0x1e] = KEY_VOLUMEDOWN, - [ 0x4b ] = KEY_PAUSE, - [ 0x4d ] = KEY_REWIND, - [ 0x2e ] = KEY_PLAY, - [ 0x4e ] = KEY_FORWARD, - [ 0x53 ] = KEY_PREVIOUS, - [ 0x4c ] = KEY_STOP, - [ 0x54 ] = KEY_NEXT, + [0x49] = KEY_MENU, - [ 0x69 ] = KEY_0, - [ 0x6a ] = KEY_1, - [ 0x6b ] = KEY_2, - [ 0x6c ] = KEY_3, - [ 0x6d ] = KEY_4, - [ 0x6e ] = KEY_5, - [ 0x6f ] = KEY_6, - [ 0x70 ] = KEY_7, - [ 0x71 ] = KEY_8, - [ 0x72 ] = KEY_9, + [0x16] = KEY_CHANNELUP, + [0x17] = KEY_CHANNELDOWN, - [ 0x74 ] = KEY_CHANNEL, - [ 0x0a ] = KEY_BACKSPACE, + [0x20] = KEY_UP, + [0x21] = KEY_DOWN, + [0x22] = KEY_LEFT, + [0x23] = KEY_RIGHT, + [0x0d] = KEY_SELECT, + + + + [0x08] = KEY_BACK, + [0x07] = KEY_REFRESH, + + [0x2f] = KEY_ZOOM, + [0x29] = KEY_RECORD, + + [0x4b] = KEY_PAUSE, + [0x4d] = KEY_REWIND, + [0x2e] = KEY_PLAY, + [0x4e] = KEY_FORWARD, + [0x53] = KEY_PREVIOUS, + [0x4c] = KEY_STOP, + [0x54] = KEY_NEXT, + + [0x69] = KEY_0, + [0x6a] = KEY_1, + [0x6b] = KEY_2, + [0x6c] = KEY_3, + [0x6d] = KEY_4, + [0x6e] = KEY_5, + [0x6f] = KEY_6, + [0x70] = KEY_7, + [0x71] = KEY_8, + [0x72] = KEY_9, + + [0x74] = KEY_CHANNEL, + [0x0a] = KEY_BACKSPACE, }; EXPORT_SYMBOL_GPL(ir_codes_pinnacle_color); @@ -1707,103 +1707,103 @@ EXPORT_SYMBOL_GPL(ir_codes_pinnacle_color); * almost rc5 coding, but some non-standard keys */ IR_KEYTAB_TYPE ir_codes_hauppauge_new[IR_KEYTAB_SIZE] = { /* Keys 0 to 9 */ - [ 0x00 ] = KEY_0, - [ 0x01 ] = KEY_1, - [ 0x02 ] = KEY_2, - [ 0x03 ] = KEY_3, - [ 0x04 ] = KEY_4, - [ 0x05 ] = KEY_5, - [ 0x06 ] = KEY_6, - [ 0x07 ] = KEY_7, - [ 0x08 ] = KEY_8, - [ 0x09 ] = KEY_9, - - [ 0x0a ] = KEY_TEXT, /* keypad asterisk as well */ - [ 0x0b ] = KEY_RED, /* red button */ - [ 0x0c ] = KEY_RADIO, - [ 0x0d ] = KEY_MENU, - [ 0x0e ] = KEY_SUBTITLE, /* also the # key */ - [ 0x0f ] = KEY_MUTE, - [ 0x10 ] = KEY_VOLUMEUP, - [ 0x11 ] = KEY_VOLUMEDOWN, - [ 0x12 ] = KEY_PREVIOUS, /* previous channel */ - [ 0x14 ] = KEY_UP, - [ 0x15 ] = KEY_DOWN, - [ 0x16 ] = KEY_LEFT, - [ 0x17 ] = KEY_RIGHT, - [ 0x18 ] = KEY_VIDEO, /* Videos */ - [ 0x19 ] = KEY_AUDIO, /* Music */ + [0x00] = KEY_0, + [0x01] = KEY_1, + [0x02] = KEY_2, + [0x03] = KEY_3, + [0x04] = KEY_4, + [0x05] = KEY_5, + [0x06] = KEY_6, + [0x07] = KEY_7, + [0x08] = KEY_8, + [0x09] = KEY_9, + + [0x0a] = KEY_TEXT, /* keypad asterisk as well */ + [0x0b] = KEY_RED, /* red button */ + [0x0c] = KEY_RADIO, + [0x0d] = KEY_MENU, + [0x0e] = KEY_SUBTITLE, /* also the # key */ + [0x0f] = KEY_MUTE, + [0x10] = KEY_VOLUMEUP, + [0x11] = KEY_VOLUMEDOWN, + [0x12] = KEY_PREVIOUS, /* previous channel */ + [0x14] = KEY_UP, + [0x15] = KEY_DOWN, + [0x16] = KEY_LEFT, + [0x17] = KEY_RIGHT, + [0x18] = KEY_VIDEO, /* Videos */ + [0x19] = KEY_AUDIO, /* Music */ /* 0x1a: Pictures - presume this means "Multimedia Home Platform" - no "PICTURES" key in input.h */ - [ 0x1a ] = KEY_MHP, - - [ 0x1b ] = KEY_EPG, /* Guide */ - [ 0x1c ] = KEY_TV, - [ 0x1e ] = KEY_NEXTSONG, /* skip >| */ - [ 0x1f ] = KEY_EXIT, /* back/exit */ - [ 0x20 ] = KEY_CHANNELUP, /* channel / program + */ - [ 0x21 ] = KEY_CHANNELDOWN, /* channel / program - */ - [ 0x22 ] = KEY_CHANNEL, /* source (old black remote) */ - [ 0x24 ] = KEY_PREVIOUSSONG, /* replay |< */ - [ 0x25 ] = KEY_ENTER, /* OK */ - [ 0x26 ] = KEY_SLEEP, /* minimize (old black remote) */ - [ 0x29 ] = KEY_BLUE, /* blue key */ - [ 0x2e ] = KEY_GREEN, /* green button */ - [ 0x30 ] = KEY_PAUSE, /* pause */ - [ 0x32 ] = KEY_REWIND, /* backward << */ - [ 0x34 ] = KEY_FASTFORWARD, /* forward >> */ - [ 0x35 ] = KEY_PLAY, - [ 0x36 ] = KEY_STOP, - [ 0x37 ] = KEY_RECORD, /* recording */ - [ 0x38 ] = KEY_YELLOW, /* yellow key */ - [ 0x3b ] = KEY_SELECT, /* top right button */ - [ 0x3c ] = KEY_ZOOM, /* full */ - [ 0x3d ] = KEY_POWER, /* system power (green button) */ + [0x1a] = KEY_MHP, + + [0x1b] = KEY_EPG, /* Guide */ + [0x1c] = KEY_TV, + [0x1e] = KEY_NEXTSONG, /* skip >| */ + [0x1f] = KEY_EXIT, /* back/exit */ + [0x20] = KEY_CHANNELUP, /* channel / program + */ + [0x21] = KEY_CHANNELDOWN, /* channel / program - */ + [0x22] = KEY_CHANNEL, /* source (old black remote) */ + [0x24] = KEY_PREVIOUSSONG, /* replay |< */ + [0x25] = KEY_ENTER, /* OK */ + [0x26] = KEY_SLEEP, /* minimize (old black remote) */ + [0x29] = KEY_BLUE, /* blue key */ + [0x2e] = KEY_GREEN, /* green button */ + [0x30] = KEY_PAUSE, /* pause */ + [0x32] = KEY_REWIND, /* backward << */ + [0x34] = KEY_FASTFORWARD, /* forward >> */ + [0x35] = KEY_PLAY, + [0x36] = KEY_STOP, + [0x37] = KEY_RECORD, /* recording */ + [0x38] = KEY_YELLOW, /* yellow key */ + [0x3b] = KEY_SELECT, /* top right button */ + [0x3c] = KEY_ZOOM, /* full */ + [0x3d] = KEY_POWER, /* system power (green button) */ }; EXPORT_SYMBOL_GPL(ir_codes_hauppauge_new); IR_KEYTAB_TYPE ir_codes_npgtech[IR_KEYTAB_SIZE] = { - [ 0x1d ] = KEY_SWITCHVIDEOMODE, /* switch inputs */ - [ 0x2a ] = KEY_FRONT, - - [ 0x3e ] = KEY_1, - [ 0x02 ] = KEY_2, - [ 0x06 ] = KEY_3, - [ 0x0a ] = KEY_4, - [ 0x0e ] = KEY_5, - [ 0x12 ] = KEY_6, - [ 0x16 ] = KEY_7, - [ 0x1a ] = KEY_8, - [ 0x1e ] = KEY_9, - [ 0x3a ] = KEY_0, - [ 0x22 ] = KEY_NUMLOCK, /* -/-- */ - [ 0x20 ] = KEY_REFRESH, - - [ 0x03 ] = KEY_BRIGHTNESSDOWN, - [ 0x28 ] = KEY_AUDIO, - [ 0x3c ] = KEY_UP, - [ 0x3f ] = KEY_LEFT, - [ 0x2e ] = KEY_MUTE, - [ 0x3b ] = KEY_RIGHT, - [ 0x00 ] = KEY_DOWN, - [ 0x07 ] = KEY_BRIGHTNESSUP, - [ 0x2c ] = KEY_TEXT, - - [ 0x37 ] = KEY_RECORD, - [ 0x17 ] = KEY_PLAY, - [ 0x13 ] = KEY_PAUSE, - [ 0x26 ] = KEY_STOP, - [ 0x18 ] = KEY_FASTFORWARD, - [ 0x14 ] = KEY_REWIND, - [ 0x33 ] = KEY_ZOOM, - [ 0x32 ] = KEY_KEYBOARD, - [ 0x30 ] = KEY_GOTO, /* Pointing arrow */ - [ 0x36 ] = KEY_MACRO, /* Maximize/Minimize (yellow) */ - [ 0x0b ] = KEY_RADIO, - [ 0x10 ] = KEY_POWER, + [0x1d] = KEY_SWITCHVIDEOMODE, /* switch inputs */ + [0x2a] = KEY_FRONT, + + [0x3e] = KEY_1, + [0x02] = KEY_2, + [0x06] = KEY_3, + [0x0a] = KEY_4, + [0x0e] = KEY_5, + [0x12] = KEY_6, + [0x16] = KEY_7, + [0x1a] = KEY_8, + [0x1e] = KEY_9, + [0x3a] = KEY_0, + [0x22] = KEY_NUMLOCK, /* -/-- */ + [0x20] = KEY_REFRESH, + + [0x03] = KEY_BRIGHTNESSDOWN, + [0x28] = KEY_AUDIO, + [0x3c] = KEY_UP, + [0x3f] = KEY_LEFT, + [0x2e] = KEY_MUTE, + [0x3b] = KEY_RIGHT, + [0x00] = KEY_DOWN, + [0x07] = KEY_BRIGHTNESSUP, + [0x2c] = KEY_TEXT, + + [0x37] = KEY_RECORD, + [0x17] = KEY_PLAY, + [0x13] = KEY_PAUSE, + [0x26] = KEY_STOP, + [0x18] = KEY_FASTFORWARD, + [0x14] = KEY_REWIND, + [0x33] = KEY_ZOOM, + [0x32] = KEY_KEYBOARD, + [0x30] = KEY_GOTO, /* Pointing arrow */ + [0x36] = KEY_MACRO, /* Maximize/Minimize (yellow) */ + [0x0b] = KEY_RADIO, + [0x10] = KEY_POWER, }; @@ -1814,45 +1814,45 @@ EXPORT_SYMBOL_GPL(ir_codes_npgtech); Key comments are the functions given in the manual */ IR_KEYTAB_TYPE ir_codes_norwood[IR_KEYTAB_SIZE] = { /* Keys 0 to 9 */ - [ 0x20 ] = KEY_0, - [ 0x21 ] = KEY_1, - [ 0x22 ] = KEY_2, - [ 0x23 ] = KEY_3, - [ 0x24 ] = KEY_4, - [ 0x25 ] = KEY_5, - [ 0x26 ] = KEY_6, - [ 0x27 ] = KEY_7, - [ 0x28 ] = KEY_8, - [ 0x29 ] = KEY_9, - - [ 0x78 ] = KEY_TUNER, /* Video Source */ - [ 0x2c ] = KEY_EXIT, /* Open/Close software */ - [ 0x2a ] = KEY_SELECT, /* 2 Digit Select */ - [ 0x69 ] = KEY_AGAIN, /* Recall */ - - [ 0x32 ] = KEY_BRIGHTNESSUP, /* Brightness increase */ - [ 0x33 ] = KEY_BRIGHTNESSDOWN, /* Brightness decrease */ - [ 0x6b ] = KEY_KPPLUS, /* (not named >>>>>) */ - [ 0x6c ] = KEY_KPMINUS, /* (not named <<<<<) */ - - [ 0x2d ] = KEY_MUTE, /* Mute */ - [ 0x30 ] = KEY_VOLUMEUP, /* Volume up */ - [ 0x31 ] = KEY_VOLUMEDOWN, /* Volume down */ - [ 0x60 ] = KEY_CHANNELUP, /* Channel up */ - [ 0x61 ] = KEY_CHANNELDOWN, /* Channel down */ - - [ 0x3f ] = KEY_RECORD, /* Record */ - [ 0x37 ] = KEY_PLAY, /* Play */ - [ 0x36 ] = KEY_PAUSE, /* Pause */ - [ 0x2b ] = KEY_STOP, /* Stop */ - [ 0x67 ] = KEY_FASTFORWARD, /* Foward */ - [ 0x66 ] = KEY_REWIND, /* Rewind */ - [ 0x3e ] = KEY_SEARCH, /* Auto Scan */ - [ 0x2e ] = KEY_CAMERA, /* Capture Video */ - [ 0x6d ] = KEY_MENU, /* Show/Hide Control */ - [ 0x2f ] = KEY_ZOOM, /* Full Screen */ - [ 0x34 ] = KEY_RADIO, /* FM */ - [ 0x65 ] = KEY_POWER, /* Computer power */ + [0x20] = KEY_0, + [0x21] = KEY_1, + [0x22] = KEY_2, + [0x23] = KEY_3, + [0x24] = KEY_4, + [0x25] = KEY_5, + [0x26] = KEY_6, + [0x27] = KEY_7, + [0x28] = KEY_8, + [0x29] = KEY_9, + + [0x78] = KEY_TUNER, /* Video Source */ + [0x2c] = KEY_EXIT, /* Open/Close software */ + [0x2a] = KEY_SELECT, /* 2 Digit Select */ + [0x69] = KEY_AGAIN, /* Recall */ + + [0x32] = KEY_BRIGHTNESSUP, /* Brightness increase */ + [0x33] = KEY_BRIGHTNESSDOWN, /* Brightness decrease */ + [0x6b] = KEY_KPPLUS, /* (not named >>>>>) */ + [0x6c] = KEY_KPMINUS, /* (not named <<<<<) */ + + [0x2d] = KEY_MUTE, /* Mute */ + [0x30] = KEY_VOLUMEUP, /* Volume up */ + [0x31] = KEY_VOLUMEDOWN, /* Volume down */ + [0x60] = KEY_CHANNELUP, /* Channel up */ + [0x61] = KEY_CHANNELDOWN, /* Channel down */ + + [0x3f] = KEY_RECORD, /* Record */ + [0x37] = KEY_PLAY, /* Play */ + [0x36] = KEY_PAUSE, /* Pause */ + [0x2b] = KEY_STOP, /* Stop */ + [0x67] = KEY_FASTFORWARD, /* Foward */ + [0x66] = KEY_REWIND, /* Rewind */ + [0x3e] = KEY_SEARCH, /* Auto Scan */ + [0x2e] = KEY_CAMERA, /* Capture Video */ + [0x6d] = KEY_MENU, /* Show/Hide Control */ + [0x2f] = KEY_ZOOM, /* Full Screen */ + [0x34] = KEY_RADIO, /* FM */ + [0x65] = KEY_POWER, /* Computer power */ }; EXPORT_SYMBOL_GPL(ir_codes_norwood); @@ -1863,51 +1863,51 @@ EXPORT_SYMBOL_GPL(ir_codes_norwood); * This is a "middle of the road" approach, differences are noted */ IR_KEYTAB_TYPE ir_codes_budget_ci_old[IR_KEYTAB_SIZE] = { - [ 0x00 ] = KEY_0, - [ 0x01 ] = KEY_1, - [ 0x02 ] = KEY_2, - [ 0x03 ] = KEY_3, - [ 0x04 ] = KEY_4, - [ 0x05 ] = KEY_5, - [ 0x06 ] = KEY_6, - [ 0x07 ] = KEY_7, - [ 0x08 ] = KEY_8, - [ 0x09 ] = KEY_9, - [ 0x0a ] = KEY_ENTER, - [ 0x0b ] = KEY_RED, - [ 0x0c ] = KEY_POWER, /* RADIO on Hauppauge */ - [ 0x0d ] = KEY_MUTE, - [ 0x0f ] = KEY_A, /* TV on Hauppauge */ - [ 0x10 ] = KEY_VOLUMEUP, - [ 0x11 ] = KEY_VOLUMEDOWN, - [ 0x14 ] = KEY_B, - [ 0x1c ] = KEY_UP, - [ 0x1d ] = KEY_DOWN, - [ 0x1e ] = KEY_OPTION, /* RESERVED on Hauppauge */ - [ 0x1f ] = KEY_BREAK, - [ 0x20 ] = KEY_CHANNELUP, - [ 0x21 ] = KEY_CHANNELDOWN, - [ 0x22 ] = KEY_PREVIOUS, /* Prev. Ch on Zenith, SOURCE on Hauppauge */ - [ 0x24 ] = KEY_RESTART, - [ 0x25 ] = KEY_OK, - [ 0x26 ] = KEY_CYCLEWINDOWS, /* MINIMIZE on Hauppauge */ - [ 0x28 ] = KEY_ENTER, /* VCR mode on Zenith */ - [ 0x29 ] = KEY_PAUSE, - [ 0x2b ] = KEY_RIGHT, - [ 0x2c ] = KEY_LEFT, - [ 0x2e ] = KEY_MENU, /* FULL SCREEN on Hauppauge */ - [ 0x30 ] = KEY_SLOW, - [ 0x31 ] = KEY_PREVIOUS, /* VCR mode on Zenith */ - [ 0x32 ] = KEY_REWIND, - [ 0x34 ] = KEY_FASTFORWARD, - [ 0x35 ] = KEY_PLAY, - [ 0x36 ] = KEY_STOP, - [ 0x37 ] = KEY_RECORD, - [ 0x38 ] = KEY_TUNER, /* TV/VCR on Zenith */ - [ 0x3a ] = KEY_C, - [ 0x3c ] = KEY_EXIT, - [ 0x3d ] = KEY_POWER2, - [ 0x3e ] = KEY_TUNER, + [0x00] = KEY_0, + [0x01] = KEY_1, + [0x02] = KEY_2, + [0x03] = KEY_3, + [0x04] = KEY_4, + [0x05] = KEY_5, + [0x06] = KEY_6, + [0x07] = KEY_7, + [0x08] = KEY_8, + [0x09] = KEY_9, + [0x0a] = KEY_ENTER, + [0x0b] = KEY_RED, + [0x0c] = KEY_POWER, /* RADIO on Hauppauge */ + [0x0d] = KEY_MUTE, + [0x0f] = KEY_A, /* TV on Hauppauge */ + [0x10] = KEY_VOLUMEUP, + [0x11] = KEY_VOLUMEDOWN, + [0x14] = KEY_B, + [0x1c] = KEY_UP, + [0x1d] = KEY_DOWN, + [0x1e] = KEY_OPTION, /* RESERVED on Hauppauge */ + [0x1f] = KEY_BREAK, + [0x20] = KEY_CHANNELUP, + [0x21] = KEY_CHANNELDOWN, + [0x22] = KEY_PREVIOUS, /* Prev. Ch on Zenith, SOURCE on Hauppauge */ + [0x24] = KEY_RESTART, + [0x25] = KEY_OK, + [0x26] = KEY_CYCLEWINDOWS, /* MINIMIZE on Hauppauge */ + [0x28] = KEY_ENTER, /* VCR mode on Zenith */ + [0x29] = KEY_PAUSE, + [0x2b] = KEY_RIGHT, + [0x2c] = KEY_LEFT, + [0x2e] = KEY_MENU, /* FULL SCREEN on Hauppauge */ + [0x30] = KEY_SLOW, + [0x31] = KEY_PREVIOUS, /* VCR mode on Zenith */ + [0x32] = KEY_REWIND, + [0x34] = KEY_FASTFORWARD, + [0x35] = KEY_PLAY, + [0x36] = KEY_STOP, + [0x37] = KEY_RECORD, + [0x38] = KEY_TUNER, /* TV/VCR on Zenith */ + [0x3a] = KEY_C, + [0x3c] = KEY_EXIT, + [0x3d] = KEY_POWER2, + [0x3e] = KEY_TUNER, }; EXPORT_SYMBOL_GPL(ir_codes_budget_ci_old); @@ -1919,49 +1919,49 @@ EXPORT_SYMBOL_GPL(ir_codes_budget_ci_old); */ IR_KEYTAB_TYPE ir_codes_asus_pc39[IR_KEYTAB_SIZE] = { /* Keys 0 to 9 */ - [ 0x15 ] = KEY_0, - [ 0x29 ] = KEY_1, - [ 0x2d ] = KEY_2, - [ 0x2b ] = KEY_3, - [ 0x09 ] = KEY_4, - [ 0x0d ] = KEY_5, - [ 0x0b ] = KEY_6, - [ 0x31 ] = KEY_7, - [ 0x35 ] = KEY_8, - [ 0x33 ] = KEY_9, - - [ 0x3e ] = KEY_RADIO, /* radio */ - [ 0x03 ] = KEY_MENU, /* dvd/menu */ - [ 0x2a ] = KEY_VOLUMEUP, - [ 0x19 ] = KEY_VOLUMEDOWN, - [ 0x37 ] = KEY_UP, - [ 0x3b ] = KEY_DOWN, - [ 0x27 ] = KEY_LEFT, - [ 0x2f ] = KEY_RIGHT, - [ 0x25 ] = KEY_VIDEO, /* video */ - [ 0x39 ] = KEY_AUDIO, /* music */ - - [ 0x21 ] = KEY_TV, /* tv */ - [ 0x1d ] = KEY_EXIT, /* back */ - [ 0x0a ] = KEY_CHANNELUP, /* channel / program + */ - [ 0x1b ] = KEY_CHANNELDOWN, /* channel / program - */ - [ 0x1a ] = KEY_ENTER, /* enter */ - - [ 0x06 ] = KEY_PAUSE, /* play/pause */ - [ 0x1e ] = KEY_PREVIOUS, /* rew */ - [ 0x26 ] = KEY_NEXT, /* forward */ - [ 0x0e ] = KEY_REWIND, /* backward << */ - [ 0x3a ] = KEY_FASTFORWARD, /* forward >> */ - [ 0x36 ] = KEY_STOP, - [ 0x2e ] = KEY_RECORD, /* recording */ - [ 0x16 ] = KEY_POWER, /* the button that reads "close" */ - - [ 0x11 ] = KEY_ZOOM, /* full screen */ - [ 0x13 ] = KEY_MACRO, /* recall */ - [ 0x23 ] = KEY_HOME, /* home */ - [ 0x05 ] = KEY_PVR, /* picture */ - [ 0x3d ] = KEY_MUTE, /* mute */ - [ 0x01 ] = KEY_DVD, /* dvd */ + [0x15] = KEY_0, + [0x29] = KEY_1, + [0x2d] = KEY_2, + [0x2b] = KEY_3, + [0x09] = KEY_4, + [0x0d] = KEY_5, + [0x0b] = KEY_6, + [0x31] = KEY_7, + [0x35] = KEY_8, + [0x33] = KEY_9, + + [0x3e] = KEY_RADIO, /* radio */ + [0x03] = KEY_MENU, /* dvd/menu */ + [0x2a] = KEY_VOLUMEUP, + [0x19] = KEY_VOLUMEDOWN, + [0x37] = KEY_UP, + [0x3b] = KEY_DOWN, + [0x27] = KEY_LEFT, + [0x2f] = KEY_RIGHT, + [0x25] = KEY_VIDEO, /* video */ + [0x39] = KEY_AUDIO, /* music */ + + [0x21] = KEY_TV, /* tv */ + [0x1d] = KEY_EXIT, /* back */ + [0x0a] = KEY_CHANNELUP, /* channel / program + */ + [0x1b] = KEY_CHANNELDOWN, /* channel / program - */ + [0x1a] = KEY_ENTER, /* enter */ + + [0x06] = KEY_PAUSE, /* play/pause */ + [0x1e] = KEY_PREVIOUS, /* rew */ + [0x26] = KEY_NEXT, /* forward */ + [0x0e] = KEY_REWIND, /* backward << */ + [0x3a] = KEY_FASTFORWARD, /* forward >> */ + [0x36] = KEY_STOP, + [0x2e] = KEY_RECORD, /* recording */ + [0x16] = KEY_POWER, /* the button that reads "close" */ + + [0x11] = KEY_ZOOM, /* full screen */ + [0x13] = KEY_MACRO, /* recall */ + [0x23] = KEY_HOME, /* home */ + [0x05] = KEY_PVR, /* picture */ + [0x3d] = KEY_MUTE, /* mute */ + [0x01] = KEY_DVD, /* dvd */ }; EXPORT_SYMBOL_GPL(ir_codes_asus_pc39); @@ -1973,78 +1973,78 @@ IR_KEYTAB_TYPE ir_codes_encore_enltv[IR_KEYTAB_SIZE] = { /* Power button does nothing, neither in Windows app, although it sends data (used for BIOS wakeup?) */ - [ 0x0d ] = KEY_MUTE, - - [ 0x1e ] = KEY_TV, - [ 0x00 ] = KEY_VIDEO, - [ 0x01 ] = KEY_AUDIO, /* music */ - [ 0x02 ] = KEY_MHP, /* picture */ - - [ 0x1f ] = KEY_1, - [ 0x03 ] = KEY_2, - [ 0x04 ] = KEY_3, - [ 0x05 ] = KEY_4, - [ 0x1c ] = KEY_5, - [ 0x06 ] = KEY_6, - [ 0x07 ] = KEY_7, - [ 0x08 ] = KEY_8, - [ 0x1d ] = KEY_9, - [ 0x0a ] = KEY_0, - - [ 0x09 ] = KEY_LIST, /* -/-- */ - [ 0x0b ] = KEY_LAST, /* recall */ - - [ 0x14 ] = KEY_HOME, /* win start menu */ - [ 0x15 ] = KEY_EXIT, /* exit */ + [0x0d] = KEY_MUTE, + + [0x1e] = KEY_TV, + [0x00] = KEY_VIDEO, + [0x01] = KEY_AUDIO, /* music */ + [0x02] = KEY_MHP, /* picture */ + + [0x1f] = KEY_1, + [0x03] = KEY_2, + [0x04] = KEY_3, + [0x05] = KEY_4, + [0x1c] = KEY_5, + [0x06] = KEY_6, + [0x07] = KEY_7, + [0x08] = KEY_8, + [0x1d] = KEY_9, + [0x0a] = KEY_0, + + [0x09] = KEY_LIST, /* -/-- */ + [0x0b] = KEY_LAST, /* recall */ + + [0x14] = KEY_HOME, /* win start menu */ + [0x15] = KEY_EXIT, /* exit */ #if 0 - [ 0x16 ] = KEY_CHANNELUP, /* UP */ - [ 0x12 ] = KEY_CHANNELDOWN, /* DOWN */ - [ 0x0c ] = KEY_VOLUMEUP, /* RIGHT */ - [ 0x17 ] = KEY_VOLUMEDOWN, /* LEFT */ + [0x16] = KEY_CHANNELUP, /* UP */ + [0x12] = KEY_CHANNELDOWN, /* DOWN */ + [0x0c] = KEY_VOLUMEUP, /* RIGHT */ + [0x17] = KEY_VOLUMEDOWN, /* LEFT */ #else - [ 0x16 ] = KEY_UP, - [ 0x12 ] = KEY_DOWN, - [ 0x0c ] = KEY_RIGHT, - [ 0x17 ] = KEY_LEFT, + [0x16] = KEY_UP, + [0x12] = KEY_DOWN, + [0x0c] = KEY_RIGHT, + [0x17] = KEY_LEFT, #endif - [ 0x18 ] = KEY_ENTER, /* OK */ + [0x18] = KEY_ENTER, /* OK */ - [ 0x0e ] = KEY_ESC, - [ 0x13 ] = KEY_D, /* desktop */ - [ 0x11 ] = KEY_TAB, - [ 0x19 ] = KEY_SWITCHVIDEOMODE, /* switch */ + [0x0e] = KEY_ESC, + [0x13] = KEY_D, /* desktop */ + [0x11] = KEY_TAB, + [0x19] = KEY_SWITCHVIDEOMODE, /* switch */ - [ 0x1a ] = KEY_MENU, - [ 0x1b ] = KEY_ZOOM, /* fullscreen */ - [ 0x44 ] = KEY_TIME, /* time shift */ - [ 0x40 ] = KEY_MODE, /* source */ + [0x1a] = KEY_MENU, + [0x1b] = KEY_ZOOM, /* fullscreen */ + [0x44] = KEY_TIME, /* time shift */ + [0x40] = KEY_MODE, /* source */ - [ 0x5a ] = KEY_RECORD, - [ 0x42 ] = KEY_PLAY, /* play/pause */ - [ 0x45 ] = KEY_STOP, - [ 0x43 ] = KEY_CAMERA, /* camera icon */ + [0x5a] = KEY_RECORD, + [0x42] = KEY_PLAY, /* play/pause */ + [0x45] = KEY_STOP, + [0x43] = KEY_CAMERA, /* camera icon */ - [ 0x48 ] = KEY_REWIND, - [ 0x4a ] = KEY_FASTFORWARD, - [ 0x49 ] = KEY_PREVIOUS, - [ 0x4b ] = KEY_NEXT, + [0x48] = KEY_REWIND, + [0x4a] = KEY_FASTFORWARD, + [0x49] = KEY_PREVIOUS, + [0x4b] = KEY_NEXT, - [ 0x4c ] = KEY_FAVORITES, /* tv wall */ - [ 0x4d ] = KEY_SOUND, /* DVD sound */ - [ 0x4e ] = KEY_LANGUAGE, /* DVD lang */ - [ 0x4f ] = KEY_TEXT, /* DVD text */ + [0x4c] = KEY_FAVORITES, /* tv wall */ + [0x4d] = KEY_SOUND, /* DVD sound */ + [0x4e] = KEY_LANGUAGE, /* DVD lang */ + [0x4f] = KEY_TEXT, /* DVD text */ - [ 0x50 ] = KEY_SLEEP, /* shutdown */ - [ 0x51 ] = KEY_MODE, /* stereo > main */ - [ 0x52 ] = KEY_SELECT, /* stereo > sap */ - [ 0x53 ] = KEY_PROG1, /* teletext */ + [0x50] = KEY_SLEEP, /* shutdown */ + [0x51] = KEY_MODE, /* stereo > main */ + [0x52] = KEY_SELECT, /* stereo > sap */ + [0x53] = KEY_PROG1, /* teletext */ - [ 0x59 ] = KEY_RED, /* AP1 */ - [ 0x41 ] = KEY_GREEN, /* AP2 */ - [ 0x47 ] = KEY_YELLOW, /* AP3 */ - [ 0x57 ] = KEY_BLUE, /* AP4 */ + [0x59] = KEY_RED, /* AP1 */ + [0x41] = KEY_GREEN, /* AP2 */ + [0x47] = KEY_YELLOW, /* AP3 */ + [0x57] = KEY_BLUE, /* AP4 */ }; EXPORT_SYMBOL_GPL(ir_codes_encore_enltv); @@ -2102,45 +2102,45 @@ EXPORT_SYMBOL_GPL(ir_codes_encore_enltv2); /* for the Technotrend 1500 bundled remotes (grey and black): */ IR_KEYTAB_TYPE ir_codes_tt_1500[IR_KEYTAB_SIZE] = { - [ 0x01 ] = KEY_POWER, - [ 0x02 ] = KEY_SHUFFLE, /* ? double-arrow key */ - [ 0x03 ] = KEY_1, - [ 0x04 ] = KEY_2, - [ 0x05 ] = KEY_3, - [ 0x06 ] = KEY_4, - [ 0x07 ] = KEY_5, - [ 0x08 ] = KEY_6, - [ 0x09 ] = KEY_7, - [ 0x0a ] = KEY_8, - [ 0x0b ] = KEY_9, - [ 0x0c ] = KEY_0, - [ 0x0d ] = KEY_UP, - [ 0x0e ] = KEY_LEFT, - [ 0x0f ] = KEY_OK, - [ 0x10 ] = KEY_RIGHT, - [ 0x11 ] = KEY_DOWN, - [ 0x12 ] = KEY_INFO, - [ 0x13 ] = KEY_EXIT, - [ 0x14 ] = KEY_RED, - [ 0x15 ] = KEY_GREEN, - [ 0x16 ] = KEY_YELLOW, - [ 0x17 ] = KEY_BLUE, - [ 0x18 ] = KEY_MUTE, - [ 0x19 ] = KEY_TEXT, - [ 0x1a ] = KEY_MODE, /* ? TV/Radio */ - [ 0x21 ] = KEY_OPTION, - [ 0x22 ] = KEY_EPG, - [ 0x23 ] = KEY_CHANNELUP, - [ 0x24 ] = KEY_CHANNELDOWN, - [ 0x25 ] = KEY_VOLUMEUP, - [ 0x26 ] = KEY_VOLUMEDOWN, - [ 0x27 ] = KEY_SETUP, - [ 0x3a ] = KEY_RECORD, /* these keys are only in the black remote */ - [ 0x3b ] = KEY_PLAY, - [ 0x3c ] = KEY_STOP, - [ 0x3d ] = KEY_REWIND, - [ 0x3e ] = KEY_PAUSE, - [ 0x3f ] = KEY_FORWARD, + [0x01] = KEY_POWER, + [0x02] = KEY_SHUFFLE, /* ? double-arrow key */ + [0x03] = KEY_1, + [0x04] = KEY_2, + [0x05] = KEY_3, + [0x06] = KEY_4, + [0x07] = KEY_5, + [0x08] = KEY_6, + [0x09] = KEY_7, + [0x0a] = KEY_8, + [0x0b] = KEY_9, + [0x0c] = KEY_0, + [0x0d] = KEY_UP, + [0x0e] = KEY_LEFT, + [0x0f] = KEY_OK, + [0x10] = KEY_RIGHT, + [0x11] = KEY_DOWN, + [0x12] = KEY_INFO, + [0x13] = KEY_EXIT, + [0x14] = KEY_RED, + [0x15] = KEY_GREEN, + [0x16] = KEY_YELLOW, + [0x17] = KEY_BLUE, + [0x18] = KEY_MUTE, + [0x19] = KEY_TEXT, + [0x1a] = KEY_MODE, /* ? TV/Radio */ + [0x21] = KEY_OPTION, + [0x22] = KEY_EPG, + [0x23] = KEY_CHANNELUP, + [0x24] = KEY_CHANNELDOWN, + [0x25] = KEY_VOLUMEUP, + [0x26] = KEY_VOLUMEDOWN, + [0x27] = KEY_SETUP, + [0x3a] = KEY_RECORD, /* these keys are only in the black remote */ + [0x3b] = KEY_PLAY, + [0x3c] = KEY_STOP, + [0x3d] = KEY_REWIND, + [0x3e] = KEY_PAUSE, + [0x3f] = KEY_FORWARD, }; EXPORT_SYMBOL_GPL(ir_codes_tt_1500); @@ -2148,60 +2148,60 @@ EXPORT_SYMBOL_GPL(ir_codes_tt_1500); /* DViCO FUSION HDTV MCE remote */ IR_KEYTAB_TYPE ir_codes_fusionhdtv_mce[IR_KEYTAB_SIZE] = { - [ 0x0b ] = KEY_1, - [ 0x17 ] = KEY_2, - [ 0x1b ] = KEY_3, - [ 0x07 ] = KEY_4, - [ 0x50 ] = KEY_5, - [ 0x54 ] = KEY_6, - [ 0x48 ] = KEY_7, - [ 0x4c ] = KEY_8, - [ 0x58 ] = KEY_9, - [ 0x03 ] = KEY_0, - - [ 0x5e ] = KEY_OK, - [ 0x51 ] = KEY_UP, - [ 0x53 ] = KEY_DOWN, - [ 0x5b ] = KEY_LEFT, - [ 0x5f ] = KEY_RIGHT, - - [ 0x02 ] = KEY_TV, /* Labeled DTV on remote */ - [ 0x0e ] = KEY_MP3, - [ 0x1a ] = KEY_DVD, - [ 0x1e ] = KEY_FAVORITES, /* Labeled CPF on remote */ - [ 0x16 ] = KEY_SETUP, - [ 0x46 ] = KEY_POWER2, /* TV On/Off button on remote */ - [ 0x0a ] = KEY_EPG, /* Labeled Guide on remote */ - - [ 0x49 ] = KEY_BACK, - [ 0x59 ] = KEY_INFO, /* Labeled MORE on remote */ - [ 0x4d ] = KEY_MENU, /* Labeled DVDMENU on remote */ - [ 0x55 ] = KEY_CYCLEWINDOWS, /* Labeled ALT-TAB on remote */ - - [ 0x0f ] = KEY_PREVIOUSSONG, /* Labeled |<< REPLAY on remote */ - [ 0x12 ] = KEY_NEXTSONG, /* Labeled >>| SKIP on remote */ - [ 0x42 ] = KEY_ENTER, /* Labeled START with a green + [0x0b] = KEY_1, + [0x17] = KEY_2, + [0x1b] = KEY_3, + [0x07] = KEY_4, + [0x50] = KEY_5, + [0x54] = KEY_6, + [0x48] = KEY_7, + [0x4c] = KEY_8, + [0x58] = KEY_9, + [0x03] = KEY_0, + + [0x5e] = KEY_OK, + [0x51] = KEY_UP, + [0x53] = KEY_DOWN, + [0x5b] = KEY_LEFT, + [0x5f] = KEY_RIGHT, + + [0x02] = KEY_TV, /* Labeled DTV on remote */ + [0x0e] = KEY_MP3, + [0x1a] = KEY_DVD, + [0x1e] = KEY_FAVORITES, /* Labeled CPF on remote */ + [0x16] = KEY_SETUP, + [0x46] = KEY_POWER2, /* TV On/Off button on remote */ + [0x0a] = KEY_EPG, /* Labeled Guide on remote */ + + [0x49] = KEY_BACK, + [0x59] = KEY_INFO, /* Labeled MORE on remote */ + [0x4d] = KEY_MENU, /* Labeled DVDMENU on remote */ + [0x55] = KEY_CYCLEWINDOWS, /* Labeled ALT-TAB on remote */ + + [0x0f] = KEY_PREVIOUSSONG, /* Labeled |<< REPLAY on remote */ + [0x12] = KEY_NEXTSONG, /* Labeled >>| SKIP on remote */ + [0x42] = KEY_ENTER, /* Labeled START with a green * MS windows logo on remote */ - [ 0x15 ] = KEY_VOLUMEUP, - [ 0x05 ] = KEY_VOLUMEDOWN, - [ 0x11 ] = KEY_CHANNELUP, - [ 0x09 ] = KEY_CHANNELDOWN, - - [ 0x52 ] = KEY_CAMERA, - [ 0x5a ] = KEY_TUNER, - [ 0x19 ] = KEY_OPEN, - - [ 0x13 ] = KEY_MODE, /* 4:3 16:9 select */ - [ 0x1f ] = KEY_ZOOM, - - [ 0x43 ] = KEY_REWIND, - [ 0x47 ] = KEY_PLAYPAUSE, - [ 0x4f ] = KEY_FASTFORWARD, - [ 0x57 ] = KEY_MUTE, - [ 0x0d ] = KEY_STOP, - [ 0x01 ] = KEY_RECORD, - [ 0x4e ] = KEY_POWER, + [0x15] = KEY_VOLUMEUP, + [0x05] = KEY_VOLUMEDOWN, + [0x11] = KEY_CHANNELUP, + [0x09] = KEY_CHANNELDOWN, + + [0x52] = KEY_CAMERA, + [0x5a] = KEY_TUNER, + [0x19] = KEY_OPEN, + + [0x13] = KEY_MODE, /* 4:3 16:9 select */ + [0x1f] = KEY_ZOOM, + + [0x43] = KEY_REWIND, + [0x47] = KEY_PLAYPAUSE, + [0x4f] = KEY_FASTFORWARD, + [0x57] = KEY_MUTE, + [0x0d] = KEY_STOP, + [0x01] = KEY_RECORD, + [0x4e] = KEY_POWER, }; EXPORT_SYMBOL_GPL(ir_codes_fusionhdtv_mce); @@ -2257,8 +2257,8 @@ IR_KEYTAB_TYPE ir_codes_behold[IR_KEYTAB_SIZE] = { /* 0x1c 0x12 * * TV/FM POWER * * */ - [ 0x1c ] = KEY_TUNER, /*XXX KEY_TV KEY_RADIO */ - [ 0x12 ] = KEY_POWER, + [0x1c] = KEY_TUNER, /*XXX KEY_TV KEY_RADIO */ + [0x12] = KEY_POWER, /* 0x01 0x02 0x03 * * 1 2 3 * @@ -2269,28 +2269,28 @@ IR_KEYTAB_TYPE ir_codes_behold[IR_KEYTAB_SIZE] = { * 0x07 0x08 0x09 * * 7 8 9 * * */ - [ 0x01 ] = KEY_1, - [ 0x02 ] = KEY_2, - [ 0x03 ] = KEY_3, - [ 0x04 ] = KEY_4, - [ 0x05 ] = KEY_5, - [ 0x06 ] = KEY_6, - [ 0x07 ] = KEY_7, - [ 0x08 ] = KEY_8, - [ 0x09 ] = KEY_9, + [0x01] = KEY_1, + [0x02] = KEY_2, + [0x03] = KEY_3, + [0x04] = KEY_4, + [0x05] = KEY_5, + [0x06] = KEY_6, + [0x07] = KEY_7, + [0x08] = KEY_8, + [0x09] = KEY_9, /* 0x0a 0x00 0x17 * * RECALL 0 MODE * * */ - [ 0x0a ] = KEY_AGAIN, - [ 0x00 ] = KEY_0, - [ 0x17 ] = KEY_MODE, + [0x0a] = KEY_AGAIN, + [0x00] = KEY_0, + [0x17] = KEY_MODE, /* 0x14 0x10 * * ASPECT FULLSCREEN * * */ - [ 0x14 ] = KEY_SCREEN, - [ 0x10 ] = KEY_ZOOM, + [0x14] = KEY_SCREEN, + [0x10] = KEY_ZOOM, /* 0x0b * * Up * @@ -2301,17 +2301,17 @@ IR_KEYTAB_TYPE ir_codes_behold[IR_KEYTAB_SIZE] = { * 0x015 * * Down * * */ - [ 0x0b ] = KEY_CHANNELUP, /*XXX KEY_UP */ - [ 0x18 ] = KEY_VOLUMEDOWN, /*XXX KEY_LEFT */ - [ 0x16 ] = KEY_OK, /*XXX KEY_ENTER */ - [ 0x0c ] = KEY_VOLUMEUP, /*XXX KEY_RIGHT */ - [ 0x15 ] = KEY_CHANNELDOWN, /*XXX KEY_DOWN */ + [0x0b] = KEY_CHANNELUP, /*XXX KEY_UP */ + [0x18] = KEY_VOLUMEDOWN, /*XXX KEY_LEFT */ + [0x16] = KEY_OK, /*XXX KEY_ENTER */ + [0x0c] = KEY_VOLUMEUP, /*XXX KEY_RIGHT */ + [0x15] = KEY_CHANNELDOWN, /*XXX KEY_DOWN */ /* 0x11 0x0d * * MUTE INFO * * */ - [ 0x11 ] = KEY_MUTE, - [ 0x0d ] = KEY_INFO, + [0x11] = KEY_MUTE, + [0x0d] = KEY_INFO, /* 0x0f 0x1b 0x1a * * RECORD PLAY/PAUSE STOP * @@ -2320,26 +2320,26 @@ IR_KEYTAB_TYPE ir_codes_behold[IR_KEYTAB_SIZE] = { *TELETEXT AUDIO SOURCE * * RED YELLOW * * */ - [ 0x0f ] = KEY_RECORD, - [ 0x1b ] = KEY_PLAYPAUSE, - [ 0x1a ] = KEY_STOP, - [ 0x0e ] = KEY_TEXT, - [ 0x1f ] = KEY_RED, /*XXX KEY_AUDIO */ - [ 0x1e ] = KEY_YELLOW, /*XXX KEY_SOURCE */ + [0x0f] = KEY_RECORD, + [0x1b] = KEY_PLAYPAUSE, + [0x1a] = KEY_STOP, + [0x0e] = KEY_TEXT, + [0x1f] = KEY_RED, /*XXX KEY_AUDIO */ + [0x1e] = KEY_YELLOW, /*XXX KEY_SOURCE */ /* 0x1d 0x13 0x19 * * SLEEP PREVIEW DVB * * GREEN BLUE * * */ - [ 0x1d ] = KEY_SLEEP, - [ 0x13 ] = KEY_GREEN, - [ 0x19 ] = KEY_BLUE, /*XXX KEY_SAT */ + [0x1d] = KEY_SLEEP, + [0x13] = KEY_GREEN, + [0x19] = KEY_BLUE, /*XXX KEY_SAT */ /* 0x58 0x5c * * FREEZE SNAPSHOT * * */ - [ 0x58 ] = KEY_SLOW, - [ 0x5c ] = KEY_SAVE, + [0x58] = KEY_SLOW, + [0x5c] = KEY_SAVE, }; -- cgit v1.2.3 From a7fe8361bede9ae74c6f658604bd8024cfb1295a Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 27 Aug 2009 09:50:21 -0300 Subject: Properly indent comments with tabs From: Mauro Carvalho Chehab Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/common/ir-keymaps.c | 758 ++++++++++++++++---------------- 1 file changed, 379 insertions(+), 379 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/common/ir-keymaps.c b/linux/drivers/media/common/ir-keymaps.c index cf9950bf3..37db62ea5 100644 --- a/linux/drivers/media/common/ir-keymaps.c +++ b/linux/drivers/media/common/ir-keymaps.c @@ -46,60 +46,60 @@ IR_KEYTAB_TYPE ir_codes_proteus_2309[IR_KEYTAB_SIZE] = { [0x08] = KEY_8, [0x09] = KEY_9, - [0x5c] = KEY_POWER, /* power */ - [0x20] = KEY_F, /* full screen */ - [0x0f] = KEY_BACKSPACE, /* recall */ - [0x1b] = KEY_ENTER, /* mute */ - [0x41] = KEY_RECORD, /* record */ - [0x43] = KEY_STOP, /* stop */ + [0x5c] = KEY_POWER, /* power */ + [0x20] = KEY_F, /* full screen */ + [0x0f] = KEY_BACKSPACE, /* recall */ + [0x1b] = KEY_ENTER, /* mute */ + [0x41] = KEY_RECORD, /* record */ + [0x43] = KEY_STOP, /* stop */ [0x16] = KEY_S, - [0x1a] = KEY_Q, /* off */ + [0x1a] = KEY_Q, /* off */ [0x2e] = KEY_RED, - [0x1f] = KEY_DOWN, /* channel - */ - [0x1c] = KEY_UP, /* channel + */ - [0x10] = KEY_LEFT, /* volume - */ - [0x1e] = KEY_RIGHT, /* volume + */ + [0x1f] = KEY_DOWN, /* channel - */ + [0x1c] = KEY_UP, /* channel + */ + [0x10] = KEY_LEFT, /* volume - */ + [0x1e] = KEY_RIGHT, /* volume + */ [0x14] = KEY_F1, }; EXPORT_SYMBOL_GPL(ir_codes_proteus_2309); /* Matt Jesson >' */ - [0x3a] = KEY_RECORD, /* 'capture' */ - [0x0a] = KEY_MUTE, /* 'mute' */ - [0x2c] = KEY_RECORD, /* 'record' */ - [0x1c] = KEY_PAUSE, /* 'pause' */ - [0x3c] = KEY_STOP, /* 'stop' */ - [0x0c] = KEY_PLAY, /* 'play' */ - [0x2e] = KEY_RED, /* 'red' */ - [0x01] = KEY_BLUE, /* 'blue' / 'cancel' */ - [0x0e] = KEY_YELLOW, /* 'yellow' / 'ok' */ - [0x21] = KEY_GREEN, /* 'green' */ - [0x11] = KEY_CHANNELDOWN, /* 'channel -' */ - [0x31] = KEY_CHANNELUP, /* 'channel +' */ - [0x1e] = KEY_VOLUMEDOWN, /* 'volume -' */ - [0x3e] = KEY_VOLUMEUP, /* 'volume +' */ + [0x28] = KEY_0, /* '0' / 'enter' */ + [0x22] = KEY_1, /* '1' */ + [0x12] = KEY_2, /* '2' / 'up arrow' */ + [0x32] = KEY_3, /* '3' */ + [0x24] = KEY_4, /* '4' / 'left arrow' */ + [0x14] = KEY_5, /* '5' */ + [0x34] = KEY_6, /* '6' / 'right arrow' */ + [0x26] = KEY_7, /* '7' */ + [0x16] = KEY_8, /* '8' / 'down arrow' */ + [0x36] = KEY_9, /* '9' */ + + [0x20] = KEY_LIST, /* 'source' */ + [0x10] = KEY_TEXT, /* 'teletext' */ + [0x00] = KEY_POWER, /* 'power' */ + [0x04] = KEY_AUDIO, /* 'audio' */ + [0x06] = KEY_ZOOM, /* 'full screen' */ + [0x18] = KEY_VIDEO, /* 'display' */ + [0x38] = KEY_SEARCH, /* 'loop' */ + [0x08] = KEY_INFO, /* 'preview' */ + [0x2a] = KEY_REWIND, /* 'backward <<' */ + [0x1a] = KEY_FASTFORWARD, /* 'forward >>' */ + [0x3a] = KEY_RECORD, /* 'capture' */ + [0x0a] = KEY_MUTE, /* 'mute' */ + [0x2c] = KEY_RECORD, /* 'record' */ + [0x1c] = KEY_PAUSE, /* 'pause' */ + [0x3c] = KEY_STOP, /* 'stop' */ + [0x0c] = KEY_PLAY, /* 'play' */ + [0x2e] = KEY_RED, /* 'red' */ + [0x01] = KEY_BLUE, /* 'blue' / 'cancel' */ + [0x0e] = KEY_YELLOW, /* 'yellow' / 'ok' */ + [0x21] = KEY_GREEN, /* 'green' */ + [0x11] = KEY_CHANNELDOWN, /* 'channel -' */ + [0x31] = KEY_CHANNELUP, /* 'channel +' */ + [0x1e] = KEY_VOLUMEDOWN, /* 'volume -' */ + [0x3e] = KEY_VOLUMEUP, /* 'volume +' */ }; EXPORT_SYMBOL_GPL(ir_codes_avermedia_dvbt); @@ -192,7 +192,7 @@ IR_KEYTAB_TYPE ir_codes_avermedia_cardbus[IR_KEYTAB_SIZE] = { [0x27] = KEY_ANGLE, /* Size */ [0x28] = KEY_SELECT, /* Select */ [0x29] = KEY_BLUE, /* Blue/Picture */ - [0x2a] = KEY_BACKSPACE, /* Back */ + [0x2a] = KEY_BACKSPACE, /* Back */ [0x2b] = KEY_MEDIA, /* PIP (Picture-in-picture) */ [0x2c] = KEY_DOWN, [0x2e] = KEY_DOT, @@ -207,9 +207,9 @@ IR_KEYTAB_TYPE ir_codes_avermedia_cardbus[IR_KEYTAB_SIZE] = { [0x3e] = KEY_OK, /* Ok */ [0x3f] = KEY_RIGHT, [0x40] = KEY_NEXT, /* Next */ - [0x41] = KEY_PREVIOUS, /* Previous */ + [0x41] = KEY_PREVIOUS, /* Previous */ [0x42] = KEY_CHANNELDOWN, /* Channel down */ - [0x43] = KEY_CHANNELUP /* Channel up */ + [0x43] = KEY_CHANNELUP, /* Channel up */ }; EXPORT_SYMBOL_GPL(ir_codes_avermedia_cardbus); @@ -226,32 +226,32 @@ IR_KEYTAB_TYPE ir_codes_apac_viewcomp[IR_KEYTAB_SIZE] = { [0x08] = KEY_8, [0x09] = KEY_9, [0x00] = KEY_0, - [0x17] = KEY_LAST, /* +100 */ - [0x0a] = KEY_LIST, /* recall */ - - - [0x1c] = KEY_TUNER, /* TV/FM */ - [0x15] = KEY_SEARCH, /* scan */ - [0x12] = KEY_POWER, /* power */ - [0x1f] = KEY_VOLUMEDOWN, /* vol up */ - [0x1b] = KEY_VOLUMEUP, /* vol down */ - [0x1e] = KEY_CHANNELDOWN, /* chn up */ - [0x1a] = KEY_CHANNELUP, /* chn down */ - - [0x11] = KEY_VIDEO, /* video */ - [0x0f] = KEY_ZOOM, /* full screen */ - [0x13] = KEY_MUTE, /* mute/unmute */ - [0x10] = KEY_TEXT, /* min */ - - [0x0d] = KEY_STOP, /* freeze */ - [0x0e] = KEY_RECORD, /* record */ - [0x1d] = KEY_PLAYPAUSE, /* stop */ - [0x19] = KEY_PLAY, /* play */ - - [0x16] = KEY_GOTO, /* osd */ - [0x14] = KEY_REFRESH, /* default */ - [0x0c] = KEY_KPPLUS, /* fine tune >>>> */ - [0x18] = KEY_KPMINUS /* fine tune <<<< */ + [0x17] = KEY_LAST, /* +100 */ + [0x0a] = KEY_LIST, /* recall */ + + + [0x1c] = KEY_TUNER, /* TV/FM */ + [0x15] = KEY_SEARCH, /* scan */ + [0x12] = KEY_POWER, /* power */ + [0x1f] = KEY_VOLUMEDOWN, /* vol up */ + [0x1b] = KEY_VOLUMEUP, /* vol down */ + [0x1e] = KEY_CHANNELDOWN, /* chn up */ + [0x1a] = KEY_CHANNELUP, /* chn down */ + + [0x11] = KEY_VIDEO, /* video */ + [0x0f] = KEY_ZOOM, /* full screen */ + [0x13] = KEY_MUTE, /* mute/unmute */ + [0x10] = KEY_TEXT, /* min */ + + [0x0d] = KEY_STOP, /* freeze */ + [0x0e] = KEY_RECORD, /* record */ + [0x1d] = KEY_PLAYPAUSE, /* stop */ + [0x19] = KEY_PLAY, /* play */ + + [0x16] = KEY_GOTO, /* osd */ + [0x14] = KEY_REFRESH, /* default */ + [0x0c] = KEY_KPPLUS, /* fine tune >>>> */ + [0x18] = KEY_KPMINUS, /* fine tune <<<< */ }; EXPORT_SYMBOL_GPL(ir_codes_apac_viewcomp); @@ -260,9 +260,9 @@ EXPORT_SYMBOL_GPL(ir_codes_apac_viewcomp); IR_KEYTAB_TYPE ir_codes_pixelview[IR_KEYTAB_SIZE] = { - [0x1e] = KEY_POWER, /* power */ - [0x07] = KEY_MEDIA, /* source */ - [0x1c] = KEY_SEARCH, /* scan */ + [0x1e] = KEY_POWER, /* power */ + [0x07] = KEY_MEDIA, /* source */ + [0x1c] = KEY_SEARCH, /* scan */ #if 0 /* FIXME: duplicate keycodes? */ @@ -275,11 +275,11 @@ IR_KEYTAB_TYPE ir_codes_pixelview[IR_KEYTAB_SIZE] = { * 6384fb for "Tune <" and "<<<", * 638cfb for "Tune >" and ">>>", regardless of the mask. */ - [0x17] = KEY_BACK, /* fm scan << */ - [0x1f] = KEY_FORWARD, /* fm scan >> */ + [0x17] = KEY_BACK, /* fm scan << */ + [0x1f] = KEY_FORWARD, /* fm scan >> */ - [0x04] = KEY_LEFT, /* fm tuning < */ - [0x0c] = KEY_RIGHT, /* fm tuning > */ + [0x04] = KEY_LEFT, /* fm tuning < */ + [0x0c] = KEY_RIGHT, /* fm tuning > */ /* * For now, these four keys are disabled. Pressing them will generate @@ -287,15 +287,15 @@ IR_KEYTAB_TYPE ir_codes_pixelview[IR_KEYTAB_SIZE] = { */ #endif - [0x03] = KEY_TUNER, /* TV/FM */ + [0x03] = KEY_TUNER, /* TV/FM */ [0x00] = KEY_RECORD, [0x08] = KEY_STOP, [0x11] = KEY_PLAY, - [0x1a] = KEY_PLAYPAUSE, /* freeze */ - [0x19] = KEY_ZOOM, /* zoom */ - [0x0f] = KEY_TEXT, /* min */ + [0x1a] = KEY_PLAYPAUSE, /* freeze */ + [0x19] = KEY_ZOOM, /* zoom */ + [0x0f] = KEY_TEXT, /* min */ [0x01] = KEY_1, [0x0b] = KEY_2, @@ -307,21 +307,21 @@ IR_KEYTAB_TYPE ir_codes_pixelview[IR_KEYTAB_SIZE] = { [0x0a] = KEY_8, [0x12] = KEY_9, [0x02] = KEY_0, - [0x10] = KEY_LAST, /* +100 */ - [0x13] = KEY_LIST, /* recall */ + [0x10] = KEY_LAST, /* +100 */ + [0x13] = KEY_LIST, /* recall */ - [0x1f] = KEY_CHANNELUP, /* chn down */ - [0x17] = KEY_CHANNELDOWN, /* chn up */ - [0x16] = KEY_VOLUMEUP, /* vol down */ - [0x14] = KEY_VOLUMEDOWN, /* vol up */ + [0x1f] = KEY_CHANNELUP, /* chn down */ + [0x17] = KEY_CHANNELDOWN, /* chn up */ + [0x16] = KEY_VOLUMEUP, /* vol down */ + [0x14] = KEY_VOLUMEDOWN, /* vol up */ - [0x04] = KEY_KPMINUS, /* <<< */ - [0x0e] = KEY_SETUP, /* function */ - [0x0c] = KEY_KPPLUS, /* >>> */ + [0x04] = KEY_KPMINUS, /* <<< */ + [0x0e] = KEY_SETUP, /* function */ + [0x0c] = KEY_KPPLUS, /* >>> */ - [0x0d] = KEY_GOTO, /* mts */ - [0x1d] = KEY_REFRESH, /* reset */ - [0x18] = KEY_MUTE /* mute/unmute */ + [0x0d] = KEY_GOTO, /* mts */ + [0x1d] = KEY_REFRESH, /* reset */ + [0x18] = KEY_MUTE, /* mute/unmute */ }; EXPORT_SYMBOL_GPL(ir_codes_pixelview); @@ -426,7 +426,7 @@ IR_KEYTAB_TYPE ir_codes_nebula[IR_KEYTAB_SIZE] = { [0x33] = KEY_F19, /* web */ [0x34] = KEY_EMAIL, [0x35] = KEY_PHONE, - [0x36] = KEY_PC + [0x36] = KEY_PC, }; EXPORT_SYMBOL_GPL(ir_codes_nebula); @@ -482,7 +482,7 @@ IR_KEYTAB_TYPE ir_codes_iodata_bctv7e[IR_KEYTAB_SIZE] = { [0x00] = KEY_POWER, /* Keys 0 to 9 */ - [0x44] = KEY_0, /* 10 */ + [0x44] = KEY_0, /* 10 */ [0x50] = KEY_1, [0x30] = KEY_2, [0x70] = KEY_3, @@ -653,53 +653,53 @@ IR_KEYTAB_TYPE ir_codes_msi_tvanywhere_plus[IR_KEYTAB_SIZE] = { << FUNC >> RESET */ - [0x01] = KEY_KP1, /* 1 */ - [0x0b] = KEY_KP2, /* 2 */ - [0x1b] = KEY_KP3, /* 3 */ - [0x05] = KEY_KP4, /* 4 */ - [0x09] = KEY_KP5, /* 5 */ - [0x15] = KEY_KP6, /* 6 */ - [0x06] = KEY_KP7, /* 7 */ - [0x0a] = KEY_KP8, /* 8 */ - [0x12] = KEY_KP9, /* 9 */ - [0x02] = KEY_KP0, /* 0 */ - [0x10] = KEY_KPPLUS, /* + */ - [0x13] = KEY_AGAIN, /* Recall */ - - [0x1e] = KEY_POWER, /* Power */ - [0x07] = KEY_TUNER, /* Source */ - [0x1c] = KEY_SEARCH, /* Scan */ - [0x18] = KEY_MUTE, /* Mute */ - - [0x03] = KEY_RADIO, /* TV/FM */ + [0x01] = KEY_KP1, /* 1 */ + [0x0b] = KEY_KP2, /* 2 */ + [0x1b] = KEY_KP3, /* 3 */ + [0x05] = KEY_KP4, /* 4 */ + [0x09] = KEY_KP5, /* 5 */ + [0x15] = KEY_KP6, /* 6 */ + [0x06] = KEY_KP7, /* 7 */ + [0x0a] = KEY_KP8, /* 8 */ + [0x12] = KEY_KP9, /* 9 */ + [0x02] = KEY_KP0, /* 0 */ + [0x10] = KEY_KPPLUS, /* + */ + [0x13] = KEY_AGAIN, /* Recall */ + + [0x1e] = KEY_POWER, /* Power */ + [0x07] = KEY_TUNER, /* Source */ + [0x1c] = KEY_SEARCH, /* Scan */ + [0x18] = KEY_MUTE, /* Mute */ + + [0x03] = KEY_RADIO, /* TV/FM */ /* The next four keys are duplicates that appear to send the same IR code as Ch+, Ch-, >>, and << . The raw code assigned to them is the actual code + 0x20 - they will never be detected as such unless some way is discovered to distinguish these buttons from those that have the same code. */ - [0x3f] = KEY_RIGHT, /* |> and Ch+ */ - [0x37] = KEY_LEFT, /* <| and Ch- */ - [0x2c] = KEY_UP, /* ^^Up and >> */ - [0x24] = KEY_DOWN, /* vvDn and << */ - - [0x00] = KEY_RECORD, /* Record */ - [0x08] = KEY_STOP, /* Stop */ - [0x11] = KEY_PLAY, /* Play */ - - [0x0f] = KEY_CLOSE, /* Minimize */ - [0x19] = KEY_ZOOM, /* Zoom */ - [0x1a] = KEY_SHUFFLE, /* Snapshot */ - [0x0d] = KEY_LANGUAGE, /* MTS */ - - [0x14] = KEY_VOLUMEDOWN, /* Vol- */ - [0x16] = KEY_VOLUMEUP, /* Vol+ */ - [0x17] = KEY_CHANNELDOWN, /* Ch- */ - [0x1f] = KEY_CHANNELUP, /* Ch+ */ - - [0x04] = KEY_REWIND, /* << */ - [0x0e] = KEY_MENU, /* Function */ - [0x0c] = KEY_FASTFORWARD, /* >> */ - [0x1d] = KEY_RESTART, /* Reset */ + [0x3f] = KEY_RIGHT, /* |> and Ch+ */ + [0x37] = KEY_LEFT, /* <| and Ch- */ + [0x2c] = KEY_UP, /* ^^Up and >> */ + [0x24] = KEY_DOWN, /* vvDn and << */ + + [0x00] = KEY_RECORD, /* Record */ + [0x08] = KEY_STOP, /* Stop */ + [0x11] = KEY_PLAY, /* Play */ + + [0x0f] = KEY_CLOSE, /* Minimize */ + [0x19] = KEY_ZOOM, /* Zoom */ + [0x1a] = KEY_SHUFFLE, /* Snapshot */ + [0x0d] = KEY_LANGUAGE, /* MTS */ + + [0x14] = KEY_VOLUMEDOWN,/* Vol- */ + [0x16] = KEY_VOLUMEUP, /* Vol+ */ + [0x17] = KEY_CHANNELDOWN,/* Ch- */ + [0x1f] = KEY_CHANNELUP, /* Ch+ */ + + [0x04] = KEY_REWIND, /* << */ + [0x0e] = KEY_MENU, /* Function */ + [0x0c] = KEY_FASTFORWARD,/* >> */ + [0x1d] = KEY_RESTART, /* Reset */ }; EXPORT_SYMBOL_GPL(ir_codes_msi_tvanywhere_plus); @@ -843,9 +843,9 @@ IR_KEYTAB_TYPE ir_codes_dntv_live_dvbt_pro[IR_KEYTAB_SIZE] = { [0x40] = KEY_REWIND, [0x12] = KEY_FASTFORWARD, [0x41] = KEY_PREVIOUSSONG, /* replay |< */ - [0x42] = KEY_NEXTSONG, /* skip >| */ + [0x42] = KEY_NEXTSONG, /* skip >| */ [0x54] = KEY_CAMERA, /* capture */ - [0x50] = KEY_LANGUAGE, /* sap */ + [0x50] = KEY_LANGUAGE, /* sap */ [0x47] = KEY_TV2, /* pip */ [0x4d] = KEY_SCREEN, [0x43] = KEY_SUBTITLE, @@ -853,7 +853,7 @@ IR_KEYTAB_TYPE ir_codes_dntv_live_dvbt_pro[IR_KEYTAB_SIZE] = { [0x49] = KEY_AUDIO, /* l/r */ [0x07] = KEY_SLEEP, [0x08] = KEY_VIDEO, /* a/v */ - [0x0e] = KEY_PREVIOUS, /* recall */ + [0x0e] = KEY_PREVIOUS, /* recall */ [0x45] = KEY_ZOOM, /* zoom + */ [0x46] = KEY_ANGLE, /* zoom - */ [0x56] = KEY_RED, @@ -962,24 +962,24 @@ IR_KEYTAB_TYPE ir_codes_flyvideo[IR_KEYTAB_SIZE] = { [0x0c] = KEY_8, [0x0d] = KEY_9, - [0x0e] = KEY_MODE, /* Air/Cable */ - [0x11] = KEY_VIDEO, /* Video */ - [0x15] = KEY_AUDIO, /* Audio */ - [0x00] = KEY_POWER, /* Power */ - [0x18] = KEY_TUNER, /* AV Source */ - [0x02] = KEY_ZOOM, /* Fullscreen */ - [0x1a] = KEY_LANGUAGE, /* Stereo */ - [0x1b] = KEY_MUTE, /* Mute */ - [0x14] = KEY_VOLUMEUP, /* Volume + */ - [0x17] = KEY_VOLUMEDOWN, /* Volume - */ - [0x12] = KEY_CHANNELUP, /* Channel + */ - [0x13] = KEY_CHANNELDOWN, /* Channel - */ - [0x06] = KEY_AGAIN, /* Recall */ - [0x10] = KEY_ENTER, /* Enter */ - - [0x19] = KEY_BACK, /* Rewind ( <<< ) */ - [0x1f] = KEY_FORWARD, /* Forward ( >>> ) */ - [0x0a] = KEY_ANGLE, /* (no label, may be used as the PAUSE button) */ + [0x0e] = KEY_MODE, /* Air/Cable */ + [0x11] = KEY_VIDEO, /* Video */ + [0x15] = KEY_AUDIO, /* Audio */ + [0x00] = KEY_POWER, /* Power */ + [0x18] = KEY_TUNER, /* AV Source */ + [0x02] = KEY_ZOOM, /* Fullscreen */ + [0x1a] = KEY_LANGUAGE, /* Stereo */ + [0x1b] = KEY_MUTE, /* Mute */ + [0x14] = KEY_VOLUMEUP, /* Volume + */ + [0x17] = KEY_VOLUMEDOWN,/* Volume - */ + [0x12] = KEY_CHANNELUP, /* Channel + */ + [0x13] = KEY_CHANNELDOWN,/* Channel - */ + [0x06] = KEY_AGAIN, /* Recall */ + [0x10] = KEY_ENTER, /* Enter */ + + [0x19] = KEY_BACK, /* Rewind ( <<< ) */ + [0x1f] = KEY_FORWARD, /* Forward ( >>> ) */ + [0x0a] = KEY_ANGLE, /* no label, may be used as the PAUSE button */ }; EXPORT_SYMBOL_GPL(ir_codes_flyvideo); @@ -1038,15 +1038,15 @@ IR_KEYTAB_TYPE ir_codes_cinergy[IR_KEYTAB_SIZE] = { [0x09] = KEY_9, [0x0a] = KEY_POWER, - [0x0b] = KEY_PROG1, /* app */ - [0x0c] = KEY_ZOOM, /* zoom/fullscreen */ - [0x0d] = KEY_CHANNELUP, /* channel */ - [0x0e] = KEY_CHANNELDOWN, /* channel- */ + [0x0b] = KEY_PROG1, /* app */ + [0x0c] = KEY_ZOOM, /* zoom/fullscreen */ + [0x0d] = KEY_CHANNELUP, /* channel */ + [0x0e] = KEY_CHANNELDOWN,/* channel- */ [0x0f] = KEY_VOLUMEUP, [0x10] = KEY_VOLUMEDOWN, - [0x11] = KEY_TUNER, /* AV */ - [0x12] = KEY_NUMLOCK, /* -/-- */ - [0x13] = KEY_AUDIO, /* audio */ + [0x11] = KEY_TUNER, /* AV */ + [0x12] = KEY_NUMLOCK, /* -/-- */ + [0x13] = KEY_AUDIO, /* audio */ [0x14] = KEY_MUTE, [0x15] = KEY_UP, [0x16] = KEY_DOWN, @@ -1054,7 +1054,7 @@ IR_KEYTAB_TYPE ir_codes_cinergy[IR_KEYTAB_SIZE] = { [0x18] = KEY_RIGHT, [0x19] = BTN_LEFT, [0x1a] = BTN_RIGHT, - [0x1b] = KEY_WWW, /* text */ + [0x1b] = KEY_WWW, /* text */ [0x1c] = KEY_REWIND, [0x1d] = KEY_FORWARD, [0x1e] = KEY_RECORD, @@ -1071,38 +1071,38 @@ EXPORT_SYMBOL_GPL(ir_codes_cinergy); * updates from Job D. R. Borges */ IR_KEYTAB_TYPE ir_codes_eztv[IR_KEYTAB_SIZE] = { [0x12] = KEY_POWER, - [0x01] = KEY_TV, /* DVR */ - [0x15] = KEY_DVD, /* DVD */ - [0x17] = KEY_AUDIO, /* music */ - /* DVR mode / DVD mode / music mode */ - - [0x1b] = KEY_MUTE, /* mute */ - [0x02] = KEY_LANGUAGE, /* MTS/SAP / audio / autoseek */ - [0x1e] = KEY_SUBTITLE, /* closed captioning / subtitle / seek */ - [0x16] = KEY_ZOOM, /* full screen */ - [0x1c] = KEY_VIDEO, /* video source / eject / delall */ - [0x1d] = KEY_RESTART, /* playback / angle / del */ - [0x2f] = KEY_SEARCH, /* scan / menu / playlist */ - [0x30] = KEY_CHANNEL, /* CH surfing / bookmark / memo */ - - [0x31] = KEY_HELP, /* help */ - [0x32] = KEY_MODE, /* num/memo */ - [0x33] = KEY_ESC, /* cancel */ - - [0x0c] = KEY_UP, /* up */ - [0x10] = KEY_DOWN, /* down */ - [0x08] = KEY_LEFT, /* left */ - [0x04] = KEY_RIGHT, /* right */ - [0x03] = KEY_SELECT, /* select */ - - [0x1f] = KEY_REWIND, /* rewind */ - [0x20] = KEY_PLAYPAUSE, /* play/pause */ - [0x29] = KEY_FORWARD, /* forward */ - [0x14] = KEY_AGAIN, /* repeat */ - [0x2b] = KEY_RECORD, /* recording */ - [0x2c] = KEY_STOP, /* stop */ - [0x2d] = KEY_PLAY, /* play */ - [0x2e] = KEY_SHUFFLE, /* snapshot / shuffle */ + [0x01] = KEY_TV, /* DVR */ + [0x15] = KEY_DVD, /* DVD */ + [0x17] = KEY_AUDIO, /* music */ + /* DVR mode / DVD mode / music mode */ + + [0x1b] = KEY_MUTE, /* mute */ + [0x02] = KEY_LANGUAGE, /* MTS/SAP / audio / autoseek */ + [0x1e] = KEY_SUBTITLE, /* closed captioning / subtitle / seek */ + [0x16] = KEY_ZOOM, /* full screen */ + [0x1c] = KEY_VIDEO, /* video source / eject / delall */ + [0x1d] = KEY_RESTART, /* playback / angle / del */ + [0x2f] = KEY_SEARCH, /* scan / menu / playlist */ + [0x30] = KEY_CHANNEL, /* CH surfing / bookmark / memo */ + + [0x31] = KEY_HELP, /* help */ + [0x32] = KEY_MODE, /* num/memo */ + [0x33] = KEY_ESC, /* cancel */ + + [0x0c] = KEY_UP, /* up */ + [0x10] = KEY_DOWN, /* down */ + [0x08] = KEY_LEFT, /* left */ + [0x04] = KEY_RIGHT, /* right */ + [0x03] = KEY_SELECT, /* select */ + + [0x1f] = KEY_REWIND, /* rewind */ + [0x20] = KEY_PLAYPAUSE, /* play/pause */ + [0x29] = KEY_FORWARD, /* forward */ + [0x14] = KEY_AGAIN, /* repeat */ + [0x2b] = KEY_RECORD, /* recording */ + [0x2c] = KEY_STOP, /* stop */ + [0x2d] = KEY_PLAY, /* play */ + [0x2e] = KEY_SHUFFLE, /* snapshot / shuffle */ [0x00] = KEY_0, [0x05] = KEY_1, @@ -1117,11 +1117,11 @@ IR_KEYTAB_TYPE ir_codes_eztv[IR_KEYTAB_SIZE] = { [0x2a] = KEY_VOLUMEUP, [0x11] = KEY_VOLUMEDOWN, - [0x18] = KEY_CHANNELUP, /* CH.tracking up */ - [0x19] = KEY_CHANNELDOWN, /* CH.tracking down */ + [0x18] = KEY_CHANNELUP, /* CH.tracking up */ + [0x19] = KEY_CHANNELDOWN,/* CH.tracking down */ - [0x13] = KEY_ENTER, /* enter */ - [0x21] = KEY_DOT, /* . (decimal dot) */ + [0x13] = KEY_ENTER, /* enter */ + [0x21] = KEY_DOT, /* . (decimal dot) */ }; EXPORT_SYMBOL_GPL(ir_codes_eztv); @@ -1148,7 +1148,7 @@ IR_KEYTAB_TYPE ir_codes_avermedia[IR_KEYTAB_SIZE] = { [0x04] = KEY_AUDIO, /* AUDIO */ [0x0c] = KEY_ZOOM, /* FULL SCREEN */ - [0x12] = KEY_SUBTITLE, /* DISPLAY */ + [0x12] = KEY_SUBTITLE, /* DISPLAY */ [0x32] = KEY_REWIND, /* LOOP */ [0x02] = KEY_PRINT, /* PREVIEW */ @@ -1168,9 +1168,9 @@ IR_KEYTAB_TYPE ir_codes_avermedia[IR_KEYTAB_SIZE] = { [0x01] = KEY_BLUE, /* BLUE */ [0x1e] = KEY_VOLUMEDOWN, /* VOLUME- */ - [0x3e] = KEY_VOLUMEUP, /* VOLUME+ */ + [0x3e] = KEY_VOLUMEUP, /* VOLUME+ */ [0x11] = KEY_CHANNELDOWN, /* CHANNEL/PAGE- */ - [0x31] = KEY_CHANNELUP /* CHANNEL/PAGE+ */ + [0x31] = KEY_CHANNELUP /* CHANNEL/PAGE+ */ }; EXPORT_SYMBOL_GPL(ir_codes_avermedia); @@ -1297,7 +1297,7 @@ IR_KEYTAB_TYPE ir_codes_manli[IR_KEYTAB_SIZE] = { * SOURCE STEREO * * */ [0x11] = KEY_TV, /*XXX*/ - [0x0d] = KEY_MODE, /*XXX there's no KEY_STEREO */ + [0x0d] = KEY_MODE, /*XXX there's no KEY_STEREO */ /* 0x0f 0x1b 0x1a * * AUDIO Vol+ Chan+ * @@ -1309,7 +1309,7 @@ IR_KEYTAB_TYPE ir_codes_manli[IR_KEYTAB_SIZE] = { [0x0f] = KEY_AUDIO, [0x1b] = KEY_VOLUMEUP, [0x1a] = KEY_CHANNELUP, - [0x0e] = KEY_SLEEP, /*XXX maybe KEY_PAUSE */ + [0x0e] = KEY_SLEEP, /*XXX maybe KEY_PAUSE */ [0x1f] = KEY_VOLUMEDOWN, [0x1e] = KEY_CHANNELDOWN, @@ -1339,29 +1339,29 @@ IR_KEYTAB_TYPE ir_codes_gotview7135[IR_KEYTAB_SIZE] = { [0x24] = KEY_7, [0x18] = KEY_8, [0x2b] = KEY_9, - [0x3b] = KEY_AGAIN, /* LOOP */ + [0x3b] = KEY_AGAIN, /* LOOP */ [0x06] = KEY_AUDIO, - [0x31] = KEY_PRINT, /* PREVIEW */ + [0x31] = KEY_PRINT, /* PREVIEW */ [0x3e] = KEY_VIDEO, [0x10] = KEY_CHANNELUP, [0x20] = KEY_CHANNELDOWN, [0x0c] = KEY_VOLUMEDOWN, [0x28] = KEY_VOLUMEUP, [0x08] = KEY_MUTE, - [0x26] = KEY_SEARCH, /*SCAN*/ - [0x3f] = KEY_SHUFFLE, /* SNAPSHOT */ + [0x26] = KEY_SEARCH, /*SCAN*/ + [0x3f] = KEY_SHUFFLE, /* SNAPSHOT */ [0x12] = KEY_RECORD, [0x32] = KEY_STOP, [0x3c] = KEY_PLAY, [0x1d] = KEY_REWIND, [0x2d] = KEY_PAUSE, [0x0d] = KEY_FORWARD, - [0x05] = KEY_ZOOM, /*FULL*/ + [0x05] = KEY_ZOOM, /*FULL*/ - [0x2a] = KEY_F21, /* LIVE TIMESHIFT */ - [0x0e] = KEY_F22, /* MIN TIMESHIFT */ - [0x1e] = KEY_F23, /* TIMESHIFT */ - [0x38] = KEY_F24, /* NORMAL TIMESHIFT */ + [0x2a] = KEY_F21, /* LIVE TIMESHIFT */ + [0x0e] = KEY_F22, /* MIN TIMESHIFT */ + [0x1e] = KEY_F23, /* TIMESHIFT */ + [0x38] = KEY_F24, /* NORMAL TIMESHIFT */ }; EXPORT_SYMBOL_GPL(ir_codes_gotview7135); @@ -1369,7 +1369,7 @@ EXPORT_SYMBOL_GPL(ir_codes_gotview7135); IR_KEYTAB_TYPE ir_codes_purpletv[IR_KEYTAB_SIZE] = { [0x03] = KEY_POWER, [0x6f] = KEY_MUTE, - [0x10] = KEY_BACKSPACE, /* Recall */ + [0x10] = KEY_BACKSPACE, /* Recall */ [0x11] = KEY_0, [0x04] = KEY_1, @@ -1381,7 +1381,7 @@ IR_KEYTAB_TYPE ir_codes_purpletv[IR_KEYTAB_SIZE] = { [0x0c] = KEY_7, [0x0d] = KEY_8, [0x0e] = KEY_9, - [0x12] = KEY_DOT, /* 100+ */ + [0x12] = KEY_DOT, /* 100+ */ [0x07] = KEY_VOLUMEUP, [0x0b] = KEY_VOLUMEDOWN, @@ -1393,25 +1393,25 @@ IR_KEYTAB_TYPE ir_codes_purpletv[IR_KEYTAB_SIZE] = { [0x13] = KEY_CHANNELDOWN, [0x48] = KEY_ZOOM, - [0x1b] = KEY_VIDEO, /* Video source */ + [0x1b] = KEY_VIDEO, /* Video source */ #if 0 - [0x1f] = KEY_S, /* Snapshot */ + [0x1f] = KEY_S, /* Snapshot */ #endif - [0x49] = KEY_LANGUAGE, /* MTS Select */ - [0x19] = KEY_SEARCH, /* Auto Scan */ + [0x49] = KEY_LANGUAGE, /* MTS Select */ + [0x19] = KEY_SEARCH, /* Auto Scan */ [0x4b] = KEY_RECORD, [0x46] = KEY_PLAY, - [0x45] = KEY_PAUSE, /* Pause */ + [0x45] = KEY_PAUSE, /* Pause */ [0x44] = KEY_STOP, #if 0 - [0x43] = KEY_T, /* Time Shift */ - [0x47] = KEY_Y, /* Time Shift OFF */ - [0x4a] = KEY_O, /* TOP */ - [0x17] = KEY_F, /* SURF CH */ + [0x43] = KEY_T, /* Time Shift */ + [0x47] = KEY_Y, /* Time Shift OFF */ + [0x4a] = KEY_O, /* TOP */ + [0x17] = KEY_F, /* SURF CH */ #endif - [0x40] = KEY_FORWARD, /* Forward ? */ - [0x42] = KEY_REWIND, /* Backward ? */ + [0x40] = KEY_FORWARD, /* Forward ? */ + [0x42] = KEY_REWIND, /* Backward ? */ }; @@ -1433,29 +1433,29 @@ IR_KEYTAB_TYPE ir_codes_pctv_sedna[IR_KEYTAB_SIZE] = { [0x08] = KEY_8, [0x09] = KEY_9, - [0x0a] = KEY_AGAIN, /* Recall */ + [0x0a] = KEY_AGAIN, /* Recall */ [0x0b] = KEY_CHANNELUP, [0x0c] = KEY_VOLUMEUP, - [0x0d] = KEY_MODE, /* Stereo */ + [0x0d] = KEY_MODE, /* Stereo */ [0x0e] = KEY_STOP, [0x0f] = KEY_PREVIOUSSONG, [0x10] = KEY_ZOOM, - [0x11] = KEY_TUNER, /* Source */ + [0x11] = KEY_TUNER, /* Source */ [0x12] = KEY_POWER, [0x13] = KEY_MUTE, [0x15] = KEY_CHANNELDOWN, [0x18] = KEY_VOLUMEDOWN, - [0x19] = KEY_SHUFFLE, /* Snapshot */ + [0x19] = KEY_SHUFFLE, /* Snapshot */ [0x1a] = KEY_NEXTSONG, - [0x1b] = KEY_TEXT, /* Time Shift */ - [0x1c] = KEY_RADIO, /* FM Radio */ + [0x1b] = KEY_TEXT, /* Time Shift */ + [0x1c] = KEY_RADIO, /* FM Radio */ [0x1d] = KEY_RECORD, [0x1e] = KEY_PAUSE, /* additional codes for Kozumi's remote */ - [0x14] = KEY_INFO, /* OSD */ - [0x16] = KEY_OK, /* OK */ - [0x17] = KEY_DIGITS, /* Plus */ - [0x1f] = KEY_PLAY, /* Play */ + [0x14] = KEY_INFO, /* OSD */ + [0x16] = KEY_OK, /* OK */ + [0x17] = KEY_DIGITS, /* Plus */ + [0x1f] = KEY_PLAY, /* Play */ }; EXPORT_SYMBOL_GPL(ir_codes_pctv_sedna); @@ -1489,14 +1489,14 @@ IR_KEYTAB_TYPE ir_codes_pv951[IR_KEYTAB_SIZE] = { [0x0b] = KEY_TV, /* AIR/CBL */ [0x11] = KEY_PC, /* PC/TV */ [0x17] = KEY_OK, /* CH RTN */ - [0x19] = KEY_MODE, /* FUNC */ - [0x0c] = KEY_SEARCH, /* AUTOSCAN */ + [0x19] = KEY_MODE, /* FUNC */ + [0x0c] = KEY_SEARCH, /* AUTOSCAN */ /* Not sure what to do with these ones! */ - [0x0f] = KEY_SELECT, /* SOURCE */ + [0x0f] = KEY_SELECT, /* SOURCE */ [0x0a] = KEY_KPPLUS, /* +100 */ [0x14] = KEY_EQUAL, /* SYNC */ - [0x1c] = KEY_MEDIA, /* PC/TV */ + [0x1c] = KEY_MEDIA, /* PC/TV */ }; EXPORT_SYMBOL_GPL(ir_codes_pv951); @@ -1526,10 +1526,10 @@ IR_KEYTAB_TYPE ir_codes_rc5_tv[IR_KEYTAB_SIZE] = { [0x12] = KEY_BRIGHTNESSUP, [0x13] = KEY_BRIGHTNESSDOWN, [0x1e] = KEY_SEARCH, /* search + */ - [0x20] = KEY_CHANNELUP, /* channel / program + */ + [0x20] = KEY_CHANNELUP, /* channel / program + */ [0x21] = KEY_CHANNELDOWN, /* channel / program - */ [0x22] = KEY_CHANNEL, /* alt / channel */ - [0x23] = KEY_LANGUAGE, /* 1st / 2nd language */ + [0x23] = KEY_LANGUAGE, /* 1st / 2nd language */ [0x26] = KEY_SLEEP, /* sleeptimer */ [0x2e] = KEY_MENU, /* 2nd controls (USA: menu) */ [0x30] = KEY_PAUSE, @@ -1538,41 +1538,41 @@ IR_KEYTAB_TYPE ir_codes_rc5_tv[IR_KEYTAB_SIZE] = { [0x35] = KEY_PLAY, [0x36] = KEY_STOP, [0x37] = KEY_RECORD, /* recording */ - [0x3c] = KEY_TEXT, /* teletext submode (Japan: 12) */ + [0x3c] = KEY_TEXT, /* teletext submode (Japan: 12) */ [0x3d] = KEY_SUSPEND, /* system standby */ #if 0 /* FIXME */ - [0x0a] = KEY_RESERVED, /* 1/2/3 digits (japan: 10) */ - [0x0e] = KEY_RESERVED, /* P.P. (personal preference) */ - [0x14] = KEY_RESERVED, /* colour saturation + */ - [0x15] = KEY_RESERVED, /* colour saturation - */ - [0x16] = KEY_RESERVED, /* bass + */ - [0x17] = KEY_RESERVED, /* bass - */ - [0x18] = KEY_RESERVED, /* treble + */ - [0x19] = KEY_RESERVED, /* treble - */ - [0x1a] = KEY_RESERVED, /* balance right */ - [0x1b] = KEY_RESERVED, /* balance left */ - [0x1c] = KEY_RESERVED, /* contrast + */ - [0x1d] = KEY_RESERVED, /* contrast - */ - [0x1f] = KEY_RESERVED, /* tint/hue + */ - [0x24] = KEY_RESERVED, /* spacial stereo on/off */ - [0x25] = KEY_RESERVED, /* mono / stereo (USA) */ - [0x27] = KEY_RESERVED, /* tint / hue - */ - [0x28] = KEY_RESERVED, /* RF switch/PIP select */ - [0x29] = KEY_RESERVED, /* vote */ - [0x2a] = KEY_RESERVED, /* timed page/channel clck */ - [0x2b] = KEY_RESERVED, /* increment (USA) */ - [0x2c] = KEY_RESERVED, /* decrement (USA) */ - [0x2d] = KEY_RESERVED, /* */ - [0x2f] = KEY_RESERVED, /* PIP shift */ - [0x31] = KEY_RESERVED, /* erase */ - [0x34] = KEY_RESERVED, /* wind */ - [0x38] = KEY_RESERVED, /* external 1 */ - [0x39] = KEY_RESERVED, /* external 2 */ - [0x3a] = KEY_RESERVED, /* PIP display mode */ - [0x3b] = KEY_RESERVED, /* view data mode / advance */ - [0x3e] = KEY_RESERVED, /* crispener on/off */ - [0x3f] = KEY_RESERVED, /* system select */ + [0x0a] = KEY_RESERVED, /* 1/2/3 digits (japan: 10) */ + [0x0e] = KEY_RESERVED, /* P.P. (personal preference) */ + [0x14] = KEY_RESERVED, /* colour saturation + */ + [0x15] = KEY_RESERVED, /* colour saturation - */ + [0x16] = KEY_RESERVED, /* bass + */ + [0x17] = KEY_RESERVED, /* bass - */ + [0x18] = KEY_RESERVED, /* treble + */ + [0x19] = KEY_RESERVED, /* treble - */ + [0x1a] = KEY_RESERVED, /* balance right */ + [0x1b] = KEY_RESERVED, /* balance left */ + [0x1c] = KEY_RESERVED, /* contrast + */ + [0x1d] = KEY_RESERVED, /* contrast - */ + [0x1f] = KEY_RESERVED, /* tint/hue + */ + [0x24] = KEY_RESERVED, /* spacial stereo on/off */ + [0x25] = KEY_RESERVED, /* mono / stereo (USA) */ + [0x27] = KEY_RESERVED, /* tint / hue - */ + [0x28] = KEY_RESERVED, /* RF switch/PIP select */ + [0x29] = KEY_RESERVED, /* vote */ + [0x2a] = KEY_RESERVED, /* timed page/channel clck */ + [0x2b] = KEY_RESERVED, /* increment (USA) */ + [0x2c] = KEY_RESERVED, /* decrement (USA) */ + [0x2d] = KEY_RESERVED, /* */ + [0x2f] = KEY_RESERVED, /* PIP shift */ + [0x31] = KEY_RESERVED, /* erase */ + [0x34] = KEY_RESERVED, /* wind */ + [0x38] = KEY_RESERVED, /* external 1 */ + [0x39] = KEY_RESERVED, /* external 2 */ + [0x3a] = KEY_RESERVED, /* PIP display mode */ + [0x3b] = KEY_RESERVED, /* view data mode / advance */ + [0x3e] = KEY_RESERVED, /* crispener on/off */ + [0x3f] = KEY_RESERVED, /* system select */ #endif }; @@ -1593,10 +1593,10 @@ IR_KEYTAB_TYPE ir_codes_winfast[IR_KEYTAB_SIZE] = { [0x0f] = KEY_9, [0x00] = KEY_POWER, - [0x1b] = KEY_AUDIO, /* Audio Source */ + [0x1b] = KEY_AUDIO, /* Audio Source */ [0x02] = KEY_TUNER, /* TV/FM, not on Y0400052 */ - [0x1e] = KEY_VIDEO, /* Video Source */ - [0x16] = KEY_INFO, /* Display information */ + [0x1e] = KEY_VIDEO, /* Video Source */ + [0x16] = KEY_INFO, /* Display information */ [0x04] = KEY_VOLUMEUP, [0x08] = KEY_VOLUMEDOWN, [0x0c] = KEY_CHANNELUP, @@ -1604,7 +1604,7 @@ IR_KEYTAB_TYPE ir_codes_winfast[IR_KEYTAB_SIZE] = { [0x03] = KEY_ZOOM, /* fullscreen */ [0x1f] = KEY_TEXT, /* closed caption/teletext */ [0x20] = KEY_SLEEP, - [0x29] = KEY_CLEAR, /* boss key */ + [0x29] = KEY_CLEAR, /* boss key */ [0x14] = KEY_MUTE, [0x2b] = KEY_RED, [0x2c] = KEY_GREEN, @@ -1612,32 +1612,32 @@ IR_KEYTAB_TYPE ir_codes_winfast[IR_KEYTAB_SIZE] = { [0x2e] = KEY_BLUE, [0x18] = KEY_KPPLUS, /* fine tune + , not on Y040052 */ [0x19] = KEY_KPMINUS, /* fine tune - , not on Y040052 */ - [0x2a] = KEY_MEDIA, /* PIP (Picture in picture */ + [0x2a] = KEY_MEDIA, /* PIP (Picture in picture */ [0x21] = KEY_DOT, [0x13] = KEY_ENTER, - [0x11] = KEY_LAST, /* Recall (last channel */ + [0x11] = KEY_LAST, /* Recall (last channel */ [0x22] = KEY_PREVIOUS, [0x23] = KEY_PLAYPAUSE, [0x24] = KEY_NEXT, - [0x25] = KEY_ARCHIVE, /* Time Shifting */ + [0x25] = KEY_ARCHIVE, /* Time Shifting */ [0x26] = KEY_STOP, [0x27] = KEY_RECORD, - [0x28] = KEY_SAVE, /* Screenshot */ + [0x28] = KEY_SAVE, /* Screenshot */ [0x2f] = KEY_MENU, [0x30] = KEY_CANCEL, - [0x31] = KEY_CHANNEL, /* Channel Surf */ + [0x31] = KEY_CHANNEL, /* Channel Surf */ [0x32] = KEY_SUBTITLE, [0x33] = KEY_LANGUAGE, [0x34] = KEY_REWIND, [0x35] = KEY_FASTFORWARD, [0x36] = KEY_TV, - [0x37] = KEY_RADIO, /* FM */ + [0x37] = KEY_RADIO, /* FM */ [0x38] = KEY_DVD, - [0x3e] = KEY_F21, /* MCE +VOL, on Y04G0033 */ - [0x3a] = KEY_F22, /* MCE -VOL, on Y04G0033 */ - [0x3b] = KEY_F23, /* MCE +CH, on Y04G0033 */ - [0x3f] = KEY_F24 /* MCE -CH, on Y04G0033 */ + [0x3e] = KEY_F21, /* MCE +VOL, on Y04G0033 */ + [0x3a] = KEY_F22, /* MCE -VOL, on Y04G0033 */ + [0x3b] = KEY_F23, /* MCE +CH, on Y04G0033 */ + [0x3f] = KEY_F24 /* MCE -CH, on Y04G0033 */ }; EXPORT_SYMBOL_GPL(ir_codes_winfast); @@ -1718,15 +1718,15 @@ IR_KEYTAB_TYPE ir_codes_hauppauge_new[IR_KEYTAB_SIZE] = { [0x08] = KEY_8, [0x09] = KEY_9, - [0x0a] = KEY_TEXT, /* keypad asterisk as well */ + [0x0a] = KEY_TEXT, /* keypad asterisk as well */ [0x0b] = KEY_RED, /* red button */ [0x0c] = KEY_RADIO, [0x0d] = KEY_MENU, - [0x0e] = KEY_SUBTITLE, /* also the # key */ + [0x0e] = KEY_SUBTITLE, /* also the # key */ [0x0f] = KEY_MUTE, [0x10] = KEY_VOLUMEUP, [0x11] = KEY_VOLUMEDOWN, - [0x12] = KEY_PREVIOUS, /* previous channel */ + [0x12] = KEY_PREVIOUS, /* previous channel */ [0x14] = KEY_UP, [0x15] = KEY_DOWN, [0x16] = KEY_LEFT, @@ -1741,9 +1741,9 @@ IR_KEYTAB_TYPE ir_codes_hauppauge_new[IR_KEYTAB_SIZE] = { [0x1b] = KEY_EPG, /* Guide */ [0x1c] = KEY_TV, - [0x1e] = KEY_NEXTSONG, /* skip >| */ + [0x1e] = KEY_NEXTSONG, /* skip >| */ [0x1f] = KEY_EXIT, /* back/exit */ - [0x20] = KEY_CHANNELUP, /* channel / program + */ + [0x20] = KEY_CHANNELUP, /* channel / program + */ [0x21] = KEY_CHANNELDOWN, /* channel / program - */ [0x22] = KEY_CHANNEL, /* source (old black remote) */ [0x24] = KEY_PREVIOUSSONG, /* replay |< */ @@ -1766,7 +1766,7 @@ IR_KEYTAB_TYPE ir_codes_hauppauge_new[IR_KEYTAB_SIZE] = { EXPORT_SYMBOL_GPL(ir_codes_hauppauge_new); IR_KEYTAB_TYPE ir_codes_npgtech[IR_KEYTAB_SIZE] = { - [0x1d] = KEY_SWITCHVIDEOMODE, /* switch inputs */ + [0x1d] = KEY_SWITCHVIDEOMODE, /* switch inputs */ [0x2a] = KEY_FRONT, [0x3e] = KEY_1, @@ -1779,7 +1779,7 @@ IR_KEYTAB_TYPE ir_codes_npgtech[IR_KEYTAB_SIZE] = { [0x1a] = KEY_8, [0x1e] = KEY_9, [0x3a] = KEY_0, - [0x22] = KEY_NUMLOCK, /* -/-- */ + [0x22] = KEY_NUMLOCK, /* -/-- */ [0x20] = KEY_REFRESH, [0x03] = KEY_BRIGHTNESSDOWN, @@ -1800,8 +1800,8 @@ IR_KEYTAB_TYPE ir_codes_npgtech[IR_KEYTAB_SIZE] = { [0x14] = KEY_REWIND, [0x33] = KEY_ZOOM, [0x32] = KEY_KEYBOARD, - [0x30] = KEY_GOTO, /* Pointing arrow */ - [0x36] = KEY_MACRO, /* Maximize/Minimize (yellow) */ + [0x30] = KEY_GOTO, /* Pointing arrow */ + [0x36] = KEY_MACRO, /* Maximize/Minimize (yellow) */ [0x0b] = KEY_RADIO, [0x10] = KEY_POWER, @@ -1825,34 +1825,34 @@ IR_KEYTAB_TYPE ir_codes_norwood[IR_KEYTAB_SIZE] = { [0x28] = KEY_8, [0x29] = KEY_9, - [0x78] = KEY_TUNER, /* Video Source */ - [0x2c] = KEY_EXIT, /* Open/Close software */ - [0x2a] = KEY_SELECT, /* 2 Digit Select */ - [0x69] = KEY_AGAIN, /* Recall */ - - [0x32] = KEY_BRIGHTNESSUP, /* Brightness increase */ - [0x33] = KEY_BRIGHTNESSDOWN, /* Brightness decrease */ - [0x6b] = KEY_KPPLUS, /* (not named >>>>>) */ - [0x6c] = KEY_KPMINUS, /* (not named <<<<<) */ - - [0x2d] = KEY_MUTE, /* Mute */ - [0x30] = KEY_VOLUMEUP, /* Volume up */ - [0x31] = KEY_VOLUMEDOWN, /* Volume down */ - [0x60] = KEY_CHANNELUP, /* Channel up */ - [0x61] = KEY_CHANNELDOWN, /* Channel down */ - - [0x3f] = KEY_RECORD, /* Record */ - [0x37] = KEY_PLAY, /* Play */ - [0x36] = KEY_PAUSE, /* Pause */ - [0x2b] = KEY_STOP, /* Stop */ - [0x67] = KEY_FASTFORWARD, /* Foward */ - [0x66] = KEY_REWIND, /* Rewind */ - [0x3e] = KEY_SEARCH, /* Auto Scan */ - [0x2e] = KEY_CAMERA, /* Capture Video */ - [0x6d] = KEY_MENU, /* Show/Hide Control */ - [0x2f] = KEY_ZOOM, /* Full Screen */ - [0x34] = KEY_RADIO, /* FM */ - [0x65] = KEY_POWER, /* Computer power */ + [0x78] = KEY_TUNER, /* Video Source */ + [0x2c] = KEY_EXIT, /* Open/Close software */ + [0x2a] = KEY_SELECT, /* 2 Digit Select */ + [0x69] = KEY_AGAIN, /* Recall */ + + [0x32] = KEY_BRIGHTNESSUP, /* Brightness increase */ + [0x33] = KEY_BRIGHTNESSDOWN, /* Brightness decrease */ + [0x6b] = KEY_KPPLUS, /* (not named >>>>>) */ + [0x6c] = KEY_KPMINUS, /* (not named <<<<<) */ + + [0x2d] = KEY_MUTE, /* Mute */ + [0x30] = KEY_VOLUMEUP, /* Volume up */ + [0x31] = KEY_VOLUMEDOWN,/* Volume down */ + [0x60] = KEY_CHANNELUP, /* Channel up */ + [0x61] = KEY_CHANNELDOWN,/* Channel down */ + + [0x3f] = KEY_RECORD, /* Record */ + [0x37] = KEY_PLAY, /* Play */ + [0x36] = KEY_PAUSE, /* Pause */ + [0x2b] = KEY_STOP, /* Stop */ + [0x67] = KEY_FASTFORWARD,/* Foward */ + [0x66] = KEY_REWIND, /* Rewind */ + [0x3e] = KEY_SEARCH, /* Auto Scan */ + [0x2e] = KEY_CAMERA, /* Capture Video */ + [0x6d] = KEY_MENU, /* Show/Hide Control */ + [0x2f] = KEY_ZOOM, /* Full Screen */ + [0x34] = KEY_RADIO, /* FM */ + [0x65] = KEY_POWER, /* Computer power */ }; EXPORT_SYMBOL_GPL(ir_codes_norwood); @@ -1875,35 +1875,35 @@ IR_KEYTAB_TYPE ir_codes_budget_ci_old[IR_KEYTAB_SIZE] = { [0x09] = KEY_9, [0x0a] = KEY_ENTER, [0x0b] = KEY_RED, - [0x0c] = KEY_POWER, /* RADIO on Hauppauge */ + [0x0c] = KEY_POWER, /* RADIO on Hauppauge */ [0x0d] = KEY_MUTE, - [0x0f] = KEY_A, /* TV on Hauppauge */ + [0x0f] = KEY_A, /* TV on Hauppauge */ [0x10] = KEY_VOLUMEUP, [0x11] = KEY_VOLUMEDOWN, [0x14] = KEY_B, [0x1c] = KEY_UP, [0x1d] = KEY_DOWN, - [0x1e] = KEY_OPTION, /* RESERVED on Hauppauge */ + [0x1e] = KEY_OPTION, /* RESERVED on Hauppauge */ [0x1f] = KEY_BREAK, [0x20] = KEY_CHANNELUP, [0x21] = KEY_CHANNELDOWN, - [0x22] = KEY_PREVIOUS, /* Prev. Ch on Zenith, SOURCE on Hauppauge */ + [0x22] = KEY_PREVIOUS, /* Prev Ch on Zenith, SOURCE on Hauppauge */ [0x24] = KEY_RESTART, [0x25] = KEY_OK, - [0x26] = KEY_CYCLEWINDOWS, /* MINIMIZE on Hauppauge */ - [0x28] = KEY_ENTER, /* VCR mode on Zenith */ + [0x26] = KEY_CYCLEWINDOWS, /* MINIMIZE on Hauppauge */ + [0x28] = KEY_ENTER, /* VCR mode on Zenith */ [0x29] = KEY_PAUSE, [0x2b] = KEY_RIGHT, [0x2c] = KEY_LEFT, - [0x2e] = KEY_MENU, /* FULL SCREEN on Hauppauge */ + [0x2e] = KEY_MENU, /* FULL SCREEN on Hauppauge */ [0x30] = KEY_SLOW, - [0x31] = KEY_PREVIOUS, /* VCR mode on Zenith */ + [0x31] = KEY_PREVIOUS, /* VCR mode on Zenith */ [0x32] = KEY_REWIND, [0x34] = KEY_FASTFORWARD, [0x35] = KEY_PLAY, [0x36] = KEY_STOP, [0x37] = KEY_RECORD, - [0x38] = KEY_TUNER, /* TV/VCR on Zenith */ + [0x38] = KEY_TUNER, /* TV/VCR on Zenith */ [0x3a] = KEY_C, [0x3c] = KEY_EXIT, [0x3d] = KEY_POWER2, @@ -1943,12 +1943,12 @@ IR_KEYTAB_TYPE ir_codes_asus_pc39[IR_KEYTAB_SIZE] = { [0x21] = KEY_TV, /* tv */ [0x1d] = KEY_EXIT, /* back */ - [0x0a] = KEY_CHANNELUP, /* channel / program + */ + [0x0a] = KEY_CHANNELUP, /* channel / program + */ [0x1b] = KEY_CHANNELDOWN, /* channel / program - */ [0x1a] = KEY_ENTER, /* enter */ [0x06] = KEY_PAUSE, /* play/pause */ - [0x1e] = KEY_PREVIOUS, /* rew */ + [0x1e] = KEY_PREVIOUS, /* rew */ [0x26] = KEY_NEXT, /* forward */ [0x0e] = KEY_REWIND, /* backward << */ [0x3a] = KEY_FASTFORWARD, /* forward >> */ @@ -1991,15 +1991,15 @@ IR_KEYTAB_TYPE ir_codes_encore_enltv[IR_KEYTAB_SIZE] = { [0x1d] = KEY_9, [0x0a] = KEY_0, - [0x09] = KEY_LIST, /* -/-- */ - [0x0b] = KEY_LAST, /* recall */ + [0x09] = KEY_LIST, /* -/-- */ + [0x0b] = KEY_LAST, /* recall */ [0x14] = KEY_HOME, /* win start menu */ [0x15] = KEY_EXIT, /* exit */ #if 0 - [0x16] = KEY_CHANNELUP, /* UP */ + [0x16] = KEY_CHANNELUP, /* UP */ [0x12] = KEY_CHANNELDOWN, /* DOWN */ - [0x0c] = KEY_VOLUMEUP, /* RIGHT */ + [0x0c] = KEY_VOLUMEUP, /* RIGHT */ [0x17] = KEY_VOLUMEDOWN, /* LEFT */ #else [0x16] = KEY_UP, @@ -2011,7 +2011,7 @@ IR_KEYTAB_TYPE ir_codes_encore_enltv[IR_KEYTAB_SIZE] = { [0x18] = KEY_ENTER, /* OK */ [0x0e] = KEY_ESC, - [0x13] = KEY_D, /* desktop */ + [0x13] = KEY_D, /* desktop */ [0x11] = KEY_TAB, [0x19] = KEY_SWITCHVIDEOMODE, /* switch */ @@ -2030,9 +2030,9 @@ IR_KEYTAB_TYPE ir_codes_encore_enltv[IR_KEYTAB_SIZE] = { [0x49] = KEY_PREVIOUS, [0x4b] = KEY_NEXT, - [0x4c] = KEY_FAVORITES, /* tv wall */ + [0x4c] = KEY_FAVORITES, /* tv wall */ [0x4d] = KEY_SOUND, /* DVD sound */ - [0x4e] = KEY_LANGUAGE, /* DVD lang */ + [0x4e] = KEY_LANGUAGE, /* DVD lang */ [0x4f] = KEY_TEXT, /* DVD text */ [0x50] = KEY_SLEEP, /* shutdown */ @@ -2089,9 +2089,9 @@ IR_KEYTAB_TYPE ir_codes_encore_enltv2[IR_KEYTAB_SIZE] = { [0x72] = KEY_CHANNELDOWN, [0x41] = KEY_RECORD, - [0x51] = KEY_SHUFFLE, /* Snapshot */ - [0x75] = KEY_TIME, /* Timeshift */ - [0x71] = KEY_TV2, /* PIP */ + [0x51] = KEY_SHUFFLE, /* Snapshot */ + [0x75] = KEY_TIME, /* Timeshift */ + [0x71] = KEY_TV2, /* PIP */ [0x45] = KEY_REWIND, [0x6f] = KEY_PAUSE, @@ -2103,7 +2103,7 @@ EXPORT_SYMBOL_GPL(ir_codes_encore_enltv2); /* for the Technotrend 1500 bundled remotes (grey and black): */ IR_KEYTAB_TYPE ir_codes_tt_1500[IR_KEYTAB_SIZE] = { [0x01] = KEY_POWER, - [0x02] = KEY_SHUFFLE, /* ? double-arrow key */ + [0x02] = KEY_SHUFFLE, /* ? double-arrow key */ [0x03] = KEY_1, [0x04] = KEY_2, [0x05] = KEY_3, @@ -2127,7 +2127,7 @@ IR_KEYTAB_TYPE ir_codes_tt_1500[IR_KEYTAB_SIZE] = { [0x17] = KEY_BLUE, [0x18] = KEY_MUTE, [0x19] = KEY_TEXT, - [0x1a] = KEY_MODE, /* ? TV/Radio */ + [0x1a] = KEY_MODE, /* ? TV/Radio */ [0x21] = KEY_OPTION, [0x22] = KEY_EPG, [0x23] = KEY_CHANNELUP, @@ -2135,7 +2135,7 @@ IR_KEYTAB_TYPE ir_codes_tt_1500[IR_KEYTAB_SIZE] = { [0x25] = KEY_VOLUMEUP, [0x26] = KEY_VOLUMEDOWN, [0x27] = KEY_SETUP, - [0x3a] = KEY_RECORD, /* these keys are only in the black remote */ + [0x3a] = KEY_RECORD, /* these keys are only in the black remote */ [0x3b] = KEY_PLAY, [0x3c] = KEY_STOP, [0x3d] = KEY_REWIND, @@ -2168,7 +2168,7 @@ IR_KEYTAB_TYPE ir_codes_fusionhdtv_mce[IR_KEYTAB_SIZE] = { [0x02] = KEY_TV, /* Labeled DTV on remote */ [0x0e] = KEY_MP3, [0x1a] = KEY_DVD, - [0x1e] = KEY_FAVORITES, /* Labeled CPF on remote */ + [0x1e] = KEY_FAVORITES, /* Labeled CPF on remote */ [0x16] = KEY_SETUP, [0x46] = KEY_POWER2, /* TV On/Off button on remote */ [0x0a] = KEY_EPG, /* Labeled Guide on remote */ @@ -2179,9 +2179,9 @@ IR_KEYTAB_TYPE ir_codes_fusionhdtv_mce[IR_KEYTAB_SIZE] = { [0x55] = KEY_CYCLEWINDOWS, /* Labeled ALT-TAB on remote */ [0x0f] = KEY_PREVIOUSSONG, /* Labeled |<< REPLAY on remote */ - [0x12] = KEY_NEXTSONG, /* Labeled >>| SKIP on remote */ - [0x42] = KEY_ENTER, /* Labeled START with a green - * MS windows logo on remote */ + [0x12] = KEY_NEXTSONG, /* Labeled >>| SKIP on remote */ + [0x42] = KEY_ENTER, /* Labeled START with a green + MS windows logo on remote */ [0x15] = KEY_VOLUMEUP, [0x05] = KEY_VOLUMEDOWN, @@ -2257,7 +2257,7 @@ IR_KEYTAB_TYPE ir_codes_behold[IR_KEYTAB_SIZE] = { /* 0x1c 0x12 * * TV/FM POWER * * */ - [0x1c] = KEY_TUNER, /*XXX KEY_TV KEY_RADIO */ + [0x1c] = KEY_TUNER, /* XXX KEY_TV / KEY_RADIO */ [0x12] = KEY_POWER, /* 0x01 0x02 0x03 * @@ -2301,11 +2301,11 @@ IR_KEYTAB_TYPE ir_codes_behold[IR_KEYTAB_SIZE] = { * 0x015 * * Down * * */ - [0x0b] = KEY_CHANNELUP, /*XXX KEY_UP */ - [0x18] = KEY_VOLUMEDOWN, /*XXX KEY_LEFT */ - [0x16] = KEY_OK, /*XXX KEY_ENTER */ - [0x0c] = KEY_VOLUMEUP, /*XXX KEY_RIGHT */ - [0x15] = KEY_CHANNELDOWN, /*XXX KEY_DOWN */ + [0x0b] = KEY_CHANNELUP, /* XXX KEY_UP */ + [0x18] = KEY_VOLUMEDOWN, /* XXX KEY_LEFT */ + [0x16] = KEY_OK, /* XXX KEY_ENTER */ + [0x0c] = KEY_VOLUMEUP, /* XXX KEY_RIGHT */ + [0x15] = KEY_CHANNELDOWN, /* XXX KEY_DOWN */ /* 0x11 0x0d * * MUTE INFO * @@ -2324,8 +2324,8 @@ IR_KEYTAB_TYPE ir_codes_behold[IR_KEYTAB_SIZE] = { [0x1b] = KEY_PLAYPAUSE, [0x1a] = KEY_STOP, [0x0e] = KEY_TEXT, - [0x1f] = KEY_RED, /*XXX KEY_AUDIO */ - [0x1e] = KEY_YELLOW, /*XXX KEY_SOURCE */ + [0x1f] = KEY_RED, /*XXX KEY_AUDIO */ + [0x1e] = KEY_YELLOW, /*XXX KEY_SOURCE */ /* 0x1d 0x13 0x19 * * SLEEP PREVIEW DVB * @@ -2333,7 +2333,7 @@ IR_KEYTAB_TYPE ir_codes_behold[IR_KEYTAB_SIZE] = { * */ [0x1d] = KEY_SLEEP, [0x13] = KEY_GREEN, - [0x19] = KEY_BLUE, /*XXX KEY_SAT */ + [0x19] = KEY_BLUE, /* XXX KEY_SAT */ /* 0x58 0x5c * * FREEZE SNAPSHOT * @@ -2361,7 +2361,7 @@ IR_KEYTAB_TYPE ir_codes_behold_columbus[IR_KEYTAB_SIZE] = { [0x13] = KEY_MUTE, [0x11] = KEY_PROPS, - [0x1C] = KEY_TUNER, /* KEY_TV/KEY_RADIO */ + [0x1C] = KEY_TUNER, /* KEY_TV/KEY_RADIO */ [0x12] = KEY_POWER, /* 0x01 0x02 0x03 0x0D * @@ -2380,7 +2380,7 @@ IR_KEYTAB_TYPE ir_codes_behold_columbus[IR_KEYTAB_SIZE] = { [0x04] = KEY_4, [0x05] = KEY_5, [0x06] = KEY_6, - [0x19] = KEY_BOOKMARKS, /* Snapshot key */ + [0x19] = KEY_BOOKMARKS, /* Snapshot key */ [0x07] = KEY_7, [0x08] = KEY_8, [0x09] = KEY_9, @@ -2446,7 +2446,7 @@ IR_KEYTAB_TYPE ir_codes_genius_tvgo_a11mce[IR_KEYTAB_SIZE] = { [0x04] = KEY_LIST, /* -/-- */ /* small arrows above numbers */ [0x1a] = KEY_NEXT, /* also Fast Forward */ - [0x0e] = KEY_PREVIOUS, /* also Rewind */ + [0x0e] = KEY_PREVIOUS, /* also Rewind */ /* these are in a rather non standard layout and have an alternate name written */ [0x1e] = KEY_UP, /* Video Setting */ @@ -2887,7 +2887,7 @@ IR_KEYTAB_TYPE ir_codes_videomate_s350[IR_KEYTAB_SIZE] = { [0x00] = KEY_TV, [0x01] = KEY_DVD, [0x04] = KEY_RECORD, - [0x05] = KEY_VIDEO, /* TV/Video */ + [0x05] = KEY_VIDEO, /* TV/Video */ [0x07] = KEY_STOP, [0x08] = KEY_PLAYPAUSE, [0x0a] = KEY_REWIND, @@ -2909,13 +2909,13 @@ IR_KEYTAB_TYPE ir_codes_videomate_s350[IR_KEYTAB_SIZE] = { [0x1f] = KEY_0, [0x21] = KEY_SLEEP, [0x24] = KEY_ZOOM, - [0x25] = KEY_LAST, /* Recall */ - [0x26] = KEY_SUBTITLE, /* CC */ - [0x27] = KEY_LANGUAGE, /* MTS */ - [0x29] = KEY_CHANNEL, /* SURF */ + [0x25] = KEY_LAST, /* Recall */ + [0x26] = KEY_SUBTITLE, /* CC */ + [0x27] = KEY_LANGUAGE, /* MTS */ + [0x29] = KEY_CHANNEL, /* SURF */ [0x2b] = KEY_A, [0x2c] = KEY_B, - [0x2f] = KEY_SHUFFLE, /* Snapshot */ + [0x2f] = KEY_SHUFFLE, /* Snapshot */ [0x23] = KEY_RADIO, [0x02] = KEY_PREVIOUSSONG, [0x06] = KEY_NEXTSONG, -- cgit v1.2.3 From b3662c3abe7526be7701c10712ac2ec2e231aca0 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 27 Aug 2009 09:54:44 -0300 Subject: Fix a number of EXPORT_SYMBOL warnings From: Mauro Carvalho Chehab Make Checkpatch tool happy: -:2349: WARNING: EXPORT_SYMBOL(foo); should immediately follow its function/variable On all cases, it were just a blank line at the wrong place. Yet, fixing it is trivial Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/common/ir-keymaps.c | 39 +-------------------------------- 1 file changed, 1 insertion(+), 38 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/common/ir-keymaps.c b/linux/drivers/media/common/ir-keymaps.c index 37db62ea5..307b275f2 100644 --- a/linux/drivers/media/common/ir-keymaps.c +++ b/linux/drivers/media/common/ir-keymaps.c @@ -29,7 +29,6 @@ IR_KEYTAB_TYPE ir_codes_empty[IR_KEYTAB_SIZE] = { [0x2a] = KEY_COFFEE, }; - EXPORT_SYMBOL_GPL(ir_codes_empty); /* Michal Majchrowicz */ @@ -61,8 +60,8 @@ IR_KEYTAB_TYPE ir_codes_proteus_2309[IR_KEYTAB_SIZE] = { [0x1e] = KEY_RIGHT, /* volume + */ [0x14] = KEY_F1, }; - EXPORT_SYMBOL_GPL(ir_codes_proteus_2309); + /* Matt Jesson */ @@ -253,7 +251,6 @@ IR_KEYTAB_TYPE ir_codes_apac_viewcomp[IR_KEYTAB_SIZE] = { [0x0c] = KEY_KPPLUS, /* fine tune >>>> */ [0x18] = KEY_KPMINUS, /* fine tune <<<< */ }; - EXPORT_SYMBOL_GPL(ir_codes_apac_viewcomp); /* ---------------------------------------------------------------------- */ @@ -323,7 +320,6 @@ IR_KEYTAB_TYPE ir_codes_pixelview[IR_KEYTAB_SIZE] = { [0x1d] = KEY_REFRESH, /* reset */ [0x18] = KEY_MUTE, /* mute/unmute */ }; - EXPORT_SYMBOL_GPL(ir_codes_pixelview); /* @@ -428,7 +424,6 @@ IR_KEYTAB_TYPE ir_codes_nebula[IR_KEYTAB_SIZE] = { [0x35] = KEY_PHONE, [0x36] = KEY_PC, }; - EXPORT_SYMBOL_GPL(ir_codes_nebula); /* DigitalNow DNTV Live DVB-T Remote */ @@ -469,7 +464,6 @@ IR_KEYTAB_TYPE ir_codes_dntv_live_dvb_t[IR_KEYTAB_SIZE] = { [0x1e] = KEY_CHANNELDOWN, [0x1f] = KEY_VOLUMEDOWN, }; - EXPORT_SYMBOL_GPL(ir_codes_dntv_live_dvb_t); /* ---------------------------------------------------------------------- */ @@ -522,7 +516,6 @@ IR_KEYTAB_TYPE ir_codes_iodata_bctv7e[IR_KEYTAB_SIZE] = { [0x61] = KEY_FASTFORWARD, /* forward >> */ [0x01] = KEY_NEXT, /* skip >| */ }; - EXPORT_SYMBOL_GPL(ir_codes_iodata_bctv7e); /* ---------------------------------------------------------------------- */ @@ -576,7 +569,6 @@ IR_KEYTAB_TYPE ir_codes_adstech_dvb_t_pci[IR_KEYTAB_SIZE] = { [0x15] = KEY_VOLUMEUP, [0x1c] = KEY_VOLUMEDOWN, }; - EXPORT_SYMBOL_GPL(ir_codes_adstech_dvb_t_pci); /* ---------------------------------------------------------------------- */ @@ -611,7 +603,6 @@ IR_KEYTAB_TYPE ir_codes_msi_tvanywhere[IR_KEYTAB_SIZE] = { [0x1e] = KEY_CHANNELDOWN, [0x1f] = KEY_VOLUMEDOWN, }; - EXPORT_SYMBOL_GPL(ir_codes_msi_tvanywhere); /* ---------------------------------------------------------------------- */ @@ -749,7 +740,6 @@ IR_KEYTAB_TYPE ir_codes_cinergy_1400[IR_KEYTAB_SIZE] = { [0x48] = KEY_STOP, [0x5c] = KEY_NEXT, }; - EXPORT_SYMBOL_GPL(ir_codes_cinergy_1400); /* ---------------------------------------------------------------------- */ @@ -799,7 +789,6 @@ IR_KEYTAB_TYPE ir_codes_avertv_303[IR_KEYTAB_SIZE] = { [0x13] = KEY_DOWN, [0x1b] = KEY_UP, }; - EXPORT_SYMBOL_GPL(ir_codes_avertv_303); /* ---------------------------------------------------------------------- */ @@ -861,7 +850,6 @@ IR_KEYTAB_TYPE ir_codes_dntv_live_dvbt_pro[IR_KEYTAB_SIZE] = { [0x5c] = KEY_YELLOW, [0x5d] = KEY_BLUE, }; - EXPORT_SYMBOL_GPL(ir_codes_dntv_live_dvbt_pro); IR_KEYTAB_TYPE ir_codes_em_terratec[IR_KEYTAB_SIZE] = { @@ -894,7 +882,6 @@ IR_KEYTAB_TYPE ir_codes_em_terratec[IR_KEYTAB_SIZE] = { [0x1e] = KEY_STOP, [0x40] = KEY_ZOOM, }; - EXPORT_SYMBOL_GPL(ir_codes_em_terratec); IR_KEYTAB_TYPE ir_codes_pinnacle_grey[IR_KEYTAB_SIZE] = { @@ -947,7 +934,6 @@ IR_KEYTAB_TYPE ir_codes_pinnacle_grey[IR_KEYTAB_SIZE] = { [0x2a] = KEY_MEDIA, [0x18] = KEY_EPG, }; - EXPORT_SYMBOL_GPL(ir_codes_pinnacle_grey); IR_KEYTAB_TYPE ir_codes_flyvideo[IR_KEYTAB_SIZE] = { @@ -981,7 +967,6 @@ IR_KEYTAB_TYPE ir_codes_flyvideo[IR_KEYTAB_SIZE] = { [0x1f] = KEY_FORWARD, /* Forward ( >>> ) */ [0x0a] = KEY_ANGLE, /* no label, may be used as the PAUSE button */ }; - EXPORT_SYMBOL_GPL(ir_codes_flyvideo); IR_KEYTAB_TYPE ir_codes_flydvb[IR_KEYTAB_SIZE] = { @@ -1022,7 +1007,6 @@ IR_KEYTAB_TYPE ir_codes_flydvb[IR_KEYTAB_SIZE] = { [0x11] = KEY_STOP, /* Stop */ [0x0e] = KEY_NEXT, /* End >>| */ }; - EXPORT_SYMBOL_GPL(ir_codes_flydvb); IR_KEYTAB_TYPE ir_codes_cinergy[IR_KEYTAB_SIZE] = { @@ -1064,7 +1048,6 @@ IR_KEYTAB_TYPE ir_codes_cinergy[IR_KEYTAB_SIZE] = { [0x22] = KEY_PAUSE, [0x23] = KEY_STOP, }; - EXPORT_SYMBOL_GPL(ir_codes_cinergy); /* Alfons Geser @@ -1123,7 +1106,6 @@ IR_KEYTAB_TYPE ir_codes_eztv[IR_KEYTAB_SIZE] = { [0x13] = KEY_ENTER, /* enter */ [0x21] = KEY_DOT, /* . (decimal dot) */ }; - EXPORT_SYMBOL_GPL(ir_codes_eztv); /* Alex Hermann */ @@ -1172,7 +1154,6 @@ IR_KEYTAB_TYPE ir_codes_avermedia[IR_KEYTAB_SIZE] = { [0x11] = KEY_CHANNELDOWN, /* CHANNEL/PAGE- */ [0x31] = KEY_CHANNELUP /* CHANNEL/PAGE+ */ }; - EXPORT_SYMBOL_GPL(ir_codes_avermedia); IR_KEYTAB_TYPE ir_codes_videomate_tv_pvr[IR_KEYTAB_SIZE] = { @@ -1223,7 +1204,6 @@ IR_KEYTAB_TYPE ir_codes_videomate_tv_pvr[IR_KEYTAB_SIZE] = { [0x20] = KEY_LANGUAGE, [0x21] = KEY_SLEEP, }; - EXPORT_SYMBOL_GPL(ir_codes_videomate_tv_pvr); /* Michael Tokarev @@ -1321,7 +1301,6 @@ IR_KEYTAB_TYPE ir_codes_manli[IR_KEYTAB_SIZE] = { /* 0x1d unused ? */ }; - EXPORT_SYMBOL_GPL(ir_codes_manli); /* Mike Baikov */ @@ -1363,7 +1342,6 @@ IR_KEYTAB_TYPE ir_codes_gotview7135[IR_KEYTAB_SIZE] = { [0x1e] = KEY_F23, /* TIMESHIFT */ [0x38] = KEY_F24, /* NORMAL TIMESHIFT */ }; - EXPORT_SYMBOL_GPL(ir_codes_gotview7135); IR_KEYTAB_TYPE ir_codes_purpletv[IR_KEYTAB_SIZE] = { @@ -1414,7 +1392,6 @@ IR_KEYTAB_TYPE ir_codes_purpletv[IR_KEYTAB_SIZE] = { [0x42] = KEY_REWIND, /* Backward ? */ }; - EXPORT_SYMBOL_GPL(ir_codes_purpletv); /* Mapping for the 28 key remote control as seen at @@ -1457,7 +1434,6 @@ IR_KEYTAB_TYPE ir_codes_pctv_sedna[IR_KEYTAB_SIZE] = { [0x17] = KEY_DIGITS, /* Plus */ [0x1f] = KEY_PLAY, /* Play */ }; - EXPORT_SYMBOL_GPL(ir_codes_pctv_sedna); /* Mark Phalan */ @@ -1498,7 +1474,6 @@ IR_KEYTAB_TYPE ir_codes_pv951[IR_KEYTAB_SIZE] = { [0x14] = KEY_EQUAL, /* SYNC */ [0x1c] = KEY_MEDIA, /* PC/TV */ }; - EXPORT_SYMBOL_GPL(ir_codes_pv951); /* generic RC5 keytable */ @@ -1575,7 +1550,6 @@ IR_KEYTAB_TYPE ir_codes_rc5_tv[IR_KEYTAB_SIZE] = { [0x3f] = KEY_RESERVED, /* system select */ #endif }; - EXPORT_SYMBOL_GPL(ir_codes_rc5_tv); /* Table for Leadtek Winfast Remote Controls - used by both bttv and cx88 */ @@ -1639,7 +1613,6 @@ IR_KEYTAB_TYPE ir_codes_winfast[IR_KEYTAB_SIZE] = { [0x3b] = KEY_F23, /* MCE +CH, on Y04G0033 */ [0x3f] = KEY_F24 /* MCE -CH, on Y04G0033 */ }; - EXPORT_SYMBOL_GPL(ir_codes_winfast); IR_KEYTAB_TYPE ir_codes_pinnacle_color[IR_KEYTAB_SIZE] = { @@ -1699,7 +1672,6 @@ IR_KEYTAB_TYPE ir_codes_pinnacle_color[IR_KEYTAB_SIZE] = { [0x74] = KEY_CHANNEL, [0x0a] = KEY_BACKSPACE, }; - EXPORT_SYMBOL_GPL(ir_codes_pinnacle_color); /* Hauppauge: the newer, gray remotes (seems there are multiple @@ -1762,7 +1734,6 @@ IR_KEYTAB_TYPE ir_codes_hauppauge_new[IR_KEYTAB_SIZE] = { [0x3c] = KEY_ZOOM, /* full */ [0x3d] = KEY_POWER, /* system power (green button) */ }; - EXPORT_SYMBOL_GPL(ir_codes_hauppauge_new); IR_KEYTAB_TYPE ir_codes_npgtech[IR_KEYTAB_SIZE] = { @@ -1806,7 +1777,6 @@ IR_KEYTAB_TYPE ir_codes_npgtech[IR_KEYTAB_SIZE] = { [0x10] = KEY_POWER, }; - EXPORT_SYMBOL_GPL(ir_codes_npgtech); /* Norwood Micro (non-Pro) TV Tuner @@ -1854,7 +1824,6 @@ IR_KEYTAB_TYPE ir_codes_norwood[IR_KEYTAB_SIZE] = { [0x34] = KEY_RADIO, /* FM */ [0x65] = KEY_POWER, /* Computer power */ }; - EXPORT_SYMBOL_GPL(ir_codes_norwood); /* From reading the following remotes: @@ -1909,7 +1878,6 @@ IR_KEYTAB_TYPE ir_codes_budget_ci_old[IR_KEYTAB_SIZE] = { [0x3d] = KEY_POWER2, [0x3e] = KEY_TUNER, }; - EXPORT_SYMBOL_GPL(ir_codes_budget_ci_old); /* @@ -1963,7 +1931,6 @@ IR_KEYTAB_TYPE ir_codes_asus_pc39[IR_KEYTAB_SIZE] = { [0x3d] = KEY_MUTE, /* mute */ [0x01] = KEY_DVD, /* dvd */ }; - EXPORT_SYMBOL_GPL(ir_codes_asus_pc39); @@ -2142,7 +2109,6 @@ IR_KEYTAB_TYPE ir_codes_tt_1500[IR_KEYTAB_SIZE] = { [0x3e] = KEY_PAUSE, [0x3f] = KEY_FORWARD, }; - EXPORT_SYMBOL_GPL(ir_codes_tt_1500); /* DViCO FUSION HDTV MCE remote */ @@ -2203,7 +2169,6 @@ IR_KEYTAB_TYPE ir_codes_fusionhdtv_mce[IR_KEYTAB_SIZE] = { [0x01] = KEY_RECORD, [0x4e] = KEY_POWER, }; - EXPORT_SYMBOL_GPL(ir_codes_fusionhdtv_mce); /* Pinnacle PCTV HD 800i mini remote */ @@ -2342,7 +2307,6 @@ IR_KEYTAB_TYPE ir_codes_behold[IR_KEYTAB_SIZE] = { [0x5c] = KEY_SAVE, }; - EXPORT_SYMBOL_GPL(ir_codes_behold); /* Beholder Intl. Ltd. 2008 @@ -2764,7 +2728,6 @@ IR_KEYTAB_TYPE ir_codes_ati_tv_wonder_hd_600[IR_KEYTAB_SIZE] = { [0x16] = KEY_MUTE, [0x17] = KEY_VOLUMEDOWN, }; - EXPORT_SYMBOL_GPL(ir_codes_ati_tv_wonder_hd_600); /* DVBWorld remotes -- cgit v1.2.3 From 99451276a3fae1aa2b2cfd7ea23a702627df4242 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 29 Aug 2009 08:37:58 -0300 Subject: ir-keymaps: replace KEY_KP[0-9] to KEY_[0-9] From: Mauro Carvalho Chehab This is needed to match the standard mapping defined at: http://linuxtv.org/wiki/index.php/Remote_Controllers#Remote_Controllers Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/common/ir-keymaps.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/common/ir-keymaps.c b/linux/drivers/media/common/ir-keymaps.c index 307b275f2..35d35e872 100644 --- a/linux/drivers/media/common/ir-keymaps.c +++ b/linux/drivers/media/common/ir-keymaps.c @@ -644,16 +644,16 @@ IR_KEYTAB_TYPE ir_codes_msi_tvanywhere_plus[IR_KEYTAB_SIZE] = { << FUNC >> RESET */ - [0x01] = KEY_KP1, /* 1 */ - [0x0b] = KEY_KP2, /* 2 */ - [0x1b] = KEY_KP3, /* 3 */ - [0x05] = KEY_KP4, /* 4 */ - [0x09] = KEY_KP5, /* 5 */ - [0x15] = KEY_KP6, /* 6 */ - [0x06] = KEY_KP7, /* 7 */ - [0x0a] = KEY_KP8, /* 8 */ - [0x12] = KEY_KP9, /* 9 */ - [0x02] = KEY_KP0, /* 0 */ + [0x01] = KEY_1, /* 1 */ + [0x0b] = KEY_2, /* 2 */ + [0x1b] = KEY_3, /* 3 */ + [0x05] = KEY_4, /* 4 */ + [0x09] = KEY_5, /* 5 */ + [0x15] = KEY_6, /* 6 */ + [0x06] = KEY_7, /* 7 */ + [0x0a] = KEY_8, /* 8 */ + [0x12] = KEY_9, /* 9 */ + [0x02] = KEY_0, /* 0 */ [0x10] = KEY_KPPLUS, /* + */ [0x13] = KEY_AGAIN, /* Recall */ -- cgit v1.2.3 From 2decedc3e9cf2bfc4220e752cf3b56e1a6314629 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 29 Aug 2009 08:43:20 -0300 Subject: ir-keymaps: add a link to the IR standard layout page From: Mauro Carvalho Chehab While we're still discussing it, let's point to the wiki page. In the future, this should be added at V4L2 API spec DocBooks. Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/common/ir-keymaps.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/common/ir-keymaps.c b/linux/drivers/media/common/ir-keymaps.c index 35d35e872..1f2ead284 100644 --- a/linux/drivers/media/common/ir-keymaps.c +++ b/linux/drivers/media/common/ir-keymaps.c @@ -1,8 +1,6 @@ /* - - - Keytables for supported remote controls. This file is part of - video4linux. + Keytables for supported remote controls, used on drivers/media + devices. 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 @@ -17,7 +15,13 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ +/* + * NOTICE FOR DEVELOPERS: + * The IR mappings should be as close as possible to what's + * specified at: + * http://linuxtv.org/wiki/index.php/Remote_Controllers */ #include -- cgit v1.2.3 From f517214d8e0dc0bfabeb958ffd7540e51ab383d0 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 29 Aug 2009 09:01:54 -0300 Subject: ir-keymaps: Replace most KEY_[A-Z] to the proper definitions From: Mauro Carvalho Chehab There are several IR's that were using IR to type a letter that it is known by some random application. Instead, the better is to use the standard definitions found at: http://linuxtv.org/wiki/index.php/Remote_Controllers And, if needed, submit a patch for the application to understand the media keys. Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/common/ir-keymaps.c | 62 ++++++++++++++++----------------- 1 file changed, 30 insertions(+), 32 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/common/ir-keymaps.c b/linux/drivers/media/common/ir-keymaps.c index 1f2ead284..c9f204048 100644 --- a/linux/drivers/media/common/ir-keymaps.c +++ b/linux/drivers/media/common/ir-keymaps.c @@ -50,13 +50,13 @@ IR_KEYTAB_TYPE ir_codes_proteus_2309[IR_KEYTAB_SIZE] = { [0x09] = KEY_9, [0x5c] = KEY_POWER, /* power */ - [0x20] = KEY_F, /* full screen */ + [0x20] = KEY_ZOOM, /* full screen */ [0x0f] = KEY_BACKSPACE, /* recall */ [0x1b] = KEY_ENTER, /* mute */ [0x41] = KEY_RECORD, /* record */ [0x43] = KEY_STOP, /* stop */ [0x16] = KEY_S, - [0x1a] = KEY_Q, /* off */ + [0x1a] = KEY_POWER2, /* off */ [0x2e] = KEY_RED, [0x1f] = KEY_DOWN, /* channel - */ [0x1c] = KEY_UP, /* channel + */ @@ -454,7 +454,7 @@ IR_KEYTAB_TYPE ir_codes_dntv_live_dvb_t[IR_KEYTAB_SIZE] = { [0x10] = KEY_MUTE, [0x11] = KEY_REWIND, /* backward << */ [0x12] = KEY_POWER, - [0x13] = KEY_S, /* snap */ + [0x13] = KEY_CAMERA, /* snap */ [0x14] = KEY_AUDIO, /* stereo */ [0x15] = KEY_CLEAR, /* reset */ [0x16] = KEY_PLAY, @@ -505,13 +505,13 @@ IR_KEYTAB_TYPE ir_codes_iodata_bctv7e[IR_KEYTAB_SIZE] = { [0x74] = KEY_VOLUMEUP, [0x14] = KEY_MUTE, - [0x4c] = KEY_S, /* SVIDEO */ + [0x4c] = KEY_VCR, /* SVIDEO */ [0x2c] = KEY_CHANNELDOWN, [0x6c] = KEY_VOLUMEDOWN, [0x0c] = KEY_ZOOM, [0x5c] = KEY_PAUSE, - [0x3c] = KEY_C, /* || (red) */ + [0x3c] = KEY_RED, /* || (red) */ [0x7c] = KEY_RECORD, /* recording */ [0x1c] = KEY_STOP, @@ -594,7 +594,7 @@ IR_KEYTAB_TYPE ir_codes_msi_tvanywhere[IR_KEYTAB_SIZE] = { [0x0c] = KEY_MUTE, [0x0f] = KEY_SCREEN, /* Full Screen */ - [0x10] = KEY_F, /* Funtion */ + [0x10] = KEY_FN, /* Funtion */ [0x11] = KEY_T, /* Time shift */ [0x12] = KEY_POWER, [0x13] = KEY_MEDIA, /* MTS */ @@ -1376,9 +1376,7 @@ IR_KEYTAB_TYPE ir_codes_purpletv[IR_KEYTAB_SIZE] = { [0x48] = KEY_ZOOM, [0x1b] = KEY_VIDEO, /* Video source */ -#if 0 - [0x1f] = KEY_S, /* Snapshot */ -#endif + [0x1f] = KEY_CAMERA, /* Snapshot */ [0x49] = KEY_LANGUAGE, /* MTS Select */ [0x19] = KEY_SEARCH, /* Auto Scan */ @@ -1390,8 +1388,8 @@ IR_KEYTAB_TYPE ir_codes_purpletv[IR_KEYTAB_SIZE] = { [0x43] = KEY_T, /* Time Shift */ [0x47] = KEY_Y, /* Time Shift OFF */ [0x4a] = KEY_O, /* TOP */ - [0x17] = KEY_F, /* SURF CH */ #endif + [0x17] = KEY_CHANNEL, /* SURF CH */ [0x40] = KEY_FORWARD, /* Forward ? */ [0x42] = KEY_REWIND, /* Backward ? */ @@ -1982,7 +1980,7 @@ IR_KEYTAB_TYPE ir_codes_encore_enltv[IR_KEYTAB_SIZE] = { [0x18] = KEY_ENTER, /* OK */ [0x0e] = KEY_ESC, - [0x13] = KEY_D, /* desktop */ + [0x13] = KEY_CYCLEWINDOWS, /* desktop */ [0x11] = KEY_TAB, [0x19] = KEY_SWITCHVIDEOMODE, /* switch */ @@ -2738,8 +2736,8 @@ EXPORT_SYMBOL_GPL(ir_codes_ati_tv_wonder_hd_600); Igor M. Liplianin */ IR_KEYTAB_TYPE ir_codes_dm1105_nec[IR_KEYTAB_SIZE] = { - [0x0a] = KEY_Q, /*power*/ - [0x0c] = KEY_M, /*mute*/ + [0x0a] = KEY_POWER2, /* power */ + [0x0c] = KEY_MUTE, /* mute */ [0x11] = KEY_1, [0x12] = KEY_2, [0x13] = KEY_3, @@ -2750,25 +2748,25 @@ IR_KEYTAB_TYPE ir_codes_dm1105_nec[IR_KEYTAB_SIZE] = { [0x18] = KEY_8, [0x19] = KEY_9, [0x10] = KEY_0, - [0x1c] = KEY_PAGEUP, /*ch+*/ - [0x0f] = KEY_PAGEDOWN, /*ch-*/ - [0x1a] = KEY_O, /*vol+*/ - [0x0e] = KEY_Z, /*vol-*/ - [0x04] = KEY_R, /*rec*/ - [0x09] = KEY_D, /*fav*/ - [0x08] = KEY_BACKSPACE, /*rewind*/ - [0x07] = KEY_A, /*fast*/ - [0x0b] = KEY_P, /*pause*/ - [0x02] = KEY_ESC, /*cancel*/ - [0x03] = KEY_G, /*tab*/ - [0x00] = KEY_UP, /*up*/ - [0x1f] = KEY_ENTER, /*ok*/ - [0x01] = KEY_DOWN, /*down*/ - [0x05] = KEY_C, /*cap*/ - [0x06] = KEY_S, /*stop*/ - [0x40] = KEY_F, /*full*/ - [0x1e] = KEY_W, /*tvmode*/ - [0x1b] = KEY_B, /*recall*/ + [0x1c] = KEY_PAGEUP, /* ch+ */ + [0x0f] = KEY_PAGEDOWN, /* ch- */ + [0x1a] = KEY_VOLUMEUP, /* vol+ */ + [0x0e] = KEY_VOLUMEDOWN, /* vol- */ + [0x04] = KEY_RECORD, /* rec */ + [0x09] = KEY_CHANNEL, /* fav */ + [0x08] = KEY_BACKSPACE, /* rewind */ + [0x07] = KEY_FASTFORWARD, /* fast */ + [0x0b] = KEY_PAUSE, /* pause */ + [0x02] = KEY_ESC, /* cancel */ + [0x03] = KEY_TAB, /* tab */ + [0x00] = KEY_UP, /* up */ + [0x1f] = KEY_ENTER, /* ok */ + [0x01] = KEY_DOWN, /* down */ + [0x05] = KEY_RECORD, /* cap */ + [0x06] = KEY_STOP, /* stop */ + [0x40] = KEY_ZOOM, /* full */ + [0x1e] = KEY_TV, /* tvmode */ + [0x1b] = KEY_B, /* recall */ }; EXPORT_SYMBOL_GPL(ir_codes_dm1105_nec); -- cgit v1.2.3 From 668392480789cab466a0a979ed95f9057d005379 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 29 Aug 2009 09:06:07 -0300 Subject: ir-keymaps: standardize timeshift key From: Mauro Carvalho Chehab Each remote were using a different keycode for timeshift. Use the same keycode for all of them, using the map as defined at: http://linuxtv.org/wiki/index.php/Remote_Controllers Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/common/ir-keymaps.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/common/ir-keymaps.c b/linux/drivers/media/common/ir-keymaps.c index c9f204048..24a635529 100644 --- a/linux/drivers/media/common/ir-keymaps.c +++ b/linux/drivers/media/common/ir-keymaps.c @@ -331,7 +331,7 @@ EXPORT_SYMBOL_GPL(ir_codes_pixelview); present on PV MPEG 8000GT */ IR_KEYTAB_TYPE ir_codes_pixelview_new[IR_KEYTAB_SIZE] = { - [0x3c] = KEY_PAUSE, /* Timeshift */ + [0x3c] = KEY_TIME, /* Timeshift */ [0x12] = KEY_POWER, [0x3d] = KEY_1, @@ -492,7 +492,7 @@ IR_KEYTAB_TYPE ir_codes_iodata_bctv7e[IR_KEYTAB_SIZE] = { [0x78] = KEY_9, [0x10] = KEY_L, /* Live */ - [0x08] = KEY_T, /* Time Shift */ + [0x08] = KEY_TIME, /* Time Shift */ [0x18] = KEY_PLAYPAUSE, /* Play */ @@ -595,7 +595,7 @@ IR_KEYTAB_TYPE ir_codes_msi_tvanywhere[IR_KEYTAB_SIZE] = { [0x0c] = KEY_MUTE, [0x0f] = KEY_SCREEN, /* Full Screen */ [0x10] = KEY_FN, /* Funtion */ - [0x11] = KEY_T, /* Time shift */ + [0x11] = KEY_TIME, /* Time shift */ [0x12] = KEY_POWER, [0x13] = KEY_MEDIA, /* MTS */ [0x14] = KEY_SLOW, @@ -1293,7 +1293,7 @@ IR_KEYTAB_TYPE ir_codes_manli[IR_KEYTAB_SIZE] = { [0x0f] = KEY_AUDIO, [0x1b] = KEY_VOLUMEUP, [0x1a] = KEY_CHANNELUP, - [0x0e] = KEY_SLEEP, /*XXX maybe KEY_PAUSE */ + [0x0e] = KEY_TIME, [0x1f] = KEY_VOLUMEDOWN, [0x1e] = KEY_CHANNELDOWN, @@ -1343,7 +1343,7 @@ IR_KEYTAB_TYPE ir_codes_gotview7135[IR_KEYTAB_SIZE] = { [0x2a] = KEY_F21, /* LIVE TIMESHIFT */ [0x0e] = KEY_F22, /* MIN TIMESHIFT */ - [0x1e] = KEY_F23, /* TIMESHIFT */ + [0x1e] = KEY_TIMESHIFT, /* TIMESHIFT */ [0x38] = KEY_F24, /* NORMAL TIMESHIFT */ }; EXPORT_SYMBOL_GPL(ir_codes_gotview7135); @@ -1384,8 +1384,8 @@ IR_KEYTAB_TYPE ir_codes_purpletv[IR_KEYTAB_SIZE] = { [0x46] = KEY_PLAY, [0x45] = KEY_PAUSE, /* Pause */ [0x44] = KEY_STOP, + [0x43] = KEY_TIME, /* Time Shift */ #if 0 - [0x43] = KEY_T, /* Time Shift */ [0x47] = KEY_Y, /* Time Shift OFF */ [0x4a] = KEY_O, /* TOP */ #endif @@ -1426,7 +1426,7 @@ IR_KEYTAB_TYPE ir_codes_pctv_sedna[IR_KEYTAB_SIZE] = { [0x18] = KEY_VOLUMEDOWN, [0x19] = KEY_SHUFFLE, /* Snapshot */ [0x1a] = KEY_NEXTSONG, - [0x1b] = KEY_TEXT, /* Time Shift */ + [0x1b] = KEY_TIME, /* Time Shift */ [0x1c] = KEY_RADIO, /* FM Radio */ [0x1d] = KEY_RECORD, [0x1e] = KEY_PAUSE, @@ -1595,7 +1595,7 @@ IR_KEYTAB_TYPE ir_codes_winfast[IR_KEYTAB_SIZE] = { [0x22] = KEY_PREVIOUS, [0x23] = KEY_PLAYPAUSE, [0x24] = KEY_NEXT, - [0x25] = KEY_ARCHIVE, /* Time Shifting */ + [0x25] = KEY_TIME, /* Time Shifting */ [0x26] = KEY_STOP, [0x27] = KEY_RECORD, [0x28] = KEY_SAVE, /* Screenshot */ @@ -2364,7 +2364,7 @@ IR_KEYTAB_TYPE ir_codes_behold_columbus[IR_KEYTAB_SIZE] = { * Timeshift Record ChannelDown VolumeDown * * */ - [0x1B] = KEY_REWIND, + [0x1B] = KEY_TIME, [0x1D] = KEY_RECORD, [0x15] = KEY_CHANNELDOWN, [0x18] = KEY_VOLUMEDOWN, @@ -2516,7 +2516,7 @@ IR_KEYTAB_TYPE ir_codes_kworld_plus_tv_analog[IR_KEYTAB_SIZE] = { Also, it is not related to the time between keyup and keydown. */ - [0x19] = KEY_PAUSE, /* Timeshift */ + [0x19] = KEY_TIME, /* Timeshift */ [0x1a] = KEY_STOP, [0x1b] = KEY_RECORD, @@ -2687,7 +2687,7 @@ IR_KEYTAB_TYPE ir_codes_real_audio_220_32_keys[IR_KEYTAB_SIZE] = { [0x0d] = KEY_AUDIO, /* stereo */ [0x0f] = KEY_PREVIOUS, /* Prev */ - [0x1b] = KEY_PAUSE, /* Timeshift */ + [0x1b] = KEY_TIME, /* Timeshift */ [0x1a] = KEY_NEXT, /* Next */ [0x0e] = KEY_STOP, -- cgit v1.2.3 From eff582b37eade3b542a8501d3f3f920f6eaeab65 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 29 Aug 2009 09:37:00 -0300 Subject: ir-keymaps: Fix IR mappings for channel and volume +/- keys From: Mauro Carvalho Chehab Use standard definitions for channel controls, as defined at: http://linuxtv.org/wiki/index.php/Remote_Controllers While here, fix a few broken up/down/left/right mappings Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/common/ir-keymaps.c | 71 ++++++++++++++------------------- 1 file changed, 31 insertions(+), 40 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/common/ir-keymaps.c b/linux/drivers/media/common/ir-keymaps.c index 24a635529..d1b742fc2 100644 --- a/linux/drivers/media/common/ir-keymaps.c +++ b/linux/drivers/media/common/ir-keymaps.c @@ -49,19 +49,19 @@ IR_KEYTAB_TYPE ir_codes_proteus_2309[IR_KEYTAB_SIZE] = { [0x08] = KEY_8, [0x09] = KEY_9, - [0x5c] = KEY_POWER, /* power */ - [0x20] = KEY_ZOOM, /* full screen */ - [0x0f] = KEY_BACKSPACE, /* recall */ - [0x1b] = KEY_ENTER, /* mute */ - [0x41] = KEY_RECORD, /* record */ - [0x43] = KEY_STOP, /* stop */ + [0x5c] = KEY_POWER, /* power */ + [0x20] = KEY_ZOOM, /* full screen */ + [0x0f] = KEY_BACKSPACE, /* recall */ + [0x1b] = KEY_ENTER, /* mute */ + [0x41] = KEY_RECORD, /* record */ + [0x43] = KEY_STOP, /* stop */ [0x16] = KEY_S, - [0x1a] = KEY_POWER2, /* off */ + [0x1a] = KEY_POWER2, /* off */ [0x2e] = KEY_RED, - [0x1f] = KEY_DOWN, /* channel - */ - [0x1c] = KEY_UP, /* channel + */ - [0x10] = KEY_LEFT, /* volume - */ - [0x1e] = KEY_RIGHT, /* volume + */ + [0x1f] = KEY_CHANNELDOWN, /* channel - */ + [0x1c] = KEY_CHANNELUP, /* channel + */ + [0x10] = KEY_VOLUMEDOWN, /* volume - */ + [0x1e] = KEY_VOLUMEUP, /* volume + */ [0x14] = KEY_F1, }; EXPORT_SYMBOL_GPL(ir_codes_proteus_2309); @@ -1270,11 +1270,11 @@ IR_KEYTAB_TYPE ir_codes_manli[IR_KEYTAB_SIZE] = { * 0x015 * * Down * * */ - [0x0b] = KEY_UP, /*XXX KEY_SCROLLUP? */ - [0x18] = KEY_LEFT, /*XXX KEY_BACK? */ + [0x0b] = KEY_UP, + [0x18] = KEY_LEFT, [0x16] = KEY_OK, /*XXX KEY_SELECT? KEY_ENTER? */ - [0x0c] = KEY_RIGHT, /*XXX KEY_FORWARD? */ - [0x15] = KEY_DOWN, /*XXX KEY_SCROLLDOWN? */ + [0x0c] = KEY_RIGHT, + [0x15] = KEY_DOWN, /* 0x11 0x0d * * TV/AV MODE * @@ -1644,8 +1644,6 @@ IR_KEYTAB_TYPE ir_codes_pinnacle_color[IR_KEYTAB_SIZE] = { [0x23] = KEY_RIGHT, [0x0d] = KEY_SELECT, - - [0x08] = KEY_BACK, [0x07] = KEY_REFRESH, @@ -1757,11 +1755,11 @@ IR_KEYTAB_TYPE ir_codes_npgtech[IR_KEYTAB_SIZE] = { [0x03] = KEY_BRIGHTNESSDOWN, [0x28] = KEY_AUDIO, - [0x3c] = KEY_UP, - [0x3f] = KEY_LEFT, + [0x3c] = KEY_CHANNELUP, + [0x3f] = KEY_VOLUMEDOWN, [0x2e] = KEY_MUTE, - [0x3b] = KEY_RIGHT, - [0x00] = KEY_DOWN, + [0x3b] = KEY_VOLUMEUP, + [0x00] = KEY_CHANNELDOWN, [0x07] = KEY_BRIGHTNESSUP, [0x2c] = KEY_TEXT, @@ -1965,17 +1963,10 @@ IR_KEYTAB_TYPE ir_codes_encore_enltv[IR_KEYTAB_SIZE] = { [0x14] = KEY_HOME, /* win start menu */ [0x15] = KEY_EXIT, /* exit */ -#if 0 [0x16] = KEY_CHANNELUP, /* UP */ [0x12] = KEY_CHANNELDOWN, /* DOWN */ [0x0c] = KEY_VOLUMEUP, /* RIGHT */ [0x17] = KEY_VOLUMEDOWN, /* LEFT */ -#else - [0x16] = KEY_UP, - [0x12] = KEY_DOWN, - [0x0c] = KEY_RIGHT, - [0x17] = KEY_LEFT, -#endif [0x18] = KEY_ENTER, /* OK */ @@ -2268,11 +2259,11 @@ IR_KEYTAB_TYPE ir_codes_behold[IR_KEYTAB_SIZE] = { * 0x015 * * Down * * */ - [0x0b] = KEY_CHANNELUP, /* XXX KEY_UP */ - [0x18] = KEY_VOLUMEDOWN, /* XXX KEY_LEFT */ + [0x0b] = KEY_CHANNELUP, + [0x18] = KEY_VOLUMEDOWN, [0x16] = KEY_OK, /* XXX KEY_ENTER */ - [0x0c] = KEY_VOLUMEUP, /* XXX KEY_RIGHT */ - [0x15] = KEY_CHANNELDOWN, /* XXX KEY_DOWN */ + [0x0c] = KEY_VOLUMEUP, + [0x15] = KEY_CHANNELDOWN, /* 0x11 0x0d * * MUTE INFO * @@ -2450,10 +2441,10 @@ IR_KEYTAB_TYPE ir_codes_powercolor_real_angel[IR_KEYTAB_SIZE] = { [0x13] = KEY_BRIGHTNESSDOWN, [0x2b] = KEY_MODE, /* stereo/mono */ [0x2c] = KEY_TEXT, /* teletext */ - [0x20] = KEY_UP, /* channel up */ - [0x21] = KEY_DOWN, /* channel down */ - [0x10] = KEY_RIGHT, /* volume up */ - [0x11] = KEY_LEFT, /* volume down */ + [0x20] = KEY_CHANNELUP, /* channel up */ + [0x21] = KEY_CHANELDOWN, /* channel down */ + [0x10] = KEY_VOLUMEUP, /* volume up */ + [0x11] = KEY_VOLUMEDOWN, /* volume down */ [0x0d] = KEY_MUTE, [0x1f] = KEY_RECORD, [0x17] = KEY_PLAY, @@ -2651,11 +2642,11 @@ IR_KEYTAB_TYPE ir_codes_encore_enltv_fm53[IR_KEYTAB_SIZE] = { [0x54] = KEY_RECORD, [0x4d] = KEY_PLAY, /* pause */ - [0x1e] = KEY_UP, /* video setting */ + [0x1e] = KEY_MENU, /* video setting */ [0x0e] = KEY_RIGHT, /* <- */ [0x1a] = KEY_LEFT, /* -> */ - [0x0a] = KEY_DOWN, /* video default */ + [0x0a] = KEY_CLEAR, /* video default */ [0x0c] = KEY_ZOOM, /* hide pannel */ [0x47] = KEY_SLEEP, /* shutdown */ }; @@ -2748,8 +2739,8 @@ IR_KEYTAB_TYPE ir_codes_dm1105_nec[IR_KEYTAB_SIZE] = { [0x18] = KEY_8, [0x19] = KEY_9, [0x10] = KEY_0, - [0x1c] = KEY_PAGEUP, /* ch+ */ - [0x0f] = KEY_PAGEDOWN, /* ch- */ + [0x1c] = KEY_CHANNELUP, /* ch+ */ + [0x0f] = KEY_CHANNELDOWN, /* ch- */ [0x1a] = KEY_VOLUMEUP, /* vol+ */ [0x0e] = KEY_VOLUMEDOWN, /* vol- */ [0x04] = KEY_RECORD, /* rec */ -- cgit v1.2.3 From 53346f9dc73de737bcab79ce76d1dc2f8bf7b625 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 29 Aug 2009 09:48:21 -0300 Subject: ir-keymaps: use KEY_CAMERA for snapshots From: Mauro Carvalho Chehab KEY_CAMERA is already used for a long time with webcam drivers to take a picture. On other media drivers, due to the lack of a snapshot button, random KEY codes were sent, being KEY_SHUFFLE the most used one, probably due to cut-and-paste from other remotes, since one of them uses the same key for snapshot and shuffle. The better is to use KEY_CAMERA on all drivers solving this issue. This follows the IR standard map as defined at: http://linuxtv.org/wiki/index.php/Remote_Controllers Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/common/ir-keymaps.c | 34 ++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/common/ir-keymaps.c b/linux/drivers/media/common/ir-keymaps.c index d1b742fc2..7e7a4ca29 100644 --- a/linux/drivers/media/common/ir-keymaps.c +++ b/linux/drivers/media/common/ir-keymaps.c @@ -356,7 +356,7 @@ IR_KEYTAB_TYPE ir_codes_pixelview_new[IR_KEYTAB_SIZE] = { [0x14] = KEY_VOLUMEDOWN, [0x13] = KEY_ZOOM, - [0x19] = KEY_SHUFFLE, /* SNAPSHOT */ + [0x19] = KEY_CAMERA, /* SNAPSHOT */ [0x1a] = KEY_SEARCH, /* scan */ [0x37] = KEY_REWIND, /* << */ @@ -683,7 +683,7 @@ IR_KEYTAB_TYPE ir_codes_msi_tvanywhere_plus[IR_KEYTAB_SIZE] = { [0x0f] = KEY_CLOSE, /* Minimize */ [0x19] = KEY_ZOOM, /* Zoom */ - [0x1a] = KEY_SHUFFLE, /* Snapshot */ + [0x1a] = KEY_CAMERA, /* Snapshot */ [0x0d] = KEY_LANGUAGE, /* MTS */ [0x14] = KEY_VOLUMEDOWN,/* Vol- */ @@ -1089,7 +1089,7 @@ IR_KEYTAB_TYPE ir_codes_eztv[IR_KEYTAB_SIZE] = { [0x2b] = KEY_RECORD, /* recording */ [0x2c] = KEY_STOP, /* stop */ [0x2d] = KEY_PLAY, /* play */ - [0x2e] = KEY_SHUFFLE, /* snapshot / shuffle */ + [0x2e] = KEY_CAMERA, /* snapshot / shuffle */ [0x00] = KEY_0, [0x05] = KEY_1, @@ -1140,7 +1140,7 @@ IR_KEYTAB_TYPE ir_codes_avermedia[IR_KEYTAB_SIZE] = { [0x2a] = KEY_SEARCH, /* AUTOSCAN */ [0x1a] = KEY_SLEEP, /* FREEZE */ - [0x3a] = KEY_SHUFFLE, /* SNAPSHOT */ + [0x3a] = KEY_CAMERA, /* SNAPSHOT */ [0x0a] = KEY_MUTE, /* MUTE */ [0x26] = KEY_RECORD, /* RECORD */ @@ -1301,7 +1301,7 @@ IR_KEYTAB_TYPE ir_codes_manli[IR_KEYTAB_SIZE] = { * MUTE SNAPSHOT* * */ [0x13] = KEY_MUTE, - [0x19] = KEY_RECORD, /*XXX*/ + [0x19] = KEY_CAMERA, /* 0x1d unused ? */ }; @@ -1331,8 +1331,8 @@ IR_KEYTAB_TYPE ir_codes_gotview7135[IR_KEYTAB_SIZE] = { [0x0c] = KEY_VOLUMEDOWN, [0x28] = KEY_VOLUMEUP, [0x08] = KEY_MUTE, - [0x26] = KEY_SEARCH, /*SCAN*/ - [0x3f] = KEY_SHUFFLE, /* SNAPSHOT */ + [0x26] = KEY_SEARCH, /* SCAN */ + [0x3f] = KEY_CAMERA, /* SNAPSHOT */ [0x12] = KEY_RECORD, [0x32] = KEY_STOP, [0x3c] = KEY_PLAY, @@ -1424,7 +1424,7 @@ IR_KEYTAB_TYPE ir_codes_pctv_sedna[IR_KEYTAB_SIZE] = { [0x13] = KEY_MUTE, [0x15] = KEY_CHANNELDOWN, [0x18] = KEY_VOLUMEDOWN, - [0x19] = KEY_SHUFFLE, /* Snapshot */ + [0x19] = KEY_CAMERA, /* Snapshot */ [0x1a] = KEY_NEXTSONG, [0x1b] = KEY_TIME, /* Time Shift */ [0x1c] = KEY_RADIO, /* FM Radio */ @@ -2049,7 +2049,7 @@ IR_KEYTAB_TYPE ir_codes_encore_enltv2[IR_KEYTAB_SIZE] = { [0x72] = KEY_CHANNELDOWN, [0x41] = KEY_RECORD, - [0x51] = KEY_SHUFFLE, /* Snapshot */ + [0x51] = KEY_CAMERA, /* Snapshot */ [0x75] = KEY_TIME, /* Timeshift */ [0x71] = KEY_TV2, /* PIP */ @@ -2297,7 +2297,7 @@ IR_KEYTAB_TYPE ir_codes_behold[IR_KEYTAB_SIZE] = { * FREEZE SNAPSHOT * * */ [0x58] = KEY_SLOW, - [0x5c] = KEY_SAVE, + [0x5c] = KEY_CAMERA, }; EXPORT_SYMBOL_GPL(ir_codes_behold); @@ -2337,7 +2337,7 @@ IR_KEYTAB_TYPE ir_codes_behold_columbus[IR_KEYTAB_SIZE] = { [0x04] = KEY_4, [0x05] = KEY_5, [0x06] = KEY_6, - [0x19] = KEY_BOOKMARKS, /* Snapshot key */ + [0x19] = KEY_CAMERA, /* Snapshot key */ [0x07] = KEY_7, [0x08] = KEY_8, [0x09] = KEY_9, @@ -2408,7 +2408,7 @@ IR_KEYTAB_TYPE ir_codes_genius_tvgo_a11mce[IR_KEYTAB_SIZE] = { an alternate name written */ [0x1e] = KEY_UP, /* Video Setting */ [0x0a] = KEY_DOWN, /* Video Default */ - [0x05] = KEY_LEFT, /* Snapshot */ + [0x05] = KEY_CAMERA, /* Snapshot */ [0x0c] = KEY_RIGHT, /* Hide Panel */ /* Four buttons without label */ [0x49] = KEY_RED, @@ -2453,7 +2453,7 @@ IR_KEYTAB_TYPE ir_codes_powercolor_real_angel[IR_KEYTAB_SIZE] = { [0x27] = KEY_FASTFORWARD, [0x26] = KEY_REWIND, [0x1e] = KEY_SEARCH, /* autoscan */ - [0x0e] = KEY_SHUFFLE, /* snapshot */ + [0x0e] = KEY_CAMERA, /* snapshot */ [0x2d] = KEY_SETUP, [0x0f] = KEY_SCREEN, /* full screen */ [0x14] = KEY_RADIO, /* FM radio */ @@ -2515,7 +2515,7 @@ IR_KEYTAB_TYPE ir_codes_kworld_plus_tv_analog[IR_KEYTAB_SIZE] = { [0x15] = KEY_AUDIO, /* ((*)) */ [0x0f] = KEY_ZOOM, - [0x1c] = KEY_SHUFFLE, /* snapshot */ + [0x1c] = KEY_CAMERA, /* snapshot */ [0x18] = KEY_RED, /* B */ [0x23] = KEY_GREEN, /* C */ @@ -2631,7 +2631,7 @@ IR_KEYTAB_TYPE ir_codes_encore_enltv_fm53[IR_KEYTAB_SIZE] = { [0x40] = KEY_LAST, /* recall */ [0x02] = KEY_MODE, /* TV/AV */ - [0x05] = KEY_SHUFFLE, /* SNAPSHOT */ + [0x05] = KEY_CAMERA, /* SNAPSHOT */ [0x4c] = KEY_CHANNELUP, /* UP */ [0x00] = KEY_CHANNELDOWN, /* DOWN */ @@ -2687,7 +2687,7 @@ IR_KEYTAB_TYPE ir_codes_real_audio_220_32_keys[IR_KEYTAB_SIZE] = { [0x1d] = KEY_RECORD, [0x13] = KEY_MUTE, - [0x19] = KEY_SHUFFLE, /* Snapshot */ + [0x19] = KEY_CAMERA, /* Snapshot */ }; EXPORT_SYMBOL_GPL(ir_codes_real_audio_220_32_keys); @@ -2871,7 +2871,7 @@ IR_KEYTAB_TYPE ir_codes_videomate_s350[IR_KEYTAB_SIZE] = { [0x29] = KEY_CHANNEL, /* SURF */ [0x2b] = KEY_A, [0x2c] = KEY_B, - [0x2f] = KEY_SHUFFLE, /* Snapshot */ + [0x2f] = KEY_CAMERA, /* Snapshot */ [0x23] = KEY_RADIO, [0x02] = KEY_PREVIOUSSONG, [0x06] = KEY_NEXTSONG, -- cgit v1.2.3 From 53e62967f3826e6ee00f29ee836c49cd4ca3485d Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 29 Aug 2009 09:51:51 -0300 Subject: Fix compilation issues caused by typos From: Mauro Carvalho Chehab This patch should be folded with the original ones at -git. kernel-sync: Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/common/ir-keymaps.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/common/ir-keymaps.c b/linux/drivers/media/common/ir-keymaps.c index 7e7a4ca29..7ab7d0586 100644 --- a/linux/drivers/media/common/ir-keymaps.c +++ b/linux/drivers/media/common/ir-keymaps.c @@ -1343,7 +1343,7 @@ IR_KEYTAB_TYPE ir_codes_gotview7135[IR_KEYTAB_SIZE] = { [0x2a] = KEY_F21, /* LIVE TIMESHIFT */ [0x0e] = KEY_F22, /* MIN TIMESHIFT */ - [0x1e] = KEY_TIMESHIFT, /* TIMESHIFT */ + [0x1e] = KEY_TIME, /* TIMESHIFT */ [0x38] = KEY_F24, /* NORMAL TIMESHIFT */ }; EXPORT_SYMBOL_GPL(ir_codes_gotview7135); @@ -2442,7 +2442,7 @@ IR_KEYTAB_TYPE ir_codes_powercolor_real_angel[IR_KEYTAB_SIZE] = { [0x2b] = KEY_MODE, /* stereo/mono */ [0x2c] = KEY_TEXT, /* teletext */ [0x20] = KEY_CHANNELUP, /* channel up */ - [0x21] = KEY_CHANELDOWN, /* channel down */ + [0x21] = KEY_CHANNELDOWN, /* channel down */ [0x10] = KEY_VOLUMEUP, /* volume up */ [0x11] = KEY_VOLUMEDOWN, /* volume down */ [0x0d] = KEY_MUTE, -- cgit v1.2.3 From 810944b9c6ecec7746372ac6ae94252d2d713531 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 26 Aug 2009 22:06:28 -0300 Subject: FM1216MK5 FM radio From: Dmitri Belimov Implement Philips FM1216MK5. 1. Implement get_stereo function. 2. Add correct data byte for FM radio mode Priority: normal Signed-off-by: Beholder Intl. Ltd. Dmitry Belimov Signed-off-by: Douglas Schilling Landgraf Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/common/tuners/tuner-simple.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/common/tuners/tuner-simple.c b/linux/drivers/media/common/tuners/tuner-simple.c index 2ac1c8edb..4bac1d0c6 100644 --- a/linux/drivers/media/common/tuners/tuner-simple.c +++ b/linux/drivers/media/common/tuners/tuner-simple.c @@ -145,6 +145,8 @@ static inline int tuner_stereo(const int type, const int status) case TUNER_LG_NTSC_TAPE: case TUNER_TCL_MF02GIP_5N: return ((status & TUNER_SIGNAL) == TUNER_STEREO_MK3); + case TUNER_PHILIPS_FM1216MK5: + return status | TUNER_STEREO; default: return status & TUNER_STEREO; } @@ -515,6 +517,10 @@ static int simple_radio_bandswitch(struct dvb_frontend *fe, u8 *buffer) case TUNER_TCL_MF02GIP_5N: buffer[3] = 0x19; break; + case TUNER_PHILIPS_FM1216MK5: + buffer[2] = 0x88; + buffer[3] = 0x09; + break; case TUNER_TNF_5335MF: buffer[3] = 0x11; break; -- cgit v1.2.3 From 640cb9f7f8d3aca8ad56e1f6a7bac42e15aa6962 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 26 Aug 2009 22:10:55 -0300 Subject: support AverMedia Studio 505 From: Vasiliy Temnikov Added support to AverMedia Studio 505 Priority: normal Signed-off-by: Vasiliy Temnikov [dougsland@redhat.com: fixed rejects and removed the change to add dk as default secam variant] [mchehab@redhat.com: fix a few CodingStyle issues] Signed-off-by: Andrew Morton Signed-off-by: Douglas Schilling Landgraf Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/saa7134/saa7134-cards.c | 43 +++++++++++++++++++++++ linux/drivers/media/video/saa7134/saa7134-input.c | 1 + linux/drivers/media/video/saa7134/saa7134.h | 1 + 3 files changed, 45 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/saa7134/saa7134-cards.c b/linux/drivers/media/video/saa7134/saa7134-cards.c index c401a37ea..cdb04fdbb 100644 --- a/linux/drivers/media/video/saa7134/saa7134-cards.c +++ b/linux/drivers/media/video/saa7134/saa7134-cards.c @@ -1364,6 +1364,42 @@ struct saa7134_board saa7134_boards[] = { .amux = LINE1, }, }, + [SAA7134_BOARD_AVERMEDIA_STUDIO_505] = { + /* Vasiliy Temnikov */ + .name = "AverMedia AverTV Studio 505", + .audio_clock = 0x00187de7, + .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .tda9887_conf = TDA9887_PRESENT, + .inputs = { { + .name = name_tv, + .vmux = 1, + .amux = LINE2, + .tv = 1, + }, { + .name = name_comp1, + .vmux = 0, + .amux = LINE2, + }, { + .name = name_comp2, + .vmux = 3, + .amux = LINE2, + },{ + .name = name_svideo, + .vmux = 8, + .amux = LINE2, + } }, + .radio = { + .name = name_radio, + .amux = LINE2, + }, + .mute = { + .name = name_mute, + .amux = LINE1, + }, + }, [SAA7134_BOARD_UPMOST_PURPLE_TV] = { .name = "UPMOST PURPLE TV", .audio_clock = 0x00187de7, @@ -5437,6 +5473,12 @@ struct pci_device_id saa7134_pci_tbl[] = { .subdevice = 0x2115, .driver_data = SAA7134_BOARD_AVERMEDIA_STUDIO_305, },{ + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7130, + .subvendor = 0x1461, /* Avermedia Technologies Inc */ + .subdevice = 0xa115, + .driver_data = SAA7134_BOARD_AVERMEDIA_STUDIO_505, + }, { .vendor = PCI_VENDOR_ID_PHILIPS, .device = PCI_DEVICE_ID_PHILIPS_SAA7130, .subvendor = 0x1461, /* Avermedia Technologies Inc */ @@ -6607,6 +6649,7 @@ int saa7134_board_init1(struct saa7134_dev *dev) case SAA7134_BOARD_KWORLD_VSTREAM_XPERT: case SAA7134_BOARD_KWORLD_XPERT: case SAA7134_BOARD_AVERMEDIA_STUDIO_305: + case SAA7134_BOARD_AVERMEDIA_STUDIO_505: case SAA7134_BOARD_AVERMEDIA_305: case SAA7134_BOARD_AVERMEDIA_STUDIO_307: case SAA7134_BOARD_AVERMEDIA_307: diff --git a/linux/drivers/media/video/saa7134/saa7134-input.c b/linux/drivers/media/video/saa7134/saa7134-input.c index 146ac816a..8dbad5dbe 100644 --- a/linux/drivers/media/video/saa7134/saa7134-input.c +++ b/linux/drivers/media/video/saa7134/saa7134-input.c @@ -486,6 +486,7 @@ int saa7134_input_init1(struct saa7134_dev *dev) case SAA7134_BOARD_AVERMEDIA_305: case SAA7134_BOARD_AVERMEDIA_307: case SAA7134_BOARD_AVERMEDIA_STUDIO_305: + case SAA7134_BOARD_AVERMEDIA_STUDIO_505: case SAA7134_BOARD_AVERMEDIA_STUDIO_307: case SAA7134_BOARD_AVERMEDIA_STUDIO_507: case SAA7134_BOARD_AVERMEDIA_STUDIO_507UA: diff --git a/linux/drivers/media/video/saa7134/saa7134.h b/linux/drivers/media/video/saa7134/saa7134.h index c0757f8a1..b59e0f18b 100644 --- a/linux/drivers/media/video/saa7134/saa7134.h +++ b/linux/drivers/media/video/saa7134/saa7134.h @@ -294,6 +294,7 @@ struct saa7134_format { #define SAA7134_BOARD_BEHOLD_609RDS_MK3 167 #define SAA7134_BOARD_BEHOLD_609RDS_MK5 168 #define SAA7134_BOARD_VIDEOMATE_S350 169 +#define SAA7134_BOARD_AVERMEDIA_STUDIO_505 170 #define SAA7134_MAXBOARDS 32 #define SAA7134_INPUT_MAX 8 -- cgit v1.2.3 From 52ef68ff244a5cd4707558c9aa803ecb9c1342dc Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 26 Aug 2009 22:13:43 -0300 Subject: Fix test of bandwidth range in cx22700_set_tps() From: Roel Kluin For the bandwidth to be less than 8 MHZ and greater than 6 MHZ is logically impossible. Priority: normal Signed-off-by: Roel Kluin Signed-off-by: Andrew Morton Signed-off-by: Douglas Schilling Landgraf Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/frontends/cx22700.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/frontends/cx22700.c b/linux/drivers/media/dvb/frontends/cx22700.c index fbd838eca..5fbc0fc37 100644 --- a/linux/drivers/media/dvb/frontends/cx22700.c +++ b/linux/drivers/media/dvb/frontends/cx22700.c @@ -155,7 +155,7 @@ static int cx22700_set_tps (struct cx22700_state *state, struct dvb_ofdm_paramet p->hierarchy_information > HIERARCHY_4) return -EINVAL; - if (p->bandwidth < BANDWIDTH_8_MHZ && p->bandwidth > BANDWIDTH_6_MHZ) + if (p->bandwidth < BANDWIDTH_8_MHZ || p->bandwidth > BANDWIDTH_6_MHZ) return -EINVAL; if (p->bandwidth == BANDWIDTH_7_MHZ) -- cgit v1.2.3